summaryrefslogtreecommitdiff
path: root/chromium/content
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@digia.com>2014-03-18 13:16:26 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-03-20 15:55:39 +0100
commit3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch)
tree92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/content
parente90d7c4b152c56919d963987e2503f9909a666d2 (diff)
downloadqtwebengine-chromium-3f0f86b0caed75241fa71c95a5d73bc0164348c5.tar.gz
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies needed on Windows. Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42 Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu> Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/content')
-rw-r--r--chromium/content/DEPS4
-rw-r--r--chromium/content/OWNERS5
-rw-r--r--chromium/content/app/android/child_process_service.cc2
-rw-r--r--chromium/content/app/android/content_main.cc2
-rw-r--r--chromium/content/app/android/library_loader_hooks.cc102
-rw-r--r--chromium/content/app/content_main_runner.cc34
-rw-r--r--chromium/content/browser/DEPS9
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter.cc33
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter.h34
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc68
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_gtk.cc7
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm7
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc32
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.h12
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc23
-rw-r--r--chromium/content/browser/accessibility/accessibility_ui.cc6
-rw-r--r--chromium/content/browser/accessibility/accessibility_win_browsertest.cc26
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc149
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h42
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc352
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.h42
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm428
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_delegate_mac.h3
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_gtk.cc45
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm16
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc54
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h9
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.cc143
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.h6
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_gtk.cc16
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_gtk.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm62
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc242
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc183
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.h13
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.cc1012
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.h74
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc157
-rw-r--r--chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc48
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc50
-rw-r--r--chromium/content/browser/android/OWNERS7
-rw-r--r--chromium/content/browser/android/child_process_launcher_android.cc11
-rw-r--r--chromium/content/browser/android/child_process_launcher_android.h2
-rw-r--r--chromium/content/browser/android/content_settings.cc6
-rw-r--r--chromium/content/browser/android/content_startup_flags.cc20
-rw-r--r--chromium/content/browser/android/content_video_view.cc53
-rw-r--r--chromium/content/browser/android/content_video_view.h15
-rw-r--r--chromium/content/browser/android/content_view_core_impl.cc408
-rw-r--r--chromium/content/browser/android/content_view_core_impl.h93
-rw-r--r--chromium/content/browser/android/content_view_render_view.cc28
-rw-r--r--chromium/content/browser/android/content_view_render_view.h8
-rw-r--r--chromium/content/browser/android/content_view_statics.cc6
-rw-r--r--chromium/content/browser/android/date_time_chooser_android.cc154
-rw-r--r--chromium/content/browser/android/date_time_chooser_android.h43
-rw-r--r--chromium/content/browser/android/download_controller_android_impl.cc54
-rw-r--r--chromium/content/browser/android/edge_effect.cc11
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_impl.cc66
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_impl.h8
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_output_surface.cc25
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_output_surface.h6
-rw-r--r--chromium/content/browser/android/in_process/synchronous_input_event_filter.cc8
-rw-r--r--chromium/content/browser/android/in_process/synchronous_input_event_filter.h6
-rw-r--r--chromium/content/browser/android/interstitial_page_delegate_android.cc4
-rw-r--r--chromium/content/browser/android/overscroll_glow.cc164
-rw-r--r--chromium/content/browser/android/overscroll_glow.h55
-rw-r--r--chromium/content/browser/android/popup_item_type_list.h23
-rw-r--r--chromium/content/browser/android/touch_point.cc66
-rw-r--r--chromium/content/browser/android/touch_point.h4
-rw-r--r--chromium/content/browser/android/tracing_controller_android.cc78
-rw-r--r--chromium/content/browser/android/tracing_controller_android.h43
-rw-r--r--chromium/content/browser/android/tracing_intent_handler.cc57
-rw-r--r--chromium/content/browser/android/tracing_intent_handler.h31
-rw-r--r--chromium/content/browser/android/web_contents_observer_android.cc72
-rw-r--r--chromium/content/browser/android/web_contents_observer_android.h13
-rw-r--r--chromium/content/browser/appcache/appcache_dispatcher_host.cc1
-rw-r--r--chromium/content/browser/aura/browser_compositor_output_surface.cc60
-rw-r--r--chromium/content/browser/aura/browser_compositor_output_surface.h41
-rw-r--r--chromium/content/browser/aura/browser_compositor_output_surface_proxy.h4
-rw-r--r--chromium/content/browser/aura/gpu_browser_compositor_output_surface.cc51
-rw-r--r--chromium/content/browser/aura/gpu_browser_compositor_output_surface.h36
-rw-r--r--chromium/content/browser/aura/gpu_process_transport_factory.cc318
-rw-r--r--chromium/content/browser/aura/gpu_process_transport_factory.h21
-rw-r--r--chromium/content/browser/aura/image_transport_factory.cc50
-rw-r--r--chromium/content/browser/aura/image_transport_factory.h10
-rw-r--r--chromium/content/browser/aura/image_transport_factory_browsertest.cc69
-rw-r--r--chromium/content/browser/aura/no_transport_image_transport_factory.cc19
-rw-r--r--chromium/content/browser/aura/no_transport_image_transport_factory.h2
-rw-r--r--chromium/content/browser/aura/owned_mailbox.cc42
-rw-r--r--chromium/content/browser/aura/owned_mailbox.h41
-rw-r--r--chromium/content/browser/aura/reflector_impl.cc28
-rw-r--r--chromium/content/browser/aura/reflector_impl.h3
-rw-r--r--chromium/content/browser/aura/software_browser_compositor_output_surface.cc40
-rw-r--r--chromium/content/browser/aura/software_browser_compositor_output_surface.h49
-rw-r--r--chromium/content/browser/aura/software_browser_compositor_output_surface_unittest.cc147
-rw-r--r--chromium/content/browser/aura/software_output_device_ozone.cc73
-rw-r--r--chromium/content/browser/aura/software_output_device_ozone.h41
-rw-r--r--chromium/content/browser/aura/software_output_device_ozone_unittest.cc195
-rw-r--r--chromium/content/browser/aura/software_output_device_win.cc2
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.cc12
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.h6
-rw-r--r--chromium/content/browser/browser_context.cc5
-rw-r--r--chromium/content/browser/browser_main_loop.cc167
-rw-r--r--chromium/content/browser/browser_main_loop.h10
-rw-r--r--chromium/content/browser/browser_main_runner.cc9
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_embedder.cc59
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_embedder.h12
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc455
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.h191
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest_helper.cc55
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest_helper.h59
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc118
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest_manager.h11
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc335
-rw-r--r--chromium/content/browser/browser_plugin/test_browser_plugin_guest.cc56
-rw-r--r--chromium/content/browser/browser_plugin/test_browser_plugin_guest.h19
-rw-r--r--chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc10
-rw-r--r--chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h7
-rw-r--r--chromium/content/browser/browser_shutdown_profile_dumper.cc7
-rw-r--r--chromium/content/browser/browser_thread_impl.cc5
-rw-r--r--chromium/content/browser/browser_url_handler_impl.cc22
-rw-r--r--chromium/content/browser/cert_store_impl.cc158
-rw-r--r--chromium/content/browser/cert_store_impl.h42
-rw-r--r--chromium/content/browser/child_process_launcher.cc47
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc248
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.h62
-rw-r--r--chromium/content/browser/child_process_security_policy_unittest.cc204
-rw-r--r--chromium/content/browser/device_monitor_mac.h18
-rw-r--r--chromium/content/browser/device_monitor_mac.mm280
-rw-r--r--chromium/content/browser/device_monitor_udev.cc (renamed from chromium/content/browser/device_monitor_linux.cc)4
-rw-r--r--chromium/content/browser/device_monitor_udev.h (renamed from chromium/content/browser/device_monitor_linux.h)8
-rw-r--r--chromium/content/browser/device_orientation/accelerometer_mac.cc105
-rw-r--r--chromium/content/browser/device_orientation/accelerometer_mac.h40
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher.h24
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_impl_android.cc119
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_impl_android.h31
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_impl_android_unittest.cc9
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_impl_win.cc193
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_impl_win.h63
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_orientation_android.cc37
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_orientation_android.h32
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory.h7
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_android.cc2
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.cc24
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.h21
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_base_unittest.cc53
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_default.cc4
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_mac.cc9
-rw-r--r--chromium/content/browser/device_orientation/data_fetcher_shared_memory_win.cc38
-rw-r--r--chromium/content/browser/device_orientation/device_inertial_sensor_browsertest.cc186
-rw-r--r--chromium/content/browser/device_orientation/device_inertial_sensor_service.cc5
-rw-r--r--chromium/content/browser/device_orientation/device_inertial_sensor_service.h4
-rw-r--r--chromium/content/browser/device_orientation/device_orientation_browsertest.cc79
-rw-r--r--chromium/content/browser/device_orientation/inertial_sensor_consts.h6
-rw-r--r--chromium/content/browser/device_orientation/message_filter.cc38
-rw-r--r--chromium/content/browser/device_orientation/message_filter.h44
-rw-r--r--chromium/content/browser/device_orientation/observer_delegate.cc49
-rw-r--r--chromium/content/browser/device_orientation/observer_delegate.h45
-rw-r--r--chromium/content/browser/device_orientation/orientation.cc70
-rw-r--r--chromium/content/browser/device_orientation/orientation.h73
-rw-r--r--chromium/content/browser/device_orientation/orientation_message_filter.cc32
-rw-r--r--chromium/content/browser/device_orientation/orientation_message_filter.h30
-rw-r--r--chromium/content/browser/device_orientation/provider.cc59
-rw-r--r--chromium/content/browser/device_orientation/provider.h67
-rw-r--r--chromium/content/browser/device_orientation/provider_impl.cc292
-rw-r--r--chromium/content/browser/device_orientation/provider_impl.h81
-rw-r--r--chromium/content/browser/device_orientation/provider_unittest.cc591
-rw-r--r--chromium/content/browser/devtools/OWNERS2
-rw-r--r--chromium/content/browser/devtools/browser_protocol.json6
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.cc3
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler_impl.cc320
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler_impl.h31
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler_unittest.cc10
-rw-r--r--chromium/content/browser/devtools/devtools_manager_unittest.cc30
-rw-r--r--chromium/content/browser/devtools/devtools_protocol.cc9
-rw-r--r--chromium/content/browser/devtools/devtools_protocol.h13
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_constants.cc397
-rw-r--r--chromium/content/browser/devtools/devtools_protocol_constants.h296
-rw-r--r--chromium/content/browser/devtools/devtools_resources.gyp2
-rw-r--r--chromium/content/browser/devtools/devtools_system_info_handler.cc4
-rw-r--r--chromium/content/browser/devtools/devtools_tracing_handler.cc118
-rw-r--r--chromium/content/browser/devtools/devtools_tracing_handler.h26
-rw-r--r--chromium/content/browser/devtools/render_view_devtools_agent_host.cc102
-rw-r--r--chromium/content/browser/devtools/render_view_devtools_agent_host.h23
-rw-r--r--chromium/content/browser/devtools/renderer_overrides_handler.cc433
-rw-r--r--chromium/content/browser/devtools/renderer_overrides_handler.h17
-rw-r--r--chromium/content/browser/devtools/renderer_overrides_handler_browsertest.cc100
-rw-r--r--chromium/content/browser/devtools/worker_devtools_manager.h8
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl.cc97
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl.h23
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc112
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_host.cc97
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_host.h24
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_message_filter.cc53
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_message_filter.h23
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.cc261
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.h78
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_session.cc87
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_session.h18
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.cc3
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl.cc34
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl.h14
-rw-r--r--chromium/content/browser/download/base_file.cc6
-rw-r--r--chromium/content/browser/download/base_file_unittest.cc7
-rw-r--r--chromium/content/browser/download/download_browsertest.cc14
-rw-r--r--chromium/content/browser/download/download_create_info.cc17
-rw-r--r--chromium/content/browser/download/download_create_info.h3
-rw-r--r--chromium/content/browser/download/download_file_unittest.cc4
-rw-r--r--chromium/content/browser/download/download_item_impl.cc62
-rw-r--r--chromium/content/browser/download/download_item_impl.h5
-rw-r--r--chromium/content/browser/download/download_item_impl_unittest.cc5
-rw-r--r--chromium/content/browser/download/download_manager_impl.cc48
-rw-r--r--chromium/content/browser/download/download_manager_impl.h1
-rw-r--r--chromium/content/browser/download/download_manager_impl_unittest.cc10
-rw-r--r--chromium/content/browser/download/download_resource_handler.cc159
-rw-r--r--chromium/content/browser/download/download_resource_handler.h21
-rw-r--r--chromium/content/browser/download/download_stats.cc182
-rw-r--r--chromium/content/browser/download/download_stats.h48
-rw-r--r--chromium/content/browser/download/drag_download_file.h1
-rw-r--r--chromium/content/browser/download/drag_download_file_browsertest.cc13
-rw-r--r--chromium/content/browser/download/drag_download_util.cc12
-rw-r--r--chromium/content/browser/download/drag_download_util.h4
-rw-r--r--chromium/content/browser/download/file_metadata_unittest_linux.cc5
-rw-r--r--chromium/content/browser/download/mhtml_generation_browsertest.cc2
-rw-r--r--chromium/content/browser/download/save_file_manager.cc2
-rw-r--r--chromium/content/browser/download/save_file_resource_handler.cc15
-rw-r--r--chromium/content/browser/download/save_file_resource_handler.h7
-rw-r--r--chromium/content/browser/download/save_package.cc6
-rw-r--r--chromium/content/browser/download/save_package.h2
-rw-r--r--chromium/content/browser/download/save_package_unittest.cc4
-rw-r--r--chromium/content/browser/fileapi/blob_url_request_job_unittest.cc438
-rw-r--r--chromium/content/browser/fileapi/copy_or_move_file_validator_unittest.cc326
-rw-r--r--chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc866
-rw-r--r--chromium/content/browser/fileapi/dragged_file_util_unittest.cc544
-rw-r--r--chromium/content/browser/fileapi/file_system_browsertest.cc4
-rw-r--r--chromium/content/browser/fileapi/file_system_context_unittest.cc374
-rw-r--r--chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc321
-rw-r--r--chromium/content/browser/fileapi/file_system_file_stream_reader_unittest.cc266
-rw-r--r--chromium/content/browser/fileapi/file_system_operation_impl_unittest.cc1241
-rw-r--r--chromium/content/browser/fileapi/file_system_operation_impl_write_unittest.cc328
-rw-r--r--chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc162
-rw-r--r--chromium/content/browser/fileapi/file_system_quota_client_unittest.cc561
-rw-r--r--chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc368
-rw-r--r--chromium/content/browser/fileapi/file_writer_delegate_unittest.cc455
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.cc216
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.h42
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc25
-rw-r--r--chromium/content/browser/fileapi/local_file_util_unittest.cc388
-rw-r--r--chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc2490
-rw-r--r--chromium/content/browser/fileapi/plugin_private_file_system_backend_unittest.cc147
-rw-r--r--chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc280
-rw-r--r--chromium/content/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc82
-rw-r--r--chromium/content/browser/fileapi/sandbox_file_system_backend_unittest.cc319
-rw-r--r--chromium/content/browser/fileapi/transient_file_util_unittest.cc121
-rw-r--r--chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc278
-rw-r--r--chromium/content/browser/frame_host/DEPS23
-rw-r--r--chromium/content/browser/frame_host/OWNERS1
-rw-r--r--chromium/content/browser/frame_host/debug_urls.cc (renamed from chromium/content/browser/web_contents/debug_urls.cc)17
-rw-r--r--chromium/content/browser/frame_host/debug_urls.h26
-rw-r--r--chromium/content/browser/frame_host/frame_tree.cc191
-rw-r--r--chromium/content/browser/frame_host/frame_tree.h138
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.cc72
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.h169
-rw-r--r--chromium/content/browser/frame_host/frame_tree_unittest.cc180
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc (renamed from chromium/content/browser/web_contents/interstitial_page_impl.cc)146
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.h (renamed from chromium/content/browser/web_contents/interstitial_page_impl.h)45
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc17
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_navigator_impl.h33
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.cc73
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.h53
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_delegate.h79
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.cc (renamed from chromium/content/browser/web_contents/navigation_controller_impl.cc)220
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.h (renamed from chromium/content/browser/web_contents/navigation_controller_impl.h)55
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc (renamed from chromium/content/browser/web_contents/navigation_controller_impl_unittest.cc)689
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.cc (renamed from chromium/content/browser/web_contents/navigation_entry_impl.cc)43
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.h (renamed from chromium/content/browser/web_contents/navigation_entry_impl.h)68
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc (renamed from chromium/content/browser/web_contents/navigation_entry_impl_unittest.cc)16
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc (renamed from chromium/content/browser/web_contents/web_contents_screenshot_manager.cc)42
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_screenshot_manager.h (renamed from chromium/content/browser/web_contents/web_contents_screenshot_manager.h)23
-rw-r--r--chromium/content/browser/frame_host/navigator.h42
-rw-r--r--chromium/content/browser/frame_host/navigator_delegate.h37
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.cc85
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.h49
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.cc15
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h37
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_factory.cc49
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_factory.h71
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc128
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h100
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc (renamed from chromium/content/browser/web_contents/render_view_host_manager.cc)539
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.h (renamed from chromium/content/browser/web_contents/render_view_host_manager.h)109
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc (renamed from chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc)372
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc (renamed from chromium/content/browser/web_contents/render_view_host_manager_unittest.cc)305
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.cc71
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.h44
-rw-r--r--chromium/content/browser/gamepad/gamepad_data_fetcher.h4
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher.cc2
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h4
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc10
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h8
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h14
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm9
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc18
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h16
-rw-r--r--chromium/content/browser/gamepad/gamepad_provider.cc2
-rw-r--r--chromium/content/browser/gamepad/gamepad_provider_unittest.cc2
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings.h6
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc20
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm30
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc16
-rw-r--r--chromium/content/browser/gamepad/gamepad_test_helpers.cc8
-rw-r--r--chromium/content/browser/gamepad/gamepad_test_helpers.h10
-rw-r--r--chromium/content/browser/geolocation/OWNERS7
-rw-r--r--chromium/content/browser/geolocation/empty_wifi_data_provider.cc3
-rw-r--r--chromium/content/browser/geolocation/fake_access_token_store.cc2
-rw-r--r--chromium/content/browser/geolocation/fake_access_token_store.h5
-rw-r--r--chromium/content/browser/geolocation/geolocation_dispatcher_host.cc128
-rw-r--r--chromium/content/browser/geolocation/geolocation_dispatcher_host.h7
-rw-r--r--chromium/content/browser/geolocation/gps_location_provider_linux.cc302
-rw-r--r--chromium/content/browser/geolocation/gps_location_provider_linux.h105
-rw-r--r--chromium/content/browser/geolocation/gps_location_provider_unittest_linux.cc208
-rw-r--r--chromium/content/browser/geolocation/location_api_adapter_android.cc9
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl.cc4
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl.h2
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc2
-rw-r--r--chromium/content/browser/geolocation/network_location_provider.cc14
-rw-r--r--chromium/content/browser/geolocation/network_location_provider.h12
-rw-r--r--chromium/content/browser/geolocation/network_location_request.cc67
-rw-r--r--chromium/content/browser/geolocation/network_location_request.h4
-rw-r--r--chromium/content/browser/geolocation/wifi_data.cc2
-rw-r--r--chromium/content/browser/geolocation/wifi_data.h4
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_common.cc2
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_common.h2
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_win.cc38
-rw-r--r--chromium/content/browser/gpu/OWNERS1
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc277
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.h68
-rw-r--r--chromium/content/browser/gpu/compositor_util.cc345
-rw-r--r--chromium/content/browser/gpu/compositor_util.h5
-rw-r--r--chromium/content/browser/gpu/compositor_util_browsertest.cc28
-rwxr-xr-xchromium/content/browser/gpu/generate_webgl_conformance_test_list.py108
-rw-r--r--chromium/content/browser/gpu/gpu_crash_browsertest.cc76
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.cc5
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.h3
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc214
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.h26
-rw-r--r--chromium/content/browser/gpu/gpu_functional_browsertest.cc142
-rw-r--r--chromium/content/browser/gpu/gpu_info_browsertest.cc110
-rw-r--r--chromium/content/browser/gpu/gpu_internals_ui.cc299
-rw-r--r--chromium/content/browser/gpu/gpu_ipc_browsertests.cc180
-rw-r--r--chromium/content/browser/gpu/gpu_memory_test.cc243
-rw-r--r--chromium/content/browser/gpu/gpu_pixel_browsertest.cc568
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc43
-rw-r--r--chromium/content/browser/gpu/gpu_process_host_ui_shim.cc50
-rw-r--r--chromium/content/browser/gpu/gpu_process_host_ui_shim.h3
-rw-r--r--chromium/content/browser/gpu/webgl_conformance_test.cc96
-rw-r--r--chromium/content/browser/gpu/webgl_conformance_test_list_autogen.h1080
-rw-r--r--chromium/content/browser/histogram_message_filter.cc4
-rw-r--r--chromium/content/browser/histogram_message_filter.h3
-rw-r--r--chromium/content/browser/histogram_synchronizer.cc13
-rw-r--r--chromium/content/browser/host_zoom_map_impl.cc25
-rw-r--r--chromium/content/browser/host_zoom_map_impl.h7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc581
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.h97
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc164
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_browsertest.cc21
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.cc17
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.h6
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc42
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_connection.cc12
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_connection.h4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.cc63
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.h10
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cursor.cc10
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cursor.h4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.cc220
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.h41
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_error.h6
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_unittest.cc83
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc109
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h14
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory.cc235
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory.h72
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc481
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc28
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h30
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_index_writer.cc7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_index_writer.h4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc315
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h52
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc142
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_metadata.cc13
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_metadata.h16
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc10
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction.cc147
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction.h84
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc67
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h20
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc125
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_unittest.cc80
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.cc102
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.h7
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc26
-rw-r--r--chromium/content/browser/indexed_db/list_set.h4
-rw-r--r--chromium/content/browser/indexed_db/list_set_unittest.cc4
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc30
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h37
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc26
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h37
-rw-r--r--chromium/content/browser/loader/async_resource_handler.cc130
-rw-r--r--chromium/content/browser/loader/async_resource_handler.h15
-rw-r--r--chromium/content/browser/loader/buffered_resource_handler.cc70
-rw-r--r--chromium/content/browser/loader/buffered_resource_handler.h8
-rw-r--r--chromium/content/browser/loader/certificate_resource_handler.cc24
-rw-r--r--chromium/content/browser/loader/certificate_resource_handler.h16
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler.cc189
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler.h20
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.cc209
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.h94
-rw-r--r--chromium/content/browser/loader/doomed_resource_handler.cc78
-rw-r--r--chromium/content/browser/loader/doomed_resource_handler.h60
-rw-r--r--chromium/content/browser/loader/layered_resource_handler.cc17
-rw-r--r--chromium/content/browser/loader/layered_resource_handler.h16
-rw-r--r--chromium/content/browser/loader/power_save_block_resource_throttle.cc4
-rw-r--r--chromium/content/browser/loader/power_save_block_resource_throttle.h1
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.cc45
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.h12
-rw-r--r--chromium/content/browser/loader/render_view_host_tracker.cc74
-rw-r--r--chromium/content/browser/loader/render_view_host_tracker.h53
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc13
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc317
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h28
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc973
-rw-r--r--chromium/content/browser/loader/resource_handler.cc19
-rw-r--r--chromium/content/browser/loader/resource_handler.h29
-rw-r--r--chromium/content/browser/loader/resource_loader.cc212
-rw-r--r--chromium/content/browser/loader/resource_loader.h42
-rw-r--r--chromium/content/browser/loader/resource_loader_unittest.cc107
-rw-r--r--chromium/content/browser/loader/resource_message_delegate.h4
-rw-r--r--chromium/content/browser/loader/resource_message_filter.cc9
-rw-r--r--chromium/content/browser/loader/resource_message_filter.h6
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc46
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h58
-rw-r--r--chromium/content/browser/loader/resource_scheduler.cc172
-rw-r--r--chromium/content/browser/loader/resource_scheduler.h17
-rw-r--r--chromium/content/browser/loader/resource_scheduler_filter.cc13
-rw-r--r--chromium/content/browser/loader/resource_scheduler_unittest.cc61
-rw-r--r--chromium/content/browser/loader/stream_resource_handler.cc10
-rw-r--r--chromium/content/browser/loader/stream_resource_handler.h8
-rw-r--r--chromium/content/browser/loader/sync_resource_handler.cc51
-rw-r--r--chromium/content/browser/loader/sync_resource_handler.h14
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler.cc61
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler.h17
-rw-r--r--chromium/content/browser/loader/transfer_navigation_resource_throttle.cc93
-rw-r--r--chromium/content/browser/loader/transfer_navigation_resource_throttle.h38
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.cc7
-rw-r--r--chromium/content/browser/media/android/browser_demuxer_android.cc87
-rw-r--r--chromium/content/browser/media/android/browser_demuxer_android.h35
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.cc312
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.h89
-rw-r--r--chromium/content/browser/media/encrypted_media_browsertest.cc150
-rw-r--r--chromium/content/browser/media/media_browsertest.cc19
-rw-r--r--chromium/content/browser/media/media_devices_monitor.cc (renamed from chromium/content/browser/media_devices_monitor.cc)5
-rw-r--r--chromium/content/browser/media/media_internals.cc287
-rw-r--r--chromium/content/browser/media/media_internals.h108
-rw-r--r--chromium/content/browser/media/media_internals_handler.cc13
-rw-r--r--chromium/content/browser/media/media_internals_handler.h6
-rw-r--r--chromium/content/browser/media/media_internals_proxy.cc6
-rw-r--r--chromium/content/browser/media/media_internals_proxy.h4
-rw-r--r--chromium/content/browser/media/media_internals_unittest.cc253
-rw-r--r--chromium/content/browser/media/media_source_browsertest.cc29
-rw-r--r--chromium/content/browser/media/webrtc_browsertest.cc372
-rw-r--r--chromium/content/browser/media/webrtc_identity_store.cc56
-rw-r--r--chromium/content/browser/media/webrtc_identity_store.h5
-rw-r--r--chromium/content/browser/media/webrtc_identity_store_backend.cc143
-rw-r--r--chromium/content/browser/media/webrtc_identity_store_backend.h13
-rw-r--r--chromium/content/browser/media/webrtc_identity_store_unittest.cc80
-rw-r--r--chromium/content/browser/media/webrtc_internals_browsertest.cc2
-rw-r--r--chromium/content/browser/media/webrtc_internals_message_handler.cc4
-rw-r--r--chromium/content/browser/message_port_message_filter.cc65
-rw-r--r--chromium/content/browser/message_port_message_filter.h49
-rw-r--r--chromium/content/browser/message_port_service.cc (renamed from chromium/content/browser/worker_host/message_port_service.cc)24
-rw-r--r--chromium/content/browser/message_port_service.h (renamed from chromium/content/browser/worker_host/message_port_service.h)29
-rw-r--r--chromium/content/browser/net/sqlite_persistent_cookie_store.cc160
-rw-r--r--chromium/content/browser/net/sqlite_persistent_cookie_store.h4
-rw-r--r--chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc7
-rw-r--r--chromium/content/browser/net/sqlite_persistent_cookie_store_unittest.cc169
-rw-r--r--chromium/content/browser/plugin_browsertest.cc131
-rw-r--r--chromium/content/browser/plugin_loader_posix_unittest.cc6
-rw-r--r--chromium/content/browser/plugin_process_host.cc22
-rw-r--r--chromium/content/browser/plugin_process_host.h14
-rw-r--r--chromium/content/browser/plugin_service_impl.cc74
-rw-r--r--chromium/content/browser/plugin_service_impl.h11
-rw-r--r--chromium/content/browser/power_save_blocker_android.cc2
-rw-r--r--chromium/content/browser/power_save_blocker_mac.cc2
-rw-r--r--chromium/content/browser/power_save_blocker_win.cc2
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc40
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.h2
-rw-r--r--chromium/content/browser/profiler_message_filter.cc2
-rw-r--r--chromium/content/browser/renderer_data_memoizing_store.h214
-rw-r--r--chromium/content/browser/renderer_host/DEPS15
-rw-r--r--chromium/content/browser/renderer_host/OWNERS7
-rw-r--r--chromium/content/browser/renderer_host/backing_store_aura.cc4
-rw-r--r--chromium/content/browser/renderer_host/backing_store_gtk.cc8
-rw-r--r--chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc61
-rw-r--r--chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h37
-rw-r--r--chromium/content/browser/renderer_host/clipboard_message_filter.cc108
-rw-r--r--chromium/content/browser/renderer_host/clipboard_message_filter.h35
-rw-r--r--chromium/content/browser/renderer_host/clipboard_message_filter_mac.mm3
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_context_mac.h8
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm34
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.mm8
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_mac.h59
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_mac.mm207
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc209
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h51
-rw-r--r--chromium/content/browser/renderer_host/database_message_filter.cc48
-rw-r--r--chromium/content/browser/renderer_host/database_message_filter.h24
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_evictor.cc34
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_evictor.h41
-rw-r--r--chromium/content/browser/renderer_host/dip_util.cc2
-rw-r--r--chromium/content/browser/renderer_host/file_utilities_message_filter.cc2
-rw-r--r--chromium/content/browser/renderer_host/frame_memory_manager.h44
-rw-r--r--chromium/content/browser/renderer_host/generic_touch_gesture_android.cc62
-rw-r--r--chromium/content/browser/renderer_host/generic_touch_gesture_android.h48
-rw-r--r--chromium/content/browser/renderer_host/gpu_message_filter.cc45
-rw-r--r--chromium/content/browser/renderer_host/gpu_message_filter.h6
-rw-r--r--chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc30
-rw-r--r--chromium/content/browser/renderer_host/gtk_im_context_wrapper.h6
-rw-r--r--chromium/content/browser/renderer_host/gtk_key_bindings_handler.cc2
-rw-r--r--chromium/content/browser/renderer_host/gtk_window_utils.cc12
-rw-r--r--chromium/content/browser/renderer_host/gtk_window_utils.h4
-rw-r--r--chromium/content/browser/renderer_host/image_transport_factory_android.cc116
-rw-r--r--chromium/content/browser/renderer_host/image_transport_factory_android.h5
-rw-r--r--chromium/content/browser/renderer_host/ime_adapter_android.cc61
-rw-r--r--chromium/content/browser/renderer_host/ime_adapter_android.h3
-rw-r--r--chromium/content/browser/renderer_host/input/browser_input_event.cc47
-rw-r--r--chromium/content/browser/renderer_host/input/browser_input_event.h69
-rw-r--r--chromium/content/browser/renderer_host/input/buffered_input_router.cc336
-rw-r--r--chromium/content/browser/renderer_host/input/buffered_input_router.h144
-rw-r--r--chromium/content/browser/renderer_host/input/buffered_input_router_unittest.cc320
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_filter.cc269
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_filter.h86
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_filter_unittest.cc912
-rw-r--r--chromium/content/browser/renderer_host/input/immediate_input_router.cc574
-rw-r--r--chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc1858
-rw-r--r--chromium/content/browser/renderer_host/input/input_ack_handler.h4
-rw-r--r--chromium/content/browser/renderer_host/input/input_queue.cc183
-rw-r--r--chromium/content/browser/renderer_host/input/input_queue.h82
-rw-r--r--chromium/content/browser/renderer_host/input/input_queue_client.h35
-rw-r--r--chromium/content/browser/renderer_host/input/input_queue_unittest.cc363
-rw-r--r--chromium/content/browser/renderer_host/input/input_router.h21
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_client.h28
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.cc729
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.h (renamed from chromium/content/browser/renderer_host/input/immediate_input_router.h)190
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc894
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_unittest.cc225
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_unittest.h83
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc35
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_ack_handler.h23
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.cc115
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.h72
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture.cc46
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture.h57
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc80
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h49
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc814
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target.h55
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc92
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h58
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc163
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h53
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc122
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h71
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.cc166
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.h61
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc223
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h70
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc119
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h49
-rw-r--r--chromium/content/browser/renderer_host/input/tap_suppression_controller.cc24
-rw-r--r--chromium/content/browser/renderer_host/input/tap_suppression_controller.h10
-rw-r--r--chromium/content/browser/renderer_host/input/tap_suppression_controller_client.h9
-rw-r--r--chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc28
-rw-r--r--chromium/content/browser/renderer_host/input/timeout_monitor.cc78
-rw-r--r--chromium/content/browser/renderer_host/input/timeout_monitor.h50
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.cc63
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.h45
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc100
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.cc404
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.h72
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc1148
-rw-r--r--chromium/content/browser/renderer_host/input/touch_input_browsertest.cc307
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc9
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h19
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller_aura.cc19
-rw-r--r--chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc48
-rw-r--r--chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h23
-rw-r--r--chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller_stub.cc9
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc12
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android.h10
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.cc12
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.h12
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_win.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_win.h6
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util.h4
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util_posix.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util_posix.h2
-rw-r--r--chromium/content/browser/renderer_host/java/OWNERS2
-rw-r--r--chromium/content/browser/renderer_host/java/java_bound_object.cc4
-rw-r--r--chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc64
-rw-r--r--chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.h33
-rw-r--r--chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc27
-rw-r--r--chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h10
-rw-r--r--chromium/content/browser/renderer_host/java/java_method.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/OWNERS3
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc13
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.h4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.cc89
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.h13
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc185
-rw-r--r--chromium/content/browser/renderer_host/media/audio_sync_reader.cc174
-rw-r--r--chromium/content/browser/renderer_host/media/audio_sync_reader.h29
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device.cc323
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device.h12
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device_aura.cc442
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device_aura.h48
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device_aura_unittest.cc114
-rw-r--r--chromium/content/browser/renderer_host/media/desktop_capture_device_unittest.cc230
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter.cc105
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter.h31
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc99
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc164
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h54
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc672
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc1454
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.h188
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc36
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_provider.h5
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_requester.h25
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc8
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc8
-rw-r--r--chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc23
-rw-r--r--chromium/content/browser/renderer_host/media/midi_dispatcher_host.h7
-rw-r--r--chromium/content/browser/renderer_host/media/midi_host.cc141
-rw-r--r--chromium/content/browser/renderer_host/media/midi_host.h28
-rw-r--r--chromium/content/browser/renderer_host/media/midi_host_unittest.cc90
-rw-r--r--chromium/content/browser/renderer_host/media/mock_media_observer.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/mock_media_observer.h22
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc235
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool.h101
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc285
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc770
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.h40
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h30
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc328
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_device_impl.cc304
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_device_impl.h191
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.cc119
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.h114
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc277
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.cc304
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.h94
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc149
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_oracle.cc10
-rw-r--r--chromium/content/browser/renderer_host/media/web_contents_video_capture_device.cc699
-rw-r--r--chromium/content/browser/renderer_host/media/web_contents_video_capture_device.h29
-rw-r--r--chromium/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc401
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc12
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h7
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc20
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc4
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc18
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm2
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_win.cc2
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.cc143
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.h32
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller_delegate.h5
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc20
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h9
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.h7
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc24
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.h6
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc4
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h6
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc39
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc210
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h215
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.cc78
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.h10
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc42
-rw-r--r--chromium/content/browser/renderer_host/pepper/OWNERS1
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc12
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h7
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc3
-rw-r--r--chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc5
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc24
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h1
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc611
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h165
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc23
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h8
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc476
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h139
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc80
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc29
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc24
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc5
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc152
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc18
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc12
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_ozone.cc20
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_pango.cc (renamed from chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_linux.cc)1
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation.cc147
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation.h97
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc248
-rw-r--r--chromium/content/browser/renderer_host/render_frame_host_impl.cc67
-rw-r--r--chromium/content/browser/renderer_host/render_frame_host_impl.h47
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.cc218
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.h39
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_browsertest.cc40
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc474
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h42
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_unittest.cc29
-rw-r--r--chromium/content/browser/renderer_host/render_sandbox_host_linux.cc40
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_browsertest.cc8
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.cc8
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.h64
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.cc10
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.h3
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc565
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h160
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_unittest.cc15
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.cc8
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.h4
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_browsertest.cc3
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.h4
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc746
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h102
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc355
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc562
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h91
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc999
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h158
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc429
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc77
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h32
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc56
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_gtk.cc88
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_gtk.h14
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_guest.cc123
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_guest.h19
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.h77
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm616
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm18
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_win.cc253
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_win.h52
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc226
-rw-r--r--chromium/content/browser/renderer_host/renderer_frame_manager.cc (renamed from chromium/content/browser/renderer_host/frame_memory_manager.cc)36
-rw-r--r--chromium/content/browser/renderer_host/renderer_frame_manager.h50
-rw-r--r--chromium/content/browser/renderer_host/software_frame_manager.cc202
-rw-r--r--chromium/content/browser/renderer_host/software_frame_manager.h79
-rw-r--r--chromium/content/browser/renderer_host/software_frame_manager_unittest.cc255
-rw-r--r--chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc143
-rw-r--r--chromium/content/browser/renderer_host/surface_texture_transport_client_android.h62
-rw-r--r--chromium/content/browser/renderer_host/synthetic_gesture_calculator.cc37
-rw-r--r--chromium/content/browser/renderer_host/synthetic_gesture_calculator.h28
-rw-r--r--chromium/content/browser/renderer_host/synthetic_gesture_controller.cc84
-rw-r--r--chromium/content/browser/renderer_host/synthetic_gesture_controller.h57
-rw-r--r--chromium/content/browser/renderer_host/synthetic_gesture_controller_unittest.cc183
-rw-r--r--chromium/content/browser/renderer_host/test_backing_store.cc38
-rw-r--r--chromium/content/browser/renderer_host/test_backing_store.h39
-rw-r--r--chromium/content/browser/renderer_host/test_render_view_host.cc418
-rw-r--r--chromium/content/browser/renderer_host/test_render_view_host.h378
-rw-r--r--chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc75
-rw-r--r--chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h45
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.cc131
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.h8
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura.cc120
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura.h16
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc50
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aurawin.cc10
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aurax11.cc16
-rw-r--r--chromium/content/browser/renderer_host/webmenurunner_mac.mm8
-rw-r--r--chromium/content/browser/renderer_host/websocket_dispatcher_host.cc168
-rw-r--r--chromium/content/browser/renderer_host/websocket_dispatcher_host.h140
-rw-r--r--chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc158
-rw-r--r--chromium/content/browser/renderer_host/websocket_host.cc223
-rw-r--r--chromium/content/browser/renderer_host/websocket_host.h71
-rw-r--r--chromium/content/browser/resolve_proxy_msg_helper_unittest.cc22
-rw-r--r--chromium/content/browser/resource_context_impl.cc24
-rw-r--r--chromium/content/browser/resources/gpu/gpu_internals.html4
-rw-r--r--chromium/content/browser/resources/gpu/info_view.js34
-rw-r--r--chromium/content/browser/resources/media/client_renderer.js150
-rw-r--r--chromium/content/browser/resources/media/dump_creator.js10
-rw-r--r--chromium/content/browser/resources/media/main.js33
-rw-r--r--chromium/content/browser/resources/media/manager.js52
-rw-r--r--chromium/content/browser/resources/media/media_internals.css47
-rw-r--r--chromium/content/browser/resources/media/media_internals.html33
-rw-r--r--chromium/content/browser/resources/media/stats_graph_helper.js1
-rw-r--r--chromium/content/browser/resources/media/stats_table.js11
-rw-r--r--chromium/content/browser/resources/media/tab_view.js119
-rw-r--r--chromium/content/browser/resources/media/webrtc_internals.css76
-rw-r--r--chromium/content/browser/resources/media/webrtc_internals.html7
-rw-r--r--chromium/content/browser/resources/media/webrtc_internals.js30
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc113
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc99
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h102
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc137
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.cc70
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.h77
-rw-r--r--chromium/content/browser/service_worker/service_worker_context.cc25
-rw-r--r--chromium/content/browser/service_worker/service_worker_context.h36
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.cc99
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.h104
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_unittest.cc168
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.cc52
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.h54
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.cc179
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.h45
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc190
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.cc19
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.h42
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.cc117
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.h80
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.cc43
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.h88
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_status.cc41
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_status.h29
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_unittest.cc85
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.cc194
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.h108
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage_unittest.cc384
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc56
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h94
-rw-r--r--chromium/content/browser/session_history_browsertest.cc2
-rw-r--r--chromium/content/browser/signed_certificate_timestamp_store_impl.cc39
-rw-r--r--chromium/content/browser/signed_certificate_timestamp_store_impl.h43
-rw-r--r--chromium/content/browser/site_instance_impl.cc50
-rw-r--r--chromium/content/browser/site_instance_impl.h32
-rw-r--r--chromium/content/browser/site_instance_impl_unittest.cc22
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc330
-rw-r--r--chromium/content/browser/speech/OWNERS1
-rw-r--r--chromium/content/browser/speech/google_one_shot_remote_engine.cc2
-rw-r--r--chromium/content/browser/speech/google_streaming_remote_engine.cc13
-rw-r--r--chromium/content/browser/speech/google_streaming_remote_engine.h13
-rw-r--r--chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc4
-rw-r--r--chromium/content/browser/speech/input_tag_speech_browsertest.cc10
-rw-r--r--chromium/content/browser/speech/input_tag_speech_dispatcher_host.cc45
-rw-r--r--chromium/content/browser/speech/input_tag_speech_dispatcher_host.h16
-rw-r--r--chromium/content/browser/speech/speech_recognition_browsertest.cc202
-rw-r--r--chromium/content/browser/speech/speech_recognition_dispatcher_host.cc60
-rw-r--r--chromium/content/browser/speech/speech_recognition_dispatcher_host.h14
-rw-r--r--chromium/content/browser/speech/speech_recognition_manager_impl.cc35
-rw-r--r--chromium/content/browser/speech/speech_recognition_manager_impl.h6
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.cc2
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.h2
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_android.cc4
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_unittest.cc2
-rw-r--r--chromium/content/browser/ssl/ssl_client_auth_handler.cc53
-rw-r--r--chromium/content/browser/ssl/ssl_client_auth_handler.h11
-rw-r--r--chromium/content/browser/ssl/ssl_error_handler.cc2
-rw-r--r--chromium/content/browser/ssl/ssl_manager.cc26
-rw-r--r--chromium/content/browser/ssl/ssl_policy.cc5
-rw-r--r--chromium/content/browser/ssl/ssl_policy_backend.cc2
-rw-r--r--chromium/content/browser/storage_partition_impl.cc409
-rw-r--r--chromium/content/browser/storage_partition_impl.h77
-rw-r--r--chromium/content/browser/storage_partition_impl_map.cc12
-rw-r--r--chromium/content/browser/storage_partition_impl_unittest.cc863
-rw-r--r--chromium/content/browser/streams/stream_url_request_job_unittest.cc14
-rw-r--r--chromium/content/browser/theme_helper_mac.h44
-rw-r--r--chromium/content/browser/theme_helper_mac.mm117
-rw-r--r--chromium/content/browser/tracing/trace_controller_impl.cc417
-rw-r--r--chromium/content/browser/tracing/trace_controller_impl.h109
-rw-r--r--chromium/content/browser/tracing/trace_message_filter.cc79
-rw-r--r--chromium/content/browser/tracing/trace_message_filter.h13
-rw-r--r--chromium/content/browser/tracing/trace_subscriber_stdio.cc201
-rw-r--r--chromium/content/browser/tracing/trace_subscriber_stdio.h57
-rw-r--r--chromium/content/browser/tracing/trace_subscriber_stdio_unittest.cc132
-rw-r--r--chromium/content/browser/tracing/tracing_controller_browsertest.cc205
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc531
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.h107
-rw-r--r--chromium/content/browser/tracing/tracing_ui.cc593
-rw-r--r--chromium/content/browser/utility_process_host_impl.cc24
-rw-r--r--chromium/content/browser/utility_process_host_impl.h7
-rw-r--r--chromium/content/browser/vibration/vibration_message_filter.cc (renamed from chromium/content/browser/android/vibration_message_filter.cc)46
-rw-r--r--chromium/content/browser/vibration/vibration_message_filter.h (renamed from chromium/content/browser/android/vibration_message_filter.h)17
-rw-r--r--chromium/content/browser/vibration/vibration_provider_android.cc57
-rw-r--r--chromium/content/browser/vibration/vibration_provider_android.h30
-rw-r--r--chromium/content/browser/web_contents/OWNERS2
-rw-r--r--chromium/content/browser/web_contents/aura/window_slider_unittest.cc6
-rw-r--r--chromium/content/browser/web_contents/debug_urls.h20
-rw-r--r--chromium/content/browser/web_contents/drag_utils_gtk.cc12
-rw-r--r--chromium/content/browser/web_contents/drag_utils_gtk.h4
-rw-r--r--chromium/content/browser/web_contents/frame_tree_node.cc37
-rw-r--r--chromium/content/browser/web_contents/frame_tree_node.h76
-rw-r--r--chromium/content/browser/web_contents/touch_editable_impl_aura.cc13
-rw-r--r--chromium/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc97
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.cc58
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.h46
-rw-r--r--chromium/content/browser/web_contents/web_contents_delegate_unittest.cc2
-rw-r--r--chromium/content/browser/web_contents/web_contents_drag_win.cc16
-rw-r--r--chromium/content/browser/web_contents/web_contents_drag_win.h6
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc1193
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h307
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc87
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_unittest.cc166
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.cc12
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.h10
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc448
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.h17
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc92
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_gtk.cc21
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_gtk.h6
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.cc17
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.h9
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.h23
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm63
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_win.cc8
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_win.h6
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_gtk.cc15
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_gtk.h2
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_mac.mm12
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm4
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_win.cc20
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_win.h4
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_gtk.cc6
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_gtk.h4
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac.mm12
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_win.cc6
-rw-r--r--chromium/content/browser/web_contents/web_drag_utils_win.cc14
-rw-r--r--chromium/content/browser/web_contents/web_drag_utils_win.h8
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.cc18
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.cc9
-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.cc4
-rw-r--r--chromium/content/browser/webui/web_ui_impl.cc12
-rw-r--r--chromium/content/browser/webui/web_ui_impl.h10
-rw-r--r--chromium/content/browser/webui/web_ui_message_handler.cc6
-rw-r--r--chromium/content/browser/webui/web_ui_message_handler_unittest.cc16
-rw-r--r--chromium/content/browser/worker_host/worker_message_filter.cc39
-rw-r--r--chromium/content/browser/worker_host/worker_message_filter.h16
-rw-r--r--chromium/content/browser/worker_host/worker_process_host.cc103
-rw-r--r--chromium/content/browser/worker_host/worker_process_host.h17
-rw-r--r--chromium/content/browser/worker_host/worker_service_impl.cc8
-rw-r--r--chromium/content/browser/worker_host/worker_service_impl.h8
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.cc135
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.h20
-rw-r--r--chromium/content/child/DEPS1
-rw-r--r--chromium/content/child/OWNERS5
-rw-r--r--chromium/content/child/appcache/appcache_frontend_impl.cc4
-rw-r--r--chromium/content/child/appcache/web_application_cache_host_impl.cc16
-rw-r--r--chromium/content/child/appcache/web_application_cache_host_impl.h30
-rw-r--r--chromium/content/child/browser_font_resource_trusted.cc26
-rw-r--r--chromium/content/child/browser_font_resource_trusted.h4
-rw-r--r--chromium/content/child/child_histogram_message_filter.cc56
-rw-r--r--chromium/content/child/child_histogram_message_filter.h24
-rw-r--r--chromium/content/child/child_message_filter.cc64
-rw-r--r--chromium/content/child/child_message_filter.h68
-rw-r--r--chromium/content/child/child_thread.cc93
-rw-r--r--chromium/content/child/child_thread.h31
-rw-r--r--chromium/content/child/database_util.cc4
-rw-r--r--chromium/content/child/database_util.h12
-rw-r--r--chromium/content/child/db_message_filter.cc14
-rw-r--r--chromium/content/child/db_message_filter.h4
-rw-r--r--chromium/content/child/fileapi/OWNERS1
-rw-r--r--chromium/content/child/fileapi/file_system_dispatcher.cc27
-rw-r--r--chromium/content/child/fileapi/file_system_dispatcher.h12
-rw-r--r--chromium/content/child/fileapi/webfilesystem_impl.cc60
-rw-r--r--chromium/content/child/fileapi/webfilesystem_impl.h81
-rw-r--r--chromium/content/child/fileapi/webfilewriter_base.cc14
-rw-r--r--chromium/content/child/fileapi/webfilewriter_base.h16
-rw-r--r--chromium/content/child/fileapi/webfilewriter_base_unittest.cc106
-rw-r--r--chromium/content/child/fileapi/webfilewriter_impl.cc24
-rw-r--r--chromium/content/child/fileapi/webfilewriter_impl.h4
-rw-r--r--chromium/content/child/image_decoder.cc6
-rw-r--r--chromium/content/child/indexed_db/indexed_db_dispatcher.cc74
-rw-r--r--chromium/content/child/indexed_db/indexed_db_dispatcher.h73
-rw-r--r--chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc14
-rw-r--r--chromium/content/child/indexed_db/indexed_db_key_builders.cc62
-rw-r--r--chromium/content/child/indexed_db/indexed_db_key_builders.h12
-rw-r--r--chromium/content/child/indexed_db/indexed_db_message_filter.cc45
-rw-r--r--chromium/content/child/indexed_db/indexed_db_message_filter.h19
-rw-r--r--chromium/content/child/indexed_db/webidbcursor_impl.cc (renamed from chromium/content/child/indexed_db/proxy_webidbcursor_impl.cc)54
-rw-r--r--chromium/content/child/indexed_db/webidbcursor_impl.h (renamed from chromium/content/child/indexed_db/proxy_webidbcursor_impl.h)28
-rw-r--r--chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc (renamed from chromium/content/child/indexed_db/proxy_webidbcursor_impl_unittest.cc)26
-rw-r--r--chromium/content/child/indexed_db/webidbdatabase_impl.cc (renamed from chromium/content/child/indexed_db/proxy_webidbdatabase_impl.cc)200
-rw-r--r--chromium/content/child/indexed_db/webidbdatabase_impl.h (renamed from chromium/content/child/indexed_db/proxy_webidbdatabase_impl.h)83
-rw-r--r--chromium/content/child/indexed_db/webidbfactory_impl.cc (renamed from chromium/content/child/indexed_db/proxy_webidbfactory_impl.cc)46
-rw-r--r--chromium/content/child/indexed_db/webidbfactory_impl.h (renamed from chromium/content/child/indexed_db/proxy_webidbfactory_impl.h)33
-rw-r--r--chromium/content/child/npapi/np_channel_base.cc103
-rw-r--r--chromium/content/child/npapi/npobject_proxy.cc2
-rw-r--r--chromium/content/child/npapi/npobject_stub.cc2
-rw-r--r--chromium/content/child/npapi/npobject_util.cc7
-rw-r--r--chromium/content/child/npapi/npruntime_util.cc2
-rw-r--r--chromium/content/child/npapi/plugin_host.cc6
-rw-r--r--chromium/content/child/npapi/plugin_instance_mac.mm50
-rw-r--r--chromium/content/child/npapi/plugin_stream_posix.cc6
-rw-r--r--chromium/content/child/npapi/plugin_stream_url.cc10
-rw-r--r--chromium/content/child/npapi/plugin_url_fetcher.cc53
-rw-r--r--chromium/content/child/npapi/plugin_url_fetcher.h7
-rw-r--r--chromium/content/child/npapi/plugin_web_event_converter_mac.h12
-rw-r--r--chromium/content/child/npapi/plugin_web_event_converter_mac.mm8
-rw-r--r--chromium/content/child/npapi/webplugin_delegate.h4
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl.cc14
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl.h17
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl_android.cc2
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl_aura.cc2
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl_gtk.cc6
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl_mac.mm8
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl_win.cc57
-rw-r--r--chromium/content/child/plugin_messages.h11
-rw-r--r--chromium/content/child/plugin_param_traits.cc6
-rw-r--r--chromium/content/child/quota_dispatcher.cc32
-rw-r--r--chromium/content/child/quota_dispatcher.h4
-rw-r--r--chromium/content/child/quota_message_filter.cc65
-rw-r--r--chromium/content/child/quota_message_filter.h23
-rw-r--r--chromium/content/child/request_extra_data.cc8
-rw-r--r--chromium/content/child/request_extra_data.h14
-rw-r--r--chromium/content/child/resource_dispatcher.cc11
-rw-r--r--chromium/content/child/resource_dispatcher_unittest.cc8
-rw-r--r--chromium/content/child/runtime_features.cc80
-rw-r--r--chromium/content/child/scoped_child_process_reference.cc34
-rw-r--r--chromium/content/child/scoped_child_process_reference.h37
-rw-r--r--chromium/content/child/service_worker/OWNERS3
-rw-r--r--chromium/content/child/service_worker/service_worker_dispatcher.cc150
-rw-r--r--chromium/content/child/service_worker/service_worker_dispatcher.h80
-rw-r--r--chromium/content/child/service_worker/service_worker_message_filter.cc41
-rw-r--r--chromium/content/child/service_worker/service_worker_message_filter.h41
-rw-r--r--chromium/content/child/service_worker/web_service_worker_impl.cc11
-rw-r--r--chromium/content/child/service_worker/web_service_worker_impl.h29
-rw-r--r--chromium/content/child/service_worker/web_service_worker_provider_impl.cc59
-rw-r--r--chromium/content/child/service_worker/web_service_worker_provider_impl.h49
-rw-r--r--chromium/content/child/site_isolation_policy.cc535
-rw-r--r--chromium/content/child/site_isolation_policy.h45
-rw-r--r--chromium/content/child/site_isolation_policy_unittest.cc85
-rw-r--r--chromium/content/child/socket_stream_dispatcher.cc6
-rw-r--r--chromium/content/child/socket_stream_dispatcher.h4
-rw-r--r--chromium/content/child/thread_safe_sender.h2
-rw-r--r--chromium/content/child/web_database_observer_impl.cc118
-rw-r--r--chromium/content/child/web_database_observer_impl.h60
-rw-r--r--chromium/content/child/webblobregistry_impl.cc47
-rw-r--r--chromium/content/child/webblobregistry_impl.h46
-rw-r--r--chromium/content/child/webkitplatformsupport_impl.cc11
-rw-r--r--chromium/content/child/webkitplatformsupport_impl.h9
-rw-r--r--chromium/content/child/webmessageportchannel_impl.cc30
-rw-r--r--chromium/content/child/webmessageportchannel_impl.h20
-rw-r--r--chromium/content/child/websocket_bridge.cc284
-rw-r--r--chromium/content/child/websocket_bridge.h67
-rw-r--r--chromium/content/child/websocket_dispatcher.cc67
-rw-r--r--chromium/content/child/websocket_dispatcher.h48
-rw-r--r--chromium/content/child/worker_thread_task_runner.cc40
-rw-r--r--chromium/content/child/worker_thread_task_runner.h39
-rw-r--r--chromium/content/common/DEPS3
-rw-r--r--chromium/content/common/OWNERS10
-rw-r--r--chromium/content/common/accessibility_messages.h6
-rw-r--r--chromium/content/common/accessibility_node_data.cc287
-rw-r--r--chromium/content/common/accessibility_node_data.h28
-rw-r--r--chromium/content/common/android/OWNERS1
-rw-r--r--chromium/content/common/android/address_parser.cc14
-rw-r--r--chromium/content/common/android/address_parser.h6
-rw-r--r--chromium/content/common/android/address_parser_internal.cc30
-rw-r--r--chromium/content/common/android/address_parser_internal.h20
-rw-r--r--chromium/content/common/android/address_parser_unittest.cc22
-rw-r--r--chromium/content/common/android/command_line.cc79
-rw-r--r--chromium/content/common/android/command_line.h17
-rw-r--r--chromium/content/common/android/linker/DEPS5
-rw-r--r--chromium/content/common/browser_plugin/OWNERS1
-rw-r--r--chromium/content/common/browser_plugin/browser_plugin_constants.cc4
-rw-r--r--chromium/content/common/browser_plugin/browser_plugin_constants.h1
-rw-r--r--chromium/content/common/browser_plugin/browser_plugin_messages.h61
-rw-r--r--chromium/content/common/cc_messages.cc234
-rw-r--r--chromium/content/common/cc_messages.h5
-rw-r--r--chromium/content/common/cc_messages_perftest.cc157
-rw-r--r--chromium/content/common/cc_messages_unittest.cc296
-rw-r--r--chromium/content/common/child_process_host_impl.cc15
-rw-r--r--chromium/content/common/child_process_host_impl.h8
-rw-r--r--chromium/content/common/child_process_messages.h18
-rw-r--r--chromium/content/common/child_process_sandbox_support_impl_linux.cc6
-rw-r--r--chromium/content/common/child_process_sandbox_support_impl_linux.h6
-rw-r--r--chromium/content/common/child_process_sandbox_support_impl_shm_linux.cc2
-rw-r--r--chromium/content/common/clipboard_messages.h34
-rw-r--r--chromium/content/common/common_param_traits_unittest.cc2
-rw-r--r--chromium/content/common/content_message_generator.h2
-rw-r--r--chromium/content/common/content_param_traits.cc26
-rw-r--r--chromium/content/common/content_param_traits.h2
-rw-r--r--chromium/content/common/content_param_traits_macros.h5
-rw-r--r--chromium/content/common/database_messages.h22
-rw-r--r--chromium/content/common/date_time_suggestion.h31
-rw-r--r--chromium/content/common/desktop_notification_messages.h4
-rw-r--r--chromium/content/common/device_orientation/device_motion_hardware_buffer.h (renamed from chromium/content/common/device_motion_hardware_buffer.h)9
-rw-r--r--chromium/content/common/device_orientation/device_motion_messages.h15
-rw-r--r--chromium/content/common/device_orientation/device_orientation_hardware_buffer.h2
-rw-r--r--chromium/content/common/device_orientation/device_orientation_messages.h46
-rw-r--r--chromium/content/common/devtools_messages.h13
-rw-r--r--chromium/content/common/dom_storage/dom_storage_messages.h26
-rw-r--r--chromium/content/common/drag_messages.h10
-rw-r--r--chromium/content/common/drag_traits.h2
-rw-r--r--chromium/content/common/fileapi/OWNERS1
-rw-r--r--chromium/content/common/fileapi/file_system_messages.h26
-rw-r--r--chromium/content/common/fileapi/webblob_messages.h12
-rw-r--r--chromium/content/common/font_cache_dispatcher_win.cc10
-rw-r--r--chromium/content/common/font_config_ipc_linux.cc2
-rw-r--r--chromium/content/common/font_list_mac.mm4
-rw-r--r--chromium/content/common/font_list_ozone.cc15
-rw-r--r--chromium/content/common/font_list_win.cc10
-rw-r--r--chromium/content/common/frame_messages.h87
-rw-r--r--chromium/content/common/gamepad_hardware_buffer.h4
-rw-r--r--chromium/content/common/gamepad_user_gesture.cc6
-rw-r--r--chromium/content/common/gamepad_user_gesture.h4
-rw-r--r--chromium/content/common/gpu/OWNERS1
-rw-r--r--chromium/content/common/gpu/client/command_buffer_proxy_impl.cc164
-rw-r--r--chromium/content/common/gpu/client/command_buffer_proxy_impl.h89
-rw-r--r--chromium/content/common/gpu/client/context_provider_command_buffer.cc176
-rw-r--r--chromium/content/common/gpu/client/context_provider_command_buffer.h19
-rw-r--r--chromium/content/common/gpu/client/context_provider_command_buffer_browsertest.cc29
-rw-r--r--chromium/content/common/gpu/client/gl_helper.cc120
-rw-r--r--chromium/content/common/gpu/client/gl_helper.h113
-rw-r--r--chromium/content/common/gpu/client/gl_helper_benchmark.cc16
-rw-r--r--chromium/content/common/gpu/client/gl_helper_scaling.cc70
-rw-r--r--chromium/content/common/gpu/client/gl_helper_scaling.h10
-rw-r--r--chromium/content/common/gpu/client/gl_helper_unittests.cc255
-rw-r--r--chromium/content/common/gpu/client/gl_surface_capturer_host.cc196
-rw-r--r--chromium/content/common/gpu/client/gl_surface_capturer_host.h107
-rw-r--r--chromium/content/common/gpu/client/gpu_channel_host.cc47
-rw-r--r--chromium/content/common/gpu/client/gpu_channel_host.h30
-rw-r--r--chromium/content/common/gpu/client/gpu_context_tests.h56
-rw-r--r--chromium/content/common/gpu/client/gpu_in_process_context_tests.cc10
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc53
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl.h43
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_android.cc29
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc79
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h42
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc29
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc38
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.cc56
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.h36
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_win.cc29
-rw-r--r--chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc13
-rw-r--r--chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h6
-rw-r--r--chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc7
-rw-r--r--chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc567
-rw-r--r--chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h205
-rw-r--r--chromium/content/common/gpu/devtools_gpu_agent.cc79
-rw-r--r--chromium/content/common/gpu/devtools_gpu_agent.h52
-rw-r--r--chromium/content/common/gpu/devtools_gpu_instrumentation.cc50
-rw-r--r--chromium/content/common/gpu/devtools_gpu_instrumentation.h65
-rw-r--r--chromium/content/common/gpu/gpu_channel.cc23
-rw-r--r--chromium/content/common/gpu/gpu_channel.h6
-rw-r--r--chromium/content/common/gpu/gpu_channel_manager.h6
-rw-r--r--chromium/content/common/gpu/gpu_command_buffer_stub.cc134
-rw-r--r--chromium/content/common/gpu/gpu_command_buffer_stub.h28
-rw-r--r--chromium/content/common/gpu/gpu_memory_allocation.h156
-rw-r--r--chromium/content/common/gpu/gpu_memory_manager.cc188
-rw-r--r--chromium/content/common/gpu/gpu_memory_manager.h17
-rw-r--r--chromium/content/common/gpu/gpu_memory_manager_client.cc7
-rw-r--r--chromium/content/common/gpu/gpu_memory_manager_client.h15
-rw-r--r--chromium/content/common/gpu/gpu_memory_manager_unittest.cc323
-rw-r--r--chromium/content/common/gpu/gpu_messages.h128
-rw-r--r--chromium/content/common/gpu/gpu_rendering_stats.cc5
-rw-r--r--chromium/content/common/gpu/gpu_rendering_stats.h1
-rw-r--r--chromium/content/common/gpu/image_transport_surface.cc26
-rw-r--r--chromium/content/common/gpu/image_transport_surface.h9
-rw-r--r--chromium/content/common/gpu/image_transport_surface_android.cc182
-rw-r--r--chromium/content/common/gpu/image_transport_surface_mac.cc53
-rw-r--r--chromium/content/common/gpu/image_transport_surface_win.cc8
-rw-r--r--chromium/content/common/gpu/media/DEPS1
-rw-r--r--chromium/content/common/gpu/media/android_video_decode_accelerator.cc208
-rw-r--r--chromium/content/common/gpu/media/android_video_decode_accelerator.h30
-rw-r--r--chromium/content/common/gpu/media/android_video_encode_accelerator.cc412
-rw-r--r--chromium/content/common/gpu/media/android_video_encode_accelerator.h115
-rw-r--r--chromium/content/common/gpu/media/dxva_video_decode_accelerator.cc159
-rw-r--r--chromium/content/common/gpu/media/dxva_video_decode_accelerator.h45
-rw-r--r--chromium/content/common/gpu/media/exynos_video_decode_accelerator.cc1065
-rw-r--r--chromium/content/common/gpu/media/exynos_video_decode_accelerator.h152
-rw-r--r--chromium/content/common/gpu/media/exynos_video_encode_accelerator.cc94
-rw-r--r--chromium/content/common/gpu/media/exynos_video_encode_accelerator.h5
-rw-r--r--chromium/content/common/gpu/media/gl_surface_capturer.cc186
-rw-r--r--chromium/content/common/gpu/media/gl_surface_capturer.h88
-rw-r--r--chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc174
-rw-r--r--chromium/content/common/gpu/media/gpu_video_decode_accelerator.h35
-rw-r--r--chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc22
-rw-r--r--chromium/content/common/gpu/media/h264_bit_reader.cc10
-rw-r--r--chromium/content/common/gpu/media/h264_bit_reader.h6
-rw-r--r--chromium/content/common/gpu/media/h264_parser.cc3
-rw-r--r--chromium/content/common/gpu/media/rendering_helper.cc (renamed from chromium/content/common/gpu/media/rendering_helper_gl.cc)199
-rw-r--r--chromium/content/common/gpu/media/rendering_helper.h86
-rw-r--r--chromium/content/common/gpu/media/vaapi_h264_decoder.cc44
-rw-r--r--chromium/content/common/gpu/media/vaapi_h264_decoder.h3
-rw-r--r--chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc27
-rw-r--r--chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h4
-rw-r--r--chromium/content/common/gpu/media/vaapi_wrapper.cc69
-rw-r--r--chromium/content/common/gpu/media/vaapi_wrapper.h7
-rw-r--r--chromium/content/common/gpu/media/video_decode_accelerator_impl.h4
-rw-r--r--chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc750
-rw-r--r--chromium/content/common/gpu/surface_capturer.h100
-rw-r--r--chromium/content/common/gpu/texture_image_transport_surface.cc7
-rw-r--r--chromium/content/common/gpu/texture_image_transport_surface.h1
-rw-r--r--chromium/content/common/handle_enumerator_win.cc12
-rw-r--r--chromium/content/common/handle_enumerator_win.h5
-rw-r--r--chromium/content/common/indexed_db/indexed_db_constants.h14
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key.cc34
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key.h21
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key_path.cc18
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key_path.h20
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key_range.cc4
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key_unittest.cc10
-rw-r--r--chromium/content/common/indexed_db/indexed_db_messages.h43
-rw-r--r--chromium/content/common/indexed_db/indexed_db_param_traits.cc45
-rw-r--r--chromium/content/common/input/OWNERS1
-rw-r--r--chromium/content/common/input/event_packet.cc22
-rw-r--r--chromium/content/common/input/event_packet.h49
-rw-r--r--chromium/content/common/input/input_event.cc24
-rw-r--r--chromium/content/common/input/input_event.h49
-rw-r--r--chromium/content/common/input/input_event_disposition.cc67
-rw-r--r--chromium/content/common/input/input_event_disposition.h41
-rw-r--r--chromium/content/common/input/input_param_traits.cc222
-rw-r--r--chromium/content/common/input/input_param_traits.h61
-rw-r--r--chromium/content/common/input/input_param_traits_unittest.cc291
-rw-r--r--chromium/content/common/input/ipc_input_event_payload.cc35
-rw-r--r--chromium/content/common/input/ipc_input_event_payload.h40
-rw-r--r--chromium/content/common/input/scoped_web_input_event.cc26
-rw-r--r--chromium/content/common/input/scoped_web_input_event.h28
-rw-r--r--chromium/content/common/input/synthetic_gesture_packet.cc13
-rw-r--r--chromium/content/common/input/synthetic_gesture_packet.h39
-rw-r--r--chromium/content/common/input/synthetic_gesture_params.cc18
-rw-r--r--chromium/content/common/input/synthetic_gesture_params.h57
-rw-r--r--chromium/content/common/input/synthetic_pinch_gesture_params.cc39
-rw-r--r--chromium/content/common/input/synthetic_pinch_gesture_params.h35
-rw-r--r--chromium/content/common/input/synthetic_smooth_scroll_gesture_params.cc42
-rw-r--r--chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h36
-rw-r--r--chromium/content/common/input/synthetic_tap_gesture_params.cc33
-rw-r--r--chromium/content/common/input/synthetic_tap_gesture_params.h32
-rw-r--r--chromium/content/common/input/synthetic_web_input_event_builders.cc192
-rw-r--r--chromium/content/common/input/synthetic_web_input_event_builders.h82
-rw-r--r--chromium/content/common/input/touch_action.h25
-rw-r--r--chromium/content/common/input/web_input_event_payload.cc98
-rw-r--r--chromium/content/common/input/web_input_event_payload.h67
-rw-r--r--chromium/content/common/input/web_input_event_traits.cc304
-rw-r--r--chromium/content/common/input/web_input_event_traits.h30
-rw-r--r--chromium/content/common/input_messages.h74
-rw-r--r--chromium/content/common/java_bridge_messages.h7
-rw-r--r--chromium/content/common/mac/attributed_string_coder.h6
-rw-r--r--chromium/content/common/mac/attributed_string_coder.mm4
-rw-r--r--chromium/content/common/mac/font_descriptor.h4
-rw-r--r--chromium/content/common/mac/font_descriptor.mm2
-rw-r--r--chromium/content/common/mac/font_loader.mm8
-rw-r--r--chromium/content/common/media/media_param_traits.cc52
-rw-r--r--chromium/content/common/media/media_param_traits.h7
-rw-r--r--chromium/content/common/media/media_player_messages_android.h121
-rw-r--r--chromium/content/common/media/media_stream_messages.h62
-rw-r--r--chromium/content/common/media/media_stream_options.cc102
-rw-r--r--chromium/content/common/media/media_stream_options.h74
-rw-r--r--chromium/content/common/media/midi_messages.h6
-rw-r--r--chromium/content/common/media/video_capture_messages.h42
-rw-r--r--chromium/content/common/message_port_messages.h85
-rw-r--r--chromium/content/common/p2p_messages.h15
-rw-r--r--chromium/content/common/page_state_serialization.cc100
-rw-r--r--chromium/content/common/page_state_serialization.h11
-rw-r--r--chromium/content/common/page_state_serialization_unittest.cc51
-rw-r--r--chromium/content/common/pepper_plugin_list.cc41
-rw-r--r--chromium/content/common/plugin_constants_win.cc1
-rw-r--r--chromium/content/common/plugin_constants_win.h2
-rw-r--r--chromium/content/common/plugin_list_posix.cc10
-rw-r--r--chromium/content/common/plugin_list_win.cc46
-rw-r--r--chromium/content/common/resource_messages.cc9
-rw-r--r--chromium/content/common/resource_messages.h9
-rw-r--r--chromium/content/common/sandbox_init_linux.cc20
-rw-r--r--chromium/content/common/sandbox_linux/OWNERS3
-rw-r--r--chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc227
-rw-r--r--chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h29
-rw-r--r--chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.cc248
-rw-r--r--chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.h57
-rw-r--r--chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc70
-rw-r--r--chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.h27
-rw-r--r--chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc88
-rw-r--r--chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.h27
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.cc40
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h49
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_init_linux.cc21
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_linux.cc (renamed from chromium/content/common/sandbox_linux.cc)258
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_linux.h (renamed from chromium/content/common/sandbox_linux.h)46
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc297
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h (renamed from chromium/content/common/sandbox_seccomp_bpf_linux.h)24
-rw-r--r--chromium/content/common/sandbox_mac.mm10
-rw-r--r--chromium/content/common/sandbox_mac_diraccess_unittest.mm5
-rw-r--r--chromium/content/common/sandbox_mac_fontloading_unittest.mm2
-rw-r--r--chromium/content/common/sandbox_mac_unittest_helper.h2
-rw-r--r--chromium/content/common/sandbox_seccomp_bpf_linux.cc2083
-rw-r--r--chromium/content/common/sandbox_win.cc30
-rw-r--r--chromium/content/common/savable_url_schemes.cc2
-rw-r--r--chromium/content/common/service_worker_messages.h60
-rw-r--r--chromium/content/common/set_process_title.cc2
-rw-r--r--chromium/content/common/socket_stream_handle_data.cc2
-rw-r--r--chromium/content/common/socket_stream_handle_data.h8
-rw-r--r--chromium/content/common/ssl_status_serialization.cc61
-rw-r--r--chromium/content/common/ssl_status_serialization.h26
-rw-r--r--chromium/content/common/swapped_out_messages.cc3
-rw-r--r--chromium/content/common/url_schemes.cc9
-rw-r--r--chromium/content/common/view_messages.h377
-rw-r--r--chromium/content/common/websocket.cc18
-rw-r--r--chromium/content/common/websocket.h39
-rw-r--r--chromium/content/common/websocket_messages.h87
-rw-r--r--chromium/content/common/worker_messages.h107
-rw-r--r--chromium/content/content.gyp40
-rw-r--r--chromium/content/content_app.gypi1
-rw-r--r--chromium/content/content_browser.gypi317
-rw-r--r--chromium/content/content_browsertests.isolate10
-rw-r--r--chromium/content/content_child.gypi33
-rw-r--r--chromium/content/content_common.gypi116
-rw-r--r--chromium/content/content_gpu.gypi14
-rw-r--r--chromium/content/content_jni.gypi14
-rw-r--r--chromium/content/content_plugin.gypi4
-rw-r--r--chromium/content/content_ppapi_plugin.gypi1
-rw-r--r--chromium/content/content_renderer.gypi197
-rw-r--r--chromium/content/content_resources.grd3
-rw-r--r--chromium/content/content_shell.gypi206
-rw-r--r--chromium/content/content_shell_and_tests.gyp32
-rw-r--r--chromium/content/content_tests.gypi495
-rw-r--r--chromium/content/content_unittests.isolate45
-rw-r--r--chromium/content/content_worker.gypi2
-rw-r--r--chromium/content/gpu/OWNERS1
-rw-r--r--chromium/content/gpu/gpu_main.cc129
-rw-r--r--chromium/content/gpu/gpu_watchdog_thread.cc27
-rw-r--r--chromium/content/gpu/gpu_watchdog_thread.h4
-rw-r--r--chromium/content/plugin/plugin_channel.cc35
-rw-r--r--chromium/content/plugin/plugin_channel.h4
-rw-r--r--chromium/content/plugin/plugin_main_mac.mm2
-rw-r--r--chromium/content/plugin/plugin_thread.cc3
-rw-r--r--chromium/content/plugin/webplugin_delegate_stub.cc22
-rw-r--r--chromium/content/plugin/webplugin_delegate_stub.h13
-rw-r--r--chromium/content/plugin/webplugin_proxy.cc6
-rw-r--r--chromium/content/port/browser/event_with_latency_info.h27
-rw-r--r--chromium/content/port/browser/render_view_host_delegate_view.h4
-rw-r--r--chromium/content/port/browser/render_widget_host_view_port.h52
-rw-r--r--chromium/content/port/browser/synthetic_gesture.h36
-rw-r--r--chromium/content/port/browser/vibration_provider.h23
-rw-r--r--chromium/content/port/browser/web_contents_view_port.h2
-rw-r--r--chromium/content/port/common/input_event_ack_state.h1
-rw-r--r--chromium/content/ppapi_plugin/broker_process_dispatcher.cc7
-rw-r--r--chromium/content/ppapi_plugin/broker_process_dispatcher.h3
-rw-r--r--chromium/content/ppapi_plugin/plugin_process_dispatcher.cc6
-rw-r--r--chromium/content/ppapi_plugin/plugin_process_dispatcher.h3
-rw-r--r--chromium/content/ppapi_plugin/ppapi_plugin_main.cc20
-rw-r--r--chromium/content/ppapi_plugin/ppapi_thread.cc56
-rw-r--r--chromium/content/ppapi_plugin/ppapi_thread.h25
-rw-r--r--chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.cc92
-rw-r--r--chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h47
-rw-r--r--chromium/content/public/android/OWNERS1
-rw-r--r--chromium/content/public/app/android_library_loader_hooks.h10
-rw-r--r--chromium/content/public/browser/access_token_store.h4
-rw-r--r--chromium/content/public/browser/android/compositor.h35
-rw-r--r--chromium/content/public/browser/android/content_view_core.h1
-rw-r--r--chromium/content/public/browser/android/content_view_layer_renderer.h6
-rw-r--r--chromium/content/public/browser/android/synchronous_compositor.cc11
-rw-r--r--chromium/content/public/browser/android/synchronous_compositor.h3
-rw-r--r--chromium/content/public/browser/android/synchronous_compositor_client.h6
-rw-r--r--chromium/content/public/browser/browser_child_process_host.h2
-rw-r--r--chromium/content/public/browser/browser_child_process_host_iterator.cc10
-rw-r--r--chromium/content/public/browser/browser_child_process_host_iterator.h1
-rw-r--r--chromium/content/public/browser/browser_context.h8
-rw-r--r--chromium/content/public/browser/browser_message_filter.cc145
-rw-r--r--chromium/content/public/browser/browser_message_filter.h55
-rw-r--r--chromium/content/public/browser/browser_plugin_guest_delegate.cc11
-rw-r--r--chromium/content/public/browser/browser_plugin_guest_delegate.h16
-rw-r--r--chromium/content/public/browser/browser_thread.h4
-rw-r--r--chromium/content/public/browser/child_process_data.h2
-rw-r--r--chromium/content/public/browser/child_process_security_policy.h52
-rw-r--r--chromium/content/public/browser/content_browser_client.cc31
-rw-r--r--chromium/content/public/browser/content_browser_client.h55
-rw-r--r--chromium/content/public/browser/cookie_crypto_delegate.h22
-rw-r--r--chromium/content/public/browser/cookie_store_factory.h16
-rw-r--r--chromium/content/public/browser/desktop_media_id.cc147
-rw-r--r--chromium/content/public/browser/desktop_media_id.h (renamed from chromium/content/public/common/desktop_media_id.h)21
-rw-r--r--chromium/content/public/browser/devtools_http_handler.h23
-rw-r--r--chromium/content/public/browser/devtools_http_handler_delegate.h20
-rw-r--r--chromium/content/public/browser/devtools_target.h64
-rw-r--r--chromium/content/public/browser/download_manager.h6
-rw-r--r--chromium/content/public/browser/download_save_info.h2
-rw-r--r--chromium/content/public/browser/download_url_parameters.h6
-rw-r--r--chromium/content/public/browser/host_zoom_map.h8
-rw-r--r--chromium/content/public/browser/indexed_db_context.h2
-rw-r--r--chromium/content/public/browser/javascript_dialog_manager.cc2
-rw-r--r--chromium/content/public/browser/javascript_dialog_manager.h10
-rw-r--r--chromium/content/public/browser/media_device_id.cc39
-rw-r--r--chromium/content/public/browser/media_device_id.h38
-rw-r--r--chromium/content/public/browser/native_web_keyboard_event.h6
-rw-r--r--chromium/content/public/browser/navigation_controller.cc4
-rw-r--r--chromium/content/public/browser/navigation_controller.h29
-rw-r--r--chromium/content/public/browser/navigation_entry.h31
-rw-r--r--chromium/content/public/browser/notification_types.h37
-rw-r--r--chromium/content/public/browser/page_navigator.cc4
-rw-r--r--chromium/content/public/browser/page_navigator.h13
-rw-r--r--chromium/content/public/browser/plugin_service.h7
-rw-r--r--chromium/content/public/browser/plugin_service_filter.h2
-rw-r--r--chromium/content/public/browser/render_frame_host.h3
-rw-r--r--chromium/content/public/browser/render_process_host.h26
-rw-r--r--chromium/content/public/browser/render_process_host_observer.h27
-rw-r--r--chromium/content/public/browser/render_view_host.h55
-rw-r--r--chromium/content/public/browser/render_view_host_observer.cc56
-rw-r--r--chromium/content/public/browser/render_view_host_observer.h70
-rw-r--r--chromium/content/public/browser/render_widget_host.h21
-rw-r--r--chromium/content/public/browser/render_widget_host_view.h2
-rw-r--r--chromium/content/public/browser/render_widget_host_view_mac_delegate.h14
-rw-r--r--chromium/content/public/browser/resource_context.h41
-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_request_info.h14
-rw-r--r--chromium/content/public/browser/resource_throttle.h5
-rw-r--r--chromium/content/public/browser/session_storage_namespace.h43
-rw-r--r--chromium/content/public/browser/signed_certificate_timestamp_store.h53
-rw-r--r--chromium/content/public/browser/site_instance.h11
-rw-r--r--chromium/content/public/browser/speech_recognition_manager.h10
-rw-r--r--chromium/content/public/browser/speech_recognition_session_config.cc3
-rw-r--r--chromium/content/public/browser/speech_recognition_session_config.h3
-rw-r--r--chromium/content/public/browser/speech_recognition_session_context.cc6
-rw-r--r--chromium/content/public/browser/speech_recognition_session_context.h17
-rw-r--r--chromium/content/public/browser/storage_partition.h34
-rw-r--r--chromium/content/public/browser/trace_controller.h107
-rw-r--r--chromium/content/public/browser/trace_subscriber.h43
-rw-r--r--chromium/content/public/browser/tracing_controller.h71
-rw-r--r--chromium/content/public/browser/url_data_source.cc4
-rw-r--r--chromium/content/public/browser/url_data_source.h7
-rw-r--r--chromium/content/public/browser/user_metrics.h16
-rw-r--r--chromium/content/public/browser/utility_process_host.h6
-rw-r--r--chromium/content/public/browser/web_contents.h29
-rw-r--r--chromium/content/public/browser/web_contents_delegate.cc12
-rw-r--r--chromium/content/public/browser/web_contents_delegate.h46
-rw-r--r--chromium/content/public/browser/web_contents_observer.cc4
-rw-r--r--chromium/content/public/browser/web_contents_observer.h45
-rw-r--r--chromium/content/public/browser/web_contents_view.h9
-rw-r--r--chromium/content/public/browser/web_drag_dest_delegate.h2
-rw-r--r--chromium/content/public/browser/web_ui.h6
-rw-r--r--chromium/content/public/browser/web_ui_data_source.h3
-rw-r--r--chromium/content/public/browser/web_ui_message_handler.h2
-rw-r--r--chromium/content/public/browser/worker_service.h2
-rw-r--r--chromium/content/public/browser/worker_service_observer.h2
-rw-r--r--chromium/content/public/browser/zygote_host_linux.h6
-rw-r--r--chromium/content/public/common/browser_plugin_permission_type.h4
-rw-r--r--chromium/content/public/common/color_suggestion.cc16
-rw-r--r--chromium/content/public/common/color_suggestion.h30
-rw-r--r--chromium/content/public/common/common_param_traits.cc104
-rw-r--r--chromium/content/public/common/common_param_traits_macros.h29
-rw-r--r--chromium/content/public/common/content_client.cc4
-rw-r--r--chromium/content/public/common/content_client.h2
-rw-r--r--chromium/content/public/common/content_constants.cc9
-rw-r--r--chromium/content/public/common/content_constants.h18
-rw-r--r--chromium/content/public/common/content_descriptors.h2
-rw-r--r--chromium/content/public/common/content_switches.cc204
-rw-r--r--chromium/content/public/common/content_switches.h123
-rw-r--r--chromium/content/public/common/context_menu_params.cc12
-rw-r--r--chromium/content/public/common/context_menu_params.h15
-rw-r--r--chromium/content/public/common/desktop_media_id.cc41
-rw-r--r--chromium/content/public/common/drop_data.cc2
-rw-r--r--chromium/content/public/common/drop_data.h2
-rw-r--r--chromium/content/public/common/file_chooser_params.h4
-rw-r--r--chromium/content/public/common/media_stream_request.cc13
-rw-r--r--chromium/content/public/common/media_stream_request.h29
-rw-r--r--chromium/content/public/common/menu_item.h8
-rw-r--r--chromium/content/public/common/p2p_socket_type.h (renamed from chromium/content/common/p2p_sockets.h)8
-rw-r--r--chromium/content/public/common/page_state.cc4
-rw-r--r--chromium/content/public/common/referrer.h6
-rw-r--r--chromium/content/public/common/renderer_preferences.cc1
-rw-r--r--chromium/content/public/common/renderer_preferences.h3
-rw-r--r--chromium/content/public/common/result_codes_list.h6
-rw-r--r--chromium/content/public/common/sandbox_init.h20
-rw-r--r--chromium/content/public/common/sandbox_linux.h5
-rw-r--r--chromium/content/public/common/show_desktop_notification_params.cc2
-rw-r--r--chromium/content/public/common/show_desktop_notification_params.h14
-rw-r--r--chromium/content/public/common/signed_certificate_timestamp_id_and_status.cc18
-rw-r--r--chromium/content/public/common/signed_certificate_timestamp_id_and_status.h32
-rw-r--r--chromium/content/public/common/speech_recognition_result.h4
-rw-r--r--chromium/content/public/common/ssl_status.cc2
-rw-r--r--chromium/content/public/common/ssl_status.h7
-rw-r--r--chromium/content/public/common/url_constants.cc5
-rw-r--r--chromium/content/public/common/url_constants.h7
-rw-r--r--chromium/content/public/common/url_utils.cc20
-rw-r--r--chromium/content/public/common/url_utils.h25
-rw-r--r--chromium/content/public/common/user_metrics_action.h29
-rw-r--r--chromium/content/public/common/webplugininfo.cc2
-rw-r--r--chromium/content/public/common/window_container_type.cc2
-rw-r--r--chromium/content/public/common/window_container_type.h4
-rw-r--r--chromium/content/public/common/zygote_fork_delegate_linux.h12
-rw-r--r--chromium/content/public/plugin/content_plugin_client.h2
-rw-r--r--chromium/content/public/renderer/android/OWNERS5
-rw-r--r--chromium/content/public/renderer/content_renderer_client.cc96
-rw-r--r--chromium/content/public/renderer/content_renderer_client.h131
-rw-r--r--chromium/content/public/renderer/document_state.h4
-rw-r--r--chromium/content/public/renderer/history_item_serialization.cc33
-rw-r--r--chromium/content/public/renderer/history_item_serialization.h6
-rw-r--r--chromium/content/public/renderer/media_stream_audio_sink.cc40
-rw-r--r--chromium/content/public/renderer/media_stream_audio_sink.h59
-rw-r--r--chromium/content/public/renderer/media_stream_sink.h30
-rw-r--r--chromium/content/public/renderer/media_stream_video_sink.cc31
-rw-r--r--chromium/content/public/renderer/media_stream_video_sink.h47
-rw-r--r--chromium/content/public/renderer/navigation_state.cc1
-rw-r--r--chromium/content/public/renderer/navigation_state.h18
-rw-r--r--chromium/content/public/renderer/p2p_socket_client.h62
-rw-r--r--chromium/content/public/renderer/p2p_socket_client_delegate.h46
-rw-r--r--chromium/content/public/renderer/pepper_plugin_instance.h14
-rw-r--r--chromium/content/public/renderer/render_frame.h55
-rw-r--r--chromium/content/public/renderer/render_frame_observer.cc55
-rw-r--r--chromium/content/public/renderer/render_frame_observer.h61
-rw-r--r--chromium/content/public/renderer/render_frame_observer_tracker.h68
-rw-r--r--chromium/content/public/renderer/render_thread.h21
-rw-r--r--chromium/content/public/renderer/render_view.h70
-rw-r--r--chromium/content/public/renderer/render_view_observer.cc2
-rw-r--r--chromium/content/public/renderer/render_view_observer.h69
-rw-r--r--chromium/content/public/renderer/renderer_ppapi_host.h22
-rw-r--r--chromium/content/public/renderer/resource_fetcher.h55
-rw-r--r--chromium/content/public/renderer/v8_value_converter.h6
-rw-r--r--chromium/content/public/renderer/web_preferences.h4
-rw-r--r--chromium/content/public/renderer/webrtc_log_message_delegate.h8
-rw-r--r--chromium/content/renderer/DEPS1
-rw-r--r--chromium/content/renderer/OWNERS1
-rw-r--r--chromium/content/renderer/accessibility/accessibility_node_serializer.cc136
-rw-r--r--chromium/content/renderer/accessibility/accessibility_node_serializer.h6
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility.cc62
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility.h8
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc84
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility_complete.cc68
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility_complete.h16
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc36
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h8
-rw-r--r--chromium/content/renderer/active_notification_tracker.cc16
-rw-r--r--chromium/content/renderer/active_notification_tracker.h22
-rw-r--r--chromium/content/renderer/active_notification_tracker_unittest.cc6
-rw-r--r--chromium/content/renderer/android/OWNERS1
-rw-r--r--chromium/content/renderer/android/address_detector.cc13
-rw-r--r--chromium/content/renderer/android/address_detector.h6
-rw-r--r--chromium/content/renderer/android/content_detector.cc14
-rw-r--r--chromium/content/renderer/android/content_detector.h14
-rw-r--r--chromium/content/renderer/android/email_detector.cc6
-rw-r--r--chromium/content/renderer/android/email_detector.h4
-rw-r--r--chromium/content/renderer/android/email_detector_unittest.cc4
-rw-r--r--chromium/content/renderer/android/phone_number_detector.cc13
-rw-r--r--chromium/content/renderer/android/phone_number_detector.h4
-rw-r--r--chromium/content/renderer/android/phone_number_detector_unittest.cc8
-rw-r--r--chromium/content/renderer/bmp_image_decoder_unittest.cc4
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.cc263
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.h99
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc53
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc13
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc207
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.h49
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_manager.h6
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc5
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h3
-rw-r--r--chromium/content/renderer/browser_plugin/mock_browser_plugin.cc5
-rw-r--r--chromium/content/renderer/browser_plugin/mock_browser_plugin.h3
-rw-r--r--chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc6
-rw-r--r--chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h4
-rw-r--r--chromium/content/renderer/clipboard_client.h24
-rw-r--r--chromium/content/renderer/clipboard_utils.cc39
-rw-r--r--chromium/content/renderer/clipboard_utils.h27
-rw-r--r--chromium/content/renderer/context_menu_params_builder.cc16
-rw-r--r--chromium/content/renderer/context_menu_params_builder.h4
-rw-r--r--chromium/content/renderer/cpp_bound_class_unittest.cc6
-rw-r--r--chromium/content/renderer/cursor_utils.cc4
-rw-r--r--chromium/content/renderer/cursor_utils.h10
-rw-r--r--chromium/content/renderer/date_time_formatter.cc300
-rw-r--r--chromium/content/renderer/date_time_formatter.h81
-rw-r--r--chromium/content/renderer/date_time_formatter_unittest.cc225
-rw-r--r--chromium/content/renderer/date_time_suggestion_builder.cc22
-rw-r--r--chromium/content/renderer/date_time_suggestion_builder.h23
-rw-r--r--chromium/content/renderer/device_orientation/device_motion_event_pump.cc4
-rw-r--r--chromium/content/renderer/device_orientation/device_motion_event_pump.h8
-rw-r--r--chromium/content/renderer/device_orientation/device_motion_event_pump_unittest.cc18
-rw-r--r--chromium/content/renderer/device_orientation/device_orientation_event_pump.cc6
-rw-r--r--chromium/content/renderer/device_orientation/device_orientation_event_pump.h12
-rw-r--r--chromium/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc53
-rw-r--r--chromium/content/renderer/device_orientation/device_sensor_event_pump.cc5
-rw-r--r--chromium/content/renderer/device_orientation_dispatcher.cc94
-rw-r--r--chromium/content/renderer/device_orientation_dispatcher.h46
-rw-r--r--chromium/content/renderer/devtools/devtools_agent.cc120
-rw-r--r--chromium/content/renderer/devtools/devtools_agent.h53
-rw-r--r--chromium/content/renderer/devtools/devtools_agent_filter.cc4
-rw-r--r--chromium/content/renderer/devtools/devtools_client.cc6
-rw-r--r--chromium/content/renderer/devtools/devtools_client.h10
-rw-r--r--chromium/content/renderer/disambiguation_popup_helper.cc4
-rw-r--r--chromium/content/renderer/disambiguation_popup_helper.h4
-rw-r--r--chromium/content/renderer/disambiguation_popup_helper_unittest.cc6
-rw-r--r--chromium/content/renderer/dom_serializer_browsertest.cc62
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_cached_area.cc18
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_cached_area.h11
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc7
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc57
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_dispatcher.h1
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_proxy.h5
-rw-r--r--chromium/content/renderer/dom_storage/webstoragearea_impl.cc4
-rw-r--r--chromium/content/renderer/dom_storage/webstoragearea_impl.h14
-rw-r--r--chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc6
-rw-r--r--chromium/content/renderer/dom_storage/webstoragenamespace_impl.h8
-rw-r--r--chromium/content/renderer/drop_data_builder.cc6
-rw-r--r--chromium/content/renderer/drop_data_builder.h4
-rw-r--r--chromium/content/renderer/external_popup_menu.cc25
-rw-r--r--chromium/content/renderer/external_popup_menu.h25
-rw-r--r--chromium/content/renderer/external_popup_menu_browsertest.cc6
-rw-r--r--chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.cc21
-rw-r--r--chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.h29
-rw-r--r--chromium/content/renderer/fetchers/image_resource_fetcher.cc12
-rw-r--r--chromium/content/renderer/fetchers/image_resource_fetcher.h17
-rw-r--r--chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc12
-rw-r--r--chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h20
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher.h135
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_impl.cc (renamed from chromium/content/renderer/fetchers/resource_fetcher.cc)103
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_impl.h102
-rw-r--r--chromium/content/renderer/gamepad_shared_memory_reader.cc6
-rw-r--r--chromium/content/renderer/gamepad_shared_memory_reader.h2
-rw-r--r--chromium/content/renderer/geolocation_dispatcher.cc16
-rw-r--r--chromium/content/renderer/geolocation_dispatcher.h16
-rw-r--r--chromium/content/renderer/gin_browsertest.cc95
-rw-r--r--chromium/content/renderer/gpu/OWNERS4
-rw-r--r--chromium/content/renderer/gpu/compositor_output_surface.cc23
-rw-r--r--chromium/content/renderer/gpu/compositor_output_surface.h4
-rw-r--r--chromium/content/renderer/gpu/compositor_software_output_device.cc3
-rw-r--r--chromium/content/renderer/gpu/compositor_software_output_device.h1
-rw-r--r--chromium/content/renderer/gpu/gpu_benchmarking_extension.cc632
-rw-r--r--chromium/content/renderer/gpu/mailbox_output_surface.cc13
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor.cc151
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor.h74
-rw-r--r--chromium/content/renderer/ico_image_decoder_unittest.cc6
-rw-r--r--chromium/content/renderer/idle_user_detector.cc2
-rw-r--r--chromium/content/renderer/idle_user_detector.h4
-rw-r--r--chromium/content/renderer/image_loading_helper.cc9
-rw-r--r--chromium/content/renderer/input/OWNERS2
-rw-r--r--chromium/content/renderer/input/input_event_filter.cc (renamed from chromium/content/renderer/gpu/input_event_filter.cc)16
-rw-r--r--chromium/content/renderer/input/input_event_filter.h (renamed from chromium/content/renderer/gpu/input_event_filter.h)12
-rw-r--r--chromium/content/renderer/input/input_event_filter_unittest.cc (renamed from chromium/content/renderer/gpu/input_event_filter_unittest.cc)14
-rw-r--r--chromium/content/renderer/input/input_handler_manager.cc (renamed from chromium/content/renderer/gpu/input_handler_manager.cc)23
-rw-r--r--chromium/content/renderer/input/input_handler_manager.h (renamed from chromium/content/renderer/gpu/input_handler_manager.h)21
-rw-r--r--chromium/content/renderer/input/input_handler_manager_client.h (renamed from chromium/content/renderer/gpu/input_handler_manager_client.h)10
-rw-r--r--chromium/content/renderer/input/input_handler_proxy.cc (renamed from chromium/content/renderer/gpu/input_handler_proxy.cc)67
-rw-r--r--chromium/content/renderer/input/input_handler_proxy.h (renamed from chromium/content/renderer/gpu/input_handler_proxy.h)34
-rw-r--r--chromium/content/renderer/input/input_handler_proxy_client.h (renamed from chromium/content/renderer/gpu/input_handler_proxy_client.h)18
-rw-r--r--chromium/content/renderer/input/input_handler_proxy_unittest.cc (renamed from chromium/content/renderer/gpu/input_handler_proxy_unittest.cc)182
-rw-r--r--chromium/content/renderer/input/input_handler_wrapper.cc (renamed from chromium/content/renderer/gpu/input_handler_wrapper.cc)19
-rw-r--r--chromium/content/renderer/input/input_handler_wrapper.h (renamed from chromium/content/renderer/gpu/input_handler_wrapper.h)32
-rw-r--r--chromium/content/renderer/input_tag_speech_dispatcher.cc28
-rw-r--r--chromium/content/renderer/input_tag_speech_dispatcher.h18
-rw-r--r--chromium/content/renderer/internal_document_state_data.cc6
-rw-r--r--chromium/content/renderer/internal_document_state_data.h20
-rw-r--r--chromium/content/renderer/java/OWNERS2
-rw-r--r--chromium/content/renderer/java/java_bridge_channel.cc4
-rw-r--r--chromium/content/renderer/java/java_bridge_dispatcher.cc12
-rw-r--r--chromium/content/renderer/java/java_bridge_dispatcher.h8
-rw-r--r--chromium/content/renderer/load_progress_tracker.cc2
-rw-r--r--chromium/content/renderer/load_progress_tracker.h6
-rw-r--r--chromium/content/renderer/media/active_loader.cc2
-rw-r--r--chromium/content/renderer/media/active_loader.h6
-rw-r--r--chromium/content/renderer/media/android/audio_decoder_android.cc16
-rw-r--r--chromium/content/renderer/media/android/audio_decoder_android.h4
-rw-r--r--chromium/content/renderer/media/android/media_info_loader.cc38
-rw-r--r--chromium/content/renderer/media/android/media_info_loader.h40
-rw-r--r--chromium/content/renderer/media/android/media_info_loader_unittest.cc43
-rw-r--r--chromium/content/renderer/media/android/media_source_delegate.cc224
-rw-r--r--chromium/content/renderer/media/android/media_source_delegate.h72
-rw-r--r--chromium/content/renderer/media/android/proxy_media_keys.cc80
-rw-r--r--chromium/content/renderer/media/android/proxy_media_keys.h54
-rw-r--r--chromium/content/renderer/media/android/renderer_demuxer_android.cc19
-rw-r--r--chromium/content/renderer/media/android/renderer_demuxer_android.h9
-rw-r--r--chromium/content/renderer/media/android/renderer_media_player_manager.cc368
-rw-r--r--chromium/content/renderer/media/android/renderer_media_player_manager.h160
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_android.h6
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_android_impl.cc6
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_android_impl.h7
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc19
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h15
-rw-r--r--chromium/content/renderer/media/android/webmediaplayer_android.cc482
-rw-r--r--chromium/content/renderer/media/android/webmediaplayer_android.h142
-rw-r--r--chromium/content/renderer/media/android/webmediaplayer_proxy_android.cc265
-rw-r--r--chromium/content/renderer/media/android/webmediaplayer_proxy_android.h136
-rw-r--r--chromium/content/renderer/media/audio_decoder.cc4
-rw-r--r--chromium/content/renderer/media/audio_decoder.h4
-rw-r--r--chromium/content/renderer/media/audio_input_message_filter.cc6
-rw-r--r--chromium/content/renderer/media/audio_message_filter.cc13
-rw-r--r--chromium/content/renderer/media/buffered_data_source.cc90
-rw-r--r--chromium/content/renderer/media/buffered_data_source.h23
-rw-r--r--chromium/content/renderer/media/buffered_data_source_unittest.cc21
-rw-r--r--chromium/content/renderer/media/buffered_resource_loader.cc52
-rw-r--r--chromium/content/renderer/media/buffered_resource_loader.h43
-rw-r--r--chromium/content/renderer/media/buffered_resource_loader_unittest.cc23
-rw-r--r--chromium/content/renderer/media/cache_util.cc2
-rw-r--r--chromium/content/renderer/media/cache_util.h4
-rw-r--r--chromium/content/renderer/media/cache_util_unittest.cc4
-rw-r--r--chromium/content/renderer/media/crypto/content_decryption_module_factory.cc78
-rw-r--r--chromium/content/renderer/media/crypto/content_decryption_module_factory.h22
-rw-r--r--chromium/content/renderer/media/crypto/key_systems.cc102
-rw-r--r--chromium/content/renderer/media/crypto/key_systems.h7
-rw-r--r--chromium/content/renderer/media/crypto/key_systems_info.cc43
-rw-r--r--chromium/content/renderer/media/crypto/key_systems_info.h27
-rw-r--r--chromium/content/renderer/media/crypto/key_systems_support_uma.cc125
-rw-r--r--chromium/content/renderer/media/crypto/key_systems_support_uma.h57
-rw-r--r--chromium/content/renderer/media/crypto/key_systems_unittest.cc5
-rw-r--r--chromium/content/renderer/media/crypto/ppapi_decryptor.cc163
-rw-r--r--chromium/content/renderer/media/crypto/ppapi_decryptor.h75
-rw-r--r--chromium/content/renderer/media/crypto/proxy_decryptor.cc172
-rw-r--r--chromium/content/renderer/media/crypto/proxy_decryptor.h103
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor.cc354
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor.h138
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_options.cc96
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_options.h53
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_unittest.cc166
-rw-r--r--chromium/content/renderer/media/media_stream_audio_sink_owner.cc70
-rw-r--r--chromium/content/renderer/media/media_stream_audio_sink_owner.h54
-rw-r--r--chromium/content/renderer/media/media_stream_audio_track_sink.h72
-rw-r--r--chromium/content/renderer/media/media_stream_center.cc127
-rw-r--r--chromium/content/renderer/media/media_stream_center.h36
-rw-r--r--chromium/content/renderer/media/media_stream_dependency_factory.cc455
-rw-r--r--chromium/content/renderer/media/media_stream_dependency_factory.h55
-rw-r--r--chromium/content/renderer/media/media_stream_dependency_factory_unittest.cc75
-rw-r--r--chromium/content/renderer/media/media_stream_dispatcher.cc229
-rw-r--r--chromium/content/renderer/media/media_stream_dispatcher.h55
-rw-r--r--chromium/content/renderer/media/media_stream_dispatcher_eventhandler.h9
-rw-r--r--chromium/content/renderer/media/media_stream_dispatcher_unittest.cc307
-rw-r--r--chromium/content/renderer/media/media_stream_extra_data.h2
-rw-r--r--chromium/content/renderer/media/media_stream_impl.cc670
-rw-r--r--chromium/content/renderer/media/media_stream_impl.h94
-rw-r--r--chromium/content/renderer/media/media_stream_impl_unittest.cc160
-rw-r--r--chromium/content/renderer/media/media_stream_registry_interface.h2
-rw-r--r--chromium/content/renderer/media/media_stream_source_extra_data.h50
-rw-r--r--chromium/content/renderer/media/media_stream_source_observer.cc8
-rw-r--r--chromium/content/renderer/media/media_stream_track_extra_data.cc20
-rw-r--r--chromium/content/renderer/media/media_stream_track_extra_data.h41
-rw-r--r--chromium/content/renderer/media/media_stream_video_track.cc47
-rw-r--r--chromium/content/renderer/media/media_stream_video_track.h49
-rw-r--r--chromium/content/renderer/media/midi_dispatcher.cc24
-rw-r--r--chromium/content/renderer/media/midi_dispatcher.h12
-rw-r--r--chromium/content/renderer/media/midi_message_filter.cc8
-rw-r--r--chromium/content/renderer/media/midi_message_filter.h8
-rw-r--r--chromium/content/renderer/media/mock_media_stream_dependency_factory.cc10
-rw-r--r--chromium/content/renderer/media/mock_media_stream_dependency_factory.h4
-rw-r--r--chromium/content/renderer/media/mock_media_stream_dispatcher.cc37
-rw-r--r--chromium/content/renderer/media/mock_media_stream_dispatcher.h12
-rw-r--r--chromium/content/renderer/media/mock_media_stream_registry.cc12
-rw-r--r--chromium/content/renderer/media/mock_media_stream_registry.h6
-rw-r--r--chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.cc6
-rw-r--r--chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.h20
-rw-r--r--chromium/content/renderer/media/peer_connection_audio_sink_owner.cc71
-rw-r--r--chromium/content/renderer/media/peer_connection_audio_sink_owner.h54
-rw-r--r--chromium/content/renderer/media/peer_connection_handler_base.cc39
-rw-r--r--chromium/content/renderer/media/peer_connection_handler_base.h9
-rw-r--r--chromium/content/renderer/media/peer_connection_identity_service.cc16
-rw-r--r--chromium/content/renderer/media/peer_connection_identity_service.h4
-rw-r--r--chromium/content/renderer/media/peer_connection_tracker.cc20
-rw-r--r--chromium/content/renderer/media/peer_connection_tracker.h22
-rw-r--r--chromium/content/renderer/media/remote_media_stream_impl.cc39
-rw-r--r--chromium/content/renderer/media/remote_media_stream_impl.h4
-rw-r--r--chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc177
-rw-r--r--chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h36
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl.cc8
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl.h10
-rw-r--r--chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc2
-rw-r--r--chromium/content/renderer/media/renderer_webmidiaccessor_impl.h8
-rw-r--r--chromium/content/renderer/media/rtc_data_channel_handler.cc18
-rw-r--r--chromium/content/renderer/media/rtc_data_channel_handler.h14
-rw-r--r--chromium/content/renderer/media/rtc_dtmf_sender_handler.cc6
-rw-r--r--chromium/content/renderer/media/rtc_dtmf_sender_handler.h12
-rw-r--r--chromium/content/renderer/media/rtc_media_constraints.cc23
-rw-r--r--chromium/content/renderer/media/rtc_media_constraints.h4
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler.cc176
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler.h95
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc177
-rw-r--r--chromium/content/renderer/media/rtc_video_capture_delegate.cc15
-rw-r--r--chromium/content/renderer/media/rtc_video_capture_delegate.h8
-rw-r--r--chromium/content/renderer/media/rtc_video_capturer.cc17
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder.cc54
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder.h7
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder_factory_tv.cc19
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder_factory_tv.h7
-rw-r--r--chromium/content/renderer/media/rtc_video_encoder.cc23
-rw-r--r--chromium/content/renderer/media/rtc_video_encoder.h10
-rw-r--r--chromium/content/renderer/media/rtc_video_renderer.cc139
-rw-r--r--chromium/content/renderer/media/rtc_video_renderer.h53
-rw-r--r--chromium/content/renderer/media/tagged_list.h94
-rw-r--r--chromium/content/renderer/media/test_response_generator.cc6
-rw-r--r--chromium/content/renderer/media/test_response_generator.h12
-rw-r--r--chromium/content/renderer/media/texttrack_impl.cc55
-rw-r--r--chromium/content/renderer/media/texttrack_impl.h25
-rw-r--r--chromium/content/renderer/media/video_capture_impl.cc211
-rw-r--r--chromium/content/renderer/media/video_capture_impl.h62
-rw-r--r--chromium/content/renderer/media/video_capture_impl_unittest.cc68
-rw-r--r--chromium/content/renderer/media/video_capture_message_filter.cc26
-rw-r--r--chromium/content/renderer/media/video_capture_message_filter.h43
-rw-r--r--chromium/content/renderer/media/video_capture_message_filter_unittest.cc204
-rw-r--r--chromium/content/renderer/media/video_destination_handler.cc4
-rw-r--r--chromium/content/renderer/media/video_destination_handler.h2
-rw-r--r--chromium/content/renderer/media/video_destination_handler_unittest.cc4
-rw-r--r--chromium/content/renderer/media/video_source_handler.cc4
-rw-r--r--chromium/content/renderer/media/video_source_handler.h2
-rw-r--r--chromium/content/renderer/media/webaudio_capturer_source.cc45
-rw-r--r--chromium/content/renderer/media/webaudio_capturer_source.h18
-rw-r--r--chromium/content/renderer/media/webaudiosourceprovider_impl.cc49
-rw-r--r--chromium/content/renderer/media/webaudiosourceprovider_impl.h26
-rw-r--r--chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc17
-rw-r--r--chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc109
-rw-r--r--chromium/content/renderer/media/webcontentdecryptionmodule_impl.h13
-rw-r--r--chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc69
-rw-r--r--chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h33
-rw-r--r--chromium/content/renderer/media/webinbandtexttrack_impl.cc38
-rw-r--r--chromium/content/renderer/media/webinbandtexttrack_impl.h31
-rw-r--r--chromium/content/renderer/media/webmediaplayer_delegate.h8
-rw-r--r--chromium/content/renderer/media/webmediaplayer_impl.cc226
-rw-r--r--chromium/content/renderer/media/webmediaplayer_impl.h110
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms.cc24
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms.h44
-rw-r--r--chromium/content/renderer/media/webmediaplayer_util.cc20
-rw-r--r--chromium/content/renderer/media/webmediaplayer_util.h6
-rw-r--r--chromium/content/renderer/media/webmediasource_impl.cc10
-rw-r--r--chromium/content/renderer/media/webmediasource_impl.h10
-rw-r--r--chromium/content/renderer/media/webrtc/OWNERS10
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.cc119
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.h60
-rw-r--r--chromium/content/renderer/media/webrtc_audio_capturer.cc233
-rw-r--r--chromium/content/renderer/media/webrtc_audio_capturer.h71
-rw-r--r--chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.cc57
-rw-r--r--chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.h66
-rw-r--r--chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc174
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_impl.cc62
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_impl.h62
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_not_impl.cc8
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_not_impl.h2
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_unittest.cc119
-rw-r--r--chromium/content/renderer/media/webrtc_audio_renderer.cc34
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_renderer.cc296
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_renderer.h76
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider.cc125
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider.h51
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc61
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_track.cc267
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_track.h53
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc332
-rw-r--r--chromium/content/renderer/media/webrtc_logging.cc (renamed from chromium/content/renderer/media/webrtc_logging_initializer.cc)12
-rw-r--r--chromium/content/renderer/media/webrtc_logging.h22
-rw-r--r--chromium/content/renderer/media/webrtc_logging_initializer.h23
-rw-r--r--chromium/content/renderer/media/webrtc_logging_noop.cc (renamed from chromium/content/common/gpu/surface_capturer.cc)4
-rw-r--r--chromium/content/renderer/media/websourcebuffer_impl.cc4
-rw-r--r--chromium/content/renderer/media/websourcebuffer_impl.h8
-rw-r--r--chromium/content/renderer/memory_benchmarking_extension.cc15
-rw-r--r--chromium/content/renderer/menu_item_builder.cc4
-rw-r--r--chromium/content/renderer/menu_item_builder.h4
-rw-r--r--chromium/content/renderer/mhtml_generator.cc4
-rw-r--r--chromium/content/renderer/mouse_lock_dispatcher.cc2
-rw-r--r--chromium/content/renderer/mouse_lock_dispatcher.h8
-rw-r--r--chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc14
-rw-r--r--chromium/content/renderer/notification_provider.cc61
-rw-r--r--chromium/content/renderer/notification_provider.h26
-rw-r--r--chromium/content/renderer/npapi/plugin_channel_host.cc2
-rw-r--r--chromium/content/renderer/npapi/webplugin_delegate_proxy.cc54
-rw-r--r--chromium/content/renderer/npapi/webplugin_delegate_proxy.h17
-rw-r--r--chromium/content/renderer/npapi/webplugin_impl.cc83
-rw-r--r--chromium/content/renderer/npapi/webplugin_impl.h86
-rw-r--r--chromium/content/renderer/npapi/webplugin_impl_unittest.cc6
-rw-r--r--chromium/content/renderer/p2p/ipc_network_manager.cc32
-rw-r--r--chromium/content/renderer/p2p/ipc_socket_factory.cc57
-rw-r--r--chromium/content/renderer/p2p/ipc_socket_factory.h1
-rw-r--r--chromium/content/renderer/p2p/port_allocator.cc18
-rw-r--r--chromium/content/renderer/p2p/port_allocator.h22
-rw-r--r--chromium/content/renderer/p2p/socket_client.cc186
-rw-r--r--chromium/content/renderer/p2p/socket_client_impl.cc243
-rw-r--r--chromium/content/renderer/p2p/socket_client_impl.h (renamed from chromium/content/renderer/p2p/socket_client.h)74
-rw-r--r--chromium/content/renderer/p2p/socket_dispatcher.cc25
-rw-r--r--chromium/content/renderer/p2p/socket_dispatcher.h15
-rw-r--r--chromium/content/renderer/pepper/OWNERS1
-rw-r--r--chromium/content/renderer/pepper/content_decryptor_delegate.cc215
-rw-r--r--chromium/content/renderer/pepper/content_decryptor_delegate.h71
-rw-r--r--chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc19
-rw-r--r--chromium/content/renderer/pepper/event_conversion.cc16
-rw-r--r--chromium/content/renderer/pepper/event_conversion.h10
-rw-r--r--chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc81
-rw-r--r--chromium/content/renderer/pepper/fake_pepper_plugin_instance.h49
-rw-r--r--chromium/content/renderer/pepper/fullscreen_container.h12
-rw-r--r--chromium/content/renderer/pepper/host_array_buffer_var.cc2
-rw-r--r--chromium/content/renderer/pepper/host_array_buffer_var.h6
-rw-r--r--chromium/content/renderer/pepper/host_dispatcher_wrapper.cc5
-rw-r--r--chromium/content/renderer/pepper/host_globals.cc8
-rw-r--r--chromium/content/renderer/pepper/host_globals.h2
-rw-r--r--chromium/content/renderer/pepper/host_resource_var.cc17
-rw-r--r--chromium/content/renderer/pepper/host_resource_var.h23
-rw-r--r--chromium/content/renderer/pepper/host_var_tracker.cc11
-rw-r--r--chromium/content/renderer/pepper/host_var_tracker.h5
-rw-r--r--chromium/content/renderer/pepper/host_var_tracker_unittest.cc2
-rw-r--r--chromium/content/renderer/pepper/message_channel.cc51
-rw-r--r--chromium/content/renderer/pepper/message_channel.h18
-rw-r--r--chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc20
-rw-r--r--chromium/content/renderer/pepper/mock_renderer_ppapi_host.h11
-rw-r--r--chromium/content/renderer/pepper/npapi_glue.cc8
-rw-r--r--chromium/content/renderer/pepper/npobject_var.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_audio_input_host.cc22
-rw-r--r--chromium/content/renderer/pepper/pepper_browser_connection.cc8
-rw-r--r--chromium/content/renderer/pepper/pepper_browser_connection.h12
-rw-r--r--chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc24
-rw-r--r--chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h9
-rw-r--r--chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc16
-rw-r--r--chromium/content/renderer/pepper/pepper_file_chooser_host.cc14
-rw-r--r--chromium/content/renderer/pepper/pepper_file_io_host.cc563
-rw-r--r--chromium/content/renderer/pepper/pepper_file_io_host.h148
-rw-r--r--chromium/content/renderer/pepper/pepper_file_system_host.cc80
-rw-r--r--chromium/content/renderer/pepper/pepper_file_system_host.h23
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host.cc150
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host.h66
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc302
-rw-r--r--chromium/content/renderer/pepper/pepper_hung_plugin_filter.cc10
-rw-r--r--chromium/content/renderer/pepper/pepper_hung_plugin_filter.h8
-rw-r--r--chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc1
-rw-r--r--chromium/content/renderer/pepper/pepper_in_process_router.cc8
-rw-r--r--chromium/content/renderer/pepper/pepper_media_device_manager.cc56
-rw-r--r--chromium/content/renderer/pepper/pepper_media_device_manager.h10
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_context_3d.cc13
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_context_3d.h9
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_video_capture.cc19
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_video_capture.h7
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc369
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.h162
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_registry.cc33
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_registry.h1
-rw-r--r--chromium/content/renderer/pepper/pepper_truetype_font_win.cc14
-rw-r--r--chromium/content/renderer/pepper/pepper_url_loader_host.cc20
-rw-r--r--chromium/content/renderer/pepper/pepper_url_loader_host.h34
-rw-r--r--chromium/content/renderer/pepper/pepper_url_request_unittest.cc14
-rw-r--r--chromium/content/renderer/pepper/pepper_video_capture_host.cc50
-rw-r--r--chromium/content/renderer/pepper/pepper_video_capture_host.h9
-rw-r--r--chromium/content/renderer/pepper/pepper_webplugin_impl.cc61
-rw-r--r--chromium/content/renderer/pepper/pepper_webplugin_impl.h54
-rw-r--r--chromium/content/renderer/pepper/pepper_websocket_host.cc20
-rw-r--r--chromium/content/renderer/pepper/pepper_websocket_host.h10
-rw-r--r--chromium/content/renderer/pepper/plugin_module.cc43
-rw-r--r--chromium/content/renderer/pepper/plugin_module.h14
-rw-r--r--chromium/content/renderer/pepper/plugin_object.cc2
-rw-r--r--chromium/content/renderer/pepper/ppb_broker_impl.cc2
-rw-r--r--chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc23
-rw-r--r--chromium/content/renderer/pepper/ppb_graphics_3d_impl.h2
-rw-r--r--chromium/content/renderer/pepper/ppb_image_data_impl.cc93
-rw-r--r--chromium/content/renderer/pepper/ppb_image_data_impl.h11
-rw-r--r--chromium/content/renderer/pepper/ppb_scrollbar_impl.cc24
-rw-r--r--chromium/content/renderer/pepper/ppb_scrollbar_impl.h20
-rw-r--r--chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc4
-rw-r--r--chromium/content/renderer/pepper/quota_file_io.cc390
-rw-r--r--chromium/content/renderer/pepper/quota_file_io.h133
-rw-r--r--chromium/content/renderer/pepper/quota_file_io_unittest.cc496
-rw-r--r--chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc38
-rw-r--r--chromium/content/renderer/pepper/renderer_ppapi_host_impl.h7
-rw-r--r--chromium/content/renderer/pepper/resource_converter.cc126
-rw-r--r--chromium/content/renderer/pepper/resource_converter.h43
-rw-r--r--chromium/content/renderer/pepper/resource_creation_impl.cc5
-rw-r--r--chromium/content/renderer/pepper/resource_creation_impl.h2
-rw-r--r--chromium/content/renderer/pepper/url_request_info_util.cc14
-rw-r--r--chromium/content/renderer/pepper/url_request_info_util.h6
-rw-r--r--chromium/content/renderer/pepper/url_response_info_util.cc6
-rw-r--r--chromium/content/renderer/pepper/url_response_info_util.h4
-rw-r--r--chromium/content/renderer/pepper/usb_key_code_conversion.cc2
-rw-r--r--chromium/content/renderer/pepper/usb_key_code_conversion.h8
-rw-r--r--chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc4
-rw-r--r--chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc4
-rw-r--r--chromium/content/renderer/pepper/usb_key_code_conversion_win.cc11
-rw-r--r--chromium/content/renderer/pepper/v8_var_converter.cc62
-rw-r--r--chromium/content/renderer/pepper/v8_var_converter_unittest.cc29
-rw-r--r--chromium/content/renderer/render_frame_impl.cc882
-rw-r--r--chromium/content/renderer/render_frame_impl.h371
-rw-r--r--chromium/content/renderer/render_process_impl.cc11
-rw-r--r--chromium/content/renderer/render_thread_impl.cc272
-rw-r--r--chromium/content/renderer/render_thread_impl.h75
-rw-r--r--chromium/content/renderer/render_view_browsertest.cc358
-rw-r--r--chromium/content/renderer/render_view_browsertest_mac.mm85
-rw-r--r--chromium/content/renderer/render_view_impl.cc1521
-rw-r--r--chromium/content/renderer/render_view_impl.h747
-rw-r--r--chromium/content/renderer/render_view_impl_android.cc9
-rw-r--r--chromium/content/renderer/render_view_impl_params.cc4
-rw-r--r--chromium/content/renderer/render_view_impl_params.h10
-rw-r--r--chromium/content/renderer/render_view_linux.cc2
-rw-r--r--chromium/content/renderer/render_view_mouse_lock_dispatcher.cc2
-rw-r--r--chromium/content/renderer/render_widget.cc835
-rw-r--r--chromium/content/renderer/render_widget.h239
-rw-r--r--chromium/content/renderer/render_widget_fullscreen.cc8
-rw-r--r--chromium/content/renderer/render_widget_fullscreen.h6
-rw-r--r--chromium/content/renderer/render_widget_fullscreen_pepper.cc63
-rw-r--r--chromium/content/renderer/render_widget_fullscreen_pepper.h19
-rw-r--r--chromium/content/renderer/render_widget_unittest.cc146
-rw-r--r--chromium/content/renderer/renderer_clipboard_client.cc56
-rw-r--r--chromium/content/renderer/renderer_clipboard_client.h34
-rw-r--r--chromium/content/renderer/renderer_date_time_picker.cc82
-rw-r--r--chromium/content/renderer/renderer_date_time_picker.h14
-rw-r--r--chromium/content/renderer/renderer_main.cc3
-rw-r--r--chromium/content/renderer/renderer_main_platform_delegate_linux.cc4
-rw-r--r--chromium/content/renderer/renderer_main_platform_delegate_mac.mm8
-rw-r--r--chromium/content/renderer/renderer_main_platform_delegate_win.cc5
-rw-r--r--chromium/content/renderer/renderer_webapplicationcachehost_impl.cc8
-rw-r--r--chromium/content/renderer/renderer_webapplicationcachehost_impl.h2
-rw-r--r--chromium/content/renderer/renderer_webcolorchooser_impl.cc16
-rw-r--r--chromium/content/renderer/renderer_webcolorchooser_impl.h18
-rw-r--r--chromium/content/renderer/renderer_webcookiejar_impl.cc24
-rw-r--r--chromium/content/renderer/renderer_webcookiejar_impl.h24
-rw-r--r--chromium/content/renderer/renderer_webkitplatformsupport_impl.cc291
-rw-r--r--chromium/content/renderer/renderer_webkitplatformsupport_impl.h150
-rw-r--r--chromium/content/renderer/resizing_mode_selector.cc38
-rw-r--r--chromium/content/renderer/resizing_mode_selector.h43
-rw-r--r--chromium/content/renderer/resource_fetcher_browsertest.cc32
-rw-r--r--chromium/content/renderer/resources/media/mediaplayer_remote_playback.pngbin0 -> 7568 bytes
-rw-r--r--chromium/content/renderer/sad_plugin.cc2
-rw-r--r--chromium/content/renderer/sad_plugin.h2
-rw-r--r--chromium/content/renderer/savable_resources.cc22
-rw-r--r--chromium/content/renderer/savable_resources.h12
-rw-r--r--chromium/content/renderer/savable_resources_browsertest.cc2
-rw-r--r--chromium/content/renderer/scoped_clipboard_writer_glue.cc4
-rw-r--r--chromium/content/renderer/service_worker/OWNERS3
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc94
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_dispatcher.h49
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.cc98
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.h63
-rw-r--r--chromium/content/renderer/shared_worker_repository.cc58
-rw-r--r--chromium/content/renderer/shared_worker_repository.h39
-rw-r--r--chromium/content/renderer/skia_benchmarking_extension.cc100
-rw-r--r--chromium/content/renderer/speech_recognition_dispatcher.cc14
-rw-r--r--chromium/content/renderer/speech_recognition_dispatcher.h28
-rw-r--r--chromium/content/renderer/stats_collection_controller.cc127
-rw-r--r--chromium/content/renderer/stats_collection_controller.h34
-rw-r--r--chromium/content/renderer/stats_collection_observer.cc4
-rw-r--r--chromium/content/renderer/stats_collection_observer.h8
-rw-r--r--chromium/content/renderer/text_input_client_observer.cc17
-rw-r--r--chromium/content/renderer/text_input_client_observer.h4
-rw-r--r--chromium/content/renderer/v8_value_converter_impl.cc93
-rw-r--r--chromium/content/renderer/v8_value_converter_impl.h16
-rw-r--r--chromium/content/renderer/v8_value_converter_impl_unittest.cc151
-rw-r--r--chromium/content/renderer/web_preferences.cc54
-rw-r--r--chromium/content/renderer/web_ui_extension.cc31
-rw-r--r--chromium/content/renderer/webclipboard_impl.cc111
-rw-r--r--chromium/content/renderer/webclipboard_impl.h39
-rw-r--r--chromium/content/renderer/webcrypto/OWNERS2
-rw-r--r--chromium/content/renderer/webcrypto/webcrypto_impl.cc631
-rw-r--r--chromium/content/renderer/webcrypto/webcrypto_impl.h153
-rw-r--r--chromium/content/renderer/webcrypto/webcrypto_impl_nss.cc1013
-rw-r--r--chromium/content/renderer/webcrypto/webcrypto_impl_openssl.cc539
-rw-r--r--chromium/content/renderer/webcrypto/webcrypto_impl_unittest.cc1641
-rw-r--r--chromium/content/renderer/webcrypto/webcrypto_util.cc205
-rw-r--r--chromium/content/renderer/webcrypto/webcrypto_util.h107
-rw-r--r--chromium/content/renderer/webcrypto_impl.cc74
-rw-r--r--chromium/content/renderer/webcrypto_impl.h74
-rw-r--r--chromium/content/renderer/webcrypto_impl_nss.cc252
-rw-r--r--chromium/content/renderer/webcrypto_impl_openssl.cc46
-rw-r--r--chromium/content/renderer/webcrypto_impl_unittest.cc277
-rw-r--r--chromium/content/renderer/webpublicsuffixlist_impl.cc23
-rw-r--r--chromium/content/renderer/webpublicsuffixlist_impl.h22
-rw-r--r--chromium/content/renderer/websharedworker_proxy.cc34
-rw-r--r--chromium/content/renderer/websharedworker_proxy.h31
-rw-r--r--chromium/content/renderer/websharedworkerrepository_impl.cc35
-rw-r--r--chromium/content/renderer/websharedworkerrepository_impl.h37
-rw-r--r--chromium/content/shell/DEPS8
-rw-r--r--chromium/content/shell/OWNERS1
-rw-r--r--chromium/content/shell/android/browsertests_apk/AndroidManifest.xml2
-rw-r--r--chromium/content/shell/android/browsertests_apk/content_browser_tests_android.cc2
-rw-r--r--chromium/content/shell/android/linker_test_apk/AndroidManifest.xml109
-rw-r--r--chromium/content/shell/android/linker_test_apk/content_linker_test_android.cc36
-rw-r--r--chromium/content/shell/android/linker_test_apk/content_linker_test_linker_tests.cc185
-rw-r--r--chromium/content/shell/android/linker_test_apk/content_linker_test_linker_tests.h16
-rw-r--r--chromium/content/shell/android/linker_test_apk/res/layout/test_activity.xml16
-rw-r--r--chromium/content/shell/android/shell_apk/AndroidManifest.xml2
-rw-r--r--chromium/content/shell/android/shell_descriptors.h5
-rw-r--r--chromium/content/shell/android/shell_manager.h6
-rw-r--r--chromium/content/shell/app/framework-Info.plist18
-rw-r--r--chromium/content/shell/app/shell.rc2
-rw-r--r--chromium/content/shell/app/shell_breakpad_client.cc72
-rw-r--r--chromium/content/shell/app/shell_breakpad_client.h55
-rw-r--r--chromium/content/shell/app/shell_main_delegate.cc68
-rw-r--r--chromium/content/shell/app/shell_main_delegate.h3
-rw-r--r--chromium/content/shell/browser/minimal_shell.cc54
-rw-r--r--chromium/content/shell/browser/minimal_shell.h67
-rw-r--r--chromium/content/shell/browser/shell.cc68
-rw-r--r--chromium/content/shell/browser/shell.h66
-rw-r--r--chromium/content/shell/browser/shell_android.cc7
-rw-r--r--chromium/content/shell/browser/shell_aura.cc426
-rw-r--r--chromium/content/shell/browser/shell_aura.h48
-rw-r--r--chromium/content/shell/browser/shell_browser_context.cc10
-rw-r--r--chromium/content/shell/browser/shell_browser_context.h6
-rw-r--r--chromium/content/shell/browser/shell_browser_main.cc4
-rw-r--r--chromium/content/shell/browser/shell_browser_main_parts.cc22
-rw-r--r--chromium/content/shell/browser/shell_browser_main_parts.h9
-rw-r--r--chromium/content/shell/browser/shell_content_browser_client.cc133
-rw-r--r--chromium/content/shell/browser/shell_content_browser_client.h14
-rw-r--r--chromium/content/shell/browser/shell_devtools_delegate.cc125
-rw-r--r--chromium/content/shell/browser/shell_devtools_delegate.h5
-rw-r--r--chromium/content/shell/browser/shell_devtools_frontend.cc21
-rw-r--r--chromium/content/shell/browser/shell_devtools_frontend.h4
-rw-r--r--chromium/content/shell/browser/shell_download_manager_delegate.cc4
-rw-r--r--chromium/content/shell/browser/shell_gtk.cc37
-rw-r--r--chromium/content/shell/browser/shell_javascript_dialog.h8
-rw-r--r--chromium/content/shell/browser/shell_javascript_dialog_gtk.cc10
-rw-r--r--chromium/content/shell/browser/shell_javascript_dialog_mac.mm6
-rw-r--r--chromium/content/shell/browser/shell_javascript_dialog_manager.cc24
-rw-r--r--chromium/content/shell/browser/shell_javascript_dialog_manager.h6
-rw-r--r--chromium/content/shell/browser/shell_javascript_dialog_win.cc8
-rw-r--r--chromium/content/shell/browser/shell_login_dialog.cc20
-rw-r--r--chromium/content/shell/browser/shell_login_dialog.h11
-rw-r--r--chromium/content/shell/browser/shell_login_dialog_gtk.cc2
-rw-r--r--chromium/content/shell/browser/shell_login_dialog_mac.mm2
-rw-r--r--chromium/content/shell/browser/shell_mac.mm14
-rw-r--r--chromium/content/shell/browser/shell_network_delegate.cc2
-rw-r--r--chromium/content/shell/browser/shell_network_delegate.h2
-rw-r--r--chromium/content/shell/browser/shell_plugin_service_filter.cc2
-rw-r--r--chromium/content/shell/browser/shell_plugin_service_filter.h2
-rw-r--r--chromium/content/shell/browser/shell_url_request_context_getter.cc2
-rw-r--r--chromium/content/shell/browser/shell_views.cc398
-rw-r--r--chromium/content/shell/browser/shell_web_contents_view_delegate_gtk.cc2
-rw-r--r--chromium/content/shell/browser/shell_web_contents_view_delegate_mac.mm2
-rw-r--r--chromium/content/shell/browser/shell_web_contents_view_delegate_win.cc2
-rw-r--r--chromium/content/shell/browser/shell_win.cc10
-rw-r--r--chromium/content/shell/browser/webkit_test_controller.cc28
-rw-r--r--chromium/content/shell/browser/webkit_test_controller.h3
-rw-r--r--chromium/content/shell/common/shell_content_client.cc2
-rw-r--r--chromium/content/shell/common/shell_content_client.h2
-rw-r--r--chromium/content/shell/common/shell_switches.cc6
-rw-r--r--chromium/content/shell/common/shell_switches.h2
-rw-r--r--chromium/content/shell/common/webkit_test_helpers.cc8
-rw-r--r--chromium/content/shell/geolocation/shell_access_token_store.cc2
-rw-r--r--chromium/content/shell/geolocation/shell_access_token_store.h2
-rw-r--r--chromium/content/shell/renderer/shell_content_renderer_client.cc36
-rw-r--r--chromium/content/shell/renderer/shell_content_renderer_client.h34
-rw-r--r--chromium/content/shell/renderer/shell_render_process_observer.cc8
-rw-r--r--chromium/content/shell/renderer/shell_render_process_observer.h3
-rw-r--r--chromium/content/shell/renderer/shell_render_view_observer.cc4
-rw-r--r--chromium/content/shell/renderer/shell_render_view_observer.h4
-rw-r--r--chromium/content/shell/renderer/webkit_test_runner.cc75
-rw-r--r--chromium/content/shell/renderer/webkit_test_runner.h38
-rw-r--r--chromium/content/shell/resources/missingImage.pngbin411 -> 372 bytes
-rw-r--r--chromium/content/shell/resources/textAreaResizeCorner.pngbin195 -> 92 bytes
-rw-r--r--chromium/content/shell/tools/DEPS4
-rw-r--r--chromium/content/shell/tools/content_shell_crash_service.cc42
-rw-r--r--chromium/content/utility/utility_main.cc47
-rw-r--r--chromium/content/utility/utility_thread_impl.cc23
-rw-r--r--chromium/content/worker/shared_worker_devtools_agent.cc8
-rw-r--r--chromium/content/worker/shared_worker_devtools_agent.h10
-rw-r--r--chromium/content/worker/shared_worker_permission_client_proxy.cc60
-rw-r--r--chromium/content/worker/shared_worker_permission_client_proxy.h47
-rw-r--r--chromium/content/worker/websharedworker_stub.cc17
-rw-r--r--chromium/content/worker/websharedworker_stub.h18
-rw-r--r--chromium/content/worker/websharedworkerclient_proxy.cc112
-rw-r--r--chromium/content/worker/websharedworkerclient_proxy.h56
-rw-r--r--chromium/content/worker/worker_main.cc3
-rw-r--r--chromium/content/worker/worker_thread.cc44
-rw-r--r--chromium/content/worker/worker_thread.h4
-rw-r--r--chromium/content/worker/worker_webapplicationcachehost_impl.cc8
-rw-r--r--chromium/content/worker/worker_webapplicationcachehost_impl.h8
-rw-r--r--chromium/content/worker/worker_webkitplatformsupport_impl.cc62
-rw-r--r--chromium/content/worker/worker_webkitplatformsupport_impl.h113
-rw-r--r--chromium/content/zygote/zygote_linux.cc30
-rw-r--r--chromium/content/zygote/zygote_linux.h3
-rw-r--r--chromium/content/zygote/zygote_main_linux.cc99
2160 files changed, 101647 insertions, 61618 deletions
diff --git a/chromium/content/DEPS b/chromium/content/DEPS
index dd0a7d6b036..9f3434a0b58 100644
--- a/chromium/content/DEPS
+++ b/chromium/content/DEPS
@@ -18,7 +18,6 @@ include_rules = [
"+cc",
# If you want to use any of these files, move them to src/base first.
- "-cc/base/hash_pair.h",
"-cc/base/scoped_ptr_algorithm.h",
"-cc/base/scoped_ptr_deque.h",
"-cc/base/scoped_ptr_vector.h",
@@ -58,9 +57,8 @@ include_rules = [
"-tools",
# Allow inclusion of third-party code:
- "+third_party/angle_dx11",
+ "+third_party/angle",
"+third_party/flac",
- "+third_party/gpsd",
"+third_party/libjingle",
"+third_party/mozilla",
"+third_party/npapi/bindings",
diff --git a/chromium/content/OWNERS b/chromium/content/OWNERS
index e6de2ac7d5a..00ed6cf10b9 100644
--- a/chromium/content/OWNERS
+++ b/chromium/content/OWNERS
@@ -3,6 +3,7 @@ brettw@chromium.org
creis@chromium.org
darin@chromium.org
jam@chromium.org
+jochen@chromium.org
piman@chromium.org
# Mac Sandbox profiles.
@@ -11,11 +12,7 @@ per-file *.sb=jeremy@chromium.org
per-file *.isolate=csharp@chromium.org
per-file *.isolate=maruel@chromium.org
-per-file content_gpu.gypi=apatrick@chromium.org
per-file content_gpu.gypi=kbr@chromium.org
per-file content_jni.gypi=bulach@chromium.org
per-file content_jni.gypi=yfriedman@chromium.org
per-file content_renderer.gypi=jamesr@chromium.org
-per-file content_renderer.gypi=jochen@chromium.org
-per-file content_shell.gypi=jochen@chromium.org
-per-file content_tests.gypi=jochen@chromium.org
diff --git a/chromium/content/app/android/child_process_service.cc b/chromium/content/app/android/child_process_service.cc
index 4d5de1d5589..308246ef96c 100644
--- a/chromium/content/app/android/child_process_service.cc
+++ b/chromium/content/app/android/child_process_service.cc
@@ -126,7 +126,7 @@ void InitChildProcess(JNIEnv* env,
}
void ExitChildProcess(JNIEnv* env, jclass clazz) {
- LOG(INFO) << "ChildProcessService: Exiting child process.";
+ VLOG(0) << "ChildProcessService: Exiting child process.";
LibraryLoaderExitHook();
_exit(0);
}
diff --git a/chromium/content/app/android/content_main.cc b/chromium/content/app/android/content_main.cc
index bfc372f71f3..00074b88340 100644
--- a/chromium/content/app/android/content_main.cc
+++ b/chromium/content/app/android/content_main.cc
@@ -32,7 +32,7 @@ namespace content {
static void InitApplicationContext(JNIEnv* env, jclass clazz, jobject context) {
base::android::ScopedJavaLocalRef<jobject> scoped_context(env, context);
- base::android::InitApplicationContext(scoped_context);
+ base::android::InitApplicationContext(env, scoped_context);
}
static jint Start(JNIEnv* env, jclass clazz) {
diff --git a/chromium/content/app/android/library_loader_hooks.cc b/chromium/content/app/android/library_loader_hooks.cc
index 725491d67fe..b412c3abfee 100644
--- a/chromium/content/app/android/library_loader_hooks.cc
+++ b/chromium/content/app/android/library_loader_hooks.cc
@@ -5,6 +5,7 @@
#include "content/public/app/android_library_loader_hooks.h"
#include "base/android/base_jni_registrar.h"
+#include "base/android/command_line_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_registrar.h"
#include "base/android/jni_string.h"
@@ -14,31 +15,76 @@
#include "base/debug/trace_event.h"
#include "base/files/file_path.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
#include "base/tracked_objects.h"
#include "content/app/android/app_jni_registrar.h"
#include "content/browser/android/browser_jni_registrar.h"
#include "content/child/android/child_jni_registrar.h"
-#include "content/common/android/command_line.h"
#include "content/common/android/common_jni_registrar.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "jni/LibraryLoader_jni.h"
#include "media/base/android/media_jni_registrar.h"
#include "net/android/net_jni_registrar.h"
-#include "ui/android/ui_jni_registrar.h"
+#include "ui/base/android/ui_base_jni_registrar.h"
+#include "ui/gfx/android/gfx_jni_registrar.h"
#include "ui/gl/android/gl_jni_registrar.h"
#include "ui/shell_dialogs/android/shell_dialogs_jni_registrar.h"
+namespace content {
+
namespace {
base::AtExitManager* g_at_exit_manager = NULL;
+const char* g_library_version_number = "";
}
-namespace content {
+bool EnsureJniRegistered(JNIEnv* env) {
+ static bool g_jni_init_done = false;
+
+ if (!g_jni_init_done) {
+ if (!base::android::RegisterJni(env))
+ return false;
+
+ if (!gfx::android::RegisterJni(env))
+ return false;
+
+ if (!net::android::RegisterJni(env))
+ return false;
+
+ if (!ui::android::RegisterJni(env))
+ return false;
+
+ if (!ui::gl::android::RegisterJni(env))
+ return false;
+
+ if (!ui::shell_dialogs::RegisterJni(env))
+ return false;
+
+ if (!content::android::RegisterChildJni(env))
+ return false;
+
+ if (!content::android::RegisterCommonJni(env))
+ return false;
+
+ if (!content::android::RegisterBrowserJni(env))
+ return false;
+
+ if (!content::android::RegisterAppJni(env))
+ return false;
+
+ if (!media::RegisterJni(env))
+ return false;
+
+ g_jni_init_done = true;
+ }
+
+ return true;
+}
static jint LibraryLoaded(JNIEnv* env, jclass clazz,
jobjectArray init_command_line) {
- InitNativeCommandLineFromJavaArray(env, init_command_line);
+ base::android::InitNativeCommandLineFromJavaArray(env, init_command_line);
CommandLine* command_line = CommandLine::ForCurrentProcess();
@@ -70,39 +116,23 @@ static jint LibraryLoaded(JNIEnv* env, jclass clazz,
VLOG(0) << "Chromium logging enabled: level = " << logging::GetMinLogLevel()
<< ", default verbosity = " << logging::GetVlogVerbosity();
- if (!base::android::RegisterJni(env))
- return RESULT_CODE_FAILED_TO_REGISTER_JNI;
-
- if (!net::android::RegisterJni(env))
- return RESULT_CODE_FAILED_TO_REGISTER_JNI;
-
- if (!ui::android::RegisterJni(env))
- return RESULT_CODE_FAILED_TO_REGISTER_JNI;
-
- if (!ui::gl::android::RegisterJni(env))
- return RESULT_CODE_FAILED_TO_REGISTER_JNI;
-
- if (!ui::shell_dialogs::RegisterJni(env))
- return RESULT_CODE_FAILED_TO_REGISTER_JNI;
-
- if (!content::android::RegisterChildJni(env))
- return RESULT_CODE_FAILED_TO_REGISTER_JNI;
-
- if (!content::android::RegisterCommonJni(env))
- return RESULT_CODE_FAILED_TO_REGISTER_JNI;
-
- if (!content::android::RegisterBrowserJni(env))
- return RESULT_CODE_FAILED_TO_REGISTER_JNI;
-
- if (!content::android::RegisterAppJni(env))
- return RESULT_CODE_FAILED_TO_REGISTER_JNI;
-
- if (!media::RegisterJni(env))
+ if (!EnsureJniRegistered(env))
return RESULT_CODE_FAILED_TO_REGISTER_JNI;
return 0;
}
+static void RecordContentAndroidLinkerHistogram(
+ JNIEnv* env,
+ jclass clazz,
+ jboolean loaded_at_fixed_address_failed,
+ jboolean is_low_memory_device) {
+ UMA_HISTOGRAM_BOOLEAN("ContentAndroidLinker.LoadedAtFixedAddressFailed",
+ loaded_at_fixed_address_failed);
+ UMA_HISTOGRAM_BOOLEAN("ContentAndroidLinker.IsLowMemoryDevice",
+ is_low_memory_device);
+}
+
void LibraryLoaderExitHook() {
if (g_at_exit_manager) {
delete g_at_exit_manager;
@@ -117,4 +147,12 @@ bool RegisterLibraryLoaderEntryHook(JNIEnv* env) {
return RegisterNativesImpl(env);
}
+void SetVersionNumber(const char* version_number) {
+ g_library_version_number = strdup(version_number);
+}
+
+jstring GetVersionNumber(JNIEnv* env, jclass clazz) {
+ return env->NewStringUTF(g_library_version_number);
+}
+
} // namespace content
diff --git a/chromium/content/app/content_main_runner.cc b/chromium/content/app/content_main_runner.cc
index da27afaaf01..776417d58f9 100644
--- a/chromium/content/app/content_main_runner.cc
+++ b/chromium/content/app/content_main_runner.cc
@@ -133,13 +133,15 @@ void EnableThemeSupportOnAllWindowStations() {
HWINSTA winsta0 = ::OpenWindowStationA("WinSta0", FALSE, GENERIC_READ);
if (!winsta0) {
- DLOG(INFO) << "Unable to open to WinSta0, we: "<< ::GetLastError();
+ DVLOG(0) << "Unable to open to WinSta0, we: "<< ::GetLastError();
return;
}
if (!::SetProcessWindowStation(winsta0)) {
// Could not set the alternate window station. There is a possibility
// that the theme wont be correctly initialized.
NOTREACHED() << "Unable to switch to WinSta0, we: "<< ::GetLastError();
+ ::CloseWindowStation(winsta0);
+ return;
}
HWND window = ::CreateWindowExW(0, L"Static", L"", WS_POPUP | WS_DISABLED,
@@ -406,6 +408,27 @@ int RunZygote(const MainFunctionParams& main_function_params,
#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
#if !defined(OS_IOS)
+static void RegisterMainThreadFactories() {
+#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
+ UtilityProcessHost::RegisterUtilityMainThreadFactory(
+ CreateInProcessUtilityThread);
+ RenderProcessHost::RegisterRendererMainThreadFactory(
+ CreateInProcessRendererThread);
+ GpuProcessHost::RegisterGpuMainThreadFactory(
+ CreateInProcessGpuThread);
+#else
+ CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kSingleProcess)) {
+ LOG(FATAL) <<
+ "--single-process is not supported in chrome multiple dll browser.";
+ }
+ if (command_line.HasSwitch(switches::kInProcessGPU)) {
+ LOG(FATAL) <<
+ "--in-process-gpu is not supported in chrome multiple dll browser.";
+ }
+#endif
+}
+
// Run the FooMain() for a given process type.
// If |process_type| is empty, runs BrowserMain().
// Returns the exit code for this process.
@@ -430,14 +453,7 @@ int RunNamedProcessTypeMain(
#endif // !CHROME_MULTIPLE_DLL_BROWSER
};
-#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
- UtilityProcessHost::RegisterUtilityMainThreadFactory(
- CreateInProcessUtilityThread);
- RenderProcessHost::RegisterRendererMainThreadFactory(
- CreateInProcessRendererThread);
- GpuProcessHost::RegisterGpuMainThreadFactory(
- CreateInProcessGpuThread);
-#endif
+ RegisterMainThreadFactories();
for (size_t i = 0; i < arraysize(kMainFunctions); ++i) {
if (process_type == kMainFunctions[i].name) {
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index 2a42e40f7e3..6e6295235ac 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -5,6 +5,7 @@ include_rules = [
"+media/audio", # For audio input for speech input feature.
"+media/base", # For Android JNI registration.
"+media/midi", # For Web MIDI API
+ "+media/video", # For Video Device monitoring in Mac.
"+sql",
"+ui/webui",
"+win8/util",
@@ -31,19 +32,19 @@ include_rules = [
# No inclusion of WebKit from the browser, other than strictly enum/POD,
# header-only types, and some selected common code.
"-third_party/WebKit",
+ "+third_party/WebKit/public/platform/WebCursorInfo.h",
"+third_party/WebKit/public/platform/WebGamepads.h",
"+third_party/WebKit/public/platform/WebGraphicsContext3D.h",
- "+third_party/WebKit/public/platform/WebIDBCallbacks.h",
"+third_party/WebKit/public/platform/WebIDBDatabaseException.h",
"+third_party/WebKit/public/platform/WebIDBTypes.h",
"+third_party/WebKit/public/platform/WebReferrerPolicy.h",
"+third_party/WebKit/public/platform/WebScreenInfo.h",
+ "+third_party/WebKit/public/platform/WebServiceWorkerError.h",
"+third_party/WebKit/public/platform/WebString.h",
"+third_party/WebKit/public/platform/WebVibration.h",
"+third_party/WebKit/public/web/WebAXEnums.h",
"+third_party/WebKit/public/web/WebCompositionUnderline.h",
"+third_party/WebKit/public/web/WebConsoleMessage.h",
- "+third_party/WebKit/public/web/WebCursorInfo.h",
"+third_party/WebKit/public/web/WebDragOperation.h",
"+third_party/WebKit/public/web/WebDragStatus.h",
"+third_party/WebKit/public/web/WebFindOptions.h",
@@ -53,12 +54,14 @@ include_rules = [
"+third_party/WebKit/public/web/WebPageSerializerClient.h",
"+third_party/WebKit/public/web/WebPluginAction.h",
"+third_party/WebKit/public/web/WebPopupType.h",
- "+third_party/WebKit/public/web/WebScreenInfo.h",
+ "+third_party/WebKit/public/web/WebSerializedScriptValueVersion.h",
"+third_party/WebKit/public/web/WebTextDirection.h",
# These should be burned down. http://crbug.com/237267
"!third_party/WebKit/public/web/mac/WebInputEventFactory.h",
+ "+ui/ozone/ozone_switches.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.
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
index 4368cf13217..af33a42a7c3 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
@@ -55,7 +55,7 @@ AccessibilityTreeFormatter::BuildAccessibilityTree() {
}
void AccessibilityTreeFormatter::FormatAccessibilityTree(
- string16* contents) {
+ base::string16* contents) {
scoped_ptr<base::DictionaryValue> dict = BuildAccessibilityTree();
RecursiveFormatAccessibilityTree(*(dict.get()), contents);
}
@@ -66,10 +66,8 @@ void AccessibilityTreeFormatter::RecursiveBuildAccessibilityTree(
base::ListValue* children = new base::ListValue;
dict->Set(kChildrenDictAttr, children);
- if (!IncludeChildren(node))
- return;
- for (size_t i = 0; i < node.children().size(); ++i) {
+ for (size_t i = 0; i < node.PlatformChildCount(); ++i) {
BrowserAccessibility* child_node = node.children()[i];
base::DictionaryValue* child_dict = new base::DictionaryValue;
children->Append(child_dict);
@@ -78,9 +76,10 @@ void AccessibilityTreeFormatter::RecursiveBuildAccessibilityTree(
}
void AccessibilityTreeFormatter::RecursiveFormatAccessibilityTree(
- const base::DictionaryValue& dict, string16* contents, int depth) {
- string16 line = ToString(dict, string16(depth * kIndentSpaces, ' '));
- if (line.find(ASCIIToUTF16(kSkipString)) != string16::npos)
+ const base::DictionaryValue& dict, base::string16* contents, int depth) {
+ base::string16 line =
+ ToString(dict, base::string16(depth * kIndentSpaces, ' '));
+ if (line.find(ASCIIToUTF16(kSkipString)) != base::string16::npos)
return;
*contents += line;
@@ -93,13 +92,6 @@ void AccessibilityTreeFormatter::RecursiveFormatAccessibilityTree(
}
}
-#if !defined(OS_ANDROID)
-bool AccessibilityTreeFormatter::IncludeChildren(
- const BrowserAccessibility& node) {
- return true;
-}
-#endif
-
#if (!defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
!defined(TOOLKIT_GTK))
void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node,
@@ -107,8 +99,9 @@ void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node,
dict->SetInteger("id", node.renderer_id());
}
-string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& node,
- const string16& indent) {
+base::string16 AccessibilityTreeFormatter::ToString(
+ const base::DictionaryValue& node,
+ const base::string16& indent) {
int id_value;
node.GetInteger("id", &id_value);
return indent + base::IntToString16(id_value) +
@@ -151,7 +144,7 @@ void AccessibilityTreeFormatter::SetFilters(
}
bool AccessibilityTreeFormatter::MatchesFilters(
- const string16& text, bool default_result) const {
+ const base::string16& text, bool default_result) const {
std::vector<Filter>::const_iterator iter = filters_.begin();
bool allow = default_result;
for (iter = filters_.begin(); iter != filters_.end(); ++iter) {
@@ -167,7 +160,7 @@ bool AccessibilityTreeFormatter::MatchesFilters(
return allow;
}
-string16 AccessibilityTreeFormatter::FormatCoordinates(
+base::string16 AccessibilityTreeFormatter::FormatCoordinates(
const char* name, const char* x_name, const char* y_name,
const base::DictionaryValue& value) {
int x, y;
@@ -179,12 +172,12 @@ string16 AccessibilityTreeFormatter::FormatCoordinates(
}
void AccessibilityTreeFormatter::WriteAttribute(
- bool include_by_default, const std::string& attr, string16* line) {
+ bool include_by_default, const std::string& attr, base::string16* line) {
WriteAttribute(include_by_default, UTF8ToUTF16(attr), line);
}
void AccessibilityTreeFormatter::WriteAttribute(
- bool include_by_default, const string16& attr, string16* line) {
+ bool include_by_default, const base::string16& attr, base::string16* line) {
if (attr.empty())
return;
if (!MatchesFilters(attr, include_by_default))
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter.h b/chromium/content/browser/accessibility/accessibility_tree_formatter.h
index 3c36b2f6e52..a290886aad9 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter.h
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter.h
@@ -52,7 +52,7 @@ class CONTENT_EXPORT AccessibilityTreeFormatter {
scoped_ptr<base::DictionaryValue> BuildAccessibilityTree();
// Dumps a BrowserAccessibility tree into a string.
- void FormatAccessibilityTree(string16* contents);
+ void FormatAccessibilityTree(base::string16* contents);
// A single filter specification. See GetAllowString() and GetDenyString()
// for more information.
@@ -62,10 +62,10 @@ class CONTENT_EXPORT AccessibilityTreeFormatter {
ALLOW_EMPTY,
DENY
};
- string16 match_str;
+ base::string16 match_str;
Type type;
- Filter(string16 match_str, Type type)
+ Filter(base::string16 match_str, Type type)
: match_str(match_str), type(type) {}
};
@@ -100,12 +100,12 @@ class CONTENT_EXPORT AccessibilityTreeFormatter {
protected:
void RecursiveFormatAccessibilityTree(const BrowserAccessibility& node,
- string16* contents,
+ base::string16* contents,
int indent);
void RecursiveBuildAccessibilityTree(const BrowserAccessibility& node,
base::DictionaryValue* tree_node);
void RecursiveFormatAccessibilityTree(const base::DictionaryValue& tree_node,
- string16* contents,
+ base::string16* contents,
int depth = 0);
// Overridden by each platform to add the required attributes for each node
@@ -113,32 +113,28 @@ class CONTENT_EXPORT AccessibilityTreeFormatter {
void AddProperties(const BrowserAccessibility& node,
base::DictionaryValue* dict);
- // Returns true by default; can be overridden by the platform to
- // prune some children from the tree when they wouldn't be exposed
- // natively on that platform.
- virtual bool IncludeChildren(const BrowserAccessibility& node);
-
- string16 FormatCoordinates(const char* name,
- const char* x_name,
- const char* y_name,
- const base::DictionaryValue& value);
+ base::string16 FormatCoordinates(const char* name,
+ const char* x_name,
+ const char* y_name,
+ const base::DictionaryValue& value);
// Returns a platform specific representation of a BrowserAccessibility.
// Should be zero or more complete lines, each with |prefix| prepended
// (to indent each line).
- string16 ToString(const base::DictionaryValue& node, const string16& indent);
+ base::string16 ToString(const base::DictionaryValue& node,
+ const base::string16& indent);
void Initialize();
- bool MatchesFilters(const string16& text, bool default_result) const;
+ bool MatchesFilters(const base::string16& text, bool default_result) const;
// Writes the given attribute string out to |line| if it matches the filters.
void WriteAttribute(bool include_by_default,
- const string16& attr,
- string16* line);
+ const base::string16& attr,
+ base::string16* line);
void WriteAttribute(bool include_by_default,
const std::string& attr,
- string16* line);
+ base::string16* line);
BrowserAccessibility* root_;
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
index 11f4be64627..8c625a3eae2 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
@@ -25,12 +25,20 @@ const char* BOOL_ATTRIBUTES[] = {
"checkable",
"checked",
"clickable",
+ "collection",
+ "collection_item",
+ "content_invalid",
"disabled",
+ "dismissable",
"editable_text",
"focusable",
"focused",
+ "heading",
+ "hierarchical",
"invisible",
+ "multiline",
"password",
+ "range",
"scrollable",
"selected"
};
@@ -41,7 +49,18 @@ const char* STRING_ATTRIBUTES[] = {
const char* INT_ATTRIBUTES[] = {
"item_index",
- "item_count"
+ "item_count",
+ "row_count",
+ "column_count",
+ "row_index",
+ "row_span",
+ "column_index",
+ "column_span",
+ "input_type",
+ "live_region_type",
+ "range_min",
+ "range_max",
+ "range_current_value",
};
}
@@ -57,17 +76,24 @@ void AccessibilityTreeFormatter::AddProperties(
dict->SetString("class", android_node->GetClassName());
// Bool attributes.
- dict->SetBoolean("focusable", android_node->IsFocusable());
- dict->SetBoolean("focused", android_node->IsFocused());
- dict->SetBoolean("clickable", android_node->IsClickable());
- dict->SetBoolean("editable_text", android_node->IsEditableText());
dict->SetBoolean("checkable", android_node->IsCheckable());
dict->SetBoolean("checked", android_node->IsChecked());
+ dict->SetBoolean("clickable", android_node->IsClickable());
+ dict->SetBoolean("collection", android_node->IsCollection());
+ dict->SetBoolean("collection_item", android_node->IsCollectionItem());
dict->SetBoolean("disabled", !android_node->IsEnabled());
- dict->SetBoolean("scrollable", android_node->IsScrollable());
+ dict->SetBoolean("dismissable", android_node->IsDismissable());
+ dict->SetBoolean("editable_text", android_node->IsEditableText());
+ dict->SetBoolean("focusable", android_node->IsFocusable());
+ dict->SetBoolean("focused", android_node->IsFocused());
+ dict->SetBoolean("heading", android_node->IsHeading());
+ dict->SetBoolean("hierarchical", android_node->IsHierarchical());
+ dict->SetBoolean("invisible", !android_node->IsVisibleToUser());
+ dict->SetBoolean("multiline", android_node->IsMultiLine());
+ dict->SetBoolean("range", android_node->IsRangeType());
dict->SetBoolean("password", android_node->IsPassword());
+ dict->SetBoolean("scrollable", android_node->IsScrollable());
dict->SetBoolean("selected", android_node->IsSelected());
- dict->SetBoolean("invisible", !android_node->IsVisibleToUser());
// String attributes.
dict->SetString("name", android_node->GetText());
@@ -75,20 +101,26 @@ void AccessibilityTreeFormatter::AddProperties(
// Int attributes.
dict->SetInteger("item_index", android_node->GetItemIndex());
dict->SetInteger("item_count", android_node->GetItemCount());
+ dict->SetInteger("row_count", android_node->RowCount());
+ dict->SetInteger("column_count", android_node->ColumnCount());
+ dict->SetInteger("row_index", android_node->RowIndex());
+ dict->SetInteger("row_span", android_node->RowSpan());
+ dict->SetInteger("column_index", android_node->ColumnIndex());
+ dict->SetInteger("column_span", android_node->ColumnSpan());
+ dict->SetInteger("input_type", android_node->AndroidInputType());
+ dict->SetInteger("live_region_type", android_node->AndroidLiveRegionType());
+ dict->SetInteger("range_min", static_cast<int>(android_node->RangeMin()));
+ dict->SetInteger("range_max", static_cast<int>(android_node->RangeMax()));
+ dict->SetInteger("range_current_value",
+ static_cast<int>(android_node->RangeCurrentValue()));
}
-bool AccessibilityTreeFormatter::IncludeChildren(
- const BrowserAccessibility& node) {
- const BrowserAccessibilityAndroid* android_node =
- static_cast<const BrowserAccessibilityAndroid*>(&node);
- return !android_node->IsLeaf();
-}
-
-string16 AccessibilityTreeFormatter::ToString(const DictionaryValue& dict,
- const string16& indent) {
- string16 line;
+base::string16 AccessibilityTreeFormatter::ToString(
+ const DictionaryValue& dict,
+ const base::string16& indent) {
+ base::string16 line;
- string16 class_value;
+ base::string16 class_value;
dict.GetString("class", &class_value);
WriteAttribute(true, UTF16ToUTF8(class_value), &line);
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_gtk.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_gtk.cc
index 8dd6b9328a7..0dc21ce1247 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_gtk.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_gtk.cc
@@ -37,9 +37,10 @@ void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node,
dict->SetInteger("id", node.renderer_id());
}
-string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& node,
- const string16& indent) {
- string16 line;
+base::string16 AccessibilityTreeFormatter::ToString(
+ const base::DictionaryValue& node,
+ const base::string16& indent) {
+ base::string16 line;
std::string role_value;
node.GetString("role", &role_value);
if (!role_value.empty())
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index 58881b4af4b..021b5fdc419 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -161,9 +161,10 @@ void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node,
dict->Set(kSizeDictAttr, PopulateSize(cocoa_node).release());
}
-string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& dict,
- const string16& indent) {
- string16 line;
+base::string16 AccessibilityTreeFormatter::ToString(
+ const base::DictionaryValue& dict,
+ const base::string16& indent) {
+ base::string16 line;
NSArray* defaultAttributes =
[NSArray arrayWithObjects:NSAccessibilityTitleAttribute,
NSAccessibilityValueAttribute,
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
index 053e39b9b09..e2cebc126c2 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
@@ -20,10 +20,10 @@ class AccessibilityRoleStateMap {
public:
static AccessibilityRoleStateMap* GetInstance();
- std::map<int32, string16> ia_role_string_map;
- std::map<int32, string16> ia2_role_string_map;
- std::map<int32, string16> ia_state_string_map;
- std::map<int32, string16> ia2_state_string_map;
+ std::map<int32, base::string16> ia_role_string_map;
+ std::map<int32, base::string16> ia2_role_string_map;
+ std::map<int32, base::string16> ia_state_string_map;
+ std::map<int32, base::string16> ia2_state_string_map;
private:
AccessibilityRoleStateMap();
@@ -220,44 +220,44 @@ AccessibilityRoleStateMap::AccessibilityRoleStateMap() {
} // namespace.
-string16 IAccessibleRoleToString(int32 ia_role) {
+base::string16 IAccessibleRoleToString(int32 ia_role) {
return AccessibilityRoleStateMap::GetInstance()->ia_role_string_map[ia_role];
}
-string16 IAccessible2RoleToString(int32 ia_role) {
+base::string16 IAccessible2RoleToString(int32 ia_role) {
return AccessibilityRoleStateMap::GetInstance()->ia2_role_string_map[ia_role];
}
void IAccessibleStateToStringVector(int32 ia_state,
- std::vector<string16>* result) {
- const std::map<int32, string16>& state_string_map =
+ std::vector<base::string16>* result) {
+ const std::map<int32, base::string16>& state_string_map =
AccessibilityRoleStateMap::GetInstance()->ia_state_string_map;
- std::map<int32, string16>::const_iterator it;
+ std::map<int32, base::string16>::const_iterator it;
for (it = state_string_map.begin(); it != state_string_map.end(); ++it) {
if (it->first & ia_state)
result->push_back(it->second);
}
}
-string16 IAccessibleStateToString(int32 ia_state) {
- std::vector<string16> strings;
+base::string16 IAccessibleStateToString(int32 ia_state) {
+ std::vector<base::string16> strings;
IAccessibleStateToStringVector(ia_state, &strings);
return JoinString(strings, ',');
}
void IAccessible2StateToStringVector(int32 ia2_state,
- std::vector<string16>* result) {
- const std::map<int32, string16>& state_string_map =
+ std::vector<base::string16>* result) {
+ const std::map<int32, base::string16>& state_string_map =
AccessibilityRoleStateMap::GetInstance()->ia2_state_string_map;
- std::map<int32, string16>::const_iterator it;
+ std::map<int32, base::string16>::const_iterator it;
for (it = state_string_map.begin(); it != state_string_map.end(); ++it) {
if (it->first & ia2_state)
result->push_back(it->second);
}
}
-string16 IAccessible2StateToString(int32 ia2_state) {
- std::vector<string16> strings;
+base::string16 IAccessible2StateToString(int32 ia2_state) {
+ std::vector<base::string16> strings;
IAccessible2StateToStringVector(ia2_state, &strings);
return JoinString(strings, ',');
}
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.h b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.h
index 1baf20d54a8..86b377a64ef 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.h
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.h
@@ -13,14 +13,14 @@
namespace content {
-CONTENT_EXPORT string16 IAccessibleRoleToString(int32 ia_role);
-CONTENT_EXPORT string16 IAccessible2RoleToString(int32 ia_role);
-CONTENT_EXPORT string16 IAccessibleStateToString(int32 ia_state);
+CONTENT_EXPORT base::string16 IAccessibleRoleToString(int32 ia_role);
+CONTENT_EXPORT base::string16 IAccessible2RoleToString(int32 ia_role);
+CONTENT_EXPORT base::string16 IAccessibleStateToString(int32 ia_state);
CONTENT_EXPORT void IAccessibleStateToStringVector(
- int32 ia_state, std::vector<string16>* result);
-CONTENT_EXPORT string16 IAccessible2StateToString(int32 ia2_state);
+ int32 ia_state, std::vector<base::string16>* result);
+CONTENT_EXPORT base::string16 IAccessible2StateToString(int32 ia2_state);
CONTENT_EXPORT void IAccessible2StateToStringVector(
- int32 ia_state, std::vector<string16>* result);
+ int32 ia_state, std::vector<base::string16>* result);
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
index 679843dc42e..c50b52630d9 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -76,7 +76,7 @@ void AccessibilityTreeFormatter::AddProperties(
if (hresult == S_OK)
dict->SetString("value", msaa_variant.m_str);
- std::vector<string16> state_strings;
+ std::vector<base::string16> state_strings;
int32 ia_state = acc_obj->ia_state();
// Avoid flakiness: these states depend on whether the window is focused
@@ -87,16 +87,16 @@ void AccessibilityTreeFormatter::AddProperties(
IAccessibleStateToStringVector(ia_state, &state_strings);
IAccessible2StateToStringVector(acc_obj->ia2_state(), &state_strings);
base::ListValue* states = new base::ListValue;
- for (std::vector<string16>::const_iterator it = state_strings.begin();
+ for (std::vector<base::string16>::const_iterator it = state_strings.begin();
it != state_strings.end();
++it) {
states->AppendString(UTF16ToUTF8(*it));
}
dict->Set("states", states);
- const std::vector<string16>& ia2_attributes = acc_obj->ia2_attributes();
+ const std::vector<base::string16>& ia2_attributes = acc_obj->ia2_attributes();
base::ListValue* attributes = new base::ListValue;
- for (std::vector<string16>::const_iterator it = ia2_attributes.begin();
+ for (std::vector<base::string16>::const_iterator it = ia2_attributes.begin();
it != ia2_attributes.end();
++it) {
attributes->AppendString(UTF16ToUTF8(*it));
@@ -199,15 +199,16 @@ void AccessibilityTreeFormatter::AddProperties(
}
}
-string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& dict,
- const string16& indent) {
- string16 line;
+base::string16 AccessibilityTreeFormatter::ToString(
+ const base::DictionaryValue& dict,
+ const base::string16& indent) {
+ base::string16 line;
- string16 role_value;
+ base::string16 role_value;
dict.GetString("role", &role_value);
WriteAttribute(true, UTF16ToUTF8(role_value), &line);
- string16 name_value;
+ base::string16 name_value;
dict.GetString("name", &name_value);
WriteAttribute(true, base::StringPrintf(L"name='%ls'", name_value.c_str()),
&line);
@@ -220,7 +221,7 @@ string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& dict,
switch (value->GetType()) {
case base::Value::TYPE_STRING: {
- string16 string_value;
+ base::string16 string_value;
value->GetAsString(&string_value);
WriteAttribute(false,
StringPrintf(L"%ls='%ls'",
@@ -257,7 +258,7 @@ string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& dict,
for (base::ListValue::const_iterator it = list_value->begin();
it != list_value->end();
++it) {
- string16 string_value;
+ base::string16 string_value;
if ((*it)->GetAsString(&string_value))
WriteAttribute(false, string_value, &line);
}
diff --git a/chromium/content/browser/accessibility/accessibility_ui.cc b/chromium/content/browser/accessibility/accessibility_ui.cc
index d5a9734b0eb..5203af6ade7 100644
--- a/chromium/content/browser/accessibility/accessibility_ui.cc
+++ b/chromium/content/browser/accessibility/accessibility_ui.cc
@@ -72,10 +72,12 @@ base::DictionaryValue* BuildTargetDescriptor(RenderViewHost* rvh) {
GURL url;
GURL favicon_url;
if (web_contents) {
+ // TODO(nasko): Fix the following code to use a consistent set of data
+ // across the URL, title, and favicon.
url = web_contents->GetURL();
title = UTF16ToUTF8(web_contents->GetTitle());
NavigationController& controller = web_contents->GetController();
- NavigationEntry* entry = controller.GetActiveEntry();
+ NavigationEntry* entry = controller.GetVisibleEntry();
if (entry != NULL && entry->GetURL().is_valid())
favicon_url = entry->GetFavicon().url;
}
@@ -231,7 +233,7 @@ void AccessibilityUI::RequestAccessibilityTree(const base::ListValue* args) {
}
scoped_ptr<AccessibilityTreeFormatter> formatter(
AccessibilityTreeFormatter::Create(rvh));
- string16 accessibility_contents_utf16;
+ base::string16 accessibility_contents_utf16;
BrowserAccessibilityManager* manager =
host_view->GetBrowserAccessibilityManager();
if (!manager) {
diff --git a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
index 6d069954117..bb35348ba76 100644
--- a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -149,7 +149,7 @@ void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml(
const std::string& html) {
AccessibilityNotificationWaiter waiter(
shell(), AccessibilityModeComplete,
- WebKit::WebAXEventLoadComplete);
+ blink::WebAXEventLoadComplete);
GURL html_data_url("data:text/html," + html);
NavigateToURL(shell(), html_data_url);
waiter.WaitForNotification();
@@ -226,7 +226,7 @@ class AccessibleChecker {
void CheckAccessibleValue(IAccessible* accessible);
void CheckAccessibleState(IAccessible* accessible);
void CheckAccessibleChildren(IAccessible* accessible);
- string16 RoleVariantToString(const base::win::ScopedVariant& role);
+ base::string16 RoleVariantToString(const base::win::ScopedVariant& role);
// Expected accessible name. Checked against IAccessible::get_accName.
std::wstring name_;
@@ -403,13 +403,13 @@ void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) {
}
}
-string16 AccessibleChecker::RoleVariantToString(
+base::string16 AccessibleChecker::RoleVariantToString(
const base::win::ScopedVariant& role) {
if (role.type() == VT_I4)
return IAccessibleRoleToString(V_I4(&role));
if (role.type() == VT_BSTR)
- return string16(V_BSTR(&role), SysStringLen(V_BSTR(&role)));
- return string16();
+ return base::string16(V_BSTR(&role), SysStringLen(V_BSTR(&role)));
+ return base::string16();
}
} // namespace
@@ -504,7 +504,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
scoped_ptr<AccessibilityNotificationWaiter> waiter(
new AccessibilityNotificationWaiter(
shell(), AccessibilityModeComplete,
- WebKit::WebAXEventFocus));
+ blink::WebAXEventFocus));
ExecuteScript(L"document.body.children[0].focus()");
waiter->WaitForNotification();
@@ -516,7 +516,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Set the active descendant of the radio group
waiter.reset(new AccessibilityNotificationWaiter(
shell(), AccessibilityModeComplete,
- WebKit::WebAXEventFocus));
+ blink::WebAXEventFocus));
ExecuteScript(
L"document.body.children[0].setAttribute('aria-activedescendant', 'li')");
waiter->WaitForNotification();
@@ -549,7 +549,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
scoped_ptr<AccessibilityNotificationWaiter> waiter(
new AccessibilityNotificationWaiter(
shell(), AccessibilityModeComplete,
- WebKit::WebAXEventCheckedStateChanged));
+ blink::WebAXEventCheckedStateChanged));
ExecuteScript(L"document.body.children[0].checked=true");
waiter->WaitForNotification();
@@ -577,7 +577,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
new AccessibilityNotificationWaiter(
shell(),
AccessibilityModeComplete,
- WebKit::WebAXEventChildrenChanged));
+ blink::WebAXEventChildrenChanged));
ExecuteScript(L"document.body.innerHTML='<b>new text</b>'");
waiter->WaitForNotification();
@@ -602,7 +602,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
scoped_ptr<AccessibilityNotificationWaiter> waiter(
new AccessibilityNotificationWaiter(
shell(), AccessibilityModeComplete,
- WebKit::WebAXEventChildrenChanged));
+ blink::WebAXEventChildrenChanged));
ExecuteScript(L"document.body.children[0].style.visibility='visible'");
waiter->WaitForNotification();
@@ -635,7 +635,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
scoped_ptr<AccessibilityNotificationWaiter> waiter(
new AccessibilityNotificationWaiter(
shell(), AccessibilityModeComplete,
- WebKit::WebAXEventFocus));
+ blink::WebAXEventFocus));
ExecuteScript(L"document.body.children[0].focus()");
waiter->WaitForNotification();
@@ -649,7 +649,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
waiter.reset(
new AccessibilityNotificationWaiter(
shell(), AccessibilityModeComplete,
- WebKit::WebAXEventBlur));
+ blink::WebAXEventBlur));
base::win::ScopedComPtr<IAccessible> document_accessible(
GetRendererAccessible());
ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL));
@@ -685,7 +685,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
scoped_ptr<AccessibilityNotificationWaiter> waiter(
new AccessibilityNotificationWaiter(
shell(), AccessibilityModeComplete,
- WebKit::WebAXEventValueChanged));
+ blink::WebAXEventValueChanged));
ExecuteScript(L"document.body.children[0].value='new value'");
waiter->WaitForNotification();
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index e039cc71e69..223cd8df559 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -43,10 +43,18 @@ BrowserAccessibility::BrowserAccessibility()
BrowserAccessibility::~BrowserAccessibility() {
}
+bool BrowserAccessibility::PlatformIsLeaf() const {
+ return role_ == blink::WebAXRoleStaticText || child_count() == 0;
+}
+
+uint32 BrowserAccessibility::PlatformChildCount() const {
+ return PlatformIsLeaf() ? 0 : children_.size();
+}
+
void BrowserAccessibility::DetachTree(
std::vector<BrowserAccessibility*>* nodes) {
nodes->push_back(this);
- for (size_t i = 0; i < children_.size(); i++)
+ for (size_t i = 0; i < children_.size(); ++i)
children_[i]->DetachTree(nodes);
children_.clear();
parent_ = NULL;
@@ -112,7 +120,8 @@ bool BrowserAccessibility::IsDescendantOf(
return false;
}
-BrowserAccessibility* BrowserAccessibility::GetChild(uint32 child_index) const {
+BrowserAccessibility* BrowserAccessibility::PlatformGetChild(
+ uint32 child_index) const {
DCHECK(child_index < children_.size());
return children_[child_index];
}
@@ -142,8 +151,8 @@ gfx::Rect BrowserAccessibility::GetLocalBoundsRect() const {
// nested web area.
BrowserAccessibility* parent = parent_;
bool need_to_offset_web_area =
- (role_ == WebKit::WebAXRoleWebArea ||
- role_ == WebKit::WebAXRoleRootWebArea);
+ (role_ == blink::WebAXRoleWebArea ||
+ role_ == blink::WebAXRoleRootWebArea);
while (parent) {
if (need_to_offset_web_area &&
parent->location().width() > 0 &&
@@ -154,13 +163,13 @@ gfx::Rect BrowserAccessibility::GetLocalBoundsRect() const {
// On some platforms, we don't want to take the root scroll offsets
// into account.
- if (parent->role() == WebKit::WebAXRoleRootWebArea &&
+ if (parent->role() == blink::WebAXRoleRootWebArea &&
!manager()->UseRootScrollOffsetsWhenComputingBounds()) {
break;
}
- if (parent->role() == WebKit::WebAXRoleWebArea ||
- parent->role() == WebKit::WebAXRoleRootWebArea) {
+ if (parent->role() == blink::WebAXRoleWebArea ||
+ parent->role() == blink::WebAXRoleRootWebArea) {
int sx = 0;
int sy = 0;
if (parent->GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X, &sx) &&
@@ -185,12 +194,102 @@ gfx::Rect BrowserAccessibility::GetGlobalBoundsRect() const {
return bounds;
}
+gfx::Rect BrowserAccessibility::GetLocalBoundsForRange(int start, int len)
+ const {
+ DCHECK_EQ(role_, blink::WebAXRoleStaticText);
+ int end = start + len;
+ int child_start = 0;
+ int child_end = 0;
+
+ gfx::Rect bounds;
+ for (size_t i = 0; i < children_.size() && child_end < start + len; ++i) {
+ BrowserAccessibility* child = children_[i];
+ DCHECK_EQ(child->role(), blink::WebAXRoleInlineTextBox);
+ std::string child_text;
+ child->GetStringAttribute(AccessibilityNodeData::ATTR_VALUE, &child_text);
+ int child_len = static_cast<int>(child_text.size());
+ child_start = child_end;
+ child_end += child_len;
+
+ if (child_end < start)
+ continue;
+
+ int overlap_start = std::max(start, child_start);
+ int overlap_end = std::min(end, child_end);
+
+ int local_start = overlap_start - child_start;
+ int local_end = overlap_end - child_start;
+
+ gfx::Rect child_rect = child->location();
+ int text_direction = child->GetIntAttribute(
+ AccessibilityNodeData::ATTR_TEXT_DIRECTION);
+ const std::vector<int32>& character_offsets = child->GetIntListAttribute(
+ AccessibilityNodeData::ATTR_CHARACTER_OFFSETS);
+ int start_pixel_offset =
+ local_start > 0 ? character_offsets[local_start - 1] : 0;
+ int end_pixel_offset =
+ local_end > 0 ? character_offsets[local_end - 1] : 0;
+
+ gfx::Rect child_overlap_rect;
+ switch (text_direction) {
+ case blink::WebAXTextDirectionLR: {
+ int left = child_rect.x() + start_pixel_offset;
+ int right = child_rect.x() + end_pixel_offset;
+ child_overlap_rect = gfx::Rect(left, child_rect.y(),
+ right - left, child_rect.height());
+ break;
+ }
+ case blink::WebAXTextDirectionRL: {
+ int right = child_rect.right() - start_pixel_offset;
+ int left = child_rect.right() - end_pixel_offset;
+ child_overlap_rect = gfx::Rect(left, child_rect.y(),
+ right - left, child_rect.height());
+ break;
+ }
+ case blink::WebAXTextDirectionTB: {
+ int top = child_rect.y() + start_pixel_offset;
+ int bottom = child_rect.y() + end_pixel_offset;
+ child_overlap_rect = gfx::Rect(child_rect.x(), top,
+ child_rect.width(), bottom - top);
+ break;
+ }
+ case blink::WebAXTextDirectionBT: {
+ int bottom = child_rect.bottom() - start_pixel_offset;
+ int top = child_rect.bottom() - end_pixel_offset;
+ child_overlap_rect = gfx::Rect(child_rect.x(), top,
+ child_rect.width(), bottom - top);
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+
+ if (bounds.width() == 0 && bounds.height() == 0)
+ bounds = child_overlap_rect;
+ else
+ bounds.Union(child_overlap_rect);
+ }
+
+ return bounds;
+}
+
+gfx::Rect BrowserAccessibility::GetGlobalBoundsForRange(int start, int len)
+ const {
+ gfx::Rect bounds = GetLocalBoundsForRange(start, len);
+
+ // Adjust the bounds by the top left corner of the containing view's bounds
+ // in screen coordinates.
+ bounds.Offset(manager_->GetViewBounds().OffsetFromOrigin());
+
+ return bounds;
+}
+
BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint(
const gfx::Point& point) {
// Walk the children recursively looking for the BrowserAccessibility that
// most tightly encloses the specified point.
- for (int i = children_.size() - 1; i >= 0; --i) {
- BrowserAccessibility* child = children_[i];
+ for (int i = static_cast<int>(PlatformChildCount()) - 1; i >= 0; --i) {
+ BrowserAccessibility* child = PlatformGetChild(i);
if (child->GetGlobalBoundsRect().Contains(point))
return child->BrowserAccessibilityForPoint(point);
}
@@ -211,7 +310,7 @@ void BrowserAccessibility::Destroy() {
PostInitialize();
manager_->NotifyAccessibilityEvent(
- WebKit::WebAXEventHide, this);
+ blink::WebAXEventHide, this);
instance_active_ = false;
manager_->RemoveNode(this);
@@ -345,17 +444,17 @@ bool BrowserAccessibility::GetStringAttribute(
return false;
}
-string16 BrowserAccessibility::GetString16Attribute(
+base::string16 BrowserAccessibility::GetString16Attribute(
StringAttribute attribute) const {
std::string value_utf8;
if (!GetStringAttribute(attribute, &value_utf8))
- return string16();
+ return base::string16();
return UTF8ToUTF16(value_utf8);
}
bool BrowserAccessibility::GetString16Attribute(
StringAttribute attribute,
- string16* value) const {
+ base::string16* value) const {
std::string value_utf8;
if (!GetStringAttribute(attribute, &value_utf8))
return false;
@@ -411,7 +510,7 @@ bool BrowserAccessibility::GetIntListAttribute(
bool BrowserAccessibility::GetHtmlAttribute(
const char* html_attr, std::string* value) const {
- for (size_t i = 0; i < html_attributes_.size(); i++) {
+ for (size_t i = 0; i < html_attributes_.size(); ++i) {
const std::string& attr = html_attributes_[i].first;
if (LowerCaseEqualsASCII(attr, html_attr)) {
*value = html_attributes_[i].second;
@@ -423,7 +522,7 @@ bool BrowserAccessibility::GetHtmlAttribute(
}
bool BrowserAccessibility::GetHtmlAttribute(
- const char* html_attr, string16* value) const {
+ const char* html_attr, base::string16* value) const {
std::string value_utf8;
if (!GetHtmlAttribute(html_attr, &value_utf8))
return false;
@@ -438,7 +537,7 @@ bool BrowserAccessibility::GetAriaTristate(
*is_defined = false;
*is_mixed = false;
- string16 value;
+ base::string16 value;
if (!GetHtmlAttribute(html_attr, &value) ||
value.empty() ||
EqualsASCII(value, "undefined")) {
@@ -456,24 +555,24 @@ bool BrowserAccessibility::GetAriaTristate(
return false; // Not set
}
-bool BrowserAccessibility::HasState(WebKit::WebAXState state_enum) const {
+bool BrowserAccessibility::HasState(blink::WebAXState state_enum) const {
return (state_ >> state_enum) & 1;
}
bool BrowserAccessibility::IsEditableText() const {
// These roles don't have readonly set, but they're not editable text.
- if (role_ == WebKit::WebAXRoleScrollArea ||
- role_ == WebKit::WebAXRoleColumn ||
- role_ == WebKit::WebAXRoleTableHeaderContainer) {
+ if (role_ == blink::WebAXRoleScrollArea ||
+ role_ == blink::WebAXRoleColumn ||
+ role_ == blink::WebAXRoleTableHeaderContainer) {
return false;
}
// Note: WebAXStateReadonly being false means it's either a text control,
// or contenteditable. We also check for editable text roles to cover
// another element that has role=textbox set on it.
- return (!HasState(WebKit::WebAXStateReadonly) ||
- role_ == WebKit::WebAXRoleTextField ||
- role_ == WebKit::WebAXRoleTextArea);
+ return (!HasState(blink::WebAXStateReadonly) ||
+ role_ == blink::WebAXRoleTextField ||
+ role_ == blink::WebAXRoleTextArea);
}
std::string BrowserAccessibility::GetTextRecursive() const {
@@ -482,8 +581,8 @@ std::string BrowserAccessibility::GetTextRecursive() const {
}
std::string result;
- for (size_t i = 0; i < children_.size(); ++i)
- result += children_[i]->GetTextRecursive();
+ for (uint32 i = 0; i < PlatformChildCount(); ++i)
+ result += PlatformGetChild(i)->GetTextRecursive();
return result;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index a52075128a5..1258803e376 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -89,8 +89,21 @@ class CONTENT_EXPORT BrowserAccessibility {
// Returns the number of children of this object.
uint32 child_count() const { return children_.size(); }
- // Return a pointer to the child with the given index.
- BrowserAccessibility* GetChild(uint32 child_index) const;
+ // Returns true if this is a leaf node on this platform, meaning any
+ // children should not be exposed to this platform's native accessibility
+ // layer. Each platform subclass should implement this itself.
+ // The definition of a leaf may vary depending on the platform,
+ // but a leaf node should never have children that are focusable or
+ // that might send notifications.
+ virtual bool PlatformIsLeaf() const;
+
+ // Returns the number of children of this object, or 0 if PlatformIsLeaf()
+ // returns true.
+ uint32 PlatformChildCount() const;
+
+ // Return a pointer to the child at the given index, or NULL for an
+ // invalid index. Returns NULL if PlatformIsLeaf() returns true.
+ BrowserAccessibility* PlatformGetChild(uint32 child_index) const;
// Return the previous sibling of this object, or NULL if it's the first
// child of its parent.
@@ -107,6 +120,15 @@ class CONTENT_EXPORT BrowserAccessibility {
// Returns the bounds of this object in screen coordinates.
gfx::Rect GetGlobalBoundsRect() const;
+ // Returns the bounds of the given range in coordinates relative to the
+ // top-left corner of the overall web area. Only valid when the
+ // role is WebAXRoleStaticText.
+ gfx::Rect GetLocalBoundsForRange(int start, int len) const;
+
+ // Same as GetLocalBoundsForRange, in screen coordinates. Only valid when
+ // the role is WebAXRoleStaticText.
+ gfx::Rect GetGlobalBoundsForRange(int start, int len) const;
+
// Returns the deepest descendant that contains the specified point
// (in global screen coordinates).
BrowserAccessibility* BrowserAccessibilityForPoint(const gfx::Point& point);
@@ -143,12 +165,15 @@ class CONTENT_EXPORT BrowserAccessibility {
gfx::Rect location() const { return location_; }
BrowserAccessibilityManager* manager() const { return manager_; }
const std::string& name() const { return name_; }
+ const std::string& value() const { return value_; }
int32 renderer_id() const { return renderer_id_; }
int32 role() const { return role_; }
int32 state() const { return state_; }
- const std::string& value() const { return value_; }
bool instance_active() const { return instance_active_; }
+ void set_name(const std::string& name) { name_ = name; }
+ void set_value(const std::string& value) { value_ = value; }
+
#if defined(OS_MACOSX) && __OBJC__
BrowserAccessibilityCocoa* ToBrowserAccessibilityCocoa();
#elif defined(OS_WIN)
@@ -170,7 +195,7 @@ class CONTENT_EXPORT BrowserAccessibility {
// need to distinguish between the default value and a missing attribute),
// and another that returns the default value for that type if the
// attribute is not present. In addition, strings can be returned as
- // either std::string or string16, for convenience.
+ // either std::string or base::string16, for convenience.
bool HasBoolAttribute(AccessibilityNodeData::BoolAttribute attr) const;
bool GetBoolAttribute(AccessibilityNodeData::BoolAttribute attr) const;
@@ -195,8 +220,8 @@ class CONTENT_EXPORT BrowserAccessibility {
std::string* value) const;
bool GetString16Attribute(AccessibilityNodeData::StringAttribute attribute,
- string16* value) const;
- string16 GetString16Attribute(
+ base::string16* value) const;
+ base::string16 GetString16Attribute(
AccessibilityNodeData::StringAttribute attribute) const;
bool HasIntListAttribute(
@@ -212,7 +237,7 @@ class CONTENT_EXPORT BrowserAccessibility {
// Retrieve the value of a html attribute from the attribute map and
// returns true if found.
- bool GetHtmlAttribute(const char* attr, string16* value) const;
+ bool GetHtmlAttribute(const char* attr, base::string16* value) const;
bool GetHtmlAttribute(const char* attr, std::string* value) const;
// Utility method to handle special cases for ARIA booleans, tristates and
@@ -232,7 +257,7 @@ class CONTENT_EXPORT BrowserAccessibility {
bool* is_mixed) const;
// Returns true if the bit corresponding to the given state enum is 1.
- bool HasState(WebKit::WebAXState state_enum) const;
+ bool HasState(blink::WebAXState state_enum) const;
// Returns true if this node is an editable text field of any kind.
bool IsEditableText() const;
@@ -256,6 +281,7 @@ class CONTENT_EXPORT BrowserAccessibility {
// The parent of this object, may be NULL if we're the root object.
BrowserAccessibility* parent_;
+ private:
// The index of this within its parent object.
int32 index_in_parent_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index d8899d7d31c..444aee29656 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -9,6 +9,38 @@
#include "content/common/accessibility_messages.h"
#include "content/common/accessibility_node_data.h"
+namespace {
+
+// These are enums from android.text.InputType in Java:
+enum {
+ ANDROID_TEXT_INPUTTYPE_TYPE_NULL = 0,
+ ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME = 0x4,
+ ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME_DATE = 0x14,
+ ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME_TIME = 0x24,
+ ANDROID_TEXT_INPUTTYPE_TYPE_NUMBER = 0x2,
+ ANDROID_TEXT_INPUTTYPE_TYPE_PHONE = 0x3,
+ ANDROID_TEXT_INPUTTYPE_TYPE_TEXT = 0x1,
+ ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_URI = 0x11,
+ ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_WEB_EDIT_TEXT = 0xa1,
+ ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_WEB_EMAIL = 0xd1,
+ ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_WEB_PASSWORD = 0xe1
+};
+
+// These are enums from android.view.View in Java:
+enum {
+ ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_NONE = 0,
+ ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_POLITE = 1,
+ ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2
+};
+
+// These are enums from
+// android.view.accessibility.AccessibilityNodeInfo.RangeInfo in Java:
+enum {
+ ANDROID_VIEW_ACCESSIBILITY_RANGE_TYPE_FLOAT = 1
+};
+
+} // namespace
+
namespace content {
// static
@@ -24,14 +56,14 @@ bool BrowserAccessibilityAndroid::IsNative() const {
return true;
}
-bool BrowserAccessibilityAndroid::IsLeaf() const {
+bool BrowserAccessibilityAndroid::PlatformIsLeaf() const {
if (child_count() == 0)
return true;
// Iframes are always allowed to contain children.
if (IsIframe() ||
- role() == WebKit::WebAXRoleRootWebArea ||
- role() == WebKit::WebAXRoleWebArea) {
+ role() == blink::WebAXRoleRootWebArea ||
+ role() == blink::WebAXRoleWebArea) {
return false;
}
@@ -40,19 +72,19 @@ bool BrowserAccessibilityAndroid::IsLeaf() const {
return false;
// Headings with text can drop their children.
- string16 name = GetText();
- if (role() == WebKit::WebAXRoleHeading && !name.empty())
+ base::string16 name = GetText();
+ if (role() == blink::WebAXRoleHeading && !name.empty())
return true;
// Focusable nodes with text can drop their children.
- if (HasState(WebKit::WebAXStateFocusable) && !name.empty())
+ if (HasState(blink::WebAXStateFocusable) && !name.empty())
return true;
// Nodes with only static text as children can drop their children.
if (HasOnlyStaticTextChildren())
return true;
- return false;
+ return BrowserAccessibility::PlatformIsLeaf();
}
bool BrowserAccessibilityAndroid::IsCheckable() const {
@@ -60,32 +92,59 @@ bool BrowserAccessibilityAndroid::IsCheckable() const {
bool is_aria_pressed_defined;
bool is_mixed;
GetAriaTristate("aria-pressed", &is_aria_pressed_defined, &is_mixed);
- if (role() == WebKit::WebAXRoleCheckBox ||
- role() == WebKit::WebAXRoleRadioButton ||
+ if (role() == blink::WebAXRoleCheckBox ||
+ role() == blink::WebAXRoleRadioButton ||
is_aria_pressed_defined) {
checkable = true;
}
- if (HasState(WebKit::WebAXStateChecked))
+ if (HasState(blink::WebAXStateChecked))
checkable = true;
return checkable;
}
bool BrowserAccessibilityAndroid::IsChecked() const {
- return HasState(WebKit::WebAXStateChecked);
+ return HasState(blink::WebAXStateChecked);
}
bool BrowserAccessibilityAndroid::IsClickable() const {
- return (IsLeaf() && !GetText().empty());
+ return (PlatformIsLeaf() && !GetText().empty());
+}
+
+bool BrowserAccessibilityAndroid::IsCollection() const {
+ return (role() == blink::WebAXRoleGrid ||
+ role() == blink::WebAXRoleList ||
+ role() == blink::WebAXRoleListBox ||
+ role() == blink::WebAXRoleTable ||
+ role() == blink::WebAXRoleTree);
+}
+
+bool BrowserAccessibilityAndroid::IsCollectionItem() const {
+ return (role() == blink::WebAXRoleCell ||
+ role() == blink::WebAXRoleColumnHeader ||
+ role() == blink::WebAXRoleDescriptionListTerm ||
+ role() == blink::WebAXRoleListBoxOption ||
+ role() == blink::WebAXRoleListItem ||
+ role() == blink::WebAXRoleRowHeader ||
+ role() == blink::WebAXRoleTreeItem);
+}
+
+bool BrowserAccessibilityAndroid::IsContentInvalid() const {
+ std::string invalid;
+ return GetHtmlAttribute("aria-invalid", &invalid);
+}
+
+bool BrowserAccessibilityAndroid::IsDismissable() const {
+ return false; // No concept of "dismissable" on the web currently.
}
bool BrowserAccessibilityAndroid::IsEnabled() const {
- return HasState(WebKit::WebAXStateEnabled);
+ return HasState(blink::WebAXStateEnabled);
}
bool BrowserAccessibilityAndroid::IsFocusable() const {
- bool focusable = HasState(WebKit::WebAXStateFocusable);
+ bool focusable = HasState(blink::WebAXStateFocusable);
if (IsIframe() ||
- role() == WebKit::WebAXRoleWebArea) {
+ role() == blink::WebAXRoleWebArea) {
focusable = false;
}
return focusable;
@@ -95,8 +154,29 @@ bool BrowserAccessibilityAndroid::IsFocused() const {
return manager()->GetFocus(manager()->GetRoot()) == this;
}
+bool BrowserAccessibilityAndroid::IsHeading() const {
+ return (role() == blink::WebAXRoleColumnHeader ||
+ role() == blink::WebAXRoleHeading ||
+ role() == blink::WebAXRoleRowHeader);
+}
+
+bool BrowserAccessibilityAndroid::IsHierarchical() const {
+ return (role() == blink::WebAXRoleList ||
+ role() == blink::WebAXRoleTree);
+}
+
+bool BrowserAccessibilityAndroid::IsMultiLine() const {
+ return role() == blink::WebAXRoleTextArea;
+}
+
bool BrowserAccessibilityAndroid::IsPassword() const {
- return HasState(WebKit::WebAXStateProtected);
+ return HasState(blink::WebAXStateProtected);
+}
+
+bool BrowserAccessibilityAndroid::IsRangeType() const {
+ return (role() == blink::WebAXRoleProgressIndicator ||
+ role() == blink::WebAXRoleScrollBar ||
+ role() == blink::WebAXRoleSlider);
}
bool BrowserAccessibilityAndroid::IsScrollable() const {
@@ -105,61 +185,68 @@ bool BrowserAccessibilityAndroid::IsScrollable() const {
}
bool BrowserAccessibilityAndroid::IsSelected() const {
- return HasState(WebKit::WebAXStateSelected);
+ return HasState(blink::WebAXStateSelected);
}
bool BrowserAccessibilityAndroid::IsVisibleToUser() const {
- return !HasState(WebKit::WebAXStateInvisible);
+ return !HasState(blink::WebAXStateInvisible);
+}
+
+bool BrowserAccessibilityAndroid::CanOpenPopup() const {
+ return HasState(blink::WebAXStateHaspopup);
}
const char* BrowserAccessibilityAndroid::GetClassName() const {
const char* class_name = NULL;
switch(role()) {
- case WebKit::WebAXRoleEditableText:
- case WebKit::WebAXRoleSpinButton:
- case WebKit::WebAXRoleTextArea:
- case WebKit::WebAXRoleTextField:
+ case blink::WebAXRoleEditableText:
+ case blink::WebAXRoleSpinButton:
+ case blink::WebAXRoleTextArea:
+ case blink::WebAXRoleTextField:
class_name = "android.widget.EditText";
break;
- case WebKit::WebAXRoleSlider:
+ case blink::WebAXRoleSlider:
class_name = "android.widget.SeekBar";
break;
- case WebKit::WebAXRoleComboBox:
+ case blink::WebAXRoleComboBox:
class_name = "android.widget.Spinner";
break;
- case WebKit::WebAXRoleButton:
- case WebKit::WebAXRoleMenuButton:
- case WebKit::WebAXRolePopUpButton:
+ case blink::WebAXRoleButton:
+ case blink::WebAXRoleMenuButton:
+ case blink::WebAXRolePopUpButton:
class_name = "android.widget.Button";
break;
- case WebKit::WebAXRoleCheckBox:
+ case blink::WebAXRoleCheckBox:
class_name = "android.widget.CheckBox";
break;
- case WebKit::WebAXRoleRadioButton:
+ case blink::WebAXRoleRadioButton:
class_name = "android.widget.RadioButton";
break;
- case WebKit::WebAXRoleToggleButton:
+ case blink::WebAXRoleToggleButton:
class_name = "android.widget.ToggleButton";
break;
- case WebKit::WebAXRoleCanvas:
- case WebKit::WebAXRoleImage:
+ case blink::WebAXRoleCanvas:
+ case blink::WebAXRoleImage:
class_name = "android.widget.Image";
break;
- case WebKit::WebAXRoleProgressIndicator:
+ case blink::WebAXRoleProgressIndicator:
class_name = "android.widget.ProgressBar";
break;
- case WebKit::WebAXRoleTabList:
+ case blink::WebAXRoleTabList:
class_name = "android.widget.TabWidget";
break;
- case WebKit::WebAXRoleGrid:
- case WebKit::WebAXRoleTable:
+ case blink::WebAXRoleGrid:
+ case blink::WebAXRoleTable:
class_name = "android.widget.GridView";
break;
- case WebKit::WebAXRoleList:
- case WebKit::WebAXRoleListBox:
+ case blink::WebAXRoleList:
+ case blink::WebAXRoleListBox:
class_name = "android.widget.ListView";
break;
+ case blink::WebAXRoleDialog:
+ class_name = "android.app.Dialog";
+ break;
default:
class_name = "android.view.View";
break;
@@ -168,15 +255,15 @@ const char* BrowserAccessibilityAndroid::GetClassName() const {
return class_name;
}
-string16 BrowserAccessibilityAndroid::GetText() const {
+base::string16 BrowserAccessibilityAndroid::GetText() const {
if (IsIframe() ||
- role() == WebKit::WebAXRoleWebArea) {
- return string16();
+ role() == blink::WebAXRoleWebArea) {
+ return base::string16();
}
- string16 description = GetString16Attribute(
+ base::string16 description = GetString16Attribute(
AccessibilityNodeData::ATTR_DESCRIPTION);
- string16 text;
+ base::string16 text;
if (!name().empty())
text = base::UTF8ToUTF16(name());
else if (!description.empty())
@@ -184,21 +271,23 @@ string16 BrowserAccessibilityAndroid::GetText() const {
else if (!value().empty())
text = base::UTF8ToUTF16(value());
+ // This is called from PlatformIsLeaf, so don't call PlatformChildCount
+ // from within this!
if (text.empty() && HasOnlyStaticTextChildren()) {
for (uint32 i = 0; i < child_count(); i++) {
- BrowserAccessibility* child = GetChild(i);
+ BrowserAccessibility* child = children()[i];
text += static_cast<BrowserAccessibilityAndroid*>(child)->GetText();
}
}
switch(role()) {
- case WebKit::WebAXRoleImageMapLink:
- case WebKit::WebAXRoleLink:
+ case blink::WebAXRoleImageMapLink:
+ case blink::WebAXRoleLink:
if (!text.empty())
text += ASCIIToUTF16(" ");
text += ASCIIToUTF16("Link");
break;
- case WebKit::WebAXRoleHeading:
+ case blink::WebAXRoleHeading:
// Only append "heading" if this node already has text.
if (!text.empty())
text += ASCIIToUTF16(" Heading");
@@ -211,12 +300,13 @@ string16 BrowserAccessibilityAndroid::GetText() const {
int BrowserAccessibilityAndroid::GetItemIndex() const {
int index = 0;
switch(role()) {
- case WebKit::WebAXRoleListItem:
- case WebKit::WebAXRoleListBoxOption:
+ case blink::WebAXRoleListItem:
+ case blink::WebAXRoleListBoxOption:
+ case blink::WebAXRoleTreeItem:
index = index_in_parent();
break;
- case WebKit::WebAXRoleSlider:
- case WebKit::WebAXRoleProgressIndicator: {
+ case blink::WebAXRoleSlider:
+ case blink::WebAXRoleProgressIndicator: {
float value_for_range;
if (GetFloatAttribute(
AccessibilityNodeData::ATTR_VALUE_FOR_RANGE, &value_for_range)) {
@@ -231,12 +321,12 @@ int BrowserAccessibilityAndroid::GetItemIndex() const {
int BrowserAccessibilityAndroid::GetItemCount() const {
int count = 0;
switch(role()) {
- case WebKit::WebAXRoleList:
- case WebKit::WebAXRoleListBox:
- count = child_count();
+ case blink::WebAXRoleList:
+ case blink::WebAXRoleListBox:
+ count = PlatformChildCount();
break;
- case WebKit::WebAXRoleSlider:
- case WebKit::WebAXRoleProgressIndicator: {
+ case blink::WebAXRoleSlider:
+ case blink::WebAXRoleProgressIndicator: {
float max_value_for_range;
if (GetFloatAttribute(AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE,
&max_value_for_range)) {
@@ -318,7 +408,7 @@ int BrowserAccessibilityAndroid::GetTextChangeRemovedCount() const {
return (old_len - left - right);
}
-string16 BrowserAccessibilityAndroid::GetTextChangeBeforeText() const {
+base::string16 BrowserAccessibilityAndroid::GetTextChangeBeforeText() const {
return old_value_;
}
@@ -338,10 +428,119 @@ int BrowserAccessibilityAndroid::GetEditableTextLength() const {
return value().length();
}
+int BrowserAccessibilityAndroid::AndroidInputType() const {
+ std::string html_tag = GetStringAttribute(
+ AccessibilityNodeData::ATTR_HTML_TAG);
+ if (html_tag != "input")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_NULL;
+
+ std::string type;
+ if (!GetHtmlAttribute("type", &type))
+ return ANDROID_TEXT_INPUTTYPE_TYPE_TEXT;
+
+ if (type == "" || type == "text" || type == "search")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_TEXT;
+ else if (type == "date")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME_DATE;
+ else if (type == "datetime" || type == "datetime-local")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME;
+ else if (type == "email")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_WEB_EMAIL;
+ else if (type == "month")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME_DATE;
+ else if (type == "number")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_NUMBER;
+ else if (type == "password")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_WEB_PASSWORD;
+ else if (type == "tel")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_PHONE;
+ else if (type == "time")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME_TIME;
+ else if (type == "url")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_URI;
+ else if (type == "week")
+ return ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME;
+
+ return ANDROID_TEXT_INPUTTYPE_TYPE_NULL;
+}
+
+int BrowserAccessibilityAndroid::AndroidLiveRegionType() const {
+ std::string live = GetStringAttribute(
+ AccessibilityNodeData::ATTR_LIVE_STATUS);
+ if (live == "polite")
+ return ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_POLITE;
+ else if (live == "assertive")
+ return ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_ASSERTIVE;
+ return ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_NONE;
+}
+
+int BrowserAccessibilityAndroid::AndroidRangeType() const {
+ return ANDROID_VIEW_ACCESSIBILITY_RANGE_TYPE_FLOAT;
+}
+
+int BrowserAccessibilityAndroid::RowCount() const {
+ if (role() == blink::WebAXRoleGrid ||
+ role() == blink::WebAXRoleTable) {
+ return CountChildrenWithRole(blink::WebAXRoleRow);
+ }
+
+ if (role() == blink::WebAXRoleList ||
+ role() == blink::WebAXRoleListBox ||
+ role() == blink::WebAXRoleTree) {
+ return PlatformChildCount();
+ }
+
+ return 0;
+}
+
+int BrowserAccessibilityAndroid::ColumnCount() const {
+ if (role() == blink::WebAXRoleGrid ||
+ role() == blink::WebAXRoleTable) {
+ return CountChildrenWithRole(blink::WebAXRoleColumn);
+ }
+ return 0;
+}
+
+int BrowserAccessibilityAndroid::RowIndex() const {
+ if (role() == blink::WebAXRoleListItem ||
+ role() == blink::WebAXRoleListBoxOption ||
+ role() == blink::WebAXRoleTreeItem) {
+ return index_in_parent();
+ }
+
+ return GetIntAttribute(AccessibilityNodeData::ATTR_TABLE_CELL_ROW_INDEX);
+}
+
+int BrowserAccessibilityAndroid::RowSpan() const {
+ return GetIntAttribute(AccessibilityNodeData::ATTR_TABLE_CELL_ROW_SPAN);
+}
+
+int BrowserAccessibilityAndroid::ColumnIndex() const {
+ return GetIntAttribute(AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_INDEX);
+}
+
+int BrowserAccessibilityAndroid::ColumnSpan() const {
+ return GetIntAttribute(AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_SPAN);
+}
+
+float BrowserAccessibilityAndroid::RangeMin() const {
+ return GetFloatAttribute(AccessibilityNodeData::ATTR_MIN_VALUE_FOR_RANGE);
+}
+
+float BrowserAccessibilityAndroid::RangeMax() const {
+ return GetFloatAttribute(AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE);
+}
+
+float BrowserAccessibilityAndroid::RangeCurrentValue() const {
+ return GetFloatAttribute(AccessibilityNodeData::ATTR_VALUE_FOR_RANGE);
+}
+
bool BrowserAccessibilityAndroid::HasFocusableChild() const {
+ // This is called from PlatformIsLeaf, so don't call PlatformChildCount
+ // from within this!
for (uint32 i = 0; i < child_count(); i++) {
- BrowserAccessibility* child = GetChild(i);
- if (child->HasState(WebKit::WebAXStateFocusable))
+ BrowserAccessibility* child = children()[i];
+ if (child->HasState(blink::WebAXStateFocusable))
return true;
if (static_cast<BrowserAccessibilityAndroid*>(child)->HasFocusableChild())
return true;
@@ -350,16 +549,18 @@ bool BrowserAccessibilityAndroid::HasFocusableChild() const {
}
bool BrowserAccessibilityAndroid::HasOnlyStaticTextChildren() const {
+ // This is called from PlatformIsLeaf, so don't call PlatformChildCount
+ // from within this!
for (uint32 i = 0; i < child_count(); i++) {
- BrowserAccessibility* child = GetChild(i);
- if (child->role() != WebKit::WebAXRoleStaticText)
+ BrowserAccessibility* child = children()[i];
+ if (child->role() != blink::WebAXRoleStaticText)
return false;
}
return true;
}
bool BrowserAccessibilityAndroid::IsIframe() const {
- string16 html_tag = GetString16Attribute(
+ base::string16 html_tag = GetString16Attribute(
AccessibilityNodeData::ATTR_HTML_TAG);
return html_tag == ASCIIToUTF16("iframe");
}
@@ -368,16 +569,16 @@ void BrowserAccessibilityAndroid::PostInitialize() {
BrowserAccessibility::PostInitialize();
if (IsEditableText()) {
- if (base::UTF8ToUTF16(value_) != new_value_) {
+ if (base::UTF8ToUTF16(value()) != new_value_) {
old_value_ = new_value_;
- new_value_ = base::UTF8ToUTF16(value_);
+ new_value_ = base::UTF8ToUTF16(value());
}
}
- if (role_ == WebKit::WebAXRoleAlert && first_time_)
- manager_->NotifyAccessibilityEvent(WebKit::WebAXEventAlert, this);
+ if (role() == blink::WebAXRoleAlert && first_time_)
+ manager()->NotifyAccessibilityEvent(blink::WebAXEventAlert, this);
- string16 live;
+ base::string16 live;
if (GetString16Attribute(
AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS, &live)) {
NotifyLiveRegionUpdate(live);
@@ -386,19 +587,30 @@ void BrowserAccessibilityAndroid::PostInitialize() {
first_time_ = false;
}
-void BrowserAccessibilityAndroid::NotifyLiveRegionUpdate(string16& aria_live) {
+void BrowserAccessibilityAndroid::NotifyLiveRegionUpdate(
+ base::string16& aria_live) {
if (!EqualsASCII(aria_live, aria_strings::kAriaLivePolite) &&
!EqualsASCII(aria_live, aria_strings::kAriaLiveAssertive))
return;
- string16 text = GetText();
+ base::string16 text = GetText();
if (cached_text_ != text) {
if (!text.empty()) {
- manager_->NotifyAccessibilityEvent(WebKit::WebAXEventShow,
+ manager()->NotifyAccessibilityEvent(blink::WebAXEventShow,
this);
}
cached_text_ = text;
}
}
+int BrowserAccessibilityAndroid::CountChildrenWithRole(
+ blink::WebAXRole role) const {
+ int count = 0;
+ for (uint32 i = 0; i < PlatformChildCount(); i++) {
+ if (PlatformGetChild(i)->role() == role)
+ count++;
+ }
+ return count;
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.h b/chromium/content/browser/accessibility/browser_accessibility_android.h
index 8b4ed84bc9e..2968184b53c 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.h
@@ -16,21 +16,31 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility {
virtual void PostInitialize() OVERRIDE;
virtual bool IsNative() const OVERRIDE;
- bool IsLeaf() const;
+ virtual bool PlatformIsLeaf() const OVERRIDE;
bool IsCheckable() const;
bool IsChecked() const;
bool IsClickable() const;
+ bool IsCollection() const;
+ bool IsCollectionItem() const;
+ bool IsContentInvalid() const;
+ bool IsDismissable() const;
bool IsEnabled() const;
bool IsFocusable() const;
bool IsFocused() const;
+ bool IsHeading() const;
+ bool IsHierarchical() const;
+ bool IsMultiLine() const;
bool IsPassword() const;
+ bool IsRangeType() const;
bool IsScrollable() const;
bool IsSelected() const;
bool IsVisibleToUser() const;
+ bool CanOpenPopup() const;
+
const char* GetClassName() const;
- string16 GetText() const;
+ base::string16 GetText() const;
int GetItemIndex() const;
int GetItemCount() const;
@@ -43,12 +53,28 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility {
int GetTextChangeFromIndex() const;
int GetTextChangeAddedCount() const;
int GetTextChangeRemovedCount() const;
- string16 GetTextChangeBeforeText() const;
+ base::string16 GetTextChangeBeforeText() const;
int GetSelectionStart() const;
int GetSelectionEnd() const;
int GetEditableTextLength() const;
+ int AndroidInputType() const;
+ int AndroidLiveRegionType() const;
+ int AndroidRangeType() const;
+
+ int RowCount() const;
+ int ColumnCount() const;
+
+ int RowIndex() const;
+ int RowSpan() const;
+ int ColumnIndex() const;
+ int ColumnSpan() const;
+
+ float RangeMin() const;
+ float RangeMax() const;
+ float RangeCurrentValue() const;
+
private:
// This gives BrowserAccessibility::Create access to the class constructor.
friend class BrowserAccessibility;
@@ -59,12 +85,14 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility {
bool HasOnlyStaticTextChildren() const;
bool IsIframe() const;
- void NotifyLiveRegionUpdate(string16& aria_live);
+ void NotifyLiveRegionUpdate(base::string16& aria_live);
+
+ int CountChildrenWithRole(blink::WebAXRole role) const;
- string16 cached_text_;
+ base::string16 cached_text_;
bool first_time_;
- string16 old_value_;
- string16 new_value_;
+ base::string16 old_value_;
+ base::string16 new_value_;
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityAndroid);
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
index d690d81dd4d..9ac751fdb41 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -40,7 +40,7 @@
// Convenience method to get the internal, cross-platform role
// from browserAccessibility_.
-- (WebKit::WebAXRole)internalRole;
+- (blink::WebAXRole)internalRole;
// Return the method name for the given attribute. For testing only.
- (NSString*)methodNameForAttribute:(NSString*)attribute;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index be9ff5b329d..9364dbbfc00 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -40,129 +40,129 @@ NSString* NSStringForStringAttribute(
}
struct MapEntry {
- WebKit::WebAXRole webKitValue;
+ blink::WebAXRole webKitValue;
NSString* nativeValue;
};
-typedef std::map<WebKit::WebAXRole, NSString*> RoleMap;
+typedef std::map<blink::WebAXRole, NSString*> RoleMap;
// GetState checks the bitmask used in AccessibilityNodeData to check
// if the given state was set on the accessibility object.
-bool GetState(BrowserAccessibility* accessibility, WebKit::WebAXState state) {
+bool GetState(BrowserAccessibility* accessibility, blink::WebAXState state) {
return ((accessibility->state() >> state) & 1);
}
RoleMap BuildRoleMap() {
const MapEntry roles[] = {
- { WebKit::WebAXRoleAlert, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleAlertDialog, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleAnnotation, NSAccessibilityUnknownRole },
- { WebKit::WebAXRoleApplication, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleArticle, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleBrowser, NSAccessibilityBrowserRole },
- { WebKit::WebAXRoleBusyIndicator, NSAccessibilityBusyIndicatorRole },
- { WebKit::WebAXRoleButton, NSAccessibilityButtonRole },
- { WebKit::WebAXRoleCanvas, NSAccessibilityImageRole },
- { WebKit::WebAXRoleCell, @"AXCell" },
- { WebKit::WebAXRoleCheckBox, NSAccessibilityCheckBoxRole },
- { WebKit::WebAXRoleColorWell, NSAccessibilityColorWellRole },
- { WebKit::WebAXRoleComboBox, NSAccessibilityComboBoxRole },
- { WebKit::WebAXRoleColumn, NSAccessibilityColumnRole },
- { WebKit::WebAXRoleColumnHeader, @"AXCell" },
- { WebKit::WebAXRoleDefinition, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleDescriptionListDetail, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleDescriptionListTerm, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleDialog, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleDirectory, NSAccessibilityListRole },
- { WebKit::WebAXRoleDisclosureTriangle,
+ { blink::WebAXRoleAlert, NSAccessibilityGroupRole },
+ { blink::WebAXRoleAlertDialog, NSAccessibilityGroupRole },
+ { blink::WebAXRoleAnnotation, NSAccessibilityUnknownRole },
+ { blink::WebAXRoleApplication, NSAccessibilityGroupRole },
+ { blink::WebAXRoleArticle, NSAccessibilityGroupRole },
+ { blink::WebAXRoleBrowser, NSAccessibilityBrowserRole },
+ { blink::WebAXRoleBusyIndicator, NSAccessibilityBusyIndicatorRole },
+ { blink::WebAXRoleButton, NSAccessibilityButtonRole },
+ { blink::WebAXRoleCanvas, NSAccessibilityImageRole },
+ { blink::WebAXRoleCell, @"AXCell" },
+ { blink::WebAXRoleCheckBox, NSAccessibilityCheckBoxRole },
+ { blink::WebAXRoleColorWell, NSAccessibilityColorWellRole },
+ { blink::WebAXRoleComboBox, NSAccessibilityComboBoxRole },
+ { blink::WebAXRoleColumn, NSAccessibilityColumnRole },
+ { blink::WebAXRoleColumnHeader, @"AXCell" },
+ { blink::WebAXRoleDefinition, NSAccessibilityGroupRole },
+ { blink::WebAXRoleDescriptionListDetail, NSAccessibilityGroupRole },
+ { blink::WebAXRoleDescriptionListTerm, NSAccessibilityGroupRole },
+ { blink::WebAXRoleDialog, NSAccessibilityGroupRole },
+ { blink::WebAXRoleDirectory, NSAccessibilityListRole },
+ { blink::WebAXRoleDisclosureTriangle,
NSAccessibilityDisclosureTriangleRole },
- { WebKit::WebAXRoleDiv, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleDocument, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleDrawer, NSAccessibilityDrawerRole },
- { WebKit::WebAXRoleEditableText, NSAccessibilityTextFieldRole },
- { WebKit::WebAXRoleFooter, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleForm, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleGrid, NSAccessibilityGridRole },
- { WebKit::WebAXRoleGroup, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleGrowArea, NSAccessibilityGrowAreaRole },
- { WebKit::WebAXRoleHeading, @"AXHeading" },
- { WebKit::WebAXRoleHelpTag, NSAccessibilityHelpTagRole },
- { WebKit::WebAXRoleHorizontalRule, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleIgnored, NSAccessibilityUnknownRole },
- { WebKit::WebAXRoleImage, NSAccessibilityImageRole },
- { WebKit::WebAXRoleImageMap, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleImageMapLink, NSAccessibilityLinkRole },
- { WebKit::WebAXRoleIncrementor, NSAccessibilityIncrementorRole },
- { WebKit::WebAXRoleLabel, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleApplication, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleBanner, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleComplementary, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleContentInfo, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleMain, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleNavigation, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleSearch, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleLink, NSAccessibilityLinkRole },
- { WebKit::WebAXRoleList, NSAccessibilityListRole },
- { WebKit::WebAXRoleListItem, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleListMarker, @"AXListMarker" },
- { WebKit::WebAXRoleListBox, NSAccessibilityListRole },
- { WebKit::WebAXRoleListBoxOption, NSAccessibilityStaticTextRole },
- { WebKit::WebAXRoleLog, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleMarquee, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleMath, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleMatte, NSAccessibilityMatteRole },
- { WebKit::WebAXRoleMenu, NSAccessibilityMenuRole },
- { WebKit::WebAXRoleMenuBar, NSAccessibilityMenuBarRole },
- { WebKit::WebAXRoleMenuItem, NSAccessibilityMenuItemRole },
- { WebKit::WebAXRoleMenuButton, NSAccessibilityButtonRole },
- { WebKit::WebAXRoleMenuListOption, NSAccessibilityMenuItemRole },
- { WebKit::WebAXRoleMenuListPopup, NSAccessibilityUnknownRole },
- { WebKit::WebAXRoleNote, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleOutline, NSAccessibilityOutlineRole },
- { WebKit::WebAXRoleParagraph, NSAccessibilityGroupRole },
- { WebKit::WebAXRolePopUpButton, NSAccessibilityPopUpButtonRole },
- { WebKit::WebAXRolePresentational, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleProgressIndicator,
+ { blink::WebAXRoleDiv, NSAccessibilityGroupRole },
+ { blink::WebAXRoleDocument, NSAccessibilityGroupRole },
+ { blink::WebAXRoleDrawer, NSAccessibilityDrawerRole },
+ { blink::WebAXRoleEditableText, NSAccessibilityTextFieldRole },
+ { blink::WebAXRoleFooter, NSAccessibilityGroupRole },
+ { blink::WebAXRoleForm, NSAccessibilityGroupRole },
+ { blink::WebAXRoleGrid, NSAccessibilityGridRole },
+ { blink::WebAXRoleGroup, NSAccessibilityGroupRole },
+ { blink::WebAXRoleGrowArea, NSAccessibilityGrowAreaRole },
+ { blink::WebAXRoleHeading, @"AXHeading" },
+ { blink::WebAXRoleHelpTag, NSAccessibilityHelpTagRole },
+ { blink::WebAXRoleHorizontalRule, NSAccessibilityGroupRole },
+ { blink::WebAXRoleIgnored, NSAccessibilityUnknownRole },
+ { blink::WebAXRoleImage, NSAccessibilityImageRole },
+ { blink::WebAXRoleImageMap, NSAccessibilityGroupRole },
+ { blink::WebAXRoleImageMapLink, NSAccessibilityLinkRole },
+ { blink::WebAXRoleIncrementor, NSAccessibilityIncrementorRole },
+ { blink::WebAXRoleLabel, NSAccessibilityGroupRole },
+ { blink::WebAXRoleApplication, NSAccessibilityGroupRole },
+ { blink::WebAXRoleBanner, NSAccessibilityGroupRole },
+ { blink::WebAXRoleComplementary, NSAccessibilityGroupRole },
+ { blink::WebAXRoleContentInfo, NSAccessibilityGroupRole },
+ { blink::WebAXRoleMain, NSAccessibilityGroupRole },
+ { blink::WebAXRoleNavigation, NSAccessibilityGroupRole },
+ { blink::WebAXRoleSearch, NSAccessibilityGroupRole },
+ { blink::WebAXRoleLink, NSAccessibilityLinkRole },
+ { blink::WebAXRoleList, NSAccessibilityListRole },
+ { blink::WebAXRoleListItem, NSAccessibilityGroupRole },
+ { blink::WebAXRoleListMarker, @"AXListMarker" },
+ { blink::WebAXRoleListBox, NSAccessibilityListRole },
+ { blink::WebAXRoleListBoxOption, NSAccessibilityStaticTextRole },
+ { blink::WebAXRoleLog, NSAccessibilityGroupRole },
+ { blink::WebAXRoleMarquee, NSAccessibilityGroupRole },
+ { blink::WebAXRoleMath, NSAccessibilityGroupRole },
+ { blink::WebAXRoleMatte, NSAccessibilityMatteRole },
+ { blink::WebAXRoleMenu, NSAccessibilityMenuRole },
+ { blink::WebAXRoleMenuBar, NSAccessibilityMenuBarRole },
+ { blink::WebAXRoleMenuItem, NSAccessibilityMenuItemRole },
+ { blink::WebAXRoleMenuButton, NSAccessibilityButtonRole },
+ { blink::WebAXRoleMenuListOption, NSAccessibilityMenuItemRole },
+ { blink::WebAXRoleMenuListPopup, NSAccessibilityUnknownRole },
+ { blink::WebAXRoleNote, NSAccessibilityGroupRole },
+ { blink::WebAXRoleOutline, NSAccessibilityOutlineRole },
+ { blink::WebAXRoleParagraph, NSAccessibilityGroupRole },
+ { blink::WebAXRolePopUpButton, NSAccessibilityPopUpButtonRole },
+ { blink::WebAXRolePresentational, NSAccessibilityGroupRole },
+ { blink::WebAXRoleProgressIndicator,
NSAccessibilityProgressIndicatorRole },
- { WebKit::WebAXRoleRadioButton, NSAccessibilityRadioButtonRole },
- { WebKit::WebAXRoleRadioGroup, NSAccessibilityRadioGroupRole },
- { WebKit::WebAXRoleRegion, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleRootWebArea, @"AXWebArea" },
- { WebKit::WebAXRoleRow, NSAccessibilityRowRole },
- { WebKit::WebAXRoleRowHeader, @"AXCell" },
- { WebKit::WebAXRoleRuler, NSAccessibilityRulerRole },
- { WebKit::WebAXRoleRulerMarker, NSAccessibilityRulerMarkerRole },
+ { blink::WebAXRoleRadioButton, NSAccessibilityRadioButtonRole },
+ { blink::WebAXRoleRadioGroup, NSAccessibilityRadioGroupRole },
+ { blink::WebAXRoleRegion, NSAccessibilityGroupRole },
+ { blink::WebAXRoleRootWebArea, @"AXWebArea" },
+ { blink::WebAXRoleRow, NSAccessibilityRowRole },
+ { blink::WebAXRoleRowHeader, @"AXCell" },
+ { blink::WebAXRoleRuler, NSAccessibilityRulerRole },
+ { blink::WebAXRoleRulerMarker, NSAccessibilityRulerMarkerRole },
// TODO(dtseng): we don't correctly support the attributes for these roles.
- // { WebKit::WebAXRoleScrollArea, NSAccessibilityScrollAreaRole },
- { WebKit::WebAXRoleScrollBar, NSAccessibilityScrollBarRole },
- { WebKit::WebAXRoleSheet, NSAccessibilitySheetRole },
- { WebKit::WebAXRoleSlider, NSAccessibilitySliderRole },
- { WebKit::WebAXRoleSliderThumb, NSAccessibilityValueIndicatorRole },
- { WebKit::WebAXRoleSpinButton, NSAccessibilitySliderRole },
- { WebKit::WebAXRoleSplitter, NSAccessibilitySplitterRole },
- { WebKit::WebAXRoleSplitGroup, NSAccessibilitySplitGroupRole },
- { WebKit::WebAXRoleStaticText, NSAccessibilityStaticTextRole },
- { WebKit::WebAXRoleStatus, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleSVGRoot, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleSystemWide, NSAccessibilityUnknownRole },
- { WebKit::WebAXRoleTab, NSAccessibilityRadioButtonRole },
- { WebKit::WebAXRoleTabList, NSAccessibilityTabGroupRole },
- { WebKit::WebAXRoleTabPanel, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleTable, NSAccessibilityTableRole },
- { WebKit::WebAXRoleTableHeaderContainer, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleTextArea, NSAccessibilityTextAreaRole },
- { WebKit::WebAXRoleTextField, NSAccessibilityTextFieldRole },
- { WebKit::WebAXRoleTimer, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleToggleButton, NSAccessibilityButtonRole },
- { WebKit::WebAXRoleToolbar, NSAccessibilityToolbarRole },
- { WebKit::WebAXRoleUserInterfaceTooltip, NSAccessibilityGroupRole },
- { WebKit::WebAXRoleTree, NSAccessibilityOutlineRole },
- { WebKit::WebAXRoleTreeGrid, NSAccessibilityTableRole },
- { WebKit::WebAXRoleTreeItem, NSAccessibilityRowRole },
- { WebKit::WebAXRoleValueIndicator, NSAccessibilityValueIndicatorRole },
- { WebKit::WebAXRoleLink, NSAccessibilityLinkRole },
- { WebKit::WebAXRoleWebArea, @"AXWebArea" },
- { WebKit::WebAXRoleWindow, NSAccessibilityWindowRole },
+ // { blink::WebAXRoleScrollArea, NSAccessibilityScrollAreaRole },
+ { blink::WebAXRoleScrollBar, NSAccessibilityScrollBarRole },
+ { blink::WebAXRoleSheet, NSAccessibilitySheetRole },
+ { blink::WebAXRoleSlider, NSAccessibilitySliderRole },
+ { blink::WebAXRoleSliderThumb, NSAccessibilityValueIndicatorRole },
+ { blink::WebAXRoleSpinButton, NSAccessibilitySliderRole },
+ { blink::WebAXRoleSplitter, NSAccessibilitySplitterRole },
+ { blink::WebAXRoleSplitGroup, NSAccessibilitySplitGroupRole },
+ { blink::WebAXRoleStaticText, NSAccessibilityStaticTextRole },
+ { blink::WebAXRoleStatus, NSAccessibilityGroupRole },
+ { blink::WebAXRoleSVGRoot, NSAccessibilityGroupRole },
+ { blink::WebAXRoleSystemWide, NSAccessibilityUnknownRole },
+ { blink::WebAXRoleTab, NSAccessibilityRadioButtonRole },
+ { blink::WebAXRoleTabList, NSAccessibilityTabGroupRole },
+ { blink::WebAXRoleTabPanel, NSAccessibilityGroupRole },
+ { blink::WebAXRoleTable, NSAccessibilityTableRole },
+ { blink::WebAXRoleTableHeaderContainer, NSAccessibilityGroupRole },
+ { blink::WebAXRoleTextArea, NSAccessibilityTextAreaRole },
+ { blink::WebAXRoleTextField, NSAccessibilityTextFieldRole },
+ { blink::WebAXRoleTimer, NSAccessibilityGroupRole },
+ { blink::WebAXRoleToggleButton, NSAccessibilityButtonRole },
+ { blink::WebAXRoleToolbar, NSAccessibilityToolbarRole },
+ { blink::WebAXRoleUserInterfaceTooltip, NSAccessibilityGroupRole },
+ { blink::WebAXRoleTree, NSAccessibilityOutlineRole },
+ { blink::WebAXRoleTreeGrid, NSAccessibilityTableRole },
+ { blink::WebAXRoleTreeItem, NSAccessibilityRowRole },
+ { blink::WebAXRoleValueIndicator, NSAccessibilityValueIndicatorRole },
+ { blink::WebAXRoleLink, NSAccessibilityLinkRole },
+ { blink::WebAXRoleWebArea, @"AXWebArea" },
+ { blink::WebAXRoleWindow, NSAccessibilityWindowRole },
};
RoleMap role_map;
@@ -173,7 +173,7 @@ RoleMap BuildRoleMap() {
// A mapping of webkit roles to native roles.
NSString* NativeRoleFromAccessibilityNodeDataRole(
- const WebKit::WebAXRole& role) {
+ const blink::WebAXRole& role) {
CR_DEFINE_STATIC_LOCAL(RoleMap, web_accessibility_to_native_role,
(BuildRoleMap()));
RoleMap::iterator it = web_accessibility_to_native_role.find(role);
@@ -185,32 +185,32 @@ NSString* NativeRoleFromAccessibilityNodeDataRole(
RoleMap BuildSubroleMap() {
const MapEntry subroles[] = {
- { WebKit::WebAXRoleAlert, @"AXApplicationAlert" },
- { WebKit::WebAXRoleAlertDialog, @"AXApplicationAlertDialog" },
- { WebKit::WebAXRoleArticle, @"AXDocumentArticle" },
- { WebKit::WebAXRoleDefinition, @"AXDefinition" },
- { WebKit::WebAXRoleDescriptionListDetail, @"AXDescription" },
- { WebKit::WebAXRoleDescriptionListTerm, @"AXTerm" },
- { WebKit::WebAXRoleDialog, @"AXApplicationDialog" },
- { WebKit::WebAXRoleDocument, @"AXDocument" },
- { WebKit::WebAXRoleFooter, @"AXLandmarkContentInfo" },
- { WebKit::WebAXRoleApplication, @"AXLandmarkApplication" },
- { WebKit::WebAXRoleBanner, @"AXLandmarkBanner" },
- { WebKit::WebAXRoleComplementary, @"AXLandmarkComplementary" },
- { WebKit::WebAXRoleContentInfo, @"AXLandmarkContentInfo" },
- { WebKit::WebAXRoleMain, @"AXLandmarkMain" },
- { WebKit::WebAXRoleNavigation, @"AXLandmarkNavigation" },
- { WebKit::WebAXRoleSearch, @"AXLandmarkSearch" },
- { WebKit::WebAXRoleLog, @"AXApplicationLog" },
- { WebKit::WebAXRoleMarquee, @"AXApplicationMarquee" },
- { WebKit::WebAXRoleMath, @"AXDocumentMath" },
- { WebKit::WebAXRoleNote, @"AXDocumentNote" },
- { WebKit::WebAXRoleRegion, @"AXDocumentRegion" },
- { WebKit::WebAXRoleStatus, @"AXApplicationStatus" },
- { WebKit::WebAXRoleTabPanel, @"AXTabPanel" },
- { WebKit::WebAXRoleTimer, @"AXApplicationTimer" },
- { WebKit::WebAXRoleUserInterfaceTooltip, @"AXUserInterfaceTooltip" },
- { WebKit::WebAXRoleTreeItem, NSAccessibilityOutlineRowSubrole },
+ { blink::WebAXRoleAlert, @"AXApplicationAlert" },
+ { blink::WebAXRoleAlertDialog, @"AXApplicationAlertDialog" },
+ { blink::WebAXRoleArticle, @"AXDocumentArticle" },
+ { blink::WebAXRoleDefinition, @"AXDefinition" },
+ { blink::WebAXRoleDescriptionListDetail, @"AXDescription" },
+ { blink::WebAXRoleDescriptionListTerm, @"AXTerm" },
+ { blink::WebAXRoleDialog, @"AXApplicationDialog" },
+ { blink::WebAXRoleDocument, @"AXDocument" },
+ { blink::WebAXRoleFooter, @"AXLandmarkContentInfo" },
+ { blink::WebAXRoleApplication, @"AXLandmarkApplication" },
+ { blink::WebAXRoleBanner, @"AXLandmarkBanner" },
+ { blink::WebAXRoleComplementary, @"AXLandmarkComplementary" },
+ { blink::WebAXRoleContentInfo, @"AXLandmarkContentInfo" },
+ { blink::WebAXRoleMain, @"AXLandmarkMain" },
+ { blink::WebAXRoleNavigation, @"AXLandmarkNavigation" },
+ { blink::WebAXRoleSearch, @"AXLandmarkSearch" },
+ { blink::WebAXRoleLog, @"AXApplicationLog" },
+ { blink::WebAXRoleMarquee, @"AXApplicationMarquee" },
+ { blink::WebAXRoleMath, @"AXDocumentMath" },
+ { blink::WebAXRoleNote, @"AXDocumentNote" },
+ { blink::WebAXRoleRegion, @"AXDocumentRegion" },
+ { blink::WebAXRoleStatus, @"AXApplicationStatus" },
+ { blink::WebAXRoleTabPanel, @"AXTabPanel" },
+ { blink::WebAXRoleTimer, @"AXApplicationTimer" },
+ { blink::WebAXRoleUserInterfaceTooltip, @"AXUserInterfaceTooltip" },
+ { blink::WebAXRoleTreeItem, NSAccessibilityOutlineRowSubrole },
};
RoleMap subrole_map;
@@ -221,7 +221,7 @@ RoleMap BuildSubroleMap() {
// A mapping of webkit roles to native subroles.
NSString* NativeSubroleFromAccessibilityNodeDataRole(
- const WebKit::WebAXRole& role) {
+ const blink::WebAXRole& role) {
CR_DEFINE_STATIC_LOCAL(RoleMap, web_accessibility_to_native_subrole,
(BuildSubroleMap()));
RoleMap::iterator it = web_accessibility_to_native_subrole.find(role);
@@ -353,13 +353,12 @@ NSDictionary* attributeToMethodNameMap = nil;
// accessibility children of this object.
- (NSArray*)children {
if (!children_) {
- children_.reset([[NSMutableArray alloc]
- initWithCapacity:browserAccessibility_->child_count()] );
- for (uint32 index = 0;
- index < browserAccessibility_->child_count();
- ++index) {
+ uint32 childCount = browserAccessibility_->PlatformChildCount();
+ children_.reset([[NSMutableArray alloc] initWithCapacity:childCount]);
+ for (uint32 index = 0; index < childCount; ++index) {
BrowserAccessibilityCocoa* child =
- browserAccessibility_->GetChild(index)->ToBrowserAccessibilityCocoa();
+ browserAccessibility_->PlatformGetChild(index)->
+ ToBrowserAccessibilityCocoa();
if ([child isIgnored])
[children_ addObjectsFromArray:[child children]];
else
@@ -397,8 +396,8 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSArray*)columnHeaders {
- if ([self internalRole] != WebKit::WebAXRoleTable &&
- [self internalRole] != WebKit::WebAXRoleGrid) {
+ if ([self internalRole] != blink::WebAXRoleTable &&
+ [self internalRole] != blink::WebAXRoleGrid) {
return nil;
}
@@ -410,14 +409,14 @@ NSDictionary* attributeToMethodNameMap = nil;
int id = uniqueCellIds[i];
BrowserAccessibility* cell =
browserAccessibility_->manager()->GetFromRendererID(id);
- if (cell && cell->role() == WebKit::WebAXRoleColumnHeader)
+ if (cell && cell->role() == blink::WebAXRoleColumnHeader)
[ret addObject:cell->ToBrowserAccessibilityCocoa()];
}
return ret;
}
- (NSValue*)columnIndexRange {
- if ([self internalRole] != WebKit::WebAXRoleCell)
+ if ([self internalRole] != blink::WebAXRoleCell)
return nil;
int column = -1;
@@ -475,9 +474,9 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSNumber*)disclosing {
- if ([self internalRole] == WebKit::WebAXRoleTreeItem) {
+ if ([self internalRole] == blink::WebAXRoleTreeItem) {
return [NSNumber numberWithBool:
- GetState(browserAccessibility_, WebKit::WebAXStateExpanded)];
+ GetState(browserAccessibility_, blink::WebAXStateExpanded)];
} else {
return nil;
}
@@ -490,9 +489,9 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSNumber*)disclosureLevel {
- WebKit::WebAXRole role = [self internalRole];
- if (role == WebKit::WebAXRoleRow ||
- role == WebKit::WebAXRoleTreeItem) {
+ blink::WebAXRole role = [self internalRole];
+ if (role == blink::WebAXRoleRow ||
+ role == blink::WebAXRoleTreeItem) {
int level = browserAccessibility_->GetIntAttribute(
AccessibilityNodeData::ATTR_HIERARCHICAL_LEVEL);
// Mac disclosureLevel is 0-based, but web levels are 1-based.
@@ -511,7 +510,7 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSNumber*)enabled {
return [NSNumber numberWithBool:
- GetState(browserAccessibility_, WebKit::WebAXStateEnabled)];
+ GetState(browserAccessibility_, blink::WebAXStateEnabled)];
}
- (NSNumber*)focused {
@@ -523,14 +522,14 @@ NSDictionary* attributeToMethodNameMap = nil;
- (id)header {
int headerElementId = -1;
- if ([self internalRole] == WebKit::WebAXRoleTable ||
- [self internalRole] == WebKit::WebAXRoleGrid) {
+ if ([self internalRole] == blink::WebAXRoleTable ||
+ [self internalRole] == blink::WebAXRoleGrid) {
browserAccessibility_->GetIntAttribute(
AccessibilityNodeData::ATTR_TABLE_HEADER_ID, &headerElementId);
- } else if ([self internalRole] == WebKit::WebAXRoleColumn) {
+ } else if ([self internalRole] == blink::WebAXRoleColumn) {
browserAccessibility_->GetIntAttribute(
AccessibilityNodeData::ATTR_TABLE_COLUMN_HEADER_ID, &headerElementId);
- } else if ([self internalRole] == WebKit::WebAXRoleRow) {
+ } else if ([self internalRole] == blink::WebAXRoleRow) {
browserAccessibility_->GetIntAttribute(
AccessibilityNodeData::ATTR_TABLE_ROW_HEADER_ID, &headerElementId);
}
@@ -550,11 +549,11 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSNumber*)index {
- if ([self internalRole] == WebKit::WebAXRoleColumn) {
+ if ([self internalRole] == blink::WebAXRoleColumn) {
int columnIndex = browserAccessibility_->GetIntAttribute(
AccessibilityNodeData::ATTR_TABLE_COLUMN_INDEX);
return [NSNumber numberWithInt:columnIndex];
- } else if ([self internalRole] == WebKit::WebAXRoleRow) {
+ } else if ([self internalRole] == blink::WebAXRoleRow) {
int rowIndex = browserAccessibility_->GetIntAttribute(
AccessibilityNodeData::ATTR_TABLE_ROW_INDEX);
return [NSNumber numberWithInt:rowIndex];
@@ -570,7 +569,7 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSString*)invalid {
- string16 invalidUTF;
+ base::string16 invalidUTF;
if (!browserAccessibility_->GetHtmlAttribute("aria-invalid", &invalidUTF))
return NULL;
NSString* invalid = base::SysUTF16ToNSString(invalidUTF);
@@ -606,10 +605,10 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSString*)orientation {
// We present a spin button as a vertical slider, with a role description
// of "spin button".
- if ([self internalRole] == WebKit::WebAXRoleSpinButton)
+ if ([self internalRole] == blink::WebAXRoleSpinButton)
return NSAccessibilityVerticalOrientationValue;
- if (GetState(browserAccessibility_, WebKit::WebAXStateVertical))
+ if (GetState(browserAccessibility_, blink::WebAXStateVertical))
return NSAccessibilityVerticalOrientationValue;
else
return NSAccessibilityHorizontalOrientationValue;
@@ -642,23 +641,27 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSValue*)position {
- return [NSValue valueWithPoint:[delegate_ accessibilityPointInScreen:self]];
+ NSPoint origin = [self origin];
+ NSSize size = [[self size] sizeValue];
+ NSPoint pointInScreen =
+ [delegate_ accessibilityPointInScreen:origin size:size];
+ return [NSValue valueWithPoint:pointInScreen];
}
- (NSNumber*)required {
return [NSNumber numberWithBool:
- GetState(browserAccessibility_, WebKit::WebAXStateRequired)];
+ GetState(browserAccessibility_, blink::WebAXStateRequired)];
}
// Returns an enum indicating the role from browserAccessibility_.
-- (WebKit::WebAXRole)internalRole {
- return static_cast<WebKit::WebAXRole>(browserAccessibility_->role());
+- (blink::WebAXRole)internalRole {
+ return static_cast<blink::WebAXRole>(browserAccessibility_->role());
}
// Returns a string indicating the NSAccessibility role of this object.
- (NSString*)role {
- WebKit::WebAXRole role = [self internalRole];
- if (role == WebKit::WebAXRoleCanvas &&
+ blink::WebAXRole role = [self internalRole];
+ if (role == blink::WebAXRoleCanvas &&
browserAccessibility_->GetBoolAttribute(
AccessibilityNodeData::ATTR_CANVAS_HAS_FALLBACK)) {
return NSAccessibilityGroupRole;
@@ -692,10 +695,10 @@ NSDictionary* attributeToMethodNameMap = nil;
[role isEqualToString:NSAccessibilityRadioButtonRole]) {
std::string role;
if (browserAccessibility_->GetHtmlAttribute("role", &role)) {
- WebKit::WebAXRole internalRole = [self internalRole];
- if ((internalRole != WebKit::WebAXRoleGroup &&
- internalRole != WebKit::WebAXRoleListItem) ||
- internalRole == WebKit::WebAXRoleTab) {
+ blink::WebAXRole internalRole = [self internalRole];
+ if ((internalRole != blink::WebAXRoleGroup &&
+ internalRole != blink::WebAXRoleListItem) ||
+ internalRole == blink::WebAXRoleTab) {
// TODO(dtseng): This is not localized; see crbug/84814.
return base::SysUTF8ToNSString(role);
}
@@ -703,10 +706,10 @@ NSDictionary* attributeToMethodNameMap = nil;
}
switch([self internalRole]) {
- case WebKit::WebAXRoleFooter:
+ case blink::WebAXRoleFooter:
return base::SysUTF16ToNSString(content_client->GetLocalizedString(
IDS_AX_ROLE_FOOTER));
- case WebKit::WebAXRoleSpinButton:
+ case blink::WebAXRoleSpinButton:
// This control is similar to what VoiceOver calls a "stepper".
return base::SysUTF16ToNSString(content_client->GetLocalizedString(
IDS_AX_ROLE_STEPPER));
@@ -718,8 +721,8 @@ NSDictionary* attributeToMethodNameMap = nil;
}
- (NSArray*)rowHeaders {
- if ([self internalRole] != WebKit::WebAXRoleTable &&
- [self internalRole] != WebKit::WebAXRoleGrid) {
+ if ([self internalRole] != blink::WebAXRoleTable &&
+ [self internalRole] != blink::WebAXRoleGrid) {
return nil;
}
@@ -731,14 +734,14 @@ NSDictionary* attributeToMethodNameMap = nil;
int id = uniqueCellIds[i];
BrowserAccessibility* cell =
browserAccessibility_->manager()->GetFromRendererID(id);
- if (cell && cell->role() == WebKit::WebAXRoleRowHeader)
+ if (cell && cell->role() == blink::WebAXRoleRowHeader)
[ret addObject:cell->ToBrowserAccessibilityCocoa()];
}
return ret;
}
- (NSValue*)rowIndexRange {
- if ([self internalRole] != WebKit::WebAXRoleCell)
+ if ([self internalRole] != blink::WebAXRoleCell)
return nil;
int row = -1;
@@ -755,13 +758,13 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSArray*)rows {
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
- if ([self internalRole] == WebKit::WebAXRoleTable||
- [self internalRole] == WebKit::WebAXRoleGrid) {
+ if ([self internalRole] == blink::WebAXRoleTable||
+ [self internalRole] == blink::WebAXRoleGrid) {
for (BrowserAccessibilityCocoa* child in [self children]) {
if ([[child role] isEqualToString:NSAccessibilityRowRole])
[ret addObject:child];
}
- } else if ([self internalRole] == WebKit::WebAXRoleColumn) {
+ } else if ([self internalRole] == blink::WebAXRoleColumn) {
const std::vector<int32>& indirectChildIds =
browserAccessibility_->GetIntListAttribute(
AccessibilityNodeData::ATTR_INDIRECT_CHILD_IDS);
@@ -785,16 +788,16 @@ NSDictionary* attributeToMethodNameMap = nil;
// Returns a subrole based upon the role.
- (NSString*) subrole {
- WebKit::WebAXRole browserAccessibilityRole = [self internalRole];
- if (browserAccessibilityRole == WebKit::WebAXRoleTextField &&
- GetState(browserAccessibility_, WebKit::WebAXStateProtected)) {
+ blink::WebAXRole browserAccessibilityRole = [self internalRole];
+ if (browserAccessibilityRole == blink::WebAXRoleTextField &&
+ GetState(browserAccessibility_, blink::WebAXStateProtected)) {
return @"AXSecureTextField";
}
NSString* htmlTag = NSStringForStringAttribute(
browserAccessibility_, AccessibilityNodeData::ATTR_HTML_TAG);
- if (browserAccessibilityRole == WebKit::WebAXRoleList) {
+ if (browserAccessibilityRole == blink::WebAXRoleList) {
if ([htmlTag isEqualToString:@"ul"] ||
[htmlTag isEqualToString:@"ol"]) {
return @"AXContentList";
@@ -810,7 +813,7 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSArray*)tabs {
NSMutableArray* tabSubtree = [[[NSMutableArray alloc] init] autorelease];
- if ([self internalRole] == WebKit::WebAXRoleTab)
+ if ([self internalRole] == blink::WebAXRoleTab)
[tabSubtree addObject:self];
for (uint i=0; i < [[self children] count]; ++i) {
@@ -865,9 +868,9 @@ NSDictionary* attributeToMethodNameMap = nil;
[role isEqualToString:NSAccessibilityRadioButtonRole]) {
int value = 0;
value = GetState(
- browserAccessibility_, WebKit::WebAXStateChecked) ? 1 : 0;
+ browserAccessibility_, blink::WebAXStateChecked) ? 1 : 0;
value = GetState(
- browserAccessibility_, WebKit::WebAXStateSelected) ?
+ browserAccessibility_, blink::WebAXStateSelected) ?
1 :
value;
@@ -935,7 +938,7 @@ NSDictionary* attributeToMethodNameMap = nil;
- (NSNumber*)visited {
return [NSNumber numberWithBool:
- GetState(browserAccessibility_, WebKit::WebAXStateVisited)];
+ GetState(browserAccessibility_, blink::WebAXStateVisited)];
}
- (id)window {
@@ -1033,8 +1036,8 @@ NSDictionary* attributeToMethodNameMap = nil;
if ([attribute isEqualToString:
NSAccessibilityCellForColumnAndRowParameterizedAttribute]) {
- if ([self internalRole] != WebKit::WebAXRoleTable &&
- [self internalRole] != WebKit::WebAXRoleGrid) {
+ if ([self internalRole] != blink::WebAXRoleTable &&
+ [self internalRole] != blink::WebAXRoleGrid) {
return nil;
}
if (![parameter isKindOfClass:[NSArray self]])
@@ -1051,10 +1054,10 @@ NSDictionary* attributeToMethodNameMap = nil;
return nil;
}
for (size_t i = 0;
- i < browserAccessibility_->child_count();
+ i < browserAccessibility_->PlatformChildCount();
++i) {
- BrowserAccessibility* child = browserAccessibility_->GetChild(i);
- if (child->role() != WebKit::WebAXRoleRow)
+ BrowserAccessibility* child = browserAccessibility_->PlatformGetChild(i);
+ if (child->role() != blink::WebAXRoleRow)
continue;
int rowIndex;
if (!child->GetIntAttribute(
@@ -1066,10 +1069,10 @@ NSDictionary* attributeToMethodNameMap = nil;
if (rowIndex > row)
break;
for (size_t j = 0;
- j < child->child_count();
+ j < child->PlatformChildCount();
++j) {
- BrowserAccessibility* cell = child->GetChild(j);
- if (cell->role() != WebKit::WebAXRoleCell)
+ BrowserAccessibility* cell = child->PlatformGetChild(j);
+ if (cell->role() != blink::WebAXRoleCell)
continue;
int colIndex;
if (!cell->GetIntAttribute(
@@ -1086,13 +1089,27 @@ NSDictionary* attributeToMethodNameMap = nil;
return nil;
}
+ if ([attribute isEqualToString:
+ NSAccessibilityBoundsForRangeParameterizedAttribute]) {
+ if ([self internalRole] != blink::WebAXRoleStaticText)
+ return nil;
+ NSRange range = [(NSValue*)parameter rangeValue];
+ gfx::Rect rect = browserAccessibility_->GetGlobalBoundsForRange(
+ range.location, range.length);
+ NSPoint origin = NSMakePoint(rect.x(), rect.y());
+ NSSize size = NSMakeSize(rect.width(), rect.height());
+ NSPoint pointInScreen =
+ [delegate_ accessibilityPointInScreen:origin size:size];
+ NSRect nsrect = NSMakeRect(
+ pointInScreen.x, pointInScreen.y, rect.width(), rect.height());
+ return [NSValue valueWithRect:nsrect];
+ }
+
// TODO(dtseng): support the following attributes.
if ([attribute isEqualTo:
NSAccessibilityRangeForPositionParameterizedAttribute] ||
[attribute isEqualTo:
NSAccessibilityRangeForIndexParameterizedAttribute] ||
- [attribute isEqualTo:
- NSAccessibilityBoundsForRangeParameterizedAttribute] ||
[attribute isEqualTo:NSAccessibilityRTFForRangeParameterizedAttribute] ||
[attribute isEqualTo:
NSAccessibilityStyleRangeForIndexParameterizedAttribute]) {
@@ -1127,6 +1144,11 @@ NSDictionary* attributeToMethodNameMap = nil;
NSAccessibilityStyleRangeForIndexParameterizedAttribute,
nil];
}
+ if ([self internalRole] == blink::WebAXRoleStaticText) {
+ return [NSArray arrayWithObjects:
+ NSAccessibilityBoundsForRangeParameterizedAttribute,
+ nil];
+ }
return nil;
}
@@ -1274,10 +1296,10 @@ NSDictionary* attributeToMethodNameMap = nil;
nil]];
} else if ([role isEqualToString:NSAccessibilityRowRole]) {
if (browserAccessibility_->parent()) {
- string16 parentRole;
+ base::string16 parentRole;
browserAccessibility_->parent()->GetHtmlAttribute(
"role", &parentRole);
- const string16 treegridRole(ASCIIToUTF16("treegrid"));
+ const base::string16 treegridRole(ASCIIToUTF16("treegrid"));
if (parentRole == treegridRole) {
[ret addObjectsFromArray:[NSArray arrayWithObjects:
NSAccessibilityDisclosingAttribute,
@@ -1342,7 +1364,7 @@ NSDictionary* attributeToMethodNameMap = nil;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute])
return GetState(browserAccessibility_,
- WebKit::WebAXStateFocusable);
+ blink::WebAXStateFocusable);
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
return browserAccessibility_->GetBoolAttribute(
AccessibilityNodeData::ATTR_CAN_SET_VALUE);
@@ -1422,6 +1444,8 @@ NSDictionary* attributeToMethodNameMap = nil;
BrowserAccessibilityCocoa* hit = self;
for (BrowserAccessibilityCocoa* child in [self children]) {
+ if (!child->browserAccessibility_)
+ continue;
NSPoint origin = [child origin];
NSSize size = [[child size] sizeValue];
NSRect rect;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_delegate_mac.h b/chromium/content/browser/accessibility/browser_accessibility_delegate_mac.h
index 8b9abff3a73..054c255e7fc 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_delegate_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_delegate_mac.h
@@ -12,7 +12,8 @@
// to, or otherwise communicate with, their underlying WebAccessibility
// objects over the IPC boundary.
@protocol BrowserAccessibilityDelegateCocoa
-- (NSPoint)accessibilityPointInScreen:(BrowserAccessibilityCocoa*)accessibility;
+- (NSPoint)accessibilityPointInScreen:(NSPoint)origin
+ size:(NSSize)size;
- (void)doDefaultAction:(int32)accessibilityObjectId;
- (void)accessibilitySetTextSelection:(int32)accId
startOffset:(int32)startOffset
diff --git a/chromium/content/browser/accessibility/browser_accessibility_gtk.cc b/chromium/content/browser/accessibility/browser_accessibility_gtk.cc
index faf4c82e307..06a164cb920 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_gtk.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_gtk.cc
@@ -208,7 +208,8 @@ static gint browser_accessibility_get_n_children(AtkObject* atk_object) {
BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object);
if (!obj)
return 0;
- return obj->children().size();
+
+ return obj->PlatformChildCount();
}
static AtkObject* browser_accessibility_ref_child(
@@ -216,6 +217,10 @@ static AtkObject* browser_accessibility_ref_child(
BrowserAccessibilityGtk* obj = ToBrowserAccessibilityGtk(atk_object);
if (!obj)
return NULL;
+
+ if (index < 0 || index >= static_cast<gint>(obj->PlatformChildCount()))
+ return NULL;
+
AtkObject* result =
obj->children()[index]->ToBrowserAccessibilityGtk()->GetAtkObject();
g_object_ref(result);
@@ -250,11 +255,11 @@ static AtkStateSet* browser_accessibility_ref_state_set(AtkObject* atk_object) {
ref_state_set(atk_object);
int32 state = obj->state();
- if (state & (1 << WebKit::WebAXStateFocusable))
+ if (state & (1 << blink::WebAXStateFocusable))
atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
if (obj->manager()->GetFocus(NULL) == obj)
atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
- if (state & (1 << WebKit::WebAXStateEnabled))
+ if (state & (1 << blink::WebAXStateEnabled))
atk_state_set_add_state(state_set, ATK_STATE_ENABLED);
return state_set;
@@ -359,9 +364,9 @@ static int GetInterfaceMaskFromObject(BrowserAccessibilityGtk* obj) {
interface_mask |= 1 << ATK_COMPONENT_INTERFACE;
int role = obj->role();
- if (role == WebKit::WebAXRoleProgressIndicator ||
- role == WebKit::WebAXRoleScrollBar ||
- role == WebKit::WebAXRoleSlider) {
+ if (role == blink::WebAXRoleProgressIndicator ||
+ role == blink::WebAXRoleScrollBar ||
+ role == blink::WebAXRoleSlider) {
interface_mask |= 1 << ATK_VALUE_INTERFACE;
}
@@ -470,38 +475,38 @@ bool BrowserAccessibilityGtk::IsNative() const {
}
void BrowserAccessibilityGtk::InitRoleAndState() {
- switch(role_) {
- case WebKit::WebAXRoleDocument:
- case WebKit::WebAXRoleRootWebArea:
- case WebKit::WebAXRoleWebArea:
+ switch(role()) {
+ case blink::WebAXRoleDocument:
+ case blink::WebAXRoleRootWebArea:
+ case blink::WebAXRoleWebArea:
atk_role_ = ATK_ROLE_DOCUMENT_WEB;
break;
- case WebKit::WebAXRoleGroup:
- case WebKit::WebAXRoleDiv:
+ case blink::WebAXRoleGroup:
+ case blink::WebAXRoleDiv:
atk_role_ = ATK_ROLE_SECTION;
break;
- case WebKit::WebAXRoleButton:
+ case blink::WebAXRoleButton:
atk_role_ = ATK_ROLE_PUSH_BUTTON;
break;
- case WebKit::WebAXRoleCheckBox:
+ case blink::WebAXRoleCheckBox:
atk_role_ = ATK_ROLE_CHECK_BOX;
break;
- case WebKit::WebAXRoleComboBox:
+ case blink::WebAXRoleComboBox:
atk_role_ = ATK_ROLE_COMBO_BOX;
break;
- case WebKit::WebAXRoleLink:
+ case blink::WebAXRoleLink:
atk_role_ = ATK_ROLE_LINK;
break;
- case WebKit::WebAXRoleRadioButton:
+ case blink::WebAXRoleRadioButton:
atk_role_ = ATK_ROLE_RADIO_BUTTON;
break;
- case WebKit::WebAXRoleStaticText:
+ case blink::WebAXRoleStaticText:
atk_role_ = ATK_ROLE_TEXT;
break;
- case WebKit::WebAXRoleTextArea:
+ case blink::WebAXRoleTextArea:
atk_role_ = ATK_ROLE_ENTRY;
break;
- case WebKit::WebAXRoleTextField:
+ case blink::WebAXRoleTextField:
atk_role_ = ATK_ROLE_ENTRY;
break;
default:
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
index d23d8e6a691..5ff0a3864f9 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
@@ -17,7 +17,8 @@
@interface MockAccessibilityDelegate :
NSView<BrowserAccessibilityDelegateCocoa>
-- (NSPoint)accessibilityPointInScreen:(BrowserAccessibilityCocoa*)accessibility;
+- (NSPoint)accessibilityPointInScreen:(NSPoint)origin
+ size:(NSSize)size;
- (void)doDefaultAction:(int32)accessibilityObjectId;
- (void)accessibilitySetTextSelection:(int32)accId
startOffset:(int32)startOffset
@@ -31,8 +32,8 @@
@implementation MockAccessibilityDelegate
-- (NSPoint)accessibilityPointInScreen:
- (BrowserAccessibilityCocoa*)accessibility {
+- (NSPoint)accessibilityPointInScreen:(NSPoint)origin
+ size:(NSSize)size {
return NSZeroPoint;
}
- (void)doDefaultAction:(int32)accessibilityObjectId {
@@ -67,7 +68,7 @@ class BrowserAccessibilityTest : public ui::CocoaTest {
root.id = 1000;
root.location.set_width(500);
root.location.set_height(100);
- root.role = WebKit::WebAXRoleRootWebArea;
+ root.role = blink::WebAXRoleRootWebArea;
root.AddStringAttribute(AccessibilityNodeData::ATTR_HELP, "HelpText");
root.child_ids.push_back(1001);
root.child_ids.push_back(1002);
@@ -77,14 +78,14 @@ class BrowserAccessibilityTest : public ui::CocoaTest {
child1.SetName("Child1");
child1.location.set_width(250);
child1.location.set_height(100);
- child1.role = WebKit::WebAXRoleButton;
+ child1.role = blink::WebAXRoleButton;
AccessibilityNodeData child2;
child2.id = 1002;
child2.location.set_x(250);
child2.location.set_width(250);
child2.location.set_height(100);
- child2.role = WebKit::WebAXRoleHeading;
+ child2.role = blink::WebAXRoleHeading;
delegate_.reset([[MockAccessibilityDelegate alloc] init]);
manager_.reset(
@@ -125,8 +126,7 @@ TEST_F(BrowserAccessibilityTest, InvalidHitTestCoordsTest) {
}
// Test to ensure querying standard attributes works.
-// http://crbug.com/173983 Test fails on Mac ASan bot
-TEST_F(BrowserAccessibilityTest, DISABLED_BasicAttributeTest) {
+TEST_F(BrowserAccessibilityTest, BasicAttributeTest) {
NSString* helpText = [accessibility_
accessibilityAttributeValue:NSAccessibilityHelpAttribute];
EXPECT_NSEQ(@"HelpText", helpText);
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index 2161fb11243..88338300c7c 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -69,7 +69,7 @@ void BrowserAccessibilityManager::Initialize(const AccessibilityNodeData src) {
AccessibilityNodeData BrowserAccessibilityManager::GetEmptyDocument() {
AccessibilityNodeData empty_document;
empty_document.id = 0;
- empty_document.role = WebKit::WebAXRoleRootWebArea;
+ empty_document.role = blink::WebAXRoleRootWebArea;
return empty_document;
}
@@ -93,7 +93,7 @@ void BrowserAccessibilityManager::GotFocus(bool touch_event_context) {
if (!focus_)
return;
- NotifyAccessibilityEvent(WebKit::WebAXEventFocus, focus_);
+ NotifyAccessibilityEvent(blink::WebAXEventFocus, focus_);
}
void BrowserAccessibilityManager::WasHidden() {
@@ -102,7 +102,7 @@ void BrowserAccessibilityManager::WasHidden() {
void BrowserAccessibilityManager::GotMouseDown() {
osk_state_ = OSK_ALLOWED_WITHIN_FOCUSED_OBJECT;
- NotifyAccessibilityEvent(WebKit::WebAXEventFocus, focus_);
+ NotifyAccessibilityEvent(blink::WebAXEventFocus, focus_);
}
bool BrowserAccessibilityManager::IsOSKAllowed(const gfx::Rect& bounds) {
@@ -126,22 +126,42 @@ void BrowserAccessibilityManager::RemoveNode(BrowserAccessibility* node) {
void BrowserAccessibilityManager::OnAccessibilityEvents(
const std::vector<AccessibilityHostMsg_EventParams>& params) {
+ bool should_send_initial_focus = false;
+
+ // Process all changes to the accessibility tree first.
for (uint32 index = 0; index < params.size(); index++) {
const AccessibilityHostMsg_EventParams& param = params[index];
-
- // Update nodes that changed.
if (!UpdateNodes(param.nodes))
return;
+ // Set initial focus when a page is loaded.
+ blink::WebAXEvent event_type = param.event_type;
+ if (event_type == blink::WebAXEventLoadComplete) {
+ if (!focus_) {
+ SetFocus(root_, false);
+ should_send_initial_focus = true;
+ }
+ }
+ }
+
+ if (should_send_initial_focus &&
+ (!delegate_ || delegate_->HasFocus())) {
+ NotifyAccessibilityEvent(blink::WebAXEventFocus, focus_);
+ }
+
+ // Now iterate over the events again and fire the events.
+ for (uint32 index = 0; index < params.size(); index++) {
+ const AccessibilityHostMsg_EventParams& param = params[index];
+
// Find the node corresponding to the id that's the target of the
// event (which may not be the root of the update tree).
BrowserAccessibility* node = GetFromRendererID(param.id);
if (!node)
continue;
- WebKit::WebAXEvent event_type = param.event_type;
- if (event_type == WebKit::WebAXEventFocus ||
- event_type == WebKit::WebAXEventBlur) {
+ blink::WebAXEvent event_type = param.event_type;
+ if (event_type == blink::WebAXEventFocus ||
+ event_type == blink::WebAXEventBlur) {
SetFocus(node, false);
if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN &&
@@ -156,14 +176,6 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
// Send the event event to the operating system.
NotifyAccessibilityEvent(event_type, node);
-
- // Set initial focus when a page is loaded.
- if (event_type == WebKit::WebAXEventLoadComplete) {
- if (!focus_)
- SetFocus(root_, false);
- if (!delegate_ || delegate_->HasFocus())
- NotifyAccessibilityEvent(WebKit::WebAXEventFocus, focus_);
- }
}
}
@@ -333,7 +345,7 @@ bool BrowserAccessibilityManager::UpdateNode(const AccessibilityNodeData& src) {
// and this is a serious error.
BrowserAccessibility* instance = GetFromRendererID(src.id);
if (!instance) {
- if (src.role != WebKit::WebAXRoleRootWebArea)
+ if (src.role != blink::WebAXRoleRootWebArea)
return false;
instance = CreateNode(NULL, src.id, 0);
}
@@ -400,7 +412,7 @@ bool BrowserAccessibilityManager::UpdateNode(const AccessibilityNodeData& src) {
instance->SwapChildren(new_children);
// Handle the case where this node is the new root of the tree.
- if (src.role == WebKit::WebAXRoleRootWebArea &&
+ if (src.role == blink::WebAXRoleRootWebArea &&
(!root_ || root_->renderer_id() != src.id)) {
if (root_)
root_->Destroy();
@@ -410,9 +422,9 @@ bool BrowserAccessibilityManager::UpdateNode(const AccessibilityNodeData& src) {
}
// Keep track of what node is focused.
- if (src.role != WebKit::WebAXRoleRootWebArea &&
- src.role != WebKit::WebAXRoleWebArea &&
- (src.state >> WebKit::WebAXStateFocused & 1)) {
+ if (src.role != blink::WebAXRoleRootWebArea &&
+ src.role != blink::WebAXRoleWebArea &&
+ (src.state >> blink::WebAXStateFocused & 1)) {
SetFocus(instance, false);
}
return success;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index 09439b2a4b5..716ee405ff5 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -19,6 +19,9 @@ struct AccessibilityHostMsg_EventParams;
namespace content {
class BrowserAccessibility;
+#if defined(OS_ANDROID)
+class BrowserAccessibilityManagerAndroid;
+#endif
#if defined(OS_WIN)
class BrowserAccessibilityManagerWin;
#endif
@@ -67,7 +70,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager {
static AccessibilityNodeData GetEmptyDocument();
virtual void NotifyAccessibilityEvent(
- WebKit::WebAXEvent event_type, BrowserAccessibility* node) { }
+ blink::WebAXEvent event_type, BrowserAccessibility* node) { }
// Return a pointer to the root of the tree, does not make a new reference.
BrowserAccessibility* GetRoot();
@@ -130,6 +133,10 @@ class CONTENT_EXPORT BrowserAccessibilityManager {
BrowserAccessibilityManagerWin* ToBrowserAccessibilityManagerWin();
#endif
+#if defined(OS_ANDROID)
+ BrowserAccessibilityManagerAndroid* ToBrowserAccessibilityManagerAndroid();
+#endif
+
// Return the object that has focus, if it's a descandant of the
// given root (inclusive). Does not make a new reference.
BrowserAccessibility* GetFocus(BrowserAccessibility* root);
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
index 2943c5cf4be..17538e9b347 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -49,19 +49,18 @@ BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
src, delegate, factory);
}
+BrowserAccessibilityManagerAndroid*
+BrowserAccessibilityManager::ToBrowserAccessibilityManagerAndroid() {
+ return static_cast<BrowserAccessibilityManagerAndroid*>(this);
+}
+
BrowserAccessibilityManagerAndroid::BrowserAccessibilityManagerAndroid(
ScopedJavaLocalRef<jobject> content_view_core,
const AccessibilityNodeData& src,
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory)
: BrowserAccessibilityManager(src, delegate, factory) {
- if (content_view_core.is_null())
- return;
-
- JNIEnv* env = AttachCurrentThread();
- java_ref_ = JavaObjectWeakGlobalRef(
- env, Java_BrowserAccessibilityManager_create(
- env, reinterpret_cast<jint>(this), content_view_core.obj()).obj());
+ SetContentViewCore(content_view_core);
}
BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() {
@@ -77,19 +76,34 @@ BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() {
AccessibilityNodeData BrowserAccessibilityManagerAndroid::GetEmptyDocument() {
AccessibilityNodeData empty_document;
empty_document.id = 0;
- empty_document.role = WebKit::WebAXRoleRootWebArea;
- empty_document.state = 1 << WebKit::WebAXStateReadonly;
+ empty_document.role = blink::WebAXRoleRootWebArea;
+ empty_document.state = 1 << blink::WebAXStateReadonly;
return empty_document;
}
+void BrowserAccessibilityManagerAndroid::SetContentViewCore(
+ ScopedJavaLocalRef<jobject> content_view_core) {
+ if (content_view_core.is_null())
+ return;
+
+ JNIEnv* env = AttachCurrentThread();
+ java_ref_ = JavaObjectWeakGlobalRef(
+ env, Java_BrowserAccessibilityManager_create(
+ env, reinterpret_cast<intptr_t>(this),
+ content_view_core.obj()).obj());
+}
+
void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
- WebKit::WebAXEvent event_type,
+ blink::WebAXEvent event_type,
BrowserAccessibility* node) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
+ if (event_type == blink::WebAXEventHide)
+ return;
+
// Always send AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED to notify
// the Android system that the accessibility hierarchy rooted at this
// node has changed.
@@ -97,26 +111,26 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
env, obj.obj(), node->renderer_id());
switch (event_type) {
- case WebKit::WebAXEventLoadComplete:
+ case blink::WebAXEventLoadComplete:
Java_BrowserAccessibilityManager_handlePageLoaded(
env, obj.obj(), focus_->renderer_id());
break;
- case WebKit::WebAXEventFocus:
+ case blink::WebAXEventFocus:
Java_BrowserAccessibilityManager_handleFocusChanged(
env, obj.obj(), node->renderer_id());
break;
- case WebKit::WebAXEventCheckedStateChanged:
+ case blink::WebAXEventCheckedStateChanged:
Java_BrowserAccessibilityManager_handleCheckStateChanged(
env, obj.obj(), node->renderer_id());
break;
- case WebKit::WebAXEventScrolledToAnchor:
+ case blink::WebAXEventScrolledToAnchor:
Java_BrowserAccessibilityManager_handleScrolledToAnchor(
env, obj.obj(), node->renderer_id());
break;
- case WebKit::WebAXEventAlert:
+ case blink::WebAXEventAlert:
// An alert is a special case of live region. Fall through to the
// next case to handle it.
- case WebKit::WebAXEventShow: {
+ case blink::WebAXEventShow: {
// This event is fired when an object appears in a live region.
// Speak its text.
BrowserAccessibilityAndroid* android_node =
@@ -127,13 +141,13 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
env, android_node->GetText()).obj());
break;
}
- case WebKit::WebAXEventSelectedTextChanged:
+ case blink::WebAXEventSelectedTextChanged:
Java_BrowserAccessibilityManager_handleTextSelectionChanged(
env, obj.obj(), node->renderer_id());
break;
- case WebKit::WebAXEventChildrenChanged:
- case WebKit::WebAXEventTextChanged:
- case WebKit::WebAXEventValueChanged:
+ case blink::WebAXEventChildrenChanged:
+ case blink::WebAXEventTextChanged:
+ case blink::WebAXEventValueChanged:
if (node->IsEditableText()) {
Java_BrowserAccessibilityManager_handleEditableTextChanged(
env, obj.obj(), node->renderer_id());
@@ -150,6 +164,11 @@ jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) {
return static_cast<jint>(root_->renderer_id());
}
+jboolean BrowserAccessibilityManagerAndroid::IsNodeValid(
+ JNIEnv* env, jobject obj, jint id) {
+ return GetFromRendererID(id) != NULL;
+}
+
jint BrowserAccessibilityManagerAndroid::HitTest(
JNIEnv* env, jobject obj, jint x, jint y) {
BrowserAccessibilityAndroid* result =
@@ -182,11 +201,9 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
Java_BrowserAccessibilityManager_setAccessibilityNodeInfoParent(
env, obj, info, node->parent()->renderer_id());
}
- if (!node->IsLeaf()) {
- for (unsigned i = 0; i < node->child_count(); ++i) {
- Java_BrowserAccessibilityManager_addAccessibilityNodeInfoChild(
- env, obj, info, node->children()[i]->renderer_id());
- }
+ for (unsigned i = 0; i < node->PlatformChildCount(); ++i) {
+ Java_BrowserAccessibilityManager_addAccessibilityNodeInfoChild(
+ env, obj, info, node->children()[i]->renderer_id());
}
Java_BrowserAccessibilityManager_setAccessibilityNodeInfoBooleanAttributes(
env, obj, info,
@@ -220,6 +237,40 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
absolute_rect.width(), absolute_rect.height(),
is_root);
+ // New KitKat APIs
+ Java_BrowserAccessibilityManager_setAccessibilityNodeInfoKitKatAttributes(
+ env, obj, info,
+ node->CanOpenPopup(),
+ node->IsContentInvalid(),
+ node->IsDismissable(),
+ node->IsMultiLine(),
+ node->AndroidInputType(),
+ node->AndroidLiveRegionType());
+ if (node->IsCollection()) {
+ Java_BrowserAccessibilityManager_setAccessibilityNodeInfoCollectionInfo(
+ env, obj, info,
+ node->RowCount(),
+ node->ColumnCount(),
+ node->IsHierarchical());
+ }
+ if (node->IsCollectionItem() || node->IsHeading()) {
+ Java_BrowserAccessibilityManager_setAccessibilityNodeInfoCollectionItemInfo(
+ env, obj, info,
+ node->RowIndex(),
+ node->RowSpan(),
+ node->ColumnIndex(),
+ node->ColumnSpan(),
+ node->IsHeading());
+ }
+ if (node->IsRangeType()) {
+ Java_BrowserAccessibilityManager_setAccessibilityNodeInfoRangeInfo(
+ env, obj, info,
+ node->AndroidRangeType(),
+ node->RangeMin(),
+ node->RangeMax(),
+ node->RangeCurrentValue());
+ }
+
return true;
}
@@ -273,6 +324,40 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityEvent(
break;
}
+ // Backwards-compatible fallback for new KitKat APIs.
+ Java_BrowserAccessibilityManager_setAccessibilityEventKitKatAttributes(
+ env, obj, event,
+ node->CanOpenPopup(),
+ node->IsContentInvalid(),
+ node->IsDismissable(),
+ node->IsMultiLine(),
+ node->AndroidInputType(),
+ node->AndroidLiveRegionType());
+ if (node->IsCollection()) {
+ Java_BrowserAccessibilityManager_setAccessibilityEventCollectionInfo(
+ env, obj, event,
+ node->RowCount(),
+ node->ColumnCount(),
+ node->IsHierarchical());
+ }
+ if (node->IsCollectionItem() || node->IsHeading()) {
+ Java_BrowserAccessibilityManager_setAccessibilityEventCollectionItemInfo(
+ env, obj, event,
+ node->RowIndex(),
+ node->RowSpan(),
+ node->ColumnIndex(),
+ node->ColumnSpan(),
+ node->IsHeading());
+ }
+ if (node->IsRangeType()) {
+ Java_BrowserAccessibilityManager_setAccessibilityEventRangeInfo(
+ env, obj, event,
+ node->AndroidRangeType(),
+ node->RangeMin(),
+ node->RangeMax(),
+ node->RangeCurrentValue());
+ }
+
return true;
}
@@ -328,11 +413,9 @@ void BrowserAccessibilityManagerAndroid::FuzzyHitTestImpl(
return;
}
- if (!node->IsLeaf()) {
- for (uint32 i = 0; i < node->child_count(); i++) {
- BrowserAccessibility* child = node->GetChild(i);
- FuzzyHitTestImpl(x, y, child, nearest_candidate, nearest_distance);
- }
+ for (uint32 i = 0; i < node->PlatformChildCount(); i++) {
+ BrowserAccessibility* child = node->PlatformGetChild(i);
+ FuzzyHitTestImpl(x, y, child, nearest_candidate, nearest_distance);
}
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
index 056fe8dff6f..6a9f38d8fb8 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -29,9 +29,12 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
static AccessibilityNodeData GetEmptyDocument();
+ void SetContentViewCore(
+ base::android::ScopedJavaLocalRef<jobject> content_view_core);
+
// Implementation of BrowserAccessibilityManager.
virtual void NotifyAccessibilityEvent(
- WebKit::WebAXEvent event_type, BrowserAccessibility* node) OVERRIDE;
+ blink::WebAXEvent event_type, BrowserAccessibility* node) OVERRIDE;
// --------------------------------------------------------------------------
// Methods called from Java via JNI
@@ -39,6 +42,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
// Tree methods.
jint GetRootId(JNIEnv* env, jobject obj);
+ jboolean IsNodeValid(JNIEnv* env, jobject obj, jint id);
jint HitTest(JNIEnv* env, jobject obj, jint x, jint y);
// Populate Java accessibility data structures with info about a node.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.cc
index a6246c5e795..e97f8b2635b 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.cc
@@ -38,29 +38,27 @@ BrowserAccessibilityManagerGtk::~BrowserAccessibilityManagerGtk() {
AccessibilityNodeData BrowserAccessibilityManagerGtk::GetEmptyDocument() {
AccessibilityNodeData empty_document;
empty_document.id = 0;
- empty_document.role = WebKit::WebAXRoleRootWebArea;
+ empty_document.role = blink::WebAXRoleRootWebArea;
empty_document.state =
- 1 << WebKit::WebAXStateReadonly;
+ 1 << blink::WebAXStateReadonly;
return empty_document;
}
void BrowserAccessibilityManagerGtk::NotifyAccessibilityEvent(
- WebKit::WebAXEvent event_type,
+ blink::WebAXEvent event_type,
BrowserAccessibility* node) {
if (!node->IsNative())
return;
AtkObject* atk_object = node->ToBrowserAccessibilityGtk()->GetAtkObject();
switch (event_type) {
- case WebKit::WebAXEventChildrenChanged:
+ case blink::WebAXEventChildrenChanged:
RecursivelySendChildrenChanged(GetRoot()->ToBrowserAccessibilityGtk());
break;
- case WebKit::WebAXEventFocus:
- // Note: atk_focus_tracker_notify may be deprecated in the future;
- // follow this bug for the replacement:
- // https://bugzilla.gnome.org/show_bug.cgi?id=649575#c4
+ case blink::WebAXEventFocus:
+ // Note: the focus-event was deprecated in ATK 2.9.4
+ // See https://bugzilla.gnome.org/show_bug.cgi?id=649575#c8
g_signal_emit_by_name(atk_object, "focus-event", true);
- atk_focus_tracker_notify(atk_object);
break;
default:
break;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.h b/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.h
index 4c29d8d7955..97d99d36f7b 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_gtk.h
@@ -28,7 +28,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerGtk
// BrowserAccessibilityManager methods
virtual void NotifyAccessibilityEvent(
- WebKit::WebAXEvent event_type, BrowserAccessibility* node) OVERRIDE;
+ blink::WebAXEvent event_type, BrowserAccessibility* node) OVERRIDE;
GtkWidget* parent_widget() { return parent_widget_; }
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
index 70ca4192a38..3b00f051121 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -24,7 +24,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
// Implementation of BrowserAccessibilityManager.
virtual void NotifyAccessibilityEvent(
- WebKit::WebAXEvent event_type, BrowserAccessibility* node) OVERRIDE;
+ blink::WebAXEvent event_type, BrowserAccessibility* node) OVERRIDE;
NSView* parent_view() { return parent_view_; }
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 1abf5fc5611..8f07f31959f 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -31,14 +31,14 @@ BrowserAccessibilityManagerMac::BrowserAccessibilityManagerMac(
AccessibilityNodeData BrowserAccessibilityManagerMac::GetEmptyDocument() {
AccessibilityNodeData empty_document;
empty_document.id = 0;
- empty_document.role = WebKit::WebAXRoleRootWebArea;
+ empty_document.role = blink::WebAXRoleRootWebArea;
empty_document.state =
- 1 << WebKit::WebAXStateReadonly;
+ 1 << blink::WebAXStateReadonly;
return empty_document;
}
void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
- WebKit::WebAXEvent event_type,
+ blink::WebAXEvent event_type,
BrowserAccessibility* node) {
if (!node->IsNative())
return;
@@ -46,88 +46,88 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
// Refer to AXObjectCache.mm (webkit).
NSString* event_id = @"";
switch (event_type) {
- case WebKit::WebAXEventActiveDescendantChanged:
- if (node->role() == WebKit::WebAXRoleTree)
+ case blink::WebAXEventActiveDescendantChanged:
+ if (node->role() == blink::WebAXRoleTree)
event_id = NSAccessibilitySelectedRowsChangedNotification;
else
event_id = NSAccessibilityFocusedUIElementChangedNotification;
break;
- case WebKit::WebAXEventAlert:
+ case blink::WebAXEventAlert:
// Not used on Mac.
return;
- case WebKit::WebAXEventBlur:
+ case blink::WebAXEventBlur:
// A no-op on Mac.
return;
- case WebKit::WebAXEventCheckedStateChanged:
+ case blink::WebAXEventCheckedStateChanged:
// Not used on Mac.
return;
- case WebKit::WebAXEventChildrenChanged:
+ case blink::WebAXEventChildrenChanged:
// TODO(dtseng): no clear equivalent on Mac.
return;
- case WebKit::WebAXEventFocus:
+ case blink::WebAXEventFocus:
event_id = NSAccessibilityFocusedUIElementChangedNotification;
break;
- case WebKit::WebAXEventLayoutComplete:
+ case blink::WebAXEventLayoutComplete:
event_id = @"AXLayoutComplete";
break;
- case WebKit::WebAXEventLiveRegionChanged:
+ case blink::WebAXEventLiveRegionChanged:
event_id = @"AXLiveRegionChanged";
break;
- case WebKit::WebAXEventLoadComplete:
+ case blink::WebAXEventLoadComplete:
event_id = @"AXLoadComplete";
break;
- case WebKit::WebAXEventMenuListValueChanged:
+ case blink::WebAXEventMenuListValueChanged:
// Not used on Mac.
return;
- case WebKit::WebAXEventShow:
+ case blink::WebAXEventShow:
// Not used on Mac.
return;
- case WebKit::WebAXEventHide:
+ case blink::WebAXEventHide:
// Not used on Mac.
return;
- case WebKit::WebAXEventRowCountChanged:
+ case blink::WebAXEventRowCountChanged:
event_id = NSAccessibilityRowCountChangedNotification;
break;
- case WebKit::WebAXEventRowCollapsed:
+ case blink::WebAXEventRowCollapsed:
event_id = @"AXRowCollapsed";
break;
- case WebKit::WebAXEventRowExpanded:
+ case blink::WebAXEventRowExpanded:
event_id = @"AXRowExpanded";
break;
- case WebKit::WebAXEventScrolledToAnchor:
+ case blink::WebAXEventScrolledToAnchor:
// Not used on Mac.
return;
- case WebKit::WebAXEventSelectedChildrenChanged:
+ case blink::WebAXEventSelectedChildrenChanged:
event_id = NSAccessibilitySelectedChildrenChangedNotification;
break;
- case WebKit::WebAXEventSelectedTextChanged:
+ case blink::WebAXEventSelectedTextChanged:
event_id = NSAccessibilitySelectedTextChangedNotification;
break;
- case WebKit::WebAXEventTextInserted:
+ case blink::WebAXEventTextInserted:
// Not used on Mac.
return;
- case WebKit::WebAXEventTextRemoved:
+ case blink::WebAXEventTextRemoved:
// Not used on Mac.
return;
- case WebKit::WebAXEventValueChanged:
+ case blink::WebAXEventValueChanged:
event_id = NSAccessibilityValueChangedNotification;
break;
- case WebKit::WebAXEventAriaAttributeChanged:
+ case blink::WebAXEventAriaAttributeChanged:
// Not used on Mac.
return;
- case WebKit::WebAXEventAutocorrectionOccured:
+ case blink::WebAXEventAutocorrectionOccured:
// Not used on Mac.
return;
- case WebKit::WebAXEventInvalidStatusChanged:
+ case blink::WebAXEventInvalidStatusChanged:
// Not used on Mac.
return;
- case WebKit::WebAXEventLocationChanged:
+ case blink::WebAXEventLocationChanged:
// Not used on Mac.
return;
- case WebKit::WebAXEventMenuListItemSelected:
+ case blink::WebAXEventMenuListItemSelected:
// Not used on Mac.
return;
- case WebKit::WebAXEventTextChanged:
+ case blink::WebAXEventTextChanged:
// Not used on Mac.
return;
default:
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
index d6a9f554c8f..b0d48363989 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -93,19 +93,19 @@ TEST(BrowserAccessibilityManagerTest, TestNoLeaks) {
AccessibilityNodeData button;
button.id = 2;
button.SetName("Button");
- button.role = WebKit::WebAXRoleButton;
+ button.role = blink::WebAXRoleButton;
button.state = 0;
AccessibilityNodeData checkbox;
checkbox.id = 3;
checkbox.SetName("Checkbox");
- checkbox.role = WebKit::WebAXRoleCheckBox;
+ checkbox.role = blink::WebAXRoleCheckBox;
checkbox.state = 0;
AccessibilityNodeData root;
root.id = 1;
root.SetName("Document");
- root.role = WebKit::WebAXRoleRootWebArea;
+ root.role = blink::WebAXRoleRootWebArea;
root.state = 0;
root.child_ids.push_back(2);
root.child_ids.push_back(3);
@@ -142,7 +142,8 @@ TEST(BrowserAccessibilityManagerTest, TestNoLeaks) {
static_cast<CountedBrowserAccessibility*>(manager->GetRoot());
root_accessible->NativeAddReference();
CountedBrowserAccessibility* child1_accessible =
- static_cast<CountedBrowserAccessibility*>(root_accessible->GetChild(1));
+ static_cast<CountedBrowserAccessibility*>(
+ root_accessible->PlatformGetChild(1));
child1_accessible->NativeAddReference();
// Now delete the manager, and only one of the three nodes in the tree
@@ -171,25 +172,25 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) {
AccessibilityNodeData tree1_child1;
tree1_child1.id = 2;
tree1_child1.SetName("Child1");
- tree1_child1.role = WebKit::WebAXRoleButton;
+ tree1_child1.role = blink::WebAXRoleButton;
tree1_child1.state = 0;
AccessibilityNodeData tree1_child2;
tree1_child2.id = 3;
tree1_child2.SetName("Child2");
- tree1_child2.role = WebKit::WebAXRoleButton;
+ tree1_child2.role = blink::WebAXRoleButton;
tree1_child2.state = 0;
AccessibilityNodeData tree1_child3;
tree1_child3.id = 4;
tree1_child3.SetName("Child3");
- tree1_child3.role = WebKit::WebAXRoleButton;
+ tree1_child3.role = blink::WebAXRoleButton;
tree1_child3.state = 0;
AccessibilityNodeData tree1_root;
tree1_root.id = 1;
tree1_root.SetName("Document");
- tree1_root.role = WebKit::WebAXRoleRootWebArea;
+ tree1_root.role = blink::WebAXRoleRootWebArea;
tree1_root.state = 0;
tree1_root.child_ids.push_back(2);
tree1_root.child_ids.push_back(3);
@@ -206,13 +207,13 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) {
AccessibilityNodeData tree2_child0;
tree2_child0.id = 5;
tree2_child0.SetName("Child0");
- tree2_child0.role = WebKit::WebAXRoleButton;
+ tree2_child0.role = blink::WebAXRoleButton;
tree2_child0.state = 0;
AccessibilityNodeData tree2_root;
tree2_root.id = 1;
tree2_root.SetName("DocumentChanged");
- tree2_root.role = WebKit::WebAXRoleRootWebArea;
+ tree2_root.role = blink::WebAXRoleRootWebArea;
tree2_root.state = 0;
tree2_root.child_ids.push_back(5);
tree2_root.child_ids.push_back(2);
@@ -233,13 +234,16 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) {
static_cast<CountedBrowserAccessibility*>(manager->GetRoot());
root_accessible->NativeAddReference();
CountedBrowserAccessibility* child1_accessible =
- static_cast<CountedBrowserAccessibility*>(root_accessible->GetChild(0));
+ static_cast<CountedBrowserAccessibility*>(
+ root_accessible->PlatformGetChild(0));
child1_accessible->NativeAddReference();
CountedBrowserAccessibility* child2_accessible =
- static_cast<CountedBrowserAccessibility*>(root_accessible->GetChild(1));
+ static_cast<CountedBrowserAccessibility*>(
+ root_accessible->PlatformGetChild(1));
child2_accessible->NativeAddReference();
CountedBrowserAccessibility* child3_accessible =
- static_cast<CountedBrowserAccessibility*>(root_accessible->GetChild(2));
+ static_cast<CountedBrowserAccessibility*>(
+ root_accessible->PlatformGetChild(2));
child3_accessible->NativeAddReference();
// Check the index in parent.
@@ -251,7 +255,7 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) {
std::vector<AccessibilityHostMsg_EventParams> params;
params.push_back(AccessibilityHostMsg_EventParams());
AccessibilityHostMsg_EventParams* msg = &params[0];
- msg->event_type = WebKit::WebAXEventChildrenChanged;
+ msg->event_type = blink::WebAXEventChildrenChanged;
msg->nodes.push_back(tree2_root);
msg->nodes.push_back(tree2_child0);
msg->id = tree2_root.id;
@@ -303,46 +307,46 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
AccessibilityNodeData tree1_grandchild1;
tree1_grandchild1.id = 4;
tree1_grandchild1.SetName("GrandChild1");
- tree1_grandchild1.role = WebKit::WebAXRoleButton;
+ tree1_grandchild1.role = blink::WebAXRoleButton;
tree1_grandchild1.state = 0;
AccessibilityNodeData tree1_child1;
tree1_child1.id = 3;
tree1_child1.SetName("Child1");
- tree1_child1.role = WebKit::WebAXRoleButton;
+ tree1_child1.role = blink::WebAXRoleButton;
tree1_child1.state = 0;
tree1_child1.child_ids.push_back(4);
AccessibilityNodeData tree1_grandchild2;
tree1_grandchild2.id = 6;
tree1_grandchild2.SetName("GrandChild1");
- tree1_grandchild2.role = WebKit::WebAXRoleButton;
+ tree1_grandchild2.role = blink::WebAXRoleButton;
tree1_grandchild2.state = 0;
AccessibilityNodeData tree1_child2;
tree1_child2.id = 5;
tree1_child2.SetName("Child2");
- tree1_child2.role = WebKit::WebAXRoleButton;
+ tree1_child2.role = blink::WebAXRoleButton;
tree1_child2.state = 0;
tree1_child2.child_ids.push_back(6);
AccessibilityNodeData tree1_grandchild3;
tree1_grandchild3.id = 8;
tree1_grandchild3.SetName("GrandChild3");
- tree1_grandchild3.role = WebKit::WebAXRoleButton;
+ tree1_grandchild3.role = blink::WebAXRoleButton;
tree1_grandchild3.state = 0;
AccessibilityNodeData tree1_child3;
tree1_child3.id = 7;
tree1_child3.SetName("Child3");
- tree1_child3.role = WebKit::WebAXRoleButton;
+ tree1_child3.role = blink::WebAXRoleButton;
tree1_child3.state = 0;
tree1_child3.child_ids.push_back(8);
AccessibilityNodeData tree1_container;
tree1_container.id = 2;
tree1_container.SetName("Container");
- tree1_container.role = WebKit::WebAXRoleGroup;
+ tree1_container.role = blink::WebAXRoleGroup;
tree1_container.state = 0;
tree1_container.child_ids.push_back(3);
tree1_container.child_ids.push_back(5);
@@ -351,7 +355,7 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
AccessibilityNodeData tree1_root;
tree1_root.id = 1;
tree1_root.SetName("Document");
- tree1_root.role = WebKit::WebAXRoleRootWebArea;
+ tree1_root.role = blink::WebAXRoleRootWebArea;
tree1_root.state = 0;
tree1_root.child_ids.push_back(2);
@@ -370,20 +374,20 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
AccessibilityNodeData tree2_grandchild0;
tree2_grandchild0.id = 9;
tree2_grandchild0.SetName("GrandChild0");
- tree2_grandchild0.role = WebKit::WebAXRoleButton;
+ tree2_grandchild0.role = blink::WebAXRoleButton;
tree2_grandchild0.state = 0;
AccessibilityNodeData tree2_child0;
tree2_child0.id = 10;
tree2_child0.SetName("Child0");
- tree2_child0.role = WebKit::WebAXRoleButton;
+ tree2_child0.role = blink::WebAXRoleButton;
tree2_child0.state = 0;
tree2_child0.child_ids.push_back(9);
AccessibilityNodeData tree2_container;
tree2_container.id = 2;
tree2_container.SetName("Container");
- tree2_container.role = WebKit::WebAXRoleGroup;
+ tree2_container.role = blink::WebAXRoleGroup;
tree2_container.state = 0;
tree2_container.child_ids.push_back(10);
tree2_container.child_ids.push_back(3);
@@ -407,15 +411,16 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
static_cast<CountedBrowserAccessibility*>(manager->GetRoot());
root_accessible->NativeAddReference();
CountedBrowserAccessibility* container_accessible =
- static_cast<CountedBrowserAccessibility*>(root_accessible->GetChild(0));
+ static_cast<CountedBrowserAccessibility*>(
+ root_accessible->PlatformGetChild(0));
container_accessible->NativeAddReference();
CountedBrowserAccessibility* child2_accessible =
static_cast<CountedBrowserAccessibility*>(
- container_accessible->GetChild(1));
+ container_accessible->PlatformGetChild(1));
child2_accessible->NativeAddReference();
CountedBrowserAccessibility* child3_accessible =
static_cast<CountedBrowserAccessibility*>(
- container_accessible->GetChild(2));
+ container_accessible->PlatformGetChild(2));
child3_accessible->NativeAddReference();
// Check the index in parent.
@@ -427,7 +432,7 @@ TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) {
std::vector<AccessibilityHostMsg_EventParams> params;
params.push_back(AccessibilityHostMsg_EventParams());
AccessibilityHostMsg_EventParams* msg = &params[0];
- msg->event_type = WebKit::WebAXEventChildrenChanged;
+ msg->event_type = blink::WebAXEventChildrenChanged;
msg->nodes.push_back(tree2_container);
msg->nodes.push_back(tree2_child0);
msg->nodes.push_back(tree2_grandchild0);
@@ -489,7 +494,7 @@ TEST(BrowserAccessibilityManagerTest, TestMoveChildUp) {
AccessibilityNodeData tree1_1;
tree1_1.id = 1;
- tree1_1.role = WebKit::WebAXRoleRootWebArea;
+ tree1_1.role = blink::WebAXRoleRootWebArea;
tree1_1.state = 0;
tree1_1.child_ids.push_back(2);
tree1_1.child_ids.push_back(3);
@@ -534,7 +539,7 @@ TEST(BrowserAccessibilityManagerTest, TestMoveChildUp) {
std::vector<AccessibilityHostMsg_EventParams> params;
params.push_back(AccessibilityHostMsg_EventParams());
AccessibilityHostMsg_EventParams* msg = &params[0];
- msg->event_type = WebKit::WebAXEventChildrenChanged;
+ msg->event_type = blink::WebAXEventChildrenChanged;
msg->nodes.push_back(tree2_1);
msg->nodes.push_back(tree2_4);
msg->nodes.push_back(tree2_5);
@@ -550,6 +555,12 @@ TEST(BrowserAccessibilityManagerTest, TestMoveChildUp) {
ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_);
}
+// Crashes on Windows. http://crbug.com/304130
+#if defined(OS_WIN)
+#define MAYBE_TestFatalError DISABLED_TestFatalError
+#else
+#define MAYBE_TestFatalError TestFatalError
+#endif
TEST(BrowserAccessibilityManagerTest, TestFatalError) {
// Test that BrowserAccessibilityManager raises a fatal error
// (which will crash the renderer) if the same id is used in
@@ -557,7 +568,7 @@ TEST(BrowserAccessibilityManagerTest, TestFatalError) {
AccessibilityNodeData root;
root.id = 1;
- root.role = WebKit::WebAXRoleRootWebArea;
+ root.role = blink::WebAXRoleRootWebArea;
root.child_ids.push_back(2);
root.child_ids.push_back(2);
@@ -575,7 +586,7 @@ TEST(BrowserAccessibilityManagerTest, TestFatalError) {
AccessibilityNodeData root2;
root2.id = 1;
- root2.role = WebKit::WebAXRoleRootWebArea;
+ root2.role = blink::WebAXRoleRootWebArea;
root2.child_ids.push_back(2);
root2.child_ids.push_back(3);
@@ -600,4 +611,169 @@ TEST(BrowserAccessibilityManagerTest, TestFatalError) {
ASSERT_TRUE(delegate->got_fatal_error());
}
+TEST(BrowserAccessibilityManagerTest, BoundsForRange) {
+ AccessibilityNodeData root;
+ root.id = 1;
+ root.role = blink::WebAXRoleRootWebArea;
+
+ AccessibilityNodeData static_text;
+ static_text.id = 2;
+ static_text.SetValue("Hello, world.");
+ static_text.role = blink::WebAXRoleStaticText;
+ static_text.location = gfx::Rect(100, 100, 29, 18);
+ root.child_ids.push_back(2);
+
+ AccessibilityNodeData inline_text1;
+ inline_text1.id = 3;
+ inline_text1.SetValue("Hello, ");
+ inline_text1.role = blink::WebAXRoleInlineTextBox;
+ inline_text1.location = gfx::Rect(100, 100, 29, 9);
+ inline_text1.AddIntAttribute(AccessibilityNodeData::ATTR_TEXT_DIRECTION,
+ blink::WebAXTextDirectionLR);
+ std::vector<int32> character_offsets1;
+ character_offsets1.push_back(6); // 0
+ character_offsets1.push_back(11); // 1
+ character_offsets1.push_back(16); // 2
+ character_offsets1.push_back(21); // 3
+ character_offsets1.push_back(26); // 4
+ character_offsets1.push_back(29); // 5
+ character_offsets1.push_back(29); // 6 (note that the space has no width)
+ inline_text1.AddIntListAttribute(
+ AccessibilityNodeData::ATTR_CHARACTER_OFFSETS, character_offsets1);
+ static_text.child_ids.push_back(3);
+
+ AccessibilityNodeData inline_text2;
+ inline_text2.id = 4;
+ inline_text2.SetValue("world.");
+ inline_text2.role = blink::WebAXRoleInlineTextBox;
+ inline_text2.location = gfx::Rect(100, 109, 28, 9);
+ inline_text2.AddIntAttribute(AccessibilityNodeData::ATTR_TEXT_DIRECTION,
+ blink::WebAXTextDirectionLR);
+ std::vector<int32> character_offsets2;
+ character_offsets2.push_back(5);
+ character_offsets2.push_back(10);
+ character_offsets2.push_back(15);
+ character_offsets2.push_back(20);
+ character_offsets2.push_back(25);
+ character_offsets2.push_back(28);
+ inline_text2.AddIntListAttribute(
+ AccessibilityNodeData::ATTR_CHARACTER_OFFSETS, character_offsets2);
+ static_text.child_ids.push_back(4);
+
+ scoped_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ root,
+ NULL,
+ new CountedBrowserAccessibilityFactory()));
+ manager->UpdateNodesForTesting(static_text, inline_text1, inline_text2);
+
+ BrowserAccessibility* root_accessible = manager->GetRoot();
+ BrowserAccessibility* static_text_accessible =
+ root_accessible->PlatformGetChild(0);
+
+ EXPECT_EQ(gfx::Rect(100, 100, 6, 9).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(0, 1).ToString());
+
+ EXPECT_EQ(gfx::Rect(100, 100, 26, 9).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(0, 5).ToString());
+
+ EXPECT_EQ(gfx::Rect(100, 109, 5, 9).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(7, 1).ToString());
+
+ EXPECT_EQ(gfx::Rect(100, 109, 25, 9).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(7, 5).ToString());
+
+ EXPECT_EQ(gfx::Rect(100, 100, 29, 18).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(5, 3).ToString());
+
+ EXPECT_EQ(gfx::Rect(100, 100, 29, 18).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(0, 13).ToString());
+
+ // Test range that's beyond the text.
+ EXPECT_EQ(gfx::Rect(100, 100, 29, 18).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(-1, 999).ToString());
+}
+
+TEST(BrowserAccessibilityManagerTest, BoundsForRangeBiDi) {
+ // In this example, we assume that the string "123abc" is rendered with
+ // "123" going left-to-right and "abc" going right-to-left. In other
+ // words, on-screen it would look like "123cba". This is possible to
+ // acheive if the source string had unicode control characters
+ // to switch directions. This test doesn't worry about how, though - it just
+ // tests that if something like that were to occur, GetLocalBoundsForRange
+ // returns the correct bounds for different ranges.
+
+ AccessibilityNodeData root;
+ root.id = 1;
+ root.role = blink::WebAXRoleRootWebArea;
+
+ AccessibilityNodeData static_text;
+ static_text.id = 2;
+ static_text.SetValue("123abc");
+ static_text.role = blink::WebAXRoleStaticText;
+ static_text.location = gfx::Rect(100, 100, 60, 20);
+ root.child_ids.push_back(2);
+
+ AccessibilityNodeData inline_text1;
+ inline_text1.id = 3;
+ inline_text1.SetValue("123");
+ inline_text1.role = blink::WebAXRoleInlineTextBox;
+ inline_text1.location = gfx::Rect(100, 100, 30, 20);
+ inline_text1.AddIntAttribute(AccessibilityNodeData::ATTR_TEXT_DIRECTION,
+ blink::WebAXTextDirectionLR);
+ std::vector<int32> character_offsets1;
+ character_offsets1.push_back(10); // 0
+ character_offsets1.push_back(20); // 1
+ character_offsets1.push_back(30); // 2
+ inline_text1.AddIntListAttribute(
+ AccessibilityNodeData::ATTR_CHARACTER_OFFSETS, character_offsets1);
+ static_text.child_ids.push_back(3);
+
+ AccessibilityNodeData inline_text2;
+ inline_text2.id = 4;
+ inline_text2.SetValue("abc");
+ inline_text2.role = blink::WebAXRoleInlineTextBox;
+ inline_text2.location = gfx::Rect(130, 100, 30, 20);
+ inline_text2.AddIntAttribute(AccessibilityNodeData::ATTR_TEXT_DIRECTION,
+ blink::WebAXTextDirectionRL);
+ std::vector<int32> character_offsets2;
+ character_offsets2.push_back(10);
+ character_offsets2.push_back(20);
+ character_offsets2.push_back(30);
+ inline_text2.AddIntListAttribute(
+ AccessibilityNodeData::ATTR_CHARACTER_OFFSETS, character_offsets2);
+ static_text.child_ids.push_back(4);
+
+ scoped_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ root,
+ NULL,
+ new CountedBrowserAccessibilityFactory()));
+ manager->UpdateNodesForTesting(static_text, inline_text1, inline_text2);
+
+ BrowserAccessibility* root_accessible = manager->GetRoot();
+ BrowserAccessibility* static_text_accessible =
+ root_accessible->PlatformGetChild(0);
+
+ EXPECT_EQ(gfx::Rect(100, 100, 60, 20).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(0, 6).ToString());
+
+ EXPECT_EQ(gfx::Rect(100, 100, 10, 20).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(0, 1).ToString());
+
+ EXPECT_EQ(gfx::Rect(100, 100, 30, 20).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(0, 3).ToString());
+
+ EXPECT_EQ(gfx::Rect(150, 100, 10, 20).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(3, 1).ToString());
+
+ EXPECT_EQ(gfx::Rect(130, 100, 30, 20).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(3, 3).ToString());
+
+ // This range is only two characters, but because of the direction switch
+ // the bounds are as wide as four characters.
+ EXPECT_EQ(gfx::Rect(120, 100, 40, 20).ToString(),
+ static_text_accessible->GetLocalBoundsForRange(2, 2).ToString());
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index 881d1b80b25..4e5f8dc9abc 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -4,11 +4,97 @@
#include "content/browser/accessibility/browser_accessibility_manager_win.h"
+#include <atlbase.h>
+#include <atlapp.h>
+#include <atlcom.h>
+#include <atlcrack.h>
+#include <oleacc.h>
+
+#include "base/command_line.h"
+#include "base/win/scoped_comptr.h"
+#include "base/win/windows_version.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
#include "content/common/accessibility_messages.h"
namespace content {
+// Some screen readers expect every tab / every unique web content container
+// to be in its own HWND, like it was before Aura, but with Aura there's just
+// one main HWND for a frame, or even for the whole desktop. So, we need a
+// fake HWND as the root of the accessibility tree for each tab.
+// We should get rid of this code when the latest two versions of all
+// supported screen readers no longer make this assumption.
+//
+// This class implements a child HWND with zero size, that delegates its
+// accessibility implementation to the root of the BrowserAccessibilityManager
+// tree. This HWND is hooked up as the parent of the root object in the
+// BrowserAccessibilityManager tree, so when any accessibility client
+// calls ::WindowFromAccessibleObject, they get this HWND instead of the
+// DesktopRootWindowHostWin.
+class AccessibleHWND
+ : public ATL::CWindowImpl<AccessibleHWND,
+ ATL::CWindow,
+ ATL::CWinTraits<WS_CHILD> > {
+ public:
+ // Unfortunately, some screen readers look for this exact window class
+ // to enable certain features. It'd be great to remove this.
+ DECLARE_WND_CLASS_EX(L"Chrome_RenderWidgetHostHWND", CS_DBLCLKS, 0);
+
+ BEGIN_MSG_MAP_EX(AccessibleHWND)
+ MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
+ END_MSG_MAP()
+
+ AccessibleHWND(HWND parent, BrowserAccessibilityManagerWin* manager)
+ : manager_(manager) {
+ Create(parent);
+ ShowWindow(true);
+ MoveWindow(0, 0, 0, 0);
+
+ HRESULT hr = ::CreateStdAccessibleObject(
+ hwnd(), OBJID_WINDOW, IID_IAccessible,
+ reinterpret_cast<void **>(window_accessible_.Receive()));
+ DCHECK(SUCCEEDED(hr));
+ }
+
+ HWND hwnd() {
+ DCHECK(::IsWindow(m_hWnd));
+ return m_hWnd;
+ }
+
+ IAccessible* window_accessible() { return window_accessible_; }
+
+ void OnManagerDeleted() {
+ manager_ = NULL;
+ }
+
+ protected:
+ virtual void OnFinalMessage(HWND hwnd) OVERRIDE {
+ if (manager_)
+ manager_->OnAccessibleHwndDeleted();
+ delete this;
+ }
+
+ private:
+ LRESULT OnGetObject(UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ if (OBJID_CLIENT != l_param || !manager_)
+ return static_cast<LRESULT>(0L);
+
+ base::win::ScopedComPtr<IAccessible> root(
+ manager_->GetRoot()->ToBrowserAccessibilityWin());
+ return LresultFromObject(IID_IAccessible, w_param,
+ static_cast<IAccessible*>(root.Detach()));
+ }
+
+ BrowserAccessibilityManagerWin* manager_;
+ base::win::ScopedComPtr<IAccessible> window_accessible_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccessibleHWND);
+};
+
+
// static
BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
const AccessibilityNodeData& src,
@@ -32,7 +118,10 @@ BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin(
: BrowserAccessibilityManager(src, delegate, factory),
parent_hwnd_(parent_hwnd),
parent_iaccessible_(parent_iaccessible),
- tracked_scroll_object_(NULL) {
+ tracked_scroll_object_(NULL),
+ is_chrome_frame_(
+ CommandLine::ForCurrentProcess()->HasSwitch("chrome-frame")),
+ accessible_hwnd_(NULL) {
}
BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
@@ -40,24 +129,42 @@ BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
tracked_scroll_object_->Release();
tracked_scroll_object_ = NULL;
}
+ if (accessible_hwnd_)
+ accessible_hwnd_->OnManagerDeleted();
}
// static
AccessibilityNodeData BrowserAccessibilityManagerWin::GetEmptyDocument() {
AccessibilityNodeData empty_document;
empty_document.id = 0;
- empty_document.role = WebKit::WebAXRoleRootWebArea;
+ empty_document.role = blink::WebAXRoleRootWebArea;
empty_document.state =
- (1 << WebKit::WebAXStateEnabled) |
- (1 << WebKit::WebAXStateReadonly) |
- (1 << WebKit::WebAXStateBusy);
+ (1 << blink::WebAXStateEnabled) |
+ (1 << blink::WebAXStateReadonly) |
+ (1 << blink::WebAXStateBusy);
return empty_document;
}
void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent(DWORD event,
LONG child_id) {
- if (parent_iaccessible())
- ::NotifyWinEvent(event, parent_hwnd(), OBJID_CLIENT, child_id);
+ // Don't fire events if this view isn't hooked up to its parent.
+ if (!parent_iaccessible())
+ return;
+
+#if defined(USE_AURA)
+ // If this is an Aura build on Win 7 and complete accessibility is
+ // enabled, create a fake child HWND to use as the root of the
+ // accessibility tree. See comments above AccessibleHWND for details.
+ if (BrowserAccessibilityStateImpl::GetInstance()->IsAccessibleBrowser() &&
+ !is_chrome_frame_ &&
+ !accessible_hwnd_) {
+ accessible_hwnd_ = new AccessibleHWND(parent_hwnd_, this);
+ parent_hwnd_ = accessible_hwnd_->hwnd();
+ parent_iaccessible_ = accessible_hwnd_->window_accessible();
+ }
+#endif
+
+ ::NotifyWinEvent(event, parent_hwnd(), OBJID_CLIENT, child_id);
}
void BrowserAccessibilityManagerWin::AddNodeToMap(BrowserAccessibility* node) {
@@ -77,79 +184,82 @@ void BrowserAccessibilityManagerWin::RemoveNode(BrowserAccessibility* node) {
}
void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
- WebKit::WebAXEvent event_type,
+ blink::WebAXEvent event_type,
BrowserAccessibility* node) {
+ if (node->role() == blink::WebAXRoleInlineTextBox)
+ return;
+
LONG event_id = EVENT_MIN;
switch (event_type) {
- case WebKit::WebAXEventActiveDescendantChanged:
+ case blink::WebAXEventActiveDescendantChanged:
event_id = IA2_EVENT_ACTIVE_DESCENDANT_CHANGED;
break;
- case WebKit::WebAXEventAlert:
+ case blink::WebAXEventAlert:
event_id = EVENT_SYSTEM_ALERT;
break;
- case WebKit::WebAXEventAriaAttributeChanged:
+ case blink::WebAXEventAriaAttributeChanged:
event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED;
break;
- case WebKit::WebAXEventAutocorrectionOccured:
+ case blink::WebAXEventAutocorrectionOccured:
event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED;
break;
- case WebKit::WebAXEventBlur:
+ case blink::WebAXEventBlur:
// Equivalent to focus on the root.
event_id = EVENT_OBJECT_FOCUS;
node = GetRoot();
break;
- case WebKit::WebAXEventCheckedStateChanged:
+ case blink::WebAXEventCheckedStateChanged:
event_id = EVENT_OBJECT_STATECHANGE;
break;
- case WebKit::WebAXEventChildrenChanged:
+ case blink::WebAXEventChildrenChanged:
event_id = EVENT_OBJECT_REORDER;
break;
- case WebKit::WebAXEventFocus:
+ case blink::WebAXEventFocus:
event_id = EVENT_OBJECT_FOCUS;
break;
- case WebKit::WebAXEventInvalidStatusChanged:
+ case blink::WebAXEventInvalidStatusChanged:
event_id = EVENT_OBJECT_STATECHANGE;
break;
- case WebKit::WebAXEventLiveRegionChanged:
+ case blink::WebAXEventLiveRegionChanged:
// TODO: try not firing a native notification at all, since
// on Windows, each individual item in a live region that changes
// already gets its own notification.
event_id = EVENT_OBJECT_REORDER;
break;
- case WebKit::WebAXEventLoadComplete:
+ case blink::WebAXEventLoadComplete:
event_id = IA2_EVENT_DOCUMENT_LOAD_COMPLETE;
break;
- case WebKit::WebAXEventMenuListItemSelected:
+ case blink::WebAXEventMenuListItemSelected:
event_id = EVENT_OBJECT_FOCUS;
break;
- case WebKit::WebAXEventMenuListValueChanged:
+ case blink::WebAXEventMenuListValueChanged:
event_id = EVENT_OBJECT_VALUECHANGE;
break;
- case WebKit::WebAXEventHide:
+ case blink::WebAXEventHide:
event_id = EVENT_OBJECT_HIDE;
break;
- case WebKit::WebAXEventShow:
+ case blink::WebAXEventShow:
event_id = EVENT_OBJECT_SHOW;
break;
- case WebKit::WebAXEventScrolledToAnchor:
+ case blink::WebAXEventScrolledToAnchor:
event_id = EVENT_SYSTEM_SCROLLINGSTART;
break;
- case WebKit::WebAXEventSelectedChildrenChanged:
+ case blink::WebAXEventSelectedChildrenChanged:
event_id = EVENT_OBJECT_SELECTIONWITHIN;
break;
- case WebKit::WebAXEventSelectedTextChanged:
+ case blink::WebAXEventSelectedTextChanged:
event_id = IA2_EVENT_TEXT_CARET_MOVED;
break;
- case WebKit::WebAXEventTextChanged:
+ case blink::WebAXEventTextChanged:
event_id = EVENT_OBJECT_NAMECHANGE;
break;
- case WebKit::WebAXEventTextInserted:
+ case blink::WebAXEventTextInserted:
event_id = IA2_EVENT_TEXT_INSERTED;
break;
- case WebKit::WebAXEventTextRemoved:
+ case blink::WebAXEventTextRemoved:
event_id = IA2_EVENT_TEXT_REMOVED;
break;
- case WebKit::WebAXEventValueChanged:
+ case blink::WebAXEventValueChanged:
event_id = EVENT_OBJECT_VALUECHANGE;
break;
default:
@@ -170,7 +280,7 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
// If this is a layout complete notification (sent when a container scrolls)
// and there is a descendant tracked object, send a notification on it.
// TODO(dmazzoni): remove once http://crbug.com/113483 is fixed.
- if (event_type == WebKit::WebAXEventLayoutComplete &&
+ if (event_type == blink::WebAXEventLayoutComplete &&
tracked_scroll_object_ &&
tracked_scroll_object_->IsDescendantOf(node)) {
MaybeCallNotifyWinEvent(
@@ -201,4 +311,15 @@ BrowserAccessibilityWin* BrowserAccessibilityManagerWin::GetFromUniqueIdWin(
return NULL;
}
+void BrowserAccessibilityManagerWin::OnAccessibleHwndDeleted() {
+ // If the AccessibleHWND is deleted, |parent_hwnd_| and
+ // |parent_iaccessible_| are no longer valid either, since they were
+ // derived from AccessibleHWND. We don't have to restore them to
+ // previous values, though, because this should only happen
+ // during the destruct sequence for this window.
+ accessible_hwnd_ = NULL;
+ parent_hwnd_ = NULL;
+ parent_iaccessible_ = NULL;
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
index 7857f68a76e..cbfc877909e 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -7,12 +7,15 @@
#include <oleacc.h>
+#include "base/memory/scoped_ptr.h"
#include "base/win/scoped_comptr.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
namespace content {
class BrowserAccessibilityWin;
+class AccessibleHWND;
+
// Manages a tree of BrowserAccessibilityWin objects.
class CONTENT_EXPORT BrowserAccessibilityManagerWin
: public BrowserAccessibilityManager {
@@ -44,7 +47,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
virtual void AddNodeToMap(BrowserAccessibility* node);
virtual void RemoveNode(BrowserAccessibility* node) OVERRIDE;
virtual void NotifyAccessibilityEvent(
- WebKit::WebAXEvent event_type, BrowserAccessibility* node) OVERRIDE;
+ blink::WebAXEvent event_type, BrowserAccessibility* node) OVERRIDE;
// Track this object and post a VISIBLE_DATA_CHANGED notification when
// its container scrolls.
@@ -55,6 +58,9 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// unique id, does not make a new reference.
BrowserAccessibilityWin* GetFromUniqueIdWin(LONG unique_id_win);
+ // Called when |accessible_hwnd_| is deleted by its parent.
+ void OnAccessibleHwndDeleted();
+
private:
// The closest ancestor HWND.
HWND parent_hwnd_;
@@ -74,6 +80,11 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// browser process) to renderer ids within this page.
base::hash_map<long, int32> unique_id_to_renderer_id_map_;
+ bool is_chrome_frame_;
+
+ // Owned by its parent; OnAccessibleHwndDeleted gets called upon deletion.
+ AccessibleHWND* accessible_hwnd_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerWin);
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
index 824055f6e5d..28f05e0e7ec 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
@@ -57,7 +57,7 @@ void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
for (size_t i = 0; i < module_count; i++) {
TCHAR filename[MAX_PATH];
GetModuleFileName(modules[i], filename, sizeof(filename));
- string16 module_name(base::FilePath(filename).BaseName().value());
+ base::string16 module_name(base::FilePath(filename).BaseName().value());
if (LowerCaseEqualsASCII(module_name, "fsdomsrv.dll"))
jaws = true;
if (LowerCaseEqualsASCII(module_name, "vbufbackend_gecko_ia2.dll"))
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.cc b/chromium/content/browser/accessibility/browser_accessibility_win.cc
index df3263e845d..2c0150322b9 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.cc
@@ -58,7 +58,7 @@ class BrowserAccessibilityRelation
CONTENT_EXPORT virtual ~BrowserAccessibilityRelation() {}
CONTENT_EXPORT void Initialize(BrowserAccessibilityWin* owner,
- const string16& type);
+ const base::string16& type);
CONTENT_EXPORT void AddTarget(int target_id);
// IAccessibleRelation methods.
@@ -75,13 +75,13 @@ class BrowserAccessibilityRelation
}
private:
- string16 type_;
+ base::string16 type_;
base::win::ScopedComPtr<BrowserAccessibilityWin> owner_;
std::vector<int> target_ids_;
};
void BrowserAccessibilityRelation::Initialize(BrowserAccessibilityWin* owner,
- const string16& type) {
+ const base::string16& type) {
owner_ = owner;
type_ = type;
}
@@ -195,7 +195,9 @@ BrowserAccessibilityWin::BrowserAccessibilityWin()
ia2_role_(0),
ia2_state_(0),
first_time_(true),
- old_ia_state_(0) {
+ old_ia_state_(0),
+ previous_scroll_x_(0),
+ previous_scroll_y_(0) {
// Start unique IDs at -1 and decrement each time, because get_accChild
// uses positive IDs to enumerate children, so we use negative IDs to
// clearly distinguish between indices and unique IDs.
@@ -217,27 +219,27 @@ BrowserAccessibilityWin::~BrowserAccessibilityWin() {
// IAccessible methods.
//
// Conventions:
-// * Always test for instance_active_ first and return E_FAIL if it's false.
+// * Always test for instance_active() first and return E_FAIL if it's false.
// * Always check for invalid arguments first, even if they're unused.
// * Return S_FALSE if the only output is a string argument and it's empty.
//
HRESULT BrowserAccessibilityWin::accDoDefaultAction(VARIANT var_id) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
BrowserAccessibilityWin* target = GetTargetFromChildID(var_id);
if (!target)
return E_INVALIDARG;
- manager_->DoDefaultAction(*target);
+ manager()->DoDefaultAction(*target);
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::accHitTest(LONG x_left,
LONG y_top,
VARIANT* child) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!child)
@@ -267,7 +269,7 @@ STDMETHODIMP BrowserAccessibilityWin::accLocation(LONG* x_left,
LONG* width,
LONG* height,
VARIANT var_id) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!x_left || !y_top || !width || !height)
@@ -299,6 +301,8 @@ STDMETHODIMP BrowserAccessibilityWin::accNavigate(LONG nav_dir,
return E_INVALIDARG;
}
+ uint32 child_count = target->PlatformChildCount();
+
BrowserAccessibility* result = NULL;
switch (nav_dir) {
case NAVDIR_DOWN:
@@ -308,12 +312,12 @@ STDMETHODIMP BrowserAccessibilityWin::accNavigate(LONG nav_dir,
// These directions are not implemented, matching Mozilla and IE.
return E_NOTIMPL;
case NAVDIR_FIRSTCHILD:
- if (!target->children_.empty())
- result = target->children_.front();
+ if (child_count > 0)
+ result = target->PlatformGetChild(0);
break;
case NAVDIR_LASTCHILD:
- if (!target->children_.empty())
- result = target->children_.back();
+ if (child_count > 0)
+ result = target->PlatformGetChild(child_count - 1);
break;
case NAVDIR_NEXT:
result = target->GetNextSibling();
@@ -335,7 +339,7 @@ STDMETHODIMP BrowserAccessibilityWin::accNavigate(LONG nav_dir,
STDMETHODIMP BrowserAccessibilityWin::get_accChild(VARIANT var_child,
IDispatch** disp_child) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!disp_child)
@@ -352,19 +356,20 @@ STDMETHODIMP BrowserAccessibilityWin::get_accChild(VARIANT var_child,
}
STDMETHODIMP BrowserAccessibilityWin::get_accChildCount(LONG* child_count) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!child_count)
return E_INVALIDARG;
- *child_count = children_.size();
+ *child_count = PlatformChildCount();
+
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::get_accDefaultAction(VARIANT var_id,
BSTR* def_action) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!def_action)
@@ -380,7 +385,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accDefaultAction(VARIANT var_id,
STDMETHODIMP BrowserAccessibilityWin::get_accDescription(VARIANT var_id,
BSTR* desc) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!desc)
@@ -395,14 +400,14 @@ STDMETHODIMP BrowserAccessibilityWin::get_accDescription(VARIANT var_id,
}
STDMETHODIMP BrowserAccessibilityWin::get_accFocus(VARIANT* focus_child) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!focus_child)
return E_INVALIDARG;
BrowserAccessibilityWin* focus = static_cast<BrowserAccessibilityWin*>(
- manager_->GetFocus(this));
+ manager()->GetFocus(this));
if (focus == this) {
focus_child->vt = VT_I4;
focus_child->lVal = CHILDID_SELF;
@@ -417,7 +422,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accFocus(VARIANT* focus_child) {
}
STDMETHODIMP BrowserAccessibilityWin::get_accHelp(VARIANT var_id, BSTR* help) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!help)
@@ -433,7 +438,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accHelp(VARIANT var_id, BSTR* help) {
STDMETHODIMP BrowserAccessibilityWin::get_accKeyboardShortcut(VARIANT var_id,
BSTR* acc_key) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!acc_key)
@@ -448,7 +453,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accKeyboardShortcut(VARIANT var_id,
}
STDMETHODIMP BrowserAccessibilityWin::get_accName(VARIANT var_id, BSTR* name) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!name)
@@ -466,7 +471,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accName(VARIANT var_id, BSTR* name) {
if (target->GetIntAttribute(AccessibilityNodeData::ATTR_TITLE_UI_ELEMENT,
&title_elem_id)) {
BrowserAccessibility* title_elem =
- manager_->GetFromRendererID(title_elem_id);
+ manager()->GetFromRendererID(title_elem_id);
if (title_elem)
name_str = title_elem->GetTextRecursive();
}
@@ -482,31 +487,33 @@ STDMETHODIMP BrowserAccessibilityWin::get_accName(VARIANT var_id, BSTR* name) {
}
STDMETHODIMP BrowserAccessibilityWin::get_accParent(IDispatch** disp_parent) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!disp_parent)
return E_INVALIDARG;
- IAccessible* parent = parent_->ToBrowserAccessibilityWin();
- if (parent == NULL) {
+ IAccessible* parent_obj = parent()->ToBrowserAccessibilityWin();
+ if (parent_obj == NULL) {
// This happens if we're the root of the tree;
// return the IAccessible for the window.
- parent = manager_->ToBrowserAccessibilityManagerWin()->parent_iaccessible();
+ parent_obj =
+ manager()->ToBrowserAccessibilityManagerWin()->parent_iaccessible();
+
// |parent| can only be NULL if the manager was created before the parent
// IAccessible was known and it wasn't subsequently set before a client
// requested it. Crash hard if this happens so that we get crash reports.
- CHECK(parent);
+ CHECK(parent_obj);
}
- parent->AddRef();
- *disp_parent = parent;
+ parent_obj->AddRef();
+ *disp_parent = parent_obj;
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::get_accRole(VARIANT var_id,
VARIANT* role) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!role)
@@ -528,7 +535,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accRole(VARIANT var_id,
STDMETHODIMP BrowserAccessibilityWin::get_accState(VARIANT var_id,
VARIANT* state) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!state)
@@ -540,7 +547,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accState(VARIANT var_id,
state->vt = VT_I4;
state->lVal = target->ia_state_;
- if (manager_->GetFocus(NULL) == this)
+ if (manager()->GetFocus(NULL) == this)
state->lVal |= STATE_SYSTEM_FOCUSED;
return S_OK;
@@ -548,7 +555,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accState(VARIANT var_id,
STDMETHODIMP BrowserAccessibilityWin::get_accValue(VARIANT var_id,
BSTR* value) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!value)
@@ -561,7 +568,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accValue(VARIANT var_id,
if (target->ia_role() == ROLE_SYSTEM_PROGRESSBAR ||
target->ia_role() == ROLE_SYSTEM_SCROLLBAR ||
target->ia_role() == ROLE_SYSTEM_SLIDER) {
- string16 value_text = target->GetValueText();
+ base::string16 value_text = target->GetValueText();
*value = SysAllocString(value_text.c_str());
DCHECK(*value);
return S_OK;
@@ -575,7 +582,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accValue(VARIANT var_id,
AccessibilityNodeData::ATTR_COLOR_VALUE_GREEN);
int b = target->GetIntAttribute(
AccessibilityNodeData::ATTR_COLOR_VALUE_BLUE);
- string16 value_text;
+ base::string16 value_text;
value_text = base::IntToString16((r * 100) / 255) + L"% red " +
base::IntToString16((g * 100) / 255) + L"% green " +
base::IntToString16((b * 100) / 255) + L"% blue";
@@ -596,15 +603,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_accHelpTopic(BSTR* help_file,
}
STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
- if (role_ != WebKit::WebAXRoleListBox)
+ if (blink_role() != blink::WebAXRoleListBox)
return E_NOTIMPL;
unsigned long selected_count = 0;
- for (size_t i = 0; i < children_.size(); ++i) {
- if (children_[i]->HasState(WebKit::WebAXStateSelected))
+ for (size_t i = 0; i < children().size(); ++i) {
+ if (children()[i]->HasState(blink::WebAXStateSelected))
++selected_count;
}
@@ -614,11 +621,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) {
}
if (selected_count == 1) {
- for (size_t i = 0; i < children_.size(); ++i) {
- if (children_[i]->HasState(WebKit::WebAXStateSelected)) {
+ for (size_t i = 0; i < children().size(); ++i) {
+ if (children()[i]->HasState(blink::WebAXStateSelected)) {
selected->vt = VT_DISPATCH;
selected->pdispVal =
- children_[i]->ToBrowserAccessibilityWin()->NewReference();
+ children()[i]->ToBrowserAccessibilityWin()->NewReference();
return S_OK;
}
}
@@ -629,11 +636,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) {
new base::win::EnumVariant(selected_count);
enum_variant->AddRef();
unsigned long index = 0;
- for (size_t i = 0; i < children_.size(); ++i) {
- if (children_[i]->HasState(WebKit::WebAXStateSelected)) {
+ for (size_t i = 0; i < children().size(); ++i) {
+ if (children()[i]->HasState(blink::WebAXStateSelected)) {
enum_variant->ItemAt(index)->vt = VT_DISPATCH;
enum_variant->ItemAt(index)->pdispVal =
- children_[i]->ToBrowserAccessibilityWin()->NewReference();
+ children()[i]->ToBrowserAccessibilityWin()->NewReference();
++index;
}
}
@@ -645,11 +652,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) {
STDMETHODIMP BrowserAccessibilityWin::accSelect(
LONG flags_sel, VARIANT var_id) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (flags_sel & SELFLAG_TAKEFOCUS) {
- manager_->SetFocus(this, true);
+ manager()->SetFocus(this, true);
return S_OK;
}
@@ -661,7 +668,7 @@ STDMETHODIMP BrowserAccessibilityWin::accSelect(
//
STDMETHODIMP BrowserAccessibilityWin::role(LONG* role) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!role)
@@ -673,7 +680,7 @@ STDMETHODIMP BrowserAccessibilityWin::role(LONG* role) {
}
STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!attributes)
@@ -681,7 +688,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) {
// The iaccessible2 attributes are a set of key-value pairs
// separated by semicolons, with a colon between the key and the value.
- string16 str;
+ base::string16 str;
for (unsigned int i = 0; i < ia2_attributes_.size(); ++i) {
if (i != 0)
str += L';';
@@ -697,7 +704,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) {
}
STDMETHODIMP BrowserAccessibilityWin::get_states(AccessibleStates* states) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!states)
@@ -709,7 +716,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_states(AccessibleStates* states) {
}
STDMETHODIMP BrowserAccessibilityWin::get_uniqueID(LONG* unique_id) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!unique_id)
@@ -720,29 +727,29 @@ STDMETHODIMP BrowserAccessibilityWin::get_uniqueID(LONG* unique_id) {
}
STDMETHODIMP BrowserAccessibilityWin::get_windowHandle(HWND* window_handle) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!window_handle)
return E_INVALIDARG;
- *window_handle = manager_->ToBrowserAccessibilityManagerWin()->parent_hwnd();
+ *window_handle = manager()->ToBrowserAccessibilityManagerWin()->parent_hwnd();
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::get_indexInParent(LONG* index_in_parent) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!index_in_parent)
return E_INVALIDARG;
- *index_in_parent = index_in_parent_;
+ *index_in_parent = this->index_in_parent();
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::get_nRelations(LONG* n_relations) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!n_relations)
@@ -755,7 +762,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nRelations(LONG* n_relations) {
STDMETHODIMP BrowserAccessibilityWin::get_relation(
LONG relation_index,
IAccessibleRelation** relation) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (relation_index < 0 ||
@@ -775,7 +782,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_relations(
LONG max_relations,
IAccessibleRelation** relations,
LONG* n_relations) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!relations || !n_relations)
@@ -795,42 +802,41 @@ STDMETHODIMP BrowserAccessibilityWin::get_relations(
}
STDMETHODIMP BrowserAccessibilityWin::scrollTo(enum IA2ScrollType scroll_type) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
- gfx::Rect r = location_;
+ gfx::Rect r = location();
switch(scroll_type) {
case IA2_SCROLL_TYPE_TOP_LEFT:
- manager_->ScrollToMakeVisible(*this, gfx::Rect(r.x(), r.y(), 0, 0));
+ manager()->ScrollToMakeVisible(*this, gfx::Rect(r.x(), r.y(), 0, 0));
break;
case IA2_SCROLL_TYPE_BOTTOM_RIGHT:
- manager_->ScrollToMakeVisible(
+ manager()->ScrollToMakeVisible(
*this, gfx::Rect(r.right(), r.bottom(), 0, 0));
break;
case IA2_SCROLL_TYPE_TOP_EDGE:
- manager_->ScrollToMakeVisible(
+ manager()->ScrollToMakeVisible(
*this, gfx::Rect(r.x(), r.y(), r.width(), 0));
break;
case IA2_SCROLL_TYPE_BOTTOM_EDGE:
- manager_->ScrollToMakeVisible(
+ manager()->ScrollToMakeVisible(
*this, gfx::Rect(r.x(), r.bottom(), r.width(), 0));
break;
case IA2_SCROLL_TYPE_LEFT_EDGE:
- manager_->ScrollToMakeVisible(
+ manager()->ScrollToMakeVisible(
*this, gfx::Rect(r.x(), r.y(), 0, r.height()));
break;
case IA2_SCROLL_TYPE_RIGHT_EDGE:
- manager_->ScrollToMakeVisible(
+ manager()->ScrollToMakeVisible(
*this, gfx::Rect(r.right(), r.y(), 0, r.height()));
break;
case IA2_SCROLL_TYPE_ANYWHERE:
default:
- manager_->ScrollToMakeVisible(*this, r);
+ manager()->ScrollToMakeVisible(*this, r);
break;
}
- static_cast<BrowserAccessibilityManagerWin*>(manager_)
- ->TrackScrollingObject(this);
+ manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this);
return S_OK;
}
@@ -839,24 +845,22 @@ STDMETHODIMP BrowserAccessibilityWin::scrollToPoint(
enum IA2CoordinateType coordinate_type,
LONG x,
LONG y) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
gfx::Point scroll_to(x, y);
if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) {
- scroll_to -= manager_->GetViewBounds().OffsetFromOrigin();
+ scroll_to -= manager()->GetViewBounds().OffsetFromOrigin();
} else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) {
- if (parent_)
- scroll_to += parent_->location().OffsetFromOrigin();
+ if (parent())
+ scroll_to += parent()->location().OffsetFromOrigin();
} else {
return E_INVALIDARG;
}
- manager_->ScrollToPoint(*this, scroll_to);
-
- static_cast<BrowserAccessibilityManagerWin*>(manager_)
- ->TrackScrollingObject(this);
+ manager()->ScrollToPoint(*this, scroll_to);
+ manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this);
return S_OK;
}
@@ -865,18 +869,18 @@ STDMETHODIMP BrowserAccessibilityWin::get_groupPosition(
LONG* group_level,
LONG* similar_items_in_group,
LONG* position_in_group) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!group_level || !similar_items_in_group || !position_in_group)
return E_INVALIDARG;
- if (role_ == WebKit::WebAXRoleListBoxOption &&
- parent_ &&
- parent_->role() == WebKit::WebAXRoleListBox) {
+ if (blink_role() == blink::WebAXRoleListBoxOption &&
+ parent() &&
+ parent()->role() == blink::WebAXRoleListBox) {
*group_level = 0;
- *similar_items_in_group = parent_->child_count();
- *position_in_group = index_in_parent_ + 1;
+ *similar_items_in_group = parent()->PlatformChildCount();
+ *position_in_group = index_in_parent() + 1;
return S_OK;
}
@@ -888,7 +892,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_groupPosition(
//
STDMETHODIMP BrowserAccessibilityWin::get_appName(BSTR* app_name) {
- // No need to check |instance_active_| because this interface is
+ // No need to check |instance_active()| because this interface is
// global, and doesn't depend on any local state.
if (!app_name)
@@ -907,7 +911,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_appName(BSTR* app_name) {
}
STDMETHODIMP BrowserAccessibilityWin::get_appVersion(BSTR* app_version) {
- // No need to check |instance_active_| because this interface is
+ // No need to check |instance_active()| because this interface is
// global, and doesn't depend on any local state.
if (!app_version)
@@ -926,7 +930,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_appVersion(BSTR* app_version) {
}
STDMETHODIMP BrowserAccessibilityWin::get_toolkitName(BSTR* toolkit_name) {
- // No need to check |instance_active_| because this interface is
+ // No need to check |instance_active()| because this interface is
// global, and doesn't depend on any local state.
if (!toolkit_name)
@@ -942,7 +946,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_toolkitName(BSTR* toolkit_name) {
STDMETHODIMP BrowserAccessibilityWin::get_toolkitVersion(
BSTR* toolkit_version) {
- // No need to check |instance_active_| because this interface is
+ // No need to check |instance_active()| because this interface is
// global, and doesn't depend on any local state.
if (!toolkit_version)
@@ -959,7 +963,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_toolkitVersion(
//
STDMETHODIMP BrowserAccessibilityWin::get_description(BSTR* desc) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!desc)
@@ -973,7 +977,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_imagePosition(
enum IA2CoordinateType coordinate_type,
LONG* x,
LONG* y) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!x || !y)
@@ -981,17 +985,17 @@ STDMETHODIMP BrowserAccessibilityWin::get_imagePosition(
if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) {
HWND parent_hwnd =
- manager_->ToBrowserAccessibilityManagerWin()->parent_hwnd();
+ manager()->ToBrowserAccessibilityManagerWin()->parent_hwnd();
POINT top_left = {0, 0};
::ClientToScreen(parent_hwnd, &top_left);
- *x = location_.x() + top_left.x;
- *y = location_.y() + top_left.y;
+ *x = location().x() + top_left.x;
+ *y = location().y() + top_left.y;
} else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) {
- *x = location_.x();
- *y = location_.y();
- if (parent_) {
- *x -= parent_->location().x();
- *y -= parent_->location().y();
+ *x = location().x();
+ *y = location().y();
+ if (parent()) {
+ *x -= parent()->location().x();
+ *y -= parent()->location().y();
}
} else {
return E_INVALIDARG;
@@ -1001,14 +1005,14 @@ STDMETHODIMP BrowserAccessibilityWin::get_imagePosition(
}
STDMETHODIMP BrowserAccessibilityWin::get_imageSize(LONG* height, LONG* width) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!height || !width)
return E_INVALIDARG;
- *height = location_.height();
- *width = location_.width();
+ *height = location().height();
+ *width = location().width();
return S_OK;
}
@@ -1020,7 +1024,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accessibleAt(
long row,
long column,
IUnknown** accessible) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!accessible)
@@ -1056,7 +1060,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accessibleAt(
}
STDMETHODIMP BrowserAccessibilityWin::get_caption(IUnknown** accessible) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!accessible)
@@ -1069,7 +1073,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_caption(IUnknown** accessible) {
STDMETHODIMP BrowserAccessibilityWin::get_childIndex(long row,
long column,
long* cell_index) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!cell_index)
@@ -1107,7 +1111,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_childIndex(long row,
STDMETHODIMP BrowserAccessibilityWin::get_columnDescription(long column,
BSTR* description) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!description)
@@ -1131,9 +1135,9 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnDescription(long column,
for (int i = 0; i < rows; ++i) {
int cell_id = cell_ids[i * columns + column];
BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>(
- manager_->GetFromRendererID(cell_id));
- if (cell && cell->role_ == WebKit::WebAXRoleColumnHeader) {
- string16 cell_name = cell->GetString16Attribute(
+ manager()->GetFromRendererID(cell_id));
+ if (cell && cell->blink_role() == blink::WebAXRoleColumnHeader) {
+ base::string16 cell_name = cell->GetString16Attribute(
AccessibilityNodeData::ATTR_NAME);
if (cell_name.size() > 0) {
*description = SysAllocString(cell_name.c_str());
@@ -1152,7 +1156,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnExtentAt(
long row,
long column,
long* n_columns_spanned) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!n_columns_spanned)
@@ -1175,7 +1179,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnExtentAt(
AccessibilityNodeData::ATTR_CELL_IDS);
int cell_id = cell_ids[row * columns + column];
BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>(
- manager_->GetFromRendererID(cell_id));
+ manager()->GetFromRendererID(cell_id));
int colspan;
if (cell &&
cell->GetIntAttribute(
@@ -1197,7 +1201,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeader(
STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long cell_index,
long* column_index) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!column_index)
@@ -1213,7 +1217,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long cell_index,
int cell_id = unique_cell_ids[cell_index];
BrowserAccessibilityWin* cell =
- manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
+ manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
int col_index;
if (cell &&
cell->GetIntAttribute(
@@ -1226,7 +1230,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long cell_index,
}
STDMETHODIMP BrowserAccessibilityWin::get_nColumns(long* column_count) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!column_count)
@@ -1243,7 +1247,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nColumns(long* column_count) {
}
STDMETHODIMP BrowserAccessibilityWin::get_nRows(long* row_count) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!row_count)
@@ -1259,7 +1263,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nRows(long* row_count) {
}
STDMETHODIMP BrowserAccessibilityWin::get_nSelectedChildren(long* cell_count) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!cell_count)
@@ -1271,7 +1275,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelectedChildren(long* cell_count) {
}
STDMETHODIMP BrowserAccessibilityWin::get_nSelectedColumns(long* column_count) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!column_count)
@@ -1282,7 +1286,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelectedColumns(long* column_count) {
}
STDMETHODIMP BrowserAccessibilityWin::get_nSelectedRows(long* row_count) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!row_count)
@@ -1294,7 +1298,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelectedRows(long* row_count) {
STDMETHODIMP BrowserAccessibilityWin::get_rowDescription(long row,
BSTR* description) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!description)
@@ -1318,9 +1322,9 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowDescription(long row,
for (int i = 0; i < columns; ++i) {
int cell_id = cell_ids[row * columns + i];
BrowserAccessibilityWin* cell =
- manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
- if (cell && cell->role_ == WebKit::WebAXRoleRowHeader) {
- string16 cell_name = cell->GetString16Attribute(
+ manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
+ if (cell && cell->blink_role() == blink::WebAXRoleRowHeader) {
+ base::string16 cell_name = cell->GetString16Attribute(
AccessibilityNodeData::ATTR_NAME);
if (cell_name.size() > 0) {
*description = SysAllocString(cell_name.c_str());
@@ -1338,7 +1342,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowDescription(long row,
STDMETHODIMP BrowserAccessibilityWin::get_rowExtentAt(long row,
long column,
long* n_rows_spanned) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!n_rows_spanned)
@@ -1361,7 +1365,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowExtentAt(long row,
AccessibilityNodeData::ATTR_CELL_IDS);
int cell_id = cell_ids[row * columns + column];
BrowserAccessibilityWin* cell =
- manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
+ manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
int rowspan;
if (cell &&
cell->GetIntAttribute(
@@ -1383,7 +1387,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeader(
STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long cell_index,
long* row_index) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!row_index)
@@ -1399,7 +1403,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long cell_index,
int cell_id = unique_cell_ids[cell_index];
BrowserAccessibilityWin* cell =
- manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
+ manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
int cell_row_index;
if (cell &&
cell->GetIntAttribute(
@@ -1414,7 +1418,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long cell_index,
STDMETHODIMP BrowserAccessibilityWin::get_selectedChildren(long max_children,
long** children,
long* n_children) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!children || !n_children)
@@ -1428,7 +1432,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedChildren(long max_children,
STDMETHODIMP BrowserAccessibilityWin::get_selectedColumns(long max_columns,
long** columns,
long* n_columns) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!columns || !n_columns)
@@ -1442,7 +1446,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedColumns(long max_columns,
STDMETHODIMP BrowserAccessibilityWin::get_selectedRows(long max_rows,
long** rows,
long* n_rows) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!rows || !n_rows)
@@ -1454,7 +1458,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedRows(long max_rows,
}
STDMETHODIMP BrowserAccessibilityWin::get_summary(IUnknown** accessible) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!accessible)
@@ -1467,7 +1471,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_summary(IUnknown** accessible) {
STDMETHODIMP BrowserAccessibilityWin::get_isColumnSelected(
long column,
boolean* is_selected) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!is_selected)
@@ -1480,7 +1484,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_isColumnSelected(
STDMETHODIMP BrowserAccessibilityWin::get_isRowSelected(long row,
boolean* is_selected) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!is_selected)
@@ -1494,7 +1498,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_isRowSelected(long row,
STDMETHODIMP BrowserAccessibilityWin::get_isSelected(long row,
long column,
boolean* is_selected) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!is_selected)
@@ -1512,7 +1516,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtentsAtIndex(
long* row_extents,
long* column_extents,
boolean* is_selected) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!row || !column || !row_extents || !column_extents || !is_selected)
@@ -1528,7 +1532,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtentsAtIndex(
int cell_id = unique_cell_ids[index];
BrowserAccessibilityWin* cell =
- manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
+ manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
int rowspan;
int colspan;
if (cell &&
@@ -1563,7 +1567,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelectedCells(long* cell_count) {
STDMETHODIMP BrowserAccessibilityWin::get_selectedCells(
IUnknown*** cells,
long* n_selected_cells) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!cells || !n_selected_cells)
@@ -1576,7 +1580,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedCells(
STDMETHODIMP BrowserAccessibilityWin::get_selectedColumns(long** columns,
long* n_columns) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!columns || !n_columns)
@@ -1589,7 +1593,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedColumns(long** columns,
STDMETHODIMP BrowserAccessibilityWin::get_selectedRows(long** rows,
long* n_rows) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!rows || !n_rows)
@@ -1607,7 +1611,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedRows(long** rows,
STDMETHODIMP BrowserAccessibilityWin::get_columnExtent(
long* n_columns_spanned) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!n_columns_spanned)
@@ -1627,7 +1631,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnExtent(
STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells(
IUnknown*** cell_accessibles,
long* n_column_header_cells) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!cell_accessibles || !n_column_header_cells)
@@ -1642,7 +1646,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells(
}
BrowserAccessibility* table = parent();
- while (table && table->role() != WebKit::WebAXRoleTable)
+ while (table && table->role() != blink::WebAXRoleTable)
table = table->parent();
if (!table) {
NOTREACHED();
@@ -1666,8 +1670,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells(
for (int i = 0; i < rows; ++i) {
int cell_id = cell_ids[i * columns + column];
BrowserAccessibilityWin* cell =
- manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
- if (cell && cell->role_ == WebKit::WebAXRoleColumnHeader)
+ manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
+ if (cell && cell->blink_role() == blink::WebAXRoleColumnHeader)
(*n_column_header_cells)++;
}
@@ -1676,11 +1680,10 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells(
int index = 0;
for (int i = 0; i < rows; ++i) {
int cell_id = cell_ids[i * columns + column];
- BrowserAccessibilityWin* cell =
- manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
- if (cell && cell->role_ == WebKit::WebAXRoleColumnHeader) {
- (*cell_accessibles)[index] =
- static_cast<IAccessible*>(cell->NewReference());
+ BrowserAccessibility* cell = manager()->GetFromRendererID(cell_id);
+ if (cell && cell->role() == blink::WebAXRoleColumnHeader) {
+ (*cell_accessibles)[index] = static_cast<IAccessible*>(
+ cell->ToBrowserAccessibilityWin()->NewReference());
++index;
}
}
@@ -1689,7 +1692,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells(
}
STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long* column_index) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!column_index)
@@ -1706,7 +1709,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long* column_index) {
}
STDMETHODIMP BrowserAccessibilityWin::get_rowExtent(long* n_rows_spanned) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!n_rows_spanned)
@@ -1726,7 +1729,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowExtent(long* n_rows_spanned) {
STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells(
IUnknown*** cell_accessibles,
long* n_row_header_cells) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!cell_accessibles || !n_row_header_cells)
@@ -1741,7 +1744,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells(
}
BrowserAccessibility* table = parent();
- while (table && table->role() != WebKit::WebAXRoleTable)
+ while (table && table->role() != blink::WebAXRoleTable)
table = table->parent();
if (!table) {
NOTREACHED();
@@ -1764,9 +1767,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells(
for (int i = 0; i < columns; ++i) {
int cell_id = cell_ids[row * columns + i];
- BrowserAccessibilityWin* cell =
- manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
- if (cell && cell->role_ == WebKit::WebAXRoleRowHeader)
+ BrowserAccessibility* cell = manager()->GetFromRendererID(cell_id);
+ if (cell && cell->role() == blink::WebAXRoleRowHeader)
(*n_row_header_cells)++;
}
@@ -1775,11 +1777,10 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells(
int index = 0;
for (int i = 0; i < columns; ++i) {
int cell_id = cell_ids[row * columns + i];
- BrowserAccessibilityWin* cell =
- manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin();
- if (cell && cell->role_ == WebKit::WebAXRoleRowHeader) {
- (*cell_accessibles)[index] =
- static_cast<IAccessible*>(cell->NewReference());
+ BrowserAccessibility* cell = manager()->GetFromRendererID(cell_id);
+ if (cell && cell->role() == blink::WebAXRoleRowHeader) {
+ (*cell_accessibles)[index] = static_cast<IAccessible*>(
+ cell->ToBrowserAccessibilityWin()->NewReference());
++index;
}
}
@@ -1788,7 +1789,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells(
}
STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long* row_index) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!row_index)
@@ -1803,7 +1804,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long* row_index) {
}
STDMETHODIMP BrowserAccessibilityWin::get_isSelected(boolean* is_selected) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!is_selected)
@@ -1819,7 +1820,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtents(
long* row_extents,
long* column_extents,
boolean* is_selected) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!row_index ||
@@ -1853,7 +1854,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtents(
}
STDMETHODIMP BrowserAccessibilityWin::get_table(IUnknown** table) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!table)
@@ -1866,7 +1867,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_table(IUnknown** table) {
GetIntAttribute(AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_INDEX, &column);
BrowserAccessibility* find_table = parent();
- while (find_table && find_table->role() != WebKit::WebAXRoleTable)
+ while (find_table && find_table->role() != blink::WebAXRoleTable)
find_table = find_table->parent();
if (!find_table) {
NOTREACHED();
@@ -1884,7 +1885,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_table(IUnknown** table) {
//
STDMETHODIMP BrowserAccessibilityWin::get_nCharacters(LONG* n_characters) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!n_characters)
@@ -1895,15 +1896,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_nCharacters(LONG* n_characters) {
}
STDMETHODIMP BrowserAccessibilityWin::get_caretOffset(LONG* offset) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!offset)
return E_INVALIDARG;
*offset = 0;
- if (role_ == WebKit::WebAXRoleTextField ||
- role_ == WebKit::WebAXRoleTextArea) {
+ if (blink_role() == blink::WebAXRoleTextField ||
+ blink_role() == blink::WebAXRoleTextArea) {
int sel_start = 0;
if (GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_START,
&sel_start))
@@ -1913,16 +1914,56 @@ STDMETHODIMP BrowserAccessibilityWin::get_caretOffset(LONG* offset) {
return S_OK;
}
+STDMETHODIMP BrowserAccessibilityWin::get_characterExtents(
+ LONG offset,
+ enum IA2CoordinateType coordinate_type,
+ LONG* out_x,
+ LONG* out_y,
+ LONG* out_width,
+ LONG* out_height) {
+ if (!instance_active())
+ return E_FAIL;
+
+ if (!out_x || !out_y || !out_width || !out_height)
+ return E_INVALIDARG;
+
+ const base::string16& text_str = TextForIAccessibleText();
+ HandleSpecialTextOffset(text_str, &offset);
+
+ if (offset < 0 || offset > static_cast<LONG>(text_str.size()))
+ return E_INVALIDARG;
+
+ if (blink_role() != blink::WebAXRoleStaticText)
+ return E_FAIL;
+
+ gfx::Rect character_bounds;
+ if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) {
+ character_bounds = GetGlobalBoundsForRange(offset, 1);
+ } else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) {
+ character_bounds = GetLocalBoundsForRange(offset, 1);
+ character_bounds -= location().OffsetFromOrigin();
+ } else {
+ return E_INVALIDARG;
+ }
+
+ *out_x = character_bounds.x();
+ *out_y = character_bounds.y();
+ *out_width = character_bounds.width();
+ *out_height = character_bounds.height();
+
+ return S_OK;
+}
+
STDMETHODIMP BrowserAccessibilityWin::get_nSelections(LONG* n_selections) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!n_selections)
return E_INVALIDARG;
*n_selections = 0;
- if (role_ == WebKit::WebAXRoleTextField ||
- role_ == WebKit::WebAXRoleTextArea) {
+ if (blink_role() == blink::WebAXRoleTextField ||
+ blink_role() == blink::WebAXRoleTextArea) {
int sel_start = 0;
int sel_end = 0;
if (GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_START,
@@ -1938,7 +1979,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelections(LONG* n_selections) {
STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index,
LONG* start_offset,
LONG* end_offset) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!start_offset || !end_offset || selection_index != 0)
@@ -1946,8 +1987,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index,
*start_offset = 0;
*end_offset = 0;
- if (role_ == WebKit::WebAXRoleTextField ||
- role_ == WebKit::WebAXRoleTextArea) {
+ if (blink_role() == blink::WebAXRoleTextField ||
+ blink_role() == blink::WebAXRoleTextArea) {
int sel_start = 0;
int sel_end = 0;
if (GetIntAttribute(
@@ -1964,13 +2005,13 @@ STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index,
STDMETHODIMP BrowserAccessibilityWin::get_text(LONG start_offset,
LONG end_offset,
BSTR* text) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!text)
return E_INVALIDARG;
- const string16& text_str = TextForIAccessibleText();
+ const base::string16& text_str = TextForIAccessibleText();
// Handle special text offsets.
HandleSpecialTextOffset(text_str, &start_offset);
@@ -1991,7 +2032,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_text(LONG start_offset,
if (end_offset > len)
return E_INVALIDARG;
- string16 substr = text_str.substr(start_offset, end_offset - start_offset);
+ base::string16 substr = text_str.substr(start_offset,
+ end_offset - start_offset);
if (substr.empty())
return S_FALSE;
@@ -2006,7 +2048,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textAtOffset(
LONG* start_offset,
LONG* end_offset,
BSTR* text) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!start_offset || !end_offset || !text)
@@ -2021,7 +2063,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textAtOffset(
return S_FALSE;
}
- const string16& text_str = TextForIAccessibleText();
+ const base::string16& text_str = TextForIAccessibleText();
*start_offset = FindBoundary(
text_str, boundary_type, offset, ui::BACKWARDS_DIRECTION);
@@ -2036,7 +2078,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textBeforeOffset(
LONG* start_offset,
LONG* end_offset,
BSTR* text) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!start_offset || !end_offset || !text)
@@ -2051,7 +2093,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textBeforeOffset(
return S_FALSE;
}
- const string16& text_str = TextForIAccessibleText();
+ const base::string16& text_str = TextForIAccessibleText();
*start_offset = FindBoundary(
text_str, boundary_type, offset, ui::BACKWARDS_DIRECTION);
@@ -2065,7 +2107,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textAfterOffset(
LONG* start_offset,
LONG* end_offset,
BSTR* text) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!start_offset || !end_offset || !text)
@@ -2080,7 +2122,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textAfterOffset(
return S_FALSE;
}
- const string16& text_str = TextForIAccessibleText();
+ const base::string16& text_str = TextForIAccessibleText();
*start_offset = offset;
*end_offset = FindBoundary(
@@ -2089,13 +2131,13 @@ STDMETHODIMP BrowserAccessibilityWin::get_textAfterOffset(
}
STDMETHODIMP BrowserAccessibilityWin::get_newText(IA2TextSegment* new_text) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!new_text)
return E_INVALIDARG;
- string16 text = TextForIAccessibleText();
+ base::string16 text = TextForIAccessibleText();
new_text->text = SysAllocString(text.c_str());
new_text->start = 0;
@@ -2104,7 +2146,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_newText(IA2TextSegment* new_text) {
}
STDMETHODIMP BrowserAccessibilityWin::get_oldText(IA2TextSegment* old_text) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!old_text)
@@ -2121,7 +2163,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_offsetAtPoint(
LONG y,
enum IA2CoordinateType coord_type,
LONG* offset) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!offset)
@@ -2153,52 +2195,52 @@ STDMETHODIMP BrowserAccessibilityWin::scrollSubstringToPoint(
STDMETHODIMP BrowserAccessibilityWin::addSelection(LONG start_offset,
LONG end_offset) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
- const string16& text_str = TextForIAccessibleText();
+ const base::string16& text_str = TextForIAccessibleText();
HandleSpecialTextOffset(text_str, &start_offset);
HandleSpecialTextOffset(text_str, &end_offset);
- manager_->SetTextSelection(*this, start_offset, end_offset);
+ manager()->SetTextSelection(*this, start_offset, end_offset);
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::removeSelection(LONG selection_index) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (selection_index != 0)
return E_INVALIDARG;
- manager_->SetTextSelection(*this, 0, 0);
+ manager()->SetTextSelection(*this, 0, 0);
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::setCaretOffset(LONG offset) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
- const string16& text_str = TextForIAccessibleText();
+ const base::string16& text_str = TextForIAccessibleText();
HandleSpecialTextOffset(text_str, &offset);
- manager_->SetTextSelection(*this, offset, offset);
+ manager()->SetTextSelection(*this, offset, offset);
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::setSelection(LONG selection_index,
LONG start_offset,
LONG end_offset) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (selection_index != 0)
return E_INVALIDARG;
- const string16& text_str = TextForIAccessibleText();
+ const base::string16& text_str = TextForIAccessibleText();
HandleSpecialTextOffset(text_str, &start_offset);
HandleSpecialTextOffset(text_str, &end_offset);
- manager_->SetTextSelection(*this, start_offset, end_offset);
+ manager()->SetTextSelection(*this, start_offset, end_offset);
return S_OK;
}
@@ -2207,7 +2249,7 @@ STDMETHODIMP BrowserAccessibilityWin::setSelection(LONG selection_index,
//
STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!hyperlink_count)
@@ -2220,7 +2262,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) {
STDMETHODIMP BrowserAccessibilityWin::get_hyperlink(
long index,
IAccessibleHyperlink** hyperlink) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!hyperlink ||
@@ -2230,7 +2272,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_hyperlink(
}
BrowserAccessibilityWin* child =
- children_[hyperlinks_[index]]->ToBrowserAccessibilityWin();
+ children()[hyperlinks_[index]]->ToBrowserAccessibilityWin();
*hyperlink = static_cast<IAccessibleHyperlink*>(child->NewReference());
return S_OK;
}
@@ -2238,7 +2280,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_hyperlink(
STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex(
long char_index,
long* hyperlink_index) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!hyperlink_index)
@@ -2263,7 +2305,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex(
//
STDMETHODIMP BrowserAccessibilityWin::get_currentValue(VARIANT* value) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!value)
@@ -2282,7 +2324,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_currentValue(VARIANT* value) {
}
STDMETHODIMP BrowserAccessibilityWin::get_minimumValue(VARIANT* value) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!value)
@@ -2301,7 +2343,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_minimumValue(VARIANT* value) {
}
STDMETHODIMP BrowserAccessibilityWin::get_maximumValue(VARIANT* value) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!value)
@@ -2329,7 +2371,7 @@ STDMETHODIMP BrowserAccessibilityWin::setCurrentValue(VARIANT new_value) {
//
STDMETHODIMP BrowserAccessibilityWin::get_URL(BSTR* url) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!url)
@@ -2339,7 +2381,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_URL(BSTR* url) {
}
STDMETHODIMP BrowserAccessibilityWin::get_title(BSTR* title) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!title)
@@ -2349,7 +2391,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_title(BSTR* title) {
}
STDMETHODIMP BrowserAccessibilityWin::get_mimeType(BSTR* mime_type) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!mime_type)
@@ -2360,7 +2402,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_mimeType(BSTR* mime_type) {
}
STDMETHODIMP BrowserAccessibilityWin::get_docType(BSTR* doc_type) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!doc_type)
@@ -2381,7 +2423,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nodeInfo(
unsigned int* num_children,
unsigned int* unique_id,
unsigned short* node_type) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!node_name || !name_space_id || !node_value || !num_children ||
@@ -2389,15 +2431,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_nodeInfo(
return E_INVALIDARG;
}
- string16 tag;
+ base::string16 tag;
if (GetString16Attribute(AccessibilityNodeData::ATTR_HTML_TAG, &tag))
*node_name = SysAllocString(tag.c_str());
else
*node_name = NULL;
*name_space_id = 0;
- *node_value = SysAllocString(UTF8ToUTF16(value_).c_str());
- *num_children = children_.size();
+ *node_value = SysAllocString(UTF8ToUTF16(value()).c_str());
+ *num_children = PlatformChildCount();
*unique_id = unique_id_win_;
if (ia_role_ == ROLE_SYSTEM_DOCUMENT) {
@@ -2418,22 +2460,22 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributes(
short* name_space_id,
BSTR* attrib_values,
unsigned short* num_attribs) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!attrib_names || !name_space_id || !attrib_values || !num_attribs)
return E_INVALIDARG;
*num_attribs = max_attribs;
- if (*num_attribs > html_attributes_.size())
- *num_attribs = html_attributes_.size();
+ if (*num_attribs > html_attributes().size())
+ *num_attribs = html_attributes().size();
for (unsigned short i = 0; i < *num_attribs; ++i) {
attrib_names[i] = SysAllocString(
- UTF8ToUTF16(html_attributes_[i].first).c_str());
+ UTF8ToUTF16(html_attributes()[i].first).c_str());
name_space_id[i] = 0;
attrib_values[i] = SysAllocString(
- UTF8ToUTF16(html_attributes_[i].second).c_str());
+ UTF8ToUTF16(html_attributes()[i].second).c_str());
}
return S_OK;
}
@@ -2443,7 +2485,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributesForNames(
BSTR* attrib_names,
short* name_space_id,
BSTR* attrib_values) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!attrib_names || !name_space_id || !attrib_values)
@@ -2453,10 +2495,10 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributesForNames(
name_space_id[i] = 0;
bool found = false;
std::string name = UTF16ToUTF8((LPCWSTR)attrib_names[i]);
- for (unsigned int j = 0; j < html_attributes_.size(); ++j) {
- if (html_attributes_[j].first == name) {
+ for (unsigned int j = 0; j < html_attributes().size(); ++j) {
+ if (html_attributes()[j].first == name) {
attrib_values[i] = SysAllocString(
- UTF8ToUTF16(html_attributes_[j].second).c_str());
+ UTF8ToUTF16(html_attributes()[j].second).c_str());
found = true;
break;
}
@@ -2474,7 +2516,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyle(
BSTR* style_properties,
BSTR* style_values,
unsigned short *num_style_properties) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!style_properties || !style_values)
@@ -2482,7 +2524,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyle(
// We only cache a single style property for now: DISPLAY
- string16 display;
+ base::string16 display;
if (max_style_properties == 0 ||
!GetString16Attribute(AccessibilityNodeData::ATTR_DISPLAY, &display)) {
*num_style_properties = 0;
@@ -2501,7 +2543,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyleForProperties(
boolean use_alternate_view,
BSTR* style_properties,
BSTR* style_values) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!style_properties || !style_values)
@@ -2510,10 +2552,10 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyleForProperties(
// We only cache a single style property for now: DISPLAY
for (unsigned short i = 0; i < num_style_properties; ++i) {
- string16 name = (LPCWSTR)style_properties[i];
+ base::string16 name = (LPCWSTR)style_properties[i];
StringToLowerASCII(&name);
if (name == L"display") {
- string16 display = GetString16Attribute(
+ base::string16 display = GetString16Attribute(
AccessibilityNodeData::ATTR_DISPLAY);
style_values[i] = SysAllocString(display.c_str());
} else {
@@ -2530,81 +2572,82 @@ STDMETHODIMP BrowserAccessibilityWin::scrollTo(boolean placeTopLeft) {
}
STDMETHODIMP BrowserAccessibilityWin::get_parentNode(ISimpleDOMNode** node) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!node)
return E_INVALIDARG;
- *node = parent_->ToBrowserAccessibilityWin()->NewReference();
+ *node = parent()->ToBrowserAccessibilityWin()->NewReference();
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::get_firstChild(ISimpleDOMNode** node) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!node)
return E_INVALIDARG;
- if (children_.empty()) {
+ if (PlatformChildCount() == 0) {
*node = NULL;
return S_FALSE;
}
- *node = children_[0]->ToBrowserAccessibilityWin()->NewReference();
+ *node = PlatformGetChild(0)->ToBrowserAccessibilityWin()->NewReference();
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::get_lastChild(ISimpleDOMNode** node) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!node)
return E_INVALIDARG;
- if (children_.empty()) {
+ if (PlatformChildCount() == 0) {
*node = NULL;
return S_FALSE;
}
- *node = (*children_.rbegin())->ToBrowserAccessibilityWin()->NewReference();
+ *node = PlatformGetChild(PlatformChildCount() - 1)
+ ->ToBrowserAccessibilityWin()->NewReference();
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::get_previousSibling(
ISimpleDOMNode** node) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!node)
return E_INVALIDARG;
- if (!parent_ || index_in_parent_ <= 0) {
+ if (!parent() || index_in_parent() <= 0) {
*node = NULL;
return S_FALSE;
}
- *node = parent_->children()[index_in_parent_ - 1]->
+ *node = parent()->children()[index_in_parent() - 1]->
ToBrowserAccessibilityWin()->NewReference();
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::get_nextSibling(ISimpleDOMNode** node) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!node)
return E_INVALIDARG;
- if (!parent_ ||
- index_in_parent_ < 0 ||
- index_in_parent_ >= static_cast<int>(parent_->children().size()) - 1) {
+ if (!parent() ||
+ index_in_parent() < 0 ||
+ index_in_parent() >= static_cast<int>(parent()->children().size()) - 1) {
*node = NULL;
return S_FALSE;
}
- *node = parent_->children()[index_in_parent_ + 1]->
+ *node = parent()->children()[index_in_parent() + 1]->
ToBrowserAccessibilityWin()->NewReference();
return S_OK;
}
@@ -2612,18 +2655,22 @@ STDMETHODIMP BrowserAccessibilityWin::get_nextSibling(ISimpleDOMNode** node) {
STDMETHODIMP BrowserAccessibilityWin::get_childAt(
unsigned int child_index,
ISimpleDOMNode** node) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!node)
return E_INVALIDARG;
- if (child_index < children_.size()) {
+ if (child_index >= PlatformChildCount())
+ return E_INVALIDARG;
+
+ BrowserAccessibility* child = PlatformGetChild(child_index);
+ if (!child) {
*node = NULL;
return S_FALSE;
}
- *node = children_[child_index]->ToBrowserAccessibilityWin()->NewReference();
+ *node = child->ToBrowserAccessibilityWin()->NewReference();
return S_OK;
}
@@ -2632,7 +2679,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_childAt(
//
STDMETHODIMP BrowserAccessibilityWin::get_domText(BSTR* dom_text) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
if (!dom_text)
@@ -2642,6 +2689,71 @@ STDMETHODIMP BrowserAccessibilityWin::get_domText(BSTR* dom_text) {
AccessibilityNodeData::ATTR_NAME, dom_text);
}
+STDMETHODIMP BrowserAccessibilityWin::get_clippedSubstringBounds(
+ unsigned int start_index,
+ unsigned int end_index,
+ int* out_x,
+ int* out_y,
+ int* out_width,
+ int* out_height) {
+ // TODO(dmazzoni): fully support this API by intersecting the
+ // rect with the container's rect.
+ return get_unclippedSubstringBounds(
+ start_index, end_index, out_x, out_y, out_width, out_height);
+}
+
+STDMETHODIMP BrowserAccessibilityWin::get_unclippedSubstringBounds(
+ unsigned int start_index,
+ unsigned int end_index,
+ int* out_x,
+ int* out_y,
+ int* out_width,
+ int* out_height) {
+ if (!instance_active())
+ return E_FAIL;
+
+ if (!out_x || !out_y || !out_width || !out_height)
+ return E_INVALIDARG;
+
+ const base::string16& text_str = TextForIAccessibleText();
+ if (start_index > text_str.size() ||
+ end_index > text_str.size() ||
+ start_index > end_index) {
+ return E_INVALIDARG;
+ }
+
+ if (blink_role() != blink::WebAXRoleStaticText)
+ return E_FAIL;
+
+ gfx::Rect bounds = GetGlobalBoundsForRange(
+ start_index, end_index - start_index);
+ *out_x = bounds.x();
+ *out_y = bounds.y();
+ *out_width = bounds.width();
+ *out_height = bounds.height();
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibilityWin::scrollToSubstring(
+ unsigned int start_index,
+ unsigned int end_index) {
+ if (!instance_active())
+ return E_FAIL;
+
+ const base::string16& text_str = TextForIAccessibleText();
+ if (start_index > text_str.size() ||
+ end_index > text_str.size() ||
+ start_index > end_index) {
+ return E_INVALIDARG;
+ }
+
+ manager()->ScrollToMakeVisible(*this, GetLocalBoundsForRange(
+ start_index, end_index - start_index));
+ manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this);
+
+ return S_OK;
+}
+
//
// IServiceProvider methods.
//
@@ -2649,7 +2761,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_domText(BSTR* dom_text) {
STDMETHODIMP BrowserAccessibilityWin::QueryService(REFGUID guidService,
REFIID riid,
void** object) {
- if (!instance_active_)
+ if (!instance_active())
return E_FAIL;
// The system uses IAccessible APIs for many purposes, but only
@@ -2662,7 +2774,7 @@ STDMETHODIMP BrowserAccessibilityWin::QueryService(REFGUID guidService,
// Special Mozilla extension: return the accessible for the root document.
// Screen readers use this to distinguish between a document loaded event
// on the root document vs on an iframe.
- return manager_->GetRoot()->ToBrowserAccessibilityWin()->QueryInterface(
+ return manager()->GetRoot()->ToBrowserAccessibilityWin()->QueryInterface(
IID_IAccessible2, object);
}
@@ -2708,7 +2820,7 @@ STDMETHODIMP BrowserAccessibilityWin::GetPatternProvider(PATTERNID id,
if (IsEditableText()) {
// The BrowserAccessibilityManager keeps track of instances when
// we don't want to show the on-screen keyboard.
- if (!manager_->IsOSKAllowed(GetGlobalBoundsRect()))
+ if (!manager()->IsOSKAllowed(GetGlobalBoundsRect()))
return E_NOTIMPL;
DVLOG(1) << "Returning UIA text provider";
@@ -2799,13 +2911,13 @@ void BrowserAccessibilityWin::PreInitialize() {
IntAttributeToIA2(AccessibilityNodeData::ATTR_HIERARCHICAL_LEVEL, "level");
// Expose the set size and position in set for listbox options.
- if (role_ == WebKit::WebAXRoleListBoxOption &&
- parent_ &&
- parent_->role() == WebKit::WebAXRoleListBox) {
+ if (blink_role() == blink::WebAXRoleListBoxOption &&
+ parent() &&
+ parent()->role() == blink::WebAXRoleListBox) {
ia2_attributes_.push_back(
- L"setsize:" + base::IntToString16(parent_->child_count()));
+ L"setsize:" + base::IntToString16(parent()->PlatformChildCount()));
ia2_attributes_.push_back(
- L"setsize:" + base::IntToString16(index_in_parent_ + 1));
+ L"setsize:" + base::IntToString16(index_in_parent() + 1));
}
if (ia_role_ == ROLE_SYSTEM_CHECKBUTTON ||
@@ -2840,15 +2952,15 @@ void BrowserAccessibilityWin::PreInitialize() {
// Expose table cell index.
if (ia_role_ == ROLE_SYSTEM_CELL) {
BrowserAccessibility* table = parent();
- while (table && table->role() != WebKit::WebAXRoleTable)
+ while (table && table->role() != blink::WebAXRoleTable)
table = table->parent();
if (table) {
const std::vector<int32>& unique_cell_ids = table->GetIntListAttribute(
AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS);
for (size_t i = 0; i < unique_cell_ids.size(); ++i) {
- if (unique_cell_ids[i] == renderer_id_) {
+ if (unique_cell_ids[i] == renderer_id()) {
ia2_attributes_.push_back(
- string16(L"table-cell-index:") + base::IntToString16(i));
+ base::string16(L"table-cell-index:") + base::IntToString16(i));
}
}
}
@@ -2896,25 +3008,25 @@ void BrowserAccessibilityWin::PreInitialize() {
// it's nonempty, and the help should become the description if
// there's no description - or the name if there's no name or description.
if (!description.empty()) {
- name_ = description;
+ set_name(description);
description.clear();
}
if (!help.empty() && description.empty()) {
description = help;
help.clear();
}
- if (!description.empty() && name_.empty() && !title_elem_id) {
- name_ = description;
+ if (!description.empty() && name().empty() && !title_elem_id) {
+ set_name(description);
description.clear();
}
// If it's a text field, also consider the placeholder.
std::string placeholder;
- if (role_ == WebKit::WebAXRoleTextField &&
- HasState(WebKit::WebAXStateFocusable) &&
+ if (blink_role() == blink::WebAXRoleTextField &&
+ HasState(blink::WebAXStateFocusable) &&
GetHtmlAttribute("placeholder", &placeholder)) {
- if (name_.empty() && !title_elem_id) {
- name_ = placeholder;
+ if (name().empty() && !title_elem_id) {
+ set_name(placeholder);
} else if (description.empty()) {
description = placeholder;
}
@@ -2924,25 +3036,27 @@ void BrowserAccessibilityWin::PreInitialize() {
SetStringAttribute(AccessibilityNodeData::ATTR_HELP, help);
// On Windows, the value of a document should be its url.
- if (role_ == WebKit::WebAXRoleRootWebArea ||
- role_ == WebKit::WebAXRoleWebArea) {
- GetStringAttribute(AccessibilityNodeData::ATTR_DOC_URL, &value_);
+ if (blink_role() == blink::WebAXRoleRootWebArea ||
+ blink_role() == blink::WebAXRoleWebArea) {
+ set_value(GetStringAttribute(AccessibilityNodeData::ATTR_DOC_URL));
}
// For certain roles (listbox option, static text, and list marker)
// WebKit stores the main accessible text in the "value" - swap it so
// that it's the "name".
- if (name_.empty() &&
- (role_ == WebKit::WebAXRoleListBoxOption ||
- role_ == WebKit::WebAXRoleStaticText ||
- role_ == WebKit::WebAXRoleListMarker)) {
- name_.swap(value_);
+ if (name().empty() &&
+ (blink_role() == blink::WebAXRoleListBoxOption ||
+ blink_role() == blink::WebAXRoleStaticText ||
+ blink_role() == blink::WebAXRoleListMarker)) {
+ std::string tmp = value();
+ set_value(name());
+ set_name(tmp);
}
// 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))
- GetStringAttribute(AccessibilityNodeData::ATTR_URL, &value_);
+ if (value().empty() && (ia_state_ & STATE_SYSTEM_LINKED))
+ set_value(GetStringAttribute(AccessibilityNodeData::ATTR_URL));
// Clear any old relationships between this node and other nodes.
for (size_t i = 0; i < relations_.size(); ++i)
@@ -2970,9 +3084,9 @@ void BrowserAccessibilityWin::PostInitialize() {
hyperlink_offset_to_index_.clear();
hyperlinks_.clear();
hypertext_.clear();
- for (unsigned int i = 0; i < children().size(); ++i) {
- BrowserAccessibility* child = children()[i];
- if (child->role() == WebKit::WebAXRoleStaticText) {
+ for (unsigned int i = 0; i < PlatformChildCount(); ++i) {
+ BrowserAccessibility* child = PlatformGetChild(i);
+ if (child->role() == blink::WebAXRoleStaticText) {
hypertext_ += UTF8ToUTF16(child->name());
} else {
hyperlink_offset_to_index_[hypertext_.size()] = hyperlinks_.size();
@@ -2983,15 +3097,15 @@ void BrowserAccessibilityWin::PostInitialize() {
DCHECK_EQ(hyperlink_offset_to_index_.size(), hyperlinks_.size());
// Fire an event when an alert first appears.
- if (role_ == WebKit::WebAXRoleAlert && first_time_)
- manager_->NotifyAccessibilityEvent(WebKit::WebAXEventAlert, this);
+ if (blink_role() == blink::WebAXRoleAlert && first_time_)
+ manager()->NotifyAccessibilityEvent(blink::WebAXEventAlert, this);
// Fire events if text has changed.
- string16 text = TextForIAccessibleText();
+ base::string16 text = TextForIAccessibleText();
if (previous_text_ != text) {
if (!previous_text_.empty() && !text.empty()) {
- manager_->NotifyAccessibilityEvent(
- WebKit::WebAXEventShow, this);
+ manager()->NotifyAccessibilityEvent(
+ blink::WebAXEventShow, this);
}
// TODO(dmazzoni): Look into HIDE events, too.
@@ -3000,16 +3114,16 @@ void BrowserAccessibilityWin::PostInitialize() {
previous_text_ = text;
}
+ BrowserAccessibilityManagerWin* manager =
+ this->manager()->ToBrowserAccessibilityManagerWin();
+
// Fire events if the state has changed.
if (!first_time_ && ia_state_ != old_ia_state_) {
- BrowserAccessibilityManagerWin* manager =
- manager_->ToBrowserAccessibilityManagerWin();
-
// 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 (role_ == WebKit::WebAXRoleListBoxOption &&
+ if (blink_role() == blink::WebAXRoleListBoxOption &&
(ia_state_ & STATE_SYSTEM_FOCUSABLE) &&
(ia_state_ & STATE_SYSTEM_SELECTABLE) &&
(ia_state_ & STATE_SYSTEM_FOCUSED) &&
@@ -3030,6 +3144,20 @@ void BrowserAccessibilityWin::PostInitialize() {
old_ia_state_ = ia_state_;
}
+ // Fire an event if this container object has scrolled.
+ int sx = 0;
+ int sy = 0;
+ if (GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X, &sx) &&
+ GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_Y, &sy)) {
+ if (!first_time_ &&
+ (sx != previous_scroll_x_ || sy != previous_scroll_y_)) {
+ manager->MaybeCallNotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND,
+ unique_id_win());
+ }
+ previous_scroll_x_ = sx;
+ previous_scroll_y_ = sy;
+ }
+
first_time_ = false;
}
@@ -3047,7 +3175,7 @@ bool BrowserAccessibilityWin::IsNative() const {
void BrowserAccessibilityWin::SetLocation(const gfx::Rect& new_location) {
BrowserAccessibility::SetLocation(new_location);
- manager_->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent(
+ manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent(
EVENT_OBJECT_LOCATIONCHANGE, unique_id_win());
}
@@ -3065,17 +3193,17 @@ BrowserAccessibilityWin* BrowserAccessibilityWin::GetTargetFromChildID(
if (child_id == CHILDID_SELF)
return this;
- if (child_id >= 1 && child_id <= static_cast<LONG>(children_.size()))
- return children_[child_id - 1]->ToBrowserAccessibilityWin();
+ if (child_id >= 1 && child_id <= static_cast<LONG>(PlatformChildCount()))
+ return PlatformGetChild(child_id - 1)->ToBrowserAccessibilityWin();
- return manager_->ToBrowserAccessibilityManagerWin()->
+ return manager()->ToBrowserAccessibilityManagerWin()->
GetFromUniqueIdWin(child_id);
}
HRESULT BrowserAccessibilityWin::GetStringAttributeAsBstr(
AccessibilityNodeData::StringAttribute attribute,
BSTR* value_bstr) {
- string16 str;
+ base::string16 str;
if (!GetString16Attribute(attribute, &str))
return S_FALSE;
@@ -3092,7 +3220,7 @@ HRESULT BrowserAccessibilityWin::GetStringAttributeAsBstr(
void BrowserAccessibilityWin::StringAttributeToIA2(
AccessibilityNodeData::StringAttribute attribute,
const char* ia2_attr) {
- string16 value;
+ base::string16 value;
if (GetString16Attribute(attribute, &value))
ia2_attributes_.push_back(ASCIIToUTF16(ia2_attr) + L":" + value);
}
@@ -3117,9 +3245,10 @@ void BrowserAccessibilityWin::IntAttributeToIA2(
}
}
-string16 BrowserAccessibilityWin::GetValueText() {
+base::string16 BrowserAccessibilityWin::GetValueText() {
float fval;
- string16 value = UTF8ToUTF16(value_);
+ base::string16 value = UTF8ToUTF16(this->value());
+
if (value.empty() &&
GetFloatAttribute(AccessibilityNodeData::ATTR_VALUE_FOR_RANGE, &fval)) {
value = UTF8ToUTF16(base::DoubleToString(fval));
@@ -3127,15 +3256,16 @@ string16 BrowserAccessibilityWin::GetValueText() {
return value;
}
-string16 BrowserAccessibilityWin::TextForIAccessibleText() {
+base::string16 BrowserAccessibilityWin::TextForIAccessibleText() {
if (IsEditableText())
- return UTF8ToUTF16(value_);
- return (role_ == WebKit::WebAXRoleStaticText) ?
- UTF8ToUTF16(name_) : hypertext_;
+ return UTF8ToUTF16(value());
+ return (blink_role() == blink::WebAXRoleStaticText) ?
+ UTF8ToUTF16(name()) : hypertext_;
}
-void BrowserAccessibilityWin::HandleSpecialTextOffset(const string16& text,
- LONG* offset) {
+void BrowserAccessibilityWin::HandleSpecialTextOffset(
+ const base::string16& text,
+ LONG* offset) {
if (*offset == IA2_TEXT_OFFSET_LENGTH)
*offset = static_cast<LONG>(text.size());
else if (*offset == IA2_TEXT_OFFSET_CARET)
@@ -3158,7 +3288,7 @@ ui::TextBoundaryType BrowserAccessibilityWin::IA2TextBoundaryToTextBoundary(
}
LONG BrowserAccessibilityWin::FindBoundary(
- const string16& text,
+ const base::string16& text,
IA2TextBoundaryType ia2_boundary,
LONG start_offset,
ui::TextBoundaryDirection direction) {
@@ -3172,7 +3302,7 @@ LONG BrowserAccessibilityWin::FindBoundary(
BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromRendererID(
int32 renderer_id) {
- return manager_->GetFromRendererID(renderer_id)->ToBrowserAccessibilityWin();
+ return manager()->GetFromRendererID(renderer_id)->ToBrowserAccessibilityWin();
}
void BrowserAccessibilityWin::InitRoleAndState() {
@@ -3180,62 +3310,62 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia2_state_ = IA2_STATE_OPAQUE;
ia2_attributes_.clear();
- if (HasState(WebKit::WebAXStateBusy))
+ if (HasState(blink::WebAXStateBusy))
ia_state_ |= STATE_SYSTEM_BUSY;
- if (HasState(WebKit::WebAXStateChecked))
+ if (HasState(blink::WebAXStateChecked))
ia_state_ |= STATE_SYSTEM_CHECKED;
- if (HasState(WebKit::WebAXStateCollapsed))
+ if (HasState(blink::WebAXStateCollapsed))
ia_state_ |= STATE_SYSTEM_COLLAPSED;
- if (HasState(WebKit::WebAXStateExpanded))
+ if (HasState(blink::WebAXStateExpanded))
ia_state_ |= STATE_SYSTEM_EXPANDED;
- if (HasState(WebKit::WebAXStateFocusable))
+ if (HasState(blink::WebAXStateFocusable))
ia_state_ |= STATE_SYSTEM_FOCUSABLE;
- if (HasState(WebKit::WebAXStateHaspopup))
+ if (HasState(blink::WebAXStateHaspopup))
ia_state_ |= STATE_SYSTEM_HASPOPUP;
- if (HasState(WebKit::WebAXStateHovered))
+ if (HasState(blink::WebAXStateHovered))
ia_state_ |= STATE_SYSTEM_HOTTRACKED;
- if (HasState(WebKit::WebAXStateIndeterminate))
+ if (HasState(blink::WebAXStateIndeterminate))
ia_state_ |= STATE_SYSTEM_INDETERMINATE;
- if (HasState(WebKit::WebAXStateInvisible))
+ if (HasState(blink::WebAXStateInvisible))
ia_state_ |= STATE_SYSTEM_INVISIBLE;
- if (HasState(WebKit::WebAXStateLinked))
+ if (HasState(blink::WebAXStateLinked))
ia_state_ |= STATE_SYSTEM_LINKED;
- if (HasState(WebKit::WebAXStateMultiselectable)) {
+ if (HasState(blink::WebAXStateMultiselectable)) {
ia_state_ |= STATE_SYSTEM_EXTSELECTABLE;
ia_state_ |= STATE_SYSTEM_MULTISELECTABLE;
}
// TODO(ctguil): Support STATE_SYSTEM_EXTSELECTABLE/accSelect.
- if (HasState(WebKit::WebAXStateOffscreen))
+ if (HasState(blink::WebAXStateOffscreen))
ia_state_ |= STATE_SYSTEM_OFFSCREEN;
- if (HasState(WebKit::WebAXStatePressed))
+ if (HasState(blink::WebAXStatePressed))
ia_state_ |= STATE_SYSTEM_PRESSED;
- if (HasState(WebKit::WebAXStateProtected))
+ if (HasState(blink::WebAXStateProtected))
ia_state_ |= STATE_SYSTEM_PROTECTED;
- if (HasState(WebKit::WebAXStateRequired))
+ if (HasState(blink::WebAXStateRequired))
ia2_state_ |= IA2_STATE_REQUIRED;
- if (HasState(WebKit::WebAXStateSelectable))
+ if (HasState(blink::WebAXStateSelectable))
ia_state_ |= STATE_SYSTEM_SELECTABLE;
- if (HasState(WebKit::WebAXStateSelected))
+ if (HasState(blink::WebAXStateSelected))
ia_state_ |= STATE_SYSTEM_SELECTED;
- if (HasState(WebKit::WebAXStateVisited))
+ if (HasState(blink::WebAXStateVisited))
ia_state_ |= STATE_SYSTEM_TRAVERSED;
- if (!HasState(WebKit::WebAXStateEnabled))
+ if (!HasState(blink::WebAXStateEnabled))
ia_state_ |= STATE_SYSTEM_UNAVAILABLE;
- if (HasState(WebKit::WebAXStateVertical)) {
+ if (HasState(blink::WebAXStateVertical)) {
ia2_state_ |= IA2_STATE_VERTICAL;
} else {
ia2_state_ |= IA2_STATE_HORIZONTAL;
}
- if (HasState(WebKit::WebAXStateVisited))
+ if (HasState(blink::WebAXStateVisited))
ia_state_ |= STATE_SYSTEM_TRAVERSED;
// WebKit marks everything as readonly unless it's editable text, so if it's
// not readonly, mark it as editable now. The final computation of the
// READONLY state for MSAA is below, after the switch.
- if (!HasState(WebKit::WebAXStateReadonly))
+ if (!HasState(blink::WebAXStateReadonly))
ia2_state_ |= IA2_STATE_EDITABLE;
- string16 invalid;
+ base::string16 invalid;
if (GetHtmlAttribute("aria-invalid", &invalid))
ia2_state_ |= IA2_STATE_INVALID_ENTRY;
@@ -3245,30 +3375,30 @@ void BrowserAccessibilityWin::InitRoleAndState() {
if (GetBoolAttribute(AccessibilityNodeData::ATTR_CAN_SET_VALUE))
ia2_state_ |= IA2_STATE_EDITABLE;
- string16 html_tag = GetString16Attribute(
+ base::string16 html_tag = GetString16Attribute(
AccessibilityNodeData::ATTR_HTML_TAG);
ia_role_ = 0;
ia2_role_ = 0;
- switch (role_) {
- case WebKit::WebAXRoleAlert:
+ switch (blink_role()) {
+ case blink::WebAXRoleAlert:
ia_role_ = ROLE_SYSTEM_ALERT;
break;
- case WebKit::WebAXRoleAlertDialog:
+ case blink::WebAXRoleAlertDialog:
ia_role_ = ROLE_SYSTEM_DIALOG;
break;
- case WebKit::WebAXRoleApplication:
+ case blink::WebAXRoleApplication:
ia_role_ = ROLE_SYSTEM_APPLICATION;
break;
- case WebKit::WebAXRoleArticle:
+ case blink::WebAXRoleArticle:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleBusyIndicator:
+ case blink::WebAXRoleBusyIndicator:
ia_role_ = ROLE_SYSTEM_ANIMATION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleButton:
+ case blink::WebAXRoleButton:
ia_role_ = ROLE_SYSTEM_PUSHBUTTON;
bool is_aria_pressed_defined;
bool is_mixed;
@@ -3279,7 +3409,7 @@ void BrowserAccessibilityWin::InitRoleAndState() {
if (is_mixed)
ia_state_ |= STATE_SYSTEM_MIXED;
break;
- case WebKit::WebAXRoleCanvas:
+ case blink::WebAXRoleCanvas:
if (GetBoolAttribute(AccessibilityNodeData::ATTR_CANVAS_HAS_FALLBACK)) {
role_name_ = L"canvas";
ia2_role_ = IA2_ROLE_CANVAS;
@@ -3287,79 +3417,79 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_role_ = ROLE_SYSTEM_GRAPHIC;
}
break;
- case WebKit::WebAXRoleCell:
+ case blink::WebAXRoleCell:
ia_role_ = ROLE_SYSTEM_CELL;
break;
- case WebKit::WebAXRoleCheckBox:
+ case blink::WebAXRoleCheckBox:
ia_role_ = ROLE_SYSTEM_CHECKBUTTON;
break;
- case WebKit::WebAXRoleColorWell:
+ case blink::WebAXRoleColorWell:
ia_role_ = ROLE_SYSTEM_CLIENT;
ia2_role_ = IA2_ROLE_COLOR_CHOOSER;
break;
- case WebKit::WebAXRoleColumn:
+ case blink::WebAXRoleColumn:
ia_role_ = ROLE_SYSTEM_COLUMN;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleColumnHeader:
+ case blink::WebAXRoleColumnHeader:
ia_role_ = ROLE_SYSTEM_COLUMNHEADER;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleComboBox:
+ case blink::WebAXRoleComboBox:
ia_role_ = ROLE_SYSTEM_COMBOBOX;
break;
- case WebKit::WebAXRoleDiv:
+ case blink::WebAXRoleDiv:
role_name_ = L"div";
ia2_role_ = IA2_ROLE_SECTION;
break;
- case WebKit::WebAXRoleDefinition:
+ case blink::WebAXRoleDefinition:
role_name_ = html_tag;
ia2_role_ = IA2_ROLE_PARAGRAPH;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleDescriptionListDetail:
+ case blink::WebAXRoleDescriptionListDetail:
role_name_ = html_tag;
ia2_role_ = IA2_ROLE_PARAGRAPH;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleDescriptionListTerm:
+ case blink::WebAXRoleDescriptionListTerm:
ia_role_ = ROLE_SYSTEM_LISTITEM;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleDialog:
+ case blink::WebAXRoleDialog:
ia_role_ = ROLE_SYSTEM_DIALOG;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleDisclosureTriangle:
+ case blink::WebAXRoleDisclosureTriangle:
ia_role_ = ROLE_SYSTEM_OUTLINEBUTTON;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleDocument:
- case WebKit::WebAXRoleRootWebArea:
- case WebKit::WebAXRoleWebArea:
+ case blink::WebAXRoleDocument:
+ case blink::WebAXRoleRootWebArea:
+ case blink::WebAXRoleWebArea:
ia_role_ = ROLE_SYSTEM_DOCUMENT;
ia_state_ |= STATE_SYSTEM_READONLY;
ia_state_ |= STATE_SYSTEM_FOCUSABLE;
break;
- case WebKit::WebAXRoleEditableText:
+ case blink::WebAXRoleEditableText:
ia_role_ = ROLE_SYSTEM_TEXT;
ia2_state_ |= IA2_STATE_SINGLE_LINE;
ia2_state_ |= IA2_STATE_EDITABLE;
break;
- case WebKit::WebAXRoleForm:
+ case blink::WebAXRoleForm:
role_name_ = L"form";
ia2_role_ = IA2_ROLE_FORM;
break;
- case WebKit::WebAXRoleFooter:
+ case blink::WebAXRoleFooter:
ia_role_ = IA2_ROLE_FOOTER;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleGrid:
+ case blink::WebAXRoleGrid:
ia_role_ = ROLE_SYSTEM_TABLE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleGroup: {
- string16 aria_role = GetString16Attribute(
+ case blink::WebAXRoleGroup: {
+ base::string16 aria_role = GetString16Attribute(
AccessibilityNodeData::ATTR_ROLE);
if (aria_role == L"group" || html_tag == L"fieldset") {
ia_role_ = ROLE_SYSTEM_GROUPING;
@@ -3375,189 +3505,189 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_state_ |= STATE_SYSTEM_READONLY;
break;
}
- case WebKit::WebAXRoleGrowArea:
+ case blink::WebAXRoleGrowArea:
ia_role_ = ROLE_SYSTEM_GRIP;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleHeading:
+ case blink::WebAXRoleHeading:
role_name_ = html_tag;
ia2_role_ = IA2_ROLE_HEADING;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleHorizontalRule:
+ case blink::WebAXRoleHorizontalRule:
ia_role_ = ROLE_SYSTEM_SEPARATOR;
break;
- case WebKit::WebAXRoleImage:
+ case blink::WebAXRoleImage:
ia_role_ = ROLE_SYSTEM_GRAPHIC;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleImageMap:
+ case blink::WebAXRoleImageMap:
role_name_ = html_tag;
ia2_role_ = IA2_ROLE_IMAGE_MAP;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleImageMapLink:
+ case blink::WebAXRoleImageMapLink:
ia_role_ = ROLE_SYSTEM_LINK;
ia_state_ |= STATE_SYSTEM_LINKED;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleLabel:
+ case blink::WebAXRoleLabel:
ia_role_ = ROLE_SYSTEM_TEXT;
ia2_role_ = IA2_ROLE_LABEL;
break;
- case WebKit::WebAXRoleBanner:
- case WebKit::WebAXRoleComplementary:
- case WebKit::WebAXRoleContentInfo:
- case WebKit::WebAXRoleMain:
- case WebKit::WebAXRoleNavigation:
- case WebKit::WebAXRoleSearch:
+ case blink::WebAXRoleBanner:
+ case blink::WebAXRoleComplementary:
+ case blink::WebAXRoleContentInfo:
+ case blink::WebAXRoleMain:
+ case blink::WebAXRoleNavigation:
+ case blink::WebAXRoleSearch:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleLink:
+ case blink::WebAXRoleLink:
ia_role_ = ROLE_SYSTEM_LINK;
ia_state_ |= STATE_SYSTEM_LINKED;
break;
- case WebKit::WebAXRoleList:
+ case blink::WebAXRoleList:
ia_role_ = ROLE_SYSTEM_LIST;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleListBox:
+ case blink::WebAXRoleListBox:
ia_role_ = ROLE_SYSTEM_LIST;
break;
- case WebKit::WebAXRoleListBoxOption:
+ case blink::WebAXRoleListBoxOption:
ia_role_ = ROLE_SYSTEM_LISTITEM;
if (ia_state_ & STATE_SYSTEM_SELECTABLE) {
ia_state_ |= STATE_SYSTEM_FOCUSABLE;
- if (HasState(WebKit::WebAXStateFocused))
+ if (HasState(blink::WebAXStateFocused))
ia_state_ |= STATE_SYSTEM_FOCUSED;
}
break;
- case WebKit::WebAXRoleListItem:
+ case blink::WebAXRoleListItem:
ia_role_ = ROLE_SYSTEM_LISTITEM;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleListMarker:
+ case blink::WebAXRoleListMarker:
ia_role_ = ROLE_SYSTEM_TEXT;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleMath:
+ case blink::WebAXRoleMath:
ia_role_ = ROLE_SYSTEM_EQUATION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleMenu:
- case WebKit::WebAXRoleMenuButton:
+ case blink::WebAXRoleMenu:
+ case blink::WebAXRoleMenuButton:
ia_role_ = ROLE_SYSTEM_MENUPOPUP;
break;
- case WebKit::WebAXRoleMenuBar:
+ case blink::WebAXRoleMenuBar:
ia_role_ = ROLE_SYSTEM_MENUBAR;
break;
- case WebKit::WebAXRoleMenuItem:
+ case blink::WebAXRoleMenuItem:
ia_role_ = ROLE_SYSTEM_MENUITEM;
break;
- case WebKit::WebAXRoleMenuListPopup:
+ case blink::WebAXRoleMenuListPopup:
ia_role_ = ROLE_SYSTEM_CLIENT;
break;
- case WebKit::WebAXRoleMenuListOption:
+ case blink::WebAXRoleMenuListOption:
ia_role_ = ROLE_SYSTEM_LISTITEM;
if (ia_state_ & STATE_SYSTEM_SELECTABLE) {
ia_state_ |= STATE_SYSTEM_FOCUSABLE;
- if (HasState(WebKit::WebAXStateFocused))
+ if (HasState(blink::WebAXStateFocused))
ia_state_ |= STATE_SYSTEM_FOCUSED;
}
break;
- case WebKit::WebAXRoleNote:
+ case blink::WebAXRoleNote:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_NOTE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleOutline:
+ case blink::WebAXRoleOutline:
ia_role_ = ROLE_SYSTEM_OUTLINE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleParagraph:
+ case blink::WebAXRoleParagraph:
role_name_ = L"P";
ia2_role_ = IA2_ROLE_PARAGRAPH;
break;
- case WebKit::WebAXRolePopUpButton:
+ case blink::WebAXRolePopUpButton:
if (html_tag == L"select") {
ia_role_ = ROLE_SYSTEM_COMBOBOX;
} else {
ia_role_ = ROLE_SYSTEM_BUTTONMENU;
}
break;
- case WebKit::WebAXRoleProgressIndicator:
+ case blink::WebAXRoleProgressIndicator:
ia_role_ = ROLE_SYSTEM_PROGRESSBAR;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleRadioButton:
+ case blink::WebAXRoleRadioButton:
ia_role_ = ROLE_SYSTEM_RADIOBUTTON;
break;
- case WebKit::WebAXRoleRadioGroup:
+ case blink::WebAXRoleRadioGroup:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
break;
- case WebKit::WebAXRoleRegion:
+ case blink::WebAXRoleRegion:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleRow:
+ case blink::WebAXRoleRow:
ia_role_ = ROLE_SYSTEM_ROW;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleRowHeader:
+ case blink::WebAXRoleRowHeader:
ia_role_ = ROLE_SYSTEM_ROWHEADER;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleRuler:
+ case blink::WebAXRoleRuler:
ia_role_ = ROLE_SYSTEM_CLIENT;
ia2_role_ = IA2_ROLE_RULER;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleScrollArea:
+ case blink::WebAXRoleScrollArea:
ia_role_ = ROLE_SYSTEM_CLIENT;
ia2_role_ = IA2_ROLE_SCROLL_PANE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleScrollBar:
+ case blink::WebAXRoleScrollBar:
ia_role_ = ROLE_SYSTEM_SCROLLBAR;
break;
- case WebKit::WebAXRoleSlider:
+ case blink::WebAXRoleSlider:
ia_role_ = ROLE_SYSTEM_SLIDER;
break;
- case WebKit::WebAXRoleSpinButton:
+ case blink::WebAXRoleSpinButton:
ia_role_ = ROLE_SYSTEM_SPINBUTTON;
break;
- case WebKit::WebAXRoleSpinButtonPart:
+ case blink::WebAXRoleSpinButtonPart:
ia_role_ = ROLE_SYSTEM_PUSHBUTTON;
break;
- case WebKit::WebAXRoleSplitGroup:
+ case blink::WebAXRoleSplitGroup:
ia_role_ = ROLE_SYSTEM_CLIENT;
ia2_role_ = IA2_ROLE_SPLIT_PANE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleAnnotation:
- case WebKit::WebAXRoleStaticText:
+ case blink::WebAXRoleAnnotation:
+ case blink::WebAXRoleStaticText:
ia_role_ = ROLE_SYSTEM_TEXT;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleStatus:
+ case blink::WebAXRoleStatus:
ia_role_ = ROLE_SYSTEM_STATUSBAR;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleSplitter:
+ case blink::WebAXRoleSplitter:
ia_role_ = ROLE_SYSTEM_SEPARATOR;
break;
- case WebKit::WebAXRoleSVGRoot:
+ case blink::WebAXRoleSVGRoot:
ia_role_ = ROLE_SYSTEM_GRAPHIC;
break;
- case WebKit::WebAXRoleTab:
+ case blink::WebAXRoleTab:
ia_role_ = ROLE_SYSTEM_PAGETAB;
break;
- case WebKit::WebAXRoleTable: {
- string16 aria_role = GetString16Attribute(
+ case blink::WebAXRoleTable: {
+ base::string16 aria_role = GetString16Attribute(
AccessibilityNodeData::ATTR_ROLE);
if (aria_role == L"treegrid") {
ia_role_ = ROLE_SYSTEM_OUTLINE;
@@ -3567,77 +3697,77 @@ void BrowserAccessibilityWin::InitRoleAndState() {
}
break;
}
- case WebKit::WebAXRoleTableHeaderContainer:
+ case blink::WebAXRoleTableHeaderContainer:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleTabList:
+ case blink::WebAXRoleTabList:
ia_role_ = ROLE_SYSTEM_PAGETABLIST;
break;
- case WebKit::WebAXRoleTabPanel:
+ case blink::WebAXRoleTabPanel:
ia_role_ = ROLE_SYSTEM_PROPERTYPAGE;
break;
- case WebKit::WebAXRoleToggleButton:
+ case blink::WebAXRoleToggleButton:
ia_role_ = ROLE_SYSTEM_PUSHBUTTON;
ia2_role_ = IA2_ROLE_TOGGLE_BUTTON;
break;
- case WebKit::WebAXRoleTextArea:
+ case blink::WebAXRoleTextArea:
ia_role_ = ROLE_SYSTEM_TEXT;
ia2_state_ |= IA2_STATE_MULTI_LINE;
ia2_state_ |= IA2_STATE_EDITABLE;
ia2_state_ |= IA2_STATE_SELECTABLE_TEXT;
break;
- case WebKit::WebAXRoleTextField:
+ case blink::WebAXRoleTextField:
ia_role_ = ROLE_SYSTEM_TEXT;
ia2_state_ |= IA2_STATE_SINGLE_LINE;
ia2_state_ |= IA2_STATE_EDITABLE;
ia2_state_ |= IA2_STATE_SELECTABLE_TEXT;
break;
- case WebKit::WebAXRoleTimer:
+ case blink::WebAXRoleTimer:
ia_role_ = ROLE_SYSTEM_CLOCK;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleToolbar:
+ case blink::WebAXRoleToolbar:
ia_role_ = ROLE_SYSTEM_TOOLBAR;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleUserInterfaceTooltip:
+ case blink::WebAXRoleUserInterfaceTooltip:
ia_role_ = ROLE_SYSTEM_TOOLTIP;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleTree:
+ case blink::WebAXRoleTree:
ia_role_ = ROLE_SYSTEM_OUTLINE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleTreeGrid:
+ case blink::WebAXRoleTreeGrid:
ia_role_ = ROLE_SYSTEM_OUTLINE;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleTreeItem:
+ case blink::WebAXRoleTreeItem:
ia_role_ = ROLE_SYSTEM_OUTLINEITEM;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case WebKit::WebAXRoleWindow:
+ case blink::WebAXRoleWindow:
ia_role_ = ROLE_SYSTEM_WINDOW;
break;
// TODO(dmazzoni): figure out the proper MSAA role for all of these.
- case WebKit::WebAXRoleBrowser:
- case WebKit::WebAXRoleDirectory:
- case WebKit::WebAXRoleDrawer:
- case WebKit::WebAXRoleHelpTag:
- case WebKit::WebAXRoleIgnored:
- case WebKit::WebAXRoleIncrementor:
- case WebKit::WebAXRoleLog:
- case WebKit::WebAXRoleMarquee:
- case WebKit::WebAXRoleMatte:
- case WebKit::WebAXRolePresentational:
- case WebKit::WebAXRoleRulerMarker:
- case WebKit::WebAXRoleSheet:
- case WebKit::WebAXRoleSliderThumb:
- case WebKit::WebAXRoleSystemWide:
- case WebKit::WebAXRoleValueIndicator:
+ case blink::WebAXRoleBrowser:
+ case blink::WebAXRoleDirectory:
+ case blink::WebAXRoleDrawer:
+ case blink::WebAXRoleHelpTag:
+ case blink::WebAXRoleIgnored:
+ case blink::WebAXRoleIncrementor:
+ case blink::WebAXRoleLog:
+ case blink::WebAXRoleMarquee:
+ case blink::WebAXRoleMatte:
+ case blink::WebAXRolePresentational:
+ case blink::WebAXRoleRulerMarker:
+ case blink::WebAXRoleSheet:
+ case blink::WebAXRoleSliderThumb:
+ case blink::WebAXRoleSystemWide:
+ case blink::WebAXRoleValueIndicator:
default:
ia_role_ = ROLE_SYSTEM_CLIENT;
break;
@@ -3649,11 +3779,11 @@ void BrowserAccessibilityWin::InitRoleAndState() {
// aria-readonly attribute and for a few roles (in the switch above).
// We clear the READONLY state on focusable controls and on a document.
// Everything else, the majority of objects, do not have this state set.
- if (HasState(WebKit::WebAXStateFocusable) &&
+ if (HasState(blink::WebAXStateFocusable) &&
ia_role_ != ROLE_SYSTEM_DOCUMENT) {
ia_state_ &= ~(STATE_SYSTEM_READONLY);
}
- if (!HasState(WebKit::WebAXStateReadonly))
+ if (!HasState(blink::WebAXStateReadonly))
ia_state_ &= ~(STATE_SYSTEM_READONLY);
if (GetBoolAttribute(AccessibilityNodeData::ATTR_ARIA_READONLY))
ia_state_ |= STATE_SYSTEM_READONLY;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.h b/chromium/content/browser/accessibility/browser_accessibility_win.h
index db8040e3161..69d6efb7631 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.h
@@ -86,8 +86,8 @@ BrowserAccessibilityWin
// Mappings from roles and states to human readable strings. Initialize
// with |InitializeStringMaps|.
- static std::map<int32, string16> role_string_map;
- static std::map<int32, string16> state_string_map;
+ static std::map<int32, base::string16> role_string_map;
+ static std::map<int32, base::string16> state_string_map;
CONTENT_EXPORT BrowserAccessibilityWin();
@@ -445,6 +445,14 @@ BrowserAccessibilityWin
CONTENT_EXPORT STDMETHODIMP get_caretOffset(LONG* offset);
+ CONTENT_EXPORT STDMETHODIMP get_characterExtents(
+ LONG offset,
+ enum IA2CoordinateType coord_type,
+ LONG* out_x,
+ LONG* out_y,
+ LONG* out_width,
+ LONG* out_height);
+
CONTENT_EXPORT STDMETHODIMP get_nSelections(LONG* n_selections);
CONTENT_EXPORT STDMETHODIMP get_selection(LONG selection_index,
@@ -513,14 +521,6 @@ BrowserAccessibilityWin
BSTR* text_attributes) {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_characterExtents(LONG offset,
- enum IA2CoordinateType coord_type,
- LONG* x,
- LONG* y,
- LONG* width,
- LONG* height) {
- return E_NOTIMPL;
- }
//
// IAccessibleHypertext methods.
@@ -682,27 +682,21 @@ BrowserAccessibilityWin
CONTENT_EXPORT STDMETHODIMP get_clippedSubstringBounds(
unsigned int start_index,
unsigned int end_index,
- int* x,
- int* y,
- int* width,
- int* height) {
- return E_NOTIMPL;
- }
+ int* out_x,
+ int* out_y,
+ int* out_width,
+ int* out_height);
CONTENT_EXPORT STDMETHODIMP get_unclippedSubstringBounds(
unsigned int start_index,
unsigned int end_index,
- int* x,
- int* y,
- int* width,
- int* height) {
- return E_NOTIMPL;
- }
+ int* out_x,
+ int* out_y,
+ int* out_width,
+ int* out_height);
CONTENT_EXPORT STDMETHODIMP scrollToSubstring(unsigned int start_index,
- unsigned int end_index) {
- return E_NOTIMPL;
- }
+ unsigned int end_index);
CONTENT_EXPORT STDMETHODIMP get_fontFamily(BSTR *font_family) {
return E_NOTIMPL;
@@ -771,13 +765,17 @@ BrowserAccessibilityWin
// Accessors.
int32 ia_role() const { return ia_role_; }
int32 ia_state() const { return ia_state_; }
- const string16& role_name() const { return role_name_; }
+ const base::string16& role_name() const { return role_name_; }
int32 ia2_role() const { return ia2_role_; }
int32 ia2_state() const { return ia2_state_; }
- const std::vector<string16>& ia2_attributes() const {
+ const std::vector<base::string16>& ia2_attributes() const {
return ia2_attributes_;
}
+ // BrowserAccessibility::role is shadowed by IAccessible2::role, so
+ // we provide an alias for it.
+ int32 blink_role() const { return BrowserAccessibility::role(); }
+
private:
// Add one to the reference count and return the same object. Always
// use this method when returning a BrowserAccessibilityWin object as
@@ -819,15 +817,15 @@ BrowserAccessibilityWin
// Get the value text, which might come from the floating-point
// value for some roles.
- string16 GetValueText();
+ base::string16 GetValueText();
// Get the text of this node for the purposes of IAccessibleText - it may
// be the name, it may be the value, etc. depending on the role.
- string16 TextForIAccessibleText();
+ base::string16 TextForIAccessibleText();
// If offset is a member of IA2TextSpecialOffsets this function updates the
// value of offset and returns, otherwise offset remains unchanged.
- void HandleSpecialTextOffset(const string16& text, LONG* offset);
+ void HandleSpecialTextOffset(const base::string16& text, LONG* offset);
// Convert from a IA2TextBoundaryType to a ui::TextBoundaryType.
ui::TextBoundaryType IA2TextBoundaryToTextBoundary(IA2TextBoundaryType type);
@@ -835,7 +833,7 @@ BrowserAccessibilityWin
// Search forwards (direction == 1) or backwards (direction == -1)
// from the given offset until the given boundary is found, and
// return the offset of that boundary.
- LONG FindBoundary(const string16& text,
+ LONG FindBoundary(const base::string16& text,
IA2TextBoundaryType ia2_boundary,
LONG start_offset,
ui::TextBoundaryDirection direction);
@@ -852,26 +850,26 @@ BrowserAccessibilityWin
// IAccessible role and state.
int32 ia_role_;
int32 ia_state_;
- string16 role_name_;
+ base::string16 role_name_;
// IAccessible2 role and state.
int32 ia2_role_;
int32 ia2_state_;
// IAccessible2 attributes.
- std::vector<string16> ia2_attributes_;
+ std::vector<base::string16> ia2_attributes_;
// True in Initialize when the object is first created, and false
// subsequent times.
bool first_time_;
// The previous text, before the last update to this object.
- string16 previous_text_;
+ base::string16 previous_text_;
// The old text to return in IAccessibleText::get_oldText - this is like
// previous_text_ except that it's NOT updated when the object
// is initialized again but the text doesn't change.
- string16 old_text_;
+ base::string16 old_text_;
// The previous state, used to see if there was a state change.
int32 old_ia_state_;
@@ -880,7 +878,7 @@ BrowserAccessibilityWin
std::vector<BrowserAccessibilityRelation*> relations_;
// The text of this node including embedded hyperlink characters.
- string16 hypertext_;
+ base::string16 hypertext_;
// Maps the |hypertext_| embedded character offset to an index in
// |hyperlinks_|.
@@ -890,6 +888,10 @@ BrowserAccessibilityWin
// a hyperlink.
std::vector<int32> hyperlinks_;
+ // The previous scroll position, so we can tell if this object scrolled.
+ int previous_scroll_x_;
+ int previous_scroll_y_;
+
// The next unique id to use.
static LONG next_unique_id_win_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index c623e257803..408fb4df361 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -9,6 +9,7 @@
#include "base/win/scoped_variant.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_manager_win.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
#include "content/common/accessibility_messages.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -115,19 +116,19 @@ TEST_F(BrowserAccessibilityTest, TestNoLeaks) {
AccessibilityNodeData button;
button.id = 2;
button.SetName("Button");
- button.role = WebKit::WebAXRoleButton;
+ button.role = blink::WebAXRoleButton;
button.state = 0;
AccessibilityNodeData checkbox;
checkbox.id = 3;
checkbox.SetName("Checkbox");
- checkbox.role = WebKit::WebAXRoleCheckBox;
+ checkbox.role = blink::WebAXRoleCheckBox;
checkbox.state = 0;
AccessibilityNodeData root;
root.id = 1;
root.SetName("Document");
- root.role = WebKit::WebAXRoleRootWebArea;
+ root.role = blink::WebAXRoleRootWebArea;
root.state = 0;
root.child_ids.push_back(2);
root.child_ids.push_back(3);
@@ -183,14 +184,14 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
// BrowserAccessibilityManager.
AccessibilityNodeData text;
text.id = 2;
- text.role = WebKit::WebAXRoleStaticText;
+ text.role = blink::WebAXRoleStaticText;
text.SetName("old text");
text.state = 0;
AccessibilityNodeData root;
root.id = 1;
root.SetName("Document");
- root.role = WebKit::WebAXRoleRootWebArea;
+ root.role = blink::WebAXRoleRootWebArea;
root.state = 0;
root.child_ids.push_back(2);
@@ -219,7 +220,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
base::win::ScopedBstr name;
hr = text_accessible->get_accName(childid_self, name.Receive());
ASSERT_EQ(S_OK, hr);
- EXPECT_EQ(L"old text", string16(name));
+ EXPECT_EQ(L"old text", base::string16(name));
name.Reset();
text_dispatch.Release();
@@ -228,11 +229,11 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
// Notify the BrowserAccessibilityManager that the text child has changed.
AccessibilityNodeData text2;
text2.id = 2;
- text2.role = WebKit::WebAXRoleStaticText;
+ text2.role = blink::WebAXRoleStaticText;
text2.SetName("new text");
text2.SetName("old text");
AccessibilityHostMsg_EventParams param;
- param.event_type = WebKit::WebAXEventChildrenChanged;
+ param.event_type = blink::WebAXEventChildrenChanged;
param.nodes.push_back(text2);
param.id = text2.id;
std::vector<AccessibilityHostMsg_EventParams> events;
@@ -250,7 +251,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
hr = text_accessible->get_accName(childid_self, name.Receive());
ASSERT_EQ(S_OK, hr);
- EXPECT_EQ(L"new text", string16(name));
+ EXPECT_EQ(L"new text", base::string16(name));
text_dispatch.Release();
text_accessible.Release();
@@ -267,17 +268,17 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
// BrowserAccessibilityManager.
AccessibilityNodeData div;
div.id = 2;
- div.role = WebKit::WebAXRoleGroup;
+ div.role = blink::WebAXRoleGroup;
div.state = 0;
AccessibilityNodeData text3;
text3.id = 3;
- text3.role = WebKit::WebAXRoleStaticText;
+ text3.role = blink::WebAXRoleStaticText;
text3.state = 0;
AccessibilityNodeData text4;
text4.id = 4;
- text4.role = WebKit::WebAXRoleStaticText;
+ text4.role = blink::WebAXRoleStaticText;
text4.state = 0;
div.child_ids.push_back(3);
@@ -285,7 +286,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
AccessibilityNodeData root;
root.id = 1;
- root.role = WebKit::WebAXRoleRootWebArea;
+ root.role = blink::WebAXRoleRootWebArea;
root.state = 0;
root.child_ids.push_back(2);
@@ -304,7 +305,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
// were removed and ensure that only one BrowserAccessibility instance exists.
root.child_ids.clear();
AccessibilityHostMsg_EventParams param;
- param.event_type = WebKit::WebAXEventChildrenChanged;
+ param.event_type = blink::WebAXEventChildrenChanged;
param.nodes.push_back(root);
param.id = root.id;
std::vector<AccessibilityHostMsg_EventParams> events;
@@ -323,7 +324,7 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
AccessibilityNodeData text1;
text1.id = 11;
- text1.role = WebKit::WebAXRoleTextField;
+ text1.role = blink::WebAXRoleTextField;
text1.state = 0;
text1.AddStringAttribute(AccessibilityNodeData::ATTR_VALUE, text1_value);
std::vector<int32> line_breaks;
@@ -333,7 +334,7 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
AccessibilityNodeData root;
root.id = 1;
- root.role = WebKit::WebAXRoleRootWebArea;
+ root.role = blink::WebAXRoleRootWebArea;
root.state = 0;
root.child_ids.push_back(11);
@@ -347,14 +348,14 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
BrowserAccessibilityWin* root_obj =
manager->GetRoot()->ToBrowserAccessibilityWin();
BrowserAccessibilityWin* text1_obj =
- root_obj->GetChild(0)->ToBrowserAccessibilityWin();
+ root_obj->PlatformGetChild(0)->ToBrowserAccessibilityWin();
long text1_len;
ASSERT_EQ(S_OK, text1_obj->get_nCharacters(&text1_len));
base::win::ScopedBstr text;
ASSERT_EQ(S_OK, text1_obj->get_text(0, text1_len, text.Receive()));
- ASSERT_EQ(text1_value, base::UTF16ToUTF8(string16(text)));
+ ASSERT_EQ(text1_value, base::UTF16ToUTF8(base::string16(text)));
text.Reset();
ASSERT_EQ(S_OK, text1_obj->get_text(0, 4, text.Receive()));
@@ -420,20 +421,20 @@ TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) {
AccessibilityNodeData text1;
text1.id = 11;
- text1.role = WebKit::WebAXRoleStaticText;
- text1.state = 1 << WebKit::WebAXStateReadonly;
+ text1.role = blink::WebAXRoleStaticText;
+ text1.state = 1 << blink::WebAXStateReadonly;
text1.SetName(text1_name);
AccessibilityNodeData text2;
text2.id = 12;
- text2.role = WebKit::WebAXRoleStaticText;
- text2.state = 1 << WebKit::WebAXStateReadonly;
+ text2.role = blink::WebAXRoleStaticText;
+ text2.state = 1 << blink::WebAXStateReadonly;
text2.SetName(text2_name);
AccessibilityNodeData root;
root.id = 1;
- root.role = WebKit::WebAXRoleRootWebArea;
- root.state = 1 << WebKit::WebAXStateReadonly;
+ root.role = blink::WebAXRoleRootWebArea;
+ root.state = 1 << blink::WebAXStateReadonly;
root.child_ids.push_back(11);
root.child_ids.push_back(12);
@@ -452,7 +453,7 @@ TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) {
base::win::ScopedBstr text;
ASSERT_EQ(S_OK, root_obj->get_text(0, text_len, text.Receive()));
- EXPECT_EQ(text1_name + text2_name, base::UTF16ToUTF8(string16(text)));
+ EXPECT_EQ(text1_name + text2_name, base::UTF16ToUTF8(base::string16(text)));
long hyperlink_count;
ASSERT_EQ(S_OK, root_obj->get_nHyperlinks(&hyperlink_count));
@@ -488,40 +489,40 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
AccessibilityNodeData text1;
text1.id = 11;
- text1.role = WebKit::WebAXRoleStaticText;
- text1.state = 1 << WebKit::WebAXStateReadonly;
+ text1.role = blink::WebAXRoleStaticText;
+ text1.state = 1 << blink::WebAXStateReadonly;
text1.SetName(text1_name);
AccessibilityNodeData text2;
text2.id = 12;
- text2.role = WebKit::WebAXRoleStaticText;
- text2.state = 1 << WebKit::WebAXStateReadonly;
+ text2.role = blink::WebAXRoleStaticText;
+ text2.state = 1 << blink::WebAXStateReadonly;
text2.SetName(text2_name);
AccessibilityNodeData button1, button1_text;
button1.id = 13;
button1_text.id = 15;
button1_text.SetName(button1_text_name);
- button1.role = WebKit::WebAXRoleButton;
- button1_text.role = WebKit::WebAXRoleStaticText;
- button1.state = 1 << WebKit::WebAXStateReadonly;
- button1_text.state = 1 << WebKit::WebAXStateReadonly;
+ button1.role = blink::WebAXRoleButton;
+ button1_text.role = blink::WebAXRoleStaticText;
+ button1.state = 1 << blink::WebAXStateReadonly;
+ button1_text.state = 1 << blink::WebAXStateReadonly;
button1.child_ids.push_back(15);
AccessibilityNodeData link1, link1_text;
link1.id = 14;
link1_text.id = 16;
link1_text.SetName(link1_text_name);
- link1.role = WebKit::WebAXRoleLink;
- link1_text.role = WebKit::WebAXRoleStaticText;
- link1.state = 1 << WebKit::WebAXStateReadonly;
- link1_text.state = 1 << WebKit::WebAXStateReadonly;
+ link1.role = blink::WebAXRoleLink;
+ link1_text.role = blink::WebAXRoleStaticText;
+ link1.state = 1 << blink::WebAXStateReadonly;
+ link1_text.state = 1 << blink::WebAXStateReadonly;
link1.child_ids.push_back(16);
AccessibilityNodeData root;
root.id = 1;
- root.role = WebKit::WebAXRoleRootWebArea;
- root.state = 1 << WebKit::WebAXStateReadonly;
+ root.role = blink::WebAXRoleRootWebArea;
+ root.state = 1 << blink::WebAXStateReadonly;
root.child_ids.push_back(11);
root.child_ids.push_back(13);
root.child_ids.push_back(12);
@@ -548,7 +549,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
const std::string embed = base::UTF16ToUTF8(
BrowserAccessibilityWin::kEmbeddedCharacter);
EXPECT_EQ(text1_name + embed + text2_name + embed,
- UTF16ToUTF8(string16(text)));
+ UTF16ToUTF8(base::string16(text)));
text.Reset();
long hyperlink_count;
@@ -566,7 +567,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive()));
EXPECT_EQ(S_OK, hypertext->get_text(0, 3, text.Receive()));
EXPECT_STREQ(button1_text_name.c_str(),
- base::UTF16ToUTF8(string16(text)).c_str());
+ base::UTF16ToUTF8(base::string16(text)).c_str());
text.Reset();
hyperlink.Release();
hypertext.Release();
@@ -576,7 +577,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive()));
EXPECT_EQ(S_OK, hypertext->get_text(0, 4, text.Receive()));
EXPECT_STREQ(link1_text_name.c_str(),
- base::UTF16ToUTF8(string16(text)).c_str());
+ base::UTF16ToUTF8(base::string16(text)).c_str());
text.Reset();
hyperlink.Release();
hypertext.Release();
@@ -601,9 +602,9 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
// Try creating an empty document with busy state. Readonly is
// set automatically.
CountedBrowserAccessibility::reset();
- const int32 busy_state = 1 << WebKit::WebAXStateBusy;
- const int32 readonly_state = 1 << WebKit::WebAXStateReadonly;
- const int32 enabled_state = 1 << WebKit::WebAXStateEnabled;
+ const int32 busy_state = 1 << blink::WebAXStateBusy;
+ const int32 readonly_state = 1 << blink::WebAXStateReadonly;
+ const int32 enabled_state = 1 << blink::WebAXStateEnabled;
scoped_ptr<BrowserAccessibilityManager> manager(
new BrowserAccessibilityManagerWin(
GetDesktopWindow(),
@@ -615,24 +616,24 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
// Verify the root is as we expect by default.
BrowserAccessibility* root = manager->GetRoot();
EXPECT_EQ(0, root->renderer_id());
- EXPECT_EQ(WebKit::WebAXRoleRootWebArea, root->role());
+ EXPECT_EQ(blink::WebAXRoleRootWebArea, root->role());
EXPECT_EQ(busy_state | readonly_state | enabled_state, root->state());
// Tree with a child textfield.
AccessibilityNodeData tree1_1;
tree1_1.id = 1;
- tree1_1.role = WebKit::WebAXRoleRootWebArea;
+ tree1_1.role = blink::WebAXRoleRootWebArea;
tree1_1.child_ids.push_back(2);
AccessibilityNodeData tree1_2;
tree1_2.id = 2;
- tree1_2.role = WebKit::WebAXRoleTextField;
+ tree1_2.role = blink::WebAXRoleTextField;
// Process a load complete.
std::vector<AccessibilityHostMsg_EventParams> params;
params.push_back(AccessibilityHostMsg_EventParams());
AccessibilityHostMsg_EventParams* msg = &params[0];
- msg->event_type = WebKit::WebAXEventLoadComplete;
+ msg->event_type = blink::WebAXEventLoadComplete;
msg->nodes.push_back(tree1_1);
msg->nodes.push_back(tree1_2);
msg->id = tree1_1.id;
@@ -645,18 +646,18 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
EXPECT_NE(root, manager->GetRoot());
// And the proper child remains.
- EXPECT_EQ(WebKit::WebAXRoleTextField, acc1_2->role());
+ EXPECT_EQ(blink::WebAXRoleTextField, acc1_2->role());
EXPECT_EQ(2, acc1_2->renderer_id());
// Tree with a child button.
AccessibilityNodeData tree2_1;
tree2_1.id = 1;
- tree2_1.role = WebKit::WebAXRoleRootWebArea;
+ tree2_1.role = blink::WebAXRoleRootWebArea;
tree2_1.child_ids.push_back(3);
AccessibilityNodeData tree2_2;
tree2_2.id = 3;
- tree2_2.role = WebKit::WebAXRoleButton;
+ tree2_2.role = blink::WebAXRoleButton;
msg->nodes.clear();
msg->nodes.push_back(tree2_1);
@@ -672,7 +673,7 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
EXPECT_NE(root, manager->GetRoot());
// And the new child exists.
- EXPECT_EQ(WebKit::WebAXRoleButton, acc2_2->role());
+ EXPECT_EQ(blink::WebAXRoleButton, acc2_2->role());
EXPECT_EQ(3, acc2_2->renderer_id());
// Ensure we properly cleaned up.
@@ -680,4 +681,54 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
}
+#if defined(USE_AURA)
+TEST(BrowserAccessibilityManagerWinTest, TestAccessibleHWND) {
+ HWND desktop_hwnd = GetDesktopWindow();
+ base::win::ScopedComPtr<IAccessible> desktop_hwnd_iaccessible;
+ ASSERT_EQ(S_OK, AccessibleObjectFromWindow(
+ desktop_hwnd, OBJID_CLIENT,
+ IID_IAccessible,
+ reinterpret_cast<void**>(desktop_hwnd_iaccessible.Receive())));
+
+ scoped_ptr<BrowserAccessibilityManagerWin> manager(
+ new BrowserAccessibilityManagerWin(
+ desktop_hwnd,
+ desktop_hwnd_iaccessible,
+ BrowserAccessibilityManagerWin::GetEmptyDocument(),
+ NULL));
+ ASSERT_EQ(desktop_hwnd, manager->parent_hwnd());
+
+ // Enabling screen reader support and calling MaybeCallNotifyWinEvent
+ // should trigger creating the AccessibleHWND, and we should now get a
+ // new parent_hwnd with the right window class to fool older screen
+ // readers.
+ BrowserAccessibilityStateImpl::GetInstance()->OnScreenReaderDetected();
+ manager->MaybeCallNotifyWinEvent(0, 0);
+ HWND new_parent_hwnd = manager->parent_hwnd();
+ ASSERT_NE(desktop_hwnd, new_parent_hwnd);
+ WCHAR hwnd_class_name[256];
+ ASSERT_NE(0, GetClassName(new_parent_hwnd, hwnd_class_name, 256));
+ ASSERT_STREQ(L"Chrome_RenderWidgetHostHWND", hwnd_class_name);
+
+ // Destroy the hwnd explicitly; that should trigger clearing parent_hwnd().
+ DestroyWindow(new_parent_hwnd);
+ ASSERT_EQ(NULL, manager->parent_hwnd());
+
+ // Now create it again.
+ manager.reset(
+ new BrowserAccessibilityManagerWin(
+ desktop_hwnd,
+ desktop_hwnd_iaccessible,
+ BrowserAccessibilityManagerWin::GetEmptyDocument(),
+ NULL));
+ manager->MaybeCallNotifyWinEvent(0, 0);
+ new_parent_hwnd = manager->parent_hwnd();
+ ASSERT_FALSE(NULL == new_parent_hwnd);
+
+ // This time, destroy the manager first, make sure the AccessibleHWND doesn't
+ // crash on destruction (to be caught by SyzyASAN or other tools).
+ manager.reset(NULL);
+}
+#endif
+
} // 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 eb61a1c8d24..f0aa13ff921 100644
--- a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -40,7 +40,7 @@ class CrossPlatformAccessibilityBrowserTest : public ContentBrowserTest {
const AccessibilityNodeDataTreeNode& GetAccessibilityNodeDataTree(
AccessibilityMode accessibility_mode = AccessibilityModeComplete) {
AccessibilityNotificationWaiter waiter(
- shell(), accessibility_mode, WebKit::WebAXEventLayoutComplete);
+ shell(), accessibility_mode, blink::WebAXEventLayoutComplete);
waiter.WaitForNotification();
return waiter.GetAccessibilityNodeDataTree();
}
@@ -152,12 +152,12 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
EXPECT_STREQ(
"Accessibility Test",
GetAttr(tree, AccessibilityNodeData::ATTR_NAME).c_str());
- EXPECT_EQ(WebKit::WebAXRoleRootWebArea, tree.role);
+ EXPECT_EQ(blink::WebAXRoleRootWebArea, tree.role);
// Check properites of the BODY element.
ASSERT_EQ(1U, tree.children.size());
const AccessibilityNodeDataTreeNode& body = tree.children[0];
- EXPECT_EQ(WebKit::WebAXRoleGroup, body.role);
+ EXPECT_EQ(blink::WebAXRoleGroup, body.role);
EXPECT_STREQ("body",
GetAttr(body, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
EXPECT_STREQ("block",
@@ -167,7 +167,7 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
ASSERT_EQ(2U, body.children.size());
const AccessibilityNodeDataTreeNode& button = body.children[0];
- EXPECT_EQ(WebKit::WebAXRoleButton, button.role);
+ EXPECT_EQ(blink::WebAXRoleButton, button.role);
EXPECT_STREQ(
"input", GetAttr(button, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
EXPECT_STREQ(
@@ -183,7 +183,7 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
EXPECT_STREQ("push", button.html_attributes[1].second.c_str());
const AccessibilityNodeDataTreeNode& checkbox = body.children[1];
- EXPECT_EQ(WebKit::WebAXRoleCheckBox, checkbox.role);
+ EXPECT_EQ(blink::WebAXRoleCheckBox, checkbox.role);
EXPECT_STREQ(
"input", GetAttr(checkbox, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
EXPECT_STREQ(
@@ -211,7 +211,7 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const AccessibilityNodeDataTreeNode& body = tree.children[0];
ASSERT_EQ(1U, body.children.size());
const AccessibilityNodeDataTreeNode& text = body.children[0];
- EXPECT_EQ(WebKit::WebAXRoleTextField, text.role);
+ EXPECT_EQ(blink::WebAXRoleTextField, text.role);
EXPECT_STREQ(
"input", GetAttr(text, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
EXPECT_EQ(0, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_START));
@@ -242,7 +242,7 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const AccessibilityNodeDataTreeNode& body = tree.children[0];
ASSERT_EQ(1U, body.children.size());
const AccessibilityNodeDataTreeNode& text = body.children[0];
- EXPECT_EQ(WebKit::WebAXRoleTextField, text.role);
+ EXPECT_EQ(blink::WebAXRoleTextField, text.role);
EXPECT_STREQ(
"input", GetAttr(text, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
EXPECT_EQ(0, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_START));
@@ -269,15 +269,15 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
ASSERT_EQ(1U, tree.children.size());
const AccessibilityNodeDataTreeNode& table = tree.children[0];
- EXPECT_EQ(WebKit::WebAXRoleTable, table.role);
+ EXPECT_EQ(blink::WebAXRoleTable, table.role);
const AccessibilityNodeDataTreeNode& row = table.children[0];
- EXPECT_EQ(WebKit::WebAXRoleRow, row.role);
+ EXPECT_EQ(blink::WebAXRoleRow, row.role);
const AccessibilityNodeDataTreeNode& cell1 = row.children[0];
- EXPECT_EQ(WebKit::WebAXRoleCell, cell1.role);
+ EXPECT_EQ(blink::WebAXRoleCell, cell1.role);
const AccessibilityNodeDataTreeNode& cell2 = row.children[1];
- EXPECT_EQ(WebKit::WebAXRoleCell, cell2.role);
+ EXPECT_EQ(blink::WebAXRoleCell, cell2.role);
const AccessibilityNodeDataTreeNode& column1 = table.children[1];
- EXPECT_EQ(WebKit::WebAXRoleColumn, column1.role);
+ EXPECT_EQ(blink::WebAXRoleColumn, column1.role);
EXPECT_EQ(0U, column1.children.size());
EXPECT_EQ(1U, column1.intlist_attributes.size());
EXPECT_EQ(AccessibilityNodeData::ATTR_INDIRECT_CHILD_IDS,
@@ -287,7 +287,7 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
EXPECT_EQ(1U, column1_indirect_child_ids.size());
EXPECT_EQ(cell1.id, column1_indirect_child_ids[0]);
const AccessibilityNodeDataTreeNode& column2 = table.children[2];
- EXPECT_EQ(WebKit::WebAXRoleColumn, column2.role);
+ EXPECT_EQ(blink::WebAXRoleColumn, column2.role);
EXPECT_EQ(0U, column2.children.size());
EXPECT_EQ(AccessibilityNodeData::ATTR_INDIRECT_CHILD_IDS,
column2.intlist_attributes[0].first);
@@ -340,7 +340,7 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
ASSERT_EQ(3U, body.children.size());
const AccessibilityNodeDataTreeNode& button1 = body.children[0];
- EXPECT_EQ(WebKit::WebAXRoleButton, button1.role);
+ EXPECT_EQ(blink::WebAXRoleButton, button1.role);
EXPECT_STREQ(
"Button 1",
GetAttr(button1, AccessibilityNodeData::ATTR_NAME).c_str());
@@ -351,23 +351,23 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
ASSERT_EQ(1U, iframe.children.size());
const AccessibilityNodeDataTreeNode& scroll_area = iframe.children[0];
- EXPECT_EQ(WebKit::WebAXRoleScrollArea, scroll_area.role);
+ EXPECT_EQ(blink::WebAXRoleScrollArea, scroll_area.role);
ASSERT_EQ(1U, scroll_area.children.size());
const AccessibilityNodeDataTreeNode& sub_document = scroll_area.children[0];
- EXPECT_EQ(WebKit::WebAXRoleWebArea, sub_document.role);
+ EXPECT_EQ(blink::WebAXRoleWebArea, sub_document.role);
ASSERT_EQ(1U, sub_document.children.size());
const AccessibilityNodeDataTreeNode& sub_body = sub_document.children[0];
ASSERT_EQ(1U, sub_body.children.size());
const AccessibilityNodeDataTreeNode& button2 = sub_body.children[0];
- EXPECT_EQ(WebKit::WebAXRoleButton, button2.role);
+ EXPECT_EQ(blink::WebAXRoleButton, button2.role);
EXPECT_STREQ("Button 2",
GetAttr(button2, AccessibilityNodeData::ATTR_NAME).c_str());
const AccessibilityNodeDataTreeNode& button3 = body.children[2];
- EXPECT_EQ(WebKit::WebAXRoleButton, button3.role);
+ EXPECT_EQ(blink::WebAXRoleButton, button3.role);
EXPECT_STREQ("Button 3",
GetAttr(button3, AccessibilityNodeData::ATTR_NAME).c_str());
}
@@ -413,13 +413,13 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
const AccessibilityNodeDataTreeNode& table = tree.children[0];
- EXPECT_EQ(WebKit::WebAXRoleTable, table.role);
+ EXPECT_EQ(blink::WebAXRoleTable, table.role);
ASSERT_GE(table.children.size(), 5U);
- EXPECT_EQ(WebKit::WebAXRoleRow, table.children[0].role);
- EXPECT_EQ(WebKit::WebAXRoleRow, table.children[1].role);
- EXPECT_EQ(WebKit::WebAXRoleColumn, table.children[2].role);
- EXPECT_EQ(WebKit::WebAXRoleColumn, table.children[3].role);
- EXPECT_EQ(WebKit::WebAXRoleColumn, table.children[4].role);
+ EXPECT_EQ(blink::WebAXRoleRow, table.children[0].role);
+ EXPECT_EQ(blink::WebAXRoleRow, table.children[1].role);
+ EXPECT_EQ(blink::WebAXRoleColumn, table.children[2].role);
+ EXPECT_EQ(blink::WebAXRoleColumn, table.children[3].role);
+ EXPECT_EQ(blink::WebAXRoleColumn, table.children[4].role);
EXPECT_EQ(3,
GetIntAttr(table, AccessibilityNodeData::ATTR_TABLE_COLUMN_COUNT));
EXPECT_EQ(2, GetIntAttr(table, AccessibilityNodeData::ATTR_TABLE_ROW_COUNT));
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 948b8fde628..8cceea7bc5f 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -6,6 +6,7 @@
#include <string>
#include <vector>
+#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
@@ -20,6 +21,7 @@
#include "content/port/browser/render_widget_host_view_port.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/shell/browser/shell.h"
#include "content/test/accessibility_browser_test_utils.h"
@@ -119,6 +121,13 @@ class DumpAccessibilityTreeTest : public ContentBrowserTest {
}
}
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ ContentBrowserTest::SetUpCommandLine(command_line);
+ // Enable <dialog>, which is used in some tests.
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ }
+
void RunTest(const base::FilePath::CharType* file_path);
};
@@ -152,7 +161,7 @@ void DumpAccessibilityTreeTest::RunTest(
// Tolerate Windows-style line endings (\r\n) in the expected file:
// normalize by deleting all \r from the file (if any) to leave only \n.
std::string expected_contents;
- RemoveChars(expected_contents_raw, "\r", &expected_contents);
+ base::RemoveChars(expected_contents_raw, "\r", &expected_contents);
if (!expected_contents.compare(0, strlen(kMarkSkipFile), kMarkSkipFile)) {
printf("Skipping this test on this platform.\n");
@@ -160,13 +169,13 @@ void DumpAccessibilityTreeTest::RunTest(
}
// Load the page.
- string16 html_contents16;
+ base::string16 html_contents16;
html_contents16 = UTF8ToUTF16(html_contents);
GURL url = GetTestUrl("accessibility",
html_file.BaseName().MaybeAsASCII().c_str());
AccessibilityNotificationWaiter waiter(
shell(), AccessibilityModeComplete,
- WebKit::WebAXEventLoadComplete);
+ blink::WebAXEventLoadComplete);
NavigateToURL(shell(), url);
waiter.WaitForNotification();
@@ -182,7 +191,7 @@ void DumpAccessibilityTreeTest::RunTest(
formatter.SetFilters(filters);
// Perform a diff (or write the initial baseline).
- string16 actual_contents_utf16;
+ base::string16 actual_contents_utf16;
formatter.FormatAccessibilityTree(&actual_contents_utf16);
std::string actual_contents = UTF16ToUTF8(actual_contents_utf16);
std::vector<std::string> actual_lines, expected_lines;
@@ -332,6 +341,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunTest(FILE_PATH_LITERAL("checkbox-name-calc.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDialog) {
+ RunTest(FILE_PATH_LITERAL("dialog.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDiv) {
RunTest(FILE_PATH_LITERAL("div.html"));
}
@@ -398,6 +411,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunTest(FILE_PATH_LITERAL("input-text-name-calc.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputTypes) {
+ RunTest(FILE_PATH_LITERAL("input-types.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityLabel) {
RunTest(FILE_PATH_LITERAL("label.html"));
}
@@ -406,6 +423,31 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityListMarkers) {
RunTest(FILE_PATH_LITERAL("list-markers.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityModalDialogClosed) {
+ RunTest(FILE_PATH_LITERAL("modal-dialog-closed.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityModalDialogOpened) {
+ RunTest(FILE_PATH_LITERAL("modal-dialog-opened.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityModalDialogInIframeClosed) {
+ RunTest(FILE_PATH_LITERAL("modal-dialog-in-iframe-closed.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityModalDialogInIframeOpened) {
+ RunTest(FILE_PATH_LITERAL("modal-dialog-in-iframe-opened.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityModalDialogStack) {
+ RunTest(FILE_PATH_LITERAL("modal-dialog-stack.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityP) {
RunTest(FILE_PATH_LITERAL("p.html"));
}
diff --git a/chromium/content/browser/android/OWNERS b/chromium/content/browser/android/OWNERS
index a5cf4a90179..4fd5d774a7c 100644
--- a/chromium/content/browser/android/OWNERS
+++ b/chromium/content/browser/android/OWNERS
@@ -1,5 +1,8 @@
bulach@chromium.org
-joth@chromium.org
+sievers@chromium.org
+skyostil@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
-sievers@chromium.org
+
+# Input handling related
+jdduke@chromium.org
diff --git a/chromium/content/browser/android/child_process_launcher_android.cc b/chromium/content/browser/android/child_process_launcher_android.cc
index 962fee861f7..cf915e4a42a 100644
--- a/chromium/content/browser/android/child_process_launcher_android.cc
+++ b/chromium/content/browser/android/child_process_launcher_android.cc
@@ -70,7 +70,7 @@ static void SetSurfacePeer(
// the ChildProcess could not be created.
static void OnChildProcessStarted(JNIEnv*,
jclass,
- jint client_context,
+ jlong client_context,
jint handle) {
StartChildProcessCallback* callback =
reinterpret_cast<StartChildProcessCallback*>(client_context);
@@ -122,7 +122,7 @@ void StartChildProcess(
j_file_ids.obj(),
j_file_fds.obj(),
j_file_auto_close.obj(),
- reinterpret_cast<jint>(new StartChildProcessCallback(callback)));
+ reinterpret_cast<intptr_t>(new StartChildProcessCallback(callback)));
}
void StopChildProcess(base::ProcessHandle handle) {
@@ -131,6 +131,13 @@ void StopChildProcess(base::ProcessHandle handle) {
Java_ChildProcessLauncher_stop(env, static_cast<jint>(handle));
}
+bool IsChildProcessOomProtected(base::ProcessHandle handle) {
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+ return Java_ChildProcessLauncher_isOomProtected(env,
+ static_cast<jint>(handle));
+}
+
void EstablishSurfacePeer(
JNIEnv* env, jclass clazz,
jint pid, jobject surface, jint primary_id, jint secondary_id) {
diff --git a/chromium/content/browser/android/child_process_launcher_android.h b/chromium/content/browser/android/child_process_launcher_android.h
index b90ff2338c6..71a6f04c712 100644
--- a/chromium/content/browser/android/child_process_launcher_android.h
+++ b/chromium/content/browser/android/child_process_launcher_android.h
@@ -29,6 +29,8 @@ void StartChildProcess(
// StartChildProcess.
void StopChildProcess(base::ProcessHandle handle);
+bool IsChildProcessOomProtected(base::ProcessHandle handle);
+
bool RegisterChildProcessLauncher(JNIEnv* env);
} // namespace content
diff --git a/chromium/content/browser/android/content_settings.cc b/chromium/content/browser/android/content_settings.cc
index d087d6bd2c2..7c6407fd177 100644
--- a/chromium/content/browser/android/content_settings.cc
+++ b/chromium/content/browser/android/content_settings.cc
@@ -26,7 +26,7 @@ ContentSettings::~ContentSettings() {
ScopedJavaLocalRef<jobject> obj = content_settings_.get(env);
if (obj.obj()) {
Java_ContentSettings_onNativeContentSettingsDestroyed(env, obj.obj(),
- reinterpret_cast<jint>(this));
+ reinterpret_cast<intptr_t>(this));
}
}
@@ -46,13 +46,13 @@ void ContentSettings::WebContentsDestroyed(WebContents* web_contents) {
delete this;
}
-static jint Init(JNIEnv* env, jobject obj, jint nativeContentViewCore) {
+static jlong Init(JNIEnv* env, jobject obj, jlong nativeContentViewCore) {
WebContents* web_contents =
reinterpret_cast<ContentViewCoreImpl*>(nativeContentViewCore)
->GetWebContents();
ContentSettings* content_settings =
new ContentSettings(env, obj, web_contents);
- return reinterpret_cast<jint>(content_settings);
+ return reinterpret_cast<intptr_t>(content_settings);
}
} // namespace content
diff --git a/chromium/content/browser/android/content_startup_flags.cc b/chromium/content/browser/android/content_startup_flags.cc
index b755e4dc783..7d950343443 100644
--- a/chromium/content/browser/android/content_startup_flags.cc
+++ b/chromium/content/browser/android/content_startup_flags.cc
@@ -4,6 +4,7 @@
#include "content/browser/android/content_startup_flags.h"
+#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
@@ -60,32 +61,41 @@ void SetContentCommandLineFlags(int max_render_process_count,
parsed_command_line->AppendSwitch(switches::kEnableBeginFrameScheduling);
parsed_command_line->AppendSwitch(switches::kEnableDeadlineScheduling);
+ parsed_command_line->AppendSwitch(switches::kDisableGestureDebounce);
parsed_command_line->AppendSwitch(switches::kEnableGestureTapHighlight);
parsed_command_line->AppendSwitch(switches::kEnablePinch);
parsed_command_line->AppendSwitch(switches::kEnableOverlayFullscreenVideo);
parsed_command_line->AppendSwitch(switches::kEnableOverlayScrollbars);
parsed_command_line->AppendSwitch(switches::kEnableOverscrollNotifications);
+ parsed_command_line->AppendSwitchASCII(switches::kTouchAckTimeoutDelayMs,
+ "200");
// Run the GPU service as a thread in the browser instead of as a
// standalone process.
parsed_command_line->AppendSwitch(switches::kInProcessGPU);
parsed_command_line->AppendSwitch(switches::kDisableGpuShaderDiskCache);
- // Always use fixed layout and viewport tag.
- parsed_command_line->AppendSwitch(switches::kEnableFixedLayout);
parsed_command_line->AppendSwitch(switches::kEnableViewport);
-
- // Disable <canvas> path antialiasing.
- parsed_command_line->AppendSwitch(switches::kDisable2dCanvasAntialiasing);
+ parsed_command_line->AppendSwitch(switches::kEnableViewportMeta);
+ parsed_command_line->AppendSwitch(
+ switches::kMainFrameResizesAreOrientationChanges);
// Disable anti-aliasing.
parsed_command_line->AppendSwitch(
cc::switches::kDisableCompositedAntialiasing);
+ parsed_command_line->AppendSwitch(switches::kUIPrioritizeInGpuProcess);
+
if (!plugin_descriptor.empty()) {
parsed_command_line->AppendSwitchNative(
switches::kRegisterPepperPlugins, plugin_descriptor);
}
+
+ // Disable profiler timing by default.
+ if (!parsed_command_line->HasSwitch(switches::kProfilerTiming)) {
+ parsed_command_line->AppendSwitchASCII(
+ switches::kProfilerTiming, switches::kProfilerTimingDisabledValue);
+ }
}
} // namespace content
diff --git a/chromium/content/browser/android/content_video_view.cc b/chromium/content/browser/android/content_video_view.cc
index b8d5c64d542..9ee541aab0d 100644
--- a/chromium/content/browser/android/content_video_view.cc
+++ b/chromium/content/browser/android/content_video_view.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "content/browser/media/android/browser_media_player_manager.h"
+#include "content/browser/power_save_blocker_impl.h"
#include "content/common/android/surface_texture_peer.h"
#include "content/public/common/content_switches.h"
#include "jni/ContentVideoView_jni.h"
@@ -48,8 +49,9 @@ ContentVideoView::ContentVideoView(
JNIEnv *env = AttachCurrentThread();
j_content_video_view_ = JavaObjectWeakGlobalRef(env,
Java_ContentVideoView_createContentVideoView(env, context.obj(),
- reinterpret_cast<int>(this), client.obj()).obj());
+ reinterpret_cast<intptr_t>(this), client.obj()).obj());
g_content_video_view = this;
+ CreatePowerSaveBlocker();
}
ContentVideoView::~ContentVideoView() {
@@ -59,23 +61,26 @@ ContentVideoView::~ContentVideoView() {
}
void ContentVideoView::OpenVideo() {
- JNIEnv *env = AttachCurrentThread();
+ JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
- if (!content_video_view.is_null())
+ if (!content_video_view.is_null()) {
+ CreatePowerSaveBlocker();
Java_ContentVideoView_openVideo(env, content_video_view.obj());
+ }
}
void ContentVideoView::OnMediaPlayerError(int error_type) {
- JNIEnv *env = AttachCurrentThread();
+ JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
+ power_save_blocker_.reset();
Java_ContentVideoView_onMediaPlayerError(env, content_video_view.obj(),
error_type);
}
}
void ContentVideoView::OnVideoSizeChanged(int width, int height) {
- JNIEnv *env = AttachCurrentThread();
+ JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
Java_ContentVideoView_onVideoSizeChanged(env, content_video_view.obj(),
@@ -84,7 +89,7 @@ void ContentVideoView::OnVideoSizeChanged(int width, int height) {
}
void ContentVideoView::OnBufferingUpdate(int percent) {
- JNIEnv *env = AttachCurrentThread();
+ JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
Java_ContentVideoView_onBufferingUpdate(env, content_video_view.obj(),
@@ -93,10 +98,12 @@ void ContentVideoView::OnBufferingUpdate(int percent) {
}
void ContentVideoView::OnPlaybackComplete() {
- JNIEnv *env = AttachCurrentThread();
+ JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
- if (!content_video_view.is_null())
+ if (!content_video_view.is_null()) {
+ power_save_blocker_.reset();
Java_ContentVideoView_onPlaybackComplete(env, content_video_view.obj());
+ }
}
void ContentVideoView::OnExitFullscreen() {
@@ -104,7 +111,7 @@ void ContentVideoView::OnExitFullscreen() {
}
void ContentVideoView::UpdateMediaMetadata() {
- JNIEnv *env = AttachCurrentThread();
+ JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null())
UpdateMediaMetadata(env, content_video_view.obj());
@@ -140,15 +147,18 @@ void ContentVideoView::SeekTo(JNIEnv*, jobject obj, jint msec) {
}
void ContentVideoView::Play(JNIEnv*, jobject obj) {
+ CreatePowerSaveBlocker();
manager_->FullscreenPlayerPlay();
}
void ContentVideoView::Pause(JNIEnv*, jobject obj) {
+ power_save_blocker_.reset();
manager_->FullscreenPlayerPause();
}
void ContentVideoView::ExitFullscreen(
JNIEnv*, jobject, jboolean release_media_player) {
+ power_save_blocker_.reset();
j_content_video_view_.reset();
manager_->ExitFullscreen(release_media_player);
}
@@ -172,10 +182,33 @@ ScopedJavaLocalRef<jobject> ContentVideoView::GetJavaObject(JNIEnv* env) {
return j_content_video_view_.get(env);
}
+gfx::NativeView ContentVideoView::GetNativeView() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
+ if (content_video_view.is_null())
+ return NULL;
+
+ return reinterpret_cast<gfx::NativeView>(
+ Java_ContentVideoView_getNativeViewAndroid(env,
+ content_video_view.obj()));
+
+}
+
+void ContentVideoView::CreatePowerSaveBlocker() {
+ if (power_save_blocker_) return;
+
+ power_save_blocker_ = PowerSaveBlocker::Create(
+ PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
+ "Playing video").Pass();
+ static_cast<PowerSaveBlockerImpl*>(power_save_blocker_.get())->
+ InitDisplaySleepBlocker(GetNativeView());
+}
+
void ContentVideoView::DestroyContentVideoView(bool native_view_destroyed) {
- JNIEnv *env = AttachCurrentThread();
+ JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
+ j_content_video_view_.reset();
Java_ContentVideoView_destroyContentVideoView(env,
content_video_view.obj(), native_view_destroyed);
j_content_video_view_.reset();
diff --git a/chromium/content/browser/android/content_video_view.h b/chromium/content/browser/android/content_video_view.h
index 2a86830def3..633b9031fbf 100644
--- a/chromium/content/browser/android/content_video_view.h
+++ b/chromium/content/browser/android/content_video_view.h
@@ -13,10 +13,12 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
+#include "ui/gfx/native_widget_types.h"
namespace content {
class BrowserMediaPlayerManager;
+class PowerSaveBlocker;
// Native mirror of ContentVideoView.java. This class is responsible for
// creating the Java video view and pass all the player status change to
@@ -80,10 +82,23 @@ class ContentVideoView {
// no further calls to the native object is allowed.
void DestroyContentVideoView(bool native_view_destroyed);
+ // Returns the associated NativeView
+ gfx::NativeView GetNativeView();
+
+ void CreatePowerSaveBlocker();
+
// Object that manages the fullscreen media player. It is responsible for
// handling all the playback controls.
BrowserMediaPlayerManager* manager_;
+ // PowerSaveBlock to keep screen on for fullscreen video.
+ // There is already blocker when inline video started, and it requires the
+ // ContentView's container displayed to take effect; but in WebView, apps
+ // could use another container to hold ContentVideoView, and the blocker in
+ // ContentView's container can not keep screen on; so we need another blocker
+ // here, it is no harm, just an additonal blocker.
+ scoped_ptr<PowerSaveBlocker> power_save_blocker_;
+
// Weak reference of corresponding Java object.
JavaObjectWeakGlobalRef j_content_video_view_;
diff --git a/chromium/content/browser/android/content_view_core_impl.cc b/chromium/content/browser/android/content_view_core_impl.cc
index dd15c1f67b8..f5450f45110 100644
--- a/chromium/content/browser/android/content_view_core_impl.cc
+++ b/chromium/content/browser/android/content_view_core_impl.cc
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "cc/layers/layer.h"
@@ -18,6 +19,9 @@
#include "content/browser/android/interstitial_page_delegate_android.h"
#include "content/browser/android/load_url_params.h"
#include "content/browser/android/touch_point.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/media/android/browser_media_player_manager.h"
#include "content/browser/renderer_host/compositor_impl_android.h"
#include "content/browser/renderer_host/input/web_input_event_builders_android.h"
@@ -27,9 +31,6 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/browser/ssl/ssl_host_state.h"
-#include "content/browser/web_contents/interstitial_page_impl.h"
-#include "content/browser/web_contents/navigation_controller_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/browser/web_contents/web_contents_view_android.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
@@ -48,8 +49,8 @@
#include "jni/ContentViewCore_jni.h"
#include "third_party/WebKit/public/web/WebBindings.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/android/view_android.h"
-#include "ui/android/window_android.h"
+#include "ui/base/android/view_android.h"
+#include "ui/base/android/window_android.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size_conversions.h"
@@ -63,17 +64,20 @@ using base::android::ConvertUTF16ToJavaString;
using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
// Describes the type and enabled state of a select popup item.
-// Keep in sync with the value defined in SelectPopupDialog.java
-enum PopupItemType {
- POPUP_ITEM_TYPE_GROUP = 0,
- POPUP_ITEM_TYPE_DISABLED,
- POPUP_ITEM_TYPE_ENABLED
+namespace {
+
+enum {
+#define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
+#include "content/browser/android/popup_item_type_list.h"
+#undef DEFINE_POPUP_ITEM_TYPE
};
+} //namespace
+
namespace content {
namespace {
@@ -103,7 +107,8 @@ ScopedJavaLocalRef<jobject> CreateJavaRect(
static_cast<int>(rect.y()),
static_cast<int>(rect.right()),
static_cast<int>(rect.bottom())));
-};
+}
+
} // namespace
// Enables a callback when the underlying WebContents is destroyed, to enable
@@ -159,24 +164,21 @@ ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env, jobject obj,
WebContents* web_contents,
ui::ViewAndroid* view_android,
ui::WindowAndroid* window_android)
- : java_ref_(env, obj),
+ : WebContentsObserver(web_contents),
+ java_ref_(env, obj),
web_contents_(static_cast<WebContentsImpl*>(web_contents)),
root_layer_(cc::Layer::Create()),
- tab_crashed_(false),
vsync_interval_(base::TimeDelta::FromMicroseconds(
kDefaultVSyncIntervalMicros)),
expected_browser_composite_time_(base::TimeDelta::FromMicroseconds(
kDefaultVSyncIntervalMicros * kDefaultBrowserCompositeVSyncFraction)),
view_android_(view_android),
- window_android_(window_android) {
+ window_android_(window_android),
+ device_orientation_(0),
+ geolocation_needs_pause_(false) {
CHECK(web_contents) <<
"A ContentViewCoreImpl should be created with a valid WebContents.";
- // When a tab is restored (from a saved state), it does not have a renderer
- // process. We treat it like the tab is crashed. If the content is loaded
- // when the tab is shown, tab_crashed_ will be reset.
- UpdateTabCrashedFlag();
-
// TODO(leandrogracia): make use of the hardware_accelerated argument.
const gfx::Display& display =
@@ -202,13 +204,18 @@ ContentViewCoreImpl::~ContentViewCoreImpl() {
java_ref_.reset();
if (!j_obj.is_null()) {
Java_ContentViewCore_onNativeContentViewCoreDestroyed(
- env, j_obj.obj(), reinterpret_cast<jint>(this));
+ env, j_obj.obj(), reinterpret_cast<intptr_t>(this));
}
// Make sure nobody calls back into this object while we are tearing things
// down.
notification_registrar_.RemoveAll();
}
+base::android::ScopedJavaLocalRef<jobject>
+ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) {
+ return web_contents_->GetJavaWebContents();
+}
+
void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
jobject obj) {
DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
@@ -219,16 +226,13 @@ void ContentViewCoreImpl::InitWebContents() {
DCHECK(web_contents_);
notification_registrar_.Add(
this, NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
- Source<NavigationController>(&web_contents_->GetController()));
+ Source<WebContents>(web_contents_));
notification_registrar_.Add(
this, NOTIFICATION_RENDERER_PROCESS_CREATED,
content::NotificationService::AllBrowserContextsAndSources());
notification_registrar_.Add(
this, NOTIFICATION_WEB_CONTENTS_CONNECTED,
Source<WebContents>(web_contents_));
- notification_registrar_.Add(
- this, NOTIFICATION_WEB_CONTENTS_SWAPPED,
- Source<WebContents>(web_contents_));
static_cast<WebContentsViewAndroid*>(web_contents_->GetView())->
SetContentViewCore(this);
@@ -248,6 +252,12 @@ void ContentViewCoreImpl::Observe(int type,
if (switched_details->first) {
old_pid = GetRenderProcessIdFromRenderViewHost(
switched_details->first);
+
+ RenderWidgetHostViewAndroid* view =
+ static_cast<RenderWidgetHostViewAndroid*>(
+ switched_details->first->GetView());
+ if (view)
+ view->SetContentViewCore(NULL);
}
int new_pid = GetRenderProcessIdFromRenderViewHost(
web_contents_->GetRenderViewHost());
@@ -261,6 +271,8 @@ void ContentViewCoreImpl::Observe(int type,
}
}
SetFocusInternal(HasFocus());
+ if (geolocation_needs_pause_)
+ PauseOrResumeGeolocation(true);
break;
}
case NOTIFICATION_RENDERER_PROCESS_CREATED: {
@@ -289,16 +301,14 @@ void ContentViewCoreImpl::Observe(int type,
}
break;
}
- case NOTIFICATION_WEB_CONTENTS_SWAPPED: {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (!obj.is_null()) {
- Java_ContentViewCore_onWebContentsSwapped(env, obj.obj());
- }
- }
}
}
+void ContentViewCoreImpl::RenderViewReady() {
+ if (device_orientation_ != 0)
+ SendOrientationChangeEventInternal();
+}
+
RenderWidgetHostViewAndroid*
ContentViewCoreImpl::GetRenderWidgetHostViewAndroid() {
RenderWidgetHostView* rwhv = NULL;
@@ -335,9 +345,6 @@ void ContentViewCoreImpl::OnShow(JNIEnv* env, jobject obj) {
void ContentViewCoreImpl::Show() {
GetWebContents()->WasShown();
- // Displaying WebContents may trigger a lazy reload, spawning a new renderer
- // for the tab.
- UpdateTabCrashedFlag();
}
void ContentViewCoreImpl::Hide() {
@@ -351,24 +358,32 @@ void ContentViewCoreImpl::PauseVideo() {
host->Send(new ViewMsg_PauseVideo(host->GetRoutingID()));
}
+void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
+ geolocation_needs_pause_ = should_pause;
+ RenderViewHostImpl* rvh =
+ static_cast<RenderViewHostImpl*>(web_contents_->GetRenderViewHost());
+ if (rvh) {
+ scoped_refptr<GeolocationDispatcherHost> geolocation_dispatcher =
+ static_cast<RenderProcessHostImpl*>(
+ web_contents_->GetRenderProcessHost())->
+ geolocation_dispatcher_host();
+ if (geolocation_dispatcher.get()) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&GeolocationDispatcherHost::PauseOrResume,
+ geolocation_dispatcher,
+ rvh->GetRoutingID(),
+ should_pause));
+ geolocation_needs_pause_ = false;
+ }
+ }
+}
+
void ContentViewCoreImpl::OnTabCrashed() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
Java_ContentViewCore_resetVSyncNotification(env, obj.obj());
-
- // Note that we might reach this place multiple times while the
- // ContentViewCore remains crashed. E.g. if two tabs share the render process
- // and the process crashes, this will be called for each tab. If the user
- // reload one tab, a new render process is created and it can be shared by the
- // other tab. But if user closes the reloaded tab before reloading the other
- // tab, the new render process will be shut down. This will trigger the other
- // tab's OnTabCrashed() called again as two tabs share the same
- // BrowserRenderProcessHost. The Java side will distinguish this case using
- // tab_crashed_ passed below.
- Java_ContentViewCore_onTabCrash(env, obj.obj(), tab_crashed_);
- tab_crashed_ = true;
}
// All positions and sizes are in CSS pixels.
@@ -383,15 +398,19 @@ void ContentViewCoreImpl::UpdateFrameInfo(
const gfx::Vector2dF& controls_offset,
const gfx::Vector2dF& content_offset,
float overdraw_bottom_height) {
- if (window_android_)
- window_android_->set_content_offset(
- gfx::ScaleVector2d(content_offset, dpi_scale_));
-
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
+ if (window_android_) {
+ gfx::Vector2dF window_offset(
+ Java_ContentViewCore_getLocationInWindowX(env, obj.obj()),
+ Java_ContentViewCore_getLocationInWindowY(env, obj.obj()));
+ window_android_->set_content_offset(
+ gfx::ScaleVector2d(content_offset, dpi_scale_) + window_offset);
+ }
+
Java_ContentViewCore_updateFrameInfo(
env, obj.obj(),
scroll_offset.x(),
@@ -408,7 +427,7 @@ void ContentViewCoreImpl::UpdateFrameInfo(
overdraw_bottom_height);
}
-void ContentViewCoreImpl::SetTitle(const string16& title) {
+void ContentViewCoreImpl::SetTitle(const base::string16& title) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
@@ -457,7 +476,7 @@ void ContentViewCoreImpl::ShowSelectPopupMenu(
ScopedJavaLocalRef<jintArray> enabled_array(env,
env->NewIntArray(items.size()));
- std::vector<string16> labels;
+ std::vector<base::string16> labels;
labels.reserve(items.size());
for (size_t i = 0; i < items.size(); ++i) {
labels.push_back(items[i].label);
@@ -491,6 +510,14 @@ void ContentViewCoreImpl::UnhandledFlingStartEvent() {
Java_ContentViewCore_unhandledFlingStartEvent(env, j_obj.obj());
}
+void ContentViewCoreImpl::OnScrollUpdateGestureConsumed() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
+ if (j_obj.is_null())
+ return;
+ Java_ContentViewCore_onScrollUpdateGestureConsumed(env, j_obj.obj());
+}
+
void ContentViewCoreImpl::HasTouchEventHandlers(bool need_touch_events) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
@@ -589,28 +616,13 @@ void ContentViewCoreImpl::ShowDisambiguationPopup(
java_bitmap.obj());
}
-ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateOnePointTouchGesture(
- int32 start_x, int32 start_y, int32 delta_x, int32 delta_y) {
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null())
- return ScopedJavaLocalRef<jobject>();
- return Java_ContentViewCore_createOnePointTouchGesture(
- env, obj.obj(), start_x, start_y, delta_x, delta_y);
-}
-
-ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTwoPointTouchGesture(
- int32 start_x0, int32 start_y0, int32 delta_x0, int32 delta_y0,
- int32 start_x1, int32 start_y1, int32 delta_x1, int32 delta_y1) {
+ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return ScopedJavaLocalRef<jobject>();
- return Java_ContentViewCore_createTwoPointTouchGesture(
- env, obj.obj(), start_x0, start_y0, delta_x0, delta_y0,
- start_x1, start_y1, delta_x1, delta_y1);
+ return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
}
void ContentViewCoreImpl::NotifyExternalSurface(
@@ -652,6 +664,17 @@ ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() {
return Java_ContentViewCore_getContext(env, obj.obj());
}
+bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
+ JNIEnv* env = AttachCurrentThread();
+
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return true;
+ ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
+ return Java_ContentViewCore_shouldBlockMediaRequest(env, obj.obj(),
+ j_url.obj());
+}
+
gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
@@ -712,16 +735,22 @@ void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
void ContentViewCoreImpl::LoadUrl(
NavigationController::LoadURLParams& params) {
GetWebContents()->GetController().LoadURLWithParams(params);
- UpdateTabCrashedFlag();
}
-void ContentViewCoreImpl::SetNeedsBeginFrame(bool enabled) {
+void ContentViewCoreImpl::AddBeginFrameSubscriber() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return;
+ Java_ContentViewCore_addVSyncSubscriber(env, obj.obj());
+}
+
+void ContentViewCoreImpl::RemoveBeginFrameSubscriber() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
- Java_ContentViewCore_setVSyncNotificationEnabled(
- env, obj.obj(), static_cast<jboolean>(enabled));
+ Java_ContentViewCore_removeVSyncSubscriber(env, obj.obj());
}
void ContentViewCoreImpl::SetNeedsAnimate() {
@@ -858,13 +887,10 @@ void ContentViewCoreImpl::SetFocusInternal(bool focused) {
void ContentViewCoreImpl::SendOrientationChangeEvent(JNIEnv* env,
jobject obj,
jint orientation) {
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
- if (rwhv)
- rwhv->UpdateScreenInfo(rwhv->GetNativeView());
-
- RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
- web_contents_->GetRenderViewHost());
- rvhi->SendOrientationChangeEvent(orientation);
+ if (device_orientation_ != orientation) {
+ device_orientation_ = orientation;
+ SendOrientationChangeEventInternal();
+ }
}
jboolean ContentViewCoreImpl::SendTouchEvent(JNIEnv* env,
@@ -874,8 +900,8 @@ jboolean ContentViewCoreImpl::SendTouchEvent(JNIEnv* env,
jobjectArray pts) {
RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
if (rwhv) {
- using WebKit::WebTouchEvent;
- WebKit::WebTouchEvent event;
+ using blink::WebTouchEvent;
+ blink::WebTouchEvent event;
TouchPoint::BuildWebTouchEvent(env, type, time_ms, GetDpiScale(), pts,
event);
rwhv->SendTouchEvent(event);
@@ -909,9 +935,9 @@ jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
if (!rwhv)
return false;
- WebKit::WebMouseEvent event = WebMouseEventBuilder::Build(
+ blink::WebMouseEvent event = WebMouseEventBuilder::Build(
WebInputEvent::MouseMove,
- WebKit::WebMouseEvent::ButtonNone,
+ blink::WebMouseEvent::ButtonNone,
time_ms / 1000.0, x / GetDpiScale(), y / GetDpiScale(), 0, 1);
rwhv->SendMouseEvent(event);
@@ -936,7 +962,7 @@ jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
} else {
return false;
}
- WebKit::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
+ blink::WebMouseWheelEvent event = WebMouseWheelEventBuilder::Build(
direction, time_ms / 1000.0, x / GetDpiScale(), y / GetDpiScale());
rwhv->SendMouseWheelEvent(event);
@@ -944,24 +970,18 @@ jboolean ContentViewCoreImpl::SendMouseWheelEvent(JNIEnv* env,
}
WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
- WebInputEvent::Type type, long time_ms, float x, float y) const {
+ WebInputEvent::Type type, int64 time_ms, float x, float y) const {
return WebGestureEventBuilder::Build(
type, time_ms / 1000.0, x / GetDpiScale(), y / GetDpiScale());
}
void ContentViewCoreImpl::SendGestureEvent(
- const WebKit::WebGestureEvent& event) {
+ const blink::WebGestureEvent& event) {
RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
if (rwhv)
rwhv->SendGestureEvent(event);
}
-void ContentViewCoreImpl::UpdateTabCrashedFlag() {
- // Since RenderWidgetHostView is associated with the lifetime of the renderer
- // process, we use it to test whether there is a renderer process.
- tab_crashed_ = !(web_contents_->GetRenderWidgetHostView());
-}
-
void ContentViewCoreImpl::ScrollBegin(JNIEnv* env, jobject obj, jlong time_ms,
jfloat x, jfloat y) {
WebGestureEvent event = MakeGestureEvent(
@@ -1039,20 +1059,28 @@ void ContentViewCoreImpl::ShowPressState(JNIEnv* env, jobject obj,
jlong time_ms,
jfloat x, jfloat y) {
WebGestureEvent event = MakeGestureEvent(
- WebInputEvent::GestureTapDown, time_ms, x, y);
+ WebInputEvent::GestureShowPress, time_ms, x, y);
SendGestureEvent(event);
}
-void ContentViewCoreImpl::ShowPressCancel(JNIEnv* env,
- jobject obj,
- jlong time_ms,
- jfloat x,
- jfloat y) {
+void ContentViewCoreImpl::TapCancel(JNIEnv* env,
+ jobject obj,
+ jlong time_ms,
+ jfloat x,
+ jfloat y) {
WebGestureEvent event = MakeGestureEvent(
WebInputEvent::GestureTapCancel, time_ms, x, y);
SendGestureEvent(event);
}
+void ContentViewCoreImpl::TapDown(JNIEnv* env, jobject obj,
+ jlong time_ms,
+ jfloat x, jfloat y) {
+ WebGestureEvent event = MakeGestureEvent(
+ WebInputEvent::GestureTapDown, time_ms, x, y);
+ SendGestureEvent(event);
+}
+
void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
jfloat x, jfloat y) {
WebGestureEvent event = MakeGestureEvent(
@@ -1131,44 +1159,8 @@ void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
}
}
-jboolean ContentViewCoreImpl::CanGoBack(JNIEnv* env, jobject obj) {
- return web_contents_->GetController().CanGoBack();
-}
-
-jboolean ContentViewCoreImpl::CanGoForward(JNIEnv* env, jobject obj) {
- return web_contents_->GetController().CanGoForward();
-}
-
-jboolean ContentViewCoreImpl::CanGoToOffset(JNIEnv* env, jobject obj,
- jint offset) {
- return web_contents_->GetController().CanGoToOffset(offset);
-}
-
-void ContentViewCoreImpl::GoBack(JNIEnv* env, jobject obj) {
- web_contents_->GetController().GoBack();
- UpdateTabCrashedFlag();
-}
-
-void ContentViewCoreImpl::GoForward(JNIEnv* env, jobject obj) {
- web_contents_->GetController().GoForward();
- UpdateTabCrashedFlag();
-}
-
-void ContentViewCoreImpl::GoToOffset(JNIEnv* env, jobject obj, jint offset) {
- web_contents_->GetController().GoToOffset(offset);
- UpdateTabCrashedFlag();
-}
-
-void ContentViewCoreImpl::GoToNavigationIndex(JNIEnv* env,
- jobject obj,
- jint index) {
- web_contents_->GetController().GoToIndex(index);
- UpdateTabCrashedFlag();
-}
-
void ContentViewCoreImpl::LoadIfNecessary(JNIEnv* env, jobject obj) {
web_contents_->GetController().LoadIfNecessary();
- UpdateTabCrashedFlag();
}
void ContentViewCoreImpl::RequestRestoreLoad(JNIEnv* env, jobject obj) {
@@ -1179,14 +1171,19 @@ void ContentViewCoreImpl::StopLoading(JNIEnv* env, jobject obj) {
web_contents_->Stop();
}
-void ContentViewCoreImpl::Reload(JNIEnv* env, jobject obj) {
- // Set check_for_repost parameter to false as we have no repost confirmation
- // dialog ("confirm form resubmission" screen will still appear, however).
+void ContentViewCoreImpl::Reload(JNIEnv* env,
+ jobject obj,
+ jboolean check_for_repost) {
if (web_contents_->GetController().NeedsReload())
web_contents_->GetController().LoadIfNecessary();
else
- web_contents_->GetController().Reload(true);
- UpdateTabCrashedFlag();
+ web_contents_->GetController().Reload(check_for_repost);
+}
+
+void ContentViewCoreImpl::ReloadIgnoringCache(JNIEnv* env,
+ jobject obj,
+ jboolean check_for_repost) {
+ web_contents_->GetController().ReloadIgnoringCache(check_for_repost);
}
void ContentViewCoreImpl::CancelPendingReload(JNIEnv* env, jobject obj) {
@@ -1199,8 +1196,8 @@ void ContentViewCoreImpl::ContinuePendingReload(JNIEnv* env, jobject obj) {
void ContentViewCoreImpl::ClearHistory(JNIEnv* env, jobject obj) {
// TODO(creis): Do callers of this need to know if it fails?
- if (web_contents_->GetController().CanPruneAllButVisible())
- web_contents_->GetController().PruneAllButVisible();
+ if (web_contents_->GetController().CanPruneAllButLastCommitted())
+ web_contents_->GetController().PruneAllButLastCommitted();
}
void ContentViewCoreImpl::AddJavascriptInterface(
@@ -1223,7 +1220,7 @@ void ContentViewCoreImpl::AddJavascriptInterface(
java_bridge->AsWeakPtr());
java_bridge->AddNamedObject(ConvertJavaStringToUTF16(env, name),
bound_object);
- WebKit::WebBindings::releaseObject(bound_object);
+ blink::WebBindings::releaseObject(bound_object);
}
void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
@@ -1317,27 +1314,27 @@ void ContentViewCoreImpl::AttachExternalVideoSurface(JNIEnv* env,
jobject obj,
jint player_id,
jobject jsurface) {
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
web_contents_->GetRenderViewHost());
if (rvhi && rvhi->media_player_manager()) {
rvhi->media_player_manager()->AttachExternalVideoSurface(
static_cast<int>(player_id), jsurface);
}
-#endif
+#endif // defined(VIDEO_HOLE)
}
void ContentViewCoreImpl::DetachExternalVideoSurface(JNIEnv* env,
jobject obj,
jint player_id) {
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
web_contents_->GetRenderViewHost());
if (rvhi && rvhi->media_player_manager()) {
rvhi->media_player_manager()->DetachExternalVideoSurface(
static_cast<int>(player_id));
}
-#endif
+#endif // defined(VIDEO_HOLE)
}
jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
@@ -1459,10 +1456,6 @@ int ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
return rwhva->GetNativeImeAdapter();
}
-jboolean ContentViewCoreImpl::NeedsReload(JNIEnv* env, jobject obj) {
- return web_contents_->GetController().NeedsReload();
-}
-
void ContentViewCoreImpl::UndoScrollFocusedEditableNodeIntoView(
JNIEnv* env,
jobject obj) {
@@ -1501,7 +1494,7 @@ void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv* env,
if (!callback) {
// No callback requested.
- rvh->ExecuteJavascriptInWebFrame(string16(), // frame_xpath
+ rvh->ExecuteJavascriptInWebFrame(base::string16(), // frame_xpath
ConvertJavaStringToUTF16(env, script));
return;
}
@@ -1514,7 +1507,7 @@ void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv* env,
base::Bind(&JavaScriptResultCallback, j_callback);
rvh->ExecuteJavascriptInWebFrameCallbackResult(
- string16(), // frame_xpath
+ base::string16(), // frame_xpath
ConvertJavaStringToUTF16(env, script),
c_callback);
}
@@ -1532,7 +1525,8 @@ void ContentViewCoreImpl::UpdateImeAdapter(int native_ime_adapter,
int selection_end,
int composition_start,
int composition_end,
- bool show_ime_if_needed) {
+ bool show_ime_if_needed,
+ bool require_ack) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
@@ -1544,15 +1538,7 @@ void ContentViewCoreImpl::UpdateImeAdapter(int native_ime_adapter,
jstring_text.obj(),
selection_start, selection_end,
composition_start, composition_end,
- show_ime_if_needed);
-}
-
-void ContentViewCoreImpl::ProcessImeBatchStateAck(bool is_begin) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null())
- return;
- Java_ContentViewCore_processImeBatchStateAck(env, obj.obj(), is_begin);
+ show_ime_if_needed, require_ack);
}
void ContentViewCoreImpl::ClearSslPreferences(JNIEnv* env, jobject obj) {
@@ -1594,29 +1580,103 @@ void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
return;
RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(
host_view->GetRenderWidgetHost());
+ BrowserAccessibilityState* accessibility_state =
+ BrowserAccessibilityState::GetInstance();
if (enabled) {
- BrowserAccessibilityState::GetInstance()->EnableAccessibility();
- if (host_impl)
+ // This enables accessibility globally unless it was explicitly disallowed
+ // by a command-line flag.
+ accessibility_state->OnScreenReaderDetected();
+ // If it was actually enabled globally, enable it for this RenderWidget now.
+ if (accessibility_state->IsAccessibleBrowser() && host_impl)
host_impl->SetAccessibilityMode(AccessibilityModeComplete);
} else {
- BrowserAccessibilityState::GetInstance()->DisableAccessibility();
+ accessibility_state->DisableAccessibility();
if (host_impl)
host_impl->SetAccessibilityMode(AccessibilityModeOff);
}
}
+void ContentViewCoreImpl::SendSingleTapUma(JNIEnv* env,
+ jobject obj,
+ jint type,
+ jint count) {
+ UMA_HISTOGRAM_ENUMERATION("Event.SingleTapType", type, count);
+}
+
+void ContentViewCoreImpl::SendActionAfterDoubleTapUma(JNIEnv* env,
+ jobject obj,
+ jint type,
+ jboolean has_delay,
+ jint count) {
+ // This UMA stat tracks a user's action after a double tap within
+ // k seconds (where k == 5 currently). This UMA will tell us if
+ // removing the tap gesture delay will lead to significantly more
+ // accidental navigations after a double tap.
+ if (has_delay) {
+ UMA_HISTOGRAM_ENUMERATION("Event.ActionAfterDoubleTapWithDelay", type,
+ count);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("Event.ActionAfterDoubleTapNoDelay", type,
+ count);
+ }
+}
+
+void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
+ RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
+ if (rwhv)
+ rwhv->UpdateScreenInfo(rwhv->GetNativeView());
+
+ RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
+ web_contents_->GetRenderViewHost());
+ rvhi->SendOrientationChangeEvent(device_orientation_);
+}
+
+void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
+ jobject obj,
+ jint x,
+ jint y,
+ jint width,
+ jint height) {
+ gfx::Rect rect(
+ static_cast<int>(x / GetDpiScale()),
+ static_cast<int>(y / GetDpiScale()),
+ static_cast<int>((width > 0 && width < GetDpiScale()) ?
+ 1 : (int)(width / GetDpiScale())),
+ static_cast<int>((height > 0 && height < GetDpiScale()) ?
+ 1 : (int)(height / GetDpiScale())));
+ GetWebContents()->Send(new ViewMsg_ExtractSmartClipData(
+ GetWebContents()->GetRoutingID(), rect));
+}
+
+void ContentViewCoreImpl::OnSmartClipDataExtracted(const string16& result) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return;
+ ScopedJavaLocalRef<jstring> jresult = ConvertUTF16ToJavaString(env, result);
+ Java_ContentViewCore_onSmartClipDataExtracted(
+ env, obj.obj(), jresult.obj());
+}
+
+void ContentViewCoreImpl::WebContentsDestroyed(WebContents* web_contents) {
+ WebContentsViewAndroid* wcva =
+ static_cast<WebContentsViewAndroid*>(web_contents->GetView());
+ DCHECK(wcva);
+ wcva->SetContentViewCore(NULL);
+}
+
// This is called for each ContentView.
-jint Init(JNIEnv* env, jobject obj,
- jboolean hardware_accelerated,
- jint native_web_contents,
- jint view_android,
- jint window_android) {
+jlong Init(JNIEnv* env, jobject obj,
+ jboolean hardware_accelerated,
+ jlong native_web_contents,
+ jlong view_android,
+ jlong window_android) {
ContentViewCoreImpl* view = new ContentViewCoreImpl(
env, obj, hardware_accelerated,
reinterpret_cast<WebContents*>(native_web_contents),
reinterpret_cast<ui::ViewAndroid*>(view_android),
reinterpret_cast<ui::WindowAndroid*>(window_android));
- return reinterpret_cast<jint>(view);
+ return reinterpret_cast<intptr_t>(view);
}
bool RegisterContentViewCore(JNIEnv* env) {
diff --git a/chromium/content/browser/android/content_view_core_impl.h b/chromium/content/browser/android/content_view_core_impl.h
index 765f63da983..5c61ae60b6d 100644
--- a/chromium/content/browser/android/content_view_core_impl.h
+++ b/chromium/content/browser/android/content_view_core_impl.h
@@ -19,6 +19,7 @@
#include "content/public/browser/android/content_view_core.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/web_contents_observer.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_f.h"
@@ -35,7 +36,8 @@ struct MenuItem;
// TODO(jrg): this is a shell. Upstream the rest.
class ContentViewCoreImpl : public ContentViewCore,
- public NotificationObserver {
+ public NotificationObserver,
+ public WebContentsObserver {
public:
static ContentViewCoreImpl* FromWebContents(WebContents* web_contents);
ContentViewCoreImpl(JNIEnv* env,
@@ -61,11 +63,15 @@ class ContentViewCoreImpl : public ContentViewCore,
virtual void RequestContentClipping(const gfx::Rect& clipping,
const gfx::Size& content_size) OVERRIDE;
virtual void PauseVideo() OVERRIDE;
+ virtual void PauseOrResumeGeolocation(bool should_pause) OVERRIDE;
// --------------------------------------------------------------------------
// Methods called from Java via JNI
// --------------------------------------------------------------------------
+ base::android::ScopedJavaLocalRef<jobject> GetWebContentsAndroid(JNIEnv* env,
+ jobject obj);
+
void OnJavaContentViewCoreDestroyed(JNIEnv* env, jobject obj);
// Notifies the ContentViewCore that items were selected in the currently
@@ -87,7 +93,6 @@ class ContentViewCoreImpl : public ContentViewCore,
base::android::ScopedJavaLocalRef<jstring> GetTitle(
JNIEnv* env, jobject obj) const;
jboolean IsIncognito(JNIEnv* env, jobject obj);
- jboolean Crashed(JNIEnv* env, jobject obj) const { return tab_crashed_; }
void SendOrientationChangeEvent(JNIEnv* env, jobject obj, jint orientation);
jboolean SendTouchEvent(JNIEnv* env,
jobject obj,
@@ -119,8 +124,10 @@ class ContentViewCoreImpl : public ContentViewCore,
jfloat x, jfloat y);
void ShowPressState(JNIEnv* env, jobject obj, jlong time_ms,
jfloat x, jfloat y);
- void ShowPressCancel(JNIEnv* env, jobject obj, jlong time_ms,
- jfloat x, jfloat y);
+ void TapCancel(JNIEnv* env, jobject obj, jlong time_ms,
+ jfloat x, jfloat y);
+ void TapDown(JNIEnv* env, jobject obj, jlong time_ms,
+ jfloat x, jfloat y);
void DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
jfloat x, jfloat y) ;
void LongPress(JNIEnv* env, jobject obj, jlong time_ms,
@@ -138,20 +145,13 @@ class ContentViewCoreImpl : public ContentViewCore,
jfloat x2, jfloat y2);
void MoveCaret(JNIEnv* env, jobject obj, jfloat x, jfloat y);
- jboolean CanGoBack(JNIEnv* env, jobject obj);
- jboolean CanGoForward(JNIEnv* env, jobject obj);
- jboolean CanGoToOffset(JNIEnv* env, jobject obj, jint offset);
- void GoBack(JNIEnv* env, jobject obj);
- void GoForward(JNIEnv* env, jobject obj);
- void GoToOffset(JNIEnv* env, jobject obj, jint offset);
- void GoToNavigationIndex(JNIEnv* env, jobject obj, jint index);
void LoadIfNecessary(JNIEnv* env, jobject obj);
void RequestRestoreLoad(JNIEnv* env, jobject obj);
void StopLoading(JNIEnv* env, jobject obj);
- void Reload(JNIEnv* env, jobject obj);
+ void Reload(JNIEnv* env, jobject obj, jboolean check_for_repost);
+ void ReloadIgnoringCache(JNIEnv* env, jobject obj, jboolean check_for_repost);
void CancelPendingReload(JNIEnv* env, jobject obj);
void ContinuePendingReload(JNIEnv* env, jobject obj);
- jboolean NeedsReload(JNIEnv* env, jobject obj);
void ClearHistory(JNIEnv* env, jobject obj);
void EvaluateJavaScript(JNIEnv* env,
jobject obj,
@@ -219,11 +219,25 @@ class ContentViewCoreImpl : public ContentViewCore,
jobject jsurface);
void DetachExternalVideoSurface(JNIEnv* env, jobject obj, jint player_id);
void SetAccessibilityEnabled(JNIEnv* env, jobject obj, bool enabled);
-
+ void SendActionAfterDoubleTapUma(JNIEnv* env,
+ jobject obj,
+ jint type,
+ jboolean has_delay,
+ jint count);
+ void SendSingleTapUma(JNIEnv* env, jobject obj, jint type, jint count);
+
+ void ExtractSmartClipData(JNIEnv* env,
+ jobject obj,
+ jint x,
+ jint y,
+ jint width,
+ jint height);
// --------------------------------------------------------------------------
// Public methods that call to Java via JNI
// --------------------------------------------------------------------------
+ void OnSmartClipDataExtracted(const string16& result);
+
// Creates a popup menu with |items|.
// |multiple| defines if it should support multi-select.
// If not |multiple|, |selected_item| sets the initially selected item.
@@ -248,14 +262,14 @@ class ContentViewCoreImpl : public ContentViewCore,
const std::string& text,
int selection_start, int selection_end,
int composition_start, int composition_end,
- bool show_ime_if_needed);
- void ProcessImeBatchStateAck(bool is_begin);
- void SetTitle(const string16& title);
+ bool show_ime_if_needed, bool require_ack);
+ void SetTitle(const base::string16& title);
void OnBackgroundColorChanged(SkColor color);
bool HasFocus();
void ConfirmTouchEvent(InputEventAckState ack_result);
void UnhandledFlingStartEvent();
+ void OnScrollUpdateGestureConsumed();
void HasTouchEventHandlers(bool need_touch_events);
void OnSelectionChanged(const std::string& text);
void OnSelectionBoundsChanged(
@@ -269,16 +283,9 @@ class ContentViewCoreImpl : public ContentViewCore,
void ShowDisambiguationPopup(
const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap);
- // Creates a java-side touch gesture, e.g. used by
- // chrome.gpuBenchmarking.smoothScrollBy.
- base::android::ScopedJavaLocalRef<jobject> CreateOnePointTouchGesture(
- int start_x, int start_y, int delta_x, int delta_y);
-
- // Creates a java-side touch gesture with two pointers, e.g. used by
- // chrome.gpuBenchmarking.pinchBy.
- base::android::ScopedJavaLocalRef<jobject> CreateTwoPointTouchGesture(
- int start_x0, int start_y0, int delta_x0, int delta_y0,
- int start_x1, int start_y1, int delta_x1, int delta_y1);
+ // Creates a java-side touch event, used for injecting touch event for
+ // testing/benchmarking purposes
+ base::android::ScopedJavaLocalRef<jobject> CreateTouchEventSynthesizer();
// Notifies the java object about the external surface, requesting for one if
// necessary.
@@ -291,6 +298,9 @@ class ContentViewCoreImpl : public ContentViewCore,
// typically be an Activity context for an on screen view.
base::android::ScopedJavaLocalRef<jobject> GetContext();
+ // Returns True if the given media should be blocked to load.
+ bool ShouldBlockMediaRequest(const GURL& url);
+
// --------------------------------------------------------------------------
// Methods called from native code
// --------------------------------------------------------------------------
@@ -302,7 +312,8 @@ class ContentViewCoreImpl : public ContentViewCore,
void AttachLayer(scoped_refptr<cc::Layer> layer);
void RemoveLayer(scoped_refptr<cc::Layer> layer);
- void SetNeedsBeginFrame(bool enabled);
+ void AddBeginFrameSubscriber();
+ void RemoveBeginFrameSubscriber();
void SetNeedsAnimate();
private:
@@ -316,6 +327,10 @@ class ContentViewCoreImpl : public ContentViewCore,
const NotificationSource& source,
const NotificationDetails& details) OVERRIDE;
+ // WebContentsObserver implementation.
+ virtual void RenderViewReady() OVERRIDE;
+ virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
+
// --------------------------------------------------------------------------
// Other private methods and data
// --------------------------------------------------------------------------
@@ -326,8 +341,8 @@ class ContentViewCoreImpl : public ContentViewCore,
float GetTouchPaddingDip();
- WebKit::WebGestureEvent MakeGestureEvent(
- WebKit::WebInputEvent::Type type, long time_ms, float x, float y) const;
+ blink::WebGestureEvent MakeGestureEvent(
+ blink::WebInputEvent::Type type, int64 time_ms, float x, float y) const;
void SendBeginFrame(base::TimeTicks frame_time);
@@ -336,15 +351,14 @@ class ContentViewCoreImpl : public ContentViewCore,
void DeleteScaledSnapshotTexture();
- void SendGestureEvent(const WebKit::WebGestureEvent& event);
-
- // Checks if there there is a corresponding renderer process and updates
- // |tab_crashed_| accordingly.
- void UpdateTabCrashedFlag();
+ void SendGestureEvent(const blink::WebGestureEvent& event);
// Update focus state of the RenderWidgetHostView.
void SetFocusInternal(bool focused);
+ // Send device_orientation_ to renderer.
+ void SendOrientationChangeEventInternal();
+
// A weak reference to the Java ContentViewCore object.
JavaObjectWeakGlobalRef java_ref_;
@@ -357,9 +371,6 @@ class ContentViewCoreImpl : public ContentViewCore,
// A compositor layer containing any layer that should be shown.
scoped_refptr<cc::Layer> root_layer_;
- // Whether the renderer backing this ContentViewCore has crashed.
- bool tab_crashed_;
-
// Device scale factor.
float dpi_scale_;
@@ -374,6 +385,12 @@ class ContentViewCoreImpl : public ContentViewCore,
// The owning window that has a hold of main application activity.
ui::WindowAndroid* window_android_;
+ // The cache of device's current orientation set from Java side, this value
+ // will be sent to Renderer once it is ready.
+ int device_orientation_;
+
+ bool geolocation_needs_pause_;
+
DISALLOW_COPY_AND_ASSIGN(ContentViewCoreImpl);
};
diff --git a/chromium/content/browser/android/content_view_render_view.cc b/chromium/content/browser/android/content_view_render_view.cc
index 4faa4df97aa..639deae5ca6 100644
--- a/chromium/content/browser/android/content_view_render_view.cc
+++ b/chromium/content/browser/android/content_view_render_view.cc
@@ -16,8 +16,10 @@
#include "content/public/browser/android/compositor.h"
#include "content/public/browser/android/content_view_layer_renderer.h"
#include "jni/ContentViewRenderView_jni.h"
+#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/size.h"
+#include <android/bitmap.h>
#include <android/native_window_jni.h>
using base::android::ScopedJavaLocalRef;
@@ -29,8 +31,11 @@ bool ContentViewRenderView::RegisterContentViewRenderView(JNIEnv* env) {
return RegisterNativesImpl(env);
}
-ContentViewRenderView::ContentViewRenderView(JNIEnv* env, jobject obj)
- : buffers_swapped_during_composite_(false) {
+ContentViewRenderView::ContentViewRenderView(JNIEnv* env,
+ jobject obj,
+ gfx::NativeWindow root_window)
+ : buffers_swapped_during_composite_(false),
+ root_window_(root_window) {
java_obj_.Reset(env, obj);
}
@@ -38,10 +43,12 @@ ContentViewRenderView::~ContentViewRenderView() {
}
// static
-static jint Init(JNIEnv* env, jobject obj) {
+static jlong Init(JNIEnv* env, jobject obj, jlong native_root_window) {
+ gfx::NativeWindow root_window =
+ reinterpret_cast<gfx::NativeWindow>(native_root_window);
ContentViewRenderView* content_view_render_view =
- new ContentViewRenderView(env, obj);
- return reinterpret_cast<jint>(content_view_render_view);
+ new ContentViewRenderView(env, obj, root_window);
+ return reinterpret_cast<intptr_t>(content_view_render_view);
}
void ContentViewRenderView::Destroy(JNIEnv* env, jobject obj) {
@@ -83,6 +90,15 @@ jboolean ContentViewRenderView::Composite(JNIEnv* env, jobject obj) {
return buffers_swapped_during_composite_;
}
+jboolean ContentViewRenderView::CompositeToBitmap(JNIEnv* env, jobject obj,
+ jobject java_bitmap) {
+ gfx::JavaBitmap bitmap(java_bitmap);
+ if (!compositor_ || bitmap.format() != ANDROID_BITMAP_FORMAT_RGBA_8888)
+ return false;
+ return compositor_->CompositeAndReadback(bitmap.pixels(),
+ gfx::Rect(bitmap.size()));
+}
+
void ContentViewRenderView::ScheduleComposite() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_ContentViewRenderView_requestRender(env, java_obj_.obj());
@@ -99,7 +115,7 @@ void ContentViewRenderView::OnSwapBuffersCompleted() {
void ContentViewRenderView::InitCompositor() {
if (!compositor_)
- compositor_.reset(Compositor::Create(this));
+ compositor_.reset(Compositor::Create(this, root_window_));
}
} // namespace content
diff --git a/chromium/content/browser/android/content_view_render_view.h b/chromium/content/browser/android/content_view_render_view.h
index 714f02f7d32..1bd3899ac3c 100644
--- a/chromium/content/browser/android/content_view_render_view.h
+++ b/chromium/content/browser/android/content_view_render_view.h
@@ -10,6 +10,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/android/compositor_client.h"
+#include "ui/gfx/native_widget_types.h"
namespace content {
class Compositor;
@@ -19,7 +20,9 @@ class ContentViewRenderView : public CompositorClient {
// Registers the JNI methods for ContentViewRender.
static bool RegisterContentViewRenderView(JNIEnv* env);
- ContentViewRenderView(JNIEnv* env, jobject obj);
+ ContentViewRenderView(JNIEnv* env,
+ jobject obj,
+ gfx::NativeWindow root_window);
// Methods called from Java via JNI -----------------------------------------
void Destroy(JNIEnv* env, jobject obj);
@@ -28,6 +31,7 @@ class ContentViewRenderView : public CompositorClient {
void SurfaceDestroyed(JNIEnv* env, jobject obj);
void SurfaceSetSize(JNIEnv* env, jobject obj, jint width, jint height);
jboolean Composite(JNIEnv* env, jobject obj);
+ jboolean CompositeToBitmap(JNIEnv* env, jobject obj, jobject java_bitmap);
// CompositorClient ---------------------------------------------------------
virtual void ScheduleComposite() OVERRIDE;
@@ -45,6 +49,8 @@ class ContentViewRenderView : public CompositorClient {
scoped_ptr<content::Compositor> compositor_;
+ gfx::NativeWindow root_window_;
+
DISALLOW_COPY_AND_ASSIGN(ContentViewRenderView);
};
diff --git a/chromium/content/browser/android/content_view_statics.cc b/chromium/content/browser/android/content_view_statics.cc
index 66af8652d49..e176564c4a0 100644
--- a/chromium/content/browser/android/content_view_statics.cc
+++ b/chromium/content/browser/android/content_view_statics.cc
@@ -24,7 +24,7 @@ namespace {
// TODO(pliard): http://crbug.com/235909. Move WebKit shared timer toggling
// functionality out of ContentViewStatistics and not be build on top of
-// WebKit::Platform::SuspendSharedTimer.
+// blink::Platform::SuspendSharedTimer.
// TODO(pliard): http://crbug.com/235912. Add unit tests for WebKit shared timer
// toggling.
@@ -62,8 +62,8 @@ void ResumeWebkitSharedTimers(const std::vector<int>& suspended_processes) {
// Returns the first substring consisting of the address of a physical location.
static jstring FindAddress(JNIEnv* env, jclass clazz, jstring addr) {
- string16 content_16 = ConvertJavaStringToUTF16(env, addr);
- string16 result_16;
+ base::string16 content_16 = ConvertJavaStringToUTF16(env, addr);
+ base::string16 result_16;
if (content::address_parser::FindAddress(content_16, &result_16))
return ConvertUTF16ToJavaString(env, result_16).Release();
return NULL;
diff --git a/chromium/content/browser/android/date_time_chooser_android.cc b/chromium/content/browser/android/date_time_chooser_android.cc
index 7c91ff0977d..f6b50c9da4b 100644
--- a/chromium/content/browser/android/date_time_chooser_android.cc
+++ b/chromium/content/browser/android/date_time_chooser_android.cc
@@ -4,74 +4,46 @@
#include "content/browser/android/date_time_chooser_android.h"
+#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
+#include "base/i18n/char_iterator.h"
+#include "content/common/date_time_suggestion.h"
#include "content/common/view_messages.h"
#include "content/public/browser/android/content_view_core.h"
-#include "content/public/browser/render_view_host_observer.h"
+#include "content/public/browser/render_view_host.h"
#include "jni/DateTimeChooserAndroid_jni.h"
+#include "third_party/icu/source/common/unicode/uchar.h"
+#include "third_party/icu/source/common/unicode/unistr.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertUTF8ToJavaString;
-
-
-namespace content {
-
-// Updates date/time via IPC to the RenderView
-class DateTimeChooserAndroid::DateTimeIPCSender :
- public RenderViewHostObserver {
- public:
- explicit DateTimeIPCSender(RenderViewHost* sender);
- virtual ~DateTimeIPCSender() {}
- void ReplaceDateTime(int dialog_type,
- int year,
- int month,
- int day,
- int hour,
- int minute,
- int second,
- int milli,
- int week);
- void CancelDialog();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DateTimeIPCSender);
-};
-
-DateTimeChooserAndroid::DateTimeIPCSender::DateTimeIPCSender(
- RenderViewHost* sender)
- : RenderViewHostObserver(sender) {
+using base::android::ConvertUTF16ToJavaString;
+
+
+namespace {
+
+string16 SanitizeSuggestionString(const string16& string) {
+ string16 trimmed = string.substr(0, 255);
+ icu::UnicodeString sanitized;
+ base::i18n::UTF16CharIterator sanitized_iterator(&trimmed);
+ while (!sanitized_iterator.end()) {
+ UChar c = sanitized_iterator.get();
+ if (u_isprint(c))
+ sanitized.append(c);
+ sanitized_iterator.Advance();
+ }
+ return string16(sanitized.getBuffer(),
+ static_cast<size_t>(sanitized.length()));
}
-void DateTimeChooserAndroid::DateTimeIPCSender::ReplaceDateTime(int dialog_type,
- int year,
- int month,
- int day,
- int hour,
- int minute,
- int second,
- int milli,
- int week) {
- ViewHostMsg_DateTimeDialogValue_Params value;
- value.year = year;
- value.month = month;
- value.day = day;
- value.hour = hour;
- value.minute = minute;
- value.second = second;
- value.milli = milli;
- value.week = week;
- value.dialog_type = dialog_type;
- Send(new ViewMsg_ReplaceDateTime(routing_id(), value));
-}
+} // namespace
-void DateTimeChooserAndroid::DateTimeIPCSender::CancelDialog() {
- Send(new ViewMsg_CancelDateTimeDialog(routing_id()));
-}
+namespace content {
// DateTimeChooserAndroid implementation
DateTimeChooserAndroid::DateTimeChooserAndroid()
- : sender_(NULL) {
+ : host_(NULL) {
}
DateTimeChooserAndroid::~DateTimeChooserAndroid() {
@@ -92,58 +64,54 @@ void DateTimeChooserAndroid::InitializeDateInputTypes(
void DateTimeChooserAndroid::ReplaceDateTime(JNIEnv* env,
jobject,
- int dialog_type,
- int year,
- int month,
- int day,
- int hour,
- int minute,
- int second,
- int milli,
- int week) {
- sender_->ReplaceDateTime(
- dialog_type, year, month, day, hour, minute, second, milli, week);
+ jdouble value) {
+ host_->Send(new ViewMsg_ReplaceDateTime(host_->GetRoutingID(), value));
}
void DateTimeChooserAndroid::CancelDialog(JNIEnv* env, jobject) {
- sender_->CancelDialog();
+ host_->Send(new ViewMsg_CancelDateTimeDialog(host_->GetRoutingID()));
}
-void DateTimeChooserAndroid::ShowDialog(ContentViewCore* content,
- RenderViewHost* sender,
- int type,
- int year,
- int month,
- int day,
- int hour,
- int minute,
- int second,
- int milli,
- int week,
- double min,
- double max,
- double step) {
- if (sender_)
- delete sender_;
- sender_ = new DateTimeIPCSender(sender);
+void DateTimeChooserAndroid::ShowDialog(
+ ContentViewCore* content,
+ RenderViewHost* host,
+ ui::TextInputType dialog_type,
+ double dialog_value,
+ double min,
+ double max,
+ double step,
+ const std::vector<DateTimeSuggestion>& suggestions) {
+ host_ = host;
JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobjectArray> suggestions_array;
+
+ if (suggestions.size() > 0) {
+ suggestions_array =
+ Java_DateTimeChooserAndroid_createSuggestionsArray(env,
+ suggestions.size());
+ for (size_t i = 0; i < suggestions.size(); ++i) {
+ const content::DateTimeSuggestion& suggestion = suggestions[i];
+ ScopedJavaLocalRef<jstring> localized_value = ConvertUTF16ToJavaString(
+ env, SanitizeSuggestionString(suggestion.localized_value));
+ ScopedJavaLocalRef<jstring> label = ConvertUTF16ToJavaString(
+ env, SanitizeSuggestionString(suggestion.label));
+ Java_DateTimeChooserAndroid_setDateTimeSuggestionAt(env,
+ suggestions_array.obj(), i,
+ suggestion.value, localized_value.obj(), label.obj());
+ }
+ }
+
j_date_time_chooser_.Reset(Java_DateTimeChooserAndroid_createDateTimeChooser(
env,
content->GetJavaObject().obj(),
reinterpret_cast<intptr_t>(this),
- type,
- year,
- month,
- day,
- hour,
- minute,
- second,
- milli,
- week,
+ dialog_type,
+ dialog_value,
min,
max,
- step));
+ step,
+ suggestions_array.obj()));
}
// ----------------------------------------------------------------------------
diff --git a/chromium/content/browser/android/date_time_chooser_android.h b/chromium/content/browser/android/date_time_chooser_android.h
index 68cb4560172..c02ecf56fe2 100644
--- a/chromium/content/browser/android/date_time_chooser_android.h
+++ b/chromium/content/browser/android/date_time_chooser_android.h
@@ -6,14 +6,17 @@
#define CONTENT_BROWSER_ANDROID_DATE_TIME_CHOOSER_ANDROID_H_
#include <string>
+#include <vector>
#include "base/android/jni_helper.h"
#include "base/memory/scoped_ptr.h"
+#include "ui/base/ime/text_input_type.h"
namespace content {
class ContentViewCore;
class RenderViewHost;
+struct DateTimeSuggestion;
// Android implementation for DateTimeChooser dialogs.
class DateTimeChooserAndroid {
@@ -22,33 +25,19 @@ class DateTimeChooserAndroid {
~DateTimeChooserAndroid();
// DateTimeChooser implementation:
+ // Shows the dialog. |dialog_value| is the date/time value converted to a
+ // number as defined in HTML. (See blink::InputType::parseToNumber())
void ShowDialog(ContentViewCore* content,
- RenderViewHost* sender,
- int type,
- int year,
- int month,
- int day,
- int hour,
- int minute,
- int second,
- int milli,
- int week,
+ RenderViewHost* host,
+ ui::TextInputType dialog_type,
+ double dialog_value,
double min,
double max,
- double step);
-
- // Replaces the current value with the one passed the different fields
- void ReplaceDateTime(JNIEnv* env,
- jobject,
- jint dialog_type,
- jint year,
- jint month,
- jint day,
- jint hour,
- jint minute,
- jint second,
- jint milli,
- jint week);
+ double step,
+ const std::vector<DateTimeSuggestion>& suggestions);
+
+ // Replaces the current value
+ void ReplaceDateTime(JNIEnv* env, jobject, jdouble value);
// Closes the dialog without propagating any changes.
void CancelDialog(JNIEnv* env, jobject);
@@ -61,11 +50,7 @@ class DateTimeChooserAndroid {
int text_input_type_time, int text_input_type_week);
private:
- class DateTimeIPCSender;
-
- // The DateTimeIPCSender class is a render view observer, so it will take care
- // of its own deletion.
- DateTimeIPCSender* sender_;
+ RenderViewHost* host_;
base::android::ScopedJavaGlobalRef<jobject> j_date_time_chooser_;
diff --git a/chromium/content/browser/android/download_controller_android_impl.cc b/chromium/content/browser/android/download_controller_android_impl.cc
index 7d27e64a193..f3a274a3ef4 100644
--- a/chromium/content/browser/android/download_controller_android_impl.cc
+++ b/chromium/content/browser/android/download_controller_android_impl.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
#include "content/browser/android/content_view_core_impl.h"
#include "content/browser/download/download_item_impl.h"
#include "content/browser/download/download_manager_impl.h"
@@ -254,18 +255,9 @@ void DownloadControllerAndroidImpl::OnDownloadStarted(
void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (item->IsDangerous() &&
- (item->GetState() != DownloadItem::CANCELLED))
+ if (item->IsDangerous() && (item->GetState() != DownloadItem::CANCELLED))
OnDangerousDownload(item);
- if (item->GetState() != DownloadItem::COMPLETE)
- return;
-
- // Multiple OnDownloadUpdated() notifications may be issued while the download
- // is in the COMPLETE state. Only handle one.
- item->RemoveObserver(this);
-
- // Call onDownloadCompleted
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> jurl =
ConvertUTF8ToJavaString(env, item->GetURL().spec());
@@ -276,10 +268,44 @@ void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString(
env, item->GetTargetFilePath().BaseName().value());
- Java_DownloadController_onDownloadCompleted(
- env, GetJavaObject()->Controller(env).obj(),
- base::android::GetApplicationContext(), jurl.obj(), jmime_type.obj(),
- jfilename.obj(), jpath.obj(), item->GetReceivedBytes(), true);
+ switch (item->GetState()) {
+ case DownloadItem::IN_PROGRESS: {
+ base::TimeDelta time_delta;
+ item->TimeRemaining(&time_delta);
+ Java_DownloadController_onDownloadUpdated(
+ env, GetJavaObject()->Controller(env).obj(),
+ base::android::GetApplicationContext(), jurl.obj(), jmime_type.obj(),
+ jfilename.obj(), jpath.obj(), item->GetReceivedBytes(), true,
+ item->GetId(), item->PercentComplete(), time_delta.InMilliseconds());
+ 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(),
+ base::android::GetApplicationContext(), jurl.obj(), jmime_type.obj(),
+ jfilename.obj(), jpath.obj(), item->GetReceivedBytes(), true,
+ item->GetId());
+ break;
+ case DownloadItem::CANCELLED:
+ // TODO(shashishekhar): An interrupted download can be resumed. Android
+ // currently does not support resumable downloads. Add handling for
+ // interrupted case based on item->CanResume().
+ case DownloadItem::INTERRUPTED:
+ // Call onDownloadCompleted with success = false.
+ Java_DownloadController_onDownloadCompleted(
+ env, GetJavaObject()->Controller(env).obj(),
+ base::android::GetApplicationContext(), jurl.obj(), jmime_type.obj(),
+ jfilename.obj(), jpath.obj(), item->GetReceivedBytes(), false,
+ item->GetId());
+ break;
+ case DownloadItem::MAX_DOWNLOAD_STATE:
+ NOTREACHED();
+ }
}
void DownloadControllerAndroidImpl::OnDangerousDownload(DownloadItem* item) {
diff --git a/chromium/content/browser/android/edge_effect.cc b/chromium/content/browser/android/edge_effect.cc
index d8411bc1f89..41fa1a171e1 100644
--- a/chromium/content/browser/android/edge_effect.cc
+++ b/chromium/content/browser/android/edge_effect.cc
@@ -36,8 +36,9 @@ const float kMaxGlowHeight = 4.f;
const float kPullGlowBegin = 1.f;
const float kPullEdgeBegin = 0.6f;
-// Minimum velocity that will be absorbed
+// Min/max velocity that will be absorbed
const float kMinVelocity = 100.f;
+const float kMaxVelocity = 10000.f;
const float kEpsilon = 0.001f;
@@ -51,7 +52,7 @@ const int kPullDistanceGlowFactor = 7;
const float kPullDistanceAlphaGlowFactor = 1.1f;
const int kVelocityEdgeFactor = 8;
-const int kVelocityGlowFactor = 16;
+const int kVelocityGlowFactor = 12;
template <typename T>
T Lerp(T a, T b, T t) {
@@ -220,11 +221,11 @@ void EdgeEffect::Release(base::TimeTicks current_time) {
void EdgeEffect::Absorb(base::TimeTicks current_time, float velocity) {
state_ = STATE_ABSORB;
float scaled_velocity =
- dpi_scale_ * std::max(kMinVelocity, std::abs(velocity));
+ dpi_scale_ * Clamp(std::abs(velocity), kMinVelocity, kMaxVelocity);
start_time_ = current_time;
// This should never be less than 1 millisecond.
- duration_ = base::TimeDelta::FromMilliseconds(0.1f + (velocity * 0.03f));
+ duration_ = base::TimeDelta::FromMilliseconds(0.15f + (velocity * 0.02f));
// The edge should always be at least partially visible, regardless
// of velocity.
@@ -232,7 +233,7 @@ void EdgeEffect::Absorb(base::TimeTicks current_time, float velocity) {
edge_scale_y_ = edge_scale_y_start_ = 0.f;
// The glow depends more on the velocity, and therefore starts out
// nearly invisible.
- glow_alpha_start_ = 0.5f;
+ glow_alpha_start_ = 0.3f;
glow_scale_y_start_ = 0.f;
// Factor the velocity by 8. Testing on device shows this works best to
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc b/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc
index b04e85456f1..230b1e92dc6 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc
@@ -59,7 +59,7 @@ class VideoContextProvider
return gl_in_process_context_->GetSurfaceTexture(stream_id);
}
- virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
+ virtual blink::WebGraphicsContext3D* Context3d() OVERRIDE {
return context_provider_->Context3d();
}
@@ -109,7 +109,7 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
- WebKit::WebGraphicsContext3D::Attributes attributes;
+ blink::WebGraphicsContext3D::Attributes attributes;
attributes.antialias = false;
attributes.shareResources = true;
attributes.noAutomaticFlushes = true;
@@ -178,15 +178,13 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
virtual scoped_ptr<StreamTextureFactory> CreateStreamTextureFactory(
int view_id) OVERRIDE {
- scoped_refptr<VideoContextProvider> context_provider;
- if (CanCreateMainThreadContext()) {
- context_provider =
- new VideoContextProvider(offscreen_context_for_main_thread_,
- wrapped_gl_context_for_main_thread_);
- }
- return make_scoped_ptr(new StreamTextureFactorySynchronousImpl(
- context_provider.get(), view_id))
- .PassAs<StreamTextureFactory>();
+ scoped_ptr<StreamTextureFactorySynchronousImpl> factory(
+ new StreamTextureFactorySynchronousImpl(
+ base::Bind(&SynchronousCompositorFactoryImpl::
+ TryCreateStreamTextureFactory,
+ base::Unretained(this)),
+ view_id));
+ return factory.PassAs<StreamTextureFactory>();
}
void CompositorInitializedHardwareDraw(SynchronousCompositorImpl* compositor);
@@ -195,6 +193,8 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
private:
void ReleaseGlobalHardwareResources();
bool CanCreateMainThreadContext();
+ scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
+ TryCreateStreamTextureFactory();
SynchronousInputEventFilter synchronous_input_event_filter_;
@@ -247,6 +247,21 @@ bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
return num_hardware_compositors_ > 0;
}
+scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
+SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
+ scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
+ context_provider;
+ if (CanCreateMainThreadContext() &&
+ GetOffscreenContextProviderForMainThread()) {
+ DCHECK(offscreen_context_for_main_thread_);
+ DCHECK(wrapped_gl_context_for_main_thread_);
+ context_provider =
+ new VideoContextProvider(offscreen_context_for_main_thread_,
+ wrapped_gl_context_for_main_thread_);
+ }
+ return context_provider;
+}
+
base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory =
LAZY_INSTANCE_INITIALIZER;
@@ -396,7 +411,7 @@ void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable) {
}
InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
- const WebKit::WebInputEvent& input_event) {
+ const blink::WebInputEvent& input_event) {
DCHECK(CalledOnValidThread());
return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent(
contents_->GetRoutingID(), input_event);
@@ -415,6 +430,13 @@ void SynchronousCompositorImpl::DidActivatePendingTree() {
compositor_client_->DidUpdateContent();
}
+void SynchronousCompositorImpl::SetMaxScrollOffset(
+ gfx::Vector2dF max_scroll_offset) {
+ DCHECK(CalledOnValidThread());
+ if (compositor_client_)
+ compositor_client_->SetMaxRootLayerScrollOffset(max_scroll_offset);
+}
+
void SynchronousCompositorImpl::SetTotalScrollOffset(gfx::Vector2dF new_value) {
DCHECK(CalledOnValidThread());
if (compositor_client_)
@@ -428,6 +450,26 @@ gfx::Vector2dF SynchronousCompositorImpl::GetTotalScrollOffset() {
return gfx::Vector2dF();
}
+bool SynchronousCompositorImpl::IsExternalFlingActive() const {
+ DCHECK(CalledOnValidThread());
+ if (compositor_client_)
+ return compositor_client_->IsExternalFlingActive();
+ return false;
+}
+
+void SynchronousCompositorImpl::SetTotalPageScaleFactor(
+ float page_scale_factor) {
+ DCHECK(CalledOnValidThread());
+ if (compositor_client_)
+ compositor_client_->SetRootLayerPageScaleFactor(page_scale_factor);
+}
+
+void SynchronousCompositorImpl::SetScrollableSize(gfx::SizeF scrollable_size) {
+ DCHECK(CalledOnValidThread());
+ if (compositor_client_)
+ compositor_client_->SetRootLayerScrollableSize(scrollable_size);
+}
+
// Not using base::NonThreadSafe as we want to enforce a more exacting threading
// requirement: SynchronousCompositorImpl() must only be used on the UI thread.
bool SynchronousCompositorImpl::CalledOnValidThread() const {
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_impl.h b/chromium/content/browser/android/in_process/synchronous_compositor_impl.h
index 3189dcc983a..f23d920a555 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_impl.h
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_impl.h
@@ -19,7 +19,7 @@ class InputHandler;
struct DidOverscrollParams;
}
-namespace WebKit {
+namespace blink {
class WebInputEvent;
}
@@ -43,7 +43,7 @@ class SynchronousCompositorImpl
// is implicitly that of the in-process renderer.
static SynchronousCompositorImpl* FromRoutingID(int routing_id);
- InputEventAckState HandleInputEvent(const WebKit::WebInputEvent& input_event);
+ InputEventAckState HandleInputEvent(const blink::WebInputEvent& input_event);
// SynchronousCompositor
virtual void SetClient(SynchronousCompositorClient* compositor_client)
@@ -73,8 +73,12 @@ class SynchronousCompositorImpl
virtual void DidActivatePendingTree() OVERRIDE;
// LayerScrollOffsetDelegate
+ virtual void SetMaxScrollOffset(gfx::Vector2dF max_scroll_offset) OVERRIDE;
virtual void SetTotalScrollOffset(gfx::Vector2dF new_value) OVERRIDE;
virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE;
+ virtual bool IsExternalFlingActive() const OVERRIDE;
+ virtual void SetTotalPageScaleFactor(float page_scale_factor) OVERRIDE;
+ virtual void SetScrollableSize(gfx::SizeF scrollable_size) OVERRIDE;
void SetInputHandler(cc::InputHandler* input_handler);
void DidOverscroll(const cc::DidOverscrollParams& params);
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.cc b/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.cc
index 28119a20329..2d37659723c 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.cc
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.cc
@@ -14,6 +14,7 @@
#include "content/browser/android/in_process/synchronous_compositor_impl.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/command_buffer/client/gl_in_process_context.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "third_party/skia/include/core/SkBitmapDevice.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/rect_conversions.h"
@@ -35,7 +36,7 @@ CreateWebGraphicsContext3D(scoped_refptr<gfx::GLSurface> surface) {
const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
- WebKit::WebGraphicsContext3D::Attributes attributes;
+ blink::WebGraphicsContext3D::Attributes attributes;
attributes.antialias = false;
attributes.shareResources = true;
attributes.noAutomaticFlushes = true;
@@ -104,7 +105,7 @@ SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
: cc::OutputSurface(
scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareDevice(this))),
routing_id_(routing_id),
- needs_begin_frame_(false),
+ needs_begin_impl_frame_(false),
invoking_composite_(false),
did_swap_buffer_(false),
current_sw_canvas_(NULL),
@@ -115,6 +116,9 @@ SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
capabilities_.adjust_deadline_for_parent = false;
// Cannot call out to GetDelegate() here as the output surface is not
// constructed on the correct thread.
+
+ memory_policy_.priority_cutoff_when_visible =
+ gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
}
SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {
@@ -155,14 +159,14 @@ void SynchronousCompositorOutputSurface::Reshape(
// Intentional no-op: surface size is controlled by the embedder.
}
-void SynchronousCompositorOutputSurface::SetNeedsBeginFrame(
+void SynchronousCompositorOutputSurface::SetNeedsBeginImplFrame(
bool enable) {
DCHECK(CalledOnValidThread());
- cc::OutputSurface::SetNeedsBeginFrame(enable);
- needs_begin_frame_ = enable;
+ cc::OutputSurface::SetNeedsBeginImplFrame(enable);
+ needs_begin_impl_frame_ = enable;
SynchronousCompositorOutputSurfaceDelegate* delegate = GetDelegate();
if (delegate)
- delegate->SetContinuousInvalidate(needs_begin_frame_);
+ delegate->SetContinuousInvalidate(needs_begin_impl_frame_);
}
void SynchronousCompositorOutputSurface::SwapBuffers(
@@ -261,8 +265,8 @@ void SynchronousCompositorOutputSurface::InvokeComposite(
adjusted_transform, viewport, clip, valid_for_tile_management);
SetNeedsRedrawRect(gfx::Rect(viewport.size()));
- if (needs_begin_frame_)
- BeginFrame(cc::BeginFrameArgs::CreateForSynchronousCompositor());
+ if (needs_begin_impl_frame_)
+ BeginImplFrame(cc::BeginFrameArgs::CreateForSynchronousCompositor());
// After software draws (which might move the viewport arbitrarily), restore
// the previous hardware viewport to allow CC's tile manager to prioritize
@@ -280,8 +284,9 @@ void SynchronousCompositorOutputSurface::InvokeComposite(
OnSwapBuffersComplete();
}
-void SynchronousCompositorOutputSurface::PostCheckForRetroactiveBeginFrame() {
- // Synchronous compositor cannot perform retroactive begin frames, so
+void
+SynchronousCompositorOutputSurface::PostCheckForRetroactiveBeginImplFrame() {
+ // Synchronous compositor cannot perform retroactive BeginImplFrames, so
// intentionally no-op here.
}
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.h b/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.h
index b9b4d678c09..2879de00c04 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.h
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.h
@@ -59,7 +59,7 @@ class SynchronousCompositorOutputSurface
virtual bool ForcedDrawToSoftwareDevice() const OVERRIDE;
virtual bool BindToClient(cc::OutputSurfaceClient* surface_client) OVERRIDE;
virtual void Reshape(gfx::Size size, float scale_factor) OVERRIDE;
- virtual void SetNeedsBeginFrame(bool enable) OVERRIDE;
+ virtual void SetNeedsBeginImplFrame(bool enable) OVERRIDE;
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
// Partial SynchronousCompositor API implementation.
@@ -80,7 +80,7 @@ class SynchronousCompositorOutputSurface
friend class SoftwareDevice;
// Private OutputSurface overrides.
- virtual void PostCheckForRetroactiveBeginFrame() OVERRIDE;
+ virtual void PostCheckForRetroactiveBeginImplFrame() OVERRIDE;
void InvokeComposite(const gfx::Transform& transform,
gfx::Rect viewport,
@@ -90,7 +90,7 @@ class SynchronousCompositorOutputSurface
SynchronousCompositorOutputSurfaceDelegate* GetDelegate();
int routing_id_;
- bool needs_begin_frame_;
+ bool needs_begin_impl_frame_;
bool invoking_composite_;
bool did_swap_buffer_;
diff --git a/chromium/content/browser/android/in_process/synchronous_input_event_filter.cc b/chromium/content/browser/android/in_process/synchronous_input_event_filter.cc
index 34144dac579..b8ba0ea3352 100644
--- a/chromium/content/browser/android/in_process/synchronous_input_event_filter.cc
+++ b/chromium/content/browser/android/in_process/synchronous_input_event_filter.cc
@@ -10,7 +10,7 @@
#include "content/public/browser/browser_thread.h"
#include "ui/events/latency_info.h"
-using WebKit::WebInputEvent;
+using blink::WebInputEvent;
namespace content {
@@ -22,14 +22,14 @@ SynchronousInputEventFilter::~SynchronousInputEventFilter() {
InputEventAckState SynchronousInputEventFilter::HandleInputEvent(
int routing_id,
- const WebKit::WebInputEvent& input_event) {
+ const blink::WebInputEvent& input_event) {
// The handler will be empty both before renderer initialization and after
// renderer destruction. It's possible that this will be reached in such a
// state. While not good, it should also not be fatal.
if (handler_.is_null())
return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
-
- return handler_.Run(routing_id, &input_event, ui::LatencyInfo());
+ ui::LatencyInfo latency;
+ return handler_.Run(routing_id, &input_event, &latency);
}
void SynchronousInputEventFilter::SetBoundHandler(const Handler& handler) {
diff --git a/chromium/content/browser/android/in_process/synchronous_input_event_filter.h b/chromium/content/browser/android/in_process/synchronous_input_event_filter.h
index 18601c222ae..a6fa68fcfda 100644
--- a/chromium/content/browser/android/in_process/synchronous_input_event_filter.h
+++ b/chromium/content/browser/android/in_process/synchronous_input_event_filter.h
@@ -9,10 +9,10 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "content/port/common/input_event_ack_state.h"
-#include "content/renderer/gpu/input_handler_manager_client.h"
+#include "content/renderer/input/input_handler_manager_client.h"
#include "ui/gfx/vector2d_f.h"
-namespace WebKit {
+namespace blink {
class WebInputEvent;
}
@@ -29,7 +29,7 @@ class SynchronousInputEventFilter : public InputHandlerManagerClient {
virtual ~SynchronousInputEventFilter();
InputEventAckState HandleInputEvent(int routing_id,
- const WebKit::WebInputEvent& input_event);
+ const blink::WebInputEvent& input_event);
// InputHandlerManagerClient implementation.
virtual void SetBoundHandler(const Handler& handler) OVERRIDE;
diff --git a/chromium/content/browser/android/interstitial_page_delegate_android.cc b/chromium/content/browser/android/interstitial_page_delegate_android.cc
index 4ed48907bed..f598cd36a5c 100644
--- a/chromium/content/browser/android/interstitial_page_delegate_android.cc
+++ b/chromium/content/browser/android/interstitial_page_delegate_android.cc
@@ -84,11 +84,11 @@ bool InterstitialPageDelegateAndroid
return RegisterNativesImpl(env);
}
-static jint Init(JNIEnv* env, jobject obj, jstring html_content) {
+static jlong Init(JNIEnv* env, jobject obj, jstring html_content) {
InterstitialPageDelegateAndroid* delegate =
new InterstitialPageDelegateAndroid(
env, obj, base::android::ConvertJavaStringToUTF8(env, html_content));
- return reinterpret_cast<jint>(delegate);
+ return reinterpret_cast<intptr_t>(delegate);
}
} // namespace content
diff --git a/chromium/content/browser/android/overscroll_glow.cc b/chromium/content/browser/android/overscroll_glow.cc
index 6adf7dbec48..8e08de45eca 100644
--- a/chromium/content/browser/android/overscroll_glow.cc
+++ b/chromium/content/browser/android/overscroll_glow.cc
@@ -6,6 +6,7 @@
#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
+#include "base/threading/worker_pool.h"
#include "cc/layers/image_layer.h"
#include "content/browser/android/edge_effect.h"
#include "ui/gfx/android/java_bitmap.h"
@@ -63,54 +64,61 @@ gfx::Vector2dF ZeroSmallComponents(gfx::Vector2dF vector) {
return vector;
}
+// Force loading of any necessary resources. This function is thread-safe.
+void EnsureResources() {
+ g_overscroll_resources.Get();
+}
+
} // namespace
-scoped_ptr<OverscrollGlow> OverscrollGlow::Create(bool enabled,
- gfx::SizeF size) {
- const SkBitmap& edge = g_overscroll_resources.Get().edge_bitmap();
- const SkBitmap& glow = g_overscroll_resources.Get().glow_bitmap();
- if (edge.isNull() || glow.isNull())
- return scoped_ptr<OverscrollGlow>();
+scoped_ptr<OverscrollGlow> OverscrollGlow::Create(bool enabled) {
+ // Don't block the main thread with effect resource loading during creation.
+ // Effect instantiation is deferred until the effect overscrolls, in which
+ // case the main thread may block until the resource has loaded.
+ if (enabled && g_overscroll_resources == NULL)
+ base::WorkerPool::PostTask(FROM_HERE, base::Bind(EnsureResources), true);
- return make_scoped_ptr(new OverscrollGlow(enabled, size, edge, glow));
+ return make_scoped_ptr(new OverscrollGlow(enabled));
}
-void OverscrollGlow::EnsureResources() {
- g_overscroll_resources.Get();
-}
-
-OverscrollGlow::OverscrollGlow(bool enabled,
- gfx::SizeF size,
- const SkBitmap& edge,
- const SkBitmap& glow)
+OverscrollGlow::OverscrollGlow(bool enabled)
: enabled_(enabled),
- size_(size),
+ initialized_(false),
horizontal_overscroll_enabled_(true),
- vertical_overscroll_enabled_(true),
- root_layer_(cc::Layer::Create()) {
- for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
- scoped_refptr<cc::Layer> edge_layer = CreateImageLayer(edge);
- scoped_refptr<cc::Layer> glow_layer = CreateImageLayer(glow);
- root_layer_->AddChild(edge_layer);
- root_layer_->AddChild(glow_layer);
- edge_effects_[i] = make_scoped_ptr(new EdgeEffect(edge_layer, glow_layer));
- }
-}
+ vertical_overscroll_enabled_(true) {}
OverscrollGlow::~OverscrollGlow() {
- root_layer_->RemoveFromParent();
+ Detach();
+}
+
+void OverscrollGlow::Enable() {
+ enabled_ = true;
+}
+
+void OverscrollGlow::Disable() {
+ if (!enabled_)
+ return;
+ enabled_ = false;
+ if (!enabled_ && initialized_) {
+ Detach();
+ for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i)
+ edge_effects_[i]->Finish();
+ }
}
-void OverscrollGlow::OnOverscrolled(base::TimeTicks current_time,
+bool OverscrollGlow::OnOverscrolled(cc::Layer* overscrolling_layer,
+ base::TimeTicks current_time,
gfx::Vector2dF overscroll,
gfx::Vector2dF velocity) {
+ DCHECK(overscrolling_layer);
+
if (!enabled_)
- return;
+ return false;
// The size of the glow determines the relative effect of the inputs; an
// empty-sized effect is effectively disabled.
if (size_.IsEmpty())
- return;
+ return false;
if (!horizontal_overscroll_enabled_) {
overscroll.set_x(0);
@@ -126,10 +134,16 @@ void OverscrollGlow::OnOverscrolled(base::TimeTicks current_time,
velocity = ZeroSmallComponents(velocity);
if (overscroll.IsZero()) {
- Release(current_time);
- return;
+ if (initialized_) {
+ Release(current_time);
+ UpdateLayerAttachment(overscrolling_layer);
+ }
+ return NeedsAnimate();
}
+ if (!InitializeIfNecessary())
+ return false;
+
if (!velocity.IsZero()) {
// Release effects if scrolling has changed directions.
if (velocity.x() * old_velocity_.x() < 0)
@@ -152,18 +166,16 @@ void OverscrollGlow::OnOverscrolled(base::TimeTicks current_time,
old_velocity_ = velocity;
old_overscroll_ = overscroll;
-}
-void OverscrollGlow::Release(base::TimeTicks current_time) {
- for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
- edge_effects_[i]->Release(current_time);
- }
- old_overscroll_ = old_velocity_ = gfx::Vector2dF();
+ UpdateLayerAttachment(overscrolling_layer);
+ return NeedsAnimate();
}
bool OverscrollGlow::Animate(base::TimeTicks current_time) {
- if (!NeedsAnimate())
+ if (!NeedsAnimate()) {
+ Detach();
return false;
+ }
const gfx::SizeF sizes[EdgeEffect::EDGE_COUNT] = {
size_, gfx::SizeF(size_.height(), size_.width()),
@@ -177,21 +189,16 @@ bool OverscrollGlow::Animate(base::TimeTicks current_time) {
}
}
- return NeedsAnimate();
-}
-
-void OverscrollGlow::SetEnabled(bool enabled) {
- if (enabled_ == enabled)
- return;
- enabled_ = enabled;
- if (!enabled_) {
- for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i)
- edge_effects_[i]->Finish();
+ if (!NeedsAnimate()) {
+ Detach();
+ return false;
}
+
+ return true;
}
bool OverscrollGlow::NeedsAnimate() const {
- if (!enabled_)
+ if (!enabled_ || !initialized_)
return false;
for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
if (!edge_effects_[i]->IsFinished())
@@ -200,8 +207,54 @@ bool OverscrollGlow::NeedsAnimate() const {
return false;
}
+void OverscrollGlow::UpdateLayerAttachment(cc::Layer* parent) {
+ DCHECK(parent);
+ if (!root_layer_)
+ return;
+
+ if (!NeedsAnimate()) {
+ Detach();
+ return;
+ }
+
+ if (root_layer_->parent() != parent)
+ parent->AddChild(root_layer_);
+}
+
+void OverscrollGlow::Detach() {
+ if (root_layer_)
+ root_layer_->RemoveFromParent();
+}
+
+bool OverscrollGlow::InitializeIfNecessary() {
+ DCHECK(enabled_);
+ if (initialized_)
+ return true;
+
+ const SkBitmap& edge = g_overscroll_resources.Get().edge_bitmap();
+ const SkBitmap& glow = g_overscroll_resources.Get().glow_bitmap();
+ if (edge.isNull() || glow.isNull()) {
+ Disable();
+ return false;
+ }
+
+ DCHECK(!root_layer_);
+ root_layer_ = cc::Layer::Create();
+ for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
+ scoped_refptr<cc::Layer> edge_layer = CreateImageLayer(edge);
+ scoped_refptr<cc::Layer> glow_layer = CreateImageLayer(glow);
+ root_layer_->AddChild(edge_layer);
+ root_layer_->AddChild(glow_layer);
+ edge_effects_[i] = make_scoped_ptr(new EdgeEffect(edge_layer, glow_layer));
+ }
+
+ initialized_ = true;
+ return true;
+}
+
void OverscrollGlow::Pull(base::TimeTicks current_time,
gfx::Vector2dF overscroll_delta) {
+ DCHECK(enabled_ && initialized_);
overscroll_delta = ZeroSmallComponents(overscroll_delta);
if (overscroll_delta.IsZero())
return;
@@ -229,6 +282,7 @@ void OverscrollGlow::Absorb(base::TimeTicks current_time,
gfx::Vector2dF velocity,
gfx::Vector2dF overscroll,
gfx::Vector2dF old_overscroll) {
+ DCHECK(enabled_ && initialized_);
if (overscroll.IsZero() || velocity.IsZero())
return;
@@ -249,7 +303,16 @@ void OverscrollGlow::Absorb(base::TimeTicks current_time,
}
}
+void OverscrollGlow::Release(base::TimeTicks current_time) {
+ DCHECK(initialized_);
+ for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
+ edge_effects_[i]->Release(current_time);
+ }
+ old_overscroll_ = old_velocity_ = gfx::Vector2dF();
+}
+
void OverscrollGlow::ReleaseAxis(Axis axis, base::TimeTicks current_time) {
+ DCHECK(initialized_);
switch (axis) {
case AXIS_X:
edge_effects_[EdgeEffect::EDGE_LEFT]->Release(current_time);
@@ -267,6 +330,7 @@ void OverscrollGlow::ReleaseAxis(Axis axis, base::TimeTicks current_time) {
}
EdgeEffect* OverscrollGlow::GetOppositeEdge(int edge_index) {
+ DCHECK(initialized_);
return edge_effects_[(edge_index + 2) % EdgeEffect::EDGE_COUNT].get();
}
diff --git a/chromium/content/browser/android/overscroll_glow.h b/chromium/content/browser/android/overscroll_glow.h
index 01156a23f03..3a13fb3c4f1 100644
--- a/chromium/content/browser/android/overscroll_glow.h
+++ b/chromium/content/browser/android/overscroll_glow.h
@@ -26,43 +26,35 @@ namespace content {
*/
class OverscrollGlow {
public:
- // Create and initialize a new effect with the necessary resources.
- // If |enabled| is false, the effect will be be deactivated until
- // SetEnabled(true) is called.
- // The caller should attach |root_layer| to the desired layer tree.
- static scoped_ptr<OverscrollGlow> Create(bool enabled, gfx::SizeF size);
-
- // Force loading of any necessary resources. This function is thread-safe.
- static void EnsureResources();
+ // Create a new effect. If |enabled| is false, the effect will remain
+ // deactivated until explicitly enabled.
+ // Note: No resources will be allocated until the effect is both
+ // enabled and an overscroll event has occurred.
+ static scoped_ptr<OverscrollGlow> Create(bool enabled);
~OverscrollGlow();
- // If false, the glow will be deactivated, and subsequent calls to
- // OnOverscrolled or Animate will have no effect.
- void SetEnabled(bool enabled);
+ // Enable the effect. If the effect was previously disabled, it will remain
+ // dormant until subsequent calls to |OnOverscrolled()|.
+ void Enable();
+
+ // Deactivate and detach the effect. Subsequent calls to |OnOverscrolled()| or
+ // |Animate()| will have no effect.
+ void Disable();
+ // Effect layers will be attached to |overscrolling_layer| if necessary.
// |overscroll| is the accumulated overscroll for the current gesture.
// |velocity| is the instantaneous velocity for the overscroll.
- void OnOverscrolled(base::TimeTicks current_time,
+ // Returns true if the effect still needs animation ticks.
+ bool OnOverscrolled(cc::Layer* overscrolling_layer,
+ base::TimeTicks current_time,
gfx::Vector2dF overscroll,
gfx::Vector2dF velocity);
- // Triggers glow recession for any active edges.
- // Note: This does not actually release any resources; the name mirrors that
- // in Android's OverscrollGlow class.
- void Release(base::TimeTicks current_time);
-
// Returns true if the effect still needs animation ticks.
+ // Note: The effect will detach itself when no further animation is required.
bool Animate(base::TimeTicks current_time);
- // Returns true if the effect needs animation ticks.
- bool NeedsAnimate() const;
-
- // The root layer of the effect (not necessarily of the tree).
- scoped_refptr<cc::Layer> root_layer() const {
- return root_layer_;
- }
-
// Horizontal overscroll will be ignored when false.
void set_horizontal_overscroll_enabled(bool enabled) {
horizontal_overscroll_enabled_ = enabled;
@@ -79,18 +71,20 @@ class OverscrollGlow {
private:
enum Axis { AXIS_X, AXIS_Y };
- OverscrollGlow(bool enabled,
- gfx::SizeF size,
- const SkBitmap& edge,
- const SkBitmap& glow);
+ OverscrollGlow(bool enabled);
+ // Returns whether the effect is initialized.
+ bool InitializeIfNecessary();
+ bool NeedsAnimate() const;
+ void UpdateLayerAttachment(cc::Layer* parent);
+ void Detach();
void Pull(base::TimeTicks current_time,
gfx::Vector2dF added_overscroll);
void Absorb(base::TimeTicks current_time,
gfx::Vector2dF velocity,
gfx::Vector2dF overscroll,
gfx::Vector2dF old_overscroll);
-
+ void Release(base::TimeTicks current_time);
void ReleaseAxis(Axis axis, base::TimeTicks current_time);
EdgeEffect* GetOppositeEdge(int edge_index);
@@ -98,6 +92,7 @@ class OverscrollGlow {
scoped_ptr<EdgeEffect> edge_effects_[EdgeEffect::EDGE_COUNT];
bool enabled_;
+ bool initialized_;
gfx::SizeF size_;
gfx::Vector2dF old_overscroll_;
gfx::Vector2dF old_velocity_;
diff --git a/chromium/content/browser/android/popup_item_type_list.h b/chromium/content/browser/android/popup_item_type_list.h
new file mode 100644
index 00000000000..3f50490f610
--- /dev/null
+++ b/chromium/content/browser/android/popup_item_type_list.h
@@ -0,0 +1,23 @@
+// 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.
+
+// This file intentionally does not have header guards because this file
+// is meant to be included inside a macro to generate enum values.
+
+// This file contains a list of sync PopupItemTypes which describe the type
+// and enabled state of a select popup item. List is used by Android when
+// displaying a new select popup menu.
+
+#ifndef DEFINE_POPUP_ITEM_TYPE
+#error "Please define DEFINE_POPUP_ITEM_TYPE before including this file."
+#endif
+
+// Popup item is of type group
+DEFINE_POPUP_ITEM_TYPE(GROUP, 0)
+
+// Popup item is disabled
+DEFINE_POPUP_ITEM_TYPE(DISABLED, 1)
+
+// Popup item is enabled
+DEFINE_POPUP_ITEM_TYPE(ENABLED, 2)
diff --git a/chromium/content/browser/android/touch_point.cc b/chromium/content/browser/android/touch_point.cc
index 1a10e6ecfca..ffe2e50507c 100644
--- a/chromium/content/browser/android/touch_point.cc
+++ b/chromium/content/browser/android/touch_point.cc
@@ -10,15 +10,15 @@
#include "jni/TouchPoint_jni.h"
-using WebKit::WebTouchEvent;
-using WebKit::WebTouchPoint;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
namespace {
void MaybeAddTouchPoint(JNIEnv* env,
jobject pt,
float dpi_scale,
- WebKit::WebTouchEvent& event) {
+ blink::WebTouchEvent& event) {
WebTouchPoint::State state = static_cast<WebTouchPoint::State>(
Java_TouchPoint_getState(env, pt));
if (state == WebTouchPoint::StateUndefined)
@@ -32,7 +32,7 @@ void MaybeAddTouchPoint(JNIEnv* env,
// Record the current number of points in the WebTouchEvent
const int idx = event.touchesLength;
- DCHECK_LT(idx, WebKit::WebTouchEvent::touchesLengthCap);
+ DCHECK_LT(idx, blink::WebTouchEvent::touchesLengthCap);
WebTouchPoint wtp;
wtp.id = Java_TouchPoint_getId(env, pt);
@@ -43,20 +43,28 @@ void MaybeAddTouchPoint(JNIEnv* env,
wtp.screenPosition = wtp.position;
wtp.force = Java_TouchPoint_getPressure(env, pt);
- // TODO(djsollen): WebKit stores touch point size as a pair of radii, which
- // are integers. We receive touch point size from Android as a float
- // between 0 and 1 and interpret 'size' as an elliptical area. We convert
- // size to a radius and then scale up to avoid truncating away all of the
- // data. W3C spec is for the radii to be in units of screen pixels. Need to
- // change.
- const static double PI = 3.1415926;
- const static double SCALE_FACTOR = 1024.0;
- const int radius = static_cast<int>(
- (sqrt(Java_TouchPoint_getSize(env, pt)) / PI) * SCALE_FACTOR);
- wtp.radiusX = radius / dpi_scale;
- wtp.radiusY = radius / dpi_scale;
- // Since our radii are equal, a rotation angle doesn't mean anything.
- wtp.rotationAngle = 0.0;
+ const int radiusMajor = static_cast<int>(
+ Java_TouchPoint_getTouchMajor(env, pt) * 0.5f / dpi_scale);
+ const int radiusMinor = static_cast<int>(
+ Java_TouchPoint_getTouchMinor(env, pt) * 0.5f / dpi_scale);
+ const float majorAngleInRadiansClockwiseFromVertical =
+ Java_TouchPoint_getOrientation(env, pt);
+ const float majorAngleInDegreesClockwiseFromVertical =
+ std::isnan(majorAngleInRadiansClockwiseFromVertical)
+ ? 0.f : (majorAngleInRadiansClockwiseFromVertical * 180.f) / M_PI;
+ // Android provides a major axis orientation clockwise with respect to the
+ // vertical of [-90, 90], while the W3C specifies a range of [0, 90].
+ if (majorAngleInDegreesClockwiseFromVertical >= 0) {
+ wtp.radiusX = radiusMinor;
+ wtp.radiusY = radiusMajor;
+ wtp.rotationAngle = majorAngleInDegreesClockwiseFromVertical;
+ } else {
+ wtp.radiusX = radiusMajor;
+ wtp.radiusY = radiusMinor;
+ wtp.rotationAngle = majorAngleInDegreesClockwiseFromVertical + 90.f;
+ }
+ DCHECK_GE(wtp.rotationAngle, 0.f);
+ DCHECK_LE(wtp.rotationAngle, 90.f);
// Add the newly created WebTouchPoint to the event
event.touches[idx] = wtp;
@@ -72,7 +80,7 @@ void TouchPoint::BuildWebTouchEvent(JNIEnv* env,
jlong time_ms,
float dpi_scale,
jobjectArray pts,
- WebKit::WebTouchEvent& event) {
+ blink::WebTouchEvent& event) {
event.type = static_cast<WebTouchEvent::Type>(type);
event.timeStampSeconds =
static_cast<double>(time_ms) / base::Time::kMillisecondsPerSecond;
@@ -91,16 +99,16 @@ void TouchPoint::BuildWebTouchEvent(JNIEnv* env,
static void RegisterConstants(JNIEnv* env) {
Java_TouchPoint_initializeConstants(
env,
- WebKit::WebTouchEvent::TouchStart,
- WebKit::WebTouchEvent::TouchMove,
- WebKit::WebTouchEvent::TouchEnd,
- WebKit::WebTouchEvent::TouchCancel,
- WebKit::WebTouchPoint::StateUndefined,
- WebKit::WebTouchPoint::StateReleased,
- WebKit::WebTouchPoint::StatePressed,
- WebKit::WebTouchPoint::StateMoved,
- WebKit::WebTouchPoint::StateStationary,
- WebKit::WebTouchPoint::StateCancelled);
+ blink::WebTouchEvent::TouchStart,
+ blink::WebTouchEvent::TouchMove,
+ blink::WebTouchEvent::TouchEnd,
+ blink::WebTouchEvent::TouchCancel,
+ blink::WebTouchPoint::StateUndefined,
+ blink::WebTouchPoint::StateReleased,
+ blink::WebTouchPoint::StatePressed,
+ blink::WebTouchPoint::StateMoved,
+ blink::WebTouchPoint::StateStationary,
+ blink::WebTouchPoint::StateCancelled);
}
bool RegisterTouchPoint(JNIEnv* env) {
diff --git a/chromium/content/browser/android/touch_point.h b/chromium/content/browser/android/touch_point.h
index 8e9971bad5c..d7caac08764 100644
--- a/chromium/content/browser/android/touch_point.h
+++ b/chromium/content/browser/android/touch_point.h
@@ -12,7 +12,7 @@
namespace content {
// This class provides a helper method to convert a java object array of touch
-// events (in physical pixdels) into a WebKit::WebTouchEvent (in dip).
+// events (in physical pixdels) into a blink::WebTouchEvent (in dip).
class TouchPoint {
public:
static void BuildWebTouchEvent(JNIEnv* env,
@@ -20,7 +20,7 @@ class TouchPoint {
jlong time_ms,
float dpi_scale,
jobjectArray pts,
- WebKit::WebTouchEvent& event);
+ blink::WebTouchEvent& event);
};
bool RegisterTouchPoint(JNIEnv* env);
diff --git a/chromium/content/browser/android/tracing_controller_android.cc b/chromium/content/browser/android/tracing_controller_android.cc
new file mode 100644
index 00000000000..75ac6d7c238
--- /dev/null
+++ b/chromium/content/browser/android/tracing_controller_android.cc
@@ -0,0 +1,78 @@
+// 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/android/tracing_controller_android.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "content/public/browser/tracing_controller.h"
+#include "jni/TracingControllerAndroid_jni.h"
+
+namespace content {
+
+static jlong Init(JNIEnv* env, jobject obj) {
+ TracingControllerAndroid* profiler = new TracingControllerAndroid(env, obj);
+ return reinterpret_cast<intptr_t>(profiler);
+}
+
+TracingControllerAndroid::TracingControllerAndroid(JNIEnv* env, jobject obj)
+ : weak_java_object_(env, obj),
+ weak_factory_(this) {}
+
+TracingControllerAndroid::~TracingControllerAndroid() {}
+
+void TracingControllerAndroid::Destroy(JNIEnv* env, jobject obj) {
+ delete this;
+}
+
+bool TracingControllerAndroid::StartTracing(JNIEnv* env,
+ jobject obj,
+ jstring jfilename,
+ jstring jcategories,
+ jboolean record_continuously) {
+ file_path_ = base::FilePath(
+ base::android::ConvertJavaStringToUTF8(env, jfilename));
+ std::string categories =
+ base::android::ConvertJavaStringToUTF8(env, jcategories);
+
+ // This log is required by adb_profile_chrome.py.
+ LOG(WARNING) << "Logging performance trace to file: " << file_path_.value();
+
+ return TracingController::GetInstance()->EnableRecording(
+ categories,
+ record_continuously ? TracingController::RECORD_CONTINUOUSLY
+ : TracingController::DEFAULT_OPTIONS,
+ TracingController::EnableRecordingDoneCallback());
+}
+
+void TracingControllerAndroid::StopTracing(JNIEnv* env, jobject obj) {
+ if (!TracingController::GetInstance()->DisableRecording(
+ file_path_,
+ base::Bind(&TracingControllerAndroid::OnTracingStopped,
+ weak_factory_.GetWeakPtr()))) {
+ LOG(ERROR) << "EndTracingAsync failed, forcing an immediate stop";
+ OnTracingStopped(file_path_);
+ }
+}
+
+void TracingControllerAndroid::OnTracingStopped(
+ const base::FilePath& file_path) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ base::android::ScopedJavaLocalRef<jobject> obj = weak_java_object_.get(env);
+ if (obj.obj())
+ Java_TracingControllerAndroid_onTracingStopped(env, obj.obj());
+}
+
+static jstring GetDefaultCategories(JNIEnv* env, jobject obj) {
+ return base::android::ConvertUTF8ToJavaString(env,
+ base::debug::CategoryFilter::kDefaultCategoryFilterString).Release();
+}
+
+bool RegisterTracingControllerAndroid(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/tracing_controller_android.h b/chromium/content/browser/android/tracing_controller_android.h
new file mode 100644
index 00000000000..4d70e7b75ef
--- /dev/null
+++ b/chromium/content/browser/android/tracing_controller_android.h
@@ -0,0 +1,43 @@
+// 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_ANDROID_TRACING_CONTROLLER_ANDROID_H_
+#define CONTENT_BROWSER_ANDROID_TRACING_CONTROLLER_ANDROID_H_
+
+#include "base/android/jni_helper.h"
+#include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
+
+namespace content {
+
+// This class implements the native methods of TracingControllerAndroid.java
+class TracingControllerAndroid {
+ public:
+ TracingControllerAndroid(JNIEnv* env, jobject obj);
+ void Destroy(JNIEnv* env, jobject obj);
+
+ bool StartTracing(JNIEnv* env,
+ jobject obj,
+ jstring filename,
+ jstring categories,
+ jboolean record_continuously);
+ void StopTracing(JNIEnv* env, jobject obj);
+
+ private:
+ ~TracingControllerAndroid();
+ void OnTracingStopped(const base::FilePath& file_path);
+
+ JavaObjectWeakGlobalRef weak_java_object_;
+ base::FilePath file_path_;
+ base::WeakPtrFactory<TracingControllerAndroid> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(TracingControllerAndroid);
+};
+
+// Register this class's native methods through jni.
+bool RegisterTracingControllerAndroid(JNIEnv* env);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_TRACING_CONTROLLER_ANDROID_H_
diff --git a/chromium/content/browser/android/tracing_intent_handler.cc b/chromium/content/browser/android/tracing_intent_handler.cc
deleted file mode 100644
index 324f8055cc1..00000000000
--- a/chromium/content/browser/android/tracing_intent_handler.cc
+++ /dev/null
@@ -1,57 +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/tracing_intent_handler.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "content/public/browser/trace_controller.h"
-#include "jni/TracingIntentHandler_jni.h"
-
-namespace content {
-
-TracingIntentHandler* g_trace_intent_handler = NULL;
-
-TracingIntentHandler::TracingIntentHandler(const base::FilePath& path)
- : TraceSubscriberStdio(path, FILE_TYPE_ARRAY, false) {
- TraceController::GetInstance()->BeginTracing(
- this,
- std::string("-test*"),
- base::debug::TraceLog::RECORD_UNTIL_FULL);
-}
-
-TracingIntentHandler::~TracingIntentHandler() {
-}
-
-void TracingIntentHandler::OnEndTracingComplete() {
- TraceSubscriberStdio::OnEndTracingComplete();
- delete this;
-}
-
-void TracingIntentHandler::OnEndTracing() {
- if (!TraceController::GetInstance()->EndTracingAsync(this)) {
- delete this;
- }
-}
-
-static void BeginTracing(JNIEnv* env, jclass clazz, jstring jspath) {
- std::string path(base::android::ConvertJavaStringToUTF8(env, jspath));
- if (g_trace_intent_handler != NULL)
- return;
- g_trace_intent_handler = new TracingIntentHandler(base::FilePath(path));
-}
-
-static void EndTracing(JNIEnv* env, jclass clazz) {
- DCHECK(!g_trace_intent_handler);
- g_trace_intent_handler->OnEndTracing();
- g_trace_intent_handler = NULL;
-}
-
-bool RegisterTracingIntentHandler(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/android/tracing_intent_handler.h b/chromium/content/browser/android/tracing_intent_handler.h
deleted file mode 100644
index 787f854e628..00000000000
--- a/chromium/content/browser/android/tracing_intent_handler.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_TRACING_INTENT_HANDLER_H_
-#define CONTENT_BROWSER_ANDROID_TRACING_INTENT_HANDLER_H_
-
-#include <jni.h>
-#include <string>
-
-#include "content/browser/tracing/trace_subscriber_stdio.h"
-
-namespace content {
-
-// Registers the TracingIntentHandler native methods.
-bool RegisterTracingIntentHandler(JNIEnv* env);
-
-class TracingIntentHandler : public TraceSubscriberStdio {
- public:
- explicit TracingIntentHandler(const base::FilePath& path);
- virtual ~TracingIntentHandler();
-
- // TraceSubscriber implementation
- virtual void OnEndTracingComplete() OVERRIDE;
-
- // IntentHandler
- void OnEndTracing();
-};
-
-} // namespace content
-#endif // CONTENT_BROWSER_ANDROID_TRACING_INTENT_HANDLER_H_
diff --git a/chromium/content/browser/android/web_contents_observer_android.cc b/chromium/content/browser/android/web_contents_observer_android.cc
index e30bf953304..797ea3b1af9 100644
--- a/chromium/content/browser/android/web_contents_observer_android.cc
+++ b/chromium/content/browser/android/web_contents_observer_android.cc
@@ -22,7 +22,6 @@ using base::android::AttachCurrentThread;
using base::android::ScopedJavaLocalRef;
using base::android::ConvertUTF8ToJavaString;
using base::android::ConvertUTF16ToJavaString;
-using base::android::HasClass;
namespace content {
@@ -37,12 +36,12 @@ WebContentsObserverAndroid::WebContentsObserverAndroid(
WebContentsObserverAndroid::~WebContentsObserverAndroid() {
}
-jint Init(JNIEnv* env, jobject obj, jint native_content_view_core) {
+jlong Init(JNIEnv* env, jobject obj, jlong native_content_view_core) {
ContentViewCore* content_view_core =
reinterpret_cast<ContentViewCore*>(native_content_view_core);
WebContentsObserverAndroid* native_observer = new WebContentsObserverAndroid(
env, obj, content_view_core->GetWebContents());
- return reinterpret_cast<jint>(native_observer);
+ return reinterpret_cast<intptr_t>(native_observer);
}
void WebContentsObserverAndroid::Destroy(JNIEnv* env, jobject obj) {
@@ -61,6 +60,18 @@ void WebContentsObserverAndroid::WebContentsDestroyed(
}
}
+void WebContentsObserverAndroid::RenderProcessGone(
+ base::TerminationStatus termination_status) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
+ if (obj.is_null())
+ return;
+ jboolean was_oom_protected =
+ termination_status == base::TERMINATION_STATUS_OOM_PROTECTED;
+ Java_WebContentsObserverAndroid_renderProcessGone(
+ env, obj.obj(), was_oom_protected);
+}
+
void WebContentsObserverAndroid::DidStartLoading(
RenderViewHost* render_view_host) {
JNIEnv* env = AttachCurrentThread();
@@ -79,29 +90,19 @@ void WebContentsObserverAndroid::DidStopLoading(
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
return;
-
- std::string url_string;
- NavigationEntry* entry =
- web_contents()->GetController().GetLastCommittedEntry();
- // Not that GetBaseURLForDataURL is only used by the Android WebView
- if (entry && !entry->GetBaseURLForDataURL().is_empty()) {
- url_string = entry->GetBaseURLForDataURL().possibly_invalid_spec();
- } else {
- url_string = web_contents()->GetLastCommittedURL().spec();
- }
-
- ScopedJavaLocalRef<jstring> jstring_url(
- ConvertUTF8ToJavaString(env, url_string));
+ ScopedJavaLocalRef<jstring> jstring_url(ConvertUTF8ToJavaString(
+ env, web_contents()->GetLastCommittedURL().spec()));
Java_WebContentsObserverAndroid_didStopLoading(
env, obj.obj(), jstring_url.obj());
}
void WebContentsObserverAndroid::DidFailProvisionalLoad(
int64 frame_id,
+ const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& validated_url,
int error_code,
- const string16& error_description,
+ const base::string16& error_description,
RenderViewHost* render_view_host) {
DidFailLoadInternal(
true, is_main_frame, error_code, error_description, validated_url);
@@ -112,7 +113,7 @@ void WebContentsObserverAndroid::DidFailLoad(
const GURL& validated_url,
bool is_main_frame,
int error_code,
- const string16& error_description,
+ const base::string16& error_description,
RenderViewHost* render_view_host) {
DidFailLoadInternal(
false, is_main_frame, error_code, error_description, validated_url);
@@ -129,9 +130,16 @@ void WebContentsObserverAndroid::DidNavigateMainFrame(
ConvertUTF8ToJavaString(env, params.url.spec()));
ScopedJavaLocalRef<jstring> jstring_base_url(
ConvertUTF8ToJavaString(env, params.base_url.spec()));
- Java_WebContentsObserverAndroid_didNavigateMainFrame(
+ // See http://crbug.com/251330 for why it's determined this way.
+ bool in_page_navigation =
+ details.type == NAVIGATION_TYPE_IN_PAGE || details.is_in_page;
+ // TODO(mkosiba): delete once downstream rolls.
+ Java_WebContentsObserverAndroid_didNavigateMainFrameV_JLS_JLS_Z(
env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
details.is_navigation_to_different_page());
+ Java_WebContentsObserverAndroid_didNavigateMainFrameV_JLS_JLS_Z_Z(
+ env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
+ details.is_navigation_to_different_page(), in_page_navigation);
}
void WebContentsObserverAndroid::DidNavigateAnyFrame(
@@ -174,6 +182,7 @@ void WebContentsObserverAndroid::DidStartProvisionalLoadForFrame(
void WebContentsObserverAndroid::DidCommitProvisionalLoadForFrame(
int64 frame_id,
+ const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& url,
PageTransition transition_type,
@@ -198,12 +207,29 @@ void WebContentsObserverAndroid::DidFinishLoad(
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
return;
+
+ std::string url_string = validated_url.spec();
+ NavigationEntry* entry =
+ web_contents()->GetController().GetLastCommittedEntry();
+ // Note that GetBaseURLForDataURL is only used by the Android WebView.
+ if (entry && !entry->GetBaseURLForDataURL().is_empty())
+ url_string = entry->GetBaseURLForDataURL().possibly_invalid_spec();
+
ScopedJavaLocalRef<jstring> jstring_url(
- ConvertUTF8ToJavaString(env, validated_url.spec()));
+ ConvertUTF8ToJavaString(env, url_string));
Java_WebContentsObserverAndroid_didFinishLoad(
env, obj.obj(), frame_id, jstring_url.obj(), is_main_frame);
}
+void WebContentsObserverAndroid::NavigationEntryCommitted(
+ const LoadCommittedDetails& load_details) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
+ if (obj.is_null())
+ return;
+ Java_WebContentsObserverAndroid_navigationEntryCommitted(env, obj.obj());
+}
+
void WebContentsObserverAndroid::DidChangeVisibleSSLState() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
@@ -232,7 +258,7 @@ void WebContentsObserverAndroid::DidFailLoadInternal(
bool is_provisional_load,
bool is_main_frame,
int error_code,
- const string16& description,
+ const base::string16& description,
const GURL& url) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
@@ -252,10 +278,6 @@ void WebContentsObserverAndroid::DidFailLoadInternal(
}
bool RegisterWebContentsObserverAndroid(JNIEnv* env) {
- if (!HasClass(env, kWebContentsObserverAndroidClassPath)) {
- DLOG(ERROR) << "Unable to find class WebContentsObserverAndroid!";
- return false;
- }
return RegisterNativesImpl(env);
}
} // namespace content
diff --git a/chromium/content/browser/android/web_contents_observer_android.h b/chromium/content/browser/android/web_contents_observer_android.h
index e975d795260..15a136390f8 100644
--- a/chromium/content/browser/android/web_contents_observer_android.h
+++ b/chromium/content/browser/android/web_contents_observer_android.h
@@ -9,6 +9,7 @@
#include "base/android/jni_helper.h"
#include "base/basictypes.h"
+#include "base/process/kill.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/frame_navigate_params.h"
@@ -31,20 +32,23 @@ class WebContentsObserverAndroid : public WebContentsObserver {
void Destroy(JNIEnv* env, jobject obj);
private:
+ virtual void RenderProcessGone(
+ base::TerminationStatus termination_status) OVERRIDE;
virtual void DidStartLoading(RenderViewHost* render_view_host) OVERRIDE;
virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE;
virtual void DidFailProvisionalLoad(
int64 frame_id,
+ const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& validated_url,
int error_code,
- const string16& error_description,
+ const base::string16& error_description,
RenderViewHost* render_view_host) OVERRIDE;
virtual void DidFailLoad(int64 frame_id,
const GURL& validated_url,
bool is_main_frame,
int error_code,
- const string16& error_description,
+ const base::string16& error_description,
RenderViewHost* render_view_host) OVERRIDE;
virtual void DidNavigateMainFrame(const LoadCommittedDetails& details,
const FrameNavigateParams& params) OVERRIDE;
@@ -60,6 +64,7 @@ class WebContentsObserverAndroid : public WebContentsObserver {
RenderViewHost* render_view_host) OVERRIDE;
virtual void DidCommitProvisionalLoadForFrame(
int64 frame_id,
+ const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& url,
PageTransition transition_type,
@@ -68,6 +73,8 @@ class WebContentsObserverAndroid : public WebContentsObserver {
const GURL& validated_url,
bool is_main_frame,
RenderViewHost* render_view_host) OVERRIDE;
+ virtual void NavigationEntryCommitted(
+ const LoadCommittedDetails& load_details) OVERRIDE;
virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
virtual void DidChangeVisibleSSLState() OVERRIDE;
virtual void DidAttachInterstitialPage() OVERRIDE;
@@ -76,7 +83,7 @@ class WebContentsObserverAndroid : public WebContentsObserver {
void DidFailLoadInternal(bool is_provisional_load,
bool is_main_frame,
int error_code,
- const string16& description,
+ const base::string16& description,
const GURL& url);
JavaObjectWeakGlobalRef weak_java_observer_;
diff --git a/chromium/content/browser/appcache/appcache_dispatcher_host.cc b/chromium/content/browser/appcache/appcache_dispatcher_host.cc
index b68a73d466e..25e33cf209a 100644
--- a/chromium/content/browser/appcache/appcache_dispatcher_host.cc
+++ b/chromium/content/browser/appcache/appcache_dispatcher_host.cc
@@ -21,7 +21,6 @@ AppCacheDispatcherHost::AppCacheDispatcherHost(
}
void AppCacheDispatcherHost::OnChannelConnected(int32 peer_pid) {
- BrowserMessageFilter::OnChannelConnected(peer_pid);
if (appcache_service_.get()) {
backend_impl_.Initialize(
appcache_service_.get(), &frontend_proxy_, process_id_);
diff --git a/chromium/content/browser/aura/browser_compositor_output_surface.cc b/chromium/content/browser/aura/browser_compositor_output_surface.cc
index 36e5dcdbfda..2125d3845f4 100644
--- a/chromium/content/browser/aura/browser_compositor_output_surface.cc
+++ b/chromium/content/browser/aura/browser_compositor_output_surface.cc
@@ -9,10 +9,8 @@
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/string_number_conversions.h"
-#include "cc/output/compositor_frame.h"
#include "content/browser/aura/reflector_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_switches.h"
@@ -29,6 +27,31 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
output_surface_map_(output_surface_map),
compositor_message_loop_(compositor_message_loop),
compositor_(compositor) {
+ Initialize();
+}
+
+BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
+ scoped_ptr<cc::SoftwareOutputDevice> software_device,
+ int surface_id,
+ IDMap<BrowserCompositorOutputSurface>* output_surface_map,
+ base::MessageLoopProxy* compositor_message_loop,
+ base::WeakPtr<ui::Compositor> compositor)
+ : OutputSurface(software_device.Pass()),
+ surface_id_(surface_id),
+ output_surface_map_(output_surface_map),
+ compositor_message_loop_(compositor_message_loop),
+ compositor_(compositor) {
+ Initialize();
+}
+
+BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() {
+ DCHECK(CalledOnValidThread());
+ if (!HasClient())
+ return;
+ output_surface_map_->Remove(surface_id_);
+}
+
+void BrowserCompositorOutputSurface::Initialize() {
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kUIMaxFramesPending)) {
std::string string_value = command_line->GetSwitchValueASCII(
@@ -40,14 +63,8 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
LOG(ERROR) << "Trouble parsing --" << switches::kUIMaxFramesPending;
}
capabilities_.adjust_deadline_for_parent = false;
- DetachFromThread();
-}
-BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() {
- DCHECK(CalledOnValidThread());
- if (!HasClient())
- return;
- output_surface_map_->Remove(surface_id_);
+ DetachFromThread();
}
bool BrowserCompositorOutputSurface::BindToClient(
@@ -58,6 +75,8 @@ bool BrowserCompositorOutputSurface::BindToClient(
return false;
output_surface_map_->AddWithID(this, surface_id_);
+ if (reflector_)
+ reflector_->OnSourceSurfaceReady(surface_id_);
return true;
}
@@ -68,29 +87,6 @@ void BrowserCompositorOutputSurface::Reshape(gfx::Size size,
reflector_->OnReshape(size);
}
-void BrowserCompositorOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
- DCHECK(frame->gl_frame_data);
-
- WebGraphicsContext3DCommandBufferImpl* command_buffer_context =
- static_cast<WebGraphicsContext3DCommandBufferImpl*>(
- context_provider_->Context3d());
- CommandBufferProxyImpl* command_buffer_proxy =
- command_buffer_context->GetCommandBufferProxy();
- DCHECK(command_buffer_proxy);
- context_provider_->Context3d()->shallowFlushCHROMIUM();
- command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
-
- if (reflector_.get()) {
- if (frame->gl_frame_data->sub_buffer_rect ==
- gfx::Rect(frame->gl_frame_data->size))
- reflector_->OnSwapBuffers();
- else
- reflector_->OnPostSubBuffer(frame->gl_frame_data->sub_buffer_rect);
- }
-
- OutputSurface::SwapBuffers(frame);
-}
-
void BrowserCompositorOutputSurface::OnUpdateVSyncParameters(
base::TimeTicks timebase,
base::TimeDelta interval) {
diff --git a/chromium/content/browser/aura/browser_compositor_output_surface.h b/chromium/content/browser/aura/browser_compositor_output_surface.h
index f9ec3c8d9d5..79f757a56a2 100644
--- a/chromium/content/browser/aura/browser_compositor_output_surface.h
+++ b/chromium/content/browser/aura/browser_compositor_output_surface.h
@@ -9,9 +9,14 @@
#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "cc/output/output_surface.h"
+#include "content/common/content_export.h"
namespace base { class MessageLoopProxy; }
+namespace cc {
+class SoftwareOutputDevice;
+}
+
namespace ui { class Compositor; }
namespace content {
@@ -19,39 +24,49 @@ class ContextProviderCommandBuffer;
class ReflectorImpl;
class WebGraphicsContext3DCommandBufferImpl;
-// Adapts a WebGraphicsContext3DCommandBufferImpl into a
-// cc::OutputSurface that also handles vsync parameter updates
-// arriving from the GPU process.
-class BrowserCompositorOutputSurface
+class CONTENT_EXPORT BrowserCompositorOutputSurface
: public cc::OutputSurface,
public base::NonThreadSafe {
public:
- BrowserCompositorOutputSurface(
- const scoped_refptr<ContextProviderCommandBuffer>& context,
- int surface_id,
- IDMap<BrowserCompositorOutputSurface>* output_surface_map,
- base::MessageLoopProxy* compositor_message_loop,
- base::WeakPtr<ui::Compositor> compositor);
-
virtual ~BrowserCompositorOutputSurface();
// cc::OutputSurface implementation.
virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE;
virtual void Reshape(gfx::Size size, float scale_factor) OVERRIDE;
- virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
void OnUpdateVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval);
void SetReflector(ReflectorImpl* reflector);
- private:
+ protected:
+ // Constructor used by the accelerated implementation.
+ BrowserCompositorOutputSurface(
+ const scoped_refptr<ContextProviderCommandBuffer>& context,
+ int surface_id,
+ IDMap<BrowserCompositorOutputSurface>* output_surface_map,
+ base::MessageLoopProxy* compositor_message_loop,
+ base::WeakPtr<ui::Compositor> compositor);
+
+ // Constructor used by the software implementation.
+ BrowserCompositorOutputSurface(
+ scoped_ptr<cc::SoftwareOutputDevice> software_device,
+ int surface_id,
+ IDMap<BrowserCompositorOutputSurface>* output_surface_map,
+ base::MessageLoopProxy* compositor_message_loop,
+ base::WeakPtr<ui::Compositor> compositor);
+
int surface_id_;
IDMap<BrowserCompositorOutputSurface>* output_surface_map_;
scoped_refptr<base::MessageLoopProxy> compositor_message_loop_;
base::WeakPtr<ui::Compositor> compositor_;
scoped_refptr<ReflectorImpl> reflector_;
+
+ private:
+ void Initialize();
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserCompositorOutputSurface);
};
} // namespace content
diff --git a/chromium/content/browser/aura/browser_compositor_output_surface_proxy.h b/chromium/content/browser/aura/browser_compositor_output_surface_proxy.h
index 2a08d0a89dd..0c5ffcd6740 100644
--- a/chromium/content/browser/aura/browser_compositor_output_surface_proxy.h
+++ b/chromium/content/browser/aura/browser_compositor_output_surface_proxy.h
@@ -8,6 +8,7 @@
#include "base/id_map.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
+#include "content/common/content_export.h"
namespace base { class SingleThreadTaskRunner; }
@@ -17,7 +18,7 @@ namespace content {
class BrowserCompositorOutputSurface;
// Directs vsync updates to the appropriate BrowserCompositorOutputSurface.
-class BrowserCompositorOutputSurfaceProxy
+class CONTENT_EXPORT BrowserCompositorOutputSurfaceProxy
: public base::RefCountedThreadSafe<BrowserCompositorOutputSurfaceProxy> {
public:
BrowserCompositorOutputSurfaceProxy(
@@ -30,6 +31,7 @@ class BrowserCompositorOutputSurfaceProxy
private:
friend class base::RefCountedThreadSafe<BrowserCompositorOutputSurfaceProxy>;
+ friend class SoftwareBrowserCompositorOutputSurface;
~BrowserCompositorOutputSurfaceProxy();
void OnMessageReceivedOnCompositorThread(const IPC::Message& message);
diff --git a/chromium/content/browser/aura/gpu_browser_compositor_output_surface.cc b/chromium/content/browser/aura/gpu_browser_compositor_output_surface.cc
new file mode 100644
index 00000000000..8e3c30ca529
--- /dev/null
+++ b/chromium/content/browser/aura/gpu_browser_compositor_output_surface.cc
@@ -0,0 +1,51 @@
+// 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/aura/gpu_browser_compositor_output_surface.h"
+
+#include "cc/output/compositor_frame.h"
+#include "content/browser/aura/reflector_impl.h"
+#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+
+namespace content {
+
+GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
+ const scoped_refptr<ContextProviderCommandBuffer>& context,
+ int surface_id,
+ IDMap<BrowserCompositorOutputSurface>* output_surface_map,
+ base::MessageLoopProxy* compositor_message_loop,
+ base::WeakPtr<ui::Compositor> compositor)
+ : BrowserCompositorOutputSurface(context,
+ surface_id,
+ output_surface_map,
+ compositor_message_loop,
+ compositor) {}
+
+GpuBrowserCompositorOutputSurface::~GpuBrowserCompositorOutputSurface() {}
+
+void GpuBrowserCompositorOutputSurface::SwapBuffers(
+ cc::CompositorFrame* frame) {
+ DCHECK(frame->gl_frame_data);
+
+ WebGraphicsContext3DCommandBufferImpl* command_buffer_context =
+ static_cast<WebGraphicsContext3DCommandBufferImpl*>(
+ context_provider_->Context3d());
+ CommandBufferProxyImpl* command_buffer_proxy =
+ command_buffer_context->GetCommandBufferProxy();
+ DCHECK(command_buffer_proxy);
+ context_provider_->Context3d()->shallowFlushCHROMIUM();
+ command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
+
+ if (reflector_.get()) {
+ if (frame->gl_frame_data->sub_buffer_rect ==
+ gfx::Rect(frame->gl_frame_data->size))
+ reflector_->OnSwapBuffers();
+ else
+ reflector_->OnPostSubBuffer(frame->gl_frame_data->sub_buffer_rect);
+ }
+
+ OutputSurface::SwapBuffers(frame);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/aura/gpu_browser_compositor_output_surface.h b/chromium/content/browser/aura/gpu_browser_compositor_output_surface.h
new file mode 100644
index 00000000000..76b9724d4a6
--- /dev/null
+++ b/chromium/content/browser/aura/gpu_browser_compositor_output_surface.h
@@ -0,0 +1,36 @@
+// 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_AURA_GPU_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
+#define CONTENT_BROWSER_AURA_GPU_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
+
+#include "content/browser/aura/browser_compositor_output_surface.h"
+
+namespace content {
+
+// Adapts a WebGraphicsContext3DCommandBufferImpl into a
+// cc::OutputSurface that also handles vsync parameter updates
+// arriving from the GPU process.
+class GpuBrowserCompositorOutputSurface
+ : public BrowserCompositorOutputSurface {
+ public:
+ GpuBrowserCompositorOutputSurface(
+ const scoped_refptr<ContextProviderCommandBuffer>& context,
+ int surface_id,
+ IDMap<BrowserCompositorOutputSurface>* output_surface_map,
+ base::MessageLoopProxy* compositor_message_loop,
+ base::WeakPtr<ui::Compositor> compositor);
+
+ virtual ~GpuBrowserCompositorOutputSurface();
+
+ private:
+ // cc::OutputSurface implementation.
+ virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuBrowserCompositorOutputSurface);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_AURA_GPU_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
diff --git a/chromium/content/browser/aura/gpu_process_transport_factory.cc b/chromium/content/browser/aura/gpu_process_transport_factory.cc
index 959210decea..47efce7555f 100644
--- a/chromium/content/browser/aura/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/aura/gpu_process_transport_factory.cc
@@ -15,6 +15,7 @@
#include "cc/output/output_surface.h"
#include "content/browser/aura/browser_compositor_output_surface.h"
#include "content/browser/aura/browser_compositor_output_surface_proxy.h"
+#include "content/browser/aura/gpu_browser_compositor_output_surface.h"
#include "content/browser/aura/reflector_impl.h"
#include "content/browser/aura/software_browser_compositor_output_surface.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
@@ -27,8 +28,10 @@
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/common/gpu/gpu_process_launch_causes.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/compositor/compositor.h"
+#include "ui/compositor/compositor_constants.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
@@ -36,15 +39,19 @@
#if defined(OS_WIN)
#include "content/browser/aura/software_output_device_win.h"
#include "ui/surface/accelerated_surface_win.h"
+#elif defined(USE_OZONE)
+#include "content/browser/aura/software_output_device_ozone.h"
#elif defined(USE_X11)
#include "content/browser/aura/software_output_device_x11.h"
#endif
+using cc::ContextProvider;
+using gpu::gles2::GLES2Interface;
+
namespace content {
struct GpuProcessTransportFactory::PerCompositorData {
int surface_id;
- scoped_ptr<CompositorSwapClient> swap_client;
#if defined(OS_WIN)
scoped_ptr<AcceleratedSurface> accelerated_surface;
#endif
@@ -53,29 +60,30 @@ struct GpuProcessTransportFactory::PerCompositorData {
class OwnedTexture : public ui::Texture, ImageTransportFactoryObserver {
public:
- OwnedTexture(WebKit::WebGraphicsContext3D* host_context,
+ OwnedTexture(const scoped_refptr<ContextProvider>& provider,
const gfx::Size& size,
float device_scale_factor,
- unsigned int texture_id)
+ GLuint texture_id)
: ui::Texture(true, size, device_scale_factor),
- host_context_(host_context),
+ provider_(provider),
texture_id_(texture_id) {
ImageTransportFactory::GetInstance()->AddObserver(this);
}
// ui::Texture overrides:
virtual unsigned int PrepareTexture() OVERRIDE {
+ // It's possible that we may have lost the context owning our
+ // texture but not yet fired the OnLostResources callback, so poll to see if
+ // it's still valid.
+ if (provider_ && provider_->IsContextLost())
+ texture_id_ = 0u;
return texture_id_;
}
- virtual WebKit::WebGraphicsContext3D* HostContext3D() OVERRIDE {
- return host_context_;
- }
-
// ImageTransportFactory overrides:
virtual void OnLostResources() OVERRIDE {
DeleteTexture();
- host_context_ = NULL;
+ provider_ = NULL;
}
protected:
@@ -87,29 +95,27 @@ class OwnedTexture : public ui::Texture, ImageTransportFactoryObserver {
protected:
void DeleteTexture() {
if (texture_id_) {
- host_context_->deleteTexture(texture_id_);
+ provider_->ContextGL()->DeleteTextures(1, &texture_id_);
texture_id_ = 0;
}
}
- // The OnLostResources() callback will happen before this context
- // pointer is destroyed.
- WebKit::WebGraphicsContext3D* host_context_;
- unsigned texture_id_;
+ scoped_refptr<cc::ContextProvider> provider_;
+ GLuint texture_id_;
+ private:
DISALLOW_COPY_AND_ASSIGN(OwnedTexture);
};
class ImageTransportClientTexture : public OwnedTexture {
public:
- ImageTransportClientTexture(
- WebKit::WebGraphicsContext3D* host_context,
- float device_scale_factor)
- : OwnedTexture(host_context,
+ ImageTransportClientTexture(const scoped_refptr<ContextProvider>& provider,
+ float device_scale_factor,
+ GLuint texture_id)
+ : OwnedTexture(provider,
gfx::Size(0, 0),
device_scale_factor,
- host_context->createTexture()) {
- }
+ texture_id) {}
virtual void Consume(const std::string& mailbox_name,
const gfx::Size& new_size) OVERRIDE {
@@ -118,18 +124,16 @@ class ImageTransportClientTexture : public OwnedTexture {
if (mailbox_name.empty())
return;
- DCHECK(host_context_ && texture_id_);
- host_context_->bindTexture(GL_TEXTURE_2D, texture_id_);
- host_context_->consumeTextureCHROMIUM(
- GL_TEXTURE_2D,
- reinterpret_cast<const signed char*>(mailbox_name.c_str()));
+ DCHECK(provider_ && texture_id_);
+ GLES2Interface* gl = provider_->ContextGL();
+ gl->BindTexture(GL_TEXTURE_2D, texture_id_);
+ gl->ConsumeTextureCHROMIUM(
+ GL_TEXTURE_2D, reinterpret_cast<const GLbyte*>(mailbox_name.c_str()));
size_ = new_size;
- host_context_->shallowFlushCHROMIUM();
+ gl->ShallowFlushCHROMIUM();
}
- virtual std::string Produce() OVERRIDE {
- return mailbox_name_;
- }
+ virtual std::string Produce() OVERRIDE { return mailbox_name_; }
protected:
virtual ~ImageTransportClientTexture() {}
@@ -139,48 +143,6 @@ class ImageTransportClientTexture : public OwnedTexture {
DISALLOW_COPY_AND_ASSIGN(ImageTransportClientTexture);
};
-class CompositorSwapClient
- : public base::SupportsWeakPtr<CompositorSwapClient>,
- public WebGraphicsContext3DSwapBuffersClient {
- public:
- CompositorSwapClient(ui::Compositor* compositor,
- GpuProcessTransportFactory* factory)
- : compositor_(compositor),
- factory_(factory) {
- }
-
- virtual ~CompositorSwapClient() {
- }
-
- virtual void OnViewContextSwapBuffersPosted() OVERRIDE {
- compositor_->OnSwapBuffersPosted();
- }
-
- virtual void OnViewContextSwapBuffersComplete() OVERRIDE {
- compositor_->OnSwapBuffersComplete();
- }
-
- virtual void OnViewContextSwapBuffersAborted() OVERRIDE {
- // Recreating contexts directly from here causes issues, so post a task
- // instead.
- // TODO(piman): Fix the underlying issues.
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&CompositorSwapClient::OnLostContext, this->AsWeakPtr()));
- }
-
- private:
- void OnLostContext() {
- factory_->OnLostContext(compositor_);
- // Note: previous line destroyed this. Don't access members from now on.
- }
-
- ui::Compositor* compositor_;
- GpuProcessTransportFactory* factory_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorSwapClient);
-};
-
GpuProcessTransportFactory::GpuProcessTransportFactory()
: callback_factory_(this) {
output_surface_proxy_ = new BrowserCompositorOutputSurfaceProxy(
@@ -196,8 +158,7 @@ GpuProcessTransportFactory::~GpuProcessTransportFactory() {
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
GpuProcessTransportFactory::CreateOffscreenCommandBufferContext() {
- base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> swap_client;
- return CreateContextCommon(swap_client, 0);
+ return CreateContextCommon(0);
}
scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
@@ -205,6 +166,9 @@ scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
#if defined(OS_WIN)
return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceWin(
compositor));
+#elif defined(USE_OZONE)
+ return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceOzone(
+ compositor));
#elif defined(USE_X11)
return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceX11(
compositor));
@@ -215,20 +179,32 @@ scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
}
scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
- ui::Compositor* compositor) {
+ ui::Compositor* compositor, bool software_fallback) {
PerCompositorData* data = per_compositor_data_[compositor];
if (!data)
data = CreatePerCompositorData(compositor);
+ bool force_software_renderer = false;
+#if defined(OS_WIN)
+ if (::GetProp(compositor->widget(), kForceSoftwareCompositor)) {
+ force_software_renderer = reinterpret_cast<bool>(
+ ::RemoveProp(compositor->widget(), kForceSoftwareCompositor));
+ }
+#endif
+
scoped_refptr<ContextProviderCommandBuffer> context_provider;
+ // Software fallback does not happen on Chrome OS.
+#if defined(OS_CHROMEOS)
+ software_fallback = false;
+#endif
+
CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (!command_line->HasSwitch(switches::kUIEnableSoftwareCompositing)) {
+ if (!command_line->HasSwitch(switches::kUIEnableSoftwareCompositing) &&
+ !force_software_renderer && !software_fallback) {
context_provider = ContextProviderCommandBuffer::Create(
- GpuProcessTransportFactory::CreateContextCommon(
- data->swap_client->AsWeakPtr(),
- data->surface_id),
- "Compositor");
+ GpuProcessTransportFactory::CreateContextCommon(data->surface_id),
+ "Compositor");
}
UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor", !!context_provider);
@@ -239,9 +215,14 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
" compositing with browser threaded compositing. Aborting.";
}
- scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface =
- SoftwareBrowserCompositorOutputSurface::Create(
- CreateSoftwareOutputDevice(compositor));
+ scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface(
+ new SoftwareBrowserCompositorOutputSurface(
+ output_surface_proxy_,
+ CreateSoftwareOutputDevice(compositor),
+ per_compositor_data_[compositor]->surface_id,
+ &output_surface_map_,
+ base::MessageLoopProxy::current().get(),
+ compositor->AsWeakPtr()));
return surface.PassAs<cc::OutputSurface>();
}
@@ -256,7 +237,7 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
compositor_thread_task_runner.get());
scoped_ptr<BrowserCompositorOutputSurface> surface(
- new BrowserCompositorOutputSurface(
+ new GpuBrowserCompositorOutputSurface(
context_provider,
per_compositor_data_[compositor]->surface_id,
&output_surface_map_,
@@ -317,16 +298,17 @@ ui::ContextFactory* GpuProcessTransportFactory::AsContextFactory() {
}
gfx::GLSurfaceHandle GpuProcessTransportFactory::CreateSharedSurfaceHandle() {
- CreateSharedContextLazy();
- if (!shared_contexts_main_thread_ ||
- !shared_contexts_main_thread_->Context3d())
+ scoped_refptr<cc::ContextProvider> provider =
+ SharedMainThreadContextProvider();
+ if (!provider.get())
return gfx::GLSurfaceHandle();
+ typedef WebGraphicsContext3DCommandBufferImpl WGC3DCBI;
+ WGC3DCBI* context = static_cast<WGC3DCBI*>(provider->Context3d());
gfx::GLSurfaceHandle handle = gfx::GLSurfaceHandle(
gfx::kNullPluginWindow, gfx::TEXTURE_TRANSPORT);
- handle.parent_gpu_process_id =
- shared_contexts_main_thread_->Context3d()->GetGPUProcessID();
+ handle.parent_gpu_process_id = context->GetGPUProcessID();
handle.parent_client_id =
- shared_contexts_main_thread_->Context3d()->GetChannelID();
+ BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
return handle;
}
@@ -335,12 +317,15 @@ void GpuProcessTransportFactory::DestroySharedSurfaceHandle(
scoped_refptr<ui::Texture> GpuProcessTransportFactory::CreateTransportClient(
float device_scale_factor) {
- if (!shared_contexts_main_thread_.get())
+ scoped_refptr<cc::ContextProvider> provider =
+ SharedMainThreadContextProvider();
+ if (!provider.get())
return NULL;
+ GLuint texture_id = 0;
+ provider->ContextGL()->GenTextures(1, &texture_id);
scoped_refptr<ImageTransportClientTexture> image(
new ImageTransportClientTexture(
- shared_contexts_main_thread_->Context3d(),
- device_scale_factor));
+ provider, device_scale_factor, texture_id));
return image;
}
@@ -348,36 +333,40 @@ scoped_refptr<ui::Texture> GpuProcessTransportFactory::CreateOwnedTexture(
const gfx::Size& size,
float device_scale_factor,
unsigned int texture_id) {
- if (!shared_contexts_main_thread_.get())
+ scoped_refptr<cc::ContextProvider> provider =
+ SharedMainThreadContextProvider();
+ if (!provider.get())
return NULL;
scoped_refptr<OwnedTexture> image(new OwnedTexture(
- shared_contexts_main_thread_->Context3d(),
- size,
- device_scale_factor,
- texture_id));
+ provider, size, device_scale_factor, texture_id));
return image;
}
GLHelper* GpuProcessTransportFactory::GetGLHelper() {
if (!gl_helper_) {
- CreateSharedContextLazy();
- WebGraphicsContext3DCommandBufferImpl* context_for_main_thread =
- shared_contexts_main_thread_->Context3d();
- gl_helper_.reset(new GLHelper(context_for_main_thread));
+ scoped_refptr<cc::ContextProvider> provider =
+ SharedMainThreadContextProvider();
+ if (provider.get())
+ gl_helper_.reset(new GLHelper(provider->Context3d(),
+ provider->ContextSupport()));
}
return gl_helper_.get();
}
uint32 GpuProcessTransportFactory::InsertSyncPoint() {
- if (!shared_contexts_main_thread_.get())
+ scoped_refptr<cc::ContextProvider> provider =
+ SharedMainThreadContextProvider();
+ if (!provider.get())
return 0;
- return shared_contexts_main_thread_->Context3d()->insertSyncPoint();
+ return provider->Context3d()->insertSyncPoint();
}
void GpuProcessTransportFactory::WaitSyncPoint(uint32 sync_point) {
- if (!shared_contexts_main_thread_.get())
+ scoped_refptr<cc::ContextProvider> provider =
+ SharedMainThreadContextProvider();
+ if (!provider.get())
return;
- shared_contexts_main_thread_->Context3d()->waitSyncPoint(sync_point);
+ provider->Context3d()->waitSyncPoint(sync_point);
}
void GpuProcessTransportFactory::AddObserver(
@@ -391,50 +380,52 @@ void GpuProcessTransportFactory::RemoveObserver(
}
scoped_refptr<cc::ContextProvider>
-GpuProcessTransportFactory::OffscreenContextProviderForMainThread() {
+GpuProcessTransportFactory::OffscreenCompositorContextProvider() {
// Don't check for DestroyedOnMainThread() here. We hear about context
// loss for this context through the lost context callback. If the context
// is lost, we want to leave this ContextProvider available until the lost
// context notification is sent to the ImageTransportFactoryObserver clients.
- if (!shared_contexts_main_thread_.get()) {
- shared_contexts_main_thread_ = ContextProviderCommandBuffer::Create(
- GpuProcessTransportFactory::CreateOffscreenCommandBufferContext(),
- "Compositor-Offscreen-MainThread");
- if (shared_contexts_main_thread_) {
- shared_contexts_main_thread_->SetLostContextCallback(base::Bind(
- &GpuProcessTransportFactory::
- OnLostMainThreadSharedContextInsideCallback,
- callback_factory_.GetWeakPtr()));
-
- if (!shared_contexts_main_thread_->BindToCurrentThread())
- shared_contexts_main_thread_ = NULL;
- }
- }
- return shared_contexts_main_thread_;
+ if (offscreen_compositor_contexts_.get())
+ return offscreen_compositor_contexts_;
+
+ offscreen_compositor_contexts_ = ContextProviderCommandBuffer::Create(
+ GpuProcessTransportFactory::CreateOffscreenCommandBufferContext(),
+ "Compositor-Offscreen");
+
+ return offscreen_compositor_contexts_;
}
scoped_refptr<cc::ContextProvider>
-GpuProcessTransportFactory::OffscreenContextProviderForCompositorThread() {
- // The lifetime of this context is tied to the main thread context so that
- // they are always in the same share group. So do not check for
- // DestroyedOnMainThread().
- if (!shared_contexts_compositor_thread_.get()) {
- shared_contexts_compositor_thread_ = ContextProviderCommandBuffer::Create(
+GpuProcessTransportFactory::SharedMainThreadContextProvider() {
+ if (shared_main_thread_contexts_.get())
+ return shared_main_thread_contexts_;
+
+ if (ui::Compositor::WasInitializedWithThread()) {
+ // In threaded compositing mode, we have to create our own context for the
+ // main thread since the compositor's context will be bound to the
+ // compositor thread.
+ shared_main_thread_contexts_ = ContextProviderCommandBuffer::Create(
GpuProcessTransportFactory::CreateOffscreenCommandBufferContext(),
- "Compositor-Offscreen");
+ "Offscreen-MainThread");
+ } else {
+ // In single threaded compositing mode, we can just reuse the compositor's
+ // shared context.
+ shared_main_thread_contexts_ =
+ static_cast<ContextProviderCommandBuffer*>(
+ OffscreenCompositorContextProvider().get());
}
- return shared_contexts_compositor_thread_;
-}
-
-void GpuProcessTransportFactory::OnLostContext(ui::Compositor* compositor) {
- LOG(ERROR) << "Lost UI compositor context.";
- PerCompositorData* data = per_compositor_data_[compositor];
- DCHECK(data);
- // Prevent callbacks from other contexts in the same share group from
- // calling us again.
- data->swap_client.reset(new CompositorSwapClient(compositor, this));
- compositor->OnSwapBuffersAborted();
+ if (shared_main_thread_contexts_) {
+ shared_main_thread_contexts_->SetLostContextCallback(
+ base::Bind(&GpuProcessTransportFactory::
+ OnLostMainThreadSharedContextInsideCallback,
+ callback_factory_.GetWeakPtr()));
+ if (!shared_main_thread_contexts_->BindToCurrentThread()) {
+ shared_main_thread_contexts_ = NULL;
+ offscreen_compositor_contexts_ = NULL;
+ }
+ }
+ return shared_main_thread_contexts_;
}
GpuProcessTransportFactory::PerCompositorData*
@@ -442,14 +433,11 @@ GpuProcessTransportFactory::CreatePerCompositorData(
ui::Compositor* compositor) {
DCHECK(!per_compositor_data_[compositor]);
- CreateSharedContextLazy();
-
gfx::AcceleratedWidget widget = compositor->widget();
GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
PerCompositorData* data = new PerCompositorData;
data->surface_id = tracker->AddSurfaceForNativeWidget(widget);
- data->swap_client.reset(new CompositorSwapClient(compositor, this));
#if defined(OS_WIN)
if (GpuDataManagerImpl::GetInstance()->IsUsingAcceleratedSurface())
data->accelerated_surface.reset(new AcceleratedSurface(widget));
@@ -464,38 +452,33 @@ GpuProcessTransportFactory::CreatePerCompositorData(
}
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
-GpuProcessTransportFactory::CreateContextCommon(
- const base::WeakPtr<WebGraphicsContext3DSwapBuffersClient>& swap_client,
- int surface_id) {
+GpuProcessTransportFactory::CreateContextCommon(int surface_id) {
if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor())
return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
- WebKit::WebGraphicsContext3D::Attributes attrs;
+ blink::WebGraphicsContext3D::Attributes attrs;
attrs.shareResources = true;
attrs.depth = false;
attrs.stencil = false;
attrs.antialias = false;
attrs.noAutomaticFlushes = true;
- GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance();
+ CauseForGpuLaunch cause =
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
+ scoped_refptr<GpuChannelHost> gpu_channel_host(
+ BrowserGpuChannelHostFactory::instance()->EstablishGpuChannelSync(cause));
+ if (!gpu_channel_host)
+ return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
GURL url("chrome://gpu/GpuProcessTransportFactory::CreateContextCommon");
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
new WebGraphicsContext3DCommandBufferImpl(
surface_id,
url,
- factory,
- swap_client));
- if (!context->InitializeWithDefaultBufferSizes(
- attrs,
- false,
- CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE))
- return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
+ gpu_channel_host.get(),
+ attrs,
+ false,
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits()));
return context.Pass();
}
-void GpuProcessTransportFactory::CreateSharedContextLazy() {
- scoped_refptr<cc::ContextProvider> provider =
- OffscreenContextProviderForMainThread();
-}
-
void GpuProcessTransportFactory::OnLostMainThreadSharedContextInsideCallback() {
base::MessageLoop::current()->PostTask(
FROM_HERE,
@@ -510,13 +493,12 @@ void GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
// new resources are created if needed.
// Kill shared contexts for both threads in tandem so they are always in
// the same share group.
-
- scoped_refptr<cc::ContextProvider> lost_shared_contexts_main_thread =
- shared_contexts_main_thread_;
- scoped_refptr<cc::ContextProvider> lost_shared_contexts_compositor_thread =
- shared_contexts_compositor_thread_;
- shared_contexts_main_thread_ = NULL;
- shared_contexts_compositor_thread_ = NULL;
+ scoped_refptr<cc::ContextProvider> lost_offscreen_compositor_contexts =
+ offscreen_compositor_contexts_;
+ scoped_refptr<cc::ContextProvider> lost_shared_main_thread_contexts =
+ shared_main_thread_contexts_;
+ offscreen_compositor_contexts_ = NULL;
+ shared_main_thread_contexts_ = NULL;
scoped_ptr<GLHelper> lost_gl_helper = gl_helper_.Pass();
@@ -526,8 +508,8 @@ void GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
// Kill things that use the shared context before killing the shared context.
lost_gl_helper.reset();
- lost_shared_contexts_main_thread = NULL;
- lost_shared_contexts_compositor_thread = NULL;
+ lost_offscreen_compositor_contexts = NULL;
+ lost_shared_main_thread_contexts = NULL;
}
} // namespace content
diff --git a/chromium/content/browser/aura/gpu_process_transport_factory.h b/chromium/content/browser/aura/gpu_process_transport_factory.h
index 56d3e55498a..13da92b2539 100644
--- a/chromium/content/browser/aura/gpu_process_transport_factory.h
+++ b/chromium/content/browser/aura/gpu_process_transport_factory.h
@@ -22,7 +22,6 @@ class CompositorSwapClient;
class ContextProviderCommandBuffer;
class ReflectorImpl;
class WebGraphicsContext3DCommandBufferImpl;
-class WebGraphicsContext3DSwapBuffersClient;
class GpuProcessTransportFactory
: public ui::ContextFactory,
@@ -37,7 +36,7 @@ class GpuProcessTransportFactory
// ui::ContextFactory implementation.
virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(
- ui::Compositor* compositor) OVERRIDE;
+ ui::Compositor* compositor, bool software_fallback) OVERRIDE;
virtual scoped_refptr<ui::Reflector> CreateReflector(
ui::Compositor* source,
ui::Layer* target) OVERRIDE;
@@ -45,9 +44,9 @@ class GpuProcessTransportFactory
scoped_refptr<ui::Reflector> reflector) OVERRIDE;
virtual void RemoveCompositor(ui::Compositor* compositor) OVERRIDE;
virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForMainThread() OVERRIDE;
+ OffscreenCompositorContextProvider() OVERRIDE;
virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForCompositorThread() OVERRIDE;
+ SharedMainThreadContextProvider() OVERRIDE;
virtual bool DoesCreateTestContexts() OVERRIDE;
// ImageTransportFactory implementation.
@@ -68,26 +67,20 @@ class GpuProcessTransportFactory
virtual void RemoveObserver(
ImageTransportFactoryObserver* observer) OVERRIDE;
- void OnLostContext(ui::Compositor* compositor);
-
private:
struct PerCompositorData;
PerCompositorData* CreatePerCompositorData(ui::Compositor* compositor);
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContextCommon(
- const base::WeakPtr<WebGraphicsContext3DSwapBuffersClient>& swap_client,
- int surface_id);
-
- void CreateSharedContextLazy();
+ scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
+ CreateContextCommon(int surface_id);
void OnLostMainThreadSharedContextInsideCallback();
void OnLostMainThreadSharedContext();
typedef std::map<ui::Compositor*, PerCompositorData*> PerCompositorDataMap;
PerCompositorDataMap per_compositor_data_;
- scoped_refptr<ContextProviderCommandBuffer> shared_contexts_main_thread_;
- scoped_refptr<ContextProviderCommandBuffer>
- shared_contexts_compositor_thread_;
+ scoped_refptr<ContextProviderCommandBuffer> offscreen_compositor_contexts_;
+ scoped_refptr<ContextProviderCommandBuffer> shared_main_thread_contexts_;
scoped_ptr<GLHelper> gl_helper_;
ObserverList<ImageTransportFactoryObserver> observer_list_;
base::WeakPtrFactory<GpuProcessTransportFactory> callback_factory_;
diff --git a/chromium/content/browser/aura/image_transport_factory.cc b/chromium/content/browser/aura/image_transport_factory.cc
index e38ae880bbb..4a20e7d9af1 100644
--- a/chromium/content/browser/aura/image_transport_factory.cc
+++ b/chromium/content/browser/aura/image_transport_factory.cc
@@ -4,59 +4,32 @@
#include "content/browser/aura/image_transport_factory.h"
-#include "base/command_line.h"
#include "content/browser/aura/gpu_process_transport_factory.h"
#include "content/browser/aura/no_transport_image_transport_factory.h"
-#include "content/public/common/content_switches.h"
#include "ui/compositor/compositor.h"
-#include "ui/compositor/compositor_switches.h"
-
-#if defined(OS_CHROMEOS)
-#include "base/chromeos/chromeos_version.h"
-#endif
namespace content {
namespace {
-ImageTransportFactory* g_factory;
-}
-
-
-static bool UseTestContextAndTransportFactory() {
-#if defined(OS_CHROMEOS)
- // If the test is running on the chromeos envrionment (such as
- // device or vm bots), always use real contexts.
- if (base::chromeos::IsRunningOnChromeOS())
- return false;
-#endif
-
- // Only used if the enable command line flag is used.
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (!command_line->HasSwitch(switches::kTestCompositor))
- return false;
-
- // The disable command line flag preempts the enable flag.
- if (!command_line->HasSwitch(switches::kDisableTestCompositor))
- return true;
-
- return false;
+ImageTransportFactory* g_factory = NULL;
+bool g_initialized_for_unit_tests = false;
}
// static
void ImageTransportFactory::Initialize() {
- DCHECK(!g_factory);
- if (UseTestContextAndTransportFactory()) {
- g_factory =
- new NoTransportImageTransportFactory(new ui::TestContextFactory);
- } else {
- g_factory = new GpuProcessTransportFactory;
- }
+ DCHECK(!g_factory || g_initialized_for_unit_tests);
+ if (g_initialized_for_unit_tests)
+ return;
+ g_factory = new GpuProcessTransportFactory;
ui::ContextFactory::SetInstance(g_factory->AsContextFactory());
}
-void ImageTransportFactory::InitializeForUnitTests() {
+void ImageTransportFactory::InitializeForUnitTests(
+ scoped_ptr<ui::ContextFactory> test_factory) {
DCHECK(!g_factory);
- g_factory = new NoTransportImageTransportFactory(new ui::TestContextFactory);
+ DCHECK(!g_initialized_for_unit_tests);
+ g_initialized_for_unit_tests = true;
+ g_factory = new NoTransportImageTransportFactory(test_factory.Pass());
ui::ContextFactory::SetInstance(g_factory->AsContextFactory());
}
@@ -65,6 +38,7 @@ void ImageTransportFactory::Terminate() {
ui::ContextFactory::SetInstance(NULL);
delete g_factory;
g_factory = NULL;
+ g_initialized_for_unit_tests = false;
}
// static
diff --git a/chromium/content/browser/aura/image_transport_factory.h b/chromium/content/browser/aura/image_transport_factory.h
index 7cd2523c421..fecb4426edf 100644
--- a/chromium/content/browser/aura/image_transport_factory.h
+++ b/chromium/content/browser/aura/image_transport_factory.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "ui/gfx/native_widget_types.h"
@@ -20,7 +21,7 @@ class ContextFactory;
class Texture;
}
-namespace WebKit {
+namespace blink {
class WebGraphicsContext3D;
}
@@ -52,9 +53,10 @@ class CONTENT_EXPORT ImageTransportFactory {
// Initializes the global transport factory.
static void Initialize();
- // Initializes the global transport factory for unit tests, using a test
- // context.
- static void InitializeForUnitTests();
+ // Initializes the global transport factory for unit tests using the provided
+ // context factory.
+ static void InitializeForUnitTests(
+ scoped_ptr<ui::ContextFactory> test_factory);
// Terminates the global transport factory.
static void Terminate();
diff --git a/chromium/content/browser/aura/image_transport_factory_browsertest.cc b/chromium/content/browser/aura/image_transport_factory_browsertest.cc
new file mode 100644
index 00000000000..bf770a7e857
--- /dev/null
+++ b/chromium/content/browser/aura/image_transport_factory_browsertest.cc
@@ -0,0 +1,69 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/run_loop.h"
+#include "cc/output/context_provider.h"
+#include "content/browser/aura/image_transport_factory.h"
+#include "content/public/browser/gpu_data_manager.h"
+#include "content/test/content_browser_test.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "ui/compositor/compositor.h"
+
+namespace content {
+namespace {
+
+class ImageTransportFactoryBrowserTest : public ContentBrowserTest {
+ public:
+ ImageTransportFactoryBrowserTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ UseRealGLContexts();
+ ContentBrowserTest::SetUp();
+ }
+};
+
+class MockImageTransportFactoryObserver : public ImageTransportFactoryObserver {
+ public:
+ MOCK_METHOD0(OnLostResources, void());
+};
+
+// Checks that upon context loss, the observer is called and the created
+// resources are reset.
+IN_PROC_BROWSER_TEST_F(ImageTransportFactoryBrowserTest, TestLostContext) {
+ // This test doesn't make sense in software compositing mode.
+ if (!GpuDataManager::GetInstance()->CanUseGpuBrowserCompositor())
+ return;
+
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ scoped_refptr<ui::Texture> texture = factory->CreateTransportClient(1.f);
+ ASSERT_TRUE(texture.get());
+
+ MockImageTransportFactoryObserver observer;
+ factory->AddObserver(&observer);
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(observer, OnLostResources())
+ .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+
+ ui::ContextFactory* context_factory = ui::ContextFactory::GetInstance();
+
+ gpu::gles2::GLES2Interface* gl =
+ context_factory->SharedMainThreadContextProvider()->ContextGL();
+ gl->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
+ GL_INNOCENT_CONTEXT_RESET_ARB);
+
+ // We have to flush to make sure that the client side gets a chance to notice
+ // the context is gone.
+ gl->Flush();
+
+ run_loop.Run();
+ EXPECT_EQ(0u, texture->PrepareTexture());
+
+ factory->RemoveObserver(&observer);
+}
+
+} // anonymous namespace
+} // namespace content
diff --git a/chromium/content/browser/aura/no_transport_image_transport_factory.cc b/chromium/content/browser/aura/no_transport_image_transport_factory.cc
index 6fa80c69095..7f68e02edaa 100644
--- a/chromium/content/browser/aura/no_transport_image_transport_factory.cc
+++ b/chromium/content/browser/aura/no_transport_image_transport_factory.cc
@@ -22,9 +22,6 @@ class FakeTexture : public ui::Texture {
texture_(context_provider_->Context3d()->createTexture()) {}
virtual unsigned int PrepareTexture() OVERRIDE { return texture_; }
- virtual WebKit::WebGraphicsContext3D* HostContext3D() OVERRIDE {
- return context_provider_->Context3d();
- }
virtual void Consume(const std::string& mailbox_name,
const gfx::Size& new_size) OVERRIDE {
@@ -44,10 +41,8 @@ class FakeTexture : public ui::Texture {
} // anonymous namespace
NoTransportImageTransportFactory::NoTransportImageTransportFactory(
- ui::ContextFactory* context_factory)
- : context_factory_(context_factory),
- context_provider_(
- context_factory_->OffscreenContextProviderForMainThread()) {}
+ scoped_ptr<ui::ContextFactory> context_factory)
+ : context_factory_(context_factory.Pass()) {}
NoTransportImageTransportFactory::~NoTransportImageTransportFactory() {}
@@ -66,7 +61,8 @@ void NoTransportImageTransportFactory::DestroySharedSurfaceHandle(
scoped_refptr<ui::Texture>
NoTransportImageTransportFactory::CreateTransportClient(
float device_scale_factor) {
- return new FakeTexture(context_provider_, device_scale_factor);
+ return new FakeTexture(context_factory_->SharedMainThreadContextProvider(),
+ device_scale_factor);
}
scoped_refptr<ui::Texture> NoTransportImageTransportFactory::CreateOwnedTexture(
@@ -77,8 +73,11 @@ scoped_refptr<ui::Texture> NoTransportImageTransportFactory::CreateOwnedTexture(
}
GLHelper* NoTransportImageTransportFactory::GetGLHelper() {
- if (!gl_helper_)
- gl_helper_.reset(new GLHelper(context_provider_->Context3d()));
+ if (!gl_helper_) {
+ context_provider_ = context_factory_->SharedMainThreadContextProvider();
+ gl_helper_.reset(new GLHelper(context_provider_->Context3d(),
+ context_provider_->ContextSupport()));
+ }
return gl_helper_.get();
}
diff --git a/chromium/content/browser/aura/no_transport_image_transport_factory.h b/chromium/content/browser/aura/no_transport_image_transport_factory.h
index 0d571643afd..dd551d97d53 100644
--- a/chromium/content/browser/aura/no_transport_image_transport_factory.h
+++ b/chromium/content/browser/aura/no_transport_image_transport_factory.h
@@ -18,7 +18,7 @@ namespace content {
class NoTransportImageTransportFactory : public ImageTransportFactory {
public:
explicit NoTransportImageTransportFactory(
- ui::ContextFactory* context_factory);
+ scoped_ptr<ui::ContextFactory> context_factory);
virtual ~NoTransportImageTransportFactory();
// ImageTransportFactory implementation.
diff --git a/chromium/content/browser/aura/owned_mailbox.cc b/chromium/content/browser/aura/owned_mailbox.cc
new file mode 100644
index 00000000000..1a99d335ac2
--- /dev/null
+++ b/chromium/content/browser/aura/owned_mailbox.cc
@@ -0,0 +1,42 @@
+// 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/aura/owned_mailbox.h"
+
+#include "base/logging.h"
+#include "content/browser/aura/image_transport_factory.h"
+#include "content/common/gpu/client/gl_helper.h"
+
+namespace content {
+
+OwnedMailbox::OwnedMailbox(GLHelper* gl_helper)
+ : texture_id_(0), sync_point_(0), gl_helper_(gl_helper) {
+ texture_id_ = gl_helper_->CreateTexture();
+ mailbox_ = gl_helper_->ProduceMailboxFromTexture(texture_id_, &sync_point_);
+ ImageTransportFactory::GetInstance()->AddObserver(this);
+}
+
+OwnedMailbox::~OwnedMailbox() {
+ ImageTransportFactory::GetInstance()->RemoveObserver(this);
+ if (gl_helper_) {
+ gl_helper_->WaitSyncPoint(sync_point_);
+ gl_helper_->DeleteTexture(texture_id_);
+ }
+}
+
+void OwnedMailbox::UpdateSyncPoint(uint32 sync_point) {
+ if (sync_point)
+ sync_point_ = sync_point;
+}
+
+void OwnedMailbox::OnLostResources() {
+ gl_helper_->WaitSyncPoint(sync_point_);
+ gl_helper_->DeleteTexture(texture_id_);
+ texture_id_ = 0;
+ mailbox_ = gpu::Mailbox();
+ sync_point_ = 0;
+ gl_helper_ = NULL;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/aura/owned_mailbox.h b/chromium/content/browser/aura/owned_mailbox.h
new file mode 100644
index 00000000000..ea1c242bf74
--- /dev/null
+++ b/chromium/content/browser/aura/owned_mailbox.h
@@ -0,0 +1,41 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/ref_counted.h"
+#include "content/browser/aura/image_transport_factory.h"
+#include "gpu/command_buffer/common/mailbox.h"
+
+namespace content {
+
+class GLHelper;
+
+// This class holds a texture id and gpu::Mailbox, and deletes the texture
+// id when the object itself is destroyed. Should only be created if a GLHelper
+// exists on the ImageTransportFactory.
+class OwnedMailbox : public base::RefCounted<OwnedMailbox>,
+ public ImageTransportFactoryObserver {
+ public:
+ explicit OwnedMailbox(GLHelper* gl_helper);
+
+ uint32 texture_id() const { return texture_id_; }
+ uint32 sync_point() const { return sync_point_; }
+ const gpu::Mailbox& mailbox() const { return mailbox_; }
+
+ void UpdateSyncPoint(uint32 sync_point);
+
+ protected:
+ virtual ~OwnedMailbox();
+
+ virtual void OnLostResources() OVERRIDE;
+
+ private:
+ friend class base::RefCounted<OwnedMailbox>;
+
+ uint32 texture_id_;
+ gpu::Mailbox mailbox_;
+ uint32 sync_point_;
+ GLHelper* gl_helper_;
+};
+
+} // namespace content
diff --git a/chromium/content/browser/aura/reflector_impl.cc b/chromium/content/browser/aura/reflector_impl.cc
index 78726ecdcc2..08f7b0d11ff 100644
--- a/chromium/content/browser/aura/reflector_impl.cc
+++ b/chromium/content/browser/aura/reflector_impl.cc
@@ -33,7 +33,19 @@ ReflectorImpl::ReflectorImpl(
}
void ReflectorImpl::InitOnImplThread() {
- AttachToOutputSurface(output_surface_map_->Lookup(surface_id_));
+ // Ignore if the reflector was shutdown before
+ // initialized, or it's already initialized.
+ if (!output_surface_map_ || gl_helper_.get())
+ return;
+
+ BrowserCompositorOutputSurface* source_surface =
+ output_surface_map_->Lookup(surface_id_);
+ // Skip if the source surface isn't ready yet. This will be
+ // initiailze when the source surface becomes ready.
+ if (!source_surface)
+ return;
+
+ AttachToOutputSurface(source_surface);
gl_helper_->CopyTextureFullImage(texture_id_, texture_size_);
// The shared texture doesn't have the data, so invokes full redraw
// now.
@@ -43,6 +55,11 @@ void ReflectorImpl::InitOnImplThread() {
scoped_refptr<ReflectorImpl>(this)));
}
+void ReflectorImpl::OnSourceSurfaceReady(int surface_id) {
+ DCHECK_EQ(surface_id_, surface_id);
+ InitOnImplThread();
+}
+
void ReflectorImpl::Shutdown() {
mirroring_compositor_ = NULL;
mirroring_layer_ = NULL;
@@ -55,7 +72,9 @@ void ReflectorImpl::Shutdown() {
void ReflectorImpl::ShutdownOnImplThread() {
BrowserCompositorOutputSurface* output_surface =
output_surface_map_->Lookup(surface_id_);
- output_surface->SetReflector(NULL);
+ if (output_surface)
+ output_surface->SetReflector(NULL);
+ output_surface_map_ = NULL;
gl_helper_.reset();
// The instance must be deleted on main thread.
main_message_loop_->PostTask(
@@ -69,7 +88,8 @@ void ReflectorImpl::ShutdownOnImplThread() {
void ReflectorImpl::AttachToOutputSurface(
BrowserCompositorOutputSurface* output_surface) {
gl_helper_.reset(
- new GLHelper(output_surface->context_provider()->Context3d()));
+ new GLHelper(output_surface->context_provider()->Context3d(),
+ output_surface->context_provider()->ContextSupport()));
output_surface->SetReflector(this);
}
@@ -79,7 +99,7 @@ void ReflectorImpl::OnMirroringCompositorResized() {
void ReflectorImpl::OnLostResources() {
shared_texture_ = NULL;
- mirroring_layer_->SetExternalTexture(NULL);
+ mirroring_layer_->SetShowPaintedContent();
}
void ReflectorImpl::OnReshape(gfx::Size size) {
diff --git a/chromium/content/browser/aura/reflector_impl.h b/chromium/content/browser/aura/reflector_impl.h
index b24acffd404..e5b5128accf 100644
--- a/chromium/content/browser/aura/reflector_impl.h
+++ b/chromium/content/browser/aura/reflector_impl.h
@@ -75,6 +75,9 @@ class ReflectorImpl : public ImageTransportFactoryObserver,
// race with ImplThread accessing |texture_id_|.
void CreateSharedTexture();
+ // Called when the source surface is bound and available. This must
+ // be called on ImplThread.
+ void OnSourceSurfaceReady(int surface_id);
private:
virtual ~ReflectorImpl();
diff --git a/chromium/content/browser/aura/software_browser_compositor_output_surface.cc b/chromium/content/browser/aura/software_browser_compositor_output_surface.cc
index 1f92582841e..070a6365d9f 100644
--- a/chromium/content/browser/aura/software_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/aura/software_browser_compositor_output_surface.cc
@@ -4,23 +4,55 @@
#include "content/browser/aura/software_browser_compositor_output_surface.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/software_output_device.h"
+#include "content/browser/aura/browser_compositor_output_surface_proxy.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "ui/events/latency_info.h"
+#include "ui/gfx/vsync_provider.h"
namespace content {
SoftwareBrowserCompositorOutputSurface::SoftwareBrowserCompositorOutputSurface(
- scoped_ptr<cc::SoftwareOutputDevice> software_device)
- : cc::OutputSurface(software_device.Pass()) {}
+ scoped_refptr<BrowserCompositorOutputSurfaceProxy> surface_proxy,
+ scoped_ptr<cc::SoftwareOutputDevice> software_device,
+ int surface_id,
+ IDMap<BrowserCompositorOutputSurface>* output_surface_map,
+ base::MessageLoopProxy* compositor_message_loop,
+ base::WeakPtr<ui::Compositor> compositor)
+ : BrowserCompositorOutputSurface(software_device.Pass(),
+ surface_id,
+ output_surface_map,
+ compositor_message_loop,
+ compositor),
+ output_surface_proxy_(surface_proxy) {}
+
+SoftwareBrowserCompositorOutputSurface::
+ ~SoftwareBrowserCompositorOutputSurface() {}
void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
cc::CompositorFrame* frame) {
ui::LatencyInfo latency_info = frame->metadata.latency_info;
- latency_info.swap_timestamp = base::TimeTicks::HighResNow();
- RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
+ latency_info.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
+
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &RenderWidgetHostImpl::CompositorFrameDrawn,
+ latency_info));
+
+ gfx::VSyncProvider* vsync_provider = software_device()->GetVSyncProvider();
+ if (vsync_provider) {
+ vsync_provider->GetVSyncParameters(
+ base::Bind(&BrowserCompositorOutputSurfaceProxy::
+ OnUpdateVSyncParametersOnCompositorThread,
+ output_surface_proxy_,
+ surface_id_));
+ }
}
} // namespace content
diff --git a/chromium/content/browser/aura/software_browser_compositor_output_surface.h b/chromium/content/browser/aura/software_browser_compositor_output_surface.h
index ac499da5eb2..79c7901f055 100644
--- a/chromium/content/browser/aura/software_browser_compositor_output_surface.h
+++ b/chromium/content/browser/aura/software_browser_compositor_output_surface.h
@@ -2,32 +2,49 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_SURFACE_H_
-#define CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_SURFACE_H_
+#ifndef CONTENT_BROWSER_AURA_SOFTWARE_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
+#define CONTENT_BROWSER_AURA_SOFTWARE_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
-#include "cc/output/output_surface.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/aura/browser_compositor_output_surface.h"
+#include "content/common/content_export.h"
+#include "ui/compositor/compositor.h"
-namespace cc { class SoftwareOutputDevice; }
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace cc {
+class SoftwareOutputDevice;
+}
namespace content {
-// TODO(danakj): Inherit from BrowserCompositorOutputSurface to share stuff like
-// reflectors, when we split the GL-specific stuff out of the class.
-class SoftwareBrowserCompositorOutputSurface : public cc::OutputSurface {
+class BrowserCompositorOutputSurfaceProxy;
+
+class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
+ : public BrowserCompositorOutputSurface {
public:
- static scoped_ptr<SoftwareBrowserCompositorOutputSurface> Create(
- scoped_ptr<cc::SoftwareOutputDevice> software_device) {
- return make_scoped_ptr(
- new SoftwareBrowserCompositorOutputSurface(software_device.Pass()));
- }
+ SoftwareBrowserCompositorOutputSurface(
+ scoped_refptr<BrowserCompositorOutputSurfaceProxy> surface_proxy,
+ scoped_ptr<cc::SoftwareOutputDevice> software_device,
+ int surface_id,
+ IDMap<BrowserCompositorOutputSurface>* output_surface_map,
+ base::MessageLoopProxy* compositor_message_loop,
+ base::WeakPtr<ui::Compositor> compositor);
- private:
- explicit SoftwareBrowserCompositorOutputSurface(
- scoped_ptr<cc::SoftwareOutputDevice> software_device);
+ virtual ~SoftwareBrowserCompositorOutputSurface();
+ private:
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
+
+ // On the software path we need to explicitly call the proxy to update the
+ // VSync parameters.
+ scoped_refptr<BrowserCompositorOutputSurfaceProxy> output_surface_proxy_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareBrowserCompositorOutputSurface);
};
} // namespace content
-#endif // CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_SURFACE_H_
+#endif // CONTENT_BROWSER_AURA_SOFTWARE_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
diff --git a/chromium/content/browser/aura/software_browser_compositor_output_surface_unittest.cc b/chromium/content/browser/aura/software_browser_compositor_output_surface_unittest.cc
new file mode 100644
index 00000000000..1d05295cb81
--- /dev/null
+++ b/chromium/content/browser/aura/software_browser_compositor_output_surface_unittest.cc
@@ -0,0 +1,147 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_loop.h"
+#include "cc/output/compositor_frame.h"
+#include "content/browser/aura/browser_compositor_output_surface_proxy.h"
+#include "content/browser/aura/software_browser_compositor_output_surface.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/compositor/test/context_factories_for_test.h"
+#include "ui/gfx/vsync_provider.h"
+#include "ui/gl/gl_implementation.h"
+
+namespace {
+
+class FakeVSyncProvider : public gfx::VSyncProvider {
+ public:
+ FakeVSyncProvider() : call_count_(0) {}
+ virtual ~FakeVSyncProvider() {}
+
+ virtual void GetVSyncParameters(const UpdateVSyncCallback& callback)
+ OVERRIDE {
+ callback.Run(timebase_, interval_);
+ call_count_++;
+ }
+
+ int call_count() const { return call_count_; }
+
+ void set_timebase(base::TimeTicks timebase) { timebase_ = timebase; }
+ void set_interval(base::TimeDelta interval) { interval_ = interval; }
+
+ private:
+ base::TimeTicks timebase_;
+ base::TimeDelta interval_;
+
+ int call_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeVSyncProvider);
+};
+
+class FakeSoftwareOutputDevice : public cc::SoftwareOutputDevice {
+ public:
+ FakeSoftwareOutputDevice() : vsync_provider_(new FakeVSyncProvider()) {}
+ virtual ~FakeSoftwareOutputDevice() {}
+
+ virtual gfx::VSyncProvider* GetVSyncProvider() OVERRIDE {
+ return vsync_provider_.get();
+ }
+
+ private:
+ scoped_ptr<gfx::VSyncProvider> vsync_provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeSoftwareOutputDevice);
+};
+
+} // namespace
+
+class SoftwareBrowserCompositorOutputSurfaceTest : public testing::Test {
+ public:
+ SoftwareBrowserCompositorOutputSurfaceTest();
+ virtual ~SoftwareBrowserCompositorOutputSurfaceTest();
+
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ scoped_ptr<content::BrowserCompositorOutputSurface> CreateSurface(
+ scoped_ptr<cc::SoftwareOutputDevice> device);
+
+ protected:
+ scoped_ptr<content::BrowserCompositorOutputSurface> output_surface_;
+
+ scoped_ptr<base::MessageLoop> message_loop_;
+ scoped_ptr<ui::Compositor> compositor_;
+
+ IDMap<content::BrowserCompositorOutputSurface> surface_map_;
+ scoped_refptr<content::BrowserCompositorOutputSurfaceProxy> surface_proxy_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareBrowserCompositorOutputSurfaceTest);
+};
+
+SoftwareBrowserCompositorOutputSurfaceTest::
+ SoftwareBrowserCompositorOutputSurfaceTest() {
+ CHECK(gfx::InitializeGLBindings(gfx::kGLImplementationOSMesaGL));
+ message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
+}
+
+SoftwareBrowserCompositorOutputSurfaceTest::
+ ~SoftwareBrowserCompositorOutputSurfaceTest() {}
+
+void SoftwareBrowserCompositorOutputSurfaceTest::SetUp() {
+ ui::InitializeContextFactoryForTests(false);
+ ui::Compositor::Initialize();
+
+ compositor_.reset(new ui::Compositor(gfx::kNullAcceleratedWidget));
+ surface_proxy_ =
+ new content::BrowserCompositorOutputSurfaceProxy(&surface_map_);
+}
+
+void SoftwareBrowserCompositorOutputSurfaceTest::TearDown() {
+ output_surface_.reset();
+ compositor_.reset();
+
+ EXPECT_TRUE(surface_map_.IsEmpty());
+
+ surface_map_.Clear();
+ ui::TerminateContextFactoryForTests();
+ ui::Compositor::Terminate();
+}
+
+scoped_ptr<content::BrowserCompositorOutputSurface>
+SoftwareBrowserCompositorOutputSurfaceTest::CreateSurface(
+ scoped_ptr<cc::SoftwareOutputDevice> device) {
+ return scoped_ptr<content::BrowserCompositorOutputSurface>(
+ new content::SoftwareBrowserCompositorOutputSurface(
+ surface_proxy_,
+ device.Pass(),
+ 1,
+ &surface_map_,
+ compositor_->GetCompositorMessageLoop(),
+ compositor_->AsWeakPtr()));
+}
+
+TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, NoVSyncProvider) {
+ scoped_ptr<cc::SoftwareOutputDevice> software_device(
+ new cc::SoftwareOutputDevice());
+ output_surface_ = CreateSurface(software_device.Pass());
+
+ cc::CompositorFrame frame;
+ output_surface_->SwapBuffers(&frame);
+
+ EXPECT_EQ(NULL, output_surface_->software_device()->GetVSyncProvider());
+}
+
+TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, VSyncProviderUpdates) {
+ scoped_ptr<cc::SoftwareOutputDevice> software_device(
+ new FakeSoftwareOutputDevice());
+ output_surface_ = CreateSurface(software_device.Pass());
+
+ FakeVSyncProvider* vsync_provider = static_cast<FakeVSyncProvider*>(
+ output_surface_->software_device()->GetVSyncProvider());
+ EXPECT_EQ(0, vsync_provider->call_count());
+
+ cc::CompositorFrame frame;
+ output_surface_->SwapBuffers(&frame);
+
+ EXPECT_EQ(1, vsync_provider->call_count());
+}
diff --git a/chromium/content/browser/aura/software_output_device_ozone.cc b/chromium/content/browser/aura/software_output_device_ozone.cc
new file mode 100644
index 00000000000..661ab50716d
--- /dev/null
+++ b/chromium/content/browser/aura/software_output_device_ozone.cc
@@ -0,0 +1,73 @@
+// 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/aura/software_output_device_ozone.h"
+#include "third_party/skia/include/core/SkBitmapDevice.h"
+#include "third_party/skia/include/core/SkDevice.h"
+#include "ui/compositor/compositor.h"
+#include "ui/gfx/ozone/surface_factory_ozone.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/gfx/vsync_provider.h"
+
+namespace content {
+
+SoftwareOutputDeviceOzone::SoftwareOutputDeviceOzone(ui::Compositor* compositor)
+ : compositor_(compositor), realized_widget_(gfx::kNullAcceleratedWidget) {
+ gfx::SurfaceFactoryOzone* factory = gfx::SurfaceFactoryOzone::GetInstance();
+
+ if (factory->InitializeHardware() != gfx::SurfaceFactoryOzone::INITIALIZED)
+ LOG(FATAL) << "Failed to initialize hardware in OZONE";
+
+ realized_widget_ = factory->RealizeAcceleratedWidget(compositor_->widget());
+
+ if (realized_widget_ == gfx::kNullAcceleratedWidget)
+ LOG(FATAL) << "Failed to get a realized AcceleratedWidget";
+
+ vsync_provider_.reset(factory->GetVSyncProvider(realized_widget_));
+}
+
+SoftwareOutputDeviceOzone::~SoftwareOutputDeviceOzone() {
+}
+
+void SoftwareOutputDeviceOzone::Resize(gfx::Size viewport_size) {
+ if (viewport_size_ == viewport_size)
+ return;
+
+ viewport_size_ = viewport_size;
+ gfx::Rect bounds(viewport_size_);
+
+ gfx::SurfaceFactoryOzone* factory = gfx::SurfaceFactoryOzone::GetInstance();
+ factory->AttemptToResizeAcceleratedWidget(compositor_->widget(),
+ bounds);
+
+ canvas_ = skia::SharePtr(factory->GetCanvasForWidget(realized_widget_));
+ device_ = skia::SharePtr(canvas_->getDevice());
+}
+
+SkCanvas* SoftwareOutputDeviceOzone::BeginPaint(gfx::Rect damage_rect) {
+ DCHECK(gfx::Rect(viewport_size_).Contains(damage_rect));
+
+ canvas_->clipRect(gfx::RectToSkRect(damage_rect), SkRegion::kReplace_Op);
+ // Save the current state so we can restore once we're done drawing. This is
+ // saved after the clip since we want to keep the clip information after we're
+ // done drawing such that OZONE knows what was updated.
+ canvas_->save();
+
+ return SoftwareOutputDevice::BeginPaint(damage_rect);
+}
+
+void SoftwareOutputDeviceOzone::EndPaint(cc::SoftwareFrameData* frame_data) {
+ SoftwareOutputDevice::EndPaint(frame_data);
+
+ canvas_->restore();
+
+ if (damage_rect_.IsEmpty())
+ return;
+
+ bool scheduled = gfx::SurfaceFactoryOzone::GetInstance()->SchedulePageFlip(
+ compositor_->widget());
+ DCHECK(scheduled) << "Failed to schedule pageflip";
+}
+
+} // namespace content
diff --git a/chromium/content/browser/aura/software_output_device_ozone.h b/chromium/content/browser/aura/software_output_device_ozone.h
new file mode 100644
index 00000000000..7ebf430f323
--- /dev/null
+++ b/chromium/content/browser/aura/software_output_device_ozone.h
@@ -0,0 +1,41 @@
+// 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_AURA_SOFTWARE_OUTPUT_DEVICE_OZONE_H_
+#define CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_DEVICE_OZONE_H_
+
+#include "cc/output/software_output_device.h"
+#include "content/common/content_export.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace ui {
+class Compositor;
+}
+
+namespace content {
+
+// Ozone implementation which relies on software rendering. Ozone will present
+// an accelerated widget as a SkCanvas. SoftwareOutputDevice will then use the
+// Ozone provided canvas to draw.
+class CONTENT_EXPORT SoftwareOutputDeviceOzone
+ : public cc::SoftwareOutputDevice {
+ public:
+ explicit SoftwareOutputDeviceOzone(ui::Compositor* compositor);
+ virtual ~SoftwareOutputDeviceOzone();
+
+ virtual void Resize(gfx::Size viewport_size) OVERRIDE;
+ virtual SkCanvas* BeginPaint(gfx::Rect damage_rect) OVERRIDE;
+ virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
+
+ private:
+ ui::Compositor* compositor_;
+
+ gfx::AcceleratedWidget realized_widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceOzone);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_DEVICE_OZONE_H_
diff --git a/chromium/content/browser/aura/software_output_device_ozone_unittest.cc b/chromium/content/browser/aura/software_output_device_ozone_unittest.cc
new file mode 100644
index 00000000000..6469995f6ec
--- /dev/null
+++ b/chromium/content/browser/aura/software_output_device_ozone_unittest.cc
@@ -0,0 +1,195 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "cc/output/software_frame_data.h"
+#include "content/browser/aura/software_output_device_ozone.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmapDevice.h"
+#include "ui/compositor/compositor.h"
+#include "ui/compositor/test/context_factories_for_test.h"
+#include "ui/gfx/ozone/surface_factory_ozone.h"
+#include "ui/gfx/size.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/gl/gl_implementation.h"
+
+namespace {
+
+class MockSurfaceFactoryOzone : public gfx::SurfaceFactoryOzone {
+ public:
+ MockSurfaceFactoryOzone() {}
+ virtual ~MockSurfaceFactoryOzone() {}
+
+ virtual HardwareState InitializeHardware() OVERRIDE {
+ return SurfaceFactoryOzone::INITIALIZED;
+ }
+
+ virtual void ShutdownHardware() OVERRIDE {}
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE { return 1; }
+ virtual gfx::AcceleratedWidget RealizeAcceleratedWidget(
+ gfx::AcceleratedWidget w) OVERRIDE { return w; }
+ virtual bool LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) OVERRIDE {
+ return false;
+ }
+ virtual bool AttemptToResizeAcceleratedWidget(
+ gfx::AcceleratedWidget w, const gfx::Rect& bounds) OVERRIDE {
+ device_ = skia::AdoptRef(new SkBitmapDevice(SkBitmap::kARGB_8888_Config,
+ bounds.width(),
+ bounds.height(),
+ true));
+ canvas_ = skia::AdoptRef(new SkCanvas(device_.get()));
+ return true;
+ }
+ virtual SkCanvas* GetCanvasForWidget(gfx::AcceleratedWidget w) OVERRIDE {
+ return canvas_.get();
+ }
+ virtual gfx::VSyncProvider* GetVSyncProvider(
+ gfx::AcceleratedWidget w) OVERRIDE {
+ return NULL;
+ }
+ private:
+ skia::RefPtr<SkBitmapDevice> device_;
+ skia::RefPtr<SkCanvas> canvas_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockSurfaceFactoryOzone);
+};
+
+} // namespace
+
+class SoftwareOutputDeviceOzoneTest : public testing::Test {
+ public:
+ SoftwareOutputDeviceOzoneTest();
+ virtual ~SoftwareOutputDeviceOzoneTest();
+
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ protected:
+ scoped_ptr<content::SoftwareOutputDeviceOzone> output_device_;
+
+ private:
+ scoped_ptr<ui::Compositor> compositor_;
+ scoped_ptr<base::MessageLoop> message_loop_;
+ scoped_ptr<gfx::SurfaceFactoryOzone> surface_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceOzoneTest);
+};
+
+SoftwareOutputDeviceOzoneTest::SoftwareOutputDeviceOzoneTest() {
+ CHECK(gfx::InitializeGLBindings(gfx::kGLImplementationOSMesaGL));
+ message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
+}
+
+SoftwareOutputDeviceOzoneTest::~SoftwareOutputDeviceOzoneTest() {
+}
+
+void SoftwareOutputDeviceOzoneTest::SetUp() {
+ ui::InitializeContextFactoryForTests(false);
+ ui::Compositor::Initialize();
+
+ surface_factory_.reset(new MockSurfaceFactoryOzone());
+ gfx::SurfaceFactoryOzone::SetInstance(surface_factory_.get());
+
+ const gfx::Size size(500, 400);
+ compositor_.reset(new ui::Compositor(
+ gfx::SurfaceFactoryOzone::GetInstance()->GetAcceleratedWidget()));
+ compositor_->SetScaleAndSize(1.0f, size);
+
+ output_device_.reset(new content::SoftwareOutputDeviceOzone(
+ compositor_.get()));
+ output_device_->Resize(size);
+}
+
+void SoftwareOutputDeviceOzoneTest::TearDown() {
+ output_device_.reset();
+ compositor_.reset();
+ surface_factory_.reset();
+ ui::TerminateContextFactoryForTests();
+ ui::Compositor::Terminate();
+}
+
+TEST_F(SoftwareOutputDeviceOzoneTest, CheckClipAfterBeginPaint) {
+ gfx::Rect damage(10, 10, 100, 100);
+ SkCanvas* canvas = output_device_->BeginPaint(damage);
+
+ SkIRect sk_bounds;
+ canvas->getClipDeviceBounds(&sk_bounds);
+
+ EXPECT_EQ(damage.ToString(), gfx::SkIRectToRect(sk_bounds).ToString());
+}
+
+TEST_F(SoftwareOutputDeviceOzoneTest, CheckClipAfterSecondBeginPaint) {
+ gfx::Rect damage(10, 10, 100, 100);
+ SkCanvas* canvas = output_device_->BeginPaint(damage);
+
+ cc::SoftwareFrameData frame;
+ output_device_->EndPaint(&frame);
+
+ damage = gfx::Rect(100, 100, 100, 100);
+ canvas = output_device_->BeginPaint(damage);
+ SkIRect sk_bounds;
+ canvas->getClipDeviceBounds(&sk_bounds);
+
+ EXPECT_EQ(damage.ToString(), gfx::SkIRectToRect(sk_bounds).ToString());
+}
+
+TEST_F(SoftwareOutputDeviceOzoneTest, CheckCorrectResizeBehavior) {
+ gfx::Rect damage(0, 0, 100, 100);
+ gfx::Size size(200, 100);
+ // Reduce size.
+ output_device_->Resize(size);
+
+ SkCanvas* canvas = output_device_->BeginPaint(damage);
+ gfx::Size canvas_size(canvas->getDeviceSize().width(),
+ canvas->getDeviceSize().height());
+ EXPECT_EQ(size.ToString(), canvas_size.ToString());
+
+ size.SetSize(1000, 500);
+ // Increase size.
+ output_device_->Resize(size);
+
+ canvas = output_device_->BeginPaint(damage);
+ canvas_size.SetSize(canvas->getDeviceSize().width(),
+ canvas->getDeviceSize().height());
+ EXPECT_EQ(size.ToString(), canvas_size.ToString());
+
+}
+
+TEST_F(SoftwareOutputDeviceOzoneTest, CheckCopyToBitmap) {
+ const gfx::Rect area(6, 4);
+ output_device_->Resize(area.size());
+ SkCanvas* canvas = output_device_->BeginPaint(area);
+
+ // Clear the background to black.
+ canvas->drawColor(SK_ColorBLACK);
+
+ cc::SoftwareFrameData frame;
+ output_device_->EndPaint(&frame);
+
+ // Draw a white rectangle.
+ gfx::Rect damage(area.width() / 2, area.height() / 2);
+ canvas = output_device_->BeginPaint(damage);
+
+ canvas->drawColor(SK_ColorWHITE);
+
+ output_device_->EndPaint(&frame);
+
+ SkBitmap bitmap;
+ output_device_->CopyToBitmap(area, &bitmap);
+
+ SkAutoLockPixels pixel_lock(bitmap);
+ // Check that the copied bitmap contains the same pixel values as what we
+ // painted.
+ for (int i = 0; i < area.height(); ++i) {
+ for (int j = 0; j < area.width(); ++j) {
+ if (j < damage.width() && i < damage.height())
+ EXPECT_EQ(SK_ColorWHITE, bitmap.getColor(j, i));
+ else
+ EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(j, i));
+ }
+ }
+}
diff --git a/chromium/content/browser/aura/software_output_device_win.cc b/chromium/content/browser/aura/software_output_device_win.cc
index 7937810e2ba..f8d6d9b6d70 100644
--- a/chromium/content/browser/aura/software_output_device_win.cc
+++ b/chromium/content/browser/aura/software_output_device_win.cc
@@ -36,7 +36,7 @@ void SoftwareOutputDeviceWin::Resize(gfx::Size viewport_size) {
return;
viewport_size_ = viewport_size;
- contents_.reset(new gfx::Canvas(viewport_size, ui::SCALE_FACTOR_100P, true));
+ contents_.reset(new gfx::Canvas(viewport_size, 1.0f, true));
memset(&bitmap_info_, 0, sizeof(bitmap_info_));
gfx::CreateBitmapHeader(viewport_size_.width(), viewport_size_.height(),
&bitmap_info_.bmiHeader);
diff --git a/chromium/content/browser/browser_child_process_host_impl.cc b/chromium/content/browser/browser_child_process_host_impl.cc
index 5cc953281d3..42615723344 100644
--- a/chromium/content/browser/browser_child_process_host_impl.cc
+++ b/chromium/content/browser/browser_child_process_host_impl.cc
@@ -100,9 +100,9 @@ BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
data_.id = ChildProcessHostImpl::GenerateChildProcessUniqueId();
child_process_host_.reset(ChildProcessHost::Create(this));
- child_process_host_->AddFilter(new TraceMessageFilter);
- child_process_host_->AddFilter(new ProfilerMessageFilter(process_type));
- child_process_host_->AddFilter(new HistogramMessageFilter());
+ AddFilter(new TraceMessageFilter);
+ AddFilter(new ProfilerMessageFilter(process_type));
+ AddFilter(new HistogramMessageFilter);
g_child_process_list.Get().push_back(this);
GetContentClient()->browser()->BrowserChildProcessHostCreated(this);
@@ -192,7 +192,7 @@ base::ProcessHandle BrowserChildProcessHostImpl::GetHandle() const {
return child_process_->GetHandle();
}
-void BrowserChildProcessHostImpl::SetName(const string16& name) {
+void BrowserChildProcessHostImpl::SetName(const base::string16& name) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
data_.name = name;
}
@@ -218,6 +218,10 @@ void BrowserChildProcessHostImpl::SetTerminateChildOnShutdown(
child_process_->SetTerminateChildOnShutdown(terminate_on_shutdown);
}
+void BrowserChildProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
+ child_process_host_->AddFilter(filter->GetFilter());
+}
+
void BrowserChildProcessHostImpl::NotifyProcessInstanceCreated(
const ChildProcessData& data) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
diff --git a/chromium/content/browser/browser_child_process_host_impl.h b/chromium/content/browser/browser_child_process_host_impl.h
index 7540209f5cc..428da3ddaf5 100644
--- a/chromium/content/browser/browser_child_process_host_impl.h
+++ b/chromium/content/browser/browser_child_process_host_impl.h
@@ -21,6 +21,7 @@ namespace content {
class BrowserChildProcessHostIterator;
class BrowserChildProcessObserver;
+class BrowserMessageFilter;
// 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
@@ -53,7 +54,7 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
virtual ChildProcessHost* GetHost() const OVERRIDE;
virtual base::TerminationStatus GetTerminationStatus(
bool known_dead, int* exit_code) OVERRIDE;
- virtual void SetName(const string16& name) OVERRIDE;
+ virtual void SetName(const base::string16& name) OVERRIDE;
virtual void SetHandle(base::ProcessHandle handle) OVERRIDE;
// Returns the handle of the child process. This can be called only after
@@ -70,6 +71,9 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
// shutdown. Default is to always terminate.
void SetTerminateChildOnShutdown(bool terminate_on_shutdown);
+ // Adds an IPC message filter.
+ void AddFilter(BrowserMessageFilter* filter);
+
// Called when an instance of a particular child is created in a page.
static void NotifyProcessInstanceCreated(const ChildProcessData& data);
diff --git a/chromium/content/browser/browser_context.cc b/chromium/content/browser/browser_context.cc
index 2e76dc00ad5..b720ae48014 100644
--- a/chromium/content/browser/browser_context.cc
+++ b/chromium/content/browser/browser_context.cc
@@ -36,9 +36,12 @@ namespace {
// Key names on BrowserContext.
const char kDownloadManagerKeyName[] = "download_manager";
-const char kMountPointsKey[] = "mount_points";
const char kStorageParitionMapKeyName[] = "content_storage_partition_map";
+#if defined(OS_CHROMEOS)
+const char kMountPointsKey[] = "mount_points";
+#endif // defined(OS_CHROMEOS)
+
StoragePartitionImplMap* GetStoragePartitionMap(
BrowserContext* browser_context) {
StoragePartitionImplMap* partition_map =
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index 14dd61410bc..1930bc083a7 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -34,19 +34,21 @@
#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/media/media_internals.h"
#include "content/browser/net/browser_online_state_observer.h"
#include "content/browser/plugin_service_impl.h"
#include "content/browser/renderer_host/media/audio_mirroring_manager.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/speech/speech_recognition_manager_impl.h"
#include "content/browser/startup_task_runner.h"
-#include "content/browser/tracing/trace_controller_impl.h"
#include "content/browser/webui/content_web_ui_controller_factory.h"
#include "content/browser/webui/url_data_manager.h"
#include "content/public/browser/browser_main_parts.h"
#include "content/public/browser/browser_shutdown.h"
#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_switches.h"
#include "content/public/common/main_function_params.h"
#include "content/public/common/result_codes.h"
@@ -70,6 +72,10 @@
#include "content/browser/android/surface_texture_peer_browser_impl.h"
#endif
+#if defined(OS_MACOSX)
+#include "content/browser/theme_helper_mac.h"
+#endif
+
#if defined(OS_WIN)
#include <windows.h>
#include <commctrl.h>
@@ -82,12 +88,12 @@
#include "ui/base/l10n/l10n_util_win.h"
#endif
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#if defined(USE_GLIB)
#include <glib-object.h>
#endif
-#if defined(OS_LINUX)
-#include "content/browser/device_monitor_linux.h"
+#if defined(OS_LINUX) && defined(USE_UDEV)
+#include "content/browser/device_monitor_udev.h"
#elif defined(OS_MACOSX) && !defined(OS_IOS)
#include "content/browser/device_monitor_mac.h"
#endif
@@ -175,7 +181,7 @@ void SetupSandbox(const CommandLine& parsed_command_line) {
}
#endif
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#if defined(USE_GLIB)
static void GLibLogHandler(const gchar* log_domain,
GLogLevelFlags log_level,
const gchar* message,
@@ -313,7 +319,10 @@ BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters)
: parameters_(parameters),
parsed_command_line_(parameters.command_line),
result_code_(RESULT_CODE_NORMAL_EXIT),
- created_threads_(false) {
+ created_threads_(false),
+ // ContentMainRunner should have enabled tracing of the browser process
+ // when kTraceStartup is in the command line.
+ is_tracing_startup_(base::debug::TraceLog::GetInstance()->IsEnabled()) {
DCHECK(!g_current_browser_main_loop);
g_current_browser_main_loop = this;
}
@@ -336,6 +345,13 @@ void BrowserMainLoop::Init() {
void BrowserMainLoop::EarlyInitialization() {
TRACE_EVENT0("startup", "BrowserMainLoop::EarlyInitialization");
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+ // No thread should be created before this call, as SetupSandbox()
+ // will end-up using fork().
+ SetupSandbox(parsed_command_line_);
+#endif
+
#if defined(USE_X11)
if (parsed_command_line_.HasSwitch(switches::kSingleProcess) ||
parsed_command_line_.HasSwitch(switches::kInProcessGPU)) {
@@ -345,6 +361,29 @@ void BrowserMainLoop::EarlyInitialization() {
}
#endif
+ // GLib's spawning of new processes is buggy, so it's important that at this
+ // point GLib does not need to start DBUS. Chrome should always start with
+ // DBUS_SESSION_BUS_ADDRESS properly set. See crbug.com/309093.
+#if defined(USE_GLIB)
+ // g_type_init will be deprecated in 2.36. 2.35 is the development
+ // version for 2.36, hence do not call g_type_init starting 2.35.
+ // http://developer.gnome.org/gobject/unstable/gobject-Type-Information.html#g-type-init
+#if !GLIB_CHECK_VERSION(2, 35, 0)
+ // GLib type system initialization. Needed at least for gconf,
+ // used in net/proxy/proxy_config_service_linux.cc. Most likely
+ // this is superfluous as gtk_init() ought to do this. It's
+ // definitely harmless, so retained as a reminder of this
+ // requirement for gconf.
+ g_type_init();
+#endif
+
+#if !defined(USE_AURA)
+ gfx::GtkInitFromCommandLine(parsed_command_line_);
+#endif
+
+ SetUpGLibLogHandler();
+#endif
+
if (parts_)
parts_->PreEarlyInitialization();
@@ -357,10 +396,6 @@ void BrowserMainLoop::EarlyInitialization() {
crypto::EnsureNSPRInit();
#endif // !defined(USE_OPENSSL)
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
- SetupSandbox(parsed_command_line_);
-#endif
-
if (parsed_command_line_.HasSwitch(switches::kEnableSSLCachedInfo))
net::SSLConfigService::EnableCachedInfo();
@@ -428,7 +463,8 @@ void BrowserMainLoop::MainMessageLoopStart() {
}
{
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:AudioMan")
- audio_manager_.reset(media::AudioManager::Create());
+ audio_manager_.reset(media::AudioManager::Create(
+ MediaInternals::GetInstance()));
}
{
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MIDIManager")
@@ -446,10 +482,9 @@ void BrowserMainLoop::MainMessageLoopStart() {
}
// Start tracing to a file if needed.
- if (base::debug::TraceLog::GetInstance()->IsEnabled()) {
+ if (is_tracing_startup_) {
TRACE_EVENT0("startup", "BrowserMainLoop::InitStartupTracing")
- TraceControllerImpl::GetInstance()->InitStartupTracing(
- parsed_command_line_);
+ InitStartupTracing(parsed_command_line_);
}
{
@@ -699,7 +734,6 @@ void BrowserMainLoop::RunMainMessageLoopParts() {
}
void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
-
if (!created_threads_) {
// Called early, nothing to do
return;
@@ -714,6 +748,9 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
true));
+ if (RenderProcessHost::run_renderer_in_process())
+ RenderProcessHostImpl::ShutDownInProcessRenderer();
+
if (parts_) {
TRACE_EVENT0("shutdown",
"BrowserMainLoop::Subsystem:PostMainMessageLoopRun");
@@ -747,6 +784,10 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
}
#endif
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+ ZygoteHostImpl::GetInstance()->TearDownAfterLastChild();
+#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+
// The device monitors are using |system_monitor_| as dependency, so delete
// them before |system_monitor_| goes away.
// On Mac and windows, the monitor needs to be destroyed on the same thread
@@ -849,7 +890,8 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
// it.
{
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:GPUChannelFactory");
- BrowserGpuChannelHostFactory::Terminate();
+ if (BrowserGpuChannelHostFactory::instance())
+ BrowserGpuChannelHostFactory::Terminate();
}
// Must happen after the I/O thread is shutdown since this class lives on the
@@ -906,12 +948,29 @@ int BrowserMainLoop::BrowserThreadsStarted() {
#if !defined(OS_IOS)
HistogramSynchronizer::GetInstance();
- BrowserGpuChannelHostFactory::Initialize();
+ // Initialize the GpuDataManager before we set up the MessageLoops because
+ // otherwise we'll trigger the assertion about doing IO on the UI thread.
+ GpuDataManagerImpl::GetInstance()->Initialize();
+
+ bool always_uses_gpu = IsForceCompositingModeEnabled();
+ bool established_gpu_channel = false;
+#if defined(USE_AURA) || defined(OS_ANDROID)
+ established_gpu_channel =
+ !parsed_command_line_.HasSwitch(switches::kDisableGpuProcessPrelaunch) ||
+ parsed_command_line_.HasSwitch(switches::kSingleProcess) ||
+ parsed_command_line_.HasSwitch(switches::kInProcessGPU);
#if defined(USE_AURA)
+ if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
+ established_gpu_channel = always_uses_gpu = false;
+ }
+ BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
ImageTransportFactory::Initialize();
+#elif defined(OS_ANDROID)
+ BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
+#endif
#endif
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) && defined(USE_UDEV)
device_monitor_linux_.reset(new DeviceMonitorLinux());
#elif defined(OS_MACOSX)
device_monitor_mac_.reset(new DeviceMonitorMac());
@@ -931,10 +990,6 @@ int BrowserMainLoop::BrowserThreadsStarted() {
media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
}
- // Initialize the GpuDataManager before we set up the MessageLoops because
- // otherwise we'll trigger the assertion about doing IO on the UI thread.
- GpuDataManagerImpl::GetInstance()->Initialize();
-
{
TRACE_EVENT0("startup",
"BrowserMainLoop::BrowserThreadsStarted:InitSpeechRecognition");
@@ -965,12 +1020,8 @@ int BrowserMainLoop::BrowserThreadsStarted() {
// When running the GPU thread in-process, avoid optimistically starting it
// since creating the GPU thread races against creation of the one-and-only
// ChildProcess instance which is created by the renderer thread.
- bool always_uses_gpu = IsForceCompositingModeEnabled();
-#if defined(USE_AURA)
- if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor())
- always_uses_gpu = false;
-#endif
if (GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL) &&
+ !established_gpu_channel &&
always_uses_gpu &&
!parsed_command_line_.HasSwitch(switches::kDisableGpuProcessPrelaunch) &&
!parsed_command_line_.HasSwitch(switches::kSingleProcess) &&
@@ -984,6 +1035,10 @@ int BrowserMainLoop::BrowserThreadsStarted() {
CAUSE_FOR_GPU_LAUNCH_BROWSER_STARTUP));
}
#endif // !defined(OS_IOS)
+
+#if defined(OS_MACOSX)
+ ThemeHelperMac::GetInstance();
+#endif
return result_code_;
}
@@ -994,25 +1049,7 @@ void BrowserMainLoop::InitializeToolkit() {
// are no #else branches on any #ifs.
// TODO(stevenjb): Move platform specific code into platform specific Parts
// (Need to add InitializeToolkit stage to BrowserParts).
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
- // g_type_init will be deprecated in 2.36. 2.35 is the development
- // version for 2.36, hence do not call g_type_init starting 2.35.
- // http://developer.gnome.org/gobject/unstable/gobject-Type-Information.html#g-type-init
-#if !GLIB_CHECK_VERSION(2, 35, 0)
- // Glib type system initialization. Needed at least for gconf,
- // used in net/proxy/proxy_config_service_linux.cc. Most likely
- // this is superfluous as gtk_init() ought to do this. It's
- // definitely harmless, so retained as a reminder of this
- // requirement for gconf.
- g_type_init();
-#endif
-
-#if !defined(USE_AURA)
- gfx::GtkInitFromCommandLine(parsed_command_line_);
-#endif
-
- SetUpGLibLogHandler();
-#endif
+ // See also GTK setup in EarlyInitialization, above, and associated comments.
#if defined(TOOLKIT_GTK)
// It is important for this to happen before the first run dialog, as it
@@ -1048,4 +1085,42 @@ void BrowserMainLoop::MainMessageLoopRun() {
#endif
}
+void BrowserMainLoop::InitStartupTracing(const CommandLine& command_line) {
+ DCHECK(is_tracing_startup_);
+
+ base::FilePath trace_file = command_line.GetSwitchValuePath(
+ switches::kTraceStartupFile);
+ // trace_file = "none" means that startup events will show up for the next
+ // begin/end tracing (via about:tracing or AutomationProxy::BeginTracing/
+ // EndTracing, for example).
+ if (trace_file == base::FilePath().AppendASCII("none"))
+ return;
+
+ if (trace_file.empty()) {
+ // Default to saving the startup trace into the current dir.
+ trace_file = base::FilePath().AppendASCII("chrometrace.log");
+ }
+
+ std::string delay_str = command_line.GetSwitchValueASCII(
+ switches::kTraceStartupDuration);
+ int delay_secs = 5;
+ if (!delay_str.empty() && !base::StringToInt(delay_str, &delay_secs)) {
+ DLOG(WARNING) << "Could not parse --" << switches::kTraceStartupDuration
+ << "=" << delay_str << " defaulting to 5 (secs)";
+ delay_secs = 5;
+ }
+
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&BrowserMainLoop::EndStartupTracing,
+ base::Unretained(this), trace_file),
+ base::TimeDelta::FromSeconds(delay_secs));
+}
+
+void BrowserMainLoop::EndStartupTracing(const base::FilePath& trace_file) {
+ is_tracing_startup_ = false;
+ TracingController::GetInstance()->DisableRecording(
+ trace_file, TracingController::TracingFileResultCallback());
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index 821da872755..445d99050ef 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -14,6 +14,7 @@
class CommandLine;
namespace base {
+class FilePath;
class HighResolutionTimerManager;
class MessageLoop;
class PowerMonitor;
@@ -98,6 +99,8 @@ class CONTENT_EXPORT BrowserMainLoop {
media::MIDIManager* midi_manager() const { return midi_manager_.get(); }
base::Thread* indexed_db_thread() const { return indexed_db_thread_.get(); }
+ bool is_tracing_startup() const { return is_tracing_startup_; }
+
private:
class MemoryObserver;
// For ShutdownThreadsAndCleanUp.
@@ -118,6 +121,9 @@ class CONTENT_EXPORT BrowserMainLoop {
void MainMessageLoopRun();
+ void InitStartupTracing(const CommandLine& command_line);
+ void EndStartupTracing(const base::FilePath& trace_file);
+
// Members initialized on construction ---------------------------------------
const MainFunctionParams& parameters_;
const CommandLine& parsed_command_line_;
@@ -141,7 +147,7 @@ class CONTENT_EXPORT BrowserMainLoop {
scoped_ptr<BrowserOnlineStateObserver> online_state_observer_;
#if defined(OS_WIN)
scoped_ptr<SystemMessageWindowWin> system_message_window_;
-#elif defined(OS_LINUX)
+#elif defined(USE_UDEV)
scoped_ptr<DeviceMonitorLinux> device_monitor_linux_;
#elif defined(OS_MACOSX) && !defined(OS_IOS)
scoped_ptr<DeviceMonitorMac> device_monitor_mac_;
@@ -173,6 +179,8 @@ class CONTENT_EXPORT BrowserMainLoop {
scoped_ptr<base::debug::TraceMemoryController> trace_memory_controller_;
scoped_ptr<base::debug::TraceEventSystemStatsMonitor> system_stats_monitor_;
+ bool is_tracing_startup_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserMainLoop);
};
diff --git a/chromium/content/browser/browser_main_runner.cc b/chromium/content/browser/browser_main_runner.cc
index 27fb6fcff58..b2610b751af 100644
--- a/chromium/content/browser/browser_main_runner.cc
+++ b/chromium/content/browser/browser_main_runner.cc
@@ -7,6 +7,7 @@
#include "base/allocator/allocator_shim.h"
#include "base/base_switches.h"
#include "base/command_line.h"
+#include "base/debug/leak_annotations.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
@@ -125,6 +126,14 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
virtual void Shutdown() OVERRIDE {
DCHECK(initialization_started_);
DCHECK(!is_shutdown_);
+#ifdef LEAK_SANITIZER
+ // Invoke leak detection now, to avoid dealing with shutdown-only leaks.
+ // Normally this will have already happened in
+ // BroserProcessImpl::ReleaseModule(), so this call has no effect. This is
+ // only for processes which do not instantiate a BrowserProcess.
+ // If leaks are found, the process will exit here.
+ __lsan_do_leak_check();
+#endif
// The shutdown tracing got enabled in AttemptUserExit earlier, but someone
// needs to write the result to disc. For that a dumper needs to get created
// which will dump the traces to disc when it gets destroyed.
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
index 1f673ba520f..18bfc25c3b4 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
@@ -8,6 +8,7 @@
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
#include "content/browser/browser_plugin/browser_plugin_host_factory.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/browser_plugin/browser_plugin_constants.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
@@ -16,11 +17,13 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/native_web_keyboard_event.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "net/base/escape.h"
+#include "ui/events/keycodes/keyboard_codes.h"
namespace content {
@@ -78,15 +81,58 @@ void BrowserPluginEmbedder::GetRenderViewHostAtPosition(
++next_get_render_view_request_id_;
}
+bool BrowserPluginEmbedder::DidSendScreenRectsCallback(
+ BrowserPluginGuest* guest) {
+ static_cast<RenderViewHostImpl*>(
+ guest->GetWebContents()->GetRenderViewHost())->SendScreenRects();
+ // Not handled => Iterate over all guests.
+ return false;
+}
+
void BrowserPluginEmbedder::DidSendScreenRects() {
- GetBrowserPluginGuestManager()->DidSendScreenRects(
- static_cast<WebContentsImpl*>(web_contents()));
+ WebContentsImpl* embedder =
+ static_cast<WebContentsImpl*>(web_contents());
+ GetBrowserPluginGuestManager()->ForEachGuest(embedder, base::Bind(
+ &BrowserPluginEmbedder::DidSendScreenRectsCallback,
+ base::Unretained(this)));
+}
+
+bool BrowserPluginEmbedder::UnlockMouseIfNecessaryCallback(
+ const NativeWebKeyboardEvent& event,
+ BrowserPluginGuest* guest) {
+ return guest->UnlockMouseIfNecessary(event);
}
bool BrowserPluginEmbedder::HandleKeyboardEvent(
const NativeWebKeyboardEvent& event) {
- return GetBrowserPluginGuestManager()->UnlockMouseIfNecessary(
- static_cast<WebContentsImpl*>(web_contents()), event);
+ if ((event.type != blink::WebInputEvent::RawKeyDown) ||
+ (event.windowsKeyCode != ui::VKEY_ESCAPE) ||
+ (event.modifiers & blink::WebInputEvent::InputModifiers)) {
+ return false;
+ }
+
+ WebContentsImpl* embedder =
+ static_cast<WebContentsImpl*>(web_contents());
+ return GetBrowserPluginGuestManager()->ForEachGuest(embedder, base::Bind(
+ &BrowserPluginEmbedder::UnlockMouseIfNecessaryCallback,
+ base::Unretained(this),
+ event));
+}
+
+bool BrowserPluginEmbedder::SetZoomLevelCallback(
+ double level, BrowserPluginGuest* guest) {
+ guest->GetWebContents()->SetZoomLevel(level);
+ // Not handled => Iterate over all guests.
+ return false;
+}
+
+void BrowserPluginEmbedder::SetZoomLevel(double level) {
+ WebContentsImpl* embedder =
+ static_cast<WebContentsImpl*>(web_contents());
+ GetBrowserPluginGuestManager()->ForEachGuest(embedder, base::Bind(
+ &BrowserPluginEmbedder::SetZoomLevelCallback,
+ base::Unretained(this),
+ level));
}
void BrowserPluginEmbedder::RenderProcessGone(base::TerminationStatus status) {
@@ -109,7 +155,7 @@ bool BrowserPluginEmbedder::OnMessageReceived(const IPC::Message& message) {
}
void BrowserPluginEmbedder::DragSourceEndedAt(int client_x, int client_y,
- int screen_x, int screen_y, WebKit::WebDragOperation operation) {
+ int screen_x, int screen_y, blink::WebDragOperation operation) {
if (guest_started_drag_.get()) {
gfx::Point guest_offset =
guest_started_drag_->GetScreenCoordinates(gfx::Point());
@@ -177,7 +223,6 @@ void BrowserPluginEmbedder::OnAttach(
GetBrowserPluginGuestManager()->GetGuestByInstanceID(
instance_id, web_contents()->GetRenderProcessHost()->GetID());
-
if (guest) {
// There is an implicit order expectation here:
// 1. The content embedder is made aware of the attachment.
@@ -203,7 +248,7 @@ void BrowserPluginEmbedder::OnAttach(
guest->GetWebContents(),
web_contents(),
extra_params);
- guest->Initialize(static_cast<WebContentsImpl*>(web_contents()), params);
+ guest->Initialize(params, static_cast<WebContentsImpl*>(web_contents()));
}
}
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.h b/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
index 52610632f59..107fa618686 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
@@ -67,12 +67,15 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
factory_ = factory;
}
+ // Sets the zoom level for all guests within this embedder.
+ void SetZoomLevel(double level);
+
// WebContentsObserver implementation.
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
void DragSourceEndedAt(int client_x, int client_y, int screen_x,
- int screen_y, WebKit::WebDragOperation operation);
+ int screen_y, blink::WebDragOperation operation);
void DragSourceMovedTo(int client_x, int client_y,
int screen_x, int screen_y);
@@ -98,6 +101,13 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
BrowserPluginGuestManager* GetBrowserPluginGuestManager();
+ bool DidSendScreenRectsCallback(BrowserPluginGuest* guest);
+
+ bool SetZoomLevelCallback(double level, BrowserPluginGuest* guest);
+
+ bool UnlockMouseIfNecessaryCallback(const NativeWebKeyboardEvent& event,
+ BrowserPluginGuest* guest);
+
// Message handlers.
void OnAllocateInstanceID(int request_id);
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index 19e7eba3d44..9668d227c51 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -10,7 +10,6 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
-#include "content/browser/browser_plugin/browser_plugin_guest_helper.h"
#include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
#include "content/browser/browser_plugin/browser_plugin_host_factory.h"
#include "content/browser/browser_thread_impl.h"
@@ -28,15 +27,16 @@
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/port/browser/render_view_host_delegate_view.h"
+#include "content/port/browser/render_widget_host_view_port.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/geolocation_permission_context.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
+#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/resource_request_details.h"
#include "content/public/browser/user_metrics.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/drop_data.h"
#include "content/public/common/media_stream_request.h"
@@ -44,7 +44,7 @@
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "net/url_request/url_request.h"
-#include "third_party/WebKit/public/web/WebCursorInfo.h"
+#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/surface/transport_dib.h"
#include "webkit/common/resource_type.h"
@@ -64,6 +64,9 @@ class BrowserPluginGuest::PermissionRequest :
public base::RefCounted<BrowserPluginGuest::PermissionRequest> {
public:
virtual void Respond(bool should_allow, const std::string& user_input) = 0;
+ virtual bool AllowedByDefault() const {
+ return false;
+ }
protected:
PermissionRequest() {
RecordAction(UserMetricsAction("BrowserPlugin.Guest.PermissionRequest"));
@@ -193,7 +196,7 @@ class BrowserPluginGuest::NewWindowRequest : public PermissionRequest {
guest_->GetWebContents()->GetBrowserPluginGuestManager()->
GetGuestByInstanceID(instance_id_, embedder_render_process_id);
if (!guest) {
- LOG(INFO) << "Guest not found. Instance ID: " << instance_id_;
+ VLOG(0) << "Guest not found. Instance ID: " << instance_id_;
return;
}
@@ -213,8 +216,7 @@ class BrowserPluginGuest::JavaScriptDialogRequest : public PermissionRequest {
JavaScriptDialogRequest(const DialogClosedCallback& callback)
: callback_(callback) {
RecordAction(
- UserMetricsAction(
- "BrowserPlugin.Guest.PermissionRequest.JavaScriptDialog"));
+ UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.JSDialog"));
}
virtual void Respond(bool should_allow,
@@ -247,8 +249,6 @@ class BrowserPluginGuest::PointerLockRequest : public PermissionRequest {
};
namespace {
-const size_t kNumMaxOutstandingPermissionRequests = 1024;
-
std::string WindowOpenDispositionToString(
WindowOpenDisposition window_open_disposition) {
switch (window_open_disposition) {
@@ -298,40 +298,46 @@ static std::string RetrieveDownloadURLFromRequestId(
ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
if (url_request)
return url_request->url().possibly_invalid_spec();
- return std::string();
+ return "";
}
} // namespace
-class BrowserPluginGuest::EmbedderRenderViewHostObserver
- : public RenderViewHostObserver {
+class BrowserPluginGuest::EmbedderWebContentsObserver
+ : public WebContentsObserver {
public:
- explicit EmbedderRenderViewHostObserver(BrowserPluginGuest* guest)
- : RenderViewHostObserver(
- guest->embedder_web_contents()->GetRenderViewHost()),
+ explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest)
+ : WebContentsObserver(guest->embedder_web_contents()),
browser_plugin_guest_(guest) {
}
- virtual ~EmbedderRenderViewHostObserver() {
+ virtual ~EmbedderWebContentsObserver() {
}
- // RenderViewHostObserver:
- virtual void RenderViewHostDestroyed(
- RenderViewHost* render_view_host) OVERRIDE {
+ // WebContentsObserver:
+ virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
browser_plugin_guest_->EmbedderDestroyed();
}
+ virtual void WasShown() OVERRIDE {
+ browser_plugin_guest_->EmbedderVisibilityChanged(true);
+ }
+
+ virtual void WasHidden() OVERRIDE {
+ browser_plugin_guest_->EmbedderVisibilityChanged(false);
+ }
+
private:
BrowserPluginGuest* browser_plugin_guest_;
- DISALLOW_COPY_AND_ASSIGN(EmbedderRenderViewHostObserver);
+ DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver);
};
BrowserPluginGuest::BrowserPluginGuest(
int instance_id,
+ bool has_render_view,
WebContentsImpl* web_contents,
- BrowserPluginGuest* opener,
- bool has_render_view)
+ BrowserPluginGuest* opener)
: WebContentsObserver(web_contents),
weak_ptr_factory_(this),
embedder_web_contents_(NULL),
@@ -346,6 +352,7 @@ BrowserPluginGuest::BrowserPluginGuest(
mouse_locked_(false),
pending_lock_request_(false),
embedder_visible_(true),
+ copy_request_id_(0),
next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID),
has_render_view_(has_render_view),
last_seen_auto_size_enabled_(false),
@@ -360,9 +367,9 @@ BrowserPluginGuest::BrowserPluginGuest(
bool BrowserPluginGuest::AddMessageToConsole(WebContents* source,
int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id) {
+ const base::string16& source_id) {
if (!delegate_)
return false;
@@ -382,7 +389,22 @@ void BrowserPluginGuest::DestroyUnattachedWindows() {
}
// All pending windows should be removed from the set after Destroy() is
// called on all of them.
- DCHECK_EQ(0ul, pending_new_windows_.size());
+ DCHECK(pending_new_windows_.empty());
+}
+
+void BrowserPluginGuest::LoadURLWithParams(const GURL& url,
+ const Referrer& referrer,
+ PageTransition transition_type,
+ WebContents* web_contents) {
+ NavigationController::LoadURLParams load_url_params(url);
+ load_url_params.referrer = referrer;
+ load_url_params.transition_type = transition_type;
+ load_url_params.extra_headers = std::string();
+ if (delegate_ && delegate_->IsOverridingUserAgent()) {
+ load_url_params.override_user_agent =
+ NavigationController::UA_OVERRIDE_TRUE;
+ }
+ web_contents->GetController().LoadURLWithParams(load_url_params);
}
void BrowserPluginGuest::RespondToPermissionRequest(
@@ -391,7 +413,7 @@ void BrowserPluginGuest::RespondToPermissionRequest(
const std::string& user_input) {
RequestMap::iterator request_itr = permission_request_map_.find(request_id);
if (request_itr == permission_request_map_.end()) {
- LOG(INFO) << "Not a valid request ID.";
+ VLOG(0) << "Not a valid request ID.";
return;
}
request_itr->second->Respond(should_allow, user_input);
@@ -415,9 +437,12 @@ int BrowserPluginGuest::RequestPermission(
AsWeakPtr(),
request_id);
// If BrowserPluginGuestDelegate hasn't handled the permission then we simply
- // reject it immediately.
- if (!delegate_->RequestPermission(permission_type, request_info, callback))
- callback.Run(false, "");
+ // perform the default action (which is one of allow or reject) immediately.
+ if (!delegate_->RequestPermission(
+ permission_type, request_info, callback, request->AllowedByDefault())) {
+ callback.Run(request->AllowedByDefault(), "");
+ return browser_plugin::kInvalidPermissionRequestID;
+ }
return request_id;
}
@@ -454,11 +479,8 @@ BrowserPluginGuest* BrowserPluginGuest::CreateNewGuestWindow(
std::make_pair(new_guest, NewWindowInfo(params.url, std::string())));
// Request permission to show the new window.
- RequestNewWindowPermission(
- new_guest->GetWebContents(),
- params.disposition,
- gfx::Rect(),
- params.user_gesture);
+ RequestNewWindowPermission(params.disposition, gfx::Rect(),
+ params.user_gesture, new_guest->GetWebContents());
return new_guest;
}
@@ -487,21 +509,33 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
OnSwapBuffersACK)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameACK,
OnCompositorFrameACK)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
+ OnCopyFromCompositingSurfaceAck)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
OnDragStatusUpdate)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
OnExecuteEditCommand)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete,
+ OnExtendSelectionAndDelete)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
OnHandleInputEvent)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition,
+ OnImeConfirmComposition)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition,
+ OnImeSetComposition)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_NavigateGuest, OnNavigateGuest)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources,
+ OnReclaimCompositorResources)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetSize)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
OnSetEditCommandsForNextKeyEvent)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetName, OnSetName)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque,
+ OnSetContentsOpaque)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry)
@@ -512,10 +546,11 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
}
void BrowserPluginGuest::Initialize(
- WebContentsImpl* embedder_web_contents,
- const BrowserPluginHostMsg_Attach_Params& params) {
+ const BrowserPluginHostMsg_Attach_Params& params,
+ WebContentsImpl* embedder_web_contents) {
focused_ = params.focused;
guest_visible_ = params.visible;
+ guest_opaque_ = params.opaque;
guest_window_rect_ = params.resize_guest_params.view_rect;
if (!params.name.empty())
@@ -532,11 +567,9 @@ void BrowserPluginGuest::Initialize(
static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
new_view->OnGuestInitialized(embedder_web_contents->GetView());
- // |render_view_host| manages the ownership of this BrowserPluginGuestHelper.
- new BrowserPluginGuestHelper(this, GetWebContents()->GetRenderViewHost());
-
RendererPreferences* renderer_prefs =
GetWebContents()->GetMutableRendererPrefs();
+ std::string guest_user_agent_override = renderer_prefs->user_agent_override;
// Copy renderer preferences (and nothing else) from the embedder's
// WebContents to the guest.
//
@@ -544,6 +577,7 @@ void BrowserPluginGuest::Initialize(
// values for caret blinking interval, colors related to selection and
// focus.
*renderer_prefs = *embedder_web_contents_->GetMutableRendererPrefs();
+ renderer_prefs->user_agent_override = guest_user_agent_override;
// We would like the guest to report changes to frame names so that we can
// update the BrowserPlugin's corresponding 'name' attribute.
@@ -555,14 +589,7 @@ void BrowserPluginGuest::Initialize(
// Disable "client blocked" error page for browser plugin.
renderer_prefs->disable_client_blocked_error_page = true;
- // Listen to embedder visibility changes so that the guest is in a 'shown'
- // state if both the embedder is visible and the BrowserPlugin is marked as
- // visible.
- notification_registrar_.Add(
- this, NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
- Source<WebContents>(embedder_web_contents_));
-
- embedder_rvh_observer_.reset(new EmbedderRenderViewHostObserver(this));
+ embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this));
OnSetSize(instance_id_, params.auto_size_params, params.resize_guest_params);
@@ -575,8 +602,10 @@ void BrowserPluginGuest::Initialize(
new BrowserPluginMsg_GuestContentWindowReady(instance_id_,
guest_routing_id));
- if (!params.src.empty())
+ if (!params.src.empty()) {
+ // params.src will be validated in BrowserPluginGuest::OnNavigateGuest.
OnNavigateGuest(instance_id_, params.src);
+ }
has_render_view_ = true;
@@ -606,6 +635,9 @@ void BrowserPluginGuest::Initialize(
ack_params.name = name_;
SendMessageToEmbedder(
new BrowserPluginMsg_Attach_ACK(instance_id_, ack_params));
+
+ if (delegate_)
+ delegate_->DidAttach();
}
BrowserPluginGuest::~BrowserPluginGuest() {
@@ -618,6 +650,7 @@ BrowserPluginGuest::~BrowserPluginGuest() {
// static
BrowserPluginGuest* BrowserPluginGuest::Create(
int instance_id,
+ SiteInstance* guest_site_instance,
WebContentsImpl* web_contents,
scoped_ptr<base::DictionaryValue> extra_params) {
RecordAction(UserMetricsAction("BrowserPlugin.Guest.Create"));
@@ -625,13 +658,13 @@ BrowserPluginGuest* BrowserPluginGuest::Create(
if (factory_) {
guest = factory_->CreateBrowserPluginGuest(instance_id, web_contents);
} else {
- guest = new BrowserPluginGuest(instance_id, web_contents, NULL, false);
+ guest = new BrowserPluginGuest(instance_id, false, web_contents, NULL);
}
guest->extra_attach_params_.reset(extra_params->DeepCopy());
web_contents->SetBrowserPluginGuest(guest);
BrowserPluginGuestDelegate* delegate = NULL;
GetContentClient()->browser()->GuestWebContentsCreated(
- web_contents, NULL, &delegate, extra_params.Pass());
+ guest_site_instance, web_contents, NULL, &delegate, extra_params.Pass());
guest->SetDelegate(delegate);
return guest;
}
@@ -639,15 +672,16 @@ BrowserPluginGuest* BrowserPluginGuest::Create(
// static
BrowserPluginGuest* BrowserPluginGuest::CreateWithOpener(
int instance_id,
+ bool has_render_view,
WebContentsImpl* web_contents,
- BrowserPluginGuest* opener,
- bool has_render_view) {
+ BrowserPluginGuest* opener) {
BrowserPluginGuest* guest =
new BrowserPluginGuest(
- instance_id, web_contents, opener, has_render_view);
+ instance_id, has_render_view, web_contents, opener);
web_contents->SetBrowserPluginGuest(guest);
BrowserPluginGuestDelegate* delegate = NULL;
GetContentClient()->browser()->GuestWebContentsCreated(
+ opener->GetWebContents()->GetSiteInstance(),
web_contents, opener->GetWebContents(), &delegate,
scoped_ptr<base::DictionaryValue>());
guest->SetDelegate(delegate);
@@ -662,6 +696,16 @@ void BrowserPluginGuest::UpdateVisibility() {
OnSetVisibility(instance_id_, visible());
}
+void BrowserPluginGuest::CopyFromCompositingSurface(
+ gfx::Rect src_subrect,
+ gfx::Size dst_size,
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
+ copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback));
+ SendMessageToEmbedder(
+ new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(),
+ copy_request_id_, src_subrect, dst_size));
+}
+
// screen.
gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
gfx::Rect guest_rect(bounds);
@@ -669,20 +713,9 @@ gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
return guest_rect;
}
-void BrowserPluginGuest::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- switch (type) {
- case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: {
- DCHECK_EQ(Source<WebContents>(source).ptr(), embedder_web_contents_);
- embedder_visible_ = *Details<bool>(details).ptr();
- UpdateVisibility();
- break;
- }
- default:
- NOTREACHED() << "Unexpected notification sent.";
- break;
- }
+void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
+ embedder_visible_ = visible;
+ UpdateVisibility();
}
void BrowserPluginGuest::AddNewContents(WebContents* source,
@@ -693,8 +726,8 @@ void BrowserPluginGuest::AddNewContents(WebContents* source,
bool* was_blocked) {
if (was_blocked)
*was_blocked = false;
- RequestNewWindowPermission(static_cast<WebContentsImpl*>(new_contents),
- disposition, initial_pos, user_gesture);
+ RequestNewWindowPermission(disposition, initial_pos, user_gesture,
+ static_cast<WebContentsImpl*>(new_contents));
}
void BrowserPluginGuest::CanDownload(
@@ -702,12 +735,6 @@ void BrowserPluginGuest::CanDownload(
int request_id,
const std::string& request_method,
const base::Callback<void(bool)>& callback) {
- if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
- // Deny the download request.
- callback.Run(false);
- return;
- }
-
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::IO, FROM_HERE,
base::Bind(&RetrieveDownloadURLFromRequestId,
@@ -754,6 +781,9 @@ void BrowserPluginGuest::HandleKeyboardEvent(
if (delegate_ && delegate_->HandleKeyboardEvent(event))
return;
+ if (!embedder_web_contents_->GetDelegate())
+ return;
+
// Send the unhandled keyboard events back to the embedder to reprocess them.
// TODO(fsamuel): This introduces the possibility of out-of-order keyboard
// events because the guest may be arbitrarily delayed when responding to
@@ -783,8 +813,7 @@ WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source,
}
if (params.disposition == CURRENT_TAB) {
// This can happen for cross-site redirects.
- source->GetController().LoadURL(
- params.url, params.referrer, params.transition, std::string());
+ LoadURLWithParams(params.url, params.referrer, params.transition, source);
return source;
}
@@ -793,7 +822,7 @@ WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source,
void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents,
int64 source_frame_id,
- const string16& frame_name,
+ const base::string16& frame_name,
const GURL& target_url,
WebContents* new_contents) {
WebContentsImpl* new_contents_impl =
@@ -825,6 +854,12 @@ void BrowserPluginGuest::RendererResponsive(WebContents* source) {
void BrowserPluginGuest::RunFileChooser(WebContents* web_contents,
const FileChooserParams& params) {
+ if (!attached())
+ return;
+
+ if (!embedder_web_contents_->GetDelegate())
+ return;
+
embedder_web_contents_->GetDelegate()->RunFileChooser(web_contents, params);
}
@@ -886,10 +921,10 @@ bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const {
}
void BrowserPluginGuest::RequestNewWindowPermission(
- WebContentsImpl* new_contents,
WindowOpenDisposition disposition,
const gfx::Rect& initial_bounds,
- bool user_gesture) {
+ bool user_gesture,
+ WebContentsImpl* new_contents) {
BrowserPluginGuest* guest = new_contents->GetBrowserPluginGuest();
PendingWindowMap::iterator it = pending_new_windows_.find(guest);
if (it == pending_new_windows_.end())
@@ -940,7 +975,7 @@ void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
}
void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
- int screen_x, int screen_y, WebKit::WebDragOperation operation) {
+ int screen_x, int screen_y, blink::WebDragOperation operation) {
web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
screen_x, screen_y, operation);
}
@@ -956,9 +991,9 @@ void BrowserPluginGuest::EndSystemDrag() {
GetWebContents()->GetRenderViewHost());
guest_rvh->DragSourceSystemDragEnded();
// Issue a MouseUp event to get out of a selection state.
- WebKit::WebMouseEvent mouse_event;
- mouse_event.type = WebKit::WebInputEvent::MouseUp;
- mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
+ blink::WebMouseEvent mouse_event;
+ mouse_event.type = blink::WebInputEvent::MouseUp;
+ mouse_event.button = blink::WebMouseEvent::ButtonLeft;
guest_rvh->ForwardMouseEvent(mouse_event);
}
@@ -971,12 +1006,6 @@ void BrowserPluginGuest::AskEmbedderForGeolocationPermission(
int bridge_id,
const GURL& requesting_frame,
const GeolocationCallback& callback) {
- if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
- // Deny the geolocation request.
- callback.Run(false);
- return;
- }
-
base::DictionaryValue request_info;
request_info.Set(browser_plugin::kURL,
base::Value::CreateStringValue(requesting_frame.spec()));
@@ -1031,6 +1060,7 @@ void BrowserPluginGuest::SendQueuedMessages() {
void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
int64 frame_id,
+ const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& url,
PageTransition transition_type,
@@ -1047,23 +1077,26 @@ void BrowserPluginGuest::DidStopLoading(RenderViewHost* render_view_host) {
const char script[] = "window.addEventListener('dragstart', function() { "
" window.event.preventDefault(); "
"});";
- render_view_host->ExecuteJavascriptInWebFrame(string16(),
+ render_view_host->ExecuteJavascriptInWebFrame(base::string16(),
ASCIIToUTF16(script));
}
}
void BrowserPluginGuest::RenderViewReady() {
+ RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
+ // The guest RenderView should always live in a guest process.
+ CHECK(rvh->GetProcess()->IsGuest());
// TODO(fsamuel): Investigate whether it's possible to update state earlier
// here (see http://crbug.com/158151).
Send(new InputMsg_SetFocus(routing_id(), focused_));
UpdateVisibility();
- RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
if (auto_size_enabled_)
rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
else
rvh->DisableAutoResize(damage_view_size_);
Send(new ViewMsg_SetName(routing_id(), name_));
+ OnSetContentsOpaque(instance_id_, guest_opaque_);
RenderWidgetHostImpl::From(rvh)->
set_hung_renderer_delay_ms(guest_hang_timeout_);
@@ -1110,26 +1143,31 @@ bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
switch (message.type()) {
case BrowserPluginHostMsg_BuffersSwappedACK::ID:
case BrowserPluginHostMsg_CompositorFrameACK::ID:
+ case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID:
case BrowserPluginHostMsg_DragStatusUpdate::ID:
case BrowserPluginHostMsg_ExecuteEditCommand::ID:
+ case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID:
case BrowserPluginHostMsg_HandleInputEvent::ID:
+ case BrowserPluginHostMsg_ImeConfirmComposition::ID:
+ case BrowserPluginHostMsg_ImeSetComposition::ID:
case BrowserPluginHostMsg_LockMouse_ACK::ID:
case BrowserPluginHostMsg_NavigateGuest::ID:
case BrowserPluginHostMsg_PluginDestroyed::ID:
+ case BrowserPluginHostMsg_ReclaimCompositorResources::ID:
case BrowserPluginHostMsg_ResizeGuest::ID:
case BrowserPluginHostMsg_SetAutoSize::ID:
case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID:
case BrowserPluginHostMsg_SetFocus::ID:
case BrowserPluginHostMsg_SetName::ID:
+ case BrowserPluginHostMsg_SetContentsOpaque::ID:
case BrowserPluginHostMsg_SetVisibility::ID:
case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
case BrowserPluginHostMsg_UpdateGeometry::ID:
case BrowserPluginHostMsg_UpdateRect_ACK::ID:
return true;
default:
- break;
+ return false;
}
- return false;
}
bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
@@ -1147,6 +1185,14 @@ bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged,
+ OnTextInputTypeChanged)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
+ OnImeCancelComposition)
+#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
+ OnImeCompositionRangeChanged)
+#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFrameName, OnUpdateFrameName)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
@@ -1170,7 +1216,7 @@ void BrowserPluginGuest::Attach(
params.src.clear();
// If a RenderView has already been created for this new window, then we need
- // to initialize the browser-side state now so that the RenderViewHostManager
+ // to initialize the browser-side state now so that the RenderFrameHostManager
// does not create a new RenderView on navigation.
if (has_render_view_) {
static_cast<RenderViewHostImpl*>(
@@ -1203,7 +1249,7 @@ void BrowserPluginGuest::Attach(
if (!name_.empty())
params.name.clear();
- Initialize(embedder_web_contents, params);
+ Initialize(params, embedder_web_contents);
SendQueuedMessages();
@@ -1223,29 +1269,29 @@ void BrowserPluginGuest::OnCompositorFrameACK(
}
void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
- WebKit::WebDragStatus drag_status,
+ blink::WebDragStatus drag_status,
const DropData& drop_data,
- WebKit::WebDragOperationsMask mask,
+ blink::WebDragOperationsMask mask,
const gfx::Point& location) {
RenderViewHost* host = GetWebContents()->GetRenderViewHost();
switch (drag_status) {
- case WebKit::WebDragStatusEnter:
+ case blink::WebDragStatusEnter:
embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
this);
host->DragTargetDragEnter(drop_data, location, location, mask, 0);
break;
- case WebKit::WebDragStatusOver:
+ case blink::WebDragStatusOver:
host->DragTargetDragOver(location, location, mask, 0);
break;
- case WebKit::WebDragStatusLeave:
+ case blink::WebDragStatusLeave:
embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
host->DragTargetDragLeave();
break;
- case WebKit::WebDragStatusDrop:
+ case blink::WebDragStatusDrop:
host->DragTargetDrop(location, location, 0);
EndSystemDrag();
break;
- case WebKit::WebDragStatusUnknown:
+ case blink::WebDragStatusUnknown:
NOTREACHED();
}
}
@@ -1255,10 +1301,50 @@ void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
}
+void BrowserPluginGuest::OnImeSetComposition(
+ int instance_id,
+ const std::string& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
+ int selection_start,
+ int selection_end) {
+ Send(new ViewMsg_ImeSetComposition(routing_id(),
+ UTF8ToUTF16(text), underlines,
+ selection_start, selection_end));
+}
+
+void BrowserPluginGuest::OnImeConfirmComposition(
+ int instance_id,
+ const std::string& text,
+ bool keep_selection) {
+ Send(new ViewMsg_ImeConfirmComposition(routing_id(),
+ UTF8ToUTF16(text),
+ gfx::Range::InvalidRange(),
+ keep_selection));
+}
+
+void BrowserPluginGuest::OnExtendSelectionAndDelete(
+ int instance_id,
+ int before,
+ int after) {
+ Send(new ViewMsg_ExtendSelectionAndDelete(routing_id(), before, after));
+}
+
+void BrowserPluginGuest::OnReclaimCompositorResources(
+ int instance_id,
+ int route_id,
+ uint32 output_surface_id,
+ int renderer_host_id,
+ const cc::CompositorFrameAck& ack) {
+ RenderWidgetHostImpl::SendReclaimCompositorResources(route_id,
+ output_surface_id,
+ renderer_host_id,
+ ack);
+}
+
void BrowserPluginGuest::OnHandleInputEvent(
int instance_id,
const gfx::Rect& guest_window_rect,
- const WebKit::WebInputEvent* event) {
+ const blink::WebInputEvent* event) {
guest_window_rect_ = guest_window_rect;
// If the embedder's RWHV is destroyed then that means that the embedder's
// window has been closed but the embedder's WebContents has not yet been
@@ -1273,19 +1359,19 @@ void BrowserPluginGuest::OnHandleInputEvent(
RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
GetWebContents()->GetRenderViewHost());
- if (WebKit::WebInputEvent::isMouseEventType(event->type)) {
+ if (blink::WebInputEvent::isMouseEventType(event->type)) {
guest_rvh->ForwardMouseEvent(
- *static_cast<const WebKit::WebMouseEvent*>(event));
+ *static_cast<const blink::WebMouseEvent*>(event));
return;
}
- if (event->type == WebKit::WebInputEvent::MouseWheel) {
+ if (event->type == blink::WebInputEvent::MouseWheel) {
guest_rvh->ForwardWheelEvent(
- *static_cast<const WebKit::WebMouseWheelEvent*>(event));
+ *static_cast<const blink::WebMouseWheelEvent*>(event));
return;
}
- if (WebKit::WebInputEvent::isKeyboardEventType(event->type)) {
+ if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
embedder_web_contents_->GetRenderViewHost());
if (!embedder_rvh->GetLastKeyboardEvent())
@@ -1296,16 +1382,16 @@ void BrowserPluginGuest::OnHandleInputEvent(
return;
}
- if (WebKit::WebInputEvent::isTouchEventType(event->type)) {
+ if (blink::WebInputEvent::isTouchEventType(event->type)) {
guest_rvh->ForwardTouchEventWithLatencyInfo(
- *static_cast<const WebKit::WebTouchEvent*>(event),
+ *static_cast<const blink::WebTouchEvent*>(event),
ui::LatencyInfo());
return;
}
- if (WebKit::WebInputEvent::isGestureEventType(event->type)) {
+ if (blink::WebInputEvent::isGestureEventType(event->type)) {
guest_rvh->ForwardGestureEvent(
- *static_cast<const WebKit::WebGestureEvent*>(event));
+ *static_cast<const blink::WebGestureEvent*>(event));
return;
}
}
@@ -1313,9 +1399,7 @@ void BrowserPluginGuest::OnHandleInputEvent(
void BrowserPluginGuest::OnLockMouse(bool user_gesture,
bool last_unlocked_by_target,
bool privileged) {
- if (pending_lock_request_ ||
- (permission_request_map_.size() >=
- kNumMaxOutstandingPermissionRequests)) {
+ if (pending_lock_request_) {
// Immediately reject the lock because only one pointerLock may be active
// at a time.
Send(new ViewMsg_LockMouse_ACK(routing_id(), false));
@@ -1346,39 +1430,45 @@ void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
void BrowserPluginGuest::OnNavigateGuest(
int instance_id,
const std::string& src) {
- GURL url(src);
+ GURL url = delegate_ ? delegate_->ResolveURL(src) : GURL(src);
// We do not load empty urls in web_contents.
// If a guest sets empty src attribute after it has navigated to some
// non-empty page, the action is considered no-op. This empty src navigation
// should never be sent to BrowserPluginGuest (browser process).
DCHECK(!src.empty());
- if (!src.empty()) {
- // Do not allow navigating a guest to schemes other than known safe schemes.
- // This will block the embedder trying to load unwanted schemes, e.g.
- // chrome://settings.
- bool scheme_is_blocked =
- (!ChildProcessSecurityPolicyImpl::GetInstance()->IsWebSafeScheme(
- url.scheme()) &&
- !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme(
- url.scheme())) ||
- url.SchemeIs(kJavaScriptScheme);
- if (scheme_is_blocked || !url.is_valid()) {
- if (delegate_) {
- std::string error_type;
- RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::", &error_type);
- delegate_->LoadAbort(true /* is_top_level */, url, error_type);
- }
- return;
- }
+ if (src.empty())
+ return;
- // As guests do not swap processes on navigation, only navigations to
- // normal web URLs are supported. No protocol handlers are installed for
- // other schemes (e.g., WebUI or extensions), and no permissions or bindings
- // can be granted to the guest process.
- GetWebContents()->GetController().LoadURL(url, Referrer(),
- PAGE_TRANSITION_AUTO_TOPLEVEL,
- std::string());
+ // Do not allow navigating a guest to schemes other than known safe schemes.
+ // This will block the embedder trying to load unwanted schemes, e.g.
+ // chrome://settings.
+ bool scheme_is_blocked =
+ (!ChildProcessSecurityPolicyImpl::GetInstance()->IsWebSafeScheme(
+ url.scheme()) &&
+ !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme(
+ url.scheme())) ||
+ url.SchemeIs(kJavaScriptScheme);
+ if (scheme_is_blocked || !url.is_valid()) {
+ if (delegate_) {
+ std::string error_type;
+ base::RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::",
+ &error_type);
+ delegate_->LoadAbort(true /* is_top_level */, url, error_type);
+ }
+ return;
}
+
+ GURL validated_url(url);
+ RenderViewHost::FilterURL(
+ GetWebContents()->GetRenderProcessHost(),
+ false,
+ &validated_url);
+ // As guests do not swap processes on navigation, only navigations to
+ // normal web URLs are supported. No protocol handlers are installed for
+ // other schemes (e.g., WebUI or extensions), and no permissions or bindings
+ // can be granted to the guest process.
+ LoadURLWithParams(validated_url, Referrer(), PAGE_TRANSITION_AUTO_TOPLEVEL,
+ GetWebContents());
}
void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
@@ -1413,15 +1503,10 @@ void BrowserPluginGuest::OnResizeGuest(
}
// Invalid damage buffer means we are in HW compositing mode,
// so just resize the WebContents and repaint if needed.
- if (!base::SharedMemory::IsHandleValid(params.damage_buffer_handle)) {
- if (!params.view_rect.size().IsEmpty())
- GetWebContents()->GetView()->SizeContents(params.view_rect.size());
- if (params.repaint)
- Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size()));
- return;
- }
- SetDamageBuffer(params);
- GetWebContents()->GetView()->SizeContents(params.view_rect.size());
+ if (base::SharedMemory::IsHandleValid(params.damage_buffer_handle))
+ SetDamageBuffer(params);
+ if (!params.view_rect.size().IsEmpty())
+ GetWebContents()->GetView()->SizeContents(params.view_rect.size());
if (params.repaint)
Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size()));
}
@@ -1480,6 +1565,18 @@ void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
edit_commands));
}
+void BrowserPluginGuest::OnSetContentsOpaque(int instance_id, bool opaque) {
+ guest_opaque_ = opaque;
+
+ SkBitmap background;
+ if (!guest_opaque_) {
+ background.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
+ unsigned int color = 0;
+ background.setPixels(&color);
+ }
+ Send(new ViewMsg_SetBackground(routing_id(), background));
+}
+
void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
guest_visible_ = visible;
if (embedder_visible_ && guest_visible_)
@@ -1529,6 +1626,18 @@ void BrowserPluginGuest::OnUpdateRectACK(
OnSetSize(instance_id_, auto_size_params, resize_guest_params);
}
+void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
+ int instance_id,
+ int request_id,
+ const SkBitmap& bitmap) {
+ CHECK(copy_request_callbacks_.count(request_id));
+ if (!copy_request_callbacks_.count(request_id))
+ return;
+ const CopyRequestCallback& callback = copy_request_callbacks_[request_id];
+ callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap);
+ copy_request_callbacks_.erase(request_id);
+}
+
void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
const gfx::Rect& view_rect) {
// The plugin has moved within the embedder without resizing or the
@@ -1591,12 +1700,6 @@ void BrowserPluginGuest::RequestMediaAccessPermission(
WebContents* web_contents,
const MediaStreamRequest& request,
const MediaResponseCallback& callback) {
- if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
- // Deny the media request.
- callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
- return;
- }
-
base::DictionaryValue request_info;
request_info.Set(
browser_plugin::kURL,
@@ -1612,15 +1715,10 @@ void BrowserPluginGuest::RunJavaScriptDialog(
const GURL& origin_url,
const std::string& accept_lang,
JavaScriptMessageType javascript_message_type,
- const string16& message_text,
- const string16& default_prompt_text,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
const DialogClosedCallback& callback,
bool* did_suppress_message) {
- if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
- // Cancel the dialog.
- callback.Run(false, string16());
- return;
- }
base::DictionaryValue request_info;
request_info.Set(
browser_plugin::kDefaultPromptText,
@@ -1643,18 +1741,18 @@ void BrowserPluginGuest::RunJavaScriptDialog(
void BrowserPluginGuest::RunBeforeUnloadDialog(
WebContents* web_contents,
- const string16& message_text,
+ const base::string16& message_text,
bool is_reload,
const DialogClosedCallback& callback) {
// This is called if the guest has a beforeunload event handler.
// This callback allows navigation to proceed.
- callback.Run(true, string16());
+ callback.Run(true, base::string16());
}
bool BrowserPluginGuest::HandleJavaScriptDialog(
WebContents* web_contents,
bool accept,
- const string16* prompt_override) {
+ const base::string16* prompt_override) {
return false;
}
@@ -1729,6 +1827,29 @@ void BrowserPluginGuest::OnUpdateRect(
new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
}
+void BrowserPluginGuest::OnTextInputTypeChanged(ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline) {
+ RenderWidgetHostViewPort::FromRWHV(
+ web_contents()->GetRenderWidgetHostView())->TextInputTypeChanged(
+ type, input_mode, can_compose_inline);
+}
+
+void BrowserPluginGuest::OnImeCancelComposition() {
+ RenderWidgetHostViewPort::FromRWHV(
+ web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
+}
+
+#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
+void BrowserPluginGuest::OnImeCompositionRangeChanged(
+ const gfx::Range& range,
+ const std::vector<gfx::Rect>& character_bounds) {
+ RenderWidgetHostViewPort::FromRWHV(
+ web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
+ range, character_bounds);
+}
+#endif
+
void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId(
const std::string& request_method,
const base::Callback<void(bool)>& callback,
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
index 0101ff7118d..46c95a40da8 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
@@ -6,12 +6,9 @@
// renderer channel. A BrowserPlugin (a WebPlugin) is on the embedder
// renderer side of browser <--> embedder renderer communication.
//
-// BrowserPluginGuest lives on the UI thread of the browser process. It has a
-// helper, BrowserPluginGuestHelper, which is a RenderViewHostObserver. The
-// helper object intercepts messages (ViewHostMsg_*) directed at the browser
-// process and redirects them to this class. Any messages about the guest render
-// process that the embedder might be interested in receiving should be listened
-// for here.
+// BrowserPluginGuest lives on the UI thread of the browser process. Any
+// messages about the guest render process that the embedder might be interested
+// in receiving should be listened for here.
//
// BrowserPluginGuest is a WebContentsDelegate and WebContentsObserver for the
// guest WebContents. BrowserPluginGuest operates under the assumption that the
@@ -33,15 +30,15 @@
#include "content/port/common/input_event_ack_state.h"
#include "content/public/browser/browser_plugin_guest_delegate.h"
#include "content/public/browser/javascript_dialog_manager.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/render_view_host_observer.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/browser_plugin_permission_type.h"
+#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
#include "third_party/WebKit/public/web/WebDragStatus.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/base/ime/text_input_mode.h"
+#include "ui/base/ime/text_input_type.h"
#include "ui/gfx/rect.h"
#include "ui/surface/transport_dib.h"
@@ -59,10 +56,14 @@ namespace cc {
class CompositorFrameAck;
}
-namespace WebKit {
+namespace blink {
class WebInputEvent;
}
+namespace gfx {
+class Range;
+}
+
namespace content {
class BrowserPluginHostFactory;
@@ -70,6 +71,7 @@ class BrowserPluginEmbedder;
class BrowserPluginGuestManager;
class RenderProcessHost;
class RenderWidgetHostView;
+class SiteInstance;
struct DropData;
struct MediaStreamRequest;
@@ -85,7 +87,6 @@ struct MediaStreamRequest;
// which means it can share storage and can script this guest.
class CONTENT_EXPORT BrowserPluginGuest
: public JavaScriptDialogManager,
- public NotificationObserver,
public WebContentsDelegate,
public WebContentsObserver,
public base::SupportsWeakPtr<BrowserPluginGuest> {
@@ -93,21 +94,32 @@ class CONTENT_EXPORT BrowserPluginGuest
typedef base::Callback<void(bool)> GeolocationCallback;
virtual ~BrowserPluginGuest();
+ // The WebContents passed into the factory method here has not been
+ // initialized yet and so it does not yet hold a SiteInstance.
+ // BrowserPluginGuest must be constructed and installed into a WebContents
+ // prior to its initialization because WebContents needs to determine what
+ // type of WebContentsView to construct on initialization. The content
+ // embedder needs to be aware of |guest_site_instance| on the guest's
+ // construction and so we pass it in here.
static BrowserPluginGuest* Create(
int instance_id,
+ SiteInstance* guest_site_instance,
WebContentsImpl* web_contents,
scoped_ptr<base::DictionaryValue> extra_params);
static BrowserPluginGuest* CreateWithOpener(
int instance_id,
+ bool has_render_view,
WebContentsImpl* web_contents,
- BrowserPluginGuest* opener,
- bool has_render_view);
+ BrowserPluginGuest* opener);
- // Called when the embedder RenderViewHost is destroyed to give the
+ // Called when the embedder WebContents is destroyed to give the
// BrowserPluginGuest an opportunity to clean up after itself.
void EmbedderDestroyed();
+ // Called when the embedder WebContents changes visibility.
+ void EmbedderVisibilityChanged(bool visible);
+
// Destroys the guest WebContents and all its associated state, including
// this BrowserPluginGuest, and its new unattached windows.
void Destroy();
@@ -116,20 +128,10 @@ class CONTENT_EXPORT BrowserPluginGuest
// within an embedder.
int instance_id() const { return instance_id_; }
- // Overrides factory for testing. Default (NULL) value indicates regular
- // (non-test) environment.
- static void set_factory_for_testing(BrowserPluginHostFactory* factory) {
- BrowserPluginGuest::factory_ = factory;
- }
-
bool OnMessageReceivedFromEmbedder(const IPC::Message& message);
- void Initialize(WebContentsImpl* embedder_web_contents,
- const BrowserPluginHostMsg_Attach_Params& params);
-
- void set_guest_hang_timeout_for_testing(const base::TimeDelta& timeout) {
- guest_hang_timeout_ = timeout;
- }
+ void Initialize(const BrowserPluginHostMsg_Attach_Params& params,
+ WebContentsImpl* embedder_web_contents);
WebContentsImpl* embedder_web_contents() const {
return embedder_web_contents_;
@@ -149,14 +151,15 @@ class CONTENT_EXPORT BrowserPluginGuest
void UpdateVisibility();
- // NotificationObserver implementation.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void CopyFromCompositingSurface(
+ gfx::Rect src_subrect,
+ gfx::Size dst_size,
+ const base::Callback<void(bool, const SkBitmap&)>& callback);
// WebContentsObserver implementation.
virtual void DidCommitProvisionalLoadForFrame(
int64 frame_id,
+ const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& url,
PageTransition transition_type,
@@ -170,9 +173,9 @@ class CONTENT_EXPORT BrowserPluginGuest
// WebContentsDelegate implementation.
virtual bool AddMessageToConsole(WebContents* source,
int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id) OVERRIDE;
+ const base::string16& source_id) OVERRIDE;
// If a new window is created with target="_blank" and rel="noreferrer", then
// this method is called, indicating that the new WebContents is ready to be
// attached.
@@ -198,7 +201,7 @@ class CONTENT_EXPORT BrowserPluginGuest
const OpenURLParams& params) OVERRIDE;
virtual void WebContentsCreated(WebContents* source_contents,
int64 source_frame_id,
- const string16& frame_name,
+ const base::string16& frame_name,
const GURL& target_url,
WebContents* new_contents) OVERRIDE;
virtual void RendererUnresponsive(WebContents* source) OVERRIDE;
@@ -217,18 +220,19 @@ class CONTENT_EXPORT BrowserPluginGuest
const GURL& origin_url,
const std::string& accept_lang,
JavaScriptMessageType javascript_message_type,
- const string16& message_text,
- const string16& default_prompt_text,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
const DialogClosedCallback& callback,
bool* did_suppress_message) OVERRIDE;
virtual void RunBeforeUnloadDialog(
WebContents* web_contents,
- const string16& message_text,
+ const base::string16& message_text,
bool is_reload,
const DialogClosedCallback& callback) OVERRIDE;
- virtual bool HandleJavaScriptDialog(WebContents* web_contents,
- bool accept,
- const string16* prompt_override) OVERRIDE;
+ virtual bool HandleJavaScriptDialog(
+ WebContents* web_contents,
+ bool accept,
+ const base::string16* prompt_override) OVERRIDE;
virtual void CancelActiveAndPendingDialogs(
WebContents* web_contents) OVERRIDE;
virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
@@ -249,7 +253,7 @@ class CONTENT_EXPORT BrowserPluginGuest
virtual void SendMessageToEmbedder(IPC::Message* msg);
// Returns whether the guest is attached to an embedder.
- bool attached() const { return !!embedder_web_contents_; }
+ bool attached() const { return embedder_web_contents_ != NULL; }
// Attaches this BrowserPluginGuest to the provided |embedder_web_contents|
// and initializes the guest with the provided |params|. Attaching a guest
@@ -281,7 +285,7 @@ class CONTENT_EXPORT BrowserPluginGuest
gfx::Rect ToGuestRect(const gfx::Rect& rect);
void DragSourceEndedAt(int client_x, int client_y, int screen_x,
- int screen_y, WebKit::WebDragOperation operation);
+ int screen_y, blink::WebDragOperation operation);
void DragSourceMovedTo(int client_x, int client_y,
int screen_x, int screen_y);
@@ -296,8 +300,14 @@ class CONTENT_EXPORT BrowserPluginGuest
bool should_allow,
const std::string& user_input);
+ // Overrides factory for testing. Default (NULL) value indicates regular
+ // (non-test) environment.
+ static void set_factory_for_testing(BrowserPluginHostFactory* factory) {
+ BrowserPluginGuest::factory_ = factory;
+ }
+
private:
- class EmbedderRenderViewHostObserver;
+ class EmbedderWebContentsObserver;
friend class TestBrowserPluginGuest;
class DownloadRequest;
@@ -309,15 +319,36 @@ class CONTENT_EXPORT BrowserPluginGuest
class PermissionRequest;
class PointerLockRequest;
+ // Tracks the name, and target URL of the new window and whether or not it has
+ // changed since the WebContents has been created and before the new window
+ // has been attached to a BrowserPlugin. Once the first navigation commits, we
+ // no longer track this information.
+ struct NewWindowInfo {
+ bool changed;
+ GURL url;
+ std::string name;
+ NewWindowInfo(const GURL& url, const std::string& name) :
+ changed(false),
+ url(url),
+ name(name) {}
+ };
+
+ // BrowserPluginGuest is a WebContentsObserver of |web_contents| and
+ // |web_contents| has to stay valid for the lifetime of BrowserPluginGuest.
BrowserPluginGuest(int instance_id,
+ bool has_render_view,
WebContentsImpl* web_contents,
- BrowserPluginGuest* opener,
- bool has_render_view);
+ BrowserPluginGuest* opener);
// Destroy unattached new windows that have been opened by this
// BrowserPluginGuest.
void DestroyUnattachedWindows();
+ void LoadURLWithParams(const GURL& url,
+ const Referrer& referrer,
+ PageTransition transition_type,
+ WebContents* web_contents);
+
// Bridge IDs correspond to a geolocation request. This method will remove
// the bookkeeping for a particular geolocation request associated with the
// provided |bridge_id|. It returns the request ID of the geolocation request.
@@ -344,10 +375,10 @@ class CONTENT_EXPORT BrowserPluginGuest
bool InAutoSizeBounds(const gfx::Size& size) const;
- void RequestNewWindowPermission(WebContentsImpl* new_contents,
- WindowOpenDisposition disposition,
+ void RequestNewWindowPermission(WindowOpenDisposition disposition,
const gfx::Rect& initial_bounds,
- bool user_gesture);
+ bool user_gesture,
+ WebContentsImpl* new_contents);
// Message handlers for messages from embedder.
@@ -356,24 +387,34 @@ class CONTENT_EXPORT BrowserPluginGuest
uint32 output_surface_id,
int renderer_host_id,
const cc::CompositorFrameAck& ack);
-
+ void OnCopyFromCompositingSurfaceAck(int instance_id,
+ int request_id,
+ const SkBitmap& bitmap);
// Handles drag events from the embedder.
// When dragging, the drag events go to the embedder first, and if the drag
// happens on the browser plugin, then the plugin sends a corresponding
// drag-message to the guest. This routes the drag-message to the guest
// renderer.
void OnDragStatusUpdate(int instance_id,
- WebKit::WebDragStatus drag_status,
+ blink::WebDragStatus drag_status,
const DropData& drop_data,
- WebKit::WebDragOperationsMask drag_mask,
+ blink::WebDragOperationsMask drag_mask,
const gfx::Point& location);
// Instructs the guest to execute an edit command decoded in the embedder.
void OnExecuteEditCommand(int instance_id,
const std::string& command);
+
+ // Returns compositor resources reclaimed in the embedder to the guest.
+ void OnReclaimCompositorResources(int instance_id,
+ int route_id,
+ uint32 output_surface_id,
+ int renderer_host_id,
+ const cc::CompositorFrameAck& ack);
+
// Overriden in tests.
virtual void OnHandleInputEvent(int instance_id,
const gfx::Rect& guest_window_rect,
- const WebKit::WebInputEvent* event);
+ const blink::WebInputEvent* event);
void OnLockMouse(bool user_gesture,
bool last_unlocked_by_target,
bool privileged);
@@ -397,6 +438,7 @@ class CONTENT_EXPORT BrowserPluginGuest
void OnSetEditCommandsForNextKeyEvent(
int instance_id,
const std::vector<EditCommand>& edit_commands);
+ void OnSetContentsOpaque(int instance_id, bool opaque);
// The guest WebContents is visible if both its embedder is visible and
// the browser plugin element is visible. If either one is not then the
// WebContents is marked as hidden. A hidden WebContents will consume
@@ -428,12 +470,33 @@ class CONTENT_EXPORT BrowserPluginGuest
const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params);
+ void OnTextInputTypeChanged(ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline);
+ void OnImeSetComposition(
+ int instance_id,
+ const std::string& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
+ int selection_start,
+ int selection_end);
+ void OnImeConfirmComposition(
+ int instance_id,
+ const std::string& text,
+ bool keep_selection);
+ void OnExtendSelectionAndDelete(int instance_id, int before, int after);
+ // Overridden in tests.
+ virtual void OnImeCancelComposition();
+#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
+ void OnImeCompositionRangeChanged(
+ const gfx::Range& range,
+ const std::vector<gfx::Rect>& character_bounds);
+#endif
// Message handlers for messages from guest.
void OnDragStopped();
void OnHandleInputEventAck(
- WebKit::WebInputEvent::Type event_type,
+ blink::WebInputEvent::Type event_type,
InputEventAckState ack_result);
void OnHasTouchEventHandlers(bool accept);
void OnSetCursor(const WebCursor& cursor);
@@ -471,8 +534,7 @@ class CONTENT_EXPORT BrowserPluginGuest
// Static factory instance (always NULL for non-test).
static BrowserPluginHostFactory* factory_;
- NotificationRegistrar notification_registrar_;
- scoped_ptr<EmbedderRenderViewHostObserver> embedder_rvh_observer_;
+ scoped_ptr<EmbedderWebContentsObserver> embedder_web_contents_observer_;
WebContentsImpl* embedder_web_contents_;
std::map<int, int> bridge_id_to_request_id_map_;
@@ -494,25 +556,20 @@ class CONTENT_EXPORT BrowserPluginGuest
bool mouse_locked_;
bool pending_lock_request_;
bool guest_visible_;
+ bool guest_opaque_;
bool embedder_visible_;
std::string name_;
bool auto_size_enabled_;
gfx::Size max_auto_size_;
gfx::Size min_auto_size_;
- // Tracks the name, and target URL of the new window and whether or not it has
- // changed since the WebContents has been created and before the new window
- // has been attached to a BrowserPlugin. Once the first navigation commits, we
- // no longer track this information.
- struct NewWindowInfo {
- bool changed;
- GURL url;
- std::string name;
- NewWindowInfo(const GURL& url, const std::string& name) :
- changed(false),
- url(url),
- name(name) {}
- };
+ // Each copy-request is identified by a unique number. The unique number is
+ // used to keep track of the right callback.
+ int copy_request_id_;
+ typedef base::Callback<void(bool, const SkBitmap&)> CopyRequestCallback;
+ typedef std::map<int, const CopyRequestCallback> CopyRequestMap;
+ CopyRequestMap copy_request_callbacks_;
+
typedef std::map<BrowserPluginGuest*, NewWindowInfo> PendingWindowMap;
PendingWindowMap pending_new_windows_;
base::WeakPtr<BrowserPluginGuest> opener_;
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.cc
deleted file mode 100644
index ee18b6e92e3..00000000000
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.cc
+++ /dev/null
@@ -1,55 +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/browser_plugin/browser_plugin_guest_helper.h"
-
-#include "content/browser/browser_plugin/browser_plugin_guest.h"
-#include "content/common/drag_messages.h"
-#include "content/common/view_messages.h"
-#include "content/public/browser/render_view_host.h"
-
-namespace content {
-
-BrowserPluginGuestHelper::BrowserPluginGuestHelper(
- BrowserPluginGuest* guest,
- RenderViewHost* render_view_host)
- : RenderViewHostObserver(render_view_host),
- guest_(guest) {
-}
-
-BrowserPluginGuestHelper::~BrowserPluginGuestHelper() {
-}
-
-bool BrowserPluginGuestHelper::OnMessageReceived(
- const IPC::Message& message) {
- if (ShouldForwardToBrowserPluginGuest(message))
- return guest_->OnMessageReceived(message);
- return false;
-}
-
-// static
-bool BrowserPluginGuestHelper::ShouldForwardToBrowserPluginGuest(
- const IPC::Message& message) {
- switch (message.type()) {
- case DragHostMsg_StartDragging::ID:
- case DragHostMsg_TargetDrop_ACK::ID:
- case ViewHostMsg_HasTouchEventHandlers::ID:
- case ViewHostMsg_SetCursor::ID:
- #if defined(OS_MACOSX)
- case ViewHostMsg_ShowPopup::ID:
- #endif
- case ViewHostMsg_ShowWidget::ID:
- case ViewHostMsg_TakeFocus::ID:
- case ViewHostMsg_UpdateFrameName::ID:
- case ViewHostMsg_UpdateRect::ID:
- case ViewHostMsg_LockMouse::ID:
- case ViewHostMsg_UnlockMouse::ID:
- return true;
- default:
- break;
- }
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.h b/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.h
deleted file mode 100644
index dfe2e321691..00000000000
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest_helper.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_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_HELPER_H_
-#define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_HELPER_H_
-
-#include "content/port/common/input_event_ack_state.h"
-#include "content/public/browser/render_view_host_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "third_party/WebKit/public/web/WebDragOperation.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-class WebCursor;
-#if defined(OS_MACOSX)
-struct ViewHostMsg_ShowPopup_Params;
-#endif
-struct ViewHostMsg_UpdateRect_Params;
-
-namespace gfx {
-class Size;
-}
-
-namespace content {
-class BrowserPluginGuest;
-class RenderViewHost;
-
-// Helper for BrowserPluginGuest.
-//
-// The purpose of this class is to intercept messages from the guest RenderView
-// before they are handled by the standard message handlers in the browser
-// process. This permits overriding standard behavior with BrowserPlugin-
-// specific behavior.
-//
-// The lifetime of this class is managed by the associated RenderViewHost. A
-// BrowserPluginGuestHelper is created whenever a BrowserPluginGuest is created.
-class BrowserPluginGuestHelper : public RenderViewHostObserver {
- public:
- BrowserPluginGuestHelper(BrowserPluginGuest* guest,
- RenderViewHost* render_view_host);
- virtual ~BrowserPluginGuestHelper();
-
- protected:
- // RenderViewHostObserver implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- private:
- // Returns whether a message should be forward to the helper's associated
- // BrowserPluginGuest.
- static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message);
-
- BrowserPluginGuest* guest_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuestHelper);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_HELPER_H_
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc
index 6c86331b0fe..ed91c1f51ad 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.cc
@@ -4,7 +4,6 @@
#include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
-#include "base/command_line.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/browser_plugin/browser_plugin_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -13,11 +12,10 @@
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/content_export.h"
#include "content/public/browser/user_metrics.h"
-#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
+#include "content/public/common/url_utils.h"
#include "net/base/escape.h"
-#include "ui/events/keycodes/keyboard_codes.h"
namespace content {
@@ -43,7 +41,8 @@ BrowserPluginGuest* BrowserPluginGuestManager::CreateGuest(
int instance_id,
const BrowserPluginHostMsg_Attach_Params& params,
scoped_ptr<base::DictionaryValue> extra_params) {
- SiteInstance* guest_site_instance = NULL;
+ RenderProcessHost* embedder_process_host =
+ embedder_site_instance->GetProcess();
// Validate that the partition id coming from the renderer is valid UTF-8,
// since we depend on this in other parts of the code, such as FilePath
// creation. If the validation fails, treat it as a bad message and kill the
@@ -51,50 +50,44 @@ BrowserPluginGuest* BrowserPluginGuestManager::CreateGuest(
if (!IsStringUTF8(params.storage_partition_id)) {
content::RecordAction(UserMetricsAction("BadMessageTerminate_BPGM"));
base::KillProcess(
- embedder_site_instance->GetProcess()->GetHandle(),
+ embedder_process_host->GetHandle(),
content::RESULT_CODE_KILLED_BAD_MESSAGE, false);
return NULL;
}
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kSitePerProcess)) {
- // When --site-per-process is specified, the behavior of BrowserPlugin
- // as <webview> is broken and we use it for rendering out-of-process
- // iframes instead. We use the src URL sent by the renderer to find the
- // right process in which to place this instance.
- // Note: Since BrowserPlugin doesn't support cross-process navigation,
- // the instance will stay in the initially assigned process, regardless
- // of the site it is navigated to.
- // TODO(nasko): Fix this, and such that cross-process navigations are
- // supported.
- guest_site_instance =
- embedder_site_instance->GetRelatedSiteInstance(GURL(params.src));
- } else {
- const std::string& host = embedder_site_instance->GetSiteURL().host();
-
- std::string url_encoded_partition = net::EscapeQueryParamValue(
- params.storage_partition_id, false);
- // The SiteInstance of a given webview tag is based on the fact that it's
- // a guest process in addition to which platform application the tag
- // belongs to and what storage partition is in use, rather than the URL
- // that the tag is being navigated to.
- GURL guest_site(
- base::StringPrintf("%s://%s/%s?%s", chrome::kGuestScheme,
- host.c_str(),
- params.persist_storage ? "persist" : "",
- url_encoded_partition.c_str()));
-
- // If we already have a webview tag in the same app using the same storage
- // partition, we should use the same SiteInstance so the existing tag and
- // the new tag can script each other.
- guest_site_instance = GetGuestSiteInstance(guest_site);
- if (!guest_site_instance) {
- // Create the SiteInstance in a new BrowsingInstance, which will ensure
- // that webview tags are also not allowed to send messages across
- // different partitions.
- guest_site_instance = SiteInstance::CreateForURL(
- embedder_site_instance->GetBrowserContext(), guest_site);
- }
+ // We usually require BrowserPlugins to be hosted by a storage isolated
+ // extension. We treat WebUI pages as a special case if they host the
+ // BrowserPlugin in a component extension iframe. In that case, we use the
+ // iframe's URL to determine the extension.
+ const GURL& embedder_site_url = embedder_site_instance->GetSiteURL();
+ GURL validated_frame_url(params.embedder_frame_url);
+ RenderViewHost::FilterURL(
+ embedder_process_host, false, &validated_frame_url);
+ const std::string& host = content::HasWebUIScheme(embedder_site_url) ?
+ validated_frame_url.host() : embedder_site_url.host();
+
+ std::string url_encoded_partition = net::EscapeQueryParamValue(
+ params.storage_partition_id, false);
+ // The SiteInstance of a given webview tag is based on the fact that it's
+ // a guest process in addition to which platform application the tag
+ // belongs to and what storage partition is in use, rather than the URL
+ // that the tag is being navigated to.
+ GURL guest_site(base::StringPrintf("%s://%s/%s?%s",
+ kGuestScheme,
+ host.c_str(),
+ params.persist_storage ? "persist" : "",
+ url_encoded_partition.c_str()));
+
+ // If we already have a webview tag in the same app using the same storage
+ // partition, we should use the same SiteInstance so the existing tag and
+ // the new tag can script each other.
+ SiteInstance* guest_site_instance = GetGuestSiteInstance(guest_site);
+ if (!guest_site_instance) {
+ // Create the SiteInstance in a new BrowsingInstance, which will ensure
+ // that webview tags are also not allowed to send messages across
+ // different partitions.
+ guest_site_instance = SiteInstance::CreateForURL(
+ embedder_site_instance->GetBrowserContext(), guest_site);
}
return WebContentsImpl::CreateGuest(
@@ -233,40 +226,17 @@ void BrowserPluginGuestManager::OnUnhandledSwapBuffersACK(
sync_point);
}
-void BrowserPluginGuestManager::DidSendScreenRects(
- WebContentsImpl* embedder_web_contents) {
- // TODO(lazyboy): Generalize iterating over guest instances and performing
- // actions on the guests.
+bool BrowserPluginGuestManager::ForEachGuest(
+ WebContentsImpl* embedder_web_contents, const GuestCallback& callback) {
for (GuestInstanceMap::iterator it =
guest_web_contents_by_instance_id_.begin();
- it != guest_web_contents_by_instance_id_.end(); ++it) {
+ it != guest_web_contents_by_instance_id_.end(); ++it) {
BrowserPluginGuest* guest = it->second->GetBrowserPluginGuest();
- if (embedder_web_contents == guest->embedder_web_contents()) {
- static_cast<RenderViewHostImpl*>(
- guest->GetWebContents()->GetRenderViewHost())->SendScreenRects();
- }
- }
-}
+ if (embedder_web_contents != guest->embedder_web_contents())
+ continue;
-bool BrowserPluginGuestManager::UnlockMouseIfNecessary(
- WebContentsImpl* embedder_web_contents,
- const NativeWebKeyboardEvent& event) {
- if ((event.type != WebKit::WebInputEvent::RawKeyDown) ||
- (event.windowsKeyCode != ui::VKEY_ESCAPE) ||
- (event.modifiers & WebKit::WebInputEvent::InputModifiers)) {
- return false;
- }
-
- // TODO(lazyboy): Generalize iterating over guest instances and performing
- // actions on the guests.
- for (GuestInstanceMap::iterator it =
- guest_web_contents_by_instance_id_.begin();
- it != guest_web_contents_by_instance_id_.end(); ++it) {
- BrowserPluginGuest* guest = it->second->GetBrowserPluginGuest();
- if (embedder_web_contents == guest->embedder_web_contents()) {
- if (guest->UnlockMouseIfNecessary(event))
- return true;
- }
+ if (callback.Run(guest))
+ return true;
}
return false;
}
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.h b/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.h
index a657bfa7a67..5f3b3b9c686 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest_manager.h
@@ -36,8 +36,10 @@ class RenderWidgetHostImpl;
class SiteInstance;
class WebContents;
class WebContentsImpl;
-struct NativeWebKeyboardEvent;
+// WARNING: All APIs should be guarded with a process ID check like
+// CanEmbedderAccessInstanceIDMaybeKill, to prevent abuse by normal renderer
+// processes.
class CONTENT_EXPORT BrowserPluginGuestManager :
public base::SupportsUserData::Data {
public:
@@ -83,10 +85,9 @@ class CONTENT_EXPORT BrowserPluginGuestManager :
bool CanEmbedderAccessInstanceIDMaybeKill(int embedder_render_process_id,
int instance_id) const;
- void DidSendScreenRects(WebContentsImpl* embedder_web_contents);
-
- bool UnlockMouseIfNecessary(WebContentsImpl* embedder_web_contents_,
- const NativeWebKeyboardEvent& event);
+ typedef base::Callback<bool(BrowserPluginGuest*)> GuestCallback;
+ bool ForEachGuest(WebContentsImpl* embedder_web_contents,
+ const GuestCallback& callback);
void OnMessageReceived(const IPC::Message& message, int render_process_id);
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc b/chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
index d49f169f05f..9e48a49647d 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
@@ -18,11 +18,12 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_view_host_observer.h"
#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/drop_data.h"
#include "content/public/common/url_constants.h"
@@ -38,31 +39,16 @@
#include "net/test/spawned_test_server/spawned_test_server.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
using content::BrowserPluginEmbedder;
using content::BrowserPluginGuest;
using content::BrowserPluginHostFactory;
using content::WebContentsImpl;
-namespace {
-
const char kHTMLForGuest[] =
"data:text/html,<html><body>hello world</body></html>";
-const char kHTMLForGuestBusyLoop[] =
- "data:text/html,<html><head><script type=\"text/javascript\">"
- "function PauseMs(timems) {"
- " document.title = \"start\";"
- " var date = new Date();"
- " var currDate = null;"
- " do {"
- " currDate = new Date();"
- " } while (currDate - date < timems)"
- "}"
- "function StartPauseMs(timems) {"
- " setTimeout(function() { PauseMs(timems); }, 0);"
- "}"
- "</script></head><body></body></html>";
+
const char kHTMLForGuestTouchHandler[] =
"data:text/html,<html><body><div id=\"touch\">With touch</div></body>"
"<script type=\"text/javascript\">"
@@ -76,11 +62,7 @@ const char kHTMLForGuestTouchHandler[] =
" handler);"
"}"
"</script></html>";
-const char kHTMLForGuestWithTitle[] =
- "data:text/html,"
- "<html><head><title>%s</title></head>"
- "<body>hello world</body>"
- "</html>";
+
const char kHTMLForGuestAcceptDrag[] =
"data:text/html,<html><body>"
"<script>"
@@ -92,6 +74,7 @@ const char kHTMLForGuestAcceptDrag[] =
" ondrop=\"dropped();\">"
"</textarea>"
"</body></html>";
+
const char kHTMLForGuestWithSize[] =
"data:text/html,"
"<html>"
@@ -100,12 +83,6 @@ const char kHTMLForGuestWithSize[] =
"</body>"
"</html>";
-std::string GetHTMLForGuestWithTitle(const std::string& title) {
- return base::StringPrintf(kHTMLForGuestWithTitle, title.c_str());
-}
-
-} // namespace
-
namespace content {
// Test factory for creating test instances of BrowserPluginEmbedder and
@@ -169,9 +146,9 @@ class TestShortHangTimeoutGuestFactory : public TestBrowserPluginHostFactory {
public:
virtual BrowserPluginGuest* CreateBrowserPluginGuest(
int instance_id, WebContentsImpl* web_contents) OVERRIDE {
- BrowserPluginGuest* guest =
+ TestBrowserPluginGuest* guest =
new TestBrowserPluginGuest(instance_id, web_contents);
- guest->set_guest_hang_timeout_for_testing(TestTimeouts::tiny_timeout());
+ guest->set_guest_hang_timeout(TestTimeouts::tiny_timeout());
return guest;
}
@@ -193,16 +170,15 @@ class TestShortHangTimeoutGuestFactory : public TestBrowserPluginHostFactory {
// A transparent observer that can be used to verify that a RenderViewHost
// received a specific message.
-class RenderViewHostMessageObserver : public RenderViewHostObserver {
+class MessageObserver : public WebContentsObserver {
public:
- RenderViewHostMessageObserver(RenderViewHost* host,
- uint32 message_id)
- : RenderViewHostObserver(host),
+ MessageObserver(WebContents* web_contents, uint32 message_id)
+ : WebContentsObserver(web_contents),
message_id_(message_id),
message_received_(false) {
}
- virtual ~RenderViewHostMessageObserver() {}
+ virtual ~MessageObserver() {}
void WaitUntilMessageReceived() {
if (message_received_)
@@ -230,7 +206,7 @@ class RenderViewHostMessageObserver : public RenderViewHostObserver {
uint32 message_id_;
bool message_received_;
- DISALLOW_COPY_AND_ASSIGN(RenderViewHostMessageObserver);
+ DISALLOW_COPY_AND_ASSIGN(MessageObserver);
};
class BrowserPluginHostTest : public ContentBrowserTest {
@@ -411,7 +387,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AdvanceFocus) {
StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, std::string());
SimulateMouseClick(test_embedder()->web_contents(), 0,
- WebKit::WebMouseEvent::ButtonLeft);
+ blink::WebMouseEvent::ButtonLeft);
BrowserPluginHostTest::SimulateTabKeyPress(test_embedder()->web_contents());
// Wait until we focus into the guest.
test_guest()->WaitForFocus();
@@ -445,7 +421,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderChangedAfterSwap) {
GURL test_https_url(https_server.GetURL(
"files/browser_plugin_title_change.html"));
content::WindowedNotificationObserver swap_observer(
- content::NOTIFICATION_WEB_CONTENTS_SWAPPED,
+ content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
content::Source<WebContents>(test_embedder()->web_contents()));
NavigateToURL(shell(), test_https_url);
swap_observer.Wait();
@@ -463,7 +439,13 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderChangedAfterSwap) {
// This test opens two pages in http and there is no RenderViewHost swap,
// therefore the embedder created on first page navigation stays the same in
// web_contents.
-IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderSameAfterNav) {
+// Failing flakily on Windows: crbug.com/308405
+#if defined(OS_WIN)
+#define MAYBE_EmbedderSameAfterNav DISABLED_EmbedderSameAfterNav
+#else
+#define MAYBE_EmbedderSameAfterNav EmbedderSameAfterNav
+#endif
+IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, MAYBE_EmbedderSameAfterNav) {
const char kEmbedderURL[] = "/browser_plugin_embedder.html";
StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
WebContentsImpl* embedder_web_contents = test_embedder()->web_contents();
@@ -472,13 +454,13 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderSameAfterNav) {
// does not happen and existing embedder doesn't change in web_contents.
GURL test_url_new(embedded_test_server()->GetURL(
"/browser_plugin_title_change.html"));
- const string16 expected_title = ASCIIToUTF16("done");
+ const base::string16 expected_title = ASCIIToUTF16("done");
content::TitleWatcher title_watcher(shell()->web_contents(), expected_title);
NavigateToURL(shell(), test_url_new);
- LOG(INFO) << "Start waiting for title";
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ VLOG(0) << "Start waiting for title";
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
- LOG(INFO) << "Done navigating to second page";
+ VLOG(0) << "Done navigating to second page";
TestBrowserPluginEmbedder* test_embedder_after_nav =
static_cast<TestBrowserPluginEmbedder*>(
@@ -527,8 +509,8 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AcceptTouchEvents) {
// Install the touch handler in the guest. This should cause the embedder to
// start listening for touch events too.
- RenderViewHostMessageObserver observer(rvh,
- ViewHostMsg_HasTouchEventHandlers::ID);
+ MessageObserver observer(test_embedder()->web_contents(),
+ ViewHostMsg_HasTouchEventHandlers::ID);
ExecuteSyncJSFunction(test_guest()->web_contents()->GetRenderViewHost(),
"InstallTouchHandler();");
observer.WaitUntilMessageReceived();
@@ -555,26 +537,26 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, ReloadEmbedder) {
// the page has successfully reloaded when it goes back to 'embedder'
// in the next step.
{
- const string16 expected_title = ASCIIToUTF16("modified");
+ const base::string16 expected_title = ASCIIToUTF16("modified");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
ExecuteSyncJSFunction(rvh,
base::StringPrintf("SetTitle('%s');", "modified"));
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
// Reload the embedder page, and verify that the reload was successful.
// Then navigate the guest to verify that the browser process does not crash.
{
- const string16 expected_title = ASCIIToUTF16("embedder");
+ const base::string16 expected_title = ASCIIToUTF16("embedder");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
test_embedder()->web_contents()->GetController().Reload(false);
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
ExecuteSyncJSFunction(
@@ -596,8 +578,9 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, ReloadEmbedder) {
}
}
-// Always failing in the win7_aura try bot. See http://crbug.com/181107.
-#if defined(OS_WIN) && defined(USE_AURA)
+// Always failing in the win7_aura try bot. See http://crbug.com/181107.
+// Times out on the Mac. See http://crbug.com/297576.
+#if (defined(OS_WIN) && defined(USE_AURA)) || defined(OS_MACOSX)
#define MAYBE_AcceptDragEvents DISABLED_AcceptDragEvents
#else
#define MAYBE_AcceptDragEvents AcceptDragEvents
@@ -636,17 +619,17 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, MAYBE_AcceptDragEvents) {
// This should trigger appropriate messages from the embedder to the guest,
// and end with a drop on the guest. The guest changes title when a drop
// happens.
- const string16 expected_title = ASCIIToUTF16("DROPPED");
+ const base::string16 expected_title = ASCIIToUTF16("DROPPED");
content::TitleWatcher title_watcher(test_guest()->web_contents(),
expected_title);
rvh->DragTargetDragEnter(drop_data, gfx::Point(start_x, start_y),
- gfx::Point(start_x, start_y), WebKit::WebDragOperationEvery, 0);
+ gfx::Point(start_x, start_y), blink::WebDragOperationEvery, 0);
rvh->DragTargetDragOver(gfx::Point(end_x, end_y), gfx::Point(end_x, end_y),
- WebKit::WebDragOperationEvery, 0);
+ blink::WebDragOperationEvery, 0);
rvh->DragTargetDrop(gfx::Point(end_x, end_y), gfx::Point(end_x, end_y), 0);
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
@@ -668,7 +651,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, PostMessage) {
RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
test_embedder()->web_contents()->GetRenderViewHost());
{
- const string16 expected_title = ASCIIToUTF16("main guest");
+ const base::string16 expected_title = ASCIIToUTF16("main guest");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
@@ -679,7 +662,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, PostMessage) {
// The title will be updated to "main guest" at the last stage of the
// process described above.
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
}
@@ -696,7 +679,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_PostMessageToIFrame) {
RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
test_embedder()->web_contents()->GetRenderViewHost());
{
- const string16 expected_title = ASCIIToUTF16("main guest");
+ const base::string16 expected_title = ASCIIToUTF16("main guest");
content::TitleWatcher title_watcher(test_embedder()->web_contents(),
expected_title);
@@ -705,7 +688,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_PostMessageToIFrame) {
// The title will be updated to "main guest" at the last stage of the
// process described above.
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
}
{
@@ -721,7 +704,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_PostMessageToIFrame) {
base::StringPrintf(
"CreateChildFrame('%s');", test_url.spec().c_str()));
- string16 actual_title = ready_watcher.WaitAndGetTitle();
+ base::string16 actual_title = ready_watcher.WaitAndGetTitle();
EXPECT_EQ(ASCIIToUTF16("ready"), actual_title);
content::TitleWatcher iframe_watcher(test_embedder()->web_contents(),
@@ -823,10 +806,234 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DoNotCrashOnInvalidNavigation) {
// should be blocked because the scheme isn't web-safe or a pseudo-scheme.
ExecuteSyncJSFunction(
test_embedder()->web_contents()->GetRenderViewHost(),
- base::StringPrintf("SetSrc('%s://abc123');",
- chrome::kGuestScheme));
+ base::StringPrintf("SetSrc('%s://abc123');", kGuestScheme));
EXPECT_TRUE(delegate->load_aborted());
EXPECT_TRUE(delegate->load_aborted_url().is_valid());
}
+// Tests involving the threaded compositor.
+class BrowserPluginThreadedCompositorTest : public BrowserPluginHostTest {
+ public:
+ BrowserPluginThreadedCompositorTest() {}
+ virtual ~BrowserPluginThreadedCompositorTest() {}
+
+ protected:
+ virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE {
+ BrowserPluginHostTest::SetUpCommandLine(cmd);
+ cmd->AppendSwitch(switches::kEnableThreadedCompositing);
+
+ // http://crbug.com/327035
+ cmd->AppendSwitch(switches::kDisableDelegatedRenderer);
+ }
+};
+
+static void CompareSkBitmaps(const SkBitmap& expected_bitmap,
+ const SkBitmap& bitmap) {
+ EXPECT_EQ(expected_bitmap.width(), bitmap.width());
+ if (expected_bitmap.width() != bitmap.width())
+ return;
+ EXPECT_EQ(expected_bitmap.height(), bitmap.height());
+ if (expected_bitmap.height() != bitmap.height())
+ return;
+ EXPECT_EQ(expected_bitmap.config(), bitmap.config());
+ if (expected_bitmap.config() != bitmap.config())
+ return;
+
+ SkAutoLockPixels expected_bitmap_lock(expected_bitmap);
+ SkAutoLockPixels bitmap_lock(bitmap);
+ int fails = 0;
+ const int kAllowableError = 2;
+ for (int i = 0; i < bitmap.width() && fails < 10; ++i) {
+ for (int j = 0; j < bitmap.height() && fails < 10; ++j) {
+ SkColor expected_color = expected_bitmap.getColor(i, j);
+ SkColor color = bitmap.getColor(i, j);
+ int expected_alpha = SkColorGetA(expected_color);
+ int alpha = SkColorGetA(color);
+ int expected_red = SkColorGetR(expected_color);
+ int red = SkColorGetR(color);
+ int expected_green = SkColorGetG(expected_color);
+ int green = SkColorGetG(color);
+ int expected_blue = SkColorGetB(expected_color);
+ int blue = SkColorGetB(color);
+ EXPECT_NEAR(expected_alpha, alpha, kAllowableError)
+ << "expected_color: " << std::hex << expected_color
+ << " color: " << color
+ << " Failed at " << std::dec << i << ", " << j
+ << " Failure " << ++fails;
+ EXPECT_NEAR(expected_red, red, kAllowableError)
+ << "expected_color: " << std::hex << expected_color
+ << " color: " << color
+ << " Failed at " << std::dec << i << ", " << j
+ << " Failure " << ++fails;
+ EXPECT_NEAR(expected_green, green, kAllowableError)
+ << "expected_color: " << std::hex << expected_color
+ << " color: " << color
+ << " Failed at " << std::dec << i << ", " << j
+ << " Failure " << ++fails;
+ EXPECT_NEAR(expected_blue, blue, kAllowableError)
+ << "expected_color: " << std::hex << expected_color
+ << " color: " << color
+ << " Failed at " << std::dec << i << ", " << j
+ << " Failure " << ++fails;
+ }
+ }
+ EXPECT_LT(fails, 10);
+}
+
+static void CompareSkBitmapAndRun(const base::Closure& callback,
+ const SkBitmap& expected_bitmap,
+ bool *result,
+ bool succeed,
+ const SkBitmap& bitmap) {
+ *result = succeed;
+ if (succeed)
+ CompareSkBitmaps(expected_bitmap, bitmap);
+ callback.Run();
+}
+
+// http://crbug.com/171744
+#if defined(OS_MACOSX)
+#define MAYBE_GetBackingStore DISABLED_GetBackingStore
+#else
+#define MAYBE_GetBackingStore GetBackingStore
+#endif
+IN_PROC_BROWSER_TEST_F(BrowserPluginThreadedCompositorTest,
+ MAYBE_GetBackingStore) {
+ const char kEmbedderURL[] = "/browser_plugin_embedder.html";
+ const char kHTMLForGuest[] =
+ "data:text/html,<html><style>body { background-color: red; }</style>"
+ "<body></body></html>";
+ StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true,
+ std::string("SetSize(50, 60);"));
+
+ WebContentsImpl* guest_contents = test_guest()->web_contents();
+ RenderWidgetHostImpl* guest_widget_host =
+ RenderWidgetHostImpl::From(guest_contents->GetRenderViewHost());
+
+ SkBitmap expected_bitmap;
+ expected_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 50, 60);
+ expected_bitmap.allocPixels();
+ expected_bitmap.eraseARGB(255, 255, 0, 0); // #f00
+ bool result = false;
+ while (!result) {
+ base::RunLoop loop;
+ guest_widget_host->CopyFromBackingStore(gfx::Rect(),
+ guest_widget_host->GetView()->GetViewBounds().size(),
+ base::Bind(&CompareSkBitmapAndRun, loop.QuitClosure(), expected_bitmap,
+ &result));
+ loop.Run();
+ }
+}
+
+// Tests input method.
+IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, InputMethod) {
+ const char kEmbedderURL[] = "/browser_plugin_embedder.html";
+ const char kGuestHTML[] = "data:text/html,"
+ "<html><body><input id=\"input1\">"
+ "<input id=\"input2\"></body>"
+ "<script>"
+ "var i = document.getElementById(\"input1\");"
+ "i.oninput = function() {"
+ " document.title = i.value;"
+ "}"
+ "</script>"
+ "</html>";
+ StartBrowserPluginTest(kEmbedderURL, kGuestHTML, true,
+ "document.getElementById(\"plugin\").focus();");
+
+ RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
+ test_embedder()->web_contents()->GetRenderViewHost());
+ RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
+ test_guest()->web_contents()->GetRenderViewHost());
+
+ std::vector<blink::WebCompositionUnderline> underlines;
+
+ // An input field in browser plugin guest gets focus and given some user
+ // input via IME.
+ {
+ ExecuteSyncJSFunction(guest_rvh,
+ "document.getElementById('input1').focus();");
+ string16 expected_title = UTF8ToUTF16("InputTest123");
+ content::TitleWatcher title_watcher(test_guest()->web_contents(),
+ expected_title);
+ embedder_rvh->Send(
+ new ViewMsg_ImeSetComposition(
+ test_embedder()->web_contents()->GetRoutingID(),
+ expected_title,
+ underlines,
+ 12, 12));
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
+ EXPECT_EQ(expected_title, actual_title);
+ }
+ // A composition is committed via IME.
+ {
+ string16 expected_title = UTF8ToUTF16("InputTest456");
+ content::TitleWatcher title_watcher(test_guest()->web_contents(),
+ expected_title);
+ embedder_rvh->Send(
+ new ViewMsg_ImeConfirmComposition(
+ test_embedder()->web_contents()->GetRoutingID(),
+ expected_title,
+ gfx::Range(),
+ true));
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
+ EXPECT_EQ(expected_title, actual_title);
+ }
+ // IME composition starts, but focus moves out, then the composition will
+ // be committed and get cancel msg.
+ {
+ ExecuteSyncJSFunction(guest_rvh,
+ "document.getElementById('input1').value = '';");
+ string16 composition = UTF8ToUTF16("InputTest789");
+ content::TitleWatcher title_watcher(test_guest()->web_contents(),
+ composition);
+ embedder_rvh->Send(
+ new ViewMsg_ImeSetComposition(
+ test_embedder()->web_contents()->GetRoutingID(),
+ composition,
+ underlines,
+ 12, 12));
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
+ EXPECT_EQ(composition, actual_title);
+ // Moving focus causes IME cancel, and the composition will be committed
+ // in input1, not in input2.
+ ExecuteSyncJSFunction(guest_rvh,
+ "document.getElementById('input2').focus();");
+ test_guest()->WaitForImeCancel();
+ scoped_ptr<base::Value> value =
+ content::ExecuteScriptAndGetValue(
+ guest_rvh, "document.getElementById('input1').value");
+ std::string result;
+ ASSERT_TRUE(value->GetAsString(&result));
+ EXPECT_EQ(UTF16ToUTF8(composition), result);
+ }
+ // Tests ExtendSelectionAndDelete message works in browser_plugin.
+ {
+ // Set 'InputTestABC' in input1 and put caret at 6 (after 'T').
+ ExecuteSyncJSFunction(guest_rvh,
+ "var i = document.getElementById('input1');"
+ "i.focus();"
+ "i.value = 'InputTestABC';"
+ "i.selectionStart=6;"
+ "i.selectionEnd=6;");
+ string16 expected_value = UTF8ToUTF16("InputABC");
+ content::TitleWatcher title_watcher(test_guest()->web_contents(),
+ expected_value);
+ // Delete 'Test' in 'InputTestABC', as the caret is after 'T':
+ // delete before 1 character ('T') and after 3 characters ('est').
+ embedder_rvh->Send(
+ new ViewMsg_ExtendSelectionAndDelete(
+ test_embedder()->web_contents()->GetRoutingID(),
+ 1, 3));
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
+ EXPECT_EQ(expected_value, actual_title);
+ scoped_ptr<base::Value> value =
+ content::ExecuteScriptAndGetValue(
+ guest_rvh, "document.getElementById('input1').value");
+ std::string actual_value;
+ ASSERT_TRUE(value->GetAsString(&actual_value));
+ EXPECT_EQ(UTF16ToUTF8(expected_value), actual_value);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_plugin/test_browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/test_browser_plugin_guest.cc
index a6e62a3ba55..91ba2909d21 100644
--- a/chromium/content/browser/browser_plugin/test_browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/test_browser_plugin_guest.cc
@@ -8,7 +8,6 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
-#include "content/public/browser/notification_types.h"
namespace content {
@@ -17,7 +16,7 @@ class BrowserPluginGuest;
TestBrowserPluginGuest::TestBrowserPluginGuest(
int instance_id,
WebContentsImpl* web_contents)
- : BrowserPluginGuest(instance_id, web_contents, NULL, false),
+ : BrowserPluginGuest(instance_id, false, web_contents, NULL),
update_rect_count_(0),
damage_buffer_call_count_(0),
exit_observed_(false),
@@ -28,12 +27,9 @@ TestBrowserPluginGuest::TestBrowserPluginGuest(
set_damage_buffer_observed_(false),
input_observed_(false),
load_stop_observed_(false),
+ ime_cancel_observed_(false),
waiting_for_damage_buffer_with_size_(false),
last_damage_buffer_size_(gfx::Size()) {
- // Listen to visibility changes so that a test can wait for these changes.
- notification_registrar_.Add(this,
- NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
- Source<WebContents>(web_contents));
}
TestBrowserPluginGuest::~TestBrowserPluginGuest() {
@@ -43,24 +39,6 @@ WebContentsImpl* TestBrowserPluginGuest::web_contents() const {
return static_cast<WebContentsImpl*>(BrowserPluginGuest::web_contents());
}
-void TestBrowserPluginGuest::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- switch (type) {
- case NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED: {
- bool visible = *Details<bool>(details).ptr();
- if (!visible) {
- was_hidden_observed_ = true;
- if (was_hidden_message_loop_runner_.get())
- was_hidden_message_loop_runner_->Quit();
- }
- return;
- }
- }
-
- BrowserPluginGuest::Observe(type, source, details);
-}
-
void TestBrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
if (msg->type() == BrowserPluginMsg_UpdateRect::ID) {
update_rect_count_++;
@@ -106,7 +84,7 @@ void TestBrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
exit_observed_ = true;
if (status != base::TERMINATION_STATUS_NORMAL_TERMINATION &&
status != base::TERMINATION_STATUS_STILL_RUNNING)
- LOG(INFO) << "Guest crashed status: " << status;
+ VLOG(0) << "Guest crashed status: " << status;
if (crash_message_loop_runner_.get())
crash_message_loop_runner_->Quit();
BrowserPluginGuest::RenderProcessGone(status);
@@ -115,7 +93,7 @@ void TestBrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
void TestBrowserPluginGuest::OnHandleInputEvent(
int instance_id,
const gfx::Rect& guest_window_rect,
- const WebKit::WebInputEvent* event) {
+ const blink::WebInputEvent* event) {
BrowserPluginGuest::OnHandleInputEvent(instance_id,
guest_window_rect,
event);
@@ -204,6 +182,17 @@ void TestBrowserPluginGuest::WaitForViewSize(const gfx::Size& view_size) {
last_view_size_observed_ = gfx::Size();
}
+void TestBrowserPluginGuest::WaitForImeCancel() {
+ if (ime_cancel_observed_) {
+ ime_cancel_observed_ = false;
+ return;
+ }
+
+ ime_cancel_message_loop_runner_ = new MessageLoopRunner();
+ ime_cancel_message_loop_runner_->Run();
+ ime_cancel_observed_ = false;
+}
+
void TestBrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
if (focused) {
focus_observed_ = true;
@@ -247,4 +236,19 @@ void TestBrowserPluginGuest::DidStopLoading(
load_stop_message_loop_runner_->Quit();
}
+void TestBrowserPluginGuest::OnImeCancelComposition() {
+ if (!ime_cancel_observed_) {
+ ime_cancel_observed_ = true;
+ if (ime_cancel_message_loop_runner_.get())
+ ime_cancel_message_loop_runner_->Quit();
+ }
+ BrowserPluginGuest::OnImeCancelComposition();
+}
+
+void TestBrowserPluginGuest::WasHidden() {
+ was_hidden_observed_ = true;
+ if (was_hidden_message_loop_runner_.get())
+ was_hidden_message_loop_runner_->Quit();
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_plugin/test_browser_plugin_guest.h b/chromium/content/browser/browser_plugin/test_browser_plugin_guest.h
index 7fccb002388..1ef7f0dbecf 100644
--- a/chromium/content/browser/browser_plugin/test_browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/test_browser_plugin_guest.h
@@ -27,21 +27,20 @@ class TestBrowserPluginGuest : public BrowserPluginGuest {
WebContentsImpl* web_contents() const;
- // NotificationObserver method override.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
-
// Overridden methods from BrowserPluginGuest to intercept in test objects.
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
virtual void OnHandleInputEvent(int instance_id,
const gfx::Rect& guest_window_rect,
- const WebKit::WebInputEvent* event) OVERRIDE;
+ const blink::WebInputEvent* event) OVERRIDE;
virtual void OnSetFocus(int instance_id, bool focused) OVERRIDE;
virtual void OnTakeFocus(bool reverse) OVERRIDE;
virtual void SetDamageBuffer(
const BrowserPluginHostMsg_ResizeGuest_Params& params) OVERRIDE;
virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE;
+ virtual void OnImeCancelComposition() OVERRIDE;
+
+ // Overridden from WebContentsObserver.
+ virtual void WasHidden() OVERRIDE;
// Test utilities to wait for a event we are interested in.
// Waits until UpdateRect message is sent from the guest, meaning it is
@@ -66,6 +65,12 @@ class TestBrowserPluginGuest : public BrowserPluginGuest {
void WaitForLoadStop();
// Waits until UpdateRect with a particular |view_size| is observed.
void WaitForViewSize(const gfx::Size& view_size);
+ // Waits until IME cancellation is observed.
+ void WaitForImeCancel();
+
+ void set_guest_hang_timeout(const base::TimeDelta& timeout) {
+ guest_hang_timeout_ = timeout;
+ }
private:
// Overridden methods from BrowserPluginGuest to intercept in test objects.
@@ -81,6 +86,7 @@ class TestBrowserPluginGuest : public BrowserPluginGuest {
bool set_damage_buffer_observed_;
bool input_observed_;
bool load_stop_observed_;
+ bool ime_cancel_observed_;
gfx::Size last_view_size_observed_;
gfx::Size expected_auto_view_size_;
@@ -99,6 +105,7 @@ class TestBrowserPluginGuest : public BrowserPluginGuest {
scoped_refptr<MessageLoopRunner> input_message_loop_runner_;
scoped_refptr<MessageLoopRunner> load_stop_message_loop_runner_;
scoped_refptr<MessageLoopRunner> auto_view_size_message_loop_runner_;
+ scoped_refptr<MessageLoopRunner> ime_cancel_message_loop_runner_;
DISALLOW_COPY_AND_ASSIGN(TestBrowserPluginGuest);
};
diff --git a/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc b/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc
index 28c27b7578e..59ae63555d9 100644
--- a/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc
+++ b/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc
@@ -20,9 +20,9 @@ void TestBrowserPluginGuestDelegate::ResetStates() {
void TestBrowserPluginGuestDelegate::AddMessageToConsole(
int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id) {
+ const base::string16& source_id) {
}
void TestBrowserPluginGuestDelegate::Close() {
@@ -53,10 +53,12 @@ void TestBrowserPluginGuestDelegate::RendererUnresponsive() {
bool TestBrowserPluginGuestDelegate::RequestPermission(
BrowserPluginPermissionType permission_type,
const base::DictionaryValue& request_info,
- const PermissionResponseCallback& callback) {
+ const PermissionResponseCallback& callback,
+ bool allowed_by_default) {
return BrowserPluginGuestDelegate::RequestPermission(permission_type,
request_info,
- callback);
+ callback,
+ allowed_by_default);
}
void TestBrowserPluginGuestDelegate::SizeChanged(const gfx::Size& old_size,
diff --git a/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h b/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h
index b6e7e9079f3..4bfae4c622f 100644
--- a/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h
+++ b/chromium/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h
@@ -22,9 +22,9 @@ class TestBrowserPluginGuestDelegate : public BrowserPluginGuestDelegate {
private:
// Overridden from BrowserPluginGuestDelegate:
virtual void AddMessageToConsole(int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id) OVERRIDE;
+ const base::string16& source_id) OVERRIDE;
virtual void Close() OVERRIDE;
virtual void GuestProcessGone(base::TerminationStatus status) OVERRIDE;
virtual bool HandleKeyboardEvent(
@@ -37,7 +37,8 @@ class TestBrowserPluginGuestDelegate : public BrowserPluginGuestDelegate {
virtual bool RequestPermission(
BrowserPluginPermissionType permission_type,
const base::DictionaryValue& request_info,
- const PermissionResponseCallback& callback) OVERRIDE;
+ const PermissionResponseCallback& callback,
+ bool allowed_by_default) OVERRIDE;
virtual void SizeChanged(const gfx::Size& old_size,
const gfx::Size& new_size) OVERRIDE;
diff --git a/chromium/content/browser/browser_shutdown_profile_dumper.cc b/chromium/content/browser/browser_shutdown_profile_dumper.cc
index 70e3e5389c1..3e74e063b0c 100644
--- a/chromium/content/browser/browser_shutdown_profile_dumper.cc
+++ b/chromium/content/browser/browser_shutdown_profile_dumper.cc
@@ -37,7 +37,7 @@ void BrowserShutdownProfileDumper::WriteTracesToDisc(
base::debug::TraceLog::GetInstance()->GetBufferPercentFull() <<
" full.";
DCHECK(!dump_file_);
- dump_file_ = file_util::OpenFile(file_name, "w+");
+ dump_file_ = base::OpenFile(file_name, "w+");
if (!IsFileValid()) {
LOG(ERROR) << "Failed to open performance trace file: " <<
file_name.value();
@@ -65,8 +65,7 @@ void BrowserShutdownProfileDumper::WriteTracesToDisc(
void BrowserShutdownProfileDumper::EndTraceAndFlush(
base::WaitableEvent* flush_complete_event) {
- while (base::debug::TraceLog::GetInstance()->IsEnabled())
- base::debug::TraceLog::GetInstance()->SetDisabled();
+ base::debug::TraceLog::GetInstance()->SetDisabled();
base::debug::TraceLog::GetInstance()->Flush(
base::Bind(&BrowserShutdownProfileDumper::WriteTraceDataCollected,
base::Unretained(this),
@@ -132,7 +131,7 @@ void BrowserShutdownProfileDumper::WriteChars(const char* chars, size_t size) {
void BrowserShutdownProfileDumper::CloseFile() {
if (!dump_file_)
return;
- file_util::CloseFile(dump_file_);
+ base::CloseFile(dump_file_);
dump_file_ = NULL;
}
diff --git a/chromium/content/browser/browser_thread_impl.cc b/chromium/content/browser/browser_thread_impl.cc
index fb6feac452f..099ec3b72a4 100644
--- a/chromium/content/browser/browser_thread_impl.cc
+++ b/chromium/content/browser/browser_thread_impl.cc
@@ -167,7 +167,7 @@ MSVC_POP_WARNING()
MSVC_ENABLE_OPTIMIZE();
void BrowserThreadImpl::Run(base::MessageLoop* message_loop) {
- BrowserThread::ID thread_id;
+ BrowserThread::ID thread_id = ID_COUNT;
if (!GetCurrentThreadIdentifier(&thread_id))
return Thread::Run(message_loop);
@@ -248,7 +248,7 @@ bool BrowserThreadImpl::PostTaskHelper(
// Note: since the array is so small, ok to loop instead of creating a map,
// which would require a lock because std::map isn't thread safe, defeating
// the whole purpose of this optimization.
- BrowserThread::ID current_thread;
+ BrowserThread::ID current_thread = ID_COUNT;
bool target_thread_outlives_current =
GetCurrentThreadIdentifier(&current_thread) &&
current_thread >= identifier;
@@ -316,6 +316,7 @@ bool BrowserThread::PostBlockingPoolTask(
return g_globals.Get().blocking_pool->PostWorkerTask(from_here, task);
}
+// static
bool BrowserThread::PostBlockingPoolTaskAndReply(
const tracked_objects::Location& from_here,
const base::Closure& task,
diff --git a/chromium/content/browser/browser_url_handler_impl.cc b/chromium/content/browser/browser_url_handler_impl.cc
index 5ff1309f1a8..05cc72df474 100644
--- a/chromium/content/browser/browser_url_handler_impl.cc
+++ b/chromium/content/browser/browser_url_handler_impl.cc
@@ -4,9 +4,12 @@
#include "content/browser/browser_url_handler_impl.h"
+#include "base/command_line.h"
#include "base/strings/string_util.h"
+#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/webui/web_ui_impl.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "url/gurl.h"
@@ -16,12 +19,12 @@ namespace content {
static bool HandleViewSource(GURL* url, BrowserContext* browser_context) {
if (url->SchemeIs(kViewSourceScheme)) {
// Load the inner URL instead.
- *url = GURL(url->path());
+ *url = GURL(url->GetContent());
// Bug 26129: limit view-source to view the content and not any
// other kind of 'active' url scheme like 'javascript' or 'data'.
static const char* const allowed_sub_schemes[] = {
- kHttpScheme, kHttpsScheme, chrome::kFtpScheme,
+ kHttpScheme, kHttpsScheme, kFtpScheme,
chrome::kChromeDevToolsScheme, chrome::kChromeUIScheme,
chrome::kFileScheme, chrome::kFileSystemScheme
};
@@ -59,7 +62,18 @@ static bool ReverseViewSource(GURL* url, BrowserContext* browser_context) {
return true;
}
-static bool HandleDebugUrl(GURL* url, BrowserContext* browser_context) {
+static bool DebugURLHandler(GURL* url, BrowserContext* browser_context) {
+ // If running inside the Telemetry test harness, allow automated
+ // navigations to access browser-side debug URLs. They must use the
+ // chrome:// scheme, since the about: scheme won't be rewritten in
+ // this code path.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableGpuBenchmarking)) {
+ if (HandleDebugURL(*url, PAGE_TRANSITION_FROM_ADDRESS_BAR)) {
+ return true;
+ }
+ }
+
// Circumvent processing URLs that the renderer process will handle.
return *url == GURL(kChromeUICrashURL) ||
*url == GURL(kChromeUIHangURL) ||
@@ -84,7 +98,7 @@ BrowserURLHandlerImpl* BrowserURLHandlerImpl::GetInstance() {
}
BrowserURLHandlerImpl::BrowserURLHandlerImpl() {
- AddHandlerPair(&HandleDebugUrl, BrowserURLHandlerImpl::null_handler());
+ AddHandlerPair(&DebugURLHandler, BrowserURLHandlerImpl::null_handler());
GetContentClient()->browser()->BrowserURLHandlerCreated(this);
diff --git a/chromium/content/browser/cert_store_impl.cc b/chromium/content/browser/cert_store_impl.cc
index e7fc1d24060..cd24b9654ce 100644
--- a/chromium/content/browser/cert_store_impl.cc
+++ b/chromium/content/browser/cert_store_impl.cc
@@ -4,28 +4,6 @@
#include "content/browser/cert_store_impl.h"
-#include <algorithm>
-#include <functional>
-
-#include "base/bind.h"
-#include "base/stl_util.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-
-template <typename T>
-struct MatchSecond {
- explicit MatchSecond(const T& t) : value(t) {}
-
- template<typename Pair>
- bool operator()(const Pair& p) const {
- return (value == p.second);
- }
- T value;
-};
-
namespace content {
// static
@@ -38,145 +16,17 @@ CertStoreImpl* CertStoreImpl::GetInstance() {
return Singleton<CertStoreImpl>::get();
}
-CertStoreImpl::CertStoreImpl() : next_cert_id_(1) {
- if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- RegisterForNotification();
- } else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&CertStoreImpl::RegisterForNotification,
- base::Unretained(this)));
- }
-}
-
-CertStoreImpl::~CertStoreImpl() {
-}
+CertStoreImpl::CertStoreImpl() {}
-void CertStoreImpl::RegisterForNotification() {
- // We watch for RenderProcess termination, as this is how we clear
- // certificates for now.
- // TODO(jcampan): we should be listening to events such as resource cached/
- // removed from cache, and remove the cert when we know it
- // is not used anymore.
-
- registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
- NotificationService::AllBrowserContextsAndSources());
- registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED,
- NotificationService::AllBrowserContextsAndSources());
-}
+CertStoreImpl::~CertStoreImpl() {}
int CertStoreImpl::StoreCert(net::X509Certificate* cert, int process_id) {
- DCHECK(cert);
- base::AutoLock auto_lock(cert_lock_);
-
- int cert_id;
-
- // Do we already know this cert?
- ReverseCertMap::iterator cert_iter = cert_to_id_.find(cert);
- if (cert_iter == cert_to_id_.end()) {
- cert_id = next_cert_id_++;
- // We use 0 as an invalid cert_id value. In the unlikely event that
- // next_cert_id_ wraps around, we reset it to 1.
- if (next_cert_id_ == 0)
- next_cert_id_ = 1;
- cert->AddRef();
- id_to_cert_[cert_id] = cert;
- cert_to_id_[cert] = cert_id;
- } else {
- cert_id = cert_iter->second;
- }
-
- // Let's update process_id_to_cert_id_.
- std::pair<IDMap::iterator, IDMap::iterator> process_ids =
- process_id_to_cert_id_.equal_range(process_id);
- if (std::find_if(process_ids.first, process_ids.second,
- MatchSecond<int>(cert_id)) == process_ids.second) {
- process_id_to_cert_id_.insert(std::make_pair(process_id, cert_id));
- }
-
- // And cert_id_to_process_id_.
- std::pair<IDMap::iterator, IDMap::iterator> cert_ids =
- cert_id_to_process_id_.equal_range(cert_id);
- if (std::find_if(cert_ids.first, cert_ids.second,
- MatchSecond<int>(process_id)) == cert_ids.second) {
- cert_id_to_process_id_.insert(std::make_pair(cert_id, process_id));
- }
-
- return cert_id;
+ return store_.Store(cert, process_id);
}
bool CertStoreImpl::RetrieveCert(int cert_id,
scoped_refptr<net::X509Certificate>* cert) {
- base::AutoLock auto_lock(cert_lock_);
-
- CertMap::iterator iter = id_to_cert_.find(cert_id);
- if (iter == id_to_cert_.end())
- return false;
- if (cert)
- *cert = iter->second;
- return true;
-}
-
-void CertStoreImpl::RemoveCertInternal(int cert_id) {
- CertMap::iterator cert_iter = id_to_cert_.find(cert_id);
- DCHECK(cert_iter != id_to_cert_.end());
-
- ReverseCertMap::iterator id_iter = cert_to_id_.find(cert_iter->second.get());
- DCHECK(id_iter != cert_to_id_.end());
- cert_to_id_.erase(id_iter);
-
- cert_iter->second->Release();
- id_to_cert_.erase(cert_iter);
-}
-
-void CertStoreImpl::RemoveCertsForRenderProcesHost(int process_id) {
- base::AutoLock auto_lock(cert_lock_);
-
- // We iterate through all the cert ids for that process.
- std::pair<IDMap::iterator, IDMap::iterator> process_ids =
- process_id_to_cert_id_.equal_range(process_id);
- for (IDMap::iterator ids_iter = process_ids.first;
- ids_iter != process_ids.second; ++ids_iter) {
- int cert_id = ids_iter->second;
- // Find all the processes referring to this cert id in
- // cert_id_to_process_id_, then locate the process being removed within
- // that range.
- std::pair<IDMap::iterator, IDMap::iterator> cert_ids =
- cert_id_to_process_id_.equal_range(cert_id);
- IDMap::iterator proc_iter =
- std::find_if(cert_ids.first, cert_ids.second,
- MatchSecond<int>(process_id));
- DCHECK(proc_iter != cert_ids.second);
-
- // Before removing, determine if no other processes refer to the current
- // cert id. If |proc_iter| (the current process) is the lower bound of
- // processes containing the current cert id and if |next_proc_iter| is the
- // upper bound (the first process that does not), then only one process,
- // the one being removed, refers to the cert id.
- IDMap::iterator next_proc_iter = proc_iter;
- ++next_proc_iter;
- bool last_process_for_cert_id =
- (proc_iter == cert_ids.first && next_proc_iter == cert_ids.second);
- cert_id_to_process_id_.erase(proc_iter);
-
- if (last_process_for_cert_id) {
- // The current cert id is not referenced by any other processes, so
- // remove it from id_to_cert_ and cert_to_id_.
- RemoveCertInternal(cert_id);
- }
- }
- if (process_ids.first != process_ids.second)
- process_id_to_cert_id_.erase(process_ids.first, process_ids.second);
-}
-
-void CertStoreImpl::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- DCHECK(type == NOTIFICATION_RENDERER_PROCESS_TERMINATED ||
- type == NOTIFICATION_RENDERER_PROCESS_CLOSED);
- RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
- DCHECK(rph);
- RemoveCertsForRenderProcesHost(rph->GetID());
+ return store_.Retrieve(cert_id, cert);
}
} // namespace content
diff --git a/chromium/content/browser/cert_store_impl.h b/chromium/content/browser/cert_store_impl.h
index 8a326e95e8f..cba87207d27 100644
--- a/chromium/content/browser/cert_store_impl.h
+++ b/chromium/content/browser/cert_store_impl.h
@@ -5,19 +5,14 @@
#ifndef CONTENT_BROWSER_CERT_STORE_IMPL_H_
#define CONTENT_BROWSER_CERT_STORE_IMPL_H_
-#include <map>
-
#include "base/memory/singleton.h"
-#include "base/synchronization/lock.h"
+#include "content/browser/renderer_data_memoizing_store.h"
#include "content/public/browser/cert_store.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
#include "net/cert/x509_certificate.h"
namespace content {
-class CertStoreImpl : public CertStore,
- public NotificationObserver {
+class CertStoreImpl : public CertStore {
public:
// Returns the singleton instance of the CertStore.
static CertStoreImpl* GetInstance();
@@ -28,10 +23,6 @@ class CertStoreImpl : public CertStore,
virtual bool RetrieveCert(int cert_id,
scoped_refptr<net::X509Certificate>* cert) OVERRIDE;
- // NotificationObserver implementation.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
protected:
CertStoreImpl();
virtual ~CertStoreImpl();
@@ -39,34 +30,7 @@ class CertStoreImpl : public CertStore,
private:
friend struct DefaultSingletonTraits<CertStoreImpl>;
- void RegisterForNotification();
-
- // Remove the specified cert from id_to_cert_ and cert_to_id_.
- // NOTE: the caller (RemoveCertsForRenderProcesHost) must hold cert_lock_.
- void RemoveCertInternal(int cert_id);
-
- // Removes all the certs associated with the specified process from the store.
- void RemoveCertsForRenderProcesHost(int render_process_host_id);
-
- typedef std::multimap<int, int> IDMap;
- typedef std::map<int, scoped_refptr<net::X509Certificate> > CertMap;
- typedef std::map<net::X509Certificate*, int, net::X509Certificate::LessThan>
- ReverseCertMap;
-
- // Is only used on the UI Thread.
- NotificationRegistrar registrar_;
-
- IDMap process_id_to_cert_id_;
- IDMap cert_id_to_process_id_;
-
- CertMap id_to_cert_;
- ReverseCertMap cert_to_id_;
-
- int next_cert_id_;
-
- // This lock protects: process_to_ids_, id_to_processes_, id_to_cert_ and
- // cert_to_id_.
- base::Lock cert_lock_;
+ RendererDataMemoizingStore<net::X509Certificate> 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 721cd5a88ed..3a162119bd5 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -32,6 +32,7 @@
#include "base/android/jni_android.h"
#include "content/browser/android/child_process_launcher_android.h"
#elif defined(OS_POSIX)
+#include "base/memory/shared_memory.h"
#include "base/memory/singleton.h"
#include "content/browser/renderer_host/render_sandbox_host_linux.h"
#include "content/browser/zygote_host/zygote_host_impl_linux.h"
@@ -39,6 +40,7 @@
#endif
#if defined(OS_POSIX)
+#include "base/metrics/stats_table.h"
#include "base/posix/global_descriptors.h"
#endif
@@ -197,17 +199,27 @@ class ChildProcessLauncher::Context
#if defined(OS_WIN)
scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
base::ProcessHandle handle = StartSandboxedProcess(delegate, cmd_line);
-#elif defined(OS_ANDROID)
- // Android WebView runs in single process, ensure that we never get here
- // when running in single process mode.
- CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
-
+#elif defined(OS_POSIX)
std::string process_type =
cmd_line->GetSwitchValueASCII(switches::kProcessType);
std::vector<FileDescriptorInfo> files_to_register;
files_to_register.push_back(
FileDescriptorInfo(kPrimaryIPCChannel,
- base::FileDescriptor(ipcfd, false)));
+ base::FileDescriptor(ipcfd, false)));
+ base::StatsTable* stats_table = base::StatsTable::current();
+ if (stats_table &&
+ base::SharedMemory::IsHandleValid(
+ stats_table->GetSharedMemoryHandle())) {
+ files_to_register.push_back(
+ FileDescriptorInfo(kStatsTableSharedMemFd,
+ stats_table->GetSharedMemoryHandle()));
+ }
+#endif
+
+#if defined(OS_ANDROID)
+ // Android WebView runs in single process, ensure that we never get here
+ // when running in single process mode.
+ CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
GetContentClient()->browser()->
GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
@@ -223,13 +235,6 @@ class ChildProcessLauncher::Context
// child termination.
file_util::ScopedFD ipcfd_closer(&ipcfd);
- std::string process_type =
- cmd_line->GetSwitchValueASCII(switches::kProcessType);
- std::vector<FileDescriptorInfo> files_to_register;
- files_to_register.push_back(
- FileDescriptorInfo(kPrimaryIPCChannel,
- base::FileDescriptor(ipcfd, false)));
-
#if !defined(OS_MACOSX)
GetContentClient()->browser()->
GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
@@ -368,7 +373,7 @@ class ChildProcessLauncher::Context
#endif
base::ProcessHandle handle) {
#if defined(OS_ANDROID)
- LOG(INFO) << "ChromeProcess: Stopping process with handle " << handle;
+ VLOG(0) << "ChromeProcess: Stopping process with handle " << handle;
StopChildProcess(handle);
#else
base::Process process(handle);
@@ -464,14 +469,22 @@ base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
if (context_->zygote_) {
context_->termination_status_ = ZygoteHostImpl::GetInstance()->
GetTerminationStatus(handle, known_dead, &context_->exit_code_);
- } else
+ } else if (known_dead) {
+ context_->termination_status_ =
+ base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_);
+ } else {
#elif defined(OS_MACOSX)
if (known_dead) {
context_->termination_status_ =
base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_);
- } else
-#endif
+ } else {
+#elif defined(OS_ANDROID)
+ if (IsChildProcessOomProtected(handle)) {
+ context_->termination_status_ = base::TERMINATION_STATUS_OOM_PROTECTED;
+ } else {
+#else
{
+#endif
context_->termination_status_ =
base::GetTerminationStatus(handle, &context_->exit_code_);
}
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index 6933f9e0b1d..0667964f3e2 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -31,43 +31,38 @@ namespace content {
namespace {
-const int kReadFilePermissions =
- base::PLATFORM_FILE_OPEN |
- base::PLATFORM_FILE_READ |
- base::PLATFORM_FILE_EXCLUSIVE_READ |
- base::PLATFORM_FILE_ASYNC;
-
-const int kWriteFilePermissions =
- base::PLATFORM_FILE_OPEN |
- base::PLATFORM_FILE_WRITE |
- base::PLATFORM_FILE_APPEND |
- base::PLATFORM_FILE_EXCLUSIVE_WRITE |
- base::PLATFORM_FILE_ASYNC |
- base::PLATFORM_FILE_WRITE_ATTRIBUTES;
-
-const int kCreateFilePermissions =
- base::PLATFORM_FILE_CREATE;
-
-const int kEnumerateDirectoryPermissions =
- kReadFilePermissions |
- base::PLATFORM_FILE_ENUMERATE;
-
-// TODO(tommycli): These flag sets need some work to make more obvious.
-// Why for instance, does Create|Write != CreateWrite? http://crbug.com/263150
-const int kCreateReadWriteFilePermissions =
- kReadFilePermissions |
- kWriteFilePermissions |
- kCreateFilePermissions |
- base::PLATFORM_FILE_OPEN_ALWAYS |
- base::PLATFORM_FILE_CREATE_ALWAYS |
- base::PLATFORM_FILE_OPEN_TRUNCATED;
-
-const int kCreateWriteFilePermissions =
- kWriteFilePermissions |
- kCreateFilePermissions |
- base::PLATFORM_FILE_OPEN_ALWAYS |
- base::PLATFORM_FILE_CREATE_ALWAYS |
- base::PLATFORM_FILE_OPEN_TRUNCATED;
+// Used internally only. These bit positions have no relationship to any
+// underlying OS and can be changed to accommodate finer-grained permissions.
+enum ChildProcessSecurityPermissions {
+ READ_FILE_PERMISSION = 1 << 0,
+ WRITE_FILE_PERMISSION = 1 << 1,
+ CREATE_NEW_FILE_PERMISSION = 1 << 2,
+ CREATE_OVERWRITE_FILE_PERMISSION = 1 << 3,
+ DELETE_FILE_PERMISSION = 1 << 4,
+
+ // Used by Media Galleries API
+ COPY_INTO_FILE_PERMISSION = 1 << 5,
+};
+
+// Used internally only. Bitmasks that are actually used by the Grant* and Can*
+// methods. These contain one or more ChildProcessSecurityPermissions.
+enum ChildProcessSecurityGrants {
+ READ_FILE_GRANT = READ_FILE_PERMISSION,
+ WRITE_FILE_GRANT = WRITE_FILE_PERMISSION,
+
+ CREATE_NEW_FILE_GRANT = CREATE_NEW_FILE_PERMISSION |
+ COPY_INTO_FILE_PERMISSION,
+
+ CREATE_READ_WRITE_FILE_GRANT = CREATE_NEW_FILE_PERMISSION |
+ CREATE_OVERWRITE_FILE_PERMISSION |
+ READ_FILE_PERMISSION |
+ WRITE_FILE_PERMISSION |
+ COPY_INTO_FILE_PERMISSION |
+ DELETE_FILE_PERMISSION,
+
+ COPY_INTO_FILE_GRANT = COPY_INTO_FILE_PERMISSION,
+ DELETE_FILE_GRANT = DELETE_FILE_PERMISSION,
+};
} // namespace
@@ -126,20 +121,35 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
// Grant certain permissions to a file.
void GrantPermissionsForFileSystem(const std::string& filesystem_id,
int permissions) {
- if (filesystem_permissions_.find(filesystem_id) ==
- filesystem_permissions_.end())
+ if (!ContainsKey(filesystem_permissions_, filesystem_id))
fileapi::IsolatedContext::GetInstance()->AddReference(filesystem_id);
filesystem_permissions_[filesystem_id] |= permissions;
}
bool HasPermissionsForFileSystem(const std::string& filesystem_id,
int permissions) {
- if (filesystem_permissions_.find(filesystem_id) ==
- filesystem_permissions_.end())
+ FileSystemMap::const_iterator it =
+ filesystem_permissions_.find(filesystem_id);
+ if (it == filesystem_permissions_.end())
+ return false;
+ return (it->second & permissions) == permissions;
+ }
+
+#if defined(OS_ANDROID)
+ // Determine if the certain permissions have been granted to a content URI.
+ bool HasPermissionsForContentUri(const base::FilePath& file,
+ int permissions) {
+ DCHECK(!file.empty());
+ DCHECK(file.IsContentUri());
+ if (!permissions)
return false;
- return (filesystem_permissions_[filesystem_id] & permissions) ==
- permissions;
+ base::FilePath file_path = file.StripTrailingSeparators();
+ FileMap::const_iterator it = file_permissions_.find(file_path);
+ if (it != file_permissions_.end())
+ return (it->second & permissions) == permissions;
+ return false;
}
+#endif
void GrantBindings(int bindings) {
enabled_bindings_ |= bindings;
@@ -169,7 +179,7 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
if (url.SchemeIs(chrome::kFileScheme)) {
base::FilePath path;
if (net::FileURLToFilePath(url, &path))
- return request_file_set_.find(path) != request_file_set_.end();
+ return ContainsKey(request_file_set_, path);
}
return false; // Unmentioned schemes are disallowed.
@@ -177,21 +187,26 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
// Determine if the certain permissions have been granted to a file.
bool HasPermissionsForFile(const base::FilePath& file, int permissions) {
+#if defined(OS_ANDROID)
+ if (file.IsContentUri())
+ return HasPermissionsForContentUri(file, permissions);
+#endif
if (!permissions || file.empty() || !file.IsAbsolute())
return false;
base::FilePath current_path = file.StripTrailingSeparators();
base::FilePath last_path;
int skip = 0;
while (current_path != last_path) {
- base::FilePath base_name = current_path.BaseName();
+ base::FilePath base_name = current_path.BaseName();
if (base_name.value() == base::FilePath::kParentDirectory) {
++skip;
} else if (skip > 0) {
if (base_name.value() != base::FilePath::kCurrentDirectory)
--skip;
} else {
- if (file_permissions_.find(current_path) != file_permissions_.end())
- return (file_permissions_[current_path] & permissions) == permissions;
+ FileMap::const_iterator it = file_permissions_.find(current_path);
+ if (it != file_permissions_.end())
+ return (it->second & permissions) == permissions;
}
last_path = current_path;
current_path = current_path.DirName();
@@ -295,7 +310,7 @@ ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() {
// We know about these schemes and believe them to be safe.
RegisterWebSafeScheme(kHttpScheme);
RegisterWebSafeScheme(kHttpsScheme);
- RegisterWebSafeScheme(chrome::kFtpScheme);
+ RegisterWebSafeScheme(kFtpScheme);
RegisterWebSafeScheme(chrome::kDataScheme);
RegisterWebSafeScheme("feed");
RegisterWebSafeScheme(chrome::kBlobScheme);
@@ -338,19 +353,21 @@ void ChildProcessSecurityPolicyImpl::AddWorker(int child_id,
void ChildProcessSecurityPolicyImpl::Remove(int child_id) {
base::AutoLock lock(lock_);
- if (!security_state_.count(child_id))
+ SecurityStateMap::iterator it = security_state_.find(child_id);
+ if (it == security_state_.end())
return; // May be called multiple times.
- delete security_state_[child_id];
- security_state_.erase(child_id);
+ delete it->second;
+ security_state_.erase(it);
worker_map_.erase(child_id);
}
void ChildProcessSecurityPolicyImpl::RegisterWebSafeScheme(
const std::string& scheme) {
base::AutoLock lock(lock_);
- DCHECK(web_safe_schemes_.count(scheme) == 0) << "Add schemes at most once.";
- DCHECK(pseudo_schemes_.count(scheme) == 0) << "Web-safe implies not pseudo.";
+ DCHECK_EQ(0U, web_safe_schemes_.count(scheme)) << "Add schemes at most once.";
+ DCHECK_EQ(0U, pseudo_schemes_.count(scheme))
+ << "Web-safe implies not pseudo.";
web_safe_schemes_.insert(scheme);
}
@@ -359,15 +376,15 @@ bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme(
const std::string& scheme) {
base::AutoLock lock(lock_);
- return (web_safe_schemes_.find(scheme) != web_safe_schemes_.end());
+ return ContainsKey(web_safe_schemes_, scheme);
}
void ChildProcessSecurityPolicyImpl::RegisterPseudoScheme(
const std::string& scheme) {
base::AutoLock lock(lock_);
- DCHECK(pseudo_schemes_.count(scheme) == 0) << "Add schemes at most once.";
- DCHECK(web_safe_schemes_.count(scheme) == 0) <<
- "Pseudo implies not web-safe.";
+ DCHECK_EQ(0U, pseudo_schemes_.count(scheme)) << "Add schemes at most once.";
+ DCHECK_EQ(0U, web_safe_schemes_.count(scheme))
+ << "Pseudo implies not web-safe.";
pseudo_schemes_.insert(scheme);
}
@@ -376,7 +393,7 @@ bool ChildProcessSecurityPolicyImpl::IsPseudoScheme(
const std::string& scheme) {
base::AutoLock lock(lock_);
- return (pseudo_schemes_.find(scheme) != pseudo_schemes_.end());
+ return ContainsKey(pseudo_schemes_, scheme);
}
void ChildProcessSecurityPolicyImpl::GrantRequestURL(
@@ -396,7 +413,7 @@ void ChildProcessSecurityPolicyImpl::GrantRequestURL(
// 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.path()));
+ GrantRequestURL(child_id, GURL(url.GetContent()));
}
return; // Can't grant the capability to request pseudo schemes.
@@ -436,22 +453,12 @@ void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL(
void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id,
const base::FilePath& file) {
- GrantPermissionsForFile(child_id, file, kReadFilePermissions);
+ GrantPermissionsForFile(child_id, file, READ_FILE_GRANT);
}
void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFile(
int child_id, const base::FilePath& file) {
- GrantPermissionsForFile(child_id, file, kCreateReadWriteFilePermissions);
-}
-
-void ChildProcessSecurityPolicyImpl::GrantCreateWriteFile(
- int child_id, const base::FilePath& file) {
- GrantPermissionsForFile(child_id, file, kCreateWriteFilePermissions);
-}
-
-void ChildProcessSecurityPolicyImpl::GrantReadDirectory(
- int child_id, const base::FilePath& directory) {
- GrantPermissionsForFile(child_id, directory, kEnumerateDirectoryPermissions);
+ GrantPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT);
}
void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile(
@@ -478,26 +485,33 @@ void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile(
void ChildProcessSecurityPolicyImpl::GrantReadFileSystem(
int child_id, const std::string& filesystem_id) {
- GrantPermissionsForFileSystem(child_id, filesystem_id, kReadFilePermissions);
+ GrantPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT);
}
void ChildProcessSecurityPolicyImpl::GrantWriteFileSystem(
int child_id, const std::string& filesystem_id) {
- GrantPermissionsForFileSystem(child_id, filesystem_id, kWriteFilePermissions);
+ GrantPermissionsForFileSystem(child_id, filesystem_id, WRITE_FILE_GRANT);
}
void ChildProcessSecurityPolicyImpl::GrantCreateFileForFileSystem(
int child_id, const std::string& filesystem_id) {
- GrantPermissionsForFileSystem(child_id, filesystem_id,
- kCreateFilePermissions);
+ GrantPermissionsForFileSystem(child_id, filesystem_id, CREATE_NEW_FILE_GRANT);
+}
+
+void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFileSystem(
+ int child_id, const std::string& filesystem_id) {
+ GrantPermissionsForFileSystem(
+ child_id, filesystem_id, CREATE_READ_WRITE_FILE_GRANT);
}
void ChildProcessSecurityPolicyImpl::GrantCopyIntoFileSystem(
int child_id, const std::string& filesystem_id) {
- // TODO(tommycli): These granted permissions a bit too broad, but not abused.
- // We are fixing in http://crbug.com/262142 and associated CL.
- GrantPermissionsForFileSystem(child_id, filesystem_id,
- kCreateFilePermissions);
+ GrantPermissionsForFileSystem(child_id, filesystem_id, COPY_INTO_FILE_GRANT);
+}
+
+void ChildProcessSecurityPolicyImpl::GrantDeleteFromFileSystem(
+ int child_id, const std::string& filesystem_id) {
+ GrantPermissionsForFileSystem(child_id, filesystem_id, DELETE_FILE_GRANT);
}
void ChildProcessSecurityPolicyImpl::GrantSendMIDISysExMessage(int child_id) {
@@ -586,7 +600,7 @@ bool ChildProcessSecurityPolicyImpl::CanRequestURL(
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.path());
+ GURL child_url(url.GetContent());
if (child_url.SchemeIs(kViewSourceScheme) &&
url.SchemeIs(kViewSourceScheme))
return false;
@@ -623,54 +637,36 @@ bool ChildProcessSecurityPolicyImpl::CanRequestURL(
bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id,
const base::FilePath& file) {
- return HasPermissionsForFile(child_id, file, kReadFilePermissions);
-}
-
-bool ChildProcessSecurityPolicyImpl::CanWriteFile(int child_id,
- const base::FilePath& file) {
- return HasPermissionsForFile(child_id, file, kWriteFilePermissions);
-}
-
-bool ChildProcessSecurityPolicyImpl::CanCreateFile(int child_id,
- const base::FilePath& file) {
- return HasPermissionsForFile(child_id, file, kCreateFilePermissions);
+ return HasPermissionsForFile(child_id, file, READ_FILE_GRANT);
}
-bool ChildProcessSecurityPolicyImpl::CanCreateWriteFile(
+bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile(
int child_id,
const base::FilePath& file) {
- return HasPermissionsForFile(child_id, file, kCreateWriteFilePermissions);
-}
-
-bool ChildProcessSecurityPolicyImpl::CanReadDirectory(
- int child_id, const base::FilePath& directory) {
- return HasPermissionsForFile(child_id,
- directory,
- kEnumerateDirectoryPermissions);
+ return HasPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanReadFileSystem(
int child_id, const std::string& filesystem_id) {
- return HasPermissionsForFileSystem(child_id,
- filesystem_id,
- kReadFilePermissions);
+ return HasPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanReadWriteFileSystem(
int child_id, const std::string& filesystem_id) {
- return HasPermissionsForFileSystem(child_id,
- filesystem_id,
- kReadFilePermissions |
- kWriteFilePermissions);
+ return HasPermissionsForFileSystem(child_id, filesystem_id,
+ READ_FILE_GRANT | WRITE_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystem(
int child_id, const std::string& filesystem_id) {
- // TODO(tommycli): These granted permissions a bit too broad, but not abused.
- // We are fixing in http://crbug.com/262142 and associated CL.
- return HasPermissionsForFileSystem(child_id,
- filesystem_id,
- kCreateFilePermissions);
+ return HasPermissionsForFileSystem(child_id, filesystem_id,
+ COPY_INTO_FILE_GRANT);
+}
+
+bool ChildProcessSecurityPolicyImpl::CanDeleteFromFileSystem(
+ int child_id, const std::string& filesystem_id) {
+ return HasPermissionsForFileSystem(child_id, filesystem_id,
+ DELETE_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile(
@@ -700,7 +696,7 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
// Any write access is disallowed on the root path.
if (fileapi::VirtualPath::IsRootPath(url.path()) &&
- (permissions & ~kReadFilePermissions)) {
+ (permissions & ~READ_FILE_GRANT)) {
return false;
}
@@ -718,7 +714,7 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
return false;
if ((found->second & fileapi::FILE_PERMISSION_READ_ONLY) &&
- permissions & ~kReadFilePermissions) {
+ permissions & ~READ_FILE_GRANT) {
return false;
}
@@ -734,26 +730,38 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile(
int child_id,
const fileapi::FileSystemURL& url) {
- return HasPermissionsForFileSystemFile(child_id, url, kReadFilePermissions);
+ return HasPermissionsForFileSystemFile(child_id, url, READ_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile(
int child_id,
const fileapi::FileSystemURL& url) {
- return HasPermissionsForFileSystemFile(child_id, url, kWriteFilePermissions);
+ return HasPermissionsForFileSystemFile(child_id, url, WRITE_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile(
int child_id,
const fileapi::FileSystemURL& url) {
- return HasPermissionsForFileSystemFile(child_id, url, kCreateFilePermissions);
+ return HasPermissionsForFileSystemFile(child_id, url, CREATE_NEW_FILE_GRANT);
}
-bool ChildProcessSecurityPolicyImpl::CanCreateWriteFileSystemFile(
+bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile(
int child_id,
const fileapi::FileSystemURL& url) {
return HasPermissionsForFileSystemFile(child_id, url,
- kCreateWriteFilePermissions);
+ CREATE_READ_WRITE_FILE_GRANT);
+}
+
+bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile(
+ int child_id,
+ const fileapi::FileSystemURL& url) {
+ return HasPermissionsForFileSystemFile(child_id, url, COPY_INTO_FILE_GRANT);
+}
+
+bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
+ int child_id,
+ const fileapi::FileSystemURL& url) {
+ return HasPermissionsForFileSystemFile(child_id, url, DELETE_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) {
@@ -805,7 +813,7 @@ bool ChildProcessSecurityPolicyImpl::CanAccessCookiesForOrigin(
bool ChildProcessSecurityPolicyImpl::CanSendCookiesForOrigin(int child_id,
const GURL& gurl) {
for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
- if (iter.GetData().process_type == child_id) {
+ if (iter.GetData().id == child_id) {
if (iter.GetData().process_type == PROCESS_TYPE_PLUGIN) {
// NPAPI plugin processes are unsandboxed and so are trusted. Plugins
// can make request to any origin.
diff --git a/chromium/content/browser/child_process_security_policy_impl.h b/chromium/content/browser/child_process_security_policy_impl.h
index 0a874b3beb4..93480ad6b32 100644
--- a/chromium/content/browser/child_process_security_policy_impl.h
+++ b/chromium/content/browser/child_process_security_policy_impl.h
@@ -45,8 +45,6 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
virtual void GrantReadFile(int child_id, const base::FilePath& file) OVERRIDE;
virtual void GrantCreateReadWriteFile(int child_id,
const base::FilePath& file) OVERRIDE;
- virtual void GrantCreateWriteFile(int child_id,
- const base::FilePath& file) OVERRIDE;
virtual void GrantReadFileSystem(
int child_id,
const std::string& filesystem_id) OVERRIDE;
@@ -56,15 +54,19 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
virtual void GrantCreateFileForFileSystem(
int child_id,
const std::string& filesystem_id) OVERRIDE;
+ virtual void GrantCreateReadWriteFileSystem(
+ int child_id,
+ const std::string& filesystem_id) OVERRIDE;
virtual void GrantCopyIntoFileSystem(
int child_id,
const std::string& filesystem_id) OVERRIDE;
+ virtual void GrantDeleteFromFileSystem(
+ int child_id,
+ const std::string& filesystem_id) OVERRIDE;
virtual void GrantScheme(int child_id, const std::string& scheme) OVERRIDE;
virtual bool CanReadFile(int child_id, const base::FilePath& file) OVERRIDE;
- virtual bool CanWriteFile(int child_id, const base::FilePath& file) OVERRIDE;
- virtual bool CanCreateFile(int child_id, const base::FilePath& file) OVERRIDE;
- virtual bool CanCreateWriteFile(int child_id,
- const base::FilePath& file) OVERRIDE;
+ virtual bool CanCreateReadWriteFile(int child_id,
+ const base::FilePath& file) OVERRIDE;
virtual bool CanReadFileSystem(int child_id,
const std::string& filesystem_id) OVERRIDE;
virtual bool CanReadWriteFileSystem(
@@ -72,6 +74,9 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
const std::string& filesystem_id) OVERRIDE;
virtual bool CanCopyIntoFileSystem(int child_id,
const std::string& filesystem_id) OVERRIDE;
+ virtual bool CanDeleteFromFileSystem(
+ int child_id,
+ const std::string& filesystem_id) OVERRIDE;
// Pseudo schemes are treated differently than other schemes because they
// cannot be requested like normal URLs. There is no mechanism for revoking
@@ -106,10 +111,6 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// file:// URL, but not all urls of the file:// scheme.
void GrantRequestSpecificFileURL(int child_id, const GURL& url);
- // Grants the child process permission to enumerate all the files in
- // this directory and read those files.
- void GrantReadDirectory(int child_id, const base::FilePath& directory);
-
// Revokes all permissions granted to the given file.
void RevokeAllPermissionsForFile(int child_id, const base::FilePath& file);
@@ -137,16 +138,16 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
const GURL& url,
ResourceType::Type resource_type);
- // Before servicing a child process's request to enumerate a directory
- // the browser should call this method to check for the capability.
- bool CanReadDirectory(int child_id, const base::FilePath& directory);
-
// Explicit permissions checks for FileSystemURL specified files.
bool CanReadFileSystemFile(int child_id, const fileapi::FileSystemURL& url);
bool CanWriteFileSystemFile(int child_id, const fileapi::FileSystemURL& url);
bool CanCreateFileSystemFile(int child_id, const fileapi::FileSystemURL& url);
- bool CanCreateWriteFileSystemFile(int child_id,
- const fileapi::FileSystemURL& url);
+ bool CanCreateReadWriteFileSystemFile(int child_id,
+ const fileapi::FileSystemURL& url);
+ bool CanCopyIntoFileSystemFile(int child_id,
+ const fileapi::FileSystemURL& url);
+ bool CanDeleteFileSystemFile(int child_id,
+ const fileapi::FileSystemURL& url);
// Returns true if the specified child_id has been granted WebUIBindings.
// The browser should check this property before assuming the child process is
@@ -175,13 +176,6 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// --site-per-process flags are used.
void LockToOrigin(int child_id, const GURL& gurl);
- // Determines if certain permissions were granted for a file fystem.
- // |permissions| must be a bitwise-or'd value of base::PlatformFileFlags.
- bool HasPermissionsForFileSystem(
- int child_id,
- const std::string& filesystem_id,
- int permission);
-
// Register FileSystem type and permission policy which should be used
// for the type. The |policy| must be a bitwise-or'd value of
// fileapi::FilePermissionPolicy.
@@ -214,14 +208,13 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
void AddChild(int child_id);
// Determines if certain permissions were granted for a file to given child
- // process. |permissions| must be a bitwise-or'd value of
- // base::PlatformFileFlags.
+ // process. |permissions| is an internally defined bit-set.
bool ChildProcessHasPermissionsForFile(int child_id,
const base::FilePath& file,
int permissions);
- // Grant a particular permission set for a file. |permissions| is a bit-set
- // of base::PlatformFileFlags.
+ // Grant a particular permission set for a file. |permissions| is an
+ // internally defined bit-set.
void GrantPermissionsForFile(int child_id,
const base::FilePath& file,
int permissions);
@@ -234,20 +227,27 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
const std::string& filesystem_id,
int permission);
- // Deprecated: Use CanReadFile, etc. methods instead.
// Determines if certain permissions were granted for a file. |permissions|
- // must be a bitwise-or'd value of base::PlatformFileFlags.
+ // is an internally defined bit-set. If |child_id| is a worker process,
+ // this returns true if either the worker process or its parent renderer
+ // has permissions for the file.
bool HasPermissionsForFile(int child_id,
const base::FilePath& file,
int permissions);
- // Deprecated: Use CanReadFileSystemFile, etc. methods instead.
// Determines if certain permissions were granted for a file in FileSystem
- // API. |permissions| must be a bitwise-or'd value of base::PlatformFileFlags.
+ // API. |permissions| is an internally defined bit-set.
bool HasPermissionsForFileSystemFile(int child_id,
const fileapi::FileSystemURL& url,
int permissions);
+ // Determines if certain permissions were granted for a file system.
+ // |permissions| is an internally defined bit-set.
+ bool HasPermissionsForFileSystem(
+ int child_id,
+ const std::string& filesystem_id,
+ int permission);
+
// You must acquire this lock before reading or writing any members of this
// class. You must not block while holding this lock.
base::Lock lock_;
diff --git a/chromium/content/browser/child_process_security_policy_unittest.cc b/chromium/content/browser/child_process_security_policy_unittest.cc
index 247a74f69d5..c4d51b3eb38 100644
--- a/chromium/content/browser/child_process_security_policy_unittest.cc
+++ b/chromium/content/browser/child_process_security_policy_unittest.cc
@@ -89,6 +89,27 @@ class ChildProcessSecurityPolicyTest : public testing::Test {
p->GrantPermissionsForFile(child_id, file, permissions);
}
+ void CheckHasNoFileSystemPermission(ChildProcessSecurityPolicyImpl* p,
+ const std::string& child_id) {
+ EXPECT_FALSE(p->CanReadFileSystem(kRendererID, child_id));
+ EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, child_id));
+ EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, child_id));
+ EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, child_id));
+ }
+
+ void CheckHasNoFileSystemFilePermission(ChildProcessSecurityPolicyImpl* p,
+ const base::FilePath& file,
+ const fileapi::FileSystemURL& url) {
+ EXPECT_FALSE(p->CanReadFile(kRendererID, file));
+ EXPECT_FALSE(p->CanCreateReadWriteFile(kRendererID, file));
+ EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url));
+ EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
+ EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
+ EXPECT_FALSE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
+ EXPECT_FALSE(p->CanCopyIntoFileSystemFile(kRendererID, url));
+ EXPECT_FALSE(p->CanDeleteFileSystemFile(kRendererID, url));
+ }
+
private:
ChildProcessSecurityPolicyTestBrowserClient test_browser_client_;
ContentBrowserClient* old_browser_client_;
@@ -101,7 +122,7 @@ TEST_F(ChildProcessSecurityPolicyTest, IsWebSafeSchemeTest) {
EXPECT_TRUE(p->IsWebSafeScheme(kHttpScheme));
EXPECT_TRUE(p->IsWebSafeScheme(kHttpsScheme));
- EXPECT_TRUE(p->IsWebSafeScheme(chrome::kFtpScheme));
+ EXPECT_TRUE(p->IsWebSafeScheme(kFtpScheme));
EXPECT_TRUE(p->IsWebSafeScheme(chrome::kDataScheme));
EXPECT_TRUE(p->IsWebSafeScheme("feed"));
EXPECT_TRUE(p->IsWebSafeScheme(chrome::kBlobScheme));
@@ -300,70 +321,63 @@ TEST_F(ChildProcessSecurityPolicyTest, FileSystemGrantsTest) {
RegisterFileSystemForVirtualPath(fileapi::kFileSystemTypeTest,
"copy_into_filesystem",
base::FilePath());
+ std::string delete_from_id = fileapi::IsolatedContext::GetInstance()->
+ RegisterFileSystemForVirtualPath(fileapi::kFileSystemTypeTest,
+ "delete_from_filesystem",
+ base::FilePath());
// Test initially having no permissions.
- EXPECT_FALSE(p->CanReadFileSystem(kRendererID, read_id));
- EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, read_id));
- EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_id));
-
- EXPECT_FALSE(p->CanReadFileSystem(kRendererID, read_write_id));
- EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, read_write_id));
- EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_write_id));
-
- EXPECT_FALSE(p->CanReadFileSystem(kRendererID, copy_into_id));
- EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, copy_into_id));
- EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, copy_into_id));
+ CheckHasNoFileSystemPermission(p, read_id);
+ CheckHasNoFileSystemPermission(p, read_write_id);
+ CheckHasNoFileSystemPermission(p, copy_into_id);
+ CheckHasNoFileSystemPermission(p, delete_from_id);
// Testing varying combinations of grants and checks.
p->GrantReadFileSystem(kRendererID, read_id);
EXPECT_TRUE(p->CanReadFileSystem(kRendererID, read_id));
EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, read_id));
EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_id));
+ EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, read_id));
p->GrantReadFileSystem(kRendererID, read_write_id);
p->GrantWriteFileSystem(kRendererID, read_write_id);
EXPECT_TRUE(p->CanReadFileSystem(kRendererID, read_write_id));
EXPECT_TRUE(p->CanReadWriteFileSystem(kRendererID, read_write_id));
EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_write_id));
+ EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, read_write_id));
p->GrantCopyIntoFileSystem(kRendererID, copy_into_id);
EXPECT_FALSE(p->CanReadFileSystem(kRendererID, copy_into_id));
EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, copy_into_id));
EXPECT_TRUE(p->CanCopyIntoFileSystem(kRendererID, copy_into_id));
+ EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, copy_into_id));
+
+ p->GrantDeleteFromFileSystem(kRendererID, delete_from_id);
+ EXPECT_FALSE(p->CanReadFileSystem(kRendererID, delete_from_id));
+ EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, delete_from_id));
+ EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, delete_from_id));
+ EXPECT_TRUE(p->CanDeleteFromFileSystem(kRendererID, delete_from_id));
// Test revoke permissions on renderer ID removal.
p->Remove(kRendererID);
- EXPECT_FALSE(p->CanReadFileSystem(kRendererID, read_id));
- EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, read_id));
- EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_id));
-
- EXPECT_FALSE(p->CanReadFileSystem(kRendererID, read_write_id));
- EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, read_write_id));
- EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_write_id));
-
- EXPECT_FALSE(p->CanReadFileSystem(kRendererID, copy_into_id));
- EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, copy_into_id));
- EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, copy_into_id));
+ CheckHasNoFileSystemPermission(p, read_id);
+ CheckHasNoFileSystemPermission(p, read_write_id);
+ CheckHasNoFileSystemPermission(p, copy_into_id);
+ CheckHasNoFileSystemPermission(p, delete_from_id);
// Test having no permissions upon re-adding same renderer ID.
p->Add(kRendererID);
- EXPECT_FALSE(p->CanReadFileSystem(kRendererID, read_id));
- EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, read_id));
- EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_id));
-
- EXPECT_FALSE(p->CanReadFileSystem(kRendererID, read_write_id));
- EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, read_write_id));
- EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_write_id));
-
- EXPECT_FALSE(p->CanReadFileSystem(kRendererID, copy_into_id));
- EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, copy_into_id));
- EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, copy_into_id));
+ CheckHasNoFileSystemPermission(p, read_id);
+ CheckHasNoFileSystemPermission(p, read_write_id);
+ CheckHasNoFileSystemPermission(p, copy_into_id);
+ CheckHasNoFileSystemPermission(p, delete_from_id);
// Cleanup.
p->Remove(kRendererID);
fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(read_id);
fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(read_write_id);
fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(copy_into_id);
+ fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(delete_from_id);
}
TEST_F(ChildProcessSecurityPolicyTest, FilePermissionGrantingAndRevoking) {
@@ -381,142 +395,54 @@ TEST_F(ChildProcessSecurityPolicyTest, FilePermissionGrantingAndRevoking) {
GURL("http://foo/"), fileapi::kFileSystemTypeTest, file);
// Test initially having no permissions.
- EXPECT_FALSE(p->CanReadFile(kRendererID, file));
- EXPECT_FALSE(p->CanWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateWriteFileSystemFile(kRendererID, url));
+ CheckHasNoFileSystemFilePermission(p, file, url);
// Testing every combination of permissions granting and revoking.
p->GrantReadFile(kRendererID, file);
EXPECT_TRUE(p->CanReadFile(kRendererID, file));
- EXPECT_FALSE(p->CanWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateWriteFile(kRendererID, file));
+ EXPECT_FALSE(p->CanCreateReadWriteFile(kRendererID, file));
EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateWriteFileSystemFile(kRendererID, url));
+ EXPECT_FALSE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
+ EXPECT_FALSE(p->CanCopyIntoFileSystemFile(kRendererID, url));
+ EXPECT_FALSE(p->CanDeleteFileSystemFile(kRendererID, url));
p->RevokeAllPermissionsForFile(kRendererID, file);
- EXPECT_FALSE(p->CanReadFile(kRendererID, file));
- EXPECT_FALSE(p->CanWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateWriteFileSystemFile(kRendererID, url));
+ CheckHasNoFileSystemFilePermission(p, file, url);
p->GrantCreateReadWriteFile(kRendererID, file);
EXPECT_TRUE(p->CanReadFile(kRendererID, file));
- EXPECT_TRUE(p->CanWriteFile(kRendererID, file));
- EXPECT_TRUE(p->CanCreateFile(kRendererID, file));
- EXPECT_TRUE(p->CanCreateWriteFile(kRendererID, file));
+ EXPECT_TRUE(p->CanCreateReadWriteFile(kRendererID, file));
EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanWriteFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanCreateFileSystemFile(kRendererID, url));
- EXPECT_TRUE(p->CanCreateWriteFileSystemFile(kRendererID, url));
- p->RevokeAllPermissionsForFile(kRendererID, file);
- EXPECT_FALSE(p->CanReadFile(kRendererID, file));
- EXPECT_FALSE(p->CanWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateWriteFileSystemFile(kRendererID, url));
-
- p->GrantCreateWriteFile(kRendererID, file);
- EXPECT_FALSE(p->CanReadFile(kRendererID, file));
- EXPECT_TRUE(p->CanWriteFile(kRendererID, file));
- EXPECT_TRUE(p->CanCreateFile(kRendererID, file));
- EXPECT_TRUE(p->CanCreateWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url));
- EXPECT_TRUE(p->CanWriteFileSystemFile(kRendererID, url));
- EXPECT_TRUE(p->CanCreateFileSystemFile(kRendererID, url));
- EXPECT_TRUE(p->CanCreateWriteFileSystemFile(kRendererID, url));
+ EXPECT_TRUE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
+ EXPECT_TRUE(p->CanCopyIntoFileSystemFile(kRendererID, url));
+ EXPECT_TRUE(p->CanDeleteFileSystemFile(kRendererID, url));
p->RevokeAllPermissionsForFile(kRendererID, file);
- EXPECT_FALSE(p->CanReadFile(kRendererID, file));
- EXPECT_FALSE(p->CanWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateWriteFileSystemFile(kRendererID, url));
+ CheckHasNoFileSystemFilePermission(p, file, url);
// Test revoke permissions on renderer ID removal.
p->GrantCreateReadWriteFile(kRendererID, file);
EXPECT_TRUE(p->CanReadFile(kRendererID, file));
- EXPECT_TRUE(p->CanWriteFile(kRendererID, file));
- EXPECT_TRUE(p->CanCreateFile(kRendererID, file));
- EXPECT_TRUE(p->CanCreateWriteFile(kRendererID, file));
+ EXPECT_TRUE(p->CanCreateReadWriteFile(kRendererID, file));
EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanWriteFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanCreateFileSystemFile(kRendererID, url));
- EXPECT_TRUE(p->CanCreateWriteFileSystemFile(kRendererID, url));
+ EXPECT_TRUE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
+ EXPECT_TRUE(p->CanCopyIntoFileSystemFile(kRendererID, url));
+ EXPECT_TRUE(p->CanDeleteFileSystemFile(kRendererID, url));
p->Remove(kRendererID);
- EXPECT_FALSE(p->CanReadFile(kRendererID, file));
- EXPECT_FALSE(p->CanWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateWriteFileSystemFile(kRendererID, url));
+ CheckHasNoFileSystemFilePermission(p, file, url);
// Test having no permissions upon re-adding same renderer ID.
p->Add(kRendererID);
- EXPECT_FALSE(p->CanReadFile(kRendererID, file));
- EXPECT_FALSE(p->CanWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateFile(kRendererID, file));
- EXPECT_FALSE(p->CanCreateWriteFile(kRendererID, file));
- EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
- EXPECT_FALSE(p->CanCreateWriteFileSystemFile(kRendererID, url));
+ CheckHasNoFileSystemFilePermission(p, file, url);
// Cleanup.
p->Remove(kRendererID);
}
-TEST_F(ChildProcessSecurityPolicyTest, CanReadDirectories) {
- ChildProcessSecurityPolicyImpl* p =
- ChildProcessSecurityPolicyImpl::GetInstance();
-
- p->Add(kRendererID);
-
- EXPECT_FALSE(p->CanReadDirectory(kRendererID,
- base::FilePath(TEST_PATH("/etc/"))));
- p->GrantReadDirectory(kRendererID,
- base::FilePath(TEST_PATH("/etc/")));
- EXPECT_TRUE(p->CanReadDirectory(kRendererID,
- base::FilePath(TEST_PATH("/etc/"))));
- EXPECT_TRUE(p->CanReadFile(kRendererID,
- base::FilePath(TEST_PATH("/etc/passwd"))));
-
- p->Remove(kRendererID);
- p->Add(kRendererID);
-
- EXPECT_FALSE(p->CanReadDirectory(kRendererID,
- base::FilePath(TEST_PATH("/etc/"))));
- EXPECT_FALSE(p->CanReadFile(kRendererID,
- base::FilePath(TEST_PATH("/etc/passwd"))));
-
- // Just granting read permission as a file doesn't imply reading as a
- // directory.
- p->GrantReadFile(kRendererID, base::FilePath(TEST_PATH("/etc/")));
- EXPECT_TRUE(p->CanReadFile(kRendererID,
- base::FilePath(TEST_PATH("/etc/passwd"))));
- EXPECT_FALSE(p->CanReadDirectory(kRendererID,
- base::FilePath(TEST_PATH("/etc/"))));
-
- p->Remove(kRendererID);
-}
-
TEST_F(ChildProcessSecurityPolicyTest, FilePermissions) {
base::FilePath granted_file = base::FilePath(TEST_PATH("/home/joe"));
base::FilePath sibling_file = base::FilePath(TEST_PATH("/home/bob"));
diff --git a/chromium/content/browser/device_monitor_mac.h b/chromium/content/browser/device_monitor_mac.h
index bab522f4dbe..6def493a81f 100644
--- a/chromium/content/browser/device_monitor_mac.h
+++ b/chromium/content/browser/device_monitor_mac.h
@@ -8,19 +8,29 @@
#include "base/basictypes.h"
#include "base/system_monitor/system_monitor.h"
+namespace {
+class DeviceMonitorMacImpl;
+}
+
namespace content {
+// Class to track audio/video devices removal or addition via callback to
+// base::SystemMonitor ProcessDevicesChanged(). A single object of this class
+// is created from the browser main process and lives as long as this one.
class DeviceMonitorMac {
public:
DeviceMonitorMac();
~DeviceMonitorMac();
- private:
- // Forward the notifications to system monitor.
+ // Method called by the internal DeviceMonitorMacImpl object
+ // |device_monitor_impl_| when a device of type |type| has been added to or
+ // removed from the system. This code executes in the notification thread
+ // (QTKit or AVFoundation).
void NotifyDeviceChanged(base::SystemMonitor::DeviceType type);
- class QTMonitorImpl;
- scoped_ptr<DeviceMonitorMac::QTMonitorImpl> qt_monitor_;
+ private:
+ scoped_ptr<DeviceMonitorMacImpl> device_monitor_impl_;
+
DISALLOW_COPY_AND_ASSIGN(DeviceMonitorMac);
};
diff --git a/chromium/content/browser/device_monitor_mac.mm b/chromium/content/browser/device_monitor_mac.mm
index 7b12e91cbdf..ebc0f77de02 100644
--- a/chromium/content/browser/device_monitor_mac.mm
+++ b/chromium/content/browser/device_monitor_mac.mm
@@ -7,97 +7,275 @@
#import <QTKit/QTKit.h>
#include "base/logging.h"
+#import "media/video/capture/mac/avfoundation_glue.h"
-namespace content {
+namespace {
-class DeviceMonitorMac::QTMonitorImpl {
+// This class is used to keep track of system devices names and their types.
+class DeviceInfo {
public:
- explicit QTMonitorImpl(DeviceMonitorMac* monitor);
- virtual ~QTMonitorImpl() {}
+ enum DeviceType {
+ kAudio,
+ kVideo,
+ kMuxed,
+ kUnknown,
+ kInvalid
+ };
+
+ DeviceInfo(std::string unique_id, DeviceType type)
+ : unique_id_(unique_id), type_(type) {}
- void Start();
- void Stop();
+ // Operator== is needed here to use this class in a std::find. A given
+ // |unique_id_| always has the same |type_| so for comparison purposes the
+ // latter can be safely ignored.
+ bool operator==(const DeviceInfo& device) const {
+ return unique_id_ == device.unique_id_;
+ }
+
+ const std::string& unique_id() const { return unique_id_; }
+ DeviceType type() const { return type_; }
private:
- void OnDeviceChanged();
+ std::string unique_id_;
+ DeviceType type_;
+ // Allow generated copy constructor and assignment.
+};
+
+// Base abstract class used by DeviceMonitorMac to interact with either a QTKit
+// or an AVFoundation implementation of events and notifications.
+class DeviceMonitorMacImpl {
+ public:
+ explicit DeviceMonitorMacImpl(content::DeviceMonitorMac* monitor)
+ : monitor_(monitor),
+ cached_devices_(),
+ device_arrival_(nil),
+ device_removal_(nil) {
+ DCHECK(monitor);
+ // Initialise the devices_cache_ with a not-valid entry. For the case in
+ // which there is one single device in the system and we get notified when
+ // it gets removed, this will prevent the system from thinking that no
+ // devices were added nor removed and not notifying the |monitor_|.
+ cached_devices_.push_back(DeviceInfo("invalid", DeviceInfo::kInvalid));
+ }
+ virtual ~DeviceMonitorMacImpl() {}
+
+ virtual void OnDeviceChanged() = 0;
- DeviceMonitorMac* monitor_;
- int number_audio_devices_;
- int number_video_devices_;
+ // Method called by the default notification center when a device is removed
+ // or added to the system. It will compare the |cached_devices_| with the
+ // current situation, update it, and, if there's an update, signal to
+ // |monitor_| with the appropriate device type.
+ void ConsolidateDevicesListAndNotify(
+ const std::vector<DeviceInfo>& snapshot_devices);
+
+ protected:
+ content::DeviceMonitorMac* monitor_;
+ std::vector<DeviceInfo> cached_devices_;
+
+ // Handles to NSNotificationCenter block observers.
id device_arrival_;
id device_removal_;
- DISALLOW_COPY_AND_ASSIGN(QTMonitorImpl);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DeviceMonitorMacImpl);
};
-DeviceMonitorMac::QTMonitorImpl::QTMonitorImpl(DeviceMonitorMac* monitor)
- : monitor_(monitor),
- number_audio_devices_(0),
- number_video_devices_(0),
- device_arrival_(nil),
- device_removal_(nil) {
- DCHECK(monitor);
+void DeviceMonitorMacImpl::ConsolidateDevicesListAndNotify(
+ const std::vector<DeviceInfo>& snapshot_devices) {
+ bool video_device_added = false;
+ bool audio_device_added = false;
+ bool video_device_removed = false;
+ bool audio_device_removed = false;
+
+ // Compare the current system devices snapshot with the ones cached to detect
+ // additions, present in the former but not in the latter. If we find a device
+ // in snapshot_devices entry also present in cached_devices, we remove it from
+ // the latter vector.
+ std::vector<DeviceInfo>::const_iterator it;
+ for (it = snapshot_devices.begin(); it != snapshot_devices.end(); ++it) {
+ std::vector<DeviceInfo>::iterator cached_devices_iterator =
+ std::find(cached_devices_.begin(), cached_devices_.end(), *it);
+ if (cached_devices_iterator == cached_devices_.end()) {
+ video_device_added |= ((it->type() == DeviceInfo::kVideo) ||
+ (it->type() == DeviceInfo::kMuxed));
+ audio_device_added |= ((it->type() == DeviceInfo::kAudio) ||
+ (it->type() == DeviceInfo::kMuxed));
+ DVLOG(1) << "Device has been added, id: " << it->unique_id();
+ } else {
+ cached_devices_.erase(cached_devices_iterator);
+ }
+ }
+ // All the remaining entries in cached_devices are removed devices.
+ for (it = cached_devices_.begin(); it != cached_devices_.end(); ++it) {
+ video_device_removed |= ((it->type() == DeviceInfo::kVideo) ||
+ (it->type() == DeviceInfo::kMuxed) ||
+ (it->type() == DeviceInfo::kInvalid));
+ audio_device_removed |= ((it->type() == DeviceInfo::kAudio) ||
+ (it->type() == DeviceInfo::kMuxed) ||
+ (it->type() == DeviceInfo::kInvalid));
+ DVLOG(1) << "Device has been removed, id: " << it->unique_id();
+ }
+ // Update the cached devices with the current system snapshot.
+ cached_devices_ = snapshot_devices;
+
+ if (video_device_added || video_device_removed)
+ monitor_->NotifyDeviceChanged(base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
+ if (audio_device_added || audio_device_removed)
+ monitor_->NotifyDeviceChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE);
}
-void DeviceMonitorMac::QTMonitorImpl::Start() {
+class QTKitMonitorImpl : public DeviceMonitorMacImpl {
+ public:
+ explicit QTKitMonitorImpl(content::DeviceMonitorMac* monitor);
+ virtual ~QTKitMonitorImpl();
+
+ virtual void OnDeviceChanged() OVERRIDE;
+ private:
+ void CountDevices();
+ void OnAttributeChanged(NSNotification* notification);
+
+ id device_change_;
+};
+
+QTKitMonitorImpl::QTKitMonitorImpl(content::DeviceMonitorMac* monitor)
+ : DeviceMonitorMacImpl(monitor) {
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
device_arrival_ =
- [nc addObserverForName:QTCaptureDeviceWasConnectedNotification
- object:nil
- queue:nil
- usingBlock:^(NSNotification* notification) {
- OnDeviceChanged();}];
-
+ [nc addObserverForName:QTCaptureDeviceWasConnectedNotification
+ object:nil
+ queue:nil
+ usingBlock:^(NSNotification* notification) {
+ OnDeviceChanged();}];
device_removal_ =
[nc addObserverForName:QTCaptureDeviceWasDisconnectedNotification
object:nil
queue:nil
usingBlock:^(NSNotification* notification) {
OnDeviceChanged();}];
+ device_change_ =
+ [nc addObserverForName:QTCaptureDeviceAttributeDidChangeNotification
+ object:nil
+ queue:nil
+ usingBlock:^(NSNotification* notification) {
+ OnAttributeChanged(notification);}];
}
-void DeviceMonitorMac::QTMonitorImpl::Stop() {
- if (!monitor_)
- return;
-
+QTKitMonitorImpl::~QTKitMonitorImpl() {
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:device_arrival_];
[nc removeObserver:device_removal_];
+ [nc removeObserver:device_change_];
}
-void DeviceMonitorMac::QTMonitorImpl::OnDeviceChanged() {
+void QTKitMonitorImpl::OnAttributeChanged(
+ NSNotification* notification) {
+ if ([[[notification userInfo]
+ objectForKey:QTCaptureDeviceChangedAttributeKey]
+ isEqualToString:QTCaptureDeviceSuspendedAttribute]) {
+ OnDeviceChanged();
+ }
+}
+
+void QTKitMonitorImpl::OnDeviceChanged() {
+ std::vector<DeviceInfo> snapshot_devices;
+
NSArray* devices = [QTCaptureDevice inputDevices];
- int number_video_devices = 0;
- int number_audio_devices = 0;
for (QTCaptureDevice* device in devices) {
- if ([device hasMediaType:QTMediaTypeVideo] ||
- [device hasMediaType:QTMediaTypeMuxed])
- ++number_video_devices;
-
- if ([device hasMediaType:QTMediaTypeSound] ||
- [device hasMediaType:QTMediaTypeMuxed])
- ++number_audio_devices;
+ DeviceInfo::DeviceType device_type = DeviceInfo::kUnknown;
+ // Act as if suspended video capture devices are not attached. For
+ // example, a laptop's internal webcam is suspended when the lid is closed.
+ if ([device hasMediaType:QTMediaTypeVideo] &&
+ ![[device attributeForKey:QTCaptureDeviceSuspendedAttribute]
+ boolValue]) {
+ device_type = DeviceInfo::kVideo;
+ } else if ([device hasMediaType:QTMediaTypeMuxed] &&
+ ![[device attributeForKey:QTCaptureDeviceSuspendedAttribute]
+ boolValue]) {
+ device_type = DeviceInfo::kMuxed;
+ } else if ([device hasMediaType:QTMediaTypeSound] &&
+ ![[device attributeForKey:QTCaptureDeviceSuspendedAttribute]
+ boolValue]) {
+ device_type = DeviceInfo::kAudio;
+ }
+ snapshot_devices.push_back(
+ DeviceInfo([[device uniqueID] UTF8String], device_type));
}
+ ConsolidateDevicesListAndNotify(snapshot_devices);
+}
- if (number_video_devices_ != number_video_devices) {
- number_video_devices_ = number_video_devices;
- monitor_->NotifyDeviceChanged(base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
- }
+class AVFoundationMonitorImpl : public DeviceMonitorMacImpl {
+ public:
+ explicit AVFoundationMonitorImpl(content::DeviceMonitorMac* monitor);
+ virtual ~AVFoundationMonitorImpl();
- if (number_audio_devices_ != number_audio_devices) {
- number_audio_devices_ = number_audio_devices;
- monitor_->NotifyDeviceChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE);
+ virtual void OnDeviceChanged() OVERRIDE;
+};
+
+AVFoundationMonitorImpl::AVFoundationMonitorImpl(
+ content::DeviceMonitorMac* monitor)
+ : DeviceMonitorMacImpl(monitor) {
+ NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
+ device_arrival_ =
+ [nc addObserverForName:AVFoundationGlue::
+ AVCaptureDeviceWasConnectedNotification()
+ object:nil
+ queue:nil
+ usingBlock:^(NSNotification* notification) {
+ OnDeviceChanged();}];
+ device_removal_ =
+ [nc addObserverForName:AVFoundationGlue::
+ AVCaptureDeviceWasDisconnectedNotification()
+ object:nil
+ queue:nil
+ usingBlock:^(NSNotification* notification) {
+ OnDeviceChanged();}];
+}
+
+AVFoundationMonitorImpl::~AVFoundationMonitorImpl() {
+ NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
+ [nc removeObserver:device_arrival_];
+ [nc removeObserver:device_removal_];
+}
+
+void AVFoundationMonitorImpl::OnDeviceChanged() {
+ std::vector<DeviceInfo> snapshot_devices;
+
+ NSArray* devices = [AVCaptureDeviceGlue devices];
+ for (CrAVCaptureDevice* device in devices) {
+ DeviceInfo::DeviceType device_type = DeviceInfo::kUnknown;
+ if ([device hasMediaType:AVFoundationGlue::AVMediaTypeVideo()]) {
+ device_type = DeviceInfo::kVideo;
+ } else if ([device hasMediaType:AVFoundationGlue::AVMediaTypeMuxed()]) {
+ device_type = DeviceInfo::kMuxed;
+ } else if ([device hasMediaType:AVFoundationGlue::AVMediaTypeAudio()]) {
+ device_type = DeviceInfo::kAudio;
+ }
+ snapshot_devices.push_back(DeviceInfo([[device uniqueID] UTF8String],
+ device_type));
}
+ ConsolidateDevicesListAndNotify(snapshot_devices);
}
+} // namespace
+
+namespace content {
+
DeviceMonitorMac::DeviceMonitorMac() {
- qt_monitor_.reset(new QTMonitorImpl(this));
- qt_monitor_->Start();
+ if (AVFoundationGlue::IsAVFoundationSupported()) {
+ DVLOG(1) << "Monitoring via AVFoundation";
+ device_monitor_impl_.reset(new AVFoundationMonitorImpl(this));
+ // For the AVFoundation to start sending connect/disconnect notifications,
+ // the AVFoundation NSBundle has to be loaded and the devices enumerated.
+ // This operation seems to take in the range of hundred of ms. so should be
+ // moved to the point when is needed, and that is during
+ // DeviceVideoCaptureMac +getDeviceNames.
+ } else {
+ DVLOG(1) << "Monitoring via QTKit";
+ device_monitor_impl_.reset(new QTKitMonitorImpl(this));
+ }
}
-DeviceMonitorMac::~DeviceMonitorMac() {
- qt_monitor_->Stop();
-}
+DeviceMonitorMac::~DeviceMonitorMac() {}
void DeviceMonitorMac::NotifyDeviceChanged(
base::SystemMonitor::DeviceType type) {
diff --git a/chromium/content/browser/device_monitor_linux.cc b/chromium/content/browser/device_monitor_udev.cc
index 61aad7c113c..ddfe053eae2 100644
--- a/chromium/content/browser/device_monitor_linux.cc
+++ b/chromium/content/browser/device_monitor_udev.cc
@@ -1,10 +1,10 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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.
// libudev is used for monitoring device changes.
-#include "content/browser/device_monitor_linux.h"
+#include "content/browser/device_monitor_udev.h"
#include <libudev.h>
diff --git a/chromium/content/browser/device_monitor_linux.h b/chromium/content/browser/device_monitor_udev.h
index b56de1ebdc0..b65cfc5a29b 100644
--- a/chromium/content/browser/device_monitor_linux.h
+++ b/chromium/content/browser/device_monitor_udev.h
@@ -1,12 +1,12 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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.
// This class is used to detect device change and notify base::SystemMonitor
// on Linux.
-#ifndef CONTENT_BROWSER_DEVICE_MONITOR_LINUX_H_
-#define CONTENT_BROWSER_DEVICE_MONITOR_LINUX_H_
+#ifndef CONTENT_BROWSER_DEVICE_MONITOR_UDEV_H_
+#define CONTENT_BROWSER_DEVICE_MONITOR_UDEV_H_
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
@@ -41,4 +41,4 @@ class DeviceMonitorLinux : public base::MessageLoop::DestructionObserver {
} // namespace content
-#endif // CONTENT_BROWSER_DEVICE_MONITOR_LINUX_H_
+#endif // CONTENT_BROWSER_DEVICE_MONITOR_UDEV_H_
diff --git a/chromium/content/browser/device_orientation/accelerometer_mac.cc b/chromium/content/browser/device_orientation/accelerometer_mac.cc
deleted file mode 100644
index 04c5d71b65c..00000000000
--- a/chromium/content/browser/device_orientation/accelerometer_mac.cc
+++ /dev/null
@@ -1,105 +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/device_orientation/accelerometer_mac.h"
-
-#include <math.h>
-
-#include "base/logging.h"
-#include "content/browser/device_orientation/orientation.h"
-#include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h"
-
-namespace content {
-
-// Create a AccelerometerMac object and return NULL if no valid sensor found.
-DataFetcher* AccelerometerMac::Create() {
- scoped_ptr<AccelerometerMac> accelerometer(new AccelerometerMac);
- return accelerometer->Init() ? accelerometer.release() : NULL;
-}
-
-AccelerometerMac::~AccelerometerMac() {
-}
-
-AccelerometerMac::AccelerometerMac() {
-}
-
-const DeviceData* AccelerometerMac::GetDeviceData(DeviceData::Type type) {
- if (type != DeviceData::kTypeOrientation)
- return NULL;
- return GetOrientation();
-}
-
-// Retrieve per-axis orientation values.
-//
-// Axes and angles are defined according to the W3C DeviceOrientation Draft.
-// See here: http://dev.w3.org/geo/api/spec-source-orientation.html
-//
-// Note: only beta and gamma angles are provided. Alpha is set to zero.
-//
-// Returns false in case of error.
-//
-const Orientation* AccelerometerMac::GetOrientation() {
- DCHECK(sudden_motion_sensor_.get());
-
- // Retrieve per-axis calibrated values.
- float axis_value[3];
- if (!sudden_motion_sensor_->ReadSensorValues(axis_value))
- return NULL;
-
- // Transform the accelerometer values to W3C draft angles.
- //
- // Accelerometer values are just dot products of the sensor axes
- // by the gravity vector 'g' with the result for the z axis inverted.
- //
- // To understand this transformation calculate the 3rd row of the z-x-y
- // Euler angles rotation matrix (because of the 'g' vector, only 3rd row
- // affects to the result). Note that z-x-y matrix means R = Ry * Rx * Rz.
- // Then, assume alpha = 0 and you get this:
- //
- // x_acc = sin(gamma)
- // y_acc = - cos(gamma) * sin(beta)
- // z_acc = cos(beta) * cos(gamma)
- //
- // After that the rest is just a bit of trigonometry.
- //
- // Also note that alpha can't be provided but it's assumed to be always zero.
- // This is necessary in order to provide enough information to solve
- // the equations.
- //
- const double kRad2deg = 180.0 / M_PI;
-
- scoped_refptr<Orientation> orientation(new Orientation());
-
- orientation->set_beta(kRad2deg * atan2(-axis_value[1], axis_value[2]));
- orientation->set_gamma(kRad2deg * asin(axis_value[0]));
- // TODO(aousterh): should absolute_ be set to false here?
- // See crbug.com/136010.
-
- // Make sure that the interval boundaries comply with the specification. At
- // this point, beta is [-180, 180] and gamma is [-90, 90], but the spec has
- // the upper bound open on both.
- if (orientation->beta() == 180.0) {
- orientation->set_beta(-180.0); // -180 == 180 (upside-down)
- }
- if (orientation->gamma() == 90.0) {
- static double just_less_than_90 = nextafter(90, 0);
- orientation->set_gamma(just_less_than_90);
- }
-
- // At this point, DCHECKing is paranoia. Never hurts.
- DCHECK_GE(orientation->beta(), -180.0);
- DCHECK_LT(orientation->beta(), 180.0);
- DCHECK_GE(orientation->gamma(), -90.0);
- DCHECK_LT(orientation->gamma(), 90.0);
-
- orientation->AddRef();
- return orientation.get();
-}
-
-bool AccelerometerMac::Init() {
- sudden_motion_sensor_.reset(SuddenMotionSensor::Create());
- return sudden_motion_sensor_.get() != NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/accelerometer_mac.h b/chromium/content/browser/device_orientation/accelerometer_mac.h
deleted file mode 100644
index 654ae83e843..00000000000
--- a/chromium/content/browser/device_orientation/accelerometer_mac.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_BROWSER_DEVICE_ORIENTATION_ACCELEROMETER_MAC_H_
-#define CONTENT_BROWSER_DEVICE_ORIENTATION_ACCELEROMETER_MAC_H_
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/device_orientation/data_fetcher.h"
-#include "content/browser/device_orientation/device_data.h"
-
-class SuddenMotionSensor;
-
-namespace content {
-
-class Orientation;
-
-class AccelerometerMac : public DataFetcher {
- public:
- static DataFetcher* Create();
-
- // Implement DataFetcher.
- virtual const DeviceData* GetDeviceData(DeviceData::Type type) OVERRIDE;
-
- virtual ~AccelerometerMac();
-
- private:
- AccelerometerMac();
- bool Init();
- const Orientation* GetOrientation();
-
- scoped_ptr<SuddenMotionSensor> sudden_motion_sensor_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_ACCELEROMETER_MAC_H_
diff --git a/chromium/content/browser/device_orientation/data_fetcher.h b/chromium/content/browser/device_orientation/data_fetcher.h
deleted file mode 100644
index 0e739cddbf0..00000000000
--- a/chromium/content/browser/device_orientation/data_fetcher.h
+++ /dev/null
@@ -1,24 +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_DEVICE_ORIENTATION_DATA_FETCHER_H_
-#define CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_H_
-
-#include "content/browser/device_orientation/device_data.h"
-
-namespace content {
-
-class DataFetcher {
- public:
- virtual ~DataFetcher() {}
-
- // Returns NULL if there was a fatal error getting the device data of this
- // type or if this fetcher can never provide this type of data. Otherwise,
- // returns a pointer to a DeviceData containing the most recent data.
- virtual const DeviceData* GetDeviceData(DeviceData::Type type) = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_H_
diff --git a/chromium/content/browser/device_orientation/data_fetcher_impl_android.cc b/chromium/content/browser/device_orientation/data_fetcher_impl_android.cc
index 8d4919c4d58..c103029f62b 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_impl_android.cc
+++ b/chromium/content/browser/device_orientation/data_fetcher_impl_android.cc
@@ -8,20 +8,21 @@
#include "base/android/jni_android.h"
#include "base/memory/singleton.h"
-#include "content/browser/device_orientation/orientation.h"
+#include "base/metrics/histogram.h"
+#include "content/browser/device_orientation/inertial_sensor_consts.h"
#include "jni/DeviceMotionAndOrientation_jni.h"
using base::android::AttachCurrentThread;
-namespace content {
-
namespace {
-// This should match ProviderImpl::kDesiredSamplingIntervalMs.
-// TODO(husky): Make that constant public so we can use it directly.
-const int kPeriodInMilliseconds = 100;
+static void updateRotationVectorHistogram(bool value) {
+ UMA_HISTOGRAM_BOOLEAN("InertialSensor.RotationVectorAndroidAvailable", value);
+}
-} // namespace
+}
+
+namespace content {
DataFetcherImplAndroid::DataFetcherImplAndroid()
: number_active_device_motion_sensors_(0),
@@ -46,53 +47,25 @@ DataFetcherImplAndroid* DataFetcherImplAndroid::GetInstance() {
LeakySingletonTraits<DataFetcherImplAndroid> >::get();
}
-const DeviceData* DataFetcherImplAndroid::GetDeviceData(
- DeviceData::Type type) {
- if (type != DeviceData::kTypeOrientation)
- return NULL;
- return GetOrientation();
-}
-
-const Orientation* DataFetcherImplAndroid::GetOrientation() {
- // Do we have a new orientation value? (It's safe to do this outside the lock
- // because we only skip the lock if the value is null. We always enter the
- // lock if we're going to make use of the new value.)
- if (next_orientation_.get()) {
- base::AutoLock autolock(next_orientation_lock_);
- next_orientation_.swap(current_orientation_);
- }
- if (!current_orientation_.get())
- return new Orientation();
- return current_orientation_.get();
-}
-
void DataFetcherImplAndroid::GotOrientation(
JNIEnv*, jobject, double alpha, double beta, double gamma) {
- {
- // TODO(timvolodine): remove this part once Device Orientation is
- // completely implemented using shared memory.
- base::AutoLock autolock(next_orientation_lock_);
-
- Orientation* orientation = new Orientation();
- orientation->set_alpha(alpha);
- orientation->set_beta(beta);
- orientation->set_gamma(gamma);
- orientation->set_absolute(true);
- next_orientation_ = orientation;
- }
+ base::AutoLock autolock(orientation_buffer_lock_);
- if (device_orientation_buffer_) {
- device_orientation_buffer_->seqlock.WriteBegin();
- device_orientation_buffer_->data.alpha = alpha;
- device_orientation_buffer_->data.hasAlpha = true;
- device_orientation_buffer_->data.beta = beta;
- device_orientation_buffer_->data.hasBeta = true;
- device_orientation_buffer_->data.gamma = gamma;
- device_orientation_buffer_->data.hasGamma = true;
- device_orientation_buffer_->seqlock.WriteEnd();
-
- if (!is_orientation_buffer_ready_)
- SetOrientationBufferReadyStatus(true);
+ if (!device_orientation_buffer_)
+ return;
+
+ device_orientation_buffer_->seqlock.WriteBegin();
+ device_orientation_buffer_->data.alpha = alpha;
+ device_orientation_buffer_->data.hasAlpha = true;
+ device_orientation_buffer_->data.beta = beta;
+ device_orientation_buffer_->data.hasBeta = true;
+ device_orientation_buffer_->data.gamma = gamma;
+ device_orientation_buffer_->data.hasGamma = true;
+ device_orientation_buffer_->seqlock.WriteEnd();
+
+ if (!is_orientation_buffer_ready_) {
+ SetOrientationBufferReadyStatus(true);
+ updateRotationVectorHistogram(true);
}
}
@@ -166,8 +139,8 @@ bool DataFetcherImplAndroid::Start(DeviceData::Type event_type) {
DCHECK(!device_orientation_.is_null());
return Java_DeviceMotionAndOrientation_start(
AttachCurrentThread(), device_orientation_.obj(),
- reinterpret_cast<jint>(this), static_cast<jint>(event_type),
- kPeriodInMilliseconds);
+ reinterpret_cast<intptr_t>(this), static_cast<jint>(event_type),
+ kInertialSensorIntervalMillis);
}
void DataFetcherImplAndroid::Stop(DeviceData::Type event_type) {
@@ -226,9 +199,18 @@ void DataFetcherImplAndroid::CheckMotionBufferReadyToRead() {
received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] ==
number_active_device_motion_sensors_) {
device_motion_buffer_->seqlock.WriteBegin();
- device_motion_buffer_->data.interval = kPeriodInMilliseconds;
+ device_motion_buffer_->data.interval = kInertialSensorIntervalMillis;
device_motion_buffer_->seqlock.WriteEnd();
SetMotionBufferReadyStatus(true);
+
+ UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerAndroidAvailable",
+ received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] > 0);
+ UMA_HISTOGRAM_BOOLEAN(
+ "InertialSensor.AccelerometerIncGravityAndroidAvailable",
+ received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY]
+ > 0);
+ UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyroscopeAndroidAvailable",
+ received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] > 0);
}
}
@@ -249,6 +231,8 @@ void DataFetcherImplAndroid::ClearInternalMotionBuffers() {
void DataFetcherImplAndroid::SetOrientationBufferReadyStatus(bool ready) {
device_orientation_buffer_->seqlock.WriteBegin();
+ device_orientation_buffer_->data.absolute = ready;
+ device_orientation_buffer_->data.hasAbsolute = ready;
device_orientation_buffer_->data.allAvailableSensorsAreActive = ready;
device_orientation_buffer_->seqlock.WriteEnd();
is_orientation_buffer_ready_ = ready;
@@ -257,20 +241,33 @@ void DataFetcherImplAndroid::SetOrientationBufferReadyStatus(bool ready) {
bool DataFetcherImplAndroid::StartFetchingDeviceOrientationData(
DeviceOrientationHardwareBuffer* buffer) {
DCHECK(buffer);
- device_orientation_buffer_ = buffer;
+ {
+ base::AutoLock autolock(orientation_buffer_lock_);
+ device_orientation_buffer_ = buffer;
+ }
bool success = Start(DeviceData::kTypeOrientation);
- // If Start() was unsuccessful then set the buffer ready flag to true
- // to start firing all-null events.
- SetOrientationBufferReadyStatus(!success);
+ {
+ base::AutoLock autolock(orientation_buffer_lock_);
+ // If Start() was unsuccessful then set the buffer ready flag to true
+ // to start firing all-null events.
+ SetOrientationBufferReadyStatus(!success);
+ }
+
+ if (!success)
+ updateRotationVectorHistogram(false);
+
return success;
}
void DataFetcherImplAndroid::StopFetchingDeviceOrientationData() {
Stop(DeviceData::kTypeOrientation);
- if (device_orientation_buffer_) {
- SetOrientationBufferReadyStatus(false);
- device_orientation_buffer_ = NULL;
+ {
+ base::AutoLock autolock(orientation_buffer_lock_);
+ if (device_orientation_buffer_) {
+ SetOrientationBufferReadyStatus(false);
+ device_orientation_buffer_ = NULL;
+ }
}
}
diff --git a/chromium/content/browser/device_orientation/data_fetcher_impl_android.h b/chromium/content/browser/device_orientation/data_fetcher_impl_android.h
index f348e1d3e54..9332fa2e20a 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_impl_android.h
+++ b/chromium/content/browser/device_orientation/data_fetcher_impl_android.h
@@ -10,25 +10,21 @@
#include "base/synchronization/lock.h"
#include "content/browser/device_orientation/device_data.h"
#include "content/common/content_export.h"
-#include "content/common/device_motion_hardware_buffer.h"
+#include "content/common/device_orientation/device_motion_hardware_buffer.h"
#include "content/common/device_orientation/device_orientation_hardware_buffer.h"
template<typename T> struct DefaultSingletonTraits;
namespace content {
-class Orientation;
-// Android implementation of DeviceOrientation API.
+// Android implementation of Device Orientation API.
+//
+// Android's SensorManager has a push API, so when Got*() methods are called
+// by the system the browser process puts the received data into a shared
+// memory buffer, which is read by the renderer processes.
+//
-// Android's SensorManager has a push API, whereas Chrome wants to pull data.
-// To fit them together, we store incoming sensor events in a 1-element buffer.
-// SensorManager calls SetOrientation() which pushes a new value (discarding the
-// previous value if any). Chrome calls GetDeviceData() which reads the most
-// recent value. Repeated calls to GetDeviceData() will return the same value.
-
-// TODO(timvolodine): Simplify this class and remove GetDeviceData() method,
-// once Device Orientation switches to shared memory implementation.
-// Also rename this class to SensorManagerAndroid.
+// TODO(timvolodine): rename this class to SensorManagerAndroid.
class CONTENT_EXPORT DataFetcherImplAndroid {
public:
// Must be called at startup, before GetInstance().
@@ -47,8 +43,6 @@ class CONTENT_EXPORT DataFetcherImplAndroid {
void GotRotationRate(JNIEnv*, jobject,
double alpha, double beta, double gamma);
- const DeviceData* GetDeviceData(DeviceData::Type type);
-
virtual bool Start(DeviceData::Type event_type);
virtual void Stop(DeviceData::Type event_type);
@@ -69,8 +63,6 @@ class CONTENT_EXPORT DataFetcherImplAndroid {
private:
friend struct DefaultSingletonTraits<DataFetcherImplAndroid>;
- const Orientation* GetOrientation();
-
void CheckMotionBufferReadyToRead();
void SetMotionBufferReadyStatus(bool ready);
void ClearInternalMotionBuffers();
@@ -83,12 +75,6 @@ class CONTENT_EXPORT DataFetcherImplAndroid {
RECEIVED_MOTION_DATA_ROTATION_RATE = 2,
RECEIVED_MOTION_DATA_MAX = 3,
};
- // Value returned by GetDeviceData.
- scoped_refptr<Orientation> current_orientation_;
-
- // 1-element buffer, written by GotOrientation, read by GetDeviceData.
- base::Lock next_orientation_lock_;
- scoped_refptr<Orientation> next_orientation_;
// The Java provider of orientation info.
base::android::ScopedJavaGlobalRef<jobject> device_orientation_;
@@ -100,6 +86,7 @@ class CONTENT_EXPORT DataFetcherImplAndroid {
bool is_orientation_buffer_ready_;
base::Lock motion_buffer_lock_;
+ base::Lock orientation_buffer_lock_;
DISALLOW_COPY_AND_ASSIGN(DataFetcherImplAndroid);
};
diff --git a/chromium/content/browser/device_orientation/data_fetcher_impl_android_unittest.cc b/chromium/content/browser/device_orientation/data_fetcher_impl_android_unittest.cc
index d12c8c6feb1..3d36222cf0c 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_impl_android_unittest.cc
+++ b/chromium/content/browser/device_orientation/data_fetcher_impl_android_unittest.cc
@@ -7,14 +7,13 @@
#include "base/android/jni_android.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "content/browser/device_orientation/inertial_sensor_consts.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
-const int kPeriodInMilliseconds = 100;
-
class FakeDataFetcherImplAndroid : public DataFetcherImplAndroid {
public:
FakeDataFetcherImplAndroid() { }
@@ -84,7 +83,7 @@ TEST_F(AndroidDataFetcherTest, ThreeDeviceMotionSensorsActive) {
ASSERT_TRUE(motion_buffer_->data.hasRotationRateBeta);
ASSERT_EQ(9, motion_buffer_->data.rotationRateGamma);
ASSERT_TRUE(motion_buffer_->data.hasRotationRateGamma);
- ASSERT_EQ(kPeriodInMilliseconds, motion_buffer_->data.interval);
+ ASSERT_EQ(kInertialSensorIntervalMillis, motion_buffer_->data.interval);
fetcher.StopFetchingDeviceMotionData();
ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
@@ -103,7 +102,7 @@ TEST_F(AndroidDataFetcherTest, TwoDeviceMotionSensorsActive) {
fetcher.GotAccelerationIncludingGravity(0, 0, 1, 2, 3);
ASSERT_TRUE(motion_buffer_->data.allAvailableSensorsAreActive);
- ASSERT_EQ(kPeriodInMilliseconds, motion_buffer_->data.interval);
+ ASSERT_EQ(kInertialSensorIntervalMillis, motion_buffer_->data.interval);
fetcher.StopFetchingDeviceMotionData();
ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
@@ -116,7 +115,7 @@ TEST_F(AndroidDataFetcherTest, ZeroDeviceMotionSensorsActive) {
fetcher.StartFetchingDeviceMotionData(motion_buffer_.get());
ASSERT_TRUE(motion_buffer_->data.allAvailableSensorsAreActive);
- ASSERT_EQ(kPeriodInMilliseconds, motion_buffer_->data.interval);
+ ASSERT_EQ(kInertialSensorIntervalMillis, motion_buffer_->data.interval);
fetcher.StopFetchingDeviceMotionData();
ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
diff --git a/chromium/content/browser/device_orientation/data_fetcher_impl_win.cc b/chromium/content/browser/device_orientation/data_fetcher_impl_win.cc
deleted file mode 100644
index d08ed446ad6..00000000000
--- a/chromium/content/browser/device_orientation/data_fetcher_impl_win.cc
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/device_orientation/data_fetcher_impl_win.h"
-
-#include <InitGuid.h>
-#include <PortableDeviceTypes.h>
-#include <Sensors.h>
-
-#include "base/logging.h"
-#include "base/win/iunknown_impl.h"
-#include "base/win/windows_version.h"
-#include "content/browser/device_orientation/orientation.h"
-
-namespace {
-
-// This should match ProviderImpl::kDesiredSamplingIntervalMs.
-const int kPeriodInMilliseconds = 100;
-
-} // namespace
-
-namespace content {
-
-class DataFetcherImplWin::SensorEventSink : public ISensorEvents,
- public base::win::IUnknownImpl {
- public:
- explicit SensorEventSink(DataFetcherImplWin* const fetcher)
- : fetcher_(fetcher) {}
-
- virtual ~SensorEventSink() {}
-
- // IUnknown interface
- virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE {
- return IUnknownImpl::AddRef();
- }
-
- virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE {
- return IUnknownImpl::Release();
- }
-
- virtual STDMETHODIMP QueryInterface(REFIID riid, void** ppv) OVERRIDE {
- if (riid == __uuidof(ISensorEvents)) {
- *ppv = static_cast<ISensorEvents*>(this);
- AddRef();
- return S_OK;
- }
- return IUnknownImpl::QueryInterface(riid, ppv);
- }
-
- // ISensorEvents interface
- STDMETHODIMP OnEvent(ISensor* sensor,
- REFGUID event_id,
- IPortableDeviceValues* event_data) OVERRIDE {
- return S_OK;
- }
-
- STDMETHODIMP OnDataUpdated(ISensor* sensor,
- ISensorDataReport* new_data) OVERRIDE {
- if (NULL == new_data || NULL == sensor)
- return E_INVALIDARG;
-
- PROPVARIANT value = {};
- scoped_refptr<Orientation> orientation = new Orientation();
-
- if (SUCCEEDED(new_data->GetSensorValue(
- SENSOR_DATA_TYPE_TILT_X_DEGREES, &value))) {
- orientation->set_beta(value.fltVal);
- }
- PropVariantClear(&value);
-
- if (SUCCEEDED(new_data->GetSensorValue(
- SENSOR_DATA_TYPE_TILT_Y_DEGREES, &value))) {
- orientation->set_gamma(value.fltVal);
- }
- PropVariantClear(&value);
-
- if (SUCCEEDED(new_data->GetSensorValue(
- SENSOR_DATA_TYPE_TILT_Z_DEGREES, &value))) {
- orientation->set_alpha(value.fltVal);
- }
- PropVariantClear(&value);
-
- orientation->set_absolute(true);
- fetcher_->OnOrientationData(orientation.get());
-
- return S_OK;
- }
-
- STDMETHODIMP OnLeave(REFSENSOR_ID sensor_id) OVERRIDE {
- return S_OK;
- }
-
- STDMETHODIMP OnStateChanged(ISensor* sensor, SensorState state) OVERRIDE {
- return S_OK;
- }
-
- private:
- DataFetcherImplWin* const fetcher_;
-
- DISALLOW_COPY_AND_ASSIGN(SensorEventSink);
-};
-
-// Create a DataFetcherImplWin object and return NULL if no valid sensor found.
-// static
-DataFetcher* DataFetcherImplWin::Create() {
- scoped_ptr<DataFetcherImplWin> fetcher(new DataFetcherImplWin);
- if (fetcher->Initialize())
- return fetcher.release();
-
- LOG(ERROR) << "DataFetcherImplWin::Initialize failed!";
- return NULL;
-}
-
-DataFetcherImplWin::~DataFetcherImplWin() {
- if (sensor_)
- sensor_->SetEventSink(NULL);
-}
-
-DataFetcherImplWin::DataFetcherImplWin() {
-}
-
-void DataFetcherImplWin::OnOrientationData(Orientation* orientation) {
- // This method is called on Windows sensor thread.
- base::AutoLock autolock(next_orientation_lock_);
- next_orientation_ = orientation;
-}
-
-const DeviceData* DataFetcherImplWin::GetDeviceData(DeviceData::Type type) {
- if (type != DeviceData::kTypeOrientation)
- return NULL;
- return GetOrientation();
-}
-
-const Orientation* DataFetcherImplWin::GetOrientation() {
- if (next_orientation_.get()) {
- base::AutoLock autolock(next_orientation_lock_);
- next_orientation_.swap(current_orientation_);
- }
- if (!current_orientation_.get())
- return new Orientation();
- return current_orientation_.get();
-}
-
-bool DataFetcherImplWin::Initialize() {
- if (base::win::GetVersion() < base::win::VERSION_WIN7)
- return false;
-
- base::win::ScopedComPtr<ISensorManager> sensor_manager;
- HRESULT hr = sensor_manager.CreateInstance(CLSID_SensorManager);
- if (FAILED(hr) || !sensor_manager)
- return false;
-
- base::win::ScopedComPtr<ISensorCollection> sensor_collection;
- hr = sensor_manager->GetSensorsByType(
- SENSOR_TYPE_INCLINOMETER_3D, sensor_collection.Receive());
-
- if (FAILED(hr) || !sensor_collection)
- return false;
-
- ULONG count = 0;
- hr = sensor_collection->GetCount(&count);
- if (FAILED(hr) || !count)
- return false;
-
- hr = sensor_collection->GetAt(0, sensor_.Receive());
- if (FAILED(hr) || !sensor_)
- return false;
-
- base::win::ScopedComPtr<IPortableDeviceValues> device_values;
- if (SUCCEEDED(device_values.CreateInstance(CLSID_PortableDeviceValues))) {
- if (SUCCEEDED(device_values->SetUnsignedIntegerValue(
- SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, kPeriodInMilliseconds))) {
- base::win::ScopedComPtr<IPortableDeviceValues> return_values;
- sensor_->SetProperties(device_values.get(), return_values.Receive());
- }
- }
-
- scoped_refptr<SensorEventSink> sensor_event_impl(new SensorEventSink(this));
- base::win::ScopedComPtr<ISensorEvents> sensor_events;
- hr = sensor_event_impl->QueryInterface(
- __uuidof(ISensorEvents), sensor_events.ReceiveVoid());
- if (FAILED(hr) || !sensor_events)
- return false;
-
- hr = sensor_->SetEventSink(sensor_events);
- if (FAILED(hr))
- return false;
-
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/data_fetcher_impl_win.h b/chromium/content/browser/device_orientation/data_fetcher_impl_win.h
deleted file mode 100644
index 9a065066a31..00000000000
--- a/chromium/content/browser/device_orientation/data_fetcher_impl_win.h
+++ /dev/null
@@ -1,63 +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_DEVICE_ORIENTATION_DATA_FETCHER_IMPL_WIN_H_
-#define CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_IMPL_WIN_H_
-
-#include <SensorsApi.h>
-
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "base/win/scoped_comptr.h"
-#include "content/browser/device_orientation/data_fetcher.h"
-#include "content/browser/device_orientation/device_data.h"
-
-namespace content {
-
-class Orientation;
-
-// Windows implementation of DeviceOrientation API.
-// The SensorEventSink is installed to Windows sensor thread to listen for
-// sensor's data. Upon each notification, DataFetcherImplWin buffers the data.
-// Then Chrome sensor polling thread pulls the buffered data via GetDeviceData.
-// The Inclinometer 3D sensor (SENSOR_TYPE_INCLINOMETER_3D) is used to get the
-// orientation data.
-
-class DataFetcherImplWin : public DataFetcher {
- public:
- virtual ~DataFetcherImplWin();
-
- // Factory function. It returns NULL on error.
- // The created object listens for events for the whole lifetime.
- static DataFetcher* Create();
-
- // Implement DataFetcher.
- virtual const DeviceData* GetDeviceData(DeviceData::Type type) OVERRIDE;
-
- private:
- class SensorEventSink;
- friend SensorEventSink;
-
- DataFetcherImplWin();
- bool Initialize();
- void OnOrientationData(Orientation* orientation);
- const Orientation* GetOrientation();
-
- base::win::ScopedComPtr<ISensor> sensor_;
-
- // Value returned by GetDeviceData.
- scoped_refptr<Orientation> current_orientation_;
-
- // The 1-element buffer follows DataFetcherImplAndroid implementation.
- // It is written by OnOrientationData and read by GetDeviceData.
- base::Lock next_orientation_lock_;
- scoped_refptr<Orientation> next_orientation_;
-
- DISALLOW_COPY_AND_ASSIGN(DataFetcherImplWin);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_IMPL_WIN_H_
diff --git a/chromium/content/browser/device_orientation/data_fetcher_orientation_android.cc b/chromium/content/browser/device_orientation/data_fetcher_orientation_android.cc
deleted file mode 100644
index 823595651f4..00000000000
--- a/chromium/content/browser/device_orientation/data_fetcher_orientation_android.cc
+++ /dev/null
@@ -1,37 +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/device_orientation/data_fetcher_orientation_android.h"
-
-#include "base/logging.h"
-#include "content/browser/device_orientation/data_fetcher_impl_android.h"
-
-namespace content {
-
-DataFetcherOrientationAndroid::DataFetcherOrientationAndroid() {
-}
-
-DataFetcherOrientationAndroid::~DataFetcherOrientationAndroid() {
- DataFetcherImplAndroid::GetInstance()->Stop(DeviceData::kTypeOrientation);
-}
-
-DataFetcher* DataFetcherOrientationAndroid::Create() {
- scoped_ptr<DataFetcherOrientationAndroid> fetcher(
- new DataFetcherOrientationAndroid);
- if (DataFetcherImplAndroid::GetInstance()->Start(
- DeviceData::kTypeOrientation))
- return fetcher.release();
-
- DVLOG(2) << "DataFetcherImplAndroid::Start failed!";
- return NULL;
-}
-
-const DeviceData* DataFetcherOrientationAndroid::GetDeviceData(
- DeviceData::Type type) {
- if (type != DeviceData::kTypeOrientation)
- return NULL;
- return DataFetcherImplAndroid::GetInstance()->GetDeviceData(type);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/data_fetcher_orientation_android.h b/chromium/content/browser/device_orientation/data_fetcher_orientation_android.h
deleted file mode 100644
index b0a17021217..00000000000
--- a/chromium/content/browser/device_orientation/data_fetcher_orientation_android.h
+++ /dev/null
@@ -1,32 +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 CHROME_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_ORIENTATION_ANDROID_H_
-#define CHROME_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_ORIENTATION_ANDROID_H_
-
-#include "content/browser/device_orientation/data_fetcher.h"
-#include "content/browser/device_orientation/device_data.h"
-
-namespace content {
-
-class DataFetcherOrientationAndroid : public DataFetcher {
- public:
- // Factory function. We'll listen for events for the lifetime of this object.
- // Returns NULL on error.
- static DataFetcher* Create();
-
- virtual ~DataFetcherOrientationAndroid();
-
- // Implementation of DataFetcher.
- virtual const DeviceData* GetDeviceData(DeviceData::Type type) OVERRIDE;
-
- protected:
- DataFetcherOrientationAndroid();
-
- DISALLOW_COPY_AND_ASSIGN(DataFetcherOrientationAndroid);
-};
-
-} // namespace content
-
-#endif // CHROME_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_ORIENTATION_ANDROID_H_
diff --git a/chromium/content/browser/device_orientation/data_fetcher_shared_memory.h b/chromium/content/browser/device_orientation/data_fetcher_shared_memory.h
index dad1cb60dd2..16a55fe4cd0 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_shared_memory.h
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory.h
@@ -8,7 +8,7 @@
#include "content/browser/device_orientation/data_fetcher_shared_memory_base.h"
#if !defined(OS_ANDROID)
-#include "content/common/device_motion_hardware_buffer.h"
+#include "content/common/device_orientation/device_motion_hardware_buffer.h"
#include "content/common/device_orientation/device_orientation_hardware_buffer.h"
#endif
@@ -38,7 +38,7 @@ class CONTENT_EXPORT DataFetcherSharedMemory
#endif
#if defined(OS_MACOSX)
virtual void Fetch(unsigned consumer_bitmask) OVERRIDE;
- virtual bool IsPolling() const OVERRIDE;
+ virtual FetcherType GetType() const OVERRIDE;
scoped_ptr<SuddenMotionSensor> sudden_motion_sensor_;
#elif defined(OS_WIN)
@@ -46,8 +46,7 @@ class CONTENT_EXPORT DataFetcherSharedMemory
class SensorEventSinkMotion;
class SensorEventSinkOrientation;
- virtual bool IsPolling() const OVERRIDE;
- virtual base::TimeDelta GetPollDelay() const OVERRIDE;
+ virtual FetcherType GetType() const OVERRIDE;
bool RegisterForSensor(REFSENSOR_TYPE_ID sensor_type, ISensor** sensor,
scoped_refptr<SensorEventSink> event_sink);
diff --git a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_android.cc b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_android.cc
index 3f00c3d179f..194c0c21b8d 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_android.cc
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_android.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "content/browser/device_orientation/data_fetcher_impl_android.h"
-#include "content/common/device_motion_hardware_buffer.h"
+#include "content/common/device_orientation/device_motion_hardware_buffer.h"
#include "content/common/device_orientation/device_orientation_hardware_buffer.h"
namespace content {
diff --git a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.cc b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.cc
index 429713c781f..690d1f8aa7f 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.cc
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.cc
@@ -9,13 +9,12 @@
#include "base/stl_util.h"
#include "base/threading/thread.h"
#include "base/timer/timer.h"
-#include "content/common/device_motion_hardware_buffer.h"
+#include "content/common/device_orientation/device_motion_hardware_buffer.h"
#include "content/common/device_orientation/device_orientation_hardware_buffer.h"
namespace content {
namespace {
-const int kPeriodInMilliseconds = 100;
static size_t GetConsumerSharedMemoryBufferSize(ConsumerType consumer_type) {
switch (consumer_type) {
@@ -48,7 +47,6 @@ class DataFetcherSharedMemoryBase::PollingThread : public base::Thread {
unsigned consumers_bitmask_;
DataFetcherSharedMemoryBase* fetcher_;
- base::TimeDelta poll_interval_;
scoped_ptr<base::RepeatingTimer<PollingThread> > timer_;
DISALLOW_COPY_AND_ASSIGN(PollingThread);
@@ -60,8 +58,7 @@ DataFetcherSharedMemoryBase::PollingThread::PollingThread(
const char* name, DataFetcherSharedMemoryBase* fetcher)
: base::Thread(name),
consumers_bitmask_(0),
- fetcher_(fetcher),
- poll_interval_(fetcher->GetPollDelay()) {
+ fetcher_(fetcher) {
}
DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
@@ -75,10 +72,10 @@ void DataFetcherSharedMemoryBase::PollingThread::AddConsumer(
consumers_bitmask_ |= consumer_type;
- if (!timer_ && poll_interval_.InMilliseconds() > 0) {
+ if (!timer_ && fetcher_->GetType() == FETCHER_TYPE_POLLING_CALLBACK) {
timer_.reset(new base::RepeatingTimer<PollingThread>());
timer_->Start(FROM_HERE,
- poll_interval_,
+ fetcher_->GetInterval(),
this, &PollingThread::DoPoll);
}
}
@@ -128,7 +125,7 @@ bool DataFetcherSharedMemoryBase::StartFetchingDeviceData(
if (!buffer)
return false;
- if (IsPolling()) {
+ if (GetType() != FETCHER_TYPE_DEFAULT) {
if (!InitAndStartPollingThreadIfNecessary())
return false;
polling_thread_->message_loop()->PostTask(
@@ -151,7 +148,7 @@ bool DataFetcherSharedMemoryBase::StopFetchingDeviceData(
if (!(started_consumers_ & consumer_type))
return true;
- if (IsPolling()) {
+ if (GetType() != FETCHER_TYPE_DEFAULT) {
polling_thread_->message_loop()->PostTask(
FROM_HERE,
base::Bind(&PollingThread::RemoveConsumer,
@@ -197,12 +194,13 @@ void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask) {
NOTIMPLEMENTED();
}
-bool DataFetcherSharedMemoryBase::IsPolling() const {
- return false;
+DataFetcherSharedMemoryBase::FetcherType
+DataFetcherSharedMemoryBase::GetType() const {
+ return FETCHER_TYPE_DEFAULT;
}
-base::TimeDelta DataFetcherSharedMemoryBase::GetPollDelay() const {
- return base::TimeDelta::FromMilliseconds(kPeriodInMilliseconds);
+base::TimeDelta DataFetcherSharedMemoryBase::GetInterval() const {
+ return base::TimeDelta::FromMilliseconds(kInertialSensorIntervalMillis);
}
base::SharedMemory* DataFetcherSharedMemoryBase::GetSharedMemory(
diff --git a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.h b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.h
index 8894b014a01..e0ac543f217 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.h
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base.h
@@ -39,6 +39,15 @@ class CONTENT_EXPORT DataFetcherSharedMemoryBase {
base::SharedMemoryHandle GetSharedMemoryHandleForProcess(
ConsumerType consumer_type, base::ProcessHandle process);
+ enum FetcherType {
+ // Fetcher runs on the same thread as its creator.
+ FETCHER_TYPE_DEFAULT,
+ // Fetcher runs on a separate thread calling |Fetch()| at regular intervals.
+ FETCHER_TYPE_POLLING_CALLBACK,
+ // Fetcher runs on a separate thread, but no callbacks are executed.
+ FETCHER_TYPE_SEPARATE_THREAD
+ };
+
protected:
class PollingThread;
@@ -53,13 +62,13 @@ class CONTENT_EXPORT DataFetcherSharedMemoryBase {
// at regular intervals.
virtual void Fetch(unsigned consumer_bitmask);
- // Returns true if this fetcher needs to use a polling thread to
- // fetch the sensor data.
- virtual bool IsPolling() const;
+ // Returns the type of thread this fetcher runs on.
+ virtual FetcherType GetType() const;
- // Returns the interval between successive calls to Fetch().
- // If interval is zero, Fetch() is never called.
- virtual base::TimeDelta GetPollDelay() const;
+ // Returns the sensor sampling interval. In particular if this fetcher
+ // GetType() == FETCHER_TYPE_POLLING_CALLBACK the interval between
+ // successive calls to Fetch().
+ virtual base::TimeDelta GetInterval() const;
// Start() method should call InitSharedMemoryBuffer() to get the shared
// memory pointer. If IsPolling() is true both Start() and Stop() methods
diff --git a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base_unittest.cc b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base_unittest.cc
index f2028a6c436..dd452a073d4 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base_unittest.cc
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_base_unittest.cc
@@ -8,7 +8,7 @@
#include "base/process/process_handle.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
-#include "content/common/device_motion_hardware_buffer.h"
+#include "content/common/device_orientation/device_motion_hardware_buffer.h"
#include "content/common/device_orientation/device_orientation_hardware_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -16,9 +16,6 @@ namespace content {
namespace {
-const int kPeriodInMilliseconds = 100;
-
-
class FakeDataFetcher : public DataFetcherSharedMemoryBase {
public:
FakeDataFetcher()
@@ -54,7 +51,7 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase {
DeviceMotionHardwareBuffer* buffer = GetMotionBuffer();
ASSERT_TRUE(buffer);
buffer->seqlock.WriteBegin();
- buffer->data.interval = kPeriodInMilliseconds;
+ buffer->data.interval = kInertialSensorIntervalMillis;
buffer->seqlock.WriteEnd();
updated_motion_.Signal();
}
@@ -160,15 +157,15 @@ class FakeNonPollingDataFetcher : public FakeDataFetcher {
return true;
}
- virtual bool IsPolling() const OVERRIDE {
- return false;
- }
-
virtual void Fetch(unsigned consumer_bitmask) OVERRIDE {
FAIL() << "fetch should not be called, "
<< "because this is a non-polling fetcher";
}
+ virtual FetcherType GetType() const OVERRIDE {
+ return FakeDataFetcher::GetType();
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(FakeNonPollingDataFetcher);
@@ -223,8 +220,8 @@ class FakePollingDataFetcher : public FakeDataFetcher {
UpdateMotion();
}
- virtual bool IsPolling() const OVERRIDE {
- return true;
+ virtual FetcherType GetType() const OVERRIDE {
+ return FETCHER_TYPE_POLLING_CALLBACK;
}
private:
@@ -274,12 +271,8 @@ class FakeZeroDelayPollingDataFetcher : public FakeDataFetcher {
FAIL() << "fetch should not be called";
}
- virtual bool IsPolling() const OVERRIDE {
- return true;
- }
-
- virtual base::TimeDelta GetPollDelay() const OVERRIDE {
- return base::TimeDelta::FromMilliseconds(0);
+ virtual FetcherType GetType() const OVERRIDE {
+ return FETCHER_TYPE_SEPARATE_THREAD;
}
bool IsPollingTimerRunningForTesting() const {
@@ -294,12 +287,13 @@ class FakeZeroDelayPollingDataFetcher : public FakeDataFetcher {
TEST(DataFetcherSharedMemoryBaseTest, DoesStartMotion) {
FakeNonPollingDataFetcher fake_data_fetcher;
- EXPECT_FALSE(fake_data_fetcher.IsPolling());
+ EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_DEFAULT,
+ fake_data_fetcher.GetType());
EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_MOTION));
fake_data_fetcher.WaitForStart(CONSUMER_TYPE_MOTION);
- EXPECT_EQ(kPeriodInMilliseconds,
+ EXPECT_EQ(kInertialSensorIntervalMillis,
fake_data_fetcher.GetMotionBuffer()->data.interval);
fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
@@ -308,7 +302,8 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesStartMotion) {
TEST(DataFetcherSharedMemoryBaseTest, DoesStartOrientation) {
FakeNonPollingDataFetcher fake_data_fetcher;
- EXPECT_FALSE(fake_data_fetcher.IsPolling());
+ EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_DEFAULT,
+ fake_data_fetcher.GetType());
EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
CONSUMER_TYPE_ORIENTATION));
@@ -322,13 +317,14 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesStartOrientation) {
TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotion) {
FakePollingDataFetcher fake_data_fetcher;
- EXPECT_TRUE(fake_data_fetcher.IsPolling());
+ EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK,
+ fake_data_fetcher.GetType());
EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_MOTION));
fake_data_fetcher.WaitForStart(CONSUMER_TYPE_MOTION);
fake_data_fetcher.WaitForUpdate(CONSUMER_TYPE_MOTION);
- EXPECT_EQ(kPeriodInMilliseconds,
+ EXPECT_EQ(kInertialSensorIntervalMillis,
fake_data_fetcher.GetMotionBuffer()->data.interval);
fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
@@ -337,7 +333,8 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotion) {
TEST(DataFetcherSharedMemoryBaseTest, DoesPollOrientation) {
FakePollingDataFetcher fake_data_fetcher;
- EXPECT_TRUE(fake_data_fetcher.IsPolling());
+ EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK,
+ fake_data_fetcher.GetType());
EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
CONSUMER_TYPE_ORIENTATION));
@@ -352,7 +349,8 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesPollOrientation) {
TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotionAndOrientation) {
FakePollingDataFetcher fake_data_fetcher;
- EXPECT_TRUE(fake_data_fetcher.IsPolling());
+ EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK,
+ fake_data_fetcher.GetType());
EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
CONSUMER_TYPE_ORIENTATION));
@@ -375,7 +373,7 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotionAndOrientation) {
fake_data_fetcher.WaitForUpdate(CONSUMER_TYPE_MOTION);
EXPECT_EQ(1, fake_data_fetcher.GetOrientationBuffer()->data.alpha);
- EXPECT_EQ(kPeriodInMilliseconds,
+ EXPECT_EQ(kInertialSensorIntervalMillis,
fake_data_fetcher.GetMotionBuffer()->data.interval);
fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
@@ -386,8 +384,8 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotionAndOrientation) {
TEST(DataFetcherSharedMemoryBaseTest, DoesNotPollZeroDelay) {
FakeZeroDelayPollingDataFetcher fake_data_fetcher;
- EXPECT_TRUE(fake_data_fetcher.IsPolling());
- EXPECT_EQ(0, fake_data_fetcher.GetPollDelay().InMilliseconds());
+ EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_SEPARATE_THREAD,
+ fake_data_fetcher.GetType());
EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
CONSUMER_TYPE_ORIENTATION));
@@ -401,7 +399,6 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesNotPollZeroDelay) {
}
-
} // namespace
} // namespace content
diff --git a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_default.cc b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_default.cc
index c05cdcdbb8f..ce7b5676e66 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_default.cc
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_default.cc
@@ -5,6 +5,7 @@
#include "data_fetcher_shared_memory.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
namespace {
@@ -45,10 +46,13 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
switch (consumer_type) {
case CONSUMER_TYPE_MOTION:
motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer);
+ UMA_HISTOGRAM_BOOLEAN("InertialSensor.MotionDefaultAvailable", false);
return SetMotionBuffer(motion_buffer_, true);
case CONSUMER_TYPE_ORIENTATION:
orientation_buffer_ =
static_cast<DeviceOrientationHardwareBuffer*>(buffer);
+ UMA_HISTOGRAM_BOOLEAN("InertialSensor.OrientationDefaultAvailable",
+ false);
return SetOrientationBuffer(orientation_buffer_, true);
default:
NOTREACHED();
diff --git a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_mac.cc b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_mac.cc
index f606bda3a61..91ffd3e1fc4 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_mac.cc
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_mac.cc
@@ -5,6 +5,7 @@
#include "data_fetcher_shared_memory.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h"
namespace {
@@ -111,8 +112,8 @@ void DataFetcherSharedMemory::Fetch(unsigned consumer_bitmask) {
FetchMotion(sudden_motion_sensor_.get(), motion_buffer_);
}
-bool DataFetcherSharedMemory::IsPolling() const {
- return true;
+DataFetcherSharedMemory::FetcherType DataFetcherSharedMemory::GetType() const {
+ return FETCHER_TYPE_POLLING_CALLBACK;
}
bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
@@ -124,12 +125,16 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer);
if (!sudden_motion_sensor_)
sudden_motion_sensor_.reset(SuddenMotionSensor::Create());
+ UMA_HISTOGRAM_BOOLEAN("InertialSensor.MotionMacAvailable",
+ sudden_motion_sensor_.get() != NULL);
return sudden_motion_sensor_.get() != NULL;
case CONSUMER_TYPE_ORIENTATION:
orientation_buffer_ =
static_cast<DeviceOrientationHardwareBuffer*>(buffer);
if (!sudden_motion_sensor_)
sudden_motion_sensor_.reset(SuddenMotionSensor::Create());
+ UMA_HISTOGRAM_BOOLEAN("InertialSensor.OrientationMacAvailable",
+ sudden_motion_sensor_.get() != NULL);
return sudden_motion_sensor_.get() != NULL;
default:
NOTREACHED();
diff --git a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_win.cc b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_win.cc
index 65389890ee2..d5cf46a97e0 100644
--- a/chromium/content/browser/device_orientation/data_fetcher_shared_memory_win.cc
+++ b/chromium/content/browser/device_orientation/data_fetcher_shared_memory_win.cc
@@ -10,13 +10,13 @@
#include <Sensors.h>
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/win/iunknown_impl.h"
#include "base/win/windows_version.h"
namespace {
const double kMeanGravity = 9.80665;
-const int kPeriodInMilliseconds = 100;
} // namespace
@@ -183,9 +183,8 @@ class DataFetcherSharedMemory::SensorEventSinkMotion
-acceleration_including_gravity_z * kMeanGravity;
buffer_->data.hasAccelerationIncludingGravityZ =
has_acceleration_including_gravity_z;
- // TODO(timvolodine): consider setting the two variables below
- // after all sensors have fired.
- buffer_->data.interval = kPeriodInMilliseconds;
+ // TODO(timvolodine): consider setting this after all
+ // sensors have fired.
buffer_->data.allAvailableSensorsAreActive = true;
buffer_->seqlock.WriteEnd();
}
@@ -209,7 +208,6 @@ class DataFetcherSharedMemory::SensorEventSinkMotion
buffer_->data.hasRotationRateBeta = has_beta;
buffer_->data.rotationRateGamma = gamma;
buffer_->data.hasRotationRateGamma = has_gamma;
- buffer_->data.interval = kPeriodInMilliseconds;
buffer_->data.allAvailableSensorsAreActive = true;
buffer_->seqlock.WriteEnd();
}
@@ -233,14 +231,8 @@ DataFetcherSharedMemory::DataFetcherSharedMemory()
DataFetcherSharedMemory::~DataFetcherSharedMemory() {
}
-bool DataFetcherSharedMemory::IsPolling() const {
- return true;
-}
-
-base::TimeDelta DataFetcherSharedMemory::GetPollDelay() const {
- // We only need a new thread for this fetcher, the actual interface
- // is push-bashed so no need for explicit callbacks to Fetch().
- return base::TimeDelta::FromMilliseconds(0);
+DataFetcherSharedMemory::FetcherType DataFetcherSharedMemory::GetType() const {
+ return FETCHER_TYPE_SEPARATE_THREAD;
}
bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
@@ -253,8 +245,11 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
static_cast<DeviceOrientationHardwareBuffer*>(buffer);
scoped_refptr<SensorEventSink> sink(
new SensorEventSinkOrientation(orientation_buffer_));
- if (RegisterForSensor(SENSOR_TYPE_INCLINOMETER_3D,
- sensor_inclinometer_.Receive(), sink))
+ bool inclinometer_available = RegisterForSensor(
+ SENSOR_TYPE_INCLINOMETER_3D, sensor_inclinometer_.Receive(), sink);
+ UMA_HISTOGRAM_BOOLEAN("InertialSensor.InclinometerWindowsAvailable",
+ inclinometer_available);
+ if (inclinometer_available)
return true;
// if no sensors are available set buffer to ready, to fire null-events.
SetBufferAvailableState(consumer_type, true);
@@ -270,8 +265,16 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
sink);
bool gyrometer_available = RegisterForSensor(
SENSOR_TYPE_GYROMETER_3D, sensor_gyrometer_.Receive(), sink);
- if (accelerometer_available || gyrometer_available)
+ UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerWindowsAvailable",
+ accelerometer_available);
+ UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyrometerWindowsAvailable",
+ gyrometer_available);
+ if (accelerometer_available || gyrometer_available) {
+ motion_buffer_->seqlock.WriteBegin();
+ motion_buffer_->data.interval = GetInterval().InMilliseconds();
+ motion_buffer_->seqlock.WriteEnd();
return true;
+ }
// if no sensors are available set buffer to ready, to fire null-events.
SetBufferAvailableState(consumer_type, true);
}
@@ -329,7 +332,8 @@ bool DataFetcherSharedMemory::RegisterForSensor(
base::win::ScopedComPtr<IPortableDeviceValues> device_values;
if (SUCCEEDED(device_values.CreateInstance(CLSID_PortableDeviceValues))) {
if (SUCCEEDED(device_values->SetUnsignedIntegerValue(
- SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, kPeriodInMilliseconds))) {
+ SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL,
+ GetInterval().InMilliseconds()))) {
base::win::ScopedComPtr<IPortableDeviceValues> return_values;
(*sensor)->SetProperties(device_values.get(), return_values.Receive());
}
diff --git a/chromium/content/browser/device_orientation/device_inertial_sensor_browsertest.cc b/chromium/content/browser/device_orientation/device_inertial_sensor_browsertest.cc
new file mode 100644
index 00000000000..86f20f46728
--- /dev/null
+++ b/chromium/content/browser/device_orientation/device_inertial_sensor_browsertest.cc
@@ -0,0 +1,186 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/synchronization/waitable_event.h"
+#include "content/browser/device_orientation/data_fetcher_shared_memory.h"
+#include "content/browser/device_orientation/device_inertial_sensor_service.h"
+#include "content/common/device_orientation/device_motion_hardware_buffer.h"
+#include "content/common/device_orientation/device_orientation_hardware_buffer.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
+
+namespace content {
+
+namespace {
+
+class FakeDataFetcher : public DataFetcherSharedMemory {
+ public:
+ FakeDataFetcher()
+ : started_orientation_(false, false),
+ stopped_orientation_(false, false),
+ started_motion_(false, false),
+ stopped_motion_(false, false) {
+ }
+ virtual ~FakeDataFetcher() { }
+
+ virtual bool Start(ConsumerType consumer_type, void* buffer) OVERRIDE {
+ EXPECT_TRUE(buffer);
+
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ UpdateMotion(static_cast<DeviceMotionHardwareBuffer*>(buffer));
+ started_motion_.Signal();
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ UpdateOrientation(
+ static_cast<DeviceOrientationHardwareBuffer*>(buffer));
+ started_orientation_.Signal();
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ virtual bool Stop(ConsumerType consumer_type) OVERRIDE {
+ switch (consumer_type) {
+ case CONSUMER_TYPE_MOTION:
+ stopped_motion_.Signal();
+ break;
+ case CONSUMER_TYPE_ORIENTATION:
+ stopped_orientation_.Signal();
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ virtual void Fetch(unsigned consumer_bitmask) OVERRIDE {
+ FAIL() << "fetch should not be called";
+ }
+
+ virtual FetcherType GetType() const OVERRIDE {
+ return FETCHER_TYPE_DEFAULT;
+ }
+
+ void UpdateMotion(DeviceMotionHardwareBuffer* buffer) {
+ buffer->seqlock.WriteBegin();
+ buffer->data.accelerationX = 1;
+ buffer->data.hasAccelerationX = true;
+ buffer->data.accelerationY = 2;
+ buffer->data.hasAccelerationY = true;
+ buffer->data.accelerationZ = 3;
+ buffer->data.hasAccelerationZ = true;
+
+ buffer->data.accelerationIncludingGravityX = 4;
+ buffer->data.hasAccelerationIncludingGravityX = true;
+ buffer->data.accelerationIncludingGravityY = 5;
+ buffer->data.hasAccelerationIncludingGravityY = true;
+ buffer->data.accelerationIncludingGravityZ = 6;
+ buffer->data.hasAccelerationIncludingGravityZ = true;
+
+ buffer->data.rotationRateAlpha = 7;
+ buffer->data.hasRotationRateAlpha = true;
+ buffer->data.rotationRateBeta = 8;
+ buffer->data.hasRotationRateBeta = true;
+ buffer->data.rotationRateGamma = 9;
+ buffer->data.hasRotationRateGamma = true;
+
+ buffer->data.interval = 100;
+ buffer->data.allAvailableSensorsAreActive = true;
+ buffer->seqlock.WriteEnd();
+ }
+
+ void UpdateOrientation(DeviceOrientationHardwareBuffer* buffer) {
+ buffer->seqlock.WriteBegin();
+ buffer->data.alpha = 1;
+ buffer->data.hasAlpha = true;
+ buffer->data.beta = 2;
+ buffer->data.hasBeta = true;
+ buffer->data.gamma = 3;
+ buffer->data.hasGamma = true;
+ buffer->data.allAvailableSensorsAreActive = true;
+ buffer->seqlock.WriteEnd();
+ }
+
+ base::WaitableEvent started_orientation_;
+ base::WaitableEvent stopped_orientation_;
+ base::WaitableEvent started_motion_;
+ base::WaitableEvent stopped_motion_;
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(FakeDataFetcher);
+};
+
+
+class DeviceInertialSensorBrowserTest : public ContentBrowserTest {
+ public:
+ DeviceInertialSensorBrowserTest()
+ : fetcher_(NULL),
+ io_loop_finished_event_(false, false) {
+ }
+
+ // From ContentBrowserTest.
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ EXPECT_TRUE(!command_line->HasSwitch(switches::kDisableDeviceOrientation));
+ EXPECT_TRUE(!command_line->HasSwitch(switches::kDisableDeviceMotion));
+ }
+
+ virtual void SetUpOnMainThread() OVERRIDE {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&DeviceInertialSensorBrowserTest::SetUpOnIOThread, this));
+ io_loop_finished_event_.Wait();
+ }
+
+ void SetUpOnIOThread() {
+ fetcher_ = new FakeDataFetcher();
+ DeviceInertialSensorService::GetInstance()->
+ SetDataFetcherForTests(fetcher_);
+ io_loop_finished_event_.Signal();
+ }
+
+ FakeDataFetcher* fetcher_;
+
+ private:
+ base::WaitableEvent io_loop_finished_event_;
+};
+
+
+IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, OrientationTest) {
+ // The test page will register an event handler for orientation events,
+ // expects to get an event with fake values, then removes the event
+ // handler and navigates to #pass.
+ GURL test_url = GetTestUrl(
+ "device_orientation", "device_orientation_test.html");
+ NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
+
+ EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
+ fetcher_->started_orientation_.Wait();
+ fetcher_->stopped_orientation_.Wait();
+}
+
+IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, MotionTest) {
+ // The test page will register an event handler for motion events,
+ // expects to get an event with fake values, then removes the event
+ // handler and navigates to #pass.
+ GURL test_url = GetTestUrl(
+ "device_orientation", "device_motion_test.html");
+ NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
+
+ EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
+ fetcher_->started_motion_.Wait();
+ fetcher_->stopped_motion_.Wait();
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/device_orientation/device_inertial_sensor_service.cc b/chromium/content/browser/device_orientation/device_inertial_sensor_service.cc
index ee90be16668..cb8bbf300b2 100644
--- a/chromium/content/browser/device_orientation/device_inertial_sensor_service.cc
+++ b/chromium/content/browser/device_orientation/device_inertial_sensor_service.cc
@@ -91,4 +91,9 @@ void DeviceInertialSensorService::Shutdown() {
is_shutdown_ = true;
}
+void DeviceInertialSensorService::SetDataFetcherForTests(
+ DataFetcherSharedMemory* test_data_fetcher) {
+ data_fetcher_.reset(test_data_fetcher);
+}
+
} // namespace content
diff --git a/chromium/content/browser/device_orientation/device_inertial_sensor_service.h b/chromium/content/browser/device_orientation/device_inertial_sensor_service.h
index 028d15568ad..1c7c162f23f 100644
--- a/chromium/content/browser/device_orientation/device_inertial_sensor_service.h
+++ b/chromium/content/browser/device_orientation/device_inertial_sensor_service.h
@@ -44,6 +44,10 @@ class CONTENT_EXPORT DeviceInertialSensorService {
// Stop/join with the background polling thread in |provider_|.
void Shutdown();
+ // Injects a custom data fetcher for testing purposes. This class takes
+ // ownership of the injected object.
+ void SetDataFetcherForTests(DataFetcherSharedMemory* test_data_fetcher);
+
private:
friend struct DefaultSingletonTraits<DeviceInertialSensorService>;
diff --git a/chromium/content/browser/device_orientation/device_orientation_browsertest.cc b/chromium/content/browser/device_orientation/device_orientation_browsertest.cc
deleted file mode 100644
index 92a83c70e0c..00000000000
--- a/chromium/content/browser/device_orientation/device_orientation_browsertest.cc
+++ /dev/null
@@ -1,79 +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/command_line.h"
-#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/device_orientation/device_data.h"
-#include "content/browser/device_orientation/orientation.h"
-#include "content/browser/device_orientation/provider.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_switches.h"
-#include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
-
-namespace content {
-
-class MockProvider : public Provider {
- public:
- MockProvider(const DeviceData* device_data, DeviceData::Type type)
- : device_data_(device_data),
- device_data_type_(type),
- added_observer_(false),
- removed_observer_(false) {
- }
-
- virtual void AddObserver(Observer* observer) OVERRIDE {
- added_observer_ = true;
- observer->OnDeviceDataUpdate(device_data_.get(), device_data_type_);
- }
- virtual void RemoveObserver(Observer* observer) OVERRIDE {
- removed_observer_ = true;
- }
-
- scoped_refptr<const DeviceData> device_data_;
- DeviceData::Type device_data_type_;
- bool added_observer_;
- bool removed_observer_;
-
- private:
- virtual ~MockProvider() {}
-};
-
-class DeviceOrientationBrowserTest : public ContentBrowserTest {
- public:
- // From ContentBrowserTest.
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- EXPECT_TRUE(!command_line->HasSwitch(switches::kDisableDeviceOrientation));
- }
-};
-
-// crbug.com/113952
-IN_PROC_BROWSER_TEST_F(DeviceOrientationBrowserTest, BasicTest) {
- scoped_refptr<Orientation> test_orientation(new Orientation());
- test_orientation->set_alpha(1);
- test_orientation->set_beta(2);
- test_orientation->set_gamma(3);
- test_orientation->set_absolute(true);
- scoped_refptr<MockProvider> provider(
- new MockProvider(test_orientation.get(), DeviceData::kTypeOrientation));
- Provider::SetInstanceForTests(provider.get());
-
- // The test page will register an event handler for orientation events,
- // expects to get an event with kTestOrientation orientation,
- // then removes the event handler and navigates to #pass.
- GURL test_url = GetTestUrl(
- "device_orientation", "device_orientation_test.html");
- NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
-
- // Check that the page got the event it expected and that the provider
- // saw requests for adding and removing an observer.
- EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
- EXPECT_TRUE(provider->added_observer_);
- EXPECT_TRUE(provider->removed_observer_);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/inertial_sensor_consts.h b/chromium/content/browser/device_orientation/inertial_sensor_consts.h
index 312b18b1066..6a37fc82a4e 100644
--- a/chromium/content/browser/device_orientation/inertial_sensor_consts.h
+++ b/chromium/content/browser/device_orientation/inertial_sensor_consts.h
@@ -14,6 +14,12 @@ enum ConsumerType {
CONSUMER_TYPE_ORIENTATION = 1 << 1,
};
+// Specifies the minimal interval between subsequent sensor data updates.
+// Note that when changing this value it is desirable to have an adequate
+// matching value |DeviceSensorEventPump::kDefaultPumpDelayMillis| in
+// content/renderer/device_orientation/device_sensor_event_pump.cc.
+const int kInertialSensorIntervalMillis = 50;
+
} // namespace content
#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_INERTIAL_SENSOR_CONSTS_H_
diff --git a/chromium/content/browser/device_orientation/message_filter.cc b/chromium/content/browser/device_orientation/message_filter.cc
deleted file mode 100644
index b20071daeed..00000000000
--- a/chromium/content/browser/device_orientation/message_filter.cc
+++ /dev/null
@@ -1,38 +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/device_orientation/message_filter.h"
-
-#include "content/browser/device_orientation/observer_delegate.h"
-#include "content/browser/device_orientation/provider.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-
-DeviceOrientationMessageFilterOld::DeviceOrientationMessageFilterOld(
- DeviceData::Type device_data_type)
- : provider_(NULL),
- device_data_type_(device_data_type) {
-}
-
-DeviceOrientationMessageFilterOld::~DeviceOrientationMessageFilterOld() {
-}
-
-void DeviceOrientationMessageFilterOld::OnStartUpdating(int render_view_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- if (!provider_.get())
- provider_ = Provider::GetInstance();
-
- observers_map_[render_view_id] = new ObserverDelegate(
- device_data_type_, provider_.get(), render_view_id, this);
-}
-
-void DeviceOrientationMessageFilterOld::OnStopUpdating(int render_view_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- observers_map_.erase(render_view_id);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/message_filter.h b/chromium/content/browser/device_orientation/message_filter.h
deleted file mode 100644
index c5dce140124..00000000000
--- a/chromium/content/browser/device_orientation/message_filter.h
+++ /dev/null
@@ -1,44 +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_DEVICE_ORIENTATION_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_DEVICE_ORIENTATION_MESSAGE_FILTER_H_
-
-#include <map>
-
-#include "content/browser/device_orientation/device_data.h"
-#include "content/public/browser/browser_message_filter.h"
-
-namespace content {
-
-// Helper class that observes a Provider and forwards updates to a RenderView.
-class ObserverDelegate;
-
-class Provider;
-
-class DeviceOrientationMessageFilterOld : public BrowserMessageFilter {
- public:
- // BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message,
- bool* message_was_ok) OVERRIDE = 0;
-
- protected:
- DeviceOrientationMessageFilterOld(DeviceData::Type device_data_type);
- virtual ~DeviceOrientationMessageFilterOld();
-
- void OnStartUpdating(int render_view_id);
- void OnStopUpdating(int render_view_id);
-
- private:
-
- // map from render_view_id to ObserverDelegate.
- std::map<int, scoped_refptr<ObserverDelegate> > observers_map_;
-
- scoped_refptr<Provider> provider_;
- DeviceData::Type device_data_type_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/device_orientation/observer_delegate.cc b/chromium/content/browser/device_orientation/observer_delegate.cc
deleted file mode 100644
index 5c233109dd7..00000000000
--- a/chromium/content/browser/device_orientation/observer_delegate.cc
+++ /dev/null
@@ -1,49 +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/device_orientation/observer_delegate.h"
-
-#include "base/logging.h"
-#include "content/browser/device_orientation/device_data.h"
-#include "content/browser/device_orientation/orientation.h"
-#include "ipc/ipc_sender.h"
-
-namespace content {
-
-ObserverDelegate::ObserverDelegate(DeviceData::Type device_data_type,
- Provider* provider, int render_view_id,
- IPC::Sender* sender)
- : Observer(device_data_type),
- provider_(provider),
- render_view_id_(render_view_id),
- sender_(sender) {
- provider_->AddObserver(this);
-}
-
-ObserverDelegate::~ObserverDelegate() {
- provider_->RemoveObserver(this);
-}
-
-void ObserverDelegate::OnDeviceDataUpdate(
- const DeviceData* device_data, DeviceData::Type device_data_type) {
- scoped_refptr<const DeviceData> new_device_data(device_data);
- if (!new_device_data.get())
- new_device_data = EmptyDeviceData(device_data_type);
-
- sender_->Send(new_device_data->CreateIPCMessage(render_view_id_));
-}
-
-DeviceData* ObserverDelegate::EmptyDeviceData(DeviceData::Type type) {
- switch (type) {
- case DeviceData::kTypeOrientation:
- return new Orientation();
- case DeviceData::kTypeMotion:
- case DeviceData::kTypeTest:
- NOTREACHED();
- }
- NOTREACHED();
- return NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/observer_delegate.h b/chromium/content/browser/device_orientation/observer_delegate.h
deleted file mode 100644
index 8c7dab84b08..00000000000
--- a/chromium/content/browser/device_orientation/observer_delegate.h
+++ /dev/null
@@ -1,45 +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_DEVICE_ORIENTATION_OBSERVER_DELEGATE_H_
-#define CONTENT_BROWSER_DEVICE_ORIENTATION_OBSERVER_DELEGATE_H_
-
-#include "content/browser/device_orientation/device_data.h"
-#include "content/browser/device_orientation/provider.h"
-
-namespace IPC {
-class Sender;
-}
-
-namespace content {
-
-class ObserverDelegate
- : public base::RefCounted<ObserverDelegate>, public Provider::Observer {
- public:
- // Create ObserverDelegate that observes provider and forwards updates to
- // render_view_id.
- // Will stop observing provider when destructed.
- ObserverDelegate(DeviceData::Type device_data_type, Provider* provider,
- int render_view_id, IPC::Sender* sender);
-
- // From Provider::Observer.
- virtual void OnDeviceDataUpdate(const DeviceData* device_data,
- DeviceData::Type device_data_type) OVERRIDE;
-
- private:
- static DeviceData* EmptyDeviceData(DeviceData::Type type);
-
- friend class base::RefCounted<ObserverDelegate>;
- virtual ~ObserverDelegate();
-
- scoped_refptr<Provider> provider_;
- int render_view_id_;
- IPC::Sender* sender_; // Weak pointer.
-
- DISALLOW_COPY_AND_ASSIGN(ObserverDelegate);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_OBSERVER_DELEGATE_H_
diff --git a/chromium/content/browser/device_orientation/orientation.cc b/chromium/content/browser/device_orientation/orientation.cc
deleted file mode 100644
index b0b463fcad0..00000000000
--- a/chromium/content/browser/device_orientation/orientation.cc
+++ /dev/null
@@ -1,70 +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/device_orientation/orientation.h"
-
-#include <cmath>
-
-#include "content/common/device_orientation/device_orientation_messages.h"
-
-namespace content {
-
-Orientation::Orientation()
- : can_provide_alpha_(false),
- can_provide_beta_(false),
- can_provide_gamma_(false),
- can_provide_absolute_(false) {
-}
-
-Orientation::~Orientation() {
-}
-
-IPC::Message* Orientation::CreateIPCMessage(int render_view_id) const {
- DeviceOrientationMsg_Updated_Params params;
- params.can_provide_alpha = can_provide_alpha_;
- params.alpha = alpha_;
- params.can_provide_beta = can_provide_beta_;
- params.beta = beta_;
- params.can_provide_gamma = can_provide_gamma_;
- params.gamma = gamma_;
- params.can_provide_absolute = can_provide_absolute_;
- params.absolute = absolute_;
-
- return new DeviceOrientationMsg_Updated(render_view_id, params);
-}
-
-// Returns true if two orientations are considered different enough that
-// observers should be notified of the new orientation.
-bool Orientation::ShouldFireEvent(const DeviceData* old_data) const {
- scoped_refptr<const Orientation> old_orientation(
- static_cast<const Orientation*>(old_data));
-
- return IsElementSignificantlyDifferent(can_provide_alpha_,
- old_orientation->can_provide_alpha(),
- alpha_,
- old_orientation->alpha()) ||
- IsElementSignificantlyDifferent(can_provide_beta_,
- old_orientation->can_provide_beta(),
- beta_,
- old_orientation->beta()) ||
- IsElementSignificantlyDifferent(can_provide_gamma_,
- old_orientation->can_provide_gamma(),
- gamma_,
- old_orientation->gamma()) ||
- can_provide_absolute_ != old_orientation->can_provide_absolute() ||
- absolute_ != old_orientation->absolute();
-}
-
-bool Orientation::IsElementSignificantlyDifferent(bool can_provide_element1,
- bool can_provide_element2, double element1, double element2) {
- const double kThreshold = 0.1;
-
- if (can_provide_element1 != can_provide_element2)
- return true;
- if (can_provide_element1 && std::fabs(element1 - element2) >= kThreshold)
- return true;
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/orientation.h b/chromium/content/browser/device_orientation/orientation.h
deleted file mode 100644
index b3ebd27c6e0..00000000000
--- a/chromium/content/browser/device_orientation/orientation.h
+++ /dev/null
@@ -1,73 +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_DEVICE_ORIENTATION_ORIENTATION_H_
-#define CONTENT_BROWSER_DEVICE_ORIENTATION_ORIENTATION_H_
-
-#include "base/compiler_specific.h"
-#include "content/browser/device_orientation/device_data.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class Orientation : public DeviceData {
- public:
- // alpha, beta, gamma and absolute are the rotations around the axes as
- // specified in http://dev.w3.org/geo/api/spec-source-orientation.html
- //
- // can_provide_{alpha,beta,gamma,absolute} is true if data can be provided
- // for that variable.
- CONTENT_EXPORT Orientation();
-
- // From DeviceData.
- virtual IPC::Message* CreateIPCMessage(int render_view_id) const OVERRIDE;
- virtual bool ShouldFireEvent(const DeviceData* old_data) const OVERRIDE;
-
- void set_alpha(double alpha) {
- can_provide_alpha_ = true;
- alpha_ = alpha;
- }
- bool can_provide_alpha() const { return can_provide_alpha_; }
- double alpha() const { return alpha_; }
-
- void set_beta(double beta) {
- can_provide_beta_ = true;
- beta_ = beta;
- }
- bool can_provide_beta() const { return can_provide_beta_; }
- double beta() const { return beta_; }
-
- void set_gamma(double gamma) {
- can_provide_gamma_ = true;
- gamma_ = gamma;
- }
- bool can_provide_gamma() const { return can_provide_gamma_; }
- double gamma() const { return gamma_; }
-
- void set_absolute(bool absolute) {
- can_provide_absolute_ = true;
- absolute_ = absolute;
- }
- bool can_provide_absolute() const { return can_provide_absolute_; }
- bool absolute() const { return absolute_; }
-
- private:
- virtual ~Orientation();
-
- static bool IsElementSignificantlyDifferent(bool can_provide_element1,
- bool can_provide_element2, double element1, double element2);
-
- double alpha_;
- double beta_;
- double gamma_;
- bool absolute_;
- bool can_provide_alpha_;
- bool can_provide_beta_;
- bool can_provide_gamma_;
- bool can_provide_absolute_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_ORIENTATION_H_
diff --git a/chromium/content/browser/device_orientation/orientation_message_filter.cc b/chromium/content/browser/device_orientation/orientation_message_filter.cc
deleted file mode 100644
index b7cde576981..00000000000
--- a/chromium/content/browser/device_orientation/orientation_message_filter.cc
+++ /dev/null
@@ -1,32 +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/device_orientation/orientation_message_filter.h"
-
-#include "content/browser/device_orientation/device_data.h"
-#include "content/common/device_orientation/device_orientation_messages.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-
-OrientationMessageFilter::OrientationMessageFilter()
- : DeviceOrientationMessageFilterOld(DeviceData::kTypeOrientation) {
-}
-
-OrientationMessageFilter::~OrientationMessageFilter() {
-}
-
-bool OrientationMessageFilter::OnMessageReceived(const IPC::Message& message,
- bool* message_was_ok) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP_EX(OrientationMessageFilter, message, *message_was_ok)
- IPC_MESSAGE_HANDLER(DeviceOrientationHostMsg_StartUpdating, OnStartUpdating)
- IPC_MESSAGE_HANDLER(DeviceOrientationHostMsg_StopUpdating, OnStopUpdating)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/orientation_message_filter.h b/chromium/content/browser/device_orientation/orientation_message_filter.h
deleted file mode 100644
index 80181d52a9f..00000000000
--- a/chromium/content/browser/device_orientation/orientation_message_filter.h
+++ /dev/null
@@ -1,30 +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_DEVICE_ORIENTATION_ORIENTATION_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_DEVICE_ORIENTATION_ORIENTATION_MESSAGE_FILTER_H_
-
-#include <map>
-
-#include "content/browser/device_orientation/message_filter.h"
-
-namespace content {
-
-class OrientationMessageFilter : public DeviceOrientationMessageFilterOld {
- public:
- OrientationMessageFilter();
-
- // DeviceOrientationMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message,
- bool* message_was_ok) OVERRIDE;
-
- private:
- virtual ~OrientationMessageFilter();
-
- DISALLOW_COPY_AND_ASSIGN(OrientationMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_ORIENTATION_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/device_orientation/provider.cc b/chromium/content/browser/device_orientation/provider.cc
deleted file mode 100644
index 49fc4f2164f..00000000000
--- a/chromium/content/browser/device_orientation/provider.cc
+++ /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.
-
-#include "content/browser/device_orientation/provider.h"
-
-#include "base/logging.h"
-#include "content/browser/device_orientation/data_fetcher.h"
-#include "content/browser/device_orientation/provider_impl.h"
-#include "content/public/browser/browser_thread.h"
-
-#if defined(OS_MACOSX)
-#include "content/browser/device_orientation/accelerometer_mac.h"
-#elif defined(OS_ANDROID)
-#include "content/browser/device_orientation/data_fetcher_orientation_android.h"
-#elif defined(OS_WIN)
-#include "content/browser/device_orientation/data_fetcher_impl_win.h"
-#endif
-
-namespace content {
-
-Provider* Provider::GetInstance() {
- if (!instance_) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ProviderImpl::DataFetcherFactory default_factory = NULL;
-
-#if defined(OS_MACOSX)
- default_factory = AccelerometerMac::Create;
-#elif defined(OS_ANDROID)
- default_factory = DataFetcherOrientationAndroid::Create;
-#elif defined(OS_WIN)
- default_factory = DataFetcherImplWin::Create;
-#endif
-
- instance_ = new ProviderImpl(default_factory);
- }
- return instance_;
-}
-
-void Provider::SetInstanceForTests(Provider* provider) {
- DCHECK(!instance_);
- instance_ = provider;
-}
-
-Provider* Provider::GetInstanceForTests() {
- return instance_;
-}
-
-Provider::Provider() {
-}
-
-Provider::~Provider() {
- DCHECK(instance_ == this);
- instance_ = NULL;
-}
-
-Provider* Provider::instance_ = NULL;
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/provider.h b/chromium/content/browser/device_orientation/provider.h
deleted file mode 100644
index 4bc0635fda6..00000000000
--- a/chromium/content/browser/device_orientation/provider.h
+++ /dev/null
@@ -1,67 +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_DEVICE_ORIENTATION_PROVIDER_H_
-#define CONTENT_BROWSER_DEVICE_ORIENTATION_PROVIDER_H_
-
-#include "base/memory/ref_counted.h"
-#include "content/browser/device_orientation/device_data.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class CONTENT_EXPORT Provider : public base::RefCountedThreadSafe<Provider> {
- public:
- class Observer {
- public:
- // Called when device data changes.
- // An Observer must not synchronously call Provider::RemoveObserver
- // or Provider::AddObserver when this is called.
- virtual void OnDeviceDataUpdate(const DeviceData* device_data,
- DeviceData::Type device_data_type) = 0;
- DeviceData::Type device_data_type() { return device_data_type_; }
-
- protected:
- Observer(DeviceData::Type device_data_type)
- : device_data_type_(device_data_type) {
- }
- virtual ~Observer() {}
-
- private:
- // Each Observer observes exactly one type of DeviceData.
- DeviceData::Type device_data_type_;
- };
-
- // Returns a pointer to the singleton instance of this class.
- // The caller should store the returned pointer in a scoped_refptr.
- // The Provider instance is lazily constructed when GetInstance() is called,
- // and destructed when the last scoped_refptr referring to it is destructed.
- static Provider* GetInstance();
-
- // Inject a mock Provider for testing. Only a weak pointer to the injected
- // object will be held by Provider, i.e. it does not itself contribute to the
- // injected object's reference count.
- static void SetInstanceForTests(Provider* provider);
-
- // Get the current instance. Used for testing.
- static Provider* GetInstanceForTests();
-
- // Note: AddObserver may call back synchronously to the observer with data.
- virtual void AddObserver(Observer* observer) = 0;
- virtual void RemoveObserver(Observer* observer) = 0;
-
- protected:
- Provider();
- virtual ~Provider();
-
- private:
- friend class base::RefCountedThreadSafe<Provider>;
- static Provider* instance_;
-
- DISALLOW_COPY_AND_ASSIGN(Provider);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_PROVIDER_H_
diff --git a/chromium/content/browser/device_orientation/provider_impl.cc b/chromium/content/browser/device_orientation/provider_impl.cc
deleted file mode 100644
index 6cc63212cc4..00000000000
--- a/chromium/content/browser/device_orientation/provider_impl.cc
+++ /dev/null
@@ -1,292 +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/device_orientation/provider_impl.h"
-
-#include <set>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/threading/thread.h"
-#include "base/threading/worker_pool.h"
-
-namespace {
-
-void DeleteThread(base::Thread* thread) {
- delete thread;
-}
-
-}
-
-namespace content {
-
-class ProviderImpl::PollingThread : public base::Thread {
- public:
- PollingThread(const char* name,
- base::WeakPtr<ProviderImpl> provider,
- base::MessageLoop* creator_loop);
- virtual ~PollingThread();
-
- // Method for creating a DataFetcher and starting the polling, if the fetcher
- // can provide this type of data.
- void Initialize(DataFetcherFactory factory, DeviceData::Type type);
-
- // Method for adding a type of data to poll for.
- void DoAddPollingDataType(DeviceData::Type type);
-
- private:
- // Method for polling a DataFetcher.
- void DoPoll();
- void ScheduleDoPoll();
-
- // Schedule a notification to the |provider_| which lives on a different
- // thread (|creator_loop_| is its message loop).
- void ScheduleDoNotify(const scoped_refptr<const DeviceData>& device_data,
- DeviceData::Type device_data_type);
-
- enum { kDesiredSamplingIntervalMs = 100 };
- base::TimeDelta SamplingInterval() const;
-
- // The Message Loop on which this object was created.
- // Typically the I/O loop, but may be something else during testing.
- base::MessageLoop* creator_loop_;
-
- scoped_ptr<DataFetcher> data_fetcher_;
- std::map<DeviceData::Type, scoped_refptr<const DeviceData> >
- last_device_data_map_;
- std::set<DeviceData::Type> polling_data_types_;
-
- base::WeakPtr<ProviderImpl> provider_;
-};
-
-ProviderImpl::PollingThread::PollingThread(const char* name,
- base::WeakPtr<ProviderImpl> provider,
- base::MessageLoop* creator_loop)
- : base::Thread(name), creator_loop_(creator_loop), provider_(provider) {}
-
-ProviderImpl::PollingThread::~PollingThread() {
- Stop();
-}
-
-void ProviderImpl::PollingThread::DoAddPollingDataType(DeviceData::Type type) {
- DCHECK(base::MessageLoop::current() == message_loop());
-
- polling_data_types_.insert(type);
-}
-
-void ProviderImpl::PollingThread::Initialize(DataFetcherFactory factory,
- DeviceData::Type type) {
- DCHECK(base::MessageLoop::current() == message_loop());
-
- if (factory != NULL) {
- // Try to use factory to create a fetcher that can provide this type of
- // data. If factory creates a fetcher that provides this type of data,
- // start polling.
- scoped_ptr<DataFetcher> fetcher(factory());
-
- if (fetcher) {
- scoped_refptr<const DeviceData> device_data(fetcher->GetDeviceData(type));
- if (device_data.get() != NULL) {
- // Pass ownership of fetcher to provider_.
- data_fetcher_.swap(fetcher);
- last_device_data_map_[type] = device_data;
-
- // Notify observers.
- ScheduleDoNotify(device_data, type);
-
- // Start polling.
- ScheduleDoPoll();
- return;
- }
- }
- }
-
- // When no device data can be provided.
- ScheduleDoNotify(NULL, type);
-}
-
-void ProviderImpl::PollingThread::ScheduleDoNotify(
- const scoped_refptr<const DeviceData>& device_data,
- DeviceData::Type device_data_type) {
- DCHECK(base::MessageLoop::current() == message_loop());
-
- creator_loop_->PostTask(FROM_HERE,
- base::Bind(&ProviderImpl::DoNotify, provider_,
- device_data, device_data_type));
-}
-
-void ProviderImpl::PollingThread::DoPoll() {
- DCHECK(base::MessageLoop::current() == message_loop());
-
- // Poll the fetcher for each type of data.
- typedef std::set<DeviceData::Type>::const_iterator SetIterator;
- for (SetIterator i = polling_data_types_.begin();
- i != polling_data_types_.end(); ++i) {
- DeviceData::Type device_data_type = *i;
- scoped_refptr<const DeviceData> device_data(data_fetcher_->GetDeviceData(
- device_data_type));
-
- if (device_data.get() == NULL) {
- LOG(ERROR) << "Failed to poll device data fetcher.";
- ScheduleDoNotify(NULL, device_data_type);
- continue;
- }
-
- const DeviceData* old_data = last_device_data_map_[device_data_type].get();
- if (old_data != NULL && !device_data->ShouldFireEvent(old_data))
- continue;
-
- // Update the last device data of this type and notify observers.
- last_device_data_map_[device_data_type] = device_data;
- ScheduleDoNotify(device_data, device_data_type);
- }
-
- ScheduleDoPoll();
-}
-
-void ProviderImpl::PollingThread::ScheduleDoPoll() {
- DCHECK(base::MessageLoop::current() == message_loop());
-
- message_loop()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&PollingThread::DoPoll, base::Unretained(this)),
- SamplingInterval());
-}
-
-base::TimeDelta ProviderImpl::PollingThread::SamplingInterval() const {
- DCHECK(base::MessageLoop::current() == message_loop());
- DCHECK(data_fetcher_.get());
-
- // TODO(erg): There used to be unused code here, that called a default
- // implementation on the DataFetcherInterface that was never defined. I'm
- // removing unused methods from headers.
- return base::TimeDelta::FromMilliseconds(kDesiredSamplingIntervalMs);
-}
-
-ProviderImpl::ProviderImpl(DataFetcherFactory factory)
- : creator_loop_(base::MessageLoop::current()),
- factory_(factory),
- weak_factory_(this),
- polling_thread_(NULL) {
-}
-
-ProviderImpl::~ProviderImpl() {
- Stop();
-}
-
-void ProviderImpl::ScheduleDoAddPollingDataType(DeviceData::Type type) {
- DCHECK(base::MessageLoop::current() == creator_loop_);
-
- base::MessageLoop* polling_loop = polling_thread_->message_loop();
- polling_loop->PostTask(FROM_HERE,
- base::Bind(&PollingThread::DoAddPollingDataType,
- base::Unretained(polling_thread_),
- type));
-}
-
-void ProviderImpl::AddObserver(Observer* observer) {
- DCHECK(base::MessageLoop::current() == creator_loop_);
-
- DeviceData::Type type = observer->device_data_type();
-
- observers_.insert(observer);
- if (observers_.size() == 1)
- Start(type);
- else {
- // Notify observer of most recent notification if one exists.
- const DeviceData* last_notification = last_notifications_map_[type].get();
- if (last_notification != NULL)
- observer->OnDeviceDataUpdate(last_notification, type);
- }
-
- ScheduleDoAddPollingDataType(type);
-}
-
-void ProviderImpl::RemoveObserver(Observer* observer) {
- DCHECK(base::MessageLoop::current() == creator_loop_);
-
- observers_.erase(observer);
- if (observers_.empty())
- Stop();
-}
-
-void ProviderImpl::Start(DeviceData::Type type) {
- DCHECK(base::MessageLoop::current() == creator_loop_);
- DCHECK(!polling_thread_);
-
- polling_thread_ = new PollingThread("Device data polling thread",
- weak_factory_.GetWeakPtr(),
- creator_loop_);
-#if defined(OS_WIN)
- polling_thread_->init_com_with_mta(true);
-#endif
- if (!polling_thread_->Start()) {
- LOG(ERROR) << "Failed to start device data polling thread";
- delete polling_thread_;
- polling_thread_ = NULL;
- return;
- }
- ScheduleInitializePollingThread(type);
-}
-
-void ProviderImpl::Stop() {
- DCHECK(base::MessageLoop::current() == creator_loop_);
-
- weak_factory_.InvalidateWeakPtrs();
- if (polling_thread_) {
- polling_thread_->StopSoon();
- bool posted = base::WorkerPool::PostTask(
- FROM_HERE,
- base::Bind(&DeleteThread, base::Unretained(polling_thread_)),
- true /* task is slow */);
- DCHECK(posted);
- polling_thread_ = NULL;
- }
-}
-
-void ProviderImpl::ScheduleInitializePollingThread(
- DeviceData::Type device_data_type) {
- DCHECK(base::MessageLoop::current() == creator_loop_);
-
- base::MessageLoop* polling_loop = polling_thread_->message_loop();
- polling_loop->PostTask(FROM_HERE,
- base::Bind(&PollingThread::Initialize,
- base::Unretained(polling_thread_),
- factory_,
- device_data_type));
-}
-
-void ProviderImpl::DoNotify(const scoped_refptr<const DeviceData>& data,
- DeviceData::Type device_data_type) {
- DCHECK(base::MessageLoop::current() == creator_loop_);
-
- // Update last notification of this type.
- last_notifications_map_[device_data_type] = data;
-
- // Notify observers of this type of the new data.
- typedef std::set<Observer*>::const_iterator ConstIterator;
- for (ConstIterator i = observers_.begin(); i != observers_.end(); ++i) {
- if ((*i)->device_data_type() == device_data_type)
- (*i)->OnDeviceDataUpdate(data.get(), device_data_type);
- }
-
- if (data.get() == NULL) {
- // Notify observers exactly once about failure to provide data.
- typedef std::set<Observer*>::iterator Iterator;
- Iterator i = observers_.begin();
- while (i != observers_.end()) {
- Iterator current = i++;
- if ((*current)->device_data_type() == device_data_type)
- observers_.erase(current);
- }
-
- if (observers_.empty())
- Stop();
- }
-}
-
-
-} // namespace content
diff --git a/chromium/content/browser/device_orientation/provider_impl.h b/chromium/content/browser/device_orientation/provider_impl.h
deleted file mode 100644
index be7cf3b048d..00000000000
--- a/chromium/content/browser/device_orientation/provider_impl.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_DEVICE_ORIENTATION_PROVIDER_IMPL_H_
-#define CONTENT_BROWSER_DEVICE_ORIENTATION_PROVIDER_IMPL_H_
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/device_orientation/data_fetcher.h"
-#include "content/browser/device_orientation/device_data.h"
-#include "content/browser/device_orientation/provider.h"
-#include "content/common/content_export.h"
-
-namespace base {
-class MessageLoop;
-}
-
-namespace content {
-
-class ProviderImpl : public Provider {
- public:
- typedef DataFetcher* (*DataFetcherFactory)();
-
- // Create a ProviderImpl that uses the factory to create a DataFetcher that
- // can provide data. A NULL DataFetcherFactory indicates that there are no
- // DataFetchers for this OS.
- CONTENT_EXPORT ProviderImpl(DataFetcherFactory factory);
-
- // From Provider.
- virtual void AddObserver(Observer* observer) OVERRIDE;
- virtual void RemoveObserver(Observer* observer) OVERRIDE;
-
- private:
- class PollingThread;
-
- virtual ~ProviderImpl();
-
- // Starts or Stops the provider. Called from creator_loop_.
- void Start(DeviceData::Type type);
- void Stop();
-
- void ScheduleInitializePollingThread(DeviceData::Type device_data_type);
- void ScheduleDoAddPollingDataType(DeviceData::Type type);
-
- // Method for notifying observers of a data update.
- // Runs on the creator_thread_.
- void DoNotify(const scoped_refptr<const DeviceData>& data,
- DeviceData::Type device_data_type);
-
- static bool ShouldFireEvent(const DeviceData* old_data,
- const DeviceData* new_data, DeviceData::Type device_data_type);
-
- // The Message Loop on which this object was created.
- // Typically the I/O loop, but may be something else during testing.
- base::MessageLoop* creator_loop_;
-
- // Members below are only to be used from the creator_loop_.
- DataFetcherFactory factory_;
- std::set<Observer*> observers_;
- std::map<DeviceData::Type, scoped_refptr<const DeviceData> >
- last_notifications_map_;
-
- // When polling_thread_ is running, members below are only to be used
- // from that thread.
- base::WeakPtrFactory<ProviderImpl> weak_factory_;
-
- // Polling is done on this background thread. PollingThread is owned by
- // the ProviderImpl object. But its deletion doesn't happen synchronously
- // along with deletion of the ProviderImpl. Thus this should be a raw
- // pointer instead of scoped_ptr.
- PollingThread* polling_thread_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_ORIENTATION_PROVIDER_IMPL_H_
diff --git a/chromium/content/browser/device_orientation/provider_unittest.cc b/chromium/content/browser/device_orientation/provider_unittest.cc
deleted file mode 100644
index 1f310ea3ad4..00000000000
--- a/chromium/content/browser/device_orientation/provider_unittest.cc
+++ /dev/null
@@ -1,591 +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 <map>
-#include <queue>
-
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/lock.h"
-#include "content/browser/device_orientation/data_fetcher.h"
-#include "content/browser/device_orientation/device_data.h"
-#include "content/browser/device_orientation/orientation.h"
-#include "content/browser/device_orientation/provider.h"
-#include "content/browser/device_orientation/provider_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-namespace {
-
-// Class for testing multiple types of device data.
-class TestData : public DeviceData {
- public:
- TestData()
- : value_(0) {
- }
-
- // From DeviceData.
- virtual IPC::Message* CreateIPCMessage(int render_view_id) const OVERRIDE {
- NOTREACHED();
- return NULL;
- }
- virtual bool ShouldFireEvent(const DeviceData* old_data) const OVERRIDE {
- return true;
- }
-
- void set_value(double value) { value_ = value; }
- double value() const { return value_; }
-
- private:
- virtual ~TestData() { }
-
- double value_;
-};
-
-// Class for checking expectations on device_data updates from the Provider.
-class UpdateChecker : public Provider::Observer {
- public:
- UpdateChecker(DeviceData::Type device_data_type,
- int *expectations_count_ptr)
- : Observer(device_data_type),
- expectations_count_ptr_(expectations_count_ptr) {
- }
- virtual ~UpdateChecker() {}
-
- // From Provider::Observer.
- virtual void OnDeviceDataUpdate(const DeviceData* device_data,
- DeviceData::Type device_data_type) OVERRIDE = 0;
-
- void AddExpectation(const DeviceData* device_data) {
- scoped_refptr<const DeviceData> expected_device_data(device_data);
- expectations_queue_.push(expected_device_data);
- ++(*expectations_count_ptr_);
- }
-
- protected:
- // Set up by the test fixture, which then blocks while it is accessed
- // from OnDeviceDataUpdate which is executed on the test fixture's
- // message_loop_.
- int* expectations_count_ptr_;
- std::queue<scoped_refptr<const DeviceData> > expectations_queue_;
-};
-
-// Class for checking expectations on orientation updates from the Provider.
-class OrientationUpdateChecker : public UpdateChecker {
- public:
- explicit OrientationUpdateChecker(int* expectations_count_ptr)
- : UpdateChecker(DeviceData::kTypeOrientation, expectations_count_ptr) {
- }
-
- virtual ~OrientationUpdateChecker() {}
-
- // From UpdateChecker.
- virtual void OnDeviceDataUpdate(const DeviceData* device_data,
- DeviceData::Type device_data_type) OVERRIDE {
- ASSERT_FALSE(expectations_queue_.empty());
- ASSERT_EQ(DeviceData::kTypeOrientation, device_data_type);
-
- scoped_refptr<const Orientation> orientation(
- static_cast<const Orientation*>(device_data));
- if (orientation.get() == NULL)
- orientation = new Orientation();
-
- scoped_refptr<const Orientation> expected(static_cast<const Orientation*>(
- (expectations_queue_.front().get())));
- expectations_queue_.pop();
-
- EXPECT_EQ(expected->can_provide_alpha(), orientation->can_provide_alpha());
- EXPECT_EQ(expected->can_provide_beta(), orientation->can_provide_beta());
- EXPECT_EQ(expected->can_provide_gamma(), orientation->can_provide_gamma());
- EXPECT_EQ(expected->can_provide_absolute(),
- orientation->can_provide_absolute());
- if (expected->can_provide_alpha())
- EXPECT_EQ(expected->alpha(), orientation->alpha());
- if (expected->can_provide_beta())
- EXPECT_EQ(expected->beta(), orientation->beta());
- if (expected->can_provide_gamma())
- EXPECT_EQ(expected->gamma(), orientation->gamma());
- if (expected->can_provide_absolute())
- EXPECT_EQ(expected->absolute(), orientation->absolute());
-
- --(*expectations_count_ptr_);
-
- if (*expectations_count_ptr_ == 0) {
- base::MessageLoop::current()->PostTask(FROM_HERE,
- base::MessageLoop::QuitClosure());
- }
- }
-};
-
-// Class for checking expectations on test_data updates from the Provider.
-class TestDataUpdateChecker : public UpdateChecker {
- public:
- explicit TestDataUpdateChecker(int* expectations_count_ptr)
- : UpdateChecker(DeviceData::kTypeTest, expectations_count_ptr) {
- }
-
- // From UpdateChecker.
- virtual void OnDeviceDataUpdate(const DeviceData* device_data,
- DeviceData::Type device_data_type) OVERRIDE {
- ASSERT_FALSE(expectations_queue_.empty());
- ASSERT_EQ(DeviceData::kTypeTest, device_data_type);
-
- scoped_refptr<const TestData> test_data(
- static_cast<const TestData*>(device_data));
- if (test_data.get() == NULL)
- test_data = new TestData();
-
- scoped_refptr<const TestData> expected(static_cast<const TestData*>(
- (expectations_queue_.front().get())));
- expectations_queue_.pop();
-
- EXPECT_EQ(expected->value(), test_data->value());
-
- --(*expectations_count_ptr_);
-
- if (*expectations_count_ptr_ == 0) {
- base::MessageLoop::current()->PostTask(FROM_HERE,
- base::MessageLoop::QuitClosure());
- }
- }
-};
-
-// Class for injecting test device data into the Provider.
-class MockDeviceDataFactory
- : public base::RefCountedThreadSafe<MockDeviceDataFactory> {
- public:
- MockDeviceDataFactory()
- : is_failing_(false) {
- }
-
- static void SetCurInstance(MockDeviceDataFactory* instance) {
- if (instance) {
- EXPECT_FALSE(instance_);
- }
- else {
- EXPECT_TRUE(instance_);
- }
- instance_ = instance;
- }
-
- static DataFetcher* CreateDataFetcher() {
- EXPECT_TRUE(instance_);
- return new MockDataFetcher(instance_);
- }
-
- void SetDeviceData(const DeviceData* device_data, DeviceData::Type type) {
- base::AutoLock auto_lock(lock_);
- device_data_map_[type] = device_data;
- }
-
- void SetFailing(bool is_failing) {
- base::AutoLock auto_lock(lock_);
- is_failing_ = is_failing;
- }
-
- private:
- friend class base::RefCountedThreadSafe<MockDeviceDataFactory>;
-
- ~MockDeviceDataFactory() {
- }
-
- // Owned by ProviderImpl. Holds a reference back to MockDeviceDataFactory.
- class MockDataFetcher : public DataFetcher {
- public:
- explicit MockDataFetcher(MockDeviceDataFactory* device_data_factory)
- : device_data_factory_(device_data_factory) { }
-
- // From DataFetcher. Called by the Provider.
- virtual const DeviceData* GetDeviceData(
- DeviceData::Type device_data_type) OVERRIDE {
- base::AutoLock auto_lock(device_data_factory_->lock_);
- if (device_data_factory_->is_failing_)
- return NULL;
- return device_data_factory_->device_data_map_[device_data_type].get();
- }
-
- private:
- scoped_refptr<MockDeviceDataFactory> device_data_factory_;
- };
-
- static MockDeviceDataFactory* instance_;
- std::map<DeviceData::Type, scoped_refptr<const DeviceData> > device_data_map_;
- bool is_failing_;
- base::Lock lock_;
-};
-
-MockDeviceDataFactory* MockDeviceDataFactory::instance_;
-
-class DeviceOrientationProviderTest : public testing::Test {
- public:
- DeviceOrientationProviderTest()
- : pending_expectations_(0) {
- }
-
- virtual void TearDown() {
- provider_ = NULL;
-
- // Make sure it is really gone.
- EXPECT_FALSE(Provider::GetInstanceForTests());
-
- // Clean up in any case, so as to not break subsequent test.
- Provider::SetInstanceForTests(NULL);
- }
-
- // Initialize the test fixture with a ProviderImpl that uses the
- // DataFetcherFactory factory.
- void Init(ProviderImpl::DataFetcherFactory factory) {
- provider_ = new ProviderImpl(factory);
- Provider::SetInstanceForTests(provider_.get());
- }
-
- protected:
- // Number of pending expectations.
- int pending_expectations_;
-
- // Provider instance under test.
- scoped_refptr<Provider> provider_;
-
- // Message loop for the test thread.
- base::MessageLoop message_loop_;
-};
-
-TEST_F(DeviceOrientationProviderTest, FailingTest) {
- scoped_refptr<MockDeviceDataFactory> device_data_factory(
- new MockDeviceDataFactory());
- MockDeviceDataFactory::SetCurInstance(device_data_factory.get());
- Init(MockDeviceDataFactory::CreateDataFetcher);
-
- scoped_ptr<OrientationUpdateChecker> checker_a(
- new OrientationUpdateChecker(&pending_expectations_));
- scoped_ptr<OrientationUpdateChecker> checker_b(
- new OrientationUpdateChecker(&pending_expectations_));
-
- checker_a->AddExpectation(new Orientation());
- provider_->AddObserver(checker_a.get());
- base::MessageLoop::current()->Run();
-
- checker_b->AddExpectation(new Orientation());
- provider_->AddObserver(checker_b.get());
- base::MessageLoop::current()->Run();
-
- MockDeviceDataFactory::SetCurInstance(NULL);
-}
-
-TEST_F(DeviceOrientationProviderTest, ProviderIsSingleton) {
- scoped_refptr<MockDeviceDataFactory> device_data_factory(
- new MockDeviceDataFactory());
- MockDeviceDataFactory::SetCurInstance(device_data_factory.get());
- Init(MockDeviceDataFactory::CreateDataFetcher);
-
- scoped_refptr<Provider> provider_a(Provider::GetInstance());
- scoped_refptr<Provider> provider_b(Provider::GetInstance());
-
- EXPECT_EQ(provider_a.get(), provider_b.get());
- MockDeviceDataFactory::SetCurInstance(NULL);
-}
-
-TEST_F(DeviceOrientationProviderTest, BasicPushTest) {
- scoped_refptr<MockDeviceDataFactory> device_data_factory(
- new MockDeviceDataFactory());
- MockDeviceDataFactory::SetCurInstance(device_data_factory.get());
- Init(MockDeviceDataFactory::CreateDataFetcher);
- scoped_refptr<Orientation> test_orientation(new Orientation());
- test_orientation->set_alpha(1);
- test_orientation->set_beta(2);
- test_orientation->set_gamma(3);
- test_orientation->set_absolute(true);
-
- scoped_ptr<OrientationUpdateChecker> checker(
- new OrientationUpdateChecker(&pending_expectations_));
- checker->AddExpectation(test_orientation.get());
- device_data_factory->SetDeviceData(test_orientation.get(),
- DeviceData::kTypeOrientation);
- provider_->AddObserver(checker.get());
- base::MessageLoop::current()->Run();
-
- provider_->RemoveObserver(checker.get());
- MockDeviceDataFactory::SetCurInstance(NULL);
-}
-
-// Tests multiple observers observing the same type of data.
-TEST_F(DeviceOrientationProviderTest, MultipleObserversPushTest) {
- scoped_refptr<MockDeviceDataFactory> device_data_factory(
- new MockDeviceDataFactory());
- MockDeviceDataFactory::SetCurInstance(device_data_factory.get());
- Init(MockDeviceDataFactory::CreateDataFetcher);
-
- scoped_refptr<Orientation> test_orientations[] = {new Orientation(),
- new Orientation(), new Orientation()};
- test_orientations[0]->set_alpha(1);
- test_orientations[0]->set_beta(2);
- test_orientations[0]->set_gamma(3);
- test_orientations[0]->set_absolute(true);
-
- test_orientations[1]->set_alpha(4);
- test_orientations[1]->set_beta(5);
- test_orientations[1]->set_gamma(6);
- test_orientations[1]->set_absolute(false);
-
- test_orientations[2]->set_alpha(7);
- test_orientations[2]->set_beta(8);
- test_orientations[2]->set_gamma(9);
- // can't provide absolute
-
- scoped_ptr<OrientationUpdateChecker> checker_a(
- new OrientationUpdateChecker(&pending_expectations_));
- scoped_ptr<OrientationUpdateChecker> checker_b(
- new OrientationUpdateChecker(&pending_expectations_));
- scoped_ptr<OrientationUpdateChecker> checker_c(
- new OrientationUpdateChecker(&pending_expectations_));
-
- checker_a->AddExpectation(test_orientations[0].get());
- device_data_factory->SetDeviceData(test_orientations[0].get(),
- DeviceData::kTypeOrientation);
- provider_->AddObserver(checker_a.get());
- base::MessageLoop::current()->Run();
-
- checker_a->AddExpectation(test_orientations[1].get());
- checker_b->AddExpectation(test_orientations[0].get());
- checker_b->AddExpectation(test_orientations[1].get());
- device_data_factory->SetDeviceData(test_orientations[1].get(),
- DeviceData::kTypeOrientation);
- provider_->AddObserver(checker_b.get());
- base::MessageLoop::current()->Run();
-
- provider_->RemoveObserver(checker_a.get());
- checker_b->AddExpectation(test_orientations[2].get());
- checker_c->AddExpectation(test_orientations[1].get());
- checker_c->AddExpectation(test_orientations[2].get());
- device_data_factory->SetDeviceData(test_orientations[2].get(),
- DeviceData::kTypeOrientation);
- provider_->AddObserver(checker_c.get());
- base::MessageLoop::current()->Run();
-
- provider_->RemoveObserver(checker_b.get());
- provider_->RemoveObserver(checker_c.get());
- MockDeviceDataFactory::SetCurInstance(NULL);
-}
-
-// Test for when the fetcher cannot provide the first type of data but can
-// provide the second type.
-TEST_F(DeviceOrientationProviderTest, FailingFirstDataTypeTest) {
-
- scoped_refptr<MockDeviceDataFactory> device_data_factory(
- new MockDeviceDataFactory());
- MockDeviceDataFactory::SetCurInstance(device_data_factory.get());
- Init(MockDeviceDataFactory::CreateDataFetcher);
-
- scoped_ptr<TestDataUpdateChecker> test_data_checker(
- new TestDataUpdateChecker(&pending_expectations_));
- scoped_ptr<OrientationUpdateChecker> orientation_checker(
- new OrientationUpdateChecker(&pending_expectations_));
-
- scoped_refptr<Orientation> test_orientation(new Orientation());
- test_orientation->set_alpha(1);
- test_orientation->set_beta(2);
- test_orientation->set_gamma(3);
- test_orientation->set_absolute(true);
-
- test_data_checker->AddExpectation(new TestData());
- provider_->AddObserver(test_data_checker.get());
- base::MessageLoop::current()->Run();
-
- orientation_checker->AddExpectation(test_orientation.get());
- device_data_factory->SetDeviceData(test_orientation.get(),
- DeviceData::kTypeOrientation);
- provider_->AddObserver(orientation_checker.get());
- base::MessageLoop::current()->Run();
-
- provider_->RemoveObserver(test_data_checker.get());
- provider_->RemoveObserver(orientation_checker.get());
- MockDeviceDataFactory::SetCurInstance(NULL);
-}
-
-#if defined(OS_LINUX) || defined(OS_WIN)
-// Flakily DCHECKs on Linux. See crbug.com/104950.
-// FLAKY on Win. See crbug.com/104950.
-#define MAYBE_ObserverNotRemoved DISABLED_ObserverNotRemoved
-#else
-#define MAYBE_ObserverNotRemoved ObserverNotRemoved
-#endif
-TEST_F(DeviceOrientationProviderTest, MAYBE_ObserverNotRemoved) {
- scoped_refptr<MockDeviceDataFactory> device_data_factory(
- new MockDeviceDataFactory());
- MockDeviceDataFactory::SetCurInstance(device_data_factory.get());
- Init(MockDeviceDataFactory::CreateDataFetcher);
- scoped_refptr<Orientation> test_orientation(new Orientation());
- test_orientation->set_alpha(1);
- test_orientation->set_beta(2);
- test_orientation->set_gamma(3);
- test_orientation->set_absolute(true);
-
- scoped_refptr<Orientation> test_orientation2(new Orientation());
- test_orientation2->set_alpha(4);
- test_orientation2->set_beta(5);
- test_orientation2->set_gamma(6);
- test_orientation2->set_absolute(false);
-
- scoped_ptr<OrientationUpdateChecker> checker(
- new OrientationUpdateChecker(&pending_expectations_));
- checker->AddExpectation(test_orientation.get());
- device_data_factory->SetDeviceData(test_orientation.get(),
- DeviceData::kTypeOrientation);
- provider_->AddObserver(checker.get());
- base::MessageLoop::current()->Run();
-
- checker->AddExpectation(test_orientation2.get());
- device_data_factory->SetDeviceData(test_orientation2.get(),
- DeviceData::kTypeOrientation);
- base::MessageLoop::current()->Run();
-
- MockDeviceDataFactory::SetCurInstance(NULL);
-
- // Note that checker is not removed. This should not be a problem.
-}
-
-#if defined(OS_WIN)
-// FLAKY on Win. See crbug.com/104950.
-#define MAYBE_StartFailing DISABLED_StartFailing
-#else
-#define MAYBE_StartFailing StartFailing
-#endif
-TEST_F(DeviceOrientationProviderTest, MAYBE_StartFailing) {
- scoped_refptr<MockDeviceDataFactory> device_data_factory(
- new MockDeviceDataFactory());
- MockDeviceDataFactory::SetCurInstance(device_data_factory.get());
- Init(MockDeviceDataFactory::CreateDataFetcher);
- scoped_refptr<Orientation> test_orientation(new Orientation());
- test_orientation->set_alpha(1);
- test_orientation->set_beta(2);
- test_orientation->set_gamma(3);
- test_orientation->set_absolute(true);
-
- scoped_ptr<OrientationUpdateChecker> checker_a(new OrientationUpdateChecker(
- &pending_expectations_));
- scoped_ptr<OrientationUpdateChecker> checker_b(new OrientationUpdateChecker(
- &pending_expectations_));
-
- device_data_factory->SetDeviceData(test_orientation.get(),
- DeviceData::kTypeOrientation);
- checker_a->AddExpectation(test_orientation.get());
- provider_->AddObserver(checker_a.get());
- base::MessageLoop::current()->Run();
-
- checker_a->AddExpectation(new Orientation());
- device_data_factory->SetFailing(true);
- base::MessageLoop::current()->Run();
-
- checker_b->AddExpectation(new Orientation());
- provider_->AddObserver(checker_b.get());
- base::MessageLoop::current()->Run();
-
- provider_->RemoveObserver(checker_a.get());
- provider_->RemoveObserver(checker_b.get());
- MockDeviceDataFactory::SetCurInstance(NULL);
-}
-
-TEST_F(DeviceOrientationProviderTest, StartStopStart) {
- scoped_refptr<MockDeviceDataFactory> device_data_factory(
- new MockDeviceDataFactory());
- MockDeviceDataFactory::SetCurInstance(device_data_factory.get());
- Init(MockDeviceDataFactory::CreateDataFetcher);
-
- scoped_refptr<Orientation> test_orientation(new Orientation());
- test_orientation->set_alpha(1);
- test_orientation->set_beta(2);
- test_orientation->set_gamma(3);
- test_orientation->set_absolute(true);
-
- scoped_refptr<Orientation> test_orientation2(new Orientation());
- test_orientation2->set_alpha(4);
- test_orientation2->set_beta(5);
- test_orientation2->set_gamma(6);
- test_orientation2->set_absolute(false);
-
- scoped_ptr<OrientationUpdateChecker> checker_a(new OrientationUpdateChecker(
- &pending_expectations_));
- scoped_ptr<OrientationUpdateChecker> checker_b(new OrientationUpdateChecker(
- &pending_expectations_));
-
- checker_a->AddExpectation(test_orientation.get());
- device_data_factory->SetDeviceData(test_orientation.get(),
- DeviceData::kTypeOrientation);
- provider_->AddObserver(checker_a.get());
- base::MessageLoop::current()->Run();
-
- provider_->RemoveObserver(checker_a.get()); // This stops the Provider.
-
- checker_b->AddExpectation(test_orientation2.get());
- device_data_factory->SetDeviceData(test_orientation2.get(),
- DeviceData::kTypeOrientation);
- provider_->AddObserver(checker_b.get());
- base::MessageLoop::current()->Run();
-
- provider_->RemoveObserver(checker_b.get());
- MockDeviceDataFactory::SetCurInstance(NULL);
-}
-
-// Tests that Orientation events only fire if the change is significant.
-TEST_F(DeviceOrientationProviderTest, OrientationSignificantlyDifferent) {
- scoped_refptr<MockDeviceDataFactory> device_data_factory(
- new MockDeviceDataFactory());
- MockDeviceDataFactory::SetCurInstance(device_data_factory.get());
- Init(MockDeviceDataFactory::CreateDataFetcher);
-
- // Values that should be well below or above the implementation's
- // significane threshold.
- const double kInsignificantDifference = 1e-6;
- const double kSignificantDifference = 30;
- const double kAlpha = 4, kBeta = 5, kGamma = 6;
-
- scoped_refptr<Orientation> first_orientation(new Orientation());
- first_orientation->set_alpha(kAlpha);
- first_orientation->set_beta(kBeta);
- first_orientation->set_gamma(kGamma);
- first_orientation->set_absolute(true);
-
- scoped_refptr<Orientation> second_orientation(new Orientation());
- second_orientation->set_alpha(kAlpha + kInsignificantDifference);
- second_orientation->set_beta(kBeta + kInsignificantDifference);
- second_orientation->set_gamma(kGamma + kInsignificantDifference);
- second_orientation->set_absolute(false);
-
- scoped_refptr<Orientation> third_orientation(new Orientation());
- third_orientation->set_alpha(kAlpha + kSignificantDifference);
- third_orientation->set_beta(kBeta + kSignificantDifference);
- third_orientation->set_gamma(kGamma + kSignificantDifference);
- // can't provide absolute
-
- scoped_ptr<OrientationUpdateChecker> checker_a(new OrientationUpdateChecker(
- &pending_expectations_));
- scoped_ptr<OrientationUpdateChecker> checker_b(new OrientationUpdateChecker(
- &pending_expectations_));
-
- device_data_factory->SetDeviceData(first_orientation.get(),
- DeviceData::kTypeOrientation);
- checker_a->AddExpectation(first_orientation.get());
- provider_->AddObserver(checker_a.get());
- base::MessageLoop::current()->Run();
-
- // The observers should not see this insignificantly different orientation.
- device_data_factory->SetDeviceData(second_orientation.get(),
- DeviceData::kTypeOrientation);
- checker_b->AddExpectation(first_orientation.get());
- provider_->AddObserver(checker_b.get());
- base::MessageLoop::current()->Run();
-
- device_data_factory->SetDeviceData(third_orientation.get(),
- DeviceData::kTypeOrientation);
- checker_a->AddExpectation(third_orientation.get());
- checker_b->AddExpectation(third_orientation.get());
- base::MessageLoop::current()->Run();
-
- provider_->RemoveObserver(checker_a.get());
- provider_->RemoveObserver(checker_b.get());
- MockDeviceDataFactory::SetCurInstance(NULL);
-}
-
-} // namespace
-
-} // namespace content
diff --git a/chromium/content/browser/devtools/OWNERS b/chromium/content/browser/devtools/OWNERS
index bb6028e656a..d995b0f999c 100644
--- a/chromium/content/browser/devtools/OWNERS
+++ b/chromium/content/browser/devtools/OWNERS
@@ -1,2 +1,4 @@
+kaznacheev@chromium.org
pfeldman@chromium.org
+vsevik@chromium.org
yurys@chromium.org
diff --git a/chromium/content/browser/devtools/browser_protocol.json b/chromium/content/browser/devtools/browser_protocol.json
index ecc1bc3624a..59e73c0c590 100644
--- a/chromium/content/browser/devtools/browser_protocol.json
+++ b/chromium/content/browser/devtools/browser_protocol.json
@@ -21,7 +21,8 @@
"type": "object",
"properties": [
{ "name": "devices", "type": "array", "items": { "$ref": "GPUDevice" }, "description": "The graphics devices on the system. Element 0 is the primary GPU." },
- { "name": "auxAttributes", "type": "object", "optional": "true", "description": "An optional dictionary of additional GPU related attributes." }
+ { "name": "auxAttributes", "type": "object", "optional": "true", "description": "An optional dictionary of additional GPU related attributes." },
+ { "name": "featureStatus", "type": "object", "optional": "true", "description": "An optional dictionary of graphics features and their status." }
],
"description": "Provides information about the GPU(s) on the system."
},
@@ -41,7 +42,8 @@
"description": "Returns information about the system.",
"returns": [
{ "name": "info", "$ref": "SystemInfo", "description": "Information about the system." }
- ]
+ ],
+ "handlers": ["browser"]
}
]
}]
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.cc b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
index 35111e9ab82..087004296d5 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
@@ -10,6 +10,7 @@
#include "base/guid.h"
#include "base/lazy_instance.h"
#include "content/browser/devtools/devtools_manager_impl.h"
+#include "content/public/browser/browser_thread.h"
namespace content {
@@ -21,10 +22,12 @@ base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
DevToolsAgentHostImpl::DevToolsAgentHostImpl()
: close_listener_(NULL),
id_(base::GenerateGUID()) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
g_instances.Get()[id_] = this;
}
DevToolsAgentHostImpl::~DevToolsAgentHostImpl() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
g_instances.Get().erase(g_instances.Get().find(id_));
}
diff --git a/chromium/content/browser/devtools/devtools_http_handler_impl.cc b/chromium/content/browser/devtools/devtools_http_handler_impl.cc
index 8003b8bd751..1d0fca1e282 100644
--- a/chromium/content/browser/devtools/devtools_http_handler_impl.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler_impl.cc
@@ -11,12 +11,9 @@
#include "base/compiler_specific.h"
#include "base/file_util.h"
#include "base/json/json_writer.h"
-#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "base/values.h"
#include "content/browser/devtools/devtools_browser_target.h"
@@ -25,18 +22,13 @@
#include "content/browser/devtools/devtools_system_info_handler.h"
#include "content/browser/devtools/devtools_tracing_handler.h"
#include "content/browser/devtools/tethering_handler.h"
-#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/devtools_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_client_host.h"
#include "content/public/browser/devtools_http_handler_delegate.h"
#include "content/public/browser/devtools_manager.h"
-#include "content/public/browser/favicon_status.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/devtools_target.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "grit/devtools_resources_map.h"
@@ -45,51 +37,33 @@
#include "net/base/ip_endpoint.h"
#include "net/server/http_server_request_info.h"
#include "net/server/http_server_response_info.h"
-#include "ui/base/layout.h"
-#include "url/gurl.h"
#include "webkit/common/user_agent/user_agent.h"
#include "webkit/common/user_agent/user_agent_util.h"
-namespace content {
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#endif
-const int kBufferSize = 16 * 1024;
+namespace content {
namespace {
-static const char* kProtocolVersion = "1.0";
+const char kProtocolVersion[] = "1.0";
-static const char* kDevToolsHandlerThreadName = "Chrome_DevToolsHandlerThread";
+const char kDevToolsHandlerThreadName[] = "Chrome_DevToolsHandlerThread";
-static const char* kThumbUrlPrefix = "/thumb/";
-static const char* kPageUrlPrefix = "/devtools/page/";
+const char kThumbUrlPrefix[] = "/thumb/";
+const char kPageUrlPrefix[] = "/devtools/page/";
-static const char* kTargetIdField = "id";
-static const char* kTargetTypeField = "type";
-static const char* kTargetTitleField = "title";
-static const char* kTargetDescriptionField = "description";
-static const char* kTargetUrlField = "url";
-static const char* kTargetThumbnailUrlField = "thumbnailUrl";
-static const char* kTargetFaviconUrlField = "faviconUrl";
-static const char* kTargetWebSocketDebuggerUrlField = "webSocketDebuggerUrl";
-static const char* kTargetDevtoolsFrontendUrlField = "devtoolsFrontendUrl";
-
-static const char* kTargetTypePage = "page";
-static const char* kTargetTypeOther = "other";
-
-class DevToolsDefaultBindingHandler
- : public DevToolsHttpHandler::DevToolsAgentHostBinding {
- public:
- DevToolsDefaultBindingHandler() {
- }
-
- virtual std::string GetIdentifier(DevToolsAgentHost* agent_host) OVERRIDE {
- return agent_host->GetId();
- }
-
- virtual DevToolsAgentHost* ForIdentifier(const std::string& id) OVERRIDE {
- return DevToolsAgentHost::GetForId(id).get();
- }
-};
+const char kTargetIdField[] = "id";
+const char kTargetTypeField[] = "type";
+const char kTargetTitleField[] = "title";
+const char kTargetDescriptionField[] = "description";
+const char kTargetUrlField[] = "url";
+const char kTargetThumbnailUrlField[] = "thumbnailUrl";
+const char kTargetFaviconUrlField[] = "faviconUrl";
+const char kTargetWebSocketDebuggerUrlField[] = "webSocketDebuggerUrl";
+const char kTargetDevtoolsFrontendUrlField[] = "devtoolsFrontendUrl";
// An internal implementation of DevToolsClientHost that delegates
// messages sent for DevToolsClient to a DebuggerShell instance.
@@ -151,18 +125,9 @@ class DevToolsClientHostImpl : public DevToolsClientHost {
std::string detach_reason_;
};
-static base::TimeTicks GetLastSelectedTime(RenderViewHost* rvh) {
- WebContents* web_contents = rvh->GetDelegate()->GetAsWebContents();
- if (!web_contents)
- return base::TimeTicks();
-
- return web_contents->GetLastSelectedTime();
-}
-
-typedef std::pair<RenderViewHost*, base::TimeTicks> PageInfo;
-
-static bool TimeComparator(const PageInfo& info1, const PageInfo& info2) {
- return info1.second > info2.second;
+static bool TimeComparator(const DevToolsTarget* target1,
+ const DevToolsTarget* target2) {
+ return target1->GetLastActivityTime() > target2->GetLastActivityTime();
}
} // namespace
@@ -200,6 +165,7 @@ DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() {
// Stop() must be called prior to destruction.
DCHECK(server_.get() == NULL);
DCHECK(thread_.get() == NULL);
+ STLDeleteValues(&target_map_);
}
void DevToolsHttpHandlerImpl::Start() {
@@ -245,27 +211,12 @@ void DevToolsHttpHandlerImpl::Stop() {
base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease, this));
}
-void DevToolsHttpHandlerImpl::SetDevToolsAgentHostBinding(
- DevToolsAgentHostBinding* binding) {
- if (binding)
- binding_ = binding;
- else
- binding_ = default_binding_.get();
-}
-
-GURL DevToolsHttpHandlerImpl::GetFrontendURL(DevToolsAgentHost* agent_host) {
+GURL DevToolsHttpHandlerImpl::GetFrontendURL() {
net::IPEndPoint ip_address;
if (server_->GetLocalAddress(&ip_address))
return GURL();
- if (!agent_host) {
- return GURL(std::string("http://") + ip_address.ToString() +
- overridden_frontend_url_);
- }
- std::string host = ip_address.ToString();
- std::string id = binding_->GetIdentifier(agent_host);
- return GURL(std::string("http://") +
- ip_address.ToString() +
- GetFrontendURLInternal(id, host));
+ return GURL(std::string("http://") + ip_address.ToString() +
+ overridden_frontend_url_);
}
static std::string PathWithoutParams(const std::string& path) {
@@ -308,13 +259,10 @@ void DevToolsHttpHandlerImpl::OnHttpRequest(
if (info.path.find(kThumbUrlPrefix) == 0) {
// Thumbnail request.
const std::string target_id = info.path.substr(strlen(kThumbUrlPrefix));
- DevToolsAgentHost* agent_host = binding_->ForIdentifier(target_id);
+ DevToolsTarget* target = GetTarget(target_id);
GURL page_url;
- if (agent_host) {
- RenderViewHost* rvh = agent_host->GetRenderViewHost();
- if (rvh)
- page_url = rvh->GetDelegate()->GetURL();
- }
+ if (target)
+ page_url = target->GetUrl();
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
@@ -481,9 +429,12 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI(
std::string path = info.path.substr(5);
// Trim fragment and query
+ std::string query;
size_t query_pos = path.find("?");
- if (query_pos != std::string::npos)
+ if (query_pos != std::string::npos) {
+ query = path.substr(query_pos + 1);
path = path.substr(0, query_pos);
+ }
size_t fragment_pos = path.find("#");
if (fragment_pos != std::string::npos)
@@ -506,45 +457,30 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI(
version.SetString("Browser", content::GetContentClient()->GetProduct());
version.SetString("User-Agent",
webkit_glue::GetUserAgent(GURL(kAboutBlankURL)));
+#if defined(OS_ANDROID)
+ version.SetString("Android-Package",
+ base::android::BuildInfo::GetInstance()->package_name());
+#endif
SendJson(connection_id, net::HTTP_OK, &version, std::string());
return;
}
if (command == "list") {
- typedef std::vector<PageInfo> PageList;
- PageList page_list;
-
- std::vector<RenderViewHost*> rvh_list =
- DevToolsAgentHost::GetValidRenderViewHosts();
- for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
- it != rvh_list.end(); ++it)
- page_list.push_back(PageInfo(*it, GetLastSelectedTime(*it)));
-
- std::sort(page_list.begin(), page_list.end(), TimeComparator);
-
- base::ListValue* target_list = new base::ListValue();
std::string host = info.headers["host"];
- for (PageList::iterator i = page_list.begin(); i != page_list.end(); ++i)
- target_list->Append(SerializePageInfo(i->first, host));
-
- AddRef(); // Balanced in SendTargetList.
- BrowserThread::PostTaskAndReply(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&DevToolsHttpHandlerImpl::CollectWorkerInfo,
- base::Unretained(this),
- target_list,
- host),
- base::Bind(&DevToolsHttpHandlerImpl::SendTargetList,
- base::Unretained(this),
- connection_id,
- target_list));
+ AddRef(); // Balanced in OnTargetListReceived.
+ delegate_->EnumerateTargets(
+ base::Bind(&DevToolsHttpHandlerImpl::OnTargetListReceived,
+ this, connection_id, host));
return;
}
if (command == "new") {
- RenderViewHost* rvh = delegate_->CreateNewTarget();
- if (!rvh) {
+ GURL url(net::UnescapeURLComponent(
+ query, net::UnescapeRule::URL_SPECIAL_CHARS));
+ if (!url.is_valid())
+ url = GURL(kAboutBlankURL);
+ scoped_ptr<DevToolsTarget> target(delegate_->CreateNewTarget(url));
+ if (!target) {
SendJson(connection_id,
net::HTTP_INTERNAL_SERVER_ERROR,
NULL,
@@ -552,15 +488,17 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI(
return;
}
std::string host = info.headers["host"];
- scoped_ptr<base::DictionaryValue> dictionary(SerializePageInfo(rvh, host));
+ scoped_ptr<base::DictionaryValue> dictionary(
+ SerializeTarget(*target.get(), host));
SendJson(connection_id, net::HTTP_OK, dictionary.get(), std::string());
+ const std::string target_id = target->GetId();
+ target_map_[target_id] = target.release();
return;
}
if (command == "activate" || command == "close") {
- DevToolsAgentHost* agent_host = binding_->ForIdentifier(target_id);
- RenderViewHost* rvh = agent_host ? agent_host->GetRenderViewHost() : NULL;
- if (!rvh) {
+ DevToolsTarget* target = GetTarget(target_id);
+ if (!target) {
SendJson(connection_id,
net::HTTP_NOT_FOUND,
NULL,
@@ -569,14 +507,26 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI(
}
if (command == "activate") {
- rvh->GetDelegate()->Activate();
- SendJson(connection_id, net::HTTP_OK, NULL, "Target activated");
+ if (target->Activate()) {
+ SendJson(connection_id, net::HTTP_OK, NULL, "Target activated");
+ } else {
+ SendJson(connection_id,
+ net::HTTP_INTERNAL_SERVER_ERROR,
+ NULL,
+ "Could not activate target id: " + target_id);
+ }
return;
}
if (command == "close") {
- rvh->ClosePage();
- SendJson(connection_id, net::HTTP_OK, NULL, "Target is closing");
+ if (target->Close()) {
+ SendJson(connection_id, net::HTTP_OK, NULL, "Target is closing");
+ } else {
+ SendJson(connection_id,
+ net::HTTP_INTERNAL_SERVER_ERROR,
+ NULL,
+ "Could not close target id: " + target_id);
+ }
return;
}
}
@@ -587,21 +537,30 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI(
return;
}
-void DevToolsHttpHandlerImpl::CollectWorkerInfo(base::ListValue* target_list,
- std::string host) {
-
- std::vector<WorkerService::WorkerInfo> worker_info =
- WorkerService::GetInstance()->GetWorkers();
+void DevToolsHttpHandlerImpl::OnTargetListReceived(
+ int connection_id,
+ const std::string& host,
+ const DevToolsHttpHandlerDelegate::TargetList& targets) {
+ DevToolsHttpHandlerDelegate::TargetList sorted_targets = targets;
+ std::sort(sorted_targets.begin(), sorted_targets.end(), TimeComparator);
- for (size_t i = 0; i < worker_info.size(); ++i)
- target_list->Append(SerializeWorkerInfo(worker_info[i], host));
+ STLDeleteValues(&target_map_);
+ base::ListValue list_value;
+ for (DevToolsHttpHandlerDelegate::TargetList::const_iterator it =
+ sorted_targets.begin(); it != sorted_targets.end(); ++it) {
+ DevToolsTarget* target = *it;
+ target_map_[target->GetId()] = target;
+ list_value.Append(SerializeTarget(*target, host));
+ }
+ SendJson(connection_id, net::HTTP_OK, &list_value, std::string());
+ Release(); // Balanced in OnJsonRequestUI.
}
-void DevToolsHttpHandlerImpl::SendTargetList(int connection_id,
- base::ListValue* target_list) {
- SendJson(connection_id, net::HTTP_OK, target_list, std::string());
- delete target_list;
- Release(); // Balanced OnJsonRequestUI.
+DevToolsTarget* DevToolsHttpHandlerImpl::GetTarget(const std::string& id) {
+ TargetMap::const_iterator it = target_map_.find(id);
+ if (it == target_map_.end())
+ return NULL;
+ return it->second;
}
void DevToolsHttpHandlerImpl::OnThumbnailRequestUI(
@@ -631,7 +590,9 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequestUI(
}
std::string page_id = request.path.substr(strlen(kPageUrlPrefix));
- DevToolsAgentHost* agent = binding_->ForIdentifier(page_id);
+ DevToolsTarget* target = GetTarget(page_id);
+ scoped_refptr<DevToolsAgentHost> agent =
+ target ? target->GetAgentHost() : NULL;
if (!agent) {
Send500(connection_id, "No such target id: " + page_id);
return;
@@ -687,9 +648,6 @@ DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl(
if (overridden_frontend_url_.empty())
overridden_frontend_url_ = "/devtools/devtools.html";
- default_binding_.reset(new DevToolsDefaultBindingHandler);
- binding_ = default_binding_.get();
-
// Balanced in ResetHandlerThreadAndRelease().
AddRef();
}
@@ -788,84 +746,44 @@ void DevToolsHttpHandlerImpl::AcceptWebSocket(
connection_id, request));
}
-base::DictionaryValue* DevToolsHttpHandlerImpl::SerializePageInfo(
- RenderViewHost* rvh,
+base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget(
+ const DevToolsTarget& target,
const std::string& host) {
base::DictionaryValue* dictionary = new base::DictionaryValue;
- scoped_refptr<DevToolsAgentHost> agent(
- DevToolsAgentHost::GetOrCreateFor(rvh));
-
- std::string id = binding_->GetIdentifier(agent.get());
+ std::string id = target.GetId();
dictionary->SetString(kTargetIdField, id);
+ dictionary->SetString(kTargetTypeField, target.GetType());
+ dictionary->SetString(kTargetTitleField,
+ net::EscapeForHTML(target.GetTitle()));
+ dictionary->SetString(kTargetDescriptionField, target.GetDescription());
- switch (delegate_->GetTargetType(rvh)) {
- case DevToolsHttpHandlerDelegate::kTargetTypeTab:
- dictionary->SetString(kTargetTypeField, kTargetTypePage);
- break;
- default:
- dictionary->SetString(kTargetTypeField, kTargetTypeOther);
- }
+ GURL url = target.GetUrl();
+ dictionary->SetString(kTargetUrlField, url.spec());
- WebContents* web_contents = rvh->GetDelegate()->GetAsWebContents();
- if (web_contents) {
- dictionary->SetString(kTargetTitleField, UTF16ToUTF8(
- net::EscapeForHTML(web_contents->GetTitle())));
- dictionary->SetString(kTargetUrlField, web_contents->GetURL().spec());
- dictionary->SetString(kTargetThumbnailUrlField,
- std::string(kThumbUrlPrefix) + id);
+ GURL favicon_url = target.GetFaviconUrl();
+ if (favicon_url.is_valid())
+ dictionary->SetString(kTargetFaviconUrlField, favicon_url.spec());
- NavigationController& controller = web_contents->GetController();
- NavigationEntry* entry = controller.GetActiveEntry();
- if (entry != NULL && entry->GetURL().is_valid()) {
- dictionary->SetString(kTargetFaviconUrlField,
- entry->GetFavicon().url.spec());
- }
+ if (!delegate_->GetPageThumbnailData(url).empty()) {
+ dictionary->SetString(kTargetThumbnailUrlField,
+ std::string(kThumbUrlPrefix) + id);
}
- dictionary->SetString(kTargetDescriptionField,
- delegate_->GetViewDescription(rvh));
- if (!agent->IsAttached())
- SerializeDebuggerURLs(dictionary, id, host);
- return dictionary;
-}
-
-base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeWorkerInfo(
- const WorkerService::WorkerInfo& worker,
- const std::string& host) {
- base::DictionaryValue* dictionary = new base::DictionaryValue;
-
- scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetForWorker(
- worker.process_id, worker.route_id));
-
- std::string id = binding_->GetIdentifier(agent.get());
-
- dictionary->SetString(kTargetIdField, id);
- dictionary->SetString(kTargetTypeField, kTargetTypeOther);
- dictionary->SetString(kTargetTitleField,
- UTF16ToUTF8(net::EscapeForHTML(worker.name)));
- dictionary->SetString(kTargetUrlField, worker.url.spec());
- dictionary->SetString(kTargetDescriptionField,
- base::StringPrintf("Worker pid:%d", base::GetProcId(worker.handle)));
+ if (!target.IsAttached()) {
+ dictionary->SetString(kTargetWebSocketDebuggerUrlField,
+ base::StringPrintf("ws://%s%s%s",
+ host.c_str(),
+ kPageUrlPrefix,
+ id.c_str()));
+ std::string devtools_frontend_url = GetFrontendURLInternal(
+ id.c_str(),
+ host);
+ dictionary->SetString(
+ kTargetDevtoolsFrontendUrlField, devtools_frontend_url);
+ }
- if (!agent->IsAttached())
- SerializeDebuggerURLs(dictionary, id, host);
return dictionary;
}
-void DevToolsHttpHandlerImpl::SerializeDebuggerURLs(
- base::DictionaryValue* dictionary,
- const std::string& id,
- const std::string& host) {
- dictionary->SetString(kTargetWebSocketDebuggerUrlField,
- base::StringPrintf("ws://%s%s%s",
- host.c_str(),
- kPageUrlPrefix,
- id.c_str()));
- std::string devtools_frontend_url = GetFrontendURLInternal(
- id.c_str(),
- host);
- dictionary->SetString(kTargetDevtoolsFrontendUrlField, devtools_frontend_url);
-}
-
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_http_handler_impl.h b/chromium/content/browser/devtools/devtools_http_handler_impl.h
index f7ccca02d45..4e40db07f11 100644
--- a/chromium/content/browser/devtools/devtools_http_handler_impl.h
+++ b/chromium/content/browser/devtools/devtools_http_handler_impl.h
@@ -15,7 +15,6 @@
#include "content/common/content_export.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_http_handler_delegate.h"
-#include "content/public/browser/worker_service.h"
#include "net/http/http_status_code.h"
#include "net/server/http_server.h"
@@ -53,9 +52,7 @@ class DevToolsHttpHandlerImpl
// DevToolsHttpHandler implementation.
virtual void Stop() OVERRIDE;
- virtual void SetDevToolsAgentHostBinding(
- DevToolsAgentHostBinding* binding) OVERRIDE;
- virtual GURL GetFrontendURL(DevToolsAgentHost* agent_host) OVERRIDE;
+ virtual GURL GetFrontendURL() OVERRIDE;
// net::HttpServer::Delegate implementation.
virtual void OnHttpRequest(int connection_id,
@@ -80,8 +77,12 @@ class DevToolsHttpHandlerImpl
void ResetHandlerThread();
void ResetHandlerThreadAndRelease();
- void CollectWorkerInfo(base::ListValue* target_list, std::string host);
- void SendTargetList(int connection_id, base::ListValue* target_list);
+ void OnTargetListReceived(
+ int connection_id,
+ const std::string& host,
+ const DevToolsHttpHandlerDelegate::TargetList& targets);
+
+ DevToolsTarget* GetTarget(const std::string& id);
void Init();
void Teardown();
@@ -103,19 +104,11 @@ class DevToolsHttpHandlerImpl
const net::HttpServerRequestInfo& request);
// Returns the front end url without the host at the beginning.
- std::string GetFrontendURLInternal(const std::string rvh_id,
+ std::string GetFrontendURLInternal(const std::string target_id,
const std::string& host);
- base::DictionaryValue* SerializePageInfo(RenderViewHost* rvh,
- const std::string& host);
-
- base::DictionaryValue* SerializeWorkerInfo(
- const WorkerService::WorkerInfo& worker,
- const std::string& host);
-
- void SerializeDebuggerURLs(base::DictionaryValue* dictionary,
- const std::string& id,
- const std::string& host);
+ base::DictionaryValue* SerializeTarget(const DevToolsTarget& target,
+ const std::string& host);
// The thread used by the devtools handler to run server socket.
scoped_ptr<base::Thread> thread_;
@@ -126,8 +119,8 @@ class DevToolsHttpHandlerImpl
typedef std::map<int, DevToolsClientHost*> ConnectionToClientHostMap;
ConnectionToClientHostMap connection_to_client_host_ui_;
scoped_ptr<DevToolsHttpHandlerDelegate> delegate_;
- DevToolsAgentHostBinding* binding_;
- scoped_ptr<DevToolsAgentHostBinding> default_binding_;
+ typedef std::map<std::string, DevToolsTarget*> TargetMap;
+ TargetMap target_map_;
scoped_refptr<DevToolsBrowserTarget> browser_target_;
DISALLOW_COPY_AND_ASSIGN(DevToolsHttpHandlerImpl);
};
diff --git a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
index a57c4ccd4cd..f3179f0f140 100644
--- a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
@@ -7,6 +7,7 @@
#include "content/browser/browser_thread_impl.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_http_handler_delegate.h"
+#include "content/public/browser/devtools_target.h"
#include "net/socket/stream_listen_socket.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -64,12 +65,11 @@ class DummyDelegate : public DevToolsHttpHandlerDelegate {
virtual std::string GetPageThumbnailData(const GURL& url) OVERRIDE {
return std::string();
}
- virtual RenderViewHost* CreateNewTarget() OVERRIDE { return NULL; }
- virtual TargetType GetTargetType(RenderViewHost*) OVERRIDE {
- return kTargetTypeTab;
+ virtual scoped_ptr<DevToolsTarget> CreateNewTarget(const GURL& url) OVERRIDE {
+ return scoped_ptr<DevToolsTarget>();
}
- virtual std::string GetViewDescription(content::RenderViewHost*) OVERRIDE {
- return std::string();
+ virtual void EnumerateTargets(TargetCallback callback) OVERRIDE {
+ callback.Run(TargetList());
}
virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(
net::StreamListenSocket::Delegate* delegate,
diff --git a/chromium/content/browser/devtools/devtools_manager_unittest.cc b/chromium/content/browser/devtools/devtools_manager_unittest.cc
index 46c198cc05c..aac9b6cbb92 100644
--- a/chromium/content/browser/devtools/devtools_manager_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_manager_unittest.cc
@@ -7,7 +7,6 @@
#include "base/time/time.h"
#include "content/browser/devtools/devtools_manager_impl.h"
#include "content/browser/devtools/render_view_devtools_agent_host.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
#include "content/common/view_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/devtools_agent_host.h"
@@ -16,6 +15,7 @@
#include "content/public/browser/devtools_external_agent_proxy_delegate.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/test/test_content_browser_client.h"
+#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -87,41 +87,14 @@ class TestWebContentsDelegate : public WebContentsDelegate {
bool renderer_unresponsive_received_;
};
-class DevToolsManagerTestBrowserClient : public TestContentBrowserClient {
- public:
- DevToolsManagerTestBrowserClient() {
- }
-
- virtual bool ShouldSwapProcessesForNavigation(
- SiteInstance* site_instance,
- const GURL& current_url,
- const GURL& new_url) OVERRIDE {
- return true;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DevToolsManagerTestBrowserClient);
-};
-
} // namespace
class DevToolsManagerTest : public RenderViewHostImplTestHarness {
protected:
virtual void SetUp() OVERRIDE {
- original_browser_client_ = SetBrowserClientForTesting(&browser_client_);
-
RenderViewHostImplTestHarness::SetUp();
TestDevToolsClientHost::ResetCounters();
}
-
- virtual void TearDown() OVERRIDE {
- RenderViewHostImplTestHarness::TearDown();
- SetBrowserClientForTesting(original_browser_client_);
- }
-
- private:
- ContentBrowserClient* original_browser_client_;
- DevToolsManagerTestBrowserClient browser_client_;
};
TEST_F(DevToolsManagerTest, OpenAndManuallyCloseDevToolsClientHost) {
@@ -200,7 +173,6 @@ TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) {
}
TEST_F(DevToolsManagerTest, ReattachOnCancelPendingNavigation) {
- contents()->transition_cross_site = true;
// Navigate to URL. First URL should use first RenderViewHost.
const GURL url("http://www.google.com");
controller().LoadURL(
diff --git a/chromium/content/browser/devtools/devtools_protocol.cc b/chromium/content/browser/devtools/devtools_protocol.cc
index 948ed6be8a4..e0e544e54c4 100644
--- a/chromium/content/browser/devtools/devtools_protocol.cc
+++ b/chromium/content/browser/devtools/devtools_protocol.cc
@@ -236,6 +236,15 @@ scoped_refptr<DevToolsProtocol::Command> DevToolsProtocol::ParseCommand(
}
// static
+scoped_refptr<DevToolsProtocol::Command>
+DevToolsProtocol::CreateCommand(
+ int id,
+ const std::string& method,
+ base::DictionaryValue* params) {
+ return new Command(id, method, params);
+}
+
+// static
scoped_refptr<DevToolsProtocol::Notification>
DevToolsProtocol::ParseNotification(const std::string& json) {
scoped_ptr<base::DictionaryValue> dict(ParseMessage(json, NULL));
diff --git a/chromium/content/browser/devtools/devtools_protocol.h b/chromium/content/browser/devtools/devtools_protocol.h
index 2f7ce0bfecb..15b0a8087be 100644
--- a/chromium/content/browser/devtools/devtools_protocol.h
+++ b/chromium/content/browser/devtools/devtools_protocol.h
@@ -13,6 +13,7 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/values.h"
+#include "content/common/content_export.h"
namespace content {
@@ -119,7 +120,7 @@ class DevToolsProtocol {
DISALLOW_COPY_AND_ASSIGN(Notification);
};
- class Handler {
+ class CONTENT_EXPORT Handler {
public:
typedef base::Callback<scoped_refptr<DevToolsProtocol::Response>(
scoped_refptr<DevToolsProtocol::Command> command)> CommandHandler;
@@ -156,8 +157,14 @@ class DevToolsProtocol {
DISALLOW_COPY_AND_ASSIGN(Handler);
};
- static scoped_refptr<Command> ParseCommand(const std::string& json,
- std::string* error_response);
+ CONTENT_EXPORT static scoped_refptr<Command> ParseCommand(
+ const std::string& json,
+ std::string* error_response);
+
+ CONTENT_EXPORT static scoped_refptr<Command> CreateCommand(
+ int id,
+ const std::string& method,
+ base::DictionaryValue* params);
static scoped_refptr<Notification> ParseNotification(
const std::string& json);
diff --git a/chromium/content/browser/devtools/devtools_protocol_constants.cc b/chromium/content/browser/devtools/devtools_protocol_constants.cc
index d9c337fc8aa..af5ecd1f580 100644
--- a/chromium/content/browser/devtools/devtools_protocol_constants.cc
+++ b/chromium/content/browser/devtools/devtools_protocol_constants.cc
@@ -2,171 +2,292 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// THIS FILE IS AUTOGENERATED.
+// If you need change something in this file, please see
+// protocol.json and browser_protocol.json
+
#include "content/browser/devtools/devtools_protocol_constants.h"
namespace content {
namespace devtools {
-const char kParamX[] = "x";
-const char kParamY[] = "y";
-const char kParamWidth[] = "width";
-const char kParamHeight[] = "height";
+const char kResult[] = "result";
namespace DOM {
-
-namespace setFileInputFiles {
- const char kName[] = "DOM.setFileInputFiles";
- const char kParamFiles[] = "files";
-} // setFileInputFiles
-
-} // DOM
+ const char kName[] = "DOM";
+
+ namespace Rect {
+ const char kParamHeight[] = "height";
+ const char kParamWidth[] = "width";
+ const char kParamX[] = "x";
+ const char kParamY[] = "y";
+ } // Rect
+
+ namespace setFileInputFiles {
+ const char kName[] = "DOM.setFileInputFiles";
+ const char kParamFiles[] = "files";
+ const char kParamNodeId[] = "nodeId";
+ } // setFileInputFiles
+} // DOM
namespace Input {
-
-const char kParamType[] = "type";
-const char kParamModifiers[] = "modifiers";
-const char kParamTimestamp[] = "timestamp";
-const char kParamDeviceSpace[] = "deviceSpace";
-
-namespace dispatchMouseEvent {
- const char kName[] = "Input.dispatchMouseEvent";
- const char kParamButton[] = "button";
- const char kParamClickCount[] = "clickCount";
-} // dispatchMouseEvent
-
-namespace dispatchGestureEvent {
- const char kName[] = "Input.dispatchGestureEvent";
- const char kParamDeltaX[] = "deltaX";
- const char kParamDeltaY[] = "deltaY";
- const char kParamPinchScale[] = "pinchScale";
-} // dispatchGestureEvent
-
-} // Input
+ const char kName[] = "Input";
+
+ namespace dispatchGestureEvent {
+ const char kName[] = "Input.dispatchGestureEvent";
+ const char kParamDeltaX[] = "deltaX";
+ const char kParamDeltaY[] = "deltaY";
+ const char kParamPinchScale[] = "pinchScale";
+ const char kParamTimestamp[] = "timestamp";
+ const char kParamType[] = "type";
+ const char kParamX[] = "x";
+ const char kParamY[] = "y";
+
+ namespace Type {
+ const char kEnumPinchBegin[] = "pinchBegin";
+ const char kEnumPinchEnd[] = "pinchEnd";
+ const char kEnumPinchUpdate[] = "pinchUpdate";
+ const char kEnumScrollBegin[] = "scrollBegin";
+ const char kEnumScrollEnd[] = "scrollEnd";
+ const char kEnumScrollUpdate[] = "scrollUpdate";
+ const char kEnumTap[] = "tap";
+ const char kEnumTapDown[] = "tapDown";
+ } // Type
+ } // dispatchGestureEvent
+
+ namespace dispatchMouseEvent {
+ const char kName[] = "Input.dispatchMouseEvent";
+ const char kParamButton[] = "button";
+ const char kParamClickCount[] = "clickCount";
+ const char kParamDeviceSpace[] = "deviceSpace";
+ const char kParamModifiers[] = "modifiers";
+ const char kParamTimestamp[] = "timestamp";
+ const char kParamType[] = "type";
+ const char kParamX[] = "x";
+ const char kParamY[] = "y";
+
+ namespace Button {
+ const char kEnumLeft[] = "left";
+ const char kEnumMiddle[] = "middle";
+ const char kEnumNone[] = "none";
+ const char kEnumRight[] = "right";
+ } // Button
+
+ namespace Type {
+ const char kEnumMouseMoved[] = "mouseMoved";
+ const char kEnumMousePressed[] = "mousePressed";
+ const char kEnumMouseReleased[] = "mouseReleased";
+ } // Type
+ } // dispatchMouseEvent
+} // Input
namespace Inspector {
+ const char kName[] = "Inspector";
-namespace detached {
- const char kName[] = "Inspector.detached";
- const char kParamReason[] = "reason";
-} // detached
+ namespace detached {
+ const char kName[] = "Inspector.detached";
+ const char kParamReason[] = "reason";
+ } // detached
-namespace targetCrashed {
- const char kName[] = "Inspector.targetCrashed";
-} // targetCrashed
-
-} // Inspector
+ namespace targetCrashed {
+ const char kName[] = "Inspector.targetCrashed";
+ } // targetCrashed
+} // Inspector
namespace Page {
+ const char kName[] = "Page";
+
+ namespace NavigationEntry {
+ const char kParamId[] = "id";
+ const char kParamTitle[] = "title";
+ const char kParamUrl[] = "url";
+ } // NavigationEntry
+
+ namespace Quota {
+ const char kParamPersistent[] = "persistent";
+ const char kParamTemporary[] = "temporary";
+ } // Quota
+
+ namespace ScreencastFrameMetadata {
+ const char kParamDeviceScaleFactor[] = "deviceScaleFactor";
+ const char kParamOffsetBottom[] = "offsetBottom";
+ const char kParamOffsetTop[] = "offsetTop";
+ const char kParamPageScaleFactor[] = "pageScaleFactor";
+ const char kParamPageScaleFactorMax[] = "pageScaleFactorMax";
+ const char kParamPageScaleFactorMin[] = "pageScaleFactorMin";
+ const char kParamViewport[] = "viewport";
+ } // ScreencastFrameMetadata
+
+ namespace Usage {
+ const char kParamPersistent[] = "persistent";
+ const char kParamSyncable[] = "syncable";
+ const char kParamTemporary[] = "temporary";
+ } // Usage
+
+ namespace UsageItem {
+ const char kParamId[] = "id";
+ const char kParamValue[] = "value";
+
+ namespace Id {
+ const char kEnumAppcache[] = "appcache";
+ const char kEnumDatabase[] = "database";
+ const char kEnumFilesystem[] = "filesystem";
+ const char kEnumIndexeddatabase[] = "indexeddatabase";
+ } // Id
+ } // UsageItem
+
+ namespace canScreencast {
+ const char kName[] = "Page.canScreencast";
+ const char kResponseResult[] = "result";
+ } // canScreencast
+
+ namespace captureScreenshot {
+ const char kName[] = "Page.captureScreenshot";
+ const char kParamFormat[] = "format";
+ const char kParamMaxHeight[] = "maxHeight";
+ const char kParamMaxWidth[] = "maxWidth";
+ const char kParamQuality[] = "quality";
+ const char kResponseData[] = "data";
+ const char kResponseMetadata[] = "metadata";
+
+ namespace Format {
+ const char kEnumJpeg[] = "jpeg";
+ const char kEnumPng[] = "png";
+ } // Format
+ } // captureScreenshot
+
+ namespace disable {
+ const char kName[] = "Page.disable";
+ } // disable
+
+ namespace getNavigationHistory {
+ const char kName[] = "Page.getNavigationHistory";
+ const char kResponseCurrentIndex[] = "currentIndex";
+ const char kResponseEntries[] = "entries";
+ } // getNavigationHistory
+
+ namespace handleJavaScriptDialog {
+ const char kName[] = "Page.handleJavaScriptDialog";
+ const char kParamAccept[] = "accept";
+ const char kParamPromptText[] = "promptText";
+ } // handleJavaScriptDialog
+
+ namespace navigate {
+ const char kName[] = "Page.navigate";
+ const char kParamUrl[] = "url";
+ } // navigate
+
+ namespace navigateToHistoryEntry {
+ const char kName[] = "Page.navigateToHistoryEntry";
+ const char kParamEntryId[] = "entryId";
+ } // navigateToHistoryEntry
+
+ namespace queryUsageAndQuota {
+ const char kName[] = "Page.queryUsageAndQuota";
+ const char kParamSecurityOrigin[] = "securityOrigin";
+ const char kResponseQuota[] = "quota";
+ const char kResponseUsage[] = "usage";
+ } // queryUsageAndQuota
+
+ namespace reload {
+ const char kName[] = "Page.reload";
+ const char kParamIgnoreCache[] = "ignoreCache";
+ const char kParamScriptPreprocessor[] = "scriptPreprocessor";
+ const char kParamScriptToEvaluateOnLoad[] = "scriptToEvaluateOnLoad";
+ } // reload
+
+ namespace screencastFrame {
+ const char kName[] = "Page.screencastFrame";
+ const char kParamData[] = "data";
+ const char kParamMetadata[] = "metadata";
+ } // screencastFrame
+
+ namespace screencastVisibilityChanged {
+ const char kName[] = "Page.screencastVisibilityChanged";
+ const char kParamVisible[] = "visible";
+ } // screencastVisibilityChanged
+
+ namespace startScreencast {
+ const char kName[] = "Page.startScreencast";
+ const char kParamFormat[] = "format";
+ const char kParamMaxHeight[] = "maxHeight";
+ const char kParamMaxWidth[] = "maxWidth";
+ const char kParamQuality[] = "quality";
+
+ namespace Format {
+ const char kEnumJpeg[] = "jpeg";
+ const char kEnumPng[] = "png";
+ } // Format
+ } // startScreencast
+
+ namespace stopScreencast {
+ const char kName[] = "Page.stopScreencast";
+ } // stopScreencast
+} // Page
-const char kData[] = "data";
-const char kParamDeviceScaleFactor[] = "deviceScaleFactor";
-const char kParamPageScaleFactor[] = "pageScaleFactor";
-const char kParamPageScaleFactorMin[] = "pageScaleFactorMin";
-const char kParamPageScaleFactorMax[] = "pageScaleFactorMax";
-const char kParamOffsetBottom[] = "offsetBottom";
-const char kParamOffsetTop[] = "offsetTop";
-const char kParamViewport[] = "viewport";
-
-namespace disable {
- const char kName[] = "Page.disable";
-} // disable
-
-namespace handleJavaScriptDialog {
- const char kName[] = "Page.handleJavaScriptDialog";
- const char kParamAccept[] = "accept";
- const char kParamPromptText[] = "promptText";
-} // handleJavaScriptDialog
-
-namespace navigate {
- const char kName[] = "Page.navigate";
- const char kParamUrl[] = "url";
-} // navigate
-
-namespace reload {
- const char kName[] = "Page.reload";
-} // reload
-
-namespace getNavigationHistory {
- const char kName[] = "Page.getNavigationHistory";
- const char kResponseCurrentIndex[] = "currentIndex";
- const char kResponseEntries[] = "entries";
- const char kResponseEntryId[] = "id";
- const char kResponseEntryURL[] = "url";
- const char kResponseEntryTitle[] = "title";
-} // getNavigationHistory
-
-namespace navigateToHistoryEntry {
- const char kName[] = "Page.navigateToHistoryEntry";
- const char kParamEntryId[] = "entryId";
-} // navigateToHistoryEntry
-
-namespace captureScreenshot {
- const char kName[] = "Page.captureScreenshot";
- const char kParamFormat[] = "format";
- const char kParamQuality[] = "quality";
- const char kParamMaxWidth[] = "maxWidth";
- const char kParamMaxHeight[] = "maxHeight";
-} // captureScreenshot
-
-namespace startScreencast {
- const char kName[] = "Page.startScreencast";
-} // startScreencast
-
-namespace stopScreencast {
- const char kName[] = "Page.stopScreencast";
-} // stopScreencast
-
-namespace screencastFrame {
- const char kName[] = "Page.screencastFrame";
-} // screencastFrame
-
-namespace screencastVisibilityChanged {
- const char kName[] = "Page.screencastVisibilityChanged";
- const char kParamVisible[] = "visible";
-} // screencastVisibilityChanged
-
-} // Page
-
-namespace Worker {
-
-namespace disconnectedFromWorker {
- const char kName[] = "Worker.disconnectedFromWorker";
-} // disconnectedFromWorker
+namespace SystemInfo {
+ const char kName[] = "SystemInfo";
-} // Worker
+ namespace GPUDevice {
+ const char kParamDeviceId[] = "deviceId";
+ const char kParamDeviceString[] = "deviceString";
+ const char kParamVendorId[] = "vendorId";
+ const char kParamVendorString[] = "vendorString";
+ } // GPUDevice
+
+ namespace GPUInfo {
+ const char kParamAuxAttributes[] = "auxAttributes";
+ const char kParamDevices[] = "devices";
+ const char kParamFeatureStatus[] = "featureStatus";
+ } // GPUInfo
+
+ namespace SystemInfo {
+ const char kParamGpu[] = "gpu";
+ const char kParamModelName[] = "modelName";
+ } // SystemInfo
+
+ namespace getInfo {
+ const char kName[] = "SystemInfo.getInfo";
+ const char kResponseInfo[] = "info";
+ } // getInfo
+} // SystemInfo
namespace Tracing {
const char kName[] = "Tracing";
-namespace start {
- const char kName[] = "Tracing.start";
- const char kCategories[] = "categories";
- const char kTraceOptions[] = "trace-options";
-} // start
+ namespace dataCollected {
+ const char kName[] = "Tracing.dataCollected";
+ const char kParamValue[] = "value";
+ } // dataCollected
-namespace end {
- const char kName[] = "Tracing.end";
-}
+ namespace end {
+ const char kName[] = "Tracing.end";
+ } // end
-namespace tracingComplete {
- const char kName[] = "Tracing.tracingComplete";
-}
+ namespace start {
+ const char kName[] = "Tracing.start";
+ const char kParamCategories[] = "categories";
+ const char kParamOptions[] = "options";
+ } // start
-namespace dataCollected {
- const char kName[] = "Tracing.dataCollected";
- const char kValue[] = "value";
-}
+ namespace tracingComplete {
+ const char kName[] = "Tracing.tracingComplete";
+ } // tracingComplete
+} // Tracing
-} // Tracing
+namespace Worker {
+ const char kName[] = "Worker";
-namespace SystemInfo {
- const char kName[] = "SystemInfo";
+ namespace disconnectFromWorker {
+ const char kName[] = "Worker.disconnectFromWorker";
+ const char kParamWorkerId[] = "workerId";
+ } // disconnectFromWorker
+
+ namespace disconnectedFromWorker {
+ const char kName[] = "Worker.disconnectedFromWorker";
+ } // disconnectedFromWorker
+} // Worker
-namespace getInfo {
- const char kName[] = "SystemInfo.getInfo";
-} // getInfo
-} // SystemInfo
} // devtools
} // content
-
diff --git a/chromium/content/browser/devtools/devtools_protocol_constants.h b/chromium/content/browser/devtools/devtools_protocol_constants.h
index 733e697189c..8ed159bc0df 100644
--- a/chromium/content/browser/devtools/devtools_protocol_constants.h
+++ b/chromium/content/browser/devtools/devtools_protocol_constants.h
@@ -5,176 +5,290 @@
#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTSH_
#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTSH_
-// The constants in this file should be used instead manually constructing
-// strings passed to and from DevTools protocol.
-//
-// There is a plan to generate this file from inspector.json automatically.
-// Until then please feel free to add the constants here as needed.
+// THIS FILE IS AUTOGENERATED.
+// If you need change something in this file, please see
+// protocol.json and browser_protocol.json
namespace content {
namespace devtools {
-extern const char kParamX[];
-extern const char kParamY[];
-extern const char kParamWidth[];
-extern const char kParamHeight[];
+extern const char kResult[];
namespace DOM {
+ extern const char kName[];
+
+ namespace Rect {
+ extern const char kParamHeight[];
+ extern const char kParamWidth[];
+ extern const char kParamX[];
+ extern const char kParamY[];
+ } // Rect
namespace setFileInputFiles {
extern const char kName[];
extern const char kParamFiles[];
- } // setFileInputFiles
-
-} // DOM
+ extern const char kParamNodeId[];
+ } // setFileInputFiles
+} // DOM
namespace Input {
-
- extern const char kParamType[];
- extern const char kParamModifiers[];
- extern const char kParamTimestamp[];
- extern const char kParamDeviceSpace[];
-
- namespace dispatchMouseEvent {
- extern const char kName[];
- extern const char kParamX[];
- extern const char kParamY[];
- extern const char kParamButton[];
- extern const char kParamClickCount[];
- } // dispatchMouseEvent
+ extern const char kName[];
namespace dispatchGestureEvent {
extern const char kName[];
extern const char kParamDeltaX[];
extern const char kParamDeltaY[];
extern const char kParamPinchScale[];
- } // dispatchGestureEvent
+ extern const char kParamTimestamp[];
+ extern const char kParamType[];
+ extern const char kParamX[];
+ extern const char kParamY[];
-} // Input
+ namespace Type {
+ extern const char kEnumPinchBegin[];
+ extern const char kEnumPinchEnd[];
+ extern const char kEnumPinchUpdate[];
+ extern const char kEnumScrollBegin[];
+ extern const char kEnumScrollEnd[];
+ extern const char kEnumScrollUpdate[];
+ extern const char kEnumTap[];
+ extern const char kEnumTapDown[];
+ } // Type
+ } // dispatchGestureEvent
+
+ namespace dispatchMouseEvent {
+ extern const char kName[];
+ extern const char kParamButton[];
+ extern const char kParamClickCount[];
+ extern const char kParamDeviceSpace[];
+ extern const char kParamModifiers[];
+ extern const char kParamTimestamp[];
+ extern const char kParamType[];
+ extern const char kParamX[];
+ extern const char kParamY[];
+
+ namespace Button {
+ extern const char kEnumLeft[];
+ extern const char kEnumMiddle[];
+ extern const char kEnumNone[];
+ extern const char kEnumRight[];
+ } // Button
+
+ namespace Type {
+ extern const char kEnumMouseMoved[];
+ extern const char kEnumMousePressed[];
+ extern const char kEnumMouseReleased[];
+ } // Type
+ } // dispatchMouseEvent
+} // Input
namespace Inspector {
+ extern const char kName[];
namespace detached {
extern const char kName[];
extern const char kParamReason[];
- } // detached
+ } // detached
namespace targetCrashed {
extern const char kName[];
- } // targetCrashed
-
-} // Inspector
+ } // targetCrashed
+} // Inspector
namespace Page {
+ extern const char kName[];
- extern const char kData[];
- extern const char kParamDeviceScaleFactor[];
- extern const char kParamPageScaleFactor[];
- extern const char kParamPageScaleFactorMin[];
- extern const char kParamPageScaleFactorMax[];
- extern const char kParamOffsetBottom[];
- extern const char kParamOffsetTop[];
- extern const char kParamViewport[];
+ namespace NavigationEntry {
+ extern const char kParamId[];
+ extern const char kParamTitle[];
+ extern const char kParamUrl[];
+ } // NavigationEntry
+
+ namespace Quota {
+ extern const char kParamPersistent[];
+ extern const char kParamTemporary[];
+ } // Quota
+
+ namespace ScreencastFrameMetadata {
+ extern const char kParamDeviceScaleFactor[];
+ extern const char kParamOffsetBottom[];
+ extern const char kParamOffsetTop[];
+ extern const char kParamPageScaleFactor[];
+ extern const char kParamPageScaleFactorMax[];
+ extern const char kParamPageScaleFactorMin[];
+ extern const char kParamViewport[];
+ } // ScreencastFrameMetadata
+
+ namespace Usage {
+ extern const char kParamPersistent[];
+ extern const char kParamSyncable[];
+ extern const char kParamTemporary[];
+ } // Usage
+
+ namespace UsageItem {
+ extern const char kParamId[];
+ extern const char kParamValue[];
+
+ namespace Id {
+ extern const char kEnumAppcache[];
+ extern const char kEnumDatabase[];
+ extern const char kEnumFilesystem[];
+ extern const char kEnumIndexeddatabase[];
+ } // Id
+ } // UsageItem
+
+ namespace canScreencast {
+ extern const char kName[];
+ extern const char kResponseResult[];
+ } // canScreencast
+
+ namespace captureScreenshot {
+ extern const char kName[];
+ extern const char kParamFormat[];
+ extern const char kParamMaxHeight[];
+ extern const char kParamMaxWidth[];
+ extern const char kParamQuality[];
+ extern const char kResponseData[];
+ extern const char kResponseMetadata[];
+
+ namespace Format {
+ extern const char kEnumJpeg[];
+ extern const char kEnumPng[];
+ } // Format
+ } // captureScreenshot
namespace disable {
extern const char kName[];
- } // disable
+ } // disable
+
+ namespace getNavigationHistory {
+ extern const char kName[];
+ extern const char kResponseCurrentIndex[];
+ extern const char kResponseEntries[];
+ } // getNavigationHistory
namespace handleJavaScriptDialog {
extern const char kName[];
extern const char kParamAccept[];
extern const char kParamPromptText[];
- } // handleJavaScriptDialog
+ } // handleJavaScriptDialog
namespace navigate {
extern const char kName[];
extern const char kParamUrl[];
- } // navigate
+ } // navigate
+
+ namespace navigateToHistoryEntry {
+ extern const char kName[];
+ extern const char kParamEntryId[];
+ } // navigateToHistoryEntry
+
+ namespace queryUsageAndQuota {
+ extern const char kName[];
+ extern const char kParamSecurityOrigin[];
+ extern const char kResponseQuota[];
+ extern const char kResponseUsage[];
+ } // queryUsageAndQuota
namespace reload {
extern const char kName[];
- } // reload
+ extern const char kParamIgnoreCache[];
+ extern const char kParamScriptPreprocessor[];
+ extern const char kParamScriptToEvaluateOnLoad[];
+ } // reload
- namespace getNavigationHistory {
+ namespace screencastFrame {
extern const char kName[];
- extern const char kResponseCurrentIndex[];
- extern const char kResponseEntries[];
- extern const char kResponseEntryId[];
- extern const char kResponseEntryURL[];
- extern const char kResponseEntryTitle[];
- } // getNavigationHistory
+ extern const char kParamData[];
+ extern const char kParamMetadata[];
+ } // screencastFrame
- namespace navigateToHistoryEntry {
+ namespace screencastVisibilityChanged {
extern const char kName[];
- extern const char kParamEntryId[];
- } // navigateToHistoryEntry
+ extern const char kParamVisible[];
+ } // screencastVisibilityChanged
- namespace captureScreenshot {
+ namespace startScreencast {
extern const char kName[];
extern const char kParamFormat[];
- extern const char kParamQuality[];
- extern const char kParamMaxWidth[];
extern const char kParamMaxHeight[];
- } // captureScreenshot
+ extern const char kParamMaxWidth[];
+ extern const char kParamQuality[];
- namespace startScreencast {
- extern const char kName[];
- } // startScreencast
+ namespace Format {
+ extern const char kEnumJpeg[];
+ extern const char kEnumPng[];
+ } // Format
+ } // startScreencast
namespace stopScreencast {
extern const char kName[];
- } // stopScreencast
+ } // stopScreencast
+} // Page
- namespace screencastFrame {
- extern const char kName[];
- } // screencastFrame
+namespace SystemInfo {
+ extern const char kName[];
- namespace screencastVisibilityChanged {
+ namespace GPUDevice {
+ extern const char kParamDeviceId[];
+ extern const char kParamDeviceString[];
+ extern const char kParamVendorId[];
+ extern const char kParamVendorString[];
+ } // GPUDevice
+
+ namespace GPUInfo {
+ extern const char kParamAuxAttributes[];
+ extern const char kParamDevices[];
+ extern const char kParamFeatureStatus[];
+ } // GPUInfo
+
+ namespace SystemInfo {
+ extern const char kParamGpu[];
+ extern const char kParamModelName[];
+ } // SystemInfo
+
+ namespace getInfo {
extern const char kName[];
- extern const char kParamVisible[];
- } // screencastVisibilityChanged
-} // Page
+ extern const char kResponseInfo[];
+ } // getInfo
+} // SystemInfo
namespace Tracing {
extern const char kName[];
- namespace start {
+ namespace dataCollected {
extern const char kName[];
- extern const char kCategories[];
- extern const char kTraceOptions[];
- } // start
+ extern const char kParamValue[];
+ } // dataCollected
namespace end {
extern const char kName[];
- }
+ } // end
- namespace tracingComplete {
+ namespace start {
extern const char kName[];
- }
+ extern const char kParamCategories[];
+ extern const char kParamOptions[];
+ } // start
- namespace dataCollected {
+ namespace tracingComplete {
extern const char kName[];
- extern const char kValue[];
- }
-
-} // Tracing
+ } // tracingComplete
+} // Tracing
namespace Worker {
+ extern const char kName[];
- namespace disconnectedFromWorker {
+ namespace disconnectFromWorker {
extern const char kName[];
- } // disconnectedFromWorker
-
-} // Worker
-
+ extern const char kParamWorkerId[];
+ } // disconnectFromWorker
-namespace SystemInfo {
- extern const char kName[];
+ namespace disconnectedFromWorker {
+ extern const char kName[];
+ } // disconnectedFromWorker
+} // Worker
-namespace getInfo {
- extern const char kName[];
-} // getInfo
-} // SystemInfo
} // devtools
} // content
diff --git a/chromium/content/browser/devtools/devtools_resources.gyp b/chromium/content/browser/devtools/devtools_resources.gyp
index 19b114c9dfa..30b42209453 100644
--- a/chromium/content/browser/devtools/devtools_resources.gyp
+++ b/chromium/content/browser/devtools/devtools_resources.gyp
@@ -8,7 +8,7 @@
'target_name': 'devtools_resources',
'type': 'none',
'dependencies': [
- '../../../third_party/WebKit/Source/devtools/devtools.gyp:generate_devtools_grd',
+ '../../../third_party/WebKit/public/blink_devtools.gyp:blink_generate_devtools_grd',
],
'variables': {
'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/webkit',
diff --git a/chromium/content/browser/devtools/devtools_system_info_handler.cc b/chromium/content/browser/devtools/devtools_system_info_handler.cc
index 1fee6424676..4ade158c2bc 100644
--- a/chromium/content/browser/devtools/devtools_system_info_handler.cc
+++ b/chromium/content/browser/devtools/devtools_system_info_handler.cc
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/values.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "gpu/config/gpu_info.h"
@@ -19,6 +20,7 @@ const char kAuxAttributes[] = "auxAttributes";
const char kDeviceId[] = "deviceId";
const char kDeviceString[] = "deviceString";
const char kDevices[] = "devices";
+const char kFeatureStatus[] = "featureStatus";
const char kGPU[] = "gpu";
const char kModelName[] = "modelName";
const char kVendorId[] = "vendorId";
@@ -114,6 +116,8 @@ DevToolsSystemInfoHandler::OnGetInfo(
gpu_info.EnumerateFields(&enumerator);
gpu_dict->Set(kAuxAttributes, aux_attributes);
+ gpu_dict->Set(kFeatureStatus, GetFeatureStatus());
+
base::DictionaryValue* system_dict = new base::DictionaryValue;
system_dict->SetString(kModelName, gpu_info.machine_model);
system_dict->Set(kGPU, gpu_dict);
diff --git a/chromium/content/browser/devtools/devtools_tracing_handler.cc b/chromium/content/browser/devtools/devtools_tracing_handler.cc
index 0657b8e48d2..e9f6cf10b29 100644
--- a/chromium/content/browser/devtools/devtools_tracing_handler.cc
+++ b/chromium/content/browser/devtools/devtools_tracing_handler.cc
@@ -6,14 +6,18 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "base/location.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "content/browser/devtools/devtools_http_handler_impl.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
-#include "content/public/browser/trace_controller.h"
-#include "content/public/browser/trace_subscriber.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/tracing_controller.h"
namespace content {
@@ -23,10 +27,23 @@ const char kRecordUntilFull[] = "record-until-full";
const char kRecordContinuously[] = "record-continuously";
const char kEnableSampling[] = "enable-sampling";
+void ReadFile(
+ const base::FilePath& path,
+ const base::Callback<void(const scoped_refptr<base::RefCountedString>&)>
+ callback) {
+ std::string trace_data;
+ if (!base::ReadFileToString(path, &trace_data))
+ LOG(ERROR) << "Failed to read file: " << path.value();
+ base::DeleteFile(path, false);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, make_scoped_refptr(
+ base::RefCountedString::TakeString(&trace_data))));
+}
+
} // namespace
DevToolsTracingHandler::DevToolsTracingHandler()
- : is_running_(false) {
+ : weak_factory_(this) {
RegisterCommandHandler(devtools::Tracing::start::kName,
base::Bind(&DevToolsTracingHandler::OnStart,
base::Unretained(this)));
@@ -38,28 +55,60 @@ DevToolsTracingHandler::DevToolsTracingHandler()
DevToolsTracingHandler::~DevToolsTracingHandler() {
}
-void DevToolsTracingHandler::OnEndTracingComplete() {
- is_running_ = false;
+void DevToolsTracingHandler::BeginReadingRecordingResult(
+ const base::FilePath& path) {
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&ReadFile, path,
+ base::Bind(&DevToolsTracingHandler::ReadRecordingResult,
+ weak_factory_.GetWeakPtr())));
+}
+
+void DevToolsTracingHandler::ReadRecordingResult(
+ const scoped_refptr<base::RefCountedString>& trace_data) {
+ if (trace_data->data().size()) {
+ scoped_ptr<base::Value> trace_value(base::JSONReader::Read(
+ trace_data->data()));
+ DictionaryValue* dictionary = NULL;
+ bool ok = trace_value->GetAsDictionary(&dictionary);
+ DCHECK(ok);
+ ListValue* list = NULL;
+ ok = dictionary->GetList("traceEvents", &list);
+ DCHECK(ok);
+ std::string buffer;
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ std::string item;
+ base::Value* item_value;
+ list->Get(i, &item_value);
+ base::JSONWriter::Write(item_value, &item);
+ if (buffer.size())
+ buffer.append(",");
+ buffer.append(item);
+ if (i % 1000 == 0) {
+ OnTraceDataCollected(buffer);
+ buffer.clear();
+ }
+ }
+ if (buffer.size())
+ OnTraceDataCollected(buffer);
+ }
+
SendNotification(devtools::Tracing::tracingComplete::kName, NULL);
}
void DevToolsTracingHandler::OnTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& trace_fragment) {
- if (is_running_) {
- // Hand-craft protocol notification message so we can substitute JSON
- // that we already got as string as a bare object, not a quoted string.
- std::string message = base::StringPrintf(
- "{ \"method\": \"%s\", \"params\": { \"%s\": [ %s ] } }",
- devtools::Tracing::dataCollected::kName,
- devtools::Tracing::dataCollected::kValue,
- trace_fragment->data().c_str());
- SendRawMessage(message);
- }
+ const std::string& trace_fragment) {
+ // Hand-craft protocol notification message so we can substitute JSON
+ // that we already got as string as a bare object, not a quoted string.
+ std::string message = base::StringPrintf(
+ "{ \"method\": \"%s\", \"params\": { \"%s\": [ %s ] } }",
+ devtools::Tracing::dataCollected::kName,
+ devtools::Tracing::dataCollected::kParamValue,
+ trace_fragment.c_str());
+ SendRawMessage(message);
}
-// Note, if you add more options here you also need to update:
-// base/debug/trace_event_impl:TraceOptionsFromString
-base::debug::TraceLog::Options DevToolsTracingHandler::TraceOptionsFromString(
+TracingController::Options DevToolsTracingHandler::TraceOptionsFromString(
const std::string& options) {
std::vector<std::string> split;
std::vector<std::string>::iterator iter;
@@ -68,18 +117,14 @@ base::debug::TraceLog::Options DevToolsTracingHandler::TraceOptionsFromString(
base::SplitString(options, ',', &split);
for (iter = split.begin(); iter != split.end(); ++iter) {
if (*iter == kRecordUntilFull) {
- ret |= base::debug::TraceLog::RECORD_UNTIL_FULL;
+ ret &= ~TracingController::RECORD_CONTINUOUSLY;
} else if (*iter == kRecordContinuously) {
- ret |= base::debug::TraceLog::RECORD_CONTINUOUSLY;
+ ret |= TracingController::RECORD_CONTINUOUSLY;
} else if (*iter == kEnableSampling) {
- ret |= base::debug::TraceLog::ENABLE_SAMPLING;
+ ret |= TracingController::ENABLE_SAMPLING;
}
}
- if (!(ret & base::debug::TraceLog::RECORD_UNTIL_FULL) &&
- !(ret & base::debug::TraceLog::RECORD_CONTINUOUSLY))
- ret |= base::debug::TraceLog::RECORD_UNTIL_FULL;
-
- return static_cast<base::debug::TraceLog::Options>(ret);
+ return static_cast<TracingController::Options>(ret);
}
scoped_refptr<DevToolsProtocol::Response>
@@ -88,25 +133,28 @@ DevToolsTracingHandler::OnStart(
std::string categories;
base::DictionaryValue* params = command->params();
if (params)
- params->GetString(devtools::Tracing::start::kCategories, &categories);
+ params->GetString(devtools::Tracing::start::kParamCategories, &categories);
- base::debug::TraceLog::Options options =
- base::debug::TraceLog::RECORD_UNTIL_FULL;
- if (params && params->HasKey(devtools::Tracing::start::kTraceOptions)) {
+ TracingController::Options options = TracingController::DEFAULT_OPTIONS;
+ if (params && params->HasKey(devtools::Tracing::start::kParamOptions)) {
std::string options_param;
- params->GetString(devtools::Tracing::start::kTraceOptions, &options_param);
+ params->GetString(devtools::Tracing::start::kParamOptions, &options_param);
options = TraceOptionsFromString(options_param);
}
- TraceController::GetInstance()->BeginTracing(this, categories, options);
- is_running_ = true;
+ TracingController::GetInstance()->EnableRecording(
+ categories, options,
+ TracingController::EnableRecordingDoneCallback());
return command->SuccessResponse(NULL);
}
scoped_refptr<DevToolsProtocol::Response>
DevToolsTracingHandler::OnEnd(
scoped_refptr<DevToolsProtocol::Command> command) {
- TraceController::GetInstance()->EndTracingAsync(this);
+ TracingController::GetInstance()->DisableRecording(
+ base::FilePath(),
+ base::Bind(&DevToolsTracingHandler::BeginReadingRecordingResult,
+ weak_factory_.GetWeakPtr()));
return command->SuccessResponse(NULL);
}
diff --git a/chromium/content/browser/devtools/devtools_tracing_handler.h b/chromium/content/browser/devtools/devtools_tracing_handler.h
index 43cd6150eda..b551e7579e2 100644
--- a/chromium/content/browser/devtools/devtools_tracing_handler.h
+++ b/chromium/content/browser/devtools/devtools_tracing_handler.h
@@ -5,36 +5,36 @@
#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_TRACING_HANDLER_H_
#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_TRACING_HANDLER_H_
-#include "base/debug/trace_event.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/devtools/devtools_protocol.h"
-#include "content/public/browser/trace_subscriber.h"
+#include "content/public/browser/tracing_controller.h"
+
+namespace base {
+class RefCountedString;
+}
namespace content {
// This class bridges DevTools remote debugging server with the trace
// infrastructure.
-class DevToolsTracingHandler
- : public TraceSubscriber,
- public DevToolsProtocol::Handler {
+class DevToolsTracingHandler : public DevToolsProtocol::Handler {
public:
DevToolsTracingHandler();
virtual ~DevToolsTracingHandler();
- // TraceSubscriber:
- virtual void OnEndTracingComplete() OVERRIDE;;
- virtual void OnTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& trace_fragment) OVERRIDE;
-
private:
+ void BeginReadingRecordingResult(const base::FilePath& path);
+ void ReadRecordingResult(const scoped_refptr<base::RefCountedString>& result);
+ void OnTraceDataCollected(const std::string& trace_fragment);
+
scoped_refptr<DevToolsProtocol::Response> OnStart(
scoped_refptr<DevToolsProtocol::Command> command);
scoped_refptr<DevToolsProtocol::Response> OnEnd(
scoped_refptr<DevToolsProtocol::Command> command);
- base::debug::TraceLog::Options TraceOptionsFromString(
- const std::string& options);
+ TracingController::Options TraceOptionsFromString(const std::string& options);
- bool is_running_;
+ base::WeakPtrFactory<DevToolsTracingHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DevToolsTracingHandler);
};
diff --git a/chromium/content/browser/devtools/render_view_devtools_agent_host.cc b/chromium/content/browser/devtools/render_view_devtools_agent_host.cc
index 5570ee839ed..39ced5eb581 100644
--- a/chromium/content/browser/devtools/render_view_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_view_devtools_agent_host.cc
@@ -23,6 +23,11 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_widget_host_iterator.h"
+#if defined(OS_ANDROID)
+#include "content/browser/power_save_blocker_impl.h"
+#include "content/public/browser/render_widget_host_view.h"
+#endif
+
namespace content {
typedef std::vector<RenderViewDevToolsAgentHost*> Instances;
@@ -43,28 +48,6 @@ static RenderViewDevToolsAgentHost* FindAgentHost(RenderViewHost* rvh) {
} // namespace
-class RenderViewDevToolsAgentHost::DevToolsAgentHostRvhObserver
- : public RenderViewHostObserver {
- public:
- DevToolsAgentHostRvhObserver(RenderViewHost* rvh,
- RenderViewDevToolsAgentHost* agent_host)
- : RenderViewHostObserver(rvh),
- agent_host_(agent_host) {
- }
- virtual ~DevToolsAgentHostRvhObserver() {}
-
- // RenderViewHostObserver overrides.
- virtual void RenderViewHostDestroyed(RenderViewHost* rvh) OVERRIDE {
- agent_host_->RenderViewHostDestroyed(rvh);
- }
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
- return agent_host_->OnRvhMessageReceived(message);
- }
- private:
- RenderViewDevToolsAgentHost* agent_host_;
- DISALLOW_COPY_AND_ASSIGN(DevToolsAgentHostRvhObserver);
-};
-
// static
scoped_refptr<DevToolsAgentHost>
DevToolsAgentHost::GetOrCreateFor(RenderViewHost* rvh) {
@@ -147,9 +130,6 @@ RenderViewDevToolsAgentHost::RenderViewDevToolsAgentHost(
overrides_handler_->SetNotifier(notifier);
tracing_handler_->SetNotifier(notifier);
g_instances.Get().push_back(this);
- RenderViewHostDelegate* delegate = render_view_host_->GetDelegate();
- if (delegate && delegate->GetAsWebContents())
- WebContentsObserver::Observe(delegate->GetAsWebContents());
AddRef(); // Balanced in RenderViewHostDestroyed.
}
@@ -193,11 +173,26 @@ void RenderViewDevToolsAgentHost::OnClientAttached() {
render_view_host_->GetProcess()->GetID());
// TODO(kaznacheev): Move this call back to DevToolsManagerImpl when
- // ExtensionProcessManager no longer relies on this notification.
+ // extensions::ProcessManager no longer relies on this notification.
DevToolsManagerImpl::GetInstance()->NotifyObservers(this, true);
+
+#if defined(OS_ANDROID)
+ power_save_blocker_.reset(
+ static_cast<PowerSaveBlockerImpl*>(
+ PowerSaveBlocker::Create(
+ PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
+ "DevTools").release()));
+ if (render_view_host_->GetView()) {
+ power_save_blocker_.get()->
+ InitDisplaySleepBlocker(render_view_host_->GetView()->GetNativeView());
+ }
+#endif
}
void RenderViewDevToolsAgentHost::OnClientDetached() {
+#if defined(OS_ANDROID)
+ power_save_blocker_.reset();
+#endif
overrides_handler_->OnClientDetached();
ClientDetachedFromRenderer();
}
@@ -224,7 +219,7 @@ void RenderViewDevToolsAgentHost::ClientDetachedFromRenderer() {
}
// TODO(kaznacheev): Move this call back to DevToolsManagerImpl when
- // ExtensionProcessManager no longer relies on this notification.
+ // extensions::ProcessManager no longer relies on this notification.
DevToolsManagerImpl::GetInstance()->NotifyObservers(this, false);
}
@@ -249,6 +244,28 @@ void RenderViewDevToolsAgentHost::AboutToNavigateRenderView(
ConnectRenderViewHost(dest_rvh);
}
+void RenderViewDevToolsAgentHost::RenderViewHostChanged(
+ RenderViewHost* old_host,
+ RenderViewHost* new_host) {
+ if (new_host != render_view_host_) {
+ // AboutToNavigateRenderView was not called for renderer-initiated
+ // navigation.
+ DisconnectRenderViewHost();
+ ConnectRenderViewHost(new_host);
+ }
+}
+
+void RenderViewDevToolsAgentHost::RenderViewDeleted(RenderViewHost* rvh) {
+ if (rvh != render_view_host_)
+ return;
+
+ DCHECK(render_view_host_);
+ scoped_refptr<RenderViewDevToolsAgentHost> protect(this);
+ NotifyCloseListener();
+ ClearRenderViewHost();
+ Release();
+}
+
void RenderViewDevToolsAgentHost::RenderProcessGone(
base::TerminationStatus status) {
switch(status) {
@@ -287,7 +304,9 @@ void RenderViewDevToolsAgentHost::Observe(int type,
void RenderViewDevToolsAgentHost::SetRenderViewHost(RenderViewHost* rvh) {
DCHECK(!render_view_host_);
render_view_host_ = rvh;
- rvh_observer_.reset(new DevToolsAgentHostRvhObserver(rvh, this));
+
+ WebContentsObserver::Observe(WebContents::FromRenderViewHost(rvh));
+
registrar_.Add(
this,
content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
@@ -300,7 +319,6 @@ void RenderViewDevToolsAgentHost::ClearRenderViewHost() {
this,
content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
content::Source<RenderWidgetHost>(render_view_host_));
- rvh_observer_.reset(NULL);
render_view_host_ = NULL;
}
@@ -315,15 +333,6 @@ void RenderViewDevToolsAgentHost::DisconnectRenderViewHost() {
ClearRenderViewHost();
}
-void RenderViewDevToolsAgentHost::RenderViewHostDestroyed(
- RenderViewHost* rvh) {
- DCHECK(render_view_host_);
- scoped_refptr<RenderViewDevToolsAgentHost> protect(this);
- NotifyCloseListener();
- ClearRenderViewHost();
- Release();
-}
-
void RenderViewDevToolsAgentHost::RenderViewCrashed() {
scoped_refptr<DevToolsProtocol::Notification> notification =
DevToolsProtocol::CreateNotification(
@@ -332,8 +341,11 @@ void RenderViewDevToolsAgentHost::RenderViewCrashed() {
DispatchOnInspectorFrontend(this, notification->Serialize());
}
-bool RenderViewDevToolsAgentHost::OnRvhMessageReceived(
+bool RenderViewDevToolsAgentHost::OnMessageReceived(
const IPC::Message& msg) {
+ if (!render_view_host_)
+ return false;
+
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderViewDevToolsAgentHost, msg)
IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
@@ -352,7 +364,17 @@ bool RenderViewDevToolsAgentHost::OnRvhMessageReceived(
void RenderViewDevToolsAgentHost::OnSwapCompositorFrame(
const IPC::Message& message) {
- overrides_handler_->OnSwapCompositorFrame(message);
+ ViewHostMsg_SwapCompositorFrame::Param param;
+ if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
+ return;
+ overrides_handler_->OnSwapCompositorFrame(param.b.metadata);
+}
+
+void RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame(
+ const cc::CompositorFrameMetadata& frame_metadata) {
+ if (!render_view_host_)
+ return;
+ overrides_handler_->OnSwapCompositorFrame(frame_metadata);
}
void RenderViewDevToolsAgentHost::OnSaveAgentRuntimeState(
diff --git a/chromium/content/browser/devtools/render_view_devtools_agent_host.h b/chromium/content/browser/devtools/render_view_devtools_agent_host.h
index 3f763cabb36..88ba70cc81a 100644
--- a/chromium/content/browser/devtools/render_view_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_view_devtools_agent_host.h
@@ -14,15 +14,22 @@
#include "content/common/content_export.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/render_view_host_observer.h"
#include "content/public/browser/web_contents_observer.h"
+namespace cc {
+class CompositorFrameMetadata;
+}
+
namespace content {
class DevToolsTracingHandler;
class RendererOverridesHandler;
class RenderViewHost;
+#if defined(OS_ANDROID)
+class PowerSaveBlockerImpl;
+#endif
+
class CONTENT_EXPORT RenderViewDevToolsAgentHost
: public IPCDevToolsAgentHost,
private WebContentsObserver,
@@ -35,9 +42,11 @@ class CONTENT_EXPORT RenderViewDevToolsAgentHost
RenderViewHost* render_view_host() { return render_view_host_; }
+ void SynchronousSwapCompositorFrame(
+ const cc::CompositorFrameMetadata& frame_metadata);
+
private:
friend class DevToolsAgentHost;
- class DevToolsAgentHostRvhObserver;
virtual ~RenderViewDevToolsAgentHost();
@@ -54,8 +63,12 @@ class CONTENT_EXPORT RenderViewDevToolsAgentHost
// WebContentsObserver overrides.
virtual void AboutToNavigateRenderView(RenderViewHost* dest_rvh) OVERRIDE;
+ virtual void RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) OVERRIDE;
+ virtual void RenderViewDeleted(RenderViewHost* rvh) OVERRIDE;
virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
virtual void DidAttachInterstitialPage() OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
// NotificationObserver overrides:
virtual void Observe(int type,
@@ -65,9 +78,7 @@ class CONTENT_EXPORT RenderViewDevToolsAgentHost
void SetRenderViewHost(RenderViewHost* rvh);
void ClearRenderViewHost();
- void RenderViewHostDestroyed(RenderViewHost* rvh);
void RenderViewCrashed();
- bool OnRvhMessageReceived(const IPC::Message& message);
void OnSwapCompositorFrame(const IPC::Message& message);
void OnDispatchOnInspectorFrontend(const std::string& message);
@@ -78,9 +89,11 @@ class CONTENT_EXPORT RenderViewDevToolsAgentHost
void ClientDetachedFromRenderer();
RenderViewHost* render_view_host_;
- scoped_ptr<DevToolsAgentHostRvhObserver> rvh_observer_;
scoped_ptr<RendererOverridesHandler> overrides_handler_;
scoped_ptr<DevToolsTracingHandler> tracing_handler_;
+#if defined(OS_ANDROID)
+ scoped_ptr<PowerSaveBlockerImpl> power_save_blocker_;
+#endif
std::string state_;
NotificationRegistrar registrar_;
diff --git a/chromium/content/browser/devtools/renderer_overrides_handler.cc b/chromium/content/browser/devtools/renderer_overrides_handler.cc
index c25adde7619..4901f34cc12 100644
--- a/chromium/content/browser/devtools/renderer_overrides_handler.cc
+++ b/chromium/content/browser/devtools/renderer_overrides_handler.cc
@@ -4,8 +4,10 @@
#include "content/browser/devtools/renderer_overrides_handler.h"
+#include <map>
#include <string>
+#include "base/barrier_closure.h"
#include "base/base64.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -28,21 +30,25 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/common/content_client.h"
#include "content/public/common/page_transition_types.h"
#include "content/public/common/referrer.h"
#include "ipc/ipc_sender.h"
+#include "net/base/net_util.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/size_conversions.h"
#include "ui/snapshot/snapshot.h"
#include "url/gurl.h"
+#include "webkit/browser/quota/quota_manager.h"
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
namespace content {
@@ -52,11 +58,12 @@ static const char kPng[] = "png";
static const char kJpeg[] = "jpeg";
static int kDefaultScreenshotQuality = 80;
static int kFrameRateThresholdMs = 100;
+static int kCaptureRetryLimit = 2;
void ParseGenericInputParams(base::DictionaryValue* params,
WebInputEvent* event) {
int modifiers = 0;
- if (params->GetInteger(devtools::Input::kParamModifiers,
+ if (params->GetInteger(devtools::Input::dispatchMouseEvent::kParamModifiers,
&modifiers)) {
if (modifiers & 1)
event->modifiers |= WebInputEvent::AltKey;
@@ -68,7 +75,7 @@ void ParseGenericInputParams(base::DictionaryValue* params,
event->modifiers |= WebInputEvent::ShiftKey;
}
- params->GetDouble(devtools::Input::kParamTimestamp,
+ params->GetDouble(devtools::Input::dispatchMouseEvent::kParamTimestamp,
&event->timeStampSeconds);
}
@@ -76,6 +83,7 @@ void ParseGenericInputParams(base::DictionaryValue* params,
RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent)
: agent_(agent),
+ capture_retry_count_(0),
weak_factory_(this) {
RegisterCommandHandler(
devtools::DOM::setFileInputFiles::kName,
@@ -117,6 +125,11 @@ RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent)
&RendererOverridesHandler::PageCaptureScreenshot,
base::Unretained(this)));
RegisterCommandHandler(
+ devtools::Page::canScreencast::kName,
+ base::Bind(
+ &RendererOverridesHandler::PageCanScreencast,
+ base::Unretained(this)));
+ RegisterCommandHandler(
devtools::Page::startScreencast::kName,
base::Bind(
&RendererOverridesHandler::PageStartScreencast,
@@ -127,6 +140,11 @@ RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent)
&RendererOverridesHandler::PageStopScreencast,
base::Unretained(this)));
RegisterCommandHandler(
+ devtools::Page::queryUsageAndQuota::kName,
+ base::Bind(
+ &RendererOverridesHandler::PageQueryUsageAndQuota,
+ base::Unretained(this)));
+ RegisterCommandHandler(
devtools::Input::dispatchMouseEvent::kName,
base::Bind(
&RendererOverridesHandler::InputDispatchMouseEvent,
@@ -145,11 +163,8 @@ void RendererOverridesHandler::OnClientDetached() {
}
void RendererOverridesHandler::OnSwapCompositorFrame(
- const IPC::Message& message) {
- ViewHostMsg_SwapCompositorFrame::Param param;
- if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
- return;
- last_compositor_frame_metadata_ = param.b.metadata;
+ const cc::CompositorFrameMetadata& frame_metadata) {
+ last_compositor_frame_metadata_ = frame_metadata;
if (screencast_command_)
InnerSwapCompositorFrame();
@@ -167,13 +182,16 @@ void RendererOverridesHandler::InnerSwapCompositorFrame() {
return;
}
+ RenderViewHost* host = agent_->GetRenderViewHost();
+ if (!host->GetView())
+ return;
+
last_frame_time_ = base::TimeTicks::Now();
std::string format;
int quality = kDefaultScreenshotQuality;
double scale = 1;
ParseCaptureParameters(screencast_command_.get(), &format, &quality, &scale);
- RenderViewHost* host = agent_->GetRenderViewHost();
RenderWidgetHostViewPort* view_port =
RenderWidgetHostViewPort::FromRWHV(host->GetView());
@@ -194,9 +212,6 @@ void RendererOverridesHandler::ParseCaptureParameters(
std::string* format,
int* quality,
double* scale) {
- RenderViewHost* host = agent_->GetRenderViewHost();
- gfx::Rect view_bounds = host->GetView()->GetViewBounds();
-
*quality = kDefaultScreenshotQuality;
*scale = 1;
double max_width = -1;
@@ -213,12 +228,13 @@ void RendererOverridesHandler::ParseCaptureParameters(
&max_height);
}
- float device_sf = last_compositor_frame_metadata_.device_scale_factor;
-
+ RenderViewHost* host = agent_->GetRenderViewHost();
+ CHECK(host->GetView());
+ gfx::Rect view_bounds = host->GetView()->GetViewBounds();
if (max_width > 0)
- *scale = std::min(*scale, max_width / view_bounds.width() / device_sf);
+ *scale = std::min(*scale, max_width / view_bounds.width());
if (max_height > 0)
- *scale = std::min(*scale, max_height / view_bounds.height() / device_sf);
+ *scale = std::min(*scale, max_height / view_bounds.height());
if (format->empty())
*format = kPng;
@@ -274,8 +290,8 @@ RendererOverridesHandler::PageHandleJavaScriptDialog(
bool accept;
if (!params || !params->GetBoolean(paramAccept, &accept))
return command->InvalidParamResponse(paramAccept);
- string16 prompt_override;
- string16* prompt_override_ptr = &prompt_override;
+ base::string16 prompt_override;
+ base::string16* prompt_override_ptr = &prompt_override;
if (!params || !params->GetString(
devtools::Page::handleJavaScriptDialog::kParamPromptText,
prompt_override_ptr)) {
@@ -356,13 +372,13 @@ RendererOverridesHandler::PageGetNavigationHistory(
const NavigationEntry* entry = controller.GetEntryAtIndex(i);
base::DictionaryValue* entry_value = new base::DictionaryValue();
entry_value->SetInteger(
- devtools::Page::getNavigationHistory::kResponseEntryId,
+ devtools::Page::NavigationEntry::kParamId,
entry->GetUniqueID());
entry_value->SetString(
- devtools::Page::getNavigationHistory::kResponseEntryURL,
+ devtools::Page::NavigationEntry::kParamUrl,
entry->GetURL().spec());
entry_value->SetString(
- devtools::Page::getNavigationHistory::kResponseEntryTitle,
+ devtools::Page::NavigationEntry::kParamTitle,
entry->GetTitle());
entries->Append(entry_value);
}
@@ -406,39 +422,40 @@ RendererOverridesHandler::PageNavigateToHistoryEntry(
scoped_refptr<DevToolsProtocol::Response>
RendererOverridesHandler::PageCaptureScreenshot(
scoped_refptr<DevToolsProtocol::Command> command) {
+ RenderViewHost* host = agent_->GetRenderViewHost();
+ if (!host->GetView())
+ return command->InternalErrorResponse("Unable to access the view");
+
std::string format;
int quality = kDefaultScreenshotQuality;
double scale = 1;
ParseCaptureParameters(command.get(), &format, &quality, &scale);
- RenderViewHost* host = agent_->GetRenderViewHost();
gfx::Rect view_bounds = host->GetView()->GetViewBounds();
+ gfx::Size snapshot_size = gfx::ToFlooredSize(
+ gfx::ScaleSize(view_bounds.size(), scale));
// Grab screen pixels if available for current platform.
// TODO(pfeldman): support format, scale and quality in ui::GrabViewSnapshot.
std::vector<unsigned char> png;
bool is_unscaled_png = scale == 1 && format == kPng;
if (is_unscaled_png && ui::GrabViewSnapshot(host->GetView()->GetNativeView(),
- &png, view_bounds)) {
+ &png,
+ gfx::Rect(snapshot_size))) {
std::string base64_data;
- bool success = base::Base64Encode(
+ base::Base64Encode(
base::StringPiece(reinterpret_cast<char*>(&*png.begin()), png.size()),
&base64_data);
- if (success) {
- base::DictionaryValue* result = new base::DictionaryValue();
- result->SetString(
- devtools::Page::kData, base64_data);
- return command->SuccessResponse(result);
- }
- return command->InternalErrorResponse("Unable to base64encode screenshot");
+ base::DictionaryValue* result = new base::DictionaryValue();
+ result->SetString(
+ devtools::Page::captureScreenshot::kResponseData, base64_data);
+ return command->SuccessResponse(result);
}
// Fallback to copying from compositing surface.
RenderWidgetHostViewPort* view_port =
RenderWidgetHostViewPort::FromRWHV(host->GetView());
- gfx::Size snapshot_size = gfx::ToFlooredSize(
- gfx::ScaleSize(view_bounds.size(), scale));
view_port->CopyFromCompositingSurface(
view_bounds, snapshot_size,
base::Bind(&RendererOverridesHandler::ScreenshotCaptured,
@@ -448,6 +465,18 @@ RendererOverridesHandler::PageCaptureScreenshot(
}
scoped_refptr<DevToolsProtocol::Response>
+RendererOverridesHandler::PageCanScreencast(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ base::DictionaryValue* result = new base::DictionaryValue();
+#if defined(OS_ANDROID)
+ result->SetBoolean(devtools::kResult, true);
+#else
+ result->SetBoolean(devtools::kResult, false);
+#endif // defined(OS_ANDROID)
+ return command->SuccessResponse(result);
+}
+
+scoped_refptr<DevToolsProtocol::Response>
RendererOverridesHandler::PageStartScreencast(
scoped_refptr<DevToolsProtocol::Command> command) {
screencast_command_ = command;
@@ -479,6 +508,13 @@ void RendererOverridesHandler::ScreenshotCaptured(
if (command) {
SendAsyncResponse(
command->InternalErrorResponse("Unable to capture screenshot"));
+ } else if (capture_retry_count_) {
+ --capture_retry_count_;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&RendererOverridesHandler::InnerSwapCompositorFrame,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kFrameRateThresholdMs));
}
return;
}
@@ -514,42 +550,56 @@ void RendererOverridesHandler::ScreenshotCaptured(
}
std::string base_64_data;
- if (!base::Base64Encode(base::StringPiece(
- reinterpret_cast<char*>(&data[0]),
- data.size()),
- &base_64_data)) {
- if (command) {
- SendAsyncResponse(
- command->InternalErrorResponse("Unable to base64 encode"));
- }
- return;
- }
+ base::Base64Encode(
+ base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()),
+ &base_64_data);
base::DictionaryValue* response = new base::DictionaryValue();
- response->SetString(devtools::Page::kData, base_64_data);
+ response->SetString(devtools::Page::screencastFrame::kParamData,
+ base_64_data);
// Consider metadata empty in case it has no device scale factor.
if (metadata.device_scale_factor != 0) {
- response->SetDouble(devtools::Page::kParamDeviceScaleFactor,
- metadata.device_scale_factor);
- response->SetDouble(devtools::Page::kParamPageScaleFactor,
- metadata.page_scale_factor);
- response->SetDouble(devtools::Page::kParamPageScaleFactorMin,
- metadata.min_page_scale_factor);
- response->SetDouble(devtools::Page::kParamPageScaleFactorMax,
- metadata.max_page_scale_factor);
- response->SetDouble(devtools::Page::kParamOffsetTop,
- metadata.location_bar_content_translation.y());
- response->SetDouble(devtools::Page::kParamOffsetBottom,
- metadata.overdraw_bottom_height);
+ base::DictionaryValue* response_metadata = new base::DictionaryValue();
+
+ response_metadata->SetDouble(
+ devtools::Page::ScreencastFrameMetadata::kParamDeviceScaleFactor,
+ metadata.device_scale_factor);
+ response_metadata->SetDouble(
+ devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactor,
+ metadata.page_scale_factor);
+ response_metadata->SetDouble(
+ devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactorMin,
+ metadata.min_page_scale_factor);
+ response_metadata->SetDouble(
+ devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactorMax,
+ metadata.max_page_scale_factor);
+ response_metadata->SetDouble(
+ devtools::Page::ScreencastFrameMetadata::kParamOffsetTop,
+ metadata.location_bar_content_translation.y());
+ response_metadata->SetDouble(
+ devtools::Page::ScreencastFrameMetadata::kParamOffsetBottom,
+ metadata.overdraw_bottom_height);
base::DictionaryValue* viewport = new base::DictionaryValue();
- viewport->SetDouble(devtools::kParamX, metadata.root_scroll_offset.x());
- viewport->SetDouble(devtools::kParamY, metadata.root_scroll_offset.y());
- viewport->SetDouble(devtools::kParamWidth, metadata.viewport_size.width());
- viewport->SetDouble(devtools::kParamHeight,
+ viewport->SetDouble(devtools::DOM::Rect::kParamX,
+ metadata.root_scroll_offset.x());
+ viewport->SetDouble(devtools::DOM::Rect::kParamY,
+ metadata.root_scroll_offset.y());
+ viewport->SetDouble(devtools::DOM::Rect::kParamWidth,
+ metadata.viewport_size.width());
+ viewport->SetDouble(devtools::DOM::Rect::kParamHeight,
metadata.viewport_size.height());
- response->Set(devtools::Page::kParamViewport, viewport);
+ response_metadata->Set(
+ devtools::Page::ScreencastFrameMetadata::kParamViewport, viewport);
+
+ if (command) {
+ response->Set(devtools::Page::captureScreenshot::kResponseMetadata,
+ response_metadata);
+ } else {
+ response->Set(devtools::Page::screencastFrame::kParamMetadata,
+ response_metadata);
+ }
}
if (command) {
@@ -559,7 +609,206 @@ void RendererOverridesHandler::ScreenshotCaptured(
}
}
+// Quota and Usage ------------------------------------------
+
+namespace {
+
+typedef base::Callback<void(scoped_ptr<base::DictionaryValue>)>
+ ResponseCallback;
+
+void QueryUsageAndQuotaCompletedOnIOThread(
+ scoped_ptr<base::DictionaryValue> quota,
+ scoped_ptr<base::DictionaryValue> usage,
+ ResponseCallback callback) {
+
+ scoped_ptr<base::DictionaryValue> response_data(new base::DictionaryValue);
+ response_data->Set(devtools::Page::queryUsageAndQuota::kResponseQuota,
+ quota.release());
+ response_data->Set(devtools::Page::queryUsageAndQuota::kResponseUsage,
+ usage.release());
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, base::Passed(&response_data)));
+}
+
+void DidGetHostUsage(
+ base::ListValue* list,
+ const std::string& client_id,
+ const base::Closure& barrier,
+ int64 value) {
+ base::DictionaryValue* usage_item = new base::DictionaryValue;
+ usage_item->SetString(devtools::Page::UsageItem::kParamId, client_id);
+ usage_item->SetDouble(devtools::Page::UsageItem::kParamValue, value);
+ list->Append(usage_item);
+ barrier.Run();
+}
+
+void DidGetQuotaValue(
+ base::DictionaryValue* dictionary,
+ const std::string& item_name,
+ const base::Closure& barrier,
+ quota::QuotaStatusCode status,
+ int64 value) {
+ if (status == quota::kQuotaStatusOk)
+ dictionary->SetDouble(item_name, value);
+ barrier.Run();
+}
+
+void DidGetUsageAndQuotaForWebApps(
+ base::DictionaryValue* quota,
+ const std::string& item_name,
+ const base::Closure& barrier,
+ quota::QuotaStatusCode status,
+ int64 used_bytes,
+ int64 quota_in_bytes) {
+ if (status == quota::kQuotaStatusOk)
+ quota->SetDouble(item_name, quota_in_bytes);
+ barrier.Run();
+}
+
+std::string GetStorageTypeName(quota::StorageType type) {
+ switch (type) {
+ case quota::kStorageTypeTemporary:
+ return devtools::Page::Usage::kParamTemporary;
+ case quota::kStorageTypePersistent:
+ return devtools::Page::Usage::kParamPersistent;
+ case quota::kStorageTypeSyncable:
+ return devtools::Page::Usage::kParamSyncable;
+ case quota::kStorageTypeQuotaNotManaged:
+ case quota::kStorageTypeUnknown:
+ NOTREACHED();
+ }
+ return "";
+}
+
+std::string GetQuotaClientName(quota::QuotaClient::ID id) {
+ switch (id) {
+ case quota::QuotaClient::kFileSystem:
+ return devtools::Page::UsageItem::Id::kEnumFilesystem;
+ case quota::QuotaClient::kDatabase:
+ return devtools::Page::UsageItem::Id::kEnumDatabase;
+ case quota::QuotaClient::kAppcache:
+ return devtools::Page::UsageItem::Id::kEnumAppcache;
+ case quota::QuotaClient::kIndexedDatabase:
+ return devtools::Page::UsageItem::Id::kEnumIndexeddatabase;
+ default:
+ NOTREACHED();
+ return "";
+ }
+}
+
+void QueryUsageAndQuotaOnIOThread(
+ scoped_refptr<quota::QuotaManager> quota_manager,
+ const GURL& security_origin,
+ const ResponseCallback& callback) {
+ scoped_ptr<base::DictionaryValue> quota(new base::DictionaryValue);
+ scoped_ptr<base::DictionaryValue> usage(new base::DictionaryValue);
+
+ static quota::QuotaClient::ID kQuotaClients[] = {
+ quota::QuotaClient::kFileSystem,
+ quota::QuotaClient::kDatabase,
+ quota::QuotaClient::kAppcache,
+ quota::QuotaClient::kIndexedDatabase
+ };
+
+ static const size_t kStorageTypeCount = quota::kStorageTypeUnknown;
+ std::map<quota::StorageType, base::ListValue*> storage_type_lists;
+
+ for (size_t i = 0; i != kStorageTypeCount; i++) {
+ const quota::StorageType type = static_cast<quota::StorageType>(i);
+ if (type == quota::kStorageTypeQuotaNotManaged)
+ continue;
+ storage_type_lists[type] = new base::ListValue;
+ usage->Set(GetStorageTypeName(type), storage_type_lists[type]);
+ }
+
+ const int kExpectedResults =
+ 2 + arraysize(kQuotaClients) * storage_type_lists.size();
+ base::DictionaryValue* quota_raw_ptr = quota.get();
+
+ // Takes ownership on usage and quota.
+ base::Closure barrier = BarrierClosure(
+ kExpectedResults,
+ base::Bind(&QueryUsageAndQuotaCompletedOnIOThread,
+ base::Passed(&quota),
+ base::Passed(&usage),
+ callback));
+ std::string host = net::GetHostOrSpecFromURL(security_origin);
+
+ quota_manager->GetUsageAndQuotaForWebApps(
+ security_origin,
+ quota::kStorageTypeTemporary,
+ base::Bind(&DidGetUsageAndQuotaForWebApps, quota_raw_ptr,
+ std::string(devtools::Page::Quota::kParamTemporary), barrier));
+
+ quota_manager->GetPersistentHostQuota(
+ host,
+ base::Bind(&DidGetQuotaValue, quota_raw_ptr,
+ std::string(devtools::Page::Quota::kParamPersistent),
+ barrier));
+
+ for (size_t i = 0; i != arraysize(kQuotaClients); i++) {
+ std::map<quota::StorageType, base::ListValue*>::const_iterator iter;
+ for (iter = storage_type_lists.begin();
+ iter != storage_type_lists.end(); ++iter) {
+ const quota::StorageType type = (*iter).first;
+ if (!quota_manager->IsTrackingHostUsage(type, kQuotaClients[i])) {
+ barrier.Run();
+ continue;
+ }
+ quota_manager->GetHostUsage(
+ host, type, kQuotaClients[i],
+ base::Bind(&DidGetHostUsage, (*iter).second,
+ GetQuotaClientName(kQuotaClients[i]),
+ barrier));
+ }
+ }
+}
+
+} // namespace
+
+scoped_refptr<DevToolsProtocol::Response>
+RendererOverridesHandler::PageQueryUsageAndQuota(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ base::DictionaryValue* params = command->params();
+ std::string security_origin;
+ if (!params || !params->GetString(
+ devtools::Page::queryUsageAndQuota::kParamSecurityOrigin,
+ &security_origin)) {
+ return command->InvalidParamResponse(
+ devtools::Page::queryUsageAndQuota::kParamSecurityOrigin);
+ }
+
+ ResponseCallback callback = base::Bind(
+ &RendererOverridesHandler::PageQueryUsageAndQuotaCompleted,
+ weak_factory_.GetWeakPtr(),
+ command);
+
+ scoped_refptr<quota::QuotaManager> quota_manager =
+ agent_->GetRenderViewHost()->GetProcess()->
+ GetStoragePartition()->GetQuotaManager();
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(
+ &QueryUsageAndQuotaOnIOThread,
+ quota_manager,
+ GURL(security_origin),
+ callback));
+
+ return command->AsyncResponsePromise();
+}
+
+void RendererOverridesHandler::PageQueryUsageAndQuotaCompleted(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ scoped_ptr<base::DictionaryValue> response_data) {
+ SendAsyncResponse(command->SuccessResponse(response_data.release()));
+}
+
void RendererOverridesHandler::NotifyScreencastVisibility(bool visible) {
+ if (visible)
+ capture_retry_count_ = kCaptureRetryLimit;
base::DictionaryValue* params = new base::DictionaryValue();
params->SetBoolean(
devtools::Page::screencastVisibilityChanged::kParamVisible, visible);
@@ -577,24 +826,28 @@ RendererOverridesHandler::InputDispatchMouseEvent(
return NULL;
bool device_space = false;
- if (!params->GetBoolean(devtools::Input::kParamDeviceSpace,
- &device_space) ||
+ if (!params->GetBoolean(
+ devtools::Input::dispatchMouseEvent::kParamDeviceSpace,
+ &device_space) ||
!device_space) {
return NULL;
}
RenderViewHost* host = agent_->GetRenderViewHost();
- WebKit::WebMouseEvent mouse_event;
+ blink::WebMouseEvent mouse_event;
ParseGenericInputParams(params, &mouse_event);
std::string type;
- if (params->GetString(devtools::Input::kParamType,
+ if (params->GetString(devtools::Input::dispatchMouseEvent::kParamType,
&type)) {
- if (type == "mousePressed")
+ if (type ==
+ devtools::Input::dispatchMouseEvent::Type::kEnumMousePressed)
mouse_event.type = WebInputEvent::MouseDown;
- else if (type == "mouseReleased")
+ else if (type ==
+ devtools::Input::dispatchMouseEvent::Type::kEnumMouseReleased)
mouse_event.type = WebInputEvent::MouseUp;
- else if (type == "mouseMoved")
+ else if (type ==
+ devtools::Input::dispatchMouseEvent::Type::kEnumMouseMoved)
mouse_event.type = WebInputEvent::MouseMove;
else
return NULL;
@@ -602,8 +855,10 @@ RendererOverridesHandler::InputDispatchMouseEvent(
return NULL;
}
- if (!params->GetInteger(devtools::kParamX, &mouse_event.x) ||
- !params->GetInteger(devtools::kParamY, &mouse_event.y)) {
+ if (!params->GetInteger(devtools::Input::dispatchMouseEvent::kParamX,
+ &mouse_event.x) ||
+ !params->GetInteger(devtools::Input::dispatchMouseEvent::kParamY,
+ &mouse_event.y)) {
return NULL;
}
@@ -649,27 +904,35 @@ RendererOverridesHandler::InputDispatchGestureEvent(
RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
agent_->GetRenderViewHost());
- WebKit::WebGestureEvent event;
+ blink::WebGestureEvent event;
ParseGenericInputParams(params, &event);
std::string type;
- if (params->GetString(devtools::Input::kParamType,
+ if (params->GetString(devtools::Input::dispatchGestureEvent::kParamType,
&type)) {
- if (type == "scrollBegin")
+ if (type ==
+ devtools::Input::dispatchGestureEvent::Type::kEnumScrollBegin)
event.type = WebInputEvent::GestureScrollBegin;
- else if (type == "scrollUpdate")
+ else if (type ==
+ devtools::Input::dispatchGestureEvent::Type::kEnumScrollUpdate)
event.type = WebInputEvent::GestureScrollUpdate;
- else if (type == "scrollEnd")
+ else if (type ==
+ devtools::Input::dispatchGestureEvent::Type::kEnumScrollEnd)
event.type = WebInputEvent::GestureScrollEnd;
- else if (type == "tapDown")
+ else if (type ==
+ devtools::Input::dispatchGestureEvent::Type::kEnumTapDown)
event.type = WebInputEvent::GestureTapDown;
- else if (type == "tap")
+ else if (type ==
+ devtools::Input::dispatchGestureEvent::Type::kEnumTap)
event.type = WebInputEvent::GestureTap;
- else if (type == "pinchBegin")
+ else if (type ==
+ devtools::Input::dispatchGestureEvent::Type::kEnumPinchBegin)
event.type = WebInputEvent::GesturePinchBegin;
- else if (type == "pinchUpdate")
+ else if (type ==
+ devtools::Input::dispatchGestureEvent::Type::kEnumPinchUpdate)
event.type = WebInputEvent::GesturePinchUpdate;
- else if (type == "pinchEnd")
+ else if (type ==
+ devtools::Input::dispatchGestureEvent::Type::kEnumPinchEnd)
event.type = WebInputEvent::GesturePinchEnd;
else
return NULL;
@@ -677,8 +940,10 @@ RendererOverridesHandler::InputDispatchGestureEvent(
return NULL;
}
- if (!params->GetInteger(devtools::kParamX, &event.x) ||
- !params->GetInteger(devtools::kParamY, &event.y)) {
+ if (!params->GetInteger(devtools::Input::dispatchGestureEvent::kParamX,
+ &event.x) ||
+ !params->GetInteger(devtools::Input::dispatchGestureEvent::kParamY,
+ &event.y)) {
return NULL;
}
event.globalX = event.x;
diff --git a/chromium/content/browser/devtools/renderer_overrides_handler.h b/chromium/content/browser/devtools/renderer_overrides_handler.h
index a5336bf4542..cce32767c39 100644
--- a/chromium/content/browser/devtools/renderer_overrides_handler.h
+++ b/chromium/content/browser/devtools/renderer_overrides_handler.h
@@ -12,6 +12,7 @@
#include "base/time/time.h"
#include "cc/output/compositor_frame_metadata.h"
#include "content/browser/devtools/devtools_protocol.h"
+#include "content/common/content_export.h"
class SkBitmap;
@@ -27,13 +28,14 @@ class DevToolsTracingHandler;
// Overrides Inspector commands before they are sent to the renderer.
// May override the implementation completely, ignore it, or handle
// additional browser process implementation details.
-class RendererOverridesHandler : public DevToolsProtocol::Handler {
+class CONTENT_EXPORT RendererOverridesHandler
+ : public DevToolsProtocol::Handler {
public:
explicit RendererOverridesHandler(DevToolsAgentHost* agent);
virtual ~RendererOverridesHandler();
void OnClientDetached();
- void OnSwapCompositorFrame(const IPC::Message& message);
+ void OnSwapCompositorFrame(const cc::CompositorFrameMetadata& frame_metadata);
void OnVisibilityChanged(bool visible);
private:
@@ -62,10 +64,14 @@ class RendererOverridesHandler : public DevToolsProtocol::Handler {
scoped_refptr<DevToolsProtocol::Command> command);
scoped_refptr<DevToolsProtocol::Response> PageCaptureScreenshot(
scoped_refptr<DevToolsProtocol::Command> command);
+ scoped_refptr<DevToolsProtocol::Response> PageCanScreencast(
+ scoped_refptr<DevToolsProtocol::Command> command);
scoped_refptr<DevToolsProtocol::Response> PageStartScreencast(
scoped_refptr<DevToolsProtocol::Command> command);
scoped_refptr<DevToolsProtocol::Response> PageStopScreencast(
scoped_refptr<DevToolsProtocol::Command> command);
+ scoped_refptr<DevToolsProtocol::Response> PageQueryUsageAndQuota(
+ scoped_refptr<DevToolsProtocol::Command>);
void ScreenshotCaptured(
scoped_refptr<DevToolsProtocol::Command> command,
@@ -75,6 +81,10 @@ class RendererOverridesHandler : public DevToolsProtocol::Handler {
bool success,
const SkBitmap& bitmap);
+ void PageQueryUsageAndQuotaCompleted(
+ scoped_refptr<DevToolsProtocol::Command>,
+ scoped_ptr<base::DictionaryValue> response_data);
+
void NotifyScreencastVisibility(bool visible);
// Input domain.
@@ -84,10 +94,11 @@ class RendererOverridesHandler : public DevToolsProtocol::Handler {
scoped_refptr<DevToolsProtocol::Command> command);
DevToolsAgentHost* agent_;
- base::WeakPtrFactory<RendererOverridesHandler> weak_factory_;
scoped_refptr<DevToolsProtocol::Command> screencast_command_;
cc::CompositorFrameMetadata last_compositor_frame_metadata_;
base::TimeTicks last_frame_time_;
+ int capture_retry_count_;
+ base::WeakPtrFactory<RendererOverridesHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RendererOverridesHandler);
};
diff --git a/chromium/content/browser/devtools/renderer_overrides_handler_browsertest.cc b/chromium/content/browser/devtools/renderer_overrides_handler_browsertest.cc
new file mode 100644
index 00000000000..24dd9621341
--- /dev/null
+++ b/chromium/content/browser/devtools/renderer_overrides_handler_browsertest.cc
@@ -0,0 +1,100 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/json/json_reader.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/devtools/renderer_overrides_handler.h"
+#include "content/public/browser/devtools_agent_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
+
+namespace content {
+
+class RendererOverridesHandlerTest : public ContentBrowserTest {
+ protected:
+ scoped_refptr<DevToolsProtocol::Response> SendCommand(
+ const std::string& method,
+ DictionaryValue* params) {
+ scoped_ptr<RendererOverridesHandler> handler(CreateHandler());
+ scoped_refptr<DevToolsProtocol::Command> command(
+ DevToolsProtocol::CreateCommand(1, method, params));
+ return handler->HandleCommand(command);
+ }
+
+ void SendAsyncCommand(const std::string& method, DictionaryValue* params) {
+ scoped_ptr<RendererOverridesHandler> handler(CreateHandler());
+ scoped_refptr<DevToolsProtocol::Command> command(
+ DevToolsProtocol::CreateCommand(1, method, params));
+ scoped_refptr<DevToolsProtocol::Response> response =
+ handler->HandleCommand(command);
+ EXPECT_TRUE(response->is_async_promise());
+ base::MessageLoop::current()->Run();
+ }
+
+ bool HasValue(const std::string& path) {
+ base::Value* value = 0;
+ return result_->Get(path, &value);
+ }
+
+ bool HasListItem(const std::string& path_to_list,
+ const std::string& name,
+ const std::string& value) {
+ base::ListValue* list;
+ if (!result_->GetList(path_to_list, &list))
+ return false;
+
+ for (size_t i = 0; i != list->GetSize(); i++) {
+ base::DictionaryValue* item;
+ if (!list->GetDictionary(i, &item))
+ return false;
+ std::string id;
+ if (!item->GetString(name, &id))
+ return false;
+ if (id == value)
+ return true;
+ }
+ return false;
+ }
+
+ scoped_ptr<base::DictionaryValue> result_;
+
+ private:
+ RendererOverridesHandler* CreateHandler() {
+ RenderViewHost* rvh = shell()->web_contents()->GetRenderViewHost();
+ DevToolsAgentHost* agent = DevToolsAgentHost::GetOrCreateFor(rvh).get();
+ scoped_ptr<RendererOverridesHandler> handler(
+ new RendererOverridesHandler(agent));
+ handler->SetNotifier(base::Bind(
+ &RendererOverridesHandlerTest::OnMessageSent, base::Unretained(this)));
+ return handler.release();
+ }
+
+ void OnMessageSent(const std::string& message) {
+ scoped_ptr<base::DictionaryValue> root(
+ static_cast<base::DictionaryValue*>(base::JSONReader::Read(message)));
+ base::DictionaryValue* result;
+ root->GetDictionary("result", &result);
+ result_.reset(result->DeepCopy());
+ base::MessageLoop::current()->QuitNow();
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(RendererOverridesHandlerTest, QueryUsageAndQuota) {
+ DictionaryValue* params = new DictionaryValue();
+ params->SetString("securityOrigin", "http://example.com");
+ SendAsyncCommand("Page.queryUsageAndQuota", params);
+
+ EXPECT_TRUE(HasValue("quota.persistent"));
+ EXPECT_TRUE(HasValue("quota.temporary"));
+ EXPECT_TRUE(HasListItem("usage.temporary", "id", "appcache"));
+ EXPECT_TRUE(HasListItem("usage.temporary", "id", "database"));
+ EXPECT_TRUE(HasListItem("usage.temporary", "id", "indexeddatabase"));
+ EXPECT_TRUE(HasListItem("usage.temporary", "id", "filesystem"));
+ EXPECT_TRUE(HasListItem("usage.persistent", "id", "filesystem"));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/worker_devtools_manager.h b/chromium/content/browser/devtools/worker_devtools_manager.h
index e6d090c2159..955b1db5d47 100644
--- a/chromium/content/browser/devtools/worker_devtools_manager.h
+++ b/chromium/content/browser/devtools/worker_devtools_manager.h
@@ -57,7 +57,7 @@ class WorkerDevToolsManager {
struct InspectedWorker {
InspectedWorker(WorkerProcessHost* host, int route_id, const GURL& url,
- const string16& name)
+ const base::string16& name)
: host(host),
route_id(route_id),
worker_url(url),
@@ -65,7 +65,7 @@ class WorkerDevToolsManager {
WorkerProcessHost* const host;
int const route_id;
GURL worker_url;
- string16 worker_name;
+ base::string16 worker_name;
};
typedef std::list<InspectedWorker> InspectedWorkersList;
@@ -98,13 +98,13 @@ class WorkerDevToolsManager {
InspectedWorkersList inspected_workers_;
struct TerminatedInspectedWorker {
- TerminatedInspectedWorker(WorkerId id, const GURL& url, const string16& name)
+ TerminatedInspectedWorker(WorkerId id, const GURL& url, const base::string16& name)
: old_worker_id(id),
worker_url(url),
worker_name(name) {}
WorkerId old_worker_id;
GURL worker_url;
- string16 worker_name;
+ base::string16 worker_name;
};
typedef std::list<TerminatedInspectedWorker> TerminatedInspectedWorkers;
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 dd1f33e847f..2c31bd627b3 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
@@ -68,7 +68,7 @@ DOMStorageNamespace* DOMStorageContextImpl::GetStorageNamespace(
if (found == namespaces_.end()) {
if (namespace_id == kLocalStorageNamespaceId) {
if (!localstorage_directory_.empty()) {
- if (!file_util::CreateDirectory(localstorage_directory_)) {
+ if (!base::CreateDirectory(localstorage_directory_)) {
LOG(ERROR) << "Failed to create 'Local Storage' directory,"
" falling back to in-memory only.";
localstorage_directory_ = base::FilePath();
@@ -238,6 +238,16 @@ void DOMStorageContextImpl::NotifyAreaCleared(
OnDOMStorageAreaCleared(area, page_url));
}
+void DOMStorageContextImpl::NotifyAliasSessionMerged(
+ int64 namespace_id,
+ DOMStorageNamespace* old_alias_master_namespace) {
+ FOR_EACH_OBSERVER(
+ EventObserver, event_observers_,
+ OnDOMSessionStorageReset(namespace_id));
+ if (old_alias_master_namespace)
+ MaybeShutdownSessionNamespace(old_alias_master_namespace);
+}
+
std::string DOMStorageContextImpl::AllocatePersistentSessionId() {
std::string guid = base::GenerateGUID();
std::replace(guid.begin(), guid.end(), '-', '_');
@@ -262,11 +272,36 @@ void DOMStorageContextImpl::DeleteSessionNamespace(
int64 namespace_id, bool should_persist_data) {
DCHECK_NE(kLocalStorageNamespaceId, namespace_id);
StorageNamespaceMap::const_iterator it = namespaces_.find(namespace_id);
- if (it == namespaces_.end())
+ if (it == namespaces_.end() ||
+ it->second->ready_for_deletion_pending_aliases()) {
return;
- std::string persistent_namespace_id = it->second->persistent_namespace_id();
+ }
+ it->second->set_ready_for_deletion_pending_aliases(true);
+ DOMStorageNamespace* alias_master = it->second->alias_master_namespace();
+ if (alias_master) {
+ DCHECK(it->second->num_aliases() == 0);
+ DCHECK(alias_master->alias_master_namespace() == NULL);
+ if (should_persist_data)
+ alias_master->set_must_persist_at_shutdown(true);
+ if (it->second->DecrementMasterAliasCount())
+ MaybeShutdownSessionNamespace(alias_master);
+ namespaces_.erase(namespace_id);
+ } else {
+ if (should_persist_data)
+ it->second->set_must_persist_at_shutdown(true);
+ MaybeShutdownSessionNamespace(it->second);
+ }
+}
+
+void DOMStorageContextImpl::MaybeShutdownSessionNamespace(
+ DOMStorageNamespace* ns) {
+ if (ns->num_aliases() > 0 || !ns->ready_for_deletion_pending_aliases())
+ return;
+ DCHECK_EQ(ns->num_aliases(), 0);
+ DCHECK(ns->alias_master_namespace() == NULL);
+ std::string persistent_namespace_id = ns->persistent_namespace_id();
if (session_storage_database_.get()) {
- if (!should_persist_data) {
+ if (!ns->must_persist_at_shutdown()) {
task_runner_->PostShutdownBlockingTask(
FROM_HERE,
DOMStorageTaskRunner::COMMIT_SEQUENCE,
@@ -276,7 +311,7 @@ void DOMStorageContextImpl::DeleteSessionNamespace(
persistent_namespace_id));
} else {
// Ensure that the data gets committed before we shut down.
- it->second->Shutdown();
+ ns->Shutdown();
if (!scavenging_started_) {
// Protect the persistent namespace ID from scavenging.
protected_persistent_session_ids_.insert(persistent_namespace_id);
@@ -284,7 +319,7 @@ void DOMStorageContextImpl::DeleteSessionNamespace(
}
}
persistent_namespace_id_to_namespace_id_.erase(persistent_namespace_id);
- namespaces_.erase(namespace_id);
+ namespaces_.erase(ns->namespace_id());
}
void DOMStorageContextImpl::CloneSessionNamespace(
@@ -301,6 +336,21 @@ void DOMStorageContextImpl::CloneSessionNamespace(
CreateSessionNamespace(new_id, new_persistent_id);
}
+void DOMStorageContextImpl::CreateAliasSessionNamespace(
+ int64 existing_id, int64 new_id,
+ const std::string& persistent_id) {
+ if (is_shutdown_)
+ return;
+ DCHECK_NE(kLocalStorageNamespaceId, existing_id);
+ DCHECK_NE(kLocalStorageNamespaceId, new_id);
+ StorageNamespaceMap::iterator found = namespaces_.find(existing_id);
+ if (found != namespaces_.end()) {
+ namespaces_[new_id] = found->second->CreateAlias(new_id);
+ } else {
+ CreateSessionNamespace(new_id, persistent_id);
+ }
+}
+
void DOMStorageContextImpl::ClearSessionOnlyOrigins() {
if (!localstorage_directory_.empty()) {
std::vector<LocalStorageUsageInfo> infos;
@@ -419,4 +469,39 @@ void DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence() {
}
}
+void DOMStorageContextImpl::AddTransactionLogProcessId(int64 namespace_id,
+ int process_id) {
+ DCHECK_NE(kLocalStorageNamespaceId, namespace_id);
+ StorageNamespaceMap::const_iterator it = namespaces_.find(namespace_id);
+ if (it == namespaces_.end())
+ return;
+ it->second->AddTransactionLogProcessId(process_id);
+}
+
+void DOMStorageContextImpl::RemoveTransactionLogProcessId(int64 namespace_id,
+ int process_id) {
+ DCHECK_NE(kLocalStorageNamespaceId, namespace_id);
+ StorageNamespaceMap::const_iterator it = namespaces_.find(namespace_id);
+ if (it == namespaces_.end())
+ return;
+ it->second->RemoveTransactionLogProcessId(process_id);
+}
+
+SessionStorageNamespace::MergeResult
+DOMStorageContextImpl::MergeSessionStorage(
+ int64 namespace1_id, bool actually_merge, int process_id,
+ int64 namespace2_id) {
+ DCHECK_NE(kLocalStorageNamespaceId, namespace1_id);
+ DCHECK_NE(kLocalStorageNamespaceId, namespace2_id);
+ StorageNamespaceMap::const_iterator it = namespaces_.find(namespace1_id);
+ if (it == namespaces_.end())
+ return SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_FOUND;
+ DOMStorageNamespace* ns1 = it->second;
+ it = namespaces_.find(namespace2_id);
+ if (it == namespaces_.end())
+ return SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_FOUND;
+ DOMStorageNamespace* ns2 = it->second;
+ return ns1->Merge(actually_merge, process_id, ns2, this);
+}
+
} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_impl.h b/chromium/content/browser/dom_storage/dom_storage_context_impl.h
index 8f55656cb5b..a9400fbc594 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl.h
@@ -16,7 +16,9 @@
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/time/time.h"
+#include "content/browser/dom_storage/dom_storage_namespace.h"
#include "content/common/content_export.h"
+#include "content/public/browser/session_storage_namespace.h"
#include "url/gurl.h"
namespace base {
@@ -32,7 +34,6 @@ class SpecialStoragePolicy;
namespace content {
class DOMStorageArea;
-class DOMStorageNamespace;
class DOMStorageSession;
class DOMStorageTaskRunner;
class SessionStorageDatabase;
@@ -80,6 +81,9 @@ class CONTENT_EXPORT DOMStorageContextImpl
virtual void OnDOMStorageAreaCleared(
const DOMStorageArea* area,
const GURL& page_url) = 0;
+ // Indicates that cached values of the DOM Storage provided must be
+ // cleared and retrieved again.
+ virtual void OnDOMSessionStorageReset(int64 namespace_id) = 0;
protected:
virtual ~EventObserver() {}
@@ -133,6 +137,7 @@ class CONTENT_EXPORT DOMStorageContextImpl
// Methods to add, remove, and notify EventObservers.
void AddEventObserver(EventObserver* observer);
void RemoveEventObserver(EventObserver* observer);
+
void NotifyItemSet(
const DOMStorageArea* area,
const base::string16& key,
@@ -147,6 +152,9 @@ class CONTENT_EXPORT DOMStorageContextImpl
void NotifyAreaCleared(
const DOMStorageArea* area,
const GURL& page_url);
+ void NotifyAliasSessionMerged(
+ int64 namespace_id,
+ DOMStorageNamespace* old_alias_master_namespace);
// May be called on any thread.
int64 AllocateSessionId() {
@@ -161,6 +169,8 @@ class CONTENT_EXPORT DOMStorageContextImpl
void DeleteSessionNamespace(int64 namespace_id, bool should_persist_data);
void CloneSessionNamespace(int64 existing_id, int64 new_id,
const std::string& new_persistent_id);
+ void CreateAliasSessionNamespace(int64 existing_id, int64 new_id,
+ const std::string& persistent_id);
// Starts backing sessionStorage on disk. This function must be called right
// after DOMStorageContextImpl is created, before it's used.
@@ -171,6 +181,13 @@ class CONTENT_EXPORT DOMStorageContextImpl
// unclean exit.
void StartScavengingUnusedSessionStorage();
+ void AddTransactionLogProcessId(int64 namespace_id, int process_id);
+ void RemoveTransactionLogProcessId(int64 namespace_id, int process_id);
+
+ SessionStorageNamespace::MergeResult MergeSessionStorage(
+ int64 namespace1_id, bool actually_merge, int process_id,
+ int64 namespace2_id);
+
private:
friend class DOMStorageContextImplTest;
FRIEND_TEST_ALL_PREFIXES(DOMStorageContextImplTest, Basics);
@@ -178,10 +195,12 @@ class CONTENT_EXPORT DOMStorageContextImpl
typedef std::map<int64, scoped_refptr<DOMStorageNamespace> >
StorageNamespaceMap;
- ~DOMStorageContextImpl();
+ virtual ~DOMStorageContextImpl();
void ClearSessionOnlyOrigins();
+ void MaybeShutdownSessionNamespace(DOMStorageNamespace* ns);
+
// For scavenging unused sessionStorages.
void FindUnusedNamespaces();
void FindUnusedNamespacesInCommitSequence(
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 27aaefb24d3..ba8d8e98bc6 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
@@ -15,6 +15,7 @@
#include "content/browser/dom_storage/dom_storage_namespace.h"
#include "content/browser/dom_storage/dom_storage_task_runner.h"
#include "content/public/browser/local_storage_usage_info.h"
+#include "content/public/browser/session_storage_namespace.h"
#include "content/public/browser/session_storage_usage_info.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/browser/quota/mock_special_storage_policy.h"
@@ -260,4 +261,115 @@ TEST_F(DOMStorageContextImplTest, DeleteSessionStorage) {
base::MessageLoop::current()->RunUntilIdle();
}
+TEST_F(DOMStorageContextImplTest, SessionStorageAlias) {
+ const int kFirstSessionStorageNamespaceId = 1;
+ const std::string kPersistentId = "persistent";
+ context_->CreateSessionNamespace(kFirstSessionStorageNamespaceId,
+ kPersistentId);
+ DOMStorageNamespace* dom_namespace1 =
+ context_->GetStorageNamespace(kFirstSessionStorageNamespaceId);
+ ASSERT_TRUE(dom_namespace1);
+ DOMStorageArea* area1 = dom_namespace1->OpenStorageArea(kOrigin);
+ base::NullableString16 old_value;
+ area1->SetItem(kKey, kValue, &old_value);
+ EXPECT_TRUE(old_value.is_null());
+ base::NullableString16 read_value = area1->GetItem(kKey);
+ EXPECT_TRUE(!read_value.is_null() && read_value.string() == kValue);
+
+ // Create an alias.
+ const int kAliasSessionStorageNamespaceId = 2;
+ context_->CreateAliasSessionNamespace(kFirstSessionStorageNamespaceId,
+ kAliasSessionStorageNamespaceId,
+ kPersistentId);
+ DOMStorageNamespace* dom_namespace2 =
+ context_->GetStorageNamespace(kAliasSessionStorageNamespaceId);
+ ASSERT_TRUE(dom_namespace2);
+ ASSERT_TRUE(dom_namespace2->alias_master_namespace() == dom_namespace1);
+
+ // Verify that read values are identical.
+ DOMStorageArea* area2 = dom_namespace2->OpenStorageArea(kOrigin);
+ read_value = area2->GetItem(kKey);
+ EXPECT_TRUE(!read_value.is_null() && read_value.string() == kValue);
+
+ // Verify that writes are reflected in both namespaces.
+ const base::string16 kValue2(ASCIIToUTF16("value2"));
+ area2->SetItem(kKey, kValue2, &old_value);
+ read_value = area1->GetItem(kKey);
+ EXPECT_TRUE(!read_value.is_null() && read_value.string() == kValue2);
+ dom_namespace1->CloseStorageArea(area1);
+ dom_namespace2->CloseStorageArea(area2);
+
+ // When creating an alias of an alias, ensure that the master relationship
+ // is collapsed.
+ const int kAlias2SessionStorageNamespaceId = 3;
+ context_->CreateAliasSessionNamespace(kAliasSessionStorageNamespaceId,
+ kAlias2SessionStorageNamespaceId,
+ kPersistentId);
+ DOMStorageNamespace* dom_namespace3 =
+ context_->GetStorageNamespace(kAlias2SessionStorageNamespaceId);
+ ASSERT_TRUE(dom_namespace3);
+ ASSERT_TRUE(dom_namespace3->alias_master_namespace() == dom_namespace1);
+}
+
+TEST_F(DOMStorageContextImplTest, SessionStorageMerge) {
+ // Create a target namespace that we will merge into.
+ const int kTargetSessionStorageNamespaceId = 1;
+ const std::string kTargetPersistentId = "persistent";
+ context_->CreateSessionNamespace(kTargetSessionStorageNamespaceId,
+ kTargetPersistentId);
+ DOMStorageNamespace* target_ns =
+ context_->GetStorageNamespace(kTargetSessionStorageNamespaceId);
+ ASSERT_TRUE(target_ns);
+ DOMStorageArea* target_ns_area = target_ns->OpenStorageArea(kOrigin);
+ base::NullableString16 old_value;
+ const base::string16 kKey2(ASCIIToUTF16("key2"));
+ const base::string16 kKey2Value(ASCIIToUTF16("key2value"));
+ target_ns_area->SetItem(kKey, kValue, &old_value);
+ target_ns_area->SetItem(kKey2, kKey2Value, &old_value);
+
+ // Create a source namespace & its alias.
+ const int kSourceSessionStorageNamespaceId = 2;
+ const int kAliasSessionStorageNamespaceId = 3;
+ const std::string kSourcePersistentId = "persistent_source";
+ context_->CreateSessionNamespace(kSourceSessionStorageNamespaceId,
+ kSourcePersistentId);
+ context_->CreateAliasSessionNamespace(kSourceSessionStorageNamespaceId,
+ kAliasSessionStorageNamespaceId,
+ kSourcePersistentId);
+ DOMStorageNamespace* alias_ns =
+ context_->GetStorageNamespace(kAliasSessionStorageNamespaceId);
+ ASSERT_TRUE(alias_ns);
+
+ // Create a transaction log that can't be merged.
+ const int kPid1 = 10;
+ ASSERT_FALSE(alias_ns->IsLoggingRenderer(kPid1));
+ alias_ns->AddTransactionLogProcessId(kPid1);
+ ASSERT_TRUE(alias_ns->IsLoggingRenderer(kPid1));
+ const base::string16 kValue2(ASCIIToUTF16("value2"));
+ DOMStorageNamespace::TransactionRecord txn;
+ txn.origin = kOrigin;
+ txn.key = kKey;
+ txn.value = base::NullableString16(kValue2, false);
+ txn.transaction_type = DOMStorageNamespace::TRANSACTION_READ;
+ alias_ns->AddTransaction(kPid1, txn);
+ ASSERT_TRUE(alias_ns->Merge(false, kPid1, target_ns, NULL) ==
+ SessionStorageNamespace::MERGE_RESULT_NOT_MERGEABLE);
+
+ // Create a transaction log that can be merged.
+ const int kPid2 = 20;
+ alias_ns->AddTransactionLogProcessId(kPid2);
+ txn.transaction_type = DOMStorageNamespace::TRANSACTION_WRITE;
+ alias_ns->AddTransaction(kPid2, txn);
+ ASSERT_TRUE(alias_ns->Merge(true, kPid2, target_ns, NULL) ==
+ SessionStorageNamespace::MERGE_RESULT_MERGEABLE);
+
+ // Verify that the merge was successful.
+ ASSERT_TRUE(alias_ns->alias_master_namespace() == target_ns);
+ base::NullableString16 read_value = target_ns_area->GetItem(kKey);
+ EXPECT_TRUE(!read_value.is_null() && read_value.string() == kValue2);
+ DOMStorageArea* alias_ns_area = alias_ns->OpenStorageArea(kOrigin);
+ read_value = alias_ns_area->GetItem(kKey2);
+ EXPECT_TRUE(!read_value.is_null() && read_value.string() == kKey2Value);
+}
+
} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_host.cc b/chromium/content/browser/dom_storage/dom_storage_host.cc
index 14d288d8653..9128f57461f 100644
--- a/chromium/content/browser/dom_storage/dom_storage_host.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_host.cc
@@ -12,8 +12,10 @@
namespace content {
-DOMStorageHost::DOMStorageHost(DOMStorageContextImpl* context)
- : context_(context) {
+DOMStorageHost::DOMStorageHost(DOMStorageContextImpl* context,
+ int render_process_id)
+ : context_(context),
+ render_process_id_(render_process_id) {
}
DOMStorageHost::~DOMStorageHost() {
@@ -30,8 +32,12 @@ bool DOMStorageHost::OpenStorageArea(int connection_id, int namespace_id,
return false; // Indicates the renderer gave us very bad data.
NamespaceAndArea references;
references.namespace_ = context_->GetStorageNamespace(namespace_id);
- if (!references.namespace_.get())
- return false;
+ if (!references.namespace_.get()) {
+ // TODO(michaeln): Fix crbug/134003 and return false here.
+ // Until then return true to avoid crashing the renderer for
+ // sending a bad message.
+ return true;
+ }
references.area_ = references.namespace_->OpenStorageArea(origin);
DCHECK(references.area_.get());
connections_[connection_id] = references;
@@ -47,11 +53,15 @@ void DOMStorageHost::CloseStorageArea(int connection_id) {
}
bool DOMStorageHost::ExtractAreaValues(
- int connection_id, DOMStorageValuesMap* map) {
+ int connection_id, DOMStorageValuesMap* map, bool* send_log_get_messages) {
map->clear();
DOMStorageArea* area = GetOpenArea(connection_id);
- if (!area)
- return false;
+ if (!area) {
+ // TODO(michaeln): Fix crbug/134003 and return false here.
+ // Until then return true to avoid crashing the renderer
+ // for sending a bad message.
+ return true;
+ }
if (!area->IsLoadedInMemory()) {
DOMStorageNamespace* ns = GetNamespace(connection_id);
DCHECK(ns);
@@ -62,6 +72,10 @@ bool DOMStorageHost::ExtractAreaValues(
}
}
area->ExtractValues(map);
+ *send_log_get_messages = false;
+ DOMStorageNamespace* ns = GetNamespace(connection_id);
+ DCHECK(ns);
+ *send_log_get_messages = ns->IsLoggingRenderer(render_process_id_);
return true;
}
@@ -93,15 +107,34 @@ bool DOMStorageHost::SetAreaItem(
const base::string16& value, const GURL& page_url,
base::NullableString16* old_value) {
DOMStorageArea* area = GetOpenArea(connection_id);
- if (!area)
- return false;
+ if (!area) {
+ // TODO(michaeln): Fix crbug/134003 and return false here.
+ // Until then return true to allow the renderer to operate
+ // to a limited degree out of its cache.
+ return true;
+ }
if (!area->SetItem(key, value, old_value))
return false;
if (old_value->is_null() || old_value->string() != value)
context_->NotifyItemSet(area, key, value, *old_value, page_url);
+ MaybeLogTransaction(connection_id,
+ DOMStorageNamespace::TRANSACTION_WRITE,
+ area->origin(), page_url, key,
+ base::NullableString16(value, false));
return true;
}
+void DOMStorageHost::LogGetAreaItem(
+ int connection_id, const base::string16& key,
+ const base::NullableString16& value) {
+ DOMStorageArea* area = GetOpenArea(connection_id);
+ if (!area)
+ return;
+ MaybeLogTransaction(connection_id,
+ DOMStorageNamespace::TRANSACTION_READ,
+ area->origin(), GURL(), key, value);
+}
+
bool DOMStorageHost::RemoveAreaItem(
int connection_id, const base::string16& key, const GURL& page_url,
base::string16* old_value) {
@@ -111,6 +144,9 @@ bool DOMStorageHost::RemoveAreaItem(
if (!area->RemoveItem(key, old_value))
return false;
context_->NotifyItemRemoved(area, key, *old_value, page_url);
+ MaybeLogTransaction(connection_id,
+ DOMStorageNamespace::TRANSACTION_REMOVE,
+ area->origin(), page_url, key, base::NullableString16());
return true;
}
@@ -121,21 +157,40 @@ bool DOMStorageHost::ClearArea(int connection_id, const GURL& page_url) {
if (!area->Clear())
return false;
context_->NotifyAreaCleared(area, page_url);
+ MaybeLogTransaction(connection_id,
+ DOMStorageNamespace::TRANSACTION_CLEAR,
+ area->origin(), page_url, base::string16(),
+ base::NullableString16());
return true;
}
bool DOMStorageHost::HasAreaOpen(
- int namespace_id, const GURL& origin) const {
+ int64 namespace_id, const GURL& origin, int64* alias_namespace_id) const {
AreaMap::const_iterator it = connections_.begin();
for (; it != connections_.end(); ++it) {
- if (namespace_id == it->second.namespace_->namespace_id() &&
+ if (namespace_id == it->second.area_->namespace_id() &&
origin == it->second.area_->origin()) {
+ *alias_namespace_id = it->second.namespace_->namespace_id();
return true;
}
}
return false;
}
+bool DOMStorageHost::ResetOpenAreasForNamespace(int64 namespace_id) {
+ bool result = false;
+ AreaMap::iterator it = connections_.begin();
+ for (; it != connections_.end(); ++it) {
+ if (namespace_id == it->second.namespace_->namespace_id()) {
+ GURL origin = it->second.area_->origin();
+ it->second.namespace_->CloseStorageArea(it->second.area_.get());
+ it->second.area_ = it->second.namespace_->OpenStorageArea(origin);
+ result = true;
+ }
+ }
+ return result;
+}
+
DOMStorageArea* DOMStorageHost::GetOpenArea(int connection_id) {
AreaMap::iterator found = connections_.find(connection_id);
if (found == connections_.end())
@@ -150,6 +205,26 @@ DOMStorageNamespace* DOMStorageHost::GetNamespace(int connection_id) {
return found->second.namespace_.get();
}
+void DOMStorageHost::MaybeLogTransaction(
+ int connection_id,
+ DOMStorageNamespace::LogType transaction_type,
+ const GURL& origin,
+ const GURL& page_url,
+ const base::string16& key,
+ const base::NullableString16& value) {
+ DOMStorageNamespace* ns = GetNamespace(connection_id);
+ DCHECK(ns);
+ if (!ns->IsLoggingRenderer(render_process_id_))
+ return;
+ DOMStorageNamespace::TransactionRecord transaction;
+ transaction.transaction_type = transaction_type;
+ transaction.origin = origin;
+ transaction.page_url = page_url;
+ transaction.key = key;
+ transaction.value = value;
+ ns->AddTransaction(render_process_id_, transaction);
+}
+
// NamespaceAndArea
DOMStorageHost::NamespaceAndArea::NamespaceAndArea() {}
diff --git a/chromium/content/browser/dom_storage/dom_storage_host.h b/chromium/content/browser/dom_storage/dom_storage_host.h
index 3aa9d8078f7..f4ca784b2fa 100644
--- a/chromium/content/browser/dom_storage/dom_storage_host.h
+++ b/chromium/content/browser/dom_storage/dom_storage_host.h
@@ -10,6 +10,7 @@
#include "base/memory/ref_counted.h"
#include "base/strings/nullable_string16.h"
#include "base/strings/string16.h"
+#include "content/browser/dom_storage/dom_storage_namespace.h"
#include "content/common/content_export.h"
#include "content/common/dom_storage/dom_storage_types.h"
@@ -23,19 +24,20 @@ class DOMStorageNamespace;
class DOMStorageArea;
// One instance is allocated in the main process for each client process.
-// Used by DOMStorageMessageFilter in Chrome and by SimpleDOMStorage in DRT.
+// Used by DOMStorageMessageFilter in Chrome.
// This class is single threaded, and performs blocking file reads/writes,
// so it shouldn't be used on chrome's IO thread.
// See class comments for DOMStorageContextImpl for a larger overview.
class CONTENT_EXPORT DOMStorageHost {
public:
- explicit DOMStorageHost(DOMStorageContextImpl* context);
+ DOMStorageHost(DOMStorageContextImpl* context, int render_process_id);
~DOMStorageHost();
bool OpenStorageArea(int connection_id, int namespace_id,
const GURL& origin);
void CloseStorageArea(int connection_id);
- bool ExtractAreaValues(int connection_id, DOMStorageValuesMap* map);
+ bool ExtractAreaValues(int connection_id, DOMStorageValuesMap* map,
+ bool* send_log_get_messages);
unsigned GetAreaLength(int connection_id);
base::NullableString16 GetAreaKey(int connection_id, unsigned index);
base::NullableString16 GetAreaItem(int connection_id,
@@ -43,11 +45,17 @@ class CONTENT_EXPORT DOMStorageHost {
bool SetAreaItem(int connection_id, const base::string16& key,
const base::string16& value, const GURL& page_url,
base::NullableString16* old_value);
+ void LogGetAreaItem(int connection_id, const base::string16& key,
+ const base::NullableString16& value);
bool RemoveAreaItem(int connection_id, const base::string16& key,
const GURL& page_url,
base::string16* old_value);
bool ClearArea(int connection_id, const GURL& page_url);
- bool HasAreaOpen(int namespace_id, const GURL& origin) const;
+ bool HasAreaOpen(int64 namespace_id, const GURL& origin,
+ int64* alias_namespace_id) const;
+ // Resets all open areas for the namespace provided. Returns true
+ // iff there were any areas to reset.
+ bool ResetOpenAreasForNamespace(int64 namespace_id);
private:
// Struct to hold references needed for areas that are open
@@ -62,9 +70,17 @@ class CONTENT_EXPORT DOMStorageHost {
DOMStorageArea* GetOpenArea(int connection_id);
DOMStorageNamespace* GetNamespace(int connection_id);
+ void MaybeLogTransaction(
+ int connection_id,
+ DOMStorageNamespace::LogType transaction_type,
+ const GURL& origin,
+ const GURL& page_url,
+ const base::string16& key,
+ const base::NullableString16& value);
scoped_refptr<DOMStorageContextImpl> context_;
AreaMap connections_;
+ int render_process_id_;
};
} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_message_filter.cc b/chromium/content/browser/dom_storage/dom_storage_message_filter.cc
index 52aabe11018..fbc3880abb7 100644
--- a/chromium/content/browser/dom_storage/dom_storage_message_filter.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_message_filter.cc
@@ -21,9 +21,10 @@
namespace content {
DOMStorageMessageFilter::DOMStorageMessageFilter(
- int unused,
+ int render_process_id,
DOMStorageContextWrapper* context)
- : context_(context->context()),
+ : render_process_id_(render_process_id),
+ context_(context->context()),
connection_dispatching_message_for_(0) {
}
@@ -33,7 +34,7 @@ DOMStorageMessageFilter::~DOMStorageMessageFilter() {
void DOMStorageMessageFilter::InitializeInSequence() {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
- host_.reset(new DOMStorageHost(context_.get()));
+ host_.reset(new DOMStorageHost(context_.get(), render_process_id_));
context_->AddEventObserver(this);
}
@@ -46,8 +47,6 @@ void DOMStorageMessageFilter::UninitializeInSequence() {
}
void DOMStorageMessageFilter::OnFilterAdded(IPC::Channel* channel) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- BrowserMessageFilter::OnFilterAdded(channel);
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE,
DOMStorageTaskRunner::PRIMARY_SEQUENCE,
@@ -55,8 +54,6 @@ void DOMStorageMessageFilter::OnFilterAdded(IPC::Channel* channel) {
}
void DOMStorageMessageFilter::OnFilterRemoved() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- BrowserMessageFilter::OnFilterRemoved();
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE,
DOMStorageTaskRunner::PRIMARY_SEQUENCE,
@@ -83,6 +80,7 @@ bool DOMStorageMessageFilter::OnMessageReceived(const IPC::Message& message,
IPC_MESSAGE_HANDLER(DOMStorageHostMsg_CloseStorageArea, OnCloseStorageArea)
IPC_MESSAGE_HANDLER(DOMStorageHostMsg_LoadStorageArea, OnLoadStorageArea)
IPC_MESSAGE_HANDLER(DOMStorageHostMsg_SetItem, OnSetItem)
+ IPC_MESSAGE_HANDLER(DOMStorageHostMsg_LogGetItem, OnLogGetItem)
IPC_MESSAGE_HANDLER(DOMStorageHostMsg_RemoveItem, OnRemoveItem)
IPC_MESSAGE_HANDLER(DOMStorageHostMsg_Clear, OnClear)
IPC_MESSAGE_HANDLER(DOMStorageHostMsg_FlushMessages, OnFlushMessages)
@@ -107,9 +105,10 @@ void DOMStorageMessageFilter::OnCloseStorageArea(int connection_id) {
}
void DOMStorageMessageFilter::OnLoadStorageArea(int connection_id,
- DOMStorageValuesMap* map) {
+ DOMStorageValuesMap* map,
+ bool* send_log_get_messages) {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!host_->ExtractAreaValues(connection_id, map)) {
+ if (!host_->ExtractAreaValues(connection_id, map, send_log_get_messages)) {
RecordAction(UserMetricsAction("BadMessageTerminate_DSMF_2"));
BadMessageReceived();
}
@@ -117,8 +116,8 @@ void DOMStorageMessageFilter::OnLoadStorageArea(int connection_id,
}
void DOMStorageMessageFilter::OnSetItem(
- int connection_id, const string16& key,
- const string16& value, const GURL& page_url) {
+ int connection_id, const base::string16& key,
+ const base::string16& value, const GURL& page_url) {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_EQ(0, connection_dispatching_message_for_);
base::AutoReset<int> auto_reset(&connection_dispatching_message_for_,
@@ -129,14 +128,21 @@ void DOMStorageMessageFilter::OnSetItem(
Send(new DOMStorageMsg_AsyncOperationComplete(success));
}
+void DOMStorageMessageFilter::OnLogGetItem(
+ int connection_id, const base::string16& key,
+ const base::NullableString16& value) {
+ DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
+ host_->LogGetAreaItem(connection_id, key, value);
+}
+
void DOMStorageMessageFilter::OnRemoveItem(
- int connection_id, const string16& key,
+ int connection_id, const base::string16& key,
const GURL& page_url) {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_EQ(0, connection_dispatching_message_for_);
base::AutoReset<int> auto_reset(&connection_dispatching_message_for_,
connection_id);
- string16 not_used;
+ base::string16 not_used;
host_->RemoveAreaItem(connection_id, key, page_url, &not_used);
Send(new DOMStorageMsg_AsyncOperationComplete(true));
}
@@ -157,8 +163,8 @@ void DOMStorageMessageFilter::OnFlushMessages() {
void DOMStorageMessageFilter::OnDOMStorageItemSet(
const DOMStorageArea* area,
- const string16& key,
- const string16& new_value,
+ const base::string16& key,
+ const base::string16& new_value,
const base::NullableString16& old_value,
const GURL& page_url) {
SendDOMStorageEvent(area, page_url,
@@ -169,8 +175,8 @@ void DOMStorageMessageFilter::OnDOMStorageItemSet(
void DOMStorageMessageFilter::OnDOMStorageItemRemoved(
const DOMStorageArea* area,
- const string16& key,
- const string16& old_value,
+ const base::string16& key,
+ const base::string16& old_value,
const GURL& page_url) {
SendDOMStorageEvent(area, page_url,
base::NullableString16(key, false),
@@ -187,6 +193,11 @@ void DOMStorageMessageFilter::OnDOMStorageAreaCleared(
base::NullableString16());
}
+void DOMStorageMessageFilter::OnDOMSessionStorageReset(int64 namespace_id) {
+ if (host_->ResetOpenAreasForNamespace(namespace_id))
+ Send(new DOMStorageMsg_ResetCachedValues(namespace_id));
+}
+
void DOMStorageMessageFilter::SendDOMStorageEvent(
const DOMStorageArea* area,
const GURL& page_url,
@@ -196,8 +207,10 @@ void DOMStorageMessageFilter::SendDOMStorageEvent(
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
// Only send mutation events to processes which have the area open.
bool originated_in_process = connection_dispatching_message_for_ != 0;
- if (originated_in_process ||
- host_->HasAreaOpen(area->namespace_id(), area->origin())) {
+ int64 alias_namespace_id = area->namespace_id();
+ if (host_->HasAreaOpen(area->namespace_id(), area->origin(),
+ &alias_namespace_id) ||
+ originated_in_process) {
DOMStorageMsg_Event_Params params;
params.origin = area->origin();
params.page_url = page_url;
@@ -205,7 +218,7 @@ void DOMStorageMessageFilter::SendDOMStorageEvent(
params.key = key;
params.new_value = new_value;
params.old_value = old_value;
- params.namespace_id = area->namespace_id();
+ params.namespace_id = alias_namespace_id;
Send(new DOMStorageMsg_Event(params));
}
}
diff --git a/chromium/content/browser/dom_storage/dom_storage_message_filter.h b/chromium/content/browser/dom_storage/dom_storage_message_filter.h
index 2ec928a4732..3c82418842c 100644
--- a/chromium/content/browser/dom_storage/dom_storage_message_filter.h
+++ b/chromium/content/browser/dom_storage/dom_storage_message_filter.h
@@ -30,7 +30,7 @@ class DOMStorageMessageFilter
: public BrowserMessageFilter,
public DOMStorageContextImpl::EventObserver {
public:
- explicit DOMStorageMessageFilter(int unused,
+ explicit DOMStorageMessageFilter(int render_process_id,
DOMStorageContextWrapper* context);
private:
@@ -51,10 +51,13 @@ class DOMStorageMessageFilter
void OnOpenStorageArea(int connection_id, int64 namespace_id,
const GURL& origin);
void OnCloseStorageArea(int connection_id);
- void OnLoadStorageArea(int connection_id, DOMStorageValuesMap* map);
- void OnSetItem(int connection_id, const string16& key,
- const string16& value, const GURL& page_url);
- void OnRemoveItem(int connection_id, const string16& key,
+ void OnLoadStorageArea(int connection_id, DOMStorageValuesMap* map,
+ bool* send_log_get_messages);
+ void OnSetItem(int connection_id, const base::string16& key,
+ const base::string16& value, const GURL& page_url);
+ void OnLogGetItem(int connection_id, const base::string16& key,
+ const base::NullableString16& value);
+ void OnRemoveItem(int connection_id, const base::string16& key,
const GURL& page_url);
void OnClear(int connection_id, const GURL& page_url);
void OnFlushMessages();
@@ -63,18 +66,19 @@ class DOMStorageMessageFilter
// sends events back to our renderer process.
virtual void OnDOMStorageItemSet(
const DOMStorageArea* area,
- const string16& key,
- const string16& new_value,
+ const base::string16& key,
+ const base::string16& new_value,
const base::NullableString16& old_value,
const GURL& page_url) OVERRIDE;
virtual void OnDOMStorageItemRemoved(
const DOMStorageArea* area,
- const string16& key,
- const string16& old_value,
+ const base::string16& key,
+ const base::string16& old_value,
const GURL& page_url) OVERRIDE;
virtual void OnDOMStorageAreaCleared(
const DOMStorageArea* area,
const GURL& page_url) OVERRIDE;
+ virtual void OnDOMSessionStorageReset(int64 namespace_id) OVERRIDE;
void SendDOMStorageEvent(
const DOMStorageArea* area,
@@ -83,6 +87,7 @@ class DOMStorageMessageFilter
const base::NullableString16& new_value,
const base::NullableString16& old_value);
+ int render_process_id_;
scoped_refptr<DOMStorageContextImpl> context_;
scoped_ptr<DOMStorageHost> host_;
int connection_dispatching_message_for_;
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.cc b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
index 75bfdaacb71..ac1e2f89cd0 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
@@ -4,23 +4,40 @@
#include "content/browser/dom_storage/dom_storage_namespace.h"
+#include <set>
+#include <utility>
+
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/stl_util.h"
#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_task_runner.h"
#include "content/browser/dom_storage/session_storage_database.h"
+#include "content/common/child_process_host_impl.h"
#include "content/common/dom_storage/dom_storage_types.h"
namespace content {
+namespace {
+
+static const unsigned int kMaxTransactionLogEntries = 8 * 1024;
+
+} // namespace
+
DOMStorageNamespace::DOMStorageNamespace(
const base::FilePath& directory,
DOMStorageTaskRunner* task_runner)
: namespace_id_(kLocalStorageNamespaceId),
directory_(directory),
- task_runner_(task_runner) {
+ task_runner_(task_runner),
+ num_aliases_(0),
+ old_master_for_close_area_(NULL),
+ master_alias_count_decremented_(false),
+ ready_for_deletion_pending_aliases_(false),
+ must_persist_at_shutdown_(false) {
}
DOMStorageNamespace::DOMStorageNamespace(
@@ -31,14 +48,23 @@ DOMStorageNamespace::DOMStorageNamespace(
: namespace_id_(namespace_id),
persistent_namespace_id_(persistent_namespace_id),
task_runner_(task_runner),
- session_storage_database_(session_storage_database) {
+ session_storage_database_(session_storage_database),
+ num_aliases_(0),
+ old_master_for_close_area_(NULL),
+ master_alias_count_decremented_(false),
+ ready_for_deletion_pending_aliases_(false),
+ must_persist_at_shutdown_(false) {
DCHECK_NE(kLocalStorageNamespaceId, namespace_id);
}
DOMStorageNamespace::~DOMStorageNamespace() {
+ STLDeleteValues(&transactions_);
+ DecrementMasterAliasCount();
}
DOMStorageArea* DOMStorageNamespace::OpenStorageArea(const GURL& origin) {
+ if (alias_master_namespace_)
+ return alias_master_namespace_->OpenStorageArea(origin);
if (AreaHolder* holder = GetAreaHolder(origin)) {
++(holder->open_count_);
return holder->area_.get();
@@ -57,6 +83,14 @@ DOMStorageArea* DOMStorageNamespace::OpenStorageArea(const GURL& origin) {
void DOMStorageNamespace::CloseStorageArea(DOMStorageArea* area) {
AreaHolder* holder = GetAreaHolder(area->origin());
+ if (alias_master_namespace_) {
+ DCHECK(!holder);
+ if (old_master_for_close_area_)
+ old_master_for_close_area_->CloseStorageArea(area);
+ else
+ alias_master_namespace_->CloseStorageArea(area);
+ return;
+ }
DCHECK(holder);
DCHECK_EQ(holder->area_.get(), area);
--(holder->open_count_);
@@ -65,6 +99,8 @@ void DOMStorageNamespace::CloseStorageArea(DOMStorageArea* area) {
}
DOMStorageArea* DOMStorageNamespace::GetOpenStorageArea(const GURL& origin) {
+ if (alias_master_namespace_)
+ return alias_master_namespace_->GetOpenStorageArea(origin);
AreaHolder* holder = GetAreaHolder(origin);
if (holder && holder->open_count_)
return holder->area_.get();
@@ -74,6 +110,10 @@ DOMStorageArea* DOMStorageNamespace::GetOpenStorageArea(const GURL& origin) {
DOMStorageNamespace* DOMStorageNamespace::Clone(
int64 clone_namespace_id,
const std::string& clone_persistent_namespace_id) {
+ if (alias_master_namespace_) {
+ return alias_master_namespace_->Clone(clone_namespace_id,
+ clone_persistent_namespace_id);
+ }
DCHECK_NE(kLocalStorageNamespaceId, namespace_id_);
DCHECK_NE(kLocalStorageNamespaceId, clone_namespace_id);
DOMStorageNamespace* clone = new DOMStorageNamespace(
@@ -98,8 +138,34 @@ DOMStorageNamespace* DOMStorageNamespace::Clone(
return clone;
}
+DOMStorageNamespace* DOMStorageNamespace::CreateAlias(
+ int64 alias_namespace_id) {
+ // Creates an alias of the current DOMStorageNamespace.
+ // The alias will have a reference to this namespace (called the master),
+ // and all operations will be redirected to the master (in particular,
+ // the alias will never open any areas of its own, but always redirect
+ // to the master). Accordingly, an alias will also never undergo the shutdown
+ // procedure which initiates persisting to disk, since there is never any data
+ // of its own to persist to disk. DOMStorageContextImpl is the place where
+ // shutdowns are initiated, but only for non-alias DOMStorageNamespaces.
+ DCHECK_NE(kLocalStorageNamespaceId, namespace_id_);
+ DCHECK_NE(kLocalStorageNamespaceId, alias_namespace_id);
+ DOMStorageNamespace* alias = new DOMStorageNamespace(
+ alias_namespace_id, persistent_namespace_id_,
+ session_storage_database_.get(), task_runner_.get());
+ if (alias_master_namespace_ != NULL) {
+ DCHECK(alias_master_namespace_->alias_master_namespace_ == NULL);
+ alias->alias_master_namespace_ = alias_master_namespace_;
+ } else {
+ alias->alias_master_namespace_ = this;
+ }
+ alias->alias_master_namespace_->num_aliases_++;
+ return alias;
+}
+
void DOMStorageNamespace::DeleteLocalStorageOrigin(const GURL& origin) {
DCHECK(!session_storage_database_.get());
+ DCHECK(!alias_master_namespace_.get());
AreaHolder* holder = GetAreaHolder(origin);
if (holder) {
holder->area_->DeleteOrigin();
@@ -113,12 +179,20 @@ void DOMStorageNamespace::DeleteLocalStorageOrigin(const GURL& origin) {
}
void DOMStorageNamespace::DeleteSessionStorageOrigin(const GURL& origin) {
+ if (alias_master_namespace_) {
+ alias_master_namespace_->DeleteSessionStorageOrigin(origin);
+ return;
+ }
DOMStorageArea* area = OpenStorageArea(origin);
area->FastClear();
CloseStorageArea(area);
}
void DOMStorageNamespace::PurgeMemory(PurgeOption option) {
+ if (alias_master_namespace_) {
+ alias_master_namespace_->PurgeMemory(option);
+ return;
+ }
if (directory_.empty())
return; // We can't purge w/o backing on disk.
AreaMap::iterator it = areas_.begin();
@@ -154,6 +228,8 @@ void DOMStorageNamespace::Shutdown() {
}
unsigned int DOMStorageNamespace::CountInMemoryAreas() const {
+ if (alias_master_namespace_)
+ return alias_master_namespace_->CountInMemoryAreas();
unsigned int area_count = 0;
for (AreaMap::const_iterator it = areas_.begin(); it != areas_.end(); ++it) {
if (it->second.area_->IsLoadedInMemory())
@@ -170,6 +246,187 @@ DOMStorageNamespace::GetAreaHolder(const GURL& origin) {
return &(found->second);
}
+void DOMStorageNamespace::AddTransactionLogProcessId(int process_id) {
+ DCHECK(process_id != ChildProcessHostImpl::kInvalidChildProcessId);
+ DCHECK(transactions_.count(process_id) == 0);
+ TransactionData* transaction_data = new TransactionData;
+ transactions_[process_id] = transaction_data;
+}
+
+void DOMStorageNamespace::RemoveTransactionLogProcessId(int process_id) {
+ DCHECK(process_id != ChildProcessHostImpl::kInvalidChildProcessId);
+ DCHECK(transactions_.count(process_id) == 1);
+ delete transactions_[process_id];
+ transactions_.erase(process_id);
+}
+
+SessionStorageNamespace::MergeResult DOMStorageNamespace::Merge(
+ bool actually_merge,
+ int process_id,
+ DOMStorageNamespace* other,
+ DOMStorageContextImpl* context) {
+ if (!alias_master_namespace())
+ return SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_ALIAS;
+ if (transactions_.count(process_id) < 1)
+ return SessionStorageNamespace::MERGE_RESULT_NOT_LOGGING;
+ TransactionData* data = transactions_[process_id];
+ if (data->max_log_size_exceeded)
+ return SessionStorageNamespace::MERGE_RESULT_TOO_MANY_TRANSACTIONS;
+ if (data->log.size() < 1) {
+ if (actually_merge)
+ SwitchToNewAliasMaster(other, context);
+ return SessionStorageNamespace::MERGE_RESULT_NO_TRANSACTIONS;
+ }
+
+ // skip_areas and skip_keys store areas and (area, key) pairs, respectively,
+ // that have already been handled previously. Any further modifications to
+ // them will not change the result of the hypothetical merge.
+ std::set<GURL> skip_areas;
+ typedef std::pair<GURL, base::string16> OriginKey;
+ std::set<OriginKey> skip_keys;
+ // Indicates whether we could still merge the namespaces preserving all
+ // individual transactions.
+ for (unsigned int i = 0; i < data->log.size(); i++) {
+ TransactionRecord& transaction = data->log[i];
+ if (transaction.transaction_type == TRANSACTION_CLEAR) {
+ skip_areas.insert(transaction.origin);
+ continue;
+ }
+ if (skip_areas.find(transaction.origin) != skip_areas.end())
+ continue;
+ if (skip_keys.find(OriginKey(transaction.origin, transaction.key))
+ != skip_keys.end()) {
+ continue;
+ }
+ if (transaction.transaction_type == TRANSACTION_REMOVE ||
+ transaction.transaction_type == TRANSACTION_WRITE) {
+ skip_keys.insert(OriginKey(transaction.origin, transaction.key));
+ continue;
+ }
+ if (transaction.transaction_type == TRANSACTION_READ) {
+ DOMStorageArea* area = other->OpenStorageArea(transaction.origin);
+ base::NullableString16 other_value = area->GetItem(transaction.key);
+ other->CloseStorageArea(area);
+ if (transaction.value != other_value)
+ return SessionStorageNamespace::MERGE_RESULT_NOT_MERGEABLE;
+ continue;
+ }
+ NOTREACHED();
+ }
+ if (!actually_merge)
+ return SessionStorageNamespace::MERGE_RESULT_MERGEABLE;
+
+ // Actually perform the merge.
+
+ for (unsigned int i = 0; i < data->log.size(); i++) {
+ TransactionRecord& transaction = data->log[i];
+ if (transaction.transaction_type == TRANSACTION_READ)
+ continue;
+ DOMStorageArea* area = other->OpenStorageArea(transaction.origin);
+ if (transaction.transaction_type == TRANSACTION_CLEAR) {
+ area->Clear();
+ if (context)
+ context->NotifyAreaCleared(area, transaction.page_url);
+ }
+ if (transaction.transaction_type == TRANSACTION_REMOVE) {
+ base::string16 old_value;
+ area->RemoveItem(transaction.key, &old_value);
+ if (context) {
+ context->NotifyItemRemoved(area, transaction.key, old_value,
+ transaction.page_url);
+ }
+ }
+ if (transaction.transaction_type == TRANSACTION_WRITE) {
+ base::NullableString16 old_value;
+ area->SetItem(transaction.key, base::string16(transaction.value.string()),
+ &old_value);
+ if (context) {
+ context->NotifyItemSet(area, transaction.key,transaction.value.string(),
+ old_value, transaction.page_url);
+ }
+ }
+ other->CloseStorageArea(area);
+ }
+
+ SwitchToNewAliasMaster(other, context);
+ return SessionStorageNamespace::MERGE_RESULT_MERGEABLE;
+}
+
+bool DOMStorageNamespace::IsLoggingRenderer(int process_id) {
+ DCHECK(process_id != ChildProcessHostImpl::kInvalidChildProcessId);
+ if (transactions_.count(process_id) < 1)
+ return false;
+ return !transactions_[process_id]->max_log_size_exceeded;
+}
+
+void DOMStorageNamespace::AddTransaction(
+ int process_id, const TransactionRecord& transaction) {
+ if (!IsLoggingRenderer(process_id))
+ return;
+ TransactionData* transaction_data = transactions_[process_id];
+ DCHECK(transaction_data);
+ if (transaction_data->max_log_size_exceeded)
+ return;
+ transaction_data->log.push_back(transaction);
+ if (transaction_data->log.size() > kMaxTransactionLogEntries) {
+ transaction_data->max_log_size_exceeded = true;
+ transaction_data->log.clear();
+ }
+}
+
+bool DOMStorageNamespace::DecrementMasterAliasCount() {
+ if (!alias_master_namespace_ || master_alias_count_decremented_)
+ return false;
+ DCHECK_GT(alias_master_namespace_->num_aliases_, 0);
+ alias_master_namespace_->num_aliases_--;
+ master_alias_count_decremented_ = true;
+ return (alias_master_namespace_->num_aliases_ == 0);
+}
+
+void DOMStorageNamespace::SwitchToNewAliasMaster(
+ DOMStorageNamespace* new_master,
+ DOMStorageContextImpl* context) {
+ DCHECK(alias_master_namespace());
+ scoped_refptr<DOMStorageNamespace> old_master = alias_master_namespace();
+ if (new_master->alias_master_namespace())
+ new_master = new_master->alias_master_namespace();
+ DCHECK(!new_master->alias_master_namespace());
+ DCHECK(old_master != this);
+ DCHECK(old_master != new_master);
+ DecrementMasterAliasCount();
+ alias_master_namespace_ = new_master;
+ alias_master_namespace_->num_aliases_++;
+ master_alias_count_decremented_ = false;
+ // There are three things that we need to clean up:
+ // -- the old master may ready for shutdown, if its last alias has disappeared
+ // -- The dom_storage hosts need to close and reopen their areas, so that
+ // they point to the correct new areas.
+ // -- The renderers will need to reset their local caches.
+ // All three of these things are accomplished with the following call below.
+ // |context| will be NULL in unit tests, which is when this will
+ // not apply, of course.
+ // During this call, open areas will be closed & reopened, so that they now
+ // come from the correct new master. Therefore, we must send close operations
+ // to the old master.
+ old_master_for_close_area_ = old_master.get();
+ if (context)
+ context->NotifyAliasSessionMerged(namespace_id(), old_master.get());
+ old_master_for_close_area_ = NULL;
+}
+
+DOMStorageNamespace::TransactionData::TransactionData()
+ : max_log_size_exceeded(false) {
+}
+
+DOMStorageNamespace::TransactionData::~TransactionData() {
+}
+
+DOMStorageNamespace::TransactionRecord::TransactionRecord() {
+}
+
+DOMStorageNamespace::TransactionRecord::~TransactionRecord() {
+}
+
// AreaHolder
DOMStorageNamespace::AreaHolder::AreaHolder()
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.h b/chromium/content/browser/dom_storage/dom_storage_namespace.h
index 5860685f807..5d18882834d 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.h
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.h
@@ -6,16 +6,20 @@
#define CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_NAMESPACE_H_
#include <map>
+#include <vector>
#include "base/basictypes.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
+#include "base/strings/nullable_string16.h"
#include "content/common/content_export.h"
+#include "content/public/browser/session_storage_namespace.h"
#include "url/gurl.h"
namespace content {
class DOMStorageArea;
+class DOMStorageContextImpl;
class DOMStorageTaskRunner;
class SessionStorageDatabase;
@@ -66,6 +70,10 @@ class CONTENT_EXPORT DOMStorageNamespace
DOMStorageNamespace* Clone(int64 clone_namespace_id,
const std::string& clone_persistent_namespace_id);
+ // Creates an alias of |this| namespace.
+ // Should only be called for session storage namespaces.
+ DOMStorageNamespace* CreateAlias(int64 alias_namespace_id);
+
void DeleteLocalStorageOrigin(const GURL& origin);
void DeleteSessionStorageOrigin(const GURL& origin);
void PurgeMemory(PurgeOption purge);
@@ -73,6 +81,50 @@ class CONTENT_EXPORT DOMStorageNamespace
unsigned int CountInMemoryAreas() const;
+ void AddTransactionLogProcessId(int process_id);
+ void RemoveTransactionLogProcessId(int process_id);
+ SessionStorageNamespace::MergeResult Merge(
+ bool actually_merge,
+ int process_id,
+ DOMStorageNamespace* other,
+ DOMStorageContextImpl* context);
+ DOMStorageNamespace* alias_master_namespace() {
+ return alias_master_namespace_.get();
+ }
+ int num_aliases() const { return num_aliases_; }
+ bool ready_for_deletion_pending_aliases() const {
+ return ready_for_deletion_pending_aliases_; }
+ void set_ready_for_deletion_pending_aliases(bool value) {
+ ready_for_deletion_pending_aliases_ = value;
+ }
+ bool must_persist_at_shutdown() const { return must_persist_at_shutdown_; }
+ void set_must_persist_at_shutdown(bool value) {
+ must_persist_at_shutdown_ = value;
+ }
+
+ enum LogType {
+ TRANSACTION_READ,
+ TRANSACTION_WRITE,
+ TRANSACTION_REMOVE,
+ TRANSACTION_CLEAR
+ };
+
+ struct CONTENT_EXPORT TransactionRecord {
+ LogType transaction_type;
+ GURL origin;
+ GURL page_url;
+ base::string16 key;
+ base::NullableString16 value;
+ TransactionRecord();
+ ~TransactionRecord();
+ };
+
+ void AddTransaction(int process_id, const TransactionRecord& transaction);
+ bool IsLoggingRenderer(int process_id);
+ // Decrements the count of aliases owned by the master, and returns true
+ // if the new count is 0.
+ bool DecrementMasterAliasCount();
+
private:
friend class base::RefCountedThreadSafe<DOMStorageNamespace>;
@@ -87,17 +139,43 @@ class CONTENT_EXPORT DOMStorageNamespace
};
typedef std::map<GURL, AreaHolder> AreaMap;
+ struct TransactionData {
+ bool max_log_size_exceeded;
+ std::vector<TransactionRecord> log;
+ TransactionData();
+ ~TransactionData();
+ };
+
~DOMStorageNamespace();
// Returns a pointer to the area holder in our map or NULL.
AreaHolder* GetAreaHolder(const GURL& origin);
+ // Switches the current alias DOM storage namespace to a new alias master.
+ void SwitchToNewAliasMaster(DOMStorageNamespace* new_master,
+ DOMStorageContextImpl* context);
+
int64 namespace_id_;
std::string persistent_namespace_id_;
base::FilePath directory_;
AreaMap areas_;
scoped_refptr<DOMStorageTaskRunner> task_runner_;
scoped_refptr<SessionStorageDatabase> session_storage_database_;
+ std::map<int, TransactionData*> transactions_;
+ int num_aliases_;
+ scoped_refptr<DOMStorageNamespace> alias_master_namespace_;
+ DOMStorageNamespace* old_master_for_close_area_;
+ // Indicates whether we have already decremented |num_aliases_| for this
+ // namespace in its alias master. We may only decrement it once, and around
+ // deletion, this instance will stick around a bit longer until its refcount
+ // drops to 0. Therefore, we want to make sure we don't decrement the master's
+ // alias count a second time.
+ bool master_alias_count_decremented_;
+ // This indicates, for an alias master, that the master itself is ready
+ // for deletion, but there are aliases outstanding that we have to wait for
+ // before we can start cleaning up the master.
+ bool ready_for_deletion_pending_aliases_;
+ bool must_persist_at_shutdown_;
};
} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_session.cc b/chromium/content/browser/dom_storage/dom_storage_session.cc
index 7706ec85064..c3b7a9e3046 100644
--- a/chromium/content/browser/dom_storage/dom_storage_session.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_session.cc
@@ -7,12 +7,33 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
+#include "base/single_thread_task_runner.h"
+#include "base/thread_task_runner_handle.h"
#include "base/tracked_objects.h"
#include "content/browser/dom_storage/dom_storage_context_impl.h"
#include "content/browser/dom_storage/dom_storage_task_runner.h"
namespace content {
+namespace {
+
+void PostMergeTaskResult(
+ const SessionStorageNamespace::MergeResultCallback& callback,
+ SessionStorageNamespace::MergeResult result) {
+ callback.Run(result);
+}
+
+void RunMergeTaskAndPostResult(
+ const base::Callback<SessionStorageNamespace::MergeResult(void)>& task,
+ scoped_refptr<base::SingleThreadTaskRunner> result_loop,
+ const SessionStorageNamespace::MergeResultCallback& callback) {
+ SessionStorageNamespace::MergeResult result = task.Run();
+ result_loop->PostTask(
+ FROM_HERE, base::Bind(&PostMergeTaskResult, callback, result));
+}
+
+} // namespace
+
DOMStorageSession::DOMStorageSession(DOMStorageContextImpl* context)
: context_(context),
namespace_id_(context->AllocateSessionId()),
@@ -36,6 +57,22 @@ DOMStorageSession::DOMStorageSession(DOMStorageContextImpl* context,
context_, namespace_id_, persistent_namespace_id_));
}
+DOMStorageSession::DOMStorageSession(
+ DOMStorageSession* master_dom_storage_session)
+ : context_(master_dom_storage_session->context_),
+ namespace_id_(master_dom_storage_session->context_->AllocateSessionId()),
+ persistent_namespace_id_(
+ master_dom_storage_session->persistent_namespace_id()),
+ should_persist_(false) {
+ context_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DOMStorageContextImpl::CreateAliasSessionNamespace,
+ context_,
+ master_dom_storage_session->namespace_id(),
+ namespace_id_,
+ persistent_namespace_id_));
+}
+
void DOMStorageSession::SetShouldPersist(bool should_persist) {
should_persist_ = should_persist;
}
@@ -81,4 +118,54 @@ DOMStorageSession::~DOMStorageSession() {
context_, namespace_id_, should_persist_));
}
+void DOMStorageSession::AddTransactionLogProcessId(int process_id) {
+ context_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DOMStorageContextImpl::AddTransactionLogProcessId,
+ context_, namespace_id_, process_id));
+}
+
+void DOMStorageSession::RemoveTransactionLogProcessId(int process_id) {
+ context_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DOMStorageContextImpl::RemoveTransactionLogProcessId,
+ context_, namespace_id_, process_id));
+}
+
+void DOMStorageSession::Merge(
+ bool actually_merge,
+ int process_id,
+ DOMStorageSession* other,
+ const SessionStorageNamespace::MergeResultCallback& callback) {
+ scoped_refptr<base::SingleThreadTaskRunner> current_loop(
+ base::ThreadTaskRunnerHandle::Get());
+ SessionStorageNamespace::MergeResultCallback cb =
+ base::Bind(&DOMStorageSession::ProcessMergeResult,
+ this,
+ actually_merge,
+ callback,
+ other->persistent_namespace_id());
+ context_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&RunMergeTaskAndPostResult,
+ base::Bind(&DOMStorageContextImpl::MergeSessionStorage,
+ context_, namespace_id_, actually_merge, process_id,
+ other->namespace_id_),
+ current_loop,
+ cb));
+}
+
+void DOMStorageSession::ProcessMergeResult(
+ bool actually_merge,
+ const SessionStorageNamespace::MergeResultCallback& callback,
+ const std::string& new_persistent_namespace_id,
+ SessionStorageNamespace::MergeResult result) {
+ if (actually_merge &&
+ (result == SessionStorageNamespace::MERGE_RESULT_MERGEABLE ||
+ result == SessionStorageNamespace::MERGE_RESULT_NO_TRANSACTIONS)) {
+ persistent_namespace_id_ = new_persistent_namespace_id;
+ }
+ callback.Run(result);
+}
+
} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_session.h b/chromium/content/browser/dom_storage/dom_storage_session.h
index 62c6d97252c..5e126216c60 100644
--- a/chromium/content/browser/dom_storage/dom_storage_session.h
+++ b/chromium/content/browser/dom_storage/dom_storage_session.h
@@ -9,6 +9,7 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
+#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/common/content_export.h"
namespace content {
@@ -30,6 +31,10 @@ class CONTENT_EXPORT DOMStorageSession
DOMStorageSession(DOMStorageContextImpl* context,
const std::string& persistent_namespace_id);
+ // Constructs a |DOMStorageSession| as an alias of
+ // |master_dom_storage_session|. Allocates a new non-persistent ID.
+ explicit DOMStorageSession(DOMStorageSession* master_dom_storage_session);
+
int64 namespace_id() const { return namespace_id_; }
const std::string& persistent_namespace_id() const {
return persistent_namespace_id_;
@@ -44,6 +49,13 @@ class CONTENT_EXPORT DOMStorageSession
static DOMStorageSession* CloneFrom(DOMStorageContextImpl* context,
int64 namepace_id_to_clone);
+ void AddTransactionLogProcessId(int process_id);
+ void RemoveTransactionLogProcessId(int process_id);
+ void Merge(bool actually_merge,
+ int process_id,
+ DOMStorageSession* other,
+ const SessionStorageNamespace::MergeResultCallback& callback);
+
private:
friend class base::RefCountedThreadSafe<DOMStorageSession>;
@@ -52,6 +64,12 @@ class CONTENT_EXPORT DOMStorageSession
const std::string& persistent_namespace_id);
~DOMStorageSession();
+ void ProcessMergeResult(
+ bool actually_merge,
+ const SessionStorageNamespace::MergeResultCallback& callback,
+ const std::string& new_persistent_namespace_id,
+ SessionStorageNamespace::MergeResult result);
+
scoped_refptr<DOMStorageContextImpl> context_;
int64 namespace_id_;
std::string persistent_namespace_id_;
diff --git a/chromium/content/browser/dom_storage/session_storage_database.cc b/chromium/content/browser/dom_storage/session_storage_database.cc
index bac3df7a67b..7b8dcd0bf0a 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database.cc
@@ -280,8 +280,7 @@ bool SessionStorageDatabase::LazyOpen(bool create_if_needed) {
return true;
if (!create_if_needed &&
- (!base::PathExists(file_path_) ||
- file_util::IsDirectoryEmpty(file_path_))) {
+ (!base::PathExists(file_path_) || base::IsDirectoryEmpty(file_path_))) {
// If the directory doesn't exist already and we haven't been asked to
// create a file on disk, then we don't bother opening the database. This
// means we wait until we absolutely need to put something onto disk before
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc b/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
index a1f7f2dd7f7..dab20332d53 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
@@ -25,6 +25,13 @@ SessionStorageNamespaceImpl::SessionStorageNamespaceImpl(
: session_(new DOMStorageSession(context->context(), persistent_id)) {
}
+SessionStorageNamespaceImpl::SessionStorageNamespaceImpl(
+ SessionStorageNamespaceImpl* master_session_storage_namespace)
+ : session_(new DOMStorageSession(
+ master_session_storage_namespace->session_)) {
+}
+
+
int64 SessionStorageNamespaceImpl::id() const {
return session_->namespace_id();
}
@@ -58,4 +65,31 @@ SessionStorageNamespaceImpl::SessionStorageNamespaceImpl(
SessionStorageNamespaceImpl::~SessionStorageNamespaceImpl() {
}
+void SessionStorageNamespaceImpl::AddTransactionLogProcessId(int process_id) {
+ session_->AddTransactionLogProcessId(process_id);
+}
+
+void SessionStorageNamespaceImpl::RemoveTransactionLogProcessId(
+ int process_id) {
+ session_->RemoveTransactionLogProcessId(process_id);
+}
+
+void SessionStorageNamespaceImpl::Merge(
+ bool actually_merge,
+ int process_id,
+ SessionStorageNamespace* other,
+ const MergeResultCallback& callback) {
+ SessionStorageNamespaceImpl* other_impl =
+ static_cast<SessionStorageNamespaceImpl*>(other);
+ session_->Merge(actually_merge, process_id, other_impl->session_, callback);
+}
+
+bool SessionStorageNamespaceImpl::IsAliasOf(SessionStorageNamespace* other) {
+ return persistent_id() == other->persistent_id();
+}
+
+SessionStorageNamespace* SessionStorageNamespaceImpl::CreateAlias() {
+ return new SessionStorageNamespaceImpl(this);
+}
+
} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl.h b/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
index d741848c9e8..ad010857243 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
@@ -34,6 +34,11 @@ class SessionStorageNamespaceImpl
SessionStorageNamespaceImpl(DOMStorageContextWrapper* context,
const std::string& persistent_id);
+ // Creates an alias of |master_session_storage_namespace|. This will allocate
+ // a new non-persistent ID.
+ explicit SessionStorageNamespaceImpl(
+ SessionStorageNamespaceImpl* master_session_storage_namespace);
+
// SessionStorageNamespace implementation.
virtual int64 id() const OVERRIDE;
virtual const std::string& persistent_id() const OVERRIDE;
@@ -43,6 +48,15 @@ class SessionStorageNamespaceImpl
SessionStorageNamespaceImpl* Clone();
bool IsFromContext(DOMStorageContextWrapper* context);
+ virtual void AddTransactionLogProcessId(int process_id) OVERRIDE;
+ virtual void RemoveTransactionLogProcessId(int process_id) OVERRIDE;
+ virtual void Merge(bool actually_merge,
+ int process_id,
+ SessionStorageNamespace* other,
+ const MergeResultCallback& callback) OVERRIDE;
+ virtual bool IsAliasOf(SessionStorageNamespace* other) OVERRIDE;
+ virtual SessionStorageNamespace* CreateAlias() OVERRIDE;
+
private:
explicit SessionStorageNamespaceImpl(DOMStorageSession* clone);
virtual ~SessionStorageNamespaceImpl();
diff --git a/chromium/content/browser/download/base_file.cc b/chromium/content/browser/download/base_file.cc
index 90ab485c361..1de3e842dd8 100644
--- a/chromium/content/browser/download/base_file.cc
+++ b/chromium/content/browser/download/base_file.cc
@@ -82,8 +82,8 @@ DownloadInterruptReason BaseFile::Initialize(
// |initial_directory| can still be empty if ContentBrowserClient returned
// an empty path for the downloads directory.
if ((initial_directory.empty() ||
- !file_util::CreateTemporaryFileInDir(initial_directory, &temp_file)) &&
- !file_util::CreateTemporaryFile(&temp_file)) {
+ !base::CreateTemporaryFileInDir(initial_directory, &temp_file)) &&
+ !base::CreateTemporaryFile(&temp_file)) {
return LogInterruptReason("Unable to create", 0,
DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
}
@@ -165,7 +165,7 @@ DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) {
net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED,
base::Bind(&FileRenamedNetLogCallback, &full_path_, &new_path));
Close();
- file_util::CreateDirectory(new_path.DirName());
+ base::CreateDirectory(new_path.DirName());
// A simple rename wouldn't work here since we want the file to have
// permissions / security descriptors that makes sense in the new directory.
diff --git a/chromium/content/browser/download/base_file_unittest.cc b/chromium/content/browser/download/base_file_unittest.cc
index b82b0a8ab70..4ab0c2ae8f6 100644
--- a/chromium/content/browser/download/base_file_unittest.cc
+++ b/chromium/content/browser/download/base_file_unittest.cc
@@ -464,7 +464,7 @@ TEST_F(BaseFileTest, RenameWithError) {
// TestDir is a subdirectory in |temp_dir_| that we will make read-only so
// that the rename will fail.
base::FilePath test_dir(temp_dir_.path().AppendASCII("TestDir"));
- ASSERT_TRUE(file_util::CreateDirectory(test_dir));
+ ASSERT_TRUE(base::CreateDirectory(test_dir));
base::FilePath new_path(test_dir.AppendASCII("TestFile"));
EXPECT_FALSE(base::PathExists(new_path));
@@ -482,7 +482,7 @@ TEST_F(BaseFileTest, RenameWithError) {
// Write data to the file multiple times.
TEST_F(BaseFileTest, MultipleWritesWithError) {
base::FilePath path;
- ASSERT_TRUE(file_util::CreateTemporaryFile(&path));
+ ASSERT_TRUE(base::CreateTemporaryFile(&path));
// Create a new file stream. scoped_ptr takes ownership and passes it to
// BaseFile; we use the pointer anyway and rely on the BaseFile not
// deleting the MockFileStream until the BaseFile is reset.
@@ -623,8 +623,7 @@ TEST_F(BaseFileTest, CreatedInDefaultDirectory) {
// be a string-wise match to base_file_->full_path().DirName() even though
// they are in the same directory.
base::FilePath temp_file;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file));
ASSERT_FALSE(temp_file.empty());
EXPECT_STREQ(temp_file.DirName().value().c_str(),
base_file_->full_path().DirName().value().c_str());
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc
index 767819edbcf..80c83e81bc2 100644
--- a/chromium/content/browser/download/download_browsertest.cc
+++ b/chromium/content/browser/download/download_browsertest.cc
@@ -1125,12 +1125,12 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
switches::kEnableDownloadResumption);
ASSERT_TRUE(test_server()->Start());
- GURL url = test_server()->GetURL(
- base::StringPrintf(
- // First download hits an RST, rest don't, precondition fail.
- "rangereset?size=%d&rst_boundary=%d&"
- "token=NoRange&rst_limit=1&fail_precondition=2",
- GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
+ GURL url = test_server()->GetURL(base::StringPrintf(
+ // First download hits an RST, rest don't, precondition fail.
+ "rangereset?size=%d&rst_boundary=%d&"
+ "token=BadPrecondition&rst_limit=1&fail_precondition=2",
+ GetSafeBufferChunk() * 3,
+ GetSafeBufferChunk()));
// Start the download and wait for first data chunk.
DownloadItem* download(StartDownloadAndReturnItem(url));
@@ -1142,6 +1142,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
ConfirmFileStatusForResume(
download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
+ EXPECT_EQ("BadPrecondition2", download->GetETag());
DownloadUpdatedObserver completion_observer(
download, base::Bind(DownloadCompleteFilter));
@@ -1151,6 +1152,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
ConfirmFileStatusForResume(
download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
base::FilePath(FILE_PATH_LITERAL("rangereset")));
+ EXPECT_EQ("BadPrecondition0", download->GetETag());
static const RecordingDownloadObserver::RecordStruct expected_record[] = {
// Result of RST
diff --git a/chromium/content/browser/download/download_create_info.cc b/chromium/content/browser/download/download_create_info.cc
index 8c47cabd038..e381fa854bd 100644
--- a/chromium/content/browser/download/download_create_info.cc
+++ b/chromium/content/browser/download/download_create_info.cc
@@ -11,20 +11,19 @@
namespace content {
-DownloadCreateInfo::DownloadCreateInfo(
- const base::Time& start_time,
- int64 total_bytes,
- const net::BoundNetLog& bound_net_log,
- bool has_user_gesture,
- PageTransition transition_type)
+DownloadCreateInfo::DownloadCreateInfo(const base::Time& start_time,
+ int64 total_bytes,
+ const net::BoundNetLog& bound_net_log,
+ bool has_user_gesture,
+ PageTransition transition_type,
+ scoped_ptr<DownloadSaveInfo> save_info)
: start_time(start_time),
total_bytes(total_bytes),
download_id(DownloadItem::kInvalidId),
has_user_gesture(has_user_gesture),
transition_type(transition_type),
- save_info(new DownloadSaveInfo()),
- request_bound_net_log(bound_net_log) {
-}
+ save_info(save_info.Pass()),
+ request_bound_net_log(bound_net_log) {}
DownloadCreateInfo::DownloadCreateInfo()
: total_bytes(0),
diff --git a/chromium/content/browser/download/download_create_info.h b/chromium/content/browser/download/download_create_info.h
index 4326b2428b0..e032fbf293d 100644
--- a/chromium/content/browser/download/download_create_info.h
+++ b/chromium/content/browser/download/download_create_info.h
@@ -28,7 +28,8 @@ struct CONTENT_EXPORT DownloadCreateInfo {
int64 total_bytes,
const net::BoundNetLog& bound_net_log,
bool has_user_gesture,
- PageTransition transition_type);
+ PageTransition transition_type,
+ scoped_ptr<DownloadSaveInfo> save_info);
DownloadCreateInfo();
~DownloadCreateInfo();
diff --git a/chromium/content/browser/download/download_file_unittest.cc b/chromium/content/browser/download/download_file_unittest.cc
index dcc0e424bd2..141808685f7 100644
--- a/chromium/content/browser/download/download_file_unittest.cc
+++ b/chromium/content/browser/download/download_file_unittest.cc
@@ -195,7 +195,7 @@ class DownloadFileTest : public testing::Test {
void VerifyStreamAndSize() {
::testing::Mock::VerifyAndClearExpectations(input_stream_);
int64 size;
- EXPECT_TRUE(file_util::GetFileSize(download_file_->FullPath(), &size));
+ EXPECT_TRUE(base::GetFileSize(download_file_->FullPath(), &size));
EXPECT_EQ(expected_data_.size(), static_cast<size_t>(size));
}
@@ -461,7 +461,7 @@ TEST_F(DownloadFileTest, RenameError) {
// Create a subdirectory.
base::FilePath tempdir(
initial_path.DirName().Append(FILE_PATH_LITERAL("tempdir")));
- ASSERT_TRUE(file_util::CreateDirectory(tempdir));
+ ASSERT_TRUE(base::CreateDirectory(tempdir));
base::FilePath target_path(tempdir.Append(initial_path.BaseName()));
// Targets
diff --git a/chromium/content/browser/download/download_item_impl.cc b/chromium/content/browser/download/download_item_impl.cc
index e2e86a34eb6..b8f78ff56ef 100644
--- a/chromium/content/browser/download/download_item_impl.cc
+++ b/chromium/content/browser/download/download_item_impl.cc
@@ -294,7 +294,8 @@ void DownloadItemImpl::ValidateDangerousDownload() {
if (IsDone() || !IsDangerous())
return;
- RecordDangerousDownloadAccept(GetDangerType());
+ RecordDangerousDownloadAccept(GetDangerType(),
+ GetTargetFilePath());
danger_type_ = DOWNLOAD_DANGER_TYPE_USER_VALIDATED;
@@ -380,7 +381,8 @@ void DownloadItemImpl::Cancel(bool user_cancel) {
RecordDangerousDownloadDiscard(
user_cancel ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION
: DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN,
- GetDangerType());
+ GetDangerType(),
+ GetTargetFilePath());
}
last_reason_ = user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
@@ -894,6 +896,50 @@ DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const {
return mode;
}
+void DownloadItemImpl::MergeOriginInfoOnResume(
+ const DownloadCreateInfo& new_create_info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_EQ(RESUMING_INTERNAL, state_);
+ DCHECK(!new_create_info.url_chain.empty());
+
+ // We are going to tack on any new redirects to our list of redirects.
+ // When a download is resumed, the URL used for the resumption request is the
+ // one at the end of the previous redirect chain. Tacking additional redirects
+ // to the end of this chain ensures that:
+ // - If the download needs to be resumed again, the ETag/Last-Modified headers
+ // will be used with the last server that sent them to us.
+ // - The redirect chain contains all the servers that were involved in this
+ // download since the initial request, in order.
+ std::vector<GURL>::const_iterator chain_iter =
+ new_create_info.url_chain.begin();
+ if (*chain_iter == url_chain_.back())
+ ++chain_iter;
+
+ // Record some stats. If the precondition failed (the server returned
+ // HTTP_PRECONDITION_FAILED), then the download will automatically retried as
+ // a full request rather than a partial. Full restarts clobber validators.
+ int origin_state = 0;
+ if (chain_iter != new_create_info.url_chain.end())
+ origin_state |= ORIGIN_STATE_ON_RESUMPTION_ADDITIONAL_REDIRECTS;
+ if (etag_ != new_create_info.etag ||
+ last_modified_time_ != new_create_info.last_modified)
+ origin_state |= ORIGIN_STATE_ON_RESUMPTION_VALIDATORS_CHANGED;
+ if (content_disposition_ != new_create_info.content_disposition)
+ origin_state |= ORIGIN_STATE_ON_RESUMPTION_CONTENT_DISPOSITION_CHANGED;
+ RecordOriginStateOnResumption(new_create_info.save_info->offset != 0,
+ origin_state);
+
+ url_chain_.insert(
+ url_chain_.end(), chain_iter, new_create_info.url_chain.end());
+ etag_ = new_create_info.etag;
+ last_modified_time_ = new_create_info.last_modified;
+ content_disposition_ = new_create_info.content_disposition;
+
+ // Don't update observers. This method is expected to be called just before a
+ // DownloadFile is created and Start() is called. The observers will be
+ // notified when the download transitions to the IN_PROGRESS state.
+}
+
void DownloadItemImpl::NotifyRemoved() {
FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this));
}
@@ -1545,6 +1591,18 @@ void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) {
net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED,
base::Bind(&ItemCheckedNetLogCallback, danger_type));
}
+ // Only record the Malicious UMA stat if it's going from {not malicious} ->
+ // {malicious}.
+ if ((danger_type_ == DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
+ danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE ||
+ danger_type_ == DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT ||
+ danger_type_ == DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT) &&
+ (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST ||
+ danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_URL ||
+ danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT ||
+ danger_type == DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED)) {
+ RecordMaliciousDownloadClassified(danger_type);
+ }
danger_type_ = danger_type;
}
diff --git a/chromium/content/browser/download/download_item_impl.h b/chromium/content/browser/download/download_item_impl.h
index 2086a54a89d..804afa671b7 100644
--- a/chromium/content/browser/download/download_item_impl.h
+++ b/chromium/content/browser/download/download_item_impl.h
@@ -163,6 +163,11 @@ class CONTENT_EXPORT DownloadItemImpl
// INTERRUPTED state.
virtual ResumeMode GetResumeMode() const;
+ // Notify the download item that new origin information is available due to a
+ // resumption request receiving a response.
+ virtual void MergeOriginInfoOnResume(
+ const DownloadCreateInfo& new_create_info);
+
// State transition operations on regular downloads --------------------------
// Start the download.
diff --git a/chromium/content/browser/download/download_item_impl_unittest.cc b/chromium/content/browser/download/download_item_impl_unittest.cc
index ff5d32602fa..9abe3417e7e 100644
--- a/chromium/content/browser/download/download_item_impl_unittest.cc
+++ b/chromium/content/browser/download/download_item_impl_unittest.cc
@@ -30,15 +30,10 @@ using ::testing::Return;
using ::testing::SaveArg;
using ::testing::StrictMock;
-namespace {
-
const int kDownloadChunkSize = 1000;
const int kDownloadSpeed = 1000;
-const int kDummyDBHandle = 10;
const base::FilePath::CharType kDummyPath[] = FILE_PATH_LITERAL("/testpath");
-} // namespace
-
namespace content {
namespace {
diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc
index ccfb4cc0a51..4f2e68a908f 100644
--- a/chromium/content/browser/download/download_manager_impl.cc
+++ b/chromium/content/browser/download/download_manager_impl.cc
@@ -40,6 +40,7 @@
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/referrer.h"
#include "net/base/load_flags.h"
+#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/url_request/url_request_context.h"
@@ -55,8 +56,8 @@ void BeginDownload(scoped_ptr<DownloadUrlParameters> params,
// we must down cast. RDHI is the only subclass of RDH as of 2012 May 4.
scoped_ptr<net::URLRequest> request(
params->resource_context()->GetRequestContext()->CreateRequest(
- params->url(), NULL));
- request->set_load_flags(request->load_flags() | params->load_flags());
+ params->url(), net::DEFAULT_PRIORITY, NULL));
+ request->SetLoadFlags(request->load_flags() | params->load_flags());
request->set_method(params->method());
if (!params->post_body().empty()) {
const std::string& body = params->post_body();
@@ -71,10 +72,10 @@ void BeginDownload(scoped_ptr<DownloadUrlParameters> params,
// to do a re-POST without user consent, and currently don't have a good
// plan on how to display the UI for that.
DCHECK(params->prefer_cache());
- DCHECK(params->method() == "POST");
+ DCHECK_EQ("POST", params->method());
ScopedVector<net::UploadElementReader> element_readers;
request->set_upload(make_scoped_ptr(
- new net::UploadDataStream(&element_readers, params->post_id())));
+ new net::UploadDataStream(element_readers.Pass(), params->post_id())));
}
// If we're not at the beginning of the file, retrieve only the remaining
@@ -108,7 +109,7 @@ void BeginDownload(scoped_ptr<DownloadUrlParameters> params,
iter != params->request_headers_end();
++iter) {
request->SetExtraRequestHeaderByName(
- iter->first, iter->second, false/*overwrite*/);
+ iter->first, iter->second, false /*overwrite*/);
}
scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
@@ -156,13 +157,6 @@ class MapValueIteratorAdapter {
// Allow copy and assign.
};
-void EnsureNoPendingDownloadJobsOnFile(bool* result) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- *result = (DownloadFile::GetNumberOfDownloadFiles() == 0);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
-}
-
class DownloadItemFactoryImpl : public DownloadItemFactory {
public:
DownloadItemFactoryImpl() {}
@@ -404,6 +398,7 @@ void DownloadManagerImpl::StartDownloadWithId(
}
download = item_iterator->second;
DCHECK_EQ(DownloadItem::INTERRUPTED, download->GetState());
+ download->MergeOriginInfoOnResume(*info);
}
base::FilePath default_download_directory;
@@ -419,7 +414,7 @@ void DownloadManagerImpl::StartDownloadWithId(
file_factory_->CreateFile(
info->save_info.Pass(), default_download_directory,
info->url(), info->referrer_url,
- delegate_->GenerateFileHash(),
+ delegate_ && delegate_->GenerateFileHash(),
stream.Pass(), download->GetBoundNetLog(),
download->DestinationObserverAsWeakPtr()));
@@ -561,11 +556,9 @@ void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) {
return;
uint32 download_id = download->GetId();
- if (downloads_.find(download_id) == downloads_.end())
+ if (downloads_.erase(download_id) == 0)
return;
-
delete download;
- downloads_.erase(download_id);
}
int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin,
@@ -605,7 +598,7 @@ void DownloadManagerImpl::DownloadUrl(
if (params->post_id() >= 0) {
// Check this here so that the traceback is more useful.
DCHECK(params->prefer_cache());
- DCHECK(params->method() == "POST");
+ DCHECK_EQ("POST", params->method());
}
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
&BeginDownload, base::Passed(&params),
@@ -636,9 +629,10 @@ DownloadItem* DownloadManagerImpl::CreateDownloadItem(
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
bool opened) {
- DCHECK(!ContainsKey(downloads_, id));
- if (ContainsKey(downloads_, id))
+ if (ContainsKey(downloads_, id)) {
+ NOTREACHED();
return NULL;
+ }
DownloadItemImpl* item = item_factory_->CreatePersistedItem(
this,
id,
@@ -673,6 +667,22 @@ int DownloadManagerImpl::InProgressCount() const {
return count;
}
+int DownloadManagerImpl::NonMaliciousInProgressCount() const {
+ int count = 0;
+ for (DownloadMap::const_iterator it = downloads_.begin();
+ it != downloads_.end(); ++it) {
+ if (it->second->GetState() == DownloadItem::IN_PROGRESS &&
+ it->second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_URL &&
+ it->second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT &&
+ it->second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST &&
+ it->second->GetDangerType() !=
+ DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED) {
+ ++count;
+ }
+ }
+ return count;
+}
+
DownloadItem* DownloadManagerImpl::GetDownload(uint32 download_id) {
return ContainsKey(downloads_, download_id) ? downloads_[download_id] : NULL;
}
diff --git a/chromium/content/browser/download/download_manager_impl.h b/chromium/content/browser/download/download_manager_impl.h
index a9384c7567f..6381417832e 100644
--- a/chromium/content/browser/download/download_manager_impl.h
+++ b/chromium/content/browser/download/download_manager_impl.h
@@ -89,6 +89,7 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
DownloadInterruptReason interrupt_reason,
bool opened) OVERRIDE;
virtual int InProgressCount() const OVERRIDE;
+ virtual int NonMaliciousInProgressCount() const OVERRIDE;
virtual BrowserContext* GetBrowserContext() const OVERRIDE;
virtual void CheckForHistoryFilesRemoval() OVERRIDE;
virtual DownloadItem* GetDownload(uint32 id) OVERRIDE;
diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc
index 0865c04b2fa..3afc41ad5af 100644
--- a/chromium/content/browser/download/download_manager_impl_unittest.cc
+++ b/chromium/content/browser/download/download_manager_impl_unittest.cc
@@ -120,7 +120,7 @@ class MockDownloadItemImpl : public DownloadItemImpl {
MOCK_CONST_METHOD0(CurrentSpeed, int64());
MOCK_CONST_METHOD0(PercentComplete, int());
MOCK_CONST_METHOD0(AllDataSaved, bool());
- MOCK_CONST_METHOD1(MatchesQuery, bool(const string16& query));
+ MOCK_CONST_METHOD1(MatchesQuery, bool(const base::string16& query));
MOCK_CONST_METHOD0(IsDone, bool());
MOCK_CONST_METHOD0(GetFullPath, const base::FilePath&());
MOCK_CONST_METHOD0(GetTargetFilePath, const base::FilePath&());
@@ -404,11 +404,17 @@ class MockBrowserContext : public BrowserContext {
MOCK_METHOD2(GetMediaRequestContextForStoragePartition,
net::URLRequestContextGetter*(
const base::FilePath& partition_path, bool in_memory));
- MOCK_METHOD4(RequestMIDISysExPermission,
+ MOCK_METHOD5(RequestMIDISysExPermission,
void(int render_process_id,
int render_view_id,
+ int bridge_id,
const GURL& requesting_frame,
const MIDISysExPermissionCallback& callback));
+ MOCK_METHOD4(CancelMIDISysExPermissionRequest,
+ void(int render_process_id,
+ int render_view_id,
+ int bridge_id,
+ const GURL& requesting_frame));
MOCK_METHOD0(GetResourceContext, ResourceContext*());
MOCK_METHOD0(GetDownloadManagerDelegate, DownloadManagerDelegate*());
MOCK_METHOD0(GetGeolocationPermissionContext,
diff --git a/chromium/content/browser/download/download_resource_handler.cc b/chromium/content/browser/download/download_resource_handler.cc
index ed4edff67fe..9f00ef660b5 100644
--- a/chromium/content/browser/download/download_resource_handler.cc
+++ b/chromium/content/browser/download/download_resource_handler.cc
@@ -74,10 +74,8 @@ DownloadResourceHandler::DownloadResourceHandler(
net::URLRequest* request,
const DownloadUrlParameters::OnStartedCallback& started_cb,
scoped_ptr<DownloadSaveInfo> save_info)
- : download_id_(id),
- render_view_id_(0), // Actually initialized below.
- content_length_(0),
- request_(request),
+ : ResourceHandler(request),
+ download_id_(id),
started_cb_(started_cb),
save_info_(save_info.Pass()),
last_buffer_size_(0),
@@ -85,10 +83,6 @@ DownloadResourceHandler::DownloadResourceHandler(
pause_count_(0),
was_deferred_(false),
on_response_started_called_(false) {
- ResourceRequestInfoImpl* info(ResourceRequestInfoImpl::ForRequest(request));
- global_id_ = info->GetGlobalRequestID();
- render_view_id_ = info->GetRouteID();
-
RecordDownloadCount(UNTHROTTLED_COUNT);
}
@@ -105,7 +99,7 @@ bool DownloadResourceHandler::OnRequestRedirected(
bool* defer) {
// We treat a download as a main frame load, and thus update the policy URL
// on redirects.
- request_->set_first_party_for_cookies(url);
+ request()->set_first_party_for_cookies(url);
return true;
}
@@ -124,26 +118,28 @@ bool DownloadResourceHandler::OnResponseStarted(
download_start_time_ = base::TimeTicks::Now();
// If it's a download, we don't want to poison the cache with it.
- request_->StopCaching();
+ request()->StopCaching();
// Lower priority as well, so downloads don't contend for resources
// with main frames.
- request_->SetPriority(net::IDLE);
+ request()->SetPriority(net::IDLE);
- std::string content_disposition;
- request_->GetResponseHeaderByName("content-disposition",
- &content_disposition);
- SetContentDisposition(content_disposition);
- SetContentLength(response->head.content_length);
+ // If the content-length header is not present (or contains something other
+ // than numbers), the incoming content_length is -1 (unknown size).
+ // Set the content length to 0 to indicate unknown size to DownloadManager.
+ int64 content_length =
+ response->head.content_length > 0 ? response->head.content_length : 0;
- const ResourceRequestInfoImpl* request_info =
- ResourceRequestInfoImpl::ForRequest(request_);
+ const ResourceRequestInfoImpl* request_info = GetRequestInfo();
// Deleted in DownloadManager.
- scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo(
- base::Time::Now(), content_length_,
- request_->net_log(), request_info->HasUserGesture(),
- request_info->GetPageTransition()));
+ scoped_ptr<DownloadCreateInfo> info(
+ new DownloadCreateInfo(base::Time::Now(),
+ content_length,
+ request()->net_log(),
+ request_info->HasUserGesture(),
+ request_info->GetPageTransition(),
+ save_info_.Pass()));
// Create the ByteStream for sending data to the download sink.
scoped_ptr<ByteStreamReader> stream_reader;
@@ -155,53 +151,45 @@ bool DownloadResourceHandler::OnResponseStarted(
base::Bind(&DownloadResourceHandler::ResumeRequest, AsWeakPtr()));
info->download_id = download_id_;
- info->url_chain = request_->url_chain();
- info->referrer_url = GURL(request_->referrer());
- info->start_time = base::Time::Now();
- info->total_bytes = content_length_;
- info->has_user_gesture = request_info->HasUserGesture();
- info->content_disposition = content_disposition_;
+ info->url_chain = request()->url_chain();
+ info->referrer_url = GURL(request()->referrer());
info->mime_type = response->head.mime_type;
- info->remote_address = request_->GetSocketAddress().host();
+ info->remote_address = request()->GetSocketAddress().host();
+ request()->GetResponseHeaderByName("content-disposition",
+ &info->content_disposition);
RecordDownloadMimeType(info->mime_type);
RecordDownloadContentDisposition(info->content_disposition);
info->request_handle =
- DownloadRequestHandle(AsWeakPtr(), global_id_.child_id,
- render_view_id_, global_id_.request_id);
+ DownloadRequestHandle(AsWeakPtr(), request_info->GetChildID(),
+ request_info->GetRouteID(),
+ request_info->GetRequestID());
// Get the last modified time and etag.
- const net::HttpResponseHeaders* headers = request_->response_headers();
+ const net::HttpResponseHeaders* headers = request()->response_headers();
if (headers) {
- std::string last_modified_hdr;
- if (headers->EnumerateHeader(NULL, "Last-Modified", &last_modified_hdr))
- info->last_modified = last_modified_hdr;
- if (headers->EnumerateHeader(NULL, "ETag", &etag_))
- info->etag = etag_;
+ if (headers->HasStrongValidators()) {
+ // If we don't have strong validators as per RFC 2616 section 13.3.3, then
+ // we neither store nor use them for range requests.
+ if (!headers->EnumerateHeader(NULL, "Last-Modified",
+ &info->last_modified))
+ info->last_modified.clear();
+ if (!headers->EnumerateHeader(NULL, "ETag", &info->etag))
+ info->etag.clear();
+ }
int status = headers->response_code();
if (2 == status / 100 && status != net::HTTP_PARTIAL_CONTENT) {
// Success & not range response; if we asked for a range, we didn't
// get it--reset the file pointers to reflect that.
- save_info_->offset = 0;
- save_info_->hash_state = "";
+ info->save_info->offset = 0;
+ info->save_info->hash_state = "";
}
- }
-
- std::string content_type_header;
- if (!response->head.headers.get() ||
- !response->head.headers->GetMimeType(&content_type_header))
- content_type_header = "";
- info->original_mime_type = content_type_header;
- if (!response->head.headers.get() ||
- !response->head.headers->EnumerateHeader(
- NULL, "Accept-Ranges", &accept_ranges_)) {
- accept_ranges_ = "";
+ if (!headers->GetMimeType(&info->original_mime_type))
+ info->original_mime_type.clear();
}
- info->save_info = save_info_.Pass();
-
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&StartOnUIThread,
@@ -236,8 +224,10 @@ bool DownloadResourceHandler::OnWillStart(int request_id,
// Create a new buffer, which will be handed to the download thread for file
// writing and deletion.
-bool DownloadResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
- int* buf_size, int min_size) {
+bool DownloadResourceHandler::OnWillRead(int request_id,
+ scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(buf && buf_size);
DCHECK(!read_buffer_.get());
@@ -290,12 +280,13 @@ bool DownloadResourceHandler::OnReadCompleted(int request_id, int bytes_read,
return true;
}
-bool DownloadResourceHandler::OnResponseCompleted(
+void DownloadResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) {
+ const std::string& security_info,
+ bool* defer) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- int response_code = status.is_success() ? request_->GetResponseCode() : 0;
+ int response_code = status.is_success() ? request()->GetResponseCode() : 0;
VLOG(20) << __FUNCTION__ << "()" << DebugString()
<< " request_id = " << request_id
<< " status.status() = " << status.status()
@@ -339,7 +330,7 @@ bool DownloadResourceHandler::OnResponseCompleted(
if (status.is_success() &&
reason == DOWNLOAD_INTERRUPT_REASON_NONE &&
- request_->response_headers()) {
+ request()->response_headers()) {
// Handle server's response codes.
switch(response_code) {
case -1: // Non-HTTP request.
@@ -375,9 +366,17 @@ bool DownloadResourceHandler::OnResponseCompleted(
}
}
- RecordAcceptsRanges(accept_ranges_, bytes_read_, etag_);
- RecordNetworkBlockage(
- base::TimeTicks::Now() - download_start_time_, total_pause_time_);
+ std::string accept_ranges;
+ bool has_strong_validators = false;
+ if (request()->response_headers()) {
+ request()->response_headers()->EnumerateHeader(
+ NULL, "Accept-Ranges", &accept_ranges);
+ has_strong_validators =
+ request()->response_headers()->HasStrongValidators();
+ }
+ RecordAcceptsRanges(accept_ranges, bytes_read_, has_strong_validators);
+ RecordNetworkBlockage(base::TimeTicks::Now() - download_start_time_,
+ total_pause_time_);
CallStartedCB(NULL, error_code);
@@ -396,8 +395,6 @@ bool DownloadResourceHandler::OnResponseCompleted(
stream_writer_.reset(); // We no longer need the stream.
read_buffer_ = NULL;
-
- return true;
}
void DownloadResourceHandler::OnDataDownloaded(
@@ -406,22 +403,6 @@ void DownloadResourceHandler::OnDataDownloaded(
NOTREACHED();
}
-// If the content-length header is not present (or contains something other
-// than numbers), the incoming content_length is -1 (unknown size).
-// Set the content length to 0 to indicate unknown size to DownloadManager.
-void DownloadResourceHandler::SetContentLength(const int64& content_length) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- content_length_ = 0;
- if (content_length > 0)
- content_length_ = content_length;
-}
-
-void DownloadResourceHandler::SetContentDisposition(
- const std::string& content_disposition) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- content_disposition_ = content_disposition;
-}
-
void DownloadResourceHandler::PauseRequest() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -451,27 +432,29 @@ void DownloadResourceHandler::ResumeRequest() {
void DownloadResourceHandler::CancelRequest() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ const ResourceRequestInfo* info = GetRequestInfo();
ResourceDispatcherHostImpl::Get()->CancelRequest(
- global_id_.child_id,
- global_id_.request_id,
+ info->GetChildID(),
+ info->GetRequestID(),
false);
}
std::string DownloadResourceHandler::DebugString() const {
+ const ResourceRequestInfo* info = GetRequestInfo();
return base::StringPrintf("{"
" url_ = " "\"%s\""
- " global_id_ = {"
+ " info = {"
" child_id = " "%d"
" request_id = " "%d"
+ " route_id = " "%d"
" }"
- " render_view_id_ = " "%d"
" }",
- request_ ?
- request_->url().spec().c_str() :
+ request() ?
+ request()->url().spec().c_str() :
"<NULL request>",
- global_id_.child_id,
- global_id_.request_id,
- render_view_id_);
+ info->GetChildID(),
+ info->GetRequestID(),
+ info->GetRouteID());
}
DownloadResourceHandler::~DownloadResourceHandler() {
diff --git a/chromium/content/browser/download/download_resource_handler.h b/chromium/content/browser/download/download_resource_handler.h
index 60fbc944387..36bb0d27005 100644
--- a/chromium/content/browser/download/download_resource_handler.h
+++ b/chromium/content/browser/download/download_resource_handler.h
@@ -67,16 +67,17 @@ class CONTENT_EXPORT DownloadResourceHandler
// Create a new buffer, which will be handed to the download thread for file
// writing and deletion.
virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) OVERRIDE;
virtual bool OnReadCompleted(int request_id, int bytes_read,
bool* defer) OVERRIDE;
- virtual bool OnResponseCompleted(int request_id,
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) OVERRIDE;
+ const std::string& security_info,
+ bool* defer) OVERRIDE;
// N/A to this flavor of DownloadHandler.
virtual void OnDataDownloaded(int request_id, int bytes_downloaded) OVERRIDE;
@@ -95,19 +96,7 @@ class CONTENT_EXPORT DownloadResourceHandler
// on the IO thread.
void CallStartedCB(DownloadItem* item, net::Error error);
- // If the content-length header is not present (or contains something other
- // than numbers), the incoming content_length is -1 (unknown size).
- // Set the content length to 0 to indicate unknown size to DownloadManager.
- void SetContentLength(const int64& content_length);
-
- void SetContentDisposition(const std::string& content_disposition);
-
uint32 download_id_;
- GlobalRequestID global_id_;
- int render_view_id_;
- std::string content_disposition_;
- int64 content_length_;
- net::URLRequest* request_;
// This is read only on the IO thread, but may only
// be called on the UI thread.
DownloadUrlParameters::OnStartedCallback started_cb_;
@@ -124,8 +113,6 @@ class CONTENT_EXPORT DownloadResourceHandler
base::TimeDelta total_pause_time_;
size_t last_buffer_size_;
int64 bytes_read_;
- std::string accept_ranges_;
- std::string etag_;
int pause_count_;
bool was_deferred_;
diff --git a/chromium/content/browser/download/download_stats.cc b/chromium/content/browser/download/download_stats.cc
index 7831a4db32a..66716cac415 100644
--- a/chromium/content/browser/download/download_stats.cc
+++ b/chromium/content/browser/download/download_stats.cc
@@ -5,6 +5,7 @@
#include "content/browser/download/download_stats.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
#include "base/strings/string_util.h"
#include "content/browser/download/download_resource_handler.h"
#include "content/public/browser/download_interrupt_reasons.h"
@@ -66,6 +67,144 @@ void RecordContentDispositionCountFlag(
RecordContentDispositionCount(type, (flags_to_test & flag) == flag);
}
+// Do not insert, delete, or reorder; this is being histogrammed. Append only.
+// All of the download_extensions.cc file types should be in this list.
+const base::FilePath::CharType* kDangerousFileTypes[] = {
+ FILE_PATH_LITERAL(".ad"),
+ FILE_PATH_LITERAL(".ade"),
+ FILE_PATH_LITERAL(".adp"),
+ FILE_PATH_LITERAL(".ah"),
+ FILE_PATH_LITERAL(".apk"),
+ FILE_PATH_LITERAL(".app"),
+ FILE_PATH_LITERAL(".application"),
+ FILE_PATH_LITERAL(".asp"),
+ FILE_PATH_LITERAL(".asx"),
+ FILE_PATH_LITERAL(".bas"),
+ FILE_PATH_LITERAL(".bash"),
+ FILE_PATH_LITERAL(".bat"),
+ FILE_PATH_LITERAL(".cfg"),
+ FILE_PATH_LITERAL(".chi"),
+ FILE_PATH_LITERAL(".chm"),
+ FILE_PATH_LITERAL(".class"),
+ FILE_PATH_LITERAL(".cmd"),
+ FILE_PATH_LITERAL(".com"),
+ FILE_PATH_LITERAL(".command"),
+ FILE_PATH_LITERAL(".crt"),
+ FILE_PATH_LITERAL(".crx"),
+ FILE_PATH_LITERAL(".csh"),
+ FILE_PATH_LITERAL(".deb"),
+ FILE_PATH_LITERAL(".dex"),
+ FILE_PATH_LITERAL(".dll"),
+ FILE_PATH_LITERAL(".drv"),
+ FILE_PATH_LITERAL(".exe"),
+ FILE_PATH_LITERAL(".fxp"),
+ FILE_PATH_LITERAL(".grp"),
+ FILE_PATH_LITERAL(".hlp"),
+ FILE_PATH_LITERAL(".hta"),
+ FILE_PATH_LITERAL(".htm"),
+ FILE_PATH_LITERAL(".html"),
+ FILE_PATH_LITERAL(".htt"),
+ FILE_PATH_LITERAL(".inf"),
+ FILE_PATH_LITERAL(".ini"),
+ FILE_PATH_LITERAL(".ins"),
+ FILE_PATH_LITERAL(".isp"),
+ FILE_PATH_LITERAL(".jar"),
+ FILE_PATH_LITERAL(".jnlp"),
+ FILE_PATH_LITERAL(".user.js"),
+ FILE_PATH_LITERAL(".js"),
+ FILE_PATH_LITERAL(".jse"),
+ FILE_PATH_LITERAL(".ksh"),
+ FILE_PATH_LITERAL(".lnk"),
+ FILE_PATH_LITERAL(".local"),
+ FILE_PATH_LITERAL(".mad"),
+ FILE_PATH_LITERAL(".maf"),
+ FILE_PATH_LITERAL(".mag"),
+ FILE_PATH_LITERAL(".mam"),
+ FILE_PATH_LITERAL(".manifest"),
+ FILE_PATH_LITERAL(".maq"),
+ FILE_PATH_LITERAL(".mar"),
+ FILE_PATH_LITERAL(".mas"),
+ FILE_PATH_LITERAL(".mat"),
+ FILE_PATH_LITERAL(".mau"),
+ FILE_PATH_LITERAL(".mav"),
+ FILE_PATH_LITERAL(".maw"),
+ FILE_PATH_LITERAL(".mda"),
+ FILE_PATH_LITERAL(".mdb"),
+ FILE_PATH_LITERAL(".mde"),
+ FILE_PATH_LITERAL(".mdt"),
+ FILE_PATH_LITERAL(".mdw"),
+ FILE_PATH_LITERAL(".mdz"),
+ FILE_PATH_LITERAL(".mht"),
+ FILE_PATH_LITERAL(".mhtml"),
+ FILE_PATH_LITERAL(".mmc"),
+ FILE_PATH_LITERAL(".mof"),
+ FILE_PATH_LITERAL(".msc"),
+ FILE_PATH_LITERAL(".msh"),
+ FILE_PATH_LITERAL(".mshxml"),
+ FILE_PATH_LITERAL(".msi"),
+ FILE_PATH_LITERAL(".msp"),
+ FILE_PATH_LITERAL(".mst"),
+ FILE_PATH_LITERAL(".ocx"),
+ FILE_PATH_LITERAL(".ops"),
+ FILE_PATH_LITERAL(".pcd"),
+ FILE_PATH_LITERAL(".pif"),
+ FILE_PATH_LITERAL(".pkg"),
+ FILE_PATH_LITERAL(".pl"),
+ FILE_PATH_LITERAL(".plg"),
+ FILE_PATH_LITERAL(".prf"),
+ FILE_PATH_LITERAL(".prg"),
+ FILE_PATH_LITERAL(".pst"),
+ FILE_PATH_LITERAL(".py"),
+ FILE_PATH_LITERAL(".pyc"),
+ FILE_PATH_LITERAL(".pyw"),
+ FILE_PATH_LITERAL(".rb"),
+ FILE_PATH_LITERAL(".reg"),
+ FILE_PATH_LITERAL(".rpm"),
+ FILE_PATH_LITERAL(".scf"),
+ FILE_PATH_LITERAL(".scr"),
+ FILE_PATH_LITERAL(".sct"),
+ FILE_PATH_LITERAL(".sh"),
+ FILE_PATH_LITERAL(".shar"),
+ FILE_PATH_LITERAL(".shb"),
+ FILE_PATH_LITERAL(".shs"),
+ FILE_PATH_LITERAL(".shtm"),
+ FILE_PATH_LITERAL(".shtml"),
+ FILE_PATH_LITERAL(".spl"),
+ FILE_PATH_LITERAL(".svg"),
+ FILE_PATH_LITERAL(".swf"),
+ FILE_PATH_LITERAL(".sys"),
+ FILE_PATH_LITERAL(".tcsh"),
+ FILE_PATH_LITERAL(".url"),
+ FILE_PATH_LITERAL(".vb"),
+ FILE_PATH_LITERAL(".vbe"),
+ FILE_PATH_LITERAL(".vbs"),
+ FILE_PATH_LITERAL(".vsd"),
+ FILE_PATH_LITERAL(".vsmacros"),
+ FILE_PATH_LITERAL(".vss"),
+ FILE_PATH_LITERAL(".vst"),
+ FILE_PATH_LITERAL(".vsw"),
+ FILE_PATH_LITERAL(".ws"),
+ FILE_PATH_LITERAL(".wsc"),
+ FILE_PATH_LITERAL(".wsf"),
+ FILE_PATH_LITERAL(".wsh"),
+ FILE_PATH_LITERAL(".xbap"),
+ FILE_PATH_LITERAL(".xht"),
+ FILE_PATH_LITERAL(".xhtm"),
+ FILE_PATH_LITERAL(".xhtml"),
+ FILE_PATH_LITERAL(".xml"),
+ FILE_PATH_LITERAL(".xsl"),
+ FILE_PATH_LITERAL(".xslt")
+};
+
+// Maps extensions to their matching UMA histogram int value.
+int GetDangerousFileType(const base::FilePath& file_path) {
+ for (size_t i = 0; i < arraysize(kDangerousFileTypes); ++i) {
+ if (file_path.MatchesExtension(kDangerousFileTypes[i]))
+ return i + 1;
+ }
+ return 0; // Unknown extension.
+}
+
} // namespace
void RecordDownloadCount(DownloadCountTypes type) {
@@ -145,22 +284,43 @@ void RecordDownloadInterrupted(DownloadInterruptReason reason,
UMA_HISTOGRAM_BOOLEAN("Download.InterruptedUnknownSize", unknown_size);
}
-void RecordDangerousDownloadAccept(DownloadDangerType danger_type) {
+void RecordMaliciousDownloadClassified(DownloadDangerType danger_type) {
+ UMA_HISTOGRAM_ENUMERATION("Download.MaliciousDownloadClassified",
+ danger_type,
+ DOWNLOAD_DANGER_TYPE_MAX);
+}
+
+void RecordDangerousDownloadAccept(DownloadDangerType danger_type,
+ const base::FilePath& file_path) {
UMA_HISTOGRAM_ENUMERATION("Download.DangerousDownloadValidated",
danger_type,
DOWNLOAD_DANGER_TYPE_MAX);
+ if (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY(
+ "Download.DangerousFile.DangerousDownloadValidated",
+ GetDangerousFileType(file_path));
+ }
}
void RecordDangerousDownloadDiscard(DownloadDiscardReason reason,
- DownloadDangerType danger_type) {
+ DownloadDangerType danger_type,
+ const base::FilePath& file_path) {
switch (reason) {
case DOWNLOAD_DISCARD_DUE_TO_USER_ACTION:
UMA_HISTOGRAM_ENUMERATION(
"Download.UserDiscard", danger_type, DOWNLOAD_DANGER_TYPE_MAX);
+ if (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Download.DangerousFile.UserDiscard",
+ GetDangerousFileType(file_path));
+ }
break;
case DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN:
UMA_HISTOGRAM_ENUMERATION(
"Download.Discard", danger_type, DOWNLOAD_DANGER_TYPE_MAX);
+ if (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Download.DangerousFile.Discard",
+ GetDangerousFileType(file_path));
+ }
break;
default:
NOTREACHED();
@@ -178,7 +338,7 @@ void RecordDownloadWriteLoopCount(int count) {
void RecordAcceptsRanges(const std::string& accepts_ranges,
int64 download_len,
- const std::string& etag) {
+ bool has_strong_validator) {
int64 max = 1024 * 1024 * 1024; // One Terabyte.
download_len /= 1024; // In Kilobytes
static const int kBuckets = 50;
@@ -195,10 +355,8 @@ void RecordAcceptsRanges(const std::string& accepts_ranges,
1,
max,
kBuckets);
- // ETags that start with "W/" are considered weak ETags which don't imply
- // byte-wise equality.
- if (!StartsWithASCII(etag, "w/", false))
- RecordDownloadCount(STRONG_ETAG_AND_ACCEPTS_RANGES);
+ if (has_strong_validator)
+ RecordDownloadCount(STRONG_VALIDATOR_AND_ACCEPTS_RANGES);
} else {
UMA_HISTOGRAM_CUSTOM_COUNTS("Download.AcceptRangesMissingOrInvalid.KBytes",
download_len,
@@ -459,4 +617,14 @@ void RecordSavePackageEvent(SavePackageEvent event) {
SAVE_PACKAGE_LAST_ENTRY);
}
+void RecordOriginStateOnResumption(bool is_partial,
+ int state) {
+ if (is_partial)
+ UMA_HISTOGRAM_ENUMERATION("Download.OriginStateOnPartialResumption", state,
+ ORIGIN_STATE_ON_RESUMPTION_MAX);
+ else
+ UMA_HISTOGRAM_ENUMERATION("Download.OriginStateOnFullResumption", state,
+ ORIGIN_STATE_ON_RESUMPTION_MAX);
+}
+
} // namespace content
diff --git a/chromium/content/browser/download/download_stats.h b/chromium/content/browser/download/download_stats.h
index ebe643eaaec..65fad8d6b4a 100644
--- a/chromium/content/browser/download/download_stats.h
+++ b/chromium/content/browser/download/download_stats.h
@@ -15,6 +15,7 @@
#include "content/public/browser/download_interrupt_reasons.h"
namespace base {
+class FilePath;
class Time;
class TimeDelta;
class TimeTicks;
@@ -71,14 +72,19 @@ enum DownloadCountTypes {
// successful invocation of ScanAndSaveDownloadedFile().
FILE_MISSING_AFTER_SUCCESSFUL_SCAN_COUNT,
- // Count of downloads that supplies a strong ETag and has a 'Accept-Ranges:
- // bytes' header. These downloads are candidates for partial resumption.
- STRONG_ETAG_AND_ACCEPTS_RANGES,
+ // (Deprecated) Count of downloads with a strong ETag and specified
+ // 'Accept-Ranges: bytes'.
+ DOWNLOAD_COUNT_UNUSED_15,
// Count of downloads that didn't have a valid WebContents at the time it was
// interrupted.
INTERRUPTED_WITHOUT_WEBCONTENTS,
+ // Count of downloads that supplies a strong validator (implying byte-wise
+ // equivalence) and has a 'Accept-Ranges: bytes' header. These downloads are
+ // candidates for partial resumption.
+ STRONG_VALIDATOR_AND_ACCEPTS_RANGES,
+
DOWNLOAD_COUNT_TYPES_LAST_ENTRY
};
@@ -128,12 +134,19 @@ void RecordDownloadInterrupted(DownloadInterruptReason reason,
int64 received,
int64 total);
+// Record that a download has been classified as malicious.
+void RecordMaliciousDownloadClassified(DownloadDangerType danger_type);
+
// Record a dangerous download accept event.
-void RecordDangerousDownloadAccept(DownloadDangerType danger_type);
+void RecordDangerousDownloadAccept(
+ DownloadDangerType danger_type,
+ const base::FilePath& file_path);
// Record a dangerous download discard event.
-void RecordDangerousDownloadDiscard(DownloadDiscardReason reason,
- DownloadDangerType danger_type);
+void RecordDangerousDownloadDiscard(
+ DownloadDiscardReason reason,
+ DownloadDangerType danger_type,
+ const base::FilePath& file_path);
// Records the mime type of the download.
void RecordDownloadMimeType(const std::string& mime_type);
@@ -160,10 +173,12 @@ void RecordBandwidth(double actual_bandwidth, double potential_bandwidth);
void RecordOpen(const base::Time& end, bool first);
// Record whether or not the server accepts ranges, and the download size. Also
-// counts if a strong ETag is supplied. The combination of range request support
-// and ETag indicates downloads that are candidates for partial resumption.
-void RecordAcceptsRanges(const std::string& accepts_ranges, int64 download_len,
- const std::string& etag);
+// counts if a strong validator is supplied. The combination of range request
+// support and ETag indicates downloads that are candidates for partial
+// resumption.
+void RecordAcceptsRanges(const std::string& accepts_ranges,
+ int64 download_len,
+ bool has_strong_validator);
// Record the number of downloads removed by ClearAll.
void RecordClearAllSize(int size);
@@ -206,6 +221,19 @@ enum SavePackageEvent {
void RecordSavePackageEvent(SavePackageEvent event);
+enum OriginStateOnResumption {
+ ORIGIN_STATE_ON_RESUMPTION_ADDITIONAL_REDIRECTS = 1<<0,
+ ORIGIN_STATE_ON_RESUMPTION_VALIDATORS_CHANGED = 1<<1,
+ ORIGIN_STATE_ON_RESUMPTION_CONTENT_DISPOSITION_CHANGED = 1<<2,
+ ORIGIN_STATE_ON_RESUMPTION_MAX = 1<<3
+};
+
+// Record the state of the origin information across a download resumption
+// request. |state| is a combination of values from OriginStateOnResumption
+// enum.
+void RecordOriginStateOnResumption(bool is_partial,
+ int state);
+
} // namespace content
#endif // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_STATS_H_
diff --git a/chromium/content/browser/download/drag_download_file.h b/chromium/content/browser/download/drag_download_file.h
index 41fdf6224e2..c281d977d87 100644
--- a/chromium/content/browser/download/drag_download_file.h
+++ b/chromium/content/browser/download/drag_download_file.h
@@ -17,7 +17,6 @@
#include "content/public/common/referrer.h"
#include "net/base/file_stream.h"
#include "ui/base/dragdrop/download_file_interface.h"
-#include "ui/base/ui_export.h"
#include "url/gurl.h"
namespace net {
diff --git a/chromium/content/browser/download/drag_download_file_browsertest.cc b/chromium/content/browser/download/drag_download_file_browsertest.cc
index a4f50056ad3..5ea0e576af4 100644
--- a/chromium/content/browser/download/drag_download_file_browsertest.cc
+++ b/chromium/content/browser/download/drag_download_file_browsertest.cc
@@ -94,12 +94,9 @@ IN_PROC_BROWSER_TEST_F(DragDownloadFileTest, DragDownloadFileTest_NetError) {
"download-test.lib"))));
Referrer referrer;
std::string referrer_encoding;
- DragDownloadFile* file = new DragDownloadFile(name,
- scoped_ptr<net::FileStream>(),
- url,
- referrer,
- referrer_encoding,
- shell()->web_contents());
+ scoped_refptr<DragDownloadFile> file(
+ new DragDownloadFile(name, scoped_ptr<net::FileStream>(), url, referrer,
+ referrer_encoding, shell()->web_contents()));
scoped_refptr<MockDownloadFileObserver> observer(
new MockDownloadFileObserver());
EXPECT_CALL(*observer.get(), OnDownloadAborted())
@@ -119,9 +116,9 @@ IN_PROC_BROWSER_TEST_F(DragDownloadFileTest, DragDownloadFileTest_Complete) {
std::string referrer_encoding;
net::FileStream* stream = NULL;
SetUpServer();
- DragDownloadFile* file = new DragDownloadFile(
+ scoped_refptr<DragDownloadFile> file(new DragDownloadFile(
name, scoped_ptr<net::FileStream>(stream), url, referrer,
- referrer_encoding, shell()->web_contents());
+ referrer_encoding, shell()->web_contents()));
scoped_refptr<MockDownloadFileObserver> observer(
new MockDownloadFileObserver());
EXPECT_CALL(*observer.get(), OnDownloadCompleted(_))
diff --git a/chromium/content/browser/download/drag_download_util.cc b/chromium/content/browser/download/drag_download_util.cc
index 41bff06dd27..0850c3ba081 100644
--- a/chromium/content/browser/download/drag_download_util.cc
+++ b/chromium/content/browser/download/drag_download_util.cc
@@ -23,18 +23,18 @@ using net::FileStream;
namespace content {
-bool ParseDownloadMetadata(const string16& metadata,
- string16* mime_type,
+bool ParseDownloadMetadata(const base::string16& metadata,
+ base::string16* mime_type,
base::FilePath* file_name,
GURL* url) {
const char16 separator = L':';
size_t mime_type_end_pos = metadata.find(separator);
- if (mime_type_end_pos == string16::npos)
+ if (mime_type_end_pos == base::string16::npos)
return false;
size_t file_name_end_pos = metadata.find(separator, mime_type_end_pos + 1);
- if (file_name_end_pos == string16::npos)
+ if (file_name_end_pos == base::string16::npos)
return false;
GURL parsed_url = GURL(metadata.substr(file_name_end_pos + 1));
@@ -44,7 +44,7 @@ bool ParseDownloadMetadata(const string16& metadata,
if (mime_type)
*mime_type = metadata.substr(0, mime_type_end_pos);
if (file_name) {
- string16 file_name_str = metadata.substr(
+ base::string16 file_name_str = metadata.substr(
mime_type_end_pos + 1, file_name_end_pos - mime_type_end_pos - 1);
#if defined(OS_WIN)
*file_name = base::FilePath(file_name_str);
@@ -70,7 +70,7 @@ FileStream* CreateFileStreamForDrop(base::FilePath* file_path,
new_file_path = *file_path;
} else {
#if defined(OS_WIN)
- string16 suffix = ASCIIToUTF16("-") + base::IntToString16(seq);
+ base::string16 suffix = ASCIIToUTF16("-") + base::IntToString16(seq);
#else
std::string suffix = std::string("-") + base::IntToString(seq);
#endif
diff --git a/chromium/content/browser/download/drag_download_util.h b/chromium/content/browser/download/drag_download_util.h
index 8b58f4840e2..ca266efa622 100644
--- a/chromium/content/browser/download/drag_download_util.h
+++ b/chromium/content/browser/download/drag_download_util.h
@@ -32,8 +32,8 @@ namespace content {
// appropriately.
// For example, we can have
// text/plain:example.txt:http://example.com/example.txt
-bool ParseDownloadMetadata(const string16& metadata,
- string16* mime_type,
+bool ParseDownloadMetadata(const base::string16& metadata,
+ base::string16* mime_type,
base::FilePath* file_name,
GURL* url);
diff --git a/chromium/content/browser/download/file_metadata_unittest_linux.cc b/chromium/content/browser/download/file_metadata_unittest_linux.cc
index 4a3ebca5a2c..96db2646470 100644
--- a/chromium/content/browser/download/file_metadata_unittest_linux.cc
+++ b/chromium/content/browser/download/file_metadata_unittest_linux.cc
@@ -52,13 +52,12 @@ class FileMetadataLinuxTest : public testing::Test {
protected:
virtual void SetUp() OVERRIDE {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &test_file_));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &test_file_));
int result = setxattr(test_file_.value().c_str(),
"user.test", "test", 4, 0);
is_xattr_supported_ = (!result) || (errno != ENOTSUP);
if (!is_xattr_supported_) {
- LOG(INFO) << "Test will be skipped because extended attributes are not "
+ VLOG(0) << "Test will be skipped because extended attributes are not "
<< "supported on this OS/file system.";
}
}
diff --git a/chromium/content/browser/download/mhtml_generation_browsertest.cc b/chromium/content/browser/download/mhtml_generation_browsertest.cc
index 6e790135bce..11a08519e2d 100644
--- a/chromium/content/browser/download/mhtml_generation_browsertest.cc
+++ b/chromium/content/browser/download/mhtml_generation_browsertest.cc
@@ -66,7 +66,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTML) {
// Make sure the actual generated file has some contents.
int64 file_size;
- ASSERT_TRUE(file_util::GetFileSize(path, &file_size));
+ ASSERT_TRUE(base::GetFileSize(path, &file_size));
EXPECT_GT(file_size, 100);
}
diff --git a/chromium/content/browser/download/save_file_manager.cc b/chromium/content/browser/download/save_file_manager.cc
index 442c28e1024..85651b77092 100644
--- a/chromium/content/browser/download/save_file_manager.cc
+++ b/chromium/content/browser/download/save_file_manager.cc
@@ -482,7 +482,7 @@ void SaveFileManager::RenameAllFiles(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (!resource_dir.empty() && !base::PathExists(resource_dir))
- file_util::CreateDirectory(resource_dir);
+ base::CreateDirectory(resource_dir);
for (FinalNameList::const_iterator i = final_names.begin();
i != final_names.end(); ++i) {
diff --git a/chromium/content/browser/download/save_file_resource_handler.cc b/chromium/content/browser/download/save_file_resource_handler.cc
index ee72e0b0f79..d6405ffdb7a 100644
--- a/chromium/content/browser/download/save_file_resource_handler.cc
+++ b/chromium/content/browser/download/save_file_resource_handler.cc
@@ -19,7 +19,8 @@ SaveFileResourceHandler::SaveFileResourceHandler(int render_process_host_id,
int render_view_id,
const GURL& url,
SaveFileManager* manager)
- : save_id_(-1),
+ : ResourceHandler(NULL),
+ save_id_(-1),
render_process_id_(render_process_host_id),
render_view_id_(render_view_id),
url_(url),
@@ -73,8 +74,10 @@ bool SaveFileResourceHandler::OnWillStart(int request_id,
return true;
}
-bool SaveFileResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
- int* buf_size, int min_size) {
+bool SaveFileResourceHandler::OnWillRead(int request_id,
+ scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) {
DCHECK(buf && buf_size);
if (!read_buffer_.get()) {
*buf_size = min_size < 0 ? kReadBufSize : min_size;
@@ -97,16 +100,16 @@ bool SaveFileResourceHandler::OnReadCompleted(int request_id, int bytes_read,
return true;
}
-bool SaveFileResourceHandler::OnResponseCompleted(
+void SaveFileResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) {
+ const std::string& security_info,
+ bool* defer) {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&SaveFileManager::SaveFinished, save_manager_, save_id_, url_,
render_process_id_, status.is_success() && !status.is_io_pending()));
read_buffer_ = NULL;
- return true;
}
void SaveFileResourceHandler::OnDataDownloaded(
diff --git a/chromium/content/browser/download/save_file_resource_handler.h b/chromium/content/browser/download/save_file_resource_handler.h
index 8dad4f890a1..2079431f9dd 100644
--- a/chromium/content/browser/download/save_file_resource_handler.h
+++ b/chromium/content/browser/download/save_file_resource_handler.h
@@ -48,7 +48,7 @@ class SaveFileResourceHandler : public ResourceHandler {
// Creates a new buffer, which will be handed to the download thread for file
// writing and deletion.
virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) OVERRIDE;
@@ -56,9 +56,10 @@ class SaveFileResourceHandler : public ResourceHandler {
virtual bool OnReadCompleted(int request_id, int bytes_read,
bool* defer) OVERRIDE;
- virtual bool OnResponseCompleted(int request_id,
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) OVERRIDE;
+ const std::string& security_info,
+ bool* defer) OVERRIDE;
// N/A to this flavor of SaveFileResourceHandler.
virtual void OnDataDownloaded(int request_id, int bytes_downloaded) OVERRIDE;
diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc
index f38f9cdb1e4..5961e6bf580 100644
--- a/chromium/content/browser/download/save_package.cc
+++ b/chromium/content/browser/download/save_package.cc
@@ -46,7 +46,7 @@
#include "third_party/WebKit/public/web/WebPageSerializerClient.h"
using base::Time;
-using WebKit::WebPageSerializerClient;
+using blink::WebPageSerializerClient;
namespace content {
namespace {
@@ -519,7 +519,7 @@ bool SavePackage::GenerateFileName(const std::string& disposition,
if (ordinal_number > (kMaxFileOrdinalNumber - 1)) {
// Use a random file from temporary file.
base::FilePath temp_file;
- file_util::CreateTemporaryFile(&temp_file);
+ base::CreateTemporaryFile(&temp_file);
file_name = temp_file.RemoveExtension().BaseName().value();
// Get safe pure file name.
if (!GetSafePureFileName(saved_main_directory_path_,
@@ -1347,7 +1347,7 @@ void SavePackage::CreateDirectoryOnFileThread(
if (!skip_dir_check && !base::DirectoryExists(website_save_dir)) {
// If the default download dir doesn't exist, create it.
if (!base::DirectoryExists(download_save_dir)) {
- bool res = file_util::CreateDirectory(download_save_dir);
+ bool res = base::CreateDirectory(download_save_dir);
DCHECK(res);
}
save_dir = download_save_dir;
diff --git a/chromium/content/browser/download/save_package.h b/chromium/content/browser/download/save_package.h
index 939002e1eee..1ab429e16b9 100644
--- a/chromium/content/browser/download/save_package.h
+++ b/chromium/content/browser/download/save_package.h
@@ -279,7 +279,7 @@ class CONTENT_EXPORT SavePackage
base::FilePath saved_main_directory_path_;
// The title of the page the user wants to save.
- string16 title_;
+ base::string16 title_;
// Used to calculate package download speed (in files per second).
base::TimeTicks start_tick_;
diff --git a/chromium/content/browser/download/save_package_unittest.cc b/chromium/content/browser/download/save_package_unittest.cc
index c0aa3f8862b..47fd1b46686 100644
--- a/chromium/content/browser/download/save_package_unittest.cc
+++ b/chromium/content/browser/download/save_package_unittest.cc
@@ -10,8 +10,8 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/download/save_package.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
#include "content/test/net/url_request_mock_http_job.h"
+#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -346,7 +346,7 @@ TEST_F(SavePackageTest, MAYBE_TestEnsureMimeExtension) {
static const struct SuggestedSaveNameTestCase {
const char* page_url;
- const string16 page_title;
+ const base::string16 page_title;
const base::FilePath::CharType* expected_name;
bool ensure_html_extension;
} kSuggestedSaveNames[] = {
diff --git a/chromium/content/browser/fileapi/blob_url_request_job_unittest.cc b/chromium/content/browser/fileapi/blob_url_request_job_unittest.cc
new file mode 100644
index 00000000000..a09456b607f
--- /dev/null
+++ b/chromium/content/browser/fileapi/blob_url_request_job_unittest.cc
@@ -0,0 +1,438 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "base/time/time.h"
+#include "content/public/test/test_file_system_context.h"
+#include "net/base/io_buffer.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_byte_range.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"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/blob/blob_url_request_job.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/common/blob/blob_data.h"
+
+namespace webkit_blob {
+
+namespace {
+
+const int kBufferSize = 1024;
+const char kTestData1[] = "Hello";
+const char kTestData2[] = "Here it is data.";
+const char kTestFileData1[] = "0123456789";
+const char kTestFileData2[] = "This is sample file.";
+const char kTestFileSystemFileData1[] = "abcdefghijklmnop";
+const char kTestFileSystemFileData2[] = "File system file test data.";
+const char kTestContentType[] = "foo/bar";
+const char kTestContentDisposition[] = "attachment; filename=foo.txt";
+
+const char kFileSystemURLOrigin[] = "http://remote";
+const fileapi::FileSystemType kFileSystemType =
+ fileapi::kFileSystemTypeTemporary;
+
+} // namespace
+
+class BlobURLRequestJobTest : public testing::Test {
+ public:
+
+ // Test Harness -------------------------------------------------------------
+ // TODO(jianli): share this test harness with AppCacheURLRequestJobTest
+
+ class MockURLRequestDelegate : public net::URLRequest::Delegate {
+ public:
+ MockURLRequestDelegate()
+ : received_data_(new net::IOBuffer(kBufferSize)) {}
+
+ virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {
+ if (request->status().is_success()) {
+ EXPECT_TRUE(request->response_headers());
+ ReadSome(request);
+ } else {
+ RequestComplete();
+ }
+ }
+
+ virtual void OnReadCompleted(net::URLRequest* request,
+ int bytes_read) OVERRIDE {
+ if (bytes_read > 0)
+ ReceiveData(request, bytes_read);
+ else
+ RequestComplete();
+ }
+
+ const std::string& response_data() const { return response_data_; }
+
+ private:
+ void ReadSome(net::URLRequest* request) {
+ if (!request->is_pending()) {
+ RequestComplete();
+ return;
+ }
+
+ int bytes_read = 0;
+ if (!request->Read(received_data_.get(), kBufferSize, &bytes_read)) {
+ if (!request->status().is_io_pending()) {
+ RequestComplete();
+ }
+ return;
+ }
+
+ ReceiveData(request, bytes_read);
+ }
+
+ void ReceiveData(net::URLRequest* request, int bytes_read) {
+ if (bytes_read) {
+ response_data_.append(received_data_->data(),
+ static_cast<size_t>(bytes_read));
+ ReadSome(request);
+ } else {
+ RequestComplete();
+ }
+ }
+
+ void RequestComplete() {
+ base::MessageLoop::current()->Quit();
+ }
+
+ scoped_refptr<net::IOBuffer> received_data_;
+ std::string response_data_;
+ };
+
+ // A simple ProtocolHandler implementation to create BlobURLRequestJob.
+ class MockProtocolHandler :
+ public net::URLRequestJobFactory::ProtocolHandler {
+ public:
+ MockProtocolHandler(BlobURLRequestJobTest* test) : test_(test) {}
+
+ // net::URLRequestJobFactory::ProtocolHandler override.
+ virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const OVERRIDE {
+ return new BlobURLRequestJob(request,
+ network_delegate,
+ test_->blob_data_.get(),
+ test_->file_system_context_.get(),
+ base::MessageLoopProxy::current().get());
+ }
+
+ private:
+ BlobURLRequestJobTest* test_;
+ };
+
+ BlobURLRequestJobTest()
+ : blob_data_(new BlobData()),
+ expected_status_code_(0) {}
+
+ virtual void SetUp() {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ temp_file1_ = temp_dir_.path().AppendASCII("BlobFile1.dat");
+ ASSERT_EQ(static_cast<int>(arraysize(kTestFileData1) - 1),
+ file_util::WriteFile(temp_file1_, kTestFileData1,
+ arraysize(kTestFileData1) - 1));
+ base::PlatformFileInfo file_info1;
+ base::GetFileInfo(temp_file1_, &file_info1);
+ temp_file_modification_time1_ = file_info1.last_modified;
+
+ temp_file2_ = temp_dir_.path().AppendASCII("BlobFile2.dat");
+ ASSERT_EQ(static_cast<int>(arraysize(kTestFileData2) - 1),
+ file_util::WriteFile(temp_file2_, kTestFileData2,
+ arraysize(kTestFileData2) - 1));
+ base::PlatformFileInfo file_info2;
+ base::GetFileInfo(temp_file2_, &file_info2);
+ temp_file_modification_time2_ = file_info2.last_modified;
+
+ url_request_job_factory_.SetProtocolHandler("blob",
+ new MockProtocolHandler(this));
+ url_request_context_.set_job_factory(&url_request_job_factory_);
+ }
+
+ virtual void TearDown() {
+ }
+
+ void SetUpFileSystem() {
+ // Prepare file system.
+ file_system_context_ = fileapi::CreateFileSystemContextForTesting(
+ NULL, temp_dir_.path());
+
+ file_system_context_->OpenFileSystem(
+ GURL(kFileSystemURLOrigin),
+ kFileSystemType,
+ fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&BlobURLRequestJobTest::OnValidateFileSystem,
+ base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(file_system_root_url_.is_valid());
+
+ // Prepare files on file system.
+ const char kFilename1[] = "FileSystemFile1.dat";
+ temp_file_system_file1_ = GetFileSystemURL(kFilename1);
+ WriteFileSystemFile(kFilename1, kTestFileSystemFileData1,
+ arraysize(kTestFileSystemFileData1) - 1,
+ &temp_file_system_file_modification_time1_);
+ const char kFilename2[] = "FileSystemFile2.dat";
+ temp_file_system_file2_ = GetFileSystemURL(kFilename2);
+ WriteFileSystemFile(kFilename2, kTestFileSystemFileData2,
+ arraysize(kTestFileSystemFileData2) - 1,
+ &temp_file_system_file_modification_time2_);
+ }
+
+ GURL GetFileSystemURL(const std::string& filename) {
+ return GURL(file_system_root_url_.spec() + filename);
+ }
+
+ void WriteFileSystemFile(const std::string& filename,
+ const char* buf, int buf_size,
+ base::Time* modification_time) {
+ fileapi::FileSystemURL url =
+ file_system_context_->CreateCrackedFileSystemURL(
+ GURL(kFileSystemURLOrigin),
+ kFileSystemType,
+ base::FilePath().AppendASCII(filename));
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ fileapi::AsyncFileTestHelper::CreateFileWithData(
+ file_system_context_, url, buf, buf_size));
+
+ base::PlatformFileInfo file_info;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ fileapi::AsyncFileTestHelper::GetMetadata(
+ file_system_context_, url, &file_info));
+ if (modification_time)
+ *modification_time = file_info.last_modified;
+ }
+
+ void OnValidateFileSystem(const GURL& root,
+ const std::string& name,
+ base::PlatformFileError result) {
+ ASSERT_EQ(base::PLATFORM_FILE_OK, result);
+ ASSERT_TRUE(root.is_valid());
+ file_system_root_url_ = root;
+ }
+
+ void TestSuccessRequest(const std::string& expected_response) {
+ expected_status_code_ = 200;
+ expected_response_ = expected_response;
+ TestRequest("GET", net::HttpRequestHeaders());
+ }
+
+ void TestErrorRequest(int expected_status_code) {
+ expected_status_code_ = expected_status_code;
+ expected_response_ = "";
+ TestRequest("GET", net::HttpRequestHeaders());
+ }
+
+ void TestRequest(const std::string& method,
+ const net::HttpRequestHeaders& extra_headers) {
+ request_ = url_request_context_.CreateRequest(
+ GURL("blob:blah"), net::DEFAULT_PRIORITY, &url_request_delegate_);
+ request_->set_method(method);
+ if (!extra_headers.IsEmpty())
+ request_->SetExtraRequestHeaders(extra_headers);
+ request_->Start();
+
+ base::MessageLoop::current()->Run();
+
+ // Verify response.
+ EXPECT_TRUE(request_->status().is_success());
+ EXPECT_EQ(expected_status_code_,
+ request_->response_headers()->response_code());
+ EXPECT_EQ(expected_response_, url_request_delegate_.response_data());
+ }
+
+ void BuildComplicatedData(std::string* expected_result) {
+ blob_data_->AppendData(kTestData1 + 1, 2);
+ blob_data_->AppendFile(temp_file1_, 2, 3, temp_file_modification_time1_);
+ blob_data_->AppendFileSystemFile(temp_file_system_file1_, 3, 4,
+ temp_file_system_file_modification_time1_);
+ blob_data_->AppendData(kTestData2 + 4, 5);
+ blob_data_->AppendFile(temp_file2_, 5, 6, temp_file_modification_time2_);
+ blob_data_->AppendFileSystemFile(temp_file_system_file2_, 6, 7,
+ temp_file_system_file_modification_time2_);
+ *expected_result = std::string(kTestData1 + 1, 2);
+ *expected_result += std::string(kTestFileData1 + 2, 3);
+ *expected_result += std::string(kTestFileSystemFileData1 + 3, 4);
+ *expected_result += std::string(kTestData2 + 4, 5);
+ *expected_result += std::string(kTestFileData2 + 5, 6);
+ *expected_result += std::string(kTestFileSystemFileData2 + 6, 7);
+ }
+
+ protected:
+ base::ScopedTempDir temp_dir_;
+ base::FilePath temp_file1_;
+ base::FilePath temp_file2_;
+ base::Time temp_file_modification_time1_;
+ base::Time temp_file_modification_time2_;
+ GURL file_system_root_url_;
+ GURL temp_file_system_file1_;
+ GURL temp_file_system_file2_;
+ base::Time temp_file_system_file_modification_time1_;
+ base::Time temp_file_system_file_modification_time2_;
+
+ base::MessageLoopForIO message_loop_;
+ scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<BlobData> blob_data_;
+ net::URLRequestJobFactoryImpl url_request_job_factory_;
+ net::URLRequestContext url_request_context_;
+ MockURLRequestDelegate url_request_delegate_;
+ scoped_ptr<net::URLRequest> request_;
+
+ int expected_status_code_;
+ std::string expected_response_;
+};
+
+TEST_F(BlobURLRequestJobTest, TestGetSimpleDataRequest) {
+ blob_data_->AppendData(kTestData1);
+ TestSuccessRequest(kTestData1);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetSimpleFileRequest) {
+ blob_data_->AppendFile(temp_file1_, 0, -1, base::Time());
+ TestSuccessRequest(kTestFileData1);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetLargeFileRequest) {
+ base::FilePath large_temp_file =
+ temp_dir_.path().AppendASCII("LargeBlob.dat");
+ std::string large_data;
+ large_data.reserve(kBufferSize * 5);
+ for (int i = 0; i < kBufferSize * 5; ++i)
+ large_data.append(1, static_cast<char>(i % 256));
+ ASSERT_EQ(static_cast<int>(large_data.size()),
+ file_util::WriteFile(large_temp_file, large_data.data(),
+ large_data.size()));
+ blob_data_->AppendFile(large_temp_file, 0, -1, base::Time());
+ TestSuccessRequest(large_data);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetNonExistentFileRequest) {
+ base::FilePath non_existent_file =
+ temp_file1_.InsertBeforeExtension(FILE_PATH_LITERAL("-na"));
+ blob_data_->AppendFile(non_existent_file, 0, -1, base::Time());
+ TestErrorRequest(404);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetChangedFileRequest) {
+ base::Time old_time =
+ temp_file_modification_time1_ - base::TimeDelta::FromSeconds(10);
+ blob_data_->AppendFile(temp_file1_, 0, 3, old_time);
+ TestErrorRequest(404);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetSlicedFileRequest) {
+ blob_data_->AppendFile(temp_file1_, 2, 4, temp_file_modification_time1_);
+ std::string result(kTestFileData1 + 2, 4);
+ TestSuccessRequest(result);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetSimpleFileSystemFileRequest) {
+ SetUpFileSystem();
+ blob_data_->AppendFileSystemFile(temp_file_system_file1_, 0, -1,
+ base::Time());
+ TestSuccessRequest(kTestFileSystemFileData1);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetLargeFileSystemFileRequest) {
+ SetUpFileSystem();
+ std::string large_data;
+ large_data.reserve(kBufferSize * 5);
+ for (int i = 0; i < kBufferSize * 5; ++i)
+ large_data.append(1, static_cast<char>(i % 256));
+
+ const char kFilename[] = "LargeBlob.dat";
+ WriteFileSystemFile(kFilename, large_data.data(), large_data.size(), NULL);
+
+ blob_data_->AppendFileSystemFile(GetFileSystemURL(kFilename),
+ 0, -1, base::Time());
+ TestSuccessRequest(large_data);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetNonExistentFileSystemFileRequest) {
+ SetUpFileSystem();
+ GURL non_existent_file = GetFileSystemURL("non-existent.dat");
+ blob_data_->AppendFileSystemFile(non_existent_file, 0, -1, base::Time());
+ TestErrorRequest(404);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetChangedFileSystemFileRequest) {
+ SetUpFileSystem();
+ base::Time old_time =
+ temp_file_system_file_modification_time1_ -
+ base::TimeDelta::FromSeconds(10);
+ blob_data_->AppendFileSystemFile(temp_file_system_file1_, 0, 3, old_time);
+ TestErrorRequest(404);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetSlicedFileSystemFileRequest) {
+ SetUpFileSystem();
+ blob_data_->AppendFileSystemFile(temp_file_system_file1_, 2, 4,
+ temp_file_system_file_modification_time1_);
+ std::string result(kTestFileSystemFileData1 + 2, 4);
+ TestSuccessRequest(result);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetComplicatedDataAndFileRequest) {
+ SetUpFileSystem();
+ std::string result;
+ BuildComplicatedData(&result);
+ TestSuccessRequest(result);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetRangeRequest1) {
+ SetUpFileSystem();
+ std::string result;
+ BuildComplicatedData(&result);
+ net::HttpRequestHeaders extra_headers;
+ extra_headers.SetHeader(net::HttpRequestHeaders::kRange,
+ net::HttpByteRange::Bounded(5, 10).GetHeaderValue());
+ expected_status_code_ = 206;
+ expected_response_ = result.substr(5, 10 - 5 + 1);
+ TestRequest("GET", extra_headers);
+}
+
+TEST_F(BlobURLRequestJobTest, TestGetRangeRequest2) {
+ SetUpFileSystem();
+ std::string result;
+ BuildComplicatedData(&result);
+ net::HttpRequestHeaders extra_headers;
+ extra_headers.SetHeader(net::HttpRequestHeaders::kRange,
+ net::HttpByteRange::Suffix(10).GetHeaderValue());
+ expected_status_code_ = 206;
+ expected_response_ = result.substr(result.length() - 10);
+ TestRequest("GET", extra_headers);
+}
+
+TEST_F(BlobURLRequestJobTest, TestExtraHeaders) {
+ blob_data_->set_content_type(kTestContentType);
+ blob_data_->set_content_disposition(kTestContentDisposition);
+ blob_data_->AppendData(kTestData1);
+ expected_status_code_ = 200;
+ expected_response_ = kTestData1;
+ TestRequest("GET", net::HttpRequestHeaders());
+
+ std::string content_type;
+ EXPECT_TRUE(request_->response_headers()->GetMimeType(&content_type));
+ EXPECT_EQ(kTestContentType, content_type);
+ void* iter = NULL;
+ std::string content_disposition;
+ EXPECT_TRUE(request_->response_headers()->EnumerateHeader(
+ &iter, "Content-Disposition", &content_disposition));
+ EXPECT_EQ(kTestContentDisposition, content_disposition);
+}
+
+} // namespace webkit_blob
diff --git a/chromium/content/browser/fileapi/copy_or_move_file_validator_unittest.cc b/chromium/content/browser/fileapi/copy_or_move_file_validator_unittest.cc
new file mode 100644
index 00000000000..1dd3f986552
--- /dev/null
+++ b/chromium/content/browser/fileapi/copy_or_move_file_validator_unittest.cc
@@ -0,0 +1,326 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_file_system_backend.h"
+#include "content/public/test/test_file_system_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+#include "webkit/browser/fileapi/file_system_backend.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/quota/mock_special_storage_policy.h"
+#include "webkit/common/blob/shareable_file_reference.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+namespace fileapi {
+
+namespace {
+
+const FileSystemType kNoValidatorType = kFileSystemTypeTemporary;
+const FileSystemType kWithValidatorType = kFileSystemTypeTest;
+
+void ExpectOk(const GURL& origin_url,
+ const std::string& name,
+ base::PlatformFileError error) {
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+}
+
+class CopyOrMoveFileValidatorTestHelper {
+ public:
+ CopyOrMoveFileValidatorTestHelper(
+ const GURL& origin,
+ FileSystemType src_type,
+ FileSystemType dest_type)
+ : origin_(origin),
+ src_type_(src_type),
+ dest_type_(dest_type) {}
+
+ ~CopyOrMoveFileValidatorTestHelper() {
+ file_system_context_ = NULL;
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void SetUp() {
+ ASSERT_TRUE(base_.CreateUniqueTempDir());
+ base::FilePath base_dir = base_.path();
+
+ file_system_context_ = CreateFileSystemContextForTesting(NULL, base_dir);
+
+ // Set up TestFileSystemBackend to require CopyOrMoveFileValidator.
+ FileSystemBackend* test_file_system_backend =
+ file_system_context_->GetFileSystemBackend(kWithValidatorType);
+ static_cast<TestFileSystemBackend*>(test_file_system_backend)->
+ set_require_copy_or_move_validator(true);
+
+ // Sets up source.
+ FileSystemBackend* src_file_system_backend =
+ file_system_context_->GetFileSystemBackend(src_type_);
+ src_file_system_backend->OpenFileSystem(
+ origin_, src_type_,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&ExpectOk));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::PLATFORM_FILE_OK, CreateDirectory(SourceURL("")));
+
+ // Sets up dest.
+ DCHECK_EQ(kWithValidatorType, dest_type_);
+ ASSERT_EQ(base::PLATFORM_FILE_OK, CreateDirectory(DestURL("")));
+
+ copy_src_ = SourceURL("copy_src.jpg");
+ move_src_ = SourceURL("move_src.jpg");
+ copy_dest_ = DestURL("copy_dest.jpg");
+ move_dest_ = DestURL("move_dest.jpg");
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK, CreateFile(copy_src_, 10));
+ ASSERT_EQ(base::PLATFORM_FILE_OK, CreateFile(move_src_, 10));
+
+ ASSERT_TRUE(FileExists(copy_src_, 10));
+ ASSERT_TRUE(FileExists(move_src_, 10));
+ ASSERT_FALSE(FileExists(copy_dest_, 10));
+ ASSERT_FALSE(FileExists(move_dest_, 10));
+ }
+
+ void SetMediaCopyOrMoveFileValidatorFactory(
+ scoped_ptr<CopyOrMoveFileValidatorFactory> factory) {
+ TestFileSystemBackend* backend = static_cast<TestFileSystemBackend*>(
+ file_system_context_->GetFileSystemBackend(kWithValidatorType));
+ backend->InitializeCopyOrMoveFileValidatorFactory(factory.Pass());
+ }
+
+ void CopyTest(base::PlatformFileError expected) {
+ ASSERT_TRUE(FileExists(copy_src_, 10));
+ ASSERT_FALSE(FileExists(copy_dest_, 10));
+
+ EXPECT_EQ(expected,
+ AsyncFileTestHelper::Copy(
+ file_system_context_.get(), copy_src_, copy_dest_));
+
+ EXPECT_TRUE(FileExists(copy_src_, 10));
+ if (expected == base::PLATFORM_FILE_OK)
+ EXPECT_TRUE(FileExists(copy_dest_, 10));
+ else
+ EXPECT_FALSE(FileExists(copy_dest_, 10));
+ };
+
+ void MoveTest(base::PlatformFileError expected) {
+ ASSERT_TRUE(FileExists(move_src_, 10));
+ ASSERT_FALSE(FileExists(move_dest_, 10));
+
+ EXPECT_EQ(expected,
+ AsyncFileTestHelper::Move(
+ file_system_context_.get(), move_src_, move_dest_));
+
+ if (expected == base::PLATFORM_FILE_OK) {
+ EXPECT_FALSE(FileExists(move_src_, 10));
+ EXPECT_TRUE(FileExists(move_dest_, 10));
+ } else {
+ EXPECT_TRUE(FileExists(move_src_, 10));
+ EXPECT_FALSE(FileExists(move_dest_, 10));
+ }
+ };
+
+ private:
+ FileSystemURL SourceURL(const std::string& path) {
+ return file_system_context_->CreateCrackedFileSystemURL(
+ origin_, src_type_,
+ base::FilePath().AppendASCII("src").AppendASCII(path));
+ }
+
+ FileSystemURL DestURL(const std::string& path) {
+ return file_system_context_->CreateCrackedFileSystemURL(
+ origin_, dest_type_,
+ base::FilePath().AppendASCII("dest").AppendASCII(path));
+ }
+
+ base::PlatformFileError CreateFile(const FileSystemURL& url, size_t size) {
+ base::PlatformFileError result =
+ AsyncFileTestHelper::CreateFile(file_system_context_.get(), url);
+ if (result != base::PLATFORM_FILE_OK)
+ return result;
+ return AsyncFileTestHelper::TruncateFile(
+ file_system_context_.get(), url, size);
+ }
+
+ base::PlatformFileError CreateDirectory(const FileSystemURL& url) {
+ return AsyncFileTestHelper::CreateDirectory(file_system_context_.get(),
+ url);
+ }
+
+ bool FileExists(const FileSystemURL& url, int64 expected_size) {
+ return AsyncFileTestHelper::FileExists(
+ file_system_context_.get(), url, expected_size);
+ }
+
+ base::ScopedTempDir base_;
+
+ const GURL origin_;
+
+ const FileSystemType src_type_;
+ const FileSystemType dest_type_;
+ std::string src_fsid_;
+ std::string dest_fsid_;
+
+ base::MessageLoop message_loop_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+
+ FileSystemURL copy_src_;
+ FileSystemURL copy_dest_;
+ FileSystemURL move_src_;
+ FileSystemURL move_dest_;
+
+ DISALLOW_COPY_AND_ASSIGN(CopyOrMoveFileValidatorTestHelper);
+};
+
+// For TestCopyOrMoveFileValidatorFactory
+enum Validity {
+ VALID,
+ PRE_WRITE_INVALID,
+ POST_WRITE_INVALID
+};
+
+class TestCopyOrMoveFileValidatorFactory
+ : public CopyOrMoveFileValidatorFactory {
+ public:
+ // A factory that creates validators that accept everything or nothing.
+ // TODO(gbillock): switch args to enum or something
+ explicit TestCopyOrMoveFileValidatorFactory(Validity validity)
+ : validity_(validity) {}
+ virtual ~TestCopyOrMoveFileValidatorFactory() {}
+
+ virtual CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
+ const FileSystemURL& /*src_url*/,
+ const base::FilePath& /*platform_path*/) OVERRIDE {
+ return new TestCopyOrMoveFileValidator(validity_);
+ }
+
+ private:
+ class TestCopyOrMoveFileValidator : public CopyOrMoveFileValidator {
+ public:
+ explicit TestCopyOrMoveFileValidator(Validity validity)
+ : result_(validity == VALID || validity == POST_WRITE_INVALID
+ ? base::PLATFORM_FILE_OK
+ : base::PLATFORM_FILE_ERROR_SECURITY),
+ write_result_(validity == VALID || validity == PRE_WRITE_INVALID
+ ? base::PLATFORM_FILE_OK
+ : base::PLATFORM_FILE_ERROR_SECURITY) {
+ }
+ virtual ~TestCopyOrMoveFileValidator() {}
+
+ virtual void StartPreWriteValidation(
+ const ResultCallback& result_callback) OVERRIDE {
+ // Post the result since a real validator must do work asynchronously.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(result_callback, result_));
+ }
+
+ virtual void StartPostWriteValidation(
+ const base::FilePath& dest_platform_path,
+ const ResultCallback& result_callback) OVERRIDE {
+ // Post the result since a real validator must do work asynchronously.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(result_callback, write_result_));
+ }
+
+ private:
+ base::PlatformFileError result_;
+ base::PlatformFileError write_result_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidator);
+ };
+
+ Validity validity_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidatorFactory);
+};
+
+} // namespace
+
+TEST(CopyOrMoveFileValidatorTest, NoValidatorWithinSameFSType) {
+ // Within a file system type, validation is not expected, so it should
+ // work for kWithValidatorType without a validator set.
+ CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
+ kWithValidatorType,
+ kWithValidatorType);
+ helper.SetUp();
+ helper.CopyTest(base::PLATFORM_FILE_OK);
+ helper.MoveTest(base::PLATFORM_FILE_OK);
+}
+
+TEST(CopyOrMoveFileValidatorTest, MissingValidator) {
+ // Copying or moving into a kWithValidatorType requires a file
+ // validator. An error is expected if copy is attempted without a validator.
+ CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
+ kNoValidatorType,
+ kWithValidatorType);
+ helper.SetUp();
+ helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
+ helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
+}
+
+TEST(CopyOrMoveFileValidatorTest, AcceptAll) {
+ CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
+ kNoValidatorType,
+ kWithValidatorType);
+ helper.SetUp();
+ scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
+ new TestCopyOrMoveFileValidatorFactory(VALID));
+ helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
+
+ helper.CopyTest(base::PLATFORM_FILE_OK);
+ helper.MoveTest(base::PLATFORM_FILE_OK);
+}
+
+TEST(CopyOrMoveFileValidatorTest, AcceptNone) {
+ CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
+ kNoValidatorType,
+ kWithValidatorType);
+ helper.SetUp();
+ scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
+ new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID));
+ helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
+
+ helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
+ helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
+}
+
+TEST(CopyOrMoveFileValidatorTest, OverrideValidator) {
+ // Once set, you can not override the validator.
+ CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
+ kNoValidatorType,
+ kWithValidatorType);
+ helper.SetUp();
+ scoped_ptr<CopyOrMoveFileValidatorFactory> reject_factory(
+ new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID));
+ helper.SetMediaCopyOrMoveFileValidatorFactory(reject_factory.Pass());
+
+ scoped_ptr<CopyOrMoveFileValidatorFactory> accept_factory(
+ new TestCopyOrMoveFileValidatorFactory(VALID));
+ helper.SetMediaCopyOrMoveFileValidatorFactory(accept_factory.Pass());
+
+ helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
+ helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
+}
+
+TEST(CopyOrMoveFileValidatorTest, RejectPostWrite) {
+ CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
+ kNoValidatorType,
+ kWithValidatorType);
+ helper.SetUp();
+ scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
+ new TestCopyOrMoveFileValidatorFactory(POST_WRITE_INVALID));
+ helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
+
+ helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
+ helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
new file mode 100644
index 00000000000..eb002ab0a0c
--- /dev/null
+++ b/chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
@@ -0,0 +1,866 @@
+// 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 <map>
+#include <queue>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/stl_util.h"
+#include "content/public/test/test_file_system_backend.h"
+#include "content/public/test/test_file_system_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/blob/file_stream_reader.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
+#include "webkit/browser/fileapi/copy_or_move_operation_delegate.h"
+#include "webkit/browser/fileapi/file_stream_writer.h"
+#include "webkit/browser/fileapi/file_system_backend.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_operation.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/browser/fileapi/test_file_set.h"
+#include "webkit/browser/quota/mock_quota_manager.h"
+#include "webkit/browser/quota/quota_manager.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+namespace fileapi {
+
+typedef FileSystemOperation::FileEntryList FileEntryList;
+
+namespace {
+
+void ExpectOk(const GURL& origin_url,
+ const std::string& name,
+ base::PlatformFileError error) {
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+}
+
+class TestValidatorFactory : public CopyOrMoveFileValidatorFactory {
+ public:
+ // A factory that creates validators that accept everything or nothing.
+ TestValidatorFactory() {}
+ virtual ~TestValidatorFactory() {}
+
+ virtual CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
+ const FileSystemURL& /*src_url*/,
+ const base::FilePath& /*platform_path*/) OVERRIDE {
+ // Move arg management to TestValidator?
+ return new TestValidator(true, true, std::string("2"));
+ }
+
+ private:
+ class TestValidator : public CopyOrMoveFileValidator {
+ public:
+ explicit TestValidator(bool pre_copy_valid,
+ bool post_copy_valid,
+ const std::string& reject_string)
+ : result_(pre_copy_valid ? base::PLATFORM_FILE_OK
+ : base::PLATFORM_FILE_ERROR_SECURITY),
+ write_result_(post_copy_valid ? base::PLATFORM_FILE_OK
+ : base::PLATFORM_FILE_ERROR_SECURITY),
+ reject_string_(reject_string) {
+ }
+ virtual ~TestValidator() {}
+
+ virtual void StartPreWriteValidation(
+ const ResultCallback& result_callback) OVERRIDE {
+ // Post the result since a real validator must do work asynchronously.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(result_callback, result_));
+ }
+
+ virtual void StartPostWriteValidation(
+ const base::FilePath& dest_platform_path,
+ const ResultCallback& result_callback) OVERRIDE {
+ base::PlatformFileError result = write_result_;
+ std::string unsafe = dest_platform_path.BaseName().AsUTF8Unsafe();
+ if (unsafe.find(reject_string_) != std::string::npos) {
+ result = base::PLATFORM_FILE_ERROR_SECURITY;
+ }
+ // Post the result since a real validator must do work asynchronously.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(result_callback, result));
+ }
+
+ private:
+ base::PlatformFileError result_;
+ base::PlatformFileError write_result_;
+ std::string reject_string_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestValidator);
+ };
+};
+
+// Records CopyProgressCallback invocations.
+struct ProgressRecord {
+ FileSystemOperation::CopyProgressType type;
+ FileSystemURL source_url;
+ FileSystemURL dest_url;
+ int64 size;
+};
+
+void RecordProgressCallback(std::vector<ProgressRecord>* records,
+ FileSystemOperation::CopyProgressType type,
+ const FileSystemURL& source_url,
+ const FileSystemURL& dest_url,
+ int64 size) {
+ ProgressRecord record;
+ record.type = type;
+ record.source_url = source_url;
+ record.dest_url = dest_url;
+ record.size = size;
+ records->push_back(record);
+}
+
+void RecordFileProgressCallback(std::vector<int64>* records,
+ int64 progress) {
+ records->push_back(progress);
+}
+
+void AssignAndQuit(base::RunLoop* run_loop,
+ base::PlatformFileError* result_out,
+ base::PlatformFileError result) {
+ *result_out = result;
+ run_loop->Quit();
+}
+
+class ScopedThreadStopper {
+ public:
+ ScopedThreadStopper(base::Thread* thread) : thread_(thread) {
+ }
+
+ ~ScopedThreadStopper() {
+ if (thread_) {
+ // Give another chance for deleted streams to perform Close.
+ base::RunLoop run_loop;
+ thread_->message_loop_proxy()->PostTaskAndReply(
+ FROM_HERE, base::Bind(&base::DoNothing), run_loop.QuitClosure());
+ run_loop.Run();
+ thread_->Stop();
+ }
+ }
+
+ bool is_valid() const { return thread_; }
+
+ private:
+ base::Thread* thread_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedThreadStopper);
+};
+
+} // namespace
+
+class CopyOrMoveOperationTestHelper {
+ public:
+ CopyOrMoveOperationTestHelper(
+ const GURL& origin,
+ FileSystemType src_type,
+ FileSystemType dest_type)
+ : origin_(origin),
+ src_type_(src_type),
+ dest_type_(dest_type) {}
+
+ ~CopyOrMoveOperationTestHelper() {
+ file_system_context_ = NULL;
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+ quota_manager_ = NULL;
+ quota_manager_proxy_ = NULL;
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void SetUp() {
+ SetUp(true, true);
+ }
+
+ void SetUpNoValidator() {
+ SetUp(true, false);
+ }
+
+ void SetUp(bool require_copy_or_move_validator,
+ bool init_copy_or_move_validator) {
+ ASSERT_TRUE(base_.CreateUniqueTempDir());
+ base::FilePath base_dir = base_.path();
+ quota_manager_ =
+ new quota::MockQuotaManager(false /* is_incognito */,
+ base_dir,
+ base::MessageLoopProxy::current().get(),
+ base::MessageLoopProxy::current().get(),
+ NULL /* special storage policy */);
+ quota_manager_proxy_ = new quota::MockQuotaManagerProxy(
+ quota_manager_.get(), base::MessageLoopProxy::current().get());
+ file_system_context_ =
+ CreateFileSystemContextForTesting(quota_manager_proxy_.get(), base_dir);
+
+ // Prepare the origin's root directory.
+ FileSystemBackend* backend =
+ file_system_context_->GetFileSystemBackend(src_type_);
+ backend->OpenFileSystem(origin_, src_type_,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&ExpectOk));
+ backend = file_system_context_->GetFileSystemBackend(dest_type_);
+ if (dest_type_ == kFileSystemTypeTest) {
+ TestFileSystemBackend* test_backend =
+ static_cast<TestFileSystemBackend*>(backend);
+ scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
+ new TestValidatorFactory);
+ test_backend->set_require_copy_or_move_validator(
+ require_copy_or_move_validator);
+ if (init_copy_or_move_validator)
+ test_backend->InitializeCopyOrMoveFileValidatorFactory(factory.Pass());
+ }
+ backend->OpenFileSystem(origin_, dest_type_,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&ExpectOk));
+ base::RunLoop().RunUntilIdle();
+
+ // Grant relatively big quota initially.
+ quota_manager_->SetQuota(origin_,
+ FileSystemTypeToQuotaStorageType(src_type_),
+ 1024 * 1024);
+ quota_manager_->SetQuota(origin_,
+ FileSystemTypeToQuotaStorageType(dest_type_),
+ 1024 * 1024);
+ }
+
+ int64 GetSourceUsage() {
+ int64 usage = 0;
+ GetUsageAndQuota(src_type_, &usage, NULL);
+ return usage;
+ }
+
+ int64 GetDestUsage() {
+ int64 usage = 0;
+ GetUsageAndQuota(dest_type_, &usage, NULL);
+ return usage;
+ }
+
+ FileSystemURL SourceURL(const std::string& path) {
+ return file_system_context_->CreateCrackedFileSystemURL(
+ origin_, src_type_, base::FilePath::FromUTF8Unsafe(path));
+ }
+
+ FileSystemURL DestURL(const std::string& path) {
+ return file_system_context_->CreateCrackedFileSystemURL(
+ origin_, dest_type_, base::FilePath::FromUTF8Unsafe(path));
+ }
+
+ base::PlatformFileError Copy(const FileSystemURL& src,
+ const FileSystemURL& dest) {
+ return AsyncFileTestHelper::Copy(file_system_context_.get(), src, dest);
+ }
+
+ base::PlatformFileError CopyWithProgress(
+ const FileSystemURL& src,
+ const FileSystemURL& dest,
+ const AsyncFileTestHelper::CopyProgressCallback& progress_callback) {
+ return AsyncFileTestHelper::CopyWithProgress(
+ file_system_context_.get(), src, dest, progress_callback);
+ }
+
+ base::PlatformFileError Move(const FileSystemURL& src,
+ const FileSystemURL& dest) {
+ return AsyncFileTestHelper::Move(file_system_context_.get(), src, dest);
+ }
+
+ base::PlatformFileError SetUpTestCaseFiles(
+ const FileSystemURL& root,
+ const test::TestCaseRecord* const test_cases,
+ size_t test_case_size) {
+ base::PlatformFileError result = base::PLATFORM_FILE_ERROR_FAILED;
+ for (size_t i = 0; i < test_case_size; ++i) {
+ const test::TestCaseRecord& test_case = test_cases[i];
+ FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
+ root.origin(),
+ root.mount_type(),
+ root.virtual_path().Append(test_case.path));
+ if (test_case.is_directory)
+ result = CreateDirectory(url);
+ else
+ result = CreateFile(url, test_case.data_file_size);
+ EXPECT_EQ(base::PLATFORM_FILE_OK, result) << url.DebugString();
+ if (result != base::PLATFORM_FILE_OK)
+ return result;
+ }
+ return result;
+ }
+
+ void VerifyTestCaseFiles(
+ const FileSystemURL& root,
+ const test::TestCaseRecord* const test_cases,
+ size_t test_case_size) {
+ std::map<base::FilePath, const test::TestCaseRecord*> test_case_map;
+ for (size_t i = 0; i < test_case_size; ++i) {
+ test_case_map[
+ base::FilePath(test_cases[i].path).NormalizePathSeparators()] =
+ &test_cases[i];
+ }
+
+ std::queue<FileSystemURL> directories;
+ FileEntryList entries;
+ directories.push(root);
+ while (!directories.empty()) {
+ FileSystemURL dir = directories.front();
+ directories.pop();
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ReadDirectory(dir, &entries));
+ for (size_t i = 0; i < entries.size(); ++i) {
+ FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
+ dir.origin(),
+ dir.mount_type(),
+ dir.virtual_path().Append(entries[i].name));
+ base::FilePath relative;
+ root.virtual_path().AppendRelativePath(url.virtual_path(), &relative);
+ relative = relative.NormalizePathSeparators();
+ ASSERT_TRUE(ContainsKey(test_case_map, relative));
+ if (entries[i].is_directory) {
+ EXPECT_TRUE(test_case_map[relative]->is_directory);
+ directories.push(url);
+ } else {
+ EXPECT_FALSE(test_case_map[relative]->is_directory);
+ EXPECT_TRUE(FileExists(url, test_case_map[relative]->data_file_size));
+ }
+ test_case_map.erase(relative);
+ }
+ }
+ EXPECT_TRUE(test_case_map.empty());
+ std::map<base::FilePath, const test::TestCaseRecord*>::const_iterator it;
+ for (it = test_case_map.begin(); it != test_case_map.end(); ++it) {
+ LOG(ERROR) << "Extra entry: " << it->first.LossyDisplayName();
+ }
+ }
+
+ base::PlatformFileError ReadDirectory(const FileSystemURL& url,
+ FileEntryList* entries) {
+ return AsyncFileTestHelper::ReadDirectory(
+ file_system_context_.get(), url, entries);
+ }
+
+ base::PlatformFileError CreateDirectory(const FileSystemURL& url) {
+ return AsyncFileTestHelper::CreateDirectory(file_system_context_.get(),
+ url);
+ }
+
+ base::PlatformFileError CreateFile(const FileSystemURL& url, size_t size) {
+ base::PlatformFileError result =
+ AsyncFileTestHelper::CreateFile(file_system_context_.get(), url);
+ if (result != base::PLATFORM_FILE_OK)
+ return result;
+ return AsyncFileTestHelper::TruncateFile(
+ file_system_context_.get(), url, size);
+ }
+
+ bool FileExists(const FileSystemURL& url, int64 expected_size) {
+ return AsyncFileTestHelper::FileExists(
+ file_system_context_.get(), url, expected_size);
+ }
+
+ bool DirectoryExists(const FileSystemURL& url) {
+ return AsyncFileTestHelper::DirectoryExists(file_system_context_.get(),
+ url);
+ }
+
+ private:
+ void GetUsageAndQuota(FileSystemType type, int64* usage, int64* quota) {
+ quota::QuotaStatusCode status = AsyncFileTestHelper::GetUsageAndQuota(
+ quota_manager_.get(), origin_, type, usage, quota);
+ ASSERT_EQ(quota::kQuotaStatusOk, status);
+ }
+
+ private:
+ base::ScopedTempDir base_;
+
+ const GURL origin_;
+ const FileSystemType src_type_;
+ const FileSystemType dest_type_;
+
+ base::MessageLoopForIO message_loop_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ scoped_refptr<quota::MockQuotaManagerProxy> quota_manager_proxy_;
+ scoped_refptr<quota::MockQuotaManager> quota_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOperationTestHelper);
+};
+
+TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFile) {
+ CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
+ kFileSystemTypeTemporary,
+ kFileSystemTypePersistent);
+ helper.SetUp();
+
+ FileSystemURL src = helper.SourceURL("a");
+ FileSystemURL dest = helper.DestURL("b");
+ int64 src_initial_usage = helper.GetSourceUsage();
+ int64 dest_initial_usage = helper.GetDestUsage();
+
+ // Set up a source file.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateFile(src, 10));
+ int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
+
+ // Copy it.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Copy(src, dest));
+
+ // Verify.
+ ASSERT_TRUE(helper.FileExists(src, 10));
+ ASSERT_TRUE(helper.FileExists(dest, 10));
+
+ int64 src_new_usage = helper.GetSourceUsage();
+ ASSERT_EQ(src_initial_usage + src_increase, src_new_usage);
+
+ int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
+ ASSERT_EQ(src_increase, dest_increase);
+}
+
+TEST(LocalFileSystemCopyOrMoveOperationTest, MoveSingleFile) {
+ CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
+ kFileSystemTypeTemporary,
+ kFileSystemTypePersistent);
+ helper.SetUp();
+
+ FileSystemURL src = helper.SourceURL("a");
+ FileSystemURL dest = helper.DestURL("b");
+ int64 src_initial_usage = helper.GetSourceUsage();
+ int64 dest_initial_usage = helper.GetDestUsage();
+
+ // Set up a source file.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateFile(src, 10));
+ int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
+
+ // Move it.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Move(src, dest));
+
+ // Verify.
+ ASSERT_FALSE(helper.FileExists(src, AsyncFileTestHelper::kDontCheckSize));
+ ASSERT_TRUE(helper.FileExists(dest, 10));
+
+ int64 src_new_usage = helper.GetSourceUsage();
+ ASSERT_EQ(src_initial_usage, src_new_usage);
+
+ int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
+ ASSERT_EQ(src_increase, dest_increase);
+}
+
+TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleDirectory) {
+ CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
+ kFileSystemTypeTemporary,
+ kFileSystemTypePersistent);
+ helper.SetUp();
+
+ FileSystemURL src = helper.SourceURL("a");
+ FileSystemURL dest = helper.DestURL("b");
+ int64 src_initial_usage = helper.GetSourceUsage();
+ int64 dest_initial_usage = helper.GetDestUsage();
+
+ // Set up a source directory.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
+ int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
+
+ // Copy it.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Copy(src, dest));
+
+ // Verify.
+ ASSERT_TRUE(helper.DirectoryExists(src));
+ ASSERT_TRUE(helper.DirectoryExists(dest));
+
+ int64 src_new_usage = helper.GetSourceUsage();
+ ASSERT_EQ(src_initial_usage + src_increase, src_new_usage);
+
+ int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
+ ASSERT_EQ(src_increase, dest_increase);
+}
+
+TEST(LocalFileSystemCopyOrMoveOperationTest, MoveSingleDirectory) {
+ CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
+ kFileSystemTypeTemporary,
+ kFileSystemTypePersistent);
+ helper.SetUp();
+
+ FileSystemURL src = helper.SourceURL("a");
+ FileSystemURL dest = helper.DestURL("b");
+ int64 src_initial_usage = helper.GetSourceUsage();
+ int64 dest_initial_usage = helper.GetDestUsage();
+
+ // Set up a source directory.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
+ int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
+
+ // Move it.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Move(src, dest));
+
+ // Verify.
+ ASSERT_FALSE(helper.DirectoryExists(src));
+ ASSERT_TRUE(helper.DirectoryExists(dest));
+
+ int64 src_new_usage = helper.GetSourceUsage();
+ ASSERT_EQ(src_initial_usage, src_new_usage);
+
+ int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
+ ASSERT_EQ(src_increase, dest_increase);
+}
+
+TEST(LocalFileSystemCopyOrMoveOperationTest, CopyDirectory) {
+ CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
+ kFileSystemTypeTemporary,
+ kFileSystemTypePersistent);
+ helper.SetUp();
+
+ FileSystemURL src = helper.SourceURL("a");
+ FileSystemURL dest = helper.DestURL("b");
+ int64 src_initial_usage = helper.GetSourceUsage();
+ int64 dest_initial_usage = helper.GetDestUsage();
+
+ // Set up a source directory.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ helper.SetUpTestCaseFiles(src,
+ test::kRegularTestCases,
+ test::kRegularTestCaseSize));
+ int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
+
+ // Copy it.
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ helper.CopyWithProgress(
+ src, dest,
+ AsyncFileTestHelper::CopyProgressCallback()));
+
+ // Verify.
+ ASSERT_TRUE(helper.DirectoryExists(src));
+ ASSERT_TRUE(helper.DirectoryExists(dest));
+
+ helper.VerifyTestCaseFiles(dest,
+ test::kRegularTestCases,
+ test::kRegularTestCaseSize);
+
+ int64 src_new_usage = helper.GetSourceUsage();
+ ASSERT_EQ(src_initial_usage + src_increase, src_new_usage);
+
+ int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
+ ASSERT_EQ(src_increase, dest_increase);
+}
+
+TEST(LocalFileSystemCopyOrMoveOperationTest, MoveDirectory) {
+ CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
+ kFileSystemTypeTemporary,
+ kFileSystemTypePersistent);
+ helper.SetUp();
+
+ FileSystemURL src = helper.SourceURL("a");
+ FileSystemURL dest = helper.DestURL("b");
+ int64 src_initial_usage = helper.GetSourceUsage();
+ int64 dest_initial_usage = helper.GetDestUsage();
+
+ // Set up a source directory.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ helper.SetUpTestCaseFiles(src,
+ test::kRegularTestCases,
+ test::kRegularTestCaseSize));
+ int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
+
+ // Move it.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Move(src, dest));
+
+ // Verify.
+ ASSERT_FALSE(helper.DirectoryExists(src));
+ ASSERT_TRUE(helper.DirectoryExists(dest));
+
+ helper.VerifyTestCaseFiles(dest,
+ test::kRegularTestCases,
+ test::kRegularTestCaseSize);
+
+ int64 src_new_usage = helper.GetSourceUsage();
+ ASSERT_EQ(src_initial_usage, src_new_usage);
+
+ int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
+ ASSERT_EQ(src_increase, dest_increase);
+}
+
+TEST(LocalFileSystemCopyOrMoveOperationTest,
+ MoveDirectoryFailPostWriteValidation) {
+ CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
+ kFileSystemTypeTemporary,
+ kFileSystemTypeTest);
+ helper.SetUp();
+
+ FileSystemURL src = helper.SourceURL("a");
+ FileSystemURL dest = helper.DestURL("b");
+
+ // Set up a source directory.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ helper.SetUpTestCaseFiles(src,
+ test::kRegularTestCases,
+ test::kRegularTestCaseSize));
+
+ // Move it.
+ helper.Move(src, dest);
+
+ // Verify.
+ ASSERT_TRUE(helper.DirectoryExists(src));
+ ASSERT_TRUE(helper.DirectoryExists(dest));
+
+ test::TestCaseRecord kMoveDirResultCases[] = {
+ {false, FILE_PATH_LITERAL("file 0"), 38},
+ {false, FILE_PATH_LITERAL("file 3"), 0},
+ };
+
+ helper.VerifyTestCaseFiles(dest,
+ kMoveDirResultCases,
+ arraysize(kMoveDirResultCases));
+}
+
+TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFileNoValidator) {
+ CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
+ kFileSystemTypeTemporary,
+ kFileSystemTypeTest);
+ helper.SetUpNoValidator();
+
+ FileSystemURL src = helper.SourceURL("a");
+ FileSystemURL dest = helper.DestURL("b");
+
+ // Set up a source file.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateFile(src, 10));
+
+ // The copy attempt should fail with a security error -- getting
+ // the factory returns a security error, and the copy operation must
+ // respect that.
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_SECURITY, helper.Copy(src, dest));
+}
+
+TEST(LocalFileSystemCopyOrMoveOperationTest, ProgressCallback) {
+ CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
+ kFileSystemTypeTemporary,
+ kFileSystemTypePersistent);
+ helper.SetUp();
+
+ FileSystemURL src = helper.SourceURL("a");
+ FileSystemURL dest = helper.DestURL("b");
+
+ // Set up a source directory.
+ ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ helper.SetUpTestCaseFiles(src,
+ test::kRegularTestCases,
+ test::kRegularTestCaseSize));
+
+ std::vector<ProgressRecord> records;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ helper.CopyWithProgress(src, dest,
+ base::Bind(&RecordProgressCallback,
+ base::Unretained(&records))));
+
+ // Verify progress callback.
+ for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
+ const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
+
+ FileSystemURL src_url = helper.SourceURL(
+ std::string("a/") + base::FilePath(test_case.path).AsUTF8Unsafe());
+ FileSystemURL dest_url = helper.DestURL(
+ std::string("b/") + base::FilePath(test_case.path).AsUTF8Unsafe());
+
+ // Find the first and last progress record.
+ size_t begin_index = records.size();
+ size_t end_index = records.size();
+ for (size_t j = 0; j < records.size(); ++j) {
+ if (records[j].source_url == src_url) {
+ if (begin_index == records.size())
+ begin_index = j;
+ end_index = j;
+ }
+ }
+
+ // The record should be found.
+ ASSERT_NE(begin_index, records.size());
+ ASSERT_NE(end_index, records.size());
+ ASSERT_NE(begin_index, end_index);
+
+ EXPECT_EQ(FileSystemOperation::BEGIN_COPY_ENTRY,
+ records[begin_index].type);
+ EXPECT_FALSE(records[begin_index].dest_url.is_valid());
+ EXPECT_EQ(FileSystemOperation::END_COPY_ENTRY, records[end_index].type);
+ EXPECT_EQ(dest_url, records[end_index].dest_url);
+
+ if (test_case.is_directory) {
+ // For directory copy, the progress shouldn't be interlaced.
+ EXPECT_EQ(begin_index + 1, end_index);
+ } else {
+ // PROGRESS event's size should be assending order.
+ int64 current_size = 0;
+ for (size_t j = begin_index + 1; j < end_index; ++j) {
+ if (records[j].source_url == src_url) {
+ EXPECT_EQ(FileSystemOperation::PROGRESS, records[j].type);
+ EXPECT_FALSE(records[j].dest_url.is_valid());
+ EXPECT_GE(records[j].size, current_size);
+ current_size = records[j].size;
+ }
+ }
+ }
+ }
+}
+
+TEST(LocalFileSystemCopyOrMoveOperationTest, StreamCopyHelper) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath source_path = temp_dir.path().AppendASCII("source");
+ const char kTestData[] = "abcdefghijklmnopqrstuvwxyz0123456789";
+ file_util::WriteFile(source_path, kTestData,
+ arraysize(kTestData) - 1); // Exclude trailing '\0'.
+
+ base::FilePath dest_path = temp_dir.path().AppendASCII("dest");
+ // LocalFileWriter requires the file exists. So create an empty file here.
+ file_util::WriteFile(dest_path, "", 0);
+
+ base::MessageLoopForIO message_loop;
+ base::Thread file_thread("file_thread");
+ ASSERT_TRUE(file_thread.Start());
+ ScopedThreadStopper thread_stopper(&file_thread);
+ ASSERT_TRUE(thread_stopper.is_valid());
+
+ scoped_refptr<base::MessageLoopProxy> task_runner =
+ file_thread.message_loop_proxy();
+
+ scoped_ptr<webkit_blob::FileStreamReader> reader(
+ webkit_blob::FileStreamReader::CreateForLocalFile(
+ task_runner.get(), source_path, 0, base::Time()));
+
+ scoped_ptr<FileStreamWriter> writer(
+ FileStreamWriter::CreateForLocalFile(task_runner.get(), dest_path, 0));
+
+ std::vector<int64> progress;
+ CopyOrMoveOperationDelegate::StreamCopyHelper helper(
+ reader.Pass(), writer.Pass(),
+ false, // don't need flush
+ 10, // buffer size
+ base::Bind(&RecordFileProgressCallback, base::Unretained(&progress)),
+ base::TimeDelta()); // For testing, we need all the progress.
+
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ base::RunLoop run_loop;
+ helper.Run(base::Bind(&AssignAndQuit, &run_loop, &error));
+ run_loop.Run();
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK, error);
+ ASSERT_EQ(5U, progress.size());
+ EXPECT_EQ(0, progress[0]);
+ EXPECT_EQ(10, progress[1]);
+ EXPECT_EQ(20, progress[2]);
+ EXPECT_EQ(30, progress[3]);
+ EXPECT_EQ(36, progress[4]);
+
+ std::string content;
+ ASSERT_TRUE(base::ReadFileToString(dest_path, &content));
+ EXPECT_EQ(kTestData, content);
+}
+
+TEST(LocalFileSystemCopyOrMoveOperationTest, StreamCopyHelperWithFlush) {
+ // Testing the same configuration as StreamCopyHelper, but with |need_flush|
+ // parameter set to true. Since it is hard to test that the flush is indeed
+ // taking place, this test just only verifies that the file is correctly
+ // written with or without the flag.
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath source_path = temp_dir.path().AppendASCII("source");
+ const char kTestData[] = "abcdefghijklmnopqrstuvwxyz0123456789";
+ file_util::WriteFile(source_path, kTestData,
+ arraysize(kTestData) - 1); // Exclude trailing '\0'.
+
+ base::FilePath dest_path = temp_dir.path().AppendASCII("dest");
+ // LocalFileWriter requires the file exists. So create an empty file here.
+ file_util::WriteFile(dest_path, "", 0);
+
+ base::MessageLoopForIO message_loop;
+ base::Thread file_thread("file_thread");
+ ASSERT_TRUE(file_thread.Start());
+ ScopedThreadStopper thread_stopper(&file_thread);
+ ASSERT_TRUE(thread_stopper.is_valid());
+
+ scoped_refptr<base::MessageLoopProxy> task_runner =
+ file_thread.message_loop_proxy();
+
+ scoped_ptr<webkit_blob::FileStreamReader> reader(
+ webkit_blob::FileStreamReader::CreateForLocalFile(
+ task_runner.get(), source_path, 0, base::Time()));
+
+ scoped_ptr<FileStreamWriter> writer(
+ FileStreamWriter::CreateForLocalFile(task_runner.get(), dest_path, 0));
+
+ std::vector<int64> progress;
+ CopyOrMoveOperationDelegate::StreamCopyHelper helper(
+ reader.Pass(), writer.Pass(),
+ true, // need flush
+ 10, // buffer size
+ base::Bind(&RecordFileProgressCallback, base::Unretained(&progress)),
+ base::TimeDelta()); // For testing, we need all the progress.
+
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ base::RunLoop run_loop;
+ helper.Run(base::Bind(&AssignAndQuit, &run_loop, &error));
+ run_loop.Run();
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK, error);
+ ASSERT_EQ(5U, progress.size());
+ EXPECT_EQ(0, progress[0]);
+ EXPECT_EQ(10, progress[1]);
+ EXPECT_EQ(20, progress[2]);
+ EXPECT_EQ(30, progress[3]);
+ EXPECT_EQ(36, progress[4]);
+
+ std::string content;
+ ASSERT_TRUE(base::ReadFileToString(dest_path, &content));
+ EXPECT_EQ(kTestData, content);
+}
+
+TEST(LocalFileSystemCopyOrMoveOperationTest, StreamCopyHelper_Cancel) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath source_path = temp_dir.path().AppendASCII("source");
+ const char kTestData[] = "abcdefghijklmnopqrstuvwxyz0123456789";
+ file_util::WriteFile(source_path, kTestData,
+ arraysize(kTestData) - 1); // Exclude trailing '\0'.
+
+ base::FilePath dest_path = temp_dir.path().AppendASCII("dest");
+ // LocalFileWriter requires the file exists. So create an empty file here.
+ file_util::WriteFile(dest_path, "", 0);
+
+ base::MessageLoopForIO message_loop;
+ base::Thread file_thread("file_thread");
+ ASSERT_TRUE(file_thread.Start());
+ ScopedThreadStopper thread_stopper(&file_thread);
+ ASSERT_TRUE(thread_stopper.is_valid());
+
+ scoped_refptr<base::MessageLoopProxy> task_runner =
+ file_thread.message_loop_proxy();
+
+ scoped_ptr<webkit_blob::FileStreamReader> reader(
+ webkit_blob::FileStreamReader::CreateForLocalFile(
+ task_runner.get(), source_path, 0, base::Time()));
+
+ scoped_ptr<FileStreamWriter> writer(
+ FileStreamWriter::CreateForLocalFile(task_runner.get(), dest_path, 0));
+
+ std::vector<int64> progress;
+ CopyOrMoveOperationDelegate::StreamCopyHelper helper(
+ reader.Pass(), writer.Pass(),
+ false, // need_flush
+ 10, // buffer size
+ base::Bind(&RecordFileProgressCallback, base::Unretained(&progress)),
+ base::TimeDelta()); // For testing, we need all the progress.
+
+ // Call Cancel() later.
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&CopyOrMoveOperationDelegate::StreamCopyHelper::Cancel,
+ base::Unretained(&helper)));
+
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ base::RunLoop run_loop;
+ helper.Run(base::Bind(&AssignAndQuit, &run_loop, &error));
+ run_loop.Run();
+
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_ABORT, error);
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/dragged_file_util_unittest.cc b/chromium/content/browser/fileapi/dragged_file_util_unittest.cc
new file mode 100644
index 00000000000..17b29cc6be5
--- /dev/null
+++ b/chromium/content/browser/fileapi/dragged_file_util_unittest.cc
@@ -0,0 +1,544 @@
+// 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 <map>
+#include <queue>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/file_util.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/time/time.h"
+#include "content/public/test/test_file_system_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/dragged_file_util.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/fileapi/local_file_util.h"
+#include "webkit/browser/fileapi/native_file_util.h"
+#include "webkit/browser/fileapi/test_file_set.h"
+
+namespace fileapi {
+
+namespace {
+
+typedef AsyncFileTestHelper::FileEntryList FileEntryList;
+
+// Used in DraggedFileUtilTest::SimulateDropFiles().
+// Random root paths in which we create each file/directory of the
+// RegularTestCases (so that we can simulate a drop with files/directories
+// from multiple directories).
+static const base::FilePath::CharType* kRootPaths[] = {
+ FILE_PATH_LITERAL("a"),
+ FILE_PATH_LITERAL("b/c"),
+ FILE_PATH_LITERAL("etc"),
+};
+
+base::FilePath GetTopLevelPath(const base::FilePath& path) {
+ std::vector<base::FilePath::StringType> components;
+ path.GetComponents(&components);
+ return base::FilePath(components[0]);
+}
+
+bool IsDirectoryEmpty(FileSystemContext* context, const FileSystemURL& url) {
+ FileEntryList entries;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::ReadDirectory(context, url, &entries));
+ return entries.empty();
+}
+
+FileSystemURL GetEntryURL(FileSystemContext* file_system_context,
+ const FileSystemURL& dir,
+ const base::FilePath::StringType& name) {
+ return file_system_context->CreateCrackedFileSystemURL(
+ dir.origin(),
+ dir.mount_type(),
+ dir.virtual_path().Append(name));
+}
+
+base::FilePath GetRelativeVirtualPath(const FileSystemURL& root,
+ const FileSystemURL& url) {
+ if (root.virtual_path().empty())
+ return url.virtual_path();
+ base::FilePath relative;
+ const bool success = root.virtual_path().AppendRelativePath(
+ url.virtual_path(), &relative);
+ DCHECK(success);
+ return relative;
+}
+
+FileSystemURL GetOtherURL(FileSystemContext* file_system_context,
+ const FileSystemURL& root,
+ const FileSystemURL& other_root,
+ const FileSystemURL& url) {
+ return file_system_context->CreateCrackedFileSystemURL(
+ other_root.origin(),
+ other_root.mount_type(),
+ other_root.virtual_path().Append(GetRelativeVirtualPath(root, url)));
+}
+
+} // namespace
+
+class DraggedFileUtilTest : public testing::Test {
+ public:
+ DraggedFileUtilTest() {}
+
+ virtual void SetUp() {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+ ASSERT_TRUE(partition_dir_.CreateUniqueTempDir());
+ file_util_.reset(new DraggedFileUtil());
+
+ // Register the files/directories of RegularTestCases (with random
+ // root paths) as dropped files.
+ SimulateDropFiles();
+
+ file_system_context_ = CreateFileSystemContextForTesting(
+ NULL /* quota_manager */,
+ partition_dir_.path());
+
+ isolated_context()->AddReference(filesystem_id_);
+ }
+
+ virtual void TearDown() {
+ isolated_context()->RemoveReference(filesystem_id_);
+ }
+
+ protected:
+ IsolatedContext* isolated_context() const {
+ return IsolatedContext::GetInstance();
+ }
+ const base::FilePath& root_path() const {
+ return data_dir_.path();
+ }
+ FileSystemContext* file_system_context() const {
+ return file_system_context_.get();
+ }
+ FileSystemFileUtil* file_util() const { return file_util_.get(); }
+ std::string filesystem_id() const { return filesystem_id_; }
+
+ base::FilePath GetTestCasePlatformPath(
+ const base::FilePath::StringType& path) {
+ return toplevel_root_map_[GetTopLevelPath(base::FilePath(path))]
+ .Append(path).NormalizePathSeparators();
+ }
+
+ base::FilePath GetTestCaseLocalPath(const base::FilePath& path) {
+ base::FilePath relative;
+ if (data_dir_.path().AppendRelativePath(path, &relative))
+ return relative;
+ return path;
+ }
+
+ FileSystemURL GetFileSystemURL(const base::FilePath& path) const {
+ base::FilePath virtual_path = isolated_context()->CreateVirtualRootPath(
+ filesystem_id()).Append(path);
+ return file_system_context_->CreateCrackedFileSystemURL(
+ GURL("http://example.com"),
+ kFileSystemTypeIsolated,
+ virtual_path);
+ }
+
+ FileSystemURL GetOtherFileSystemURL(const base::FilePath& path) const {
+ return file_system_context()->CreateCrackedFileSystemURL(
+ GURL("http://example.com"),
+ kFileSystemTypeTemporary,
+ base::FilePath().AppendASCII("dest").Append(path));
+ }
+
+ void VerifyFilesHaveSameContent(const FileSystemURL& url1,
+ const FileSystemURL& url2) {
+ // Get the file info and the platform path for url1.
+ base::PlatformFileInfo info1;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::GetMetadata(
+ file_system_context(), url1, &info1));
+ base::FilePath platform_path1;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::GetPlatformPath(
+ file_system_context(), url1, &platform_path1));
+
+ // Get the file info and the platform path for url2.
+ base::PlatformFileInfo info2;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::GetMetadata(
+ file_system_context(), url2, &info2));
+ base::FilePath platform_path2;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::GetPlatformPath(
+ file_system_context(), url2, &platform_path2));
+
+ // See if file info matches with the other one.
+ EXPECT_EQ(info1.is_directory, info2.is_directory);
+ EXPECT_EQ(info1.size, info2.size);
+ EXPECT_EQ(info1.is_symbolic_link, info2.is_symbolic_link);
+ EXPECT_NE(platform_path1, platform_path2);
+
+ std::string content1, content2;
+ EXPECT_TRUE(base::ReadFileToString(platform_path1, &content1));
+ EXPECT_TRUE(base::ReadFileToString(platform_path2, &content2));
+ EXPECT_EQ(content1, content2);
+ }
+
+ void VerifyDirectoriesHaveSameContent(const FileSystemURL& root1,
+ const FileSystemURL& root2) {
+ base::FilePath root_path1 = root1.path();
+ base::FilePath root_path2 = root2.path();
+
+ FileEntryList entries;
+ std::queue<FileSystemURL> directories;
+
+ directories.push(root1);
+ std::set<base::FilePath> file_set1;
+ while (!directories.empty()) {
+ FileSystemURL dir = directories.front();
+ directories.pop();
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::ReadDirectory(
+ file_system_context(), dir, &entries));
+ for (size_t i = 0; i < entries.size(); ++i) {
+ FileSystemURL url = GetEntryURL(file_system_context(),
+ dir, entries[i].name);
+ if (entries[i].is_directory) {
+ directories.push(url);
+ continue;
+ }
+ file_set1.insert(GetRelativeVirtualPath(root1, url));
+ }
+ }
+
+ directories.push(root2);
+ while (!directories.empty()) {
+ FileSystemURL dir = directories.front();
+ directories.pop();
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::ReadDirectory(
+ file_system_context(), dir, &entries));
+ for (size_t i = 0; i < entries.size(); ++i) {
+ FileSystemURL url2 = GetEntryURL(file_system_context(),
+ dir, entries[i].name);
+ FileSystemURL url1 = GetOtherURL(file_system_context(),
+ root2, root1, url2);
+ if (entries[i].is_directory) {
+ directories.push(url2);
+ EXPECT_EQ(IsDirectoryEmpty(file_system_context(), url1),
+ IsDirectoryEmpty(file_system_context(), url2));
+ continue;
+ }
+ base::FilePath relative = GetRelativeVirtualPath(root2, url2);
+ EXPECT_TRUE(file_set1.find(relative) != file_set1.end());
+ VerifyFilesHaveSameContent(url1, url2);
+ }
+ }
+ }
+
+ scoped_ptr<FileSystemOperationContext> GetOperationContext() {
+ return make_scoped_ptr(
+ new FileSystemOperationContext(file_system_context())).Pass();
+ }
+
+
+ private:
+ void SimulateDropFiles() {
+ size_t root_path_index = 0;
+
+ IsolatedContext::FileInfoSet toplevels;
+ for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
+ const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
+ base::FilePath path(test_case.path);
+ base::FilePath toplevel = GetTopLevelPath(path);
+
+ // We create the test case files under one of the kRootPaths
+ // to simulate a drop with multiple directories.
+ if (toplevel_root_map_.find(toplevel) == toplevel_root_map_.end()) {
+ base::FilePath root = root_path().Append(
+ kRootPaths[(root_path_index++) % arraysize(kRootPaths)]);
+ toplevel_root_map_[toplevel] = root;
+ toplevels.AddPath(root.Append(path), NULL);
+ }
+
+ test::SetUpOneTestCase(toplevel_root_map_[toplevel], test_case);
+ }
+
+ // Register the toplevel entries.
+ filesystem_id_ = isolated_context()->RegisterDraggedFileSystem(toplevels);
+ }
+
+ base::ScopedTempDir data_dir_;
+ base::ScopedTempDir partition_dir_;
+ base::MessageLoopForIO message_loop_;
+ std::string filesystem_id_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ std::map<base::FilePath, base::FilePath> toplevel_root_map_;
+ scoped_ptr<DraggedFileUtil> file_util_;
+ DISALLOW_COPY_AND_ASSIGN(DraggedFileUtilTest);
+};
+
+TEST_F(DraggedFileUtilTest, BasicTest) {
+ for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
+ SCOPED_TRACE(testing::Message() << "Testing RegularTestCases " << i);
+ const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
+
+ FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
+
+ // See if we can query the file info via the isolated FileUtil.
+ // (This should succeed since we have registered all the top-level
+ // entries of the test cases in SetUp())
+ base::PlatformFileInfo info;
+ base::FilePath platform_path;
+ FileSystemOperationContext context(file_system_context());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->GetFileInfo(&context, url, &info, &platform_path));
+
+ // See if the obtained file info is correct.
+ if (!test_case.is_directory)
+ ASSERT_EQ(test_case.data_file_size, info.size);
+ ASSERT_EQ(test_case.is_directory, info.is_directory);
+ ASSERT_EQ(GetTestCasePlatformPath(test_case.path),
+ platform_path.NormalizePathSeparators());
+ }
+}
+
+TEST_F(DraggedFileUtilTest, UnregisteredPathsTest) {
+ static const fileapi::test::TestCaseRecord kUnregisteredCases[] = {
+ {true, FILE_PATH_LITERAL("nonexistent"), 0},
+ {true, FILE_PATH_LITERAL("nonexistent/dir foo"), 0},
+ {false, FILE_PATH_LITERAL("nonexistent/false"), 0},
+ {false, FILE_PATH_LITERAL("foo"), 30},
+ {false, FILE_PATH_LITERAL("bar"), 20},
+ };
+
+ for (size_t i = 0; i < arraysize(kUnregisteredCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "Creating kUnregisteredCases " << i);
+ const test::TestCaseRecord& test_case = kUnregisteredCases[i];
+
+ // Prepare the test file/directory.
+ SetUpOneTestCase(root_path(), test_case);
+
+ // Make sure regular GetFileInfo succeeds.
+ base::PlatformFileInfo info;
+ ASSERT_TRUE(base::GetFileInfo(root_path().Append(test_case.path), &info));
+ if (!test_case.is_directory)
+ ASSERT_EQ(test_case.data_file_size, info.size);
+ ASSERT_EQ(test_case.is_directory, info.is_directory);
+ }
+
+ for (size_t i = 0; i < arraysize(kUnregisteredCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "Creating kUnregisteredCases " << i);
+ const test::TestCaseRecord& test_case = kUnregisteredCases[i];
+ FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
+
+ // We should not be able to get the valid URL for unregistered files.
+ ASSERT_FALSE(url.is_valid());
+ }
+}
+
+TEST_F(DraggedFileUtilTest, ReadDirectoryTest) {
+ for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
+ const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
+ if (!test_case.is_directory)
+ continue;
+
+ SCOPED_TRACE(testing::Message() << "Testing RegularTestCases " << i
+ << ": " << test_case.path);
+
+ // Read entries in the directory to construct the expected results map.
+ typedef std::map<base::FilePath::StringType, DirectoryEntry> EntryMap;
+ EntryMap expected_entry_map;
+
+ base::FilePath dir_path = GetTestCasePlatformPath(test_case.path);
+ base::FileEnumerator file_enum(
+ dir_path, false /* not recursive */,
+ base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
+ base::FilePath current;
+ while (!(current = file_enum.Next()).empty()) {
+ base::FileEnumerator::FileInfo file_info = file_enum.GetInfo();
+ DirectoryEntry entry;
+ entry.is_directory = file_info.IsDirectory();
+ entry.name = current.BaseName().value();
+ entry.size = file_info.GetSize();
+ entry.last_modified_time = file_info.GetLastModifiedTime();
+ expected_entry_map[entry.name] = entry;
+
+#if defined(OS_POSIX)
+ // Creates a symlink for each file/directory.
+ // They should be ignored by ReadDirectory, so we don't add them
+ // to expected_entry_map.
+ base::CreateSymbolicLink(
+ current,
+ dir_path.Append(current.BaseName().AddExtension(
+ FILE_PATH_LITERAL("link"))));
+#endif
+ }
+
+ // Perform ReadDirectory in the isolated filesystem.
+ FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
+ FileEntryList entries;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::ReadDirectory(
+ file_system_context(), url, &entries));
+
+ EXPECT_EQ(expected_entry_map.size(), entries.size());
+ for (size_t i = 0; i < entries.size(); ++i) {
+ const DirectoryEntry& entry = entries[i];
+ EntryMap::iterator found = expected_entry_map.find(entry.name);
+ EXPECT_TRUE(found != expected_entry_map.end());
+ EXPECT_EQ(found->second.name, entry.name);
+ EXPECT_EQ(found->second.is_directory, entry.is_directory);
+ EXPECT_EQ(found->second.size, entry.size);
+ EXPECT_EQ(found->second.last_modified_time.ToDoubleT(),
+ entry.last_modified_time.ToDoubleT());
+ }
+ }
+}
+
+TEST_F(DraggedFileUtilTest, GetLocalFilePathTest) {
+ for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
+ const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
+ FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
+
+ FileSystemOperationContext context(file_system_context());
+
+ base::FilePath local_file_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->GetLocalFilePath(&context, url, &local_file_path));
+ EXPECT_EQ(GetTestCasePlatformPath(test_case.path).value(),
+ local_file_path.value());
+ }
+}
+
+TEST_F(DraggedFileUtilTest, CopyOutFileTest) {
+ FileSystemURL src_root = GetFileSystemURL(base::FilePath());
+ FileSystemURL dest_root = GetOtherFileSystemURL(base::FilePath());
+
+ FileEntryList entries;
+ std::queue<FileSystemURL> directories;
+ directories.push(src_root);
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::CreateDirectory(file_system_context(),
+ dest_root));
+
+ while (!directories.empty()) {
+ FileSystemURL dir = directories.front();
+ directories.pop();
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::ReadDirectory(file_system_context(),
+ dir, &entries));
+ for (size_t i = 0; i < entries.size(); ++i) {
+ FileSystemURL src_url = GetEntryURL(file_system_context(),
+ dir, entries[i].name);
+ FileSystemURL dest_url = GetOtherURL(file_system_context(),
+ src_root, dest_root, src_url);
+
+ if (entries[i].is_directory) {
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::CreateDirectory(file_system_context(),
+ dest_url));
+ directories.push(src_url);
+ continue;
+ }
+ SCOPED_TRACE(testing::Message() << "Testing file copy "
+ << src_url.path().value());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::Copy(file_system_context(),
+ src_url, dest_url));
+ VerifyFilesHaveSameContent(src_url, dest_url);
+ }
+ }
+}
+
+TEST_F(DraggedFileUtilTest, CopyOutDirectoryTest) {
+ FileSystemURL src_root = GetFileSystemURL(base::FilePath());
+ FileSystemURL dest_root = GetOtherFileSystemURL(base::FilePath());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::CreateDirectory(file_system_context(),
+ dest_root));
+
+ FileEntryList entries;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::ReadDirectory(file_system_context(),
+ src_root, &entries));
+ for (size_t i = 0; i < entries.size(); ++i) {
+ if (!entries[i].is_directory)
+ continue;
+ FileSystemURL src_url = GetEntryURL(file_system_context(),
+ src_root, entries[i].name);
+ FileSystemURL dest_url = GetOtherURL(file_system_context(),
+ src_root, dest_root, src_url);
+ SCOPED_TRACE(testing::Message() << "Testing file copy "
+ << src_url.path().value());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::Copy(file_system_context(),
+ src_url, dest_url));
+ VerifyDirectoriesHaveSameContent(src_url, dest_url);
+ }
+}
+
+TEST_F(DraggedFileUtilTest, TouchTest) {
+ for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
+ const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
+ if (test_case.is_directory)
+ continue;
+ SCOPED_TRACE(testing::Message() << test_case.path);
+ FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
+
+ base::Time last_access_time = base::Time::FromTimeT(1000);
+ base::Time last_modified_time = base::Time::FromTimeT(2000);
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Touch(GetOperationContext().get(), url,
+ last_access_time,
+ last_modified_time));
+
+ // Verification.
+ base::PlatformFileInfo info;
+ base::FilePath platform_path;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->GetFileInfo(GetOperationContext().get(), url,
+ &info, &platform_path));
+ EXPECT_EQ(last_access_time.ToTimeT(), info.last_accessed.ToTimeT());
+ EXPECT_EQ(last_modified_time.ToTimeT(), info.last_modified.ToTimeT());
+ }
+}
+
+TEST_F(DraggedFileUtilTest, TruncateTest) {
+ for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
+ const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
+ if (test_case.is_directory)
+ continue;
+
+ SCOPED_TRACE(testing::Message() << test_case.path);
+ FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
+
+ // Truncate to 0.
+ base::PlatformFileInfo info;
+ base::FilePath platform_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Truncate(GetOperationContext().get(), url, 0));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->GetFileInfo(GetOperationContext().get(), url,
+ &info, &platform_path));
+ EXPECT_EQ(0, info.size);
+
+ // Truncate (extend) to 999.
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Truncate(GetOperationContext().get(), url, 999));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->GetFileInfo(GetOperationContext().get(), url,
+ &info, &platform_path));
+ EXPECT_EQ(999, info.size);
+ }
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/file_system_browsertest.cc b/chromium/content/browser/fileapi/file_system_browsertest.cc
index eafb1b1cfa4..a3a83efd483 100644
--- a/chromium/content/browser/fileapi/file_system_browsertest.cc
+++ b/chromium/content/browser/fileapi/file_system_browsertest.cc
@@ -33,9 +33,9 @@ class FileSystemBrowserTest : public ContentBrowserTest {
// a #pass or #fail ref.
Shell* the_browser = incognito ? CreateOffTheRecordBrowser() : shell();
- LOG(INFO) << "Navigating to URL and blocking.";
+ VLOG(0) << "Navigating to URL and blocking.";
NavigateToURLBlockUntilNavigationsComplete(the_browser, test_url, 2);
- LOG(INFO) << "Navigation done.";
+ VLOG(0) << "Navigation done.";
std::string result =
the_browser->web_contents()->GetLastCommittedURL().ref();
if (result != "pass") {
diff --git a/chromium/content/browser/fileapi/file_system_context_unittest.cc b/chromium/content/browser/fileapi/file_system_context_unittest.cc
new file mode 100644
index 00000000000..43003ad0dc4
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_context_unittest.cc
@@ -0,0 +1,374 @@
+// 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 "webkit/browser/fileapi/file_system_context.h"
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/stringprintf.h"
+#include "content/public/test/test_file_system_options.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+#include "webkit/browser/fileapi/file_system_backend.h"
+#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/quota/mock_quota_manager.h"
+#include "webkit/browser/quota/mock_special_storage_policy.h"
+
+#define FPL(x) FILE_PATH_LITERAL(x)
+
+#if defined(FILE_PATH_USES_DRIVE_LETTERS)
+#define DRIVE FPL("C:")
+#else
+#define DRIVE
+#endif
+
+namespace fileapi {
+
+namespace {
+
+const char kTestOrigin[] = "http://chromium.org/";
+
+GURL CreateRawFileSystemURL(const std::string& type_str,
+ const std::string& fs_id) {
+ std::string url_str = base::StringPrintf(
+ "filesystem:http://chromium.org/%s/%s/root/file",
+ type_str.c_str(),
+ fs_id.c_str());
+ return GURL(url_str);
+}
+
+class FileSystemContextTest : public testing::Test {
+ public:
+ FileSystemContextTest() {}
+
+ virtual void SetUp() {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+
+ storage_policy_ = new quota::MockSpecialStoragePolicy();
+
+ mock_quota_manager_ =
+ new quota::MockQuotaManager(false /* is_incognito */,
+ data_dir_.path(),
+ base::MessageLoopProxy::current().get(),
+ base::MessageLoopProxy::current().get(),
+ storage_policy_.get());
+ }
+
+ protected:
+ FileSystemContext* CreateFileSystemContextForTest(
+ ExternalMountPoints* external_mount_points) {
+ return new FileSystemContext(base::MessageLoopProxy::current().get(),
+ base::MessageLoopProxy::current().get(),
+ external_mount_points,
+ storage_policy_.get(),
+ mock_quota_manager_->proxy(),
+ ScopedVector<FileSystemBackend>(),
+ data_dir_.path(),
+ CreateAllowFileAccessOptions());
+ }
+
+ // Verifies a *valid* filesystem url has expected values.
+ void ExpectFileSystemURLMatches(const FileSystemURL& url,
+ const GURL& expect_origin,
+ FileSystemType expect_mount_type,
+ FileSystemType expect_type,
+ const base::FilePath& expect_path,
+ const base::FilePath& expect_virtual_path,
+ const std::string& expect_filesystem_id) {
+ EXPECT_TRUE(url.is_valid());
+
+ EXPECT_EQ(expect_origin, url.origin());
+ EXPECT_EQ(expect_mount_type, url.mount_type());
+ EXPECT_EQ(expect_type, url.type());
+ EXPECT_EQ(expect_path, url.path());
+ EXPECT_EQ(expect_virtual_path, url.virtual_path());
+ EXPECT_EQ(expect_filesystem_id, url.filesystem_id());
+ }
+
+ private:
+ base::ScopedTempDir data_dir_;
+ base::MessageLoop message_loop_;
+ scoped_refptr<quota::SpecialStoragePolicy> storage_policy_;
+ scoped_refptr<quota::MockQuotaManager> mock_quota_manager_;
+};
+
+// It is not valid to pass NULL ExternalMountPoints to FileSystemContext on
+// ChromeOS.
+#if !defined(OS_CHROMEOS)
+TEST_F(FileSystemContextTest, NullExternalMountPoints) {
+ scoped_refptr<FileSystemContext> file_system_context(
+ CreateFileSystemContextForTest(NULL));
+
+ // Cracking system external mount and isolated mount points should work.
+ std::string isolated_name = "root";
+ std::string isolated_id =
+ IsolatedContext::GetInstance()->RegisterFileSystemForPath(
+ kFileSystemTypeNativeLocal,
+ base::FilePath(DRIVE FPL("/test/isolated/root")),
+ &isolated_name);
+ // Register system external mount point.
+ ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+ "system",
+ kFileSystemTypeNativeLocal,
+ FileSystemMountOption(),
+ base::FilePath(DRIVE FPL("/test/sys/"))));
+
+ FileSystemURL cracked_isolated = file_system_context->CrackURL(
+ CreateRawFileSystemURL("isolated", isolated_id));
+
+ ExpectFileSystemURLMatches(
+ cracked_isolated,
+ GURL(kTestOrigin),
+ kFileSystemTypeIsolated,
+ kFileSystemTypeNativeLocal,
+ base::FilePath(
+ DRIVE FPL("/test/isolated/root/file")).NormalizePathSeparators(),
+ base::FilePath::FromUTF8Unsafe(isolated_id).Append(FPL("root/file")).
+ NormalizePathSeparators(),
+ isolated_id);
+
+ FileSystemURL cracked_external = file_system_context->CrackURL(
+ CreateRawFileSystemURL("external", "system"));
+
+ ExpectFileSystemURLMatches(
+ cracked_external,
+ GURL(kTestOrigin),
+ kFileSystemTypeExternal,
+ kFileSystemTypeNativeLocal,
+ base::FilePath(
+ DRIVE FPL("/test/sys/root/file")).NormalizePathSeparators(),
+ base::FilePath(FPL("system/root/file")).NormalizePathSeparators(),
+ "system");
+
+
+ IsolatedContext::GetInstance()->RevokeFileSystem(isolated_id);
+ ExternalMountPoints::GetSystemInstance()->RevokeFileSystem("system");
+}
+#endif // !defiend(OS_CHROMEOS)
+
+TEST_F(FileSystemContextTest, FileSystemContextKeepsMountPointsAlive) {
+ scoped_refptr<ExternalMountPoints> mount_points =
+ ExternalMountPoints::CreateRefCounted();
+
+ // Register system external mount point.
+ ASSERT_TRUE(mount_points->RegisterFileSystem(
+ "system",
+ kFileSystemTypeNativeLocal,
+ FileSystemMountOption(),
+ base::FilePath(DRIVE FPL("/test/sys/"))));
+
+ scoped_refptr<FileSystemContext> file_system_context(
+ CreateFileSystemContextForTest(mount_points.get()));
+
+ // Release a MountPoints reference created in the test.
+ mount_points = NULL;
+
+ // FileSystemContext should keep a reference to the |mount_points|, so it
+ // should be able to resolve the URL.
+ FileSystemURL cracked_external = file_system_context->CrackURL(
+ CreateRawFileSystemURL("external", "system"));
+
+ ExpectFileSystemURLMatches(
+ cracked_external,
+ GURL(kTestOrigin),
+ kFileSystemTypeExternal,
+ kFileSystemTypeNativeLocal,
+ base::FilePath(
+ DRIVE FPL("/test/sys/root/file")).NormalizePathSeparators(),
+ base::FilePath(FPL("system/root/file")).NormalizePathSeparators(),
+ "system");
+
+ // No need to revoke the registered filesystem since |mount_points| lifetime
+ // is bound to this test.
+}
+
+TEST_F(FileSystemContextTest, CrackFileSystemURL) {
+ scoped_refptr<ExternalMountPoints> external_mount_points(
+ ExternalMountPoints::CreateRefCounted());
+ scoped_refptr<FileSystemContext> file_system_context(
+ CreateFileSystemContextForTest(external_mount_points.get()));
+
+ // Register an isolated mount point.
+ std::string isolated_file_system_name = "root";
+ const std::string kIsolatedFileSystemID =
+ IsolatedContext::GetInstance()->RegisterFileSystemForPath(
+ kFileSystemTypeNativeLocal,
+ base::FilePath(DRIVE FPL("/test/isolated/root")),
+ &isolated_file_system_name);
+ // Register system external mount point.
+ ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+ "system",
+ kFileSystemTypeDrive,
+ FileSystemMountOption(),
+ base::FilePath(DRIVE FPL("/test/sys/"))));
+ ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+ "ext",
+ kFileSystemTypeNativeLocal,
+ FileSystemMountOption(),
+ base::FilePath(DRIVE FPL("/test/ext"))));
+ // Register a system external mount point with the same name/id as the
+ // registered isolated mount point.
+ ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+ kIsolatedFileSystemID,
+ kFileSystemTypeRestrictedNativeLocal,
+ FileSystemMountOption(),
+ base::FilePath(DRIVE FPL("/test/system/isolated"))));
+ // Add a mount points with the same name as a system mount point to
+ // FileSystemContext's external mount points.
+ ASSERT_TRUE(external_mount_points->RegisterFileSystem(
+ "ext",
+ kFileSystemTypeNativeLocal,
+ FileSystemMountOption(),
+ base::FilePath(DRIVE FPL("/test/local/ext/"))));
+
+ const GURL kTestOrigin = GURL("http://chromium.org/");
+ const base::FilePath kVirtualPathNoRoot = base::FilePath(FPL("root/file"));
+
+ struct TestCase {
+ // Test case values.
+ std::string root;
+ std::string type_str;
+
+ // Expected test results.
+ bool expect_is_valid;
+ FileSystemType expect_mount_type;
+ FileSystemType expect_type;
+ const base::FilePath::CharType* expect_path;
+ std::string expect_filesystem_id;
+ };
+
+ const TestCase kTestCases[] = {
+ // Following should not be handled by the url crackers:
+ {
+ "pers_mount", "persistent", true /* is_valid */,
+ kFileSystemTypePersistent, kFileSystemTypePersistent,
+ FPL("pers_mount/root/file"),
+ std::string() /* filesystem id */
+ },
+ {
+ "temp_mount", "temporary", true /* is_valid */,
+ kFileSystemTypeTemporary, kFileSystemTypeTemporary,
+ FPL("temp_mount/root/file"),
+ std::string() /* filesystem id */
+ },
+ // Should be cracked by isolated mount points:
+ {
+ kIsolatedFileSystemID, "isolated", true /* is_valid */,
+ kFileSystemTypeIsolated, kFileSystemTypeNativeLocal,
+ DRIVE FPL("/test/isolated/root/file"),
+ kIsolatedFileSystemID
+ },
+ // Should be cracked by system mount points:
+ {
+ "system", "external", true /* is_valid */,
+ kFileSystemTypeExternal, kFileSystemTypeDrive,
+ DRIVE FPL("/test/sys/root/file"),
+ "system"
+ },
+ {
+ kIsolatedFileSystemID, "external", true /* is_valid */,
+ kFileSystemTypeExternal, kFileSystemTypeRestrictedNativeLocal,
+ DRIVE FPL("/test/system/isolated/root/file"),
+ kIsolatedFileSystemID
+ },
+ // Should be cracked by FileSystemContext's ExternalMountPoints.
+ {
+ "ext", "external", true /* is_valid */,
+ kFileSystemTypeExternal, kFileSystemTypeNativeLocal,
+ DRIVE FPL("/test/local/ext/root/file"),
+ "ext"
+ },
+ // Test for invalid filesystem url (made invalid by adding invalid
+ // filesystem type).
+ {
+ "sytem", "external", false /* is_valid */,
+ // The rest of values will be ignored.
+ kFileSystemTypeUnknown, kFileSystemTypeUnknown, FPL(""),
+ std::string()
+ },
+ // Test for URL with non-existing filesystem id.
+ {
+ "invalid", "external", false /* is_valid */,
+ // The rest of values will be ignored.
+ kFileSystemTypeUnknown, kFileSystemTypeUnknown, FPL(""),
+ std::string()
+ },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ const base::FilePath virtual_path =
+ base::FilePath::FromUTF8Unsafe(
+ kTestCases[i].root).Append(kVirtualPathNoRoot);
+
+ GURL raw_url =
+ CreateRawFileSystemURL(kTestCases[i].type_str, kTestCases[i].root);
+ FileSystemURL cracked_url = file_system_context->CrackURL(raw_url);
+
+ SCOPED_TRACE(testing::Message() << "Test case " << i << ": "
+ << "Cracking URL: " << raw_url);
+
+ EXPECT_EQ(kTestCases[i].expect_is_valid, cracked_url.is_valid());
+ if (!kTestCases[i].expect_is_valid)
+ continue;
+
+ ExpectFileSystemURLMatches(
+ cracked_url,
+ GURL(kTestOrigin),
+ kTestCases[i].expect_mount_type,
+ kTestCases[i].expect_type,
+ base::FilePath(kTestCases[i].expect_path).NormalizePathSeparators(),
+ virtual_path.NormalizePathSeparators(),
+ kTestCases[i].expect_filesystem_id);
+ }
+
+ IsolatedContext::GetInstance()->RevokeFileSystemByPath(
+ base::FilePath(DRIVE FPL("/test/isolated/root")));
+ ExternalMountPoints::GetSystemInstance()->RevokeFileSystem("system");
+ ExternalMountPoints::GetSystemInstance()->RevokeFileSystem("ext");
+ ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ kIsolatedFileSystemID);
+}
+
+TEST_F(FileSystemContextTest, CanServeURLRequest) {
+ scoped_refptr<ExternalMountPoints> external_mount_points(
+ ExternalMountPoints::CreateRefCounted());
+ scoped_refptr<FileSystemContext> context(
+ CreateFileSystemContextForTest(external_mount_points.get()));
+
+ // A request for a sandbox mount point should be served.
+ FileSystemURL cracked_url =
+ context->CrackURL(CreateRawFileSystemURL("persistent", "pers_mount"));
+ EXPECT_EQ(kFileSystemTypePersistent, cracked_url.mount_type());
+ EXPECT_TRUE(context->CanServeURLRequest(cracked_url));
+
+ // A request for an isolated mount point should NOT be served.
+ std::string isolated_fs_name = "root";
+ std::string isolated_fs_id =
+ IsolatedContext::GetInstance()->RegisterFileSystemForPath(
+ kFileSystemTypeNativeLocal,
+ base::FilePath(DRIVE FPL("/test/isolated/root")),
+ &isolated_fs_name);
+ cracked_url = context->CrackURL(
+ CreateRawFileSystemURL("isolated", isolated_fs_id));
+ EXPECT_EQ(kFileSystemTypeIsolated, cracked_url.mount_type());
+ EXPECT_FALSE(context->CanServeURLRequest(cracked_url));
+
+ // A request for an external mount point should be served.
+ const std::string kExternalMountName = "ext_mount";
+ ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+ kExternalMountName, kFileSystemTypeDrive, FileSystemMountOption(),
+ base::FilePath()));
+ cracked_url = context->CrackURL(
+ CreateRawFileSystemURL("external", kExternalMountName));
+ EXPECT_EQ(kFileSystemTypeExternal, cracked_url.mount_type());
+ EXPECT_TRUE(context->CanServeURLRequest(cracked_url));
+
+ ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ kExternalMountName);
+ IsolatedContext::GetInstance()->RevokeFileSystem(isolated_fs_id);
+}
+
+} // namespace
+
+} // namespace fileapi
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
new file mode 100644
index 00000000000..874e61b0203
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc
@@ -0,0 +1,321 @@
+// 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 "webkit/browser/fileapi/file_system_dir_url_request_job.h"
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/format_macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/platform_file.h"
+#include "base/run_loop.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/test/test_file_system_context.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_request_headers.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/icu/source/i18n/unicode/regex.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_file_util.h"
+#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/browser/quota/mock_special_storage_policy.h"
+
+namespace fileapi {
+namespace {
+
+// We always use the TEMPORARY FileSystem in this test.
+static const char kFileSystemURLPrefix[] =
+ "filesystem:http://remote/temporary/";
+
+} // namespace
+
+class FileSystemDirURLRequestJobTest : public testing::Test {
+ protected:
+ FileSystemDirURLRequestJobTest()
+ : weak_factory_(this) {
+ }
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ special_storage_policy_ = new quota::MockSpecialStoragePolicy;
+ file_system_context_ = CreateFileSystemContextForTesting(
+ NULL, temp_dir_.path());
+
+ file_system_context_->OpenFileSystem(
+ GURL("http://remote/"), kFileSystemTypeTemporary,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&FileSystemDirURLRequestJobTest::OnOpenFileSystem,
+ weak_factory_.GetWeakPtr()));
+ base::RunLoop().RunUntilIdle();
+
+ net::URLRequest::Deprecated::RegisterProtocolFactory(
+ "filesystem", &FileSystemDirURLRequestJobFactory);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ // NOTE: order matters, request must die before delegate
+ request_.reset(NULL);
+ delegate_.reset(NULL);
+
+ net::URLRequest::Deprecated::RegisterProtocolFactory("filesystem", NULL);
+ ClearUnusedJob();
+ }
+
+ void OnOpenFileSystem(const GURL& root_url,
+ const std::string& name,
+ base::PlatformFileError result) {
+ ASSERT_EQ(base::PLATFORM_FILE_OK, result);
+ }
+
+ void TestRequestHelper(const GURL& url, bool run_to_completion,
+ FileSystemContext* file_system_context) {
+ delegate_.reset(new net::TestDelegate());
+ delegate_->set_quit_on_redirect(true);
+ request_ = empty_context_.CreateRequest(
+ url, net::DEFAULT_PRIORITY, delegate_.get());
+ job_ = new FileSystemDirURLRequestJob(
+ request_.get(), NULL, file_system_context);
+
+ request_->Start();
+ ASSERT_TRUE(request_->is_pending()); // verify that we're starting async
+ if (run_to_completion)
+ base::MessageLoop::current()->Run();
+ }
+
+ void TestRequest(const GURL& url) {
+ TestRequestHelper(url, true, file_system_context_.get());
+ }
+
+ void TestRequestWithContext(const GURL& url,
+ FileSystemContext* file_system_context) {
+ TestRequestHelper(url, true, file_system_context);
+ }
+
+ void TestRequestNoRun(const GURL& url) {
+ TestRequestHelper(url, false, file_system_context_.get());
+ }
+
+ FileSystemURL CreateURL(const base::FilePath& file_path) {
+ return file_system_context_->CreateCrackedFileSystemURL(
+ GURL("http://remote"),
+ fileapi::kFileSystemTypeTemporary,
+ file_path);
+ }
+
+ FileSystemOperationContext* NewOperationContext() {
+ FileSystemOperationContext* context(
+ new FileSystemOperationContext(file_system_context_.get()));
+ context->set_allowed_bytes_growth(1024);
+ return context;
+ }
+
+ void CreateDirectory(const base::StringPiece& dir_name) {
+ base::FilePath path = base::FilePath().AppendASCII(dir_name);
+ scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK, file_util()->CreateDirectory(
+ context.get(),
+ CreateURL(path),
+ false /* exclusive */,
+ false /* recursive */));
+ }
+
+ void EnsureFileExists(const base::StringPiece file_name) {
+ base::FilePath path = base::FilePath().AppendASCII(file_name);
+ scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK, file_util()->EnsureFileExists(
+ context.get(), CreateURL(path), NULL));
+ }
+
+ void TruncateFile(const base::StringPiece file_name, int64 length) {
+ base::FilePath path = base::FilePath().AppendASCII(file_name);
+ scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK, file_util()->Truncate(
+ context.get(), CreateURL(path), length));
+ }
+
+ base::PlatformFileError GetFileInfo(const base::FilePath& path,
+ base::PlatformFileInfo* file_info,
+ base::FilePath* platform_file_path) {
+ scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
+ return file_util()->GetFileInfo(context.get(),
+ CreateURL(path),
+ file_info, platform_file_path);
+ }
+
+ void VerifyListingEntry(const std::string& entry_line,
+ const std::string& name,
+ const std::string& url,
+ bool is_directory,
+ int64 size) {
+#define STR "([^\"]*)"
+ icu::UnicodeString pattern("^<script>addRow\\(\"" STR "\",\"" STR
+ "\",(0|1),\"" STR "\",\"" STR "\"\\);</script>");
+#undef STR
+ icu::UnicodeString input(entry_line.c_str());
+
+ UErrorCode status = U_ZERO_ERROR;
+ icu::RegexMatcher match(pattern, input, 0, status);
+
+ EXPECT_TRUE(match.find());
+ EXPECT_EQ(5, match.groupCount());
+ EXPECT_EQ(icu::UnicodeString(name.c_str()), match.group(1, status));
+ EXPECT_EQ(icu::UnicodeString(url.c_str()), match.group(2, status));
+ EXPECT_EQ(icu::UnicodeString(is_directory ? "1" : "0"),
+ match.group(3, status));
+ icu::UnicodeString size_string(FormatBytesUnlocalized(size).c_str());
+ EXPECT_EQ(size_string, match.group(4, status));
+
+ base::Time date;
+ icu::UnicodeString date_ustr(match.group(5, status));
+ std::string date_str;
+ UTF16ToUTF8(date_ustr.getBuffer(), date_ustr.length(), &date_str);
+ EXPECT_TRUE(base::Time::FromString(date_str.c_str(), &date));
+ EXPECT_FALSE(date.is_null());
+ }
+
+ GURL CreateFileSystemURL(const std::string path) {
+ return GURL(kFileSystemURLPrefix + path);
+ }
+
+ static net::URLRequestJob* FileSystemDirURLRequestJobFactory(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const std::string& scheme) {
+ DCHECK(job_);
+ net::URLRequestJob* temp = job_;
+ job_ = NULL;
+ return temp;
+ }
+
+ static void ClearUnusedJob() {
+ if (job_) {
+ scoped_refptr<net::URLRequestJob> deleter = job_;
+ job_ = NULL;
+ }
+ }
+
+ FileSystemFileUtil* file_util() {
+ return file_system_context_->sandbox_delegate()->sync_file_util();
+ }
+
+ // Put the message loop at the top, so that it's the last thing deleted.
+ // Delete all MessageLoopProxy objects before the MessageLoop, to help prevent
+ // leaks caused by tasks posted during shutdown.
+ base::MessageLoopForIO message_loop_;
+
+ base::ScopedTempDir temp_dir_;
+ net::URLRequestContext empty_context_;
+ scoped_ptr<net::TestDelegate> delegate_;
+ scoped_ptr<net::URLRequest> request_;
+ scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ base::WeakPtrFactory<FileSystemDirURLRequestJobTest> weak_factory_;
+
+ static net::URLRequestJob* job_;
+};
+
+// static
+net::URLRequestJob* FileSystemDirURLRequestJobTest::job_ = NULL;
+
+namespace {
+
+TEST_F(FileSystemDirURLRequestJobTest, DirectoryListing) {
+ CreateDirectory("foo");
+ CreateDirectory("foo/bar");
+ CreateDirectory("foo/bar/baz");
+
+ EnsureFileExists("foo/bar/hoge");
+ TruncateFile("foo/bar/hoge", 10);
+
+ TestRequest(CreateFileSystemURL("foo/bar/"));
+
+ ASSERT_FALSE(request_->is_pending());
+ EXPECT_EQ(1, delegate_->response_started_count());
+ EXPECT_FALSE(delegate_->received_data_before_response());
+ EXPECT_GT(delegate_->bytes_received(), 0);
+
+ std::istringstream in(delegate_->data_received());
+ std::string line;
+ EXPECT_TRUE(std::getline(in, line));
+
+#if defined(OS_WIN)
+ EXPECT_EQ("<script>start(\"foo\\\\bar\");</script>", line);
+#elif defined(OS_POSIX)
+ EXPECT_EQ("<script>start(\"/foo/bar\");</script>", line);
+#endif
+
+ EXPECT_TRUE(std::getline(in, line));
+ VerifyListingEntry(line, "hoge", "hoge", false, 10);
+
+ EXPECT_TRUE(std::getline(in, line));
+ VerifyListingEntry(line, "baz", "baz", true, 0);
+}
+
+TEST_F(FileSystemDirURLRequestJobTest, InvalidURL) {
+ TestRequest(GURL("filesystem:/foo/bar/baz"));
+ ASSERT_FALSE(request_->is_pending());
+ EXPECT_TRUE(delegate_->request_failed());
+ ASSERT_FALSE(request_->status().is_success());
+ EXPECT_EQ(net::ERR_INVALID_URL, request_->status().error());
+}
+
+TEST_F(FileSystemDirURLRequestJobTest, NoSuchRoot) {
+ TestRequest(GURL("filesystem:http://remote/persistent/somedir/"));
+ ASSERT_FALSE(request_->is_pending());
+ ASSERT_FALSE(request_->status().is_success());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
+}
+
+TEST_F(FileSystemDirURLRequestJobTest, NoSuchDirectory) {
+ TestRequest(CreateFileSystemURL("somedir/"));
+ ASSERT_FALSE(request_->is_pending());
+ ASSERT_FALSE(request_->status().is_success());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
+}
+
+TEST_F(FileSystemDirURLRequestJobTest, Cancel) {
+ CreateDirectory("foo");
+ TestRequestNoRun(CreateFileSystemURL("foo/"));
+ // Run StartAsync() and only StartAsync().
+ base::MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release());
+ base::RunLoop().RunUntilIdle();
+ // If we get here, success! we didn't crash!
+}
+
+TEST_F(FileSystemDirURLRequestJobTest, Incognito) {
+ CreateDirectory("foo");
+
+ scoped_refptr<FileSystemContext> file_system_context =
+ CreateIncognitoFileSystemContextForTesting(NULL, temp_dir_.path());
+
+ TestRequestWithContext(CreateFileSystemURL("/"),
+ file_system_context.get());
+ ASSERT_FALSE(request_->is_pending());
+ ASSERT_TRUE(request_->status().is_success());
+
+ std::istringstream in(delegate_->data_received());
+ std::string line;
+ EXPECT_TRUE(std::getline(in, line));
+ EXPECT_FALSE(std::getline(in, line));
+
+ TestRequestWithContext(CreateFileSystemURL("foo"),
+ file_system_context.get());
+ ASSERT_FALSE(request_->is_pending());
+ ASSERT_FALSE(request_->status().is_success());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
+}
+
+} // namespace (anonymous)
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/file_system_file_stream_reader_unittest.cc b/chromium/content/browser/fileapi/file_system_file_stream_reader_unittest.cc
new file mode 100644
index 00000000000..3540d5b8c05
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_file_stream_reader_unittest.cc
@@ -0,0 +1,266 @@
+// 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 "webkit/browser/fileapi/file_system_file_stream_reader.h"
+
+#include <limits>
+#include <string>
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/platform_file.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_file_system_context.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_file_util.h"
+
+namespace fileapi {
+
+namespace {
+
+const char kURLOrigin[] = "http://remote/";
+const char kTestFileName[] = "test.dat";
+const char kTestData[] = "0123456789";
+const int kTestDataSize = arraysize(kTestData) - 1;
+
+void ReadFromReader(FileSystemFileStreamReader* reader,
+ std::string* data,
+ size_t size,
+ int* result) {
+ ASSERT_TRUE(reader != NULL);
+ ASSERT_TRUE(result != NULL);
+ *result = net::OK;
+ net::TestCompletionCallback callback;
+ size_t total_bytes_read = 0;
+ while (total_bytes_read < size) {
+ scoped_refptr<net::IOBufferWithSize> buf(
+ new net::IOBufferWithSize(size - total_bytes_read));
+ int rv = reader->Read(buf.get(), buf->size(), callback.callback());
+ if (rv == net::ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ if (rv < 0)
+ *result = rv;
+ if (rv <= 0)
+ break;
+ total_bytes_read += rv;
+ data->append(buf->data(), rv);
+ }
+}
+
+void NeverCalled(int unused) { ADD_FAILURE(); }
+
+} // namespace
+
+class FileSystemFileStreamReaderTest : public testing::Test {
+ public:
+ FileSystemFileStreamReaderTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ file_system_context_ = CreateFileSystemContextForTesting(
+ NULL, temp_dir_.path());
+
+ file_system_context_->OpenFileSystem(
+ GURL(kURLOrigin), kFileSystemTypeTemporary,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&OnOpenFileSystem));
+ base::RunLoop().RunUntilIdle();
+
+ WriteFile(kTestFileName, kTestData, kTestDataSize,
+ &test_file_modification_time_);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ base::RunLoop().RunUntilIdle();
+ }
+
+ protected:
+ FileSystemFileStreamReader* CreateFileReader(
+ const std::string& file_name,
+ int64 initial_offset,
+ const base::Time& expected_modification_time) {
+ return new FileSystemFileStreamReader(file_system_context_.get(),
+ GetFileSystemURL(file_name),
+ initial_offset,
+ expected_modification_time);
+ }
+
+ base::Time test_file_modification_time() const {
+ return test_file_modification_time_;
+ }
+
+ void WriteFile(const std::string& file_name,
+ const char* buf,
+ int buf_size,
+ base::Time* modification_time) {
+ FileSystemURL url = GetFileSystemURL(file_name);
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ fileapi::AsyncFileTestHelper::CreateFileWithData(
+ file_system_context_, url, buf, buf_size));
+
+ base::PlatformFileInfo file_info;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::GetMetadata(
+ file_system_context_, url, &file_info));
+ if (modification_time)
+ *modification_time = file_info.last_modified;
+ }
+
+ private:
+ static void OnOpenFileSystem(const GURL& root_url,
+ const std::string& name,
+ base::PlatformFileError result) {
+ ASSERT_EQ(base::PLATFORM_FILE_OK, result);
+ }
+
+ FileSystemURL GetFileSystemURL(const std::string& file_name) {
+ return file_system_context_->CreateCrackedFileSystemURL(
+ GURL(kURLOrigin),
+ kFileSystemTypeTemporary,
+ base::FilePath().AppendASCII(file_name));
+ }
+
+ base::MessageLoopForIO message_loop_;
+ base::ScopedTempDir temp_dir_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ base::Time test_file_modification_time_;
+};
+
+TEST_F(FileSystemFileStreamReaderTest, NonExistent) {
+ const char kFileName[] = "nonexistent";
+ scoped_ptr<FileSystemFileStreamReader> reader(
+ CreateFileReader(kFileName, 0, base::Time()));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, 10, &result);
+ ASSERT_EQ(net::ERR_FILE_NOT_FOUND, result);
+ ASSERT_EQ(0U, data.size());
+}
+
+TEST_F(FileSystemFileStreamReaderTest, Empty) {
+ const char kFileName[] = "empty";
+ WriteFile(kFileName, NULL, 0, NULL);
+
+ scoped_ptr<FileSystemFileStreamReader> reader(
+ CreateFileReader(kFileName, 0, base::Time()));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, 10, &result);
+ ASSERT_EQ(net::OK, result);
+ ASSERT_EQ(0U, data.size());
+
+ net::TestInt64CompletionCallback callback;
+ int64 length_result = reader->GetLength(callback.callback());
+ if (length_result == net::ERR_IO_PENDING)
+ length_result = callback.WaitForResult();
+ ASSERT_EQ(0, length_result);
+}
+
+TEST_F(FileSystemFileStreamReaderTest, GetLengthNormal) {
+ scoped_ptr<FileSystemFileStreamReader> reader(
+ CreateFileReader(kTestFileName, 0, test_file_modification_time()));
+ net::TestInt64CompletionCallback callback;
+ int64 result = reader->GetLength(callback.callback());
+ if (result == net::ERR_IO_PENDING)
+ result = callback.WaitForResult();
+ ASSERT_EQ(kTestDataSize, result);
+}
+
+TEST_F(FileSystemFileStreamReaderTest, GetLengthAfterModified) {
+ // Pass a fake expected modifictaion time so that the expectation fails.
+ base::Time fake_expected_modification_time =
+ test_file_modification_time() - base::TimeDelta::FromSeconds(10);
+
+ scoped_ptr<FileSystemFileStreamReader> reader(
+ CreateFileReader(kTestFileName, 0, fake_expected_modification_time));
+ net::TestInt64CompletionCallback callback;
+ int64 result = reader->GetLength(callback.callback());
+ if (result == net::ERR_IO_PENDING)
+ result = callback.WaitForResult();
+ ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
+
+ // With NULL expected modification time this should work.
+ reader.reset(CreateFileReader(kTestFileName, 0, base::Time()));
+ result = reader->GetLength(callback.callback());
+ if (result == net::ERR_IO_PENDING)
+ result = callback.WaitForResult();
+ ASSERT_EQ(kTestDataSize, result);
+}
+
+TEST_F(FileSystemFileStreamReaderTest, GetLengthWithOffset) {
+ scoped_ptr<FileSystemFileStreamReader> reader(
+ CreateFileReader(kTestFileName, 3, base::Time()));
+ net::TestInt64CompletionCallback callback;
+ int64 result = reader->GetLength(callback.callback());
+ if (result == net::ERR_IO_PENDING)
+ result = callback.WaitForResult();
+ // Initial offset does not affect the result of GetLength.
+ ASSERT_EQ(kTestDataSize, result);
+}
+
+TEST_F(FileSystemFileStreamReaderTest, ReadNormal) {
+ scoped_ptr<FileSystemFileStreamReader> reader(
+ CreateFileReader(kTestFileName, 0, test_file_modification_time()));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, kTestDataSize, &result);
+ ASSERT_EQ(net::OK, result);
+ ASSERT_EQ(kTestData, data);
+}
+
+TEST_F(FileSystemFileStreamReaderTest, ReadAfterModified) {
+ // Pass a fake expected modifictaion time so that the expectation fails.
+ base::Time fake_expected_modification_time =
+ test_file_modification_time() - base::TimeDelta::FromSeconds(10);
+
+ scoped_ptr<FileSystemFileStreamReader> reader(
+ CreateFileReader(kTestFileName, 0, fake_expected_modification_time));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, kTestDataSize, &result);
+ ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
+ ASSERT_EQ(0U, data.size());
+
+ // With NULL expected modification time this should work.
+ data.clear();
+ reader.reset(CreateFileReader(kTestFileName, 0, base::Time()));
+ ReadFromReader(reader.get(), &data, kTestDataSize, &result);
+ ASSERT_EQ(net::OK, result);
+ ASSERT_EQ(kTestData, data);
+}
+
+TEST_F(FileSystemFileStreamReaderTest, ReadWithOffset) {
+ scoped_ptr<FileSystemFileStreamReader> reader(
+ CreateFileReader(kTestFileName, 3, base::Time()));
+ int result = 0;
+ std::string data;
+ ReadFromReader(reader.get(), &data, kTestDataSize, &result);
+ ASSERT_EQ(net::OK, result);
+ ASSERT_EQ(&kTestData[3], data);
+}
+
+TEST_F(FileSystemFileStreamReaderTest, DeleteWithUnfinishedRead) {
+ scoped_ptr<FileSystemFileStreamReader> reader(
+ CreateFileReader(kTestFileName, 0, base::Time()));
+
+ net::TestCompletionCallback callback;
+ scoped_refptr<net::IOBufferWithSize> buf(
+ new net::IOBufferWithSize(kTestDataSize));
+ int rv = reader->Read(buf.get(), buf->size(), base::Bind(&NeverCalled));
+ ASSERT_TRUE(rv == net::ERR_IO_PENDING || rv >= 0);
+
+ // Delete immediately.
+ // Should not crash; nor should NeverCalled be callback.
+ reader.reset();
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/file_system_operation_impl_unittest.cc b/chromium/content/browser/fileapi/file_system_operation_impl_unittest.cc
new file mode 100644
index 00000000000..445657d9a01
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_operation_impl_unittest.cc
@@ -0,0 +1,1241 @@
+// 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 "webkit/browser/fileapi/file_system_operation_impl.h"
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "content/public/test/sandbox_file_system_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_file_util.h"
+#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/file_system_operation_runner.h"
+#include "webkit/browser/fileapi/mock_file_change_observer.h"
+#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
+#include "webkit/browser/quota/mock_quota_manager.h"
+#include "webkit/browser/quota/quota_manager.h"
+#include "webkit/common/blob/shareable_file_reference.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+using quota::QuotaManager;
+using quota::QuotaManagerProxy;
+using webkit_blob::ShareableFileReference;
+
+namespace fileapi {
+
+namespace {
+
+const int kFileOperationStatusNotSet = 1;
+
+void AssertFileErrorEq(const tracked_objects::Location& from_here,
+ base::PlatformFileError expected,
+ base::PlatformFileError actual) {
+ ASSERT_EQ(expected, actual) << from_here.ToString();
+}
+
+} // namespace (anonymous)
+
+// Test class for FileSystemOperationImpl.
+class FileSystemOperationImplTest
+ : public testing::Test {
+ public:
+ FileSystemOperationImplTest()
+ : status_(kFileOperationStatusNotSet),
+ weak_factory_(this) {}
+
+ protected:
+ virtual void SetUp() OVERRIDE {
+ EXPECT_TRUE(base_.CreateUniqueTempDir());
+ change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
+
+ base::FilePath base_dir = base_.path().AppendASCII("filesystem");
+ quota_manager_ =
+ new quota::MockQuotaManager(false /* is_incognito */,
+ base_dir,
+ base::MessageLoopProxy::current().get(),
+ base::MessageLoopProxy::current().get(),
+ NULL /* special storage policy */);
+ quota_manager_proxy_ = new quota::MockQuotaManagerProxy(
+ quota_manager(), base::MessageLoopProxy::current().get());
+ sandbox_file_system_.SetUp(base_dir, quota_manager_proxy_.get());
+ sandbox_file_system_.AddFileChangeObserver(&change_observer_);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ // Let the client go away before dropping a ref of the quota manager proxy.
+ quota_manager_proxy()->SimulateQuotaManagerDestroyed();
+ quota_manager_ = NULL;
+ quota_manager_proxy_ = NULL;
+ sandbox_file_system_.TearDown();
+ }
+
+ FileSystemOperationRunner* operation_runner() {
+ return sandbox_file_system_.operation_runner();
+ }
+
+ int status() const { return status_; }
+ const base::PlatformFileInfo& info() const { return info_; }
+ const base::FilePath& path() const { return path_; }
+ const std::vector<DirectoryEntry>& entries() const {
+ return entries_;
+ }
+
+ const ShareableFileReference* shareable_file_ref() const {
+ return shareable_file_ref_.get();
+ }
+
+ quota::MockQuotaManager* quota_manager() {
+ return static_cast<quota::MockQuotaManager*>(quota_manager_.get());
+ }
+
+ quota::MockQuotaManagerProxy* quota_manager_proxy() {
+ return static_cast<quota::MockQuotaManagerProxy*>(
+ quota_manager_proxy_.get());
+ }
+
+ FileSystemFileUtil* file_util() {
+ return sandbox_file_system_.file_util();
+ }
+
+ MockFileChangeObserver* change_observer() {
+ return &change_observer_;
+ }
+
+ scoped_ptr<FileSystemOperationContext> NewContext() {
+ FileSystemOperationContext* context =
+ sandbox_file_system_.NewOperationContext();
+ // Grant enough quota for all test cases.
+ context->set_allowed_bytes_growth(1000000);
+ return make_scoped_ptr(context);
+ }
+
+ FileSystemURL URLForPath(const std::string& path) const {
+ return sandbox_file_system_.CreateURLFromUTF8(path);
+ }
+
+ base::FilePath PlatformPath(const std::string& path) {
+ return sandbox_file_system_.GetLocalPath(
+ base::FilePath::FromUTF8Unsafe(path));
+ }
+
+ bool FileExists(const std::string& path) {
+ return AsyncFileTestHelper::FileExists(
+ sandbox_file_system_.file_system_context(), URLForPath(path),
+ AsyncFileTestHelper::kDontCheckSize);
+ }
+
+ bool DirectoryExists(const std::string& path) {
+ return AsyncFileTestHelper::DirectoryExists(
+ sandbox_file_system_.file_system_context(), URLForPath(path));
+ }
+
+ FileSystemURL CreateFile(const std::string& path) {
+ FileSystemURL url = URLForPath(path);
+ bool created = false;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->EnsureFileExists(NewContext().get(),
+ url, &created));
+ EXPECT_TRUE(created);
+ return url;
+ }
+
+ FileSystemURL CreateDirectory(const std::string& path) {
+ FileSystemURL url = URLForPath(path);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->CreateDirectory(NewContext().get(), url,
+ false /* exclusive */, true));
+ return url;
+ }
+
+ int64 GetFileSize(const std::string& path) {
+ base::PlatformFileInfo info;
+ EXPECT_TRUE(base::GetFileInfo(PlatformPath(path), &info));
+ return info.size;
+ }
+
+ // Callbacks for recording test results.
+ FileSystemOperation::StatusCallback RecordStatusCallback() {
+ return base::Bind(&FileSystemOperationImplTest::DidFinish,
+ weak_factory_.GetWeakPtr());
+ }
+
+ FileSystemOperation::ReadDirectoryCallback
+ RecordReadDirectoryCallback() {
+ return base::Bind(&FileSystemOperationImplTest::DidReadDirectory,
+ weak_factory_.GetWeakPtr());
+ }
+
+ FileSystemOperation::GetMetadataCallback RecordMetadataCallback() {
+ return base::Bind(&FileSystemOperationImplTest::DidGetMetadata,
+ weak_factory_.GetWeakPtr());
+ }
+
+ FileSystemOperation::SnapshotFileCallback RecordSnapshotFileCallback() {
+ return base::Bind(&FileSystemOperationImplTest::DidCreateSnapshotFile,
+ weak_factory_.GetWeakPtr());
+ }
+
+ void DidFinish(base::PlatformFileError status) {
+ status_ = status;
+ }
+
+ void DidReadDirectory(
+ base::PlatformFileError status,
+ const std::vector<DirectoryEntry>& entries,
+ bool /* has_more */) {
+ entries_ = entries;
+ status_ = status;
+ }
+
+ void DidGetMetadata(base::PlatformFileError status,
+ const base::PlatformFileInfo& info) {
+ info_ = info;
+ status_ = status;
+ }
+
+ void DidCreateSnapshotFile(
+ base::PlatformFileError status,
+ const base::PlatformFileInfo& info,
+ const base::FilePath& platform_path,
+ const scoped_refptr<ShareableFileReference>& shareable_file_ref) {
+ info_ = info;
+ path_ = platform_path;
+ status_ = status;
+ shareable_file_ref_ = shareable_file_ref;
+ }
+
+ int64 GetDataSizeOnDisk() {
+ return sandbox_file_system_.ComputeCurrentOriginUsage() -
+ sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
+ }
+
+ void GetUsageAndQuota(int64* usage, int64* quota) {
+ quota::QuotaStatusCode status =
+ AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(),
+ sandbox_file_system_.origin(),
+ sandbox_file_system_.type(),
+ usage,
+ quota);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(quota::kQuotaStatusOk, status);
+ }
+
+ int64 ComputePathCost(const FileSystemURL& url) {
+ int64 base_usage;
+ GetUsageAndQuota(&base_usage, NULL);
+
+ AsyncFileTestHelper::CreateFile(
+ sandbox_file_system_.file_system_context(), url);
+ operation_runner()->Remove(url, false /* recursive */,
+ base::Bind(&AssertFileErrorEq, FROM_HERE,
+ base::PLATFORM_FILE_OK));
+ base::RunLoop().RunUntilIdle();
+ change_observer()->ResetCount();
+
+ int64 total_usage;
+ GetUsageAndQuota(&total_usage, NULL);
+ return total_usage - base_usage;
+ }
+
+ void GrantQuotaForCurrentUsage() {
+ int64 usage;
+ GetUsageAndQuota(&usage, NULL);
+ quota_manager()->SetQuota(sandbox_file_system_.origin(),
+ sandbox_file_system_.storage_type(),
+ usage);
+ }
+
+ int64 GetUsage() {
+ int64 usage = 0;
+ GetUsageAndQuota(&usage, NULL);
+ return usage;
+ }
+
+ void AddQuota(int64 quota_delta) {
+ int64 quota;
+ GetUsageAndQuota(NULL, &quota);
+ quota_manager()->SetQuota(sandbox_file_system_.origin(),
+ sandbox_file_system_.storage_type(),
+ quota + quota_delta);
+ }
+
+ base::MessageLoop message_loop_;
+ scoped_refptr<QuotaManager> quota_manager_;
+ scoped_refptr<QuotaManagerProxy> quota_manager_proxy_;
+
+ // Common temp base for nondestructive uses.
+ base::ScopedTempDir base_;
+
+ SandboxFileSystemTestHelper sandbox_file_system_;
+
+ // For post-operation status.
+ int status_;
+ base::PlatformFileInfo info_;
+ base::FilePath path_;
+ std::vector<DirectoryEntry> entries_;
+ scoped_refptr<ShareableFileReference> shareable_file_ref_;
+
+ MockFileChangeObserver change_observer_;
+ ChangeObserverList change_observers_;
+
+ base::WeakPtrFactory<FileSystemOperationImplTest> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplTest);
+};
+
+TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDoesntExist) {
+ change_observer()->ResetCount();
+ operation_runner()->Move(URLForPath("a"), URLForPath("b"),
+ FileSystemOperation::OPTION_NONE,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestMoveFailureContainsPath) {
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL dest_dir(CreateDirectory("src/dest"));
+
+ operation_runner()->Move(src_dir, dest_dir,
+ FileSystemOperation::OPTION_NONE,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDirExistsDestFile) {
+ // Src exists and is dir. Dest is a file.
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+ FileSystemURL dest_file(CreateFile("dest/file"));
+
+ operation_runner()->Move(src_dir, dest_file,
+ FileSystemOperation::OPTION_NONE,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest,
+ TestMoveFailureSrcFileExistsDestNonEmptyDir) {
+ // Src exists and is a directory. Dest is a non-empty directory.
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+ FileSystemURL dest_file(CreateFile("dest/file"));
+
+ operation_runner()->Move(src_dir, dest_dir,
+ FileSystemOperation::OPTION_NONE,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcFileExistsDestDir) {
+ // Src exists and is a file. Dest is a directory.
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL src_file(CreateFile("src/file"));
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+
+ operation_runner()->Move(src_file, dest_dir,
+ FileSystemOperation::OPTION_NONE,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestMoveFailureDestParentDoesntExist) {
+ // Dest. parent path does not exist.
+ FileSystemURL src_dir(CreateDirectory("src"));
+ operation_runner()->Move(src_dir, URLForPath("nonexistent/deset"),
+ FileSystemOperation::OPTION_NONE,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndOverwrite) {
+ FileSystemURL src_file(CreateFile("src"));
+ FileSystemURL dest_file(CreateFile("dest"));
+
+ operation_runner()->Move(src_file, dest_file,
+ FileSystemOperation::OPTION_NONE,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(FileExists("dest"));
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
+}
+
+TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndNew) {
+ FileSystemURL src_file(CreateFile("src"));
+
+ operation_runner()->Move(src_file, URLForPath("new"),
+ FileSystemOperation::OPTION_NONE,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(FileExists("new"));
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndOverwrite) {
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+
+ operation_runner()->Move(src_dir, dest_dir,
+ FileSystemOperation::OPTION_NONE,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_FALSE(DirectoryExists("src"));
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
+ EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ // Make sure we've overwritten but not moved the source under the |dest_dir|.
+ EXPECT_TRUE(DirectoryExists("dest"));
+ EXPECT_FALSE(DirectoryExists("dest/src"));
+}
+
+TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndNew) {
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+
+ operation_runner()->Move(src_dir, URLForPath("dest/new"),
+ FileSystemOperation::OPTION_NONE,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_FALSE(DirectoryExists("src"));
+ EXPECT_TRUE(DirectoryExists("dest/new"));
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirRecursive) {
+ FileSystemURL src_dir(CreateDirectory("src"));
+ CreateDirectory("src/dir");
+ CreateFile("src/dir/sub");
+
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+
+ operation_runner()->Move(src_dir, dest_dir,
+ FileSystemOperation::OPTION_NONE,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(DirectoryExists("dest/dir"));
+ EXPECT_TRUE(FileExists("dest/dir/sub"));
+
+ EXPECT_EQ(3, change_observer()->get_and_reset_remove_directory_count());
+ EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDoesntExist) {
+ operation_runner()->Copy(URLForPath("a"), URLForPath("b"),
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopyFailureContainsPath) {
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL dest_dir(CreateDirectory("src/dir"));
+
+ operation_runner()->Copy(src_dir, dest_dir,
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDirExistsDestFile) {
+ // Src exists and is dir. Dest is a file.
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+ FileSystemURL dest_file(CreateFile("dest/file"));
+
+ operation_runner()->Copy(src_dir, dest_file,
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest,
+ TestCopyFailureSrcFileExistsDestNonEmptyDir) {
+ // Src exists and is a directory. Dest is a non-empty directory.
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+ FileSystemURL dest_file(CreateFile("dest/file"));
+
+ operation_runner()->Copy(src_dir, dest_dir,
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcFileExistsDestDir) {
+ // Src exists and is a file. Dest is a directory.
+ FileSystemURL src_file(CreateFile("src"));
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+
+ operation_runner()->Copy(src_file, dest_dir,
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopyFailureDestParentDoesntExist) {
+ // Dest. parent path does not exist.
+ FileSystemURL src_dir(CreateDirectory("src"));
+
+ operation_runner()->Copy(src_dir, URLForPath("nonexistent/dest"),
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopyFailureByQuota) {
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL src_file(CreateFile("src/file"));
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+ operation_runner()->Truncate(src_file, 6, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_EQ(6, GetFileSize("src/file"));
+
+ FileSystemURL dest_file(URLForPath("dest/file"));
+ int64 dest_path_cost = ComputePathCost(dest_file);
+ GrantQuotaForCurrentUsage();
+ AddQuota(6 + dest_path_cost - 1);
+
+ operation_runner()->Copy(src_file, dest_file,
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
+ EXPECT_FALSE(FileExists("dest/file"));
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndOverwrite) {
+ FileSystemURL src_file(CreateFile("src"));
+ FileSystemURL dest_file(CreateFile("dest"));
+
+ operation_runner()->Copy(src_file, dest_file,
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(FileExists("dest"));
+ EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count());
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndNew) {
+ FileSystemURL src_file(CreateFile("src"));
+
+ operation_runner()->Copy(src_file, URLForPath("new"),
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(FileExists("new"));
+ EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count());
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndOverwrite) {
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+
+ operation_runner()->Copy(src_dir, dest_dir,
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+
+ // Make sure we've overwritten but not copied the source under the |dest_dir|.
+ EXPECT_TRUE(DirectoryExists("dest"));
+ EXPECT_FALSE(DirectoryExists("dest/src"));
+ EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 3);
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndNew) {
+ FileSystemURL src_dir(CreateDirectory("src"));
+ FileSystemURL dest_dir_new(URLForPath("dest"));
+
+ operation_runner()->Copy(src_dir, dest_dir_new,
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(DirectoryExists("dest"));
+ EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 2);
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirRecursive) {
+ FileSystemURL src_dir(CreateDirectory("src"));
+ CreateDirectory("src/dir");
+ CreateFile("src/dir/sub");
+
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+
+ operation_runner()->Copy(src_dir, dest_dir,
+ FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(DirectoryExists("dest/dir"));
+ EXPECT_TRUE(FileExists("dest/dir/sub"));
+
+ // For recursive copy we may record multiple read access.
+ EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 1);
+
+ EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileSuccess) {
+ base::FilePath src_local_disk_file_path;
+ base::CreateTemporaryFile(&src_local_disk_file_path);
+ const char test_data[] = "foo";
+ int data_size = ARRAYSIZE_UNSAFE(test_data);
+ file_util::WriteFile(src_local_disk_file_path, test_data, data_size);
+
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+
+ int64 before_usage;
+ GetUsageAndQuota(&before_usage, NULL);
+
+ // Check that the file copied and corresponding usage increased.
+ operation_runner()->CopyInForeignFile(src_local_disk_file_path,
+ URLForPath("dest/file"),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1, change_observer()->create_file_count());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(FileExists("dest/file"));
+ int64 after_usage;
+ GetUsageAndQuota(&after_usage, NULL);
+ EXPECT_GT(after_usage, before_usage);
+
+ // Compare contents of src and copied file.
+ char buffer[100];
+ EXPECT_EQ(data_size, base::ReadFile(PlatformPath("dest/file"),
+ buffer, data_size));
+ for (int i = 0; i < data_size; ++i)
+ EXPECT_EQ(test_data[i], buffer[i]);
+}
+
+TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileFailureByQuota) {
+ base::FilePath src_local_disk_file_path;
+ base::CreateTemporaryFile(&src_local_disk_file_path);
+ const char test_data[] = "foo";
+ file_util::WriteFile(src_local_disk_file_path, test_data,
+ ARRAYSIZE_UNSAFE(test_data));
+
+ FileSystemURL dest_dir(CreateDirectory("dest"));
+
+ GrantQuotaForCurrentUsage();
+ operation_runner()->CopyInForeignFile(src_local_disk_file_path,
+ URLForPath("dest/file"),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(FileExists("dest/file"));
+ EXPECT_EQ(0, change_observer()->create_file_count());
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCreateFileFailure) {
+ // Already existing file and exclusive true.
+ FileSystemURL file(CreateFile("file"));
+ operation_runner()->CreateFile(file, true, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileExists) {
+ // Already existing file and exclusive false.
+ FileSystemURL file(CreateFile("file"));
+ operation_runner()->CreateFile(file, false, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(FileExists("file"));
+
+ // The file was already there; did nothing.
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessExclusive) {
+ // File doesn't exist but exclusive is true.
+ operation_runner()->CreateFile(URLForPath("new"), true,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(FileExists("new"));
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileDoesntExist) {
+ // Non existing file.
+ operation_runner()->CreateFile(URLForPath("nonexistent"), false,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
+}
+
+TEST_F(FileSystemOperationImplTest,
+ TestCreateDirFailureDestParentDoesntExist) {
+ // Dest. parent path does not exist.
+ operation_runner()->CreateDirectory(
+ URLForPath("nonexistent/dir"), false, false,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCreateDirFailureDirExists) {
+ // Exclusive and dir existing at path.
+ FileSystemURL dir(CreateDirectory("dir"));
+ operation_runner()->CreateDirectory(dir, true, false,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCreateDirFailureFileExists) {
+ // Exclusive true and file existing at path.
+ FileSystemURL file(CreateFile("file"));
+ operation_runner()->CreateDirectory(file, true, false,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCreateDirSuccess) {
+ // Dir exists and exclusive is false.
+ FileSystemURL dir(CreateDirectory("dir"));
+ operation_runner()->CreateDirectory(dir, false, false,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ // Dir doesn't exist.
+ operation_runner()->CreateDirectory(URLForPath("new"), false, false,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(DirectoryExists("new"));
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCreateDirSuccessExclusive) {
+ // Dir doesn't exist.
+ operation_runner()->CreateDirectory(URLForPath("new"), true, false,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(DirectoryExists("new"));
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataFailure) {
+ operation_runner()->GetMetadata(URLForPath("nonexistent"),
+ RecordMetadataCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
+
+ operation_runner()->FileExists(URLForPath("nonexistent"),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
+
+ operation_runner()->DirectoryExists(URLForPath("nonexistent"),
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataSuccess) {
+ FileSystemURL dir(CreateDirectory("dir"));
+ FileSystemURL file(CreateFile("dir/file"));
+ int read_access = 0;
+
+ operation_runner()->DirectoryExists(dir, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ ++read_access;
+
+ operation_runner()->GetMetadata(dir, RecordMetadataCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(info().is_directory);
+ ++read_access;
+
+ operation_runner()->FileExists(file, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ ++read_access;
+
+ operation_runner()->GetMetadata(file, RecordMetadataCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_FALSE(info().is_directory);
+ ++read_access;
+
+ EXPECT_EQ(read_access,
+ quota_manager_proxy()->notify_storage_accessed_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestTypeMismatchErrors) {
+ FileSystemURL dir(CreateDirectory("dir"));
+ operation_runner()->FileExists(dir, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE, status());
+
+ FileSystemURL file(CreateFile("file"));
+ operation_runner()->DirectoryExists(file, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, status());
+}
+
+TEST_F(FileSystemOperationImplTest, TestReadDirFailure) {
+ // Path doesn't exist
+ operation_runner()->ReadDirectory(URLForPath("nonexistent"),
+ RecordReadDirectoryCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
+
+ // File exists.
+ FileSystemURL file(CreateFile("file"));
+ operation_runner()->ReadDirectory(file, RecordReadDirectoryCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestReadDirSuccess) {
+ // parent_dir
+ // | |
+ // child_dir child_file
+ // Verify reading parent_dir.
+ FileSystemURL parent_dir(CreateDirectory("dir"));
+ FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
+ FileSystemURL child_file(CreateFile("dir/child_file"));
+
+ operation_runner()->ReadDirectory(parent_dir, RecordReadDirectoryCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_EQ(2u, entries().size());
+
+ for (size_t i = 0; i < entries().size(); ++i) {
+ if (entries()[i].is_directory)
+ EXPECT_EQ(FILE_PATH_LITERAL("child_dir"), entries()[i].name);
+ else
+ EXPECT_EQ(FILE_PATH_LITERAL("child_file"), entries()[i].name);
+ }
+ EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestRemoveFailure) {
+ // Path doesn't exist.
+ operation_runner()->Remove(URLForPath("nonexistent"), false /* recursive */,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
+
+ // It's an error to try to remove a non-empty directory if recursive flag
+ // is false.
+ // parent_dir
+ // | |
+ // child_dir child_file
+ // Verify deleting parent_dir.
+ FileSystemURL parent_dir(CreateDirectory("dir"));
+ FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
+ FileSystemURL child_file(CreateFile("dir/child_file"));
+
+ operation_runner()->Remove(parent_dir, false /* recursive */,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestRemoveSuccess) {
+ FileSystemURL empty_dir(CreateDirectory("empty_dir"));
+ EXPECT_TRUE(DirectoryExists("empty_dir"));
+ operation_runner()->Remove(empty_dir, false /* recursive */,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_FALSE(DirectoryExists("empty_dir"));
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestRemoveSuccessRecursive) {
+ // Removing a non-empty directory with recursive flag == true should be ok.
+ // parent_dir
+ // | |
+ // child_dir child_files
+ // |
+ // child_files
+ //
+ // Verify deleting parent_dir.
+ FileSystemURL parent_dir(CreateDirectory("dir"));
+ for (int i = 0; i < 8; ++i)
+ CreateFile(base::StringPrintf("dir/file-%d", i));
+ FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
+ for (int i = 0; i < 8; ++i)
+ CreateFile(base::StringPrintf("dir/child_dir/file-%d", i));
+
+ operation_runner()->Remove(parent_dir, true /* recursive */,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_FALSE(DirectoryExists("parent_dir"));
+
+ EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count());
+ EXPECT_EQ(16, change_observer()->get_and_reset_remove_file_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(FileSystemOperationImplTest, TestTruncate) {
+ FileSystemURL file(CreateFile("file"));
+ base::FilePath platform_path = PlatformPath("file");
+
+ char test_data[] = "test data";
+ int data_size = static_cast<int>(sizeof(test_data));
+ EXPECT_EQ(data_size,
+ file_util::WriteFile(platform_path, test_data, data_size));
+
+ // Check that its length is the size of the data written.
+ operation_runner()->GetMetadata(file, RecordMetadataCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_FALSE(info().is_directory);
+ EXPECT_EQ(data_size, info().size);
+
+ // Extend the file by truncating it.
+ int length = 17;
+ operation_runner()->Truncate(file, length, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ // Check that its length is now 17 and that it's all zeroes after the test
+ // data.
+ EXPECT_EQ(length, GetFileSize("file"));
+ char data[100];
+ EXPECT_EQ(length, base::ReadFile(platform_path, data, length));
+ for (int i = 0; i < length; ++i) {
+ if (i < static_cast<int>(sizeof(test_data)))
+ EXPECT_EQ(test_data[i], data[i]);
+ else
+ EXPECT_EQ(0, data[i]);
+ }
+
+ // Shorten the file by truncating it.
+ length = 3;
+ operation_runner()->Truncate(file, length, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ // Check that its length is now 3 and that it contains only bits of test data.
+ EXPECT_EQ(length, GetFileSize("file"));
+ EXPECT_EQ(length, base::ReadFile(platform_path, data, length));
+ for (int i = 0; i < length; ++i)
+ EXPECT_EQ(test_data[i], data[i]);
+
+ // Truncate is not a 'read' access. (Here expected access count is 1
+ // since we made 1 read access for GetMetadata.)
+ EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
+}
+
+TEST_F(FileSystemOperationImplTest, TestTruncateFailureByQuota) {
+ FileSystemURL dir(CreateDirectory("dir"));
+ FileSystemURL file(CreateFile("dir/file"));
+
+ GrantQuotaForCurrentUsage();
+ AddQuota(10);
+
+ operation_runner()->Truncate(file, 10, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ EXPECT_EQ(10, GetFileSize("dir/file"));
+
+ operation_runner()->Truncate(file, 11, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ EXPECT_EQ(10, GetFileSize("dir/file"));
+}
+
+TEST_F(FileSystemOperationImplTest, TestTouchFile) {
+ FileSystemURL file(CreateFile("file"));
+ base::FilePath platform_path = PlatformPath("file");
+
+ base::PlatformFileInfo info;
+ EXPECT_TRUE(base::GetFileInfo(platform_path, &info));
+ EXPECT_FALSE(info.is_directory);
+ EXPECT_EQ(0, info.size);
+ const base::Time last_modified = info.last_modified;
+ const base::Time last_accessed = info.last_accessed;
+
+ const base::Time new_modified_time = base::Time::UnixEpoch();
+ const base::Time new_accessed_time = new_modified_time +
+ base::TimeDelta::FromHours(77);
+ ASSERT_NE(last_modified, new_modified_time);
+ ASSERT_NE(last_accessed, new_accessed_time);
+
+ operation_runner()->TouchFile(file, new_accessed_time, new_modified_time,
+ RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ EXPECT_TRUE(base::GetFileInfo(platform_path, &info));
+ // We compare as time_t here to lower our resolution, to avoid false
+ // negatives caused by conversion to the local filesystem's native
+ // representation and back.
+ EXPECT_EQ(new_modified_time.ToTimeT(), info.last_modified.ToTimeT());
+ EXPECT_EQ(new_accessed_time.ToTimeT(), info.last_accessed.ToTimeT());
+}
+
+TEST_F(FileSystemOperationImplTest, TestCreateSnapshotFile) {
+ FileSystemURL dir(CreateDirectory("dir"));
+
+ // Create a file for the testing.
+ operation_runner()->DirectoryExists(dir, RecordStatusCallback());
+ FileSystemURL file(CreateFile("dir/file"));
+ operation_runner()->FileExists(file, RecordStatusCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+
+ // See if we can get a 'snapshot' file info for the file.
+ // Since FileSystemOperationImpl assumes the file exists in the local
+ // directory it should just returns the same metadata and platform_path
+ // as the file itself.
+ operation_runner()->CreateSnapshotFile(file, RecordSnapshotFileCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_FALSE(info().is_directory);
+ EXPECT_EQ(PlatformPath("dir/file"), path());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ // The FileSystemOpration implementation does not create a
+ // shareable file reference.
+ EXPECT_EQ(NULL, shareable_file_ref());
+}
+
+TEST_F(FileSystemOperationImplTest,
+ TestMoveSuccessSrcDirRecursiveWithQuota) {
+ FileSystemURL src(CreateDirectory("src"));
+ int src_path_cost = GetUsage();
+
+ FileSystemURL dest(CreateDirectory("dest"));
+ FileSystemURL child_file1(CreateFile("src/file1"));
+ FileSystemURL child_file2(CreateFile("src/file2"));
+ FileSystemURL child_dir(CreateDirectory("src/dir"));
+ FileSystemURL grandchild_file1(CreateFile("src/dir/file1"));
+ FileSystemURL grandchild_file2(CreateFile("src/dir/file2"));
+
+ int total_path_cost = GetUsage();
+ EXPECT_EQ(0, GetDataSizeOnDisk());
+
+ operation_runner()->Truncate(
+ child_file1, 5000,
+ base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
+ operation_runner()->Truncate(
+ child_file2, 400,
+ base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
+ operation_runner()->Truncate(
+ grandchild_file1, 30,
+ base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
+ operation_runner()->Truncate(
+ grandchild_file2, 2,
+ base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
+ base::RunLoop().RunUntilIdle();
+
+ const int64 all_file_size = 5000 + 400 + 30 + 2;
+ EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
+ EXPECT_EQ(all_file_size + total_path_cost, GetUsage());
+
+ operation_runner()->Move(
+ src, dest, FileSystemOperation::OPTION_NONE,
+ base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(DirectoryExists("src/dir"));
+ EXPECT_FALSE(FileExists("src/dir/file2"));
+ EXPECT_TRUE(DirectoryExists("dest/dir"));
+ EXPECT_TRUE(FileExists("dest/dir/file2"));
+
+ EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
+ EXPECT_EQ(all_file_size + total_path_cost - src_path_cost,
+ GetUsage());
+}
+
+TEST_F(FileSystemOperationImplTest,
+ TestCopySuccessSrcDirRecursiveWithQuota) {
+ FileSystemURL src(CreateDirectory("src"));
+ FileSystemURL dest1(CreateDirectory("dest1"));
+ FileSystemURL dest2(CreateDirectory("dest2"));
+
+ int64 usage = GetUsage();
+ FileSystemURL child_file1(CreateFile("src/file1"));
+ FileSystemURL child_file2(CreateFile("src/file2"));
+ FileSystemURL child_dir(CreateDirectory("src/dir"));
+ int64 child_path_cost = GetUsage() - usage;
+ usage += child_path_cost;
+
+ FileSystemURL grandchild_file1(CreateFile("src/dir/file1"));
+ FileSystemURL grandchild_file2(CreateFile("src/dir/file2"));
+ int64 total_path_cost = GetUsage();
+ int64 grandchild_path_cost = total_path_cost - usage;
+
+ EXPECT_EQ(0, GetDataSizeOnDisk());
+
+ operation_runner()->Truncate(
+ child_file1, 8000,
+ base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
+ operation_runner()->Truncate(
+ child_file2, 700,
+ base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
+ operation_runner()->Truncate(
+ grandchild_file1, 60,
+ base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
+ operation_runner()->Truncate(
+ grandchild_file2, 5,
+ base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
+ base::RunLoop().RunUntilIdle();
+
+ const int64 child_file_size = 8000 + 700;
+ const int64 grandchild_file_size = 60 + 5;
+ const int64 all_file_size = child_file_size + grandchild_file_size;
+ int64 expected_usage = all_file_size + total_path_cost;
+
+ usage = GetUsage();
+ EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
+ EXPECT_EQ(expected_usage, usage);
+
+ // Copy src to dest1.
+ operation_runner()->Copy(
+ src, dest1, FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
+ base::RunLoop().RunUntilIdle();
+
+ expected_usage += all_file_size + child_path_cost + grandchild_path_cost;
+ EXPECT_TRUE(DirectoryExists("src/dir"));
+ EXPECT_TRUE(FileExists("src/dir/file2"));
+ EXPECT_TRUE(DirectoryExists("dest1/dir"));
+ EXPECT_TRUE(FileExists("dest1/dir/file2"));
+
+ EXPECT_EQ(2 * all_file_size, GetDataSizeOnDisk());
+ EXPECT_EQ(expected_usage, GetUsage());
+
+ // Copy src/dir to dest2.
+ operation_runner()->Copy(
+ child_dir, dest2, FileSystemOperation::OPTION_NONE,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
+ base::RunLoop().RunUntilIdle();
+
+ expected_usage += grandchild_file_size + grandchild_path_cost;
+ usage = GetUsage();
+ EXPECT_EQ(2 * child_file_size + 3 * grandchild_file_size,
+ GetDataSizeOnDisk());
+ EXPECT_EQ(expected_usage, usage);
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/file_system_operation_impl_write_unittest.cc b/chromium/content/browser/fileapi/file_system_operation_impl_write_unittest.cc
new file mode 100644
index 00000000000..a92288af0fd
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_operation_impl_write_unittest.cc
@@ -0,0 +1,328 @@
+// 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 <vector>
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_file_system_backend.h"
+#include "content/public/test/test_file_system_context.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_job.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "webkit/browser/blob/blob_storage_context.h"
+#include "webkit/browser/blob/blob_url_request_job.h"
+#include "webkit/browser/blob/mock_blob_url_request_context.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_file_util.h"
+#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/file_system_operation_runner.h"
+#include "webkit/browser/fileapi/local_file_util.h"
+#include "webkit/browser/fileapi/mock_file_change_observer.h"
+#include "webkit/browser/quota/mock_quota_manager.h"
+#include "webkit/common/blob/blob_data.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+using webkit_blob::MockBlobURLRequestContext;
+using webkit_blob::ScopedTextBlob;
+
+namespace fileapi {
+
+namespace {
+
+const GURL kOrigin("http://example.com");
+const FileSystemType kFileSystemType = kFileSystemTypeTest;
+
+void AssertStatusEq(base::PlatformFileError expected,
+ base::PlatformFileError actual) {
+ ASSERT_EQ(expected, actual);
+}
+
+} // namespace
+
+class FileSystemOperationImplWriteTest
+ : public testing::Test {
+ public:
+ FileSystemOperationImplWriteTest()
+ : status_(base::PLATFORM_FILE_OK),
+ cancel_status_(base::PLATFORM_FILE_ERROR_FAILED),
+ bytes_written_(0),
+ complete_(false),
+ weak_factory_(this) {
+ change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
+ }
+
+ virtual void SetUp() {
+ ASSERT_TRUE(dir_.CreateUniqueTempDir());
+
+ quota_manager_ =
+ new quota::MockQuotaManager(false /* is_incognito */,
+ dir_.path(),
+ base::MessageLoopProxy::current().get(),
+ base::MessageLoopProxy::current().get(),
+ NULL /* special storage policy */);
+ virtual_path_ = base::FilePath(FILE_PATH_LITERAL("temporary file"));
+
+ file_system_context_ = CreateFileSystemContextForTesting(
+ quota_manager_->proxy(), dir_.path());
+ url_request_context_.reset(
+ new MockBlobURLRequestContext(file_system_context_.get()));
+
+ file_system_context_->operation_runner()->CreateFile(
+ URLForPath(virtual_path_), true /* exclusive */,
+ base::Bind(&AssertStatusEq, base::PLATFORM_FILE_OK));
+
+ static_cast<TestFileSystemBackend*>(
+ file_system_context_->GetFileSystemBackend(kFileSystemType))
+ ->AddFileChangeObserver(change_observer());
+ }
+
+ virtual void TearDown() {
+ quota_manager_ = NULL;
+ file_system_context_ = NULL;
+ base::RunLoop().RunUntilIdle();
+ }
+
+ base::PlatformFileError status() const { return status_; }
+ base::PlatformFileError cancel_status() const { return cancel_status_; }
+ void add_bytes_written(int64 bytes, bool complete) {
+ bytes_written_ += bytes;
+ EXPECT_FALSE(complete_);
+ complete_ = complete;
+ }
+ int64 bytes_written() const { return bytes_written_; }
+ bool complete() const { return complete_; }
+
+ protected:
+ const ChangeObserverList& change_observers() const {
+ return change_observers_;
+ }
+
+ MockFileChangeObserver* change_observer() {
+ return &change_observer_;
+ }
+
+ FileSystemURL URLForPath(const base::FilePath& path) const {
+ return file_system_context_->CreateCrackedFileSystemURL(
+ kOrigin, kFileSystemType, path);
+ }
+
+ // Callback function for recording test results.
+ FileSystemOperation::WriteCallback RecordWriteCallback() {
+ return base::Bind(&FileSystemOperationImplWriteTest::DidWrite,
+ weak_factory_.GetWeakPtr());
+ }
+
+ FileSystemOperation::StatusCallback RecordCancelCallback() {
+ return base::Bind(&FileSystemOperationImplWriteTest::DidCancel,
+ weak_factory_.GetWeakPtr());
+ }
+
+ void DidWrite(base::PlatformFileError status, int64 bytes, bool complete) {
+ if (status == base::PLATFORM_FILE_OK) {
+ add_bytes_written(bytes, complete);
+ if (complete)
+ base::MessageLoop::current()->Quit();
+ } else {
+ EXPECT_FALSE(complete_);
+ EXPECT_EQ(status_, base::PLATFORM_FILE_OK);
+ complete_ = true;
+ status_ = status;
+ if (base::MessageLoop::current()->is_running())
+ base::MessageLoop::current()->Quit();
+ }
+ }
+
+ void DidCancel(base::PlatformFileError status) {
+ cancel_status_ = status;
+ }
+
+ const MockBlobURLRequestContext& url_request_context() const {
+ return *url_request_context_;
+ }
+
+ scoped_refptr<FileSystemContext> file_system_context_;
+ scoped_refptr<quota::MockQuotaManager> quota_manager_;
+
+ base::MessageLoopForIO loop_;
+
+ base::ScopedTempDir dir_;
+ base::FilePath virtual_path_;
+
+ // For post-operation status.
+ base::PlatformFileError status_;
+ base::PlatformFileError cancel_status_;
+ int64 bytes_written_;
+ bool complete_;
+
+ scoped_ptr<MockBlobURLRequestContext> url_request_context_;
+
+ MockFileChangeObserver change_observer_;
+ ChangeObserverList change_observers_;
+
+ base::WeakPtrFactory<FileSystemOperationImplWriteTest> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplWriteTest);
+};
+
+TEST_F(FileSystemOperationImplWriteTest, TestWriteSuccess) {
+ ScopedTextBlob blob(url_request_context(),
+ "blob-id:success",
+ "Hello, world!\n");
+ file_system_context_->operation_runner()->Write(
+ &url_request_context(), URLForPath(virtual_path_),
+ blob.GetBlobDataHandle(),
+ 0, RecordWriteCallback());
+ base::MessageLoop::current()->Run();
+
+ EXPECT_EQ(14, bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(complete());
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+}
+
+TEST_F(FileSystemOperationImplWriteTest, TestWriteZero) {
+ ScopedTextBlob blob(url_request_context(), "blob_id:zero", "");
+ file_system_context_->operation_runner()->Write(
+ &url_request_context(), URLForPath(virtual_path_),
+ blob.GetBlobDataHandle(), 0, RecordWriteCallback());
+ base::MessageLoop::current()->Run();
+
+ EXPECT_EQ(0, bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status());
+ EXPECT_TRUE(complete());
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+}
+
+
+TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) {
+ scoped_ptr<webkit_blob::BlobDataHandle> null_handle;
+ file_system_context_->operation_runner()->Write(
+ &url_request_context(), URLForPath(virtual_path_),
+ null_handle.Pass(), 0, RecordWriteCallback());
+ base::MessageLoop::current()->Run();
+
+ EXPECT_EQ(0, bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_FAILED, status());
+ EXPECT_TRUE(complete());
+
+ EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
+}
+
+TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidFile) {
+ ScopedTextBlob blob(url_request_context(), "blob_id:writeinvalidfile",
+ "It\'ll not be written.");
+ file_system_context_->operation_runner()->Write(
+ &url_request_context(),
+ URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))),
+ blob.GetBlobDataHandle(), 0, RecordWriteCallback());
+ base::MessageLoop::current()->Run();
+
+ EXPECT_EQ(0, bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
+ EXPECT_TRUE(complete());
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+}
+
+TEST_F(FileSystemOperationImplWriteTest, TestWriteDir) {
+ base::FilePath virtual_dir_path(FILE_PATH_LITERAL("d"));
+ file_system_context_->operation_runner()->CreateDirectory(
+ URLForPath(virtual_dir_path),
+ true /* exclusive */, false /* recursive */,
+ base::Bind(&AssertStatusEq, base::PLATFORM_FILE_OK));
+
+ ScopedTextBlob blob(url_request_context(), "blob:writedir",
+ "It\'ll not be written, too.");
+ file_system_context_->operation_runner()->Write(
+ &url_request_context(), URLForPath(virtual_dir_path),
+ blob.GetBlobDataHandle(), 0, RecordWriteCallback());
+ base::MessageLoop::current()->Run();
+
+ EXPECT_EQ(0, bytes_written());
+ // TODO(kinuko): This error code is platform- or fileutil- dependent
+ // right now. Make it return PLATFORM_FILE_ERROR_NOT_A_FILE in every case.
+ EXPECT_TRUE(status() == base::PLATFORM_FILE_ERROR_NOT_A_FILE ||
+ status() == base::PLATFORM_FILE_ERROR_ACCESS_DENIED ||
+ status() == base::PLATFORM_FILE_ERROR_FAILED);
+ EXPECT_TRUE(complete());
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+}
+
+TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) {
+ ScopedTextBlob blob(url_request_context(), "blob:success",
+ "Hello, world!\n");
+ quota_manager_->SetQuota(
+ kOrigin, FileSystemTypeToQuotaStorageType(kFileSystemType), 10);
+ file_system_context_->operation_runner()->Write(
+ &url_request_context(), URLForPath(virtual_path_),
+ blob.GetBlobDataHandle(), 0, RecordWriteCallback());
+ base::MessageLoop::current()->Run();
+
+ EXPECT_EQ(10, bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
+ EXPECT_TRUE(complete());
+
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+}
+
+TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelSuccessfulWrite) {
+ ScopedTextBlob blob(url_request_context(), "blob:success",
+ "Hello, world!\n");
+ FileSystemOperationRunner::OperationID id =
+ file_system_context_->operation_runner()->Write(
+ &url_request_context(), URLForPath(virtual_path_),
+ blob.GetBlobDataHandle(), 0, RecordWriteCallback());
+ file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback());
+ // We use RunAllPendings() instead of Run() here, because we won't dispatch
+ // callbacks after Cancel() is issued (so no chance to Quit) nor do we need
+ // to run another write cycle.
+ base::RunLoop().RunUntilIdle();
+
+ // Issued Cancel() before receiving any response from Write(),
+ // so nothing should have happen.
+ EXPECT_EQ(0, bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_ABORT, status());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, cancel_status());
+ EXPECT_TRUE(complete());
+
+ EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
+}
+
+TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelFailingWrite) {
+ ScopedTextBlob blob(url_request_context(), "blob:writeinvalidfile",
+ "It\'ll not be written.");
+ FileSystemOperationRunner::OperationID id =
+ file_system_context_->operation_runner()->Write(
+ &url_request_context(),
+ URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))),
+ blob.GetBlobDataHandle(), 0, RecordWriteCallback());
+ file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback());
+ // We use RunAllPendings() instead of Run() here, because we won't dispatch
+ // callbacks after Cancel() is issued (so no chance to Quit) nor do we need
+ // to run another write cycle.
+ base::RunLoop().RunUntilIdle();
+
+ // Issued Cancel() before receiving any response from Write(),
+ // so nothing should have happen.
+ EXPECT_EQ(0, bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_ABORT, status());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, cancel_status());
+ EXPECT_TRUE(complete());
+
+ EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
+}
+
+// TODO(ericu,dmikurube,kinuko): Add more tests for cancel cases.
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc b/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
new file mode 100644
index 00000000000..1fa711b8672
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
@@ -0,0 +1,162 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/platform_file.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_file_system_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_operation_runner.h"
+
+namespace fileapi {
+
+void GetStatus(bool* done,
+ base::PlatformFileError *status_out,
+ base::PlatformFileError status) {
+ ASSERT_FALSE(*done);
+ *done = true;
+ *status_out = status;
+}
+
+void GetCancelStatus(bool* operation_done,
+ bool* cancel_done,
+ base::PlatformFileError *status_out,
+ base::PlatformFileError status) {
+ // Cancel callback must be always called after the operation's callback.
+ ASSERT_TRUE(*operation_done);
+ ASSERT_FALSE(*cancel_done);
+ *cancel_done = true;
+ *status_out = status;
+}
+
+class FileSystemOperationRunnerTest : public testing::Test {
+ protected:
+ FileSystemOperationRunnerTest() {}
+ virtual ~FileSystemOperationRunnerTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(base_.CreateUniqueTempDir());
+ base::FilePath base_dir = base_.path();
+ file_system_context_ =
+ CreateFileSystemContextForTesting(NULL, base_dir);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ file_system_context_ = NULL;
+ base::RunLoop().RunUntilIdle();
+ }
+
+ FileSystemURL URL(const std::string& path) {
+ return file_system_context_->CreateCrackedFileSystemURL(
+ GURL("http://example.com"), kFileSystemTypeTemporary,
+ base::FilePath::FromUTF8Unsafe(path));
+ }
+
+ FileSystemOperationRunner* operation_runner() {
+ return file_system_context_->operation_runner();
+ }
+
+ private:
+ base::ScopedTempDir base_;
+ base::MessageLoop message_loop_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemOperationRunnerTest);
+};
+
+TEST_F(FileSystemOperationRunnerTest, NotFoundError) {
+ bool done = false;
+ base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED;
+
+ // Regular NOT_FOUND error, which is called asynchronously.
+ operation_runner()->Truncate(URL("foo"), 0,
+ base::Bind(&GetStatus, &done, &status));
+ ASSERT_FALSE(done);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(done);
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status);
+}
+
+TEST_F(FileSystemOperationRunnerTest, InvalidURLError) {
+ bool done = false;
+ base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED;
+
+ // Invalid URL error, which calls DidFinish synchronously.
+ operation_runner()->Truncate(FileSystemURL(), 0,
+ base::Bind(&GetStatus, &done, &status));
+ // The error call back shouldn't be fired synchronously.
+ ASSERT_FALSE(done);
+
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(done);
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_URL, status);
+}
+
+TEST_F(FileSystemOperationRunnerTest, NotFoundErrorAndCancel) {
+ bool done = false;
+ bool cancel_done = false;
+ base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED;
+ base::PlatformFileError cancel_status = base::PLATFORM_FILE_ERROR_FAILED;
+
+ // Call Truncate with non-existent URL, and try to cancel it immediately
+ // after that (before its callback is fired).
+ FileSystemOperationRunner::OperationID id =
+ operation_runner()->Truncate(URL("foo"), 0,
+ base::Bind(&GetStatus, &done, &status));
+ operation_runner()->Cancel(id, base::Bind(&GetCancelStatus,
+ &done, &cancel_done,
+ &cancel_status));
+
+ ASSERT_FALSE(done);
+ ASSERT_FALSE(cancel_done);
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_TRUE(done);
+ ASSERT_TRUE(cancel_done);
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status);
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, cancel_status);
+}
+
+TEST_F(FileSystemOperationRunnerTest, InvalidURLErrorAndCancel) {
+ bool done = false;
+ bool cancel_done = false;
+ base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED;
+ base::PlatformFileError cancel_status = base::PLATFORM_FILE_ERROR_FAILED;
+
+ // Call Truncate with invalid URL, and try to cancel it immediately
+ // after that (before its callback is fired).
+ FileSystemOperationRunner::OperationID id =
+ operation_runner()->Truncate(FileSystemURL(), 0,
+ base::Bind(&GetStatus, &done, &status));
+ operation_runner()->Cancel(id, base::Bind(&GetCancelStatus,
+ &done, &cancel_done,
+ &cancel_status));
+
+ ASSERT_FALSE(done);
+ ASSERT_FALSE(cancel_done);
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_TRUE(done);
+ ASSERT_TRUE(cancel_done);
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_URL, status);
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, cancel_status);
+}
+
+TEST_F(FileSystemOperationRunnerTest, CancelWithInvalidId) {
+ const FileSystemOperationRunner::OperationID kInvalidId = -1;
+ bool done = true; // The operation is not running.
+ bool cancel_done = false;
+ base::PlatformFileError cancel_status = base::PLATFORM_FILE_ERROR_FAILED;
+ operation_runner()->Cancel(kInvalidId, base::Bind(&GetCancelStatus,
+ &done, &cancel_done,
+ &cancel_status));
+
+ ASSERT_TRUE(cancel_done);
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, cancel_status);
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/file_system_quota_client_unittest.cc b/chromium/content/browser/fileapi/file_system_quota_client_unittest.cc
new file mode 100644
index 00000000000..c4baa4f8aa6
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_quota_client_unittest.cc
@@ -0,0 +1,561 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/platform_file.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_file_system_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_quota_client.h"
+#include "webkit/browser/fileapi/file_system_usage_cache.h"
+#include "webkit/browser/fileapi/obfuscated_file_util.h"
+#include "webkit/common/fileapi/file_system_types.h"
+#include "webkit/common/fileapi/file_system_util.h"
+#include "webkit/common/quota/quota_types.h"
+
+namespace fileapi {
+namespace {
+
+const char kDummyURL1[] = "http://www.dummy.org";
+const char kDummyURL2[] = "http://www.example.com";
+const char kDummyURL3[] = "http://www.bleh";
+
+// Declared to shorten the variable names.
+const quota::StorageType kTemporary = quota::kStorageTypeTemporary;
+const quota::StorageType kPersistent = quota::kStorageTypePersistent;
+
+} // namespace
+
+class FileSystemQuotaClientTest : public testing::Test {
+ public:
+ FileSystemQuotaClientTest()
+ : weak_factory_(this),
+ additional_callback_count_(0),
+ deletion_status_(quota::kQuotaStatusUnknown) {
+ }
+
+ virtual void SetUp() {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+ file_system_context_ = CreateFileSystemContextForTesting(
+ NULL, data_dir_.path());
+ }
+
+ struct TestFile {
+ bool isDirectory;
+ const char* name;
+ int64 size;
+ const char* origin_url;
+ quota::StorageType type;
+ };
+
+ protected:
+ FileSystemQuotaClient* NewQuotaClient(bool is_incognito) {
+ return new FileSystemQuotaClient(file_system_context_.get(), is_incognito);
+ }
+
+ void GetOriginUsageAsync(FileSystemQuotaClient* quota_client,
+ const std::string& origin_url,
+ quota::StorageType type) {
+ quota_client->GetOriginUsage(
+ GURL(origin_url), type,
+ base::Bind(&FileSystemQuotaClientTest::OnGetUsage,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ int64 GetOriginUsage(FileSystemQuotaClient* quota_client,
+ const std::string& origin_url,
+ quota::StorageType type) {
+ GetOriginUsageAsync(quota_client, origin_url, type);
+ base::RunLoop().RunUntilIdle();
+ return usage_;
+ }
+
+ const std::set<GURL>& GetOriginsForType(FileSystemQuotaClient* quota_client,
+ quota::StorageType type) {
+ origins_.clear();
+ quota_client->GetOriginsForType(
+ type,
+ base::Bind(&FileSystemQuotaClientTest::OnGetOrigins,
+ weak_factory_.GetWeakPtr()));
+ base::RunLoop().RunUntilIdle();
+ return origins_;
+ }
+
+ const std::set<GURL>& GetOriginsForHost(FileSystemQuotaClient* quota_client,
+ quota::StorageType type,
+ const std::string& host) {
+ origins_.clear();
+ quota_client->GetOriginsForHost(
+ type, host,
+ base::Bind(&FileSystemQuotaClientTest::OnGetOrigins,
+ weak_factory_.GetWeakPtr()));
+ base::RunLoop().RunUntilIdle();
+ return origins_;
+ }
+
+ void RunAdditionalOriginUsageTask(FileSystemQuotaClient* quota_client,
+ const std::string& origin_url,
+ quota::StorageType type) {
+ quota_client->GetOriginUsage(
+ GURL(origin_url), type,
+ base::Bind(&FileSystemQuotaClientTest::OnGetAdditionalUsage,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ bool CreateFileSystemDirectory(const base::FilePath& file_path,
+ const std::string& origin_url,
+ quota::StorageType storage_type) {
+ FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
+ FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
+ GURL(origin_url), type, file_path);
+
+ base::PlatformFileError result =
+ AsyncFileTestHelper::CreateDirectory(file_system_context_, url);
+ return result == base::PLATFORM_FILE_OK;
+ }
+
+ bool CreateFileSystemFile(const base::FilePath& file_path,
+ int64 file_size,
+ const std::string& origin_url,
+ quota::StorageType storage_type) {
+ if (file_path.empty())
+ return false;
+
+ FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
+ FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
+ GURL(origin_url), type, file_path);
+
+ base::PlatformFileError result =
+ AsyncFileTestHelper::CreateFile(file_system_context_, url);
+ if (result != base::PLATFORM_FILE_OK)
+ return false;
+
+ result = AsyncFileTestHelper::TruncateFile(
+ file_system_context_, url, file_size);
+ return result == base::PLATFORM_FILE_OK;
+ }
+
+ void InitializeOriginFiles(FileSystemQuotaClient* quota_client,
+ const TestFile* files,
+ int num_files) {
+ for (int i = 0; i < num_files; i++) {
+ base::FilePath path = base::FilePath().AppendASCII(files[i].name);
+ if (files[i].isDirectory) {
+ ASSERT_TRUE(CreateFileSystemDirectory(
+ path, files[i].origin_url, files[i].type));
+ if (path.empty()) {
+ // Create the usage cache.
+ // HACK--we always create the root [an empty path] first. If we
+ // create it later, this will fail due to a quota mismatch. If we
+ // call this before we create the root, it succeeds, but hasn't
+ // actually created the cache.
+ ASSERT_EQ(0, GetOriginUsage(
+ quota_client, files[i].origin_url, files[i].type));
+ }
+ } else {
+ ASSERT_TRUE(CreateFileSystemFile(
+ path, files[i].size, files[i].origin_url, files[i].type));
+ }
+ }
+ }
+
+ // This is a bit fragile--it depends on the test data always creating a
+ // directory before adding a file or directory to it, so that we can just
+ // count the basename of each addition. A recursive creation of a path, which
+ // created more than one directory in a single shot, would break this.
+ int64 ComputeFilePathsCostForOriginAndType(const TestFile* files,
+ int num_files,
+ const std::string& origin_url,
+ quota::StorageType type) {
+ int64 file_paths_cost = 0;
+ for (int i = 0; i < num_files; i++) {
+ if (files[i].type == type &&
+ GURL(files[i].origin_url) == GURL(origin_url)) {
+ base::FilePath path = base::FilePath().AppendASCII(files[i].name);
+ if (!path.empty()) {
+ file_paths_cost += ObfuscatedFileUtil::ComputeFilePathCost(path);
+ }
+ }
+ }
+ return file_paths_cost;
+ }
+
+ void DeleteOriginData(FileSystemQuotaClient* quota_client,
+ const std::string& origin,
+ quota::StorageType type) {
+ deletion_status_ = quota::kQuotaStatusUnknown;
+ quota_client->DeleteOriginData(
+ GURL(origin), type,
+ base::Bind(&FileSystemQuotaClientTest::OnDeleteOrigin,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ int64 usage() const { return usage_; }
+ quota::QuotaStatusCode status() { return deletion_status_; }
+ int additional_callback_count() const { return additional_callback_count_; }
+ void set_additional_callback_count(int count) {
+ additional_callback_count_ = count;
+ }
+
+ private:
+ void OnGetUsage(int64 usage) {
+ usage_ = usage;
+ }
+
+ void OnGetOrigins(const std::set<GURL>& origins) {
+ origins_ = origins;
+ }
+
+ void OnGetAdditionalUsage(int64 usage_unused) {
+ ++additional_callback_count_;
+ }
+
+ void OnDeleteOrigin(quota::QuotaStatusCode status) {
+ deletion_status_ = status;
+ }
+
+ base::ScopedTempDir data_dir_;
+ base::MessageLoop message_loop_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ base::WeakPtrFactory<FileSystemQuotaClientTest> weak_factory_;
+ int64 usage_;
+ int additional_callback_count_;
+ std::set<GURL> origins_;
+ quota::QuotaStatusCode deletion_status_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemQuotaClientTest);
+};
+
+TEST_F(FileSystemQuotaClientTest, NoFileSystemTest) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+
+ EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+}
+
+TEST_F(FileSystemQuotaClientTest, NoFileTest) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ }
+}
+
+TEST_F(FileSystemQuotaClientTest, OneFileTest) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {false, "foo", 4921, kDummyURL1, kTemporary},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
+ kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(4921 + file_paths_cost,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ }
+}
+
+TEST_F(FileSystemQuotaClientTest, TwoFilesTest) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {false, "foo", 10310, kDummyURL1, kTemporary},
+ {false, "bar", 41, kDummyURL1, kTemporary},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
+ kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(10310 + 41 + file_paths_cost,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ }
+}
+
+TEST_F(FileSystemQuotaClientTest, EmptyFilesTest) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {false, "foo", 0, kDummyURL1, kTemporary},
+ {false, "bar", 0, kDummyURL1, kTemporary},
+ {false, "baz", 0, kDummyURL1, kTemporary},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
+ kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(file_paths_cost,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ }
+}
+
+TEST_F(FileSystemQuotaClientTest, SubDirectoryTest) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {true, "dirtest", 0, kDummyURL1, kTemporary},
+ {false, "dirtest/foo", 11921, kDummyURL1, kTemporary},
+ {false, "bar", 4814, kDummyURL1, kTemporary},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
+ kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(11921 + 4814 + file_paths_cost,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ }
+}
+
+TEST_F(FileSystemQuotaClientTest, MultiTypeTest) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {true, "dirtest", 0, kDummyURL1, kTemporary},
+ {false, "dirtest/foo", 133, kDummyURL1, kTemporary},
+ {false, "bar", 14, kDummyURL1, kTemporary},
+ {true, NULL, 0, kDummyURL1, kPersistent},
+ {true, "dirtest", 0, kDummyURL1, kPersistent},
+ {false, "dirtest/foo", 193, kDummyURL1, kPersistent},
+ {false, "bar", 9, kDummyURL1, kPersistent},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ const int64 file_paths_cost_temporary = ComputeFilePathsCostForOriginAndType(
+ kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+ const int64 file_paths_cost_persistent = ComputeFilePathsCostForOriginAndType(
+ kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(133 + 14 + file_paths_cost_temporary,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ EXPECT_EQ(193 + 9 + file_paths_cost_persistent,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kPersistent));
+ }
+}
+
+TEST_F(FileSystemQuotaClientTest, MultiDomainTest) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {true, "dir1", 0, kDummyURL1, kTemporary},
+ {false, "dir1/foo", 1331, kDummyURL1, kTemporary},
+ {false, "bar", 134, kDummyURL1, kTemporary},
+ {true, NULL, 0, kDummyURL1, kPersistent},
+ {true, "dir2", 0, kDummyURL1, kPersistent},
+ {false, "dir2/foo", 1903, kDummyURL1, kPersistent},
+ {false, "bar", 19, kDummyURL1, kPersistent},
+ {true, NULL, 0, kDummyURL2, kTemporary},
+ {true, "dom", 0, kDummyURL2, kTemporary},
+ {false, "dom/fan", 1319, kDummyURL2, kTemporary},
+ {false, "bar", 113, kDummyURL2, kTemporary},
+ {true, NULL, 0, kDummyURL2, kPersistent},
+ {true, "dom", 0, kDummyURL2, kPersistent},
+ {false, "dom/fan", 2013, kDummyURL2, kPersistent},
+ {false, "baz", 18, kDummyURL2, kPersistent},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ const int64 file_paths_cost_temporary1 = ComputeFilePathsCostForOriginAndType(
+ kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+ const int64 file_paths_cost_persistent1 =
+ ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ kDummyURL1, kPersistent);
+ const int64 file_paths_cost_temporary2 = ComputeFilePathsCostForOriginAndType(
+ kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL2, kTemporary);
+ const int64 file_paths_cost_persistent2 =
+ ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ kDummyURL2, kPersistent);
+
+ for (int i = 0; i < 2; i++) {
+ EXPECT_EQ(1331 + 134 + file_paths_cost_temporary1,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ EXPECT_EQ(1903 + 19 + file_paths_cost_persistent1,
+ GetOriginUsage(quota_client.get(), kDummyURL1, kPersistent));
+ EXPECT_EQ(1319 + 113 + file_paths_cost_temporary2,
+ GetOriginUsage(quota_client.get(), kDummyURL2, kTemporary));
+ EXPECT_EQ(2013 + 18 + file_paths_cost_persistent2,
+ GetOriginUsage(quota_client.get(), kDummyURL2, kPersistent));
+ }
+}
+
+TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {false, "foo", 11, kDummyURL1, kTemporary},
+ {false, "bar", 22, kDummyURL1, kTemporary},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
+ kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+
+ // Dispatching three GetUsage tasks.
+ set_additional_callback_count(0);
+ GetOriginUsageAsync(quota_client.get(), kDummyURL1, kTemporary);
+ RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
+ RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(11 + 22 + file_paths_cost, usage());
+ EXPECT_EQ(2, additional_callback_count());
+
+ // Once more, in a different order.
+ set_additional_callback_count(0);
+ RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
+ GetOriginUsageAsync(quota_client.get(), kDummyURL1, kTemporary);
+ RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(11 + 22 + file_paths_cost, usage());
+ EXPECT_EQ(2, additional_callback_count());
+}
+
+TEST_F(FileSystemQuotaClientTest, GetOriginsForType) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {true, NULL, 0, kDummyURL2, kTemporary},
+ {true, NULL, 0, kDummyURL3, kPersistent},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ std::set<GURL> origins = GetOriginsForType(quota_client.get(), kTemporary);
+ EXPECT_EQ(2U, origins.size());
+ EXPECT_TRUE(origins.find(GURL(kDummyURL1)) != origins.end());
+ EXPECT_TRUE(origins.find(GURL(kDummyURL2)) != origins.end());
+ EXPECT_TRUE(origins.find(GURL(kDummyURL3)) == origins.end());
+}
+
+TEST_F(FileSystemQuotaClientTest, GetOriginsForHost) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+ const char* kURL1 = "http://foo.com/";
+ const char* kURL2 = "https://foo.com/";
+ const char* kURL3 = "http://foo.com:1/";
+ const char* kURL4 = "http://foo2.com/";
+ const char* kURL5 = "http://foo.com:2/";
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kURL1, kTemporary},
+ {true, NULL, 0, kURL2, kTemporary},
+ {true, NULL, 0, kURL3, kTemporary},
+ {true, NULL, 0, kURL4, kTemporary},
+ {true, NULL, 0, kURL5, kPersistent},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ std::set<GURL> origins = GetOriginsForHost(
+ quota_client.get(), kTemporary, "foo.com");
+ EXPECT_EQ(3U, origins.size());
+ EXPECT_TRUE(origins.find(GURL(kURL1)) != origins.end());
+ EXPECT_TRUE(origins.find(GURL(kURL2)) != origins.end());
+ EXPECT_TRUE(origins.find(GURL(kURL3)) != origins.end());
+ EXPECT_TRUE(origins.find(GURL(kURL4)) == origins.end()); // Different host.
+ EXPECT_TRUE(origins.find(GURL(kURL5)) == origins.end()); // Different type.
+}
+
+TEST_F(FileSystemQuotaClientTest, IncognitoTest) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(true));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, kDummyURL1, kTemporary},
+ {false, "foo", 10, kDummyURL1, kTemporary},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+
+ // Having files in the usual directory wouldn't affect the result
+ // queried in incognito mode.
+ EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
+ EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kPersistent));
+
+ std::set<GURL> origins = GetOriginsForType(quota_client.get(), kTemporary);
+ EXPECT_EQ(0U, origins.size());
+ origins = GetOriginsForHost(quota_client.get(), kTemporary, "www.dummy.org");
+ EXPECT_EQ(0U, origins.size());
+}
+
+TEST_F(FileSystemQuotaClientTest, DeleteOriginTest) {
+ scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
+ const TestFile kFiles[] = {
+ {true, NULL, 0, "http://foo.com/", kTemporary},
+ {false, "a", 1, "http://foo.com/", kTemporary},
+ {true, NULL, 0, "https://foo.com/", kTemporary},
+ {false, "b", 2, "https://foo.com/", kTemporary},
+ {true, NULL, 0, "http://foo.com/", kPersistent},
+ {false, "c", 4, "http://foo.com/", kPersistent},
+ {true, NULL, 0, "http://bar.com/", kTemporary},
+ {false, "d", 8, "http://bar.com/", kTemporary},
+ {true, NULL, 0, "http://bar.com/", kPersistent},
+ {false, "e", 16, "http://bar.com/", kPersistent},
+ {true, NULL, 0, "https://bar.com/", kPersistent},
+ {false, "f", 32, "https://bar.com/", kPersistent},
+ {true, NULL, 0, "https://bar.com/", kTemporary},
+ {false, "g", 64, "https://bar.com/", kTemporary},
+ };
+ InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ const int64 file_paths_cost_temporary_foo_https =
+ ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ "https://foo.com/", kTemporary);
+ const int64 file_paths_cost_persistent_foo =
+ ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ "http://foo.com/", kPersistent);
+ const int64 file_paths_cost_temporary_bar =
+ ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ "http://bar.com/", kTemporary);
+ const int64 file_paths_cost_temporary_bar_https =
+ ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ "https://bar.com/", kTemporary);
+ const int64 file_paths_cost_persistent_bar_https =
+ ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ "https://bar.com/", kPersistent);
+
+ DeleteOriginData(quota_client.get(), "http://foo.com/", kTemporary);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(quota::kQuotaStatusOk, status());
+
+ DeleteOriginData(quota_client.get(), "http://bar.com/", kPersistent);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(quota::kQuotaStatusOk, status());
+
+ DeleteOriginData(quota_client.get(), "http://buz.com/", kTemporary);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(quota::kQuotaStatusOk, status());
+
+ EXPECT_EQ(0, GetOriginUsage(
+ quota_client.get(), "http://foo.com/", kTemporary));
+ EXPECT_EQ(0, GetOriginUsage(
+ quota_client.get(), "http://bar.com/", kPersistent));
+ EXPECT_EQ(0, GetOriginUsage(
+ quota_client.get(), "http://buz.com/", kTemporary));
+
+ EXPECT_EQ(2 + file_paths_cost_temporary_foo_https,
+ GetOriginUsage(quota_client.get(),
+ "https://foo.com/",
+ kTemporary));
+ EXPECT_EQ(4 + file_paths_cost_persistent_foo,
+ GetOriginUsage(quota_client.get(),
+ "http://foo.com/",
+ kPersistent));
+ EXPECT_EQ(8 + file_paths_cost_temporary_bar,
+ GetOriginUsage(quota_client.get(),
+ "http://bar.com/",
+ kTemporary));
+ EXPECT_EQ(32 + file_paths_cost_persistent_bar_https,
+ GetOriginUsage(quota_client.get(),
+ "https://bar.com/",
+ kPersistent));
+ EXPECT_EQ(64 + file_paths_cost_temporary_bar_https,
+ GetOriginUsage(quota_client.get(),
+ "https://bar.com/",
+ kTemporary));
+}
+
+} // namespace fileapi
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
new file mode 100644
index 00000000000..7edd26aa656
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc
@@ -0,0 +1,368 @@
+// 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 "webkit/browser/fileapi/file_system_url_request_job.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/format_macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/platform_file.h"
+#include "base/rand_util.h"
+#include "base/run_loop.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/test/test_file_system_context.h"
+#include "net/base/load_flags.h"
+#include "net/base/mime_util.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_byte_range.h"
+#include "net/http/http_request_headers.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_file_util.h"
+
+namespace fileapi {
+namespace {
+
+// We always use the TEMPORARY FileSystem in this test.
+const char kFileSystemURLPrefix[] = "filesystem:http://remote/temporary/";
+const char kTestFileData[] = "0123456789";
+
+void FillBuffer(char* buffer, size_t len) {
+ base::RandBytes(buffer, len);
+}
+
+} // namespace
+
+class FileSystemURLRequestJobTest : public testing::Test {
+ protected:
+ FileSystemURLRequestJobTest() : weak_factory_(this) {
+ }
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ // We use the main thread so that we can get the root path synchronously.
+ // TODO(adamk): Run this on the FILE thread we've created as well.
+ file_system_context_ =
+ CreateFileSystemContextForTesting(NULL, temp_dir_.path());
+
+ file_system_context_->OpenFileSystem(
+ GURL("http://remote/"), kFileSystemTypeTemporary,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&FileSystemURLRequestJobTest::OnOpenFileSystem,
+ weak_factory_.GetWeakPtr()));
+ base::RunLoop().RunUntilIdle();
+
+ net::URLRequest::Deprecated::RegisterProtocolFactory(
+ "filesystem", &FileSystemURLRequestJobFactory);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ net::URLRequest::Deprecated::RegisterProtocolFactory("filesystem", NULL);
+ ClearUnusedJob();
+ if (pending_job_.get()) {
+ pending_job_->Kill();
+ pending_job_ = NULL;
+ }
+ // FileReader posts a task to close the file in destructor.
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void OnOpenFileSystem(const GURL& root_url,
+ const std::string& name,
+ base::PlatformFileError result) {
+ ASSERT_EQ(base::PLATFORM_FILE_OK, result);
+ }
+
+ void TestRequestHelper(const GURL& url,
+ const net::HttpRequestHeaders* headers,
+ bool run_to_completion,
+ FileSystemContext* file_system_context) {
+ delegate_.reset(new net::TestDelegate());
+ // Make delegate_ exit the MessageLoop when the request is done.
+ delegate_->set_quit_on_complete(true);
+ delegate_->set_quit_on_redirect(true);
+ request_ = empty_context_.CreateRequest(
+ url, net::DEFAULT_PRIORITY, delegate_.get());
+ if (headers)
+ request_->SetExtraRequestHeaders(*headers);
+ ASSERT_TRUE(!job_);
+ job_ = new FileSystemURLRequestJob(
+ request_.get(), NULL, file_system_context);
+ pending_job_ = job_;
+
+ request_->Start();
+ ASSERT_TRUE(request_->is_pending()); // verify that we're starting async
+ if (run_to_completion)
+ base::MessageLoop::current()->Run();
+ }
+
+ void TestRequest(const GURL& url) {
+ TestRequestHelper(url, NULL, true, file_system_context_.get());
+ }
+
+ void TestRequestWithContext(const GURL& url,
+ FileSystemContext* file_system_context) {
+ TestRequestHelper(url, NULL, true, file_system_context);
+ }
+
+ void TestRequestWithHeaders(const GURL& url,
+ const net::HttpRequestHeaders* headers) {
+ TestRequestHelper(url, headers, true, file_system_context_.get());
+ }
+
+ void TestRequestNoRun(const GURL& url) {
+ TestRequestHelper(url, NULL, false, file_system_context_.get());
+ }
+
+ void CreateDirectory(const base::StringPiece& dir_name) {
+ FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
+ GURL("http://remote"),
+ kFileSystemTypeTemporary,
+ base::FilePath().AppendASCII(dir_name));
+ ASSERT_EQ(base::PLATFORM_FILE_OK, AsyncFileTestHelper::CreateDirectory(
+ file_system_context_, url));
+ }
+
+ void WriteFile(const base::StringPiece& file_name,
+ const char* buf, int buf_size) {
+ FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
+ GURL("http://remote"),
+ kFileSystemTypeTemporary,
+ base::FilePath().AppendASCII(file_name));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::CreateFileWithData(
+ file_system_context_, url, buf, buf_size));
+ }
+
+ GURL CreateFileSystemURL(const std::string& path) {
+ return GURL(kFileSystemURLPrefix + path);
+ }
+
+ static net::URLRequestJob* FileSystemURLRequestJobFactory(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const std::string& scheme) {
+ DCHECK(job_);
+ net::URLRequestJob* temp = job_;
+ job_ = NULL;
+ return temp;
+ }
+
+ static void ClearUnusedJob() {
+ if (job_) {
+ scoped_refptr<net::URLRequestJob> deleter = job_;
+ job_ = NULL;
+ }
+ }
+
+ // Put the message loop at the top, so that it's the last thing deleted.
+ base::MessageLoopForIO message_loop_;
+
+ base::ScopedTempDir temp_dir_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ base::WeakPtrFactory<FileSystemURLRequestJobTest> weak_factory_;
+
+ net::URLRequestContext empty_context_;
+
+ // NOTE: order matters, request must die before delegate
+ scoped_ptr<net::TestDelegate> delegate_;
+ scoped_ptr<net::URLRequest> request_;
+
+ scoped_refptr<net::URLRequestJob> pending_job_;
+ static net::URLRequestJob* job_;
+};
+
+// static
+net::URLRequestJob* FileSystemURLRequestJobTest::job_ = NULL;
+
+namespace {
+
+TEST_F(FileSystemURLRequestJobTest, FileTest) {
+ WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
+ TestRequest(CreateFileSystemURL("file1.dat"));
+
+ ASSERT_FALSE(request_->is_pending());
+ EXPECT_EQ(1, delegate_->response_started_count());
+ EXPECT_FALSE(delegate_->received_data_before_response());
+ EXPECT_EQ(kTestFileData, delegate_->data_received());
+ EXPECT_EQ(200, request_->GetResponseCode());
+ std::string cache_control;
+ request_->GetResponseHeaderByName("cache-control", &cache_control);
+ EXPECT_EQ("no-cache", cache_control);
+}
+
+TEST_F(FileSystemURLRequestJobTest, FileTestFullSpecifiedRange) {
+ const size_t buffer_size = 4000;
+ scoped_ptr<char[]> buffer(new char[buffer_size]);
+ FillBuffer(buffer.get(), buffer_size);
+ WriteFile("bigfile", buffer.get(), buffer_size);
+
+ const size_t first_byte_position = 500;
+ const size_t last_byte_position = buffer_size - first_byte_position;
+ std::string partial_buffer_string(buffer.get() + first_byte_position,
+ buffer.get() + last_byte_position + 1);
+
+ net::HttpRequestHeaders headers;
+ headers.SetHeader(
+ net::HttpRequestHeaders::kRange,
+ net::HttpByteRange::Bounded(
+ first_byte_position, last_byte_position).GetHeaderValue());
+ TestRequestWithHeaders(CreateFileSystemURL("bigfile"), &headers);
+
+ ASSERT_FALSE(request_->is_pending());
+ EXPECT_EQ(1, delegate_->response_started_count());
+ EXPECT_FALSE(delegate_->received_data_before_response());
+ EXPECT_TRUE(partial_buffer_string == delegate_->data_received());
+}
+
+TEST_F(FileSystemURLRequestJobTest, FileTestHalfSpecifiedRange) {
+ const size_t buffer_size = 4000;
+ scoped_ptr<char[]> buffer(new char[buffer_size]);
+ FillBuffer(buffer.get(), buffer_size);
+ WriteFile("bigfile", buffer.get(), buffer_size);
+
+ const size_t first_byte_position = 500;
+ std::string partial_buffer_string(buffer.get() + first_byte_position,
+ buffer.get() + buffer_size);
+
+ net::HttpRequestHeaders headers;
+ headers.SetHeader(
+ net::HttpRequestHeaders::kRange,
+ net::HttpByteRange::RightUnbounded(first_byte_position).GetHeaderValue());
+ TestRequestWithHeaders(CreateFileSystemURL("bigfile"), &headers);
+ ASSERT_FALSE(request_->is_pending());
+ EXPECT_EQ(1, delegate_->response_started_count());
+ EXPECT_FALSE(delegate_->received_data_before_response());
+ // Don't use EXPECT_EQ, it will print out a lot of garbage if check failed.
+ EXPECT_TRUE(partial_buffer_string == delegate_->data_received());
+}
+
+
+TEST_F(FileSystemURLRequestJobTest, FileTestMultipleRangesNotSupported) {
+ WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
+ net::HttpRequestHeaders headers;
+ headers.SetHeader(net::HttpRequestHeaders::kRange,
+ "bytes=0-5,10-200,200-300");
+ TestRequestWithHeaders(CreateFileSystemURL("file1.dat"), &headers);
+ EXPECT_TRUE(delegate_->request_failed());
+ EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
+ request_->status().error());
+}
+
+TEST_F(FileSystemURLRequestJobTest, RangeOutOfBounds) {
+ WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
+ net::HttpRequestHeaders headers;
+ headers.SetHeader(
+ net::HttpRequestHeaders::kRange,
+ net::HttpByteRange::Bounded(500, 1000).GetHeaderValue());
+ TestRequestWithHeaders(CreateFileSystemURL("file1.dat"), &headers);
+
+ ASSERT_FALSE(request_->is_pending());
+ EXPECT_TRUE(delegate_->request_failed());
+ EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
+ request_->status().error());
+}
+
+TEST_F(FileSystemURLRequestJobTest, FileDirRedirect) {
+ CreateDirectory("dir");
+ TestRequest(CreateFileSystemURL("dir"));
+
+ EXPECT_EQ(1, delegate_->received_redirect_count());
+ EXPECT_TRUE(request_->status().is_success());
+ EXPECT_FALSE(delegate_->request_failed());
+
+ // We've deferred the redirect; now cancel the request to avoid following it.
+ request_->Cancel();
+ base::MessageLoop::current()->Run();
+}
+
+TEST_F(FileSystemURLRequestJobTest, InvalidURL) {
+ TestRequest(GURL("filesystem:/foo/bar/baz"));
+ ASSERT_FALSE(request_->is_pending());
+ EXPECT_TRUE(delegate_->request_failed());
+ EXPECT_EQ(net::ERR_INVALID_URL, request_->status().error());
+}
+
+TEST_F(FileSystemURLRequestJobTest, NoSuchRoot) {
+ TestRequest(GURL("filesystem:http://remote/persistent/somefile"));
+ ASSERT_FALSE(request_->is_pending());
+ EXPECT_TRUE(delegate_->request_failed());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
+}
+
+TEST_F(FileSystemURLRequestJobTest, NoSuchFile) {
+ TestRequest(CreateFileSystemURL("somefile"));
+ ASSERT_FALSE(request_->is_pending());
+ EXPECT_TRUE(delegate_->request_failed());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
+}
+
+TEST_F(FileSystemURLRequestJobTest, Cancel) {
+ WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
+ TestRequestNoRun(CreateFileSystemURL("file1.dat"));
+
+ // Run StartAsync() and only StartAsync().
+ base::MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release());
+ base::RunLoop().RunUntilIdle();
+ // If we get here, success! we didn't crash!
+}
+
+TEST_F(FileSystemURLRequestJobTest, GetMimeType) {
+ const char kFilename[] = "hoge.html";
+
+ std::string mime_type_direct;
+ base::FilePath::StringType extension =
+ base::FilePath().AppendASCII(kFilename).Extension();
+ if (!extension.empty())
+ extension = extension.substr(1);
+ EXPECT_TRUE(net::GetWellKnownMimeTypeFromExtension(
+ extension, &mime_type_direct));
+
+ TestRequest(CreateFileSystemURL(kFilename));
+
+ std::string mime_type_from_job;
+ request_->GetMimeType(&mime_type_from_job);
+ EXPECT_EQ(mime_type_direct, mime_type_from_job);
+}
+
+TEST_F(FileSystemURLRequestJobTest, Incognito) {
+ WriteFile("file", kTestFileData, arraysize(kTestFileData) - 1);
+
+ // Creates a new filesystem context for incognito mode.
+ scoped_refptr<FileSystemContext> file_system_context =
+ CreateIncognitoFileSystemContextForTesting(NULL, temp_dir_.path());
+
+ // The request should return NOT_FOUND error if it's in incognito mode.
+ TestRequestWithContext(CreateFileSystemURL("file"),
+ file_system_context.get());
+ ASSERT_FALSE(request_->is_pending());
+ EXPECT_TRUE(delegate_->request_failed());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
+
+ // Make sure it returns success with regular (non-incognito) context.
+ TestRequest(CreateFileSystemURL("file"));
+ ASSERT_FALSE(request_->is_pending());
+ EXPECT_EQ(kTestFileData, delegate_->data_received());
+ EXPECT_EQ(200, request_->GetResponseCode());
+}
+
+} // namespace
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/file_writer_delegate_unittest.cc b/chromium/content/browser/fileapi/file_writer_delegate_unittest.cc
new file mode 100644
index 00000000000..c18877f7727
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_writer_delegate_unittest.cc
@@ -0,0 +1,455 @@
+// 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 <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_file_system_context.h"
+#include "net/base/io_buffer.h"
+#include "net/base/request_priority.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_job.h"
+#include "net/url_request/url_request_status.h"
+#include "testing/platform_test.h"
+#include "url/gurl.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_quota_util.h"
+#include "webkit/browser/fileapi/file_writer_delegate.h"
+#include "webkit/browser/fileapi/sandbox_file_stream_writer.h"
+
+namespace fileapi {
+
+namespace {
+
+const GURL kOrigin("http://example.com");
+const FileSystemType kFileSystemType = kFileSystemTypeTest;
+
+const char kData[] = "The quick brown fox jumps over the lazy dog.\n";
+const int kDataSize = ARRAYSIZE_UNSAFE(kData) - 1;
+
+class Result {
+ public:
+ Result()
+ : status_(base::PLATFORM_FILE_OK),
+ bytes_written_(0),
+ write_status_(FileWriterDelegate::SUCCESS_IO_PENDING) {}
+
+ base::PlatformFileError status() const { return status_; }
+ int64 bytes_written() const { return bytes_written_; }
+ FileWriterDelegate::WriteProgressStatus write_status() const {
+ return write_status_;
+ }
+
+ void DidWrite(base::PlatformFileError status, int64 bytes,
+ FileWriterDelegate::WriteProgressStatus write_status) {
+ write_status_ = write_status;
+ if (status == base::PLATFORM_FILE_OK) {
+ bytes_written_ += bytes;
+ if (write_status_ != FileWriterDelegate::SUCCESS_IO_PENDING)
+ base::MessageLoop::current()->Quit();
+ } else {
+ EXPECT_EQ(base::PLATFORM_FILE_OK, status_);
+ status_ = status;
+ base::MessageLoop::current()->Quit();
+ }
+ }
+
+ private:
+ // For post-operation status.
+ base::PlatformFileError status_;
+ int64 bytes_written_;
+ FileWriterDelegate::WriteProgressStatus write_status_;
+};
+
+} // namespace (anonymous)
+
+class FileWriterDelegateTest : public PlatformTest {
+ public:
+ FileWriterDelegateTest() {}
+
+ protected:
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ int64 usage() {
+ return file_system_context_->GetQuotaUtil(kFileSystemType)
+ ->GetOriginUsageOnFileThread(
+ file_system_context_.get(), kOrigin, kFileSystemType);
+ }
+
+ int64 GetFileSizeOnDisk(const char* test_file_path) {
+ // There might be in-flight flush/write.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&base::DoNothing));
+ base::RunLoop().RunUntilIdle();
+
+ FileSystemURL url = GetFileSystemURL(test_file_path);
+ base::PlatformFileInfo file_info;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::GetMetadata(
+ file_system_context_, url, &file_info));
+ return file_info.size;
+ }
+
+ FileSystemURL GetFileSystemURL(const char* file_name) const {
+ return file_system_context_->CreateCrackedFileSystemURL(
+ kOrigin, kFileSystemType, base::FilePath().FromUTF8Unsafe(file_name));
+ }
+
+ FileWriterDelegate* CreateWriterDelegate(
+ const char* test_file_path,
+ int64 offset,
+ int64 allowed_growth) {
+ SandboxFileStreamWriter* writer = new SandboxFileStreamWriter(
+ file_system_context_.get(),
+ GetFileSystemURL(test_file_path),
+ offset,
+ *file_system_context_->GetUpdateObservers(kFileSystemType));
+ writer->set_default_quota(allowed_growth);
+ return new FileWriterDelegate(scoped_ptr<FileStreamWriter>(writer));
+ }
+
+ FileWriterDelegate::DelegateWriteCallback GetWriteCallback(Result* result) {
+ return base::Bind(&Result::DidWrite, base::Unretained(result));
+ }
+
+ // Creates and sets up a FileWriterDelegate for writing the given |blob_url|,
+ // and creates a new FileWriterDelegate for the file.
+ void PrepareForWrite(const char* test_file_path,
+ const GURL& blob_url,
+ int64 offset,
+ int64 allowed_growth) {
+ file_writer_delegate_.reset(
+ CreateWriterDelegate(test_file_path, offset, allowed_growth));
+ request_ = empty_context_.CreateRequest(
+ blob_url, net::DEFAULT_PRIORITY, file_writer_delegate_.get());
+ }
+
+ static net::URLRequest::ProtocolFactory Factory;
+
+ // This should be alive until the very end of this instance.
+ base::MessageLoopForIO loop_;
+
+ scoped_refptr<FileSystemContext> file_system_context_;
+
+ net::URLRequestContext empty_context_;
+ scoped_ptr<FileWriterDelegate> file_writer_delegate_;
+ scoped_ptr<net::URLRequest> request_;
+
+ base::ScopedTempDir dir_;
+
+ static const char* content_;
+};
+
+const char* FileWriterDelegateTest::content_ = NULL;
+
+namespace {
+
+static std::string g_content;
+
+class FileWriterDelegateTestJob : public net::URLRequestJob {
+ public:
+ FileWriterDelegateTestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const std::string& content)
+ : net::URLRequestJob(request, network_delegate),
+ content_(content),
+ remaining_bytes_(content.length()),
+ cursor_(0) {
+ }
+
+ virtual void Start() OVERRIDE {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&FileWriterDelegateTestJob::NotifyHeadersComplete, this));
+ }
+
+ virtual bool ReadRawData(net::IOBuffer* buf,
+ int buf_size,
+ int *bytes_read) OVERRIDE {
+ if (remaining_bytes_ < buf_size)
+ buf_size = static_cast<int>(remaining_bytes_);
+
+ for (int i = 0; i < buf_size; ++i)
+ buf->data()[i] = content_[cursor_++];
+ remaining_bytes_ -= buf_size;
+
+ SetStatus(net::URLRequestStatus());
+ *bytes_read = buf_size;
+ return true;
+ }
+
+ virtual int GetResponseCode() const OVERRIDE {
+ return 200;
+ }
+
+ protected:
+ virtual ~FileWriterDelegateTestJob() {}
+
+ private:
+ std::string content_;
+ int remaining_bytes_;
+ int cursor_;
+};
+
+} // namespace (anonymous)
+
+// static
+net::URLRequestJob* FileWriterDelegateTest::Factory(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const std::string& scheme) {
+ return new FileWriterDelegateTestJob(
+ request, network_delegate, FileWriterDelegateTest::content_);
+}
+
+void FileWriterDelegateTest::SetUp() {
+ ASSERT_TRUE(dir_.CreateUniqueTempDir());
+
+ file_system_context_ = CreateFileSystemContextForTesting(
+ NULL, dir_.path());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::CreateFile(
+ file_system_context_, GetFileSystemURL("test")));
+ net::URLRequest::Deprecated::RegisterProtocolFactory("blob", &Factory);
+}
+
+void FileWriterDelegateTest::TearDown() {
+ net::URLRequest::Deprecated::RegisterProtocolFactory("blob", NULL);
+ file_system_context_ = NULL;
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimit) {
+ const GURL kBlobURL("blob:nolimit");
+ content_ = kData;
+
+ PrepareForWrite("test", kBlobURL, 0, kint64max);
+
+ Result result;
+ ASSERT_EQ(0, usage());
+ file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
+ base::MessageLoop::current()->Run();
+
+ ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
+ file_writer_delegate_.reset();
+
+ ASSERT_EQ(kDataSize, usage());
+ EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
+ EXPECT_EQ(kDataSize, result.bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
+}
+
+TEST_F(FileWriterDelegateTest, WriteSuccessWithJustQuota) {
+ const GURL kBlobURL("blob:just");
+ content_ = kData;
+ const int64 kAllowedGrowth = kDataSize;
+ PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
+
+ Result result;
+ ASSERT_EQ(0, usage());
+ file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
+ base::MessageLoop::current()->Run();
+ ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
+ file_writer_delegate_.reset();
+
+ ASSERT_EQ(kAllowedGrowth, usage());
+ EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
+
+ EXPECT_EQ(kAllowedGrowth, result.bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
+}
+
+TEST_F(FileWriterDelegateTest, DISABLED_WriteFailureByQuota) {
+ const GURL kBlobURL("blob:failure");
+ content_ = kData;
+ const int64 kAllowedGrowth = kDataSize - 1;
+ PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
+
+ Result result;
+ ASSERT_EQ(0, usage());
+ file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
+ base::MessageLoop::current()->Run();
+ ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
+ file_writer_delegate_.reset();
+
+ ASSERT_EQ(kAllowedGrowth, usage());
+ EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
+
+ EXPECT_EQ(kAllowedGrowth, result.bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, result.status());
+ ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
+}
+
+TEST_F(FileWriterDelegateTest, WriteZeroBytesSuccessfullyWithZeroQuota) {
+ const GURL kBlobURL("blob:zero");
+ content_ = "";
+ int64 kAllowedGrowth = 0;
+ PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
+
+ Result result;
+ ASSERT_EQ(0, usage());
+ file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
+ base::MessageLoop::current()->Run();
+ ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
+ file_writer_delegate_.reset();
+
+ ASSERT_EQ(kAllowedGrowth, usage());
+ EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
+
+ EXPECT_EQ(kAllowedGrowth, result.bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
+ ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
+}
+
+TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimitConcurrent) {
+ scoped_ptr<FileWriterDelegate> file_writer_delegate2;
+ scoped_ptr<net::URLRequest> request2;
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::CreateFile(
+ file_system_context_, GetFileSystemURL("test2")));
+
+ const GURL kBlobURL("blob:nolimitconcurrent");
+ const GURL kBlobURL2("blob:nolimitconcurrent2");
+ content_ = kData;
+
+ PrepareForWrite("test", kBlobURL, 0, kint64max);
+
+ // Credate another FileWriterDelegate for concurrent write.
+ file_writer_delegate2.reset(CreateWriterDelegate("test2", 0, kint64max));
+ request2 = empty_context_.CreateRequest(
+ kBlobURL2, net::DEFAULT_PRIORITY, file_writer_delegate2.get());
+
+ Result result, result2;
+ ASSERT_EQ(0, usage());
+ file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
+ file_writer_delegate2->Start(request2.Pass(), GetWriteCallback(&result2));
+ base::MessageLoop::current()->Run();
+ if (result.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING ||
+ result2.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING)
+ base::MessageLoop::current()->Run();
+
+ ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
+ ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result2.write_status());
+ file_writer_delegate_.reset();
+ file_writer_delegate2.reset();
+
+ ASSERT_EQ(kDataSize * 2, usage());
+ EXPECT_EQ(GetFileSizeOnDisk("test") + GetFileSizeOnDisk("test2"), usage());
+
+ EXPECT_EQ(kDataSize, result.bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
+ EXPECT_EQ(kDataSize, result2.bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, result2.status());
+}
+
+TEST_F(FileWriterDelegateTest, WritesWithQuotaAndOffset) {
+ const GURL kBlobURL("blob:failure-with-updated-quota");
+ content_ = kData;
+
+ // Writing kDataSize (=45) bytes data while allowed_growth is 100.
+ int64 offset = 0;
+ int64 allowed_growth = 100;
+ ASSERT_LT(kDataSize, allowed_growth);
+ PrepareForWrite("test", kBlobURL, offset, allowed_growth);
+
+ {
+ Result result;
+ ASSERT_EQ(0, usage());
+ file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
+ base::MessageLoop::current()->Run();
+ ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
+ file_writer_delegate_.reset();
+
+ ASSERT_EQ(kDataSize, usage());
+ EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
+ EXPECT_EQ(kDataSize, result.bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
+ }
+
+ // Trying to overwrite kDataSize bytes data while allowed_growth is 20.
+ offset = 0;
+ allowed_growth = 20;
+ PrepareForWrite("test", kBlobURL, offset, allowed_growth);
+
+ {
+ Result result;
+ file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
+ base::MessageLoop::current()->Run();
+ EXPECT_EQ(kDataSize, usage());
+ EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
+ EXPECT_EQ(kDataSize, result.bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
+ ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
+ }
+
+ // Trying to write kDataSize bytes data from offset 25 while
+ // allowed_growth is 55.
+ offset = 25;
+ allowed_growth = 55;
+ PrepareForWrite("test", kBlobURL, offset, allowed_growth);
+
+ {
+ Result result;
+ file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
+ base::MessageLoop::current()->Run();
+ ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
+ file_writer_delegate_.reset();
+
+ EXPECT_EQ(offset + kDataSize, usage());
+ EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
+ EXPECT_EQ(kDataSize, result.bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
+ }
+
+ // Trying to overwrite 45 bytes data while allowed_growth is -20.
+ offset = 0;
+ allowed_growth = -20;
+ PrepareForWrite("test", kBlobURL, offset, allowed_growth);
+ int64 pre_write_usage = GetFileSizeOnDisk("test");
+
+ {
+ Result result;
+ file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
+ base::MessageLoop::current()->Run();
+ ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
+ file_writer_delegate_.reset();
+
+ EXPECT_EQ(pre_write_usage, usage());
+ EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
+ EXPECT_EQ(kDataSize, result.bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
+ }
+
+ // Trying to overwrite 45 bytes data with offset pre_write_usage - 20,
+ // while allowed_growth is 10.
+ const int kOverlap = 20;
+ offset = pre_write_usage - kOverlap;
+ allowed_growth = 10;
+ PrepareForWrite("test", kBlobURL, offset, allowed_growth);
+
+ {
+ Result result;
+ file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
+ base::MessageLoop::current()->Run();
+ ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
+ file_writer_delegate_.reset();
+
+ EXPECT_EQ(pre_write_usage + allowed_growth, usage());
+ EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
+ EXPECT_EQ(kOverlap + allowed_growth, result.bytes_written());
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, result.status());
+ }
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.cc b/chromium/content/browser/fileapi/fileapi_message_filter.cc
index 1a79ea2d349..b6b89fb50a6 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter.cc
+++ b/chromium/content/browser/fileapi/fileapi_message_filter.cc
@@ -34,7 +34,6 @@
#include "webkit/browser/fileapi/file_permission_policy.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/browser/quota/quota_manager.h"
#include "webkit/common/blob/blob_data.h"
#include "webkit/common/blob/shareable_file_reference.h"
#include "webkit/common/fileapi/directory_entry.h"
@@ -42,17 +41,10 @@
#include "webkit/common/fileapi/file_system_types.h"
#include "webkit/common/fileapi/file_system_util.h"
-#if defined(ENABLE_PLUGINS)
-#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
-#include "ppapi/shared_impl/file_type_conversion.h"
-#endif // defined(ENABLE_PLUGINS)
-
using fileapi::FileSystemFileUtil;
using fileapi::FileSystemBackend;
using fileapi::FileSystemOperation;
using fileapi::FileSystemURL;
-using fileapi::FileUpdateObserver;
-using fileapi::UpdateObserverList;
using webkit_blob::BlobData;
using webkit_blob::BlobStorageContext;
using webkit_blob::BlobStorageHost;
@@ -107,7 +99,6 @@ FileAPIMessageFilter::FileAPIMessageFilter(
void FileAPIMessageFilter::OnChannelConnected(int32 peer_pid) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- BrowserMessageFilter::OnChannelConnected(peer_pid);
if (request_context_getter_.get()) {
DCHECK(!request_context_);
@@ -124,7 +115,6 @@ void FileAPIMessageFilter::OnChannelConnected(int32 peer_pid) {
void FileAPIMessageFilter::OnChannelClosing() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- BrowserMessageFilter::OnChannelClosing();
// Unregister all the blob and stream URLs that are previously registered in
// this process.
@@ -136,22 +126,6 @@ void FileAPIMessageFilter::OnChannelClosing() {
in_transit_snapshot_files_.clear();
- // Close all files that are previously OpenFile()'ed in this process.
- if (!on_close_callbacks_.IsEmpty()) {
- DLOG(INFO)
- << "File API: Renderer process shut down before NotifyCloseFile"
- << " for " << on_close_callbacks_.size() << " files opened in PPAPI";
- }
-
- for (OnCloseCallbackMap::iterator itr(&on_close_callbacks_);
- !itr.IsAtEnd(); itr.Advance()) {
- const base::Closure* callback = itr.GetCurrentValue();
- DCHECK(callback);
- if (!callback->is_null())
- callback->Run();
- }
-
- on_close_callbacks_.Clear();
operation_runner_.reset();
operations_.clear();
}
@@ -168,31 +142,24 @@ bool FileAPIMessageFilter::OnMessageReceived(
*message_was_ok = true;
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(FileAPIMessageFilter, message, *message_was_ok)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_Open, OnOpen)
+ IPC_MESSAGE_HANDLER(FileSystemHostMsg_OpenFileSystem, OnOpenFileSystem)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_ResolveURL, OnResolveURL)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_DeleteFileSystem, OnDeleteFileSystem)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_Move, OnMove)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_Copy, OnCopy)
- IPC_MESSAGE_HANDLER(FileSystemMsg_Remove, OnRemove)
+ IPC_MESSAGE_HANDLER(FileSystemHostMsg_Remove, OnRemove)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_ReadMetadata, OnReadMetadata)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_Create, OnCreate)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_Exists, OnExists)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_ReadDirectory, OnReadDirectory)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_Write, OnWrite)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_WriteDeprecated, OnWriteDeprecated)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_Truncate, OnTruncate)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_TouchFile, OnTouchFile)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_CancelWrite, OnCancel)
-#if defined(ENABLE_PLUGINS)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_OpenPepperFile, OnOpenPepperFile)
-#endif // defined(ENABLE_PLUGINS)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_NotifyCloseFile, OnNotifyCloseFile)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_CreateSnapshotFile,
OnCreateSnapshotFile)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_DidReceiveSnapshotFile,
OnDidReceiveSnapshotFile)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_WillUpdate, OnWillUpdate)
- IPC_MESSAGE_HANDLER(FileSystemHostMsg_DidUpdate, OnDidUpdate)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_SyncGetPlatformPath,
OnSyncGetPlatformPath)
IPC_MESSAGE_HANDLER(BlobHostMsg_StartBuilding, OnStartBuildingBlob)
@@ -208,12 +175,6 @@ bool FileAPIMessageFilter::OnMessageReceived(
IPC_MESSAGE_HANDLER(BlobHostMsg_RegisterPublicURL,
OnRegisterPublicBlobURL)
IPC_MESSAGE_HANDLER(BlobHostMsg_RevokePublicURL, OnRevokePublicBlobURL)
- IPC_MESSAGE_HANDLER(BlobHostMsg_DeprecatedRegisterBlobURL,
- OnDeprecatedRegisterBlobURL)
- IPC_MESSAGE_HANDLER(BlobHostMsg_DeprecatedRevokeBlobURL,
- OnDeprecatedRevokeBlobURL)
- IPC_MESSAGE_HANDLER(BlobHostMsg_DeprecatedCloneBlobURL,
- OnDeprecatedCloneBlobURL)
IPC_MESSAGE_HANDLER(StreamHostMsg_StartBuilding, OnStartBuildingStream)
IPC_MESSAGE_HANDLER(StreamHostMsg_AppendBlobDataItem,
OnAppendBlobDataItemToStream)
@@ -235,19 +196,17 @@ void FileAPIMessageFilter::BadMessageReceived() {
BrowserMessageFilter::BadMessageReceived();
}
-void FileAPIMessageFilter::OnOpen(
- int request_id, const GURL& origin_url, fileapi::FileSystemType type,
- int64 requested_size, bool create) {
+void FileAPIMessageFilter::OnOpenFileSystem(int request_id,
+ const GURL& origin_url,
+ fileapi::FileSystemType type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (type == fileapi::kFileSystemTypeTemporary) {
RecordAction(UserMetricsAction("OpenFileSystemTemporary"));
} else if (type == fileapi::kFileSystemTypePersistent) {
RecordAction(UserMetricsAction("OpenFileSystemPersistent"));
}
- // TODO(kinuko): Use this mode for IPC too.
fileapi::OpenFileSystemMode mode =
- create ? fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT
- : fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT;
+ fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT;
context_->OpenFileSystem(origin_url, type, mode, base::Bind(
&FileAPIMessageFilter::DidOpenFileSystem, this, request_id));
}
@@ -288,7 +247,7 @@ void FileAPIMessageFilter::OnMove(
return;
}
if (!security_policy_->CanReadFileSystemFile(process_id_, src_url) ||
- !security_policy_->CanWriteFileSystemFile(process_id_, src_url) ||
+ !security_policy_->CanDeleteFileSystemFile(process_id_, src_url) ||
!security_policy_->CanCreateFileSystemFile(process_id_, dest_url)) {
Send(new FileSystemMsg_DidFail(request_id,
base::PLATFORM_FILE_ERROR_SECURITY));
@@ -297,6 +256,7 @@ void FileAPIMessageFilter::OnMove(
operations_[request_id] = operation_runner()->Move(
src_url, dest_url,
+ fileapi::FileSystemOperation::OPTION_NONE,
base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
}
@@ -310,7 +270,7 @@ void FileAPIMessageFilter::OnCopy(
return;
}
if (!security_policy_->CanReadFileSystemFile(process_id_, src_url) ||
- !security_policy_->CanCreateFileSystemFile(process_id_, dest_url)) {
+ !security_policy_->CanCopyIntoFileSystemFile(process_id_, dest_url)) {
Send(new FileSystemMsg_DidFail(request_id,
base::PLATFORM_FILE_ERROR_SECURITY));
return;
@@ -318,6 +278,7 @@ void FileAPIMessageFilter::OnCopy(
operations_[request_id] = operation_runner()->Copy(
src_url, dest_url,
+ fileapi::FileSystemOperation::OPTION_NONE,
fileapi::FileSystemOperationRunner::CopyProgressCallback(),
base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
}
@@ -328,7 +289,7 @@ void FileAPIMessageFilter::OnRemove(
FileSystemURL url(context_->CrackURL(path));
if (!ValidateFileSystemURL(request_id, url))
return;
- if (!security_policy_->CanWriteFileSystemFile(process_id_, url)) {
+ if (!security_policy_->CanDeleteFileSystemFile(process_id_, url)) {
Send(new FileSystemMsg_DidFail(request_id,
base::PLATFORM_FILE_ERROR_SECURITY));
return;
@@ -419,16 +380,6 @@ void FileAPIMessageFilter::OnReadDirectory(
this, request_id));
}
-void FileAPIMessageFilter::OnWriteDeprecated(
- int request_id,
- const GURL& path,
- const GURL& blob_url,
- int64 offset) {
- std::string uuid =
- blob_storage_context_->context()->LookupUuidFromDeprecatedURL(blob_url);
- OnWrite(request_id, path, uuid, offset);
-}
-
void FileAPIMessageFilter::OnWrite(
int request_id,
const GURL& path,
@@ -515,84 +466,6 @@ void FileAPIMessageFilter::OnCancel(
}
}
-#if defined(ENABLE_PLUGINS)
-void FileAPIMessageFilter::OnOpenPepperFile(
- int request_id, const GURL& path, int pp_open_flags) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-FileSystemURL url(context_->CrackURL(path));
- if (!ValidateFileSystemURL(request_id, url))
- return;
- if (!CanOpenFileSystemURLWithPepperFlags(pp_open_flags, process_id_, url)) {
- Send(new FileSystemMsg_DidFail(
- request_id, base::PLATFORM_FILE_ERROR_SECURITY));
- return;
- }
-
- quota::QuotaLimitType quota_policy = quota::kQuotaLimitTypeUnknown;
- quota::QuotaManagerProxy* quota_manager_proxy =
- context_->quota_manager_proxy();
- CHECK(quota_manager_proxy);
- CHECK(quota_manager_proxy->quota_manager());
-
- if (quota_manager_proxy->quota_manager()->IsStorageUnlimited(
- url.origin(), FileSystemTypeToQuotaStorageType(url.type()))) {
- quota_policy = quota::kQuotaLimitTypeUnlimited;
- } else {
- quota_policy = quota::kQuotaLimitTypeLimited;
- }
-
- int platform_file_flags = 0;
- if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(pp_open_flags,
- &platform_file_flags)) {
- // |pp_open_flags| should have already been checked in PepperFileIOHost.
- NOTREACHED() << "Open file request with invalid pp_open_flags ignored.";
- }
-
- operations_[request_id] = operation_runner()->OpenFile(
- url, platform_file_flags, PeerHandle(),
- base::Bind(&FileAPIMessageFilter::DidOpenFile, this, request_id,
- quota_policy));
-}
-#endif // defined(ENABLE_PLUGINS)
-
-void FileAPIMessageFilter::OnNotifyCloseFile(int file_open_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- // Remove |file_open_id| from the map of |on_close_callback|s.
- // It must only be called for a ID that is successfully opened and enrolled in
- // DidOpenFile.
- base::Closure* on_close_callback = on_close_callbacks_.Lookup(file_open_id);
- if (on_close_callback && !on_close_callback->is_null()) {
- on_close_callback->Run();
- on_close_callbacks_.Remove(file_open_id);
- }
-}
-
-void FileAPIMessageFilter::OnWillUpdate(const GURL& path) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- FileSystemURL url(context_->CrackURL(path));
- if (!url.is_valid())
- return;
- const UpdateObserverList* observers =
- context_->GetUpdateObservers(url.type());
- if (!observers)
- return;
- observers->Notify(&FileUpdateObserver::OnStartUpdate, MakeTuple(url));
-}
-
-void FileAPIMessageFilter::OnDidUpdate(const GURL& path, int64 delta) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- FileSystemURL url(context_->CrackURL(path));
- if (!url.is_valid())
- return;
- const UpdateObserverList* observers =
- context_->GetUpdateObservers(url.type());
- if (!observers)
- return;
- observers->Notify(&FileUpdateObserver::OnUpdate, MakeTuple(url, delta));
- observers->Notify(&FileUpdateObserver::OnEndUpdate, MakeTuple(url));
-}
-
void FileAPIMessageFilter::OnSyncGetPlatformPath(
const GURL& path, base::FilePath* platform_path) {
SyncGetPlatformPath(context_, process_id_, path, platform_path);
@@ -706,23 +579,6 @@ void FileAPIMessageFilter::OnRevokePublicBlobURL(const GURL& public_url) {
ignore_result(blob_storage_host_->RevokePublicBlobURL(public_url));
}
-void FileAPIMessageFilter::OnDeprecatedRegisterBlobURL(
- const GURL& url, const std::string& uuid) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- blob_storage_host_->DeprecatedRegisterBlobURL(url, uuid);
-}
-
-void FileAPIMessageFilter::OnDeprecatedCloneBlobURL(
- const GURL& url, const GURL& src_url) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- blob_storage_host_->DeprecatedCloneBlobURL(url, src_url);
-}
-
-void FileAPIMessageFilter::OnDeprecatedRevokeBlobURL(const GURL& url) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- blob_storage_host_->DeprecatedRevokeBlobURL(url);
-}
-
void FileAPIMessageFilter::OnStartBuildingStream(
const GURL& url, const std::string& content_type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -851,31 +707,6 @@ void FileAPIMessageFilter::DidReadDirectory(
operations_.erase(request_id);
}
-void FileAPIMessageFilter::DidOpenFile(int request_id,
- quota::QuotaLimitType quota_policy,
- base::PlatformFileError result,
- base::PlatformFile file,
- const base::Closure& on_close_callback,
- base::ProcessHandle peer_handle) {
- if (result == base::PLATFORM_FILE_OK) {
- IPC::PlatformFileForTransit file_for_transit =
- file != base::kInvalidPlatformFileValue ?
- IPC::GetFileHandleForProcess(file, peer_handle, true) :
- IPC::InvalidPlatformFileForTransit();
- int file_open_id = on_close_callbacks_.Add(
- new base::Closure(on_close_callback));
-
- Send(new FileSystemMsg_DidOpenFile(request_id,
- file_for_transit,
- file_open_id,
- quota_policy));
- } else {
- Send(new FileSystemMsg_DidFail(request_id,
- result));
- }
- operations_.erase(request_id);
-}
-
void FileAPIMessageFilter::DidWrite(int request_id,
base::PlatformFileError result,
int64 bytes,
@@ -891,9 +722,9 @@ void FileAPIMessageFilter::DidWrite(int request_id,
}
void FileAPIMessageFilter::DidOpenFileSystem(int request_id,
- base::PlatformFileError result,
+ const GURL& root,
const std::string& filesystem_name,
- const GURL& root) {
+ base::PlatformFileError result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (result == base::PLATFORM_FILE_OK) {
DCHECK(root.is_valid());
@@ -983,11 +814,22 @@ void FileAPIMessageFilter::DidCreateSnapshot(
bool FileAPIMessageFilter::ValidateFileSystemURL(
int request_id, const fileapi::FileSystemURL& url) {
- if (FileSystemURLIsValid(context_, url))
- return true;
- Send(new FileSystemMsg_DidFail(request_id,
- base::PLATFORM_FILE_ERROR_INVALID_URL));
- return false;
+ if (!FileSystemURLIsValid(context_, url)) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_INVALID_URL));
+ return false;
+ }
+
+ // Deny access to files in PluginPrivate FileSystem from JavaScript.
+ // TODO(nhiroki): Move this filter somewhere else since this is not for
+ // validation.
+ if (url.type() == fileapi::kFileSystemTypePluginPrivate) {
+ Send(new FileSystemMsg_DidFail(request_id,
+ base::PLATFORM_FILE_ERROR_SECURITY));
+ return false;
+ }
+
+ return true;
}
scoped_refptr<Stream> FileAPIMessageFilter::GetStreamForURL(const GURL& url) {
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.h b/chromium/content/browser/fileapi/fileapi_message_filter.h
index e9a707f4ac4..d734e85d217 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter.h
+++ b/chromium/content/browser/fileapi/fileapi_message_filter.h
@@ -12,7 +12,6 @@
#include "base/callback.h"
#include "base/containers/hash_tables.h"
#include "base/files/file_util_proxy.h"
-#include "base/id_map.h"
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
#include "base/platform_file.h"
@@ -89,11 +88,9 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
private:
typedef fileapi::FileSystemOperationRunner::OperationID OperationID;
- void OnOpen(int request_id,
- const GURL& origin_url,
- fileapi::FileSystemType type,
- int64 requested_size,
- bool create);
+ void OnOpenFileSystem(int request_id,
+ const GURL& origin_url,
+ fileapi::FileSystemType type);
void OnResolveURL(int request_id,
const GURL& filesystem_url);
void OnDeleteFileSystem(int request_id,
@@ -118,23 +115,12 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
const GURL& path,
const std::string& blob_uuid,
int64 offset);
- void OnWriteDeprecated(
- int request_id,
- const GURL& path,
- const GURL& blob_url,
- int64 offset);
void OnTruncate(int request_id, const GURL& path, int64 length);
void OnTouchFile(int request_id,
const GURL& path,
const base::Time& last_access_time,
const base::Time& last_modified_time);
void OnCancel(int request_id, int request_to_cancel);
-#if defined(ENABLE_PLUGINS)
- void OnOpenPepperFile(int request_id, const GURL& path, int pp_open_flags);
-#endif // defined(ENABLE_PLUGINS)
- void OnNotifyCloseFile(int file_open_id);
- void OnWillUpdate(const GURL& path);
- void OnDidUpdate(const GURL& path, int64 delta);
void OnSyncGetPlatformPath(const GURL& path,
base::FilePath* platform_path);
void OnCreateSnapshotFile(int request_id,
@@ -157,13 +143,6 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
void OnRegisterPublicBlobURL(const GURL& public_url, const std::string& uuid);
void OnRevokePublicBlobURL(const GURL& public_url);
- // Extra methods to establish a mapping from old-style blobURLs to uuids,
- // and to clone them. These won't be here for long, just during a
- // transition period. See crbug/174200
- void OnDeprecatedRegisterBlobURL(const GURL& url, const std::string& uuid);
- void OnDeprecatedCloneBlobURL(const GURL& url, const GURL& existing_url);
- void OnDeprecatedRevokeBlobURL(const GURL& url);
-
// Handlers for StreamHostMsg_ family messages.
//
// TODO(tyoshino): Consider renaming BlobData to more generic one as it's now
@@ -192,20 +171,14 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
base::PlatformFileError result,
const std::vector<fileapi::DirectoryEntry>& entries,
bool has_more);
- void DidOpenFile(int request_id,
- quota::QuotaLimitType quota_policy,
- base::PlatformFileError result,
- base::PlatformFile file,
- const base::Closure& on_close_callback,
- base::ProcessHandle peer_handle);
void DidWrite(int request_id,
base::PlatformFileError result,
int64 bytes,
bool complete);
void DidOpenFileSystem(int request_id,
- base::PlatformFileError result,
+ const GURL& root,
const std::string& filesystem_name,
- const GURL& root);
+ base::PlatformFileError result);
void DidResolveURL(int request_id,
base::PlatformFileError result,
const fileapi::FileSystemInfo& info,
@@ -266,11 +239,6 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
std::map<int, scoped_refptr<webkit_blob::ShareableFileReference> >
in_transit_snapshot_files_;
- // Keep track of file system file opened by OpenFile() in this process.
- // Need to close all of them when the renderer process dies.
- typedef IDMap<base::Closure, IDMapOwnPointer> OnCloseCallbackMap;
- OnCloseCallbackMap on_close_callbacks_;
-
DISALLOW_COPY_AND_ASSIGN(FileAPIMessageFilter);
};
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
index 90e422c7da6..3dbdcc3d538 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
+++ b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
@@ -21,11 +21,11 @@
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_file_system_context.h"
#include "net/base/io_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/browser/blob/blob_storage_context.h"
#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
#include "webkit/common/blob/blob_data.h"
namespace content {
@@ -76,12 +76,10 @@ class FileAPIMessageFilterTest : public testing::Test {
}
// Tests via OnMessageReceived(const IPC::Message&). The channel proxy calls
- // this method. Since OnMessageReceived is hidden on FileAPIMessageFilter,
- // we need to cast it.
+ // this method.
bool InvokeOnMessageReceived(const IPC::Message& message) {
- IPC::ChannelProxy::MessageFilter* casted_filter =
- static_cast<IPC::ChannelProxy::MessageFilter*>(filter_.get());
- return casted_filter->OnMessageReceived(message);
+ bool message_was_ok;
+ return filter_->OnMessageReceived(message, &message_was_ok);
}
base::MessageLoop message_loop_;
@@ -108,13 +106,11 @@ TEST_F(FileAPIMessageFilterTest, CloseChannelWithInflightRequest) {
// Complete initialization.
message_loop_.RunUntilIdle();
- IPC::ChannelProxy::MessageFilter* casted_filter =
- static_cast<IPC::ChannelProxy::MessageFilter*>(filter.get());
-
int request_id = 0;
const GURL kUrl("filesystem:http://example.com/temporary/foo");
FileSystemHostMsg_ReadMetadata read_metadata(request_id++, kUrl);
- EXPECT_TRUE(casted_filter->OnMessageReceived(read_metadata));
+ bool message_was_ok;
+ EXPECT_TRUE(filter->OnMessageReceived(read_metadata, &message_was_ok));
// Close the filter while it has inflight request.
filter->OnChannelClosing();
@@ -144,13 +140,11 @@ TEST_F(FileAPIMessageFilterTest, MultipleFilters) {
// Complete initialization.
message_loop_.RunUntilIdle();
- IPC::ChannelProxy::MessageFilter* casted_filter =
- static_cast<IPC::ChannelProxy::MessageFilter*>(filter1.get());
-
int request_id = 0;
const GURL kUrl("filesystem:http://example.com/temporary/foo");
FileSystemHostMsg_ReadMetadata read_metadata(request_id++, kUrl);
- EXPECT_TRUE(casted_filter->OnMessageReceived(read_metadata));
+ bool message_was_ok;
+ EXPECT_TRUE(filter1->OnMessageReceived(read_metadata, &message_was_ok));
// Close the other filter before the request for filter1 is processed.
filter2->OnChannelClosing();
@@ -251,8 +245,7 @@ TEST_F(FileAPIMessageFilterTest, BuildStreamWithSharedMemory) {
// OnAppendSharedMemoryToStream passes the peer process's handle to
// SharedMemory's constructor. If it's incorrect, DuplicateHandle won't work
// correctly.
- static_cast<IPC::ChannelProxy::MessageFilter*>(
- filter_.get())->OnChannelConnected(base::Process::Current().pid());
+ filter_->set_peer_pid_for_testing(base::Process::Current().pid());
StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
EXPECT_TRUE(InvokeOnMessageReceived(start_message));
diff --git a/chromium/content/browser/fileapi/local_file_util_unittest.cc b/chromium/content/browser/fileapi/local_file_util_unittest.cc
new file mode 100644
index 00000000000..40995d69310
--- /dev/null
+++ b/chromium/content/browser/fileapi/local_file_util_unittest.cc
@@ -0,0 +1,388 @@
+// 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 <string>
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/platform_file.h"
+#include "base/run_loop.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/test/test_file_system_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/async_file_util_adapter.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_file_util.h"
+#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/local_file_util.h"
+#include "webkit/browser/fileapi/native_file_util.h"
+#include "webkit/common/fileapi/file_system_types.h"
+
+namespace fileapi {
+
+namespace {
+
+const GURL kOrigin("http://foo/");
+const FileSystemType kFileSystemType = kFileSystemTypeTest;
+
+} // namespace
+
+class LocalFileUtilTest : public testing::Test {
+ public:
+ LocalFileUtilTest() {}
+
+ virtual void SetUp() {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+ file_system_context_ = CreateFileSystemContextForTesting(
+ NULL, data_dir_.path());
+ }
+
+ virtual void TearDown() {
+ file_system_context_ = NULL;
+ base::RunLoop().RunUntilIdle();
+ }
+
+ protected:
+ FileSystemOperationContext* NewContext() {
+ FileSystemOperationContext* context =
+ new FileSystemOperationContext(file_system_context_.get());
+ context->set_update_observers(
+ *file_system_context_->GetUpdateObservers(kFileSystemType));
+ return context;
+ }
+
+ LocalFileUtil* file_util() {
+ AsyncFileUtilAdapter* adapter = static_cast<AsyncFileUtilAdapter*>(
+ file_system_context_->GetAsyncFileUtil(kFileSystemType));
+ return static_cast<LocalFileUtil*>(adapter->sync_file_util());
+ }
+
+ FileSystemURL CreateURL(const std::string& file_name) {
+ return file_system_context_->CreateCrackedFileSystemURL(
+ kOrigin, kFileSystemType, base::FilePath().FromUTF8Unsafe(file_name));
+ }
+
+ base::FilePath LocalPath(const char *file_name) {
+ base::FilePath path;
+ scoped_ptr<FileSystemOperationContext> context(NewContext());
+ file_util()->GetLocalFilePath(context.get(), CreateURL(file_name), &path);
+ return path;
+ }
+
+ bool FileExists(const char *file_name) {
+ return base::PathExists(LocalPath(file_name)) &&
+ !base::DirectoryExists(LocalPath(file_name));
+ }
+
+ bool DirectoryExists(const char *file_name) {
+ return base::DirectoryExists(LocalPath(file_name));
+ }
+
+ int64 GetSize(const char *file_name) {
+ base::PlatformFileInfo info;
+ base::GetFileInfo(LocalPath(file_name), &info);
+ return info.size;
+ }
+
+ base::PlatformFileError CreateFile(const char* file_name,
+ base::PlatformFile* file_handle,
+ bool* created) {
+ int file_flags = base::PLATFORM_FILE_CREATE |
+ base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC;
+
+ scoped_ptr<FileSystemOperationContext> context(NewContext());
+ return file_util()->CreateOrOpen(
+ context.get(),
+ CreateURL(file_name),
+ file_flags, file_handle, created);
+ }
+
+ base::PlatformFileError EnsureFileExists(const char* file_name,
+ bool* created) {
+ scoped_ptr<FileSystemOperationContext> context(NewContext());
+ return file_util()->EnsureFileExists(
+ context.get(),
+ CreateURL(file_name), created);
+ }
+
+ FileSystemContext* file_system_context() {
+ return file_system_context_.get();
+ }
+
+ private:
+ base::MessageLoop message_loop_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ base::ScopedTempDir data_dir_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocalFileUtilTest);
+};
+
+TEST_F(LocalFileUtilTest, CreateAndClose) {
+ const char *file_name = "test_file";
+ base::PlatformFile file_handle;
+ bool created;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ CreateFile(file_name, &file_handle, &created));
+ ASSERT_TRUE(created);
+
+ EXPECT_TRUE(FileExists(file_name));
+ EXPECT_EQ(0, GetSize(file_name));
+
+ scoped_ptr<FileSystemOperationContext> context(NewContext());
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Close(context.get(), file_handle));
+}
+
+// base::CreateSymbolicLink is only supported on POSIX.
+#if defined(OS_POSIX)
+TEST_F(LocalFileUtilTest, CreateFailForSymlink) {
+ // Create symlink target file.
+ const char *target_name = "symlink_target";
+ base::PlatformFile target_handle;
+ bool symlink_target_created = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ CreateFile(target_name, &target_handle, &symlink_target_created));
+ ASSERT_TRUE(symlink_target_created);
+ base::FilePath target_path = LocalPath(target_name);
+
+ // Create symlink where target must be real file.
+ const char *symlink_name = "symlink_file";
+ base::FilePath symlink_path = LocalPath(symlink_name);
+ ASSERT_TRUE(base::CreateSymbolicLink(target_path, symlink_path));
+ ASSERT_TRUE(FileExists(symlink_name));
+
+ // Try to open the symlink file which should fail.
+ scoped_ptr<FileSystemOperationContext> context(NewContext());
+ FileSystemURL url = CreateURL(symlink_name);
+ int file_flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
+ base::PlatformFile file_handle;
+ bool created = false;
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, file_util()->CreateOrOpen(
+ context.get(), url, file_flags, &file_handle, &created));
+ EXPECT_FALSE(created);
+}
+#endif
+
+TEST_F(LocalFileUtilTest, EnsureFileExists) {
+ const char *file_name = "foobar";
+ bool created;
+ ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(file_name, &created));
+ ASSERT_TRUE(created);
+
+ EXPECT_TRUE(FileExists(file_name));
+ EXPECT_EQ(0, GetSize(file_name));
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(file_name, &created));
+ EXPECT_FALSE(created);
+}
+
+TEST_F(LocalFileUtilTest, TouchFile) {
+ const char *file_name = "test_file";
+ base::PlatformFile file_handle;
+ bool created;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ CreateFile(file_name, &file_handle, &created));
+ ASSERT_TRUE(created);
+
+ scoped_ptr<FileSystemOperationContext> context(NewContext());
+
+ base::PlatformFileInfo info;
+ ASSERT_TRUE(base::GetFileInfo(LocalPath(file_name), &info));
+ const base::Time new_accessed =
+ info.last_accessed + base::TimeDelta::FromHours(10);
+ const base::Time new_modified =
+ info.last_modified + base::TimeDelta::FromHours(5);
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Touch(context.get(), CreateURL(file_name),
+ new_accessed, new_modified));
+
+ ASSERT_TRUE(base::GetFileInfo(LocalPath(file_name), &info));
+ EXPECT_EQ(new_accessed, info.last_accessed);
+ EXPECT_EQ(new_modified, info.last_modified);
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Close(context.get(), file_handle));
+}
+
+TEST_F(LocalFileUtilTest, TouchDirectory) {
+ const char *dir_name = "test_dir";
+ scoped_ptr<FileSystemOperationContext> context(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->CreateDirectory(context.get(),
+ CreateURL(dir_name),
+ false /* exclusive */,
+ false /* recursive */));
+
+ base::PlatformFileInfo info;
+ ASSERT_TRUE(base::GetFileInfo(LocalPath(dir_name), &info));
+ const base::Time new_accessed =
+ info.last_accessed + base::TimeDelta::FromHours(10);
+ const base::Time new_modified =
+ info.last_modified + base::TimeDelta::FromHours(5);
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Touch(context.get(), CreateURL(dir_name),
+ new_accessed, new_modified));
+
+ ASSERT_TRUE(base::GetFileInfo(LocalPath(dir_name), &info));
+ EXPECT_EQ(new_accessed, info.last_accessed);
+ EXPECT_EQ(new_modified, info.last_modified);
+}
+
+TEST_F(LocalFileUtilTest, Truncate) {
+ const char *file_name = "truncated";
+ bool created;
+ ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(file_name, &created));
+ ASSERT_TRUE(created);
+
+ scoped_ptr<FileSystemOperationContext> context;
+
+ context.reset(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Truncate(context.get(), CreateURL(file_name), 1020));
+
+ EXPECT_TRUE(FileExists(file_name));
+ EXPECT_EQ(1020, GetSize(file_name));
+}
+
+TEST_F(LocalFileUtilTest, CopyFile) {
+ const char *from_file = "fromfile";
+ const char *to_file1 = "tofile1";
+ const char *to_file2 = "tofile2";
+ bool created;
+ ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created));
+ ASSERT_TRUE(created);
+
+ scoped_ptr<FileSystemOperationContext> context;
+ context.reset(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
+
+ EXPECT_TRUE(FileExists(from_file));
+ EXPECT_EQ(1020, GetSize(from_file));
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::Copy(file_system_context(),
+ CreateURL(from_file),
+ CreateURL(to_file1)));
+
+ context.reset(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::Copy(file_system_context(),
+ CreateURL(from_file),
+ CreateURL(to_file2)));
+
+ EXPECT_TRUE(FileExists(from_file));
+ EXPECT_EQ(1020, GetSize(from_file));
+ EXPECT_TRUE(FileExists(to_file1));
+ EXPECT_EQ(1020, GetSize(to_file1));
+ EXPECT_TRUE(FileExists(to_file2));
+ EXPECT_EQ(1020, GetSize(to_file2));
+}
+
+TEST_F(LocalFileUtilTest, CopyDirectory) {
+ const char *from_dir = "fromdir";
+ const char *from_file = "fromdir/fromfile";
+ const char *to_dir = "todir";
+ const char *to_file = "todir/fromfile";
+ bool created;
+ scoped_ptr<FileSystemOperationContext> context;
+
+ context.reset(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->CreateDirectory(context.get(), CreateURL(from_dir),
+ false, false));
+ ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created));
+ ASSERT_TRUE(created);
+
+ context.reset(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
+
+ EXPECT_TRUE(DirectoryExists(from_dir));
+ EXPECT_TRUE(FileExists(from_file));
+ EXPECT_EQ(1020, GetSize(from_file));
+ EXPECT_FALSE(DirectoryExists(to_dir));
+
+ context.reset(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::Copy(file_system_context(),
+ CreateURL(from_dir), CreateURL(to_dir)));
+
+ EXPECT_TRUE(DirectoryExists(from_dir));
+ EXPECT_TRUE(FileExists(from_file));
+ EXPECT_EQ(1020, GetSize(from_file));
+ EXPECT_TRUE(DirectoryExists(to_dir));
+ EXPECT_TRUE(FileExists(to_file));
+ EXPECT_EQ(1020, GetSize(to_file));
+}
+
+TEST_F(LocalFileUtilTest, MoveFile) {
+ const char *from_file = "fromfile";
+ const char *to_file = "tofile";
+ bool created;
+ ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created));
+ ASSERT_TRUE(created);
+ scoped_ptr<FileSystemOperationContext> context;
+
+ context.reset(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
+
+ EXPECT_TRUE(FileExists(from_file));
+ EXPECT_EQ(1020, GetSize(from_file));
+
+ context.reset(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::Move(file_system_context(),
+ CreateURL(from_file),
+ CreateURL(to_file)));
+
+ EXPECT_FALSE(FileExists(from_file));
+ EXPECT_TRUE(FileExists(to_file));
+ EXPECT_EQ(1020, GetSize(to_file));
+}
+
+TEST_F(LocalFileUtilTest, MoveDirectory) {
+ const char *from_dir = "fromdir";
+ const char *from_file = "fromdir/fromfile";
+ const char *to_dir = "todir";
+ const char *to_file = "todir/fromfile";
+ bool created;
+ scoped_ptr<FileSystemOperationContext> context;
+
+ context.reset(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->CreateDirectory(context.get(), CreateURL(from_dir),
+ false, false));
+ ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created));
+ ASSERT_TRUE(created);
+
+ context.reset(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
+
+ EXPECT_TRUE(DirectoryExists(from_dir));
+ EXPECT_TRUE(FileExists(from_file));
+ EXPECT_EQ(1020, GetSize(from_file));
+ EXPECT_FALSE(DirectoryExists(to_dir));
+
+ context.reset(NewContext());
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::Move(file_system_context(),
+ CreateURL(from_dir),
+ CreateURL(to_dir)));
+
+ EXPECT_FALSE(DirectoryExists(from_dir));
+ EXPECT_TRUE(DirectoryExists(to_dir));
+ EXPECT_TRUE(FileExists(to_file));
+ EXPECT_EQ(1020, GetSize(to_file));
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc b/chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc
new file mode 100644
index 00000000000..72dd36008dd
--- /dev/null
+++ b/chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc
@@ -0,0 +1,2490 @@
+// 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 <set>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/platform_file.h"
+#include "base/run_loop.h"
+#include "content/public/test/sandbox_file_system_test_helper.h"
+#include "content/public/test/test_file_system_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+#include "webkit/browser/fileapi/file_system_backend.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/file_system_usage_cache.h"
+#include "webkit/browser/fileapi/mock_file_change_observer.h"
+#include "webkit/browser/fileapi/obfuscated_file_util.h"
+#include "webkit/browser/fileapi/sandbox_directory_database.h"
+#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
+#include "webkit/browser/fileapi/sandbox_isolated_origin_database.h"
+#include "webkit/browser/fileapi/sandbox_origin_database.h"
+#include "webkit/browser/fileapi/test_file_set.h"
+#include "webkit/browser/quota/mock_special_storage_policy.h"
+#include "webkit/browser/quota/quota_manager.h"
+#include "webkit/common/database/database_identifier.h"
+#include "webkit/common/quota/quota_types.h"
+
+namespace fileapi {
+
+namespace {
+
+bool FileExists(const base::FilePath& path) {
+ return base::PathExists(path) && !base::DirectoryExists(path);
+}
+
+int64 GetSize(const base::FilePath& path) {
+ int64 size;
+ EXPECT_TRUE(base::GetFileSize(path, &size));
+ return size;
+}
+
+// After a move, the dest exists and the source doesn't.
+// After a copy, both source and dest exist.
+struct CopyMoveTestCaseRecord {
+ bool is_copy_not_move;
+ const char source_path[64];
+ const char dest_path[64];
+ bool cause_overwrite;
+};
+
+const CopyMoveTestCaseRecord kCopyMoveTestCases[] = {
+ // This is the combinatoric set of:
+ // rename vs. same-name
+ // different directory vs. same directory
+ // overwrite vs. no-overwrite
+ // copy vs. move
+ // We can never be called with source and destination paths identical, so
+ // those cases are omitted.
+ {true, "dir0/file0", "dir0/file1", false},
+ {false, "dir0/file0", "dir0/file1", false},
+ {true, "dir0/file0", "dir0/file1", true},
+ {false, "dir0/file0", "dir0/file1", true},
+
+ {true, "dir0/file0", "dir1/file0", false},
+ {false, "dir0/file0", "dir1/file0", false},
+ {true, "dir0/file0", "dir1/file0", true},
+ {false, "dir0/file0", "dir1/file0", true},
+ {true, "dir0/file0", "dir1/file1", false},
+ {false, "dir0/file0", "dir1/file1", false},
+ {true, "dir0/file0", "dir1/file1", true},
+ {false, "dir0/file0", "dir1/file1", true},
+};
+
+struct OriginEnumerationTestRecord {
+ std::string origin_url;
+ bool has_temporary;
+ bool has_persistent;
+};
+
+const OriginEnumerationTestRecord kOriginEnumerationTestRecords[] = {
+ {"http://example.com", false, true},
+ {"http://example1.com", true, false},
+ {"https://example1.com", true, true},
+ {"file://", false, true},
+ {"http://example.com:8000", false, true},
+};
+
+FileSystemURL FileSystemURLAppend(
+ const FileSystemURL& url, const base::FilePath::StringType& child) {
+ return FileSystemURL::CreateForTest(
+ url.origin(), url.mount_type(), url.virtual_path().Append(child));
+}
+
+FileSystemURL FileSystemURLAppendUTF8(
+ const FileSystemURL& url, const std::string& child) {
+ return FileSystemURL::CreateForTest(
+ url.origin(),
+ url.mount_type(),
+ url.virtual_path().Append(base::FilePath::FromUTF8Unsafe(child)));
+}
+
+FileSystemURL FileSystemURLDirName(const FileSystemURL& url) {
+ return FileSystemURL::CreateForTest(
+ url.origin(), url.mount_type(), VirtualPath::DirName(url.virtual_path()));
+}
+
+std::string GetTypeString(FileSystemType type) {
+ return SandboxFileSystemBackendDelegate::GetTypeString(type);
+}
+
+bool HasFileSystemType(
+ ObfuscatedFileUtil::AbstractOriginEnumerator* enumerator,
+ FileSystemType type) {
+ return enumerator->HasTypeDirectory(GetTypeString(type));
+}
+
+} // namespace
+
+// TODO(ericu): The vast majority of this and the other FSFU subclass tests
+// could theoretically be shared. It would basically be a FSFU interface
+// compliance test, and only the subclass-specific bits that look into the
+// implementation would need to be written per-subclass.
+class ObfuscatedFileUtilTest : public testing::Test {
+ public:
+ ObfuscatedFileUtilTest()
+ : origin_(GURL("http://www.example.com")),
+ type_(kFileSystemTypeTemporary),
+ weak_factory_(this),
+ sandbox_file_system_(origin_, type_),
+ quota_status_(quota::kQuotaStatusUnknown),
+ usage_(-1) {
+ }
+
+ virtual void SetUp() {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+
+ storage_policy_ = new quota::MockSpecialStoragePolicy();
+
+ quota_manager_ =
+ new quota::QuotaManager(false /* is_incognito */,
+ data_dir_.path(),
+ base::MessageLoopProxy::current().get(),
+ base::MessageLoopProxy::current().get(),
+ storage_policy_.get());
+
+ // Every time we create a new sandbox_file_system helper,
+ // it creates another context, which creates another path manager,
+ // another sandbox_backend, and another OFU.
+ // We need to pass in the context to skip all that.
+ file_system_context_ = CreateFileSystemContextForTesting(
+ quota_manager_->proxy(),
+ data_dir_.path());
+
+ sandbox_file_system_.SetUp(file_system_context_.get());
+
+ change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
+ }
+
+ virtual void TearDown() {
+ quota_manager_ = NULL;
+ sandbox_file_system_.TearDown();
+ }
+
+ scoped_ptr<FileSystemOperationContext> LimitedContext(
+ int64 allowed_bytes_growth) {
+ scoped_ptr<FileSystemOperationContext> context(
+ sandbox_file_system_.NewOperationContext());
+ context->set_allowed_bytes_growth(allowed_bytes_growth);
+ return context.Pass();
+ }
+
+ scoped_ptr<FileSystemOperationContext> UnlimitedContext() {
+ return LimitedContext(kint64max);
+ }
+
+ FileSystemOperationContext* NewContext(
+ SandboxFileSystemTestHelper* file_system) {
+ change_observer()->ResetCount();
+ FileSystemOperationContext* context;
+ if (file_system)
+ context = file_system->NewOperationContext();
+ else
+ context = sandbox_file_system_.NewOperationContext();
+ // Setting allowed_bytes_growth big enough for all tests.
+ context->set_allowed_bytes_growth(1024 * 1024);
+ context->set_change_observers(change_observers());
+ return context;
+ }
+
+ const ChangeObserverList& change_observers() const {
+ return change_observers_;
+ }
+
+ MockFileChangeObserver* change_observer() {
+ return &change_observer_;
+ }
+
+ // This can only be used after SetUp has run and created file_system_context_
+ // and obfuscated_file_util_.
+ // Use this for tests which need to run in multiple origins; we need a test
+ // helper per origin.
+ SandboxFileSystemTestHelper* NewFileSystem(
+ const GURL& origin, fileapi::FileSystemType type) {
+ SandboxFileSystemTestHelper* file_system =
+ new SandboxFileSystemTestHelper(origin, type);
+
+ file_system->SetUp(file_system_context_.get());
+ return file_system;
+ }
+
+ ObfuscatedFileUtil* ofu() {
+ return static_cast<ObfuscatedFileUtil*>(sandbox_file_system_.file_util());
+ }
+
+ const base::FilePath& test_directory() const {
+ return data_dir_.path();
+ }
+
+ const GURL& origin() const {
+ return origin_;
+ }
+
+ fileapi::FileSystemType type() const {
+ return type_;
+ }
+
+ std::string type_string() const {
+ return GetTypeString(type_);
+ }
+
+ int64 ComputeTotalFileSize() {
+ return sandbox_file_system_.ComputeCurrentOriginUsage() -
+ sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
+ }
+
+ void GetUsageFromQuotaManager() {
+ int64 quota = -1;
+ quota_status_ =
+ AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(),
+ origin(),
+ sandbox_file_system_.type(),
+ &usage_,
+ &quota);
+ EXPECT_EQ(quota::kQuotaStatusOk, quota_status_);
+ }
+
+ void RevokeUsageCache() {
+ quota_manager_->ResetUsageTracker(sandbox_file_system_.storage_type());
+ usage_cache()->Delete(sandbox_file_system_.GetUsageCachePath());
+ }
+
+ int64 SizeByQuotaUtil() {
+ return sandbox_file_system_.GetCachedOriginUsage();
+ }
+
+ int64 SizeInUsageFile() {
+ base::RunLoop().RunUntilIdle();
+ int64 usage = 0;
+ return usage_cache()->GetUsage(
+ sandbox_file_system_.GetUsageCachePath(), &usage) ? usage : -1;
+ }
+
+ bool PathExists(const FileSystemURL& url) {
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ base::PlatformFileInfo file_info;
+ base::FilePath platform_path;
+ base::PlatformFileError error = ofu()->GetFileInfo(
+ context.get(), url, &file_info, &platform_path);
+ return error == base::PLATFORM_FILE_OK;
+ }
+
+ bool DirectoryExists(const FileSystemURL& url) {
+ return AsyncFileTestHelper::DirectoryExists(file_system_context(), url);
+ }
+
+ int64 usage() const { return usage_; }
+ FileSystemUsageCache* usage_cache() {
+ return sandbox_file_system_.usage_cache();
+ }
+
+ FileSystemURL CreateURLFromUTF8(const std::string& path) {
+ return sandbox_file_system_.CreateURLFromUTF8(path);
+ }
+
+ int64 PathCost(const FileSystemURL& url) {
+ return ObfuscatedFileUtil::ComputeFilePathCost(url.path());
+ }
+
+ FileSystemURL CreateURL(const base::FilePath& path) {
+ return sandbox_file_system_.CreateURL(path);
+ }
+
+ void CheckFileAndCloseHandle(
+ const FileSystemURL& url, base::PlatformFile file_handle) {
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ base::FilePath local_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
+ context.get(), url, &local_path));
+
+ base::PlatformFileInfo file_info0;
+ base::FilePath data_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
+ context.get(), url, &file_info0, &data_path));
+ EXPECT_EQ(data_path, local_path);
+ EXPECT_TRUE(FileExists(data_path));
+ EXPECT_EQ(0, GetSize(data_path));
+
+ const char data[] = "test data";
+ const int length = arraysize(data) - 1;
+
+ if (base::kInvalidPlatformFileValue == file_handle) {
+ bool created = true;
+ base::PlatformFileError error;
+ file_handle = base::CreatePlatformFile(
+ data_path,
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
+ &created,
+ &error);
+ ASSERT_NE(base::kInvalidPlatformFileValue, file_handle);
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+ EXPECT_FALSE(created);
+ }
+ ASSERT_EQ(length, base::WritePlatformFile(file_handle, 0, data, length));
+ EXPECT_TRUE(base::ClosePlatformFile(file_handle));
+
+ base::PlatformFileInfo file_info1;
+ EXPECT_EQ(length, GetSize(data_path));
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
+ context.get(), url, &file_info1, &data_path));
+ EXPECT_EQ(data_path, local_path);
+
+ EXPECT_FALSE(file_info0.is_directory);
+ EXPECT_FALSE(file_info1.is_directory);
+ EXPECT_FALSE(file_info0.is_symbolic_link);
+ EXPECT_FALSE(file_info1.is_symbolic_link);
+ EXPECT_EQ(0, file_info0.size);
+ EXPECT_EQ(length, file_info1.size);
+ EXPECT_LE(file_info0.last_modified, file_info1.last_modified);
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
+ context.get(), url, length * 2));
+ EXPECT_EQ(length * 2, GetSize(data_path));
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
+ context.get(), url, 0));
+ EXPECT_EQ(0, GetSize(data_path));
+ }
+
+ void ValidateTestDirectory(
+ const FileSystemURL& root_url,
+ const std::set<base::FilePath::StringType>& files,
+ const std::set<base::FilePath::StringType>& directories) {
+ scoped_ptr<FileSystemOperationContext> context;
+ std::set<base::FilePath::StringType>::const_iterator iter;
+ for (iter = files.begin(); iter != files.end(); ++iter) {
+ bool created = true;
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ context.get(), FileSystemURLAppend(root_url, *iter),
+ &created));
+ ASSERT_FALSE(created);
+ }
+ for (iter = directories.begin(); iter != directories.end(); ++iter) {
+ context.reset(NewContext(NULL));
+ EXPECT_TRUE(DirectoryExists(
+ FileSystemURLAppend(root_url, *iter)));
+ }
+ }
+
+ class UsageVerifyHelper {
+ public:
+ UsageVerifyHelper(scoped_ptr<FileSystemOperationContext> context,
+ SandboxFileSystemTestHelper* file_system,
+ int64 expected_usage)
+ : context_(context.Pass()),
+ sandbox_file_system_(file_system),
+ expected_usage_(expected_usage) {}
+
+ ~UsageVerifyHelper() {
+ base::RunLoop().RunUntilIdle();
+ Check();
+ }
+
+ FileSystemOperationContext* context() {
+ return context_.get();
+ }
+
+ private:
+ void Check() {
+ ASSERT_EQ(expected_usage_,
+ sandbox_file_system_->GetCachedOriginUsage());
+ }
+
+ scoped_ptr<FileSystemOperationContext> context_;
+ SandboxFileSystemTestHelper* sandbox_file_system_;
+ int64 expected_usage_;
+ };
+
+ scoped_ptr<UsageVerifyHelper> AllowUsageIncrease(int64 requested_growth) {
+ int64 usage = sandbox_file_system_.GetCachedOriginUsage();
+ return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
+ LimitedContext(requested_growth),
+ &sandbox_file_system_, usage + requested_growth));
+ }
+
+ scoped_ptr<UsageVerifyHelper> DisallowUsageIncrease(int64 requested_growth) {
+ int64 usage = sandbox_file_system_.GetCachedOriginUsage();
+ return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
+ LimitedContext(requested_growth - 1), &sandbox_file_system_, usage));
+ }
+
+ void FillTestDirectory(
+ const FileSystemURL& root_url,
+ std::set<base::FilePath::StringType>* files,
+ std::set<base::FilePath::StringType>* directories) {
+ scoped_ptr<FileSystemOperationContext> context;
+ std::vector<DirectoryEntry> entries;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::ReadDirectory(
+ file_system_context(), root_url, &entries));
+ EXPECT_EQ(0UL, entries.size());
+
+ files->clear();
+ files->insert(FILE_PATH_LITERAL("first"));
+ files->insert(FILE_PATH_LITERAL("second"));
+ files->insert(FILE_PATH_LITERAL("third"));
+ directories->clear();
+ directories->insert(FILE_PATH_LITERAL("fourth"));
+ directories->insert(FILE_PATH_LITERAL("fifth"));
+ directories->insert(FILE_PATH_LITERAL("sixth"));
+ std::set<base::FilePath::StringType>::iterator iter;
+ for (iter = files->begin(); iter != files->end(); ++iter) {
+ bool created = false;
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ context.get(),
+ FileSystemURLAppend(root_url, *iter),
+ &created));
+ ASSERT_TRUE(created);
+ }
+ for (iter = directories->begin(); iter != directories->end(); ++iter) {
+ bool exclusive = true;
+ bool recursive = false;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(
+ context.get(),
+ FileSystemURLAppend(root_url, *iter),
+ exclusive, recursive));
+ }
+ ValidateTestDirectory(root_url, *files, *directories);
+ }
+
+ void TestReadDirectoryHelper(const FileSystemURL& root_url) {
+ std::set<base::FilePath::StringType> files;
+ std::set<base::FilePath::StringType> directories;
+ FillTestDirectory(root_url, &files, &directories);
+
+ scoped_ptr<FileSystemOperationContext> context;
+ std::vector<DirectoryEntry> entries;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::ReadDirectory(
+ file_system_context(), root_url, &entries));
+ std::vector<DirectoryEntry>::iterator entry_iter;
+ EXPECT_EQ(files.size() + directories.size(), entries.size());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+ for (entry_iter = entries.begin(); entry_iter != entries.end();
+ ++entry_iter) {
+ const DirectoryEntry& entry = *entry_iter;
+ std::set<base::FilePath::StringType>::iterator iter =
+ files.find(entry.name);
+ if (iter != files.end()) {
+ EXPECT_FALSE(entry.is_directory);
+ files.erase(iter);
+ continue;
+ }
+ iter = directories.find(entry.name);
+ EXPECT_FALSE(directories.end() == iter);
+ EXPECT_TRUE(entry.is_directory);
+ directories.erase(iter);
+ }
+ }
+
+ void TestTouchHelper(const FileSystemURL& url, bool is_file) {
+ base::Time last_access_time = base::Time::Now();
+ base::Time last_modified_time = base::Time::Now();
+
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Touch(
+ context.get(), url, last_access_time, last_modified_time));
+ // Currently we fire no change notifications for Touch.
+ EXPECT_TRUE(change_observer()->HasNoChange());
+ base::FilePath local_path;
+ base::PlatformFileInfo file_info;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
+ context.get(), url, &file_info, &local_path));
+ // We compare as time_t here to lower our resolution, to avoid false
+ // negatives caused by conversion to the local filesystem's native
+ // representation and back.
+ EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
+
+ context.reset(NewContext(NULL));
+ last_modified_time += base::TimeDelta::FromHours(1);
+ last_access_time += base::TimeDelta::FromHours(14);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Touch(
+ context.get(), url, last_access_time, last_modified_time));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
+ context.get(), url, &file_info, &local_path));
+ EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
+ if (is_file) // Directories in OFU don't support atime.
+ EXPECT_EQ(file_info.last_accessed.ToTimeT(), last_access_time.ToTimeT());
+ }
+
+ void TestCopyInForeignFileHelper(bool overwrite) {
+ base::ScopedTempDir source_dir;
+ ASSERT_TRUE(source_dir.CreateUniqueTempDir());
+ base::FilePath root_file_path = source_dir.path();
+ base::FilePath src_file_path = root_file_path.AppendASCII("file_name");
+ FileSystemURL dest_url = CreateURLFromUTF8("new file");
+ int64 src_file_length = 87;
+
+ base::PlatformFileError error_code;
+ bool created = false;
+ int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE;
+ base::PlatformFile file_handle =
+ base::CreatePlatformFile(
+ src_file_path, file_flags, &created, &error_code);
+ EXPECT_TRUE(created);
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error_code);
+ ASSERT_NE(base::kInvalidPlatformFileValue, file_handle);
+ ASSERT_TRUE(base::TruncatePlatformFile(file_handle, src_file_length));
+ EXPECT_TRUE(base::ClosePlatformFile(file_handle));
+
+ scoped_ptr<FileSystemOperationContext> context;
+
+ if (overwrite) {
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), dest_url, &created));
+ EXPECT_TRUE(created);
+
+ // We must have observed one (and only one) create_file_count.
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
+ EXPECT_TRUE(change_observer()->HasNoChange());
+ }
+
+ const int64 path_cost =
+ ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path());
+ if (!overwrite) {
+ // Verify that file creation requires sufficient quota for the path.
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(path_cost + src_file_length - 1);
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
+ ofu()->CopyInForeignFile(context.get(),
+ src_file_path, dest_url));
+ }
+
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(path_cost + src_file_length);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyInForeignFile(context.get(),
+ src_file_path, dest_url));
+
+ EXPECT_TRUE(PathExists(dest_url));
+ EXPECT_FALSE(DirectoryExists(dest_url));
+
+ context.reset(NewContext(NULL));
+ base::PlatformFileInfo file_info;
+ base::FilePath data_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
+ context.get(), dest_url, &file_info, &data_path));
+ EXPECT_NE(data_path, src_file_path);
+ EXPECT_TRUE(FileExists(data_path));
+ EXPECT_EQ(src_file_length, GetSize(data_path));
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->DeleteFile(context.get(), dest_url));
+ }
+
+ void ClearTimestamp(const FileSystemURL& url) {
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Touch(context.get(), url, base::Time(), base::Time()));
+ EXPECT_EQ(base::Time(), GetModifiedTime(url));
+ }
+
+ base::Time GetModifiedTime(const FileSystemURL& url) {
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ base::FilePath data_path;
+ base::PlatformFileInfo file_info;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->GetFileInfo(context.get(), url, &file_info, &data_path));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+ return file_info.last_modified;
+ }
+
+ void TestDirectoryTimestampHelper(const FileSystemURL& base_dir,
+ bool copy,
+ bool overwrite) {
+ scoped_ptr<FileSystemOperationContext> context;
+ const FileSystemURL src_dir_url(
+ FileSystemURLAppendUTF8(base_dir, "foo_dir"));
+ const FileSystemURL dest_dir_url(
+ FileSystemURLAppendUTF8(base_dir, "bar_dir"));
+
+ const FileSystemURL src_file_url(
+ FileSystemURLAppendUTF8(src_dir_url, "hoge"));
+ const FileSystemURL dest_file_url(
+ FileSystemURLAppendUTF8(dest_dir_url, "fuga"));
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(context.get(), src_dir_url, true, true));
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(context.get(), dest_dir_url, true, true));
+
+ bool created = false;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), src_file_url, &created));
+ if (overwrite) {
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(),
+ dest_file_url, &created));
+ }
+
+ ClearTimestamp(src_dir_url);
+ ClearTimestamp(dest_dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(context.get(),
+ src_file_url, dest_file_url,
+ FileSystemOperation::OPTION_NONE,
+ copy));
+ if (copy)
+ EXPECT_EQ(base::Time(), GetModifiedTime(src_dir_url));
+ else
+ EXPECT_NE(base::Time(), GetModifiedTime(src_dir_url));
+ EXPECT_NE(base::Time(), GetModifiedTime(dest_dir_url));
+ }
+
+ int64 ComputeCurrentUsage() {
+ return sandbox_file_system_.ComputeCurrentOriginUsage() -
+ sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
+ }
+
+ FileSystemContext* file_system_context() {
+ return sandbox_file_system_.file_system_context();
+ }
+
+ const base::FilePath& data_dir_path() const {
+ return data_dir_.path();
+ }
+
+ protected:
+ base::ScopedTempDir data_dir_;
+ base::MessageLoop message_loop_;
+ scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy_;
+ scoped_refptr<quota::QuotaManager> quota_manager_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ GURL origin_;
+ fileapi::FileSystemType type_;
+ base::WeakPtrFactory<ObfuscatedFileUtilTest> weak_factory_;
+ SandboxFileSystemTestHelper sandbox_file_system_;
+ quota::QuotaStatusCode quota_status_;
+ int64 usage_;
+ MockFileChangeObserver change_observer_;
+ ChangeObserverList change_observers_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtilTest);
+};
+
+TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
+ base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
+ bool created;
+ FileSystemURL url = CreateURLFromUTF8("fake/file");
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE;
+
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->CreateOrOpen(
+ context.get(), url, file_flags, &file_handle,
+ &created));
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->DeleteFile(context.get(), url));
+
+ url = CreateURLFromUTF8("test file");
+
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ // Verify that file creation requires sufficient quota for the path.
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(
+ ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
+ ofu()->CreateOrOpen(
+ context.get(), url, file_flags, &file_handle, &created));
+
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(
+ ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateOrOpen(
+ context.get(), url, file_flags, &file_handle, &created));
+ ASSERT_TRUE(created);
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
+ EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
+
+ CheckFileAndCloseHandle(url, file_handle);
+
+ context.reset(NewContext(NULL));
+ base::FilePath local_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
+ context.get(), url, &local_path));
+ EXPECT_TRUE(base::PathExists(local_path));
+
+ // Verify that deleting a file isn't stopped by zero quota, and that it frees
+ // up quote from its path.
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(0);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->DeleteFile(context.get(), url));
+ EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
+ EXPECT_FALSE(base::PathExists(local_path));
+ EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
+ context->allowed_bytes_growth());
+
+ context.reset(NewContext(NULL));
+ bool exclusive = true;
+ bool recursive = true;
+ FileSystemURL directory_url = CreateURLFromUTF8(
+ "series/of/directories");
+ url = FileSystemURLAppendUTF8(directory_url, "file name");
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(), directory_url, exclusive, recursive));
+ // The oepration created 3 directories recursively.
+ EXPECT_EQ(3, change_observer()->get_and_reset_create_directory_count());
+
+ context.reset(NewContext(NULL));
+ file_handle = base::kInvalidPlatformFileValue;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateOrOpen(
+ context.get(), url, file_flags, &file_handle, &created));
+ ASSERT_TRUE(created);
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
+ EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
+
+ CheckFileAndCloseHandle(url, file_handle);
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
+ context.get(), url, &local_path));
+ EXPECT_TRUE(base::PathExists(local_path));
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->DeleteFile(context.get(), url));
+ EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
+ EXPECT_FALSE(base::PathExists(local_path));
+
+ // Make sure we have no unexpected changes.
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestTruncate) {
+ bool created = false;
+ FileSystemURL url = CreateURLFromUTF8("file");
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->Truncate(context.get(), url, 4));
+
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ ASSERT_TRUE(created);
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
+
+ context.reset(NewContext(NULL));
+ base::FilePath local_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
+ context.get(), url, &local_path));
+ EXPECT_EQ(0, GetSize(local_path));
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
+ context.get(), url, 10));
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+ EXPECT_EQ(10, GetSize(local_path));
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
+ context.get(), url, 1));
+ EXPECT_EQ(1, GetSize(local_path));
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
+
+ EXPECT_FALSE(DirectoryExists(url));
+ EXPECT_TRUE(PathExists(url));
+
+ // Make sure we have no unexpected changes.
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestQuotaOnTruncation) {
+ bool created = false;
+ FileSystemURL url = CreateURLFromUTF8("file");
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ AllowUsageIncrease(PathCost(url))->context(),
+ url, &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(0, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(1020)->context(),
+ url, 1020));
+ ASSERT_EQ(1020, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(-1020)->context(),
+ url, 0));
+ ASSERT_EQ(0, ComputeTotalFileSize());
+
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
+ ofu()->Truncate(
+ DisallowUsageIncrease(1021)->context(),
+ url, 1021));
+ ASSERT_EQ(0, ComputeTotalFileSize());
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(1020)->context(),
+ url, 1020));
+ ASSERT_EQ(1020, ComputeTotalFileSize());
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(0)->context(),
+ url, 1020));
+ ASSERT_EQ(1020, ComputeTotalFileSize());
+
+ // quota exceeded
+ {
+ scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(-1);
+ helper->context()->set_allowed_bytes_growth(
+ helper->context()->allowed_bytes_growth() - 1);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(helper->context(), url, 1019));
+ ASSERT_EQ(1019, ComputeTotalFileSize());
+ }
+
+ // Delete backing file to make following truncation fail.
+ base::FilePath local_path;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->GetLocalFilePath(
+ UnlimitedContext().get(),
+ url, &local_path));
+ ASSERT_FALSE(local_path.empty());
+ ASSERT_TRUE(base::DeleteFile(local_path, false));
+
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->Truncate(
+ LimitedContext(1234).get(),
+ url, 1234));
+ ASSERT_EQ(0, ComputeTotalFileSize());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) {
+ FileSystemURL url = CreateURLFromUTF8("fake/file");
+ bool created = false;
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->EnsureFileExists(
+ context.get(), url, &created));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ // Verify that file creation requires sufficient quota for the path.
+ context.reset(NewContext(NULL));
+ url = CreateURLFromUTF8("test file");
+ created = false;
+ context->set_allowed_bytes_growth(
+ ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ ASSERT_FALSE(created);
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(
+ ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ ASSERT_TRUE(created);
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
+
+ CheckFileAndCloseHandle(url, base::kInvalidPlatformFileValue);
+
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ ASSERT_FALSE(created);
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ // Also test in a subdirectory.
+ url = CreateURLFromUTF8("path/to/file.txt");
+ context.reset(NewContext(NULL));
+ bool exclusive = true;
+ bool recursive = true;
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(),
+ FileSystemURLDirName(url),
+ exclusive, recursive));
+ // 2 directories: path/ and path/to.
+ EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
+
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ ASSERT_TRUE(created);
+ EXPECT_FALSE(DirectoryExists(url));
+ EXPECT_TRUE(PathExists(url));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) {
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+
+ bool exclusive = false;
+ bool recursive = false;
+ FileSystemURL url = CreateURLFromUTF8("foo/bar");
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->DeleteDirectory(context.get(), url));
+
+ FileSystemURL root = CreateURLFromUTF8(std::string());
+ EXPECT_FALSE(DirectoryExists(url));
+ EXPECT_FALSE(PathExists(url));
+ context.reset(NewContext(NULL));
+ EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), root));
+
+ context.reset(NewContext(NULL));
+ exclusive = false;
+ recursive = true;
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+ EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
+
+ EXPECT_TRUE(DirectoryExists(url));
+ EXPECT_TRUE(PathExists(url));
+
+ context.reset(NewContext(NULL));
+ EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), root));
+ EXPECT_TRUE(DirectoryExists(FileSystemURLDirName(url)));
+
+ context.reset(NewContext(NULL));
+ EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(),
+ FileSystemURLDirName(url)));
+
+ // Can't remove a non-empty directory.
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY,
+ ofu()->DeleteDirectory(context.get(),
+ FileSystemURLDirName(url)));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ base::PlatformFileInfo file_info;
+ base::FilePath local_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
+ context.get(), url, &file_info, &local_path));
+ EXPECT_TRUE(local_path.empty());
+ EXPECT_TRUE(file_info.is_directory);
+ EXPECT_FALSE(file_info.is_symbolic_link);
+
+ // Same create again should succeed, since exclusive is false.
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ exclusive = true;
+ recursive = true;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ // Verify that deleting a directory isn't stopped by zero quota, and that it
+ // frees up quota from its path.
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(0);
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->DeleteDirectory(context.get(), url));
+ EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
+ EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
+ context->allowed_bytes_growth());
+
+ url = CreateURLFromUTF8("foo/bop");
+
+ EXPECT_FALSE(DirectoryExists(url));
+ EXPECT_FALSE(PathExists(url));
+
+ context.reset(NewContext(NULL));
+ EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->GetFileInfo(
+ context.get(), url, &file_info, &local_path));
+
+ // Verify that file creation requires sufficient quota for the path.
+ exclusive = true;
+ recursive = false;
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(
+ ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(
+ ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
+
+ EXPECT_TRUE(DirectoryExists(url));
+ EXPECT_TRUE(PathExists(url));
+
+ exclusive = true;
+ recursive = false;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ exclusive = true;
+ recursive = false;
+ url = CreateURLFromUTF8("foo");
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+
+ url = CreateURLFromUTF8("blah");
+
+ EXPECT_FALSE(DirectoryExists(url));
+ EXPECT_FALSE(PathExists(url));
+
+ exclusive = true;
+ recursive = false;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
+
+ EXPECT_TRUE(DirectoryExists(url));
+ EXPECT_TRUE(PathExists(url));
+
+ exclusive = true;
+ recursive = false;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestReadDirectory) {
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ bool exclusive = true;
+ bool recursive = true;
+ FileSystemURL url = CreateURLFromUTF8("directory/to/use");
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+ TestReadDirectoryHelper(url);
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestReadRootWithSlash) {
+ TestReadDirectoryHelper(CreateURLFromUTF8(std::string()));
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestReadRootWithEmptyString) {
+ TestReadDirectoryHelper(CreateURLFromUTF8("/"));
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) {
+ FileSystemURL url = CreateURLFromUTF8("file");
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+
+ bool created = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ ASSERT_TRUE(created);
+
+ std::vector<DirectoryEntry> entries;
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY,
+ AsyncFileTestHelper::ReadDirectory(
+ file_system_context(), url, &entries));
+
+ EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestTouch) {
+ FileSystemURL url = CreateURLFromUTF8("file");
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+
+ base::Time last_access_time = base::Time::Now();
+ base::Time last_modified_time = base::Time::Now();
+
+ // It's not there yet.
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->Touch(
+ context.get(), url, last_access_time, last_modified_time));
+
+ // OK, now create it.
+ context.reset(NewContext(NULL));
+ bool created = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ ASSERT_TRUE(created);
+ TestTouchHelper(url, true);
+
+ // Now test a directory:
+ context.reset(NewContext(NULL));
+ bool exclusive = true;
+ bool recursive = false;
+ url = CreateURLFromUTF8("dir");
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(context.get(),
+ url, exclusive, recursive));
+ TestTouchHelper(url, false);
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestPathQuotas) {
+ FileSystemURL url = CreateURLFromUTF8("fake/file");
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+
+ url = CreateURLFromUTF8("file name");
+ context->set_allowed_bytes_growth(5);
+ bool created = false;
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ EXPECT_FALSE(created);
+ context->set_allowed_bytes_growth(1024);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ EXPECT_TRUE(created);
+ int64 path_cost = ObfuscatedFileUtil::ComputeFilePathCost(url.path());
+ EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
+
+ context->set_allowed_bytes_growth(1024);
+ bool exclusive = true;
+ bool recursive = true;
+ url = CreateURLFromUTF8("directory/to/use");
+ std::vector<base::FilePath::StringType> components;
+ url.path().GetComponents(&components);
+ path_cost = 0;
+ typedef std::vector<base::FilePath::StringType>::iterator iterator;
+ for (iterator iter = components.begin();
+ iter != components.end(); ++iter) {
+ path_cost += ObfuscatedFileUtil::ComputeFilePathCost(
+ base::FilePath(*iter));
+ }
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(1024);
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(), url, exclusive, recursive));
+ EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) {
+ FileSystemURL source_url = CreateURLFromUTF8("path0.txt");
+ FileSystemURL dest_url = CreateURLFromUTF8("path1.txt");
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+
+ bool is_copy_not_move = false;
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
+ FileSystemOperation::OPTION_NONE,
+ is_copy_not_move));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+ context.reset(NewContext(NULL));
+ is_copy_not_move = true;
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
+ FileSystemOperation::OPTION_NONE,
+ is_copy_not_move));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+ source_url = CreateURLFromUTF8("dir/dir/file");
+ bool exclusive = true;
+ bool recursive = true;
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(),
+ FileSystemURLDirName(source_url),
+ exclusive, recursive));
+ EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
+ is_copy_not_move = false;
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
+ FileSystemOperation::OPTION_NONE,
+ is_copy_not_move));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+ context.reset(NewContext(NULL));
+ is_copy_not_move = true;
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
+ FileSystemOperation::OPTION_NONE,
+ is_copy_not_move));
+ EXPECT_TRUE(change_observer()->HasNoChange());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) {
+ const int64 kSourceLength = 5;
+ const int64 kDestLength = 50;
+
+ for (size_t i = 0; i < arraysize(kCopyMoveTestCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "kCopyMoveTestCase " << i);
+ const CopyMoveTestCaseRecord& test_case = kCopyMoveTestCases[i];
+ SCOPED_TRACE(testing::Message() << "\t is_copy_not_move " <<
+ test_case.is_copy_not_move);
+ SCOPED_TRACE(testing::Message() << "\t source_path " <<
+ test_case.source_path);
+ SCOPED_TRACE(testing::Message() << "\t dest_path " <<
+ test_case.dest_path);
+ SCOPED_TRACE(testing::Message() << "\t cause_overwrite " <<
+ test_case.cause_overwrite);
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+
+ bool exclusive = false;
+ bool recursive = true;
+ FileSystemURL source_url = CreateURLFromUTF8(test_case.source_path);
+ FileSystemURL dest_url = CreateURLFromUTF8(test_case.dest_path);
+
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(),
+ FileSystemURLDirName(source_url),
+ exclusive, recursive));
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(),
+ FileSystemURLDirName(dest_url),
+ exclusive, recursive));
+
+ bool created = false;
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), source_url, &created));
+ ASSERT_TRUE(created);
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(context.get(), source_url, kSourceLength));
+
+ if (test_case.cause_overwrite) {
+ context.reset(NewContext(NULL));
+ created = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), dest_url, &created));
+ ASSERT_TRUE(created);
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(context.get(), dest_url, kDestLength));
+ }
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CopyOrMoveFile(
+ context.get(), source_url, dest_url, FileSystemOperation::OPTION_NONE,
+ test_case.is_copy_not_move));
+
+ if (test_case.is_copy_not_move) {
+ base::PlatformFileInfo file_info;
+ base::FilePath local_path;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
+ context.get(), source_url, &file_info, &local_path));
+ EXPECT_EQ(kSourceLength, file_info.size);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->DeleteFile(context.get(), source_url));
+ } else {
+ base::PlatformFileInfo file_info;
+ base::FilePath local_path;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->GetFileInfo(
+ context.get(), source_url, &file_info, &local_path));
+ }
+ base::PlatformFileInfo file_info;
+ base::FilePath local_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
+ context.get(), dest_url, &file_info, &local_path));
+ EXPECT_EQ(kSourceLength, file_info.size);
+
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->DeleteFile(context.get(), dest_url));
+ }
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestCopyPathQuotas) {
+ FileSystemURL src_url = CreateURLFromUTF8("src path");
+ FileSystemURL dest_url = CreateURLFromUTF8("destination path");
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ bool created = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
+ context.get(), src_url, &created));
+
+ bool is_copy = true;
+ // Copy, no overwrite.
+ context->set_allowed_bytes_growth(
+ ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1);
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
+ ofu()->CopyOrMoveFile(
+ context.get(),
+ src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy));
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(
+ ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ context.get(),
+ src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy));
+
+ // Copy, with overwrite.
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(0);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ context.get(),
+ src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy));
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) {
+ FileSystemURL src_url = CreateURLFromUTF8("src path");
+ FileSystemURL dest_url = CreateURLFromUTF8("destination path");
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ bool created = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
+ context.get(), src_url, &created));
+
+ bool is_copy = false;
+ // Move, rename, no overwrite.
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(
+ ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
+ ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()) - 1);
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
+ ofu()->CopyOrMoveFile(
+ context.get(),
+ src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy));
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(
+ ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
+ ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ context.get(),
+ src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy));
+
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
+ context.get(), src_url, &created));
+
+ // Move, rename, with overwrite.
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(0);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ context.get(),
+ src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy));
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) {
+ FileSystemURL src_url = CreateURLFromUTF8("src path");
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ bool created = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
+ context.get(), src_url, &created));
+
+ bool exclusive = true;
+ bool recursive = false;
+ FileSystemURL dir_url = CreateURLFromUTF8("directory path");
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(), dir_url, exclusive, recursive));
+
+ FileSystemURL dest_url = FileSystemURLAppend(
+ dir_url, src_url.path().value());
+
+ bool is_copy = false;
+ int64 allowed_bytes_growth = -1000; // Over quota, this should still work.
+ // Move, no rename, no overwrite.
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(allowed_bytes_growth);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ context.get(),
+ src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy));
+ EXPECT_EQ(allowed_bytes_growth, context->allowed_bytes_growth());
+
+ // Move, no rename, with overwrite.
+ context.reset(NewContext(NULL));
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
+ context.get(), src_url, &created));
+ context.reset(NewContext(NULL));
+ context->set_allowed_bytes_growth(allowed_bytes_growth);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ context.get(),
+ src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy));
+ EXPECT_EQ(
+ allowed_bytes_growth +
+ ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()),
+ context->allowed_bytes_growth());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestCopyInForeignFile) {
+ TestCopyInForeignFileHelper(false /* overwrite */);
+ TestCopyInForeignFileHelper(true /* overwrite */);
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestEnumerator) {
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ FileSystemURL src_url = CreateURLFromUTF8("source dir");
+ bool exclusive = true;
+ bool recursive = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
+ context.get(), src_url, exclusive, recursive));
+
+ std::set<base::FilePath::StringType> files;
+ std::set<base::FilePath::StringType> directories;
+ FillTestDirectory(src_url, &files, &directories);
+
+ FileSystemURL dest_url = CreateURLFromUTF8("destination dir");
+
+ EXPECT_FALSE(DirectoryExists(dest_url));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::Copy(
+ file_system_context(), src_url, dest_url));
+
+ ValidateTestDirectory(dest_url, files, directories);
+ EXPECT_TRUE(DirectoryExists(src_url));
+ EXPECT_TRUE(DirectoryExists(dest_url));
+ recursive = true;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::Remove(
+ file_system_context(), dest_url, recursive));
+ EXPECT_FALSE(DirectoryExists(dest_url));
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestOriginEnumerator) {
+ scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator>
+ enumerator(ofu()->CreateOriginEnumerator());
+ // The test helper starts out with a single filesystem.
+ EXPECT_TRUE(enumerator.get());
+ EXPECT_EQ(origin(), enumerator->Next());
+ ASSERT_TRUE(type() == kFileSystemTypeTemporary);
+ EXPECT_TRUE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
+ EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
+ EXPECT_EQ(GURL(), enumerator->Next());
+ EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
+ EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
+
+ std::set<GURL> origins_expected;
+ origins_expected.insert(origin());
+
+ for (size_t i = 0; i < arraysize(kOriginEnumerationTestRecords); ++i) {
+ SCOPED_TRACE(testing::Message() <<
+ "Validating kOriginEnumerationTestRecords " << i);
+ const OriginEnumerationTestRecord& record =
+ kOriginEnumerationTestRecords[i];
+ GURL origin_url(record.origin_url);
+ origins_expected.insert(origin_url);
+ if (record.has_temporary) {
+ scoped_ptr<SandboxFileSystemTestHelper> file_system(
+ NewFileSystem(origin_url, kFileSystemTypeTemporary));
+ scoped_ptr<FileSystemOperationContext> context(
+ NewContext(file_system.get()));
+ bool created = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ context.get(),
+ file_system->CreateURLFromUTF8("file"),
+ &created));
+ EXPECT_TRUE(created);
+ }
+ if (record.has_persistent) {
+ scoped_ptr<SandboxFileSystemTestHelper> file_system(
+ NewFileSystem(origin_url, kFileSystemTypePersistent));
+ scoped_ptr<FileSystemOperationContext> context(
+ NewContext(file_system.get()));
+ bool created = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ context.get(),
+ file_system->CreateURLFromUTF8("file"),
+ &created));
+ EXPECT_TRUE(created);
+ }
+ }
+ enumerator.reset(ofu()->CreateOriginEnumerator());
+ EXPECT_TRUE(enumerator.get());
+ std::set<GURL> origins_found;
+ GURL origin_url;
+ while (!(origin_url = enumerator->Next()).is_empty()) {
+ origins_found.insert(origin_url);
+ SCOPED_TRACE(testing::Message() << "Handling " << origin_url.spec());
+ bool found = false;
+ for (size_t i = 0; !found && i < arraysize(kOriginEnumerationTestRecords);
+ ++i) {
+ const OriginEnumerationTestRecord& record =
+ kOriginEnumerationTestRecords[i];
+ if (GURL(record.origin_url) != origin_url)
+ continue;
+ found = true;
+ EXPECT_EQ(record.has_temporary,
+ HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
+ EXPECT_EQ(record.has_persistent,
+ HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
+ }
+ // Deal with the default filesystem created by the test helper.
+ if (!found && origin_url == origin()) {
+ ASSERT_TRUE(type() == kFileSystemTypeTemporary);
+ EXPECT_TRUE(HasFileSystemType(enumerator.get(),
+ kFileSystemTypeTemporary));
+ EXPECT_FALSE(HasFileSystemType(enumerator.get(),
+ kFileSystemTypePersistent));
+ found = true;
+ }
+ EXPECT_TRUE(found);
+ }
+
+ std::set<GURL> diff;
+ std::set_symmetric_difference(origins_expected.begin(),
+ origins_expected.end(), origins_found.begin(), origins_found.end(),
+ inserter(diff, diff.begin()));
+ EXPECT_TRUE(diff.empty());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestRevokeUsageCache) {
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+
+ int64 expected_quota = 0;
+
+ for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
+ SCOPED_TRACE(testing::Message() << "Creating kRegularTestCase " << i);
+ const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
+ base::FilePath file_path(test_case.path);
+ expected_quota += ObfuscatedFileUtil::ComputeFilePathCost(file_path);
+ if (test_case.is_directory) {
+ bool exclusive = true;
+ bool recursive = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(context.get(), CreateURL(file_path),
+ exclusive, recursive));
+ } else {
+ bool created = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), CreateURL(file_path),
+ &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(context.get(),
+ CreateURL(file_path),
+ test_case.data_file_size));
+ expected_quota += test_case.data_file_size;
+ }
+ }
+
+ // Usually raw size in usage cache and the usage returned by QuotaUtil
+ // should be same.
+ EXPECT_EQ(expected_quota, SizeInUsageFile());
+ EXPECT_EQ(expected_quota, SizeByQuotaUtil());
+
+ RevokeUsageCache();
+ EXPECT_EQ(-1, SizeInUsageFile());
+ EXPECT_EQ(expected_quota, SizeByQuotaUtil());
+
+ // This should reconstruct the cache.
+ GetUsageFromQuotaManager();
+ EXPECT_EQ(expected_quota, SizeInUsageFile());
+ EXPECT_EQ(expected_quota, SizeByQuotaUtil());
+ EXPECT_EQ(expected_quota, usage());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestInconsistency) {
+ const FileSystemURL kPath1 = CreateURLFromUTF8("hoge");
+ const FileSystemURL kPath2 = CreateURLFromUTF8("fuga");
+
+ scoped_ptr<FileSystemOperationContext> context;
+ base::PlatformFile file;
+ base::PlatformFileInfo file_info;
+ base::FilePath data_path;
+ bool created = false;
+
+ // Create a non-empty file.
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), kPath1, &created));
+ EXPECT_TRUE(created);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(context.get(), kPath1, 10));
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->GetFileInfo(
+ context.get(), kPath1, &file_info, &data_path));
+ EXPECT_EQ(10, file_info.size);
+
+ // Destroy database to make inconsistency between database and filesystem.
+ ofu()->DestroyDirectoryDatabase(origin(), type_string());
+
+ // Try to get file info of broken file.
+ EXPECT_FALSE(PathExists(kPath1));
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), kPath1, &created));
+ EXPECT_TRUE(created);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->GetFileInfo(
+ context.get(), kPath1, &file_info, &data_path));
+ EXPECT_EQ(0, file_info.size);
+
+ // Make another broken file to |kPath2|.
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), kPath2, &created));
+ EXPECT_TRUE(created);
+
+ // Destroy again.
+ ofu()->DestroyDirectoryDatabase(origin(), type_string());
+
+ // Repair broken |kPath1|.
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->Touch(context.get(), kPath1, base::Time::Now(),
+ base::Time::Now()));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), kPath1, &created));
+ EXPECT_TRUE(created);
+
+ // Copy from sound |kPath1| to broken |kPath2|.
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(context.get(), kPath1, kPath2,
+ FileSystemOperation::OPTION_NONE,
+ true /* copy */));
+
+ ofu()->DestroyDirectoryDatabase(origin(), type_string());
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateOrOpen(
+ context.get(), kPath1,
+ base::PLATFORM_FILE_READ | base::PLATFORM_FILE_CREATE,
+ &file, &created));
+ EXPECT_TRUE(created);
+ EXPECT_TRUE(base::GetPlatformFileInfo(file, &file_info));
+ EXPECT_EQ(0, file_info.size);
+ EXPECT_TRUE(base::ClosePlatformFile(file));
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) {
+ const FileSystemURL kPath[] = {
+ CreateURLFromUTF8("foo"),
+ CreateURLFromUTF8("bar"),
+ CreateURLFromUTF8("baz")
+ };
+ const FileSystemURL empty_path = CreateURL(base::FilePath());
+ scoped_ptr<FileSystemOperationContext> context;
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kPath); ++i) {
+ bool created = false;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), kPath[i], &created));
+ EXPECT_TRUE(created);
+ }
+
+ std::vector<DirectoryEntry> entries;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::ReadDirectory(
+ file_system_context(), empty_path, &entries));
+ EXPECT_EQ(3u, entries.size());
+
+ base::FilePath local_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->GetLocalFilePath(context.get(), kPath[0], &local_path));
+ EXPECT_TRUE(base::DeleteFile(local_path, false));
+
+ entries.clear();
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::ReadDirectory(
+ file_system_context(), empty_path, &entries));
+ EXPECT_EQ(ARRAYSIZE_UNSAFE(kPath) - 1, entries.size());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
+
+ // Create working directory.
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(context.get(), dir_url, false, false));
+
+ // EnsureFileExists, create case.
+ FileSystemURL url(FileSystemURLAppendUTF8(
+ dir_url, "EnsureFileExists_file"));
+ bool created = false;
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ EXPECT_TRUE(created);
+ EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
+
+ // non create case.
+ created = true;
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ EXPECT_FALSE(created);
+ EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
+
+ // fail case.
+ url = FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_dir");
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(context.get(), url, false, false));
+
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
+
+ // CreateOrOpen, create case.
+ url = FileSystemURLAppendUTF8(dir_url, "CreateOrOpen_file");
+ base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
+ created = false;
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateOrOpen(
+ context.get(), url,
+ base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE,
+ &file_handle, &created));
+ EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
+ EXPECT_TRUE(created);
+ EXPECT_TRUE(base::ClosePlatformFile(file_handle));
+ EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
+
+ // open case.
+ file_handle = base::kInvalidPlatformFileValue;
+ created = true;
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateOrOpen(
+ context.get(), url,
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
+ &file_handle, &created));
+ EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
+ EXPECT_FALSE(created);
+ EXPECT_TRUE(base::ClosePlatformFile(file_handle));
+ EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
+
+ // fail case
+ file_handle = base::kInvalidPlatformFileValue;
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS,
+ ofu()->CreateOrOpen(
+ context.get(), url,
+ base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE,
+ &file_handle, &created));
+ EXPECT_EQ(base::kInvalidPlatformFileValue, file_handle);
+ EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
+
+ // CreateDirectory, create case.
+ // Creating CreateDirectory_dir and CreateDirectory_dir/subdir.
+ url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
+ FileSystemURL subdir_url(FileSystemURLAppendUTF8(url, "subdir"));
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(context.get(), subdir_url,
+ true /* exclusive */, true /* recursive */));
+ EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
+
+ // create subdir case.
+ // Creating CreateDirectory_dir/subdir2.
+ subdir_url = FileSystemURLAppendUTF8(url, "subdir2");
+ ClearTimestamp(dir_url);
+ ClearTimestamp(url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(context.get(), subdir_url,
+ true /* exclusive */, true /* recursive */));
+ EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
+ EXPECT_NE(base::Time(), GetModifiedTime(url));
+
+ // fail case.
+ url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS,
+ ofu()->CreateDirectory(context.get(), url,
+ true /* exclusive */, true /* recursive */));
+ EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
+
+ // CopyInForeignFile, create case.
+ url = FileSystemURLAppendUTF8(dir_url, "CopyInForeignFile_file");
+ FileSystemURL src_path = FileSystemURLAppendUTF8(
+ dir_url, "CopyInForeignFile_src_file");
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), src_path, &created));
+ EXPECT_TRUE(created);
+ base::FilePath src_local_path;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->GetLocalFilePath(context.get(), src_path, &src_local_path));
+
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyInForeignFile(context.get(),
+ src_local_path,
+ url));
+ EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) {
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
+
+ // Create working directory.
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(context.get(), dir_url, false, false));
+
+ // DeleteFile, delete case.
+ FileSystemURL url = FileSystemURLAppendUTF8(
+ dir_url, "DeleteFile_file");
+ bool created = false;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), url, &created));
+ EXPECT_TRUE(created);
+
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->DeleteFile(context.get(), url));
+ EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
+
+ // fail case.
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ ofu()->DeleteFile(context.get(), url));
+ EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
+
+ // DeleteDirectory, fail case.
+ url = FileSystemURLAppendUTF8(dir_url, "DeleteDirectory_dir");
+ FileSystemURL file_path(FileSystemURLAppendUTF8(url, "pakeratta"));
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(context.get(), url, true, true));
+ created = false;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), file_path, &created));
+ EXPECT_TRUE(created);
+
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY,
+ ofu()->DeleteDirectory(context.get(), url));
+ EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
+
+ // delete case.
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->DeleteFile(context.get(), file_path));
+
+ ClearTimestamp(dir_url);
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->DeleteDirectory(context.get(), url));
+ EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCopyAndMove) {
+ TestDirectoryTimestampHelper(
+ CreateURLFromUTF8("copy overwrite"), true, true);
+ TestDirectoryTimestampHelper(
+ CreateURLFromUTF8("copy non-overwrite"), true, false);
+ TestDirectoryTimestampHelper(
+ CreateURLFromUTF8("move overwrite"), false, true);
+ TestDirectoryTimestampHelper(
+ CreateURLFromUTF8("move non-overwrite"), false, false);
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) {
+ FileSystemURL dir = CreateURLFromUTF8("foo");
+ FileSystemURL url1 = FileSystemURLAppendUTF8(dir, "bar");
+ FileSystemURL url2 = FileSystemURLAppendUTF8(dir, "baz");
+
+ scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(context.get(), dir, false, false));
+
+ bool created = false;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(context.get(), url1, &created));
+ EXPECT_TRUE(created);
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(context.get(), url2, false, false));
+
+ base::FilePath file_path;
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->GetLocalFilePath(context.get(), url1, &file_path));
+ EXPECT_FALSE(file_path.empty());
+
+ context.reset(NewContext(NULL));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Touch(context.get(), url1,
+ base::Time::Now() + base::TimeDelta::FromHours(1),
+ base::Time()));
+
+ context.reset(NewContext(NULL));
+ scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum(
+ ofu()->CreateFileEnumerator(context.get(), dir, false));
+
+ int count = 0;
+ base::FilePath file_path_each;
+ while (!(file_path_each = file_enum->Next()).empty()) {
+ context.reset(NewContext(NULL));
+ base::PlatformFileInfo file_info;
+ base::FilePath file_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->GetFileInfo(context.get(),
+ FileSystemURL::CreateForTest(
+ dir.origin(),
+ dir.mount_type(),
+ file_path_each),
+ &file_info, &file_path));
+ EXPECT_EQ(file_info.is_directory, file_enum->IsDirectory());
+ EXPECT_EQ(file_info.last_modified, file_enum->LastModifiedTime());
+ EXPECT_EQ(file_info.size, file_enum->Size());
+ ++count;
+ }
+ EXPECT_EQ(2, count);
+}
+
+// crbug.com/176470
+#if defined(OS_WIN) || defined(OS_ANDROID)
+#define MAYBE_TestQuotaOnCopyFile DISABLED_TestQuotaOnCopyFile
+#else
+#define MAYBE_TestQuotaOnCopyFile TestQuotaOnCopyFile
+#endif
+TEST_F(ObfuscatedFileUtilTest, MAYBE_TestQuotaOnCopyFile) {
+ FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
+ FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
+ FileSystemURL to_file1(CreateURLFromUTF8("tofile1"));
+ FileSystemURL to_file2(CreateURLFromUTF8("tofile2"));
+ bool created;
+
+ int64 expected_total_file_size = 0;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ AllowUsageIncrease(PathCost(from_file))->context(),
+ from_file, &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ AllowUsageIncrease(PathCost(obstacle_file))->context(),
+ obstacle_file, &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ int64 from_file_size = 1020;
+ expected_total_file_size += from_file_size;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(from_file_size)->context(),
+ from_file, from_file_size));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ int64 obstacle_file_size = 1;
+ expected_total_file_size += obstacle_file_size;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(obstacle_file_size)->context(),
+ obstacle_file, obstacle_file_size));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ int64 to_file1_size = from_file_size;
+ expected_total_file_size += to_file1_size;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ AllowUsageIncrease(
+ PathCost(to_file1) + to_file1_size)->context(),
+ from_file, to_file1,
+ FileSystemOperation::OPTION_NONE,
+ true /* copy */));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
+ ofu()->CopyOrMoveFile(
+ DisallowUsageIncrease(
+ PathCost(to_file2) + from_file_size)->context(),
+ from_file, to_file2, FileSystemOperation::OPTION_NONE,
+ true /* copy */));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ int64 old_obstacle_file_size = obstacle_file_size;
+ obstacle_file_size = from_file_size;
+ expected_total_file_size += obstacle_file_size - old_obstacle_file_size;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ AllowUsageIncrease(
+ obstacle_file_size - old_obstacle_file_size)->context(),
+ from_file, obstacle_file,
+ FileSystemOperation::OPTION_NONE,
+ true /* copy */));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ int64 old_from_file_size = from_file_size;
+ from_file_size = old_from_file_size - 1;
+ expected_total_file_size += from_file_size - old_from_file_size;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(
+ from_file_size - old_from_file_size)->context(),
+ from_file, from_file_size));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ // quota exceeded
+ {
+ old_obstacle_file_size = obstacle_file_size;
+ obstacle_file_size = from_file_size;
+ expected_total_file_size += obstacle_file_size - old_obstacle_file_size;
+ scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(
+ obstacle_file_size - old_obstacle_file_size);
+ helper->context()->set_allowed_bytes_growth(
+ helper->context()->allowed_bytes_growth() - 1);
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ helper->context(),
+ from_file, obstacle_file,
+ FileSystemOperation::OPTION_NONE,
+ true /* copy */));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+ }
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestQuotaOnMoveFile) {
+ FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
+ FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
+ FileSystemURL to_file(CreateURLFromUTF8("tofile"));
+ bool created;
+
+ int64 expected_total_file_size = 0;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ AllowUsageIncrease(PathCost(from_file))->context(),
+ from_file, &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ int64 from_file_size = 1020;
+ expected_total_file_size += from_file_size;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(from_file_size)->context(),
+ from_file, from_file_size));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ int64 to_file_size ALLOW_UNUSED = from_file_size;
+ from_file_size = 0;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ AllowUsageIncrease(-PathCost(from_file) +
+ PathCost(to_file))->context(),
+ from_file, to_file,
+ FileSystemOperation::OPTION_NONE,
+ false /* move */));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ AllowUsageIncrease(PathCost(from_file))->context(),
+ from_file, &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ AllowUsageIncrease(PathCost(obstacle_file))->context(),
+ obstacle_file, &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ from_file_size = 1020;
+ expected_total_file_size += from_file_size;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(from_file_size)->context(),
+ from_file, from_file_size));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ int64 obstacle_file_size = 1;
+ expected_total_file_size += obstacle_file_size;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(1)->context(),
+ obstacle_file, obstacle_file_size));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ int64 old_obstacle_file_size = obstacle_file_size;
+ obstacle_file_size = from_file_size;
+ from_file_size = 0;
+ expected_total_file_size -= old_obstacle_file_size;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ AllowUsageIncrease(
+ -old_obstacle_file_size - PathCost(from_file))->context(),
+ from_file, obstacle_file,
+ FileSystemOperation::OPTION_NONE,
+ false /* move */));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ AllowUsageIncrease(PathCost(from_file))->context(),
+ from_file, &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ from_file_size = 10;
+ expected_total_file_size += from_file_size;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(from_file_size)->context(),
+ from_file, from_file_size));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+
+ // quota exceeded even after operation
+ old_obstacle_file_size = obstacle_file_size;
+ obstacle_file_size = from_file_size;
+ from_file_size = 0;
+ expected_total_file_size -= old_obstacle_file_size;
+ scoped_ptr<FileSystemOperationContext> context =
+ LimitedContext(-old_obstacle_file_size - PathCost(from_file) - 1);
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CopyOrMoveFile(
+ context.get(), from_file, obstacle_file,
+ FileSystemOperation::OPTION_NONE,
+ false /* move */));
+ ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
+ context.reset();
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestQuotaOnRemove) {
+ FileSystemURL dir(CreateURLFromUTF8("dir"));
+ FileSystemURL file(CreateURLFromUTF8("file"));
+ FileSystemURL dfile1(CreateURLFromUTF8("dir/dfile1"));
+ FileSystemURL dfile2(CreateURLFromUTF8("dir/dfile2"));
+ bool created;
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ AllowUsageIncrease(PathCost(file))->context(),
+ file, &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(0, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateDirectory(
+ AllowUsageIncrease(PathCost(dir))->context(),
+ dir, false, false));
+ ASSERT_EQ(0, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ AllowUsageIncrease(PathCost(dfile1))->context(),
+ dfile1, &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(0, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ AllowUsageIncrease(PathCost(dfile2))->context(),
+ dfile2, &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(0, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(340)->context(),
+ file, 340));
+ ASSERT_EQ(340, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(1020)->context(),
+ dfile1, 1020));
+ ASSERT_EQ(1360, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(120)->context(),
+ dfile2, 120));
+ ASSERT_EQ(1480, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->DeleteFile(
+ AllowUsageIncrease(-PathCost(file) - 340)->context(),
+ file));
+ ASSERT_EQ(1140, ComputeTotalFileSize());
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::Remove(
+ file_system_context(), dir, true /* recursive */));
+ ASSERT_EQ(0, ComputeTotalFileSize());
+}
+
+TEST_F(ObfuscatedFileUtilTest, TestQuotaOnOpen) {
+ FileSystemURL file(CreateURLFromUTF8("file"));
+ base::PlatformFile file_handle;
+ bool created;
+
+ // Creating a file.
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(
+ AllowUsageIncrease(PathCost(file))->context(),
+ file, &created));
+ ASSERT_TRUE(created);
+ ASSERT_EQ(0, ComputeTotalFileSize());
+
+ // Opening it, which shouldn't change the usage.
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateOrOpen(
+ AllowUsageIncrease(0)->context(), file,
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
+ &file_handle, &created));
+ ASSERT_EQ(0, ComputeTotalFileSize());
+ EXPECT_TRUE(base::ClosePlatformFile(file_handle));
+
+ const int length = 33;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(length)->context(), file, length));
+ ASSERT_EQ(length, ComputeTotalFileSize());
+
+ // Opening it with CREATE_ALWAYS flag, which should truncate the file size.
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateOrOpen(
+ AllowUsageIncrease(-length)->context(), file,
+ base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
+ &file_handle, &created));
+ ASSERT_EQ(0, ComputeTotalFileSize());
+ EXPECT_TRUE(base::ClosePlatformFile(file_handle));
+
+ // Extending the file again.
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->Truncate(
+ AllowUsageIncrease(length)->context(), file, length));
+ ASSERT_EQ(length, ComputeTotalFileSize());
+
+ // Opening it with TRUNCATED flag, which should truncate the file size.
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->CreateOrOpen(
+ AllowUsageIncrease(-length)->context(), file,
+ base::PLATFORM_FILE_OPEN_TRUNCATED | base::PLATFORM_FILE_WRITE,
+ &file_handle, &created));
+ ASSERT_EQ(0, ComputeTotalFileSize());
+ EXPECT_TRUE(base::ClosePlatformFile(file_handle));
+}
+
+TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase) {
+ scoped_ptr<ObfuscatedFileUtil> file_util(
+ ObfuscatedFileUtil::CreateForTesting(
+ NULL, data_dir_path(),
+ base::MessageLoopProxy::current().get()));
+ file_util->InitOriginDatabase(GURL(), true /*create*/);
+ ASSERT_TRUE(file_util->origin_database_ != NULL);
+
+ // Callback to Drop DB is called while ObfuscatedFileUtilTest is still alive.
+ file_util->db_flush_delay_seconds_ = 0;
+ file_util->MarkUsed();
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_TRUE(file_util->origin_database_ == NULL);
+}
+
+TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAlreadyDeletedCase) {
+ // Run message loop after OFU is already deleted to make sure callback doesn't
+ // cause a crash for use after free.
+ {
+ scoped_ptr<ObfuscatedFileUtil> file_util(
+ ObfuscatedFileUtil::CreateForTesting(
+ NULL, data_dir_path(),
+ base::MessageLoopProxy::current().get()));
+ file_util->InitOriginDatabase(GURL(), true /*create*/);
+ file_util->db_flush_delay_seconds_ = 0;
+ file_util->MarkUsed();
+ }
+
+ // At this point the callback is still in the message queue but OFU is gone.
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(ObfuscatedFileUtilTest, DestroyDirectoryDatabase_Isolated) {
+ storage_policy_->AddIsolated(origin_);
+ scoped_ptr<ObfuscatedFileUtil> file_util(
+ ObfuscatedFileUtil::CreateForTesting(
+ storage_policy_.get(), data_dir_path(),
+ base::MessageLoopProxy::current().get()));
+ const FileSystemURL url = FileSystemURL::CreateForTest(
+ origin_, kFileSystemTypePersistent, base::FilePath());
+
+ // Create DirectoryDatabase for isolated origin.
+ SandboxDirectoryDatabase* db =
+ file_util->GetDirectoryDatabase(url, true /* create */);
+ ASSERT_TRUE(db != NULL);
+
+ // Destory it.
+ ASSERT_TRUE(file_util->DestroyDirectoryDatabase(
+ url.origin(), GetTypeString(url.type())));
+ ASSERT_TRUE(file_util->directories_.empty());
+}
+
+TEST_F(ObfuscatedFileUtilTest, GetDirectoryDatabase_Isolated) {
+ storage_policy_->AddIsolated(origin_);
+ scoped_ptr<ObfuscatedFileUtil> file_util(
+ ObfuscatedFileUtil::CreateForTesting(
+ storage_policy_.get(), data_dir_path(),
+ base::MessageLoopProxy::current().get()));
+ const FileSystemURL url = FileSystemURL::CreateForTest(
+ origin_, kFileSystemTypePersistent, base::FilePath());
+
+ // Create DirectoryDatabase for isolated origin.
+ SandboxDirectoryDatabase* db =
+ file_util->GetDirectoryDatabase(url, true /* create */);
+ ASSERT_TRUE(db != NULL);
+ ASSERT_EQ(1U, file_util->directories_.size());
+
+ // Remove isolated.
+ storage_policy_->RemoveIsolated(url.origin());
+
+ // This should still get the same database.
+ SandboxDirectoryDatabase* db2 =
+ file_util->GetDirectoryDatabase(url, false /* create */);
+ ASSERT_EQ(db, db2);
+}
+
+TEST_F(ObfuscatedFileUtilTest, MigrationBackFromIsolated) {
+ std::string kFakeDirectoryData("0123456789");
+ base::FilePath old_directory_db_path;
+
+ // Initialize the directory with one origin using
+ // SandboxIsolatedOriginDatabase.
+ {
+ std::string origin_string =
+ webkit_database::GetIdentifierFromOrigin(origin_);
+ SandboxIsolatedOriginDatabase database_old(
+ origin_string, data_dir_path(),
+ base::FilePath(
+ SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory));
+ base::FilePath path;
+ EXPECT_TRUE(database_old.GetPathForOrigin(origin_string, &path));
+ EXPECT_FALSE(path.empty());
+
+ // Populate the origin directory with some fake data.
+ old_directory_db_path = data_dir_path().Append(path);
+ ASSERT_TRUE(base::CreateDirectory(old_directory_db_path));
+ EXPECT_EQ(static_cast<int>(kFakeDirectoryData.size()),
+ file_util::WriteFile(old_directory_db_path.AppendASCII("dummy"),
+ kFakeDirectoryData.data(),
+ kFakeDirectoryData.size()));
+ }
+
+ storage_policy_->AddIsolated(origin_);
+ scoped_ptr<ObfuscatedFileUtil> file_util(
+ ObfuscatedFileUtil::CreateForTesting(
+ storage_policy_.get(), data_dir_path(),
+ base::MessageLoopProxy::current().get()));
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ base::FilePath origin_directory = file_util->GetDirectoryForOrigin(
+ origin_, true /* create */, &error);
+ EXPECT_EQ(base::PLATFORM_FILE_OK, error);
+
+ // The database is migrated from the old one.
+ EXPECT_TRUE(base::DirectoryExists(origin_directory));
+ EXPECT_FALSE(base::DirectoryExists(old_directory_db_path));
+
+ // Check we see the same contents in the new origin directory.
+ std::string origin_db_data;
+ EXPECT_TRUE(base::PathExists(origin_directory.AppendASCII("dummy")));
+ EXPECT_TRUE(base::ReadFileToString(
+ origin_directory.AppendASCII("dummy"), &origin_db_data));
+ EXPECT_EQ(kFakeDirectoryData, origin_db_data);
+}
+
+TEST_F(ObfuscatedFileUtilTest, OpenPathInNonDirectory) {
+ FileSystemURL file(CreateURLFromUTF8("file"));
+ FileSystemURL path_in_file(CreateURLFromUTF8("file/file"));
+ bool created;
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(UnlimitedContext().get(), file, &created));
+ ASSERT_TRUE(created);
+
+ created = false;
+ base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
+ int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE;
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY,
+ ofu()->CreateOrOpen(UnlimitedContext().get(),
+ path_in_file,
+ file_flags,
+ &file_handle,
+ &created));
+ ASSERT_FALSE(created);
+ ASSERT_EQ(base::kInvalidPlatformFileValue, file_handle);
+
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY,
+ ofu()->CreateDirectory(UnlimitedContext().get(),
+ path_in_file,
+ false /* exclusive */,
+ false /* recursive */));
+}
+
+TEST_F(ObfuscatedFileUtilTest, CreateDirectory_NotADirectoryInRecursive) {
+ FileSystemURL file(CreateURLFromUTF8("file"));
+ FileSystemURL path_in_file(CreateURLFromUTF8("file/child"));
+ FileSystemURL path_in_file_in_file(
+ CreateURLFromUTF8("file/child/grandchild"));
+ bool created;
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ ofu()->EnsureFileExists(UnlimitedContext().get(), file, &created));
+ ASSERT_TRUE(created);
+
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY,
+ ofu()->CreateDirectory(UnlimitedContext().get(),
+ path_in_file,
+ false /* exclusive */,
+ true /* recursive */));
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY,
+ ofu()->CreateDirectory(UnlimitedContext().get(),
+ path_in_file_in_file,
+ false /* exclusive */,
+ true /* recursive */));
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/plugin_private_file_system_backend_unittest.cc b/chromium/content/browser/fileapi/plugin_private_file_system_backend_unittest.cc
new file mode 100644
index 00000000000..0cc2f48bb00
--- /dev/null
+++ b/chromium/content/browser/fileapi/plugin_private_file_system_backend_unittest.cc
@@ -0,0 +1,147 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_file_system_context.h"
+#include "content/public/test/test_file_system_options.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/fileapi/obfuscated_file_util.h"
+#include "webkit/browser/fileapi/plugin_private_file_system_backend.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+namespace fileapi {
+
+namespace {
+
+const GURL kOrigin("http://www.example.com");
+const std::string kPlugin1("plugin1");
+const std::string kPlugin2("plugin2");
+const FileSystemType kType = kFileSystemTypePluginPrivate;
+const std::string kRootName = "pluginprivate";
+
+void DidOpenFileSystem(base::PlatformFileError* error_out,
+ base::PlatformFileError error) {
+ *error_out = error;
+}
+
+std::string RegisterFileSystem() {
+ return IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
+ kType, kRootName, base::FilePath());
+}
+
+} // namespace
+
+class PluginPrivateFileSystemBackendTest : public testing::Test {
+ protected:
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+ context_ = CreateFileSystemContextForTesting(
+ NULL /* quota_manager_proxy */,
+ data_dir_.path());
+ }
+
+ FileSystemURL CreateURL(const GURL& root_url, const std::string& relative) {
+ FileSystemURL root = context_->CrackURL(root_url);
+ return context_->CreateCrackedFileSystemURL(
+ root.origin(),
+ root.mount_type(),
+ root.virtual_path().AppendASCII(relative));
+ }
+
+ PluginPrivateFileSystemBackend* backend() const {
+ return context_->plugin_private_backend();
+ }
+
+ const base::FilePath& base_path() const { return backend()->base_path(); }
+
+ base::ScopedTempDir data_dir_;
+ base::MessageLoop message_loop_;
+ scoped_refptr<FileSystemContext> context_;
+ std::string filesystem_id_;
+};
+
+TEST_F(PluginPrivateFileSystemBackendTest, OpenFileSystemBasic) {
+ const std::string filesystem_id1 = RegisterFileSystem();
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ backend()->OpenPrivateFileSystem(
+ kOrigin, kType, filesystem_id1, kPlugin1,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&DidOpenFileSystem, &error));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+
+ // Run this again with FAIL_IF_NONEXISTENT to see if it succeeds.
+ const std::string filesystem_id2 = RegisterFileSystem();
+ error = base::PLATFORM_FILE_ERROR_FAILED;
+ backend()->OpenPrivateFileSystem(
+ kOrigin, kType, filesystem_id2, kPlugin1,
+ OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+ base::Bind(&DidOpenFileSystem, &error));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+
+ const GURL root_url(
+ GetIsolatedFileSystemRootURIString(kOrigin, filesystem_id1, kRootName));
+ FileSystemURL file = CreateURL(root_url, "foo");
+ base::FilePath platform_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::CreateFile(context_.get(), file));
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::GetPlatformPath(context_.get(), file,
+ &platform_path));
+ EXPECT_TRUE(base_path().AppendASCII("000").AppendASCII(kPlugin1).IsParent(
+ platform_path));
+}
+
+TEST_F(PluginPrivateFileSystemBackendTest, PluginIsolation) {
+ // Open filesystem for kPlugin1 and kPlugin2.
+ const std::string filesystem_id1 = RegisterFileSystem();
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ backend()->OpenPrivateFileSystem(
+ kOrigin, kType, filesystem_id1, kPlugin1,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&DidOpenFileSystem, &error));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+
+ const std::string filesystem_id2 = RegisterFileSystem();
+ error = base::PLATFORM_FILE_ERROR_FAILED;
+ backend()->OpenPrivateFileSystem(
+ kOrigin, kType, filesystem_id2, kPlugin2,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&DidOpenFileSystem, &error));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+
+ // Create 'foo' in kPlugin1.
+ const GURL root_url1(
+ GetIsolatedFileSystemRootURIString(kOrigin, filesystem_id1, kRootName));
+ FileSystemURL file1 = CreateURL(root_url1, "foo");
+ base::FilePath platform_path;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::CreateFile(context_.get(), file1));
+ EXPECT_TRUE(AsyncFileTestHelper::FileExists(
+ context_.get(), file1, AsyncFileTestHelper::kDontCheckSize));
+
+ // See the same path is not available in kPlugin2.
+ const GURL root_url2(
+ GetIsolatedFileSystemRootURIString(kOrigin, filesystem_id2, kRootName));
+ FileSystemURL file2 = CreateURL(root_url2, "foo");
+ EXPECT_FALSE(AsyncFileTestHelper::FileExists(
+ context_.get(), file2, AsyncFileTestHelper::kDontCheckSize));
+}
+
+// TODO(kinuko,nhiroki): also test if DeleteOriginDataOnFileThread
+// works fine when there's multiple plugin partitions.
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc b/chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc
new file mode 100644
index 00000000000..d3671fe89f8
--- /dev/null
+++ b/chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc
@@ -0,0 +1,280 @@
+// 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 "webkit/browser/fileapi/recursive_operation_delegate.h"
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
+#include "content/public/test/sandbox_file_system_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/file_system_file_util.h"
+#include "webkit/browser/fileapi/file_system_operation.h"
+#include "webkit/browser/fileapi/file_system_operation_runner.h"
+
+namespace fileapi {
+namespace {
+
+class LoggingRecursiveOperation : public RecursiveOperationDelegate {
+ public:
+ struct LogEntry {
+ enum Type {
+ PROCESS_FILE,
+ PROCESS_DIRECTORY,
+ POST_PROCESS_DIRECTORY
+ };
+ Type type;
+ FileSystemURL url;
+ };
+
+ LoggingRecursiveOperation(FileSystemContext* file_system_context,
+ const FileSystemURL& root,
+ const StatusCallback& callback)
+ : RecursiveOperationDelegate(file_system_context),
+ root_(root),
+ callback_(callback),
+ weak_factory_(this) {
+ }
+ virtual ~LoggingRecursiveOperation() {}
+
+ const std::vector<LogEntry>& log_entries() const { return log_entries_; }
+
+ // RecursiveOperationDelegate overrides.
+ virtual void Run() OVERRIDE {
+ NOTREACHED();
+ }
+
+ virtual void RunRecursively() OVERRIDE {
+ StartRecursiveOperation(root_, callback_);
+ }
+
+ virtual void ProcessFile(const FileSystemURL& url,
+ const StatusCallback& callback) OVERRIDE {
+ RecordLogEntry(LogEntry::PROCESS_FILE, url);
+ operation_runner()->GetMetadata(
+ url,
+ base::Bind(&LoggingRecursiveOperation::DidGetMetadata,
+ weak_factory_.GetWeakPtr(), callback));
+ }
+
+ virtual void ProcessDirectory(const FileSystemURL& url,
+ const StatusCallback& callback) OVERRIDE {
+ RecordLogEntry(LogEntry::PROCESS_DIRECTORY, url);
+ callback.Run(base::PLATFORM_FILE_OK);
+ }
+
+ virtual void PostProcessDirectory(const FileSystemURL& url,
+ const StatusCallback& callback) OVERRIDE {
+ RecordLogEntry(LogEntry::POST_PROCESS_DIRECTORY, url);
+ callback.Run(base::PLATFORM_FILE_OK);
+ }
+
+ private:
+ void RecordLogEntry(LogEntry::Type type, const FileSystemURL& url) {
+ LogEntry entry;
+ entry.type = type;
+ entry.url = url;
+ log_entries_.push_back(entry);
+ }
+
+ void DidGetMetadata(const StatusCallback& callback,
+ base::PlatformFileError result,
+ const base::PlatformFileInfo& file_info) {
+ if (result != base::PLATFORM_FILE_OK) {
+ callback.Run(result);
+ return;
+ }
+
+ callback.Run(file_info.is_directory ?
+ base::PLATFORM_FILE_ERROR_NOT_A_FILE :
+ base::PLATFORM_FILE_OK);
+ }
+
+ FileSystemURL root_;
+ StatusCallback callback_;
+ std::vector<LogEntry> log_entries_;
+
+ base::WeakPtrFactory<LoggingRecursiveOperation> weak_factory_;
+ DISALLOW_COPY_AND_ASSIGN(LoggingRecursiveOperation);
+};
+
+void ReportStatus(base::PlatformFileError* out_error,
+ base::PlatformFileError error) {
+ DCHECK(out_error);
+ *out_error = error;
+}
+
+// To test the Cancel() during operation, calls Cancel() of |operation|
+// after |counter| times message posting.
+void CallCancelLater(RecursiveOperationDelegate* operation, int counter) {
+ if (counter > 0) {
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&CallCancelLater, base::Unretained(operation), counter - 1));
+ return;
+ }
+
+ operation->Cancel();
+}
+
+} // namespace
+
+class RecursiveOperationDelegateTest : public testing::Test {
+ protected:
+ virtual void SetUp() OVERRIDE {
+ EXPECT_TRUE(base_.CreateUniqueTempDir());
+ sandbox_file_system_.SetUp(base_.path().AppendASCII("filesystem"));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ sandbox_file_system_.TearDown();
+ }
+
+ scoped_ptr<FileSystemOperationContext> NewContext() {
+ FileSystemOperationContext* context =
+ sandbox_file_system_.NewOperationContext();
+ // Grant enough quota for all test cases.
+ context->set_allowed_bytes_growth(1000000);
+ return make_scoped_ptr(context);
+ }
+
+ FileSystemFileUtil* file_util() {
+ return sandbox_file_system_.file_util();
+ }
+
+ FileSystemURL URLForPath(const std::string& path) const {
+ return sandbox_file_system_.CreateURLFromUTF8(path);
+ }
+
+ FileSystemURL CreateFile(const std::string& path) {
+ FileSystemURL url = URLForPath(path);
+ bool created = false;
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->EnsureFileExists(NewContext().get(),
+ url, &created));
+ EXPECT_TRUE(created);
+ return url;
+ }
+
+ FileSystemURL CreateDirectory(const std::string& path) {
+ FileSystemURL url = URLForPath(path);
+ EXPECT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->CreateDirectory(NewContext().get(), url,
+ false /* exclusive */, true));
+ return url;
+ }
+
+ private:
+ base::MessageLoop message_loop_;
+
+ // Common temp base for nondestructive uses.
+ base::ScopedTempDir base_;
+ SandboxFileSystemTestHelper sandbox_file_system_;
+};
+
+TEST_F(RecursiveOperationDelegateTest, RootIsFile) {
+ FileSystemURL src_file(CreateFile("src"));
+
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ scoped_ptr<FileSystemOperationContext> context = NewContext();
+ scoped_ptr<LoggingRecursiveOperation> operation(
+ new LoggingRecursiveOperation(
+ context->file_system_context(), src_file,
+ base::Bind(&ReportStatus, &error)));
+ operation->RunRecursively();
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+
+ const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
+ operation->log_entries();
+ ASSERT_EQ(1U, log_entries.size());
+ const LoggingRecursiveOperation::LogEntry& entry = log_entries[0];
+ EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, entry.type);
+ EXPECT_EQ(src_file, entry.url);
+}
+
+TEST_F(RecursiveOperationDelegateTest, RootIsDirectory) {
+ FileSystemURL src_root(CreateDirectory("src"));
+ FileSystemURL src_dir1(CreateDirectory("src/dir1"));
+ FileSystemURL src_file1(CreateFile("src/file1"));
+ FileSystemURL src_file2(CreateFile("src/dir1/file2"));
+ FileSystemURL src_file3(CreateFile("src/dir1/file3"));
+
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ scoped_ptr<FileSystemOperationContext> context = NewContext();
+ scoped_ptr<LoggingRecursiveOperation> operation(
+ new LoggingRecursiveOperation(
+ context->file_system_context(), src_root,
+ base::Bind(&ReportStatus, &error)));
+ operation->RunRecursively();
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+
+ const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
+ operation->log_entries();
+ ASSERT_EQ(8U, log_entries.size());
+
+ EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
+ log_entries[0].type);
+ EXPECT_EQ(src_root, log_entries[0].url);
+
+ EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
+ log_entries[1].type);
+ EXPECT_EQ(src_root, log_entries[1].url);
+
+ EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
+ log_entries[2].type);
+ EXPECT_EQ(src_file1, log_entries[2].url);
+
+ EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
+ log_entries[3].type);
+ EXPECT_EQ(src_dir1, log_entries[3].url);
+
+ // The order of src/dir1/file2 and src/dir1/file3 depends on the file system
+ // implementation (can be swapped).
+ EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
+ log_entries[4].type);
+ EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
+ log_entries[5].type);
+ EXPECT_TRUE((src_file2 == log_entries[4].url &&
+ src_file3 == log_entries[5].url) ||
+ (src_file3 == log_entries[4].url &&
+ src_file2 == log_entries[5].url));
+
+ EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
+ log_entries[6].type);
+ EXPECT_EQ(src_dir1, log_entries[6].url);
+
+ EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
+ log_entries[7].type);
+ EXPECT_EQ(src_root, log_entries[7].url);
+}
+
+TEST_F(RecursiveOperationDelegateTest, Cancel) {
+ FileSystemURL src_root(CreateDirectory("src"));
+ FileSystemURL src_dir1(CreateDirectory("src/dir1"));
+ FileSystemURL src_file1(CreateFile("src/file1"));
+ FileSystemURL src_file2(CreateFile("src/dir1/file2"));
+
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ scoped_ptr<FileSystemOperationContext> context = NewContext();
+ scoped_ptr<LoggingRecursiveOperation> operation(
+ new LoggingRecursiveOperation(
+ context->file_system_context(), src_root,
+ base::Bind(&ReportStatus, &error)));
+ operation->RunRecursively();
+
+ // Invoke Cancel(), after 5 times message posting.
+ CallCancelLater(operation.get(), 5);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_ABORT, error);
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc b/chromium/content/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc
new file mode 100644
index 00000000000..c87043b74ca
--- /dev/null
+++ b/chromium/content/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc
@@ -0,0 +1,82 @@
+// 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 "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
+
+#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "content/public/test/test_file_system_options.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+
+namespace fileapi {
+
+namespace {
+
+FileSystemURL CreateFileSystemURL(const char* path) {
+ const GURL kOrigin("http://foo/");
+ return FileSystemURL::CreateForTest(
+ kOrigin, kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe(path));
+}
+
+} // namespace
+
+class SandboxFileSystemBackendDelegateTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+ delegate_.reset(new SandboxFileSystemBackendDelegate(
+ NULL /* quota_manager_proxy */,
+ base::MessageLoopProxy::current().get(),
+ data_dir_.path(),
+ NULL /* special_storage_policy */,
+ CreateAllowFileAccessOptions()));
+ }
+
+ base::ScopedTempDir data_dir_;
+ base::MessageLoop message_loop_;
+ scoped_ptr<SandboxFileSystemBackendDelegate> delegate_;
+};
+
+TEST_F(SandboxFileSystemBackendDelegateTest, IsAccessValid) {
+ // Normal case.
+ EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL("a")));
+
+ // Access to a path with parent references ('..') should be disallowed.
+ EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL("a/../b")));
+
+ // Access from non-allowed scheme should be disallowed.
+ EXPECT_FALSE(delegate_->IsAccessValid(
+ FileSystemURL::CreateForTest(
+ GURL("unknown://bar"), kFileSystemTypeTemporary,
+ base::FilePath::FromUTF8Unsafe("foo"))));
+
+ // Access with restricted name should be disallowed.
+ EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL(".")));
+ EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL("..")));
+
+ // This is also disallowed due to Windows XP parent path handling.
+ EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL("...")));
+
+ // These are identified as unsafe cases due to weird path handling
+ // on Windows.
+ EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL(" ..")));
+ EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL(".. ")));
+
+ // Similar but safe cases.
+ EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL(" .")));
+ EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL(". ")));
+ EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL("b.")));
+ EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL(".b")));
+
+ // A path that looks like a drive letter.
+ EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL("c:")));
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/sandbox_file_system_backend_unittest.cc b/chromium/content/browser/fileapi/sandbox_file_system_backend_unittest.cc
new file mode 100644
index 00000000000..4bb12261a97
--- /dev/null
+++ b/chromium/content/browser/fileapi/sandbox_file_system_backend_unittest.cc
@@ -0,0 +1,319 @@
+// 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 "webkit/browser/fileapi/sandbox_file_system_backend.h"
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_file_system_options.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "webkit/browser/fileapi/file_system_backend.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+// PS stands for path separator.
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+#define PS "\\"
+#else
+#define PS "/"
+#endif
+
+namespace fileapi {
+
+namespace {
+
+const struct RootPathTest {
+ fileapi::FileSystemType type;
+ const char* origin_url;
+ const char* expected_path;
+} kRootPathTestCases[] = {
+ { fileapi::kFileSystemTypeTemporary, "http://foo:1/",
+ "000" PS "t" },
+ { fileapi::kFileSystemTypePersistent, "http://foo:1/",
+ "000" PS "p" },
+ { fileapi::kFileSystemTypeTemporary, "http://bar.com/",
+ "001" PS "t" },
+ { fileapi::kFileSystemTypePersistent, "http://bar.com/",
+ "001" PS "p" },
+ { fileapi::kFileSystemTypeTemporary, "https://foo:2/",
+ "002" PS "t" },
+ { fileapi::kFileSystemTypePersistent, "https://foo:2/",
+ "002" PS "p" },
+ { fileapi::kFileSystemTypeTemporary, "https://bar.com/",
+ "003" PS "t" },
+ { fileapi::kFileSystemTypePersistent, "https://bar.com/",
+ "003" PS "p" },
+};
+
+const struct RootPathFileURITest {
+ fileapi::FileSystemType type;
+ const char* origin_url;
+ const char* expected_path;
+ const char* virtual_path;
+} kRootPathFileURITestCases[] = {
+ { fileapi::kFileSystemTypeTemporary, "file:///",
+ "000" PS "t", NULL },
+ { fileapi::kFileSystemTypePersistent, "file:///",
+ "000" PS "p", NULL },
+};
+
+void DidOpenFileSystem(base::PlatformFileError* error_out,
+ const GURL& origin_url,
+ const std::string& name,
+ base::PlatformFileError error) {
+ *error_out = error;
+}
+
+} // namespace
+
+class SandboxFileSystemBackendTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+ SetUpNewDelegate(CreateAllowFileAccessOptions());
+ }
+
+ void SetUpNewDelegate(const FileSystemOptions& options) {
+ delegate_.reset(new SandboxFileSystemBackendDelegate(
+ NULL /* quota_manager_proxy */,
+ base::MessageLoopProxy::current().get(),
+ data_dir_.path(),
+ NULL /* special_storage_policy */,
+ options));
+ }
+
+ void SetUpNewBackend(const FileSystemOptions& options) {
+ SetUpNewDelegate(options);
+ backend_.reset(new SandboxFileSystemBackend(delegate_.get()));
+ }
+
+ SandboxFileSystemBackendDelegate::OriginEnumerator*
+ CreateOriginEnumerator() const {
+ return backend_->CreateOriginEnumerator();
+ }
+
+ void CreateOriginTypeDirectory(const GURL& origin,
+ fileapi::FileSystemType type) {
+ base::FilePath target = delegate_->
+ GetBaseDirectoryForOriginAndType(origin, type, true);
+ ASSERT_TRUE(!target.empty());
+ ASSERT_TRUE(base::DirectoryExists(target));
+ }
+
+ bool GetRootPath(const GURL& origin_url,
+ fileapi::FileSystemType type,
+ OpenFileSystemMode mode,
+ base::FilePath* root_path) {
+ base::PlatformFileError error = base::PLATFORM_FILE_OK;
+ backend_->OpenFileSystem(
+ origin_url, type, mode,
+ base::Bind(&DidOpenFileSystem, &error));
+ base::RunLoop().RunUntilIdle();
+ if (error != base::PLATFORM_FILE_OK)
+ return false;
+ base::FilePath returned_root_path =
+ delegate_->GetBaseDirectoryForOriginAndType(
+ origin_url, type, false /* create */);
+ if (root_path)
+ *root_path = returned_root_path;
+ return !returned_root_path.empty();
+ }
+
+ base::FilePath file_system_path() const {
+ return data_dir_.path().Append(
+ SandboxFileSystemBackendDelegate::kFileSystemDirectory);
+ }
+
+ base::ScopedTempDir data_dir_;
+ base::MessageLoop message_loop_;
+ scoped_ptr<SandboxFileSystemBackendDelegate> delegate_;
+ scoped_ptr<SandboxFileSystemBackend> backend_;
+};
+
+TEST_F(SandboxFileSystemBackendTest, Empty) {
+ SetUpNewBackend(CreateAllowFileAccessOptions());
+ scoped_ptr<SandboxFileSystemBackendDelegate::OriginEnumerator> enumerator(
+ CreateOriginEnumerator());
+ ASSERT_TRUE(enumerator->Next().is_empty());
+}
+
+TEST_F(SandboxFileSystemBackendTest, EnumerateOrigins) {
+ SetUpNewBackend(CreateAllowFileAccessOptions());
+ const char* temporary_origins[] = {
+ "http://www.bar.com/",
+ "http://www.foo.com/",
+ "http://www.foo.com:1/",
+ "http://www.example.com:8080/",
+ "http://www.google.com:80/",
+ };
+ const char* persistent_origins[] = {
+ "http://www.bar.com/",
+ "http://www.foo.com:8080/",
+ "http://www.foo.com:80/",
+ };
+ size_t temporary_size = ARRAYSIZE_UNSAFE(temporary_origins);
+ size_t persistent_size = ARRAYSIZE_UNSAFE(persistent_origins);
+ std::set<GURL> temporary_set, persistent_set;
+ for (size_t i = 0; i < temporary_size; ++i) {
+ CreateOriginTypeDirectory(GURL(temporary_origins[i]),
+ fileapi::kFileSystemTypeTemporary);
+ temporary_set.insert(GURL(temporary_origins[i]));
+ }
+ for (size_t i = 0; i < persistent_size; ++i) {
+ CreateOriginTypeDirectory(GURL(persistent_origins[i]),
+ kFileSystemTypePersistent);
+ persistent_set.insert(GURL(persistent_origins[i]));
+ }
+
+ scoped_ptr<SandboxFileSystemBackendDelegate::OriginEnumerator> enumerator(
+ CreateOriginEnumerator());
+ size_t temporary_actual_size = 0;
+ size_t persistent_actual_size = 0;
+ GURL current;
+ while (!(current = enumerator->Next()).is_empty()) {
+ SCOPED_TRACE(testing::Message() << "EnumerateOrigin " << current.spec());
+ if (enumerator->HasFileSystemType(kFileSystemTypeTemporary)) {
+ ASSERT_TRUE(temporary_set.find(current) != temporary_set.end());
+ ++temporary_actual_size;
+ }
+ if (enumerator->HasFileSystemType(kFileSystemTypePersistent)) {
+ ASSERT_TRUE(persistent_set.find(current) != persistent_set.end());
+ ++persistent_actual_size;
+ }
+ }
+
+ EXPECT_EQ(temporary_size, temporary_actual_size);
+ EXPECT_EQ(persistent_size, persistent_actual_size);
+}
+
+TEST_F(SandboxFileSystemBackendTest, GetRootPathCreateAndExamine) {
+ std::vector<base::FilePath> returned_root_path(
+ ARRAYSIZE_UNSAFE(kRootPathTestCases));
+ SetUpNewBackend(CreateAllowFileAccessOptions());
+
+ // Create a new root directory.
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "RootPath (create) #" << i << " "
+ << kRootPathTestCases[i].expected_path);
+
+ base::FilePath root_path;
+ EXPECT_TRUE(GetRootPath(GURL(kRootPathTestCases[i].origin_url),
+ kRootPathTestCases[i].type,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ &root_path));
+
+ base::FilePath expected = file_system_path().AppendASCII(
+ kRootPathTestCases[i].expected_path);
+ EXPECT_EQ(expected.value(), root_path.value());
+ EXPECT_TRUE(base::DirectoryExists(root_path));
+ ASSERT_TRUE(returned_root_path.size() > i);
+ returned_root_path[i] = root_path;
+ }
+
+ // Get the root directory with create=false and see if we get the
+ // same directory.
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "RootPath (get) #" << i << " "
+ << kRootPathTestCases[i].expected_path);
+
+ base::FilePath root_path;
+ EXPECT_TRUE(GetRootPath(GURL(kRootPathTestCases[i].origin_url),
+ kRootPathTestCases[i].type,
+ OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+ &root_path));
+ ASSERT_TRUE(returned_root_path.size() > i);
+ EXPECT_EQ(returned_root_path[i].value(), root_path.value());
+ }
+}
+
+TEST_F(SandboxFileSystemBackendTest,
+ GetRootPathCreateAndExamineWithNewBackend) {
+ std::vector<base::FilePath> returned_root_path(
+ ARRAYSIZE_UNSAFE(kRootPathTestCases));
+ SetUpNewBackend(CreateAllowFileAccessOptions());
+
+ GURL origin_url("http://foo.com:1/");
+
+ base::FilePath root_path1;
+ EXPECT_TRUE(GetRootPath(origin_url, kFileSystemTypeTemporary,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ &root_path1));
+
+ SetUpNewBackend(CreateDisallowFileAccessOptions());
+ base::FilePath root_path2;
+ EXPECT_TRUE(GetRootPath(origin_url, kFileSystemTypeTemporary,
+ OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+ &root_path2));
+
+ EXPECT_EQ(root_path1.value(), root_path2.value());
+}
+
+TEST_F(SandboxFileSystemBackendTest, GetRootPathGetWithoutCreate) {
+ SetUpNewBackend(CreateDisallowFileAccessOptions());
+
+ // Try to get a root directory without creating.
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "RootPath (create=false) #" << i << " "
+ << kRootPathTestCases[i].expected_path);
+ EXPECT_FALSE(GetRootPath(GURL(kRootPathTestCases[i].origin_url),
+ kRootPathTestCases[i].type,
+ OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+ NULL));
+ }
+}
+
+TEST_F(SandboxFileSystemBackendTest, GetRootPathInIncognito) {
+ SetUpNewBackend(CreateIncognitoFileSystemOptions());
+
+ // Try to get a root directory.
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "RootPath (incognito) #" << i << " "
+ << kRootPathTestCases[i].expected_path);
+ EXPECT_FALSE(
+ GetRootPath(GURL(kRootPathTestCases[i].origin_url),
+ kRootPathTestCases[i].type,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ NULL));
+ }
+}
+
+TEST_F(SandboxFileSystemBackendTest, GetRootPathFileURI) {
+ SetUpNewBackend(CreateDisallowFileAccessOptions());
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathFileURITestCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "RootPathFileURI (disallow) #"
+ << i << " " << kRootPathFileURITestCases[i].expected_path);
+ EXPECT_FALSE(
+ GetRootPath(GURL(kRootPathFileURITestCases[i].origin_url),
+ kRootPathFileURITestCases[i].type,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ NULL));
+ }
+}
+
+TEST_F(SandboxFileSystemBackendTest, GetRootPathFileURIWithAllowFlag) {
+ SetUpNewBackend(CreateAllowFileAccessOptions());
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathFileURITestCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "RootPathFileURI (allow) #"
+ << i << " " << kRootPathFileURITestCases[i].expected_path);
+ base::FilePath root_path;
+ EXPECT_TRUE(GetRootPath(GURL(kRootPathFileURITestCases[i].origin_url),
+ kRootPathFileURITestCases[i].type,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ &root_path));
+ base::FilePath expected = file_system_path().AppendASCII(
+ kRootPathFileURITestCases[i].expected_path);
+ EXPECT_EQ(expected.value(), root_path.value());
+ EXPECT_TRUE(base::DirectoryExists(root_path));
+ }
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/transient_file_util_unittest.cc b/chromium/content/browser/fileapi/transient_file_util_unittest.cc
new file mode 100644
index 00000000000..2ddb315c55f
--- /dev/null
+++ b/chromium/content/browser/fileapi/transient_file_util_unittest.cc
@@ -0,0 +1,121 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/platform_file.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_file_system_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/fileapi/transient_file_util.h"
+#include "webkit/common/blob/scoped_file.h"
+
+namespace fileapi {
+
+class TransientFileUtilTest : public testing::Test {
+ public:
+ TransientFileUtilTest() {}
+ virtual ~TransientFileUtilTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ file_system_context_ = CreateFileSystemContextForTesting(
+ NULL, base::FilePath(FILE_PATH_LITERAL("dummy")));
+ transient_file_util_.reset(new TransientFileUtil);
+
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+ }
+
+ virtual void TearDown() OVERRIDE {
+ file_system_context_ = NULL;
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void CreateAndRegisterTemporaryFile(
+ FileSystemURL* file_url,
+ base::FilePath* file_path) {
+ EXPECT_TRUE(base::CreateTemporaryFileInDir(data_dir_.path(), file_path));
+ IsolatedContext* isolated_context = IsolatedContext::GetInstance();
+ std::string name = "tmp";
+ std::string fsid = isolated_context->RegisterFileSystemForPath(
+ kFileSystemTypeForTransientFile,
+ *file_path,
+ &name);
+ ASSERT_TRUE(!fsid.empty());
+ base::FilePath virtual_path = isolated_context->CreateVirtualRootPath(
+ fsid).AppendASCII(name);
+ *file_url = file_system_context_->CreateCrackedFileSystemURL(
+ GURL("http://foo"),
+ kFileSystemTypeIsolated,
+ virtual_path);
+ }
+
+ scoped_ptr<FileSystemOperationContext> NewOperationContext() {
+ return make_scoped_ptr(
+ new FileSystemOperationContext(file_system_context_.get()));
+ }
+
+ FileSystemFileUtil* file_util() { return transient_file_util_.get(); }
+
+ private:
+ base::MessageLoop message_loop_;
+ base::ScopedTempDir data_dir_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ scoped_ptr<TransientFileUtil> transient_file_util_;
+
+ DISALLOW_COPY_AND_ASSIGN(TransientFileUtilTest);
+};
+
+TEST_F(TransientFileUtilTest, TransientFile) {
+ FileSystemURL temp_url;
+ base::FilePath temp_path;
+
+ CreateAndRegisterTemporaryFile(&temp_url, &temp_path);
+
+ base::PlatformFileError error;
+ base::PlatformFileInfo file_info;
+ base::FilePath path;
+
+ // Make sure the file is there.
+ ASSERT_TRUE(temp_url.is_valid());
+ ASSERT_TRUE(base::PathExists(temp_path));
+ ASSERT_FALSE(base::DirectoryExists(temp_path));
+
+ // Create a snapshot file.
+ {
+ webkit_blob::ScopedFile scoped_file =
+ file_util()->CreateSnapshotFile(NewOperationContext().get(),
+ temp_url,
+ &error,
+ &file_info,
+ &path);
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+ ASSERT_EQ(temp_path, path);
+ ASSERT_FALSE(file_info.is_directory);
+
+ // The file should be still there.
+ ASSERT_TRUE(base::PathExists(temp_path));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ file_util()->GetFileInfo(NewOperationContext().get(),
+ temp_url, &file_info, &path));
+ ASSERT_EQ(temp_path, path);
+ ASSERT_FALSE(file_info.is_directory);
+ }
+
+ // The file's now scoped out.
+ base::RunLoop().RunUntilIdle();
+
+ // Now the temporary file and the transient filesystem must be gone too.
+ ASSERT_FALSE(base::PathExists(temp_path));
+ ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ file_util()->GetFileInfo(NewOperationContext().get(),
+ temp_url, &file_info, &path));
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc b/chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
new file mode 100644
index 00000000000..4ae03b9b344
--- /dev/null
+++ b/chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
@@ -0,0 +1,278 @@
+// 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 "webkit/browser/fileapi/upload_file_system_file_element_reader.h"
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_file_system_context.h"
+#include "net/base/io_buffer.h"
+#include "net/base/test_completion_callback.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/async_file_test_helper.h"
+#include "webkit/browser/fileapi/file_system_backend.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+
+namespace fileapi {
+
+namespace {
+
+const char kFileSystemURLOrigin[] = "http://remote";
+const fileapi::FileSystemType kFileSystemType =
+ fileapi::kFileSystemTypeTemporary;
+
+} // namespace
+
+class UploadFileSystemFileElementReaderTest : public testing::Test {
+ public:
+ UploadFileSystemFileElementReaderTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ file_system_context_ = fileapi::CreateFileSystemContextForTesting(
+ NULL, temp_dir_.path());
+
+ file_system_context_->OpenFileSystem(
+ GURL(kFileSystemURLOrigin),
+ kFileSystemType,
+ OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&UploadFileSystemFileElementReaderTest::OnOpenFileSystem,
+ base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(file_system_root_url_.is_valid());
+
+ // Prepare a file on file system.
+ const char kTestData[] = "abcdefghijklmnop0123456789";
+ file_data_.assign(kTestData, kTestData + arraysize(kTestData) - 1);
+ const char kFilename[] = "File.dat";
+ file_url_ = GetFileSystemURL(kFilename);
+ WriteFileSystemFile(kFilename, &file_data_[0], file_data_.size(),
+ &file_modification_time_);
+
+ // Create and initialize a reader.
+ reader_.reset(
+ new UploadFileSystemFileElementReader(file_system_context_.get(),
+ file_url_,
+ 0,
+ kuint64max,
+ file_modification_time_));
+ net::TestCompletionCallback callback;
+ ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(callback.callback()));
+ EXPECT_EQ(net::OK, callback.WaitForResult());
+ EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
+ EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
+ EXPECT_FALSE(reader_->IsInMemory());
+ }
+
+ virtual void TearDown() OVERRIDE {
+ reader_.reset();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ protected:
+ GURL GetFileSystemURL(const std::string& filename) {
+ return GURL(file_system_root_url_.spec() + filename);
+ }
+
+ void WriteFileSystemFile(const std::string& filename,
+ const char* buf,
+ int buf_size,
+ base::Time* modification_time) {
+ fileapi::FileSystemURL url =
+ file_system_context_->CreateCrackedFileSystemURL(
+ GURL(kFileSystemURLOrigin),
+ kFileSystemType,
+ base::FilePath().AppendASCII(filename));
+
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::CreateFileWithData(
+ file_system_context_, url, buf, buf_size));
+
+ base::PlatformFileInfo file_info;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ AsyncFileTestHelper::GetMetadata(
+ file_system_context_, url, &file_info));
+ *modification_time = file_info.last_modified;
+ }
+
+ void OnOpenFileSystem(const GURL& root,
+ const std::string& name,
+ base::PlatformFileError result) {
+ ASSERT_EQ(base::PLATFORM_FILE_OK, result);
+ ASSERT_TRUE(root.is_valid());
+ file_system_root_url_ = root;
+ }
+
+ base::MessageLoopForIO message_loop_;
+ base::ScopedTempDir temp_dir_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ GURL file_system_root_url_;
+ std::vector<char> file_data_;
+ GURL file_url_;
+ base::Time file_modification_time_;
+ scoped_ptr<UploadFileSystemFileElementReader> reader_;
+};
+
+TEST_F(UploadFileSystemFileElementReaderTest, ReadAll) {
+ scoped_refptr<net::IOBufferWithSize> buf =
+ new net::IOBufferWithSize(file_data_.size());
+ net::TestCompletionCallback read_callback;
+ ASSERT_EQ(net::ERR_IO_PENDING,
+ reader_->Read(buf.get(), buf->size(), read_callback.callback()));
+ EXPECT_EQ(buf->size(), read_callback.WaitForResult());
+ EXPECT_EQ(0U, reader_->BytesRemaining());
+ EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
+ // Try to read again.
+ EXPECT_EQ(0, reader_->Read(buf.get(), buf->size(), read_callback.callback()));
+}
+
+TEST_F(UploadFileSystemFileElementReaderTest, ReadPartially) {
+ const size_t kHalfSize = file_data_.size() / 2;
+ ASSERT_EQ(file_data_.size(), kHalfSize * 2);
+
+ scoped_refptr<net::IOBufferWithSize> buf =
+ new net::IOBufferWithSize(kHalfSize);
+
+ net::TestCompletionCallback read_callback1;
+ ASSERT_EQ(net::ERR_IO_PENDING,
+ reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
+ EXPECT_EQ(buf->size(), read_callback1.WaitForResult());
+ EXPECT_EQ(file_data_.size() - buf->size(), reader_->BytesRemaining());
+ EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.begin() + kHalfSize,
+ buf->data()));
+
+ net::TestCompletionCallback read_callback2;
+ EXPECT_EQ(net::ERR_IO_PENDING,
+ reader_->Read(buf.get(), buf->size(), read_callback2.callback()));
+ EXPECT_EQ(buf->size(), read_callback2.WaitForResult());
+ EXPECT_EQ(0U, reader_->BytesRemaining());
+ EXPECT_TRUE(std::equal(file_data_.begin() + kHalfSize, file_data_.end(),
+ buf->data()));
+}
+
+TEST_F(UploadFileSystemFileElementReaderTest, ReadTooMuch) {
+ const size_t kTooLargeSize = file_data_.size() * 2;
+ scoped_refptr<net::IOBufferWithSize> buf =
+ new net::IOBufferWithSize(kTooLargeSize);
+ net::TestCompletionCallback read_callback;
+ ASSERT_EQ(net::ERR_IO_PENDING,
+ reader_->Read(buf.get(), buf->size(), read_callback.callback()));
+ EXPECT_EQ(static_cast<int>(file_data_.size()), read_callback.WaitForResult());
+ EXPECT_EQ(0U, reader_->BytesRemaining());
+ EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
+}
+
+TEST_F(UploadFileSystemFileElementReaderTest, MultipleInit) {
+ scoped_refptr<net::IOBufferWithSize> buf =
+ new net::IOBufferWithSize(file_data_.size());
+
+ // Read all.
+ net::TestCompletionCallback read_callback1;
+ ASSERT_EQ(net::ERR_IO_PENDING,
+ reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
+ EXPECT_EQ(buf->size(), read_callback1.WaitForResult());
+ EXPECT_EQ(0U, reader_->BytesRemaining());
+ EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
+
+ // Call Init() again to reset the state.
+ net::TestCompletionCallback init_callback;
+ ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
+ EXPECT_EQ(net::OK, init_callback.WaitForResult());
+ EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
+ EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
+
+ // Read again.
+ net::TestCompletionCallback read_callback2;
+ ASSERT_EQ(net::ERR_IO_PENDING,
+ reader_->Read(buf.get(), buf->size(), read_callback2.callback()));
+ EXPECT_EQ(buf->size(), read_callback2.WaitForResult());
+ EXPECT_EQ(0U, reader_->BytesRemaining());
+ EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
+}
+
+TEST_F(UploadFileSystemFileElementReaderTest, InitDuringAsyncOperation) {
+ scoped_refptr<net::IOBufferWithSize> buf =
+ new net::IOBufferWithSize(file_data_.size());
+
+ // Start reading all.
+ net::TestCompletionCallback read_callback1;
+ EXPECT_EQ(net::ERR_IO_PENDING,
+ reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
+
+ // Call Init to cancel the previous read.
+ net::TestCompletionCallback init_callback1;
+ EXPECT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback1.callback()));
+
+ // Call Init again to cancel the previous init.
+ net::TestCompletionCallback init_callback2;
+ EXPECT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback2.callback()));
+ EXPECT_EQ(net::OK, init_callback2.WaitForResult());
+ EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
+ EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
+
+ // Read half.
+ scoped_refptr<net::IOBufferWithSize> buf2 =
+ new net::IOBufferWithSize(file_data_.size() / 2);
+ net::TestCompletionCallback read_callback2;
+ EXPECT_EQ(net::ERR_IO_PENDING,
+ reader_->Read(buf2.get(), buf2->size(), read_callback2.callback()));
+ EXPECT_EQ(buf2->size(), read_callback2.WaitForResult());
+ EXPECT_EQ(file_data_.size() - buf2->size(), reader_->BytesRemaining());
+ EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.begin() + buf2->size(),
+ buf2->data()));
+
+ // Make sure callbacks are not called for cancelled operations.
+ EXPECT_FALSE(read_callback1.have_result());
+ EXPECT_FALSE(init_callback1.have_result());
+}
+
+TEST_F(UploadFileSystemFileElementReaderTest, Range) {
+ const int kOffset = 2;
+ const int kLength = file_data_.size() - kOffset * 3;
+ reader_.reset(new UploadFileSystemFileElementReader(
+ file_system_context_.get(), file_url_, kOffset, kLength, base::Time()));
+ net::TestCompletionCallback init_callback;
+ ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
+ EXPECT_EQ(net::OK, init_callback.WaitForResult());
+ EXPECT_EQ(static_cast<uint64>(kLength), reader_->GetContentLength());
+ EXPECT_EQ(static_cast<uint64>(kLength), reader_->BytesRemaining());
+ scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(kLength);
+ net::TestCompletionCallback read_callback;
+ ASSERT_EQ(net::ERR_IO_PENDING,
+ reader_->Read(buf.get(), buf->size(), read_callback.callback()));
+ EXPECT_EQ(kLength, read_callback.WaitForResult());
+ EXPECT_TRUE(std::equal(file_data_.begin() + kOffset,
+ file_data_.begin() + kOffset + kLength,
+ buf->data()));
+}
+
+TEST_F(UploadFileSystemFileElementReaderTest, FileChanged) {
+ // Expect one second before the actual modification time to simulate change.
+ const base::Time expected_modification_time =
+ file_modification_time_ - base::TimeDelta::FromSeconds(1);
+ reader_.reset(
+ new UploadFileSystemFileElementReader(file_system_context_.get(),
+ file_url_,
+ 0,
+ kuint64max,
+ expected_modification_time));
+ net::TestCompletionCallback init_callback;
+ ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
+ EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, init_callback.WaitForResult());
+}
+
+TEST_F(UploadFileSystemFileElementReaderTest, WrongURL) {
+ const GURL wrong_url = GetFileSystemURL("wrong_file_name.dat");
+ reader_.reset(new UploadFileSystemFileElementReader(
+ file_system_context_.get(), wrong_url, 0, kuint64max, base::Time()));
+ net::TestCompletionCallback init_callback;
+ ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, init_callback.WaitForResult());
+}
+
+} // namespace fileapi
diff --git a/chromium/content/browser/frame_host/DEPS b/chromium/content/browser/frame_host/DEPS
new file mode 100644
index 00000000000..09569cb1402
--- /dev/null
+++ b/chromium/content/browser/frame_host/DEPS
@@ -0,0 +1,23 @@
+include_rules = [
+ # The frame_host files should only call upwards in the layering via the
+ # delegate interfaces.
+ "-content/browser/web_contents",
+ "-content/public/browser/web_contents.h",
+ "-content/public/browser/web_contents_delegate.h",
+ "-content/public/browser/web_contents_view.h",
+]
+
+specific_include_rules = {
+ ".*_(unit|browser)test\.cc": [
+ "+content/browser/web_contents",
+ "+content/public/browser/web_contents.h",
+ "+content/public/browser/web_contents_delegate.h",
+ ],
+ ".*interstitial_page_impl\.cc": [
+ # TODO(nasko): This should be removed once we remove
+ # WebContentsObserver as the method of telling interstitial pages to
+ # clean themselves up.
+ "+content/browser/web_contents",
+ "+content/public/browser/web_contents_delegate.h",
+ ],
+}
diff --git a/chromium/content/browser/frame_host/OWNERS b/chromium/content/browser/frame_host/OWNERS
new file mode 100644
index 00000000000..37b83e5c25e
--- /dev/null
+++ b/chromium/content/browser/frame_host/OWNERS
@@ -0,0 +1 @@
+nasko@chromium.org
diff --git a/chromium/content/browser/web_contents/debug_urls.cc b/chromium/content/browser/frame_host/debug_urls.cc
index 1f1222ccfe8..8e36933b276 100644
--- a/chromium/content/browser/web_contents/debug_urls.cc
+++ b/chromium/content/browser/frame_host/debug_urls.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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/web_contents/debug_urls.h"
+#include "content/browser/frame_host/debug_urls.h"
#include <vector>
@@ -79,4 +79,17 @@ bool HandleDebugURL(const GURL& url, PageTransition transition) {
return false;
}
+bool IsRendererDebugURL(const GURL& url) {
+ if (!url.is_valid())
+ return false;
+
+ if (url.SchemeIs(kJavaScriptScheme))
+ return true;
+
+ return url == GURL(kChromeUICrashURL) ||
+ url == GURL(kChromeUIKillURL) ||
+ url == GURL(kChromeUIHangURL) ||
+ url == GURL(kChromeUIShorthangURL);
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/debug_urls.h b/chromium/content/browser/frame_host/debug_urls.h
new file mode 100644
index 00000000000..01530b46807
--- /dev/null
+++ b/chromium/content/browser/frame_host/debug_urls.h
@@ -0,0 +1,26 @@
+// 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_FRAME_HOST_DEBUG_URLS_H_
+#define CONTENT_BROWSER_FRAME_HOST_DEBUG_URLS_H_
+
+#include "content/public/common/page_transition_types.h"
+
+class GURL;
+
+namespace content {
+
+// Checks if the given url is a url used for debugging purposes, and if so
+// handles it and returns true.
+bool HandleDebugURL(const GURL& url, PageTransition transition);
+
+// Returns whether the given url is either a debugging url handled in the
+// renderer process, such as one that crashes or hangs the renderer, or a
+// javascript: URL that operates on the current page in the renderer. Such URLs
+// do not represent actual navigations and can be loaded in any SiteInstance.
+bool IsRendererDebugURL(const GURL& url);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_DEBUG_URLS_H_
diff --git a/chromium/content/browser/frame_host/frame_tree.cc b/chromium/content/browser/frame_host/frame_tree.cc
new file mode 100644
index 00000000000..fef82eebab8
--- /dev/null
+++ b/chromium/content/browser/frame_host/frame_tree.cc
@@ -0,0 +1,191 @@
+// 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/frame_host/frame_tree.h"
+
+#include <queue>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/navigator.h"
+#include "content/browser/frame_host/render_frame_host_factory.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+
+namespace content {
+
+namespace {
+// Used with FrameTree::ForEach() to search for the FrameTreeNode
+// corresponding to |frame_tree_node_id|.
+bool FrameTreeNodeForId(int64 frame_tree_node_id,
+ FrameTreeNode** out_node,
+ FrameTreeNode* node) {
+ if (node->frame_tree_node_id() == frame_tree_node_id) {
+ *out_node = node;
+ // Terminate iteration once the node has been found.
+ return false;
+ }
+ return true;
+}
+
+// TODO(creis): Remove this version along with FrameTreeNode::frame_id().
+bool FrameTreeNodeForFrameId(int64 frame_id,
+ FrameTreeNode** out_node,
+ FrameTreeNode* node) {
+ if (node->frame_id() == frame_id) {
+ *out_node = node;
+ // Terminate iteration once the node has been found.
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+FrameTree::FrameTree(Navigator* navigator,
+ RenderFrameHostDelegate* render_frame_delegate,
+ RenderViewHostDelegate* render_view_delegate,
+ RenderWidgetHostDelegate* render_widget_delegate,
+ RenderFrameHostManager::Delegate* manager_delegate)
+ : render_frame_delegate_(render_frame_delegate),
+ render_view_delegate_(render_view_delegate),
+ render_widget_delegate_(render_widget_delegate),
+ manager_delegate_(manager_delegate),
+ root_(new FrameTreeNode(navigator,
+ render_frame_delegate,
+ render_view_delegate,
+ render_widget_delegate,
+ manager_delegate,
+ FrameTreeNode::kInvalidFrameId,
+ std::string())) {
+}
+
+FrameTree::~FrameTree() {
+}
+
+FrameTreeNode* FrameTree::FindByID(int64 frame_tree_node_id) {
+ FrameTreeNode* node = NULL;
+ ForEach(base::Bind(&FrameTreeNodeForId, frame_tree_node_id, &node));
+ return node;
+}
+
+void FrameTree::ForEach(
+ const base::Callback<bool(FrameTreeNode*)>& on_node) const {
+ std::queue<FrameTreeNode*> queue;
+ queue.push(root_.get());
+
+ while (!queue.empty()) {
+ FrameTreeNode* node = queue.front();
+ queue.pop();
+ if (!on_node.Run(node))
+ break;
+
+ for (size_t i = 0; i < node->child_count(); ++i)
+ queue.push(node->child_at(i));
+ }
+}
+
+bool FrameTree::IsFirstNavigationAfterSwap() const {
+ return root_->frame_id() == FrameTreeNode::kInvalidFrameId;
+}
+
+void FrameTree::OnFirstNavigationAfterSwap(int main_frame_id) {
+ root_->set_frame_id(main_frame_id);
+}
+
+RenderFrameHostImpl* FrameTree::AddFrame(int render_frame_host_id,
+ int64 parent_frame_id,
+ int64 frame_id,
+ const std::string& frame_name) {
+ FrameTreeNode* parent = FindByFrameID(parent_frame_id);
+ // TODO(ajwong): Should the renderer be killed here? Would there be a race on
+ // shutdown that might make this case possible?
+ if (!parent)
+ return NULL;
+
+ scoped_ptr<FrameTreeNode> node(CreateNode(
+ frame_id, frame_name, render_frame_host_id, parent));
+ RenderFrameHostImpl* render_frame = node->render_frame_host();
+ parent->AddChild(node.Pass());
+ return render_frame;
+}
+
+void FrameTree::RemoveFrame(RenderFrameHostImpl* render_frame_host,
+ int64 parent_frame_id,
+ int64 frame_id) {
+ // If switches::kSitePerProcess is not specified, then the FrameTree only
+ // contains a node for the root element. However, even in this case
+ // frame detachments need to be broadcast outwards.
+ //
+ // TODO(ajwong): Move this below the |parent| check after the FrameTree is
+ // guaranteed to be correctly populated even without the
+ // switches::kSitePerProcess flag.
+ FrameTreeNode* parent = FindByFrameID(parent_frame_id);
+ FrameTreeNode* child = FindByFrameID(frame_id);
+ if (!on_frame_removed_.is_null()) {
+ on_frame_removed_.Run(
+ render_frame_host->render_view_host(), frame_id);
+ }
+
+ // TODO(ajwong): Should the renderer be killed here? Would there be a race on
+ // shutdown that might make this case possible?
+ if (!parent || !child)
+ return;
+
+ parent->RemoveChild(child);
+}
+
+void FrameTree::SetFrameUrl(int64 frame_id, const GURL& url) {
+ FrameTreeNode* node = FindByFrameID(frame_id);
+ // TODO(ajwong): Should the renderer be killed here? Would there be a race on
+ // shutdown that might make this case possible?
+ if (!node)
+ return;
+
+ if (node)
+ node->set_current_url(url);
+}
+
+void FrameTree::SwapMainFrame(RenderFrameHostImpl* render_frame_host) {
+ return root_->ResetForMainFrame(render_frame_host);
+}
+
+RenderFrameHostImpl* FrameTree::GetMainFrame() const {
+ return root_->render_frame_host();
+}
+
+void FrameTree::SetFrameRemoveListener(
+ const base::Callback<void(RenderViewHostImpl*, int64)>& on_frame_removed) {
+ on_frame_removed_ = on_frame_removed;
+}
+
+FrameTreeNode* FrameTree::FindByFrameID(int64 frame_id) {
+ FrameTreeNode* node = NULL;
+ ForEach(base::Bind(&FrameTreeNodeForFrameId, frame_id, &node));
+ return node;
+}
+
+scoped_ptr<FrameTreeNode> FrameTree::CreateNode(
+ int64 frame_id,
+ const std::string& frame_name,
+ int render_frame_host_id,
+ FrameTreeNode* parent_node) {
+ scoped_ptr<FrameTreeNode> frame_tree_node(new FrameTreeNode(
+ parent_node->navigator(), render_frame_delegate_, render_view_delegate_,
+ render_widget_delegate_, manager_delegate_, frame_id, frame_name));
+
+ scoped_ptr<RenderFrameHostImpl> render_frame_host(
+ RenderFrameHostFactory::Create(
+ parent_node->render_frame_host()->render_view_host(),
+ parent_node->render_frame_host()->delegate(),
+ this,
+ frame_tree_node.get(),
+ render_frame_host_id,
+ false));
+
+ frame_tree_node->set_render_frame_host(render_frame_host.release(), true);
+ return frame_tree_node.Pass();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/frame_tree.h b/chromium/content/browser/frame_host/frame_tree.h
new file mode 100644
index 00000000000..3ef2d4c979e
--- /dev/null
+++ b/chromium/content/browser/frame_host/frame_tree.h
@@ -0,0 +1,138 @@
+// 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_FRAME_HOST_FRAME_TREE_H_
+#define CONTENT_BROWSER_FRAME_HOST_FRAME_TREE_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class FrameTreeNode;
+class Navigator;
+class RenderFrameHostDelegate;
+class RenderProcessHost;
+class RenderViewHostDelegate;
+class RenderViewHostImpl;
+class RenderFrameHostManager;
+class RenderWidgetHostDelegate;
+
+// Represents the frame tree for a page. With the exception of the main frame,
+// all FrameTreeNodes will be created/deleted in response to frame attach and
+// detach events in the DOM.
+//
+// The main frame's FrameTreeNode is special in that it is reused. This allows
+// it to serve as an anchor for state that needs to persist across top-level
+// page navigations.
+//
+// TODO(ajwong): Move NavigationController ownership to the main frame
+// FrameTreeNode. Possibly expose access to it from here.
+//
+// TODO(ajwong): Currently this class only contains FrameTreeNodes for
+// subframes if the --site-per-process flag is enabled.
+//
+// This object is only used on the UI thread.
+class CONTENT_EXPORT FrameTree {
+ public:
+ // Each FrameTreeNode will default to using the given |navigator| for
+ // navigation tasks in the frame.
+ // A set of delegates are remembered here so that we can create
+ // RenderFrameHostManagers.
+ // TODO(creis): This set of delegates will change as we move things to
+ // Navigator.
+ FrameTree(Navigator* navigator,
+ RenderFrameHostDelegate* render_frame_delegate,
+ RenderViewHostDelegate* render_view_delegate,
+ RenderWidgetHostDelegate* render_widget_delegate,
+ RenderFrameHostManager::Delegate* manager_delegate);
+ ~FrameTree();
+
+ // Returns the FrameTreeNode with the given |frame_tree_node_id|.
+ FrameTreeNode* FindByID(int64 frame_tree_node_id);
+
+ // Executes |on_node| on each node in the frame tree. If |on_node| returns
+ // false, terminates the iteration immediately. Returning false is useful
+ // if |on_node| is just doing a search over the tree.
+ void ForEach(const base::Callback<bool(FrameTreeNode*)>& on_node) const;
+
+ // After the FrameTree is created, or after SwapMainFrame() has been called,
+ // the root node does not yet have a frame id. This is allocated by the
+ // renderer and is published to the browser process on the first navigation
+ // after a swap. These two functions are used to set the root node's frame
+ // id.
+ //
+ // TODO(ajwong): Remove these once RenderFrameHost's routing id replaces
+ // frame_id.
+ bool IsFirstNavigationAfterSwap() const;
+ void OnFirstNavigationAfterSwap(int main_frame_id);
+
+ // Frame tree manipulation routines.
+ // TODO(creis): These should take in RenderFrameHost routing IDs.
+ RenderFrameHostImpl* AddFrame(int render_frame_host_id,
+ int64 parent_frame_tree_node_id,
+ int64 frame_id,
+ const std::string& frame_name);
+ void RemoveFrame(RenderFrameHostImpl* render_frame_host,
+ int64 parent_frame_id,
+ int64 frame_id);
+ void SetFrameUrl(int64 frame_id, const GURL& url);
+
+ // Resets the FrameTree and changes RenderFrameHost for the main frame.
+ // This destroys most of the frame tree but retains the root node so that
+ // navigation state may be kept on it between process swaps. Used to
+ // support bookkeeping for top-level navigations.
+ //
+ // If |main_frame| is NULL, reset tree to initially constructed state.
+ //
+ // TODO(ajwong): This function should not be given a |main_frame|. This is
+ // required currently because the RenderViewHost owns its main frame. When
+ // that relation is fixed, the FrameTree should be responsible for
+ // created/destroying the main frame on the swap.
+ void SwapMainFrame(RenderFrameHostImpl* main_frame);
+
+ // Convenience accessor for the main frame's RenderFrameHostImpl.
+ RenderFrameHostImpl* GetMainFrame() const;
+
+ // Allows a client to listen for frame removal. The listener should expect
+ // to receive the RenderViewHostImpl containing the frame and the renderer-
+ // specific frame ID of the removed frame.
+ // TODO(creis): These parameters will later change to be the RenderFrameHost.
+ void SetFrameRemoveListener(
+ const base::Callback<void(RenderViewHostImpl*, int64)>& on_frame_removed);
+
+ FrameTreeNode* root() const { return root_.get(); }
+
+ private:
+ // Returns the FrameTreeNode with the given renderer-specific |frame_id|.
+ // For internal use only.
+ // TODO(creis): Replace this with a version that takes in a routing ID.
+ FrameTreeNode* FindByFrameID(int64 frame_id);
+
+ scoped_ptr<FrameTreeNode> CreateNode(int64 frame_id,
+ const std::string& frame_name,
+ int render_frame_host_id,
+ FrameTreeNode* parent_node);
+
+ // These delegates are installed into all the RenderViewHosts and
+ // RenderFrameHosts that we create.
+ RenderFrameHostDelegate* render_frame_delegate_;
+ RenderViewHostDelegate* render_view_delegate_;
+ RenderWidgetHostDelegate* render_widget_delegate_;
+ RenderFrameHostManager::Delegate* manager_delegate_;
+
+ scoped_ptr<FrameTreeNode> root_;
+
+ base::Callback<void(RenderViewHostImpl*, int64)> on_frame_removed_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameTree);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_FRAME_TREE_H_
diff --git a/chromium/content/browser/frame_host/frame_tree_node.cc b/chromium/content/browser/frame_host/frame_tree_node.cc
new file mode 100644
index 00000000000..37b61b4fadf
--- /dev/null
+++ b/chromium/content/browser/frame_host/frame_tree_node.cc
@@ -0,0 +1,72 @@
+// 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/frame_host/frame_tree_node.h"
+
+#include <queue>
+
+#include "base/stl_util.h"
+#include "content/browser/frame_host/navigator.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+
+namespace content {
+
+const int64 FrameTreeNode::kInvalidFrameId = -1;
+int64 FrameTreeNode::next_frame_tree_node_id_ = 1;
+
+FrameTreeNode::FrameTreeNode(Navigator* navigator,
+ RenderFrameHostDelegate* render_frame_delegate,
+ RenderViewHostDelegate* render_view_delegate,
+ RenderWidgetHostDelegate* render_widget_delegate,
+ RenderFrameHostManager::Delegate* manager_delegate,
+ int64 frame_id,
+ const std::string& name)
+ : navigator_(navigator),
+ render_manager_(render_frame_delegate,
+ render_view_delegate,
+ render_widget_delegate,
+ manager_delegate),
+ frame_tree_node_id_(next_frame_tree_node_id_++),
+ frame_id_(frame_id),
+ frame_name_(name),
+ owns_render_frame_host_(true),
+ render_frame_host_(NULL) {
+}
+
+FrameTreeNode::~FrameTreeNode() {
+ if (owns_render_frame_host_)
+ delete render_frame_host_;
+}
+
+void FrameTreeNode::AddChild(scoped_ptr<FrameTreeNode> child) {
+ children_.push_back(child.release());
+}
+
+void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
+ std::vector<FrameTreeNode*>::iterator iter;
+
+ for (iter = children_.begin(); iter != children_.end(); ++iter) {
+ if ((*iter) == child)
+ break;
+ }
+
+ if (iter != children_.end())
+ children_.erase(iter);
+}
+
+void FrameTreeNode::ResetForMainFrame(
+ RenderFrameHostImpl* new_render_frame_host) {
+ owns_render_frame_host_ = false;
+ frame_id_ = kInvalidFrameId;
+ current_url_ = GURL();
+
+ // The children may not have been cleared if a cross-process navigation
+ // commits before the old process cleans everything up. Make sure the child
+ // nodes get deleted.
+ children_.clear();
+
+ render_frame_host_ = new_render_frame_host;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/frame_tree_node.h b/chromium/content/browser/frame_host/frame_tree_node.h
new file mode 100644
index 00000000000..9c22b125ba3
--- /dev/null
+++ b/chromium/content/browser/frame_host/frame_tree_node.h
@@ -0,0 +1,169 @@
+// 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_FRAME_HOST_FRAME_TREE_NODE_H_
+#define CONTENT_BROWSER_FRAME_HOST_FRAME_TREE_NODE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.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 "url/gurl.h"
+
+namespace content {
+
+class Navigator;
+class RenderFrameHostImpl;
+
+// When a page contains iframes, its renderer process maintains a tree structure
+// of those frames. We are mirroring this tree in the browser process. This
+// class represents a node in this tree and is a wrapper for all objects that
+// are frame-specific (as opposed to page-specific).
+class CONTENT_EXPORT FrameTreeNode {
+ public:
+ static const int64 kInvalidFrameId;
+
+ FrameTreeNode(Navigator* navigator,
+ RenderFrameHostDelegate* render_frame_delegate,
+ RenderViewHostDelegate* render_view_delegate,
+ RenderWidgetHostDelegate* render_widget_delegate,
+ RenderFrameHostManager::Delegate* manager_delegate,
+ int64 frame_id,
+ const std::string& name);
+
+ ~FrameTreeNode();
+
+ void AddChild(scoped_ptr<FrameTreeNode> child);
+ void RemoveChild(FrameTreeNode* child);
+
+ // TODO(nasko): This method should be removed once RenderFrameHosts are
+ // created by RenderFrameHostManager.
+ void set_render_frame_host(
+ RenderFrameHostImpl* render_frame_host,
+ bool owns_render_frame_host) {
+ render_frame_host_ = render_frame_host;
+ owns_render_frame_host_ = owns_render_frame_host;
+ }
+
+ // Transitional API allowing the RenderFrameHost of a FrameTreeNode
+ // representing the main frame to be provided by someone else. After
+ // this is called, the FrameTreeNode no longer owns its RenderFrameHost.
+ //
+ // This should only be used for the main frame (aka root) in a frame tree.
+ //
+ // TODO(ajwong): Remove this method once the main frame RenderFrameHostImpl is
+ // no longer owned by the RenderViewHostImpl.
+ void ResetForMainFrame(RenderFrameHostImpl* new_render_frame_host);
+
+ Navigator* navigator() {
+ return navigator_.get();
+ }
+
+ RenderFrameHostManager* render_manager() {
+ return &render_manager_;
+ }
+
+ int64 frame_tree_node_id() const {
+ return frame_tree_node_id_;
+ }
+
+ // DO NOT USE. Only used by FrameTree until we replace renderer-specific
+ // frame IDs with RenderFrameHost routing IDs.
+ void set_frame_id(int64 frame_id) {
+ DCHECK_EQ(frame_id_, kInvalidFrameId);
+ frame_id_ = frame_id;
+ }
+ int64 frame_id() const {
+ return frame_id_;
+ }
+
+ const std::string& frame_name() const {
+ return frame_name_;
+ }
+
+ size_t child_count() const {
+ return children_.size();
+ }
+
+ FrameTreeNode* child_at(size_t index) const {
+ return children_[index];
+ }
+
+ const GURL& current_url() const {
+ return current_url_;
+ }
+
+ void set_current_url(const GURL& url) {
+ current_url_ = url;
+ }
+
+ RenderFrameHostImpl* render_frame_host() const {
+ return render_frame_host_;
+ }
+
+ private:
+ // The next available browser-global FrameTreeNode ID.
+ static int64 next_frame_tree_node_id_;
+
+ // The Navigator object responsible for managing navigations at this node
+ // of the frame tree.
+ scoped_refptr<Navigator> navigator_;
+
+ // Manages creation and swapping of RenderViewHosts for this frame. This must
+ // be declared before |children_| so that it gets deleted after them. That's
+ // currently necessary so that RenderFrameHostImpl's destructor can call
+ // GetProcess.
+ // TODO(creis): This will eliminate the need for |render_frame_host_| below.
+ RenderFrameHostManager render_manager_;
+
+ // A browser-global identifier for the frame in the page, which stays stable
+ // even if the frame does a cross-process navigation.
+ const int64 frame_tree_node_id_;
+
+ // The renderer-specific identifier for the frame in the page.
+ // TODO(creis): Remove this in favor of the RenderFrameHost's routing ID once
+ // we create FrameTreeNodes for all frames (even without a flag), since this
+ // value can change after cross-process navigations.
+ int64 frame_id_;
+
+ // The assigned name of the frame. This name can be empty, unlike the unique
+ // name generated internally in the DOM tree.
+ std::string frame_name_;
+
+ // The immediate children of this specific frame.
+ ScopedVector<FrameTreeNode> children_;
+
+ // When ResetForMainFrame() is called, this is set to false and the
+ // |render_frame_host_| below is not deleted on destruction.
+ //
+ // For the mainframe, the FrameTree does not own the |render_frame_host_|.
+ // This is a transitional wart because RenderFrameHostManager does not yet
+ // have the bookkeeping logic to handle creating a pending RenderFrameHost
+ // along with a pending RenderViewHost. Thus, for the main frame, the
+ // RenderViewHost currently retains ownership and the FrameTreeNode should
+ // not delete it on destruction.
+ bool owns_render_frame_host_;
+
+ // The active RenderFrameHost for this frame. The FrameTreeNode does not
+ // always own this pointer. See comments above |owns_render_frame_host_|.
+ // TODO(ajwong): Replace with RenderFrameHostManager.
+ RenderFrameHostImpl* render_frame_host_;
+
+ // Track the current frame's last committed URL, so we can estimate the
+ // process impact of out-of-process iframes.
+ // TODO(creis): Remove this when we can store subframe URLs in the
+ // NavigationController.
+ GURL current_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameTreeNode);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_FRAME_TREE_NODE_H_
diff --git a/chromium/content/browser/frame_host/frame_tree_unittest.cc b/chromium/content/browser/frame_host/frame_tree_unittest.cc
new file mode 100644
index 00000000000..6f1bb330380
--- /dev/null
+++ b/chromium/content/browser/frame_host/frame_tree_unittest.cc
@@ -0,0 +1,180 @@
+// 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/frame_host/frame_tree.h"
+
+#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/browser/frame_host/navigator_impl.h"
+#include "content/browser/frame_host/render_frame_host_factory.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_renderer_host.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+class FrameTreeTest : public RenderViewHostTestHarness {
+ protected:
+ // Prints a FrameTree, for easy assertions of the tree hierarchy.
+ std::string GetTreeState(FrameTree* frame_tree) {
+ std::string result;
+ AppendTreeNodeState(frame_tree->root(), &result);
+ return result;
+ }
+
+ private:
+ void AppendTreeNodeState(FrameTreeNode* node, std::string* result) {
+ result->append(base::Int64ToString(node->frame_id()));
+ if (!node->frame_name().empty()) {
+ result->append(" '");
+ result->append(node->frame_name());
+ result->append("'");
+ }
+ result->append(": [");
+ const char* separator = "";
+ for (size_t i = 0; i < node->child_count(); i++) {
+ result->append(separator);
+ AppendTreeNodeState(node->child_at(i), result);
+ separator = ", ";
+ }
+ result->append("]");
+ }
+};
+
+// The root node never changes during navigation even though its
+// RenderFrameHost does.
+// - Swapping main frame doesn't change root node.
+// - Swapping back to NULL doesn't crash (easier tear-down for interstitials).
+// - Main frame does not own RenderFrameHost.
+TEST_F(FrameTreeTest, RootNode) {
+ FrameTree frame_tree(new NavigatorImpl(NULL, NULL), NULL, NULL, NULL, NULL);
+
+ // Initial state has empty node.
+ FrameTreeNode* root = frame_tree.root();
+ ASSERT_TRUE(root);
+ EXPECT_FALSE(frame_tree.GetMainFrame());
+
+ // Swap in main frame.
+ RenderFrameHostImpl* dummy = reinterpret_cast<RenderFrameHostImpl*>(0x1);
+ frame_tree.SwapMainFrame(dummy);
+ EXPECT_EQ(root, frame_tree.root());
+ EXPECT_EQ(dummy, frame_tree.GetMainFrame());
+
+ // Move back to NULL.
+ frame_tree.SwapMainFrame(NULL);
+ EXPECT_EQ(root, frame_tree.root());
+ EXPECT_FALSE(frame_tree.GetMainFrame());
+
+ // Move back to an invalid pointer, let the FrameTree go out of scope. Test
+ // should not crash because the main frame isn't owned.
+ frame_tree.SwapMainFrame(dummy);
+}
+
+// Test that swapping the main frame resets the renderer-assigned frame id.
+// - On creation, frame id is unassigned.
+// - After a swap, frame id is unassigned.
+TEST_F(FrameTreeTest, FirstNavigationAfterSwap) {
+ FrameTree frame_tree(new NavigatorImpl(NULL, NULL), NULL, NULL, NULL, NULL);
+
+ EXPECT_TRUE(frame_tree.IsFirstNavigationAfterSwap());
+ EXPECT_EQ(FrameTreeNode::kInvalidFrameId,
+ frame_tree.root()->frame_id());
+ frame_tree.OnFirstNavigationAfterSwap(1);
+ EXPECT_FALSE(frame_tree.IsFirstNavigationAfterSwap());
+ EXPECT_EQ(1, frame_tree.root()->frame_id());
+
+ frame_tree.SwapMainFrame(NULL);
+ EXPECT_TRUE(frame_tree.IsFirstNavigationAfterSwap());
+ EXPECT_EQ(FrameTreeNode::kInvalidFrameId,
+ frame_tree.root()->frame_id());
+}
+
+// Exercise tree manipulation routines.
+// - Add a series of nodes and verify tree structure.
+// - Remove a series of nodes and verify tree structure.
+TEST_F(FrameTreeTest, Shape) {
+ FrameTree frame_tree(new NavigatorImpl(NULL, NULL), NULL, NULL, NULL, NULL);
+
+ std::string no_children_node("no children node");
+ std::string deep_subtree("node with deep subtree");
+
+ // Ensure the top-level node of the FrameTree is initialized by simulating a
+ // main frame swap here.
+ scoped_ptr<RenderFrameHostImpl> render_frame_host =
+ RenderFrameHostFactory::Create(static_cast<RenderViewHostImpl*>(rvh()),
+ NULL,
+ &frame_tree,
+ frame_tree.root(),
+ process()->GetNextRoutingID(),
+ false);
+ frame_tree.SwapMainFrame(render_frame_host.get());
+ frame_tree.OnFirstNavigationAfterSwap(5);
+
+ ASSERT_EQ("5: []", GetTreeState(&frame_tree));
+
+ // Simulate attaching a series of frames to build the frame tree.
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 5, 14, std::string());
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 5, 15, std::string());
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 5, 16, std::string());
+
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 14, 244, std::string());
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 15, 255, no_children_node);
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 14, 245, std::string());
+
+ ASSERT_EQ("5: [14: [244: [], 245: []], "
+ "15: [255 'no children node': []], "
+ "16: []]",
+ GetTreeState(&frame_tree));
+
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 16, 264, std::string());
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 16, 265, std::string());
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 16, 266, std::string());
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 16, 267, deep_subtree);
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 16, 268, std::string());
+
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 267, 365, std::string());
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 365, 455, std::string());
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 455, 555, std::string());
+ frame_tree.AddFrame(process()->GetNextRoutingID(), 555, 655, std::string());
+
+ // Now that's it's fully built, verify the tree structure is as expected.
+ ASSERT_EQ("5: [14: [244: [], 245: []], "
+ "15: [255 'no children node': []], "
+ "16: [264: [], 265: [], 266: [], "
+ "267 'node with deep subtree': "
+ "[365: [455: [555: [655: []]]]], 268: []]]",
+ GetTreeState(&frame_tree));
+
+ // Test removing of nodes.
+ frame_tree.RemoveFrame(NULL, 555, 655);
+ ASSERT_EQ("5: [14: [244: [], 245: []], "
+ "15: [255 'no children node': []], "
+ "16: [264: [], 265: [], 266: [], "
+ "267 'node with deep subtree': "
+ "[365: [455: [555: []]]], 268: []]]",
+ GetTreeState(&frame_tree));
+
+ frame_tree.RemoveFrame(NULL, 16, 265);
+ ASSERT_EQ("5: [14: [244: [], 245: []], "
+ "15: [255 'no children node': []], "
+ "16: [264: [], 266: [], "
+ "267 'node with deep subtree': "
+ "[365: [455: [555: []]]], 268: []]]",
+ GetTreeState(&frame_tree));
+
+ frame_tree.RemoveFrame(NULL, 5, 15);
+ ASSERT_EQ("5: [14: [244: [], 245: []], "
+ "16: [264: [], 266: [], "
+ "267 'node with deep subtree': "
+ "[365: [455: [555: []]]], 268: []]]",
+ GetTreeState(&frame_tree));
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/web_contents/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index bb93dc3d6c9..7af8d029f7e 100644
--- a/chromium/content/browser/web_contents/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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/web_contents/interstitial_page_impl.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
#include <vector>
@@ -14,12 +14,14 @@
#include "base/threading/thread.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
+#include "content/browser/frame_host/interstitial_page_navigator_impl.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigation_entry_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_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
-#include "content/browser/web_contents/navigation_controller_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/view_messages.h"
#include "content/port/browser/render_view_host_delegate_view.h"
@@ -40,8 +42,8 @@
#include "net/base/escape.h"
#include "net/url_request/url_request_context_getter.h"
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationsMask;
+using blink::WebDragOperation;
+using blink::WebDragOperationsMask;
namespace content {
namespace {
@@ -117,7 +119,11 @@ InterstitialPage* InterstitialPage::Create(WebContents* web_contents,
bool new_navigation,
const GURL& url,
InterstitialPageDelegate* delegate) {
- return new InterstitialPageImpl(web_contents, new_navigation, url, delegate);
+ return new InterstitialPageImpl(
+ web_contents,
+ static_cast<RenderWidgetHostDelegate*>(
+ static_cast<WebContentsImpl*>(web_contents)),
+ new_navigation, url, delegate);
}
InterstitialPage* InterstitialPage::GetInterstitialPage(
@@ -131,12 +137,17 @@ InterstitialPage* InterstitialPage::GetInterstitialPage(
return iter->second;
}
-InterstitialPageImpl::InterstitialPageImpl(WebContents* web_contents,
- bool new_navigation,
- const GURL& url,
- InterstitialPageDelegate* delegate)
+InterstitialPageImpl::InterstitialPageImpl(
+ WebContents* web_contents,
+ RenderWidgetHostDelegate* render_widget_host_delegate,
+ bool new_navigation,
+ const GURL& url,
+ InterstitialPageDelegate* delegate)
: WebContentsObserver(web_contents),
- web_contents_(static_cast<WebContentsImpl*>(web_contents)),
+ web_contents_(web_contents),
+ controller_(static_cast<NavigationControllerImpl*>(
+ &web_contents->GetController())),
+ render_widget_host_delegate_(render_widget_host_delegate),
url_(url),
new_navigation_(new_navigation),
should_discard_pending_nav_entry_(new_navigation),
@@ -144,6 +155,14 @@ InterstitialPageImpl::InterstitialPageImpl(WebContents* web_contents,
enabled_(true),
action_taken_(NO_ACTION),
render_view_host_(NULL),
+ // TODO(nasko): The InterstitialPageImpl will need to provide its own
+ // NavigationControllerImpl to the Navigator, which is separate from
+ // the WebContents one, so we can enforce no navigation policy here.
+ // While we get the code to a point to do this, pass NULL for it.
+ // TODO(creis): We will also need to pass delegates for the RVHM as we
+ // start to use it.
+ frame_tree_(new InterstitialPageNavigatorImpl(this, controller_),
+ NULL, NULL, NULL, NULL),
original_child_id_(web_contents->GetRenderProcessHost()->GetID()),
original_rvh_id_(web_contents->GetRenderViewHost()->GetRoutingID()),
should_revert_web_contents_title_(false),
@@ -198,7 +217,7 @@ void InterstitialPageImpl::Show() {
// already been destroyed.
notification_registrar_.Add(
this, NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
- Source<RenderWidgetHost>(web_contents_->GetRenderViewHost()));
+ Source<RenderWidgetHost>(controller_->delegate()->GetRenderViewHost()));
// Update the g_web_contents_to_interstitial_page map.
iter = g_web_contents_to_interstitial_page->find(web_contents_);
@@ -214,11 +233,12 @@ void InterstitialPageImpl::Show() {
// Give delegates a chance to set some states on the navigation entry.
delegate_->OverrideEntry(entry);
- web_contents_->GetController().SetTransientEntry(entry);
+ controller_->SetTransientEntry(entry);
}
DCHECK(!render_view_host_);
render_view_host_ = static_cast<RenderViewHostImpl*>(CreateRenderViewHost());
+ render_view_host_->AttachToFrameTree();
CreateWebContentsView();
std::string data_url = "data:text/html;charset=utf-8," +
@@ -226,7 +246,7 @@ void InterstitialPageImpl::Show() {
render_view_host_->NavigateToURL(GURL(data_url));
notification_registrar_.Add(this, NOTIFICATION_NAV_ENTRY_PENDING,
- Source<NavigationController>(&web_contents_->GetController()));
+ Source<NavigationController>(controller_));
notification_registrar_.Add(
this, NOTIFICATION_DOM_OPERATION_RESPONSE,
Source<RenderViewHost>(render_view_host_));
@@ -242,9 +262,11 @@ void InterstitialPageImpl::Hide() {
Disable();
RenderWidgetHostView* old_view =
- web_contents_->GetRenderViewHost()->GetView();
- if (web_contents_->GetInterstitialPage() == this &&
- old_view && !old_view->IsShowing() && !web_contents_->IsHidden()) {
+ controller_->delegate()->GetRenderViewHost()->GetView();
+ if (controller_->delegate()->GetInterstitialPage() == this &&
+ old_view &&
+ !old_view->IsShowing() &&
+ !controller_->delegate()->IsHidden()) {
// Show the original RVH since we're going away. Note it might not exist if
// the renderer crashed while the interstitial was showing.
// Note that it is important that we don't call Show() if the view is
@@ -257,9 +279,9 @@ void InterstitialPageImpl::Hide() {
// (Note that in unit-tests the RVH may not have a view).
if (render_view_host_->GetView() &&
render_view_host_->GetView()->HasFocus() &&
- web_contents_->GetRenderViewHost()->GetView()) {
+ controller_->delegate()->GetRenderViewHost()->GetView()) {
RenderWidgetHostViewPort::FromRWHV(
- web_contents_->GetRenderViewHost()->GetView())->Focus();
+ controller_->delegate()->GetRenderViewHost()->GetView())->Focus();
}
// Shutdown the RVH asynchronously, as we may have been called from a RVH
@@ -270,12 +292,14 @@ void InterstitialPageImpl::Hide() {
weak_ptr_factory_.GetWeakPtr(),
render_view_host_));
render_view_host_ = NULL;
- web_contents_->DetachInterstitialPage();
+ frame_tree_.SwapMainFrame(NULL);
+ controller_->delegate()->DetachInterstitialPage();
// Let's revert to the original title if necessary.
- NavigationEntry* entry = web_contents_->GetController().GetActiveEntry();
+ NavigationEntry* entry = controller_->GetVisibleEntry();
if (!new_navigation_ && should_revert_web_contents_title_) {
entry->SetTitle(original_web_contents_title_);
- web_contents_->NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE);
+ controller_->delegate()->NotifyNavigationStateChanged(
+ INVALIDATE_TYPE_TITLE);
}
InterstitialPageMap::iterator iter =
@@ -378,12 +402,12 @@ void InterstitialPageImpl::DidNavigate(
}
// The RenderViewHost has loaded its contents, we can show it now.
- if (!web_contents_->IsHidden())
+ if (!controller_->delegate()->IsHidden())
render_view_host_->GetView()->Show();
- web_contents_->AttachInterstitialPage(this);
+ controller_->delegate()->AttachInterstitialPage(this);
RenderWidgetHostView* rwh_view =
- web_contents_->GetRenderViewHost()->GetView();
+ controller_->delegate()->GetRenderViewHost()->GetView();
// The RenderViewHost may already have crashed before we even get here.
if (rwh_view) {
@@ -396,24 +420,25 @@ void InterstitialPageImpl::DidNavigate(
}
// Notify the tab we are not loading so the throbber is stopped. It also
- // causes a NOTIFY_LOAD_STOP notification, that the AutomationProvider (used
- // by the UI tests) expects to consider a navigation as complete. Without
- // this, navigating in a UI test to a URL that triggers an interstitial would
- // hang.
- web_contents_was_loading_ = web_contents_->IsLoading();
- web_contents_->SetIsLoading(false, NULL);
+ // causes a WebContentsObserver::DidStopLoading callback that the
+ // AutomationProvider (used by the UI tests) expects to consider a navigation
+ // as complete. Without this, navigating in a UI test to a URL that triggers
+ // an interstitial would hang.
+ web_contents_was_loading_ = controller_->delegate()->IsLoading();
+ controller_->delegate()->SetIsLoading(
+ controller_->delegate()->GetRenderViewHost(), false, NULL);
}
void InterstitialPageImpl::UpdateTitle(
RenderViewHost* render_view_host,
int32 page_id,
- const string16& title,
+ const base::string16& title,
base::i18n::TextDirection title_direction) {
if (!enabled())
return;
DCHECK(render_view_host == render_view_host_);
- NavigationEntry* entry = web_contents_->GetController().GetActiveEntry();
+ NavigationEntry* entry = controller_->GetVisibleEntry();
if (!entry) {
// Crash reports from the field indicate this can be NULL.
// This is unexpected as InterstitialPages constructed with the
@@ -436,7 +461,7 @@ void InterstitialPageImpl::UpdateTitle(
// TODO(evan): make use of title_direction.
// http://code.google.com/p/chromium/issues/detail?id=27094
entry->SetTitle(title);
- web_contents_->NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE);
+ controller_->delegate()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE);
}
RendererPreferences InterstitialPageImpl::GetRendererPrefs(
@@ -449,7 +474,7 @@ WebPreferences InterstitialPageImpl::GetWebkitPrefs() {
if (!enabled())
return WebPreferences();
- return WebContentsImpl::GetWebkitPrefs(render_view_host_, url_);
+ return render_view_host_->GetWebkitPrefs(url_);
}
void InterstitialPageImpl::RenderWidgetDeleted(
@@ -462,19 +487,20 @@ bool InterstitialPageImpl::PreHandleKeyboardEvent(
bool* is_keyboard_shortcut) {
if (!enabled())
return false;
- return web_contents_->PreHandleKeyboardEvent(event, is_keyboard_shortcut);
+ return render_widget_host_delegate_->PreHandleKeyboardEvent(
+ event, is_keyboard_shortcut);
}
void InterstitialPageImpl::HandleKeyboardEvent(
const NativeWebKeyboardEvent& event) {
if (enabled())
- web_contents_->HandleKeyboardEvent(event);
+ render_widget_host_delegate_->HandleKeyboardEvent(event);
}
#if defined(OS_WIN) && defined(USE_AURA)
gfx::NativeViewAccessible
InterstitialPageImpl::GetParentNativeViewAccessible() {
- return web_contents_->GetParentNativeViewAccessible();
+ return render_widget_host_delegate_->GetParentNativeViewAccessible();
}
#endif
@@ -498,16 +524,14 @@ RenderViewHost* InterstitialPageImpl::CreateRenderViewHost() {
session_storage_namespace_ =
new SessionStorageNamespaceImpl(dom_storage_context);
- RenderViewHostImpl* render_view_host =
- new RenderViewHostImpl(site_instance.get(),
- this,
- this,
- MSG_ROUTING_NONE,
- MSG_ROUTING_NONE,
- false,
- false);
- web_contents_->RenderViewForInterstitialPageCreated(render_view_host);
- return render_view_host;
+ return RenderViewHostFactory::Create(site_instance.get(),
+ this,
+ this,
+ this,
+ MSG_ROUTING_NONE,
+ MSG_ROUTING_NONE,
+ false,
+ false);
}
WebContentsView* InterstitialPageImpl::CreateWebContentsView() {
@@ -523,9 +547,11 @@ WebContentsView* InterstitialPageImpl::CreateWebContentsView() {
int32 max_page_id = web_contents()->
GetMaxPageIDForSiteInstance(render_view_host_->GetSiteInstance());
- render_view_host_->CreateRenderView(string16(),
+ render_view_host_->CreateRenderView(base::string16(),
MSG_ROUTING_NONE,
max_page_id);
+ controller_->delegate()->RenderViewForInterstitialPageCreated(
+ render_view_host_);
view->SetSize(web_contents_view->GetContainerSize());
// Don't show the interstitial until we have navigated to it.
view->Hide();
@@ -547,7 +573,8 @@ void InterstitialPageImpl::Proceed() {
// Resumes the throbber, if applicable.
if (web_contents_was_loading_)
- web_contents_->SetIsLoading(true, NULL);
+ controller_->delegate()->SetIsLoading(
+ controller_->delegate()->GetRenderViewHost(), true, NULL);
// If this is a new navigation, the old page is going away, so we cancel any
// blocked requests for it. If it is not a new navigation, then it means the
@@ -594,11 +621,11 @@ void InterstitialPageImpl::DontProceed() {
// explicitely. Note that by calling DiscardNonCommittedEntries() we also
// discard the pending entry, which is what we want, since the navigation is
// cancelled.
- web_contents_->GetController().DiscardNonCommittedEntries();
+ controller_->DiscardNonCommittedEntries();
}
if (reload_on_dont_proceed_)
- web_contents_->GetController().Reload(true);
+ controller_->Reload(true);
Hide();
delegate_->OnDontProceed();
@@ -672,6 +699,7 @@ gfx::Rect InterstitialPageImpl::GetRootWindowResizerRect() const {
}
void InterstitialPageImpl::CreateNewWindow(
+ int render_process_id,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
@@ -679,12 +707,14 @@ void InterstitialPageImpl::CreateNewWindow(
NOTREACHED() << "InterstitialPage does not support showing popups yet.";
}
-void InterstitialPageImpl::CreateNewWidget(int route_id,
- WebKit::WebPopupType popup_type) {
+void InterstitialPageImpl::CreateNewWidget(int render_process_id,
+ int route_id,
+ blink::WebPopupType popup_type) {
NOTREACHED() << "InterstitialPage does not support showing drop-downs yet.";
}
-void InterstitialPageImpl::CreateNewFullscreenWidget(int route_id) {
+void InterstitialPageImpl::CreateNewFullscreenWidget(int render_process_id,
+ int route_id) {
NOTREACHED()
<< "InterstitialPage does not support showing full screen popups.";
}
@@ -711,6 +741,10 @@ SessionStorageNamespace* InterstitialPageImpl::GetSessionStorageNamespace(
return session_storage_namespace_.get();
}
+FrameTree* InterstitialPageImpl::GetFrameTree() {
+ return &frame_tree_;
+}
+
void InterstitialPageImpl::Disable() {
enabled_ = false;
}
diff --git a/chromium/content/browser/web_contents/interstitial_page_impl.h b/chromium/content/browser/frame_host/interstitial_page_impl.h
index 1f4d94fcc8e..fddeacd10f4 100644
--- a/chromium/content/browser/web_contents/interstitial_page_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.h
@@ -1,13 +1,16 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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_WEB_CONTENTS_INTERSTITIAL_PAGE_IMPL_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_INTERSTITIAL_PAGE_IMPL_H_
+#ifndef CONTENT_BROWSER_FRAME_HOST_INTERSTITIAL_PAGE_IMPL_H_
+#define CONTENT_BROWSER_FRAME_HOST_INTERSTITIAL_PAGE_IMPL_H_
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/navigator_delegate.h"
+#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/public/browser/interstitial_page.h"
@@ -19,6 +22,7 @@
namespace content {
class NavigationEntry;
+class NavigationControllerImpl;
class RenderViewHostImpl;
class RenderWidgetHostView;
class WebContentsView;
@@ -34,8 +38,10 @@ class CONTENT_EXPORT InterstitialPageImpl
: public NON_EXPORTED_BASE(InterstitialPage),
public NotificationObserver,
public WebContentsObserver,
+ public NON_EXPORTED_BASE(RenderFrameHostDelegate),
public RenderViewHostDelegate,
- public RenderWidgetHostDelegate {
+ public RenderWidgetHostDelegate,
+ public NON_EXPORTED_BASE(NavigatorDelegate) {
public:
// The different state of actions the user can take in an interstitial.
enum ActionState {
@@ -45,6 +51,7 @@ class CONTENT_EXPORT InterstitialPageImpl
};
InterstitialPageImpl(WebContents* web_contents,
+ RenderWidgetHostDelegate* render_widget_host_delegate,
bool new_navigation,
const GURL& url,
InterstitialPageDelegate* delegate);
@@ -95,6 +102,8 @@ class CONTENT_EXPORT InterstitialPageImpl
virtual void NavigationEntryCommitted(
const LoadCommittedDetails& load_details) OVERRIDE;
+ // RenderFrameHostDelegate implementation:
+
// RenderViewHostDelegate implementation:
virtual RenderViewHostDelegateView* GetDelegateView() OVERRIDE;
virtual const GURL& GetURL() const OVERRIDE;
@@ -106,20 +115,23 @@ class CONTENT_EXPORT InterstitialPageImpl
const ViewHostMsg_FrameNavigate_Params& params) OVERRIDE;
virtual void UpdateTitle(RenderViewHost* render_view_host,
int32 page_id,
- const string16& title,
+ const base::string16& title,
base::i18n::TextDirection title_direction) OVERRIDE;
virtual RendererPreferences GetRendererPrefs(
BrowserContext* browser_context) const OVERRIDE;
virtual WebPreferences GetWebkitPrefs() OVERRIDE;
virtual gfx::Rect GetRootWindowResizerRect() const OVERRIDE;
virtual void CreateNewWindow(
+ int render_process_id,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
SessionStorageNamespace* session_storage_namespace) OVERRIDE;
- virtual void CreateNewWidget(int route_id,
- WebKit::WebPopupType popup_type) OVERRIDE;
- virtual void CreateNewFullscreenWidget(int route_id) OVERRIDE;
+ virtual void CreateNewWidget(int render_process_id,
+ int route_id,
+ blink::WebPopupType popup_type) OVERRIDE;
+ virtual void CreateNewFullscreenWidget(int render_process_id,
+ int route_id) OVERRIDE;
virtual void ShowCreatedWindow(int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_pos,
@@ -131,6 +143,8 @@ class CONTENT_EXPORT InterstitialPageImpl
virtual SessionStorageNamespace* GetSessionStorageNamespace(
SiteInstance* instance) OVERRIDE;
+ virtual FrameTree* GetFrameTree() OVERRIDE;
+
// RenderWidgetHostDelegate implementation:
virtual void RenderWidgetDeleted(
RenderWidgetHostImpl* render_widget_host) OVERRIDE;
@@ -179,7 +193,13 @@ class CONTENT_EXPORT InterstitialPageImpl
// The contents in which we are displayed. This is valid until Hide is
// called, at which point it will be set to NULL because the WebContents
// itself may be deleted.
- WebContentsImpl* web_contents_;
+ WebContents* web_contents_;
+
+ // The NavigationController for the content this page is being displayed over.
+ NavigationControllerImpl* controller_;
+
+ // Delegate for dispatching keyboard events and accessing the native view.
+ RenderWidgetHostDelegate* render_widget_host_delegate_;
// The URL that is shown when the interstitial is showing.
GURL url_;
@@ -211,6 +231,9 @@ class CONTENT_EXPORT InterstitialPageImpl
// that shutdown has started.
RenderViewHostImpl* render_view_host_;
+ // The frame tree structure of the current page.
+ FrameTree frame_tree_;
+
// The IDs for the Render[View|Process]Host hidden by this interstitial.
int original_child_id_;
int original_rvh_id_;
@@ -229,7 +252,7 @@ class CONTENT_EXPORT InterstitialPageImpl
// The original title of the contents that should be reverted to when the
// interstitial is hidden.
- string16 original_web_contents_title_;
+ base::string16 original_web_contents_title_;
// Our RenderViewHostViewDelegate, necessary for accelerators to work.
scoped_ptr<InterstitialPageRVHDelegateView> rvh_delegate_view_;
@@ -250,4 +273,4 @@ class CONTENT_EXPORT InterstitialPageImpl
} // namespace content
-#endif // CONTENT_BROWSER_WEB_CONTENTS_INTERSTITIAL_PAGE_IMPL_H_
+#endif // CONTENT_BROWSER_FRAME_HOST_INTERSTITIAL_PAGE_IMPL_H_
diff --git a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc
new file mode 100644
index 00000000000..830e1bfde1d
--- /dev/null
+++ b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc
@@ -0,0 +1,17 @@
+// 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/frame_host/interstitial_page_navigator_impl.h"
+
+#include "content/browser/frame_host/interstitial_page_impl.h"
+#include "content/browser/frame_host/navigator_delegate.h"
+
+namespace content {
+
+InterstitialPageNavigatorImpl::InterstitialPageNavigatorImpl(
+ InterstitialPageImpl* interstitial,
+ NavigationControllerImpl* navigation_controller) {
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h
new file mode 100644
index 00000000000..1b55fd21a3c
--- /dev/null
+++ b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h
@@ -0,0 +1,33 @@
+// 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_FRAME_HOST_INTERSTITIAL_PAGE_NAVIGATOR_IMPL_H_
+#define CONTENT_BROWSER_FRAME_HOST_INTERSTITIAL_PAGE_NAVIGATOR_IMPL_H_
+
+#include "base/memory/ref_counted.h"
+#include "content/browser/frame_host/navigator.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class NavigationControllerImpl;
+class InterstitialPageImpl;
+
+// Navigator implementation specific to InterstialPageImpl. It allows only one
+// navigation to commit, since interstitial pages are not allowed to navigate.
+class CONTENT_EXPORT InterstitialPageNavigatorImpl : public Navigator {
+ public:
+ InterstitialPageNavigatorImpl(
+ InterstitialPageImpl* interstitial,
+ NavigationControllerImpl* navigation_controller);
+
+ private:
+ virtual ~InterstitialPageNavigatorImpl() {}
+
+ DISALLOW_COPY_AND_ASSIGN(InterstitialPageNavigatorImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_INTERSTITIAL_PAGE_NAVIGATOR_IMPL_H_
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.cc b/chromium/content/browser/frame_host/navigation_controller_android.cc
new file mode 100644
index 00000000000..536e17dd3ec
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigation_controller_android.cc
@@ -0,0 +1,73 @@
+// 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/frame_host/navigation_controller_android.h"
+
+#include "base/android/jni_android.h"
+#include "content/public/browser/navigation_controller.h"
+#include "jni/NavigationControllerImpl_jni.h"
+
+using base::android::AttachCurrentThread;
+
+namespace content {
+
+// static
+bool NavigationControllerAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+NavigationControllerAndroid::NavigationControllerAndroid(
+ NavigationController* navigation_controller)
+ : navigation_controller_(navigation_controller) {
+ JNIEnv* env = AttachCurrentThread();
+ obj_.Reset(env,
+ Java_NavigationControllerImpl_create(
+ env, reinterpret_cast<intptr_t>(this)).obj());
+}
+
+NavigationControllerAndroid::~NavigationControllerAndroid() {
+ Java_NavigationControllerImpl_destroy(AttachCurrentThread(), obj_.obj());
+}
+
+base::android::ScopedJavaLocalRef<jobject>
+NavigationControllerAndroid::GetJavaObject() {
+ return base::android::ScopedJavaLocalRef<jobject>(obj_);
+}
+
+jboolean NavigationControllerAndroid::CanGoBack(JNIEnv* env, jobject obj) {
+ return navigation_controller_->CanGoBack();
+}
+
+jboolean NavigationControllerAndroid::CanGoForward(JNIEnv* env,
+ jobject obj) {
+ return navigation_controller_->CanGoForward();
+}
+
+jboolean NavigationControllerAndroid::CanGoToOffset(JNIEnv* env,
+ jobject obj,
+ jint offset) {
+ return navigation_controller_->CanGoToOffset(offset);
+}
+
+void NavigationControllerAndroid::GoBack(JNIEnv* env, jobject obj) {
+ navigation_controller_->GoBack();
+}
+
+void NavigationControllerAndroid::GoForward(JNIEnv* env, jobject obj) {
+ navigation_controller_->GoForward();
+}
+
+void NavigationControllerAndroid::GoToOffset(JNIEnv* env,
+ jobject obj,
+ jint offset) {
+ navigation_controller_->GoToOffset(offset);
+}
+
+void NavigationControllerAndroid::GoToNavigationIndex(JNIEnv* env,
+ jobject obj,
+ jint index) {
+ navigation_controller_->GoToIndex(index);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.h b/chromium/content/browser/frame_host/navigation_controller_android.h
new file mode 100644
index 00000000000..e0c96a63a0c
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigation_controller_android.h
@@ -0,0 +1,53 @@
+// 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_FRAME_HOST_NAVIGATION_CONTROLLER_ANDROID_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATION_CONTROLLER_ANDROID_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class NavigationController;
+
+// Android wrapper around NavigationController that provides safer passage
+// from java and back to native and provides java with a means of communicating
+// with its native counterpart.
+class CONTENT_EXPORT NavigationControllerAndroid {
+ public:
+ static bool Register(JNIEnv* env);
+
+ explicit NavigationControllerAndroid(
+ NavigationController* navigation_controller);
+ ~NavigationControllerAndroid();
+
+ NavigationController* navigation_controller() const {
+ return navigation_controller_;
+ }
+
+ base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
+
+ jboolean CanGoBack(JNIEnv* env, jobject obj);
+ jboolean CanGoForward(JNIEnv* env, jobject obj);
+ jboolean CanGoToOffset(JNIEnv* env, jobject obj, jint offset);
+ void GoBack(JNIEnv* env, jobject obj);
+ void GoForward(JNIEnv* env, jobject obj);
+ void GoToOffset(JNIEnv* env, jobject obj, jint offset);
+ void GoToNavigationIndex(JNIEnv* env, jobject obj, jint index);
+
+ private:
+ NavigationController* navigation_controller_;
+ base::android::ScopedJavaGlobalRef<jobject> obj_;
+
+ DISALLOW_COPY_AND_ASSIGN(NavigationControllerAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATION_CONTROLLER_ANDROID_H_
diff --git a/chromium/content/browser/frame_host/navigation_controller_delegate.h b/chromium/content/browser/frame_host/navigation_controller_delegate.h
new file mode 100644
index 00000000000..cb3204cde63
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigation_controller_delegate.h
@@ -0,0 +1,79 @@
+// 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_FRAME_HOST_NAVIGATION_CONTROLLER_DELEGATE_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATION_CONTROLLER_DELEGATE_H_
+
+#include <string>
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_details.h"
+
+namespace content {
+
+struct LoadCommittedDetails;
+struct LoadNotificationDetails;
+struct NativeWebKeyboardEvent;
+class InterstitialPage;
+class InterstitialPageImpl;
+class RenderViewHost;
+class SiteInstance;
+class WebContents;
+class WebContentsDelegate;
+
+// Interface for objects embedding a NavigationController to provide the
+// functionality NavigationController needs.
+// TODO(nasko): This interface should exist for short amount of time, while
+// we transition navigation code from WebContents to Navigator.
+class NavigationControllerDelegate {
+ public:
+ virtual ~NavigationControllerDelegate() {}
+
+ // Duplicates of WebContents methods.
+ virtual RenderViewHost* GetRenderViewHost() const = 0;
+ virtual InterstitialPage* GetInterstitialPage() const = 0;
+ virtual const std::string& GetContentsMimeType() const = 0;
+ virtual void NotifyNavigationStateChanged(unsigned changed_flags) = 0;
+ virtual void Stop() = 0;
+ virtual SiteInstance* GetSiteInstance() const = 0;
+ virtual SiteInstance* GetPendingSiteInstance() const = 0;
+ virtual int32 GetMaxPageID() = 0;
+ virtual int32 GetMaxPageIDForSiteInstance(SiteInstance* site_instance) = 0;
+ virtual bool IsLoading() const = 0;
+
+ // Methods from WebContentsImpl that NavigationControllerImpl needs to
+ // call.
+ virtual void NotifyBeforeFormRepostWarningShow() = 0;
+ virtual void NotifyNavigationEntryCommitted(
+ const LoadCommittedDetails& load_details) = 0;
+ virtual bool NavigateToPendingEntry(
+ NavigationController::ReloadType reload_type) = 0;
+ virtual void SetHistoryLengthAndPrune(
+ const SiteInstance* site_instance,
+ int merge_history_length,
+ int32 minimum_page_id) = 0;
+ virtual void CopyMaxPageIDsFrom(WebContents* web_contents) = 0;
+ virtual void UpdateMaxPageID(int32 page_id) = 0;
+ virtual void UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance,
+ int32 page_id) = 0;
+ virtual void ActivateAndShowRepostFormWarningDialog() = 0;
+
+ // This method is needed, since we are no longer guaranteed that the
+ // embedder for NavigationController will be a WebContents object.
+ virtual WebContents* GetWebContents() = 0;
+
+ // Methods needed by InterstitialPageImpl.
+ virtual bool IsHidden() = 0;
+ virtual void RenderViewForInterstitialPageCreated(
+ RenderViewHost* render_view_host) = 0;
+ virtual void AttachInterstitialPage(
+ InterstitialPageImpl* interstitial_page) = 0;
+ virtual void DetachInterstitialPage() = 0;
+ virtual void SetIsLoading(RenderViewHost* render_view_host,
+ bool is_loading,
+ LoadNotificationDetails* details) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATION_CONTROLLER_DELEGATE_H_
diff --git a/chromium/content/browser/web_contents/navigation_controller_impl.cc b/chromium/content/browser/frame_host/navigation_controller_impl.cc
index faad72b5f38..40f133679a5 100644
--- a/chromium/content/browser/web_contents/navigation_controller_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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/web_contents/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
#include "base/bind.h"
#include "base/debug/trace_event.h"
@@ -14,13 +14,12 @@
#include "content/browser/browser_url_handler_impl.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
+#include "content/browser/frame_host/debug_urls.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
#include "content/browser/renderer_host/render_view_host_impl.h" // Temporary
#include "content/browser/site_instance_impl.h"
-#include "content/browser/web_contents/debug_urls.h"
-#include "content/browser/web_contents/interstitial_page_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/web_contents/web_contents_screenshot_manager.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
@@ -32,7 +31,6 @@
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/user_metrics.h"
-#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/url_constants.h"
@@ -165,7 +163,7 @@ NavigationEntry* NavigationController::CreateNavigationEntry(
-1,
loaded_url,
referrer,
- string16(),
+ base::string16(),
transition,
is_renderer_initiated);
entry->SetVirtualURL(url);
@@ -197,21 +195,21 @@ base::Time NavigationControllerImpl::TimeSmoother::GetSmoothedTime(
}
NavigationControllerImpl::NavigationControllerImpl(
- WebContentsImpl* web_contents,
+ NavigationControllerDelegate* delegate,
BrowserContext* browser_context)
: browser_context_(browser_context),
pending_entry_(NULL),
last_committed_entry_index_(-1),
pending_entry_index_(-1),
transient_entry_index_(-1),
- web_contents_(web_contents),
+ delegate_(delegate),
max_restored_page_id_(-1),
ssl_manager_(this),
needs_reload_(false),
is_initial_navigation_(true),
pending_reload_(NO_RELOAD),
get_timestamp_callback_(base::Bind(&base::Time::Now)),
- screenshot_manager_(new WebContentsScreenshotManager(this)) {
+ screenshot_manager_(new NavigationEntryScreenshotManager(this)) {
DCHECK(browser_context_);
}
@@ -220,7 +218,7 @@ NavigationControllerImpl::~NavigationControllerImpl() {
}
WebContents* NavigationControllerImpl::GetWebContents() const {
- return web_contents_;
+ return delegate_->GetWebContents();
}
BrowserContext* NavigationControllerImpl::GetBrowserContext() const {
@@ -268,14 +266,14 @@ void NavigationControllerImpl::ReloadInternal(bool check_for_repost,
if (transient_entry_index_ != -1) {
// If an interstitial is showing, treat a reload as a navigation to the
// transient entry's URL.
- NavigationEntryImpl* active_entry =
- NavigationEntryImpl::FromNavigationEntry(GetActiveEntry());
- if (!active_entry)
+ NavigationEntryImpl* transient_entry =
+ NavigationEntryImpl::FromNavigationEntry(GetTransientEntry());
+ if (!transient_entry)
return;
- LoadURL(active_entry->GetURL(),
+ LoadURL(transient_entry->GetURL(),
Referrer(),
PAGE_TRANSITION_RELOAD,
- active_entry->extra_headers());
+ transient_entry->extra_headers());
return;
}
@@ -303,16 +301,24 @@ void NavigationControllerImpl::ReloadInternal(bool check_for_repost,
if (!entry)
return;
+ if (reload_type == NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL &&
+ entry->GetOriginalRequestURL().is_valid() && !entry->GetHasPostData()) {
+ // We may have been redirected when navigating to the current URL.
+ // Use the URL the user originally intended to visit, if it's valid and if a
+ // POST wasn't involved; the latter case avoids issues with sending data to
+ // the wrong page.
+ entry->SetURL(entry->GetOriginalRequestURL());
+ }
+
if (g_check_for_repost && check_for_repost &&
entry->GetHasPostData()) {
// The user is asking to reload a page with POST data. Prompt to make sure
// they really want to do this. If they do, the dialog will call us back
// with check_for_repost = false.
- web_contents_->NotifyBeforeFormRepostWarningShow();
+ delegate_->NotifyBeforeFormRepostWarningShow();
pending_reload_ = reload_type;
- web_contents_->Activate();
- web_contents_->GetDelegate()->ShowRepostFormWarningDialog(web_contents_);
+ delegate_->ActivateAndShowRepostFormWarningDialog();
} else {
if (!IsInitialNavigation())
DiscardNonCommittedEntriesInternal();
@@ -325,7 +331,10 @@ void NavigationControllerImpl::ReloadInternal(bool check_for_repost,
// Tabs that are discarded due to low memory conditions may not have a site
// instance, and should not be treated as a cross-site reload.
SiteInstanceImpl* site_instance = entry->site_instance();
- if (site_instance &&
+ // Permit reloading guests without further checks.
+ bool is_guest = site_instance && site_instance->HasProcess() &&
+ site_instance->GetProcess()->IsGuest();
+ if (!is_guest && site_instance &&
site_instance->HasWrongProcessForURL(entry->GetURL())) {
// Create a navigation entry that resembles the current one, but do not
// copy page id, site instance, content state, or timestamp.
@@ -348,7 +357,7 @@ void NavigationControllerImpl::ReloadInternal(bool check_for_repost,
// meanwhile, so we need to revert to the default title upon reload and
// invalidate the previously cached title (SetTitle will do both).
// See Chromium issue 96041.
- pending_entry_->SetTitle(string16());
+ pending_entry_->SetTitle(base::string16());
pending_entry_->SetTransitionType(PAGE_TRANSITION_RELOAD);
}
@@ -418,7 +427,7 @@ NavigationEntry* NavigationControllerImpl::GetVisibleEntry() const {
// the new tab. If another page modifies this blank page, a URL spoof is
// possible, so we must stop showing the pending entry.
RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
- web_contents_->GetRenderViewHost());
+ delegate_->GetRenderViewHost());
bool safe_to_show_pending =
pending_entry_ &&
// Require a new navigation.
@@ -459,12 +468,12 @@ NavigationEntry* NavigationControllerImpl::GetLastCommittedEntry() const {
}
bool NavigationControllerImpl::CanViewSource() const {
- const std::string& mime_type = web_contents_->GetContentsMimeType();
+ const std::string& mime_type = delegate_->GetContentsMimeType();
bool is_viewable_mime_type = net::IsSupportedNonImageMimeType(mime_type) &&
!net::IsSupportedMediaMimeType(mime_type);
- NavigationEntry* active_entry = GetActiveEntry();
- return active_entry && !active_entry->IsViewSourceMode() &&
- is_viewable_mime_type && !web_contents_->GetInterstitialPage();
+ NavigationEntry* visible_entry = GetVisibleEntry();
+ return visible_entry && !visible_entry->IsViewSourceMode() &&
+ is_viewable_mime_type && !delegate_->GetInterstitialPage();
}
int NavigationControllerImpl::GetLastCommittedEntryIndex() const {
@@ -499,9 +508,9 @@ void NavigationControllerImpl::TakeScreenshot() {
}
void NavigationControllerImpl::SetScreenshotManager(
- WebContentsScreenshotManager* manager) {
+ NavigationEntryScreenshotManager* manager) {
screenshot_manager_.reset(manager ? manager :
- new WebContentsScreenshotManager(this));
+ new NavigationEntryScreenshotManager(this));
}
bool NavigationControllerImpl::CanGoBack() const {
@@ -632,6 +641,16 @@ void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) {
if (HandleDebugURL(params.url, params.transition_type))
return;
+ // Any renderer-side debug URLs or javascript: URLs should be ignored if the
+ // renderer process is not live, unless it is the initial navigation of the
+ // tab.
+ if (IsRendererDebugURL(params.url)) {
+ // TODO(creis): Find the RVH for the correct frame.
+ if (!delegate_->GetRenderViewHost()->IsRenderViewLive() &&
+ !IsInitialNavigation())
+ return;
+ }
+
// Checks based on params.load_type.
switch (params.load_type) {
case LOAD_TYPE_DEFAULT:
@@ -681,6 +700,10 @@ void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) {
params.is_renderer_initiated,
params.extra_headers,
browser_context_));
+ if (params.frame_tree_node_id != -1)
+ entry->set_frame_tree_node_id(params.frame_tree_node_id);
+ if (params.redirect_chain.size() > 0)
+ entry->set_redirect_chain(params.redirect_chain);
if (params.should_replace_current_entry)
entry->set_should_replace_entry(true);
entry->set_should_clear_history_list(params.should_clear_history_list);
@@ -771,7 +794,7 @@ bool NavigationControllerImpl::RendererDidNavigate(
// the caller that nothing has happened.
if (pending_entry_) {
DiscardNonCommittedEntries();
- web_contents_->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
+ delegate_->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
}
return false;
default:
@@ -800,24 +823,18 @@ bool NavigationControllerImpl::RendererDidNavigate(
active_entry->SetTimestamp(timestamp);
active_entry->SetHttpStatusCode(params.http_status_code);
active_entry->SetPageState(params.page_state);
- // No longer needed since content state will hold the post data if any.
- active_entry->SetBrowserInitiatedPostData(NULL);
-
- // Once committed, we do not need to track if the entry was initiated by
- // the renderer.
- active_entry->set_is_renderer_initiated(false);
- // Once committed, we no longer need to track whether the session history was
- // cleared. Navigating to this entry again shouldn't clear it again.
- active_entry->set_should_clear_history_list(false);
+ // Once it is committed, we no longer need to track several pieces of state on
+ // the entry.
+ active_entry->ResetForCommit();
// The active entry's SiteInstance should match our SiteInstance.
- CHECK(active_entry->site_instance() == web_contents_->GetSiteInstance());
+ CHECK(active_entry->site_instance() == delegate_->GetSiteInstance());
// Remember the bindings the renderer process has at this point, so that
// we do not grant this entry additional bindings if we come back to it.
active_entry->SetBindings(
- web_contents_->GetRenderViewHost()->GetEnabledBindings());
+ delegate_->GetRenderViewHost()->GetEnabledBindings());
// Now prep the rest of the details for the notification and broadcast.
details->entry = active_entry;
@@ -854,7 +871,7 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
return NAVIGATION_TYPE_NAV_IGNORE;
}
- if (params.page_id > web_contents_->GetMaxPageID()) {
+ if (params.page_id > delegate_->GetMaxPageID()) {
// Greater page IDs than we've ever seen before are new pages. We may or may
// not have a pending entry for the page, and this may or may not be the
// main frame.
@@ -878,7 +895,7 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
// Now we know that the notification is for an existing page. Find that entry.
int existing_entry_index = GetEntryIndexWithPageID(
- web_contents_->GetSiteInstance(),
+ delegate_->GetSiteInstance(),
params.page_id);
if (existing_entry_index == -1) {
// The page was not found. It could have been pruned because of the limit on
@@ -897,7 +914,7 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
temp.append("#page");
temp.append(base::IntToString(params.page_id));
temp.append("#max");
- temp.append(base::IntToString(web_contents_->GetMaxPageID()));
+ temp.append(base::IntToString(delegate_->GetMaxPageID()));
temp.append("#frame");
temp.append(base::IntToString(params.frame_id));
temp.append("#ids");
@@ -912,13 +929,13 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
temp.append(base::IntToString(entries_[i]->site_instance()->GetId()));
else
temp.append("N");
- if (entries_[i]->site_instance() != web_contents_->GetSiteInstance())
+ if (entries_[i]->site_instance() != delegate_->GetSiteInstance())
temp.append("x");
temp.append(",");
}
GURL url(temp);
static_cast<RenderViewHostImpl*>(
- web_contents_->GetRenderViewHost())->Send(
+ delegate_->GetRenderViewHost())->Send(
new ViewMsg_TempCrashWithData(url));
return NAVIGATION_TYPE_NAV_IGNORE;
}
@@ -964,16 +981,6 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
return NAVIGATION_TYPE_EXISTING_PAGE;
}
-bool NavigationControllerImpl::IsRedirect(
- const ViewHostMsg_FrameNavigate_Params& params) {
- // For main frame transition, we judge by params.transition.
- // Otherwise, by params.redirects.
- if (PageTransitionIsMainFrame(params.transition)) {
- return PageTransitionIsRedirect(params.transition);
- }
- return params.redirects.size() > 1;
-}
-
void NavigationControllerImpl::RendererDidNavigateToNewPage(
const ViewHostMsg_FrameNavigate_Params& params, bool replace_entry) {
NavigationEntryImpl* new_entry;
@@ -983,7 +990,7 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
// the SiteInstance hasn't been assigned to something else.
if (pending_entry_ &&
(!pending_entry_->site_instance() ||
- pending_entry_->site_instance() == web_contents_->GetSiteInstance())) {
+ pending_entry_->site_instance() == delegate_->GetSiteInstance())) {
new_entry = new NavigationEntryImpl(*pending_entry_);
// Don't use the page type from the pending entry. Some interstitial page
@@ -1017,7 +1024,7 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
new_entry->SetPageID(params.page_id);
new_entry->SetTransitionType(params.transition);
new_entry->set_site_instance(
- static_cast<SiteInstanceImpl*>(web_contents_->GetSiteInstance()));
+ static_cast<SiteInstanceImpl*>(delegate_->GetSiteInstance()));
new_entry->SetHasPostData(params.is_post);
new_entry->SetPostID(params.post_id);
new_entry->SetOriginalRequestURL(params.original_request_url);
@@ -1044,7 +1051,7 @@ void NavigationControllerImpl::RendererDidNavigateToExistingPage(
// This is a back/forward navigation. The existing page for the ID is
// guaranteed to exist by ClassifyNavigation, and we just need to update it
// with new information from the renderer.
- int entry_index = GetEntryIndexWithPageID(web_contents_->GetSiteInstance(),
+ int entry_index = GetEntryIndexWithPageID(delegate_->GetSiteInstance(),
params.page_id);
DCHECK(entry_index >= 0 &&
entry_index < static_cast<int>(entries_.size()));
@@ -1063,9 +1070,9 @@ void NavigationControllerImpl::RendererDidNavigateToExistingPage(
// The site instance will normally be the same except during session restore,
// when no site instance will be assigned.
DCHECK(entry->site_instance() == NULL ||
- entry->site_instance() == web_contents_->GetSiteInstance());
+ entry->site_instance() == delegate_->GetSiteInstance());
entry->set_site_instance(
- static_cast<SiteInstanceImpl*>(web_contents_->GetSiteInstance()));
+ static_cast<SiteInstanceImpl*>(delegate_->GetSiteInstance()));
entry->SetHasPostData(params.is_post);
entry->SetPostID(params.post_id);
@@ -1084,7 +1091,7 @@ void NavigationControllerImpl::RendererDidNavigateToExistingPage(
// If a transient entry was removed, the indices might have changed, so we
// have to query the entry index again.
last_committed_entry_index_ =
- GetEntryIndexWithPageID(web_contents_->GetSiteInstance(), params.page_id);
+ GetEntryIndexWithPageID(delegate_->GetSiteInstance(), params.page_id);
}
void NavigationControllerImpl::RendererDidNavigateToSamePage(
@@ -1093,7 +1100,7 @@ void NavigationControllerImpl::RendererDidNavigateToSamePage(
// entry for this page ID. This entry is guaranteed to exist by
// ClassifyNavigation. All we need to do is update the existing entry.
NavigationEntryImpl* existing_entry = GetEntryWithPageID(
- web_contents_->GetSiteInstance(), params.page_id);
+ delegate_->GetSiteInstance(), params.page_id);
// We assign the entry's unique ID to be that of the new one. Since this is
// always the result of a user action, we want to dismiss infobars, etc. like
@@ -1105,6 +1112,10 @@ void NavigationControllerImpl::RendererDidNavigateToSamePage(
UpdateVirtualURLToURL(existing_entry, params.url);
existing_entry->SetURL(params.url);
+ // The page may have been requested with a different HTTP method.
+ existing_entry->SetHasPostData(params.is_post);
+ existing_entry->SetPostID(params.post_id);
+
DiscardNonCommittedEntries();
}
@@ -1114,7 +1125,7 @@ void NavigationControllerImpl::RendererDidNavigateInPage(
"WebKit should only tell us about in-page navs for the main frame.";
// We're guaranteed to have an entry for this one.
NavigationEntryImpl* existing_entry = GetEntryWithPageID(
- web_contents_->GetSiteInstance(), params.page_id);
+ delegate_->GetSiteInstance(), params.page_id);
// Reference fragment navigation. We're guaranteed to have the last_committed
// entry and it will be the same page as the new navigation (minus the
@@ -1132,7 +1143,7 @@ void NavigationControllerImpl::RendererDidNavigateInPage(
// If a transient entry was removed, the indices might have changed, so we
// have to query the entry index again.
last_committed_entry_index_ =
- GetEntryIndexWithPageID(web_contents_->GetSiteInstance(), params.page_id);
+ GetEntryIndexWithPageID(delegate_->GetSiteInstance(), params.page_id);
}
void NavigationControllerImpl::RendererDidNavigateNewSubframe(
@@ -1166,7 +1177,7 @@ bool NavigationControllerImpl::RendererDidNavigateAutoSubframe(
// navigation entry. This is case "2." in NAV_AUTO_SUBFRAME comment in the
// header file. In case "1." this will be a NOP.
int entry_index = GetEntryIndexWithPageID(
- web_contents_->GetSiteInstance(),
+ delegate_->GetSiteInstance(),
params.page_id);
if (entry_index < 0 ||
entry_index >= static_cast<int>(entries_.size())) {
@@ -1231,13 +1242,14 @@ void NavigationControllerImpl::CopyStateFrom(
// Copy the max page id map from the old tab to the new tab. This ensures
// that new and existing navigations in the tab's current SiteInstances
// are identified properly.
- web_contents_->CopyMaxPageIDsFrom(source.web_contents());
+ delegate_->CopyMaxPageIDsFrom(source.delegate()->GetWebContents());
}
void NavigationControllerImpl::CopyStateFromAndPrune(
- NavigationController* temp) {
+ NavigationController* temp,
+ bool replace_entry) {
// It is up to callers to check the invariants before calling this.
- CHECK(CanPruneAllButVisible());
+ CHECK(CanPruneAllButLastCommitted());
NavigationControllerImpl* source =
static_cast<NavigationControllerImpl*>(temp);
@@ -1251,15 +1263,16 @@ void NavigationControllerImpl::CopyStateFromAndPrune(
last_committed->site_instance());
int32 minimum_page_id = last_committed->GetPageID();
int32 max_page_id =
- web_contents_->GetMaxPageIDForSiteInstance(site_instance.get());
+ delegate_->GetMaxPageIDForSiteInstance(site_instance.get());
// Remove all the entries leaving the active entry.
- PruneAllButVisibleInternal();
+ PruneAllButLastCommittedInternal();
// We now have one entry, possibly with a new pending entry. Ensure that
// adding the entries from source won't put us over the limit.
DCHECK_EQ(1, GetEntryCount());
- source->PruneOldestEntryIfFull();
+ if (!replace_entry)
+ source->PruneOldestEntryIfFull();
// Insert the entries from source. Don't use source->GetCurrentEntryIndex as
// we don't want to copy over the transient entry. Ignore any pending entry,
@@ -1269,29 +1282,36 @@ void NavigationControllerImpl::CopyStateFromAndPrune(
max_source_index = source->GetEntryCount();
else
max_source_index++;
+
+ // Ignore the source's current entry if merging with replacement.
+ // TODO(davidben): This should preserve entries forward of the current
+ // too. http://crbug.com/317872
+ if (replace_entry && max_source_index > 0)
+ max_source_index--;
+
InsertEntriesFrom(*source, max_source_index);
// Adjust indices such that the last entry and pending are at the end now.
last_committed_entry_index_ = GetEntryCount() - 1;
- web_contents_->SetHistoryLengthAndPrune(site_instance.get(),
- max_source_index,
- minimum_page_id);
+ delegate_->SetHistoryLengthAndPrune(site_instance.get(),
+ max_source_index,
+ minimum_page_id);
// Copy the max page id map from the old tab to the new tab. This ensures
// that new and existing navigations in the tab's current SiteInstances
// are identified properly.
- web_contents_->CopyMaxPageIDsFrom(source->web_contents());
+ delegate_->CopyMaxPageIDsFrom(source->delegate()->GetWebContents());
// If there is a last committed entry, be sure to include it in the new
// max page ID map.
if (max_page_id > -1) {
- web_contents_->UpdateMaxPageIDForSiteInstance(site_instance.get(),
- max_page_id);
+ delegate_->UpdateMaxPageIDForSiteInstance(site_instance.get(),
+ max_page_id);
}
}
-bool NavigationControllerImpl::CanPruneAllButVisible() {
+bool NavigationControllerImpl::CanPruneAllButLastCommitted() {
// If there is no last committed entry, we cannot prune. Even if there is a
// pending entry, it may not commit, leaving this WebContents blank, despite
// possibly giving it new entries via CopyStateFromAndPrune.
@@ -1312,26 +1332,26 @@ bool NavigationControllerImpl::CanPruneAllButVisible() {
return true;
}
-void NavigationControllerImpl::PruneAllButVisible() {
- PruneAllButVisibleInternal();
+void NavigationControllerImpl::PruneAllButLastCommitted() {
+ PruneAllButLastCommittedInternal();
// We should still have a last committed entry.
DCHECK_NE(-1, last_committed_entry_index_);
- NavigationEntryImpl* entry =
- NavigationEntryImpl::FromNavigationEntry(GetActiveEntry());
// We pass 0 instead of GetEntryCount() for the history_length parameter of
// SetHistoryLengthAndPrune, because it will create history_length additional
// history entries.
// TODO(jochen): This API is confusing and we should clean it up.
// http://crbug.com/178491
- web_contents_->SetHistoryLengthAndPrune(
+ NavigationEntryImpl* entry =
+ NavigationEntryImpl::FromNavigationEntry(GetVisibleEntry());
+ delegate_->SetHistoryLengthAndPrune(
entry->site_instance(), 0, entry->GetPageID());
}
-void NavigationControllerImpl::PruneAllButVisibleInternal() {
+void NavigationControllerImpl::PruneAllButLastCommittedInternal() {
// It is up to callers to check the invariants before calling this.
- CHECK(CanPruneAllButVisible());
+ CHECK(CanPruneAllButLastCommitted());
// Erase all entries but the last committed entry. There may still be a
// new pending entry after this.
@@ -1438,7 +1458,7 @@ void NavigationControllerImpl::DiscardNonCommittedEntries() {
// If there was a transient entry, invalidate everything so the new active
// entry state is shown.
if (transient) {
- web_contents_->NotifyNavigationStateChanged(kInvalidateAll);
+ delegate_->NotifyNavigationStateChanged(kInvalidateAll);
}
}
@@ -1491,7 +1511,7 @@ void NavigationControllerImpl::InsertOrReplaceEntry(NavigationEntryImpl* entry,
last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1;
// This is a new page ID, so we need everybody to know about it.
- web_contents_->UpdateMaxPageID(entry->GetPageID());
+ delegate_->UpdateMaxPageID(entry->GetPageID());
}
void NavigationControllerImpl::PruneOldestEntryIfFull() {
@@ -1518,12 +1538,12 @@ void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) {
NavigationEntryImpl::RESTORE_NONE) &&
(entries_[pending_entry_index_]->GetTransitionType() &
PAGE_TRANSITION_FORWARD_BACK)) {
- web_contents_->Stop();
+ delegate_->Stop();
// If an interstitial page is showing, we want to close it to get back
// to what was showing before.
- if (web_contents_->GetInterstitialPage())
- web_contents_->GetInterstitialPage()->DontProceed();
+ if (delegate_->GetInterstitialPage())
+ delegate_->GetInterstitialPage()->DontProceed();
DiscardNonCommittedEntries();
return;
@@ -1533,8 +1553,8 @@ void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) {
// cannot make new requests. Unblock (and disable) it to allow this
// navigation to succeed. The interstitial will stay visible until the
// resulting DidNavigate.
- if (web_contents_->GetInterstitialPage()) {
- static_cast<InterstitialPageImpl*>(web_contents_->GetInterstitialPage())->
+ if (delegate_->GetInterstitialPage()) {
+ static_cast<InterstitialPageImpl*>(delegate_->GetInterstitialPage())->
CancelForNavigation();
}
@@ -1544,7 +1564,7 @@ void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) {
pending_entry_ = entries_[pending_entry_index_].get();
}
- if (!web_contents_->NavigateToPendingEntry(reload_type))
+ if (!delegate_->NavigateToPendingEntry(reload_type))
DiscardNonCommittedEntries();
// If the entry is being restored and doesn't have a SiteInstance yet, fill
@@ -1554,22 +1574,22 @@ void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) {
if (pending_entry_ && !pending_entry_->site_instance() &&
pending_entry_->restore_type() != NavigationEntryImpl::RESTORE_NONE) {
pending_entry_->set_site_instance(static_cast<SiteInstanceImpl*>(
- web_contents_->GetPendingSiteInstance()));
+ delegate_->GetPendingSiteInstance()));
pending_entry_->set_restore_type(NavigationEntryImpl::RESTORE_NONE);
}
}
void NavigationControllerImpl::NotifyNavigationEntryCommitted(
LoadCommittedDetails* details) {
- details->entry = GetActiveEntry();
+ details->entry = GetLastCommittedEntry();
// We need to notify the ssl_manager_ before the web_contents_ so the
// location bar will have up-to-date information about the security style
// when it wants to draw. See http://crbug.com/11157
ssl_manager_.DidCommitProvisionalLoad(*details);
- web_contents_->NotifyNavigationStateChanged(kInvalidateAll);
- web_contents_->NotifyNavigationEntryCommitted(*details);
+ delegate_->NotifyNavigationStateChanged(kInvalidateAll);
+ delegate_->NotifyNavigationEntryCommitted(*details);
// TODO(avi): Remove. http://crbug.com/170921
NotificationDetails notification_details =
@@ -1671,7 +1691,7 @@ void NavigationControllerImpl::SetTransientEntry(NavigationEntry* entry) {
entries_.begin() + index, linked_ptr<NavigationEntryImpl>(
NavigationEntryImpl::FromNavigationEntry(entry)));
transient_entry_index_ = index;
- web_contents_->NotifyNavigationStateChanged(kInvalidateAll);
+ delegate_->NotifyNavigationStateChanged(kInvalidateAll);
}
void NavigationControllerImpl::InsertEntriesFrom(
diff --git a/chromium/content/browser/web_contents/navigation_controller_impl.h b/chromium/content/browser/frame_host/navigation_controller_impl.h
index 6e6f333506c..99fc36ae002 100644
--- a/chromium/content/browser/web_contents/navigation_controller_impl.h
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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_WEB_CONTENTS_NAVIGATION_CONTROLLER_IMPL_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_NAVIGATION_CONTROLLER_IMPL_H_
+#ifndef CONTENT_BROWSER_FRAME_HOST_NAVIGATION_CONTROLLER_IMPL_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATION_CONTROLLER_IMPL_H_
#include "base/callback.h"
#include "base/compiler_specific.h"
@@ -11,6 +11,7 @@
#include "base/memory/linked_ptr.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "content/browser/frame_host/navigation_controller_delegate.h"
#include "content/browser/ssl/ssl_manager.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_type.h"
@@ -20,8 +21,7 @@ struct ViewHostMsg_FrameNavigate_Params;
namespace content {
class NavigationEntryImpl;
class RenderViewHost;
-class WebContentsImpl;
-class WebContentsScreenshotManager;
+class NavigationEntryScreenshotManager;
class SiteInstance;
struct LoadCommittedDetails;
@@ -29,7 +29,7 @@ class CONTENT_EXPORT NavigationControllerImpl
: public NON_EXPORTED_BASE(NavigationController) {
public:
NavigationControllerImpl(
- WebContentsImpl* web_contents,
+ NavigationControllerDelegate* delegate,
BrowserContext* browser_context);
virtual ~NavigationControllerImpl();
@@ -88,10 +88,10 @@ class CONTENT_EXPORT NavigationControllerImpl
int index) OVERRIDE;
virtual void CopyStateFrom(
const NavigationController& source) OVERRIDE;
- virtual void CopyStateFromAndPrune(
- NavigationController* source) OVERRIDE;
- virtual bool CanPruneAllButVisible() OVERRIDE;
- virtual void PruneAllButVisible() OVERRIDE;
+ virtual void CopyStateFromAndPrune(NavigationController* source,
+ bool replace_entry) OVERRIDE;
+ virtual bool CanPruneAllButLastCommitted() OVERRIDE;
+ virtual void PruneAllButLastCommitted() OVERRIDE;
virtual void ClearAllScreenshots() OVERRIDE;
// The session storage namespace that all child RenderViews belonging to
@@ -114,10 +114,8 @@ class CONTENT_EXPORT NavigationControllerImpl
SiteInstance* instance,
int32 page_id) const;
- // WebContentsImpl -----------------------------------------------------------
-
- WebContentsImpl* web_contents() const {
- return web_contents_;
+ NavigationControllerDelegate* delegate() const {
+ return delegate_;
}
// For use by WebContentsImpl ------------------------------------------------
@@ -202,11 +200,13 @@ class CONTENT_EXPORT NavigationControllerImpl
// a new screenshot-manager is set, or when the controller is destroyed.
// Setting a NULL manager recreates the default screenshot manager and uses
// that.
- void SetScreenshotManager(WebContentsScreenshotManager* manager);
+ void SetScreenshotManager(NavigationEntryScreenshotManager* manager);
+
+ // Discards only the pending entry.
+ void DiscardPendingEntry();
private:
friend class RestoreHelper;
- friend class WebContentsImpl; // For invoking OnReservedPageIDRange.
FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest,
PurgeScreenshot);
@@ -293,9 +293,6 @@ class CONTENT_EXPORT NavigationControllerImpl
// Discards both the pending and transient entries.
void DiscardNonCommittedEntriesInternal();
- // Discards only the pending entry.
- void DiscardPendingEntry();
-
// Discards only the transient entry.
void DiscardTransientEntry();
@@ -304,13 +301,11 @@ class CONTENT_EXPORT NavigationControllerImpl
void PruneOldestEntryIfFull();
// Removes all entries except the last committed entry. If there is a new
- // pending navigation it is preserved. In contrast to PruneAllButVisible()
- // this does not update the session history of the RenderView. Callers
- // must ensure that |CanPruneAllButVisible| returns true before calling this.
- void PruneAllButVisibleInternal();
-
- // Returns true if the navigation is redirect.
- bool IsRedirect(const ViewHostMsg_FrameNavigate_Params& params);
+ // pending navigation it is preserved. In contrast to
+ // PruneAllButLastCommitted() this does not update the session history of the
+ // RenderView. Callers must ensure that |CanPruneAllButLastCommitted| returns
+ // true before calling this.
+ void PruneAllButLastCommittedInternal();
// Returns true if the navigation is likley to be automatic rather than
// user-initiated.
@@ -358,9 +353,9 @@ class CONTENT_EXPORT NavigationControllerImpl
// after the transient entry will become invalid if you navigate forward.
int transient_entry_index_;
- // The WebContents associated with the controller. Possibly NULL during
+ // The delegate associated with the controller. Possibly NULL during
// setup.
- WebContentsImpl* web_contents_;
+ NavigationControllerDelegate* delegate_;
// The max restored page ID in this controller, if it was restored. We must
// store this so that WebContentsImpl can tell any renderer in charge of one
@@ -403,11 +398,11 @@ class CONTENT_EXPORT NavigationControllerImpl
// the wrong order in the history view.
TimeSmoother time_smoother_;
- scoped_ptr<WebContentsScreenshotManager> screenshot_manager_;
+ scoped_ptr<NavigationEntryScreenshotManager> screenshot_manager_;
DISALLOW_COPY_AND_ASSIGN(NavigationControllerImpl);
};
} // namespace content
-#endif // CONTENT_BROWSER_WEB_CONTENTS_NAVIGATION_CONTROLLER_IMPL_H_
+#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATION_CONTROLLER_IMPL_H_
diff --git a/chromium/content/browser/web_contents/navigation_controller_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
index e91ad13fe72..68f753a5e91 100644
--- a/chromium/content/browser/web_contents/navigation_controller_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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.
@@ -11,26 +11,17 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
-// These are only used for commented out tests. If someone wants to enable
-// them, they should be moved to chrome first.
-// #include "chrome/browser/history/history_service.h"
-// #include "chrome/browser/profiles/profile_manager.h"
-// #include "chrome/browser/sessions/session_service.h"
-// #include "chrome/browser/sessions/session_service_factory.h"
-// #include "chrome/browser/sessions/session_service_test_helper.h"
-// #include "chrome/browser/sessions/session_types.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
+#include "content/browser/frame_host/navigator.h"
#include "content/browser/site_instance_impl.h"
-#include "content/browser/web_contents/navigation_controller_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/web_contents/web_contents_screenshot_manager.h"
#include "content/common/view_messages.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_view_host_observer.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/page_state.h"
@@ -38,6 +29,7 @@
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_notification_tracker.h"
#include "content/public/test/test_utils.h"
+#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "net/base/net_util.h"
#include "skia/ext/platform_canvas.h"
@@ -73,10 +65,10 @@ bool DoImagesMatch(const gfx::Image& a, const gfx::Image& b) {
a_bitmap.getSize()) == 0;
}
-class MockScreenshotManager : public content::WebContentsScreenshotManager {
+class MockScreenshotManager : public content::NavigationEntryScreenshotManager {
public:
explicit MockScreenshotManager(content::NavigationControllerImpl* owner)
- : content::WebContentsScreenshotManager(owner),
+ : content::NavigationEntryScreenshotManager(owner),
encoding_screenshot_in_progress_(false) {
}
@@ -94,7 +86,7 @@ class MockScreenshotManager : public content::WebContentsScreenshotManager {
}
int GetScreenshotCount() {
- return content::WebContentsScreenshotManager::GetScreenshotCount();
+ return content::NavigationEntryScreenshotManager::GetScreenshotCount();
}
void WaitUntilScreenshotIsReady() {
@@ -105,7 +97,7 @@ class MockScreenshotManager : public content::WebContentsScreenshotManager {
}
private:
- // Overridden from content::WebContentsScreenshotManager:
+ // Overridden from content::NavigationEntryScreenshotManager:
virtual void TakeScreenshotImpl(
content::RenderViewHost* host,
content::NavigationEntryImpl* entry) OVERRIDE {
@@ -113,7 +105,7 @@ class MockScreenshotManager : public content::WebContentsScreenshotManager {
virtual void OnScreenshotSet(content::NavigationEntryImpl* entry) OVERRIDE {
encoding_screenshot_in_progress_ = false;
- WebContentsScreenshotManager::OnScreenshotSet(entry);
+ NavigationEntryScreenshotManager::OnScreenshotSet(entry);
if (message_loop_runner_.get())
message_loop_runner_->Quit();
}
@@ -202,16 +194,27 @@ class NavigationControllerTest
}
// WebContentsObserver:
+ virtual void DidStartNavigationToPendingEntry(
+ const GURL& url,
+ NavigationController::ReloadType reload_type) OVERRIDE {
+ navigated_url_ = url;
+ }
+
virtual void NavigationEntryCommitted(
const LoadCommittedDetails& load_details) OVERRIDE {
navigation_entry_committed_counter_++;
}
+ const GURL& navigated_url() const {
+ return navigated_url_;
+ }
+
NavigationControllerImpl& controller_impl() {
return static_cast<NavigationControllerImpl&>(controller());
}
protected:
+ GURL navigated_url_;
size_t navigation_entry_committed_counter_;
};
@@ -253,7 +256,6 @@ TEST_F(NavigationControllerTest, Defaults) {
NavigationControllerImpl& controller = controller_impl();
EXPECT_FALSE(controller.GetPendingEntry());
- EXPECT_FALSE(controller.GetActiveEntry());
EXPECT_FALSE(controller.GetVisibleEntry());
EXPECT_FALSE(controller.GetLastCommittedEntry());
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
@@ -277,7 +279,7 @@ TEST_F(NavigationControllerTest, GoToOffset) {
test_rvh()->SendNavigate(0, urls[0]);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_EQ(urls[0], controller.GetActiveEntry()->GetVirtualURL());
+ EXPECT_EQ(urls[0], controller.GetVisibleEntry()->GetVirtualURL());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
EXPECT_FALSE(controller.CanGoToOffset(1));
@@ -286,7 +288,7 @@ TEST_F(NavigationControllerTest, GoToOffset) {
test_rvh()->SendNavigate(i, urls[i]);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_EQ(urls[i], controller.GetActiveEntry()->GetVirtualURL());
+ EXPECT_EQ(urls[i], controller.GetVisibleEntry()->GetVirtualURL());
EXPECT_TRUE(controller.CanGoToOffset(-i));
EXPECT_FALSE(controller.CanGoToOffset(-(i + 1)));
EXPECT_FALSE(controller.CanGoToOffset(1));
@@ -349,7 +351,6 @@ TEST_F(NavigationControllerTest, LoadURL) {
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
EXPECT_FALSE(controller.GetLastCommittedEntry());
ASSERT_TRUE(controller.GetPendingEntry());
- EXPECT_EQ(controller.GetPendingEntry(), controller.GetActiveEntry());
EXPECT_EQ(controller.GetPendingEntry(), controller.GetVisibleEntry());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
@@ -372,8 +373,7 @@ TEST_F(NavigationControllerTest, LoadURL) {
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
EXPECT_TRUE(controller.GetLastCommittedEntry());
EXPECT_FALSE(controller.GetPendingEntry());
- ASSERT_TRUE(controller.GetActiveEntry());
- EXPECT_EQ(controller.GetActiveEntry(), controller.GetVisibleEntry());
+ ASSERT_TRUE(controller.GetVisibleEntry());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
EXPECT_EQ(contents()->GetMaxPageID(), 0);
@@ -381,7 +381,7 @@ TEST_F(NavigationControllerTest, LoadURL) {
controller.GetLastCommittedEntry())->bindings());
// The timestamp should have been set.
- EXPECT_FALSE(controller.GetActiveEntry()->GetTimestamp().is_null());
+ EXPECT_FALSE(controller.GetVisibleEntry()->GetTimestamp().is_null());
// Load another...
controller.LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
@@ -392,7 +392,6 @@ TEST_F(NavigationControllerTest, LoadURL) {
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
EXPECT_TRUE(controller.GetLastCommittedEntry());
ASSERT_TRUE(controller.GetPendingEntry());
- EXPECT_EQ(controller.GetPendingEntry(), controller.GetActiveEntry());
EXPECT_EQ(controller.GetPendingEntry(), controller.GetVisibleEntry());
// TODO(darin): maybe this should really be true?
EXPECT_FALSE(controller.CanGoBack());
@@ -415,13 +414,12 @@ TEST_F(NavigationControllerTest, LoadURL) {
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
EXPECT_TRUE(controller.GetLastCommittedEntry());
EXPECT_FALSE(controller.GetPendingEntry());
- ASSERT_TRUE(controller.GetActiveEntry());
- EXPECT_EQ(controller.GetActiveEntry(), controller.GetVisibleEntry());
+ ASSERT_TRUE(controller.GetVisibleEntry());
EXPECT_TRUE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
EXPECT_EQ(contents()->GetMaxPageID(), 1);
- EXPECT_FALSE(controller.GetActiveEntry()->GetTimestamp().is_null());
+ EXPECT_FALSE(controller.GetVisibleEntry()->GetTimestamp().is_null());
}
namespace {
@@ -502,7 +500,7 @@ TEST_F(NavigationControllerTest, LoadURLWithParams) {
NavigationController::LoadURLParams load_params(GURL("http://foo"));
load_params.referrer =
- Referrer(GURL("http://referrer"), WebKit::WebReferrerPolicyDefault);
+ Referrer(GURL("http://referrer"), blink::WebReferrerPolicyDefault);
load_params.transition_type = PAGE_TRANSITION_GENERATED;
load_params.extra_headers = "content-type: text/plain";
load_params.load_type = NavigationController::LOAD_TYPE_DEFAULT;
@@ -583,8 +581,8 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage) {
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- ASSERT_TRUE(controller.GetActiveEntry());
- const base::Time timestamp = controller.GetActiveEntry()->GetTimestamp();
+ ASSERT_TRUE(controller.GetVisibleEntry());
+ const base::Time timestamp = controller.GetVisibleEntry()->GetTimestamp();
EXPECT_FALSE(timestamp.is_null());
controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
@@ -599,7 +597,7 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage) {
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
EXPECT_TRUE(controller.GetLastCommittedEntry());
EXPECT_FALSE(controller.GetPendingEntry());
- ASSERT_TRUE(controller.GetActiveEntry());
+ ASSERT_TRUE(controller.GetVisibleEntry());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
@@ -607,7 +605,43 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage) {
//
// TODO(akalin): Change this EXPECT_GE (and other similar ones) to
// EXPECT_GT once we guarantee that timestamps are unique.
- EXPECT_GE(controller.GetActiveEntry()->GetTimestamp(), timestamp);
+ EXPECT_GE(controller.GetVisibleEntry()->GetTimestamp(), timestamp);
+}
+
+// Load the same page twice, once as a GET and once as a POST.
+// We should update the post state on the NavigationEntry.
+TEST_F(NavigationControllerTest, LoadURL_SamePage_DifferentMethod) {
+ NavigationControllerImpl& controller = controller_impl();
+ TestNotificationTracker notifications;
+ RegisterForAllNavNotifications(&notifications, &controller);
+
+ const GURL url1("http://foo1");
+
+ controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ ViewHostMsg_FrameNavigate_Params params;
+ params.page_id = 0;
+ params.url = url1;
+ params.transition = PAGE_TRANSITION_TYPED;
+ params.is_post = true;
+ params.post_id = 123;
+ params.page_state = PageState::CreateForTesting(url1, false, 0, 0);
+ test_rvh()->SendNavigateWithParams(&params);
+
+ // The post data should be visible.
+ NavigationEntry* entry = controller.GetVisibleEntry();
+ ASSERT_TRUE(entry);
+ EXPECT_TRUE(entry->GetHasPostData());
+ EXPECT_EQ(entry->GetPostID(), 123);
+
+ controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ test_rvh()->SendNavigate(0, url1);
+
+ // We should not have produced a new session history entry.
+ ASSERT_EQ(controller.GetVisibleEntry(), entry);
+
+ // The post data should have been cleared due to the GET.
+ EXPECT_FALSE(entry->GetHasPostData());
+ EXPECT_EQ(entry->GetPostID(), 0);
}
// Tests loading a URL but discarding it before the load commits.
@@ -625,8 +659,8 @@ TEST_F(NavigationControllerTest, LoadURL_Discarded) {
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- ASSERT_TRUE(controller.GetActiveEntry());
- const base::Time timestamp = controller.GetActiveEntry()->GetTimestamp();
+ ASSERT_TRUE(controller.GetVisibleEntry());
+ const base::Time timestamp = controller.GetVisibleEntry()->GetTimestamp();
EXPECT_FALSE(timestamp.is_null());
controller.LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
@@ -639,12 +673,12 @@ TEST_F(NavigationControllerTest, LoadURL_Discarded) {
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
EXPECT_TRUE(controller.GetLastCommittedEntry());
EXPECT_FALSE(controller.GetPendingEntry());
- ASSERT_TRUE(controller.GetActiveEntry());
+ ASSERT_TRUE(controller.GetVisibleEntry());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
// Timestamp should not have changed.
- EXPECT_EQ(timestamp, controller.GetActiveEntry()->GetTimestamp());
+ EXPECT_EQ(timestamp, controller.GetVisibleEntry()->GetTimestamp());
}
// Tests navigations that come in unrequested. This happens when the user
@@ -672,7 +706,7 @@ TEST_F(NavigationControllerTest, LoadURL_NoPending) {
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
- EXPECT_EQ(kNewURL, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(kNewURL, controller.GetVisibleEntry()->GetURL());
}
// Tests navigating to a new URL when there is a new pending navigation that is
@@ -710,7 +744,7 @@ TEST_F(NavigationControllerTest, LoadURL_NewPending) {
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
- EXPECT_EQ(kNewURL, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(kNewURL, controller.GetVisibleEntry()->GetURL());
}
// Tests navigating to a new URL when there is a pending back/forward
@@ -754,7 +788,7 @@ TEST_F(NavigationControllerTest, LoadURL_ExistingPending) {
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
- EXPECT_EQ(kNewURL, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(kNewURL, controller.GetVisibleEntry()->GetURL());
}
// Tests navigating to a new URL when there is a pending back/forward
@@ -807,7 +841,7 @@ TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
- EXPECT_EQ(kNewURL, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(kNewURL, controller.GetVisibleEntry()->GetURL());
EXPECT_EQ(0, NavigationEntryImpl::FromNavigationEntry(
controller.GetLastCommittedEntry())->bindings());
}
@@ -852,7 +886,7 @@ TEST_F(NavigationControllerTest, LoadURL_BackPreemptsPending) {
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
- EXPECT_EQ(kExistingURL1, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(kExistingURL1, controller.GetVisibleEntry()->GetURL());
}
// Tests an ignored navigation when there is a pending new navigation.
@@ -924,7 +958,7 @@ TEST_F(NavigationControllerTest, LoadURL_AbortDoesntCancelPending) {
params.frame_id = 1;
params.is_main_frame = true;
params.error_code = net::ERR_ABORTED;
- params.error_description = string16();
+ params.error_description = base::string16();
params.url = kNewURL;
params.showing_repost_interstitial = false;
test_rvh()->OnMessageReceived(
@@ -1002,7 +1036,7 @@ TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) {
params.frame_id = 1;
params.is_main_frame = true;
params.error_code = net::ERR_ABORTED;
- params.error_description = string16();
+ params.error_description = base::string16();
params.url = kRedirectURL;
params.showing_repost_interstitial = false;
test_rvh()->OnMessageReceived(
@@ -1090,12 +1124,12 @@ TEST_F(NavigationControllerTest, Reload) {
test_rvh()->SendNavigate(0, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- ASSERT_TRUE(controller.GetActiveEntry());
- controller.GetActiveEntry()->SetTitle(ASCIIToUTF16("Title"));
+ ASSERT_TRUE(controller.GetVisibleEntry());
+ controller.GetVisibleEntry()->SetTitle(ASCIIToUTF16("Title"));
controller.Reload(true);
EXPECT_EQ(0U, notifications.size());
- const base::Time timestamp = controller.GetActiveEntry()->GetTimestamp();
+ const base::Time timestamp = controller.GetVisibleEntry()->GetTimestamp();
EXPECT_FALSE(timestamp.is_null());
// The reload is pending.
@@ -1109,7 +1143,7 @@ TEST_F(NavigationControllerTest, Reload) {
// Make sure the title has been cleared (will be redrawn just after reload).
// Avoids a stale cached title when the new page being reloaded has no title.
// See http://crbug.com/96041.
- EXPECT_TRUE(controller.GetActiveEntry()->GetTitle().empty());
+ EXPECT_TRUE(controller.GetVisibleEntry()->GetTitle().empty());
test_rvh()->SendNavigate(0, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
@@ -1125,8 +1159,8 @@ TEST_F(NavigationControllerTest, Reload) {
EXPECT_FALSE(controller.CanGoForward());
// The timestamp should have been updated.
- ASSERT_TRUE(controller.GetActiveEntry());
- EXPECT_GE(controller.GetActiveEntry()->GetTimestamp(), timestamp);
+ ASSERT_TRUE(controller.GetVisibleEntry());
+ EXPECT_GE(controller.GetVisibleEntry()->GetTimestamp(), timestamp);
}
// Tests what happens when a reload navigation produces a new page.
@@ -1160,31 +1194,42 @@ TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) {
EXPECT_FALSE(controller.CanGoForward());
}
-class TestNavigationObserver : public RenderViewHostObserver {
- public:
- explicit TestNavigationObserver(RenderViewHost* render_view_host)
- : RenderViewHostObserver(render_view_host) {
- }
+// This test ensures that when a guest renderer reloads, the reload goes through
+// without ending up in the "we have a wrong process for the URL" branch in
+// NavigationControllerImpl::ReloadInternal.
+TEST_F(NavigationControllerTest, ReloadWithGuest) {
+ NavigationControllerImpl& controller = controller_impl();
- const GURL& navigated_url() const {
- return navigated_url_;
- }
+ const GURL url1("http://foo1");
+ controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ test_rvh()->SendNavigate(0, url1);
+ ASSERT_TRUE(controller.GetVisibleEntry());
- protected:
- virtual void Navigate(const GURL& url) OVERRIDE {
- navigated_url_ = url;
- }
+ // Make the entry believe its RenderProcessHost is a guest.
+ NavigationEntryImpl* entry1 =
+ NavigationEntryImpl::FromNavigationEntry(controller.GetVisibleEntry());
+ reinterpret_cast<MockRenderProcessHost*>(
+ entry1->site_instance()->GetProcess())->SetIsGuest(true);
- private:
- GURL navigated_url_;
-};
+ // And reload.
+ controller.Reload(true);
+
+ // The reload is pending. Check that the NavigationEntry didn't get replaced
+ // because of having the wrong process.
+ EXPECT_EQ(controller.GetEntryCount(), 1);
+ EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 0);
+ EXPECT_EQ(controller.GetPendingEntryIndex(), 0);
+
+ NavigationEntryImpl* entry2 =
+ NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry());
+ EXPECT_EQ(entry1, entry2);
+}
#if !defined(OS_ANDROID) // http://crbug.com/157428
TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
NavigationControllerImpl& controller = controller_impl();
TestNotificationTracker notifications;
RegisterForAllNavNotifications(&notifications, &controller);
- TestNavigationObserver observer(test_rvh());
const GURL original_url("http://foo1");
const GURL final_url("http://foo2");
@@ -1199,16 +1244,17 @@ TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
// The NavigationEntry should save both the original URL and the final
// redirected URL.
- EXPECT_EQ(original_url, controller.GetActiveEntry()->GetOriginalRequestURL());
- EXPECT_EQ(final_url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(
+ original_url, controller.GetVisibleEntry()->GetOriginalRequestURL());
+ EXPECT_EQ(final_url, controller.GetVisibleEntry()->GetURL());
// Reload using the original URL.
- controller.GetActiveEntry()->SetTitle(ASCIIToUTF16("Title"));
+ controller.GetVisibleEntry()->SetTitle(ASCIIToUTF16("Title"));
controller.ReloadOriginalRequestURL(false);
EXPECT_EQ(0U, notifications.size());
// The reload is pending. The request should point to the original URL.
- EXPECT_EQ(original_url, observer.navigated_url());
+ EXPECT_EQ(original_url, navigated_url());
EXPECT_EQ(controller.GetEntryCount(), 1);
EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 0);
EXPECT_EQ(controller.GetPendingEntryIndex(), 0);
@@ -1220,7 +1266,7 @@ TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
// Make sure the title has been cleared (will be redrawn just after reload).
// Avoids a stale cached title when the new page being reloaded has no title.
// See http://crbug.com/96041.
- EXPECT_TRUE(controller.GetActiveEntry()->GetTitle().empty());
+ EXPECT_TRUE(controller.GetVisibleEntry()->GetTitle().empty());
// Send that the navigation has proceeded; say it got redirected again.
test_rvh()->SendNavigate(0, final_url);
@@ -1239,6 +1285,56 @@ TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
#endif // !defined(OS_ANDROID)
+// Test that certain non-persisted NavigationEntryImpl values get reset after
+// commit.
+TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
+ NavigationControllerImpl& controller = controller_impl();
+ const GURL url1("http://foo1");
+ controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+
+ // Set up some sample values.
+ const unsigned char* raw_data =
+ reinterpret_cast<const unsigned char*>("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);
+ std::vector<GURL> redirects;
+ redirects.push_back(GURL("http://foo2"));
+
+ // Set non-persisted values on the pending entry.
+ NavigationEntryImpl* pending_entry =
+ NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry());
+ pending_entry->SetBrowserInitiatedPostData(post_data.get());
+ 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_redirect_chain(redirects);
+ pending_entry->set_should_clear_history_list(true);
+ EXPECT_EQ(post_data.get(), pending_entry->GetBrowserInitiatedPostData());
+ EXPECT_TRUE(pending_entry->is_renderer_initiated());
+ EXPECT_EQ(transfer_id, pending_entry->transferred_global_request_id());
+ EXPECT_TRUE(pending_entry->should_replace_entry());
+ EXPECT_EQ(1U, pending_entry->redirect_chain().size());
+ EXPECT_TRUE(pending_entry->should_clear_history_list());
+
+ test_rvh()->SendNavigate(0, url1);
+
+ // Certain values that are only used for pending entries get reset after
+ // commit.
+ NavigationEntryImpl* committed_entry =
+ NavigationEntryImpl::FromNavigationEntry(
+ controller.GetLastCommittedEntry());
+ EXPECT_FALSE(committed_entry->GetBrowserInitiatedPostData());
+ EXPECT_FALSE(committed_entry->is_renderer_initiated());
+ EXPECT_EQ(GlobalRequestID(-1, -1),
+ committed_entry->transferred_global_request_id());
+ EXPECT_FALSE(committed_entry->should_replace_entry());
+ EXPECT_EQ(0U, committed_entry->redirect_chain().size());
+ EXPECT_FALSE(committed_entry->should_clear_history_list());
+}
+
// Tests what happens when we navigate back successfully
TEST_F(NavigationControllerTest, Back) {
NavigationControllerImpl& controller = controller_impl();
@@ -1561,7 +1657,7 @@ TEST_F(NavigationControllerTest, Redirect) {
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
- EXPECT_EQ(url1, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
ViewHostMsg_FrameNavigate_Params params;
params.page_id = 0;
@@ -1587,7 +1683,7 @@ TEST_F(NavigationControllerTest, Redirect) {
EXPECT_TRUE(controller.GetLastCommittedEntry());
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
EXPECT_FALSE(controller.GetPendingEntry());
- EXPECT_EQ(url2, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
@@ -1606,7 +1702,7 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
// First request as POST
controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- controller.GetActiveEntry()->SetHasPostData(true);
+ controller.GetVisibleEntry()->SetHasPostData(true);
EXPECT_EQ(0U, notifications.size());
test_rvh()->SendNavigate(0, url2);
@@ -1618,7 +1714,7 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
- EXPECT_EQ(url1, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
ViewHostMsg_FrameNavigate_Params params;
params.page_id = 0;
@@ -1644,8 +1740,8 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
EXPECT_TRUE(controller.GetLastCommittedEntry());
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
EXPECT_FALSE(controller.GetPendingEntry());
- EXPECT_EQ(url2, controller.GetActiveEntry()->GetURL());
- EXPECT_FALSE(controller.GetActiveEntry()->GetHasPostData());
+ EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
+ EXPECT_FALSE(controller.GetVisibleEntry()->GetHasPostData());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
@@ -1665,7 +1761,7 @@ TEST_F(NavigationControllerTest, ImmediateRedirect) {
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
- EXPECT_EQ(url1, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
ViewHostMsg_FrameNavigate_Params params;
params.page_id = 0;
@@ -1691,7 +1787,7 @@ TEST_F(NavigationControllerTest, ImmediateRedirect) {
EXPECT_TRUE(controller.GetLastCommittedEntry());
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
EXPECT_FALSE(controller.GetPendingEntry());
- EXPECT_EQ(url2, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
@@ -1944,7 +2040,7 @@ TEST_F(NavigationControllerTest, InPage) {
EXPECT_TRUE(details.is_in_page);
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(0, controller.GetCurrentEntryIndex());
- EXPECT_EQ(back_params.url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(back_params.url, controller.GetVisibleEntry()->GetURL());
// Go forward
ViewHostMsg_FrameNavigate_Params forward_params(params);
@@ -1958,7 +2054,7 @@ TEST_F(NavigationControllerTest, InPage) {
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetCurrentEntryIndex());
EXPECT_EQ(forward_params.url,
- controller.GetActiveEntry()->GetURL());
+ controller.GetVisibleEntry()->GetURL());
// Now go back and forward again. This is to work around a bug where we would
// compare the incoming URL with the last committed entry rather than the
@@ -1969,7 +2065,7 @@ TEST_F(NavigationControllerTest, InPage) {
controller.GoForward();
EXPECT_TRUE(controller.RendererDidNavigate(forward_params, &details));
EXPECT_EQ(forward_params.url,
- controller.GetActiveEntry()->GetURL());
+ controller.GetVisibleEntry()->GetURL());
// Finally, navigate to an unrelated URL to make sure in_page is not sticky.
const GURL url3("http://bar");
@@ -2096,7 +2192,7 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
test_rvh()->SendNavigate(1, url);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_EQ(url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url, controller.GetVisibleEntry()->GetURL());
}
}
@@ -2314,7 +2410,7 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {
fail_load_params.frame_id = 1;
fail_load_params.is_main_frame = true;
fail_load_params.error_code = net::ERR_ABORTED;
- fail_load_params.error_description = string16();
+ fail_load_params.error_description = base::string16();
fail_load_params.url = url;
fail_load_params.showing_repost_interstitial = false;
rvh->OnMessageReceived(
@@ -2463,7 +2559,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
EXPECT_EQ(0U, notifications.size());
// Check our state.
- EXPECT_EQ(transient_url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
EXPECT_EQ(controller.GetEntryCount(), 3);
EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 1);
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
@@ -2479,17 +2575,17 @@ TEST_F(NavigationControllerTest, TransientEntry) {
test_rvh()->SendNavigate(2, url2);
// We should have navigated, transient entry should be gone.
- EXPECT_EQ(url2, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
EXPECT_EQ(controller.GetEntryCount(), 3);
// Add a transient again, then navigate with no pending entry this time.
transient_entry = new NavigationEntryImpl;
transient_entry->SetURL(transient_url);
controller.SetTransientEntry(transient_entry);
- EXPECT_EQ(transient_url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
test_rvh()->SendNavigate(3, url3);
// Transient entry should be gone.
- EXPECT_EQ(url3, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL());
EXPECT_EQ(controller.GetEntryCount(), 4);
// Initiate a navigation, add a transient then commit navigation.
@@ -2498,21 +2594,21 @@ TEST_F(NavigationControllerTest, TransientEntry) {
transient_entry = new NavigationEntryImpl;
transient_entry->SetURL(transient_url);
controller.SetTransientEntry(transient_entry);
- EXPECT_EQ(transient_url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
test_rvh()->SendNavigate(4, url4);
- EXPECT_EQ(url4, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url4, controller.GetVisibleEntry()->GetURL());
EXPECT_EQ(controller.GetEntryCount(), 5);
// Add a transient and go back. This should simply remove the transient.
transient_entry = new NavigationEntryImpl;
transient_entry->SetURL(transient_url);
controller.SetTransientEntry(transient_entry);
- EXPECT_EQ(transient_url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
EXPECT_TRUE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
controller.GoBack();
// Transient entry should be gone.
- EXPECT_EQ(url4, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url4, controller.GetVisibleEntry()->GetURL());
EXPECT_EQ(controller.GetEntryCount(), 5);
test_rvh()->SendNavigate(3, url3);
@@ -2520,10 +2616,11 @@ TEST_F(NavigationControllerTest, TransientEntry) {
transient_entry = new NavigationEntryImpl;
transient_entry->SetURL(transient_url);
controller.SetTransientEntry(transient_entry);
- EXPECT_EQ(transient_url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
controller.GoToIndex(1);
// The navigation should have been initiated, transient entry should be gone.
- EXPECT_EQ(url1, controller.GetActiveEntry()->GetURL());
+ EXPECT_FALSE(controller.GetTransientEntry());
+ EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
// Visible entry does not update for history navigations until commit.
EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL());
test_rvh()->SendNavigate(1, url1);
@@ -2533,12 +2630,12 @@ TEST_F(NavigationControllerTest, TransientEntry) {
transient_entry = new NavigationEntryImpl;
transient_entry->SetURL(transient_url);
controller.SetTransientEntry(transient_entry);
- EXPECT_EQ(transient_url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
controller.GoToIndex(3);
// The navigation should have been initiated, transient entry should be gone.
// Because of the transient entry that is removed, going to index 3 makes us
// land on url2 (which is visible after the commit).
- EXPECT_EQ(url2, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
test_rvh()->SendNavigate(2, url2);
EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
@@ -2547,11 +2644,12 @@ TEST_F(NavigationControllerTest, TransientEntry) {
transient_entry = new NavigationEntryImpl;
transient_entry->SetURL(transient_url);
controller.SetTransientEntry(transient_entry);
- EXPECT_EQ(transient_url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
EXPECT_TRUE(controller.CanGoForward());
controller.GoForward();
// We should have navigated, transient entry should be gone.
- EXPECT_EQ(url3, controller.GetActiveEntry()->GetURL());
+ EXPECT_FALSE(controller.GetTransientEntry());
+ EXPECT_EQ(url3, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
test_rvh()->SendNavigate(3, url3);
EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL());
@@ -2560,10 +2658,11 @@ TEST_F(NavigationControllerTest, TransientEntry) {
transient_entry = new NavigationEntryImpl;
transient_entry->SetURL(transient_url);
controller.SetTransientEntry(transient_entry);
- EXPECT_EQ(transient_url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
test_rvh()->SendNavigate(3, url3_ref);
// Transient entry should be gone.
- EXPECT_EQ(url3_ref, controller.GetActiveEntry()->GetURL());
+ EXPECT_FALSE(controller.GetTransientEntry());
+ EXPECT_EQ(url3_ref, controller.GetVisibleEntry()->GetURL());
// Ensure the URLs are correct.
EXPECT_EQ(controller.GetEntryCount(), 5);
@@ -2593,7 +2692,7 @@ TEST_F(NavigationControllerTest, ReloadTransient) {
transient_entry->SetURL(transient_url);
controller.SetTransientEntry(transient_entry);
EXPECT_TRUE(controller.GetTransientEntry());
- EXPECT_EQ(transient_url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
// The page is reloaded, which should remove the pending entry for |url1| and
// the transient entry for |transient_url|, and start a navigation to
@@ -2601,7 +2700,7 @@ TEST_F(NavigationControllerTest, ReloadTransient) {
controller.Reload(true);
EXPECT_FALSE(controller.GetTransientEntry());
EXPECT_TRUE(controller.GetPendingEntry());
- EXPECT_EQ(transient_url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
ASSERT_EQ(controller.GetEntryCount(), 1);
EXPECT_EQ(controller.GetEntryAtIndex(0)->GetURL(), url0);
@@ -2617,6 +2716,8 @@ TEST_F(NavigationControllerTest, ReloadTransient) {
// See http://crbug.com/266922.
TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
NavigationControllerImpl& controller = controller_impl();
+ Navigator* navigator =
+ contents()->GetFrameTree()->root()->navigator();
const GURL url1("nonexistent:12121");
const GURL url1_fixed("http://nonexistent:12121/");
@@ -2624,8 +2725,7 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
// We create pending entries for renderer-initiated navigations so that we
// can show them in new tabs when it is safe.
- contents()->DidStartProvisionalLoadForFrame(
- test_rvh(), 1, -1, true, url1);
+ navigator->DidStartProvisionalLoad(main_test_rfh(), 1, -1, true, url1);
// Simulate what happens if a BrowserURLHandler rewrites the URL, causing
// the virtual URL to differ from the URL.
@@ -2639,8 +2739,7 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
is_renderer_initiated());
// If the user clicks another link, we should replace the pending entry.
- contents()->DidStartProvisionalLoadForFrame(
- test_rvh(), 1, -1, true, url2);
+ navigator->DidStartProvisionalLoad(main_test_rfh(), 1, -1, true, url2);
EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url2, controller.GetPendingEntry()->GetVirtualURL());
@@ -2650,24 +2749,24 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetVirtualURL());
// We should not replace the pending entry for an error URL.
- contents()->DidStartProvisionalLoadForFrame(
- test_rvh(), 1, -1, true, url1);
+ navigator->DidStartProvisionalLoad(main_test_rfh(), 1, -1, true, url1);
EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
- contents()->DidStartProvisionalLoadForFrame(
- test_rvh(), 1, -1, true, GURL(kUnreachableWebDataURL));
+ navigator->DidStartProvisionalLoad(
+ main_test_rfh(), 1, -1, true, GURL(kUnreachableWebDataURL));
EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
// We should remember if the pending entry will replace the current one.
// http://crbug.com/308444.
- contents()->DidStartProvisionalLoadForFrame(
- test_rvh(), 1, -1, true, url1);
+ navigator->DidStartProvisionalLoad(main_test_rfh(), 1, -1, true, url1);
NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
set_should_replace_entry(true);
- contents()->DidStartProvisionalLoadForFrame(
- test_rvh(), 1, -1, true, url2);
+ navigator->DidStartProvisionalLoad(main_test_rfh(), 1, -1, true, url2);
EXPECT_TRUE(
NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
should_replace_entry());
+ // TODO(nasko): Until OnNavigate is moved to RenderFrameHost, we need
+ // to go through the RenderViewHost. The TestRenderViewHost routes navigations
+ // to the main frame.
test_rvh()->SendNavigate(0, url2);
EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
}
@@ -2683,29 +2782,29 @@ TEST_F(NavigationControllerTest, DontShowRendererURLUntilCommit) {
const GURL url0("http://foo/0");
const GURL url1("http://foo/1");
- // For typed navigations (browser-initiated), both active and visible entries
+ // For typed navigations (browser-initiated), both pending and visible entries
// should update before commit.
controller.LoadURL(url0, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- EXPECT_EQ(url0, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url0, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url0, controller.GetVisibleEntry()->GetURL());
test_rvh()->SendNavigate(0, url0);
- // For link clicks (renderer-initiated navigations), the active entry should
+ // For link clicks (renderer-initiated navigations), the pending entry should
// update before commit but the visible should not.
NavigationController::LoadURLParams load_url_params(url1);
load_url_params.is_renderer_initiated = true;
controller.LoadURLWithParams(load_url_params);
- EXPECT_EQ(url1, controller.GetActiveEntry()->GetURL());
EXPECT_EQ(url0, controller.GetVisibleEntry()->GetURL());
+ EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
EXPECT_TRUE(
NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
is_renderer_initiated());
- // After commit, both should be updated, and we should no longer treat the
- // entry as renderer-initiated.
+ // After commit, both visible should be updated, there should be no pending
+ // entry, and we should no longer treat the entry as renderer-initiated.
test_rvh()->SendNavigate(1, url1);
- EXPECT_EQ(url1, controller.GetActiveEntry()->GetURL());
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
+ EXPECT_FALSE(controller.GetPendingEntry());
EXPECT_FALSE(
NavigationEntryImpl::FromNavigationEntry(
controller.GetLastCommittedEntry())->is_renderer_initiated());
@@ -2731,8 +2830,8 @@ TEST_F(NavigationControllerTest, ShowRendererURLInNewTabUntilModified) {
load_url_params.transition_type = PAGE_TRANSITION_LINK;
load_url_params.is_renderer_initiated = true;
controller.LoadURLWithParams(load_url_params);
- EXPECT_EQ(url, controller.GetActiveEntry()->GetURL());
EXPECT_EQ(url, controller.GetVisibleEntry()->GetURL());
+ EXPECT_EQ(url, controller.GetPendingEntry()->GetURL());
EXPECT_TRUE(
NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
is_renderer_initiated());
@@ -2748,7 +2847,7 @@ TEST_F(NavigationControllerTest, ShowRendererURLInNewTabUntilModified) {
ViewHostMsg_DidAccessInitialDocument(0));
EXPECT_TRUE(test_rvh()->has_accessed_initial_document());
EXPECT_FALSE(controller.GetVisibleEntry());
- EXPECT_EQ(url, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url, controller.GetPendingEntry()->GetURL());
notifications.Reset();
}
@@ -2768,7 +2867,6 @@ TEST_F(NavigationControllerTest, DontShowRendererURLInNewTabAfterCommit) {
load_url_params.transition_type = PAGE_TRANSITION_LINK;
load_url_params.is_renderer_initiated = true;
controller.LoadURLWithParams(load_url_params);
- EXPECT_EQ(url1, controller.GetActiveEntry()->GetURL());
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
EXPECT_TRUE(
NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
@@ -2867,10 +2965,10 @@ TEST_F(NavigationControllerTest, CloneAndGoBack) {
NavigationControllerImpl& controller = controller_impl();
const GURL url1("http://foo1");
const GURL url2("http://foo2");
- const string16 title(ASCIIToUTF16("Title"));
+ const base::string16 title(ASCIIToUTF16("Title"));
NavigateAndCommit(url1);
- controller.GetActiveEntry()->SetTitle(title);
+ controller.GetVisibleEntry()->SetTitle(title);
NavigateAndCommit(url2);
scoped_ptr<WebContents> clone(controller.GetWebContents()->Clone());
@@ -2892,10 +2990,10 @@ TEST_F(NavigationControllerTest, CloneAndReload) {
NavigationControllerImpl& controller = controller_impl();
const GURL url1("http://foo1");
const GURL url2("http://foo2");
- const string16 title(ASCIIToUTF16("Title"));
+ const base::string16 title(ASCIIToUTF16("Title"));
NavigateAndCommit(url1);
- controller.GetActiveEntry()->SetTitle(title);
+ controller.GetVisibleEntry()->SetTitle(title);
NavigateAndCommit(url2);
scoped_ptr<WebContents> clone(controller.GetWebContents()->Clone());
@@ -2978,7 +3076,7 @@ TEST_F(NavigationControllerTest, SubframeWhilePending) {
EXPECT_EQ(url1, controller.GetLastCommittedEntry()->GetURL());
// The active entry should be unchanged by the subframe load.
- EXPECT_EQ(url2, controller.GetActiveEntry()->GetURL());
+ EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL());
}
// Test CopyStateFrom with 2 urls, the first selected and nothing in the target.
@@ -3062,7 +3160,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune) {
other_contents->ExpectSetHistoryLengthAndPrune(
GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(0)), 2,
other_controller.GetEntryAtIndex(0)->GetPageID());
- other_controller.CopyStateFromAndPrune(&controller);
+ other_controller.CopyStateFromAndPrune(&controller, false);
// other_controller should now contain the 3 urls: url1, url2 and url3.
@@ -3077,10 +3175,12 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune) {
EXPECT_EQ(1, other_controller.GetEntryAtIndex(1)->GetPageID());
EXPECT_EQ(0, other_controller.GetEntryAtIndex(2)->GetPageID());
- // A new SiteInstance should be used for the new tab.
+ // A new SiteInstance in a different BrowsingInstance should be used for the
+ // new tab.
SiteInstance* instance3 =
GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(2));
EXPECT_NE(instance3, instance1);
+ EXPECT_FALSE(instance3->IsRelatedSiteInstance(instance1));
// The max page ID map should be copied over and updated with the max page ID
// from the current tab.
@@ -3108,7 +3208,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune2) {
other_contents->ExpectSetHistoryLengthAndPrune(
GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(0)), 1,
other_controller.GetEntryAtIndex(0)->GetPageID());
- other_controller.CopyStateFromAndPrune(&controller);
+ other_controller.CopyStateFromAndPrune(&controller, false);
// other_controller should now contain: url1, url3
@@ -3146,7 +3246,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune3) {
other_contents->ExpectSetHistoryLengthAndPrune(
GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(1)), 2,
other_controller.GetEntryAtIndex(0)->GetPageID());
- other_controller.CopyStateFromAndPrune(&controller);
+ other_controller.CopyStateFromAndPrune(&controller, false);
// other_controller should now contain: url1, url2, url4
@@ -3186,7 +3286,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneNotLast) {
other_contents->ExpectSetHistoryLengthAndPrune(
GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(0)), 2,
other_controller.GetEntryAtIndex(0)->GetPageID());
- other_controller.CopyStateFromAndPrune(&controller);
+ other_controller.CopyStateFromAndPrune(&controller, false);
// other_controller should now contain: url1, url2, url3
@@ -3227,7 +3327,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneTargetPending) {
other_contents->ExpectSetHistoryLengthAndPrune(
GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(0)), 1,
other_controller.GetEntryAtIndex(0)->GetPageID());
- other_controller.CopyStateFromAndPrune(&controller);
+ other_controller.CopyStateFromAndPrune(&controller, false);
// other_controller should now contain url1, url3, and a pending entry
// for url4.
@@ -3274,7 +3374,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneTargetPending2) {
other_contents->ExpectSetHistoryLengthAndPrune(
GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(0)), 1,
other_controller.GetEntryAtIndex(0)->GetPageID());
- other_controller.CopyStateFromAndPrune(&controller);
+ other_controller.CopyStateFromAndPrune(&controller, false);
// other_controller should now contain url1, url2a, and a pending entry
// for url2b.
@@ -3318,7 +3418,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneSourcePending) {
other_contents->ExpectSetHistoryLengthAndPrune(
GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(0)), 2,
other_controller.GetEntryAtIndex(0)->GetPageID());
- other_controller.CopyStateFromAndPrune(&controller);
+ other_controller.CopyStateFromAndPrune(&controller, false);
// other_controller should now contain: url1, url2, url3
@@ -3365,7 +3465,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneMaxEntries) {
other_contents->ExpectSetHistoryLengthAndPrune(
GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(0)), 2,
other_controller.GetEntryAtIndex(0)->GetPageID());
- other_controller.CopyStateFromAndPrune(&controller);
+ other_controller.CopyStateFromAndPrune(&controller, false);
// We should have received a pruned notification.
EXPECT_EQ(1, listener.notification_count_);
@@ -3388,6 +3488,109 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneMaxEntries) {
NavigationControllerImpl::set_max_entry_count_for_testing(original_count);
}
+// Tests CopyStateFromAndPrune with 2 urls in source, 1 in dest, with
+// replace_entry set to true.
+TEST_F(NavigationControllerTest, CopyStateFromAndPruneReplaceEntry) {
+ NavigationControllerImpl& controller = controller_impl();
+ const GURL url1("http://foo/1");
+ const GURL url2("http://foo/2");
+ const GURL url3("http://foo/3");
+
+ NavigateAndCommit(url1);
+ NavigateAndCommit(url2);
+
+ // First two entries should have the same SiteInstance.
+ SiteInstance* instance1 =
+ GetSiteInstanceFromEntry(controller.GetEntryAtIndex(0));
+ SiteInstance* instance2 =
+ GetSiteInstanceFromEntry(controller.GetEntryAtIndex(1));
+ EXPECT_EQ(instance1, instance2);
+ EXPECT_EQ(0, controller.GetEntryAtIndex(0)->GetPageID());
+ EXPECT_EQ(1, controller.GetEntryAtIndex(1)->GetPageID());
+ EXPECT_EQ(1, contents()->GetMaxPageIDForSiteInstance(instance1));
+
+ scoped_ptr<TestWebContents> other_contents(
+ static_cast<TestWebContents*>(CreateTestWebContents()));
+ NavigationControllerImpl& other_controller = other_contents->GetController();
+ other_contents->NavigateAndCommit(url3);
+ other_contents->ExpectSetHistoryLengthAndPrune(
+ GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(0)), 1,
+ other_controller.GetEntryAtIndex(0)->GetPageID());
+ other_controller.CopyStateFromAndPrune(&controller, true);
+
+ // other_controller should now contain the 2 urls: url1 and url3.
+
+ ASSERT_EQ(2, other_controller.GetEntryCount());
+
+ ASSERT_EQ(1, other_controller.GetCurrentEntryIndex());
+
+ EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->GetURL());
+ EXPECT_EQ(url3, other_controller.GetEntryAtIndex(1)->GetURL());
+ EXPECT_EQ(0, other_controller.GetEntryAtIndex(0)->GetPageID());
+ EXPECT_EQ(0, other_controller.GetEntryAtIndex(1)->GetPageID());
+
+ // A new SiteInstance in a different BrowsingInstance should be used for the
+ // new tab.
+ SiteInstance* instance3 =
+ GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(1));
+ EXPECT_NE(instance3, instance1);
+ EXPECT_FALSE(instance3->IsRelatedSiteInstance(instance1));
+
+ // The max page ID map should be copied over and updated with the max page ID
+ // from the current tab.
+ EXPECT_EQ(1, other_contents->GetMaxPageIDForSiteInstance(instance1));
+ EXPECT_EQ(0, other_contents->GetMaxPageIDForSiteInstance(instance3));
+}
+
+// Tests CopyStateFromAndPrune with 3 urls in source, 1 in dest, when the max
+// entry count is 3 and replace_entry is true. We should not prune entries.
+TEST_F(NavigationControllerTest, CopyStateFromAndPruneMaxEntriesReplaceEntry) {
+ NavigationControllerImpl& controller = controller_impl();
+ size_t original_count = NavigationControllerImpl::max_entry_count();
+ const int kMaxEntryCount = 3;
+
+ NavigationControllerImpl::set_max_entry_count_for_testing(kMaxEntryCount);
+
+ const GURL url1("http://foo/1");
+ const GURL url2("http://foo/2");
+ const GURL url3("http://foo/3");
+ const GURL url4("http://foo/4");
+
+ // Create a PrunedListener to observe prune notifications.
+ PrunedListener listener(&controller);
+
+ NavigateAndCommit(url1);
+ NavigateAndCommit(url2);
+ NavigateAndCommit(url3);
+
+ scoped_ptr<TestWebContents> other_contents(
+ static_cast<TestWebContents*>(CreateTestWebContents()));
+ NavigationControllerImpl& other_controller = other_contents->GetController();
+ other_contents->NavigateAndCommit(url4);
+ other_contents->ExpectSetHistoryLengthAndPrune(
+ GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(0)), 2,
+ other_controller.GetEntryAtIndex(0)->GetPageID());
+ other_controller.CopyStateFromAndPrune(&controller, true);
+
+ // We should have received no pruned notification.
+ EXPECT_EQ(0, listener.notification_count_);
+
+ // other_controller should now contain only 3 urls: url1, url2 and url4.
+
+ ASSERT_EQ(3, other_controller.GetEntryCount());
+
+ ASSERT_EQ(2, other_controller.GetCurrentEntryIndex());
+
+ EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->GetURL());
+ EXPECT_EQ(url2, other_controller.GetEntryAtIndex(1)->GetURL());
+ EXPECT_EQ(url4, other_controller.GetEntryAtIndex(2)->GetURL());
+ EXPECT_EQ(0, other_controller.GetEntryAtIndex(0)->GetPageID());
+ EXPECT_EQ(1, other_controller.GetEntryAtIndex(1)->GetPageID());
+ EXPECT_EQ(0, other_controller.GetEntryAtIndex(2)->GetPageID());
+
+ NavigationControllerImpl::set_max_entry_count_for_testing(original_count);
+}
+
// Tests that navigations initiated from the page (with the history object)
// work as expected without navigation entries.
TEST_F(NavigationControllerTest, HistoryNavigate) {
@@ -3437,8 +3640,8 @@ TEST_F(NavigationControllerTest, HistoryNavigate) {
EXPECT_TRUE(message == NULL);
}
-// Test call to PruneAllButVisible for the only entry.
-TEST_F(NavigationControllerTest, PruneAllButVisibleForSingle) {
+// Test call to PruneAllButLastCommitted for the only entry.
+TEST_F(NavigationControllerTest, PruneAllButLastCommittedForSingle) {
NavigationControllerImpl& controller = controller_impl();
const GURL url1("http://foo1");
NavigateAndCommit(url1);
@@ -3447,14 +3650,14 @@ TEST_F(NavigationControllerTest, PruneAllButVisibleForSingle) {
GetSiteInstanceFromEntry(controller.GetEntryAtIndex(0)), 0,
controller.GetEntryAtIndex(0)->GetPageID());
- controller.PruneAllButVisible();
+ controller.PruneAllButLastCommitted();
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_EQ(controller.GetEntryAtIndex(0)->GetURL(), url1);
}
-// Test call to PruneAllButVisible for first entry.
-TEST_F(NavigationControllerTest, PruneAllButVisibleForFirst) {
+// Test call to PruneAllButLastCommitted for first entry.
+TEST_F(NavigationControllerTest, PruneAllButLastCommittedForFirst) {
NavigationControllerImpl& controller = controller_impl();
const GURL url1("http://foo/1");
const GURL url2("http://foo/2");
@@ -3471,14 +3674,14 @@ TEST_F(NavigationControllerTest, PruneAllButVisibleForFirst) {
GetSiteInstanceFromEntry(controller.GetEntryAtIndex(0)), 0,
controller.GetEntryAtIndex(0)->GetPageID());
- controller.PruneAllButVisible();
+ controller.PruneAllButLastCommitted();
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_EQ(controller.GetEntryAtIndex(0)->GetURL(), url1);
}
-// Test call to PruneAllButVisible for intermediate entry.
-TEST_F(NavigationControllerTest, PruneAllButVisibleForIntermediate) {
+// Test call to PruneAllButLastCommitted for intermediate entry.
+TEST_F(NavigationControllerTest, PruneAllButLastCommittedForIntermediate) {
NavigationControllerImpl& controller = controller_impl();
const GURL url1("http://foo/1");
const GURL url2("http://foo/2");
@@ -3494,15 +3697,15 @@ TEST_F(NavigationControllerTest, PruneAllButVisibleForIntermediate) {
GetSiteInstanceFromEntry(controller.GetEntryAtIndex(1)), 0,
controller.GetEntryAtIndex(1)->GetPageID());
- controller.PruneAllButVisible();
+ controller.PruneAllButLastCommitted();
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_EQ(controller.GetEntryAtIndex(0)->GetURL(), url2);
}
-// Test call to PruneAllButVisible for a pending entry that is not yet in the
-// list of entries.
-TEST_F(NavigationControllerTest, PruneAllButVisibleForPendingNotInList) {
+// Test call to PruneAllButLastCommitted for a pending entry that is not yet in
+// the list of entries.
+TEST_F(NavigationControllerTest, PruneAllButLastCommittedForPendingNotInList) {
NavigationControllerImpl& controller = controller_impl();
const GURL url1("http://foo/1");
const GURL url2("http://foo/2");
@@ -3519,7 +3722,7 @@ TEST_F(NavigationControllerTest, PruneAllButVisibleForPendingNotInList) {
contents()->ExpectSetHistoryLengthAndPrune(
NULL, 0, controller.GetPendingEntry()->GetPageID());
- controller.PruneAllButVisible();
+ controller.PruneAllButLastCommitted();
// We should only have the last committed and pending entries at this point,
// and the pending entry should still not be in the entry list.
@@ -3808,185 +4011,7 @@ TEST_F(NavigationControllerTest, ClearHistoryList) {
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
- EXPECT_EQ(url4, controller.GetActiveEntry()->GetURL());
-}
-
-/* TODO(brettw) These test pass on my local machine but fail on the XP buildbot
- (but not Vista) cleaning up the directory after they run.
- This should be fixed.
-
-// NavigationControllerHistoryTest ---------------------------------------------
-
-class NavigationControllerHistoryTest : public NavigationControllerTest {
- public:
- NavigationControllerHistoryTest()
- : url0("http://foo1"),
- url1("http://foo1"),
- url2("http://foo1"),
- profile_manager_(NULL) {
- }
-
- virtual ~NavigationControllerHistoryTest() {
- // Prevent our base class from deleting the profile since profile's
- // lifetime is managed by profile_manager_.
- STLDeleteElements(&windows_);
- }
-
- // testing::Test overrides.
- virtual void SetUp() {
- NavigationControllerTest::SetUp();
-
- // Force the session service to be created.
- SessionService* service = new SessionService(profile());
- SessionServiceFactory::SetForTestProfile(profile(), service);
- service->SetWindowType(window_id, Browser::TYPE_TABBED);
- service->SetWindowBounds(window_id, gfx::Rect(0, 1, 2, 3), false);
- service->SetTabIndexInWindow(window_id,
- controller.session_id(), 0);
- controller.SetWindowID(window_id);
-
- session_helper_.SetService(service);
- }
-
- virtual void TearDown() {
- // Release profile's reference to the session service. Otherwise the file
- // will still be open and we won't be able to delete the directory below.
- session_helper_.ReleaseService(); // profile owns this
- SessionServiceFactory::SetForTestProfile(profile(), NULL);
-
- // Make sure we wait for history to shut down before continuing. The task
- // we add will cause our message loop to quit once it is destroyed.
- HistoryService* history = HistoryServiceFactory::GetForProfiles(
- profile(), Profile::IMPLICIT_ACCESS);
- if (history) {
- history->SetOnBackendDestroyTask(base::MessageLoop::QuitClosure());
- base::MessageLoop::current()->Run();
- }
-
- // Do normal cleanup before deleting the profile directory below.
- NavigationControllerTest::TearDown();
-
- ASSERT_TRUE(base::DeleteFile(test_dir_, true));
- ASSERT_FALSE(base::PathExists(test_dir_));
- }
-
- // Deletes the current profile manager and creates a new one. Indirectly this
- // shuts down the history database and reopens it.
- void ReopenDatabase() {
- session_helper_.SetService(NULL);
- SessionServiceFactory::SetForTestProfile(profile(), NULL);
-
- SessionService* service = new SessionService(profile());
- SessionServiceFactory::SetForTestProfile(profile(), service);
- session_helper_.SetService(service);
- }
-
- void GetLastSession() {
- SessionServiceFactory::GetForProfile(profile())->TabClosed(
- controller.window_id(), controller.session_id(), false);
-
- ReopenDatabase();
- Time close_time;
-
- session_helper_.ReadWindows(&windows_);
- }
-
- CancelableRequestConsumer consumer;
-
- // URLs for testing.
- const GURL url0;
- const GURL url1;
- const GURL url2;
-
- std::vector<SessionWindow*> windows_;
-
- SessionID window_id;
-
- SessionServiceTestHelper session_helper_;
-
- private:
- ProfileManager* profile_manager_;
- base::FilePath test_dir_;
-};
-
-// A basic test case. Navigates to a single url, and make sure the history
-// db matches.
-TEST_F(NavigationControllerHistoryTest, Basic) {
- NavigationControllerImpl& controller = controller_impl();
- controller.LoadURL(url0, GURL(), PAGE_TRANSITION_LINK);
- test_rvh()->SendNavigate(0, url0);
-
- GetLastSession();
-
- session_helper_.AssertSingleWindowWithSingleTab(windows_, 1);
- session_helper_.AssertTabEquals(0, 0, 1, *(windows_[0]->tabs[0]));
- TabNavigation nav1(0, url0, GURL(), string16(),
- webkit_glue::CreateHistoryStateForURL(url0),
- PAGE_TRANSITION_LINK);
- session_helper_.AssertNavigationEquals(nav1,
- windows_[0]->tabs[0]->navigations[0]);
-}
-
-// Navigates to three urls, then goes back and make sure the history database
-// is in sync.
-TEST_F(NavigationControllerHistoryTest, NavigationThenBack) {
- NavigationControllerImpl& controller = controller_impl();
- test_rvh()->SendNavigate(0, url0);
- test_rvh()->SendNavigate(1, url1);
- test_rvh()->SendNavigate(2, url2);
-
- controller.GoBack();
- test_rvh()->SendNavigate(1, url1);
-
- GetLastSession();
-
- session_helper_.AssertSingleWindowWithSingleTab(windows_, 3);
- session_helper_.AssertTabEquals(0, 1, 3, *(windows_[0]->tabs[0]));
-
- TabNavigation nav(0, url0, GURL(), string16(),
- webkit_glue::CreateHistoryStateForURL(url0),
- PAGE_TRANSITION_LINK);
- session_helper_.AssertNavigationEquals(nav,
- windows_[0]->tabs[0]->navigations[0]);
- nav.set_url(url1);
- session_helper_.AssertNavigationEquals(nav,
- windows_[0]->tabs[0]->navigations[1]);
- nav.set_url(url2);
- session_helper_.AssertNavigationEquals(nav,
- windows_[0]->tabs[0]->navigations[2]);
-}
-
-// Navigates to three urls, then goes back twice, then loads a new url.
-TEST_F(NavigationControllerHistoryTest, NavigationPruning) {
- NavigationControllerImpl& controller = controller_impl();
- test_rvh()->SendNavigate(0, url0);
- test_rvh()->SendNavigate(1, url1);
- test_rvh()->SendNavigate(2, url2);
-
- controller.GoBack();
- test_rvh()->SendNavigate(1, url1);
-
- controller.GoBack();
- test_rvh()->SendNavigate(0, url0);
-
- test_rvh()->SendNavigate(3, url2);
-
- // Now have url0, and url2.
-
- GetLastSession();
-
- session_helper_.AssertSingleWindowWithSingleTab(windows_, 2);
- session_helper_.AssertTabEquals(0, 1, 2, *(windows_[0]->tabs[0]));
-
- TabNavigation nav(0, url0, GURL(), string16(),
- webkit_glue::CreateHistoryStateForURL(url0),
- PAGE_TRANSITION_LINK);
- session_helper_.AssertNavigationEquals(nav,
- windows_[0]->tabs[0]->navigations[0]);
- nav.set_url(url2);
- session_helper_.AssertNavigationEquals(nav,
- windows_[0]->tabs[0]->navigations[1]);
+ EXPECT_EQ(url4, controller.GetVisibleEntry()->GetURL());
}
-*/
} // namespace content
diff --git a/chromium/content/browser/web_contents/navigation_entry_impl.cc b/chromium/content/browser/frame_host/navigation_entry_impl.cc
index 10d50ca0df2..d5d6fc2c982 100644
--- a/chromium/content/browser/web_contents/navigation_entry_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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/web_contents/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
@@ -52,14 +52,15 @@ NavigationEntryImpl::NavigationEntryImpl()
is_renderer_initiated_(false),
should_replace_entry_(false),
should_clear_history_list_(false),
- can_load_local_resources_(false) {
+ can_load_local_resources_(false),
+ frame_tree_node_id_(-1) {
}
NavigationEntryImpl::NavigationEntryImpl(SiteInstanceImpl* instance,
int page_id,
const GURL& url,
const Referrer& referrer,
- const string16& title,
+ const base::string16& title,
PageTransition transition_type,
bool is_renderer_initiated)
: unique_id_(GetUniqueIDInConstructor()),
@@ -80,7 +81,8 @@ NavigationEntryImpl::NavigationEntryImpl(SiteInstanceImpl* instance,
is_renderer_initiated_(is_renderer_initiated),
should_replace_entry_(false),
should_clear_history_list_(false),
- can_load_local_resources_(false) {
+ can_load_local_resources_(false),
+ frame_tree_node_id_(-1) {
}
NavigationEntryImpl::~NavigationEntryImpl() {
@@ -128,12 +130,12 @@ const GURL& NavigationEntryImpl::GetVirtualURL() const {
return virtual_url_.is_empty() ? url_ : virtual_url_;
}
-void NavigationEntryImpl::SetTitle(const string16& title) {
+void NavigationEntryImpl::SetTitle(const base::string16& title) {
title_ = title;
cached_display_title_.clear();
}
-const string16& NavigationEntryImpl::GetTitle() const {
+const base::string16& NavigationEntryImpl::GetTitle() const {
return title_;
}
@@ -164,7 +166,7 @@ void NavigationEntryImpl::SetBindings(int bindings) {
bindings_ = bindings;
}
-const string16& NavigationEntryImpl::GetTitleForDisplay(
+const base::string16& NavigationEntryImpl::GetTitleForDisplay(
const std::string& languages) const {
// Most pages have real titles. Don't even bother caching anything if this is
// the case.
@@ -177,7 +179,7 @@ const string16& NavigationEntryImpl::GetTitleForDisplay(
return cached_display_title_;
// Use the virtual URL first if any, and fall back on using the real URL.
- string16 title;
+ base::string16 title;
if (!virtual_url_.is_empty()) {
title = net::FormatUrl(virtual_url_, languages);
} else if (!url_.is_empty()) {
@@ -186,8 +188,8 @@ const string16& NavigationEntryImpl::GetTitleForDisplay(
// For file:// URLs use the filename as the title, not the full path.
if (url_.SchemeIsFile()) {
- string16::size_type slashpos = title.rfind('/');
- if (slashpos != string16::npos)
+ base::string16::size_type slashpos = title.rfind('/');
+ if (slashpos != base::string16::npos)
title = title.substr(slashpos + 1);
}
@@ -304,13 +306,14 @@ const std::string& NavigationEntryImpl::GetFrameToNavigate() const {
}
void NavigationEntryImpl::SetExtraData(const std::string& key,
- const string16& data) {
+ const base::string16& data) {
extra_data_[key] = data;
}
bool NavigationEntryImpl::GetExtraData(const std::string& key,
- string16* data) const {
- std::map<std::string, string16>::const_iterator iter = extra_data_.find(key);
+ base::string16* data) const {
+ std::map<std::string, base::string16>::const_iterator iter =
+ extra_data_.find(key);
if (iter == extra_data_.end())
return false;
*data = iter->second;
@@ -321,6 +324,18 @@ void NavigationEntryImpl::ClearExtraData(const std::string& key) {
extra_data_.erase(key);
}
+void NavigationEntryImpl::ResetForCommit() {
+ // Any state that only matters when a navigation entry is pending should be
+ // cleared here.
+ SetBrowserInitiatedPostData(NULL);
+ set_is_renderer_initiated(false);
+ set_transferred_global_request_id(GlobalRequestID());
+ set_should_replace_entry(false);
+ redirect_chain_.clear();
+ set_should_clear_history_list(false);
+ set_frame_tree_node_id(-1);
+}
+
void NavigationEntryImpl::SetScreenshotPNGData(
scoped_refptr<base::RefCountedBytes> png_data) {
screenshot_ = png_data;
diff --git a/chromium/content/browser/web_contents/navigation_entry_impl.h b/chromium/content/browser/frame_host/navigation_entry_impl.h
index 63924b8ad73..8a518888ce5 100644
--- a/chromium/content/browser/web_contents/navigation_entry_impl.h
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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_WEB_CONTENTS_NAVIGATION_ENTRY_IMPL_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_NAVIGATION_ENTRY_IMPL_H_
+#ifndef CONTENT_BROWSER_FRAME_HOST_NAVIGATION_ENTRY_IMPL_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATION_ENTRY_IMPL_H_
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
@@ -29,7 +29,7 @@ class CONTENT_EXPORT NavigationEntryImpl
int page_id,
const GURL& url,
const Referrer& referrer,
- const string16& title,
+ const base::string16& title,
PageTransition transition_type,
bool is_renderer_initiated);
virtual ~NavigationEntryImpl();
@@ -45,13 +45,13 @@ class CONTENT_EXPORT NavigationEntryImpl
virtual const Referrer& GetReferrer() const OVERRIDE;
virtual void SetVirtualURL(const GURL& url) OVERRIDE;
virtual const GURL& GetVirtualURL() const OVERRIDE;
- virtual void SetTitle(const string16& title) OVERRIDE;
- virtual const string16& GetTitle() const OVERRIDE;
+ virtual void SetTitle(const base::string16& title) OVERRIDE;
+ virtual const base::string16& GetTitle() const OVERRIDE;
virtual void SetPageState(const PageState& state) OVERRIDE;
virtual const PageState& GetPageState() const OVERRIDE;
virtual void SetPageID(int page_id) OVERRIDE;
virtual int32 GetPageID() const OVERRIDE;
- virtual const string16& GetTitleForDisplay(
+ virtual const base::string16& GetTitleForDisplay(
const std::string& languages) const OVERRIDE;
virtual bool IsViewSourceMode() const OVERRIDE;
virtual void SetTransitionType(PageTransition transition_type) OVERRIDE;
@@ -80,13 +80,17 @@ class CONTENT_EXPORT NavigationEntryImpl
virtual void SetFrameToNavigate(const std::string& frame_name) OVERRIDE;
virtual const std::string& GetFrameToNavigate() const OVERRIDE;
virtual void SetExtraData(const std::string& key,
- const string16& data) OVERRIDE;
+ const base::string16& data) OVERRIDE;
virtual bool GetExtraData(const std::string& key,
- string16* data) const OVERRIDE;
+ base::string16* data) const OVERRIDE;
virtual void ClearExtraData(const std::string& key) OVERRIDE;
virtual void SetHttpStatusCode(int http_status_code) OVERRIDE;
virtual int GetHttpStatusCode() const OVERRIDE;
+ // Once a navigation entry is committed, we should no longer track several
+ // pieces of non-persisted state, as documented on the members below.
+ void ResetForCommit();
+
void set_unique_id(int unique_id) {
unique_id_ = unique_id;
}
@@ -188,6 +192,16 @@ class CONTENT_EXPORT NavigationEntryImpl
should_replace_entry_ = should_replace_entry;
}
+ // Any redirects present in a pending entry when it is transferred from one
+ // process to another. Not valid after commit.
+ const std::vector<GURL>& redirect_chain() const {
+ return redirect_chain_;
+ }
+
+ void set_redirect_chain(const std::vector<GURL>& redirect_chain) {
+ redirect_chain_ = redirect_chain;
+ }
+
void SetScreenshotPNGData(scoped_refptr<base::RefCountedBytes> png_data);
const scoped_refptr<base::RefCountedBytes> screenshot() const {
return screenshot_;
@@ -202,6 +216,15 @@ class CONTENT_EXPORT NavigationEntryImpl
should_clear_history_list_ = should_clear_history_list;
}
+ // Indicates which FrameTreeNode to navigate. Currently only used if the
+ // --site-per-process flag is passed.
+ int64 frame_tree_node_id() const {
+ return frame_tree_node_id_;
+ }
+ void set_frame_tree_node_id(int64 frame_tree_node_id) {
+ frame_tree_node_id_ = frame_tree_node_id;
+ }
+
private:
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
// Session/Tab restore save portions of this class so that it can be recreated
@@ -220,7 +243,7 @@ class CONTENT_EXPORT NavigationEntryImpl
Referrer referrer_;
GURL virtual_url_;
bool update_virtual_url_with_url_;
- string16 title_;
+ base::string16 title_;
FaviconStatus favicon_;
PageState page_state_;
int32 page_id_;
@@ -239,6 +262,7 @@ class CONTENT_EXPORT NavigationEntryImpl
// 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_;
// This is also a transient member (i.e. is not persisted with session
@@ -259,14 +283,14 @@ class CONTENT_EXPORT NavigationEntryImpl
// Whether the entry, while loading, was created for a renderer-initiated
// navigation. This dictates whether the URL should be displayed before the
- // navigation commits. It is cleared on commit and not persisted.
+ // navigation commits. It is cleared in |ResetForCommit| and not persisted.
bool is_renderer_initiated_;
// This is a cached version of the result of GetTitleForDisplay. It prevents
// us from having to do URL formatting on the URL every time the title is
// displayed. When the URL, virtual URL, or title is set, this should be
// cleared to force a refresh.
- mutable string16 cached_display_title_;
+ mutable base::string16 cached_display_title_;
// In case a navigation is transferred to a new RVH but the request has
// been generated in the renderer already, this identifies the old request so
@@ -275,24 +299,29 @@ class CONTENT_EXPORT NavigationEntryImpl
// carries this |transferred_global_request_id_| annotation. Once the request
// is transferred to the new process, this is cleared and the request
// continues as normal.
+ // Cleared in |ResetForCommit|.
GlobalRequestID transferred_global_request_id_;
// This is set to true when this entry is being reloaded and due to changes in
// the state of the URL, it has to be reloaded in a different site instance.
// In such case, we must treat it as an existing navigation in the new site
// instance, instead of a new navigation. This value should not be persisted
- // and is not needed after the entry commits.
+ // and is cleared in |ResetForCommit|.
//
// We also use this flag for cross-process redirect navigations, so that the
// browser will replace the current navigation entry (which is the page
// doing the redirect).
bool should_replace_entry_;
+ // This is used when transferring a pending entry from one process to another.
+ // It is cleared in |ResetForCommit| and should not be persisted.
+ std::vector<GURL> redirect_chain_;
+
// This is set to true when this entry's navigation should clear the session
// history both on the renderer and browser side. The browser side history
// won't be cleared until the renderer has committed this navigation. This
// entry is not persisted by the session restore system, as it is always
- // reset to false after commit.
+ // cleared in |ResetForCommit|.
bool should_clear_history_list_;
// Set when this entry should be able to access local file:// resources. This
@@ -303,14 +332,21 @@ class CONTENT_EXPORT NavigationEntryImpl
// persisted, because it is currently only used in tests.
std::string frame_to_navigate_;
+ // If not -1, this indicates which FrameTreeNode to navigate. This field is
+ // not persisted because it is experimental and only used when the
+ // --site-per-process flag is passed. It is cleared in |ResetForCommit|
+ // because we only use it while the navigation is pending.
+ // TODO(creis): Move this to FrameNavigationEntry.
+ int64 frame_tree_node_id_;
+
// Used to store extra data to support browser features. This member is not
// persisted, unless specific data is taken out/put back in at save/restore
// time (see TabNavigation for an example of this).
- std::map<std::string, string16> extra_data_;
+ std::map<std::string, base::string16> extra_data_;
// Copy and assignment is explicitly allowed for this class.
};
} // namespace content
-#endif // CONTENT_BROWSER_WEB_CONTENTS_NAVIGATION_ENTRY_IMPL_H_
+#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATION_ENTRY_IMPL_H_
diff --git a/chromium/content/browser/web_contents/navigation_entry_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
index 138ed74cfd5..488106fefed 100644
--- a/chromium/content/browser/web_contents/navigation_entry_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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.
@@ -6,8 +6,8 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/site_instance_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/public/common/ssl_status.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -27,7 +27,7 @@ class NavigationEntryTest : public testing::Test {
entry2_.reset(new NavigationEntryImpl(
instance_, 3,
GURL("test:url"),
- Referrer(GURL("from"), WebKit::WebReferrerPolicyDefault),
+ Referrer(GURL("from"), blink::WebReferrerPolicyDefault),
ASCIIToUTF16("title"),
PAGE_TRANSITION_TYPED,
false));
@@ -132,11 +132,11 @@ TEST_F(NavigationEntryTest, NavigationEntryAccessors) {
EXPECT_EQ(GURL(), entry1_->GetReferrer().url);
EXPECT_EQ(GURL("from"), entry2_->GetReferrer().url);
entry2_->SetReferrer(
- Referrer(GURL("from2"), WebKit::WebReferrerPolicyDefault));
+ Referrer(GURL("from2"), blink::WebReferrerPolicyDefault));
EXPECT_EQ(GURL("from2"), entry2_->GetReferrer().url);
// Title
- EXPECT_EQ(string16(), entry1_->GetTitle());
+ EXPECT_EQ(base::string16(), entry1_->GetTitle());
EXPECT_EQ(ASCIIToUTF16("title"), entry2_->GetTitle());
entry2_->SetTitle(ASCIIToUTF16("title2"));
EXPECT_EQ(ASCIIToUTF16("title2"), entry2_->GetTitle());
@@ -219,8 +219,8 @@ TEST_F(NavigationEntryTest, NavigationEntryTimestamps) {
// Test extra data stored in the navigation entry.
TEST_F(NavigationEntryTest, NavigationEntryExtraData) {
- string16 test_data = ASCIIToUTF16("my search terms");
- string16 output;
+ base::string16 test_data = ASCIIToUTF16("my search terms");
+ base::string16 output;
entry1_->SetExtraData("search_terms", test_data);
EXPECT_FALSE(entry1_->GetExtraData("non_existent_key", &output));
@@ -233,7 +233,7 @@ TEST_F(NavigationEntryTest, NavigationEntryExtraData) {
EXPECT_FALSE(entry1_->GetExtraData("search_terms", &output));
EXPECT_EQ(test_data, output);
// Using an empty string shows that the data is not present in the map.
- string16 output2;
+ base::string16 output2;
EXPECT_FALSE(entry1_->GetExtraData("search_terms", &output2));
EXPECT_EQ(ASCIIToUTF16(""), output2);
}
diff --git a/chromium/content/browser/web_contents/web_contents_screenshot_manager.cc b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc
index 811e4ea7fbc..0b955fc6d7c 100644
--- a/chromium/content/browser/web_contents/web_contents_screenshot_manager.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc
@@ -1,15 +1,14 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// 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/web_contents/web_contents_screenshot_manager.h"
+#include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
#include "base/command_line.h"
#include "base/threading/worker_pool.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/web_contents/navigation_controller_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
-#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/content_switches.h"
@@ -59,17 +58,17 @@ class ScreenshotData : public base::RefCountedThreadSafe<ScreenshotData> {
DISALLOW_COPY_AND_ASSIGN(ScreenshotData);
};
-WebContentsScreenshotManager::WebContentsScreenshotManager(
+NavigationEntryScreenshotManager::NavigationEntryScreenshotManager(
NavigationControllerImpl* owner)
: owner_(owner),
screenshot_factory_(this),
min_screenshot_interval_ms_(kMinScreenshotIntervalMS) {
}
-WebContentsScreenshotManager::~WebContentsScreenshotManager() {
+NavigationEntryScreenshotManager::~NavigationEntryScreenshotManager() {
}
-void WebContentsScreenshotManager::TakeScreenshot() {
+void NavigationEntryScreenshotManager::TakeScreenshot() {
static bool overscroll_enabled = CommandLine::ForCurrentProcess()->
GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
if (!overscroll_enabled)
@@ -81,7 +80,7 @@ void WebContentsScreenshotManager::TakeScreenshot() {
return;
RenderViewHost* render_view_host =
- owner_->web_contents()->GetRenderViewHost();
+ owner_->delegate()->GetRenderViewHost();
if (!static_cast<RenderViewHostImpl*>
(render_view_host)->overscroll_controller()) {
return;
@@ -104,7 +103,7 @@ void WebContentsScreenshotManager::TakeScreenshot() {
// Implemented here and not in NavigationEntry because this manager keeps track
// of the total number of screen shots across all entries.
-void WebContentsScreenshotManager::ClearAllScreenshots() {
+void NavigationEntryScreenshotManager::ClearAllScreenshots() {
int count = owner_->GetEntryCount();
for (int i = 0; i < count; ++i) {
ClearScreenshot(NavigationEntryImpl::FromNavigationEntry(
@@ -113,24 +112,25 @@ void WebContentsScreenshotManager::ClearAllScreenshots() {
DCHECK_EQ(GetScreenshotCount(), 0);
}
-void WebContentsScreenshotManager::TakeScreenshotImpl(
+void NavigationEntryScreenshotManager::TakeScreenshotImpl(
RenderViewHost* host,
NavigationEntryImpl* entry) {
DCHECK(host && host->GetView());
DCHECK(entry);
host->CopyFromBackingStore(gfx::Rect(),
host->GetView()->GetViewBounds().size(),
- base::Bind(&WebContentsScreenshotManager::OnScreenshotTaken,
+ base::Bind(&NavigationEntryScreenshotManager::OnScreenshotTaken,
screenshot_factory_.GetWeakPtr(),
entry->GetUniqueID()));
}
-void WebContentsScreenshotManager::SetMinScreenshotIntervalMS(int interval_ms) {
+void NavigationEntryScreenshotManager::SetMinScreenshotIntervalMS(
+ int interval_ms) {
DCHECK_GE(interval_ms, 0);
min_screenshot_interval_ms_ = interval_ms;
}
-void WebContentsScreenshotManager::OnScreenshotTaken(int unique_id,
+void NavigationEntryScreenshotManager::OnScreenshotTaken(int unique_id,
bool success,
const SkBitmap& bitmap) {
NavigationEntryImpl* entry = NULL;
@@ -157,13 +157,13 @@ void WebContentsScreenshotManager::OnScreenshotTaken(int unique_id,
scoped_refptr<ScreenshotData> screenshot = new ScreenshotData();
screenshot->EncodeScreenshot(
bitmap,
- base::Bind(&WebContentsScreenshotManager::OnScreenshotEncodeComplete,
+ base::Bind(&NavigationEntryScreenshotManager::OnScreenshotEncodeComplete,
screenshot_factory_.GetWeakPtr(),
unique_id,
screenshot));
}
-int WebContentsScreenshotManager::GetScreenshotCount() const {
+int NavigationEntryScreenshotManager::GetScreenshotCount() const {
int screenshot_count = 0;
int entry_count = owner_->GetEntryCount();
for (int i = 0; i < entry_count; ++i) {
@@ -175,7 +175,7 @@ int WebContentsScreenshotManager::GetScreenshotCount() const {
return screenshot_count;
}
-void WebContentsScreenshotManager::OnScreenshotEncodeComplete(
+void NavigationEntryScreenshotManager::OnScreenshotEncodeComplete(
int unique_id,
scoped_refptr<ScreenshotData> screenshot) {
NavigationEntryImpl* entry = NULL;
@@ -193,12 +193,14 @@ void WebContentsScreenshotManager::OnScreenshotEncodeComplete(
OnScreenshotSet(entry);
}
-void WebContentsScreenshotManager::OnScreenshotSet(NavigationEntryImpl* entry) {
+void NavigationEntryScreenshotManager::OnScreenshotSet(
+ NavigationEntryImpl* entry) {
if (entry->screenshot().get())
PurgeScreenshotsIfNecessary();
}
-bool WebContentsScreenshotManager::ClearScreenshot(NavigationEntryImpl* entry) {
+bool NavigationEntryScreenshotManager::ClearScreenshot(
+ NavigationEntryImpl* entry) {
if (!entry->screenshot().get())
return false;
@@ -206,7 +208,7 @@ bool WebContentsScreenshotManager::ClearScreenshot(NavigationEntryImpl* entry) {
return true;
}
-void WebContentsScreenshotManager::PurgeScreenshotsIfNecessary() {
+void NavigationEntryScreenshotManager::PurgeScreenshotsIfNecessary() {
// Allow only a certain number of entries to keep screenshots.
const int kMaxScreenshots = 10;
int screenshot_count = GetScreenshotCount();
diff --git a/chromium/content/browser/web_contents/web_contents_screenshot_manager.h b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.h
index 23df41ee757..072d6fd4a7f 100644
--- a/chromium/content/browser/web_contents/web_contents_screenshot_manager.h
+++ b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// 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_WEB_CONTENTS_WEB_CONTENTS_SCREENSHOT_MANAGER_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_SCREENSHOT_MANAGER_H_
+#ifndef CONTENT_BROWSER_FRAME_HOST_NAVIGATION_ENTRY_SCREENSHOT_MANAGER_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATION_ENTRY_SCREENSHOT_MANAGER_H_
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
@@ -19,14 +19,15 @@ class NavigationEntryImpl;
class RenderViewHost;
class ScreenshotData;
-// WebContentsScreenshotManager takes care of taking image-captures for the
+// NavigationEntryScreenshotManager takes care of taking image-captures for the
// current navigation entry of a NavigationControllerImpl, and managing these
// captured images. These image-captures are used for history navigation using
// overscroll gestures.
-class CONTENT_EXPORT WebContentsScreenshotManager {
+class CONTENT_EXPORT NavigationEntryScreenshotManager {
public:
- explicit WebContentsScreenshotManager(NavigationControllerImpl* controller);
- virtual ~WebContentsScreenshotManager();
+ explicit NavigationEntryScreenshotManager(
+ NavigationControllerImpl* controller);
+ virtual ~NavigationEntryScreenshotManager();
// Takes a screenshot of the last-committed entry of the controller.
void TakeScreenshot();
@@ -75,15 +76,15 @@ class CONTENT_EXPORT WebContentsScreenshotManager {
// Taking a screenshot and encoding them can be async. So use a weakptr for
// the callback to make sure that the screenshot/encoding completion callback
- // does not trigger on a destroyed WebContentsScreenshotManager.
- base::WeakPtrFactory<WebContentsScreenshotManager> screenshot_factory_;
+ // does not trigger on a destroyed NavigationEntryScreenshotManager.
+ base::WeakPtrFactory<NavigationEntryScreenshotManager> screenshot_factory_;
base::Time last_screenshot_time_;
int min_screenshot_interval_ms_;
- DISALLOW_COPY_AND_ASSIGN(WebContentsScreenshotManager);
+ DISALLOW_COPY_AND_ASSIGN(NavigationEntryScreenshotManager);
};
} // namespace content
-#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_SCREENSHOT_MANAGER_H_
+#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATION_ENTRY_SCREENSHOT_MANAGER_H_
diff --git a/chromium/content/browser/frame_host/navigator.h b/chromium/content/browser/frame_host/navigator.h
new file mode 100644
index 00000000000..d6658e4cd90
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigator.h
@@ -0,0 +1,42 @@
+// 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_FRAME_HOST_NAVIGATOR_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_H_
+
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+
+class GURL;
+
+namespace content {
+
+class NavigationControllerImpl;
+class NavigatorDelegate;
+class RenderFrameHostImpl;
+
+// Implementations of this interface are responsible for performing navigations
+// in a node of the FrameTree. Its lifetime is bound to all FrameTreeNode
+// objects that are using it and will be released once all nodes that use it are
+// freed. The Navigator is bound to a single frame tree and cannot be used by
+// multiple instances of FrameTree.
+// TODO(nasko): Move all navigation methods, such as didStartProvisionalLoad
+// from WebContentsImpl to this interface.
+class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
+ public:
+ // The RenderFrameHostImpl started a provisional load.
+ virtual void DidStartProvisionalLoad(RenderFrameHostImpl* render_frame_host,
+ int64 frame_id,
+ int64 parent_frame_id,
+ bool main_frame,
+ const GURL& url) {};
+
+ protected:
+ friend class base::RefCounted<Navigator>;
+ virtual ~Navigator() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_H_
diff --git a/chromium/content/browser/frame_host/navigator_delegate.h b/chromium/content/browser/frame_host/navigator_delegate.h
new file mode 100644
index 00000000000..62b5b48b0bb
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigator_delegate.h
@@ -0,0 +1,37 @@
+// 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_FRAME_HOST_NAVIGATOR_DELEGATE_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_DELEGATE_H_
+
+#include "content/public/browser/invalidate_type.h"
+
+namespace content {
+
+class RenderFrameHost;
+
+// A delegate API used by Navigator to notify its embedder of navigation
+// related events.
+class NavigatorDelegate {
+ public:
+ // The RenderFrameHost started a provisional load for the frame
+ // represented by |render_frame_host|.
+ virtual void DidStartProvisionalLoad(
+ RenderFrameHostImpl* render_frame_host,
+ int64 frame_id,
+ int64 parent_frame_id,
+ bool is_main_frame,
+ const GURL& validated_url,
+ bool is_error_page,
+ bool is_iframe_srcdoc) {}
+
+ // Notification to the Navigator embedder that navigation state has
+ // changed. This method corresponds to
+ // WebContents::NotifyNavigationStateChanged.
+ virtual void NotifyChangedNavigationState(InvalidateTypes changed_flags) {}
+};
+
+} // namspace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_DELEGATE_H_
diff --git a/chromium/content/browser/frame_host/navigator_impl.cc b/chromium/content/browser/frame_host/navigator_impl.cc
new file mode 100644
index 00000000000..6cc9dad1488
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigator_impl.cc
@@ -0,0 +1,85 @@
+// 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/frame_host/navigator_impl.h"
+
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigator_delegate.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/site_instance_impl.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/invalidate_type.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/common/url_constants.h"
+
+namespace content {
+
+NavigatorImpl::NavigatorImpl(
+ NavigationControllerImpl* navigation_controller,
+ NavigatorDelegate* delegate)
+ : controller_(navigation_controller),
+ delegate_(delegate) {
+}
+
+void NavigatorImpl::DidStartProvisionalLoad(
+ RenderFrameHostImpl* render_frame_host,
+ int64 frame_id,
+ int64 parent_frame_id,
+ bool is_main_frame,
+ const GURL& url) {
+ bool is_error_page = (url.spec() == kUnreachableWebDataURL);
+ bool is_iframe_srcdoc = (url.spec() == kAboutSrcDocURL);
+ GURL validated_url(url);
+ RenderProcessHost* render_process_host = render_frame_host->GetProcess();
+ RenderViewHost::FilterURL(render_process_host, false, &validated_url);
+
+ if (is_main_frame) {
+ // If there is no browser-initiated pending entry for this navigation and it
+ // is not for the error URL, create a pending entry using the current
+ // SiteInstance, and ensure the address bar updates accordingly. We don't
+ // know the referrer or extra headers at this point, but the referrer will
+ // be set properly upon commit.
+ NavigationEntryImpl* pending_entry =
+ NavigationEntryImpl::FromNavigationEntry(
+ controller_->GetPendingEntry());
+ bool has_browser_initiated_pending_entry = pending_entry &&
+ !pending_entry->is_renderer_initiated();
+ if (!has_browser_initiated_pending_entry && !is_error_page) {
+ NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
+ controller_->CreateNavigationEntry(validated_url,
+ content::Referrer(),
+ content::PAGE_TRANSITION_LINK,
+ true /* is_renderer_initiated */,
+ std::string(),
+ controller_->GetBrowserContext()));
+ entry->set_site_instance(
+ static_cast<SiteInstanceImpl*>(
+ render_frame_host->render_view_host()->GetSiteInstance()));
+ // TODO(creis): If there's a pending entry already, find a safe way to
+ // update it instead of replacing it and copying over things like this.
+ if (pending_entry) {
+ entry->set_transferred_global_request_id(
+ pending_entry->transferred_global_request_id());
+ entry->set_should_replace_entry(pending_entry->should_replace_entry());
+ entry->set_redirect_chain(pending_entry->redirect_chain());
+ }
+ controller_->SetPendingEntry(entry);
+ if (delegate_)
+ delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL);
+ }
+ }
+
+ if (delegate_) {
+ // Notify the observer about the start of the provisional load.
+ delegate_->DidStartProvisionalLoad(
+ render_frame_host, frame_id, parent_frame_id, is_main_frame,
+ validated_url, is_error_page, is_iframe_srcdoc);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator_impl.h b/chromium/content/browser/frame_host/navigator_impl.h
new file mode 100644
index 00000000000..b66b87de036
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigator_impl.h
@@ -0,0 +1,49 @@
+// 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_FRAME_HOST_NAVIGATOR_IMPL_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_IMPL_H_
+
+#include "base/memory/ref_counted.h"
+#include "content/browser/frame_host/navigator.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class NavigationControllerImpl;
+class NavigatorDelegate;
+
+// This class is an implementation of Navigator, responsible for managing
+// navigations in regular browser tabs.
+class CONTENT_EXPORT NavigatorImpl : public Navigator {
+ public:
+ NavigatorImpl(NavigationControllerImpl* navigation_controller,
+ NavigatorDelegate* delegate);
+
+ // Navigator implementation.
+ virtual void DidStartProvisionalLoad(RenderFrameHostImpl* render_frame_host,
+ int64 frame_id,
+ int64 parent_frame_id,
+ bool main_frame,
+ const GURL& url) OVERRIDE;
+
+ private:
+ virtual ~NavigatorImpl() {}
+
+ // The NavigationController that will keep track of session history for all
+ // RenderFrameHost objects using this NavigatorImpl.
+ // TODO(nasko): Move ownership of the NavigationController from
+ // WebContentsImpl to this class.
+ NavigationControllerImpl* controller_;
+
+ // Used to notify the object embedding this Navigator about navigation
+ // events. Can be NULL in tests.
+ NavigatorDelegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(NavigatorImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_IMPL_H_
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.cc b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
new file mode 100644
index 00000000000..14ed0ad4cb2
--- /dev/null
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
@@ -0,0 +1,15 @@
+// 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/frame_host/render_frame_host_delegate.h"
+
+namespace content {
+
+bool RenderFrameHostDelegate::OnMessageReceived(
+ RenderFrameHost* render_view_host,
+ const IPC::Message& message) {
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.h b/chromium/content/browser/frame_host/render_frame_host_delegate.h
new file mode 100644
index 00000000000..1de47dff379
--- /dev/null
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -0,0 +1,37 @@
+// 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_FRAME_HOST_RENDER_FRAME_HOST_DELEGATE_H_
+#define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_DELEGATE_H_
+
+#include "content/common/content_export.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace content {
+class RenderFrameHost;
+
+// An interface implemented by an object interested in knowing about the state
+// of the RenderFrameHost.
+class CONTENT_EXPORT RenderFrameHostDelegate {
+ public:
+ // This is used to give the delegate a chance to filter IPC messages.
+ virtual bool OnMessageReceived(RenderFrameHost* render_frame_host,
+ const IPC::Message& message);
+
+ // Informs the delegate whenever a RenderFrameHost is created.
+ virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) {}
+
+ // Informs the delegate whenever a RenderFrameHost is deleted.
+ virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) {}
+
+ protected:
+ virtual ~RenderFrameHostDelegate() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_DELEGATE_H_
diff --git a/chromium/content/browser/frame_host/render_frame_host_factory.cc b/chromium/content/browser/frame_host/render_frame_host_factory.cc
new file mode 100644
index 00000000000..4262c1c7eb2
--- /dev/null
+++ b/chromium/content/browser/frame_host/render_frame_host_factory.cc
@@ -0,0 +1,49 @@
+// 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/frame_host/render_frame_host_factory.h"
+
+#include "base/logging.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+
+namespace content {
+
+// static
+RenderFrameHostFactory* RenderFrameHostFactory::factory_ = NULL;
+
+// static
+scoped_ptr<RenderFrameHostImpl> RenderFrameHostFactory::Create(
+ RenderViewHostImpl* render_view_host,
+ RenderFrameHostDelegate* delegate,
+ FrameTree* frame_tree,
+ FrameTreeNode* frame_tree_node,
+ int routing_id,
+ bool is_swapped_out) {
+ if (factory_) {
+ return factory_->CreateRenderFrameHost(render_view_host,
+ delegate,
+ frame_tree,
+ frame_tree_node,
+ routing_id,
+ is_swapped_out).Pass();
+ }
+ return make_scoped_ptr(new RenderFrameHostImpl(
+ render_view_host, delegate, frame_tree, frame_tree_node, routing_id,
+ is_swapped_out));
+}
+
+// static
+void RenderFrameHostFactory::RegisterFactory(RenderFrameHostFactory* factory) {
+ DCHECK(!factory_) << "Can't register two factories at once.";
+ factory_ = factory;
+}
+
+// static
+void RenderFrameHostFactory::UnregisterFactory() {
+ DCHECK(factory_) << "No factory to unregister.";
+ factory_ = NULL;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_factory.h b/chromium/content/browser/frame_host/render_frame_host_factory.h
new file mode 100644
index 00000000000..ce8433d0882
--- /dev/null
+++ b/chromium/content/browser/frame_host/render_frame_host_factory.h
@@ -0,0 +1,71 @@
+// 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_FRAME_HOST_RENDER_FRAME_HOST_FACTORY_H_
+#define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_FACTORY_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class FrameTree;
+class FrameTreeNode;
+class RenderFrameHostDelegate;
+class RenderFrameHostImpl;
+class RenderViewHostImpl;
+
+// A factory for creating RenderFrameHosts. There is a global factory function
+// that can be installed for the purposes of testing to provide a specialized
+// RenderFrameHostImpl class.
+class CONTENT_EXPORT RenderFrameHostFactory {
+ public:
+ // Creates a new RenderFrameHostImpl using the currently registered factory,
+ // or a regular RenderFrameHostImpl if no factory is registered.
+ static scoped_ptr<RenderFrameHostImpl> Create(
+ RenderViewHostImpl* render_view_host,
+ RenderFrameHostDelegate* delegate,
+ FrameTree* frame_tree,
+ FrameTreeNode* frame_tree_node,
+ int routing_id,
+ bool is_swapped_out);
+
+ // Returns true if there is currently a globally-registered factory.
+ static bool has_factory() { return !!factory_; }
+
+ protected:
+ RenderFrameHostFactory() {}
+ virtual ~RenderFrameHostFactory() {}
+
+ // You can derive from this class and specify an implementation for this
+ // function to create an alternate kind of RenderFrameHostImpl for testing.
+ virtual scoped_ptr<RenderFrameHostImpl> CreateRenderFrameHost(
+ RenderViewHostImpl* render_view_host,
+ RenderFrameHostDelegate* delegate,
+ FrameTree* frame_tree,
+ FrameTreeNode* frame_tree_node,
+ int routing_id,
+ bool is_swapped_out) = 0;
+
+ // Registers a factory to be called when new RenderFrameHostImpls are created.
+ // We have only one global factory, so there must be no factory registered
+ // before the call. This class does NOT take ownership of the pointer.
+ static void RegisterFactory(RenderFrameHostFactory* factory);
+
+ // Unregister the previously registered factory. With no factory registered,
+ // regular RenderFrameHostImpls will be created.
+ static void UnregisterFactory();
+
+ private:
+ // The current globally registered factory. This is NULL when we should create
+ // regular RenderFrameHostImpls.
+ static RenderFrameHostFactory* factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameHostFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_FACTORY_H_
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl.cc b/chromium/content/browser/frame_host/render_frame_host_impl.cc
new file mode 100644
index 00000000000..658e834230d
--- /dev/null
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -0,0 +1,128 @@
+// 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/frame_host/render_frame_host_impl.h"
+
+#include "base/containers/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/navigator.h"
+#include "content/browser/frame_host/render_frame_host_delegate.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/common/frame_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/user_metrics.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// The (process id, routing id) pair that identifies one RenderFrame.
+typedef std::pair<int32, int32> RenderFrameHostID;
+typedef base::hash_map<RenderFrameHostID, RenderFrameHostImpl*>
+ RoutingIDFrameMap;
+static base::LazyInstance<RoutingIDFrameMap> g_routing_id_frame_map =
+ LAZY_INSTANCE_INITIALIZER;
+
+// static
+RenderFrameHostImpl* RenderFrameHostImpl::FromID(
+ int process_id, int routing_id) {
+ RoutingIDFrameMap* frames = g_routing_id_frame_map.Pointer();
+ RoutingIDFrameMap::iterator it = frames->find(
+ RenderFrameHostID(process_id, routing_id));
+ return it == frames->end() ? NULL : it->second;
+}
+
+RenderFrameHostImpl::RenderFrameHostImpl(
+ RenderViewHostImpl* render_view_host,
+ RenderFrameHostDelegate* delegate,
+ FrameTree* frame_tree,
+ FrameTreeNode* frame_tree_node,
+ int routing_id,
+ bool is_swapped_out)
+ : render_view_host_(render_view_host),
+ delegate_(delegate),
+ frame_tree_(frame_tree),
+ frame_tree_node_(frame_tree_node),
+ routing_id_(routing_id),
+ is_swapped_out_(is_swapped_out) {
+ GetProcess()->AddRoute(routing_id_, this);
+ g_routing_id_frame_map.Get().insert(std::make_pair(
+ RenderFrameHostID(GetProcess()->GetID(), routing_id_),
+ this));
+}
+
+RenderFrameHostImpl::~RenderFrameHostImpl() {
+ GetProcess()->RemoveRoute(routing_id_);
+ g_routing_id_frame_map.Get().erase(
+ RenderFrameHostID(GetProcess()->GetID(), routing_id_));
+ if (delegate_)
+ delegate_->RenderFrameDeleted(this);
+}
+
+int RenderFrameHostImpl::GetRoutingID() {
+ return routing_id_;
+}
+
+bool RenderFrameHostImpl::Send(IPC::Message* message) {
+ return GetProcess()->Send(message);
+}
+
+bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
+ if (delegate_->OnMessageReceived(this, msg))
+ return true;
+
+ bool handled = true;
+ bool msg_is_ok = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(RenderFrameHostImpl, msg, msg_is_ok)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_Detach, OnDetach)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartProvisionalLoadForFrame,
+ OnDidStartProvisionalLoadForFrame)
+ IPC_END_MESSAGE_MAP_EX()
+
+ if (!msg_is_ok) {
+ // The message had a handler, but its de-serialization failed.
+ // Kill the renderer.
+ RecordAction(UserMetricsAction("BadMessageTerminate_RFH"));
+ GetProcess()->ReceivedBadMessage();
+ }
+
+ return handled;
+}
+
+void RenderFrameHostImpl::Init() {
+ GetProcess()->ResumeRequestsForView(routing_id());
+}
+
+RenderProcessHost* RenderFrameHostImpl::GetProcess() const {
+ // TODO(nasko): This should return its own process, once we have working
+ // cross-process navigation for subframes.
+ return render_view_host_->GetProcess();
+}
+
+void RenderFrameHostImpl::OnCreateChildFrame(int new_frame_routing_id,
+ int64 parent_frame_id,
+ int64 frame_id,
+ const std::string& frame_name) {
+ RenderFrameHostImpl* new_frame = frame_tree_->AddFrame(
+ new_frame_routing_id, parent_frame_id, frame_id, frame_name);
+ if (delegate_)
+ delegate_->RenderFrameCreated(new_frame);
+}
+
+void RenderFrameHostImpl::OnDetach(int64 parent_frame_id, int64 frame_id) {
+ frame_tree_->RemoveFrame(this, parent_frame_id, frame_id);
+}
+
+void RenderFrameHostImpl::OnDidStartProvisionalLoadForFrame(
+ int64 frame_id,
+ int64 parent_frame_id,
+ bool is_main_frame,
+ const GURL& url) {
+ frame_tree_node_->navigator()->DidStartProvisionalLoad(
+ this, frame_id, parent_frame_id, is_main_frame, url);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl.h b/chromium/content/browser/frame_host/render_frame_host_impl.h
new file mode 100644
index 00000000000..2822724adfa
--- /dev/null
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -0,0 +1,100 @@
+// 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_FRAME_HOST_RENDER_FRAME_HOST_IMPL_H_
+#define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_IMPL_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/render_frame_host.h"
+
+class GURL;
+
+namespace base {
+class FilePath;
+}
+
+namespace content {
+
+class FrameTree;
+class FrameTreeNode;
+class RenderFrameHostDelegate;
+class RenderProcessHost;
+class RenderViewHostImpl;
+
+class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
+ public:
+ static RenderFrameHostImpl* FromID(int process_id, int routing_id);
+
+ virtual ~RenderFrameHostImpl();
+
+ // RenderFrameHost
+ virtual int GetRoutingID() OVERRIDE;
+
+ // IPC::Sender
+ virtual bool Send(IPC::Message* msg) OVERRIDE;
+
+ // IPC::Listener
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ void Init();
+ RenderProcessHost* GetProcess() const;
+ int routing_id() const { return routing_id_; }
+ void OnCreateChildFrame(int new_frame_routing_id,
+ int64 parent_frame_id,
+ int64 frame_id,
+ const std::string& frame_name);
+
+ RenderViewHostImpl* render_view_host() { return render_view_host_; }
+ RenderFrameHostDelegate* delegate() { return delegate_; }
+
+ protected:
+ friend class RenderFrameHostFactory;
+
+ // TODO(nasko): Remove dependency on RenderViewHost here. RenderProcessHost
+ // should be the abstraction needed here, but we need RenderViewHost to pass
+ // into WebContentsObserver::FrameDetached for now.
+ RenderFrameHostImpl(RenderViewHostImpl* render_view_host,
+ RenderFrameHostDelegate* delegate,
+ FrameTree* frame_tree,
+ FrameTreeNode* frame_tree_node,
+ int routing_id,
+ bool is_swapped_out);
+
+ private:
+ friend class TestRenderViewHost;
+
+ // IPC Message handlers.
+ void OnDetach(int64 parent_frame_id, int64 frame_id);
+ void OnDidStartProvisionalLoadForFrame(int64 frame_id,
+ int64 parent_frame_id,
+ bool main_frame,
+ const GURL& url);
+
+ bool is_swapped_out() { return is_swapped_out_; }
+
+ // TODO(nasko): This should be removed and replaced by RenderProcessHost.
+ RenderViewHostImpl* render_view_host_; // Not owned.
+
+ RenderFrameHostDelegate* delegate_;
+
+ // Reference to the whole frame tree that this RenderFrameHost belongs too.
+ // Allows this RenderFrameHost to add and remove nodes in response to
+ // messages from the renderer requesting DOM manipulation.
+ FrameTree* frame_tree_;
+
+ // The FrameTreeNode which this RenderFrameHostImpl is hosted in.
+ FrameTreeNode* frame_tree_node_;
+
+ int routing_id_;
+ bool is_swapped_out_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameHostImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_IMPL_H_
diff --git a/chromium/content/browser/web_contents/render_view_host_manager.cc b/chromium/content/browser/frame_host/render_frame_host_manager.cc
index f8b3f06dd27..aeb87e753d5 100644
--- a/chromium/content/browser/web_contents/render_view_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -1,22 +1,24 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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/web_contents/render_view_host_manager.h"
+#include "content/browser/frame_host/render_frame_host_manager.h"
#include <utility>
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/render_view_devtools_agent_host.h"
+#include "content/browser/frame_host/debug_urls.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
-#include "content/browser/web_contents/interstitial_page_impl.h"
-#include "content/browser/web_contents/navigation_controller_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/webui/web_ui_impl.h"
#include "content/common/view_messages.h"
@@ -26,27 +28,43 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/user_metrics.h"
-#include "content/public/browser/web_contents_view.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
namespace content {
-RenderViewHostManager::PendingNavigationParams::PendingNavigationParams() {
+RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams()
+ : is_transfer(false), frame_id(-1), should_replace_current_entry(false) {
}
-RenderViewHostManager::PendingNavigationParams::PendingNavigationParams(
- const GlobalRequestID& global_request_id)
- : global_request_id(global_request_id) {
+RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams(
+ const GlobalRequestID& global_request_id,
+ bool is_transfer,
+ const std::vector<GURL>& transfer_url_chain,
+ Referrer referrer,
+ PageTransition page_transition,
+ int64 frame_id,
+ bool should_replace_current_entry)
+ : global_request_id(global_request_id),
+ is_transfer(is_transfer),
+ transfer_url_chain(transfer_url_chain),
+ referrer(referrer),
+ page_transition(page_transition),
+ frame_id(frame_id),
+ should_replace_current_entry(should_replace_current_entry) {
}
-RenderViewHostManager::RenderViewHostManager(
+RenderFrameHostManager::PendingNavigationParams::~PendingNavigationParams() {}
+
+RenderFrameHostManager::RenderFrameHostManager(
+ RenderFrameHostDelegate* render_frame_delegate,
RenderViewHostDelegate* render_view_delegate,
RenderWidgetHostDelegate* render_widget_delegate,
Delegate* delegate)
: delegate_(delegate),
cross_navigation_pending_(false),
+ render_frame_delegate_(render_frame_delegate),
render_view_delegate_(render_view_delegate),
render_widget_delegate_(render_widget_delegate),
render_view_host_(NULL),
@@ -54,7 +72,7 @@ RenderViewHostManager::RenderViewHostManager(
interstitial_page_(NULL) {
}
-RenderViewHostManager::~RenderViewHostManager() {
+RenderFrameHostManager::~RenderFrameHostManager() {
if (pending_render_view_host_)
CancelPending();
@@ -72,10 +90,10 @@ RenderViewHostManager::~RenderViewHostManager() {
}
}
-void RenderViewHostManager::Init(BrowserContext* browser_context,
- SiteInstance* site_instance,
- int routing_id,
- int main_frame_routing_id) {
+void RenderFrameHostManager::Init(BrowserContext* browser_context,
+ SiteInstance* site_instance,
+ int routing_id,
+ int main_frame_routing_id) {
// Create a RenderViewHost, once we have an instance. It is important to
// immediately give this SiteInstance to a RenderViewHost so that it is
// ref counted.
@@ -83,8 +101,10 @@ void RenderViewHostManager::Init(BrowserContext* browser_context,
site_instance = SiteInstance::Create(browser_context);
render_view_host_ = static_cast<RenderViewHostImpl*>(
RenderViewHostFactory::Create(
- site_instance, render_view_delegate_, render_widget_delegate_,
- routing_id, main_frame_routing_id, false, delegate_->IsHidden()));
+ site_instance, render_view_delegate_, render_frame_delegate_,
+ render_widget_delegate_, routing_id, main_frame_routing_id, false,
+ delegate_->IsHidden()));
+ render_view_host_->AttachToFrameTree();
// Keep track of renderer processes as they start to shut down or are
// crashed/killed.
@@ -94,15 +114,15 @@ void RenderViewHostManager::Init(BrowserContext* browser_context,
NotificationService::AllSources());
}
-RenderViewHostImpl* RenderViewHostManager::current_host() const {
+RenderViewHostImpl* RenderFrameHostManager::current_host() const {
return render_view_host_;
}
-RenderViewHostImpl* RenderViewHostManager::pending_render_view_host() const {
+RenderViewHostImpl* RenderFrameHostManager::pending_render_view_host() const {
return pending_render_view_host_;
}
-RenderWidgetHostView* RenderViewHostManager::GetRenderWidgetHostView() const {
+RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const {
if (interstitial_page_)
return interstitial_page_->GetView();
if (!render_view_host_)
@@ -110,7 +130,7 @@ RenderWidgetHostView* RenderViewHostManager::GetRenderWidgetHostView() const {
return render_view_host_->GetView();
}
-void RenderViewHostManager::SetPendingWebUI(const NavigationEntryImpl& entry) {
+void RenderFrameHostManager::SetPendingWebUI(const NavigationEntryImpl& entry) {
pending_web_ui_.reset(
delegate_->CreateWebUIForRenderManager(entry.GetURL()));
pending_and_current_web_ui_.reset();
@@ -127,9 +147,9 @@ void RenderViewHostManager::SetPendingWebUI(const NavigationEntryImpl& entry) {
}
}
-RenderViewHostImpl* RenderViewHostManager::Navigate(
+RenderViewHostImpl* RenderFrameHostManager::Navigate(
const NavigationEntryImpl& entry) {
- TRACE_EVENT0("browser", "RenderViewHostManager:Navigate");
+ TRACE_EVENT0("browser", "RenderFrameHostManager:Navigate");
// Create a pending RenderViewHost. It will give us the one we should use
RenderViewHostImpl* dest_render_view_host =
static_cast<RenderViewHostImpl*>(UpdateRendererStateForNavigate(entry));
@@ -165,22 +185,14 @@ RenderViewHostImpl* RenderViewHostManager::Navigate(
} else {
// This is our primary renderer, notify here as we won't be calling
// CommitPending (which does the notify).
- RenderViewHost* null_rvh = NULL;
- std::pair<RenderViewHost*, RenderViewHost*> details =
- std::make_pair(null_rvh, render_view_host_);
- NotificationService::current()->Notify(
- NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
- Source<NavigationController>(
- &delegate_->GetControllerForRenderManager()),
- Details<std::pair<RenderViewHost*, RenderViewHost*> >(
- &details));
+ delegate_->NotifySwappedFromRenderManager(NULL, render_view_host_);
}
}
return dest_render_view_host;
}
-void RenderViewHostManager::Stop() {
+void RenderFrameHostManager::Stop() {
render_view_host_->Stop();
// If we are cross-navigating, we should stop the pending renderers. This
@@ -191,13 +203,13 @@ void RenderViewHostManager::Stop() {
}
}
-void RenderViewHostManager::SetIsLoading(bool is_loading) {
+void RenderFrameHostManager::SetIsLoading(bool is_loading) {
render_view_host_->SetIsLoading(is_loading);
if (pending_render_view_host_)
pending_render_view_host_->SetIsLoading(is_loading);
}
-bool RenderViewHostManager::ShouldCloseTabOnUnresponsiveRenderer() {
+bool RenderFrameHostManager::ShouldCloseTabOnUnresponsiveRenderer() {
if (!cross_navigation_pending_)
return true;
@@ -229,7 +241,7 @@ bool RenderViewHostManager::ShouldCloseTabOnUnresponsiveRenderer() {
return false;
}
-void RenderViewHostManager::SwappedOut(RenderViewHost* render_view_host) {
+void RenderFrameHostManager::SwappedOut(RenderViewHost* render_view_host) {
// Make sure this is from our current RVH, and that we have a pending
// navigation from OnCrossSiteResponse. (There may be no pending navigation
// for data URLs that don't make network requests, for example.) If not,
@@ -239,8 +251,32 @@ void RenderViewHostManager::SwappedOut(RenderViewHost* render_view_host) {
return;
}
- // Now that the unload handler has run, we need to resume the paused response.
- if (pending_render_view_host_) {
+ // Now that the unload handler has run, we need to either initiate the
+ // pending transfer (if there is one) or resume the paused response (if not).
+ // TODO(creis): The blank swapped out page is visible during this time, but
+ // we can shorten this by delivering the response directly, rather than
+ // forcing an identical request to be made.
+ if (pending_nav_params_->is_transfer) {
+ // Treat the last URL in the chain as the destination and the remainder as
+ // the redirect chain.
+ CHECK(pending_nav_params_->transfer_url_chain.size());
+ GURL transfer_url = pending_nav_params_->transfer_url_chain.back();
+ pending_nav_params_->transfer_url_chain.pop_back();
+
+ // We don't know whether the original request had |user_action| set to true.
+ // However, since we force the navigation to be in the current tab, it
+ // doesn't matter.
+ render_view_host->GetDelegate()->RequestTransferURL(
+ transfer_url,
+ pending_nav_params_->transfer_url_chain,
+ pending_nav_params_->referrer,
+ pending_nav_params_->page_transition,
+ CURRENT_TAB,
+ pending_nav_params_->frame_id,
+ pending_nav_params_->global_request_id,
+ pending_nav_params_->should_replace_current_entry,
+ true);
+ } else if (pending_render_view_host_) {
RenderProcessHostImpl* pending_process =
static_cast<RenderProcessHostImpl*>(
pending_render_view_host_->GetProcess());
@@ -250,7 +286,7 @@ void RenderViewHostManager::SwappedOut(RenderViewHost* render_view_host) {
pending_nav_params_.reset();
}
-void RenderViewHostManager::DidNavigateMainFrame(
+void RenderFrameHostManager::DidNavigateMainFrame(
RenderViewHost* render_view_host) {
if (!cross_navigation_pending_) {
DCHECK(!pending_render_view_host_);
@@ -285,7 +321,7 @@ void RenderViewHostManager::DidNavigateMainFrame(
}
}
-void RenderViewHostManager::DidDisownOpener(RenderViewHost* render_view_host) {
+void RenderFrameHostManager::DidDisownOpener(RenderViewHost* render_view_host) {
// Notify all swapped out hosts, including the pending RVH.
for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin();
iter != swapped_out_hosts_.end();
@@ -296,7 +332,7 @@ void RenderViewHostManager::DidDisownOpener(RenderViewHost* render_view_host) {
}
}
-void RenderViewHostManager::RendererAbortedProvisionalLoad(
+void RenderFrameHostManager::RendererAbortedProvisionalLoad(
RenderViewHost* render_view_host) {
// We used to cancel the pending renderer here for cross-site downloads.
// However, it's not safe to do that because the download logic repeatedly
@@ -310,7 +346,7 @@ void RenderViewHostManager::RendererAbortedProvisionalLoad(
// the response is not a download.
}
-void RenderViewHostManager::RendererProcessClosing(
+void RenderFrameHostManager::RendererProcessClosing(
RenderProcessHost* render_process_host) {
// Remove any swapped out RVHs from this process, so that we don't try to
// swap them back in while the process is exiting. Start by finding them,
@@ -331,7 +367,7 @@ void RenderViewHostManager::RendererProcessClosing(
}
}
-void RenderViewHostManager::ShouldClosePage(
+void RenderFrameHostManager::ShouldClosePage(
bool for_cross_site_transition,
bool proceed,
const base::TimeTicks& proceed_time) {
@@ -362,37 +398,60 @@ void RenderViewHostManager::ShouldClosePage(
&proceed_to_fire_unload);
if (proceed_to_fire_unload) {
+ // If we're about to close the tab and there's a pending RVH, cancel it.
+ // Otherwise, if the navigation in the pending RVH completes before the
+ // close in the current RVH, we'll lose the tab close.
+ if (pending_render_view_host_) {
+ CancelPending();
+ cross_navigation_pending_ = false;
+ }
+
// This is not a cross-site navigation, the tab is being closed.
render_view_host_->ClosePage();
}
}
}
-void RenderViewHostManager::OnCrossSiteResponse(
+void RenderFrameHostManager::OnCrossSiteResponse(
RenderViewHost* pending_render_view_host,
- const GlobalRequestID& global_request_id) {
- // This should be called when the pending RVH is ready to commit.
- DCHECK_EQ(pending_render_view_host_, pending_render_view_host);
-
- // Remember the request ID until the unload handler has run.
- pending_nav_params_.reset(new PendingNavigationParams(global_request_id));
+ const GlobalRequestID& global_request_id,
+ bool is_transfer,
+ const std::vector<GURL>& transfer_url_chain,
+ const Referrer& referrer,
+ PageTransition page_transition,
+ int64 frame_id,
+ bool should_replace_current_entry) {
+ // This should be called either when the pending RVH is ready to commit or
+ // when we realize that the current RVH's request requires a transfer.
+ DCHECK(
+ pending_render_view_host == pending_render_view_host_ ||
+ pending_render_view_host == render_view_host_);
+
+ // TODO(creis): Eventually we will want to check all navigation responses
+ // here, but currently we pass information for a transfer if
+ // ShouldSwapProcessesForRedirect returned true in the network stack.
+ // In that case, we should set up a transfer after the unload handler runs.
+ // If is_transfer is false, we will just run the unload handler and resume.
+ pending_nav_params_.reset(new PendingNavigationParams(
+ global_request_id, is_transfer, transfer_url_chain, referrer,
+ page_transition, frame_id, should_replace_current_entry));
// Run the unload handler of the current page.
SwapOutOldPage();
}
-void RenderViewHostManager::SwapOutOldPage() {
- // Should only see this while we have a pending renderer.
- if (!cross_navigation_pending_)
- return;
- DCHECK(pending_render_view_host_);
-
- // First close any modal dialogs that would prevent us from swapping out.
- // TODO(creis): This is not a guarantee. The renderer could immediately
- // create another dialog in a loop, potentially causing a renderer crash when
- // we tell it to swap out with a nested message loop and PageGroupLoadDeferrer
- // on the stack. We should prevent the renderer from showing more dialogs
- // until the SwapOut. See http://crbug.com/312490.
+void RenderFrameHostManager::SwapOutOldPage() {
+ // Should only see this while we have a pending renderer or transfer.
+ CHECK(cross_navigation_pending_ || pending_nav_params_.get());
+
+ // Tell the renderer to suppress any further modal dialogs so that we can swap
+ // it out. This must be done before canceling any current dialog, in case
+ // there is a loop creating additional dialogs.
+ render_view_host_->SuppressDialogsUntilSwapOut();
+
+ // Now close any modal dialogs that would prevent us from swapping out. This
+ // must be done separately from SwapOut, so that the PageGroupLoadDeferrer is
+ // no longer on the stack when we send the SwapOut message.
delegate_->CancelModalDialogsForRenderManager();
// Tell the old renderer it is being swapped out. This will fire the unload
@@ -406,10 +465,11 @@ void RenderViewHostManager::SwapOutOldPage() {
// means it is not a download or unsafe page, and we are going to perform the
// navigation. Thus, we no longer need to remember that the RenderViewHost
// is part of a pending cross-site request.
- pending_render_view_host_->SetHasPendingCrossSiteRequest(false);
+ if (pending_render_view_host_)
+ pending_render_view_host_->SetHasPendingCrossSiteRequest(false);
}
-void RenderViewHostManager::Observe(
+void RenderFrameHostManager::Observe(
int type,
const NotificationSource& source,
const NotificationDetails& details) {
@@ -425,7 +485,7 @@ void RenderViewHostManager::Observe(
}
}
-bool RenderViewHostManager::ShouldTransitionCrossSite() {
+bool RenderFrameHostManager::ShouldTransitionCrossSite() {
// False in the single-process mode, as it makes RVHs to accumulate
// in swapped_out_hosts_.
// True if we are using process-per-site-instance (default) or
@@ -435,79 +495,103 @@ bool RenderViewHostManager::ShouldTransitionCrossSite() {
!CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab);
}
-bool RenderViewHostManager::ShouldSwapProcessesForNavigation(
- const NavigationEntry* curr_entry,
+bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation(
+ const NavigationEntry* current_entry,
const NavigationEntryImpl* new_entry) const {
DCHECK(new_entry);
+ // If new_entry already has a SiteInstance, assume it is correct and use it.
+ if (new_entry->site_instance())
+ return false;
+
// Check for reasons to swap processes even if we are in a process model that
- // doesn't usually swap (e.g., process-per-tab).
+ // doesn't usually swap (e.g., process-per-tab). Any time we return true,
+ // the new_entry will be rendered in a new SiteInstance AND BrowsingInstance.
- // For security, we should transition between processes when one is a Web UI
- // page and one isn't. If there's no curr_entry, check the current RVH's
- // site, which might already be committed to a Web UI URL (such as the NTP).
- const GURL& current_url = (curr_entry) ? curr_entry->GetURL() :
- render_view_host_->GetSiteInstance()->GetSiteURL();
+ // We use the effective URL here, since that's what is used in the
+ // SiteInstance's site and when we later call IsSameWebSite. If there is no
+ // current_entry, check the current SiteInstance's site, which might already
+ // be committed to a Web UI URL (such as the NTP).
BrowserContext* browser_context =
delegate_->GetControllerForRenderManager().GetBrowserContext();
+ const GURL& current_url = (current_entry) ?
+ SiteInstanceImpl::GetEffectiveURL(browser_context,
+ current_entry->GetURL()) :
+ render_view_host_->GetSiteInstance()->GetSiteURL();
+ const GURL& new_url = SiteInstanceImpl::GetEffectiveURL(browser_context,
+ new_entry->GetURL());
+
+ // Don't force a new BrowsingInstance for debug URLs that are handled in the
+ // renderer process, like javascript: or chrome://crash.
+ if (IsRendererDebugURL(new_url))
+ return false;
+
+ // For security, we should transition between processes when one is a Web UI
+ // page and one isn't.
if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
browser_context, current_url)) {
- // Force swap if it's not an acceptable URL for Web UI.
+ // If so, force a swap if destination is not an acceptable URL for Web UI.
// Here, data URLs are never allowed.
if (!WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
- browser_context, new_entry->GetURL(), false)) {
+ browser_context, new_url, false)) {
return true;
}
} else {
- // Force swap if it's a Web UI URL.
+ // Force a swap if it's a Web UI URL.
if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
- browser_context, new_entry->GetURL())) {
+ browser_context, new_url)) {
return true;
}
}
- if (GetContentClient()->browser()->ShouldSwapProcessesForNavigation(
- render_view_host_->GetSiteInstance(),
- curr_entry ? curr_entry->GetURL() : GURL(),
- new_entry->GetURL())) {
+ // Check with the content client as well. Important to pass current_url here,
+ // which uses the SiteInstance's site if there is no current_entry.
+ if (GetContentClient()->browser()->ShouldSwapBrowsingInstancesForNavigation(
+ render_view_host_->GetSiteInstance(), current_url, new_url)) {
return true;
}
- if (!curr_entry)
- return false;
-
// We can't switch a RenderView between view source and non-view source mode
// without screwing up the session history sometimes (when navigating between
- // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat
- // it as a new navigation). So require a view switch.
- if (curr_entry->IsViewSourceMode() != new_entry->IsViewSourceMode())
+ // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat
+ // it as a new navigation). So require a BrowsingInstance switch.
+ if (current_entry &&
+ current_entry->IsViewSourceMode() != new_entry->IsViewSourceMode())
return true;
return false;
}
-bool RenderViewHostManager::ShouldReuseWebUI(
- const NavigationEntry* curr_entry,
+bool RenderFrameHostManager::ShouldReuseWebUI(
+ const NavigationEntry* current_entry,
const NavigationEntryImpl* new_entry) const {
NavigationControllerImpl& controller =
delegate_->GetControllerForRenderManager();
- return curr_entry && web_ui_.get() &&
+ return current_entry && web_ui_.get() &&
(WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
- controller.GetBrowserContext(), curr_entry->GetURL()) ==
+ controller.GetBrowserContext(), current_entry->GetURL()) ==
WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
controller.GetBrowserContext(), new_entry->GetURL()));
}
-SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
+SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry(
const NavigationEntryImpl& entry,
- SiteInstance* curr_instance) {
- // NOTE: This is only called when ShouldTransitionCrossSite is true.
-
+ SiteInstance* current_instance,
+ bool force_browsing_instance_swap) {
+ // Determine which SiteInstance to use for navigating to |entry|.
const GURL& dest_url = entry.GetURL();
NavigationControllerImpl& controller =
delegate_->GetControllerForRenderManager();
BrowserContext* browser_context = controller.GetBrowserContext();
+ // If a swap is required, we need to force the SiteInstance AND
+ // BrowsingInstance to be different ones, using CreateForURL.
+ if (force_browsing_instance_swap) {
+ // We shouldn't be forcing a swap if an entry already has a SiteInstance.
+ CHECK(!entry.site_instance());
+ return SiteInstance::CreateForURL(browser_context, dest_url);
+ }
+
// If the entry has an instance already we should use it.
if (entry.site_instance())
return entry.site_instance();
@@ -525,23 +609,23 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerSite) &&
PageTransitionCoreTypeIs(entry.GetTransitionType(),
PAGE_TRANSITION_GENERATED)) {
- return curr_instance;
+ return current_instance;
}
- SiteInstanceImpl* curr_site_instance =
- static_cast<SiteInstanceImpl*>(curr_instance);
+ SiteInstanceImpl* current_site_instance =
+ static_cast<SiteInstanceImpl*>(current_instance);
// If we haven't used our SiteInstance (and thus RVH) yet, then we can use it
// for this entry. We won't commit the SiteInstance to this site until the
// navigation commits (in DidNavigate), unless the navigation entry was
// restored or it's a Web UI as described below.
- if (!curr_site_instance->HasSite()) {
+ if (!current_site_instance->HasSite()) {
// If we've already created a SiteInstance for our destination, we don't
// want to use this unused SiteInstance; use the existing one. (We don't
- // do this check if the curr_instance has a site, because for now, we want
- // to compare against the current URL and not the SiteInstance's site. In
- // this case, there is no current URL, so comparing against the site is ok.
- // See additional comments below.)
+ // do this check if the current_instance has a site, because for now, we
+ // want to compare against the current URL and not the SiteInstance's site.
+ // In this case, there is no current URL, so comparing against the site is
+ // ok. See additional comments below.)
//
// Also, if the URL should use process-per-site mode and there is an
// existing process for the site, we should use it. We can call
@@ -550,17 +634,17 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
bool use_process_per_site =
RenderProcessHost::ShouldUseProcessPerSite(browser_context, dest_url) &&
RenderProcessHostImpl::GetProcessHostForSite(browser_context, dest_url);
- if (curr_site_instance->HasRelatedSiteInstance(dest_url) ||
+ if (current_site_instance->HasRelatedSiteInstance(dest_url) ||
use_process_per_site) {
- return curr_site_instance->GetRelatedSiteInstance(dest_url);
+ return current_site_instance->GetRelatedSiteInstance(dest_url);
}
// For extensions, Web UI URLs (such as the new tab page), and apps we do
- // not want to use the curr_instance if it has no site, since it will have a
- // RenderProcessHost of PRIV_NORMAL. Create a new SiteInstance for this
- // URL instead (with the correct process type).
- if (curr_site_instance->HasWrongProcessForURL(dest_url))
- return curr_site_instance->GetRelatedSiteInstance(dest_url);
+ // not want to use the current_instance if it has no site, since it will
+ // have a RenderProcessHost of PRIV_NORMAL. Create a new SiteInstance for
+ // this URL instead (with the correct process type).
+ if (current_site_instance->HasWrongProcessForURL(dest_url))
+ return current_site_instance->GetRelatedSiteInstance(dest_url);
// View-source URLs must use a new SiteInstance and BrowsingInstance.
// TODO(nasko): This is the same condition as later in the function. This
@@ -585,28 +669,28 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
// we need to set the site first, otherwise after a restore none of the
// pages would share renderers in process-per-site.
if (entry.restore_type() != NavigationEntryImpl::RESTORE_NONE)
- curr_site_instance->SetSite(dest_url);
+ current_site_instance->SetSite(dest_url);
- return curr_site_instance;
+ return current_site_instance;
}
- // Otherwise, only create a new SiteInstance for cross-site navigation.
+ // Otherwise, only create a new SiteInstance for a cross-site navigation.
// TODO(creis): Once we intercept links and script-based navigations, we
// will be able to enforce that all entries in a SiteInstance actually have
// the same site, and it will be safe to compare the URL against the
// SiteInstance's site, as follows:
- // const GURL& current_url = curr_instance->site();
+ // const GURL& current_url = current_instance->site();
// For now, though, we're in a hybrid model where you only switch
// SiteInstances if you type in a cross-site URL. This means we have to
// compare the entry's URL to the last committed entry's URL.
- NavigationEntry* curr_entry = controller.GetLastCommittedEntry();
+ NavigationEntry* current_entry = controller.GetLastCommittedEntry();
if (interstitial_page_) {
// The interstitial is currently the last committed entry, but we want to
// compare against the last non-interstitial entry.
- curr_entry = controller.GetEntryAtOffset(-1);
+ current_entry = controller.GetEntryAtOffset(-1);
}
- // If there is no last non-interstitial entry (and curr_instance already
+ // If there is no last non-interstitial entry (and current_instance already
// has a site), then we must have been opened from another tab. We want
// to compare against the URL of the page that opened us, but we can't
// get to it directly. The best we can do is check against the site of
@@ -616,14 +700,17 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
// to open a new tab to an interstitial-inducing URL, and then navigates
// the page to a different same-site URL. (This seems very unlikely in
// practice.)
- const GURL& current_url = (curr_entry) ? curr_entry->GetURL() :
- curr_instance->GetSiteURL();
+ const GURL& current_url = (current_entry) ? current_entry->GetURL() :
+ current_instance->GetSiteURL();
// View-source URLs must use a new SiteInstance and BrowsingInstance.
+ // We don't need a swap when going from view-source to a debug URL like
+ // chrome://crash, however.
// TODO(creis): Refactor this method so this duplicated code isn't needed.
// See http://crbug.com/123007.
- if (curr_entry &&
- curr_entry->IsViewSourceMode() != entry.IsViewSourceMode()) {
+ if (current_entry &&
+ current_entry->IsViewSourceMode() != entry.IsViewSourceMode() &&
+ !IsRendererDebugURL(dest_url)) {
return SiteInstance::CreateForURL(browser_context, dest_url);
}
@@ -631,28 +718,19 @@ SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
// process type is correct. (The URL may have been installed as an app since
// the last time we visited it.)
if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) &&
- !static_cast<SiteInstanceImpl*>(curr_instance)->HasWrongProcessForURL(
- dest_url)) {
- return curr_instance;
- } else if (ShouldSwapProcessesForNavigation(curr_entry, &entry)) {
- // When we're swapping, we need to force the site instance AND browsing
- // instance to be different ones. This addresses special cases where we use
- // a single BrowsingInstance for all pages of a certain type (e.g., New Tab
- // Pages), keeping them in the same process. When you navigate away from
- // that page, we want to explicity ignore that BrowsingInstance and group
- // this page into the appropriate SiteInstance for its URL.
- return SiteInstance::CreateForURL(browser_context, dest_url);
- } else {
- // Start the new renderer in a new SiteInstance, but in the current
- // BrowsingInstance. It is important to immediately give this new
- // SiteInstance to a RenderViewHost (if it is different than our current
- // SiteInstance), so that it is ref counted. This will happen in
- // CreateRenderView.
- return curr_instance->GetRelatedSiteInstance(dest_url);
+ !current_site_instance->HasWrongProcessForURL(dest_url)) {
+ return current_instance;
}
+
+ // Start the new renderer in a new SiteInstance, but in the current
+ // BrowsingInstance. It is important to immediately give this new
+ // SiteInstance to a RenderViewHost (if it is different than our current
+ // SiteInstance), so that it is ref counted. This will happen in
+ // CreateRenderView.
+ return current_instance->GetRelatedSiteInstance(dest_url);
}
-int RenderViewHostManager::CreateRenderView(
+int RenderFrameHostManager::CreateRenderView(
SiteInstance* instance,
int opener_route_id,
bool swapped_out,
@@ -660,6 +738,10 @@ int RenderViewHostManager::CreateRenderView(
CHECK(instance);
DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden.
+ // We are creating a pending or swapped out RVH here. We should never create
+ // it in the same SiteInstance as our current RVH.
+ CHECK_NE(render_view_host_->GetSiteInstance(), instance);
+
// Check if we've already created an RVH for this SiteInstance. If so, try
// to re-use the existing one, which has already been initialized. We'll
// remove it from the list of swapped out hosts if it commits.
@@ -674,6 +756,7 @@ int RenderViewHostManager::CreateRenderView(
new_render_view_host = static_cast<RenderViewHostImpl*>(
RenderViewHostFactory::Create(instance,
render_view_delegate_,
+ render_frame_delegate_,
render_widget_delegate_,
MSG_ROUTING_NONE,
MSG_ROUTING_NONE,
@@ -704,40 +787,53 @@ int RenderViewHostManager::CreateRenderView(
return new_render_view_host->GetRoutingID();
}
-bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host,
- int opener_route_id) {
+bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host,
+ int opener_route_id) {
// If the pending navigation is to a WebUI and the RenderView is not in a
// guest process, tell the RenderView about any bindings it will need enabled.
- if (pending_web_ui() && !render_view_host->GetProcess()->IsGuest())
+ if (pending_web_ui() && !render_view_host->GetProcess()->IsGuest()) {
render_view_host->AllowBindings(pending_web_ui()->GetBindings());
+ } else {
+ // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
+ // process unless it's swapped out.
+ RenderViewHostImpl* rvh_impl =
+ static_cast<RenderViewHostImpl*>(render_view_host);
+ if (!rvh_impl->is_swapped_out()) {
+ CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ render_view_host->GetProcess()->GetID()));
+ }
+ }
return delegate_->CreateRenderViewForRenderManager(render_view_host,
opener_route_id);
}
-void RenderViewHostManager::CommitPending() {
+void RenderFrameHostManager::CommitPending() {
// First check whether we're going to want to focus the location bar after
// this commit. We do this now because the navigation hasn't formally
// committed yet, so if we've already cleared |pending_web_ui_| the call chain
// this triggers won't be able to figure out what's going on.
bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
- // We currently can't guarantee that the renderer isn't showing a new modal
- // dialog, even though we canceled them in SwapOutOldPage. (It may have
- // created another in the meantime.) Make sure we run and reset the callback
- // now before we delete its RVH below.
- // TODO(creis): Remove this if we can guarantee that no new dialogs will be
- // shown after SwapOutOldPage. See http://crbug.com/312490.
+ // We expect SwapOutOldPage to have canceled any modal dialogs and told the
+ // renderer to suppress any further dialogs until it is swapped out. However,
+ // crash reports indicate that it's still possible for modal dialogs to exist
+ // at this point, which poses a risk if we delete their RenderViewHost below.
+ // Cancel them again to be safe. http://crbug.com/324320.
delegate_->CancelModalDialogsForRenderManager();
// Next commit the Web UI, if any. Either replace |web_ui_| with
// |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
// leave |web_ui_| as is if reusing it.
DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get()));
- if (pending_web_ui_)
+ if (pending_web_ui_) {
web_ui_.reset(pending_web_ui_.release());
- else if (!pending_and_current_web_ui_.get())
+ } else if (!pending_and_current_web_ui_.get()) {
web_ui_.reset();
+ } else {
+ DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get());
+ pending_and_current_web_ui_.reset();
+ }
// It's possible for the pending_render_view_host_ to be NULL when we aren't
// crossing process boundaries. If so, we just needed to handle the Web UI
@@ -753,10 +849,12 @@ void RenderViewHostManager::CommitPending() {
bool focus_render_view = !will_focus_location_bar &&
render_view_host_->GetView() && render_view_host_->GetView()->HasFocus();
- // Swap in the pending view and make it active.
+ // Swap in the pending view and make it active. Also ensure the FrameTree
+ // stays in sync.
RenderViewHostImpl* old_render_view_host = render_view_host_;
render_view_host_ = pending_render_view_host_;
pending_render_view_host_ = NULL;
+ render_view_host_->AttachToFrameTree();
// The process will no longer try to exit, so we can decrement the count.
render_view_host_->GetProcess()->RemovePendingView();
@@ -783,23 +881,15 @@ void RenderViewHostManager::CommitPending() {
else if (focus_render_view && render_view_host_->GetView())
RenderWidgetHostViewPort::FromRWHV(render_view_host_->GetView())->Focus();
- std::pair<RenderViewHost*, RenderViewHost*> details =
- std::make_pair(old_render_view_host, render_view_host_);
- NotificationService::current()->Notify(
- NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
- Source<NavigationController>(
- &delegate_->GetControllerForRenderManager()),
- Details<std::pair<RenderViewHost*, RenderViewHost*> >(&details));
+ // Notify that we've swapped RenderViewHosts. We do this
+ // before shutting down the RVH so that we can clean up
+ // RendererResources related to the RVH first.
+ delegate_->NotifySwappedFromRenderManager(old_render_view_host,
+ render_view_host_);
// If the pending view was on the swapped out list, we can remove it.
swapped_out_hosts_.erase(render_view_host_->GetSiteInstance()->GetId());
- // Let the task manager know that we've swapped RenderViewHosts,
- // since it might need to update its process groupings. We do this
- // before shutting down the RVH so that we can clean up
- // RendererResources related to the RVH first.
- delegate_->NotifySwappedFromRenderManager(old_render_view_host);
-
// If there are no active RVHs in this SiteInstance, it means that
// this RVH was the last active one in the SiteInstance. Now that we
// know that all RVHs are swapped out, we can delete all the RVHs in
@@ -834,7 +924,7 @@ void RenderViewHostManager::CommitPending() {
}
}
-void RenderViewHostManager::ShutdownRenderViewHostsInSiteInstance(
+void RenderFrameHostManager::ShutdownRenderViewHostsInSiteInstance(
int32 site_instance_id) {
// First remove any swapped out RVH for this SiteInstance from our
// list.
@@ -852,34 +942,45 @@ void RenderViewHostManager::ShutdownRenderViewHostsInSiteInstance(
}
}
-RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
+RenderViewHostImpl* RenderFrameHostManager::UpdateRendererStateForNavigate(
const NavigationEntryImpl& entry) {
- // If we are cross-navigating, then we want to get back to normal and navigate
- // as usual.
+ // If we are currently navigating cross-process, we want to get back to normal
+ // and then navigate as usual.
if (cross_navigation_pending_) {
if (pending_render_view_host_)
CancelPending();
cross_navigation_pending_ = false;
}
- // render_view_host_ will not be deleted before the end of this method, so we
- // don't have to worry about this SiteInstance's ref count dropping to zero.
- SiteInstance* curr_instance = render_view_host_->GetSiteInstance();
-
- // Determine if we need a new SiteInstance for this entry.
- // Again, new_instance won't be deleted before the end of this method, so it
- // is safe to use a normal pointer here.
- SiteInstance* new_instance = curr_instance;
- const NavigationEntry* curr_entry =
+ // render_view_host_'s SiteInstance and new_instance will not be deleted
+ // before the end of this method, so we don't have to worry about their ref
+ // counts dropping to zero.
+ SiteInstance* current_instance = render_view_host_->GetSiteInstance();
+ SiteInstance* new_instance = current_instance;
+
+ // We do not currently swap processes for navigations in webview tag guests.
+ bool is_guest_scheme = current_instance->GetSiteURL().SchemeIs(kGuestScheme);
+
+ // Determine if we need a new BrowsingInstance for this entry. If true, this
+ // implies that it will get a new SiteInstance (and likely process), and that
+ // other tabs in the current BrosingInstance will be unalbe to script it.
+ // This is used for cases that require a process swap even in the
+ // process-per-tab model, such as WebUI pages.
+ const NavigationEntry* current_entry =
delegate_->GetLastCommittedNavigationEntryForRenderManager();
- bool is_guest_scheme = curr_instance->GetSiteURL().SchemeIs(
- chrome::kGuestScheme);
- bool force_swap = ShouldSwapProcessesForNavigation(curr_entry, &entry);
+ bool force_swap = !is_guest_scheme &&
+ ShouldSwapBrowsingInstancesForNavigation(current_entry, &entry);
if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap))
- new_instance = GetSiteInstanceForEntry(entry, curr_instance);
+ new_instance = GetSiteInstanceForEntry(entry, current_instance, force_swap);
+
+ // If force_swap is true, we must use a different SiteInstance. If we didn't,
+ // we would have two RenderViewHosts in the same SiteInstance and the same
+ // tab, resulting in page_id conflicts for their NavigationEntries.
+ if (force_swap)
+ CHECK_NE(new_instance, current_instance);
- if (!is_guest_scheme && (new_instance != curr_instance || force_swap)) {
- // New SiteInstance.
+ if (new_instance != current_instance) {
+ // New SiteInstance: create a pending RVH to navigate.
DCHECK(!cross_navigation_pending_);
// This will possibly create (set to NULL) a Web UI object for the pending
@@ -894,7 +995,7 @@ RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
// we are staying in the same BrowsingInstance. This allows the pending RVH
// to send cross-process script calls to its opener(s).
int opener_route_id = MSG_ROUTING_NONE;
- if (new_instance->IsRelatedSiteInstance(curr_instance)) {
+ if (new_instance->IsRelatedSiteInstance(current_instance)) {
opener_route_id =
delegate_->CreateOpenerRenderViewsForRenderManager(new_instance);
}
@@ -932,7 +1033,12 @@ RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
DCHECK(!pending_render_view_host_->are_navigations_suspended());
bool is_transfer =
entry.transferred_global_request_id() != GlobalRequestID();
- if (!is_transfer) {
+ if (is_transfer) {
+ // We don't need to stop the old renderer or run beforeunload/unload
+ // handlers, because those have already been done.
+ DCHECK(pending_nav_params_->global_request_id ==
+ entry.transferred_global_request_id());
+ } else {
// Also make sure the old render view 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.)
@@ -941,12 +1047,12 @@ RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
pending_render_view_host_->SetNavigationsSuspended(true,
base::TimeTicks());
- }
- // Tell the CrossSiteRequestManager that this RVH has a pending cross-site
- // request, so that ResourceDispatcherHost will know to tell us to run the
- // old page's unload handler before it sends the response.
- pending_render_view_host_->SetHasPendingCrossSiteRequest(true);
+ // Tell the CrossSiteRequestManager that this RVH has a pending cross-site
+ // request, so that ResourceDispatcherHost will know to tell us to run the
+ // old page's unload handler before it sends the response.
+ pending_render_view_host_->SetHasPendingCrossSiteRequest(true);
+ }
// We now have a pending RVH.
DCHECK(!cross_navigation_pending_);
@@ -960,36 +1066,35 @@ RenderViewHostImpl* RenderViewHostManager::UpdateRendererStateForNavigate(
render_view_host_->FirePageBeforeUnload(true);
return pending_render_view_host_;
+ }
+
+ // Otherwise the same SiteInstance can be used. Navigate render_view_host_.
+ DCHECK(!cross_navigation_pending_);
+ if (ShouldReuseWebUI(current_entry, &entry)) {
+ pending_web_ui_.reset();
+ pending_and_current_web_ui_ = web_ui_->AsWeakPtr();
} else {
- if (ShouldReuseWebUI(curr_entry, &entry)) {
- pending_web_ui_.reset();
- pending_and_current_web_ui_ = web_ui_->AsWeakPtr();
- } else {
- SetPendingWebUI(entry);
+ SetPendingWebUI(entry);
- // Make sure the new RenderViewHost has the right bindings.
- if (pending_web_ui())
- render_view_host_->AllowBindings(pending_web_ui()->GetBindings());
- }
+ // Make sure the new RenderViewHost has the right bindings.
+ if (pending_web_ui() && !render_view_host_->GetProcess()->IsGuest())
+ render_view_host_->AllowBindings(pending_web_ui()->GetBindings());
+ }
- if (pending_web_ui() && render_view_host_->IsRenderViewLive())
- pending_web_ui()->GetController()->RenderViewReused(render_view_host_);
+ if (pending_web_ui() && render_view_host_->IsRenderViewLive())
+ pending_web_ui()->GetController()->RenderViewReused(render_view_host_);
- // The renderer can exit view source mode when any error or cancellation
- // happen. We must overwrite to recover the mode.
- if (entry.IsViewSourceMode()) {
- render_view_host_->Send(
- new ViewMsg_EnableViewSourceMode(render_view_host_->GetRoutingID()));
- }
+ // The renderer can exit view source mode when any error or cancellation
+ // happen. We must overwrite to recover the mode.
+ if (entry.IsViewSourceMode()) {
+ render_view_host_->Send(
+ new ViewMsg_EnableViewSourceMode(render_view_host_->GetRoutingID()));
}
- // Same SiteInstance can be used. Navigate render_view_host_ if we are not
- // cross navigating.
- DCHECK(!cross_navigation_pending_);
return render_view_host_;
}
-void RenderViewHostManager::CancelPending() {
+void RenderFrameHostManager::CancelPending() {
RenderViewHostImpl* pending_render_view_host = pending_render_view_host_;
pending_render_view_host_ = NULL;
@@ -1018,7 +1123,7 @@ void RenderViewHostManager::CancelPending() {
pending_and_current_web_ui_.reset();
}
-void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) {
+void RenderFrameHostManager::RenderViewDeleted(RenderViewHost* rvh) {
// We are doing this in order to work around and to track a crasher
// (http://crbug.com/23411) where it seems that pending_render_view_host_ is
// deleted (not sure from where) but not NULLed.
@@ -1046,7 +1151,7 @@ void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) {
}
}
-bool RenderViewHostManager::IsOnSwappedOutList(RenderViewHost* rvh) const {
+bool RenderFrameHostManager::IsOnSwappedOutList(RenderViewHost* rvh) const {
if (!rvh->GetSiteInstance())
return false;
@@ -1058,7 +1163,7 @@ bool RenderViewHostManager::IsOnSwappedOutList(RenderViewHost* rvh) const {
return iter->second == rvh;
}
-RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost(
+RenderViewHostImpl* RenderFrameHostManager::GetSwappedOutRenderViewHost(
SiteInstance* instance) {
RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId());
if (iter != swapped_out_hosts_.end())
diff --git a/chromium/content/browser/web_contents/render_view_host_manager.h b/chromium/content/browser/frame_host/render_frame_host_manager.h
index 8f73610b4b5..94a4998b62f 100644
--- a/chromium/content/browser/web_contents/render_view_host_manager.h
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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_WEB_CONTENTS_RENDER_VIEW_HOST_MANAGER_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_RENDER_VIEW_HOST_MANAGER_H_
+#ifndef CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_
+#define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_
#include "base/basictypes.h"
#include "base/logging.h"
@@ -14,6 +14,7 @@
#include "content/common/content_export.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
+#include "content/public/common/referrer.h"
namespace content {
@@ -22,18 +23,18 @@ class InterstitialPageImpl;
class NavigationControllerImpl;
class NavigationEntry;
class NavigationEntryImpl;
+class RenderFrameHostDelegate;
+class RenderFrameHostManagerTest;
class RenderViewHost;
class RenderViewHostImpl;
-class RenderViewHostManagerTest;
class RenderWidgetHostDelegate;
class RenderWidgetHostView;
class TestWebContents;
class WebUIImpl;
-// Manages RenderViewHosts for a WebContentsImpl. Normally there is only one and
-// it is easy to do. But we can also have transitions of processes (and hence
-// RenderViewHosts) that can get complex.
-class CONTENT_EXPORT RenderViewHostManager
+// Manages RenderFrameHosts for a FrameTreeNode. This class acts as a state
+// machine to make cross-process navigations in a frame possible.
+class CONTENT_EXPORT RenderFrameHostManager
: public RenderViewHostDelegate::RendererManagement,
public NotificationObserver {
public:
@@ -66,7 +67,7 @@ class CONTENT_EXPORT RenderViewHostManager
virtual void UpdateRenderViewSizeForRenderManager() = 0;
virtual void CancelModalDialogsForRenderManager() = 0;
virtual void NotifySwappedFromRenderManager(
- RenderViewHost* old_render_view_host) = 0;
+ RenderViewHost* old_host, RenderViewHost* new_host) = 0;
virtual NavigationControllerImpl&
GetControllerForRenderManager() = 0;
@@ -112,11 +113,12 @@ class CONTENT_EXPORT RenderViewHostManager
// RenderViewHosts that are created.
//
// You must call Init() before using this class.
- RenderViewHostManager(
+ RenderFrameHostManager(
+ RenderFrameHostDelegate* render_frame_delegate,
RenderViewHostDelegate* render_view_delegate,
RenderWidgetHostDelegate* render_widget_delegate,
Delegate* delegate);
- virtual ~RenderViewHostManager();
+ virtual ~RenderFrameHostManager();
// For arguments, see WebContentsImpl constructor.
void Init(BrowserContext* browser_context,
@@ -218,7 +220,13 @@ class CONTENT_EXPORT RenderViewHostManager
const base::TimeTicks& proceed_time) OVERRIDE;
virtual void OnCrossSiteResponse(
RenderViewHost* pending_render_view_host,
- const GlobalRequestID& global_request_id) OVERRIDE;
+ const GlobalRequestID& global_request_id,
+ bool is_transfer,
+ const std::vector<GURL>& transfer_url_chain,
+ const Referrer& referrer,
+ PageTransition page_transition,
+ int64 frame_id,
+ bool should_replace_current_entry) OVERRIDE;
// NotificationObserver implementation.
virtual void Observe(int type,
@@ -236,21 +244,55 @@ class CONTENT_EXPORT RenderViewHostManager
RenderViewHostImpl* GetSwappedOutRenderViewHost(SiteInstance* instance);
// Runs the unload handler in the current page, when we know that a pending
- // cross-process navigation is going to commit.
+ // cross-process navigation is going to commit. We may initiate a transfer
+ // to a new process after this completes or times out.
void SwapOutOldPage();
private:
- friend class RenderViewHostManagerTest;
+ friend class RenderFrameHostManagerTest;
friend class TestWebContents;
// Tracks information about a navigation while a cross-process transition is
- // in progress.
- // TODO(creis): Add transfer navigation params for http://crbug.com/238331.
+ // in progress, in case we need to transfer it to a new RenderViewHost.
struct PendingNavigationParams {
PendingNavigationParams();
- explicit PendingNavigationParams(const GlobalRequestID& global_request_id);
-
+ PendingNavigationParams(const GlobalRequestID& global_request_id,
+ bool is_transfer,
+ const std::vector<GURL>& transfer_url,
+ Referrer referrer,
+ PageTransition page_transition,
+ int64 frame_id,
+ bool should_replace_current_entry);
+ ~PendingNavigationParams();
+
+ // The child ID and request ID for the pending navigation. Present whether
+ // |is_transfer| is true or false.
GlobalRequestID global_request_id;
+
+ // Whether this pending navigation needs to be transferred to another
+ // process than the one it was going to commit in. If so, the
+ // |transfer_url|, |referrer|, and |frame_id| parameters will be set.
+ bool is_transfer;
+
+ // If |is_transfer|, this is the URL chain of the request. The first entry
+ // is the original request URL, and the last entry is the destination URL to
+ // request in the new process.
+ std::vector<GURL> transfer_url_chain;
+
+ // If |is_transfer|, this is the referrer to use for the request in the new
+ // process.
+ Referrer referrer;
+
+ // If |is_transfer|, this is the transition type for the original
+ // navigation.
+ PageTransition page_transition;
+
+ // If |is_transfer|, this is the frame ID to use in RequestTransferURL.
+ int64 frame_id;
+
+ // If |is_transfer|, this is whether the navigation should replace the
+ // current history entry.
+ bool should_replace_current_entry;
};
// Returns whether this tab should transition to a new renderer for
@@ -258,26 +300,30 @@ class CONTENT_EXPORT RenderViewHostManager
// switch. Can be overridden in unit tests.
bool ShouldTransitionCrossSite();
- // Returns true if the two navigation entries are incompatible in some way
- // other than site instances. Cases where this can happen include Web UI
- // to regular web pages. It will cause us to swap RenderViewHosts (and hence
- // RenderProcessHosts) even if the site instance would otherwise be the same.
- // As part of this, we'll also force new SiteInstances and BrowsingInstances.
+ // Returns true if for the navigation from |current_entry| to |new_entry|,
+ // a new SiteInstance and BrowsingInstance should be created (even if we are
+ // in a process model that doesn't usually swap). This forces a process swap
+ // and severs script connections with existing tabs. Cases where this can
+ // happen include transitions between WebUI and regular web pages.
// Either of the entries may be NULL.
- bool ShouldSwapProcessesForNavigation(
- const NavigationEntry* curr_entry,
+ bool ShouldSwapBrowsingInstancesForNavigation(
+ const NavigationEntry* current_entry,
const NavigationEntryImpl* new_entry) const;
+ // Returns true if it is safe to reuse the current WebUI when navigating from
+ // |current_entry| to |new_entry|.
bool ShouldReuseWebUI(
- const NavigationEntry* curr_entry,
+ const NavigationEntry* current_entry,
const NavigationEntryImpl* new_entry) const;
// Returns an appropriate SiteInstance object for the given NavigationEntry,
- // possibly reusing the current SiteInstance.
- // Never called if --process-per-tab is used.
+ // possibly reusing the current SiteInstance. If --process-per-tab is used,
+ // this is only called when ShouldSwapBrowsingInstancesForNavigation returns
+ // true.
SiteInstance* GetSiteInstanceForEntry(
const NavigationEntryImpl& entry,
- SiteInstance* curr_instance);
+ SiteInstance* current_instance,
+ bool force_browsing_instance_swap);
// Sets up the necessary state for a new RenderViewHost with the given opener.
bool InitRenderView(RenderViewHost* render_view_host, int opener_route_id);
@@ -312,6 +358,7 @@ class CONTENT_EXPORT RenderViewHostManager
// Implemented by the owner of this class, these delegates are installed into
// all the RenderViewHosts that we create.
+ RenderFrameHostDelegate* render_frame_delegate_;
RenderViewHostDelegate* render_view_delegate_;
RenderWidgetHostDelegate* render_widget_delegate_;
@@ -354,9 +401,9 @@ class CONTENT_EXPORT RenderViewHostManager
NotificationRegistrar registrar_;
- DISALLOW_COPY_AND_ASSIGN(RenderViewHostManager);
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameHostManager);
};
} // namespace content
-#endif // CONTENT_BROWSER_WEB_CONTENTS_RENDER_VIEW_HOST_MANAGER_H_
+#endif // CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_
diff --git a/chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc b/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index 55785d07859..5692fac8745 100644
--- a/chromium/content/browser/renderer_host/render_view_host_manager_browsertest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -1,15 +1,19 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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 <set>
+
#include "base/json/json_reader.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/browser/webui/web_ui_impl.h"
#include "content/common/content_constants_internal.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
@@ -18,7 +22,6 @@
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host_observer.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/url_constants.h"
@@ -33,9 +36,9 @@
namespace content {
-class RenderViewHostManagerTest : public ContentBrowserTest {
+class RenderFrameHostManagerTest : public ContentBrowserTest {
public:
- RenderViewHostManagerTest() {}
+ RenderFrameHostManagerTest() {}
static bool GetFilePathWithHostAndPortReplacement(
const std::string& original_file_path,
@@ -50,7 +53,7 @@ class RenderViewHostManagerTest : public ContentBrowserTest {
};
// Web pages should not have script access to the swapped out page.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
DISABLED_NoScriptAccessAfterSwapOut) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
@@ -118,7 +121,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Test for crbug.com/24447. Following a cross-site link with rel=noreferrer
// and target=_blank should create a new SiteInstance.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
SwapProcessWithRelNoreferrerAndTargetBlank) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
@@ -172,7 +175,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// As of crbug.com/69267, we create a new BrowsingInstance (and SiteInstance)
// for rel=noreferrer links in new windows, even to same site pages and named
// targets.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
SwapProcessWithSameSiteRelNoreferrer) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
@@ -226,7 +229,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Test for crbug.com/24447. Following a cross-site link with just
// target=_blank should not create a new SiteInstance.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
DontSwapProcessWithOnlyTargetBlank) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
@@ -274,7 +277,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Test for crbug.com/24447. Following a cross-site link with rel=noreferrer
// and no target=_blank should not create a new SiteInstance.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
DontSwapProcessWithOnlyRelNoreferrer) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
@@ -319,31 +322,9 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
EXPECT_EQ(orig_site_instance, noref_site_instance);
}
-namespace {
-
-class WebContentsDestroyedObserver : public WebContentsObserver {
- public:
- WebContentsDestroyedObserver(WebContents* web_contents,
- const base::Closure& callback)
- : WebContentsObserver(web_contents),
- callback_(callback) {
- }
-
- virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
- callback_.Run();
- }
-
- private:
- base::Closure callback_;
-
- DISALLOW_COPY_AND_ASSIGN(WebContentsDestroyedObserver);
-};
-
-} // namespace
-
// Test for crbug.com/116192. Targeted links should still work after the
// named target window has swapped processes.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
AllowTargetedNavigationsAfterSwap) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
@@ -411,15 +392,13 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
NavigateToURL(new_shell, https_server.GetURL("files/title1.html"));
EXPECT_EQ(new_site_instance,
new_shell->web_contents()->GetSiteInstance());
- scoped_refptr<MessageLoopRunner> loop_runner(new MessageLoopRunner);
- WebContentsDestroyedObserver close_observer(new_shell->web_contents(),
- loop_runner->QuitClosure());
+ WebContentsDestroyedWatcher close_watcher(new_shell->web_contents());
EXPECT_TRUE(ExecuteScriptAndExtractBool(
shell()->web_contents(),
"window.domAutomationController.send(testCloseWindow());",
&success));
EXPECT_TRUE(success);
- loop_runner->Run();
+ close_watcher.Wait();
}
// Test that setting the opener to null in a window affects cross-process
@@ -430,7 +409,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
#else
#define MAYBE_DisownOpener DisownOpener
#endif
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, MAYBE_DisownOpener) {
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_DisownOpener) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
net::SpawnedTestServer https_server(
@@ -506,7 +485,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, MAYBE_DisownOpener) {
}
// Test that subframes can disown their openers. http://crbug.com/225528.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, DisownSubframeOpener) {
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, DisownSubframeOpener) {
const GURL frame_url("data:text/html,<iframe name=\"foo\"></iframe>");
NavigateToURL(shell(), frame_url);
@@ -528,7 +507,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, DisownSubframeOpener) {
// 4) Post a message from _blank to "foo".
// 5) Post a message from "foo" to a subframe of opener, which replies back.
// 6) Post a message from _blank to a subframe of "foo".
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
SupportCrossProcessPostMessage) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
@@ -551,7 +530,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
scoped_refptr<SiteInstance> orig_site_instance(
opener_contents->GetSiteInstance());
EXPECT_TRUE(orig_site_instance.get() != NULL);
- RenderViewHostManager* opener_manager = static_cast<WebContentsImpl*>(
+ RenderFrameHostManager* opener_manager = static_cast<WebContentsImpl*>(
opener_contents)->GetRenderManagerForTesting();
// 1) Open two more windows, one named. These initially have openers but no
@@ -594,7 +573,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
EXPECT_EQ("/files/title2.html", new_contents->GetLastCommittedURL().path());
NavigateToURL(new_shell2, test_server()->GetURL("files/post_message.html"));
EXPECT_EQ(orig_site_instance, new_contents->GetSiteInstance());
- RenderViewHostManager* new_manager =
+ RenderFrameHostManager* new_manager =
static_cast<WebContentsImpl*>(new_contents)->GetRenderManagerForTesting();
// We now have three windows. The opener should have a swapped out RVH
@@ -619,9 +598,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// 3) Post a message from the foo window to the opener. The opener will
// reply, causing the foo window to update its own title.
- WindowedNotificationObserver title_observer(
- NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
- Source<WebContents>(foo_contents));
+ base::string16 expected_title = ASCIIToUTF16("msg");
+ TitleWatcher title_watcher(foo_contents, expected_title);
EXPECT_TRUE(ExecuteScriptAndExtractBool(
foo_contents,
"window.domAutomationController.send(postToOpener('msg','*'));",
@@ -629,7 +607,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
EXPECT_TRUE(success);
ASSERT_FALSE(
opener_manager->GetSwappedOutRenderViewHost(orig_site_instance.get()));
- title_observer.Wait();
+ ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
// We should have received only 1 message in the opener and "foo" tabs,
// and updated the title.
@@ -649,16 +627,14 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// 4) Now post a message from the _blank window to the foo window. The
// foo window will update its title and will not reply.
- WindowedNotificationObserver title_observer2(
- NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
- Source<WebContents>(foo_contents));
+ expected_title = ASCIIToUTF16("msg2");
+ TitleWatcher title_watcher2(foo_contents, expected_title);
EXPECT_TRUE(ExecuteScriptAndExtractBool(
new_contents,
"window.domAutomationController.send(postToFoo('msg2'));",
&success));
EXPECT_TRUE(success);
- title_observer2.Wait();
- EXPECT_EQ(ASCIIToUTF16("msg2"), foo_contents->GetTitle());
+ ASSERT_EQ(expected_title, title_watcher2.WaitAndGetTitle());
// This postMessage should have created a swapped out RVH for the new
// SiteInstance in the target=_blank window.
@@ -669,9 +645,112 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// http://crbug.com/153701 is fixed.
}
+// Test for crbug.com/278336. MessagePorts should work cross-process. I.e.,
+// messages which contain Transferables and get intercepted by
+// RenderViewImpl::willCheckAndDispatchMessageEvent (because the RenderView is
+// swapped out) should work.
+// Specifically:
+// 1) Create 2 windows (opener and "foo") and send "foo" cross-process.
+// 2) Post a message containing a message port from opener to "foo".
+// 3) Post a message from "foo" back to opener via the passed message port.
+// The test will be enabled when the feature implementation lands.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ SupportCrossProcessPostMessageWithMessagePort) {
+ // Start two servers with different sites.
+ ASSERT_TRUE(test_server()->Start());
+ net::SpawnedTestServer https_server(
+ net::SpawnedTestServer::TYPE_HTTPS,
+ net::SpawnedTestServer::kLocalhost,
+ base::FilePath(FILE_PATH_LITERAL("content/test/data")));
+ ASSERT_TRUE(https_server.Start());
+
+ // Load a page with links that open in a new window.
+ std::string replacement_path;
+ ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
+ "files/click-noreferrer-links.html",
+ https_server.host_port_pair(),
+ &replacement_path));
+ NavigateToURL(shell(), test_server()->GetURL(replacement_path));
+
+ // Get the original SiteInstance and RVHM for later comparison.
+ WebContents* opener_contents = shell()->web_contents();
+ scoped_refptr<SiteInstance> orig_site_instance(
+ opener_contents->GetSiteInstance());
+ EXPECT_TRUE(orig_site_instance.get() != NULL);
+ RenderFrameHostManager* opener_manager = static_cast<WebContentsImpl*>(
+ opener_contents)->GetRenderManagerForTesting();
+
+ // 1) Open a named target=foo window. We will later post a message between the
+ // opener and the new window.
+ ShellAddedObserver new_shell_observer;
+ bool success = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ opener_contents,
+ "window.domAutomationController.send(clickSameSiteTargetedLink());",
+ &success));
+ EXPECT_TRUE(success);
+ Shell* new_shell = new_shell_observer.GetShell();
+
+ // Wait for the navigation in the new window to finish, if it hasn't, then
+ // send it to post_message.html on a different site.
+ WebContents* foo_contents = new_shell->web_contents();
+ WaitForLoadStop(foo_contents);
+ EXPECT_EQ("/files/navigate_opener.html",
+ foo_contents->GetLastCommittedURL().path());
+ NavigateToURL(
+ new_shell,
+ https_server.GetURL("files/post_message.html"));
+ scoped_refptr<SiteInstance> foo_site_instance(
+ foo_contents->GetSiteInstance());
+ EXPECT_NE(orig_site_instance, foo_site_instance);
+
+ // We now have two windows. The opener should have a swapped out RVH
+ // for the new SiteInstance.
+ EXPECT_EQ(2u, Shell::windows().size());
+ EXPECT_TRUE(
+ opener_manager->GetSwappedOutRenderViewHost(foo_site_instance.get()));
+
+ // 2) Post a message containing a MessagePort from opener to the the foo
+ // window. The foo window will reply via the passed port, causing the opener
+ // to update its own title.
+ WindowedNotificationObserver title_observer(
+ NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
+ Source<WebContents>(opener_contents));
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ opener_contents,
+ "window.domAutomationController.send(postWithPortToFoo());",
+ &success));
+ EXPECT_TRUE(success);
+ ASSERT_FALSE(
+ opener_manager->GetSwappedOutRenderViewHost(orig_site_instance.get()));
+ title_observer.Wait();
+
+ // Check message counts.
+ int opener_received_messages_via_port = 0;
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(
+ opener_contents,
+ "window.domAutomationController.send(window.receivedMessagesViaPort);",
+ &opener_received_messages_via_port));
+ int foo_received_messages = 0;
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(
+ foo_contents,
+ "window.domAutomationController.send(window.receivedMessages);",
+ &foo_received_messages));
+ int foo_received_messages_with_port = 0;
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(
+ foo_contents,
+ "window.domAutomationController.send(window.receivedMessagesWithPort);",
+ &foo_received_messages_with_port));
+ EXPECT_EQ(1, foo_received_messages);
+ EXPECT_EQ(1, foo_received_messages_with_port);
+ EXPECT_EQ(1, opener_received_messages_via_port);
+ EXPECT_EQ(ASCIIToUTF16("msg-with-port"), foo_contents->GetTitle());
+ EXPECT_EQ(ASCIIToUTF16("msg-back-via-port"), opener_contents->GetTitle());
+}
+
// Test for crbug.com/116192. Navigations to a window's opener should
// still work after a process swap.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
AllowTargetedNavigationsInOpenerAfterSwap) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
@@ -739,7 +818,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Test that opening a new window in the same SiteInstance and then navigating
// both windows to a different SiteInstance allows the first process to exit.
// See http://crbug.com/126333.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
ProcessExitWithSwappedOutViews) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
@@ -807,7 +886,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Test for crbug.com/76666. A cross-site navigation that fails with a 204
// error should not make us ignore future renderer-initiated navigations.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ClickLinkAfter204Error) {
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ClickLinkAfter204Error) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
net::SpawnedTestServer https_server(
@@ -871,7 +950,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ClickLinkAfter204Error) {
// initiated navigation in a new tab, until the content of the initial
// about:blank page is modified by another window. At that point, we should
// revert to showing about:blank to prevent a URL spoof.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ShowLoadingURLUntilSpoof) {
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ShowLoadingURLUntilSpoof) {
ASSERT_TRUE(test_server()->Start());
// Load a page that can open a URL that won't commit in a new window.
@@ -900,17 +979,15 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ShowLoadingURLUntilSpoof) {
// Now modify the contents of the new window from the opener. This will also
// modify the title of the document to give us something to listen for.
- WindowedNotificationObserver title_observer(
- NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
- Source<WebContents>(contents));
+ base::string16 expected_title = ASCIIToUTF16("Modified Title");
+ TitleWatcher title_watcher(contents, expected_title);
success = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
orig_contents,
"window.domAutomationController.send(modifyNewWindow());",
&success));
EXPECT_TRUE(success);
- title_observer.Wait();
- EXPECT_EQ(ASCIIToUTF16("Modified Title"), contents->GetTitle());
+ ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
// At this point, we should no longer be showing the destination URL.
// The visible entry should be null, resulting in about:blank in the address
@@ -922,7 +999,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ShowLoadingURLUntilSpoof) {
// initiated navigation in a new tab if it is not the initial navigation. In
// this case, the renderer will not notify us of a modification, so we cannot
// show the pending URL without allowing a spoof.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
DontShowLoadingURLIfNotInitialNav) {
ASSERT_TRUE(test_server()->Start());
@@ -956,7 +1033,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
// Test for http://crbug.com/93427. Ensure that cross-site navigations
// do not cause back/forward navigations to be considered stale by the
// renderer.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, BackForwardNotStale) {
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, BackForwardNotStale) {
NavigateToURL(shell(), GURL(kAboutBlankURL));
// Start two servers with different sites.
@@ -1054,7 +1131,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, BackForwardNotStale) {
// Test for http://crbug.com/130016.
// Swapping out a render view should update its visiblity state.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
SwappedOutViewHasCorrectVisibilityState) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
@@ -1092,7 +1169,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
EXPECT_TRUE(ExecuteScriptAndExtractBool(
rvh,
"window.domAutomationController.send("
- " document.webkitVisibilityState == 'visible');",
+ " document.visibilityState == 'visible');",
&success));
EXPECT_TRUE(success);
@@ -1103,7 +1180,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
EXPECT_TRUE(ExecuteScriptAndExtractBool(
rvh,
"window.domAutomationController.send("
- " document.webkitVisibilityState == 'hidden');",
+ " document.visibilityState == 'hidden');",
&success));
EXPECT_TRUE(success);
@@ -1123,55 +1200,32 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
EXPECT_TRUE(ExecuteScriptAndExtractBool(
rvh,
"window.domAutomationController.send("
- " document.webkitVisibilityState == 'visible');",
+ " document.visibilityState == 'visible');",
&success));
EXPECT_TRUE(success);
}
-// This class holds onto RenderViewHostObservers for as long as their observed
-// RenderViewHosts are alive. This allows us to confirm that all hosts have
-// properly been shutdown.
-class RenderViewHostObserverArray {
+// This class ensures that all the given RenderViewHosts have properly been
+// shutdown.
+class RenderViewHostDestructionObserver : public WebContentsObserver {
public:
- ~RenderViewHostObserverArray() {
- // In case some would be left in there with a dead pointer to us.
- for (std::list<RVHObserver*>::iterator iter = observers_.begin();
- iter != observers_.end(); ++iter) {
- (*iter)->ClearParent();
- }
- }
- void AddObserverToRVH(RenderViewHost* rvh) {
- observers_.push_back(new RVHObserver(this, rvh));
+ explicit RenderViewHostDestructionObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+ virtual ~RenderViewHostDestructionObserver() {}
+ void EnsureRVHGetsDestructed(RenderViewHost* rvh) {
+ watched_render_view_hosts_.insert(rvh);
}
- size_t GetNumObservers() const {
- return observers_.size();
+ size_t GetNumberOfWatchedRenderViewHosts() const {
+ return watched_render_view_hosts_.size();
}
private:
- friend class RVHObserver;
- class RVHObserver : public RenderViewHostObserver {
- public:
- RVHObserver(RenderViewHostObserverArray* parent, RenderViewHost* rvh)
- : RenderViewHostObserver(rvh),
- parent_(parent) {
- }
- virtual void RenderViewHostDestroyed(RenderViewHost* rvh) OVERRIDE {
- if (parent_)
- parent_->RemoveObserver(this);
- RenderViewHostObserver::RenderViewHostDestroyed(rvh);
- };
- void ClearParent() {
- parent_ = NULL;
- }
- private:
- RenderViewHostObserverArray* parent_;
- };
-
- void RemoveObserver(RVHObserver* observer) {
- observers_.remove(observer);
+ // WebContentsObserver implementation:
+ virtual void RenderViewDeleted(RenderViewHost* rvh) OVERRIDE {
+ watched_render_view_hosts_.erase(rvh);
}
- std::list<RVHObserver*> observers_;
+ std::set<RenderViewHost*> watched_render_view_hosts_;
};
// Test for crbug.com/90867. Make sure we don't leak render view hosts since
@@ -1179,7 +1233,7 @@ class RenderViewHostObserverArray {
// delegate_. This test also verifies crbug.com/117420 and crbug.com/143255 to
// ensure that a separate SiteInstance is created when navigating to view-source
// URLs, regardless of current URL.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, LeakingRenderViewHosts) {
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, LeakingRenderViewHosts) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
net::SpawnedTestServer https_server(
@@ -1189,7 +1243,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, LeakingRenderViewHosts) {
ASSERT_TRUE(https_server.Start());
// Observe the created render_view_host's to make sure they will not leak.
- RenderViewHostObserverArray rvh_observers;
+ RenderViewHostDestructionObserver rvh_observers(shell()->web_contents());
GURL navigated_url(test_server()->GetURL("files/title2.html"));
GURL view_source_url(kViewSourceScheme + std::string(":") +
@@ -1201,7 +1255,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, LeakingRenderViewHosts) {
SiteInstance* blank_site_instance = blank_rvh->GetSiteInstance();
EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), GURL::EmptyGURL());
EXPECT_EQ(blank_site_instance->GetSiteURL(), GURL::EmptyGURL());
- rvh_observers.AddObserverToRVH(blank_rvh);
+ rvh_observers.EnsureRVHGetsDestructed(blank_rvh);
// Now navigate to the view-source URL and ensure we got a different
// SiteInstance and RenderViewHost.
@@ -1209,7 +1263,8 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, LeakingRenderViewHosts) {
EXPECT_NE(blank_rvh, shell()->web_contents()->GetRenderViewHost());
EXPECT_NE(blank_site_instance, shell()->web_contents()->
GetRenderViewHost()->GetSiteInstance());
- rvh_observers.AddObserverToRVH(shell()->web_contents()->GetRenderViewHost());
+ rvh_observers.EnsureRVHGetsDestructed(
+ shell()->web_contents()->GetRenderViewHost());
// Load a random page and then navigate to view-source: of it.
// This used to cause two RVH instances for the same SiteInstance, which
@@ -1217,10 +1272,12 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, LeakingRenderViewHosts) {
NavigateToURL(shell(), navigated_url);
SiteInstance* site_instance1 = shell()->web_contents()->
GetRenderViewHost()->GetSiteInstance();
- rvh_observers.AddObserverToRVH(shell()->web_contents()->GetRenderViewHost());
+ rvh_observers.EnsureRVHGetsDestructed(
+ shell()->web_contents()->GetRenderViewHost());
NavigateToURL(shell(), view_source_url);
- rvh_observers.AddObserverToRVH(shell()->web_contents()->GetRenderViewHost());
+ rvh_observers.EnsureRVHGetsDestructed(
+ shell()->web_contents()->GetRenderViewHost());
SiteInstance* site_instance2 = shell()->web_contents()->
GetRenderViewHost()->GetSiteInstance();
@@ -1229,14 +1286,15 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, LeakingRenderViewHosts) {
// Now navigate to a different instance so that we swap out again.
NavigateToURL(shell(), https_server.GetURL("files/title2.html"));
- rvh_observers.AddObserverToRVH(shell()->web_contents()->GetRenderViewHost());
+ rvh_observers.EnsureRVHGetsDestructed(
+ shell()->web_contents()->GetRenderViewHost());
// This used to leak a render view host.
shell()->Close();
RunAllPendingInMessageLoop(); // Needed on ChromeOS.
- EXPECT_EQ(0U, rvh_observers.GetNumObservers());
+ EXPECT_EQ(0U, rvh_observers.GetNumberOfWatchedRenderViewHosts());
}
// Test for crbug.com/143155. Frame tree updates during unload should not
@@ -1250,7 +1308,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, LeakingRenderViewHosts) {
// This used to cause an update to the frame tree of the swapped out RV,
// just as it was navigating to a real page. That pre-empted the real
// navigation and visibly sent the tab to swappedout://.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
DontPreemptNavigationWithFrameTreeUpdate) {
// Start two servers with different sites.
ASSERT_TRUE(test_server()->Start());
@@ -1302,4 +1360,96 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
EXPECT_EQ(new_site_instance, shell()->web_contents()->GetSiteInstance());
}
+// Ensure that renderer-side debug URLs do not cause a process swap, since they
+// are meant to run in the current page. We had a bug where we expected a
+// BrowsingInstance swap to occur on pages like view-source and extensions,
+// which broke chrome://crash and javascript: URLs.
+// See http://crbug.com/335503.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, RendererDebugURLsDontSwap) {
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL original_url(test_server()->GetURL("files/title2.html"));
+ GURL view_source_url(kViewSourceScheme + std::string(":") +
+ original_url.spec());
+
+ NavigateToURL(shell(), view_source_url);
+
+ // Check that javascript: URLs work.
+ base::string16 expected_title = ASCIIToUTF16("msg");
+ TitleWatcher title_watcher(shell()->web_contents(), expected_title);
+ shell()->LoadURL(GURL("javascript:document.title='msg'"));
+ ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+
+ // Crash the renderer of the view-source page.
+ RenderProcessHost* process = shell()->web_contents()->GetRenderProcessHost();
+ WindowedNotificationObserver crash_observer(
+ NOTIFICATION_RENDERER_PROCESS_CLOSED,
+ Source<RenderProcessHost>(process));
+ NavigateToURL(shell(), GURL(kChromeUICrashURL));
+ crash_observer.Wait();
+}
+
+// Ensure that renderer-side debug URLs don't take effect on crashed renderers.
+// Otherwise, we might try to load an unprivileged about:blank page into a
+// WebUI-enabled RenderProcessHost, failing a safety check in InitRenderView.
+// See http://crbug.com/334214.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ IgnoreRendererDebugURLsWhenCrashed) {
+ // Visit a WebUI page with bindings.
+ GURL webui_url = GURL(std::string(chrome::kChromeUIScheme) + "://" +
+ std::string(kChromeUIGpuHost));
+ NavigateToURL(shell(), webui_url);
+ RenderProcessHost* process = shell()->web_contents()->GetRenderProcessHost();
+ EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ process->GetID()));
+
+ // Crash the renderer of the WebUI page.
+ WindowedNotificationObserver crash_observer(
+ NOTIFICATION_RENDERER_PROCESS_CLOSED,
+ Source<RenderProcessHost>(process));
+ NavigateToURL(shell(), GURL(kChromeUICrashURL));
+ crash_observer.Wait();
+
+ // Load the crash URL again but don't wait for any action. If it is not
+ // ignored this time, we will fail the WebUI CHECK in InitRenderView.
+ shell()->LoadURL(GURL(kChromeUICrashURL));
+
+ // Ensure that such URLs can still work as the initial navigation of a tab.
+ // We postpone the initial navigation of the tab using an empty GURL, so that
+ // we can add a watcher for crashes.
+ Shell* shell2 = Shell::CreateNewWindow(
+ shell()->web_contents()->GetBrowserContext(), GURL(), NULL,
+ MSG_ROUTING_NONE, gfx::Size());
+ RenderProcessHost* process2 = shell2->web_contents()->GetRenderProcessHost();
+ WindowedNotificationObserver crash_observer2(
+ NOTIFICATION_RENDERER_PROCESS_CLOSED,
+ Source<RenderProcessHost>(process2));
+ NavigateToURL(shell2, GURL(kChromeUIKillURL));
+ crash_observer2.Wait();
+}
+
+// Ensure that pending_and_current_web_ui_ is cleared when a URL commits.
+// Otherwise it might get picked up by InitRenderView when granting bindings
+// to other RenderViewHosts. See http://crbug.com/330811.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ClearPendingWebUIOnCommit) {
+ // Visit a WebUI page with bindings.
+ GURL webui_url(GURL(std::string(chrome::kChromeUIScheme) + "://" +
+ std::string(kChromeUIGpuHost)));
+ NavigateToURL(shell(), webui_url);
+ EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ shell()->web_contents()->GetRenderProcessHost()->GetID()));
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ shell()->web_contents());
+ WebUIImpl* webui = web_contents->GetRenderManagerForTesting()->web_ui();
+ EXPECT_TRUE(webui);
+ EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->pending_web_ui());
+
+ // Navigate to another WebUI URL that reuses the WebUI object. Make sure we
+ // clear pending_web_ui() when it commits.
+ GURL webui_url2(webui_url.spec() + "#foo");
+ NavigateToURL(shell(), webui_url2);
+ EXPECT_EQ(webui, web_contents->GetRenderManagerForTesting()->web_ui());
+ EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->pending_web_ui());
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/render_view_host_manager_unittest.cc b/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
index d8837ebc5cc..2ba5fb8493a 100644
--- a/chromium/content/browser/web_contents/render_view_host_manager_unittest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -1,13 +1,12 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/strings/utf_string_conversions.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/render_frame_host_manager.h"
#include "content/browser/site_instance_impl.h"
-#include "content/browser/web_contents/navigation_controller_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
-#include "content/browser/web_contents/render_view_host_manager.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/view_messages.h"
#include "content/public/browser/notification_details.h"
@@ -15,8 +14,9 @@
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host_observer.h"
#include "content/public/browser/render_widget_host_iterator.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/javascript_message_type.h"
@@ -27,19 +27,20 @@
#include "content/public/test/test_notification_tracker.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_content_client.h"
+#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
-class RenderViewHostManagerTestWebUIControllerFactory
+class RenderFrameHostManagerTestWebUIControllerFactory
: public WebUIControllerFactory {
public:
- RenderViewHostManagerTestWebUIControllerFactory()
+ RenderFrameHostManagerTestWebUIControllerFactory()
: should_create_webui_(false) {
}
- virtual ~RenderViewHostManagerTestWebUIControllerFactory() {}
+ virtual ~RenderFrameHostManagerTestWebUIControllerFactory() {}
void set_should_create_webui(bool should_create_webui) {
should_create_webui_ = should_create_webui;
@@ -71,12 +72,27 @@ class RenderViewHostManagerTestWebUIControllerFactory
private:
bool should_create_webui_;
- DISALLOW_COPY_AND_ASSIGN(RenderViewHostManagerTestWebUIControllerFactory);
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameHostManagerTestWebUIControllerFactory);
+};
+
+class BeforeUnloadFiredWebContentsDelegate : public WebContentsDelegate {
+ public:
+ BeforeUnloadFiredWebContentsDelegate() {}
+ virtual ~BeforeUnloadFiredWebContentsDelegate() {}
+
+ virtual void BeforeUnloadFired(WebContents* web_contents,
+ bool proceed,
+ bool* proceed_to_fire_unload) OVERRIDE {
+ *proceed_to_fire_unload = proceed;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BeforeUnloadFiredWebContentsDelegate);
};
} // namespace
-class RenderViewHostManagerTest
+class RenderFrameHostManagerTest
: public RenderViewHostImplTestHarness {
public:
virtual void SetUp() OVERRIDE {
@@ -117,10 +133,11 @@ class RenderViewHostManagerTest
active_test_rvh()->SendNavigate(max_page_id + 1, url);
}
- bool ShouldSwapProcesses(RenderViewHostManager* manager,
- const NavigationEntryImpl* cur_entry,
+ bool ShouldSwapProcesses(RenderFrameHostManager* manager,
+ const NavigationEntryImpl* current_entry,
const NavigationEntryImpl* new_entry) const {
- return manager->ShouldSwapProcessesForNavigation(cur_entry, new_entry);
+ return manager->ShouldSwapBrowsingInstancesForNavigation(current_entry,
+ new_entry);
}
// Creates a test RenderViewHost that's swapped out.
@@ -160,14 +177,14 @@ class RenderViewHostManagerTest
}
private:
- RenderViewHostManagerTestWebUIControllerFactory factory_;
+ RenderFrameHostManagerTestWebUIControllerFactory factory_;
};
// Tests that when you navigate from a chrome:// url to another page, and
// then do that same thing in another tab, that the two resulting pages have
// different SiteInstances, BrowsingInstances, and RenderProcessHosts. This is
// a regression test for bug 9364.
-TEST_F(RenderViewHostManagerTest, NewTabPageProcesses) {
+TEST_F(RenderFrameHostManagerTest, NewTabPageProcesses) {
set_should_create_webui(true);
const GURL kChromeUrl("chrome://foo");
const GURL kDestUrl("http://www.google.com/");
@@ -233,7 +250,7 @@ TEST_F(RenderViewHostManagerTest, NewTabPageProcesses) {
// action on requests from a non-active renderer. The main exception is
// for synchronous messages, which cannot be ignored without leaving the
// renderer in a stuck state. See http://crbug.com/93427.
-TEST_F(RenderViewHostManagerTest, FilterMessagesWhileSwappedOut) {
+TEST_F(RenderFrameHostManagerTest, FilterMessagesWhileSwappedOut) {
const GURL kChromeURL("chrome://foo");
const GURL kDestUrl("http://www.google.com/");
@@ -243,8 +260,8 @@ TEST_F(RenderViewHostManagerTest, FilterMessagesWhileSwappedOut) {
contents()->GetRenderManagerForTesting()->current_host());
// Send an update title message and make sure it works.
- const string16 ntp_title = ASCIIToUTF16("NTP Title");
- WebKit::WebTextDirection direction = WebKit::WebTextDirectionLeftToRight;
+ const base::string16 ntp_title = ASCIIToUTF16("NTP Title");
+ blink::WebTextDirection direction = blink::WebTextDirectionLeftToRight;
EXPECT_TRUE(ntp_rvh->OnMessageReceived(
ViewHostMsg_UpdateTitle(rvh()->GetRoutingID(), 0, ntp_title, direction)));
EXPECT_EQ(ntp_title, contents()->GetTitle());
@@ -271,7 +288,7 @@ TEST_F(RenderViewHostManagerTest, FilterMessagesWhileSwappedOut) {
dest_rvh->SendNavigate(101, kDestUrl);
// The new RVH should be able to update its title.
- const string16 dest_title = ASCIIToUTF16("Google");
+ const base::string16 dest_title = ASCIIToUTF16("Google");
EXPECT_TRUE(dest_rvh->OnMessageReceived(
ViewHostMsg_UpdateTitle(rvh()->GetRoutingID(), 101, dest_title,
direction)));
@@ -291,9 +308,9 @@ TEST_F(RenderViewHostManagerTest, FilterMessagesWhileSwappedOut) {
MockRenderProcessHost* ntp_process_host =
static_cast<MockRenderProcessHost*>(ntp_rvh->GetProcess());
ntp_process_host->sink().ClearMessages();
- const string16 msg = ASCIIToUTF16("Message");
+ const base::string16 msg = ASCIIToUTF16("Message");
bool result = false;
- string16 unused;
+ base::string16 unused;
ViewHostMsg_RunBeforeUnloadConfirm before_unload_msg(
rvh()->GetRoutingID(), kChromeURL, msg, false, &result, &unused);
// Enable pumping for check in BrowserMessageFilter::CheckCanDispatchOnUI.
@@ -311,7 +328,7 @@ TEST_F(RenderViewHostManagerTest, FilterMessagesWhileSwappedOut) {
EXPECT_TRUE(ntp_process_host->sink().GetUniqueMessageMatching(IPC_REPLY_ID));
}
-TEST_F(RenderViewHostManagerTest, WhiteListSwapCompositorFrame) {
+TEST_F(RenderFrameHostManagerTest, WhiteListSwapCompositorFrame) {
TestRenderViewHost* swapped_out_rvh = CreateSwappedOutRenderViewHost();
TestRenderWidgetHostView* swapped_out_rwhv =
static_cast<TestRenderWidgetHostView*>(swapped_out_rvh->GetView());
@@ -328,7 +345,7 @@ TEST_F(RenderViewHostManagerTest, WhiteListSwapCompositorFrame) {
EXPECT_TRUE(swapped_out_rwhv->did_swap_compositor_frame());
}
-TEST_F(RenderViewHostManagerTest, WhiteListDidActivateAcceleratedCompositing) {
+TEST_F(RenderFrameHostManagerTest, WhiteListDidActivateAcceleratedCompositing) {
TestRenderViewHost* swapped_out_rvh = CreateSwappedOutRenderViewHost();
MockRenderProcessHost* process_host =
@@ -342,7 +359,7 @@ TEST_F(RenderViewHostManagerTest, WhiteListDidActivateAcceleratedCompositing) {
// Test if RenderViewHost::GetRenderWidgetHosts() only returns active
// widgets.
-TEST_F(RenderViewHostManagerTest, GetRenderWidgetHostsReturnsActiveViews) {
+TEST_F(RenderFrameHostManagerTest, GetRenderWidgetHostsReturnsActiveViews) {
TestRenderViewHost* swapped_out_rvh = CreateSwappedOutRenderViewHost();
EXPECT_TRUE(swapped_out_rvh->is_swapped_out());
@@ -362,7 +379,7 @@ TEST_F(RenderViewHostManagerTest, GetRenderWidgetHostsReturnsActiveViews) {
// RenderViewHost::GetRenderWidgetHosts() returns only active widgets, but
// RenderViewHostImpl::GetAllRenderWidgetHosts() returns everything
// including swapped out ones.
-TEST_F(RenderViewHostManagerTest,
+TEST_F(RenderFrameHostManagerTest,
GetRenderWidgetHostsWithinGetAllRenderWidgetHosts) {
TestRenderViewHost* swapped_out_rvh = CreateSwappedOutRenderViewHost();
EXPECT_TRUE(swapped_out_rvh->is_swapped_out());
@@ -386,7 +403,7 @@ TEST_F(RenderViewHostManagerTest,
// Test if SiteInstanceImpl::active_view_count() is correctly updated
// as views in a SiteInstance get swapped out and in.
-TEST_F(RenderViewHostManagerTest, ActiveViewCountWhileSwappingInandOut) {
+TEST_F(RenderFrameHostManagerTest, ActiveViewCountWhileSwappingInandOut) {
const GURL kUrl1("http://www.google.com/");
const GURL kUrl2("http://www.chromium.org/");
@@ -435,20 +452,24 @@ TEST_F(RenderViewHostManagerTest, ActiveViewCountWhileSwappingInandOut) {
// other parts of the system. For now, this class is only used for the
// next test cases to detect the bug mentioned at
// http://crbug.com/259859.
-class RenderViewHostDestroyer : public content::RenderViewHostObserver {
+class RenderViewHostDestroyer : public WebContentsObserver {
public:
RenderViewHostDestroyer(RenderViewHost* render_view_host,
WebContents* web_contents)
- : content::RenderViewHostObserver(render_view_host),
+ : WebContentsObserver(WebContents::FromRenderViewHost(render_view_host)),
+ render_view_host_(render_view_host),
web_contents_(web_contents) {}
- virtual void RenderViewHostDestroyed(RenderViewHost* render_view_host)
- OVERRIDE {
- delete web_contents_;
+ virtual void RenderViewDeleted(
+ RenderViewHost* render_view_host) OVERRIDE {
+ if (render_view_host == render_view_host_)
+ delete web_contents_;
}
private:
+ RenderViewHost* render_view_host_;
WebContents* web_contents_;
+
DISALLOW_COPY_AND_ASSIGN(RenderViewHostDestroyer);
};
@@ -456,7 +477,7 @@ class RenderViewHostDestroyer : public content::RenderViewHostObserver {
// RenderWidget that has been freed while deleting a RenderViewHost in
// a previous iteration. This is a regression test for
// http://crbug.com/259859.
-TEST_F(RenderViewHostManagerTest,
+TEST_F(RenderFrameHostManagerTest,
DetectUseAfterFreeInShutdownRenderViewHostsInSiteInstance) {
const GURL kChromeURL("chrome://newtab");
const GURL kUrl1("http://www.google.com");
@@ -489,7 +510,7 @@ TEST_F(RenderViewHostManagerTest,
// mode. See WebFrameImpl::DidFail(). We check by this test that
// EnableViewSourceMode message is sent on every navigation regardless
// RenderView is being newly created or reused.
-TEST_F(RenderViewHostManagerTest, AlwaysSendEnableViewSourceMode) {
+TEST_F(RenderFrameHostManagerTest, AlwaysSendEnableViewSourceMode) {
const GURL kChromeUrl("chrome://foo");
const GURL kUrl("view-source:http://foo");
@@ -538,7 +559,7 @@ TEST_F(RenderViewHostManagerTest, AlwaysSendEnableViewSourceMode) {
}
// Tests the Init function by checking the initial RenderViewHost.
-TEST_F(RenderViewHostManagerTest, Init) {
+TEST_F(RenderFrameHostManagerTest, Init) {
// Using TestBrowserContext.
SiteInstanceImpl* instance =
static_cast<SiteInstanceImpl*>(SiteInstance::Create(browser_context()));
@@ -546,8 +567,8 @@ TEST_F(RenderViewHostManagerTest, Init) {
scoped_ptr<TestWebContents> web_contents(
TestWebContents::Create(browser_context(), instance));
- RenderViewHostManager manager(web_contents.get(), web_contents.get(),
- web_contents.get());
+ RenderFrameHostManager manager(web_contents.get(), web_contents.get(),
+ web_contents.get(), web_contents.get());
manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE);
@@ -561,20 +582,19 @@ TEST_F(RenderViewHostManagerTest, Init) {
// Tests the Navigate function. We navigate three sites consecutively and check
// how the pending/committed RenderViewHost are modified.
-TEST_F(RenderViewHostManagerTest, Navigate) {
+TEST_F(RenderFrameHostManagerTest, Navigate) {
TestNotificationTracker notifications;
SiteInstance* instance = SiteInstance::Create(browser_context());
scoped_ptr<TestWebContents> web_contents(
TestWebContents::Create(browser_context(), instance));
- notifications.ListenFor(
- NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
- Source<NavigationController>(&web_contents->GetController()));
+ notifications.ListenFor(NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
+ Source<WebContents>(web_contents.get()));
// Create.
- RenderViewHostManager manager(web_contents.get(), web_contents.get(),
- web_contents.get());
+ RenderFrameHostManager manager(web_contents.get(), web_contents.get(),
+ web_contents.get(), web_contents.get());
manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE);
@@ -584,7 +604,7 @@ TEST_F(RenderViewHostManagerTest, Navigate) {
const GURL kUrl1("http://www.google.com/");
NavigationEntryImpl entry1(
NULL /* instance */, -1 /* page_id */, kUrl1, Referrer(),
- string16() /* title */, PAGE_TRANSITION_TYPED,
+ base::string16() /* title */, PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
host = manager.Navigate(entry1);
@@ -605,8 +625,8 @@ TEST_F(RenderViewHostManagerTest, Navigate) {
const GURL kUrl2("http://www.google.com/foo");
NavigationEntryImpl entry2(
NULL /* instance */, -1 /* page_id */, kUrl2,
- Referrer(kUrl1, WebKit::WebReferrerPolicyDefault),
- string16() /* title */, PAGE_TRANSITION_LINK,
+ Referrer(kUrl1, blink::WebReferrerPolicyDefault),
+ base::string16() /* title */, PAGE_TRANSITION_LINK,
true /* is_renderer_init */);
host = manager.Navigate(entry2);
@@ -625,8 +645,8 @@ TEST_F(RenderViewHostManagerTest, Navigate) {
const GURL kUrl3("http://webkit.org/");
NavigationEntryImpl entry3(
NULL /* instance */, -1 /* page_id */, kUrl3,
- Referrer(kUrl2, WebKit::WebReferrerPolicyDefault),
- string16() /* title */, PAGE_TRANSITION_LINK,
+ Referrer(kUrl2, blink::WebReferrerPolicyDefault),
+ base::string16() /* title */, PAGE_TRANSITION_LINK,
false /* is_renderer_init */);
host = manager.Navigate(entry3);
@@ -646,35 +666,34 @@ TEST_F(RenderViewHostManagerTest, Navigate) {
EXPECT_FALSE(manager.pending_render_view_host());
// We should observe a notification.
- EXPECT_TRUE(notifications.Check1AndReset(
- NOTIFICATION_RENDER_VIEW_HOST_CHANGED));
+ EXPECT_TRUE(
+ notifications.Check1AndReset(NOTIFICATION_RENDER_VIEW_HOST_CHANGED));
}
// Tests the Navigate function. In this unit test we verify that the Navigate
// function can handle a new navigation event before the previous navigation
// has been committed. This is also a regression test for
// http://crbug.com/104600.
-TEST_F(RenderViewHostManagerTest, NavigateWithEarlyReNavigation) {
+TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyReNavigation) {
TestNotificationTracker notifications;
SiteInstance* instance = SiteInstance::Create(browser_context());
scoped_ptr<TestWebContents> web_contents(
TestWebContents::Create(browser_context(), instance));
- notifications.ListenFor(
- NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
- Source<NavigationController>(&web_contents->GetController()));
+ notifications.ListenFor(NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
+ Source<WebContents>(web_contents.get()));
// Create.
- RenderViewHostManager manager(web_contents.get(), web_contents.get(),
- web_contents.get());
+ RenderFrameHostManager manager(web_contents.get(), web_contents.get(),
+ web_contents.get(), web_contents.get());
manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE);
// 1) The first navigation. --------------------------
const GURL kUrl1("http://www.google.com/");
NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1,
- Referrer(), string16() /* title */,
+ Referrer(), base::string16() /* title */,
PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
RenderViewHost* host = manager.Navigate(entry1);
@@ -684,8 +703,8 @@ TEST_F(RenderViewHostManagerTest, NavigateWithEarlyReNavigation) {
EXPECT_FALSE(manager.pending_render_view_host());
// We should observe a notification.
- EXPECT_TRUE(notifications.Check1AndReset(
- NOTIFICATION_RENDER_VIEW_HOST_CHANGED));
+ EXPECT_TRUE(
+ notifications.Check1AndReset(NOTIFICATION_RENDER_VIEW_HOST_CHANGED));
notifications.Reset();
// Commit.
@@ -702,7 +721,7 @@ TEST_F(RenderViewHostManagerTest, NavigateWithEarlyReNavigation) {
const GURL kUrl2("http://www.example.com");
NavigationEntryImpl entry2(
NULL /* instance */, -1 /* page_id */, kUrl2, Referrer(),
- string16() /* title */, PAGE_TRANSITION_TYPED,
+ base::string16() /* title */, PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
RenderViewHostImpl* host2 = static_cast<RenderViewHostImpl*>(
manager.Navigate(entry2));
@@ -734,8 +753,8 @@ TEST_F(RenderViewHostManagerTest, NavigateWithEarlyReNavigation) {
test_host->SendShouldCloseACK(true);
// CrossSiteResourceHandler::StartCrossSiteTransition triggers a
- // call of RenderViewHostManager::SwapOutOldPage before
- // RenderViewHostManager::DidNavigateMainFrame is called.
+ // call of RenderFrameHostManager::SwapOutOldPage before
+ // RenderFrameHostManager::DidNavigateMainFrame is called.
// The RVH is not swapped out until the commit.
manager.SwapOutOldPage();
EXPECT_TRUE(test_process_host->sink().GetUniqueMessageMatching(
@@ -753,7 +772,7 @@ TEST_F(RenderViewHostManagerTest, NavigateWithEarlyReNavigation) {
// 3) Cross-site navigate to next site before 2) has committed. --------------
const GURL kUrl3("http://webkit.org/");
NavigationEntryImpl entry3(NULL /* instance */, -1 /* page_id */, kUrl3,
- Referrer(), string16() /* title */,
+ Referrer(), base::string16() /* title */,
PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
test_process_host->sink().ClearMessages();
@@ -780,8 +799,8 @@ TEST_F(RenderViewHostManagerTest, NavigateWithEarlyReNavigation) {
test_host->SendShouldCloseACK(true);
// CrossSiteResourceHandler::StartCrossSiteTransition triggers a
- // call of RenderViewHostManager::SwapOutOldPage before
- // RenderViewHostManager::DidNavigateMainFrame is called.
+ // call of RenderFrameHostManager::SwapOutOldPage before
+ // RenderFrameHostManager::DidNavigateMainFrame is called.
// The RVH is not swapped out until the commit.
manager.SwapOutOldPage();
EXPECT_TRUE(test_process_host->sink().GetUniqueMessageMatching(
@@ -798,26 +817,26 @@ TEST_F(RenderViewHostManagerTest, NavigateWithEarlyReNavigation) {
EXPECT_FALSE(manager.pending_render_view_host());
// We should observe a notification.
- EXPECT_TRUE(notifications.Check1AndReset(
- NOTIFICATION_RENDER_VIEW_HOST_CHANGED));
+ EXPECT_TRUE(
+ notifications.Check1AndReset(NOTIFICATION_RENDER_VIEW_HOST_CHANGED));
}
// Tests WebUI creation.
-TEST_F(RenderViewHostManagerTest, WebUI) {
+TEST_F(RenderFrameHostManagerTest, WebUI) {
set_should_create_webui(true);
SiteInstance* instance = SiteInstance::Create(browser_context());
scoped_ptr<TestWebContents> web_contents(
TestWebContents::Create(browser_context(), instance));
- RenderViewHostManager manager(web_contents.get(), web_contents.get(),
- web_contents.get());
+ RenderFrameHostManager manager(web_contents.get(), web_contents.get(),
+ web_contents.get(), web_contents.get());
manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE);
EXPECT_FALSE(manager.current_host()->IsRenderViewLive());
const GURL kUrl("chrome://foo");
NavigationEntryImpl entry(NULL /* instance */, -1 /* page_id */, kUrl,
- Referrer(), string16() /* title */,
+ Referrer(), base::string16() /* title */,
PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
RenderViewHost* host = manager.Navigate(entry);
@@ -849,24 +868,24 @@ TEST_F(RenderViewHostManagerTest, WebUI) {
// Tests that we can open a WebUI link in a new tab from a WebUI page and still
// grant the correct bindings. http://crbug.com/189101.
-TEST_F(RenderViewHostManagerTest, WebUIInNewTab) {
+TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
set_should_create_webui(true);
SiteInstance* blank_instance = SiteInstance::Create(browser_context());
// Create a blank tab.
scoped_ptr<TestWebContents> web_contents1(
TestWebContents::Create(browser_context(), blank_instance));
- RenderViewHostManager manager1(web_contents1.get(), web_contents1.get(),
- web_contents1.get());
+ RenderFrameHostManager manager1(web_contents1.get(), web_contents1.get(),
+ web_contents1.get(), web_contents1.get());
manager1.Init(
browser_context(), blank_instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE);
// Test the case that new RVH is considered live.
- manager1.current_host()->CreateRenderView(string16(), -1, -1);
+ manager1.current_host()->CreateRenderView(base::string16(), -1, -1);
// Navigate to a WebUI page.
const GURL kUrl1("chrome://foo");
NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1,
- Referrer(), string16() /* title */,
+ Referrer(), base::string16() /* title */,
PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
RenderViewHost* host1 = manager1.Navigate(entry1);
@@ -886,17 +905,17 @@ TEST_F(RenderViewHostManagerTest, WebUIInNewTab) {
// Now simulate clicking a link that opens in a new tab.
scoped_ptr<TestWebContents> web_contents2(
TestWebContents::Create(browser_context(), webui_instance));
- RenderViewHostManager manager2(web_contents2.get(), web_contents2.get(),
- web_contents2.get());
+ RenderFrameHostManager manager2(web_contents2.get(), web_contents2.get(),
+ web_contents2.get(), web_contents2.get());
manager2.Init(
browser_context(), webui_instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE);
// Make sure the new RVH is considered live. This is usually done in
// RenderWidgetHost::Init when opening a new tab from a link.
- manager2.current_host()->CreateRenderView(string16(), -1, -1);
+ manager2.current_host()->CreateRenderView(base::string16(), -1, -1);
const GURL kUrl2("chrome://foo/bar");
NavigationEntryImpl entry2(NULL /* instance */, -1 /* page_id */, kUrl2,
- Referrer(), string16() /* title */,
+ Referrer(), base::string16() /* title */,
PAGE_TRANSITION_LINK,
true /* is_renderer_init */);
RenderViewHost* host2 = manager2.Navigate(entry2);
@@ -911,7 +930,7 @@ TEST_F(RenderViewHostManagerTest, WebUIInNewTab) {
// Tests that we don't end up in an inconsistent state if a page does a back and
// then reload. http://crbug.com/51680
-TEST_F(RenderViewHostManagerTest, PageDoesBackAndReload) {
+TEST_F(RenderFrameHostManagerTest, PageDoesBackAndReload) {
const GURL kUrl1("http://www.google.com/");
const GURL kUrl2("http://www.evil-site.com/");
@@ -950,14 +969,15 @@ TEST_F(RenderViewHostManagerTest, PageDoesBackAndReload) {
EXPECT_EQ(evil_rvh, contents()->GetRenderManagerForTesting()->current_host());
// Also we should not have a pending navigation entry.
- NavigationEntry* entry = contents()->GetController().GetActiveEntry();
+ EXPECT_TRUE(contents()->GetController().GetPendingEntry() == NULL);
+ NavigationEntry* entry = contents()->GetController().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_EQ(kUrl2, entry->GetURL());
}
// Ensure that we can go back and forward even if a SwapOut ACK isn't received.
// See http://crbug.com/93427.
-TEST_F(RenderViewHostManagerTest, NavigateAfterMissingSwapOutACK) {
+TEST_F(RenderFrameHostManagerTest, NavigateAfterMissingSwapOutACK) {
const GURL kUrl1("http://www.google.com/");
const GURL kUrl2("http://www.chromium.org/");
@@ -1005,27 +1025,27 @@ TEST_F(RenderViewHostManagerTest, NavigateAfterMissingSwapOutACK) {
// Test that we create swapped out RVHs for the opener chain when navigating an
// opened tab cross-process. This allows us to support certain cross-process
// JavaScript calls (http://crbug.com/99202).
-TEST_F(RenderViewHostManagerTest, CreateSwappedOutOpenerRVHs) {
+TEST_F(RenderFrameHostManagerTest, CreateSwappedOutOpenerRVHs) {
const GURL kUrl1("http://www.google.com/");
const GURL kUrl2("http://www.chromium.org/");
const GURL kChromeUrl("chrome://foo");
// Navigate to an initial URL.
contents()->NavigateAndCommit(kUrl1);
- RenderViewHostManager* manager = contents()->GetRenderManagerForTesting();
+ RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting();
TestRenderViewHost* rvh1 = test_rvh();
// Create 2 new tabs and simulate them being the opener chain for the main
// tab. They should be in the same SiteInstance.
scoped_ptr<TestWebContents> opener1(
TestWebContents::Create(browser_context(), rvh1->GetSiteInstance()));
- RenderViewHostManager* opener1_manager =
+ RenderFrameHostManager* opener1_manager =
opener1->GetRenderManagerForTesting();
contents()->SetOpener(opener1.get());
scoped_ptr<TestWebContents> opener2(
TestWebContents::Create(browser_context(), rvh1->GetSiteInstance()));
- RenderViewHostManager* opener2_manager =
+ RenderFrameHostManager* opener2_manager =
opener2->GetRenderManagerForTesting();
opener1->SetOpener(opener2.get());
@@ -1071,8 +1091,9 @@ TEST_F(RenderViewHostManagerTest, CreateSwappedOutOpenerRVHs) {
// Test that we clean up swapped out RenderViewHosts when a process hosting
// those associated RenderViews crashes. http://crbug.com/258993
-TEST_F(RenderViewHostManagerTest, CleanUpSwappedOutRVHOnProcessCrash) {
+TEST_F(RenderFrameHostManagerTest, CleanUpSwappedOutRVHOnProcessCrash) {
const GURL kUrl1("http://www.google.com/");
+ const GURL kUrl2("http://www.chromium.org/");
// Navigate to an initial URL.
contents()->NavigateAndCommit(kUrl1);
@@ -1081,13 +1102,17 @@ TEST_F(RenderViewHostManagerTest, CleanUpSwappedOutRVHOnProcessCrash) {
// Create a new tab as an opener for the main tab.
scoped_ptr<TestWebContents> opener1(
TestWebContents::Create(browser_context(), rvh1->GetSiteInstance()));
- RenderViewHostManager* opener1_manager =
+ RenderFrameHostManager* opener1_manager =
opener1->GetRenderManagerForTesting();
contents()->SetOpener(opener1.get());
+ // Make sure the new opener RVH is considered live.
+ opener1_manager->current_host()->CreateRenderView(base::string16(), -1, -1);
+
+ // Use a cross-process navigation in the opener to swap out the old RVH.
EXPECT_FALSE(opener1_manager->GetSwappedOutRenderViewHost(
rvh1->GetSiteInstance()));
- opener1->CreateSwappedOutRenderView(rvh1->GetSiteInstance());
+ opener1->NavigateAndCommit(kUrl2);
EXPECT_TRUE(opener1_manager->GetSwappedOutRenderViewHost(
rvh1->GetSiteInstance()));
@@ -1106,17 +1131,18 @@ TEST_F(RenderViewHostManagerTest, CleanUpSwappedOutRVHOnProcessCrash) {
EXPECT_FALSE(opener1_manager->GetSwappedOutRenderViewHost(
rvh1->GetSiteInstance()));
- // Reload the initial tab. This should recreate the opener.
+ // Reload the initial tab. This should recreate the opener's swapped out RVH
+ // in the original SiteInstance.
contents()->GetController().Reload(true);
-
- EXPECT_EQ(opener1_manager->current_host()->GetRoutingID(),
+ EXPECT_EQ(opener1_manager->GetSwappedOutRenderViewHost(
+ rvh1->GetSiteInstance())->GetRoutingID(),
test_rvh()->opener_route_id());
}
// Test that RenderViewHosts created for WebUI navigations are properly
// granted WebUI bindings even if an unprivileged swapped out RenderViewHost
// is in the same process (http://crbug.com/79918).
-TEST_F(RenderViewHostManagerTest, EnableWebUIWithSwappedOutOpener) {
+TEST_F(RenderFrameHostManagerTest, EnableWebUIWithSwappedOutOpener) {
set_should_create_webui(true);
const GURL kSettingsUrl("chrome://chrome/settings");
const GURL kPluginUrl("chrome://plugins");
@@ -1132,7 +1158,7 @@ TEST_F(RenderViewHostManagerTest, EnableWebUIWithSwappedOutOpener) {
// tab. It should be in the same SiteInstance.
scoped_ptr<TestWebContents> opener1(
TestWebContents::Create(browser_context(), rvh1->GetSiteInstance()));
- RenderViewHostManager* opener1_manager =
+ RenderFrameHostManager* opener1_manager =
opener1->GetRenderManagerForTesting();
contents()->SetOpener(opener1.get());
@@ -1155,18 +1181,18 @@ TEST_F(RenderViewHostManagerTest, EnableWebUIWithSwappedOutOpener) {
}
// Test that we reuse the same guest SiteInstance if we navigate across sites.
-TEST_F(RenderViewHostManagerTest, NoSwapOnGuestNavigations) {
+TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
TestNotificationTracker notifications;
- GURL guest_url(std::string(chrome::kGuestScheme).append("://abc123"));
+ GURL guest_url(std::string(kGuestScheme).append("://abc123"));
SiteInstance* instance =
SiteInstance::CreateForURL(browser_context(), guest_url);
scoped_ptr<TestWebContents> web_contents(
TestWebContents::Create(browser_context(), instance));
// Create.
- RenderViewHostManager manager(web_contents.get(), web_contents.get(),
- web_contents.get());
+ RenderFrameHostManager manager(web_contents.get(), web_contents.get(),
+ web_contents.get(), web_contents.get());
manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE);
@@ -1176,7 +1202,7 @@ TEST_F(RenderViewHostManagerTest, NoSwapOnGuestNavigations) {
const GURL kUrl1("http://www.google.com/");
NavigationEntryImpl entry1(
NULL /* instance */, -1 /* page_id */, kUrl1, Referrer(),
- string16() /* title */, PAGE_TRANSITION_TYPED,
+ base::string16() /* title */, PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
host = manager.Navigate(entry1);
@@ -1198,8 +1224,8 @@ TEST_F(RenderViewHostManagerTest, NoSwapOnGuestNavigations) {
const GURL kUrl2("http://www.chromium.org");
NavigationEntryImpl entry2(
NULL /* instance */, -1 /* page_id */, kUrl2,
- Referrer(kUrl1, WebKit::WebReferrerPolicyDefault),
- string16() /* title */, PAGE_TRANSITION_LINK,
+ Referrer(kUrl1, blink::WebReferrerPolicyDefault),
+ base::string16() /* title */, PAGE_TRANSITION_LINK,
true /* is_renderer_init */);
host = manager.Navigate(entry2);
@@ -1215,4 +1241,79 @@ TEST_F(RenderViewHostManagerTest, NoSwapOnGuestNavigations) {
instance);
}
+// Test that we cancel a pending RVH if we close the tab while it's pending.
+// http://crbug.com/294697.
+TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
+ TestNotificationTracker notifications;
+
+ SiteInstance* instance = SiteInstance::Create(browser_context());
+
+ BeforeUnloadFiredWebContentsDelegate delegate;
+ scoped_ptr<TestWebContents> web_contents(
+ TestWebContents::Create(browser_context(), instance));
+ web_contents->SetDelegate(&delegate);
+ notifications.ListenFor(NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
+ Source<WebContents>(web_contents.get()));
+
+ // Create.
+ RenderFrameHostManager manager(web_contents.get(), web_contents.get(),
+ web_contents.get(), web_contents.get());
+
+ manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE);
+
+ // 1) The first navigation. --------------------------
+ const GURL kUrl1("http://www.google.com/");
+ NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1,
+ Referrer(), base::string16() /* title */,
+ PAGE_TRANSITION_TYPED,
+ false /* is_renderer_init */);
+ RenderViewHost* host = manager.Navigate(entry1);
+
+ // The RenderViewHost created in Init will be reused.
+ EXPECT_EQ(host, manager.current_host());
+ EXPECT_FALSE(manager.pending_render_view_host());
+
+ // We should observe a notification.
+ EXPECT_TRUE(
+ notifications.Check1AndReset(NOTIFICATION_RENDER_VIEW_HOST_CHANGED));
+ notifications.Reset();
+
+ // Commit.
+ manager.DidNavigateMainFrame(host);
+
+ // Commit to SiteInstance should be delayed until RenderView commit.
+ EXPECT_EQ(host, manager.current_host());
+ EXPECT_FALSE(static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->
+ HasSite());
+ static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->SetSite(kUrl1);
+
+ // 2) Cross-site navigate to next site. -------------------------
+ const GURL kUrl2("http://www.example.com");
+ NavigationEntryImpl entry2(
+ NULL /* instance */, -1 /* page_id */, kUrl2, Referrer(),
+ base::string16() /* title */, PAGE_TRANSITION_TYPED,
+ false /* is_renderer_init */);
+ RenderViewHostImpl* host2 = static_cast<RenderViewHostImpl*>(
+ manager.Navigate(entry2));
+
+ // A new RenderViewHost should be created.
+ ASSERT_EQ(host2, manager.pending_render_view_host());
+ EXPECT_NE(host2, host);
+
+ EXPECT_EQ(host, manager.current_host());
+ EXPECT_FALSE(static_cast<RenderViewHostImpl*>(
+ manager.current_host())->is_swapped_out());
+ EXPECT_EQ(host2, manager.pending_render_view_host());
+
+ // 3) Close the tab. -------------------------
+ notifications.ListenFor(NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
+ Source<RenderWidgetHost>(host2));
+ manager.ShouldClosePage(false, true, base::TimeTicks());
+
+ EXPECT_TRUE(
+ notifications.Check1AndReset(NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED));
+ EXPECT_FALSE(manager.pending_render_view_host());
+ EXPECT_EQ(host, manager.current_host());
+}
+
} // 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
new file mode 100644
index 00000000000..c1876806fae
--- /dev/null
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.cc
@@ -0,0 +1,71 @@
+// 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/frame_host/render_frame_message_filter.h"
+
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_widget_helper.h"
+#include "content/common/frame_messages.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+namespace {
+
+void CreateChildFrameOnUI(int process_id,
+ int parent_render_frame_id,
+ int64 parent_frame_id,
+ int64 frame_id,
+ const std::string& frame_name,
+ int new_render_frame_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RenderFrameHostImpl* render_frame_host =
+ RenderFrameHostImpl::FromID(process_id, parent_render_frame_id);
+ // Handles the RenderFrameHost being deleted on the UI thread while
+ // processing a subframe creation message.
+ if (render_frame_host) {
+ render_frame_host->OnCreateChildFrame(new_render_frame_id,
+ parent_frame_id, frame_id,
+ frame_name);
+ }
+}
+
+} // namespace
+
+RenderFrameMessageFilter::RenderFrameMessageFilter(
+ int render_process_id,
+ RenderWidgetHelper* render_widget_helper)
+ : render_process_id_(render_process_id),
+ render_widget_helper_(render_widget_helper) {
+}
+
+RenderFrameMessageFilter::~RenderFrameMessageFilter() {
+}
+
+bool RenderFrameMessageFilter::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(RenderFrameMessageFilter, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_CreateChildFrame, OnCreateChildFrame)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP_EX()
+
+ return handled;
+}
+
+void RenderFrameMessageFilter::OnCreateChildFrame(
+ int parent_render_frame_id,
+ int64 parent_frame_id,
+ int64 frame_id,
+ const std::string& frame_name,
+ int* new_render_frame_id) {
+ *new_render_frame_id = render_widget_helper_->GetNextRoutingID();
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&CreateChildFrameOnUI, render_process_id_,
+ parent_render_frame_id, parent_frame_id, frame_id, frame_name,
+ *new_render_frame_id));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_message_filter.h b/chromium/content/browser/frame_host/render_frame_message_filter.h
new file mode 100644
index 00000000000..82a1b9420c8
--- /dev/null
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.h
@@ -0,0 +1,44 @@
+// 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_FRAME_HOST_RENDER_FRAME_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_MESSAGE_FILTER_H_
+
+#include "content/public/browser/browser_message_filter.h"
+
+namespace content {
+class RenderWidgetHelper;
+
+// RenderFrameMessageFilter intercepts FrameHost messages on the IO thread
+// that require low-latency processing. The canonical example of this is
+// child-frame creation which is a sync IPC that provides the renderer
+// 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 {
+ public:
+ RenderFrameMessageFilter(int render_process_id,
+ RenderWidgetHelper* render_widget_helper);
+
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) OVERRIDE;
+
+ private:
+ virtual ~RenderFrameMessageFilter();
+
+ void OnCreateChildFrame(int parent_render_frame_id,
+ int64 parent_frame_id,
+ int64 frame_id,
+ const std::string& frame_name,
+ int* new_render_frame_id);
+
+ const int render_process_id_;
+
+ // Needed for issuing routing ids and surface ids.
+ scoped_refptr<RenderWidgetHelper> render_widget_helper_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/gamepad/gamepad_data_fetcher.h b/chromium/content/browser/gamepad/gamepad_data_fetcher.h
index e5e009dc42b..17887d5d0e1 100644
--- a/chromium/content/browser/gamepad/gamepad_data_fetcher.h
+++ b/chromium/content/browser/gamepad/gamepad_data_fetcher.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_BROWSER_GAMEPAD_GAMEPAD_DATA_FETCHER_H_
#define CONTENT_BROWSER_GAMEPAD_GAMEPAD_DATA_FETCHER_H_
-namespace WebKit {
+namespace blink {
class WebGamepads;
}
@@ -16,7 +16,7 @@ namespace content {
class GamepadDataFetcher {
public:
virtual ~GamepadDataFetcher() {}
- virtual void GetGamepadData(WebKit::WebGamepads* pads,
+ virtual void GetGamepadData(blink::WebGamepads* pads,
bool devices_changed_hint) = 0;
virtual void PauseHint(bool paused) {}
};
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.cc b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.cc
index b4499d6fd41..d889526e0d4 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.cc
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.cc
@@ -11,7 +11,7 @@ namespace content {
GamepadDataFetcherEmpty::GamepadDataFetcherEmpty() {
}
-void GamepadDataFetcherEmpty::GetGamepadData(WebKit::WebGamepads* pads,
+void GamepadDataFetcherEmpty::GetGamepadData(blink::WebGamepads* pads,
bool devices_changed_hint) {
pads->length = 0;
}
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h
index f073a538d6f..247306295e7 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h
@@ -30,7 +30,7 @@ typedef GamepadPlatformDataFetcherWin GamepadPlatformDataFetcher;
typedef GamepadPlatformDataFetcherMac GamepadPlatformDataFetcher;
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) && defined(USE_UDEV)
typedef GamepadPlatformDataFetcherLinux GamepadPlatformDataFetcher;
@@ -40,7 +40,7 @@ class GamepadDataFetcherEmpty : public GamepadDataFetcher {
public:
GamepadDataFetcherEmpty();
- virtual void GetGamepadData(WebKit::WebGamepads* pads,
+ virtual void GetGamepadData(blink::WebGamepads* pads,
bool devices_changed_hint) OVERRIDE;
private:
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
index c82997e22a1..d466dde4b06 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
@@ -52,7 +52,7 @@ bool IsGamepad(udev_device* dev, int* index, std::string* path) {
if (!base::StringToInt(str, &tmp_idx))
return false;
if (tmp_idx < 0 ||
- tmp_idx >= static_cast<int>(WebKit::WebGamepads::itemsLengthCap)) {
+ tmp_idx >= static_cast<int>(blink::WebGamepads::itemsLengthCap)) {
return false;
}
*index = tmp_idx;
@@ -64,8 +64,8 @@ bool IsGamepad(udev_device* dev, int* index, std::string* path) {
namespace content {
-using WebKit::WebGamepad;
-using WebKit::WebGamepads;
+using blink::WebGamepad;
+using blink::WebGamepads;
GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() {
for (size_t i = 0; i < arraysize(device_fds_); ++i)
@@ -186,8 +186,8 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) {
mapper ? "STANDARD GAMEPAD " : "",
vendor_id,
product_id);
- TruncateUTF8ToByteSize(id, WebGamepad::idLengthCap - 1, &id);
- string16 tmp16 = UTF8ToUTF16(id);
+ base::TruncateUTF8ToByteSize(id, WebGamepad::idLengthCap - 1, &id);
+ base::string16 tmp16 = UTF8ToUTF16(id);
memset(pad.id, 0, sizeof(pad.id));
tmp16.copy(pad.id, arraysize(pad.id) - 1);
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
index 916eda311f4..f95e52fc0b2 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
@@ -28,7 +28,7 @@ class GamepadPlatformDataFetcherLinux : public GamepadDataFetcher {
virtual ~GamepadPlatformDataFetcherLinux();
// GamepadDataFetcher implementation.
- virtual void GetGamepadData(WebKit::WebGamepads* pads,
+ virtual void GetGamepadData(blink::WebGamepads* pads,
bool devices_changed_hint) OVERRIDE;
private:
@@ -37,14 +37,14 @@ class GamepadPlatformDataFetcherLinux : public GamepadDataFetcher {
void ReadDeviceData(size_t index);
// File descriptors for the /dev/input/js* devices. -1 if not in use.
- int device_fds_[WebKit::WebGamepads::itemsLengthCap];
+ int device_fds_[blink::WebGamepads::itemsLengthCap];
// Functions to map from device data to standard layout, if available. May
// be null if no mapping is available.
- GamepadStandardMappingFunction mappers_[WebKit::WebGamepads::itemsLengthCap];
+ GamepadStandardMappingFunction mappers_[blink::WebGamepads::itemsLengthCap];
// Data that's returned to the consumer.
- WebKit::WebGamepads data_;
+ blink::WebGamepads data_;
scoped_ptr<UdevLinux> udev_;
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h
index 3b22b69350c..54e1944da6c 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h
@@ -32,7 +32,7 @@ class GamepadPlatformDataFetcherMac : public GamepadDataFetcher,
public:
GamepadPlatformDataFetcherMac();
virtual ~GamepadPlatformDataFetcherMac();
- virtual void GetGamepadData(WebKit::WebGamepads* pads,
+ virtual void GetGamepadData(blink::WebGamepads* pads,
bool devices_changed_hint) OVERRIDE;
virtual void PauseHint(bool paused) OVERRIDE;
@@ -73,7 +73,7 @@ class GamepadPlatformDataFetcherMac : public GamepadDataFetcher,
scoped_ptr<XboxDataFetcher> xbox_fetcher_;
- WebKit::WebGamepads data_;
+ blink::WebGamepads data_;
// Side-band data that's not passed to the consumer, but we need to maintain
// to update data_.
@@ -82,10 +82,10 @@ class GamepadPlatformDataFetcherMac : public GamepadDataFetcher,
union {
struct {
IOHIDDeviceRef device_ref;
- IOHIDElementRef button_elements[WebKit::WebGamepad::buttonsLengthCap];
- IOHIDElementRef axis_elements[WebKit::WebGamepad::buttonsLengthCap];
- CFIndex axis_minimums[WebKit::WebGamepad::axesLengthCap];
- CFIndex axis_maximums[WebKit::WebGamepad::axesLengthCap];
+ IOHIDElementRef button_elements[blink::WebGamepad::buttonsLengthCap];
+ IOHIDElementRef axis_elements[blink::WebGamepad::buttonsLengthCap];
+ CFIndex axis_minimums[blink::WebGamepad::axesLengthCap];
+ CFIndex axis_maximums[blink::WebGamepad::axesLengthCap];
// Function to map from device data to standard layout, if available.
// May be null if no mapping is available.
GamepadStandardMappingFunction mapper;
@@ -96,7 +96,7 @@ class GamepadPlatformDataFetcherMac : public GamepadDataFetcher,
} xbox;
};
};
- AssociatedData associated_[WebKit::WebGamepads::itemsLengthCap];
+ AssociatedData associated_[blink::WebGamepads::itemsLengthCap];
DISALLOW_COPY_AND_ASSIGN(GamepadPlatformDataFetcherMac);
};
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
index 51524d7f523..69d0c63e31d 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
@@ -14,8 +14,8 @@
#import <Foundation/Foundation.h>
#include <IOKit/hid/IOHIDKeys.h>
-using WebKit::WebGamepad;
-using WebKit::WebGamepads;
+using blink::WebGamepad;
+using blink::WebGamepads;
namespace content {
@@ -41,7 +41,6 @@ const uint32_t kJoystickUsageNumber = 0x04;
const uint32_t kGameUsageNumber = 0x05;
const uint32_t kMultiAxisUsageNumber = 0x08;
const uint32_t kAxisMinimumUsageNumber = 0x30;
-const uint32_t kAxisMaximumUsageNumber = 0x35;
} // namespace
@@ -267,7 +266,7 @@ void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) {
const size_t kOutputLengthBytes = sizeof(data_.items[slot].id);
memset(&data_.items[slot].id, 0, kOutputLengthBytes);
[as16 getBytes:data_.items[slot].id
- length:kOutputLengthBytes - sizeof(WebKit::WebUChar)];
+ length:kOutputLengthBytes - sizeof(blink::WebUChar)];
base::ScopedCFTypeRef<CFArrayRef> elements(
IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone));
@@ -360,7 +359,7 @@ void GamepadPlatformDataFetcherMac::XboxDeviceAdd(XboxController* device) {
const size_t kOutputLengthBytes = sizeof(data_.items[slot].id);
memset(&data_.items[slot].id, 0, kOutputLengthBytes);
[as16 getBytes:data_.items[slot].id
- length:kOutputLengthBytes - sizeof(WebKit::WebUChar)];
+ length:kOutputLengthBytes - sizeof(blink::WebUChar)];
associated_[slot].is_xbox = true;
associated_[slot].xbox.device = device;
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
index 91ebdf56519..f8f3dafb04a 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
@@ -22,7 +22,7 @@
namespace content {
-using namespace WebKit;
+using namespace blink;
namespace {
@@ -196,10 +196,10 @@ BOOL CALLBACK DirectInputEnumDevicesCallback(const DIDEVICEINSTANCE* instance,
SetDirectInputDeadZone(gamepad, 1000);
device.mapper = GetGamepadStandardMappingFunction(vendor, product);
if (device.mapper) {
- base::swprintf(device.id,
- WebGamepad::idLengthCap,
- L"STANDARD GAMEPAD (%ls)",
- instance->tszProductName);
+ swprintf(device.id,
+ WebGamepad::idLengthCap,
+ L"STANDARD GAMEPAD (%ls)",
+ instance->tszProductName);
ctxt->directinput_devices->push_back(device);
} else {
gamepad->Release();
@@ -349,10 +349,10 @@ bool GamepadPlatformDataFetcherWin::GetXInputPadConnectivity(
return false;
} else {
pad->connected = true;
- base::swprintf(pad->id,
- WebGamepad::idLengthCap,
- L"Xbox 360 Controller (XInput STANDARD %ls)",
- GamepadSubTypeName(caps.SubType));
+ swprintf(pad->id,
+ WebGamepad::idLengthCap,
+ L"Xbox 360 Controller (XInput STANDARD %ls)",
+ GamepadSubTypeName(caps.SubType));
return true;
}
}
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
index 7551ee91c4c..c894143b076 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
@@ -31,13 +31,13 @@ class GamepadPlatformDataFetcherWin : public GamepadDataFetcher {
public:
GamepadPlatformDataFetcherWin();
virtual ~GamepadPlatformDataFetcherWin();
- virtual void GetGamepadData(WebKit::WebGamepads* pads,
+ virtual void GetGamepadData(blink::WebGamepads* pads,
bool devices_changed_hint) OVERRIDE;
private:
// XInput-specific implementation for GetGamepadData.
- bool GetXInputGamepadData(WebKit::WebGamepads* pads,
+ bool GetXInputGamepadData(blink::WebGamepads* pads,
bool devices_changed_hint);
- bool GetDirectInputGamepadData(WebKit::WebGamepads* pads,
+ bool GetDirectInputGamepadData(blink::WebGamepads* pads,
bool devices_changed_hint);
// The three function types we use from xinput1_3.dll.
@@ -54,11 +54,11 @@ class GamepadPlatformDataFetcherWin : public GamepadDataFetcher {
bool GetXInputDllFunctions();
// Scan for connected XInput and DirectInput gamepads.
- void EnumerateDevices(WebKit::WebGamepads* pads);
- bool GetXInputPadConnectivity(int i, WebKit::WebGamepad* pad) const;
+ void EnumerateDevices(blink::WebGamepads* pads);
+ bool GetXInputPadConnectivity(int i, blink::WebGamepad* pad) const;
- void GetXInputPadData(int i, WebKit::WebGamepad* pad);
- void GetDirectInputPadData(int i, WebKit::WebGamepad* pad);
+ void GetXInputPadData(int i, blink::WebGamepad* pad);
+ void GetDirectInputPadData(int i, blink::WebGamepad* pad);
int FirstAvailableGamepadId() const;
bool HasXInputGamepad(int index) const;
@@ -90,7 +90,7 @@ class GamepadPlatformDataFetcherWin : public GamepadDataFetcher {
IDirectInputDevice8* directinput_gamepad;
GamepadStandardMappingFunction mapper;
};
- PadState pad_state_[WebKit::WebGamepads::itemsLengthCap];
+ PadState pad_state_[blink::WebGamepads::itemsLengthCap];
DISALLOW_COPY_AND_ASSIGN(GamepadPlatformDataFetcherWin);
};
diff --git a/chromium/content/browser/gamepad/gamepad_provider.cc b/chromium/content/browser/gamepad/gamepad_provider.cc
index 7e8e6dee132..55a5f30ed78 100644
--- a/chromium/content/browser/gamepad/gamepad_provider.cc
+++ b/chromium/content/browser/gamepad/gamepad_provider.cc
@@ -158,7 +158,7 @@ void GamepadProvider::DoPoll() {
ANNOTATE_BENIGN_RACE_SIZED(
&hwbuf->buffer,
- sizeof(WebKit::WebGamepads),
+ sizeof(blink::WebGamepads),
"Racey reads are discarded");
{
diff --git a/chromium/content/browser/gamepad/gamepad_provider_unittest.cc b/chromium/content/browser/gamepad/gamepad_provider_unittest.cc
index 0e5785cc598..398edca98e4 100644
--- a/chromium/content/browser/gamepad/gamepad_provider_unittest.cc
+++ b/chromium/content/browser/gamepad/gamepad_provider_unittest.cc
@@ -15,7 +15,7 @@ namespace content {
namespace {
-using WebKit::WebGamepads;
+using blink::WebGamepads;
// Helper class to generate and record user gesture callbacks.
class UserGestureListener {
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings.h b/chromium/content/browser/gamepad/gamepad_standard_mappings.h
index 6f5d72fc0a7..6b533ca5829 100644
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings.h
+++ b/chromium/content/browser/gamepad/gamepad_standard_mappings.h
@@ -7,15 +7,15 @@
#include "base/strings/string_piece.h"
-namespace WebKit {
+namespace blink {
class WebGamepad;
}
namespace content {
typedef void (*GamepadStandardMappingFunction)(
- const WebKit::WebGamepad& original,
- WebKit::WebGamepad* mapped);
+ const blink::WebGamepad& original,
+ blink::WebGamepad* mapped);
GamepadStandardMappingFunction GetGamepadStandardMappingFunction(
const base::StringPiece& vendor_id,
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc b/chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc
index e9e7094c532..712e753defc 100644
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc
+++ b/chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc
@@ -23,8 +23,8 @@ float AxisPositiveAsButton(float input) {
}
void MapperXInputStyleGamepad(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[2]);
mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[5]);
@@ -44,8 +44,8 @@ void MapperXInputStyleGamepad(
}
void MapperLakeviewResearch(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[kButtonPrimary] = input.buttons[2];
mapped->buttons[kButtonTertiary] = input.buttons[3];
@@ -65,8 +65,8 @@ void MapperLakeviewResearch(
}
void MapperPlaystationSixAxis(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[kButtonPrimary] = input.buttons[14];
mapped->buttons[kButtonSecondary] = input.buttons[13];
@@ -91,8 +91,8 @@ void MapperPlaystationSixAxis(
}
void MapperXGEAR(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[kButtonPrimary] = input.buttons[2];
mapped->buttons[kButtonSecondary] = input.buttons[1];
@@ -114,8 +114,8 @@ void MapperXGEAR(
void MapperDragonRiseGeneric(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[kButtonDpadUp] = AxisNegativeAsButton(input.axes[6]);
mapped->buttons[kButtonDpadDown] = AxisPositiveAsButton(input.axes[6]);
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm b/chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm
index 0ffb35f8fec..2696c53c686 100644
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm
+++ b/chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm
@@ -14,7 +14,7 @@ float AxisToButton(float input) {
return (input + 1.f) / 2.f;
}
-void DpadFromAxis(WebKit::WebGamepad* mapped, float dir) {
+void DpadFromAxis(blink::WebGamepad* mapped, float dir) {
// 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
@@ -34,8 +34,8 @@ void DpadFromAxis(WebKit::WebGamepad* mapped, float dir) {
}
void MapperXbox360Gamepad(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[2]);
mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[5]);
@@ -55,8 +55,8 @@ void MapperXbox360Gamepad(
}
void MapperPlaystationSixAxis(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[kButtonPrimary] = input.buttons[14];
mapped->buttons[kButtonSecondary] = input.buttons[13];
@@ -82,8 +82,8 @@ void MapperPlaystationSixAxis(
}
void MapperDirectInputStyle(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[kButtonPrimary] = input.buttons[1];
mapped->buttons[kButtonSecondary] = input.buttons[2];
@@ -95,8 +95,8 @@ void MapperDirectInputStyle(
}
void MapperMacallyIShock(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
enum IShockButtons {
kButtonC = kNumButtons,
kButtonD,
@@ -135,8 +135,8 @@ void MapperMacallyIShock(
}
void MapperXGEAR(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[kButtonPrimary] = input.buttons[2];
mapped->buttons[kButtonTertiary] = input.buttons[3];
@@ -153,8 +153,8 @@ void MapperXGEAR(
}
void MapperSmartJoyPLUS(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[kButtonPrimary] = input.buttons[2];
mapped->buttons[kButtonTertiary] = input.buttons[3];
@@ -172,8 +172,8 @@ void MapperSmartJoyPLUS(
}
void MapperDragonRiseGeneric(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
DpadFromAxis(mapped, input.axes[9]);
mapped->axes[kAxisLeftStickX] = input.axes[0];
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc b/chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc
index fa57c032c77..07adb9b82ad 100644
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc
+++ b/chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc
@@ -24,8 +24,8 @@ float AxisPositiveAsButton(long value) {
}
void MapperDragonRiseGeneric(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[0] = input.buttons[1];
mapped->buttons[1] = input.buttons[2];
@@ -43,8 +43,8 @@ void MapperDragonRiseGeneric(
}
void MapperLogitechDualAction(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[0] = input.buttons[1];
mapped->buttons[1] = input.buttons[2];
@@ -62,8 +62,8 @@ void MapperLogitechDualAction(
}
void MapperLogitechPrecision(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[0] = input.buttons[1];
mapped->buttons[1] = input.buttons[2];
@@ -79,8 +79,8 @@ void MapperLogitechPrecision(
}
void Mapper2Axes8Keys(
- const WebKit::WebGamepad& input,
- WebKit::WebGamepad* mapped) {
+ const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
mapped->buttons[kButtonLeftTrigger] = 0; // Not present
mapped->buttons[kButtonRightTrigger] = 0; // Not present
diff --git a/chromium/content/browser/gamepad/gamepad_test_helpers.cc b/chromium/content/browser/gamepad/gamepad_test_helpers.cc
index e4db14ce080..8837c8e59c3 100644
--- a/chromium/content/browser/gamepad/gamepad_test_helpers.cc
+++ b/chromium/content/browser/gamepad/gamepad_test_helpers.cc
@@ -9,7 +9,7 @@
namespace content {
MockGamepadDataFetcher::MockGamepadDataFetcher(
- const WebKit::WebGamepads& test_data)
+ const blink::WebGamepads& test_data)
: test_data_(test_data),
read_data_(false, false) {
}
@@ -17,7 +17,7 @@ MockGamepadDataFetcher::MockGamepadDataFetcher(
MockGamepadDataFetcher::~MockGamepadDataFetcher() {
}
-void MockGamepadDataFetcher::GetGamepadData(WebKit::WebGamepads* pads,
+void MockGamepadDataFetcher::GetGamepadData(blink::WebGamepads* pads,
bool devices_changed_hint) {
{
base::AutoLock lock(lock_);
@@ -30,7 +30,7 @@ void MockGamepadDataFetcher::WaitForDataRead() {
return read_data_.Wait();
}
-void MockGamepadDataFetcher::SetTestData(const WebKit::WebGamepads& new_data) {
+void MockGamepadDataFetcher::SetTestData(const blink::WebGamepads& new_data) {
base::AutoLock lock(lock_);
test_data_ = new_data;
}
@@ -42,7 +42,7 @@ GamepadTestHelper::~GamepadTestHelper() {
}
GamepadServiceTestConstructor::GamepadServiceTestConstructor(
- const WebKit::WebGamepads& test_data) {
+ const blink::WebGamepads& test_data) {
data_fetcher_ = new MockGamepadDataFetcher(test_data);
gamepad_service_ =
new GamepadService(scoped_ptr<GamepadDataFetcher>(data_fetcher_));
diff --git a/chromium/content/browser/gamepad/gamepad_test_helpers.h b/chromium/content/browser/gamepad/gamepad_test_helpers.h
index 3b43f7787ff..2aad5753b27 100644
--- a/chromium/content/browser/gamepad/gamepad_test_helpers.h
+++ b/chromium/content/browser/gamepad/gamepad_test_helpers.h
@@ -21,12 +21,12 @@ 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 WebKit::WebGamepads& test_data);
+ explicit MockGamepadDataFetcher(const blink::WebGamepads& test_data);
virtual ~MockGamepadDataFetcher();
// GamepadDataFetcher.
- virtual void GetGamepadData(WebKit::WebGamepads* pads,
+ virtual void GetGamepadData(blink::WebGamepads* pads,
bool devices_changed_hint) OVERRIDE;
// Blocks the current thread until the GamepadProvider reads from this
@@ -34,11 +34,11 @@ class MockGamepadDataFetcher : public GamepadDataFetcher {
void WaitForDataRead();
// Updates the test data.
- void SetTestData(const WebKit::WebGamepads& new_data);
+ void SetTestData(const blink::WebGamepads& new_data);
private:
base::Lock lock_;
- WebKit::WebGamepads test_data_;
+ blink::WebGamepads test_data_;
base::WaitableEvent read_data_;
DISALLOW_COPY_AND_ASSIGN(MockGamepadDataFetcher);
@@ -63,7 +63,7 @@ class GamepadTestHelper {
// global singleton for the gamepad service.
class GamepadServiceTestConstructor : public GamepadTestHelper {
public:
- explicit GamepadServiceTestConstructor(const WebKit::WebGamepads& test_data);
+ explicit GamepadServiceTestConstructor(const blink::WebGamepads& test_data);
virtual ~GamepadServiceTestConstructor();
GamepadService* gamepad_service() { return gamepad_service_; }
diff --git a/chromium/content/browser/geolocation/OWNERS b/chromium/content/browser/geolocation/OWNERS
index c2252ab07e2..df10cf46d57 100644
--- a/chromium/content/browser/geolocation/OWNERS
+++ b/chromium/content/browser/geolocation/OWNERS
@@ -1,6 +1,3 @@
-# Reviews:
-# Not yet owner - mvanouwerkerk@chromium.org
bulach@chromium.org
-
-# Just owners:
-joth@chromium.org
+mvanouwerkerk@chromium.org
+timvolodine@chromium.org
diff --git a/chromium/content/browser/geolocation/empty_wifi_data_provider.cc b/chromium/content/browser/geolocation/empty_wifi_data_provider.cc
index 7255f46fcc9..d24213155d5 100644
--- a/chromium/content/browser/geolocation/empty_wifi_data_provider.cc
+++ b/chromium/content/browser/geolocation/empty_wifi_data_provider.cc
@@ -18,12 +18,9 @@ bool EmptyWifiDataProvider::GetData(WifiData* data) {
return true;
}
-// Only define for platforms that lack a real wifi data provider.
-#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
// static
WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
return new EmptyWifiDataProvider();
}
-#endif
} // namespace content
diff --git a/chromium/content/browser/geolocation/fake_access_token_store.cc b/chromium/content/browser/geolocation/fake_access_token_store.cc
index 9f9f61ba7f7..0e5fe401289 100644
--- a/chromium/content/browser/geolocation/fake_access_token_store.cc
+++ b/chromium/content/browser/geolocation/fake_access_token_store.cc
@@ -45,7 +45,7 @@ void FakeAccessTokenStore::DefaultLoadAccessTokens(
}
void FakeAccessTokenStore::DefaultSaveAccessToken(
- const GURL& server_url, const string16& access_token) {
+ const GURL& server_url, const base::string16& access_token) {
DCHECK(server_url.is_valid());
access_token_set_[server_url] = access_token;
}
diff --git a/chromium/content/browser/geolocation/fake_access_token_store.h b/chromium/content/browser/geolocation/fake_access_token_store.h
index 4d0867bf0be..30a01859d10 100644
--- a/chromium/content/browser/geolocation/fake_access_token_store.h
+++ b/chromium/content/browser/geolocation/fake_access_token_store.h
@@ -23,12 +23,13 @@ class FakeAccessTokenStore : public AccessTokenStore {
MOCK_METHOD1(LoadAccessTokens,
void(const LoadAccessTokensCallbackType& callback));
MOCK_METHOD2(SaveAccessToken,
- void(const GURL& server_url, const string16& access_token));
+ void(const GURL& server_url,
+ const base::string16& access_token));
void DefaultLoadAccessTokens(const LoadAccessTokensCallbackType& callback);
void DefaultSaveAccessToken(const GURL& server_url,
- const string16& access_token);
+ const base::string16& access_token);
AccessTokenSet access_token_set_;
LoadAccessTokensCallbackType callback_;
diff --git a/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc b/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc
index 38f77504cfb..e461e63464d 100644
--- a/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc
+++ b/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc
@@ -9,6 +9,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/metrics/histogram.h"
#include "content/browser/geolocation/geolocation_provider_impl.h"
#include "content/browser/renderer_host/render_message_filter.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -65,26 +66,41 @@ class GeolocationDispatcherHostImpl : public GeolocationDispatcherHost {
const GURL& requesting_frame);
void OnStartUpdating(int render_view_id,
const GURL& requesting_frame,
- bool enable_high_accuracy);
+ bool enable_high_accuracy);
void OnStopUpdating(int render_view_id);
+
+ virtual void PauseOrResume(int render_view_id, bool should_pause) OVERRIDE;
+
// Updates the |geolocation_provider_| with the currently required update
- // options, based on |renderer_high_accuracy_|.
- void RefreshHighAccuracy();
+ // options.
+ void RefreshGeolocationOptions();
void OnLocationUpdate(const Geoposition& position);
int render_process_id_;
scoped_refptr<GeolocationPermissionContext> geolocation_permission_context_;
- // Iterated when sending location updates to renderer processes. The fan out
- // to individual bridge IDs happens renderer side, in order to minimize
- // context switches.
+ struct RendererGeolocationOptions {
+ bool high_accuracy;
+ bool is_paused;
+ };
+
+ // Used to keep track of the renderers in this process that are using
+ // geolocation and the options associated with them. The map is iterated
+ // when a location update is available and the fan out to individual bridge
+ // IDs happens renderer side, in order to minimize context switches.
// Only used on the IO thread.
- std::set<int> geolocation_renderer_ids_;
- // Maps renderer_id to whether high accuracy is requested for this particular
- // bridge.
- std::map<int, bool> renderer_high_accuracy_;
+ std::map<int, RendererGeolocationOptions> geolocation_renderers_;
+
+ // Used by Android WebView to support that case that a renderer is in the
+ // 'paused' state but not yet using geolocation. If the renderer does start
+ // using geolocation while paused, we move from this set into
+ // |geolocation_renderers_|. If the renderer doesn't end up wanting to use
+ // geolocation while 'paused' then we remove from this set. A renderer id
+ // can exist only in this set or |geolocation_renderers_|, never both.
+ std::set<int> pending_paused_geolocation_renderers_;
+
// Only set whilst we are registered with the geolocation provider.
GeolocationProviderImpl* geolocation_provider_;
@@ -107,6 +123,7 @@ GeolocationDispatcherHostImpl::GeolocationDispatcherHostImpl(
}
GeolocationDispatcherHostImpl::~GeolocationDispatcherHostImpl() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (geolocation_provider_)
geolocation_provider_->RemoveLocationUpdateCallback(callback_);
}
@@ -131,9 +148,11 @@ bool GeolocationDispatcherHostImpl::OnMessageReceived(
void GeolocationDispatcherHostImpl::OnLocationUpdate(
const Geoposition& geoposition) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- for (std::set<int>::iterator it = geolocation_renderer_ids_.begin();
- it != geolocation_renderer_ids_.end(); ++it) {
- Send(new GeolocationMsg_PositionUpdated(*it, geoposition));
+ for (std::map<int, RendererGeolocationOptions>::iterator it =
+ geolocation_renderers_.begin();
+ it != geolocation_renderers_.end(); ++it) {
+ if (!(it->second.is_paused))
+ Send(new GeolocationMsg_PositionUpdated(it->first, geoposition));
}
}
@@ -184,47 +203,84 @@ void GeolocationDispatcherHostImpl::OnStartUpdating(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
<< render_view_id;
- if (!geolocation_renderer_ids_.count(render_view_id))
- geolocation_renderer_ids_.insert(render_view_id);
-
- renderer_high_accuracy_[render_view_id] = enable_high_accuracy;
- RefreshHighAccuracy();
+ UMA_HISTOGRAM_BOOLEAN(
+ "Geolocation.GeolocationDispatcherHostImpl.EnableHighAccuracy",
+ enable_high_accuracy);
+
+ std::map<int, RendererGeolocationOptions>::iterator it =
+ geolocation_renderers_.find(render_view_id);
+ if (it == geolocation_renderers_.end()) {
+ bool should_start_paused = false;
+ if (pending_paused_geolocation_renderers_.erase(render_view_id) == 1) {
+ should_start_paused = true;
+ }
+ RendererGeolocationOptions opts = {
+ enable_high_accuracy,
+ should_start_paused
+ };
+ geolocation_renderers_[render_view_id] = opts;
+ } else {
+ it->second.high_accuracy = enable_high_accuracy;
+ }
+ RefreshGeolocationOptions();
}
void GeolocationDispatcherHostImpl::OnStopUpdating(int render_view_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
<< render_view_id;
- if (renderer_high_accuracy_.erase(render_view_id))
- RefreshHighAccuracy();
-
- DCHECK_EQ(1U, geolocation_renderer_ids_.count(render_view_id));
- geolocation_renderer_ids_.erase(render_view_id);
+ DCHECK_EQ(1U, geolocation_renderers_.count(render_view_id));
+ geolocation_renderers_.erase(render_view_id);
+ RefreshGeolocationOptions();
}
-void GeolocationDispatcherHostImpl::RefreshHighAccuracy() {
+void GeolocationDispatcherHostImpl::PauseOrResume(int render_view_id,
+ bool should_pause) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (renderer_high_accuracy_.empty()) {
- if (geolocation_provider_) {
- geolocation_provider_->RemoveLocationUpdateCallback(callback_);
- geolocation_provider_ = NULL;
+ std::map<int, RendererGeolocationOptions>::iterator it =
+ geolocation_renderers_.find(render_view_id);
+ if (it == geolocation_renderers_.end()) {
+ // This renderer is not using geolocation yet, but if it does before
+ // we get a call to resume, we should start it up in the paused state.
+ if (should_pause) {
+ pending_paused_geolocation_renderers_.insert(render_view_id);
+ } else {
+ pending_paused_geolocation_renderers_.erase(render_view_id);
}
} else {
+ RendererGeolocationOptions* opts = &(it->second);
+ if (opts->is_paused != should_pause)
+ opts->is_paused = should_pause;
+ RefreshGeolocationOptions();
+ }
+}
+
+void GeolocationDispatcherHostImpl::RefreshGeolocationOptions() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ bool needs_updates = false;
+ bool use_high_accuracy = false;
+ std::map<int, RendererGeolocationOptions>::const_iterator i =
+ geolocation_renderers_.begin();
+ for (; i != geolocation_renderers_.end(); ++i) {
+ needs_updates |= !(i->second.is_paused);
+ use_high_accuracy |= i->second.high_accuracy;
+ if (needs_updates && use_high_accuracy)
+ break;
+ }
+ if (needs_updates) {
if (!geolocation_provider_)
geolocation_provider_ = GeolocationProviderImpl::GetInstance();
// Re-add to re-establish our options, in case they changed.
- bool use_high_accuracy = false;
- std::map<int, bool>::iterator i = renderer_high_accuracy_.begin();
- for (; i != renderer_high_accuracy_.end(); ++i) {
- if (i->second) {
- use_high_accuracy = true;
- break;
- }
- }
geolocation_provider_->AddLocationUpdateCallback(
callback_, use_high_accuracy);
+ } else {
+ if (geolocation_provider_)
+ geolocation_provider_->RemoveLocationUpdateCallback(callback_);
+ geolocation_provider_ = NULL;
}
}
+
} // namespace
diff --git a/chromium/content/browser/geolocation/geolocation_dispatcher_host.h b/chromium/content/browser/geolocation/geolocation_dispatcher_host.h
index 0631c8718f2..5620e262f8b 100644
--- a/chromium/content/browser/geolocation/geolocation_dispatcher_host.h
+++ b/chromium/content/browser/geolocation/geolocation_dispatcher_host.h
@@ -19,6 +19,13 @@ class GeolocationDispatcherHost : public BrowserMessageFilter {
int render_process_id,
GeolocationPermissionContext* geolocation_permission_context);
+ // Pause or resumes geolocation for the given |render_view_id|. Should
+ // be called on the IO thread. Resuming when nothing is paused is a no-op.
+ // If a renderer is paused while not currently using geolocation but
+ // then goes on to do so before being resumed, then that renderer will
+ // not get geolocation updates until it is resumed.
+ virtual void PauseOrResume(int render_view_id, bool should_pause) = 0;
+
protected:
GeolocationDispatcherHost();
virtual ~GeolocationDispatcherHost();
diff --git a/chromium/content/browser/geolocation/gps_location_provider_linux.cc b/chromium/content/browser/geolocation/gps_location_provider_linux.cc
deleted file mode 100644
index 685c3c35aac..00000000000
--- a/chromium/content/browser/geolocation/gps_location_provider_linux.cc
+++ /dev/null
@@ -1,302 +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/geolocation/gps_location_provider_linux.h"
-
-#include <errno.h>
-
-#include <algorithm>
-#include <cmath>
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/stringprintf.h"
-#include "content/public/common/geoposition.h"
-
-namespace content {
-namespace {
-
-const int kGpsdReconnectRetryIntervalMillis = 10 * 1000;
-
-// As per http://gpsd.berlios.de/performance.html#id374524, poll twice per sec.
-const int kPollPeriodMovingMillis = 500;
-
-// Poll less frequently whilst stationary.
-const int kPollPeriodStationaryMillis = kPollPeriodMovingMillis * 3;
-
-// GPS reading must differ by more than this amount to be considered movement.
-const int kMovementThresholdMeters = 20;
-
-// This algorithm is reused from the corresponding code in the Gears project.
-// The arbitrary delta is decreased (Gears used 100 meters); if we need to
-// decrease it any further we'll likely want to do some smarter filtering to
-// remove GPS location jitter noise.
-bool PositionsDifferSiginificantly(const Geoposition& position_1,
- const Geoposition& position_2) {
- const bool pos_1_valid = position_1.Validate();
- if (pos_1_valid != position_2.Validate())
- return true;
- if (!pos_1_valid) {
- DCHECK(!position_2.Validate());
- return false;
- }
- double delta = std::sqrt(
- std::pow(std::fabs(position_1.latitude - position_2.latitude), 2) +
- std::pow(std::fabs(position_1.longitude - position_2.longitude), 2));
- // Convert to meters. 1 minute of arc of latitude (or longitude at the
- // equator) is 1 nautical mile or 1852m.
- delta *= 60 * 1852;
- return delta > kMovementThresholdMeters;
-}
-
-} // namespace
-
-#if defined(USE_LIBGPS)
-
-// See http://crbug.com/103751.
-COMPILE_ASSERT(GPSD_API_MAJOR_VERSION == 5, GPSD_API_version_is_not_5);
-
-namespace {
-
-const char kLibGpsName[] = "libgps.so.20";
-
-} // namespace
-
-LibGps::LibGps()
- : gps_data_(new gps_data_t),
- is_open_(false) {
-}
-
-LibGps::~LibGps() {
- Stop();
-}
-
-LibGps* LibGps::New() {
- scoped_ptr<LibGps> libgps(new LibGps);
- if (!libgps->libgps_loader_.Load(kLibGpsName))
- return NULL;
-
- return libgps.release();
-}
-
-bool LibGps::Start() {
- if (is_open_)
- return true;
-
- errno = 0;
- if (libgps_loader_.gps_open(GPSD_SHARED_MEMORY, 0, gps_data_.get()) != 0) {
- // See gps.h NL_NOxxx for definition of gps_open() error numbers.
- DLOG(WARNING) << "gps_open() failed " << errno;
- return false;
- }
-
- is_open_ = true;
- return true;
-}
-
-void LibGps::Stop() {
- if (is_open_)
- libgps_loader_.gps_close(gps_data_.get());
- is_open_ = false;
-}
-
-bool LibGps::Read(Geoposition* position) {
- DCHECK(position);
- position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
- if (!is_open_) {
- DLOG(WARNING) << "No gpsd connection";
- position->error_message = "No gpsd connection";
- return false;
- }
-
- if (libgps_loader_.gps_read(gps_data_.get()) < 0) {
- DLOG(WARNING) << "gps_read() fails";
- position->error_message = "gps_read() fails";
- return false;
- }
-
- if (!GetPositionIfFixed(position)) {
- DLOG(WARNING) << "No fixed position";
- position->error_message = "No fixed position";
- return false;
- }
-
- position->error_code = Geoposition::ERROR_CODE_NONE;
- position->timestamp = base::Time::Now();
- if (!position->Validate()) {
- // GetPositionIfFixed returned true, yet we've not got a valid fix.
- // This shouldn't happen; something went wrong in the conversion.
- NOTREACHED() << "Invalid position from GetPositionIfFixed: lat,long "
- << position->latitude << "," << position->longitude
- << " accuracy " << position->accuracy << " time "
- << position->timestamp.ToDoubleT();
- position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
- position->error_message = "Bad fix from gps";
- return false;
- }
- return true;
-}
-
-bool LibGps::GetPositionIfFixed(Geoposition* position) {
- DCHECK(position);
- if (gps_data_->status == STATUS_NO_FIX) {
- DVLOG(2) << "Status_NO_FIX";
- return false;
- }
-
- if (isnan(gps_data_->fix.latitude) || isnan(gps_data_->fix.longitude)) {
- DVLOG(2) << "No valid lat/lon value";
- return false;
- }
-
- position->latitude = gps_data_->fix.latitude;
- position->longitude = gps_data_->fix.longitude;
-
- if (!isnan(gps_data_->fix.epx) && !isnan(gps_data_->fix.epy)) {
- position->accuracy = std::max(gps_data_->fix.epx, gps_data_->fix.epy);
- } else if (isnan(gps_data_->fix.epx) && !isnan(gps_data_->fix.epy)) {
- position->accuracy = gps_data_->fix.epy;
- } else if (!isnan(gps_data_->fix.epx) && isnan(gps_data_->fix.epy)) {
- position->accuracy = gps_data_->fix.epx;
- } else {
- // TODO(joth): Fixme. This is a workaround for http://crbug.com/99326
- DVLOG(2) << "libgps reported accuracy NaN, forcing to zero";
- position->accuracy = 0;
- }
-
- if (gps_data_->fix.mode == MODE_3D && !isnan(gps_data_->fix.altitude)) {
- position->altitude = gps_data_->fix.altitude;
- if (!isnan(gps_data_->fix.epv))
- position->altitude_accuracy = gps_data_->fix.epv;
- }
-
- if (!isnan(gps_data_->fix.track))
- position->heading = gps_data_->fix.track;
- if (!isnan(gps_data_->fix.speed))
- position->speed = gps_data_->fix.speed;
- return true;
-}
-
-#else // !defined(USE_LIBGPS)
-
-// Stub implementation of LibGps.
-LibGps::LibGps() {
-}
-
-LibGps::~LibGps() {
-}
-
-LibGps* LibGps::New() {
- return NULL;
-}
-
-bool LibGps::Start() {
- return false;
-}
-
-void LibGps::Stop() {
-}
-
-bool LibGps::Read(Geoposition* position) {
- return false;
-}
-
-bool LibGps::GetPositionIfFixed(Geoposition* position) {
- return false;
-}
-
-#endif // !defined(USE_LIBGPS)
-
-GpsLocationProviderLinux::GpsLocationProviderLinux(LibGpsFactory libgps_factory)
- : gpsd_reconnect_interval_millis_(kGpsdReconnectRetryIntervalMillis),
- poll_period_moving_millis_(kPollPeriodMovingMillis),
- poll_period_stationary_millis_(kPollPeriodStationaryMillis),
- libgps_factory_(libgps_factory),
- weak_factory_(this) {
- DCHECK(libgps_factory_);
-}
-
-GpsLocationProviderLinux::~GpsLocationProviderLinux() {
-}
-
-bool GpsLocationProviderLinux::StartProvider(bool high_accuracy) {
- if (!high_accuracy) {
- StopProvider();
- return true; // Not an error condition, so still return true.
- }
- if (gps_ != NULL) {
- DCHECK(weak_factory_.HasWeakPtrs());
- return true;
- }
- position_.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
- gps_.reset(libgps_factory_());
- if (gps_ == NULL) {
- DLOG(WARNING) << "libgps could not be loaded";
- return false;
- }
- ScheduleNextGpsPoll(0);
- return true;
-}
-
-void GpsLocationProviderLinux::StopProvider() {
- weak_factory_.InvalidateWeakPtrs();
- gps_.reset();
-}
-
-void GpsLocationProviderLinux::GetPosition(Geoposition* position) {
- DCHECK(position);
- *position = position_;
- DCHECK(position->Validate() ||
- position->error_code != Geoposition::ERROR_CODE_NONE);
-}
-
-void GpsLocationProviderLinux::RequestRefresh() {
- ScheduleNextGpsPoll(0);
-}
-
-void GpsLocationProviderLinux::OnPermissionGranted() {
-}
-
-void GpsLocationProviderLinux::DoGpsPollTask() {
- if (!gps_->Start()) {
- DLOG(WARNING) << "Couldn't start GPS provider.";
- ScheduleNextGpsPoll(gpsd_reconnect_interval_millis_);
- return;
- }
-
- Geoposition new_position;
- if (!gps_->Read(&new_position)) {
- ScheduleNextGpsPoll(poll_period_stationary_millis_);
- return;
- }
-
- DCHECK(new_position.Validate() ||
- new_position.error_code != Geoposition::ERROR_CODE_NONE);
- const bool differ = PositionsDifferSiginificantly(position_, new_position);
- ScheduleNextGpsPoll(differ ? poll_period_moving_millis_ :
- poll_period_stationary_millis_);
- if (differ || new_position.error_code != Geoposition::ERROR_CODE_NONE) {
- // Update if the new location is interesting or we have an error to report.
- position_ = new_position;
- NotifyCallback(position_);
- }
-}
-
-void GpsLocationProviderLinux::ScheduleNextGpsPoll(int interval) {
- weak_factory_.InvalidateWeakPtrs();
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&GpsLocationProviderLinux::DoGpsPollTask,
- weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(interval));
-}
-
-LocationProvider* NewSystemLocationProvider() {
- return new GpsLocationProviderLinux(LibGps::New);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/geolocation/gps_location_provider_linux.h b/chromium/content/browser/geolocation/gps_location_provider_linux.h
deleted file mode 100644
index 76589379641..00000000000
--- a/chromium/content/browser/geolocation/gps_location_provider_linux.h
+++ /dev/null
@@ -1,105 +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 file declares GPS providers that run on linux. Currently, just uses
-// the libgps (gpsd) API. Public for testing only - for normal usage this
-// header should not be required, as location_provider.h declares the needed
-// factory function.
-
-#ifndef CONTENT_BROWSER_GEOLOCATION_GPS_LOCATION_PROVIDER_LINUX_H_
-#define CONTENT_BROWSER_GEOLOCATION_GPS_LOCATION_PROVIDER_LINUX_H_
-
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/geolocation/location_provider_base.h"
-#include "content/common/content_export.h"
-#include "content/public/common/geoposition.h"
-
-#if defined(USE_LIBGPS)
-#include "library_loaders/libgps.h"
-#endif
-
-struct gps_data_t;
-
-namespace content {
-
-// Defines a wrapper around the C libgps API (gps.h). Similar to the libgpsmm.h
-// API provided by that package.
-class CONTENT_EXPORT LibGps {
- public:
- virtual ~LibGps();
- // Attempts to dynamically load the libgps.so library and returns NULL on
- // failure.
- static LibGps* New();
-
- bool Start();
- void Stop();
- bool Read(content::Geoposition* position);
-
- protected:
- LibGps();
-
- // Returns false if there is no fix available.
- virtual bool GetPositionIfFixed(content::Geoposition* position);
-
-#if defined(USE_LIBGPS)
- LibGpsLoader libgps_loader_;
-
- scoped_ptr<gps_data_t> gps_data_;
- bool is_open_;
-#endif // defined(USE_LIBGPS)
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LibGps);
-};
-
-// Location provider for Linux, that uses libgps/gpsd to obtain position fixes.
-class CONTENT_EXPORT GpsLocationProviderLinux : public LocationProviderBase {
- public:
- typedef LibGps* (*LibGpsFactory)();
- // |factory| will be used to create the gpsd client library wrapper. (Note
- // NewSystemLocationProvider() will use the default factory).
- explicit GpsLocationProviderLinux(LibGpsFactory libgps_factory);
- virtual ~GpsLocationProviderLinux();
-
- void SetGpsdReconnectIntervalMillis(int value) {
- gpsd_reconnect_interval_millis_ = value;
- }
- void SetPollPeriodMovingMillis(int value) {
- poll_period_moving_millis_ = value;
- }
- void SetPollPeriodStationaryMillis(int value) {
- poll_period_stationary_millis_ = value;
- }
-
- // LocationProvider
- virtual bool StartProvider(bool high_accuracy) OVERRIDE;
- virtual void StopProvider() OVERRIDE;
- virtual void GetPosition(Geoposition* position) OVERRIDE;
- virtual void RequestRefresh() OVERRIDE;
- virtual void OnPermissionGranted() OVERRIDE;
-
- private:
- // Task which run in the child thread.
- void DoGpsPollTask();
-
- // Will schedule a poll; i.e. enqueue DoGpsPollTask deferred task.
- void ScheduleNextGpsPoll(int interval);
-
- int gpsd_reconnect_interval_millis_;
- int poll_period_moving_millis_;
- int poll_period_stationary_millis_;
-
- const LibGpsFactory libgps_factory_;
- scoped_ptr<LibGps> gps_;
- Geoposition position_;
-
- // Holder for the tasks which run on the thread; takes care of cleanup.
- base::WeakPtrFactory<GpsLocationProviderLinux> weak_factory_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GEOLOCATION_GPS_LOCATION_PROVIDER_LINUX_H_
diff --git a/chromium/content/browser/geolocation/gps_location_provider_unittest_linux.cc b/chromium/content/browser/geolocation/gps_location_provider_unittest_linux.cc
deleted file mode 100644
index 41967a45f96..00000000000
--- a/chromium/content/browser/geolocation/gps_location_provider_unittest_linux.cc
+++ /dev/null
@@ -1,208 +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/browser_thread_impl.h"
-#include "content/browser/geolocation/gps_location_provider_linux.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include "base/bind.h"
-
-namespace content {
-
-class MockLibGps : public LibGps {
- public:
- MockLibGps();
- virtual ~MockLibGps();
-
- virtual bool GetPositionIfFixed(Geoposition* position) OVERRIDE {
- CHECK(position);
- ++get_position_calls_;
- *position = get_position_;
- return get_position_ret_;
- }
-
- static int gps_open_stub(const char*, const char*, struct gps_data_t*) {
- CHECK(g_instance_);
- g_instance_->gps_open_calls_++;
- return g_instance_->gps_open_ret_;
- }
-
- static int gps_close_stub(struct gps_data_t*) {
- return 0;
- }
-
- static int gps_read_stub(struct gps_data_t*) {
- CHECK(g_instance_);
- g_instance_->gps_read_calls_++;
- return g_instance_->gps_read_ret_;
- }
-
- int get_position_calls_;
- bool get_position_ret_;
- int gps_open_calls_;
- int gps_open_ret_;
- int gps_read_calls_;
- int gps_read_ret_;
- Geoposition get_position_;
- static MockLibGps* g_instance_;
-};
-
-class GeolocationGpsProviderLinuxTests : public testing::Test {
- public:
- GeolocationGpsProviderLinuxTests();
- virtual ~GeolocationGpsProviderLinuxTests();
-
- static LibGps* NewMockLibGps() {
- return new MockLibGps();
- }
- static LibGps* NoLibGpsFactory() {
- return NULL;
- }
-
- protected:
- base::MessageLoop message_loop_;
- BrowserThreadImpl ui_thread_;
- scoped_ptr<LocationProvider> provider_;
-};
-
-void CheckValidPosition(const Geoposition& expected,
- const Geoposition& actual) {
- EXPECT_TRUE(actual.Validate());
- EXPECT_DOUBLE_EQ(expected.latitude, actual.latitude);
- EXPECT_DOUBLE_EQ(expected.longitude, actual.longitude);
- EXPECT_DOUBLE_EQ(expected.accuracy, actual.accuracy);
-}
-
-void QuitMessageLoopAfterUpdate(const LocationProvider* provider,
- const Geoposition& position) {
- base::MessageLoop::current()->Quit();
-}
-
-MockLibGps* MockLibGps::g_instance_ = NULL;
-
-MockLibGps::MockLibGps()
- : get_position_calls_(0),
- get_position_ret_(true),
- gps_open_calls_(0),
- gps_open_ret_(0),
- gps_read_calls_(0),
- gps_read_ret_(0) {
- get_position_.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
- EXPECT_FALSE(g_instance_);
- g_instance_ = this;
-#if defined(USE_LIBGPS)
- libgps_loader_.gps_open = gps_open_stub;
- libgps_loader_.gps_close = gps_close_stub;
- libgps_loader_.gps_read = gps_read_stub;
-#endif // defined(USE_LIBGPS)
-}
-
-MockLibGps::~MockLibGps() {
- EXPECT_EQ(this, g_instance_);
- g_instance_ = NULL;
-}
-
-GeolocationGpsProviderLinuxTests::GeolocationGpsProviderLinuxTests()
- : ui_thread_(BrowserThread::IO, &message_loop_),
- provider_(new GpsLocationProviderLinux(NewMockLibGps)) {
- provider_->SetUpdateCallback(base::Bind(&QuitMessageLoopAfterUpdate));
-}
-
-GeolocationGpsProviderLinuxTests::~GeolocationGpsProviderLinuxTests() {
-}
-
-TEST_F(GeolocationGpsProviderLinuxTests, NoLibGpsInstalled) {
- provider_.reset(new GpsLocationProviderLinux(NoLibGpsFactory));
- ASSERT_TRUE(provider_.get());
- const bool ok = provider_->StartProvider(true);
- EXPECT_FALSE(ok);
- Geoposition position;
- provider_->GetPosition(&position);
- EXPECT_FALSE(position.Validate());
- EXPECT_EQ(Geoposition::ERROR_CODE_POSITION_UNAVAILABLE, position.error_code);
-}
-
-#if defined(OS_CHROMEOS)
-
-TEST_F(GeolocationGpsProviderLinuxTests, GetPosition) {
- ASSERT_TRUE(provider_.get());
- const bool ok = provider_->StartProvider(true);
- EXPECT_TRUE(ok);
- ASSERT_TRUE(MockLibGps::g_instance_);
- EXPECT_EQ(0, MockLibGps::g_instance_->get_position_calls_);
- EXPECT_EQ(0, MockLibGps::g_instance_->gps_open_calls_);
- EXPECT_EQ(0, MockLibGps::g_instance_->gps_read_calls_);
- Geoposition position;
- provider_->GetPosition(&position);
- EXPECT_FALSE(position.Validate());
- EXPECT_EQ(Geoposition::ERROR_CODE_POSITION_UNAVAILABLE, position.error_code);
- MockLibGps::g_instance_->get_position_.error_code =
- Geoposition::ERROR_CODE_NONE;
- MockLibGps::g_instance_->get_position_.latitude = 4.5;
- MockLibGps::g_instance_->get_position_.longitude = -34.1;
- MockLibGps::g_instance_->get_position_.accuracy = 345;
- MockLibGps::g_instance_->get_position_.timestamp =
- base::Time::FromDoubleT(200);
- EXPECT_TRUE(MockLibGps::g_instance_->get_position_.Validate());
- base::MessageLoop::current()->Run();
- EXPECT_EQ(1, MockLibGps::g_instance_->get_position_calls_);
- EXPECT_EQ(1, MockLibGps::g_instance_->gps_open_calls_);
- EXPECT_EQ(1, MockLibGps::g_instance_->gps_read_calls_);
- provider_->GetPosition(&position);
- CheckValidPosition(MockLibGps::g_instance_->get_position_, position);
-
- // Movement. This will block for up to half a second.
- MockLibGps::g_instance_->get_position_.latitude += 0.01;
- base::MessageLoop::current()->Run();
- provider_->GetPosition(&position);
- EXPECT_EQ(2, MockLibGps::g_instance_->get_position_calls_);
- EXPECT_EQ(1, MockLibGps::g_instance_->gps_open_calls_);
- EXPECT_EQ(2, MockLibGps::g_instance_->gps_read_calls_);
- CheckValidPosition(MockLibGps::g_instance_->get_position_, position);
-}
-
-void EnableGpsOpenCallback() {
- CHECK(MockLibGps::g_instance_);
- MockLibGps::g_instance_->gps_open_ret_ = 0;
-}
-
-TEST_F(GeolocationGpsProviderLinuxTests, LibGpsReconnect) {
- // Setup gpsd reconnect interval to be 1000ms to speed up test.
- GpsLocationProviderLinux* gps_provider =
- static_cast<GpsLocationProviderLinux*>(provider_.get());
- gps_provider->SetGpsdReconnectIntervalMillis(1000);
- gps_provider->SetPollPeriodMovingMillis(200);
- const bool ok = provider_->StartProvider(true);
- EXPECT_TRUE(ok);
- ASSERT_TRUE(MockLibGps::g_instance_);
- // Let gps_open() fails, and so will LibGps::Start().
- // Reconnect will happen in 1000ms.
- MockLibGps::g_instance_->gps_open_ret_ = 1;
- Geoposition position;
- MockLibGps::g_instance_->get_position_.error_code =
- Geoposition::ERROR_CODE_NONE;
- MockLibGps::g_instance_->get_position_.latitude = 4.5;
- MockLibGps::g_instance_->get_position_.longitude = -34.1;
- MockLibGps::g_instance_->get_position_.accuracy = 345;
- MockLibGps::g_instance_->get_position_.timestamp =
- base::Time::FromDoubleT(200);
- EXPECT_TRUE(MockLibGps::g_instance_->get_position_.Validate());
- // This task makes gps_open() and LibGps::Start() to succeed after
- // 1500ms.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&EnableGpsOpenCallback),
- base::TimeDelta::FromMilliseconds(1500));
- base::MessageLoop::current()->Run();
- provider_->GetPosition(&position);
- EXPECT_TRUE(position.Validate());
- // 3 gps_open() calls are expected (2 failures and 1 success)
- EXPECT_EQ(1, MockLibGps::g_instance_->get_position_calls_);
- EXPECT_EQ(3, MockLibGps::g_instance_->gps_open_calls_);
- EXPECT_EQ(1, MockLibGps::g_instance_->gps_read_calls_);
-}
-
-#endif // #if defined(OS_CHROMEOS)
-
-} // namespace content
diff --git a/chromium/content/browser/geolocation/location_api_adapter_android.cc b/chromium/content/browser/geolocation/location_api_adapter_android.cc
index 3ab693b33d1..84cfd101fd3 100644
--- a/chromium/content/browser/geolocation/location_api_adapter_android.cc
+++ b/chromium/content/browser/geolocation/location_api_adapter_android.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "content/browser/geolocation/location_provider_android.h"
-#include "jni/LocationProvider_jni.h"
+#include "jni/LocationProviderAdapter_jni.h"
using base::android::AttachCurrentThread;
using base::android::CheckException;
@@ -65,7 +65,7 @@ bool AndroidLocationApiAdapter::Start(
CHECK(!java_location_provider_android_object_.is_null());
// We'll start receiving notifications from java in the main thread looper
// until Stop() is called.
- return Java_LocationProvider_start(env,
+ return Java_LocationProviderAdapter_start(env,
java_location_provider_android_object_.obj(), high_accuracy);
}
@@ -84,7 +84,8 @@ void AndroidLocationApiAdapter::Stop() {
location_provider_ = NULL;
JNIEnv* env = AttachCurrentThread();
- Java_LocationProvider_stop(env, java_location_provider_android_object_.obj());
+ Java_LocationProviderAdapter_stop(
+ env, java_location_provider_android_object_.obj());
java_location_provider_android_object_.Reset();
}
@@ -143,7 +144,7 @@ bool AndroidLocationApiAdapter::RegisterGeolocationService(JNIEnv* env) {
void AndroidLocationApiAdapter::CreateJavaObject(JNIEnv* env) {
// Create the Java AndroidLocationProvider object.
java_location_provider_android_object_.Reset(
- Java_LocationProvider_create(env,
+ Java_LocationProviderAdapter_create(env,
base::android::GetApplicationContext()));
CHECK(!java_location_provider_android_object_.is_null());
}
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl.cc b/chromium/content/browser/geolocation/location_arbitrator_impl.cc
index 149eb133b8e..b8ed8c49bf5 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl.cc
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl.cc
@@ -149,7 +149,7 @@ LocationProvider* LocationArbitratorImpl::NewNetworkLocationProvider(
AccessTokenStore* access_token_store,
net::URLRequestContextGetter* context,
const GURL& url,
- const string16& access_token) {
+ const base::string16& access_token) {
#if defined(OS_ANDROID)
// Android uses its own SystemLocationProvider.
return NULL;
@@ -160,7 +160,7 @@ LocationProvider* LocationArbitratorImpl::NewNetworkLocationProvider(
}
LocationProvider* LocationArbitratorImpl::NewSystemLocationProvider() {
-#if defined(OS_WIN) || defined(OS_MACOSX)
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
return NULL;
#else
return content::NewSystemLocationProvider();
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl.h b/chromium/content/browser/geolocation/location_arbitrator_impl.h
index 45910552e4e..e756f5e15de 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl.h
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl.h
@@ -57,7 +57,7 @@ class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator {
AccessTokenStore* access_token_store,
net::URLRequestContextGetter* context,
const GURL& url,
- const string16& access_token);
+ const base::string16& access_token);
virtual LocationProvider* NewSystemLocationProvider();
virtual base::Time GetTimeNow() const;
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc b/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
index 02df43172ee..81df7a4326f 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
@@ -85,7 +85,7 @@ class TestingLocationArbitrator : public LocationArbitratorImpl {
AccessTokenStore* access_token_store,
net::URLRequestContextGetter* context,
const GURL& url,
- const string16& access_token) OVERRIDE {
+ const base::string16& access_token) OVERRIDE {
return new MockLocationProvider(&cell_);
}
diff --git a/chromium/content/browser/geolocation/network_location_provider.cc b/chromium/content/browser/geolocation/network_location_provider.cc
index 678edb24092..efc68a73231 100644
--- a/chromium/content/browser/geolocation/network_location_provider.cc
+++ b/chromium/content/browser/geolocation/network_location_provider.cc
@@ -27,7 +27,7 @@ bool NetworkLocationProvider::PositionCache::CachePosition(
const WifiData& wifi_data,
const Geoposition& position) {
// Check that we can generate a valid key for the wifi data.
- string16 key;
+ base::string16 key;
if (!MakeKey(wifi_data, &key)) {
return false;
}
@@ -57,7 +57,7 @@ bool NetworkLocationProvider::PositionCache::CachePosition(
// the cached position if available, NULL otherwise.
const Geoposition* NetworkLocationProvider::PositionCache::FindPosition(
const WifiData& wifi_data) {
- string16 key;
+ base::string16 key;
if (!MakeKey(wifi_data, &key)) {
return NULL;
}
@@ -71,13 +71,13 @@ const Geoposition* NetworkLocationProvider::PositionCache::FindPosition(
// static
bool NetworkLocationProvider::PositionCache::MakeKey(
const WifiData& wifi_data,
- string16* key) {
+ base::string16* key) {
// Currently we use only WiFi data and base the key only on the MAC addresses.
DCHECK(key);
key->clear();
const size_t kCharsPerMacAddress = 6 * 3 + 1; // e.g. "11:22:33:44:55:66|"
key->reserve(wifi_data.access_point_data.size() * kCharsPerMacAddress);
- const string16 separator(ASCIIToUTF16("|"));
+ const base::string16 separator(ASCIIToUTF16("|"));
for (WifiData::AccessPointDataSet::const_iterator iter =
wifi_data.access_point_data.begin();
iter != wifi_data.access_point_data.end();
@@ -96,7 +96,7 @@ LocationProviderBase* NewNetworkLocationProvider(
AccessTokenStore* access_token_store,
net::URLRequestContextGetter* context,
const GURL& url,
- const string16& access_token) {
+ const base::string16& access_token) {
return new NetworkLocationProvider(
access_token_store, context, url, access_token);
}
@@ -106,7 +106,7 @@ NetworkLocationProvider::NetworkLocationProvider(
AccessTokenStore* access_token_store,
net::URLRequestContextGetter* url_context_getter,
const GURL& url,
- const string16& access_token)
+ const base::string16& access_token)
: access_token_store_(access_token_store),
wifi_data_provider_(NULL),
wifi_data_update_callback_(
@@ -163,7 +163,7 @@ void NetworkLocationProvider::WifiDataUpdateAvailable(
void NetworkLocationProvider::LocationResponseAvailable(
const Geoposition& position,
bool server_error,
- const string16& access_token,
+ const base::string16& access_token,
const WifiData& wifi_data) {
DCHECK(CalledOnValidThread());
// Record the position and update our cache.
diff --git a/chromium/content/browser/geolocation/network_location_provider.h b/chromium/content/browser/geolocation/network_location_provider.h
index d5f3e999d7e..710fd3f4fa6 100644
--- a/chromium/content/browser/geolocation/network_location_provider.h
+++ b/chromium/content/browser/geolocation/network_location_provider.h
@@ -54,12 +54,12 @@ class NetworkLocationProvider
// Makes the key for the map of cached positions, using a set of
// data. Returns true if a good key was generated, false otherwise.
static bool MakeKey(const WifiData& wifi_data,
- string16* key);
+ base::string16* key);
// The cache of positions. This is stored as a map keyed on a string that
// represents a set of data, and a list to provide
// least-recently-added eviction.
- typedef std::map<string16, Geoposition> CacheMap;
+ typedef std::map<base::string16, Geoposition> CacheMap;
CacheMap cache_;
typedef std::list<CacheMap::iterator> CacheAgeList;
CacheAgeList cache_age_list_; // Oldest first.
@@ -68,7 +68,7 @@ class NetworkLocationProvider
NetworkLocationProvider(AccessTokenStore* access_token_store,
net::URLRequestContextGetter* context,
const GURL& url,
- const string16& access_token);
+ const base::string16& access_token);
virtual ~NetworkLocationProvider();
// LocationProvider implementation
@@ -92,7 +92,7 @@ class NetworkLocationProvider
void LocationResponseAvailable(const Geoposition& position,
bool server_error,
- const string16& access_token,
+ const base::string16& access_token,
const WifiData& wifi_data);
scoped_refptr<AccessTokenStore> access_token_store_;
@@ -111,7 +111,7 @@ class NetworkLocationProvider
// Cached value loaded from the token store or set by a previous server
// response, and sent in each subsequent network request.
- string16 access_token_;
+ base::string16 access_token_;
// The current best position estimate.
Geoposition position_;
@@ -138,7 +138,7 @@ CONTENT_EXPORT LocationProviderBase* NewNetworkLocationProvider(
AccessTokenStore* access_token_store,
net::URLRequestContextGetter* context,
const GURL& url,
- const string16& access_token);
+ const base::string16& access_token);
} // namespace content
diff --git a/chromium/content/browser/geolocation/network_location_request.cc b/chromium/content/browser/geolocation/network_location_request.cc
index f15141a29e3..3ed709218fe 100644
--- a/chromium/content/browser/geolocation/network_location_request.cc
+++ b/chromium/content/browser/geolocation/network_location_request.cc
@@ -10,6 +10,7 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
@@ -25,15 +26,45 @@
namespace content {
namespace {
-const size_t kMaxRequestLength = 2048;
-
const char kAccessTokenString[] = "accessToken";
const char kLocationString[] = "location";
const char kLatitudeString[] = "lat";
const char kLongitudeString[] = "lng";
const char kAccuracyString[] = "accuracy";
-const char kStatusString[] = "status";
-const char kStatusOKString[] = "OK";
+
+enum NetworkLocationRequestEvent {
+ // NOTE: Do not renumber these as that would confuse interpretation of
+ // previously logged data. When making changes, also update the enum list
+ // in tools/metrics/histograms/histograms.xml to keep it in sync.
+ NETWORK_LOCATION_REQUEST_EVENT_REQUEST_START = 0,
+ NETWORK_LOCATION_REQUEST_EVENT_REQUEST_CANCEL = 1,
+ NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_SUCCESS = 2,
+ NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_NOT_OK = 3,
+ NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_EMPTY = 4,
+ NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_MALFORMED = 5,
+ NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_INVALID_FIX = 6,
+
+ // NOTE: Add entries only immediately above this line.
+ NETWORK_LOCATION_REQUEST_EVENT_COUNT = 7
+};
+
+void RecordUmaEvent(NetworkLocationRequestEvent event) {
+ UMA_HISTOGRAM_ENUMERATION("Geolocation.NetworkLocationRequest.Event",
+ event, NETWORK_LOCATION_REQUEST_EVENT_COUNT);
+}
+
+void RecordUmaResponseCode(int code) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Geolocation.NetworkLocationRequest.ResponseCode",
+ code);
+}
+
+void RecordUmaAccessPoints(int count) {
+ const int min = 0;
+ const int max = 20;
+ const int buckets = 21;
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Geolocation.NetworkLocationRequest.AccessPoints",
+ count, min, max, buckets);
+}
// Local functions
// Creates the request url to send to the server.
@@ -41,17 +72,18 @@ GURL FormRequestURL(const GURL& url);
void FormUploadData(const WifiData& wifi_data,
const base::Time& timestamp,
- const string16& access_token,
+ const base::string16& access_token,
std::string* upload_data);
-// Parsers the server response.
+// Attempts to extract a position from the response. Detects and indicates
+// various failure cases.
void GetLocationFromResponse(bool http_post_result,
int status_code,
const std::string& response_body,
const base::Time& timestamp,
const GURL& server_url,
Geoposition* position,
- string16* access_token);
+ base::string16* access_token);
// Parses the server response body. Returns true if parsing was successful.
// Sets |*position| to the parsed location if a valid fix was received,
@@ -59,7 +91,7 @@ void GetLocationFromResponse(bool http_post_result,
bool ParseServerResponse(const std::string& response_body,
const base::Time& timestamp,
Geoposition* position,
- string16* access_token);
+ base::string16* access_token);
void AddWifiData(const WifiData& wifi_data,
int age_milliseconds,
base::DictionaryValue* request);
@@ -79,11 +111,14 @@ NetworkLocationRequest::NetworkLocationRequest(
NetworkLocationRequest::~NetworkLocationRequest() {
}
-bool NetworkLocationRequest::MakeRequest(const string16& access_token,
+bool NetworkLocationRequest::MakeRequest(const base::string16& access_token,
const WifiData& wifi_data,
const base::Time& timestamp) {
+ RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_REQUEST_START);
+ RecordUmaAccessPoints(wifi_data.access_point_data.size());
if (url_fetcher_ != NULL) {
DVLOG(1) << "NetworkLocationRequest : Cancelling pending request";
+ RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_REQUEST_CANCEL);
url_fetcher_.reset();
}
wifi_data_ = wifi_data;
@@ -112,9 +147,10 @@ void NetworkLocationRequest::OnURLFetchComplete(
net::URLRequestStatus status = source->GetStatus();
int response_code = source->GetResponseCode();
+ RecordUmaResponseCode(response_code);
Geoposition position;
- string16 access_token;
+ base::string16 access_token;
std::string data;
source->GetResponseAsString(&data);
GetLocationFromResponse(status.is_success(),
@@ -171,7 +207,7 @@ GURL FormRequestURL(const GURL& url) {
void FormUploadData(const WifiData& wifi_data,
const base::Time& timestamp,
- const string16& access_token,
+ const base::string16& access_token,
std::string* upload_data) {
int age = kint32min; // Invalid so AddInteger() will ignore.
if (!timestamp.is_null()) {
@@ -255,7 +291,7 @@ void GetLocationFromResponse(bool http_post_result,
const base::Time& timestamp,
const GURL& server_url,
Geoposition* position,
- string16* access_token) {
+ base::string16* access_token) {
DCHECK(position);
DCHECK(access_token);
@@ -263,12 +299,14 @@ void GetLocationFromResponse(bool http_post_result,
// we're offline, or there was no response.
if (!http_post_result) {
FormatPositionError(server_url, "No response received", position);
+ RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_EMPTY);
return;
}
if (status_code != 200) { // HTTP OK.
std::string message = "Returned error code ";
message += base::IntToString(status_code);
FormatPositionError(server_url, message, position);
+ RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_NOT_OK);
return;
}
// We use the timestamp from the wifi data that was used to generate
@@ -276,6 +314,7 @@ void GetLocationFromResponse(bool http_post_result,
if (!ParseServerResponse(response_body, timestamp, position, access_token)) {
// We failed to parse the repsonse.
FormatPositionError(server_url, "Response was malformed", position);
+ RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_MALFORMED);
return;
}
// The response was successfully parsed, but it may not be a valid
@@ -283,8 +322,10 @@ void GetLocationFromResponse(bool http_post_result,
if (!position->Validate()) {
FormatPositionError(server_url,
"Did not provide a good position fix", position);
+ RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_INVALID_FIX);
return;
}
+ RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_SUCCESS);
}
// Numeric values without a decimal point have type integer and IsDouble() will
@@ -310,7 +351,7 @@ bool GetAsDouble(const base::DictionaryValue& object,
bool ParseServerResponse(const std::string& response_body,
const base::Time& timestamp,
Geoposition* position,
- string16* access_token) {
+ base::string16* access_token) {
DCHECK(position);
DCHECK(!position->Validate());
DCHECK(position->error_code == Geoposition::ERROR_CODE_NONE);
diff --git a/chromium/content/browser/geolocation/network_location_request.h b/chromium/content/browser/geolocation/network_location_request.h
index 38aaf3e6ce7..6fea08b8bd5 100644
--- a/chromium/content/browser/geolocation/network_location_request.h
+++ b/chromium/content/browser/geolocation/network_location_request.h
@@ -33,7 +33,7 @@ class NetworkLocationRequest : private net::URLFetcherDelegate {
// server or network error - either no response or a 500 error code.
typedef base::Callback<void(const Geoposition& /* position */,
bool /* server_error */,
- const string16& /* access_token */,
+ const base::string16& /* access_token */,
const WifiData& /* wifi_data */)>
LocationResponseCallback;
@@ -45,7 +45,7 @@ class NetworkLocationRequest : private net::URLFetcherDelegate {
// Makes a new request. Returns true if the new request was successfully
// started. In all cases, any currently pending request will be canceled.
- bool MakeRequest(const string16& access_token,
+ bool MakeRequest(const base::string16& access_token,
const WifiData& wifi_data,
const base::Time& timestamp);
diff --git a/chromium/content/browser/geolocation/wifi_data.cc b/chromium/content/browser/geolocation/wifi_data.cc
index f4ea267b2f1..bcfb9811bb7 100644
--- a/chromium/content/browser/geolocation/wifi_data.cc
+++ b/chromium/content/browser/geolocation/wifi_data.cc
@@ -4,6 +4,8 @@
#include "content/browser/geolocation/wifi_data.h"
+#include <algorithm>
+
#include "base/logging.h"
namespace content {
diff --git a/chromium/content/browser/geolocation/wifi_data.h b/chromium/content/browser/geolocation/wifi_data.h
index a24e42e2ac1..72bc3065abb 100644
--- a/chromium/content/browser/geolocation/wifi_data.h
+++ b/chromium/content/browser/geolocation/wifi_data.h
@@ -19,11 +19,11 @@ struct CONTENT_EXPORT AccessPointData {
~AccessPointData();
// MAC address, formatted as per MacAddressAsString16.
- string16 mac_address;
+ base::string16 mac_address;
int radio_signal_strength; // Measured in dBm
int channel;
int signal_to_noise; // Ratio in dB
- string16 ssid; // Network identifier
+ base::string16 ssid; // Network identifier
};
// This is to allow AccessPointData to be used in std::set. We order
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_common.cc b/chromium/content/browser/geolocation/wifi_data_provider_common.cc
index 31f969c3a3c..9c2cbae2345 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_common.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_common.cc
@@ -10,7 +10,7 @@
namespace content {
-string16 MacAddressAsString16(const uint8 mac_as_int[6]) {
+base::string16 MacAddressAsString16(const uint8 mac_as_int[6]) {
// mac_as_int is big-endian. Write in byte chunks.
// Format is XX-XX-XX-XX-XX-XX.
static const char* const kMacFormatString =
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_common.h b/chromium/content/browser/geolocation/wifi_data_provider_common.h
index c42b4c2a851..befdb692114 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_common.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_common.h
@@ -18,7 +18,7 @@
namespace content {
// Converts a MAC address stored as an array of uint8 to a string.
-string16 MacAddressAsString16(const uint8 mac_as_int[6]);
+base::string16 MacAddressAsString16(const uint8 mac_as_int[6]);
// Base class to promote code sharing between platform specific wifi data
// providers. It's optional for specific platforms to derive this, but if they
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_win.cc b/chromium/content/browser/geolocation/wifi_data_provider_win.cc
index 8efb1918450..ed69865fbd0 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_win.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_win.cc
@@ -127,15 +127,15 @@ class WindowsNdisApi : public WifiDataProviderCommon::WlanApiInterface {
private:
static bool GetInterfacesNDIS(
- std::vector<string16>* interface_service_names_out);
+ std::vector<base::string16>* interface_service_names_out);
// Swaps in content of the vector passed
- explicit WindowsNdisApi(std::vector<string16>* interface_service_names);
+ explicit WindowsNdisApi(std::vector<base::string16>* interface_service_names);
bool GetInterfaceDataNDIS(HANDLE adapter_handle,
WifiData::AccessPointDataSet* data);
// NDIS variables.
- std::vector<string16> interface_service_names_;
+ std::vector<base::string16> interface_service_names_;
// Remembers scan result buffer size across calls.
int oid_buffer_size_;
@@ -144,9 +144,9 @@ class WindowsNdisApi : public WifiDataProviderCommon::WlanApiInterface {
// Extracts data for an access point and converts to Gears format.
bool GetNetworkData(const WLAN_BSS_ENTRY& bss_entry,
AccessPointData* access_point_data);
-bool UndefineDosDevice(const string16& device_name);
-bool DefineDosDeviceIfNotExists(const string16& device_name);
-HANDLE GetFileHandle(const string16& device_name);
+bool UndefineDosDevice(const base::string16& device_name);
+bool DefineDosDeviceIfNotExists(const base::string16& device_name);
+HANDLE GetFileHandle(const base::string16& device_name);
// Makes the OID query and returns a Win32 error code.
int PerformQuery(HANDLE adapter_handle,
BYTE* buffer,
@@ -155,7 +155,7 @@ int PerformQuery(HANDLE adapter_handle,
bool ResizeBuffer(int requested_size, scoped_ptr_malloc<BYTE>* buffer);
// Gets the system directory and appends a trailing slash if not already
// present.
-bool GetSystemDirectory(string16* path);
+bool GetSystemDirectory(base::string16* path);
} // namespace
WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
@@ -202,12 +202,12 @@ WindowsWlanApi* WindowsWlanApi::Create() {
if (base::win::GetVersion() < base::win::VERSION_VISTA)
return NULL;
// We use an absolute path to load the DLL to avoid DLL preloading attacks.
- string16 system_directory;
+ base::string16 system_directory;
if (!GetSystemDirectory(&system_directory)) {
return NULL;
}
DCHECK(!system_directory.empty());
- string16 dll_path = system_directory + L"wlanapi.dll";
+ base::string16 dll_path = system_directory + L"wlanapi.dll";
HINSTANCE library = LoadLibraryEx(dll_path.c_str(),
NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
@@ -359,7 +359,7 @@ int WindowsWlanApi::GetInterfaceDataWLAN(
// WindowsNdisApi
WindowsNdisApi::WindowsNdisApi(
- std::vector<string16>* interface_service_names)
+ std::vector<base::string16>* interface_service_names)
: oid_buffer_size_(kInitialBufferSize) {
DCHECK(!interface_service_names->empty());
interface_service_names_.swap(*interface_service_names);
@@ -369,7 +369,7 @@ WindowsNdisApi::~WindowsNdisApi() {
}
WindowsNdisApi* WindowsNdisApi::Create() {
- std::vector<string16> interface_service_names;
+ std::vector<base::string16> interface_service_names;
if (GetInterfacesNDIS(&interface_service_names)) {
return new WindowsNdisApi(&interface_service_names);
}
@@ -412,7 +412,7 @@ bool WindowsNdisApi::GetAccessPointData(WifiData::AccessPointDataSet* data) {
}
bool WindowsNdisApi::GetInterfacesNDIS(
- std::vector<string16>* interface_service_names_out) {
+ std::vector<base::string16>* interface_service_names_out) {
HKEY network_cards_key = NULL;
if (RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
@@ -530,18 +530,18 @@ bool GetNetworkData(const WLAN_BSS_ENTRY& bss_entry,
return true;
}
-bool UndefineDosDevice(const string16& device_name) {
+bool UndefineDosDevice(const base::string16& device_name) {
// We remove only the mapping we use, that is \Device\<device_name>.
- string16 target_path = L"\\Device\\" + device_name;
+ base::string16 target_path = L"\\Device\\" + device_name;
return DefineDosDevice(
DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
device_name.c_str(),
target_path.c_str()) == TRUE;
}
-bool DefineDosDeviceIfNotExists(const string16& device_name) {
+bool DefineDosDeviceIfNotExists(const base::string16& device_name) {
// We create a DOS device name for the device at \Device\<device_name>.
- string16 target_path = L"\\Device\\" + device_name;
+ base::string16 target_path = L"\\Device\\" + device_name;
TCHAR target[kStringLength];
if (QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 &&
@@ -565,10 +565,10 @@ bool DefineDosDeviceIfNotExists(const string16& device_name) {
target_path.compare(target) == 0;
}
-HANDLE GetFileHandle(const string16& device_name) {
+HANDLE GetFileHandle(const base::string16& device_name) {
// We access a device with DOS path \Device\<device_name> at
// \\.\<device_name>.
- string16 formatted_device_name = L"\\\\.\\" + device_name;
+ base::string16 formatted_device_name = L"\\\\.\\" + device_name;
return CreateFile(formatted_device_name.c_str(),
GENERIC_READ,
@@ -610,7 +610,7 @@ bool ResizeBuffer(int requested_size, scoped_ptr_malloc<BYTE>* buffer) {
return buffer != NULL;
}
-bool GetSystemDirectory(string16* path) {
+bool GetSystemDirectory(base::string16* path) {
DCHECK(path);
// Return value includes terminating NULL.
int buffer_size = ::GetSystemDirectory(NULL, 0);
diff --git a/chromium/content/browser/gpu/OWNERS b/chromium/content/browser/gpu/OWNERS
index 92ac85812fe..b66635ae032 100644
--- a/chromium/content/browser/gpu/OWNERS
+++ b/chromium/content/browser/gpu/OWNERS
@@ -1,4 +1,3 @@
-apatrick@chromium.org
kbr@chromium.org
piman@chromium.org
zmo@chromium.org
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 7bc6fca71e6..d0ce8b48065 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -5,13 +5,16 @@
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
#include "base/bind.h"
+#include "base/debug/trace_event.h"
#include "base/threading/thread_restrictions.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
-#include "content/common/gpu/gpu_messages.h"
#include "content/common/child_process_host_impl.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
+#include "content/common/gpu/gpu_messages.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_client.h"
#include "ipc/ipc_forwarding_message_filter.h"
@@ -20,7 +23,7 @@ namespace content {
BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL;
BrowserGpuChannelHostFactory::CreateRequest::CreateRequest()
- : event(false, false),
+ : event(true, false),
gpu_host_id(0),
route_id(MSG_ROUTING_NONE) {
}
@@ -29,32 +32,141 @@ BrowserGpuChannelHostFactory::CreateRequest::~CreateRequest() {
}
BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest(
- CauseForGpuLaunch cause)
- : event(false, false),
- cause_for_gpu_launch(cause),
- gpu_host_id(0),
- reused_gpu_process(true) {
+ CauseForGpuLaunch cause,
+ int gpu_client_id,
+ int gpu_host_id)
+ : event_(false, false),
+ cause_for_gpu_launch_(cause),
+ gpu_client_id_(gpu_client_id),
+ gpu_host_id_(gpu_host_id),
+ reused_gpu_process_(false),
+ finished_(false),
+ main_loop_(base::MessageLoopProxy::current()) {
+ scoped_refptr<base::MessageLoopProxy> loop =
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
+ loop->PostTask(
+ FROM_HERE,
+ base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO,
+ this));
}
BrowserGpuChannelHostFactory::EstablishRequest::~EstablishRequest() {
}
-void BrowserGpuChannelHostFactory::Initialize() {
- instance_ = new BrowserGpuChannelHostFactory();
+void BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO() {
+ GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
+ if (!host) {
+ host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ cause_for_gpu_launch_);
+ if (!host) {
+ FinishOnIO();
+ return;
+ }
+ gpu_host_id_ = host->host_id();
+ reused_gpu_process_ = false;
+ } else {
+ if (reused_gpu_process_) {
+ // We come here if we retried to establish the channel because of a
+ // failure in ChannelEstablishedOnIO, but we ended up with the same
+ // process ID, meaning the failure was not because of a channel error,
+ // but another reason. So fail now.
+ FinishOnIO();
+ return;
+ }
+ reused_gpu_process_ = true;
+ }
+
+ host->EstablishGpuChannel(
+ gpu_client_id_,
+ true,
+ base::Bind(
+ &BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO,
+ this));
+}
+
+void BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO(
+ const IPC::ChannelHandle& channel_handle,
+ const gpu::GPUInfo& gpu_info) {
+ if (channel_handle.name.empty() && reused_gpu_process_) {
+ // We failed after re-using the GPU process, but it may have died in the
+ // mean time. Retry to have a chance to create a fresh GPU process.
+ EstablishOnIO();
+ } else {
+ channel_handle_ = channel_handle;
+ gpu_info_ = gpu_info;
+ FinishOnIO();
+ }
+}
+
+void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnIO() {
+ event_.Signal();
+ main_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain,
+ this));
+}
+
+void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain() {
+ if (!finished_) {
+ BrowserGpuChannelHostFactory* factory =
+ BrowserGpuChannelHostFactory::instance();
+ factory->GpuChannelEstablished();
+ finished_ = true;
+ }
+}
+
+void BrowserGpuChannelHostFactory::EstablishRequest::Wait() {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+ {
+ // We're blocking the UI thread, which is generally undesirable.
+ // In this case we need to wait for this before we can show any UI
+ // /anyway/, so it won't cause additional jank.
+ // TODO(piman): Make this asynchronous (http://crbug.com/125248).
+ TRACE_EVENT0("browser",
+ "BrowserGpuChannelHostFactory::EstablishGpuChannelSync");
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
+ event_.Wait();
+ }
+ FinishOnMain();
+}
+
+void BrowserGpuChannelHostFactory::EstablishRequest::Cancel() {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+ finished_ = true;
+}
+
+bool BrowserGpuChannelHostFactory::CanUseForTesting() {
+ return GpuDataManager::GetInstance()->GpuAccessAllowed(NULL);
+}
+
+void BrowserGpuChannelHostFactory::Initialize(bool establish_gpu_channel) {
+ DCHECK(!instance_);
+ instance_ = new BrowserGpuChannelHostFactory(establish_gpu_channel);
}
void BrowserGpuChannelHostFactory::Terminate() {
+ DCHECK(instance_);
delete instance_;
instance_ = NULL;
}
-BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory()
+BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory(
+ bool establish_gpu_channel)
: gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
shutdown_event_(new base::WaitableEvent(true, false)),
gpu_host_id_(0) {
+ if (establish_gpu_channel) {
+ pending_request_ = new EstablishRequest(
+ CAUSE_FOR_GPU_LAUNCH_BROWSER_STARTUP, gpu_client_id_, gpu_host_id_);
+ }
}
BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() {
+ DCHECK(IsMainThread());
+ if (pending_request_)
+ pending_request_->Cancel();
+ for (size_t n = 0; n < established_callbacks_.size(); n++)
+ established_callbacks_[n].Run();
shutdown_event_->Signal();
}
@@ -126,6 +238,8 @@ int32 BrowserGpuChannelHostFactory::CreateViewCommandBuffer(
// In this case we need to wait for this before we can show any UI /anyway/,
// so it won't cause additional jank.
// TODO(piman): Make this asynchronous (http://crbug.com/125248).
+ TRACE_EVENT0("browser",
+ "BrowserGpuChannelHostFactory::CreateViewCommandBuffer");
base::ThreadRestrictions::ScopedAllowWait allow_wait;
request.event.Wait();
return request.route_id;
@@ -197,91 +311,86 @@ void BrowserGpuChannelHostFactory::DeleteImage(
sync_point));
}
-void BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO(
- EstablishRequest* request) {
- GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
- if (!host) {
- host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- request->cause_for_gpu_launch);
- if (!host) {
- request->event.Signal();
- return;
- }
- gpu_host_id_ = host->host_id();
- request->reused_gpu_process = false;
- } else {
- if (host->host_id() == request->gpu_host_id) {
- // We come here if we retried to establish the channel because of a
- // failure in GpuChannelEstablishedOnIO, but we ended up with the same
- // process ID, meaning the failure was not because of a channel error, but
- // another reason. So fail now.
- request->event.Signal();
- return;
- }
- request->reused_gpu_process = true;
- }
- request->gpu_host_id = gpu_host_id_;
+GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync(
+ CauseForGpuLaunch cause_for_gpu_launch) {
+ EstablishGpuChannel(cause_for_gpu_launch, base::Closure());
- host->EstablishGpuChannel(
- gpu_client_id_,
- true,
- base::Bind(&BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO,
- base::Unretained(this),
- request));
-}
+ if (pending_request_)
+ pending_request_->Wait();
-void BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO(
- EstablishRequest* request,
- const IPC::ChannelHandle& channel_handle,
- const gpu::GPUInfo& gpu_info) {
- if (channel_handle.name.empty() && request->reused_gpu_process) {
- // We failed after re-using the GPU process, but it may have died in the
- // mean time. Retry to have a chance to create a fresh GPU process.
- EstablishGpuChannelOnIO(request);
- } else {
- request->channel_handle = channel_handle;
- request->gpu_info = gpu_info;
- request->event.Signal();
- }
+ return gpu_channel_.get();
}
-GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync(
- CauseForGpuLaunch cause_for_gpu_launch) {
- if (gpu_channel_.get()) {
+void BrowserGpuChannelHostFactory::EstablishGpuChannel(
+ CauseForGpuLaunch cause_for_gpu_launch,
+ const base::Closure& callback) {
+ if (gpu_channel_.get() && gpu_channel_->IsLost()) {
+ DCHECK(!pending_request_);
// Recreate the channel if it has been lost.
- if (gpu_channel_->IsLost())
- gpu_channel_ = NULL;
- else
- return gpu_channel_.get();
+ gpu_channel_ = NULL;
}
- // Ensure initialization on the main thread.
- GpuDataManagerImpl::GetInstance();
- EstablishRequest request(cause_for_gpu_launch);
- GetIOLoopProxy()->PostTask(
- FROM_HERE,
- base::Bind(
- &BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO,
- base::Unretained(this),
- &request));
+ if (!gpu_channel_ && !pending_request_) {
+ // We should only get here if the context was lost.
+ pending_request_ = new EstablishRequest(
+ cause_for_gpu_launch, gpu_client_id_, gpu_host_id_);
+ }
- {
- // We're blocking the UI thread, which is generally undesirable.
- // In this case we need to wait for this before we can show any UI /anyway/,
- // so it won't cause additional jank.
- // TODO(piman): Make this asynchronous (http://crbug.com/125248).
- base::ThreadRestrictions::ScopedAllowWait allow_wait;
- request.event.Wait();
+ if (!callback.is_null()) {
+ if (gpu_channel_)
+ callback.Run();
+ else
+ established_callbacks_.push_back(callback);
}
+}
- if (request.channel_handle.name.empty())
- return NULL;
+GpuChannelHost* BrowserGpuChannelHostFactory::GetGpuChannel() {
+ if (gpu_channel_ && !gpu_channel_->IsLost())
+ return gpu_channel_;
- GetContentClient()->SetGpuInfo(request.gpu_info);
- gpu_channel_ = GpuChannelHost::Create(
- this, request.gpu_host_id, gpu_client_id_,
- request.gpu_info, request.channel_handle);
- return gpu_channel_.get();
+ return NULL;
+}
+
+void BrowserGpuChannelHostFactory::GpuChannelEstablished() {
+ DCHECK(IsMainThread());
+ DCHECK(pending_request_);
+ if (pending_request_->channel_handle().name.empty())
+ return;
+
+ GetContentClient()->SetGpuInfo(pending_request_->gpu_info());
+ gpu_channel_ = GpuChannelHost::Create(this,
+ pending_request_->gpu_host_id(),
+ pending_request_->gpu_info(),
+ pending_request_->channel_handle());
+ gpu_host_id_ = pending_request_->gpu_host_id();
+ pending_request_ = NULL;
+
+ for (size_t n = 0; n < established_callbacks_.size(); n++)
+ established_callbacks_[n].Run();
+
+ established_callbacks_.clear();
+}
+
+scoped_ptr<gfx::GpuMemoryBuffer>
+ BrowserGpuChannelHostFactory::AllocateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat) {
+ if (!GpuMemoryBufferImpl::IsFormatValid(internalformat))
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ size_t size = width * height *
+ GpuMemoryBufferImpl::BytesPerPixel(internalformat);
+ scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
+ if (!shm->CreateAnonymous(size))
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ scoped_ptr<GpuMemoryBufferImplShm> buffer(
+ new GpuMemoryBufferImplShm(gfx::Size(width, height), internalformat));
+ if (!buffer->InitializeFromSharedMemory(shm.Pass()))
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ return buffer.PassAs<gfx::GpuMemoryBuffer>();
}
// static
diff --git a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
index ca311839d9c..8b461e4aec5 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_GPU_BROWSER_GPU_CHANNEL_HOST_FACTORY_H_
#define CONTENT_BROWSER_GPU_BROWSER_GPU_CHANNEL_HOST_FACTORY_H_
+#include <vector>
+
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/process/process.h"
@@ -17,7 +19,7 @@ namespace content {
class CONTENT_EXPORT BrowserGpuChannelHostFactory
: public GpuChannelHostFactory {
public:
- static void Initialize();
+ static void Initialize(bool establish_gpu_channel);
static void Terminate();
static BrowserGpuChannelHostFactory* instance() { return instance_; }
@@ -36,8 +38,10 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
int32 image_id,
const CreateImageCallback& callback) OVERRIDE;
virtual void DeleteImage(int32 image_idu, int32 sync_point) OVERRIDE;
- virtual GpuChannelHost* EstablishGpuChannelSync(
- CauseForGpuLaunch cause_for_gpu_launch) OVERRIDE;
+ virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat) OVERRIDE;
// Specify a task runner and callback to be used for a set of messages. The
// callback will be set up on the current GpuProcessHost, identified by
@@ -48,6 +52,15 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
const base::Callback<void(const IPC::Message&)>& handler,
base::TaskRunner* target_task_runner);
int GpuProcessHostId() { return gpu_host_id_; }
+ GpuChannelHost* EstablishGpuChannelSync(
+ CauseForGpuLaunch cause_for_gpu_launch);
+ void EstablishGpuChannel(CauseForGpuLaunch cause_for_gpu_launch,
+ const base::Closure& callback);
+ GpuChannelHost* GetGpuChannel();
+ int GetGpuChannelId() { return gpu_client_id_; }
+
+ // Used to skip GpuChannelHost tests when there can be no GPU process.
+ static bool CanUseForTesting();
private:
struct CreateRequest {
@@ -58,20 +71,42 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
int32 route_id;
};
- struct EstablishRequest {
- explicit EstablishRequest(CauseForGpuLaunch);
+ class EstablishRequest : public base::RefCountedThreadSafe<EstablishRequest> {
+ public:
+ explicit EstablishRequest(CauseForGpuLaunch cause,
+ int gpu_client_id,
+ int gpu_host_id);
+ void Wait();
+ void Cancel();
+
+ int gpu_host_id() { return gpu_host_id_; }
+ IPC::ChannelHandle& channel_handle() { return channel_handle_; }
+ gpu::GPUInfo gpu_info() { return gpu_info_; }
+
+ private:
+ friend class base::RefCountedThreadSafe<EstablishRequest>;
~EstablishRequest();
- base::WaitableEvent event;
- CauseForGpuLaunch cause_for_gpu_launch;
- int gpu_host_id;
- bool reused_gpu_process;
- IPC::ChannelHandle channel_handle;
- gpu::GPUInfo gpu_info;
+ void EstablishOnIO();
+ void OnEstablishedOnIO(const IPC::ChannelHandle& channel_handle,
+ const gpu::GPUInfo& gpu_info);
+ void FinishOnIO();
+ void FinishOnMain();
+
+ base::WaitableEvent event_;
+ CauseForGpuLaunch cause_for_gpu_launch_;
+ const int gpu_client_id_;
+ int gpu_host_id_;
+ bool reused_gpu_process_;
+ IPC::ChannelHandle channel_handle_;
+ gpu::GPUInfo gpu_info_;
+ bool finished_;
+ scoped_refptr<base::MessageLoopProxy> main_loop_;
};
- BrowserGpuChannelHostFactory();
+ explicit BrowserGpuChannelHostFactory(bool establish_gpu_channel);
virtual ~BrowserGpuChannelHostFactory();
+ void GpuChannelEstablished();
void CreateViewCommandBufferOnIO(
CreateRequest* request,
int32 surface_id,
@@ -86,19 +121,16 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
static void OnImageCreated(
const CreateImageCallback& callback, const gfx::Size size);
void DeleteImageOnIO(int32 image_id, int32 sync_point);
- void EstablishGpuChannelOnIO(EstablishRequest* request);
- void GpuChannelEstablishedOnIO(
- EstablishRequest* request,
- const IPC::ChannelHandle& channel_handle,
- const gpu::GPUInfo& gpu_info);
static void AddFilterOnIO(
int gpu_host_id,
scoped_refptr<IPC::ChannelProxy::MessageFilter> filter);
- int gpu_client_id_;
+ const int gpu_client_id_;
scoped_ptr<base::WaitableEvent> shutdown_event_;
scoped_refptr<GpuChannelHost> gpu_channel_;
int gpu_host_id_;
+ scoped_refptr<EstablishRequest> pending_request_;
+ std::vector<base::Closure> established_callbacks_;
static BrowserGpuChannelHostFactory* instance_;
diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc
index 16810e326f3..73af1304a42 100644
--- a/chromium/content/browser/gpu/compositor_util.cc
+++ b/chromium/content/browser/gpu/compositor_util.cc
@@ -5,27 +5,185 @@
#include "content/browser/gpu/compositor_util.h"
#include "base/command_line.h"
-#include "base/metrics/field_trial.h"
+#include "base/logging.h"
#include "build/build_config.h"
-#include "content/public/browser/gpu_data_manager.h"
-#include "content/public/common/content_constants.h"
+#include "cc/base/switches.h"
+#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/public/common/content_switches.h"
#include "gpu/config/gpu_feature_type.h"
-#if defined(OS_MACOSX)
-#include "base/mac/mac_util.h"
-#elif defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
-
namespace content {
namespace {
+struct GpuFeatureInfo {
+ std::string name;
+ uint32 blocked;
+ bool disabled;
+ std::string disabled_description;
+ bool fallback_to_software;
+};
+
+#if defined(OS_CHROMEOS)
+const size_t kNumFeatures = 14;
+#else
+const size_t kNumFeatures = 13;
+#endif
+const GpuFeatureInfo GetGpuFeatureInfo(size_t index) {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
+
+ const GpuFeatureInfo kGpuFeatureInfo[] = {
+ {
+ "2d_canvas",
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS),
+ command_line.HasSwitch(switches::kDisableAccelerated2dCanvas) ||
+ !GpuDataManagerImpl::GetInstance()->
+ GetGPUInfo().SupportsAccelerated2dCanvas(),
+ "Accelerated 2D canvas is unavailable: either disabled at the command"
+ " line or not supported by the current system.",
+ true
+ },
+ {
+ "compositing",
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING),
+ command_line.HasSwitch(switches::kDisableAcceleratedCompositing),
+ "Accelerated compositing has been disabled, either via about:flags or"
+ " command line. This adversely affects performance of all hardware"
+ " accelerated features.",
+ true
+ },
+ {
+ "3d_css",
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
+ manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS),
+ command_line.HasSwitch(switches::kDisableAcceleratedLayers),
+ "Accelerated layers have been disabled at the command line.",
+ false
+ },
+ {
+ "css_animation",
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
+ manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS),
+ command_line.HasSwitch(cc::switches::kDisableThreadedAnimation) ||
+ command_line.HasSwitch(switches::kDisableAcceleratedCompositing) ||
+ command_line.HasSwitch(switches::kDisableAcceleratedLayers),
+ "Accelerated CSS animation has been disabled at the command line.",
+ true
+ },
+ {
+ "webgl",
+ manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL),
+ command_line.HasSwitch(switches::kDisableExperimentalWebGL),
+ "WebGL has been disabled, either via about:flags or command line.",
+ false
+ },
+ {
+ "multisampling",
+ manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING),
+ command_line.HasSwitch(switches::kDisableGLMultisampling),
+ "Multisampling has been disabled, either via about:flags or command"
+ " line.",
+ false
+ },
+ {
+ "flash_3d",
+ manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D),
+ command_line.HasSwitch(switches::kDisableFlash3d),
+ "Using 3d in flash has been disabled, either via about:flags or"
+ " command line.",
+ false
+ },
+ {
+ "flash_stage3d",
+ manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
+ command_line.HasSwitch(switches::kDisableFlashStage3d),
+ "Using Stage3d in Flash has been disabled, either via about:flags or"
+ " command line.",
+ false
+ },
+ {
+ "flash_stage3d_baseline",
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE) ||
+ manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
+ command_line.HasSwitch(switches::kDisableFlashStage3d),
+ "Using Stage3d Baseline profile in Flash has been disabled, either"
+ " via about:flags or command line.",
+ false
+ },
+ {
+ "texture_sharing",
+ manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING),
+ command_line.HasSwitch(switches::kDisableImageTransportSurface),
+ "Sharing textures between processes has been disabled, either via"
+ " about:flags or command line.",
+ false
+ },
+ {
+ "video_decode",
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
+ command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode),
+ "Accelerated video decode has been disabled, either via about:flags"
+ " or command line.",
+ true
+ },
+#if defined(ENABLE_WEBRTC)
+ {
+ "video_encode",
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE),
+ command_line.HasSwitch(switches::kDisableWebRtcHWEncoding),
+ "Accelerated video encode has been disabled, either via about:flags"
+ " or command line.",
+ true
+ },
+#endif
+ {
+ "video",
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO),
+ command_line.HasSwitch(switches::kDisableAcceleratedVideo) ||
+ command_line.HasSwitch(switches::kDisableAcceleratedCompositing),
+ "Accelerated video presentation has been disabled, either via"
+ " about:flags or command line.",
+ true
+ },
+#if defined(OS_CHROMEOS)
+ {
+ "panel_fitting",
+ manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_PANEL_FITTING),
+ command_line.HasSwitch(switches::kDisablePanelFitting),
+ "Panel fitting has been disabled, either via about:flags or command"
+ " line.",
+ false
+ },
+#endif
+ {
+ "force_compositing_mode",
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE) &&
+ !IsForceCompositingModeEnabled(),
+ !IsForceCompositingModeEnabled() &&
+ !manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE),
+ "Force compositing mode is off, either disabled at the command"
+ " line or not supported by the current system.",
+ false
+ },
+ };
+ return kGpuFeatureInfo[index];
+}
+
bool CanDoAcceleratedCompositing() {
- const GpuDataManager* manager = GpuDataManager::GetInstance();
+ const GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
- // Don't run the field trial if gpu access has been blocked or
+ // Don't use force compositing mode if gpu access has been blocked or
// accelerated compositing is blacklisted.
if (!manager->GpuAccessAllowed(NULL) ||
manager->IsFeatureBlacklisted(
@@ -44,21 +202,16 @@ bool CanDoAcceleratedCompositing() {
}
bool IsForceCompositingModeBlacklisted() {
- return GpuDataManager::GetInstance()->IsFeatureBlacklisted(
+ return GpuDataManagerImpl::GetInstance()->IsFeatureBlacklisted(
gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE);
}
} // namespace
bool IsThreadedCompositingEnabled() {
-#if defined(USE_AURA)
- // We always want threaded compositing on Aura.
- return true;
-#endif
-
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- // Command line switches take precedence over blacklist and field trials.
+ // Command line switches take precedence over blacklist.
if (command_line.HasSwitch(switches::kDisableForceCompositingMode) ||
command_line.HasSwitch(switches::kDisableThreadedCompositing)) {
return false;
@@ -66,13 +219,22 @@ bool IsThreadedCompositingEnabled() {
return true;
}
+#if defined(USE_AURA)
+ // We always want threaded compositing on Aura.
+ return true;
+#endif
+
if (!CanDoAcceleratedCompositing() || IsForceCompositingModeBlacklisted())
return false;
- base::FieldTrial* trial =
- base::FieldTrialList::Find(kGpuCompositingFieldTrialName);
- return trial &&
- trial->group_name() == kGpuCompositingFieldTrialThreadEnabledName;
+#if defined(OS_MACOSX) || defined(OS_WIN)
+ // Windows Vista+ has been shipping with TCM enabled at 100% since M24 and
+ // Mac OSX 10.8+ since M28. The blacklist check above takes care of returning
+ // false before this hits on unsupported Win/Mac versions.
+ return true;
+#endif
+
+ return false;
}
bool IsForceCompositingModeEnabled() {
@@ -82,7 +244,7 @@ bool IsForceCompositingModeEnabled() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- // Command line switches take precedence over blacklisting and field trials.
+ // Command line switches take precedence over blacklisting.
if (command_line.HasSwitch(switches::kDisableForceCompositingMode))
return false;
else if (command_line.HasSwitch(switches::kForceCompositingMode))
@@ -91,18 +253,11 @@ bool IsForceCompositingModeEnabled() {
if (!CanDoAcceleratedCompositing() || IsForceCompositingModeBlacklisted())
return false;
- // Hardcode some platforms to use FCM, this has to be done here instead of via
- // the field trial so that this configuration is used on try bots as well.
- // TODO(gab): Do the same thing in IsThreadedCompositingEnabled() once this is
- // stable.
- // TODO(gab): Use the GPU blacklist instead of hardcoding OS versions here
- // https://codereview.chromium.org/23534006.
-#if defined(OS_MACOSX)
- // Mac OSX 10.8+ has been shipping with FCM enabled at 100% since M28.
- return base::mac::IsOSMountainLionOrLater();
-#elif defined(OS_WIN)
- // Windows Vista+ has been shipping with FCM enabled at 100% since M24.
- return base::win::GetVersion() >= base::win::VERSION_VISTA;
+#if defined(OS_MACOSX) || defined(OS_WIN)
+ // Windows Vista+ has been shipping with TCM enabled at 100% since M24 and
+ // Mac OSX 10.8+ since M28. The blacklist check above takes care of returning
+ // false before this hits on unsupported Win/Mac versions.
+ return true;
#endif
return false;
@@ -112,6 +267,11 @@ bool IsDelegatedRendererEnabled() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
bool enabled = false;
+#if defined(USE_AURA)
+ // Enable on Aura.
+ enabled = true;
+#endif
+
// Flags override.
enabled |= command_line.HasSwitch(switches::kEnableDelegatedRenderer);
enabled &= !command_line.HasSwitch(switches::kDisableDelegatedRenderer);
@@ -130,8 +290,8 @@ bool IsDelegatedRendererEnabled() {
bool IsDeadlineSchedulingEnabled() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- // Default to disabled.
- bool enabled = false;
+ // Default to enabled.
+ bool enabled = true;
// Flags override.
enabled |= command_line.HasSwitch(switches::kEnableDeadlineScheduling);
@@ -140,4 +300,115 @@ bool IsDeadlineSchedulingEnabled() {
return enabled;
}
+base::Value* GetFeatureStatus() {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
+ std::string gpu_access_blocked_reason;
+ bool gpu_access_blocked =
+ !manager->GpuAccessAllowed(&gpu_access_blocked_reason);
+
+ base::DictionaryValue* feature_status_dict = new base::DictionaryValue();
+
+ for (size_t i = 0; i < kNumFeatures; ++i) {
+ const GpuFeatureInfo gpu_feature_info = GetGpuFeatureInfo(i);
+ // force_compositing_mode status is part of the compositing status.
+ if (gpu_feature_info.name == "force_compositing_mode")
+ continue;
+
+ std::string status;
+ if (gpu_feature_info.disabled) {
+ status = "disabled";
+ if (gpu_feature_info.name == "css_animation") {
+ status += "_software_animated";
+ } else if (gpu_feature_info.name == "raster") {
+ if (cc::switches::IsImplSidePaintingEnabled())
+ status += "_software_multithreaded";
+ else
+ status += "_software";
+ } else {
+ if (gpu_feature_info.fallback_to_software)
+ status += "_software";
+ else
+ status += "_off";
+ }
+ } else if (manager->ShouldUseSwiftShader()) {
+ status = "unavailable_software";
+ } else if (gpu_feature_info.blocked ||
+ gpu_access_blocked) {
+ status = "unavailable";
+ if (gpu_feature_info.fallback_to_software)
+ status += "_software";
+ else
+ status += "_off";
+ } else {
+ status = "enabled";
+ if (gpu_feature_info.name == "webgl" &&
+ (command_line.HasSwitch(switches::kDisableAcceleratedCompositing) ||
+ manager->IsFeatureBlacklisted(
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)))
+ status += "_readback";
+ bool has_thread = IsThreadedCompositingEnabled();
+ if (gpu_feature_info.name == "compositing") {
+ bool force_compositing = IsForceCompositingModeEnabled();
+ if (force_compositing)
+ status += "_force";
+ if (has_thread)
+ status += "_threaded";
+ }
+ if (gpu_feature_info.name == "css_animation") {
+ if (has_thread)
+ status = "accelerated_threaded";
+ else
+ status = "accelerated";
+ }
+ }
+ // TODO(reveman): Remove this when crbug.com/223286 has been fixed.
+ if (gpu_feature_info.name == "raster" &&
+ cc::switches::IsImplSidePaintingEnabled()) {
+ status = "disabled_software_multithreaded";
+ }
+ feature_status_dict->SetString(
+ gpu_feature_info.name.c_str(), status.c_str());
+ }
+ return feature_status_dict;
+}
+
+base::Value* GetProblems() {
+ GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
+ std::string gpu_access_blocked_reason;
+ bool gpu_access_blocked =
+ !manager->GpuAccessAllowed(&gpu_access_blocked_reason);
+
+ base::ListValue* problem_list = new base::ListValue();
+ manager->GetBlacklistReasons(problem_list);
+
+ if (gpu_access_blocked) {
+ base::DictionaryValue* problem = new base::DictionaryValue();
+ problem->SetString("description",
+ "GPU process was unable to boot: " + gpu_access_blocked_reason);
+ problem->Set("crBugs", new base::ListValue());
+ problem->Set("webkitBugs", new base::ListValue());
+ problem_list->Insert(0, problem);
+ }
+
+ for (size_t i = 0; i < kNumFeatures; ++i) {
+ const GpuFeatureInfo gpu_feature_info = GetGpuFeatureInfo(i);
+ if (gpu_feature_info.disabled) {
+ base::DictionaryValue* problem = new base::DictionaryValue();
+ problem->SetString(
+ "description", gpu_feature_info.disabled_description);
+ problem->Set("crBugs", new base::ListValue());
+ problem->Set("webkitBugs", new base::ListValue());
+ problem_list->Append(problem);
+ }
+ }
+ return problem_list;
+}
+
+base::Value* GetDriverBugWorkarounds() {
+ base::ListValue* workaround_list = new base::ListValue();
+ GpuDataManagerImpl::GetInstance()->GetDriverBugWorkarounds(workaround_list);
+ return workaround_list;
+}
+
} // namespace content
diff --git a/chromium/content/browser/gpu/compositor_util.h b/chromium/content/browser/gpu/compositor_util.h
index c1c6a4229b1..89329f42f71 100644
--- a/chromium/content/browser/gpu/compositor_util.h
+++ b/chromium/content/browser/gpu/compositor_util.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_GPU_COMPOSITOR_UTIL_H_
#define CONTENT_BROWSER_GPU_COMPOSITOR_UTIL_H_
+#include "base/values.h"
#include "content/common/content_export.h"
namespace content {
@@ -21,6 +22,10 @@ CONTENT_EXPORT bool IsDelegatedRendererEnabled();
// Returns true if deadline scheduling is on (via flags, or platform default).
CONTENT_EXPORT bool IsDeadlineSchedulingEnabled();
+CONTENT_EXPORT base::Value* GetFeatureStatus();
+CONTENT_EXPORT base::Value* GetProblems();
+CONTENT_EXPORT base::Value* GetDriverBugWorkarounds();
+
} // namespace content
#endif // CONTENT_BROWSER_GPU_COMPOSITOR_UTIL_H_
diff --git a/chromium/content/browser/gpu/compositor_util_browsertest.cc b/chromium/content/browser/gpu/compositor_util_browsertest.cc
index 75fc60e429f..ac39daceed3 100644
--- a/chromium/content/browser/gpu/compositor_util_browsertest.cc
+++ b/chromium/content/browser/gpu/compositor_util_browsertest.cc
@@ -21,21 +21,35 @@ IN_PROC_BROWSER_TEST_F(CompositorUtilTest, CompositingModeAsExpected) {
enum CompositingMode {
DISABLED,
ENABLED,
- THREADED,
+ THREADED, // Implies FCM
+ DELEGATED, // Implies threaded
} expected_mode = DISABLED;
-#if defined(OS_ANDROID) || defined(USE_AURA)
+#if defined(USE_AURA)
+ expected_mode = DELEGATED;
+#elif defined(OS_ANDROID)
expected_mode = THREADED;
#elif defined(OS_MACOSX)
- if (base::mac::IsOSMountainLionOrLater())
- expected_mode = ENABLED;
+ expected_mode = THREADED;
+ // Lion and SnowLeopard have compositing blacklisted when using the Apple
+ // software renderer, so results will vary depending if this test is being
+ // run in a VM versus actual hardware.
+ // http://crbug.com/230931
+ if (base::mac::IsOSLionOrEarlier())
+ return;
#elif defined(OS_WIN)
if (base::win::GetVersion() >= base::win::VERSION_VISTA)
- expected_mode = ENABLED;
+ expected_mode = THREADED;
#endif
- EXPECT_EQ(expected_mode == ENABLED || expected_mode == THREADED,
+ EXPECT_EQ(expected_mode == ENABLED ||
+ expected_mode == THREADED ||
+ expected_mode == DELEGATED,
IsForceCompositingModeEnabled());
- EXPECT_EQ(expected_mode == THREADED, IsThreadedCompositingEnabled());
+ EXPECT_EQ(expected_mode == THREADED ||
+ expected_mode == DELEGATED,
+ IsThreadedCompositingEnabled());
+ EXPECT_EQ(expected_mode == DELEGATED,
+ IsDelegatedRendererEnabled());
}
}
diff --git a/chromium/content/browser/gpu/generate_webgl_conformance_test_list.py b/chromium/content/browser/gpu/generate_webgl_conformance_test_list.py
deleted file mode 100755
index 8d5854ab52d..00000000000
--- a/chromium/content/browser/gpu/generate_webgl_conformance_test_list.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-"""Auto-generates the WebGL conformance test list header file.
-
-Parses the WebGL conformance test *.txt file, which contains a list of URLs
-for individual conformance tests (each on a new line). It recursively parses
-*.txt files. For each test URL, the matching gtest call is created and
-sent to the C++ header file.
-"""
-
-import getopt
-import os
-import re
-import sys
-
-COPYRIGHT = """\
-// 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.
-
-"""
-WARNING = """\
-// DO NOT EDIT! This file is auto-generated by
-// generate_webgl_conformance_test_list.py
-// It is included by webgl_conformance_test.cc
-
-"""
-HEADER_GUARD = """\
-#ifndef CONTENT_TEST_GPU_WEBGL_CONFORMANCE_TEST_LIST_AUTOGEN_H_
-#define CONTENT_TEST_GPU_WEBGL_CONFORMANCE_TEST_LIST_AUTOGEN_H_
-
-"""
-HEADER_GUARD_END = """
-#endif // CONTENT_TEST_GPU_WEBGL_CONFORMANCE_TEST_LIST_AUTOGEN_H_
-
-"""
-
-# Assume this script is run from the src/content/test/gpu directory.
-INPUT_DIR = "../../../third_party/webgl_conformance"
-INPUT_FILE = "00_test_list.txt"
-OUTPUT_FILE = "webgl_conformance_test_list_autogen.h"
-
-def main(argv):
- """Main function for the WebGL conformance test list generator.
- """
- if not os.path.exists(os.path.join(INPUT_DIR, INPUT_FILE)):
- print >> sys.stderr, "ERROR: WebGL conformance tests do not exist."
- print >> sys.stderr, "Run the script from the directory containing it."
- return 1
-
- output = open(OUTPUT_FILE, "w")
- output.write(COPYRIGHT)
- output.write(WARNING)
- output.write(HEADER_GUARD)
-
- test_prefix = {}
-
- unparsed_files = [INPUT_FILE]
- while unparsed_files:
- filename = unparsed_files.pop(0)
- try:
- input = open(os.path.join(INPUT_DIR, filename))
- except IOError:
- print >> sys.stderr, "WARNING: %s does not exist (skipped)." % filename
- continue
-
- for url in input:
- url = re.sub("//.*", "", url)
- url = re.sub("#.*", "", url)
- url = url.strip()
- # Some filename has options before them, for example,
- # --min-version 1.0.2 testname.html
- pos = url.rfind(" ")
- if pos != -1:
- url = url[pos+1:]
-
- if not url:
- continue
-
- # Cannot use os.path.join() because Windows with use "\\" but this path
- # is sent through javascript.
- if os.path.dirname(filename):
- url = "%s/%s" % (os.path.dirname(filename), url)
-
- # Queue all text files for parsing, because test list URLs are nested
- # through .txt files.
- if re.match(".+\.txt\s*$", url):
- unparsed_files.append(url)
-
- # Convert the filename to a valid test name and output the gtest code.
- else:
- name = os.path.splitext(url)[0]
- name = re.sub("\W+", "_", name)
- if os.path.exists(os.path.join(INPUT_DIR, url)):
- output.write('CONFORMANCE_TEST(%s,\n "%s");\n' % (name, url))
- else:
- print >> sys.stderr, "WARNING: %s does not exist (skipped)." % url
- input.close()
-
- output.write(HEADER_GUARD_END)
- output.close()
- return 0
-
-if __name__ == "__main__":
- sys.exit(main(sys.argv[1:]))
diff --git a/chromium/content/browser/gpu/gpu_crash_browsertest.cc b/chromium/content/browser/gpu/gpu_crash_browsertest.cc
deleted file mode 100644
index 98650d320c1..00000000000
--- a/chromium/content/browser/gpu/gpu_crash_browsertest.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/path_service.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
-#include "content/browser/gpu/gpu_process_host_ui_shim.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/common/content_paths.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
-
-namespace content {
-class GpuCrashTest : public ContentBrowserTest {
- protected:
- virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
- base::FilePath test_dir;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir));
- gpu_test_dir_ = test_dir.AppendASCII("gpu");
- }
- base::FilePath gpu_test_dir_;
-};
-
-#if defined(OS_LINUX) && !defined(NDEBUG)
-// http://crbug.com/254724
-#define IF_NOT_DEBUG_LINUX(x) DISABLED_ ## x
-#else
-#define IF_NOT_DEBUG_LINUX(x) x
-#endif
-
-IN_PROC_BROWSER_TEST_F(GpuCrashTest, IF_NOT_DEBUG_LINUX(MANUAL_Kill)) {
- DOMMessageQueue message_queue;
-
- content::GpuDataManagerImpl::GetInstance()->
- DisableDomainBlockingFor3DAPIsForTesting();
-
- // Load page and wait for it to load.
- content::WindowedNotificationObserver observer(
- content::NOTIFICATION_LOAD_STOP,
- content::NotificationService::AllSources());
- NavigateToURL(
- shell(),
- GetFileUrlWithQuery(
- gpu_test_dir_.AppendASCII("webgl.html"), "query=kill"));
- observer.Wait();
-
- GpuProcessHostUIShim* host =
- GpuProcessHostUIShim::GetOneInstance();
- ASSERT_TRUE(host);
- host->SimulateCrash();
-
- std::string m;
- ASSERT_TRUE(message_queue.WaitForMessage(&m));
- EXPECT_EQ("\"SUCCESS\"", m);
-}
-
-IN_PROC_BROWSER_TEST_F(GpuCrashTest,
- IF_NOT_DEBUG_LINUX(MANUAL_WebkitLoseContext)) {
- DOMMessageQueue message_queue;
-
- NavigateToURL(
- shell(),
- GetFileUrlWithQuery(
- gpu_test_dir_.AppendASCII("webgl.html"),
- "query=WEBGL_lose_context"));
-
- std::string m;
- ASSERT_TRUE(message_queue.WaitForMessage(&m));
- EXPECT_EQ("\"SUCCESS\"", m);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.cc b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
index 31096574f9e..18b1a71c16e 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
@@ -162,11 +162,6 @@ void GpuDataManagerImpl::UpdateRendererWebPrefs(
private_->UpdateRendererWebPrefs(prefs);
}
-gpu::GpuSwitchingOption GpuDataManagerImpl::GetGpuSwitchingOption() const {
- base::AutoLock auto_lock(lock_);
- return private_->GetGpuSwitchingOption();
-}
-
std::string GpuDataManagerImpl::GetBlacklistVersion() const {
base::AutoLock auto_lock(lock_);
return private_->GetBlacklistVersion();
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.h b/chromium/content/browser/gpu/gpu_data_manager_impl.h
index a1ea2013129..7fb75a40894 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.h
@@ -21,7 +21,6 @@
#include "content/public/common/gpu_memory_stats.h"
#include "content/public/common/three_d_api_types.h"
#include "gpu/config/gpu_info.h"
-#include "gpu/config/gpu_switching_option.h"
class CommandLine;
class GURL;
@@ -109,8 +108,6 @@ class CONTENT_EXPORT GpuDataManagerImpl
// Update WebPreferences for renderer based on blacklisting decisions.
void UpdateRendererWebPrefs(WebPreferences* prefs) const;
- gpu::GpuSwitchingOption GetGpuSwitchingOption() const;
-
std::string GetBlacklistVersion() const;
std::string GetDriverBugListVersion() const;
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 94adacd798a..a9dfa8c8f50 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -198,21 +198,6 @@ void UpdateStats(const gpu::GPUInfo& gpu_info,
gpu_info.gl_reset_notification_strategy);
}
-// Strip out the non-digital info; if after that, we get an empty string,
-// return "0".
-std::string ProcessVersionString(const std::string& raw_string) {
- const std::string valid_set = "0123456789.";
- size_t start_pos = raw_string.find_first_of(valid_set);
- if (start_pos == std::string::npos)
- return "0";
- size_t end_pos = raw_string.find_first_not_of(raw_string, start_pos);
- std::string version_string = raw_string.substr(
- start_pos, end_pos - start_pos);
- if (version_string.empty())
- return "0";
- return version_string;
-}
-
// Combine the integers into a string, seperated by ','.
std::string IntSetToString(const std::set<int>& list) {
std::string rt;
@@ -258,10 +243,6 @@ void ApplyAndroidWorkarounds(const gpu::GPUInfo& gpu_info,
std::string renderer(StringToLowerASCII(gpu_info.gl_renderer));
bool is_img =
gpu_info.gl_vendor.find("Imagination") != std::string::npos;
- bool is_nexus7 =
- gpu_info.machine_model.find("Nexus 7") != std::string::npos;
- bool is_nexus10 =
- gpu_info.machine_model.find("Nexus 10") != std::string::npos;
gfx::DeviceDisplayInfo info;
int default_tile_size = 256;
@@ -283,11 +264,6 @@ void ApplyAndroidWorkarounds(const gpu::GPUInfo& gpu_info,
if (is_img)
default_tile_size -= 8;
- // If we are using the MapImage API double the tile size to reduce
- // the number of zero-copy buffers being used.
- if (command_line->HasSwitch(cc::switches::kEnableMapImage))
- default_tile_size *= 2;
-
// Set the command line if it isn't already set and we changed
// the default tile size.
if (default_tile_size != 256 &&
@@ -300,16 +276,23 @@ void ApplyAndroidWorkarounds(const gpu::GPUInfo& gpu_info,
command_line->AppendSwitchASCII(
switches::kDefaultTileHeight, size.str());
}
+}
+#endif // OS_ANDROID
- // Increase the resolution of low resolution tiles for Nexus tablets.
- if ((is_nexus7 || is_nexus10) &&
- !command_line->HasSwitch(
- cc::switches::kLowResolutionContentsScaleFactor)) {
- command_line->AppendSwitchASCII(
- cc::switches::kLowResolutionContentsScaleFactor, "0.25");
+// Overwrite force gpu workaround if a commandline switch exists.
+void AdjustGpuSwitchingOption(std::set<int>* workarounds) {
+ DCHECK(workarounds);
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ std::string option = command_line.GetSwitchValueASCII(
+ switches::kGpuSwitching);
+ if (option == switches::kGpuSwitchingOptionNameForceDiscrete) {
+ workarounds->erase(gpu::FORCE_INTEGRATED_GPU);
+ workarounds->insert(gpu::FORCE_DISCRETE_GPU);
+ } else if (option == switches::kGpuSwitchingOptionNameForceIntegrated) {
+ workarounds->erase(gpu::FORCE_DISCRETE_GPU);
+ workarounds->insert(gpu::FORCE_INTEGRATED_GPU);
}
}
-#endif // OS_ANDROID
// Block all domains' use of 3D APIs for this many milliseconds if
// approaching a threshold where system stability might be compromised.
@@ -332,10 +315,16 @@ void GpuDataManagerImplPrivate::InitializeForTesting(
// This function is for testing only, so disable histograms.
update_histograms_ = false;
- InitializeImpl(gpu_blacklist_json, std::string(), std::string(), gpu_info);
+ // Prevent all further initialization.
+ finalized_ = true;
+
+ InitializeImpl(gpu_blacklist_json, std::string(), gpu_info);
}
bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const {
+ if (CommandLine::ForCurrentProcess()->HasSwitch("chrome-frame") &&
+ feature == gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING)
+ return false;
#if defined(OS_CHROMEOS)
if (feature == gpu::GPU_FEATURE_TYPE_PANEL_FITTING &&
CommandLine::ForCurrentProcess()->HasSwitch(
@@ -545,13 +534,30 @@ void GpuDataManagerImplPrivate::GetGLStrings(std::string* gl_vendor,
void GpuDataManagerImplPrivate::Initialize() {
TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize");
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kSkipGpuDataLoading) &&
- !command_line->HasSwitch(switches::kUseGpuInTests))
+ if (finalized_) {
+ DVLOG(0) << "GpuDataManagerImpl marked as finalized; skipping Initialize";
+ return;
+ }
+
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kSkipGpuDataLoading))
return;
gpu::GPUInfo gpu_info;
- {
+ if (command_line->GetSwitchValueASCII(
+ switches::kUseGL) == gfx::kGLImplementationOSMesaName) {
+ // 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
+ // blacklist below which may have non-device specific entries we want to
+ // apply anyways (e.g., OS version blacklisting).
+ gpu_info.gpu.vendor_id = 0xffff;
+ gpu_info.gpu.device_id = 0xffff;
+
+ // 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;
+ } else {
TRACE_EVENT0("startup",
"GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo");
gpu::CollectBasicGraphicsInfo(&gpu_info);
@@ -562,18 +568,15 @@ void GpuDataManagerImplPrivate::Initialize() {
#endif
std::string gpu_blacklist_string;
- std::string gpu_switching_list_string;
std::string gpu_driver_bug_list_string;
if (!command_line->HasSwitch(switches::kIgnoreGpuBlacklist) &&
!command_line->HasSwitch(switches::kUseGpuInTests)) {
gpu_blacklist_string = gpu::kSoftwareRenderingListJson;
- gpu_switching_list_string = gpu::kGpuSwitchingListJson;
}
if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
gpu_driver_bug_list_string = gpu::kGpuDriverBugListJson;
}
InitializeImpl(gpu_blacklist_string,
- gpu_switching_list_string,
gpu_driver_bug_list_string,
gpu_info);
}
@@ -584,6 +587,7 @@ void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
return;
gpu::MergeGPUInfo(&gpu_info_, gpu_info);
+ gpu::DetermineActiveGPU(&gpu_info_);
complete_gpu_info_already_requested_ =
complete_gpu_info_already_requested_ || gpu_info_.finalized;
@@ -597,22 +601,11 @@ void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
UpdateBlacklistedFeatures(features);
}
- if (gpu_switching_list_) {
- std::set<int> option = gpu_switching_list_->MakeDecision(
- gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
- if (option.size() == 1) {
- // Blacklist decision should not overwrite commandline switch from users.
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (!command_line->HasSwitch(switches::kGpuSwitching)) {
- gpu_switching_ = static_cast<gpu::GpuSwitchingOption>(
- *(option.begin()));
- }
- }
- }
if (gpu_driver_bug_list_) {
gpu_driver_bugs_ = gpu_driver_bug_list_->MakeDecision(
gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
}
+ AdjustGpuSwitchingOption(&gpu_driver_bugs_);
// We have to update GpuFeatureType before notify all the observers.
NotifyGpuInfoUpdate();
@@ -630,23 +623,20 @@ void GpuDataManagerImplPrivate::AppendRendererCommandLine(
DCHECK(command_line);
if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL)) {
- if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL))
- command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
if (!command_line->HasSwitch(switches::kDisablePepper3d))
command_line->AppendSwitch(switches::kDisablePepper3d);
}
- if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING) &&
- !command_line->HasSwitch(switches::kDisableGLMultisampling))
- command_line->AppendSwitch(switches::kDisableGLMultisampling);
if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) &&
!command_line->HasSwitch(switches::kDisableAcceleratedCompositing))
command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
- if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) &&
- !command_line->HasSwitch(switches::kDisableAccelerated2dCanvas))
- command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
!command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode))
command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
+#if defined(ENABLE_WEBRTC)
+ if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) &&
+ !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding))
+ command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding);
+#endif
if (use_software_compositor_ &&
!command_line->HasSwitch(switches::kEnableSoftwareCompositing))
@@ -677,7 +667,6 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
}
if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING)) {
command_line->AppendSwitch(switches::kDisableImageTransportSurface);
- reduce_sandbox = true;
}
if (gpu_driver_bugs_.find(gpu::DISABLE_D3D11) != gpu_driver_bugs_.end())
command_line->AppendSwitch(switches::kDisableD3D11);
@@ -696,24 +685,10 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
} else if (!use_gl.empty()) {
command_line->AppendSwitchASCII(switches::kUseGL, use_gl);
}
- if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
+ if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "true");
- switch (gpu_switching_) {
- case gpu::GPU_SWITCHING_OPTION_FORCE_DISCRETE:
- command_line->AppendSwitchASCII(switches::kGpuSwitching,
- switches::kGpuSwitchingOptionNameForceDiscrete);
- break;
- case gpu::GPU_SWITCHING_OPTION_FORCE_INTEGRATED:
- command_line->AppendSwitchASCII(switches::kGpuSwitching,
- switches::kGpuSwitchingOptionNameForceIntegrated);
- break;
- case gpu::GPU_SWITCHING_OPTION_AUTOMATIC:
- case gpu::GPU_SWITCHING_OPTION_UNKNOWN:
- break;
- }
- } else {
+ else
command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "false");
- }
if (!swiftshader_path.empty()) {
command_line->AppendSwitchPath(switches::kSwiftShaderPath,
@@ -729,6 +704,12 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
!command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
}
+#if defined(ENABLE_WEBRTC)
+ if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) &&
+ !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) {
+ command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding);
+ }
+#endif
#if defined(OS_WIN)
// DisplayLink 7.1 and earlier can cause the GPU process to crash on startup.
@@ -833,13 +814,6 @@ void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
#endif
}
-gpu::GpuSwitchingOption
-GpuDataManagerImplPrivate::GetGpuSwitchingOption() const {
- if (!ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
- return gpu::GPU_SWITCHING_OPTION_UNKNOWN;
- return gpu_switching_;
-}
-
void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
card_blacklisted_ = true;
@@ -880,11 +854,7 @@ void GpuDataManagerImplPrivate::GetDriverBugWorkarounds(
void GpuDataManagerImplPrivate::AddLogMessage(
int level, const std::string& header, const std::string& message) {
- base::DictionaryValue* dict = new base::DictionaryValue();
- dict->SetInteger("level", level);
- dict->SetString("header", header);
- dict->SetString("message", message);
- log_messages_.Append(dict);
+ log_messages_.push_back(LogMessage(level, header, message));
}
void GpuDataManagerImplPrivate::ProcessCrashed(
@@ -908,8 +878,14 @@ void GpuDataManagerImplPrivate::ProcessCrashed(
}
base::ListValue* GpuDataManagerImplPrivate::GetLogMessages() const {
- base::ListValue* value;
- value = log_messages_.DeepCopy();
+ base::ListValue* value = new base::ListValue;
+ for (size_t ii = 0; ii < log_messages_.size(); ++ii) {
+ 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);
+ }
return value;
}
@@ -975,7 +951,6 @@ GpuDataManagerImplPrivate* GpuDataManagerImplPrivate::Create(
GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
GpuDataManagerImpl* owner)
: complete_gpu_info_already_requested_(false),
- gpu_switching_(gpu::GPU_SWITCHING_OPTION_AUTOMATIC),
observer_list_(new GpuDataManagerObserverList),
use_swiftshader_(false),
card_blacklisted_(false),
@@ -985,7 +960,8 @@ GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
owner_(owner),
display_count_(0),
gpu_process_accessible_(true),
- use_software_compositor_(false) {
+ use_software_compositor_(false),
+ finalized_(false) {
DCHECK(owner_);
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) {
@@ -997,22 +973,19 @@ GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
if (command_line->HasSwitch(switches::kEnableSoftwareCompositing))
use_software_compositor_ = true;
//TODO(jbauman): enable for Chrome OS and Linux
-#if defined(USE_AURA) && defined(OS_WIN)
+#if defined(USE_AURA) && !defined(OS_CHROMEOS)
use_software_compositor_ = true;
#endif
- if (command_line->HasSwitch(switches::kGpuSwitching)) {
- std::string option_string = command_line->GetSwitchValueASCII(
- switches::kGpuSwitching);
- gpu::GpuSwitchingOption option =
- gpu::StringToGpuSwitchingOption(option_string);
- if (option != gpu::GPU_SWITCHING_OPTION_UNKNOWN)
- gpu_switching_ = option;
- }
#if defined(OS_MACOSX)
CGGetActiveDisplayList (0, NULL, &display_count_);
CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_);
#endif // OS_MACOSX
+
+ // For testing only.
+ if (command_line->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs)) {
+ domain_blocking_enabled_ = false;
+ }
}
GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
@@ -1023,32 +996,26 @@ GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
void GpuDataManagerImplPrivate::InitializeImpl(
const std::string& gpu_blacklist_json,
- const std::string& gpu_switching_list_json,
const std::string& gpu_driver_bug_list_json,
const gpu::GPUInfo& gpu_info) {
- std::string browser_version_string = ProcessVersionString(
- GetContentClient()->GetProduct());
- CHECK(!browser_version_string.empty());
+ const bool log_gpu_control_list_decisions =
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kLogGpuControlListDecisions);
if (!gpu_blacklist_json.empty()) {
gpu_blacklist_.reset(gpu::GpuBlacklist::Create());
+ if (log_gpu_control_list_decisions)
+ gpu_blacklist_->enable_control_list_logging("gpu_blacklist");
bool success = gpu_blacklist_->LoadList(
- browser_version_string, gpu_blacklist_json,
- gpu::GpuControlList::kCurrentOsOnly);
- DCHECK(success);
- }
- if (!gpu_switching_list_json.empty()) {
- gpu_switching_list_.reset(gpu::GpuSwitchingList::Create());
- bool success = gpu_switching_list_->LoadList(
- browser_version_string, gpu_switching_list_json,
- gpu::GpuControlList::kCurrentOsOnly);
+ gpu_blacklist_json, gpu::GpuControlList::kCurrentOsOnly);
DCHECK(success);
}
if (!gpu_driver_bug_list_json.empty()) {
gpu_driver_bug_list_.reset(gpu::GpuDriverBugList::Create());
+ if (log_gpu_control_list_decisions)
+ gpu_driver_bug_list_->enable_control_list_logging("gpu_driver_bug_list");
bool success = gpu_driver_bug_list_->LoadList(
- browser_version_string, gpu_driver_bug_list_json,
- gpu::GpuControlList::kCurrentOsOnly);
+ gpu_driver_bug_list_json, gpu::GpuControlList::kCurrentOsOnly);
DCHECK(success);
}
@@ -1103,17 +1070,10 @@ void GpuDataManagerImplPrivate::UpdateGpuSwitchingManager(
gpu_info.secondary_gpus.size() + 1);
if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
- switch (gpu_switching_) {
- case gpu::GPU_SWITCHING_OPTION_FORCE_DISCRETE:
- ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu();
- break;
- case gpu::GPU_SWITCHING_OPTION_FORCE_INTEGRATED:
- ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
- break;
- case gpu::GPU_SWITCHING_OPTION_AUTOMATIC:
- case gpu::GPU_SWITCHING_OPTION_UNKNOWN:
- break;
- }
+ if (gpu_driver_bugs_.count(gpu::FORCE_DISCRETE_GPU) == 1)
+ ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu();
+ else if (gpu_driver_bugs_.count(gpu::FORCE_INTEGRATED_GPU) == 1)
+ ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
}
}
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
index 8d15296e4a9..8332c505913 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -9,6 +9,7 @@
#include <map>
#include <set>
#include <string>
+#include <vector>
#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
@@ -16,7 +17,6 @@
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "gpu/config/gpu_blacklist.h"
#include "gpu/config/gpu_driver_bug_list.h"
-#include "gpu/config/gpu_switching_list.h"
namespace content {
@@ -65,8 +65,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
void UpdateRendererWebPrefs(WebPreferences* prefs) const;
- gpu::GpuSwitchingOption GetGpuSwitchingOption() const;
-
std::string GetBlacklistVersion() const;
std::string GetDriverBugListVersion() const;
@@ -166,10 +164,22 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
typedef ObserverListThreadSafe<GpuDataManagerObserver>
GpuDataManagerObserverList;
+ struct LogMessage {
+ int level;
+ std::string header;
+ std::string message;
+
+ LogMessage(int _level,
+ const std::string& _header,
+ const std::string& _message)
+ : level(_level),
+ header(_header),
+ message(_message) { }
+ };
+
explicit GpuDataManagerImplPrivate(GpuDataManagerImpl* owner);
void InitializeImpl(const std::string& gpu_blacklist_json,
- const std::string& gpu_switching_list_json,
const std::string& gpu_driver_bug_list_json,
const gpu::GPUInfo& gpu_info);
@@ -206,19 +216,16 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
std::set<int> blacklisted_features_;
std::set<int> preliminary_blacklisted_features_;
- gpu::GpuSwitchingOption gpu_switching_;
-
std::set<int> gpu_driver_bugs_;
gpu::GPUInfo gpu_info_;
scoped_ptr<gpu::GpuBlacklist> gpu_blacklist_;
- scoped_ptr<gpu::GpuSwitchingList> gpu_switching_list_;
scoped_ptr<gpu::GpuDriverBugList> gpu_driver_bug_list_;
const scoped_refptr<GpuDataManagerObserverList> observer_list_;
- base::ListValue log_messages_;
+ std::vector<LogMessage> log_messages_;
bool use_swiftshader_;
@@ -247,6 +254,9 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
bool use_software_compositor_;
+ // True if all future Initialize calls should be ignored.
+ bool finalized_;
+
DISALLOW_COPY_AND_ASSIGN(GpuDataManagerImplPrivate);
};
diff --git a/chromium/content/browser/gpu/gpu_functional_browsertest.cc b/chromium/content/browser/gpu/gpu_functional_browsertest.cc
deleted file mode 100644
index 4e95d2d5c11..00000000000
--- a/chromium/content/browser/gpu/gpu_functional_browsertest.cc
+++ /dev/null
@@ -1,142 +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 "base/command_line.h"
-#include "base/path_service.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/common/content_paths.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/url_constants.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
-
-namespace content {
-
-namespace {
- void VerifyGPUProcessLaunch(bool* result) {
- GpuProcessHost* host =
- GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH);
- *result = !!host;
- }
-}
-
-class GpuFunctionalTest : public ContentBrowserTest {
- protected:
- virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
- base::FilePath test_dir;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir));
- gpu_test_dir_ = test_dir.AppendASCII("gpu");
- }
-
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- command_line->AppendSwitch(switches::kDisableGpuProcessPrelaunch);
- }
-
- void VerifyHardwareAccelerated(const std::string& feature) {
- NavigateToURL(shell(),
- GURL(std::string(chrome::kChromeUIScheme).
- append("://").
- append(kChromeUIGpuHost)));
-
- {
- // Verify that the given feature is hardware accelerated..
- std::string javascript =
- "function VerifyHardwareAccelerated(feature) {"
- " var list = document.querySelector(\".feature-status-list\");"
- " for (var i=0; i < list.childElementCount; i++) {"
- " var span_list = list.children[i].getElementsByTagName('span');"
- " var feature_str = span_list[0].textContent;"
- " var value_str = span_list[1].textContent;"
- " if ((feature_str == feature) &&"
- " (value_str == 'Hardware accelerated')) {"
- " domAutomationController.send(\"success\");"
- " }"
- " }"
- "};";
- javascript.append("VerifyHardwareAccelerated(\"");
- javascript.append(feature);
- javascript.append("\");");
- std::string result;
- EXPECT_TRUE(ExecuteScriptAndExtractString(shell()->web_contents(),
- javascript,
- &result));
- EXPECT_EQ(result, "success");
- }
- }
-
- void VerifyGPUProcessOnPage(std::string filename, bool wait) {
- ASSERT_TRUE(test_server()->Start());
- DOMMessageQueue message_queue;
-
- std::string url("files/gpu/");
- GURL full_url = test_server()->GetURL(url.append(filename));
- NavigateToURL(shell(), full_url);
-
- if (wait) {
- std::string result_string;
- ASSERT_TRUE(message_queue.WaitForMessage(&result_string));
- }
-
- bool result = false;
- BrowserThread::PostTaskAndReply(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VerifyGPUProcessLaunch, &result),
- base::MessageLoop::QuitClosure());
- base::MessageLoop::current()->Run();
- EXPECT_TRUE(result);
- }
-
- base::FilePath gpu_test_dir_;
-};
-
-#if defined(OS_LINUX) && !defined(NDEBUG)
-// http://crbug.com/254724
-#define IF_NOT_DEBUG_LINUX(x) DISABLED_ ## x
-#else
-#define IF_NOT_DEBUG_LINUX(x) x
-#endif
-
-IN_PROC_BROWSER_TEST_F(
- GpuFunctionalTest,
- IF_NOT_DEBUG_LINUX(MANUAL_TestFeatureHardwareAccelerated)) {
- VerifyHardwareAccelerated("WebGL: ");
- VerifyHardwareAccelerated("Canvas: ");
- VerifyHardwareAccelerated("3D CSS: ");
-}
-
-// Verify that gpu process is spawned in webgl example.
-IN_PROC_BROWSER_TEST_F(GpuFunctionalTest,
- IF_NOT_DEBUG_LINUX(MANUAL_TestWebGL)) {
- VerifyGPUProcessOnPage("functional_webgl.html", false);
-}
-
-// Verify that gpu process is spawned when viewing a 2D canvas.
-IN_PROC_BROWSER_TEST_F(GpuFunctionalTest,
- IF_NOT_DEBUG_LINUX(MANUAL_Test2dCanvas)) {
- VerifyGPUProcessOnPage("functional_canvas_demo.html", false);
-}
-
-// Verify that gpu process is spawned when viewing a 3D CSS page.
-IN_PROC_BROWSER_TEST_F(GpuFunctionalTest,
- IF_NOT_DEBUG_LINUX(MANUAL_Test3dCss)) {
- VerifyGPUProcessOnPage("functional_3d_css.html", false);
-}
-
-#if defined(OS_LINUX)
-// crbug.com/257109
-#define MANUAL_TestGpuWithVideo DISABLED_TestGpuWithVideo
-#endif
-
-// Verify that gpu process is started when viewing video.
-IN_PROC_BROWSER_TEST_F(GpuFunctionalTest,
- MANUAL_TestGpuWithVideo) {
- VerifyGPUProcessOnPage("functional_video.html", true);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_info_browsertest.cc b/chromium/content/browser/gpu/gpu_info_browsertest.cc
deleted file mode 100644
index d555d1d05f0..00000000000
--- a/chromium/content/browser/gpu/gpu_info_browsertest.cc
+++ /dev/null
@@ -1,110 +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 "base/command_line.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/stringprintf.h"
-#include "base/sys_info.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
-#include "content/public/browser/gpu_data_manager_observer.h"
-#include "content/public/common/content_switches.h"
-#include "content/test/content_browser_test.h"
-
-namespace content {
-
-namespace {
-
-class TestObserver : public GpuDataManagerObserver {
- public:
- explicit TestObserver(base::MessageLoop* message_loop)
- : message_loop_(message_loop) {
- }
-
- virtual ~TestObserver() { }
-
- virtual void OnGpuInfoUpdate() OVERRIDE {
- // Display GPU/Driver information.
- gpu::GPUInfo gpu_info =
- GpuDataManagerImpl::GetInstance()->GetGPUInfo();
- std::string vendor_id = base::StringPrintf(
- "0x%04x", gpu_info.gpu.vendor_id);
- std::string device_id = base::StringPrintf(
- "0x%04x", gpu_info.gpu.device_id);
- LOG(INFO) << "GPU[0]: vendor_id = " << vendor_id
- << ", device_id = " << device_id;
- for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) {
- gpu::GPUInfo::GPUDevice gpu = gpu_info.secondary_gpus[i];
- vendor_id = base::StringPrintf("0x%04x", gpu.vendor_id);
- device_id = base::StringPrintf("0x%04x", gpu.device_id);
- LOG(INFO) << "GPU[" << (i + 1)
- << "]: vendor_id = " << vendor_id
- << ", device_od = " << device_id;
- }
- LOG(INFO) << "GPU Driver: vendor = " << gpu_info.driver_vendor
- << ", version = " << gpu_info.driver_version
- << ", date = " << gpu_info.driver_date;
-
- // Display GL information.
- LOG(INFO) << "GL: vendor = " << gpu_info.gl_vendor
- << ", renderer = " << gpu_info.gl_renderer;
-
- // Display GL window system binding information.
- LOG(INFO) << "GL Window System: vendor = " << gpu_info.gl_ws_vendor
- << ", version = " << gpu_info.gl_ws_version;
-
- // Display OS information.
- LOG(INFO) << "OS = " << base::SysInfo::OperatingSystemName()
- << " " << base::SysInfo::OperatingSystemVersion();
-
- message_loop_->Quit();
- }
-
- private:
- base::MessageLoop* message_loop_;
-};
-
-} // namespace anonymous
-
-class GpuInfoBrowserTest : public ContentBrowserTest {
- public:
- GpuInfoBrowserTest()
- : message_loop_(base::MessageLoop::TYPE_UI) {
- }
-
- virtual void SetUp() {
- // We expect real pixel output for these tests.
- UseRealGLContexts();
-
- ContentBrowserTest::SetUp();
- }
-
- base::MessageLoop* GetMessageLoop() { return &message_loop_; }
-
- private:
- base::MessageLoop message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuInfoBrowserTest);
-};
-
-IN_PROC_BROWSER_TEST_F(GpuInfoBrowserTest, MANUAL_DisplayGpuInfo) {
- // crbug.com/262287
-#if defined(OS_MACOSX)
- // TODO(zmo): crashing on Mac, and also we don't have the full info
- // collected.
- return;
-#endif
-#if defined(OS_LINUX) && !defined(NDEBUG)
- // TODO(zmo): crashing on Linux Debug.
- return;
-#endif
- TestObserver observer(GetMessageLoop());
- GpuDataManagerImpl::GetInstance()->AddObserver(&observer);
- GpuDataManagerImpl::GetInstance()->RequestCompleteGpuInfoIfNeeded();
-
- GetMessageLoop()->Run();
-}
-
-} // namespace content
-
diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc
index 0340077147d..5ff4373c497 100644
--- a/chromium/content/browser/gpu/gpu_internals_ui.cc
+++ b/chromium/content/browser/gpu/gpu_internals_ui.cc
@@ -14,7 +14,6 @@
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
#include "base/values.h"
-#include "cc/base/switches.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/public/browser/browser_thread.h"
@@ -29,19 +28,11 @@
#include "gpu/config/gpu_feature_type.h"
#include "gpu/config/gpu_info.h"
#include "grit/content_resources.h"
-#include "third_party/angle_dx11/src/common/version.h"
+#include "third_party/angle/src/common/version.h"
namespace content {
namespace {
-struct GpuFeatureInfo {
- std::string name;
- uint32 blocked;
- bool disabled;
- std::string disabled_description;
- bool fallback_to_software;
-};
-
WebUIDataSource* CreateGpuHTMLSource() {
WebUIDataSource* source = WebUIDataSource::Create(kChromeUIGpuHost);
@@ -67,13 +58,6 @@ base::DictionaryValue* NewDescriptionValuePair(const std::string& desc,
return dict;
}
-base::Value* NewStatusValue(const char* name, const char* status) {
- base::DictionaryValue* value = new base::DictionaryValue();
- value->SetString("name", name);
- value->SetString("status", status);
- return value;
-}
-
#if defined(OS_WIN)
// Output DxDiagNode tree as nested array of {description,value} pairs
base::ListValue* DxDiagNodeToList(const gpu::DxDiagNode& node) {
@@ -192,282 +176,6 @@ base::DictionaryValue* GpuInfoAsDictionaryValue() {
return info;
}
-// Determine if accelerated-2d-canvas is supported, which depends on whether
-// lose_context could happen.
-bool SupportsAccelerated2dCanvas() {
- if (GpuDataManagerImpl::GetInstance()->GetGPUInfo().can_lose_context)
- return false;
- return true;
-}
-
-base::Value* GetFeatureStatus() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
- std::string gpu_access_blocked_reason;
- bool gpu_access_blocked =
- !manager->GpuAccessAllowed(&gpu_access_blocked_reason);
-
- base::DictionaryValue* status = new base::DictionaryValue();
-
- const GpuFeatureInfo kGpuFeatureInfo[] = {
- {
- "2d_canvas",
- manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS),
- command_line.HasSwitch(switches::kDisableAccelerated2dCanvas) ||
- !SupportsAccelerated2dCanvas(),
- "Accelerated 2D canvas is unavailable: either disabled at the command"
- " line or not supported by the current system.",
- true
- },
- {
- "compositing",
- manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING),
- command_line.HasSwitch(switches::kDisableAcceleratedCompositing),
- "Accelerated compositing has been disabled, either via about:flags or"
- " command line. This adversely affects performance of all hardware"
- " accelerated features.",
- true
- },
- {
- "3d_css",
- manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
- manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS),
- command_line.HasSwitch(switches::kDisableAcceleratedLayers),
- "Accelerated layers have been disabled at the command line.",
- false
- },
- {
- "css_animation",
- manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
- manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS),
- command_line.HasSwitch(cc::switches::kDisableThreadedAnimation) ||
- command_line.HasSwitch(switches::kDisableAcceleratedCompositing) ||
- command_line.HasSwitch(switches::kDisableAcceleratedLayers),
- "Accelerated CSS animation has been disabled at the command line.",
- true
- },
- {
- "webgl",
- manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL),
- command_line.HasSwitch(switches::kDisableExperimentalWebGL),
- "WebGL has been disabled, either via about:flags or command line.",
- false
- },
- {
- "multisampling",
- manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING),
- command_line.HasSwitch(switches::kDisableGLMultisampling),
- "Multisampling has been disabled, either via about:flags or command"
- " line.",
- false
- },
- {
- "flash_3d",
- manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D),
- command_line.HasSwitch(switches::kDisableFlash3d),
- "Using 3d in flash has been disabled, either via about:flags or"
- " command line.",
- false
- },
- {
- "flash_stage3d",
- manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
- command_line.HasSwitch(switches::kDisableFlashStage3d),
- "Using Stage3d in Flash has been disabled, either via about:flags or"
- " command line.",
- false
- },
- {
- "flash_stage3d_baseline",
- manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE) ||
- manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
- command_line.HasSwitch(switches::kDisableFlashStage3d),
- "Using Stage3d Baseline profile in Flash has been disabled, either"
- " via about:flags or command line.",
- false
- },
- {
- "texture_sharing",
- manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING),
- command_line.HasSwitch(switches::kDisableImageTransportSurface),
- "Sharing textures between processes has been disabled, either via"
- " about:flags or command line.",
- false
- },
- {
- "video_decode",
- manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
- command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode),
- "Accelerated video decode has been disabled, either via about:flags"
- " or command line.",
- true
- },
- {
- "video",
- manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO),
- command_line.HasSwitch(switches::kDisableAcceleratedVideo) ||
- command_line.HasSwitch(switches::kDisableAcceleratedCompositing),
- "Accelerated video presentation has been disabled, either via"
- " about:flags or command line.",
- true
- },
-#if defined(OS_CHROMEOS)
- {
- "panel_fitting",
- manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_PANEL_FITTING),
- command_line.HasSwitch(switches::kDisablePanelFitting),
- "Panel fitting has been disabled, either via about:flags or command"
- " line.",
- false
- },
-#endif
- {
- "force_compositing_mode",
- manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE) &&
- !IsForceCompositingModeEnabled(),
- !IsForceCompositingModeEnabled() &&
- !manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE),
- "Force compositing mode is off, either disabled at the command"
- " line or not supported by the current system.",
- false
- },
- };
- const size_t kNumFeatures = sizeof(kGpuFeatureInfo) / sizeof(GpuFeatureInfo);
-
- // Build the feature_status field.
- {
- base::ListValue* feature_status_list = new base::ListValue();
-
- for (size_t i = 0; i < kNumFeatures; ++i) {
- // force_compositing_mode status is part of the compositing status.
- if (kGpuFeatureInfo[i].name == "force_compositing_mode")
- continue;
-
- std::string status;
- if (kGpuFeatureInfo[i].disabled) {
- status = "disabled";
- if (kGpuFeatureInfo[i].name == "css_animation") {
- status += "_software_animated";
- } else if (kGpuFeatureInfo[i].name == "raster") {
- if (cc::switches::IsImplSidePaintingEnabled())
- status += "_software_multithreaded";
- else
- status += "_software";
- } else {
- if (kGpuFeatureInfo[i].fallback_to_software)
- status += "_software";
- else
- status += "_off";
- }
- } else if (GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()) {
- status = "unavailable_software";
- } else if (kGpuFeatureInfo[i].blocked ||
- gpu_access_blocked) {
- status = "unavailable";
- if (kGpuFeatureInfo[i].fallback_to_software)
- status += "_software";
- else
- status += "_off";
- } else {
- status = "enabled";
- if (kGpuFeatureInfo[i].name == "webgl" &&
- (command_line.HasSwitch(switches::kDisableAcceleratedCompositing) ||
- manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)))
- status += "_readback";
- bool has_thread = IsThreadedCompositingEnabled();
- if (kGpuFeatureInfo[i].name == "compositing") {
- bool force_compositing = IsForceCompositingModeEnabled();
- if (force_compositing)
- status += "_force";
- if (has_thread)
- status += "_threaded";
- }
- if (kGpuFeatureInfo[i].name == "css_animation") {
- if (has_thread)
- status = "accelerated_threaded";
- else
- status = "accelerated";
- }
- }
- // TODO(reveman): Remove this when crbug.com/223286 has been fixed.
- if (kGpuFeatureInfo[i].name == "raster" &&
- cc::switches::IsImplSidePaintingEnabled()) {
- status = "disabled_software_multithreaded";
- }
- feature_status_list->Append(
- NewStatusValue(kGpuFeatureInfo[i].name.c_str(), status.c_str()));
- }
- gpu::GpuSwitchingOption gpu_switching_option =
- GpuDataManagerImpl::GetInstance()->GetGpuSwitchingOption();
- if (gpu_switching_option != gpu::GPU_SWITCHING_OPTION_UNKNOWN) {
- std::string gpu_switching;
- switch (gpu_switching_option) {
- case gpu::GPU_SWITCHING_OPTION_AUTOMATIC:
- gpu_switching = "gpu_switching_automatic";
- break;
- case gpu::GPU_SWITCHING_OPTION_FORCE_DISCRETE:
- gpu_switching = "gpu_switching_force_discrete";
- break;
- case gpu::GPU_SWITCHING_OPTION_FORCE_INTEGRATED:
- gpu_switching = "gpu_switching_force_integrated";
- break;
- default:
- break;
- }
- feature_status_list->Append(
- NewStatusValue("gpu_switching", gpu_switching.c_str()));
- }
- status->Set("featureStatus", feature_status_list);
- }
-
- // Build the problems list.
- {
- base::ListValue* problem_list = new base::ListValue();
- GpuDataManagerImpl::GetInstance()->GetBlacklistReasons(problem_list);
-
- if (gpu_access_blocked) {
- base::DictionaryValue* problem = new base::DictionaryValue();
- problem->SetString("description",
- "GPU process was unable to boot: " + gpu_access_blocked_reason);
- problem->Set("crBugs", new base::ListValue());
- problem->Set("webkitBugs", new base::ListValue());
- problem_list->Insert(0, problem);
- }
-
- for (size_t i = 0; i < kNumFeatures; ++i) {
- if (kGpuFeatureInfo[i].disabled) {
- base::DictionaryValue* problem = new base::DictionaryValue();
- problem->SetString(
- "description", kGpuFeatureInfo[i].disabled_description);
- problem->Set("crBugs", new base::ListValue());
- problem->Set("webkitBugs", new base::ListValue());
- problem_list->Append(problem);
- }
- }
-
- status->Set("problems", problem_list);
- }
-
- // Build driver bug workaround list.
- {
- base::ListValue* workaround_list = new base::ListValue();
- GpuDataManagerImpl::GetInstance()->GetDriverBugWorkarounds(workaround_list);
- status->Set("workarounds", workaround_list);
- }
-
- return status;
-}
-
// This class receives javascript messages from the renderer.
// Note that the WebUI infrastructure runs on the UI thread, therefore all of
// this class's methods are expected to run on the UI thread.
@@ -626,7 +334,10 @@ void GpuMessageHandler::OnGpuInfoUpdate() {
scoped_ptr<base::DictionaryValue> gpu_info_val(GpuInfoAsDictionaryValue());
// Add in blacklisting features
- base::Value* feature_status = GetFeatureStatus();
+ base::DictionaryValue* feature_status = new DictionaryValue;
+ feature_status->Set("featureStatus", GetFeatureStatus());
+ feature_status->Set("problems", GetProblems());
+ feature_status->Set("workarounds", GetDriverBugWorkarounds());
if (feature_status)
gpu_info_val->Set("featureStatus", feature_status);
diff --git a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
index 0ee93dba806..ca2ccf9ee05 100644
--- a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -3,8 +3,14 @@
// found in the LICENSE file.
#include "base/command_line.h"
+#include "base/run_loop.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include "content/browser/gpu/gpu_process_host_ui_shim.h"
+#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_switches.h"
#include "content/test/content_browser_test.h"
#include "ui/gl/gl_switches.h"
@@ -12,17 +18,33 @@
namespace {
+using content::WebGraphicsContext3DCommandBufferImpl;
+
class ContextTestBase : public content::ContentBrowserTest {
public:
virtual void SetUpOnMainThread() OVERRIDE {
- CHECK(content::BrowserGpuChannelHostFactory::instance());
+ if (!content::BrowserGpuChannelHostFactory::CanUseForTesting())
+ return;
+
+ if (!content::BrowserGpuChannelHostFactory::instance())
+ content::BrowserGpuChannelHostFactory::Initialize(true);
+
+ content::BrowserGpuChannelHostFactory* factory =
+ content::BrowserGpuChannelHostFactory::instance();
+ CHECK(factory);
+ scoped_refptr<content::GpuChannelHost> gpu_channel_host(
+ factory->EstablishGpuChannelSync(
+ content::
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
context_.reset(
- content::WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- content::BrowserGpuChannelHostFactory::instance(),
- WebKit::WebGraphicsContext3D::Attributes(),
- GURL()));
+ WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
+ gpu_channel_host.get(),
+ blink::WebGraphicsContext3D::Attributes(),
+ GURL(),
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits()));
CHECK(context_.get());
context_->makeContextCurrent();
+ context_support_ = context_->GetContextSupport();
ContentBrowserTest::SetUpOnMainThread();
}
@@ -33,11 +55,155 @@ class ContextTestBase : public content::ContentBrowserTest {
}
protected:
- scoped_ptr<WebKit::WebGraphicsContext3D> context_;
+ scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
+ gpu::ContextSupport* context_support_;
};
} // namespace
-// Include the actual tests.
+// Include the shared tests.
#define CONTEXT_TEST_F IN_PROC_BROWSER_TEST_F
#include "content/common/gpu/client/gpu_context_tests.h"
+
+namespace content {
+
+class BrowserGpuChannelHostFactoryTest : public ContextTestBase {
+ public:
+ virtual void SetUpOnMainThread() OVERRIDE {
+ if (!content::BrowserGpuChannelHostFactory::CanUseForTesting())
+ return;
+
+ // Start all tests without a gpu channel so that the tests exercise a
+ // consistent codepath.
+ if (!content::BrowserGpuChannelHostFactory::instance())
+ content::BrowserGpuChannelHostFactory::Initialize(false);
+
+ CHECK(GetFactory());
+
+ ContentBrowserTest::SetUpOnMainThread();
+ }
+
+ virtual void TearDownOnMainThread() OVERRIDE {
+ ContextTestBase::TearDownOnMainThread();
+ }
+
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ // Start all tests without a gpu channel so that the tests exercise a
+ // consistent codepath.
+ command_line->AppendSwitch(switches::kDisableGpuProcessPrelaunch);
+ }
+
+ void OnContextLost(const base::Closure callback, int* counter) {
+ (*counter)++;
+ callback.Run();
+ }
+
+ protected:
+ BrowserGpuChannelHostFactory* GetFactory() {
+ return BrowserGpuChannelHostFactory::instance();
+ }
+
+ bool IsChannelEstablished() {
+ return GetFactory()->GetGpuChannel() != NULL;
+ }
+
+ void EstablishAndWait() {
+ base::RunLoop run_loop;
+ GetFactory()->EstablishGpuChannel(
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ GpuChannelHost* GetGpuChannel() {
+ return GetFactory()->GetGpuChannel();
+ }
+
+ static void Signal(bool *event) {
+ CHECK_EQ(*event, false);
+ *event = true;
+ }
+
+ scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext() {
+ return make_scoped_ptr(
+ WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
+ GetGpuChannel(),
+ blink::WebGraphicsContext3D::Attributes(),
+ GURL(),
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits()));
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, Basic) {
+ if (!context_)
+ return;
+
+ DCHECK(!IsChannelEstablished());
+ EstablishAndWait();
+ EXPECT_TRUE(GetGpuChannel() != NULL);
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
+ EstablishAndTerminate) {
+ if (!context_)
+ return;
+
+ DCHECK(!IsChannelEstablished());
+ base::RunLoop run_loop;
+ GetFactory()->EstablishGpuChannel(
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE,
+ run_loop.QuitClosure());
+ GetFactory()->Terminate();
+
+ // The callback should still trigger.
+ run_loop.Run();
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, AlreadyEstablished) {
+ if (!context_)
+ return;
+
+ DCHECK(!IsChannelEstablished());
+ scoped_refptr<GpuChannelHost> gpu_channel =
+ GetFactory()->EstablishGpuChannelSync(
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE);
+
+ // Expect established callback immediately.
+ bool event = false;
+ GetFactory()->EstablishGpuChannel(
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE,
+ base::Bind(&BrowserGpuChannelHostFactoryTest::Signal, &event));
+ EXPECT_TRUE(event);
+ EXPECT_EQ(gpu_channel, GetGpuChannel());
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, CrashAndRecover) {
+ if (!context_)
+ return;
+
+ DCHECK(!IsChannelEstablished());
+ EstablishAndWait();
+ scoped_refptr<GpuChannelHost> host = GetGpuChannel();
+
+ scoped_refptr<ContextProviderCommandBuffer> provider =
+ ContextProviderCommandBuffer::Create(CreateContext(),
+ "BrowserGpuChannelHostFactoryTest");
+ base::RunLoop run_loop;
+ int counter = 0;
+ provider->SetLostContextCallback(
+ base::Bind(&BrowserGpuChannelHostFactoryTest::OnContextLost,
+ base::Unretained(this), run_loop.QuitClosure(), &counter));
+ EXPECT_TRUE(provider->BindToCurrentThread());
+ GpuProcessHostUIShim* shim =
+ GpuProcessHostUIShim::FromID(GetFactory()->GpuProcessHostId());
+ EXPECT_TRUE(shim != NULL);
+ shim->SimulateCrash();
+ run_loop.Run();
+
+ EXPECT_EQ(1, counter);
+ EXPECT_FALSE(IsChannelEstablished());
+ EstablishAndWait();
+ EXPECT_TRUE(IsChannelEstablished());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_memory_test.cc b/chromium/content/browser/gpu/gpu_memory_test.cc
deleted file mode 100644
index 7f9a3fee167..00000000000
--- a/chromium/content/browser/gpu/gpu_memory_test.cc
+++ /dev/null
@@ -1,243 +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/callback.h"
-#include "base/command_line.h"
-#include "base/path_service.h"
-#include "content/public/browser/gpu_data_manager.h"
-#include "content/public/browser/gpu_data_manager_observer.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_paths.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
-#include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/config/gpu_test_config.h"
-#include "net/base/net_util.h"
-
-namespace content {
-
-// Run the tests with a memory limit of 256MB, and give
-// and extra 4MB of wiggle-room for over-allocation.
-const char* kMemoryLimitMBSwitch = "256";
-const size_t kMemoryLimitMB = 256;
-const size_t kSingleTabLimitMB = 128;
-const size_t kWiggleRoomMB = 4;
-
-// Observer to report GPU memory usage when requested.
-class GpuMemoryBytesAllocatedObserver : public GpuDataManagerObserver {
- public:
- GpuMemoryBytesAllocatedObserver()
- : bytes_allocated_(0) {
- }
-
- virtual ~GpuMemoryBytesAllocatedObserver() {
- }
-
- virtual void OnVideoMemoryUsageStatsUpdate(
- const GPUVideoMemoryUsageStats& video_memory_usage_stats) OVERRIDE {
- bytes_allocated_ = video_memory_usage_stats.bytes_allocated;
- message_loop_runner_->Quit();
- }
-
- size_t GetBytesAllocated() {
- message_loop_runner_ = new MessageLoopRunner;
- GpuDataManager::GetInstance()->AddObserver(this);
- GpuDataManager::GetInstance()->RequestVideoMemoryUsageStatsUpdate();
- message_loop_runner_->Run();
- GpuDataManager::GetInstance()->RemoveObserver(this);
- message_loop_runner_ = NULL;
- return bytes_allocated_;
- }
-
- private:
- size_t bytes_allocated_;
- scoped_refptr<MessageLoopRunner> message_loop_runner_;
-};
-
-class GpuMemoryTest : public ContentBrowserTest {
- public:
- GpuMemoryTest()
- : allow_tests_to_run_(false),
- has_used_first_shell_(false) {
- }
- virtual ~GpuMemoryTest() {
- }
-
- virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
- base::FilePath test_dir;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir));
- gpu_test_dir_ = test_dir.AppendASCII("gpu");
- }
-
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- command_line->AppendSwitch(switches::kEnableLogging);
- command_line->AppendSwitchASCII(switches::kForceGpuMemAvailableMb,
- kMemoryLimitMBSwitch);
- // Only run this on GPU bots for now. These tests should work with
- // any GPU process, but may be slow.
- if (command_line->HasSwitch(switches::kUseGpuInTests)) {
- allow_tests_to_run_ = true;
- }
- // Don't enable these tests on Android just yet (they use lots of memory and
- // may not be stable).
-#if defined(OS_ANDROID)
- allow_tests_to_run_ = false;
-#endif
- }
-
- enum PageType {
- PAGE_CSS3D,
- PAGE_WEBGL,
- };
-
- // Load a page and consume a specified amount of GPU memory.
- void LoadPage(Shell* tab_to_load,
- PageType page_type,
- size_t mb_to_use) {
- base::FilePath url;
- switch (page_type) {
- case PAGE_CSS3D:
- url = gpu_test_dir_.AppendASCII("mem_css3d.html");
- break;
- case PAGE_WEBGL:
- url = gpu_test_dir_.AppendASCII("mem_webgl.html");
- break;
- }
-
- NavigateToURL(tab_to_load, net::FilePathToFileURL(url));
- std::ostringstream js_call;
- js_call << "useGpuMemory(";
- js_call << mb_to_use;
- js_call << ");";
- std::string message;
- ASSERT_TRUE(ExecuteScriptInFrameAndExtractString(
- tab_to_load->web_contents(), std::string(), js_call.str(), &message));
- EXPECT_EQ("DONE_USE_GPU_MEMORY", message);
- }
-
- // Create a new tab.
- Shell* CreateNewTab() {
- // The ContentBrowserTest will create one shell by default, use that one
- // first so that we don't confuse the memory manager into thinking there
- // are more windows than there are.
- Shell* new_tab = has_used_first_shell_ ? CreateBrowser() : shell();
- has_used_first_shell_ = true;
- tabs_.insert(new_tab);
- visible_tabs_.insert(new_tab);
- return new_tab;
- }
-
- void SetTabBackgrounded(Shell* tab_to_background) {
- ASSERT_TRUE(
- visible_tabs_.find(tab_to_background) != visible_tabs_.end());
- visible_tabs_.erase(tab_to_background);
- tab_to_background->web_contents()->WasHidden();
- }
-
- bool MemoryUsageInRange(size_t low, size_t high) {
- FinishGpuMemoryChanges();
- size_t memory_usage_bytes = GetMemoryUsageMbytes();
-
- // If it's not immediately the case that low <= usage <= high, then
- // allow
- // Because we haven't implemented the full delay in FinishGpuMemoryChanges,
- // keep re-reading the GPU memory usage for 2 seconds before declaring
- // failure.
- base::Time start_time = base::Time::Now();
- while (low > memory_usage_bytes || memory_usage_bytes > high) {
- memory_usage_bytes = GetMemoryUsageMbytes();
- base::TimeDelta delta = base::Time::Now() - start_time;
- if (delta.InMilliseconds() >= 2000)
- break;
- }
-
- return (low <= memory_usage_bytes && memory_usage_bytes <= high);
- }
-
- bool AllowTestsToRun() const {
- return allow_tests_to_run_;
- }
-
- private:
- void FinishGpuMemoryChanges() {
- // This should wait until all effects of memory management complete.
- // We will need to wait until all
- // 1. pending commits from the main thread to the impl thread in the
- // compositor complete (for visible compositors).
- // 2. allocations that the renderer's impl thread will make due to the
- // compositor and WebGL are completed.
- // 3. pending GpuMemoryManager::Manage() calls to manage are made.
- // 4. renderers' OnMemoryAllocationChanged callbacks in response to
- // manager are made.
- // Each step in this sequence can cause trigger the next (as a 1-2-3-4-1
- // cycle), so we will need to pump this cycle until it stabilizes.
-
- // Pump the cycle 8 times (in principle it could take an infinite number
- // of iterations to settle).
- for (size_t pump_it = 0; pump_it < 8; ++pump_it) {
- // Wait for a RequestAnimationFrame to complete from all visible tabs
- // for stage 1 of the cycle.
- for (std::set<Shell*>::iterator it = visible_tabs_.begin();
- it != visible_tabs_.end();
- ++it) {
- std::string js_call(
- "window.webkitRequestAnimationFrame(function() {"
- " domAutomationController.setAutomationId(1);"
- " domAutomationController.send(\"DONE_RAF\");"
- "})");
- std::string message;
- ASSERT_TRUE(ExecuteScriptInFrameAndExtractString(
- (*it)->web_contents(), std::string(), js_call, &message));
- EXPECT_EQ("DONE_RAF", message);
- }
- // TODO(ccameron): send an IPC from Browser -> Renderer (delay it until
- // painting finishes) -> GPU process (delay it until any pending manages
- // happen) -> All Renderers -> Browser to flush parts 2, 3, and 4.
- }
- }
-
- size_t GetMemoryUsageMbytes() {
- GpuMemoryBytesAllocatedObserver observer;
- observer.GetBytesAllocated();
- return observer.GetBytesAllocated() / 1048576;
- }
-
- bool allow_tests_to_run_;
- std::set<Shell*> tabs_;
- std::set<Shell*> visible_tabs_;
- bool has_used_first_shell_;
- base::FilePath gpu_test_dir_;
-};
-
-#if defined(OS_LINUX) && !defined(NDEBUG)
-// http://crbug.com/254724
-#define MAYBE(x) DISABLED_ ## x
-#elif defined(OS_WIN) && defined(USE_AURA)
-// http://crbug.com/292882
-#define MAYBE(x) DISABLED_ ## x
-#else
-#define MAYBE(x) x
-#endif
-
-// When trying to load something that doesn't fit into our total GPU memory
-// limit, we shouldn't exceed that limit.
-IN_PROC_BROWSER_TEST_F(GpuMemoryTest,
- MAYBE(SingleWindowDoesNotExceedLimit)) {
- if (!AllowTestsToRun())
- return;
-
- Shell* tab = CreateNewTab();
- LoadPage(tab, PAGE_CSS3D, kMemoryLimitMB);
- // Make sure that the CSS3D page maxes out a single tab's budget (otherwise
- // the test doesn't test anything) but still stays under the limit.
- EXPECT_TRUE(MemoryUsageInRange(
- kSingleTabLimitMB - kWiggleRoomMB,
- kMemoryLimitMB + kWiggleRoomMB));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_pixel_browsertest.cc b/chromium/content/browser/gpu/gpu_pixel_browsertest.cc
deleted file mode 100644
index d6b55e2c7ee..00000000000
--- a/chromium/content/browser/gpu/gpu_pixel_browsertest.cc
+++ /dev/null
@@ -1,568 +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 "base/command_line.h"
-#include "base/file_util.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_paths.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
-#include "gpu/config/gpu_test_config.h"
-#include "net/base/net_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/codec/png_codec.h"
-#include "ui/gfx/size.h"
-#include "ui/gl/gl_switches.h"
-#include "ui/snapshot/snapshot.h"
-
-namespace {
-
-enum ReferenceImageOption {
- kReferenceImageLocal,
- kReferenceImageCheckedIn,
- kReferenceImageNone // Only check a few key pixels.
-};
-
-struct ReferencePixel {
- int x, y;
- unsigned char r, g, b;
-};
-
-// Command line flag for overriding the default location for putting generated
-// test images that do not match references.
-const char kGeneratedDir[] = "generated-dir";
-// Command line flag for overriding the default location for reference images.
-const char kReferenceDir[] = "reference-dir";
-// Command line flag for Chromium build revision.
-const char kBuildRevision[] = "build-revision";
-
-// Reads and decodes a PNG image to a bitmap. Returns true on success. The PNG
-// should have been encoded using |gfx::PNGCodec::Encode|.
-bool ReadPNGFile(const base::FilePath& file_path, SkBitmap* bitmap) {
- DCHECK(bitmap);
- base::FilePath abs_path(base::MakeAbsoluteFilePath(file_path));
- if (abs_path.empty())
- return false;
-
- std::string png_data;
- return base::ReadFileToString(abs_path, &png_data) &&
- gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&png_data[0]),
- png_data.length(),
- bitmap);
-}
-
-// Encodes a bitmap into a PNG and write to disk. Returns true on success. The
-// parent directory does not have to exist.
-bool WritePNGFile(const SkBitmap& bitmap, const base::FilePath& file_path) {
- std::vector<unsigned char> png_data;
- if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &png_data) &&
- file_util::CreateDirectory(file_path.DirName())) {
- int bytes_written = file_util::WriteFile(
- file_path, reinterpret_cast<char*>(&png_data[0]), png_data.size());
- if (bytes_written == static_cast<int>(png_data.size()))
- return true;
- }
- return false;
-}
-
-// Write an empty file, whose name indicates the chrome revision when the ref
-// image was generated.
-bool WriteREVFile(const base::FilePath& file_path) {
- if (file_util::CreateDirectory(file_path.DirName())) {
- char one_byte = 0;
- int bytes_written = file_util::WriteFile(file_path, &one_byte, 1);
- if (bytes_written == 1)
- return true;
- }
- return false;
-}
-
-} // namespace anonymous
-
-namespace content {
-
-// Test fixture for GPU image comparison tests.
-// TODO(kkania): Document how to add to/modify these tests.
-class GpuPixelBrowserTest : public ContentBrowserTest {
- public:
- GpuPixelBrowserTest()
- : ref_img_revision_(0),
- ref_img_revision_no_older_than_(0),
- ref_img_option_(kReferenceImageNone) {
- }
-
- virtual void SetUp() {
- // We expect real pixel output for these tests.
- UseRealGLContexts();
-
- ContentBrowserTest::SetUp();
- }
-
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- command_line->AppendSwitchASCII(switches::kTestGLLib,
- "libllvmpipe.so");
- }
-
- virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
- ContentBrowserTest::SetUpInProcessBrowserTestFixture();
-
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kUseGpuInTests))
- ref_img_option_ = kReferenceImageLocal;
-
- if (command_line->HasSwitch(kBuildRevision))
- build_revision_ = command_line->GetSwitchValueASCII(kBuildRevision);
-
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_data_dir_));
- test_data_dir_ = test_data_dir_.AppendASCII("gpu");
-
- if (command_line->HasSwitch(kGeneratedDir))
- generated_img_dir_ = command_line->GetSwitchValuePath(kGeneratedDir);
- else
- generated_img_dir_ = test_data_dir_.AppendASCII("generated");
-
- switch (ref_img_option_) {
- case kReferenceImageLocal:
- if (command_line->HasSwitch(kReferenceDir))
- ref_img_dir_ = command_line->GetSwitchValuePath(kReferenceDir);
- else
- ref_img_dir_ = test_data_dir_.AppendASCII("gpu_reference");
- break;
- case kReferenceImageCheckedIn:
- ref_img_dir_ = test_data_dir_.AppendASCII("llvmpipe_reference");
- break;
- default:
- break;
- }
-
- test_name_ = testing::UnitTest::GetInstance()->current_test_info()->name();
- const char* test_status_prefixes[] = {
- "DISABLED_", "FLAKY_", "FAILS_", "MANUAL_"};
- for (size_t i = 0; i < arraysize(test_status_prefixes); ++i) {
- ReplaceFirstSubstringAfterOffset(
- &test_name_, 0, test_status_prefixes[i], std::string());
- }
- }
-
- // If the existing ref image was saved from an revision older than the
- // ref_img_update_revision, refresh the ref image.
- void RunPixelTest(const gfx::Size& tab_container_size,
- const base::FilePath& url,
- int64 ref_img_update_revision,
- const ReferencePixel* ref_pixels,
- size_t ref_pixel_count) {
- if (ref_img_option_ == kReferenceImageLocal) {
- ref_img_revision_no_older_than_ = ref_img_update_revision;
- ObtainLocalRefImageRevision();
- }
-
- DOMMessageQueue message_queue;
- NavigateToURL(shell(), net::FilePathToFileURL(url));
-
- std::string message;
- // Wait for notification that page is loaded.
- ASSERT_TRUE(message_queue.WaitForMessage(&message));
- EXPECT_STREQ("\"SUCCESS\"", message.c_str()) << message;
-
- SkBitmap bitmap;
- ASSERT_TRUE(TabSnapShotToImage(&bitmap, tab_container_size));
- bool same_pixels = true;
- if (ref_img_option_ == kReferenceImageNone && ref_pixels && ref_pixel_count)
- same_pixels = ComparePixels(bitmap, ref_pixels, ref_pixel_count);
- else
- same_pixels = CompareImages(bitmap);
- EXPECT_TRUE(same_pixels);
- }
-
- const base::FilePath& test_data_dir() const {
- return test_data_dir_;
- }
-
- private:
- base::FilePath test_data_dir_;
- base::FilePath generated_img_dir_;
- base::FilePath ref_img_dir_;
- int64 ref_img_revision_;
- std::string build_revision_;
- // The name of the test, with any special prefixes dropped.
- std::string test_name_;
-
- // Any local ref image generated from older revision is ignored.
- int64 ref_img_revision_no_older_than_;
-
- // Whether use locally generated ref images, or checked in ref images, or
- // simply check a few key pixels.
- ReferenceImageOption ref_img_option_;
-
- // Compares the generated bitmap with the appropriate reference image on disk.
- // Returns true iff the images were the same.
- //
- // If no valid reference image exists, save the generated bitmap to the disk.
- // The image format is:
- // <test_name>_<revision>.png
- // E.g.,
- // WebGLTeapot_19762.png
- // The number is the chromium revision that generated the image.
- //
- // On failure or on ref image generation, the image and diff image will be
- // written to disk. The formats are:
- // FAIL_<ref_image_name>, DIFF_<ref_image_name>
- // E.g.,
- // FAIL_WebGLTeapot_19762.png, DIFF_WebGLTeapot_19762.png
- bool CompareImages(const SkBitmap& gen_bmp) {
- SkBitmap ref_bmp_on_disk;
-
- base::FilePath img_path = ref_img_dir_.AppendASCII(test_name_ + ".png");
- bool found_ref_img = ReadPNGFile(img_path, &ref_bmp_on_disk);
-
- if (!found_ref_img && ref_img_option_ == kReferenceImageCheckedIn) {
- LOG(ERROR) << "Couldn't find reference image: "
- << img_path.value();
- // No image to compare to, exit early.
- return false;
- }
-
- const SkBitmap* ref_bmp;
- bool save_gen = false;
- bool save_diff = true;
- bool rt = true;
-
- if ((ref_img_revision_ <= 0 && ref_img_option_ == kReferenceImageLocal) ||
- !found_ref_img) {
- base::FilePath rev_path = ref_img_dir_.AppendASCII(
- test_name_ + "_" + build_revision_ + ".rev");
- if (!WritePNGFile(gen_bmp, img_path)) {
- LOG(ERROR) << "Can't save generated image to: "
- << img_path.value()
- << " as future reference.";
- rt = false;
- } else {
- LOG(INFO) << "Saved reference image to: "
- << img_path.value();
- }
- if (rt) {
- if (!WriteREVFile(rev_path)) {
- LOG(ERROR) << "Can't save revision file to: "
- << rev_path.value();
- rt = false;
- base::DeleteFile(img_path, false);
- } else {
- LOG(INFO) << "Saved revision file to: "
- << rev_path.value();
- }
- }
- if (ref_img_revision_ > 0) {
- LOG(ERROR) << "Can't read the local ref image: "
- << img_path.value()
- << ", reset it.";
- rt = false;
- }
- // If we re-generate the ref image, we save the gen and diff images so
- // the ref image can be uploaded to the server and be viewed later.
- save_gen = true;
- save_diff = true;
- ref_bmp = &gen_bmp;
- } else {
- ref_bmp = &ref_bmp_on_disk;
- }
-
- SkBitmap diff_bmp;
- if (ref_bmp->width() != gen_bmp.width() ||
- ref_bmp->height() != gen_bmp.height()) {
- LOG(ERROR)
- << "Dimensions do not match (Expected) vs (Actual):"
- << "(" << ref_bmp->width() << "x" << ref_bmp->height()
- << ") vs. "
- << "(" << gen_bmp.width() << "x" << gen_bmp.height() << ")";
- if (ref_img_option_ == kReferenceImageLocal)
- save_gen = true;
- rt = false;
- } else {
- // Compare pixels and create a simple diff image.
- int diff_pixels_count = 0;
- diff_bmp.setConfig(SkBitmap::kARGB_8888_Config,
- gen_bmp.width(), gen_bmp.height());
- diff_bmp.allocPixels();
- diff_bmp.eraseColor(SK_ColorWHITE);
- SkAutoLockPixels lock_bmp(gen_bmp);
- SkAutoLockPixels lock_ref_bmp(*ref_bmp);
- SkAutoLockPixels lock_diff_bmp(diff_bmp);
- // The reference images were saved with no alpha channel. Use the mask to
- // set alpha to 0.
- uint32_t kAlphaMask = 0x00FFFFFF;
- for (int x = 0; x < gen_bmp.width(); ++x) {
- for (int y = 0; y < gen_bmp.height(); ++y) {
- if ((*gen_bmp.getAddr32(x, y) & kAlphaMask) !=
- (*ref_bmp->getAddr32(x, y) & kAlphaMask)) {
- ++diff_pixels_count;
- *diff_bmp.getAddr32(x, y) = 192 << 16; // red
- }
- }
- }
- if (diff_pixels_count > 0) {
- LOG(ERROR) << diff_pixels_count
- << " pixels do not match.";
- if (ref_img_option_ == kReferenceImageLocal) {
- save_gen = true;
- save_diff = true;
- }
- rt = false;
- }
- }
-
- std::string ref_img_filename = img_path.BaseName().MaybeAsASCII();
- if (save_gen) {
- base::FilePath img_fail_path = generated_img_dir_.AppendASCII(
- "FAIL_" + ref_img_filename);
- if (!WritePNGFile(gen_bmp, img_fail_path)) {
- LOG(ERROR) << "Can't save generated image to: "
- << img_fail_path.value();
- } else {
- LOG(INFO) << "Saved generated image to: "
- << img_fail_path.value();
- }
- }
- if (save_diff) {
- base::FilePath img_diff_path = generated_img_dir_.AppendASCII(
- "DIFF_" + ref_img_filename);
- if (!WritePNGFile(diff_bmp, img_diff_path)) {
- LOG(ERROR) << "Can't save generated diff image to: "
- << img_diff_path.value();
- } else {
- LOG(INFO) << "Saved difference image to: "
- << img_diff_path.value();
- }
- }
- return rt;
- }
-
- bool ComparePixels(const SkBitmap& gen_bmp,
- const ReferencePixel* ref_pixels,
- size_t ref_pixel_count) {
- SkAutoLockPixels lock_bmp(gen_bmp);
-
- for (size_t i = 0; i < ref_pixel_count; ++i) {
- int x = ref_pixels[i].x;
- int y = ref_pixels[i].y;
- unsigned char r = ref_pixels[i].r;
- unsigned char g = ref_pixels[i].g;
- unsigned char b = ref_pixels[i].b;
-
- DCHECK(x >= 0 && x < gen_bmp.width() && y >= 0 && y < gen_bmp.height());
-
- unsigned char* rgba = reinterpret_cast<unsigned char*>(
- gen_bmp.getAddr32(x, y));
- DCHECK(rgba);
- if (rgba[0] != b || rgba[1] != g || rgba[2] != r) {
- std::string error_message = base::StringPrintf(
- "pixel(%d,%d) expects [%u,%u,%u], but gets [%u,%u,%u] instead",
- x, y, r, g, b, rgba[0], rgba[1], rgba[2]);
- LOG(ERROR) << error_message.c_str();
- return false;
- }
- }
- return true;
- }
-
- // Take snapshot of the tab, encode it as PNG, and save to a SkBitmap.
- bool TabSnapShotToImage(SkBitmap* bitmap, const gfx::Size& size) {
- CHECK(bitmap);
- std::vector<unsigned char> png;
-
- gfx::Rect snapshot_bounds(size);
- RenderViewHost* view_host = shell()->web_contents()->GetRenderViewHost();
- if (!ui::GrabViewSnapshot(view_host->GetView()->GetNativeView(),
- &png, snapshot_bounds)) {
- LOG(ERROR) << "ui::GrabViewSnapShot() failed";
- return false;
- }
-
- if (!gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&*png.begin()),
- png.size(), bitmap)) {
- LOG(ERROR) << "Decode PNG to a SkBitmap failed";
- return false;
- }
- return true;
- }
-
- // If no valid local revision file is located, the ref_img_revision_ is 0.
- void ObtainLocalRefImageRevision() {
- base::FilePath filter;
- filter = filter.AppendASCII(test_name_ + "_*.rev");
- base::FileEnumerator locator(ref_img_dir_,
- false, // non recursive
- base::FileEnumerator::FILES,
- filter.value());
- int64 max_revision = 0;
- std::vector<base::FilePath> outdated_revs;
- for (base::FilePath full_path = locator.Next();
- !full_path.empty();
- full_path = locator.Next()) {
- std::string filename =
- full_path.BaseName().RemoveExtension().MaybeAsASCII();
- std::string revision_string =
- filename.substr(test_name_.length() + 1);
- int64 revision = 0;
- bool converted = base::StringToInt64(revision_string, &revision);
- if (!converted)
- continue;
- if (revision < ref_img_revision_no_older_than_ ||
- revision < max_revision) {
- outdated_revs.push_back(full_path);
- continue;
- }
- max_revision = revision;
- }
- ref_img_revision_ = max_revision;
- for (size_t i = 0; i < outdated_revs.size(); ++i)
- base::DeleteFile(outdated_revs[i], false);
- }
-
- DISALLOW_COPY_AND_ASSIGN(GpuPixelBrowserTest);
-};
-
-IN_PROC_BROWSER_TEST_F(GpuPixelBrowserTest, MANUAL_WebGLGreenTriangle) {
- // If test baseline needs to be updated after a given revision, update the
- // following number. If no revision requirement, then 0.
- const int64 ref_img_revision_update = 123489;
-
- const ReferencePixel ref_pixels[] = {
- // x, y, r, g, b
- {50, 100, 0, 0, 0},
- {100, 100, 0, 255, 0},
- {150, 100, 0, 0, 0},
- {50, 150, 0, 255, 0},
- {100, 150, 0, 255, 0},
- {150, 150, 0, 255, 0}
- };
- const size_t ref_pixel_count = sizeof(ref_pixels) / sizeof(ReferencePixel);
-
- gfx::Size container_size(400, 300);
- base::FilePath url =
- test_data_dir().AppendASCII("pixel_webgl.html");
- RunPixelTest(container_size, url, ref_img_revision_update,
- ref_pixels, ref_pixel_count);
-}
-
-IN_PROC_BROWSER_TEST_F(GpuPixelBrowserTest, MANUAL_CSS3DBlueBox) {
- // If test baseline needs to be updated after a given revision, update the
- // following number. If no revision requirement, then 0.
- const int64 ref_img_revision_update = 223891;
-
- const ReferencePixel ref_pixels[] = {
- // x, y, r, g, b
- {70, 50, 0, 0, 255},
- {150, 50, 0, 0, 0},
- {70, 90, 0, 0, 255},
- {150, 90, 0, 0, 255},
- {70, 125, 0, 0, 255},
- {150, 125, 0, 0, 0}
- };
- const size_t ref_pixel_count = sizeof(ref_pixels) / sizeof(ReferencePixel);
-
- gfx::Size container_size(400, 300);
- base::FilePath url =
- test_data_dir().AppendASCII("pixel_css3d.html");
- RunPixelTest(container_size, url, ref_img_revision_update,
- ref_pixels, ref_pixel_count);
-}
-
-IN_PROC_BROWSER_TEST_F(GpuPixelBrowserTest, MANUAL_Canvas2DRedBoxHD) {
- // If test baseline needs to be updated after a given revision, update the
- // following number. If no revision requirement, then 0.
- const int64 ref_img_revision_update = 224170;
-
- const ReferencePixel ref_pixels[] = {
- // x, y, r, g, b
- {40, 100, 0, 0, 0},
- {60, 100, 127, 0, 0},
- {140, 100, 127, 0, 0},
- {160, 100, 0, 0, 0}
- };
- const size_t ref_pixel_count = sizeof(ref_pixels) / sizeof(ReferencePixel);
-
- gfx::Size container_size(400, 300);
- base::FilePath url =
- test_data_dir().AppendASCII("pixel_canvas2d.html");
- RunPixelTest(container_size, url, ref_img_revision_update,
- ref_pixels, ref_pixel_count);
-}
-
-class GpuPixelTestCanvas2DSD : public GpuPixelBrowserTest {
- public:
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- GpuPixelBrowserTest::SetUpCommandLine(command_line);
- command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
- }
-};
-
-IN_PROC_BROWSER_TEST_F(GpuPixelTestCanvas2DSD, MANUAL_Canvas2DRedBoxSD) {
- // If test baseline needs to be updated after a given revision, update the
- // following number. If no revision requirement, then 0.
- const int64 ref_img_revision_update = 224170;
-
- const ReferencePixel ref_pixels[] = {
- // x, y, r, g, b
- {40, 100, 0, 0, 0},
- {60, 100, 127, 0, 0},
- {140, 100, 127, 0, 0},
- {160, 100, 0, 0, 0}
- };
- const size_t ref_pixel_count = sizeof(ref_pixels) / sizeof(ReferencePixel);
-
- gfx::Size container_size(400, 300);
- base::FilePath url =
- test_data_dir().AppendASCII("pixel_canvas2d.html");
- RunPixelTest(container_size, url, ref_img_revision_update,
- ref_pixels, ref_pixel_count);
-}
-
-class GpuPixelTestBrowserPlugin : public GpuPixelBrowserTest {
- public:
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- GpuPixelBrowserTest::SetUpCommandLine(command_line);
- command_line->AppendSwitch(switches::kEnableBrowserPluginForAllViewTypes);
- }
-};
-
-// TODO(fsamuel): re-enable as MANUAL_BrowserPluginBlueBox: crbug.com/166165
-IN_PROC_BROWSER_TEST_F(GpuPixelTestBrowserPlugin,
- DISABLED_BrowserPluginBlueBox) {
- // If test baseline needs to be updated after a given revision, update the
- // following number. If no revision requirement, then 0.
- const int64 ref_img_revision_update = 209445;
-
- const ReferencePixel ref_pixels[] = {
- // x, y, r, g, b
- {70, 50, 0, 0, 255},
- {150, 50, 0, 0, 0},
- {70, 90, 0, 0, 255},
- {150, 90, 0, 0, 255},
- {70, 125, 0, 0, 255},
- {150, 125, 0, 0, 0}
- };
- const size_t ref_pixel_count = sizeof(ref_pixels) / sizeof(ReferencePixel);
-
- gfx::Size container_size(400, 300);
- base::FilePath url =
- test_data_dir().AppendASCII("pixel_browser_plugin.html");
- RunPixelTest(container_size, url, ref_img_revision_update,
- ref_pixels, ref_pixel_count);
-}
-
-} // namespace content
-
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index 0482b347e85..1b7da1c8d7c 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -48,6 +48,10 @@
#include "ui/surface/accelerated_surface_win.h"
#endif
+#if defined(USE_OZONE)
+#include "ui/ozone/ozone_switches.h"
+#endif
+
namespace content {
bool GpuProcessHost::gpu_enabled_ = true;
@@ -200,22 +204,8 @@ class GpuSandboxedProcessLauncherDelegate
SetJobLevel(*cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy);
policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
} else {
- if (cmd_line_->GetSwitchValueASCII(switches::kUseGL) ==
- gfx::kGLImplementationSwiftShaderName ||
- cmd_line_->HasSwitch(switches::kReduceGpuSandbox) ||
- cmd_line_->HasSwitch(switches::kDisableImageTransportSurface)) {
- // Swiftshader path.
- policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
- sandbox::USER_LIMITED);
- } else {
- // Angle + DirectX path.
- policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
- sandbox::USER_RESTRICTED);
- // This is a trick to keep the GPU out of low-integrity processes. It
- // starts at low-integrity for UIPI to work, then drops below
- // low-integrity after warm-up.
- policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
- }
+ policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
+ sandbox::USER_LIMITED);
// UI restrictions break when we access Windows from outside our job.
// However, we don't want a proxy window in this process because it can
@@ -266,7 +256,7 @@ class GpuSandboxedProcessLauncherDelegate
#endif
if (cmd_line_->HasSwitch(switches::kEnableLogging)) {
- string16 log_file_path = logging::GetLogFileFullPath();
+ base::string16 log_file_path = logging::GetLogFileFullPath();
if (!log_file_path.empty()) {
result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
@@ -442,6 +432,9 @@ GpuProcessHost::~GpuProcessHost() {
static bool crashed_before = false;
static int swiftshader_crash_count = 0;
+ bool disable_crash_limit = CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGpuProcessCrashLimit);
+
// Ending only acts as a failure if the GPU process was actually started and
// was intended for actual rendering (and not just checking caps or other
// options).
@@ -451,7 +444,8 @@ GpuProcessHost::~GpuProcessHost() {
DIED_FIRST_TIME + swiftshader_crash_count,
GPU_PROCESS_LIFETIME_EVENT_MAX);
- if (++swiftshader_crash_count >= kGpuMaxCrashCount) {
+ if (++swiftshader_crash_count >= kGpuMaxCrashCount &&
+ !disable_crash_limit) {
// SwiftShader is too unstable to use. Disable it for current session.
gpu_enabled_ = false;
}
@@ -476,8 +470,8 @@ GpuProcessHost::~GpuProcessHost() {
crashed_before = true;
last_gpu_crash_time = current_time;
- if (gpu_recent_crash_count >= kGpuMaxCrashCount ||
- !initialized_) {
+ if ((gpu_recent_crash_count >= kGpuMaxCrashCount && !disable_crash_limit)
+ || !initialized_) {
#if !defined(OS_CHROMEOS)
// The gpu process is too unstable to use. Disable it for current
// session.
@@ -577,7 +571,8 @@ bool GpuProcessHost::Init() {
if (channel_id.empty())
return false;
- if (in_process_ && g_gpu_main_thread_factory) {
+ if (in_process_) {
+ DCHECK(g_gpu_main_thread_factory);
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kDisableGpuWatchdog);
@@ -1121,6 +1116,9 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
switches::kDisableImageTransportSurface,
switches::kDisableLogging,
switches::kDisableSeccompFilterSandbox,
+#if defined(ENABLE_WEBRTC)
+ switches::kDisableWebRtcHWEncoding,
+#endif
switches::kEnableLogging,
switches::kEnableShareGroupAsyncTextureUpload,
switches::kGpuStartupDialog,
@@ -1138,6 +1136,9 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
#if defined(USE_AURA)
switches::kUIPrioritizeInGpuProcess,
#endif
+#if defined(USE_OZONE)
+ switches::kOzonePlatform,
+#endif
};
cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
arraysize(kSwitchNames));
diff --git a/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc b/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc
index 50810427388..b17bc59faae 100644
--- a/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc
+++ b/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc
@@ -22,14 +22,6 @@
#include "content/public/browser/browser_thread.h"
#include "ui/gl/gl_switches.h"
-#if defined(TOOLKIT_GTK)
-// These two #includes need to come after gpu_messages.h.
-#include "ui/base/x/x11_util.h"
-#include "ui/gfx/size.h"
-#include <gdk/gdk.h> // NOLINT
-#include <gdk/gdkx.h> // NOLINT
-#endif
-
// From gl2/gl2ext.h.
#ifndef GL_MAILBOX_SIZE_CHROMIUM
#define GL_MAILBOX_SIZE_CHROMIUM 64
@@ -191,6 +183,8 @@ bool GpuProcessHostUIShim::OnControlMessageReceived(
IPC_MESSAGE_HANDLER(GpuHostMsg_OnLogMessage,
OnLogMessage)
+ IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceInitialized,
+ OnAcceleratedSurfaceInitialized)
IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
OnAcceleratedSurfaceBuffersSwapped)
IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfacePostSubBuffer,
@@ -207,9 +201,7 @@ bool GpuProcessHostUIShim::OnControlMessageReceived(
OnUpdateVSyncParameters)
IPC_MESSAGE_HANDLER(GpuHostMsg_FrameDrawn, OnFrameDrawn)
-#if defined(TOOLKIT_GTK) || defined(OS_WIN)
IPC_MESSAGE_HANDLER(GpuHostMsg_ResizeView, OnResizeView)
-#endif
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
@@ -251,8 +243,6 @@ void GpuProcessHostUIShim::OnGraphicsInfoCollected(
GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info);
}
-#if defined(TOOLKIT_GTK) || defined(OS_WIN)
-
void GpuProcessHostUIShim::OnResizeView(int32 surface_id,
int32 route_id,
gfx::Size size) {
@@ -268,34 +258,9 @@ void GpuProcessHostUIShim::OnResizeView(int32 surface_id,
if (!view)
return;
- gfx::GLSurfaceHandle surface = view->GetCompositingSurface();
-
- // Resize the window synchronously. The GPU process must not issue GL
- // calls on the command buffer until the window is the size it expects it
- // to be.
-#if defined(TOOLKIT_GTK)
- GdkWindow* window = reinterpret_cast<GdkWindow*>(
- gdk_xid_table_lookup(surface.handle));
- if (window) {
- Display* display = GDK_WINDOW_XDISPLAY(window);
- gdk_window_resize(window, size.width(), size.height());
- XSync(display, False);
- }
-#elif defined(OS_WIN)
- // Ensure window does not have zero area because D3D cannot create a zero
- // area swap chain.
- SetWindowPos(surface.handle,
- NULL,
- 0, 0,
- std::max(1, size.width()),
- std::max(1, size.height()),
- SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER |
- SWP_NOACTIVATE | SWP_DEFERERASE | SWP_NOMOVE);
-#endif
+ view->ResizeCompositingSurface(size);
}
-#endif
-
static base::TimeDelta GetSwapDelay() {
CommandLine* cmd_line = CommandLine::ForCurrentProcess();
int delay = 0;
@@ -306,6 +271,15 @@ static base::TimeDelta GetSwapDelay() {
return base::TimeDelta::FromMilliseconds(delay);
}
+void GpuProcessHostUIShim::OnAcceleratedSurfaceInitialized(int32 surface_id,
+ int32 route_id) {
+ RenderWidgetHostViewPort* view =
+ GetRenderWidgetHostViewFromSurfaceID(surface_id);
+ if (!view)
+ return;
+ view->AcceleratedSurfaceInitialized(host_id_, route_id);
+}
+
void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) {
TRACE_EVENT0("renderer",
diff --git a/chromium/content/browser/gpu/gpu_process_host_ui_shim.h b/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
index 9f4329a10a5..bd7da0a37c3 100644
--- a/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
+++ b/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
@@ -87,14 +87,13 @@ class GpuProcessHostUIShim : public IPC::Listener,
void OnLogMessage(int level, const std::string& header,
const std::string& message);
-#if defined(TOOLKIT_GTK) || defined(OS_WIN)
void OnResizeView(int32 surface_id,
int32 route_id,
gfx::Size size);
-#endif
void OnGraphicsInfoCollected(const gpu::GPUInfo& gpu_info);
+ void OnAcceleratedSurfaceInitialized(int32 surface_id, int32 route_id);
void OnAcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params);
void OnAcceleratedSurfacePostSubBuffer(
diff --git a/chromium/content/browser/gpu/webgl_conformance_test.cc b/chromium/content/browser/gpu/webgl_conformance_test.cc
deleted file mode 100644
index e8fb8a59b92..00000000000
--- a/chromium/content/browser/gpu/webgl_conformance_test.cc
+++ /dev/null
@@ -1,96 +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/command_line.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_paths.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
-#include "gpu/config/gpu_test_config.h"
-#include "gpu/config/gpu_test_expectations_parser.h"
-#include "net/base/net_util.h"
-
-namespace content {
-
-class WebGLConformanceTest : public ContentBrowserTest {
- public:
- WebGLConformanceTest() {}
-
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- // Allow privileged WebGL extensions.
- command_line->AppendSwitch(switches::kEnablePrivilegedWebGLExtensions);
-#if defined(OS_ANDROID)
- command_line->AppendSwitch(
- switches::kDisableGestureRequirementForMediaPlayback);
-#endif
- }
-
- virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
- base::FilePath webgl_conformance_path;
- PathService::Get(base::DIR_SOURCE_ROOT, &webgl_conformance_path);
- webgl_conformance_path = webgl_conformance_path.Append(
- FILE_PATH_LITERAL("third_party"));
- webgl_conformance_path = webgl_conformance_path.Append(
- FILE_PATH_LITERAL("webgl_conformance"));
- ASSERT_TRUE(base::DirectoryExists(webgl_conformance_path))
- << "Missing conformance tests: " << webgl_conformance_path.value();
-
- PathService::Get(DIR_TEST_DATA, &test_path_);
- test_path_ = test_path_.Append(FILE_PATH_LITERAL("gpu"));
- test_path_ = test_path_.Append(FILE_PATH_LITERAL("webgl_conformance.html"));
-
- ASSERT_TRUE(bot_config_.LoadCurrentConfig(NULL))
- << "Fail to load bot configuration";
- ASSERT_TRUE(bot_config_.IsValid())
- << "Invalid bot configuration";
-
- base::FilePath path;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &path));
- path = path.Append(FILE_PATH_LITERAL("gpu"))
- .Append(FILE_PATH_LITERAL("webgl_conformance_test_expectations.txt"));
- ASSERT_TRUE(base::PathExists(path));
- ASSERT_TRUE(test_expectations_.LoadTestExpectations(path));
- }
-
- void RunTest(std::string url, std::string test_name) {
- int32 expectation =
- test_expectations_.GetTestExpectation(test_name, bot_config_);
- if (expectation != gpu::GPUTestExpectationsParser::kGpuTestPass) {
- LOG(WARNING) << "Test " << test_name << " is bypassed";
- return;
- }
-
- DOMMessageQueue message_queue;
- NavigateToURL(shell(), net::FilePathToFileURL(test_path_));
-
- std::string message;
- NavigateToURL(shell(), GURL("javascript:start('" + url + "');"));
- ASSERT_TRUE(message_queue.WaitForMessage(&message));
-
- EXPECT_STREQ("\"SUCCESS\"", message.c_str()) << message;
- }
-
- private:
- base::FilePath test_path_;
- gpu::GPUTestBotConfig bot_config_;
- gpu::GPUTestExpectationsParser test_expectations_;
-};
-
-#define CONFORMANCE_TEST(name, url) \
-IN_PROC_BROWSER_TEST_F(WebGLConformanceTest, MANUAL_##name) { \
- RunTest(url, #name); \
-}
-
-// The test declarations are located in webgl_conformance_test_list_autogen.h,
-// because the list is automatically generated by a script.
-// See: generate_webgl_conformance_test_list.py
-#include "webgl_conformance_test_list_autogen.h"
-
-} // namespace content
diff --git a/chromium/content/browser/gpu/webgl_conformance_test_list_autogen.h b/chromium/content/browser/gpu/webgl_conformance_test_list_autogen.h
deleted file mode 100644
index d9a30c243c2..00000000000
--- a/chromium/content/browser/gpu/webgl_conformance_test_list_autogen.h
+++ /dev/null
@@ -1,1080 +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.
-
-// DO NOT EDIT! This file is auto-generated by
-// generate_webgl_conformance_test_list.py
-// It is included by webgl_conformance_test.cc
-
-#ifndef CONTENT_TEST_GPU_WEBGL_CONFORMANCE_TEST_LIST_AUTOGEN_H_
-#define CONTENT_TEST_GPU_WEBGL_CONFORMANCE_TEST_LIST_AUTOGEN_H_
-
-CONFORMANCE_TEST(conformance_more_conformance_constants,
- "conformance/more/conformance/constants.html");
-CONFORMANCE_TEST(conformance_more_conformance_getContext,
- "conformance/more/conformance/getContext.html");
-CONFORMANCE_TEST(conformance_more_conformance_methods,
- "conformance/more/conformance/methods.html");
-CONFORMANCE_TEST(conformance_more_conformance_quickCheckAPI_A,
- "conformance/more/conformance/quickCheckAPI-A.html");
-CONFORMANCE_TEST(conformance_more_conformance_quickCheckAPI_B1,
- "conformance/more/conformance/quickCheckAPI-B1.html");
-CONFORMANCE_TEST(conformance_more_conformance_quickCheckAPI_B2,
- "conformance/more/conformance/quickCheckAPI-B2.html");
-CONFORMANCE_TEST(conformance_more_conformance_quickCheckAPI_B3,
- "conformance/more/conformance/quickCheckAPI-B3.html");
-CONFORMANCE_TEST(conformance_more_conformance_quickCheckAPI_B4,
- "conformance/more/conformance/quickCheckAPI-B4.html");
-CONFORMANCE_TEST(conformance_more_conformance_quickCheckAPI_C,
- "conformance/more/conformance/quickCheckAPI-C.html");
-CONFORMANCE_TEST(conformance_more_conformance_quickCheckAPI_D_G,
- "conformance/more/conformance/quickCheckAPI-D_G.html");
-CONFORMANCE_TEST(conformance_more_conformance_quickCheckAPI_G_I,
- "conformance/more/conformance/quickCheckAPI-G_I.html");
-CONFORMANCE_TEST(conformance_more_conformance_quickCheckAPI_L_S,
- "conformance/more/conformance/quickCheckAPI-L_S.html");
-CONFORMANCE_TEST(conformance_more_conformance_quickCheckAPI_S_V,
- "conformance/more/conformance/quickCheckAPI-S_V.html");
-CONFORMANCE_TEST(conformance_more_conformance_webGLArrays,
- "conformance/more/conformance/webGLArrays.html");
-CONFORMANCE_TEST(conformance_more_functions_bindBuffer,
- "conformance/more/functions/bindBuffer.html");
-CONFORMANCE_TEST(conformance_more_functions_bindBufferBadArgs,
- "conformance/more/functions/bindBufferBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_bindFramebufferLeaveNonZero,
- "conformance/more/functions/bindFramebufferLeaveNonZero.html");
-CONFORMANCE_TEST(conformance_more_functions_bufferData,
- "conformance/more/functions/bufferData.html");
-CONFORMANCE_TEST(conformance_more_functions_bufferDataBadArgs,
- "conformance/more/functions/bufferDataBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_bufferSubData,
- "conformance/more/functions/bufferSubData.html");
-CONFORMANCE_TEST(conformance_more_functions_bufferSubDataBadArgs,
- "conformance/more/functions/bufferSubDataBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_copyTexImage2D,
- "conformance/more/functions/copyTexImage2D.html");
-CONFORMANCE_TEST(conformance_more_functions_copyTexImage2DBadArgs,
- "conformance/more/functions/copyTexImage2DBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_copyTexSubImage2D,
- "conformance/more/functions/copyTexSubImage2D.html");
-CONFORMANCE_TEST(conformance_more_functions_copyTexSubImage2DBadArgs,
- "conformance/more/functions/copyTexSubImage2DBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_deleteBufferBadArgs,
- "conformance/more/functions/deleteBufferBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_drawArrays,
- "conformance/more/functions/drawArrays.html");
-CONFORMANCE_TEST(conformance_more_functions_drawArraysOutOfBounds,
- "conformance/more/functions/drawArraysOutOfBounds.html");
-CONFORMANCE_TEST(conformance_more_functions_drawElements,
- "conformance/more/functions/drawElements.html");
-CONFORMANCE_TEST(conformance_more_functions_drawElementsBadArgs,
- "conformance/more/functions/drawElementsBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_isTests,
- "conformance/more/functions/isTests.html");
-CONFORMANCE_TEST(conformance_more_functions_isTestsBadArgs,
- "conformance/more/functions/isTestsBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_readPixels,
- "conformance/more/functions/readPixels.html");
-CONFORMANCE_TEST(conformance_more_functions_readPixelsBadArgs,
- "conformance/more/functions/readPixelsBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_texImage2D,
- "conformance/more/functions/texImage2D.html");
-CONFORMANCE_TEST(conformance_more_functions_texImage2DBadArgs,
- "conformance/more/functions/texImage2DBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_texImage2DHTML,
- "conformance/more/functions/texImage2DHTML.html");
-CONFORMANCE_TEST(conformance_more_functions_texImage2DHTMLBadArgs,
- "conformance/more/functions/texImage2DHTMLBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_texSubImage2D,
- "conformance/more/functions/texSubImage2D.html");
-CONFORMANCE_TEST(conformance_more_functions_texSubImage2DBadArgs,
- "conformance/more/functions/texSubImage2DBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_texSubImage2DHTML,
- "conformance/more/functions/texSubImage2DHTML.html");
-CONFORMANCE_TEST(conformance_more_functions_texSubImage2DHTMLBadArgs,
- "conformance/more/functions/texSubImage2DHTMLBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_uniformf,
- "conformance/more/functions/uniformf.html");
-CONFORMANCE_TEST(conformance_more_functions_uniformfBadArgs,
- "conformance/more/functions/uniformfBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_uniformfArrayLen1,
- "conformance/more/functions/uniformfArrayLen1.html");
-CONFORMANCE_TEST(conformance_more_functions_uniformi,
- "conformance/more/functions/uniformi.html");
-CONFORMANCE_TEST(conformance_more_functions_uniformiBadArgs,
- "conformance/more/functions/uniformiBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_uniformMatrix,
- "conformance/more/functions/uniformMatrix.html");
-CONFORMANCE_TEST(conformance_more_functions_uniformMatrixBadArgs,
- "conformance/more/functions/uniformMatrixBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_vertexAttrib,
- "conformance/more/functions/vertexAttrib.html");
-CONFORMANCE_TEST(conformance_more_functions_vertexAttribBadArgs,
- "conformance/more/functions/vertexAttribBadArgs.html");
-CONFORMANCE_TEST(conformance_more_functions_vertexAttribPointer,
- "conformance/more/functions/vertexAttribPointer.html");
-CONFORMANCE_TEST(conformance_more_functions_vertexAttribPointerBadArgs,
- "conformance/more/functions/vertexAttribPointerBadArgs.html");
-CONFORMANCE_TEST(conformance_more_glsl_arrayOutOfBounds,
- "conformance/more/glsl/arrayOutOfBounds.html");
-CONFORMANCE_TEST(conformance_more_glsl_uniformOutOfBounds,
- "conformance/more/glsl/uniformOutOfBounds.html");
-CONFORMANCE_TEST(conformance_attribs_gl_enable_vertex_attrib,
- "conformance/attribs/gl-enable-vertex-attrib.html");
-CONFORMANCE_TEST(conformance_attribs_gl_vertex_attrib_render,
- "conformance/attribs/gl-vertex-attrib-render.html");
-CONFORMANCE_TEST(conformance_attribs_gl_disabled_vertex_attrib,
- "conformance/attribs/gl-disabled-vertex-attrib.html");
-CONFORMANCE_TEST(conformance_attribs_gl_vertex_attrib_zero_issues,
- "conformance/attribs/gl-vertex-attrib-zero-issues.html");
-CONFORMANCE_TEST(conformance_attribs_gl_vertex_attrib,
- "conformance/attribs/gl-vertex-attrib.html");
-CONFORMANCE_TEST(conformance_attribs_gl_vertexattribpointer_offsets,
- "conformance/attribs/gl-vertexattribpointer-offsets.html");
-CONFORMANCE_TEST(conformance_attribs_gl_vertexattribpointer,
- "conformance/attribs/gl-vertexattribpointer.html");
-CONFORMANCE_TEST(conformance_buffers_buffer_bind_test,
- "conformance/buffers/buffer-bind-test.html");
-CONFORMANCE_TEST(conformance_buffers_buffer_data_array_buffer,
- "conformance/buffers/buffer-data-array-buffer.html");
-CONFORMANCE_TEST(conformance_buffers_index_validation_copies_indices,
- "conformance/buffers/index-validation-copies-indices.html");
-CONFORMANCE_TEST(conformance_buffers_index_validation_crash_with_buffer_sub_data,
- "conformance/buffers/index-validation-crash-with-buffer-sub-data.html");
-CONFORMANCE_TEST(conformance_buffers_index_validation_verifies_too_many_indices,
- "conformance/buffers/index-validation-verifies-too-many-indices.html");
-CONFORMANCE_TEST(conformance_buffers_index_validation_with_resized_buffer,
- "conformance/buffers/index-validation-with-resized-buffer.html");
-CONFORMANCE_TEST(conformance_buffers_index_validation,
- "conformance/buffers/index-validation.html");
-CONFORMANCE_TEST(conformance_canvas_buffer_offscreen_test,
- "conformance/canvas/buffer-offscreen-test.html");
-CONFORMANCE_TEST(conformance_canvas_buffer_preserve_test,
- "conformance/canvas/buffer-preserve-test.html");
-CONFORMANCE_TEST(conformance_canvas_canvas_test,
- "conformance/canvas/canvas-test.html");
-CONFORMANCE_TEST(conformance_canvas_canvas_zero_size,
- "conformance/canvas/canvas-zero-size.html");
-CONFORMANCE_TEST(conformance_canvas_drawingbuffer_static_canvas_test,
- "conformance/canvas/drawingbuffer-static-canvas-test.html");
-CONFORMANCE_TEST(conformance_canvas_drawingbuffer_test,
- "conformance/canvas/drawingbuffer-test.html");
-CONFORMANCE_TEST(conformance_canvas_framebuffer_bindings_unaffected_on_resize,
- "conformance/canvas/framebuffer-bindings-unaffected-on-resize.html");
-CONFORMANCE_TEST(conformance_canvas_texture_bindings_unaffected_on_resize,
- "conformance/canvas/texture-bindings-unaffected-on-resize.html");
-CONFORMANCE_TEST(conformance_canvas_viewport_unchanged_upon_resize,
- "conformance/canvas/viewport-unchanged-upon-resize.html");
-CONFORMANCE_TEST(conformance_context_constants,
- "conformance/context/constants.html");
-CONFORMANCE_TEST(conformance_context_context_attribute_preserve_drawing_buffer,
- "conformance/context/context-attribute-preserve-drawing-buffer.html");
-CONFORMANCE_TEST(conformance_context_context_attributes_alpha_depth_stencil_antialias,
- "conformance/context/context-attributes-alpha-depth-stencil-antialias.html");
-CONFORMANCE_TEST(conformance_context_context_creation_and_destruction,
- "conformance/context/context-creation-and-destruction.html");
-CONFORMANCE_TEST(conformance_context_context_lost_restored,
- "conformance/context/context-lost-restored.html");
-CONFORMANCE_TEST(conformance_context_context_lost,
- "conformance/context/context-lost.html");
-CONFORMANCE_TEST(conformance_context_context_type_test,
- "conformance/context/context-type-test.html");
-CONFORMANCE_TEST(conformance_context_incorrect_context_object_behaviour,
- "conformance/context/incorrect-context-object-behaviour.html");
-CONFORMANCE_TEST(conformance_context_methods,
- "conformance/context/methods.html");
-CONFORMANCE_TEST(conformance_context_premultiplyalpha_test,
- "conformance/context/premultiplyalpha-test.html");
-CONFORMANCE_TEST(conformance_context_resource_sharing_test,
- "conformance/context/resource-sharing-test.html");
-CONFORMANCE_TEST(conformance_extensions_get_extension,
- "conformance/extensions/get-extension.html");
-CONFORMANCE_TEST(conformance_extensions_oes_standard_derivatives,
- "conformance/extensions/oes-standard-derivatives.html");
-CONFORMANCE_TEST(conformance_extensions_oes_texture_float_with_canvas,
- "conformance/extensions/oes-texture-float-with-canvas.html");
-CONFORMANCE_TEST(conformance_extensions_oes_texture_float_with_image_data,
- "conformance/extensions/oes-texture-float-with-image-data.html");
-CONFORMANCE_TEST(conformance_extensions_oes_texture_float_with_image,
- "conformance/extensions/oes-texture-float-with-image.html");
-CONFORMANCE_TEST(conformance_extensions_oes_texture_float_with_video,
- "conformance/extensions/oes-texture-float-with-video.html");
-CONFORMANCE_TEST(conformance_extensions_oes_texture_float,
- "conformance/extensions/oes-texture-float.html");
-CONFORMANCE_TEST(conformance_extensions_oes_vertex_array_object,
- "conformance/extensions/oes-vertex-array-object.html");
-CONFORMANCE_TEST(conformance_extensions_webgl_debug_renderer_info,
- "conformance/extensions/webgl-debug-renderer-info.html");
-CONFORMANCE_TEST(conformance_extensions_webgl_debug_shaders,
- "conformance/extensions/webgl-debug-shaders.html");
-CONFORMANCE_TEST(conformance_extensions_webgl_compressed_texture_s3tc,
- "conformance/extensions/webgl-compressed-texture-s3tc.html");
-CONFORMANCE_TEST(conformance_extensions_ext_texture_filter_anisotropic,
- "conformance/extensions/ext-texture-filter-anisotropic.html");
-CONFORMANCE_TEST(conformance_limits_gl_min_attribs,
- "conformance/limits/gl-min-attribs.html");
-CONFORMANCE_TEST(conformance_limits_gl_max_texture_dimensions,
- "conformance/limits/gl-max-texture-dimensions.html");
-CONFORMANCE_TEST(conformance_limits_gl_min_textures,
- "conformance/limits/gl-min-textures.html");
-CONFORMANCE_TEST(conformance_limits_gl_min_uniforms,
- "conformance/limits/gl-min-uniforms.html");
-CONFORMANCE_TEST(conformance_misc_bad_arguments_test,
- "conformance/misc/bad-arguments-test.html");
-CONFORMANCE_TEST(conformance_misc_delayed_drawing,
- "conformance/misc/delayed-drawing.html");
-CONFORMANCE_TEST(conformance_misc_error_reporting,
- "conformance/misc/error-reporting.html");
-CONFORMANCE_TEST(conformance_misc_instanceof_test,
- "conformance/misc/instanceof-test.html");
-CONFORMANCE_TEST(conformance_misc_invalid_passed_params,
- "conformance/misc/invalid-passed-params.html");
-CONFORMANCE_TEST(conformance_misc_is_object,
- "conformance/misc/is-object.html");
-CONFORMANCE_TEST(conformance_misc_null_object_behaviour,
- "conformance/misc/null-object-behaviour.html");
-CONFORMANCE_TEST(conformance_misc_functions_returning_strings,
- "conformance/misc/functions-returning-strings.html");
-CONFORMANCE_TEST(conformance_misc_object_deletion_behaviour,
- "conformance/misc/object-deletion-behaviour.html");
-CONFORMANCE_TEST(conformance_misc_shader_precision_format,
- "conformance/misc/shader-precision-format.html");
-CONFORMANCE_TEST(conformance_misc_type_conversion_test,
- "conformance/misc/type-conversion-test.html");
-CONFORMANCE_TEST(conformance_misc_uninitialized_test,
- "conformance/misc/uninitialized-test.html");
-CONFORMANCE_TEST(conformance_misc_webgl_specific,
- "conformance/misc/webgl-specific.html");
-CONFORMANCE_TEST(conformance_programs_get_active_test,
- "conformance/programs/get-active-test.html");
-CONFORMANCE_TEST(conformance_programs_gl_bind_attrib_location_test,
- "conformance/programs/gl-bind-attrib-location-test.html");
-CONFORMANCE_TEST(conformance_programs_gl_bind_attrib_location_long_names_test,
- "conformance/programs/gl-bind-attrib-location-long-names-test.html");
-CONFORMANCE_TEST(conformance_programs_gl_get_active_attribute,
- "conformance/programs/gl-get-active-attribute.html");
-CONFORMANCE_TEST(conformance_programs_gl_get_active_uniform,
- "conformance/programs/gl-get-active-uniform.html");
-CONFORMANCE_TEST(conformance_programs_gl_getshadersource,
- "conformance/programs/gl-getshadersource.html");
-CONFORMANCE_TEST(conformance_programs_gl_shader_test,
- "conformance/programs/gl-shader-test.html");
-CONFORMANCE_TEST(conformance_programs_invalid_UTF_16,
- "conformance/programs/invalid-UTF-16.html");
-CONFORMANCE_TEST(conformance_programs_program_test,
- "conformance/programs/program-test.html");
-CONFORMANCE_TEST(conformance_programs_use_program_crash_with_discard_in_fragment_shader,
- "conformance/programs/use-program-crash-with-discard-in-fragment-shader.html");
-CONFORMANCE_TEST(conformance_reading_read_pixels_pack_alignment,
- "conformance/reading/read-pixels-pack-alignment.html");
-CONFORMANCE_TEST(conformance_reading_read_pixels_test,
- "conformance/reading/read-pixels-test.html");
-CONFORMANCE_TEST(conformance_renderbuffers_framebuffer_object_attachment,
- "conformance/renderbuffers/framebuffer-object-attachment.html");
-CONFORMANCE_TEST(conformance_renderbuffers_framebuffer_state_restoration,
- "conformance/renderbuffers/framebuffer-state-restoration.html");
-CONFORMANCE_TEST(conformance_renderbuffers_framebuffer_test,
- "conformance/renderbuffers/framebuffer-test.html");
-CONFORMANCE_TEST(conformance_renderbuffers_renderbuffer_initialization,
- "conformance/renderbuffers/renderbuffer-initialization.html");
-CONFORMANCE_TEST(conformance_rendering_culling,
- "conformance/rendering/culling.html");
-CONFORMANCE_TEST(conformance_rendering_draw_arrays_out_of_bounds,
- "conformance/rendering/draw-arrays-out-of-bounds.html");
-CONFORMANCE_TEST(conformance_rendering_draw_elements_out_of_bounds,
- "conformance/rendering/draw-elements-out-of-bounds.html");
-CONFORMANCE_TEST(conformance_rendering_gl_clear,
- "conformance/rendering/gl-clear.html");
-CONFORMANCE_TEST(conformance_rendering_gl_drawelements,
- "conformance/rendering/gl-drawelements.html");
-CONFORMANCE_TEST(conformance_rendering_gl_scissor_test,
- "conformance/rendering/gl-scissor-test.html");
-CONFORMANCE_TEST(conformance_rendering_more_than_65536_indices,
- "conformance/rendering/more-than-65536-indices.html");
-CONFORMANCE_TEST(conformance_rendering_point_size,
- "conformance/rendering/point-size.html");
-CONFORMANCE_TEST(conformance_rendering_triangle,
- "conformance/rendering/triangle.html");
-CONFORMANCE_TEST(conformance_rendering_line_loop_tri_fan,
- "conformance/rendering/line-loop-tri-fan.html");
-CONFORMANCE_TEST(conformance_state_gl_enable_enum_test,
- "conformance/state/gl-enable-enum-test.html");
-CONFORMANCE_TEST(conformance_state_gl_enum_tests,
- "conformance/state/gl-enum-tests.html");
-CONFORMANCE_TEST(conformance_state_gl_get_calls,
- "conformance/state/gl-get-calls.html");
-CONFORMANCE_TEST(conformance_state_gl_geterror,
- "conformance/state/gl-geterror.html");
-CONFORMANCE_TEST(conformance_state_gl_getstring,
- "conformance/state/gl-getstring.html");
-CONFORMANCE_TEST(conformance_state_gl_object_get_calls,
- "conformance/state/gl-object-get-calls.html");
-CONFORMANCE_TEST(conformance_textures_compressed_tex_image,
- "conformance/textures/compressed-tex-image.html");
-CONFORMANCE_TEST(conformance_textures_copy_tex_image_and_sub_image_2d,
- "conformance/textures/copy-tex-image-and-sub-image-2d.html");
-CONFORMANCE_TEST(conformance_textures_gl_pixelstorei,
- "conformance/textures/gl-pixelstorei.html");
-CONFORMANCE_TEST(conformance_textures_gl_teximage,
- "conformance/textures/gl-teximage.html");
-CONFORMANCE_TEST(conformance_textures_origin_clean_conformance,
- "conformance/textures/origin-clean-conformance.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_array_buffer_view,
- "conformance/textures/tex-image-and-sub-image-2d-with-array-buffer-view.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_canvas,
- "conformance/textures/tex-image-and-sub-image-2d-with-canvas.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_canvas_rgb565,
- "conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgb565.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_canvas_rgba4444,
- "conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba4444.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_canvas_rgba5551,
- "conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba5551.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_image_data,
- "conformance/textures/tex-image-and-sub-image-2d-with-image-data.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_image_data_rgb565,
- "conformance/textures/tex-image-and-sub-image-2d-with-image-data-rgb565.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_image_data_rgba4444,
- "conformance/textures/tex-image-and-sub-image-2d-with-image-data-rgba4444.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_image_data_rgba5551,
- "conformance/textures/tex-image-and-sub-image-2d-with-image-data-rgba5551.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_image,
- "conformance/textures/tex-image-and-sub-image-2d-with-image.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_image_rgb565,
- "conformance/textures/tex-image-and-sub-image-2d-with-image-rgb565.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_image_rgba4444,
- "conformance/textures/tex-image-and-sub-image-2d-with-image-rgba4444.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_image_rgba5551,
- "conformance/textures/tex-image-and-sub-image-2d-with-image-rgba5551.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_video,
- "conformance/textures/tex-image-and-sub-image-2d-with-video.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_video_rgb565,
- "conformance/textures/tex-image-and-sub-image-2d-with-video-rgb565.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_video_rgba4444,
- "conformance/textures/tex-image-and-sub-image-2d-with-video-rgba4444.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_sub_image_2d_with_video_rgba5551,
- "conformance/textures/tex-image-and-sub-image-2d-with-video-rgba5551.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_and_uniform_binding_bugs,
- "conformance/textures/tex-image-and-uniform-binding-bugs.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_with_format_and_type,
- "conformance/textures/tex-image-with-format-and-type.html");
-CONFORMANCE_TEST(conformance_textures_tex_image_with_invalid_data,
- "conformance/textures/tex-image-with-invalid-data.html");
-CONFORMANCE_TEST(conformance_textures_tex_input_validation,
- "conformance/textures/tex-input-validation.html");
-CONFORMANCE_TEST(conformance_textures_tex_sub_image_2d_bad_args,
- "conformance/textures/tex-sub-image-2d-bad-args.html");
-CONFORMANCE_TEST(conformance_textures_tex_sub_image_2d,
- "conformance/textures/tex-sub-image-2d.html");
-CONFORMANCE_TEST(conformance_textures_texparameter_test,
- "conformance/textures/texparameter-test.html");
-CONFORMANCE_TEST(conformance_textures_texture_active_bind_2,
- "conformance/textures/texture-active-bind-2.html");
-CONFORMANCE_TEST(conformance_textures_texture_active_bind,
- "conformance/textures/texture-active-bind.html");
-CONFORMANCE_TEST(conformance_textures_texture_attachment_formats,
- "conformance/textures/texture-attachment-formats.html");
-CONFORMANCE_TEST(conformance_textures_texture_clear,
- "conformance/textures/texture-clear.html");
-CONFORMANCE_TEST(conformance_textures_texture_complete,
- "conformance/textures/texture-complete.html");
-CONFORMANCE_TEST(conformance_textures_texture_formats_test,
- "conformance/textures/texture-formats-test.html");
-CONFORMANCE_TEST(conformance_textures_texture_mips,
- "conformance/textures/texture-mips.html");
-CONFORMANCE_TEST(conformance_textures_texture_npot_video,
- "conformance/textures/texture-npot-video.html");
-CONFORMANCE_TEST(conformance_textures_texture_npot,
- "conformance/textures/texture-npot.html");
-CONFORMANCE_TEST(conformance_textures_texture_size,
- "conformance/textures/texture-size.html");
-CONFORMANCE_TEST(conformance_textures_texture_size_cube_maps,
- "conformance/textures/texture-size-cube-maps.html");
-CONFORMANCE_TEST(conformance_textures_texture_transparent_pixels_initialized,
- "conformance/textures/texture-transparent-pixels-initialized.html");
-CONFORMANCE_TEST(conformance_textures_texture_upload_cube_maps,
- "conformance/textures/texture-upload-cube-maps.html");
-CONFORMANCE_TEST(conformance_typedarrays_array_buffer_crash,
- "conformance/typedarrays/array-buffer-crash.html");
-CONFORMANCE_TEST(conformance_typedarrays_array_buffer_view_crash,
- "conformance/typedarrays/array-buffer-view-crash.html");
-CONFORMANCE_TEST(conformance_typedarrays_array_unit_tests,
- "conformance/typedarrays/array-unit-tests.html");
-CONFORMANCE_TEST(conformance_typedarrays_data_view_crash,
- "conformance/typedarrays/data-view-crash.html");
-CONFORMANCE_TEST(conformance_typedarrays_data_view_test,
- "conformance/typedarrays/data-view-test.html");
-CONFORMANCE_TEST(conformance_uniforms_gl_uniform_arrays,
- "conformance/uniforms/gl-uniform-arrays.html");
-CONFORMANCE_TEST(conformance_uniforms_gl_uniform_bool,
- "conformance/uniforms/gl-uniform-bool.html");
-CONFORMANCE_TEST(conformance_uniforms_gl_uniformmatrix4fv,
- "conformance/uniforms/gl-uniformmatrix4fv.html");
-CONFORMANCE_TEST(conformance_uniforms_gl_unknown_uniform,
- "conformance/uniforms/gl-unknown-uniform.html");
-CONFORMANCE_TEST(conformance_uniforms_null_uniform_location,
- "conformance/uniforms/null-uniform-location.html");
-CONFORMANCE_TEST(conformance_uniforms_uniform_default_values,
- "conformance/uniforms/uniform-default-values.html");
-CONFORMANCE_TEST(conformance_uniforms_uniform_location,
- "conformance/uniforms/uniform-location.html");
-CONFORMANCE_TEST(conformance_uniforms_uniform_samplers_test,
- "conformance/uniforms/uniform-samplers-test.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function,
- "conformance/glsl/functions/glsl-function.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_abs,
- "conformance/glsl/functions/glsl-function-abs.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_acos,
- "conformance/glsl/functions/glsl-function-acos.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_asin,
- "conformance/glsl/functions/glsl-function-asin.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_atan,
- "conformance/glsl/functions/glsl-function-atan.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_atan_xy,
- "conformance/glsl/functions/glsl-function-atan-xy.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_ceil,
- "conformance/glsl/functions/glsl-function-ceil.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_clamp_float,
- "conformance/glsl/functions/glsl-function-clamp-float.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_clamp_gentype,
- "conformance/glsl/functions/glsl-function-clamp-gentype.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_cos,
- "conformance/glsl/functions/glsl-function-cos.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_cross,
- "conformance/glsl/functions/glsl-function-cross.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_distance,
- "conformance/glsl/functions/glsl-function-distance.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_dot,
- "conformance/glsl/functions/glsl-function-dot.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_faceforward,
- "conformance/glsl/functions/glsl-function-faceforward.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_floor,
- "conformance/glsl/functions/glsl-function-floor.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_fract,
- "conformance/glsl/functions/glsl-function-fract.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_length,
- "conformance/glsl/functions/glsl-function-length.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_max_float,
- "conformance/glsl/functions/glsl-function-max-float.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_max_gentype,
- "conformance/glsl/functions/glsl-function-max-gentype.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_min_float,
- "conformance/glsl/functions/glsl-function-min-float.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_min_gentype,
- "conformance/glsl/functions/glsl-function-min-gentype.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_mix_float,
- "conformance/glsl/functions/glsl-function-mix-float.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_mix_gentype,
- "conformance/glsl/functions/glsl-function-mix-gentype.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_mod_float,
- "conformance/glsl/functions/glsl-function-mod-float.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_mod_gentype,
- "conformance/glsl/functions/glsl-function-mod-gentype.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_normalize,
- "conformance/glsl/functions/glsl-function-normalize.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_reflect,
- "conformance/glsl/functions/glsl-function-reflect.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_sign,
- "conformance/glsl/functions/glsl-function-sign.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_sin,
- "conformance/glsl/functions/glsl-function-sin.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_step_float,
- "conformance/glsl/functions/glsl-function-step-float.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_step_gentype,
- "conformance/glsl/functions/glsl-function-step-gentype.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_smoothstep_float,
- "conformance/glsl/functions/glsl-function-smoothstep-float.html");
-CONFORMANCE_TEST(conformance_glsl_functions_glsl_function_smoothstep_gentype,
- "conformance/glsl/functions/glsl-function-smoothstep-gentype.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_add_int_float_vert,
- "conformance/glsl/implicit/add_int_float.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_add_int_mat2_vert,
- "conformance/glsl/implicit/add_int_mat2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_add_int_mat3_vert,
- "conformance/glsl/implicit/add_int_mat3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_add_int_mat4_vert,
- "conformance/glsl/implicit/add_int_mat4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_add_int_vec2_vert,
- "conformance/glsl/implicit/add_int_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_add_int_vec3_vert,
- "conformance/glsl/implicit/add_int_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_add_int_vec4_vert,
- "conformance/glsl/implicit/add_int_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_add_ivec2_vec2_vert,
- "conformance/glsl/implicit/add_ivec2_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_add_ivec3_vec3_vert,
- "conformance/glsl/implicit/add_ivec3_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_add_ivec4_vec4_vert,
- "conformance/glsl/implicit/add_ivec4_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_assign_int_to_float_vert,
- "conformance/glsl/implicit/assign_int_to_float.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_assign_ivec2_to_vec2_vert,
- "conformance/glsl/implicit/assign_ivec2_to_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_assign_ivec3_to_vec3_vert,
- "conformance/glsl/implicit/assign_ivec3_to_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_assign_ivec4_to_vec4_vert,
- "conformance/glsl/implicit/assign_ivec4_to_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_construct_struct_vert,
- "conformance/glsl/implicit/construct_struct.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_divide_int_float_vert,
- "conformance/glsl/implicit/divide_int_float.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_divide_int_mat2_vert,
- "conformance/glsl/implicit/divide_int_mat2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_divide_int_mat3_vert,
- "conformance/glsl/implicit/divide_int_mat3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_divide_int_mat4_vert,
- "conformance/glsl/implicit/divide_int_mat4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_divide_int_vec2_vert,
- "conformance/glsl/implicit/divide_int_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_divide_int_vec3_vert,
- "conformance/glsl/implicit/divide_int_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_divide_int_vec4_vert,
- "conformance/glsl/implicit/divide_int_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_divide_ivec2_vec2_vert,
- "conformance/glsl/implicit/divide_ivec2_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_divide_ivec3_vec3_vert,
- "conformance/glsl/implicit/divide_ivec3_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_divide_ivec4_vec4_vert,
- "conformance/glsl/implicit/divide_ivec4_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_equal_int_float_vert,
- "conformance/glsl/implicit/equal_int_float.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_equal_ivec2_vec2_vert,
- "conformance/glsl/implicit/equal_ivec2_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_equal_ivec3_vec3_vert,
- "conformance/glsl/implicit/equal_ivec3_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_equal_ivec4_vec4_vert,
- "conformance/glsl/implicit/equal_ivec4_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_function_int_float_vert,
- "conformance/glsl/implicit/function_int_float.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_function_ivec2_vec2_vert,
- "conformance/glsl/implicit/function_ivec2_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_function_ivec3_vec3_vert,
- "conformance/glsl/implicit/function_ivec3_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_function_ivec4_vec4_vert,
- "conformance/glsl/implicit/function_ivec4_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_greater_than_vert,
- "conformance/glsl/implicit/greater_than.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_greater_than_equal_vert,
- "conformance/glsl/implicit/greater_than_equal.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_less_than_vert,
- "conformance/glsl/implicit/less_than.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_less_than_equal_vert,
- "conformance/glsl/implicit/less_than_equal.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_multiply_int_float_vert,
- "conformance/glsl/implicit/multiply_int_float.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_multiply_int_mat2_vert,
- "conformance/glsl/implicit/multiply_int_mat2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_multiply_int_mat3_vert,
- "conformance/glsl/implicit/multiply_int_mat3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_multiply_int_mat4_vert,
- "conformance/glsl/implicit/multiply_int_mat4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_multiply_int_vec2_vert,
- "conformance/glsl/implicit/multiply_int_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_multiply_int_vec3_vert,
- "conformance/glsl/implicit/multiply_int_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_multiply_int_vec4_vert,
- "conformance/glsl/implicit/multiply_int_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_multiply_ivec2_vec2_vert,
- "conformance/glsl/implicit/multiply_ivec2_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_multiply_ivec3_vec3_vert,
- "conformance/glsl/implicit/multiply_ivec3_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_multiply_ivec4_vec4_vert,
- "conformance/glsl/implicit/multiply_ivec4_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_not_equal_int_float_vert,
- "conformance/glsl/implicit/not_equal_int_float.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_not_equal_ivec2_vec2_vert,
- "conformance/glsl/implicit/not_equal_ivec2_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_not_equal_ivec3_vec3_vert,
- "conformance/glsl/implicit/not_equal_ivec3_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_not_equal_ivec4_vec4_vert,
- "conformance/glsl/implicit/not_equal_ivec4_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_subtract_int_float_vert,
- "conformance/glsl/implicit/subtract_int_float.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_subtract_int_mat2_vert,
- "conformance/glsl/implicit/subtract_int_mat2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_subtract_int_mat3_vert,
- "conformance/glsl/implicit/subtract_int_mat3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_subtract_int_mat4_vert,
- "conformance/glsl/implicit/subtract_int_mat4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_subtract_int_vec2_vert,
- "conformance/glsl/implicit/subtract_int_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_subtract_int_vec3_vert,
- "conformance/glsl/implicit/subtract_int_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_subtract_int_vec4_vert,
- "conformance/glsl/implicit/subtract_int_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_subtract_ivec2_vec2_vert,
- "conformance/glsl/implicit/subtract_ivec2_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_subtract_ivec3_vec3_vert,
- "conformance/glsl/implicit/subtract_ivec3_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_subtract_ivec4_vec4_vert,
- "conformance/glsl/implicit/subtract_ivec4_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_ternary_int_float_vert,
- "conformance/glsl/implicit/ternary_int_float.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_ternary_ivec2_vec2_vert,
- "conformance/glsl/implicit/ternary_ivec2_vec2.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_ternary_ivec3_vec3_vert,
- "conformance/glsl/implicit/ternary_ivec3_vec3.vert.html");
-CONFORMANCE_TEST(conformance_glsl_implicit_ternary_ivec4_vec4_vert,
- "conformance/glsl/implicit/ternary_ivec4_vec4.vert.html");
-CONFORMANCE_TEST(conformance_glsl_matrices_glsl_mat4_to_mat3,
- "conformance/glsl/matrices/glsl-mat4-to-mat3.html");
-CONFORMANCE_TEST(conformance_glsl_misc_attrib_location_length_limits,
- "conformance/glsl/misc/attrib-location-length-limits.html");
-CONFORMANCE_TEST(conformance_glsl_misc_embedded_struct_definitions_forbidden,
- "conformance/glsl/misc/embedded-struct-definitions-forbidden.html");
-CONFORMANCE_TEST(conformance_glsl_misc_glsl_function_nodes,
- "conformance/glsl/misc/glsl-function-nodes.html");
-CONFORMANCE_TEST(conformance_glsl_misc_glsl_vertex_branch,
- "conformance/glsl/misc/glsl-vertex-branch.html");
-CONFORMANCE_TEST(conformance_glsl_misc_glsl_long_variable_names,
- "conformance/glsl/misc/glsl-long-variable-names.html");
-CONFORMANCE_TEST(conformance_glsl_misc_non_ascii_comments_vert,
- "conformance/glsl/misc/non-ascii-comments.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_non_ascii_vert,
- "conformance/glsl/misc/non-ascii.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_re_compile_re_link,
- "conformance/glsl/misc/re-compile-re-link.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_256_character_define,
- "conformance/glsl/misc/shader-with-256-character-define.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_256_character_identifier_frag,
- "conformance/glsl/misc/shader-with-256-character-identifier.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_257_character_define,
- "conformance/glsl/misc/shader-with-257-character-define.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_257_character_identifier_frag,
- "conformance/glsl/misc/shader-with-257-character-identifier.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with__webgl_identifier_vert,
- "conformance/glsl/misc/shader-with-_webgl-identifier.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_arbitrary_indexing_frag,
- "conformance/glsl/misc/shader-with-arbitrary-indexing.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_arbitrary_indexing_vert,
- "conformance/glsl/misc/shader-with-arbitrary-indexing.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_attrib_array_vert,
- "conformance/glsl/misc/shader-with-attrib-array.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_attrib_struct_vert,
- "conformance/glsl/misc/shader-with-attrib-struct.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_clipvertex_vert,
- "conformance/glsl/misc/shader-with-clipvertex.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_conditional_scoping,
- "conformance/glsl/misc/shader-with-conditional-scoping.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_conditional_scoping_negative,
- "conformance/glsl/misc/shader-with-conditional-scoping-negative.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_default_precision_frag,
- "conformance/glsl/misc/shader-with-default-precision.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_default_precision_vert,
- "conformance/glsl/misc/shader-with-default-precision.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_define_line_continuation_frag,
- "conformance/glsl/misc/shader-with-define-line-continuation.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_dfdx_no_ext_frag,
- "conformance/glsl/misc/shader-with-dfdx-no-ext.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_dfdx_frag,
- "conformance/glsl/misc/shader-with-dfdx.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_do_loop,
- "conformance/glsl/misc/shader-with-do-loop.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_error_directive,
- "conformance/glsl/misc/shader-with-error-directive.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_explicit_int_cast_vert,
- "conformance/glsl/misc/shader-with-explicit-int-cast.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_float_return_value_frag,
- "conformance/glsl/misc/shader-with-float-return-value.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_for_scoping,
- "conformance/glsl/misc/shader-with-for-scoping.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_for_loop,
- "conformance/glsl/misc/shader-with-for-loop.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_frag_depth_frag,
- "conformance/glsl/misc/shader-with-frag-depth.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_function_recursion_frag,
- "conformance/glsl/misc/shader-with-function-recursion.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_function_scoped_struct,
- "conformance/glsl/misc/shader-with-function-scoped-struct.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_functional_scoping,
- "conformance/glsl/misc/shader-with-functional-scoping.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_comma_assignment,
- "conformance/glsl/misc/shader-with-comma-assignment.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_comma_conditional_assignment,
- "conformance/glsl/misc/shader-with-comma-conditional-assignment.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_glcolor_vert,
- "conformance/glsl/misc/shader-with-glcolor.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_gles_1_frag,
- "conformance/glsl/misc/shader-with-gles-1.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_gles_symbol_frag,
- "conformance/glsl/misc/shader-with-gles-symbol.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_glprojectionmatrix_vert,
- "conformance/glsl/misc/shader-with-glprojectionmatrix.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_implicit_vec3_to_vec4_cast_vert,
- "conformance/glsl/misc/shader-with-implicit-vec3-to-vec4-cast.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_include_vert,
- "conformance/glsl/misc/shader-with-include.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_int_return_value_frag,
- "conformance/glsl/misc/shader-with-int-return-value.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_invalid_identifier_frag,
- "conformance/glsl/misc/shader-with-invalid-identifier.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_ivec2_return_value_frag,
- "conformance/glsl/misc/shader-with-ivec2-return-value.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_ivec3_return_value_frag,
- "conformance/glsl/misc/shader-with-ivec3-return-value.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_ivec4_return_value_frag,
- "conformance/glsl/misc/shader-with-ivec4-return-value.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_limited_indexing_frag,
- "conformance/glsl/misc/shader-with-limited-indexing.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_hex_int_constant_macro,
- "conformance/glsl/misc/shader-with-hex-int-constant-macro.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_long_line,
- "conformance/glsl/misc/shader-with-long-line.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_non_ascii_error_frag,
- "conformance/glsl/misc/shader-with-non-ascii-error.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_non_reserved_words,
- "conformance/glsl/misc/shader-with-non-reserved-words.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_precision_frag,
- "conformance/glsl/misc/shader-with-precision.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_quoted_error_frag,
- "conformance/glsl/misc/shader-with-quoted-error.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_reserved_words,
- "conformance/glsl/misc/shader-with-reserved-words.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_undefined_preprocessor_symbol_frag,
- "conformance/glsl/misc/shader-with-undefined-preprocessor-symbol.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_uniform_in_loop_condition_vert,
- "conformance/glsl/misc/shader-with-uniform-in-loop-condition.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_vec2_return_value_frag,
- "conformance/glsl/misc/shader-with-vec2-return-value.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_vec3_return_value_frag,
- "conformance/glsl/misc/shader-with-vec3-return-value.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_vec4_return_value_frag,
- "conformance/glsl/misc/shader-with-vec4-return-value.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_vec4_vec3_vec4_conditional,
- "conformance/glsl/misc/shader-with-vec4-vec3-vec4-conditional.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_version_100_frag,
- "conformance/glsl/misc/shader-with-version-100.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_version_100_vert,
- "conformance/glsl/misc/shader-with-version-100.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_version_120_vert,
- "conformance/glsl/misc/shader-with-version-120.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_version_130_vert,
- "conformance/glsl/misc/shader-with-version-130.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_webgl_identifier_vert,
- "conformance/glsl/misc/shader-with-webgl-identifier.vert.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_while_loop,
- "conformance/glsl/misc/shader-with-while-loop.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_without_precision_frag,
- "conformance/glsl/misc/shader-without-precision.frag.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shared,
- "conformance/glsl/misc/shared.html");
-CONFORMANCE_TEST(conformance_glsl_misc_struct_nesting_exceeds_maximum,
- "conformance/glsl/misc/struct-nesting-exceeds-maximum.html");
-CONFORMANCE_TEST(conformance_glsl_misc_struct_nesting_under_maximum,
- "conformance/glsl/misc/struct-nesting-under-maximum.html");
-CONFORMANCE_TEST(conformance_glsl_misc_uniform_location_length_limits,
- "conformance/glsl/misc/uniform-location-length-limits.html");
-CONFORMANCE_TEST(conformance_glsl_misc_shader_with_short_circuiting_operators,
- "conformance/glsl/misc/shader-with-short-circuiting-operators.html");
-CONFORMANCE_TEST(conformance_glsl_reserved__webgl_field_vert,
- "conformance/glsl/reserved/_webgl_field.vert.html");
-CONFORMANCE_TEST(conformance_glsl_reserved__webgl_function_vert,
- "conformance/glsl/reserved/_webgl_function.vert.html");
-CONFORMANCE_TEST(conformance_glsl_reserved__webgl_struct_vert,
- "conformance/glsl/reserved/_webgl_struct.vert.html");
-CONFORMANCE_TEST(conformance_glsl_reserved__webgl_variable_vert,
- "conformance/glsl/reserved/_webgl_variable.vert.html");
-CONFORMANCE_TEST(conformance_glsl_reserved_webgl_field_vert,
- "conformance/glsl/reserved/webgl_field.vert.html");
-CONFORMANCE_TEST(conformance_glsl_reserved_webgl_function_vert,
- "conformance/glsl/reserved/webgl_function.vert.html");
-CONFORMANCE_TEST(conformance_glsl_reserved_webgl_struct_vert,
- "conformance/glsl/reserved/webgl_struct.vert.html");
-CONFORMANCE_TEST(conformance_glsl_reserved_webgl_variable_vert,
- "conformance/glsl/reserved/webgl_variable.vert.html");
-CONFORMANCE_TEST(conformance_glsl_samplers_glsl_function_texture2d_bias,
- "conformance/glsl/samplers/glsl-function-texture2d-bias.html");
-CONFORMANCE_TEST(conformance_glsl_samplers_glsl_function_texture2dlod,
- "conformance/glsl/samplers/glsl-function-texture2dlod.html");
-CONFORMANCE_TEST(conformance_glsl_samplers_glsl_function_texture2dproj,
- "conformance/glsl/samplers/glsl-function-texture2dproj.html");
-CONFORMANCE_TEST(conformance_glsl_variables_gl_fragcoord,
- "conformance/glsl/variables/gl-fragcoord.html");
-CONFORMANCE_TEST(conformance_glsl_variables_gl_frontfacing,
- "conformance/glsl/variables/gl-frontfacing.html");
-CONFORMANCE_TEST(conformance_glsl_variables_gl_pointcoord,
- "conformance/glsl/variables/gl-pointcoord.html");
-CONFORMANCE_TEST(conformance_ogles_GL_abs_abs_001_to_006,
- "conformance/ogles/GL/abs/abs_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_acos_acos_001_to_006,
- "conformance/ogles/GL/acos/acos_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_all_all_001_to_004,
- "conformance/ogles/GL/all/all_001_to_004.html");
-CONFORMANCE_TEST(conformance_ogles_GL_any_any_001_to_004,
- "conformance/ogles/GL/any/any_001_to_004.html");
-CONFORMANCE_TEST(conformance_ogles_GL_array_array_001_to_006,
- "conformance/ogles/GL/array/array_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_asin_asin_001_to_006,
- "conformance/ogles/GL/asin/asin_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_atan_atan_001_to_008,
- "conformance/ogles/GL/atan/atan_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_atan_atan_009_to_012,
- "conformance/ogles/GL/atan/atan_009_to_012.html");
-CONFORMANCE_TEST(conformance_ogles_GL_biConstants_biConstants_001_to_008,
- "conformance/ogles/GL/biConstants/biConstants_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_biConstants_biConstants_009_to_016,
- "conformance/ogles/GL/biConstants/biConstants_009_to_016.html");
-CONFORMANCE_TEST(conformance_ogles_GL_biuDepthRange_biuDepthRange_001_to_002,
- "conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_001_to_008,
- "conformance/ogles/GL/build/build_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_009_to_016,
- "conformance/ogles/GL/build/build_009_to_016.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_017_to_024,
- "conformance/ogles/GL/build/build_017_to_024.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_025_to_032,
- "conformance/ogles/GL/build/build_025_to_032.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_033_to_040,
- "conformance/ogles/GL/build/build_033_to_040.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_041_to_048,
- "conformance/ogles/GL/build/build_041_to_048.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_049_to_056,
- "conformance/ogles/GL/build/build_049_to_056.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_057_to_064,
- "conformance/ogles/GL/build/build_057_to_064.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_065_to_072,
- "conformance/ogles/GL/build/build_065_to_072.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_073_to_080,
- "conformance/ogles/GL/build/build_073_to_080.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_081_to_088,
- "conformance/ogles/GL/build/build_081_to_088.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_089_to_096,
- "conformance/ogles/GL/build/build_089_to_096.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_097_to_104,
- "conformance/ogles/GL/build/build_097_to_104.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_105_to_112,
- "conformance/ogles/GL/build/build_105_to_112.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_113_to_120,
- "conformance/ogles/GL/build/build_113_to_120.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_121_to_128,
- "conformance/ogles/GL/build/build_121_to_128.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_129_to_136,
- "conformance/ogles/GL/build/build_129_to_136.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_137_to_144,
- "conformance/ogles/GL/build/build_137_to_144.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_145_to_152,
- "conformance/ogles/GL/build/build_145_to_152.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_153_to_160,
- "conformance/ogles/GL/build/build_153_to_160.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_161_to_168,
- "conformance/ogles/GL/build/build_161_to_168.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_169_to_176,
- "conformance/ogles/GL/build/build_169_to_176.html");
-CONFORMANCE_TEST(conformance_ogles_GL_build_build_177_to_178,
- "conformance/ogles/GL/build/build_177_to_178.html");
-CONFORMANCE_TEST(conformance_ogles_GL_built_in_varying_array_out_of_bounds_built_in_varying_array_out_of_bounds_001_to_001,
- "conformance/ogles/GL/built_in_varying_array_out_of_bounds/built_in_varying_array_out_of_bounds_001_to_001.html");
-CONFORMANCE_TEST(conformance_ogles_GL_ceil_ceil_001_to_006,
- "conformance/ogles/GL/ceil/ceil_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_clamp_clamp_001_to_006,
- "conformance/ogles/GL/clamp/clamp_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_control_flow_control_flow_001_to_008,
- "conformance/ogles/GL/control_flow/control_flow_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_control_flow_control_flow_009_to_010,
- "conformance/ogles/GL/control_flow/control_flow_009_to_010.html");
-CONFORMANCE_TEST(conformance_ogles_GL_cos_cos_001_to_006,
- "conformance/ogles/GL/cos/cos_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_cross_cross_001_to_002,
- "conformance/ogles/GL/cross/cross_001_to_002.html");
-CONFORMANCE_TEST(conformance_ogles_GL_default_default_001_to_001,
- "conformance/ogles/GL/default/default_001_to_001.html");
-CONFORMANCE_TEST(conformance_ogles_GL_degrees_degrees_001_to_006,
- "conformance/ogles/GL/degrees/degrees_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_discard_discard_001_to_002,
- "conformance/ogles/GL/discard/discard_001_to_002.html");
-CONFORMANCE_TEST(conformance_ogles_GL_distance_distance_001_to_006,
- "conformance/ogles/GL/distance/distance_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_dot_dot_001_to_006,
- "conformance/ogles/GL/dot/dot_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_equal_equal_001_to_008,
- "conformance/ogles/GL/equal/equal_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_equal_equal_009_to_012,
- "conformance/ogles/GL/equal/equal_009_to_012.html");
-CONFORMANCE_TEST(conformance_ogles_GL_exp_exp_001_to_008,
- "conformance/ogles/GL/exp/exp_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_exp_exp_009_to_012,
- "conformance/ogles/GL/exp/exp_009_to_012.html");
-CONFORMANCE_TEST(conformance_ogles_GL_exp2_exp2_001_to_008,
- "conformance/ogles/GL/exp2/exp2_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_exp2_exp2_009_to_012,
- "conformance/ogles/GL/exp2/exp2_009_to_012.html");
-CONFORMANCE_TEST(conformance_ogles_GL_faceforward_faceforward_001_to_006,
- "conformance/ogles/GL/faceforward/faceforward_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_floor_floor_001_to_006,
- "conformance/ogles/GL/floor/floor_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_fract_fract_001_to_006,
- "conformance/ogles/GL/fract/fract_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_001_to_008,
- "conformance/ogles/GL/functions/functions_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_009_to_016,
- "conformance/ogles/GL/functions/functions_009_to_016.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_017_to_024,
- "conformance/ogles/GL/functions/functions_017_to_024.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_025_to_032,
- "conformance/ogles/GL/functions/functions_025_to_032.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_033_to_040,
- "conformance/ogles/GL/functions/functions_033_to_040.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_041_to_048,
- "conformance/ogles/GL/functions/functions_041_to_048.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_049_to_056,
- "conformance/ogles/GL/functions/functions_049_to_056.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_057_to_064,
- "conformance/ogles/GL/functions/functions_057_to_064.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_065_to_072,
- "conformance/ogles/GL/functions/functions_065_to_072.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_073_to_080,
- "conformance/ogles/GL/functions/functions_073_to_080.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_081_to_088,
- "conformance/ogles/GL/functions/functions_081_to_088.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_089_to_096,
- "conformance/ogles/GL/functions/functions_089_to_096.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_097_to_104,
- "conformance/ogles/GL/functions/functions_097_to_104.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_105_to_112,
- "conformance/ogles/GL/functions/functions_105_to_112.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_113_to_120,
- "conformance/ogles/GL/functions/functions_113_to_120.html");
-CONFORMANCE_TEST(conformance_ogles_GL_functions_functions_121_to_126,
- "conformance/ogles/GL/functions/functions_121_to_126.html");
-CONFORMANCE_TEST(conformance_ogles_GL_gl_FragCoord_gl_FragCoord_001_to_003,
- "conformance/ogles/GL/gl_FragCoord/gl_FragCoord_001_to_003.html");
-CONFORMANCE_TEST(conformance_ogles_GL_gl_FrontFacing_gl_FrontFacing_001_to_001,
- "conformance/ogles/GL/gl_FrontFacing/gl_FrontFacing_001_to_001.html");
-CONFORMANCE_TEST(conformance_ogles_GL_greaterThan_greaterThan_001_to_008,
- "conformance/ogles/GL/greaterThan/greaterThan_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_greaterThanEqual_greaterThanEqual_001_to_008,
- "conformance/ogles/GL/greaterThanEqual/greaterThanEqual_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_inversesqrt_inversesqrt_001_to_006,
- "conformance/ogles/GL/inversesqrt/inversesqrt_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_length_length_001_to_006,
- "conformance/ogles/GL/length/length_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_lessThan_lessThan_001_to_008,
- "conformance/ogles/GL/lessThan/lessThan_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_lessThanEqual_lessThanEqual_001_to_008,
- "conformance/ogles/GL/lessThanEqual/lessThanEqual_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_log_log_001_to_008,
- "conformance/ogles/GL/log/log_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_log_log_009_to_012,
- "conformance/ogles/GL/log/log_009_to_012.html");
-CONFORMANCE_TEST(conformance_ogles_GL_log2_log2_001_to_008,
- "conformance/ogles/GL/log2/log2_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_log2_log2_009_to_012,
- "conformance/ogles/GL/log2/log2_009_to_012.html");
-CONFORMANCE_TEST(conformance_ogles_GL_mat_mat_001_to_008,
- "conformance/ogles/GL/mat/mat_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_mat_mat_009_to_016,
- "conformance/ogles/GL/mat/mat_009_to_016.html");
-CONFORMANCE_TEST(conformance_ogles_GL_mat_mat_017_to_024,
- "conformance/ogles/GL/mat/mat_017_to_024.html");
-CONFORMANCE_TEST(conformance_ogles_GL_mat_mat_025_to_032,
- "conformance/ogles/GL/mat/mat_025_to_032.html");
-CONFORMANCE_TEST(conformance_ogles_GL_mat_mat_033_to_040,
- "conformance/ogles/GL/mat/mat_033_to_040.html");
-CONFORMANCE_TEST(conformance_ogles_GL_mat_mat_041_to_046,
- "conformance/ogles/GL/mat/mat_041_to_046.html");
-CONFORMANCE_TEST(conformance_ogles_GL_mat3_mat3_001_to_006,
- "conformance/ogles/GL/mat3/mat3_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_matrixCompMult_matrixCompMult_001_to_004,
- "conformance/ogles/GL/matrixCompMult/matrixCompMult_001_to_004.html");
-CONFORMANCE_TEST(conformance_ogles_GL_max_max_001_to_006,
- "conformance/ogles/GL/max/max_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_min_min_001_to_006,
- "conformance/ogles/GL/min/min_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_mix_mix_001_to_006,
- "conformance/ogles/GL/mix/mix_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_mod_mod_001_to_008,
- "conformance/ogles/GL/mod/mod_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_normalize_normalize_001_to_006,
- "conformance/ogles/GL/normalize/normalize_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_not_not_001_to_004,
- "conformance/ogles/GL/not/not_001_to_004.html");
-CONFORMANCE_TEST(conformance_ogles_GL_notEqual_notEqual_001_to_008,
- "conformance/ogles/GL/notEqual/notEqual_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_notEqual_notEqual_009_to_012,
- "conformance/ogles/GL/notEqual/notEqual_009_to_012.html");
-CONFORMANCE_TEST(conformance_ogles_GL_operators_operators_001_to_008,
- "conformance/ogles/GL/operators/operators_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_operators_operators_009_to_016,
- "conformance/ogles/GL/operators/operators_009_to_016.html");
-CONFORMANCE_TEST(conformance_ogles_GL_operators_operators_017_to_024,
- "conformance/ogles/GL/operators/operators_017_to_024.html");
-CONFORMANCE_TEST(conformance_ogles_GL_operators_operators_025_to_026,
- "conformance/ogles/GL/operators/operators_025_to_026.html");
-CONFORMANCE_TEST(conformance_ogles_GL_pow_pow_001_to_008,
- "conformance/ogles/GL/pow/pow_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_pow_pow_009_to_016,
- "conformance/ogles/GL/pow/pow_009_to_016.html");
-CONFORMANCE_TEST(conformance_ogles_GL_pow_pow_017_to_024,
- "conformance/ogles/GL/pow/pow_017_to_024.html");
-CONFORMANCE_TEST(conformance_ogles_GL_radians_radians_001_to_006,
- "conformance/ogles/GL/radians/radians_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_reflect_reflect_001_to_006,
- "conformance/ogles/GL/reflect/reflect_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_refract_refract_001_to_006,
- "conformance/ogles/GL/refract/refract_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_sign_sign_001_to_006,
- "conformance/ogles/GL/sign/sign_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_sin_sin_001_to_006,
- "conformance/ogles/GL/sin/sin_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_smoothstep_smoothstep_001_to_006,
- "conformance/ogles/GL/smoothstep/smoothstep_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_sqrt_sqrt_001_to_006,
- "conformance/ogles/GL/sqrt/sqrt_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_step_step_001_to_006,
- "conformance/ogles/GL/step/step_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_struct_struct_001_to_008,
- "conformance/ogles/GL/struct/struct_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_struct_struct_009_to_016,
- "conformance/ogles/GL/struct/struct_009_to_016.html");
-CONFORMANCE_TEST(conformance_ogles_GL_struct_struct_017_to_024,
- "conformance/ogles/GL/struct/struct_017_to_024.html");
-CONFORMANCE_TEST(conformance_ogles_GL_struct_struct_025_to_032,
- "conformance/ogles/GL/struct/struct_025_to_032.html");
-CONFORMANCE_TEST(conformance_ogles_GL_struct_struct_033_to_040,
- "conformance/ogles/GL/struct/struct_033_to_040.html");
-CONFORMANCE_TEST(conformance_ogles_GL_struct_struct_041_to_048,
- "conformance/ogles/GL/struct/struct_041_to_048.html");
-CONFORMANCE_TEST(conformance_ogles_GL_struct_struct_049_to_056,
- "conformance/ogles/GL/struct/struct_049_to_056.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_001_to_008,
- "conformance/ogles/GL/swizzlers/swizzlers_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_009_to_016,
- "conformance/ogles/GL/swizzlers/swizzlers_009_to_016.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_017_to_024,
- "conformance/ogles/GL/swizzlers/swizzlers_017_to_024.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_025_to_032,
- "conformance/ogles/GL/swizzlers/swizzlers_025_to_032.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_033_to_040,
- "conformance/ogles/GL/swizzlers/swizzlers_033_to_040.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_041_to_048,
- "conformance/ogles/GL/swizzlers/swizzlers_041_to_048.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_049_to_056,
- "conformance/ogles/GL/swizzlers/swizzlers_049_to_056.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_057_to_064,
- "conformance/ogles/GL/swizzlers/swizzlers_057_to_064.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_065_to_072,
- "conformance/ogles/GL/swizzlers/swizzlers_065_to_072.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_073_to_080,
- "conformance/ogles/GL/swizzlers/swizzlers_073_to_080.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_081_to_088,
- "conformance/ogles/GL/swizzlers/swizzlers_081_to_088.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_089_to_096,
- "conformance/ogles/GL/swizzlers/swizzlers_089_to_096.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_097_to_104,
- "conformance/ogles/GL/swizzlers/swizzlers_097_to_104.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_105_to_112,
- "conformance/ogles/GL/swizzlers/swizzlers_105_to_112.html");
-CONFORMANCE_TEST(conformance_ogles_GL_swizzlers_swizzlers_113_to_120,
- "conformance/ogles/GL/swizzlers/swizzlers_113_to_120.html");
-CONFORMANCE_TEST(conformance_ogles_GL_tan_tan_001_to_006,
- "conformance/ogles/GL/tan/tan_001_to_006.html");
-CONFORMANCE_TEST(conformance_ogles_GL_vec_vec_001_to_008,
- "conformance/ogles/GL/vec/vec_001_to_008.html");
-CONFORMANCE_TEST(conformance_ogles_GL_vec_vec_009_to_016,
- "conformance/ogles/GL/vec/vec_009_to_016.html");
-CONFORMANCE_TEST(conformance_ogles_GL_vec_vec_017_to_018,
- "conformance/ogles/GL/vec/vec_017_to_018.html");
-CONFORMANCE_TEST(conformance_ogles_GL_vec3_vec3_001_to_008,
- "conformance/ogles/GL/vec3/vec3_001_to_008.html");
-
-#endif // CONTENT_TEST_GPU_WEBGL_CONFORMANCE_TEST_LIST_AUTOGEN_H_
-
diff --git a/chromium/content/browser/histogram_message_filter.cc b/chromium/content/browser/histogram_message_filter.cc
index d46b96bc400..f44accdc349 100644
--- a/chromium/content/browser/histogram_message_filter.cc
+++ b/chromium/content/browser/histogram_message_filter.cc
@@ -16,10 +16,6 @@ namespace content {
HistogramMessageFilter::HistogramMessageFilter() {}
-void HistogramMessageFilter::OnChannelConnected(int32 peer_pid) {
- BrowserMessageFilter::OnChannelConnected(peer_pid);
-}
-
bool HistogramMessageFilter::OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) {
bool handled = true;
diff --git a/chromium/content/browser/histogram_message_filter.h b/chromium/content/browser/histogram_message_filter.h
index 2118d4a97a2..64c13cb6987 100644
--- a/chromium/content/browser/histogram_message_filter.h
+++ b/chromium/content/browser/histogram_message_filter.h
@@ -19,9 +19,6 @@ class HistogramMessageFilter : public BrowserMessageFilter {
HistogramMessageFilter();
// BrowserMessageFilter implementation.
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
-
- // BrowserMessageFilter implementation.
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) OVERRIDE;
diff --git a/chromium/content/browser/histogram_synchronizer.cc b/chromium/content/browser/histogram_synchronizer.cc
index 5a1e6f9a413..166172376cc 100644
--- a/chromium/content/browser/histogram_synchronizer.cc
+++ b/chromium/content/browser/histogram_synchronizer.cc
@@ -8,6 +8,7 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_delta_serialization.h"
#include "base/pickle.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
@@ -268,16 +269,10 @@ void HistogramSynchronizer::OnHistogramDataCollected(
const std::vector<std::string>& pickled_histograms) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RequestContext* request = RequestContext::GetRequestContext(sequence_number);
-
- for (std::vector<std::string>::const_iterator it = pickled_histograms.begin();
- it < pickled_histograms.end();
- ++it) {
- Pickle pickle(it->data(), it->size());
- PickleIterator iter(pickle);
- base::DeserializeHistogramAndAddSamples(&iter);
- }
+ base::HistogramDeltaSerialization::DeserializeAndAddSamples(
+ pickled_histograms);
+ RequestContext* request = RequestContext::GetRequestContext(sequence_number);
if (!request)
return;
diff --git a/chromium/content/browser/host_zoom_map_impl.cc b/chromium/content/browser/host_zoom_map_impl.cc
index 667db376efd..e4058c2e613 100644
--- a/chromium/content/browser/host_zoom_map_impl.cc
+++ b/chromium/content/browser/host_zoom_map_impl.cc
@@ -112,8 +112,7 @@ void HostZoomMapImpl::SetZoomLevelForHost(const std::string& host,
change.host = host;
change.zoom_level = level;
- for (size_t i = 0; i < zoom_level_changed_callbacks_.size(); i++)
- zoom_level_changed_callbacks_[i].Run(change);
+ zoom_level_changed_callbacks_.Notify(change);
}
void HostZoomMapImpl::SetZoomLevelForHostAndScheme(const std::string& scheme,
@@ -142,8 +141,7 @@ void HostZoomMapImpl::SetZoomLevelForHostAndScheme(const std::string& scheme,
change.scheme = scheme;
change.zoom_level = level;
- for (size_t i = 0; i < zoom_level_changed_callbacks_.size(); i++)
- zoom_level_changed_callbacks_[i].Run(change);
+ zoom_level_changed_callbacks_.Notify(change);
}
double HostZoomMapImpl::GetDefaultZoomLevel() const {
@@ -154,20 +152,10 @@ void HostZoomMapImpl::SetDefaultZoomLevel(double level) {
default_zoom_level_ = level;
}
-void HostZoomMapImpl::AddZoomLevelChangedCallback(
+scoped_ptr<HostZoomMap::Subscription>
+HostZoomMapImpl::AddZoomLevelChangedCallback(
const ZoomLevelChangedCallback& callback) {
- zoom_level_changed_callbacks_.push_back(callback);
-}
-
-void HostZoomMapImpl::RemoveZoomLevelChangedCallback(
- const ZoomLevelChangedCallback& callback) {
- for (size_t i = 0; i < zoom_level_changed_callbacks_.size(); i++) {
- if (zoom_level_changed_callbacks_[i].Equals(callback)) {
- zoom_level_changed_callbacks_.erase(
- zoom_level_changed_callbacks_.begin() + i);
- return;
- }
- }
+ return zoom_level_changed_callbacks_.Add(callback);
}
double HostZoomMapImpl::GetTemporaryZoomLevel(int render_process_id,
@@ -215,8 +203,7 @@ void HostZoomMapImpl::SetTemporaryZoomLevel(int render_process_id,
change.mode = HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM;
change.zoom_level = level;
- for (size_t i = 0; i < zoom_level_changed_callbacks_.size(); i++)
- zoom_level_changed_callbacks_[i].Run(change);
+ zoom_level_changed_callbacks_.Notify(change);
}
void HostZoomMapImpl::Observe(int type,
diff --git a/chromium/content/browser/host_zoom_map_impl.h b/chromium/content/browser/host_zoom_map_impl.h
index 216c83ebc17..eab10402b09 100644
--- a/chromium/content/browser/host_zoom_map_impl.h
+++ b/chromium/content/browser/host_zoom_map_impl.h
@@ -42,9 +42,7 @@ class CONTENT_EXPORT HostZoomMapImpl : public NON_EXPORTED_BASE(HostZoomMap),
double level) OVERRIDE;
virtual double GetDefaultZoomLevel() const OVERRIDE;
virtual void SetDefaultZoomLevel(double level) OVERRIDE;
- virtual void AddZoomLevelChangedCallback(
- const ZoomLevelChangedCallback& callback) OVERRIDE;
- virtual void RemoveZoomLevelChangedCallback(
+ virtual scoped_ptr<Subscription> AddZoomLevelChangedCallback(
const ZoomLevelChangedCallback& callback) OVERRIDE;
// Returns the temporary zoom level that's only valid for the lifetime of
@@ -75,7 +73,8 @@ class CONTENT_EXPORT HostZoomMapImpl : public NON_EXPORTED_BASE(HostZoomMap),
typedef std::map<std::string, HostZoomLevels> SchemeHostZoomLevels;
// Callbacks called when zoom level changes.
- std::vector<ZoomLevelChangedCallback> zoom_level_changed_callbacks_;
+ base::CallbackList<void(const ZoomLevelChange&)>
+ zoom_level_changed_callbacks_;
// Copy of the pref data, so that we can read it on the IO thread.
HostZoomLevels host_zoom_levels_;
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 70b3b52105b..e08a7b3c564 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -21,15 +21,28 @@
#include "content/common/indexed_db/indexed_db_key_path.h"
#include "content/common/indexed_db/indexed_db_key_range.h"
#include "third_party/WebKit/public/platform/WebIDBTypes.h"
+#include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h"
#include "third_party/leveldatabase/env_chromium.h"
+#include "webkit/common/database/database_identifier.h"
using base::StringPiece;
-// TODO(jsbell): Make blink push the version during the open() call.
-static const uint32 kWireVersion = 2;
-
namespace content {
+namespace {
+
+static std::string ComputeOriginIdentifier(const GURL& origin_url) {
+ return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1";
+}
+
+static base::FilePath ComputeFileName(const GURL& origin_url) {
+ return base::FilePath()
+ .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url))
+ .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
+}
+
+} // namespace
+
static const int64 kKeyGeneratorInitialNumber =
1; // From the IndexedDB specification.
@@ -144,7 +157,7 @@ static void PutVarInt(LevelDBTransaction* transaction,
template <typename DBOrTransaction>
WARN_UNUSED_RESULT static bool GetString(DBOrTransaction* db,
const StringPiece& key,
- string16* found_string,
+ base::string16* found_string,
bool* found) {
std::string result;
*found = false;
@@ -159,7 +172,7 @@ WARN_UNUSED_RESULT static bool GetString(DBOrTransaction* db,
static void PutString(LevelDBTransaction* transaction,
const StringPiece& key,
- const string16& value) {
+ const base::string16& value) {
std::string buffer;
EncodeString(value, &buffer);
transaction->Put(key, &buffer);
@@ -209,7 +222,8 @@ WARN_UNUSED_RESULT static bool IsSchemaKnown(LevelDBDatabase* db, bool* known) {
return true;
}
- const uint32 latest_known_data_version = kWireVersion;
+ const uint32 latest_known_data_version =
+ blink::kSerializedScriptValueVersion;
int64 db_data_version = 0;
ok = GetInt(db, DataVersionKey::Encode(), &db_data_version, &found);
if (!ok)
@@ -231,7 +245,8 @@ WARN_UNUSED_RESULT static bool IsSchemaKnown(LevelDBDatabase* db, bool* known) {
WARN_UNUSED_RESULT static bool SetUpMetadata(
LevelDBDatabase* db,
const std::string& origin_identifier) {
- const uint32 latest_known_data_version = kWireVersion;
+ const uint32 latest_known_data_version =
+ blink::kSerializedScriptValueVersion;
const std::string schema_version_key = SchemaVersionKey::Encode();
const std::string data_version_key = DataVersionKey::Encode();
@@ -287,7 +302,7 @@ WARN_UNUSED_RESULT static bool SetUpMetadata(
if (db_schema_version < 2) {
db_schema_version = 2;
PutInt(transaction.get(), schema_version_key, db_schema_version);
- db_data_version = kWireVersion;
+ db_data_version = blink::kSerializedScriptValueVersion;
PutInt(transaction.get(), data_version_key, db_data_version);
}
}
@@ -360,13 +375,13 @@ class DefaultLevelDBFactory : public LevelDBFactory {
};
IndexedDBBackingStore::IndexedDBBackingStore(
- const std::string& identifier,
+ const GURL& origin_url,
scoped_ptr<LevelDBDatabase> db,
scoped_ptr<LevelDBComparator> comparator)
- : identifier_(identifier),
+ : origin_url_(origin_url),
+ origin_identifier_(ComputeOriginIdentifier(origin_url)),
db_(db.Pass()),
- comparator_(comparator.Pass()),
- weak_factory_(this) {}
+ comparator_(comparator.Pass()) {}
IndexedDBBackingStore::~IndexedDBBackingStore() {
// db_'s destructor uses comparator_. The order of destruction is important.
@@ -387,115 +402,69 @@ IndexedDBBackingStore::RecordIdentifier::~RecordIdentifier() {}
IndexedDBBackingStore::Cursor::CursorOptions::CursorOptions() {}
IndexedDBBackingStore::Cursor::CursorOptions::~CursorOptions() {}
-enum IndexedDBLevelDBBackingStoreOpenResult {
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_SUCCESS,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_CLEANUP_DESTROY_FAILED,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_DISK_FULL,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_NO_RECOVERY,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
+enum IndexedDBBackingStoreOpenResult {
+ INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS,
+ INDEXED_DB_BACKING_STORE_OPEN_SUCCESS,
+ INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY,
+ INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA,
+ INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_DESTROY_FAILED,
+ INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED,
+ INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS,
+ INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
+ INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
+ INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
+ INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
+ INDEXED_DB_BACKING_STORE_OPEN_DISK_FULL_DEPRECATED,
+ INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
+ INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY,
+ INDEXED_DB_BACKING_STORE_OPEN_MAX,
};
-// TODO(dgrogan): Move to leveldb_env.
-bool RecoveryCouldBeFruitful(leveldb::Status status) {
- leveldb_env::MethodID method;
- int error = -1;
- leveldb_env::ErrorParsingResult result = leveldb_env::ParseMethodAndError(
- status.ToString().c_str(), &method, &error);
- switch (result) {
- case leveldb_env::NONE:
- return true;
- case leveldb_env::METHOD_AND_PFE: {
- base::PlatformFileError pfe = static_cast<base::PlatformFileError>(error);
- switch (pfe) {
- case base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED:
- case base::PLATFORM_FILE_ERROR_NO_MEMORY:
- case base::PLATFORM_FILE_ERROR_NO_SPACE:
- return false;
- default:
- return true;
- }
- }
- case leveldb_env::METHOD_AND_ERRNO: {
- switch (error) {
- case EMFILE:
- case ENOMEM:
- case ENOSPC:
- return false;
- default:
- return true;
- }
- }
- default:
- return true;
- }
- return true;
-}
-
+// static
scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
- const std::string& origin_identifier,
+ const GURL& origin_url,
const base::FilePath& path_base,
- const std::string& file_identifier,
- WebKit::WebIDBCallbacks::DataLoss* data_loss,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_message,
bool* disk_full) {
- *data_loss = WebKit::WebIDBCallbacks::DataLossNone;
+ *data_loss = blink::WebIDBDataLossNone;
DefaultLevelDBFactory leveldb_factory;
- return IndexedDBBackingStore::Open(origin_identifier,
+ return IndexedDBBackingStore::Open(origin_url,
path_base,
- file_identifier,
data_loss,
+ data_loss_message,
disk_full,
&leveldb_factory);
}
-scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
- const std::string& origin_identifier,
- const base::FilePath& path_base,
- const std::string& file_identifier,
- WebKit::WebIDBCallbacks::DataLoss* data_loss,
- bool* is_disk_full,
- LevelDBFactory* leveldb_factory) {
- IDB_TRACE("IndexedDBBackingStore::Open");
- DCHECK(!path_base.empty());
- *data_loss = WebKit::WebIDBCallbacks::DataLossNone;
- *is_disk_full = false;
-
- scoped_ptr<LevelDBComparator> comparator(new Comparator());
+static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) {
+ if (origin_url.host() == "docs.google.com")
+ return ".Docs";
+ return std::string();
+}
- if (!IsStringASCII(path_base.AsUTF8Unsafe())) {
- base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII);
- }
- if (!file_util::CreateDirectory(path_base)) {
- LOG(ERROR) << "Unable to create IndexedDB database path "
- << path_base.AsUTF8Unsafe();
- base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY);
- return scoped_refptr<IndexedDBBackingStore>();
+static void HistogramOpenStatus(IndexedDBBackingStoreOpenResult result,
+ const GURL& origin_url) {
+ UMA_HISTOGRAM_ENUMERATION("WebCore.IndexedDB.BackingStore.OpenStatus",
+ result,
+ INDEXED_DB_BACKING_STORE_OPEN_MAX);
+ const std::string suffix = OriginToCustomHistogramSuffix(origin_url);
+ // Data from the WebCore.IndexedDB.BackingStore.OpenStatus histogram is used
+ // to generate a graph. So as not to alter the meaning of that graph,
+ // continue to collect all stats there (above) but also now collect docs stats
+ // separately (below).
+ if (!suffix.empty()) {
+ base::LinearHistogram::FactoryGet(
+ "WebCore.IndexedDB.BackingStore.OpenStatus" + suffix,
+ 1,
+ INDEXED_DB_BACKING_STORE_OPEN_MAX,
+ INDEXED_DB_BACKING_STORE_OPEN_MAX + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag)->Add(result);
}
+}
- base::FilePath identifier_path =
- base::FilePath().AppendASCII(origin_identifier)
- .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
-
- int limit = file_util::GetMaximumPathComponentLength(path_base);
+static bool IsPathTooLong(const base::FilePath& leveldb_dir) {
+ int limit = file_util::GetMaximumPathComponentLength(leveldb_dir.DirName());
if (limit == -1) {
DLOG(WARNING) << "GetMaximumPathComponentLength returned -1";
// In limited testing, ChromeOS returns 143, other OSes 255.
@@ -505,110 +474,117 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
limit = 255;
#endif
}
- if (identifier_path.value().length() > static_cast<uint32_t>(limit)) {
- DLOG(WARNING) << "Path component length ("
- << identifier_path.value().length() << ") exceeds maximum ("
- << limit << ") allowed by this filesystem.";
+ size_t component_length = leveldb_dir.BaseName().value().length();
+ if (component_length > static_cast<uint32_t>(limit)) {
+ DLOG(WARNING) << "Path component length (" << component_length
+ << ") exceeds maximum (" << limit
+ << ") allowed by this filesystem.";
const int min = 140;
const int max = 300;
const int num_buckets = 12;
- // TODO(dgrogan): Remove WebCore from these histogram names.
UMA_HISTOGRAM_CUSTOM_COUNTS(
"WebCore.IndexedDB.BackingStore.OverlyLargeOriginLength",
- identifier_path.value().length(),
+ component_length,
min,
max,
num_buckets);
- // TODO(dgrogan): Translate the FactoryGet calls to
- // UMA_HISTOGRAM_ENUMERATION. FactoryGet was the most direct translation
- // from the WebCore code.
- base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG);
+ return true;
+ }
+ return false;
+}
+
+// static
+scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
+ const GURL& origin_url,
+ const base::FilePath& path_base,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_message,
+ bool* is_disk_full,
+ LevelDBFactory* leveldb_factory) {
+ IDB_TRACE("IndexedDBBackingStore::Open");
+ DCHECK(!path_base.empty());
+ *data_loss = blink::WebIDBDataLossNone;
+ *data_loss_message = "";
+ *is_disk_full = false;
+
+ scoped_ptr<LevelDBComparator> comparator(new Comparator());
+
+ if (!IsStringASCII(path_base.AsUTF8Unsafe())) {
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
+ origin_url);
+ }
+ if (!base::CreateDirectory(path_base)) {
+ LOG(ERROR) << "Unable to create IndexedDB database path "
+ << path_base.AsUTF8Unsafe();
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY,
+ origin_url);
return scoped_refptr<IndexedDBBackingStore>();
}
- base::FilePath file_path = path_base.Append(identifier_path);
+ const base::FilePath file_path =
+ path_base.Append(ComputeFileName(origin_url));
+
+ if (IsPathTooLong(file_path)) {
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
+ origin_url);
+ return scoped_refptr<IndexedDBBackingStore>();
+ }
scoped_ptr<LevelDBDatabase> db;
leveldb::Status status = leveldb_factory->OpenLevelDB(
file_path, comparator.get(), &db, is_disk_full);
- if (!status.ok() && leveldb_env::IndicatesDiskFull(status)) {
- DCHECK(!db);
- *is_disk_full = true;
+ DCHECK(!db == !status.ok());
+ if (!status.ok()) {
+ if (leveldb_env::IndicatesDiskFull(status)) {
+ *is_disk_full = true;
+ } else if (leveldb_env::IsCorruption(status)) {
+ *data_loss = blink::WebIDBDataLossTotal;
+ *data_loss_message = leveldb_env::GetCorruptionMessage(status);
+ }
}
+ bool is_schema_known = false;
if (db) {
- bool known = false;
- bool ok = IsSchemaKnown(db.get(), &known);
+ bool ok = IsSchemaKnown(db.get(), &is_schema_known);
if (!ok) {
LOG(ERROR) << "IndexedDB had IO error checking schema, treating it as "
"failure to open";
- base::Histogram::FactoryGet(
- "WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA);
+ HistogramOpenStatus(
+ INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
+ origin_url);
db.reset();
- } else if (!known) {
+ *data_loss = blink::WebIDBDataLossTotal;
+ *data_loss_message = "I/O error checking schema";
+ } else if (!is_schema_known) {
LOG(ERROR) << "IndexedDB backing store had unknown schema, treating it "
"as failure to open";
- base::Histogram::FactoryGet(
- "WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA);
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA,
+ origin_url);
db.reset();
+ *data_loss = blink::WebIDBDataLossTotal;
+ *data_loss_message = "Unknown schema";
}
}
+ DCHECK(status.ok() || !is_schema_known || leveldb_env::IsIOError(status) ||
+ leveldb_env::IsCorruption(status));
+
if (db) {
- base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_SUCCESS);
- } else if (!RecoveryCouldBeFruitful(status)) {
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_SUCCESS, origin_url);
+ } else if (leveldb_env::IsIOError(status)) {
LOG(ERROR) << "Unable to open backing store, not trying to recover - "
<< status.ToString();
- base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_NO_RECOVERY);
- return scoped_refptr<IndexedDBBackingStore>();
- } else if (*is_disk_full) {
- LOG(ERROR) << "Unable to open backing store - disk is full.";
- base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_DISK_FULL);
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY, origin_url);
return scoped_refptr<IndexedDBBackingStore>();
} else {
+ DCHECK(!is_schema_known || leveldb_env::IsCorruption(status));
LOG(ERROR) << "IndexedDB backing store open failed, attempting cleanup";
- *data_loss = WebKit::WebIDBCallbacks::DataLossTotal;
bool success = leveldb_factory->DestroyLevelDB(file_path);
if (!success) {
LOG(ERROR) << "IndexedDB backing store cleanup failed";
- base::Histogram::FactoryGet(
- "WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_CLEANUP_DESTROY_FAILED);
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_DESTROY_FAILED,
+ origin_url);
return scoped_refptr<IndexedDBBackingStore>();
}
@@ -616,45 +592,34 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
leveldb_factory->OpenLevelDB(file_path, comparator.get(), &db, NULL);
if (!db) {
LOG(ERROR) << "IndexedDB backing store reopen after recovery failed";
- base::Histogram::FactoryGet(
- "WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED);
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED,
+ origin_url);
return scoped_refptr<IndexedDBBackingStore>();
}
- base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS);
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS,
+ origin_url);
}
if (!db) {
NOTREACHED();
- base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR);
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
+ origin_url);
return scoped_refptr<IndexedDBBackingStore>();
}
- return Create(file_identifier, db.Pass(), comparator.Pass());
+ return Create(origin_url, db.Pass(), comparator.Pass());
}
+// static
scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
- const std::string& file_identifier) {
+ const GURL& origin_url) {
DefaultLevelDBFactory leveldb_factory;
- return IndexedDBBackingStore::OpenInMemory(file_identifier, &leveldb_factory);
+ return IndexedDBBackingStore::OpenInMemory(origin_url, &leveldb_factory);
}
+// static
scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
- const std::string& file_identifier,
+ const GURL& origin_url,
LevelDBFactory* leveldb_factory) {
IDB_TRACE("IndexedDBBackingStore::OpenInMemory");
@@ -663,44 +628,37 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
LevelDBDatabase::OpenInMemory(comparator.get());
if (!db) {
LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed.";
- base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MEMORY_FAILED);
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
+ origin_url);
return scoped_refptr<IndexedDBBackingStore>();
}
- base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
- 1,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
- INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag)
- ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS);
+ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url);
- return Create(file_identifier, db.Pass(), comparator.Pass());
+ return Create(origin_url, db.Pass(), comparator.Pass());
}
+// static
scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
- const std::string& identifier,
+ const GURL& origin_url,
scoped_ptr<LevelDBDatabase> db,
scoped_ptr<LevelDBComparator> comparator) {
// TODO(jsbell): Handle comparator name changes.
- scoped_refptr<IndexedDBBackingStore> backing_store(
- new IndexedDBBackingStore(identifier, db.Pass(), comparator.Pass()));
- if (!SetUpMetadata(backing_store->db_.get(), identifier))
+ scoped_refptr<IndexedDBBackingStore> backing_store(
+ new IndexedDBBackingStore(origin_url, db.Pass(), comparator.Pass()));
+ if (!SetUpMetadata(backing_store->db_.get(),
+ backing_store->origin_identifier_))
return scoped_refptr<IndexedDBBackingStore>();
return backing_store;
}
-std::vector<string16> IndexedDBBackingStore::GetDatabaseNames() {
- std::vector<string16> found_names;
+std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames() {
+ std::vector<base::string16> found_names;
const std::string start_key =
- DatabaseNameKey::EncodeMinKeyForOrigin(identifier_);
+ DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_);
const std::string stop_key =
- DatabaseNameKey::EncodeStopKeyForOrigin(identifier_);
+ DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_);
DCHECK(found_names.empty());
@@ -720,10 +678,10 @@ std::vector<string16> IndexedDBBackingStore::GetDatabaseNames() {
}
bool IndexedDBBackingStore::GetIDBDatabaseMetaData(
- const string16& name,
+ const base::string16& name,
IndexedDBDatabaseMetadata* metadata,
bool* found) {
- const std::string key = DatabaseNameKey::Encode(identifier_, name);
+ const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
*found = false;
bool ok = GetInt(db_.get(), key, &metadata->id, found);
@@ -775,15 +733,13 @@ bool IndexedDBBackingStore::GetIDBDatabaseMetaData(
return true;
}
-WARN_UNUSED_RESULT static bool GetNewDatabaseId(LevelDBDatabase* db,
+WARN_UNUSED_RESULT static bool GetNewDatabaseId(LevelDBTransaction* transaction,
int64* new_id) {
- scoped_refptr<LevelDBTransaction> transaction = new LevelDBTransaction(db);
-
*new_id = -1;
int64 max_database_id = -1;
bool found = false;
- bool ok = GetInt(
- transaction.get(), MaxDatabaseIdKey::Encode(), &max_database_id, &found);
+ bool ok =
+ GetInt(transaction, MaxDatabaseIdKey::Encode(), &max_database_id, &found);
if (!ok) {
INTERNAL_READ_ERROR(GET_NEW_DATABASE_ID);
return false;
@@ -794,20 +750,20 @@ WARN_UNUSED_RESULT static bool GetNewDatabaseId(LevelDBDatabase* db,
DCHECK_GE(max_database_id, 0);
int64 database_id = max_database_id + 1;
- PutInt(transaction.get(), MaxDatabaseIdKey::Encode(), database_id);
- if (!transaction->Commit()) {
- INTERNAL_WRITE_ERROR(GET_NEW_DATABASE_ID);
- return false;
- }
+ PutInt(transaction, MaxDatabaseIdKey::Encode(), database_id);
*new_id = database_id;
return true;
}
-bool IndexedDBBackingStore::CreateIDBDatabaseMetaData(const string16& name,
- const string16& version,
- int64 int_version,
- int64* row_id) {
- bool ok = GetNewDatabaseId(db_.get(), row_id);
+bool IndexedDBBackingStore::CreateIDBDatabaseMetaData(
+ const base::string16& name,
+ const base::string16& version,
+ int64 int_version,
+ int64* row_id) {
+ scoped_refptr<LevelDBTransaction> transaction =
+ new LevelDBTransaction(db_.get());
+
+ bool ok = GetNewDatabaseId(transaction.get(), row_id);
if (!ok)
return false;
DCHECK_GE(*row_id, 0);
@@ -815,10 +771,9 @@ bool IndexedDBBackingStore::CreateIDBDatabaseMetaData(const string16& name,
if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
- scoped_refptr<LevelDBTransaction> transaction =
- new LevelDBTransaction(db_.get());
- PutInt(
- transaction.get(), DatabaseNameKey::Encode(identifier_, name), *row_id);
+ PutInt(transaction.get(),
+ DatabaseNameKey::Encode(origin_identifier_, name),
+ *row_id);
PutString(
transaction.get(),
DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION),
@@ -841,24 +796,13 @@ bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion(
if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
DCHECK_GE(int_version, 0) << "int_version was " << int_version;
- PutVarInt(Transaction::LevelDBTransactionFrom(transaction),
+ PutVarInt(transaction->transaction(),
DatabaseMetaDataKey::Encode(row_id,
DatabaseMetaDataKey::USER_INT_VERSION),
int_version);
return true;
}
-bool IndexedDBBackingStore::UpdateIDBDatabaseMetaData(
- IndexedDBBackingStore::Transaction* transaction,
- int64 row_id,
- const string16& version) {
- PutString(
- Transaction::LevelDBTransactionFrom(transaction),
- DatabaseMetaDataKey::Encode(row_id, DatabaseMetaDataKey::USER_VERSION),
- version);
- return true;
-}
-
static void DeleteRange(LevelDBTransaction* transaction,
const std::string& begin,
const std::string& end) {
@@ -868,7 +812,7 @@ static void DeleteRange(LevelDBTransaction* transaction,
transaction->Remove(it->Key());
}
-bool IndexedDBBackingStore::DeleteDatabase(const string16& name) {
+bool IndexedDBBackingStore::DeleteDatabase(const base::string16& name) {
IDB_TRACE("IndexedDBBackingStore::DeleteDatabase");
scoped_ptr<LevelDBWriteOnlyTransaction> transaction =
LevelDBWriteOnlyTransaction::Create(db_.get());
@@ -891,7 +835,7 @@ bool IndexedDBBackingStore::DeleteDatabase(const string16& name) {
it->Next())
transaction->Remove(it->Key());
- const std::string key = DatabaseNameKey::Encode(identifier_, name);
+ const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
transaction->Remove(key);
if (!transaction->Commit()) {
@@ -952,7 +896,7 @@ bool IndexedDBBackingStore::GetObjectStores(
// TODO(jsbell): Do this by direct key lookup rather than iteration, to
// simplify.
- string16 object_store_name;
+ base::string16 object_store_name;
{
StringPiece slice(it->Value());
if (!DecodeString(&slice, &object_store_name) || !slice.empty())
@@ -1041,7 +985,7 @@ bool IndexedDBBackingStore::GetObjectStores(
// (2) Later, null vs. string vs. array was stored in the key_path itself.
// So this check is only relevant for string-type key_paths.
if (!has_key_path &&
- (key_path.type() == WebKit::WebIDBKeyPathTypeString &&
+ (key_path.type() == blink::WebIDBKeyPathTypeString &&
!key_path.string().empty())) {
INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
break;
@@ -1106,14 +1050,13 @@ bool IndexedDBBackingStore::CreateObjectStore(
IndexedDBBackingStore::Transaction* transaction,
int64 database_id,
int64 object_store_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath& key_path,
bool auto_increment) {
IDB_TRACE("IndexedDBBackingStore::CreateObjectStore");
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
if (!SetMaxObjectStoreId(leveldb_transaction, database_id, object_store_id))
return false;
@@ -1159,10 +1102,9 @@ bool IndexedDBBackingStore::DeleteObjectStore(
IDB_TRACE("IndexedDBBackingStore::DeleteObjectStore");
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
- string16 object_store_name;
+ base::string16 object_store_name;
bool found = false;
bool ok = GetString(
leveldb_transaction,
@@ -1206,8 +1148,7 @@ bool IndexedDBBackingStore::GetRecord(
IDB_TRACE("IndexedDBBackingStore::GetRecord");
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
const std::string leveldb_key =
ObjectStoreDataKey::Encode(database_id, object_store_id, key);
@@ -1282,8 +1223,7 @@ bool IndexedDBBackingStore::PutRecord(
return false;
DCHECK(key.IsValid());
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
int64 version = -1;
bool ok = GetNewVersionNumber(
leveldb_transaction, database_id, object_store_id, &version);
@@ -1318,14 +1258,12 @@ bool IndexedDBBackingStore::ClearObjectStore(
IDB_TRACE("IndexedDBBackingStore::ClearObjectStore");
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
const std::string start_key =
KeyPrefix(database_id, object_store_id).Encode();
const std::string stop_key =
KeyPrefix(database_id, object_store_id + 1).Encode();
- DeleteRange(leveldb_transaction, start_key, stop_key);
+ DeleteRange(transaction->transaction(), start_key, stop_key);
return true;
}
@@ -1337,8 +1275,7 @@ bool IndexedDBBackingStore::DeleteRecord(
IDB_TRACE("IndexedDBBackingStore::DeleteRecord");
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
const std::string object_store_data_key = ObjectStoreDataKey::Encode(
database_id, object_store_id, record_identifier.primary_key());
@@ -1357,8 +1294,7 @@ bool IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
int64* key_generator_current_number) {
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
const std::string key_generator_current_number_key =
ObjectStoreMetaDataKey::Encode(
@@ -1408,7 +1344,7 @@ bool IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
return false;
}
scoped_ptr<IndexedDBKey> user_key = data_key.user_key();
- if (user_key->type() == WebKit::WebIDBKeyTypeNumber) {
+ if (user_key->type() == blink::WebIDBKeyTypeNumber) {
int64 n = static_cast<int64>(user_key->number());
if (n > max_numeric_key)
max_numeric_key = n;
@@ -1427,8 +1363,6 @@ bool IndexedDBBackingStore::MaybeUpdateKeyGeneratorCurrentNumber(
bool check_current) {
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
if (check_current) {
int64 current_number;
@@ -1445,7 +1379,8 @@ bool IndexedDBBackingStore::MaybeUpdateKeyGeneratorCurrentNumber(
database_id,
object_store_id,
ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
- PutInt(leveldb_transaction, key_generator_current_number_key, new_number);
+ PutInt(
+ transaction->transaction(), key_generator_current_number_key, new_number);
return true;
}
@@ -1460,13 +1395,11 @@ bool IndexedDBBackingStore::KeyExistsInObjectStore(
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return false;
*found = false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
const std::string leveldb_key =
ObjectStoreDataKey::Encode(database_id, object_store_id, key);
std::string data;
- bool ok = leveldb_transaction->Get(leveldb_key, &data, found);
+ bool ok = transaction->transaction()->Get(leveldb_key, &data, found);
if (!ok) {
INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE);
return false;
@@ -1541,7 +1474,7 @@ bool IndexedDBBackingStore::GetIndexes(
// TODO(jsbell): Do this by direct key lookup rather than iteration, to
// simplify.
int64 index_id = meta_data_key.IndexId();
- string16 index_name;
+ base::string16 index_name;
{
StringPiece slice(it->Value());
if (!DecodeString(&slice, &index_name) || !slice.empty())
@@ -1621,15 +1554,14 @@ bool IndexedDBBackingStore::CreateIndex(
int64 database_id,
int64 object_store_id,
int64 index_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath& key_path,
bool is_unique,
bool is_multi_entry) {
IDB_TRACE("IndexedDBBackingStore::CreateIndex");
if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
return false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
if (!SetMaxIndexId(
leveldb_transaction, database_id, object_store_id, index_id))
return false;
@@ -1658,8 +1590,7 @@ bool IndexedDBBackingStore::DeleteIndex(
IDB_TRACE("IndexedDBBackingStore::DeleteIndex");
if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
return false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
const std::string index_meta_data_start =
IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0);
@@ -1687,9 +1618,6 @@ bool IndexedDBBackingStore::PutIndexDataForRecord(
if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
return false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
-
std::string encoded_key;
EncodeIDBKey(key, &encoded_key);
@@ -1705,7 +1633,7 @@ bool IndexedDBBackingStore::PutIndexDataForRecord(
EncodeVarInt(record_identifier.version(), &data);
data.append(record_identifier.primary_key());
- leveldb_transaction->Put(index_data_key, &data);
+ transaction->transaction()->Put(index_data_key, &data);
return true;
}
@@ -1777,8 +1705,7 @@ bool IndexedDBBackingStore::FindKeyInIndex(
DCHECK(found_encoded_primary_key->empty());
*found = false;
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
const std::string leveldb_key =
IndexDataKey::Encode(database_id, object_store_id, index_id, key);
scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator();
@@ -1929,7 +1856,11 @@ bool IndexedDBBackingStore::Cursor::Advance(uint32 count) {
}
bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
+ const IndexedDBKey* primary_key,
IteratorState next_state) {
+ DCHECK(!key || key->IsValid());
+ DCHECK(!primary_key || primary_key->IsValid());
+
// TODO(alecflett): avoid a copy here?
IndexedDBKey previous_key = current_key_ ? *current_key_ : IndexedDBKey();
@@ -1945,8 +1876,14 @@ bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
for (;;) {
if (next_state == SEEK) {
// TODO(jsbell): Optimize seeking for reverse cursors as well.
- if (first_iteration && key && key->IsValid() && forward) {
- iterator_->Seek(EncodeKey(*key));
+ if (first_iteration && key && forward) {
+ std::string leveldb_key;
+ if (primary_key) {
+ leveldb_key = EncodeKey(*key, *primary_key);
+ } else {
+ leveldb_key = EncodeKey(*key);
+ }
+ iterator_->Seek(leveldb_key);
first_iteration = false;
} else if (forward) {
iterator_->Next();
@@ -1987,11 +1924,17 @@ bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
if (!LoadCurrentRow())
continue;
- if (key && key->IsValid()) {
+ if (key) {
if (forward) {
+ if (primary_key && current_key_->IsEqual(*key) &&
+ this->primary_key().IsLessThan(*primary_key))
+ continue;
if (current_key_->IsLessThan(*key))
continue;
} else {
+ if (primary_key && key->IsEqual(*current_key_) &&
+ primary_key->IsLessThan(this->primary_key()))
+ continue;
if (key->IsLessThan(*current_key_))
continue;
}
@@ -2080,7 +2023,7 @@ class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor {
}
// IndexedDBBackingStore::Cursor
- virtual std::string* Value() OVERRIDE {
+ virtual std::string* value() OVERRIDE {
NOTREACHED();
return NULL;
}
@@ -2091,6 +2034,11 @@ class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor {
return ObjectStoreDataKey::Encode(
cursor_options_.database_id, cursor_options_.object_store_id, key);
}
+ virtual std::string EncodeKey(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key) OVERRIDE {
+ NOTREACHED();
+ return std::string();
+ }
private:
explicit ObjectStoreKeyCursorImpl(const ObjectStoreKeyCursorImpl* other)
@@ -2132,7 +2080,7 @@ class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor {
virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); }
// IndexedDBBackingStore::Cursor
- virtual std::string* Value() OVERRIDE { return &current_value_; }
+ virtual std::string* value() OVERRIDE { return &current_value_; }
virtual bool LoadCurrentRow() OVERRIDE;
protected:
@@ -2140,6 +2088,11 @@ class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor {
return ObjectStoreDataKey::Encode(
cursor_options_.database_id, cursor_options_.object_store_id, key);
}
+ virtual std::string EncodeKey(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key) OVERRIDE {
+ NOTREACHED();
+ return std::string();
+ }
private:
explicit ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other)
@@ -2185,15 +2138,15 @@ class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor {
virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); }
// IndexedDBBackingStore::Cursor
- virtual std::string* Value() OVERRIDE {
+ virtual std::string* value() OVERRIDE {
NOTREACHED();
return NULL;
}
virtual const IndexedDBKey& primary_key() const OVERRIDE {
return *primary_key_;
}
- virtual const IndexedDBBackingStore::RecordIdentifier& RecordIdentifier()
- const {
+ virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
+ const OVERRIDE {
NOTREACHED();
return record_identifier_;
}
@@ -2206,6 +2159,14 @@ class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor {
cursor_options_.index_id,
key);
}
+ virtual std::string EncodeKey(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key) OVERRIDE {
+ return IndexDataKey::Encode(cursor_options_.database_id,
+ cursor_options_.object_store_id,
+ cursor_options_.index_id,
+ key,
+ primary_key);
+ }
private:
explicit IndexKeyCursorImpl(const IndexKeyCursorImpl* other)
@@ -2284,12 +2245,12 @@ class IndexCursorImpl : public IndexedDBBackingStore::Cursor {
virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); }
// IndexedDBBackingStore::Cursor
- virtual std::string* Value() OVERRIDE { return &current_value_; }
+ virtual std::string* value() OVERRIDE { return &current_value_; }
virtual const IndexedDBKey& primary_key() const OVERRIDE {
return *primary_key_;
}
- virtual const IndexedDBBackingStore::RecordIdentifier& RecordIdentifier()
- const {
+ virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
+ const OVERRIDE {
NOTREACHED();
return record_identifier_;
}
@@ -2302,6 +2263,14 @@ class IndexCursorImpl : public IndexedDBBackingStore::Cursor {
cursor_options_.index_id,
key);
}
+ virtual std::string EncodeKey(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key) OVERRIDE {
+ return IndexDataKey::Encode(cursor_options_.database_id,
+ cursor_options_.object_store_id,
+ cursor_options_.index_id,
+ key,
+ primary_key);
+ }
private:
explicit IndexCursorImpl(const IndexCursorImpl* other)
@@ -2518,8 +2487,7 @@ IndexedDBBackingStore::OpenObjectStoreCursor(
const IndexedDBKeyRange& range,
indexed_db::CursorDirection direction) {
IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreCursor");
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
if (!ObjectStoreCursorOptions(leveldb_transaction,
database_id,
@@ -2544,8 +2512,7 @@ IndexedDBBackingStore::OpenObjectStoreKeyCursor(
const IndexedDBKeyRange& range,
indexed_db::CursorDirection direction) {
IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor");
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
if (!ObjectStoreCursorOptions(leveldb_transaction,
database_id,
@@ -2571,8 +2538,7 @@ IndexedDBBackingStore::OpenIndexKeyCursor(
const IndexedDBKeyRange& range,
indexed_db::CursorDirection direction) {
IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor");
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
if (!IndexCursorOptions(leveldb_transaction,
database_id,
@@ -2599,8 +2565,7 @@ IndexedDBBackingStore::OpenIndexCursor(
const IndexedDBKeyRange& range,
indexed_db::CursorDirection direction) {
IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor");
- LevelDBTransaction* leveldb_transaction =
- IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
+ LevelDBTransaction* leveldb_transaction = transaction->transaction();
IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
if (!IndexCursorOptions(leveldb_transaction,
database_id,
diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store.h b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
index 3948411de24..890f95ebdfc 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
@@ -12,7 +12,7 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
#include "content/browser/indexed_db/indexed_db.h"
#include "content/browser/indexed_db/indexed_db_metadata.h"
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
@@ -21,8 +21,8 @@
#include "content/common/indexed_db/indexed_db_key.h"
#include "content/common/indexed_db/indexed_db_key_path.h"
#include "content/common/indexed_db/indexed_db_key_range.h"
-#include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
+#include "url/gurl.h"
namespace content {
@@ -32,11 +32,10 @@ class LevelDBDatabase;
class LevelDBFactory {
public:
virtual ~LevelDBFactory() {}
- virtual leveldb::Status OpenLevelDB(
- const base::FilePath& file_name,
- const LevelDBComparator* comparator,
- scoped_ptr<LevelDBDatabase>* db,
- bool* is_disk_full) = 0;
+ virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
+ const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
+ bool* is_disk_full) = 0;
virtual bool DestroyLevelDB(const base::FilePath& file_name) = 0;
};
@@ -45,46 +44,44 @@ class CONTENT_EXPORT IndexedDBBackingStore
public:
class CONTENT_EXPORT Transaction;
+ const GURL& origin_url() const { return origin_url_; }
+ base::OneShotTimer<IndexedDBBackingStore>* close_timer() {
+ return &close_timer_;
+ }
+
static scoped_refptr<IndexedDBBackingStore> Open(
- const std::string& origin_identifier,
+ const GURL& origin_url,
const base::FilePath& path_base,
- const std::string& file_identifier,
- WebKit::WebIDBCallbacks::DataLoss* data_loss,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_message,
bool* disk_full);
static scoped_refptr<IndexedDBBackingStore> Open(
- const std::string& origin_identifier,
+ const GURL& origin_url,
const base::FilePath& path_base,
- const std::string& file_identifier,
- WebKit::WebIDBCallbacks::DataLoss* data_loss,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_message,
bool* disk_full,
LevelDBFactory* factory);
static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
- const std::string& file_identifier);
+ const GURL& origin_url);
static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
- const std::string& file_identifier,
+ const GURL& origin_url,
LevelDBFactory* factory);
- base::WeakPtr<IndexedDBBackingStore> GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
- }
- virtual std::vector<string16> GetDatabaseNames();
- virtual bool GetIDBDatabaseMetaData(const string16& name,
+ virtual std::vector<base::string16> GetDatabaseNames();
+ virtual bool GetIDBDatabaseMetaData(const base::string16& name,
IndexedDBDatabaseMetadata* metadata,
bool* success) WARN_UNUSED_RESULT;
- virtual bool CreateIDBDatabaseMetaData(const string16& name,
- const string16& version,
+ virtual bool CreateIDBDatabaseMetaData(const base::string16& name,
+ const base::string16& version,
int64 int_version,
int64* row_id);
- virtual bool UpdateIDBDatabaseMetaData(
- IndexedDBBackingStore::Transaction* transaction,
- int64 row_id,
- const string16& version);
virtual bool UpdateIDBDatabaseIntVersion(
IndexedDBBackingStore::Transaction* transaction,
int64 row_id,
int64 int_version);
- virtual bool DeleteDatabase(const string16& name);
+ virtual bool DeleteDatabase(const base::string16& name);
bool GetObjectStores(int64 database_id,
IndexedDBDatabaseMetadata::ObjectStoreMap* map)
@@ -93,7 +90,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBBackingStore::Transaction* transaction,
int64 database_id,
int64 object_store_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath& key_path,
bool auto_increment);
virtual bool DeleteObjectStore(
@@ -163,7 +160,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
int64 database_id,
int64 object_store_id,
int64 index_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath& key_path,
bool is_unique,
bool is_multi_entry) WARN_UNUSED_RESULT;
@@ -217,14 +214,19 @@ class CONTENT_EXPORT IndexedDBBackingStore
};
const IndexedDBKey& key() const { return *current_key_; }
- bool Continue() { return Continue(NULL, SEEK); }
- bool Continue(const IndexedDBKey* key, IteratorState state);
+ bool Continue() { return Continue(NULL, NULL, SEEK); }
+ bool Continue(const IndexedDBKey* key, IteratorState state) {
+ return Continue(key, NULL, state);
+ }
+ bool Continue(const IndexedDBKey* key,
+ const IndexedDBKey* primary_key,
+ IteratorState state);
bool Advance(uint32 count);
bool FirstSeek();
virtual Cursor* Clone() = 0;
virtual const IndexedDBKey& primary_key() const;
- virtual std::string* Value() = 0;
+ virtual std::string* value() = 0;
virtual const RecordIdentifier& record_identifier() const;
virtual bool LoadCurrentRow() = 0;
@@ -234,6 +236,8 @@ class CONTENT_EXPORT IndexedDBBackingStore
explicit Cursor(const IndexedDBBackingStore::Cursor* other);
virtual std::string EncodeKey(const IndexedDBKey& key) = 0;
+ virtual std::string EncodeKey(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key) = 0;
bool IsPastBounds() const;
bool HaveEnteredRange() const;
@@ -275,19 +279,16 @@ class CONTENT_EXPORT IndexedDBBackingStore
class Transaction {
public:
explicit Transaction(IndexedDBBackingStore* backing_store);
- ~Transaction();
- void Begin();
- bool Commit();
- void Rollback();
+ virtual ~Transaction();
+ virtual void Begin();
+ virtual bool Commit();
+ virtual void Rollback();
void Reset() {
backing_store_ = NULL;
transaction_ = NULL;
}
- static LevelDBTransaction* LevelDBTransactionFrom(
- Transaction* transaction) {
- return transaction->transaction_;
- }
+ LevelDBTransaction* transaction() { return transaction_; }
private:
IndexedDBBackingStore* backing_store_;
@@ -295,7 +296,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
};
protected:
- IndexedDBBackingStore(const std::string& identifier,
+ IndexedDBBackingStore(const GURL& origin_url,
scoped_ptr<LevelDBDatabase> db,
scoped_ptr<LevelDBComparator> comparator);
virtual ~IndexedDBBackingStore();
@@ -303,7 +304,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
private:
static scoped_refptr<IndexedDBBackingStore> Create(
- const std::string& identifier,
+ const GURL& origin_url,
scoped_ptr<LevelDBDatabase> db,
scoped_ptr<LevelDBComparator> comparator);
@@ -319,11 +320,19 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBObjectStoreMetadata::IndexMap* map)
WARN_UNUSED_RESULT;
- std::string identifier_;
+ const GURL origin_url_;
+
+ // The origin identifier is a key prefix unique to the origin used in the
+ // leveldb backing store to partition data by origin. It is a normalized
+ // version of the origin URL with a versioning suffix appended, e.g.
+ // "http_localhost_81@1" Since only one origin is stored per backing store
+ // this is redundant but necessary for backwards compatibility; the suffix
+ // provides for future flexibility.
+ const std::string origin_identifier_;
scoped_ptr<LevelDBDatabase> db_;
scoped_ptr<LevelDBComparator> comparator_;
- base::WeakPtrFactory<IndexedDBBackingStore> weak_factory_;
+ base::OneShotTimer<IndexedDBBackingStore> close_timer_;
};
} // namespace content
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 50fb2f07a5d..d3e82964af4 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
@@ -4,18 +4,12 @@
#include "content/browser/indexed_db/indexed_db_backing_store.h"
-#include "base/file_util.h"
-#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
-#include "content/browser/indexed_db/indexed_db_factory.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
#include "third_party/WebKit/public/platform/WebIDBTypes.h"
-#include "url/gurl.h"
-#include "webkit/common/database/database_identifier.h"
namespace content {
@@ -25,14 +19,14 @@ class IndexedDBBackingStoreTest : public testing::Test {
public:
IndexedDBBackingStoreTest() {}
virtual void SetUp() {
- std::string file_identifier;
- backing_store_ = IndexedDBBackingStore::OpenInMemory(file_identifier);
+ const GURL origin("http://localhost:81");
+ backing_store_ = IndexedDBBackingStore::OpenInMemory(origin);
// useful keys and values during tests
m_value1 = "value1";
m_value2 = "value2";
m_value3 = "value3";
- m_key1 = IndexedDBKey(99, WebKit::WebIDBKeyTypeNumber);
+ m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber);
m_key2 = IndexedDBKey(ASCIIToUTF16("key2"));
m_key3 = IndexedDBKey(ASCIIToUTF16("key3"));
}
@@ -47,6 +41,9 @@ class IndexedDBBackingStoreTest : public testing::Test {
std::string m_value1;
std::string m_value2;
std::string m_value3;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest);
};
TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
@@ -239,19 +236,19 @@ TEST_F(IndexedDBBackingStoreTest, InvalidIds) {
}
TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
- const string16 database_name(ASCIIToUTF16("db1"));
+ const base::string16 database_name(ASCIIToUTF16("db1"));
int64 database_id;
- const string16 version(ASCIIToUTF16("old_string_version"));
+ const base::string16 version(ASCIIToUTF16("old_string_version"));
const int64 int_version = 9;
const int64 object_store_id = 99;
- const string16 object_store_name(ASCIIToUTF16("object_store1"));
+ const base::string16 object_store_name(ASCIIToUTF16("object_store1"));
const bool auto_increment = true;
const IndexedDBKeyPath object_store_key_path(
ASCIIToUTF16("object_store_key"));
const int64 index_id = 999;
- const string16 index_name(ASCIIToUTF16("index1"));
+ const base::string16 index_name(ASCIIToUTF16("index1"));
const bool unique = true;
const bool multi_entry = true;
const IndexedDBKeyPath index_key_path(ASCIIToUTF16("index_key"));
@@ -319,147 +316,6 @@ TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
}
}
-class MockIDBFactory : public IndexedDBFactory {
- public:
- scoped_refptr<IndexedDBBackingStore> TestOpenBackingStore(
- const GURL& origin,
- const base::FilePath& data_directory) {
- WebKit::WebIDBCallbacks::DataLoss data_loss =
- WebKit::WebIDBCallbacks::DataLossNone;
- bool disk_full;
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(webkit_database::GetIdentifierFromOrigin(origin),
- data_directory,
- &data_loss,
- &disk_full);
- EXPECT_EQ(WebKit::WebIDBCallbacks::DataLossNone, data_loss);
- return backing_store;
- }
-
- private:
- virtual ~MockIDBFactory() {}
-};
-
-TEST(IndexedDBFactoryTest, BackingStoreLifetime) {
- GURL origin1("http://localhost:81");
- GURL origin2("http://localhost:82");
-
- scoped_refptr<MockIDBFactory> factory = new MockIDBFactory();
-
- base::ScopedTempDir temp_directory;
- ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
- scoped_refptr<IndexedDBBackingStore> disk_store1 =
- factory->TestOpenBackingStore(origin1, temp_directory.path());
- EXPECT_TRUE(disk_store1->HasOneRef());
-
- scoped_refptr<IndexedDBBackingStore> disk_store2 =
- factory->TestOpenBackingStore(origin1, temp_directory.path());
- EXPECT_EQ(disk_store1.get(), disk_store2.get());
- EXPECT_FALSE(disk_store2->HasOneRef());
-
- scoped_refptr<IndexedDBBackingStore> disk_store3 =
- factory->TestOpenBackingStore(origin2, temp_directory.path());
- EXPECT_TRUE(disk_store3->HasOneRef());
- EXPECT_FALSE(disk_store1->HasOneRef());
-
- disk_store2 = NULL;
- EXPECT_TRUE(disk_store1->HasOneRef());
-}
-
-TEST(IndexedDBFactoryTest, MemoryBackingStoreLifetime) {
- GURL origin1("http://localhost:81");
- GURL origin2("http://localhost:82");
-
- scoped_refptr<MockIDBFactory> factory = new MockIDBFactory();
- scoped_refptr<IndexedDBBackingStore> mem_store1 =
- factory->TestOpenBackingStore(origin1, base::FilePath());
- EXPECT_FALSE(mem_store1->HasOneRef()); // mem_store1 and factory
-
- scoped_refptr<IndexedDBBackingStore> mem_store2 =
- factory->TestOpenBackingStore(origin1, base::FilePath());
- EXPECT_EQ(mem_store1.get(), mem_store2.get());
- EXPECT_FALSE(mem_store1->HasOneRef()); // mem_store1, 2 and factory
- EXPECT_FALSE(mem_store2->HasOneRef()); // mem_store1, 2 and factory
-
- scoped_refptr<IndexedDBBackingStore> mem_store3 =
- factory->TestOpenBackingStore(origin2, base::FilePath());
- EXPECT_FALSE(mem_store1->HasOneRef()); // mem_store1, 2 and factory
- EXPECT_FALSE(mem_store3->HasOneRef()); // mem_store3 and factory
-
- factory = NULL;
- EXPECT_FALSE(mem_store1->HasOneRef()); // mem_store1 and 2
- EXPECT_FALSE(mem_store2->HasOneRef()); // mem_store1 and 2
- EXPECT_TRUE(mem_store3->HasOneRef());
-
- mem_store2 = NULL;
- EXPECT_TRUE(mem_store1->HasOneRef());
-}
-
-TEST(IndexedDBFactoryTest, RejectLongOrigins) {
- base::ScopedTempDir temp_directory;
- ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
- const base::FilePath base_path = temp_directory.path();
- scoped_refptr<MockIDBFactory> factory = new MockIDBFactory();
-
- int limit = file_util::GetMaximumPathComponentLength(base_path);
- EXPECT_GT(limit, 0);
-
- std::string origin(limit + 1, 'x');
- GURL too_long_origin("http://" + origin + ":81/");
- scoped_refptr<IndexedDBBackingStore> diskStore1 =
- factory->TestOpenBackingStore(too_long_origin, base_path);
- EXPECT_FALSE(diskStore1);
-
- GURL ok_origin("http://someorigin.com:82/");
- scoped_refptr<IndexedDBBackingStore> diskStore2 =
- factory->TestOpenBackingStore(ok_origin, base_path);
- EXPECT_TRUE(diskStore2);
-}
-
-class DiskFullFactory : public IndexedDBFactory {
- private:
- virtual ~DiskFullFactory() {}
- virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
- const std::string& origin_identifier,
- const base::FilePath& data_directory,
- WebKit::WebIDBCallbacks::DataLoss* data_loss,
- bool* disk_full) OVERRIDE {
- *disk_full = true;
- return scoped_refptr<IndexedDBBackingStore>();
- }
-};
-
-class LookingForQuotaErrorMockCallbacks : public IndexedDBCallbacks {
- public:
- LookingForQuotaErrorMockCallbacks()
- : IndexedDBCallbacks(NULL, 0, 0), error_called_(false) {}
- virtual void OnError(const IndexedDBDatabaseError& error) OVERRIDE {
- error_called_ = true;
- EXPECT_EQ(WebKit::WebIDBDatabaseExceptionQuotaError, error.code());
- }
- private:
- virtual ~LookingForQuotaErrorMockCallbacks() {
- EXPECT_TRUE(error_called_);
- }
- bool error_called_;
-};
-
-TEST(IndexedDBFactoryTest, QuotaErrorOnDiskFull) {
- scoped_refptr<DiskFullFactory> factory = new DiskFullFactory;
- scoped_refptr<LookingForQuotaErrorMockCallbacks> callbacks =
- new LookingForQuotaErrorMockCallbacks;
- scoped_refptr<IndexedDBDatabaseCallbacks> dummy_database_callbacks =
- new IndexedDBDatabaseCallbacks(NULL, 0, 0);
- const string16 name(ASCIIToUTF16("name"));
- factory->Open(name,
- 1, /* version */
- 2, /* transaction_id */
- callbacks,
- dummy_database_callbacks,
- "origin",
- base::FilePath(FILE_PATH_LITERAL("/dummy")));
-}
-
} // namespace
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
index fb6d0cd2795..e979168e76d 100644
--- a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -43,9 +43,9 @@ class IndexedDBBrowserTest : public ContentBrowserTest {
// a #pass or #fail ref.
Shell* the_browser = incognito ? CreateOffTheRecordBrowser() : shell();
- LOG(INFO) << "Navigating to URL and blocking.";
+ VLOG(0) << "Navigating to URL and blocking.";
NavigateToURLBlockUntilNavigationsComplete(the_browser, test_url, 2);
- LOG(INFO) << "Navigation done.";
+ VLOG(0) << "Navigation done.";
std::string result =
the_browser->web_contents()->GetLastCommittedURL().ref();
if (result != "pass") {
@@ -66,7 +66,7 @@ class IndexedDBBrowserTest : public ContentBrowserTest {
if (hash)
url = GURL(url.spec() + hash);
- string16 expected_title16(ASCIIToUTF16(expected_string));
+ base::string16 expected_title16(ASCIIToUTF16(expected_string));
TitleWatcher title_watcher(shell->web_contents(), expected_title16);
NavigateToURL(shell, url);
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
@@ -168,11 +168,6 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, TransactionTest) {
SimpleTest(GetTestUrl("indexeddb", "transaction_test.html"));
}
-// http://crbug.com/239366
-IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_ValueSizeTest) {
- SimpleTest(GetTestUrl("indexeddb", "value_size_test.html"));
-}
-
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CallbackAccounting) {
SimpleTest(GetTestUrl("indexeddb", "callback_accounting.html"));
}
@@ -239,7 +234,7 @@ static void CopyLevelDBToProfile(Shell* shell,
// If we don't create the destination directory first, the contents of the
// leveldb directory are copied directly into profile/IndexedDB instead of
// profile/IndexedDB/file__0.xxx/
- ASSERT_TRUE(file_util::CreateDirectory(dest));
+ ASSERT_TRUE(base::CreateDirectory(dest));
const bool kRecursive = true;
ASSERT_TRUE(base::CopyDirectory(test_data_dir,
context->data_path(),
@@ -334,7 +329,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithMissingSSTFile,
DestroyTest) {
int64 original_size = RequestDiskUsage();
EXPECT_GT(original_size, 0);
- SimpleTest(GetTestUrl("indexeddb", "open_bad_db.html"));
+ SimpleTest(GetTestUrl("indexeddb", "open_missing_table.html"));
int64 new_size = RequestDiskUsage();
EXPECT_NE(original_size, new_size);
}
@@ -347,7 +342,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, LevelDBLogFileTest) {
base::FilePath log_file_path =
GetContext()->data_path().Append(leveldb_dir).Append(log_file);
int64 size;
- EXPECT_TRUE(file_util::GetFileSize(log_file_path, &size));
+ EXPECT_TRUE(base::GetFileSize(log_file_path, &size));
EXPECT_GT(size, 0);
}
@@ -404,7 +399,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ConnectionsClosedOnTabClose) {
NavigateAndWaitForTitle(new_shell, "version_change_blocked.html", "#tab2",
"setVersion(3) blocked");
- string16 expected_title16(ASCIIToUTF16("setVersion(3) complete"));
+ base::string16 expected_title16(ASCIIToUTF16("setVersion(3) complete"));
TitleWatcher title_watcher(new_shell->web_contents(), expected_title16);
base::KillProcess(
@@ -426,7 +421,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ForceCloseEventTest) {
GetContext(),
GURL("file:///")));
- string16 expected_title16(ASCIIToUTF16("connection closed"));
+ base::string16 expected_title16(ASCIIToUTF16("connection closed"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
index 46270db7531..755551cec89 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -11,16 +11,14 @@
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_metadata.h"
+#include "content/common/indexed_db/indexed_db_constants.h"
#include "content/common/indexed_db/indexed_db_messages.h"
#include "webkit/browser/quota/quota_manager.h"
-using WebKit::WebIDBCallbacks;
-
namespace content {
namespace {
const int32 kNoCursor = -1;
-const int32 kNoDatabase = -1;
const int32 kNoDatabaseCallbacks = -1;
const int64 kNoTransaction = -1;
}
@@ -73,7 +71,7 @@ void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) {
dispatcher_host_ = NULL;
}
-void IndexedDBCallbacks::OnSuccess(const std::vector<string16>& value) {
+void IndexedDBCallbacks::OnSuccess(const std::vector<base::string16>& value) {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
@@ -81,7 +79,7 @@ void IndexedDBCallbacks::OnSuccess(const std::vector<string16>& value) {
DCHECK_EQ(kNoDatabase, ipc_database_id_);
DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
- std::vector<string16> list;
+ std::vector<base::string16> list;
for (unsigned i = 0; i < value.size(); ++i)
list.push_back(value[i]);
@@ -107,7 +105,8 @@ void IndexedDBCallbacks::OnUpgradeNeeded(
int64 old_version,
scoped_ptr<IndexedDBConnection> connection,
const IndexedDBDatabaseMetadata& metadata,
- WebIDBCallbacks::DataLoss data_loss) {
+ blink::WebIDBDataLoss data_loss,
+ std::string data_loss_message) {
DCHECK(dispatcher_host_.get());
DCHECK_EQ(kNoCursor, ipc_cursor_id_);
@@ -129,6 +128,7 @@ void IndexedDBCallbacks::OnUpgradeNeeded(
params.old_version = old_version;
params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata);
params.data_loss = data_loss;
+ params.data_loss_message = data_loss_message;
dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params));
}
@@ -143,8 +143,9 @@ void IndexedDBCallbacks::OnSuccess(scoped_ptr<IndexedDBConnection> connection,
scoped_refptr<IndexedDBCallbacks> self(this);
- int32 ipc_object_id = ipc_database_id_;
- if (ipc_object_id == kNoDatabase) {
+ int32 ipc_object_id = kNoDatabase;
+ // Only register if the connection was not previously sent in OnUpgradeNeeded.
+ if (ipc_database_id_ == kNoDatabase) {
ipc_object_id = dispatcher_host_->Add(
connection.release(), ipc_thread_id_, origin_url_);
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.h b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
index 8ab8ae40aaf..048b563bf2f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.h
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
@@ -17,7 +17,6 @@
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
#include "content/common/indexed_db/indexed_db_key.h"
#include "content/common/indexed_db/indexed_db_key_path.h"
-#include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
#include "url/gurl.h"
namespace content {
@@ -52,7 +51,7 @@ class CONTENT_EXPORT IndexedDBCallbacks
virtual void OnError(const IndexedDBDatabaseError& error);
// IndexedDBFactory::GetDatabaseNames
- virtual void OnSuccess(const std::vector<string16>& string);
+ virtual void OnSuccess(const std::vector<base::string16>& string);
// IndexedDBFactory::Open / DeleteDatabase
virtual void OnBlocked(int64 existing_version);
@@ -62,7 +61,8 @@ class CONTENT_EXPORT IndexedDBCallbacks
int64 old_version,
scoped_ptr<IndexedDBConnection> connection,
const content::IndexedDBDatabaseMetadata& metadata,
- WebKit::WebIDBCallbacks::DataLoss data_loss);
+ blink::WebIDBDataLoss data_loss,
+ std::string data_loss_message);
virtual void OnSuccess(scoped_ptr<IndexedDBConnection> connection,
const content::IndexedDBDatabaseMetadata& metadata);
diff --git a/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
index 6b60a4f9291..d9445415959 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
@@ -61,24 +61,26 @@ class MockLevelDBFactory : public LevelDBFactory {
};
TEST(IndexedDBIOErrorTest, CleanUpTest) {
- std::string origin_identifier("http_localhost_81");
+ const GURL origin("http://localhost:81");
base::ScopedTempDir temp_directory;
ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
const base::FilePath path = temp_directory.path();
- std::string dummy_file_identifier;
MockLevelDBFactory mock_leveldb_factory;
- WebKit::WebIDBCallbacks::DataLoss data_loss =
- WebKit::WebIDBCallbacks::DataLossNone;
+ blink::WebIDBDataLoss data_loss =
+ blink::WebIDBDataLossNone;
+ std::string data_loss_message;
bool disk_full = false;
scoped_refptr<IndexedDBBackingStore> backing_store =
- IndexedDBBackingStore::Open(origin_identifier,
+ IndexedDBBackingStore::Open(origin,
path,
- dummy_file_identifier,
&data_loss,
+ &data_loss_message,
&disk_full,
&mock_leveldb_factory);
}
+// TODO(dgrogan): Remove expect_destroy if we end up not using it again. It is
+// currently set to false in all 4 calls below.
template <class T>
class MockErrorLevelDBFactory : public LevelDBFactory {
public:
@@ -110,50 +112,50 @@ class MockErrorLevelDBFactory : public LevelDBFactory {
};
TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
- std::string origin_identifier("http_localhost_81");
+ const GURL origin("http://localhost:81");
base::ScopedTempDir temp_directory;
ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
const base::FilePath path = temp_directory.path();
- std::string dummy_file_identifier;
- WebKit::WebIDBCallbacks::DataLoss data_loss =
- WebKit::WebIDBCallbacks::DataLossNone;
+ blink::WebIDBDataLoss data_loss =
+ blink::WebIDBDataLossNone;
+ std::string data_loss_reason;
bool disk_full = false;
MockErrorLevelDBFactory<int> mock_leveldb_factory(ENOSPC, false);
scoped_refptr<IndexedDBBackingStore> backing_store =
- IndexedDBBackingStore::Open(origin_identifier,
+ IndexedDBBackingStore::Open(origin,
path,
- dummy_file_identifier,
&data_loss,
+ &data_loss_reason,
&disk_full,
&mock_leveldb_factory);
MockErrorLevelDBFactory<base::PlatformFileError> mock_leveldb_factory2(
base::PLATFORM_FILE_ERROR_NO_MEMORY, false);
scoped_refptr<IndexedDBBackingStore> backing_store2 =
- IndexedDBBackingStore::Open(origin_identifier,
+ IndexedDBBackingStore::Open(origin,
path,
- dummy_file_identifier,
&data_loss,
+ &data_loss_reason,
&disk_full,
&mock_leveldb_factory2);
- MockErrorLevelDBFactory<int> mock_leveldb_factory3(EIO, true);
+ MockErrorLevelDBFactory<int> mock_leveldb_factory3(EIO, false);
scoped_refptr<IndexedDBBackingStore> backing_store3 =
- IndexedDBBackingStore::Open(origin_identifier,
+ IndexedDBBackingStore::Open(origin,
path,
- dummy_file_identifier,
&data_loss,
+ &data_loss_reason,
&disk_full,
&mock_leveldb_factory3);
MockErrorLevelDBFactory<base::PlatformFileError> mock_leveldb_factory4(
- base::PLATFORM_FILE_ERROR_FAILED, true);
+ base::PLATFORM_FILE_ERROR_FAILED, false);
scoped_refptr<IndexedDBBackingStore> backing_store4 =
- IndexedDBBackingStore::Open(origin_identifier,
+ IndexedDBBackingStore::Open(origin,
path,
- dummy_file_identifier,
&data_loss,
+ &data_loss_reason,
&disk_full,
&mock_leveldb_factory4);
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_connection.cc b/chromium/content/browser/indexed_db/indexed_db_connection.cc
index fc19c0c75a8..81139895366 100644
--- a/chromium/content/browser/indexed_db/indexed_db_connection.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_connection.cc
@@ -16,16 +16,22 @@ IndexedDBConnection::~IndexedDBConnection() {}
void IndexedDBConnection::Close() {
if (!callbacks_)
return;
- database_->Close(this);
+ database_->Close(this, false /* forced */);
+ database_ = NULL;
callbacks_ = NULL;
}
void IndexedDBConnection::ForceClose() {
if (!callbacks_)
return;
- database_->Close(this);
+ database_->Close(this, true /* forced */);
+ database_ = NULL;
callbacks_->OnForcedClose();
callbacks_ = NULL;
}
-} // namespace WebKit
+bool IndexedDBConnection::IsConnected() {
+ return database_.get() != NULL;
+}
+
+} // namespace blink
diff --git a/chromium/content/browser/indexed_db/indexed_db_connection.h b/chromium/content/browser/indexed_db/indexed_db_connection.h
index f6d01f6122a..e4ed928257d 100644
--- a/chromium/content/browser/indexed_db/indexed_db_connection.h
+++ b/chromium/content/browser/indexed_db/indexed_db_connection.h
@@ -19,14 +19,16 @@ class CONTENT_EXPORT IndexedDBConnection {
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks);
virtual ~IndexedDBConnection();
+ // These methods are virtual to allow subclassing in unit tests.
virtual void ForceClose();
virtual void Close();
+ virtual bool IsConnected();
IndexedDBDatabase* database() { return database_; }
IndexedDBDatabaseCallbacks* callbacks() { return callbacks_; }
private:
- // Only NULL in unit tests.
+ // NULL in some unit tests, and after the connection is closed.
scoped_refptr<IndexedDBDatabase> database_;
// The callbacks_ member is cleared when the connection is closed.
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 6c4dd84ed79..e8ab70bbbf4 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -23,6 +23,7 @@
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
#include "content/browser/indexed_db/indexed_db_factory.h"
#include "content/browser/indexed_db/indexed_db_quota_client.h"
+#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/indexed_db_info.h"
@@ -106,6 +107,7 @@ IndexedDBContextImpl::IndexedDBContextImpl(
special_storage_policy_(special_storage_policy),
quota_manager_proxy_(quota_manager_proxy),
task_runner_(task_runner) {
+ IDB_TRACE("init");
if (!data_path.empty())
data_path_ = data_path.Append(kIndexedDBDirectory);
if (quota_manager_proxy) {
@@ -119,7 +121,7 @@ IndexedDBFactory* IndexedDBContextImpl::GetIDBFactory() {
// Prime our cache of origins with existing databases so we can
// detect when dbs are newly created.
GetOriginSet();
- factory_ = new IndexedDBFactory();
+ factory_ = new IndexedDBFactory(this);
}
return factory_;
}
@@ -186,8 +188,7 @@ ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
if (factory_) {
std::vector<IndexedDBDatabase*> databases =
- factory_->GetOpenDatabasesForOrigin(
- webkit_database::GetIdentifierFromOrigin(origin_url));
+ factory_->GetOpenDatabasesForOrigin(origin_url);
// TODO(jsbell): Sort by name?
scoped_ptr<ListValue> database_list(new ListValue());
@@ -220,19 +221,19 @@ ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
const char* kModes[] = { "readonly", "readwrite", "versionchange" };
transaction_info->SetString("mode", kModes[transaction->mode()]);
- switch (transaction->queue_status()) {
+ switch (transaction->state()) {
case IndexedDBTransaction::CREATED:
- transaction_info->SetString("status", "created");
- break;
- case IndexedDBTransaction::BLOCKED:
transaction_info->SetString("status", "blocked");
break;
- case IndexedDBTransaction::UNBLOCKED:
- if (transaction->IsRunning())
+ case IndexedDBTransaction::STARTED:
+ if (transaction->diagnostics().tasks_scheduled > 0)
transaction_info->SetString("status", "running");
else
transaction_info->SetString("status", "started");
break;
+ case IndexedDBTransaction::FINISHED:
+ transaction_info->SetString("status", "finished");
+ break;
}
transaction_info->SetDouble(
@@ -245,16 +246,16 @@ ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
transaction->id()));
transaction_info->SetDouble(
"age",
- (base::Time::Now() - transaction->creation_time())
+ (base::Time::Now() - transaction->diagnostics().creation_time)
.InMillisecondsF());
transaction_info->SetDouble(
"runtime",
- (base::Time::Now() - transaction->start_time())
+ (base::Time::Now() - transaction->diagnostics().start_time)
.InMillisecondsF());
- transaction_info->SetDouble("tasks_scheduled",
- transaction->tasks_scheduled());
- transaction_info->SetDouble("tasks_completed",
- transaction->tasks_completed());
+ transaction_info->SetDouble(
+ "tasks_scheduled", transaction->diagnostics().tasks_scheduled);
+ transaction_info->SetDouble(
+ "tasks_completed", transaction->diagnostics().tasks_completed);
scoped_ptr<ListValue> scope(new ListValue());
for (std::set<int64>::const_iterator scope_it =
@@ -296,7 +297,7 @@ base::Time IndexedDBContextImpl::GetOriginLastModified(const GURL& origin_url) {
return base::Time();
base::FilePath idb_directory = GetFilePath(origin_url);
base::PlatformFileInfo file_info;
- if (!file_util::GetFileInfo(idb_directory, &file_info))
+ if (!base::GetFileInfo(idb_directory, &file_info))
return base::Time();
return file_info.last_modified;
}
@@ -309,8 +310,17 @@ void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) {
base::FilePath idb_directory = GetFilePath(origin_url);
EnsureDiskUsageCacheInitialized(origin_url);
- const bool recursive = true;
- bool deleted = base::DeleteFile(idb_directory, recursive);
+ bool deleted = LevelDBDatabase::Destroy(idb_directory);
+ if (!deleted) {
+ LOG(WARNING) << "Failed to delete LevelDB database: "
+ << idb_directory.AsUTF8Unsafe();
+ } else {
+ // LevelDB does not delete empty directories; work around this.
+ // TODO(jsbell): Remove when upstream bug is fixed.
+ // https://code.google.com/p/leveldb/issues/detail?id=209
+ const bool kNonRecursive = false;
+ base::DeleteFile(idb_directory, kNonRecursive);
+ }
QueryDiskAndUpdateQuotaUsage(origin_url);
if (deleted) {
@@ -320,7 +330,7 @@ void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) {
}
}
-void IndexedDBContextImpl::ForceClose(const GURL& origin_url) {
+void IndexedDBContextImpl::ForceClose(const GURL origin_url) {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
if (data_path_.empty() || !IsInOriginSet(origin_url))
return;
@@ -331,12 +341,15 @@ void IndexedDBContextImpl::ForceClose(const GURL& origin_url) {
while (it != connections.end()) {
// Remove before closing so callbacks don't double-erase
IndexedDBConnection* connection = *it;
+ DCHECK(connection->IsConnected());
connections.erase(it++);
connection->ForceClose();
}
DCHECK_EQ(connections_[origin_url].size(), 0UL);
connections_.erase(origin_url);
}
+ if (factory_)
+ factory_->ForceClose(origin_url);
}
size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) {
@@ -350,7 +363,7 @@ size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) {
return connections_[origin_url].size();
}
-base::FilePath IndexedDBContextImpl::GetFilePath(const GURL& origin_url) {
+base::FilePath IndexedDBContextImpl::GetFilePath(const GURL& origin_url) const {
std::string origin_id = webkit_database::GetIdentifierFromOrigin(origin_url);
return GetIndexedDBFilePath(origin_id);
}
@@ -434,12 +447,9 @@ quota::QuotaManagerProxy* IndexedDBContextImpl::quota_manager_proxy() {
IndexedDBContextImpl::~IndexedDBContextImpl() {
if (factory_) {
- IndexedDBFactory* factory = factory_;
- factory->AddRef();
+ TaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&IndexedDBFactory::ContextDestroyed, factory_));
factory_ = NULL;
- if (!task_runner_->ReleaseSoon(FROM_HERE, factory)) {
- factory->Release();
- }
}
if (data_path_.empty())
@@ -472,8 +482,7 @@ base::FilePath IndexedDBContextImpl::GetIndexedDBFilePath(
int64 IndexedDBContextImpl::ReadUsageFromDisk(const GURL& origin_url) const {
if (data_path_.empty())
return 0;
- std::string origin_id = webkit_database::GetIdentifierFromOrigin(origin_url);
- base::FilePath file_path = GetIndexedDBFilePath(origin_id);
+ base::FilePath file_path = GetFilePath(origin_url);
return base::ComputeDirectorySize(file_path);
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_context_impl.h b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
index 3c76465e6bf..d6b12429440 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
@@ -55,10 +55,8 @@ class CONTENT_EXPORT IndexedDBContextImpl
// IndexedDBContext implementation:
virtual base::TaskRunner* TaskRunner() const OVERRIDE;
- virtual std::vector<GURL> GetAllOrigins() OVERRIDE;
virtual std::vector<IndexedDBInfo> GetAllOriginsInfo() OVERRIDE;
virtual int64 GetOriginDiskUsage(const GURL& origin_url) OVERRIDE;
- virtual base::Time GetOriginLastModified(const GURL& origin_url) OVERRIDE;
virtual void DeleteForOrigin(const GURL& origin_url) OVERRIDE;
virtual base::FilePath GetFilePathForTesting(
const std::string& origin_id) const OVERRIDE;
@@ -74,9 +72,13 @@ class CONTENT_EXPORT IndexedDBContextImpl
quota::QuotaManagerProxy* quota_manager_proxy();
+ std::vector<GURL> GetAllOrigins();
+ base::Time GetOriginLastModified(const GURL& origin_url);
base::ListValue* GetAllOriginsDetails();
- void ForceClose(const GURL& origin_url);
- base::FilePath GetFilePath(const GURL& origin_url);
+ // ForceClose takes a value rather than a reference since it may release the
+ // owning object.
+ void ForceClose(const GURL origin_url);
+ base::FilePath GetFilePath(const GURL& origin_url) const;
base::FilePath data_path() const { return data_path_; }
bool IsInOriginSet(const GURL& origin_url) {
std::set<GURL>* set = GetOriginSet();
diff --git a/chromium/content/browser/indexed_db/indexed_db_cursor.cc b/chromium/content/browser/indexed_db/indexed_db_cursor.cc
index cb254d95908..6d7bc1c2d59 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cursor.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_cursor.cc
@@ -31,6 +31,7 @@ IndexedDBCursor::~IndexedDBCursor() {
}
void IndexedDBCursor::Continue(scoped_ptr<IndexedDBKey> key,
+ scoped_ptr<IndexedDBKey> primary_key,
scoped_refptr<IndexedDBCallbacks> callbacks) {
IDB_TRACE("IndexedDBCursor::Continue");
@@ -39,6 +40,7 @@ void IndexedDBCursor::Continue(scoped_ptr<IndexedDBKey> key,
base::Bind(&IndexedDBCursor::CursorIterationOperation,
this,
base::Passed(&key),
+ base::Passed(&primary_key),
callbacks));
}
@@ -68,17 +70,19 @@ void IndexedDBCursor::CursorAdvanceOperation(
void IndexedDBCursor::CursorIterationOperation(
scoped_ptr<IndexedDBKey> key,
+ scoped_ptr<IndexedDBKey> primary_key,
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* /*transaction*/) {
IDB_TRACE("IndexedDBCursor::CursorIterationOperation");
if (!cursor_ ||
- !cursor_->Continue(key.get(), IndexedDBBackingStore::Cursor::SEEK)) {
+ !cursor_->Continue(
+ key.get(), primary_key.get(), IndexedDBBackingStore::Cursor::SEEK)) {
cursor_.reset();
callbacks->OnSuccess(static_cast<std::string*>(NULL));
return;
}
- callbacks->OnSuccess(this->key(), primary_key(), Value());
+ callbacks->OnSuccess(this->key(), this->primary_key(), Value());
}
void IndexedDBCursor::PrefetchContinue(
@@ -124,7 +128,7 @@ void IndexedDBCursor::CursorPrefetchIterationOperation(
break;
case indexed_db::CURSOR_KEY_AND_VALUE: {
std::string value;
- value.swap(*cursor_->Value());
+ value.swap(*cursor_->value());
size_estimate += value.size();
found_values.push_back(value);
break;
diff --git a/chromium/content/browser/indexed_db/indexed_db_cursor.h b/chromium/content/browser/indexed_db/indexed_db_cursor.h
index db5963058e7..f1afc186a78 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cursor.h
+++ b/chromium/content/browser/indexed_db/indexed_db_cursor.h
@@ -28,6 +28,7 @@ class CONTENT_EXPORT IndexedDBCursor
void Advance(uint32 count, scoped_refptr<IndexedDBCallbacks> callbacks);
void Continue(scoped_ptr<IndexedDBKey> key,
+ scoped_ptr<IndexedDBKey> primary_key,
scoped_refptr<IndexedDBCallbacks> callbacks);
void PrefetchContinue(int number_to_fetch,
scoped_refptr<IndexedDBCallbacks> callbacks);
@@ -37,11 +38,12 @@ class CONTENT_EXPORT IndexedDBCursor
const IndexedDBKey& primary_key() const { return cursor_->primary_key(); }
std::string* Value() const {
return (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) ? NULL
- : cursor_->Value();
+ : cursor_->value();
}
void Close();
void CursorIterationOperation(scoped_ptr<IndexedDBKey> key,
+ scoped_ptr<IndexedDBKey> primary_key,
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction);
void CursorAdvanceOperation(uint32 count,
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.cc b/chromium/content/browser/indexed_db/indexed_db_database.cc
index f7b2a9bcff8..5b982fa6cf6 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database.cc
@@ -12,7 +12,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_cursor.h"
#include "content/browser/indexed_db/indexed_db_factory.h"
@@ -25,7 +24,7 @@
#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
using base::Int64ToString16;
-using WebKit::WebIDBKeyTypeNumber;
+using blink::WebIDBKeyTypeNumber;
namespace content {
@@ -86,22 +85,16 @@ class IndexedDBDatabase::PendingSuccessCall {
public:
PendingSuccessCall(scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBConnection* connection,
- int64 transaction_id,
int64 version)
- : callbacks_(callbacks),
- connection_(connection),
- version_(version),
- transaction_id_(transaction_id) {}
+ : callbacks_(callbacks), connection_(connection), version_(version) {}
scoped_refptr<IndexedDBCallbacks> Callbacks() { return callbacks_; }
IndexedDBConnection* Connection() { return connection_; }
int64 Version() { return version_; }
- int64 TransactionId() const { return transaction_id_; }
private:
scoped_refptr<IndexedDBCallbacks> callbacks_;
IndexedDBConnection* connection_;
int64 version_;
- const int64 transaction_id_;
};
class IndexedDBDatabase::PendingDeleteCall {
@@ -115,7 +108,7 @@ class IndexedDBDatabase::PendingDeleteCall {
};
scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create(
- const string16& name,
+ const base::string16& name,
IndexedDBBackingStore* backing_store,
IndexedDBFactory* factory,
const Identifier& unique_identifier) {
@@ -135,7 +128,7 @@ bool Contains(const T& container, const U& item) {
}
}
-IndexedDBDatabase::IndexedDBDatabase(const string16& name,
+IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
IndexedDBBackingStore* backing_store,
IndexedDBFactory* factory,
const Identifier& unique_identifier)
@@ -147,8 +140,7 @@ IndexedDBDatabase::IndexedDBDatabase(const string16& name,
kInvalidId),
identifier_(unique_identifier),
factory_(factory),
- running_version_change_transaction_(NULL),
- closing_connection_(false) {
+ running_version_change_transaction_(NULL) {
DCHECK(!metadata_.name.empty());
}
@@ -220,10 +212,6 @@ IndexedDBDatabase::~IndexedDBDatabase() {
DCHECK(pending_delete_calls_.empty());
}
-scoped_refptr<IndexedDBBackingStore> IndexedDBDatabase::BackingStore() const {
- return backing_store_;
-}
-
IndexedDBTransaction* IndexedDBDatabase::GetTransaction(
int64 transaction_id) const {
TransactionMap::const_iterator trans_iterator =
@@ -285,7 +273,7 @@ bool IndexedDBDatabase::ValidateObjectStoreIdAndNewIndexId(
void IndexedDBDatabase::CreateObjectStore(int64 transaction_id,
int64 object_store_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath& key_path,
bool auto_increment) {
IDB_TRACE("IndexedDBDatabase::CreateObjectStore");
@@ -329,7 +317,7 @@ void IndexedDBDatabase::CreateObjectStoreOperation(
object_store_metadata.key_path,
object_store_metadata.auto_increment)) {
transaction->Abort(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError,
+ blink::WebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16("Internal error creating object store '") +
object_store_metadata.name + ASCIIToUTF16("'.")));
return;
@@ -363,7 +351,7 @@ void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id,
void IndexedDBDatabase::CreateIndex(int64 transaction_id,
int64 object_store_id,
int64 index_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath& key_path,
bool unique,
bool multi_entry) {
@@ -404,10 +392,11 @@ void IndexedDBDatabase::CreateIndexOperation(
index_metadata.key_path,
index_metadata.unique,
index_metadata.multi_entry)) {
- string16 error_string = ASCIIToUTF16("Internal error creating index '") +
- index_metadata.name + ASCIIToUTF16("'.");
+ base::string16 error_string =
+ ASCIIToUTF16("Internal error creating index '") +
+ index_metadata.name + ASCIIToUTF16("'.");
transaction->Abort(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
+ blink::WebIDBDatabaseExceptionUnknownError, error_string));
return;
}
}
@@ -458,10 +447,11 @@ void IndexedDBDatabase::DeleteIndexOperation(
object_store_id,
index_metadata.id);
if (!ok) {
- string16 error_string = ASCIIToUTF16("Internal error deleting index '") +
- index_metadata.name + ASCIIToUTF16("'.");
+ base::string16 error_string =
+ ASCIIToUTF16("Internal error deleting index '") +
+ index_metadata.name + ASCIIToUTF16("'.");
transaction->Abort(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
+ blink::WebIDBDatabaseExceptionUnknownError, error_string));
}
}
@@ -594,7 +584,7 @@ void IndexedDBDatabase::GetOperation(
&value);
if (!ok) {
callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error in GetRecord."));
return;
}
@@ -624,7 +614,7 @@ void IndexedDBDatabase::GetOperation(
&primary_key);
if (!ok) {
callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error in GetPrimaryKeyViaIndex."));
return;
}
@@ -647,7 +637,7 @@ void IndexedDBDatabase::GetOperation(
&value);
if (!ok) {
callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error in GetRecord."));
return;
}
@@ -767,7 +757,7 @@ void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
key_was_generated = true;
if (!auto_inc_key->IsValid()) {
params->callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionConstraintError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
"Maximum key generator value reached."));
return;
}
@@ -790,20 +780,20 @@ void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
&found);
if (!ok) {
params->callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error checking key existence."));
return;
}
if (found) {
params->callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionConstraintError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
"Key already exists in the object store."));
return;
}
}
ScopedVector<IndexWriter> index_writers;
- string16 error_message;
+ base::string16 error_message;
bool obeys_constraints = false;
bool backing_store_success = MakeIndexWriters(transaction,
backing_store_.get(),
@@ -818,13 +808,13 @@ void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
&obeys_constraints);
if (!backing_store_success) {
params->callbacks->OnError(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError,
+ blink::WebIDBDatabaseExceptionUnknownError,
"Internal error: backing store error updating index keys."));
return;
}
if (!obeys_constraints) {
params->callbacks->OnError(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionConstraintError, error_message));
+ blink::WebIDBDatabaseExceptionConstraintError, error_message));
return;
}
@@ -839,7 +829,7 @@ void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
&record_identifier);
if (!backing_store_success) {
params->callbacks->OnError(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError,
+ blink::WebIDBDatabaseExceptionUnknownError,
"Internal error: backing store error performing put/add."));
return;
}
@@ -864,7 +854,7 @@ void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
!key_was_generated);
if (!ok) {
params->callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error updating key generator."));
return;
}
@@ -884,40 +874,39 @@ void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
return;
DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
- scoped_refptr<IndexedDBBackingStore> store = BackingStore();
// TODO(alecflett): This method could be asynchronous, but we need to
// evaluate if it's worth the extra complexity.
IndexedDBBackingStore::RecordIdentifier record_identifier;
bool found = false;
- bool ok =
- store->KeyExistsInObjectStore(transaction->BackingStoreTransaction(),
- metadata_.id,
- object_store_id,
- *primary_key,
- &record_identifier,
- &found);
+ bool ok = backing_store_->KeyExistsInObjectStore(
+ transaction->BackingStoreTransaction(),
+ metadata_.id,
+ object_store_id,
+ *primary_key,
+ &record_identifier,
+ &found);
if (!ok) {
transaction->Abort(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error setting index keys."));
return;
}
if (!found) {
transaction->Abort(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError,
+ blink::WebIDBDatabaseExceptionUnknownError,
"Internal error setting index keys for object store."));
return;
}
ScopedVector<IndexWriter> index_writers;
- string16 error_message;
+ base::string16 error_message;
bool obeys_constraints = false;
DCHECK(metadata_.object_stores.find(object_store_id) !=
metadata_.object_stores.end());
const IndexedDBObjectStoreMetadata& object_store_metadata =
metadata_.object_stores[object_store_id];
bool backing_store_success = MakeIndexWriters(transaction,
- store,
+ backing_store_,
id(),
object_store_metadata,
*primary_key,
@@ -929,20 +918,20 @@ void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
&obeys_constraints);
if (!backing_store_success) {
transaction->Abort(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError,
+ blink::WebIDBDatabaseExceptionUnknownError,
"Internal error: backing store error updating index keys."));
return;
}
if (!obeys_constraints) {
transaction->Abort(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionConstraintError, error_message));
+ blink::WebIDBDatabaseExceptionConstraintError, error_message));
return;
}
for (size_t i = 0; i < index_writers.size(); ++i) {
IndexWriter* index_writer = index_writers[i];
index_writer->WriteIndexKeys(record_identifier,
- store,
+ backing_store_,
transaction->BackingStoreTransaction(),
id(),
object_store_id);
@@ -1182,7 +1171,7 @@ void IndexedDBDatabase::DeleteRangeOperation(
object_store_id,
backing_store_cursor->record_identifier())) {
callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error deleting data in range"));
return;
}
@@ -1216,7 +1205,7 @@ void IndexedDBDatabase::ClearOperation(
if (!backing_store_->ClearObjectStore(
transaction->BackingStoreTransaction(), id(), object_store_id)) {
callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error clearing object store"));
return;
}
@@ -1232,11 +1221,11 @@ void IndexedDBDatabase::DeleteObjectStoreOperation(
transaction->database()->id(),
object_store_metadata.id);
if (!ok) {
- string16 error_string =
+ base::string16 error_string =
ASCIIToUTF16("Internal error deleting object store '") +
object_store_metadata.name + ASCIIToUTF16("'.");
transaction->Abort(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError, error_string));
+ blink::WebIDBDatabaseExceptionUnknownError, error_string));
}
}
@@ -1244,7 +1233,8 @@ void IndexedDBDatabase::VersionChangeOperation(
int64 version,
scoped_refptr<IndexedDBCallbacks> callbacks,
scoped_ptr<IndexedDBConnection> connection,
- WebKit::WebIDBCallbacks::DataLoss data_loss,
+ blink::WebIDBDataLoss data_loss,
+ std::string data_loss_message,
IndexedDBTransaction* transaction) {
IDB_TRACE("IndexedDBDatabase::VersionChangeOperation");
int64 old_version = metadata_.int_version;
@@ -1255,7 +1245,7 @@ void IndexedDBDatabase::VersionChangeOperation(
id(),
metadata_.int_version)) {
IndexedDBDatabaseError error(
- WebKit::WebIDBDatabaseExceptionUnknownError,
+ blink::WebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16(
"Internal error writing data to stable storage when "
"updating version."));
@@ -1264,10 +1254,10 @@ void IndexedDBDatabase::VersionChangeOperation(
return;
}
DCHECK(!pending_second_half_open_);
- pending_second_half_open_.reset(new PendingSuccessCall(
- callbacks, connection.get(), transaction->id(), version));
+ pending_second_half_open_.reset(
+ new PendingSuccessCall(callbacks, connection.get(), version));
callbacks->OnUpgradeNeeded(
- old_version, connection.Pass(), metadata(), data_loss);
+ old_version, connection.Pass(), metadata(), data_loss, data_loss_message);
}
void IndexedDBDatabase::TransactionStarted(IndexedDBTransaction* transaction) {
@@ -1294,7 +1284,7 @@ void IndexedDBDatabase::TransactionFinishedAndAbortFired(
if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
if (pending_second_half_open_) {
pending_second_half_open_->Callbacks()->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionAbortError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
"Version change transaction was aborted in "
"upgradeneeded event handler."));
pending_second_half_open_.reset();
@@ -1322,6 +1312,13 @@ void IndexedDBDatabase::TransactionFinishedAndCompleteFired(
}
}
+void IndexedDBDatabase::TransactionCommitFailed() {
+ // Factory may be null in unit tests.
+ if (!factory_)
+ return;
+ factory_->HandleBackingStoreFailure(backing_store_->origin_url());
+}
+
size_t IndexedDBDatabase::ConnectionCount() const {
// This does not include pending open calls, as those should not block version
// changes and deletes.
@@ -1398,7 +1395,7 @@ void IndexedDBDatabase::CreateTransaction(
const std::vector<int64>& object_store_ids,
uint16 mode) {
- DCHECK(connections_.has(connection));
+ DCHECK(connections_.count(connection));
DCHECK(transactions_.find(transaction_id) == transactions_.end());
if (transactions_.find(transaction_id) != transactions_.end())
return;
@@ -1408,8 +1405,14 @@ void IndexedDBDatabase::CreateTransaction(
connection->callbacks(),
std::set<int64>(object_store_ids.begin(), object_store_ids.end()),
static_cast<indexed_db::TransactionMode>(mode),
- this);
- transactions_[transaction_id] = transaction;
+ this,
+ new IndexedDBBackingStore::Transaction(backing_store_));
+ TransactionCreated(transaction);
+}
+
+void IndexedDBDatabase::TransactionCreated(
+ scoped_refptr<IndexedDBTransaction> transaction) {
+ transactions_[transaction->id()] = transaction;
}
bool IndexedDBDatabase::IsOpenConnectionBlocked() const {
@@ -1423,10 +1426,10 @@ void IndexedDBDatabase::OpenConnection(
scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
int64 transaction_id,
int64 version) {
- const WebKit::WebIDBCallbacks::DataLoss kDataLoss =
- WebKit::WebIDBCallbacks::DataLossNone;
+ const blink::WebIDBDataLoss kDataLoss =
+ blink::WebIDBDataLossNone;
OpenConnection(
- callbacks, database_callbacks, transaction_id, version, kDataLoss);
+ callbacks, database_callbacks, transaction_id, version, kDataLoss, "");
}
void IndexedDBDatabase::OpenConnection(
@@ -1434,7 +1437,8 @@ void IndexedDBDatabase::OpenConnection(
scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
int64 transaction_id,
int64 version,
- WebKit::WebIDBCallbacks::DataLoss data_loss) {
+ blink::WebIDBDataLoss data_loss,
+ std::string data_loss_message) {
DCHECK(backing_store_);
// TODO(jsbell): Should have a priority queue so that higher version
@@ -1443,7 +1447,7 @@ void IndexedDBDatabase::OpenConnection(
// The backing store only detects data loss when it is first opened. The
// presence of existing connections means we didn't even check for data loss
// so there'd better not be any.
- DCHECK_NE(WebKit::WebIDBCallbacks::DataLossTotal, data_loss);
+ DCHECK_NE(blink::WebIDBDataLossTotal, data_loss);
pending_open_calls_.push_back(new PendingOpenCall(
callbacks, database_callbacks, transaction_id, version));
return;
@@ -1456,16 +1460,17 @@ void IndexedDBDatabase::OpenConnection(
DCHECK_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
metadata_.int_version);
} else {
- string16 message;
- if (version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
+ base::string16 message;
+ if (version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
message = ASCIIToUTF16(
"Internal error opening database with no version specified.");
- else
+ } else {
message =
ASCIIToUTF16("Internal error opening database with version ") +
Int64ToString16(version);
+ }
callbacks->OnError(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError, message));
+ blink::WebIDBDatabaseExceptionUnknownError, message));
return;
}
}
@@ -1502,13 +1507,17 @@ void IndexedDBDatabase::OpenConnection(
if (version > metadata_.int_version) {
connections_.insert(connection.get());
- RunVersionChangeTransaction(
- callbacks, connection.Pass(), transaction_id, version, data_loss);
+ RunVersionChangeTransaction(callbacks,
+ connection.Pass(),
+ transaction_id,
+ version,
+ data_loss,
+ data_loss_message);
return;
}
if (version < metadata_.int_version) {
callbacks->OnError(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionVersionError,
+ blink::WebIDBDatabaseExceptionVersionError,
ASCIIToUTF16("The requested version (") + Int64ToString16(version) +
ASCIIToUTF16(") is less than the existing version (") +
Int64ToString16(metadata_.int_version) + ASCIIToUTF16(").")));
@@ -1524,12 +1533,13 @@ void IndexedDBDatabase::RunVersionChangeTransaction(
scoped_ptr<IndexedDBConnection> connection,
int64 transaction_id,
int64 requested_version,
- WebKit::WebIDBCallbacks::DataLoss data_loss) {
+ blink::WebIDBDataLoss data_loss,
+ std::string data_loss_message) {
DCHECK(callbacks);
- DCHECK(connections_.has(connection.get()));
+ DCHECK(connections_.count(connection.get()));
if (ConnectionCount() > 1) {
- DCHECK_NE(WebKit::WebIDBCallbacks::DataLossTotal, data_loss);
+ DCHECK_NE(blink::WebIDBDataLossTotal, data_loss);
// Front end ensures the event is not fired at connections that have
// close_pending set.
for (ConnectionSet::const_iterator it = connections_.begin();
@@ -1554,7 +1564,8 @@ void IndexedDBDatabase::RunVersionChangeTransaction(
connection.Pass(),
transaction_id,
requested_version,
- data_loss);
+ data_loss,
+ data_loss_message);
}
void IndexedDBDatabase::RunVersionChangeTransactionFinal(
@@ -1562,13 +1573,14 @@ void IndexedDBDatabase::RunVersionChangeTransactionFinal(
scoped_ptr<IndexedDBConnection> connection,
int64 transaction_id,
int64 requested_version) {
- const WebKit::WebIDBCallbacks::DataLoss kDataLoss =
- WebKit::WebIDBCallbacks::DataLossNone;
+ const blink::WebIDBDataLoss kDataLoss =
+ blink::WebIDBDataLossNone;
RunVersionChangeTransactionFinal(callbacks,
connection.Pass(),
transaction_id,
requested_version,
- kDataLoss);
+ kDataLoss,
+ "");
}
void IndexedDBDatabase::RunVersionChangeTransactionFinal(
@@ -1576,7 +1588,8 @@ void IndexedDBDatabase::RunVersionChangeTransactionFinal(
scoped_ptr<IndexedDBConnection> connection,
int64 transaction_id,
int64 requested_version,
- WebKit::WebIDBCallbacks::DataLoss data_loss) {
+ blink::WebIDBDataLoss data_loss,
+ std::string data_loss_message) {
std::vector<int64> object_store_ids;
CreateTransaction(transaction_id,
@@ -1592,7 +1605,8 @@ void IndexedDBDatabase::RunVersionChangeTransactionFinal(
requested_version,
callbacks,
base::Passed(&connection),
- data_loss),
+ data_loss,
+ data_loss_message),
base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation,
this,
metadata_.version,
@@ -1633,7 +1647,7 @@ void IndexedDBDatabase::DeleteDatabaseFinal(
DCHECK(backing_store_);
if (!backing_store_->DeleteDatabase(metadata_.name)) {
callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error deleting database."));
return;
}
@@ -1644,14 +1658,15 @@ void IndexedDBDatabase::DeleteDatabaseFinal(
callbacks->OnSuccess();
}
-void IndexedDBDatabase::Close(IndexedDBConnection* connection) {
- DCHECK(connections_.has(connection));
+void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
+ DCHECK(connections_.count(connection));
+ DCHECK(connection->IsConnected());
+ DCHECK(connection->database() == this);
- // Close outstanding transactions from the closing connection. This
+ // Abort outstanding transactions from the closing connection. This
// can not happen if the close is requested by the connection itself
// as the front-end defers the close until all transactions are
- // complete, so something unusual has happened e.g. unexpected
- // process termination.
+ // complete, but can occur on process termination or forced close.
{
TransactionMap transactions(transactions_);
for (TransactionMap::const_iterator it = transactions.begin(),
@@ -1660,7 +1675,7 @@ void IndexedDBDatabase::Close(IndexedDBConnection* connection) {
++it) {
if (it->second->connection() == connection->callbacks())
it->second->Abort(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Connection is closing."));
}
}
@@ -1669,19 +1684,11 @@ void IndexedDBDatabase::Close(IndexedDBConnection* connection) {
if (pending_second_half_open_ &&
pending_second_half_open_->Connection() == connection) {
pending_second_half_open_->Callbacks()->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionAbortError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
"The connection was closed."));
pending_second_half_open_.reset();
}
- // process_pending_calls allows the inspector to process a pending open call
- // and call close, reentering IndexedDBDatabase::close. Then the
- // backend would be removed both by the inspector closing its connection, and
- // by the connection that first called close.
- // To avoid that situation, don't proceed in case of reentrancy.
- if (closing_connection_)
- return;
- base::AutoReset<bool> ClosingConnection(&closing_connection_, true);
ProcessPendingCalls();
// TODO(jsbell): Add a test for the pending_open_calls_ cases below.
@@ -1689,12 +1696,15 @@ void IndexedDBDatabase::Close(IndexedDBConnection* connection) {
!pending_delete_calls_.size()) {
DCHECK(transactions_.empty());
+ const GURL origin_url = backing_store_->origin_url();
backing_store_ = NULL;
// factory_ should only be null in unit tests.
// TODO(jsbell): DCHECK(factory_ || !in_unit_tests) - somehow.
- if (factory_)
- factory_->RemoveIDBDatabaseBackend(identifier_);
+ if (factory_) {
+ factory_->ReleaseDatabase(identifier_, origin_url, forced);
+ factory_ = NULL;
+ }
}
}
@@ -1716,7 +1726,7 @@ void IndexedDBDatabase::DeleteObjectStoreAbortOperation(
}
void IndexedDBDatabase::VersionChangeAbortOperation(
- const string16& previous_version,
+ const base::string16& previous_version,
int64 previous_int_version,
IndexedDBTransaction* transaction) {
IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation");
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.h b/chromium/content/browser/indexed_db/indexed_db_database.h
index da7039cc797..6297f3dcd68 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database.h
@@ -13,16 +13,17 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "content/browser/indexed_db/indexed_db.h"
+#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_metadata.h"
#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
#include "content/browser/indexed_db/list_set.h"
+#include "url/gurl.h"
namespace content {
class IndexedDBConnection;
class IndexedDBDatabaseCallbacks;
-class IndexedDBBackingStore;
class IndexedDBFactory;
class IndexedDBKey;
class IndexedDBKeyPath;
@@ -44,18 +45,20 @@ class CONTENT_EXPORT IndexedDBDatabase
};
typedef std::vector<IndexedDBKey> IndexKeys;
- // Identifier is pair of (origin identifier, database name).
- typedef std::pair<std::string, base::string16> Identifier;
+ // Identifier is pair of (origin url, database name).
+ typedef std::pair<GURL, base::string16> Identifier;
static const int64 kInvalidId = 0;
static const int64 kMinimumIndexId = 30;
static scoped_refptr<IndexedDBDatabase> Create(
- const string16& name,
+ const base::string16& name,
IndexedDBBackingStore* backing_store,
IndexedDBFactory* factory,
const Identifier& unique_identifier);
- scoped_refptr<IndexedDBBackingStore> BackingStore() const;
+
+ const Identifier& identifier() const { return identifier_; }
+ IndexedDBBackingStore* backing_store() { return backing_store_.get(); }
int64 id() const { return metadata_.id; }
const base::string16& name() const { return metadata_.name; }
@@ -78,13 +81,14 @@ class CONTENT_EXPORT IndexedDBDatabase
scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
int64 transaction_id,
int64 version,
- WebKit::WebIDBCallbacks::DataLoss data_loss);
+ blink::WebIDBDataLoss data_loss,
+ std::string data_loss_message);
void DeleteDatabase(scoped_refptr<IndexedDBCallbacks> callbacks);
const IndexedDBDatabaseMetadata& metadata() const { return metadata_; }
void CreateObjectStore(int64 transaction_id,
int64 object_store_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath& key_path,
bool auto_increment);
void DeleteObjectStore(int64 transaction_id, int64 object_store_id);
@@ -92,7 +96,7 @@ class CONTENT_EXPORT IndexedDBDatabase
IndexedDBConnection* connection,
const std::vector<int64>& object_store_ids,
uint16 mode);
- void Close(IndexedDBConnection* connection);
+ void Close(IndexedDBConnection* connection, bool forced);
void Commit(int64 transaction_id);
void Abort(int64 transaction_id);
@@ -101,7 +105,7 @@ class CONTENT_EXPORT IndexedDBDatabase
void CreateIndex(int64 transaction_id,
int64 object_store_id,
int64 index_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath& key_path,
bool unique,
bool multi_entry);
@@ -114,11 +118,15 @@ class CONTENT_EXPORT IndexedDBDatabase
return transaction_coordinator_;
}
+ void TransactionCreated(scoped_refptr<IndexedDBTransaction> transaction);
void TransactionStarted(IndexedDBTransaction* transaction);
void TransactionFinished(IndexedDBTransaction* transaction);
void TransactionFinishedAndCompleteFired(IndexedDBTransaction* transaction);
void TransactionFinishedAndAbortFired(IndexedDBTransaction* transaction);
+ // Called by transactions to report failure committing to the backing store.
+ void TransactionCommitFailed();
+
void Get(int64 transaction_id,
int64 object_store_id,
int64 index_id,
@@ -188,9 +196,10 @@ class CONTENT_EXPORT IndexedDBDatabase
void VersionChangeOperation(int64 version,
scoped_refptr<IndexedDBCallbacks> callbacks,
scoped_ptr<IndexedDBConnection> connection,
- WebKit::WebIDBCallbacks::DataLoss data_loss,
+ blink::WebIDBDataLoss data_loss,
+ std::string data_loss_message,
IndexedDBTransaction* transaction);
- void VersionChangeAbortOperation(const string16& previous_version,
+ void VersionChangeAbortOperation(const base::string16& previous_version,
int64 previous_int_version,
IndexedDBTransaction* transaction);
void CreateIndexOperation(int64 object_store_id,
@@ -235,7 +244,7 @@ class CONTENT_EXPORT IndexedDBDatabase
private:
friend class base::RefCounted<IndexedDBDatabase>;
- IndexedDBDatabase(const string16& name,
+ IndexedDBDatabase(const base::string16& name,
IndexedDBBackingStore* backing_store,
IndexedDBFactory* factory,
const Identifier& unique_identifier);
@@ -247,7 +256,8 @@ class CONTENT_EXPORT IndexedDBDatabase
scoped_ptr<IndexedDBConnection> connection,
int64 transaction_id,
int64 requested_version,
- WebKit::WebIDBCallbacks::DataLoss data_loss);
+ blink::WebIDBDataLoss data_loss,
+ std::string data_loss_message);
void RunVersionChangeTransactionFinal(
scoped_refptr<IndexedDBCallbacks> callbacks,
scoped_ptr<IndexedDBConnection> connection,
@@ -258,7 +268,8 @@ class CONTENT_EXPORT IndexedDBDatabase
scoped_ptr<IndexedDBConnection> connection,
int64 transaction_id,
int64 requested_version,
- WebKit::WebIDBCallbacks::DataLoss data_loss);
+ blink::WebIDBDataLoss data_loss,
+ std::string data_loss_message);
void ProcessPendingCalls();
bool IsDeleteDatabaseBlocked() const;
@@ -303,8 +314,6 @@ class CONTENT_EXPORT IndexedDBDatabase
typedef list_set<IndexedDBConnection*> ConnectionSet;
ConnectionSet connections_;
-
- bool closing_connection_;
};
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_error.h b/chromium/content/browser/indexed_db/indexed_db_database_error.h
index 297bec7be33..1a4f449d818 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_error.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database_error.h
@@ -17,16 +17,16 @@ class IndexedDBDatabaseError {
: code_(code) {}
IndexedDBDatabaseError(uint16 code, const char* message)
: code_(code), message_(ASCIIToUTF16(message)) {}
- IndexedDBDatabaseError(uint16 code, const string16& message)
+ IndexedDBDatabaseError(uint16 code, const base::string16& message)
: code_(code), message_(message) {}
~IndexedDBDatabaseError() {}
uint16 code() const { return code_; }
- const string16& message() const { return message_; }
+ const base::string16& message() const { return message_; }
private:
const uint16 code_;
- const string16 message_;
+ const base::string16 message_;
};
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
index fad99106e5a..73a7ec22e2b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -14,10 +14,11 @@
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_cursor.h"
#include "content/browser/indexed_db/indexed_db_database.h"
-#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
#include "content/browser/indexed_db/indexed_db_factory.h"
#include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
+#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
+#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -38,36 +39,6 @@ TEST(IndexedDBDatabaseTest, BackingStoreRetention) {
EXPECT_TRUE(backing_store->HasOneRef()); // local
}
-class MockOpenCallbacks : public IndexedDBCallbacks {
- public:
- MockOpenCallbacks() : IndexedDBCallbacks(NULL, 0, 0) {}
-
- virtual void OnSuccess(scoped_ptr<IndexedDBConnection> connection,
- const IndexedDBDatabaseMetadata& metadata) OVERRIDE {
- connection_ = connection.Pass();
- }
-
- IndexedDBConnection* connection() { return connection_.get(); }
-
- private:
- virtual ~MockOpenCallbacks() { EXPECT_TRUE(connection_); }
- scoped_ptr<IndexedDBConnection> connection_;
-};
-
-class FakeDatabaseCallbacks : public IndexedDBDatabaseCallbacks {
- public:
- FakeDatabaseCallbacks() : IndexedDBDatabaseCallbacks(NULL, 0, 0) {}
-
- virtual void OnVersionChange(int64 old_version, int64 new_version) OVERRIDE {}
- virtual void OnForcedClose() OVERRIDE {}
- virtual void OnAbort(int64 transaction_id,
- const IndexedDBDatabaseError& error) OVERRIDE {}
- virtual void OnComplete(int64 transaction_id) OVERRIDE {}
-
- private:
- virtual ~FakeDatabaseCallbacks() {}
-};
-
TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
scoped_refptr<IndexedDBFakeBackingStore> backing_store =
new IndexedDBFakeBackingStore();
@@ -82,8 +53,9 @@ TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
- scoped_refptr<MockOpenCallbacks> request1(new MockOpenCallbacks());
- scoped_refptr<FakeDatabaseCallbacks> callbacks1(new FakeDatabaseCallbacks());
+ scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks());
+ scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
+ new MockIndexedDBDatabaseCallbacks());
const int64 transaction_id1 = 1;
db->OpenConnection(request1,
callbacks1,
@@ -92,8 +64,9 @@ TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
EXPECT_FALSE(backing_store->HasOneRef()); // db, connection count > 0
- scoped_refptr<MockOpenCallbacks> request2(new MockOpenCallbacks());
- scoped_refptr<FakeDatabaseCallbacks> callbacks2(new FakeDatabaseCallbacks());
+ scoped_refptr<MockIndexedDBCallbacks> request2(new MockIndexedDBCallbacks());
+ scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2(
+ new MockIndexedDBDatabaseCallbacks());
const int64 transaction_id2 = 2;
db->OpenConnection(request2,
callbacks2,
@@ -102,32 +75,20 @@ TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
EXPECT_FALSE(backing_store->HasOneRef()); // local and connection
- db->Close(request1->connection());
+ request1->connection()->ForceClose();
+ EXPECT_FALSE(request1->connection()->IsConnected());
EXPECT_FALSE(backing_store->HasOneRef()); // local and connection
- db->Close(request2->connection());
+ request2->connection()->ForceClose();
+ EXPECT_FALSE(request2->connection()->IsConnected());
+
EXPECT_TRUE(backing_store->HasOneRef());
- EXPECT_FALSE(db->BackingStore());
+ EXPECT_FALSE(db->backing_store());
db = NULL;
}
-class MockAbortCallbacks : public IndexedDBDatabaseCallbacks {
- public:
- MockAbortCallbacks()
- : IndexedDBDatabaseCallbacks(NULL, 0, 0), abort_called_(false) {}
-
- virtual void OnAbort(int64 transaction_id,
- const IndexedDBDatabaseError& error) OVERRIDE {
- abort_called_ = true;
- }
-
- private:
- virtual ~MockAbortCallbacks() { EXPECT_TRUE(abort_called_); }
- bool abort_called_;
-};
-
TEST(IndexedDBDatabaseTest, ForcedClose) {
scoped_refptr<IndexedDBFakeBackingStore> backing_store =
new IndexedDBFakeBackingStore();
@@ -142,8 +103,9 @@ TEST(IndexedDBDatabaseTest, ForcedClose) {
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
- scoped_refptr<MockAbortCallbacks> callbacks(new MockAbortCallbacks());
- scoped_refptr<MockOpenCallbacks> request(new MockOpenCallbacks());
+ scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks(
+ new MockIndexedDBDatabaseCallbacks());
+ scoped_refptr<MockIndexedDBCallbacks> request(new MockIndexedDBCallbacks());
const int64 upgrade_transaction_id = 3;
database->OpenConnection(request,
callbacks,
@@ -161,6 +123,7 @@ TEST(IndexedDBDatabaseTest, ForcedClose) {
request->connection()->ForceClose();
EXPECT_TRUE(backing_store->HasOneRef()); // local
+ EXPECT_TRUE(callbacks->abort_called());
}
class MockDeleteCallbacks : public IndexedDBCallbacks {
@@ -180,7 +143,6 @@ class MockDeleteCallbacks : public IndexedDBCallbacks {
private:
virtual ~MockDeleteCallbacks() { EXPECT_TRUE(success_void_called_); }
- scoped_ptr<IndexedDBConnection> connection_;
bool blocked_called_;
bool success_void_called_;
};
@@ -199,8 +161,9 @@ TEST(IndexedDBDatabaseTest, PendingDelete) {
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
- scoped_refptr<MockOpenCallbacks> request1(new MockOpenCallbacks());
- scoped_refptr<FakeDatabaseCallbacks> callbacks1(new FakeDatabaseCallbacks());
+ scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks());
+ scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
+ new MockIndexedDBDatabaseCallbacks());
const int64 transaction_id1 = 1;
db->OpenConnection(request1,
callbacks1,
@@ -215,9 +178,9 @@ TEST(IndexedDBDatabaseTest, PendingDelete) {
EXPECT_TRUE(request2->blocked_called());
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
- db->Close(request1->connection());
+ db->Close(request1->connection(), true /* forced */);
- EXPECT_FALSE(db->BackingStore());
+ EXPECT_FALSE(db->backing_store());
EXPECT_TRUE(backing_store->HasOneRef()); // local
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index 1cbc4b82a4a..6f1bf07dca9 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -27,25 +27,21 @@
#include "webkit/common/database/database_identifier.h"
using webkit_database::DatabaseUtil;
-using WebKit::WebIDBKey;
+using blink::WebIDBKey;
namespace content {
IndexedDBDispatcherHost::IndexedDBDispatcherHost(
- int ipc_process_id,
IndexedDBContextImpl* indexed_db_context)
: indexed_db_context_(indexed_db_context),
database_dispatcher_host_(new DatabaseDispatcherHost(this)),
- cursor_dispatcher_host_(new CursorDispatcherHost(this)),
- ipc_process_id_(ipc_process_id) {
+ cursor_dispatcher_host_(new CursorDispatcherHost(this)) {
DCHECK(indexed_db_context_);
}
IndexedDBDispatcherHost::~IndexedDBDispatcherHost() {}
void IndexedDBDispatcherHost::OnChannelClosing() {
- BrowserMessageFilter::OnChannelClosing();
-
bool success = indexed_db_context_->TaskRunner()->PostTask(
FROM_HERE,
base::Bind(&IndexedDBDispatcherHost::ResetDispatcherHosts, this));
@@ -223,10 +219,13 @@ void IndexedDBDispatcherHost::OnIDBFactoryGetDatabaseNames(
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
base::FilePath indexed_db_path = indexed_db_context_->data_path();
+ GURL origin_url =
+ webkit_database::GetOriginFromIdentifier(params.database_identifier);
+
Context()->GetIDBFactory()->GetDatabaseNames(
new IndexedDBCallbacks(
this, params.ipc_thread_id, params.ipc_callbacks_id),
- params.database_identifier,
+ origin_url,
indexed_db_path);
}
@@ -257,19 +256,21 @@ void IndexedDBDispatcherHost::OnIDBFactoryOpen(
host_transaction_id,
callbacks,
database_callbacks,
- params.database_identifier,
+ origin_url,
indexed_db_path);
}
void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase(
const IndexedDBHostMsg_FactoryDeleteDatabase_Params& params) {
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ GURL origin_url =
+ webkit_database::GetOriginFromIdentifier(params.database_identifier);
base::FilePath indexed_db_path = indexed_db_context_->data_path();
Context()->GetIDBFactory()->DeleteDatabase(
params.name,
new IndexedDBCallbacks(
this, params.ipc_thread_id, params.ipc_callbacks_id),
- params.database_identifier,
+ origin_url,
indexed_db_path);
}
@@ -286,18 +287,9 @@ void IndexedDBDispatcherHost::FinishTransaction(int64 host_transaction_id,
database_dispatcher_host_->transaction_database_map_;
if (committed)
Context()->TransactionComplete(transaction_url_map[host_transaction_id]);
- // It's unclear if std::map::erase(key) has defined behavior if the
- // key is not found.
- // TODO(alecflett): Remove if it is proven that it is safe.
- if (transaction_url_map.find(host_transaction_id) !=
- transaction_url_map.end())
- transaction_url_map.erase(host_transaction_id);
- if (transaction_size_map.find(host_transaction_id) !=
- transaction_size_map.end())
- transaction_size_map.erase(host_transaction_id);
- if (transaction_database_map.find(host_transaction_id) !=
- transaction_database_map.end())
- transaction_database_map.erase(host_transaction_id);
+ transaction_url_map.erase(host_transaction_id);
+ transaction_size_map.erase(host_transaction_id);
+ transaction_database_map.erase(host_transaction_id);
}
//////////////////////////////////////////////////////////////////////
@@ -369,10 +361,10 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() {
int32 ipc_database_id = iter->second;
++iter;
IndexedDBConnection* connection = map_.Lookup(ipc_database_id);
- if (connection) {
+ if (connection && connection->IsConnected()) {
connection->database()->Abort(
transaction_id,
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError));
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError));
}
}
DCHECK(transaction_database_map_.empty());
@@ -381,7 +373,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() {
iter != database_url_map_.end();
iter++) {
IndexedDBConnection* connection = map_.Lookup(iter->first);
- if (connection) {
+ if (connection && connection->IsConnected()) {
connection->Close();
parent_->Context()->ConnectionClosed(iter->second, connection);
}
@@ -422,18 +414,13 @@ bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived(
return handled;
}
-void IndexedDBDispatcherHost::DatabaseDispatcherHost::Send(
- IPC::Message* message) {
- parent_->Send(message);
-}
-
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateObjectStore(
const IndexedDBHostMsg_DatabaseCreateObjectStore_Params& params) {
DCHECK(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id);
@@ -446,7 +433,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateObjectStore(
database_url_map_[params.ipc_database_id])) {
connection->database()->Abort(
host_transaction_id,
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionQuotaError));
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError));
}
}
@@ -458,7 +445,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteObjectStore(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
connection->database()->DeleteObjectStore(
@@ -471,7 +458,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateTransaction(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id);
@@ -495,7 +482,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClose(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
connection->Close();
}
@@ -517,7 +504,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
@@ -538,12 +525,22 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut(
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
parent_, params.ipc_thread_id, params.ipc_callbacks_id));
int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id);
+ if (params.index_ids.size() != params.index_keys.size()) {
+ connection->database()->Abort(
+ host_transaction_id,
+ IndexedDBDatabaseError(
+ blink::WebIDBDatabaseExceptionUnknownError,
+ "Malformed IPC message: index_ids.size() != index_keys.size()"));
+ parent_->BadMessageReceived();
+ return;
+ }
+
// TODO(alecflett): Avoid a copy here.
std::string value_copy(params.value);
connection->database()->Put(
@@ -568,7 +565,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexKeys(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id);
@@ -576,8 +573,9 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexKeys(
connection->database()->Abort(
host_transaction_id,
IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError,
+ blink::WebIDBDatabaseExceptionUnknownError,
"Malformed IPC message: index_ids.size() != index_keys.size()"));
+ parent_->BadMessageReceived();
return;
}
@@ -598,7 +596,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexesReady(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
connection->database()->SetIndexesReady(
@@ -611,7 +609,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnOpenCursor(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
@@ -633,7 +631,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCount(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
@@ -652,7 +650,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteRange(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
@@ -674,7 +672,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClear(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
scoped_refptr<IndexedDBCallbacks> callbacks(
@@ -691,7 +689,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnAbort(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
connection->database()->Abort(parent_->HostTransactionId(transaction_id));
@@ -704,7 +702,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCommit(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
int64 host_transaction_id = parent_->HostTransactionId(transaction_id);
@@ -714,7 +712,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCommit(
transaction_url_map_[host_transaction_id], transaction_size)) {
connection->database()->Abort(
host_transaction_id,
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionQuotaError));
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError));
return;
}
@@ -727,7 +725,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateIndex(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id);
@@ -742,7 +740,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateIndex(
database_url_map_[params.ipc_database_id])) {
connection->database()->Abort(
host_transaction_id,
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionQuotaError));
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError));
}
}
@@ -755,7 +753,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteIndex(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
- if (!connection)
+ if (!connection || !connection->IsConnected())
return;
connection->database()->DeleteIndex(
@@ -793,11 +791,6 @@ bool IndexedDBDispatcherHost::CursorDispatcherHost::OnMessageReceived(
return handled;
}
-void IndexedDBDispatcherHost::CursorDispatcherHost::Send(
- IPC::Message* message) {
- parent_->Send(message);
-}
-
void IndexedDBDispatcherHost::CursorDispatcherHost::OnAdvance(
int32 ipc_cursor_id,
int32 ipc_thread_id,
@@ -820,7 +813,8 @@ void IndexedDBDispatcherHost::CursorDispatcherHost::OnContinue(
int32 ipc_cursor_id,
int32 ipc_thread_id,
int32 ipc_callbacks_id,
- const IndexedDBKey& key) {
+ const IndexedDBKey& key,
+ const IndexedDBKey& primary_key) {
DCHECK(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBCursor* idb_cursor =
@@ -829,7 +823,10 @@ void IndexedDBDispatcherHost::CursorDispatcherHost::OnContinue(
return;
idb_cursor->Continue(
- make_scoped_ptr(new IndexedDBKey(key)),
+ key.IsValid() ? make_scoped_ptr(new IndexedDBKey(key))
+ : scoped_ptr<IndexedDBKey>(),
+ primary_key.IsValid() ? make_scoped_ptr(new IndexedDBKey(primary_key))
+ : scoped_ptr<IndexedDBKey>(),
new IndexedDBCallbacks(
parent_, ipc_thread_id, ipc_callbacks_id, ipc_cursor_id));
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
index 66db4a7c144..bcbbfba029b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -41,8 +41,7 @@ struct IndexedDBDatabaseMetadata;
class IndexedDBDispatcherHost : public BrowserMessageFilter {
public:
// Only call the constructor from the UI thread.
- IndexedDBDispatcherHost(int ipc_process_id,
- IndexedDBContextImpl* indexed_db_context);
+ explicit IndexedDBDispatcherHost(IndexedDBContextImpl* indexed_db_context);
static ::IndexedDBDatabaseMetadata ConvertMetadata(
const content::IndexedDBDatabaseMetadata& metadata);
@@ -155,7 +154,6 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
void CloseAll();
bool OnMessageReceived(const IPC::Message& message, bool* msg_is_ok);
- void Send(IPC::Message* message);
void OnCreateObjectStore(
const IndexedDBHostMsg_DatabaseCreateObjectStore_Params& params);
@@ -164,9 +162,6 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
int64 object_store_id);
void OnCreateTransaction(
const IndexedDBHostMsg_DatabaseCreateTransaction_Params&);
- void OnOpen(int32 ipc_database_id,
- int32 ipc_thread_id,
- int32 ipc_callbacks_id);
void OnClose(int32 ipc_database_id);
void OnDestroyed(int32 ipc_database_id);
@@ -210,7 +205,6 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
~CursorDispatcherHost();
bool OnMessageReceived(const IPC::Message& message, bool* msg_is_ok);
- void Send(IPC::Message* message);
void OnAdvance(int32 ipc_object_store_id,
int32 ipc_thread_id,
@@ -219,7 +213,8 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
void OnContinue(int32 ipc_object_store_id,
int32 ipc_thread_id,
int32 ipc_callbacks_id,
- const IndexedDBKey& key);
+ const IndexedDBKey& key,
+ const IndexedDBKey& primary_key);
void OnPrefetch(int32 ipc_cursor_id,
int32 ipc_thread_id,
int32 ipc_callbacks_id,
@@ -239,9 +234,6 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
scoped_ptr<DatabaseDispatcherHost> database_dispatcher_host_;
scoped_ptr<CursorDispatcherHost> cursor_dispatcher_host_;
- // Used to dispatch messages to the correct view host.
- int ipc_process_id_;
-
DISALLOW_IMPLICIT_CONSTRUCTORS(IndexedDBDispatcherHost);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory.cc b/chromium/content/browser/indexed_db/indexed_db_factory.cc
index b13b704e1b2..d4f0df9f3ce 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory.cc
@@ -6,68 +6,142 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
+#include "webkit/common/database/database_identifier.h"
namespace content {
-template <typename K, typename M>
-static void CleanWeakMap(std::map<K, base::WeakPtr<M> >* map) {
- std::map<K, base::WeakPtr<M> > other;
- other.swap(*map);
+const int64 kBackingStoreGracePeriodMs = 2000;
- typename std::map<K, base::WeakPtr<M> >::const_iterator iter = other.begin();
- while (iter != other.end()) {
- if (iter->second.get())
- (*map)[iter->first] = iter->second;
- ++iter;
+IndexedDBFactory::IndexedDBFactory(IndexedDBContextImpl* context)
+ : context_(context) {}
+
+IndexedDBFactory::~IndexedDBFactory() {}
+
+void IndexedDBFactory::ReleaseDatabase(
+ const IndexedDBDatabase::Identifier& identifier,
+ const GURL& origin_url,
+ bool forcedClose) {
+ IndexedDBDatabaseMap::iterator it = database_map_.find(identifier);
+ DCHECK(it != database_map_.end());
+ DCHECK(!it->second->backing_store());
+ database_map_.erase(it);
+
+ // No grace period on a forced-close, as the initiator is
+ // assuming the backing store will be released once all
+ // connections are closed.
+ ReleaseBackingStore(origin_url, forcedClose);
+}
+
+void IndexedDBFactory::ReleaseBackingStore(const GURL& origin_url,
+ bool immediate) {
+ // Only close if this is the last reference.
+ if (!HasLastBackingStoreReference(origin_url))
+ return;
+
+ // If this factory does hold the last reference to the backing store, it can
+ // be closed - but unless requested to close it immediately, keep it around
+ // for a short period so that a re-open is fast.
+ if (immediate) {
+ CloseBackingStore(origin_url);
+ return;
}
+
+ // Start a timer to close the backing store, unless something else opens it
+ // in the mean time.
+ DCHECK(!backing_store_map_[origin_url]->close_timer()->IsRunning());
+ backing_store_map_[origin_url]->close_timer()->Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kBackingStoreGracePeriodMs),
+ base::Bind(&IndexedDBFactory::MaybeCloseBackingStore, this, origin_url));
}
-static std::string ComputeFileIdentifier(const std::string& origin_identifier) {
- return origin_identifier + "@1";
+void IndexedDBFactory::MaybeCloseBackingStore(const GURL& origin_url) {
+ // Another reference may have opened since the maybe-close was posted, so it
+ // is necessary to check again.
+ if (HasLastBackingStoreReference(origin_url))
+ CloseBackingStore(origin_url);
}
-IndexedDBFactory::IndexedDBFactory() {}
+void IndexedDBFactory::CloseBackingStore(const GURL& origin_url) {
+ IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url);
+ DCHECK(it != backing_store_map_.end());
+ // Stop the timer (if it's running) - this may happen if the timer was started
+ // and then a forced close occurs.
+ it->second->close_timer()->Stop();
+ backing_store_map_.erase(it);
+}
-IndexedDBFactory::~IndexedDBFactory() {}
+bool IndexedDBFactory::HasLastBackingStoreReference(const GURL& origin_url)
+ const {
+ IndexedDBBackingStore* ptr;
+ {
+ // Scope so that the implicit scoped_refptr<> is freed.
+ IndexedDBBackingStoreMap::const_iterator it =
+ backing_store_map_.find(origin_url);
+ DCHECK(it != backing_store_map_.end());
+ ptr = it->second.get();
+ }
+ return ptr->HasOneRef();
+}
-void IndexedDBFactory::RemoveIDBDatabaseBackend(
- const IndexedDBDatabase::Identifier& unique_identifier) {
- DCHECK(database_map_.find(unique_identifier) != database_map_.end());
- database_map_.erase(unique_identifier);
+void IndexedDBFactory::ForceClose(const GURL& origin_url) {
+ if (backing_store_map_.find(origin_url) != backing_store_map_.end())
+ ReleaseBackingStore(origin_url, true /* immediate */);
+}
+
+void IndexedDBFactory::ContextDestroyed() {
+ // Timers on backing stores hold a reference to this factory. When the
+ // context (which nominally owns this factory) is destroyed during thread
+ // termination the timers must be stopped so that this factory and the
+ // stores can be disposed of.
+ for (IndexedDBBackingStoreMap::iterator it = backing_store_map_.begin();
+ it != backing_store_map_.end();
+ ++it)
+ it->second->close_timer()->Stop();
+ backing_store_map_.clear();
+ context_ = NULL;
}
void IndexedDBFactory::GetDatabaseNames(
scoped_refptr<IndexedDBCallbacks> callbacks,
- const std::string& origin_identifier,
+ const GURL& origin_url,
const base::FilePath& data_directory) {
IDB_TRACE("IndexedDBFactory::GetDatabaseNames");
// TODO(dgrogan): Plumb data_loss back to script eventually?
- WebKit::WebIDBCallbacks::DataLoss data_loss;
+ blink::WebIDBDataLoss data_loss;
+ std::string data_loss_message;
bool disk_full;
- scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore(
- origin_identifier, data_directory, &data_loss, &disk_full);
+ scoped_refptr<IndexedDBBackingStore> backing_store =
+ OpenBackingStore(origin_url,
+ data_directory,
+ &data_loss,
+ &data_loss_message,
+ &disk_full);
if (!backing_store) {
callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error opening backing store for "
"indexedDB.webkitGetDatabaseNames."));
return;
}
callbacks->OnSuccess(backing_store->GetDatabaseNames());
+ ReleaseBackingStore(origin_url, false /* immediate */);
}
void IndexedDBFactory::DeleteDatabase(
- const string16& name,
+ const base::string16& name,
scoped_refptr<IndexedDBCallbacks> callbacks,
- const std::string& origin_identifier,
+ const GURL& origin_url,
const base::FilePath& data_directory) {
IDB_TRACE("IndexedDBFactory::DeleteDatabase");
- IndexedDBDatabase::Identifier unique_identifier(origin_identifier, name);
+ IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
if (it != database_map_.end()) {
// If there are any connections to the database, directly delete the
@@ -77,13 +151,18 @@ void IndexedDBFactory::DeleteDatabase(
}
// TODO(dgrogan): Plumb data_loss back to script eventually?
- WebKit::WebIDBCallbacks::DataLoss data_loss;
+ blink::WebIDBDataLoss data_loss;
+ std::string data_loss_message;
bool disk_full = false;
- scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore(
- origin_identifier, data_directory, &data_loss, &disk_full);
+ scoped_refptr<IndexedDBBackingStore> backing_store =
+ OpenBackingStore(origin_url,
+ data_directory,
+ &data_loss,
+ &data_loss_message,
+ &disk_full);
if (!backing_store) {
callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16(
"Internal error opening backing store "
"for indexedDB.deleteDatabase.")));
@@ -94,7 +173,7 @@ void IndexedDBFactory::DeleteDatabase(
IndexedDBDatabase::Create(name, backing_store, this, unique_identifier);
if (!database) {
callbacks->OnError(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError,
+ blink::WebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16(
"Internal error creating database backend for "
"indexedDB.deleteDatabase.")));
@@ -104,35 +183,62 @@ void IndexedDBFactory::DeleteDatabase(
database_map_[unique_identifier] = database;
database->DeleteDatabase(callbacks);
database_map_.erase(unique_identifier);
+ ReleaseBackingStore(origin_url, false /* immediate */);
+}
+
+void IndexedDBFactory::HandleBackingStoreFailure(const GURL& origin_url) {
+ // NULL after ContextDestroyed() called, and in some unit tests.
+ if (!context_)
+ return;
+ context_->ForceClose(origin_url);
+}
+
+bool IndexedDBFactory::IsDatabaseOpen(const GURL& origin_url,
+ const base::string16& name) const {
+
+ return !!database_map_.count(IndexedDBDatabase::Identifier(origin_url, name));
+}
+
+bool IndexedDBFactory::IsBackingStoreOpen(const GURL& origin_url) const {
+ return backing_store_map_.find(origin_url) != backing_store_map_.end();
+}
+
+bool IndexedDBFactory::IsBackingStorePendingClose(const GURL& origin_url)
+ const {
+ IndexedDBBackingStoreMap::const_iterator it =
+ backing_store_map_.find(origin_url);
+ if (it == backing_store_map_.end())
+ return false;
+ return it->second->close_timer()->IsRunning();
}
scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore(
- const std::string& origin_identifier,
+ const GURL& origin_url,
const base::FilePath& data_directory,
- WebKit::WebIDBCallbacks::DataLoss* data_loss,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_message,
bool* disk_full) {
- const std::string file_identifier = ComputeFileIdentifier(origin_identifier);
const bool open_in_memory = data_directory.empty();
- IndexedDBBackingStoreMap::iterator it2 =
- backing_store_map_.find(file_identifier);
- if (it2 != backing_store_map_.end() && it2->second.get())
- return it2->second.get();
+ IndexedDBBackingStoreMap::iterator it2 = backing_store_map_.find(origin_url);
+ if (it2 != backing_store_map_.end()) {
+ it2->second->close_timer()->Stop();
+ return it2->second;
+ }
scoped_refptr<IndexedDBBackingStore> backing_store;
if (open_in_memory) {
- backing_store = IndexedDBBackingStore::OpenInMemory(file_identifier);
+ backing_store = IndexedDBBackingStore::OpenInMemory(origin_url);
} else {
- backing_store = IndexedDBBackingStore::Open(origin_identifier,
+ backing_store = IndexedDBBackingStore::Open(origin_url,
data_directory,
- file_identifier,
data_loss,
+ data_loss_message,
disk_full);
}
if (backing_store.get()) {
- CleanWeakMap(&backing_store_map_);
- backing_store_map_[file_identifier] = backing_store->GetWeakPtr();
+ backing_store_map_[origin_url] = backing_store;
// If an in-memory database, bind lifetime to this factory instance.
if (open_in_memory)
session_only_backing_stores_.insert(backing_store);
@@ -148,34 +254,40 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore(
}
void IndexedDBFactory::Open(
- const string16& name,
+ const base::string16& name,
int64 version,
int64 transaction_id,
scoped_refptr<IndexedDBCallbacks> callbacks,
scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
- const std::string& origin_identifier,
+ const GURL& origin_url,
const base::FilePath& data_directory) {
IDB_TRACE("IndexedDBFactory::Open");
scoped_refptr<IndexedDBDatabase> database;
- IndexedDBDatabase::Identifier unique_identifier(origin_identifier, name);
+ IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
- WebKit::WebIDBCallbacks::DataLoss data_loss =
- WebKit::WebIDBCallbacks::DataLossNone;
+ blink::WebIDBDataLoss data_loss =
+ blink::WebIDBDataLossNone;
+ std::string data_loss_message;
bool disk_full = false;
- if (it == database_map_.end()) {
- scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore(
- origin_identifier, data_directory, &data_loss, &disk_full);
+ bool was_open = (it != database_map_.end());
+ if (!was_open) {
+ scoped_refptr<IndexedDBBackingStore> backing_store =
+ OpenBackingStore(origin_url,
+ data_directory,
+ &data_loss,
+ &data_loss_message,
+ &disk_full);
if (!backing_store) {
if (disk_full) {
callbacks->OnError(
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionQuotaError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError,
ASCIIToUTF16(
"Encountered full disk while opening "
"backing store for indexedDB.open.")));
return;
}
callbacks->OnError(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError,
+ blink::WebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16(
"Internal error opening backing store for indexedDB.open.")));
return;
@@ -185,28 +297,33 @@ void IndexedDBFactory::Open(
IndexedDBDatabase::Create(name, backing_store, this, unique_identifier);
if (!database) {
callbacks->OnError(IndexedDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError,
+ blink::WebIDBDatabaseExceptionUnknownError,
ASCIIToUTF16(
"Internal error creating database backend for indexedDB.open.")));
return;
}
-
- database_map_[unique_identifier] = database;
} else {
database = it->second;
}
- database->OpenConnection(
- callbacks, database_callbacks, transaction_id, version, data_loss);
+ database->OpenConnection(callbacks,
+ database_callbacks,
+ transaction_id,
+ version,
+ data_loss,
+ data_loss_message);
+
+ if (!was_open && database->ConnectionCount() > 0)
+ database_map_[unique_identifier] = database;
}
std::vector<IndexedDBDatabase*> IndexedDBFactory::GetOpenDatabasesForOrigin(
- const std::string& origin_identifier) const {
+ const GURL& origin_url) const {
std::vector<IndexedDBDatabase*> result;
for (IndexedDBDatabaseMap::const_iterator it = database_map_.begin();
it != database_map_.end();
++it) {
- if (it->first.first == origin_identifier)
+ if (it->first.first == origin_url)
result.push_back(it->second.get());
}
return result;
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory.h b/chromium/content/browser/indexed_db/indexed_db_factory.h
index cea2c726f2b..24d48d9e9e6 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory.h
@@ -11,63 +11,105 @@
#include "base/basictypes.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_database.h"
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
#include "content/common/content_export.h"
+#include "url/gurl.h"
namespace content {
class IndexedDBBackingStore;
+class IndexedDBContextImpl;
class CONTENT_EXPORT IndexedDBFactory
- : NON_EXPORTED_BASE(public base::RefCounted<IndexedDBFactory>) {
+ : NON_EXPORTED_BASE(public base::RefCountedThreadSafe<IndexedDBFactory>) {
public:
- IndexedDBFactory();
+ explicit IndexedDBFactory(IndexedDBContextImpl* context);
// Notifications from weak pointers.
- void RemoveIDBDatabaseBackend(
- const IndexedDBDatabase::Identifier& unique_identifier);
+ void ReleaseDatabase(const IndexedDBDatabase::Identifier& identifier,
+ const GURL& origin_url,
+ bool forcedClose);
void GetDatabaseNames(scoped_refptr<IndexedDBCallbacks> callbacks,
- const std::string& origin_identifier,
+ const GURL& origin_url,
const base::FilePath& data_directory);
- void Open(const string16& name,
+ void Open(const base::string16& name,
int64 version,
int64 transaction_id,
scoped_refptr<IndexedDBCallbacks> callbacks,
scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
- const std::string& origin_identifier,
+ const GURL& origin_url,
const base::FilePath& data_directory);
- void DeleteDatabase(const string16& name,
+ void DeleteDatabase(const base::string16& name,
scoped_refptr<IndexedDBCallbacks> callbacks,
- const std::string& origin_identifier,
+ const GURL& origin_url,
const base::FilePath& data_directory);
+ void HandleBackingStoreFailure(const GURL& origin_url);
+
// Iterates over all databases; for diagnostics only.
std::vector<IndexedDBDatabase*> GetOpenDatabasesForOrigin(
- const std::string& origin_identifier) const;
+ const GURL& origin_url) const;
+
+ // Called by IndexedDBContext after all connections are closed, to
+ // ensure the backing store closed immediately.
+ void ForceClose(const GURL& origin_url);
+
+ // Called by the IndexedDBContext destructor so the factory can do cleanup.
+ void ContextDestroyed();
protected:
- friend class base::RefCounted<IndexedDBFactory>;
+ friend class base::RefCountedThreadSafe<IndexedDBFactory>;
virtual ~IndexedDBFactory();
virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
- const std::string& origin_identifier,
+ const GURL& origin_url,
const base::FilePath& data_directory,
- WebKit::WebIDBCallbacks::DataLoss* data_loss,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_reason,
bool* disk_full);
+ void ReleaseBackingStore(const GURL& origin_url, bool immediate);
+ void CloseBackingStore(const GURL& origin_url);
+
private:
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
+ BackingStoreReleasedOnForcedClose);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
+ BackingStoreReleaseDelayedOnClose);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, DatabaseFailedOpen);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
+ DeleteDatabaseClosesBackingStore);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
+ ForceCloseReleasesBackingStore);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
+ GetDatabaseNamesClosesBackingStore);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBTest,
+ ForceCloseOpenDatabasesOnCommitFailure);
+
+ // Called internally after a database is closed, with some delay. If this
+ // factory has the last reference, it will be released.
+ void MaybeCloseBackingStore(const GURL& origin_url);
+ bool HasLastBackingStoreReference(const GURL& origin_url) const;
+
+ // Testing helpers, so unit tests don't need to grovel through internal state.
+ bool IsDatabaseOpen(const GURL& origin_url,
+ const base::string16& name) const;
+ bool IsBackingStoreOpen(const GURL& origin_url) const;
+ bool IsBackingStorePendingClose(const GURL& origin_url) const;
+
+ IndexedDBContextImpl* context_;
+
typedef std::map<IndexedDBDatabase::Identifier,
scoped_refptr<IndexedDBDatabase> > IndexedDBDatabaseMap;
IndexedDBDatabaseMap database_map_;
- typedef std::map<std::string, base::WeakPtr<IndexedDBBackingStore> >
+ typedef std::map<GURL, scoped_refptr<IndexedDBBackingStore> >
IndexedDBBackingStoreMap;
IndexedDBBackingStoreMap backing_store_map_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
new file mode 100644
index 00000000000..7d958e71b61
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -0,0 +1,481 @@
+// 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/indexed_db/indexed_db_factory.h"
+
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/indexed_db/indexed_db_connection.h"
+#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
+#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
+#include "third_party/WebKit/public/platform/WebIDBTypes.h"
+#include "url/gurl.h"
+#include "webkit/common/database/database_identifier.h"
+
+namespace content {
+
+class IndexedDBFactoryTest : public testing::Test {
+ public:
+ IndexedDBFactoryTest() {}
+
+ protected:
+ // For timers to post events.
+ base::MessageLoop loop_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBFactoryTest);
+};
+
+class MockIDBFactory : public IndexedDBFactory {
+ public:
+ MockIDBFactory() : IndexedDBFactory(NULL) {}
+ scoped_refptr<IndexedDBBackingStore> TestOpenBackingStore(
+ const GURL& origin,
+ const base::FilePath& data_directory) {
+ blink::WebIDBDataLoss data_loss =
+ blink::WebIDBDataLossNone;
+ std::string data_loss_message;
+ bool disk_full;
+ scoped_refptr<IndexedDBBackingStore> backing_store =
+ OpenBackingStore(origin,
+ data_directory,
+ &data_loss,
+ &data_loss_message,
+ &disk_full);
+ EXPECT_EQ(blink::WebIDBDataLossNone, data_loss);
+ return backing_store;
+ }
+
+ void TestCloseBackingStore(IndexedDBBackingStore* backing_store) {
+ CloseBackingStore(backing_store->origin_url());
+ }
+
+ void TestReleaseBackingStore(IndexedDBBackingStore* backing_store,
+ bool immediate) {
+ ReleaseBackingStore(backing_store->origin_url(), immediate);
+ }
+
+ private:
+ virtual ~MockIDBFactory() {}
+};
+
+TEST_F(IndexedDBFactoryTest, BackingStoreLifetime) {
+ GURL origin1("http://localhost:81");
+ GURL origin2("http://localhost:82");
+
+ scoped_refptr<MockIDBFactory> factory = new MockIDBFactory();
+
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+ scoped_refptr<IndexedDBBackingStore> disk_store1 =
+ factory->TestOpenBackingStore(origin1, temp_directory.path());
+
+ scoped_refptr<IndexedDBBackingStore> disk_store2 =
+ factory->TestOpenBackingStore(origin1, temp_directory.path());
+ EXPECT_EQ(disk_store1.get(), disk_store2.get());
+
+ scoped_refptr<IndexedDBBackingStore> disk_store3 =
+ factory->TestOpenBackingStore(origin2, temp_directory.path());
+
+ factory->TestCloseBackingStore(disk_store1);
+ factory->TestCloseBackingStore(disk_store3);
+
+ EXPECT_FALSE(disk_store1->HasOneRef());
+ EXPECT_FALSE(disk_store2->HasOneRef());
+ EXPECT_TRUE(disk_store3->HasOneRef());
+
+ disk_store2 = NULL;
+ EXPECT_TRUE(disk_store1->HasOneRef());
+}
+
+TEST_F(IndexedDBFactoryTest, BackingStoreLazyClose) {
+ GURL origin("http://localhost:81");
+
+ scoped_refptr<MockIDBFactory> factory = new MockIDBFactory();
+
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+ scoped_refptr<IndexedDBBackingStore> store =
+ factory->TestOpenBackingStore(origin, temp_directory.path());
+
+ // Give up the local refptr so that the factory has the only
+ // outstanding reference.
+ IndexedDBBackingStore* store_ptr = store.get();
+ store = NULL;
+ EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
+ factory->TestReleaseBackingStore(store_ptr, false);
+ EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
+
+ factory->TestOpenBackingStore(origin, temp_directory.path());
+ EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
+ factory->TestReleaseBackingStore(store_ptr, false);
+ EXPECT_TRUE(store_ptr->close_timer()->IsRunning());
+
+ // Take back a ref ptr and ensure that the actual close
+ // stops a running timer.
+ store = store_ptr;
+ factory->TestCloseBackingStore(store_ptr);
+ EXPECT_FALSE(store_ptr->close_timer()->IsRunning());
+}
+
+TEST_F(IndexedDBFactoryTest, MemoryBackingStoreLifetime) {
+ GURL origin1("http://localhost:81");
+ GURL origin2("http://localhost:82");
+
+ scoped_refptr<MockIDBFactory> factory = new MockIDBFactory();
+ scoped_refptr<IndexedDBBackingStore> mem_store1 =
+ factory->TestOpenBackingStore(origin1, base::FilePath());
+
+ scoped_refptr<IndexedDBBackingStore> mem_store2 =
+ factory->TestOpenBackingStore(origin1, base::FilePath());
+ EXPECT_EQ(mem_store1.get(), mem_store2.get());
+
+ scoped_refptr<IndexedDBBackingStore> mem_store3 =
+ factory->TestOpenBackingStore(origin2, base::FilePath());
+
+ factory->TestCloseBackingStore(mem_store1);
+ factory->TestCloseBackingStore(mem_store3);
+
+ EXPECT_FALSE(mem_store1->HasOneRef());
+ EXPECT_FALSE(mem_store2->HasOneRef());
+ EXPECT_FALSE(mem_store3->HasOneRef());
+
+ factory = NULL;
+ EXPECT_FALSE(mem_store1->HasOneRef()); // mem_store1 and 2
+ EXPECT_FALSE(mem_store2->HasOneRef()); // mem_store1 and 2
+ EXPECT_TRUE(mem_store3->HasOneRef());
+
+ mem_store2 = NULL;
+ EXPECT_TRUE(mem_store1->HasOneRef());
+}
+
+TEST_F(IndexedDBFactoryTest, RejectLongOrigins) {
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+ const base::FilePath base_path = temp_directory.path();
+ scoped_refptr<MockIDBFactory> factory = new MockIDBFactory();
+
+ int limit = file_util::GetMaximumPathComponentLength(base_path);
+ EXPECT_GT(limit, 0);
+
+ std::string origin(limit + 1, 'x');
+ GURL too_long_origin("http://" + origin + ":81/");
+ scoped_refptr<IndexedDBBackingStore> diskStore1 =
+ factory->TestOpenBackingStore(too_long_origin, base_path);
+ EXPECT_FALSE(diskStore1);
+
+ GURL ok_origin("http://someorigin.com:82/");
+ scoped_refptr<IndexedDBBackingStore> diskStore2 =
+ factory->TestOpenBackingStore(ok_origin, base_path);
+ EXPECT_TRUE(diskStore2);
+}
+
+class DiskFullFactory : public IndexedDBFactory {
+ public:
+ DiskFullFactory() : IndexedDBFactory(NULL) {}
+
+ private:
+ virtual ~DiskFullFactory() {}
+ virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_message,
+ bool* disk_full) OVERRIDE {
+ *disk_full = true;
+ return scoped_refptr<IndexedDBBackingStore>();
+ }
+};
+
+class LookingForQuotaErrorMockCallbacks : public IndexedDBCallbacks {
+ public:
+ LookingForQuotaErrorMockCallbacks()
+ : IndexedDBCallbacks(NULL, 0, 0), error_called_(false) {}
+ virtual void OnError(const IndexedDBDatabaseError& error) OVERRIDE {
+ error_called_ = true;
+ EXPECT_EQ(blink::WebIDBDatabaseExceptionQuotaError, error.code());
+ }
+
+ private:
+ virtual ~LookingForQuotaErrorMockCallbacks() { EXPECT_TRUE(error_called_); }
+ bool error_called_;
+};
+
+TEST_F(IndexedDBFactoryTest, QuotaErrorOnDiskFull) {
+ const GURL origin("http://localhost:81");
+
+ scoped_refptr<DiskFullFactory> factory = new DiskFullFactory;
+ scoped_refptr<LookingForQuotaErrorMockCallbacks> callbacks =
+ new LookingForQuotaErrorMockCallbacks;
+ scoped_refptr<IndexedDBDatabaseCallbacks> dummy_database_callbacks =
+ new IndexedDBDatabaseCallbacks(NULL, 0, 0);
+ const base::string16 name(ASCIIToUTF16("name"));
+ factory->Open(name,
+ 1, /* version */
+ 2, /* transaction_id */
+ callbacks,
+ dummy_database_callbacks,
+ origin,
+ base::FilePath(FILE_PATH_LITERAL("/dummy")));
+}
+
+TEST_F(IndexedDBFactoryTest, BackingStoreReleasedOnForcedClose) {
+ GURL origin("http://localhost:81");
+
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+
+ scoped_refptr<IndexedDBFactory> factory = new IndexedDBFactory(NULL);
+
+ scoped_refptr<MockIndexedDBCallbacks> callbacks(new MockIndexedDBCallbacks());
+ scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
+ new MockIndexedDBDatabaseCallbacks());
+ const int64 transaction_id = 1;
+ factory->Open(ASCIIToUTF16("db"),
+ IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION,
+ transaction_id,
+ callbacks,
+ db_callbacks,
+ origin,
+ temp_directory.path());
+
+ EXPECT_TRUE(callbacks->connection());
+
+ EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
+ EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+
+ callbacks->connection()->ForceClose();
+
+ EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
+ EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+}
+
+TEST_F(IndexedDBFactoryTest, BackingStoreReleaseDelayedOnClose) {
+ GURL origin("http://localhost:81");
+
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+
+ scoped_refptr<IndexedDBFactory> factory = new IndexedDBFactory(NULL);
+
+ scoped_refptr<MockIndexedDBCallbacks> callbacks(new MockIndexedDBCallbacks());
+ scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
+ new MockIndexedDBDatabaseCallbacks());
+ const int64 transaction_id = 1;
+ factory->Open(ASCIIToUTF16("db"),
+ IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION,
+ transaction_id,
+ callbacks,
+ db_callbacks,
+ origin,
+ temp_directory.path());
+
+ EXPECT_TRUE(callbacks->connection());
+ IndexedDBBackingStore* store =
+ callbacks->connection()->database()->backing_store();
+ EXPECT_FALSE(store->HasOneRef()); // Factory and database.
+
+ EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
+ callbacks->connection()->Close();
+ EXPECT_TRUE(store->HasOneRef()); // Factory.
+ EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
+ EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
+ EXPECT_TRUE(store->close_timer()->IsRunning());
+
+ // Take a ref so it won't be destroyed out from under the test.
+ scoped_refptr<IndexedDBBackingStore> store_ref = store;
+ // Now simulate shutdown, which should stop the timer.
+ factory->ContextDestroyed();
+ EXPECT_TRUE(store->HasOneRef()); // Local.
+ EXPECT_FALSE(store->close_timer()->IsRunning());
+ EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
+ EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+}
+
+TEST_F(IndexedDBFactoryTest, DeleteDatabaseClosesBackingStore) {
+ GURL origin("http://localhost:81");
+
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+
+ scoped_refptr<IndexedDBFactory> factory = new IndexedDBFactory(NULL);
+ EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
+
+ const bool expect_connection = false;
+ scoped_refptr<MockIndexedDBCallbacks> callbacks(
+ new MockIndexedDBCallbacks(expect_connection));
+ factory->DeleteDatabase(ASCIIToUTF16("db"),
+ callbacks,
+ origin,
+ temp_directory.path());
+
+ EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
+ EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+
+ // Now simulate shutdown, which should stop the timer.
+ factory->ContextDestroyed();
+
+ EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
+ EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+}
+
+TEST_F(IndexedDBFactoryTest, GetDatabaseNamesClosesBackingStore) {
+ GURL origin("http://localhost:81");
+
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+
+ scoped_refptr<IndexedDBFactory> factory = new IndexedDBFactory(NULL);
+ EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
+
+ const bool expect_connection = false;
+ scoped_refptr<MockIndexedDBCallbacks> callbacks(
+ new MockIndexedDBCallbacks(expect_connection));
+ factory->GetDatabaseNames(callbacks,
+ origin,
+ temp_directory.path());
+
+ EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
+ EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+
+ // Now simulate shutdown, which should stop the timer.
+ factory->ContextDestroyed();
+
+ EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
+ EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+}
+
+TEST_F(IndexedDBFactoryTest, ForceCloseReleasesBackingStore) {
+ GURL origin("http://localhost:81");
+
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+
+ scoped_refptr<IndexedDBFactory> factory = new IndexedDBFactory(NULL);
+
+ scoped_refptr<MockIndexedDBCallbacks> callbacks(new MockIndexedDBCallbacks());
+ scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
+ new MockIndexedDBDatabaseCallbacks());
+ const int64 transaction_id = 1;
+ factory->Open(ASCIIToUTF16("db"),
+ IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION,
+ transaction_id,
+ callbacks,
+ db_callbacks,
+ origin,
+ temp_directory.path());
+
+ EXPECT_TRUE(callbacks->connection());
+ EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
+ EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+
+ callbacks->connection()->Close();
+
+ EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
+ EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
+
+ factory->ForceClose(origin);
+
+ EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
+ EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
+
+ // Ensure it is safe if the store is not open.
+ factory->ForceClose(origin);
+}
+
+class UpgradeNeededCallbacks : public MockIndexedDBCallbacks {
+ public:
+ virtual void OnSuccess(scoped_ptr<IndexedDBConnection> connection,
+ const IndexedDBDatabaseMetadata& metadata) OVERRIDE {
+ EXPECT_TRUE(connection_.get());
+ EXPECT_FALSE(connection.get());
+ }
+
+ virtual void OnUpgradeNeeded(
+ int64 old_version,
+ scoped_ptr<IndexedDBConnection> connection,
+ const content::IndexedDBDatabaseMetadata& metadata,
+ blink::WebIDBDataLoss data_loss,
+ std::string data_loss_message) OVERRIDE {
+ connection_ = connection.Pass();
+ }
+
+ protected:
+ virtual ~UpgradeNeededCallbacks() {}
+};
+
+class ErrorCallbacks : public MockIndexedDBCallbacks {
+ public:
+ ErrorCallbacks() : MockIndexedDBCallbacks(false), saw_error_(false) {}
+
+ virtual void OnError(const IndexedDBDatabaseError& error) OVERRIDE {
+ saw_error_= true;
+ }
+
+ protected:
+ virtual ~ErrorCallbacks() { EXPECT_TRUE(saw_error_); }
+
+ private:
+ bool saw_error_;
+};
+
+TEST_F(IndexedDBFactoryTest, DatabaseFailedOpen) {
+ GURL origin("http://localhost:81");
+
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+
+ scoped_refptr<IndexedDBFactory> factory = new IndexedDBFactory(NULL);
+ const base::string16 db_name(ASCIIToUTF16("db"));
+ const int64 db_version = 2;
+ const int64 transaction_id = 1;
+ scoped_refptr<IndexedDBDatabaseCallbacks> db_callbacks(
+ new MockIndexedDBDatabaseCallbacks());
+
+ // Open at version 2, then close.
+ {
+ scoped_refptr<MockIndexedDBCallbacks> callbacks(
+ new UpgradeNeededCallbacks());
+ factory->Open(db_name,
+ db_version,
+ transaction_id,
+ callbacks,
+ db_callbacks,
+ origin,
+ temp_directory.path());
+ EXPECT_TRUE(factory->IsDatabaseOpen(origin, db_name));
+
+ // Pump the message loop so the upgrade transaction can run.
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_TRUE(callbacks->connection());
+ callbacks->connection()->database()->Commit(transaction_id);
+
+ callbacks->connection()->Close();
+ EXPECT_FALSE(factory->IsDatabaseOpen(origin, db_name));
+ }
+
+ // Open at version < 2, which will fail; ensure factory doesn't retain
+ // the database object.
+ {
+ scoped_refptr<IndexedDBCallbacks> callbacks(new ErrorCallbacks());
+ factory->Open(db_name,
+ db_version - 1,
+ transaction_id,
+ callbacks,
+ db_callbacks,
+ origin,
+ temp_directory.path());
+ EXPECT_FALSE(factory->IsDatabaseOpen(origin, db_name));
+ }
+
+ // Terminate all pending-close timers.
+ factory->ForceClose(origin);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
index 981f6f88b4e..3efd410727c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
@@ -10,42 +10,36 @@ namespace content {
IndexedDBFakeBackingStore::~IndexedDBFakeBackingStore() {}
-std::vector<string16> IndexedDBFakeBackingStore::GetDatabaseNames() {
- return std::vector<string16>();
+std::vector<base::string16> IndexedDBFakeBackingStore::GetDatabaseNames() {
+ return std::vector<base::string16>();
}
bool IndexedDBFakeBackingStore::GetIDBDatabaseMetaData(
- const string16& name,
+ const base::string16& name,
IndexedDBDatabaseMetadata*,
bool* found) {
return true;
}
bool IndexedDBFakeBackingStore::CreateIDBDatabaseMetaData(
- const string16& name,
- const string16& version,
+ const base::string16& name,
+ const base::string16& version,
int64 int_version,
int64* row_id) {
return true;
}
-bool IndexedDBFakeBackingStore::UpdateIDBDatabaseMetaData(
- Transaction*,
- int64 row_id,
- const string16& version) {
- return false;
-}
bool IndexedDBFakeBackingStore::UpdateIDBDatabaseIntVersion(Transaction*,
int64 row_id,
int64 version) {
return false;
}
-bool IndexedDBFakeBackingStore::DeleteDatabase(const string16& name) {
+bool IndexedDBFakeBackingStore::DeleteDatabase(const base::string16& name) {
return true;
}
bool IndexedDBFakeBackingStore::CreateObjectStore(Transaction*,
int64 database_id,
int64 object_store_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath&,
bool auto_increment) {
return false;
@@ -91,7 +85,7 @@ bool IndexedDBFakeBackingStore::CreateIndex(Transaction*,
int64 database_id,
int64 object_store_id,
int64 index_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath&,
bool is_unique,
bool is_multi_entry) {
@@ -152,4 +146,10 @@ IndexedDBFakeBackingStore::OpenIndexCursor(
return scoped_ptr<IndexedDBBackingStore::Cursor>();
}
+IndexedDBFakeBackingStore::FakeTransaction::FakeTransaction(bool result)
+ : IndexedDBBackingStore::Transaction(NULL), result_(result) {}
+void IndexedDBFakeBackingStore::FakeTransaction::Begin() {}
+bool IndexedDBFakeBackingStore::FakeTransaction::Commit() { return result_; }
+void IndexedDBFakeBackingStore::FakeTransaction::Rollback() {}
+
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
index 20ebf46f815..14b956244d0 100644
--- a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
@@ -14,29 +14,26 @@ namespace content {
class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
public:
IndexedDBFakeBackingStore()
- : IndexedDBBackingStore(std::string(),
+ : IndexedDBBackingStore(GURL("http://localhost:81"),
scoped_ptr<LevelDBDatabase>(),
scoped_ptr<LevelDBComparator>()) {}
- virtual std::vector<string16> GetDatabaseNames() OVERRIDE;
- virtual bool GetIDBDatabaseMetaData(const string16& name,
+ virtual std::vector<base::string16> GetDatabaseNames() OVERRIDE;
+ virtual bool GetIDBDatabaseMetaData(const base::string16& name,
IndexedDBDatabaseMetadata*,
bool* found) OVERRIDE;
- virtual bool CreateIDBDatabaseMetaData(const string16& name,
- const string16& version,
+ virtual bool CreateIDBDatabaseMetaData(const base::string16& name,
+ const base::string16& version,
int64 int_version,
int64* row_id) OVERRIDE;
- virtual bool UpdateIDBDatabaseMetaData(Transaction*,
- int64 row_id,
- const string16& version) OVERRIDE;
virtual bool UpdateIDBDatabaseIntVersion(Transaction*,
int64 row_id,
int64 version) OVERRIDE;
- virtual bool DeleteDatabase(const string16& name) OVERRIDE;
+ virtual bool DeleteDatabase(const base::string16& name) OVERRIDE;
virtual bool CreateObjectStore(Transaction*,
int64 database_id,
int64 object_store_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath&,
bool auto_increment) OVERRIDE;
@@ -68,7 +65,7 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
int64 database_id,
int64 object_store_id,
int64 index_id,
- const string16& name,
+ const base::string16& name,
const IndexedDBKeyPath&,
bool is_unique,
bool is_multi_entry) OVERRIDE;
@@ -110,6 +107,17 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
indexed_db::CursorDirection)
OVERRIDE;
+ class FakeTransaction : public IndexedDBBackingStore::Transaction {
+ public:
+ FakeTransaction(bool result);
+ virtual void Begin() OVERRIDE;
+ virtual bool Commit() OVERRIDE;
+ virtual void Rollback() OVERRIDE;
+
+ private:
+ bool result_;
+ };
+
protected:
friend class base::RefCounted<IndexedDBFakeBackingStore>;
virtual ~IndexedDBFakeBackingStore();
diff --git a/chromium/content/browser/indexed_db/indexed_db_index_writer.cc b/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
index 3b36cad0ec9..3e8dc3f86de 100644
--- a/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
@@ -34,7 +34,7 @@ bool IndexWriter::VerifyIndexKeys(
int64 index_id,
bool* can_add_keys,
const IndexedDBKey& primary_key,
- string16* error_message) const {
+ base::string16* error_message) const {
*can_add_keys = false;
for (size_t i = 0; i < index_keys_.size(); ++i) {
bool ok = AddingKeyAllowed(backing_store,
@@ -48,11 +48,12 @@ bool IndexWriter::VerifyIndexKeys(
if (!ok)
return false;
if (!*can_add_keys) {
- if (error_message)
+ if (error_message) {
*error_message = ASCIIToUTF16("Unable to add key to index '") +
index_metadata_.name +
ASCIIToUTF16("': at least one key does not satisfy "
"the uniqueness requirements.");
+ }
return true;
}
}
@@ -122,7 +123,7 @@ bool MakeIndexWriters(
const std::vector<int64>& index_ids,
const std::vector<IndexedDBDatabase::IndexKeys>& index_keys,
ScopedVector<IndexWriter>* index_writers,
- string16* error_message,
+ base::string16* error_message,
bool* completed) {
DCHECK_EQ(index_ids.size(), index_keys.size());
*completed = false;
diff --git a/chromium/content/browser/indexed_db/indexed_db_index_writer.h b/chromium/content/browser/indexed_db/indexed_db_index_writer.h
index 2ea1c98c8e5..8a2cdadee3a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_index_writer.h
+++ b/chromium/content/browser/indexed_db/indexed_db_index_writer.h
@@ -34,7 +34,7 @@ class IndexWriter {
int64 index_id,
bool* can_add_keys,
const IndexedDBKey& primary_key,
- string16* error_message) const WARN_UNUSED_RESULT;
+ base::string16* error_message) const WARN_UNUSED_RESULT;
void WriteIndexKeys(const IndexedDBBackingStore::RecordIdentifier& record,
IndexedDBBackingStore* store,
@@ -68,7 +68,7 @@ bool MakeIndexWriters(
const std::vector<int64>& index_ids,
const std::vector<IndexedDBDatabase::IndexKeys>& index_keys,
ScopedVector<IndexWriter>* index_writers,
- string16* error_message,
+ base::string16* error_message,
bool* completed) WARN_UNUSED_RESULT;
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
index 230b7887552..b5e888f5356 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -280,7 +280,7 @@ void IndexedDBInternalsUI::OnDownloadDataReady(
const GURL referrer(web_ui()->GetWebContents()->GetLastCommittedURL());
dl_params->set_referrer(
- content::Referrer(referrer, WebKit::WebReferrerPolicyDefault));
+ content::Referrer(referrer, blink::WebReferrerPolicyDefault));
// This is how to watch for the download to finish: first wait for it
// to start, then attach a DownloadItem::Observer to observe the
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
index 3a7028012a3..01c27d10d0f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -147,18 +147,19 @@
using base::StringPiece;
-using WebKit::WebIDBKeyType;
-using WebKit::WebIDBKeyTypeArray;
-using WebKit::WebIDBKeyTypeDate;
-using WebKit::WebIDBKeyTypeInvalid;
-using WebKit::WebIDBKeyTypeMin;
-using WebKit::WebIDBKeyTypeNull;
-using WebKit::WebIDBKeyTypeNumber;
-using WebKit::WebIDBKeyTypeString;
-using WebKit::WebIDBKeyPathType;
-using WebKit::WebIDBKeyPathTypeArray;
-using WebKit::WebIDBKeyPathTypeNull;
-using WebKit::WebIDBKeyPathTypeString;
+using blink::WebIDBKeyType;
+using blink::WebIDBKeyTypeArray;
+using blink::WebIDBKeyTypeBinary;
+using blink::WebIDBKeyTypeDate;
+using blink::WebIDBKeyTypeInvalid;
+using blink::WebIDBKeyTypeMin;
+using blink::WebIDBKeyTypeNull;
+using blink::WebIDBKeyTypeNumber;
+using blink::WebIDBKeyTypeString;
+using blink::WebIDBKeyPathType;
+using blink::WebIDBKeyPathTypeArray;
+using blink::WebIDBKeyPathTypeNull;
+using blink::WebIDBKeyPathTypeString;
namespace content {
@@ -173,6 +174,7 @@ static const unsigned char kIndexedDBKeyDateTypeByte = 2;
static const unsigned char kIndexedDBKeyNumberTypeByte = 3;
static const unsigned char kIndexedDBKeyArrayTypeByte = 4;
static const unsigned char kIndexedDBKeyMinKeyTypeByte = 5;
+static const unsigned char kIndexedDBKeyBinaryTypeByte = 6;
static const unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0;
static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0;
@@ -255,7 +257,7 @@ void EncodeVarInt(int64 value, std::string* into) {
} while (n);
}
-void EncodeString(const string16& value, std::string* into) {
+void EncodeString(const base::string16& value, std::string* into) {
if (value.empty())
return;
// Backing store is UTF-16BE, convert from host endianness.
@@ -269,7 +271,13 @@ void EncodeString(const string16& value, std::string* into) {
*dst++ = htons(*src++);
}
-void EncodeStringWithLength(const string16& value, std::string* into) {
+void EncodeBinary(const std::string& value, std::string* into) {
+ EncodeVarInt(value.length(), into);
+ into->append(value.begin(), value.end());
+ DCHECK(into->size() >= value.size());
+}
+
+void EncodeStringWithLength(const base::string16& value, std::string* into) {
EncodeVarInt(value.length(), into);
EncodeString(value, into);
}
@@ -286,7 +294,8 @@ void EncodeIDBKey(const IndexedDBKey& value, std::string* into) {
switch (value.type()) {
case WebIDBKeyTypeNull:
case WebIDBKeyTypeInvalid:
- case WebIDBKeyTypeMin: {
+ case WebIDBKeyTypeMin:
+ default: {
NOTREACHED();
EncodeByte(kIndexedDBKeyNullTypeByte, into);
return;
@@ -300,6 +309,12 @@ void EncodeIDBKey(const IndexedDBKey& value, std::string* into) {
DCHECK_GT(into->size(), previous_size);
return;
}
+ case WebIDBKeyTypeBinary: {
+ EncodeByte(kIndexedDBKeyBinaryTypeByte, into);
+ EncodeBinary(value.binary(), into);
+ DCHECK_GT(into->size(), previous_size);
+ return;
+ }
case WebIDBKeyTypeString: {
EncodeByte(kIndexedDBKeyStringTypeByte, into);
EncodeStringWithLength(value.string(), into);
@@ -340,7 +355,7 @@ void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) {
break;
}
case WebIDBKeyPathTypeArray: {
- const std::vector<string16>& array = value.array();
+ const std::vector<base::string16>& array = value.array();
size_t count = array.size();
EncodeVarInt(count, into);
for (size_t i = 0; i < count; ++i) {
@@ -406,7 +421,7 @@ bool DecodeVarInt(StringPiece* slice, int64* value) {
return true;
}
-bool DecodeString(StringPiece* slice, string16* value) {
+bool DecodeString(StringPiece* slice, base::string16* value) {
if (slice->empty()) {
value->clear();
return true;
@@ -415,7 +430,7 @@ bool DecodeString(StringPiece* slice, string16* value) {
// Backing store is UTF-16BE, convert to host endianness.
DCHECK(!(slice->size() % sizeof(char16)));
size_t length = slice->size() / sizeof(char16);
- string16 decoded;
+ base::string16 decoded;
decoded.reserve(length);
const char16* encoded = reinterpret_cast<const char16*>(slice->begin());
for (unsigned i = 0; i < length; ++i)
@@ -426,7 +441,7 @@ bool DecodeString(StringPiece* slice, string16* value) {
return true;
}
-bool DecodeStringWithLength(StringPiece* slice, string16* value) {
+bool DecodeStringWithLength(StringPiece* slice, base::string16* value) {
if (slice->empty())
return false;
@@ -445,6 +460,22 @@ bool DecodeStringWithLength(StringPiece* slice, string16* value) {
return true;
}
+bool DecodeBinary(StringPiece* slice, std::string* value) {
+ if (slice->empty())
+ return false;
+
+ int64 length = 0;
+ if (!DecodeVarInt(slice, &length) || length < 0)
+ return false;
+ size_t size = length;
+ if (slice->size() < size)
+ return false;
+
+ value->assign(slice->begin(), size);
+ slice->remove_prefix(size);
+ return true;
+}
+
bool DecodeIDBKey(StringPiece* slice, scoped_ptr<IndexedDBKey>* value) {
if (slice->empty())
return false;
@@ -471,8 +502,15 @@ bool DecodeIDBKey(StringPiece* slice, scoped_ptr<IndexedDBKey>* value) {
*value = make_scoped_ptr(new IndexedDBKey(array));
return true;
}
+ case kIndexedDBKeyBinaryTypeByte: {
+ std::string binary;
+ if (!DecodeBinary(slice, &binary))
+ return false;
+ *value = make_scoped_ptr(new IndexedDBKey(binary));
+ return true;
+ }
case kIndexedDBKeyStringTypeByte: {
- string16 s;
+ base::string16 s;
if (!DecodeStringWithLength(slice, &s))
return false;
*value = make_scoped_ptr(new IndexedDBKey(s));
@@ -513,7 +551,7 @@ bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) {
// always written as typed.
if (slice->size() < 3 || (*slice)[0] != kIndexedDBKeyPathTypeCodedByte1 ||
(*slice)[1] != kIndexedDBKeyPathTypeCodedByte2) {
- string16 s;
+ base::string16 s;
if (!DecodeString(slice, &s))
return false;
*value = IndexedDBKeyPath(s);
@@ -531,7 +569,7 @@ bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) {
*value = IndexedDBKeyPath();
return true;
case WebIDBKeyPathTypeString: {
- string16 string;
+ base::string16 string;
if (!DecodeStringWithLength(slice, &string))
return false;
DCHECK(slice->empty());
@@ -539,13 +577,13 @@ bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) {
return true;
}
case WebIDBKeyPathTypeArray: {
- std::vector<string16> array;
+ std::vector<base::string16> array;
int64 count;
if (!DecodeVarInt(slice, &count))
return false;
DCHECK_GE(count, 0);
while (count--) {
- string16 string;
+ base::string16 string;
if (!DecodeStringWithLength(slice, &string))
return false;
array.push_back(string);
@@ -577,6 +615,15 @@ bool ConsumeEncodedIDBKey(StringPiece* slice) {
}
return true;
}
+ case kIndexedDBKeyBinaryTypeByte: {
+ int64 length = 0;
+ if (!DecodeVarInt(slice, &length) || length < 0)
+ return false;
+ if (slice->size() < static_cast<size_t>(length))
+ return false;
+ slice->remove_prefix(length);
+ return true;
+ }
case kIndexedDBKeyStringTypeByte: {
int64 length = 0;
if (!DecodeVarInt(slice, &length) || length < 0)
@@ -613,6 +660,8 @@ static WebIDBKeyType KeyTypeByteToKeyType(unsigned char type) {
return WebIDBKeyTypeInvalid;
case kIndexedDBKeyArrayTypeByte:
return WebIDBKeyTypeArray;
+ case kIndexedDBKeyBinaryTypeByte:
+ return WebIDBKeyTypeBinary;
case kIndexedDBKeyStringTypeByte:
return WebIDBKeyTypeString;
case kIndexedDBKeyDateTypeByte:
@@ -649,6 +698,7 @@ int CompareEncodedStringsWithLength(StringPiece* slice1,
return 0;
}
+ // Extract the string data, and advance the passed slices.
StringPiece string1(slice1->begin(), len1 * sizeof(char16));
StringPiece string2(slice2->begin(), len2 * sizeof(char16));
slice1->remove_prefix(len1 * sizeof(char16));
@@ -659,6 +709,41 @@ int CompareEncodedStringsWithLength(StringPiece* slice1,
return string1.compare(string2);
}
+int CompareEncodedBinary(StringPiece* slice1,
+ StringPiece* slice2,
+ bool* ok) {
+ int64 len1, len2;
+ if (!DecodeVarInt(slice1, &len1) || !DecodeVarInt(slice2, &len2)) {
+ *ok = false;
+ return 0;
+ }
+ DCHECK_GE(len1, 0);
+ DCHECK_GE(len2, 0);
+ if (len1 < 0 || len2 < 0) {
+ *ok = false;
+ return 0;
+ }
+ size_t size1 = len1;
+ size_t size2 = len2;
+
+ DCHECK_GE(slice1->size(), size1);
+ DCHECK_GE(slice2->size(), size2);
+ if (slice1->size() < size1 || slice2->size() < size2) {
+ *ok = false;
+ return 0;
+ }
+
+ // Extract the binary data, and advance the passed slices.
+ StringPiece binary1(slice1->begin(), size1);
+ StringPiece binary2(slice2->begin(), size2);
+ slice1->remove_prefix(size1);
+ slice2->remove_prefix(size2);
+
+ *ok = true;
+ // This is the same as a memcmp()
+ return binary1.compare(binary2);
+}
+
static int CompareInts(int64 a, int64 b) {
#ifndef NDEBUG
// Exercised by unit tests in debug only.
@@ -717,6 +802,8 @@ int CompareEncodedIDBKeys(StringPiece* slice_a,
}
return length_a - length_b;
}
+ case kIndexedDBKeyBinaryTypeByte:
+ return CompareEncodedBinary(slice_a, slice_b, ok);
case kIndexedDBKeyStringTypeByte:
return CompareEncodedStringsWithLength(slice_a, slice_b, ok);
case kIndexedDBKeyDateTypeByte:
@@ -738,17 +825,6 @@ int CompareEncodedIDBKeys(StringPiece* slice_a,
return 0;
}
-int CompareEncodedIDBKeys(const std::string& key_a,
- const std::string& key_b,
- bool* ok) {
- DCHECK(!key_a.empty());
- DCHECK(!key_b.empty());
-
- StringPiece slice_a(key_a);
- StringPiece slice_b(key_b);
- return CompareEncodedIDBKeys(&slice_a, &slice_b, ok);
-}
-
namespace {
template <typename KeyType>
@@ -794,34 +870,6 @@ int CompareSuffix<ExistsEntryKey>(StringPiece* slice_a,
}
template <>
-int Compare<ExistsEntryKey>(const StringPiece& a,
- const StringPiece& b,
- bool only_compare_index_keys,
- bool* ok) {
- KeyPrefix prefix_a;
- KeyPrefix prefix_b;
- StringPiece slice_a(a);
- StringPiece slice_b(b);
- bool ok_a = KeyPrefix::Decode(&slice_a, &prefix_a);
- bool ok_b = KeyPrefix::Decode(&slice_b, &prefix_b);
- DCHECK(ok_a);
- DCHECK(ok_b);
- DCHECK(prefix_a.database_id_);
- DCHECK(prefix_a.object_store_id_);
- DCHECK_EQ(prefix_a.index_id_, ExistsEntryKey::kSpecialIndexNumber);
- DCHECK(prefix_b.database_id_);
- DCHECK(prefix_b.object_store_id_);
- DCHECK_EQ(prefix_b.index_id_, ExistsEntryKey::kSpecialIndexNumber);
- DCHECK(!slice_a.empty());
- DCHECK(!slice_b.empty());
- // Prefixes are not compared - it is assumed this was already done.
- DCHECK(!prefix_a.Compare(prefix_b));
-
- return CompareSuffix<ExistsEntryKey>(
- &slice_a, &slice_b, only_compare_index_keys, ok);
-}
-
-template <>
int CompareSuffix<ObjectStoreDataKey>(StringPiece* slice_a,
StringPiece* slice_b,
bool only_compare_index_keys,
@@ -830,34 +878,6 @@ int CompareSuffix<ObjectStoreDataKey>(StringPiece* slice_a,
}
template <>
-int Compare<ObjectStoreDataKey>(const StringPiece& a,
- const StringPiece& b,
- bool only_compare_index_keys,
- bool* ok) {
- KeyPrefix prefix_a;
- KeyPrefix prefix_b;
- StringPiece slice_a(a);
- StringPiece slice_b(b);
- bool ok_a = KeyPrefix::Decode(&slice_a, &prefix_a);
- bool ok_b = KeyPrefix::Decode(&slice_b, &prefix_b);
- DCHECK(ok_a);
- DCHECK(ok_b);
- DCHECK(prefix_a.database_id_);
- DCHECK(prefix_a.object_store_id_);
- DCHECK_EQ(prefix_a.index_id_, ObjectStoreDataKey::kSpecialIndexNumber);
- DCHECK(prefix_b.database_id_);
- DCHECK(prefix_b.object_store_id_);
- DCHECK_EQ(prefix_b.index_id_, ObjectStoreDataKey::kSpecialIndexNumber);
- DCHECK(!slice_a.empty());
- DCHECK(!slice_b.empty());
- // Prefixes are not compared - it is assumed this was already done.
- DCHECK(!prefix_a.Compare(prefix_b));
-
- return CompareSuffix<ObjectStoreDataKey>(
- &slice_a, &slice_b, only_compare_index_keys, ok);
-}
-
-template <>
int CompareSuffix<IndexDataKey>(StringPiece* slice_a,
StringPiece* slice_b,
bool only_compare_index_keys,
@@ -888,34 +908,6 @@ int CompareSuffix<IndexDataKey>(StringPiece* slice_a,
return CompareInts(sequence_number_a, sequence_number_b);
}
-template <>
-int Compare<IndexDataKey>(const StringPiece& a,
- const StringPiece& b,
- bool only_compare_index_keys,
- bool* ok) {
- KeyPrefix prefix_a;
- KeyPrefix prefix_b;
- StringPiece slice_a(a);
- StringPiece slice_b(b);
- bool ok_a = KeyPrefix::Decode(&slice_a, &prefix_a);
- bool ok_b = KeyPrefix::Decode(&slice_b, &prefix_b);
- DCHECK(ok_a);
- DCHECK(ok_b);
- DCHECK(prefix_a.database_id_);
- DCHECK(prefix_a.object_store_id_);
- DCHECK_GE(prefix_a.index_id_, kMinimumIndexId);
- DCHECK(prefix_b.database_id_);
- DCHECK(prefix_b.object_store_id_);
- DCHECK_GE(prefix_b.index_id_, kMinimumIndexId);
- DCHECK(!slice_a.empty());
- DCHECK(!slice_b.empty());
- // Prefixes are not compared - it is assumed this was already done.
- DCHECK(!prefix_a.Compare(prefix_b));
-
- return CompareSuffix<IndexDataKey>(
- &slice_a, &slice_b, only_compare_index_keys, ok);
-}
-
int Compare(const StringPiece& a,
const StringPiece& b,
bool only_compare_index_keys,
@@ -963,12 +955,14 @@ int Compare(const StringPiece& a,
// specialized CompareSuffix<> because metadata is relatively uncommon
// in the database.
- if (type_byte_a == kDatabaseFreeListTypeByte)
- return Compare<DatabaseFreeListKey>(
- a, b, only_compare_index_keys, ok);
- if (type_byte_a == kDatabaseNameTypeByte)
+ if (type_byte_a == kDatabaseFreeListTypeByte) {
+ // TODO(jsbell): No need to pass only_compare_index_keys through here.
+ return Compare<DatabaseFreeListKey>(a, b, only_compare_index_keys, ok);
+ }
+ if (type_byte_a == kDatabaseNameTypeByte) {
return Compare<DatabaseNameKey>(
a, b, /*only_compare_index_keys*/ false, ok);
+ }
break;
}
@@ -997,24 +991,32 @@ int Compare(const StringPiece& a,
// specialized CompareSuffix<> because metadata is relatively uncommon
// in the database.
- if (type_byte_a == kObjectStoreMetaDataTypeByte)
+ if (type_byte_a == kObjectStoreMetaDataTypeByte) {
+ // TODO(jsbell): No need to pass only_compare_index_keys through here.
return Compare<ObjectStoreMetaDataKey>(
a, b, only_compare_index_keys, ok);
- if (type_byte_a == kIndexMetaDataTypeByte)
+ }
+ if (type_byte_a == kIndexMetaDataTypeByte) {
return Compare<IndexMetaDataKey>(
a, b, /*only_compare_index_keys*/ false, ok);
- if (type_byte_a == kObjectStoreFreeListTypeByte)
+ }
+ if (type_byte_a == kObjectStoreFreeListTypeByte) {
return Compare<ObjectStoreFreeListKey>(
a, b, only_compare_index_keys, ok);
- if (type_byte_a == kIndexFreeListTypeByte)
+ }
+ if (type_byte_a == kIndexFreeListTypeByte) {
return Compare<IndexFreeListKey>(
a, b, /*only_compare_index_keys*/ false, ok);
- if (type_byte_a == kObjectStoreNamesTypeByte)
+ }
+ if (type_byte_a == kObjectStoreNamesTypeByte) {
+ // TODO(jsbell): No need to pass only_compare_index_keys through here.
return Compare<ObjectStoreNamesKey>(
a, b, only_compare_index_keys, ok);
- if (type_byte_a == kIndexNamesKeyTypeByte)
+ }
+ if (type_byte_a == kIndexNamesKeyTypeByte) {
return Compare<IndexNamesKey>(
a, b, /*only_compare_index_keys*/ false, ok);
+ }
break;
}
@@ -1321,7 +1323,7 @@ bool DatabaseNameKey::Decode(StringPiece* slice, DatabaseNameKey* result) {
}
std::string DatabaseNameKey::Encode(const std::string& origin_identifier,
- const string16& database_name) {
+ const base::string16& database_name) {
std::string ret = KeyPrefix::EncodeEmpty();
ret.push_back(kDatabaseNameTypeByte);
EncodeStringWithLength(base::ASCIIToUTF16(origin_identifier), &ret);
@@ -1331,7 +1333,7 @@ std::string DatabaseNameKey::Encode(const std::string& origin_identifier,
std::string DatabaseNameKey::EncodeMinKeyForOrigin(
const std::string& origin_identifier) {
- return Encode(origin_identifier, string16());
+ return Encode(origin_identifier, base::string16());
}
std::string DatabaseNameKey::EncodeStopKeyForOrigin(
@@ -1601,8 +1603,9 @@ bool ObjectStoreNamesKey::Decode(StringPiece* slice,
return true;
}
-std::string ObjectStoreNamesKey::Encode(int64 database_id,
- const string16& object_store_name) {
+std::string ObjectStoreNamesKey::Encode(
+ int64 database_id,
+ const base::string16& object_store_name) {
KeyPrefix prefix(database_id);
std::string ret = prefix.Encode();
ret.push_back(kObjectStoreNamesTypeByte);
@@ -1638,7 +1641,7 @@ bool IndexNamesKey::Decode(StringPiece* slice, IndexNamesKey* result) {
std::string IndexNamesKey::Encode(int64 database_id,
int64 object_store_id,
- const string16& index_name) {
+ const base::string16& index_name) {
KeyPrefix prefix(database_id);
std::string ret = prefix.Encode();
ret.push_back(kIndexNamesKeyTypeByte);
@@ -1689,10 +1692,6 @@ std::string ObjectStoreDataKey::Encode(int64 database_id,
return Encode(database_id, object_store_id, encoded_key);
}
-int ObjectStoreDataKey::Compare(const ObjectStoreDataKey& other, bool* ok) {
- return CompareEncodedIDBKeys(encoded_user_key_, other.encoded_user_key_, ok);
-}
-
scoped_ptr<IndexedDBKey> ObjectStoreDataKey::user_key() const {
scoped_ptr<IndexedDBKey> key;
StringPiece slice(encoded_user_key_);
@@ -1737,10 +1736,6 @@ std::string ExistsEntryKey::Encode(int64 database_id,
return Encode(database_id, object_store_id, encoded_key);
}
-int ExistsEntryKey::Compare(const ExistsEntryKey& other, bool* ok) {
- return CompareEncodedIDBKeys(encoded_user_key_, other.encoded_user_key_, ok);
-}
-
scoped_ptr<IndexedDBKey> ExistsEntryKey::user_key() const {
scoped_ptr<IndexedDBKey> key;
StringPiece slice(encoded_user_key_);
@@ -1814,6 +1809,23 @@ std::string IndexDataKey::Encode(int64 database_id,
database_id, object_store_id, index_id, encoded_key, MinIDBKey(), 0);
}
+std::string IndexDataKey::Encode(int64 database_id,
+ int64 object_store_id,
+ int64 index_id,
+ const IndexedDBKey& user_key,
+ const IndexedDBKey& user_primary_key) {
+ std::string encoded_key;
+ EncodeIDBKey(user_key, &encoded_key);
+ std::string encoded_primary_key;
+ EncodeIDBKey(user_primary_key, &encoded_primary_key);
+ return Encode(database_id,
+ object_store_id,
+ index_id,
+ encoded_key,
+ encoded_primary_key,
+ 0);
+}
+
std::string IndexDataKey::EncodeMinKey(int64 database_id,
int64 object_store_id,
int64 index_id) {
@@ -1832,25 +1844,6 @@ std::string IndexDataKey::EncodeMaxKey(int64 database_id,
std::numeric_limits<int64>::max());
}
-int IndexDataKey::Compare(const IndexDataKey& other,
- bool only_compare_index_keys,
- bool* ok) {
- DCHECK_GE(database_id_, 0);
- DCHECK_GE(object_store_id_, 0);
- DCHECK_GE(index_id_, 0);
- int result =
- CompareEncodedIDBKeys(encoded_user_key_, other.encoded_user_key_, ok);
- if (!*ok || result)
- return result;
- if (only_compare_index_keys)
- return 0;
- result = CompareEncodedIDBKeys(
- encoded_primary_key_, other.encoded_primary_key_, ok);
- if (!*ok || result)
- return result;
- return CompareInts(sequence_number_, other.sequence_number_);
-}
-
int64 IndexDataKey::DatabaseId() const {
DCHECK_GE(database_id_, 0);
return database_id_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
index 974c27a4fa2..556b4605af2 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
@@ -27,9 +27,11 @@ CONTENT_EXPORT void EncodeByte(unsigned char value, std::string* into);
CONTENT_EXPORT void EncodeBool(bool value, std::string* into);
CONTENT_EXPORT void EncodeInt(int64 value, std::string* into);
CONTENT_EXPORT void EncodeVarInt(int64 value, std::string* into);
-CONTENT_EXPORT void EncodeString(const string16& value, std::string* into);
-CONTENT_EXPORT void EncodeStringWithLength(const string16& value,
+CONTENT_EXPORT void EncodeString(const base::string16& value,
+ std::string* into);
+CONTENT_EXPORT void EncodeStringWithLength(const base::string16& value,
std::string* into);
+CONTENT_EXPORT void EncodeBinary(const std::string& value, std::string* into);
CONTENT_EXPORT void EncodeDouble(double value, std::string* into);
CONTENT_EXPORT void EncodeIDBKey(const IndexedDBKey& value, std::string* into);
CONTENT_EXPORT void EncodeIDBKeyPath(const IndexedDBKeyPath& value,
@@ -44,10 +46,12 @@ CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeInt(base::StringPiece* slice,
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeVarInt(base::StringPiece* slice,
int64* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeString(base::StringPiece* slice,
- string16* value);
+ base::string16* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeStringWithLength(
base::StringPiece* slice,
- string16* value);
+ base::string16* value);
+CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeBinary(base::StringPiece* slice,
+ std::string* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeDouble(base::StringPiece* slice,
double* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeIDBKey(
@@ -65,8 +69,8 @@ CONTENT_EXPORT WARN_UNUSED_RESULT bool ExtractEncodedIDBKey(
base::StringPiece* slice,
std::string* result);
-CONTENT_EXPORT int CompareEncodedIDBKeys(const std::string& a,
- const std::string& b,
+CONTENT_EXPORT int CompareEncodedIDBKeys(base::StringPiece* slice1,
+ base::StringPiece* slice2,
bool* ok);
CONTENT_EXPORT int Compare(const base::StringPiece& a,
@@ -185,18 +189,19 @@ class DatabaseNameKey {
public:
static bool Decode(base::StringPiece* slice, DatabaseNameKey* result);
CONTENT_EXPORT static std::string Encode(const std::string& origin_identifier,
- const string16& database_name);
+ const base::string16& database_name);
static std::string EncodeMinKeyForOrigin(
const std::string& origin_identifier);
static std::string EncodeStopKeyForOrigin(
const std::string& origin_identifier);
- string16 origin() const { return origin_; }
- string16 database_name() const { return database_name_; }
+ base::string16 origin() const { return origin_; }
+ base::string16 database_name() const { return database_name_; }
int Compare(const DatabaseNameKey& other);
private:
- string16 origin_; // TODO(jsbell): Store encoded strings, or just pointers.
- string16 database_name_;
+ base::string16 origin_; // TODO(jsbell): Store encoded strings, or just
+ // pointers.
+ base::string16 database_name_;
};
class DatabaseMetaDataKey {
@@ -312,14 +317,15 @@ class ObjectStoreNamesKey {
// because a mapping is kept in the IndexedDBDatabase. Can the
// mapping become unreliable? Can we remove this?
static bool Decode(base::StringPiece* slice, ObjectStoreNamesKey* result);
- CONTENT_EXPORT static std::string Encode(int64 database_id,
- const string16& object_store_name);
+ CONTENT_EXPORT static std::string Encode(
+ int64 database_id,
+ const base::string16& object_store_name);
int Compare(const ObjectStoreNamesKey& other);
- string16 object_store_name() const { return object_store_name_; }
+ base::string16 object_store_name() const { return object_store_name_; }
private:
// TODO(jsbell): Store the encoded string, or just pointers to it.
- string16 object_store_name_;
+ base::string16 object_store_name_;
};
class IndexNamesKey {
@@ -330,13 +336,13 @@ class IndexNamesKey {
static bool Decode(base::StringPiece* slice, IndexNamesKey* result);
CONTENT_EXPORT static std::string Encode(int64 database_id,
int64 object_store_id,
- const string16& index_name);
+ const base::string16& index_name);
int Compare(const IndexNamesKey& other);
- string16 index_name() const { return index_name_; }
+ base::string16 index_name() const { return index_name_; }
private:
int64 object_store_id_;
- string16 index_name_;
+ base::string16 index_name_;
};
class ObjectStoreDataKey {
@@ -348,7 +354,6 @@ class ObjectStoreDataKey {
static std::string Encode(int64 database_id,
int64 object_store_id,
const IndexedDBKey& user_key);
- int Compare(const ObjectStoreDataKey& other, bool* ok);
scoped_ptr<IndexedDBKey> user_key() const;
static const int64 kSpecialIndexNumber;
ObjectStoreDataKey();
@@ -370,7 +375,6 @@ class ExistsEntryKey {
static std::string Encode(int64 database_id,
int64 object_store_id,
const IndexedDBKey& user_key);
- int Compare(const ExistsEntryKey& other, bool* ok);
scoped_ptr<IndexedDBKey> user_key() const;
static const int64 kSpecialIndexNumber;
@@ -396,15 +400,17 @@ class IndexDataKey {
int64 object_store_id,
int64 index_id,
const IndexedDBKey& user_key);
+ static std::string Encode(int64 database_id,
+ int64 object_store_id,
+ int64 index_id,
+ const IndexedDBKey& user_key,
+ const IndexedDBKey& user_primary_key);
static std::string EncodeMinKey(int64 database_id,
int64 object_store_id,
int64 index_id);
CONTENT_EXPORT static std::string EncodeMaxKey(int64 database_id,
int64 object_store_id,
int64 index_id);
- int Compare(const IndexDataKey& other,
- bool only_compare_index_keys,
- bool* ok);
int64 DatabaseId() const;
int64 ObjectStoreId() const;
int64 IndexId() const;
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
index 01f1260828b..44c4ab88cdb 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
@@ -16,8 +16,8 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
-using WebKit::WebIDBKeyTypeDate;
-using WebKit::WebIDBKeyTypeNumber;
+using blink::WebIDBKeyTypeDate;
+using blink::WebIDBKeyTypeNumber;
namespace content {
@@ -111,8 +111,13 @@ TEST(IndexedDBLevelDBCodingTest, EncodeBool) {
}
static int CompareKeys(const std::string& a, const std::string& b) {
+ DCHECK(!a.empty());
+ DCHECK(!b.empty());
+
+ StringPiece slice_a(a);
+ StringPiece slice_b(b);
bool ok;
- int result = CompareEncodedIDBKeys(a, b, &ok);
+ int result = CompareEncodedIDBKeys(&slice_a, &slice_b, &ok);
EXPECT_TRUE(ok);
return result;
}
@@ -123,6 +128,8 @@ TEST(IndexedDBLevelDBCodingTest, MaxIDBKey) {
std::string min_key = MinIDBKey();
std::string array_key;
EncodeIDBKey(IndexedDBKey(IndexedDBKey::KeyArray()), &array_key);
+ std::string binary_key;
+ EncodeIDBKey(IndexedDBKey(std::string("\x00\x01\x02")), &binary_key);
std::string string_key;
EncodeIDBKey(IndexedDBKey(ASCIIToUTF16("Hello world")), &string_key);
std::string number_key;
@@ -132,6 +139,7 @@ TEST(IndexedDBLevelDBCodingTest, MaxIDBKey) {
EXPECT_GT(CompareKeys(max_key, min_key), 0);
EXPECT_GT(CompareKeys(max_key, array_key), 0);
+ EXPECT_GT(CompareKeys(max_key, binary_key), 0);
EXPECT_GT(CompareKeys(max_key, string_key), 0);
EXPECT_GT(CompareKeys(max_key, number_key), 0);
EXPECT_GT(CompareKeys(max_key, date_key), 0);
@@ -143,6 +151,8 @@ TEST(IndexedDBLevelDBCodingTest, MinIDBKey) {
std::string max_key = MaxIDBKey();
std::string array_key;
EncodeIDBKey(IndexedDBKey(IndexedDBKey::KeyArray()), &array_key);
+ std::string binary_key;
+ EncodeIDBKey(IndexedDBKey(std::string("\x00\x01\x02")), &binary_key);
std::string string_key;
EncodeIDBKey(IndexedDBKey(ASCIIToUTF16("Hello world")), &string_key);
std::string number_key;
@@ -152,6 +162,7 @@ TEST(IndexedDBLevelDBCodingTest, MinIDBKey) {
EXPECT_LT(CompareKeys(min_key, max_key), 0);
EXPECT_LT(CompareKeys(min_key, array_key), 0);
+ EXPECT_LT(CompareKeys(min_key, binary_key), 0);
EXPECT_LT(CompareKeys(min_key, string_key), 0);
EXPECT_LT(CompareKeys(min_key, number_key), 0);
EXPECT_LT(CompareKeys(min_key, date_key), 0);
@@ -298,7 +309,7 @@ TEST(IndexedDBLevelDBCodingTest, DecodeVarInt) {
}
}
-static std::string WrappedEncodeString(string16 value) {
+static std::string WrappedEncodeString(base::string16 value) {
std::string buffer;
EncodeString(value, &buffer);
return buffer;
@@ -315,24 +326,24 @@ TEST(IndexedDBLevelDBCodingTest, EncodeString) {
EXPECT_EQ(static_cast<size_t>(6),
WrappedEncodeString(ASCIIToUTF16("foo")).size());
EXPECT_EQ(static_cast<size_t>(6),
- WrappedEncodeString(string16(test_string_a)).size());
+ WrappedEncodeString(base::string16(test_string_a)).size());
EXPECT_EQ(static_cast<size_t>(4),
- WrappedEncodeString(string16(test_string_b)).size());
+ WrappedEncodeString(base::string16(test_string_b)).size());
}
TEST(IndexedDBLevelDBCodingTest, DecodeString) {
const char16 test_string_a[] = {'f', 'o', 'o', '\0'};
const char16 test_string_b[] = {0xdead, 0xbeef, '\0'};
- std::vector<string16> test_cases;
- test_cases.push_back(string16());
+ std::vector<base::string16> test_cases;
+ test_cases.push_back(base::string16());
test_cases.push_back(ASCIIToUTF16("a"));
test_cases.push_back(ASCIIToUTF16("foo"));
test_cases.push_back(test_string_a);
test_cases.push_back(test_string_b);
for (size_t i = 0; i < test_cases.size(); ++i) {
- const string16& test_case = test_cases[i];
+ const base::string16& test_case = test_cases[i];
std::string v = WrappedEncodeString(test_case);
StringPiece slice;
@@ -340,7 +351,7 @@ TEST(IndexedDBLevelDBCodingTest, DecodeString) {
slice = StringPiece(&*v.begin(), v.size());
}
- string16 result;
+ base::string16 result;
EXPECT_TRUE(DecodeString(&slice, &result));
EXPECT_EQ(test_case, result);
EXPECT_TRUE(slice.empty());
@@ -354,7 +365,7 @@ TEST(IndexedDBLevelDBCodingTest, DecodeString) {
}
}
-static std::string WrappedEncodeStringWithLength(string16 value) {
+static std::string WrappedEncodeStringWithLength(base::string16 value) {
std::string buffer;
EncodeStringWithLength(value, &buffer);
return buffer;
@@ -365,13 +376,15 @@ TEST(IndexedDBLevelDBCodingTest, EncodeStringWithLength) {
const char16 test_string_b[] = {0xdead, 0xbeef, '\0'};
EXPECT_EQ(static_cast<size_t>(1),
- WrappedEncodeStringWithLength(string16()).size());
+ WrappedEncodeStringWithLength(base::string16()).size());
EXPECT_EQ(static_cast<size_t>(3),
WrappedEncodeStringWithLength(ASCIIToUTF16("a")).size());
EXPECT_EQ(static_cast<size_t>(7),
- WrappedEncodeStringWithLength(string16(test_string_a)).size());
+ WrappedEncodeStringWithLength(
+ base::string16(test_string_a)).size());
EXPECT_EQ(static_cast<size_t>(5),
- WrappedEncodeStringWithLength(string16(test_string_b)).size());
+ WrappedEncodeStringWithLength(
+ base::string16(test_string_b)).size());
}
TEST(IndexedDBLevelDBCodingTest, DecodeStringWithLength) {
@@ -384,20 +397,20 @@ TEST(IndexedDBLevelDBCodingTest, DecodeStringWithLength) {
long_string[i] = i;
long_string[kLongStringLen] = 0;
- std::vector<string16> test_cases;
+ std::vector<base::string16> test_cases;
test_cases.push_back(ASCIIToUTF16(""));
test_cases.push_back(ASCIIToUTF16("a"));
test_cases.push_back(ASCIIToUTF16("foo"));
- test_cases.push_back(string16(test_string_a));
- test_cases.push_back(string16(test_string_b));
- test_cases.push_back(string16(long_string));
+ test_cases.push_back(base::string16(test_string_a));
+ test_cases.push_back(base::string16(test_string_b));
+ test_cases.push_back(base::string16(long_string));
for (size_t i = 0; i < test_cases.size(); ++i) {
- string16 s = test_cases[i];
+ base::string16 s = test_cases[i];
std::string v = WrappedEncodeStringWithLength(s);
ASSERT_GT(v.size(), static_cast<size_t>(0));
StringPiece slice(v);
- string16 res;
+ base::string16 res;
EXPECT_TRUE(DecodeStringWithLength(&slice, &res));
EXPECT_EQ(s, res);
EXPECT_TRUE(slice.empty());
@@ -438,23 +451,23 @@ TEST(IndexedDBLevelDBCodingTest, CompareEncodedStringsWithLength) {
const char16 test_string_e[] = {0xd834, 0xdd1e, '\0'};
const char16 test_string_f[] = {0xfffd, '\0'};
- std::vector<string16> test_cases;
+ std::vector<base::string16> test_cases;
test_cases.push_back(ASCIIToUTF16(""));
test_cases.push_back(ASCIIToUTF16("a"));
test_cases.push_back(ASCIIToUTF16("b"));
test_cases.push_back(ASCIIToUTF16("baaa"));
test_cases.push_back(ASCIIToUTF16("baab"));
test_cases.push_back(ASCIIToUTF16("c"));
- test_cases.push_back(string16(test_string_a));
- test_cases.push_back(string16(test_string_b));
- test_cases.push_back(string16(test_string_c));
- test_cases.push_back(string16(test_string_d));
- test_cases.push_back(string16(test_string_e));
- test_cases.push_back(string16(test_string_f));
+ test_cases.push_back(base::string16(test_string_a));
+ test_cases.push_back(base::string16(test_string_b));
+ test_cases.push_back(base::string16(test_string_c));
+ test_cases.push_back(base::string16(test_string_d));
+ test_cases.push_back(base::string16(test_string_e));
+ test_cases.push_back(base::string16(test_string_f));
for (size_t i = 0; i < test_cases.size() - 1; ++i) {
- string16 a = test_cases[i];
- string16 b = test_cases[i + 1];
+ base::string16 a = test_cases[i];
+ base::string16 b = test_cases[i + 1];
EXPECT_LT(a.compare(b), 0);
EXPECT_GT(b.compare(a), 0);
@@ -473,6 +486,58 @@ TEST(IndexedDBLevelDBCodingTest, CompareEncodedStringsWithLength) {
}
}
+static std::string WrappedEncodeBinary(std::string value) {
+ std::string buffer;
+ EncodeBinary(value, &buffer);
+ return buffer;
+}
+
+TEST(IndexedDBLevelDBCodingTest, EncodeBinary) {
+ const unsigned char binary_data[] = {0x00, 0x01, 0xfe, 0xff};
+ EXPECT_EQ(
+ static_cast<size_t>(1),
+ WrappedEncodeBinary(std::string(binary_data, binary_data + 0)).size());
+ EXPECT_EQ(
+ static_cast<size_t>(2),
+ WrappedEncodeBinary(std::string(binary_data, binary_data + 1)).size());
+ EXPECT_EQ(
+ static_cast<size_t>(5),
+ WrappedEncodeBinary(std::string(binary_data, binary_data + 4)).size());
+}
+
+TEST(IndexedDBLevelDBCodingTest, DecodeBinary) {
+ const unsigned char binary_data[] = { 0x00, 0x01, 0xfe, 0xff };
+
+ std::vector<std::string> test_cases;
+ test_cases.push_back(std::string(binary_data, binary_data + 0));
+ test_cases.push_back(std::string(binary_data, binary_data + 1));
+ test_cases.push_back(std::string(binary_data, binary_data + 4));
+
+ for (size_t i = 0; i < test_cases.size(); ++i) {
+ std::string value = test_cases[i];
+ std::string v = WrappedEncodeBinary(value);
+ ASSERT_GT(v.size(), static_cast<size_t>(0));
+ StringPiece slice(v);
+ std::string result;
+ EXPECT_TRUE(DecodeBinary(&slice, &result));
+ EXPECT_EQ(value, result);
+ EXPECT_TRUE(slice.empty());
+
+ slice = StringPiece(&*v.begin(), v.size() - 1);
+ EXPECT_FALSE(DecodeBinary(&slice, &result));
+
+ slice = StringPiece(&*v.begin(), static_cast<size_t>(0));
+ EXPECT_FALSE(DecodeBinary(&slice, &result));
+
+ // Verify decoding at an offset, to detect unaligned memory access.
+ v.insert(v.begin(), static_cast<size_t>(1), static_cast<char>(0));
+ slice = StringPiece(&*v.begin() + 1, v.size() - 1);
+ EXPECT_TRUE(DecodeBinary(&slice, &result));
+ EXPECT_EQ(value, result);
+ EXPECT_TRUE(slice.empty());
+ }
+}
+
static std::string WrappedEncodeDouble(double value) {
std::string buffer;
EncodeDouble(value, &buffer);
@@ -524,12 +589,14 @@ TEST(IndexedDBLevelDBCodingTest, EncodeDecodeIDBKey) {
test_cases.push_back(IndexedDBKey(1234, WebIDBKeyTypeNumber));
test_cases.push_back(IndexedDBKey(7890, WebIDBKeyTypeDate));
test_cases.push_back(IndexedDBKey(ASCIIToUTF16("Hello World!")));
+ test_cases.push_back(IndexedDBKey(std::string("\x01\x02")));
test_cases.push_back(IndexedDBKey(IndexedDBKey::KeyArray()));
IndexedDBKey::KeyArray array;
array.push_back(IndexedDBKey(1234, WebIDBKeyTypeNumber));
array.push_back(IndexedDBKey(7890, WebIDBKeyTypeDate));
array.push_back(IndexedDBKey(ASCIIToUTF16("Hello World!")));
+ array.push_back(IndexedDBKey(std::string("\x01\x02")));
array.push_back(IndexedDBKey(IndexedDBKey::KeyArray()));
test_cases.push_back(IndexedDBKey(array));
@@ -570,7 +637,7 @@ TEST(IndexedDBLevelDBCodingTest, EncodeDecodeIDBKeyPath) {
}
{
- key_paths.push_back(IndexedDBKeyPath(string16()));
+ key_paths.push_back(IndexedDBKeyPath(base::string16()));
char expected[] = {0, 0, // Header
1, // Type is string
0 // Length is 0
@@ -601,8 +668,8 @@ TEST(IndexedDBLevelDBCodingTest, EncodeDecodeIDBKeyPath) {
}
{
- std::vector<string16> array;
- array.push_back(string16());
+ std::vector<base::string16> array;
+ array.push_back(base::string16());
array.push_back(ASCIIToUTF16("foo"));
array.push_back(ASCIIToUTF16("foo.bar"));
@@ -640,7 +707,7 @@ TEST(IndexedDBLevelDBCodingTest, DecodeLegacyIDBKeyPath) {
std::vector<std::string> encoded_paths;
{
- key_paths.push_back(IndexedDBKeyPath(string16()));
+ key_paths.push_back(IndexedDBKeyPath(base::string16()));
encoded_paths.push_back(std::string());
}
{
@@ -685,6 +752,15 @@ TEST(IndexedDBLevelDBCodingTest, ExtractAndCompareIDBKeys) {
keys.push_back(IndexedDBKey(ASCIIToUTF16("baab")));
keys.push_back(IndexedDBKey(ASCIIToUTF16("c")));
+ keys.push_back(IndexedDBKey(std::string()));
+ keys.push_back(IndexedDBKey(std::string("\x01")));
+ keys.push_back(IndexedDBKey(std::string("\x01\x01")));
+ keys.push_back(IndexedDBKey(std::string("\x01\x02")));
+ keys.push_back(IndexedDBKey(std::string("\x02")));
+ keys.push_back(IndexedDBKey(std::string("\x02\x01")));
+ keys.push_back(IndexedDBKey(std::string("\x02\x02")));
+ keys.push_back(IndexedDBKey(std::string("\xff")));
+
keys.push_back(CreateArrayIDBKey());
keys.push_back(CreateArrayIDBKey(IndexedDBKey(0, WebIDBKeyTypeNumber)));
keys.push_back(CreateArrayIDBKey(IndexedDBKey(0, WebIDBKeyTypeNumber),
diff --git a/chromium/content/browser/indexed_db/indexed_db_metadata.cc b/chromium/content/browser/indexed_db/indexed_db_metadata.cc
index 80d31424c5f..47b7219f15b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_metadata.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_metadata.cc
@@ -7,7 +7,7 @@
namespace content {
IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata(
- const string16& name,
+ const base::string16& name,
int64 id,
const IndexedDBKeyPath& key_path,
bool auto_increment,
@@ -23,11 +23,12 @@ IndexedDBObjectStoreMetadata::~IndexedDBObjectStoreMetadata() {}
IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata()
: int_version(NO_INT_VERSION) {}
-IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(const string16& name,
- int64 id,
- const string16& version,
- int64 int_version,
- int64 max_object_store_id)
+IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(
+ const base::string16& name,
+ int64 id,
+ const base::string16& version,
+ int64 int_version,
+ int64 max_object_store_id)
: name(name),
id(id),
version(version),
diff --git a/chromium/content/browser/indexed_db/indexed_db_metadata.h b/chromium/content/browser/indexed_db/indexed_db_metadata.h
index 4e8562d1f68..00970a61ee5 100644
--- a/chromium/content/browser/indexed_db/indexed_db_metadata.h
+++ b/chromium/content/browser/indexed_db/indexed_db_metadata.h
@@ -15,7 +15,7 @@ namespace content {
struct IndexedDBIndexMetadata {
IndexedDBIndexMetadata() {}
- IndexedDBIndexMetadata(const string16& name,
+ IndexedDBIndexMetadata(const base::string16& name,
int64 id,
const IndexedDBKeyPath& key_path,
bool unique,
@@ -25,7 +25,7 @@ struct IndexedDBIndexMetadata {
key_path(key_path),
unique(unique),
multi_entry(multi_entry) {}
- string16 name;
+ base::string16 name;
int64 id;
IndexedDBKeyPath key_path;
bool unique;
@@ -36,13 +36,13 @@ struct IndexedDBIndexMetadata {
struct CONTENT_EXPORT IndexedDBObjectStoreMetadata {
IndexedDBObjectStoreMetadata();
- IndexedDBObjectStoreMetadata(const string16& name,
+ IndexedDBObjectStoreMetadata(const base::string16& name,
int64 id,
const IndexedDBKeyPath& key_path,
bool auto_increment,
int64 max_index_id);
~IndexedDBObjectStoreMetadata();
- string16 name;
+ base::string16 name;
int64 id;
IndexedDBKeyPath key_path;
bool auto_increment;
@@ -64,16 +64,16 @@ struct CONTENT_EXPORT IndexedDBDatabaseMetadata {
typedef std::map<int64, IndexedDBObjectStoreMetadata> ObjectStoreMap;
IndexedDBDatabaseMetadata();
- IndexedDBDatabaseMetadata(const string16& name,
+ IndexedDBDatabaseMetadata(const base::string16& name,
int64 id,
- const string16& version,
+ const base::string16& version,
int64 int_version,
int64 max_object_store_id);
~IndexedDBDatabaseMetadata();
- string16 name;
+ base::string16 name;
int64 id;
- string16 version;
+ base::string16 version;
int64 int_version;
int64 max_object_store_id;
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 5f3f01916ac..cd2f146deb7 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
@@ -66,7 +66,7 @@ class IndexedDBQuotaClientTest : public testing::Test {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
base::FilePath indexeddb_dir =
temp_dir_.path().Append(IndexedDBContextImpl::kIndexedDBDirectory);
- ASSERT_TRUE(file_util::CreateDirectory(indexeddb_dir));
+ ASSERT_TRUE(base::CreateDirectory(indexeddb_dir));
idb_context()->set_data_path_for_testing(indexeddb_dir);
}
@@ -141,8 +141,8 @@ class IndexedDBQuotaClientTest : public testing::Test {
void AddFakeIndexedDB(const GURL& origin, int size) {
base::FilePath file_path_origin = idb_context()->GetFilePathForTesting(
webkit_database::GetIdentifierFromOrigin(origin));
- if (!file_util::CreateDirectory(file_path_origin)) {
- LOG(ERROR) << "failed to file_util::CreateDirectory "
+ if (!base::CreateDirectory(file_path_origin)) {
+ LOG(ERROR) << "failed to base::CreateDirectory "
<< file_path_origin.value();
}
file_path_origin = file_path_origin.Append(FILE_PATH_LITERAL("fake_file"));
@@ -166,10 +166,12 @@ class IndexedDBQuotaClientTest : public testing::Test {
std::set<GURL> origins_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
scoped_refptr<IndexedDBContextImpl> idb_context_;
- base::WeakPtrFactory<IndexedDBQuotaClientTest> weak_factory_;
content::TestBrowserThreadBundle thread_bundle_;
scoped_ptr<TestBrowserContext> browser_context_;
quota::QuotaStatusCode delete_status_;
+ base::WeakPtrFactory<IndexedDBQuotaClientTest> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBQuotaClientTest);
};
TEST_F(IndexedDBQuotaClientTest, GetOriginUsage) {
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction.cc b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
index 3916726f531..387b1500efa 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
@@ -18,6 +18,8 @@
namespace content {
+const int64 kInactivityTimeoutPeriodSeconds = 60;
+
IndexedDBTransaction::TaskQueue::TaskQueue() {}
IndexedDBTransaction::TaskQueue::~TaskQueue() { clear(); }
@@ -53,22 +55,25 @@ IndexedDBTransaction::IndexedDBTransaction(
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks,
const std::set<int64>& object_store_ids,
indexed_db::TransactionMode mode,
- IndexedDBDatabase* database)
+ IndexedDBDatabase* database,
+ IndexedDBBackingStore::Transaction* backing_store_transaction)
: id_(id),
object_store_ids_(object_store_ids),
mode_(mode),
- state_(UNUSED),
+ used_(false),
+ state_(CREATED),
commit_pending_(false),
callbacks_(callbacks),
database_(database),
- transaction_(database->BackingStore().get()),
+ transaction_(backing_store_transaction),
+ backing_store_transaction_begun_(false),
should_process_queue_(false),
- pending_preemptive_events_(0),
- queue_status_(CREATED),
- creation_time_(base::Time::Now()),
- tasks_scheduled_(0),
- tasks_completed_(0) {
+ pending_preemptive_events_(0) {
database_->transaction_coordinator().DidCreateTransaction(this);
+
+ diagnostics_.tasks_scheduled = 0;
+ diagnostics_.tasks_completed = 0;
+ diagnostics_.creation_time = base::Time::Now();
}
IndexedDBTransaction::~IndexedDBTransaction() {
@@ -83,10 +88,13 @@ IndexedDBTransaction::~IndexedDBTransaction() {
void IndexedDBTransaction::ScheduleTask(Operation task, Operation abort_task) {
if (state_ == FINISHED)
return;
+
+ timeout_timer_.Stop();
+ used_ = true;
task_queue_.push(task);
- ++tasks_scheduled_;
+ ++diagnostics_.tasks_scheduled;
abort_task_stack_.push(abort_task);
- EnsureTasksRunning();
+ RunTasksIfStarted();
}
void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type,
@@ -94,27 +102,35 @@ void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type,
if (state_ == FINISHED)
return;
+ timeout_timer_.Stop();
+ used_ = true;
if (type == IndexedDBDatabase::NORMAL_TASK) {
task_queue_.push(task);
- ++tasks_scheduled_;
+ ++diagnostics_.tasks_scheduled;
} else {
preemptive_task_queue_.push(task);
}
- EnsureTasksRunning();
+ RunTasksIfStarted();
}
-void IndexedDBTransaction::EnsureTasksRunning() {
- if (state_ == UNUSED) {
- Start();
- } else if (state_ == RUNNING && !should_process_queue_) {
- should_process_queue_ = true;
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&IndexedDBTransaction::ProcessTaskQueue, this));
- }
+void IndexedDBTransaction::RunTasksIfStarted() {
+ DCHECK(used_);
+
+ // Not started by the coordinator yet.
+ if (state_ != STARTED)
+ return;
+
+ // A task is already posted.
+ if (should_process_queue_)
+ return;
+
+ should_process_queue_ = true;
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&IndexedDBTransaction::ProcessTaskQueue, this));
}
void IndexedDBTransaction::Abort() {
- Abort(IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error (unknown cause)"));
}
@@ -123,24 +139,23 @@ void IndexedDBTransaction::Abort(const IndexedDBDatabaseError& error) {
if (state_ == FINISHED)
return;
- bool was_running = state_ == RUNNING;
-
// The last reference to this object may be released while performing the
// abort steps below. We therefore take a self reference to keep ourselves
// alive while executing this method.
scoped_refptr<IndexedDBTransaction> protect(this);
+ timeout_timer_.Stop();
+
state_ = FINISHED;
should_process_queue_ = false;
- if (was_running)
- transaction_.Rollback();
+ if (backing_store_transaction_begun_)
+ transaction_->Rollback();
// Run the abort tasks, if any.
- while (!abort_task_stack_.empty()) {
- Operation task(abort_task_stack_.pop());
- task.Run(0);
- }
+ while (!abort_task_stack_.empty())
+ abort_task_stack_.pop().Run(0);
+
preemptive_task_queue_.clear();
task_queue_.clear();
@@ -149,7 +164,7 @@ void IndexedDBTransaction::Abort(const IndexedDBDatabaseError& error) {
// release references and allow the backing store itself to be
// released, and order is critical.
CloseOpenCursors();
- transaction_.Reset();
+ transaction_->Reset();
// Transactions must also be marked as completed before the
// front-end is notified, as the transaction completion unblocks
@@ -184,23 +199,17 @@ void IndexedDBTransaction::UnregisterOpenCursor(IndexedDBCursor* cursor) {
open_cursors_.erase(cursor);
}
-void IndexedDBTransaction::Run() {
+void IndexedDBTransaction::Start() {
// TransactionCoordinator has started this transaction.
- DCHECK(state_ == START_PENDING || state_ == RUNNING);
- DCHECK(!should_process_queue_);
-
- start_time_ = base::Time::Now();
- should_process_queue_ = true;
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&IndexedDBTransaction::ProcessTaskQueue, this));
-}
+ DCHECK_EQ(CREATED, state_);
+ state_ = STARTED;
+ database_->TransactionStarted(this);
+ diagnostics_.start_time = base::Time::Now();
-void IndexedDBTransaction::Start() {
- DCHECK_EQ(state_, UNUSED);
+ if (!used_)
+ return;
- state_ = START_PENDING;
- database_->transaction_coordinator().DidStartTransaction(this);
- database_->TransactionStarted(this);
+ RunTasksIfStarted();
}
void IndexedDBTransaction::Commit() {
@@ -212,7 +221,7 @@ void IndexedDBTransaction::Commit() {
if (state_ == FINISHED)
return;
- DCHECK(state_ == UNUSED || state_ == RUNNING);
+ DCHECK(!used_ || state_ == STARTED);
commit_pending_ = true;
// Front-end has requested a commit, but there may be tasks like
@@ -226,20 +235,18 @@ void IndexedDBTransaction::Commit() {
// alive while executing this method.
scoped_refptr<IndexedDBTransaction> protect(this);
- // TODO(jsbell): Run abort tasks if commit fails? http://crbug.com/241843
- abort_task_stack_.clear();
+ timeout_timer_.Stop();
- bool unused = state_ == UNUSED;
state_ = FINISHED;
- bool committed = unused || transaction_.Commit();
+ bool committed = !used_ || transaction_->Commit();
// Backing store resources (held via cursors) must be released
// before script callbacks are fired, as the script callbacks may
// release references and allow the backing store itself to be
// released, and order is critical.
CloseOpenCursors();
- transaction_.Reset();
+ transaction_->Reset();
// Transactions must also be marked as completed before the
// front-end is notified, as the transaction completion unblocks
@@ -248,14 +255,19 @@ void IndexedDBTransaction::Commit() {
database_->TransactionFinished(this);
if (committed) {
+ abort_task_stack_.clear();
callbacks_->OnComplete(id_);
database_->TransactionFinishedAndCompleteFired(this);
} else {
+ while (!abort_task_stack_.empty())
+ abort_task_stack_.pop().Run(0);
+
callbacks_->OnAbort(
id_,
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError,
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error committing transaction."));
database_->TransactionFinishedAndAbortFired(this);
+ database_->TransactionCommitFailed();
}
database_ = NULL;
@@ -271,9 +283,9 @@ void IndexedDBTransaction::ProcessTaskQueue() {
DCHECK(!IsTaskQueueEmpty());
should_process_queue_ = false;
- if (state_ == START_PENDING) {
- transaction_.Begin();
- state_ = RUNNING;
+ if (!backing_store_transaction_begun_) {
+ transaction_->Begin();
+ backing_store_transaction_begun_ = true;
}
// The last reference to this object may be released while performing the
@@ -284,12 +296,12 @@ void IndexedDBTransaction::ProcessTaskQueue() {
TaskQueue* task_queue =
pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
while (!task_queue->empty() && state_ != FINISHED) {
- DCHECK_EQ(state_, RUNNING);
+ DCHECK_EQ(STARTED, state_);
Operation task(task_queue->pop());
task.Run(this);
if (!pending_preemptive_events_) {
- DCHECK(tasks_completed_ < tasks_scheduled_);
- ++tasks_completed_;
+ DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled);
+ ++diagnostics_.tasks_completed;
}
// Event itself may change which queue should be processed next.
@@ -299,8 +311,27 @@ void IndexedDBTransaction::ProcessTaskQueue() {
// If there are no pending tasks, we haven't already committed/aborted,
// and the front-end requested a commit, it is now safe to do so.
- if (!HasPendingTasks() && state_ != FINISHED && commit_pending_)
+ if (!HasPendingTasks() && state_ != FINISHED && commit_pending_) {
Commit();
+ return;
+ }
+
+ // The transaction may have been aborted while processing tasks.
+ if (state_ == FINISHED)
+ return;
+
+ // Otherwise, start a timer in case the front-end gets wedged and
+ // never requests further activity.
+ timeout_timer_.Start(
+ FROM_HERE,
+ base::TimeDelta::FromSeconds(kInactivityTimeoutPeriodSeconds),
+ base::Bind(&IndexedDBTransaction::Timeout, this));
+}
+
+void IndexedDBTransaction::Timeout() {
+ Abort(IndexedDBDatabaseError(
+ blink::WebIDBDatabaseExceptionTimeoutError,
+ ASCIIToUTF16("Transaction timed out due to inactivity.")));
}
void IndexedDBTransaction::CloseOpenCursors() {
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction.h b/chromium/content/browser/indexed_db/indexed_db_transaction.h
index 24f44490537..6684856e573 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction.h
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction.h
@@ -13,6 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_database.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
@@ -22,27 +23,32 @@ namespace content {
class IndexedDBCursor;
class IndexedDBDatabaseCallbacks;
-class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> {
+class CONTENT_EXPORT IndexedDBTransaction
+ : public NON_EXPORTED_BASE(base::RefCounted<IndexedDBTransaction>) {
public:
typedef base::Callback<void(IndexedDBTransaction*)> Operation;
- IndexedDBTransaction(int64 id,
- scoped_refptr<IndexedDBDatabaseCallbacks> callbacks,
- const std::set<int64>& object_store_ids,
- indexed_db::TransactionMode,
- IndexedDBDatabase* db);
+ IndexedDBTransaction(
+ int64 id,
+ scoped_refptr<IndexedDBDatabaseCallbacks> callbacks,
+ const std::set<int64>& object_store_ids,
+ indexed_db::TransactionMode,
+ IndexedDBDatabase* db,
+ IndexedDBBackingStore::Transaction* backing_store_transaction);
virtual void Abort();
void Commit();
-
void Abort(const IndexedDBDatabaseError& error);
- void Run();
+
+ // Called by the transaction coordinator when this transaction is unblocked.
+ void Start();
+
indexed_db::TransactionMode mode() const { return mode_; }
const std::set<int64>& scope() const { return object_store_ids_; }
+
void ScheduleTask(Operation task) {
ScheduleTask(IndexedDBDatabase::NORMAL_TASK, task);
}
-
void ScheduleTask(Operation task, Operation abort_task);
void ScheduleTask(IndexedDBDatabase::TaskType, Operation task);
void RegisterOpenCursor(IndexedDBCursor* cursor);
@@ -53,54 +59,49 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> {
DCHECK_GE(pending_preemptive_events_, 0);
}
IndexedDBBackingStore::Transaction* BackingStoreTransaction() {
- return &transaction_;
+ return transaction_.get();
}
int64 id() const { return id_; }
IndexedDBDatabase* database() const { return database_; }
IndexedDBDatabaseCallbacks* connection() const { return callbacks_; }
- bool IsRunning() const { return state_ == RUNNING; }
- // The following types/accessors are for diagnostics only.
- enum QueueStatus {
- CREATED,
- BLOCKED,
- UNBLOCKED,
+ enum State {
+ CREATED, // Created, but not yet started by coordinator.
+ STARTED, // Started by the coordinator.
+ FINISHED, // Either aborted or committed.
};
- QueueStatus queue_status() const { return queue_status_; }
- void set_queue_status(QueueStatus status) { queue_status_ = status; }
- base::Time creation_time() const { return creation_time_; }
- base::Time start_time() const { return start_time_; }
- int tasks_scheduled() const { return tasks_scheduled_; }
- int tasks_completed() const { return tasks_completed_; }
+ State state() const { return state_; }
+ bool IsTimeoutTimerRunning() const { return timeout_timer_.IsRunning(); }
- protected:
- virtual ~IndexedDBTransaction();
- friend class base::RefCounted<IndexedDBTransaction>;
+ struct Diagnostics {
+ base::Time creation_time;
+ base::Time start_time;
+ int tasks_scheduled;
+ int tasks_completed;
+ };
+
+ const Diagnostics& diagnostics() const { return diagnostics_; }
private:
- enum State {
- UNUSED, // Created, but no tasks yet.
- START_PENDING, // Enqueued tasks, but backing store transaction not yet
- // started.
- RUNNING, // Backing store transaction started but not yet finished.
- FINISHED, // Either aborted or committed.
- };
+ friend class base::RefCounted<IndexedDBTransaction>;
+ virtual ~IndexedDBTransaction();
- void EnsureTasksRunning();
- void Start();
+ void RunTasksIfStarted();
bool IsTaskQueueEmpty() const;
bool HasPendingTasks() const;
void ProcessTaskQueue();
void CloseOpenCursors();
+ void Timeout();
const int64 id_;
const std::set<int64> object_store_ids_;
const indexed_db::TransactionMode mode_;
+ bool used_;
State state_;
bool commit_pending_;
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks_;
@@ -136,19 +137,20 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> {
TaskQueue preemptive_task_queue_;
TaskStack abort_task_stack_;
- IndexedDBBackingStore::Transaction transaction_;
+ scoped_ptr<IndexedDBBackingStore::Transaction> transaction_;
+ bool backing_store_transaction_begun_;
bool should_process_queue_;
int pending_preemptive_events_;
std::set<IndexedDBCursor*> open_cursors_;
- // The following members are for diagnostics only.
- QueueStatus queue_status_;
- base::Time creation_time_;
- base::Time start_time_;
- int tasks_scheduled_;
- int tasks_completed_;
+ // This timer is started after requests have been processed. If no subsequent
+ // requests are processed before the timer fires, assume the script is
+ // unresponsive and abort to unblock the transaction queue.
+ base::OneShotTimer<IndexedDBTransaction> timeout_timer_;
+
+ Diagnostics diagnostics_;
};
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
index 7be7bcafcaf..be47624cf4a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
@@ -13,40 +13,31 @@ namespace content {
IndexedDBTransactionCoordinator::IndexedDBTransactionCoordinator() {}
IndexedDBTransactionCoordinator::~IndexedDBTransactionCoordinator() {
- DCHECK(!transactions_.size());
DCHECK(!queued_transactions_.size());
DCHECK(!started_transactions_.size());
}
void IndexedDBTransactionCoordinator::DidCreateTransaction(
- IndexedDBTransaction* transaction) {
- DCHECK(transactions_.find(transaction) == transactions_.end());
- DCHECK(transaction->queue_status() == IndexedDBTransaction::CREATED);
- transactions_[transaction] = transaction;
-}
-
-void IndexedDBTransactionCoordinator::DidStartTransaction(
- IndexedDBTransaction* transaction) {
- DCHECK(transactions_.find(transaction) != transactions_.end());
+ scoped_refptr<IndexedDBTransaction> transaction) {
+ DCHECK(!queued_transactions_.count(transaction));
+ DCHECK(!started_transactions_.count(transaction));
+ DCHECK_EQ(IndexedDBTransaction::CREATED, transaction->state());
queued_transactions_.insert(transaction);
- ProcessStartedTransactions();
+ ProcessQueuedTransactions();
}
void IndexedDBTransactionCoordinator::DidFinishTransaction(
- IndexedDBTransaction* transaction) {
- DCHECK(transactions_.find(transaction) != transactions_.end());
-
- if (queued_transactions_.has(transaction)) {
- DCHECK(!started_transactions_.has(transaction));
+ scoped_refptr<IndexedDBTransaction> transaction) {
+ if (queued_transactions_.count(transaction)) {
+ DCHECK(!started_transactions_.count(transaction));
queued_transactions_.erase(transaction);
} else {
- if (started_transactions_.has(transaction))
- started_transactions_.erase(transaction);
+ DCHECK(started_transactions_.count(transaction));
+ started_transactions_.erase(transaction);
}
- transactions_.erase(transaction);
- ProcessStartedTransactions();
+ ProcessQueuedTransactions();
}
#ifndef NDEBUG
@@ -54,13 +45,12 @@ void IndexedDBTransactionCoordinator::DidFinishTransaction(
bool IndexedDBTransactionCoordinator::IsActive(
IndexedDBTransaction* transaction) {
bool found = false;
- if (queued_transactions_.has(transaction))
+ if (queued_transactions_.count(transaction))
found = true;
- if (started_transactions_.has(transaction)) {
+ if (started_transactions_.count(transaction)) {
DCHECK(!found);
found = true;
}
- DCHECK_EQ(found, (transactions_.find(transaction) != transactions_.end()));
return found;
}
#endif
@@ -69,14 +59,12 @@ std::vector<const IndexedDBTransaction*>
IndexedDBTransactionCoordinator::GetTransactions() const {
std::vector<const IndexedDBTransaction*> result;
- for (list_set<IndexedDBTransaction*>::const_iterator it =
- started_transactions_.begin();
+ for (TransactionSet::const_iterator it = started_transactions_.begin();
it != started_transactions_.end();
++it) {
result.push_back(*it);
}
- for (list_set<IndexedDBTransaction*>::const_iterator it =
- queued_transactions_.begin();
+ for (TransactionSet::const_iterator it = queued_transactions_.begin();
it != queued_transactions_.end();
++it) {
result.push_back(*it);
@@ -85,7 +73,7 @@ IndexedDBTransactionCoordinator::GetTransactions() const {
return result;
}
-void IndexedDBTransactionCoordinator::ProcessStartedTransactions() {
+void IndexedDBTransactionCoordinator::ProcessQueuedTransactions() {
if (queued_transactions_.empty())
return;
@@ -100,31 +88,28 @@ void IndexedDBTransactionCoordinator::ProcessStartedTransactions() {
// data. ("Version change" transactions are exclusive, but handled by the
// connection sequencing in IndexedDBDatabase.)
std::set<int64> locked_scope;
- for (list_set<IndexedDBTransaction*>::const_iterator it =
- started_transactions_.begin();
+ for (TransactionSet::const_iterator it = started_transactions_.begin();
it != started_transactions_.end();
++it) {
IndexedDBTransaction* transaction = *it;
if (transaction->mode() == indexed_db::TRANSACTION_READ_WRITE) {
- // Running read/write transactions have exclusive access to the object
+ // Started read/write transactions have exclusive access to the object
// stores within their scopes.
locked_scope.insert(transaction->scope().begin(),
transaction->scope().end());
}
}
- list_set<IndexedDBTransaction*>::const_iterator it =
- queued_transactions_.begin();
+ TransactionSet::const_iterator it = queued_transactions_.begin();
while (it != queued_transactions_.end()) {
- IndexedDBTransaction* transaction = *it;
+ scoped_refptr<IndexedDBTransaction> transaction = *it;
++it;
- if (CanRunTransaction(transaction, locked_scope)) {
- transaction->set_queue_status(IndexedDBTransaction::UNBLOCKED);
+ if (CanStartTransaction(transaction, locked_scope)) {
+ DCHECK_EQ(IndexedDBTransaction::CREATED, transaction->state());
queued_transactions_.erase(transaction);
started_transactions_.insert(transaction);
- transaction->Run();
- } else {
- transaction->set_queue_status(IndexedDBTransaction::BLOCKED);
+ transaction->Start();
+ DCHECK_EQ(IndexedDBTransaction::STARTED, transaction->state());
}
if (transaction->mode() == indexed_db::TRANSACTION_READ_WRITE) {
// Either the transaction started, so it has exclusive access to the
@@ -152,10 +137,10 @@ static bool DoSetsIntersect(const std::set<T>& set1,
return false;
}
-bool IndexedDBTransactionCoordinator::CanRunTransaction(
+bool IndexedDBTransactionCoordinator::CanStartTransaction(
IndexedDBTransaction* const transaction,
const std::set<int64>& locked_scope) const {
- DCHECK(queued_transactions_.has(transaction));
+ DCHECK(queued_transactions_.count(transaction));
switch (transaction->mode()) {
case indexed_db::TRANSACTION_VERSION_CHANGE:
DCHECK_EQ(static_cast<size_t>(1), queued_transactions_.size());
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h
index e123a4e7383..a5d543c1d8c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h
@@ -24,9 +24,8 @@ class IndexedDBTransactionCoordinator {
~IndexedDBTransactionCoordinator();
// Called by transactions as they start and finish.
- void DidCreateTransaction(IndexedDBTransaction* transaction);
- void DidStartTransaction(IndexedDBTransaction* transaction);
- void DidFinishTransaction(IndexedDBTransaction* transaction);
+ void DidCreateTransaction(scoped_refptr<IndexedDBTransaction> transaction);
+ void DidFinishTransaction(scoped_refptr<IndexedDBTransaction> transaction);
#ifndef NDEBUG
bool IsActive(IndexedDBTransaction* transaction);
@@ -36,19 +35,16 @@ class IndexedDBTransactionCoordinator {
std::vector<const IndexedDBTransaction*> GetTransactions() const;
private:
- void ProcessStartedTransactions();
- bool CanRunTransaction(IndexedDBTransaction* const transaction,
- const std::set<int64>& locked_scope) const;
-
- // This is just an efficient way to keep references to all transactions.
- std::map<IndexedDBTransaction*, scoped_refptr<IndexedDBTransaction> >
- transactions_;
+ void ProcessQueuedTransactions();
+ bool CanStartTransaction(IndexedDBTransaction* const transaction,
+ const std::set<int64>& locked_scope) const;
// Transactions in different states are grouped below.
// list_set is used to provide stable ordering; required by spec
// for the queue, convenience for diagnostics for the rest.
- list_set<IndexedDBTransaction*> queued_transactions_;
- list_set<IndexedDBTransaction*> started_transactions_;
+ typedef list_set<scoped_refptr<IndexedDBTransaction> > TransactionSet;
+ TransactionSet queued_transactions_;
+ TransactionSet started_transactions_;
};
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
new file mode 100644
index 00000000000..9aa68fa55dc
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
@@ -0,0 +1,125 @@
+// 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/indexed_db/indexed_db_transaction.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop/message_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"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+class IndexedDBTransactionTest : public testing::Test {
+ public:
+ IndexedDBTransactionTest() {
+ IndexedDBFactory* factory = NULL;
+ backing_store_ = new IndexedDBFakeBackingStore();
+ db_ = IndexedDBDatabase::Create(ASCIIToUTF16("db"),
+ backing_store_,
+ factory,
+ IndexedDBDatabase::Identifier());
+ }
+
+ void RunPostedTasks() { message_loop_.RunUntilIdle(); }
+ void DummyOperation(IndexedDBTransaction* transaction) {}
+
+ protected:
+ scoped_refptr<IndexedDBFakeBackingStore> backing_store_;
+ scoped_refptr<IndexedDBDatabase> db_;
+
+ private:
+ base::MessageLoop message_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBTransactionTest);
+};
+
+TEST_F(IndexedDBTransactionTest, Timeout) {
+ const int64 id = 0;
+ const std::set<int64> scope;
+ const bool commit_success = true;
+ scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction(
+ id,
+ new MockIndexedDBDatabaseCallbacks(),
+ scope,
+ indexed_db::TRANSACTION_READ_ONLY,
+ db_,
+ new IndexedDBFakeBackingStore::FakeTransaction(commit_success));
+ db_->TransactionCreated(transaction);
+
+ // No conflicting transactions, so coordinator will start it immediately:
+ EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state());
+ EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
+
+ // Schedule a task - timer won't be started until it's processed.
+ transaction->ScheduleTask(base::Bind(
+ &IndexedDBTransactionTest::DummyOperation, base::Unretained(this)));
+ EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
+
+ RunPostedTasks();
+ EXPECT_TRUE(transaction->IsTimeoutTimerRunning());
+
+ // Abort should cancel the timer.
+ transaction->Abort();
+ EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state());
+ EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
+
+ // This task will be ignored.
+ transaction->ScheduleTask(base::Bind(
+ &IndexedDBTransactionTest::DummyOperation, base::Unretained(this)));
+ EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state());
+ EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
+}
+
+class AbortObserver {
+ public:
+ AbortObserver() : abort_task_called_(false) {}
+
+ void AbortTask(IndexedDBTransaction* transaction) {
+ abort_task_called_ = true;
+ }
+
+ bool abort_task_called() const { return abort_task_called_; }
+
+ private:
+ bool abort_task_called_;
+ DISALLOW_COPY_AND_ASSIGN(AbortObserver);
+};
+
+TEST_F(IndexedDBTransactionTest, AbortTasks) {
+ const int64 id = 0;
+ const std::set<int64> scope;
+ const bool commit_failure = false;
+ scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction(
+ id,
+ new MockIndexedDBDatabaseCallbacks(),
+ scope,
+ indexed_db::TRANSACTION_READ_ONLY,
+ db_,
+ new IndexedDBFakeBackingStore::FakeTransaction(commit_failure));
+ db_->TransactionCreated(transaction);
+
+ AbortObserver observer;
+ transaction->ScheduleTask(
+ base::Bind(&IndexedDBTransactionTest::DummyOperation,
+ base::Unretained(this)),
+ base::Bind(&AbortObserver::AbortTask, base::Unretained(&observer)));
+
+ // Pump the message loop so that the transaction completes all pending tasks,
+ // otherwise it will defer the commit.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_FALSE(observer.abort_task_called());
+ transaction->Commit();
+ EXPECT_TRUE(observer.abort_task_called());
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
index c9aec2915f2..7c8f249f2cf 100644
--- a/chromium/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
@@ -9,6 +9,8 @@
#include "content/browser/browser_thread_impl.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
+#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/test_browser_context.h"
@@ -46,6 +48,8 @@ class IndexedDBTest : public testing::Test {
private:
BrowserThreadImpl file_thread_;
BrowserThreadImpl io_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBTest);
};
TEST_F(IndexedDBTest, ClearSessionOnlyDatabases) {
@@ -65,8 +69,8 @@ TEST_F(IndexedDBTest, ClearSessionOnlyDatabases) {
webkit_database::GetIdentifierFromOrigin(kNormalOrigin));
session_only_path = idb_context->GetFilePathForTesting(
webkit_database::GetIdentifierFromOrigin(kSessionOnlyOrigin));
- ASSERT_TRUE(file_util::CreateDirectory(normal_path));
- ASSERT_TRUE(file_util::CreateDirectory(session_only_path));
+ ASSERT_TRUE(base::CreateDirectory(normal_path));
+ ASSERT_TRUE(base::CreateDirectory(session_only_path));
FlushIndexedDBTaskRunner();
message_loop_.RunUntilIdle();
}
@@ -99,8 +103,8 @@ TEST_F(IndexedDBTest, SetForceKeepSessionState) {
webkit_database::GetIdentifierFromOrigin(kNormalOrigin));
session_only_path = idb_context->GetFilePathForTesting(
webkit_database::GetIdentifierFromOrigin(kSessionOnlyOrigin));
- ASSERT_TRUE(file_util::CreateDirectory(normal_path));
- ASSERT_TRUE(file_util::CreateDirectory(session_only_path));
+ ASSERT_TRUE(base::CreateDirectory(normal_path));
+ ASSERT_TRUE(base::CreateDirectory(session_only_path));
message_loop_.RunUntilIdle();
}
@@ -128,6 +132,10 @@ class MockConnection : public IndexedDBConnection {
force_close_called_ = true;
}
+ virtual bool IsConnected() OVERRIDE {
+ return !force_close_called_;
+ }
+
private:
bool expect_force_close_;
bool force_close_called_;
@@ -150,7 +158,7 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) {
test_path = idb_context->GetFilePathForTesting(
webkit_database::GetIdentifierFromOrigin(kTestOrigin));
- ASSERT_TRUE(file_util::CreateDirectory(test_path));
+ ASSERT_TRUE(base::CreateDirectory(test_path));
const bool kExpectForceClose = true;
@@ -190,4 +198,66 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) {
EXPECT_FALSE(base::DirectoryExists(test_path));
}
+TEST_F(IndexedDBTest, DeleteFailsIfDirectoryLocked) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ const GURL kTestOrigin("http://test/");
+
+ scoped_refptr<IndexedDBContextImpl> idb_context = new IndexedDBContextImpl(
+ temp_dir.path(), special_storage_policy_, NULL, task_runner_);
+
+ base::FilePath test_path = idb_context->GetFilePathForTesting(
+ webkit_database::GetIdentifierFromOrigin(kTestOrigin));
+ ASSERT_TRUE(base::CreateDirectory(test_path));
+
+ scoped_ptr<LevelDBLock> lock =
+ LevelDBDatabase::LockForTesting(test_path);
+ ASSERT_TRUE(lock);
+
+ idb_context->TaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &IndexedDBContextImpl::DeleteForOrigin, idb_context, kTestOrigin));
+ FlushIndexedDBTaskRunner();
+
+ EXPECT_TRUE(base::DirectoryExists(test_path));
+}
+
+TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnCommitFailure) {
+ const GURL kTestOrigin("http://test/");
+
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+ scoped_refptr<IndexedDBContextImpl> context = new IndexedDBContextImpl(
+ temp_dir.path(), special_storage_policy_, NULL, task_runner_);
+
+ scoped_refptr<IndexedDBFactory> factory = context->GetIDBFactory();
+
+ scoped_refptr<MockIndexedDBCallbacks> callbacks(new MockIndexedDBCallbacks());
+ scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
+ new MockIndexedDBDatabaseCallbacks());
+ const int64 transaction_id = 1;
+ factory->Open(ASCIIToUTF16("db"),
+ IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION,
+ transaction_id,
+ callbacks,
+ db_callbacks,
+ kTestOrigin,
+ temp_dir.path());
+
+ EXPECT_TRUE(callbacks->connection());
+
+ // ConnectionOpened() is usually called by the dispatcher.
+ context->ConnectionOpened(kTestOrigin, callbacks->connection());
+
+ EXPECT_TRUE(factory->IsBackingStoreOpen(kTestOrigin));
+
+ // Simulate the write failure.
+ callbacks->connection()->database()->TransactionCommitFailed();
+
+ EXPECT_TRUE(db_callbacks->forced_close_called());
+ EXPECT_FALSE(factory->IsBackingStoreOpen(kTestOrigin));
+}
+
} // namespace content
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
index cab8473a7a3..fd4d30cae66 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -30,6 +30,22 @@ using base::StringPiece;
namespace content {
+// Forcing flushes to disk at the end of a transaction guarantees that the
+// data hit disk, but drastically impacts throughput when the filesystem is
+// busy with background compactions. Not syncing trades off reliability for
+// performance. Note that background compactions which move data from the
+// log to SSTs are always done with reliable writes.
+//
+// Sync writes are necessary on Windows for quota calculations; POSIX
+// calculates file sizes correctly even when not synced to disk.
+#if defined(OS_WIN)
+static const bool kSyncWrites = true;
+#else
+// TODO(dgrogan): Either remove the #if block or change this back to false.
+// See http://crbug.com/338385.
+static const bool kSyncWrites = true;
+#endif
+
static leveldb::Slice MakeSlice(const StringPiece& s) {
return leveldb::Slice(s.begin(), s.size());
}
@@ -82,11 +98,7 @@ static leveldb::Status OpenDB(leveldb::Comparator* comparator,
options.comparator = comparator;
options.create_if_missing = true;
options.paranoid_checks = true;
-
- // Marking compression as explicitly off so snappy support can be
- // compiled in for other leveldb clients without implicitly enabling
- // it for IndexedDB. http://crbug.com/81384
- options.compression = leveldb::kNoCompression;
+ options.compression = leveldb::kSnappyCompression;
// For info about the troubles we've run into with this parameter, see:
// https://code.google.com/p/chromium/issues/detail?id=227313#c11
@@ -106,6 +118,30 @@ bool LevelDBDatabase::Destroy(const base::FilePath& file_name) {
return s.ok();
}
+namespace {
+class LockImpl : public LevelDBLock {
+ public:
+ explicit LockImpl(leveldb::Env* env, leveldb::FileLock* lock)
+ : env_(env), lock_(lock) {}
+ virtual ~LockImpl() { env_->UnlockFile(lock_); }
+ private:
+ leveldb::Env* env_;
+ leveldb::FileLock* lock_;
+};
+}
+
+scoped_ptr<LevelDBLock> LevelDBDatabase::LockForTesting(
+ const base::FilePath& file_name) {
+ leveldb::Env* env = leveldb::IDBEnv();
+ base::FilePath lock_path = file_name.AppendASCII("LOCK");
+ leveldb::FileLock* lock = NULL;
+ leveldb::Status status = env->LockFile(lock_path.AsUTF8Unsafe(), &lock);
+ if (!status.ok())
+ return scoped_ptr<LevelDBLock>();
+ DCHECK(lock);
+ return scoped_ptr<LevelDBLock>(new LockImpl(env, lock));
+}
+
static int CheckFreeSpace(const char* const type,
const base::FilePath& file_name) {
std::string name =
@@ -179,60 +215,16 @@ static void ParseAndHistogramIOErrorDetails(const std::string& histogram_name,
static void ParseAndHistogramCorruptionDetails(
const std::string& histogram_name,
const leveldb::Status& status) {
- DCHECK(!status.IsIOError());
- DCHECK(!status.ok());
- const int kOtherError = 0;
- int error = kOtherError;
- const std::string& str_error = status.ToString();
- // Keep in sync with LevelDBCorruptionTypes in histograms.xml.
- const char* patterns[] = {
- "missing files",
- "log record too small",
- "corrupted internal key",
- "partial record",
- "missing start of fragmented record",
- "error in middle of record",
- "unknown record type",
- "truncated record at end",
- "bad record length",
- "VersionEdit",
- "FileReader invoked with unexpected value",
- "corrupted key",
- "CURRENT file does not end with newline",
- "no meta-nextfile entry",
- "no meta-lognumber entry",
- "no last-sequence-number entry",
- "malformed WriteBatch",
- "bad WriteBatch Put",
- "bad WriteBatch Delete",
- "unknown WriteBatch tag",
- "WriteBatch has wrong count",
- "bad entry in block",
- "bad block contents",
- "bad block handle",
- "truncated block read",
- "block checksum mismatch",
- "checksum mismatch",
- "corrupted compressed block contents",
- "bad block type",
- "bad magic number",
- "file is too short",
- };
- const size_t kNumPatterns = arraysize(patterns);
- for (size_t i = 0; i < kNumPatterns; ++i) {
- if (str_error.find(patterns[i]) != std::string::npos) {
- error = i + 1;
- break;
- }
- }
+ int error = leveldb_env::GetCorruptionCode(status);
DCHECK(error >= 0);
std::string corruption_histogram_name(histogram_name);
corruption_histogram_name.append(".Corruption");
+ const int kNumPatterns = leveldb_env::GetNumCorruptionCodes();
base::LinearHistogram::FactoryGet(
corruption_histogram_name,
1,
+ kNumPatterns,
kNumPatterns + 1,
- kNumPatterns + 2,
base::HistogramBase::kUmaTargetedHistogramFlag)->Add(error);
}
@@ -328,7 +320,7 @@ scoped_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory(
bool LevelDBDatabase::Put(const StringPiece& key, std::string* value) {
leveldb::WriteOptions write_options;
- write_options.sync = true;
+ write_options.sync = kSyncWrites;
const leveldb::Status s =
db_->Put(write_options, MakeSlice(key), MakeSlice(*value));
@@ -340,7 +332,7 @@ bool LevelDBDatabase::Put(const StringPiece& key, std::string* value) {
bool LevelDBDatabase::Remove(const StringPiece& key) {
leveldb::WriteOptions write_options;
- write_options.sync = true;
+ write_options.sync = kSyncWrites;
const leveldb::Status s = db_->Delete(write_options, MakeSlice(key));
if (s.ok())
@@ -375,7 +367,7 @@ bool LevelDBDatabase::Get(const StringPiece& key,
bool LevelDBDatabase::Write(const LevelDBWriteBatch& write_batch) {
leveldb::WriteOptions write_options;
- write_options.sync = true;
+ write_options.sync = kSyncWrites;
const leveldb::Status s =
db_->Write(write_options, write_batch.write_batch_.get());
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
index 5732ac4e3d6..6f9c919014a 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
@@ -40,6 +40,11 @@ class LevelDBSnapshot {
const leveldb::Snapshot* snapshot_;
};
+class CONTENT_EXPORT LevelDBLock {
+public:
+ virtual ~LevelDBLock() {}
+};
+
class CONTENT_EXPORT LevelDBDatabase {
public:
static leveldb::Status Open(const base::FilePath& file_name,
@@ -49,6 +54,8 @@ class CONTENT_EXPORT LevelDBDatabase {
static scoped_ptr<LevelDBDatabase> OpenInMemory(
const LevelDBComparator* comparator);
static bool Destroy(const base::FilePath& file_name);
+ static scoped_ptr<LevelDBLock> LockForTesting(
+ const base::FilePath& file_name);
virtual ~LevelDBDatabase();
bool Put(const base::StringPiece& key, std::string* value);
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
index de506c57597..3edcae7fad6 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
@@ -16,6 +16,8 @@
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/leveldatabase/env_chromium.h"
+#include "third_party/leveldatabase/env_idb.h"
namespace content {
@@ -243,6 +245,30 @@ TEST(LevelDBDatabaseTest, TransactionCommitTest) {
EXPECT_EQ(value3, got_value);
}
+TEST(LevelDB, Locking) {
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+
+ leveldb::Env* env = leveldb::IDBEnv();
+ base::FilePath file = temp_directory.path().AppendASCII("LOCK");
+ leveldb::FileLock* lock;
+ leveldb::Status status = env->LockFile(file.AsUTF8Unsafe(), &lock);
+ EXPECT_TRUE(status.ok());
+
+ status = env->UnlockFile(lock);
+ EXPECT_TRUE(status.ok());
+
+ status = env->LockFile(file.AsUTF8Unsafe(), &lock);
+ EXPECT_TRUE(status.ok());
+
+ leveldb::FileLock* lock2;
+ status = env->LockFile(file.AsUTF8Unsafe(), &lock2);
+ EXPECT_FALSE(status.ok());
+
+ status = env->UnlockFile(lock);
+ EXPECT_TRUE(status.ok());
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/indexed_db/list_set.h b/chromium/content/browser/indexed_db/list_set.h
index e7945cae939..98f3b88c24c 100644
--- a/chromium/content/browser/indexed_db/list_set.h
+++ b/chromium/content/browser/indexed_db/list_set.h
@@ -47,7 +47,9 @@ class list_set {
list_.erase(it);
}
- bool has(const T& elem) const { return set_.find(elem) != set_.end(); }
+ size_t count(const T& elem) const {
+ return set_.find(elem) == set_.end() ? 0 : 1;
+ }
size_t size() const {
DCHECK_EQ(list_.size(), set_.size());
diff --git a/chromium/content/browser/indexed_db/list_set_unittest.cc b/chromium/content/browser/indexed_db/list_set_unittest.cc
index 1bfafa290bd..405fb49a7d0 100644
--- a/chromium/content/browser/indexed_db/list_set_unittest.cc
+++ b/chromium/content/browser/indexed_db/list_set_unittest.cc
@@ -64,9 +64,9 @@ TEST(ListSetTest, ListSetPrimitive) {
set.erase(3);
EXPECT_EQ(static_cast<size_t>(4), set.size());
- EXPECT_TRUE(set.has(2));
+ EXPECT_EQ(static_cast<size_t>(1), set.count(2));
set.erase(2);
- EXPECT_FALSE(set.has(2));
+ EXPECT_EQ(static_cast<size_t>(0), set.count(2));
EXPECT_EQ(static_cast<size_t>(3), set.size());
{
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc
new file mode 100644
index 00000000000..a585246ab34
--- /dev/null
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.cc
@@ -0,0 +1,30 @@
+// 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/indexed_db/mock_indexed_db_callbacks.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+MockIndexedDBCallbacks::MockIndexedDBCallbacks()
+ : IndexedDBCallbacks(NULL, 0, 0), expect_connection_(true) {}
+MockIndexedDBCallbacks::MockIndexedDBCallbacks(bool expect_connection)
+ : IndexedDBCallbacks(NULL, 0, 0), expect_connection_(expect_connection) {}
+
+MockIndexedDBCallbacks::~MockIndexedDBCallbacks() {
+ EXPECT_EQ(expect_connection_, !!connection_);
+}
+
+void MockIndexedDBCallbacks::OnSuccess() {}
+
+void MockIndexedDBCallbacks::OnSuccess(const std::vector<base::string16>&) {}
+
+void MockIndexedDBCallbacks::OnSuccess(
+ scoped_ptr<IndexedDBConnection> connection,
+ const IndexedDBDatabaseMetadata& metadata) {
+ connection_ = connection.Pass();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h
new file mode 100644
index 00000000000..1af3ca1781e
--- /dev/null
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h
@@ -0,0 +1,37 @@
+// 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_INDEXED_DB_MOCK_INDEXED_DB_CALLBACKS_H_
+#define CONTENT_BROWSER_INDEXED_DB_MOCK_INDEXED_DB_CALLBACKS_H_
+
+#include "content/browser/indexed_db/indexed_db_callbacks.h"
+#include "content/browser/indexed_db/indexed_db_connection.h"
+
+namespace content {
+
+class MockIndexedDBCallbacks : public IndexedDBCallbacks {
+ public:
+ MockIndexedDBCallbacks();
+ MockIndexedDBCallbacks(bool expect_connection);
+
+ virtual void OnSuccess() OVERRIDE;
+ virtual void OnSuccess(const std::vector<base::string16>&) OVERRIDE;
+ virtual void OnSuccess(scoped_ptr<IndexedDBConnection> connection,
+ const IndexedDBDatabaseMetadata& metadata) OVERRIDE;
+ IndexedDBConnection* connection() { return connection_.get(); }
+
+ protected:
+ virtual ~MockIndexedDBCallbacks();
+
+ scoped_ptr<IndexedDBConnection> connection_;
+
+ private:
+ bool expect_connection_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockIndexedDBCallbacks);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_MOCK_INDEXED_DB_CALLBACKS_H_
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc
new file mode 100644
index 00000000000..479bb3af60f
--- /dev/null
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.cc
@@ -0,0 +1,26 @@
+// 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/indexed_db/mock_indexed_db_database_callbacks.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+MockIndexedDBDatabaseCallbacks::MockIndexedDBDatabaseCallbacks()
+ : IndexedDBDatabaseCallbacks(NULL, 0, 0),
+ abort_called_(false),
+ forced_close_called_(false) {}
+
+void MockIndexedDBDatabaseCallbacks::OnForcedClose() {
+ forced_close_called_ = true;
+}
+
+void MockIndexedDBDatabaseCallbacks::OnAbort(
+ int64 transaction_id,
+ const IndexedDBDatabaseError& error) {
+ abort_called_ = true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h
new file mode 100644
index 00000000000..7252a9fde0a
--- /dev/null
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h
@@ -0,0 +1,37 @@
+// 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_INDEXED_DB_MOCK_INDEXED_DB_DATABASE_CALLBACKS_H_
+#define CONTENT_BROWSER_INDEXED_DB_MOCK_INDEXED_DB_DATABASE_CALLBACKS_H_
+
+#include "content/browser/indexed_db/indexed_db_callbacks.h"
+#include "content/browser/indexed_db/indexed_db_connection.h"
+
+namespace content {
+
+class MockIndexedDBDatabaseCallbacks : public IndexedDBDatabaseCallbacks {
+ public:
+ MockIndexedDBDatabaseCallbacks();
+
+ virtual void OnVersionChange(int64 old_version, int64 new_version) OVERRIDE {}
+ virtual void OnForcedClose() OVERRIDE;
+ virtual void OnAbort(int64 transaction_id,
+ const IndexedDBDatabaseError& error) OVERRIDE;
+ virtual void OnComplete(int64 transaction_id) OVERRIDE {}
+
+ bool abort_called() const { return abort_called_; }
+ bool forced_close_called() const { return forced_close_called_; }
+
+ private:
+ virtual ~MockIndexedDBDatabaseCallbacks() {}
+
+ bool abort_called_;
+ bool forced_close_called_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockIndexedDBDatabaseCallbacks);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_MOCK_INDEXED_DB_DATABASE_CALLBACKS_H_
diff --git a/chromium/content/browser/loader/async_resource_handler.cc b/chromium/content/browser/loader/async_resource_handler.cc
index c7d7f49db93..93d7e839aa2 100644
--- a/chromium/content/browser/loader/async_resource_handler.cc
+++ b/chromium/content/browser/loader/async_resource_handler.cc
@@ -77,14 +77,10 @@ class DependentIOBuffer : public net::WrappedIOBuffer {
};
AsyncResourceHandler::AsyncResourceHandler(
- ResourceMessageFilter* filter,
- ResourceContext* resource_context,
net::URLRequest* request,
ResourceDispatcherHostImpl* rdh)
- : ResourceMessageDelegate(request),
- filter_(filter),
- resource_context_(resource_context),
- request_(request),
+ : ResourceHandler(request),
+ ResourceMessageDelegate(request),
rdh_(rdh),
pending_data_count_(0),
allocation_size_(0),
@@ -97,7 +93,7 @@ AsyncResourceHandler::AsyncResourceHandler(
AsyncResourceHandler::~AsyncResourceHandler() {
if (has_checked_for_sufficient_resources_)
- rdh_->FinishedWithResourcesForRequest(request_);
+ rdh_->FinishedWithResourcesForRequest(request());
}
bool AsyncResourceHandler::OnMessageReceived(const IPC::Message& message,
@@ -115,13 +111,13 @@ void AsyncResourceHandler::OnFollowRedirect(
int request_id,
bool has_new_first_party_for_cookies,
const GURL& new_first_party_for_cookies) {
- if (!request_->status().is_success()) {
+ if (!request()->status().is_success()) {
DVLOG(1) << "OnFollowRedirect for invalid request";
return;
}
if (has_new_first_party_for_cookies)
- request_->set_first_party_for_cookies(new_first_party_for_cookies);
+ request()->set_first_party_for_cookies(new_first_party_for_cookies);
ResumeIfDeferred();
}
@@ -139,25 +135,33 @@ void AsyncResourceHandler::OnDataReceivedACK(int request_id) {
bool AsyncResourceHandler::OnUploadProgress(int request_id,
uint64 position,
uint64 size) {
- return filter_->Send(new ResourceMsg_UploadProgress(request_id, position,
- size));
+ ResourceMessageFilter* filter = GetFilter();
+ if (!filter)
+ return false;
+ return filter->Send(
+ new ResourceMsg_UploadProgress(request_id, position, size));
}
bool AsyncResourceHandler::OnRequestRedirected(int request_id,
const GURL& new_url,
ResourceResponse* response,
bool* defer) {
+ const ResourceRequestInfoImpl* info = GetRequestInfo();
+ if (!info->filter())
+ return false;
+
*defer = did_defer_ = true;
+ OnDefer();
if (rdh_->delegate()) {
rdh_->delegate()->OnRequestRedirected(
- new_url, request_, resource_context_, response);
+ new_url, request(), info->GetContext(), response);
}
- DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
- response->head.request_start = request_->creation_time();
+ DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
+ response->head.request_start = request()->creation_time();
response->head.response_start = TimeTicks::Now();
- return filter_->Send(new ResourceMsg_ReceivedRedirect(
+ return info->filter()->Send(new ResourceMsg_ReceivedRedirect(
request_id, new_url, response->head));
}
@@ -170,36 +174,41 @@ bool AsyncResourceHandler::OnResponseStarted(int request_id,
// request commits, avoiding the possibility of e.g. zooming the old content
// or of having to layout the new content twice.
+ const ResourceRequestInfoImpl* info = GetRequestInfo();
+ if (!info->filter())
+ return false;
+
if (rdh_->delegate()) {
rdh_->delegate()->OnResponseStarted(
- request_, resource_context_, response, filter_.get());
+ request(), info->GetContext(), response, info->filter());
}
- DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
+ DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
HostZoomMap* host_zoom_map =
- GetHostZoomMapForResourceContext(resource_context_);
+ GetHostZoomMapForResourceContext(info->GetContext());
- const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
if (info->GetResourceType() == ResourceType::MAIN_FRAME && host_zoom_map) {
- const GURL& request_url = request_->url();
- filter_->Send(new ViewMsg_SetZoomLevelForLoadingURL(
+ const GURL& request_url = request()->url();
+ info->filter()->Send(new ViewMsg_SetZoomLevelForLoadingURL(
info->GetRouteID(),
request_url, host_zoom_map->GetZoomLevelForHostAndScheme(
request_url.scheme(),
net::GetHostOrSpecFromURL(request_url))));
}
- response->head.request_start = request_->creation_time();
+ response->head.request_start = request()->creation_time();
response->head.response_start = TimeTicks::Now();
- filter_->Send(new ResourceMsg_ReceivedResponse(request_id, response->head));
+ info->filter()->Send(new ResourceMsg_ReceivedResponse(request_id,
+ response->head));
sent_received_response_msg_ = true;
- if (request_->response_info().metadata.get()) {
- std::vector<char> copy(request_->response_info().metadata->data(),
- request_->response_info().metadata->data() +
- request_->response_info().metadata->size());
- filter_->Send(new ResourceMsg_ReceivedCachedMetadata(request_id, copy));
+ if (request()->response_info().metadata.get()) {
+ std::vector<char> copy(request()->response_info().metadata->data(),
+ request()->response_info().metadata->data() +
+ request()->response_info().metadata->size());
+ info->filter()->Send(new ResourceMsg_ReceivedCachedMetadata(request_id,
+ copy));
}
return true;
@@ -211,8 +220,10 @@ bool AsyncResourceHandler::OnWillStart(int request_id,
return true;
}
-bool AsyncResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
- int* buf_size, int min_size) {
+bool AsyncResourceHandler::OnWillRead(int request_id,
+ scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) {
DCHECK_EQ(-1, min_size);
if (!EnsureResourceBufferIsInitialized())
@@ -233,9 +244,15 @@ bool AsyncResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read,
bool* defer) {
+ DCHECK_GE(bytes_read, 0);
+
if (!bytes_read)
return true;
+ ResourceMessageFilter* filter = GetFilter();
+ if (!filter)
+ return false;
+
buffer_->ShrinkLastAllocation(bytes_read);
UMA_HISTOGRAM_CUSTOM_COUNTS(
@@ -248,18 +265,18 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read,
if (!sent_first_data_msg_) {
base::SharedMemoryHandle handle;
int size;
- if (!buffer_->ShareToProcess(filter_->PeerHandle(), &handle, &size))
+ if (!buffer_->ShareToProcess(filter->PeerHandle(), &handle, &size))
return false;
- filter_->Send(new ResourceMsg_SetDataBuffer(
- request_id, handle, size, filter_->peer_pid()));
+ filter->Send(new ResourceMsg_SetDataBuffer(
+ request_id, handle, size, filter->peer_pid()));
sent_first_data_msg_ = true;
}
int data_offset = buffer_->GetLastAllocationOffset();
int encoded_data_length =
- DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_);
+ DevToolsNetLogObserver::GetAndResetEncodedDataLength(request());
- filter_->Send(new ResourceMsg_DataReceived(
+ filter->Send(new ResourceMsg_DataReceived(
request_id, data_offset, bytes_read, encoded_data_length));
++pending_data_count_;
UMA_HISTOGRAM_CUSTOM_COUNTS(
@@ -271,6 +288,7 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read,
"Net.AsyncResourceHandler_PendingDataCount_WhenFull",
pending_data_count_, 0, 100, 100);
*defer = did_defer_ = true;
+ OnDefer();
}
return true;
@@ -279,20 +297,28 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read,
void AsyncResourceHandler::OnDataDownloaded(
int request_id, int bytes_downloaded) {
int encoded_data_length =
- DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_);
+ DevToolsNetLogObserver::GetAndResetEncodedDataLength(request());
- filter_->Send(new ResourceMsg_DataDownloaded(
- request_id, bytes_downloaded, encoded_data_length));
+ ResourceMessageFilter* filter = GetFilter();
+ if (filter) {
+ filter->Send(new ResourceMsg_DataDownloaded(
+ request_id, bytes_downloaded, encoded_data_length));
+ }
}
-bool AsyncResourceHandler::OnResponseCompleted(
+void AsyncResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) {
+ const std::string& security_info,
+ bool* defer) {
+ const ResourceRequestInfoImpl* info = GetRequestInfo();
+ if (!info->filter())
+ return;
+
// If we crash here, figure out what URL the renderer was requesting.
// http://crbug.com/107692
char url_buf[128];
- base::strlcpy(url_buf, request_->url().spec().c_str(), arraysize(url_buf));
+ base::strlcpy(url_buf, request()->url().spec().c_str(), arraysize(url_buf));
base::debug::Alias(url_buf);
// TODO(gavinp): Remove this CHECK when we figure out the cause of
@@ -306,8 +332,7 @@ bool AsyncResourceHandler::OnResponseCompleted(
TimeTicks completion_time = TimeTicks::Now();
int error_code = status.error();
- bool was_ignored_by_handler =
- ResourceRequestInfoImpl::ForRequest(request_)->WasIgnoredByHandler();
+ bool was_ignored_by_handler = info->WasIgnoredByHandler();
DCHECK(status.status() != net::URLRequestStatus::IO_PENDING);
// If this check fails, then we're in an inconsistent state because all
@@ -325,12 +350,12 @@ bool AsyncResourceHandler::OnResponseCompleted(
error_code = net::ERR_FAILED;
}
- filter_->Send(new ResourceMsg_RequestComplete(request_id,
- error_code,
- was_ignored_by_handler,
- security_info,
- completion_time));
- return true;
+ info->filter()->Send(
+ new ResourceMsg_RequestComplete(request_id,
+ error_code,
+ was_ignored_by_handler,
+ security_info,
+ completion_time));
}
bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() {
@@ -339,7 +364,7 @@ bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() {
if (!has_checked_for_sufficient_resources_) {
has_checked_for_sufficient_resources_ = true;
- if (!rdh_->HasSufficientResourcesForRequest(request_)) {
+ if (!rdh_->HasSufficientResourcesForRequest(request())) {
controller()->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
return false;
}
@@ -354,8 +379,13 @@ bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() {
void AsyncResourceHandler::ResumeIfDeferred() {
if (did_defer_) {
did_defer_ = false;
+ request()->LogUnblocked();
controller()->Resume();
}
}
+void AsyncResourceHandler::OnDefer() {
+ request()->LogBlockedBy("AsyncResourceHandler");
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/async_resource_handler.h b/chromium/content/browser/loader/async_resource_handler.h
index b43e0ef3745..f603f4f858f 100644
--- a/chromium/content/browser/loader/async_resource_handler.h
+++ b/chromium/content/browser/loader/async_resource_handler.h
@@ -28,9 +28,7 @@ class SharedIOBuffer;
class AsyncResourceHandler : public ResourceHandler,
public ResourceMessageDelegate {
public:
- AsyncResourceHandler(ResourceMessageFilter* filter,
- ResourceContext* resource_context,
- net::URLRequest* request,
+ AsyncResourceHandler(net::URLRequest* request,
ResourceDispatcherHostImpl* rdh);
virtual ~AsyncResourceHandler();
@@ -52,15 +50,16 @@ class AsyncResourceHandler : public ResourceHandler,
const GURL& url,
bool* defer) OVERRIDE;
virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) OVERRIDE;
virtual bool OnReadCompleted(int request_id,
int bytes_read,
bool* defer) OVERRIDE;
- virtual bool OnResponseCompleted(int request_id,
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) OVERRIDE;
+ const std::string& security_info,
+ bool* defer) OVERRIDE;
virtual void OnDataDownloaded(int request_id,
int bytes_downloaded) OVERRIDE;
@@ -73,11 +72,9 @@ class AsyncResourceHandler : public ResourceHandler,
bool EnsureResourceBufferIsInitialized();
void ResumeIfDeferred();
+ void OnDefer();
scoped_refptr<ResourceBuffer> buffer_;
- scoped_refptr<ResourceMessageFilter> filter_;
- ResourceContext* resource_context_;
- net::URLRequest* request_;
ResourceDispatcherHostImpl* rdh_;
// Number of messages we've sent to the renderer that we haven't gotten an
diff --git a/chromium/content/browser/loader/buffered_resource_handler.cc b/chromium/content/browser/loader/buffered_resource_handler.cc
index a3afb3fa7b6..2a5ef9cd120 100644
--- a/chromium/content/browser/loader/buffered_resource_handler.cc
+++ b/chromium/content/browser/loader/buffered_resource_handler.cc
@@ -80,10 +80,9 @@ BufferedResourceHandler::BufferedResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
ResourceDispatcherHostImpl* host,
net::URLRequest* request)
- : LayeredResourceHandler(next_handler.Pass()),
+ : LayeredResourceHandler(request, next_handler.Pass()),
state_(STATE_STARTING),
host_(host),
- request_(request),
read_buffer_size_(0),
bytes_read_(0),
must_download_(false),
@@ -147,8 +146,10 @@ bool BufferedResourceHandler::OnResponseStarted(
// We'll let the original event handler provide a buffer, and reuse it for
// subsequent reads until we're done buffering.
-bool BufferedResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
- int* buf_size, int min_size) {
+bool BufferedResourceHandler::OnWillRead(int request_id,
+ scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) {
if (state_ == STATE_STREAMING)
return next_handler_->OnWillRead(request_id, buf, buf_size, min_size);
@@ -184,15 +185,16 @@ bool BufferedResourceHandler::OnReadCompleted(int request_id, int bytes_read,
return ProcessResponse(defer);
}
-bool BufferedResourceHandler::OnResponseCompleted(
+void BufferedResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) {
+ const std::string& security_info,
+ bool* defer) {
// Upon completion, act like a pass-through handler in case the downstream
// handler defers OnResponseCompleted.
state_ = STATE_STREAMING;
- return next_handler_->OnResponseCompleted(request_id, status, security_info);
+ next_handler_->OnResponseCompleted(request_id, status, security_info, defer);
}
void BufferedResourceHandler::Resume() {
@@ -240,8 +242,7 @@ bool BufferedResourceHandler::ProcessResponse(bool* defer) {
state_ = STATE_REPLAYING;
- int request_id = ResourceRequestInfo::ForRequest(request_)->GetRequestID();
- if (!next_handler_->OnResponseStarted(request_id, response_.get(), defer))
+ if (!next_handler_->OnResponseStarted(GetRequestID(), response_.get(), defer))
return false;
if (!read_buffer_.get()) {
@@ -259,13 +260,13 @@ bool BufferedResourceHandler::ShouldSniffContent() {
const std::string& mime_type = response_->head.mime_type;
std::string content_type_options;
- request_->GetResponseHeaderByName("x-content-type-options",
- &content_type_options);
+ request()->GetResponseHeaderByName("x-content-type-options",
+ &content_type_options);
bool sniffing_blocked =
LowerCaseEqualsASCII(content_type_options, "nosniff");
bool we_would_like_to_sniff =
- net::ShouldSniffMimeType(request_->url(), mime_type);
+ net::ShouldSniffMimeType(request()->url(), mime_type);
RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type);
@@ -273,7 +274,7 @@ bool BufferedResourceHandler::ShouldSniffContent() {
// We're going to look at the data before deciding what the content type
// is. That means we need to delay sending the ResponseStarted message
// over the IPC channel.
- VLOG(1) << "To buffer: " << request_->url().spec();
+ VLOG(1) << "To buffer: " << request()->url().spec();
return true;
}
@@ -287,7 +288,7 @@ bool BufferedResourceHandler::DetermineMimeType() {
std::string new_type;
bool made_final_decision =
- net::SniffMimeType(read_buffer_->data(), bytes_read_, request_->url(),
+ net::SniffMimeType(read_buffer_->data(), bytes_read_, request()->url(),
type_hint, &new_type);
// SniffMimeType() returns false if there is not enough data to determine
@@ -301,15 +302,13 @@ bool BufferedResourceHandler::DetermineMimeType() {
bool BufferedResourceHandler::SelectNextHandler(bool* defer) {
DCHECK(!response_->head.mime_type.empty());
- ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_);
+ ResourceRequestInfoImpl* info = GetRequestInfo();
const std::string& mime_type = response_->head.mime_type;
if (net::IsSupportedCertificateMimeType(mime_type)) {
// Install certificate file.
scoped_ptr<ResourceHandler> handler(
- new CertificateResourceHandler(request_,
- info->GetChildID(),
- info->GetRouteID()));
+ new CertificateResourceHandler(request()));
return UseAlternateNextHandler(handler.Pass());
}
@@ -322,7 +321,7 @@ bool BufferedResourceHandler::SelectNextHandler(bool* defer) {
return true;
scoped_ptr<ResourceHandler> handler(
- host_->MaybeInterceptAsStream(request_, response_.get()));
+ host_->MaybeInterceptAsStream(request(), response_.get()));
if (handler)
return UseAlternateNextHandler(handler.Pass());
@@ -346,7 +345,7 @@ bool BufferedResourceHandler::SelectNextHandler(bool* defer) {
info->set_is_download(true);
scoped_ptr<ResourceHandler> handler(
host_->CreateResourceHandlerForDownload(
- request_,
+ request(),
true, // is_content_initiated
must_download,
content::DownloadItem::kInvalidId,
@@ -364,21 +363,24 @@ bool BufferedResourceHandler::UseAlternateNextHandler(
// own error page instead of triggering a download.
// TODO(abarth): We should abstract the response_code test, but this kind
// of check is scattered throughout our codebase.
- request_->CancelWithError(net::ERR_FILE_NOT_FOUND);
+ request()->CancelWithError(net::ERR_FILE_NOT_FOUND);
return false;
}
- int request_id = ResourceRequestInfo::ForRequest(request_)->GetRequestID();
+ int request_id = GetRequestID();
// Inform the original ResourceHandler that this will be handled entirely by
// the new ResourceHandler.
// TODO(darin): We should probably check the return values of these.
+ // TODO(davidben): These DCHECKs do actually trigger.
bool defer_ignored = false;
next_handler_->OnResponseStarted(request_id, response_.get(), &defer_ignored);
DCHECK(!defer_ignored);
net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
net::ERR_ABORTED);
- next_handler_->OnResponseCompleted(request_id, status, std::string());
+ next_handler_->OnResponseCompleted(request_id, status, std::string(),
+ &defer_ignored);
+ DCHECK(!defer_ignored);
// This is handled entirely within the new ResourceHandler, so just reset the
// original ResourceHandler.
@@ -391,8 +393,8 @@ bool BufferedResourceHandler::UseAlternateNextHandler(
bool BufferedResourceHandler::ReplayReadCompleted(bool* defer) {
DCHECK(read_buffer_.get());
- int request_id = ResourceRequestInfo::ForRequest(request_)->GetRequestID();
- bool result = next_handler_->OnReadCompleted(request_id, bytes_read_, defer);
+ bool result = next_handler_->OnReadCompleted(GetRequestID(), bytes_read_,
+ defer);
read_buffer_ = NULL;
read_buffer_size_ = 0;
@@ -420,13 +422,13 @@ bool BufferedResourceHandler::MustDownload() {
must_download_is_set_ = true;
std::string disposition;
- request_->GetResponseHeaderByName("content-disposition", &disposition);
+ request()->GetResponseHeaderByName("content-disposition", &disposition);
if (!disposition.empty() &&
net::HttpContentDisposition(disposition, std::string()).is_attachment()) {
must_download_ = true;
} else if (host_->delegate() &&
host_->delegate()->ShouldForceDownloadResource(
- request_->url(), response_->head.mime_type)) {
+ request()->url(), response_->head.mime_type)) {
must_download_ = true;
} else {
must_download_ = false;
@@ -436,21 +438,27 @@ bool BufferedResourceHandler::MustDownload() {
}
bool BufferedResourceHandler::HasSupportingPlugin(bool* stale) {
- ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_);
+#if defined(ENABLE_PLUGINS)
+ ResourceRequestInfoImpl* info = GetRequestInfo();
bool allow_wildcard = false;
WebPluginInfo plugin;
return PluginServiceImpl::GetInstance()->GetPluginInfo(
- info->GetChildID(), info->GetRouteID(), info->GetContext(),
- request_->url(), GURL(), response_->head.mime_type, allow_wildcard,
+ info->GetChildID(), info->GetRenderFrameID(), info->GetContext(),
+ request()->url(), GURL(), response_->head.mime_type, allow_wildcard,
stale, &plugin, NULL);
+#else
+ if (stale)
+ *stale = false;
+ return false;
+#endif
}
bool BufferedResourceHandler::CopyReadBufferToNextHandler(int request_id) {
if (!bytes_read_)
return true;
- net::IOBuffer* buf = NULL;
+ scoped_refptr<net::IOBuffer> buf;
int buf_len = 0;
if (!next_handler_->OnWillRead(request_id, &buf, &buf_len, bytes_read_))
return false;
diff --git a/chromium/content/browser/loader/buffered_resource_handler.h b/chromium/content/browser/loader/buffered_resource_handler.h
index c1a7a6e8120..23d15cccf6f 100644
--- a/chromium/content/browser/loader/buffered_resource_handler.h
+++ b/chromium/content/browser/loader/buffered_resource_handler.h
@@ -37,14 +37,15 @@ class BufferedResourceHandler
ResourceResponse* response,
bool* defer) OVERRIDE;
virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) OVERRIDE;
virtual bool OnReadCompleted(int request_id, int bytes_read,
bool* defer) OVERRIDE;
- virtual bool OnResponseCompleted(int request_id,
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) OVERRIDE;
+ const std::string& security_info,
+ bool* defer) OVERRIDE;
// ResourceController implementation:
virtual void Resume() OVERRIDE;
@@ -95,7 +96,6 @@ class BufferedResourceHandler
scoped_refptr<ResourceResponse> response_;
ResourceDispatcherHostImpl* host_;
- net::URLRequest* request_;
scoped_refptr<net::IOBuffer> read_buffer_;
int read_buffer_size_;
int bytes_read_;
diff --git a/chromium/content/browser/loader/certificate_resource_handler.cc b/chromium/content/browser/loader/certificate_resource_handler.cc
index 9d995428b61..b9ae4ee4e56 100644
--- a/chromium/content/browser/loader/certificate_resource_handler.cc
+++ b/chromium/content/browser/loader/certificate_resource_handler.cc
@@ -18,15 +18,11 @@
namespace content {
CertificateResourceHandler::CertificateResourceHandler(
- net::URLRequest* request,
- int render_process_host_id,
- int render_view_id)
- : request_(request),
+ net::URLRequest* request)
+ : ResourceHandler(request),
content_length_(0),
read_buffer_(NULL),
resource_buffer_(NULL),
- render_process_host_id_(render_process_host_id),
- render_view_id_(render_view_id),
cert_type_(net::CERTIFICATE_MIME_TYPE_UNKNOWN) {
}
@@ -61,7 +57,7 @@ bool CertificateResourceHandler::OnWillStart(int request_id,
}
bool CertificateResourceHandler::OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) {
static const int kReadBufSize = 32768;
@@ -97,12 +93,13 @@ bool CertificateResourceHandler::OnReadCompleted(int request_id,
return true;
}
-bool CertificateResourceHandler::OnResponseCompleted(
+void CertificateResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& urs,
- const std::string& sec_info) {
+ const std::string& sec_info,
+ bool* defer) {
if (urs.status() != net::URLRequestStatus::SUCCESS)
- return false;
+ return;
AssembleResource();
@@ -112,11 +109,10 @@ bool CertificateResourceHandler::OnResponseCompleted(
// Note that it's up to the browser to verify that the certificate
// data is well-formed.
+ const ResourceRequestInfo* info = GetRequestInfo();
GetContentClient()->browser()->AddCertificate(
- request_, cert_type_, content_bytes, content_length_,
- render_process_host_id_, render_view_id_);
-
- return true;
+ request(), cert_type_, content_bytes, content_length_,
+ info->GetChildID(), info->GetRouteID());
}
void CertificateResourceHandler::AssembleResource() {
diff --git a/chromium/content/browser/loader/certificate_resource_handler.h b/chromium/content/browser/loader/certificate_resource_handler.h
index b1bd8f4a2fa..845bea01fd9 100644
--- a/chromium/content/browser/loader/certificate_resource_handler.h
+++ b/chromium/content/browser/loader/certificate_resource_handler.h
@@ -31,9 +31,7 @@ namespace content {
//
class CertificateResourceHandler : public ResourceHandler {
public:
- CertificateResourceHandler(net::URLRequest* request,
- int render_process_host_id,
- int render_view_id);
+ explicit CertificateResourceHandler(net::URLRequest* request);
virtual ~CertificateResourceHandler();
virtual bool OnUploadProgress(int request_id,
@@ -58,7 +56,7 @@ class CertificateResourceHandler : public ResourceHandler {
// Create a new buffer to store received data.
virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) OVERRIDE;
@@ -68,9 +66,10 @@ class CertificateResourceHandler : public ResourceHandler {
bool* defer) OVERRIDE;
// Done downloading the certificate.
- virtual bool OnResponseCompleted(int request_id,
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& urs,
- const std::string& sec_info) OVERRIDE;
+ const std::string& sec_info,
+ bool* defer) OVERRIDE;
// N/A to cert downloading.
virtual void OnDataDownloaded(int request_id, int bytes_downloaded) OVERRIDE;
@@ -82,15 +81,10 @@ class CertificateResourceHandler : public ResourceHandler {
void AssembleResource();
GURL url_;
- net::URLRequest* request_;
size_t content_length_;
ContentVector buffer_;
scoped_refptr<net::IOBuffer> read_buffer_;
scoped_refptr<net::IOBuffer> resource_buffer_; // Downloaded certificate.
- // The id of the |RenderProcessHost| which started the download.
- int render_process_host_id_;
- // The id of the |RenderView| which started the download.
- int render_view_id_;
net::CertificateMimeType cert_type_;
DISALLOW_COPY_AND_ASSIGN(CertificateResourceHandler);
};
diff --git a/chromium/content/browser/loader/cross_site_resource_handler.cc b/chromium/content/browser/loader/cross_site_resource_handler.cc
index 6b735f6d4fd..4215a9fd965 100644
--- a/chromium/content/browser/loader/cross_site_resource_handler.cc
+++ b/chromium/content/browser/loader/cross_site_resource_handler.cc
@@ -8,27 +8,65 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "content/browser/cross_site_request_manager.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/common/resource_response.h"
#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request.h"
+#include "webkit/browser/appcache/appcache_interceptor.h"
namespace content {
namespace {
-void OnCrossSiteResponseHelper(int render_process_id,
- int render_view_id,
- int request_id) {
- RenderViewHostImpl* rvh = RenderViewHostImpl::FromID(render_process_id,
- render_view_id);
- if (rvh && rvh->GetDelegate()->GetRendererManagementDelegate()) {
- rvh->GetDelegate()->GetRendererManagementDelegate()->OnCrossSiteResponse(
- rvh, GlobalRequestID(render_process_id, request_id));
+// The parameters to OnCrossSiteResponseHelper exceed the number of arguments
+// base::Bind supports.
+struct CrossSiteResponseParams {
+ CrossSiteResponseParams(int render_view_id,
+ const GlobalRequestID& global_request_id,
+ bool is_transfer,
+ const std::vector<GURL>& transfer_url_chain,
+ const Referrer& referrer,
+ PageTransition page_transition,
+ int64 frame_id,
+ bool should_replace_current_entry)
+ : render_view_id(render_view_id),
+ global_request_id(global_request_id),
+ is_transfer(is_transfer),
+ transfer_url_chain(transfer_url_chain),
+ referrer(referrer),
+ page_transition(page_transition),
+ frame_id(frame_id),
+ should_replace_current_entry(should_replace_current_entry) {
+ }
+
+ int render_view_id;
+ GlobalRequestID global_request_id;
+ bool is_transfer;
+ std::vector<GURL> transfer_url_chain;
+ Referrer referrer;
+ PageTransition page_transition;
+ int64 frame_id;
+ bool should_replace_current_entry;
+};
+
+void OnCrossSiteResponseHelper(const CrossSiteResponseParams& params) {
+ RenderViewHostImpl* rvh =
+ RenderViewHostImpl::FromID(params.global_request_id.child_id,
+ params.render_view_id);
+ if (rvh) {
+ rvh->OnCrossSiteResponse(
+ params.global_request_id, params.is_transfer,
+ params.transfer_url_chain, params.referrer,
+ params.page_transition, params.frame_id,
+ params.should_replace_current_entry);
}
}
@@ -36,25 +74,18 @@ void OnCrossSiteResponseHelper(int render_process_id,
CrossSiteResourceHandler::CrossSiteResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
- int render_process_host_id,
- int render_view_id,
net::URLRequest* request)
- : LayeredResourceHandler(next_handler.Pass()),
- render_process_host_id_(render_process_host_id),
- render_view_id_(render_view_id),
- request_(request),
+ : LayeredResourceHandler(request, next_handler.Pass()),
has_started_response_(false),
in_cross_site_transition_(false),
- request_id_(-1),
completed_during_transition_(false),
did_defer_(false),
- completed_status_(),
- response_(NULL) {
+ completed_status_() {
}
CrossSiteResourceHandler::~CrossSiteResourceHandler() {
// Cleanup back-pointer stored on the request info.
- ResourceRequestInfoImpl::ForRequest(request_)->set_cross_site_handler(NULL);
+ GetRequestInfo()->set_cross_site_handler(NULL);
}
bool CrossSiteResourceHandler::OnRequestRedirected(
@@ -79,7 +110,18 @@ bool CrossSiteResourceHandler::OnResponseStarted(
DCHECK(!in_cross_site_transition_);
has_started_response_ = true;
- ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_);
+ ResourceRequestInfoImpl* info = GetRequestInfo();
+
+ // We will need to swap processes if either (1) a redirect that requires a
+ // transfer occurred before we got here, or (2) a pending cross-site request
+ // was already in progress. Note that a swap may no longer be needed if we
+ // transferred back into the original process due to a redirect.
+ bool should_transfer =
+ GetContentClient()->browser()->ShouldSwapProcessesForRedirect(
+ info->GetContext(), request()->original_url(), request()->url());
+ bool swap_needed = should_transfer ||
+ CrossSiteRequestManager::GetInstance()->
+ HasPendingCrossSiteRequest(info->GetChildID(), info->GetRouteID());
// If this is a download, just pass the response through without doing a
// cross-site check. The renderer will see it is a download and abort the
@@ -89,16 +131,20 @@ bool CrossSiteResourceHandler::OnResponseStarted(
// page. We should allow the navigation to finish without running the unload
// handler or swapping in the pending RenderViewHost.
//
- // In both cases, the pending RenderViewHost will stick around until the next
- // cross-site navigation, since we are unable to tell when to destroy it.
- // See RenderViewHostManager::RendererAbortedProvisionalLoad.
- if (info->is_download() || (response->head.headers.get() &&
- response->head.headers->response_code() == 204)) {
+ // In both cases, any pending RenderViewHost (if one was created for this
+ // navigation) will stick around until the next cross-site navigation, since
+ // we are unable to tell when to destroy it.
+ // See RenderFrameHostManager::RendererAbortedProvisionalLoad.
+ if (!swap_needed || info->IsDownload() ||
+ (response->head.headers.get() &&
+ response->head.headers->response_code() == 204)) {
return next_handler_->OnResponseStarted(request_id, response, defer);
}
- // Tell the renderer to run the onunload event handler.
- StartCrossSiteTransition(request_id, response);
+ // Now that we know a swap is needed and we have something to commit, we
+ // pause to let the UI thread run the unload handler of the previous page
+ // and set up a transfer if needed.
+ StartCrossSiteTransition(request_id, response, should_transfer);
// Defer loading until after the onunload event handler has run.
did_defer_ = *defer = true;
@@ -112,24 +158,30 @@ bool CrossSiteResourceHandler::OnReadCompleted(int request_id,
return next_handler_->OnReadCompleted(request_id, bytes_read, defer);
}
-bool CrossSiteResourceHandler::OnResponseCompleted(
+void CrossSiteResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) {
+ const std::string& security_info,
+ bool* defer) {
if (!in_cross_site_transition_) {
+ ResourceRequestInfoImpl* info = GetRequestInfo();
+ // If we've already completed the transition, or we're canceling the
+ // request, or an error occurred with no cross-process navigation in
+ // progress, then we should just pass this through.
if (has_started_response_ ||
- status.status() != net::URLRequestStatus::FAILED) {
- // We've already completed the transition or we're canceling the request,
- // so just pass it through.
- return next_handler_->OnResponseCompleted(request_id, status,
- security_info);
+ status.status() != net::URLRequestStatus::FAILED ||
+ !CrossSiteRequestManager::GetInstance()->HasPendingCrossSiteRequest(
+ info->GetChildID(), info->GetRouteID())) {
+ next_handler_->OnResponseCompleted(request_id, status,
+ security_info, defer);
+ return;
}
- // An error occured, we should wait now for the cross-site transition,
+ // An error occurred. We should wait now for the cross-process transition,
// so that the error message (e.g., 404) can be displayed to the user.
// Also continue with the logic below to remember that we completed
// during the cross-site transition.
- StartCrossSiteTransition(request_id, NULL);
+ StartCrossSiteTransition(request_id, NULL, false);
}
// We have to buffer the call until after the transition completes.
@@ -137,24 +189,26 @@ bool CrossSiteResourceHandler::OnResponseCompleted(
completed_status_ = status;
completed_security_info_ = security_info;
- // Return false to tell RDH not to notify the world or clean up the
- // pending request. We will do so in ResumeResponse.
+ // Defer to tell RDH not to notify the world or clean up the pending request.
+ // We will do so in ResumeResponse.
did_defer_ = true;
- return false;
+ *defer = true;
}
// We can now send the response to the new renderer, which will cause
// WebContentsImpl to swap in the new renderer and destroy the old one.
void CrossSiteResourceHandler::ResumeResponse() {
- DCHECK(request_id_ != -1);
+ DCHECK(request());
DCHECK(in_cross_site_transition_);
in_cross_site_transition_ = false;
+ ResourceRequestInfoImpl* info = GetRequestInfo();
if (has_started_response_) {
// Send OnResponseStarted to the new renderer.
DCHECK(response_);
bool defer = false;
- if (!next_handler_->OnResponseStarted(request_id_, response_, &defer)) {
+ if (!next_handler_->OnResponseStarted(info->GetRequestID(), response_.get(),
+ &defer)) {
controller()->Cancel();
} else if (!defer) {
// Unpause the request to resume reading. Any further reads will be
@@ -164,17 +218,18 @@ void CrossSiteResourceHandler::ResumeResponse() {
}
// Remove ourselves from the ExtraRequestInfo.
- ResourceRequestInfoImpl* info =
- ResourceRequestInfoImpl::ForRequest(request_);
info->set_cross_site_handler(NULL);
// If the response completed during the transition, notify the next
// event handler.
if (completed_during_transition_) {
- if (next_handler_->OnResponseCompleted(request_id_, completed_status_,
- completed_security_info_)) {
+ bool defer = false;
+ next_handler_->OnResponseCompleted(info->GetRequestID(),
+ completed_status_,
+ completed_security_info_,
+ &defer);
+ if (!defer)
ResumeIfDeferred();
- }
}
}
@@ -182,31 +237,51 @@ void CrossSiteResourceHandler::ResumeResponse() {
// telling the old RenderViewHost to run its onunload handler.
void CrossSiteResourceHandler::StartCrossSiteTransition(
int request_id,
- ResourceResponse* response) {
+ ResourceResponse* response,
+ bool should_transfer) {
in_cross_site_transition_ = true;
- request_id_ = request_id;
response_ = response;
// Store this handler on the ExtraRequestInfo, so that RDH can call our
- // ResumeResponse method when the close ACK is received.
- ResourceRequestInfoImpl* info =
- ResourceRequestInfoImpl::ForRequest(request_);
+ // ResumeResponse method when we are ready to resume.
+ ResourceRequestInfoImpl* info = GetRequestInfo();
info->set_cross_site_handler(this);
+ DCHECK_EQ(request_id, info->GetRequestID());
+ GlobalRequestID global_id(info->GetChildID(), info->GetRequestID());
+
// Tell the contents responsible for this request that a cross-site response
// is starting, so that it can tell its old renderer to run its onunload
- // handler now. We will wait to hear the corresponding ClosePage_ACK.
+ // handler now. We will wait until the unload is finished and (if a transfer
+ // is needed) for the new renderer's request to arrive.
+ // The |transfer_url_chain| contains any redirect URLs that have already
+ // occurred, plus the destination URL at the end.
+ std::vector<GURL> transfer_url_chain;
+ Referrer referrer;
+ int frame_id = -1;
+ if (should_transfer) {
+ transfer_url_chain = request()->url_chain();
+ referrer = Referrer(GURL(request()->referrer()), info->GetReferrerPolicy());
+ frame_id = info->GetFrameID();
+
+ appcache::AppCacheInterceptor::PrepareForCrossSiteTransfer(
+ request(), global_id.child_id);
+ ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(
+ global_id, transfer_url_chain.front());
+ }
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(
&OnCrossSiteResponseHelper,
- render_process_host_id_,
- render_view_id_,
- request_id));
-
- // TODO(creis): If the above call should fail, then we need to notify the IO
- // thread to proceed anyway, using ResourceDispatcherHost::OnClosePageACK.
+ CrossSiteResponseParams(info->GetRouteID(),
+ global_id,
+ should_transfer,
+ transfer_url_chain,
+ referrer,
+ info->GetPageTransition(),
+ frame_id,
+ info->should_replace_current_entry())));
}
void CrossSiteResourceHandler::ResumeIfDeferred() {
diff --git a/chromium/content/browser/loader/cross_site_resource_handler.h b/chromium/content/browser/loader/cross_site_resource_handler.h
index 378a2061164..29e3f5acdbc 100644
--- a/chromium/content/browser/loader/cross_site_resource_handler.h
+++ b/chromium/content/browser/loader/cross_site_resource_handler.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_LOADER_CROSS_SITE_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_CROSS_SITE_RESOURCE_HANDLER_H_
+#include "base/memory/ref_counted.h"
#include "content/browser/loader/layered_resource_handler.h"
#include "net/url_request/url_request_status.h"
@@ -22,8 +23,6 @@ namespace content {
class CrossSiteResourceHandler : public LayeredResourceHandler {
public:
CrossSiteResourceHandler(scoped_ptr<ResourceHandler> next_handler,
- int render_process_host_id,
- int render_view_id,
net::URLRequest* request);
virtual ~CrossSiteResourceHandler();
@@ -38,9 +37,10 @@ class CrossSiteResourceHandler : public LayeredResourceHandler {
virtual bool OnReadCompleted(int request_id,
int bytes_read,
bool* defer) OVERRIDE;
- virtual bool OnResponseCompleted(int request_id,
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) OVERRIDE;
+ const std::string& security_info,
+ bool* defer) OVERRIDE;
// We can now send the response to the new renderer, which will cause
// WebContentsImpl to swap in the new renderer and destroy the old one.
@@ -49,23 +49,19 @@ class CrossSiteResourceHandler : public LayeredResourceHandler {
private:
// Prepare to render the cross-site response in a new RenderViewHost, by
// telling the old RenderViewHost to run its onunload handler.
- void StartCrossSiteTransition(
- int request_id,
- ResourceResponse* response);
+ void StartCrossSiteTransition(int request_id,
+ ResourceResponse* response,
+ bool should_transfer);
void ResumeIfDeferred();
- int render_process_host_id_;
- int render_view_id_;
- net::URLRequest* request_;
bool has_started_response_;
bool in_cross_site_transition_;
- int request_id_;
bool completed_during_transition_;
bool did_defer_;
net::URLRequestStatus completed_status_;
std::string completed_security_info_;
- ResourceResponse* response_;
+ scoped_refptr<ResourceResponse> response_;
DISALLOW_COPY_AND_ASSIGN(CrossSiteResourceHandler);
};
diff --git a/chromium/content/browser/loader/detachable_resource_handler.cc b/chromium/content/browser/loader/detachable_resource_handler.cc
new file mode 100644
index 00000000000..7cc7b09d0ce
--- /dev/null
+++ b/chromium/content/browser/loader/detachable_resource_handler.cc
@@ -0,0 +1,209 @@
+// 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/loader/detachable_resource_handler.h"
+
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "content/browser/loader/resource_request_info_impl.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request_status.h"
+
+namespace {
+// This matches the maximum allocation size of AsyncResourceHandler.
+const int kReadBufSize = 32 * 1024;
+}
+
+namespace content {
+
+DetachableResourceHandler::DetachableResourceHandler(
+ net::URLRequest* request,
+ base::TimeDelta cancel_delay,
+ scoped_ptr<ResourceHandler> next_handler)
+ : ResourceHandler(request),
+ next_handler_(next_handler.Pass()),
+ cancel_delay_(cancel_delay),
+ is_deferred_(false),
+ is_finished_(false) {
+ GetRequestInfo()->set_detachable_handler(this);
+}
+
+DetachableResourceHandler::~DetachableResourceHandler() {
+ // Cleanup back-pointer stored on the request info.
+ GetRequestInfo()->set_detachable_handler(NULL);
+}
+
+void DetachableResourceHandler::Detach() {
+ if (is_detached())
+ return;
+
+ if (!is_finished_) {
+ // Simulate a cancel on the next handler before destroying it.
+ net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
+ net::ERR_ABORTED);
+ bool defer_ignored = false;
+ next_handler_->OnResponseCompleted(GetRequestID(), status, std::string(),
+ &defer_ignored);
+ DCHECK(!defer_ignored);
+ // If |next_handler_| were to defer its shutdown in OnResponseCompleted,
+ // this would destroy it anyway. Fortunately, AsyncResourceHandler never
+ // does this anyway, so DCHECK it. BufferedResourceHandler and RVH shutdown
+ // already ignore deferred ResourceHandler shutdown, but
+ // DetachableResourceHandler and the detach-on-renderer-cancel logic
+ // introduces a case where this occurs when the renderer cancels a resource.
+ }
+ // A OnWillRead / OnReadCompleted pair may still be in progress, but
+ // OnWillRead passes back a scoped_refptr, so downstream handler's buffer will
+ // survive long enough to complete that read. From there, future reads will
+ // drain into |read_buffer_|. (If |next_handler_| is an AsyncResourceHandler,
+ // the net::IOBuffer takes a reference to the ResourceBuffer which owns the
+ // shared memory.)
+ next_handler_.reset();
+
+ // Time the request out if it takes too long.
+ detached_timer_.reset(new base::OneShotTimer<DetachableResourceHandler>());
+ detached_timer_->Start(
+ FROM_HERE, cancel_delay_, this, &DetachableResourceHandler::Cancel);
+
+ // Resume if necessary. The request may have been deferred, say, waiting on a
+ // full buffer in AsyncResourceHandler. Now that it has been detached, resume
+ // and drain it.
+ if (is_deferred_)
+ Resume();
+}
+
+void DetachableResourceHandler::SetController(ResourceController* controller) {
+ ResourceHandler::SetController(controller);
+
+ // Intercept the ResourceController for downstream handlers to keep track of
+ // whether the request is deferred.
+ if (next_handler_)
+ next_handler_->SetController(this);
+}
+
+bool DetachableResourceHandler::OnUploadProgress(int request_id,
+ uint64 position,
+ uint64 size) {
+ if (!next_handler_)
+ return true;
+
+ return next_handler_->OnUploadProgress(request_id, position, size);
+}
+
+bool DetachableResourceHandler::OnRequestRedirected(int request_id,
+ const GURL& url,
+ ResourceResponse* response,
+ bool* defer) {
+ DCHECK(!is_deferred_);
+
+ if (!next_handler_)
+ return true;
+
+ bool ret = next_handler_->OnRequestRedirected(request_id, url, response,
+ &is_deferred_);
+ *defer = is_deferred_;
+ return ret;
+}
+
+bool DetachableResourceHandler::OnResponseStarted(int request_id,
+ ResourceResponse* response,
+ bool* defer) {
+ DCHECK(!is_deferred_);
+
+ if (!next_handler_)
+ return true;
+
+ bool ret =
+ next_handler_->OnResponseStarted(request_id, response, &is_deferred_);
+ *defer = is_deferred_;
+ return ret;
+}
+
+bool DetachableResourceHandler::OnWillStart(int request_id, const GURL& url,
+ bool* defer) {
+ DCHECK(!is_deferred_);
+
+ if (!next_handler_)
+ return true;
+
+ bool ret = next_handler_->OnWillStart(request_id, url, &is_deferred_);
+ *defer = is_deferred_;
+ return ret;
+}
+
+bool DetachableResourceHandler::OnWillRead(int request_id,
+ scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) {
+ if (!next_handler_) {
+ DCHECK_EQ(-1, min_size);
+ if (!read_buffer_)
+ read_buffer_ = new net::IOBuffer(kReadBufSize);
+ *buf = read_buffer_;
+ *buf_size = kReadBufSize;
+ return true;
+ }
+
+ return next_handler_->OnWillRead(request_id, buf, buf_size, min_size);
+}
+
+bool DetachableResourceHandler::OnReadCompleted(int request_id, int bytes_read,
+ bool* defer) {
+ DCHECK(!is_deferred_);
+
+ if (!next_handler_)
+ return true;
+
+ bool ret =
+ next_handler_->OnReadCompleted(request_id, bytes_read, &is_deferred_);
+ *defer = is_deferred_;
+ return ret;
+}
+
+void DetachableResourceHandler::OnResponseCompleted(
+ int request_id,
+ const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) {
+ // No DCHECK(!is_deferred_) as the request may have been cancelled while
+ // deferred.
+
+ if (!next_handler_)
+ return;
+
+ is_finished_ = true;
+
+ next_handler_->OnResponseCompleted(request_id, status, security_info,
+ &is_deferred_);
+ *defer = is_deferred_;
+}
+
+void DetachableResourceHandler::OnDataDownloaded(int request_id,
+ int bytes_downloaded) {
+ if (!next_handler_)
+ return;
+
+ next_handler_->OnDataDownloaded(request_id, bytes_downloaded);
+}
+
+void DetachableResourceHandler::Resume() {
+ DCHECK(is_deferred_);
+ is_deferred_ = false;
+ controller()->Resume();
+}
+
+void DetachableResourceHandler::Cancel() {
+ controller()->Cancel();
+}
+
+void DetachableResourceHandler::CancelAndIgnore() {
+ controller()->CancelAndIgnore();
+}
+
+void DetachableResourceHandler::CancelWithError(int error_code) {
+ controller()->CancelWithError(error_code);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/detachable_resource_handler.h b/chromium/content/browser/loader/detachable_resource_handler.h
new file mode 100644
index 00000000000..990084d93b8
--- /dev/null
+++ b/chromium/content/browser/loader/detachable_resource_handler.h
@@ -0,0 +1,94 @@
+// 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_LOADER_DETACHABLE_RESOURCE_HANDLER_H_
+#define CONTENT_BROWSER_LOADER_DETACHABLE_RESOURCE_HANDLER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "content/browser/loader/resource_handler.h"
+#include "content/public/browser/resource_controller.h"
+
+namespace net {
+class IOBuffer;
+class URLRequest;
+} // namespace net
+
+namespace content {
+
+// A ResourceHandler which delegates all calls to the next handler, unless
+// detached. Once detached, it drives the request to completion itself. This is
+// used for requests which outlive the owning renderer, such as <link
+// rel=prefetch> and <a ping>. Requests do not start out detached so, e.g.,
+// prefetches appear in DevTools and get placed in the renderer's local
+// cache. If the request does not complete after a timeout on detach, it is
+// cancelled.
+//
+// Note that, once detached, the request continues without the original next
+// handler, so any policy decisions in that handler are skipped.
+class DetachableResourceHandler : public ResourceHandler,
+ public ResourceController {
+ public:
+ DetachableResourceHandler(net::URLRequest* request,
+ base::TimeDelta cancel_delay,
+ scoped_ptr<ResourceHandler> next_handler);
+ virtual ~DetachableResourceHandler();
+
+ bool is_detached() const { return next_handler_ == NULL; }
+ void Detach();
+
+ void set_cancel_delay(base::TimeDelta cancel_delay) {
+ cancel_delay_ = cancel_delay;
+ }
+
+ // ResourceHandler implementation:
+ virtual void SetController(ResourceController* controller) OVERRIDE;
+ virtual bool OnUploadProgress(int request_id, uint64 position,
+ uint64 size) OVERRIDE;
+ virtual bool OnRequestRedirected(int request_id, const GURL& url,
+ ResourceResponse* response,
+ bool* defer) OVERRIDE;
+ virtual bool OnResponseStarted(int request_id,
+ ResourceResponse* response,
+ bool* defer) OVERRIDE;
+ virtual bool OnWillStart(int request_id, const GURL& url,
+ bool* defer) OVERRIDE;
+ virtual bool OnWillRead(int request_id,
+ scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) OVERRIDE;
+ virtual bool OnReadCompleted(int request_id, int bytes_read,
+ bool* defer) OVERRIDE;
+ virtual void OnResponseCompleted(int request_id,
+ const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) OVERRIDE;
+ virtual void OnDataDownloaded(int request_id, int bytes_downloaded) OVERRIDE;
+
+ // ResourceController implementation:
+ virtual void Resume() OVERRIDE;
+ virtual void Cancel() OVERRIDE;
+ virtual void CancelAndIgnore() OVERRIDE;
+ virtual void CancelWithError(int error_code) OVERRIDE;
+
+ private:
+ scoped_ptr<ResourceHandler> next_handler_;
+ scoped_refptr<net::IOBuffer> read_buffer_;
+
+ scoped_ptr<base::OneShotTimer<DetachableResourceHandler> > detached_timer_;
+ base::TimeDelta cancel_delay_;
+
+ bool is_deferred_;
+ bool is_finished_;
+
+ DISALLOW_COPY_AND_ASSIGN(DetachableResourceHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_DETACHABLE_RESOURCE_HANDLER_H_
diff --git a/chromium/content/browser/loader/doomed_resource_handler.cc b/chromium/content/browser/loader/doomed_resource_handler.cc
deleted file mode 100644
index d9f2f58486f..00000000000
--- a/chromium/content/browser/loader/doomed_resource_handler.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/doomed_resource_handler.h"
-
-#include "base/logging.h"
-#include "net/url_request/url_request_status.h"
-
-namespace content {
-
-DoomedResourceHandler::DoomedResourceHandler(
- scoped_ptr<ResourceHandler> old_handler)
- : old_handler_(old_handler.Pass()) {
-}
-
-DoomedResourceHandler::~DoomedResourceHandler() {
-}
-
-bool DoomedResourceHandler::OnUploadProgress(int request_id,
- uint64 position,
- uint64 size) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnRequestRedirected(int request_id,
- const GURL& new_url,
- ResourceResponse* response,
- bool* defer) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnResponseStarted(int request_id,
- ResourceResponse* response,
- bool* defer) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnWillStart(int request_id,
- const GURL& url,
- bool* defer) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnWillRead(int request_id,
- net::IOBuffer** buf,
- int* buf_size,
- int min_size) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnReadCompleted(int request_id,
- int bytes_read,
- bool* defer) {
- NOTREACHED();
- return true;
-}
-
-bool DoomedResourceHandler::OnResponseCompleted(
- int request_id,
- const net::URLRequestStatus& status,
- const std::string& security_info) {
- DCHECK(status.status() == net::URLRequestStatus::CANCELED ||
- status.status() == net::URLRequestStatus::FAILED);
- return true;
-}
-
-void DoomedResourceHandler::OnDataDownloaded(int request_id,
- int bytes_downloaded) {
- NOTREACHED();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/doomed_resource_handler.h b/chromium/content/browser/loader/doomed_resource_handler.h
deleted file mode 100644
index 9533ef1c393..00000000000
--- a/chromium/content/browser/loader/doomed_resource_handler.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_DOOMED_RESOURCE_HANDLER_H_
-#define CONTENT_BROWSER_LOADER_DOOMED_RESOURCE_HANDLER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/loader/resource_handler.h"
-
-namespace content {
-
-// ResourceHandler that DCHECKs on all events but canceling and failing of
-// requests while activated for a URLRequest.
-class DoomedResourceHandler : public ResourceHandler {
- public:
- // As the DoomedResourceHandler is constructed and substituted from code
- // of another ResourceHandler, we need to make sure that this other handler
- // does not lose its last reference and gets destroyed by being substituted.
- // Therefore, we retain a reference to |old_handler| that prevents the
- // destruction.
- explicit DoomedResourceHandler(scoped_ptr<ResourceHandler> old_handler);
- virtual ~DoomedResourceHandler();
-
- // ResourceHandler implementation:
- virtual bool OnUploadProgress(int request_id,
- uint64 position,
- uint64 size) OVERRIDE;
- virtual bool OnRequestRedirected(int request_id,
- const GURL& new_url,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnResponseStarted(int request_id,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnWillStart(int request_id,
- const GURL& url,
- bool* defer) OVERRIDE;
- virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
- int* buf_size,
- int min_size) OVERRIDE;
- virtual bool OnReadCompleted(int request_id,
- int bytes_read,
- bool* defer) OVERRIDE;
- virtual bool OnResponseCompleted(int request_id,
- const net::URLRequestStatus& status,
- const std::string& security_info) OVERRIDE;
- virtual void OnDataDownloaded(int request_id,
- int bytes_downloaded) OVERRIDE;
-
- private:
- scoped_ptr<ResourceHandler> old_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(DoomedResourceHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_DOOMED_RESOURCE_HANDLER_H_
diff --git a/chromium/content/browser/loader/layered_resource_handler.cc b/chromium/content/browser/loader/layered_resource_handler.cc
index 872bc7a422d..30d3180ef3c 100644
--- a/chromium/content/browser/loader/layered_resource_handler.cc
+++ b/chromium/content/browser/loader/layered_resource_handler.cc
@@ -9,8 +9,10 @@
namespace content {
LayeredResourceHandler::LayeredResourceHandler(
+ net::URLRequest* request,
scoped_ptr<ResourceHandler> next_handler)
- : next_handler_(next_handler.Pass()) {
+ : ResourceHandler(request),
+ next_handler_(next_handler.Pass()) {
}
LayeredResourceHandler::~LayeredResourceHandler() {
@@ -54,8 +56,10 @@ bool LayeredResourceHandler::OnWillStart(int request_id, const GURL& url,
return next_handler_->OnWillStart(request_id, url, defer);
}
-bool LayeredResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
- int* buf_size, int min_size) {
+bool LayeredResourceHandler::OnWillRead(int request_id,
+ scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) {
DCHECK(next_handler_.get());
return next_handler_->OnWillRead(request_id, buf, buf_size, min_size);
}
@@ -66,12 +70,13 @@ bool LayeredResourceHandler::OnReadCompleted(int request_id, int bytes_read,
return next_handler_->OnReadCompleted(request_id, bytes_read, defer);
}
-bool LayeredResourceHandler::OnResponseCompleted(
+void LayeredResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) {
+ const std::string& security_info,
+ bool* defer) {
DCHECK(next_handler_.get());
- return next_handler_->OnResponseCompleted(request_id, status, security_info);
+ next_handler_->OnResponseCompleted(request_id, status, security_info, defer);
}
void LayeredResourceHandler::OnDataDownloaded(int request_id,
diff --git a/chromium/content/browser/loader/layered_resource_handler.h b/chromium/content/browser/loader/layered_resource_handler.h
index d41f7478e3f..e0778958d07 100644
--- a/chromium/content/browser/loader/layered_resource_handler.h
+++ b/chromium/content/browser/loader/layered_resource_handler.h
@@ -9,13 +9,18 @@
#include "content/browser/loader/resource_handler.h"
#include "content/common/content_export.h"
+namespace net {
+class URLRequest;
+} // namespace net
+
namespace content {
// A ResourceHandler that simply delegates all calls to a next handler. This
// class is intended to be subclassed.
class CONTENT_EXPORT LayeredResourceHandler : public ResourceHandler {
public:
- explicit LayeredResourceHandler(scoped_ptr<ResourceHandler> next_handler);
+ LayeredResourceHandler(net::URLRequest* request,
+ scoped_ptr<ResourceHandler> next_handler);
virtual ~LayeredResourceHandler();
// ResourceHandler implementation:
@@ -30,13 +35,16 @@ class CONTENT_EXPORT LayeredResourceHandler : public ResourceHandler {
bool* defer) OVERRIDE;
virtual bool OnWillStart(int request_id, const GURL& url,
bool* defer) OVERRIDE;
- virtual bool OnWillRead(int request_id, net::IOBuffer** buf, int* buf_size,
+ virtual bool OnWillRead(int request_id,
+ scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
int min_size) OVERRIDE;
virtual bool OnReadCompleted(int request_id, int bytes_read,
bool* defer) OVERRIDE;
- virtual bool OnResponseCompleted(int request_id,
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) OVERRIDE;
+ const std::string& security_info,
+ bool* defer) OVERRIDE;
virtual void OnDataDownloaded(int request_id, int bytes_downloaded) OVERRIDE;
scoped_ptr<ResourceHandler> next_handler_;
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 d9b843cba25..7a084b0a71d 100644
--- a/chromium/content/browser/loader/power_save_block_resource_throttle.cc
+++ b/chromium/content/browser/loader/power_save_block_resource_throttle.cc
@@ -34,6 +34,10 @@ void PowerSaveBlockResourceThrottle::WillProcessResponse(bool* defer) {
timer_.Stop();
}
+const char* PowerSaveBlockResourceThrottle::GetNameForLogging() const {
+ return "PowerSaveBlockResourceThrottle";
+}
+
void PowerSaveBlockResourceThrottle::ActivatePowerSaveBlocker() {
power_save_blocker_ = PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
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 e94b5426157..2a4f9b39c5a 100644
--- a/chromium/content/browser/loader/power_save_block_resource_throttle.h
+++ b/chromium/content/browser/loader/power_save_block_resource_throttle.h
@@ -24,6 +24,7 @@ class PowerSaveBlockResourceThrottle : public ResourceThrottle {
// ResourceThrottle overrides:
virtual void WillStartRequest(bool* defer) OVERRIDE;
virtual void WillProcessResponse(bool* defer) OVERRIDE;
+ virtual const char* GetNameForLogging() const OVERRIDE;
private:
void ActivatePowerSaveBlocker();
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
index 9d996dc3d52..37372afbbd9 100644
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
+++ b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
@@ -11,6 +11,7 @@
#include "base/platform_file.h"
#include "base/threading/thread_restrictions.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"
#include "content/public/common/resource_response.h"
#include "net/base/file_stream.h"
@@ -54,13 +55,11 @@ static const int kMaxReadBufSize = 524288;
RedirectToFileResourceHandler::RedirectToFileResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
- int process_id,
+ net::URLRequest* request,
ResourceDispatcherHostImpl* host)
- : LayeredResourceHandler(next_handler.Pass()),
+ : LayeredResourceHandler(request, next_handler.Pass()),
weak_factory_(this),
host_(host),
- process_id_(process_id),
- request_id_(-1),
buf_(new net::GrowableIOBuffer()),
buf_write_pending_(false),
write_cursor_(0),
@@ -88,7 +87,6 @@ bool RedirectToFileResourceHandler::OnResponseStarted(
bool RedirectToFileResourceHandler::OnWillStart(int request_id,
const GURL& url,
bool* defer) {
- request_id_ = request_id;
if (!deletable_file_.get()) {
// Defer starting the request until we have created the temporary file.
// TODO(darin): This is sub-optimal. We should not delay starting the
@@ -104,10 +102,11 @@ bool RedirectToFileResourceHandler::OnWillStart(int request_id,
return next_handler_->OnWillStart(request_id, url, defer);
}
-bool RedirectToFileResourceHandler::OnWillRead(int request_id,
- net::IOBuffer** buf,
- int* buf_size,
- int min_size) {
+bool RedirectToFileResourceHandler::OnWillRead(
+ int request_id,
+ scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) {
DCHECK_EQ(-1, min_size);
if (buf_->capacity() < next_buffer_size_)
@@ -147,17 +146,20 @@ bool RedirectToFileResourceHandler::OnReadCompleted(int request_id,
return WriteMore();
}
-bool RedirectToFileResourceHandler::OnResponseCompleted(
+void RedirectToFileResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) {
+ const std::string& security_info,
+ bool* defer) {
if (write_callback_pending_) {
completed_during_write_ = true;
completed_status_ = status;
completed_security_info_ = security_info;
- return false;
+ did_defer_ = true;
+ *defer = true;
+ return;
}
- return next_handler_->OnResponseCompleted(request_id, status, security_info);
+ next_handler_->OnResponseCompleted(request_id, status, security_info, defer);
}
void RedirectToFileResourceHandler::DidCreateTemporaryFile(
@@ -172,17 +174,19 @@ void RedirectToFileResourceHandler::DidCreateTemporaryFile(
new net::FileStream(file_handle.ReleaseValue(),
base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC,
NULL));
+ const ResourceRequestInfo* info = GetRequestInfo();
host_->RegisterDownloadedTempFile(
- process_id_, request_id_, deletable_file_.get());
+ info->GetChildID(), info->GetRequestID(), deletable_file_.get());
ResumeIfDeferred();
}
void RedirectToFileResourceHandler::DidWriteToFile(int result) {
write_callback_pending_ = false;
+ int request_id = GetRequestID();
bool failed = false;
if (result > 0) {
- next_handler_->OnDataDownloaded(request_id_, result);
+ next_handler_->OnDataDownloaded(request_id, result);
write_cursor_ += result;
failed = !WriteMore();
} else {
@@ -192,10 +196,13 @@ void RedirectToFileResourceHandler::DidWriteToFile(int result) {
if (failed) {
ResumeIfDeferred();
} else if (completed_during_write_) {
- if (next_handler_->OnResponseCompleted(request_id_, completed_status_,
- completed_security_info_)) {
+ bool defer = false;
+ next_handler_->OnResponseCompleted(request_id,
+ completed_status_,
+ completed_security_info_,
+ &defer);
+ if (!defer)
ResumeIfDeferred();
- }
}
}
@@ -246,7 +253,7 @@ bool RedirectToFileResourceHandler::WriteMore() {
}
if (rv <= 0)
return false;
- next_handler_->OnDataDownloaded(request_id_, rv);
+ next_handler_->OnDataDownloaded(GetRequestID(), rv);
write_cursor_ += rv;
}
}
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.h b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
index 459b98212c4..3d62835e888 100644
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.h
+++ b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
@@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "base/platform_file.h"
#include "content/browser/loader/layered_resource_handler.h"
+#include "net/url_request/url_request.h"
#include "net/url_request/url_request_status.h"
namespace net {
@@ -31,7 +32,7 @@ class RedirectToFileResourceHandler : public LayeredResourceHandler {
public:
RedirectToFileResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
- int process_id,
+ net::URLRequest* request,
ResourceDispatcherHostImpl* resource_dispatcher_host);
virtual ~RedirectToFileResourceHandler();
@@ -43,15 +44,16 @@ class RedirectToFileResourceHandler : public LayeredResourceHandler {
const GURL& url,
bool* defer) OVERRIDE;
virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) OVERRIDE;
virtual bool OnReadCompleted(int request_id,
int bytes_read,
bool* defer) OVERRIDE;
- virtual bool OnResponseCompleted(int request_id,
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) OVERRIDE;
+ const std::string& security_info,
+ bool* defer) OVERRIDE;
private:
void DidCreateTemporaryFile(base::PlatformFileError error_code,
@@ -65,8 +67,6 @@ class RedirectToFileResourceHandler : public LayeredResourceHandler {
base::WeakPtrFactory<RedirectToFileResourceHandler> weak_factory_;
ResourceDispatcherHostImpl* host_;
- int process_id_;
- int request_id_;
// We allocate a single, fixed-size IO buffer (buf_) used to read from the
// network (buf_write_pending_ is true while the system is copying data into
diff --git a/chromium/content/browser/loader/render_view_host_tracker.cc b/chromium/content/browser/loader/render_view_host_tracker.cc
deleted file mode 100644
index 2f006e8e990..00000000000
--- a/chromium/content/browser/loader/render_view_host_tracker.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/render_view_host_tracker.h"
-
-#include "base/bind_helpers.h"
-#include "base/stl_util.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_scheduler.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-
-namespace content {
-
-RenderViewHostTracker::RenderViewHostTracker()
- : rvh_created_callback_(
- base::Bind(&RenderViewHostTracker::RenderViewHostCreated,
- base::Unretained(this))) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RenderViewHost::AddCreatedCallback(rvh_created_callback_);
-}
-
-RenderViewHostTracker::~RenderViewHostTracker() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(observers_.empty());
- RenderViewHost::RemoveCreatedCallback(rvh_created_callback_);
-}
-
-void RenderViewHostTracker::RenderViewHostCreated(RenderViewHost* rvh) {
- Observer* observer = new Observer(rvh, this);
- observers_.insert(observer);
-
- int child_id = rvh->GetProcess()->GetID();
- int route_id = rvh->GetRoutingID();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostCreated,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- child_id, route_id));
-}
-
-void RenderViewHostTracker::RemoveObserver(Observer* observer) {
- DCHECK(ContainsKey(observers_, observer));
- observers_.erase(observer);
- delete observer;
-}
-
-RenderViewHostTracker::Observer::Observer(RenderViewHost* rvh,
- RenderViewHostTracker* tracker)
- : RenderViewHostObserver(rvh),
- tracker_(tracker) {
-}
-
-RenderViewHostTracker::Observer::~Observer() {
-}
-
-void RenderViewHostTracker::Observer::RenderViewHostDestroyed(
- RenderViewHost* rvh) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- int child_id = rvh->GetProcess()->GetID();
- int route_id = rvh->GetRoutingID();
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostDeleted,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- child_id, route_id));
-
- tracker_->RemoveObserver(this);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/render_view_host_tracker.h b/chromium/content/browser/loader/render_view_host_tracker.h
deleted file mode 100644
index 7fc5fa00b80..00000000000
--- a/chromium/content/browser/loader/render_view_host_tracker.h
+++ /dev/null
@@ -1,53 +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_LOADER_RENDER_VIEW_HOST_TRACKER_H_
-#define CONTENT_BROWSER_LOADER_RENDER_VIEW_HOST_TRACKER_H_
-
-#include <set>
-
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_view_host_observer.h"
-
-namespace content {
-
-// The ResourceDispatcherHost needs to know when renderers are created and
-// destroyed. That happens on the UI thread, but the ResourceDispatcherHost
-// operates on the IO thread. RenderViewHostTracker listens for renderer
-// notifications on the UI thread, then bounces them over to the IO thread so
-// the ResourceDispatcherHost can be notified.
-class CONTENT_EXPORT RenderViewHostTracker {
- public:
- RenderViewHostTracker();
- virtual ~RenderViewHostTracker();
-
- private:
- // TODO(phajdan.jr): Move this declaration of inner class to the .cc file.
- class Observer : public RenderViewHostObserver {
- public:
- Observer(RenderViewHost* rvh,
- RenderViewHostTracker* tracker);
- virtual ~Observer();
-
- private:
- // RenderViewHostObserver interface:
- virtual void RenderViewHostDestroyed(RenderViewHost* rvh) OVERRIDE;
-
- RenderViewHostTracker* tracker_;
- };
-
- friend class Observer;
- typedef std::set<Observer*> ObserverSet;
-
- void RenderViewHostCreated(RenderViewHost* rvh);
-
- void RemoveObserver(Observer* observer);
-
- RenderViewHost::CreatedCallback rvh_created_callback_;
- ObserverSet observers_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_RENDER_VIEW_HOST_TRACKER_H_
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
index 0a763fede6c..4d5d5ab598b 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -59,13 +59,13 @@ class ResourceDispatcherHostBrowserTest : public ContentBrowserTest,
void CheckTitleTest(const GURL& url,
const std::string& expected_title) {
- string16 expected_title16(ASCIIToUTF16(expected_title));
+ base::string16 expected_title16(ASCIIToUTF16(expected_title));
TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
NavigateToURL(shell(), url);
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
}
- bool GetPopupTitle(const GURL& url, string16* title) {
+ bool GetPopupTitle(const GURL& url, base::string16* title) {
NavigateToURL(shell(), url);
ShellAddedObserver new_shell_observer;
@@ -96,7 +96,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle1) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
GURL url(embedded_test_server()->GetURL("/dynamic1.html"));
- string16 title;
+ base::string16 title;
ASSERT_TRUE(GetPopupTitle(url, &title));
EXPECT_TRUE(StartsWith(title, ASCIIToUTF16("My Popup Title"), true))
<< "Actual title: " << title;
@@ -108,7 +108,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle2) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
GURL url(embedded_test_server()->GetURL("/dynamic2.html"));
- string16 title;
+ base::string16 title;
ASSERT_TRUE(GetPopupTitle(url, &title));
EXPECT_TRUE(StartsWith(title, ASCIIToUTF16("My Dynamic Title"), true))
<< "Actual title: " << title;
@@ -301,6 +301,9 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// complete and isn't conducive to quick turnarounds. As we don't currently
// strip the app on the build bots, this is bad times.
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, CrossSiteAfterCrash) {
+ // Make sure we have a live process before trying to kill it.
+ NavigateToURL(shell(), GURL("about:blank"));
+
// Cause the renderer to crash.
WindowedNotificationObserver crash_observer(
NOTIFICATION_RENDERER_PROCESS_CLOSED,
@@ -364,7 +367,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// URLs are prohibited by policy from interacting with sensitive chrome
// pages of which the error page is one. Instead, use automation to kick
// off the navigation, and wait to see that the tab loads.
- string16 expected_title16(ASCIIToUTF16("Title Of Awesomeness"));
+ base::string16 expected_title16(ASCIIToUTF16("Title Of Awesomeness"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
bool success;
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index 382a68124b1..712c8db992a 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -33,6 +33,7 @@
#include "content/browser/loader/async_resource_handler.h"
#include "content/browser/loader/buffered_resource_handler.h"
#include "content/browser/loader/cross_site_resource_handler.h"
+#include "content/browser/loader/detachable_resource_handler.h"
#include "content/browser/loader/power_save_block_resource_throttle.h"
#include "content/browser/loader/redirect_to_file_resource_handler.h"
#include "content/browser/loader/resource_message_filter.h"
@@ -40,7 +41,6 @@
#include "content/browser/loader/stream_resource_handler.h"
#include "content/browser/loader/sync_resource_handler.h"
#include "content/browser/loader/throttling_resource_handler.h"
-#include "content/browser/loader/transfer_navigation_resource_throttle.h"
#include "content/browser/loader/upload_data_stream_builder.h"
#include "content/browser/plugin_service_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
@@ -128,13 +128,22 @@ const int kUserGestureWindowMs = 3500;
// use. Arbitrarily chosen.
const double kMaxRequestsPerProcessRatio = 0.45;
-// All possible error codes from the network module. Note that the error codes
-// are all positive (since histograms expect positive sample values).
-const int kAllNetErrorCodes[] = {
-#define NET_ERROR(label, value) -(value),
-#include "net/base/net_error_list.h"
-#undef NET_ERROR
-};
+// TODO(jkarlin): The value is high to reduce the chance of the detachable
+// request timing out, forcing a blocked second request to open a new connection
+// and start over. Reduce this value once we have a better idea of what it
+// should be and once we stop blocking multiple simultaneous requests for the
+// same resource (see bugs 46104 and 31014).
+const int kDefaultDetachableCancelDelayMs = 30000;
+
+bool IsDetachableResourceType(ResourceType::Type type) {
+ switch (type) {
+ case ResourceType::PREFETCH:
+ case ResourceType::PING:
+ return true;
+ default:
+ return false;
+ }
+}
// Aborts a request before an URLRequest has actually been created.
void AbortRequestBeforeItStarts(ResourceMessageFilter* filter,
@@ -167,13 +176,13 @@ void SetReferrerForRequest(net::URLRequest* request, const Referrer& referrer) {
net::URLRequest::ReferrerPolicy net_referrer_policy =
net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
switch (referrer.policy) {
- case WebKit::WebReferrerPolicyDefault:
+ case blink::WebReferrerPolicyDefault:
net_referrer_policy =
net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
break;
- case WebKit::WebReferrerPolicyAlways:
- case WebKit::WebReferrerPolicyNever:
- case WebKit::WebReferrerPolicyOrigin:
+ case blink::WebReferrerPolicyAlways:
+ case blink::WebReferrerPolicyNever:
+ case blink::WebReferrerPolicyOrigin:
net_referrer_policy = net::URLRequest::NEVER_CLEAR_REFERRER;
break;
}
@@ -415,12 +424,15 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
for (LoaderList::iterator i = loaders_to_cancel.begin();
i != loaders_to_cancel.end(); ++i) {
// There is no strict requirement that this be the case, but currently
- // downloads, streams and transferred requests are the only requests that
- // aren't cancelled when the associated processes go away. It may be OK for
- // this invariant to change in the future, but if this assertion fires
- // without the invariant changing, then it's indicative of a leak.
- DCHECK((*i)->GetRequestInfo()->is_download() ||
+ // downloads, streams, detachable requests, and transferred requests are the
+ // only requests that aren't cancelled when the associated processes go
+ // away. It may be OK for this invariant to change in the future, but if
+ // this assertion fires without the invariant changing, then it's indicative
+ // of a leak.
+ DCHECK((*i)->GetRequestInfo()->IsDownload() ||
(*i)->GetRequestInfo()->is_stream() ||
+ ((*i)->GetRequestInfo()->detachable_handler() &&
+ (*i)->GetRequestInfo()->detachable_handler()->is_detached()) ||
(*i)->is_transferring());
}
#endif
@@ -482,7 +494,7 @@ net::Error ResourceDispatcherHostImpl::BeginDownload(
} else {
extra_load_flags |= net::LOAD_DISABLE_CACHE;
}
- request->set_load_flags(request->load_flags() | extra_load_flags);
+ request->SetLoadFlags(request->load_flags() | extra_load_flags);
// No need to get offline load flags for downloads, but make sure
// we have an OfflinePolicy to receive request completions.
@@ -571,8 +583,7 @@ ResourceDispatcherHostImpl::CreateResourceHandlerForDownload(
if (!throttles.empty()) {
handler.reset(
new ThrottlingResourceHandler(
- handler.Pass(), request_info->GetChildID(),
- request_info->GetRequestID(), throttles.Pass()));
+ handler.Pass(), request, throttles.Pass()));
}
}
return handler.Pass();
@@ -704,18 +715,20 @@ void ResourceDispatcherHostImpl::DidReceiveRedirect(ResourceLoader* loader,
void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
ResourceRequestInfoImpl* info = loader->GetRequestInfo();
+
// There should be an entry in the map created when we dispatched the
- // request.
+ // request unless it's been detached and the renderer has died.
OfflineMap::iterator policy_it(
offline_policy_map_.find(info->GetGlobalRoutingID()));
if (offline_policy_map_.end() != policy_it) {
policy_it->second->UpdateStateForSuccessfullyStartedRequest(
loader->request()->response_info());
} else {
- // We should always have an entry in offline_policy_map_ from when
- // this request traversed Begin{Download,SaveFile,Request}.
+ // Unless detached, we should have an entry in offline_policy_map_ from
+ // when this request traversed Begin{Download,SaveFile,Request}.
// TODO(rdsmith): This isn't currently true; see http://crbug.com/241176.
- NOTREACHED();
+ DCHECK(info->detachable_handler() &&
+ info->detachable_handler()->is_detached());
}
int render_process_id, render_view_id;
@@ -878,6 +891,88 @@ void ResourceDispatcherHostImpl::OnSyncLoad(
sync_result->routing_id());
}
+void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
+ int child_id,
+ int route_id,
+ int request_id,
+ const ResourceHostMsg_Request& request_data,
+ const linked_ptr<ResourceLoader>& loader) {
+ ResourceRequestInfoImpl* info = loader->GetRequestInfo();
+ GlobalRoutingID old_routing_id(
+ request_data.transferred_request_child_id, info->GetRouteID());
+ GlobalRequestID old_request_id(request_data.transferred_request_child_id,
+ request_data.transferred_request_request_id);
+ GlobalRoutingID new_routing_id(child_id, route_id);
+ GlobalRequestID new_request_id(child_id, request_id);
+
+ // Clear out data that depends on |info| before updating it.
+ IncrementOutstandingRequestsMemory(-1, *info);
+ OustandingRequestsStats empty_stats = { 0, 0 };
+ OustandingRequestsStats old_stats = GetOutstandingRequestsStats(*info);
+ UpdateOutstandingRequestsStats(*info, empty_stats);
+ pending_loaders_.erase(old_request_id);
+
+ // ResourceHandlers should always get state related to the request from the
+ // ResourceRequestInfo rather than caching it locally. This lets us update
+ // the info object when a transfer occurs.
+ info->UpdateForTransfer(child_id, route_id, request_data.origin_pid,
+ request_id, request_data.frame_id,
+ request_data.parent_frame_id, filter_->GetWeakPtr());
+
+ // Update maps that used the old IDs, if necessary. Some transfers in tests
+ // do not actually use a different ID, so not all maps need to be updated.
+ pending_loaders_[new_request_id] = loader;
+ UpdateOutstandingRequestsStats(*info, old_stats);
+ IncrementOutstandingRequestsMemory(1, *info);
+ if (old_routing_id != new_routing_id) {
+ if (offline_policy_map_.find(old_routing_id) != offline_policy_map_.end()) {
+ if (offline_policy_map_.find(new_routing_id) !=
+ offline_policy_map_.end())
+ delete offline_policy_map_[new_routing_id];
+ offline_policy_map_[new_routing_id] = offline_policy_map_[old_routing_id];
+ offline_policy_map_.erase(old_routing_id);
+ }
+ if (blocked_loaders_map_.find(old_routing_id) !=
+ blocked_loaders_map_.end()) {
+ blocked_loaders_map_[new_routing_id] =
+ blocked_loaders_map_[old_routing_id];
+ blocked_loaders_map_.erase(old_routing_id);
+ }
+ }
+ if (old_request_id != new_request_id) {
+ DelegateMap::iterator it = delegate_map_.find(old_request_id);
+ if (it != delegate_map_.end()) {
+ // Tell each delegate that the request ID has changed.
+ ObserverList<ResourceMessageDelegate>::Iterator del_it(*it->second);
+ ResourceMessageDelegate* delegate;
+ while ((delegate = del_it.GetNext()) != NULL) {
+ delegate->set_request_id(new_request_id);
+ }
+ // Now store the observer list under the new request ID.
+ delegate_map_[new_request_id] = delegate_map_[old_request_id];
+ delegate_map_.erase(old_request_id);
+ }
+ }
+
+ // Notify the delegate to allow it to update state as well.
+ if (delegate_) {
+ delegate_->WillTransferRequestToNewProcess(old_routing_id.child_id,
+ old_routing_id.route_id,
+ old_request_id.request_id,
+ child_id,
+ route_id,
+ request_id);
+ }
+
+ appcache::AppCacheInterceptor::CompleteCrossSiteTransfer(
+ loader->request(),
+ child_id,
+ request_data.appcache_host_id);
+
+ // We should have a CrossSiteResourceHandler to finish the transfer.
+ DCHECK(info->cross_site_handler());
+}
+
void ResourceDispatcherHostImpl::BeginRequest(
int request_id,
const ResourceHostMsg_Request& request_data,
@@ -887,8 +982,8 @@ void ResourceDispatcherHostImpl::BeginRequest(
int child_id = filter_->child_id();
// Reject invalid priority.
- int priority = static_cast<int>(request_data.priority);
- if (priority < net::MINIMUM_PRIORITY || priority >= net::NUM_PRIORITIES) {
+ if (request_data.priority < net::MINIMUM_PRIORITY ||
+ request_data.priority > net::MAXIMUM_PRIORITY) {
RecordAction(UserMetricsAction("BadMessageTerminate_RDH"));
filter_->BadMessageReceived();
return;
@@ -908,16 +1003,19 @@ void ResourceDispatcherHostImpl::BeginRequest(
GlobalRequestID(request_data.transferred_request_child_id,
request_data.transferred_request_request_id));
if (it != pending_loaders_.end()) {
+ // If the request is transferring to a new process, we can update our
+ // state and let it resume with its existing ResourceHandlers.
if (it->second->is_transferring()) {
deferred_loader = it->second;
- IncrementOutstandingRequestsMemory(-1,
- *deferred_loader->GetRequestInfo());
- pending_loaders_.erase(it);
+ UpdateRequestForTransfer(child_id, route_id, request_id,
+ request_data, deferred_loader);
+
+ deferred_loader->CompleteTransfer();
} else {
RecordAction(UserMetricsAction("BadMessageTerminate_RDH"));
filter_->BadMessageReceived();
- return;
}
+ return;
}
}
@@ -957,33 +1055,31 @@ void ResourceDispatcherHostImpl::BeginRequest(
load_flags |= offline_policy_map_[id]->GetAdditionalLoadFlags(
load_flags, request_data.resource_type == ResourceType::MAIN_FRAME);
+ // Sync loads should have maximum priority and should be the only
+ // requets that have the ignore limits flag set.
+ if (is_sync_load) {
+ DCHECK_EQ(request_data.priority, net::MAXIMUM_PRIORITY);
+ DCHECK_NE(load_flags & net::LOAD_IGNORE_LIMITS, 0);
+ } else {
+ DCHECK_EQ(load_flags & net::LOAD_IGNORE_LIMITS, 0);
+ }
+
// Construct the request.
scoped_ptr<net::URLRequest> new_request;
net::URLRequest* request;
- if (deferred_loader.get()) {
- request = deferred_loader->request();
+ new_request = request_context->CreateRequest(
+ request_data.url, request_data.priority, NULL);
+ request = new_request.get();
- // Give the ResourceLoader (or any of the ResourceHandlers held by it) a
- // chance to reset some state before we complete the transfer.
- deferred_loader->WillCompleteTransfer();
- } else {
- new_request.reset(request_context->CreateRequest(request_data.url, NULL));
- request = new_request.get();
+ request->set_method(request_data.method);
+ request->set_first_party_for_cookies(request_data.first_party_for_cookies);
+ SetReferrerForRequest(request, referrer);
- request->set_method(request_data.method);
- request->set_first_party_for_cookies(request_data.first_party_for_cookies);
- SetReferrerForRequest(request, referrer);
+ net::HttpRequestHeaders headers;
+ headers.AddHeadersFromString(request_data.headers);
+ request->SetExtraRequestHeaders(headers);
- net::HttpRequestHeaders headers;
- headers.AddHeadersFromString(request_data.headers);
- request->SetExtraRequestHeaders(headers);
- }
-
- // TODO(darin): Do we really need all of these URLRequest setters in the
- // transferred navigation case?
-
- request->set_load_flags(load_flags);
- request->SetPriority(request_data.priority);
+ request->SetLoadFlags(load_flags);
// Resolve elements from request_body and prepare upload data.
if (request_data.request_body.get()) {
@@ -1009,18 +1105,21 @@ void ResourceDispatcherHostImpl::BeginRequest(
route_id,
request_data.origin_pid,
request_id,
+ request_data.render_frame_id,
request_data.is_main_frame,
request_data.frame_id,
request_data.parent_is_main_frame,
request_data.parent_frame_id,
request_data.resource_type,
request_data.transition_type,
+ request_data.should_replace_current_entry,
false, // is download
false, // is stream
allow_download,
request_data.has_user_gesture,
request_data.referrer_policy,
resource_context,
+ filter_->GetWeakPtr(),
!is_sync_load);
extra_info->AssociateWithRequest(request); // Request takes ownership.
@@ -1038,34 +1137,49 @@ void ResourceDispatcherHostImpl::BeginRequest(
request, filter_->appcache_service(), child_id,
request_data.appcache_host_id, request_data.resource_type);
+ scoped_ptr<ResourceHandler> handler(
+ CreateResourceHandler(
+ request,
+ request_data, sync_result, route_id, process_type, child_id,
+ resource_context));
+
+ BeginRequestInternal(new_request.Pass(), handler.Pass());
+}
+
+scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler(
+ net::URLRequest* request,
+ const ResourceHostMsg_Request& request_data,
+ IPC::Message* sync_result,
+ int route_id,
+ int process_type,
+ int child_id,
+ ResourceContext* resource_context) {
// Construct the IPC resource handler.
scoped_ptr<ResourceHandler> handler;
if (sync_result) {
- handler.reset(new SyncResourceHandler(
- filter_, resource_context, request, sync_result, this));
+ handler.reset(new SyncResourceHandler(request, sync_result, this));
} else {
- handler.reset(new AsyncResourceHandler(
- filter_, resource_context, request, this));
+ handler.reset(new AsyncResourceHandler(request, this));
+ if (IsDetachableResourceType(request_data.resource_type)) {
+ handler.reset(new DetachableResourceHandler(
+ request,
+ base::TimeDelta::FromMilliseconds(kDefaultDetachableCancelDelayMs),
+ handler.Pass()));
+ }
}
// The RedirectToFileResourceHandler depends on being next in the chain.
if (request_data.download_to_file) {
handler.reset(
- new RedirectToFileResourceHandler(handler.Pass(), child_id, this));
+ new RedirectToFileResourceHandler(handler.Pass(), request, this));
}
- // Install a CrossSiteResourceHandler if this request is coming from a
- // RenderViewHost with a pending cross-site request. We only check this for
- // MAIN_FRAME requests. Unblock requests only come from a blocked page, do
- // not count as cross-site, otherwise it gets blocked indefinitely.
- if (request_data.resource_type == ResourceType::MAIN_FRAME &&
- process_type == PROCESS_TYPE_RENDERER &&
- CrossSiteRequestManager::GetInstance()->
- HasPendingCrossSiteRequest(child_id, route_id)) {
- // Wrap the event handler to be sure the current page's onunload handler
- // has a chance to run before we render the new page.
- handler.reset(new CrossSiteResourceHandler(handler.Pass(), child_id,
- route_id, request));
+ // Install a CrossSiteResourceHandler for all main frame requests. This will
+ // let us check whether a transfer is required and pause for the unload
+ // handler either if so or if a cross-process navigation is already under way.
+ if (request_data.resource_type == ResourceType::MAIN_FRAME &&
+ process_type == PROCESS_TYPE_RENDERER) {
+ handler.reset(new CrossSiteResourceHandler(handler.Pass(), request));
}
// Insert a buffered event handler before the actual one.
@@ -1074,16 +1188,12 @@ void ResourceDispatcherHostImpl::BeginRequest(
ScopedVector<ResourceThrottle> throttles;
if (delegate_) {
- bool is_continuation_of_transferred_request =
- (deferred_loader.get() != NULL);
-
delegate_->RequestBeginning(request,
resource_context,
filter_->appcache_service(),
request_data.resource_type,
child_id,
route_id,
- is_continuation_of_transferred_request,
&throttles);
}
@@ -1092,26 +1202,13 @@ void ResourceDispatcherHostImpl::BeginRequest(
throttles.push_back(new PowerSaveBlockResourceThrottle());
}
- if (request_data.resource_type == ResourceType::MAIN_FRAME) {
- throttles.insert(
- throttles.begin(),
- new TransferNavigationResourceThrottle(request));
- }
-
throttles.push_back(
scheduler_->ScheduleRequest(child_id, route_id, request).release());
handler.reset(
- new ThrottlingResourceHandler(handler.Pass(), child_id, request_id,
- throttles.Pass()));
+ new ThrottlingResourceHandler(handler.Pass(), request, throttles.Pass()));
- if (deferred_loader.get()) {
- pending_loaders_[extra_info->GetGlobalRequestID()] = deferred_loader;
- IncrementOutstandingRequestsMemory(1, *extra_info);
- deferred_loader->CompleteTransfer(handler.Pass());
- } else {
- BeginRequestInternal(new_request.Pass(), handler.Pass());
- }
+ return handler.Pass();
}
void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) {
@@ -1180,18 +1277,21 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
route_id,
0,
request_id_,
+ MSG_ROUTING_NONE, // render_frame_id
false, // is_main_frame
-1, // frame_id
false, // parent_is_main_frame
-1, // parent_frame_id
ResourceType::SUB_RESOURCE,
PAGE_TRANSITION_LINK,
+ false, // should_replace_current_entry
download, // is_download
- false, // is_stream
+ false, // is_stream
download, // allow_download
false, // has_user_gesture
- WebKit::WebReferrerPolicyDefault,
+ blink::WebReferrerPolicyDefault,
context,
+ base::WeakPtr<ResourceMessageFilter>(), // filter
true); // is_async
}
@@ -1243,13 +1343,13 @@ void ResourceDispatcherHostImpl::BeginSaveFile(
}
scoped_ptr<net::URLRequest> request(
- request_context->CreateRequest(url, NULL));
+ request_context->CreateRequest(url, net::DEFAULT_PRIORITY, NULL));
request->set_method("GET");
SetReferrerForRequest(request.get(), referrer);
// So far, for saving page, we need fetch content from cache, in the
// future, maybe we can use a configuration to configure this behavior.
- request->set_load_flags(net::LOAD_PREFERRING_CACHE);
+ request->SetLoadFlags(net::LOAD_PREFERRING_CACHE);
// No need to get offline load flags for save files, but make sure
// we have an OfflinePolicy to receive request completions.
@@ -1282,8 +1382,8 @@ void ResourceDispatcherHostImpl::ResumeDeferredNavigation(
}
// The object died, so cancel and detach all requests associated with it except
-// for downloads, which belong to the browser process even if initiated via a
-// renderer.
+// for downloads and detachable resources, which belong to the browser process
+// even if initiated via a renderer.
void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) {
CancelRequestsForRoute(child_id, -1 /* cancel all */);
registered_temp_files_.erase(child_id);
@@ -1297,6 +1397,7 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
// iterators found in the first loop.
// Find the global ID of all matching elements.
+ bool any_requests_transferring = false;
std::vector<GlobalRequestID> matching_requests;
for (LoaderMap::const_iterator i = pending_loaders_.begin();
i != pending_loaders_.end(); ++i) {
@@ -1307,12 +1408,14 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
GlobalRequestID id(child_id, i->first.request_id);
DCHECK(id == i->first);
-
- // Don't cancel navigations that are transferring to another process,
- // since they belong to another process now.
- if (!info->is_download() && !info->is_stream() &&
- !IsTransferredNavigation(id) &&
- (route_id == -1 || route_id == info->GetRouteID())) {
+ // Don't cancel navigations that are expected to live beyond this process.
+ if (IsTransferredNavigation(id))
+ any_requests_transferring = true;
+ if (info->detachable_handler()) {
+ info->detachable_handler()->Detach();
+ } else if (!info->IsDownload() && !info->is_stream() &&
+ !IsTransferredNavigation(id) &&
+ (route_id == -1 || route_id == info->GetRouteID())) {
matching_requests.push_back(id);
}
}
@@ -1333,6 +1436,14 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
RemovePendingLoader(iter);
}
+ // Don't clear the blocked loaders or offline policy maps if any of the
+ // requests in route_id are being transferred to a new process, since those
+ // maps will be updated with the new route_id after the transfer. Otherwise
+ // we will lose track of this info when the old route goes away, before the
+ // new one is created.
+ if (any_requests_transferring)
+ return;
+
// Now deal with blocked requests if any.
if (route_id != -1) {
if (blocked_loaders_map_.find(GlobalRoutingID(child_id, route_id)) !=
@@ -1525,7 +1636,7 @@ void ResourceDispatcherHostImpl::BeginRequestInternal(
if ((TimeTicks::Now() - last_user_gesture_time_) <
TimeDelta::FromMilliseconds(kUserGestureWindowMs)) {
- request->set_load_flags(
+ request->SetLoadFlags(
request->load_flags() | net::LOAD_MAYBE_USER_GESTURE);
}
@@ -1540,8 +1651,10 @@ void ResourceDispatcherHostImpl::BeginRequestInternal(
// status -- it has no effect beyond this, since the request hasn't started.
request->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
- if (!handler->OnResponseCompleted(info->GetRequestID(), request->status(),
- std::string())) {
+ bool defer = false;
+ handler->OnResponseCompleted(info->GetRequestID(), request->status(),
+ std::string(), &defer);
+ if (defer) {
// TODO(darin): The handler is not ready for us to kill the request. Oops!
NOTREACHED();
}
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index e6f2241d9a0..2e0253ae519 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -27,7 +27,6 @@
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/loader/global_routing_id.h"
#include "content/browser/loader/offline_policy.h"
-#include "content/browser/loader/render_view_host_tracker.h"
#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_loader_delegate.h"
#include "content/browser/loader/resource_scheduler.h"
@@ -239,6 +238,10 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
TestBlockedRequestsProcessDies);
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
CalculateApproximateMemoryCost);
+ FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
+ DetachableResourceTimesOut);
+ FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
+ TestProcessCancelDetachableTimesOut);
class ShutdownTask;
@@ -356,10 +359,31 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void OnSyncLoad(int request_id,
const ResourceHostMsg_Request& request_data,
IPC::Message* sync_result);
+
+ // Update the ResourceRequestInfo and internal maps when a request is
+ // transferred from one process to another.
+ void UpdateRequestForTransfer(int child_id,
+ int route_id,
+ int request_id,
+ const ResourceHostMsg_Request& request_data,
+ const linked_ptr<ResourceLoader>& loader);
+
void BeginRequest(int request_id,
const ResourceHostMsg_Request& request_data,
IPC::Message* sync_result, // only valid for sync
int route_id); // only valid for async
+
+ // Creates a ResourceHandler to be used by BeginRequest() for normal resource
+ // loading.
+ scoped_ptr<ResourceHandler> CreateResourceHandler(
+ net::URLRequest* request,
+ const ResourceHostMsg_Request& request_data,
+ IPC::Message* sync_result,
+ int route_id,
+ int process_type,
+ int child_id,
+ ResourceContext* resource_context);
+
void OnDataDownloadedACK(int request_id);
void OnUploadProgressACK(int request_id);
void OnCancelRequest(int request_id);
@@ -494,8 +518,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
scoped_ptr<ResourceScheduler> scheduler_;
- RenderViewHostTracker tracker_; // Lives on UI thread.
-
typedef std::map<GlobalRoutingID, OfflinePolicy*> OfflineMap;
OfflineMap offline_policy_map_;
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index 89b17c44c73..52d34328847 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -9,12 +9,16 @@
#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop.h"
#include "base/pickle.h"
+#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/loader/detachable_resource_handler.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/worker_host/worker_service_impl.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/resource_messages.h"
@@ -22,12 +26,14 @@
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
+#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/common/process_type.h"
#include "content/public/common/resource_response.h"
#include "content/public/test/test_browser_context.h"
#include "content/test/test_content_browser_client.h"
#include "net/base/net_errors.h"
+#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/http/http_util.h"
@@ -36,6 +42,7 @@
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_simple_job.h"
#include "net/url_request/url_request_test_job.h"
+#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/common/appcache/appcache_interfaces.h"
@@ -95,7 +102,7 @@ static ResourceHostMsg_Request CreateResourceRequest(
request.method = std::string(method);
request.url = url;
request.first_party_for_cookies = url; // bypass third-party cookie blocking
- request.referrer_policy = WebKit::WebReferrerPolicyDefault;
+ request.referrer_policy = blink::WebReferrerPolicyDefault;
request.load_flags = 0;
request.origin_pid = 0;
request.resource_type = type;
@@ -174,7 +181,7 @@ class ForwardingFilter : public ResourceMessageFilter {
base::Unretained(this))),
dest_(dest),
resource_context_(resource_context) {
- OnChannelConnected(base::GetCurrentProcId());
+ set_peer_pid_for_testing(base::GetCurrentProcId());
}
// ResourceMessageFilter override
@@ -434,6 +441,10 @@ class GenericResourceThrottle : public ResourceThrottle {
}
}
+ virtual const char* GetNameForLogging() const OVERRIDE {
+ return "GenericResourceThrottle";
+ }
+
void Resume() {
ASSERT_TRUE(this == active_throttle_);
active_throttle_ = NULL;
@@ -489,7 +500,6 @@ class TestResourceDispatcherHostDelegate
ResourceType::Type resource_type,
int child_id,
int route_id,
- bool is_continuation_of_transferred_request,
ScopedVector<ResourceThrottle>* throttles) OVERRIDE {
if (user_data_) {
const void* key = user_data_.get();
@@ -521,13 +531,14 @@ class ResourceDispatcherHostTest : public testing::Test,
cache_thread_(BrowserThread::CACHE, &message_loop_),
io_thread_(BrowserThread::IO, &message_loop_),
old_factory_(NULL),
- resource_type_(ResourceType::SUB_RESOURCE),
send_data_received_acks_(false) {
browser_context_.reset(new TestBrowserContext());
BrowserContext::EnsureResourceContextInitialized(browser_context_.get());
message_loop_.RunUntilIdle();
- filter_ = new ForwardingFilter(
- this, browser_context_->GetResourceContext());
+ ResourceContext* resource_context = browser_context_->GetResourceContext();
+ filter_ = new ForwardingFilter(this, resource_context);
+ resource_context->GetRequestContext()->set_network_delegate(
+ &network_delegate_);
}
virtual ~ResourceDispatcherHostTest() {
@@ -592,23 +603,25 @@ class ResourceDispatcherHostTest : public testing::Test,
message_loop_.RunUntilIdle();
}
- // Creates a request using the current test object as the filter.
+ // Creates a request using the current test object as the filter and
+ // SubResource as the resource type.
void MakeTestRequest(int render_view_id,
int request_id,
const GURL& url);
- // Generates a request using the given filter. This will probably be a
- // ForwardingFilter.
- void MakeTestRequest(ResourceMessageFilter* filter,
- int render_view_id,
- int request_id,
- const GURL& url);
+ // Generates a request using the given filter and resource type.
+ void MakeTestRequestWithResourceType(ResourceMessageFilter* filter,
+ int render_view_id, int request_id,
+ const GURL& url,
+ ResourceType::Type type);
void CancelRequest(int request_id);
void CompleteStartRequest(int request_id);
void CompleteStartRequest(ResourceMessageFilter* filter, int request_id);
+ net::TestNetworkDelegate* network_delegate() { return &network_delegate_; }
+
void EnsureSchemeIsAllowed(const std::string& scheme) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -632,11 +645,6 @@ class ResourceDispatcherHostTest : public testing::Test,
SetResponse(headers, std::string());
}
- // Sets a particular resource type for any request from now on.
- void SetResourceType(ResourceType::Type type) {
- resource_type_ = type;
- }
-
void SendDataReceivedACKs(bool send_acks) {
send_data_received_acks_ = send_acks;
}
@@ -716,13 +724,13 @@ class ResourceDispatcherHostTest : public testing::Test,
BrowserThreadImpl io_thread_;
scoped_ptr<TestBrowserContext> browser_context_;
scoped_refptr<ForwardingFilter> filter_;
+ net::TestNetworkDelegate network_delegate_;
ResourceDispatcherHostImpl host_;
ResourceIPCAccumulator accum_;
std::string response_headers_;
std::string response_data_;
std::string scheme_;
net::URLRequest::ProtocolFactory* old_factory_;
- ResourceType::Type resource_type_;
bool send_data_received_acks_;
std::set<int> child_ids_;
static ResourceDispatcherHostTest* test_fixture_;
@@ -739,19 +747,21 @@ int ResourceDispatcherHostTest::url_request_jobs_created_count_ = 0;
void ResourceDispatcherHostTest::MakeTestRequest(int render_view_id,
int request_id,
const GURL& url) {
- MakeTestRequest(filter_.get(), render_view_id, request_id, url);
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
+ url, ResourceType::SUB_RESOURCE);
}
-void ResourceDispatcherHostTest::MakeTestRequest(
+void ResourceDispatcherHostTest::MakeTestRequestWithResourceType(
ResourceMessageFilter* filter,
int render_view_id,
int request_id,
- const GURL& url) {
+ const GURL& url,
+ ResourceType::Type type) {
// If it's already there, this'll be dropped on the floor, which is fine.
child_ids_.insert(filter->child_id());
ResourceHostMsg_Request request =
- CreateResourceRequest("GET", resource_type_, url);
+ CreateResourceRequest("GET", type, url);
ResourceHostMsg_RequestResource msg(render_view_id, request_id, request);
bool msg_was_ok;
host_.OnMessageReceived(msg, filter, &msg_was_ok);
@@ -776,16 +786,47 @@ void ResourceDispatcherHostTest::CompleteStartRequest(
URLRequestTestDelayedStartJob::CompleteStart(req);
}
-void CheckSuccessfulRequest(const std::vector<IPC::Message>& messages,
- const std::string& reference_data) {
+void CheckRequestCompleteErrorCode(const IPC::Message& message,
+ int expected_error_code) {
+ // Verify the expected error code was received.
+ int request_id;
+ int error_code;
+
+ ASSERT_EQ(ResourceMsg_RequestComplete::ID, message.type());
+
+ PickleIterator iter(message);
+ ASSERT_TRUE(IPC::ReadParam(&message, &iter, &request_id));
+ ASSERT_TRUE(IPC::ReadParam(&message, &iter, &error_code));
+ ASSERT_EQ(expected_error_code, error_code);
+}
+
+testing::AssertionResult ExtractDataOffsetAndLength(const IPC::Message& message,
+ int* data_offset,
+ int* data_length) {
+ PickleIterator iter(message);
+ int request_id;
+ if (!IPC::ReadParam(&message, &iter, &request_id))
+ return testing::AssertionFailure() << "Could not read request_id";
+ if (!IPC::ReadParam(&message, &iter, data_offset))
+ return testing::AssertionFailure() << "Could not read data_offset";
+ if (!IPC::ReadParam(&message, &iter, data_length))
+ return testing::AssertionFailure() << "Could not read data_length";
+ return testing::AssertionSuccess();
+}
+
+void CheckSuccessfulRequestWithErrorCode(
+ const std::vector<IPC::Message>& messages,
+ const std::string& reference_data,
+ int expected_error) {
// A successful request will have received 4 messages:
// ReceivedResponse (indicates headers received)
// SetDataBuffer (contains shared memory handle)
// DataReceived (data offset and length into shared memory)
// RequestComplete (request is done)
//
- // This function verifies that we received 4 messages and that they
- // are appropriate.
+ // This function verifies that we received 4 messages and that they are
+ // appropriate. It allows for an error code other than net::OK if the request
+ // should successfully receive data and then abort, e.g., on cancel.
ASSERT_EQ(4U, messages.size());
// The first messages should be received response
@@ -805,12 +846,10 @@ void CheckSuccessfulRequest(const std::vector<IPC::Message>& messages,
// should probably test multiple chunks later
ASSERT_EQ(ResourceMsg_DataReceived::ID, messages[2].type());
- PickleIterator iter2(messages[2]);
- ASSERT_TRUE(IPC::ReadParam(&messages[2], &iter2, &request_id));
int data_offset;
- ASSERT_TRUE(IPC::ReadParam(&messages[2], &iter2, &data_offset));
int data_length;
- ASSERT_TRUE(IPC::ReadParam(&messages[2], &iter2, &data_length));
+ ASSERT_TRUE(
+ ExtractDataOffsetAndLength(messages[2], &data_offset, &data_length));
ASSERT_EQ(reference_data.size(), static_cast<size_t>(data_length));
ASSERT_GE(shm_size, data_length);
@@ -821,7 +860,22 @@ void CheckSuccessfulRequest(const std::vector<IPC::Message>& messages,
ASSERT_EQ(0, memcmp(reference_data.c_str(), data, data_length));
// The last message should be all data received.
- ASSERT_EQ(ResourceMsg_RequestComplete::ID, messages[3].type());
+ CheckRequestCompleteErrorCode(messages[3], expected_error);
+}
+
+void CheckSuccessfulRequest(const std::vector<IPC::Message>& messages,
+ const std::string& reference_data) {
+ CheckSuccessfulRequestWithErrorCode(messages, reference_data, net::OK);
+}
+
+void CheckSuccessfulRedirect(const std::vector<IPC::Message>& messages,
+ const std::string& reference_data) {
+ ASSERT_EQ(5U, messages.size());
+ ASSERT_EQ(ResourceMsg_ReceivedRedirect::ID, messages[0].type());
+
+ const std::vector<IPC::Message> second_req_msgs =
+ std::vector<IPC::Message>(messages.begin() + 1, messages.end());
+ CheckSuccessfulRequest(second_req_msgs, reference_data);
}
void CheckFailedRequest(const std::vector<IPC::Message>& messages,
@@ -834,15 +888,8 @@ void CheckFailedRequest(const std::vector<IPC::Message>& messages,
if (messages.size() == 2) {
EXPECT_EQ(ResourceMsg_ReceivedResponse::ID, messages[0].type());
}
- EXPECT_EQ(ResourceMsg_RequestComplete::ID, messages[failure_index].type());
-
- int request_id;
- int error_code;
- PickleIterator iter(messages[failure_index]);
- EXPECT_TRUE(IPC::ReadParam(&messages[failure_index], &iter, &request_id));
- EXPECT_TRUE(IPC::ReadParam(&messages[failure_index], &iter, &error_code));
- EXPECT_EQ(expected_error, error_code);
+ CheckRequestCompleteErrorCode(messages[failure_index], expected_error);
}
// Tests whether many messages get dispatched properly.
@@ -850,6 +897,16 @@ TEST_F(ResourceDispatcherHostTest, TestMany) {
MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
+ MakeTestRequestWithResourceType(filter_.get(), 0, 4,
+ net::URLRequestTestJob::test_url_4(),
+ ResourceType::PREFETCH); // detachable type
+ MakeTestRequest(0, 5, net::URLRequestTestJob::test_url_redirect_to_url_2());
+
+ // Finish the redirection
+ ResourceHostMsg_FollowRedirect redirect_msg(5, false, GURL());
+ bool msg_was_ok;
+ host_.OnMessageReceived(redirect_msg, filter_.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
// flush all the pending requests
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -858,52 +915,214 @@ TEST_F(ResourceDispatcherHostTest, TestMany) {
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
- // there are three requests, so we should have gotten them classified as such
- ASSERT_EQ(3U, msgs.size());
+ // there are five requests, so we should have gotten them classified as such
+ ASSERT_EQ(5U, msgs.size());
CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_2());
CheckSuccessfulRequest(msgs[2], net::URLRequestTestJob::test_data_3());
+ CheckSuccessfulRequest(msgs[3], net::URLRequestTestJob::test_data_4());
+ CheckSuccessfulRedirect(msgs[4], net::URLRequestTestJob::test_data_2());
}
-void CheckCancelledRequestCompleteMessage(const IPC::Message& message) {
- ASSERT_EQ(ResourceMsg_RequestComplete::ID, message.type());
-
- int request_id;
- int error_code;
-
- PickleIterator iter(message);
- ASSERT_TRUE(IPC::ReadParam(&message, &iter, &request_id));
- ASSERT_TRUE(IPC::ReadParam(&message, &iter, &error_code));
-
- EXPECT_EQ(net::ERR_ABORTED, error_code);
-}
-
-// Tests whether messages get canceled properly. We issue three requests,
-// cancel one of them, and make sure that each sent the proper notifications.
+// Tests whether messages get canceled properly. We issue four requests,
+// cancel two of them, and make sure that each sent the proper notifications.
TEST_F(ResourceDispatcherHostTest, Cancel) {
MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
+
+ MakeTestRequestWithResourceType(filter_.get(), 0, 4,
+ net::URLRequestTestJob::test_url_4(),
+ ResourceType::PREFETCH); // detachable type
+
CancelRequest(2);
+ // Cancel request must come from the renderer for a detachable resource to
+ // delay.
+ host_.CancelRequest(filter_->child_id(), 4, true);
+
+ // The handler should have been detached now.
+ GlobalRequestID global_request_id(filter_->child_id(), 4);
+ ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
+ host_.GetURLRequest(global_request_id));
+ ASSERT_TRUE(info->detachable_handler()->is_detached());
+
// flush all the pending requests
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
base::MessageLoop::current()->RunUntilIdle();
+ // Everything should be out now.
+ EXPECT_EQ(0, host_.pending_requests());
+
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
- // there are three requests, so we should have gotten them classified as such
- ASSERT_EQ(3U, msgs.size());
+ // there are four requests, so we should have gotten them classified as such
+ ASSERT_EQ(4U, msgs.size());
CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
CheckSuccessfulRequest(msgs[2], net::URLRequestTestJob::test_data_3());
- // Check that request 2 got canceled.
+ // Check that request 2 and 4 got canceled, as far as the renderer is
+ // concerned.
ASSERT_EQ(2U, msgs[1].size());
ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[1][0].type());
- CheckCancelledRequestCompleteMessage(msgs[1][1]);
+ CheckRequestCompleteErrorCode(msgs[1][1], net::ERR_ABORTED);
+
+ ASSERT_EQ(2U, msgs[3].size());
+ ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[3][0].type());
+ CheckRequestCompleteErrorCode(msgs[1][1], net::ERR_ABORTED);
+
+ // However, request 4 should have actually gone to completion. (Only request 2
+ // was canceled.)
+ EXPECT_EQ(4, network_delegate()->completed_requests());
+ EXPECT_EQ(1, network_delegate()->canceled_requests());
+ EXPECT_EQ(0, network_delegate()->error_count());
+}
+
+// Shows that detachable requests will timeout if the request takes too long to
+// complete.
+TEST_F(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
+ MakeTestRequestWithResourceType(filter_.get(), 0, 1,
+ net::URLRequestTestJob::test_url_2(),
+ ResourceType::PREFETCH); // detachable type
+ GlobalRequestID global_request_id(filter_->child_id(), 1);
+ ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
+ host_.GetURLRequest(global_request_id));
+ ASSERT_TRUE(info->detachable_handler());
+ info->detachable_handler()->set_cancel_delay(
+ base::TimeDelta::FromMilliseconds(200));
+ base::MessageLoop::current()->RunUntilIdle();
+ host_.CancelRequest(filter_->child_id(), 1, true);
+
+ // From the renderer's perspective, the request was cancelled.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+ ASSERT_EQ(1U, msgs.size());
+ ASSERT_EQ(2U, msgs[0].size());
+ ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type());
+ CheckRequestCompleteErrorCode(msgs[0][1], net::ERR_ABORTED);
+
+ // But it continues detached.
+ EXPECT_EQ(1, host_.pending_requests());
+ EXPECT_TRUE(info->detachable_handler()->is_detached());
+
+ // Wait until after the delay timer times out before we start processing any
+ // messages.
+ base::OneShotTimer<base::MessageLoop> timer;
+ timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(210),
+ base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle);
+ base::MessageLoop::current()->Run();
+
+ // The prefetch should be cancelled by now.
+ EXPECT_EQ(0, host_.pending_requests());
+ EXPECT_EQ(1, network_delegate()->completed_requests());
+ EXPECT_EQ(1, network_delegate()->canceled_requests());
+ EXPECT_EQ(0, network_delegate()->error_count());
+}
+
+// If the filter has disappeared then detachable resources should continue to
+// load.
+TEST_F(ResourceDispatcherHostTest, DeletedFilterDetached) {
+ // test_url_1's data is available synchronously, so use 2 and 3.
+ ResourceHostMsg_Request request_prefetch = CreateResourceRequest(
+ "GET", ResourceType::PREFETCH, net::URLRequestTestJob::test_url_2());
+ ResourceHostMsg_Request request_ping = CreateResourceRequest(
+ "GET", ResourceType::PING, net::URLRequestTestJob::test_url_3());
+
+ bool msg_was_ok;
+ ResourceHostMsg_RequestResource msg_prefetch(0, 1, request_prefetch);
+ host_.OnMessageReceived(msg_prefetch, filter_, &msg_was_ok);
+ ResourceHostMsg_RequestResource msg_ping(0, 2, request_ping);
+ host_.OnMessageReceived(msg_ping, filter_, &msg_was_ok);
+
+ // Remove the filter before processing the requests by simulating channel
+ // closure.
+ ResourceRequestInfoImpl* info_prefetch = ResourceRequestInfoImpl::ForRequest(
+ host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
+ ResourceRequestInfoImpl* info_ping = ResourceRequestInfoImpl::ForRequest(
+ host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 2)));
+ DCHECK_EQ(filter_.get(), info_prefetch->filter());
+ DCHECK_EQ(filter_.get(), info_ping->filter());
+ filter_->OnChannelClosing();
+ info_prefetch->filter_.reset();
+ info_ping->filter_.reset();
+
+ // From the renderer's perspective, the requests were cancelled.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+ ASSERT_EQ(2U, msgs.size());
+ CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ABORTED);
+ CheckRequestCompleteErrorCode(msgs[1][0], net::ERR_ABORTED);
+
+ // But it continues detached.
+ EXPECT_EQ(2, host_.pending_requests());
+ EXPECT_TRUE(info_prefetch->detachable_handler()->is_detached());
+ EXPECT_TRUE(info_ping->detachable_handler()->is_detached());
+
+ KickOffRequest();
+
+ // Make sure the requests weren't canceled early.
+ EXPECT_EQ(2, host_.pending_requests());
+
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(0, host_.pending_requests());
+ EXPECT_EQ(2, network_delegate()->completed_requests());
+ EXPECT_EQ(0, network_delegate()->canceled_requests());
+ EXPECT_EQ(0, network_delegate()->error_count());
+}
+
+// If the filter has disappeared (original process dies) then detachable
+// resources should continue to load, even when redirected.
+TEST_F(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
+ ResourceHostMsg_Request request = CreateResourceRequest(
+ "GET", ResourceType::PREFETCH,
+ net::URLRequestTestJob::test_url_redirect_to_url_2());
+
+ ResourceHostMsg_RequestResource msg(0, 1, request);
+ bool msg_was_ok;
+ host_.OnMessageReceived(msg, filter_, &msg_was_ok);
+
+ // Remove the filter before processing the request by simulating channel
+ // closure.
+ GlobalRequestID global_request_id(filter_->child_id(), 1);
+ ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
+ host_.GetURLRequest(global_request_id));
+ info->filter_->OnChannelClosing();
+ info->filter_.reset();
+
+ // From the renderer's perspective, the request was cancelled.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+ ASSERT_EQ(1U, msgs.size());
+ CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ABORTED);
+
+ // But it continues detached.
+ EXPECT_EQ(1, host_.pending_requests());
+ EXPECT_TRUE(info->detachable_handler()->is_detached());
+
+ // Verify no redirects before resetting the filter.
+ net::URLRequest* url_request = host_.GetURLRequest(global_request_id);
+ EXPECT_EQ(1u, url_request->url_chain().size());
+ KickOffRequest();
+
+ // Verify that a redirect was followed.
+ EXPECT_EQ(2u, url_request->url_chain().size());
+
+ // Make sure the request wasn't canceled early.
+ EXPECT_EQ(1, host_.pending_requests());
+
+ // Finish up the request.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_EQ(0, host_.pending_requests());
+ EXPECT_EQ(1, network_delegate()->completed_requests());
+ EXPECT_EQ(0, network_delegate()->canceled_requests());
+ EXPECT_EQ(0, network_delegate()->error_count());
}
TEST_F(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
@@ -923,11 +1142,49 @@ TEST_F(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
// calling CancelRequest.
EXPECT_FALSE(was_deleted);
- // flush all the pending requests
+ base::MessageLoop::current()->RunUntilIdle();
+
+ EXPECT_TRUE(was_deleted);
+}
+
+TEST_F(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
+ bool was_deleted = false;
+
+ // Arrange to have requests deferred before starting.
+ TestResourceDispatcherHostDelegate delegate;
+ delegate.set_flags(DEFER_STARTING_REQUEST);
+ delegate.set_url_request_user_data(new TestUserData(&was_deleted));
+ host_.SetDelegate(&delegate);
+
+ MakeTestRequestWithResourceType(filter_.get(), 0, 1,
+ net::URLRequestTestJob::test_url_1(),
+ ResourceType::PREFETCH); // detachable type
+ // Cancel request must come from the renderer for a detachable resource to
+ // detach.
+ host_.CancelRequest(filter_->child_id(), 1, true);
+
+ // Even after driving the event loop, the request has not been deleted.
+ EXPECT_FALSE(was_deleted);
+
+ // However, it is still throttled because the defer happened above the
+ // DetachableResourceHandler.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_FALSE(was_deleted);
+
+ // Resume the request.
+ GenericResourceThrottle* throttle =
+ GenericResourceThrottle::active_throttle();
+ ASSERT_TRUE(throttle);
+ throttle->Resume();
+ // Now, the request completes.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+ base::MessageLoop::current()->RunUntilIdle();
EXPECT_TRUE(was_deleted);
+ EXPECT_EQ(1, network_delegate()->completed_requests());
+ EXPECT_EQ(0, network_delegate()->canceled_requests());
+ EXPECT_EQ(0, network_delegate()->error_count());
}
// Tests if cancel is called in ResourceThrottle::WillStartRequest, then the
@@ -948,7 +1205,7 @@ TEST_F(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) {
// Check that request got canceled.
ASSERT_EQ(1U, msgs[0].size());
- CheckCancelledRequestCompleteMessage(msgs[0][0]);
+ CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ABORTED);
// Make sure URLRequest is never started.
EXPECT_EQ(0, url_request_jobs_created_count_);
@@ -1028,16 +1285,8 @@ TEST_F(ResourceDispatcherHostTest, CancelInDelegate) {
// Check the cancellation
ASSERT_EQ(1U, msgs.size());
ASSERT_EQ(1U, msgs[0].size());
- ASSERT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][0].type());
- int request_id;
- int error_code;
-
- PickleIterator iter(msgs[0][0]);
- ASSERT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &request_id));
- ASSERT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &error_code));
-
- EXPECT_EQ(net::ERR_ACCESS_DENIED, error_code);
+ CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ACCESS_DENIED);
}
// The host delegate acts as a second one so we can have some requests
@@ -1075,15 +1324,23 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
ResourceHostMsg_Request request = CreateResourceRequest(
"GET", ResourceType::SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
- MakeTestRequest(test_filter.get(), 0, 1,
- net::URLRequestTestJob::test_url_1());
+ MakeTestRequestWithResourceType(test_filter.get(), 0, 1,
+ net::URLRequestTestJob::test_url_1(),
+ ResourceType::SUB_RESOURCE);
// request 2 goes to us
MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
// request 3 goes to the test delegate
- MakeTestRequest(test_filter.get(), 0, 3,
- net::URLRequestTestJob::test_url_3());
+ MakeTestRequestWithResourceType(test_filter.get(), 0, 3,
+ net::URLRequestTestJob::test_url_3(),
+ ResourceType::SUB_RESOURCE);
+
+ // request 4 goes to us
+ MakeTestRequestWithResourceType(filter_.get(), 0, 4,
+ net::URLRequestTestJob::test_url_4(),
+ ResourceType::PREFETCH); // detachable type
+
// Make sure all requests have finished stage one. test_url_1 will have
// finished.
@@ -1095,7 +1352,9 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
// breaks the whole test.
//EXPECT_EQ(3, host_.pending_requests());
- // Process each request for one level so one callback is called.
+ // Process test_url_2 and test_url_3 for one level so one callback is called.
+ // We'll cancel test_url_4 (detachable) before processing it to verify that it
+ // delays the cancel.
for (int i = 0; i < 2; i++)
EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
@@ -1103,6 +1362,13 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
host_.CancelRequestsForProcess(filter_->child_id());
test_filter->has_canceled_ = true;
+ // The requests should all be cancelled, except request 4, which is detached.
+ EXPECT_EQ(1, host_.pending_requests());
+ GlobalRequestID global_request_id(filter_->child_id(), 4);
+ ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
+ host_.GetURLRequest(global_request_id));
+ ASSERT_TRUE(info->detachable_handler()->is_detached());
+
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1111,11 +1377,65 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
// The test delegate should not have gotten any messages after being canceled.
ASSERT_EQ(0, test_filter->received_after_canceled_);
- // We should have gotten exactly one result.
+ // There should be two results.
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
- ASSERT_EQ(1U, msgs.size());
+ ASSERT_EQ(2U, msgs.size());
CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2());
+ // The detachable request was cancelled by the renderer before it
+ // finished. From the perspective of the renderer, it should have cancelled.
+ ASSERT_EQ(2U, msgs[1].size());
+ ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[1][0].type());
+ CheckRequestCompleteErrorCode(msgs[1][1], net::ERR_ABORTED);
+ // But it completed anyway. For the network stack, no requests were canceled.
+ EXPECT_EQ(4, network_delegate()->completed_requests());
+ EXPECT_EQ(0, network_delegate()->canceled_requests());
+ EXPECT_EQ(0, network_delegate()->error_count());
+}
+
+TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
+ MakeTestRequestWithResourceType(filter_.get(), 0, 1,
+ net::URLRequestTestJob::test_url_4(),
+ ResourceType::PREFETCH); // detachable type
+ GlobalRequestID global_request_id(filter_->child_id(), 1);
+ ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
+ host_.GetURLRequest(global_request_id));
+ ASSERT_TRUE(info->detachable_handler());
+ info->detachable_handler()->set_cancel_delay(
+ base::TimeDelta::FromMilliseconds(200));
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Cancel the requests to the test process.
+ host_.CancelRequestsForProcess(filter_->child_id());
+ EXPECT_EQ(1, host_.pending_requests());
+
+ // Wait until after the delay timer times out before we start processing any
+ // messages.
+ base::OneShotTimer<base::MessageLoop> timer;
+ timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(210),
+ base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle);
+ base::MessageLoop::current()->Run();
+
+ // The prefetch should be cancelled by now.
+ EXPECT_EQ(0, host_.pending_requests());
+
+ // In case any messages are still to be processed.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+ base::MessageLoop::current()->RunUntilIdle();
+
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+
+ ASSERT_EQ(1U, msgs.size());
+
+ // The request should have cancelled.
+ ASSERT_EQ(2U, msgs[0].size());
+ ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type());
+ CheckRequestCompleteErrorCode(msgs[0][1], net::ERR_ABORTED);
+ // And not run to completion.
+ EXPECT_EQ(1, network_delegate()->completed_requests());
+ EXPECT_EQ(1, network_delegate()->canceled_requests());
+ EXPECT_EQ(0, network_delegate()->error_count());
}
// Tests blocking and resuming requests.
@@ -1184,6 +1504,10 @@ TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
+ // Blocked detachable resources should not delay cancellation.
+ MakeTestRequestWithResourceType(filter_.get(), 1, 5,
+ net::URLRequestTestJob::test_url_4(),
+ ResourceType::PREFETCH); // detachable type
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1216,12 +1540,21 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
host_.BlockRequestsForRoute(second_filter->child_id(), 0);
- MakeTestRequest(filter_.get(), 0, 1, net::URLRequestTestJob::test_url_1());
- MakeTestRequest(second_filter.get(), 0, 2,
- net::URLRequestTestJob::test_url_2());
- MakeTestRequest(filter_.get(), 0, 3, net::URLRequestTestJob::test_url_3());
- MakeTestRequest(second_filter.get(), 0, 4,
- net::URLRequestTestJob::test_url_1());
+ MakeTestRequestWithResourceType(filter_.get(), 0, 1,
+ net::URLRequestTestJob::test_url_1(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(second_filter.get(), 0, 2,
+ net::URLRequestTestJob::test_url_2(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(filter_.get(), 0, 3,
+ net::URLRequestTestJob::test_url_3(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(second_filter.get(), 0, 4,
+ net::URLRequestTestJob::test_url_1(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(second_filter.get(), 0, 5,
+ net::URLRequestTestJob::test_url_4(),
+ ResourceType::PREFETCH); // detachable type
// Simulate process death.
host_.CancelRequestsForProcess(second_filter->child_id());
@@ -1233,7 +1566,8 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
- // The 2 requests for the RVH 0 should have been processed.
+ // The 2 requests for the RVH 0 should have been processed. Note that
+ // blocked detachable requests are canceled without delay.
ASSERT_EQ(2U, msgs.size());
CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
@@ -1255,13 +1589,30 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
host_.BlockRequestsForRoute(filter_->child_id(), 2);
host_.BlockRequestsForRoute(second_filter->child_id(), 1);
- MakeTestRequest(filter_.get(), 0, 1, net::URLRequestTestJob::test_url_1());
- MakeTestRequest(filter_.get(), 1, 2, net::URLRequestTestJob::test_url_2());
- MakeTestRequest(filter_.get(), 0, 3, net::URLRequestTestJob::test_url_3());
- MakeTestRequest(second_filter.get(), 1, 4,
- net::URLRequestTestJob::test_url_1());
- MakeTestRequest(filter_.get(), 2, 5, net::URLRequestTestJob::test_url_2());
- MakeTestRequest(filter_.get(), 2, 6, net::URLRequestTestJob::test_url_3());
+ MakeTestRequestWithResourceType(filter_.get(), 0, 1,
+ net::URLRequestTestJob::test_url_1(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(filter_.get(), 1, 2,
+ net::URLRequestTestJob::test_url_2(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(filter_.get(), 0, 3,
+ net::URLRequestTestJob::test_url_3(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(second_filter.get(), 1, 4,
+ net::URLRequestTestJob::test_url_1(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(filter_.get(), 2, 5,
+ net::URLRequestTestJob::test_url_2(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(filter_.get(), 2, 6,
+ net::URLRequestTestJob::test_url_3(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(filter_.get(), 0, 7,
+ net::URLRequestTestJob::test_url_4(),
+ ResourceType::PREFETCH); // detachable type
+ MakeTestRequestWithResourceType(second_filter.get(), 1, 8,
+ net::URLRequestTestJob::test_url_4(),
+ ResourceType::PREFETCH); // detachable type
host_.CancelRequestsForProcess(filter_->child_id());
host_.CancelRequestsForProcess(second_filter->child_id());
@@ -1273,7 +1624,8 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
// Test the private helper method "CalculateApproximateMemoryCost()".
TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
net::URLRequestContext context;
- net::URLRequest req(GURL("http://www.google.com"), NULL, &context);
+ net::URLRequest req(
+ GURL("http://www.google.com"), net::DEFAULT_PRIORITY, NULL, &context);
EXPECT_EQ(4427,
ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req));
@@ -1320,22 +1672,27 @@ TEST_F(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
// Saturate the number of outstanding requests for our process.
for (size_t i = 0; i < kMaxRequests; ++i) {
- MakeTestRequest(filter_.get(), 0, i + 1,
- net::URLRequestTestJob::test_url_2());
+ MakeTestRequestWithResourceType(filter_.get(), 0, i + 1,
+ net::URLRequestTestJob::test_url_2(),
+ ResourceType::SUB_RESOURCE);
}
// Issue two more requests for our process -- these should fail immediately.
- MakeTestRequest(filter_.get(), 0, kMaxRequests + 1,
- net::URLRequestTestJob::test_url_2());
- MakeTestRequest(filter_.get(), 0, kMaxRequests + 2,
- net::URLRequestTestJob::test_url_2());
+ MakeTestRequestWithResourceType(filter_.get(), 0, kMaxRequests + 1,
+ net::URLRequestTestJob::test_url_2(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(filter_.get(), 0, kMaxRequests + 2,
+ net::URLRequestTestJob::test_url_2(),
+ ResourceType::SUB_RESOURCE);
// Issue two requests for the second process -- these should succeed since
// it is just process 0 that is saturated.
- MakeTestRequest(second_filter.get(), 0, kMaxRequests + 3,
- net::URLRequestTestJob::test_url_2());
- MakeTestRequest(second_filter.get(), 0, kMaxRequests + 4,
- net::URLRequestTestJob::test_url_2());
+ MakeTestRequestWithResourceType(second_filter.get(), 0, kMaxRequests + 3,
+ net::URLRequestTestJob::test_url_2(),
+ ResourceType::SUB_RESOURCE);
+ MakeTestRequestWithResourceType(second_filter.get(), 0, kMaxRequests + 4,
+ net::URLRequestTestJob::test_url_2(),
+ ResourceType::SUB_RESOURCE);
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1386,23 +1743,27 @@ TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
// Saturate the number of outstanding requests for our process.
for (size_t i = 0; i < kMaxRequestsPerProcess; ++i) {
- MakeTestRequest(filter_.get(), 0, i + 1,
- net::URLRequestTestJob::test_url_2());
+ MakeTestRequestWithResourceType(filter_.get(), 0, i + 1,
+ net::URLRequestTestJob::test_url_2(),
+ ResourceType::SUB_RESOURCE);
}
// Issue another request for our process -- this should fail immediately.
- MakeTestRequest(filter_.get(), 0, kMaxRequestsPerProcess + 1,
- net::URLRequestTestJob::test_url_2());
+ MakeTestRequestWithResourceType(filter_.get(), 0, kMaxRequestsPerProcess + 1,
+ net::URLRequestTestJob::test_url_2(),
+ ResourceType::SUB_RESOURCE);
// Issue a request for the second process -- this should succeed, because it
// is just process 0 that is saturated.
- MakeTestRequest(second_filter.get(), 0, kMaxRequestsPerProcess + 2,
- net::URLRequestTestJob::test_url_2());
+ MakeTestRequestWithResourceType(
+ second_filter.get(), 0, kMaxRequestsPerProcess + 2,
+ net::URLRequestTestJob::test_url_2(), ResourceType::SUB_RESOURCE);
// Issue a request for the third process -- this should fail, because the
// global limit has been reached.
- MakeTestRequest(third_filter.get(), 0, kMaxRequestsPerProcess + 3,
- net::URLRequestTestJob::test_url_2());
+ MakeTestRequestWithResourceType(
+ third_filter.get(), 0, kMaxRequestsPerProcess + 3,
+ net::URLRequestTestJob::test_url_2(), ResourceType::SUB_RESOURCE);
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1542,11 +1903,11 @@ TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
std::string response_data("<html><title>Test One</title></html>");
SetResponse(raw_headers, response_data);
- // Only MAIN_FRAMEs can trigger a download.
- SetResourceType(ResourceType::MAIN_FRAME);
-
HandleScheme("http");
- MakeTestRequest(0, 1, GURL("http:bla"));
+
+ // Only MAIN_FRAMEs can trigger a download.
+ MakeTestRequestWithResourceType(filter_.get(), 0, 1, GURL("http:bla"),
+ ResourceType::MAIN_FRAME);
// Flush all pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1561,15 +1922,7 @@ TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
// The RequestComplete message should have had the error code of
// ERR_FILE_NOT_FOUND.
- int request_id;
- int error_code;
-
- PickleIterator iter(msgs[0][0]);
- EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &request_id));
- EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &error_code));
-
- EXPECT_EQ(1, request_id);
- EXPECT_EQ(net::ERR_FILE_NOT_FOUND, error_code);
+ CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_FILE_NOT_FOUND);
}
// Test for http://crbug.com/76202 . We don't want to destroy a
@@ -1593,11 +1946,12 @@ TEST_F(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
response_data.resize(1025, ' ');
SetResponse(raw_headers, response_data);
- SetResourceType(ResourceType::MAIN_FRAME);
SetDelayedCompleteJobGeneration(true);
HandleScheme("http");
- MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
+ GURL("http://example.com/blah"),
+ ResourceType::MAIN_FRAME);
// Return some data so that the request is identified as a download
// and the proper resource handlers are created.
EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
@@ -1628,11 +1982,12 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContext) {
response_data.resize(1025, ' ');
SetResponse(raw_headers, response_data);
- SetResourceType(ResourceType::MAIN_FRAME);
SetDelayedCompleteJobGeneration(true);
HandleScheme("http");
- MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
+ GURL("http://example.com/blah"),
+ ResourceType::MAIN_FRAME);
// Return some data so that the request is identified as a download
// and the proper resource handlers are created.
EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
@@ -1656,6 +2011,33 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContext) {
EXPECT_EQ(0, host_.pending_requests());
}
+TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextDetached) {
+ EXPECT_EQ(0, host_.pending_requests());
+
+ int render_view_id = 0;
+ int request_id = 1;
+
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
+ net::URLRequestTestJob::test_url_4(),
+ ResourceType::PREFETCH); // detachable type
+
+ // Simulate a cancel coming from the renderer.
+ host_.CancelRequest(filter_->child_id(), request_id, true);
+
+ // Since the request had already started processing as detachable,
+ // the cancellation above should have been ignored and the request
+ // should have been detached.
+ EXPECT_EQ(1, host_.pending_requests());
+
+ // Cancelling by other methods should also leave it detached.
+ host_.CancelRequestsForProcess(render_view_id);
+ EXPECT_EQ(1, host_.pending_requests());
+
+ // Cancelling by context should work.
+ host_.CancelRequestsForContext(filter_->resource_context());
+ EXPECT_EQ(0, host_.pending_requests());
+}
+
// Test the cancelling of requests that are being transferred to a new renderer
// due to a redirection.
TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
@@ -1669,10 +2051,12 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
std::string response_data("<html>foobar</html>");
SetResponse(raw_headers, response_data);
- SetResourceType(ResourceType::MAIN_FRAME);
HandleScheme("http");
- MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
+ GURL("http://example.com/blah"),
+ ResourceType::MAIN_FRAME);
+
GlobalRequestID global_request_id(filter_->child_id(), request_id);
host_.MarkAsTransferredNavigation(global_request_id,
@@ -1697,7 +2081,9 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
EXPECT_EQ(0, host_.pending_requests());
}
-TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
+// Test transferred navigations with text/html, which doesn't trigger any
+// content sniffing.
+TEST_F(ResourceDispatcherHostTest, TransferNavigationHtml) {
EXPECT_EQ(0, host_.pending_requests());
int render_view_id = 0;
@@ -1707,7 +2093,6 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
SetResponse("HTTP/1.1 302 Found\n"
"Location: http://other.com/blech\n\n");
- SetResourceType(ResourceType::MAIN_FRAME);
HandleScheme("http");
// Temporarily replace ContentBrowserClient with one that will trigger the
@@ -1715,9 +2100,26 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
TransfersAllNavigationsContentBrowserClient new_client;
ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
- MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
+ GURL("http://example.com/blah"),
+ ResourceType::MAIN_FRAME);
- // Restore.
+ // Now that we're blocked on the redirect, update the response and unblock by
+ // telling the AsyncResourceHandler to follow the redirect.
+ const std::string kResponseBody = "hello world";
+ SetResponse("HTTP/1.1 200 OK\n"
+ "Content-Type: text/html\n\n",
+ kResponseBody);
+ ResourceHostMsg_FollowRedirect redirect_msg(request_id, false, GURL());
+ bool msg_was_ok;
+ host_.OnMessageReceived(redirect_msg, filter_.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Flush all the pending requests to get the response through the
+ // BufferedResourceHandler.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+
+ // Restore, now that we've set up a transfer.
SetBrowserClientForTesting(old_client);
// This second filter is used to emulate a second process.
@@ -1727,10 +2129,79 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
int new_render_view_id = 1;
int new_request_id = 2;
+ ResourceHostMsg_Request request =
+ CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
+ GURL("http://other.com/blech"));
+ request.transferred_request_child_id = filter_->child_id();
+ request.transferred_request_request_id = request_id;
+
+ // For cleanup.
+ child_ids_.insert(second_filter->child_id());
+ ResourceHostMsg_RequestResource transfer_request_msg(
+ new_render_view_id, new_request_id, request);
+ host_.OnMessageReceived(
+ transfer_request_msg, second_filter.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Check generated messages.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+
+ ASSERT_EQ(2U, msgs.size());
+ EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
+ CheckSuccessfulRequest(msgs[1], kResponseBody);
+}
+
+// Test transferred navigations with text/plain, which causes
+// BufferedResourceHandler to buffer the response to sniff the content
+// before the transfer occurs.
+TEST_F(ResourceDispatcherHostTest, TransferNavigationText) {
+ EXPECT_EQ(0, host_.pending_requests());
+
+ int render_view_id = 0;
+ int request_id = 1;
+
+ // Configure initial request.
+ SetResponse("HTTP/1.1 302 Found\n"
+ "Location: http://other.com/blech\n\n");
+
+ HandleScheme("http");
+
+ // Temporarily replace ContentBrowserClient with one that will trigger the
+ // transfer navigation code paths.
+ TransfersAllNavigationsContentBrowserClient new_client;
+ ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
+
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
+ GURL("http://example.com/blah"),
+ ResourceType::MAIN_FRAME);
+
+ // Now that we're blocked on the redirect, update the response and unblock by
+ // telling the AsyncResourceHandler to follow the redirect. Use a text/plain
+ // MIME type, which causes BufferedResourceHandler to buffer it before the
+ // transfer occurs.
const std::string kResponseBody = "hello world";
SetResponse("HTTP/1.1 200 OK\n"
"Content-Type: text/plain\n\n",
kResponseBody);
+ ResourceHostMsg_FollowRedirect redirect_msg(request_id, false, GURL());
+ bool msg_was_ok;
+ host_.OnMessageReceived(redirect_msg, filter_.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Flush all the pending requests to get the response through the
+ // BufferedResourceHandler.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+
+ // Restore, now that we've set up a transfer.
+ SetBrowserClientForTesting(old_client);
+
+ // This second filter is used to emulate a second process.
+ scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter(
+ this, browser_context_->GetResourceContext());
+
+ int new_render_view_id = 1;
+ int new_request_id = 2;
ResourceHostMsg_Request request =
CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
@@ -1742,33 +2213,31 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigation) {
child_ids_.insert(second_filter->child_id());
ResourceHostMsg_RequestResource transfer_request_msg(
new_render_view_id, new_request_id, request);
- bool msg_was_ok;
host_.OnMessageReceived(
transfer_request_msg, second_filter.get(), &msg_was_ok);
base::MessageLoop::current()->RunUntilIdle();
- // Flush all the pending requests.
- while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
-
// Check generated messages.
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
- ASSERT_EQ(1U, msgs.size());
- CheckSuccessfulRequest(msgs[0], kResponseBody);
+ ASSERT_EQ(2U, msgs.size());
+ EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
+ CheckSuccessfulRequest(msgs[1], kResponseBody);
}
-TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
+TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
EXPECT_EQ(0, host_.pending_requests());
int render_view_id = 0;
int request_id = 1;
+ int first_child_id = -1;
// Configure initial request.
SetResponse("HTTP/1.1 302 Found\n"
"Location: http://other.com/blech\n\n");
+ const std::string kResponseBody = "hello world";
- SetResourceType(ResourceType::MAIN_FRAME);
HandleScheme("http");
// Temporarily replace ContentBrowserClient with one that will trigger the
@@ -1776,11 +2245,46 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
TransfersAllNavigationsContentBrowserClient new_client;
ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
- MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
+ // Create a first filter that can be deleted before the second one starts.
+ {
+ scoped_refptr<ForwardingFilter> first_filter = new ForwardingFilter(
+ this, browser_context_->GetResourceContext());
+ first_child_id = first_filter->child_id();
+
+ ResourceHostMsg_Request first_request =
+ CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
+ GURL("http://example.com/blah"));
+
+ // For cleanup.
+ child_ids_.insert(first_child_id);
+ ResourceHostMsg_RequestResource first_request_msg(
+ render_view_id, request_id, first_request);
+ bool msg_was_ok;
+ host_.OnMessageReceived(
+ first_request_msg, first_filter.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Now that we're blocked on the redirect, update the response and unblock
+ // by telling the AsyncResourceHandler to follow the redirect.
+ SetResponse("HTTP/1.1 200 OK\n"
+ "Content-Type: text/html\n\n",
+ kResponseBody);
+ ResourceHostMsg_FollowRedirect redirect_msg(request_id, false, GURL());
+ host_.OnMessageReceived(redirect_msg, first_filter.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Flush all the pending requests to get the response through the
+ // BufferedResourceHandler.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+ }
+ // The first filter is now deleted, as if the child process died.
// Restore.
SetBrowserClientForTesting(old_client);
+ // Make sure we don't hold onto the ResourceMessageFilter after it is deleted.
+ GlobalRequestID first_global_request_id(first_child_id, request_id);
+
// This second filter is used to emulate a second process.
scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter(
this, browser_context_->GetResourceContext());
@@ -1788,17 +2292,10 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
int new_render_view_id = 1;
int new_request_id = 2;
- // Delay the start of the next request so that we can setup the response for
- // the next URL.
- SetDelayedStartJobGeneration(true);
-
- SetResponse("HTTP/1.1 302 Found\n"
- "Location: http://other.com/blerg\n\n");
-
ResourceHostMsg_Request request =
CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
GURL("http://other.com/blech"));
- request.transferred_request_child_id = filter_->child_id();
+ request.transferred_request_child_id = first_child_id;
request.transferred_request_request_id = request_id;
// For cleanup.
@@ -1810,48 +2307,111 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationAndThenRedirect) {
transfer_request_msg, second_filter.get(), &msg_was_ok);
base::MessageLoop::current()->RunUntilIdle();
- // Response data for "http://other.com/blerg":
+ // Check generated messages.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+
+ ASSERT_EQ(2U, msgs.size());
+ EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
+ CheckSuccessfulRequest(msgs[1], kResponseBody);
+}
+
+TEST_F(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
+ EXPECT_EQ(0, host_.pending_requests());
+
+ int render_view_id = 0;
+ int request_id = 1;
+
+ // Configure initial request.
+ SetResponse("HTTP/1.1 302 Found\n"
+ "Location: http://other.com/blech\n\n");
+
+ HandleScheme("http");
+
+ // Temporarily replace ContentBrowserClient with one that will trigger the
+ // transfer navigation code paths.
+ TransfersAllNavigationsContentBrowserClient new_client;
+ ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
+
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
+ GURL("http://example.com/blah"),
+ ResourceType::MAIN_FRAME);
+
+ // Now that we're blocked on the redirect, simulate hitting another redirect.
+ SetResponse("HTTP/1.1 302 Found\n"
+ "Location: http://other.com/blerg\n\n");
+ ResourceHostMsg_FollowRedirect redirect_msg(request_id, false, GURL());
+ bool msg_was_ok;
+ host_.OnMessageReceived(redirect_msg, filter_.get(), &msg_was_ok);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Now that we're blocked on the second redirect, update the response and
+ // unblock by telling the AsyncResourceHandler to follow the redirect.
+ // Again, use text/plain to force BufferedResourceHandler to buffer before
+ // the transfer.
const std::string kResponseBody = "hello world";
SetResponse("HTTP/1.1 200 OK\n"
"Content-Type: text/plain\n\n",
kResponseBody);
-
- // OK, let the redirect happen.
- SetDelayedStartJobGeneration(false);
- CompleteStartRequest(second_filter.get(), new_request_id);
+ ResourceHostMsg_FollowRedirect redirect_msg2(request_id, false, GURL());
+ host_.OnMessageReceived(redirect_msg2, filter_.get(), &msg_was_ok);
base::MessageLoop::current()->RunUntilIdle();
- // Flush all the pending requests.
+ // Flush all the pending requests to get the response through the
+ // BufferedResourceHandler.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- // Now, simulate the renderer choosing to follow the redirect.
- ResourceHostMsg_FollowRedirect redirect_msg(
- new_request_id, false, GURL());
- host_.OnMessageReceived(redirect_msg, second_filter.get(), &msg_was_ok);
- base::MessageLoop::current()->RunUntilIdle();
+ // Restore.
+ SetBrowserClientForTesting(old_client);
- // Flush all the pending requests.
- while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+ // This second filter is used to emulate a second process.
+ scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter(
+ this, browser_context_->GetResourceContext());
+
+ int new_render_view_id = 1;
+ int new_request_id = 2;
+
+ ResourceHostMsg_Request request =
+ CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
+ GURL("http://other.com/blech"));
+ request.transferred_request_child_id = filter_->child_id();
+ request.transferred_request_request_id = request_id;
+
+ // For cleanup.
+ child_ids_.insert(second_filter->child_id());
+ ResourceHostMsg_RequestResource transfer_request_msg(
+ new_render_view_id, new_request_id, request);
+ host_.OnMessageReceived(
+ transfer_request_msg, second_filter.get(), &msg_was_ok);
+
+ // Verify that we update the ResourceRequestInfo.
+ GlobalRequestID global_request_id(second_filter->child_id(), new_request_id);
+ const ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
+ host_.GetURLRequest(global_request_id));
+ EXPECT_EQ(second_filter->child_id(), info->GetChildID());
+ EXPECT_EQ(new_render_view_id, info->GetRouteID());
+ EXPECT_EQ(new_request_id, info->GetRequestID());
+ EXPECT_EQ(second_filter, info->filter());
+
+ // Let request complete.
+ base::MessageLoop::current()->RunUntilIdle();
// Check generated messages.
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
- ASSERT_EQ(1U, msgs.size());
-
- // We should have received a redirect followed by a "normal" payload.
+ ASSERT_EQ(2U, msgs.size());
EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
- msgs[0].erase(msgs[0].begin());
- CheckSuccessfulRequest(msgs[0], kResponseBody);
+ CheckSuccessfulRequest(msgs[1], kResponseBody);
}
TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
EXPECT_EQ(0, host_.pending_requests());
- SetResourceType(ResourceType::MAIN_FRAME);
HandleScheme("http");
- MakeTestRequest(0, 1, GURL("foo://bar"));
+ MakeTestRequestWithResourceType(filter_.get(), 0, 1, GURL("foo://bar"),
+ ResourceType::MAIN_FRAME);
// Flush all pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1866,15 +2426,7 @@ TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
// The RequestComplete message should have the error code of
// ERR_UNKNOWN_URL_SCHEME.
- int request_id;
- int error_code;
-
- PickleIterator iter(msgs[0][0]);
- EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &request_id));
- EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &error_code));
-
- EXPECT_EQ(1, request_id);
- EXPECT_EQ(net::ERR_UNKNOWN_URL_SCHEME, error_code);
+ CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_UNKNOWN_URL_SCHEME);
}
TEST_F(ResourceDispatcherHostTest, DataReceivedACKs) {
@@ -1898,6 +2450,65 @@ TEST_F(ResourceDispatcherHostTest, DataReceivedACKs) {
EXPECT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][size - 1].type());
}
+// Request a very large detachable resource and cancel part way. Some of the
+// data should have been sent to the renderer, but not all.
+TEST_F(ResourceDispatcherHostTest, DataSentBeforeDetach) {
+ EXPECT_EQ(0, host_.pending_requests());
+
+ int render_view_id = 0;
+ int request_id = 1;
+
+ std::string raw_headers("HTTP\n"
+ "Content-type: image/jpeg\n\n");
+ std::string response_data("01234567890123456789\x01foobar");
+
+ // Create a response larger than kMaxAllocationSize (currently 32K). Note
+ // that if this increase beyond 512K we'll need to make the response longer.
+ const int kAllocSize = 1024*512;
+ response_data.resize(kAllocSize, ' ');
+
+ SetResponse(raw_headers, response_data);
+ SetDelayedCompleteJobGeneration(true);
+ HandleScheme("http");
+
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
+ GURL("http://example.com/blah"),
+ ResourceType::PREFETCH);
+
+ // Get a bit of data before cancelling.
+ EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
+
+ // Simulate a cancellation coming from the renderer.
+ ResourceHostMsg_CancelRequest msg(request_id);
+ bool msg_was_ok;
+ host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok);
+
+ EXPECT_EQ(1, host_.pending_requests());
+
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+
+ // Sort all the messages we saw by request.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+
+ EXPECT_EQ(4U, msgs[0].size());
+
+ // Figure out how many bytes were received by the renderer.
+ int data_offset;
+ int data_length;
+ ASSERT_TRUE(
+ ExtractDataOffsetAndLength(msgs[0][2], &data_offset, &data_length));
+ EXPECT_LT(0, data_length);
+ EXPECT_GT(kAllocSize, data_length);
+
+ // Verify the data that was received before cancellation. The request should
+ // have appeared to cancel, however.
+ CheckSuccessfulRequestWithErrorCode(
+ msgs[0],
+ std::string(response_data.begin(), response_data.begin() + data_length),
+ net::ERR_ABORTED);
+}
+
TEST_F(ResourceDispatcherHostTest, DelayedDataReceivedACKs) {
EXPECT_EQ(0, host_.pending_requests());
diff --git a/chromium/content/browser/loader/resource_handler.cc b/chromium/content/browser/loader/resource_handler.cc
index 2a5d85ee253..358dd65a90a 100644
--- a/chromium/content/browser/loader/resource_handler.cc
+++ b/chromium/content/browser/loader/resource_handler.cc
@@ -4,10 +4,29 @@
#include "content/browser/loader/resource_handler.h"
+#include "content/browser/loader/resource_request_info_impl.h"
+
namespace content {
+ResourceHandler::ResourceHandler(net::URLRequest* request)
+ : controller_(NULL),
+ request_(request) {
+}
+
void ResourceHandler::SetController(ResourceController* controller) {
controller_ = controller;
}
+ResourceRequestInfoImpl* ResourceHandler::GetRequestInfo() const {
+ return ResourceRequestInfoImpl::ForRequest(request_);
+}
+
+int ResourceHandler::GetRequestID() const {
+ return GetRequestInfo()->GetRequestID();
+}
+
+ResourceMessageFilter* ResourceHandler::GetFilter() const {
+ return GetRequestInfo()->filter();
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_handler.h b/chromium/content/browser/loader/resource_handler.h
index de8bd9dc1cf..af8aebdb855 100644
--- a/chromium/content/browser/loader/resource_handler.h
+++ b/chromium/content/browser/loader/resource_handler.h
@@ -14,6 +14,7 @@
#include <string>
+#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner_helpers.h"
#include "base/threading/non_thread_safe.h"
#include "content/common/content_export.h"
@@ -22,11 +23,14 @@ class GURL;
namespace net {
class IOBuffer;
+class URLRequest;
class URLRequestStatus;
} // namespace net
namespace content {
class ResourceController;
+class ResourceMessageFilter;
+class ResourceRequestInfoImpl;
struct ResourceResponse;
// The resource dispatcher host uses this interface to process network events
@@ -77,7 +81,7 @@ class CONTENT_EXPORT ResourceHandler
// If the handler returns false, then the request is cancelled. Otherwise,
// once data is available, OnReadCompleted will be called.
virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) = 0;
@@ -88,12 +92,13 @@ class CONTENT_EXPORT ResourceHandler
virtual bool OnReadCompleted(int request_id, int bytes_read,
bool* defer) = 0;
- // The response is complete. The final response status is given. Returns
- // false if the handler is deferring the call to a later time. Otherwise,
- // the request will be destroyed upon return.
- virtual bool OnResponseCompleted(int request_id,
+ // The response is complete. The final response status is given. Set
+ // |*defer| to true to defer destruction to a later time. Otherwise, the
+ // request will be destroyed upon return.
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) = 0;
+ const std::string& security_info,
+ bool* defer) = 0;
// This notification is synthesized by the RedirectToFileResourceHandler
// to indicate progress of 'download_to_file' requests. OnReadCompleted
@@ -102,11 +107,19 @@ class CONTENT_EXPORT ResourceHandler
virtual void OnDataDownloaded(int request_id, int bytes_downloaded) = 0;
protected:
- ResourceHandler() : controller_(NULL) {}
- ResourceController* controller() { return controller_; }
+ ResourceHandler(net::URLRequest* request);
+
+ ResourceController* controller() const { return controller_; }
+ net::URLRequest* request() const { return request_; }
+
+ // Convenience functions.
+ ResourceRequestInfoImpl* GetRequestInfo() const;
+ int GetRequestID() const;
+ ResourceMessageFilter* GetFilter() const;
private:
ResourceController* controller_;
+ net::URLRequest* request_;
};
} // namespace content
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index 5b0a9f4a284..bdc9644b1dd 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -9,24 +9,26 @@
#include "base/metrics/histogram.h"
#include "base/time/time.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/loader/doomed_resource_handler.h"
+#include "content/browser/loader/cross_site_resource_handler.h"
+#include "content/browser/loader/detachable_resource_handler.h"
#include "content/browser/loader/resource_loader_delegate.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/ssl/ssl_client_auth_handler.h"
#include "content/browser/ssl/ssl_manager.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/browser/site_instance.h"
+#include "content/public/browser/signed_certificate_timestamp_store.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
#include "content/public/common/resource_response.h"
-#include "content/public/common/url_constants.h"
+#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h"
#include "net/ssl/client_cert_store.h"
-#include "net/ssl/client_cert_store_impl.h"
+#include "net/url_request/url_request_status.h"
#include "webkit/browser/appcache/appcache_interceptor.h"
using base::TimeDelta;
@@ -66,12 +68,16 @@ void PopulateResourceResponse(net::URLRequest* request,
ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request,
scoped_ptr<ResourceHandler> handler,
ResourceLoaderDelegate* delegate)
- : weak_ptr_factory_(this) {
- scoped_ptr<net::ClientCertStore> client_cert_store;
-#if !defined(USE_OPENSSL)
- client_cert_store.reset(new net::ClientCertStoreImpl());
-#endif
- Init(request.Pass(), handler.Pass(), delegate, client_cert_store.Pass());
+ : deferred_stage_(DEFERRED_NONE),
+ request_(request.Pass()),
+ handler_(handler.Pass()),
+ delegate_(delegate),
+ last_upload_position_(0),
+ waiting_for_upload_progress_ack_(false),
+ is_transferring_(false),
+ weak_ptr_factory_(this) {
+ request_->set_delegate(this);
+ handler_->SetController(this);
}
ResourceLoader::~ResourceLoader() {
@@ -163,30 +169,13 @@ void ResourceLoader::MarkAsTransferring(const GURL& target_url) {
// When transferring a request to another process, the renderer doesn't get
// a chance to update the cookie policy URL. Do it here instead.
request()->set_first_party_for_cookies(target_url);
-
- // When an URLRequest is transferred to a new RenderViewHost, its
- // ResourceHandler should not receive any notifications because it may depend
- // on the state of the old RVH. We set a ResourceHandler that only allows
- // canceling requests, because on shutdown of the RDH all pending requests
- // are canceled. The RVH of requests that are being transferred may be gone
- // by that time. In CompleteTransfer, the ResoureHandlers are substituted
- // again.
- handler_.reset(new DoomedResourceHandler(handler_.Pass()));
-}
-
-void ResourceLoader::WillCompleteTransfer() {
- handler_.reset();
}
-void ResourceLoader::CompleteTransfer(scoped_ptr<ResourceHandler> new_handler) {
- DCHECK_EQ(DEFERRED_REDIRECT, deferred_stage_);
- DCHECK(!handler_.get());
+void ResourceLoader::CompleteTransfer() {
+ DCHECK_EQ(DEFERRED_READ, deferred_stage_);
- handler_ = new_handler.Pass();
- handler_->SetController(this);
is_transferring_ = false;
-
- Resume();
+ GetRequestInfo()->cross_site_handler()->ResumeResponse();
}
ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
@@ -205,32 +194,6 @@ void ResourceLoader::OnUploadProgressACK() {
waiting_for_upload_progress_ack_ = false;
}
-ResourceLoader::ResourceLoader(
- scoped_ptr<net::URLRequest> request,
- scoped_ptr<ResourceHandler> handler,
- ResourceLoaderDelegate* delegate,
- scoped_ptr<net::ClientCertStore> client_cert_store)
- : weak_ptr_factory_(this) {
- Init(request.Pass(), handler.Pass(), delegate, client_cert_store.Pass());
-}
-
-void ResourceLoader::Init(scoped_ptr<net::URLRequest> request,
- scoped_ptr<ResourceHandler> handler,
- ResourceLoaderDelegate* delegate,
- scoped_ptr<net::ClientCertStore> client_cert_store) {
- deferred_stage_ = DEFERRED_NONE;
- request_ = request.Pass();
- handler_ = handler.Pass();
- delegate_ = delegate;
- last_upload_position_ = 0;
- waiting_for_upload_progress_ack_ = false;
- is_transferring_ = false;
- client_cert_store_ = client_cert_store.Pass();
-
- request_->set_delegate(this);
- handler_->SetController(this);
-}
-
void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
const GURL& new_url,
bool* defer) {
@@ -305,19 +268,12 @@ void ResourceLoader::OnCertificateRequested(
return;
}
-#if !defined(USE_OPENSSL)
- client_cert_store_->GetClientCerts(*cert_info, &cert_info->client_certs);
- if (cert_info->client_certs.empty()) {
- // No need to query the user if there are no certs to choose from.
- request_->ContinueWithCertificate(NULL);
- return;
- }
-#endif
-
DCHECK(!ssl_client_auth_handler_.get())
<< "OnCertificateRequested called with ssl_client_auth_handler pending";
- ssl_client_auth_handler_ = new SSLClientAuthHandler(request_.get(),
- cert_info);
+ ssl_client_auth_handler_ = new SSLClientAuthHandler(
+ GetRequestInfo()->GetContext()->CreateClientCertStore(),
+ request_.get(),
+ cert_info);
ssl_client_auth_handler_->SelectCertificate();
}
@@ -482,9 +438,16 @@ void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
// WebKit will send us a cancel for downloads since it no longer handles
// them. In this case, ignore the cancel since we handle downloads in the
// browser.
- if (from_renderer && (info->is_download() || info->is_stream()))
+ if (from_renderer && (info->IsDownload() || info->is_stream()))
return;
+ if (from_renderer && info->detachable_handler()) {
+ // TODO(davidben): Fix Blink handling of prefetches so they are not
+ // cancelled on navigate away and end up in the local cache.
+ info->detachable_handler()->Detach();
+ return;
+ }
+
// TODO(darin): Perhaps we should really be looking to see if the status is
// IO_PENDING?
bool was_pending = request_->is_pending();
@@ -511,48 +474,43 @@ void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
}
}
+void ResourceLoader::StoreSignedCertificateTimestamps(
+ const net::SignedCertificateTimestampAndStatusList& sct_list,
+ int process_id,
+ SignedCertificateTimestampIDStatusList* sct_ids) {
+ SignedCertificateTimestampStore* sct_store(
+ SignedCertificateTimestampStore::GetInstance());
+
+ for (net::SignedCertificateTimestampAndStatusList::const_iterator iter =
+ sct_list.begin(); iter != sct_list.end(); ++iter) {
+ const int sct_id(sct_store->Store(iter->sct_, process_id));
+ sct_ids->push_back(
+ SignedCertificateTimestampIDAndStatus(sct_id, iter->status_));
+ }
+}
+
void ResourceLoader::CompleteResponseStarted() {
ResourceRequestInfoImpl* info = GetRequestInfo();
scoped_refptr<ResourceResponse> response(new ResourceResponse());
PopulateResourceResponse(request_.get(), response.get());
- // The --site-per-process flag enables an out-of-process iframes
- // prototype. It works by changing the MIME type of cross-site subframe
- // responses to a Chrome specific one. This new type causes the subframe
- // to be replaced by a <webview> tag with the same URL, which results in
- // using a renderer in a different process.
- //
- // For prototyping purposes, we will use a small hack to ensure same site
- // iframes are not changed. We can compare the URL for the subframe
- // request with the referrer. If the two don't match, then it should be a
- // cross-site iframe.
- // Also, we don't do the MIME type change for chrome:// URLs, as those
- // require different privileges and are not allowed in regular renderers.
- //
- // The usage of SiteInstance::IsSameWebSite is safe on the IO thread,
- // if the browser_context parameter is NULL. This does not work for hosted
- // apps, but should be fine for prototyping.
- // TODO(nasko): Once the SiteInstance check is fixed, ensure we do the
- // right thing here. http://crbug.com/160576
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kSitePerProcess) &&
- GetRequestInfo()->GetResourceType() == ResourceType::SUB_FRAME &&
- response->head.mime_type == "text/html" &&
- !request_->url().SchemeIs(chrome::kChromeUIScheme) &&
- !SiteInstance::IsSameWebSite(NULL, request_->url(),
- GURL(request_->referrer()))) {
- response->head.mime_type = "application/browser-plugin";
- }
-
if (request_->ssl_info().cert.get()) {
int cert_id = CertStore::GetInstance()->StoreCert(
request_->ssl_info().cert.get(), info->GetChildID());
+
+ SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
+ StoreSignedCertificateTimestamps(
+ request_->ssl_info().signed_certificate_timestamps,
+ info->GetChildID(),
+ &signed_certificate_timestamp_ids);
+
response->head.security_info = SerializeSecurityInfo(
cert_id,
request_->ssl_info().cert_status,
request_->ssl_info().security_bits,
- request_->ssl_info().connection_status);
+ request_->ssl_info().connection_status,
+ signed_certificate_timestamp_ids);
} else {
// We should not have any SSL state.
DCHECK(!request_->ssl_info().cert_status &&
@@ -613,7 +571,10 @@ void ResourceLoader::ReadMore(int* bytes_read) {
ResourceRequestInfoImpl* info = GetRequestInfo();
DCHECK(!is_deferred());
- net::IOBuffer* buf;
+ // Make sure we track the buffer in at least one place. This ensures it gets
+ // deleted even in the case the request has already finished its job and
+ // doesn't use the buffer.
+ scoped_refptr<net::IOBuffer> buf;
int buf_size;
if (!handler_->OnWillRead(info->GetRequestID(), &buf, &buf_size, -1)) {
Cancel();
@@ -623,7 +584,7 @@ void ResourceLoader::ReadMore(int* bytes_read) {
DCHECK(buf);
DCHECK(buf_size > 0);
- request_->Read(buf, buf_size, bytes_read);
+ request_->Read(buf.get(), buf_size, bytes_read);
// No need to check the return value here as we'll detect errors by
// inspecting the URLRequest's status.
@@ -645,6 +606,7 @@ void ResourceLoader::CompleteRead(int bytes_read) {
void ResourceLoader::ResponseCompleted() {
VLOG(1) << "ResponseCompleted: " << request_->url().spec();
+ RecordHistograms();
ResourceRequestInfoImpl* info = GetRequestInfo();
std::string security_info;
@@ -652,19 +614,26 @@ void ResourceLoader::ResponseCompleted() {
if (ssl_info.cert.get() != NULL) {
int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert.get(),
info->GetChildID());
+ SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
+ StoreSignedCertificateTimestamps(ssl_info.signed_certificate_timestamps,
+ info->GetChildID(),
+ &signed_certificate_timestamp_ids);
+
security_info = SerializeSecurityInfo(
cert_id, ssl_info.cert_status, ssl_info.security_bits,
- ssl_info.connection_status);
+ ssl_info.connection_status, signed_certificate_timestamp_ids);
}
- if (handler_->OnResponseCompleted(info->GetRequestID(), request_->status(),
- security_info)) {
- // This will result in our destruction.
- CallDidFinishLoading();
- } else {
+ bool defer = false;
+ handler_->OnResponseCompleted(info->GetRequestID(), request_->status(),
+ security_info, &defer);
+ if (defer) {
// The handler is not ready to die yet. We will call DidFinishLoading when
// we resume.
deferred_stage_ = DEFERRED_FINISH;
+ } else {
+ // This will result in our destruction.
+ CallDidFinishLoading();
}
}
@@ -672,4 +641,37 @@ void ResourceLoader::CallDidFinishLoading() {
delegate_->DidFinishLoading(this);
}
+void ResourceLoader::RecordHistograms() {
+ ResourceRequestInfoImpl* info = GetRequestInfo();
+
+ if (info->GetResourceType() == ResourceType::PREFETCH) {
+ PrefetchStatus status = STATUS_UNDEFINED;
+ TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
+
+ switch (request_->status().status()) {
+ case net::URLRequestStatus::SUCCESS:
+ if (request_->was_cached()) {
+ status = STATUS_SUCCESS_FROM_CACHE;
+ UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromCache",
+ total_time);
+ } else {
+ status = STATUS_SUCCESS_FROM_NETWORK;
+ UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromNetwork",
+ total_time);
+ }
+ break;
+ case net::URLRequestStatus::CANCELED:
+ status = STATUS_CANCELED;
+ UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeBeforeCancel", total_time);
+ break;
+ case net::URLRequestStatus::IO_PENDING:
+ case net::URLRequestStatus::FAILED:
+ status = STATUS_UNDEFINED;
+ break;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", status, STATUS_MAX);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_loader.h b/chromium/content/browser/loader/resource_loader.h
index 76f72e2ec43..d0b3ae806ce 100644
--- a/chromium/content/browser/loader/resource_loader.h
+++ b/chromium/content/browser/loader/resource_loader.h
@@ -12,12 +12,9 @@
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/common/content_export.h"
#include "content/public/browser/resource_controller.h"
+#include "content/public/common/signed_certificate_timestamp_id_and_status.h"
#include "net/url_request/url_request.h"
-namespace net {
-class ClientCertStore;
-}
-
namespace content {
class ResourceDispatcherHostLoginDelegate;
class ResourceLoaderDelegate;
@@ -43,8 +40,7 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
bool is_transferring() const { return is_transferring_; }
void MarkAsTransferring(const GURL& target_url);
- void WillCompleteTransfer();
- void CompleteTransfer(scoped_ptr<ResourceHandler> new_handler);
+ void CompleteTransfer();
net::URLRequest* request() { return request_.get(); }
ResourceRequestInfoImpl* GetRequestInfo();
@@ -57,17 +53,7 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
private:
FRIEND_TEST_ALL_PREFIXES(ResourceLoaderTest, ClientCertStoreLookup);
-
- ResourceLoader(scoped_ptr<net::URLRequest> request,
- scoped_ptr<ResourceHandler> handler,
- ResourceLoaderDelegate* delegate,
- scoped_ptr<net::ClientCertStore> client_cert_store);
-
- // Initialization logic shared between the public and private constructor.
- void Init(scoped_ptr<net::URLRequest> request,
- scoped_ptr<ResourceHandler> handler,
- ResourceLoaderDelegate* delegate,
- scoped_ptr<net::ClientCertStore> client_cert_store);
+ FRIEND_TEST_ALL_PREFIXES(ResourceLoaderTest, ClientCertStoreNull);
// net::URLRequest::Delegate implementation:
virtual void OnReceivedRedirect(net::URLRequest* request,
@@ -98,6 +84,14 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
void StartRequestInternal();
void CancelRequestInternal(int error, bool from_renderer);
+ // Stores the SignedCertificateTimestamps held in |sct_list| in the
+ // SignedCertificateTimestampStore singleton, associated with |process_id|.
+ // On return, |sct_ids| contains the assigned ID and verification status of
+ // each SignedCertificateTimestamp.
+ void StoreSignedCertificateTimestamps(
+ const net::SignedCertificateTimestampAndStatusList& sct_list,
+ int process_id,
+ SignedCertificateTimestampIDStatusList* sct_ids);
void CompleteResponseStarted();
void StartReading(bool is_continuation);
void ResumeReading();
@@ -105,9 +99,21 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
void CompleteRead(int bytes_read);
void ResponseCompleted();
void CallDidFinishLoading();
+ void RecordHistograms();
bool is_deferred() const { return deferred_stage_ != DEFERRED_NONE; }
+ // Used for categorizing loading of prefetches for reporting in histograms.
+ // NOTE: This enumeration is used in histograms, so please do not add entries
+ // in the middle.
+ enum PrefetchStatus {
+ STATUS_UNDEFINED,
+ STATUS_SUCCESS_FROM_CACHE,
+ STATUS_SUCCESS_FROM_NETWORK,
+ STATUS_CANCELED,
+ STATUS_MAX,
+ };
+
enum DeferredStage {
DEFERRED_NONE,
DEFERRED_START,
@@ -134,8 +140,6 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
// which point we'll receive a new ResourceHandler.
bool is_transferring_;
- scoped_ptr<net::ClientCertStore> client_cert_store_;
-
base::WeakPtrFactory<ResourceLoader> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ResourceLoader);
diff --git a/chromium/content/browser/loader/resource_loader_unittest.cc b/chromium/content/browser/loader/resource_loader_unittest.cc
index 634a553dfaf..8f962118a79 100644
--- a/chromium/content/browser/loader/resource_loader_unittest.cc
+++ b/chromium/content/browser/loader/resource_loader_unittest.cc
@@ -11,6 +11,7 @@
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_content_browser_client.h"
+#include "net/base/request_priority.h"
#include "net/cert/x509_certificate.h"
#include "net/ssl/client_cert_store.h"
#include "net/ssl/ssl_cert_request_info.h"
@@ -48,12 +49,13 @@ class ClientCertStoreStub : public net::ClientCertStore {
}
// net::ClientCertStore:
- virtual bool GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
- net::CertificateList* selected_certs) OVERRIDE {
+ virtual void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
+ net::CertificateList* selected_certs,
+ const base::Closure& callback) OVERRIDE {
++request_count_;
requested_authorities_ = cert_request_info.cert_authorities;
*selected_certs = response_;
- return true;
+ callback.Run();
}
private:
@@ -66,6 +68,8 @@ class ClientCertStoreStub : public net::ClientCertStore {
// initialize ResourceLoader.
class ResourceHandlerStub : public ResourceHandler {
public:
+ ResourceHandlerStub() : ResourceHandler(NULL) {}
+
virtual bool OnUploadProgress(int request_id,
uint64 position,
uint64 size) OVERRIDE {
@@ -90,7 +94,7 @@ class ResourceHandlerStub : public ResourceHandler {
}
virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) OVERRIDE {
return true;
@@ -102,10 +106,10 @@ class ResourceHandlerStub : public ResourceHandler {
return true;
}
- virtual bool OnResponseCompleted(int request_id,
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) OVERRIDE {
- return true;
+ const std::string& security_info,
+ bool* defer) OVERRIDE {
}
virtual void OnDataDownloaded(int request_id,
@@ -141,6 +145,23 @@ class SelectCertificateBrowserClient : public TestContentBrowserClient {
int call_count_;
};
+class ResourceContextStub : public MockResourceContext {
+ public:
+ explicit ResourceContextStub(net::URLRequestContext* test_request_context)
+ : MockResourceContext(test_request_context) {}
+
+ virtual scoped_ptr<net::ClientCertStore> CreateClientCertStore() OVERRIDE {
+ return dummy_cert_store_.Pass();
+ }
+
+ void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
+ dummy_cert_store_ = store.Pass();
+ }
+
+ private:
+ scoped_ptr<net::ClientCertStore> dummy_cert_store_;
+};
+
} // namespace
class ResourceLoaderTest : public testing::Test,
@@ -180,12 +201,9 @@ class ResourceLoaderTest : public testing::Test,
content::TestBrowserThreadBundle thread_bundle_;
net::TestURLRequestContext test_url_request_context_;
- content::MockResourceContext resource_context_;
+ ResourceContextStub resource_context_;
};
-// When OpenSSL is used, client cert store is not being queried in
-// ResourceLoader.
-#if !defined(USE_OPENSSL)
// Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested()
// causes client cert store to be queried for certificates and if the returned
// certificates are correctly passed to the content browser client for
@@ -194,14 +212,17 @@ TEST_F(ResourceLoaderTest, ClientCertStoreLookup) {
const int kRenderProcessId = 1;
const int kRenderViewId = 2;
- scoped_ptr<net::URLRequest> request(new net::URLRequest(
- GURL("dummy"), NULL,
- resource_context_.GetRequestContext()));
+ scoped_ptr<net::URLRequest> request(
+ new net::URLRequest(GURL("dummy"),
+ net::DEFAULT_PRIORITY,
+ NULL,
+ resource_context_.GetRequestContext()));
ResourceRequestInfo::AllocateForTesting(request.get(),
ResourceType::MAIN_FRAME,
&resource_context_,
kRenderProcessId,
- kRenderViewId);
+ kRenderViewId,
+ false);
// Set up the test client cert store.
net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>(
@@ -215,10 +236,11 @@ TEST_F(ResourceLoaderTest, ClientCertStoreLookup) {
// later.
net::URLRequest* raw_ptr_to_request = request.get();
ClientCertStoreStub* raw_ptr_to_store = test_store.get();
+ resource_context_.SetClientCertStore(
+ test_store.PassAs<net::ClientCertStore>());
scoped_ptr<ResourceHandler> resource_handler(new ResourceHandlerStub());
- ResourceLoader loader(request.Pass(), resource_handler.Pass(), this,
- test_store.PassAs<net::ClientCertStore>());
+ ResourceLoader loader(request.Pass(), resource_handler.Pass(), this);
// Prepare a dummy certificate request.
scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
@@ -247,6 +269,55 @@ TEST_F(ResourceLoaderTest, ClientCertStoreLookup) {
EXPECT_EQ(1, test_client.call_count());
EXPECT_EQ(dummy_certs, test_client.passed_certs());
}
-#endif // !defined(OPENSSL)
+
+// Verifies if a call to net::URLRequest::Delegate::OnCertificateRequested()
+// on a platform with a NULL client cert store still calls the content browser
+// client for selection.
+TEST_F(ResourceLoaderTest, ClientCertStoreNull) {
+ const int kRenderProcessId = 1;
+ const int kRenderViewId = 2;
+
+ scoped_ptr<net::URLRequest> request(
+ new net::URLRequest(GURL("dummy"),
+ net::DEFAULT_PRIORITY,
+ NULL,
+ resource_context_.GetRequestContext()));
+ ResourceRequestInfo::AllocateForTesting(request.get(),
+ ResourceType::MAIN_FRAME,
+ &resource_context_,
+ kRenderProcessId,
+ kRenderViewId,
+ false);
+
+ // Ownership of the |request| is about to be turned over to ResourceLoader. We
+ // need to keep a raw pointer copy to access this object later.
+ net::URLRequest* raw_ptr_to_request = request.get();
+
+ scoped_ptr<ResourceHandler> resource_handler(new ResourceHandlerStub());
+ ResourceLoader loader(request.Pass(), resource_handler.Pass(), this);
+
+ // Prepare a dummy certificate request.
+ scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
+ new net::SSLCertRequestInfo());
+ std::vector<std::string> dummy_authority(1, "dummy");
+ cert_request_info->cert_authorities = dummy_authority;
+
+ // Plug in test content browser client.
+ SelectCertificateBrowserClient test_client;
+ ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
+
+ // Everything is set up. Trigger the resource loader certificate request event
+ // and run the message loop.
+ loader.OnCertificateRequested(raw_ptr_to_request, cert_request_info.get());
+ base::RunLoop().RunUntilIdle();
+
+ // Restore the original content browser client.
+ SetBrowserClientForTesting(old_client);
+
+ // Check if the SelectClientCertificate was called on the content browser
+ // client.
+ EXPECT_EQ(1, test_client.call_count());
+ EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
+}
} // namespace content
diff --git a/chromium/content/browser/loader/resource_message_delegate.h b/chromium/content/browser/loader/resource_message_delegate.h
index d5716e3ac25..f4478084634 100644
--- a/chromium/content/browser/loader/resource_message_delegate.h
+++ b/chromium/content/browser/loader/resource_message_delegate.h
@@ -32,6 +32,10 @@ class CONTENT_EXPORT ResourceMessageDelegate {
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) = 0;
+ void set_request_id(const GlobalRequestID& new_request_id) {
+ id_ = new_request_id;
+ }
+
private:
GlobalRequestID id_;
DISALLOW_IMPLICIT_CONSTRUCTORS(ResourceMessageDelegate);
diff --git a/chromium/content/browser/loader/resource_message_filter.cc b/chromium/content/browser/loader/resource_message_filter.cc
index 26ba80fbaa4..c3f30ff796e 100644
--- a/chromium/content/browser/loader/resource_message_filter.cc
+++ b/chromium/content/browser/loader/resource_message_filter.cc
@@ -24,15 +24,14 @@ ResourceMessageFilter::ResourceMessageFilter(
appcache_service_(appcache_service),
blob_storage_context_(blob_storage_context),
file_system_context_(file_system_context),
- get_contexts_callback_(get_contexts_callback) {
+ get_contexts_callback_(get_contexts_callback),
+ weak_ptr_factory_(this) {
}
ResourceMessageFilter::~ResourceMessageFilter() {
}
void ResourceMessageFilter::OnChannelClosing() {
- BrowserMessageFilter::OnChannelClosing();
-
// Unhook us from all pending network requests so they don't get sent to a
// deleted object.
ResourceDispatcherHostImpl::Get()->CancelRequestsForProcess(child_id_);
@@ -51,4 +50,8 @@ void ResourceMessageFilter::GetContexts(
return get_contexts_callback_.Run(request, resource_context, request_context);
}
+base::WeakPtr<ResourceMessageFilter> ResourceMessageFilter::GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_message_filter.h b/chromium/content/browser/loader/resource_message_filter.h
index 925e4525e28..a2fb2e38fc6 100644
--- a/chromium/content/browser/loader/resource_message_filter.h
+++ b/chromium/content/browser/loader/resource_message_filter.h
@@ -7,6 +7,7 @@
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
#include "webkit/common/resource_type.h"
@@ -76,6 +77,8 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
int child_id() const { return child_id_; }
int process_type() const { return process_type_; }
+ base::WeakPtr<ResourceMessageFilter> GetWeakPtr();
+
protected:
// Protected destructor so that we can be overriden in tests.
virtual ~ResourceMessageFilter();
@@ -92,6 +95,9 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
GetContextsCallback get_contexts_callback_;
+ // This must come last to make sure weak pointers are invalidated first.
+ base::WeakPtrFactory<ResourceMessageFilter> weak_ptr_factory_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(ResourceMessageFilter);
};
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index c41fe39e565..32ba7ac6dea 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -5,6 +5,7 @@
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader/global_routing_id.h"
+#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/worker_host/worker_service_impl.h"
#include "content/common/net/url_request_user_data.h"
#include "content/public/browser/global_request_id.h"
@@ -27,7 +28,8 @@ void ResourceRequestInfo::AllocateForTesting(
ResourceType::Type resource_type,
ResourceContext* context,
int render_process_id,
- int render_view_id) {
+ int render_view_id,
+ bool is_async) {
ResourceRequestInfoImpl* info =
new ResourceRequestInfoImpl(
PROCESS_TYPE_RENDERER, // process_type
@@ -35,19 +37,22 @@ void ResourceRequestInfo::AllocateForTesting(
render_view_id, // route_id
0, // origin_pid
0, // request_id
+ MSG_ROUTING_NONE, // render_frame_id
resource_type == ResourceType::MAIN_FRAME, // is_main_frame
0, // frame_id
false, // parent_is_main_frame
0, // parent_frame_id
resource_type, // resource_type
PAGE_TRANSITION_LINK, // transition_type
+ false, // should_replace_current_entry
false, // is_download
false, // is_stream
true, // allow_download
false, // has_user_gesture
- WebKit::WebReferrerPolicyDefault, // referrer_policy
+ blink::WebReferrerPolicyDefault, // referrer_policy
context, // context
- false); // is_async
+ base::WeakPtr<ResourceMessageFilter>(), // filter
+ is_async); // is_async
info->AssociateWithRequest(request);
}
@@ -86,29 +91,35 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
int route_id,
int origin_pid,
int request_id,
+ int render_frame_id,
bool is_main_frame,
int64 frame_id,
bool parent_is_main_frame,
int64 parent_frame_id,
ResourceType::Type resource_type,
PageTransition transition_type,
+ bool should_replace_current_entry,
bool is_download,
bool is_stream,
bool allow_download,
bool has_user_gesture,
- WebKit::WebReferrerPolicy referrer_policy,
+ blink::WebReferrerPolicy referrer_policy,
ResourceContext* context,
+ base::WeakPtr<ResourceMessageFilter> filter,
bool is_async)
: cross_site_handler_(NULL),
+ detachable_handler_(NULL),
process_type_(process_type),
child_id_(child_id),
route_id_(route_id),
origin_pid_(origin_pid),
request_id_(request_id),
+ render_frame_id_(render_frame_id),
is_main_frame_(is_main_frame),
frame_id_(frame_id),
parent_is_main_frame_(parent_is_main_frame),
parent_frame_id_(parent_frame_id),
+ should_replace_current_entry_(should_replace_current_entry),
is_download_(is_download),
is_stream_(is_stream),
allow_download_(allow_download),
@@ -119,6 +130,7 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
memory_cost_(0),
referrer_policy_(referrer_policy),
context_(context),
+ filter_(filter),
is_async_(is_async) {
}
@@ -145,6 +157,10 @@ int ResourceRequestInfoImpl::GetRequestID() const {
return request_id_;
}
+int ResourceRequestInfoImpl::GetRenderFrameID() const {
+ return render_frame_id_;
+}
+
bool ResourceRequestInfoImpl::IsMainFrame() const {
return is_main_frame_;
}
@@ -165,7 +181,7 @@ ResourceType::Type ResourceRequestInfoImpl::GetResourceType() const {
return resource_type_;
}
-WebKit::WebReferrerPolicy ResourceRequestInfoImpl::GetReferrerPolicy() const {
+blink::WebReferrerPolicy ResourceRequestInfoImpl::GetReferrerPolicy() const {
return referrer_policy_;
}
@@ -209,6 +225,10 @@ bool ResourceRequestInfoImpl::IsAsync() const {
return is_async_;
}
+bool ResourceRequestInfoImpl::IsDownload() const {
+ return is_download_;
+}
+
void ResourceRequestInfoImpl::AssociateWithRequest(net::URLRequest* request) {
request->SetUserData(NULL, this);
int render_process_id;
@@ -228,4 +248,20 @@ GlobalRoutingID ResourceRequestInfoImpl::GetGlobalRoutingID() const {
return GlobalRoutingID(child_id_, route_id_);
}
+void ResourceRequestInfoImpl::UpdateForTransfer(
+ int child_id,
+ int route_id,
+ int origin_pid,
+ int request_id,
+ int64 frame_id,
+ int64 parent_frame_id,
+ base::WeakPtr<ResourceMessageFilter> filter) {
+ child_id_ = child_id;
+ route_id_ = route_id;
+ origin_pid_ = origin_pid;
+ request_id_ = request_id;
+ frame_id_ = frame_id;
+ filter_ = filter;
+}
+
} // 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 e615116c152..2635106c5ca 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -8,8 +8,10 @@
#include <string>
#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/referrer.h"
@@ -18,7 +20,9 @@
namespace content {
class CrossSiteResourceHandler;
+class DetachableResourceHandler;
class ResourceContext;
+class ResourceMessageFilter;
struct GlobalRequestID;
struct GlobalRoutingID;
@@ -41,18 +45,21 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
int route_id,
int origin_pid,
int request_id,
+ int render_frame_id,
bool is_main_frame,
int64 frame_id,
bool parent_is_main_frame,
int64 parent_frame_id,
ResourceType::Type resource_type,
PageTransition transition_type,
+ bool should_replace_current_entry,
bool is_download,
bool is_stream,
bool allow_download,
bool has_user_gesture,
- WebKit::WebReferrerPolicy referrer_policy,
+ blink::WebReferrerPolicy referrer_policy,
ResourceContext* context,
+ base::WeakPtr<ResourceMessageFilter> filter,
bool is_async);
virtual ~ResourceRequestInfoImpl();
@@ -62,18 +69,20 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
virtual int GetRouteID() const OVERRIDE;
virtual int GetOriginPID() const OVERRIDE;
virtual int GetRequestID() const OVERRIDE;
+ virtual int GetRenderFrameID() const OVERRIDE;
virtual bool IsMainFrame() const OVERRIDE;
virtual int64 GetFrameID() const OVERRIDE;
virtual bool ParentIsMainFrame() const OVERRIDE;
virtual int64 GetParentFrameID() const OVERRIDE;
virtual ResourceType::Type GetResourceType() const OVERRIDE;
- virtual WebKit::WebReferrerPolicy GetReferrerPolicy() const OVERRIDE;
+ virtual blink::WebReferrerPolicy GetReferrerPolicy() const OVERRIDE;
virtual PageTransition GetPageTransition() const OVERRIDE;
virtual bool HasUserGesture() const OVERRIDE;
virtual bool WasIgnoredByHandler() const OVERRIDE;
virtual bool GetAssociatedRenderView(int* render_process_id,
int* render_view_id) const OVERRIDE;
virtual bool IsAsync() const OVERRIDE;
+ virtual bool IsDownload() const OVERRIDE;
CONTENT_EXPORT void AssociateWithRequest(net::URLRequest* request);
@@ -81,6 +90,23 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
CONTENT_EXPORT GlobalRequestID GetGlobalRequestID() const;
GlobalRoutingID GetGlobalRoutingID() const;
+ // May be NULL (e.g., if process dies during a transfer).
+ ResourceMessageFilter* filter() const {
+ return filter_.get();
+ }
+
+ // Updates the data associated with this request after it is is transferred
+ // to a new renderer process. Not all data will change during a transfer.
+ // We do not expect the ResourceContext to change during navigation, so that
+ // does not need to be updated.
+ void UpdateForTransfer(int child_id,
+ int route_id,
+ int origin_pid,
+ int request_id,
+ int64 frame_id,
+ int64 parent_frame_id,
+ base::WeakPtr<ResourceMessageFilter> filter);
+
// CrossSiteResourceHandler for this request. May be null.
CrossSiteResourceHandler* cross_site_handler() {
return cross_site_handler_;
@@ -89,6 +115,21 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
cross_site_handler_ = h;
}
+ // Whether this request is part of a navigation that should replace the
+ // current session history entry. This state is shuffled up and down the stack
+ // for request transfers.
+ bool should_replace_current_entry() const {
+ return should_replace_current_entry_;
+ }
+
+ // DetachableResourceHandler for this request. May be NULL.
+ DetachableResourceHandler* detachable_handler() const {
+ return detachable_handler_;
+ }
+ void set_detachable_handler(DetachableResourceHandler* h) {
+ detachable_handler_ = h;
+ }
+
// Identifies the type of process (renderer, plugin, etc.) making the request.
int process_type() const { return process_type_; }
@@ -96,7 +137,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool allow_download() const { return allow_download_; }
// Whether this is a download.
- bool is_download() const { return is_download_; }
void set_is_download(bool download) { is_download_ = download; }
// Whether this is a stream.
@@ -113,18 +153,25 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
void set_memory_cost(int cost) { memory_cost_ = cost; }
private:
+ FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
+ DeletedFilterDetached);
+ FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
+ DeletedFilterDetachedRedirect);
// Non-owning, may be NULL.
CrossSiteResourceHandler* cross_site_handler_;
+ DetachableResourceHandler* detachable_handler_;
int process_type_;
int child_id_;
int route_id_;
int origin_pid_;
int request_id_;
+ int render_frame_id_;
bool is_main_frame_;
int64 frame_id_;
bool parent_is_main_frame_;
int64 parent_frame_id_;
+ bool should_replace_current_entry_;
bool is_download_;
bool is_stream_;
bool allow_download_;
@@ -133,8 +180,11 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
ResourceType::Type resource_type_;
PageTransition transition_type_;
int memory_cost_;
- WebKit::WebReferrerPolicy referrer_policy_;
+ blink::WebReferrerPolicy referrer_policy_;
ResourceContext* context_;
+ // The filter might be deleted without deleting this object if the process
+ // exits during a transfer.
+ base::WeakPtr<ResourceMessageFilter> filter_;
bool is_async_;
DISALLOW_COPY_AND_ASSIGN(ResourceRequestInfoImpl);
diff --git a/chromium/content/browser/loader/resource_scheduler.cc b/chromium/content/browser/loader/resource_scheduler.cc
index 0277783bfdf..4ae240e6fe3 100644
--- a/chromium/content/browser/loader/resource_scheduler.cc
+++ b/chromium/content/browser/loader/resource_scheduler.cc
@@ -21,11 +21,46 @@
namespace content {
static const size_t kMaxNumDelayableRequestsPerClient = 10;
+static const size_t kMaxNumDelayableRequestsPerHost = 6;
// A thin wrapper around net::PriorityQueue that deals with
// ScheduledResourceRequests instead of PriorityQueue::Pointers.
class ResourceScheduler::RequestQueue {
+ private:
+ typedef net::PriorityQueue<ScheduledResourceRequest*> NetQueue;
+
public:
+ class Iterator {
+ public:
+ Iterator(NetQueue* queue) : queue_(queue) {
+ DCHECK(queue != NULL);
+ current_pointer_ = queue_->FirstMax();
+ }
+
+ Iterator& operator++() {
+ current_pointer_ = queue_->GetNextTowardsLastMin(current_pointer_);
+ return *this;
+ }
+
+ Iterator operator++(int) {
+ Iterator result(*this);
+ ++(*this);
+ return result;
+ }
+
+ ScheduledResourceRequest* value() {
+ return current_pointer_.value();
+ }
+
+ bool is_null() {
+ return current_pointer_.is_null();
+ }
+
+ private:
+ NetQueue* queue_;
+ NetQueue::Pointer current_pointer_;
+ };
+
RequestQueue() : queue_(net::NUM_PRIORITIES) {}
~RequestQueue() {}
@@ -41,6 +76,8 @@ class ResourceScheduler::RequestQueue {
void Erase(ScheduledResourceRequest* request) {
PointerMap::iterator it = pointers_.find(request);
DCHECK(it != pointers_.end());
+ if (it == pointers_.end())
+ return;
queue_.Erase(it->second);
pointers_.erase(it);
}
@@ -50,6 +87,10 @@ class ResourceScheduler::RequestQueue {
return queue_.FirstMax().value();
}
+ Iterator GetNextHighestIterator() {
+ return Iterator(&queue_);
+ }
+
// Returns true if |request| is queued.
bool IsQueued(ScheduledResourceRequest* request) const {
return ContainsKey(pointers_, request);
@@ -59,7 +100,6 @@ class ResourceScheduler::RequestQueue {
bool IsEmpty() const { return queue_.size() == 0; }
private:
- typedef net::PriorityQueue<ScheduledResourceRequest*> NetQueue;
typedef std::map<ScheduledResourceRequest*, NetQueue::Pointer> PointerMap;
NetQueue queue_;
@@ -90,7 +130,7 @@ class ResourceScheduler::ScheduledResourceRequest
}
void Start() {
- TRACE_EVENT_ASYNC_STEP0("net", "URLRequest", request_, "Queued");
+ TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request_, "Queued");
ready_ = true;
if (deferred_ && request_->status().is_success()) {
deferred_ = false;
@@ -119,6 +159,10 @@ class ResourceScheduler::ScheduledResourceRequest
deferred_ = *defer = !ready_;
}
+ virtual const char* GetNameForLogging() const OVERRIDE {
+ return "ResourceScheduler";
+ }
+
void DidChangePriority(int request_id, net::RequestPriority new_priority) {
scheduler_->ReprioritizeRequest(this, new_priority);
}
@@ -171,7 +215,7 @@ scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
}
Client* client = it->second;
- if (ShouldStartRequest(request.get(), client)) {
+ if (ShouldStartRequest(request.get(), client) == START_REQUEST) {
StartRequest(request.get(), client);
} else {
client->pending_requests.Insert(request.get(), url_request->priority());
@@ -218,6 +262,9 @@ void ResourceScheduler::OnClientDeleted(int child_id, int route_id) {
ClientId client_id = MakeClientId(child_id, route_id);
DCHECK(ContainsKey(client_map_, client_id));
ClientMap::iterator it = client_map_.find(client_id);
+ if (it == client_map_.end())
+ return;
+
Client* client = it->second;
// FYI, ResourceDispatcherHost cancels all of the requests after this function
@@ -273,6 +320,12 @@ void ResourceScheduler::StartRequest(ScheduledResourceRequest* request,
void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request,
net::RequestPriority new_priority) {
+ if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) {
+ // We should not be re-prioritizing requests with the
+ // IGNORE_LIMITS flag.
+ NOTREACHED();
+ return;
+ }
net::RequestPriority old_priority = request->url_request()->priority();
DCHECK_NE(new_priority, old_priority);
request->url_request()->SetPriority(new_priority);
@@ -290,7 +343,8 @@ void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request,
}
client->pending_requests.Erase(request);
- client->pending_requests.Insert(request, request->url_request()->priority());
+ client->pending_requests.Insert(request,
+ request->url_request()->priority());
if (new_priority > old_priority) {
// Check if this request is now able to load at its new priority.
@@ -299,32 +353,72 @@ void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request,
}
void ResourceScheduler::LoadAnyStartablePendingRequests(Client* client) {
- while (!client->pending_requests.IsEmpty()) {
- ScheduledResourceRequest* request = client->pending_requests.FirstMax();
- if (ShouldStartRequest(request, client)) {
+ // We iterate through all the pending requests, starting with the highest
+ // priority one. For each entry, one of three things can happen:
+ // 1) We start the request, remove it from the list, and keep checking.
+ // 2) We do NOT start the request, but ShouldStartRequest() signals us that
+ // there may be room for other requests, so we keep checking and leave
+ // the previous request still in the list.
+ // 3) We do not start the request, same as above, but StartRequest() tells
+ // us there's no point in checking any further requests.
+
+ RequestQueue::Iterator request_iter =
+ client->pending_requests.GetNextHighestIterator();
+
+ while (!request_iter.is_null()) {
+ ScheduledResourceRequest* request = request_iter.value();
+ ShouldStartReqResult query_result = ShouldStartRequest(request, client);
+
+ if (query_result == START_REQUEST) {
client->pending_requests.Erase(request);
StartRequest(request, client);
+
+ // StartRequest can modify the pending list, so we (re)start evaluation
+ // from the currently highest priority request. Avoid copying a singular
+ // iterator, which would trigger undefined behavior.
+ if (client->pending_requests.GetNextHighestIterator().is_null())
+ break;
+ request_iter = client->pending_requests.GetNextHighestIterator();
+ } else if (query_result == DO_NOT_START_REQUEST_AND_KEEP_SEARCHING) {
+ ++request_iter;
+ continue;
} else {
+ DCHECK(query_result == DO_NOT_START_REQUEST_AND_STOP_SEARCHING);
break;
}
}
}
-size_t ResourceScheduler::GetNumDelayableRequestsInFlight(
- Client* client) const {
- size_t count = 0;
+void ResourceScheduler::GetNumDelayableRequestsInFlight(
+ Client* client,
+ const net::HostPortPair& active_request_host,
+ size_t* total_delayable,
+ size_t* total_for_active_host) const {
+ DCHECK(client != NULL && total_delayable != NULL &&
+ total_for_active_host != NULL);
+
+ size_t total_delayable_count = 0;
+ size_t same_host_count = 0;
for (RequestSet::iterator it = client->in_flight_requests.begin();
it != client->in_flight_requests.end(); ++it) {
+ net::HostPortPair host_port_pair =
+ net::HostPortPair::FromURL((*it)->url_request()->url());
+
+ if (active_request_host.Equals(host_port_pair)) {
+ same_host_count++;
+ }
+
if ((*it)->url_request()->priority() < net::LOW) {
const net::HttpServerProperties& http_server_properties =
*(*it)->url_request()->context()->http_server_properties();
- if (!http_server_properties.SupportsSpdy(
- net::HostPortPair::FromURL((*it)->url_request()->url()))) {
- ++count;
+
+ if (!http_server_properties.SupportsSpdy(host_port_pair)) {
+ ++total_delayable_count;
}
}
}
- return count;
+ *total_delayable = total_delayable_count;
+ *total_for_active_host = same_host_count;
}
// ShouldStartRequest is the main scheduling algorithm.
@@ -336,6 +430,7 @@ size_t ResourceScheduler::GetNumDelayableRequestsInFlight(
// * Higher priority requests (>= net::LOW).
// * Synchronous requests.
// * Requests to SPDY-capable origin servers.
+// * Non-HTTP[S] requests.
//
// 2. The remainder are delayable requests, which follow these rules:
//
@@ -343,39 +438,60 @@ size_t ResourceScheduler::GetNumDelayableRequestsInFlight(
// requests.
// * Once the renderer has a <body>, start loading delayable requests.
// * Never exceed 10 delayable requests in flight per client.
+// * Never exceed 6 delayable requests for a given host.
// * Prior to <body>, allow one delayable request to load at a time.
-bool ResourceScheduler::ShouldStartRequest(ScheduledResourceRequest* request,
- Client* client) const {
+ResourceScheduler::ShouldStartReqResult ResourceScheduler::ShouldStartRequest(
+ ScheduledResourceRequest* request,
+ Client* client) const {
const net::URLRequest& url_request = *request->url_request();
+
+ // TODO(simonjam): This may end up causing disk contention. We should
+ // experiment with throttling if that happens.
+ if (!url_request.url().SchemeIsHTTPOrHTTPS()) {
+ return START_REQUEST;
+ }
+
const net::HttpServerProperties& http_server_properties =
*url_request.context()->http_server_properties();
+ if (url_request.priority() >= net::LOW ||
+ !ResourceRequestInfo::ForRequest(&url_request)->IsAsync()) {
+ return START_REQUEST;
+ }
+
+ net::HostPortPair host_port_pair =
+ net::HostPortPair::FromURL(url_request.url());
+
// TODO(willchan): We should really improve this algorithm as described in
// crbug.com/164101. Also, theoretically we should not count a SPDY request
// against the delayable requests limit.
- bool origin_supports_spdy = http_server_properties.SupportsSpdy(
- net::HostPortPair::FromURL(url_request.url()));
-
- if (url_request.priority() >= net::LOW ||
- !ResourceRequestInfo::ForRequest(&url_request)->IsAsync() ||
- origin_supports_spdy) {
- return true;
+ if (http_server_properties.SupportsSpdy(host_port_pair)) {
+ return START_REQUEST;
}
- size_t num_delayable_requests_in_flight =
- GetNumDelayableRequestsInFlight(client);
+ size_t num_delayable_requests_in_flight = 0;
+ size_t num_requests_in_flight_for_host = 0;
+ GetNumDelayableRequestsInFlight(client, host_port_pair,
+ &num_delayable_requests_in_flight,
+ &num_requests_in_flight_for_host);
+
if (num_delayable_requests_in_flight >= kMaxNumDelayableRequestsPerClient) {
- return false;
+ return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
+ }
+
+ if (num_requests_in_flight_for_host >= kMaxNumDelayableRequestsPerHost) {
+ // There may be other requests for other hosts we'd allow, so keep checking.
+ return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING;
}
bool have_immediate_requests_in_flight =
client->in_flight_requests.size() > num_delayable_requests_in_flight;
if (have_immediate_requests_in_flight && !client->has_body &&
num_delayable_requests_in_flight != 0) {
- return false;
+ return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
}
- return true;
+ return START_REQUEST;
}
ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
diff --git a/chromium/content/browser/loader/resource_scheduler.h b/chromium/content/browser/loader/resource_scheduler.h
index d9711134421..dddc831a2e2 100644
--- a/chromium/content/browser/loader/resource_scheduler.h
+++ b/chromium/content/browser/loader/resource_scheduler.h
@@ -17,6 +17,7 @@
#include "net/base/request_priority.h"
namespace net {
+class HostPortPair;
class URLRequest;
}
@@ -107,12 +108,22 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
// Returns the number of requests with priority < LOW that are currently in
// flight.
- size_t GetNumDelayableRequestsInFlight(Client* client) const;
+ void GetNumDelayableRequestsInFlight(
+ Client* client,
+ const net::HostPortPair& active_request_host,
+ size_t* total_delayable,
+ size_t* total_for_active_host) const;
+
+ enum ShouldStartReqResult {
+ DO_NOT_START_REQUEST_AND_STOP_SEARCHING = -2,
+ DO_NOT_START_REQUEST_AND_KEEP_SEARCHING = -1,
+ START_REQUEST = 1,
+ };
// Returns true if the request should start. This is the core scheduling
// algorithm.
- bool ShouldStartRequest(ScheduledResourceRequest* request,
- Client* client) const;
+ ShouldStartReqResult ShouldStartRequest(ScheduledResourceRequest* request,
+ Client* client) const;
// Returns the client ID for the given |child_id| and |route_id| combo.
ClientId MakeClientId(int child_id, int route_id);
diff --git a/chromium/content/browser/loader/resource_scheduler_filter.cc b/chromium/content/browser/loader/resource_scheduler_filter.cc
index fb5a7fa60f1..66e9ea4fbd0 100644
--- a/chromium/content/browser/loader/resource_scheduler_filter.cc
+++ b/chromium/content/browser/loader/resource_scheduler_filter.cc
@@ -20,6 +20,13 @@ ResourceSchedulerFilter::~ResourceSchedulerFilter() {
bool ResourceSchedulerFilter::OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) {
+ ResourceScheduler* scheduler =
+ ResourceDispatcherHostImpl::Get()->scheduler();
+ // scheduler can be NULL during shutdown, in which case it's ok to ignore the
+ // renderer's messages.
+ if (!scheduler)
+ return false;
+
switch (message.type()) {
case ViewHostMsg_FrameNavigate::ID: {
PickleIterator iter(message);
@@ -30,15 +37,13 @@ bool ResourceSchedulerFilter::OnMessageReceived(const IPC::Message& message,
}
if (PageTransitionIsMainFrame(params.transition) &&
!params.was_within_same_page) {
- ResourceDispatcherHostImpl::Get()->scheduler()->OnNavigate(
- child_id_, message.routing_id());
+ scheduler->OnNavigate(child_id_, message.routing_id());
}
break;
}
case ViewHostMsg_WillInsertBody::ID:
- ResourceDispatcherHostImpl::Get()->scheduler()->OnWillInsertBody(
- child_id_, message.routing_id());
+ scheduler->OnWillInsertBody(child_id_, message.routing_id());
break;
default:
diff --git a/chromium/content/browser/loader/resource_scheduler_unittest.cc b/chromium/content/browser/loader/resource_scheduler_unittest.cc
index 2c4c1101962..fbdc72b4660 100644
--- a/chromium/content/browser/loader/resource_scheduler_unittest.cc
+++ b/chromium/content/browser/loader/resource_scheduler_unittest.cc
@@ -17,6 +17,7 @@
#include "content/public/browser/resource_throttle.h"
#include "content/public/common/process_type.h"
#include "net/base/host_port_pair.h"
+#include "net/base/request_priority.h"
#include "net/http/http_server_properties_impl.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
@@ -139,26 +140,28 @@ class ResourceSchedulerTest : public testing::Test {
net::RequestPriority priority,
int route_id) {
scoped_ptr<net::URLRequest> url_request(
- context_.CreateRequest(GURL(url), NULL));
- url_request->SetPriority(priority);
+ context_.CreateRequest(GURL(url), priority, NULL));
ResourceRequestInfoImpl* info = new ResourceRequestInfoImpl(
PROCESS_TYPE_RENDERER, // process_type
kChildId, // child_id
route_id, // route_id
0, // origin_pid
++next_request_id_, // request_id
+ MSG_ROUTING_NONE, // render_frame_id
false, // is_main_frame
0, // frame_id
false, // parent_is_main_frame
0, // parent_frame_id
ResourceType::SUB_RESOURCE, // resource_type
PAGE_TRANSITION_LINK, // transition_type
+ false, // should_replace_current_entry
false, // is_download
false, // is_stream
true, // allow_download
false, // has_user_gesture
- WebKit::WebReferrerPolicyDefault, // referrer_policy
+ blink::WebReferrerPolicyDefault, // referrer_policy
NULL, // context
+ base::WeakPtr<ResourceMessageFilter>(), // filter
true); // is_async
info->AssociateWithRequest(url_request.get());
return url_request.Pass();
@@ -317,19 +320,41 @@ TEST_F(ResourceSchedulerTest, LimitedNumberOfDelayableRequestsInFlight) {
EXPECT_TRUE(high->started());
const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
- ScopedVector<TestRequest> lows;
- for (int i = 0; i < kMaxNumDelayableRequestsPerClient; ++i) {
+ const int kMaxNumDelayableRequestsPerHost = 6;
+ ScopedVector<TestRequest> lows_singlehost;
+ // Queue up to the per-host limit (we subtract the current high-pri request).
+ for (int i = 0; i < kMaxNumDelayableRequestsPerHost - 1; ++i) {
string url = "http://host/low" + base::IntToString(i);
- lows.push_back(NewRequest(url.c_str(), net::LOWEST));
- EXPECT_TRUE(lows[i]->started());
+ lows_singlehost.push_back(NewRequest(url.c_str(), net::LOWEST));
+ EXPECT_TRUE(lows_singlehost[i]->started());
}
- scoped_ptr<TestRequest> last(NewRequest("http://host/last", net::LOWEST));
- EXPECT_FALSE(last->started());
+ scoped_ptr<TestRequest> second_last_singlehost(NewRequest("http://host/last",
+ net::LOWEST));
+ scoped_ptr<TestRequest> last_singlehost(NewRequest("http://host/s_last",
+ net::LOWEST));
+
+ EXPECT_FALSE(second_last_singlehost->started());
high.reset();
- EXPECT_FALSE(last->started());
- lows.erase(lows.begin());
- EXPECT_TRUE(last->started());
+ EXPECT_TRUE(second_last_singlehost->started());
+ EXPECT_FALSE(last_singlehost->started());
+ lows_singlehost.erase(lows_singlehost.begin());
+ EXPECT_TRUE(last_singlehost->started());
+
+ // Queue more requests from different hosts until we reach the total limit.
+ int expected_slots_left =
+ kMaxNumDelayableRequestsPerClient - kMaxNumDelayableRequestsPerHost;
+ EXPECT_GT(expected_slots_left, 0);
+ ScopedVector<TestRequest> lows_differenthosts;
+ for (int i = 0; i < expected_slots_left; ++i) {
+ string url = "http://host" + base::IntToString(i) + "/low";
+ lows_differenthosts.push_back(NewRequest(url.c_str(), net::LOWEST));
+ EXPECT_TRUE(lows_differenthosts[i]->started());
+ }
+
+ scoped_ptr<TestRequest> last_differenthost(NewRequest("http://host_new/last",
+ net::LOWEST));
+ EXPECT_FALSE(last_differenthost->started());
}
TEST_F(ResourceSchedulerTest, RaisePriorityAndStart) {
@@ -390,7 +415,7 @@ TEST_F(ResourceSchedulerTest, LowerPriority) {
const int kNumFillerRequests = kMaxNumDelayableRequestsPerClient - 2;
ScopedVector<TestRequest> lows;
for (int i = 0; i < kNumFillerRequests; ++i) {
- string url = "http://host/low" + base::IntToString(i);
+ string url = "http://host" + base::IntToString(i) + "/low";
lows.push_back(NewRequest(url.c_str(), net::LOWEST));
}
@@ -429,6 +454,16 @@ TEST_F(ResourceSchedulerTest, ReprioritizedRequestGoesToBackOfQueue) {
EXPECT_FALSE(idle->started());
}
+TEST_F(ResourceSchedulerTest, NonHTTPSchedulesImmediately) {
+ // Dummies to enforce scheduling.
+ scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> low(NewRequest("http://host/high", net::LOWEST));
+
+ scoped_ptr<TestRequest> request(
+ NewRequest("chrome-extension://req", net::LOWEST));
+ EXPECT_TRUE(request->started());
+}
+
} // unnamed namespace
} // namespace content
diff --git a/chromium/content/browser/loader/stream_resource_handler.cc b/chromium/content/browser/loader/stream_resource_handler.cc
index 1e2acc877f5..67309e8189d 100644
--- a/chromium/content/browser/loader/stream_resource_handler.cc
+++ b/chromium/content/browser/loader/stream_resource_handler.cc
@@ -19,7 +19,7 @@ StreamResourceHandler::StreamResourceHandler(
net::URLRequest* request,
StreamRegistry* registry,
const GURL& origin)
- : request_(request),
+ : ResourceHandler(request),
read_buffer_(NULL) {
// TODO(tyoshino): Find a way to share this with the blob URL creation in
// WebKit.
@@ -58,7 +58,7 @@ bool StreamResourceHandler::OnWillStart(int request_id,
}
bool StreamResourceHandler::OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) {
static const int kReadBufSize = 32768;
@@ -93,12 +93,12 @@ bool StreamResourceHandler::OnReadCompleted(int request_id,
return true;
}
-bool StreamResourceHandler::OnResponseCompleted(
+void StreamResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& status,
- const std::string& sec_info) {
+ const std::string& sec_info,
+ bool* defer) {
stream_->Finalize();
- return status.status() == net::URLRequestStatus::SUCCESS;
}
void StreamResourceHandler::OnDataDownloaded(
diff --git a/chromium/content/browser/loader/stream_resource_handler.h b/chromium/content/browser/loader/stream_resource_handler.h
index 037ebdc9104..14c576705d4 100644
--- a/chromium/content/browser/loader/stream_resource_handler.h
+++ b/chromium/content/browser/loader/stream_resource_handler.h
@@ -51,7 +51,7 @@ class StreamResourceHandler : public StreamWriteObserver,
// Create a new buffer to store received data.
virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) OVERRIDE;
@@ -60,9 +60,10 @@ class StreamResourceHandler : public StreamWriteObserver,
int bytes_read,
bool* defer) OVERRIDE;
- virtual bool OnResponseCompleted(int request_id,
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
- const std::string& sec_info) OVERRIDE;
+ const std::string& sec_info,
+ bool* defer) OVERRIDE;
virtual void OnDataDownloaded(int request_id, int bytes_downloaded) OVERRIDE;
@@ -72,7 +73,6 @@ class StreamResourceHandler : public StreamWriteObserver,
virtual void OnSpaceAvailable(Stream* stream) OVERRIDE;
virtual void OnClose(Stream* stream) OVERRIDE;
- net::URLRequest* request_;
scoped_refptr<Stream> stream_;
scoped_refptr<net::IOBuffer> read_buffer_;
DISALLOW_COPY_AND_ASSIGN(StreamResourceHandler);
diff --git a/chromium/content/browser/loader/sync_resource_handler.cc b/chromium/content/browser/loader/sync_resource_handler.cc
index b1a71622c2b..1310d0f3669 100644
--- a/chromium/content/browser/loader/sync_resource_handler.cc
+++ b/chromium/content/browser/loader/sync_resource_handler.cc
@@ -8,33 +8,35 @@
#include "content/browser/devtools/devtools_netlog_observer.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/loader/resource_request_info_impl.h"
#include "content/common/resource_messages.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
+#include "content/public/browser/resource_request_info.h"
#include "net/base/io_buffer.h"
#include "net/http/http_response_headers.h"
namespace content {
SyncResourceHandler::SyncResourceHandler(
- ResourceMessageFilter* filter,
- ResourceContext* resource_context,
net::URLRequest* request,
IPC::Message* result_message,
ResourceDispatcherHostImpl* resource_dispatcher_host)
- : read_buffer_(new net::IOBuffer(kReadBufSize)),
- filter_(filter),
- resource_context_(resource_context),
- request_(request),
+ : ResourceHandler(request),
+ read_buffer_(new net::IOBuffer(kReadBufSize)),
result_message_(result_message),
rdh_(resource_dispatcher_host) {
- result_.final_url = request_->url();
+ result_.final_url = request->url();
}
SyncResourceHandler::~SyncResourceHandler() {
if (result_message_) {
result_message_->set_reply_error();
- filter_->Send(result_message_);
+ ResourceMessageFilter* filter = GetFilter();
+ // If the filter doesn't exist at this point, the process has died and isn't
+ // waiting for the result message anymore.
+ if (filter)
+ filter->Send(result_message_);
}
}
@@ -51,10 +53,10 @@ bool SyncResourceHandler::OnRequestRedirected(
bool* defer) {
if (rdh_->delegate()) {
rdh_->delegate()->OnRequestRedirected(
- new_url, request_, resource_context_, response);
+ new_url, request(), GetRequestInfo()->GetContext(), response);
}
- DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
+ DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
// TODO(darin): It would be much better if this could live in WebCore, but
// doing so requires API changes at all levels. Similar code exists in
// WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-(
@@ -70,12 +72,16 @@ bool SyncResourceHandler::OnResponseStarted(
int request_id,
ResourceResponse* response,
bool* defer) {
+ const ResourceRequestInfoImpl* info = GetRequestInfo();
+ if (!info->filter())
+ return false;
+
if (rdh_->delegate()) {
rdh_->delegate()->OnResponseStarted(
- request_, resource_context_, response, filter_.get());
+ request(), info->GetContext(), response, info->filter());
}
- DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
+ DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
// We don't care about copying the status here.
result_.headers = response->head.headers;
@@ -95,8 +101,10 @@ bool SyncResourceHandler::OnWillStart(int request_id,
return true;
}
-bool SyncResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
- int* buf_size, int min_size) {
+bool SyncResourceHandler::OnWillRead(int request_id,
+ scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) {
DCHECK(min_size == -1);
*buf = read_buffer_.get();
*buf_size = kReadBufSize;
@@ -111,19 +119,24 @@ bool SyncResourceHandler::OnReadCompleted(int request_id, int bytes_read,
return true;
}
-bool SyncResourceHandler::OnResponseCompleted(
+void SyncResourceHandler::OnResponseCompleted(
int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) {
+ const std::string& security_info,
+ bool* defer) {
+ ResourceMessageFilter* filter = GetFilter();
+ if (!filter)
+ return;
+
result_.error_code = status.error();
result_.encoded_data_length =
- DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_);
+ DevToolsNetLogObserver::GetAndResetEncodedDataLength(request());
ResourceHostMsg_SyncLoad::WriteReplyParams(result_message_, result_);
- filter_->Send(result_message_);
+ filter->Send(result_message_);
result_message_ = NULL;
- return true;
+ return;
}
void SyncResourceHandler::OnDataDownloaded(
diff --git a/chromium/content/browser/loader/sync_resource_handler.h b/chromium/content/browser/loader/sync_resource_handler.h
index 838a05a225c..996393da0a3 100644
--- a/chromium/content/browser/loader/sync_resource_handler.h
+++ b/chromium/content/browser/loader/sync_resource_handler.h
@@ -28,9 +28,7 @@ class ResourceMessageFilter;
// events from the resource dispatcher host.
class SyncResourceHandler : public ResourceHandler {
public:
- SyncResourceHandler(ResourceMessageFilter* filter,
- ResourceContext* resource_context,
- net::URLRequest* request,
+ SyncResourceHandler(net::URLRequest* request,
IPC::Message* result_message,
ResourceDispatcherHostImpl* resource_dispatcher_host);
virtual ~SyncResourceHandler();
@@ -49,15 +47,16 @@ class SyncResourceHandler : public ResourceHandler {
const GURL& url,
bool* defer) OVERRIDE;
virtual bool OnWillRead(int request_id,
- net::IOBuffer** buf,
+ scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) OVERRIDE;
virtual bool OnReadCompleted(int request_id,
int bytes_read,
bool* defer) OVERRIDE;
- virtual bool OnResponseCompleted(int request_id,
+ virtual void OnResponseCompleted(int request_id,
const net::URLRequestStatus& status,
- const std::string& security_info) OVERRIDE;
+ const std::string& security_info,
+ bool* defer) OVERRIDE;
virtual void OnDataDownloaded(int request_id, int bytes_downloaded) OVERRIDE;
private:
@@ -66,9 +65,6 @@ class SyncResourceHandler : public ResourceHandler {
scoped_refptr<net::IOBuffer> read_buffer_;
SyncLoadResult result_;
- scoped_refptr<ResourceMessageFilter> filter_;
- ResourceContext* resource_context_;
- net::URLRequest* request_;
IPC::Message* result_message_;
ResourceDispatcherHostImpl* rdh_;
};
diff --git a/chromium/content/browser/loader/throttling_resource_handler.cc b/chromium/content/browser/loader/throttling_resource_handler.cc
index 5725e035a80..36c595fbf1b 100644
--- a/chromium/content/browser/loader/throttling_resource_handler.cc
+++ b/chromium/content/browser/loader/throttling_resource_handler.cc
@@ -4,24 +4,28 @@
#include "content/browser/loader/throttling_resource_handler.h"
+#include "content/browser/loader/resource_request_info_impl.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/common/resource_response.h"
+#include "net/url_request/url_request.h"
namespace content {
ThrottlingResourceHandler::ThrottlingResourceHandler(
scoped_ptr<ResourceHandler> next_handler,
- int child_id,
- int request_id,
+ net::URLRequest* request,
ScopedVector<ResourceThrottle> throttles)
- : LayeredResourceHandler(next_handler.Pass()),
+ : LayeredResourceHandler(request, next_handler.Pass()),
deferred_stage_(DEFERRED_NONE),
- request_id_(request_id),
throttles_(throttles.Pass()),
- index_(0),
+ next_index_(0),
cancelled_by_resource_throttle_(false) {
- for (size_t i = 0; i < throttles_.size(); ++i)
+ for (size_t i = 0; i < throttles_.size(); ++i) {
throttles_[i]->set_controller(this);
+ // Throttles must have a name, as otherwise, bugs where a throttle fails
+ // to resume a request can be very difficult to debug.
+ DCHECK(throttles_[i]->GetNameForLogging());
+ }
}
ThrottlingResourceHandler::~ThrottlingResourceHandler() {
@@ -31,16 +35,17 @@ bool ThrottlingResourceHandler::OnRequestRedirected(int request_id,
const GURL& new_url,
ResourceResponse* response,
bool* defer) {
- DCHECK_EQ(request_id_, request_id);
DCHECK(!cancelled_by_resource_throttle_);
*defer = false;
- while (index_ < throttles_.size()) {
- throttles_[index_]->WillRedirectRequest(new_url, defer);
- index_++;
+ while (next_index_ < throttles_.size()) {
+ int index = next_index_;
+ throttles_[index]->WillRedirectRequest(new_url, defer);
+ next_index_++;
if (cancelled_by_resource_throttle_)
return false;
if (*defer) {
+ OnRequestDefered(index);
deferred_stage_ = DEFERRED_REDIRECT;
deferred_url_ = new_url;
deferred_response_ = response;
@@ -48,7 +53,7 @@ bool ThrottlingResourceHandler::OnRequestRedirected(int request_id,
}
}
- index_ = 0; // Reset for next time.
+ next_index_ = 0; // Reset for next time.
return next_handler_->OnRequestRedirected(request_id, new_url, response,
defer);
@@ -57,23 +62,24 @@ bool ThrottlingResourceHandler::OnRequestRedirected(int request_id,
bool ThrottlingResourceHandler::OnWillStart(int request_id,
const GURL& url,
bool* defer) {
- DCHECK_EQ(request_id_, request_id);
DCHECK(!cancelled_by_resource_throttle_);
*defer = false;
- while (index_ < throttles_.size()) {
- throttles_[index_]->WillStartRequest(defer);
- index_++;
+ while (next_index_ < throttles_.size()) {
+ int index = next_index_;
+ throttles_[index]->WillStartRequest(defer);
+ next_index_++;
if (cancelled_by_resource_throttle_)
return false;
if (*defer) {
+ OnRequestDefered(index);
deferred_stage_ = DEFERRED_START;
deferred_url_ = url;
return true; // Do not cancel.
}
}
- index_ = 0; // Reset for next time.
+ next_index_ = 0; // Reset for next time.
return next_handler_->OnWillStart(request_id, url, defer);
}
@@ -81,22 +87,23 @@ bool ThrottlingResourceHandler::OnWillStart(int request_id,
bool ThrottlingResourceHandler::OnResponseStarted(int request_id,
ResourceResponse* response,
bool* defer) {
- DCHECK_EQ(request_id_, request_id);
DCHECK(!cancelled_by_resource_throttle_);
- while (index_ < throttles_.size()) {
- throttles_[index_]->WillProcessResponse(defer);
- index_++;
+ while (next_index_ < throttles_.size()) {
+ int index = next_index_;
+ throttles_[index]->WillProcessResponse(defer);
+ next_index_++;
if (cancelled_by_resource_throttle_)
return false;
if (*defer) {
+ OnRequestDefered(index);
deferred_stage_ = DEFERRED_RESPONSE;
deferred_response_ = response;
return true; // Do not cancel.
}
}
- index_ = 0; // Reset for next time.
+ next_index_ = 0; // Reset for next time.
return next_handler_->OnResponseStarted(request_id, response, defer);
}
@@ -121,6 +128,8 @@ void ThrottlingResourceHandler::Resume() {
DeferredStage last_deferred_stage = deferred_stage_;
deferred_stage_ = DEFERRED_NONE;
+ // Clear information about the throttle that delayed the request.
+ request()->LogUnblocked();
switch (last_deferred_stage) {
case DEFERRED_NONE:
NOTREACHED();
@@ -144,7 +153,7 @@ void ThrottlingResourceHandler::ResumeStart() {
deferred_url_ = GURL();
bool defer = false;
- if (!OnWillStart(request_id_, url, &defer)) {
+ if (!OnWillStart(GetRequestID(), url, &defer)) {
controller()->Cancel();
} else if (!defer) {
controller()->Resume();
@@ -160,7 +169,7 @@ void ThrottlingResourceHandler::ResumeRedirect() {
deferred_response_.swap(response);
bool defer = false;
- if (!OnRequestRedirected(request_id_, new_url, response.get(), &defer)) {
+ if (!OnRequestRedirected(GetRequestID(), new_url, response.get(), &defer)) {
controller()->Cancel();
} else if (!defer) {
controller()->Resume();
@@ -174,11 +183,15 @@ void ThrottlingResourceHandler::ResumeResponse() {
deferred_response_.swap(response);
bool defer = false;
- if (!OnResponseStarted(request_id_, response.get(), &defer)) {
+ if (!OnResponseStarted(GetRequestID(), response.get(), &defer)) {
controller()->Cancel();
} else if (!defer) {
controller()->Resume();
}
}
+void ThrottlingResourceHandler::OnRequestDefered(int throttle_index) {
+ request()->LogBlockedBy(throttles_[throttle_index]->GetNameForLogging());
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/throttling_resource_handler.h b/chromium/content/browser/loader/throttling_resource_handler.h
index 2661cdd7f3b..9f98921e26f 100644
--- a/chromium/content/browser/loader/throttling_resource_handler.h
+++ b/chromium/content/browser/loader/throttling_resource_handler.h
@@ -11,6 +11,10 @@
#include "content/public/browser/resource_controller.h"
#include "url/gurl.h"
+namespace net {
+class URLRequest;
+}
+
namespace content {
class ResourceThrottle;
@@ -22,8 +26,7 @@ class ThrottlingResourceHandler : public LayeredResourceHandler,
public:
// Takes ownership of the ResourceThrottle instances.
ThrottlingResourceHandler(scoped_ptr<ResourceHandler> next_handler,
- int child_id,
- int request_id,
+ net::URLRequest* request,
ScopedVector<ResourceThrottle> throttles);
virtual ~ThrottlingResourceHandler();
@@ -37,7 +40,7 @@ class ThrottlingResourceHandler : public LayeredResourceHandler,
virtual bool OnWillStart(int request_id, const GURL& url,
bool* defer) OVERRIDE;
- // ResourceThrottleController implementation:
+ // ResourceController implementation:
virtual void Cancel() OVERRIDE;
virtual void CancelAndIgnore() OVERRIDE;
virtual void CancelWithError(int error_code) OVERRIDE;
@@ -48,6 +51,10 @@ class ThrottlingResourceHandler : public LayeredResourceHandler,
void ResumeRedirect();
void ResumeResponse();
+ // Called when the throttle at |throttle_index| defers a request. Logs the
+ // name of the throttle that delayed the request.
+ void OnRequestDefered(int throttle_index);
+
enum DeferredStage {
DEFERRED_NONE,
DEFERRED_START,
@@ -56,10 +63,8 @@ class ThrottlingResourceHandler : public LayeredResourceHandler,
};
DeferredStage deferred_stage_;
- int request_id_;
-
ScopedVector<ResourceThrottle> throttles_;
- size_t index_;
+ size_t next_index_;
GURL deferred_url_;
scoped_refptr<ResourceResponse> deferred_response_;
diff --git a/chromium/content/browser/loader/transfer_navigation_resource_throttle.cc b/chromium/content/browser/loader/transfer_navigation_resource_throttle.cc
deleted file mode 100644
index 8021bce49d5..00000000000
--- a/chromium/content/browser/loader/transfer_navigation_resource_throttle.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/transfer_navigation_resource_throttle.h"
-
-#include "base/bind.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_delegate.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/global_request_id.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/resource_request_info.h"
-#include "content/public/common/referrer.h"
-#include "net/url_request/url_request.h"
-
-namespace content {
-
-namespace {
-
-void RequestTransferURLOnUIThread(int render_process_id,
- int render_view_id,
- const GURL& new_url,
- const Referrer& referrer,
- WindowOpenDisposition window_open_disposition,
- int64 frame_id,
- const GlobalRequestID& global_request_id) {
- RenderViewHost* rvh =
- RenderViewHost::FromID(render_process_id, render_view_id);
- if (!rvh)
- return;
-
- RenderViewHostDelegate* delegate = rvh->GetDelegate();
- if (!delegate)
- return;
-
- // We don't know whether the original request had |user_action| set to true.
- // However, since we force the navigation to be in the current tab, it doesn't
- // matter.
- delegate->RequestTransferURL(
- new_url, referrer, window_open_disposition,
- frame_id, global_request_id, false, true);
-}
-
-} // namespace
-
-TransferNavigationResourceThrottle::TransferNavigationResourceThrottle(
- net::URLRequest* request)
- : request_(request) {
-}
-
-TransferNavigationResourceThrottle::~TransferNavigationResourceThrottle() {
-}
-
-void TransferNavigationResourceThrottle::WillRedirectRequest(
- const GURL& new_url,
- bool* defer) {
- const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
-
- // If a toplevel request is redirecting across extension extents, we want to
- // switch processes. We do this by deferring the redirect and resuming the
- // request once the navigation controller properly assigns the right process
- // to host the new URL.
- // TODO(mpcomplete): handle for cases other than extensions (e.g. WebUI).
- ResourceContext* resource_context = info->GetContext();
- if (GetContentClient()->browser()->ShouldSwapProcessesForRedirect(
- resource_context, request_->url(), new_url)) {
- int render_process_id, render_view_id;
- if (info->GetAssociatedRenderView(&render_process_id, &render_view_id)) {
- GlobalRequestID global_id(info->GetChildID(), info->GetRequestID());
-
- ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(global_id,
- new_url);
-
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&RequestTransferURLOnUIThread,
- render_process_id,
- render_view_id,
- new_url,
- Referrer(GURL(request_->referrer()), info->GetReferrerPolicy()),
- CURRENT_TAB,
- info->GetFrameID(),
- global_id));
-
- *defer = true;
- }
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/transfer_navigation_resource_throttle.h b/chromium/content/browser/loader/transfer_navigation_resource_throttle.h
deleted file mode 100644
index 6d08c2aaed1..00000000000
--- a/chromium/content/browser/loader/transfer_navigation_resource_throttle.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_TRANSFER_NAVIGATION_RESOURCE_THROTTLE_H_
-#define CONTENT_BROWSER_LOADER_TRANSFER_NAVIGATION_RESOURCE_THROTTLE_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "content/public/browser/resource_throttle.h"
-
-namespace net {
-class URLRequest;
-}
-
-namespace content {
-
-// This ResourceThrottle checks whether a navigation redirect will cause a
-// renderer process swap. When that happens, we remember the request so
-// that we can transfer it to be handled by the new renderer. This fixes
-// http://crbug.com/79520
-class TransferNavigationResourceThrottle : public ResourceThrottle {
- public:
- explicit TransferNavigationResourceThrottle(net::URLRequest* request);
- virtual ~TransferNavigationResourceThrottle();
-
- // ResourceThrottle implementation:
- virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE;
-
- private:
- net::URLRequest* request_;
-
- DISALLOW_COPY_AND_ASSIGN(TransferNavigationResourceThrottle);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_TRANSFER_NAVIGATION_RESOURCE_THROTTLE_H_
diff --git a/chromium/content/browser/loader/upload_data_stream_builder.cc b/chromium/content/browser/loader/upload_data_stream_builder.cc
index c22a8a8d444..ba7cca77d25 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder.cc
@@ -70,11 +70,8 @@ void ResolveBlobReference(
const ResourceRequestBody::Element& element,
std::vector<const ResourceRequestBody::Element*>* resolved_elements) {
DCHECK(blob_context);
- std::string uuid = element.blob_uuid();
- if (uuid.empty())
- uuid = blob_context->LookupUuidFromDeprecatedURL(element.blob_url());
scoped_ptr<webkit_blob::BlobDataHandle> handle =
- blob_context->GetBlobDataFromUUID(uuid);
+ blob_context->GetBlobDataFromUUID(element.blob_uuid());
DCHECK(handle);
if (!handle)
return;
@@ -144,7 +141,7 @@ scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
}
return make_scoped_ptr(
- new net::UploadDataStream(&element_readers, body->identifier()));
+ new net::UploadDataStream(element_readers.Pass(), body->identifier()));
}
} // namespace content
diff --git a/chromium/content/browser/media/android/browser_demuxer_android.cc b/chromium/content/browser/media/android/browser_demuxer_android.cc
index 229b8858f1f..8480b14f98c 100644
--- a/chromium/content/browser/media/android/browser_demuxer_android.cc
+++ b/chromium/content/browser/media/android/browser_demuxer_android.cc
@@ -8,6 +8,55 @@
namespace content {
+class BrowserDemuxerAndroid::Internal : public media::DemuxerAndroid {
+ public:
+ Internal(const scoped_refptr<BrowserDemuxerAndroid>& demuxer,
+ int demuxer_client_id)
+ : demuxer_(demuxer),
+ demuxer_client_id_(demuxer_client_id) {}
+
+ virtual ~Internal() {
+ DCHECK(ClientIDExists()) << demuxer_client_id_;
+ demuxer_->RemoveDemuxerClient(demuxer_client_id_);
+ }
+
+ // media::DemuxerAndroid implementation.
+ virtual void Initialize(media::DemuxerAndroidClient* client) OVERRIDE {
+ DCHECK(!ClientIDExists()) << demuxer_client_id_;
+ demuxer_->AddDemuxerClient(demuxer_client_id_, client);
+ }
+
+ virtual void RequestDemuxerConfigs() OVERRIDE {
+ DCHECK(ClientIDExists()) << demuxer_client_id_;
+ demuxer_->Send(new MediaPlayerMsg_MediaConfigRequest(demuxer_client_id_));
+ }
+
+ virtual void RequestDemuxerData(media::DemuxerStream::Type type) OVERRIDE {
+ DCHECK(ClientIDExists()) << demuxer_client_id_;
+ demuxer_->Send(new MediaPlayerMsg_ReadFromDemuxer(
+ demuxer_client_id_, type));
+ }
+
+ virtual void RequestDemuxerSeek(
+ const base::TimeDelta& time_to_seek,
+ bool is_browser_seek) OVERRIDE {
+ DCHECK(ClientIDExists()) << demuxer_client_id_;
+ demuxer_->Send(new MediaPlayerMsg_DemuxerSeekRequest(
+ demuxer_client_id_, time_to_seek, is_browser_seek));
+ }
+
+ private:
+ // Helper for DCHECKing that the ID is still registered.
+ bool ClientIDExists() {
+ return demuxer_->demuxer_clients_.Lookup(demuxer_client_id_);
+ }
+
+ scoped_refptr<BrowserDemuxerAndroid> demuxer_;
+ int demuxer_client_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(Internal);
+};
+
BrowserDemuxerAndroid::BrowserDemuxerAndroid() {}
BrowserDemuxerAndroid::~BrowserDemuxerAndroid() {}
@@ -19,7 +68,7 @@ void BrowserDemuxerAndroid::OverrideThreadForMessage(
case MediaPlayerHostMsg_DemuxerReady::ID:
case MediaPlayerHostMsg_ReadFromDemuxerAck::ID:
case MediaPlayerHostMsg_DurationChanged::ID:
- case MediaPlayerHostMsg_MediaSeekRequestAck::ID:
+ case MediaPlayerHostMsg_DemuxerSeekDone::ID:
*thread = BrowserThread::UI;
return;
}
@@ -34,13 +83,19 @@ bool BrowserDemuxerAndroid::OnMessageReceived(const IPC::Message& message,
OnReadFromDemuxerAck)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DurationChanged,
OnDurationChanged)
- IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaSeekRequestAck,
- OnMediaSeekRequestAck)
+ IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DemuxerSeekDone,
+ OnDemuxerSeekDone)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
+scoped_ptr<media::DemuxerAndroid> BrowserDemuxerAndroid::CreateDemuxer(
+ int demuxer_client_id) {
+ return scoped_ptr<media::DemuxerAndroid>(
+ new Internal(this, demuxer_client_id));
+}
+
void BrowserDemuxerAndroid::AddDemuxerClient(
int demuxer_client_id,
media::DemuxerAndroidClient* client) {
@@ -55,25 +110,6 @@ void BrowserDemuxerAndroid::RemoveDemuxerClient(int demuxer_client_id) {
demuxer_clients_.Remove(demuxer_client_id);
}
-void BrowserDemuxerAndroid::RequestDemuxerData(
- int demuxer_client_id, media::DemuxerStream::Type type) {
- DCHECK(demuxer_clients_.Lookup(demuxer_client_id)) << demuxer_client_id;
- Send(new MediaPlayerMsg_ReadFromDemuxer(demuxer_client_id, type));
-}
-
-void BrowserDemuxerAndroid::RequestDemuxerSeek(int demuxer_client_id,
- base::TimeDelta time_to_seek,
- unsigned seek_request_id) {
- DCHECK(demuxer_clients_.Lookup(demuxer_client_id)) << demuxer_client_id;
- Send(new MediaPlayerMsg_MediaSeekRequest(
- demuxer_client_id, time_to_seek, seek_request_id));
-}
-
-void BrowserDemuxerAndroid::RequestDemuxerConfigs(int demuxer_client_id) {
- DCHECK(demuxer_clients_.Lookup(demuxer_client_id)) << demuxer_client_id;
- Send(new MediaPlayerMsg_MediaConfigRequest(demuxer_client_id));
-}
-
void BrowserDemuxerAndroid::OnDemuxerReady(
int demuxer_client_id,
const media::DemuxerConfigs& configs) {
@@ -92,12 +128,13 @@ void BrowserDemuxerAndroid::OnReadFromDemuxerAck(
client->OnDemuxerDataAvailable(data);
}
-void BrowserDemuxerAndroid::OnMediaSeekRequestAck(int demuxer_client_id,
- unsigned seek_request_id) {
+void BrowserDemuxerAndroid::OnDemuxerSeekDone(
+ int demuxer_client_id,
+ const base::TimeDelta& actual_browser_seek_time) {
media::DemuxerAndroidClient* client =
demuxer_clients_.Lookup(demuxer_client_id);
if (client)
- client->OnDemuxerSeeked(seek_request_id);
+ client->OnDemuxerSeekDone(actual_browser_seek_time);
}
void BrowserDemuxerAndroid::OnDurationChanged(int demuxer_client_id,
diff --git a/chromium/content/browser/media/android/browser_demuxer_android.h b/chromium/content/browser/media/android/browser_demuxer_android.h
index 6d17428f2d9..76018313cb7 100644
--- a/chromium/content/browser/media/android/browser_demuxer_android.h
+++ b/chromium/content/browser/media/android/browser_demuxer_android.h
@@ -11,13 +11,12 @@
namespace content {
-// Represents the browser process half of an IPC-based implementation of
-// media::DemuxerAndroid.
+// Represents the browser process half of an IPC-based demuxer proxy.
+// It vends out media::DemuxerAndroid instances that are registered with an
+// end point in the renderer process.
//
// Refer to RendererDemuxerAndroid for the renderer process half.
-class CONTENT_EXPORT BrowserDemuxerAndroid
- : public BrowserMessageFilter,
- public media::DemuxerAndroid {
+class CONTENT_EXPORT BrowserDemuxerAndroid : public BrowserMessageFilter {
public:
BrowserDemuxerAndroid();
@@ -27,27 +26,31 @@ class CONTENT_EXPORT BrowserDemuxerAndroid
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) OVERRIDE;
- // media::DemuxerAndroid implementation.
- virtual void AddDemuxerClient(int demuxer_client_id,
- media::DemuxerAndroidClient* client) OVERRIDE;
- virtual void RemoveDemuxerClient(int demuxer_client_id) OVERRIDE;
- virtual void RequestDemuxerConfigs(int demuxer_client_id) OVERRIDE;
- virtual void RequestDemuxerData(int demuxer_client_id,
- media::DemuxerStream::Type type) OVERRIDE;
- virtual void RequestDemuxerSeek(int demuxer_client_id,
- base::TimeDelta time_to_seek,
- unsigned seek_request_id) OVERRIDE;
+ // Returns an uninitialized demuxer implementation associated with
+ // |demuxer_client_id|, which can be used to communicate with the real demuxer
+ // in the renderer process.
+ scoped_ptr<media::DemuxerAndroid> CreateDemuxer(int demuxer_client_id);
protected:
friend class base::RefCountedThreadSafe<BrowserDemuxerAndroid>;
virtual ~BrowserDemuxerAndroid();
private:
+ class Internal;
+
+ // Called by internal demuxer implementations to add/remove a client
+ // association.
+ void AddDemuxerClient(int demuxer_client_id,
+ media::DemuxerAndroidClient* client);
+ void RemoveDemuxerClient(int demuxer_client_id);
+
+ // IPC message handlers.
void OnDemuxerReady(int demuxer_client_id,
const media::DemuxerConfigs& configs);
void OnReadFromDemuxerAck(int demuxer_client_id,
const media::DemuxerData& data);
- void OnMediaSeekRequestAck(int demuxer_client_id, unsigned seek_request_id);
+ void OnDemuxerSeekDone(int demuxer_client_id,
+ const base::TimeDelta& actual_browser_seek_time);
void OnDurationChanged(int demuxer_client_id,
const base::TimeDelta& duration);
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 f0129c13b24..43b93da7fc3 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.cc
+++ b/chromium/content/browser/media/android/browser_media_player_manager.cc
@@ -11,12 +11,14 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_view_android.h"
#include "content/common/media/media_player_messages_android.h"
+#include "content/public/browser/android/content_view_core.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/common/content_switches.h"
#include "media/base/android/media_drm_bridge.h"
#include "media/base/android/media_player_bridge.h"
#include "media/base/android/media_source_player.h"
@@ -32,6 +34,14 @@ using media::MediaSourcePlayer;
// attempting to release inactive media players.
static const int kMediaPlayerThreshold = 1;
+// Maximum sizes for various EME message parameters. These are checks to
+// prevent unnecessarily large messages from being passed around, and the sizes
+// are somewhat arbitrary as the EME specification doesn't specify any limits.
+static const size_t kEmeUuidSize = 16;
+static const size_t kEmeTypeMaximum = 50; // Type is a MIME type.
+static const size_t kEmeInitDataMaximum = 10240; // 10 KB
+static const size_t kEmeResponseMaximum = 10240; // 10 KB
+
namespace content {
static BrowserMediaPlayerManager::Factory g_factory = NULL;
@@ -59,18 +69,32 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
int demuxer_client_id,
bool hide_url_log,
MediaPlayerManager* manager,
- media::DemuxerAndroid* demuxer) {
+ BrowserDemuxerAndroid* demuxer) {
switch (type) {
case MEDIA_PLAYER_TYPE_URL: {
MediaPlayerBridge* media_player_bridge = new MediaPlayerBridge(
player_id, url, first_party_for_cookies, hide_url_log, manager);
- media_player_bridge->Initialize();
+ BrowserMediaPlayerManager* browser_media_player_manager =
+ static_cast<BrowserMediaPlayerManager*>(manager);
+ ContentViewCoreImpl* content_view_core_impl =
+ static_cast<ContentViewCoreImpl*>(ContentViewCore::FromWebContents(
+ browser_media_player_manager->web_contents_));
+ if (!content_view_core_impl) {
+ // May reach here due to prerendering. Don't extract the metadata
+ // since it is expensive.
+ // TODO(qinmin): extract the metadata once the user decided to load
+ // the page.
+ browser_media_player_manager->OnMediaMetadataChanged(
+ player_id, base::TimeDelta(), 0, 0, false);
+ } else if (!content_view_core_impl->ShouldBlockMediaRequest(url)) {
+ media_player_bridge->Initialize();
+ }
return media_player_bridge;
}
case MEDIA_PLAYER_TYPE_MEDIA_SOURCE: {
return new MediaSourcePlayer(
- player_id, manager, demuxer_client_id, demuxer);
+ player_id, manager, demuxer->CreateDemuxer(demuxer_client_id));
}
}
@@ -81,8 +105,10 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
BrowserMediaPlayerManager::BrowserMediaPlayerManager(
RenderViewHost* render_view_host)
- : RenderViewHostObserver(render_view_host),
+ : WebContentsObserver(WebContents::FromRenderViewHost(render_view_host)),
fullscreen_player_id_(-1),
+ pending_fullscreen_player_id_(-1),
+ fullscreen_player_is_released_(false),
web_contents_(WebContents::FromRenderViewHost(render_view_host)),
weak_ptr_factory_(this) {
}
@@ -105,15 +131,13 @@ bool BrowserMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
DestroyAllMediaPlayers)
IPC_MESSAGE_HANDLER(MediaKeysHostMsg_InitializeCDM,
OnInitializeCDM)
- IPC_MESSAGE_HANDLER(MediaKeysHostMsg_GenerateKeyRequest,
- OnGenerateKeyRequest)
- IPC_MESSAGE_HANDLER(MediaKeysHostMsg_AddKey, OnAddKey)
- IPC_MESSAGE_HANDLER(MediaKeysHostMsg_CancelKeyRequest,
- OnCancelKeyRequest)
-#if defined(GOOGLE_TV)
+ IPC_MESSAGE_HANDLER(MediaKeysHostMsg_CreateSession, OnCreateSession)
+ IPC_MESSAGE_HANDLER(MediaKeysHostMsg_UpdateSession, OnUpdateSession)
+ IPC_MESSAGE_HANDLER(MediaKeysHostMsg_ReleaseSession, OnReleaseSession)
+#if defined(VIDEO_HOLE)
IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_NotifyExternalSurface,
OnNotifyExternalSurface)
-#endif
+#endif // defined(VIDEO_HOLE)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -122,6 +146,10 @@ bool BrowserMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
void BrowserMediaPlayerManager::FullscreenPlayerPlay() {
MediaPlayerAndroid* player = GetFullscreenPlayer();
if (player) {
+ if (fullscreen_player_is_released_) {
+ video_view_->OpenVideo();
+ fullscreen_player_is_released_ = false;
+ }
player->Start();
Send(new MediaPlayerMsg_DidMediaPlayerPlay(
routing_id(), fullscreen_player_id_));
@@ -139,8 +167,13 @@ void BrowserMediaPlayerManager::FullscreenPlayerPause() {
void BrowserMediaPlayerManager::FullscreenPlayerSeek(int msec) {
MediaPlayerAndroid* player = GetFullscreenPlayer();
- if (player)
- player->SeekTo(base::TimeDelta::FromMilliseconds(msec));
+ if (player) {
+ // TODO(kbalazs): if |fullscreen_player_is_released_| is true
+ // at this point, player->GetCurrentTime() will be wrong until
+ // FullscreenPlayerPlay (http://crbug.com/322798).
+ OnSeekRequest(fullscreen_player_id_,
+ base::TimeDelta::FromMilliseconds(msec));
+ }
}
void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player) {
@@ -166,11 +199,13 @@ void BrowserMediaPlayerManager::OnTimeUpdate(int player_id,
void BrowserMediaPlayerManager::SetVideoSurface(
gfx::ScopedJavaSurface surface) {
MediaPlayerAndroid* player = GetFullscreenPlayer();
- if (player) {
- player->SetVideoSurface(surface.Pass());
- Send(new MediaPlayerMsg_DidEnterFullscreen(
- routing_id(), player->player_id()));
+ if (!player)
+ return;
+ if (!surface.IsEmpty()) {
+ Send(new MediaPlayerMsg_DidEnterFullscreen(routing_id(),
+ player->player_id()));
}
+ player->SetVideoSurface(surface.Pass());
}
void BrowserMediaPlayerManager::OnMediaMetadataChanged(
@@ -178,13 +213,13 @@ void BrowserMediaPlayerManager::OnMediaMetadataChanged(
bool success) {
Send(new MediaPlayerMsg_MediaMetadataChanged(
routing_id(), player_id, duration, width, height, success));
- if (fullscreen_player_id_ != -1)
+ if (fullscreen_player_id_ == player_id)
video_view_->UpdateMediaMetadata();
}
void BrowserMediaPlayerManager::OnPlaybackComplete(int player_id) {
Send(new MediaPlayerMsg_MediaPlaybackCompleted(routing_id(), player_id));
- if (fullscreen_player_id_ != -1)
+ if (fullscreen_player_id_ == player_id)
video_view_->OnPlaybackComplete();
}
@@ -198,19 +233,25 @@ void BrowserMediaPlayerManager::OnBufferingUpdate(
int player_id, int percentage) {
Send(new MediaPlayerMsg_MediaBufferingUpdate(
routing_id(), player_id, percentage));
- if (fullscreen_player_id_ != -1)
+ if (fullscreen_player_id_ == player_id)
video_view_->OnBufferingUpdate(percentage);
}
-void BrowserMediaPlayerManager::OnSeekComplete(int player_id,
- base::TimeDelta current_time) {
- Send(new MediaPlayerMsg_MediaSeekCompleted(
- routing_id(), player_id, current_time));
+void BrowserMediaPlayerManager::OnSeekRequest(
+ int player_id,
+ const base::TimeDelta& time_to_seek) {
+ Send(new MediaPlayerMsg_SeekRequest(routing_id(), player_id, time_to_seek));
+}
+
+void BrowserMediaPlayerManager::OnSeekComplete(
+ int player_id,
+ const base::TimeDelta& current_time) {
+ Send(new MediaPlayerMsg_SeekCompleted(routing_id(), player_id, current_time));
}
void BrowserMediaPlayerManager::OnError(int player_id, int error) {
Send(new MediaPlayerMsg_MediaError(routing_id(), player_id, error));
- if (fullscreen_player_id_ != -1)
+ if (fullscreen_player_id_ == player_id)
video_view_->OnMediaPlayerError(error);
}
@@ -218,7 +259,7 @@ void BrowserMediaPlayerManager::OnVideoSizeChanged(
int player_id, int width, int height) {
Send(new MediaPlayerMsg_MediaVideoSizeChanged(routing_id(), player_id,
width, height));
- if (fullscreen_player_id_ != -1)
+ if (fullscreen_player_id_ == player_id)
video_view_->OnVideoSizeChanged(width, height);
}
@@ -257,7 +298,7 @@ void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id) {
media::MediaResourceGetter*
BrowserMediaPlayerManager::GetMediaResourceGetter() {
if (!media_resource_getter_.get()) {
- RenderProcessHost* host = render_view_host()->GetProcess();
+ RenderProcessHost* host = web_contents()->GetRenderProcessHost();
BrowserContext* context = host->GetBrowserContext();
StoragePartition* partition = host->GetStoragePartition();
fileapi::FileSystemContext* file_system_context =
@@ -302,38 +343,73 @@ void BrowserMediaPlayerManager::DestroyAllMediaPlayers() {
void BrowserMediaPlayerManager::OnProtectedSurfaceRequested(int player_id) {
if (fullscreen_player_id_ == player_id)
return;
+
if (fullscreen_player_id_ != -1) {
// TODO(qinmin): Determine the correct error code we should report to WMPA.
OnError(player_id, MediaPlayerAndroid::MEDIA_ERROR_DECODE);
return;
}
- OnEnterFullscreen(player_id);
-}
-void BrowserMediaPlayerManager::OnKeyAdded(int media_keys_id,
- const std::string& session_id) {
- Send(new MediaKeysMsg_KeyAdded(routing_id(), media_keys_id, session_id));
+ // If the player is pending approval, wait for the approval to happen.
+ if (media_keys_ids_pending_approval_.end() !=
+ media_keys_ids_pending_approval_.find(player_id)) {
+ pending_fullscreen_player_id_ = player_id;
+ return;
+ }
+
+ // Send an IPC to the render process to request the video element to enter
+ // fullscreen. OnEnterFullscreen() will be called later on success.
+ // This guarantees the fullscreen video will be rendered correctly.
+ // During the process, DisableFullscreenEncryptedMediaPlayback() may get
+ // called before or after OnEnterFullscreen(). If it is called before
+ // OnEnterFullscreen(), the player will not enter fullscreen. And it will
+ // retry the process once CreateSession() is allowed to proceed.
+ // TODO(qinmin): make this flag default on android.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGestureRequirementForMediaFullscreen)) {
+ Send(new MediaPlayerMsg_RequestFullscreen(routing_id(), player_id));
+ }
}
-void BrowserMediaPlayerManager::OnKeyError(
+// The following 5 functions are EME MediaKeySession events.
+
+void BrowserMediaPlayerManager::OnSessionCreated(
int media_keys_id,
- const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- int system_code) {
- Send(new MediaKeysMsg_KeyError(routing_id(), media_keys_id,
- session_id, error_code, system_code));
+ uint32 session_id,
+ const std::string& web_session_id) {
+ Send(new MediaKeysMsg_SessionCreated(
+ routing_id(), media_keys_id, session_id, web_session_id));
}
-void BrowserMediaPlayerManager::OnKeyMessage(
+void BrowserMediaPlayerManager::OnSessionMessage(
int media_keys_id,
- const std::string& session_id,
+ uint32 session_id,
const std::vector<uint8>& message,
const std::string& destination_url) {
- Send(new MediaKeysMsg_KeyMessage(routing_id(), media_keys_id,
- session_id, message, destination_url));
+ Send(new MediaKeysMsg_SessionMessage(
+ routing_id(), media_keys_id, session_id, message, destination_url));
+}
+
+void BrowserMediaPlayerManager::OnSessionReady(int media_keys_id,
+ uint32 session_id) {
+ Send(new MediaKeysMsg_SessionReady(routing_id(), media_keys_id, session_id));
+}
+
+void BrowserMediaPlayerManager::OnSessionClosed(int media_keys_id,
+ uint32 session_id) {
+ Send(new MediaKeysMsg_SessionClosed(routing_id(), media_keys_id, session_id));
+}
+
+void BrowserMediaPlayerManager::OnSessionError(
+ int media_keys_id,
+ uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code) {
+ Send(new MediaKeysMsg_SessionError(
+ routing_id(), media_keys_id, session_id, error_code, system_code));
}
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id,
jobject surface) {
MediaPlayerAndroid* player = GetPlayer(player_id);
@@ -359,10 +435,28 @@ void BrowserMediaPlayerManager::OnNotifyExternalSurface(
if (view)
view->NotifyExternalSurface(player_id, is_request, rect);
}
-#endif
+#endif // defined(VIDEO_HOLE)
+
+void BrowserMediaPlayerManager::DisableFullscreenEncryptedMediaPlayback() {
+ if (fullscreen_player_id_ == -1)
+ return;
+
+ // If the fullscreen player is not playing back encrypted video, do nothing.
+ MediaDrmBridge* drm_bridge = GetDrmBridge(fullscreen_player_id_);
+ if (!drm_bridge)
+ return;
+
+ // Exit fullscreen.
+ pending_fullscreen_player_id_ = fullscreen_player_id_;
+ OnExitFullscreen(fullscreen_player_id_);
+}
void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) {
DCHECK_EQ(fullscreen_player_id_, -1);
+ if (media_keys_ids_pending_approval_.find(player_id) !=
+ media_keys_ids_pending_approval_.end()) {
+ return;
+ }
if (video_view_.get()) {
fullscreen_player_id_ = player_id;
@@ -371,10 +465,8 @@ void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) {
// In Android WebView, two ContentViewCores could both try to enter
// fullscreen video, we just ignore the second one.
fullscreen_player_id_ = player_id;
- WebContents* web_contents =
- WebContents::FromRenderViewHost(render_view_host());
ContentViewCoreImpl* content_view_core_impl =
- ContentViewCoreImpl::FromWebContents(web_contents);
+ ContentViewCoreImpl::FromWebContents(web_contents());
video_view_.reset(new ContentVideoView(content_view_core_impl->GetContext(),
content_view_core_impl->GetContentVideoViewClient(), this));
}
@@ -401,8 +493,8 @@ void BrowserMediaPlayerManager::OnInitialize(
RemovePlayer(player_id);
- RenderProcessHostImpl* host =
- static_cast<RenderProcessHostImpl*>(render_view_host()->GetProcess());
+ RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
+ web_contents()->GetRenderProcessHost());
AddPlayer(CreateMediaPlayer(
type, player_id, url, first_party_for_cookies, demuxer_client_id,
host->GetBrowserContext()->IsOffTheRecord(), this,
@@ -415,7 +507,9 @@ void BrowserMediaPlayerManager::OnStart(int player_id) {
player->Start();
}
-void BrowserMediaPlayerManager::OnSeek(int player_id, base::TimeDelta time) {
+void BrowserMediaPlayerManager::OnSeek(
+ int player_id,
+ const base::TimeDelta& time) {
MediaPlayerAndroid* player = GetPlayer(player_id);
if (player)
player->SeekTo(time);
@@ -437,18 +531,17 @@ void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
void BrowserMediaPlayerManager::OnReleaseResources(int player_id) {
MediaPlayerAndroid* player = GetPlayer(player_id);
- // Don't release the fullscreen player when tab visibility changes,
- // it will be released when user hit the back/home button or when
- // OnDestroyPlayer is called.
- if (player && player_id != fullscreen_player_id_)
+ if (player)
player->Release();
+ if (player_id == fullscreen_player_id_)
+ fullscreen_player_is_released_ = true;
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
WebContentsViewAndroid* view =
static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
if (view)
view->NotifyExternalSurface(player_id, false, gfx::RectF());
-#endif
+#endif // defined(VIDEO_HOLE)
}
void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
@@ -461,54 +554,85 @@ void BrowserMediaPlayerManager::OnInitializeCDM(
int media_keys_id,
const std::vector<uint8>& uuid,
const GURL& frame_url) {
+ if (uuid.size() != kEmeUuidSize) {
+ // This failure will be discovered and reported by OnCreateSession()
+ // as GetDrmBridge() will return null.
+ NOTREACHED() << "Invalid UUID for ID: " << media_keys_id;
+ return;
+ }
+
AddDrmBridge(media_keys_id, uuid, frame_url);
// In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id|
// is the same as the |player_id|.
OnSetMediaKeys(media_keys_id, media_keys_id);
}
-void BrowserMediaPlayerManager::OnGenerateKeyRequest(
+void BrowserMediaPlayerManager::OnCreateSession(
int media_keys_id,
+ uint32 session_id,
const std::string& type,
const std::vector<uint8>& init_data) {
+ if (type.length() > kEmeTypeMaximum) {
+ OnSessionError(
+ media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
+ return;
+ }
+ if (init_data.size() > kEmeInitDataMaximum) {
+ OnSessionError(
+ media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
+ return;
+ }
+
if (CommandLine::ForCurrentProcess()
->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier)) {
- GenerateKeyIfAllowed(media_keys_id, type, init_data, true);
+ GenerateKeyIfAllowed(media_keys_id, session_id, type, init_data, true);
return;
}
MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
if (!drm_bridge) {
DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
- OnKeyError(media_keys_id, "", media::MediaKeys::kUnknownError, 0);
+ OnSessionError(
+ media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
return;
}
- WebContents* web_contents =
- WebContents::FromRenderViewHost(render_view_host());
- web_contents->GetDelegate()->RequestProtectedMediaIdentifierPermission(
- web_contents,
+ if (media_keys_ids_approved_.find(media_keys_id) ==
+ media_keys_ids_approved_.end()) {
+ media_keys_ids_pending_approval_.insert(media_keys_id);
+ }
+ web_contents()->GetDelegate()->RequestProtectedMediaIdentifierPermission(
+ web_contents(),
drm_bridge->frame_url(),
base::Bind(&BrowserMediaPlayerManager::GenerateKeyIfAllowed,
weak_ptr_factory_.GetWeakPtr(),
media_keys_id,
+ session_id,
type,
init_data));
}
-void BrowserMediaPlayerManager::OnAddKey(int media_keys_id,
- const std::vector<uint8>& key,
- const std::vector<uint8>& init_data,
- const std::string& session_id) {
+void BrowserMediaPlayerManager::OnUpdateSession(
+ int media_keys_id,
+ uint32 session_id,
+ const std::vector<uint8>& response) {
MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
if (!drm_bridge) {
DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
- OnKeyError(media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
+ OnSessionError(
+ media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
return;
}
- drm_bridge->AddKey(&key[0], key.size(), &init_data[0], init_data.size(),
- session_id);
+ if (response.size() > kEmeResponseMaximum) {
+ DLOG(WARNING) << "Response for ID: " << media_keys_id
+ << " too long: " << response.size();
+ OnSessionError(
+ media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
+ return;
+ }
+
+ drm_bridge->UpdateSession(session_id, &response[0], response.size());
// In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id|
// is the same as the |player_id|.
// TODO(xhwang): Separate |media_keys_id| and |player_id|.
@@ -517,28 +641,37 @@ void BrowserMediaPlayerManager::OnAddKey(int media_keys_id,
player->OnKeyAdded();
}
-void BrowserMediaPlayerManager::OnCancelKeyRequest(
- int media_keys_id,
- const std::string& session_id) {
+void BrowserMediaPlayerManager::OnReleaseSession(int media_keys_id,
+ uint32 session_id) {
MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
if (!drm_bridge) {
DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
- OnKeyError(media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
+ OnSessionError(
+ media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
return;
}
- drm_bridge->CancelKeyRequest(session_id);
+ drm_bridge->ReleaseSession(session_id);
}
void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
DCHECK(!GetPlayer(player->player_id()));
players_.push_back(player);
+ if (player->IsRemote()) {
+ Send(new MediaPlayerMsg_ConnectedToRemoteDevice(routing_id(),
+ player->player_id()));
+ }
}
void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
it != players_.end(); ++it) {
- if ((*it)->player_id() == player_id) {
+ MediaPlayerAndroid* player = *it;
+ if (player->player_id() == player_id) {
+ if (player->IsRemote()) {
+ Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(
+ routing_id(), player->player_id()));
+ }
players_.erase(it);
break;
}
@@ -554,6 +687,13 @@ scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
previous_player = *it;
players_.weak_erase(it);
players_.push_back(player);
+ if (!previous_player->IsRemote() && player->IsRemote()) {
+ Send(new MediaPlayerMsg_ConnectedToRemoteDevice(
+ routing_id(), player->player_id()));
+ } else if (previous_player->IsRemote() && !player->IsRemote()) {
+ Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(
+ routing_id(), player->player_id()));
+ }
break;
}
}
@@ -574,8 +714,9 @@ void BrowserMediaPlayerManager::AddDrmBridge(int media_keys_id,
scoped_ptr<MediaDrmBridge> drm_bridge(MediaDrmBridge::Create(
media_keys_id, uuid, frame_url, security_level, this));
if (!drm_bridge) {
+ // This failure will be discovered and reported by OnCreateSession()
+ // as GetDrmBridge() will return null.
DVLOG(1) << "failed to create drm bridge.";
- OnKeyError(media_keys_id, "", media::MediaKeys::kUnknownError, 0);
return;
}
@@ -607,6 +748,7 @@ void BrowserMediaPlayerManager::OnSetMediaKeys(int player_id,
void BrowserMediaPlayerManager::GenerateKeyIfAllowed(
int media_keys_id,
+ uint32 session_id,
const std::string& type,
const std::vector<uint8>& init_data,
bool allowed) {
@@ -616,11 +758,23 @@ void BrowserMediaPlayerManager::GenerateKeyIfAllowed(
MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
if (!drm_bridge) {
DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found";
- OnKeyError(media_keys_id, "", media::MediaKeys::kUnknownError, 0);
+ OnSessionError(
+ media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
return;
}
+ media_keys_ids_pending_approval_.erase(media_keys_id);
+ media_keys_ids_approved_.insert(media_keys_id);
+ drm_bridge->CreateSession(session_id, type, &init_data[0], init_data.size());
+
+ // TODO(qinmin): currently |media_keys_id| and player ID are identical.
+ // This might not be true in the future.
+ if (pending_fullscreen_player_id_ != media_keys_id)
+ return;
- drm_bridge->GenerateKeyRequest(type, &init_data[0], init_data.size());
+ pending_fullscreen_player_id_ = -1;
+ MediaPlayerAndroid* player = GetPlayer(media_keys_id);
+ if (player->IsPlaying())
+ OnProtectedSurfaceRequested(media_keys_id);
}
} // namespace content
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 a26e1829cf8..d407e7e56a8 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.h
+++ b/chromium/content/browser/media/android/browser_media_player_manager.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
#include <map>
+#include <set>
#include <string>
#include <vector>
@@ -16,7 +17,7 @@
#include "base/time/time.h"
#include "content/browser/android/content_video_view.h"
#include "content/common/media/media_player_messages_enums_android.h"
-#include "content/public/browser/render_view_host_observer.h"
+#include "content/public/browser/web_contents_observer.h"
#include "media/base/android/media_player_android.h"
#include "media/base/android/media_player_manager.h"
#include "ui/gfx/rect_f.h"
@@ -28,7 +29,7 @@ class MediaDrmBridge;
}
namespace content {
-
+class BrowserDemuxerAndroid;
class WebContents;
// This class manages all the MediaPlayerAndroid objects. It receives
@@ -37,7 +38,7 @@ class WebContents;
// MediaPlayerAndroid objects are converted to IPCs and then sent to the
// render process.
class CONTENT_EXPORT BrowserMediaPlayerManager
- : public RenderViewHostObserver,
+ : public WebContentsObserver,
public media::MediaPlayerManager {
public:
// Permits embedders to provide an extended version of the class.
@@ -49,7 +50,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
virtual ~BrowserMediaPlayerManager();
- // RenderViewHostObserver overrides.
+ // WebContentsObserver overrides.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
// Fullscreen video playback controls.
@@ -59,6 +60,10 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
virtual void ExitFullscreen(bool release_media_player);
virtual void SetVideoSurface(gfx::ScopedJavaSurface surface);
+ // Called when browser player wants the renderer media element to seek.
+ // Any actual seek started by renderer will be handled by browser in OnSeek().
+ void OnSeekRequest(int player_id, const base::TimeDelta& time_to_seek);
+
// media::MediaPlayerManager overrides.
virtual void OnTimeUpdate(
int player_id, base::TimeDelta current_time) OVERRIDE;
@@ -72,7 +77,8 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
virtual void OnMediaInterrupted(int player_id) OVERRIDE;
virtual void OnBufferingUpdate(int player_id, int percentage) OVERRIDE;
virtual void OnSeekComplete(
- int player_id, base::TimeDelta current_time) OVERRIDE;
+ int player_id,
+ const base::TimeDelta& current_time) OVERRIDE;
virtual void OnError(int player_id, int error) OVERRIDE;
virtual void OnVideoSizeChanged(
int player_id, int width, int height) OVERRIDE;
@@ -84,21 +90,28 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
virtual media::MediaDrmBridge* GetDrmBridge(int media_keys_id) OVERRIDE;
virtual void DestroyAllMediaPlayers() OVERRIDE;
virtual void OnProtectedSurfaceRequested(int player_id) OVERRIDE;
- virtual void OnKeyAdded(int media_keys_id,
- const std::string& session_id) OVERRIDE;
- virtual void OnKeyError(int media_keys_id,
- const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- int system_code) OVERRIDE;
- virtual void OnKeyMessage(int media_keys_id,
- const std::string& session_id,
- const std::vector<uint8>& message,
- const std::string& destination_url) OVERRIDE;
-
-#if defined(GOOGLE_TV)
+ virtual void OnSessionCreated(int media_keys_id,
+ uint32 session_id,
+ const std::string& web_session_id) OVERRIDE;
+ virtual void OnSessionMessage(int media_keys_id,
+ uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url) OVERRIDE;
+ virtual void OnSessionReady(int media_keys_id, uint32 session_id) OVERRIDE;
+ virtual void OnSessionClosed(int media_keys_id, uint32 session_id) OVERRIDE;
+ virtual void OnSessionError(int media_keys_id,
+ uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code) OVERRIDE;
+
+#if defined(VIDEO_HOLE)
void AttachExternalVideoSurface(int player_id, jobject surface);
void DetachExternalVideoSurface(int player_id);
-#endif
+#endif // defined(VIDEO_HOLE)
+
+ // Called to disble the current fullscreen playback if the video is encrypted.
+ // TODO(qinmin): remove this once we have the new fullscreen mode.
+ void DisableFullscreenEncryptedMediaPlayback();
protected:
// Clients must use Create() or subclass constructor.
@@ -114,7 +127,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
const GURL& first_party_for_cookies,
int demuxer_client_id);
virtual void OnStart(int player_id);
- virtual void OnSeek(int player_id, base::TimeDelta time);
+ virtual void OnSeek(int player_id, const base::TimeDelta& time);
virtual void OnPause(int player_id, bool is_media_related_action);
virtual void OnSetVolume(int player_id, double volume);
virtual void OnReleaseResources(int player_id);
@@ -122,20 +135,20 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
void OnInitializeCDM(int media_keys_id,
const std::vector<uint8>& uuid,
const GURL& frame_url);
- void OnGenerateKeyRequest(int media_keys_id,
- const std::string& type,
- const std::vector<uint8>& init_data);
- void OnAddKey(int media_keys_id,
- const std::vector<uint8>& key,
- const std::vector<uint8>& init_data,
- const std::string& session_id);
- void OnCancelKeyRequest(int media_keys_id, const std::string& session_id);
+ void OnCreateSession(int media_keys_id,
+ uint32 session_id,
+ const std::string& type,
+ const std::vector<uint8>& init_data);
+ void OnUpdateSession(int media_keys_id,
+ uint32 session_id,
+ const std::vector<uint8>& response);
+ void OnReleaseSession(int media_keys_id, uint32 session_id);
void OnSetMediaKeys(int player_id, int media_keys_id);
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
virtual void OnNotifyExternalSurface(
int player_id, bool is_request, const gfx::RectF& rect);
-#endif
+#endif // defined(VIDEO_HOLE)
// Adds a given player to the list.
void AddPlayer(media::MediaPlayerAndroid* player);
@@ -150,7 +163,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
int player_id,
media::MediaPlayerAndroid* player);
- // Add a new MediaDrmBridge for the given |uuid|, |media_keys_id|, and
+ // Adds a new MediaDrmBridge for the given |uuid|, |media_keys_id|, and
// |frame_url|.
void AddDrmBridge(int media_keys_id,
const std::vector<uint8>& uuid,
@@ -161,6 +174,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
private:
void GenerateKeyIfAllowed(int media_keys_id,
+ uint32 session_id,
const std::string& type,
const std::vector<uint8>& init_data,
bool allowed);
@@ -180,7 +194,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
int demuxer_client_id,
bool hide_url_log,
media::MediaPlayerManager* manager,
- media::DemuxerAndroid* demuxer);
+ BrowserDemuxerAndroid* demuxer);
// An array of managed players.
ScopedVector<media::MediaPlayerAndroid> players_;
@@ -188,6 +202,13 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// An array of managed media DRM bridges.
ScopedVector<media::MediaDrmBridge> drm_bridges_;
+ // a set of media keys IDs that are pending approval or approved to access
+ // device DRM credentials.
+ // These 2 sets does not cover all the EME videos. If a video only streams
+ // clear data, it will not be included in either set.
+ std::set<int> media_keys_ids_pending_approval_;
+ std::set<int> media_keys_ids_approved_;
+
// The fullscreen video view object or NULL if video is not played in
// fullscreen.
scoped_ptr<ContentVideoView> video_view_;
@@ -195,6 +216,12 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// Player ID of the fullscreen media player.
int fullscreen_player_id_;
+ // The player ID pending to enter fullscreen.
+ int pending_fullscreen_player_id_;
+
+ // Whether the fullscreen player has been Release()-d.
+ bool fullscreen_player_is_released_;
+
WebContents* web_contents_;
// Object for retrieving resources media players.
diff --git a/chromium/content/browser/media/encrypted_media_browsertest.cc b/chromium/content/browser/media/encrypted_media_browsertest.cc
index b3df24d643b..f4e5eafdc4c 100644
--- a/chromium/content/browser/media/encrypted_media_browsertest.cc
+++ b/chromium/content/browser/media/encrypted_media_browsertest.cc
@@ -10,20 +10,21 @@
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/shell/browser/shell.h"
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#endif
// Available key systems.
-static const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey";
+const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey";
// Supported media types.
-static const char kWebMAudioOnly[] = "audio/webm; codecs=\"vorbis\"";
-static const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\"";
-static const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
-static const char kMP4AudioOnly[] = "audio/mp4; codecs=\"mp4a.40.2\"";
-static const char kMP4VideoOnly[] = "video/mp4; codecs=\"avc1.4D4041\"";
+const char kWebMAudioOnly[] = "audio/webm; codecs=\"vorbis\"";
+const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\"";
+const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
// EME-specific test results and errors.
-static const char kEmeGkrException[] = "GENERATE_KEY_REQUEST_EXCEPTION";
-static const char kEmeKeyError[] = "KEYERROR";
+const char kEmeKeyError[] = "KEYERROR";
+const char kEmeNotSupportedError[] = "NOTSUPPORTEDERROR";
// The type of video src used to load media.
enum SrcType {
@@ -33,49 +34,67 @@ enum SrcType {
namespace content {
+// MSE is available on all desktop platforms and on Android 4.1 and later.
+static bool IsMSESupported() {
+#if defined(OS_ANDROID)
+ if (base::android::BuildInfo::GetInstance()->sdk_int() < 16) {
+ VLOG(0) << "MSE is only supported in Android 4.1 and later.";
+ return false;
+ }
+#endif // defined(OS_ANDROID)
+ return true;
+}
+
// Tests encrypted media playback with a combination of parameters:
// - char*: Key system name.
// - bool: True to load media using MSE, otherwise use src.
class EncryptedMediaTest : public content::MediaBrowserTest,
- public testing::WithParamInterface<std::tr1::tuple<const char*, SrcType> > {
+ public testing::WithParamInterface<std::tr1::tuple<const char*, SrcType> > {
public:
- void TestSimplePlayback(const char* encrypted_media, const char* media_type,
- const std::tr1::tuple<const char*, SrcType> test_params,
- const char* expectation) {
- const char* key_system = std::tr1::get<0>(test_params);
- SrcType src_type = std::tr1::get<1>(test_params);
- RunEncryptedMediaTest("encrypted_media_player.html", encrypted_media,
- media_type, key_system, src_type, expectation);
+ // Can only be used in parameterized (*_P) tests.
+ const char* CurrentKeySystem() {
+ return std::tr1::get<0>(GetParam());
}
- void TestMSESimplePlayback(const char* encrypted_media,
- const char* media_type, const char* key_system,
- const char* expectation) {
- RunEncryptedMediaTest("encrypted_media_player.html", encrypted_media,
- media_type, key_system, MSE, expectation);
+ // Can only be used in parameterized (*_P) tests.
+ SrcType CurrentSourceType() {
+ return std::tr1::get<1>(GetParam());
}
- void TestFrameSizeChange(
- const std::tr1::tuple<const char*, SrcType> test_params,
- const char* expectation) {
- const char* key_system = std::tr1::get<0>(test_params);
- SrcType src_type = std::tr1::get<1>(test_params);
+ void TestSimplePlayback(const char* encrypted_media, const char* media_type) {
+ RunSimpleEncryptedMediaTest(
+ encrypted_media, media_type, CurrentKeySystem(), CurrentSourceType());
+ }
+
+ void TestFrameSizeChange() {
RunEncryptedMediaTest("encrypted_frame_size_change.html",
"frame_size_change-av-enc-v.webm", kWebMAudioVideo,
- key_system, src_type, expectation);
+ CurrentKeySystem(), CurrentSourceType(), kEnded);
}
- void TestConfigChange(const char* key_system, const char* expectation) {
+ void TestConfigChange() {
+ if (CurrentSourceType() != MSE || !IsMSESupported()) {
+ VLOG(0) << "Skipping test - config change test requires MSE.";
+ return;
+ }
+
std::vector<StringPair> query_params;
- query_params.push_back(std::make_pair("keysystem", key_system));
+ query_params.push_back(std::make_pair("keysystem", CurrentKeySystem()));
query_params.push_back(std::make_pair("runencrypted", "1"));
- RunMediaTestPage("mse_config_change.html", &query_params, expectation,
- true);
+ RunMediaTestPage("mse_config_change.html", &query_params, kEnded, true);
}
- void RunEncryptedMediaTest(const char* html_page, const char* media_file,
- const char* media_type, const char* key_system,
- SrcType src_type, const char* expectation) {
+ void RunEncryptedMediaTest(const char* html_page,
+ const char* media_file,
+ const char* media_type,
+ const char* key_system,
+ SrcType src_type,
+ const char* expectation) {
+ if (src_type == MSE && !IsMSESupported()) {
+ VLOG(0) << "Skipping test - MSE not supported.";
+ return;
+ }
+
std::vector<StringPair> query_params;
query_params.push_back(std::make_pair("mediafile", media_file));
query_params.push_back(std::make_pair("mediatype", media_type));
@@ -85,66 +104,79 @@ class EncryptedMediaTest : public content::MediaBrowserTest,
RunMediaTestPage(html_page, &query_params, expectation, true);
}
+ void RunSimpleEncryptedMediaTest(const char* media_file,
+ const char* media_type,
+ const char* key_system,
+ SrcType src_type) {
+ RunEncryptedMediaTest("encrypted_media_player.html", media_file,
+ media_type, key_system, src_type, kEnded);
+ }
+
protected:
// We want to fail quickly when a test fails because an error is encountered.
virtual void AddWaitForTitles(content::TitleWatcher* title_watcher) OVERRIDE {
MediaBrowserTest::AddWaitForTitles(title_watcher);
- title_watcher->AlsoWaitForTitle(ASCIIToUTF16(kEmeGkrException));
+ title_watcher->AlsoWaitForTitle(ASCIIToUTF16(kEmeNotSupportedError));
title_watcher->AlsoWaitForTitle(ASCIIToUTF16(kEmeKeyError));
}
+
+#if defined(OS_ANDROID)
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ command_line->AppendSwitch(
+ switches::kDisableGestureRequirementForMediaPlayback);
+ }
+#endif
};
-INSTANTIATE_TEST_CASE_P(ClearKey, EncryptedMediaTest,
- ::testing::Combine(
- ::testing::Values(kClearKeyKeySystem), ::testing::Values(SRC, MSE)));
+using ::testing::Combine;
+using ::testing::Values;
-IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, ConfigChangeVideo_ClearKey) {
- TestConfigChange(kClearKeyKeySystem, kEnded);
-}
+#if !defined(OS_ANDROID)
+// Encrypted media playback with SRC is not supported on Android.
+INSTANTIATE_TEST_CASE_P(SRC_ClearKey, EncryptedMediaTest,
+ Combine(Values(kClearKeyKeySystem), Values(SRC)));
+#endif // !defined(OS_ANDROID)
-IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, InvalidKeySystem) {
- TestMSESimplePlayback("bear-320x240-av-enc_av.webm", kWebMAudioVideo,
- "com.example.invalid", kEmeGkrException);
-}
+INSTANTIATE_TEST_CASE_P(MSE_ClearKey, EncryptedMediaTest,
+ Combine(Values(kClearKeyKeySystem), Values(MSE)));
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM) {
- TestSimplePlayback("bear-a-enc_a.webm", kWebMAudioOnly, GetParam(), kEnded);
+ TestSimplePlayback("bear-a-enc_a.webm", kWebMAudioOnly);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioClearVideo_WebM) {
- TestSimplePlayback("bear-320x240-av-enc_a.webm", kWebMAudioVideo, GetParam(),
- kEnded);
+ TestSimplePlayback("bear-320x240-av-enc_a.webm", kWebMAudioVideo);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM) {
- TestSimplePlayback("bear-320x240-av-enc_av.webm", kWebMAudioVideo, GetParam(),
- kEnded);
+ TestSimplePlayback("bear-320x240-av-enc_av.webm", kWebMAudioVideo);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM) {
- TestSimplePlayback("bear-320x240-v-enc_v.webm", kWebMVideoOnly, GetParam(),
- kEnded);
+ TestSimplePlayback("bear-320x240-v-enc_v.webm", kWebMVideoOnly);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM) {
- TestSimplePlayback("bear-320x240-av-enc_v.webm", kWebMAudioVideo, GetParam(),
- kEnded);
+ TestSimplePlayback("bear-320x240-av-enc_v.webm", kWebMAudioVideo);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo) {
+ TestConfigChange();
}
-IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameChangeVideo) {
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameSizeChangeVideo) {
// Times out on Windows XP. http://crbug.com/171937
#if defined(OS_WIN)
if (base::win::GetVersion() < base::win::VERSION_VISTA)
return;
#endif
- TestFrameSizeChange(GetParam(), kEnded);
+ TestFrameSizeChange();
}
-// TODO(shadi): Do we need both this and InvalidKeySystem?
IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, UnknownKeySystemThrowsException) {
RunEncryptedMediaTest("encrypted_media_player.html", "bear-a-enc_a.webm",
- kWebMAudioOnly, "com.example.foo", SRC,
- kEmeGkrException);
+ kWebMAudioOnly, "com.example.foo", MSE,
+ kEmeNotSupportedError);
}
} // namespace content
diff --git a/chromium/content/browser/media/media_browsertest.cc b/chromium/content/browser/media/media_browsertest.cc
index c264ec949fc..06558233632 100644
--- a/chromium/content/browser/media/media_browsertest.cc
+++ b/chromium/content/browser/media/media_browsertest.cc
@@ -59,13 +59,13 @@ void MediaBrowserTest::RunMediaTestPage(
}
void MediaBrowserTest::RunTest(const GURL& gurl, const char* expected) {
- const string16 expected_title = ASCIIToUTF16(expected);
+ const base::string16 expected_title = ASCIIToUTF16(expected);
DVLOG(1) << "Running test URL: " << gurl;
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
AddWaitForTitles(&title_watcher);
NavigateToURL(shell(), gurl);
- string16 final_title = title_watcher.WaitAndGetTitle();
+ base::string16 final_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, final_title);
}
@@ -168,16 +168,20 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearWavGsmms) {
PlayAudio("bear_gsm_ms.wav", GetParam());
}
-IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearWavMulaw) {
- PlayAudio("bear_mulaw.wav", GetParam());
-}
-
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearFlac) {
PlayAudio("bear.flac", GetParam());
}
#endif
#endif
+IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearWavAlaw) {
+ PlayAudio("bear_alaw.wav", GetParam());
+}
+
+IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearWavMulaw) {
+ PlayAudio("bear_mulaw.wav", GetParam());
+}
+
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearWavPcm) {
PlayAudio("bear_pcm.wav", GetParam());
}
@@ -227,7 +231,8 @@ IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv420pH264)) {
}
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuvj420pH264)) {
- RunColorFormatTest("yuvj420p.mp4", "ENDED");
+ // TODO(rileya): Support YUVJ420P properly http://crbug.com/310273
+ RunColorFormatTest("yuvj420p.mp4", "FAILED");
}
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv422pH264)) {
diff --git a/chromium/content/browser/media_devices_monitor.cc b/chromium/content/browser/media/media_devices_monitor.cc
index 72c3b4b1cef..9f2c18353f1 100644
--- a/chromium/content/browser/media_devices_monitor.cc
+++ b/chromium/content/browser/media/media_devices_monitor.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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.
@@ -12,8 +12,7 @@ namespace content {
namespace {
void EnsureMonitorCaptureDevicesInternal(
MediaStreamManager* media_stream_manager) {
- media_stream_manager->EnumerateDevices(
- NULL, -1, -1, -1, MEDIA_DEVICE_AUDIO_CAPTURE, GURL());
+ media_stream_manager->EnsureDeviceMonitorStarted();
}
}
diff --git a/chromium/content/browser/media/media_internals.cc b/chromium/content/browser/media/media_internals.cc
index 22f164ddccc..1ee42d17572 100644
--- a/chromium/content/browser/media/media_internals.cc
+++ b/chromium/content/browser/media/media_internals.cc
@@ -4,7 +4,6 @@
#include "content/browser/media/media_internals.h"
-#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "content/public/browser/browser_thread.h"
@@ -13,120 +12,169 @@
#include "media/base/media_log.h"
#include "media/base/media_log_event.h"
-namespace content {
+namespace {
-MediaInternals* MediaInternals::GetInstance() {
- return Singleton<MediaInternals>::get();
+static base::LazyInstance<content::MediaInternals>::Leaky g_media_internals =
+ LAZY_INSTANCE_INITIALIZER;
+
+base::string16 SerializeUpdate(const std::string& function,
+ const base::Value* value) {
+ return content::WebUI::GetJavascriptCall(
+ function, std::vector<const base::Value*>(1, value));
}
-MediaInternals::~MediaInternals() {}
+const char kAudioLogStatusKey[] = "status";
+const char kAudioLogUpdateFunction[] = "media.updateAudioComponent";
-namespace {
-std::string FormatAudioStreamName(void* host, int stream_id) {
- return base::StringPrintf("audio_streams.%p:%d", host, stream_id);
-}
-}
+} // namespace
-void MediaInternals::OnDeleteAudioStream(void* host, int stream_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DeleteItem(FormatAudioStreamName(host, stream_id));
-}
+namespace content {
-void MediaInternals::OnSetAudioStreamPlaying(
- void* host, int stream_id, bool playing) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- UpdateAudioStream(host, stream_id,
- "playing", new base::FundamentalValue(playing));
-}
+class AudioLogImpl : public media::AudioLog {
+ public:
+ AudioLogImpl(int owner_id,
+ media::AudioLogFactory::AudioComponent component,
+ content::MediaInternals* media_internals);
+ virtual ~AudioLogImpl();
+
+ virtual void OnCreated(int component_id,
+ const media::AudioParameters& params,
+ const std::string& input_device_id,
+ const std::string& output_device_id) OVERRIDE;
+ virtual void OnStarted(int component_id) OVERRIDE;
+ virtual void OnStopped(int component_id) OVERRIDE;
+ virtual void OnClosed(int component_id) OVERRIDE;
+ virtual void OnError(int component_id) OVERRIDE;
+ virtual void OnSetVolume(int component_id, double volume) OVERRIDE;
-void MediaInternals::OnAudioStreamCreated(void* host,
- int stream_id,
- const media::AudioParameters& params,
- const std::string& input_device_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ private:
+ void SendSingleStringUpdate(int component_id,
+ const std::string& key,
+ const std::string& value);
+ void StoreComponentMetadata(int component_id, base::DictionaryValue* dict);
+ std::string FormatCacheKey(int component_id);
- StoreAudioStream(host,
- stream_id,
- "input_device_id",
- Value::CreateStringValue(input_device_id));
+ const int owner_id_;
+ const media::AudioLogFactory::AudioComponent component_;
+ content::MediaInternals* const media_internals_;
- StoreAudioStream(
- host, stream_id, "status", Value::CreateStringValue("created"));
+ DISALLOW_COPY_AND_ASSIGN(AudioLogImpl);
+};
- StoreAudioStream(
- host, stream_id, "stream_id", Value::CreateIntegerValue(stream_id));
+AudioLogImpl::AudioLogImpl(int owner_id,
+ media::AudioLogFactory::AudioComponent component,
+ content::MediaInternals* media_internals)
+ : owner_id_(owner_id),
+ component_(component),
+ media_internals_(media_internals) {}
- StoreAudioStream(host,
- stream_id,
- "input_channels",
- Value::CreateIntegerValue(params.input_channels()));
+AudioLogImpl::~AudioLogImpl() {}
- StoreAudioStream(host,
- stream_id,
- "frames_per_buffer",
- Value::CreateIntegerValue(params.frames_per_buffer()));
+void AudioLogImpl::OnCreated(int component_id,
+ const media::AudioParameters& params,
+ const std::string& input_device_id,
+ const std::string& output_device_id) {
+ base::DictionaryValue dict;
+ StoreComponentMetadata(component_id, &dict);
- StoreAudioStream(host,
- stream_id,
- "sample_rate",
- Value::CreateIntegerValue(params.sample_rate()));
+ dict.SetString(kAudioLogStatusKey, "created");
+ dict.SetString("input_device_id", input_device_id);
+ dict.SetInteger("input_channels", params.input_channels());
+ dict.SetInteger("frames_per_buffer", params.frames_per_buffer());
+ dict.SetInteger("sample_rate", params.sample_rate());
+ dict.SetString("output_device_id", output_device_id);
+ dict.SetInteger("channels", params.channels());
+ dict.SetString("channel_layout",
+ ChannelLayoutToString(params.channel_layout()));
- StoreAudioStream(host,
- stream_id,
- "output_channels",
- Value::CreateIntegerValue(params.channels()));
+ media_internals_->SendUpdateAndCache(
+ FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
+}
- StoreAudioStream(
- host,
- stream_id,
- "channel_layout",
- Value::CreateStringValue(ChannelLayoutToString(params.channel_layout())));
+void AudioLogImpl::OnStarted(int component_id) {
+ SendSingleStringUpdate(component_id, kAudioLogStatusKey, "started");
+}
- SendEverything();
+void AudioLogImpl::OnStopped(int component_id) {
+ SendSingleStringUpdate(component_id, kAudioLogStatusKey, "stopped");
}
-void MediaInternals::OnSetAudioStreamStatus(void* host,
- int stream_id,
- const std::string& status) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- UpdateAudioStream(host, stream_id,
- "status", new base::StringValue(status));
+void AudioLogImpl::OnClosed(int component_id) {
+ base::DictionaryValue dict;
+ StoreComponentMetadata(component_id, &dict);
+ dict.SetString(kAudioLogStatusKey, "closed");
+ media_internals_->SendUpdateAndPurgeCache(
+ FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
}
-void MediaInternals::OnSetAudioStreamVolume(
- void* host, int stream_id, double volume) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- UpdateAudioStream(host, stream_id,
- "volume", new base::FundamentalValue(volume));
+void AudioLogImpl::OnError(int component_id) {
+ SendSingleStringUpdate(component_id, "error_occurred", "true");
+}
+
+void AudioLogImpl::OnSetVolume(int component_id, double volume) {
+ base::DictionaryValue dict;
+ StoreComponentMetadata(component_id, &dict);
+ dict.SetDouble("volume", volume);
+ media_internals_->SendUpdateAndCache(
+ FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
+}
+
+std::string AudioLogImpl::FormatCacheKey(int component_id) {
+ return base::StringPrintf("%d:%d:%d", owner_id_, component_, component_id);
+}
+
+void AudioLogImpl::SendSingleStringUpdate(int component_id,
+ const std::string& key,
+ const std::string& value) {
+ base::DictionaryValue dict;
+ StoreComponentMetadata(component_id, &dict);
+ dict.SetString(key, value);
+ media_internals_->SendUpdateAndCache(
+ FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
}
+void AudioLogImpl::StoreComponentMetadata(int component_id,
+ base::DictionaryValue* dict) {
+ dict->SetInteger("owner_id", owner_id_);
+ dict->SetInteger("component_id", component_id);
+ dict->SetInteger("component_type", component_);
+}
+
+MediaInternals* MediaInternals::GetInstance() {
+ return g_media_internals.Pointer();
+}
+
+MediaInternals::MediaInternals() : owner_ids_() {}
+MediaInternals::~MediaInternals() {}
+
void MediaInternals::OnMediaEvents(
int render_process_id, const std::vector<media::MediaLogEvent>& events) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- // Notify observers that |event| has occured.
+ // Notify observers that |event| has occurred.
for (std::vector<media::MediaLogEvent>::const_iterator event = events.begin();
- event != events.end(); ++event) {
+ event != events.end(); ++event) {
base::DictionaryValue dict;
dict.SetInteger("renderer", render_process_id);
dict.SetInteger("player", event->id);
dict.SetString("type", media::MediaLog::EventTypeToString(event->type));
- int64 ticks = event->time.ToInternalValue();
- double ticks_millis =
- ticks / static_cast<double>(base::Time::kMicrosecondsPerMillisecond);
-
+ // TODO(dalecurtis): This is technically not correct. TimeTicks "can't" be
+ // converted to to a human readable time format. See base/time/time.h.
+ const double ticks = event->time.ToInternalValue();
+ const double ticks_millis = ticks / base::Time::kMicrosecondsPerMillisecond;
dict.SetDouble("ticksMillis", ticks_millis);
dict.Set("params", event->params.DeepCopy());
- SendUpdate("media.onMediaEvent", &dict);
+ SendUpdate(SerializeUpdate("media.onMediaEvent", &dict));
}
}
void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
update_callbacks_.push_back(callback);
}
void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
for (size_t i = 0; i < update_callbacks_.size(); ++i) {
if (update_callbacks_[i].Equals(callback)) {
update_callbacks_.erase(update_callbacks_.begin() + i);
@@ -137,68 +185,61 @@ void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) {
}
void MediaInternals::SendEverything() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- SendUpdate("media.onReceiveEverything", &data_);
+ base::string16 everything_update;
+ {
+ base::AutoLock auto_lock(lock_);
+ everything_update = SerializeUpdate(
+ "media.onReceiveEverything", &cached_data_);
+ }
+ SendUpdate(everything_update);
}
-MediaInternals::MediaInternals() {
-}
+void MediaInternals::SendUpdate(const base::string16& update) {
+ // SendUpdate() may be called from any thread, but must run on the IO thread.
+ // TODO(dalecurtis): This is pretty silly since the update callbacks simply
+ // forward the calls to the UI thread. We should avoid the extra hop.
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
+ &MediaInternals::SendUpdate, base::Unretained(this), update));
+ return;
+ }
-void MediaInternals::StoreAudioStream(void* host,
- int stream_id,
- const std::string& property,
- base::Value* value) {
- StoreItem(FormatAudioStreamName(host, stream_id), property, value);
+ for (size_t i = 0; i < update_callbacks_.size(); i++)
+ update_callbacks_[i].Run(update);
}
-void MediaInternals::UpdateAudioStream(void* host,
- int stream_id,
- const std::string& property,
- base::Value* value) {
- UpdateItem("media.updateAudioStream",
- FormatAudioStreamName(host, stream_id),
- property,
- value);
+scoped_ptr<media::AudioLog> MediaInternals::CreateAudioLog(
+ AudioComponent component) {
+ base::AutoLock auto_lock(lock_);
+ return scoped_ptr<media::AudioLog>(new AudioLogImpl(
+ owner_ids_[component]++, component, this));
}
-void MediaInternals::DeleteItem(const std::string& item) {
- data_.Remove(item, NULL);
- scoped_ptr<base::Value> value(new base::StringValue(item));
- SendUpdate("media.onItemDeleted", value.get());
-}
+void MediaInternals::SendUpdateAndCache(const std::string& cache_key,
+ const std::string& function,
+ const base::DictionaryValue* value) {
+ SendUpdate(SerializeUpdate(function, value));
-base::DictionaryValue* MediaInternals::StoreItem(const std::string& id,
- const std::string& property,
- base::Value* value) {
- base::DictionaryValue* item_properties;
- if (!data_.GetDictionary(id, &item_properties)) {
- item_properties = new base::DictionaryValue();
- data_.Set(id, item_properties);
- item_properties->SetString("id", id);
+ base::AutoLock auto_lock(lock_);
+ if (!cached_data_.HasKey(cache_key)) {
+ cached_data_.Set(cache_key, value->DeepCopy());
+ return;
}
- item_properties->Set(property, value);
- return item_properties;
-}
-void MediaInternals::UpdateItem(const std::string& update_fn,
- const std::string& id,
- const std::string& property,
- base::Value* value) {
- base::DictionaryValue* item_properties = StoreItem(id, property, value);
- SendUpdate(update_fn, item_properties);
+ base::DictionaryValue* existing_dict = NULL;
+ CHECK(cached_data_.GetDictionary(cache_key, &existing_dict));
+ existing_dict->MergeDictionary(value);
}
-void MediaInternals::SendUpdate(const std::string& function,
- base::Value* value) {
- // Only bother serializing the update to JSON if someone is watching.
- if (update_callbacks_.empty())
- return;
+void MediaInternals::SendUpdateAndPurgeCache(
+ const std::string& cache_key,
+ const std::string& function,
+ const base::DictionaryValue* value) {
+ SendUpdate(SerializeUpdate(function, value));
- std::vector<const base::Value*> args;
- args.push_back(value);
- string16 update = WebUI::GetJavascriptCall(function, args);
- for (size_t i = 0; i < update_callbacks_.size(); i++)
- update_callbacks_[i].Run(update);
+ base::AutoLock auto_lock(lock_);
+ scoped_ptr<base::Value> out_value;
+ CHECK(cached_data_.Remove(cache_key, &out_value));
}
} // namespace content
diff --git a/chromium/content/browser/media/media_internals.h b/chromium/content/browser/media/media_internals.h
index 24b314ef321..c0f144a5b8b 100644
--- a/chromium/content/browser/media/media_internals.h
+++ b/chromium/content/browser/media/media_internals.h
@@ -8,12 +8,14 @@
#include <string>
#include <vector>
-#include "base/memory/ref_counted.h"
-#include "base/memory/singleton.h"
+#include "base/callback_forward.h"
+#include "base/compiler_specific.h"
+#include "base/lazy_instance.h"
#include "base/strings/string16.h"
+#include "base/synchronization/lock.h"
#include "base/values.h"
#include "content/common/content_export.h"
-#include "content/public/common/media_stream_request.h"
+#include "media/audio/audio_logging.h"
namespace media {
class AudioParameters;
@@ -23,90 +25,60 @@ struct MediaLogEvent;
namespace content {
// This class stores information about currently active media.
-// It's constructed on the UI thread but all of its methods are called on the IO
-// thread.
-class CONTENT_EXPORT MediaInternals {
+class CONTENT_EXPORT MediaInternals
+ : NON_EXPORTED_BASE(public media::AudioLogFactory) {
public:
- virtual ~MediaInternals();
-
static MediaInternals* GetInstance();
- // The following methods are virtual for gmock.
-
- // Called when an audio stream is deleted.
- virtual void OnDeleteAudioStream(void* host, int stream_id);
-
- // Called when an audio stream is set to playing or paused.
- virtual void OnSetAudioStreamPlaying(void* host, int stream_id, bool playing);
-
- // Called when an audio stream is created with the parameters that
- // it attempts to use to make the stream.
- virtual void OnAudioStreamCreated(void* host,
- int stream_id,
- const media::AudioParameters& params,
- const std::string& input_device_id);
-
- // Called when the status of an audio stream is set to "created", "closed", or
- // "error".
- virtual void OnSetAudioStreamStatus(void* host, int stream_id,
- const std::string& status);
-
- // Called when the volume of an audio stream is set.
- virtual void OnSetAudioStreamVolume(void* host, int stream_id,
- double volume);
+ virtual ~MediaInternals();
// Called when a MediaEvent occurs.
- virtual void OnMediaEvents(int render_process_id,
- const std::vector<media::MediaLogEvent>& events);
+ void OnMediaEvents(int render_process_id,
+ const std::vector<media::MediaLogEvent>& events);
// Called with the update string.
- typedef base::Callback<void(const string16&)> UpdateCallback;
+ typedef base::Callback<void(const base::string16&)> UpdateCallback;
- // Add/remove update callbacks (see above).
+ // Add/remove update callbacks (see above). Must be called on the IO thread.
void AddUpdateCallback(const UpdateCallback& callback);
void RemoveUpdateCallback(const UpdateCallback& callback);
+
+ // Sends all cached data to each registered UpdateCallback.
void SendEverything();
+ // AudioLogFactory implementation. Safe to call from any thread.
+ virtual scoped_ptr<media::AudioLog> CreateAudioLog(
+ AudioComponent component) OVERRIDE;
+
private:
- friend class MockMediaInternals;
+ friend class AudioLogImpl;
friend class MediaInternalsTest;
- friend struct DefaultSingletonTraits<MediaInternals>;
+ friend struct base::DefaultLazyInstanceTraits<MediaInternals>;
MediaInternals();
- // Sets |property| of an audio stream to |value| and notifies observers.
- // (host, stream_id) is a unique id for the audio stream.
- // |host| will never be dereferenced.
- void UpdateAudioStream(void* host, int stream_id,
- const std::string& property, base::Value* value);
-
- // See UpdateAudioStream. The difference is that StoreAudioStream does not
- // immediately send the data to the client, instead it waits until
- // SendEverything is called.
- void StoreAudioStream(void* host,
- int stream_id,
- const std::string& property,
- base::Value* value);
-
- // Removes |item| from |data_|.
- void DeleteItem(const std::string& item);
-
- base::DictionaryValue* StoreItem(const std::string& id,
- const std::string& property,
- base::Value* value);
-
- // Sets data_.id.property = value and notifies attached UIs using update_fn.
- // id may be any depth, e.g. "video.decoders.1.2.3"
- void UpdateItem(const std::string& update_fn, const std::string& id,
- const std::string& property, base::Value* value);
-
- // Calls javascript |function|(|value|) on each attached UI.
- void SendUpdate(const std::string& function, base::Value* value);
-
- base::DictionaryValue data_;
-
+ // Sends |update| to each registered UpdateCallback. Safe to call from any
+ // thread, but will forward to the IO thread.
+ void SendUpdate(const base::string16& update);
+
+ // Caches |value| under |cache_key| so that future SendEverything() calls will
+ // include the current data. Calls JavaScript |function|(|value|) for each
+ // registered UpdateCallback. SendUpdateAndPurgeCache() is similar but purges
+ // the cache entry after completion instead.
+ void SendUpdateAndCache(const std::string& cache_key,
+ const std::string& function,
+ const base::DictionaryValue* value);
+ void SendUpdateAndPurgeCache(const std::string& cache_key,
+ const std::string& function,
+ const base::DictionaryValue* value);
+ // Must only be accessed on the IO thread.
std::vector<UpdateCallback> update_callbacks_;
+ // All variables below must be accessed under |lock_|.
+ base::Lock lock_;
+ base::DictionaryValue cached_data_;
+ int owner_ids_[AUDIO_COMPONENT_MAX];
+
DISALLOW_COPY_AND_ASSIGN(MediaInternals);
};
diff --git a/chromium/content/browser/media/media_internals_handler.cc b/chromium/content/browser/media/media_internals_handler.cc
index 1715330e8e5..9a3e7be2142 100644
--- a/chromium/content/browser/media/media_internals_handler.cc
+++ b/chromium/content/browser/media/media_internals_handler.cc
@@ -16,7 +16,8 @@
namespace content {
MediaInternalsMessageHandler::MediaInternalsMessageHandler()
- : proxy_(new MediaInternalsProxy()) {}
+ : proxy_(new MediaInternalsProxy()),
+ page_load_complete_(false) {}
MediaInternalsMessageHandler::~MediaInternalsMessageHandler() {
proxy_->Detach();
@@ -33,14 +34,16 @@ void MediaInternalsMessageHandler::RegisterMessages() {
void MediaInternalsMessageHandler::OnGetEverything(
const base::ListValue* list) {
+ page_load_complete_ = true;
proxy_->GetEverything();
}
-void MediaInternalsMessageHandler::OnUpdate(const string16& update) {
- // Don't try to execute JavaScript in a RenderView that no longer exists.
+void MediaInternalsMessageHandler::OnUpdate(const base::string16& update) {
+ // Don't try to execute JavaScript in a RenderView that no longer exists nor
+ // if the chrome://media-internals page hasn't finished loading.
RenderViewHost* host = web_ui()->GetWebContents()->GetRenderViewHost();
- if (host)
- host->ExecuteJavascriptInWebFrame(string16(), update);
+ if (host && page_load_complete_)
+ host->ExecuteJavascriptInWebFrame(base::string16(), update);
}
} // namespace content
diff --git a/chromium/content/browser/media/media_internals_handler.h b/chromium/content/browser/media/media_internals_handler.h
index 4833aee285f..265c1224d7e 100644
--- a/chromium/content/browser/media/media_internals_handler.h
+++ b/chromium/content/browser/media/media_internals_handler.h
@@ -30,11 +30,15 @@ class MediaInternalsMessageHandler : public WebUIMessageHandler {
void OnGetEverything(const base::ListValue* list);
// MediaInternals message handlers.
- void OnUpdate(const string16& update);
+ void OnUpdate(const base::string16& update);
private:
scoped_refptr<MediaInternalsProxy> proxy_;
+ // Reflects whether the chrome://media-internals HTML+JS has finished loading.
+ // If not, it's not safe to send JavaScript calls targeting the page yet.
+ bool page_load_complete_;
+
DISALLOW_COPY_AND_ASSIGN(MediaInternalsMessageHandler);
};
diff --git a/chromium/content/browser/media/media_internals_proxy.cc b/chromium/content/browser/media/media_internals_proxy.cc
index d0e0622b41b..49456ab498a 100644
--- a/chromium/content/browser/media/media_internals_proxy.cc
+++ b/chromium/content/browser/media/media_internals_proxy.cc
@@ -69,7 +69,7 @@ void MediaInternalsProxy::GetEverything() {
CallJavaScriptFunctionOnUIThread("media.onReceiveConstants", GetConstants());
}
-void MediaInternalsProxy::OnUpdate(const string16& update) {
+void MediaInternalsProxy::OnUpdate(const base::string16& update) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -140,7 +140,7 @@ void MediaInternalsProxy::GetEverythingOnIOThread() {
MediaInternals::GetInstance()->SendEverything();
}
-void MediaInternalsProxy::UpdateUIOnUIThread(const string16& update) {
+void MediaInternalsProxy::UpdateUIOnUIThread(const base::string16& update) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Don't forward updates to a destructed UI.
if (handler_)
@@ -175,7 +175,7 @@ void MediaInternalsProxy::CallJavaScriptFunctionOnUIThread(
scoped_ptr<base::Value> args_value(args);
std::vector<const base::Value*> args_vector;
args_vector.push_back(args_value.get());
- string16 update = WebUI::GetJavascriptCall(function, args_vector);
+ base::string16 update = WebUI::GetJavascriptCall(function, args_vector);
UpdateUIOnUIThread(update);
}
diff --git a/chromium/content/browser/media/media_internals_proxy.h b/chromium/content/browser/media/media_internals_proxy.h
index 5d173b3e738..b737b858a3e 100644
--- a/chromium/content/browser/media/media_internals_proxy.h
+++ b/chromium/content/browser/media/media_internals_proxy.h
@@ -49,7 +49,7 @@ class MediaInternalsProxy
void GetEverything();
// MediaInternals callback. Called on the IO thread.
- void OnUpdate(const string16& update);
+ void OnUpdate(const base::string16& update);
// net::NetLog::ThreadSafeObserver implementation. Callable from any thread:
virtual void OnAddEntry(const net::NetLog::Entry& entry) OVERRIDE;
@@ -65,7 +65,7 @@ class MediaInternalsProxy
void ObserveMediaInternalsOnIOThread();
void StopObservingMediaInternalsOnIOThread();
void GetEverythingOnIOThread();
- void UpdateUIOnUIThread(const string16& update);
+ void UpdateUIOnUIThread(const base::string16& update);
// Put |entry| on a list of events to be sent to the page.
void AddNetEventOnUIThread(base::Value* entry);
diff --git a/chromium/content/browser/media/media_internals_unittest.cc b/chromium/content/browser/media/media_internals_unittest.cc
index 173ba36539f..2947104cad3 100644
--- a/chromium/content/browser/media/media_internals_unittest.cc
+++ b/chromium/content/browser/media/media_internals_unittest.cc
@@ -5,173 +5,142 @@
#include "content/browser/media/media_internals.h"
#include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/stringprintf.h"
-#include "content/public/test/test_browser_thread.h"
+#include "base/bind_helpers.h"
+#include "base/json/json_reader.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_parameters.h"
#include "media/base/channel_layout.h"
-#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace content {
namespace {
+const int kTestComponentID = 0;
+const char kTestInputDeviceID[] = "test-input-id";
+const char kTestOutputDeviceID[] = "test-output-id";
+} // namespace
-class MockObserverBaseClass {
- public:
- ~MockObserverBaseClass() {}
- virtual void OnUpdate(const string16& javascript) = 0;
-};
+namespace content {
-class MockMediaInternalsObserver : public MockObserverBaseClass {
+class MediaInternalsTest
+ : public testing::TestWithParam<media::AudioLogFactory::AudioComponent> {
public:
- virtual ~MockMediaInternalsObserver() {}
- MOCK_METHOD1(OnUpdate, void(const string16& javascript));
-};
-
-} // namespace
+ MediaInternalsTest()
+ : media_internals_(MediaInternals::GetInstance()),
+ update_cb_(base::Bind(&MediaInternalsTest::UpdateCallbackImpl,
+ base::Unretained(this))),
+ test_params_(media::AudioParameters::AUDIO_PCM_LINEAR,
+ media::CHANNEL_LAYOUT_MONO,
+ 48000,
+ 16,
+ 128),
+ test_component_(GetParam()),
+ audio_log_(media_internals_->CreateAudioLog(test_component_)) {
+ media_internals_->AddUpdateCallback(update_cb_);
+ }
-class MediaInternalsTest : public testing::Test {
- public:
- MediaInternalsTest() : io_thread_(BrowserThread::IO, &loop_) {}
- base::DictionaryValue* data() {
- return &internals_->data_;
+ virtual ~MediaInternalsTest() {
+ media_internals_->RemoveUpdateCallback(update_cb_);
}
- void DeleteItem(const std::string& item) {
- internals_->DeleteItem(item);
+ protected:
+ // Extracts and deserializes the JSON update data; merges into |update_data_|.
+ void UpdateCallbackImpl(const base::string16& update) {
+ // Each update string looks like "<JavaScript Function Name>({<JSON>});", to
+ // use the JSON reader we need to strip out the JavaScript code.
+ std::string utf8_update = base::UTF16ToUTF8(update);
+ const std::string::size_type first_brace = utf8_update.find('{');
+ const std::string::size_type last_brace = utf8_update.rfind('}');
+ scoped_ptr<base::Value> output_value(base::JSONReader::Read(
+ utf8_update.substr(first_brace, last_brace - first_brace + 1)));
+ CHECK(output_value);
+
+ base::DictionaryValue* output_dict = NULL;
+ CHECK(output_value->GetAsDictionary(&output_dict));
+ update_data_.MergeDictionary(output_dict);
}
- void UpdateItem(const std::string& item, const std::string& property,
- base::Value* value) {
- internals_->UpdateItem(std::string(), item, property, value);
+ void ExpectInt(const std::string& key, int expected_value) {
+ int actual_value = 0;
+ ASSERT_TRUE(update_data_.GetInteger(key, &actual_value));
+ EXPECT_EQ(expected_value, actual_value);
}
- void SendUpdate(const std::string& function, base::Value* value) {
- internals_->SendUpdate(function, value);
+ void ExpectString(const std::string& key, const std::string& expected_value) {
+ std::string actual_value;
+ ASSERT_TRUE(update_data_.GetString(key, &actual_value));
+ EXPECT_EQ(expected_value, actual_value);
}
- protected:
- virtual void SetUp() {
- internals_.reset(new MediaInternals());
+ void ExpectStatus(const std::string& expected_value) {
+ ExpectString("status", expected_value);
}
- base::MessageLoop loop_;
- TestBrowserThread io_thread_;
- scoped_ptr<MediaInternals> internals_;
+ TestBrowserThreadBundle thread_bundle_;
+ MediaInternals* const media_internals_;
+ MediaInternals::UpdateCallback update_cb_;
+ base::DictionaryValue update_data_;
+ const media::AudioParameters test_params_;
+ const media::AudioLogFactory::AudioComponent test_component_;
+ scoped_ptr<media::AudioLog> audio_log_;
};
-TEST_F(MediaInternalsTest, AudioStreamCreatedSendsMessage) {
- media::AudioParameters params =
- media::AudioParameters(media::AudioParameters::AUDIO_PCM_LINEAR,
- media::CHANNEL_LAYOUT_MONO,
- 48000,
- 16,
- 129);
-
- const int stream_id = 0;
- const std::string device_id = "test";
- const std::string name =
- base::StringPrintf("audio_streams.%p:%d", this, stream_id);
-
- internals_->OnAudioStreamCreated(this, stream_id, params, device_id);
-
- std::string channel_layout;
- data()->GetString(name + ".channel_layout", &channel_layout);
- EXPECT_EQ("MONO", channel_layout);
-
- int sample_rate;
- data()->GetInteger(name + ".sample_rate", &sample_rate);
- EXPECT_EQ(params.sample_rate(), sample_rate);
-
- int frames_per_buffer;
- data()->GetInteger(name + ".frames_per_buffer", &frames_per_buffer);
- EXPECT_EQ(params.frames_per_buffer(), frames_per_buffer);
-
- int output_channels;
- data()->GetInteger(name + ".output_channels", &output_channels);
- EXPECT_EQ(params.channels(), output_channels);
-
- std::string device_id_out;
- data()->GetString(name + ".input_device_id", &device_id_out);
- EXPECT_EQ(device_id, device_id_out);
-
- int input_channels;
- data()->GetInteger(name + ".input_channels", &input_channels);
- EXPECT_EQ(params.input_channels(), input_channels);
+TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) {
+ audio_log_->OnCreated(
+ kTestComponentID, test_params_, kTestInputDeviceID, kTestOutputDeviceID);
+ base::RunLoop().RunUntilIdle();
+
+ ExpectString("channel_layout",
+ media::ChannelLayoutToString(test_params_.channel_layout()));
+ ExpectInt("sample_rate", test_params_.sample_rate());
+ ExpectInt("frames_per_buffer", test_params_.frames_per_buffer());
+ ExpectInt("channels", test_params_.channels());
+ ExpectInt("input_channels", test_params_.input_channels());
+ ExpectString("output_device_id", kTestOutputDeviceID);
+ ExpectString("input_device_id", kTestInputDeviceID);
+ ExpectInt("component_id", kTestComponentID);
+ ExpectInt("component_type", test_component_);
+ ExpectStatus("created");
+
+ // Verify OnStarted().
+ audio_log_->OnStarted(kTestComponentID);
+ base::RunLoop().RunUntilIdle();
+ ExpectStatus("started");
+
+ // Verify OnStopped().
+ audio_log_->OnStopped(kTestComponentID);
+ base::RunLoop().RunUntilIdle();
+ ExpectStatus("stopped");
+
+ // Verify OnError().
+ const char kErrorKey[] = "error_occurred";
+ std::string no_value;
+ ASSERT_FALSE(update_data_.GetString(kErrorKey, &no_value));
+ audio_log_->OnError(kTestComponentID);
+ base::RunLoop().RunUntilIdle();
+ ExpectString(kErrorKey, "true");
+
+ // Verify OnClosed().
+ audio_log_->OnClosed(kTestComponentID);
+ base::RunLoop().RunUntilIdle();
+ ExpectStatus("closed");
}
-TEST_F(MediaInternalsTest, UpdateAddsNewItem) {
- UpdateItem("some.item", "testing", new base::FundamentalValue(true));
- bool testing = false;
- std::string id;
+TEST_P(MediaInternalsTest, AudioLogCreateClose) {
+ audio_log_->OnCreated(
+ kTestComponentID, test_params_, kTestInputDeviceID, kTestOutputDeviceID);
+ base::RunLoop().RunUntilIdle();
+ ExpectStatus("created");
- EXPECT_TRUE(data()->GetBoolean("some.item.testing", &testing));
- EXPECT_TRUE(testing);
-
- EXPECT_TRUE(data()->GetString("some.item.id", &id));
- EXPECT_EQ(id, "some.item");
-}
-
-TEST_F(MediaInternalsTest, UpdateModifiesExistingItem) {
- UpdateItem("some.item", "testing", new base::FundamentalValue(true));
- UpdateItem("some.item", "value", new base::FundamentalValue(5));
- UpdateItem("some.item", "testing", new base::FundamentalValue(false));
- bool testing = true;
- int value = 0;
- std::string id;
-
- EXPECT_TRUE(data()->GetBoolean("some.item.testing", &testing));
- EXPECT_FALSE(testing);
-
- EXPECT_TRUE(data()->GetInteger("some.item.value", &value));
- EXPECT_EQ(value, 5);
-
- EXPECT_TRUE(data()->GetString("some.item.id", &id));
- EXPECT_EQ(id, "some.item");
-}
-
-TEST_F(MediaInternalsTest, ObserversReceiveNotifications) {
- scoped_ptr<MockMediaInternalsObserver> observer(
- new MockMediaInternalsObserver());
-
- EXPECT_CALL(*observer.get(), OnUpdate(testing::_)).Times(1);
-
- MediaInternals::UpdateCallback callback = base::Bind(
- &MockMediaInternalsObserver::OnUpdate, base::Unretained(observer.get()));
-
- internals_->AddUpdateCallback(callback);
- SendUpdate("fn", data());
-}
-
-TEST_F(MediaInternalsTest, RemovedObserversReceiveNoNotifications) {
- scoped_ptr<MockMediaInternalsObserver> observer(
- new MockMediaInternalsObserver());
-
- EXPECT_CALL(*observer.get(), OnUpdate(testing::_)).Times(0);
-
- MediaInternals::UpdateCallback callback = base::Bind(
- &MockMediaInternalsObserver::OnUpdate, base::Unretained(observer.get()));
-
- internals_->AddUpdateCallback(callback);
- internals_->RemoveUpdateCallback(callback);
- SendUpdate("fn", data());
+ audio_log_->OnClosed(kTestComponentID);
+ base::RunLoop().RunUntilIdle();
+ ExpectStatus("closed");
}
-TEST_F(MediaInternalsTest, DeleteRemovesItem) {
- base::Value* out;
-
- UpdateItem("some.item", "testing", base::Value::CreateNullValue());
- EXPECT_TRUE(data()->Get("some.item", &out));
- EXPECT_TRUE(data()->Get("some", &out));
-
- DeleteItem("some.item");
- EXPECT_FALSE(data()->Get("some.item", &out));
- EXPECT_TRUE(data()->Get("some", &out));
-
- DeleteItem("some");
- EXPECT_FALSE(data()->Get("some.item", &out));
- EXPECT_FALSE(data()->Get("some", &out));
-}
+INSTANTIATE_TEST_CASE_P(
+ MediaInternalsTest, MediaInternalsTest, testing::Values(
+ media::AudioLogFactory::AUDIO_INPUT_CONTROLLER,
+ media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER,
+ media::AudioLogFactory::AUDIO_OUTPUT_STREAM));
} // namespace content
diff --git a/chromium/content/browser/media/media_source_browsertest.cc b/chromium/content/browser/media/media_source_browsertest.cc
index bd119ddff07..27242e5f800 100644
--- a/chromium/content/browser/media/media_source_browsertest.cc
+++ b/chromium/content/browser/media/media_source_browsertest.cc
@@ -5,18 +5,37 @@
#include "base/command_line.h"
#include "content/browser/media/media_browsertest.h"
#include "content/public/common/content_switches.h"
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#endif
// Common media types.
-static const char kWebMAudioOnly[] = "audio/webm; codecs=\"vorbis\"";
-static const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\"";
-static const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
+const char kWebMAudioOnly[] = "audio/webm; codecs=\"vorbis\"";
+const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\"";
+const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
namespace content {
+// MSE is available on all desktop platforms and on Android 4.1 and later.
+static bool IsMSESupported() {
+#if defined(OS_ANDROID)
+ if (base::android::BuildInfo::GetInstance()->sdk_int() < 16) {
+ VLOG(0) << "MSE is only supported in Android 4.1 and later.";
+ return false;
+ }
+#endif // defined(OS_ANDROID)
+ return true;
+}
+
class MediaSourceTest : public content::MediaBrowserTest {
public:
void TestSimplePlayback(const char* media_file, const char* media_type,
const char* expectation) {
+ if (!IsMSESupported()) {
+ VLOG(0) << "Skipping test - MSE not supported.";
+ return;
+ }
+
std::vector<StringPair> query_params;
query_params.push_back(std::make_pair("mediafile", media_file));
query_params.push_back(std::make_pair("mediatype", media_type));
@@ -51,6 +70,10 @@ IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_Type_Error) {
// Flaky test crbug.com/246308
// Test changed to skip checks resulting in flakiness. Proper fix still needed.
IN_PROC_BROWSER_TEST_F(MediaSourceTest, ConfigChangeVideo) {
+ if (!IsMSESupported()) {
+ VLOG(0) << "Skipping test - MSE not supported.";
+ return;
+ }
RunMediaTestPage("mse_config_change.html", NULL, kEnded, true);
}
diff --git a/chromium/content/browser/media/webrtc_browsertest.cc b/chromium/content/browser/media/webrtc_browsertest.cc
index 6b75262c66c..47847a7d53b 100644
--- a/chromium/content/browser/media/webrtc_browsertest.cc
+++ b/chromium/content/browser/media/webrtc_browsertest.cc
@@ -3,24 +3,39 @@
// found in the LICENSE file.
#include "base/command_line.h"
+#include "base/debug/trace_event_impl.h"
+#include "base/json/json_reader.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
+#include "media/audio/audio_manager.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/perf/perf_test.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
+const char kForceIsac16K[] =
+#ifdef OS_ANDROID
+ // The default audio codec, Opus, doesn't work on Android.
+ "true";
+#else
+ "false";
+#endif
+
namespace {
-static const char kGetUserMedia[] = "getUserMedia";
-static const char kGetUserMediaWithAnalysis[] = "getUserMediaWithAnalysis";
+static const char kGetUserMediaAndStop[] = "getUserMediaAndStop";
+static const char kGetUserMediaAndWaitAndStop[] = "getUserMediaAndWaitAndStop";
+static const char kGetUserMediaAndAnalyseAndStop[] =
+ "getUserMediaAndAnalyseAndStop";
std::string GenerateGetUserMediaCall(const char* function_name,
int min_width,
@@ -63,13 +78,68 @@ class WebrtcBrowserTest: public ContentBrowserTest {
command_line->AppendSwitch(switches::kUseGpuInTests);
}
+ void DumpChromeTraceCallback(
+ const scoped_refptr<base::RefCountedString>& events,
+ bool has_more_events) {
+ // Convert the dump output into a correct JSON List.
+ std::string contents = "[" + events->data() + "]";
+
+ int error_code;
+ std::string error_message;
+ scoped_ptr<base::Value> value(
+ base::JSONReader::ReadAndReturnError(contents,
+ base::JSON_ALLOW_TRAILING_COMMAS,
+ &error_code,
+ &error_message));
+
+ ASSERT_TRUE(value.get() != NULL) << error_message;
+ EXPECT_EQ(value->GetType(), base::Value::TYPE_LIST);
+
+ base::ListValue* values;
+ ASSERT_TRUE(value->GetAsList(&values));
+
+ int duration_ns = 0;
+ std::string samples_duration;
+ double timestamp_ns = 0.0;
+ double previous_timestamp_ns = 0.0;
+ std::string samples_interarrival_ns;
+ for (ListValue::iterator it = values->begin(); it != values->end(); ++it) {
+ const DictionaryValue* dict;
+ EXPECT_TRUE((*it)->GetAsDictionary(&dict));
+
+ if (dict->GetInteger("dur", &duration_ns))
+ samples_duration.append(base::StringPrintf("%d,", duration_ns));
+ if (dict->GetDouble("ts", &timestamp_ns)) {
+ if (previous_timestamp_ns) {
+ samples_interarrival_ns.append(
+ base::StringPrintf("%f,", timestamp_ns - previous_timestamp_ns));
+ }
+ previous_timestamp_ns = timestamp_ns;
+ }
+ }
+ ASSERT_GT(samples_duration.size(), 0u)
+ << "Could not collect any samples during test, this is bad";
+ perf_test::PrintResultList("video_capture",
+ "",
+ "sample_duration",
+ samples_duration,
+ "ns",
+ true);
+ perf_test::PrintResultList("video_capture",
+ "",
+ "interarrival_time",
+ samples_interarrival_ns,
+ "ns",
+ true);
+ }
+
protected:
bool ExecuteJavascript(const std::string& javascript) {
return ExecuteScript(shell()->web_contents(), javascript);
}
void ExpectTitle(const std::string& expected_title) const {
- string16 expected_title16(ASCIIToUTF16(expected_title));
+ base::string16 expected_title16(ASCIIToUTF16(expected_title));
TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
}
@@ -79,31 +149,33 @@ class WebrtcBrowserTest: public ContentBrowserTest {
// see that the success callback is called. If the error callback is called or
// none of the callbacks are called the tests will simply time out and fail.
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, GetVideoStreamAndStop) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/getusermedia.html"));
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
- EXPECT_TRUE(ExecuteJavascript("getUserMedia({video: true});"));
+ EXPECT_TRUE(ExecuteJavascript(
+ base::StringPrintf("%s({video: true});", kGetUserMediaAndStop)));
ExpectTitle("OK");
}
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, GetAudioAndVideoStreamAndStop) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/getusermedia.html"));
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
- EXPECT_TRUE(ExecuteJavascript("getUserMedia({video: true, audio: true});"));
+ EXPECT_TRUE(ExecuteJavascript(base::StringPrintf(
+ "%s({video: true, audio: true});", kGetUserMediaAndStop)));
ExpectTitle("OK");
}
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, GetAudioAndVideoStreamAndClone) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/getusermedia.html"));
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("getUserMediaAndClone();"));
@@ -122,15 +194,45 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, GetAudioAndVideoStreamAndClone) {
// These tests will make a complete PeerConnection-based call and verify that
// video is playing for the call.
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CanSetupVideoCall) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("call({video: true});"));
ExpectTitle("OK");
}
+// This test will make a simple getUserMedia page, verify that video is playing
+// in a simple local <video>, and for a couple of seconds, collect some
+// performance traces.
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, TracePerformanceDuringGetUserMedia) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+ // Put getUserMedia to work and let it run for a couple of seconds.
+ EXPECT_TRUE(ExecuteJavascript(base::StringPrintf(
+ "%s({video: true}, 10);", kGetUserMediaAndWaitAndStop)));
+
+ // Make sure the stream is up and running, then start collecting traces.
+ ExpectTitle("Running...");
+ base::debug::TraceLog* trace_log = base::debug::TraceLog::GetInstance();
+ trace_log->SetEnabled(base::debug::CategoryFilter("video"),
+ base::debug::TraceLog::ENABLE_SAMPLING);
+ // Check that we are indeed recording.
+ EXPECT_EQ(trace_log->GetNumTracesRecorded(), 1);
+
+ // Wait until the page title changes to "OK". Do not sleep() here since that
+ // would stop both this code and the browser underneath.
+ ExpectTitle("OK");
+
+ // Note that we need to stop the trace recording before flushing the data.
+ trace_log->SetDisabled();
+ trace_log->Flush(base::Bind(&WebrtcBrowserTest::DumpChromeTraceCallback,
+ base::Unretained(this)));
+}
+
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
// Timing out on ARM linux, see http://crbug.com/240376
#define MAYBE_CanSetupAudioAndVideoCall DISABLED_CanSetupAudioAndVideoCall
@@ -139,9 +241,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CanSetupVideoCall) {
#endif
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CanSetupAudioAndVideoCall) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("call({video: true, audio: true});"));
@@ -149,9 +251,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CanSetupAudioAndVideoCall) {
}
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MANUAL_CanSetupCallAndSendDtmf) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(
@@ -160,9 +262,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MANUAL_CanSetupCallAndSendDtmf) {
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
DISABLED_CanMakeEmptyCallThenAddStreamsAndRenegotiate) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
const char* kJavascript =
@@ -171,6 +273,41 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
ExpectTitle("OK");
}
+// Below 2 test will make a complete PeerConnection-based call between pc1 and
+// pc2, and then use the remote stream to setup a call between pc3 and pc4, and
+// then verify that video is received on pc3 and pc4.
+// Flaky on win xp. http://crbug.com/304775
+#if defined(OS_WIN)
+#define MAYBE_CanForwardRemoteStream DISABLED_CanForwardRemoteStream
+#define MAYBE_CanForwardRemoteStream720p DISABLED_CanForwardRemoteStream720p
+#else
+#define MAYBE_CanForwardRemoteStream CanForwardRemoteStream
+#define MAYBE_CanForwardRemoteStream720p CanForwardRemoteStream720p
+#endif
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CanForwardRemoteStream) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ NavigateToURL(shell(), url);
+
+ EXPECT_TRUE(ExecuteJavascript(
+ "callAndForwardRemoteStream({video: true, audio: true});"));
+ ExpectTitle("OK");
+}
+
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CanForwardRemoteStream720p) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ NavigateToURL(shell(), url);
+
+ const std::string cmd = GenerateGetUserMediaCall("callAndForwardRemoteStream",
+ 1280, 1280,
+ 720, 720, 30, 30);
+ EXPECT_TRUE(ExecuteJavascript(cmd));
+ ExpectTitle("OK");
+}
+
// This test will make a complete PeerConnection-based call but remove the
// MSID and bundle attribute from the initial offer to verify that
// video is playing for the call even if the initiating client don't support
@@ -189,27 +326,85 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
#endif
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("callWithoutMsidAndBundle();"));
ExpectTitle("OK");
}
+// This test will modify the SDP offer to an unsupported codec, which should
+// cause SetLocalDescription to fail.
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
+ NegotiateUnsupportedVideoCodec) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ NavigateToURL(shell(), url);
+
+ EXPECT_TRUE(ExecuteJavascript("negotiateUnsupportedVideoCodec();"));
+ ExpectTitle("OK");
+}
+
+// This test will modify the SDP offer to use no encryption, which should
+// cause SetLocalDescription to fail.
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, NegotiateNonCryptoCall) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ NavigateToURL(shell(), url);
+
+ EXPECT_TRUE(ExecuteJavascript("negotiateNonCryptoCall();"));
+ ExpectTitle("OK");
+}
+
+// This test will make a complete PeerConnection-based call using legacy SDP
+// settings: GIce, external SDES, and no BUNDLE.
+#if defined(OS_WIN) && defined(USE_AURA)
+// Disabled for win7_aura, see http://crbug.com/235089.
+#define MAYBE_CanSetupLegacyCall DISABLED_CanSetupLegacyCall
+#elif defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
+// Timing out on ARM linux, see http://crbug.com/240373
+#define MAYBE_CanSetupLegacyCall DISABLED_CanSetupLegacyCall
+#else
+#define MAYBE_CanSetupLegacyCall CanSetupLegacyCall
+#endif
+
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CanSetupLegacyCall) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ NavigateToURL(shell(), url);
+
+ EXPECT_TRUE(ExecuteJavascript("callWithLegacySdp();"));
+ ExpectTitle("OK");
+}
+
// This test will make a PeerConnection-based call and test an unreliable text
// dataChannel.
+// TODO(mallinath) - Remove this test after rtp based data channel is disabled.
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, CallWithDataOnly) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("callWithDataOnly();"));
ExpectTitle("OK");
}
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, CallWithSctpDataOnly) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ NavigateToURL(shell(), url);
+
+ EXPECT_TRUE(ExecuteJavascript("callWithSctpDataOnly();"));
+ ExpectTitle("OK");
+}
+
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
// Timing out on ARM linux bot: http://crbug.com/238490
#define MAYBE_CallWithDataAndMedia DISABLED_CallWithDataAndMedia
@@ -219,16 +414,36 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, CallWithDataOnly) {
// This test will make a PeerConnection-based call and test an unreliable text
// dataChannel and audio and video tracks.
+// TODO(mallinath) - Remove this test after rtp based data channel is disabled.
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CallWithDataAndMedia) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("callWithDataAndMedia();"));
ExpectTitle("OK");
}
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
+// Timing out on ARM linux bot: http://crbug.com/238490
+#define MAYBE_CallWithSctpDataAndMedia DISABLED_CallWithSctpDataAndMedia
+#else
+#define MAYBE_CallWithSctpDataAndMedia CallWithSctpDataAndMedia
+#endif
+
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
+ MAYBE_CallWithSctpDataAndMedia) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ NavigateToURL(shell(), url);
+
+ EXPECT_TRUE(ExecuteJavascript("callWithSctpDataAndMedia();"));
+ ExpectTitle("OK");
+}
+
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
// Timing out on ARM linux bot: http://crbug.com/238490
#define MAYBE_CallWithDataAndLaterAddMedia DISABLED_CallWithDataAndLaterAddMedia
@@ -240,9 +455,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CallWithDataAndMedia) {
// This test will make a PeerConnection-based call and test an unreliable text
// dataChannel and later add an audio and video track.
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CallWithDataAndLaterAddMedia) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("callWithDataAndLaterAddMedia();"));
@@ -260,9 +475,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CallWithDataAndLaterAddMedia) {
// MediaStream that has been created based on a MediaStream created with
// getUserMedia.
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CallWithNewVideoMediaStream) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(ExecuteJavascript("callWithNewVideoMediaStream();"));
@@ -276,9 +491,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MAYBE_CallWithNewVideoMediaStream) {
// TODO(phoglund): This test is manual since not all buildbots has an audio
// input.
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MANUAL_CallAndModifyStream) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(
@@ -288,25 +503,25 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MANUAL_CallAndModifyStream) {
// This test calls getUserMedia in sequence with different constraints.
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, TestGetUserMediaConstraints) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/getusermedia.html"));
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
std::vector<std::string> list_of_get_user_media_calls;
- list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(kGetUserMedia, 320, 320, 180, 180, 30, 30));
- list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(kGetUserMedia, 320, 320, 240, 240, 30, 30));
- list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(kGetUserMedia, 640, 640, 360, 360, 30, 30));
- list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(kGetUserMedia, 640, 640, 480, 480, 30, 30));
- list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(kGetUserMedia, 960, 960, 720, 720, 30, 30));
- list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(kGetUserMedia, 1280, 1280, 720, 720, 30, 30));
- list_of_get_user_media_calls.push_back(
- GenerateGetUserMediaCall(kGetUserMedia, 1920, 1920, 1080, 1080, 30, 30));
+ list_of_get_user_media_calls.push_back(GenerateGetUserMediaCall(
+ kGetUserMediaAndStop, 320, 320, 180, 180, 30, 30));
+ list_of_get_user_media_calls.push_back(GenerateGetUserMediaCall(
+ kGetUserMediaAndStop, 320, 320, 240, 240, 30, 30));
+ list_of_get_user_media_calls.push_back(GenerateGetUserMediaCall(
+ kGetUserMediaAndStop, 640, 640, 360, 360, 30, 30));
+ list_of_get_user_media_calls.push_back(GenerateGetUserMediaCall(
+ kGetUserMediaAndStop, 640, 640, 480, 480, 30, 30));
+ list_of_get_user_media_calls.push_back(GenerateGetUserMediaCall(
+ kGetUserMediaAndStop, 960, 960, 720, 720, 30, 30));
+ list_of_get_user_media_calls.push_back(GenerateGetUserMediaCall(
+ kGetUserMediaAndStop, 1280, 1280, 720, 720, 30, 30));
+ list_of_get_user_media_calls.push_back(GenerateGetUserMediaCall(
+ kGetUserMediaAndStop, 1920, 1920, 1080, 1080, 30, 30));
for (std::vector<std::string>::iterator const_iterator =
list_of_get_user_media_calls.begin();
@@ -321,14 +536,14 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, TestGetUserMediaConstraints) {
// This test calls getUserMedia and checks for aspect ratio behavior.
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, TestGetUserMediaAspectRatio) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/getusermedia.html"));
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
std::string constraints_4_3 = GenerateGetUserMediaCall(
- kGetUserMediaWithAnalysis, 640, 640, 480, 480, 30, 30);
+ kGetUserMediaAndAnalyseAndStop, 640, 640, 480, 480, 30, 30);
std::string constraints_16_9 = GenerateGetUserMediaCall(
- kGetUserMediaWithAnalysis, 640, 640, 360, 360, 30, 30);
+ kGetUserMediaAndAnalyseAndStop, 640, 640, 360, 360, 30, 30);
// TODO(mcasas): add more aspect ratios, in particular 16:10 crbug.com/275594.
@@ -342,9 +557,9 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, TestGetUserMediaAspectRatio) {
}
IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, AddTwoMediaStreamsToOnePC) {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
NavigateToURL(shell(), url);
EXPECT_TRUE(
@@ -352,4 +567,55 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, AddTwoMediaStreamsToOnePC) {
ExpectTitle("OK");
}
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
+ EstablishAudioVideoCallAndMeasureOutputLevel) {
+ if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
+ // Bots with no output devices will force the audio code into a different
+ // path where it doesn't manage to set either the low or high latency path.
+ // This test will compute useless values in that case, so skip running on
+ // such bots (see crbug.com/326338).
+ LOG(INFO) << "Missing output devices: skipping test...";
+ return;
+ }
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseFakeDeviceForMediaStream))
+ << "Must run with fake devices since the test will explicitly look "
+ << "for the fake device signal.";
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ NavigateToURL(shell(), url);
+
+ EXPECT_TRUE(ExecuteJavascript(
+ base::StringPrintf("callAndEnsureAudioIsPlaying(%s);", kForceIsac16K)));
+ ExpectTitle("OK");
+}
+
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
+ EstablishAudioVideoCallAndVerifyMutingWorks) {
+ if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
+ // Bots with no output devices will force the audio code into a different
+ // path where it doesn't manage to set either the low or high latency path.
+ // This test will compute useless values in that case, so skip running on
+ // such bots (see crbug.com/326338).
+ LOG(INFO) << "Missing output devices: skipping test...";
+ return;
+ }
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseFakeDeviceForMediaStream))
+ << "Must run with fake devices since the test will explicitly look "
+ << "for the fake device signal.";
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ NavigateToURL(shell(), url);
+
+ EXPECT_TRUE(ExecuteJavascript(
+ base::StringPrintf("callAndEnsureAudioMutingWorks(%s);",
+ kForceIsac16K)));
+ ExpectTitle("OK");
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/webrtc_identity_store.cc b/chromium/content/browser/media/webrtc_identity_store.cc
index 67a25851fde..4a02b71efa0 100644
--- a/chromium/content/browser/media/webrtc_identity_store.cc
+++ b/chromium/content/browser/media/webrtc_identity_store.cc
@@ -31,28 +31,24 @@ struct WebRTCIdentityRequestResult {
std::string private_key;
};
-// Generates a new identity using |common_name| and returns the result in
-// |result|.
+// Generates a new identity using |common_name| which expires after
+// |validity_period| and returns the result in |result|.
static void GenerateIdentityWorker(const std::string& common_name,
+ base::TimeDelta validity_period,
WebRTCIdentityRequestResult* result) {
result->error = net::OK;
int serial_number = base::RandInt(0, std::numeric_limits<int>::max());
- scoped_ptr<crypto::RSAPrivateKey> key(crypto::RSAPrivateKey::Create(1024));
- if (!key.get()) {
- DLOG(ERROR) << "Unable to create key pair for client";
- result->error = net::ERR_KEY_GENERATION_FAILED;
- return;
- }
-
+ scoped_ptr<crypto::RSAPrivateKey> key;
base::Time now = base::Time::Now();
- bool success =
- net::x509_util::CreateSelfSignedCert(key.get(),
- "CN=" + common_name,
- serial_number,
- now,
- now + base::TimeDelta::FromDays(30),
- &result->certificate);
+ bool success = net::x509_util::CreateKeyAndSelfSignedCert(
+ "CN=" + common_name,
+ serial_number,
+ now,
+ now + validity_period,
+ &key,
+ &result->certificate);
+
if (!success) {
DLOG(ERROR) << "Unable to create x509 cert for client";
result->error = net::ERR_SELF_SIGNED_CERT_GENERATION_FAILED;
@@ -176,8 +172,10 @@ class WebRTCIdentityRequestHandle {
WebRTCIdentityStore::WebRTCIdentityStore(const base::FilePath& path,
quota::SpecialStoragePolicy* policy)
- : task_runner_(base::WorkerPool::GetTaskRunner(true)),
- backend_(new WebRTCIdentityStoreBackend(path, policy)) {}
+ : validity_period_(base::TimeDelta::FromDays(30)),
+ task_runner_(base::WorkerPool::GetTaskRunner(true)),
+ backend_(new WebRTCIdentityStoreBackend(path, policy, validity_period_)) {
+ }
WebRTCIdentityStore::~WebRTCIdentityStore() { backend_->Close(); }
@@ -226,6 +224,13 @@ void WebRTCIdentityStore::DeleteBetween(base::Time delete_begin,
backend_->DeleteBetween(delete_begin, delete_end, callback);
}
+void WebRTCIdentityStore::SetValidityPeriodForTesting(
+ base::TimeDelta validity_period) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ validity_period_ = validity_period;
+ backend_->SetValidityPeriodForTesting(validity_period);
+}
+
void WebRTCIdentityStore::SetTaskRunnerForTesting(
const scoped_refptr<base::TaskRunner>& task_runner) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -247,12 +252,15 @@ void WebRTCIdentityStore::BackendFindCallback(WebRTCIdentityRequest* request,
WebRTCIdentityRequestResult* result =
new WebRTCIdentityRequestResult(0, "", "");
if (!task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&GenerateIdentityWorker, request->common_name_, result),
- base::Bind(&WebRTCIdentityStore::GenerateIdentityCallback,
- this,
- request,
- base::Owned(result)))) {
+ FROM_HERE,
+ base::Bind(&GenerateIdentityWorker,
+ request->common_name_,
+ validity_period_,
+ result),
+ base::Bind(&WebRTCIdentityStore::GenerateIdentityCallback,
+ this,
+ request,
+ base::Owned(result)))) {
// Completes the request with error if failed to post the task.
WebRTCIdentityRequestResult result(net::ERR_UNEXPECTED, "", "");
PostRequestResult(request, result);
diff --git a/chromium/content/browser/media/webrtc_identity_store.h b/chromium/content/browser/media/webrtc_identity_store.h
index c2b523e2dfe..3602b7028cd 100644
--- a/chromium/content/browser/media/webrtc_identity_store.h
+++ b/chromium/content/browser/media/webrtc_identity_store.h
@@ -83,6 +83,7 @@ class CONTENT_EXPORT WebRTCIdentityStore
friend class base::RefCountedThreadSafe<WebRTCIdentityStore>;
friend class WebRTCIdentityStoreTest;
+ void SetValidityPeriodForTesting(base::TimeDelta validity_period);
void SetTaskRunnerForTesting(
const scoped_refptr<base::TaskRunner>& task_runner);
@@ -98,8 +99,12 @@ class CONTENT_EXPORT WebRTCIdentityStore
void PostRequestResult(WebRTCIdentityRequest* request,
const WebRTCIdentityRequestResult& result);
+ // The validity period of the certificates.
+ base::TimeDelta validity_period_;
+
// The TaskRunner for doing work on a worker thread.
scoped_refptr<base::TaskRunner> task_runner_;
+
// Weak references of the in flight requests. Used to join identical external
// requests.
std::vector<WebRTCIdentityRequest*> in_flight_requests_;
diff --git a/chromium/content/browser/media/webrtc_identity_store_backend.cc b/chromium/content/browser/media/webrtc_identity_store_backend.cc
index 4188116bc71..697de93c927 100644
--- a/chromium/content/browser/media/webrtc_identity_store_backend.cc
+++ b/chromium/content/browser/media/webrtc_identity_store_backend.cc
@@ -70,9 +70,10 @@ struct WebRTCIdentityStoreBackend::PendingFindRequest {
class WebRTCIdentityStoreBackend::SqlLiteStorage
: public base::RefCountedThreadSafe<SqlLiteStorage> {
public:
- SqlLiteStorage(const base::FilePath& path,
+ SqlLiteStorage(base::TimeDelta validity_period,
+ const base::FilePath& path,
quota::SpecialStoragePolicy* policy)
- : special_storage_policy_(policy) {
+ : validity_period_(validity_period), special_storage_policy_(policy) {
if (!path.empty())
path_ = path.Append(kWebRTCIdentityStoreDirectory);
}
@@ -85,9 +86,13 @@ class WebRTCIdentityStoreBackend::SqlLiteStorage
void DeleteIdentity(const GURL& origin,
const std::string& identity_name,
const Identity& identity);
- void DeleteBetween(base::Time delete_begin,
- base::Time delete_end,
- const base::Closure& callback);
+ void DeleteBetween(base::Time delete_begin, base::Time delete_end);
+
+ void SetValidityPeriodForTesting(base::TimeDelta validity_period) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ DCHECK(!db_.get());
+ validity_period_ = validity_period;
+ }
private:
friend class base::RefCountedThreadSafe<SqlLiteStorage>;
@@ -121,6 +126,7 @@ class WebRTCIdentityStoreBackend::SqlLiteStorage
const Identity& identity);
void Commit();
+ base::TimeDelta validity_period_;
// The file path of the DB. Empty if temporary.
base::FilePath path_;
scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
@@ -133,9 +139,11 @@ class WebRTCIdentityStoreBackend::SqlLiteStorage
WebRTCIdentityStoreBackend::WebRTCIdentityStoreBackend(
const base::FilePath& path,
- quota::SpecialStoragePolicy* policy)
- : state_(NOT_STARTED),
- sql_lite_storage_(new SqlLiteStorage(path, policy)) {}
+ quota::SpecialStoragePolicy* policy,
+ base::TimeDelta validity_period)
+ : validity_period_(validity_period),
+ state_(NOT_STARTED),
+ sql_lite_storage_(new SqlLiteStorage(validity_period, path, policy)) {}
bool WebRTCIdentityStoreBackend::FindIdentity(
const GURL& origin,
@@ -176,13 +184,20 @@ bool WebRTCIdentityStoreBackend::FindIdentity(
IdentityKey key(origin, identity_name);
IdentityMap::iterator iter = identities_.find(key);
if (iter != identities_.end() && iter->second.common_name == common_name) {
- // Identity found.
- return BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(callback,
- net::OK,
- iter->second.certificate,
- iter->second.private_key));
+ base::TimeDelta age = base::Time::Now() - base::Time::FromInternalValue(
+ iter->second.creation_time);
+ if (age < validity_period_) {
+ // Identity found.
+ return BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback,
+ net::OK,
+ iter->second.certificate,
+ iter->second.private_key));
+ }
+ // Removes the expired identity from the in-memory cache. The copy in the
+ // database will be removed on the next load.
+ identities_.erase(iter);
}
return BrowserThread::PostTask(
@@ -249,30 +264,50 @@ void WebRTCIdentityStoreBackend::DeleteBetween(base::Time delete_begin,
base::Time delete_end,
const base::Closure& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (state_ == CLOSED)
+ return;
+
// Delete the in-memory cache.
IdentityMap::iterator it = identities_.begin();
while (it != identities_.end()) {
if (it->second.creation_time >= delete_begin.ToInternalValue() &&
- it->second.creation_time <= delete_end.ToInternalValue())
+ it->second.creation_time <= delete_end.ToInternalValue()) {
identities_.erase(it++);
- else
- it++;
+ } else {
+ ++it;
+ }
}
-
BrowserThread::PostTaskAndReply(BrowserThread::DB,
FROM_HERE,
base::Bind(&SqlLiteStorage::DeleteBetween,
sql_lite_storage_,
delete_begin,
- delete_end,
- callback),
+ delete_end),
callback);
}
+void WebRTCIdentityStoreBackend::SetValidityPeriodForTesting(
+ base::TimeDelta validity_period) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ validity_period_ = validity_period;
+ BrowserThread::PostTask(
+ BrowserThread::DB,
+ FROM_HERE,
+ base::Bind(&SqlLiteStorage::SetValidityPeriodForTesting,
+ sql_lite_storage_,
+ validity_period));
+}
+
WebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {}
void WebRTCIdentityStoreBackend::OnLoaded(scoped_ptr<IdentityMap> out_map) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (state_ != LOADING)
+ return;
+
+ DVLOG(2) << "WebRTC identity store has loaded.";
+
state_ = LOADED;
identities_.swap(*out_map);
@@ -297,7 +332,7 @@ void WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) {
// Ensure the parent directory for storing certs is created before reading
// from it.
const base::FilePath dir = path_.DirName();
- if (!base::PathExists(dir) && !file_util::CreateDirectory(dir)) {
+ if (!base::PathExists(dir) && !base::CreateDirectory(dir)) {
DLOG(ERROR) << "Unable to open DB file path.";
return;
}
@@ -320,6 +355,9 @@ void WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) {
db_->Preload();
+ // Delete expired identities.
+ DeleteBetween(base::Time(), base::Time::Now() - validity_period_);
+
// Slurp all the identities into the out_map.
sql::Statement stmt(db_->GetUniqueStatement(
"SELECT origin, identity_name, common_name, "
@@ -374,6 +412,35 @@ void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteIdentity(
BatchOperation(DELETE_IDENTITY, origin, identity_name, identity);
}
+void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteBetween(
+ base::Time delete_begin,
+ base::Time delete_end) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ if (!db_.get())
+ return;
+
+ // Commit pending operations first.
+ Commit();
+
+ sql::Statement del_stmt(db_->GetCachedStatement(
+ SQL_FROM_HERE,
+ "DELETE FROM webrtc_identity_store"
+ " WHERE creation_time >= ? AND creation_time <= ?"));
+ CHECK(del_stmt.is_valid());
+
+ del_stmt.BindInt64(0, delete_begin.ToInternalValue());
+ del_stmt.BindInt64(1, delete_end.ToInternalValue());
+
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin()) {
+ DLOG(ERROR) << "Failed to begin the transaction.";
+ return;
+ }
+
+ CHECK(del_stmt.Run());
+ transaction.Commit();
+}
+
void WebRTCIdentityStoreBackend::SqlLiteStorage::OnDatabaseError(
int error,
sql::Statement* stmt) {
@@ -463,7 +530,7 @@ void WebRTCIdentityStoreBackend::SqlLiteStorage::Commit() {
case DELETE_IDENTITY:
del_stmt.Reset(true);
del_stmt.BindString(0, po->origin.spec());
- add_stmt.BindString(1, po->identity_name);
+ del_stmt.BindString(1, po->identity_name);
CHECK(del_stmt.Run());
break;
@@ -476,34 +543,4 @@ void WebRTCIdentityStoreBackend::SqlLiteStorage::Commit() {
pending_operations_.clear();
}
-void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteBetween(
- base::Time delete_begin,
- base::Time delete_end,
- const base::Closure& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- if (!db_.get())
- return;
-
- // Commit pending operations first.
- Commit();
-
- sql::Statement del_stmt(db_->GetCachedStatement(
- SQL_FROM_HERE,
- "DELETE FROM webrtc_identity_store"
- " WHERE creation_time >= ? AND creation_time <= ?"));
- CHECK(del_stmt.is_valid());
-
- del_stmt.BindInt64(0, delete_begin.ToInternalValue());
- del_stmt.BindInt64(1, delete_end.ToInternalValue());
-
- sql::Transaction transaction(db_.get());
- if (!transaction.Begin()) {
- DLOG(ERROR) << "Failed to begin the transaction.";
- return;
- }
-
- CHECK(del_stmt.Run());
- transaction.Commit();
-}
-
} // namespace content
diff --git a/chromium/content/browser/media/webrtc_identity_store_backend.h b/chromium/content/browser/media/webrtc_identity_store_backend.h
index e660c732cda..9be3fc2345e 100644
--- a/chromium/content/browser/media/webrtc_identity_store_backend.h
+++ b/chromium/content/browser/media/webrtc_identity_store_backend.h
@@ -34,9 +34,11 @@ class WebRTCIdentityStoreBackend
const std::string& private_key)>
FindIdentityCallback;
- // No data is saved on disk if |path| is empty.
+ // No data is saved on disk if |path| is empty. Identites older than
+ // |validity_period| will be removed lazily.
WebRTCIdentityStoreBackend(const base::FilePath& path,
- quota::SpecialStoragePolicy* policy);
+ quota::SpecialStoragePolicy* policy,
+ base::TimeDelta validity_period);
// Finds the identity with |origin|, |identity_name|, and |common_name| from
// the DB.
@@ -76,6 +78,10 @@ class WebRTCIdentityStoreBackend
base::Time delete_end,
const base::Closure& callback);
+ // Changes the validity period. Should be called before the database is
+ // loaded into memory.
+ void SetValidityPeriodForTesting(base::TimeDelta validity_period);
+
private:
friend class base::RefCountedThreadSafe<WebRTCIdentityStoreBackend>;
class SqlLiteStorage;
@@ -131,6 +137,9 @@ class WebRTCIdentityStoreBackend
void OnLoaded(scoped_ptr<IdentityMap> out_map);
+
+ // Identities expires after |validity_period_|.
+ base::TimeDelta validity_period_;
// In-memory copy of the identities.
IdentityMap identities_;
// "Find identity" requests waiting for the DB to load.
diff --git a/chromium/content/browser/media/webrtc_identity_store_unittest.cc b/chromium/content/browser/media/webrtc_identity_store_unittest.cc
index 81c25d7f63f..85bd18f3768 100644
--- a/chromium/content/browser/media/webrtc_identity_store_unittest.cc
+++ b/chromium/content/browser/media/webrtc_identity_store_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/bind.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/test/sequenced_worker_pool_owner.h"
#include "content/browser/media/webrtc_identity_store.h"
@@ -14,11 +15,6 @@
namespace content {
-// TODO(jiayl): the tests fail on Android since the openssl version of
-// CreateSelfSignedCert is not implemented. We should mock out this dependency
-// and remove the if-defined.
-#if !defined(OS_ANDROID)
-
static const char* kFakeOrigin = "http://foo.com";
static const char* kFakeIdentityName1 = "name1";
static const char* kFakeIdentityName2 = "name2";
@@ -55,6 +51,10 @@ class WebRTCIdentityStoreTest : public testing::Test {
pool_owner_->pool()->Shutdown();
}
+ void SetValidityPeriod(base::TimeDelta validity_period) {
+ webrtc_identity_store_->SetValidityPeriodForTesting(validity_period);
+ }
+
void RunUntilIdle() {
RunAllPendingInMessageLoop(BrowserThread::DB);
RunAllPendingInMessageLoop(BrowserThread::IO);
@@ -78,6 +78,11 @@ class WebRTCIdentityStoreTest : public testing::Test {
return cancel_callback;
}
+ void Restart(const base::FilePath& path) {
+ webrtc_identity_store_ = new WebRTCIdentityStore(path, NULL);
+ webrtc_identity_store_->SetTaskRunnerForTesting(pool_owner_->pool());
+ }
+
protected:
TestBrowserThreadBundle browser_thread_bundle_;
scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
@@ -274,5 +279,68 @@ TEST_F(WebRTCIdentityStoreTest, DeleteDataAndGenerateNewIdentity) {
EXPECT_NE(key_1, key_2);
}
-#endif
+TEST_F(WebRTCIdentityStoreTest, ExpiredIdentityDeleted) {
+ // The identities will expire immediately after creation.
+ SetValidityPeriod(base::TimeDelta::FromMilliseconds(0));
+
+ bool completed_1 = false;
+ bool completed_2 = false;
+ std::string cert_1, cert_2, key_1, key_2;
+
+ base::Closure cancel_callback_1 =
+ RequestIdentityAndRunUtilIdle(kFakeOrigin,
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ &completed_1,
+ &cert_1,
+ &key_1);
+ EXPECT_TRUE(completed_1);
+
+ // Check that the old identity is not returned.
+ base::Closure cancel_callback_2 =
+ RequestIdentityAndRunUtilIdle(kFakeOrigin,
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ &completed_2,
+ &cert_2,
+ &key_2);
+ EXPECT_TRUE(completed_2);
+ EXPECT_NE(cert_1, cert_2);
+ EXPECT_NE(key_1, key_2);
+}
+
+TEST_F(WebRTCIdentityStoreTest, IdentityPersistentAcrossRestart) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ Restart(temp_dir.path());
+
+ bool completed_1 = false;
+ bool completed_2 = false;
+ std::string cert_1, cert_2, key_1, key_2;
+
+ // Creates an identity.
+ base::Closure cancel_callback_1 =
+ RequestIdentityAndRunUtilIdle(kFakeOrigin,
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ &completed_1,
+ &cert_1,
+ &key_1);
+ EXPECT_TRUE(completed_1);
+
+ Restart(temp_dir.path());
+
+ // Check that the same identity is returned after the restart.
+ base::Closure cancel_callback_2 =
+ RequestIdentityAndRunUtilIdle(kFakeOrigin,
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ &completed_2,
+ &cert_2,
+ &key_2);
+ EXPECT_TRUE(completed_2);
+ EXPECT_EQ(cert_1, cert_2);
+ EXPECT_EQ(key_1, key_2);
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/webrtc_internals_browsertest.cc b/chromium/content/browser/media/webrtc_internals_browsertest.cc
index b45827623b4..0d279b3075b 100644
--- a/chromium/content/browser/media/webrtc_internals_browsertest.cc
+++ b/chromium/content/browser/media/webrtc_internals_browsertest.cc
@@ -145,7 +145,7 @@ class MAYBE_WebRTCInternalsBrowserTest: public ContentBrowserTest {
}
void ExpectTitle(const std::string& expected_title) const {
- string16 expected_title16(ASCIIToUTF16(expected_title));
+ base::string16 expected_title16(ASCIIToUTF16(expected_title));
TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
}
diff --git a/chromium/content/browser/media/webrtc_internals_message_handler.cc b/chromium/content/browser/media/webrtc_internals_message_handler.cc
index 2ba75227380..8cf85790286 100644
--- a/chromium/content/browser/media/webrtc_internals_message_handler.cc
+++ b/chromium/content/browser/media/webrtc_internals_message_handler.cc
@@ -68,11 +68,11 @@ void WebRTCInternalsMessageHandler::OnUpdate(const std::string& command,
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
std::vector<const base::Value*> args_vector;
args_vector.push_back(args);
- string16 update = WebUI::GetJavascriptCall(command, args_vector);
+ base::string16 update = WebUI::GetJavascriptCall(command, args_vector);
RenderViewHost* host = web_ui()->GetWebContents()->GetRenderViewHost();
if (host)
- host->ExecuteJavascriptInWebFrame(string16(), update);
+ host->ExecuteJavascriptInWebFrame(base::string16(), update);
}
} // namespace content
diff --git a/chromium/content/browser/message_port_message_filter.cc b/chromium/content/browser/message_port_message_filter.cc
new file mode 100644
index 00000000000..70d8175b503
--- /dev/null
+++ b/chromium/content/browser/message_port_message_filter.cc
@@ -0,0 +1,65 @@
+// 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/message_port_message_filter.h"
+
+#include "content/browser/message_port_service.h"
+#include "content/common/message_port_messages.h"
+
+namespace content {
+
+MessagePortMessageFilter::MessagePortMessageFilter(
+ const NextRoutingIDCallback& callback)
+ : next_routing_id_(callback) {
+}
+
+MessagePortMessageFilter::~MessagePortMessageFilter() {
+}
+
+void MessagePortMessageFilter::OnChannelClosing() {
+ MessagePortService::GetInstance()->OnMessagePortMessageFilterClosing(this);
+}
+
+bool MessagePortMessageFilter::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(MessagePortMessageFilter, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(MessagePortHostMsg_CreateMessagePort,
+ OnCreateMessagePort)
+ IPC_MESSAGE_FORWARD(MessagePortHostMsg_DestroyMessagePort,
+ MessagePortService::GetInstance(),
+ MessagePortService::Destroy)
+ IPC_MESSAGE_FORWARD(MessagePortHostMsg_Entangle,
+ MessagePortService::GetInstance(),
+ MessagePortService::Entangle)
+ IPC_MESSAGE_FORWARD(MessagePortHostMsg_PostMessage,
+ MessagePortService::GetInstance(),
+ MessagePortService::PostMessage)
+ IPC_MESSAGE_FORWARD(MessagePortHostMsg_QueueMessages,
+ MessagePortService::GetInstance(),
+ MessagePortService::QueueMessages)
+ IPC_MESSAGE_FORWARD(MessagePortHostMsg_SendQueuedMessages,
+ MessagePortService::GetInstance(),
+ MessagePortService::SendQueuedMessages)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP_EX()
+
+ return handled;
+}
+
+void MessagePortMessageFilter::OnDestruct() const {
+ BrowserThread::DeleteOnIOThread::Destruct(this);
+}
+
+int MessagePortMessageFilter::GetNextRoutingID() {
+ return next_routing_id_.Run();
+}
+
+void MessagePortMessageFilter::OnCreateMessagePort(int *route_id,
+ int* message_port_id) {
+ *route_id = next_routing_id_.Run();
+ MessagePortService::GetInstance()->Create(*route_id, this, message_port_id);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/message_port_message_filter.h b/chromium/content/browser/message_port_message_filter.h
new file mode 100644
index 00000000000..0dd38c94e6c
--- /dev/null
+++ b/chromium/content/browser/message_port_message_filter.h
@@ -0,0 +1,49 @@
+// 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_MESSAGE_PORT_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_MESSAGE_PORT_MESSAGE_FILTER_H_
+
+#include "base/callback.h"
+#include "content/public/browser/browser_message_filter.h"
+
+namespace content {
+
+// Filter for MessagePort related IPC messages (creating and destroying a
+// MessagePort, sending a message via a MessagePort etc).
+class MessagePortMessageFilter : public BrowserMessageFilter {
+ public:
+ typedef base::Callback<int(void)> NextRoutingIDCallback;
+
+ // |next_routing_id| is owned by this object. It can be used up until
+ // OnChannelClosing.
+ explicit MessagePortMessageFilter(const NextRoutingIDCallback& callback);
+
+ // BrowserMessageFilter implementation.
+ virtual void OnChannelClosing() OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) OVERRIDE;
+ virtual void OnDestruct() const OVERRIDE;
+
+ int GetNextRoutingID();
+
+ private:
+ friend class BrowserThread;
+ friend class base::DeleteHelper<MessagePortMessageFilter>;
+
+ virtual ~MessagePortMessageFilter();
+
+ // Message handlers.
+ void OnCreateMessagePort(int* route_id, int* message_port_id);
+
+ // This is guaranteed to be valid until OnChannelClosing is invoked, and it's
+ // not used after.
+ NextRoutingIDCallback next_routing_id_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MessagePortMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WORKER_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/worker_host/message_port_service.cc b/chromium/content/browser/message_port_service.cc
index b413c1f8c60..25c2b44200d 100644
--- a/chromium/content/browser/worker_host/message_port_service.cc
+++ b/chromium/content/browser/message_port_service.cc
@@ -1,11 +1,11 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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/worker_host/message_port_service.h"
+#include "content/browser/message_port_service.h"
-#include "content/browser/worker_host/worker_message_filter.h"
-#include "content/common/worker_messages.h"
+#include "content/browser/message_port_message_filter.h"
+#include "content/common/message_port_messages.h"
namespace content {
@@ -22,7 +22,7 @@ MessagePortService::~MessagePortService() {
void MessagePortService::UpdateMessagePort(
int message_port_id,
- WorkerMessageFilter* filter,
+ MessagePortMessageFilter* filter,
int routing_id) {
if (!message_ports_.count(message_port_id)) {
NOTREACHED();
@@ -34,8 +34,8 @@ void MessagePortService::UpdateMessagePort(
port.route_id = routing_id;
}
-void MessagePortService::OnWorkerMessageFilterClosing(
- WorkerMessageFilter* filter) {
+void MessagePortService::OnMessagePortMessageFilterClosing(
+ MessagePortMessageFilter* filter) {
// Check if the (possibly) crashed process had any message ports.
for (MessagePorts::iterator iter = message_ports_.begin();
iter != message_ports_.end();) {
@@ -47,7 +47,7 @@ void MessagePortService::OnWorkerMessageFilterClosing(
}
void MessagePortService::Create(int route_id,
- WorkerMessageFilter* filter,
+ MessagePortMessageFilter* filter,
int* message_port_id) {
*message_port_id = ++next_message_port_id_;
@@ -86,7 +86,7 @@ void MessagePortService::Entangle(int local_message_port_id,
void MessagePortService::PostMessage(
int sender_message_port_id,
- const string16& message,
+ const base::string16& message,
const std::vector<int>& sent_message_port_ids) {
if (!message_ports_.count(sender_message_port_id)) {
NOTREACHED();
@@ -108,7 +108,7 @@ void MessagePortService::PostMessage(
void MessagePortService::PostMessageTo(
int message_port_id,
- const string16& message,
+ const base::string16& message,
const std::vector<int>& sent_message_port_ids) {
if (!message_ports_.count(message_port_id)) {
NOTREACHED();
@@ -151,7 +151,7 @@ void MessagePortService::PostMessageTo(
}
// Now send the message to the entangled port.
- entangled_port.filter->Send(new WorkerProcessMsg_Message(
+ entangled_port.filter->Send(new MessagePortMsg_Message(
entangled_port.route_id, message, sent_message_port_ids,
new_routing_ids));
}
@@ -164,7 +164,7 @@ void MessagePortService::QueueMessages(int message_port_id) {
MessagePort& port = message_ports_[message_port_id];
if (port.filter) {
- port.filter->Send(new WorkerProcessMsg_MessagesQueued(port.route_id));
+ port.filter->Send(new MessagePortMsg_MessagesQueued(port.route_id));
port.queue_messages = true;
port.filter = NULL;
}
diff --git a/chromium/content/browser/worker_host/message_port_service.h b/chromium/content/browser/message_port_service.h
index 30645c79b65..3e197a48aeb 100644
--- a/chromium/content/browser/worker_host/message_port_service.h
+++ b/chromium/content/browser/message_port_service.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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_WORKER_HOST_MESSAGE_PORT_SERVICE_H_
-#define CONTENT_BROWSER_WORKER_HOST_MESSAGE_PORT_SERVICE_H_
+#ifndef CONTENT_BROWSER_MESSAGE_PORT_SERVICE_H_
+#define CONTENT_BROWSER_MESSAGE_PORT_SERVICE_H_
#include <map>
#include <utility>
@@ -15,21 +15,24 @@
#include "ipc/ipc_message.h"
namespace content {
-class WorkerMessageFilter;
+class MessagePortMessageFilter;
class MessagePortService {
public:
- typedef std::vector<std::pair<string16, std::vector<int> > > QueuedMessages;
+ typedef std::vector<std::pair<base::string16, std::vector<int> > >
+ QueuedMessages;
// Returns the MessagePortService singleton.
static MessagePortService* GetInstance();
// These methods correspond to the message port related IPCs.
- void Create(int route_id, WorkerMessageFilter* filter, int* message_port_id);
+ void Create(int route_id,
+ MessagePortMessageFilter* filter,
+ int* message_port_id);
void Destroy(int message_port_id);
void Entangle(int local_message_port_id, int remote_message_port_id);
void PostMessage(int sender_message_port_id,
- const string16& message,
+ const base::string16& message,
const std::vector<int>& sent_message_port_ids);
void QueueMessages(int message_port_id);
void SendQueuedMessages(int message_port_id,
@@ -39,10 +42,10 @@ class MessagePortService {
// (possibly different) process.
void UpdateMessagePort(
int message_port_id,
- WorkerMessageFilter* filter,
+ MessagePortMessageFilter* filter,
int routing_id);
- void OnWorkerMessageFilterClosing(WorkerMessageFilter* filter);
+ void OnMessagePortMessageFilterClosing(MessagePortMessageFilter* filter);
// Attempts to send the queued messages for a message port.
void SendQueuedMessagesIfPossible(int message_port_id);
@@ -54,7 +57,7 @@ class MessagePortService {
~MessagePortService();
void PostMessageTo(int message_port_id,
- const string16& message,
+ const base::string16& message,
const std::vector<int>& sent_message_port_ids);
// Handles the details of removing a message port id. Before calling this,
@@ -65,7 +68,7 @@ class MessagePortService {
// |filter| and |route_id| are what we need to send messages to the port.
// |filter| is just a weak pointer since we get notified when its process has
// gone away and remove it.
- WorkerMessageFilter* filter;
+ MessagePortMessageFilter* filter;
int route_id;
// A globally unique id for this message port.
int message_port_id;
@@ -78,7 +81,7 @@ class MessagePortService {
// in-flight. This flag ensures that the latter type get flushed through the
// system.
// This flag should only be set to true in response to
- // WorkerProcessHostMsg_QueueMessages.
+ // MessagePortHostMsg_QueueMessages.
bool queue_messages;
QueuedMessages queued_messages;
};
@@ -94,4 +97,4 @@ class MessagePortService {
} // namespace content
-#endif // CONTENT_BROWSER_WORKER_HOST_MESSAGE_PORT_SERVICE_H_
+#endif // CONTENT_BROWSER_MESSAGE_PORT_SERVICE_H_
diff --git a/chromium/content/browser/net/sqlite_persistent_cookie_store.cc b/chromium/content/browser/net/sqlite_persistent_cookie_store.cc
index 517a8c18a16..e2b78803314 100644
--- a/chromium/content/browser/net/sqlite_persistent_cookie_store.cc
+++ b/chromium/content/browser/net/sqlite_persistent_cookie_store.cc
@@ -18,7 +18,6 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
@@ -27,6 +26,7 @@
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/cookie_crypto_delegate.h"
#include "content/public/browser/cookie_store_factory.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/cookies/canonical_cookie.h"
@@ -74,7 +74,8 @@ class SQLitePersistentCookieStore::Backend
const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
bool restore_old_session_cookies,
- quota::SpecialStoragePolicy* special_storage_policy)
+ quota::SpecialStoragePolicy* special_storage_policy,
+ scoped_ptr<CookieCryptoDelegate> crypto_delegate)
: path_(path),
num_pending_(0),
force_keep_session_state_(false),
@@ -86,7 +87,8 @@ class SQLitePersistentCookieStore::Backend
client_task_runner_(client_task_runner),
background_task_runner_(background_task_runner),
num_priority_waiting_(0),
- total_priority_requests_(0) {}
+ total_priority_requests_(0),
+ crypto_(crypto_delegate.Pass()) {}
// Creates or loads the SQLite database.
void Load(const LoadedCallback& loaded_callback);
@@ -269,6 +271,9 @@ class SQLitePersistentCookieStore::Backend
// The cumulative duration of time when |num_priority_waiting_| was greater
// than 1.
base::TimeDelta priority_wait_duration_;
+ // Class with functions that do cryptographic operations (for protecting
+ // cookies stored persistently).
+ scoped_ptr<CookieCryptoDelegate> crypto_;
DISALLOW_COPY_AND_ASSIGN(Backend);
};
@@ -277,6 +282,13 @@ namespace {
// Version number of the database.
//
+// Version 7 adds encrypted values. Old values will continue to be used but
+// all new values written will be encrypted on selected operating systems. New
+// records read by old clients will simply get an empty cookie value while old
+// records read by new clients will continue to operate with the unencrypted
+// version. New and old clients alike will always write/update records with
+// what they support.
+//
// Version 6 adds cookie priorities. This allows developers to influence the
// order in which cookies are evicted in order to meet domain cookie limits.
//
@@ -293,7 +305,7 @@ namespace {
// Version 3 updated the database to include the last access time, so we can
// expire them in decreasing order of use when we've reached the maximum
// number of cookies.
-const int kCurrentVersionNumber = 6;
+const int kCurrentVersionNumber = 7;
const int kCompatibleVersionNumber = 5;
// Possible values for the 'priority' column.
@@ -370,7 +382,8 @@ bool InitTable(sql::Connection* db) {
"last_access_utc INTEGER NOT NULL, "
"has_expires INTEGER NOT NULL DEFAULT 1, "
"persistent INTEGER NOT NULL DEFAULT 1,"
- "priority INTEGER NOT NULL DEFAULT %d)",
+ "priority INTEGER NOT NULL DEFAULT %d,"
+ "encrypted_value BLOB DEFAULT '')",
CookiePriorityToDBCookiePriority(net::COOKIE_PRIORITY_DEFAULT)));
if (!db->Execute(stmt.c_str()))
return false;
@@ -545,12 +558,12 @@ bool SQLitePersistentCookieStore::Backend::InitializeDatabase() {
base::Time start = base::Time::Now();
const base::FilePath dir = path_.DirName();
- if (!base::PathExists(dir) && !file_util::CreateDirectory(dir)) {
+ if (!base::PathExists(dir) && !base::CreateDirectory(dir)) {
return false;
}
int64 db_size = 0;
- if (file_util::GetFileSize(path_, &db_size))
+ if (base::GetFileSize(path_, &db_size))
UMA_HISTOGRAM_COUNTS("Cookie.DBSizeInKB", db_size / 1024 );
db_.reset(new sql::Connection);
@@ -679,15 +692,16 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
if (restore_old_session_cookies_) {
smt.Assign(db_->GetCachedStatement(
SQL_FROM_HERE,
- "SELECT creation_utc, host_key, name, value, path, expires_utc, "
- "secure, httponly, last_access_utc, has_expires, persistent, priority "
- "FROM cookies WHERE host_key = ?"));
+ "SELECT creation_utc, host_key, name, value, encrypted_value, path, "
+ "expires_utc, secure, httponly, last_access_utc, has_expires, "
+ "persistent, priority FROM cookies WHERE host_key = ?"));
} else {
smt.Assign(db_->GetCachedStatement(
SQL_FROM_HERE,
- "SELECT creation_utc, host_key, name, value, path, expires_utc, "
- "secure, httponly, last_access_utc, has_expires, persistent, priority "
- "FROM cookies WHERE host_key = ? AND persistent = 1"));
+ "SELECT creation_utc, host_key, name, value, encrypted_value, path, "
+ "expires_utc, secure, httponly, last_access_utc, has_expires, "
+ "persistent, priority FROM cookies WHERE host_key = ? "
+ "AND persistent = 1"));
}
if (!smt.is_valid()) {
smt.Clear(); // Disconnect smt_ref from db_.
@@ -701,20 +715,28 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
for (; it != domains.end(); ++it) {
smt.BindString(0, *it);
while (smt.Step()) {
+ std::string value;
+ std::string encrypted_value = smt.ColumnString(4);
+ if (!encrypted_value.empty() && crypto_.get()) {
+ crypto_->DecryptString(encrypted_value, &value);
+ } else {
+ DCHECK(encrypted_value.empty());
+ value = smt.ColumnString(3);
+ }
scoped_ptr<net::CanonicalCookie> cc(new net::CanonicalCookie(
// The "source" URL is not used with persisted cookies.
GURL(), // Source
smt.ColumnString(2), // name
- smt.ColumnString(3), // value
+ value, // value
smt.ColumnString(1), // domain
- smt.ColumnString(4), // path
+ smt.ColumnString(5), // path
Time::FromInternalValue(smt.ColumnInt64(0)), // creation_utc
- Time::FromInternalValue(smt.ColumnInt64(5)), // expires_utc
- Time::FromInternalValue(smt.ColumnInt64(8)), // last_access_utc
- smt.ColumnInt(6) != 0, // secure
- smt.ColumnInt(7) != 0, // httponly
+ Time::FromInternalValue(smt.ColumnInt64(6)), // expires_utc
+ Time::FromInternalValue(smt.ColumnInt64(9)), // last_access_utc
+ smt.ColumnInt(7) != 0, // secure
+ smt.ColumnInt(8) != 0, // httponly
DBCookiePriorityToCookiePriority(
- static_cast<DBCookiePriority>(smt.ColumnInt(11))))); // priority
+ static_cast<DBCookiePriority>(smt.ColumnInt(12))))); // priority
DLOG_IF(WARNING,
cc->CreationDate() > Time::Now()) << L"CreationDate too recent";
cookies_per_origin_[CookieOrigin(cc->Domain(), cc->IsSecure())]++;
@@ -837,6 +859,26 @@ bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() {
base::TimeTicks::Now() - start_time);
}
+ if (cur_version == 6) {
+ const base::TimeTicks start_time = base::TimeTicks::Now();
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin())
+ return false;
+ // Alter the table to add empty "encrypted value" column.
+ if (!db_->Execute("ALTER TABLE cookies "
+ "ADD COLUMN encrypted_value BLOB DEFAULT ''")) {
+ LOG(WARNING) << "Unable to update cookie database to version 7.";
+ return false;
+ }
+ ++cur_version;
+ meta_table_.SetVersionNumber(cur_version);
+ meta_table_.SetCompatibleVersionNumber(
+ std::min(cur_version, kCompatibleVersionNumber));
+ transaction.Commit();
+ UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV7",
+ base::TimeTicks::Now() - start_time);
+ }
+
// Put future migration cases here.
if (cur_version < kCurrentVersionNumber) {
@@ -921,10 +963,10 @@ void SQLitePersistentCookieStore::Backend::Commit() {
return;
sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE,
- "INSERT INTO cookies (creation_utc, host_key, name, value, path, "
- "expires_utc, secure, httponly, last_access_utc, has_expires, "
- "persistent, priority) "
- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)"));
+ "INSERT INTO cookies (creation_utc, host_key, name, value, "
+ "encrypted_value, path, expires_utc, secure, httponly, last_access_utc, "
+ "has_expires, persistent, priority) "
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
if (!add_smt.is_valid())
return;
@@ -954,16 +996,26 @@ void SQLitePersistentCookieStore::Backend::Commit() {
add_smt.BindInt64(0, po->cc().CreationDate().ToInternalValue());
add_smt.BindString(1, po->cc().Domain());
add_smt.BindString(2, po->cc().Name());
- add_smt.BindString(3, po->cc().Value());
- add_smt.BindString(4, po->cc().Path());
- add_smt.BindInt64(5, po->cc().ExpiryDate().ToInternalValue());
- add_smt.BindInt(6, po->cc().IsSecure());
- add_smt.BindInt(7, po->cc().IsHttpOnly());
- add_smt.BindInt64(8, po->cc().LastAccessDate().ToInternalValue());
- add_smt.BindInt(9, po->cc().IsPersistent());
+ if (crypto_.get()) {
+ std::string encrypted_value;
+ add_smt.BindCString(3, ""); // value
+ crypto_->EncryptString(po->cc().Value(), &encrypted_value);
+ // BindBlob() immediately makes an internal copy of the data.
+ add_smt.BindBlob(4, encrypted_value.data(),
+ static_cast<int>(encrypted_value.length()));
+ } else {
+ add_smt.BindString(3, po->cc().Value());
+ add_smt.BindBlob(4, "", 0); // encrypted_value
+ }
+ add_smt.BindString(5, po->cc().Path());
+ add_smt.BindInt64(6, po->cc().ExpiryDate().ToInternalValue());
+ add_smt.BindInt(7, po->cc().IsSecure());
+ add_smt.BindInt(8, po->cc().IsHttpOnly());
+ add_smt.BindInt64(9, po->cc().LastAccessDate().ToInternalValue());
add_smt.BindInt(10, po->cc().IsPersistent());
+ add_smt.BindInt(11, po->cc().IsPersistent());
add_smt.BindInt(
- 11, CookiePriorityToDBCookiePriority(po->cc().Priority()));
+ 12, CookiePriorityToDBCookiePriority(po->cc().Priority()));
if (!add_smt.Run())
NOTREACHED() << "Could not add a cookie to the DB.";
break;
@@ -1149,12 +1201,14 @@ SQLitePersistentCookieStore::SQLitePersistentCookieStore(
const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
bool restore_old_session_cookies,
- quota::SpecialStoragePolicy* special_storage_policy)
+ quota::SpecialStoragePolicy* special_storage_policy,
+ scoped_ptr<CookieCryptoDelegate> crypto_delegate)
: backend_(new Backend(path,
client_task_runner,
background_task_runner,
restore_old_session_cookies,
- special_storage_policy)) {
+ special_storage_policy,
+ crypto_delegate.Pass())) {
}
void SQLitePersistentCookieStore::Load(const LoadedCallback& loaded_callback) {
@@ -1199,25 +1253,35 @@ net::CookieStore* CreatePersistentCookieStore(
bool restore_old_session_cookies,
quota::SpecialStoragePolicy* storage_policy,
net::CookieMonster::Delegate* cookie_monster_delegate,
- const scoped_refptr<base::SequencedTaskRunner>& background_task_runner) {
+ const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
+ const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+ scoped_ptr<CookieCryptoDelegate> crypto_delegate) {
SQLitePersistentCookieStore* persistent_store =
new SQLitePersistentCookieStore(
path,
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
- background_task_runner.get() ? background_task_runner :
- BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
- BrowserThread::GetBlockingPool()->GetSequenceToken()),
+ client_task_runner,
+ background_task_runner,
restore_old_session_cookies,
- storage_policy);
- net::CookieMonster* cookie_monster =
- new net::CookieMonster(persistent_store, cookie_monster_delegate);
-
- const std::string cookie_priority_experiment_group =
- base::FieldTrialList::FindFullName("CookieRetentionPriorityStudy");
- cookie_monster->SetPriorityAwareGarbageCollection(
- cookie_priority_experiment_group == "ExperimentOn");
+ storage_policy,
+ crypto_delegate.Pass());
+ return new net::CookieMonster(persistent_store, cookie_monster_delegate);
+}
- return cookie_monster;
+net::CookieStore* CreatePersistentCookieStore(
+ const base::FilePath& path,
+ bool restore_old_session_cookies,
+ quota::SpecialStoragePolicy* storage_policy,
+ net::CookieMonster::Delegate* cookie_monster_delegate,
+ scoped_ptr<CookieCryptoDelegate> crypto_delegate) {
+ return CreatePersistentCookieStore(
+ path,
+ restore_old_session_cookies,
+ storage_policy,
+ cookie_monster_delegate,
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
+ BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
+ BrowserThread::GetBlockingPool()->GetSequenceToken()),
+ crypto_delegate.Pass());
}
} // namespace content
diff --git a/chromium/content/browser/net/sqlite_persistent_cookie_store.h b/chromium/content/browser/net/sqlite_persistent_cookie_store.h
index 65e39824eac..e94327e2322 100644
--- a/chromium/content/browser/net/sqlite_persistent_cookie_store.h
+++ b/chromium/content/browser/net/sqlite_persistent_cookie_store.h
@@ -32,6 +32,7 @@ class SpecialStoragePolicy;
}
namespace content {
+class CookieCryptoDelegate;
// Implements the PersistentCookieStore interface in terms of a SQLite database.
// For documentation about the actual member functions consult the documentation
@@ -49,7 +50,8 @@ class CONTENT_EXPORT SQLitePersistentCookieStore
const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
bool restore_old_session_cookies,
- quota::SpecialStoragePolicy* special_storage_policy);
+ quota::SpecialStoragePolicy* special_storage_policy,
+ scoped_ptr<CookieCryptoDelegate> crypto_delegate);
// net::CookieMonster::PersistentCookieStore:
virtual void Load(const LoadedCallback& loaded_callback) OVERRIDE;
diff --git a/chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc b/chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc
index e71b56b7a80..980a0c168b5 100644
--- a/chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc
+++ b/chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc
@@ -13,6 +13,7 @@
#include "base/test/perf_time_logger.h"
#include "base/test/sequenced_worker_pool_owner.h"
#include "base/threading/sequenced_worker_pool.h"
+#include "content/public/browser/cookie_crypto_delegate.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -66,7 +67,8 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test {
temp_dir_.path().Append(cookie_filename),
client_task_runner(),
background_task_runner(),
- false, NULL);
+ false, NULL,
+ scoped_ptr<content::CookieCryptoDelegate>());
std::vector<net::CanonicalCookie*> cookies;
Load();
ASSERT_EQ(0u, cookies_.size());
@@ -97,7 +99,8 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test {
temp_dir_.path().Append(cookie_filename),
client_task_runner(),
background_task_runner(),
- false, NULL);
+ false, NULL,
+ scoped_ptr<content::CookieCryptoDelegate>());
}
virtual void TearDown() OVERRIDE {
diff --git a/chromium/content/browser/net/sqlite_persistent_cookie_store_unittest.cc b/chromium/content/browser/net/sqlite_persistent_cookie_store_unittest.cc
index 4adb7906685..11c8419673a 100644
--- a/chromium/content/browser/net/sqlite_persistent_cookie_store_unittest.cc
+++ b/chromium/content/browser/net/sqlite_persistent_cookie_store_unittest.cc
@@ -19,10 +19,15 @@
#include "base/test/sequenced_worker_pool_owner.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
+#include "content/public/browser/cookie_crypto_delegate.h"
+#include "content/public/browser/cookie_store_factory.h"
+#include "crypto/encryptor.h"
+#include "crypto/symmetric_key.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_constants.h"
#include "sql/connection.h"
#include "sql/meta_table.h"
+#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -32,6 +37,36 @@ namespace {
const base::FilePath::CharType kCookieFilename[] = FILE_PATH_LITERAL("Cookies");
+class CookieCryptor : public content::CookieCryptoDelegate {
+ public:
+ CookieCryptor();
+ virtual bool EncryptString(const std::string& plaintext,
+ std::string* ciphertext) OVERRIDE;
+ virtual bool DecryptString(const std::string& ciphertext,
+ std::string* plaintext) OVERRIDE;
+
+ private:
+ scoped_ptr<crypto::SymmetricKey> key_;
+ crypto::Encryptor encryptor_;
+};
+
+CookieCryptor::CookieCryptor() : key_(
+ crypto::SymmetricKey::DeriveKeyFromPassword(
+ crypto::SymmetricKey::AES, "password", "saltiest", 1000, 256)) {
+ std::string iv("the iv: 16 bytes");
+ encryptor_.Init(key_.get(), crypto::Encryptor::CBC, iv);
+}
+
+bool CookieCryptor::EncryptString(const std::string& plaintext,
+ std::string* ciphertext) {
+ return encryptor_.Encrypt(plaintext, ciphertext);
+}
+
+bool CookieCryptor::DecryptString(const std::string& ciphertext,
+ std::string* plaintext) {
+ return encryptor_.Decrypt(ciphertext, plaintext);
+}
+
} // namespace
typedef std::vector<net::CanonicalCookie*> CanonicalCookieVector;
@@ -90,20 +125,24 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
pool_owner_.reset(new base::SequencedWorkerPoolOwner(3, "Background Pool"));
}
- void CreateAndLoad(bool restore_old_session_cookies,
+ void CreateAndLoad(bool crypt_cookies,
+ bool restore_old_session_cookies,
CanonicalCookieVector* cookies) {
store_ = new SQLitePersistentCookieStore(
temp_dir_.path().Append(kCookieFilename),
client_task_runner(),
background_task_runner(),
restore_old_session_cookies,
- NULL);
+ NULL,
+ crypt_cookies ?
+ scoped_ptr<content::CookieCryptoDelegate>(new CookieCryptor) :
+ scoped_ptr<content::CookieCryptoDelegate>());
Load(cookies);
}
- void InitializeStore(bool restore_old_session_cookies) {
+ void InitializeStore(bool crypt, bool restore_old_session_cookies) {
CanonicalCookieVector cookies;
- CreateAndLoad(restore_old_session_cookies, &cookies);
+ CreateAndLoad(crypt, restore_old_session_cookies, &cookies);
EXPECT_EQ(0U, cookies.size());
}
@@ -125,6 +164,14 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
net::COOKIE_PRIORITY_DEFAULT));
}
+ std::string ReadRawDBContents() {
+ std::string contents;
+ if (!base::ReadFileToString(temp_dir_.path().Append(kCookieFilename),
+ &contents))
+ return std::string();
+ return contents;
+ }
+
virtual void SetUp() OVERRIDE {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
}
@@ -146,13 +193,13 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
};
TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) {
- InitializeStore(false);
+ InitializeStore(false, false);
AddCookie("A", "B", "foo.bar", "/", base::Time::Now());
DestroyStore();
// Load up the store and verify that it has good data in it.
CanonicalCookieVector cookies;
- CreateAndLoad(false, &cookies);
+ CreateAndLoad(false, false, &cookies);
ASSERT_EQ(1U, cookies.size());
ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str());
ASSERT_STREQ("A", cookies[0]->Name().c_str());
@@ -171,13 +218,13 @@ TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) {
}
// Upon loading, the database should be reset to a good, blank state.
- CreateAndLoad(false, &cookies);
+ CreateAndLoad(false, false, &cookies);
ASSERT_EQ(0U, cookies.size());
// Verify that, after, recovery, the database persists properly.
AddCookie("X", "Y", "foo.bar", "/", base::Time::Now());
DestroyStore();
- CreateAndLoad(false, &cookies);
+ CreateAndLoad(false, false, &cookies);
ASSERT_EQ(1U, cookies.size());
ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str());
ASSERT_STREQ("X", cookies[0]->Name().c_str());
@@ -187,7 +234,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) {
// Test if data is stored as expected in the SQLite database.
TEST_F(SQLitePersistentCookieStoreTest, TestPersistance) {
- InitializeStore(false);
+ InitializeStore(false, false);
AddCookie("A", "B", "foo.bar", "/", base::Time::Now());
// Replace the store effectively destroying the current one and forcing it
// to write its data to disk. Then we can see if after loading it again it
@@ -195,7 +242,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestPersistance) {
DestroyStore();
// Reload and test for persistence
CanonicalCookieVector cookies;
- CreateAndLoad(false, &cookies);
+ CreateAndLoad(false, false, &cookies);
ASSERT_EQ(1U, cookies.size());
ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str());
ASSERT_STREQ("A", cookies[0]->Name().c_str());
@@ -207,14 +254,14 @@ TEST_F(SQLitePersistentCookieStoreTest, TestPersistance) {
STLDeleteElements(&cookies);
// Reload and check if the cookie has been removed.
- CreateAndLoad(false, &cookies);
+ CreateAndLoad(false, false, &cookies);
ASSERT_EQ(0U, cookies.size());
}
// Test that priority load of cookies for a specfic domain key could be
// completed before the entire store is loaded
TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) {
- InitializeStore(false);
+ InitializeStore(false, false);
base::Time t = base::Time::Now();
AddCookie("A", "B", "foo.bar", "/", t);
t += base::TimeDelta::FromInternalValue(10);
@@ -229,7 +276,9 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) {
temp_dir_.path().Append(kCookieFilename),
client_task_runner(),
background_task_runner(),
- false, NULL);
+ false, NULL,
+ scoped_ptr<content::CookieCryptoDelegate>());
+
// Posting a blocking task to db_thread_ makes sure that the DB thread waits
// until both Load and LoadCookiesForKey have been posted to its task queue.
background_task_runner()->PostTask(
@@ -284,12 +333,12 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) {
// Test that we can force the database to be written by calling Flush().
TEST_F(SQLitePersistentCookieStoreTest, TestFlush) {
- InitializeStore(false);
+ InitializeStore(false, false);
// File timestamps don't work well on all platforms, so we'll determine
// whether the DB file has been modified by checking its size.
base::FilePath path = temp_dir_.path().Append(kCookieFilename);
base::PlatformFileInfo info;
- ASSERT_TRUE(file_util::GetFileInfo(path, &info));
+ ASSERT_TRUE(base::GetFileInfo(path, &info));
int64 base_size = info.size;
// Write some large cookies, so the DB will have to expand by several KB.
@@ -304,13 +353,13 @@ TEST_F(SQLitePersistentCookieStoreTest, TestFlush) {
Flush();
// We forced a write, so now the file will be bigger.
- ASSERT_TRUE(file_util::GetFileInfo(path, &info));
+ ASSERT_TRUE(base::GetFileInfo(path, &info));
ASSERT_GT(info.size, base_size);
}
// Test loading old session cookies from the disk.
TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) {
- InitializeStore(true);
+ InitializeStore(false, true);
// Add a session cookie.
store_->AddCookie(
@@ -325,7 +374,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) {
// Create a store that loads session cookies and test that the session cookie
// was loaded.
CanonicalCookieVector cookies;
- CreateAndLoad(true, &cookies);
+ CreateAndLoad(false, true, &cookies);
ASSERT_EQ(1U, cookies.size());
ASSERT_STREQ("sessioncookie.com", cookies[0]->Domain().c_str());
@@ -338,7 +387,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) {
// Test loading old session cookies from the disk.
TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) {
- InitializeStore(true);
+ InitializeStore(false, true);
// Add a session cookie.
store_->AddCookie(
@@ -353,7 +402,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) {
// Create a store that doesn't load old session cookies and test that the
// session cookie was not loaded.
CanonicalCookieVector cookies;
- CreateAndLoad(false, &cookies);
+ CreateAndLoad(false, false, &cookies);
ASSERT_EQ(0U, cookies.size());
// The store should also delete the session cookie. Wait until that has been
@@ -362,12 +411,12 @@ TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) {
// Create a store that loads old session cookies and test that the session
// cookie is gone.
- CreateAndLoad(true, &cookies);
+ CreateAndLoad(false, true, &cookies);
ASSERT_EQ(0U, cookies.size());
}
TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) {
- InitializeStore(true);
+ InitializeStore(false, true);
static const char kSessionName[] = "session";
static const char kPersistentName[] = "persistent";
@@ -392,7 +441,7 @@ TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) {
// Create a store that loads session cookie and test that the IsPersistent
// attribute is restored.
CanonicalCookieVector cookies;
- CreateAndLoad(true, &cookies);
+ CreateAndLoad(false, true, &cookies);
ASSERT_EQ(2U, cookies.size());
std::map<std::string, net::CanonicalCookie*> cookie_map;
@@ -422,7 +471,7 @@ TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) {
static const char kCookieValue[] = "value";
static const char kCookiePath[] = "/";
- InitializeStore(true);
+ InitializeStore(false, true);
// Add a low-priority persistent cookie.
store_->AddCookie(
@@ -457,7 +506,7 @@ TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) {
// Create a store that loads session cookie and test that the priority
// attribute values are restored.
CanonicalCookieVector cookies;
- CreateAndLoad(true, &cookies);
+ CreateAndLoad(false, true, &cookies);
ASSERT_EQ(3U, cookies.size());
// Put the cookies into a map, by name, so we can easily find them.
@@ -485,4 +534,74 @@ TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) {
STLDeleteElements(&cookies);
}
+TEST_F(SQLitePersistentCookieStoreTest, UpdateToEncryption) {
+ CanonicalCookieVector cookies;
+
+ // Create unencrypted cookie store and write something to it.
+ InitializeStore(false, false);
+ AddCookie("name", "value123XYZ", "foo.bar", "/", base::Time::Now());
+ DestroyStore();
+
+ // Verify that "value" is visible in the file. This is necessary in order to
+ // have confidence in a later test that "encrypted_value" is not visible.
+ std::string contents = ReadRawDBContents();
+ EXPECT_NE(0U, contents.length());
+ EXPECT_NE(contents.find("value123XYZ"), std::string::npos);
+
+ // Create encrypted cookie store and ensure old cookie still reads.
+ STLDeleteElements(&cookies_);
+ EXPECT_EQ(0U, cookies_.size());
+ CreateAndLoad(true, false, &cookies);
+ EXPECT_EQ(1U, cookies_.size());
+ EXPECT_EQ("name", cookies_[0]->Name());
+ EXPECT_EQ("value123XYZ", cookies_[0]->Value());
+
+ // Make sure we can update existing cookie and add new cookie as encrypted.
+ store_->DeleteCookie(*(cookies_[0]));
+ AddCookie("name", "encrypted_value123XYZ", "foo.bar", "/", base::Time::Now());
+ AddCookie("other", "something456ABC", "foo.bar", "/",
+ base::Time::Now() + base::TimeDelta::FromInternalValue(10));
+ DestroyStore();
+ STLDeleteElements(&cookies_);
+ CreateAndLoad(true, false, &cookies);
+ EXPECT_EQ(2U, cookies_.size());
+ net::CanonicalCookie* cookie_name = NULL;
+ net::CanonicalCookie* cookie_other = NULL;
+ if (cookies_[0]->Name() == "name") {
+ cookie_name = cookies_[0];
+ cookie_other = cookies_[1];
+ } else {
+ cookie_name = cookies_[1];
+ cookie_other = cookies_[0];
+ }
+ EXPECT_EQ("encrypted_value123XYZ", cookie_name->Value());
+ EXPECT_EQ("something456ABC", cookie_other->Value());
+ DestroyStore();
+ STLDeleteElements(&cookies_);
+
+ // Examine the real record to make sure plaintext version doesn't exist.
+ sql::Connection db;
+ sql::Statement smt;
+ int resultcount = 0;
+ ASSERT_TRUE(db.Open(temp_dir_.path().Append(kCookieFilename)));
+ smt.Assign(db.GetCachedStatement(SQL_FROM_HERE,
+ "SELECT * "
+ "FROM cookies "
+ "WHERE host_key = 'foo.bar'"));
+ while (smt.Step()) {
+ resultcount++;
+ for (int i=0; i < smt.ColumnCount(); i++) {
+ EXPECT_EQ(smt.ColumnString(i).find("value"), std::string::npos);
+ EXPECT_EQ(smt.ColumnString(i).find("something"), std::string::npos);
+ }
+ }
+ EXPECT_EQ(2, resultcount);
+
+ // Verify that "encrypted_value" is NOT visible in the file.
+ contents = ReadRawDBContents();
+ EXPECT_NE(0U, contents.length());
+ EXPECT_EQ(contents.find("encrypted_value123XYZ"), std::string::npos);
+ EXPECT_EQ(contents.find("something456ABC"), std::string::npos);
+}
+
} // namespace content
diff --git a/chromium/content/browser/plugin_browsertest.cc b/chromium/content/browser/plugin_browsertest.cc
index 37e1fa9449c..204a1432038 100644
--- a/chromium/content/browser/plugin_browsertest.cc
+++ b/chromium/content/browser/plugin_browsertest.cc
@@ -5,15 +5,21 @@
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/path_service.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/common/shell_switches.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "content/test/net/url_request_mock_http_job.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/url_request/url_request.h"
#include "ui/gfx/rect.h"
#if defined(OS_WIN)
@@ -77,17 +83,17 @@ class PluginTest : public ContentBrowserTest {
}
static void LoadAndWaitInWindow(Shell* window, const GURL& url) {
- string16 expected_title(ASCIIToUTF16("OK"));
+ base::string16 expected_title(ASCIIToUTF16("OK"));
TitleWatcher title_watcher(window->web_contents(), expected_title);
title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
title_watcher.AlsoWaitForTitle(ASCIIToUTF16("plugin_not_found"));
NavigateToURL(window, url);
- string16 title = title_watcher.WaitAndGetTitle();
+ base::string16 title = title_watcher.WaitAndGetTitle();
if (title == ASCIIToUTF16("plugin_not_found")) {
const testing::TestInfo* const test_info =
testing::UnitTest::GetInstance()->current_test_info();
- LOG(INFO) << "PluginTest." << test_info->name() <<
- " not running because plugin not installed.";
+ VLOG(0) << "PluginTest." << test_info->name()
+ << " not running because plugin not installed.";
} else {
EXPECT_EQ(expected_title, title);
}
@@ -111,8 +117,8 @@ class PluginTest : public ContentBrowserTest {
if (!base::PathExists(path)) {
const testing::TestInfo* const test_info =
testing::UnitTest::GetInstance()->current_test_info();
- LOG(INFO) << "PluginTest." << test_info->name() <<
- " not running because test data wasn't found.";
+ VLOG(0) << "PluginTest." << test_info->name()
+ << " not running because test data wasn't found.";
return;
}
@@ -164,17 +170,23 @@ IN_PROC_BROWSER_TEST_F(PluginTest,
MAYBE(SelfDeletePluginInvokeInSynchronousMouseUp)) {
NavigateToURL(shell(), GetURL("execute_script_delete_in_mouse_up.html"));
- string16 expected_title(ASCIIToUTF16("OK"));
+ base::string16 expected_title(ASCIIToUTF16("OK"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
SimulateMouseClick(shell()->web_contents(), 0,
- WebKit::WebMouseEvent::ButtonLeft);
+ blink::WebMouseEvent::ButtonLeft);
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
}
#endif
-// Flaky, http://crbug.com/60071.
-IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURLRequest404Response)) {
+// Flaky, http://crbug.com/302274.
+#if defined(OS_MACOSX)
+#define MAYBE_GetURLRequest404Response DISABLED_GetURLRequest404Response
+#else
+#define MAYBE_GetURLRequest404Response MAYBE(GetURLRequest404Response)
+#endif
+
+IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE_GetURLRequest404Response) {
GURL url(URLRequestMockHTTPJob::GetMockUrl(
base::FilePath().AppendASCII("npapi").
AppendASCII("plugin_url_request_404.html")));
@@ -189,7 +201,7 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvokeAlert)) {
// race condition where the alert can come up before we start watching for it.
shell()->LoadURL(GetURL("self_delete_plugin_invoke_alert.html"));
- string16 expected_title(ASCIIToUTF16("OK"));
+ base::string16 expected_title(ASCIIToUTF16("OK"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
@@ -199,9 +211,12 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvokeAlert)) {
}
// Test passing arguments to a plugin.
+// crbug.com/306318
+#if !defined(OS_LINUX)
IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Arguments)) {
LoadAndWait(GetURL("arguments.html"));
}
+#endif
// Test invoking many plugins within a single page.
IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ManyPlugins)) {
@@ -226,7 +241,7 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetJavaScriptURL2)) {
}
// Test is flaky on linux/cros/win builders. http://crbug.com/71904
-IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_GetURLRedirectNotification) {
+IN_PROC_BROWSER_TEST_F(PluginTest, GetURLRedirectNotification) {
LoadAndWait(GetURL("geturl_redirect_notify.html"));
}
@@ -264,10 +279,10 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInNewStream)) {
LoadAndWait(GetURL("self_delete_plugin_stream.html"));
}
-// This test asserts on Mac in plugin_host in the NPNVWindowNPObject case.
-#if !(defined(OS_MACOSX) && !defined(NDEBUG))
-// If this test flakes use http://crbug.com/95558.
-IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(DeletePluginInDeallocate)) {
+// On Mac this test asserts in plugin_host: http://crbug.com/95558
+// On all platforms it flakes in ~URLRequestContext: http://crbug.com/310336
+#if !defined(NDEBUG)
+IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_DeletePluginInDeallocate) {
LoadAndWait(GetURL("plugin_delete_in_deallocate.html"));
}
#endif
@@ -393,7 +408,7 @@ IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_PluginConvertPointTest) {
NavigateToURL(shell(), GetURL("convert_point.html"));
- string16 expected_title(ASCIIToUTF16("OK"));
+ base::string16 expected_title(ASCIIToUTF16("OK"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title);
title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
// TODO(stuartmorgan): When the automation system supports sending clicks,
@@ -436,7 +451,14 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Real)) {
TestPlugin("real.html");
}
-IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(FlashOctetStream)) {
+// http://crbug.com/320041
+#if (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) || \
+ (defined(GOOGLE_CHROME_BUILD) && defined(OS_WIN))
+#define MAYBE_FlashOctetStream DISABLED_FlashOctetStream
+#else
+#define MAYBE_FlashOctetStream FlashOctetStream
+#endif
+IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE_FlashOctetStream) {
TestPlugin("flash-octet-stream.html");
}
@@ -459,4 +481,77 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Silverlight)) {
}
#endif // defined(OS_WIN)
+class TestResourceDispatcherHostDelegate
+ : public ResourceDispatcherHostDelegate {
+ public:
+ TestResourceDispatcherHostDelegate() : found_cookie_(false) {}
+
+ bool found_cookie() { return found_cookie_; }
+
+ void WaitForPluginRequest() {
+ if (found_cookie_)
+ return;
+
+ runner_ = new MessageLoopRunner;
+ runner_->Run();
+ }
+
+ private:
+ // ResourceDispatcherHostDelegate implementation:
+ virtual void OnResponseStarted(
+ net::URLRequest* request,
+ ResourceContext* resource_context,
+ ResourceResponse* response,
+ IPC::Sender* sender) OVERRIDE {
+ // The URL below comes from plugin_geturl_test.cc.
+ if (!EndsWith(request->url().spec(),
+ "npapi/plugin_ref_target_page.html",
+ true)) {
+ return;
+ }
+ net::HttpRequestHeaders headers;
+ bool found_cookie = false;
+ if (request->GetFullRequestHeaders(&headers) &&
+ headers.ToString().find("Cookie: blah") != std::string::npos) {
+ found_cookie = true;
+ }
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&TestResourceDispatcherHostDelegate::GotCookie,
+ base::Unretained(this), found_cookie));
+ }
+
+ void GotCookie(bool found_cookie) {
+ found_cookie_ = found_cookie;
+ if (runner_)
+ runner_->QuitClosure().Run();
+ }
+
+ scoped_refptr<MessageLoopRunner> runner_;
+ bool found_cookie_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherHostDelegate);
+};
+
+// Ensure that cookies get sent with plugin requests.
+IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Cookies)) {
+ // Create a new browser just to ensure that the plugin process' child_id is
+ // not equal to its type (PROCESS_TYPE_PLUGIN), as that was the error which
+ // caused this bug.
+ NavigateToURL(CreateBrowser(), GURL("about:blank"));
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ GURL url(embedded_test_server()->GetURL("/npapi/cookies.html"));
+
+ TestResourceDispatcherHostDelegate test_delegate;
+ ResourceDispatcherHostDelegate* old_delegate =
+ ResourceDispatcherHostImpl::Get()->delegate();
+ ResourceDispatcherHostImpl::Get()->SetDelegate(&test_delegate);
+ LoadAndWait(url);
+ test_delegate.WaitForPluginRequest();
+ ASSERT_TRUE(test_delegate.found_cookie());
+ ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate);
+}
+
} // namespace content
diff --git a/chromium/content/browser/plugin_loader_posix_unittest.cc b/chromium/content/browser/plugin_loader_posix_unittest.cc
index 8f907232121..13620f74dd3 100644
--- a/chromium/content/browser/plugin_loader_posix_unittest.cc
+++ b/chromium/content/browser/plugin_loader_posix_unittest.cc
@@ -64,11 +64,11 @@ class PluginLoaderPosixTest : public testing::Test {
public:
PluginLoaderPosixTest()
: plugin1_(ASCIIToUTF16("plugin1"), base::FilePath("/tmp/one.plugin"),
- ASCIIToUTF16("1.0"), string16()),
+ ASCIIToUTF16("1.0"), base::string16()),
plugin2_(ASCIIToUTF16("plugin2"), base::FilePath("/tmp/two.plugin"),
- ASCIIToUTF16("2.0"), string16()),
+ ASCIIToUTF16("2.0"), base::string16()),
plugin3_(ASCIIToUTF16("plugin3"), base::FilePath("/tmp/three.plugin"),
- ASCIIToUTF16("3.0"), string16()),
+ ASCIIToUTF16("3.0"), base::string16()),
file_thread_(BrowserThread::FILE, &message_loop_),
io_thread_(BrowserThread::IO, &message_loop_),
plugin_loader_(new MockPluginLoaderPosix) {
diff --git a/chromium/content/browser/plugin_process_host.cc b/chromium/content/browser/plugin_process_host.cc
index 86d313472e4..9ec7510dfcf 100644
--- a/chromium/content/browser/plugin_process_host.cc
+++ b/chromium/content/browser/plugin_process_host.cc
@@ -19,6 +19,7 @@
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/browser_child_process_host_impl.h"
@@ -265,7 +266,7 @@ bool PluginProcessHost::Init(const WebPluginInfo& info) {
ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
process_->GetData().id, PROCESS_TYPE_PLUGIN, NULL, NULL, NULL,
get_contexts_callback);
- process_->GetHost()->AddFilter(resource_message_filter);
+ process_->AddFilter(resource_message_filter);
return true;
}
@@ -275,10 +276,6 @@ void PluginProcessHost::ForceShutdown() {
process_->ForceShutdown();
}
-void PluginProcessHost::AddFilter(IPC::ChannelProxy::MessageFilter* filter) {
- process_->GetHost()->AddFilter(filter);
-}
-
bool PluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PluginProcessHost, msg)
@@ -408,20 +405,29 @@ void PluginProcessHost::OnChannelCreated(
Client* client = sent_requests_.front();
if (client) {
- resource_context_map_[client->ID()] = client->GetResourceContext();
+ if (!resource_context_map_.count(client->ID())) {
+ ResourceContextEntry entry;
+ entry.ref_count = 0;
+ entry.resource_context = client->GetResourceContext();
+ resource_context_map_[client->ID()] = entry;
+ }
+ resource_context_map_[client->ID()].ref_count++;
client->OnChannelOpened(channel_handle);
}
sent_requests_.pop_front();
}
void PluginProcessHost::OnChannelDestroyed(int renderer_id) {
- resource_context_map_.erase(renderer_id);
+ resource_context_map_[renderer_id].ref_count--;
+ if (!resource_context_map_[renderer_id].ref_count)
+ resource_context_map_.erase(renderer_id);
}
void PluginProcessHost::GetContexts(const ResourceHostMsg_Request& request,
ResourceContext** resource_context,
net::URLRequestContext** request_context) {
- *resource_context = resource_context_map_[request.origin_pid];
+ *resource_context =
+ resource_context_map_[request.origin_pid].resource_context;
*request_context = (*resource_context)->GetRequestContext();
}
diff --git a/chromium/content/browser/plugin_process_host.h b/chromium/content/browser/plugin_process_host.h
index 75c667daf0f..aaaf6ddf566 100644
--- a/chromium/content/browser/plugin_process_host.h
+++ b/chromium/content/browser/plugin_process_host.h
@@ -120,9 +120,6 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHostDelegate,
void AddWindow(HWND window);
#endif
- // Adds an IPC message filter. A reference will be kept to the filter.
- void AddFilter(IPC::ChannelProxy::MessageFilter* filter);
-
private:
// Sends a message to the plugin process to request creation of a new channel
// for the given mime type.
@@ -185,8 +182,15 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHostDelegate,
bool plugin_cursor_visible_;
#endif
- // Map from render_process_id to its ResourceContext
- typedef std::map<int, ResourceContext*> ResourceContextMap;
+ // Map from render_process_id to its ResourceContext. Instead of storing the
+ // raw pointer, we store the struct below. This is needed because a renderer
+ // process can actually have multiple IPC channels to the same plugin process,
+ // depending on timing conditions with plugin instance creation and shutdown.
+ struct ResourceContextEntry {
+ ResourceContext* resource_context;
+ int ref_count;
+ };
+ typedef std::map<int, ResourceContextEntry> ResourceContextMap;
ResourceContextMap resource_context_map_;
scoped_ptr<BrowserChildProcessHostImpl> process_;
diff --git a/chromium/content/browser/plugin_service_impl.cc b/chromium/content/browser/plugin_service_impl.cc
index b46af4fbeff..cb0a7b4e599 100644
--- a/chromium/content/browser/plugin_service_impl.cc
+++ b/chromium/content/browser/plugin_service_impl.cc
@@ -171,25 +171,8 @@ void PluginServiceImpl::Init() {
RegisterPepperPlugins();
- // The --site-per-process flag enables an out-of-process iframes
- // prototype, which uses WebView for rendering. We need to register the MIME
- // type we use with the plugin, so the renderer can instantiate it.
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kSitePerProcess)) {
- WebPluginInfo webview_plugin(
- ASCIIToUTF16("WebView Tag"),
- base::FilePath(),
- ASCIIToUTF16("1.2.3.4"),
- ASCIIToUTF16("Browser Plugin."));
- webview_plugin.type = WebPluginInfo::PLUGIN_TYPE_NPAPI;
- WebPluginMimeType webview_plugin_mime_type;
- webview_plugin_mime_type.mime_type = "application/browser-plugin";
- webview_plugin_mime_type.file_extensions.push_back("*");
- webview_plugin.mime_types.push_back(webview_plugin_mime_type);
- RegisterInternalPlugin(webview_plugin, true);
- }
-
// Load any specified on the command line as well.
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
base::FilePath path =
command_line->GetSwitchValuePath(switches::kLoadPlugin);
if (!path.empty())
@@ -315,7 +298,12 @@ PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
START_NPAPI_FLASH_AT_LEAST_ONCE,
FLASH_USAGE_ENUM_COUNT);
}
-
+#if defined(OS_CHROMEOS)
+ // TODO(ihf): Move to an earlier place once crbug.com/314301 is fixed. For now
+ // we still want Plugin.FlashUsage recorded if we end up here.
+ LOG(WARNING) << "Refusing to start npapi plugin on ChromeOS.";
+ return NULL;
+#endif
// This plugin isn't loaded by any plugin process, so create a new process.
scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
if (!new_host->Init(info)) {
@@ -331,8 +319,10 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
const base::FilePath& profile_data_directory) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
+ if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) {
+ VLOG(1) << "Unable to load ppapi plugin: " << plugin_path.MaybeAsASCII();
return NULL;
+ }
PpapiPluginProcessHost* plugin_host =
FindPpapiPluginProcess(plugin_path, profile_data_directory);
@@ -341,8 +331,11 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
// Validate that the plugin is actually registered.
PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
- if (!info)
+ if (!info) {
+ VLOG(1) << "Unable to find ppapi plugin registration for: "
+ << plugin_path.MaybeAsASCII();
return NULL;
+ }
// Record when PPAPI Flash process is started for the first time.
static bool counted = false;
@@ -354,8 +347,14 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
}
// This plugin isn't loaded by any plugin process, so create a new process.
- return PpapiPluginProcessHost::CreatePluginHost(
+ plugin_host = PpapiPluginProcessHost::CreatePluginHost(
*info, profile_data_directory);
+ if (!plugin_host) {
+ VLOG(1) << "Unable to create ppapi plugin process for: "
+ << plugin_path.MaybeAsASCII();
+ }
+
+ return plugin_host;
}
PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
@@ -384,7 +383,7 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
void PluginServiceImpl::OpenChannelToNpapiPlugin(
int render_process_id,
- int render_view_id,
+ int render_frame_id,
const GURL& url,
const GURL& page_url,
const std::string& mime_type,
@@ -396,7 +395,7 @@ void PluginServiceImpl::OpenChannelToNpapiPlugin(
// Make sure plugins are loaded if necessary.
PluginServiceFilterParams params = {
render_process_id,
- render_view_id,
+ render_frame_id,
page_url,
client->GetResourceContext()
};
@@ -447,14 +446,14 @@ void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
const std::string& mime_type,
PluginProcessHost::Client* client,
const std::vector<WebPluginInfo>&) {
- GetAllowedPluginForOpenChannelToPlugin(params.render_process_id,
- params.render_view_id, url, params.page_url, mime_type, client,
- params.resource_context);
+ GetAllowedPluginForOpenChannelToPlugin(
+ params.render_process_id, params.render_frame_id, url, params.page_url,
+ mime_type, client, params.resource_context);
}
void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
int render_process_id,
- int render_view_id,
+ int render_frame_id,
const GURL& url,
const GURL& page_url,
const std::string& mime_type,
@@ -463,7 +462,7 @@ void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
WebPluginInfo info;
bool allow_wildcard = true;
bool found = GetPluginInfo(
- render_process_id, render_view_id, resource_context,
+ render_process_id, render_frame_id, resource_context,
url, page_url, mime_type, allow_wildcard,
NULL, &info, NULL);
base::FilePath plugin_path;
@@ -515,7 +514,7 @@ bool PluginServiceImpl::GetPluginInfoArray(
}
bool PluginServiceImpl::GetPluginInfo(int render_process_id,
- int render_view_id,
+ int render_frame_id,
ResourceContext* context,
const GURL& url,
const GURL& page_url,
@@ -533,7 +532,7 @@ bool PluginServiceImpl::GetPluginInfo(int render_process_id,
for (size_t i = 0; i < plugins.size(); ++i) {
if (!filter_ || filter_->IsPluginAvailable(render_process_id,
- render_view_id,
+ render_frame_id,
context,
url,
page_url,
@@ -564,9 +563,9 @@ bool PluginServiceImpl::GetPluginInfoByPath(const base::FilePath& plugin_path,
return false;
}
-string16 PluginServiceImpl::GetPluginDisplayNameByPath(
+base::string16 PluginServiceImpl::GetPluginDisplayNameByPath(
const base::FilePath& path) {
- string16 plugin_name = path.LossyDisplayName();
+ base::string16 plugin_name = path.LossyDisplayName();
WebPluginInfo info;
if (PluginService::GetInstance()->GetPluginInfoByPath(path, &info) &&
!info.name.empty()) {
@@ -753,7 +752,7 @@ void PluginServiceImpl::AddExtraPluginPath(const base::FilePath& path) {
if (!NPAPIPluginsSupported()) {
// TODO(jam): remove and just have CHECK once we're sure this doesn't get
// triggered.
- DLOG(INFO) << "NPAPI plugins not supported";
+ DVLOG(0) << "NPAPI plugins not supported";
return;
}
PluginList::Singleton()->AddExtraPluginPath(path);
@@ -772,7 +771,7 @@ void PluginServiceImpl::RegisterInternalPlugin(
bool add_at_beginning) {
if (!NPAPIPluginsSupported() &&
info.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
- DLOG(INFO) << "Don't register NPAPI plugins when they're not supported";
+ DVLOG(0) << "Don't register NPAPI plugins when they're not supported";
return;
}
PluginList::Singleton()->RegisterInternalPlugin(info, add_at_beginning);
@@ -842,4 +841,9 @@ bool PluginServiceImpl::IsPluginWindow(HWND window) {
}
#endif
+bool PluginServiceImpl::PpapiDevChannelSupported() {
+ return content::GetContentClient()->browser()->
+ IsPluginAllowedToUseDevChannelAPIs();
+}
+
} // namespace content
diff --git a/chromium/content/browser/plugin_service_impl.h b/chromium/content/browser/plugin_service_impl.h
index 11fb257e99b..e95fa7c9786 100644
--- a/chromium/content/browser/plugin_service_impl.h
+++ b/chromium/content/browser/plugin_service_impl.h
@@ -59,7 +59,7 @@ struct PepperPluginInfo;
// surpass that limit.
struct PluginServiceFilterParams {
int render_process_id;
- int render_view_id;
+ int render_frame_id;
GURL page_url;
ResourceContext* resource_context;
};
@@ -80,7 +80,7 @@ class CONTENT_EXPORT PluginServiceImpl
std::vector<WebPluginInfo>* info,
std::vector<std::string>* actual_mime_types) OVERRIDE;
virtual bool GetPluginInfo(int render_process_id,
- int render_view_id,
+ int render_frame_id,
ResourceContext* context,
const GURL& url,
const GURL& page_url,
@@ -91,7 +91,7 @@ class CONTENT_EXPORT PluginServiceImpl
std::string* actual_mime_type) OVERRIDE;
virtual bool GetPluginInfoByPath(const base::FilePath& plugin_path,
WebPluginInfo* info) OVERRIDE;
- virtual string16 GetPluginDisplayNameByPath(
+ virtual base::string16 GetPluginDisplayNameByPath(
const base::FilePath& path) OVERRIDE;
virtual void GetPlugins(const GetPluginsCallback& callback) OVERRIDE;
virtual PepperPluginInfo* GetRegisteredPpapiPluginInfo(
@@ -121,6 +121,7 @@ class CONTENT_EXPORT PluginServiceImpl
// Returns true iff the given HWND is a plugin.
bool IsPluginWindow(HWND window);
#endif
+ virtual bool PpapiDevChannelSupported() OVERRIDE;
// Returns the plugin process host corresponding to the plugin process that
// has been started by this service. This will start a process to host the
@@ -139,7 +140,7 @@ class CONTENT_EXPORT PluginServiceImpl
// a new plugin process if necessary. This must be called on the IO thread
// or else a deadlock can occur.
void OpenChannelToNpapiPlugin(int render_process_id,
- int render_view_id,
+ int render_frame_id,
const GURL& url,
const GURL& page_url,
const std::string& mime_type,
@@ -195,7 +196,7 @@ class CONTENT_EXPORT PluginServiceImpl
// Helper so we can do the plugin lookup on the FILE thread.
void GetAllowedPluginForOpenChannelToPlugin(
int render_process_id,
- int render_view_id,
+ int render_frame_id,
const GURL& url,
const GURL& page_url,
const std::string& mime_type,
diff --git a/chromium/content/browser/power_save_blocker_android.cc b/chromium/content/browser/power_save_blocker_android.cc
index 720fbb2bcd5..ad9b24cb276 100644
--- a/chromium/content/browser/power_save_blocker_android.cc
+++ b/chromium/content/browser/power_save_blocker_android.cc
@@ -11,7 +11,7 @@
#include "content/public/browser/android/content_view_core.h"
#include "content/public/browser/browser_thread.h"
#include "jni/PowerSaveBlocker_jni.h"
-#include "ui/android/view_android.h"
+#include "ui/base/android/view_android.h"
using base::android::AttachCurrentThread;
using base::android::ScopedJavaLocalRef;
diff --git a/chromium/content/browser/power_save_blocker_mac.cc b/chromium/content/browser/power_save_blocker_mac.cc
index ec340a1c2c6..9b3fe090c3c 100644
--- a/chromium/content/browser/power_save_blocker_mac.cc
+++ b/chromium/content/browser/power_save_blocker_mac.cc
@@ -22,7 +22,9 @@ namespace {
// 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");
diff --git a/chromium/content/browser/power_save_blocker_win.cc b/chromium/content/browser/power_save_blocker_win.cc
index fce72c65b62..cf9bb02301a 100644
--- a/chromium/content/browser/power_save_blocker_win.cc
+++ b/chromium/content/browser/power_save_blocker_win.cc
@@ -39,7 +39,7 @@ HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type, const std::string& reason) {
if (!PowerCreateRequestFn || !PowerSetRequestFn)
return INVALID_HANDLE_VALUE;
}
- string16 wide_reason = ASCIIToUTF16(reason);
+ base::string16 wide_reason = ASCIIToUTF16(reason);
REASON_CONTEXT context = {0};
context.Version = POWER_REQUEST_CONTEXT_VERSION;
context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index ecbbfd6bfce..2cecc772d4b 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -117,6 +117,7 @@ PpapiPluginProcessHost* PpapiPluginProcessHost::CreatePluginHost(
const base::FilePath& profile_data_directory) {
PpapiPluginProcessHost* plugin_host = new PpapiPluginProcessHost(
info, profile_data_directory);
+ DCHECK(plugin_host);
if (plugin_host->Init(info))
return plugin_host;
@@ -178,7 +179,7 @@ void PpapiPluginProcessHost::DidDeleteOutOfProcessInstance(
// static
void PpapiPluginProcessHost::FindByName(
- const string16& name,
+ const base::string16& name,
std::vector<PpapiPluginProcessHost*>* hosts) {
for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) {
if (iter->process_.get() && iter->process_->GetData().name == name)
@@ -215,10 +216,11 @@ PpapiPluginProcessHost::PpapiPluginProcessHost(
host_impl_.reset(new BrowserPpapiHostImpl(this, permissions_, info.name,
info.path, profile_data_directory,
- false));
+ false /* in_process */,
+ false /* external_plugin */));
filter_ = new PepperMessageFilter();
- process_->GetHost()->AddFilter(filter_.get());
+ process_->AddFilter(filter_.get());
process_->GetHost()->AddFilter(host_impl_->message_filter().get());
GetContentClient()->browser()->DidCreatePpapiPlugin(host_impl_.get());
@@ -239,7 +241,8 @@ PpapiPluginProcessHost::PpapiPluginProcessHost()
host_impl_.reset(new BrowserPpapiHostImpl(this, permissions,
std::string(), base::FilePath(),
base::FilePath(),
- false));
+ false /* in_process */,
+ false /* external_plugin */));
}
bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
@@ -251,8 +254,10 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
}
std::string channel_id = process_->GetHost()->CreateChannel();
- if (channel_id.empty())
+ if (channel_id.empty()) {
+ VLOG(1) << "Could not create pepper host channel.";
return false;
+ }
const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
CommandLine::StringType plugin_launcher =
@@ -265,8 +270,10 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
int flags = ChildProcessHost::CHILD_NORMAL;
#endif
base::FilePath exe_path = ChildProcessHost::GetChildPath(flags);
- if (exe_path.empty())
+ if (exe_path.empty()) {
+ VLOG(1) << "Pepper plugin exe path is empty.";
return false;
+ }
CommandLine* cmd_line = new CommandLine(exe_path);
cmd_line->AppendSwitchASCII(switches::kProcessType,
@@ -297,11 +304,15 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
// TODO(vtl): Stop passing flash args in the command line, or windows is
// going to explode.
std::string field_trial =
- base::FieldTrialList::FindFullName(kLowLatencyFlashAudioFieldTrialName);
+ base::FieldTrialList::FindFullName(kFlashHwVideoDecodeFieldTrialName);
std::string existing_args =
browser_command_line.GetSwitchValueASCII(switches::kPpapiFlashArgs);
- if (field_trial == kLowLatencyFlashAudioFieldTrialEnabledName)
- existing_args.append(" enable_low_latency_audio=1");
+ if (field_trial == kFlashHwVideoDecodeFieldTrialEnabledName) {
+ // Arguments passed to Flash are comma delimited.
+ if (!existing_args.empty())
+ existing_args.append(",");
+ existing_args.append("enable_hw_video_decode=1");
+ }
cmd_line->AppendSwitchASCII(switches::kPpapiFlashArgs, existing_args);
}
@@ -355,10 +366,12 @@ void PpapiPluginProcessHost::RequestPluginChannel(Client* client) {
}
void PpapiPluginProcessHost::OnProcessLaunched() {
+ VLOG(2) << "ppapi plugin process launched.";
host_impl_->set_plugin_process_handle(process_->GetHandle());
}
void PpapiPluginProcessHost::OnProcessCrashed(int exit_code) {
+ VLOG(1) << "ppapi plugin process crashed.";
PluginServiceImpl::GetInstance()->RegisterPluginCrash(plugin_path_);
}
@@ -375,10 +388,13 @@ bool PpapiPluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
// Called when the browser <--> plugin channel has been established.
void PpapiPluginProcessHost::OnChannelConnected(int32 peer_pid) {
+ bool supports_dev_channel =
+ GetContentClient()->browser()->IsPluginAllowedToUseDevChannelAPIs();
// This will actually load the plugin. Errors will actually not be reported
// back at this point. Instead, the plugin will fail to establish the
// connections when we request them on behalf of the renderer(s).
- Send(new PpapiMsg_LoadPlugin(plugin_path_, permissions_));
+ Send(new PpapiMsg_LoadPlugin(plugin_path_, permissions_,
+ supports_dev_channel));
// Process all pending channel requests from the renderers.
for (size_t i = 0; i < pending_requests_.size(); i++)
@@ -389,8 +405,8 @@ void PpapiPluginProcessHost::OnChannelConnected(int32 peer_pid) {
// Called when the browser <--> plugin channel has an error. This normally
// means the plugin has crashed.
void PpapiPluginProcessHost::OnChannelError() {
- DVLOG(1) << "PpapiPluginProcessHost" << (is_broker_ ? "[broker]" : "")
- << "::OnChannelError()";
+ VLOG(1) << "PpapiPluginProcessHost" << (is_broker_ ? "[broker]" : "")
+ << "::OnChannelError()";
// We don't need to notify the renderers that were communicating with the
// plugin since they have their own channels which will go into the error
// state at the same time. Instead, we just need to notify any renderers
diff --git a/chromium/content/browser/ppapi_plugin_process_host.h b/chromium/content/browser/ppapi_plugin_process_host.h
index 87c79c31d2a..594c12f6152 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.h
+++ b/chromium/content/browser/ppapi_plugin_process_host.h
@@ -92,7 +92,7 @@ class PpapiPluginProcessHost : public BrowserChildProcessHostDelegate,
// Returns the instances that match the specified process name.
// It can only be called on the IO thread.
- static void FindByName(const string16& name,
+ static void FindByName(const base::string16& name,
std::vector<PpapiPluginProcessHost*>* hosts);
// IPC::Sender implementation:
diff --git a/chromium/content/browser/profiler_message_filter.cc b/chromium/content/browser/profiler_message_filter.cc
index cb30f257d96..adea8e71fa0 100644
--- a/chromium/content/browser/profiler_message_filter.cc
+++ b/chromium/content/browser/profiler_message_filter.cc
@@ -16,8 +16,6 @@ ProfilerMessageFilter::ProfilerMessageFilter(int process_type)
}
void ProfilerMessageFilter::OnChannelConnected(int32 peer_pid) {
- BrowserMessageFilter::OnChannelConnected(peer_pid);
-
tracked_objects::ThreadData::Status status =
tracked_objects::ThreadData::status();
Send(new ChildProcessMsg_SetProfilerStatus(status));
diff --git a/chromium/content/browser/renderer_data_memoizing_store.h b/chromium/content/browser/renderer_data_memoizing_store.h
new file mode 100644
index 00000000000..ff55982b1a8
--- /dev/null
+++ b/chromium/content/browser/renderer_data_memoizing_store.h
@@ -0,0 +1,214 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_DATA_MEMOIZING_STORE_H_
+#define CONTENT_BROWSER_RENDERER_DATA_MEMOIZING_STORE_H_
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/synchronization/lock.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host_observer.h"
+
+namespace content {
+
+// RendererDataMemoizingStore is a thread-safe container that retains reference
+// counted objects that are associated with one or more render processes.
+// Objects are identified by an int and only a single reference to a given
+// object is retained. RendererDataMemoizingStore watches for render process
+// termination and releases objects that are no longer associated with any
+// render process.
+//
+// TODO(jcampan): Rather than watching for render process termination, we should
+// instead be listening to events such as resource cached/
+// removed from cache, and remove the items when we know they
+// are not used anymore.
+template <typename T>
+class RendererDataMemoizingStore : public RenderProcessHostObserver {
+ public:
+ RendererDataMemoizingStore() : next_item_id_(1) {
+ }
+
+ ~RendererDataMemoizingStore() {
+ DCHECK_EQ(0U, id_to_item_.size()) << "Failed to outlive render processes";
+ }
+
+ // Store adds |item| to this collection, associates it with the given render
+ // process id and returns an opaque identifier for it. If |item| is already
+ // known, the same identifier will be returned.
+ int Store(T* item, int process_id) {
+ DCHECK(item);
+ base::AutoLock auto_lock(lock_);
+
+ int item_id;
+
+ // Do we already know this item?
+ typename ReverseItemMap::iterator item_iter = item_to_id_.find(item);
+ if (item_iter == item_to_id_.end()) {
+ item_id = next_item_id_++;
+ // We use 0 as an invalid item_id value. In the unlikely event that
+ // next_item_id_ wraps around, we reset it to 1.
+ if (next_item_id_ == 0)
+ next_item_id_ = 1;
+ id_to_item_[item_id] = item;
+ item_to_id_[item] = item_id;
+ } else {
+ item_id = item_iter->second;
+ }
+
+ // Let's update process_id_to_item_id_.
+ std::pair<IDMap::iterator, IDMap::iterator> process_ids =
+ process_id_to_item_id_.equal_range(process_id);
+ bool already_watching_process = (process_ids.first != process_ids.second);
+ if (std::find_if(process_ids.first, process_ids.second,
+ MatchSecond<int>(item_id)) == process_ids.second) {
+ process_id_to_item_id_.insert(std::make_pair(process_id, item_id));
+ }
+
+ // And item_id_to_process_id_.
+ std::pair<IDMap::iterator, IDMap::iterator> item_ids =
+ item_id_to_process_id_.equal_range(item_id);
+ if (std::find_if(item_ids.first, item_ids.second,
+ MatchSecond<int>(process_id)) == item_ids.second) {
+ item_id_to_process_id_.insert(std::make_pair(item_id, process_id));
+ }
+
+ // If we're not doing so already, keep an eye for the process host deletion.
+ if (!already_watching_process) {
+ if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ StartObservingProcess(process_id);
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&RendererDataMemoizingStore::StartObservingProcess,
+ base::Unretained(this),
+ process_id));
+ }
+ }
+
+ return item_id;
+ }
+
+ // Retrieve fetches a previously Stored() item, identified by |item_id|.
+ // If |item_id| is recognized, |item| will be updated and Retrieve() will
+ // return true, it will otherwise return false.
+ bool Retrieve(int item_id, scoped_refptr<T>* item) {
+ base::AutoLock auto_lock(lock_);
+
+ typename ItemMap::iterator iter = id_to_item_.find(item_id);
+ if (iter == id_to_item_.end())
+ return false;
+ if (item)
+ *item = iter->second;
+ return true;
+ }
+
+ private:
+ typedef std::multimap<int, int> IDMap;
+ typedef std::map<int, scoped_refptr<T> > ItemMap;
+ typedef std::map<T*, int, typename T::LessThan> ReverseItemMap;
+
+ template <typename M>
+ struct MatchSecond {
+ explicit MatchSecond(const M& t) : value(t) {}
+
+ template <typename Pair>
+ bool operator()(const Pair& p) const {
+ return (value == p.second);
+ }
+
+ M value;
+ };
+
+ void StartObservingProcess(int process_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RenderProcessHost* host = RenderProcessHost::FromID(process_id);
+ if (!host) {
+ // We lost the race to observe the host before it was destroyed. Since
+ // this function was called because we're managing objects tied to that
+ // (now destroyed) RenderProcessHost, let's clean up.
+ RemoveRenderProcessItems(process_id);
+ return;
+ }
+
+ host->AddObserver(this);
+ }
+
+ // Remove the item specified by |item_id| from id_to_item_ and item_to_id_.
+ // NOTE: the caller (RemoveRenderProcessItems) must hold lock_.
+ void RemoveInternal(int item_id) {
+ typename ItemMap::iterator item_iter = id_to_item_.find(item_id);
+ DCHECK(item_iter != id_to_item_.end());
+
+ typename ReverseItemMap::iterator id_iter =
+ item_to_id_.find(item_iter->second.get());
+ DCHECK(id_iter != item_to_id_.end());
+ item_to_id_.erase(id_iter);
+
+ id_to_item_.erase(item_iter);
+ }
+
+ void RenderProcessHostDestroyed(RenderProcessHost* host) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RemoveRenderProcessItems(host->GetID());
+ }
+
+ // Removes all the items associated with the specified process from the store.
+ void RemoveRenderProcessItems(int process_id) {
+ base::AutoLock auto_lock(lock_);
+
+ // We iterate through all the item ids for that process.
+ std::pair<IDMap::iterator, IDMap::iterator> process_ids =
+ process_id_to_item_id_.equal_range(process_id);
+ for (IDMap::iterator ids_iter = process_ids.first;
+ ids_iter != process_ids.second; ++ids_iter) {
+ int item_id = ids_iter->second;
+ // Find all the processes referring to this item id in
+ // item_id_to_process_id_, then locate the process being removed within
+ // that range.
+ std::pair<IDMap::iterator, IDMap::iterator> item_ids =
+ item_id_to_process_id_.equal_range(item_id);
+ IDMap::iterator proc_iter = std::find_if(
+ item_ids.first, item_ids.second, MatchSecond<int>(process_id));
+ DCHECK(proc_iter != item_ids.second);
+
+ // Before removing, determine if no other processes refer to the current
+ // item id. If |proc_iter| (the current process) is the lower bound of
+ // processes containing the current item id and if |next_proc_iter| is the
+ // upper bound (the first process that does not), then only one process,
+ // the one being removed, refers to the item id.
+ IDMap::iterator next_proc_iter = proc_iter;
+ ++next_proc_iter;
+ bool last_process_for_item_id =
+ (proc_iter == item_ids.first && next_proc_iter == item_ids.second);
+ item_id_to_process_id_.erase(proc_iter);
+
+ if (last_process_for_item_id) {
+ // The current item id is not referenced by any other processes, so
+ // remove it from id_to_item_ and item_to_id_.
+ RemoveInternal(item_id);
+ }
+ }
+ if (process_ids.first != process_ids.second)
+ process_id_to_item_id_.erase(process_ids.first, process_ids.second);
+ }
+
+ IDMap process_id_to_item_id_;
+ IDMap item_id_to_process_id_;
+ ItemMap id_to_item_;
+ ReverseItemMap item_to_id_;
+
+ int next_item_id_;
+
+ // This lock protects: process_id_to_item_id_, item_id_to_process_id_,
+ // id_to_item_, and item_to_id_.
+ base::Lock lock_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_DATA_MEMOIZING_STORE_H_
diff --git a/chromium/content/browser/renderer_host/DEPS b/chromium/content/browser/renderer_host/DEPS
index 0848d364726..1d612c46229 100644
--- a/chromium/content/browser/renderer_host/DEPS
+++ b/chromium/content/browser/renderer_host/DEPS
@@ -7,20 +7,33 @@ include_rules = [
# The renderer_host files should only call upwards in the layering via the
# delegate interfaces.
+ "-content/browser/frame_host",
"-content/browser/web_contents",
"-content/public/browser/web_contents.h",
+ "-content/public/browser/web_contents_delegate.h",
"-content/public/browser/web_contents_view.h",
]
specific_include_rules = {
".*_(unit|browser)test\.cc": [
+ "+content/browser/frame_host",
"+content/browser/web_contents",
"+content/public/browser/web_contents.h",
"+content/public/browser/web_contents_view.h",
"+media/filters",
],
"render_sandbox_host_linux\.cc": [
+ "+third_party/WebKit/public/platform/linux/WebFontInfo.h",
"+third_party/WebKit/public/web/WebKit.h",
- "+third_party/WebKit/public/web/linux/WebFontInfo.h",
+ ],
+ "render_process_host_impl\.cc": [
+ "+content/browser/frame_host/render_frame_message_filter.h",
+ ],
+ # TODO(nasko): Remove these exceptions once we've untangled the dependency
+ # of RenderViewHost on the FrameTree.
+ "render_view_host_impl\.(cc|h)": [
+ "+content/browser/frame_host/frame_tree.h",
+ "+content/browser/frame_host/render_frame_host_factory.h",
+ "+content/browser/frame_host/render_frame_host_impl.h",
],
}
diff --git a/chromium/content/browser/renderer_host/OWNERS b/chromium/content/browser/renderer_host/OWNERS
index 920b6c56429..93266a3f46b 100644
--- a/chromium/content/browser/renderer_host/OWNERS
+++ b/chromium/content/browser/renderer_host/OWNERS
@@ -1,5 +1,3 @@
-jochen@chromium.org
-
# for *aura*
per-file *aura*=ben@chromium.org
@@ -19,3 +17,8 @@ aelias@chromium.org
# For touch/gesture specific changes
rjkroege@chromium.org
sadrul@chromium.org
+
+# WebSocket
+per-file *websocket*=ricea@chromium.org
+per-file *websocket*=tyoshino@chromium.org
+per-file *websocket*=yhirano@chromium.org
diff --git a/chromium/content/browser/renderer_host/backing_store_aura.cc b/chromium/content/browser/renderer_host/backing_store_aura.cc
index 5f976c45ea3..105bf446acd 100644
--- a/chromium/content/browser/renderer_host/backing_store_aura.cc
+++ b/chromium/content/browser/renderer_host/backing_store_aura.cc
@@ -38,7 +38,7 @@ BackingStoreAura::BackingStoreAura(RenderWidgetHost* widget,
const gfx::Size& size)
: BackingStore(widget, size) {
device_scale_factor_ =
- ui::GetScaleFactorScale(GetScaleFactorForView(widget->GetView()));
+ ui::GetImageScale(GetScaleFactorForView(widget->GetView()));
gfx::Size pixel_size = ToPixelSize(size, device_scale_factor_);
bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
pixel_size.width(), pixel_size.height());
@@ -52,7 +52,7 @@ BackingStoreAura::~BackingStoreAura() {
void BackingStoreAura::SkiaShowRect(const gfx::Point& point,
gfx::Canvas* canvas) {
gfx::ImageSkia image = gfx::ImageSkia(gfx::ImageSkiaRep(bitmap_,
- ui::GetScaleFactorFromScale(device_scale_factor_)));
+ device_scale_factor_));
canvas->DrawImageInt(image, point.x(), point.y());
}
diff --git a/chromium/content/browser/renderer_host/backing_store_gtk.cc b/chromium/content/browser/renderer_host/backing_store_gtk.cc
index 2eed33ace2f..147ee4d224e 100644
--- a/chromium/content/browser/renderer_host/backing_store_gtk.cc
+++ b/chromium/content/browser/renderer_host/backing_store_gtk.cc
@@ -272,7 +272,7 @@ BackingStoreGtk::BackingStoreGtk(RenderWidgetHost* widget,
pixmap_bpp_ = 0;
} else {
picture_ = 0;
- pixmap_bpp_ = ui::BitsPerPixelForPixmapDepth(display_, depth);
+ pixmap_bpp_ = gfx::BitsPerPixelForPixmapDepth(display_, depth);
}
pixmap_gc_ = XCreateGC(display_, pixmap_, 0, NULL);
@@ -320,9 +320,9 @@ void BackingStoreGtk::PaintRectWithoutXrender(
visual_depth_);
// Draw ARGB transport DIB onto our pixmap.
- ui::PutARGBImage(display_, visual_, visual_depth_, pixmap,
- pixmap_gc_, static_cast<uint8*>(bitmap->memory()),
- width, height);
+ gfx::PutARGBImage(display_, visual_, visual_depth_, pixmap,
+ pixmap_gc_, static_cast<uint8*>(bitmap->memory()),
+ width, height);
for (size_t i = 0; i < copy_rects.size(); i++) {
const gfx::Rect& copy_rect = copy_rects[i];
diff --git a/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc b/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc
deleted file mode 100644
index e4563375681..00000000000
--- a/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h"
-
-#include "base/debug/trace_event.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-
-namespace content {
-
-BasicMouseWheelSmoothScrollGesture::BasicMouseWheelSmoothScrollGesture(
- bool scroll_down, int pixels_to_scroll,
- int mouse_event_x, int mouse_event_y)
- : scroll_down_(scroll_down),
- pixels_scrolled_(0),
- pixels_to_scroll_(pixels_to_scroll),
- mouse_event_x_(mouse_event_x),
- mouse_event_y_(mouse_event_y) { }
-
-BasicMouseWheelSmoothScrollGesture::~BasicMouseWheelSmoothScrollGesture() { }
-
-bool BasicMouseWheelSmoothScrollGesture::ForwardInputEvents(
- base::TimeTicks now, RenderWidgetHost* host) {
-
- if (pixels_scrolled_ >= pixels_to_scroll_)
- return false;
-
- float position_delta = synthetic_gesture_calculator_.GetDelta(
- now,
- RenderWidgetHostImpl::From(host)->GetSyntheticGestureMessageInterval());
-
-
- WebKit::WebMouseWheelEvent event;
- event.type = WebKit::WebInputEvent::MouseWheel;
- event.hasPreciseScrollingDeltas = 0;
- event.deltaY = scroll_down_ ? -position_delta : position_delta;
- // TODO(vollick): find a proper way to access
- // WebCore::WheelEvent::tickMultiplier.
- event.wheelTicksY = event.deltaY / 120;
- event.modifiers = 0;
-
- // TODO(nduca): Figure out plausible x and y values.
- event.globalX = 0;
- event.globalY = 0;
- event.x = mouse_event_x_;
- event.y = mouse_event_y_;
- event.windowX = event.x;
- event.windowY = event.y;
- host->ForwardWheelEvent(event);
-
- pixels_scrolled_ += abs(event.deltaY);
-
- TRACE_COUNTER_ID1(
- "gpu", "smooth_scroll_by_pixels_scrolled", this, pixels_scrolled_);
-
- return true;
-}
-
-} // content
-
diff --git a/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h b/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h
deleted file mode 100644
index ba127da05bd..00000000000
--- a/chromium/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h
+++ /dev/null
@@ -1,37 +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_RENDERER_HOST_BASIC_MOUSE_WHEEL_SMOOTH_SCROLL_GESTURE_
-#define CONTENT_BROWSER_RENDERER_HOST_BASIC_MOUSE_WHEEL_SMOOTH_SCROLL_GESTURE_
-
-#include "base/time/time.h"
-#include "content/browser/renderer_host/synthetic_gesture_calculator.h"
-#include "content/port/browser/synthetic_gesture.h"
-
-namespace content {
-
-class RenderWidgetHost;
-
-class BasicMouseWheelSmoothScrollGesture : public SyntheticGesture {
- public:
- BasicMouseWheelSmoothScrollGesture(bool scroll_down, int pixels_to_scroll,
- int mouse_event_x, int mouse_event_y);
-
- virtual bool ForwardInputEvents(base::TimeTicks now,
- RenderWidgetHost* host) OVERRIDE;
- private:
- virtual ~BasicMouseWheelSmoothScrollGesture();
-
- SyntheticGestureCalculator synthetic_gesture_calculator_;
-
- bool scroll_down_;
- int pixels_scrolled_;
- int pixels_to_scroll_;
- int mouse_event_x_;
- int mouse_event_y_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_BASIC_MOUSE_WHEEL_SMOOTH_SCROLL_GESTURE_
diff --git a/chromium/content/browser/renderer_host/clipboard_message_filter.cc b/chromium/content/browser/renderer_host/clipboard_message_filter.cc
index e681188b937..6ba95f8f12c 100644
--- a/chromium/content/browser/renderer_host/clipboard_message_filter.cc
+++ b/chromium/content/browser/renderer_host/clipboard_message_filter.cc
@@ -6,6 +6,8 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "content/common/clipboard_messages.h"
#include "content/public/browser/browser_context.h"
@@ -17,22 +19,20 @@
namespace content {
-#if defined(OS_WIN)
namespace {
-// The write must be performed on the UI thread because the clipboard object
-// from the IO thread cannot create windows so it cannot be the "owner" of the
-// clipboard's contents. // See http://crbug.com/5823.
+// On Windows, the write must be performed on the UI thread because the
+// clipboard object from the IO thread cannot create windows so it cannot be
+// the "owner" of the clipboard's contents. See http://crbug.com/5823.
void WriteObjectsOnUIThread(ui::Clipboard::ObjectMap* objects) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
static ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
- clipboard->WriteObjects(ui::Clipboard::BUFFER_STANDARD, *objects);
+ clipboard->WriteObjects(ui::CLIPBOARD_TYPE_COPY_PASTE, *objects);
}
} // namespace
-#endif
ClipboardMessageFilter::ClipboardMessageFilter() {}
@@ -89,27 +89,32 @@ ClipboardMessageFilter::~ClipboardMessageFilter() {
}
void ClipboardMessageFilter::OnWriteObjectsSync(
- ui::Clipboard::ObjectMap objects,
+ const ui::Clipboard::ObjectMap& objects,
base::SharedMemoryHandle bitmap_handle) {
DCHECK(base::SharedMemory::IsHandleValid(bitmap_handle))
<< "Bad bitmap handle";
- // Splice the shared memory handle into the clipboard data.
- ui::Clipboard::ReplaceSharedMemHandle(&objects, bitmap_handle, PeerHandle());
-#if defined(OS_WIN)
- // We cannot write directly from the IO thread, and cannot service the IPC
- // on the UI thread. We'll copy the relevant data and get a handle to any
- // shared memory so it doesn't go away when we resume the renderer, and post
- // a task to perform the write on the UI thread.
- ui::Clipboard::ObjectMap* long_living_objects = new ui::Clipboard::ObjectMap;
- long_living_objects->swap(objects);
+
+ // On Windows, we can't write directly from the IO thread, so we copy the data
+ // into a heap allocated map and post a task to the UI thread. On other
+ // platforms, to lower the amount of time the renderer has to wait for the
+ // sync IPC to complete, we also take a copy and post a task to flush the data
+ // to the clipboard later.
+ scoped_ptr<ui::Clipboard::ObjectMap> long_living_objects(
+ new ui::Clipboard::ObjectMap(objects));
+ // Splice the shared memory handle into the data. |long_living_objects| now
+ // contains a heap-allocated SharedMemory object that references
+ // |bitmap_handle|. This reference will keep the shared memory section alive
+ // when this IPC returns, and the SharedMemory object will eventually be
+ // freed by ui::Clipboard::WriteObjects().
+ if (!ui::Clipboard::ReplaceSharedMemHandle(
+ long_living_objects.get(), bitmap_handle, PeerHandle()))
+ return;
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
- base::Bind(&WriteObjectsOnUIThread, base::Owned(long_living_objects)));
-#else
- GetClipboard()->WriteObjects(ui::Clipboard::BUFFER_STANDARD, objects);
-#endif
+ base::Bind(&WriteObjectsOnUIThread,
+ base::Owned(long_living_objects.release())));
}
void ClipboardMessageFilter::OnWriteObjectsAsync(
@@ -131,58 +136,62 @@ void ClipboardMessageFilter::OnWriteObjectsAsync(
&WriteObjectsOnUIThread, base::Owned(sanitized_objects.release())));
#else
GetClipboard()->WriteObjects(
- ui::Clipboard::BUFFER_STANDARD, *sanitized_objects.get());
+ ui::CLIPBOARD_TYPE_COPY_PASTE, *sanitized_objects.get());
#endif
}
-void ClipboardMessageFilter::OnGetSequenceNumber(
- ui::Clipboard::Buffer buffer, uint64* sequence_number) {
- *sequence_number = GetClipboard()->GetSequenceNumber(buffer);
+void ClipboardMessageFilter::OnGetSequenceNumber(ui::ClipboardType type,
+ uint64* sequence_number) {
+ *sequence_number = GetClipboard()->GetSequenceNumber(type);
}
void ClipboardMessageFilter::OnReadAvailableTypes(
- ui::Clipboard::Buffer buffer, std::vector<string16>* types,
+ ui::ClipboardType type,
+ std::vector<base::string16>* types,
bool* contains_filenames) {
- GetClipboard()->ReadAvailableTypes(buffer, types, contains_filenames);
+ GetClipboard()->ReadAvailableTypes(type, types, contains_filenames);
}
void ClipboardMessageFilter::OnIsFormatAvailable(
- const ui::Clipboard::FormatType& format, ui::Clipboard::Buffer buffer,
+ const ui::Clipboard::FormatType& format,
+ ui::ClipboardType type,
bool* result) {
- *result = GetClipboard()->IsFormatAvailable(format, buffer);
+ *result = GetClipboard()->IsFormatAvailable(format, type);
}
-void ClipboardMessageFilter::OnClear(ui::Clipboard::Buffer buffer) {
- GetClipboard()->Clear(buffer);
+void ClipboardMessageFilter::OnClear(ui::ClipboardType type) {
+ GetClipboard()->Clear(type);
}
-void ClipboardMessageFilter::OnReadText(
- ui::Clipboard::Buffer buffer, string16* result) {
- GetClipboard()->ReadText(buffer, result);
+void ClipboardMessageFilter::OnReadText(ui::ClipboardType type,
+ base::string16* result) {
+ GetClipboard()->ReadText(type, result);
}
-void ClipboardMessageFilter::OnReadAsciiText(
- ui::Clipboard::Buffer buffer, std::string* result) {
- GetClipboard()->ReadAsciiText(buffer, result);
+void ClipboardMessageFilter::OnReadAsciiText(ui::ClipboardType type,
+ std::string* result) {
+ GetClipboard()->ReadAsciiText(type, result);
}
-void ClipboardMessageFilter::OnReadHTML(
- ui::Clipboard::Buffer buffer, string16* markup, GURL* url,
- uint32* fragment_start, uint32* fragment_end) {
+void ClipboardMessageFilter::OnReadHTML(ui::ClipboardType type,
+ base::string16* markup,
+ GURL* url,
+ uint32* fragment_start,
+ uint32* fragment_end) {
std::string src_url_str;
- GetClipboard()->ReadHTML(buffer, markup, &src_url_str, fragment_start,
+ GetClipboard()->ReadHTML(type, markup, &src_url_str, fragment_start,
fragment_end);
*url = GURL(src_url_str);
}
-void ClipboardMessageFilter::OnReadRTF(
- ui::Clipboard::Buffer buffer, std::string* result) {
- GetClipboard()->ReadRTF(buffer, result);
+void ClipboardMessageFilter::OnReadRTF(ui::ClipboardType type,
+ std::string* result) {
+ GetClipboard()->ReadRTF(type, result);
}
-void ClipboardMessageFilter::OnReadImage(
- ui::Clipboard::Buffer buffer, IPC::Message* reply_msg) {
- SkBitmap bitmap = GetClipboard()->ReadImage(buffer);
+void ClipboardMessageFilter::OnReadImage(ui::ClipboardType type,
+ IPC::Message* reply_msg) {
+ SkBitmap bitmap = GetClipboard()->ReadImage(type);
#if defined(USE_X11)
BrowserThread::PostTask(
@@ -215,9 +224,10 @@ void ClipboardMessageFilter::OnReadImageReply(
Send(reply_msg);
}
-void ClipboardMessageFilter::OnReadCustomData(
- ui::Clipboard::Buffer buffer, const string16& type, string16* result) {
- GetClipboard()->ReadCustomData(buffer, type, result);
+void ClipboardMessageFilter::OnReadCustomData(ui::ClipboardType clipboard_type,
+ const base::string16& type,
+ base::string16* result) {
+ GetClipboard()->ReadCustomData(clipboard_type, type, result);
}
void ClipboardMessageFilter::OnReadData(const ui::Clipboard::FormatType& format,
diff --git a/chromium/content/browser/renderer_host/clipboard_message_filter.h b/chromium/content/browser/renderer_host/clipboard_message_filter.h
index bd3962f6042..dd2784be531 100644
--- a/chromium/content/browser/renderer_host/clipboard_message_filter.h
+++ b/chromium/content/browser/renderer_host/clipboard_message_filter.h
@@ -29,33 +29,36 @@ class ClipboardMessageFilter : public BrowserMessageFilter {
virtual ~ClipboardMessageFilter();
void OnWriteObjectsAsync(const ui::Clipboard::ObjectMap& objects);
- void OnWriteObjectsSync(ui::Clipboard::ObjectMap objects,
+ void OnWriteObjectsSync(const ui::Clipboard::ObjectMap& objects,
base::SharedMemoryHandle bitmap_handle);
- void OnGetSequenceNumber(const ui::Clipboard::Buffer buffer,
+ void OnGetSequenceNumber(const ui::ClipboardType type,
uint64* sequence_number);
void OnIsFormatAvailable(const ui::Clipboard::FormatType& format,
- ui::Clipboard::Buffer buffer,
+ ui::ClipboardType type,
bool* result);
- void OnClear(ui::Clipboard::Buffer buffer);
- void OnReadAvailableTypes(ui::Clipboard::Buffer buffer,
- std::vector<string16>* types,
+ void OnClear(ui::ClipboardType type);
+ void OnReadAvailableTypes(ui::ClipboardType type,
+ std::vector<base::string16>* types,
bool* contains_filenames);
- void OnReadText(ui::Clipboard::Buffer buffer, string16* result);
- void OnReadAsciiText(ui::Clipboard::Buffer buffer, std::string* result);
- void OnReadHTML(ui::Clipboard::Buffer buffer, string16* markup, GURL* url,
- uint32* fragment_start, uint32* fragment_end);
- void OnReadRTF(ui::Clipboard::Buffer buffer, std::string* result);
- void OnReadImage(ui::Clipboard::Buffer buffer, IPC::Message* reply_msg);
+ void OnReadText(ui::ClipboardType type, base::string16* result);
+ void OnReadAsciiText(ui::ClipboardType type, std::string* result);
+ void OnReadHTML(ui::ClipboardType type,
+ base::string16* markup,
+ GURL* url,
+ uint32* fragment_start,
+ uint32* fragment_end);
+ void OnReadRTF(ui::ClipboardType type, std::string* result);
+ void OnReadImage(ui::ClipboardType type, IPC::Message* reply_msg);
void OnReadImageReply(const SkBitmap& bitmap, IPC::Message* reply_msg);
- void OnReadCustomData(ui::Clipboard::Buffer buffer,
- const string16& type,
- string16* result);
+ void OnReadCustomData(ui::ClipboardType clipboard_type,
+ const base::string16& type,
+ base::string16* result);
void OnReadData(const ui::Clipboard::FormatType& format,
std::string* data);
#if defined(OS_MACOSX)
- void OnFindPboardWriteString(const string16& text);
+ void OnFindPboardWriteString(const base::string16& text);
#endif
// We have our own clipboard because we want to access the clipboard on the
diff --git a/chromium/content/browser/renderer_host/clipboard_message_filter_mac.mm b/chromium/content/browser/renderer_host/clipboard_message_filter_mac.mm
index ee8f5a3e428..3c59d31f40f 100644
--- a/chromium/content/browser/renderer_host/clipboard_message_filter_mac.mm
+++ b/chromium/content/browser/renderer_host/clipboard_message_filter_mac.mm
@@ -40,7 +40,8 @@ class WriteFindPboardWrapper {
} // namespace
// Called on the IO thread.
-void ClipboardMessageFilter::OnFindPboardWriteString(const string16& text) {
+void ClipboardMessageFilter::OnFindPboardWriteString(
+ const base::string16& text) {
if (text.length() <= kMaxFindPboardStringLength) {
NSString* nsText = base::SysUTF16ToNSString(text);
if (nsText) {
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.h b/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.h
index 84ffc632e7a..da9fc44597d 100644
--- a/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.h
+++ b/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.h
@@ -22,6 +22,8 @@ class CompositingIOSurfaceShaderPrograms;
class CompositingIOSurfaceContext
: public base::RefCounted<CompositingIOSurfaceContext> {
public:
+ enum { kOffscreenContextWindowNumber = -2 };
+
// Get or create a GL context for the specified window with the specified
// surface ordering. Share these GL contexts as much as possible because
// creating and destroying them can be expensive
@@ -41,6 +43,8 @@ class CompositingIOSurfaceContext
bool is_vsync_disabled() const { return is_vsync_disabled_; }
int window_number() const { return window_number_; }
+ bool IsVendorIntel();
+
private:
friend class base::RefCounted<CompositingIOSurfaceContext>;
@@ -59,6 +63,10 @@ class CompositingIOSurfaceContext
scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache_;
bool can_be_shared_;
+ bool initialized_is_intel_;
+ bool is_intel_;
+ GLint screen_;
+
// The global map from window number and window ordering to
// context data.
typedef std::map<int, CompositingIOSurfaceContext*> WindowMap;
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm b/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm
index 6394fe370cf..4c6cbf1c12a 100644
--- a/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm
+++ b/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm
@@ -69,14 +69,19 @@ CompositingIOSurfaceContext::Get(int window_number) {
GLint swapInterval = is_vsync_disabled ? 0 : 1;
[nsgl_context setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
- // Prepare the shader program cache. Precompile only the shader programs
- // needed to draw the IO Surface.
+ // Prepare the shader program cache. Precompile the shader programs
+ // needed to draw the IO Surface for non-offscreen contexts.
CGLSetCurrentContext(cgl_context);
scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache(
new CompositingIOSurfaceShaderPrograms());
- const bool prepared = (
- shader_program_cache->UseBlitProgram() &&
- shader_program_cache->UseSolidWhiteProgram());
+ bool prepared = false;
+ if (window_number == kOffscreenContextWindowNumber) {
+ prepared = true;
+ } else {
+ prepared = (
+ shader_program_cache->UseBlitProgram() &&
+ shader_program_cache->UseSolidWhiteProgram());
+ }
glUseProgram(0u);
CGLSetCurrentContext(0);
if (!prepared) {
@@ -113,7 +118,10 @@ CompositingIOSurfaceContext::CompositingIOSurfaceContext(
cgl_context_(cgl_context),
is_vsync_disabled_(is_vsync_disabled),
shader_program_cache_(shader_program_cache.Pass()),
- can_be_shared_(true) {
+ can_be_shared_(true),
+ initialized_is_intel_(false),
+ is_intel_(false),
+ screen_(0) {
DCHECK(window_map()->find(window_number_) == window_map()->end());
window_map()->insert(std::make_pair(window_number_, this));
}
@@ -133,6 +141,20 @@ CompositingIOSurfaceContext::~CompositingIOSurfaceContext() {
}
}
+bool CompositingIOSurfaceContext::IsVendorIntel() {
+ GLint screen;
+ CGLGetVirtualScreen(cgl_context(), &screen);
+ if (screen != screen_)
+ initialized_is_intel_ = false;
+ screen_ = screen;
+ if (!initialized_is_intel_) {
+ is_intel_ = strstr(reinterpret_cast<const char*>(glGetString(GL_VENDOR)),
+ "Intel") != NULL;
+ initialized_is_intel_ = true;
+ }
+ return is_intel_;
+}
+
// static
CompositingIOSurfaceContext::WindowMap*
CompositingIOSurfaceContext::window_map() {
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.mm b/chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
index 04ae21c300b..0a06d789b80 100644
--- a/chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
+++ b/chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
@@ -115,17 +115,17 @@
if (!renderWidgetHostView_)
return;
- gfx::Size window_size([self frame].size);
+ gfx::Rect window_rect([self frame]);
float window_scale_factor = 1.f;
if ([self respondsToSelector:(@selector(contentsScale))])
window_scale_factor = [self contentsScale];
CGLSetCurrentContext(glContext);
if (!renderWidgetHostView_->compositing_iosurface_->DrawIOSurface(
- window_size,
+ context_,
+ window_rect,
window_scale_factor,
- renderWidgetHostView_->frame_subscriber(),
- true)) {
+ false)) {
renderWidgetHostView_->GotAcceleratedCompositingError();
}
}
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_mac.h b/chromium/content/browser/renderer_host/compositing_iosurface_mac.h
index 623272be771..315ddc59fcc 100644
--- a/chromium/content/browser/renderer_host/compositing_iosurface_mac.h
+++ b/chromium/content/browser/renderer_host/compositing_iosurface_mac.h
@@ -45,31 +45,30 @@ class RenderWidgetHostViewMac;
// RenderWidgetHostViewCocoa for blitting the IOSurface.
class CompositingIOSurfaceMac {
public:
- // Returns NULL if IOSurface support is missing or GL APIs fail. Specify in
- // |order| the desired ordering relationship of the surface to the containing
- // window.
- static CompositingIOSurfaceMac* Create(
- const scoped_refptr<CompositingIOSurfaceContext>& context);
+ // Returns NULL if IOSurface support is missing or GL APIs fail.
+ static CompositingIOSurfaceMac* Create();
~CompositingIOSurfaceMac();
// Set IOSurface that will be drawn on the next NSView drawRect.
- bool SetIOSurface(uint64 io_surface_handle,
- const gfx::Size& size,
- float scale_factor,
- const ui::LatencyInfo& latency_info);
+ bool SetIOSurfaceWithContextCurrent(
+ scoped_refptr<CompositingIOSurfaceContext> current_context,
+ uint64 io_surface_handle,
+ const gfx::Size& size,
+ float scale_factor,
+ const ui::LatencyInfo& latency_info);
// Get the CGL renderer ID currently associated with this context.
int GetRendererID();
- // Blit the IOSurface at the upper-left corner of the of the specified
- // window_size. If the window size is larger than the IOSurface, the
- // remaining right and bottom edges will be white. |scaleFactor| is 1
- // in normal views, 2 in HiDPI views. |frame_subscriber| listens to
- // this draw event and provides output buffer for copying this frame into.
- bool DrawIOSurface(const gfx::Size& window_size,
- float window_scale_factor,
- RenderWidgetHostViewFrameSubscriber* frame_subscriber,
- bool using_core_animation);
+ // Blit the IOSurface to the rectangle specified by |window_rect| in DIPs,
+ // with the origin in the lower left corner. If the window rect's size is
+ // larger than the IOSurface, the remaining right and bottom edges will be
+ // white. |window_scale_factor| is 1 in normal views, 2 in HiDPI views.
+ bool DrawIOSurface(
+ scoped_refptr<CompositingIOSurfaceContext> drawing_context,
+ const gfx::Rect& window_rect,
+ float window_scale_factor,
+ bool flush_drawable);
// Copy the data of the "live" OpenGL texture referring to this IOSurfaceRef
// into |out|. The copied region is specified with |src_pixel_subrect| and
@@ -103,15 +102,6 @@ class CompositingIOSurfaceMac {
const gfx::Size& dip_io_surface_size() const { return dip_io_surface_size_; }
float scale_factor() const { return scale_factor_; }
- bool is_vsync_disabled() const;
-
- void SetContext(
- const scoped_refptr<CompositingIOSurfaceContext>& new_context);
-
- const scoped_refptr<CompositingIOSurfaceContext>& context() {
- return context_;
- }
-
// Get vsync scheduling parameters.
// |interval_numerator/interval_denominator| equates to fractional number of
// seconds between vsyncs.
@@ -232,7 +222,9 @@ class CompositingIOSurfaceMac {
bool IsVendorIntel();
// Returns true if IOSurface is ready to render. False otherwise.
- bool MapIOSurfaceToTexture(uint64 io_surface_handle);
+ bool MapIOSurfaceToTextureWithContextCurrent(
+ const scoped_refptr<CompositingIOSurfaceContext>& current_context,
+ uint64 io_surface_handle);
void UnrefIOSurfaceWithContextCurrent();
@@ -306,9 +298,10 @@ class CompositingIOSurfaceMac {
// Cached pointer to IOSurfaceSupport Singleton.
IOSurfaceSupport* io_surface_support_;
- // GL context, and parameters for context sharing. This may change when
- // moving between windows, but will never be NULL.
- scoped_refptr<CompositingIOSurfaceContext> context_;
+ // Offscreen context used for all operations other than drawing to the
+ // screen. This is in the same share group as the contexts used for
+ // drawing, and is the same for all IOSurfaces in all windows.
+ scoped_refptr<CompositingIOSurfaceContext> offscreen_context_;
// IOSurface data.
uint64 io_surface_handle_;
@@ -350,10 +343,6 @@ class CompositingIOSurfaceMac {
uint32 vsync_interval_numerator_;
uint32 vsync_interval_denominator_;
- bool initialized_is_intel_;
- bool is_intel_;
- GLint screen_;
-
// Error saved by GetAndSaveGLError
GLint gl_error_;
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_mac.mm b/chromium/content/browser/renderer_host/compositing_iosurface_mac.mm
index a9ca7079919..e948863ed40 100644
--- a/chromium/content/browser/renderer_host/compositing_iosurface_mac.mm
+++ b/chromium/content/browser/renderer_host/compositing_iosurface_mac.mm
@@ -230,23 +230,30 @@ void CompositingIOSurfaceMac::CopyContext::PrepareForAsynchronousReadback() {
// static
-CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create(
- const scoped_refptr<CompositingIOSurfaceContext>& context) {
+CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create() {
IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
if (!io_surface_support) {
LOG(ERROR) << "No IOSurface support";
return NULL;
}
+ scoped_refptr<CompositingIOSurfaceContext> offscreen_context =
+ CompositingIOSurfaceContext::Get(
+ CompositingIOSurfaceContext::kOffscreenContextWindowNumber);
+ if (!offscreen_context) {
+ LOG(ERROR) << "Failed to create context for offscreen operations";
+ return NULL;
+ }
+
return new CompositingIOSurfaceMac(io_surface_support,
- context);
+ offscreen_context);
}
CompositingIOSurfaceMac::CompositingIOSurfaceMac(
IOSurfaceSupport* io_surface_support,
- const scoped_refptr<CompositingIOSurfaceContext>& context)
+ const scoped_refptr<CompositingIOSurfaceContext>& offscreen_context)
: io_surface_support_(io_surface_support),
- context_(context),
+ offscreen_context_(offscreen_context),
io_surface_handle_(0),
scale_factor_(1.f),
texture_(0),
@@ -262,11 +269,8 @@ CompositingIOSurfaceMac::CompositingIOSurfaceMac(
this, &CompositingIOSurfaceMac::StopDisplayLink),
vsync_interval_numerator_(0),
vsync_interval_denominator_(0),
- initialized_is_intel_(false),
- is_intel_(false),
- screen_(0),
gl_error_(GL_NO_ERROR) {
- CHECK(context_);
+ CHECK(offscreen_context_);
}
void CompositingIOSurfaceMac::SetupCVDisplayLink() {
@@ -305,26 +309,6 @@ void CompositingIOSurfaceMac::SetupCVDisplayLink() {
StopDisplayLink();
}
-void CompositingIOSurfaceMac::SetContext(
- const scoped_refptr<CompositingIOSurfaceContext>& new_context) {
- CHECK(new_context);
-
- if (context_ == new_context)
- return;
-
- // Asynchronous copies must complete in the same context they started in.
- CheckIfAllCopiesAreFinished(true);
- CGLSetCurrentContext(context_->cgl_context());
- DestroyAllCopyContextsWithinContext();
- CGLSetCurrentContext(0);
-
- context_ = new_context;
-}
-
-bool CompositingIOSurfaceMac::is_vsync_disabled() const {
- return context_->is_vsync_disabled();
-}
-
void CompositingIOSurfaceMac::GetVSyncParameters(base::TimeTicks* timebase,
uint32* interval_numerator,
uint32* interval_denominator) {
@@ -337,14 +321,15 @@ void CompositingIOSurfaceMac::GetVSyncParameters(base::TimeTicks* timebase,
CompositingIOSurfaceMac::~CompositingIOSurfaceMac() {
FailAllCopies();
CVDisplayLinkRelease(display_link_);
- CGLSetCurrentContext(context_->cgl_context());
+ CGLSetCurrentContext(offscreen_context_->cgl_context());
DestroyAllCopyContextsWithinContext();
UnrefIOSurfaceWithContextCurrent();
CGLSetCurrentContext(0);
- context_ = NULL;
+ offscreen_context_ = NULL;
}
-bool CompositingIOSurfaceMac::SetIOSurface(
+bool CompositingIOSurfaceMac::SetIOSurfaceWithContextCurrent(
+ scoped_refptr<CompositingIOSurfaceContext> current_context,
uint64 io_surface_handle,
const gfx::Size& size,
float scale_factor,
@@ -353,21 +338,15 @@ bool CompositingIOSurfaceMac::SetIOSurface(
scale_factor_ = scale_factor;
dip_io_surface_size_ = gfx::ToFlooredSize(
gfx::ScaleSize(pixel_io_surface_size_, 1.0 / scale_factor_));
-
- CGLError cgl_error = CGLSetCurrentContext(context_->cgl_context());
- if (cgl_error != kCGLNoError) {
- LOG(ERROR) << "CGLSetCurrentContext error in SetIOSurface: " << cgl_error;
- return false;
- }
- bool result = MapIOSurfaceToTexture(io_surface_handle);
- CGLSetCurrentContext(0);
+ bool result = MapIOSurfaceToTextureWithContextCurrent(
+ current_context, io_surface_handle);
latency_info_.MergeWith(latency_info);
return result;
}
int CompositingIOSurfaceMac::GetRendererID() {
GLint current_renderer_id = -1;
- if (CGLGetParameter(context_->cgl_context(),
+ if (CGLGetParameter(offscreen_context_->cgl_context(),
kCGLCPCurrentRendererID,
&current_renderer_id) == kCGLNoError)
return current_renderer_id & kCGLRendererIDMatchingMask;
@@ -375,11 +354,11 @@ int CompositingIOSurfaceMac::GetRendererID() {
}
bool CompositingIOSurfaceMac::DrawIOSurface(
- const gfx::Size& window_size,
+ scoped_refptr<CompositingIOSurfaceContext> drawing_context,
+ const gfx::Rect& window_rect,
float window_scale_factor,
- RenderWidgetHostViewFrameSubscriber* frame_subscriber,
- bool using_core_animation) {
- bool result = true;
+ bool flush_drawable) {
+ DCHECK_EQ(CGLGetCurrentContext(), drawing_context->cgl_context());
if (display_link_ == NULL)
SetupCVDisplayLink();
@@ -388,9 +367,11 @@ bool CompositingIOSurfaceMac::DrawIOSurface(
TRACE_EVENT1("browser", "CompositingIOSurfaceMac::DrawIOSurface",
"has_io_surface", has_io_surface);
- gfx::Size pixel_window_size = gfx::ToFlooredSize(
- gfx::ScaleSize(window_size, window_scale_factor));
- glViewport(0, 0, pixel_window_size.width(), pixel_window_size.height());
+ gfx::Rect pixel_window_rect =
+ ToNearestRect(gfx::ScaleRect(window_rect, window_scale_factor));
+ glViewport(
+ pixel_window_rect.x(), pixel_window_rect.y(),
+ pixel_window_rect.width(), pixel_window_rect.height());
SurfaceQuad quad;
quad.set_size(dip_io_surface_size_, pixel_io_surface_size_);
@@ -399,9 +380,9 @@ bool CompositingIOSurfaceMac::DrawIOSurface(
glLoadIdentity();
// Note that the projection keeps things in view units, so the use of
- // window_size / dip_io_surface_size_ (as opposed to the pixel_ variants)
+ // window_rect / dip_io_surface_size_ (as opposed to the pixel_ variants)
// below is correct.
- glOrtho(0, window_size.width(), window_size.height(), 0, -1, 1);
+ glOrtho(0, window_rect.width(), window_rect.height(), 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
@@ -409,7 +390,7 @@ bool CompositingIOSurfaceMac::DrawIOSurface(
glDisable(GL_BLEND);
if (has_io_surface) {
- context_->shader_program_cache()->UseBlitProgram();
+ drawing_context->shader_program_cache()->UseBlitProgram();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
@@ -418,21 +399,21 @@ bool CompositingIOSurfaceMac::DrawIOSurface(
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); CHECK_AND_SAVE_GL_ERROR();
// Fill the resize gutters with white.
- if (window_size.width() > dip_io_surface_size_.width() ||
- window_size.height() > dip_io_surface_size_.height()) {
- context_->shader_program_cache()->UseSolidWhiteProgram();
+ if (window_rect.width() > dip_io_surface_size_.width() ||
+ window_rect.height() > dip_io_surface_size_.height()) {
+ drawing_context->shader_program_cache()->UseSolidWhiteProgram();
SurfaceQuad filler_quad;
- if (window_size.width() > dip_io_surface_size_.width()) {
+ if (window_rect.width() > dip_io_surface_size_.width()) {
// Draw right-side gutter down to the bottom of the window.
filler_quad.set_rect(dip_io_surface_size_.width(), 0.0f,
- window_size.width(), window_size.height());
+ window_rect.width(), window_rect.height());
DrawQuad(filler_quad);
}
- if (window_size.height() > dip_io_surface_size_.height()) {
+ if (window_rect.height() > dip_io_surface_size_.height()) {
// Draw bottom gutter to the width of the IOSurface.
filler_quad.set_rect(
0.0f, dip_io_surface_size_.height(),
- dip_io_surface_size_.width(), window_size.height());
+ dip_io_surface_size_.width(), window_rect.height());
DrawQuad(filler_quad);
}
}
@@ -463,7 +444,8 @@ bool CompositingIOSurfaceMac::DrawIOSurface(
}
const bool workaround_needed =
- IsVendorIntel() && !base::mac::IsOSMountainLionOrLater();
+ drawing_context->IsVendorIntel() &&
+ (!base::mac::IsOSMountainLionOrLater() || base::mac::IsOSMavericks());
const bool use_glfinish_workaround =
(workaround_needed || force_on_workaround) && !force_off_workaround;
@@ -472,39 +454,22 @@ bool CompositingIOSurfaceMac::DrawIOSurface(
// http://crbug.com/123409 : work around bugs in graphics driver on
// MacBook Air with Intel HD graphics, and possibly on other models,
// by forcing the graphics pipeline to be completely drained at this
- // point.
- // This workaround is not necessary on Mountain Lion.
+ // point. This workaround is not necessary on Mountain Lion.
+ // http://crbug.com/318877 : work around a bug where the window does
+ // not finish rendering its contents before displaying them on Mavericks
+ // on Retina MacBook Pro when using the Intel HD graphics GPU.
glFinish();
}
- base::Closure copy_done_callback;
- if (frame_subscriber) {
- const base::Time present_time = base::Time::Now();
- scoped_refptr<media::VideoFrame> frame;
- RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
- if (frame_subscriber->ShouldCaptureFrame(present_time, &frame, &callback)) {
- copy_done_callback = CopyToVideoFrameWithinContext(
- gfx::Rect(pixel_io_surface_size_), true, frame,
- base::Bind(callback, present_time));
- }
- }
-
- if (!using_core_animation) {
- CGLError cgl_error = CGLFlushDrawable(context_->cgl_context());
+ bool result = true;
+ if (flush_drawable) {
+ CGLError cgl_error = CGLFlushDrawable(drawing_context->cgl_context());
if (cgl_error != kCGLNoError) {
LOG(ERROR) << "CGLFlushDrawable error in DrawIOSurface: " << cgl_error;
result = false;
}
}
- latency_info_.swap_timestamp = base::TimeTicks::HighResNow();
- RenderWidgetHostImpl::CompositorFrameDrawn(latency_info_);
- latency_info_.Clear();
-
- // Try to finish previous copy requests after flush to get better pipelining.
- std::vector<base::Closure> copy_done_callbacks;
- CheckIfAllCopiesAreFinishedWithinContext(false, &copy_done_callbacks);
-
// Check if any of the drawing calls result in an error.
GetAndSaveGLError();
if (gl_error_ != GL_NO_ERROR) {
@@ -512,13 +477,13 @@ bool CompositingIOSurfaceMac::DrawIOSurface(
result = false;
}
- if (!using_core_animation)
- CGLSetCurrentContext(0);
+ latency_info_.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
+ RenderWidgetHostImpl::CompositorFrameDrawn(latency_info_);
+ latency_info_.Clear();
- if (!copy_done_callback.is_null())
- copy_done_callbacks.push_back(copy_done_callback);
- for (size_t i = 0; i < copy_done_callbacks.size(); ++i)
- copy_done_callbacks[i].Run();
+ // Try to finish previous copy requests after flush to get better pipelining.
+ CheckIfAllCopiesAreFinished(false);
StartOrContinueDisplayLink();
@@ -531,7 +496,11 @@ void CompositingIOSurfaceMac::CopyTo(
const base::Callback<void(bool, const SkBitmap&)>& callback) {
scoped_ptr<SkBitmap> output(new SkBitmap());
output->setConfig(SkBitmap::kARGB_8888_Config,
- dst_pixel_size.width(), dst_pixel_size.height());
+ dst_pixel_size.width(),
+ dst_pixel_size.height(),
+ 0,
+ kOpaque_SkAlphaType);
+
if (!output->allocPixels()) {
DLOG(ERROR) << "Failed to allocate SkBitmap pixels!";
callback.Run(false, *output);
@@ -539,9 +508,8 @@ void CompositingIOSurfaceMac::CopyTo(
}
DCHECK_EQ(output->rowBytesAsPixels(), dst_pixel_size.width())
<< "Stride is required to be equal to width for GPU readback.";
- output->setIsOpaque(true);
- CGLSetCurrentContext(context_->cgl_context());
+ CGLSetCurrentContext(offscreen_context_->cgl_context());
const base::Closure copy_done_callback = CopyToSelectedOutputWithinContext(
src_pixel_subrect, gfx::Rect(dst_pixel_size), false,
output.get(), NULL,
@@ -555,7 +523,7 @@ void CompositingIOSurfaceMac::CopyToVideoFrame(
const gfx::Rect& src_pixel_subrect,
const scoped_refptr<media::VideoFrame>& target,
const base::Callback<void(bool)>& callback) {
- CGLSetCurrentContext(context_->cgl_context());
+ CGLSetCurrentContext(offscreen_context_->cgl_context());
const base::Closure copy_done_callback = CopyToVideoFrameWithinContext(
src_pixel_subrect, false, target, callback);
CGLSetCurrentContext(0);
@@ -585,7 +553,8 @@ base::Closure CompositingIOSurfaceMac::CopyToVideoFrameWithinContext(
NULL, target, callback);
}
-bool CompositingIOSurfaceMac::MapIOSurfaceToTexture(
+bool CompositingIOSurfaceMac::MapIOSurfaceToTextureWithContextCurrent(
+ const scoped_refptr<CompositingIOSurfaceContext>& current_context,
uint64 io_surface_handle) {
if (io_surface_.get() && io_surface_handle == io_surface_handle_)
return true;
@@ -617,7 +586,7 @@ bool CompositingIOSurfaceMac::MapIOSurfaceToTexture(
CHECK_AND_SAVE_GL_ERROR();
GLuint plane = 0;
CGLError cgl_error = io_surface_support_->CGLTexImageIOSurface2D(
- context_->cgl_context(),
+ current_context->cgl_context(),
GL_TEXTURE_RECTANGLE_ARB,
GL_RGBA,
rounded_size.width(),
@@ -642,7 +611,7 @@ bool CompositingIOSurfaceMac::MapIOSurfaceToTexture(
}
void CompositingIOSurfaceMac::UnrefIOSurface() {
- CGLSetCurrentContext(context_->cgl_context());
+ CGLSetCurrentContext(offscreen_context_->cgl_context());
UnrefIOSurfaceWithContextCurrent();
CGLSetCurrentContext(0);
}
@@ -659,20 +628,6 @@ void CompositingIOSurfaceMac::DrawQuad(const SurfaceQuad& quad) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
-bool CompositingIOSurfaceMac::IsVendorIntel() {
- GLint screen;
- CGLGetVirtualScreen(context_->cgl_context(), &screen);
- if (screen != screen_)
- initialized_is_intel_ = false;
- screen_ = screen;
- if (!initialized_is_intel_) {
- is_intel_ = strstr(reinterpret_cast<const char*>(glGetString(GL_VENDOR)),
- "Intel") != NULL;
- initialized_is_intel_ = true;
- }
- return is_intel_;
-}
-
void CompositingIOSurfaceMac::UnrefIOSurfaceWithContextCurrent() {
if (texture_) {
glDeleteTextures(1, &texture_);
@@ -725,14 +680,18 @@ void CompositingIOSurfaceMac::StopDisplayLink() {
}
bool CompositingIOSurfaceMac::IsAsynchronousReadbackSupported() {
+ const bool forced_synchronous = CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kForceSynchronousGLReadPixels);
+ if (forced_synchronous)
+ return false;
+ if (!HasAppleFenceExtension() && HasPixelBufferObjectExtension())
+ return false;
// Using PBO crashes on Intel drivers but not on newer Mountain Lion
// systems. See bug http://crbug.com/152225.
- const bool forced_synchronous = CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kForceSynchronousGLReadPixels);
- return (!forced_synchronous &&
- HasAppleFenceExtension() &&
- HasPixelBufferObjectExtension() &&
- (base::mac::IsOSMountainLionOrLater() || !IsVendorIntel()));
+ if (offscreen_context_->IsVendorIntel() &&
+ !base::mac::IsOSMountainLionOrLater())
+ return false;
+ return true;
}
base::Closure CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext(
@@ -749,7 +708,8 @@ base::Closure CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext(
// readback for SkBitmap output since the Blit shader program doesn't support
// switchable output formats.
const bool require_sync_copy_for_workaround = bitmap_output &&
- context_->shader_program_cache()->rgb_to_yv12_output_format() == GL_RGBA;
+ offscreen_context_->shader_program_cache()->rgb_to_yv12_output_format() ==
+ GL_RGBA;
const bool async_copy = !require_sync_copy_for_workaround &&
IsAsynchronousReadbackSupported();
TRACE_EVENT2(
@@ -772,7 +732,7 @@ base::Closure CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext(
// be started here.
if (copy_requests_.size() >= 2)
return base::Bind(done_callback, false);
- copy_context = new CopyContext(context_);
+ copy_context = new CopyContext(offscreen_context_);
} else {
copy_context = copy_context_pool_.back();
copy_context_pool_.pop_back();
@@ -800,7 +760,8 @@ base::Closure CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext(
&copy_context->output_texture_sizes[0],
&copy_context->output_texture_sizes[1])) {
copy_context->output_readback_format =
- context_->shader_program_cache()->rgb_to_yv12_output_format();
+ offscreen_context_->shader_program_cache()->
+ rgb_to_yv12_output_format();
copy_context->num_outputs = 3;
copy_context->output_texture_sizes[2] =
copy_context->output_texture_sizes[1];
@@ -886,11 +847,15 @@ void CompositingIOSurfaceMac::AsynchronousReadbackForCopy(
void CompositingIOSurfaceMac::CheckIfAllCopiesAreFinished(
bool block_until_finished) {
+ if (copy_requests_.empty())
+ return;
+
std::vector<base::Closure> done_callbacks;
- CGLSetCurrentContext(context_->cgl_context());
+ CGLContextObj previous_context = CGLGetCurrentContext();
+ CGLSetCurrentContext(offscreen_context_->cgl_context());
CheckIfAllCopiesAreFinishedWithinContext(
block_until_finished, &done_callbacks);
- CGLSetCurrentContext(0);
+ CGLSetCurrentContext(previous_context);
for (size_t i = 0; i < done_callbacks.size(); ++i)
done_callbacks[i].Run();
}
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index 1e758c35a0d..78b23989bd0 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -38,8 +38,10 @@
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
+#include "ui/base/android/window_android.h"
#include "ui/gfx/android/device_display_info.h"
#include "ui/gfx/android/java_bitmap.h"
+#include "ui/gfx/frame_time.h"
#include "webkit/common/gpu/context_provider_in_process.h"
#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
@@ -90,8 +92,6 @@ class OutputSurfaceWithoutParent : public cc::OutputSurface {
};
static bool g_initialized = false;
-static base::Thread* g_impl_thread = NULL;
-static bool g_use_direct_gl = false;
} // anonymous namespace
@@ -104,8 +104,9 @@ static base::LazyInstance<SurfaceMap>
static base::LazyInstance<base::Lock> g_surface_map_lock;
// static
-Compositor* Compositor::Create(CompositorClient* client) {
- return client ? new CompositorImpl(client) : NULL;
+Compositor* Compositor::Create(CompositorClient* client,
+ gfx::NativeWindow root_window) {
+ return client ? new CompositorImpl(client, root_window) : NULL;
}
// static
@@ -115,33 +116,11 @@ void Compositor::Initialize() {
}
// static
-void Compositor::InitializeWithFlags(uint32 flags) {
- g_use_direct_gl = flags & DIRECT_CONTEXT_ON_DRAW_THREAD;
- if (flags & ENABLE_COMPOSITOR_THREAD) {
- TRACE_EVENT_INSTANT0("test_gpu", "ThreadedCompositingInitialization",
- TRACE_EVENT_SCOPE_THREAD);
- g_impl_thread = new base::Thread("Browser Compositor");
- g_impl_thread->Start();
- }
- Compositor::Initialize();
-}
-
-// static
bool CompositorImpl::IsInitialized() {
return g_initialized;
}
// static
-bool CompositorImpl::IsThreadingEnabled() {
- return g_impl_thread;
-}
-
-// static
-bool CompositorImpl::UsesDirectGL() {
- return g_use_direct_gl;
-}
-
-// static
jobject CompositorImpl::GetSurface(int surface_id) {
base::AutoLock lock(g_surface_map_lock.Get());
SurfaceMap* surfaces = g_surface_map.Pointer();
@@ -152,31 +131,30 @@ jobject CompositorImpl::GetSurface(int surface_id) {
return jsurface;
}
-CompositorImpl::CompositorImpl(CompositorClient* client)
+CompositorImpl::CompositorImpl(CompositorClient* client,
+ gfx::NativeWindow root_window)
: root_layer_(cc::Layer::Create()),
has_transparent_background_(false),
window_(NULL),
surface_id_(0),
client_(client),
- weak_factory_(this) {
+ root_window_(root_window) {
DCHECK(client);
+ DCHECK(root_window);
ImageTransportFactoryAndroid::AddObserver(this);
+ root_window->AttachCompositor();
}
CompositorImpl::~CompositorImpl() {
+ root_window_->DetachCompositor();
ImageTransportFactoryAndroid::RemoveObserver(this);
// Clean-up any surface references.
SetSurface(NULL);
}
-void CompositorImpl::SetNeedsRedraw() {
- if (host_)
- host_->SetNeedsRedraw();
-}
-
void CompositorImpl::Composite() {
if (host_)
- host_->Composite(base::TimeTicks::Now());
+ host_->Composite(gfx::FrameTime::Now());
}
void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
@@ -248,16 +226,7 @@ void CompositorImpl::SetVisible(bool visible) {
settings.use_memory_management = false;
settings.highp_threshold_min = 2048;
- // Do not clear the framebuffer when rendering into external GL contexts
- // like Android View System's.
- if (UsesDirectGL())
- settings.should_clear_root_render_pass = false;
-
- scoped_refptr<base::SingleThreadTaskRunner> impl_thread_task_runner =
- g_impl_thread ? g_impl_thread->message_loop()->message_loop_proxy()
- : NULL;
-
- host_ = cc::LayerTreeHost::Create(this, settings, impl_thread_task_runner);
+ host_ = cc::LayerTreeHost::CreateSingleThreaded(this, this, NULL, settings);
host_->SetRootLayer(root_layer_);
host_->SetVisible(true);
@@ -285,12 +254,6 @@ void CompositorImpl::SetWindowBounds(const gfx::Size& size) {
root_layer_->SetBounds(size);
}
-void CompositorImpl::SetHasTransparentBackground(bool flag) {
- has_transparent_background_ = flag;
- if (host_)
- host_->set_has_transparent_background(flag);
-}
-
bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) {
if (host_)
return host_->CompositeAndReadback(pixels, rect);
@@ -315,15 +278,15 @@ void CompositorImpl::DeleteUIResource(cc::UIResourceId resource_id) {
ui_resource_map_.erase(it);
}
-WebKit::WebGLId CompositorImpl::GenerateTexture(gfx::JavaBitmap& bitmap) {
+blink::WebGLId CompositorImpl::GenerateTexture(gfx::JavaBitmap& bitmap) {
unsigned int texture_id = BuildBasicTexture();
- WebKit::WebGraphicsContext3D* context =
+ blink::WebGraphicsContext3D* context =
ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
if (texture_id == 0 || context->isContextLost() ||
!context->makeContextCurrent())
return 0;
- WebKit::WebGLId format = GetGLFormatForBitmap(bitmap);
- WebKit::WebGLId type = GetGLTypeForBitmap(bitmap);
+ blink::WebGLId format = GetGLFormatForBitmap(bitmap);
+ blink::WebGLId type = GetGLTypeForBitmap(bitmap);
context->texImage2D(GL_TEXTURE_2D,
0,
@@ -338,11 +301,11 @@ WebKit::WebGLId CompositorImpl::GenerateTexture(gfx::JavaBitmap& bitmap) {
return texture_id;
}
-WebKit::WebGLId CompositorImpl::GenerateCompressedTexture(gfx::Size& size,
+blink::WebGLId CompositorImpl::GenerateCompressedTexture(gfx::Size& size,
int data_size,
void* data) {
unsigned int texture_id = BuildBasicTexture();
- WebKit::WebGraphicsContext3D* context =
+ blink::WebGraphicsContext3D* context =
ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
if (texture_id == 0 || context->isContextLost() ||
!context->makeContextCurrent())
@@ -359,8 +322,8 @@ WebKit::WebGLId CompositorImpl::GenerateCompressedTexture(gfx::Size& size,
return texture_id;
}
-void CompositorImpl::DeleteTexture(WebKit::WebGLId texture_id) {
- WebKit::WebGraphicsContext3D* context =
+void CompositorImpl::DeleteTexture(blink::WebGLId texture_id) {
+ blink::WebGraphicsContext3D* context =
ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
if (context->isContextLost() || !context->makeContextCurrent())
return;
@@ -368,12 +331,12 @@ void CompositorImpl::DeleteTexture(WebKit::WebGLId texture_id) {
context->shallowFlushCHROMIUM();
}
-bool CompositorImpl::CopyTextureToBitmap(WebKit::WebGLId texture_id,
+bool CompositorImpl::CopyTextureToBitmap(blink::WebGLId texture_id,
gfx::JavaBitmap& bitmap) {
return CopyTextureToBitmap(texture_id, gfx::Rect(bitmap.size()), bitmap);
}
-bool CompositorImpl::CopyTextureToBitmap(WebKit::WebGLId texture_id,
+bool CompositorImpl::CopyTextureToBitmap(blink::WebGLId texture_id,
const gfx::Rect& sub_rect,
gfx::JavaBitmap& bitmap) {
// The sub_rect should match the bitmap size.
@@ -389,68 +352,52 @@ bool CompositorImpl::CopyTextureToBitmap(WebKit::WebGLId texture_id,
static scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
CreateGpuProcessViewContext(
- const WebKit::WebGraphicsContext3D::Attributes attributes,
- int surface_id,
- base::WeakPtr<CompositorImpl> compositor_impl) {
- GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance();
+ const blink::WebGraphicsContext3D::Attributes attributes,
+ int surface_id) {
+ BrowserGpuChannelHostFactory* factory =
+ BrowserGpuChannelHostFactory::instance();
+ CauseForGpuLaunch cause =
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
+ scoped_refptr<GpuChannelHost> gpu_channel_host(
+ factory->EstablishGpuChannelSync(cause));
+ if (!gpu_channel_host)
+ return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
+
GURL url("chrome://gpu/Compositor::createContext3D");
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
- new WebGraphicsContext3DCommandBufferImpl(surface_id,
- url,
- factory,
- compositor_impl));
static const size_t kBytesPerPixel = 4;
gfx::DeviceDisplayInfo display_info;
size_t full_screen_texture_size_in_bytes =
display_info.GetDisplayHeight() *
display_info.GetDisplayWidth() *
kBytesPerPixel;
- if (!context->Initialize(
- attributes,
- false,
- CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE,
- 64 * 1024, // command buffer size
- 64 * 1024, // start transfer buffer size
- 64 * 1024, // min transfer buffer size
- std::min(3 * full_screen_texture_size_in_bytes,
- kDefaultMaxTransferBufferSize),
- 2 * 1024 * 1024 // mapped memory limit
- )) {
- LOG(ERROR) << "Failed to create 3D context for compositor.";
- return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
- }
- return context.Pass();
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
+ limits.command_buffer_size = 64 * 1024;
+ limits.start_transfer_buffer_size = 64 * 1024;
+ limits.min_transfer_buffer_size = 64 * 1024;
+ limits.max_transfer_buffer_size = std::min(
+ 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
+ limits.mapped_memory_reclaim_limit = 2 * 1024 * 1024;
+ return make_scoped_ptr(
+ new WebGraphicsContext3DCommandBufferImpl(surface_id,
+ url,
+ gpu_channel_host.get(),
+ attributes,
+ false,
+ limits));
}
scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface(
bool fallback) {
- WebKit::WebGraphicsContext3D::Attributes attrs;
+ blink::WebGraphicsContext3D::Attributes attrs;
attrs.shareResources = true;
attrs.noAutomaticFlushes = true;
- if (g_use_direct_gl) {
- using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
- scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d =
- WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext(
- attrs, window_);
- scoped_refptr<webkit::gpu::ContextProviderInProcess> context_provider =
- webkit::gpu::ContextProviderInProcess::Create(context3d.Pass(),
- "BrowserCompositor");
-
- scoped_ptr<cc::OutputSurface> output_surface;
- if (!window_)
- output_surface.reset(new DirectOutputSurface(context_provider));
- else
- output_surface.reset(new cc::OutputSurface(context_provider));
- return output_surface.Pass();
- }
-
DCHECK(window_);
DCHECK(surface_id_);
scoped_refptr<ContextProviderCommandBuffer> context_provider =
- ContextProviderCommandBuffer::Create(CreateGpuProcessViewContext(
- attrs, surface_id_, weak_factory_.GetWeakPtr()), "BrowserCompositor");
+ ContextProviderCommandBuffer::Create(
+ CreateGpuProcessViewContext(attrs, surface_id_), "BrowserCompositor");
if (!context_provider.get()) {
LOG(ERROR) << "Failed to create 3D context for compositor.";
return scoped_ptr<cc::OutputSurface>();
@@ -464,16 +411,7 @@ void CompositorImpl::OnLostResources() {
client_->DidLoseResources();
}
-void CompositorImpl::DidCompleteSwapBuffers() {
- client_->OnSwapBuffersCompleted();
-}
-
-void CompositorImpl::ScheduleComposite() {
- client_->ScheduleComposite();
-}
-
-scoped_refptr<cc::ContextProvider>
-CompositorImpl::OffscreenContextProviderForMainThread() {
+scoped_refptr<cc::ContextProvider> CompositorImpl::OffscreenContextProvider() {
// There is no support for offscreen contexts, or compositor filters that
// would require them in this compositor instance. If they are needed,
// then implement a context provider that provides contexts from
@@ -481,37 +419,34 @@ CompositorImpl::OffscreenContextProviderForMainThread() {
return NULL;
}
-scoped_refptr<cc::ContextProvider>
-CompositorImpl::OffscreenContextProviderForCompositorThread() {
- // There is no support for offscreen contexts, or compositor filters that
- // would require them in this compositor instance. If they are needed,
- // then implement a context provider that provides contexts from
- // ImageTransportSurfaceAndroid.
- return NULL;
+void CompositorImpl::DidCompleteSwapBuffers() {
+ client_->OnSwapBuffersCompleted();
}
-void CompositorImpl::OnViewContextSwapBuffersPosted() {
- TRACE_EVENT0("compositor", "CompositorImpl::OnViewContextSwapBuffersPosted");
- client_->OnSwapBuffersPosted();
+void CompositorImpl::ScheduleComposite() {
+ client_->ScheduleComposite();
}
-void CompositorImpl::OnViewContextSwapBuffersComplete() {
- TRACE_EVENT0("compositor",
- "CompositorImpl::OnViewContextSwapBuffersComplete");
- client_->OnSwapBuffersCompleted();
+void CompositorImpl::ScheduleAnimation() {
+ ScheduleComposite();
+}
+
+void CompositorImpl::DidPostSwapBuffers() {
+ TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers");
+ client_->OnSwapBuffersPosted();
}
-void CompositorImpl::OnViewContextSwapBuffersAborted() {
- TRACE_EVENT0("compositor", "CompositorImpl::OnViewContextSwapBuffersAborted");
+void CompositorImpl::DidAbortSwapBuffers() {
+ TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers");
client_->OnSwapBuffersCompleted();
}
-WebKit::WebGLId CompositorImpl::BuildBasicTexture() {
- WebKit::WebGraphicsContext3D* context =
+blink::WebGLId CompositorImpl::BuildBasicTexture() {
+ blink::WebGraphicsContext3D* context =
ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
if (context->isContextLost() || !context->makeContextCurrent())
return 0;
- WebKit::WebGLId texture_id = context->createTexture();
+ blink::WebGLId texture_id = context->createTexture();
context->bindTexture(GL_TEXTURE_2D, texture_id);
context->texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
context->texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -520,7 +455,7 @@ WebKit::WebGLId CompositorImpl::BuildBasicTexture() {
return texture_id;
}
-WebKit::WGC3Denum CompositorImpl::GetGLFormatForBitmap(
+blink::WGC3Denum CompositorImpl::GetGLFormatForBitmap(
gfx::JavaBitmap& bitmap) {
switch (bitmap.format()) {
case ANDROID_BITMAP_FORMAT_A_8:
@@ -538,7 +473,7 @@ WebKit::WGC3Denum CompositorImpl::GetGLFormatForBitmap(
}
}
-WebKit::WGC3Denum CompositorImpl::GetGLTypeForBitmap(gfx::JavaBitmap& bitmap) {
+blink::WGC3Denum CompositorImpl::GetGLTypeForBitmap(gfx::JavaBitmap& bitmap) {
switch (bitmap.format()) {
case ANDROID_BITMAP_FORMAT_A_8:
return GL_UNSIGNED_BYTE;
@@ -555,4 +490,8 @@ WebKit::WGC3Denum CompositorImpl::GetGLTypeForBitmap(gfx::JavaBitmap& bitmap) {
}
}
+void CompositorImpl::DidCommit() {
+ root_window_->OnCompositingDidCommit();
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index 58e44c89449..a662b1de72e 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -9,9 +9,9 @@
#include "base/compiler_specific.h"
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
#include "cc/resources/ui_resource_client.h"
#include "cc/trees/layer_tree_host_client.h"
+#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "content/browser/renderer_host/image_transport_factory_android.h"
#include "content/common/content_export.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
@@ -36,17 +36,13 @@ class GraphicsContext;
class CONTENT_EXPORT CompositorImpl
: public Compositor,
public cc::LayerTreeHostClient,
- public WebGraphicsContext3DSwapBuffersClient,
+ public cc::LayerTreeHostSingleThreadClient,
public ImageTransportFactoryAndroidObserver {
public:
- explicit CompositorImpl(CompositorClient* client);
+ CompositorImpl(CompositorClient* client, gfx::NativeWindow root_window);
virtual ~CompositorImpl();
static bool IsInitialized();
- static bool IsThreadingEnabled();
-
- // Returns true if initialized with DIRECT_CONTEXT_ON_DRAW_THREAD.
- static bool UsesDirectGL();
// Returns the Java Surface object for a given view surface id.
static jobject GetSurface(int surface_id);
@@ -58,27 +54,25 @@ class CONTENT_EXPORT CompositorImpl
virtual void SetVisible(bool visible) OVERRIDE;
virtual void setDeviceScaleFactor(float factor) OVERRIDE;
virtual void SetWindowBounds(const gfx::Size& size) OVERRIDE;
- virtual void SetHasTransparentBackground(bool flag) OVERRIDE;
virtual bool CompositeAndReadback(
void *pixels, const gfx::Rect& rect) OVERRIDE;
- virtual void SetNeedsRedraw() OVERRIDE;
virtual void Composite() OVERRIDE;
virtual cc::UIResourceId GenerateUIResource(
const cc::UIResourceBitmap& bitmap) OVERRIDE;
virtual void DeleteUIResource(cc::UIResourceId resource_id) OVERRIDE;
- virtual WebKit::WebGLId GenerateTexture(gfx::JavaBitmap& bitmap) OVERRIDE;
- virtual WebKit::WebGLId GenerateCompressedTexture(
+ virtual blink::WebGLId GenerateTexture(gfx::JavaBitmap& bitmap) OVERRIDE;
+ virtual blink::WebGLId GenerateCompressedTexture(
gfx::Size& size, int data_size, void* data) OVERRIDE;
- virtual void DeleteTexture(WebKit::WebGLId texture_id) OVERRIDE;
- virtual bool CopyTextureToBitmap(WebKit::WebGLId texture_id,
+ virtual void DeleteTexture(blink::WebGLId texture_id) OVERRIDE;
+ virtual bool CopyTextureToBitmap(blink::WebGLId texture_id,
gfx::JavaBitmap& bitmap) OVERRIDE;
- virtual bool CopyTextureToBitmap(WebKit::WebGLId texture_id,
+ virtual bool CopyTextureToBitmap(blink::WebGLId texture_id,
const gfx::Rect& sub_rect,
gfx::JavaBitmap& bitmap) OVERRIDE;
// LayerTreeHostClient implementation.
- virtual void WillBeginFrame() OVERRIDE {}
- virtual void DidBeginFrame() OVERRIDE {}
+ virtual void WillBeginMainFrame(int frame_id) OVERRIDE {}
+ virtual void DidBeginMainFrame() OVERRIDE {}
virtual void Animate(double frame_begin_time) OVERRIDE {}
virtual void Layout() OVERRIDE {}
virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
@@ -87,27 +81,25 @@ class CONTENT_EXPORT CompositorImpl
OVERRIDE;
virtual void DidInitializeOutputSurface(bool success) OVERRIDE {}
virtual void WillCommit() OVERRIDE {}
- virtual void DidCommit() OVERRIDE {}
+ virtual void DidCommit() OVERRIDE;
virtual void DidCommitAndDrawFrame() OVERRIDE {}
virtual void DidCompleteSwapBuffers() OVERRIDE;
- virtual void ScheduleComposite() OVERRIDE;
- virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForMainThread() OVERRIDE;
virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForCompositorThread() OVERRIDE;
+ OffscreenContextProvider() OVERRIDE;
- // WebGraphicsContext3DSwapBuffersClient implementation.
- virtual void OnViewContextSwapBuffersPosted() OVERRIDE;
- virtual void OnViewContextSwapBuffersComplete() OVERRIDE;
- virtual void OnViewContextSwapBuffersAborted() OVERRIDE;
+ // LayerTreeHostSingleThreadClient implementation.
+ virtual void ScheduleComposite() OVERRIDE;
+ virtual void ScheduleAnimation() OVERRIDE;
+ virtual void DidPostSwapBuffers() OVERRIDE;
+ virtual void DidAbortSwapBuffers() OVERRIDE;
// ImageTransportFactoryAndroidObserver implementation.
virtual void OnLostResources() OVERRIDE;
private:
- WebKit::WebGLId BuildBasicTexture();
- WebKit::WGC3Denum GetGLFormatForBitmap(gfx::JavaBitmap& bitmap);
- WebKit::WGC3Denum GetGLTypeForBitmap(gfx::JavaBitmap& bitmap);
+ blink::WebGLId BuildBasicTexture();
+ blink::WGC3Denum GetGLFormatForBitmap(gfx::JavaBitmap& bitmap);
+ blink::WGC3Denum GetGLTypeForBitmap(gfx::JavaBitmap& bitmap);
scoped_refptr<cc::Layer> root_layer_;
scoped_ptr<cc::LayerTreeHost> host_;
@@ -119,7 +111,6 @@ class CONTENT_EXPORT CompositorImpl
int surface_id_;
CompositorClient* client_;
- base::WeakPtrFactory<CompositorImpl> weak_factory_;
scoped_refptr<cc::ContextProvider> null_offscreen_context_provider_;
@@ -127,6 +118,8 @@ class CONTENT_EXPORT CompositorImpl
UIResourceMap;
UIResourceMap ui_resource_map_;
+ gfx::NativeWindow root_window_;
+
DISALLOW_COPY_AND_ASSIGN(CompositorImpl);
};
diff --git a/chromium/content/browser/renderer_host/database_message_filter.cc b/chromium/content/browser/renderer_host/database_message_filter.cc
index 38cc49a844b..55ea305d6e5 100644
--- a/chromium/content/browser/renderer_host/database_message_filter.cc
+++ b/chromium/content/browser/renderer_host/database_message_filter.cc
@@ -47,7 +47,6 @@ DatabaseMessageFilter::DatabaseMessageFilter(
}
void DatabaseMessageFilter::OnChannelClosing() {
- BrowserMessageFilter::OnChannelClosing();
if (observer_added_) {
observer_added_ = false;
BrowserThread::PostTask(
@@ -114,13 +113,14 @@ bool DatabaseMessageFilter::OnMessageReceived(
DatabaseMessageFilter::~DatabaseMessageFilter() {
}
-void DatabaseMessageFilter::OnDatabaseOpenFile(const string16& vfs_file_name,
- int desired_flags,
- IPC::Message* reply_msg) {
+void DatabaseMessageFilter::OnDatabaseOpenFile(
+ const base::string16& vfs_file_name,
+ int desired_flags,
+ IPC::Message* reply_msg) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
std::string origin_identifier;
- string16 database_name;
+ base::string16 database_name;
// When in incognito mode, we want to make sure that all DB files are
// removed when the incognito browser context goes away, so we add the
@@ -163,16 +163,18 @@ void DatabaseMessageFilter::OnDatabaseOpenFile(const string16& vfs_file_name,
Send(reply_msg);
}
-void DatabaseMessageFilter::OnDatabaseDeleteFile(const string16& vfs_file_name,
- const bool& sync_dir,
- IPC::Message* reply_msg) {
+void DatabaseMessageFilter::OnDatabaseDeleteFile(
+ const base::string16& vfs_file_name,
+ const bool& sync_dir,
+ IPC::Message* reply_msg) {
DatabaseDeleteFile(vfs_file_name, sync_dir, reply_msg, kNumDeleteRetries);
}
-void DatabaseMessageFilter::DatabaseDeleteFile(const string16& vfs_file_name,
- bool sync_dir,
- IPC::Message* reply_msg,
- int reschedule_count) {
+void DatabaseMessageFilter::DatabaseDeleteFile(
+ const base::string16& vfs_file_name,
+ bool sync_dir,
+ IPC::Message* reply_msg,
+ int reschedule_count) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
// Return an error if the file name is invalid or if the file could not
@@ -184,8 +186,8 @@ void DatabaseMessageFilter::DatabaseDeleteFile(const string16& vfs_file_name,
// In order to delete a journal file in incognito mode, we only need to
// close the open handle to it that's stored in the database tracker.
if (db_tracker_->IsIncognitoProfile()) {
- const string16 wal_suffix(ASCIIToUTF16("-wal"));
- string16 sqlite_suffix;
+ const base::string16 wal_suffix(ASCIIToUTF16("-wal"));
+ base::string16 sqlite_suffix;
// WAL files can be deleted without having previously been opened.
if (!db_tracker_->HasSavedIncognitoFileHandle(vfs_file_name) &&
@@ -216,7 +218,7 @@ void DatabaseMessageFilter::DatabaseDeleteFile(const string16& vfs_file_name,
}
void DatabaseMessageFilter::OnDatabaseGetFileAttributes(
- const string16& vfs_file_name,
+ const base::string16& vfs_file_name,
IPC::Message* reply_msg) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
int32 attributes = -1;
@@ -231,7 +233,7 @@ void DatabaseMessageFilter::OnDatabaseGetFileAttributes(
}
void DatabaseMessageFilter::OnDatabaseGetFileSize(
- const string16& vfs_file_name, IPC::Message* reply_msg) {
+ const base::string16& vfs_file_name, IPC::Message* reply_msg) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
int64 size = 0;
base::FilePath db_file =
@@ -279,8 +281,8 @@ void DatabaseMessageFilter::OnDatabaseGetUsageAndQuota(
void DatabaseMessageFilter::OnDatabaseOpened(
const std::string& origin_identifier,
- const string16& database_name,
- const string16& description,
+ const base::string16& database_name,
+ const base::string16& description,
int64 estimated_size) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
@@ -300,7 +302,7 @@ void DatabaseMessageFilter::OnDatabaseOpened(
void DatabaseMessageFilter::OnDatabaseModified(
const std::string& origin_identifier,
- const string16& database_name) {
+ const base::string16& database_name) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (!database_connections_.IsDatabaseOpened(
origin_identifier, database_name)) {
@@ -314,7 +316,7 @@ void DatabaseMessageFilter::OnDatabaseModified(
void DatabaseMessageFilter::OnDatabaseClosed(
const std::string& origin_identifier,
- const string16& database_name) {
+ const base::string16& database_name) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (!database_connections_.IsDatabaseOpened(
origin_identifier, database_name)) {
@@ -329,7 +331,7 @@ void DatabaseMessageFilter::OnDatabaseClosed(
void DatabaseMessageFilter::OnHandleSqliteError(
const std::string& origin_identifier,
- const string16& database_name,
+ const base::string16& database_name,
int error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (!DatabaseUtil::IsValidOriginIdentifier(origin_identifier)) {
@@ -343,7 +345,7 @@ void DatabaseMessageFilter::OnHandleSqliteError(
void DatabaseMessageFilter::OnDatabaseSizeChanged(
const std::string& origin_identifier,
- const string16& database_name,
+ const base::string16& database_name,
int64 database_size) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (database_connections_.IsOriginUsed(origin_identifier)) {
@@ -354,7 +356,7 @@ void DatabaseMessageFilter::OnDatabaseSizeChanged(
void DatabaseMessageFilter::OnDatabaseScheduledForDeletion(
const std::string& origin_identifier,
- const string16& database_name) {
+ const base::string16& database_name) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
Send(new DatabaseMsg_CloseImmediately(origin_identifier, database_name));
}
diff --git a/chromium/content/browser/renderer_host/database_message_filter.h b/chromium/content/browser/renderer_host/database_message_filter.h
index 9e168c5404d..50243356339 100644
--- a/chromium/content/browser/renderer_host/database_message_filter.h
+++ b/chromium/content/browser/renderer_host/database_message_filter.h
@@ -41,15 +41,15 @@ class DatabaseMessageFilter
void RemoveObserver();
// VFS message handlers (file thread)
- void OnDatabaseOpenFile(const string16& vfs_file_name,
+ void OnDatabaseOpenFile(const base::string16& vfs_file_name,
int desired_flags,
IPC::Message* reply_msg);
- void OnDatabaseDeleteFile(const string16& vfs_file_name,
+ void OnDatabaseDeleteFile(const base::string16& vfs_file_name,
const bool& sync_dir,
IPC::Message* reply_msg);
- void OnDatabaseGetFileAttributes(const string16& vfs_file_name,
+ void OnDatabaseGetFileAttributes(const base::string16& vfs_file_name,
IPC::Message* reply_msg);
- void OnDatabaseGetFileSize(const string16& vfs_file_name,
+ void OnDatabaseGetFileSize(const base::string16& vfs_file_name,
IPC::Message* reply_msg);
// Quota message handler (io thread)
@@ -62,26 +62,26 @@ class DatabaseMessageFilter
// Database tracker message handlers (file thread)
void OnDatabaseOpened(const std::string& origin_identifier,
- const string16& database_name,
- const string16& description,
+ const base::string16& database_name,
+ const base::string16& description,
int64 estimated_size);
void OnDatabaseModified(const std::string& origin_identifier,
- const string16& database_name);
+ const base::string16& database_name);
void OnDatabaseClosed(const std::string& origin_identifier,
- const string16& database_name);
+ const base::string16& database_name);
void OnHandleSqliteError(const std::string& origin_identifier,
- const string16& database_name,
+ const base::string16& database_name,
int error);
// DatabaseTracker::Observer callbacks (file thread)
virtual void OnDatabaseSizeChanged(const std::string& origin_identifier,
- const string16& database_name,
+ const base::string16& database_name,
int64 database_size) OVERRIDE;
virtual void OnDatabaseScheduledForDeletion(
const std::string& origin_identifier,
- const string16& database_name) OVERRIDE;
+ const base::string16& database_name) OVERRIDE;
- void DatabaseDeleteFile(const string16& vfs_file_name,
+ void DatabaseDeleteFile(const base::string16& vfs_file_name,
bool sync_dir,
IPC::Message* reply_msg,
int reschedule_count);
diff --git a/chromium/content/browser/renderer_host/delegated_frame_evictor.cc b/chromium/content/browser/renderer_host/delegated_frame_evictor.cc
new file mode 100644
index 00000000000..8993d113898
--- /dev/null
+++ b/chromium/content/browser/renderer_host/delegated_frame_evictor.cc
@@ -0,0 +1,34 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/delegated_frame_evictor.h"
+
+namespace content {
+
+DelegatedFrameEvictor::DelegatedFrameEvictor(
+ DelegatedFrameEvictorClient* client)
+ : client_(client), has_frame_(false) {}
+
+DelegatedFrameEvictor::~DelegatedFrameEvictor() { DiscardedFrame(); }
+
+void DelegatedFrameEvictor::SwappedFrame(bool visible) {
+ has_frame_ = true;
+ RendererFrameManager::GetInstance()->AddFrame(this, visible);
+}
+
+void DelegatedFrameEvictor::DiscardedFrame() {
+ RendererFrameManager::GetInstance()->RemoveFrame(this);
+ has_frame_ = false;
+}
+
+void DelegatedFrameEvictor::SetVisible(bool visible) {
+ if (has_frame_)
+ RendererFrameManager::GetInstance()->SetFrameVisibility(this, visible);
+}
+
+void DelegatedFrameEvictor::EvictCurrentFrame() {
+ client_->EvictDelegatedFrame();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/delegated_frame_evictor.h b/chromium/content/browser/renderer_host/delegated_frame_evictor.h
new file mode 100644
index 00000000000..c54f2c4770b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/delegated_frame_evictor.h
@@ -0,0 +1,41 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_EVICTOR_H_
+#define CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_EVICTOR_H_
+
+#include "content/browser/renderer_host/renderer_frame_manager.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class CONTENT_EXPORT DelegatedFrameEvictorClient {
+ public:
+ virtual ~DelegatedFrameEvictorClient() {}
+ virtual void EvictDelegatedFrame() = 0;
+};
+
+class CONTENT_EXPORT DelegatedFrameEvictor : public RendererFrameManagerClient {
+ public:
+ // |client| must outlive |this|.
+ explicit DelegatedFrameEvictor(DelegatedFrameEvictorClient* client);
+ virtual ~DelegatedFrameEvictor();
+
+ void SwappedFrame(bool visible);
+ void DiscardedFrame();
+ void SetVisible(bool visible);
+
+ private:
+ // RendererFrameManagerClient implementation.
+ virtual void EvictCurrentFrame() OVERRIDE;
+
+ DelegatedFrameEvictorClient* client_;
+ bool has_frame_;
+
+ DISALLOW_COPY_AND_ASSIGN(DelegatedFrameEvictor);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_EVICTOR_H_
diff --git a/chromium/content/browser/renderer_host/dip_util.cc b/chromium/content/browser/renderer_host/dip_util.cc
index 8ef2d6c4661..f855abf4af5 100644
--- a/chromium/content/browser/renderer_host/dip_util.cc
+++ b/chromium/content/browser/renderer_host/dip_util.cc
@@ -18,7 +18,7 @@ namespace content {
namespace {
float GetScaleForView(const RenderWidgetHostView* view) {
- return ui::GetScaleFactorScale(GetScaleFactorForView(view));
+ return ui::GetImageScale(GetScaleFactorForView(view));
}
} // namespace
diff --git a/chromium/content/browser/renderer_host/file_utilities_message_filter.cc b/chromium/content/browser/renderer_host/file_utilities_message_filter.cc
index 65645e014ef..5daa6ff2217 100644
--- a/chromium/content/browser/renderer_host/file_utilities_message_filter.cc
+++ b/chromium/content/browser/renderer_host/file_utilities_message_filter.cc
@@ -48,7 +48,7 @@ void FileUtilitiesMessageFilter::OnGetFileInfo(
return;
}
- if (!file_util::GetFileInfo(path, result))
+ if (!base::GetFileInfo(path, result))
*status = base::PLATFORM_FILE_ERROR_FAILED;
}
diff --git a/chromium/content/browser/renderer_host/frame_memory_manager.h b/chromium/content/browser/renderer_host/frame_memory_manager.h
deleted file mode 100644
index ce3fc258226..00000000000
--- a/chromium/content/browser/renderer_host/frame_memory_manager.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_FRAME_MEMORY_MANAGER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_FRAME_MEMORY_MANAGER_H_
-
-#include <list>
-#include <set>
-
-#include "base/basictypes.h"
-
-template <typename T> struct DefaultSingletonTraits;
-
-namespace content {
-
-class FrameContainer {
- public:
- virtual void ReleaseCurrentFrame() = 0;
-};
-
-class FrameMemoryManager {
- public:
- static FrameMemoryManager* GetInstance();
-
- void AddFrame(FrameContainer*, bool visible);
- void RemoveFrame(FrameContainer*);
- void SetFrameVisibility(FrameContainer*, bool visible);
-
- private:
- FrameMemoryManager();
- ~FrameMemoryManager();
- void CullHiddenFrames();
- friend struct DefaultSingletonTraits<FrameMemoryManager>;
-
- std::set<FrameContainer*> visible_frames_;
- std::list<FrameContainer*> hidden_frames_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameMemoryManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_MEMORY_MANAGER_H_
diff --git a/chromium/content/browser/renderer_host/generic_touch_gesture_android.cc b/chromium/content/browser/renderer_host/generic_touch_gesture_android.cc
deleted file mode 100644
index 74080cd408c..00000000000
--- a/chromium/content/browser/renderer_host/generic_touch_gesture_android.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/generic_touch_gesture_android.h"
-
-#include "base/debug/trace_event.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "jni/GenericTouchGesture_jni.h"
-
-namespace {
-bool g_jni_initialized = false;
-
-void RegisterNativesIfNeeded(JNIEnv* env) {
- if (!g_jni_initialized) {
- content::RegisterNativesImpl(env);
- g_jni_initialized = true;
- }
-}
-} // namespace
-
-namespace content {
-
-GenericTouchGestureAndroid::GenericTouchGestureAndroid(
- RenderWidgetHost* rwh,
- base::android::ScopedJavaLocalRef<jobject> java_touch_gesture)
- : has_started_(false),
- has_finished_(false),
- rwh_(rwh),
- java_touch_gesture_(java_touch_gesture) {
- JNIEnv* env = base::android::AttachCurrentThread();
- RegisterNativesIfNeeded(env);
-}
-
-GenericTouchGestureAndroid::~GenericTouchGestureAndroid() {
-}
-
-bool GenericTouchGestureAndroid::ForwardInputEvents(
- base::TimeTicks now, RenderWidgetHost* host) {
- if (!has_started_) {
- has_started_ = true;
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_GenericTouchGesture_start(
- env, java_touch_gesture_.obj(), reinterpret_cast<intptr_t>(this));
- }
-
- return !has_finished_;
-}
-
-float GenericTouchGestureAndroid::GetDelta(
- JNIEnv* env, jobject obj, float scale) {
- return synthetic_gesture_calculator_.GetDelta(
- base::TimeTicks::Now(),
- RenderWidgetHostImpl::From(rwh_)->GetSyntheticGestureMessageInterval()) *
- scale;
-}
-
-void GenericTouchGestureAndroid::SetHasFinished(JNIEnv* env, jobject obj) {
- has_finished_ = true;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/generic_touch_gesture_android.h b/chromium/content/browser/renderer_host/generic_touch_gesture_android.h
deleted file mode 100644
index 030239b1c30..00000000000
--- a/chromium/content/browser/renderer_host/generic_touch_gesture_android.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_GENERIC_TOUCH_GESTURE_ANDROID_H_
-#define CONTENT_BROWSER_RENDERER_HOST_GENERIC_TOUCH_GESTURE_ANDROID_H_
-
-#include "base/android/jni_android.h"
-#include "base/time/time.h"
-#include "content/browser/renderer_host/synthetic_gesture_calculator.h"
-#include "content/port/browser/synthetic_gesture.h"
-
-namespace content {
-
-class ContentViewCore;
-class RenderWidgetHost;
-
-class GenericTouchGestureAndroid : public SyntheticGesture {
- public:
- GenericTouchGestureAndroid(
- RenderWidgetHost* rwh,
- base::android::ScopedJavaLocalRef<jobject> java_scroller);
-
- // Called by the java side once the TimeAnimator ticks.
- float GetDelta(JNIEnv* env, jobject obj, float scale);
- void SetHasFinished(JNIEnv* env, jobject obj);
-
- // SmoothScrollGesture
- virtual bool ForwardInputEvents(base::TimeTicks now,
- RenderWidgetHost* host) OVERRIDE;
-
- private:
- virtual ~GenericTouchGestureAndroid();
-
- SyntheticGestureCalculator synthetic_gesture_calculator_;
-
- bool has_started_;
- bool has_finished_;
-
- RenderWidgetHost* rwh_;
- base::android::ScopedJavaGlobalRef<jobject> java_touch_gesture_;
-
- DISALLOW_COPY_AND_ASSIGN(GenericTouchGestureAndroid);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_GENERIC_TOUCH_GESTURE_ANDROID_H_
diff --git a/chromium/content/browser/renderer_host/gpu_message_filter.cc b/chromium/content/browser/renderer_host/gpu_message_filter.cc
index 8ab2280a0aa..9068a4072ec 100644
--- a/chromium/content/browser/renderer_host/gpu_message_filter.cc
+++ b/chromium/content/browser/renderer_host/gpu_message_filter.cc
@@ -23,16 +23,16 @@ namespace content {
struct GpuMessageFilter::CreateViewCommandBufferRequest {
CreateViewCommandBufferRequest(
- int32 surface_id_,
- const GPUCreateCommandBufferConfig& init_params_,
- IPC::Message* reply_)
- : surface_id(surface_id_),
- init_params(init_params_),
- reply(reply_) {
+ int32 surface_id,
+ const GPUCreateCommandBufferConfig& init_params,
+ scoped_ptr<IPC::Message> reply)
+ : surface_id(surface_id),
+ init_params(init_params),
+ reply(reply.Pass()) {
}
int32 surface_id;
GPUCreateCommandBufferConfig init_params;
- IPC::Message* reply;
+ scoped_ptr<IPC::Message> reply;
};
struct GpuMessageFilter::FrameSubscription {
@@ -107,7 +107,7 @@ void GpuMessageFilter::SurfaceUpdated(int32 surface_id) {
linked_ptr<CreateViewCommandBufferRequest> request = *it;
OnCreateViewCommandBuffer(request->surface_id,
request->init_params,
- request->reply);
+ request->reply.release());
}
}
}
@@ -136,8 +136,9 @@ void GpuMessageFilter::EndFrameSubscription(int route_id) {
void GpuMessageFilter::OnEstablishGpuChannel(
CauseForGpuLaunch cause_for_gpu_launch,
- IPC::Message* reply) {
+ IPC::Message* reply_ptr) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ scoped_ptr<IPC::Message> reply(reply_ptr);
// TODO(apatrick): Eventually, this will return the route ID of a
// GpuProcessStub, from which the renderer process will create a
@@ -152,7 +153,7 @@ void GpuMessageFilter::OnEstablishGpuChannel(
cause_for_gpu_launch);
if (!host) {
reply->set_reply_error();
- Send(reply);
+ Send(reply.release());
return;
}
@@ -167,14 +168,15 @@ void GpuMessageFilter::OnEstablishGpuChannel(
share_contexts_,
base::Bind(&GpuMessageFilter::EstablishChannelCallback,
weak_ptr_factory_.GetWeakPtr(),
- reply));
+ base::Passed(&reply)));
}
void GpuMessageFilter::OnCreateViewCommandBuffer(
int32 surface_id,
const GPUCreateCommandBufferConfig& init_params,
- IPC::Message* reply) {
+ IPC::Message* reply_ptr) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ scoped_ptr<IPC::Message> reply(reply_ptr);
GpuSurfaceTracker* surface_tracker = GpuSurfaceTracker::Get();
gfx::GLSurfaceHandle compositing_surface;
@@ -196,7 +198,8 @@ void GpuMessageFilter::OnCreateViewCommandBuffer(
// host, it means the GPU process died and we need to wait until the UI
// re-allocates the surface in the new process.
linked_ptr<CreateViewCommandBufferRequest> request(
- new CreateViewCommandBufferRequest(surface_id, init_params, reply));
+ new CreateViewCommandBufferRequest(
+ surface_id, init_params, reply.Pass()));
pending_requests_.push_back(request);
return;
}
@@ -207,7 +210,7 @@ void GpuMessageFilter::OnCreateViewCommandBuffer(
// GpuProcessStub with a particular routing ID. The error will be set if
// the GpuProcessStub with that routing ID is not in the MessageRouter.
reply->set_reply_error();
- Send(reply);
+ Send(reply.release());
return;
}
@@ -218,25 +221,25 @@ void GpuMessageFilter::OnCreateViewCommandBuffer(
init_params,
base::Bind(&GpuMessageFilter::CreateCommandBufferCallback,
weak_ptr_factory_.GetWeakPtr(),
- reply));
+ base::Passed(&reply)));
}
void GpuMessageFilter::EstablishChannelCallback(
- IPC::Message* reply,
+ scoped_ptr<IPC::Message> reply,
const IPC::ChannelHandle& channel,
const gpu::GPUInfo& gpu_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
GpuHostMsg_EstablishGpuChannel::WriteReplyParams(
- reply, render_process_id_, channel, gpu_info);
- Send(reply);
+ reply.get(), render_process_id_, channel, gpu_info);
+ Send(reply.release());
}
void GpuMessageFilter::CreateCommandBufferCallback(
- IPC::Message* reply, int32 route_id) {
+ scoped_ptr<IPC::Message> reply, int32 route_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- GpuHostMsg_CreateViewCommandBuffer::WriteReplyParams(reply, route_id);
- Send(reply);
+ GpuHostMsg_CreateViewCommandBuffer::WriteReplyParams(reply.get(), route_id);
+ Send(reply.release());
}
void GpuMessageFilter::BeginAllFrameSubscriptions() {
diff --git a/chromium/content/browser/renderer_host/gpu_message_filter.h b/chromium/content/browser/renderer_host/gpu_message_filter.h
index bd9c10fefa5..5492ad989a0 100644
--- a/chromium/content/browser/renderer_host/gpu_message_filter.h
+++ b/chromium/content/browser/renderer_host/gpu_message_filter.h
@@ -9,6 +9,7 @@
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
#include "content/common/gpu/gpu_process_launch_causes.h"
@@ -65,10 +66,11 @@ class GpuMessageFilter : public BrowserMessageFilter {
const GPUCreateCommandBufferConfig& init_params,
IPC::Message* reply);
// Helper callbacks for the message handlers.
- void EstablishChannelCallback(IPC::Message* reply,
+ void EstablishChannelCallback(scoped_ptr<IPC::Message> reply,
const IPC::ChannelHandle& channel,
const gpu::GPUInfo& gpu_info);
- void CreateCommandBufferCallback(IPC::Message* reply, int32 route_id);
+ void CreateCommandBufferCallback(scoped_ptr<IPC::Message> reply,
+ int32 route_id);
void BeginAllFrameSubscriptions();
void EndAllFrameSubscriptions();
diff --git a/chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc b/chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc
index 65dc54524c2..d4b77894f5a 100644
--- a/chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc
+++ b/chromium/content/browser/renderer_host/gtk_im_context_wrapper.cc
@@ -17,7 +17,7 @@
#include "content/browser/renderer_host/render_widget_host_view_gtk.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
-#include "ui/base/gtk/gtk_im_context_util.h"
+#include "ui/base/ime/composition_text_util_pango.h"
#include "ui/gfx/gtk_util.h"
#include "ui/gfx/rect.h"
@@ -41,11 +41,11 @@ const int kCompositionEventKeyCode = 229;
} // namespace
// ui::CompositionUnderline should be identical to
-// WebKit::WebCompositionUnderline, so that we can do reinterpret_cast safely.
+// blink::WebCompositionUnderline, so that we can do reinterpret_cast safely.
// TODO(suzhe): remove it after migrating all code in chrome to use
// ui::CompositionUnderline.
COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
- sizeof(WebKit::WebCompositionUnderline),
+ sizeof(blink::WebCompositionUnderline),
ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
GtkIMContextWrapper::GtkIMContextWrapper(RenderWidgetHostViewGtk* host_view)
@@ -402,7 +402,7 @@ void GtkIMContextWrapper::ProcessUnfilteredKeyPressEvent(
// isSystemKey will be set to true if this key event has Alt modifier,
// see WebInputEventFactory::keyboardEvent() for details.
if (wke->text[0]) {
- wke->type = WebKit::WebInputEvent::Char;
+ wke->type = blink::WebInputEvent::Char;
wke->skip_in_browser = true;
host_view_->ForwardKeyboardEvent(*wke);
}
@@ -455,8 +455,8 @@ void GtkIMContextWrapper::ProcessInputMethodResult(const GdkEventKey* event,
is_composing_text_ = true;
// TODO(suzhe): convert both renderer_host and renderer to use
// ui::CompositionText.
- const std::vector<WebKit::WebCompositionUnderline>& underlines =
- reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
+ const std::vector<blink::WebCompositionUnderline>& underlines =
+ reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>(
composition_.underlines);
host->ImeSetComposition(composition_.text, underlines,
composition_.selection.start(),
@@ -477,7 +477,7 @@ void GtkIMContextWrapper::ConfirmComposition() {
if (host_view_->GetRenderWidgetHost()) {
RenderWidgetHostImpl::From(
host_view_->GetRenderWidgetHost())->ImeConfirmComposition(
- string16(), gfx::Range::InvalidRange(), false);
+ base::string16(), gfx::Range::InvalidRange(), false);
}
// Reset the input method.
@@ -485,7 +485,7 @@ void GtkIMContextWrapper::ConfirmComposition() {
}
}
-void GtkIMContextWrapper::HandleCommit(const string16& text) {
+void GtkIMContextWrapper::HandleCommit(const base::string16& text) {
if (suppress_next_commit_)
return;
@@ -500,11 +500,11 @@ void GtkIMContextWrapper::HandleCommit(const string16& text) {
// In this case, the text must be committed directly.
if (!is_in_key_event_handler_ && host_view_->GetRenderWidgetHost()) {
// Workaround http://crbug.com/45478 by sending fake key down/up events.
- SendFakeCompositionKeyEvent(WebKit::WebInputEvent::RawKeyDown);
+ SendFakeCompositionKeyEvent(blink::WebInputEvent::RawKeyDown);
RenderWidgetHostImpl::From(
host_view_->GetRenderWidgetHost())->ImeConfirmComposition(
text, gfx::Range::InvalidRange(), false);
- SendFakeCompositionKeyEvent(WebKit::WebInputEvent::KeyUp);
+ SendFakeCompositionKeyEvent(blink::WebInputEvent::KeyUp);
}
}
@@ -545,17 +545,17 @@ void GtkIMContextWrapper::HandlePreeditChanged(const gchar* text,
if (!is_in_key_event_handler_ && is_composing_text_ &&
host_view_->GetRenderWidgetHost()) {
// Workaround http://crbug.com/45478 by sending fake key down/up events.
- SendFakeCompositionKeyEvent(WebKit::WebInputEvent::RawKeyDown);
+ SendFakeCompositionKeyEvent(blink::WebInputEvent::RawKeyDown);
// TODO(suzhe): convert both renderer_host and renderer to use
// ui::CompositionText.
- const std::vector<WebKit::WebCompositionUnderline>& underlines =
- reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
+ const std::vector<blink::WebCompositionUnderline>& underlines =
+ reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>(
composition_.underlines);
RenderWidgetHostImpl::From(
host_view_->GetRenderWidgetHost())->ImeSetComposition(
composition_.text, underlines, composition_.selection.start(),
composition_.selection.end());
- SendFakeCompositionKeyEvent(WebKit::WebInputEvent::KeyUp);
+ SendFakeCompositionKeyEvent(blink::WebInputEvent::KeyUp);
}
}
@@ -613,7 +613,7 @@ void GtkIMContextWrapper::HandleHostViewUnrealize() {
}
void GtkIMContextWrapper::SendFakeCompositionKeyEvent(
- WebKit::WebInputEvent::Type type) {
+ blink::WebInputEvent::Type type) {
NativeWebKeyboardEvent fake_event;
fake_event.windowsKeyCode = kCompositionEventKeyCode;
fake_event.skip_in_browser = true;
diff --git a/chromium/content/browser/renderer_host/gtk_im_context_wrapper.h b/chromium/content/browser/renderer_host/gtk_im_context_wrapper.h
index 9f1355143b9..8bd027f0e89 100644
--- a/chromium/content/browser/renderer_host/gtk_im_context_wrapper.h
+++ b/chromium/content/browser/renderer_host/gtk_im_context_wrapper.h
@@ -75,7 +75,7 @@ class GtkIMContextWrapper {
void ProcessInputMethodResult(const GdkEventKey* event, bool filtered);
// Real code of "commit" signal handler.
- void HandleCommit(const string16& text);
+ void HandleCommit(const base::string16& text);
// Real code of "preedit-start" signal handler.
void HandlePreeditStart();
@@ -101,7 +101,7 @@ class GtkIMContextWrapper {
// Sends a fake composition key event with specified event type. A composition
// key event is a key event with special key code 229.
- void SendFakeCompositionKeyEvent(WebKit::WebInputEvent::Type type);
+ void SendFakeCompositionKeyEvent(blink::WebInputEvent::Type type);
// Signal handlers of GtkIMContext object.
static void HandleCommitThunk(GtkIMContext* context, gchar* text,
@@ -180,7 +180,7 @@ class GtkIMContextWrapper {
// Stores a copy of the most recent commit text received by commit signal
// handler.
- string16 commit_text_;
+ base::string16 commit_text_;
// If it's true then the next "commit" signal will be suppressed.
// It's only used to workaround http://crbug.com/50485.
diff --git a/chromium/content/browser/renderer_host/gtk_key_bindings_handler.cc b/chromium/content/browser/renderer_host/gtk_key_bindings_handler.cc
index 5a05eeb318b..3830364a0e8 100644
--- a/chromium/content/browser/renderer_host/gtk_key_bindings_handler.cc
+++ b/chromium/content/browser/renderer_host/gtk_key_bindings_handler.cc
@@ -29,7 +29,7 @@ GtkKeyBindingsHandler::~GtkKeyBindingsHandler() {
bool GtkKeyBindingsHandler::Match(const NativeWebKeyboardEvent& wke,
EditCommands* edit_commands) {
- if (wke.type == WebKit::WebInputEvent::Char || !wke.os_event)
+ if (wke.type == blink::WebInputEvent::Char || !wke.os_event)
return false;
edit_commands_.clear();
diff --git a/chromium/content/browser/renderer_host/gtk_window_utils.cc b/chromium/content/browser/renderer_host/gtk_window_utils.cc
index f05cdca3b66..240c59d2882 100644
--- a/chromium/content/browser/renderer_host/gtk_window_utils.cc
+++ b/chromium/content/browser/renderer_host/gtk_window_utils.cc
@@ -10,7 +10,7 @@
#include <vector>
-#include "third_party/WebKit/public/web/WebScreenInfo.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "ui/base/x/x11_util.h"
#include "ui/gfx/gtk_compat.h"
#include "ui/gfx/rect.h"
@@ -45,7 +45,7 @@ gfx::Rect GetWorkArea(Window window) {
property[start_index + 2], property[start_index + 3]);
}
-WebKit::WebScreenInfo GetScreenInfo(XDisplay* display, int screenNumber) {
+blink::WebScreenInfo GetScreenInfo(XDisplay* display, int screenNumber) {
// XDisplayWidth() and XDisplayHeight() return cached values. To ensure that
// we return the correct dimensions after the screen is resized, query the
// root window's geometry each time.
@@ -56,11 +56,11 @@ WebKit::WebScreenInfo GetScreenInfo(XDisplay* display, int screenNumber) {
XGetGeometry(
display, root, &root_ret, &x, &y, &width, &height, &border, &depth);
- WebKit::WebScreenInfo results;
+ blink::WebScreenInfo results;
results.depthPerComponent = 8; // Assume 8bpp, which is usually right.
results.depth = depth;
results.isMonochrome = depth == 1;
- results.rect = WebKit::WebRect(x, y, width, height);
+ results.rect = blink::WebRect(x, y, width, height);
results.availableRect = results.rect;
return results;
}
@@ -68,7 +68,7 @@ WebKit::WebScreenInfo GetScreenInfo(XDisplay* display, int screenNumber) {
} // namespace
void GetScreenInfoFromNativeWindow(
- GdkWindow* gdk_window, WebKit::WebScreenInfo* results) {
+ GdkWindow* gdk_window, blink::WebScreenInfo* results) {
GdkScreen* screen = gdk_window_get_screen(gdk_window);
*results = GetScreenInfo(gdk_x11_drawable_get_xdisplay(gdk_window),
gdk_x11_screen_get_screen_number(screen));
@@ -76,7 +76,7 @@ void GetScreenInfoFromNativeWindow(
int monitor_number = gdk_screen_get_monitor_at_window(screen, gdk_window);
GdkRectangle monitor_rect;
gdk_screen_get_monitor_geometry(screen, monitor_number, &monitor_rect);
- results->rect = WebKit::WebRect(monitor_rect.x, monitor_rect.y,
+ results->rect = blink::WebRect(monitor_rect.x, monitor_rect.y,
monitor_rect.width, monitor_rect.height);
gfx::Rect available_rect = results->rect;
diff --git a/chromium/content/browser/renderer_host/gtk_window_utils.h b/chromium/content/browser/renderer_host/gtk_window_utils.h
index ed0cfe13895..93f1d68da68 100644
--- a/chromium/content/browser/renderer_host/gtk_window_utils.h
+++ b/chromium/content/browser/renderer_host/gtk_window_utils.h
@@ -9,14 +9,14 @@
typedef struct _GdkDrawable GdkWindow;
-namespace WebKit {
+namespace blink {
struct WebScreenInfo;
}
namespace content {
CONTENT_EXPORT void GetScreenInfoFromNativeWindow(
- GdkWindow* gdk_window, WebKit::WebScreenInfo* results);
+ GdkWindow* gdk_window, blink::WebScreenInfo* results);
} // namespace content
diff --git a/chromium/content/browser/renderer_host/image_transport_factory_android.cc b/chromium/content/browser/renderer_host/image_transport_factory_android.cc
index bc0d365d249..47ff2c5bb9c 100644
--- a/chromium/content/browser/renderer_host/image_transport_factory_android.cc
+++ b/chromium/content/browser/renderer_host/image_transport_factory_android.cc
@@ -5,17 +5,14 @@
#include "content/browser/renderer_host/image_transport_factory_android.h"
#include "base/lazy_instance.h"
-#include "base/memory/singleton.h"
#include "base/strings/stringprintf.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
-#include "content/browser/renderer_host/compositor_impl_android.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/common/gpu/gpu_process_launch_causes.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/gfx/android/device_display_info.h"
-#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
namespace content {
@@ -23,7 +20,7 @@ base::LazyInstance<ObserverList<ImageTransportFactoryAndroidObserver> >::Leaky
g_factory_observers = LAZY_INSTANCE_INITIALIZER;
class GLContextLostListener
- : public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback {
+ : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
public:
// WebGraphicsContextLostCallback implementation.
virtual void onContextLost() OVERRIDE;
@@ -33,53 +30,8 @@ class GLContextLostListener
namespace {
-using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
-
static ImageTransportFactoryAndroid* g_factory = NULL;
-class DirectGLImageTransportFactory : public ImageTransportFactoryAndroid {
- public:
- DirectGLImageTransportFactory();
- virtual ~DirectGLImageTransportFactory();
-
- virtual uint32_t InsertSyncPoint() OVERRIDE { return 0; }
- virtual void WaitSyncPoint(uint32_t sync_point) OVERRIDE {}
- virtual uint32_t CreateTexture() OVERRIDE {
- return context_->createTexture();
- }
- virtual void DeleteTexture(uint32_t id) OVERRIDE {
- context_->deleteTexture(id);
- }
- virtual void AcquireTexture(
- uint32 texture_id, const signed char* mailbox_name) OVERRIDE {}
- virtual WebKit::WebGraphicsContext3D* GetContext3D() OVERRIDE {
- return context_.get();
- }
- virtual GLHelper* GetGLHelper() OVERRIDE { return NULL; }
-
- private:
- scoped_ptr<WebKit::WebGraphicsContext3D> context_;
-
- DISALLOW_COPY_AND_ASSIGN(DirectGLImageTransportFactory);
-};
-
-DirectGLImageTransportFactory::DirectGLImageTransportFactory() {
- WebKit::WebGraphicsContext3D::Attributes attrs;
- attrs.shareResources = true;
- attrs.noAutomaticFlushes = true;
- context_ = webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl::
- CreateViewContext(attrs, NULL);
- context_->setContextLostCallback(context_lost_listener_.get());
- if (context_->makeContextCurrent())
- context_->pushGroupMarkerEXT(
- base::StringPrintf("DirectGLImageTransportFactory-%p",
- context_.get()).c_str());
-}
-
-DirectGLImageTransportFactory::~DirectGLImageTransportFactory() {
- context_->setContextLostCallback(NULL);
-}
-
class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid {
public:
CmdBufferImageTransportFactory();
@@ -91,10 +43,13 @@ class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid {
virtual void DeleteTexture(uint32_t id) OVERRIDE;
virtual void AcquireTexture(
uint32 texture_id, const signed char* mailbox_name) OVERRIDE;
- virtual WebKit::WebGraphicsContext3D* GetContext3D() OVERRIDE {
+ virtual blink::WebGraphicsContext3D* GetContext3D() OVERRIDE {
return context_.get();
}
virtual GLHelper* GetGLHelper() OVERRIDE;
+ virtual uint32 GetChannelID() OVERRIDE {
+ return BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
+ }
private:
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
@@ -104,34 +59,36 @@ class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid {
};
CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() {
- WebKit::WebGraphicsContext3D::Attributes attrs;
+ BrowserGpuChannelHostFactory* factory =
+ BrowserGpuChannelHostFactory::instance();
+ scoped_refptr<GpuChannelHost> gpu_channel_host(factory->EstablishGpuChannelSync(
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
+ DCHECK(gpu_channel_host);
+
+ blink::WebGraphicsContext3D::Attributes attrs;
attrs.shareResources = true;
- GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance();
GURL url("chrome://gpu/ImageTransportFactoryAndroid");
- base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> swap_client;
- context_.reset(new WebGraphicsContext3DCommandBufferImpl(0, // offscreen
- url,
- factory,
- swap_client));
static const size_t kBytesPerPixel = 4;
gfx::DeviceDisplayInfo display_info;
- size_t full_screen_texture_size_in_bytes =
- display_info.GetDisplayHeight() *
- display_info.GetDisplayWidth() *
- kBytesPerPixel;
+ size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() *
+ display_info.GetDisplayWidth() *
+ kBytesPerPixel;
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
+ limits.command_buffer_size = 64 * 1024;
+ limits.start_transfer_buffer_size = 64 * 1024;
+ limits.min_transfer_buffer_size = 64 * 1024;
+ limits.max_transfer_buffer_size = std::min(
+ 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
+ limits.mapped_memory_reclaim_limit =
+ WebGraphicsContext3DCommandBufferImpl::kNoLimit;
+ context_.reset(
+ new WebGraphicsContext3DCommandBufferImpl(0, // offscreen
+ url,
+ gpu_channel_host.get(),
+ attrs,
+ false,
+ limits));
context_->setContextLostCallback(context_lost_listener_.get());
- context_->Initialize(
- attrs,
- false,
- CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE,
- 64 * 1024, // command buffer size
- 64 * 1024, // starting buffer size
- 64 * 1024, // min buffer size
- std::min(3 * full_screen_texture_size_in_bytes,
- kDefaultMaxTransferBufferSize),
- WebGraphicsContext3DCommandBufferImpl::kNoLimit
- );
-
if (context_->makeContextCurrent())
context_->pushGroupMarkerEXT(
base::StringPrintf("CmdBufferImageTransportFactory-%p",
@@ -182,12 +139,13 @@ void CmdBufferImageTransportFactory::AcquireTexture(
}
context_->bindTexture(GL_TEXTURE_2D, texture_id);
context_->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox_name);
- context_->flush();
+ context_->shallowFlushCHROMIUM();
}
GLHelper* CmdBufferImageTransportFactory::GetGLHelper() {
if (!gl_helper_)
- gl_helper_.reset(new GLHelper(context_.get()));
+ gl_helper_.reset(new GLHelper(context_.get(),
+ context_->GetContextSupport()));
return gl_helper_.get();
}
@@ -196,12 +154,8 @@ GLHelper* CmdBufferImageTransportFactory::GetGLHelper() {
// static
ImageTransportFactoryAndroid* ImageTransportFactoryAndroid::GetInstance() {
- if (!g_factory) {
- if (CompositorImpl::UsesDirectGL())
- g_factory = new DirectGLImageTransportFactory();
- else
- g_factory = new CmdBufferImageTransportFactory();
- }
+ if (!g_factory)
+ g_factory = new CmdBufferImageTransportFactory();
return g_factory;
}
diff --git a/chromium/content/browser/renderer_host/image_transport_factory_android.h b/chromium/content/browser/renderer_host/image_transport_factory_android.h
index 22dc09ef435..54434fc103f 100644
--- a/chromium/content/browser/renderer_host/image_transport_factory_android.h
+++ b/chromium/content/browser/renderer_host/image_transport_factory_android.h
@@ -12,7 +12,7 @@ namespace gfx {
class GLShareGroup;
}
-namespace WebKit {
+namespace blink {
class WebGraphicsContext3D;
}
@@ -39,8 +39,9 @@ class ImageTransportFactoryAndroid {
virtual void AcquireTexture(
uint32 texture_id, const signed char* mailbox_name) = 0;
- virtual WebKit::WebGraphicsContext3D* GetContext3D() = 0;
+ virtual blink::WebGraphicsContext3D* GetContext3D() = 0;
virtual GLHelper* GetGLHelper() = 0;
+ virtual uint32 GetChannelID() = 0;
static void AddObserver(ImageTransportFactoryAndroidObserver* observer);
static void RemoveObserver(ImageTransportFactoryAndroidObserver* observer);
diff --git a/chromium/content/browser/renderer_host/ime_adapter_android.cc b/chromium/content/browser/renderer_host/ime_adapter_android.cc
index da14d7a3d5d..92d972f22c6 100644
--- a/chromium/content/browser/renderer_host/ime_adapter_android.cc
+++ b/chromium/content/browser/renderer_host/ime_adapter_android.cc
@@ -40,11 +40,11 @@ NativeWebKeyboardEvent NativeWebKeyboardEventFromKeyEvent(
int key_code,
bool is_system_key,
int unicode_char) {
- WebKit::WebInputEvent::Type type = WebKit::WebInputEvent::Undefined;
+ blink::WebInputEvent::Type type = blink::WebInputEvent::Undefined;
if (action == AKEY_EVENT_ACTION_DOWN)
- type = WebKit::WebInputEvent::RawKeyDown;
+ type = blink::WebInputEvent::RawKeyDown;
else if (action == AKEY_EVENT_ACTION_UP)
- type = WebKit::WebInputEvent::KeyUp;
+ type = blink::WebInputEvent::KeyUp;
return NativeWebKeyboardEvent(java_key_event, type, modifiers,
time_ms, key_code, unicode_char, is_system_key);
}
@@ -56,16 +56,14 @@ bool RegisterImeAdapter(JNIEnv* env) {
return false;
Java_ImeAdapter_initializeWebInputEvents(env,
- WebKit::WebInputEvent::RawKeyDown,
- WebKit::WebInputEvent::KeyUp,
- WebKit::WebInputEvent::Char,
- WebKit::WebInputEvent::ShiftKey,
- WebKit::WebInputEvent::AltKey,
- WebKit::WebInputEvent::ControlKey,
- WebKit::WebInputEvent::CapsLockOn,
- WebKit::WebInputEvent::NumLockOn);
- // TODO(miguelg): remove date time related enums after
- // https://bugs.webkit.org/show_bug.cgi?id=100935.
+ blink::WebInputEvent::RawKeyDown,
+ blink::WebInputEvent::KeyUp,
+ blink::WebInputEvent::Char,
+ blink::WebInputEvent::ShiftKey,
+ blink::WebInputEvent::AltKey,
+ blink::WebInputEvent::ControlKey,
+ blink::WebInputEvent::CapsLockOn,
+ blink::WebInputEvent::NumLockOn);
Java_ImeAdapter_initializeTextInputTypes(
env,
ui::TEXT_INPUT_TYPE_NONE,
@@ -77,12 +75,6 @@ bool RegisterImeAdapter(JNIEnv* env) {
ui::TEXT_INPUT_TYPE_EMAIL,
ui::TEXT_INPUT_TYPE_TELEPHONE,
ui::TEXT_INPUT_TYPE_NUMBER,
- ui::TEXT_INPUT_TYPE_DATE,
- ui::TEXT_INPUT_TYPE_DATE_TIME,
- ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL,
- ui::TEXT_INPUT_TYPE_MONTH,
- ui::TEXT_INPUT_TYPE_TIME,
- ui::TEXT_INPUT_TYPE_WEEK,
ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE);
return true;
}
@@ -104,7 +96,7 @@ bool ImeAdapterAndroid::SendSyntheticKeyEvent(JNIEnv*,
long time_ms,
int key_code,
int text) {
- NativeWebKeyboardEvent event(static_cast<WebKit::WebInputEvent::Type>(type),
+ NativeWebKeyboardEvent event(static_cast<blink::WebInputEvent::Type>(type),
0 /* modifiers */, time_ms / 1000.0, key_code,
text, false /* is_system_key */);
rwhva_->SendKeyEvent(event);
@@ -120,7 +112,7 @@ bool ImeAdapterAndroid::SendKeyEvent(JNIEnv* env, jobject,
env, original_key_event, action, modifiers,
time_ms, key_code, is_system_key, unicode_char);
bool key_down_text_insertion =
- event.type == WebKit::WebInputEvent::RawKeyDown && event.text[0];
+ event.type == blink::WebInputEvent::RawKeyDown && event.text[0];
// If we are going to follow up with a synthetic Char event, then that's the
// one we expect to test if it's handled or unhandled, so skip handling the
// "real" event in the browser.
@@ -129,7 +121,7 @@ bool ImeAdapterAndroid::SendKeyEvent(JNIEnv* env, jobject,
if (key_down_text_insertion) {
// Send a Char event, but without an os_event since we don't want to
// roundtrip back to java such synthetic event.
- NativeWebKeyboardEvent char_event(WebKit::WebInputEvent::Char, modifiers,
+ NativeWebKeyboardEvent char_event(blink::WebInputEvent::Char, modifiers,
time_ms, key_code, unicode_char,
is_system_key);
char_event.skip_in_browser = key_down_text_insertion;
@@ -144,10 +136,10 @@ void ImeAdapterAndroid::SetComposingText(JNIEnv* env, jobject, jstring text,
if (!rwhi)
return;
- string16 text16 = ConvertJavaStringToUTF16(env, text);
- std::vector<WebKit::WebCompositionUnderline> underlines;
+ base::string16 text16 = ConvertJavaStringToUTF16(env, text);
+ std::vector<blink::WebCompositionUnderline> underlines;
underlines.push_back(
- WebKit::WebCompositionUnderline(0, text16.length(), SK_ColorBLACK,
+ blink::WebCompositionUnderline(0, text16.length(), SK_ColorBLACK,
false));
// new_cursor_position is as described in the Android API for
// InputConnection#setComposingText, whereas the parameters for
@@ -158,22 +150,12 @@ void ImeAdapterAndroid::SetComposingText(JNIEnv* env, jobject, jstring text,
rwhi->ImeSetComposition(text16, underlines, new_cursor_pos, new_cursor_pos);
}
-void ImeAdapterAndroid::ImeBatchStateChanged(JNIEnv* env,
- jobject,
- jboolean is_begin) {
- RenderWidgetHostImpl* rwhi = GetRenderWidgetHostImpl();
- if (!rwhi)
- return;
-
- rwhi->Send(new ViewMsg_ImeBatchStateChanged(rwhi->GetRoutingID(), is_begin));
-}
-
void ImeAdapterAndroid::CommitText(JNIEnv* env, jobject, jstring text) {
RenderWidgetHostImpl* rwhi = GetRenderWidgetHostImpl();
if (!rwhi)
return;
- string16 text16 = ConvertJavaStringToUTF16(env, text);
+ base::string16 text16 = ConvertJavaStringToUTF16(env, text);
rwhi->ImeConfirmComposition(text16, gfx::Range::InvalidRange(), false);
}
@@ -182,7 +164,8 @@ void ImeAdapterAndroid::FinishComposingText(JNIEnv* env, jobject) {
if (!rwhi)
return;
- rwhi->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), true);
+ rwhi->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
+ true);
}
void ImeAdapterAndroid::AttachImeAdapter(JNIEnv* env, jobject java_object) {
@@ -212,9 +195,9 @@ void ImeAdapterAndroid::SetComposingRegion(JNIEnv*, jobject,
if (!rwhi)
return;
- std::vector<WebKit::WebCompositionUnderline> underlines;
+ std::vector<blink::WebCompositionUnderline> underlines;
underlines.push_back(
- WebKit::WebCompositionUnderline(0, end - start, SK_ColorBLACK, false));
+ blink::WebCompositionUnderline(0, end - start, SK_ColorBLACK, false));
rwhi->Send(new ViewMsg_SetCompositionFromExistingText(
rwhi->GetRoutingID(), start, end, underlines));
diff --git a/chromium/content/browser/renderer_host/ime_adapter_android.h b/chromium/content/browser/renderer_host/ime_adapter_android.h
index d55f0d532ac..ce3c335c41b 100644
--- a/chromium/content/browser/renderer_host/ime_adapter_android.h
+++ b/chromium/content/browser/renderer_host/ime_adapter_android.h
@@ -27,7 +27,7 @@ class ImeAdapterAndroid {
// Called from java -> native
// The java side is responsible to translate android KeyEvent various enums
- // and values into the corresponding WebKit::WebInputEvent.
+ // and values into the corresponding blink::WebInputEvent.
bool SendKeyEvent(JNIEnv* env, jobject,
jobject original_key_event,
int action, int meta_state,
@@ -41,7 +41,6 @@ class ImeAdapterAndroid {
int native_key_code,
int unicode_char);
void SetComposingText(JNIEnv*, jobject, jstring text, int new_cursor_pos);
- void ImeBatchStateChanged(JNIEnv*, jobject, jboolean is_begin);
void CommitText(JNIEnv*, jobject, jstring text);
void FinishComposingText(JNIEnv* env, jobject);
void AttachImeAdapter(JNIEnv*, jobject java_object);
diff --git a/chromium/content/browser/renderer_host/input/browser_input_event.cc b/chromium/content/browser/renderer_host/input/browser_input_event.cc
deleted file mode 100644
index 276245e3526..00000000000
--- a/chromium/content/browser/renderer_host/input/browser_input_event.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/input/browser_input_event.h"
-
-#include "content/common/input/web_input_event_payload.h"
-
-namespace content {
-
-BrowserInputEvent::BrowserInputEvent(BrowserInputEventClient* client)
- : client_(client) {}
-
-BrowserInputEvent::~BrowserInputEvent() {}
-
-scoped_ptr<BrowserInputEvent> BrowserInputEvent::Create(
- int64 id,
- scoped_ptr<InputEvent::Payload> payload,
- BrowserInputEventClient* client) {
- DCHECK(client);
- scoped_ptr<BrowserInputEvent> event(new BrowserInputEvent(client));
- event->Initialize(id, payload.Pass());
- return event.Pass();
-}
-
-void BrowserInputEvent::OnDispatched(
- InputEventDisposition disposition,
- ScopedVector<BrowserInputEvent>* followup_events) {
- DCHECK(followup_events);
-
- bool event_consumed =
- disposition == INPUT_EVENT_MAIN_THREAD_CONSUMED ||
- disposition == INPUT_EVENT_IMPL_THREAD_CONSUMED ||
- disposition == INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED;
-
- if (!event_consumed && CanCreateFollowupEvents())
- client_->OnDispatched(*this, disposition, followup_events);
- else
- client_->OnDispatched(*this, disposition);
-}
-
-bool BrowserInputEvent::CanCreateFollowupEvents() const {
- return payload()->GetType() == InputEvent::Payload::WEB_INPUT_EVENT &&
- WebInputEventPayload::Cast(payload())->CanCreateFollowupEvents();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/browser_input_event.h b/chromium/content/browser/renderer_host/input/browser_input_event.h
deleted file mode 100644
index 6022d80ecd2..00000000000
--- a/chromium/content/browser/renderer_host/input/browser_input_event.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_BROWSER_INPUT_EVENT_H_
-#define CONTENT_BROWSER_RENDERER_HOST_INPUT_BROWSER_INPUT_EVENT_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_vector.h"
-#include "content/common/input/input_event.h"
-#include "content/common/input/input_event_disposition.h"
-
-namespace content {
-
-class BrowserInputEvent;
-
-// Provides customized dispatch response for BrowserInputEvents.
-class BrowserInputEventClient {
- public:
- virtual ~BrowserInputEventClient() {}
-
- virtual void OnDispatched(const BrowserInputEvent& event,
- InputEventDisposition disposition) {}
-
- // Called if the event went unconsumed and can create followup events. Any
- // events added to |followup| by the client will be inserted into the
- // current input event stream. |followup| will never be NULL.
- virtual void OnDispatched(const BrowserInputEvent& event,
- InputEventDisposition disposition,
- ScopedVector<BrowserInputEvent>* followup) {}
-};
-
-// Augmented InputEvent allowing customized dispatch response in the browser.
-class CONTENT_EXPORT BrowserInputEvent : public InputEvent {
- public:
- // |client| is assumed to be non-NULL.
- static scoped_ptr<BrowserInputEvent> Create(
- int64 id,
- scoped_ptr<InputEvent::Payload> payload,
- BrowserInputEventClient* client);
-
- template <typename PayloadType>
- static scoped_ptr<BrowserInputEvent> Create(int64 id,
- scoped_ptr<PayloadType> payload,
- BrowserInputEventClient* client) {
- return Create(id, payload.template PassAs<InputEvent::Payload>(), client);
- }
-
- virtual ~BrowserInputEvent();
-
- // |followup_events| must not be NULL, and will only be modified if the
- // event went unconsumed and can create followup events.
- void OnDispatched(InputEventDisposition disposition,
- ScopedVector<BrowserInputEvent>* followup_events);
-
- protected:
- explicit BrowserInputEvent(BrowserInputEventClient* client);
-
- bool CanCreateFollowupEvents() const;
-
- private:
- BrowserInputEventClient* client_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_BROWSER_INPUT_EVENT_H_
diff --git a/chromium/content/browser/renderer_host/input/buffered_input_router.cc b/chromium/content/browser/renderer_host/input/buffered_input_router.cc
deleted file mode 100644
index 97b565311d5..00000000000
--- a/chromium/content/browser/renderer_host/input/buffered_input_router.cc
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/input/buffered_input_router.h"
-
-#include "base/auto_reset.h"
-#include "content/browser/renderer_host/input/browser_input_event.h"
-#include "content/browser/renderer_host/input/input_ack_handler.h"
-#include "content/browser/renderer_host/input/input_queue.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/common/input_messages.h"
-#include "content/common/view_messages.h"
-#include "content/public/browser/native_web_keyboard_event.h"
-#include "content/public/browser/user_metrics.h"
-
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebKeyboardEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebTouchEvent;
-
-namespace content {
-
-BufferedInputRouter::BufferedInputRouter(IPC::Sender* sender,
- InputRouterClient* client,
- InputAckHandler* ack_handler,
- int routing_id)
- : client_(client),
- ack_handler_(ack_handler),
- sender_(sender),
- routing_id_(routing_id),
- has_touch_handler_(false),
- queued_touch_count_(0),
- input_queue_override_(NULL),
- next_input_id_(1),
- in_flight_packet_id_(0) {
- input_queue_.reset(new InputQueue(this));
-}
-
-BufferedInputRouter::~BufferedInputRouter() {}
-
-void BufferedInputRouter::Flush() {
- TRACE_EVENT0("input", "BufferedInputRouter::Flush");
- DCHECK_EQ(0, in_flight_packet_id_);
- input_queue_->BeginFlush();
-}
-
-bool BufferedInputRouter::SendInput(scoped_ptr<IPC::Message> message) {
- DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart);
- DCHECK(message->type() != InputMsg_HandleEventPacket::ID);
- DCHECK(message->type() != InputMsg_HandleInputEvent::ID);
- input_queue_->QueueEvent(BrowserInputEvent::Create(
- NextInputID(), IPCInputEventPayload::Create(message.Pass()), this));
- return true;
-}
-
-void BufferedInputRouter::SendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) {
- if (!client_->OnSendMouseEvent(mouse_event))
- return;
- // TODO(jdduke): Coalescing, http://crbug.com/289520
- QueueWebEvent(mouse_event.event, mouse_event.latency, false);
-}
-
-void BufferedInputRouter::SendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) {
- if (!client_->OnSendWheelEvent(wheel_event))
- return;
- QueueWebEvent(wheel_event.event, wheel_event.latency, false);
-}
-
-void BufferedInputRouter::SendKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info) {
- bool is_shortcut = false;
- if (!client_->OnSendKeyboardEvent(key_event, latency_info, &is_shortcut))
- return;
- int64 event_id = QueueWebEvent(key_event, latency_info, is_shortcut);
- if (event_id) {
- DCHECK(queued_key_map_.find(event_id) == queued_key_map_.end());
- queued_key_map_[event_id] = key_event;
- }
-}
-
-void BufferedInputRouter::SendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) {
- if (!client_->OnSendGestureEvent(gesture_event))
- return;
- QueueWebEvent(gesture_event.event, gesture_event.latency, false);
-}
-
-void BufferedInputRouter::SendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) {
- if (!client_->OnSendTouchEvent(touch_event))
- return;
- if (QueueWebEvent(touch_event.event, touch_event.latency, false))
- ++queued_touch_count_;
-}
-
-void BufferedInputRouter::SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) {
- if (!client_->OnSendMouseEventImmediately(mouse_event))
- return;
- QueueWebEvent(mouse_event.event, mouse_event.latency, false);
-}
-
-void BufferedInputRouter::SendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) {
- if (!client_->OnSendTouchEventImmediately(touch_event))
- return;
- QueueWebEvent(touch_event.event, touch_event.latency, false);
-}
-
-void BufferedInputRouter::SendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) {
- if (!client_->OnSendGestureEventImmediately(gesture_event))
- return;
- QueueWebEvent(gesture_event.event, gesture_event.latency, false);
-}
-
-void BufferedInputRouter::Deliver(const EventPacket& packet) {
- TRACE_EVENT2("input", "BufferedInputRouter::DeliverPacket",
- "id", packet.id(),
- "events", packet.size());
- DCHECK(packet.id());
- DCHECK(!in_flight_packet_id_);
- if (!sender_->Send(new InputMsg_HandleEventPacket(
- routing_id_, packet, InputEventDispositions()))) {
- return;
- }
-
- in_flight_packet_id_ = packet.id();
- client_->IncrementInFlightEventCount();
-}
-
-void BufferedInputRouter::DidFinishFlush() {
- TRACE_EVENT0("input", "BufferedInputRouter::DidFinishFlush");
- client_->DidFlush();
-}
-
-void BufferedInputRouter::SetNeedsFlush() {
- TRACE_EVENT0("input", "BufferedInputRouter::SetNeedsFlush");
- client_->SetNeedsFlush();
-}
-
-void BufferedInputRouter::OnDispatched(const BrowserInputEvent& event,
- InputEventDisposition disposition) {
- // Only WebInputEvents currently have ack response.
- if (event.payload()->GetType() != InputEvent::Payload::WEB_INPUT_EVENT)
- return;
-
- const WebInputEventPayload* web_payload =
- WebInputEventPayload::Cast(event.payload());
-
- OnWebInputEventAck(event.id(),
- *web_payload->web_event(),
- web_payload->latency_info(),
- ToAckState(disposition),
- true);
-}
-
-void BufferedInputRouter::OnDispatched(
- const BrowserInputEvent& event,
- InputEventDisposition disposition,
- ScopedVector<BrowserInputEvent>* followup) {
- DCHECK(followup);
- DCHECK_NE(INPUT_EVENT_ACK_STATE_CONSUMED, ToAckState(disposition));
-
- // Events sent to the router within this scope will be added to |followup|.
- base::AutoReset<ScopedVector<BrowserInputEvent>*> input_queue_override(
- &input_queue_override_, followup);
-
- OnDispatched(event, disposition);
-}
-
-bool BufferedInputRouter::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- bool message_is_ok = true;
- IPC_BEGIN_MESSAGE_MAP_EX(BufferedInputRouter, message, message_is_ok)
- IPC_MESSAGE_HANDLER(InputHostMsg_HandleEventPacket_ACK, OnEventPacketAck)
- IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
- OnHasTouchEventHandlers)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- if (!message_is_ok)
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
-
- return handled;
-}
-
-const NativeWebKeyboardEvent*
- BufferedInputRouter::GetLastKeyboardEvent() const {
- return queued_key_map_.empty() ? NULL : &queued_key_map_.begin()->second;
-}
-
-bool BufferedInputRouter::ShouldForwardTouchEvent() const {
- return has_touch_handler_ && queued_touch_count_ > 0;
-}
-
-bool BufferedInputRouter::ShouldForwardGestureEvent(
- const GestureEventWithLatencyInfo& touch_event) const {
- return true;
-}
-
-void BufferedInputRouter::OnWebInputEventAck(
- int64 event_id,
- const WebKit::WebInputEvent& web_event,
- const ui::LatencyInfo& latency_info,
- InputEventAckState acked_result,
- bool ack_from_input_queue) {
- if (WebInputEvent::isKeyboardEventType(web_event.type)) {
- if (ack_from_input_queue) {
- KeyMap::iterator key_it = queued_key_map_.find(event_id);
- DCHECK(key_it != queued_key_map_.end());
- NativeWebKeyboardEvent key_event = key_it->second;
- queued_key_map_.erase(key_it);
- ack_handler_->OnKeyboardEventAck(key_event, acked_result);
- } else {
- DCHECK_EQ(0, event_id);
- ack_handler_->OnKeyboardEventAck(
- static_cast<const NativeWebKeyboardEvent&>(web_event), acked_result);
- }
- // WARNING: This BufferedInputRouter can be deallocated at this point
- // (i.e. in the case of Ctrl+W, where the call to
- // HandleKeyboardEvent destroys this BufferedInputRouter).
- } else if (web_event.type == WebInputEvent::MouseWheel) {
- ack_handler_->OnWheelEventAck(
- static_cast<const WebMouseWheelEvent&>(web_event), acked_result);
- } else if (WebInputEvent::isTouchEventType(web_event.type)) {
- if (ack_from_input_queue) {
- DCHECK_GT(queued_touch_count_, 0);
- --queued_touch_count_;
- }
- ack_handler_->OnTouchEventAck(
- TouchEventWithLatencyInfo(static_cast<const WebTouchEvent&>(web_event),
- latency_info),
- acked_result);
- } else if (WebInputEvent::isGestureEventType(web_event.type)) {
- ack_handler_->OnGestureEventAck(
- static_cast<const WebGestureEvent&>(web_event), acked_result);
- } else
- NOTREACHED() << "Unexpected WebInputEvent in OnWebInputEventAck";
-}
-
-void BufferedInputRouter::OnEventPacketAck(
- int64 packet_id,
- const InputEventDispositions& dispositions) {
- TRACE_EVENT2("input", "BufferedInputRouter::OnEventPacketAck",
- "id", packet_id,
- "dispositions", dispositions.size());
- if (!in_flight_packet_id_ || packet_id != in_flight_packet_id_) {
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK);
- return;
- }
-
- in_flight_packet_id_ = 0;
- client_->DecrementInFlightEventCount();
-
- InputQueue::AckResult ack_result =
- input_queue_->OnEventPacketAck(packet_id, dispositions);
- if (ack_result == InputQueue::ACK_UNEXPECTED)
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK);
- else if (ack_result == InputQueue::ACK_INVALID)
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
-}
-
-void BufferedInputRouter::OnHasTouchEventHandlers(bool has_handlers) {
- if (has_touch_handler_ == has_handlers)
- return;
- has_touch_handler_ = has_handlers;
- client_->OnHasTouchEventHandlers(has_handlers);
-}
-
-int64 BufferedInputRouter::QueueWebEvent(const WebKit::WebInputEvent& web_event,
- const ui::LatencyInfo& latency_info,
- bool is_key_shortcut) {
- TRACE_EVENT0("input", "BufferedInputRouter::QueueWebEvent");
-
- if (FilterWebEvent(web_event, latency_info)) {
- TRACE_EVENT_INSTANT0("input",
- "BufferedInputRouter::QueueWebEvent::Filtered",
- TRACE_EVENT_SCOPE_THREAD);
- return 0;
- }
-
- int64 event_id = NextInputID();
- scoped_ptr<BrowserInputEvent> event = BrowserInputEvent::Create(
- event_id,
- WebInputEventPayload::Create(web_event,
- latency_info,
- is_key_shortcut),
- this);
-
- // The presence of |input_queue_override_| implies that we are in the
- // scope of |OnInputEventDispatched()| with an event can create followup.
- if (input_queue_override_)
- input_queue_override_->push_back(event.release());
- else
- input_queue_->QueueEvent(event.Pass());
-
- return event_id;
-}
-
-bool BufferedInputRouter::FilterWebEvent(const WebKit::WebInputEvent& web_event,
- const ui::LatencyInfo& latency_info) {
- // Perform optional, synchronous event handling, sending ACK messages for
- // processed events, or proceeding as usual.
- InputEventAckState filter_ack =
- client_->FilterInputEvent(web_event, latency_info);
- switch (filter_ack) {
- // Send the ACK and early exit.
- case INPUT_EVENT_ACK_STATE_CONSUMED:
- case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
- OnWebInputEventAck(0, web_event, latency_info, filter_ack, false);
- // WARNING: |this| may be deleted at this point.
- return true;
-
- // Drop the event.
- case INPUT_EVENT_ACK_STATE_UNKNOWN:
- return true;
-
- // Proceed as normal.
- case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
- default:
- break;
- };
-
- return false;
-}
-
-int64 BufferedInputRouter::NextInputID() { return next_input_id_++; }
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/buffered_input_router.h b/chromium/content/browser/renderer_host/input/buffered_input_router.h
deleted file mode 100644
index a9802a68198..00000000000
--- a/chromium/content/browser/renderer_host/input/buffered_input_router.h
+++ /dev/null
@@ -1,144 +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_INPUT_RENDERER_HOST_BUFFERED_INPUT_ROUTER_H_
-#define CONTENT_BROWSER_INPUT_RENDERER_HOST_BUFFERED_INPUT_ROUTER_H_
-
-#include <map>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "content/browser/renderer_host/input/browser_input_event.h"
-#include "content/browser/renderer_host/input/input_queue.h"
-#include "content/browser/renderer_host/input/input_queue_client.h"
-#include "content/browser/renderer_host/input/input_router.h"
-
-namespace IPC {
-class Sender;
-}
-
-namespace content {
-
-class InputAckHandler;
-class RenderProcessHost;
-class RenderWidgetHostImpl;
-
-// Batches input events into EventPackets using a general input queue. Packets
-// are sent the renderer on |Flush()|, called in response to flush requests.
-class CONTENT_EXPORT BufferedInputRouter
- : public NON_EXPORTED_BASE(BrowserInputEventClient),
- public NON_EXPORTED_BASE(InputQueueClient),
- public NON_EXPORTED_BASE(InputRouter) {
- public:
- // |sender|, |client| and |ack_handler| must outlive the BufferedInputRouter.
- BufferedInputRouter(IPC::Sender* sender,
- InputRouterClient* client,
- InputAckHandler* ack_handler,
- int routing_id);
- virtual ~BufferedInputRouter();
-
- // InputRouter
- virtual void Flush() OVERRIDE;
- virtual bool SendInput(scoped_ptr<IPC::Message> message) OVERRIDE;
-
- // Certain unhandled input event acks may create follow-up events, e.g.,
- // TouchEvent -> GestureEvent. If these follow-up events are sent to the
- // router synchronously from the original event's |OnDispatched()| ack, they
- // will be inserted into the current input flush stream.
- virtual void SendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
- virtual void SendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE;
- virtual void SendKeyboardEvent(const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info) OVERRIDE;
- virtual void SendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
- virtual void SendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
- virtual void SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
- virtual void SendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
- virtual void SendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
- virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const OVERRIDE;
- virtual bool ShouldForwardTouchEvent() const OVERRIDE;
- virtual bool ShouldForwardGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) const OVERRIDE;
-
- // InputQueueClient
- virtual void Deliver(const EventPacket& packet) OVERRIDE;
- virtual void DidFinishFlush() OVERRIDE;
- virtual void SetNeedsFlush() OVERRIDE;
-
- // BrowserInputEventClient
- virtual void OnDispatched(const BrowserInputEvent& event,
- InputEventDisposition disposition) OVERRIDE;
- // Events delivered to the router within the scope of
- // |OnDispatched()| will be added to |followup|.
- virtual void OnDispatched(const BrowserInputEvent& event,
- InputEventDisposition disposition,
- ScopedVector<BrowserInputEvent>* followup) OVERRIDE;
-
- // IPC::Receiver
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- protected:
- void OnWebInputEventAck(int64 event_id,
- const WebKit::WebInputEvent& web_event,
- const ui::LatencyInfo& latency_info,
- InputEventAckState acked_result,
- bool ack_from_input_queue);
- void OnEventPacketAck(int64 packet_id,
- const InputEventDispositions& dispositions);
- void OnHasTouchEventHandlers(bool has_handlers);
-
- // Returns the non-zero ID associated with the |InputEvent| added to the
- // |input_queue_|. If the event was dropped or filtered, returns 0.
- int64 QueueWebEvent(const WebKit::WebInputEvent& web_event,
- const ui::LatencyInfo& latency_info,
- bool is_key_shortcut);
- // Used by |QueueWebEvent()|; returns true if an event was filtered and should
- // not be added to the |input_queue_|.
- bool FilterWebEvent(const WebKit::WebInputEvent& web_event,
- const ui::LatencyInfo& latency_info);
-
- // Generates a monotonically increasing sequences of id's, starting with 1.
- int64 NextInputID();
-
- const InputQueue* input_queue() const { return input_queue_.get(); }
-
- private:
- InputRouterClient* client_;
- InputAckHandler* ack_handler_;
- IPC::Sender* sender_;
- int routing_id_;
-
- scoped_ptr<InputQueue> input_queue_;
-
- // TODO(jdduke): Remove when we can properly serialize NativeWebKeyboardEvent.
- // Alternatively, attach WebInputEvents to InputEvents but don't serialize.
- typedef std::map<int64, NativeWebKeyboardEvent> KeyMap;
- KeyMap queued_key_map_;
-
- // Necessary for |ShouldForwardTouchEvent()|.
- bool has_touch_handler_;
- int queued_touch_count_;
-
- // This is non-NULL ONLY in the scope of OnInputEventAck(event, injector).
- ScopedVector<BrowserInputEvent>* input_queue_override_;
-
- // Used to assign unique ID's to each InputEvent that is generated.
- int64 next_input_id_;
-
- // 0 if there no in-flight EventPacket.
- int64 in_flight_packet_id_;
-
- DISALLOW_COPY_AND_ASSIGN(BufferedInputRouter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_INPUT_RENDERER_HOST_BUFFERED_INPUT_ROUTER_H_
diff --git a/chromium/content/browser/renderer_host/input/buffered_input_router_unittest.cc b/chromium/content/browser/renderer_host/input/buffered_input_router_unittest.cc
deleted file mode 100644
index 4d63444fef8..00000000000
--- a/chromium/content/browser/renderer_host/input/buffered_input_router_unittest.cc
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/basictypes.h"
-#include "content/browser/renderer_host/input/buffered_input_router.h"
-#include "content/browser/renderer_host/input/input_router_unittest.h"
-#include "content/common/input/event_packet.h"
-#include "content/common/input_messages.h"
-#include "content/common/view_messages.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebTouchEvent;
-using WebKit::WebTouchPoint;
-
-namespace content {
-
-class TestBufferedInputRouter : public BufferedInputRouter {
- public:
- TestBufferedInputRouter(IPC::Sender* sender,
- InputRouterClient* client,
- InputAckHandler* ack_handler,
- int routing_id)
- : BufferedInputRouter(sender, client, ack_handler, routing_id) {}
-
-
- size_t QueuedEventCount() const { return input_queue()->QueuedEventCount(); }
-};
-
-class BufferedInputRouterTest : public InputRouterTest {
- public:
- BufferedInputRouterTest() {}
- virtual ~BufferedInputRouterTest() {}
-
- protected:
- // InputRouterTest
- virtual scoped_ptr<InputRouter> CreateInputRouter(RenderProcessHost* process,
- InputRouterClient* client,
- InputAckHandler* handler,
- int routing_id) OVERRIDE {
- return scoped_ptr<InputRouter>(
- new TestBufferedInputRouter(process, client, handler, routing_id));
- }
-
- bool FinishFlush(const InputEventDispositions& dispositions) {
- if (!process_->sink().message_count())
- return false;
- IPC::Message message(*process_->sink().GetMessageAt(0));
- process_->sink().ClearMessages();
-
- InputMsg_HandleEventPacket::Param param;
- InputMsg_HandleEventPacket::Read(&message, &param);
- EventPacket& packet = param.a;
-
- return SendEventPacketACK(packet.id(), dispositions);
- }
-
- bool FinishFlush(InputEventDisposition disposition) {
- if (!process_->sink().message_count())
- return false;
- IPC::Message message(*process_->sink().GetMessageAt(0));
- process_->sink().ClearMessages();
-
- InputMsg_HandleEventPacket::Param param;
- InputMsg_HandleEventPacket::Read(&message, &param);
- EventPacket& packet = param.a;
-
- return SendEventPacketACK(
- packet.id(), InputEventDispositions(packet.size(), disposition));
- }
-
- bool SendEventPacketACK(int id, const InputEventDispositions& dispositions) {
- return input_router_->OnMessageReceived(
- InputHostMsg_HandleEventPacket_ACK(0, id, dispositions));
- }
-
- size_t QueuedEventCount() const {
- return buffered_input_router()->QueuedEventCount();
- }
-
- TestBufferedInputRouter* buffered_input_router() const {
- return static_cast<TestBufferedInputRouter*>(input_router_.get());
- }
-};
-
-TEST_F(BufferedInputRouterTest, InputEventsProperlyQueued) {
- EXPECT_TRUE(input_router_->SendInput(
- scoped_ptr<IPC::Message>(new InputMsg_Redo(MSG_ROUTING_NONE))));
- EXPECT_EQ(1U, QueuedEventCount());
-
- EXPECT_TRUE(input_router_->SendInput(
- scoped_ptr<IPC::Message>(new InputMsg_Cut(MSG_ROUTING_NONE))));
- EXPECT_EQ(2U, QueuedEventCount());
-
- EXPECT_TRUE(input_router_->SendInput(
- scoped_ptr<IPC::Message>(new InputMsg_Copy(MSG_ROUTING_NONE))));
- EXPECT_EQ(3U, QueuedEventCount());
-
- EXPECT_TRUE(input_router_->SendInput(
- scoped_ptr<IPC::Message>(new InputMsg_Paste(MSG_ROUTING_NONE))));
- EXPECT_EQ(4U, QueuedEventCount());
-}
-
-#define SCOPED_EXPECT(CALL, MESSAGE) { SCOPED_TRACE(MESSAGE); CALL; }
-
-TEST_F(BufferedInputRouterTest, ClientOnSendEventCalled) {
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- EXPECT_EQ(1U, QueuedEventCount());
-
- SimulateWheelEvent(5, 0, 0, false);
- EXPECT_EQ(2U, QueuedEventCount());
-
- SimulateMouseMove(5, 0, 0);
- EXPECT_EQ(3U, QueuedEventCount());
-
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- WebGestureEvent::Touchpad);
- EXPECT_EQ(4U, QueuedEventCount());
-
- SimulateTouchEvent(1, 1);
- EXPECT_EQ(5U, QueuedEventCount());
-}
-
-TEST_F(BufferedInputRouterTest, ClientOnSendEventHonored) {
- client_->set_allow_send_event(false);
-
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- EXPECT_EQ(0U, QueuedEventCount());
-
- SimulateWheelEvent(5, 0, 0, false);
- EXPECT_EQ(0U, QueuedEventCount());
-
- SimulateMouseMove(5, 0, 0);
- EXPECT_EQ(0U, QueuedEventCount());
-
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- WebGestureEvent::Touchpad);
- EXPECT_EQ(0U, QueuedEventCount());
-
- SimulateTouchEvent(1, 1);
- EXPECT_EQ(0U, QueuedEventCount());
-}
-
-TEST_F(BufferedInputRouterTest, FlightCountIncrementedOnDeliver) {
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- EXPECT_EQ(0, client_->in_flight_event_count());
-
- input_router_->Flush();
- EXPECT_EQ(1, client_->in_flight_event_count());
-}
-
-TEST_F(BufferedInputRouterTest, FlightCountDecrementedOnAck) {
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- EXPECT_EQ(0, client_->in_flight_event_count());
-
- input_router_->Flush();
- EXPECT_EQ(1, client_->in_flight_event_count());
-
- // The in-flight count should continue until the flush has finished.
- ASSERT_TRUE(FinishFlush(INPUT_EVENT_COULD_NOT_DELIVER));
- EXPECT_EQ(1, client_->in_flight_event_count());
-
- ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_CONSUMED));
- EXPECT_EQ(0, client_->in_flight_event_count());
-}
-
-TEST_F(BufferedInputRouterTest, FilteredEventsNeverQueued) {
- // Event should not be queued, but should be ack'ed.
- client_->set_filter_state(INPUT_EVENT_ACK_STATE_CONSUMED);
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- SCOPED_EXPECT(ack_handler_->ExpectAckCalled(1), "AckCalled");
- EXPECT_EQ(0U, QueuedEventCount());
- ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
-
- // Event should not be queued, but should be ack'ed.
- client_->set_filter_state(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- SCOPED_EXPECT(ack_handler_->ExpectAckCalled(1), "AckCalled");
- EXPECT_EQ(0U, QueuedEventCount());
- ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
-
- // |INPUT_EVENT_DISPOSITION_UNKNOWN| should drop the event without ack'ing.
- client_->set_filter_state(INPUT_EVENT_ACK_STATE_UNKNOWN);
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- SCOPED_EXPECT(ack_handler_->ExpectAckCalled(0), "AckNotCalled");
- EXPECT_EQ(0U, QueuedEventCount());
- ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
-
- // Event should be queued.
- client_->set_filter_state(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- SCOPED_EXPECT(ack_handler_->ExpectAckCalled(0), "AckNotCalled");
- EXPECT_EQ(1U, QueuedEventCount());
-}
-
-TEST_F(BufferedInputRouterTest, FollowupEventsInjected) {
- // Enable a followup gesture event.
- WebGestureEvent followup_event;
- followup_event.type = WebInputEvent::GestureScrollBegin;
- followup_event.data.scrollUpdate.deltaX = 10;
- ack_handler_->set_followup_touch_event(make_scoped_ptr(
- new GestureEventWithLatencyInfo(followup_event, ui::LatencyInfo())));
-
- // Create an initial packet of { Touch, Key } and start flushing.
- SimulateTouchEvent(1, 1);
- EXPECT_EQ(1U, QueuedEventCount());
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- EXPECT_EQ(2U, QueuedEventCount());
- input_router_->Flush();
-
- // Followup only triggered when event handled.
- ASSERT_TRUE(FinishFlush(INPUT_EVENT_COULD_NOT_DELIVER));
- SCOPED_EXPECT(client_->ExpectDidFlushCalled(false), "DidFlushNotCalled");
- EXPECT_EQ(2U, QueuedEventCount());
-
- // Ack the touch event.
- InputEventDispositions dispositions;
- dispositions.push_back(INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED);
- dispositions.push_back(INPUT_EVENT_COULD_NOT_DELIVER);
- ASSERT_TRUE(FinishFlush(dispositions));
-
- // Ack'ing the touch event should have inserted the followup gesture event;
- // the flush is not complete until the inserted event is ack'ed.
- SCOPED_EXPECT(client_->ExpectDidFlushCalled(false), "DidFlushNotCalled");
- SCOPED_EXPECT(client_->ExpectSendCalled(true), "SendGestureCalled");
- EXPECT_EQ(followup_event.type, client_->sent_gesture_event().event.type);
- EXPECT_EQ(2U, QueuedEventCount());
-
- // Our packet is now { Gesture, Key }.
- InputMsg_HandleEventPacket::Param param;
- ASSERT_EQ(1U, process_->sink().message_count());
- ASSERT_TRUE(InputMsg_HandleEventPacket::Read(process_->sink().GetMessageAt(0),
- &param));
- EventPacket& followup_packet = param.a;
- ASSERT_EQ(2U, followup_packet.size());
- ASSERT_EQ(InputEvent::Payload::WEB_INPUT_EVENT,
- followup_packet.events()[0]->payload()->GetType());
- ASSERT_EQ(InputEvent::Payload::WEB_INPUT_EVENT,
- followup_packet.events()[1]->payload()->GetType());
- const WebInputEventPayload* payload0 =
- WebInputEventPayload::Cast(followup_packet.events()[0]->payload());
- const WebInputEventPayload* payload1 =
- WebInputEventPayload::Cast(followup_packet.events()[1]->payload());
- EXPECT_EQ(followup_event.type, payload0->web_event()->type);
- EXPECT_EQ(WebInputEvent::RawKeyDown, payload1->web_event()->type);
-
- // Complete the flush; the gesture should have been ack'ed.
- ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_CONSUMED));
- SCOPED_EXPECT(client_->ExpectDidFlushCalled(true), "DidFlushCalled");
- EXPECT_EQ(followup_event.type, ack_handler_->acked_gesture_event().type);
- EXPECT_EQ(0U, QueuedEventCount());
-}
-
-TEST_F(BufferedInputRouterTest, FlushRequestedOnQueue) {
- // The first queued event should trigger a flush request.
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- EXPECT_EQ(1U, QueuedEventCount());
- SCOPED_EXPECT(client_->ExpectNeedsFlushCalled(true), "SetNeedsFlushCalled");
-
- // Subsequently queued events will not trigger another flush request.
- SimulateWheelEvent(5, 0, 0, false);
- EXPECT_EQ(2U, QueuedEventCount());
- SCOPED_EXPECT(client_->ExpectNeedsFlushCalled(false), "SetNeedsFlushCalled");
-}
-
-TEST_F(BufferedInputRouterTest, GetLastKeyboardEvent) {
- EXPECT_EQ(NULL, input_router_->GetLastKeyboardEvent());
-
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- EXPECT_EQ(WebInputEvent::RawKeyDown,
- input_router_->GetLastKeyboardEvent()->type);
-
- // Queueing another key event does not effect the "last" event.
- SimulateKeyboardEvent(WebInputEvent::KeyUp);
- EXPECT_EQ(WebInputEvent::RawKeyDown,
- input_router_->GetLastKeyboardEvent()->type);
-
- input_router_->Flush();
-
- // Ack'ing the first event should make the second event the "last" event.
- InputEventDispositions dispositions;
- dispositions.push_back(INPUT_EVENT_IMPL_THREAD_CONSUMED);
- dispositions.push_back(INPUT_EVENT_COULD_NOT_DELIVER);
- ASSERT_TRUE(FinishFlush(dispositions));
- EXPECT_EQ(WebInputEvent::KeyUp, input_router_->GetLastKeyboardEvent()->type);
-
- // A key event queued during a flush becomes "last" upon flush completion.
- SimulateKeyboardEvent(WebInputEvent::Char);
- ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_CONSUMED));
- EXPECT_EQ(WebInputEvent::Char, input_router_->GetLastKeyboardEvent()->type);
-
- // An empty queue should produce a null "last" event.
- input_router_->Flush();
- ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_CONSUMED));
- EXPECT_EQ(NULL, input_router_->GetLastKeyboardEvent());
-}
-
-TEST_F(BufferedInputRouterTest, UnexpectedAck) {
- ASSERT_FALSE(ack_handler_->unexpected_event_ack_called());
- input_router_->OnMessageReceived(
- InputHostMsg_HandleEventPacket_ACK(0, 0, InputEventDispositions()));
- EXPECT_TRUE(ack_handler_->unexpected_event_ack_called());
-}
-
-TEST_F(BufferedInputRouterTest, BadAck) {
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- input_router_->Flush();
-
- ASSERT_FALSE(ack_handler_->unexpected_event_ack_called());
- EventPacket packet;
- input_router_->OnMessageReceived(
- InputHostMsg_HandleEventPacket_ACK(0, 0, InputEventDispositions()));
- EXPECT_TRUE(ack_handler_->unexpected_event_ack_called());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_filter.cc b/chromium/content/browser/renderer_host/input/gesture_event_filter.cc
index c2ff8875c85..2761d9687d0 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_filter.cc
+++ b/chromium/content/browser/renderer_host/input/gesture_event_filter.cc
@@ -11,65 +11,39 @@
#include "content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h"
#include "content/public/common/content_switches.h"
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
namespace content {
namespace {
-// Default maximum time between the GestureRecognizer generating a
-// GestureTapDown and when it is forwarded to the renderer.
-#if !defined(OS_ANDROID)
-static const int kTapDownDeferralTimeMs = 150;
-#else
-// Android OS sends this gesture with a delay already.
-static const int kTapDownDeferralTimeMs = 0;
-#endif
-
// Default debouncing interval duration: if a scroll is in progress, non-scroll
// events during this interval are deferred to either its end or discarded on
// receipt of another GestureScrollUpdate.
static const int kDebouncingIntervalTimeMs = 30;
-// Sets |*value| to |switchKey| if it exists or sets it to |defaultValue|.
-static void GetParamHelper(int* value,
- int defaultValue,
- const char switchKey[]) {
- if (*value < 0) {
- *value = defaultValue;
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- std::string command_line_param =
- command_line->GetSwitchValueASCII(switchKey);
- if (!command_line_param.empty()) {
- int v;
- if (base::StringToInt(command_line_param, &v))
- *value = v;
- }
- DCHECK_GE(*value, 0);
- }
-}
-
-static int GetTapDownDeferralTimeMs() {
- static int tap_down_deferral_time_window = -1;
- GetParamHelper(&tap_down_deferral_time_window,
- kTapDownDeferralTimeMs,
- switches::kTapDownDeferralTimeMs);
- return tap_down_deferral_time_window;
-}
} // namespace
-GestureEventFilter::GestureEventFilter(InputRouter* input_router)
- : input_router_(input_router),
+GestureEventFilter::GestureEventFilter(
+ GestureEventFilterClient* client,
+ TouchpadTapSuppressionControllerClient* touchpad_client)
+ : client_(client),
fling_in_progress_(false),
scrolling_in_progress_(false),
ignore_next_ack_(false),
combined_scroll_pinch_(gfx::Transform()),
touchpad_tap_suppression_controller_(
- new TouchpadTapSuppressionController(input_router)),
+ new TouchpadTapSuppressionController(touchpad_client)),
touchscreen_tap_suppression_controller_(
new TouchscreenTapSuppressionController(this)),
- maximum_tap_gap_time_ms_(GetTapDownDeferralTimeMs()),
- debounce_interval_time_ms_(kDebouncingIntervalTimeMs) {
+ debounce_interval_time_ms_(kDebouncingIntervalTimeMs),
+ debounce_enabled_(true) {
+ DCHECK(client);
+ DCHECK(touchpad_tap_suppression_controller_);
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGestureDebounce)) {
+ debounce_enabled_ = false;
+ }
}
GestureEventFilter::~GestureEventFilter() { }
@@ -92,7 +66,7 @@ bool GestureEventFilter::ShouldDiscardFlingCancelEvent(
bool GestureEventFilter::ShouldForwardForBounceReduction(
const GestureEventWithLatencyInfo& gesture_event) {
- if (debounce_interval_time_ms_ == 0)
+ if (!debounce_enabled_)
return true;
switch (gesture_event.event.type) {
case WebInputEvent::GestureScrollUpdate:
@@ -133,7 +107,6 @@ bool GestureEventFilter::ShouldForward(
ShouldForwardForBounceReduction(gesture_event) &&
ShouldForwardForGFCFiltering(gesture_event) &&
ShouldForwardForTapSuppression(gesture_event) &&
- ShouldForwardForTapDeferral(gesture_event) &&
ShouldForwardForCoalescing(gesture_event);
}
@@ -163,13 +136,15 @@ bool GestureEventFilter::ShouldForwardForTapSuppression(
case WebInputEvent::GestureTapDown:
return !touchscreen_tap_suppression_controller_->
ShouldDeferGestureTapDown(gesture_event);
- case WebInputEvent::GestureTapCancel:
+ case WebInputEvent::GestureShowPress:
return !touchscreen_tap_suppression_controller_->
- ShouldSuppressGestureTapCancel();
+ ShouldDeferGestureShowPress(gesture_event);
+ case WebInputEvent::GestureTapCancel:
case WebInputEvent::GestureTap:
case WebInputEvent::GestureTapUnconfirmed:
+ case WebInputEvent::GestureDoubleTap:
return !touchscreen_tap_suppression_controller_->
- ShouldSuppressGestureTap();
+ ShouldSuppressGestureTapEnd();
default:
return true;
}
@@ -177,51 +152,6 @@ bool GestureEventFilter::ShouldForwardForTapSuppression(
return false;
}
-bool GestureEventFilter::ShouldForwardForTapDeferral(
- const GestureEventWithLatencyInfo& gesture_event) {
- switch (gesture_event.event.type) {
- case WebInputEvent::GestureTapDown:
- // GestureTapDown is always paired with either a Tap, or TapCancel, so it
- // should be impossible to have more than one outstanding at a time.
- DCHECK_EQ(deferred_tap_down_event_.event.type, WebInputEvent::Undefined);
- deferred_tap_down_event_ = gesture_event;
- send_gtd_timer_.Start(
- FROM_HERE,
- base::TimeDelta::FromMilliseconds(maximum_tap_gap_time_ms_),
- this,
- &GestureEventFilter::SendGestureTapDownNow);
- return false;
- case WebInputEvent::GestureTapCancel:
- if (deferred_tap_down_event_.event.type == WebInputEvent::Undefined) {
- // The TapDown has already been put in the queue, must send the
- // corresponding TapCancel as well.
- return true;
- }
- // Cancelling a deferred TapDown, just drop them on the floor.
- send_gtd_timer_.Stop();
- deferred_tap_down_event_.event.type = WebInputEvent::Undefined;
- return false;
- case WebInputEvent::GestureTap:
- send_gtd_timer_.Stop();
- if (deferred_tap_down_event_.event.type != WebInputEvent::Undefined) {
- ForwardGestureEventSkipDeferral(deferred_tap_down_event_);
- deferred_tap_down_event_.event.type = WebInputEvent::Undefined;
- }
- return true;
- case WebInputEvent::GestureFlingStart:
- case WebInputEvent::GestureScrollBegin:
- case WebInputEvent::GesturePinchBegin:
- send_gtd_timer_.Stop();
- deferred_tap_down_event_.event.type = WebInputEvent::Undefined;
- return true;
- default:
- return true;
- }
-
- NOTREACHED();
- return true;
-}
-
bool GestureEventFilter::ShouldForwardForCoalescing(
const GestureEventWithLatencyInfo& gesture_event) {
switch (gesture_event.event.type) {
@@ -238,45 +168,63 @@ bool GestureEventFilter::ShouldForwardForCoalescing(
default:
break;
}
- coalesced_gesture_events_.push_back(gesture_event);
+ EnqueueEvent(gesture_event);
return ShouldHandleEventNow();
}
-void GestureEventFilter::ProcessGestureAck(bool processed, int type) {
+void GestureEventFilter::ProcessGestureAck(InputEventAckState ack_result,
+ WebInputEvent::Type type,
+ const ui::LatencyInfo& latency) {
if (coalesced_gesture_events_.empty()) {
DLOG(ERROR) << "Received unexpected ACK for event type " << type;
return;
}
- DCHECK_EQ(coalesced_gesture_events_.front().event.type, type);
+
+ // Ack'ing an event may enqueue additional gesture events. By ack'ing the
+ // event before the forwarding of queued events below, such additional events
+ // can be coalesced with existing queued events prior to dispatch.
+ GestureEventWithLatencyInfo event_with_latency =
+ coalesced_gesture_events_.front();
+ DCHECK_EQ(event_with_latency.event.type, type);
+ event_with_latency.latency.AddNewLatencyFrom(latency);
+ client_->OnGestureEventAck(event_with_latency, ack_result);
+
+ const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
if (type == WebInputEvent::GestureFlingCancel) {
- if (coalesced_gesture_events_.front().event.sourceDevice ==
- WebGestureEvent::Touchscreen)
+ if (event_with_latency.event.sourceDevice == WebGestureEvent::Touchscreen)
touchscreen_tap_suppression_controller_->GestureFlingCancelAck(processed);
else
touchpad_tap_suppression_controller_->GestureFlingCancelAck(processed);
}
coalesced_gesture_events_.pop_front();
+
if (ignore_next_ack_) {
ignore_next_ack_ = false;
- } else if (!coalesced_gesture_events_.empty()) {
- const GestureEventWithLatencyInfo& next_gesture_event =
- coalesced_gesture_events_.front();
- input_router_->SendGestureEventImmediately(next_gesture_event);
- // TODO(yusufo): Introduce GesturePanScroll so that these can be combined
- // into one gesture and kept inside the queue that way.
- if (coalesced_gesture_events_.size() > 1) {
- const GestureEventWithLatencyInfo& second_gesture_event =
- coalesced_gesture_events_[1];
- if (next_gesture_event.event.type ==
- WebInputEvent::GestureScrollUpdate &&
- second_gesture_event.event.type ==
- WebInputEvent::GesturePinchUpdate) {
- input_router_->SendGestureEventImmediately(second_gesture_event);
- ignore_next_ack_ = true;
- combined_scroll_pinch_ = gfx::Transform();
- }
- }
+ return;
}
+
+ if (coalesced_gesture_events_.empty())
+ return;
+
+ const GestureEventWithLatencyInfo& first_gesture_event =
+ coalesced_gesture_events_.front();
+
+ // TODO(yusufo): Introduce GesturePanScroll so that these can be combined
+ // into one gesture and kept inside the queue that way.
+ // Check for the coupled GesturePinchUpdate before sending either event,
+ // handling the case where the first GestureScrollUpdate ack is synchronous.
+ GestureEventWithLatencyInfo second_gesture_event;
+ if (first_gesture_event.event.type == WebInputEvent::GestureScrollUpdate &&
+ coalesced_gesture_events_.size() > 1 &&
+ coalesced_gesture_events_[1].event.type ==
+ WebInputEvent::GesturePinchUpdate) {
+ second_gesture_event = coalesced_gesture_events_[1];
+ ignore_next_ack_ = true;
+ }
+
+ client_->SendGestureEventImmediately(first_gesture_event);
+ if (second_gesture_event.event.type != WebInputEvent::Undefined)
+ client_->SendGestureEventImmediately(second_gesture_event);
}
TouchpadTapSuppressionController*
@@ -288,15 +236,6 @@ bool GestureEventFilter::HasQueuedGestureEvents() const {
return !coalesced_gesture_events_.empty();
}
-const WebKit::WebGestureEvent&
-GestureEventFilter::GetGestureEventAwaitingAck() const {
- DCHECK(!coalesced_gesture_events_.empty());
- if (!ignore_next_ack_)
- return coalesced_gesture_events_.front().event;
- else
- return coalesced_gesture_events_.at(1).event;
-}
-
void GestureEventFilter::FlingHasBeenHalted() {
fling_in_progress_ = false;
}
@@ -305,71 +244,54 @@ bool GestureEventFilter::ShouldHandleEventNow() const {
return coalesced_gesture_events_.size() == 1;
}
-void GestureEventFilter::ForwardGestureEventForDeferral(
- const GestureEventWithLatencyInfo& gesture_event) {
- if (ShouldForwardForTapDeferral(gesture_event))
- ForwardGestureEventSkipDeferral(gesture_event);
-}
-
-void GestureEventFilter::ForwardGestureEventSkipDeferral(
+void GestureEventFilter::ForwardGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) {
if (ShouldForwardForCoalescing(gesture_event))
- input_router_->SendGestureEventImmediately(gesture_event);
-}
-
-void GestureEventFilter::SendGestureTapDownNow() {
- // We must not have already sent the deferred TapDown (if we did, we would
- // have stopped the timer, which prevents this task from running - even if
- // it's time had already elapsed).
- DCHECK_EQ(deferred_tap_down_event_.event.type, WebInputEvent::GestureTapDown);
- ForwardGestureEventSkipDeferral(deferred_tap_down_event_);
- deferred_tap_down_event_.event.type = WebInputEvent::Undefined;
+ client_->SendGestureEventImmediately(gesture_event);
}
void GestureEventFilter::SendScrollEndingEventsNow() {
scrolling_in_progress_ = false;
- for (GestureEventQueue::const_iterator it =
- debouncing_deferral_queue_.begin();
- it != debouncing_deferral_queue_.end(); it++) {
+ GestureEventQueue debouncing_deferral_queue;
+ debouncing_deferral_queue.swap(debouncing_deferral_queue_);
+ for (GestureEventQueue::const_iterator it = debouncing_deferral_queue.begin();
+ it != debouncing_deferral_queue.end(); it++) {
if (ShouldForwardForGFCFiltering(*it) &&
ShouldForwardForTapSuppression(*it) &&
- ShouldForwardForTapDeferral(*it) &&
ShouldForwardForCoalescing(*it)) {
- input_router_->SendGestureEventImmediately(*it);
+ client_->SendGestureEventImmediately(*it);
}
}
- debouncing_deferral_queue_.clear();
}
void GestureEventFilter::MergeOrInsertScrollAndPinchEvent(
const GestureEventWithLatencyInfo& gesture_event) {
if (coalesced_gesture_events_.size() <= 1) {
- coalesced_gesture_events_.push_back(gesture_event);
+ EnqueueEvent(gesture_event);
return;
}
GestureEventWithLatencyInfo* last_event = &coalesced_gesture_events_.back();
- if (gesture_event.event.type == WebInputEvent::GestureScrollUpdate &&
- last_event->event.type == WebInputEvent::GestureScrollUpdate &&
- last_event->event.modifiers == gesture_event.event.modifiers) {
- last_event->event.data.scrollUpdate.deltaX +=
- gesture_event.event.data.scrollUpdate.deltaX;
- last_event->event.data.scrollUpdate.deltaY +=
- gesture_event.event.data.scrollUpdate.deltaY;
- last_event->latency.MergeWith(gesture_event.latency);
+ if (last_event->CanCoalesceWith(gesture_event)) {
+ last_event->CoalesceWith(gesture_event);
+ if (!combined_scroll_pinch_.IsIdentity()) {
+ combined_scroll_pinch_.ConcatTransform(
+ GetTransformForEvent(gesture_event));
+ }
return;
}
if (coalesced_gesture_events_.size() == 2 ||
(coalesced_gesture_events_.size() == 3 && ignore_next_ack_) ||
!ShouldTryMerging(gesture_event, *last_event)) {
- coalesced_gesture_events_.push_back(gesture_event);
+ EnqueueEvent(gesture_event);
return;
}
GestureEventWithLatencyInfo scroll_event;
GestureEventWithLatencyInfo pinch_event;
scroll_event.event.modifiers |= gesture_event.event.modifiers;
scroll_event.event.timeStampSeconds = gesture_event.event.timeStampSeconds;
- scroll_event.latency = gesture_event.latency;
- scroll_event.latency.MergeWith(last_event->latency);
+ // Keep the oldest LatencyInfo.
+ DCHECK_LE(last_event->latency.trace_id, gesture_event.latency.trace_id);
+ scroll_event.latency = last_event->latency;
pinch_event = scroll_event;
scroll_event.event.type = WebInputEvent::GestureScrollUpdate;
pinch_event.event.type = WebInputEvent::GesturePinchUpdate;
@@ -384,8 +306,11 @@ void GestureEventFilter::MergeOrInsertScrollAndPinchEvent(
GestureEventWithLatencyInfo* second_last_event = &coalesced_gesture_events_
[coalesced_gesture_events_.size() - 2];
if (ShouldTryMerging(gesture_event, *second_last_event)) {
- scroll_event.latency.MergeWith(second_last_event->latency);
- pinch_event.latency.MergeWith(second_last_event->latency);
+ // Keep the oldest LatencyInfo.
+ DCHECK_LE(second_last_event->latency.trace_id,
+ scroll_event.latency.trace_id);
+ scroll_event.latency = second_last_event->latency;
+ pinch_event.latency = second_last_event->latency;
coalesced_gesture_events_.pop_back();
} else {
DCHECK(combined_scroll_pinch_ == GetTransformForEvent(gesture_event));
@@ -393,13 +318,18 @@ void GestureEventFilter::MergeOrInsertScrollAndPinchEvent(
PreconcatTransform(GetTransformForEvent(*last_event));
}
coalesced_gesture_events_.pop_back();
- float combined_scale = combined_scroll_pinch_.matrix().getDouble(0, 0);
+ float combined_scale =
+ SkMScalarToFloat(combined_scroll_pinch_.matrix().get(0, 0));
+ float combined_scroll_pinch_x =
+ SkMScalarToFloat(combined_scroll_pinch_.matrix().get(0, 3));
+ float combined_scroll_pinch_y =
+ SkMScalarToFloat(combined_scroll_pinch_.matrix().get(1, 3));
scroll_event.event.data.scrollUpdate.deltaX =
- (combined_scroll_pinch_.matrix().getDouble(0, 3) + pinch_event.event.x)
- / combined_scale - pinch_event.event.x;
+ (combined_scroll_pinch_x + pinch_event.event.x) / combined_scale -
+ pinch_event.event.x;
scroll_event.event.data.scrollUpdate.deltaY =
- (combined_scroll_pinch_.matrix().getDouble(1, 3) + pinch_event.event.y)
- / combined_scale - pinch_event.event.y;
+ (combined_scroll_pinch_y + pinch_event.event.y) / combined_scale -
+ pinch_event.event.y;
coalesced_gesture_events_.push_back(scroll_event);
pinch_event.event.data.pinchUpdate.scale = combined_scale;
coalesced_gesture_events_.push_back(pinch_event);
@@ -431,4 +361,13 @@ gfx::Transform GestureEventFilter::GetTransformForEvent(
}
return gesture_transform;
}
+
+void GestureEventFilter::EnqueueEvent(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ coalesced_gesture_events_.push_back(gesture_event);
+ // Scroll and pinch events contributing to |combined_scroll_pinch_| will be
+ // manually added to the queue in |MergeOrInsertScrollAndPinchEvent()|.
+ combined_scroll_pinch_ = gfx::Transform();
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_filter.h b/chromium/content/browser/renderer_host/input/gesture_event_filter.h
index b0c378222ea..d0517008bfc 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_filter.h
+++ b/chromium/content/browser/renderer_host/input/gesture_event_filter.h
@@ -10,21 +10,39 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
+#include "content/common/content_export.h"
#include "content/port/browser/event_with_latency_info.h"
+#include "content/port/common/input_event_ack_state.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/gfx/transform.h"
namespace content {
+class GestureEventFilterTest;
class InputRouter;
class MockRenderWidgetHost;
class TouchpadTapSuppressionController;
+class TouchpadTapSuppressionControllerClient;
class TouchscreenTapSuppressionController;
+// Interface with which the GestureEventFilter can forward gesture events, and
+// dispatch gesture event responses.
+class CONTENT_EXPORT GestureEventFilterClient {
+ public:
+ virtual ~GestureEventFilterClient() {}
+
+ virtual void SendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& event) = 0;
+
+ virtual void OnGestureEventAck(
+ const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) = 0;
+};
+
// Maintains WebGestureEvents in a queue before forwarding them to the renderer
// to apply a sequence of filters on them:
// 1. Zero-velocity fling-starts from touchpad are filtered.
// 2. The sequence is filtered for bounces. A bounce is when the finger lifts
-// from the screen briefly during an in-progress scroll. If this happens,
+// from the screen briefly during an in-progress scroll. Ifco this happens,
// non-GestureScrollUpdate events are queued until the de-bounce interval
// passes or another GestureScrollUpdate event occurs.
// 3. Unnecessary GestureFlingCancel events are filtered. These are
@@ -41,10 +59,11 @@ class TouchscreenTapSuppressionController;
// sent together.
// TODO(rjkroege): Possibly refactor into a filter chain:
// http://crbug.com/148443.
-class GestureEventFilter {
+class CONTENT_EXPORT GestureEventFilter {
public:
- // The |input_router| must outlive the GestureEventFilter.
- explicit GestureEventFilter(InputRouter* input_router);
+ // Both |client| and |touchpad_client| must outlive the GestureEventFilter.
+ GestureEventFilter(GestureEventFilterClient* client,
+ TouchpadTapSuppressionControllerClient* touchpad_client);
~GestureEventFilter();
// Returns |true| if the caller should immediately forward the provided
@@ -52,9 +71,11 @@ class GestureEventFilter {
bool ShouldForward(const GestureEventWithLatencyInfo&);
// Indicates that the caller has received an acknowledgement from the renderer
- // with state |processed| and event |type|. May send events if the queue is
+ // with state |ack_result| and event |type|. May send events if the queue is
// not empty.
- void ProcessGestureAck(bool processed, int type);
+ void ProcessGestureAck(InputEventAckState ack_result,
+ blink::WebInputEvent::Type type,
+ const ui::LatencyInfo& latency);
// Sets the state of the |fling_in_progress_| field to indicate that a fling
// is definitely not in progress.
@@ -66,29 +87,24 @@ class GestureEventFilter {
// Returns whether there are any gesture event in the queue.
bool HasQueuedGestureEvents() const;
- // Returns the last gesture event that was sent to the renderer.
- const WebKit::WebGestureEvent& GetGestureEventAwaitingAck() const;
+ void ForwardGestureEvent(const GestureEventWithLatencyInfo& gesture_event);
- // Tries forwarding the event to the tap deferral sub-filter.
- void ForwardGestureEventForDeferral(
- const GestureEventWithLatencyInfo& gesture_event);
+ void set_debounce_enabled_for_testing(bool enabled) {
+ debounce_enabled_ = enabled;
+ }
- // Tries forwarding the event, skipping the tap deferral sub-filter.
- void ForwardGestureEventSkipDeferral(
- const GestureEventWithLatencyInfo& gesture_event);
+ void set_debounce_interval_time_ms_for_testing(int interval_time_ms) {
+ debounce_interval_time_ms_ = interval_time_ms;
+ }
private:
+ friend class GestureEventFilterTest;
friend class MockRenderWidgetHost;
- friend class ImmediateInputRouterTest;
// TODO(mohsen): There are a bunch of ShouldForward.../ShouldDiscard...
// methods that are getting confusing. This should be somehow fixed. Maybe
// while refactoring GEF: http://crbug.com/148443.
- // Invoked on the expiration of the timer to release a deferred
- // GestureTapDown to the renderer.
- void SendGestureTapDownNow();
-
// Inovked on the expiration of the debounce interval to release
// deferred events.
void SendScrollEndingEventsNow();
@@ -123,10 +139,6 @@ class GestureEventFilter {
bool ShouldForwardForTapSuppression(
const GestureEventWithLatencyInfo& gesture_event);
- // Sub-filter for deferring GestureTapDowns.
- bool ShouldForwardForTapDeferral(
- const GestureEventWithLatencyInfo& gesture_event);
-
// Puts the events in a queue to forward them one by one; i.e., forward them
// whenever ACK for previous event is received. This queue also tries to
// coalesce events as much as possible.
@@ -146,8 +158,12 @@ class GestureEventFilter {
gfx::Transform GetTransformForEvent(
const GestureEventWithLatencyInfo& gesture_event) const;
+ // Adds |gesture_event| to the |coalesced_gesture_events_|, resetting the
+ // accumulation of |combined_scroll_pinch_|.
+ void EnqueueEvent(const GestureEventWithLatencyInfo& gesture_event);
+
// The receiver of all forwarded gesture events.
- InputRouter* input_router_;
+ GestureEventFilterClient* client_;
// True if a GestureFlingStart is in progress on the renderer or
// queued without a subsequent queued GestureFlingCancel event.
@@ -164,9 +180,6 @@ class GestureEventFilter {
// scroll-pinch sequence at the end of the queue.
gfx::Transform combined_scroll_pinch_;
- // Timer to release a previously deferred GestureTapDown event.
- base::OneShotTimer<GestureEventFilter> send_gtd_timer_;
-
// An object tracking the state of touchpad on the delivery of mouse events to
// the renderer to filter mouse immediately after a touchpad fling canceling
// tap.
@@ -183,25 +196,28 @@ class GestureEventFilter {
typedef std::deque<GestureEventWithLatencyInfo> GestureEventQueue;
- // Queue of coalesced gesture events not yet sent to the renderer.
+ // Queue of coalesced gesture events not yet sent to the renderer. If
+ // |ignore_next_ack_| is false, then the event at the front of the queue has
+ // been sent and is awaiting an ACK, and all other events have yet to be sent.
+ // If |ignore_next_ack_| is true, then the two events at the front of the
+ // queue have been sent, and the second is awaiting an ACK. All other events
+ // have yet to be sent.
GestureEventQueue coalesced_gesture_events_;
- // Tap gesture event currently subject to deferral.
- GestureEventWithLatencyInfo deferred_tap_down_event_;
-
- // Timer to release a previously deferred GestureTapDown event.
+ // Timer to release a previously deferred gesture event.
base::OneShotTimer<GestureEventFilter> debounce_deferring_timer_;
// Queue of events that have been deferred for debounce.
GestureEventQueue debouncing_deferral_queue_;
- // Time window in which to defer a GestureTapDown.
- int maximum_tap_gap_time_ms_;
-
// Time window in which to debounce scroll/fling ends.
// TODO(rjkroege): Make this dynamically configurable.
int debounce_interval_time_ms_;
+ // Whether scroll-ending events should be deferred when a scroll is active.
+ // Defaults to true.
+ bool debounce_enabled_;
+
DISALLOW_COPY_AND_ASSIGN(GestureEventFilter);
};
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_filter_unittest.cc b/chromium/content/browser/renderer_host/input/gesture_event_filter_unittest.cc
new file mode 100644
index 00000000000..421fd701310
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/gesture_event_filter_unittest.cc
@@ -0,0 +1,912 @@
+// 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 <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/time/time.h"
+#include "content/browser/renderer_host/input/gesture_event_filter.h"
+#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/port/common/input_event_ack_state.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+using base::TimeDelta;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+
+namespace content {
+
+class GestureEventFilterTest : public testing::Test,
+ public GestureEventFilterClient,
+ public TouchpadTapSuppressionControllerClient {
+ public:
+ GestureEventFilterTest()
+ : acked_gesture_event_count_(0),
+ sent_gesture_event_count_(0) {}
+
+ virtual ~GestureEventFilterTest() {}
+
+ // testing::Test
+ virtual void SetUp() OVERRIDE {
+ filter_.reset(new GestureEventFilter(this, this));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ // Process all pending tasks to avoid leaks.
+ RunUntilIdle();
+ filter_.reset();
+ }
+
+ // GestureEventFilterClient
+ virtual void SendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& event) OVERRIDE {
+ ++sent_gesture_event_count_;
+ if (sync_ack_result_) {
+ scoped_ptr<InputEventAckState> ack_result = sync_ack_result_.Pass();
+ SendInputEventACK(event.event.type, *ack_result);
+ }
+ }
+
+ virtual void OnGestureEventAck(
+ const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) OVERRIDE {
+ ++acked_gesture_event_count_;
+ last_acked_event_ = event.event;
+ if (sync_followup_event_)
+ SimulateGestureEvent(*sync_followup_event_.Pass());
+ }
+
+ // TouchpadTapSuppressionControllerClient
+ virtual void SendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& event) OVERRIDE {
+ }
+
+ protected:
+
+ // Returns the result of |GestureEventFilter::ShouldForward()|.
+ bool SimulateGestureEvent(const WebGestureEvent& gesture) {
+ GestureEventWithLatencyInfo gesture_with_latency(gesture,
+ ui::LatencyInfo());
+ if (filter()->ShouldForward(gesture_with_latency)) {
+ SendGestureEventImmediately(gesture_with_latency);
+ return true;
+ }
+ return false;
+ }
+
+ void SimulateGestureEvent(WebInputEvent::Type type,
+ WebGestureEvent::SourceDevice sourceDevice) {
+ SimulateGestureEvent(
+ SyntheticWebGestureEventBuilder::Build(type, sourceDevice));
+ }
+
+ void SimulateGestureScrollUpdateEvent(float dX, float dY, int modifiers) {
+ SimulateGestureEvent(
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(dX, dY, modifiers));
+ }
+
+ void SimulateGesturePinchUpdateEvent(float scale,
+ float anchorX,
+ float anchorY,
+ int modifiers) {
+ SimulateGestureEvent(
+ SyntheticWebGestureEventBuilder::BuildPinchUpdate(scale,
+ anchorX,
+ anchorY,
+ modifiers));
+ }
+
+ void SimulateGestureFlingStartEvent(
+ float velocityX,
+ float velocityY,
+ WebGestureEvent::SourceDevice sourceDevice) {
+ SimulateGestureEvent(
+ SyntheticWebGestureEventBuilder::BuildFling(velocityX,
+ velocityY,
+ sourceDevice));
+ }
+
+ void SendInputEventACK(WebInputEvent::Type type,
+ InputEventAckState ack) {
+ filter()->ProcessGestureAck(ack, type, ui::LatencyInfo());
+ }
+
+ void RunUntilIdle() {
+ base::MessageLoop::current()->RunUntilIdle();
+ }
+
+ size_t GetAndResetSentGestureEventCount() {
+ size_t count = sent_gesture_event_count_;
+ sent_gesture_event_count_ = 0;
+ return count;
+ }
+
+ size_t GetAndResetAckedGestureEventCount() {
+ size_t count = acked_gesture_event_count_;
+ acked_gesture_event_count_ = 0;
+ return count;
+ }
+
+ const WebGestureEvent& last_acked_event() const {
+ return last_acked_event_;
+ }
+
+ void DisableDebounce() {
+ filter()->set_debounce_enabled_for_testing(false);
+ }
+
+ void set_debounce_interval_time_ms(int ms) {
+ filter()->set_debounce_interval_time_ms_for_testing(ms);
+ }
+
+ void set_synchronous_ack(InputEventAckState ack_result) {
+ sync_ack_result_.reset(new InputEventAckState(ack_result));
+ }
+
+ void set_sync_followup_event(WebInputEvent::Type type,
+ WebGestureEvent::SourceDevice sourceDevice) {
+ sync_followup_event_.reset(new WebGestureEvent(
+ SyntheticWebGestureEventBuilder::Build(type, sourceDevice)));
+ }
+
+ unsigned GestureEventQueueSize() {
+ return filter()->coalesced_gesture_events_.size();
+ }
+
+ WebGestureEvent GestureEventSecondFromLastQueueEvent() {
+ return filter()->coalesced_gesture_events_.at(
+ GestureEventQueueSize() - 2).event;
+ }
+
+ WebGestureEvent GestureEventLastQueueEvent() {
+ return filter()->coalesced_gesture_events_.back().event;
+ }
+
+ unsigned GestureEventDebouncingQueueSize() {
+ return filter()->debouncing_deferral_queue_.size();
+ }
+
+ WebGestureEvent GestureEventQueueEventAt(int i) {
+ return filter()->coalesced_gesture_events_.at(i).event;
+ }
+
+ bool ScrollingInProgress() {
+ return filter()->scrolling_in_progress_;
+ }
+
+ bool FlingInProgress() {
+ return filter()->fling_in_progress_;
+ }
+
+ bool WillIgnoreNextACK() {
+ return filter()->ignore_next_ack_;
+ }
+
+ GestureEventFilter* filter() const {
+ return filter_.get();
+ }
+
+ private:
+ scoped_ptr<GestureEventFilter> filter_;
+ size_t acked_gesture_event_count_;
+ size_t sent_gesture_event_count_;
+ WebGestureEvent last_acked_event_;
+ scoped_ptr<InputEventAckState> sync_ack_result_;
+ scoped_ptr<WebGestureEvent> sync_followup_event_;
+ base::MessageLoopForUI message_loop_;
+};
+
+#if GTEST_HAS_PARAM_TEST
+// This is for tests that are to be run for all source devices.
+class GestureEventFilterWithSourceTest
+ : public GestureEventFilterTest,
+ public testing::WithParamInterface<WebGestureEvent::SourceDevice> {
+};
+#endif // GTEST_HAS_PARAM_TEST
+
+TEST_F(GestureEventFilterTest, CoalescesScrollGestureEvents) {
+ // Turn off debounce handling for test isolation.
+ DisableDebounce();
+
+ // Test coalescing of only GestureScrollUpdate events.
+ // Simulate gesture events.
+
+ // Sent.
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+
+ // Enqueued.
+ SimulateGestureScrollUpdateEvent(8, -5, 0);
+
+ // Make sure that the queue contains what we think it should.
+ WebGestureEvent merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(2U, GestureEventQueueSize());
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+
+ // Coalesced.
+ SimulateGestureScrollUpdateEvent(8, -6, 0);
+
+ // Check that coalescing updated the correct values.
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(0, merged_event.modifiers);
+ EXPECT_EQ(16, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-11, merged_event.data.scrollUpdate.deltaY);
+
+ // Enqueued.
+ SimulateGestureScrollUpdateEvent(8, -7, 1);
+
+ // Check that we didn't wrongly coalesce.
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Different.
+ SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
+ WebGestureEvent::Touchscreen);
+
+ // Check that only the first event was sent.
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+
+ // Check that the ACK sends the second message.
+ SendInputEventACK(WebInputEvent::GestureScrollBegin,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ RunUntilIdle();
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+
+ // Ack for queued coalesced event.
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ RunUntilIdle();
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+
+ // Ack for queued uncoalesced event.
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ RunUntilIdle();
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+
+ // After the final ack, the queue should be empty.
+ SendInputEventACK(WebInputEvent::GestureScrollEnd,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ RunUntilIdle();
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+}
+
+TEST_F(GestureEventFilterTest, CoalescesScrollAndPinchEvents) {
+ // Turn off debounce handling for test isolation.
+ DisableDebounce();
+
+ // Test coalescing of only GestureScrollUpdate events.
+ // Simulate gesture events.
+
+ // Sent.
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ WebGestureEvent::Touchscreen);
+
+ // Sent.
+ SimulateGestureEvent(WebInputEvent::GesturePinchBegin,
+ WebGestureEvent::Touchscreen);
+
+ // Enqueued.
+ SimulateGestureScrollUpdateEvent(8, -4, 1);
+
+ // Make sure that the queue contains what we think it should.
+ WebGestureEvent merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(3U, GestureEventQueueSize());
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+
+ // Coalesced without changing event order. Note anchor at (60, 60). Anchoring
+ // from a point that is not the origin should still give us the right scroll.
+ SimulateGesturePinchUpdateEvent(1.5, 60, 60, 1);
+ EXPECT_EQ(4U, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(1.5, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(8, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-4, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Enqueued.
+ SimulateGestureScrollUpdateEvent(6, -3, 1);
+
+ // Check whether coalesced correctly.
+ EXPECT_EQ(4U, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(1.5, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(12, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-6, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Enqueued.
+ SimulateGesturePinchUpdateEvent(2, 60, 60, 1);
+
+ // Check whether coalesced correctly.
+ EXPECT_EQ(4U, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(3, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(12, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-6, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Enqueued.
+ SimulateGesturePinchUpdateEvent(2, 60, 60, 1);
+
+ // Check whether coalesced correctly.
+ EXPECT_EQ(4U, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(6, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(12, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-6, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Check that only the first event was sent.
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+
+ // Check that the ACK sends the second message.
+ SendInputEventACK(WebInputEvent::GestureScrollBegin,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ RunUntilIdle();
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+
+ // Enqueued.
+ SimulateGestureScrollUpdateEvent(6, -6, 1);
+
+ // Check whether coalesced correctly.
+ EXPECT_EQ(3U, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(6, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(13, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-7, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // At this point ACKs shouldn't be getting ignored.
+ EXPECT_FALSE(WillIgnoreNextACK());
+
+ // Check that the ACK sends both scroll and pinch updates.
+ SendInputEventACK(WebInputEvent::GesturePinchBegin,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ RunUntilIdle();
+ EXPECT_EQ(2U, GetAndResetSentGestureEventCount());
+
+ // The next ACK should be getting ignored.
+ EXPECT_TRUE(WillIgnoreNextACK());
+
+ // Enqueued.
+ SimulateGestureScrollUpdateEvent(1, -1, 1);
+
+ // Check whether coalesced correctly.
+ EXPECT_EQ(3U, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(1, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-1, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(6, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Enqueued.
+ SimulateGestureScrollUpdateEvent(2, -2, 1);
+
+ // Coalescing scrolls should still work.
+ EXPECT_EQ(3U, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(3, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-3, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(6, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Enqueued.
+ SimulateGesturePinchUpdateEvent(0.5, 60, 60, 1);
+
+ // Check whether coalesced correctly.
+ EXPECT_EQ(4U, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(0.5, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(3, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-3, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Check that the ACK gets ignored.
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, last_acked_event().type);
+ RunUntilIdle();
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ // The flag should have been flipped back to false.
+ EXPECT_FALSE(WillIgnoreNextACK());
+
+ // Enqueued.
+ SimulateGestureScrollUpdateEvent(2, -2, 2);
+
+ // Shouldn't coalesce with different modifiers.
+ EXPECT_EQ(4U, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(2, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-2, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(2, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(0.5, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Check that the ACK sends the next scroll pinch pair.
+ SendInputEventACK(WebInputEvent::GesturePinchUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, last_acked_event().type);
+ RunUntilIdle();
+ EXPECT_EQ(2U, GetAndResetSentGestureEventCount());
+
+ // Check that the ACK sends the second message.
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, last_acked_event().type);
+ RunUntilIdle();
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+
+ // Check that the ACK sends the second event.
+ SendInputEventACK(WebInputEvent::GesturePinchUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, last_acked_event().type);
+ RunUntilIdle();
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+
+ // Check that the queue is empty after ACK and no events get sent.
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, last_acked_event().type);
+ RunUntilIdle();
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+}
+
+TEST_F(GestureEventFilterTest, CoalescesMultiplePinchEventSequences) {
+ // Turn off debounce handling for test isolation.
+ DisableDebounce();
+
+ // Simulate a pinch sequence.
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ WebGestureEvent::Touchscreen);
+ SimulateGestureEvent(WebInputEvent::GesturePinchBegin,
+ WebGestureEvent::Touchscreen);
+
+ SimulateGestureScrollUpdateEvent(8, -4, 1);
+ // Make sure that the queue contains what we think it should.
+ WebGestureEvent merged_event = GestureEventLastQueueEvent();
+ size_t expected_events_in_queue = 3;
+ EXPECT_EQ(expected_events_in_queue, GestureEventQueueSize());
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+
+ // Coalesced without changing event order. Note anchor at (60, 60). Anchoring
+ // from a point that is not the origin should still give us the right scroll.
+ SimulateGesturePinchUpdateEvent(1.5, 60, 60, 1);
+ EXPECT_EQ(++expected_events_in_queue, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(1.5, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(8, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-4, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Enqueued.
+ SimulateGestureScrollUpdateEvent(6, -3, 1);
+
+ // Check whether coalesced correctly.
+ EXPECT_EQ(expected_events_in_queue, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(1.5, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(12, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-6, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Now start another sequence before the previous sequence has been ack'ed.
+ SimulateGestureEvent(WebInputEvent::GesturePinchEnd,
+ WebGestureEvent::Touchscreen);
+ SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
+ WebGestureEvent::Touchscreen);
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ WebGestureEvent::Touchscreen);
+ SimulateGestureEvent(WebInputEvent::GesturePinchBegin,
+ WebGestureEvent::Touchscreen);
+
+ SimulateGestureScrollUpdateEvent(8, -4, 1);
+ // Make sure that the queue contains what we think it should.
+ expected_events_in_queue += 5;
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(expected_events_in_queue, GestureEventQueueSize());
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+
+ // Coalesced without changing event order. Note anchor at (60, 60). Anchoring
+ // from a point that is not the origin should still give us the right scroll.
+ SimulateGesturePinchUpdateEvent(1.5, 30, 30, 1);
+ EXPECT_EQ(++expected_events_in_queue, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(1.5, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(8, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-4, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+
+ // Enqueued.
+ SimulateGestureScrollUpdateEvent(6, -3, 1);
+
+ // Check whether coalesced correctly.
+ EXPECT_EQ(expected_events_in_queue, GestureEventQueueSize());
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
+ EXPECT_EQ(1.5, merged_event.data.pinchUpdate.scale);
+ EXPECT_EQ(1, merged_event.modifiers);
+ merged_event = GestureEventSecondFromLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+ EXPECT_EQ(12, merged_event.data.scrollUpdate.deltaX);
+ EXPECT_EQ(-6, merged_event.data.scrollUpdate.deltaY);
+ EXPECT_EQ(1, merged_event.modifiers);
+}
+
+// Tests a single event with an synchronous ack.
+TEST_F(GestureEventFilterTest, SimpleSyncAck) {
+ set_synchronous_ack(INPUT_EVENT_ACK_STATE_CONSUMED);
+ SimulateGestureEvent(WebInputEvent::GestureTapDown,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+}
+
+// Tests an event with an synchronous ack which enqueues an additional event.
+TEST_F(GestureEventFilterTest, SyncAckQueuesEvent) {
+ scoped_ptr<WebGestureEvent> queued_event;
+ set_synchronous_ack(INPUT_EVENT_ACK_STATE_CONSUMED);
+ set_sync_followup_event(WebInputEvent::GestureShowPress,
+ WebGestureEvent::Touchscreen);
+ // This event enqueues the show press event.
+ SimulateGestureEvent(WebInputEvent::GestureTapDown,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(2U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(1U, GestureEventQueueSize());
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+
+ SendInputEventACK(WebInputEvent::GestureShowPress,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+}
+
+// Tests an event with an async ack followed by an event with a sync ack.
+TEST_F(GestureEventFilterTest, AsyncThenSyncAck) {
+ // Turn off debounce handling for test isolation.
+ DisableDebounce();
+
+ SimulateGestureEvent(WebInputEvent::GestureTapDown,
+ WebGestureEvent::Touchscreen);
+
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(1U, GestureEventQueueSize());
+ EXPECT_EQ(0U, GetAndResetAckedGestureEventCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ WebGestureEvent::Touchscreen);
+ set_synchronous_ack(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+ EXPECT_EQ(0U, GetAndResetAckedGestureEventCount());
+
+ SendInputEventACK(WebInputEvent::GestureTapDown,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+ EXPECT_EQ(2U, GetAndResetAckedGestureEventCount());
+}
+
+TEST_F(GestureEventFilterTest, CoalescesScrollAndPinchEventWithSyncAck) {
+ // Turn off debounce handling for test isolation.
+ DisableDebounce();
+
+ // Simulate a pinch sequence.
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ SimulateGestureEvent(WebInputEvent::GesturePinchBegin,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+
+ SimulateGestureScrollUpdateEvent(8, -4, 1);
+ // Make sure that the queue contains what we think it should.
+ WebGestureEvent merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(3U, GestureEventQueueSize());
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
+
+ // Coalesced without changing event order. Note anchor at (60, 60). Anchoring
+ // from a point that is not the origin should still give us the right scroll.
+ SimulateGesturePinchUpdateEvent(1.5, 60, 60, 1);
+ EXPECT_EQ(4U, GestureEventQueueSize());
+
+ SendInputEventACK(WebInputEvent::GestureScrollBegin,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(3U, GestureEventQueueSize());
+
+ // Ack the PinchBegin, and schedule a synchronous ack for GestureScrollUpdate.
+ set_synchronous_ack(INPUT_EVENT_ACK_STATE_CONSUMED);
+ SendInputEventACK(WebInputEvent::GesturePinchBegin,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Both GestureScrollUpdate and GesturePinchUpdate should have been sent.
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, last_acked_event().type);
+ EXPECT_EQ(1U, GestureEventQueueSize());
+ EXPECT_EQ(2U, GetAndResetSentGestureEventCount());
+
+ // Ack the final GesturePinchUpdate.
+ SendInputEventACK(WebInputEvent::GesturePinchUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(WebInputEvent::GesturePinchUpdate, last_acked_event().type);
+ EXPECT_EQ(0U, GestureEventQueueSize());
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+}
+
+#if GTEST_HAS_PARAM_TEST
+TEST_P(GestureEventFilterWithSourceTest, GestureFlingCancelsFiltered) {
+ WebGestureEvent::SourceDevice source_device = GetParam();
+
+ // Turn off debounce handling for test isolation.
+ DisableDebounce();
+ // GFC without previous GFS is dropped.
+ SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+
+ // GFC after previous GFS is dispatched and acked.
+ SimulateGestureFlingStartEvent(0, -10, source_device);
+ EXPECT_TRUE(FlingInProgress());
+ SendInputEventACK(WebInputEvent::GestureFlingStart,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ RunUntilIdle();
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+ SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
+ EXPECT_FALSE(FlingInProgress());
+ EXPECT_EQ(2U, GetAndResetSentGestureEventCount());
+ SendInputEventACK(WebInputEvent::GestureFlingCancel,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ RunUntilIdle();
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+
+ // GFC before previous GFS is acked.
+ SimulateGestureFlingStartEvent(0, -10, source_device);
+ EXPECT_TRUE(FlingInProgress());
+ SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
+ EXPECT_FALSE(FlingInProgress());
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+
+ // Advance state realistically.
+ SendInputEventACK(WebInputEvent::GestureFlingStart,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ RunUntilIdle();
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ SendInputEventACK(WebInputEvent::GestureFlingCancel,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ RunUntilIdle();
+ EXPECT_EQ(2U, GetAndResetAckedGestureEventCount());
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+
+ // GFS is added to the queue if another event is pending
+ SimulateGestureScrollUpdateEvent(8, -7, 0);
+ SimulateGestureFlingStartEvent(0, -10, source_device);
+ EXPECT_EQ(2U, GestureEventQueueSize());
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ WebGestureEvent merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureFlingStart, merged_event.type);
+ EXPECT_TRUE(FlingInProgress());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+
+ // GFS in queue means that a GFC is added to the queue
+ SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
+ merged_event =GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureFlingCancel, merged_event.type);
+ EXPECT_FALSE(FlingInProgress());
+ EXPECT_EQ(3U, GestureEventQueueSize());
+
+ // Adding a second GFC is dropped.
+ SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
+ EXPECT_FALSE(FlingInProgress());
+ EXPECT_EQ(3U, GestureEventQueueSize());
+
+ // Adding another GFS will add it to the queue.
+ SimulateGestureFlingStartEvent(0, -10, source_device);
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureFlingStart, merged_event.type);
+ EXPECT_TRUE(FlingInProgress());
+ EXPECT_EQ(4U, GestureEventQueueSize());
+
+ // GFS in queue means that a GFC is added to the queue
+ SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureFlingCancel, merged_event.type);
+ EXPECT_FALSE(FlingInProgress());
+ EXPECT_EQ(5U, GestureEventQueueSize());
+
+ // Adding another GFC with a GFC already there is dropped.
+ SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
+ merged_event = GestureEventLastQueueEvent();
+ EXPECT_EQ(WebInputEvent::GestureFlingCancel, merged_event.type);
+ EXPECT_FALSE(FlingInProgress());
+ EXPECT_EQ(5U, GestureEventQueueSize());
+}
+
+INSTANTIATE_TEST_CASE_P(AllSources,
+ GestureEventFilterWithSourceTest,
+ testing::Values(WebGestureEvent::Touchscreen,
+ WebGestureEvent::Touchpad));
+#endif // GTEST_HAS_PARAM_TEST
+
+// Test that a GestureScrollEnd | GestureFlingStart are deferred during the
+// debounce interval, that Scrolls are not and that the deferred events are
+// sent after that timer fires.
+TEST_F(GestureEventFilterTest, DebounceDefersFollowingGestureEvents) {
+ set_debounce_interval_time_ms(3);
+
+ SimulateGestureEvent(WebInputEvent::GestureScrollUpdate,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(1U, GestureEventQueueSize());
+ EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
+ EXPECT_TRUE(ScrollingInProgress());
+
+ SimulateGestureEvent(WebInputEvent::GestureScrollUpdate,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+ EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
+ EXPECT_TRUE(ScrollingInProgress());
+
+ SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+ EXPECT_EQ(1U, GestureEventDebouncingQueueSize());
+
+ SimulateGestureFlingStartEvent(0, 10, WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+ EXPECT_EQ(2U, GestureEventDebouncingQueueSize());
+
+ SimulateGestureEvent(WebInputEvent::GestureTapDown,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+ EXPECT_EQ(3U, GestureEventDebouncingQueueSize());
+
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::MessageLoop::QuitClosure(),
+ TimeDelta::FromMilliseconds(5));
+ base::MessageLoop::current()->Run();
+
+ // The deferred events are correctly queued in coalescing queue.
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(5U, GestureEventQueueSize());
+ EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
+ EXPECT_FALSE(ScrollingInProgress());
+
+ // Verify that the coalescing queue contains the correct events.
+ WebInputEvent::Type expected[] = {
+ WebInputEvent::GestureScrollUpdate,
+ WebInputEvent::GestureScrollUpdate,
+ WebInputEvent::GestureScrollEnd,
+ WebInputEvent::GestureFlingStart};
+
+ for (unsigned i = 0; i < sizeof(expected) / sizeof(WebInputEvent::Type);
+ i++) {
+ WebGestureEvent merged_event = GestureEventQueueEventAt(i);
+ EXPECT_EQ(expected[i], merged_event.type);
+ }
+}
+
+// Test that non-scroll events are deferred while scrolling during the debounce
+// interval and are discarded if a GestureScrollUpdate event arrives before the
+// interval end.
+TEST_F(GestureEventFilterTest, DebounceDropsDeferredEvents) {
+ set_debounce_interval_time_ms(3);
+ EXPECT_FALSE(ScrollingInProgress());
+
+ SimulateGestureEvent(WebInputEvent::GestureScrollUpdate,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(1U, GestureEventQueueSize());
+ EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
+ EXPECT_TRUE(ScrollingInProgress());
+
+ // This event should get discarded.
+ SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(1U, GestureEventQueueSize());
+ EXPECT_EQ(1U, GestureEventDebouncingQueueSize());
+
+ SimulateGestureEvent(WebInputEvent::GestureScrollUpdate,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+ EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
+ EXPECT_TRUE(ScrollingInProgress());
+
+ // Verify that the coalescing queue contains the correct events.
+ WebInputEvent::Type expected[] = {
+ WebInputEvent::GestureScrollUpdate,
+ WebInputEvent::GestureScrollUpdate};
+
+ for (unsigned i = 0; i < sizeof(expected) / sizeof(WebInputEvent::Type);
+ i++) {
+ WebGestureEvent merged_event = GestureEventQueueEventAt(i);
+ EXPECT_EQ(expected[i], merged_event.type);
+ }
+}
+
+TEST_F(GestureEventFilterTest, DropZeroVelocityFlings) {
+ WebGestureEvent gesture_event;
+ gesture_event.type = WebInputEvent::GestureFlingStart;
+ gesture_event.sourceDevice = WebGestureEvent::Touchpad;
+ gesture_event.data.flingStart.velocityX = 0.f;
+ gesture_event.data.flingStart.velocityY = 0.f;
+ ASSERT_EQ(0U, GetAndResetSentGestureEventCount());
+ ASSERT_EQ(0U, GestureEventQueueSize());
+ EXPECT_FALSE(SimulateGestureEvent(gesture_event));
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/immediate_input_router.cc b/chromium/content/browser/renderer_host/input/immediate_input_router.cc
deleted file mode 100644
index a4c69054fd1..00000000000
--- a/chromium/content/browser/renderer_host/input/immediate_input_router.cc
+++ /dev/null
@@ -1,574 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/input/immediate_input_router.h"
-
-#include "base/command_line.h"
-#include "base/metrics/histogram.h"
-#include "content/browser/renderer_host/input/gesture_event_filter.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/touch_event_queue.h"
-#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/common/content_constants_internal.h"
-#include "content/common/edit_command.h"
-#include "content/common/input_messages.h"
-#include "content/common/view_messages.h"
-#include "content/port/common/input_event_ack_state.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/browser/user_metrics.h"
-#include "content/public/common/content_switches.h"
-#include "ui/events/event.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-
-using base::Time;
-using base::TimeDelta;
-using base::TimeTicks;
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebKeyboardEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-
-namespace content {
-namespace {
-
-// Returns |true| if the two wheel events should be coalesced.
-bool ShouldCoalesceMouseWheelEvents(const WebMouseWheelEvent& last_event,
- const WebMouseWheelEvent& new_event) {
- return last_event.modifiers == new_event.modifiers &&
- last_event.scrollByPage == new_event.scrollByPage &&
- last_event.hasPreciseScrollingDeltas
- == new_event.hasPreciseScrollingDeltas &&
- last_event.phase == new_event.phase &&
- last_event.momentumPhase == new_event.momentumPhase;
-}
-
-float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
- return accelerated_delta * acceleration_ratio;
-}
-
-float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) {
- if (unaccelerated_delta == 0.f || accelerated_delta == 0.f)
- return 1.f;
- return unaccelerated_delta / accelerated_delta;
-}
-
-const char* GetEventAckName(InputEventAckState ack_result) {
- switch(ack_result) {
- case INPUT_EVENT_ACK_STATE_UNKNOWN: return "UNKNOWN";
- case INPUT_EVENT_ACK_STATE_CONSUMED: return "CONSUMED";
- case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: return "NOT_CONSUMED";
- case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: return "NO_CONSUMER_EXISTS";
- default:
- DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName.\n";
- break;
- }
- return "";
-}
-
-} // namespace
-
-ImmediateInputRouter::ImmediateInputRouter(RenderProcessHost* process,
- InputRouterClient* client,
- InputAckHandler* ack_handler,
- int routing_id)
- : process_(process),
- client_(client),
- ack_handler_(ack_handler),
- routing_id_(routing_id),
- select_range_pending_(false),
- move_caret_pending_(false),
- mouse_move_pending_(false),
- mouse_wheel_pending_(false),
- has_touch_handler_(false),
- touch_event_queue_(new TouchEventQueue(this)),
- gesture_event_filter_(new GestureEventFilter(this)) {
- enable_no_touch_to_renderer_while_scrolling_ =
- CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kNoTouchToRendererWhileScrolling);
- DCHECK(process);
- DCHECK(client);
-}
-
-ImmediateInputRouter::~ImmediateInputRouter() {
-}
-
-void ImmediateInputRouter::Flush() {
- NOTREACHED() << "ImmediateInputRouter will never request a flush.";
-}
-
-bool ImmediateInputRouter::SendInput(scoped_ptr<IPC::Message> message) {
- DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart);
- switch (message->type()) {
- // Check for types that require an ACK.
- case InputMsg_SelectRange::ID:
- return SendSelectRange(message.Pass());
- case InputMsg_MoveCaret::ID:
- return SendMoveCaret(message.Pass());
- case InputMsg_HandleInputEvent::ID:
- NOTREACHED() << "WebInputEvents should never be sent via SendInput.";
- return false;
- default:
- return Send(message.release());
- }
-}
-
-void ImmediateInputRouter::SendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) {
- if (!client_->OnSendMouseEvent(mouse_event))
- return;
-
- if (mouse_event.event.type == WebInputEvent::MouseDown &&
- gesture_event_filter_->GetTouchpadTapSuppressionController()->
- ShouldDeferMouseDown(mouse_event))
- return;
- if (mouse_event.event.type == WebInputEvent::MouseUp &&
- gesture_event_filter_->GetTouchpadTapSuppressionController()->
- ShouldSuppressMouseUp())
- return;
-
- SendMouseEventImmediately(mouse_event);
-}
-
-void ImmediateInputRouter::SendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) {
- if (!client_->OnSendWheelEvent(wheel_event))
- return;
-
- // If there's already a mouse wheel event waiting to be sent to the renderer,
- // add the new deltas to that event. Not doing so (e.g., by dropping the old
- // event, as for mouse moves) results in very slow scrolling on the Mac (on
- // which many, very small wheel events are sent).
- if (mouse_wheel_pending_) {
- if (coalesced_mouse_wheel_events_.empty() ||
- !ShouldCoalesceMouseWheelEvents(
- coalesced_mouse_wheel_events_.back().event, wheel_event.event)) {
- coalesced_mouse_wheel_events_.push_back(wheel_event);
- } else {
- MouseWheelEventWithLatencyInfo* last_wheel_event =
- &coalesced_mouse_wheel_events_.back();
- float unaccelerated_x =
- GetUnacceleratedDelta(last_wheel_event->event.deltaX,
- last_wheel_event->event.accelerationRatioX) +
- GetUnacceleratedDelta(wheel_event.event.deltaX,
- wheel_event.event.accelerationRatioX);
- float unaccelerated_y =
- GetUnacceleratedDelta(last_wheel_event->event.deltaY,
- last_wheel_event->event.accelerationRatioY) +
- GetUnacceleratedDelta(wheel_event.event.deltaY,
- wheel_event.event.accelerationRatioY);
- last_wheel_event->event.deltaX += wheel_event.event.deltaX;
- last_wheel_event->event.deltaY += wheel_event.event.deltaY;
- last_wheel_event->event.wheelTicksX += wheel_event.event.wheelTicksX;
- last_wheel_event->event.wheelTicksY += wheel_event.event.wheelTicksY;
- last_wheel_event->event.accelerationRatioX =
- GetAccelerationRatio(last_wheel_event->event.deltaX, unaccelerated_x);
- last_wheel_event->event.accelerationRatioY =
- GetAccelerationRatio(last_wheel_event->event.deltaY, unaccelerated_y);
- DCHECK_GE(wheel_event.event.timeStampSeconds,
- last_wheel_event->event.timeStampSeconds);
- last_wheel_event->event.timeStampSeconds =
- wheel_event.event.timeStampSeconds;
- last_wheel_event->latency.MergeWith(wheel_event.latency);
- }
- return;
- }
- mouse_wheel_pending_ = true;
- current_wheel_event_ = wheel_event;
-
- HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize",
- coalesced_mouse_wheel_events_.size());
-
- FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency, false);
-}
-
-void ImmediateInputRouter::SendKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info) {
- bool is_shortcut = false;
- if (!client_->OnSendKeyboardEvent(key_event, latency_info, &is_shortcut))
- return;
-
- // Put all WebKeyboardEvent objects in a queue since we can't trust the
- // renderer and we need to give something to the HandleKeyboardEvent
- // handler.
- key_queue_.push_back(key_event);
- HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size());
-
- gesture_event_filter_->FlingHasBeenHalted();
-
- // Only forward the non-native portions of our event.
- FilterAndSendWebInputEvent(key_event, latency_info, is_shortcut);
-}
-
-void ImmediateInputRouter::SendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) {
- HandleGestureScroll(gesture_event);
- if (!client_->OnSendGestureEvent(gesture_event))
- return;
- FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false);
-}
-
-void ImmediateInputRouter::SendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) {
- // Always queue TouchEvents, even if the client request they be dropped.
- client_->OnSendTouchEvent(touch_event);
- touch_event_queue_->QueueEvent(touch_event);
-}
-
-// Forwards MouseEvent without passing it through
-// TouchpadTapSuppressionController.
-void ImmediateInputRouter::SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) {
- if (!client_->OnSendMouseEventImmediately(mouse_event))
- return;
-
- // Avoid spamming the renderer with mouse move events. It is important
- // to note that WM_MOUSEMOVE events are anyways synthetic, but since our
- // thread is able to rapidly consume WM_MOUSEMOVE events, we may get way
- // more WM_MOUSEMOVE events than we wish to send to the renderer.
- if (mouse_event.event.type == WebInputEvent::MouseMove) {
- if (mouse_move_pending_) {
- if (!next_mouse_move_) {
- next_mouse_move_.reset(new MouseEventWithLatencyInfo(mouse_event));
- } else {
- // Accumulate movement deltas.
- int x = next_mouse_move_->event.movementX;
- int y = next_mouse_move_->event.movementY;
- next_mouse_move_->event = mouse_event.event;
- next_mouse_move_->event.movementX += x;
- next_mouse_move_->event.movementY += y;
- next_mouse_move_->latency.MergeWith(mouse_event.latency);
- }
- return;
- }
- mouse_move_pending_ = true;
- }
-
- FilterAndSendWebInputEvent(mouse_event.event, mouse_event.latency, false);
-}
-
-void ImmediateInputRouter::SendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) {
- if (!client_->OnSendTouchEventImmediately(touch_event))
- return;
- FilterAndSendWebInputEvent(touch_event.event, touch_event.latency, false);
-}
-
-void ImmediateInputRouter::SendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) {
- HandleGestureScroll(gesture_event);
- if (!client_->OnSendGestureEventImmediately(gesture_event))
- return;
- FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false);
-}
-
-const NativeWebKeyboardEvent*
- ImmediateInputRouter::GetLastKeyboardEvent() const {
- if (key_queue_.empty())
- return NULL;
- return &key_queue_.front();
-}
-
-bool ImmediateInputRouter::ShouldForwardTouchEvent() const {
- // Always send a touch event if the renderer has a touch-event handler. It is
- // possible that a renderer stops listening to touch-events while there are
- // still events in the touch-queue. In such cases, the new events should still
- // get into the queue.
- return has_touch_handler_ || !touch_event_queue_->empty();
-}
-
-bool ImmediateInputRouter::ShouldForwardGestureEvent(
- const GestureEventWithLatencyInfo& touch_event) const {
- return gesture_event_filter_->ShouldForward(touch_event);
-}
-
-bool ImmediateInputRouter::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- bool message_is_ok = true;
- IPC_BEGIN_MESSAGE_MAP_EX(ImmediateInputRouter, message, message_is_ok)
- IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck)
- IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck)
- IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
- OnHasTouchEventHandlers)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- if (!message_is_ok)
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
-
- return handled;
-}
-
-void ImmediateInputRouter::OnTouchEventAck(
- const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) {
- ack_handler_->OnTouchEventAck(event, ack_result);
-}
-
-bool ImmediateInputRouter::SendSelectRange(scoped_ptr<IPC::Message> message) {
- DCHECK(message->type() == InputMsg_SelectRange::ID);
- if (select_range_pending_) {
- next_selection_range_ = message.Pass();
- return true;
- }
-
- select_range_pending_ = true;
- return Send(message.release());
-}
-
-bool ImmediateInputRouter::SendMoveCaret(scoped_ptr<IPC::Message> message) {
- DCHECK(message->type() == InputMsg_MoveCaret::ID);
- if (move_caret_pending_) {
- next_move_caret_ = message.Pass();
- return true;
- }
-
- move_caret_pending_ = true;
- return Send(message.release());
-}
-
-bool ImmediateInputRouter::Send(IPC::Message* message) {
- return process_->Send(message);
-}
-
-void ImmediateInputRouter::SendWebInputEvent(
- const WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info,
- bool is_keyboard_shortcut) {
- input_event_start_time_ = TimeTicks::Now();
- Send(new InputMsg_HandleInputEvent(
- routing_id(), &input_event, latency_info, is_keyboard_shortcut));
- client_->IncrementInFlightEventCount();
-}
-
-void ImmediateInputRouter::FilterAndSendWebInputEvent(
- const WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info,
- bool is_keyboard_shortcut) {
- TRACE_EVENT0("input", "ImmediateInputRouter::FilterAndSendWebInputEvent");
-
- if (!process_->HasConnection())
- return;
-
- DCHECK(!process_->IgnoreInputEvents());
-
- // Perform optional, synchronous event handling, sending ACK messages for
- // processed events, or proceeding as usual.
- InputEventAckState filter_ack = client_->FilterInputEvent(input_event,
- latency_info);
- switch (filter_ack) {
- // Send the ACK and early exit.
- case INPUT_EVENT_ACK_STATE_CONSUMED:
- case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
- next_mouse_move_.reset();
- ProcessInputEventAck(input_event.type, filter_ack, latency_info);
- // WARNING: |this| may be deleted at this point.
- return;
-
- case INPUT_EVENT_ACK_STATE_UNKNOWN: {
- if (input_event.type == WebKit::WebInputEvent::MouseMove) {
- // Since this mouse-move event has been consumed, there will be no ACKs.
- // So reset the state here so that future mouse-move events do reach the
- // renderer.
- mouse_move_pending_ = false;
- } else if (input_event.type == WebKit::WebInputEvent::MouseWheel) {
- // Reset the wheel-event state when appropriate.
- mouse_wheel_pending_ = false;
- } else if (WebInputEvent::isGestureEventType(input_event.type) &&
- gesture_event_filter_->HasQueuedGestureEvents()) {
- // If the gesture-event filter has queued gesture events, that implies
- // it's awaiting an ack for the event. Since the event is being dropped,
- // it is never sent to the renderer, and so it won't receive any ACKs.
- // So send the ACK to the gesture event filter immediately, and mark it
- // as having been processed.
- gesture_event_filter_->ProcessGestureAck(true, input_event.type);
- } else if (WebInputEvent::isTouchEventType(input_event.type)) {
- // During an overscroll gesture initiated by touch-scrolling, the
- // touch-events do not reset or contribute to the overscroll gesture.
- // However, the touch-events are not sent to the renderer. So send an
- // ACK to the touch-event queue immediately. Mark the event as not
- // processed, to make sure that the touch-scroll gesture that initiated
- // the overscroll is updated properly.
- touch_event_queue_->ProcessTouchAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
- latency_info);
- }
- return;
- }
-
- // Proceed as normal.
- case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
- break;
- }
-
- // Transmit any pending wheel events on a non-wheel event. This ensures that
- // the renderer receives the final PhaseEnded wheel event, which is necessary
- // to terminate rubber-banding, for example.
- if (input_event.type != WebInputEvent::MouseWheel) {
- for (size_t i = 0; i < coalesced_mouse_wheel_events_.size(); ++i) {
- SendWebInputEvent(coalesced_mouse_wheel_events_[i].event,
- coalesced_mouse_wheel_events_[i].latency,
- false);
- }
- coalesced_mouse_wheel_events_.clear();
- }
-
- SendWebInputEvent(input_event, latency_info, is_keyboard_shortcut);
-
- // Any input event cancels a pending mouse move event.
- next_mouse_move_.reset();
-}
-
-void ImmediateInputRouter::OnInputEventAck(
- WebInputEvent::Type event_type,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency_info) {
- // Log the time delta for processing an input event.
- TimeDelta delta = TimeTicks::Now() - input_event_start_time_;
- UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta);
-
- client_->DecrementInFlightEventCount();
-
- ProcessInputEventAck(event_type, ack_result, latency_info);
-}
-
-void ImmediateInputRouter::OnMsgMoveCaretAck() {
- move_caret_pending_ = false;
- if (next_move_caret_)
- SendMoveCaret(next_move_caret_.Pass());
-}
-
-void ImmediateInputRouter::OnSelectRangeAck() {
- select_range_pending_ = false;
- if (next_selection_range_)
- SendSelectRange(next_selection_range_.Pass());
-}
-
-void ImmediateInputRouter::OnHasTouchEventHandlers(bool has_handlers) {
- if (has_touch_handler_ == has_handlers)
- return;
- has_touch_handler_ = has_handlers;
- if (!has_handlers)
- touch_event_queue_->FlushQueue();
- client_->OnHasTouchEventHandlers(has_handlers);
-}
-
-void ImmediateInputRouter::ProcessInputEventAck(
- WebInputEvent::Type event_type,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency_info) {
- TRACE_EVENT1("input", "ImmediateInputRouter::ProcessInputEventAck",
- "ack", GetEventAckName(ack_result));
-
- int type = static_cast<int>(event_type);
- if (type < WebInputEvent::Undefined) {
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
- } else if (type == WebInputEvent::MouseMove) {
- mouse_move_pending_ = false;
-
- // now, we can send the next mouse move event
- if (next_mouse_move_) {
- DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove);
- scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move
- = next_mouse_move_.Pass();
- SendMouseEvent(*next_mouse_move);
- }
- } else if (WebInputEvent::isKeyboardEventType(type)) {
- ProcessKeyboardAck(type, ack_result);
- } else if (type == WebInputEvent::MouseWheel) {
- ProcessWheelAck(ack_result);
- } else if (WebInputEvent::isTouchEventType(type)) {
- ProcessTouchAck(ack_result, latency_info);
- } else if (WebInputEvent::isGestureEventType(type)) {
- ProcessGestureAck(type, ack_result);
- }
-
- // WARNING: |this| may be deleted at this point.
-
- // This is used only for testing, and the other end does not use the
- // source object. On linux, specifying
- // Source<RenderWidgetHost> results in a very strange
- // runtime error in the epilogue of the enclosing
- // (ProcessInputEventAck) method, but not on other platforms; using
- // 'void' instead is just as safe (since NotificationSource
- // is not actually typesafe) and avoids this error.
- NotificationService::current()->Notify(
- NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK,
- Source<void>(this),
- Details<int>(&type));
-}
-
-void ImmediateInputRouter::ProcessKeyboardAck(
- int type,
- InputEventAckState ack_result) {
- if (key_queue_.empty()) {
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK);
- } else if (key_queue_.front().type != type) {
- // Something must be wrong. Clear the |key_queue_| and char event
- // suppression so that we can resume from the error.
- key_queue_.clear();
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_EVENT_TYPE);
- } else {
- NativeWebKeyboardEvent front_item = key_queue_.front();
- key_queue_.pop_front();
-
- ack_handler_->OnKeyboardEventAck(front_item, ack_result);
- // WARNING: This ImmediateInputRouter can be deallocated at this point
- // (i.e. in the case of Ctrl+W, where the call to
- // HandleKeyboardEvent destroys this ImmediateInputRouter).
- }
-}
-
-void ImmediateInputRouter::ProcessWheelAck(InputEventAckState ack_result) {
- mouse_wheel_pending_ = false;
-
- // Process the unhandled wheel event here before calling
- // ForwardWheelEventWithLatencyInfo() since it will mutate
- // current_wheel_event_.
- ack_handler_->OnWheelEventAck(current_wheel_event_.event, ack_result);
-
- // Now send the next (coalesced) mouse wheel event.
- if (!coalesced_mouse_wheel_events_.empty()) {
- MouseWheelEventWithLatencyInfo next_wheel_event =
- coalesced_mouse_wheel_events_.front();
- coalesced_mouse_wheel_events_.pop_front();
- SendWheelEvent(next_wheel_event);
- }
-}
-
-void ImmediateInputRouter::ProcessGestureAck(int type,
- InputEventAckState ack_result) {
- const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
- ack_handler_->OnGestureEventAck(
- gesture_event_filter_->GetGestureEventAwaitingAck(), ack_result);
- gesture_event_filter_->ProcessGestureAck(processed, type);
-}
-
-void ImmediateInputRouter::ProcessTouchAck(
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency_info) {
- // |touch_event_queue_| will forward to OnTouchEventAck when appropriate.
- touch_event_queue_->ProcessTouchAck(ack_result, latency_info);
-}
-
-void ImmediateInputRouter::HandleGestureScroll(
- const GestureEventWithLatencyInfo& gesture_event) {
- if (!enable_no_touch_to_renderer_while_scrolling_)
- return;
-
- // Once scrolling is started stop forwarding touch move events to renderer.
- if (gesture_event.event.type == WebInputEvent::GestureScrollBegin)
- touch_event_queue_->set_no_touch_move_to_renderer(true);
-
- if (gesture_event.event.type == WebInputEvent::GestureScrollEnd ||
- gesture_event.event.type == WebInputEvent::GestureFlingStart) {
- touch_event_queue_->set_no_touch_move_to_renderer(false);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc b/chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc
deleted file mode 100644
index 0e4767a3239..00000000000
--- a/chromium/content/browser/renderer_host/input/immediate_input_router_unittest.cc
+++ /dev/null
@@ -1,1858 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/browser/renderer_host/input/gesture_event_filter.h"
-#include "content/browser/renderer_host/input/immediate_input_router.h"
-#include "content/browser/renderer_host/input/input_router_client.h"
-#include "content/browser/renderer_host/input/input_router_unittest.h"
-#include "content/browser/renderer_host/input/mock_input_router_client.h"
-#include "content/common/content_constants_internal.h"
-#include "content/common/edit_command.h"
-#include "content/common/input_messages.h"
-#include "content/common/view_messages.h"
-#include "content/public/test/mock_render_process_host.h"
-#include "content/public/test/test_browser_context.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-
-#if defined(OS_WIN) || defined(USE_AURA)
-#include "content/browser/renderer_host/ui_events_helper.h"
-#include "ui/events/event.h"
-#endif
-
-using base::TimeDelta;
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebTouchEvent;
-using WebKit::WebTouchPoint;
-
-namespace content {
-
-namespace {
-
-const WebInputEvent* GetInputEventFromMessage(const IPC::Message& message) {
- PickleIterator iter(message);
- const char* data;
- int data_length;
- if (!message.ReadData(&iter, &data, &data_length))
- return NULL;
- return reinterpret_cast<const WebInputEvent*>(data);
-}
-
-bool GetIsShortcutFromHandleInputEventMessage(const IPC::Message* msg) {
- InputMsg_HandleInputEvent::Schema::Param param;
- InputMsg_HandleInputEvent::Read(msg, &param);
- return param.c;
-}
-
-template<typename MSG_T, typename ARG_T1>
-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, param.a);
-}
-
-template<typename MSG_T, typename ARG_T1, typename ARG_T2>
-void ExpectIPCMessageWithArg2(const IPC::Message* msg,
- const ARG_T1& arg1,
- const ARG_T2& arg2) {
- ASSERT_EQ(MSG_T::ID, msg->type());
- typename MSG_T::Schema::Param param;
- ASSERT_TRUE(MSG_T::Read(msg, &param));
- EXPECT_EQ(arg1, param.a);
- EXPECT_EQ(arg2, param.b);
-}
-
-#if defined(OS_WIN) || defined(USE_AURA)
-bool TouchEventsAreEquivalent(const ui::TouchEvent& first,
- const ui::TouchEvent& second) {
- if (first.type() != second.type())
- return false;
- if (first.location() != second.location())
- return false;
- if (first.touch_id() != second.touch_id())
- return false;
- if (second.time_stamp().InSeconds() != first.time_stamp().InSeconds())
- return false;
- return true;
-}
-
-bool EventListIsSubset(const ScopedVector<ui::TouchEvent>& subset,
- const ScopedVector<ui::TouchEvent>& set) {
- if (subset.size() > set.size())
- return false;
- for (size_t i = 0; i < subset.size(); ++i) {
- const ui::TouchEvent* first = subset[i];
- const ui::TouchEvent* second = set[i];
- bool equivalent = TouchEventsAreEquivalent(*first, *second);
- if (!equivalent)
- return false;
- }
-
- return true;
-}
-#endif // defined(OS_WIN) || defined(USE_AURA)
-
-} // namespace
-
-class ImmediateInputRouterTest : public InputRouterTest {
- public:
- ImmediateInputRouterTest() {}
- virtual ~ImmediateInputRouterTest() {}
-
- protected:
- // InputRouterTest
- virtual scoped_ptr<InputRouter> CreateInputRouter(RenderProcessHost* process,
- InputRouterClient* client,
- InputAckHandler* handler,
- int routing_id) OVERRIDE {
- return scoped_ptr<InputRouter>(
- new ImmediateInputRouter(process, client, handler, routing_id));
- }
-
- void SendInputEventACK(WebKit::WebInputEvent::Type type,
- InputEventAckState ack_result) {
- scoped_ptr<IPC::Message> response(
- new InputHostMsg_HandleInputEvent_ACK(0, type, ack_result,
- ui::LatencyInfo()));
- input_router_->OnMessageReceived(*response);
- }
-
- ImmediateInputRouter* input_router() const {
- return static_cast<ImmediateInputRouter*>(input_router_.get());
- }
-
- void set_debounce_interval_time_ms(int ms) {
- input_router()->gesture_event_filter()->debounce_interval_time_ms_ = ms;
- }
-
- void set_maximum_tap_gap_time_ms(int delay_ms) {
- input_router()->gesture_event_filter()->maximum_tap_gap_time_ms_ = delay_ms;
- }
-
- size_t TouchEventQueueSize() {
- return touch_event_queue()->GetQueueSize();
- }
-
- const WebTouchEvent& latest_event() const {
- return touch_event_queue()->GetLatestEvent().event;
- }
-
- void EnableNoTouchToRendererWhileScrolling() {
- input_router()->enable_no_touch_to_renderer_while_scrolling_ = true;
- }
-
- bool no_touch_move_to_renderer() {
- return touch_event_queue()->no_touch_move_to_renderer_;
- }
-
- TouchEventQueue* touch_event_queue() const {
- return input_router()->touch_event_queue();
- }
-
- unsigned GestureEventLastQueueEventSize() {
- return gesture_event_filter()->coalesced_gesture_events_.size();
- }
-
- WebGestureEvent GestureEventSecondFromLastQueueEvent() {
- return gesture_event_filter()->coalesced_gesture_events_.at(
- GestureEventLastQueueEventSize() - 2).event;
- }
-
- WebGestureEvent GestureEventLastQueueEvent() {
- return gesture_event_filter()->coalesced_gesture_events_.back().event;
- }
-
- unsigned GestureEventDebouncingQueueSize() {
- return gesture_event_filter()->debouncing_deferral_queue_.size();
- }
-
- WebGestureEvent GestureEventQueueEventAt(int i) {
- return gesture_event_filter()->coalesced_gesture_events_.at(i).event;
- }
-
- bool shouldDeferTapDownEvents() {
- return gesture_event_filter()->maximum_tap_gap_time_ms_ != 0;
- }
-
- bool ScrollingInProgress() {
- return gesture_event_filter()->scrolling_in_progress_;
- }
-
- bool FlingInProgress() {
- return gesture_event_filter()->fling_in_progress_;
- }
-
- bool WillIgnoreNextACK() {
- return gesture_event_filter()->ignore_next_ack_;
- }
-
- GestureEventFilter* gesture_event_filter() const {
- return input_router()->gesture_event_filter();
- }
-};
-
-#if GTEST_HAS_PARAM_TEST
-// This is for tests that are to be run for all source devices.
-class ImmediateInputRouterWithSourceTest
- : public ImmediateInputRouterTest,
- public testing::WithParamInterface<WebGestureEvent::SourceDevice> {
-};
-#endif // GTEST_HAS_PARAM_TEST
-
-TEST_F(ImmediateInputRouterTest, CoalescesRangeSelection) {
- input_router_->SendInput(scoped_ptr<IPC::Message>(
- new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4))));
- EXPECT_EQ(1u, process_->sink().message_count());
- ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
- process_->sink().GetMessageAt(0),
- gfx::Point(1, 2),
- gfx::Point(3, 4));
- process_->sink().ClearMessages();
-
- // Send two more messages without acking.
- input_router_->SendInput(scoped_ptr<IPC::Message>(
- new InputMsg_SelectRange(0, gfx::Point(5, 6), gfx::Point(7, 8))));
- EXPECT_EQ(0u, process_->sink().message_count());
-
- input_router_->SendInput(scoped_ptr<IPC::Message>(
- new InputMsg_SelectRange(0, gfx::Point(9, 10), gfx::Point(11, 12))));
- EXPECT_EQ(0u, process_->sink().message_count());
-
- // Now ack the first message.
- {
- scoped_ptr<IPC::Message> response(new ViewHostMsg_SelectRange_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
-
- // Verify that the two messages are coalesced into one message.
- EXPECT_EQ(1u, process_->sink().message_count());
- ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
- process_->sink().GetMessageAt(0),
- gfx::Point(9, 10),
- gfx::Point(11, 12));
- process_->sink().ClearMessages();
-
- // Acking the coalesced msg should not send any more msg.
- {
- scoped_ptr<IPC::Message> response(new ViewHostMsg_SelectRange_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
- EXPECT_EQ(0u, process_->sink().message_count());
-}
-
-TEST_F(ImmediateInputRouterTest, CoalescesCaretMove) {
- input_router_->SendInput(
- scoped_ptr<IPC::Message>(new InputMsg_MoveCaret(0, gfx::Point(1, 2))));
- EXPECT_EQ(1u, process_->sink().message_count());
- ExpectIPCMessageWithArg1<InputMsg_MoveCaret>(
- process_->sink().GetMessageAt(0), gfx::Point(1, 2));
- process_->sink().ClearMessages();
-
- // Send two more messages without acking.
- input_router_->SendInput(
- scoped_ptr<IPC::Message>(new InputMsg_MoveCaret(0, gfx::Point(5, 6))));
- EXPECT_EQ(0u, process_->sink().message_count());
-
- input_router_->SendInput(
- scoped_ptr<IPC::Message>(new InputMsg_MoveCaret(0, gfx::Point(9, 10))));
- EXPECT_EQ(0u, process_->sink().message_count());
-
- // Now ack the first message.
- {
- scoped_ptr<IPC::Message> response(new ViewHostMsg_MoveCaret_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
-
- // Verify that the two messages are coalesced into one message.
- EXPECT_EQ(1u, process_->sink().message_count());
- ExpectIPCMessageWithArg1<InputMsg_MoveCaret>(
- process_->sink().GetMessageAt(0), gfx::Point(9, 10));
- process_->sink().ClearMessages();
-
- // Acking the coalesced msg should not send any more msg.
- {
- scoped_ptr<IPC::Message> response(new ViewHostMsg_MoveCaret_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
- EXPECT_EQ(0u, process_->sink().message_count());
-}
-
-TEST_F(ImmediateInputRouterTest, HandledInputEvent) {
- client_->set_filter_state(INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Simulate a keyboard event.
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
-
- // Make sure no input event is sent to the renderer.
- EXPECT_EQ(0u, process_->sink().message_count());
-
- // OnKeyboardEventAck should be triggered without actual ack.
- ack_handler_->ExpectAckCalled(1);
-
- // As the event was acked already, keyboard event queue should be
- // empty.
- ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
-}
-
-TEST_F(ImmediateInputRouterTest, ClientCanceledKeyboardEvent) {
- client_->set_allow_send_event(false);
-
- // Simulate a keyboard event.
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
-
- // Make sure no input event is sent to the renderer.
- EXPECT_EQ(0u, process_->sink().message_count());
- ack_handler_->ExpectAckCalled(0);
-}
-
-TEST_F(ImmediateInputRouterTest, ShortcutKeyboardEvent) {
- client_->set_is_shortcut(true);
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- EXPECT_TRUE(GetIsShortcutFromHandleInputEventMessage(
- process_->sink().GetMessageAt(0)));
-
- process_->sink().ClearMessages();
-
- client_->set_is_shortcut(false);
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- EXPECT_FALSE(GetIsShortcutFromHandleInputEventMessage(
- process_->sink().GetMessageAt(0)));
-}
-
-TEST_F(ImmediateInputRouterTest, NoncorrespondingKeyEvents) {
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
-
- SendInputEventACK(WebInputEvent::KeyUp,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(ack_handler_->unexpected_event_ack_called());
-}
-
-// Tests ported from RenderWidgetHostTest --------------------------------------
-
-TEST_F(ImmediateInputRouterTest, HandleKeyEventsWeSent) {
- // Simulate a keyboard event.
- SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
- ASSERT_TRUE(input_router_->GetLastKeyboardEvent());
- EXPECT_EQ(WebInputEvent::RawKeyDown,
- input_router_->GetLastKeyboardEvent()->type);
-
- // Make sure we sent the input event to the renderer.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::RawKeyDown,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(WebInputEvent::RawKeyDown,
- ack_handler_->acked_keyboard_event().type);
-}
-
-TEST_F(ImmediateInputRouterTest, IgnoreKeyEventsWeDidntSend) {
- // Send a simulated, unrequested key response. We should ignore this.
- SendInputEventACK(WebInputEvent::RawKeyDown,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- ack_handler_->ExpectAckCalled(0);
-}
-
-TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) {
- // Simulate wheel events.
- SimulateWheelEvent(0, -5, 0, false); // sent directly
- SimulateWheelEvent(0, -10, 0, false); // enqueued
- SimulateWheelEvent(8, -6, 0, false); // coalesced into previous event
- SimulateWheelEvent(9, -7, 1, false); // enqueued, different modifiers
-
- // Check that only the first event was sent.
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Check that the ACK sends the second message via ImmediateInputForwarder
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- // The coalesced events can queue up a delayed ack
- // so that additional input events can be processed before
- // we turn off coalescing.
- base::MessageLoop::current()->RunUntilIdle();
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // One more time.
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // After the final ack, the queue should be empty.
- SendInputEventACK(WebInputEvent::MouseWheel,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // FIXME(kouhei): Below is testing gesture event filter. Maybe separate test?
- {
- WebGestureEvent gesture_event;
- gesture_event.type = WebInputEvent::GestureFlingStart;
- gesture_event.sourceDevice = WebGestureEvent::Touchpad;
- gesture_event.data.flingStart.velocityX = 0.f;
- gesture_event.data.flingStart.velocityY = 0.f;
- EXPECT_FALSE(input_router_->ShouldForwardGestureEvent(
- GestureEventWithLatencyInfo(gesture_event, ui::LatencyInfo())));
- }
-}
-
-TEST_F(ImmediateInputRouterTest,
- CoalescesWheelEventsQueuedPhaseEndIsNotDropped) {
- // Send an initial gesture begin and ACK it.
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- WebGestureEvent::Touchpad);
- EXPECT_EQ(1U, process_->sink().message_count());
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
-
- // Send a wheel event, should get sent directly.
- SimulateWheelEvent(0, -5, 0, false);
- EXPECT_EQ(2U, process_->sink().message_count());
-
- // Send a wheel phase end event before an ACK is received for the previous
- // wheel event, which should get queued.
- SimulateWheelEventWithPhase(WebMouseWheelEvent::PhaseEnded);
- EXPECT_EQ(2U, process_->sink().message_count());
-
- // A gesture event should now result in the queued phase ended event being
- // transmitted before it.
- SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
- WebGestureEvent::Touchpad);
- ASSERT_EQ(4U, process_->sink().message_count());
-
- // Verify the events that were sent.
- const WebInputEvent* input_event =
- GetInputEventFromMessage(*process_->sink().GetMessageAt(2));
- ASSERT_EQ(WebInputEvent::MouseWheel, input_event->type);
- const WebMouseWheelEvent* wheel_event =
- static_cast<const WebMouseWheelEvent*>(input_event);
- ASSERT_EQ(WebMouseWheelEvent::PhaseEnded, wheel_event->phase);
-
- input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(3));
- EXPECT_EQ(WebInputEvent::GestureScrollEnd, input_event->type);
-}
-
-TEST_F(ImmediateInputRouterTest, CoalescesScrollGestureEvents) {
- // Turn off debounce handling for test isolation.
- set_debounce_interval_time_ms(0);
-
- // Test coalescing of only GestureScrollUpdate events.
- // Simulate gesture events.
-
- // Sent.
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- WebGestureEvent::Touchscreen);
-
- // Enqueued.
- SimulateGestureScrollUpdateEvent(8, -5, 0);
-
- // Make sure that the queue contains what we think it should.
- WebGestureEvent merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
-
- // Coalesced.
- SimulateGestureScrollUpdateEvent(8, -6, 0);
-
- // Check that coalescing updated the correct values.
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
- EXPECT_EQ(0, merged_event.modifiers);
- EXPECT_EQ(16, merged_event.data.scrollUpdate.deltaX);
- EXPECT_EQ(-11, merged_event.data.scrollUpdate.deltaY);
-
- // Enqueued.
- SimulateGestureScrollUpdateEvent(8, -7, 1);
-
- // Check that we didn't wrongly coalesce.
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
- EXPECT_EQ(1, merged_event.modifiers);
-
- // Different.
- SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
- WebGestureEvent::Touchscreen);
-
- // Check that only the first event was sent.
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Check that the ACK sends the second message.
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Ack for queued coalesced event.
- SendInputEventACK(WebInputEvent::GestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Ack for queued uncoalesced event.
- SendInputEventACK(WebInputEvent::GestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // After the final ack, the queue should be empty.
- SendInputEventACK(WebInputEvent::GestureScrollEnd,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(0U, process_->sink().message_count());
-}
-
-TEST_F(ImmediateInputRouterTest, CoalescesScrollAndPinchEvents) {
- // Turn off debounce handling for test isolation.
- set_debounce_interval_time_ms(0);
-
- // Test coalescing of only GestureScrollUpdate events.
- // Simulate gesture events.
-
- // Sent.
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- WebGestureEvent::Touchscreen);
-
- // Sent.
- SimulateGestureEvent(WebInputEvent::GesturePinchBegin,
- WebGestureEvent::Touchscreen);
-
- // Enqueued.
- SimulateGestureScrollUpdateEvent(8, -4, 1);
-
- // Make sure that the queue contains what we think it should.
- WebGestureEvent merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(3U, GestureEventLastQueueEventSize());
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
-
- // Coalesced without changing event order. Note anchor at (60, 60). Anchoring
- // from a poinht that is not the origin should still give us the wight scroll.
- SimulateGesturePinchUpdateEvent(1.5, 60, 60, 1);
- EXPECT_EQ(4U, GestureEventLastQueueEventSize());
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
- EXPECT_EQ(1.5, merged_event.data.pinchUpdate.scale);
- EXPECT_EQ(1, merged_event.modifiers);
- merged_event = GestureEventSecondFromLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
- EXPECT_EQ(8, merged_event.data.scrollUpdate.deltaX);
- EXPECT_EQ(-4, merged_event.data.scrollUpdate.deltaY);
- EXPECT_EQ(1, merged_event.modifiers);
-
- // Enqueued.
- SimulateGestureScrollUpdateEvent(6, -3, 1);
-
- // Check whether coalesced correctly.
- EXPECT_EQ(4U, GestureEventLastQueueEventSize());
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
- EXPECT_EQ(1.5, merged_event.data.pinchUpdate.scale);
- EXPECT_EQ(1, merged_event.modifiers);
- merged_event = GestureEventSecondFromLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
- EXPECT_EQ(12, merged_event.data.scrollUpdate.deltaX);
- EXPECT_EQ(-6, merged_event.data.scrollUpdate.deltaY);
- EXPECT_EQ(1, merged_event.modifiers);
-
- // Enqueued.
- SimulateGesturePinchUpdateEvent(2, 60, 60, 1);
-
- // Check whether coalesced correctly.
- EXPECT_EQ(4U, GestureEventLastQueueEventSize());
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
- EXPECT_EQ(3, merged_event.data.pinchUpdate.scale);
- EXPECT_EQ(1, merged_event.modifiers);
- merged_event = GestureEventSecondFromLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
- EXPECT_EQ(12, merged_event.data.scrollUpdate.deltaX);
- EXPECT_EQ(-6, merged_event.data.scrollUpdate.deltaY);
- EXPECT_EQ(1, merged_event.modifiers);
-
- // Enqueued.
- SimulateGesturePinchUpdateEvent(2, 60, 60, 1);
-
- // Check whether coalesced correctly.
- EXPECT_EQ(4U, GestureEventLastQueueEventSize());
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
- EXPECT_EQ(6, merged_event.data.pinchUpdate.scale);
- EXPECT_EQ(1, merged_event.modifiers);
- merged_event = GestureEventSecondFromLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
- EXPECT_EQ(12, merged_event.data.scrollUpdate.deltaX);
- EXPECT_EQ(-6, merged_event.data.scrollUpdate.deltaY);
- EXPECT_EQ(1, merged_event.modifiers);
-
- // Check that only the first event was sent.
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Check that the ACK sends the second message.
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Enqueued.
- SimulateGestureScrollUpdateEvent(6, -6, 1);
-
- // Check whether coalesced correctly.
- EXPECT_EQ(3U, GestureEventLastQueueEventSize());
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
- EXPECT_EQ(6, merged_event.data.pinchUpdate.scale);
- EXPECT_EQ(1, merged_event.modifiers);
- merged_event = GestureEventSecondFromLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
- EXPECT_EQ(13, merged_event.data.scrollUpdate.deltaX);
- EXPECT_EQ(-7, merged_event.data.scrollUpdate.deltaY);
- EXPECT_EQ(1, merged_event.modifiers);
-
- // At this point ACKs shouldn't be getting ignored.
- EXPECT_FALSE(WillIgnoreNextACK());
-
- // Check that the ACK sends both scroll and pinch updates.
- SendInputEventACK(WebInputEvent::GesturePinchBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(2U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetFirstMessageMatching(
- InputMsg_HandleInputEvent::ID));
- EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // The next ACK should be getting ignored.
- EXPECT_TRUE(WillIgnoreNextACK());
-
- // Enqueued.
- SimulateGestureScrollUpdateEvent(1, -1, 1);
-
- // Check whether coalesced correctly.
- EXPECT_EQ(3U, GestureEventLastQueueEventSize());
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
- EXPECT_EQ(1, merged_event.data.scrollUpdate.deltaX);
- EXPECT_EQ(-1, merged_event.data.scrollUpdate.deltaY);
- EXPECT_EQ(1, merged_event.modifiers);
- merged_event = GestureEventSecondFromLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
- EXPECT_EQ(6, merged_event.data.pinchUpdate.scale);
- EXPECT_EQ(1, merged_event.modifiers);
-
- // Enqueued.
- SimulateGestureScrollUpdateEvent(2, -2, 1);
-
- // Coalescing scrolls should still work.
- EXPECT_EQ(3U, GestureEventLastQueueEventSize());
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
- EXPECT_EQ(3, merged_event.data.scrollUpdate.deltaX);
- EXPECT_EQ(-3, merged_event.data.scrollUpdate.deltaY);
- EXPECT_EQ(1, merged_event.modifiers);
- merged_event = GestureEventSecondFromLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
- EXPECT_EQ(6, merged_event.data.pinchUpdate.scale);
- EXPECT_EQ(1, merged_event.modifiers);
-
- // Enqueued.
- SimulateGesturePinchUpdateEvent(0.5, 60, 60, 1);
-
- // Check whether coalesced correctly.
- EXPECT_EQ(4U, GestureEventLastQueueEventSize());
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
- EXPECT_EQ(0.5, merged_event.data.pinchUpdate.scale);
- EXPECT_EQ(1, merged_event.modifiers);
- merged_event = GestureEventSecondFromLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
- EXPECT_EQ(3, merged_event.data.scrollUpdate.deltaX);
- EXPECT_EQ(-3, merged_event.data.scrollUpdate.deltaY);
- EXPECT_EQ(1, merged_event.modifiers);
-
- // Check that the ACK gets ignored.
- SendInputEventACK(WebInputEvent::GestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(0U, process_->sink().message_count());
- // The flag should have been flipped back to false.
- EXPECT_FALSE(WillIgnoreNextACK());
-
- // Enqueued.
- SimulateGestureScrollUpdateEvent(2, -2, 2);
-
- // Shouldn't coalesce with different modifiers.
- EXPECT_EQ(4U, GestureEventLastQueueEventSize());
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureScrollUpdate, merged_event.type);
- EXPECT_EQ(2, merged_event.data.scrollUpdate.deltaX);
- EXPECT_EQ(-2, merged_event.data.scrollUpdate.deltaY);
- EXPECT_EQ(2, merged_event.modifiers);
- merged_event = GestureEventSecondFromLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GesturePinchUpdate, merged_event.type);
- EXPECT_EQ(0.5, merged_event.data.pinchUpdate.scale);
- EXPECT_EQ(1, merged_event.modifiers);
-
- // Check that the ACK sends the next scroll pinch pair.
- SendInputEventACK(WebInputEvent::GesturePinchUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(2U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetFirstMessageMatching(
- InputMsg_HandleInputEvent::ID));
- EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Check that the ACK sends the second message.
- SendInputEventACK(WebInputEvent::GestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Check that the ACK sends the second message.
- SendInputEventACK(WebInputEvent::GesturePinchUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Check that the queue is empty after ACK and no messages get sent.
- SendInputEventACK(WebInputEvent::GestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, GestureEventLastQueueEventSize());
-}
-
-#if GTEST_HAS_PARAM_TEST
-TEST_P(ImmediateInputRouterWithSourceTest, GestureFlingCancelsFiltered) {
- WebGestureEvent::SourceDevice source_device = GetParam();
-
- // Turn off debounce handling for test isolation.
- set_debounce_interval_time_ms(0);
- // GFC without previous GFS is dropped.
- SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, GestureEventLastQueueEventSize());
-
- // GFC after previous GFS is dispatched and acked.
- process_->sink().ClearMessages();
- SimulateGestureFlingStartEvent(0, -10, source_device);
- EXPECT_TRUE(FlingInProgress());
- SendInputEventACK(WebInputEvent::GestureFlingStart,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- ack_handler_->ExpectAckCalled(1);
- SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
- EXPECT_FALSE(FlingInProgress());
- EXPECT_EQ(2U, process_->sink().message_count());
- SendInputEventACK(WebInputEvent::GestureFlingCancel,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(0U, GestureEventLastQueueEventSize());
-
- // GFC before previous GFS is acked.
- process_->sink().ClearMessages();
- SimulateGestureFlingStartEvent(0, -10, source_device);
- EXPECT_TRUE(FlingInProgress());
- SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
- EXPECT_FALSE(FlingInProgress());
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
-
- // Advance state realistically.
- SendInputEventACK(WebInputEvent::GestureFlingStart,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- SendInputEventACK(WebInputEvent::GestureFlingCancel,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- base::MessageLoop::current()->RunUntilIdle();
- ack_handler_->ExpectAckCalled(2);
- EXPECT_EQ(0U, GestureEventLastQueueEventSize());
-
- // GFS is added to the queue if another event is pending
- process_->sink().ClearMessages();
- SimulateGestureScrollUpdateEvent(8, -7, 0);
- SimulateGestureFlingStartEvent(0, -10, source_device);
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
- EXPECT_EQ(1U, process_->sink().message_count());
- WebGestureEvent merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureFlingStart, merged_event.type);
- EXPECT_TRUE(FlingInProgress());
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
-
- // GFS in queue means that a GFC is added to the queue
- SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
- merged_event =GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureFlingCancel, merged_event.type);
- EXPECT_FALSE(FlingInProgress());
- EXPECT_EQ(3U, GestureEventLastQueueEventSize());
-
- // Adding a second GFC is dropped.
- SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
- EXPECT_FALSE(FlingInProgress());
- EXPECT_EQ(3U, GestureEventLastQueueEventSize());
-
- // Adding another GFS will add it to the queue.
- SimulateGestureFlingStartEvent(0, -10, source_device);
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureFlingStart, merged_event.type);
- EXPECT_TRUE(FlingInProgress());
- EXPECT_EQ(4U, GestureEventLastQueueEventSize());
-
- // GFS in queue means that a GFC is added to the queue
- SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureFlingCancel, merged_event.type);
- EXPECT_FALSE(FlingInProgress());
- EXPECT_EQ(5U, GestureEventLastQueueEventSize());
-
- // Adding another GFC with a GFC already there is dropped.
- SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
- merged_event = GestureEventLastQueueEvent();
- EXPECT_EQ(WebInputEvent::GestureFlingCancel, merged_event.type);
- EXPECT_FALSE(FlingInProgress());
- EXPECT_EQ(5U, GestureEventLastQueueEventSize());
-}
-
-INSTANTIATE_TEST_CASE_P(AllSources,
- ImmediateInputRouterWithSourceTest,
- testing::Values(WebGestureEvent::Touchscreen,
- WebGestureEvent::Touchpad));
-#endif // GTEST_HAS_PARAM_TEST
-
-// Test that GestureTapDown events are deferred.
-TEST_F(ImmediateInputRouterTest, DeferredGestureTapDown) {
- // Set some sort of short deferral timeout
- set_maximum_tap_gap_time_ms(5);
-
- SimulateGestureEvent(WebInputEvent::GestureTapDown,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, GestureEventLastQueueEventSize());
-
- // Wait long enough for first timeout and see if it fired.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::MessageLoop::QuitClosure(),
- TimeDelta::FromMilliseconds(10));
- base::MessageLoop::current()->Run();
-
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, GestureEventLastQueueEventSize());
- EXPECT_EQ(WebInputEvent::GestureTapDown,
- GestureEventLastQueueEvent().type);
-}
-
-// Test that GestureTapDown events are sent immediately on GestureTap.
-TEST_F(ImmediateInputRouterTest, DeferredGestureTapDownSentOnTap) {
- // Set some sort of short deferral timeout
- set_maximum_tap_gap_time_ms(5);
-
- SimulateGestureEvent(WebInputEvent::GestureTapDown,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, GestureEventLastQueueEventSize());
-
- SimulateGestureEvent(WebInputEvent::GestureTap,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
- EXPECT_EQ(WebInputEvent::GestureTap,
- GestureEventLastQueueEvent().type);
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::MessageLoop::QuitClosure(),
- TimeDelta::FromMilliseconds(10));
- base::MessageLoop::current()->Run();
-
- EXPECT_EQ(WebInputEvent::GestureTapDown,
- client_->immediately_sent_gesture_event().event.type);
-
- // If the deferral timer incorrectly fired, it sent an extra message.
- EXPECT_EQ(1U, process_->sink().message_count());
-}
-
-// Test that only a single GestureTapDown event is sent when tap occurs after
-// the timeout.
-TEST_F(ImmediateInputRouterTest, DeferredGestureTapDownOnlyOnce) {
- // Set some sort of short deferral timeout
- set_maximum_tap_gap_time_ms(5);
-
- SimulateGestureEvent(WebInputEvent::GestureTapDown,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, GestureEventLastQueueEventSize());
-
- // Wait long enough for the timeout and verify it fired.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::MessageLoop::QuitClosure(),
- TimeDelta::FromMilliseconds(10));
- base::MessageLoop::current()->Run();
-
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, GestureEventLastQueueEventSize());
- EXPECT_EQ(WebInputEvent::GestureTapDown,
- GestureEventLastQueueEvent().type);
-
- // Now send the tap gesture and verify we didn't get an extra TapDown.
- SimulateGestureEvent(WebInputEvent::GestureTap,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
- EXPECT_EQ(WebInputEvent::GestureTap,
- GestureEventLastQueueEvent().type);
-}
-
-// Test that scroll events during the deferral interval drop the GestureTapDown.
-TEST_F(ImmediateInputRouterTest, DeferredGestureTapDownAnulledOnScroll) {
- // Set some sort of short deferral timeout
- set_maximum_tap_gap_time_ms(5);
-
- SimulateGestureEvent(WebInputEvent::GestureTapDown,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, GestureEventLastQueueEventSize());
-
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, GestureEventLastQueueEventSize());
- EXPECT_EQ(WebInputEvent::GestureScrollBegin,
- GestureEventLastQueueEvent().type);
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::MessageLoop::QuitClosure(),
- TimeDelta::FromMilliseconds(10));
- base::MessageLoop::current()->Run();
-
- // If the deferral timer incorrectly fired, it will send an extra message.
- EXPECT_EQ(1U, process_->sink().message_count());
-}
-
-// Test that a tap cancel event during the deferral interval drops the
-// GestureTapDown.
-TEST_F(ImmediateInputRouterTest, DeferredGestureTapDownAnulledOnTapCancel) {
- // Set some sort of short deferral timeout
- set_maximum_tap_gap_time_ms(5);
-
- SimulateGestureEvent(WebInputEvent::GestureTapDown,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, GestureEventLastQueueEventSize());
-
- SimulateGestureEvent(WebInputEvent::GestureTapCancel,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, GestureEventLastQueueEventSize());
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::MessageLoop::QuitClosure(),
- TimeDelta::FromMilliseconds(10));
- base::MessageLoop::current()->Run();
-
- // If the deferral timer incorrectly fired, it will send an extra message.
- EXPECT_EQ(0U, process_->sink().message_count());
-}
-
-// Test that if a GestureTapDown gets sent, any corresponding GestureTapCancel
-// is also sent.
-TEST_F(ImmediateInputRouterTest, DeferredGestureTapDownTapCancel) {
- // Set some sort of short deferral timeout
- set_maximum_tap_gap_time_ms(5);
-
- SimulateGestureEvent(WebInputEvent::GestureTapDown,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, GestureEventLastQueueEventSize());
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::MessageLoop::QuitClosure(),
- TimeDelta::FromMilliseconds(10));
- base::MessageLoop::current()->Run();
-
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, GestureEventLastQueueEventSize());
-
- SimulateGestureEvent(WebInputEvent::GestureTapCancel,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
-}
-
-// Test that a GestureScrollEnd | GestureFlingStart are deferred during the
-// debounce interval, that Scrolls are not and that the deferred events are
-// sent after that timer fires.
-TEST_F(ImmediateInputRouterTest, DebounceDefersFollowingGestureEvents) {
- set_debounce_interval_time_ms(3);
-
- SimulateGestureEvent(WebInputEvent::GestureScrollUpdate,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, GestureEventLastQueueEventSize());
- EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
- EXPECT_TRUE(ScrollingInProgress());
-
- SimulateGestureEvent(WebInputEvent::GestureScrollUpdate,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
- EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
- EXPECT_TRUE(ScrollingInProgress());
-
- SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
- EXPECT_EQ(1U, GestureEventDebouncingQueueSize());
-
- SimulateGestureFlingStartEvent(0, 10, WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
- EXPECT_EQ(2U, GestureEventDebouncingQueueSize());
-
- SimulateGestureEvent(WebInputEvent::GestureTapDown,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
- EXPECT_EQ(3U, GestureEventDebouncingQueueSize());
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::MessageLoop::QuitClosure(),
- TimeDelta::FromMilliseconds(5));
- base::MessageLoop::current()->Run();
-
- // The deferred events are correctly queued in coalescing queue.
- EXPECT_EQ(1U, process_->sink().message_count());
- if (shouldDeferTapDownEvents())
- // NOTE: The TapDown is still deferred hence not queued.
- EXPECT_EQ(4U, GestureEventLastQueueEventSize());
- else
- EXPECT_EQ(5U, GestureEventLastQueueEventSize());
- EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
- EXPECT_FALSE(ScrollingInProgress());
-
- // Verify that the coalescing queue contains the correct events.
- WebInputEvent::Type expected[] = {
- WebInputEvent::GestureScrollUpdate,
- WebInputEvent::GestureScrollUpdate,
- WebInputEvent::GestureScrollEnd,
- WebInputEvent::GestureFlingStart};
-
- for (unsigned i = 0; i < sizeof(expected) / sizeof(WebInputEvent::Type);
- i++) {
- WebGestureEvent merged_event = GestureEventQueueEventAt(i);
- EXPECT_EQ(expected[i], merged_event.type);
- }
-}
-
-// Test that non-scroll events are deferred while scrolling during the debounce
-// interval and are discarded if a GestureScrollUpdate event arrives before the
-// interval end.
-TEST_F(ImmediateInputRouterTest, DebounceDropsDeferredEvents) {
- set_debounce_interval_time_ms(3);
- EXPECT_FALSE(ScrollingInProgress());
-
- SimulateGestureEvent(WebInputEvent::GestureScrollUpdate,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, GestureEventLastQueueEventSize());
- EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
- EXPECT_TRUE(ScrollingInProgress());
-
- // This event should get discarded.
- SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, GestureEventLastQueueEventSize());
- EXPECT_EQ(1U, GestureEventDebouncingQueueSize());
-
- SimulateGestureEvent(WebInputEvent::GestureScrollUpdate,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(2U, GestureEventLastQueueEventSize());
- EXPECT_EQ(0U, GestureEventDebouncingQueueSize());
- EXPECT_TRUE(ScrollingInProgress());
-
- // Verify that the coalescing queue contains the correct events.
- WebInputEvent::Type expected[] = {
- WebInputEvent::GestureScrollUpdate,
- WebInputEvent::GestureScrollUpdate};
-
- for (unsigned i = 0; i < sizeof(expected) / sizeof(WebInputEvent::Type);
- i++) {
- WebGestureEvent merged_event = GestureEventQueueEventAt(i);
- EXPECT_EQ(expected[i], merged_event.type);
- }
-}
-
-// Tests that touch-events are queued properly.
-TEST_F(ImmediateInputRouterTest, TouchEventQueue) {
- PressTouchPoint(1, 1);
- SendTouchEvent();
- client_->ExpectSendImmediatelyCalled(true);
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- // The second touch should not be sent since one is already in queue.
- MoveTouchPoint(0, 5, 5);
- SendTouchEvent();
- client_->ExpectSendImmediatelyCalled(false);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- EXPECT_EQ(2U, TouchEventQueueSize());
-
- // Receive an ACK for the first touch-event.
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, TouchEventQueueSize());
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(WebInputEvent::TouchStart,
- ack_handler_->acked_touch_event().event.type);
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- SendInputEventACK(WebInputEvent::TouchMove,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, TouchEventQueueSize());
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(WebInputEvent::TouchMove,
- ack_handler_->acked_touch_event().event.type);
- EXPECT_EQ(0U, process_->sink().message_count());
-}
-
-// Tests that the touch-queue is emptied if a page stops listening for touch
-// events.
-TEST_F(ImmediateInputRouterTest, TouchEventQueueFlush) {
- input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
- EXPECT_TRUE(client_->has_touch_handler());
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
-
- EXPECT_EQ(0U, TouchEventQueueSize());
- EXPECT_TRUE(input_router_->ShouldForwardTouchEvent());
-
- // Send a touch-press event.
- PressTouchPoint(1, 1);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- ReleaseTouchPoint(0);
- SendTouchEvent();
-
- for (int i = 5; i < 15; ++i) {
- PressTouchPoint(1, 1);
- SendTouchEvent();
- MoveTouchPoint(0, i, i);
- SendTouchEvent();
- ReleaseTouchPoint(0);
- SendTouchEvent();
- }
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(32U, TouchEventQueueSize());
-
- // Receive an ACK for the first touch-event. One of the queued touch-event
- // should be forwarded.
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(31U, TouchEventQueueSize());
- EXPECT_EQ(WebInputEvent::TouchStart,
- ack_handler_->acked_touch_event().event.type);
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- // The page stops listening for touch-events. The touch-event queue should now
- // be emptied, but none of the queued touch-events should be sent to the
- // renderer.
- input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
- EXPECT_FALSE(client_->has_touch_handler());
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
- EXPECT_FALSE(input_router_->ShouldForwardTouchEvent());
-}
-
-// Tests that touch-events are coalesced properly in the queue.
-TEST_F(ImmediateInputRouterTest, TouchEventQueueCoalesce) {
- input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
- EXPECT_TRUE(input_router_->ShouldForwardTouchEvent());
-
- // Send a touch-press event.
- PressTouchPoint(1, 1);
- SendTouchEvent();
- client_->ExpectSendImmediatelyCalled(true);
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- // Send a few touch-move events, followed by a touch-release event. All the
- // touch-move events should be coalesced into a single event.
- for (int i = 5; i < 15; ++i) {
- MoveTouchPoint(0, i, i);
- SendTouchEvent();
- }
- client_->ExpectSendImmediatelyCalled(false);
- ReleaseTouchPoint(0);
- SendTouchEvent();
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(3U, TouchEventQueueSize());
- client_->ExpectSendImmediatelyCalled(false);
-
- // ACK the press.
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(2U, TouchEventQueueSize());
- EXPECT_EQ(WebInputEvent::TouchStart,
- ack_handler_->acked_touch_event().event.type);
- ack_handler_->ExpectAckCalled(1);
- process_->sink().ClearMessages();
-
- // Coalesced touch-move events should be sent.
- client_->ExpectSendImmediatelyCalled(true);
- EXPECT_EQ(WebInputEvent::TouchMove,
- client_->immediately_sent_touch_event().event.type);
-
- // ACK the moves.
- SendInputEventACK(WebInputEvent::TouchMove,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, TouchEventQueueSize());
- EXPECT_EQ(WebInputEvent::TouchMove,
- ack_handler_->acked_touch_event().event.type);
- ack_handler_->ExpectAckCalled(10);
- process_->sink().ClearMessages();
-
- // ACK the release.
- SendInputEventACK(WebInputEvent::TouchEnd,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
- EXPECT_EQ(WebInputEvent::TouchEnd,
- ack_handler_->acked_touch_event().event.type);
- ack_handler_->ExpectAckCalled(1);
-}
-
-// Tests that an event that has already been sent but hasn't been ack'ed yet
-// doesn't get coalesced with newer events.
-TEST_F(ImmediateInputRouterTest, SentTouchEventDoesNotCoalesce) {
- input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
- EXPECT_TRUE(input_router_->ShouldForwardTouchEvent());
-
- // Send a touch-press event.
- PressTouchPoint(1, 1);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- // Send a few touch-move events, followed by a touch-release event. All the
- // touch-move events should be coalesced into a single event.
- for (int i = 5; i < 15; ++i) {
- MoveTouchPoint(0, i, i);
- SendTouchEvent();
- }
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(2U, TouchEventQueueSize());
-
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, TouchEventQueueSize());
- process_->sink().ClearMessages();
-
- // The coalesced touch-move event has been sent to the renderer. Any new
- // touch-move event should not be coalesced with the sent event.
- MoveTouchPoint(0, 5, 5);
- SendTouchEvent();
- EXPECT_EQ(2U, TouchEventQueueSize());
-
- MoveTouchPoint(0, 7, 7);
- SendTouchEvent();
- EXPECT_EQ(2U, TouchEventQueueSize());
-}
-
-// Tests that coalescing works correctly for multi-touch events.
-TEST_F(ImmediateInputRouterTest, TouchEventQueueMultiTouch) {
- input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
- EXPECT_TRUE(input_router_->ShouldForwardTouchEvent());
-
- // Press the first finger.
- PressTouchPoint(1, 1);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- // Move the finger.
- MoveTouchPoint(0, 5, 5);
- SendTouchEvent();
- EXPECT_EQ(2U, TouchEventQueueSize());
-
- // Now press a second finger.
- PressTouchPoint(2, 2);
- SendTouchEvent();
- EXPECT_EQ(3U, TouchEventQueueSize());
-
- // Move both fingers.
- MoveTouchPoint(0, 10, 10);
- MoveTouchPoint(1, 20, 20);
- SendTouchEvent();
- EXPECT_EQ(4U, TouchEventQueueSize());
-
- // Move only one finger now.
- MoveTouchPoint(0, 15, 15);
- SendTouchEvent();
- EXPECT_EQ(4U, TouchEventQueueSize());
-
- // Move the other finger.
- MoveTouchPoint(1, 25, 25);
- SendTouchEvent();
- EXPECT_EQ(4U, TouchEventQueueSize());
-
- // Make sure both fingers are marked as having been moved in the coalesced
- // event.
- const WebTouchEvent& event = latest_event();
- EXPECT_EQ(WebTouchPoint::StateMoved, event.touches[0].state);
- EXPECT_EQ(WebTouchPoint::StateMoved, event.touches[1].state);
-}
-
-// Tests that if a touch-event queue is destroyed in response to a touch-event
-// in the renderer, then there is no crash when the ACK for that touch-event
-// comes back.
-TEST_F(ImmediateInputRouterTest, TouchEventAckAfterQueueFlushed) {
- // First, install a touch-event handler and send some touch-events to the
- // renderer.
- input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
- EXPECT_TRUE(input_router_->ShouldForwardTouchEvent());
-
- PressTouchPoint(1, 1);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, TouchEventQueueSize());
- process_->sink().ClearMessages();
-
- MoveTouchPoint(0, 10, 10);
- SendTouchEvent();
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(2U, TouchEventQueueSize());
-
- // Receive an ACK for the press. This should cause the queued touch-move to
- // be sent to the renderer.
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, TouchEventQueueSize());
- process_->sink().ClearMessages();
-
- // Uninstall the touch-event handler. This will cause the queue to be flushed.
- input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
-
- // Now receive an ACK for the move.
- SendInputEventACK(WebInputEvent::TouchMove,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
-}
-
-// Tests that touch-move events are not sent to the renderer if the preceding
-// touch-press event did not have a consumer (and consequently, did not hit the
-// main thread in the renderer). Also tests that all queued/coalesced touch
-// events are flushed immediately when the ACK for the touch-press comes back
-// with NO_CONSUMER status.
-TEST_F(ImmediateInputRouterTest, TouchEventQueueNoConsumer) {
- // The first touch-press should reach the renderer.
- PressTouchPoint(1, 1);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- // The second touch should not be sent since one is already in queue.
- MoveTouchPoint(0, 5, 5);
- SendTouchEvent();
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(2U, TouchEventQueueSize());
-
- // Receive an ACK for the first touch-event. This should release the queued
- // touch-event, but it should not be sent to the renderer.
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
- EXPECT_EQ(0U, TouchEventQueueSize());
- EXPECT_EQ(WebInputEvent::TouchMove,
- ack_handler_->acked_touch_event().event.type);
- ack_handler_->ExpectAckCalled(2);
- EXPECT_EQ(0U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- // Send a release event. This should not reach the renderer.
- ReleaseTouchPoint(0);
- SendTouchEvent();
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(WebInputEvent::TouchEnd,
- ack_handler_->acked_touch_event().event.type);
- ack_handler_->ExpectAckCalled(1);
-
- // Send a press-event, followed by move and release events, and another press
- // event, before the ACK for the first press event comes back. All of the
- // events should be queued first. After the NO_CONSUMER ack for the first
- // touch-press, all events upto the second touch-press should be flushed.
- PressTouchPoint(10, 10);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- MoveTouchPoint(0, 5, 5);
- SendTouchEvent();
- MoveTouchPoint(0, 6, 5);
- SendTouchEvent();
- ReleaseTouchPoint(0);
- SendTouchEvent();
-
- PressTouchPoint(6, 5);
- SendTouchEvent();
- EXPECT_EQ(0U, process_->sink().message_count());
- // The queue should hold the first sent touch-press event, the coalesced
- // touch-move event, the touch-end event and the second touch-press event.
- EXPECT_EQ(4U, TouchEventQueueSize());
-
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(WebInputEvent::TouchEnd,
- ack_handler_->acked_touch_event().event.type);
- ack_handler_->ExpectAckCalled(4);
- EXPECT_EQ(1U, TouchEventQueueSize());
- process_->sink().ClearMessages();
-
- // ACK the second press event as NO_CONSUMER too.
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(WebInputEvent::TouchStart,
- ack_handler_->acked_touch_event().event.type);
- ack_handler_->ExpectAckCalled(1);
- EXPECT_EQ(0U, TouchEventQueueSize());
-
- // Send a second press event. Even though the first touch had NO_CONSUMER,
- // this press event should reach the renderer.
- PressTouchPoint(1, 1);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, TouchEventQueueSize());
-}
-
-TEST_F(ImmediateInputRouterTest, TouchEventQueueConsumerIgnoreMultiFinger) {
- // Press two touch points and move them around a bit. The renderer consumes
- // the events for the first touch point, but returns NO_CONSUMER_EXISTS for
- // the second touch point.
-
- PressTouchPoint(1, 1);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- MoveTouchPoint(0, 5, 5);
- SendTouchEvent();
-
- PressTouchPoint(10, 10);
- SendTouchEvent();
-
- MoveTouchPoint(0, 2, 2);
- SendTouchEvent();
-
- MoveTouchPoint(1, 4, 10);
- SendTouchEvent();
-
- MoveTouchPoint(0, 10, 10);
- MoveTouchPoint(1, 20, 20);
- SendTouchEvent();
-
- // Since the first touch-press is still pending ACK, no other event should
- // have been sent to the renderer.
- EXPECT_EQ(0U, process_->sink().message_count());
- // The queue includes the two presses, the first touch-move of the first
- // point, and a coalesced touch-move of both points.
- EXPECT_EQ(4U, TouchEventQueueSize());
-
- // ACK the first press as CONSUMED. This should cause the first touch-move of
- // the first touch-point to be dispatched.
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
- EXPECT_EQ(3U, TouchEventQueueSize());
-
- // ACK the first move as CONSUMED.
- SendInputEventACK(WebInputEvent::TouchMove,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
- EXPECT_EQ(2U, TouchEventQueueSize());
-
- // ACK the second press as NO_CONSUMER_EXISTS. This will dequeue the coalesced
- // touch-move event (which contains both touch points). Although the second
- // touch-point does not need to be sent to the renderer, the first touch-point
- // did move, and so the coalesced touch-event will be sent to the renderer.
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
- EXPECT_EQ(1U, TouchEventQueueSize());
-
- // ACK the coalesced move as NOT_CONSUMED.
- SendInputEventACK(WebInputEvent::TouchMove,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
-
- // Move just the second touch point. Because the first touch point did not
- // move, this event should not reach the renderer.
- MoveTouchPoint(1, 30, 30);
- SendTouchEvent();
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
-
- // Move just the first touch point. This should reach the renderer.
- MoveTouchPoint(0, 10, 10);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, TouchEventQueueSize());
- process_->sink().ClearMessages();
-
- // Move both fingers. This event should reach the renderer (after the ACK of
- // the previous move event is received), because the first touch point did
- // move.
- MoveTouchPoint(0, 15, 15);
- MoveTouchPoint(1, 25, 25);
- SendTouchEvent();
- EXPECT_EQ(0U, process_->sink().message_count());
-
- SendInputEventACK(WebInputEvent::TouchMove,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, TouchEventQueueSize());
- process_->sink().ClearMessages();
-
- SendInputEventACK(WebInputEvent::TouchMove,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
-
- // Release the first finger. Then move the second finger around some, then
- // press another finger. Once the release event is ACKed, the move events of
- // the second finger should be immediately released to the view, and the
- // touch-press event should be dispatched to the renderer.
- ReleaseTouchPoint(0);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, TouchEventQueueSize());
- process_->sink().ClearMessages();
-
- MoveTouchPoint(1, 40, 40);
- SendTouchEvent();
-
- MoveTouchPoint(1, 50, 50);
- SendTouchEvent();
-
- PressTouchPoint(1, 1);
- SendTouchEvent();
-
- MoveTouchPoint(1, 30, 30);
- SendTouchEvent();
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(4U, TouchEventQueueSize());
-
- SendInputEventACK(WebInputEvent::TouchEnd,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(2U, TouchEventQueueSize());
- EXPECT_EQ(WebInputEvent::TouchMove,
- ack_handler_->acked_touch_event().event.type);
- process_->sink().ClearMessages();
-
- // ACK the press with NO_CONSUMED_EXISTS. This should release the queued
- // touch-move events to the view.
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
- EXPECT_EQ(WebInputEvent::TouchMove,
- ack_handler_->acked_touch_event().event.type);
-
- ReleaseTouchPoint(2);
- ReleaseTouchPoint(1);
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
-}
-
-#if defined(OS_WIN) || defined(USE_AURA)
-// Tests that the acked events have correct state. (ui::Events are used only on
-// windows and aura)
-TEST_F(ImmediateInputRouterTest, AckedTouchEventState) {
- input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
- EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, TouchEventQueueSize());
- EXPECT_TRUE(input_router_->ShouldForwardTouchEvent());
-
- // Send a bunch of events, and make sure the ACKed events are correct.
- ScopedVector<ui::TouchEvent> expected_events;
-
- // 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();
- timestamp -= base::TimeDelta::FromSeconds(600);
-
- // Press the first finger.
- PressTouchPoint(1, 1);
- SetTouchTimestamp(timestamp);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
- expected_events.push_back(new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
- gfx::Point(1, 1), 0, timestamp));
-
- // Move the finger.
- timestamp += base::TimeDelta::FromSeconds(10);
- MoveTouchPoint(0, 5, 5);
- SetTouchTimestamp(timestamp);
- SendTouchEvent();
- EXPECT_EQ(2U, TouchEventQueueSize());
- expected_events.push_back(new ui::TouchEvent(ui::ET_TOUCH_MOVED,
- gfx::Point(5, 5), 0, timestamp));
-
- // Now press a second finger.
- timestamp += base::TimeDelta::FromSeconds(10);
- PressTouchPoint(2, 2);
- SetTouchTimestamp(timestamp);
- SendTouchEvent();
- EXPECT_EQ(3U, TouchEventQueueSize());
- expected_events.push_back(new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
- gfx::Point(2, 2), 1, timestamp));
-
- // Move both fingers.
- timestamp += base::TimeDelta::FromSeconds(10);
- MoveTouchPoint(0, 10, 10);
- MoveTouchPoint(1, 20, 20);
- SetTouchTimestamp(timestamp);
- SendTouchEvent();
- EXPECT_EQ(4U, TouchEventQueueSize());
- expected_events.push_back(new ui::TouchEvent(ui::ET_TOUCH_MOVED,
- gfx::Point(10, 10), 0, timestamp));
- expected_events.push_back(new ui::TouchEvent(ui::ET_TOUCH_MOVED,
- gfx::Point(20, 20), 1, timestamp));
-
- // Receive the ACKs and make sure the generated events from the acked events
- // are correct.
- WebInputEvent::Type acks[] = { WebInputEvent::TouchStart,
- WebInputEvent::TouchMove,
- WebInputEvent::TouchStart,
- WebInputEvent::TouchMove };
-
- TouchEventCoordinateSystem coordinate_system = LOCAL_COORDINATES;
-#if !defined(OS_WIN)
- coordinate_system = SCREEN_COORDINATES;
-#endif
- for (size_t i = 0; i < arraysize(acks); ++i) {
- SendInputEventACK(acks[i],
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(acks[i], ack_handler_->acked_touch_event().event.type);
- ScopedVector<ui::TouchEvent> acked;
-
- MakeUITouchEventsFromWebTouchEvents(
- ack_handler_->acked_touch_event(), &acked, coordinate_system);
- bool success = EventListIsSubset(acked, expected_events);
- EXPECT_TRUE(success) << "Failed on step: " << i;
- if (!success)
- break;
- expected_events.erase(expected_events.begin(),
- expected_events.begin() + acked.size());
- }
-
- EXPECT_EQ(0U, expected_events.size());
-}
-#endif // defined(OS_WIN) || defined(USE_AURA)
-
-TEST_F(ImmediateInputRouterTest, UnhandledWheelEvent) {
- // Simulate wheel events.
- SimulateWheelEvent(0, -5, 0, false); // sent directly
- SimulateWheelEvent(0, -10, 0, false); // enqueued
-
- // Check that only the first event was sent.
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // 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.
- ack_handler_->ExpectAckCalled(1);
- 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_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Check that the correct unhandled wheel event was received.
- EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -5);
-}
-
-// Tests that no touch move events are sent to renderer during scrolling.
-TEST_F(ImmediateInputRouterTest, NoTouchMoveWhileScroll) {
- EnableNoTouchToRendererWhileScrolling();
- set_debounce_interval_time_ms(0);
- input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
- process_->sink().ClearMessages();
-
- // First touch press.
- PressTouchPoint(0, 1);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // Touch move will trigger scroll.
- MoveTouchPoint(0, 20, 5);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::TouchMove,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_TRUE(no_touch_move_to_renderer());
- process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // Touch move should not be sent to renderer.
- MoveTouchPoint(0, 30, 5);
- SendTouchEvent();
- EXPECT_EQ(0U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- // Touch moves become ScrollUpdate.
- SimulateGestureScrollUpdateEvent(20, 4, 0);
- EXPECT_TRUE(no_touch_move_to_renderer());
- process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::GestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // Touch move should not be sent to renderer.
- MoveTouchPoint(0, 65, 10);
- SendTouchEvent();
- EXPECT_EQ(0U, process_->sink().message_count());
- process_->sink().ClearMessages();
-
- // Touch end should still be sent to renderer.
- ReleaseTouchPoint(0);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::TouchEnd,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // On GestureScrollEnd, resume sending touch moves to renderer.
- SimulateGestureEvent(WebKit::WebInputEvent::GestureScrollEnd,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_FALSE(no_touch_move_to_renderer());
- process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::GestureScrollEnd,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // Now touch events should come through to renderer.
- PressTouchPoint(80, 10);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- MoveTouchPoint(0, 80, 20);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::TouchMove,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- ReleaseTouchPoint(0);
- SendTouchEvent();
- EXPECT_EQ(1U, process_->sink().message_count());
- process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::TouchEnd,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-}
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_ack_handler.h b/chromium/content/browser/renderer_host/input/input_ack_handler.h
index 3e09b07cd03..7917bffa80d 100644
--- a/chromium/content/browser/renderer_host/input/input_ack_handler.h
+++ b/chromium/content/browser/renderer_host/input/input_ack_handler.h
@@ -21,11 +21,11 @@ class CONTENT_EXPORT InputAckHandler {
// Called upon event ack receipt from the renderer.
virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
InputEventAckState ack_result) = 0;
- virtual void OnWheelEventAck(const WebKit::WebMouseWheelEvent& event,
+ virtual void OnWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
InputEventAckState ack_result) = 0;
virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) = 0;
- virtual void OnGestureEventAck(const WebKit::WebGestureEvent& event,
+ virtual void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
InputEventAckState ack_result) = 0;
enum UnexpectedEventAckType {
diff --git a/chromium/content/browser/renderer_host/input/input_queue.cc b/chromium/content/browser/renderer_host/input/input_queue.cc
deleted file mode 100644
index c10500b9c08..00000000000
--- a/chromium/content/browser/renderer_host/input/input_queue.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/input/input_queue.h"
-
-#include "base/bind.h"
-#include "base/debug/trace_event.h"
-#include "content/browser/renderer_host/input/browser_input_event.h"
-#include "content/browser/renderer_host/input/input_queue_client.h"
-#include "content/common/input/event_packet.h"
-#include "content/common/input/input_event.h"
-
-namespace content {
-
-// A specialized EventPacket with utility methods for dispatched event handling.
-class InputQueue::BrowserEventPacket : public EventPacket {
- public:
- typedef ScopedVector<BrowserInputEvent> BrowserInputEvents;
-
- BrowserEventPacket() : weak_factory_(this) {}
- virtual ~BrowserEventPacket() {}
-
- // Validate the response and signal dispatch to the processed events.
- // Undelivered events will be re-enqueued, and any generated followup events
- // will be inserted at the same relative order as their generating event.
- AckResult ValidateAndDispatchAck(int64 packet_id,
- const InputEventDispositions& dispositions) {
- if (!Validate(packet_id, dispositions))
- return ACK_INVALID;
-
- // Empty the packet; events will be re-enqueued as necessary.
- InputEvents dispatched_events;
- events_.swap(dispatched_events);
-
- // The packet could be deleted as a result of event dispatch; use a local
- // weak ref to ensure proper shutdown.
- base::WeakPtr<EventPacket> weak_ref_this = weak_factory_.GetWeakPtr();
-
- BrowserInputEvents followup_events;
- for (size_t i = 0; i < dispatched_events.size(); ++i) {
- // Take ownership of the event.
- scoped_ptr<BrowserInputEvent> event(
- static_cast<BrowserInputEvent*>(dispatched_events[i]));
- dispatched_events[i] = NULL;
-
- // Re-enqueue undelivered events.
- InputEventDisposition disposition = dispositions[i];
- if (disposition == INPUT_EVENT_COULD_NOT_DELIVER) {
- Add(event.PassAs<InputEvent>());
- continue;
- }
-
- event->OnDispatched(disposition, &followup_events);
-
- // TODO(jdduke): http://crbug.com/274029
- if (!weak_ref_this.get())
- return ACK_SHUTDOWN;
-
- AddAll(&followup_events);
- }
- return ACK_OK;
- }
-
- protected:
- // Add and take ownership of events in |followup_events|.
- void AddAll(BrowserInputEvents* followup_events) {
- for (BrowserInputEvents::iterator iter = followup_events->begin();
- iter != followup_events->end();
- ++iter) {
- Add(scoped_ptr<InputEvent>(*iter));
- }
- followup_events->weak_clear();
- }
-
- // Perform a sanity check of the ack against the current packet.
- // |packet_id| should match that of this packet, and |dispositions| should
- // be of size equal to the number of events in this packet.
- bool Validate(int64 packet_id,
- const InputEventDispositions& dispositions) const {
- if (packet_id != id())
- return false;
-
- if (dispositions.size() != size())
- return false;
-
- return true;
- }
-
- private:
- base::WeakPtrFactory<EventPacket> weak_factory_;
-};
-
-InputQueue::InputQueue(InputQueueClient* client)
- : client_(client),
- next_packet_id_(1),
- flush_requested_(false),
- in_flush_packet_(new BrowserEventPacket()),
- pending_flush_packet_(new BrowserEventPacket()) {
- DCHECK(client_);
-}
-
-InputQueue::~InputQueue() {}
-
-void InputQueue::QueueEvent(scoped_ptr<BrowserInputEvent> event) {
- DCHECK(event);
- DCHECK(event->valid());
- pending_flush_packet_->Add(event.PassAs<InputEvent>());
- RequestFlushIfNecessary();
-}
-
-void InputQueue::BeginFlush() {
- // Ignore repeated flush attempts.
- if (!flush_requested_)
- return;
-
- DCHECK(!FlushInProgress());
- DCHECK(!pending_flush_packet_->empty());
-
- flush_requested_ = false;
- in_flush_packet_.swap(pending_flush_packet_);
- DeliverInFlushPacket();
-}
-
-InputQueue::AckResult InputQueue::OnEventPacketAck(
- int64 packet_id,
- const InputEventDispositions& dispositions) {
- if (!FlushInProgress())
- return ACK_UNEXPECTED;
-
- TRACE_EVENT_ASYNC_STEP1("input", "InputQueueFlush", this, "AckPacket",
- "id", packet_id);
-
- AckResult ack_result =
- in_flush_packet_->ValidateAndDispatchAck(packet_id, dispositions);
-
- if (ack_result != ACK_OK)
- return ack_result;
-
- if (FlushInProgress()) {
- DeliverInFlushPacket();
- } else {
- TRACE_EVENT_ASYNC_END0("input", "InputQueueFlush", this);
- client_->DidFinishFlush();
- RequestFlushIfNecessary();
- }
-
- return ACK_OK;
-}
-
-size_t InputQueue::QueuedEventCount() const {
- return in_flush_packet_->size() + pending_flush_packet_->size();
-}
-
-void InputQueue::DeliverInFlushPacket() {
- DCHECK(FlushInProgress());
- TRACE_EVENT_ASYNC_STEP1("input", "InputQueueFlush", this, "DeliverPacket",
- "id", next_packet_id_);
- in_flush_packet_->set_id(next_packet_id_++);
- client_->Deliver(*in_flush_packet_);
-}
-
-void InputQueue::RequestFlushIfNecessary() {
- if (flush_requested_)
- return;
-
- // Defer flush requests until the current flush has finished.
- if (FlushInProgress())
- return;
-
- // No additional events to flush.
- if (pending_flush_packet_->empty())
- return;
-
- TRACE_EVENT_ASYNC_BEGIN0("input", "InputQueueFlush", this);
- TRACE_EVENT_ASYNC_STEP0("input", "InputQueueFlush", this, "Request");
- flush_requested_ = true;
- client_->SetNeedsFlush();
-}
-
-bool InputQueue::FlushInProgress() const { return !in_flush_packet_->empty(); }
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_queue.h b/chromium/content/browser/renderer_host/input/input_queue.h
deleted file mode 100644
index 2c7acb707d2..00000000000
--- a/chromium/content/browser/renderer_host/input/input_queue.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_H_
-#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "content/common/input/input_event_disposition.h"
-
-namespace content {
-
-class BrowserInputEvent;
-class EventPacketAck;
-class InputQueueClient;
-
-// |InputQueue| handles browser input event batching and response.
-// Event packets are assembled into sequential event packets. A flush entails
-// delivery and dispatch of a single event packet, and continues until the
-// packet is ack'ed and all its events have been dispatched to the renderer.
-class CONTENT_EXPORT InputQueue {
- public:
- // The |client| should outlive the InputQueue.
- InputQueue(InputQueueClient* client);
- virtual ~InputQueue();
-
- // If a flush is in progress, |event| will be dispatched in the next flush.
- // If no flush is in progress, a flush will be requested if necessary.
- // |event| is assumed to be both non-NULL and valid.
- void QueueEvent(scoped_ptr<BrowserInputEvent> event);
-
- // Initiates the flush of the pending event packet to |client_|, if necessary.
- // This should only be called in response to |client_->SetNeedsFlush()|.
- void BeginFlush();
-
- // Called by the owner upon EventPacket responses from the sender target. This
- // will dispatch event acks for events with a corresponding |ack_handler|.
- enum AckResult {
- ACK_OK, // |acked_packet| was processed successfully.
- ACK_UNEXPECTED, // |acked_packet| was unexpected; no flush was in-progress.
- ACK_INVALID, // |acked_packet| contains invalid data.
- ACK_SHUTDOWN // |acked_packet| processing triggered queue shutdown.
- };
- AckResult OnEventPacketAck(int64 packet_id,
- const InputEventDispositions& dispositions);
-
- // Total number of evenst in the queue, both being flushed and pending flush.
- size_t QueuedEventCount() const;
-
- protected:
- friend class InputQueueTest;
-
- // Delivers |in_flush_packet_| to the client.
- void DeliverInFlushPacket();
-
- // Requests a flush via |client_| if the necessary request has not been made.
- void RequestFlushIfNecessary();
-
- // True when |in_flush_packet_| is non-empty.
- bool FlushInProgress() const;
-
- private:
- InputQueueClient* client_;
-
- // Used to assign unique, non-zero ID's to each delivered EventPacket.
- int64 next_packet_id_;
-
- // Avoid spamming the client with redundant flush requests.
- bool flush_requested_;
-
- class BrowserEventPacket;
- scoped_ptr<BrowserEventPacket> in_flush_packet_;
- scoped_ptr<BrowserEventPacket> pending_flush_packet_;
-
- DISALLOW_COPY_AND_ASSIGN(InputQueue);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_H_
diff --git a/chromium/content/browser/renderer_host/input/input_queue_client.h b/chromium/content/browser/renderer_host/input/input_queue_client.h
deleted file mode 100644
index f1151d92fed..00000000000
--- a/chromium/content/browser/renderer_host/input/input_queue_client.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_CLIENT_H_
-#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_CLIENT_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_vector.h"
-#include "content/common/input/input_event_disposition.h"
-
-namespace content {
-
-class EventPacket;
-
-class InputQueueClient {
- public:
- virtual ~InputQueueClient() {}
-
- // Used by the flush process for sending batched events to the desired target.
- virtual void Deliver(const EventPacket& packet) = 0;
-
- // Signalled when the InputQueue has received and dispatched
- // event ACK's from the previous flush.
- virtual void DidFinishFlush() = 0;
-
- // Signalled when the InputQueue receives an input event.
- virtual void SetNeedsFlush() = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_QUEUE_CLIENT_H_
diff --git a/chromium/content/browser/renderer_host/input/input_queue_unittest.cc b/chromium/content/browser/renderer_host/input/input_queue_unittest.cc
deleted file mode 100644
index 2d183d96cca..00000000000
--- a/chromium/content/browser/renderer_host/input/input_queue_unittest.cc
+++ /dev/null
@@ -1,363 +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 <vector>
-
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/renderer_host/input/browser_input_event.h"
-#include "content/browser/renderer_host/input/input_queue.h"
-#include "content/browser/renderer_host/input/input_queue_client.h"
-#include "content/common/input/event_packet.h"
-#include "content/common/input/input_event.h"
-#include "content/common/input/ipc_input_event_payload.h"
-#include "content/common/input/web_input_event_payload.h"
-#include "content/common/input_messages.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/events/latency_info.h"
-
-namespace content {
-namespace {
-
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebKeyboardEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebTouchEvent;
-
-class InputQueueTest : public testing::Test,
- public InputQueueClient,
- public BrowserInputEventClient {
- public:
- InputQueueTest()
- : queue_(new InputQueue(this)),
- routing_id_(0),
- num_flush_completions_(0),
- num_flush_requests_(0),
- num_packet_deliveries_(0),
- next_input_id_(1) {}
-
- // InputQueueClient
- virtual void Deliver(const EventPacket& packet) OVERRIDE {
- EXPECT_LT(0u, packet.size());
- ++num_packet_deliveries_;
- current_packet_id_ = packet.id();
- current_packet_dispositions_.resize(packet.size(), INPUT_EVENT_UNHANDLED);
- }
-
- virtual void DidFinishFlush() OVERRIDE { ++num_flush_completions_; }
- virtual void SetNeedsFlush() OVERRIDE { ++num_flush_requests_; }
-
- // BrowserInputEventClient
- virtual void OnDispatched(const BrowserInputEvent& event,
- InputEventDisposition disposition) OVERRIDE {
- acked_dispositions_.push_back(disposition);
- }
-
- virtual void OnDispatched(
- const BrowserInputEvent& event,
- InputEventDisposition disposition,
- ScopedVector<BrowserInputEvent>* followup) OVERRIDE {
- acked_followup_dispositions_.push_back(disposition);
- if (event_to_inject_)
- followup->push_back(event_to_inject_.release());
- }
-
- int num_flush_requests() const { return num_flush_requests_; }
- int num_flush_completions() const { return num_flush_completions_; }
- int num_packet_deliveries() const { return num_packet_deliveries_; }
-
- protected:
- scoped_ptr<BrowserInputEvent> CreateIPCInputEvent(IPC::Message* message) {
- return BrowserInputEvent::Create(
- NextInputID(),
- IPCInputEventPayload::Create(make_scoped_ptr(message)),
- this);
- }
-
- scoped_ptr<BrowserInputEvent> CreateWebInputEvent(
- WebInputEvent::Type web_type) {
- WebKit::WebMouseEvent mouse;
- WebKit::WebMouseWheelEvent wheel;
- WebKit::WebTouchEvent touch;
- WebKit::WebGestureEvent gesture;
- WebKit::WebKeyboardEvent keyboard;
-
- WebKit::WebInputEvent* web_event = NULL;
- if (WebInputEvent::isMouseEventType(web_type))
- web_event = &mouse;
- else if (WebInputEvent::isKeyboardEventType(web_type))
- web_event = &keyboard;
- else if (WebInputEvent::isTouchEventType(web_type))
- web_event = &touch;
- else if (WebInputEvent::isGestureEventType(web_type))
- web_event = &gesture;
- else
- web_event = &wheel;
- web_event->type = web_type;
-
- return BrowserInputEvent::Create(
- NextInputID(),
- WebInputEventPayload::Create(*web_event, ui::LatencyInfo(), false),
- this);
- }
-
- void QueueEvent(IPC::Message* message) {
- queue_->QueueEvent(CreateIPCInputEvent(message));
- }
-
- void QueueEvent(WebInputEvent::Type web_type) {
- queue_->QueueEvent(CreateWebInputEvent(web_type));
- }
-
- bool Flush(InputEventDisposition disposition) {
- StartFlush();
- return FinishFlush(disposition);
- }
-
- void StartFlush() {
- acked_dispositions_.clear();
- acked_followup_dispositions_.clear();
- current_packet_id_ = 0;
- current_packet_dispositions_.clear();
- queue_->BeginFlush();
- }
-
- bool FinishFlush(InputEventDisposition disposition) {
- if (!current_packet_id_)
- return false;
- current_packet_dispositions_ = InputEventDispositions(
- current_packet_dispositions_.size(), disposition);
- return InputQueue::ACK_OK ==
- queue_->OnEventPacketAck(current_packet_id_,
- current_packet_dispositions_);
- }
-
- int64 NextInputID() { return next_input_id_++; }
-
- scoped_ptr<InputQueue> queue_;
-
- int routing_id_;
- int64 current_packet_id_;
- InputEventDispositions current_packet_dispositions_;
-
- InputEventDispositions acked_dispositions_;
- InputEventDispositions acked_followup_dispositions_;
- scoped_ptr<BrowserInputEvent> event_to_inject_;
-
- int num_flush_completions_;
- int num_flush_requests_;
- int num_packet_deliveries_;
- int next_input_id_;
-};
-
-TEST_F(InputQueueTest, SetNeedsFlushOnQueueEvent) {
- EXPECT_EQ(0, num_flush_requests());
-
- QueueEvent(WebInputEvent::MouseDown);
- EXPECT_EQ(1, num_flush_requests());
-
- // Additional queued events should not trigger additional flush requests.
- QueueEvent(WebInputEvent::MouseUp);
- EXPECT_EQ(1, num_flush_requests());
- QueueEvent(WebInputEvent::TouchStart);
- EXPECT_EQ(1, num_flush_requests());
-}
-
-TEST_F(InputQueueTest, NoSetNeedsFlushOnQueueIfFlushing) {
- QueueEvent(WebInputEvent::GestureScrollBegin);
- EXPECT_EQ(1, num_flush_requests());
-
- StartFlush();
- EXPECT_EQ(1, num_flush_requests());
- EXPECT_EQ(1, num_packet_deliveries());
-
- // Events queued after a flush will not trigger an additional flush request.
- QueueEvent(WebInputEvent::GestureScrollBegin);
- EXPECT_EQ(1, num_flush_requests());
- QueueEvent(WebInputEvent::GestureScrollEnd);
- EXPECT_EQ(1, num_flush_requests());
-}
-
-TEST_F(InputQueueTest, SetNeedsFlushAfterDidFinishFlushIfEventsQueued) {
- QueueEvent(WebInputEvent::GestureScrollBegin);
- EXPECT_EQ(1, num_flush_requests());
-
- StartFlush();
- EXPECT_EQ(1, num_packet_deliveries());
-
- QueueEvent(WebInputEvent::GestureScrollBegin);
- EXPECT_EQ(1, num_flush_requests());
-
- // An additional flush request is sent for the event queued after the flush.
- ASSERT_TRUE(current_packet_id_);
- ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_CONSUMED));
- EXPECT_EQ(1, num_flush_completions());
- EXPECT_EQ(2, num_flush_requests());
-}
-
-TEST_F(InputQueueTest, EventPacketSentAfterFlush) {
- EXPECT_EQ(0, num_packet_deliveries());
- QueueEvent(WebInputEvent::GestureScrollBegin);
- EXPECT_EQ(0, num_packet_deliveries());
- StartFlush();
- EXPECT_EQ(1, num_packet_deliveries());
-}
-
-TEST_F(InputQueueTest, AcksHandledInProperOrder) {
- QueueEvent(WebInputEvent::GestureScrollBegin);
- QueueEvent(WebInputEvent::GestureScrollEnd);
- QueueEvent(WebInputEvent::GestureFlingStart);
-
- queue_->BeginFlush();
- ASSERT_EQ(3u, current_packet_dispositions_.size());
- current_packet_dispositions_[0] = INPUT_EVENT_IMPL_THREAD_CONSUMED;
- current_packet_dispositions_[1] = INPUT_EVENT_MAIN_THREAD_CONSUMED;
- current_packet_dispositions_[2] = INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS;
- queue_->OnEventPacketAck(current_packet_id_, current_packet_dispositions_);
- EXPECT_EQ(1, num_flush_completions());
-
- ASSERT_EQ(3u, acked_dispositions_.size());
- EXPECT_EQ(acked_dispositions_[0], INPUT_EVENT_IMPL_THREAD_CONSUMED);
- EXPECT_EQ(acked_dispositions_[1], INPUT_EVENT_MAIN_THREAD_CONSUMED);
- EXPECT_EQ(acked_dispositions_[2], INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS);
-}
-
-TEST_F(InputQueueTest, FollowupWhenFollowupEventNotConsumed) {
- InputEventDisposition unconsumed_dispositions[] = {
- INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS,
- INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED,
- INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS
- };
- for (size_t i = 0; i < arraysize(unconsumed_dispositions); ++i) {
- QueueEvent(WebInputEvent::GestureScrollBegin);
- QueueEvent(WebInputEvent::TouchStart);
- QueueEvent(WebInputEvent::TouchMove);
-
- Flush(unconsumed_dispositions[i]);
- EXPECT_EQ(1u, acked_dispositions_.size()) << i;
- EXPECT_EQ(2u, acked_followup_dispositions_.size()) << i;
- }
-}
-
-TEST_F(InputQueueTest, NoFollowupWhenFollowupEventConsumed) {
- InputEventDisposition consumed_dispositions[] = {
- INPUT_EVENT_IMPL_THREAD_CONSUMED,
- INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED,
- INPUT_EVENT_MAIN_THREAD_CONSUMED
- };
- for (size_t i = 0; i < arraysize(consumed_dispositions); ++i) {
- QueueEvent(WebInputEvent::GestureScrollBegin);
- QueueEvent(WebInputEvent::TouchStart);
- QueueEvent(WebInputEvent::TouchMove);
-
- Flush(consumed_dispositions[i]);
- EXPECT_EQ(3u, acked_dispositions_.size()) << i;
- EXPECT_EQ(0u, acked_followup_dispositions_.size()) << i;
- }
-}
-
-TEST_F(InputQueueTest, FlushOnEmptyQueueIgnored) {
- Flush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
- EXPECT_EQ(0, num_flush_requests());
- EXPECT_EQ(0, num_flush_completions());
-
- QueueEvent(WebInputEvent::GestureScrollBegin);
- Flush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
- EXPECT_EQ(1, num_flush_requests());
- EXPECT_EQ(1, num_flush_completions());
-
- Flush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
- EXPECT_EQ(1, num_flush_requests());
- EXPECT_EQ(1, num_flush_completions());
-}
-
-TEST_F(InputQueueTest, FlushContinuesUntilAllEventsProcessed) {
- QueueEvent(WebInputEvent::GestureScrollBegin);
- QueueEvent(WebInputEvent::GestureScrollEnd);
- QueueEvent(WebInputEvent::GestureFlingStart);
-
- EXPECT_EQ(1, num_flush_requests());
- Flush(INPUT_EVENT_COULD_NOT_DELIVER);
- EXPECT_EQ(0, num_flush_completions());
-
- FinishFlush(INPUT_EVENT_COULD_NOT_DELIVER);
- EXPECT_EQ(0, num_flush_completions());
-
- ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED));
- EXPECT_EQ(1, num_flush_completions());
-}
-
-TEST_F(InputQueueTest, InvalidPacketAckIgnored) {
- // Packet never flushed, any ack should be ignored.
- InputQueue::AckResult result =
- queue_->OnEventPacketAck(0, InputEventDispositions());
- EXPECT_EQ(InputQueue::ACK_UNEXPECTED, result);
-
- QueueEvent(WebInputEvent::GestureScrollBegin);
- StartFlush();
- // Tamper with the sent packet by adding an extra event.
- current_packet_dispositions_.push_back(INPUT_EVENT_MAIN_THREAD_CONSUMED);
- bool valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
- EXPECT_EQ(0, num_flush_completions());
- EXPECT_FALSE(valid_packet_ack);
-
- // Fix the packet.
- current_packet_dispositions_.pop_back();
- valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
- EXPECT_EQ(1, num_flush_completions());
- EXPECT_TRUE(valid_packet_ack);
-
- // Tamper with the packet by changing the id.
- QueueEvent(WebInputEvent::GestureScrollBegin);
- StartFlush();
- int64 packet_ack_id = -1;
- std::swap(current_packet_id_, packet_ack_id);
- valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
- EXPECT_EQ(1, num_flush_completions());
- EXPECT_FALSE(valid_packet_ack);
-
- // Fix the packet.
- std::swap(current_packet_id_, packet_ack_id);
- valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
- EXPECT_EQ(2, num_flush_completions());
- EXPECT_TRUE(valid_packet_ack);
-}
-
-TEST_F(InputQueueTest, InjectedEventsAckedBeforeDidFinishFlush) {
- QueueEvent(WebInputEvent::GestureScrollBegin);
- QueueEvent(WebInputEvent::TouchMove);
-
- event_to_inject_ = CreateIPCInputEvent(new InputMsg_Copy(routing_id_));
- Flush(INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS);
- EXPECT_EQ(0, num_flush_completions());
-
- // The injected event should now be in the event packet.
- EXPECT_EQ(1u, current_packet_dispositions_.size());
- EXPECT_EQ(1u, acked_followup_dispositions_.size());
- ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED));
- EXPECT_EQ(1, num_flush_completions());
-
- QueueEvent(WebInputEvent::GestureScrollBegin);
- QueueEvent(WebInputEvent::TouchStart);
- event_to_inject_ = CreateWebInputEvent(WebInputEvent::TouchMove);
- Flush(INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS);
- // |event_to_inject_| is now in the event packet.
- EXPECT_EQ(1u, acked_followup_dispositions_.size());
- EXPECT_EQ(1u, current_packet_dispositions_.size());
-
- event_to_inject_ = CreateWebInputEvent(WebInputEvent::TouchMove);
- // the next |event_to_inject_| is now in the event packet.
- ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS));
-
- EXPECT_EQ(2u, acked_followup_dispositions_.size());
- EXPECT_EQ(1u, current_packet_dispositions_.size());
- EXPECT_EQ(1, num_flush_completions());
-
- ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED));
- EXPECT_EQ(2, num_flush_completions());
-}
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router.h b/chromium/content/browser/renderer_host/input/input_router.h
index 5e4533fc1dd..2dbb4ed00a6 100644
--- a/chromium/content/browser/renderer_host/input/input_router.h
+++ b/chromium/content/browser/renderer_host/input/input_router.h
@@ -40,17 +40,12 @@ class InputRouter : public IPC::Listener {
const MouseWheelEventWithLatencyInfo& wheel_event) = 0;
virtual void SendKeyboardEvent(
const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info) = 0;
+ const ui::LatencyInfo& latency_info,
+ bool is_shortcut) = 0;
virtual void SendGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) = 0;
virtual void SendTouchEvent(
const TouchEventWithLatencyInfo& touch_event) = 0;
- virtual void SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) = 0;
- virtual void SendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) = 0;
- virtual void SendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) = 0;
// Returns the oldest queued or in-flight keyboard event sent to the router.
virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const = 0;
@@ -60,10 +55,14 @@ class InputRouter : public IPC::Listener {
// instead consume them directly.
virtual bool ShouldForwardTouchEvent() const = 0;
- // Returns |true| if the caller should immediately forward the provided
- // |gesture_event| to the router.
- virtual bool ShouldForwardGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) const = 0;
+ // Allow the router to make more informed input handling decisions based on
+ // the current view.
+ enum ViewFlags {
+ VIEW_FLAGS_NONE = 0,
+ FIXED_PAGE_SCALE = 1 << 0,
+ MOBILE_VIEWPORT = 1 << 1
+ };
+ virtual void OnViewUpdated(int view_flags) = 0;
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router_client.h b/chromium/content/browser/renderer_host/input/input_router_client.h
index 6479332d444..fefcb10c7c2 100644
--- a/chromium/content/browser/renderer_host/input/input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/input_router_client.h
@@ -17,6 +17,8 @@ struct LatencyInfo;
namespace content {
+class OverscrollController;
+
class CONTENT_EXPORT InputRouterClient {
public:
virtual ~InputRouterClient() {}
@@ -28,7 +30,7 @@ class CONTENT_EXPORT InputRouterClient {
// * |CONSUMED| or |NO_CONSUMER_EXISTS| will trigger the appropriate ack.
// * |UNKNOWN| will result in |input_event| being dropped.
virtual InputEventAckState FilterInputEvent(
- const WebKit::WebInputEvent& input_event,
+ const blink::WebInputEvent& input_event,
const ui::LatencyInfo& latency_info) = 0;
// Called each time a WebInputEvent IPC is sent.
@@ -40,26 +42,10 @@ class CONTENT_EXPORT InputRouterClient {
// Called when the renderer notifies that it has touch event handlers.
virtual void OnHasTouchEventHandlers(bool has_handlers) = 0;
- // Called upon Send*Event. Should return true if the event should be sent, and
- // false if the event should be dropped.
- virtual bool OnSendKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info,
- bool* is_shortcut) = 0;
- virtual bool OnSendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) = 0;
- virtual bool OnSendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) = 0;
- virtual bool OnSendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) = 0;
- virtual bool OnSendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) = 0;
- virtual bool OnSendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) = 0;
- virtual bool OnSendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) = 0;
- virtual bool OnSendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) = 0;
+ // Returns an optional OverscrollController. If non-NULL, the controller
+ // will be fed events and event acks by the router, when appropriate.
+ // TODO(jdduke): crbug.com/306133 - Move the controller to the router.
+ virtual OverscrollController* GetOverscrollController() const = 0;
// Certain router implementations require periodic flushing of queued events.
// When this method is called, the client should ensure a timely call, either
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.cc b/chromium/content/browser/renderer_host/input/input_router_impl.cc
new file mode 100644
index 00000000000..8e498fd5e46
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.cc
@@ -0,0 +1,729 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/input_router_impl.h"
+
+#include "base/auto_reset.h"
+#include "base/command_line.h"
+#include "base/metrics/histogram.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/browser/renderer_host/input/gesture_event_filter.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/touch_event_queue.h"
+#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
+#include "content/browser/renderer_host/overscroll_controller.h"
+#include "content/common/content_constants_internal.h"
+#include "content/common/edit_command.h"
+#include "content/common/input/touch_action.h"
+#include "content/common/input/web_input_event_traits.h"
+#include "content/common/input_messages.h"
+#include "content/common/view_messages.h"
+#include "content/port/common/input_event_ack_state.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/user_metrics.h"
+#include "content/public/common/content_switches.h"
+#include "ipc/ipc_sender.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+using base::Time;
+using base::TimeDelta;
+using base::TimeTicks;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+
+namespace content {
+namespace {
+
+bool GetTouchAckTimeoutDelayMs(size_t* touch_ack_timeout_delay_ms) {
+ CommandLine* parsed_command_line = CommandLine::ForCurrentProcess();
+ if (!parsed_command_line->HasSwitch(switches::kTouchAckTimeoutDelayMs))
+ return false;
+
+ std::string timeout_string = parsed_command_line->GetSwitchValueASCII(
+ switches::kTouchAckTimeoutDelayMs);
+ size_t timeout_value;
+ if (!base::StringToSizeT(timeout_string, &timeout_value))
+ return false;
+
+ *touch_ack_timeout_delay_ms = timeout_value;
+ return true;
+}
+
+GestureEventWithLatencyInfo MakeGestureEvent(WebInputEvent::Type type,
+ double timestamp_seconds,
+ int x,
+ int y,
+ int modifiers,
+ const ui::LatencyInfo latency) {
+ WebGestureEvent result;
+
+ result.type = type;
+ result.x = x;
+ result.y = y;
+ result.sourceDevice = WebGestureEvent::Touchscreen;
+ result.timeStampSeconds = timestamp_seconds;
+ result.modifiers = modifiers;
+
+ return GestureEventWithLatencyInfo(result, latency);
+}
+
+const char* GetEventAckName(InputEventAckState ack_result) {
+ switch(ack_result) {
+ case INPUT_EVENT_ACK_STATE_UNKNOWN: return "UNKNOWN";
+ case INPUT_EVENT_ACK_STATE_CONSUMED: return "CONSUMED";
+ case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: return "NOT_CONSUMED";
+ case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: return "NO_CONSUMER_EXISTS";
+ case INPUT_EVENT_ACK_STATE_IGNORED: return "IGNORED";
+ }
+ DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName.";
+ return "";
+}
+
+} // namespace
+
+InputRouterImpl::InputRouterImpl(IPC::Sender* sender,
+ InputRouterClient* client,
+ InputAckHandler* ack_handler,
+ int routing_id)
+ : sender_(sender),
+ client_(client),
+ ack_handler_(ack_handler),
+ routing_id_(routing_id),
+ select_range_pending_(false),
+ move_caret_pending_(false),
+ mouse_move_pending_(false),
+ mouse_wheel_pending_(false),
+ has_touch_handler_(false),
+ touch_ack_timeout_enabled_(false),
+ touch_ack_timeout_delay_ms_(std::numeric_limits<size_t>::max()),
+ current_ack_source_(ACK_SOURCE_NONE),
+ gesture_event_filter_(new GestureEventFilter(this, this)) {
+ DCHECK(sender);
+ DCHECK(client);
+ DCHECK(ack_handler);
+ touch_event_queue_.reset(new TouchEventQueue(this));
+ touch_ack_timeout_enabled_ =
+ GetTouchAckTimeoutDelayMs(&touch_ack_timeout_delay_ms_);
+ touch_event_queue_->SetAckTimeoutEnabled(touch_ack_timeout_enabled_,
+ touch_ack_timeout_delay_ms_);
+}
+
+InputRouterImpl::~InputRouterImpl() {}
+
+void InputRouterImpl::Flush() {}
+
+bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) {
+ DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart);
+ switch (message->type()) {
+ // Check for types that require an ACK.
+ case InputMsg_SelectRange::ID:
+ return SendSelectRange(message.Pass());
+ case InputMsg_MoveCaret::ID:
+ return SendMoveCaret(message.Pass());
+ case InputMsg_HandleInputEvent::ID:
+ NOTREACHED() << "WebInputEvents should never be sent via SendInput.";
+ return false;
+ default:
+ return Send(message.release());
+ }
+}
+
+void InputRouterImpl::SendMouseEvent(
+ const MouseEventWithLatencyInfo& mouse_event) {
+ // Order is important here; we need to convert all MouseEvents before they
+ // propagate further, e.g., to the tap suppression controller.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSimulateTouchScreenWithMouse)) {
+ SimulateTouchGestureWithMouse(mouse_event);
+ return;
+ }
+
+ if (mouse_event.event.type == WebInputEvent::MouseDown &&
+ gesture_event_filter_->GetTouchpadTapSuppressionController()->
+ ShouldDeferMouseDown(mouse_event))
+ return;
+ if (mouse_event.event.type == WebInputEvent::MouseUp &&
+ gesture_event_filter_->GetTouchpadTapSuppressionController()->
+ ShouldSuppressMouseUp())
+ return;
+
+ SendMouseEventImmediately(mouse_event);
+}
+
+void InputRouterImpl::SendWheelEvent(
+ const MouseWheelEventWithLatencyInfo& wheel_event) {
+ // If there's already a mouse wheel event waiting to be sent to the renderer,
+ // add the new deltas to that event. Not doing so (e.g., by dropping the old
+ // event, as for mouse moves) results in very slow scrolling on the Mac (on
+ // which many, very small wheel events are sent).
+ if (mouse_wheel_pending_) {
+ if (coalesced_mouse_wheel_events_.empty() ||
+ !coalesced_mouse_wheel_events_.back().CanCoalesceWith(wheel_event)) {
+ coalesced_mouse_wheel_events_.push_back(wheel_event);
+ } else {
+ coalesced_mouse_wheel_events_.back().CoalesceWith(wheel_event);
+ }
+ return;
+ }
+ mouse_wheel_pending_ = true;
+ current_wheel_event_ = wheel_event;
+
+ HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize",
+ coalesced_mouse_wheel_events_.size());
+
+ FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency, false);
+}
+
+void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_keyboard_shortcut) {
+ // Put all WebKeyboardEvent objects in a queue since we can't trust the
+ // renderer and we need to give something to the HandleKeyboardEvent
+ // handler.
+ key_queue_.push_back(key_event);
+ HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size());
+
+ gesture_event_filter_->FlingHasBeenHalted();
+
+ // Only forward the non-native portions of our event.
+ FilterAndSendWebInputEvent(key_event, latency_info, is_keyboard_shortcut);
+}
+
+void InputRouterImpl::SendGestureEvent(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ if (touch_action_filter_.FilterGestureEvent(gesture_event.event))
+ return;
+
+ touch_event_queue_->OnGestureScrollEvent(gesture_event);
+
+ if (!IsInOverscrollGesture() &&
+ !gesture_event_filter_->ShouldForward(gesture_event)) {
+ OverscrollController* controller = client_->GetOverscrollController();
+ if (controller)
+ controller->DiscardingGestureEvent(gesture_event.event);
+ return;
+ }
+
+ FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false);
+}
+
+void InputRouterImpl::SendTouchEvent(
+ const TouchEventWithLatencyInfo& touch_event) {
+ touch_event_queue_->QueueEvent(touch_event);
+}
+
+// Forwards MouseEvent without passing it through
+// TouchpadTapSuppressionController.
+void InputRouterImpl::SendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& mouse_event) {
+ // Avoid spamming the renderer with mouse move events. It is important
+ // to note that WM_MOUSEMOVE events are anyways synthetic, but since our
+ // thread is able to rapidly consume WM_MOUSEMOVE events, we may get way
+ // more WM_MOUSEMOVE events than we wish to send to the renderer.
+ if (mouse_event.event.type == WebInputEvent::MouseMove) {
+ if (mouse_move_pending_) {
+ if (!next_mouse_move_)
+ next_mouse_move_.reset(new MouseEventWithLatencyInfo(mouse_event));
+ else
+ next_mouse_move_->CoalesceWith(mouse_event);
+ return;
+ }
+ mouse_move_pending_ = true;
+ }
+
+ FilterAndSendWebInputEvent(mouse_event.event, mouse_event.latency, false);
+}
+
+void InputRouterImpl::SendTouchEventImmediately(
+ const TouchEventWithLatencyInfo& touch_event) {
+ FilterAndSendWebInputEvent(touch_event.event, touch_event.latency, false);
+}
+
+void InputRouterImpl::SendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false);
+}
+
+const NativeWebKeyboardEvent* InputRouterImpl::GetLastKeyboardEvent() const {
+ if (key_queue_.empty())
+ return NULL;
+ return &key_queue_.front();
+}
+
+bool InputRouterImpl::ShouldForwardTouchEvent() const {
+ // Always send a touch event if the renderer has a touch-event handler. It is
+ // possible that a renderer stops listening to touch-events while there are
+ // still events in the touch-queue. In such cases, the new events should still
+ // get into the queue.
+ return has_touch_handler_ || !touch_event_queue_->empty();
+}
+
+void InputRouterImpl::OnViewUpdated(int view_flags) {
+ bool fixed_page_scale = (view_flags & FIXED_PAGE_SCALE) != 0;
+ bool mobile_viewport = (view_flags & MOBILE_VIEWPORT) != 0;
+ touch_event_queue_->SetAckTimeoutEnabled(
+ touch_ack_timeout_enabled_ && !(fixed_page_scale || mobile_viewport),
+ touch_ack_timeout_delay_ms_);
+}
+
+bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ bool message_is_ok = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(InputRouterImpl, message, message_is_ok)
+ IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
+ OnHasTouchEventHandlers)
+ IPC_MESSAGE_HANDLER(InputHostMsg_SetTouchAction,
+ OnSetTouchAction)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ if (!message_is_ok)
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
+
+ return handled;
+}
+
+void InputRouterImpl::OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) {
+ ack_handler_->OnTouchEventAck(event, ack_result);
+}
+
+void InputRouterImpl::OnGestureEventAck(
+ const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) {
+ ProcessAckForOverscroll(event.event, ack_result);
+ ack_handler_->OnGestureEventAck(event, ack_result);
+}
+
+bool InputRouterImpl::SendSelectRange(scoped_ptr<IPC::Message> message) {
+ DCHECK(message->type() == InputMsg_SelectRange::ID);
+ if (select_range_pending_) {
+ next_selection_range_ = message.Pass();
+ return true;
+ }
+
+ select_range_pending_ = true;
+ return Send(message.release());
+}
+
+bool InputRouterImpl::SendMoveCaret(scoped_ptr<IPC::Message> message) {
+ DCHECK(message->type() == InputMsg_MoveCaret::ID);
+ if (move_caret_pending_) {
+ next_move_caret_ = message.Pass();
+ return true;
+ }
+
+ move_caret_pending_ = true;
+ return Send(message.release());
+}
+
+bool InputRouterImpl::Send(IPC::Message* message) {
+ return sender_->Send(message);
+}
+
+void InputRouterImpl::FilterAndSendWebInputEvent(
+ const WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_keyboard_shortcut) {
+ TRACE_EVENT1("input",
+ "InputRouterImpl::FilterAndSendWebInputEvent",
+ "type",
+ WebInputEventTraits::GetName(input_event.type));
+
+ // Transmit any pending wheel events on a non-wheel event. This ensures that
+ // final PhaseEnded wheel event is received, which is necessary to terminate
+ // rubber-banding, for example.
+ if (input_event.type != WebInputEvent::MouseWheel) {
+ WheelEventQueue mouse_wheel_events;
+ mouse_wheel_events.swap(coalesced_mouse_wheel_events_);
+ for (size_t i = 0; i < mouse_wheel_events.size(); ++i) {
+ OfferToHandlers(mouse_wheel_events[i].event,
+ mouse_wheel_events[i].latency,
+ false);
+ }
+ }
+
+ // Any input event cancels a pending mouse move event.
+ next_mouse_move_.reset();
+
+ OfferToHandlers(input_event, latency_info, is_keyboard_shortcut);
+}
+
+void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_keyboard_shortcut) {
+ if (OfferToOverscrollController(input_event, latency_info))
+ return;
+
+ if (OfferToClient(input_event, latency_info))
+ return;
+
+ OfferToRenderer(input_event, latency_info, is_keyboard_shortcut);
+
+ // If we don't care about the ack disposition, send the ack immediately.
+ if (WebInputEventTraits::IgnoresAckDisposition(input_event.type)) {
+ ProcessInputEventAck(input_event.type,
+ INPUT_EVENT_ACK_STATE_IGNORED,
+ latency_info,
+ IGNORING_DISPOSITION);
+ }
+}
+
+bool InputRouterImpl::OfferToOverscrollController(
+ const WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info) {
+ OverscrollController* controller = client_->GetOverscrollController();
+ if (!controller)
+ return false;
+
+ OverscrollController::Disposition disposition =
+ controller->DispatchEvent(input_event, latency_info);
+
+ bool consumed = disposition == OverscrollController::CONSUMED;
+
+ if (disposition == OverscrollController::SHOULD_FORWARD_TO_GESTURE_FILTER) {
+ DCHECK(WebInputEvent::isGestureEventType(input_event.type));
+ const blink::WebGestureEvent& gesture_event =
+ static_cast<const blink::WebGestureEvent&>(input_event);
+ // An ACK is expected for the event, so mark it as consumed.
+ consumed = !gesture_event_filter_->ShouldForward(
+ GestureEventWithLatencyInfo(gesture_event, latency_info));
+ }
+
+ if (consumed) {
+ InputEventAckState overscroll_ack =
+ WebInputEvent::isTouchEventType(input_event.type) ?
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED : INPUT_EVENT_ACK_STATE_CONSUMED;
+ ProcessInputEventAck(input_event.type,
+ overscroll_ack,
+ latency_info,
+ OVERSCROLL_CONTROLLER);
+ // WARNING: |this| may be deleted at this point.
+ }
+
+ return consumed;
+}
+
+bool InputRouterImpl::OfferToClient(const WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info) {
+ bool consumed = false;
+
+ InputEventAckState filter_ack =
+ client_->FilterInputEvent(input_event, latency_info);
+ switch (filter_ack) {
+ case INPUT_EVENT_ACK_STATE_CONSUMED:
+ case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
+ // Send the ACK and early exit.
+ next_mouse_move_.reset();
+ ProcessInputEventAck(input_event.type, filter_ack, latency_info, CLIENT);
+ // WARNING: |this| may be deleted at this point.
+ consumed = true;
+ break;
+ case INPUT_EVENT_ACK_STATE_UNKNOWN:
+ // Simply drop the event.
+ consumed = true;
+ break;
+ default:
+ break;
+ }
+
+ return consumed;
+}
+
+bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_keyboard_shortcut) {
+ input_event_start_time_ = TimeTicks::Now();
+ if (Send(new InputMsg_HandleInputEvent(
+ routing_id(), &input_event, latency_info, is_keyboard_shortcut))) {
+ // Only increment the event count if we require an ACK for |input_event|.
+ if (!WebInputEventTraits::IgnoresAckDisposition(input_event.type))
+ client_->IncrementInFlightEventCount();
+ return true;
+ }
+ return false;
+}
+
+void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type,
+ InputEventAckState ack_result,
+ const ui::LatencyInfo& latency_info) {
+ // Log the time delta for processing an input event.
+ TimeDelta delta = TimeTicks::Now() - input_event_start_time_;
+ UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta);
+
+ // A synthetic ack will already have been sent for this event, and it will
+ // not have affected the in-flight event count.
+ if (WebInputEventTraits::IgnoresAckDisposition(event_type))
+ return;
+
+ client_->DecrementInFlightEventCount();
+
+ ProcessInputEventAck(event_type, ack_result, latency_info, RENDERER);
+ // WARNING: |this| may be deleted at this point.
+
+ // This is used only for testing, and the other end does not use the
+ // source object. On linux, specifying
+ // Source<RenderWidgetHost> results in a very strange
+ // runtime error in the epilogue of the enclosing
+ // (ProcessInputEventAck) method, but not on other platforms; using
+ // 'void' instead is just as safe (since NotificationSource
+ // is not actually typesafe) and avoids this error.
+ int type = static_cast<int>(event_type);
+ NotificationService::current()->Notify(
+ NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK,
+ Source<void>(this),
+ Details<int>(&type));
+}
+
+void InputRouterImpl::OnMsgMoveCaretAck() {
+ move_caret_pending_ = false;
+ if (next_move_caret_)
+ SendMoveCaret(next_move_caret_.Pass());
+}
+
+void InputRouterImpl::OnSelectRangeAck() {
+ select_range_pending_ = false;
+ if (next_selection_range_)
+ SendSelectRange(next_selection_range_.Pass());
+}
+
+void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) {
+ if (has_touch_handler_ == has_handlers)
+ return;
+ has_touch_handler_ = has_handlers;
+ if (!has_handlers)
+ touch_event_queue_->FlushQueue();
+ client_->OnHasTouchEventHandlers(has_handlers);
+}
+
+void InputRouterImpl::OnSetTouchAction(
+ content::TouchAction touch_action) {
+ // Synthetic touchstart events should get filtered out in RenderWidget.
+ DCHECK(touch_event_queue_->IsPendingAckTouchStart());
+
+ touch_action_filter_.OnSetTouchAction(touch_action);
+}
+
+void InputRouterImpl::ProcessInputEventAck(
+ WebInputEvent::Type event_type,
+ InputEventAckState ack_result,
+ const ui::LatencyInfo& latency_info,
+ AckSource ack_source) {
+ TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck",
+ "type", WebInputEventTraits::GetName(event_type),
+ "ack", GetEventAckName(ack_result));
+
+ // Note: The keyboard ack must be treated carefully, as it may result in
+ // synchronous destruction of |this|. Handling immediately guards against
+ // future references to |this|, as with |auto_reset_current_ack_source| below.
+ if (WebInputEvent::isKeyboardEventType(event_type)) {
+ ProcessKeyboardAck(event_type, ack_result);
+ // WARNING: |this| may be deleted at this point.
+ return;
+ }
+
+ base::AutoReset<AckSource> auto_reset_current_ack_source(
+ &current_ack_source_, ack_source);
+
+ if (WebInputEvent::isMouseEventType(event_type)) {
+ ProcessMouseAck(event_type, ack_result);
+ } else if (event_type == WebInputEvent::MouseWheel) {
+ ProcessWheelAck(ack_result, latency_info);
+ } else if (WebInputEvent::isTouchEventType(event_type)) {
+ ProcessTouchAck(ack_result, latency_info);
+ } else if (WebInputEvent::isGestureEventType(event_type)) {
+ ProcessGestureAck(event_type, ack_result, latency_info);
+ } else if (event_type != WebInputEvent::Undefined) {
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
+ }
+}
+
+void InputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type,
+ InputEventAckState ack_result) {
+ if (key_queue_.empty()) {
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK);
+ } else if (key_queue_.front().type != type) {
+ // Something must be wrong. Clear the |key_queue_| and char event
+ // suppression so that we can resume from the error.
+ key_queue_.clear();
+ ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_EVENT_TYPE);
+ } else {
+ NativeWebKeyboardEvent front_item = key_queue_.front();
+ key_queue_.pop_front();
+
+ ack_handler_->OnKeyboardEventAck(front_item, ack_result);
+ // WARNING: This InputRouterImpl can be deallocated at this point
+ // (i.e. in the case of Ctrl+W, where the call to
+ // HandleKeyboardEvent destroys this InputRouterImpl).
+ // TODO(jdduke): crbug.com/274029 - Make ack-triggered shutdown async.
+ }
+}
+
+void InputRouterImpl::ProcessMouseAck(blink::WebInputEvent::Type type,
+ InputEventAckState ack_result) {
+ if (type != WebInputEvent::MouseMove)
+ return;
+
+ mouse_move_pending_ = false;
+
+ if (next_mouse_move_) {
+ DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove);
+ scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move
+ = next_mouse_move_.Pass();
+ SendMouseEvent(*next_mouse_move);
+ }
+}
+
+void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result,
+ const ui::LatencyInfo& latency) {
+ ProcessAckForOverscroll(current_wheel_event_.event, ack_result);
+
+ // TODO(miletus): Add renderer side latency to each uncoalesced mouse
+ // wheel event and add terminal component to each of them.
+ current_wheel_event_.latency.AddNewLatencyFrom(latency);
+ // Process the unhandled wheel event here before calling SendWheelEvent()
+ // since it will mutate current_wheel_event_.
+ ack_handler_->OnWheelEventAck(current_wheel_event_, ack_result);
+ mouse_wheel_pending_ = false;
+
+ // Now send the next (coalesced) mouse wheel event.
+ if (!coalesced_mouse_wheel_events_.empty()) {
+ MouseWheelEventWithLatencyInfo next_wheel_event =
+ coalesced_mouse_wheel_events_.front();
+ coalesced_mouse_wheel_events_.pop_front();
+ SendWheelEvent(next_wheel_event);
+ }
+}
+
+void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type,
+ InputEventAckState ack_result,
+ const ui::LatencyInfo& latency) {
+ // If |ack_result| originated from the overscroll controller, only
+ // feed |gesture_event_filter_| the ack if it was expecting one.
+ if (current_ack_source_ == OVERSCROLL_CONTROLLER &&
+ !gesture_event_filter_->HasQueuedGestureEvents()) {
+ return;
+ }
+
+ // |gesture_event_filter_| will forward to OnGestureEventAck when appropriate.
+ gesture_event_filter_->ProcessGestureAck(ack_result, type, latency);
+}
+
+void InputRouterImpl::ProcessTouchAck(
+ InputEventAckState ack_result,
+ const ui::LatencyInfo& latency) {
+ // |touch_event_queue_| will forward to OnTouchEventAck when appropriate.
+ touch_event_queue_->ProcessTouchAck(ack_result, latency);
+}
+
+void InputRouterImpl::ProcessAckForOverscroll(const WebInputEvent& event,
+ InputEventAckState ack_result) {
+ // Acks sent from the overscroll controller need not be fed back into the
+ // overscroll controller.
+ if (current_ack_source_ == OVERSCROLL_CONTROLLER)
+ return;
+
+ OverscrollController* controller = client_->GetOverscrollController();
+ if (!controller)
+ return;
+
+ controller->ReceivedEventACK(
+ event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
+}
+
+void InputRouterImpl::SimulateTouchGestureWithMouse(
+ const MouseEventWithLatencyInfo& event) {
+ const WebMouseEvent& mouse_event = event.event;
+ int x = mouse_event.x, y = mouse_event.y;
+ float dx = mouse_event.movementX, dy = mouse_event.movementY;
+ static int startX = 0, startY = 0;
+
+ switch (mouse_event.button) {
+ case WebMouseEvent::ButtonLeft:
+ if (mouse_event.type == WebInputEvent::MouseDown) {
+ startX = x;
+ startY = y;
+ SendGestureEvent(MakeGestureEvent(
+ WebInputEvent::GestureScrollBegin, mouse_event.timeStampSeconds,
+ x, y, 0, event.latency));
+ }
+ if (dx != 0 || dy != 0) {
+ GestureEventWithLatencyInfo gesture_event = MakeGestureEvent(
+ WebInputEvent::GestureScrollUpdate, mouse_event.timeStampSeconds,
+ x, y, 0, event.latency);
+ gesture_event.event.data.scrollUpdate.deltaX = dx;
+ gesture_event.event.data.scrollUpdate.deltaY = dy;
+ SendGestureEvent(gesture_event);
+ }
+ if (mouse_event.type == WebInputEvent::MouseUp) {
+ SendGestureEvent(MakeGestureEvent(
+ WebInputEvent::GestureScrollEnd, mouse_event.timeStampSeconds,
+ x, y, 0, event.latency));
+ }
+ break;
+ case WebMouseEvent::ButtonMiddle:
+ if (mouse_event.type == WebInputEvent::MouseDown) {
+ startX = x;
+ startY = y;
+ SendGestureEvent(MakeGestureEvent(
+ WebInputEvent::GestureShowPress, mouse_event.timeStampSeconds,
+ x, y, 0, event.latency));
+ SendGestureEvent(MakeGestureEvent(
+ WebInputEvent::GestureTapDown, mouse_event.timeStampSeconds,
+ x, y, 0, event.latency));
+ }
+ if (mouse_event.type == WebInputEvent::MouseUp) {
+ SendGestureEvent(MakeGestureEvent(
+ WebInputEvent::GestureTap, mouse_event.timeStampSeconds,
+ x, y, 0, event.latency));
+ }
+ break;
+ case WebMouseEvent::ButtonRight:
+ if (mouse_event.type == WebInputEvent::MouseDown) {
+ startX = x;
+ startY = y;
+ SendGestureEvent(MakeGestureEvent(
+ WebInputEvent::GestureScrollBegin, mouse_event.timeStampSeconds,
+ x, y, 0, event.latency));
+ SendGestureEvent(MakeGestureEvent(
+ WebInputEvent::GesturePinchBegin, mouse_event.timeStampSeconds,
+ x, y, 0, event.latency));
+ }
+ if (dx != 0 || dy != 0) {
+ dx = pow(dy < 0 ? 0.998f : 1.002f, fabs(dy));
+ GestureEventWithLatencyInfo gesture_event = MakeGestureEvent(
+ WebInputEvent::GesturePinchUpdate, mouse_event.timeStampSeconds,
+ startX, startY, 0, event.latency);
+ gesture_event.event.data.pinchUpdate.scale = dx;
+ SendGestureEvent(gesture_event);
+ }
+ if (mouse_event.type == WebInputEvent::MouseUp) {
+ SendGestureEvent(MakeGestureEvent(
+ WebInputEvent::GesturePinchEnd, mouse_event.timeStampSeconds,
+ x, y, 0, event.latency));
+ SendGestureEvent(MakeGestureEvent(
+ WebInputEvent::GestureScrollEnd, mouse_event.timeStampSeconds,
+ x, y, 0, event.latency));
+ }
+ break;
+ case WebMouseEvent::ButtonNone:
+ break;
+ }
+}
+
+bool InputRouterImpl::IsInOverscrollGesture() const {
+ OverscrollController* controller = client_->GetOverscrollController();
+ return controller && controller->overscroll_mode() != OVERSCROLL_NONE;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/immediate_input_router.h b/chromium/content/browser/renderer_host/input/input_router_impl.h
index 1d1a0c0e168..e12b7510ccf 100644
--- a/chromium/content/browser/renderer_host/input/immediate_input_router.h
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.h
@@ -2,41 +2,48 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_IMMEDIATE_INPUT_ROUTER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_INPUT_IMMEDIATE_INPUT_ROUTER_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_
#include <queue>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
+#include "content/browser/renderer_host/input/gesture_event_filter.h"
#include "content/browser/renderer_host/input/input_router.h"
+#include "content/browser/renderer_host/input/touch_action_filter.h"
#include "content/browser/renderer_host/input/touch_event_queue.h"
+#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
#include "content/public/browser/native_web_keyboard_event.h"
+namespace IPC {
+class Sender;
+}
+
namespace ui {
struct LatencyInfo;
}
namespace content {
-class GestureEventFilter;
class InputAckHandler;
class InputRouterClient;
-class RenderProcessHost;
+class OverscrollController;
class RenderWidgetHostImpl;
-// A default implementation for browser input event routing. Input commands are
-// forwarded to the renderer immediately upon receipt.
-class CONTENT_EXPORT ImmediateInputRouter
+// A default implementation for browser input event routing.
+class CONTENT_EXPORT InputRouterImpl
: public NON_EXPORTED_BASE(InputRouter),
- public NON_EXPORTED_BASE(TouchEventQueueClient) {
+ public NON_EXPORTED_BASE(GestureEventFilterClient),
+ public NON_EXPORTED_BASE(TouchEventQueueClient),
+ public NON_EXPORTED_BASE(TouchpadTapSuppressionControllerClient) {
public:
- ImmediateInputRouter(RenderProcessHost* process,
- InputRouterClient* client,
- InputAckHandler* ack_handler,
- int routing_id);
- virtual ~ImmediateInputRouter();
+ InputRouterImpl(IPC::Sender* sender,
+ InputRouterClient* client,
+ InputAckHandler* ack_handler,
+ int routing_id);
+ virtual ~InputRouterImpl();
// InputRouter
virtual void Flush() OVERRIDE;
@@ -47,97 +54,131 @@ class CONTENT_EXPORT ImmediateInputRouter
const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE;
virtual void SendKeyboardEvent(
const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info) OVERRIDE;
+ const ui::LatencyInfo& latency_info,
+ bool is_keyboard_shortcut) OVERRIDE;
virtual void SendGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
virtual void SendTouchEvent(
const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
- virtual void SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
- virtual void SendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
- virtual void SendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const OVERRIDE;
virtual bool ShouldForwardTouchEvent() const OVERRIDE;
- virtual bool ShouldForwardGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) const OVERRIDE;
+ virtual void OnViewUpdated(int view_flags) OVERRIDE;
// IPC::Listener
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- GestureEventFilter* gesture_event_filter() {
- return gesture_event_filter_.get();
- }
-
- TouchEventQueue* touch_event_queue() {
- return touch_event_queue_.get();
- }
-
private:
- friend class ImmediateInputRouterTest;
+ friend class InputRouterImplTest;
+ friend class MockRenderWidgetHost;
+
+ // TouchpadTapSuppressionControllerClient
+ virtual void SendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
// TouchEventQueueClient
+ virtual void SendTouchEventImmediately(
+ const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) OVERRIDE;
+ // GetureEventFilterClient
+ virtual void SendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
+ virtual void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) OVERRIDE;
+
bool SendMoveCaret(scoped_ptr<IPC::Message> message);
bool SendSelectRange(scoped_ptr<IPC::Message> message);
bool Send(IPC::Message* message);
- // Transmits the given input event an as an IPC::Message. This is an internal
- // helper for |FilterAndSendInputEvent()| and should not be used otherwise.
- void SendWebInputEvent(const WebKit::WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info,
- bool is_keyboard_shortcut);
-
- // Filters and forwards the given WebInputEvent to |SendWebInputEvent()|. This
- // is an internal helper for |Send*Event()| and should not be used otherwise.
- void FilterAndSendWebInputEvent(const WebKit::WebInputEvent& input_event,
+ // Filters and forwards |input_event| to the appropriate handler.
+ void FilterAndSendWebInputEvent(const blink::WebInputEvent& input_event,
const ui::LatencyInfo& latency_info,
bool is_keyboard_shortcut);
+ // Utility routine for filtering and forwarding |input_event| to the
+ // appropriate handler. |input_event| will be offered to the overscroll
+ // controller, client and renderer, in that order.
+ void OfferToHandlers(const blink::WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_keyboard_shortcut);
+
+ // Returns true if |input_event| was consumed by the overscroll controller.
+ bool OfferToOverscrollController(const blink::WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info);
+
+ // Returns true if |input_event| was consumed by the client.
+ bool OfferToClient(const blink::WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info);
+
+ // Returns true if |input_event| was successfully sent to the renderer
+ // as an async IPC Message.
+ bool OfferToRenderer(const blink::WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_keyboard_shortcut);
+
// IPC message handlers
- void OnInputEventAck(WebKit::WebInputEvent::Type event_type,
+ void OnInputEventAck(blink::WebInputEvent::Type event_type,
InputEventAckState ack_result,
const ui::LatencyInfo& latency_info);
void OnMsgMoveCaretAck();
void OnSelectRangeAck();
void OnHasTouchEventHandlers(bool has_handlers);
-
- // Handle the event ack. Triggered via |OnInputEventAck()| if the event was
- // processed in the renderer, or synchonously from |FilterAndSendInputevent()|
- // if the event was filtered by the |client_| prior to sending.
- void ProcessInputEventAck(WebKit::WebInputEvent::Type event_type,
+ void OnSetTouchAction(content::TouchAction touch_action);
+
+ // Indicates the source of an ack provided to |ProcessInputEventAck()|.
+ // The source is tracked by |current_ack_source_|, which aids in ack routing.
+ enum AckSource {
+ RENDERER,
+ CLIENT,
+ OVERSCROLL_CONTROLLER,
+ IGNORING_DISPOSITION,
+ ACK_SOURCE_NONE
+ };
+ // Note: This function may result in |this| being deleted, and as such
+ // should be the last method called in any internal chain of event handling.
+ void ProcessInputEventAck(blink::WebInputEvent::Type event_type,
InputEventAckState ack_result,
- const ui::LatencyInfo& latency_info);
+ const ui::LatencyInfo& latency_info,
+ AckSource ack_source);
+
+ // Dispatches the ack'ed event to |ack_handler_|.
+ void ProcessKeyboardAck(blink::WebInputEvent::Type type,
+ InputEventAckState ack_result);
+
+ // Forwards a valid |next_mouse_move_| if |type| is MouseMove.
+ void ProcessMouseAck(blink::WebInputEvent::Type type,
+ InputEventAckState ack_result);
+
+ // Dispatches the ack'ed event to |ack_handler_|, forwarding queued events
+ // from |coalesced_mouse_wheel_events_|.
+ void ProcessWheelAck(InputEventAckState ack_result,
+ const ui::LatencyInfo& latency);
+
+ // Forwards the event ack to |gesture_event_filter|, potentially triggering
+ // dispatch of queued gesture events.
+ void ProcessGestureAck(blink::WebInputEvent::Type type,
+ InputEventAckState ack_result,
+ const ui::LatencyInfo& latency);
+
+ // Forwards the event ack to |touch_event_queue_|, potentially triggering
+ // dispatch of queued touch events, or the creation of gesture events.
+ void ProcessTouchAck(InputEventAckState ack_result,
+ const ui::LatencyInfo& latency);
- // Called by ProcessInputEventAck() to process a keyboard event ack message.
- void ProcessKeyboardAck(int type, InputEventAckState ack_result);
+ // Forwards |ack_result| to the client's OverscrollController, if necessary.
+ void ProcessAckForOverscroll(const blink::WebInputEvent& event,
+ InputEventAckState ack_result);
- // Called by ProcessInputEventAck() to process a wheel event ack message.
- // This could result in a task being posted to allow additional wheel
- // input messages to be coalesced.
- void ProcessWheelAck(InputEventAckState ack_result);
+ void SimulateTouchGestureWithMouse(
+ const MouseEventWithLatencyInfo& mouse_event);
- // Called by ProcessInputEventAck() to process a gesture event ack message.
- // This validates the gesture for suppression of touchpad taps and sends one
- // previously queued coalesced gesture if it exists.
- void ProcessGestureAck(int type, InputEventAckState ack_result);
-
- // Called on ProcessInputEventAck() to process a touch event ack message.
- // This can result in a gesture event being generated and sent back to the
- // renderer.
- void ProcessTouchAck(InputEventAckState ack_result,
- const ui::LatencyInfo& latency_info);
-
- void HandleGestureScroll(
- const GestureEventWithLatencyInfo& gesture_event);
+ bool IsInOverscrollGesture() const;
int routing_id() const { return routing_id_; }
- RenderProcessHost* process_;
+ IPC::Sender* sender_;
InputRouterClient* client_;
InputAckHandler* ack_handler_;
int routing_id_;
@@ -194,16 +235,21 @@ private:
// not sent to the renderer.
bool has_touch_handler_;
- // Whether enabling the optimization that sending no touch move events to
- // renderer while scrolling.
- bool enable_no_touch_to_renderer_while_scrolling_;
+ // Whether touch ack timeout handling has been enabled via the command line.
+ bool touch_ack_timeout_enabled_;
+ size_t touch_ack_timeout_delay_ms_;
+
+ // The source of the ack within the scope of |ProcessInputEventAck()|.
+ // Defaults to ACK_SOURCE_NONE.
+ AckSource current_ack_source_;
scoped_ptr<TouchEventQueue> touch_event_queue_;
scoped_ptr<GestureEventFilter> gesture_event_filter_;
+ TouchActionFilter touch_action_filter_;
- DISALLOW_COPY_AND_ASSIGN(ImmediateInputRouter);
+ DISALLOW_COPY_AND_ASSIGN(InputRouterImpl);
};
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_IMMEDIATE_INPUT_ROUTER_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
new file mode 100644
index 00000000000..f51264b0038
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -0,0 +1,894 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/renderer_host/input/gesture_event_filter.h"
+#include "content/browser/renderer_host/input/input_router_client.h"
+#include "content/browser/renderer_host/input/input_router_impl.h"
+#include "content/browser/renderer_host/input/mock_input_ack_handler.h"
+#include "content/browser/renderer_host/input/mock_input_router_client.h"
+#include "content/common/content_constants_internal.h"
+#include "content/common/edit_command.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/common/input/web_input_event_traits.h"
+#include "content/common/input_messages.h"
+#include "content/common/view_messages.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+#if defined(OS_WIN) || defined(USE_AURA)
+#include "content/browser/renderer_host/ui_events_helper.h"
+#include "ui/events/event.h"
+#endif
+
+using base::TimeDelta;
+using blink::WebGestureEvent;
+using blink::WebKeyboardEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+
+namespace content {
+
+namespace {
+
+const WebInputEvent* GetInputEventFromMessage(const IPC::Message& message) {
+ PickleIterator iter(message);
+ const char* data;
+ int data_length;
+ if (!message.ReadData(&iter, &data, &data_length))
+ return NULL;
+ return reinterpret_cast<const WebInputEvent*>(data);
+}
+
+bool GetIsShortcutFromHandleInputEventMessage(const IPC::Message* msg) {
+ InputMsg_HandleInputEvent::Schema::Param param;
+ InputMsg_HandleInputEvent::Read(msg, &param);
+ return param.c;
+}
+
+template<typename MSG_T, typename ARG_T1>
+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, param.a);
+}
+
+template<typename MSG_T, typename ARG_T1, typename ARG_T2>
+void ExpectIPCMessageWithArg2(const IPC::Message* msg,
+ const ARG_T1& arg1,
+ const ARG_T2& arg2) {
+ ASSERT_EQ(MSG_T::ID, msg->type());
+ typename MSG_T::Schema::Param param;
+ ASSERT_TRUE(MSG_T::Read(msg, &param));
+ EXPECT_EQ(arg1, param.a);
+ EXPECT_EQ(arg2, param.b);
+}
+
+#if defined(OS_WIN) || defined(USE_AURA)
+bool TouchEventsAreEquivalent(const ui::TouchEvent& first,
+ const ui::TouchEvent& second) {
+ if (first.type() != second.type())
+ return false;
+ if (first.location() != second.location())
+ return false;
+ if (first.touch_id() != second.touch_id())
+ return false;
+ if (second.time_stamp().InSeconds() != first.time_stamp().InSeconds())
+ return false;
+ return true;
+}
+
+bool EventListIsSubset(const ScopedVector<ui::TouchEvent>& subset,
+ const ScopedVector<ui::TouchEvent>& set) {
+ if (subset.size() > set.size())
+ return false;
+ for (size_t i = 0; i < subset.size(); ++i) {
+ const ui::TouchEvent* first = subset[i];
+ const ui::TouchEvent* second = set[i];
+ bool equivalent = TouchEventsAreEquivalent(*first, *second);
+ if (!equivalent)
+ return false;
+ }
+
+ return true;
+}
+#endif // defined(OS_WIN) || defined(USE_AURA)
+
+} // namespace
+
+class InputRouterImplTest : public testing::Test {
+ public:
+ InputRouterImplTest() {}
+ virtual ~InputRouterImplTest() {}
+
+ protected:
+ // testing::Test
+ virtual void SetUp() OVERRIDE {
+ browser_context_.reset(new TestBrowserContext());
+ process_.reset(new MockRenderProcessHost(browser_context_.get()));
+ client_.reset(new MockInputRouterClient());
+ ack_handler_.reset(new MockInputAckHandler());
+ input_router_.reset(new InputRouterImpl(
+ process_.get(), client_.get(), ack_handler_.get(), MSG_ROUTING_NONE));
+ input_router_->gesture_event_filter_->set_debounce_enabled_for_testing(
+ false);
+ client_->set_input_router(input_router());
+ ack_handler_->set_input_router(input_router());
+ }
+
+ virtual void TearDown() OVERRIDE {
+ // Process all pending tasks to avoid leaks.
+ base::MessageLoop::current()->RunUntilIdle();
+
+ input_router_.reset();
+ client_.reset();
+ process_.reset();
+ browser_context_.reset();
+ }
+
+ void SimulateKeyboardEvent(WebInputEvent::Type type, bool is_shortcut) {
+ WebKeyboardEvent event = SyntheticWebKeyboardEventBuilder::Build(type);
+ NativeWebKeyboardEvent native_event;
+ memcpy(&native_event, &event, sizeof(event));
+ input_router_->SendKeyboardEvent(
+ native_event,
+ ui::LatencyInfo(),
+ is_shortcut);
+ }
+
+ void SimulateWheelEvent(float dX, float dY, int modifiers, bool precise) {
+ input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(
+ SyntheticWebMouseWheelEventBuilder::Build(dX, dY, modifiers, precise),
+ ui::LatencyInfo()));
+ }
+
+ void SimulateMouseMove(int x, int y, int modifiers) {
+ input_router_->SendMouseEvent(MouseEventWithLatencyInfo(
+ SyntheticWebMouseEventBuilder::Build(
+ WebInputEvent::MouseMove, x, y, modifiers),
+ ui::LatencyInfo()));
+ }
+
+ void SimulateWheelEventWithPhase(WebMouseWheelEvent::Phase phase) {
+ input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(
+ SyntheticWebMouseWheelEventBuilder::Build(phase), ui::LatencyInfo()));
+ }
+
+ void SimulateGestureEvent(const WebGestureEvent& gesture) {
+ input_router_->SendGestureEvent(
+ GestureEventWithLatencyInfo(gesture, ui::LatencyInfo()));
+ }
+
+ void SimulateGestureEvent(WebInputEvent::Type type,
+ WebGestureEvent::SourceDevice sourceDevice) {
+ SimulateGestureEvent(
+ SyntheticWebGestureEventBuilder::Build(type, sourceDevice));
+ }
+
+ void SimulateGestureScrollUpdateEvent(float dX, float dY, int modifiers) {
+ SimulateGestureEvent(
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(dX, dY, modifiers));
+ }
+
+ void SimulateGesturePinchUpdateEvent(float scale,
+ float anchorX,
+ float anchorY,
+ int modifiers) {
+ SimulateGestureEvent(
+ SyntheticWebGestureEventBuilder::BuildPinchUpdate(scale,
+ anchorX,
+ anchorY,
+ modifiers));
+ }
+
+ void SimulateGestureFlingStartEvent(
+ float velocityX,
+ float velocityY,
+ WebGestureEvent::SourceDevice sourceDevice) {
+ SimulateGestureEvent(
+ SyntheticWebGestureEventBuilder::BuildFling(velocityX,
+ velocityY,
+ sourceDevice));
+ }
+
+ void SimulateTouchEvent(WebInputEvent::Type type) {
+ touch_event_.ResetPoints();
+ int index = PressTouchPoint(0, 0);
+ switch (type) {
+ case WebInputEvent::TouchStart:
+ // Already handled by |PressTouchPoint()|.
+ break;
+ case WebInputEvent::TouchMove:
+ MoveTouchPoint(index, 5, 5);
+ break;
+ case WebInputEvent::TouchEnd:
+ ReleaseTouchPoint(index);
+ break;
+ case WebInputEvent::TouchCancel:
+ CancelTouchPoint(index);
+ break;
+ default:
+ FAIL() << "Invalid touch event type.";
+ break;
+ }
+ SendTouchEvent();
+ }
+
+ void SetTouchTimestamp(base::TimeDelta timestamp) {
+ touch_event_.SetTimestamp(timestamp);
+ }
+
+ void SendTouchEvent() {
+ input_router_->SendTouchEvent(
+ TouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo()));
+ touch_event_.ResetPoints();
+ }
+
+ int PressTouchPoint(int x, int y) {
+ return touch_event_.PressPoint(x, y);
+ }
+
+ void MoveTouchPoint(int index, int x, int y) {
+ touch_event_.MovePoint(index, x, y);
+ }
+
+ void ReleaseTouchPoint(int index) {
+ touch_event_.ReleasePoint(index);
+ }
+
+ void CancelTouchPoint(int index) {
+ touch_event_.CancelPoint(index);
+ }
+ void SendInputEventACK(blink::WebInputEvent::Type type,
+ InputEventAckState ack_result) {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_HandleInputEvent_ACK(0, type, ack_result,
+ ui::LatencyInfo()));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ InputRouterImpl* input_router() const {
+ return input_router_.get();
+ }
+
+ bool TouchEventQueueEmpty() const {
+ return input_router()->touch_event_queue_->empty();
+ }
+
+ bool TouchEventTimeoutEnabled() const {
+ return input_router()->touch_event_queue_->ack_timeout_enabled();
+ }
+
+ size_t GetSentMessageCountAndResetSink() {
+ size_t count = process_->sink().message_count();
+ process_->sink().ClearMessages();
+ return count;
+ }
+
+ scoped_ptr<MockRenderProcessHost> process_;
+ scoped_ptr<MockInputRouterClient> client_;
+ scoped_ptr<MockInputAckHandler> ack_handler_;
+ scoped_ptr<InputRouterImpl> input_router_;
+
+ private:
+ base::MessageLoopForUI message_loop_;
+ SyntheticWebTouchEvent touch_event_;
+
+ scoped_ptr<TestBrowserContext> browser_context_;
+};
+
+TEST_F(InputRouterImplTest, CoalescesRangeSelection) {
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4))));
+ ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(1, 2),
+ gfx::Point(3, 4));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Send two more messages without acking.
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(5, 6), gfx::Point(7, 8))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(9, 10), gfx::Point(11, 12))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ // Now ack the first message.
+ {
+ scoped_ptr<IPC::Message> response(new ViewHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ // Verify that the two messages are coalesced into one message.
+ ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(9, 10),
+ gfx::Point(11, 12));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Acking the coalesced msg should not send any more msg.
+ {
+ scoped_ptr<IPC::Message> response(new ViewHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+}
+
+TEST_F(InputRouterImplTest, CoalescesCaretMove) {
+ input_router_->SendInput(
+ scoped_ptr<IPC::Message>(new InputMsg_MoveCaret(0, gfx::Point(1, 2))));
+ ExpectIPCMessageWithArg1<InputMsg_MoveCaret>(
+ process_->sink().GetMessageAt(0), gfx::Point(1, 2));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Send two more messages without acking.
+ input_router_->SendInput(
+ scoped_ptr<IPC::Message>(new InputMsg_MoveCaret(0, gfx::Point(5, 6))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(
+ scoped_ptr<IPC::Message>(new InputMsg_MoveCaret(0, gfx::Point(9, 10))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ // Now ack the first message.
+ {
+ scoped_ptr<IPC::Message> response(new ViewHostMsg_MoveCaret_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ // Verify that the two messages are coalesced into one message.
+ ExpectIPCMessageWithArg1<InputMsg_MoveCaret>(
+ process_->sink().GetMessageAt(0), gfx::Point(9, 10));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Acking the coalesced msg should not send any more msg.
+ {
+ scoped_ptr<IPC::Message> response(new ViewHostMsg_MoveCaret_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+}
+
+TEST_F(InputRouterImplTest, HandledInputEvent) {
+ client_->set_filter_state(INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Simulate a keyboard event.
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown, false);
+
+ // Make sure no input event is sent to the renderer.
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ // OnKeyboardEventAck should be triggered without actual ack.
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+
+ // As the event was acked already, keyboard event queue should be
+ // empty.
+ ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
+}
+
+TEST_F(InputRouterImplTest, ClientCanceledKeyboardEvent) {
+ client_->set_filter_state(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+
+ // Simulate a keyboard event that has no consumer.
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown, false);
+
+ // Make sure no input event is sent to the renderer.
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+
+
+ // Simulate a keyboard event that should be dropped.
+ client_->set_filter_state(INPUT_EVENT_ACK_STATE_UNKNOWN);
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown, false);
+
+ // Make sure no input event is sent to the renderer, and no ack is sent.
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+}
+
+TEST_F(InputRouterImplTest, ShortcutKeyboardEvent) {
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown, true);
+ EXPECT_TRUE(GetIsShortcutFromHandleInputEventMessage(
+ process_->sink().GetMessageAt(0)));
+
+ process_->sink().ClearMessages();
+
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown, false);
+ EXPECT_FALSE(GetIsShortcutFromHandleInputEventMessage(
+ process_->sink().GetMessageAt(0)));
+}
+
+TEST_F(InputRouterImplTest, NoncorrespondingKeyEvents) {
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown, false);
+
+ SendInputEventACK(WebInputEvent::KeyUp,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_TRUE(ack_handler_->unexpected_event_ack_called());
+}
+
+// Tests ported from RenderWidgetHostTest --------------------------------------
+
+TEST_F(InputRouterImplTest, HandleKeyEventsWeSent) {
+ // Simulate a keyboard event.
+ SimulateKeyboardEvent(WebInputEvent::RawKeyDown, false);
+ ASSERT_TRUE(input_router_->GetLastKeyboardEvent());
+ EXPECT_EQ(WebInputEvent::RawKeyDown,
+ input_router_->GetLastKeyboardEvent()->type);
+
+ // Make sure we sent the input event to the renderer.
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ InputMsg_HandleInputEvent::ID));
+ process_->sink().ClearMessages();
+
+ // Send the simulated response from the renderer back.
+ SendInputEventACK(WebInputEvent::RawKeyDown,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::RawKeyDown,
+ ack_handler_->acked_keyboard_event().type);
+}
+
+TEST_F(InputRouterImplTest, IgnoreKeyEventsWeDidntSend) {
+ // Send a simulated, unrequested key response. We should ignore this.
+ SendInputEventACK(WebInputEvent::RawKeyDown,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+}
+
+TEST_F(InputRouterImplTest, CoalescesWheelEvents) {
+ // Simulate wheel events.
+ SimulateWheelEvent(0, -5, 0, false); // sent directly
+ SimulateWheelEvent(0, -10, 0, false); // enqueued
+ SimulateWheelEvent(8, -6, 0, false); // coalesced into previous event
+ SimulateWheelEvent(9, -7, 1, false); // enqueued, different modifiers
+
+ // Check that only the first event was sent.
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ InputMsg_HandleInputEvent::ID));
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // Check that the ACK sends the second message immediately.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ // The coalesced events can queue up a delayed ack
+ // so that additional input events can be processed before
+ // we turn off coalescing.
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ InputMsg_HandleInputEvent::ID));
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // One more time.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ InputMsg_HandleInputEvent::ID));
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // After the final ack, the queue should be empty.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+}
+
+TEST_F(InputRouterImplTest,
+ CoalescesWheelEventsQueuedPhaseEndIsNotDropped) {
+ // Send an initial gesture begin and ACK it.
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ WebGestureEvent::Touchpad);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollBegin,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Send a wheel event, should get sent directly.
+ SimulateWheelEvent(0, -5, 0, false);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // Send a wheel phase end event before an ACK is received for the previous
+ // wheel event, which should get queued.
+ SimulateWheelEventWithPhase(WebMouseWheelEvent::PhaseEnded);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+
+ // A gesture event should now result in the queued phase ended event being
+ // transmitted before it.
+ SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
+ WebGestureEvent::Touchpad);
+
+ // Verify the events that were sent.
+ const WebInputEvent* input_event =
+ GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
+ ASSERT_EQ(WebInputEvent::MouseWheel, input_event->type);
+ const WebMouseWheelEvent* wheel_event =
+ static_cast<const WebMouseWheelEvent*>(input_event);
+ ASSERT_EQ(WebMouseWheelEvent::PhaseEnded, wheel_event->phase);
+
+ input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(1));
+ EXPECT_EQ(WebInputEvent::GestureScrollEnd, input_event->type);
+
+ ASSERT_EQ(2U, GetSentMessageCountAndResetSink());
+}
+
+// Tests that touch-events are queued properly.
+TEST_F(InputRouterImplTest, TouchEventQueue) {
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ EXPECT_TRUE(client_->GetAndResetFilterEventCalled());
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_FALSE(TouchEventQueueEmpty());
+
+ // The second touch should not be sent since one is already in queue.
+ MoveTouchPoint(0, 5, 5);
+ SendTouchEvent();
+ EXPECT_FALSE(client_->GetAndResetFilterEventCalled());
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_FALSE(TouchEventQueueEmpty());
+
+ // Receive an ACK for the first touch-event.
+ SendInputEventACK(WebInputEvent::TouchStart,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_FALSE(TouchEventQueueEmpty());
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::TouchStart,
+ ack_handler_->acked_touch_event().event.type);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ SendInputEventACK(WebInputEvent::TouchMove,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_TRUE(TouchEventQueueEmpty());
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::TouchMove,
+ ack_handler_->acked_touch_event().event.type);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+}
+
+// Tests that the touch-queue is emptied if a page stops listening for touch
+// events.
+TEST_F(InputRouterImplTest, TouchEventQueueFlush) {
+ input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
+ EXPECT_TRUE(client_->has_touch_handler());
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_TRUE(TouchEventQueueEmpty());
+
+ EXPECT_TRUE(input_router_->ShouldForwardTouchEvent());
+
+ // Send a touch-press event.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ EXPECT_FALSE(TouchEventQueueEmpty());
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // The page stops listening for touch-events. The touch-event queue should now
+ // be emptied, but none of the queued touch-events should be sent to the
+ // renderer.
+ input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
+ EXPECT_FALSE(client_->has_touch_handler());
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_TRUE(TouchEventQueueEmpty());
+ EXPECT_FALSE(input_router_->ShouldForwardTouchEvent());
+}
+
+#if defined(OS_WIN) || defined(USE_AURA)
+// Tests that the acked events have correct state. (ui::Events are used only on
+// windows and aura)
+TEST_F(InputRouterImplTest, AckedTouchEventState) {
+ input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_TRUE(TouchEventQueueEmpty());
+ EXPECT_TRUE(input_router_->ShouldForwardTouchEvent());
+
+ // Send a bunch of events, and make sure the ACKed events are correct.
+ ScopedVector<ui::TouchEvent> expected_events;
+
+ // 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();
+ timestamp -= base::TimeDelta::FromSeconds(600);
+
+ // Press the first finger.
+ PressTouchPoint(1, 1);
+ SetTouchTimestamp(timestamp);
+ SendTouchEvent();
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ expected_events.push_back(new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
+ gfx::Point(1, 1), 0, timestamp));
+
+ // Move the finger.
+ timestamp += base::TimeDelta::FromSeconds(10);
+ MoveTouchPoint(0, 5, 5);
+ SetTouchTimestamp(timestamp);
+ SendTouchEvent();
+ EXPECT_FALSE(TouchEventQueueEmpty());
+ expected_events.push_back(new ui::TouchEvent(ui::ET_TOUCH_MOVED,
+ gfx::Point(5, 5), 0, timestamp));
+
+ // Now press a second finger.
+ timestamp += base::TimeDelta::FromSeconds(10);
+ PressTouchPoint(2, 2);
+ SetTouchTimestamp(timestamp);
+ SendTouchEvent();
+ EXPECT_FALSE(TouchEventQueueEmpty());
+ expected_events.push_back(new ui::TouchEvent(ui::ET_TOUCH_PRESSED,
+ gfx::Point(2, 2), 1, timestamp));
+
+ // Move both fingers.
+ timestamp += base::TimeDelta::FromSeconds(10);
+ MoveTouchPoint(0, 10, 10);
+ MoveTouchPoint(1, 20, 20);
+ SetTouchTimestamp(timestamp);
+ SendTouchEvent();
+ EXPECT_FALSE(TouchEventQueueEmpty());
+ expected_events.push_back(new ui::TouchEvent(ui::ET_TOUCH_MOVED,
+ gfx::Point(10, 10), 0, timestamp));
+ expected_events.push_back(new ui::TouchEvent(ui::ET_TOUCH_MOVED,
+ gfx::Point(20, 20), 1, timestamp));
+
+ // Receive the ACKs and make sure the generated events from the acked events
+ // are correct.
+ WebInputEvent::Type acks[] = { WebInputEvent::TouchStart,
+ WebInputEvent::TouchMove,
+ WebInputEvent::TouchStart,
+ WebInputEvent::TouchMove };
+
+ TouchEventCoordinateSystem coordinate_system = LOCAL_COORDINATES;
+#if !defined(OS_WIN)
+ coordinate_system = SCREEN_COORDINATES;
+#endif
+ for (size_t i = 0; i < arraysize(acks); ++i) {
+ SendInputEventACK(acks[i],
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(acks[i], ack_handler_->acked_touch_event().event.type);
+ ScopedVector<ui::TouchEvent> acked;
+
+ MakeUITouchEventsFromWebTouchEvents(
+ ack_handler_->acked_touch_event(), &acked, coordinate_system);
+ bool success = EventListIsSubset(acked, expected_events);
+ EXPECT_TRUE(success) << "Failed on step: " << i;
+ if (!success)
+ break;
+ expected_events.erase(expected_events.begin(),
+ expected_events.begin() + acked.size());
+ }
+
+ EXPECT_TRUE(TouchEventQueueEmpty());
+ EXPECT_EQ(0U, expected_events.size());
+}
+#endif // defined(OS_WIN) || defined(USE_AURA)
+
+TEST_F(InputRouterImplTest, UnhandledWheelEvent) {
+ // Simulate wheel events.
+ SimulateWheelEvent(0, -5, 0, false); // sent directly
+ SimulateWheelEvent(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());
+
+ // Check that the correct unhandled wheel event was received.
+ EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -5);
+}
+
+TEST_F(InputRouterImplTest, TouchTypesIgnoringAck) {
+ int start_type = static_cast<int>(WebInputEvent::TouchStart);
+ int end_type = static_cast<int>(WebInputEvent::TouchCancel);
+ for (int i = start_type; i <= end_type; ++i) {
+ WebInputEvent::Type type = static_cast<WebInputEvent::Type>(i);
+ if (!WebInputEventTraits::IgnoresAckDisposition(type))
+ continue;
+
+ // The TouchEventQueue requires an initial TouchStart for it to begin
+ // forwarding other touch event types.
+ if (type != WebInputEvent::TouchStart) {
+ SimulateTouchEvent(WebInputEvent::TouchStart);
+ SendInputEventACK(WebInputEvent::TouchStart,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
+ ASSERT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ ASSERT_EQ(0, client_->in_flight_event_count());
+ }
+
+ SimulateTouchEvent(type);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+ SendInputEventACK(type, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ }
+}
+
+TEST_F(InputRouterImplTest, GestureTypesIgnoringAck) {
+ int start_type = static_cast<int>(WebInputEvent::GestureScrollBegin);
+ int end_type = static_cast<int>(WebInputEvent::GesturePinchUpdate);
+ for (int i = start_type; i <= end_type; ++i) {
+ WebInputEvent::Type type = static_cast<WebInputEvent::Type>(i);
+ if (!WebInputEventTraits::IgnoresAckDisposition(type))
+ continue;
+
+ SimulateGestureEvent(type, WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+ SendInputEventACK(type, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ }
+}
+
+// Test that GestureShowPress, GestureTapDown and GestureTapCancel events don't
+// wait for ACKs.
+TEST_F(InputRouterImplTest, GestureTypesIgnoringAckInterleaved) {
+ // Interleave a few events that do and do not ignore acks, ensuring that
+ // ack-ignoring events aren't dispatched until all prior events which observe
+ // their ack disposition have been dispatched.
+ SimulateGestureEvent(WebInputEvent::GesturePinchUpdate,
+ WebGestureEvent::Touchscreen);
+ ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ SimulateGestureEvent(WebInputEvent::GestureTapDown,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ SimulateGestureEvent(WebInputEvent::GesturePinchUpdate,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureShowPress,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GesturePinchUpdate,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureTapCancel,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ // Now ack each event. Ack-ignoring events should not be dispatched until all
+ // prior events which observe ack disposition have been fired, at which
+ // point they should be sent immediately. They should also have no effect
+ // on the in-flight event count.
+ SendInputEventACK(WebInputEvent::GesturePinchUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ // For events which ignore ack disposition, non-synthetic acks are ignored.
+ SendInputEventACK(WebInputEvent::GestureTapDown,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ SendInputEventACK(WebInputEvent::GesturePinchUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ // For events which ignore ack disposition, non-synthetic acks are ignored.
+ SendInputEventACK(WebInputEvent::GestureShowPress,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ SendInputEventACK(WebInputEvent::GesturePinchUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+
+ // For events which ignore ack disposition, non-synthetic acks are ignored.
+ SendInputEventACK(WebInputEvent::GestureTapCancel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+}
+
+// Test that GestureShowPress events don't get out of order due to
+// ignoring their acks.
+TEST_F(InputRouterImplTest, GestureShowPressIsInOrder) {
+ SimulateGestureEvent(WebInputEvent::GestureTap,
+ WebGestureEvent::Touchscreen);
+
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureShowPress,
+ WebGestureEvent::Touchscreen);
+
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ // The ShowPress, though it ignores ack, is still stuck in the queue
+ // behind the Tap which requires an ack.
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureShowPress,
+ WebGestureEvent::Touchscreen);
+
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ // ShowPress has entered the queue.
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SendInputEventACK(WebInputEvent::GestureTap,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Now that the Tap has been ACKed, the ShowPress events should receive
+ // synthetics acks, and fire immediately.
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(3U, ack_handler_->GetAndResetAckCount());
+}
+
+// Test that touch ack timeout behavior is properly configured via the command
+// line, and toggled by the view update flags.
+TEST_F(InputRouterImplTest, TouchAckTimeoutConfigured) {
+ CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kTouchAckTimeoutDelayMs, "5");
+ TearDown();
+ SetUp();
+ ASSERT_TRUE(TouchEventTimeoutEnabled());
+
+ // A fixed page scale or mobile viewport should disable the touch timeout.
+ input_router()->OnViewUpdated(InputRouter::FIXED_PAGE_SCALE);
+ EXPECT_FALSE(TouchEventTimeoutEnabled());
+
+ input_router()->OnViewUpdated(InputRouter::VIEW_FLAGS_NONE);
+ EXPECT_TRUE(TouchEventTimeoutEnabled());
+
+ input_router()->OnViewUpdated(InputRouter::MOBILE_VIEWPORT);
+ EXPECT_FALSE(TouchEventTimeoutEnabled());
+
+ input_router()->OnViewUpdated(InputRouter::MOBILE_VIEWPORT |
+ InputRouter::FIXED_PAGE_SCALE);
+ EXPECT_FALSE(TouchEventTimeoutEnabled());
+
+ input_router()->OnViewUpdated(InputRouter::VIEW_FLAGS_NONE);
+ EXPECT_TRUE(TouchEventTimeoutEnabled());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router_unittest.cc b/chromium/content/browser/renderer_host/input/input_router_unittest.cc
deleted file mode 100644
index da1ef1efb70..00000000000
--- a/chromium/content/browser/renderer_host/input/input_router_unittest.cc
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/input/input_router_unittest.h"
-
-#include "content/browser/renderer_host/input/input_router.h"
-#include "content/common/input_messages.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-
-#if defined(OS_WIN) || defined(USE_AURA)
-#include "content/browser/renderer_host/ui_events_helper.h"
-#include "ui/events/event.h"
-#endif
-
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebTouchEvent;
-using WebKit::WebTouchPoint;
-
-namespace content {
-
-InputRouterTest::InputRouterTest() {}
-InputRouterTest::~InputRouterTest() {}
-
-void InputRouterTest::SetUp() {
- browser_context_.reset(new TestBrowserContext());
- process_.reset(new MockRenderProcessHost(browser_context_.get()));
- client_.reset(new MockInputRouterClient());
- ack_handler_.reset(new MockInputAckHandler());
- input_router_ = CreateInputRouter(process_.get(),
- client_.get(),
- ack_handler_.get(),
- MSG_ROUTING_NONE);
- client_->set_input_router(input_router_.get());
- ack_handler_->set_input_router(input_router_.get());
-}
-
-void InputRouterTest::TearDown() {
- // Process all pending tasks to avoid InputRouterTest::leaks.
- base::MessageLoop::current()->RunUntilIdle();
-
- input_router_.reset();
- client_.reset();
- process_.reset();
- browser_context_.reset();
-}
-
-void InputRouterTest::SimulateKeyboardEvent(WebInputEvent::Type type) {
- NativeWebKeyboardEvent key_event;
- key_event.type = type;
- key_event.windowsKeyCode = ui::VKEY_L; // non-null made up value.
- input_router_->SendKeyboardEvent(key_event, ui::LatencyInfo());
- client_->ExpectSendCalled(true);
- EXPECT_EQ(type, client_->sent_key_event().type);
- EXPECT_EQ(key_event.windowsKeyCode,
- client_->sent_key_event().windowsKeyCode);
-}
-
-void InputRouterTest::SimulateWheelEvent(float dX,
- float dY,
- int modifiers,
- bool precise) {
- WebMouseWheelEvent wheel_event;
- wheel_event.type = WebInputEvent::MouseWheel;
- wheel_event.deltaX = dX;
- wheel_event.deltaY = dY;
- wheel_event.modifiers = modifiers;
- wheel_event.hasPreciseScrollingDeltas = precise;
- input_router_->SendWheelEvent(
- MouseWheelEventWithLatencyInfo(wheel_event, ui::LatencyInfo()));
- client_->ExpectSendCalled(true);
- EXPECT_EQ(wheel_event.type, client_->sent_wheel_event().event.type);
- EXPECT_EQ(dX, client_->sent_wheel_event().event.deltaX);
-}
-
-void InputRouterTest::SimulateMouseMove(int x, int y, int modifiers) {
- WebMouseEvent mouse_event;
- mouse_event.type = WebInputEvent::MouseMove;
- mouse_event.x = mouse_event.windowX = x;
- mouse_event.y = mouse_event.windowY = y;
- mouse_event.modifiers = modifiers;
- input_router_->SendMouseEvent(
- MouseEventWithLatencyInfo(mouse_event, ui::LatencyInfo()));
- client_->ExpectSendCalled(true);
- EXPECT_EQ(mouse_event.type, client_->sent_mouse_event().event.type);
- EXPECT_EQ(x, client_->sent_mouse_event().event.x);
-}
-
-void InputRouterTest::SimulateWheelEventWithPhase(
- WebMouseWheelEvent::Phase phase) {
- WebMouseWheelEvent wheel_event;
- wheel_event.type = WebInputEvent::MouseWheel;
- wheel_event.phase = phase;
- input_router_->SendWheelEvent(
- MouseWheelEventWithLatencyInfo(wheel_event, ui::LatencyInfo()));
- client_->ExpectSendCalled(true);
- EXPECT_EQ(wheel_event.type, client_->sent_wheel_event().event.type);
- EXPECT_EQ(phase, client_->sent_wheel_event().event.phase);
-}
-
-// Inject provided synthetic WebGestureEvent instance.
-void InputRouterTest::SimulateGestureEventCore(WebInputEvent::Type type,
- WebGestureEvent::SourceDevice sourceDevice,
- WebGestureEvent* gesture_event) {
- gesture_event->type = type;
- gesture_event->sourceDevice = sourceDevice;
- GestureEventWithLatencyInfo gesture_with_latency(
- *gesture_event, ui::LatencyInfo());
- input_router_->SendGestureEvent(gesture_with_latency);
- client_->ExpectSendCalled(true);
- EXPECT_EQ(type, client_->sent_gesture_event().event.type);
- EXPECT_EQ(sourceDevice, client_->sent_gesture_event().event.sourceDevice);
-}
-
-// Inject simple synthetic WebGestureEvent instances.
-void InputRouterTest::SimulateGestureEvent(WebInputEvent::Type type,
- WebGestureEvent::SourceDevice sourceDevice) {
- WebGestureEvent gesture_event;
- SimulateGestureEventCore(type, sourceDevice, &gesture_event);
-}
-
-void InputRouterTest::SimulateGestureScrollUpdateEvent(float dX,
- float dY,
- int modifiers) {
- WebGestureEvent gesture_event;
- gesture_event.data.scrollUpdate.deltaX = dX;
- gesture_event.data.scrollUpdate.deltaY = dY;
- gesture_event.modifiers = modifiers;
- SimulateGestureEventCore(WebInputEvent::GestureScrollUpdate,
- WebGestureEvent::Touchscreen, &gesture_event);
-}
-
-void InputRouterTest::SimulateGesturePinchUpdateEvent(float scale,
- float anchorX,
- float anchorY,
- int modifiers) {
- WebGestureEvent gesture_event;
- gesture_event.data.pinchUpdate.scale = scale;
- gesture_event.x = anchorX;
- gesture_event.y = anchorY;
- gesture_event.modifiers = modifiers;
- SimulateGestureEventCore(WebInputEvent::GesturePinchUpdate,
- WebGestureEvent::Touchscreen, &gesture_event);
-}
-
-// Inject synthetic GestureFlingStart events.
-void InputRouterTest::SimulateGestureFlingStartEvent(
- float velocityX,
- float velocityY,
- WebGestureEvent::SourceDevice sourceDevice) {
- WebGestureEvent gesture_event;
- gesture_event.data.flingStart.velocityX = velocityX;
- gesture_event.data.flingStart.velocityY = velocityY;
- SimulateGestureEventCore(WebInputEvent::GestureFlingStart, sourceDevice,
- &gesture_event);
-}
-
-void InputRouterTest::SimulateTouchEvent(
- int x,
- int y) {
- PressTouchPoint(x, y);
- SendTouchEvent();
-}
-
-// Set the timestamp for the touch-event.
-void InputRouterTest::SetTouchTimestamp(base::TimeDelta timestamp) {
- touch_event_.timeStampSeconds = timestamp.InSecondsF();
-}
-
-// Sends a touch event (irrespective of whether the page has a touch-event
-// handler or not).
-void InputRouterTest::SendTouchEvent() {
- input_router_->SendTouchEvent(
- TouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo()));
-
- // Mark all the points as stationary. And remove the points that have been
- // released.
- int point = 0;
- for (unsigned int i = 0; i < touch_event_.touchesLength; ++i) {
- if (touch_event_.touches[i].state == WebTouchPoint::StateReleased)
- continue;
-
- touch_event_.touches[point] = touch_event_.touches[i];
- touch_event_.touches[point].state =
- WebTouchPoint::StateStationary;
- ++point;
- }
- touch_event_.touchesLength = point;
- touch_event_.type = WebInputEvent::Undefined;
-}
-
-int InputRouterTest::PressTouchPoint(int x, int y) {
- if (touch_event_.touchesLength == touch_event_.touchesLengthCap)
- return -1;
- WebTouchPoint& point =
- touch_event_.touches[touch_event_.touchesLength];
- point.id = touch_event_.touchesLength;
- point.position.x = point.screenPosition.x = x;
- point.position.y = point.screenPosition.y = y;
- point.state = WebTouchPoint::StatePressed;
- point.radiusX = point.radiusY = 1.f;
- ++touch_event_.touchesLength;
- touch_event_.type = WebInputEvent::TouchStart;
- return point.id;
-}
-
-void InputRouterTest::MoveTouchPoint(int index, int x, int y) {
- CHECK(index >= 0 && index < touch_event_.touchesLengthCap);
- WebTouchPoint& point = touch_event_.touches[index];
- point.position.x = point.screenPosition.x = x;
- point.position.y = point.screenPosition.y = y;
- touch_event_.touches[index].state = WebTouchPoint::StateMoved;
- touch_event_.type = WebInputEvent::TouchMove;
-}
-
-void InputRouterTest::ReleaseTouchPoint(int index) {
- CHECK(index >= 0 && index < touch_event_.touchesLengthCap);
- touch_event_.touches[index].state = WebTouchPoint::StateReleased;
- touch_event_.type = WebInputEvent::TouchEnd;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router_unittest.h b/chromium/content/browser/renderer_host/input/input_router_unittest.h
deleted file mode 100644
index 20a68af3fb1..00000000000
--- a/chromium/content/browser/renderer_host/input/input_router_unittest.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_UNITTEST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_UNITTEST_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/renderer_host/input/input_router_client.h"
-#include "content/browser/renderer_host/input/mock_input_ack_handler.h"
-#include "content/browser/renderer_host/input/mock_input_router_client.h"
-#include "content/public/test/mock_render_process_host.h"
-#include "content/public/test/test_browser_context.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-namespace content {
-
-class InputRouter;
-class MockInputRouterClient;
-
-class InputRouterTest : public testing::Test {
- public:
- InputRouterTest();
- virtual ~InputRouterTest();
-
- protected:
- // Called on SetUp.
- virtual scoped_ptr<InputRouter> CreateInputRouter(RenderProcessHost* process,
- InputRouterClient* client,
- InputAckHandler* handler,
- int routing_id) = 0;
-
- // testing::Test
- virtual void SetUp() OVERRIDE;
- virtual void TearDown() OVERRIDE;
-
- void SendInputEventACK(WebKit::WebInputEvent::Type type,
- InputEventAckState ack_result);
- void SimulateKeyboardEvent(WebKit::WebInputEvent::Type type);
- void SimulateWheelEvent(float dX, float dY, int modifiers, bool precise);
- void SimulateMouseMove(int x, int y, int modifiers);
- void SimulateWheelEventWithPhase(WebKit::WebMouseWheelEvent::Phase phase);
- void SimulateGestureEventCore(WebKit::WebInputEvent::Type type,
- WebKit::WebGestureEvent::SourceDevice sourceDevice,
- WebKit::WebGestureEvent* gesture_event);
- void SimulateGestureEvent(WebKit::WebInputEvent::Type type,
- WebKit::WebGestureEvent::SourceDevice sourceDevice);
- void SimulateGestureScrollUpdateEvent(float dX, float dY, int modifiers);
- void SimulateGesturePinchUpdateEvent(float scale,
- float anchorX,
- float anchorY,
- int modifiers);
- void SimulateGestureFlingStartEvent(
- float velocityX,
- float velocityY,
- WebKit::WebGestureEvent::SourceDevice sourceDevice);
- void SimulateTouchEvent(int x, int y);
- void SetTouchTimestamp(base::TimeDelta timestamp);
-
- // Sends a touch event (irrespective of whether the page has a touch-event
- // handler or not).
- void SendTouchEvent();
-
- int PressTouchPoint(int x, int y);
- void MoveTouchPoint(int index, int x, int y);
- void ReleaseTouchPoint(int index);
-
- scoped_ptr<MockRenderProcessHost> process_;
- scoped_ptr<MockInputRouterClient> client_;
- scoped_ptr<MockInputAckHandler> ack_handler_;
- scoped_ptr<InputRouter> input_router_;
-
- private:
- base::MessageLoopForUI message_loop_;
- WebKit::WebTouchEvent touch_event_;
-
- scoped_ptr<TestBrowserContext> browser_context_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_UNITTEST_H_
diff --git a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc
index fc97ab3450b..0ab903f8c84 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc
+++ b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc
@@ -8,12 +8,12 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::TimeDelta;
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebTouchEvent;
-using WebKit::WebTouchPoint;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
namespace content {
@@ -34,28 +34,30 @@ void MockInputAckHandler::OnKeyboardEventAck(
}
void MockInputAckHandler::OnWheelEventAck(
- const WebMouseWheelEvent& event,
- InputEventAckState ack_result) {
+ const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckState ack_result) {
VLOG(1) << __FUNCTION__ << " called!";
- acked_wheel_event_ = event;
+ acked_wheel_event_ = event.event;
RecordAckCalled(ack_result);
}
void MockInputAckHandler::OnTouchEventAck(
const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) {
+ InputEventAckState ack_result) {
VLOG(1) << __FUNCTION__ << " called!";
acked_touch_event_ = event;
RecordAckCalled(ack_result);
if (touch_followup_event_)
- input_router_->SendGestureEvent(*touch_followup_event_);
+ input_router_->SendTouchEvent(*touch_followup_event_);
+ if (gesture_followup_event_)
+ input_router_->SendGestureEvent(*gesture_followup_event_);
}
void MockInputAckHandler::OnGestureEventAck(
- const WebGestureEvent& event,
- InputEventAckState ack_result) {
+ const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) {
VLOG(1) << __FUNCTION__ << " called!";
- acked_gesture_event_ = event;
+ acked_gesture_event_ = event.event;
RecordAckCalled(ack_result);
}
@@ -64,9 +66,10 @@ void MockInputAckHandler::OnUnexpectedEventAck(UnexpectedEventAckType type) {
unexpected_event_ack_called_ = true;
}
-void MockInputAckHandler::ExpectAckCalled(int times) {
- EXPECT_EQ(times, ack_count_);
+size_t MockInputAckHandler::GetAndResetAckCount() {
+ size_t ack_count = ack_count_;
ack_count_ = 0;
+ return ack_count;
}
void MockInputAckHandler::RecordAckCalled(InputEventAckState ack_result) {
diff --git a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h
index 604b26b94cb..88ca9e186fc 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h
+++ b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h
@@ -20,21 +20,25 @@ class MockInputAckHandler : public InputAckHandler {
// InputAckHandler
virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
InputEventAckState ack_result) OVERRIDE;
- virtual void OnWheelEventAck(const WebKit::WebMouseWheelEvent& event,
+ virtual void OnWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
InputEventAckState ack_result) OVERRIDE;
virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) OVERRIDE;
- virtual void OnGestureEventAck(const WebKit::WebGestureEvent& event,
+ virtual void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
InputEventAckState ack_result) OVERRIDE;
virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) OVERRIDE;
- void ExpectAckCalled(int times);
+ size_t GetAndResetAckCount();
void set_input_router(InputRouter* input_router) {
input_router_ = input_router;
}
void set_followup_touch_event(scoped_ptr<GestureEventWithLatencyInfo> event) {
+ gesture_followup_event_ = event.Pass();
+ }
+
+ void set_followup_touch_event(scoped_ptr<TouchEventWithLatencyInfo> event) {
touch_followup_event_ = event.Pass();
}
@@ -46,13 +50,13 @@ class MockInputAckHandler : public InputAckHandler {
const NativeWebKeyboardEvent& acked_keyboard_event() const {
return acked_key_event_;
}
- const WebKit::WebMouseWheelEvent& acked_wheel_event() const {
+ const blink::WebMouseWheelEvent& acked_wheel_event() const {
return acked_wheel_event_;
}
const TouchEventWithLatencyInfo& acked_touch_event() const {
return acked_touch_event_;
}
- const WebKit::WebGestureEvent& acked_gesture_event() const {
+ const blink::WebGestureEvent& acked_gesture_event() const {
return acked_gesture_event_;
}
@@ -61,15 +65,16 @@ class MockInputAckHandler : public InputAckHandler {
InputRouter* input_router_;
- int ack_count_;
+ size_t ack_count_;
bool unexpected_event_ack_called_;
InputEventAckState ack_state_;
NativeWebKeyboardEvent acked_key_event_;
- WebKit::WebMouseWheelEvent acked_wheel_event_;
+ blink::WebMouseWheelEvent acked_wheel_event_;
TouchEventWithLatencyInfo acked_touch_event_;
- WebKit::WebGestureEvent acked_gesture_event_;
+ blink::WebGestureEvent acked_gesture_event_;
- scoped_ptr<GestureEventWithLatencyInfo> touch_followup_event_;
+ scoped_ptr<GestureEventWithLatencyInfo> gesture_followup_event_;
+ scoped_ptr<TouchEventWithLatencyInfo> touch_followup_event_;
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.cc b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
index 86fb53b6b58..436f0b06372 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
@@ -5,15 +5,16 @@
#include "content/browser/renderer_host/input/mock_input_router_client.h"
#include "content/browser/renderer_host/input/input_router.h"
+#include "content/common/input/input_event.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::TimeDelta;
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebTouchEvent;
-using WebKit::WebTouchPoint;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
namespace content {
@@ -22,10 +23,7 @@ MockInputRouterClient::MockInputRouterClient()
in_flight_event_count_(0),
has_touch_handler_(false),
filter_state_(INPUT_EVENT_ACK_STATE_NOT_CONSUMED),
- is_shortcut_(false),
- allow_send_event_(true),
- send_called_(false),
- send_immediately_called_(false),
+ filter_input_event_called_(false),
did_flush_called_(false),
set_needs_flush_called_(false) {}
@@ -33,15 +31,17 @@ MockInputRouterClient::~MockInputRouterClient() {}
InputEventAckState MockInputRouterClient::FilterInputEvent(
const WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info) {
+ const ui::LatencyInfo& latency_info) {
+ filter_input_event_called_ = true;
+ last_filter_event_.reset(new InputEvent(input_event, latency_info, false));
return filter_state_;
}
-void MockInputRouterClient::IncrementInFlightEventCount() {
+void MockInputRouterClient::IncrementInFlightEventCount() {
++in_flight_event_count_;
}
-void MockInputRouterClient::DecrementInFlightEventCount() {
+void MockInputRouterClient::DecrementInFlightEventCount() {
--in_flight_event_count_;
}
@@ -50,91 +50,14 @@ void MockInputRouterClient::OnHasTouchEventHandlers(
has_touch_handler_ = has_handlers;
}
-bool MockInputRouterClient::OnSendKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info,
- bool* is_shortcut) {
- send_called_ = true;
- sent_key_event_ = key_event;
- *is_shortcut = is_shortcut_;
-
- return allow_send_event_;
-}
-
-bool MockInputRouterClient::OnSendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) {
- send_called_ = true;
- sent_wheel_event_ = wheel_event;
-
- return allow_send_event_;
-}
-
-bool MockInputRouterClient::OnSendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) {
- send_called_ = true;
- sent_mouse_event_ = mouse_event;
-
- return allow_send_event_;
-}
-
-bool MockInputRouterClient::OnSendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) {
- send_called_ = true;
- sent_touch_event_ = touch_event;
-
- return allow_send_event_;
-}
-
-bool MockInputRouterClient::OnSendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) {
- send_called_ = true;
- sent_gesture_event_ = gesture_event;
-
- return allow_send_event_ &&
- input_router_->ShouldForwardGestureEvent(gesture_event);
-}
-
-bool MockInputRouterClient::OnSendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) {
- send_immediately_called_ = true;
- immediately_sent_mouse_event_ = mouse_event;
-
- return allow_send_event_;
-}
-
-bool MockInputRouterClient::OnSendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) {
- send_immediately_called_ = true;
- immediately_sent_touch_event_ = touch_event;
-
- return allow_send_event_;
-}
-
-bool MockInputRouterClient::OnSendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) {
- send_immediately_called_ = true;
- immediately_sent_gesture_event_ = gesture_event;
- return allow_send_event_;
-}
-
-void MockInputRouterClient::ExpectSendCalled(bool called) {
- EXPECT_EQ(called, send_called_);
- send_called_ = false;
-}
-
-void MockInputRouterClient::ExpectSendImmediatelyCalled(bool called) {
- EXPECT_EQ(called, send_immediately_called_);
- send_immediately_called_ = false;
-}
-
-void MockInputRouterClient::ExpectNeedsFlushCalled(bool called) {
- EXPECT_EQ(called, set_needs_flush_called_);
- set_needs_flush_called_ = false;
+bool MockInputRouterClient::GetAndResetFilterEventCalled() {
+ bool filter_input_event_called = filter_input_event_called_;
+ filter_input_event_called_ = false;
+ return filter_input_event_called;
}
-void MockInputRouterClient::ExpectDidFlushCalled(bool called) {
- EXPECT_EQ(called, did_flush_called_);
- did_flush_called_ = false;
+OverscrollController* MockInputRouterClient::GetOverscrollController() const {
+ return NULL;
}
void MockInputRouterClient::DidFlush() {
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.h b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
index a02f73891f0..d2ea81d45cc 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
@@ -10,6 +10,7 @@
namespace content {
+class InputEvent;
class InputRouter;
class MockInputRouterClient : public InputRouterClient {
@@ -19,36 +20,16 @@ class MockInputRouterClient : public InputRouterClient {
// InputRouterClient
virtual InputEventAckState FilterInputEvent(
- const WebKit::WebInputEvent& input_event,
+ const blink::WebInputEvent& input_event,
const ui::LatencyInfo& latency_info) OVERRIDE;
virtual void IncrementInFlightEventCount() OVERRIDE;
virtual void DecrementInFlightEventCount() OVERRIDE;
virtual void OnHasTouchEventHandlers(bool has_handlers) OVERRIDE;
- virtual bool OnSendKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info,
- bool* is_shortcut) OVERRIDE;
- virtual bool OnSendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE;
- virtual bool OnSendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
- virtual bool OnSendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
- virtual bool OnSendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
- virtual bool OnSendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
- virtual bool OnSendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
- virtual bool OnSendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
+ virtual OverscrollController* GetOverscrollController() const OVERRIDE;
virtual void DidFlush() OVERRIDE;
virtual void SetNeedsFlush() OVERRIDE;
- void ExpectSendCalled(bool called);
- void ExpectSendImmediatelyCalled(bool called);
- void ExpectNeedsFlushCalled(bool called);
- void ExpectDidFlushCalled(bool called);
+ bool GetAndResetFilterEventCalled();
void set_input_router(InputRouter* input_router) {
input_router_ = input_router;
@@ -61,39 +42,12 @@ class MockInputRouterClient : public InputRouterClient {
int in_flight_event_count() const {
return in_flight_event_count_;
}
- void set_is_shortcut(bool is_shortcut) {
- is_shortcut_ = is_shortcut;
- }
void set_allow_send_event(bool allow) {
- allow_send_event_ = allow;
- }
- const NativeWebKeyboardEvent& sent_key_event() {
- return sent_key_event_;
- }
- const MouseWheelEventWithLatencyInfo& sent_wheel_event() {
- return sent_wheel_event_;
- }
- const MouseEventWithLatencyInfo& sent_mouse_event() {
- return sent_mouse_event_;
- }
- const GestureEventWithLatencyInfo& sent_gesture_event() {
- return sent_gesture_event_;
- }
- const MouseEventWithLatencyInfo& immediately_sent_mouse_event() {
- return immediately_sent_mouse_event_;
- }
- const TouchEventWithLatencyInfo& immediately_sent_touch_event() {
- return immediately_sent_touch_event_;
- }
- const GestureEventWithLatencyInfo& immediately_sent_gesture_event() {
- return immediately_sent_gesture_event_;
+ filter_state_ = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
}
bool did_flush_called() const { return did_flush_called_; }
bool needs_flush_called() const { return set_needs_flush_called_; }
- void set_followup_touch_event(scoped_ptr<GestureEventWithLatencyInfo> event) {
- touch_followup_event_ = event.Pass();
- }
private:
InputRouter* input_router_;
@@ -102,23 +56,11 @@ class MockInputRouterClient : public InputRouterClient {
InputEventAckState filter_state_;
- bool is_shortcut_;
- bool allow_send_event_;
- bool send_called_;
- NativeWebKeyboardEvent sent_key_event_;
- MouseWheelEventWithLatencyInfo sent_wheel_event_;
- MouseEventWithLatencyInfo sent_mouse_event_;
- TouchEventWithLatencyInfo sent_touch_event_;
- GestureEventWithLatencyInfo sent_gesture_event_;
-
- bool send_immediately_called_;
- MouseEventWithLatencyInfo immediately_sent_mouse_event_;
- TouchEventWithLatencyInfo immediately_sent_touch_event_;
- GestureEventWithLatencyInfo immediately_sent_gesture_event_;
+ bool filter_input_event_called_;
+ scoped_ptr<InputEvent> last_filter_event_;
bool did_flush_called_;
bool set_needs_flush_called_;
- scoped_ptr<GestureEventWithLatencyInfo> touch_followup_event_;
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture.cc
new file mode 100644
index 00000000000..8b2b3bedbe6
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture.cc
@@ -0,0 +1,46 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/synthetic_gesture.h"
+
+#include "base/logging.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
+#include "content/browser/renderer_host/input/synthetic_pinch_gesture.h"
+#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
+#include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
+
+namespace content {
+namespace {
+
+template <typename GestureType, typename GestureParamsType>
+static scoped_ptr<SyntheticGesture> CreateGesture(
+ const SyntheticGestureParams& gesture_params) {
+ return scoped_ptr<SyntheticGesture>(
+ new GestureType(*GestureParamsType::Cast(&gesture_params)));
+}
+
+} // namespace
+
+SyntheticGesture::SyntheticGesture() {}
+
+SyntheticGesture::~SyntheticGesture() {}
+
+scoped_ptr<SyntheticGesture> SyntheticGesture::Create(
+ const SyntheticGestureParams& gesture_params) {
+ switch (gesture_params.GetGestureType()) {
+ case SyntheticGestureParams::SMOOTH_SCROLL_GESTURE:
+ return CreateGesture<SyntheticSmoothScrollGesture,
+ SyntheticSmoothScrollGestureParams>(gesture_params);
+ case SyntheticGestureParams::PINCH_GESTURE:
+ return CreateGesture<SyntheticPinchGesture,
+ SyntheticPinchGestureParams>(gesture_params);
+ case SyntheticGestureParams::TAP_GESTURE:
+ return CreateGesture<SyntheticTapGesture,
+ SyntheticTapGestureParams>(gesture_params);
+ }
+ NOTREACHED() << "Invalid synthetic gesture type";
+ return scoped_ptr<SyntheticGesture>();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_gesture.h
new file mode 100644
index 00000000000..c10c2fea214
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "content/common/input/synthetic_gesture_params.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace content {
+
+class SyntheticGestureTarget;
+
+// Base class for synthetic gesture implementations. A synthetic gesture class
+// is responsible for forwaring InputEvents, simulating the gesture, to a
+// SyntheticGestureTarget.
+//
+// Adding new gesture types involved the following steps:
+// 1) Create a sub-type of SyntheticGesture that implements the gesture.
+// 2) Extend SyntheticGesture::Create with the new class.
+// 3) Add at least one unit test per supported input source type (touch,
+// mouse, etc) to SyntheticGestureController unit tests. The unit tests
+// only checks basic functionality and termination. If the gesture is
+// hooked up to Telemetry its correctness can additionally be tested there.
+class CONTENT_EXPORT SyntheticGesture {
+ public:
+ SyntheticGesture();
+ virtual ~SyntheticGesture();
+
+ static scoped_ptr<SyntheticGesture> Create(
+ const SyntheticGestureParams& gesture_params);
+
+ enum Result {
+ GESTURE_RUNNING,
+ GESTURE_FINISHED,
+ GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED,
+ GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM,
+ GESTURE_RESULT_MAX = GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM
+ };
+
+ // Update the state of the gesture and forward the appropriate events to the
+ // platform. This function is called repeatedly by the synthetic gesture
+ // controller until it stops returning GESTURE_RUNNING.
+ virtual Result ForwardInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SyntheticGesture);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_H_
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc
new file mode 100644
index 00000000000..0529354ac38
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc
@@ -0,0 +1,80 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
+
+#include "base/debug/trace_event.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
+#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
+#include "content/common/input_messages.h"
+#include "content/public/browser/render_widget_host.h"
+
+namespace content {
+
+SyntheticGestureController::SyntheticGestureController(
+ scoped_ptr<SyntheticGestureTarget> gesture_target)
+ : gesture_target_(gesture_target.Pass()) {}
+
+SyntheticGestureController::~SyntheticGestureController() {}
+
+void SyntheticGestureController::QueueSyntheticGesture(
+ scoped_ptr<SyntheticGesture> synthetic_gesture) {
+ DCHECK(synthetic_gesture);
+
+ pending_gesture_queue_.push_back(synthetic_gesture.release());
+
+ // Start forwarding input events if the queue was previously empty.
+ if (pending_gesture_queue_.size() == 1)
+ StartGesture(*pending_gesture_queue_.front());
+}
+
+void SyntheticGestureController::Flush(base::TimeTicks timestamp) {
+ if (pending_gesture_queue_.empty())
+ return;
+
+ if (last_tick_time_.is_null()) {
+ last_tick_time_ = timestamp;
+ gesture_target_->SetNeedsFlush();
+ return;
+ }
+
+ base::TimeDelta interval = timestamp - last_tick_time_;
+ last_tick_time_ = timestamp;
+ SyntheticGesture::Result result =
+ pending_gesture_queue_.front()->ForwardInputEvents(interval,
+ gesture_target_.get());
+
+ if (result == SyntheticGesture::GESTURE_RUNNING) {
+ gesture_target_->SetNeedsFlush();
+ return;
+ }
+
+ StopGesture(*pending_gesture_queue_.front(), result);
+ pending_gesture_queue_.erase(pending_gesture_queue_.begin());
+
+ if (!pending_gesture_queue_.empty()) {
+ StartGesture(*pending_gesture_queue_.front());
+ } else {
+ // Reset last_tick_time_ so that we don't use an old value when a new
+ // gestures is queued.
+ last_tick_time_ = base::TimeTicks();
+ }
+}
+
+void SyntheticGestureController::StartGesture(const SyntheticGesture& gesture) {
+ TRACE_EVENT_ASYNC_BEGIN0("benchmark", "SyntheticGestureController::running",
+ &gesture);
+ gesture_target_->SetNeedsFlush();
+}
+
+void SyntheticGestureController::StopGesture(
+ const SyntheticGesture& gesture, SyntheticGesture::Result result) {
+ DCHECK_NE(result, SyntheticGesture::GESTURE_RUNNING);
+ TRACE_EVENT_ASYNC_END0("benchmark", "SyntheticGestureController::running",
+ &gesture);
+
+ gesture_target_->OnSyntheticGestureCompleted(result);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h
new file mode 100644
index 00000000000..ed9cec77653
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h
@@ -0,0 +1,49 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_CONTROLLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_CONTROLLER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/time/time.h"
+#include "content/browser/renderer_host/input/synthetic_gesture.h"
+#include "content/common/content_export.h"
+#include "content/common/input/synthetic_gesture_params.h"
+
+namespace content {
+
+class SyntheticGestureTarget;
+
+// Controls a synthetic gesture.
+// Repeatedly invokes the gesture object's ForwardInputEvent method to send
+// input events to the platform until the gesture has finished.
+class CONTENT_EXPORT SyntheticGestureController {
+ public:
+ explicit SyntheticGestureController(
+ scoped_ptr<SyntheticGestureTarget> gesture_target);
+ virtual ~SyntheticGestureController();
+
+ void QueueSyntheticGesture(
+ scoped_ptr<SyntheticGesture> synthetic_gesture);
+
+ // Forward input events of the currently processed gesture.
+ void Flush(base::TimeTicks timestamp);
+
+ private:
+ void StartGesture(const SyntheticGesture& gesture);
+ void StopGesture(const SyntheticGesture& gesture,
+ SyntheticGesture::Result result);
+
+ scoped_ptr<SyntheticGestureTarget> gesture_target_;
+ ScopedVector<SyntheticGesture> pending_gesture_queue_;
+
+ base::TimeTicks last_tick_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyntheticGestureController);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_CONTROLLER_H_
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
new file mode 100644
index 00000000000..f449e5774ca
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -0,0 +1,814 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "content/browser/renderer_host/input/synthetic_gesture.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
+#include "content/browser/renderer_host/input/synthetic_pinch_gesture.h"
+#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
+#include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
+#include "content/browser/renderer_host/render_widget_host_delegate.h"
+#include "content/common/input/input_event.h"
+#include "content/common/input/synthetic_pinch_gesture_params.h"
+#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
+#include "content/common/input/synthetic_tap_gesture_params.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/test/test_render_view_host.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/point_f.h"
+#include "ui/gfx/vector2d.h"
+#include "ui/gfx/vector2d_f.h"
+
+namespace content {
+
+namespace {
+
+const int kFlushInputRateInMs = 16;
+const int kPointerAssumedStoppedTimeMs = 43;
+const int kTouchSlopInDips = 7;
+
+class MockSyntheticGesture : public SyntheticGesture {
+ public:
+ MockSyntheticGesture(bool* finished, int num_steps)
+ : finished_(finished),
+ num_steps_(num_steps),
+ step_count_(0) {
+ *finished_ = false;
+ }
+ virtual ~MockSyntheticGesture() {}
+
+ virtual Result ForwardInputEvents(const base::TimeDelta& interval,
+ SyntheticGestureTarget* target) OVERRIDE {
+ step_count_++;
+ if (step_count_ == num_steps_) {
+ *finished_ = true;
+ return SyntheticGesture::GESTURE_FINISHED;
+ } else if (step_count_ > num_steps_) {
+ *finished_ = true;
+ // Return arbitrary failure.
+ return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
+ }
+
+ return SyntheticGesture::GESTURE_RUNNING;
+ }
+
+ protected:
+ bool* finished_;
+ int num_steps_;
+ int step_count_;
+};
+
+class MockSyntheticGestureTarget : public SyntheticGestureTarget {
+ public:
+ MockSyntheticGestureTarget()
+ : num_success_(0),
+ num_failure_(0),
+ flush_requested_(false),
+ pointer_assumed_stopped_time_ms_(kPointerAssumedStoppedTimeMs) {}
+ virtual ~MockSyntheticGestureTarget() {}
+
+ // SyntheticGestureTarget:
+ virtual void DispatchInputEventToPlatform(const InputEvent& event) OVERRIDE {}
+
+ virtual void OnSyntheticGestureCompleted(
+ SyntheticGesture::Result result) OVERRIDE {
+ DCHECK_NE(result, SyntheticGesture::GESTURE_RUNNING);
+ if (result == SyntheticGesture::GESTURE_FINISHED)
+ num_success_++;
+ else
+ num_failure_++;
+ }
+
+ virtual void SetNeedsFlush() OVERRIDE {
+ flush_requested_ = true;
+ }
+
+ virtual SyntheticGestureParams::GestureSourceType
+ GetDefaultSyntheticGestureSourceType() const OVERRIDE {
+ return SyntheticGestureParams::TOUCH_INPUT;
+ }
+ virtual bool SupportsSyntheticGestureSourceType(
+ SyntheticGestureParams::GestureSourceType gesture_source_type)
+ const OVERRIDE {
+ return true;
+ }
+
+ virtual base::TimeDelta PointerAssumedStoppedTime() const OVERRIDE {
+ return base::TimeDelta::FromMilliseconds(pointer_assumed_stopped_time_ms_);
+ }
+
+ void set_pointer_assumed_stopped_time_ms(int time_ms) {
+ pointer_assumed_stopped_time_ms_ = time_ms;
+ }
+
+ virtual int GetTouchSlopInDips() const OVERRIDE {
+ return kTouchSlopInDips;
+ }
+
+ int num_success() const { return num_success_; }
+ int num_failure() const { return num_failure_; }
+
+ bool flush_requested() const { return flush_requested_; }
+ void ClearFlushRequest() { flush_requested_ = false; }
+
+ private:
+ int num_success_;
+ int num_failure_;
+
+ bool flush_requested_;
+
+ int pointer_assumed_stopped_time_ms_;
+};
+
+class MockSyntheticSmoothScrollGestureTarget
+ : public MockSyntheticGestureTarget {
+ public:
+ MockSyntheticSmoothScrollGestureTarget() {}
+ virtual ~MockSyntheticSmoothScrollGestureTarget() {}
+
+ gfx::Vector2dF scroll_distance() const { return scroll_distance_; }
+
+ protected:
+ gfx::Vector2dF scroll_distance_;
+};
+
+class MockSyntheticSmoothScrollMouseTarget
+ : public MockSyntheticSmoothScrollGestureTarget {
+ public:
+ MockSyntheticSmoothScrollMouseTarget() {}
+ virtual ~MockSyntheticSmoothScrollMouseTarget() {}
+
+ virtual void DispatchInputEventToPlatform(const InputEvent& event) OVERRIDE {
+ const blink::WebInputEvent* web_event = event.web_event.get();
+ ASSERT_EQ(web_event->type, blink::WebInputEvent::MouseWheel);
+ const blink::WebMouseWheelEvent* mouse_wheel_event =
+ static_cast<const blink::WebMouseWheelEvent*>(web_event);
+ scroll_distance_ -= gfx::Vector2dF(mouse_wheel_event->deltaX,
+ mouse_wheel_event->deltaY);
+ }
+};
+
+class MockSyntheticSmoothScrollTouchTarget
+ : public MockSyntheticSmoothScrollGestureTarget {
+ public:
+ MockSyntheticSmoothScrollTouchTarget()
+ : started_(false) {}
+ virtual ~MockSyntheticSmoothScrollTouchTarget() {}
+
+ virtual void DispatchInputEventToPlatform(const InputEvent& event) OVERRIDE {
+ const blink::WebInputEvent* web_event = event.web_event.get();
+ ASSERT_TRUE(blink::WebInputEvent::isTouchEventType(web_event->type));
+ const blink::WebTouchEvent* touch_event =
+ static_cast<const blink::WebTouchEvent*>(web_event);
+ ASSERT_EQ(touch_event->touchesLength, (unsigned int)1);
+
+ if (!started_) {
+ ASSERT_EQ(touch_event->type, blink::WebInputEvent::TouchStart);
+ anchor_.SetPoint(touch_event->touches[0].position.x,
+ touch_event->touches[0].position.y);
+ started_ = true;
+ } else {
+ ASSERT_NE(touch_event->type, blink::WebInputEvent::TouchStart);
+ ASSERT_NE(touch_event->type, blink::WebInputEvent::TouchCancel);
+ // Ignore move events.
+
+ if (touch_event->type == blink::WebInputEvent::TouchEnd)
+ scroll_distance_ =
+ anchor_ - gfx::PointF(touch_event->touches[0].position.x,
+ touch_event->touches[0].position.y);
+ }
+ }
+
+ protected:
+ gfx::Point anchor_;
+ bool started_;
+};
+
+class MockSyntheticPinchTouchTarget : public MockSyntheticGestureTarget {
+ public:
+ enum ZoomDirection {
+ ZOOM_DIRECTION_UNKNOWN,
+ ZOOM_IN,
+ ZOOM_OUT
+ };
+
+ MockSyntheticPinchTouchTarget()
+ : total_num_pixels_covered_(0),
+ last_pointer_distance_(0),
+ zoom_direction_(ZOOM_DIRECTION_UNKNOWN),
+ started_(false) {}
+ virtual ~MockSyntheticPinchTouchTarget() {}
+
+ virtual void DispatchInputEventToPlatform(const InputEvent& event) OVERRIDE {
+ const blink::WebInputEvent* web_event = event.web_event.get();
+ ASSERT_TRUE(blink::WebInputEvent::isTouchEventType(web_event->type));
+ const blink::WebTouchEvent* touch_event =
+ static_cast<const blink::WebTouchEvent*>(web_event);
+ ASSERT_EQ(touch_event->touchesLength, (unsigned int)2);
+
+ if (!started_) {
+ ASSERT_EQ(touch_event->type, blink::WebInputEvent::TouchStart);
+
+ start_0_ = gfx::Point(touch_event->touches[0].position);
+ start_1_ = gfx::Point(touch_event->touches[1].position);
+ last_pointer_distance_ = (start_0_ - start_1_).Length();
+
+ started_ = true;
+ } else {
+ ASSERT_NE(touch_event->type, blink::WebInputEvent::TouchStart);
+ ASSERT_NE(touch_event->type, blink::WebInputEvent::TouchCancel);
+
+ gfx::PointF current_0 = gfx::Point(touch_event->touches[0].position);
+ gfx::PointF current_1 = gfx::Point(touch_event->touches[1].position);
+
+ total_num_pixels_covered_ =
+ (current_0 - start_0_).Length() + (current_1 - start_1_).Length();
+ float pointer_distance = (current_0 - current_1).Length();
+
+ if (last_pointer_distance_ != pointer_distance) {
+ if (zoom_direction_ == ZOOM_DIRECTION_UNKNOWN)
+ zoom_direction_ =
+ ComputeZoomDirection(last_pointer_distance_, pointer_distance);
+ else
+ EXPECT_EQ(
+ zoom_direction_,
+ ComputeZoomDirection(last_pointer_distance_, pointer_distance));
+ }
+
+ last_pointer_distance_ = pointer_distance;
+ }
+ }
+
+ float total_num_pixels_covered() const { return total_num_pixels_covered_; }
+ ZoomDirection zoom_direction() const { return zoom_direction_; }
+
+ private:
+ ZoomDirection ComputeZoomDirection(float last_pointer_distance,
+ float current_pointer_distance) {
+ DCHECK_NE(last_pointer_distance, current_pointer_distance);
+ return last_pointer_distance < current_pointer_distance ? ZOOM_IN
+ : ZOOM_OUT;
+ }
+
+ float total_num_pixels_covered_;
+ float last_pointer_distance_;
+ ZoomDirection zoom_direction_;
+ gfx::PointF start_0_;
+ gfx::PointF start_1_;
+ bool started_;
+};
+
+class MockSyntheticTapGestureTarget : public MockSyntheticGestureTarget {
+ public:
+ MockSyntheticTapGestureTarget() : state_(NOT_STARTED) {}
+ virtual ~MockSyntheticTapGestureTarget() {}
+
+ bool GestureFinished() const { return state_ == FINISHED; }
+ gfx::Point position() const { return position_; }
+
+ protected:
+ enum GestureState {
+ NOT_STARTED,
+ STARTED,
+ FINISHED
+ };
+
+ gfx::Point position_;
+ GestureState state_;
+};
+
+class MockSyntheticTapTouchTarget : public MockSyntheticTapGestureTarget {
+ public:
+ MockSyntheticTapTouchTarget() {}
+ virtual ~MockSyntheticTapTouchTarget() {}
+
+ virtual void DispatchInputEventToPlatform(const InputEvent& event) OVERRIDE {
+ const blink::WebInputEvent* web_event = event.web_event.get();
+ ASSERT_TRUE(blink::WebInputEvent::isTouchEventType(web_event->type));
+ const blink::WebTouchEvent* touch_event =
+ static_cast<const blink::WebTouchEvent*>(web_event);
+ ASSERT_EQ(touch_event->touchesLength, (unsigned int)1);
+
+ switch (state_) {
+ case NOT_STARTED:
+ EXPECT_EQ(touch_event->type, blink::WebInputEvent::TouchStart);
+ position_ = gfx::Point(touch_event->touches[0].position);
+ state_ = STARTED;
+ break;
+ case STARTED:
+ EXPECT_EQ(touch_event->type, blink::WebInputEvent::TouchEnd);
+ EXPECT_EQ(position_, gfx::Point(touch_event->touches[0].position));
+ state_ = FINISHED;
+ break;
+ case FINISHED:
+ EXPECT_FALSE(true);
+ break;
+ }
+ }
+};
+
+class MockSyntheticTapMouseTarget : public MockSyntheticTapGestureTarget {
+ public:
+ MockSyntheticTapMouseTarget() {}
+ virtual ~MockSyntheticTapMouseTarget() {}
+
+ virtual void DispatchInputEventToPlatform(const InputEvent& event) OVERRIDE {
+ const blink::WebInputEvent* web_event = event.web_event.get();
+ ASSERT_TRUE(blink::WebInputEvent::isMouseEventType(web_event->type));
+ const blink::WebMouseEvent* mouse_event =
+ static_cast<const blink::WebMouseEvent*>(web_event);
+
+ switch (state_) {
+ case NOT_STARTED:
+ EXPECT_EQ(mouse_event->type, blink::WebInputEvent::MouseDown);
+ EXPECT_EQ(mouse_event->button, blink::WebMouseEvent::ButtonLeft);
+ EXPECT_EQ(mouse_event->clickCount, 1);
+ position_ = gfx::Point(mouse_event->x, mouse_event->y);
+ state_ = STARTED;
+ break;
+ case STARTED:
+ EXPECT_EQ(mouse_event->type, blink::WebInputEvent::MouseUp);
+ EXPECT_EQ(mouse_event->button, blink::WebMouseEvent::ButtonLeft);
+ EXPECT_EQ(mouse_event->clickCount, 1);
+ EXPECT_EQ(position_, gfx::Point(mouse_event->x, mouse_event->y));
+ state_ = FINISHED;
+ break;
+ case FINISHED:
+ EXPECT_FALSE(true);
+ break;
+ }
+ }
+};
+
+class SyntheticGestureControllerTest : public testing::Test {
+ public:
+ SyntheticGestureControllerTest() {}
+ virtual ~SyntheticGestureControllerTest() {}
+
+ protected:
+ template<typename MockGestureTarget>
+ void CreateControllerAndTarget() {
+ target_ = new MockGestureTarget();
+
+ controller_.reset(new SyntheticGestureController(
+ scoped_ptr<SyntheticGestureTarget>(target_)));
+ }
+
+ virtual void SetUp() OVERRIDE {
+ start_time_ = base::TimeTicks::Now();
+ time_ = start_time_;
+ }
+
+ virtual void TearDown() OVERRIDE {
+ controller_.reset();
+ target_ = NULL;
+ time_ = base::TimeTicks();
+ }
+
+ void FlushInputUntilComplete() {
+ while (target_->flush_requested()) {
+ target_->ClearFlushRequest();
+ time_ += base::TimeDelta::FromMilliseconds(kFlushInputRateInMs);
+ controller_->Flush(time_);
+ }
+ }
+
+ base::TimeDelta GetTotalTime() const { return time_ - start_time_; }
+
+ MockSyntheticGestureTarget* target_;
+ scoped_ptr<SyntheticGestureController> controller_;
+ base::TimeTicks start_time_;
+ base::TimeTicks time_;
+};
+
+TEST_F(SyntheticGestureControllerTest, SingleGesture) {
+ CreateControllerAndTarget<MockSyntheticGestureTarget>();
+
+ bool finished;
+ scoped_ptr<MockSyntheticGesture> gesture(
+ new MockSyntheticGesture(&finished, 3));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ EXPECT_TRUE(finished);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+}
+
+TEST_F(SyntheticGestureControllerTest, GestureFailed) {
+ CreateControllerAndTarget<MockSyntheticGestureTarget>();
+
+ bool finished;
+ scoped_ptr<MockSyntheticGesture> gesture(
+ new MockSyntheticGesture(&finished, 0));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ EXPECT_TRUE(finished);
+ EXPECT_EQ(1, target_->num_failure());
+ EXPECT_EQ(0, target_->num_success());
+}
+
+TEST_F(SyntheticGestureControllerTest, SuccessiveGestures) {
+ CreateControllerAndTarget<MockSyntheticGestureTarget>();
+
+ bool finished_1, finished_2;
+ scoped_ptr<MockSyntheticGesture> gesture_1(
+ new MockSyntheticGesture(&finished_1, 2));
+ scoped_ptr<MockSyntheticGesture> gesture_2(
+ new MockSyntheticGesture(&finished_2, 4));
+
+ // Queue first gesture and wait for it to finish
+ controller_->QueueSyntheticGesture(gesture_1.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ EXPECT_TRUE(finished_1);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+
+ // Queue second gesture.
+ controller_->QueueSyntheticGesture(gesture_2.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ EXPECT_TRUE(finished_2);
+ EXPECT_EQ(2, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+}
+
+TEST_F(SyntheticGestureControllerTest, TwoGesturesInFlight) {
+ CreateControllerAndTarget<MockSyntheticGestureTarget>();
+
+ bool finished_1, finished_2;
+ scoped_ptr<MockSyntheticGesture> gesture_1(
+ new MockSyntheticGesture(&finished_1, 2));
+ scoped_ptr<MockSyntheticGesture> gesture_2(
+ new MockSyntheticGesture(&finished_2, 4));
+
+ controller_->QueueSyntheticGesture(gesture_1.PassAs<SyntheticGesture>());
+ controller_->QueueSyntheticGesture(gesture_2.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ EXPECT_TRUE(finished_1);
+ EXPECT_TRUE(finished_2);
+
+ EXPECT_EQ(2, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+}
+
+gfx::Vector2d AddTouchSlopToVector(const gfx::Vector2d& vector,
+ SyntheticGestureTarget* target) {
+ const int kTouchSlop = target->GetTouchSlopInDips();
+
+ int x = vector.x();
+ if (x > 0)
+ x += kTouchSlop;
+ else if (x < 0)
+ x -= kTouchSlop;
+
+ int y = vector.y();
+ if (y > 0)
+ y += kTouchSlop;
+ else if (y < 0)
+ y -= kTouchSlop;
+
+ return gfx::Vector2d(x, y);
+}
+
+TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchVertical) {
+ CreateControllerAndTarget<MockSyntheticSmoothScrollTouchTarget>();
+
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.distance = gfx::Vector2d(0, 123);
+ params.anchor.SetPoint(89, 32);
+
+ scoped_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target =
+ static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ EXPECT_EQ(AddTouchSlopToVector(params.distance, target_),
+ smooth_scroll_target->scroll_distance());
+}
+
+TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchHorizontal) {
+ CreateControllerAndTarget<MockSyntheticSmoothScrollTouchTarget>();
+
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.distance = gfx::Vector2d(-234, 0);
+ params.anchor.SetPoint(12, -23);
+
+ scoped_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target =
+ static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ EXPECT_EQ(AddTouchSlopToVector(params.distance, target_),
+ smooth_scroll_target->scroll_distance());
+}
+
+void CheckIsWithinRange(float scroll_distance,
+ int target_distance,
+ SyntheticGestureTarget* target) {
+ if (target_distance > 0) {
+ EXPECT_LE(target_distance, scroll_distance);
+ EXPECT_LE(scroll_distance, target_distance + target->GetTouchSlopInDips());
+ } else {
+ EXPECT_GE(target_distance, scroll_distance);
+ EXPECT_GE(scroll_distance, target_distance - target->GetTouchSlopInDips());
+ }
+}
+
+void CheckScrollDistanceIsWithinRange(const gfx::Vector2dF& scroll_distance,
+ const gfx::Vector2d& target_distance,
+ SyntheticGestureTarget* target) {
+ CheckIsWithinRange(scroll_distance.x(), target_distance.x(), target);
+ CheckIsWithinRange(scroll_distance.y(), target_distance.y(), target);
+}
+
+TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchDiagonal) {
+ CreateControllerAndTarget<MockSyntheticSmoothScrollTouchTarget>();
+
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.distance = gfx::Vector2d(413, -83);
+ params.anchor.SetPoint(0, 7);
+
+ scoped_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target =
+ static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ CheckScrollDistanceIsWithinRange(
+ smooth_scroll_target->scroll_distance(), params.distance, target_);
+}
+
+TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchLongStop) {
+ CreateControllerAndTarget<MockSyntheticSmoothScrollTouchTarget>();
+
+ // Create a smooth scroll with a short distance and set the pointer assumed
+ // stopped time high, so that the stopping should dominate the time the
+ // gesture is active.
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.distance = gfx::Vector2d(21, -12);
+ params.prevent_fling = true;
+ params.anchor.SetPoint(-98, -23);
+
+ target_->set_pointer_assumed_stopped_time_ms(543);
+
+ scoped_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target =
+ static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ CheckScrollDistanceIsWithinRange(
+ smooth_scroll_target->scroll_distance(), params.distance, target_);
+ EXPECT_GE(GetTotalTime(), target_->PointerAssumedStoppedTime());
+}
+
+TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchFling) {
+ CreateControllerAndTarget<MockSyntheticSmoothScrollTouchTarget>();
+
+ // Create a smooth scroll with a short distance and set the pointer assumed
+ // stopped time high. Disable 'prevent_fling' and check that the gesture
+ // finishes without waiting before it stops.
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.distance = gfx::Vector2d(-43, 19);
+ params.prevent_fling = false;
+ params.anchor.SetPoint(-89, 78);
+
+ target_->set_pointer_assumed_stopped_time_ms(543);
+
+ scoped_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target =
+ static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ CheckScrollDistanceIsWithinRange(
+ smooth_scroll_target->scroll_distance(), params.distance, target_);
+ EXPECT_LE(GetTotalTime(), target_->PointerAssumedStoppedTime());
+}
+
+TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchZeroDistance) {
+ CreateControllerAndTarget<MockSyntheticSmoothScrollTouchTarget>();
+
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.distance = gfx::Vector2d(0, 0);
+ params.anchor.SetPoint(-32, 43);
+
+ scoped_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target =
+ static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ EXPECT_EQ(gfx::Vector2dF(0, 0), smooth_scroll_target->scroll_distance());
+}
+
+TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureMouseVertical) {
+ CreateControllerAndTarget<MockSyntheticSmoothScrollMouseTarget>();
+
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
+ params.distance = gfx::Vector2d(0, -234);
+ params.anchor.SetPoint(432, 89);
+
+ scoped_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target =
+ static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ EXPECT_EQ(params.distance, smooth_scroll_target->scroll_distance());
+}
+
+TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureMouseHorizontal) {
+ CreateControllerAndTarget<MockSyntheticSmoothScrollMouseTarget>();
+
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
+ params.distance = gfx::Vector2d(345, 0);
+ params.anchor.SetPoint(90, 12);
+
+ scoped_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target =
+ static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ EXPECT_EQ(params.distance, smooth_scroll_target->scroll_distance());
+}
+
+TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureMouseDiagonal) {
+ CreateControllerAndTarget<MockSyntheticSmoothScrollMouseTarget>();
+
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
+ params.distance = gfx::Vector2d(-194, 303);
+ params.anchor.SetPoint(90, 12);
+
+ scoped_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target =
+ static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ EXPECT_EQ(params.distance, smooth_scroll_target->scroll_distance());
+}
+
+TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomIn) {
+ CreateControllerAndTarget<MockSyntheticPinchTouchTarget>();
+
+ SyntheticPinchGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.zoom_in = true;
+ params.total_num_pixels_covered = 345;
+ params.anchor.SetPoint(54, 89);
+
+ scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticPinchTouchTarget* pinch_target =
+ static_cast<MockSyntheticPinchTouchTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ EXPECT_EQ(pinch_target->zoom_direction(),
+ MockSyntheticPinchTouchTarget::ZOOM_IN);
+ EXPECT_EQ(params.total_num_pixels_covered + 2 * target_->GetTouchSlopInDips(),
+ pinch_target->total_num_pixels_covered());
+}
+
+TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomOut) {
+ CreateControllerAndTarget<MockSyntheticPinchTouchTarget>();
+
+ SyntheticPinchGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.zoom_in = false;
+ params.total_num_pixels_covered = 456;
+ params.anchor.SetPoint(-12, 93);
+
+ scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticPinchTouchTarget* pinch_target =
+ static_cast<MockSyntheticPinchTouchTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ EXPECT_EQ(pinch_target->zoom_direction(),
+ MockSyntheticPinchTouchTarget::ZOOM_OUT);
+ EXPECT_EQ(params.total_num_pixels_covered + 2 * target_->GetTouchSlopInDips(),
+ pinch_target->total_num_pixels_covered());
+}
+
+TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZeroPixelsCovered) {
+ CreateControllerAndTarget<MockSyntheticPinchTouchTarget>();
+
+ SyntheticPinchGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.zoom_in = true;
+ params.total_num_pixels_covered = 0;
+
+ scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticPinchTouchTarget* pinch_target =
+ static_cast<MockSyntheticPinchTouchTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ EXPECT_EQ(pinch_target->zoom_direction(),
+ MockSyntheticPinchTouchTarget::ZOOM_DIRECTION_UNKNOWN);
+ EXPECT_EQ(0, pinch_target->total_num_pixels_covered());
+}
+
+TEST_F(SyntheticGestureControllerTest, TapGestureTouch) {
+ CreateControllerAndTarget<MockSyntheticTapTouchTarget>();
+
+ SyntheticTapGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.duration_ms = 123;
+ params.position.SetPoint(87, -124);
+
+ scoped_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticTapTouchTarget* tap_target =
+ static_cast<MockSyntheticTapTouchTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ EXPECT_TRUE(tap_target->GestureFinished());
+ EXPECT_EQ(tap_target->position(), params.position);
+ EXPECT_GE(GetTotalTime(),
+ base::TimeDelta::FromMilliseconds(params.duration_ms));
+}
+
+TEST_F(SyntheticGestureControllerTest, TapGestureMouse) {
+ CreateControllerAndTarget<MockSyntheticTapMouseTarget>();
+
+ SyntheticTapGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
+ params.duration_ms = 79;
+ params.position.SetPoint(98, 123);
+
+ scoped_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params));
+ controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ FlushInputUntilComplete();
+
+ MockSyntheticTapMouseTarget* tap_target =
+ static_cast<MockSyntheticTapMouseTarget*>(target_);
+ EXPECT_EQ(1, target_->num_success());
+ EXPECT_EQ(0, target_->num_failure());
+ EXPECT_TRUE(tap_target->GestureFinished());
+ EXPECT_EQ(tap_target->position(), params.position);
+ EXPECT_GE(GetTotalTime(),
+ base::TimeDelta::FromMilliseconds(params.duration_ms));
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target.h
new file mode 100644
index 00000000000..01487fc2772
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target.h
@@ -0,0 +1,55 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_H_
+
+#include "base/time/time.h"
+#include "content/browser/renderer_host/input/synthetic_gesture.h"
+#include "content/common/content_export.h"
+#include "content/common/input/synthetic_gesture_params.h"
+
+namespace content {
+
+class InputEvent;
+
+// Interface between the synthetic gesture controller and the RenderWidgetHost.
+class CONTENT_EXPORT SyntheticGestureTarget {
+ public:
+ SyntheticGestureTarget() {}
+ virtual ~SyntheticGestureTarget() {}
+
+ // Allows synthetic gestures to insert input events in the highest level of
+ // input processing on the target platform (e.g. Java on Android), so that
+ // the event traverses the entire input processing stack.
+ virtual void DispatchInputEventToPlatform(const InputEvent& event) = 0;
+
+ // Called by SyntheticGestureController when a gesture has finished.
+ virtual void OnSyntheticGestureCompleted(
+ SyntheticGesture::Result result) = 0;
+
+ // Called by SyntheticGestureController to request a flush at a time
+ // appropriate for the platform, e.g. aligned with vsync.
+ virtual void SetNeedsFlush() = 0;
+
+ // Returns the default gesture source type for the target.
+ virtual SyntheticGestureParams::GestureSourceType
+ GetDefaultSyntheticGestureSourceType() const = 0;
+
+ // Check if a particular gesture type is supported by the target.
+ virtual bool SupportsSyntheticGestureSourceType(
+ SyntheticGestureParams::GestureSourceType gesture_source_type) const = 0;
+
+ // After how much time of inaction does the target assume that a pointer has
+ // stopped moving.
+ virtual base::TimeDelta PointerAssumedStoppedTime() const = 0;
+
+ // Returns the maximum number of DIPs a touch pointer can move without being
+ // considered moving by the platform.
+ virtual int GetTouchSlopInDips() const = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_H_
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc
new file mode 100644
index 00000000000..cf5181ab93c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc
@@ -0,0 +1,92 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
+
+#include "content/browser/android/content_view_core_impl.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "jni/TouchEventSynthesizer_jni.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/gfx/android/view_configuration.h"
+#include "ui/gfx/screen.h"
+
+using blink::WebTouchEvent;
+
+namespace content {
+
+SyntheticGestureTargetAndroid::SyntheticGestureTargetAndroid(
+ RenderWidgetHostImpl* host,
+ base::android::ScopedJavaLocalRef<jobject> touch_event_synthesizer)
+ : SyntheticGestureTargetBase(host),
+ touch_event_synthesizer_(touch_event_synthesizer) {
+ DCHECK(!touch_event_synthesizer_.is_null());
+}
+
+SyntheticGestureTargetAndroid::~SyntheticGestureTargetAndroid() {
+}
+
+bool SyntheticGestureTargetAndroid::RegisterTouchEventSynthesizer(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+void SyntheticGestureTargetAndroid::TouchSetPointer(
+ JNIEnv* env, int index, int x, int y, int id) {
+ Java_TouchEventSynthesizer_setPointer(env, touch_event_synthesizer_.obj(),
+ index, x, y, id);
+}
+
+void SyntheticGestureTargetAndroid::TouchInject(
+ JNIEnv* env, Action action, int pointer_count) {
+ Java_TouchEventSynthesizer_inject(env, touch_event_synthesizer_.obj(),
+ static_cast<int>(action), pointer_count);
+}
+
+void SyntheticGestureTargetAndroid::DispatchWebTouchEventToPlatform(
+ const blink::WebTouchEvent& web_touch, const ui::LatencyInfo&) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+
+ SyntheticGestureTargetAndroid::Action action =
+ SyntheticGestureTargetAndroid::ActionInvalid;
+ switch (web_touch.type) {
+ case blink::WebInputEvent::TouchStart:
+ action = SyntheticGestureTargetAndroid::ActionStart;
+ break;
+ case blink::WebInputEvent::TouchMove:
+ action = SyntheticGestureTargetAndroid::ActionMove;
+ break;
+ case blink::WebInputEvent::TouchCancel:
+ action = SyntheticGestureTargetAndroid::ActionCancel;
+ break;
+ case blink::WebInputEvent::TouchEnd:
+ action = SyntheticGestureTargetAndroid::ActionEnd;
+ break;
+ default:
+ NOTREACHED();
+ }
+ const unsigned num_touches = web_touch.touchesLength;
+ for (unsigned i = 0; i < num_touches; ++i) {
+ const blink::WebTouchPoint* point = &web_touch.touches[i];
+ TouchSetPointer(env, i, point->position.x, point->position.y, point->id);
+ }
+
+ TouchInject(env, action, num_touches);
+}
+
+SyntheticGestureParams::GestureSourceType
+SyntheticGestureTargetAndroid::GetDefaultSyntheticGestureSourceType() const {
+ return SyntheticGestureParams::TOUCH_INPUT;
+}
+
+bool SyntheticGestureTargetAndroid::SupportsSyntheticGestureSourceType(
+ SyntheticGestureParams::GestureSourceType gesture_source_type) const {
+ return gesture_source_type == SyntheticGestureParams::TOUCH_INPUT;
+}
+
+int SyntheticGestureTargetAndroid::GetTouchSlopInDips() const {
+ float device_scale_factor =
+ gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().device_scale_factor();
+ return gfx::ViewConfiguration::GetTouchSlopInPixels() / device_scale_factor;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h
new file mode 100644
index 00000000000..b8c5a5d8142
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h
@@ -0,0 +1,58 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_ANDROID_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_ANDROID_H_
+
+#include "base/android/jni_android.h"
+#include "base/time/time.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
+
+namespace content {
+
+class ContentViewCoreImpl;
+
+class SyntheticGestureTargetAndroid : public SyntheticGestureTargetBase {
+ public:
+ SyntheticGestureTargetAndroid(
+ RenderWidgetHostImpl* host,
+ base::android::ScopedJavaLocalRef<jobject> touch_event_synthesizer);
+ virtual ~SyntheticGestureTargetAndroid();
+
+ static bool RegisterTouchEventSynthesizer(JNIEnv* env);
+
+ virtual void DispatchWebTouchEventToPlatform(
+ const blink::WebTouchEvent& web_touch,
+ const ui::LatencyInfo& latency_info) OVERRIDE;
+
+ // SyntheticGestureTarget:
+ virtual SyntheticGestureParams::GestureSourceType
+ GetDefaultSyntheticGestureSourceType() const OVERRIDE;
+ virtual bool SupportsSyntheticGestureSourceType(
+ SyntheticGestureParams::GestureSourceType gesture_source_type) const
+ OVERRIDE;
+
+ virtual int GetTouchSlopInDips() const OVERRIDE;
+
+ private:
+ // Enum values below need to be kept in sync with TouchEventSynthesizer.java
+ enum Action {
+ ActionInvalid = -1,
+ ActionStart = 0,
+ ActionMove = 1,
+ ActionCancel = 2,
+ ActionEnd = 3
+ };
+
+ void TouchSetPointer(JNIEnv* env, int index, int x, int y, int id);
+ void TouchInject(JNIEnv* env, Action action, int pointer_count);
+
+ base::android::ScopedJavaGlobalRef<jobject> touch_event_synthesizer_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyntheticGestureTargetAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_ANDROID_H_
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
new file mode 100644
index 00000000000..f9ab85895c7
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
@@ -0,0 +1,163 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
+
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "content/browser/renderer_host/ui_events_helper.h"
+#include "content/common/input/input_event.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/window.h"
+#include "ui/events/gestures/gesture_configuration.h"
+
+using blink::WebTouchEvent;
+using blink::WebMouseWheelEvent;
+
+namespace content {
+
+SyntheticGestureTargetAura::SyntheticGestureTargetAura(
+ RenderWidgetHostImpl* host)
+ : SyntheticGestureTargetBase(host) {
+}
+
+void SyntheticGestureTargetAura::DispatchWebTouchEventToPlatform(
+ const WebTouchEvent& web_touch,
+ const ui::LatencyInfo& latency_info) {
+ aura::Window* window = render_widget_host()->GetView()->GetNativeView();
+ aura::Window* root_window = window->GetRootWindow();
+ aura::client::ScreenPositionClient* position_client =
+ aura::client::GetScreenPositionClient(root_window);
+ DCHECK(position_client);
+
+ TouchEventWithLatencyInfo touch_with_latency(web_touch, latency_info);
+
+ // SyntheticGesture may skip calculating screenPosition, so we will fill it
+ // in here. "screenPosition" is converted from "position".
+ const size_t num_touches = touch_with_latency.event.touchesLength;
+ for (size_t i = 0; i < num_touches; ++ i) {
+ blink::WebTouchPoint* point = &touch_with_latency.event.touches[i];
+ gfx::Point position(point->position.x, point->position.y);
+ position_client->ConvertPointToScreen(window, &position);
+ point->screenPosition.x = position.x();
+ point->screenPosition.y = position.y();
+ }
+
+ ScopedVector<ui::TouchEvent> events;
+ bool conversion_success = MakeUITouchEventsFromWebTouchEvents(
+ touch_with_latency, &events, SCREEN_COORDINATES);
+ DCHECK(conversion_success);
+
+ aura::RootWindowHostDelegate* root_window_host_delegate =
+ GetRootWindowHostDelegate();
+ for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
+ end = events.end(); iter != end; ++iter) {
+ root_window_host_delegate->OnHostTouchEvent(*iter);
+ }
+}
+
+void SyntheticGestureTargetAura::DispatchWebMouseWheelEventToPlatform(
+ const blink::WebMouseWheelEvent& web_wheel,
+ const ui::LatencyInfo&) {
+ gfx::Point location(web_wheel.x, web_wheel.y);
+ ui::MouseEvent mouse_event(
+ ui::ET_MOUSEWHEEL, location, location, ui::EF_NONE);
+ ui::MouseWheelEvent wheel_event(
+ mouse_event, web_wheel.deltaX, web_wheel.deltaY);
+
+ GetRootWindowHostDelegate()->OnHostMouseEvent(&wheel_event);
+}
+
+namespace {
+
+ui::EventType
+WebMouseEventTypeToEventType(blink::WebInputEvent::Type web_type) {
+ switch (web_type) {
+ case blink::WebInputEvent::MouseDown:
+ return ui::ET_MOUSE_PRESSED;
+
+ case blink::WebInputEvent::MouseUp:
+ return ui::ET_MOUSE_RELEASED;
+
+ case blink::WebInputEvent::MouseMove:
+ return ui::ET_MOUSE_MOVED;
+
+ case blink::WebInputEvent::MouseEnter:
+ return ui::ET_MOUSE_ENTERED;
+
+ case blink::WebInputEvent::MouseLeave:
+ return ui::ET_MOUSE_EXITED;
+
+ case blink::WebInputEvent::ContextMenu:
+ NOTREACHED() << "WebInputEvent::ContextMenu not supported by"
+ "SyntheticGestureTargetAura";
+
+ default:
+ NOTREACHED();
+ }
+
+ return ui::ET_UNKNOWN;
+}
+
+int WebMouseEventButtonToFlags(blink::WebMouseEvent::Button button) {
+ switch (button) {
+ case blink::WebMouseEvent::ButtonLeft:
+ return ui::EF_LEFT_MOUSE_BUTTON;
+
+ case blink::WebMouseEvent::ButtonMiddle:
+ return ui::EF_MIDDLE_MOUSE_BUTTON;
+
+ case blink::WebMouseEvent::ButtonRight:
+ return ui::EF_RIGHT_MOUSE_BUTTON;
+
+ default:
+ NOTREACHED();
+ }
+
+ return 0;
+}
+
+} // namespace
+
+void SyntheticGestureTargetAura::DispatchWebMouseEventToPlatform(
+ const blink::WebMouseEvent& web_mouse,
+ const ui::LatencyInfo& latency_info) {
+ gfx::Point location(web_mouse.x, web_mouse.y);
+ ui::EventType event_type = WebMouseEventTypeToEventType(web_mouse.type);
+ int flags = WebMouseEventButtonToFlags(web_mouse.button);
+ ui::MouseEvent mouse_event(event_type, location, location, flags);
+
+ GetRootWindowHostDelegate()->OnHostMouseEvent(&mouse_event);
+}
+
+SyntheticGestureParams::GestureSourceType
+SyntheticGestureTargetAura::GetDefaultSyntheticGestureSourceType() const {
+ return SyntheticGestureParams::MOUSE_INPUT;
+}
+
+bool SyntheticGestureTargetAura::SupportsSyntheticGestureSourceType(
+ SyntheticGestureParams::GestureSourceType gesture_source_type) const {
+ return gesture_source_type == SyntheticGestureParams::TOUCH_INPUT ||
+ gesture_source_type == SyntheticGestureParams::MOUSE_INPUT;
+}
+
+int SyntheticGestureTargetAura::GetTouchSlopInDips() const {
+ // - 1 because Aura considers a pointer to be moving if it has moved at least
+ // 'max_touch_move_in_pixels_for_click' pixels.
+ return ui::GestureConfiguration::max_touch_move_in_pixels_for_click() - 1;
+}
+
+aura::RootWindowHostDelegate*
+SyntheticGestureTargetAura::GetRootWindowHostDelegate() const {
+ aura::Window* window = render_widget_host()->GetView()->GetNativeView();
+ aura::Window* root_window = window->GetRootWindow();
+ aura::RootWindowHostDelegate* root_window_host_delegate =
+ root_window->GetDispatcher()->AsRootWindowHostDelegate();
+ DCHECK(root_window_host_delegate);
+ return root_window_host_delegate;
+}
+
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h
new file mode 100644
index 00000000000..9befda688f4
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_AURA_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_AURA_H_
+
+#include "base/time/time.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
+#include "content/common/input/synthetic_gesture_params.h"
+
+namespace aura {
+class RootWindowHostDelegate;
+}
+
+namespace content {
+
+class InputEvent;
+
+// SyntheticGestureTarget implementation for aura
+class SyntheticGestureTargetAura : public SyntheticGestureTargetBase {
+ public:
+ explicit SyntheticGestureTargetAura(RenderWidgetHostImpl* host);
+
+ // SyntheticGestureTargetBase:
+ virtual void DispatchWebTouchEventToPlatform(
+ const blink::WebTouchEvent& web_touch,
+ const ui::LatencyInfo& latency_info) OVERRIDE;
+ virtual void DispatchWebMouseWheelEventToPlatform(
+ const blink::WebMouseWheelEvent& web_wheel,
+ const ui::LatencyInfo& latency_info) OVERRIDE;
+ virtual void DispatchWebMouseEventToPlatform(
+ const blink::WebMouseEvent& web_mouse,
+ const ui::LatencyInfo& latency_info) OVERRIDE;
+
+ // SyntheticGestureTarget:
+ virtual SyntheticGestureParams::GestureSourceType
+ GetDefaultSyntheticGestureSourceType() const OVERRIDE;
+ virtual bool SupportsSyntheticGestureSourceType(
+ SyntheticGestureParams::GestureSourceType gesture_source_type) const
+ OVERRIDE;
+
+ virtual int GetTouchSlopInDips() const OVERRIDE;
+
+ private:
+ aura::RootWindowHostDelegate* GetRootWindowHostDelegate() const;
+
+ DISALLOW_COPY_AND_ASSIGN(SyntheticGestureTargetAura);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_AURA_H_
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
new file mode 100644
index 00000000000..0938eebb649
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
@@ -0,0 +1,122 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
+
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/renderer_host/ui_events_helper.h"
+#include "content/common/input/input_event.h"
+#include "content/common/input_messages.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/event.h"
+#include "ui/events/latency_info.h"
+
+using blink::WebInputEvent;
+using blink::WebTouchEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+
+namespace content {
+namespace {
+
+// This value was determined experimentally. It was sufficient to not cause a
+// fling on Android.
+const int kPointerAssumedStoppedTimeMs = 50;
+
+// SyntheticGestureTargetBase passes input events straight on to the renderer
+// without going through a gesture recognition framework. There is thus no touch
+// slop.
+const int kTouchSlopInDips = 0;
+
+} // namespace
+
+SyntheticGestureTargetBase::SyntheticGestureTargetBase(
+ RenderWidgetHostImpl* host)
+ : host_(host) {
+ DCHECK(host);
+}
+
+SyntheticGestureTargetBase::~SyntheticGestureTargetBase() {
+}
+
+void SyntheticGestureTargetBase::DispatchInputEventToPlatform(
+ const InputEvent& event) {
+ const WebInputEvent* web_event = event.web_event.get();
+ if (WebInputEvent::isTouchEventType(web_event->type)) {
+ DCHECK(SupportsSyntheticGestureSourceType(
+ SyntheticGestureParams::TOUCH_INPUT));
+
+ const WebTouchEvent* web_touch =
+ static_cast<const WebTouchEvent*>(web_event);
+ DispatchWebTouchEventToPlatform(*web_touch, event.latency_info);
+ } else if (web_event->type == WebInputEvent::MouseWheel) {
+ DCHECK(SupportsSyntheticGestureSourceType(
+ SyntheticGestureParams::MOUSE_INPUT));
+
+ const WebMouseWheelEvent* web_wheel =
+ static_cast<const WebMouseWheelEvent*>(web_event);
+ DispatchWebMouseWheelEventToPlatform(*web_wheel, event.latency_info);
+ } else if (WebInputEvent::isMouseEventType(web_event->type)) {
+ DCHECK(SupportsSyntheticGestureSourceType(
+ SyntheticGestureParams::MOUSE_INPUT));
+
+ const WebMouseEvent* web_mouse =
+ static_cast<const WebMouseEvent*>(web_event);
+ DispatchWebMouseEventToPlatform(*web_mouse, event.latency_info);
+ } else {
+ NOTREACHED();
+ }
+}
+
+void SyntheticGestureTargetBase::DispatchWebTouchEventToPlatform(
+ const blink::WebTouchEvent& web_touch,
+ const ui::LatencyInfo& latency_info) {
+ host_->ForwardTouchEventWithLatencyInfo(web_touch, latency_info);
+}
+
+void SyntheticGestureTargetBase::DispatchWebMouseWheelEventToPlatform(
+ const blink::WebMouseWheelEvent& web_wheel,
+ const ui::LatencyInfo& latency_info) {
+ host_->ForwardWheelEventWithLatencyInfo(
+ MouseWheelEventWithLatencyInfo(web_wheel, latency_info));
+}
+
+void SyntheticGestureTargetBase::DispatchWebMouseEventToPlatform(
+ const blink::WebMouseEvent& web_mouse,
+ const ui::LatencyInfo& latency_info) {
+ host_->ForwardMouseEventWithLatencyInfo(
+ MouseEventWithLatencyInfo(web_mouse, latency_info));
+}
+
+void SyntheticGestureTargetBase::OnSyntheticGestureCompleted(
+ SyntheticGesture::Result result) {
+ host_->Send(new InputMsg_SyntheticGestureCompleted(host_->GetRoutingID()));
+}
+
+void SyntheticGestureTargetBase::SetNeedsFlush() {
+ host_->SetNeedsFlush();
+}
+
+SyntheticGestureParams::GestureSourceType
+SyntheticGestureTargetBase::GetDefaultSyntheticGestureSourceType() const {
+ return SyntheticGestureParams::MOUSE_INPUT;
+}
+
+bool SyntheticGestureTargetBase::SupportsSyntheticGestureSourceType(
+ SyntheticGestureParams::GestureSourceType gesture_source_type) const {
+ return gesture_source_type == SyntheticGestureParams::MOUSE_INPUT ||
+ gesture_source_type == SyntheticGestureParams::TOUCH_INPUT;
+}
+
+base::TimeDelta SyntheticGestureTargetBase::PointerAssumedStoppedTime()
+ const {
+ return base::TimeDelta::FromMilliseconds(kPointerAssumedStoppedTimeMs);
+}
+
+int SyntheticGestureTargetBase::GetTouchSlopInDips() const {
+ return kTouchSlopInDips;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h
new file mode 100644
index 00000000000..efb8d76b57e
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h
@@ -0,0 +1,71 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_BASE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_BASE_H_
+
+#include "base/time/time.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
+
+namespace ui {
+struct LatencyInfo;
+}
+
+namespace blink {
+class WebTouchEvent;
+class WebMouseEvent;
+class WebMouseWheelEvent;
+}
+
+namespace content {
+
+class RenderWidgetHostImpl;
+
+class SyntheticGestureTargetBase : public SyntheticGestureTarget {
+ public:
+ explicit SyntheticGestureTargetBase(RenderWidgetHostImpl* host);
+ virtual ~SyntheticGestureTargetBase();
+
+ virtual void DispatchWebTouchEventToPlatform(
+ const blink::WebTouchEvent& web_touch,
+ const ui::LatencyInfo& latency_info);
+
+ virtual void DispatchWebMouseWheelEventToPlatform(
+ const blink::WebMouseWheelEvent& web_wheel,
+ const ui::LatencyInfo& latency_info);
+
+ virtual void DispatchWebMouseEventToPlatform(
+ const blink::WebMouseEvent& web_mouse,
+ const ui::LatencyInfo& latency_info);
+
+ // SyntheticGestureTarget:
+ virtual void DispatchInputEventToPlatform(const InputEvent& event) OVERRIDE;
+
+ virtual void OnSyntheticGestureCompleted(
+ SyntheticGesture::Result result) OVERRIDE;
+
+ virtual void SetNeedsFlush() OVERRIDE;
+
+ virtual SyntheticGestureParams::GestureSourceType
+ GetDefaultSyntheticGestureSourceType() const OVERRIDE;
+ virtual bool SupportsSyntheticGestureSourceType(
+ SyntheticGestureParams::GestureSourceType gesture_source_type) const
+ OVERRIDE;
+
+ virtual base::TimeDelta PointerAssumedStoppedTime() const OVERRIDE;
+
+ virtual int GetTouchSlopInDips() const OVERRIDE;
+
+ protected:
+ RenderWidgetHostImpl* render_widget_host() const { return host_; }
+
+ private:
+ RenderWidgetHostImpl* host_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyntheticGestureTargetBase);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_BASE_H_
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.cc
new file mode 100644
index 00000000000..dfe5cf474e7
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.cc
@@ -0,0 +1,166 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/synthetic_pinch_gesture.h"
+
+#include <cmath>
+
+#include "base/logging.h"
+#include "content/common/input/input_event.h"
+#include "ui/events/latency_info.h"
+
+namespace content {
+
+SyntheticPinchGesture::SyntheticPinchGesture(
+ const SyntheticPinchGestureParams& params)
+ : params_(params),
+ current_y_0_(0.0f),
+ current_y_1_(0.0f),
+ target_y_0_(0.0f),
+ target_y_1_(0.0f),
+ gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT),
+ state_(SETUP) {
+ DCHECK_GE(params_.total_num_pixels_covered, 0);
+}
+
+SyntheticPinchGesture::~SyntheticPinchGesture() {}
+
+SyntheticGesture::Result SyntheticPinchGesture::ForwardInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target) {
+ if (state_ == SETUP) {
+ gesture_source_type_ = params_.gesture_source_type;
+ if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT)
+ gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType();
+
+ if (!target->SupportsSyntheticGestureSourceType(gesture_source_type_))
+ return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM;
+
+ state_ = STARTED;
+ }
+
+ DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
+ if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT)
+ ForwardTouchInputEvents(interval, target);
+ else
+ return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
+
+ return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED
+ : SyntheticGesture::GESTURE_RUNNING;
+}
+
+void SyntheticPinchGesture::ForwardTouchInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target) {
+ switch (state_) {
+ case STARTED:
+ // Check for an early finish.
+ if (params_.total_num_pixels_covered == 0) {
+ state_ = DONE;
+ break;
+ }
+ SetupCoordinates(target);
+ PressTouchPoints(target);
+ state_ = MOVING;
+ break;
+ case MOVING:
+ UpdateTouchPoints(interval);
+ MoveTouchPoints(target);
+ if (HasReachedTarget()) {
+ ReleaseTouchPoints(target);
+ state_ = DONE;
+ }
+ break;
+ case SETUP:
+ NOTREACHED() << "State SETUP invalid for synthetic pinch.";
+ case DONE:
+ NOTREACHED() << "State DONE invalid for synthetic pinch.";
+ }
+}
+
+void SyntheticPinchGesture::UpdateTouchPoints(base::TimeDelta interval) {
+ // Compute the delta for the first pointer. The other one moves exactly
+ // the same but in the opposite direction.
+ float delta = GetDeltaForPointer0(interval);
+ current_y_0_ += delta;
+ current_y_1_ -= delta;
+}
+
+void SyntheticPinchGesture::PressTouchPoints(SyntheticGestureTarget* target) {
+ touch_event_.PressPoint(params_.anchor.x(), current_y_0_);
+ touch_event_.PressPoint(params_.anchor.x(), current_y_1_);
+ ForwardTouchEvent(target);
+}
+
+void SyntheticPinchGesture::MoveTouchPoints(SyntheticGestureTarget* target) {
+ // The current pointer positions are stored as float but the pointer
+ // coordinates of the input event are integers. Floor both positions so that
+ // in case of an odd distance one of the pointers (the one whose position goes
+ // down) moves one pixel further than the other. The explicit flooring is only
+ // needed for negative values.
+ touch_event_.MovePoint(0, params_.anchor.x(), floor(current_y_0_));
+ touch_event_.MovePoint(1, params_.anchor.x(), floor(current_y_1_));
+ ForwardTouchEvent(target);
+}
+
+void SyntheticPinchGesture::ReleaseTouchPoints(SyntheticGestureTarget* target) {
+ touch_event_.ReleasePoint(0);
+ touch_event_.ReleasePoint(1);
+ ForwardTouchEvent(target);
+}
+
+
+void SyntheticPinchGesture::ForwardTouchEvent(SyntheticGestureTarget* target)
+ const {
+ target->DispatchInputEventToPlatform(
+ InputEvent(touch_event_, ui::LatencyInfo(), false));
+}
+
+void SyntheticPinchGesture::SetupCoordinates(SyntheticGestureTarget* target) {
+ const float kTouchSlopInDips = target->GetTouchSlopInDips();
+ float inner_distance_to_anchor = 2 * kTouchSlopInDips;
+ float outer_distance_to_anchor = inner_distance_to_anchor +
+ params_.total_num_pixels_covered / 2.0f +
+ kTouchSlopInDips;
+
+ // Move pointers away from each other to zoom in
+ // or towards each other to zoom out.
+ if (params_.zoom_in) {
+ current_y_0_ = params_.anchor.y() - inner_distance_to_anchor;
+ current_y_1_ = params_.anchor.y() + inner_distance_to_anchor;
+ target_y_0_ = params_.anchor.y() - outer_distance_to_anchor;
+ target_y_1_ = params_.anchor.y() + outer_distance_to_anchor;
+ } else {
+ current_y_0_ = params_.anchor.y() - outer_distance_to_anchor;
+ current_y_1_ = params_.anchor.y() + outer_distance_to_anchor;
+ target_y_0_ = params_.anchor.y() - inner_distance_to_anchor;
+ target_y_1_ = params_.anchor.y() + inner_distance_to_anchor;
+ }
+}
+
+float SyntheticPinchGesture::GetDeltaForPointer0(
+ const base::TimeDelta& interval) const {
+ float total_abs_delta =
+ params_.relative_pointer_speed_in_pixels_s * interval.InSecondsF();
+
+ // Make sure we're not moving too far in the final step.
+ total_abs_delta =
+ std::min(total_abs_delta, ComputeAbsoluteRemainingDistance());
+
+ float abs_delta_pointer_0 = total_abs_delta / 2;
+ return params_.zoom_in ? -abs_delta_pointer_0 : abs_delta_pointer_0;
+}
+
+float SyntheticPinchGesture::ComputeAbsoluteRemainingDistance() const {
+ float distance_0 = params_.zoom_in ? (current_y_0_ - target_y_0_)
+ : (target_y_0_ - current_y_0_);
+ DCHECK_GE(distance_0, 0);
+
+ // Both pointers move the same overall distance at the same speed.
+ return 2 * distance_0;
+}
+
+bool SyntheticPinchGesture::HasReachedTarget() const {
+ return ComputeAbsoluteRemainingDistance() == 0;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.h
new file mode 100644
index 00000000000..97405ce1267
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.h
@@ -0,0 +1,61 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_PINCH_GESTURE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_PINCH_GESTURE_H_
+
+#include "content/browser/renderer_host/input/synthetic_gesture.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
+#include "content/common/content_export.h"
+#include "content/common/input/synthetic_pinch_gesture_params.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace content {
+
+class CONTENT_EXPORT SyntheticPinchGesture : public SyntheticGesture {
+ public:
+ explicit SyntheticPinchGesture(const SyntheticPinchGestureParams& params);
+ virtual ~SyntheticPinchGesture();
+
+ virtual SyntheticGesture::Result ForwardInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target) OVERRIDE;
+
+ private:
+ enum GestureState {
+ SETUP,
+ STARTED,
+ MOVING,
+ DONE
+ };
+
+ void ForwardTouchInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target);
+
+ void UpdateTouchPoints(base::TimeDelta interval);
+ void PressTouchPoints(SyntheticGestureTarget* target);
+ void MoveTouchPoints(SyntheticGestureTarget* target);
+ void ReleaseTouchPoints(SyntheticGestureTarget* target);
+ void ForwardTouchEvent(SyntheticGestureTarget* target) const;
+
+ void SetupCoordinates(SyntheticGestureTarget* target);
+ float GetDeltaForPointer0(const base::TimeDelta& interval) const;
+ float ComputeAbsoluteRemainingDistance() const;
+ bool HasReachedTarget() const;
+
+ SyntheticPinchGestureParams params_;
+ float current_y_0_;
+ float current_y_1_;
+ float target_y_0_;
+ float target_y_1_;
+ SyntheticGestureParams::GestureSourceType gesture_source_type_;
+ GestureState state_;
+ SyntheticWebTouchEvent touch_event_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyntheticPinchGesture);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_PINCH_GESTURE_H_
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
new file mode 100644
index 00000000000..b2fb4bb7eb3
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
@@ -0,0 +1,223 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
+
+#include "base/logging.h"
+#include "content/common/input/input_event.h"
+#include "ui/events/latency_info.h"
+#include "ui/gfx/point_f.h"
+
+namespace content {
+namespace {
+
+gfx::Vector2d FloorTowardZero(const gfx::Vector2dF& vector) {
+ int x = vector.x() > 0 ? floor(vector.x()) : ceil(vector.x());
+ int y = vector.y() > 0 ? floor(vector.y()) : ceil(vector.y());
+ return gfx::Vector2d(x, y);
+}
+
+gfx::Vector2d CeilFromZero(const gfx::Vector2dF& vector) {
+ int x = vector.x() > 0 ? ceil(vector.x()) : floor(vector.x());
+ int y = vector.y() > 0 ? ceil(vector.y()) : floor(vector.y());
+ return gfx::Vector2d(x, y);
+}
+
+} // namespace
+
+SyntheticSmoothScrollGesture::SyntheticSmoothScrollGesture(
+ const SyntheticSmoothScrollGestureParams& params)
+ : params_(params),
+ gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT),
+ state_(SETUP) {}
+
+SyntheticSmoothScrollGesture::~SyntheticSmoothScrollGesture() {}
+
+SyntheticGesture::Result SyntheticSmoothScrollGesture::ForwardInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target) {
+ if (state_ == SETUP) {
+ gesture_source_type_ = params_.gesture_source_type;
+ if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT)
+ gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType();
+
+ if (!target->SupportsSyntheticGestureSourceType(gesture_source_type_))
+ return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM;
+
+ state_ = STARTED;
+ }
+
+ DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
+ if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT)
+ ForwardTouchInputEvents(interval, target);
+ else if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT)
+ ForwardMouseInputEvents(interval, target);
+ else
+ return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
+
+ return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED
+ : SyntheticGesture::GESTURE_RUNNING;
+}
+
+void SyntheticSmoothScrollGesture::ForwardTouchInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target) {
+ switch (state_) {
+ case STARTED:
+ // Check for an early finish.
+ if (params_.distance.IsZero()) {
+ state_ = DONE;
+ break;
+ }
+ AddTouchSlopToDistance(target);
+ PressTouchPoint(target);
+ state_ = MOVING;
+ break;
+ case MOVING:
+ total_delta_ += GetPositionDelta(interval);
+ MoveTouchPoint(target);
+
+ if (HasScrolledEntireDistance()) {
+ if (params_.prevent_fling) {
+ state_ = STOPPING;
+ } else {
+ ReleaseTouchPoint(target);
+ state_ = DONE;
+ }
+ }
+ break;
+ case STOPPING:
+ total_stopping_wait_time_ += interval;
+ if (total_stopping_wait_time_ >= target->PointerAssumedStoppedTime()) {
+ // Send one last move event, but don't change the location. Without this
+ // we'd still sometimes cause a fling on Android.
+ MoveTouchPoint(target);
+ ReleaseTouchPoint(target);
+ state_ = DONE;
+ }
+ break;
+ case SETUP:
+ NOTREACHED()
+ << "State STARTED invalid for synthetic scroll using touch input.";
+ case DONE:
+ NOTREACHED()
+ << "State DONE invalid for synthetic scroll using touch input.";
+ }
+}
+
+void SyntheticSmoothScrollGesture::ForwardMouseInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target) {
+ switch (state_) {
+ case STARTED:
+ // Check for an early finish.
+ if (params_.distance.IsZero()) {
+ state_ = DONE;
+ break;
+ }
+ state_ = MOVING;
+ // Fall through to forward the first event.
+ case MOVING:
+ {
+ // Even though WebMouseWheelEvents take floating point deltas,
+ // internally the scroll position is stored as an integer. We therefore
+ // keep track of the discrete delta which is consistent with the
+ // internal scrolling state. This ensures that when the gesture has
+ // finished we've scrolled exactly the specified distance.
+ total_delta_ += GetPositionDelta(interval);
+ gfx::Vector2d delta_discrete =
+ FloorTowardZero(total_delta_ - total_delta_discrete_);
+ ForwardMouseWheelEvent(target, delta_discrete);
+ total_delta_discrete_ += delta_discrete;
+ }
+ if (HasScrolledEntireDistance())
+ state_ = DONE;
+ break;
+ case SETUP:
+ NOTREACHED()
+ << "State STARTED invalid for synthetic scroll using touch input.";
+ case STOPPING:
+ NOTREACHED()
+ << "State STOPPING invalid for synthetic scroll using touch input.";
+ case DONE:
+ NOTREACHED()
+ << "State DONE invalid for synthetic scroll using touch input.";
+ }
+}
+
+void SyntheticSmoothScrollGesture::ForwardTouchEvent(
+ SyntheticGestureTarget* target) const {
+ target->DispatchInputEventToPlatform(
+ InputEvent(touch_event_, ui::LatencyInfo(), false));
+}
+
+void SyntheticSmoothScrollGesture::ForwardMouseWheelEvent(
+ SyntheticGestureTarget* target, const gfx::Vector2dF& delta) const {
+ blink::WebMouseWheelEvent mouse_wheel_event =
+ SyntheticWebMouseWheelEventBuilder::Build(delta.x(), delta.y(), 0, false);
+
+ mouse_wheel_event.x = params_.anchor.x();
+ mouse_wheel_event.y = params_.anchor.y();
+
+ target->DispatchInputEventToPlatform(
+ InputEvent(mouse_wheel_event, ui::LatencyInfo(), false));
+}
+
+void SyntheticSmoothScrollGesture::PressTouchPoint(
+ SyntheticGestureTarget* target) {
+ touch_event_.PressPoint(params_.anchor.x(), params_.anchor.y());
+ ForwardTouchEvent(target);
+}
+
+void SyntheticSmoothScrollGesture::MoveTouchPoint(
+ SyntheticGestureTarget* target) {
+ gfx::PointF touch_position = params_.anchor + total_delta_;
+ touch_event_.MovePoint(0, touch_position.x(), touch_position.y());
+ ForwardTouchEvent(target);
+}
+
+void SyntheticSmoothScrollGesture::ReleaseTouchPoint(
+ SyntheticGestureTarget* target) {
+ touch_event_.ReleasePoint(0);
+ ForwardTouchEvent(target);
+}
+
+void SyntheticSmoothScrollGesture::AddTouchSlopToDistance(
+ SyntheticGestureTarget* target) {
+ // Android uses euclidean distance to compute if a touch pointer has moved
+ // beyond the slop, while Aura uses Manhattan distance. We're using Euclidean
+ // distance and round up to the nearest integer.
+ // For vertical and horizontal scrolls (the common case), both methods produce
+ // the same result.
+ gfx::Vector2dF touch_slop_delta = ProjectLengthOntoScrollDirection(
+ target->GetTouchSlopInDips());
+ params_.distance += CeilFromZero(touch_slop_delta);
+}
+
+gfx::Vector2dF SyntheticSmoothScrollGesture::GetPositionDelta(
+ const base::TimeDelta& interval) const {
+ float delta_length = params_.speed_in_pixels_s * interval.InSecondsF();
+
+ // Make sure we're not scrolling too far.
+ gfx::Vector2dF remaining_delta = ComputeRemainingDelta();
+ if (delta_length > remaining_delta.Length())
+ // In order to scroll in a certain direction we need to move the
+ // touch pointer/mouse wheel in the opposite direction.
+ return -remaining_delta;
+ else
+ return -ProjectLengthOntoScrollDirection(delta_length);
+}
+
+gfx::Vector2dF SyntheticSmoothScrollGesture::ProjectLengthOntoScrollDirection(
+ float delta_length) const {
+ const float kTotalLength = params_.distance.Length();
+ return ScaleVector2d(params_.distance, delta_length / kTotalLength);
+}
+
+gfx::Vector2dF SyntheticSmoothScrollGesture::ComputeRemainingDelta() const {
+ return params_.distance + total_delta_;
+}
+
+bool SyntheticSmoothScrollGesture::HasScrolledEntireDistance() const {
+ return ComputeRemainingDelta().IsZero();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h
new file mode 100644
index 00000000000..53b4da54683
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h
@@ -0,0 +1,70 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_H_
+
+#include "base/time/time.h"
+#include "content/browser/renderer_host/input/synthetic_gesture.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
+#include "content/common/content_export.h"
+#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/gfx/vector2d.h"
+#include "ui/gfx/vector2d_f.h"
+
+namespace content {
+
+class CONTENT_EXPORT SyntheticSmoothScrollGesture : public SyntheticGesture {
+ public:
+ explicit SyntheticSmoothScrollGesture(
+ const SyntheticSmoothScrollGestureParams& params);
+ virtual ~SyntheticSmoothScrollGesture();
+
+ virtual SyntheticGesture::Result ForwardInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target) OVERRIDE;
+
+ private:
+ enum GestureState {
+ SETUP,
+ STARTED,
+ MOVING,
+ STOPPING,
+ DONE
+ };
+
+ void ForwardTouchInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target);
+ void ForwardMouseInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target);
+
+ void ForwardTouchEvent(SyntheticGestureTarget* target) const;
+ void ForwardMouseWheelEvent(SyntheticGestureTarget* target,
+ const gfx::Vector2dF& delta) const;
+
+ void PressTouchPoint(SyntheticGestureTarget* target);
+ void MoveTouchPoint(SyntheticGestureTarget* target);
+ void ReleaseTouchPoint(SyntheticGestureTarget* target);
+
+ void AddTouchSlopToDistance(SyntheticGestureTarget* target);
+ gfx::Vector2dF GetPositionDelta(const base::TimeDelta& interval) const;
+ gfx::Vector2dF ProjectLengthOntoScrollDirection(float delta_length) const;
+ gfx::Vector2dF ComputeRemainingDelta() const;
+ bool HasScrolledEntireDistance() const;
+
+ SyntheticSmoothScrollGestureParams params_;
+ gfx::Vector2dF total_delta_;
+ gfx::Vector2d total_delta_discrete_;
+ SyntheticWebTouchEvent touch_event_;
+ SyntheticGestureParams::GestureSourceType gesture_source_type_;
+ GestureState state_;
+ base::TimeDelta total_stopping_wait_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyntheticSmoothScrollGesture);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_H_
diff --git a/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc
new file mode 100644
index 00000000000..1f15d82f013
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc
@@ -0,0 +1,119 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
+
+#include "base/logging.h"
+#include "content/common/input/input_event.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/latency_info.h"
+
+namespace content {
+namespace {
+
+void DispatchEventToPlatform(SyntheticGestureTarget* target,
+ const blink::WebInputEvent& event) {
+ target->DispatchInputEventToPlatform(
+ InputEvent(event, ui::LatencyInfo(), false));
+}
+
+} // namespace
+
+SyntheticTapGesture::SyntheticTapGesture(
+ const SyntheticTapGestureParams& params)
+ : params_(params),
+ gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT),
+ state_(SETUP) {
+ DCHECK_GE(params_.duration_ms, 0);
+}
+
+SyntheticTapGesture::~SyntheticTapGesture() {}
+
+SyntheticGesture::Result SyntheticTapGesture::ForwardInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target) {
+ if (state_ == SETUP) {
+ gesture_source_type_ = params_.gesture_source_type;
+ if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT)
+ gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType();
+
+ if (!target->SupportsSyntheticGestureSourceType(gesture_source_type_))
+ return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM;
+
+ state_ = PRESS;
+ }
+
+ DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
+ if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT ||
+ gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT)
+ ForwardTouchOrMouseInputEvents(interval, target);
+ else
+ return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
+
+ return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED
+ : SyntheticGesture::GESTURE_RUNNING;
+}
+
+void SyntheticTapGesture::ForwardTouchOrMouseInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target) {
+ switch (state_) {
+ case PRESS:
+ Press(target);
+ // Release immediately if duration is 0.
+ if (params_.duration_ms == 0) {
+ Release(target);
+ state_ = DONE;
+ } else {
+ state_ = WAITING_TO_RELEASE;
+ }
+ break;
+ case WAITING_TO_RELEASE:
+ total_waiting_time_ += interval;
+ if (total_waiting_time_ >=
+ base::TimeDelta::FromMilliseconds(params_.duration_ms)) {
+ Release(target);
+ state_ = DONE;
+ }
+ break;
+ case SETUP:
+ NOTREACHED() << "State SETUP invalid for synthetic tap gesture.";
+ case DONE:
+ NOTREACHED() << "State DONE invalid for synthetic tap gesture.";
+ }
+}
+
+void SyntheticTapGesture::Press(SyntheticGestureTarget* target) {
+ if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) {
+ touch_event_.PressPoint(params_.position.x(), params_.position.y());
+ DispatchEventToPlatform(target, touch_event_);
+ } else if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) {
+ blink::WebMouseEvent mouse_event =
+ SyntheticWebMouseEventBuilder::Build(blink::WebInputEvent::MouseDown,
+ params_.position.x(),
+ params_.position.y(),
+ 0);
+ mouse_event.clickCount = 1;
+ DispatchEventToPlatform(target, mouse_event);
+ } else {
+ NOTREACHED() << "Invalid gesture source type for synthetic tap gesture.";
+ }
+}
+
+void SyntheticTapGesture::Release(SyntheticGestureTarget* target) {
+ if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) {
+ touch_event_.ReleasePoint(0);
+ DispatchEventToPlatform(target, touch_event_);
+ } else if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) {
+ blink::WebMouseEvent mouse_event =
+ SyntheticWebMouseEventBuilder::Build(blink::WebInputEvent::MouseUp,
+ params_.position.x(),
+ params_.position.y(),
+ 0);
+ mouse_event.clickCount = 1;
+ DispatchEventToPlatform(target, mouse_event);
+ } else {
+ NOTREACHED() << "Invalid gesture source type for synthetic tap gesture.";
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h
new file mode 100644
index 00000000000..22217f99090
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h
@@ -0,0 +1,49 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TAP_GESTURE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TAP_GESTURE_H_
+
+#include "content/browser/renderer_host/input/synthetic_gesture.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
+#include "content/common/content_export.h"
+#include "content/common/input/synthetic_tap_gesture_params.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+
+namespace content {
+
+class CONTENT_EXPORT SyntheticTapGesture : public SyntheticGesture {
+ public:
+ explicit SyntheticTapGesture(const SyntheticTapGestureParams& params);
+ virtual ~SyntheticTapGesture();
+
+ virtual SyntheticGesture::Result ForwardInputEvents(
+ const base::TimeDelta& interval, SyntheticGestureTarget* target) OVERRIDE;
+
+ private:
+ enum GestureState {
+ SETUP,
+ PRESS,
+ WAITING_TO_RELEASE,
+ DONE
+ };
+
+ void ForwardTouchOrMouseInputEvents(const base::TimeDelta& interval,
+ SyntheticGestureTarget* target);
+
+ void Press(SyntheticGestureTarget* target);
+ void Release(SyntheticGestureTarget* target);
+
+ SyntheticTapGestureParams params_;
+ base::TimeDelta total_waiting_time_;
+ SyntheticWebTouchEvent touch_event_;
+ SyntheticGestureParams::GestureSourceType gesture_source_type_;
+ GestureState state_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyntheticTapGesture);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TAP_GESTURE_H_
diff --git a/chromium/content/browser/renderer_host/input/tap_suppression_controller.cc b/chromium/content/browser/renderer_host/input/tap_suppression_controller.cc
index 387576c2c2a..641af6ad108 100644
--- a/chromium/content/browser/renderer_host/input/tap_suppression_controller.cc
+++ b/chromium/content/browser/renderer_host/input/tap_suppression_controller.cc
@@ -45,7 +45,7 @@ void TapSuppressionController::GestureFlingCancelAck(bool processed) {
TRACE_EVENT0("browser",
"TapSuppressionController::GestureFlingCancelAck");
StopTapDownTimer();
- client_->ForwardStashedTapDownForDeferral();
+ client_->ForwardStashedTapDown();
state_ = NOTHING;
} // Else waiting for the timer to release the stashed tap down.
break;
@@ -84,7 +84,7 @@ bool TapSuppressionController::ShouldDeferTapDown() {
return false;
}
-bool TapSuppressionController::ShouldSuppressTapUp() {
+bool TapSuppressionController::ShouldSuppressTapEnd() {
switch (state_) {
case NOTHING:
case GFC_IN_PROGRESS:
@@ -95,23 +95,7 @@ bool TapSuppressionController::ShouldSuppressTapUp() {
client_->DropStashedTapDown();
return true;
case LAST_CANCEL_STOPPED_FLING:
- NOTREACHED() << "Invalid TapUp on LAST_CANCEL_STOPPED_FLING state";
- }
- return false;
-}
-
-bool TapSuppressionController::ShouldSuppressTapCancel() {
- switch (state_) {
- case NOTHING:
- case GFC_IN_PROGRESS:
- return false;
- case TAP_DOWN_STASHED:
- state_ = NOTHING;
- StopTapDownTimer();
- client_->DropStashedTapDown();
- return true;
- case LAST_CANCEL_STOPPED_FLING:
- NOTREACHED() << "Invalid TapCancel on LAST_CANCEL_STOPPED_FLING state";
+ NOTREACHED() << "Invalid tap end on LAST_CANCEL_STOPPED_FLING state";
}
return false;
}
@@ -140,7 +124,7 @@ void TapSuppressionController::TapDownTimerExpired() {
case TAP_DOWN_STASHED:
TRACE_EVENT0("browser",
"TapSuppressionController::TapDownTimerExpired");
- client_->ForwardStashedTapDownSkipDeferral();
+ client_->ForwardStashedTapDown();
state_ = NOTHING;
break;
}
diff --git a/chromium/content/browser/renderer_host/input/tap_suppression_controller.h b/chromium/content/browser/renderer_host/input/tap_suppression_controller.h
index b355a0dda2d..ef662f32f7b 100644
--- a/chromium/content/browser/renderer_host/input/tap_suppression_controller.h
+++ b/chromium/content/browser/renderer_host/input/tap_suppression_controller.h
@@ -35,13 +35,9 @@ class CONTENT_EXPORT TapSuppressionController {
// for keeping the event for later release, if needed.
bool ShouldDeferTapDown();
- // Should be called whenever a tap up (touchpad or touchscreen) is received.
- // Returns true if the tap up should be suppressed.
- bool ShouldSuppressTapUp();
-
- // Should be called whenever a tap cancel is received. Returns true if the tap
- // cancel should be suppressed.
- bool ShouldSuppressTapCancel();
+ // Should be called whenever a tap ending event is received. Returns true if
+ // the tap event should be suppressed.
+ bool ShouldSuppressTapEnd();
protected:
virtual base::TimeTicks Now();
diff --git a/chromium/content/browser/renderer_host/input/tap_suppression_controller_client.h b/chromium/content/browser/renderer_host/input/tap_suppression_controller_client.h
index 821f5467920..fcea0e1f58e 100644
--- a/chromium/content/browser/renderer_host/input/tap_suppression_controller_client.h
+++ b/chromium/content/browser/renderer_host/input/tap_suppression_controller_client.h
@@ -25,14 +25,9 @@ class TapSuppressionControllerClient {
virtual void DropStashedTapDown() = 0;
// Called whenever the deferred tap down (if saved) should be forwarded to the
- // renderer. In this case, the tap down should go back to normal path it was
+ // renderer. The tap down should go back to normal path it was
// on before being deferred.
- virtual void ForwardStashedTapDownForDeferral() = 0;
-
- // Called whenever the deferred tap down (if saved) should be forwarded to the
- // renderer. In this case, the tap down should skip deferral filter, because
- // it is handled here, and there is no need to delay it more.
- virtual void ForwardStashedTapDownSkipDeferral() = 0;
+ virtual void ForwardStashedTapDown() = 0;
protected:
TapSuppressionControllerClient() {}
diff --git a/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc b/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
index a31471eaef9..d436f45a4a5 100644
--- a/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
@@ -4,8 +4,8 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-#include "content/browser/renderer_host/tap_suppression_controller.h"
-#include "content/browser/renderer_host/tap_suppression_controller_client.h"
+#include "content/browser/renderer_host/input/tap_suppression_controller.h"
+#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::TimeDelta;
@@ -29,8 +29,7 @@ class MockTapSuppressionController : public TapSuppressionController,
TAP_UP_FORWARDED = 1 << 4,
TAP_CANCEL_SUPPRESSED = 1 << 5,
TAP_CANCEL_FORWARDED = 1 << 6,
- TAP_DOWN_FORWARDED_FOR_DEFERRAL = 1 << 7,
- TAP_DOWN_FORWARDED_SKIPPING_DEFERRAL = 1 << 8,
+ STASHED_TAP_DOWN_FORWARDED = 1 << 7,
};
MockTapSuppressionController()
@@ -64,7 +63,7 @@ class MockTapSuppressionController : public TapSuppressionController,
void SendTapUp() {
last_actions_ = NONE;
- if (ShouldSuppressTapUp())
+ if (ShouldSuppressTapEnd())
last_actions_ |= TAP_UP_SUPPRESSED;
else
last_actions_ |= TAP_UP_FORWARDED;
@@ -72,7 +71,7 @@ class MockTapSuppressionController : public TapSuppressionController,
void SendTapCancel() {
last_actions_ = NONE;
- if (ShouldSuppressTapCancel())
+ if (ShouldSuppressTapEnd())
last_actions_ |= TAP_CANCEL_SUPPRESSED;
else
last_actions_ |= TAP_CANCEL_FORWARDED;
@@ -127,20 +126,15 @@ class MockTapSuppressionController : public TapSuppressionController,
last_actions_ |= TAP_DOWN_DROPPED;
}
- virtual void ForwardStashedTapDownForDeferral() OVERRIDE {
- last_actions_ |= TAP_DOWN_FORWARDED_FOR_DEFERRAL;
- }
-
- virtual void ForwardStashedTapDownSkipDeferral() OVERRIDE {
- last_actions_ |= TAP_DOWN_FORWARDED_SKIPPING_DEFERRAL;
+ virtual void ForwardStashedTapDown() OVERRIDE {
+ last_actions_ |= STASHED_TAP_DOWN_FORWARDED;
}
// Hiding some derived public methods
using TapSuppressionController::GestureFlingCancel;
using TapSuppressionController::GestureFlingCancelAck;
using TapSuppressionController::ShouldDeferTapDown;
- using TapSuppressionController::ShouldSuppressTapUp;
- using TapSuppressionController::ShouldSuppressTapCancel;
+ using TapSuppressionController::ShouldSuppressTapEnd;
int max_cancel_to_down_time_in_ms_;
int max_tap_gap_time_in_ms_;
@@ -284,7 +278,7 @@ TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapSufficientlyLateTapUp) {
// Wait more than allowed delay between TapDown and TapUp, so they are not
// considered a tap. This should release the previously suppressed TapDown.
tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(13));
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_FORWARDED_SKIPPING_DEFERRAL,
+ EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::NOTHING,
tap_suppression_controller_->state());
@@ -407,7 +401,7 @@ TEST_F(TapSuppressionControllerTest, GFCAckUnprocessedAfterTapFast) {
// Send unprocessed GestureFlingCancel Ack. This should release the
// previously suppressed TapDown.
tap_suppression_controller_->SendGestureFlingCancelAck(false);
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_FORWARDED_FOR_DEFERRAL,
+ EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::NOTHING,
tap_suppression_controller_->state());
@@ -530,7 +524,7 @@ TEST_F(TapSuppressionControllerTest, GFCAckAfterTapSufficientlyLateTapUp) {
// Wait more than allowed delay between TapDown and TapUp, so they are not
// considered as a tap. This should release the previously suppressed TapDown.
tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(13));
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_FORWARDED_SKIPPING_DEFERRAL,
+ EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::NOTHING,
tap_suppression_controller_->state());
diff --git a/chromium/content/browser/renderer_host/input/timeout_monitor.cc b/chromium/content/browser/renderer_host/input/timeout_monitor.cc
new file mode 100644
index 00000000000..93b310286b0
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/timeout_monitor.cc
@@ -0,0 +1,78 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/timeout_monitor.h"
+
+using base::Time;
+using base::TimeDelta;
+
+namespace content {
+
+TimeoutMonitor::TimeoutMonitor(const TimeoutHandler& timeout_handler)
+ : timeout_handler_(timeout_handler) {
+ DCHECK(!timeout_handler_.is_null());
+}
+
+TimeoutMonitor::~TimeoutMonitor() {}
+
+void TimeoutMonitor::Start(TimeDelta delay) {
+ // Set time_when_considered_timed_out_ if it's null. Also, update
+ // time_when_considered_timed_out_ if the caller's request is sooner than the
+ // existing one. This will have the side effect that the existing timeout will
+ // be forgotten.
+ Time requested_end_time = Time::Now() + delay;
+ if (time_when_considered_timed_out_.is_null() ||
+ time_when_considered_timed_out_ > requested_end_time)
+ time_when_considered_timed_out_ = requested_end_time;
+
+ // If we already have a timer with the same or shorter duration, then we can
+ // wait for it to finish.
+ if (timeout_timer_.IsRunning() && timeout_timer_.GetCurrentDelay() <= delay) {
+ // If time_when_considered_timed_out_ was null, this timer may fire early.
+ // CheckTimedOut handles that that by calling Start with the remaining time.
+ // If time_when_considered_timed_out_ was non-null, it means we still
+ // haven't been stopped, so we leave time_when_considered_timed_out_ as is.
+ return;
+ }
+
+ // Either the timer is not yet running, or we need to adjust the timer to
+ // fire sooner.
+ time_when_considered_timed_out_ = requested_end_time;
+ timeout_timer_.Stop();
+ timeout_timer_.Start(FROM_HERE, delay, this, &TimeoutMonitor::CheckTimedOut);
+}
+
+void TimeoutMonitor::Restart(TimeDelta delay) {
+ // Setting to null will cause StartTimeoutMonitor to restart the timer.
+ time_when_considered_timed_out_ = Time();
+ Start(delay);
+}
+
+void TimeoutMonitor::Stop() {
+ // We do not bother to stop the timeout_timer_ here in case it will be
+ // started again shortly, which happens to be the common use case.
+ time_when_considered_timed_out_ = Time();
+}
+
+void TimeoutMonitor::CheckTimedOut() {
+ // If we received a call to |Stop()|.
+ if (time_when_considered_timed_out_.is_null())
+ return;
+
+ // If we have not waited long enough, then wait some more.
+ Time now = Time::Now();
+ if (now < time_when_considered_timed_out_) {
+ Start(time_when_considered_timed_out_ - now);
+ return;
+ }
+
+ timeout_handler_.Run();
+}
+
+bool TimeoutMonitor::IsRunning() const {
+ return timeout_timer_.IsRunning() &&
+ !time_when_considered_timed_out_.is_null();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/timeout_monitor.h b/chromium/content/browser/renderer_host/input/timeout_monitor.h
new file mode 100644
index 00000000000..88154e86e75
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/timeout_monitor.h
@@ -0,0 +1,50 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_TIMEOUT_MONITOR_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TIMEOUT_MONITOR_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Utility class for handling a timeout callback with periodic starts and stops.
+class CONTENT_EXPORT TimeoutMonitor {
+ public:
+ typedef base::Closure TimeoutHandler;
+
+ explicit TimeoutMonitor(const TimeoutHandler& timeout_handler);
+ ~TimeoutMonitor();
+
+ // Schedule the timeout timer to fire at |delay| into the future. If a timeout
+ // has already been scheduled, reschedule only if |delay| is sooner than the
+ // currently scheduled timeout time.
+ void Start(base::TimeDelta delay);
+
+ void Restart(base::TimeDelta delay);
+ void Stop();
+ bool IsRunning() const;
+
+ private:
+ void CheckTimedOut();
+
+ TimeoutHandler timeout_handler_;
+
+ // Indicates a time in the future when we would consider the input as
+ // having timed out, if it does not receive an appropriate stop request.
+ base::Time time_when_considered_timed_out_;
+
+ // This timer runs to check if |time_when_considered_timed_out_| has past.
+ base::OneShotTimer<TimeoutMonitor> timeout_timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(TimeoutMonitor);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TIMEOUT_MONITOR_H_
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter.cc b/chromium/content/browser/renderer_host/input/touch_action_filter.cc
new file mode 100644
index 00000000000..665ff15bd30
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.cc
@@ -0,0 +1,63 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/touch_action_filter.h"
+
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+using blink::WebInputEvent;
+using blink::WebGestureEvent;
+
+namespace content {
+
+TouchActionFilter::TouchActionFilter() :
+ drop_scroll_gesture_events_(false),
+ allowed_touch_action_(TOUCH_ACTION_AUTO) {
+}
+
+bool TouchActionFilter::FilterGestureEvent(
+ const WebGestureEvent& gesture_event) {
+ // Filter for allowable touch actions first (eg. before the TouchEventQueue
+ // can decide to send a touch cancel event).
+ // TODO(rbyers): Add touch-action control over for pinch. crbug.com/247566.
+ switch(gesture_event.type) {
+ case WebInputEvent::GestureScrollBegin:
+ if (allowed_touch_action_ == TOUCH_ACTION_NONE)
+ drop_scroll_gesture_events_ = true;
+ // FALL THROUGH
+ case WebInputEvent::GestureScrollUpdate:
+ if (drop_scroll_gesture_events_)
+ return true;
+ break;
+
+ case WebInputEvent::GestureScrollEnd:
+ case WebInputEvent::GestureFlingStart:
+ allowed_touch_action_ = content::TOUCH_ACTION_AUTO;
+ if (drop_scroll_gesture_events_) {
+ drop_scroll_gesture_events_ = false;
+ return true;
+ }
+ break;
+
+ default:
+ // Gesture events unrelated to touch actions (panning/zooming) are left
+ // alone.
+ break;
+ }
+
+ return false;
+}
+
+void TouchActionFilter::OnSetTouchAction(
+ content::TouchAction touch_action) {
+ // For multiple fingers, we take the intersection of the touch actions for
+ // all fingers that have gone down during this action.
+ // TODO(rbyers): What exact multi-finger semantic do we want? This is left
+ // as implementation-defined in the pointer events specification.
+ // crbug.com/247566.
+ if (touch_action == content::TOUCH_ACTION_NONE)
+ allowed_touch_action_ = content::TOUCH_ACTION_NONE;
+}
+
+}
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter.h b/chromium/content/browser/renderer_host/input/touch_action_filter.h
new file mode 100644
index 00000000000..6485c45a935
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.h
@@ -0,0 +1,45 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_ACTION_FILTER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_ACTION_FILTER_H_
+
+#include "base/basictypes.h"
+#include "content/common/content_export.h"
+#include "content/common/input/touch_action.h"
+
+namespace blink {
+class WebGestureEvent;
+}
+
+namespace content {
+
+// The TouchActionFilter is responsible for filtering scroll and pinch gesture
+// events according to the CSS touch-action values the renderer has sent for
+// each touch point.
+// For details see the touch-action design doc at http://goo.gl/KcKbxQ.
+class CONTENT_EXPORT TouchActionFilter {
+public:
+ TouchActionFilter();
+
+ // Returns true if the supplied gesture event should be dropped based on
+ // the current touch-action state.
+ bool FilterGestureEvent(const blink::WebGestureEvent& gesture_event);
+
+ // Called when a set-touch-action message is received from the renderer
+ // for a touch start event that is currently in flight.
+ void OnSetTouchAction(content::TouchAction touch_action);
+
+private:
+ // Whether GestureScroll events should be discarded due to touch-action.
+ bool drop_scroll_gesture_events_;
+
+ // What touch actions are currently permitted.
+ content::TouchAction allowed_touch_action_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchActionFilter);
+};
+
+}
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_ACTION_FILTER_H_
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc b/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc
new file mode 100644
index 00000000000..a07ef09dfbe
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc
@@ -0,0 +1,100 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/touch_action_filter.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/port/browser/event_with_latency_info.h"
+#include "content/port/common/input_event_ack_state.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+
+namespace content {
+
+TEST(TouchActionFilterTest, SimpleFilter) {
+ TouchActionFilter filter;
+
+ const WebGestureEvent scroll_begin = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::GestureScrollBegin, WebGestureEvent::Touchscreen);
+ const WebGestureEvent scroll_update =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(0, 10, 0);
+ const WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::GestureScrollEnd, WebGestureEvent::Touchscreen);
+ const WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::GestureTap, WebGestureEvent::Touchscreen);
+
+ // No events filtered by default.
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_end));
+ EXPECT_FALSE(filter.FilterGestureEvent(tap));
+
+ // TOUCH_ACTION_AUTO doesn't cause any filtering.
+ filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_end));
+
+ // TOUCH_ACTION_NONE filters out all scroll events, but no other events.
+ filter.OnSetTouchAction(TOUCH_ACTION_NONE);
+ EXPECT_FALSE(filter.FilterGestureEvent(tap));
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_begin));
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_end));
+
+ // After the end of a gesture the state is reset.
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_end));
+
+ // Setting touch action doesn't impact any in-progress gestures.
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_begin));
+ filter.OnSetTouchAction(TOUCH_ACTION_NONE);
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_end));
+
+ // And the state is still cleared for the next gesture.
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(scroll_end));
+
+ // Changing the touch action during a gesture has no effect.
+ filter.OnSetTouchAction(TOUCH_ACTION_NONE);
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_begin));
+ filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_end));
+}
+
+TEST(TouchActionFilterTest, MultiTouch) {
+ TouchActionFilter filter;
+
+ const WebGestureEvent scroll_begin = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::GestureScrollBegin, WebGestureEvent::Touchscreen);
+ const WebGestureEvent scroll_update =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(0, 10, 0);
+ const WebGestureEvent scrollEnd = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::GestureScrollEnd, WebGestureEvent::Touchscreen);
+
+ // For multiple points, the intersection is what matters.
+ filter.OnSetTouchAction(TOUCH_ACTION_NONE);
+ filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_begin));
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_TRUE(filter.FilterGestureEvent(scrollEnd));
+
+ filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
+ filter.OnSetTouchAction(TOUCH_ACTION_NONE);
+ filter.OnSetTouchAction(TOUCH_ACTION_AUTO);
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_begin));
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_TRUE(filter.FilterGestureEvent(scroll_update));
+ EXPECT_TRUE(filter.FilterGestureEvent(scrollEnd));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue.cc b/chromium/content/browser/renderer_host/input/touch_event_queue.cc
index e22c05d0f80..3524b18250e 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.cc
@@ -5,13 +5,165 @@
#include "content/browser/renderer_host/input/touch_event_queue.h"
#include "base/auto_reset.h"
+#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/stl_util.h"
+#include "content/browser/renderer_host/input/timeout_monitor.h"
+#include "content/common/input/web_input_event_traits.h"
+#include "content/public/common/content_switches.h"
+
+using blink::WebInputEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
namespace content {
+namespace {
+
+const InputEventAckState kDefaultNotForwardedAck =
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
+TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
+ const TouchEventWithLatencyInfo& event_to_cancel) {
+ TouchEventWithLatencyInfo event = event_to_cancel;
+ event.event.type = WebInputEvent::TouchCancel;
+ for (size_t i = 0; i < event.event.touchesLength; i++)
+ event.event.touches[i].state = WebTouchPoint::StateCancelled;
+ return event;
+}
+
+bool IsNewTouchGesture(const WebTouchEvent& event) {
+ if (event.type != WebInputEvent::TouchStart)
+ return false;
+ if (!event.touchesLength)
+ return false;
+ for (size_t i = 0; i < event.touchesLength; i++) {
+ if (event.touches[i].state != WebTouchPoint::StatePressed)
+ return false;
+ }
+ return true;
+}
+
+bool ShouldTouchTypeTriggerTimeout(WebInputEvent::Type type) {
+ return type == WebInputEvent::TouchStart ||
+ type == WebInputEvent::TouchMove;
+}
+
+} // namespace
+
+class TouchEventQueue::TouchTimeoutHandler {
+ public:
+ TouchTimeoutHandler(TouchEventQueue* touch_queue, size_t timeout_delay_ms)
+ : touch_queue_(touch_queue),
+ timeout_delay_(base::TimeDelta::FromMilliseconds(timeout_delay_ms)),
+ pending_ack_state_(PENDING_ACK_NONE),
+ timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut,
+ base::Unretained(this))) {}
+
+ ~TouchTimeoutHandler() {}
+
+ void Start(const TouchEventWithLatencyInfo& event) {
+ DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE);
+ DCHECK(ShouldTouchTypeTriggerTimeout(event.event.type));
+ timeout_event_ = event;
+ timeout_monitor_.Restart(timeout_delay_);
+ }
+
+ bool ConfirmTouchEvent(InputEventAckState ack_result) {
+ switch (pending_ack_state_) {
+ case PENDING_ACK_NONE:
+ timeout_monitor_.Stop();
+ return false;
+ case PENDING_ACK_ORIGINAL_EVENT:
+ if (AckedTimeoutEventRequiresCancel(ack_result)) {
+ SetPendingAckState(PENDING_ACK_CANCEL_EVENT);
+ TouchEventWithLatencyInfo cancel_event =
+ ObtainCancelEventForTouchEvent(timeout_event_);
+ touch_queue_->UpdateTouchAckStates(
+ cancel_event.event, kDefaultNotForwardedAck);
+ touch_queue_->client_->SendTouchEventImmediately(cancel_event);
+ } else {
+ SetPendingAckState(PENDING_ACK_NONE);
+ touch_queue_->UpdateTouchAckStates(timeout_event_.event, ack_result);
+ }
+ return true;
+ case PENDING_ACK_CANCEL_EVENT:
+ SetPendingAckState(PENDING_ACK_NONE);
+ return true;
+ }
+ return false;
+ }
+
+ bool HasTimeoutEvent() const {
+ return pending_ack_state_ != PENDING_ACK_NONE;
+ }
+
+ bool IsTimeoutTimerRunning() const {
+ return timeout_monitor_.IsRunning();
+ }
+
+ private:
+ enum PendingAckState {
+ PENDING_ACK_NONE,
+ PENDING_ACK_ORIGINAL_EVENT,
+ PENDING_ACK_CANCEL_EVENT,
+ };
+
+ void OnTimeOut() {
+ SetPendingAckState(PENDING_ACK_ORIGINAL_EVENT);
+ touch_queue_->FlushQueue();
+ }
+
+ // Skip a cancel event if the timed-out event had no consumer and was the
+ // initial event in the gesture.
+ bool AckedTimeoutEventRequiresCancel(InputEventAckState ack_result) const {
+ DCHECK(HasTimeoutEvent());
+ if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
+ return true;
+ return !IsNewTouchGesture(timeout_event_.event);
+ }
+
+ void SetPendingAckState(PendingAckState new_pending_ack_state) {
+ DCHECK_NE(pending_ack_state_, new_pending_ack_state);
+ switch (new_pending_ack_state) {
+ case PENDING_ACK_ORIGINAL_EVENT:
+ DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE);
+ TRACE_EVENT_ASYNC_BEGIN0("input", "TouchEventTimeout", this);
+ break;
+ case PENDING_ACK_CANCEL_EVENT:
+ DCHECK_EQ(pending_ack_state_, PENDING_ACK_ORIGINAL_EVENT);
+ DCHECK(!timeout_monitor_.IsRunning());
+ DCHECK(touch_queue_->empty());
+ TRACE_EVENT_ASYNC_STEP_INTO0(
+ "input", "TouchEventTimeout", this, "CancelEvent");
+ break;
+ case PENDING_ACK_NONE:
+ DCHECK(!timeout_monitor_.IsRunning());
+ DCHECK(touch_queue_->empty());
+ TRACE_EVENT_ASYNC_END0("input", "TouchEventTimeout", this);
+ break;
+ }
+ pending_ack_state_ = new_pending_ack_state;
+ }
+
+
+ TouchEventQueue* touch_queue_;
+
+ // How long to wait on a touch ack before cancelling the touch sequence.
+ base::TimeDelta timeout_delay_;
+
+ // The touch event source for which we expect the next ack.
+ PendingAckState pending_ack_state_;
+
+ // The event for which the ack timeout is triggered.
+ TouchEventWithLatencyInfo timeout_event_;
+
+ // Provides timeout-based callback behavior.
+ TimeoutMonitor timeout_monitor_;
+};
+
+
// This class represents a single coalesced touch event. However, it also keeps
// track of all the original touch-events that were coalesced into a single
// event. The coalesced event is forwarded to the renderer, while the original
@@ -19,8 +171,10 @@ typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
// the Client receives the event with their original timestamp.
class CoalescedWebTouchEvent {
public:
- explicit CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event)
- : coalesced_event_(event) {
+ CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event,
+ bool ignore_ack)
+ : coalesced_event_(event),
+ ignore_ack_(ignore_ack) {
events_.push_back(event);
TRACE_EVENT_ASYNC_BEGIN0(
"input", "TouchEventQueue::QueueEvent", this);
@@ -35,50 +189,35 @@ class CoalescedWebTouchEvent {
// the event was coalesced.
bool CoalesceEventIfPossible(
const TouchEventWithLatencyInfo& event_with_latency) {
- if (coalesced_event_.event.type == WebKit::WebInputEvent::TouchMove &&
- event_with_latency.event.type == WebKit::WebInputEvent::TouchMove &&
- coalesced_event_.event.modifiers ==
- event_with_latency.event.modifiers &&
- coalesced_event_.event.touchesLength ==
- event_with_latency.event.touchesLength) {
- TRACE_EVENT_INSTANT0(
- "input", "TouchEventQueue::MoveCoalesced", TRACE_EVENT_SCOPE_THREAD);
- events_.push_back(event_with_latency);
- // The WebTouchPoints include absolute position information. So it is
- // sufficient to simply replace the previous event with the new event.
- // However, it is necessary to make sure that all the points have the
- // correct state, i.e. the touch-points that moved in the last event, but
- // didn't change in the current event, will have Stationary state. It is
- // necessary to change them back to Moved state.
- const WebKit::WebTouchEvent last_event = coalesced_event_.event;
- const ui::LatencyInfo last_latency = coalesced_event_.latency;
- coalesced_event_ = event_with_latency;
- coalesced_event_.latency.MergeWith(last_latency);
- for (unsigned i = 0; i < last_event.touchesLength; ++i) {
- if (last_event.touches[i].state == WebKit::WebTouchPoint::StateMoved)
- coalesced_event_.event.touches[i].state =
- WebKit::WebTouchPoint::StateMoved;
- }
- return true;
- }
+ if (ignore_ack_)
+ return false;
- return false;
+ if (!coalesced_event_.CanCoalesceWith(event_with_latency))
+ return false;
+
+ TRACE_EVENT_INSTANT0(
+ "input", "TouchEventQueue::MoveCoalesced", TRACE_EVENT_SCOPE_THREAD);
+ coalesced_event_.CoalesceWith(event_with_latency);
+ events_.push_back(event_with_latency);
+ return true;
}
const TouchEventWithLatencyInfo& coalesced_event() const {
return coalesced_event_;
}
- WebTouchEventWithLatencyList::const_iterator begin() const {
+ WebTouchEventWithLatencyList::iterator begin() {
return events_.begin();
}
- WebTouchEventWithLatencyList::const_iterator end() const {
+ WebTouchEventWithLatencyList::iterator end() {
return events_.end();
}
size_t size() const { return events_.size(); }
+ bool ignore_ack() const { return ignore_ack_; }
+
private:
// This is the event that is forwarded to the renderer.
TouchEventWithLatencyInfo coalesced_event_;
@@ -86,13 +225,20 @@ class CoalescedWebTouchEvent {
// This is the list of the original events that were coalesced.
WebTouchEventWithLatencyList events_;
+ // If |ignore_ack_| is true, don't send this touch event to client
+ // when the event is acked.
+ bool ignore_ack_;
+
DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent);
};
TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client)
: client_(client),
- dispatching_touch_ack_(false),
- no_touch_move_to_renderer_(false) {
+ dispatching_touch_ack_(NULL),
+ dispatching_touch_(false),
+ no_touch_to_renderer_(false),
+ renderer_is_consuming_touch_gesture_(false),
+ ack_timeout_enabled_(false) {
DCHECK(client);
}
@@ -107,12 +253,8 @@ void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
if (touch_queue_.empty() && !dispatching_touch_ack_) {
// There is no touch event in the queue. Forward it to the renderer
// immediately.
- touch_queue_.push_back(new CoalescedWebTouchEvent(event));
- if (ShouldForwardToRenderer(event.event))
- client_->SendTouchEventImmediately(event);
- else
- PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- ui::LatencyInfo());
+ touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
+ TryForwardNextEventToRenderer();
return;
}
@@ -123,104 +265,181 @@ void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
if (last_event->CoalesceEventIfPossible(event))
return;
}
- touch_queue_.push_back(new CoalescedWebTouchEvent(event));
+ touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
}
void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
const ui::LatencyInfo& latency_info) {
DCHECK(!dispatching_touch_ack_);
+ dispatching_touch_ = false;
+
+ if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result))
+ return;
+
if (touch_queue_.empty())
return;
- // Update the ACK status for each touch point in the ACKed event.
- const WebKit::WebTouchEvent& event =
- touch_queue_.front()->coalesced_event().event;
- if (event.type == WebKit::WebInputEvent::TouchEnd ||
- event.type == WebKit::WebInputEvent::TouchCancel) {
- // The points have been released. Erase the ACK states.
- for (unsigned i = 0; i < event.touchesLength; ++i) {
- const WebKit::WebTouchPoint& point = event.touches[i];
- if (point.state == WebKit::WebTouchPoint::StateReleased ||
- point.state == WebKit::WebTouchPoint::StateCancelled)
- touch_ack_states_.erase(point.id);
- }
- } else if (event.type == WebKit::WebInputEvent::TouchStart) {
- for (unsigned i = 0; i < event.touchesLength; ++i) {
- const WebKit::WebTouchPoint& point = event.touches[i];
- if (point.state == WebKit::WebTouchPoint::StatePressed)
- touch_ack_states_[point.id] = ack_result;
- }
- }
+ if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
+ renderer_is_consuming_touch_gesture_ = true;
+ const WebTouchEvent& acked_event =
+ touch_queue_.front()->coalesced_event().event;
+ UpdateTouchAckStates(acked_event, ack_result);
PopTouchEventToClient(ack_result, latency_info);
+ TryForwardNextEventToRenderer();
+}
+void TouchEventQueue::TryForwardNextEventToRenderer() {
+ DCHECK(!dispatching_touch_ack_);
// If there are queued touch events, then try to forward them to the renderer
// immediately, or ACK the events back to the client if appropriate.
while (!touch_queue_.empty()) {
const TouchEventWithLatencyInfo& touch =
touch_queue_.front()->coalesced_event();
+ if (IsNewTouchGesture(touch.event))
+ renderer_is_consuming_touch_gesture_ = false;
if (ShouldForwardToRenderer(touch.event)) {
- client_->SendTouchEventImmediately(touch);
+ ForwardToRenderer(touch);
break;
}
- PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- ui::LatencyInfo());
+ PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo());
+ }
+}
+
+void TouchEventQueue::ForwardToRenderer(
+ const TouchEventWithLatencyInfo& touch) {
+ DCHECK(!dispatching_touch_);
+ // A synchronous ack will reset |dispatching_touch_|, in which case
+ // the touch timeout should not be started.
+ base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
+ client_->SendTouchEventImmediately(touch);
+ if (ack_timeout_enabled_ &&
+ dispatching_touch_ &&
+ !renderer_is_consuming_touch_gesture_ &&
+ ShouldTouchTypeTriggerTimeout(touch.event.type)) {
+ DCHECK(timeout_handler_);
+ timeout_handler_->Start(touch);
+ }
+}
+
+void TouchEventQueue::OnGestureScrollEvent(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ blink::WebInputEvent::Type type = gesture_event.event.type;
+ if (type == blink::WebInputEvent::GestureScrollBegin) {
+ // We assume the scroll event are generated synchronously from
+ // dispatching a touch event ack, so that we can fake a cancel
+ // event that has the correct touch ids as the touch event that
+ // is being acked. If not, we don't do the touch-cancel optimization.
+ if (no_touch_to_renderer_ || !dispatching_touch_ack_)
+ return;
+ no_touch_to_renderer_ = true;
+
+ // If we have a timeout event, a cancel has already been dispatched
+ // for the current touch stream.
+ if (HasTimeoutEvent())
+ return;
+
+ // Fake a TouchCancel to cancel the touch points of the touch event
+ // that is currently being acked.
+ // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we
+ // are in the scope of PopTouchEventToClient() and that no touch event
+ // in the queue is waiting for ack from renderer. So we can just insert
+ // the touch cancel at the beginning of the queue.
+ touch_queue_.push_front(new CoalescedWebTouchEvent(
+ ObtainCancelEventForTouchEvent(
+ dispatching_touch_ack_->coalesced_event()), true));
+ } else if (type == blink::WebInputEvent::GestureScrollEnd ||
+ type == blink::WebInputEvent::GestureFlingStart) {
+ no_touch_to_renderer_ = false;
}
}
void TouchEventQueue::FlushQueue() {
DCHECK(!dispatching_touch_ack_);
+ DCHECK(!dispatching_touch_);
while (!touch_queue_.empty())
- PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
- ui::LatencyInfo());
+ PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo());
+}
+
+bool TouchEventQueue::IsPendingAckTouchStart() const {
+ DCHECK(!dispatching_touch_ack_);
+ if (touch_queue_.empty())
+ return false;
+
+ const blink::WebTouchEvent& event =
+ touch_queue_.front()->coalesced_event().event;
+ return (event.type == WebInputEvent::TouchStart);
}
-size_t TouchEventQueue::GetQueueSize() const {
- return touch_queue_.size();
+void TouchEventQueue::SetAckTimeoutEnabled(bool enabled,
+ size_t ack_timeout_delay_ms) {
+ if (!enabled) {
+ // Avoid resetting |timeout_handler_|, as an outstanding timeout may
+ // be active and must be completed for ack handling consistency.
+ ack_timeout_enabled_ = false;
+ return;
+ }
+
+ ack_timeout_enabled_ = true;
+ if (!timeout_handler_)
+ timeout_handler_.reset(new TouchTimeoutHandler(this, ack_timeout_delay_ms));
+}
+
+bool TouchEventQueue::HasTimeoutEvent() const {
+ return timeout_handler_ && timeout_handler_->HasTimeoutEvent();
+}
+
+bool TouchEventQueue::IsTimeoutRunningForTesting() const {
+ return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning();
}
-const TouchEventWithLatencyInfo& TouchEventQueue::GetLatestEvent() const {
+const TouchEventWithLatencyInfo&
+TouchEventQueue::GetLatestEventForTesting() const {
return touch_queue_.back()->coalesced_event();
}
void TouchEventQueue::PopTouchEventToClient(
InputEventAckState ack_result,
const ui::LatencyInfo& renderer_latency_info) {
+ DCHECK(!dispatching_touch_ack_);
if (touch_queue_.empty())
return;
scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front());
touch_queue_.pop_front();
+ if (acked_event->ignore_ack())
+ return;
+
// Note that acking the touch-event may result in multiple gestures being sent
// to the renderer, or touch-events being queued.
- base::AutoReset<bool> dispatching_touch_ack(&dispatching_touch_ack_, true);
+ base::AutoReset<CoalescedWebTouchEvent*>
+ dispatching_touch_ack(&dispatching_touch_ack_, acked_event.get());
- base::TimeTicks now = base::TimeTicks::HighResNow();
- for (WebTouchEventWithLatencyList::const_iterator iter = acked_event->begin(),
+ for (WebTouchEventWithLatencyList::iterator iter = acked_event->begin(),
end = acked_event->end();
iter != end; ++iter) {
- ui::LatencyInfo* latency = const_cast<ui::LatencyInfo*>(&(iter->latency));
- latency->AddNewLatencyFrom(renderer_latency_info);
- latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACKED_COMPONENT, 0, 0, now, 1);
+ iter->latency.AddNewLatencyFrom(renderer_latency_info);
client_->OnTouchEventAck((*iter), ack_result);
}
}
bool TouchEventQueue::ShouldForwardToRenderer(
- const WebKit::WebTouchEvent& event) const {
- // Touch press events should always be forwarded to the renderer.
- if (event.type == WebKit::WebInputEvent::TouchStart)
- return true;
+ const WebTouchEvent& event) const {
+ if (HasTimeoutEvent())
+ return false;
- if (event.type == WebKit::WebInputEvent::TouchMove &&
- no_touch_move_to_renderer_)
+ if (no_touch_to_renderer_ &&
+ event.type != blink::WebInputEvent::TouchCancel)
return false;
+ // Touch press events should always be forwarded to the renderer.
+ if (event.type == WebInputEvent::TouchStart)
+ return true;
+
for (unsigned int i = 0; i < event.touchesLength; ++i) {
- const WebKit::WebTouchPoint& point = event.touches[i];
+ const WebTouchPoint& point = event.touches[i];
// If a point has been stationary, then don't take it into account.
- if (point.state == WebKit::WebTouchPoint::StateStationary)
+ if (point.state == WebTouchPoint::StateStationary)
continue;
if (touch_ack_states_.count(point.id) > 0) {
@@ -237,4 +456,25 @@ bool TouchEventQueue::ShouldForwardToRenderer(
return false;
}
+void TouchEventQueue::UpdateTouchAckStates(const WebTouchEvent& event,
+ InputEventAckState ack_result) {
+ // Update the ACK status for each touch point in the ACKed event.
+ if (event.type == WebInputEvent::TouchEnd ||
+ event.type == WebInputEvent::TouchCancel) {
+ // The points have been released. Erase the ACK states.
+ for (unsigned i = 0; i < event.touchesLength; ++i) {
+ const WebTouchPoint& point = event.touches[i];
+ if (point.state == WebTouchPoint::StateReleased ||
+ point.state == WebTouchPoint::StateCancelled)
+ touch_ack_states_.erase(point.id);
+ }
+ } else if (event.type == WebInputEvent::TouchStart) {
+ for (unsigned i = 0; i < event.touchesLength; ++i) {
+ const WebTouchPoint& point = event.touches[i];
+ if (point.state == WebTouchPoint::StatePressed)
+ touch_ack_states_[point.id] = ack_result;
+ }
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue.h b/chromium/content/browser/renderer_host/input/touch_event_queue.h
index 358fae9c50d..ea7eb71fe5a 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.h
@@ -20,7 +20,7 @@ class CoalescedWebTouchEvent;
// Interface with which TouchEventQueue can forward touch events, and dispatch
// touch event responses.
-class TouchEventQueueClient {
+class CONTENT_EXPORT TouchEventQueueClient {
public:
virtual ~TouchEventQueueClient() {}
@@ -33,12 +33,12 @@ class TouchEventQueueClient {
};
// A queue for throttling and coalescing touch-events.
-class TouchEventQueue {
+class CONTENT_EXPORT TouchEventQueue {
public:
// The |client| must outlive the TouchEventQueue.
explicit TouchEventQueue(TouchEventQueueClient* client);
- virtual ~TouchEventQueue();
+ ~TouchEventQueue();
// Adds an event to the queue. The event may be coalesced with previously
// queued events (e.g. consecutive touch-move events can be coalesced into a
@@ -52,32 +52,60 @@ class TouchEventQueue {
void ProcessTouchAck(InputEventAckState ack_result,
const ui::LatencyInfo& latency_info);
+ // When GestureScrollBegin is received, we send a touch cancel to renderer,
+ // route all the following touch events directly to client, and ignore the
+ // ack for the touch cancel. When Gesture{ScrollEnd,FlingStart} is received,
+ // resume the normal flow of sending touch events to the renderer.
+ void OnGestureScrollEvent(const GestureEventWithLatencyInfo& gesture_event);
+
// Empties the queue of touch events. This may result in any number of gesture
// events being sent to the renderer.
void FlushQueue();
- // Returns whether the event-queue is empty.
+ // Returns whether the currently pending touch event (waiting ACK) is for
+ // a touch start event.
+ bool IsPendingAckTouchStart() const;
+
+ // Sets whether a delayed touch ack will cancel and flush the current
+ // touch sequence.
+ void SetAckTimeoutEnabled(bool enabled, size_t ack_timeout_delay_ms);
+
bool empty() const WARN_UNUSED_RESULT {
return touch_queue_.empty();
}
- void set_no_touch_move_to_renderer(bool value) {
- no_touch_move_to_renderer_ = value;
+ size_t size() const {
+ return touch_queue_.size();
+ }
+
+ bool ack_timeout_enabled() const {
+ return ack_timeout_enabled_;
}
private:
- friend class MockRenderWidgetHost;
- friend class ImmediateInputRouterTest;
+ class TouchTimeoutHandler;
+ friend class TouchTimeoutHandler;
+ friend class TouchEventQueueTest;
- CONTENT_EXPORT size_t GetQueueSize() const;
- CONTENT_EXPORT const TouchEventWithLatencyInfo& GetLatestEvent() const;
+ bool HasTimeoutEvent() const;
+ bool IsTimeoutRunningForTesting() const;
+ const TouchEventWithLatencyInfo& GetLatestEventForTesting() const;
+
+ // Walks the queue, checking each event for |ShouldForwardToRenderer()|.
+ // If true, forwards the touch event and stops processing further events.
+ // If false, acks the event with |INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS|.
+ void TryForwardNextEventToRenderer();
// Pops the touch-event from the top of the queue and sends it to the
// TouchEventQueueClient. This reduces the size of the queue by one.
void PopTouchEventToClient(InputEventAckState ack_result,
const ui::LatencyInfo& renderer_latency_info);
- bool ShouldForwardToRenderer(const WebKit::WebTouchEvent& event) const;
+ bool ShouldForwardToRenderer(const blink::WebTouchEvent& event) const;
+ void ForwardToRenderer(const TouchEventWithLatencyInfo& event);
+ void UpdateTouchAckStates(const blink::WebTouchEvent& event,
+ InputEventAckState ack_result);
+
// Handles touch event forwarding and ack'ed event dispatch.
TouchEventQueueClient* client_;
@@ -90,12 +118,24 @@ class TouchEventQueue {
TouchPointAckStates touch_ack_states_;
// Used to defer touch forwarding when ack dispatch triggers |QueueEvent()|.
- bool dispatching_touch_ack_;
+ // If not NULL, |dispatching_touch_ack_| is the touch event of which the ack
+ // is being dispatched.
+ CoalescedWebTouchEvent* dispatching_touch_ack_;
+
+ // Used to prevent touch timeout scheduling if we receive a synchronous
+ // ack after forwarding a touch event to the client.
+ bool dispatching_touch_;
+
+ // Don't send touch events to the renderer while scrolling.
+ bool no_touch_to_renderer_;
+
+ // Whether an event in the current (multi)touch sequence was consumed by the
+ // renderer. The touch timeout will never be activated when this is true.
+ bool renderer_is_consuming_touch_gesture_;
- // Don't send touch move events to renderer. This is enabled when the page
- // is scrolling. This behaviour is currently enabled only on aura behind a
- // flag.
- bool no_touch_move_to_renderer_;
+ // Optional handler for timed-out touch event acks, disabled by default.
+ bool ack_timeout_enabled_;
+ scoped_ptr<TouchTimeoutHandler> timeout_handler_;
DISALLOW_COPY_AND_ASSIGN(TouchEventQueue);
};
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc
new file mode 100644
index 00000000000..875b798546c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc
@@ -0,0 +1,1148 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "content/browser/renderer_host/input/timeout_monitor.h"
+#include "content/browser/renderer_host/input/touch_event_queue.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+
+namespace content {
+namespace {
+const size_t kDefaultTouchTimeoutDelayMs = 10;
+}
+
+class TouchEventQueueTest : public testing::Test,
+ public TouchEventQueueClient {
+ public:
+ TouchEventQueueTest()
+ : sent_event_count_(0),
+ acked_event_count_(0),
+ last_acked_event_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
+
+ virtual ~TouchEventQueueTest() {}
+
+ // testing::Test
+ virtual void SetUp() OVERRIDE {
+ queue_.reset(new TouchEventQueue(this));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ queue_.reset();
+ }
+
+ // TouchEventQueueClient
+ virtual void SendTouchEventImmediately(
+ const TouchEventWithLatencyInfo& event) OVERRIDE {
+ ++sent_event_count_;
+ last_sent_event_ = event.event;
+ if (sync_ack_result_)
+ SendTouchEventACK(*sync_ack_result_.Pass());
+ }
+
+ virtual void OnTouchEventAck(
+ const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) OVERRIDE {
+ ++acked_event_count_;
+ last_acked_event_ = event.event;
+ last_acked_event_state_ = ack_result;
+ if (followup_touch_event_) {
+ scoped_ptr<WebTouchEvent> followup_touch_event =
+ followup_touch_event_.Pass();
+ SendTouchEvent(*followup_touch_event);
+ }
+ if (followup_gesture_event_) {
+ scoped_ptr<WebGestureEvent> followup_gesture_event =
+ followup_gesture_event_.Pass();
+ queue_->OnGestureScrollEvent(
+ GestureEventWithLatencyInfo(*followup_gesture_event,
+ ui::LatencyInfo()));
+ }
+ }
+
+ protected:
+
+ void SetUpForTimeoutTesting(size_t timeout_delay_ms) {
+ queue_->SetAckTimeoutEnabled(true, timeout_delay_ms);
+ }
+
+ void SendTouchEvent(const WebTouchEvent& event) {
+ queue_->QueueEvent(TouchEventWithLatencyInfo(event, ui::LatencyInfo()));
+ }
+
+ void SendGestureEvent(WebInputEvent::Type type) {
+ WebGestureEvent event;
+ event.type = type;
+ queue_->OnGestureScrollEvent(
+ GestureEventWithLatencyInfo(event, ui::LatencyInfo()));
+ }
+
+ void SendTouchEventACK(InputEventAckState ack_result) {
+ queue_->ProcessTouchAck(ack_result, ui::LatencyInfo());
+ }
+
+ void SetFollowupEvent(const WebTouchEvent& event) {
+ followup_touch_event_.reset(new WebTouchEvent(event));
+ }
+
+ void SetFollowupEvent(const WebGestureEvent& event) {
+ followup_gesture_event_.reset(new WebGestureEvent(event));
+ }
+
+ void SetSyncAckResult(InputEventAckState sync_ack_result) {
+ sync_ack_result_.reset(new InputEventAckState(sync_ack_result));
+ }
+
+ void PressTouchPoint(int x, int y) {
+ touch_event_.PressPoint(x, y);
+ SendTouchEvent();
+ }
+
+ void MoveTouchPoint(int index, int x, int y) {
+ touch_event_.MovePoint(index, x, y);
+ SendTouchEvent();
+ }
+
+ void MoveTouchPoints(int index0, int x0, int y0, int index1, int x1, int y1) {
+ touch_event_.MovePoint(index0, x0, y0);
+ touch_event_.MovePoint(index1, x1, y1);
+ SendTouchEvent();
+ }
+
+ void ReleaseTouchPoint(int index) {
+ touch_event_.ReleasePoint(index);
+ SendTouchEvent();
+ }
+
+ void CancelTouchPoint(int index) {
+ touch_event_.CancelPoint(index);
+ SendTouchEvent();
+ }
+
+ size_t GetAndResetAckedEventCount() {
+ size_t count = acked_event_count_;
+ acked_event_count_ = 0;
+ return count;
+ }
+
+ size_t GetAndResetSentEventCount() {
+ size_t count = sent_event_count_;
+ sent_event_count_ = 0;
+ return count;
+ }
+
+ bool IsPendingAckTouchStart() const {
+ return queue_->IsPendingAckTouchStart();
+ }
+
+ void Flush() {
+ queue_->FlushQueue();
+ }
+
+ void SetEnableTouchForwarding(bool enabled) {
+ queue_->no_touch_to_renderer_ = !enabled;
+ }
+
+ bool WillForwardTouchEvents() {
+ return !queue_->no_touch_to_renderer_ && !queue_->HasTimeoutEvent();
+ }
+
+ bool IsTimeoutRunning() {
+ return queue_->IsTimeoutRunningForTesting();
+ }
+
+ size_t queued_event_count() const {
+ return queue_->size();
+ }
+
+ const WebTouchEvent& latest_event() const {
+ return queue_->GetLatestEventForTesting().event;
+ }
+
+ const WebTouchEvent& acked_event() const {
+ return last_acked_event_;
+ }
+
+ const WebTouchEvent& sent_event() const {
+ return last_sent_event_;
+ }
+
+ InputEventAckState acked_event_state() const {
+ return last_acked_event_state_;
+ }
+
+ void set_no_touch_to_renderer(bool no_touch) {
+ queue_->no_touch_to_renderer_ = no_touch;
+ }
+
+ bool no_touch_to_renderer() const {
+ return queue_->no_touch_to_renderer_;
+ }
+
+ private:
+ void SendTouchEvent() {
+ SendTouchEvent(touch_event_);
+ touch_event_.ResetPoints();
+ }
+
+ scoped_ptr<TouchEventQueue> queue_;
+ size_t sent_event_count_;
+ size_t acked_event_count_;
+ WebTouchEvent last_sent_event_;
+ WebTouchEvent last_acked_event_;
+ InputEventAckState last_acked_event_state_;
+ SyntheticWebTouchEvent touch_event_;
+ scoped_ptr<WebTouchEvent> followup_touch_event_;
+ scoped_ptr<WebGestureEvent> followup_gesture_event_;
+ scoped_ptr<InputEventAckState> sync_ack_result_;
+ base::MessageLoopForUI message_loop_;
+};
+
+
+// Tests that touch-events are queued properly.
+TEST_F(TouchEventQueueTest, Basic) {
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // The second touch should not be sent since one is already in queue.
+ MoveTouchPoint(0, 5, 5);
+ EXPECT_EQ(2U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+
+ // Receive an ACK for the first touch-event.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type);
+
+ // Receive an ACK for the second touch-event.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(WebInputEvent::TouchMove, acked_event().type);
+}
+
+// Tests that the touch-queue is emptied if a page stops listening for touch
+// events.
+TEST_F(TouchEventQueueTest, Flush) {
+ Flush();
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+
+ // Send a touch-press event.
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ ReleaseTouchPoint(0);
+
+ // Events will be queued until the first sent event is ack'ed.
+ for (int i = 5; i < 15; ++i) {
+ PressTouchPoint(1, 1);
+ MoveTouchPoint(0, i, i);
+ ReleaseTouchPoint(0);
+ }
+ EXPECT_EQ(32U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+
+ // Receive an ACK for the first touch-event. One of the queued touch-event
+ // should be forwarded.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(31U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type);
+
+ // Flush the queue. The touch-event queue should now be emptied, but none of
+ // the queued touch-events should be sent to the renderer.
+ Flush();
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(31U, GetAndResetAckedEventCount());
+}
+
+// Tests that touch-events are coalesced properly in the queue.
+TEST_F(TouchEventQueueTest, Coalesce) {
+ // Send a touch-press event.
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Send a few touch-move events, followed by a touch-release event. All the
+ // touch-move events should be coalesced into a single event.
+ for (int i = 5; i < 15; ++i)
+ MoveTouchPoint(0, i, i);
+
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ ReleaseTouchPoint(0);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(3U, queued_event_count());
+
+ // ACK the press. Coalesced touch-move events should be sent.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(2U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type);
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, acked_event_state());
+
+ // ACK the moves.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(10U, GetAndResetAckedEventCount());
+ EXPECT_EQ(WebInputEvent::TouchMove, acked_event().type);
+
+ // ACK the release.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(WebInputEvent::TouchEnd, acked_event().type);
+}
+
+// Tests that an event that has already been sent but hasn't been ack'ed yet
+// doesn't get coalesced with newer events.
+TEST_F(TouchEventQueueTest, SentTouchEventDoesNotCoalesce) {
+ // Send a touch-press event.
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Send a few touch-move events, followed by a touch-release event. All the
+ // touch-move events should be coalesced into a single event.
+ for (int i = 5; i < 15; ++i)
+ MoveTouchPoint(0, i, i);
+
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(2U, queued_event_count());
+
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+
+ // The coalesced touch-move event has been sent to the renderer. Any new
+ // touch-move event should not be coalesced with the sent event.
+ MoveTouchPoint(0, 5, 5);
+ EXPECT_EQ(2U, queued_event_count());
+
+ MoveTouchPoint(0, 7, 7);
+ EXPECT_EQ(2U, queued_event_count());
+}
+
+// Tests that coalescing works correctly for multi-touch events.
+TEST_F(TouchEventQueueTest, MultiTouch) {
+ // Press the first finger.
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Move the finger.
+ MoveTouchPoint(0, 5, 5);
+ EXPECT_EQ(2U, queued_event_count());
+
+ // Now press a second finger.
+ PressTouchPoint(2, 2);
+ EXPECT_EQ(3U, queued_event_count());
+
+ // Move both fingers.
+ MoveTouchPoints(0, 10, 10, 1, 20, 20);
+ MoveTouchPoint(1, 20, 20);
+ EXPECT_EQ(4U, queued_event_count());
+
+ // Move only one finger now.
+ MoveTouchPoint(0, 15, 15);
+ EXPECT_EQ(4U, queued_event_count());
+
+ // Move the other finger.
+ MoveTouchPoint(1, 25, 25);
+ EXPECT_EQ(4U, queued_event_count());
+
+ // Make sure both fingers are marked as having been moved in the coalesced
+ // event.
+ const WebTouchEvent& event = latest_event();
+ EXPECT_EQ(WebTouchPoint::StateMoved, event.touches[0].state);
+ EXPECT_EQ(WebTouchPoint::StateMoved, event.touches[1].state);
+}
+
+// Tests that if a touch-event queue is destroyed in response to a touch-event
+// in the renderer, then there is no crash when the ACK for that touch-event
+// comes back.
+TEST_F(TouchEventQueueTest, AckAfterQueueFlushed) {
+ // Send some touch-events to the renderer.
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+
+ MoveTouchPoint(0, 10, 10);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(2U, queued_event_count());
+
+ // Receive an ACK for the press. This should cause the queued touch-move to
+ // be sent to the renderer.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+
+ Flush();
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+
+ // Now receive an ACK for the move.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+}
+
+// Tests that touch-move events are not sent to the renderer if the preceding
+// touch-press event did not have a consumer (and consequently, did not hit the
+// main thread in the renderer). Also tests that all queued/coalesced touch
+// events are flushed immediately when the ACK for the touch-press comes back
+// with NO_CONSUMER status.
+TEST_F(TouchEventQueueTest, NoConsumer) {
+ // The first touch-press should reach the renderer.
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // The second touch should not be sent since one is already in queue.
+ MoveTouchPoint(0, 5, 5);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(2U, queued_event_count());
+
+ // Receive an ACK for the first touch-event. This should release the queued
+ // touch-event, but it should not be sent to the renderer.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(WebInputEvent::TouchMove, acked_event().type);
+ EXPECT_EQ(2U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+
+ // Send a release event. This should not reach the renderer.
+ ReleaseTouchPoint(0);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(WebInputEvent::TouchEnd, acked_event().type);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Send a press-event, followed by move and release events, and another press
+ // event, before the ACK for the first press event comes back. All of the
+ // events should be queued first. After the NO_CONSUMER ack for the first
+ // touch-press, all events upto the second touch-press should be flushed.
+ PressTouchPoint(10, 10);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ MoveTouchPoint(0, 5, 5);
+ MoveTouchPoint(0, 6, 5);
+ ReleaseTouchPoint(0);
+
+ PressTouchPoint(6, 5);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ // The queue should hold the first sent touch-press event, the coalesced
+ // touch-move event, the touch-end event and the second touch-press event.
+ EXPECT_EQ(4U, queued_event_count());
+
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(WebInputEvent::TouchEnd, acked_event().type);
+ EXPECT_EQ(4U, GetAndResetAckedEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+
+ // ACK the second press event as NO_CONSUMER too.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+
+ // Send a second press event. Even though the first touch had NO_CONSUMER,
+ // this press event should reach the renderer.
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+}
+
+TEST_F(TouchEventQueueTest, ConsumerIgnoreMultiFinger) {
+ // Press two touch points and move them around a bit. The renderer consumes
+ // the events for the first touch point, but returns NO_CONSUMER_EXISTS for
+ // the second touch point.
+
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ MoveTouchPoint(0, 5, 5);
+
+ PressTouchPoint(10, 10);
+
+ MoveTouchPoint(0, 2, 2);
+
+ MoveTouchPoint(1, 4, 10);
+
+ MoveTouchPoints(0, 10, 10, 1, 20, 20);
+
+ // Since the first touch-press is still pending ACK, no other event should
+ // have been sent to the renderer.
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ // The queue includes the two presses, the first touch-move of the first
+ // point, and a coalesced touch-move of both points.
+ EXPECT_EQ(4U, queued_event_count());
+
+ // ACK the first press as CONSUMED. This should cause the first touch-move of
+ // the first touch-point to be dispatched.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(3U, queued_event_count());
+
+ // ACK the first move as CONSUMED.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(2U, queued_event_count());
+
+ // ACK the second press as NO_CONSUMER_EXISTS. This will dequeue the coalesced
+ // touch-move event (which contains both touch points). Although the second
+ // touch-point does not need to be sent to the renderer, the first touch-point
+ // did move, and so the coalesced touch-event will be sent to the renderer.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+
+ // ACK the coalesced move as NOT_CONSUMED.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+
+ // Move just the second touch point. Because the first touch point did not
+ // move, this event should not reach the renderer.
+ MoveTouchPoint(1, 30, 30);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+
+ // Move just the first touch point. This should reach the renderer.
+ MoveTouchPoint(0, 10, 10);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+
+ // Move both fingers. This event should reach the renderer (after the ACK of
+ // the previous move event is received), because the first touch point did
+ // move.
+ MoveTouchPoints(0, 15, 15, 1, 25, 25);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+
+ // Release the first finger. Then move the second finger around some, then
+ // press another finger. Once the release event is ACKed, the move events of
+ // the second finger should be immediately released to the view, and the
+ // touch-press event should be dispatched to the renderer.
+ ReleaseTouchPoint(0);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+
+ MoveTouchPoint(1, 40, 40);
+
+ MoveTouchPoint(1, 50, 50);
+
+ PressTouchPoint(1, 1);
+
+ MoveTouchPoint(1, 30, 30);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(4U, queued_event_count());
+
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(2U, queued_event_count());
+ EXPECT_EQ(WebInputEvent::TouchMove, acked_event().type);
+
+ // ACK the press with NO_CONSUMED_EXISTS. This should release the queued
+ // touch-move events to the view.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(WebInputEvent::TouchMove, acked_event().type);
+
+ ReleaseTouchPoint(2);
+ ReleaseTouchPoint(1);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+}
+
+// Tests that touch-event's enqueued via a touch ack are properly handled.
+TEST_F(TouchEventQueueTest, AckWithFollowupEvents) {
+ // Queue a touch down.
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+
+ // Create a touch event that will be queued synchronously by a touch ack.
+ // Note, this will be triggered by all subsequent touch acks.
+ WebTouchEvent followup_event;
+ followup_event.type = WebInputEvent::TouchStart;
+ followup_event.touchesLength = 1;
+ followup_event.touches[0].id = 1;
+ followup_event.touches[0].state = WebTouchPoint::StatePressed;
+ SetFollowupEvent(followup_event);
+
+ // Receive an ACK for the press. This should cause the followup touch-move to
+ // be sent to the renderer.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, acked_event_state());
+ EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type);
+
+ // Queue another event.
+ MoveTouchPoint(0, 2, 2);
+ EXPECT_EQ(2U, queued_event_count());
+
+ // Receive an ACK for the touch-move followup event. This should cause the
+ // subsequent touch move event be sent to the renderer.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+}
+
+// Tests that touch-events can be synchronously ack'ed.
+TEST_F(TouchEventQueueTest, SynchronousAcks) {
+ // TouchStart
+ SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED);
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // TouchMove
+ SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED);
+ MoveTouchPoint(0, 2, 2);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // TouchEnd
+ SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED);
+ ReleaseTouchPoint(0);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // TouchCancel (first inserting a TouchStart so the TouchCancel will be sent)
+ PressTouchPoint(1, 1);
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED);
+ CancelTouchPoint(0);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+}
+
+// Tests that followup events triggered by an immediate ack from
+// TouchEventQueue::QueueEvent() are properly handled.
+TEST_F(TouchEventQueueTest, ImmediateAckWithFollowupEvents) {
+ // Create a touch event that will be queued synchronously by a touch ack.
+ WebTouchEvent followup_event;
+ followup_event.type = WebInputEvent::TouchStart;
+ followup_event.touchesLength = 1;
+ followup_event.touches[0].id = 1;
+ followup_event.touches[0].state = WebTouchPoint::StatePressed;
+ SetFollowupEvent(followup_event);
+
+ // Now, enqueue a stationary touch that will not be forwarded. This should be
+ // immediately ack'ed with "NO_CONSUMER_EXISTS". The followup event should
+ // then be enqueued and immediately sent to the renderer.
+ WebTouchEvent stationary_event;
+ stationary_event.touchesLength = 1;
+ stationary_event.type = WebInputEvent::TouchMove;
+ stationary_event.touches[0].id = 1;
+ stationary_event.touches[0].state = WebTouchPoint::StateStationary;
+ SendTouchEvent(stationary_event);
+
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, acked_event_state());
+ EXPECT_EQ(WebInputEvent::TouchMove, acked_event().type);
+}
+
+// Tests basic TouchEvent forwarding suppression.
+TEST_F(TouchEventQueueTest, NoTouchBasic) {
+ // Disable TouchEvent forwarding.
+ SetEnableTouchForwarding(false);
+ MoveTouchPoint(0, 30, 5);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // TouchMove should not be sent to renderer.
+ MoveTouchPoint(0, 65, 10);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // TouchEnd should not be sent to renderer.
+ ReleaseTouchPoint(0);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // TouchStart should not be sent to renderer.
+ PressTouchPoint(5, 5);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Enable TouchEvent forwarding.
+ SetEnableTouchForwarding(true);
+
+ PressTouchPoint(80, 10);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ MoveTouchPoint(0, 80, 20);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ ReleaseTouchPoint(0);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+}
+
+// Tests that no TouchEvents are sent to renderer during scrolling.
+TEST_F(TouchEventQueueTest, NoTouchOnScroll) {
+ // Queue a TouchStart.
+ PressTouchPoint(0, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ MoveTouchPoint(0, 20, 5);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Queue another TouchStart.
+ PressTouchPoint(20, 20);
+ EXPECT_EQ(2U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(WebInputEvent::TouchStart, latest_event().type);
+
+ // GestureScrollBegin inserts a synthetic TouchCancel before the TouchStart.
+ WebGestureEvent followup_scroll;
+ followup_scroll.type = WebInputEvent::GestureScrollBegin;
+ SetFollowupEvent(followup_scroll);
+ ASSERT_TRUE(WillForwardTouchEvents());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_FALSE(WillForwardTouchEvents());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(2U, queued_event_count());
+ EXPECT_EQ(WebInputEvent::TouchCancel, sent_event().type);
+ EXPECT_EQ(WebInputEvent::TouchStart, latest_event().type);
+
+ // Acking the TouchCancel will result in dispatch of the next TouchStart.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ // The synthetic TouchCancel should not reach client, only the TouchStart.
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type);
+
+ // TouchMove should not be sent to the renderer.
+ MoveTouchPoint(0, 30, 5);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, acked_event_state());
+
+ // GestureScrollUpdates should not change affect touch forwarding.
+ SendGestureEvent(WebInputEvent::GestureScrollUpdate);
+ EXPECT_FALSE(WillForwardTouchEvents());
+
+ // TouchEnd should not be sent to the renderer.
+ ReleaseTouchPoint(0);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, acked_event_state());
+
+ // GestureScrollEnd will resume the sending of TouchEvents to renderer.
+ SendGestureEvent(blink::WebInputEvent::GestureScrollEnd);
+ EXPECT_TRUE(WillForwardTouchEvents());
+
+ // Now TouchEvents should be forwarded normally.
+ PressTouchPoint(80, 10);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ MoveTouchPoint(0, 80, 20);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ ReleaseTouchPoint(0);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+}
+
+// Tests that IsTouchStartPendingAck works correctly.
+TEST_F(TouchEventQueueTest, PendingStart) {
+
+ EXPECT_FALSE(IsPendingAckTouchStart());
+
+ // Send the touchstart for one point (#1).
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_TRUE(IsPendingAckTouchStart());
+
+ // Send a touchmove for that point (#2).
+ MoveTouchPoint(0, 5, 5);
+ EXPECT_EQ(2U, queued_event_count());
+ EXPECT_TRUE(IsPendingAckTouchStart());
+
+ // Ack the touchstart (#1).
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_FALSE(IsPendingAckTouchStart());
+
+ // Send a touchstart for another point (#3).
+ PressTouchPoint(10, 10);
+ EXPECT_EQ(2U, queued_event_count());
+ EXPECT_FALSE(IsPendingAckTouchStart());
+
+ // Ack the touchmove (#2).
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_TRUE(IsPendingAckTouchStart());
+
+ // Send a touchstart for a third point (#4).
+ PressTouchPoint(15, 15);
+ EXPECT_EQ(2U, queued_event_count());
+ EXPECT_TRUE(IsPendingAckTouchStart());
+
+ // Ack the touchstart for the second point (#3).
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_TRUE(IsPendingAckTouchStart());
+
+ // Ack the touchstart for the third point (#4).
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_FALSE(IsPendingAckTouchStart());
+}
+
+// Tests that the touch timeout is started when sending certain touch types.
+TEST_F(TouchEventQueueTest, TouchTimeoutTypes) {
+ SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
+
+ // Sending a TouchStart will start the timeout.
+ PressTouchPoint(0, 1);
+ EXPECT_TRUE(IsTimeoutRunning());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_FALSE(IsTimeoutRunning());
+
+ // A TouchMove should start the timeout.
+ MoveTouchPoint(0, 5, 5);
+ EXPECT_TRUE(IsTimeoutRunning());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_FALSE(IsTimeoutRunning());
+
+ // A TouchEnd should not start the timeout.
+ ReleaseTouchPoint(0);
+ EXPECT_FALSE(IsTimeoutRunning());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_FALSE(IsTimeoutRunning());
+
+ // A TouchCancel should not start the timeout.
+ PressTouchPoint(0, 1);
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ ASSERT_FALSE(IsTimeoutRunning());
+ CancelTouchPoint(0);
+ EXPECT_FALSE(IsTimeoutRunning());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_FALSE(IsTimeoutRunning());
+}
+
+// Tests that a delayed TouchEvent ack will trigger a TouchCancel timeout,
+// disabling touch forwarding until the next TouchStart is received after
+// the timeout events are ack'ed.
+TEST_F(TouchEventQueueTest, TouchTimeoutBasic) {
+ SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
+
+ // Queue a TouchStart.
+ GetAndResetSentEventCount();
+ GetAndResetAckedEventCount();
+ PressTouchPoint(0, 1);
+ ASSERT_EQ(1U, GetAndResetSentEventCount());
+ ASSERT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_TRUE(IsTimeoutRunning());
+ EXPECT_TRUE(WillForwardTouchEvents());
+
+ // Delay the ack.
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::MessageLoop::QuitClosure(),
+ base::TimeDelta::FromMilliseconds(kDefaultTouchTimeoutDelayMs * 2));
+ base::MessageLoop::current()->Run();
+
+ // The timeout should have fired, synthetically ack'ing the timed-out event.
+ // TouchEvent forwarding is disabled until the ack is received for the
+ // timed-out event and the future cancel event.
+ EXPECT_FALSE(IsTimeoutRunning());
+ EXPECT_FALSE(WillForwardTouchEvents());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Ack'ing the original event should trigger a cancel event.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_FALSE(IsTimeoutRunning());
+ EXPECT_FALSE(WillForwardTouchEvents());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Touch events should not be forwarded until we receive the cancel acks.
+ PressTouchPoint(0, 1);
+ ASSERT_EQ(0U, GetAndResetSentEventCount());
+ ASSERT_EQ(1U, GetAndResetAckedEventCount());
+
+ // The synthetic TouchCancel ack should not reach the client, but should
+ // resume touch forwarding.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_TRUE(WillForwardTouchEvents());
+
+ // Subsequent events should be handled normally.
+ PressTouchPoint(0, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+}
+
+// Tests that the timeout is never started if the renderer consumes
+// a TouchEvent from the current touch sequence.
+TEST_F(TouchEventQueueTest, NoTouchTimeoutIfRendererIsConsumingGesture) {
+ SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
+
+ // Queue a TouchStart.
+ PressTouchPoint(0, 1);
+ ASSERT_TRUE(IsTimeoutRunning());
+
+ // Mark the event as consumed. This should prevent the timeout from
+ // being activated on subsequent TouchEvents in this gesture.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_FALSE(IsTimeoutRunning());
+
+ // A TouchMove should not start the timeout.
+ MoveTouchPoint(0, 5, 5);
+ EXPECT_FALSE(IsTimeoutRunning());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // A secondary TouchStart should not start the timeout.
+ PressTouchPoint(1, 0);
+ EXPECT_FALSE(IsTimeoutRunning());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // A TouchEnd should not start the timeout.
+ ReleaseTouchPoint(1);
+ EXPECT_FALSE(IsTimeoutRunning());
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // A TouchCancel should not start the timeout.
+ CancelTouchPoint(0);
+ EXPECT_FALSE(IsTimeoutRunning());
+}
+
+// Tests that the timeout is never started if the ack is synchronous.
+TEST_F(TouchEventQueueTest, NoTouchTimeoutIfAckIsSynchronous) {
+ SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
+
+ // Queue a TouchStart.
+ SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED);
+ ASSERT_FALSE(IsTimeoutRunning());
+ PressTouchPoint(0, 1);
+ EXPECT_FALSE(IsTimeoutRunning());
+}
+
+// Tests that a TouchCancel timeout plays nice when the timed out touch stream
+// turns into a scroll gesture sequence.
+TEST_F(TouchEventQueueTest, TouchTimeoutWithFollowupGesture) {
+ SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
+
+ // Queue a TouchStart.
+ PressTouchPoint(0, 1);
+ EXPECT_TRUE(IsTimeoutRunning());
+ EXPECT_TRUE(WillForwardTouchEvents());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // The cancelled sequence may turn into a scroll gesture.
+ WebGestureEvent followup_scroll;
+ followup_scroll.type = WebInputEvent::GestureScrollBegin;
+ SetFollowupEvent(followup_scroll);
+
+ // Delay the ack.
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::MessageLoop::QuitClosure(),
+ base::TimeDelta::FromMilliseconds(kDefaultTouchTimeoutDelayMs * 2));
+ base::MessageLoop::current()->Run();
+
+ // The timeout should have fired, disabling touch forwarding until both acks
+ // are received, acking the timed out event.
+ EXPECT_FALSE(IsTimeoutRunning());
+ EXPECT_FALSE(WillForwardTouchEvents());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Ack the original event, triggering a TouchCancel.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_FALSE(IsTimeoutRunning());
+ EXPECT_FALSE(WillForwardTouchEvents());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+
+ // Ack the cancel event. Normally, this would resume touch forwarding,
+ // but we're still within a scroll gesture so it remains disabled.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_FALSE(IsTimeoutRunning());
+ EXPECT_FALSE(WillForwardTouchEvents());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+
+ // Try to forward a touch event.
+ GetAndResetSentEventCount();
+ GetAndResetAckedEventCount();
+ PressTouchPoint(0, 1);
+ EXPECT_FALSE(IsTimeoutRunning());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Now end the scroll sequence, resuming touch handling.
+ SendGestureEvent(blink::WebInputEvent::GestureScrollEnd);
+ EXPECT_TRUE(WillForwardTouchEvents());
+ PressTouchPoint(0, 1);
+ EXPECT_TRUE(IsTimeoutRunning());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+}
+
+// Tests that a TouchCancel timeout plays nice when the timed out touch stream
+// turns into a scroll gesture sequence, but the original event acks are
+// significantly delayed.
+TEST_F(TouchEventQueueTest, TouchTimeoutWithFollowupGestureAndDelayedAck) {
+ SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
+
+ // Queue a TouchStart.
+ PressTouchPoint(0, 1);
+ EXPECT_TRUE(IsTimeoutRunning());
+ EXPECT_TRUE(WillForwardTouchEvents());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // The cancelled sequence may turn into a scroll gesture.
+ WebGestureEvent followup_scroll;
+ followup_scroll.type = WebInputEvent::GestureScrollBegin;
+ SetFollowupEvent(followup_scroll);
+
+ // Delay the ack.
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::MessageLoop::QuitClosure(),
+ base::TimeDelta::FromMilliseconds(kDefaultTouchTimeoutDelayMs * 2));
+ base::MessageLoop::current()->Run();
+
+ // The timeout should have fired, disabling touch forwarding until both acks
+ // are received and acking the timed out event.
+ EXPECT_FALSE(IsTimeoutRunning());
+ EXPECT_FALSE(WillForwardTouchEvents());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Try to forward a touch event.
+ GetAndResetSentEventCount();
+ GetAndResetAckedEventCount();
+ PressTouchPoint(0, 1);
+ EXPECT_FALSE(IsTimeoutRunning());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Now end the scroll sequence. Events will not be forwarded until the two
+ // outstanding touch acks are received.
+ SendGestureEvent(blink::WebInputEvent::GestureScrollEnd);
+ PressTouchPoint(0, 1);
+ EXPECT_FALSE(IsTimeoutRunning());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Ack the original event, triggering a cancel.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+
+ // Ack the cancel event, resuming touch forwarding.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+
+ PressTouchPoint(0, 1);
+ EXPECT_TRUE(IsTimeoutRunning());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+}
+
+// Tests that a delayed TouchEvent ack will not trigger a TouchCancel timeout if
+// the timed-out event had no consumer.
+TEST_F(TouchEventQueueTest, NoCancelOnTouchTimeoutWithoutConsumer) {
+ SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs);
+
+ // Queue a TouchStart.
+ PressTouchPoint(0, 1);
+ ASSERT_EQ(1U, GetAndResetSentEventCount());
+ ASSERT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_TRUE(IsTimeoutRunning());
+ EXPECT_TRUE(WillForwardTouchEvents());
+
+ // Delay the ack.
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::MessageLoop::QuitClosure(),
+ base::TimeDelta::FromMilliseconds(kDefaultTouchTimeoutDelayMs * 2));
+ base::MessageLoop::current()->Run();
+
+ // The timeout should have fired, synthetically ack'ing the timed out event.
+ // TouchEvent forwarding is disabled until the original ack is received.
+ EXPECT_FALSE(IsTimeoutRunning());
+ EXPECT_FALSE(WillForwardTouchEvents());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Touch events should not be forwarded until we receive the original ack.
+ PressTouchPoint(0, 1);
+ ASSERT_EQ(0U, GetAndResetSentEventCount());
+ ASSERT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Ack'ing the original event should not trigger a cancel event, as the
+ // TouchStart had no consumer. However, it should re-enable touch forwarding.
+ SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ EXPECT_FALSE(IsTimeoutRunning());
+ EXPECT_TRUE(WillForwardTouchEvents());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+
+ // Subsequent events should be handled normally.
+ PressTouchPoint(0, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+}
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
new file mode 100644
index 00000000000..859e1a4af45
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
@@ -0,0 +1,307 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/auto_reset.h"
+#include "base/command_line.h"
+#include "base/run_loop.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/common/input_messages.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/common/content_switches.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/event_switches.h"
+#include "ui/events/latency_info.h"
+
+using blink::WebInputEvent;
+
+namespace {
+
+void GiveItSomeTime() {
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ run_loop.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(10));
+ run_loop.Run();
+}
+
+const char kTouchEventDataURL[] =
+ "data:text/html;charset=utf-8,"
+ "<body onload='setup();'>"
+ "<div id='first'></div><div id='second'></div><div id='third'></div>"
+ "<style>"
+ " #first {"
+ " position: absolute;"
+ " width: 100px;"
+ " height: 100px;"
+ " top: 0px;"
+ " left: 0px;"
+ " background-color: green;"
+ " -webkit-transform: translate3d(0, 0, 0);"
+ " }"
+ " #second {"
+ " position: absolute;"
+ " width: 100px;"
+ " height: 100px;"
+ " top: 0px;"
+ " left: 110px;"
+ " background-color: blue;"
+ " -webkit-transform: translate3d(0, 0, 0);"
+ " }"
+ " #third {"
+ " position: absolute;"
+ " width: 100px;"
+ " height: 100px;"
+ " top: 110px;"
+ " left: 0px;"
+ " background-color: yellow;"
+ " -webkit-transform: translate3d(0, 0, 0);"
+ " }"
+ "</style>"
+ "<script>"
+ " function setup() {"
+ " second.ontouchstart = function() {};"
+ " third.ontouchstart = function(e) {"
+ " e.preventDefault();"
+ " };"
+ " }"
+ "</script>";
+
+} // namespace
+
+namespace content {
+
+class InputEventMessageFilter : public BrowserMessageFilter {
+ public:
+ InputEventMessageFilter()
+ : type_(WebInputEvent::Undefined),
+ state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
+
+ void WaitForAck(WebInputEvent::Type type) {
+ base::RunLoop run_loop;
+ base::AutoReset<base::Closure> reset_quit(&quit_, run_loop.QuitClosure());
+ base::AutoReset<WebInputEvent::Type> reset_type(&type_, type);
+ run_loop.Run();
+ }
+
+ InputEventAckState last_ack_state() const { return state_; }
+
+ protected:
+ virtual ~InputEventMessageFilter() {}
+
+ private:
+ void ReceivedEventAck(WebInputEvent::Type type, InputEventAckState state) {
+ if (type_ == type) {
+ state_ = state;
+ quit_.Run();
+ }
+ }
+
+ // BrowserMessageFilter:
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) OVERRIDE {
+ if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) {
+ ui::LatencyInfo latency;
+ WebInputEvent::Type type = WebInputEvent::Undefined;
+ InputEventAckState ack = INPUT_EVENT_ACK_STATE_UNKNOWN;
+ InputHostMsg_HandleInputEvent_ACK::Read(&message, &type, &ack, &latency);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&InputEventMessageFilter::ReceivedEventAck,
+ this, type, ack));
+ }
+ return false;
+ }
+
+ base::Closure quit_;
+ WebInputEvent::Type type_;
+ InputEventAckState state_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilter);
+};
+
+class TouchInputBrowserTest : public ContentBrowserTest,
+ public testing::WithParamInterface<std::string> {
+ public:
+ TouchInputBrowserTest() {}
+ virtual ~TouchInputBrowserTest() {}
+
+ RenderWidgetHostImpl* GetWidgetHost() {
+ return RenderWidgetHostImpl::From(shell()->web_contents()->
+ GetRenderViewHost());
+ }
+
+ InputEventMessageFilter* filter() { return filter_.get(); }
+
+ protected:
+ void LoadURLAndAddFilter() {
+ const GURL data_url(kTouchEventDataURL);
+ NavigateToURL(shell(), data_url);
+
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderWidgetHostImpl* host =
+ RenderWidgetHostImpl::From(web_contents->GetRenderViewHost());
+ host->GetView()->SetSize(gfx::Size(400, 400));
+
+ // The page is loaded in the renderer, wait for a new frame to arrive.
+ while (!host->ScheduleComposite())
+ GiveItSomeTime();
+
+ filter_ = new InputEventMessageFilter();
+ host->GetProcess()->AddFilter(filter_);
+ }
+
+ // ContentBrowserTest:
+ virtual void SetUp() OVERRIDE {
+ // We expect real pixel output for these tests.
+ UseRealGLContexts();
+
+ // On legacy windows, these tests need real GL bindings to pass.
+#if defined(OS_WIN) && !defined(USE_AURA)
+ UseRealGLBindings();
+#endif
+
+ ContentBrowserTest::SetUp();
+ }
+
+ virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE {
+ cmd->AppendSwitchASCII(switches::kTouchEvents,
+ switches::kTouchEventsEnabled);
+ cmd->AppendSwitch(GetParam());
+ }
+
+ scoped_refptr<InputEventMessageFilter> filter_;
+};
+
+// Touch input event tests don't work on Mac with the legacy software renderer.
+// These can be enabled when software compositing is enabled.
+// http://crbug.com/268038
+#if defined(OS_MACOSX)
+#define MAYBE_TouchNoHandler DISABLED_TouchNoHandler
+#else
+#define MAYBE_TouchNoHandler TouchNoHandler
+#endif
+IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, MAYBE_TouchNoHandler) {
+ LoadURLAndAddFilter();
+ SyntheticWebTouchEvent touch;
+
+ // A press on |first| should be acked with NO_CONSUMER_EXISTS since there is
+ // no touch-handler on it.
+ touch.PressPoint(25, 25);
+ GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
+ filter()->WaitForAck(WebInputEvent::TouchStart);
+
+ if (GetParam() == std::string(switches::kEnableThreadedCompositing)) {
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
+ filter()->last_ack_state());
+ } else {
+ // http://crbug.com/326232: This should be NO_CONSUMER_EXISTS once
+ // WebViewImpl::hasTouchEventHandlersAt() is implemented.
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
+ }
+
+ // If a touch-press is acked with NO_CONSUMER_EXISTS, then subsequent
+ // touch-points don't need to be dispatched until the touch point is released.
+ touch.ReleasePoint(0);
+ GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
+ touch.ResetPoints();
+}
+
+// Touch input event tests don't work on Mac with the legacy software renderer.
+// These can be enabled when software compositing is enabled.
+// http://crbug.com/268038
+#if defined(OS_MACOSX)
+#define MAYBE_TouchHandlerNoConsume DISABLED_TouchHandlerNoConsume
+#else
+#define MAYBE_TouchHandlerNoConsume TouchHandlerNoConsume
+#endif
+IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, MAYBE_TouchHandlerNoConsume) {
+ LoadURLAndAddFilter();
+ SyntheticWebTouchEvent touch;
+
+ // Press on |second| should be acked with NOT_CONSUMED since there is a
+ // touch-handler on |second|, but it doesn't consume the event.
+ touch.PressPoint(125, 25);
+ GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
+ filter()->WaitForAck(WebInputEvent::TouchStart);
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
+
+ touch.ReleasePoint(0);
+ GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
+ filter()->WaitForAck(WebInputEvent::TouchEnd);
+ touch.ResetPoints();
+}
+
+// Touch input event tests don't work on Mac with the legacy software renderer.
+// These can be enabled when software compositing is enabled.
+// http://crbug.com/268038
+#if defined(OS_MACOSX)
+#define MAYBE_TouchHandlerConsume DISABLED_TouchHandlerConsume
+#else
+#define MAYBE_TouchHandlerConsume TouchHandlerConsume
+#endif
+IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, MAYBE_TouchHandlerConsume) {
+ LoadURLAndAddFilter();
+ SyntheticWebTouchEvent touch;
+
+ // Press on |third| should be acked with CONSUMED since the touch-handler on
+ // |third| consimes the event.
+ touch.PressPoint(25, 125);
+ GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
+ filter()->WaitForAck(WebInputEvent::TouchStart);
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state());
+
+ touch.ReleasePoint(0);
+ GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
+ filter()->WaitForAck(WebInputEvent::TouchEnd);
+}
+
+// Touch input event tests don't work on Mac with the legacy software renderer.
+// These can be enabled when software compositing is enabled.
+// http://crbug.com/268038
+#if defined(OS_MACOSX)
+#define MAYBE_MultiPointTouchPress DISABLED_MultiPointTouchPress
+#else
+#define MAYBE_MultiPointTouchPress MultiPointTouchPress
+#endif
+IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, MAYBE_MultiPointTouchPress) {
+ LoadURLAndAddFilter();
+ SyntheticWebTouchEvent touch;
+
+ // Press on |first|, which sould be acked with NO_CONSUMER_EXISTS. Then press
+ // on |third|. That point should be acked with CONSUMED.
+ touch.PressPoint(25, 25);
+ GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
+ filter()->WaitForAck(WebInputEvent::TouchStart);
+ if (GetParam() == std::string(switches::kEnableThreadedCompositing)) {
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
+ filter()->last_ack_state());
+ } else {
+ // http://crbug.com/326232: This should be NO_CONSUMER_EXISTS once
+ // WebViewImpl::hasTouchEventHandlersAt() is implemented.
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
+ }
+
+ touch.PressPoint(25, 125);
+ GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
+ filter()->WaitForAck(WebInputEvent::TouchStart);
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state());
+}
+
+INSTANTIATE_TEST_CASE_P(WithoutInputHandlerProxy, TouchInputBrowserTest,
+ ::testing::Values(std::string(switches::kDisableThreadedCompositing)));
+
+#if !defined(OS_MACOSX)
+INSTANTIATE_TEST_CASE_P(WithInputHandlerProxy, TouchInputBrowserTest,
+ ::testing::Values(std::string(switches::kEnableThreadedCompositing)));
+#endif
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc
index ab89f3151fc..d9207792027 100644
--- a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc
+++ b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc
@@ -13,8 +13,8 @@
namespace content {
TouchpadTapSuppressionController::TouchpadTapSuppressionController(
- InputRouter* /*input_router*/)
- : input_router_(NULL) {}
+ TouchpadTapSuppressionControllerClient* /* client */)
+ : client_(NULL) {}
TouchpadTapSuppressionController::~TouchpadTapSuppressionController() {}
@@ -42,10 +42,7 @@ int TouchpadTapSuppressionController::MaxTapGapTimeInMs() {
void TouchpadTapSuppressionController::DropStashedTapDown() {
}
-void TouchpadTapSuppressionController::ForwardStashedTapDownForDeferral() {
-}
-
-void TouchpadTapSuppressionController::ForwardStashedTapDownSkipDeferral() {
+void TouchpadTapSuppressionController::ForwardStashedTapDown() {
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
index 3350350750e..64b2ed4bc2a 100644
--- a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
+++ b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
@@ -7,20 +7,28 @@
#include "base/memory/scoped_ptr.h"
#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
+#include "content/common/content_export.h"
#include "content/port/browser/event_with_latency_info.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace content {
-class InputRouter;
class TapSuppressionController;
+class CONTENT_EXPORT TouchpadTapSuppressionControllerClient {
+ public:
+ virtual ~TouchpadTapSuppressionControllerClient() {}
+ virtual void SendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& event) = 0;
+};
+
// Controls the suppression of touchpad taps immediately following the dispatch
// of a GestureFlingCancel event.
class TouchpadTapSuppressionController : public TapSuppressionControllerClient {
public:
- // The |input_router| must outlive the TouchpadTapSupressionController.
- explicit TouchpadTapSuppressionController(InputRouter* input_router);
+ // The |client| must outlive the TouchpadTapSupressionController.
+ explicit TouchpadTapSuppressionController(
+ TouchpadTapSuppressionControllerClient* client);
virtual ~TouchpadTapSuppressionController();
// Should be called on arrival of GestureFlingCancel events.
@@ -46,10 +54,9 @@ class TouchpadTapSuppressionController : public TapSuppressionControllerClient {
virtual int MaxCancelToDownTimeInMs() OVERRIDE;
virtual int MaxTapGapTimeInMs() OVERRIDE;
virtual void DropStashedTapDown() OVERRIDE;
- virtual void ForwardStashedTapDownForDeferral() OVERRIDE;
- virtual void ForwardStashedTapDownSkipDeferral() OVERRIDE;
+ virtual void ForwardStashedTapDown() OVERRIDE;
- InputRouter* input_router_;
+ TouchpadTapSuppressionControllerClient* client_;
MouseEventWithLatencyInfo stashed_mouse_down_;
// The core controller of tap suppression.
diff --git a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller_aura.cc b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller_aura.cc
index 4c0cf3432c8..991097d3f75 100644
--- a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller_aura.cc
+++ b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller_aura.cc
@@ -4,16 +4,15 @@
#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
-#include "content/browser/renderer_host/input/input_router.h"
#include "content/browser/renderer_host/input/tap_suppression_controller.h"
#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
-#include "ui/base/gestures/gesture_configuration.h"
+#include "ui/events/gestures/gesture_configuration.h"
namespace content {
TouchpadTapSuppressionController::TouchpadTapSuppressionController(
- InputRouter* input_router)
- : input_router_(input_router),
+ TouchpadTapSuppressionControllerClient* client)
+ : client_(client),
controller_(new TapSuppressionController(this)) {
}
@@ -36,7 +35,7 @@ bool TouchpadTapSuppressionController::ShouldDeferMouseDown(
}
bool TouchpadTapSuppressionController::ShouldSuppressMouseUp() {
- return controller_->ShouldSuppressTapUp();
+ return controller_->ShouldSuppressTapEnd();
}
int TouchpadTapSuppressionController::MaxCancelToDownTimeInMs() {
@@ -50,16 +49,10 @@ int TouchpadTapSuppressionController::MaxTapGapTimeInMs() {
void TouchpadTapSuppressionController::DropStashedTapDown() {
}
-void TouchpadTapSuppressionController::ForwardStashedTapDownForDeferral() {
+void TouchpadTapSuppressionController::ForwardStashedTapDown() {
// Mouse downs are not handled by gesture event filter; so, they are
// immediately forwarded to the renderer.
- input_router_->SendMouseEventImmediately(stashed_mouse_down_);
-}
-
-void TouchpadTapSuppressionController::ForwardStashedTapDownSkipDeferral() {
- // Mouse downs are not handled by gesture event filter; so, they are
- // immediately forwarded to the renderer.
- input_router_->SendMouseEventImmediately(stashed_mouse_down_);
+ client_->SendMouseEventImmediately(stashed_mouse_down_);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
index ce7fb907c86..39fca2f854e 100644
--- a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
+++ b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
@@ -6,7 +6,11 @@
#include "content/browser/renderer_host/input/gesture_event_filter.h"
#include "content/browser/renderer_host/input/tap_suppression_controller.h"
-#include "ui/base/gestures/gesture_configuration.h"
+#include "ui/events/gestures/gesture_configuration.h"
+
+#if defined(OS_ANDROID)
+#include "ui/gfx/android/view_configuration.h"
+#endif
namespace content {
@@ -31,18 +35,34 @@ bool TouchscreenTapSuppressionController::ShouldDeferGestureTapDown(
const GestureEventWithLatencyInfo& event) {
bool should_defer = controller_->ShouldDeferTapDown();
if (should_defer)
- stashed_tap_down_ = event;
+ stashed_tap_down_.reset(new GestureEventWithLatencyInfo(event));
return should_defer;
}
-bool TouchscreenTapSuppressionController::ShouldSuppressGestureTap() {
- return controller_->ShouldSuppressTapUp();
+bool TouchscreenTapSuppressionController::ShouldDeferGestureShowPress(
+ const GestureEventWithLatencyInfo& event) {
+ if (!stashed_tap_down_)
+ return false;
+
+ stashed_show_press_.reset(new GestureEventWithLatencyInfo(event));
+ return true;
+}
+
+bool TouchscreenTapSuppressionController::ShouldSuppressGestureTapEnd() {
+ return controller_->ShouldSuppressTapEnd();
}
-bool TouchscreenTapSuppressionController::ShouldSuppressGestureTapCancel() {
- return controller_->ShouldSuppressTapCancel();
+#if defined(OS_ANDROID)
+// TODO(jdduke): Enable ui::GestureConfiguration on Android and initialize
+// with parameters from ViewConfiguration.
+int TouchscreenTapSuppressionController::MaxCancelToDownTimeInMs() {
+ return gfx::ViewConfiguration::GetTapTimeoutInMs();
}
+int TouchscreenTapSuppressionController::MaxTapGapTimeInMs() {
+ return gfx::ViewConfiguration::GetLongPressTimeoutInMs();
+}
+#else
int TouchscreenTapSuppressionController::MaxCancelToDownTimeInMs() {
return ui::GestureConfiguration::fling_max_cancel_to_down_time_in_ms();
}
@@ -51,16 +71,20 @@ int TouchscreenTapSuppressionController::MaxTapGapTimeInMs() {
return static_cast<int>(
ui::GestureConfiguration::semi_long_press_time_in_seconds() * 1000);
}
+#endif
void TouchscreenTapSuppressionController::DropStashedTapDown() {
+ stashed_tap_down_.reset();
+ stashed_show_press_.reset();
}
-void TouchscreenTapSuppressionController::ForwardStashedTapDownForDeferral() {
- gesture_event_filter_->ForwardGestureEventForDeferral(stashed_tap_down_);
-}
-
-void TouchscreenTapSuppressionController::ForwardStashedTapDownSkipDeferral() {
- gesture_event_filter_->ForwardGestureEventSkipDeferral(stashed_tap_down_);
+void TouchscreenTapSuppressionController::ForwardStashedTapDown() {
+ DCHECK(stashed_tap_down_);
+ ScopedGestureEvent tap_down = stashed_tap_down_.Pass();
+ ScopedGestureEvent show_press = stashed_show_press_.Pass();
+ gesture_event_filter_->ForwardGestureEvent(*tap_down);
+ if (show_press)
+ gesture_event_filter_->ForwardGestureEvent(*show_press);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
index b974d9c08ba..0857bd74672 100644
--- a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
+++ b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
@@ -30,28 +30,29 @@ class TouchscreenTapSuppressionController
void GestureFlingCancelAck(bool processed);
// Should be called on arrival of GestureTapDown events. Returns true if the
- // caller should stop normal handling of the GestureTapDown. In this case, the
- // caller is responsible for saving the event for later use, if needed.
+ // caller should stop normal handling of the GestureTapDown.
bool ShouldDeferGestureTapDown(const GestureEventWithLatencyInfo& event);
- // Should be called on arrival of GestureTap events. Returns true if the
- // caller should stop normal handling of the GestureTap.
- bool ShouldSuppressGestureTap();
+ // Should be called on arrival of GestureShowPress events. Returns true if the
+ // caller should stop normal handling of the GestureShowPress.
+ bool ShouldDeferGestureShowPress(const GestureEventWithLatencyInfo& event);
- // Should be called on arrival of GestureTapCancel events. Returns true if the
- // caller should stop normal handling of the GestureTapCancel.
- bool ShouldSuppressGestureTapCancel();
+ // Should be called on arrival of tap-ending gesture events. Returns true if
+ // the caller should stop normal handling of the GestureTap.
+ bool ShouldSuppressGestureTapEnd();
private:
// TapSuppressionControllerClient implementation.
virtual int MaxCancelToDownTimeInMs() OVERRIDE;
virtual int MaxTapGapTimeInMs() OVERRIDE;
virtual void DropStashedTapDown() OVERRIDE;
- virtual void ForwardStashedTapDownForDeferral() OVERRIDE;
- virtual void ForwardStashedTapDownSkipDeferral() OVERRIDE;
+ virtual void ForwardStashedTapDown() OVERRIDE;
GestureEventFilter* gesture_event_filter_;
- GestureEventWithLatencyInfo stashed_tap_down_;
+
+ typedef scoped_ptr<GestureEventWithLatencyInfo> ScopedGestureEvent;
+ ScopedGestureEvent stashed_tap_down_;
+ ScopedGestureEvent stashed_show_press_;
// The core controller of tap suppression.
scoped_ptr<TapSuppressionController> controller_;
diff --git a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller_stub.cc b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller_stub.cc
index d6cf6c8a6a7..198dcb5de9a 100644
--- a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller_stub.cc
+++ b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller_stub.cc
@@ -28,11 +28,12 @@ bool TouchscreenTapSuppressionController::ShouldDeferGestureTapDown(
return false;
}
-bool TouchscreenTapSuppressionController::ShouldSuppressGestureTap() {
+bool TouchscreenTapSuppressionController::ShouldDeferGestureShowPress(
+ const GestureEventWithLatencyInfo& /*event*/) {
return false;
}
-bool TouchscreenTapSuppressionController::ShouldSuppressGestureTapCancel() {
+bool TouchscreenTapSuppressionController::ShouldSuppressGestureTapEnd() {
return false;
}
@@ -46,8 +47,6 @@ int TouchscreenTapSuppressionController::MaxTapGapTimeInMs() {
void TouchscreenTapSuppressionController::DropStashedTapDown() {}
-void TouchscreenTapSuppressionController::ForwardStashedTapDownForDeferral() {}
-
-void TouchscreenTapSuppressionController::ForwardStashedTapDownSkipDeferral() {}
+void TouchscreenTapSuppressionController::ForwardStashedTapDown() {}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
index b5c96c657eb..43e9bb86572 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
@@ -12,11 +12,11 @@
namespace content {
-using WebKit::WebInputEvent;
-using WebKit::WebKeyboardEvent;
-using WebKit::WebGestureEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebGestureEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
WebKeyboardEvent WebKeyboardEventBuilder::Build(WebInputEvent::Type type,
int modifiers,
@@ -48,7 +48,7 @@ WebKeyboardEvent WebKeyboardEventBuilder::Build(WebInputEvent::Type type,
return result;
}
-WebMouseEvent WebMouseEventBuilder::Build(WebKit::WebInputEvent::Type type,
+WebMouseEvent WebMouseEventBuilder::Build(blink::WebInputEvent::Type type,
WebMouseEvent::Button button,
double time_sec,
int window_x,
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
index 4488375aa5f..10595725335 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
@@ -11,8 +11,8 @@ namespace content {
class WebMouseEventBuilder {
public:
- static WebKit::WebMouseEvent Build(WebKit::WebInputEvent::Type type,
- WebKit::WebMouseEvent::Button button,
+ static blink::WebMouseEvent Build(blink::WebInputEvent::Type type,
+ blink::WebMouseEvent::Button button,
double time_sec,
int window_x,
int window_y,
@@ -29,7 +29,7 @@ class WebMouseWheelEventBuilder {
DIRECTION_RIGHT,
};
- static WebKit::WebMouseWheelEvent Build(Direction direction,
+ static blink::WebMouseWheelEvent Build(Direction direction,
double time_sec,
int window_x,
int window_y);
@@ -37,7 +37,7 @@ class WebMouseWheelEventBuilder {
class WebKeyboardEventBuilder {
public:
- static WebKit::WebKeyboardEvent Build(WebKit::WebInputEvent::Type type,
+ static blink::WebKeyboardEvent Build(blink::WebInputEvent::Type type,
int modifiers,
double time_sec,
int keycode,
@@ -47,7 +47,7 @@ class WebKeyboardEventBuilder {
class WebGestureEventBuilder {
public:
- static WebKit::WebGestureEvent Build(WebKit::WebInputEvent::Type type,
+ static blink::WebGestureEvent Build(blink::WebInputEvent::Type type,
double time_sec,
int x,
int y);
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.cc
index c101595c79f..d5c2bded6e1 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.cc
@@ -13,10 +13,10 @@
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/keycodes/keyboard_code_conversion_gtk.h"
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebKeyboardEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebKeyboardEvent;
namespace {
@@ -53,7 +53,7 @@ void ResetClickCountState() {
last_click_time = 0;
last_click_x = 0;
last_click_y = 0;
- last_click_button = WebKit::WebMouseEvent::ButtonNone;
+ last_click_button = blink::WebMouseEvent::ButtonNone;
}
bool IsKeyPadKeyval(guint keyval) {
@@ -395,7 +395,7 @@ WebKeyboardEvent WebKeyboardEventBuilder::Build(wchar_t character,
// function creates a WebInputEvent::Char event without using a
// GdkEventKey object.
WebKeyboardEvent result;
- result.type = WebKit::WebInputEvent::Char;
+ result.type = blink::WebInputEvent::Char;
result.timeStampSeconds = timeStampSeconds;
result.modifiers = GdkStateToWebEventModifiers(state);
result.windowsKeyCode = character;
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.h b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.h
index 6fe16429b35..0d0250b1746 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk.h
@@ -19,23 +19,23 @@ namespace content {
class CONTENT_EXPORT WebKeyboardEventBuilder {
public:
- static WebKit::WebKeyboardEvent Build(const GdkEventKey* event);
- static WebKit::WebKeyboardEvent Build(wchar_t character,
+ static blink::WebKeyboardEvent Build(const GdkEventKey* event);
+ static blink::WebKeyboardEvent Build(wchar_t character,
int state,
double time_secs);
};
class CONTENT_EXPORT WebMouseEventBuilder {
public:
- static WebKit::WebMouseEvent Build(const GdkEventButton* event);
- static WebKit::WebMouseEvent Build(const GdkEventMotion* event);
- static WebKit::WebMouseEvent Build(const GdkEventCrossing* event);
+ static blink::WebMouseEvent Build(const GdkEventButton* event);
+ static blink::WebMouseEvent Build(const GdkEventMotion* event);
+ static blink::WebMouseEvent Build(const GdkEventCrossing* event);
};
class CONTENT_EXPORT WebMouseWheelEventBuilder {
public:
static float ScrollbarPixelsPerTick();
- static WebKit::WebMouseWheelEvent Build(
+ static blink::WebMouseWheelEvent Build(
const GdkEventScroll* event);
};
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc
index 9498c9eb1be..b5e2d423a08 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc
@@ -11,9 +11,9 @@
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/keycodes/keyboard_code_conversion_gtk.h"
-using WebKit::WebInputEvent;
-using WebKit::WebKeyboardEvent;
-using WebKit::WebMouseEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
using content::WebMouseEventBuilder;
using content::WebKeyboardEventBuilder;
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_win.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_win.cc
index ba081fd429b..8c63e44db09 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_win.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_win.cc
@@ -7,10 +7,10 @@
#include "base/logging.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
-using WebKit::WebInputEvent;
-using WebKit::WebKeyboardEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
namespace content {
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_win.h b/chromium/content/browser/renderer_host/input/web_input_event_builders_win.h
index f01cd29fd5c..d3ec4a7b86f 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_win.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_win.h
@@ -13,19 +13,19 @@ namespace content {
class WebKeyboardEventBuilder {
public:
- static WebKit::WebKeyboardEvent Build(HWND hwnd, UINT message,
+ static blink::WebKeyboardEvent Build(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
};
class WebMouseEventBuilder {
public:
- static WebKit::WebMouseEvent Build(HWND hwnd, UINT message,
+ static blink::WebMouseEvent Build(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
};
class WebMouseWheelEventBuilder {
public:
- static WebKit::WebMouseWheelEvent Build(HWND hwnd, UINT message,
+ static blink::WebMouseWheelEvent Build(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
};
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util.cc b/chromium/content/browser/renderer_host/input/web_input_event_util.cc
index e3c28990ffd..804c0b126c1 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util.cc
@@ -129,7 +129,7 @@ const char* GetKeyIdentifier(ui::KeyboardCode key_code) {
namespace content {
-void UpdateWindowsKeyCodeAndKeyIdentifier(WebKit::WebKeyboardEvent* event,
+void UpdateWindowsKeyCodeAndKeyIdentifier(blink::WebKeyboardEvent* event,
ui::KeyboardCode windows_key_code) {
event->windowsKeyCode = windows_key_code;
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util.h b/chromium/content/browser/renderer_host/input/web_input_event_util.h
index 1abaf8cf34e..f0680f24b53 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util.h
@@ -8,7 +8,7 @@
#include "content/common/content_export.h"
#include "ui/events/keycodes/keyboard_codes.h"
-namespace WebKit {
+namespace blink {
class WebKeyboardEvent;
}
@@ -17,7 +17,7 @@ namespace content {
// Update |event|'s windowsKeyCode and keyIdentifer properties using the
// provided |windows_key_code|.
CONTENT_EXPORT void UpdateWindowsKeyCodeAndKeyIdentifier(
- WebKit::WebKeyboardEvent* event,
+ blink::WebKeyboardEvent* event,
ui::KeyboardCode windows_key_code);
}
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util_posix.cc b/chromium/content/browser/renderer_host/input/web_input_event_util_posix.cc
index 72786c84058..7ae224281f5 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util_posix.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util_posix.cc
@@ -22,21 +22,21 @@ ui::KeyboardCode GetWindowsKeyCodeWithoutLocation(ui::KeyboardCode key_code) {
}
}
-WebKit::WebInputEvent::Modifiers GetLocationModifiersFromWindowsKeyCode(
+blink::WebInputEvent::Modifiers GetLocationModifiersFromWindowsKeyCode(
ui::KeyboardCode key_code) {
switch (key_code) {
case ui::VKEY_LCONTROL:
case ui::VKEY_LSHIFT:
case ui::VKEY_LMENU:
case ui::VKEY_LWIN:
- return WebKit::WebKeyboardEvent::IsLeft;
+ return blink::WebKeyboardEvent::IsLeft;
case ui::VKEY_RCONTROL:
case ui::VKEY_RSHIFT:
case ui::VKEY_RMENU:
case ui::VKEY_RWIN:
- return WebKit::WebKeyboardEvent::IsRight;
+ return blink::WebKeyboardEvent::IsRight;
default:
- return static_cast<WebKit::WebInputEvent::Modifiers>(0);
+ return static_cast<blink::WebInputEvent::Modifiers>(0);
}
}
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util_posix.h b/chromium/content/browser/renderer_host/input/web_input_event_util_posix.h
index e7dc1549cb9..9f2f4c05c02 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util_posix.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util_posix.h
@@ -11,7 +11,7 @@
namespace content {
ui::KeyboardCode GetWindowsKeyCodeWithoutLocation(ui::KeyboardCode key_code);
-WebKit::WebInputEvent::Modifiers GetLocationModifiersFromWindowsKeyCode(
+blink::WebInputEvent::Modifiers GetLocationModifiersFromWindowsKeyCode(
ui::KeyboardCode key_code);
} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/OWNERS b/chromium/content/browser/renderer_host/java/OWNERS
index 4b297c43ee6..d378671071d 100644
--- a/chromium/content/browser/renderer_host/java/OWNERS
+++ b/chromium/content/browser/renderer_host/java/OWNERS
@@ -1,2 +1,2 @@
-joth@chromium.org
steveblock@chromium.org
+torne@chromium.org
diff --git a/chromium/content/browser/renderer_host/java/java_bound_object.cc b/chromium/content/browser/renderer_host/java/java_bound_object.cc
index 4199cca77b8..e2ad87a15c3 100644
--- a/chromium/content/browser/renderer_host/java/java_bound_object.cc
+++ b/chromium/content/browser/renderer_host/java/java_bound_object.cc
@@ -11,6 +11,7 @@
#include "base/strings/stringprintf.h"
#include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
#include "content/browser/renderer_host/java/java_type.h"
+#include "content/browser/renderer_host/java/jni_helper.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/WebKit/public/web/WebBindings.h"
@@ -18,11 +19,10 @@ using base::StringPrintf;
using base::android::AttachCurrentThread;
using base::android::ConvertUTF8ToJavaString;
using base::android::GetClass;
-using base::android::GetMethodIDFromClassName;
using base::android::JavaRef;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
-using WebKit::WebBindings;
+using blink::WebBindings;
// The conversion between JavaScript and Java types is based on the Live
// Connect 2 spec. See
diff --git a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc
index 95a1c6aefe4..562517a1140 100644
--- a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc
@@ -18,7 +18,7 @@
#include "third_party/WebKit/public/web/WebBindings.h"
#if !defined(OS_ANDROID)
-#error "JavaBridge currently only supports OS_ANDROID"
+#error "JavaBridge only supports OS_ANDROID"
#endif
namespace content {
@@ -50,8 +50,7 @@ base::LazyInstance<JavaBridgeThread> g_background_thread =
JavaBridgeDispatcherHost::JavaBridgeDispatcherHost(
RenderViewHost* render_view_host)
- : RenderViewHostObserver(render_view_host),
- is_renderer_initialized_(false) {
+ : render_view_host_(render_view_host) {
}
JavaBridgeDispatcherHost::~JavaBridgeDispatcherHost() {
@@ -60,46 +59,27 @@ JavaBridgeDispatcherHost::~JavaBridgeDispatcherHost() {
base::Bind(&CleanUpStubs, stubs_));
}
-void JavaBridgeDispatcherHost::AddNamedObject(const string16& name,
+void JavaBridgeDispatcherHost::AddNamedObject(const base::string16& name,
NPObject* object) {
NPVariant_Param variant_param;
CreateNPVariantParam(object, &variant_param);
- if (!is_renderer_initialized_) {
- is_renderer_initialized_ = true;
- Send(new JavaBridgeMsg_Init(routing_id()));
- }
- Send(new JavaBridgeMsg_AddNamedObject(routing_id(), name, variant_param));
+ Send(new JavaBridgeMsg_AddNamedObject(
+ render_view_host_->GetRoutingID(), name, variant_param));
}
-void JavaBridgeDispatcherHost::RemoveNamedObject(const string16& name) {
+void JavaBridgeDispatcherHost::RemoveNamedObject(const base::string16& name) {
// On receipt of this message, the JavaBridgeDispatcher will drop its
// reference to the corresponding proxy object. When the last reference is
// removed, the proxy object will delete its NPObjectProxy, which will cause
// the NPObjectStub to be deleted, which will drop its reference to the
// original NPObject.
- Send(new JavaBridgeMsg_RemoveNamedObject(routing_id(), name));
-}
-
-bool JavaBridgeDispatcherHost::Send(IPC::Message* msg) {
- return RenderViewHostObserver::Send(msg);
+ Send(new JavaBridgeMsg_RemoveNamedObject(
+ render_view_host_->GetRoutingID(), name));
}
-void JavaBridgeDispatcherHost::RenderViewHostDestroyed(
- RenderViewHost* render_view_host) {
- // Base implementation deletes the object. This class is ref counted, with
- // refs held by the JavaBridgeDispatcherHostManager and base::Bind, so that
- // behavior is unwanted.
-}
-
-bool JavaBridgeDispatcherHost::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(JavaBridgeDispatcherHost, msg)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(JavaBridgeHostMsg_GetChannelHandle,
- OnGetChannelHandle)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
+void JavaBridgeDispatcherHost::RenderViewDeleted() {
+ render_view_host_ = NULL;
}
void JavaBridgeDispatcherHost::OnGetChannelHandle(IPC::Message* reply_msg) {
@@ -108,6 +88,15 @@ void JavaBridgeDispatcherHost::OnGetChannelHandle(IPC::Message* reply_msg) {
base::Bind(&JavaBridgeDispatcherHost::GetChannelHandle, this, reply_msg));
}
+void JavaBridgeDispatcherHost::Send(IPC::Message* msg) {
+ if (render_view_host_) {
+ render_view_host_->Send(msg);
+ return;
+ }
+
+ delete msg;
+}
+
void JavaBridgeDispatcherHost::GetChannelHandle(IPC::Message* reply_msg) {
// The channel creates the channel handle based on the renderer ID we passed
// to GetJavaBridgeChannelHost() and, on POSIX, the file descriptor used by
@@ -115,7 +104,11 @@ void JavaBridgeDispatcherHost::GetChannelHandle(IPC::Message* reply_msg) {
JavaBridgeHostMsg_GetChannelHandle::WriteReplyParams(
reply_msg,
channel_->channel_handle());
- Send(reply_msg);
+
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&JavaBridgeDispatcherHost::Send, this, reply_msg));
}
void JavaBridgeDispatcherHost::CreateNPVariantParam(NPObject* object,
@@ -135,20 +128,21 @@ void JavaBridgeDispatcherHost::CreateNPVariantParam(NPObject* object,
int route_id = JavaBridgeChannelHost::ThreadsafeGenerateRouteID();
param->npobject_routing_id = route_id;
- WebKit::WebBindings::retainObject(object);
+ blink::WebBindings::retainObject(object);
g_background_thread.Get().message_loop()->PostTask(
FROM_HERE,
base::Bind(&JavaBridgeDispatcherHost::CreateObjectStub, this, object,
- route_id));
+ render_view_host_->GetProcess()->GetID(), route_id));
}
void JavaBridgeDispatcherHost::CreateObjectStub(NPObject* object,
+ int render_process_id,
int route_id) {
DCHECK_EQ(g_background_thread.Get().message_loop(),
base::MessageLoop::current());
if (!channel_.get()) {
channel_ = JavaBridgeChannelHost::GetJavaBridgeChannelHost(
- render_view_host()->GetProcess()->GetID(),
+ render_process_id,
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
}
@@ -167,7 +161,7 @@ void JavaBridgeDispatcherHost::CreateObjectStub(NPObject* object,
// The NPObjectStub takes a reference to the NPObject. Release the ref added
// in CreateNPVariantParam().
- WebKit::WebBindings::releaseObject(object);
+ blink::WebBindings::releaseObject(object);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.h b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.h
index 6d44c39d22a..21e47c0d3b7 100644
--- a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.h
@@ -10,11 +10,14 @@
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "content/child/npapi/npobject_stub.h"
-#include "content/public/browser/render_view_host_observer.h"
class RouteIDGenerator;
struct NPObject;
+namespace IPC {
+class Message;
+}
+
namespace content {
class NPChannelBase;
class RenderViewHost;
@@ -25,11 +28,10 @@ struct NPVariant_Param;
// proxy object is created in the renderer. An instance of this class exists
// for each RenderViewHost.
class JavaBridgeDispatcherHost
- : public base::RefCountedThreadSafe<JavaBridgeDispatcherHost>,
- public RenderViewHostObserver {
+ : public base::RefCountedThreadSafe<JavaBridgeDispatcherHost> {
public:
// We hold a weak pointer to the RenderViewhost. It must outlive this object.
- JavaBridgeDispatcherHost(RenderViewHost* render_view_host);
+ explicit JavaBridgeDispatcherHost(RenderViewHost* render_view_host);
// Injects |object| into the main frame of the corresponding RenderView. A
// proxy object is created in the renderer and when the main frame's window
@@ -40,31 +42,26 @@ class JavaBridgeDispatcherHost
// to |object|, which is manipulated on the background thread. This class
// holds a reference to |object| for the time that the proxy object is bound
// to the window object.
- void AddNamedObject(const string16& name, NPObject* object);
- void RemoveNamedObject(const string16& name);
+ void AddNamedObject(const base::string16& name, NPObject* object);
+ void RemoveNamedObject(const base::string16& name);
+
+ // Since this object is ref-counted, it might outlive render_view_host_.
+ void RenderViewDeleted();
- // RenderViewHostObserver overrides:
- // The IPC macros require this to be public.
- virtual bool Send(IPC::Message* msg) OVERRIDE;
- virtual void RenderViewHostDestroyed(
- RenderViewHost* render_view_host) OVERRIDE;
+ void OnGetChannelHandle(IPC::Message* reply_msg);
private:
friend class base::RefCountedThreadSafe<JavaBridgeDispatcherHost>;
virtual ~JavaBridgeDispatcherHost();
- // RenderViewHostObserver override:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- // Message handlers
- void OnGetChannelHandle(IPC::Message* reply_msg);
+ void Send(IPC::Message* msg);
void GetChannelHandle(IPC::Message* reply_msg);
void CreateNPVariantParam(NPObject* object, NPVariant_Param* param);
- void CreateObjectStub(NPObject* object, int route_id);
+ void CreateObjectStub(NPObject* object, int render_process_id, int route_id);
scoped_refptr<NPChannelBase> channel_;
- bool is_renderer_initialized_;
+ RenderViewHost* render_view_host_;
std::vector<base::WeakPtr<NPObjectStub> > stubs_;
DISALLOW_COPY_AND_ASSIGN(JavaBridgeDispatcherHost);
diff --git a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc
index bac38564e79..02cf4dcc060 100644
--- a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc
+++ b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc
@@ -26,18 +26,18 @@ JavaBridgeDispatcherHostManager::JavaBridgeDispatcherHostManager(
JavaBridgeDispatcherHostManager::~JavaBridgeDispatcherHostManager() {
for (ObjectMap::iterator iter = objects_.begin(); iter != objects_.end();
++iter) {
- WebKit::WebBindings::releaseObject(iter->second);
+ blink::WebBindings::releaseObject(iter->second);
}
DCHECK_EQ(0U, instances_.size());
}
-void JavaBridgeDispatcherHostManager::AddNamedObject(const string16& name,
+void JavaBridgeDispatcherHostManager::AddNamedObject(const base::string16& name,
NPObject* object) {
// Record this object in a map so that we can add it into RenderViewHosts
// created later. The JavaBridgeDispatcherHost instances will take a
// reference to the object, but we take one too, because this method can be
// called before there are any such instances.
- WebKit::WebBindings::retainObject(object);
+ blink::WebBindings::retainObject(object);
objects_[name] = object;
for (InstanceMap::iterator iter = instances_.begin();
@@ -67,13 +67,14 @@ void JavaBridgeDispatcherHostManager::SetRetainedObjectSet(
}
}
-void JavaBridgeDispatcherHostManager::RemoveNamedObject(const string16& name) {
+void JavaBridgeDispatcherHostManager::RemoveNamedObject(
+ const base::string16& name) {
ObjectMap::iterator iter = objects_.find(name);
if (iter == objects_.end()) {
return;
}
- WebKit::WebBindings::releaseObject(iter->second);
+ blink::WebBindings::releaseObject(iter->second);
objects_.erase(iter);
for (InstanceMap::iterator iter = instances_.begin();
@@ -82,6 +83,11 @@ void JavaBridgeDispatcherHostManager::RemoveNamedObject(const string16& name) {
}
}
+void JavaBridgeDispatcherHostManager::OnGetChannelHandle(
+ RenderViewHost* render_view_host, IPC::Message* reply_msg) {
+ instances_[render_view_host]->OnGetChannelHandle(reply_msg);
+}
+
void JavaBridgeDispatcherHostManager::RenderViewCreated(
RenderViewHost* render_view_host) {
// Creates a JavaBridgeDispatcherHost for the specified RenderViewHost and
@@ -99,17 +105,12 @@ void JavaBridgeDispatcherHostManager::RenderViewCreated(
void JavaBridgeDispatcherHostManager::RenderViewDeleted(
RenderViewHost* render_view_host) {
+ if (!instances_.count(render_view_host)) // Needed for tests.
+ return;
+ instances_[render_view_host]->RenderViewDeleted();
instances_.erase(render_view_host);
}
-void JavaBridgeDispatcherHostManager::WebContentsDestroyed(
- WebContents* web_contents) {
- // When a WebContents is shutting down, it clears its observers before
- // it kills all of its RenderViewHosts, so we won't get a call to
- // RenderViewDeleted() for all RenderViewHosts.
- instances_.clear();
-}
-
void JavaBridgeDispatcherHostManager::DocumentAvailableInMainFrame() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Called when the window object has been cleared in the main frame.
diff --git a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h
index 6fb7aab7cfb..29523b57396 100644
--- a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h
+++ b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h
@@ -34,8 +34,11 @@ class JavaBridgeDispatcherHostManager
// These methods add or remove the object to each JavaBridgeDispatcherHost.
// Each one holds a reference to the NPObject while the object is bound to
// the corresponding RenderView. See JavaBridgeDispatcherHost for details.
- void AddNamedObject(const string16& name, NPObject* object);
- void RemoveNamedObject(const string16& name);
+ void AddNamedObject(const base::string16& name, NPObject* object);
+ void RemoveNamedObject(const base::string16& name);
+
+ void OnGetChannelHandle(RenderViewHost* render_view_host,
+ IPC::Message* reply_msg);
// Every time a JavaBoundObject backed by a real Java object is
// created/destroyed, we insert/remove a strong ref to that Java object into
@@ -48,7 +51,6 @@ class JavaBridgeDispatcherHostManager
// WebContentsObserver overrides
virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE;
virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE;
- virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
virtual void DocumentAvailableInMainFrame() OVERRIDE;
void JavaBoundObjectCreated(const base::android::JavaRef<jobject>& object);
@@ -58,7 +60,7 @@ class JavaBridgeDispatcherHostManager
typedef std::map<RenderViewHost*, scoped_refptr<JavaBridgeDispatcherHost> >
InstanceMap;
InstanceMap instances_;
- typedef std::map<string16, NPObject*> ObjectMap;
+ typedef std::map<base::string16, NPObject*> ObjectMap;
ObjectMap objects_;
JavaObjectWeakGlobalRef retained_object_set_;
diff --git a/chromium/content/browser/renderer_host/java/java_method.cc b/chromium/content/browser/renderer_host/java/java_method.cc
index 3cc569fbcae..5a654fe1300 100644
--- a/chromium/content/browser/renderer_host/java/java_method.cc
+++ b/chromium/content/browser/renderer_host/java/java_method.cc
@@ -9,11 +9,11 @@
#include "base/lazy_instance.h"
#include "base/memory/singleton.h"
#include "base/strings/string_util.h" // For ReplaceSubstringsAfterOffset
+#include "content/browser/renderer_host/java/jni_helper.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF8;
using base::android::GetClass;
-using base::android::GetMethodIDFromClassName;
using base::android::MethodID;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
@@ -86,7 +86,7 @@ std::string BinaryNameToJNIName(const std::string& binary_name,
return jni_name;
}
NOTREACHED();
- return EmptyString();
+ return std::string();
}
} // namespace
diff --git a/chromium/content/browser/renderer_host/media/OWNERS b/chromium/content/browser/renderer_host/media/OWNERS
index 45ac6611129..bc20fb9af2a 100644
--- a/chromium/content/browser/renderer_host/media/OWNERS
+++ b/chromium/content/browser/renderer_host/media/OWNERS
@@ -16,6 +16,9 @@ per-file web_contents*=hclam@chromium.org
per-file web_contents*=justinlin@chromium.org
per-file web_contents*=miu@chromium.org
per-file web_contents*=nick@chromium.org
+per-file video_capture_device_impl*=hclam@chromium.org
+per-file video_capture_device_impl*=miu@chromium.org
+per-file video_capture_device_impl*=nick@chromium.org
per-file video_capture_oracle*=hclam@chromium.org
per-file video_capture_oracle*=justinlin@chromium.org
per-file video_capture_oracle*=miu@chromium.org
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
index 50bb3ec8310..cfe00caea32 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -35,7 +35,7 @@ AudioInputDeviceManager::AudioInputDeviceManager(
media::AudioManagerBase::kDefaultDeviceName,
media::AudioManagerBase::kDefaultDeviceId,
44100, media::CHANNEL_LAYOUT_STEREO,
- 0, false);
+ 0);
fake_device.session_id = kFakeOpenSessionId;
devices_.push_back(fake_device);
}
@@ -143,7 +143,7 @@ void AudioInputDeviceManager::EnumerateOnDeviceThread(
it != device_names.end(); ++it) {
// Add device information to device vector.
devices->push_back(StreamDeviceInfo(
- stream_type, it->device_name, it->unique_id, false));
+ stream_type, it->device_name, it->unique_id));
}
// If the |use_fake_device_| flag is on, inject the fake device if there is
@@ -151,7 +151,7 @@ void AudioInputDeviceManager::EnumerateOnDeviceThread(
if (use_fake_device_ && devices->empty()) {
devices->push_back(StreamDeviceInfo(
stream_type, media::AudioManagerBase::kDefaultDeviceName,
- media::AudioManagerBase::kDefaultDeviceId, false));
+ media::AudioManagerBase::kDefaultDeviceId));
}
// Return the device list through the listener by posting a task on
@@ -170,7 +170,7 @@ void AudioInputDeviceManager::OpenOnDeviceThread(
DCHECK(IsOnDeviceThread());
StreamDeviceInfo out(info.device.type, info.device.name, info.device.id,
- 0, 0, 0, false);
+ 0, 0, 0);
out.session_id = session_id;
MediaStreamDevice::AudioDeviceParameters& input_params = out.device.input;
@@ -187,6 +187,7 @@ void AudioInputDeviceManager::OpenOnDeviceThread(
input_params.sample_rate = params.sample_rate();
input_params.channel_layout = params.channel_layout();
input_params.frames_per_buffer = params.frames_per_buffer();
+ input_params.effects = params.effects();
// Add preferred output device information if a matching output device
// exists.
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
index 25d8a1722e9..76cb1794a96 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -55,7 +55,7 @@ class AudioInputDeviceManagerTest : public testing::Test {
message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
- audio_manager_.reset(media::AudioManager::Create());
+ audio_manager_.reset(media::AudioManager::CreateForTesting());
manager_ = new AudioInputDeviceManager(audio_manager_.get());
audio_input_listener_.reset(new MockAudioInputDeviceManagerListener());
manager_->Register(audio_input_listener_.get(),
@@ -177,8 +177,7 @@ TEST_F(AudioInputDeviceManagerTest, OpenNotExistingDevice) {
int sample_rate(0);
int channel_config(0);
StreamDeviceInfo dummy_device(
- stream_type, device_name, device_id, sample_rate, channel_config, 2048,
- false);
+ stream_type, device_name, device_id, sample_rate, channel_config, 2048);
int session_id = manager_->Open(dummy_device);
EXPECT_CALL(*audio_input_listener_,
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
index 1c021095676..e3d88cc702b 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
@@ -8,6 +8,7 @@
#include "base/memory/shared_memory.h"
#include "base/metrics/histogram.h"
#include "base/process/process.h"
+#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/audio_input_sync_writer.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
@@ -56,15 +57,15 @@ AudioInputRendererHost::AudioInputRendererHost(
: audio_manager_(audio_manager),
media_stream_manager_(media_stream_manager),
audio_mirroring_manager_(audio_mirroring_manager),
- user_input_monitor_(user_input_monitor) {}
+ user_input_monitor_(user_input_monitor),
+ audio_log_(MediaInternals::GetInstance()->CreateAudioLog(
+ media::AudioLogFactory::AUDIO_INPUT_CONTROLLER)) {}
AudioInputRendererHost::~AudioInputRendererHost() {
DCHECK(audio_entries_.empty());
}
void AudioInputRendererHost::OnChannelClosing() {
- BrowserMessageFilter::OnChannelClosing();
-
// Since the IPC channel is gone, close all requested audio streams.
DeleteEntries();
}
@@ -180,6 +181,7 @@ void AudioInputRendererHost::DoHandleError(
if (!entry)
return;
+ audio_log_->OnError(entry->stream_id);
DeleteEntryOnError(entry);
}
@@ -306,6 +308,8 @@ void AudioInputRendererHost::OnCreateStream(
// to the map.
entry->stream_id = stream_id;
audio_entries_.insert(std::make_pair(stream_id, entry.release()));
+
+ audio_log_->OnCreated(stream_id, audio_params, device_id, std::string());
}
void AudioInputRendererHost::OnRecordStream(int stream_id) {
@@ -318,6 +322,7 @@ void AudioInputRendererHost::OnRecordStream(int stream_id) {
}
entry->controller->Record();
+ audio_log_->OnStarted(stream_id);
}
void AudioInputRendererHost::OnCloseStream(int stream_id) {
@@ -339,6 +344,7 @@ void AudioInputRendererHost::OnSetVolume(int stream_id, double volume) {
}
entry->controller->SetVolume(volume);
+ audio_log_->OnSetVolume(stream_id, volume);
}
void AudioInputRendererHost::SendErrorMessage(int stream_id) {
@@ -362,6 +368,7 @@ void AudioInputRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
entry->controller->Close(base::Bind(&AudioInputRendererHost::DeleteEntry,
this, entry));
entry->pending_close = true;
+ audio_log_->OnClosed(entry->stream_id);
}
}
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
index 5df1fc6f2f0..7587b144add 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
@@ -39,6 +39,7 @@
#include "content/public/browser/browser_thread.h"
#include "media/audio/audio_input_controller.h"
#include "media/audio/audio_io.h"
+#include "media/audio/audio_logging.h"
#include "media/audio/simple_sources.h"
namespace media {
@@ -79,6 +80,7 @@ class CONTENT_EXPORT AudioInputRendererHost
private:
// TODO(henrika): extend test suite (compare AudioRenderHost)
friend class BrowserThread;
+ friend class TestAudioInputRendererHost;
friend class base::DeleteHelper<AudioInputRendererHost>;
struct AudioEntry;
@@ -159,6 +161,8 @@ class CONTENT_EXPORT AudioInputRendererHost
// Raw pointer of the UserInputMonitor.
media::UserInputMonitor* user_input_monitor_;
+ scoped_ptr<media::AudioLog> audio_log_;
+
DISALLOW_COPY_AND_ASSIGN(AudioInputRendererHost);
};
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 c09dc6ce08b..6282a13fada 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/command_line.h"
#include "base/memory/shared_memory.h"
#include "base/metrics/histogram.h"
#include "base/process/process.h"
@@ -21,11 +20,11 @@
#include "content/public/browser/media_observer.h"
#include "content/public/common/content_switches.h"
#include "media/audio/audio_manager_base.h"
-#include "media/audio/shared_memory_util.h"
#include "media/base/audio_bus.h"
#include "media/base/limits.h"
using media::AudioBus;
+using media::AudioManager;
namespace content {
@@ -108,6 +107,7 @@ AudioRendererHost::AudioEntry::~AudioEntry() {}
///////////////////////////////////////////////////////////////////////////////
// AudioRendererHost implementations.
+
AudioRendererHost::AudioRendererHost(
int render_process_id,
media::AudioManager* audio_manager,
@@ -117,7 +117,8 @@ AudioRendererHost::AudioRendererHost(
: render_process_id_(render_process_id),
audio_manager_(audio_manager),
mirroring_manager_(mirroring_manager),
- media_internals_(media_internals),
+ audio_log_(media_internals->CreateAudioLog(
+ media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)),
media_stream_manager_(media_stream_manager) {
DCHECK(audio_manager_);
DCHECK(media_stream_manager_);
@@ -127,11 +128,18 @@ AudioRendererHost::~AudioRendererHost() {
DCHECK(audio_entries_.empty());
}
-void AudioRendererHost::OnChannelClosing() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- BrowserMessageFilter::OnChannelClosing();
+void AudioRendererHost::GetOutputControllers(
+ int render_view_id,
+ const RenderViewHost::GetAudioOutputControllersCallback& callback) const {
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&AudioRendererHost::DoGetOutputControllers, this,
+ render_view_id),
+ callback);
+}
+void AudioRendererHost::OnChannelClosing() {
// Since the IPC channel is gone, close all requested audio streams.
while (!audio_entries_.empty()) {
// Note: OnCloseStream() removes the entries from audio_entries_.
@@ -200,7 +208,7 @@ void AudioRendererHost::DoCompleteCreation(int stream_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!PeerHandle()) {
- NOTREACHED() << "Renderer process handle is invalid.";
+ DLOG(WARNING) << "Renderer process handle is invalid.";
ReportErrorAndClose(stream_id);
return;
}
@@ -242,7 +250,22 @@ void AudioRendererHost::DoCompleteCreation(int stream_id) {
entry->stream_id(),
foreign_memory_handle,
foreign_socket_handle,
- media::PacketSizeInBytes(entry->shared_memory()->requested_size())));
+ entry->shared_memory()->requested_size()));
+}
+
+RenderViewHost::AudioOutputControllerList
+AudioRendererHost::DoGetOutputControllers(int render_view_id) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ RenderViewHost::AudioOutputControllerList controllers;
+ AudioEntryMap::const_iterator it = audio_entries_.begin();
+ for (; it != audio_entries_.end(); ++it) {
+ AudioEntry* entry = it->second;
+ if (entry->render_view_id() == render_view_id)
+ controllers.push_back(entry->controller());
+ }
+
+ return controllers;
}
void AudioRendererHost::DoNotifyAudioPowerLevel(int stream_id,
@@ -253,14 +276,11 @@ void AudioRendererHost::DoNotifyAudioPowerLevel(int stream_id,
MediaObserver* const media_observer =
GetContentClient()->browser()->GetMediaObserver();
if (media_observer) {
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableAudibleNotifications)) {
- AudioEntry* const entry = LookupById(stream_id);
- if (entry) {
- media_observer->OnAudioStreamPlayingChanged(
- render_process_id_, entry->render_view_id(), entry->stream_id(),
- true, power_dbfs, clipped);
- }
+ AudioEntry* const entry = LookupById(stream_id);
+ if (entry) {
+ media_observer->OnAudioStreamPlayingChanged(
+ render_process_id_, entry->render_view_id(), entry->stream_id(),
+ true, power_dbfs, clipped);
}
}
}
@@ -327,15 +347,12 @@ void AudioRendererHost::OnCreateStream(
// Calculate output and input memory size.
int output_memory_size = AudioBus::CalculateMemorySize(params);
int frames = params.frames_per_buffer();
- int input_memory_size =
- AudioBus::CalculateMemorySize(input_channels, frames);
+ int input_memory_size = AudioBus::CalculateMemorySize(input_channels, frames);
// Create the shared memory and share with the renderer process.
// For synchronized I/O (if input_channels > 0) then we allocate
// extra memory after the output data for the input data.
- uint32 io_buffer_size = output_memory_size + input_memory_size;
- uint32 shared_memory_size =
- media::TotalSharedMemorySizeInBytes(io_buffer_size);
+ uint32 shared_memory_size = output_memory_size + input_memory_size;
scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
SendErrorMessage(stream_id);
@@ -363,10 +380,7 @@ void AudioRendererHost::OnCreateStream(
render_process_id_, entry->render_view_id(), entry->controller());
}
audio_entries_.insert(std::make_pair(stream_id, entry.release()));
- if (media_internals_) {
- media_internals_->OnAudioStreamCreated(
- this, stream_id, params, input_device_id);
- }
+ audio_log_->OnCreated(stream_id, params, input_device_id, output_device_id);
}
void AudioRendererHost::OnPlayStream(int stream_id) {
@@ -379,8 +393,7 @@ void AudioRendererHost::OnPlayStream(int stream_id) {
}
entry->controller()->Play();
- if (media_internals_)
- media_internals_->OnSetAudioStreamPlaying(this, stream_id, true);
+ audio_log_->OnStarted(stream_id);
}
void AudioRendererHost::OnPauseStream(int stream_id) {
@@ -393,8 +406,7 @@ void AudioRendererHost::OnPauseStream(int stream_id) {
}
entry->controller()->Pause();
- if (media_internals_)
- media_internals_->OnSetAudioStreamPlaying(this, stream_id, false);
+ audio_log_->OnStopped(stream_id);
}
void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
@@ -410,8 +422,7 @@ void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
if (volume < 0 || volume > 1.0)
return;
entry->controller()->SetVolume(volume);
- if (media_internals_)
- media_internals_->OnSetAudioStreamVolume(this, stream_id, volume);
+ audio_log_->OnSetVolume(stream_id, volume);
}
void AudioRendererHost::SendErrorMessage(int stream_id) {
@@ -437,9 +448,7 @@ void AudioRendererHost::OnCloseStream(int stream_id) {
}
controller->Close(
base::Bind(&AudioRendererHost::DeleteEntry, this, base::Passed(&entry)));
-
- if (media_internals_)
- media_internals_->OnSetAudioStreamStatus(this, stream_id, "closed");
+ audio_log_->OnClosed(stream_id);
}
void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) {
@@ -453,12 +462,6 @@ void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) {
render_process_id_, entry->render_view_id(), entry->stream_id(),
false, -std::numeric_limits<float>::infinity(), false);
}
-
- // Notify the media observer.
- if (media_internals_)
- media_internals_->OnDeleteAudioStream(this, entry->stream_id());
-
- // Note: |entry| will be deleted upon leaving this scope.
}
void AudioRendererHost::ReportErrorAndClose(int stream_id) {
@@ -472,9 +475,7 @@ void AudioRendererHost::ReportErrorAndClose(int stream_id) {
SendErrorMessage(stream_id);
- if (media_internals_)
- media_internals_->OnSetAudioStreamStatus(this, stream_id, "error");
-
+ audio_log_->OnError(stream_id);
OnCloseStream(stream_id);
}
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host.h b/chromium/content/browser/renderer_host/media/audio_renderer_host.h
index 47dbee9c0c1..147436619e2 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.h
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.h
@@ -47,7 +47,9 @@
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_view_host.h"
#include "media/audio/audio_io.h"
+#include "media/audio/audio_logging.h"
#include "media/audio/audio_output_controller.h"
#include "media/audio/simple_sources.h"
@@ -72,6 +74,11 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
MediaInternals* media_internals,
MediaStreamManager* media_stream_manager);
+ // Calls |callback| with the list of AudioOutputControllers for this object.
+ void GetOutputControllers(
+ int render_view_id,
+ const RenderViewHost::GetAudioOutputControllersCallback& callback) const;
+
// BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
virtual void OnDestruct() const OVERRIDE;
@@ -83,6 +90,7 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
friend class BrowserThread;
friend class base::DeleteHelper<AudioRendererHost>;
friend class MockAudioRendererHost;
+ friend class TestAudioRendererHost;
FRIEND_TEST_ALL_PREFIXES(AudioRendererHostTest, CreateMockStream);
FRIEND_TEST_ALL_PREFIXES(AudioRendererHostTest, MockStreamDataConversation);
@@ -124,6 +132,9 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
// NotifyStreamCreated message to the peer.
void DoCompleteCreation(int stream_id);
+ RenderViewHost::AudioOutputControllerList DoGetOutputControllers(
+ int render_view_id) const;
+
// Propagate measured power level of the audio signal to MediaObserver.
void DoNotifyAudioPowerLevel(int stream_id, float power_dbfs, bool clipped);
@@ -146,7 +157,7 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
media::AudioManager* const audio_manager_;
AudioMirroringManager* const mirroring_manager_;
- MediaInternals* const media_internals_;
+ scoped_ptr<media::AudioLog> audio_log_;
// Used to access to AudioInputDeviceManager.
MediaStreamManager* media_stream_manager_;
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 26c0963e5e8..ff36a2797bc 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
@@ -3,23 +3,19 @@
// found in the LICENSE file.
#include "base/bind.h"
-#include "base/environment.h"
#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/sync_socket.h"
-#include "content/browser/browser_thread_impl.h"
+#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/audio_mirroring_manager.h"
#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/browser/renderer_host/media/mock_media_observer.h"
#include "content/common/media/audio_messages.h"
-#include "content/common/media/media_stream_options.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "ipc/ipc_message_utils.h"
#include "media/audio/audio_manager.h"
-#include "media/audio/audio_manager_base.h"
-#include "media/audio/fake_audio_output_stream.h"
-#include "net/url_request/url_request_context.h"
+#include "media/base/bind_to_loop.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -28,11 +24,13 @@ using ::testing::Assign;
using ::testing::DoAll;
using ::testing::NotNull;
-namespace content {
+namespace {
+const int kRenderProcessId = 1;
+const int kRenderViewId = 4;
+const int kStreamId = 50;
+} // namespace
-static const int kRenderProcessId = 1;
-static const int kRenderViewId = 4;
-static const int kStreamId = 50;
+namespace content {
class MockAudioMirroringManager : public AudioMirroringManager {
public:
@@ -40,10 +38,12 @@ class MockAudioMirroringManager : public AudioMirroringManager {
virtual ~MockAudioMirroringManager() {}
MOCK_METHOD3(AddDiverter,
- void(int render_process_id, int render_view_id,
+ void(int render_process_id,
+ int render_view_id,
Diverter* diverter));
MOCK_METHOD3(RemoveDiverter,
- void(int render_process_id, int render_view_id,
+ void(int render_process_id,
+ int render_view_id,
Diverter* diverter));
private:
@@ -52,22 +52,19 @@ class MockAudioMirroringManager : public AudioMirroringManager {
class MockAudioRendererHost : public AudioRendererHost {
public:
- explicit MockAudioRendererHost(
- media::AudioManager* audio_manager,
- AudioMirroringManager* mirroring_manager,
- MediaInternals* media_internals,
- MediaStreamManager* media_stream_manager)
+ MockAudioRendererHost(media::AudioManager* audio_manager,
+ AudioMirroringManager* mirroring_manager,
+ MediaInternals* media_internals,
+ MediaStreamManager* media_stream_manager)
: AudioRendererHost(kRenderProcessId,
audio_manager,
mirroring_manager,
media_internals,
media_stream_manager),
- shared_memory_length_(0) {
- }
+ shared_memory_length_(0) {}
// A list of mock methods.
- MOCK_METHOD2(OnStreamCreated,
- void(int stream_id, int length));
+ MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length));
MOCK_METHOD1(OnStreamPlaying, void(int stream_id));
MOCK_METHOD1(OnStreamPaused, void(int stream_id));
MOCK_METHOD1(OnStreamError, void(int stream_id));
@@ -100,7 +97,8 @@ class MockAudioRendererHost : public AudioRendererHost {
return true;
}
- void OnStreamCreated(const IPC::Message& msg, int stream_id,
+ void OnStreamCreated(const IPC::Message& msg,
+ int stream_id,
base::SharedMemoryHandle handle,
#if defined(OS_WIN)
base::SyncSocket::Handle socket_handle,
@@ -127,7 +125,8 @@ class MockAudioRendererHost : public AudioRendererHost {
OnStreamCreated(stream_id, length);
}
- void OnStreamStateChanged(const IPC::Message& msg, int stream_id,
+ void OnStreamStateChanged(const IPC::Message& msg,
+ int stream_id,
media::AudioOutputIPCDelegate::State state) {
switch (state) {
case media::AudioOutputIPCDelegate::kPlaying:
@@ -152,64 +151,36 @@ class MockAudioRendererHost : public AudioRendererHost {
DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost);
};
-ACTION_P(QuitMessageLoop, message_loop) {
- message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
-}
-
class AudioRendererHostTest : public testing::Test {
public:
- AudioRendererHostTest() : is_stream_active_(false) {}
-
- protected:
- virtual void SetUp() {
- // Create a message loop so AudioRendererHost can use it.
- message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
-
- // Claim to be on both the UI and IO threads to pass all the DCHECKS.
- io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
- message_loop_.get()));
- ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
- message_loop_.get()));
- audio_manager_.reset(media::AudioManager::Create());
+ AudioRendererHostTest() {
+ audio_manager_.reset(media::AudioManager::CreateForTesting());
media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
media_stream_manager_->UseFakeDevice();
- observer_.reset(new MockMediaInternals());
- host_ = new MockAudioRendererHost(
- audio_manager_.get(), &mirroring_manager_, observer_.get(),
- media_stream_manager_.get());
+ host_ = new MockAudioRendererHost(audio_manager_.get(),
+ &mirroring_manager_,
+ MediaInternals::GetInstance(),
+ media_stream_manager_.get());
// Simulate IPC channel connected.
- host_->OnChannelConnected(base::GetCurrentProcId());
+ host_->set_peer_pid_for_testing(base::GetCurrentProcId());
}
- virtual void TearDown() {
- // Simulate closing the IPC channel.
+ virtual ~AudioRendererHostTest() {
+ // Simulate closing the IPC channel and give the audio thread time to close
+ // the underlying streams.
host_->OnChannelClosing();
+ SyncWithAudioThread();
// Release the reference to the mock object. The object will be destructed
// on message_loop_.
host_ = NULL;
-
- // We need to continue running message_loop_ to complete all destructions.
- SyncWithAudioThread();
- audio_manager_.reset();
-
- // Make sure the stream has been deleted before continuing.
- while (is_stream_active_)
- message_loop_->Run();
-
- io_thread_.reset();
- ui_thread_.reset();
-
- // Delete the IO message loop. This will cause the MediaStreamManager to be
- // notified so it will stop its device thread and device managers.
- message_loop_.reset();
}
+ protected:
void Create(bool unified_stream) {
- EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _))
- .WillOnce(DoAll(Assign(&is_stream_active_, true),
- QuitMessageLoop(message_loop_.get())));
+ EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
+
EXPECT_CALL(mirroring_manager_,
AddDiverter(kRenderProcessId, kRenderViewId, NotNull()))
.RetiresOnSaturation();
@@ -227,7 +198,8 @@ class AudioRendererHostTest : public testing::Test {
media::CHANNEL_LAYOUT_STEREO,
2,
media::AudioParameters::kAudioCDSampleRate, 16,
- media::AudioParameters::kAudioCDSampleRate / 10);
+ media::AudioParameters::kAudioCDSampleRate / 10,
+ media::AudioParameters::NO_EFFECTS);
} else {
session_id = 0;
params = media::AudioParameters(
@@ -237,65 +209,40 @@ class AudioRendererHostTest : public testing::Test {
media::AudioParameters::kAudioCDSampleRate / 10);
}
host_->OnCreateStream(kStreamId, kRenderViewId, session_id, params);
- message_loop_->Run();
// At some point in the future, a corresponding RemoveDiverter() call must
// be made.
EXPECT_CALL(mirroring_manager_,
RemoveDiverter(kRenderProcessId, kRenderViewId, NotNull()))
.RetiresOnSaturation();
-
- // All created streams should ultimately be closed.
- EXPECT_CALL(*observer_,
- OnSetAudioStreamStatus(_, kStreamId, "closed"));
-
- // Expect the audio stream will be deleted at some later point.
- EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId))
- .WillOnce(DoAll(Assign(&is_stream_active_, false),
- QuitMessageLoop(message_loop_.get())));
+ SyncWithAudioThread();
}
void Close() {
// Send a message to AudioRendererHost to tell it we want to close the
// stream.
host_->OnCloseStream(kStreamId);
- if (is_stream_active_)
- message_loop_->Run();
- else
- message_loop_->RunUntilIdle();
+ SyncWithAudioThread();
}
void Play() {
- EXPECT_CALL(*observer_,
- OnSetAudioStreamPlaying(_, kStreamId, true));
- EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId))
- .WillOnce(QuitMessageLoop(message_loop_.get()));
-
+ EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId));
host_->OnPlayStream(kStreamId);
- message_loop_->Run();
+ SyncWithAudioThread();
}
void Pause() {
- EXPECT_CALL(*observer_,
- OnSetAudioStreamPlaying(_, kStreamId, false));
- EXPECT_CALL(*host_.get(), OnStreamPaused(kStreamId))
- .WillOnce(QuitMessageLoop(message_loop_.get()));
-
+ EXPECT_CALL(*host_.get(), OnStreamPaused(kStreamId));
host_->OnPauseStream(kStreamId);
- message_loop_->Run();
+ SyncWithAudioThread();
}
void SetVolume(double volume) {
- EXPECT_CALL(*observer_,
- OnSetAudioStreamVolume(_, kStreamId, volume));
-
host_->OnSetVolume(kStreamId, volume);
- message_loop_->RunUntilIdle();
+ SyncWithAudioThread();
}
void SimulateError() {
- EXPECT_CALL(*observer_,
- OnSetAudioStreamStatus(_, kStreamId, "error"));
EXPECT_EQ(1u, host_->audio_entries_.size())
<< "Calls Create() before calling this method";
@@ -310,43 +257,27 @@ class AudioRendererHostTest : public testing::Test {
EXPECT_EQ(0u, host_->audio_entries_.size());
}
- // Called on the audio thread.
- static void PostQuitMessageLoop(base::MessageLoop* message_loop) {
- message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
- }
-
- // Called on the main thread.
- static void PostQuitOnAudioThread(media::AudioManager* audio_manager,
- base::MessageLoop* message_loop) {
- audio_manager->GetMessageLoop()->PostTask(FROM_HERE,
- base::Bind(&PostQuitMessageLoop, message_loop));
- }
-
// SyncWithAudioThread() waits until all pending tasks on the audio thread
// are executed while also processing pending task in message_loop_ on the
// current thread. It is used to synchronize with the audio thread when we are
// closing an audio stream.
void SyncWithAudioThread() {
- // Don't use scoped_refptr to addref the media::AudioManager when posting
- // to the thread that itself owns.
- message_loop_->PostTask(
- FROM_HERE, base::Bind(&PostQuitOnAudioThread,
- base::Unretained(audio_manager_.get()),
- message_loop_.get()));
- message_loop_->Run();
+ base::RunLoop().RunUntilIdle();
+
+ base::RunLoop run_loop;
+ audio_manager_->GetMessageLoop()->PostTask(
+ FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
+ run_loop.Run();
}
private:
- scoped_ptr<MockMediaInternals> observer_;
+ // MediaStreamManager uses a DestructionObserver, so it must outlive the
+ // TestBrowserThreadBundle.
+ scoped_ptr<MediaStreamManager> media_stream_manager_;
+ TestBrowserThreadBundle thread_bundle_;
+ scoped_ptr<media::AudioManager> audio_manager_;
MockAudioMirroringManager mirroring_manager_;
scoped_refptr<MockAudioRendererHost> host_;
- scoped_ptr<base::MessageLoop> message_loop_;
- scoped_ptr<BrowserThreadImpl> io_thread_;
- scoped_ptr<BrowserThreadImpl> ui_thread_;
- scoped_ptr<media::AudioManager> audio_manager_;
- scoped_ptr<MediaStreamManager> media_stream_manager_;
-
- bool is_stream_active_;
DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
};
diff --git a/chromium/content/browser/renderer_host/media/audio_sync_reader.cc b/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
index dea8ae2a207..a51d3d1e357 100644
--- a/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
+++ b/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
@@ -12,7 +12,6 @@
#include "content/public/common/content_switches.h"
#include "media/audio/audio_buffers_state.h"
#include "media/audio/audio_parameters.h"
-#include "media/audio/shared_memory_util.h"
using media::AudioBus;
@@ -25,9 +24,16 @@ AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory,
input_channels_(input_channels),
mute_audio_(CommandLine::ForCurrentProcess()->HasSwitch(
switches::kMuteAudio)),
+ packet_size_(shared_memory_->requested_size()),
renderer_callback_count_(0),
- renderer_missed_callback_count_(0) {
- packet_size_ = media::PacketSizeInBytes(shared_memory_->requested_size());
+ renderer_missed_callback_count_(0),
+#if defined(OS_MACOSX)
+ maximum_wait_time_(params.GetBufferDuration() / 2),
+#else
+ // TODO(dalecurtis): Investigate if we can reduce this on all platforms.
+ maximum_wait_time_(base::TimeDelta::FromMilliseconds(20)),
+#endif
+ buffer_index_(0) {
int input_memory_size = 0;
int output_memory_size = AudioBus::CalculateMemorySize(params);
if (input_channels_ > 0) {
@@ -37,9 +43,11 @@ AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory,
char* input_data =
static_cast<char*>(shared_memory_->memory()) + output_memory_size;
input_bus_ = AudioBus::WrapMemory(input_channels_, frames, input_data);
+ input_bus_->Zero();
}
DCHECK_EQ(packet_size_, output_memory_size + input_memory_size);
output_bus_ = AudioBus::WrapMemory(params, shared_memory->memory());
+ output_bus_->Zero();
}
AudioSyncReader::~AudioSyncReader() {
@@ -54,93 +62,40 @@ AudioSyncReader::~AudioSyncReader() {
"Media.AudioRendererMissedDeadline", percentage_missed);
}
-bool AudioSyncReader::DataReady() {
- return !media::IsUnknownDataSize(shared_memory_, packet_size_);
-}
-
// media::AudioOutputController::SyncReader implementations.
void AudioSyncReader::UpdatePendingBytes(uint32 bytes) {
- if (bytes != static_cast<uint32>(media::kPauseMark)) {
- // Store unknown length of data into buffer, so we later
- // can find out if data became available.
- media::SetUnknownDataSize(shared_memory_, packet_size_);
- }
-
- if (socket_) {
- socket_->Send(&bytes, sizeof(bytes));
- }
+ // Zero out the entire output buffer to avoid stuttering/repeating-buffers
+ // in the anomalous case if the renderer is unable to keep up with real-time.
+ output_bus_->Zero();
+ socket_->Send(&bytes, sizeof(bytes));
+ ++buffer_index_;
}
-int AudioSyncReader::Read(bool block, const AudioBus* source, AudioBus* dest) {
+void AudioSyncReader::Read(const AudioBus* source, AudioBus* dest) {
++renderer_callback_count_;
- if (!DataReady()) {
+ if (!WaitUntilDataIsReady()) {
++renderer_missed_callback_count_;
-
- if (block)
- WaitTillDataReady();
+ dest->Zero();
+ return;
}
// Copy optional synchronized live audio input for consumption by renderer
// process.
- if (source && input_bus_) {
- DCHECK_EQ(source->channels(), input_bus_->channels());
- // TODO(crogers): In some cases with device and sample-rate changes
- // it's possible for an AOR to insert a resampler in the path.
- // Because this is used with the Web Audio API, it'd be better
- // to bypass the device change handling in AOR and instead let
- // the renderer-side Web Audio code deal with this.
- if (source->frames() == input_bus_->frames() &&
- source->channels() == input_bus_->channels())
+ if (input_bus_) {
+ if (source)
source->CopyTo(input_bus_.get());
else
input_bus_->Zero();
}
- // Retrieve the actual number of bytes available from the shared memory. If
- // the renderer has not completed rendering this value will be invalid (still
- // the marker stored in UpdatePendingBytes() above) and must be sanitized.
- // TODO(dalecurtis): Technically this is not the exact size. Due to channel
- // padding for alignment, there may be more data available than this; AudioBus
- // will automatically do the right thing during CopyTo(). Rename this method
- // to GetActualFrameCount().
- uint32 size = media::GetActualDataSizeInBytes(shared_memory_, packet_size_);
-
- // Compute the actual number of frames read. It's important to sanitize this
- // value for a couple reasons. One, it might still be the unknown data size
- // marker. Two, shared memory comes from a potentially untrusted source.
- int frames =
- size / (sizeof(*output_bus_->channel(0)) * output_bus_->channels());
- if (frames < 0)
- frames = 0;
- else if (frames > output_bus_->frames())
- frames = output_bus_->frames();
-
- if (mute_audio_) {
+ if (mute_audio_)
dest->Zero();
- } else {
- // Copy data from the shared memory into the caller's AudioBus.
+ else
output_bus_->CopyTo(dest);
-
- // Zero out any unfilled frames in the destination bus.
- dest->ZeroFramesPartial(frames, dest->frames() - frames);
- }
-
- // Zero out the entire output buffer to avoid stuttering/repeating-buffers
- // in the anomalous case if the renderer is unable to keep up with real-time.
- output_bus_->Zero();
-
- // Store unknown length of data into buffer, in case renderer does not store
- // the length itself. It also helps in decision if we need to yield.
- media::SetUnknownDataSize(shared_memory_, packet_size_);
-
- // Return the actual number of frames read.
- return frames;
}
void AudioSyncReader::Close() {
- if (socket_) {
- socket_->Close();
- }
+ socket_->Close();
}
bool AudioSyncReader::Init() {
@@ -157,9 +112,7 @@ bool AudioSyncReader::PrepareForeignSocketHandle(
::DuplicateHandle(GetCurrentProcess(), foreign_socket_->handle(),
process_handle, foreign_handle,
0, FALSE, DUPLICATE_SAME_ACCESS);
- if (*foreign_handle != 0)
- return true;
- return false;
+ return (*foreign_handle != 0);
}
#else
bool AudioSyncReader::PrepareForeignSocketHandle(
@@ -167,34 +120,59 @@ bool AudioSyncReader::PrepareForeignSocketHandle(
base::FileDescriptor* foreign_handle) {
foreign_handle->fd = foreign_socket_->handle();
foreign_handle->auto_close = false;
- if (foreign_handle->fd != -1)
- return true;
- return false;
+ return (foreign_handle->fd != -1);
}
#endif
-void AudioSyncReader::WaitTillDataReady() {
- base::TimeTicks start = base::TimeTicks::Now();
- const base::TimeDelta kMaxWait = base::TimeDelta::FromMilliseconds(20);
-#if defined(OS_WIN)
- // Sleep(0) on Windows lets the other threads run.
- const base::TimeDelta kSleep = base::TimeDelta::FromMilliseconds(0);
-#else
- // We want to sleep for a bit here, as otherwise a backgrounded renderer won't
- // get enough cpu to send the data and the high priority thread in the browser
- // will use up a core causing even more skips.
- const base::TimeDelta kSleep = base::TimeDelta::FromMilliseconds(2);
-#endif
- base::TimeDelta time_since_start;
- do {
- base::PlatformThread::Sleep(kSleep);
- time_since_start = base::TimeTicks::Now() - start;
- } while (!DataReady() && time_since_start < kMaxWait);
- UMA_HISTOGRAM_CUSTOM_TIMES("Media.AudioOutputControllerDataNotReady",
- time_since_start,
- base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMilliseconds(1000),
- 50);
+bool AudioSyncReader::WaitUntilDataIsReady() {
+ base::TimeDelta timeout = maximum_wait_time_;
+ const base::TimeTicks start_time = base::TimeTicks::Now();
+ const base::TimeTicks finish_time = start_time + timeout;
+
+ // Check if data is ready and if not, wait a reasonable amount of time for it.
+ //
+ // Data readiness is achieved via parallel counters, one on the renderer side
+ // and one here. Every time a buffer is requested via UpdatePendingBytes(),
+ // |buffer_index_| is incremented. Subsequently every time the renderer has a
+ // buffer ready it increments its counter and sends the counter value over the
+ // SyncSocket. Data is ready when |buffer_index_| matches the counter value
+ // received from the renderer.
+ //
+ // The counter values may temporarily become out of sync if the renderer is
+ // unable to deliver audio fast enough. It's assumed that the renderer will
+ // catch up at some point, which means discarding counter values read from the
+ // SyncSocket which don't match our current buffer index.
+ size_t bytes_received = 0;
+ uint32 renderer_buffer_index = 0;
+ while (timeout.InMicroseconds() > 0) {
+ bytes_received = socket_->ReceiveWithTimeout(
+ &renderer_buffer_index, sizeof(renderer_buffer_index), timeout);
+ if (!bytes_received)
+ break;
+
+ DCHECK_EQ(bytes_received, sizeof(renderer_buffer_index));
+ if (renderer_buffer_index == buffer_index_)
+ break;
+
+ // Reduce the timeout value as receives succeed, but aren't the right index.
+ timeout = finish_time - base::TimeTicks::Now();
+ }
+
+ // Receive timed out or another error occurred. Receive can timeout if the
+ // renderer is unable to deliver audio data within the allotted time.
+ if (!bytes_received || renderer_buffer_index != buffer_index_) {
+ DVLOG(2) << "AudioSyncReader::WaitUntilDataIsReady() timed out.";
+
+ base::TimeDelta time_since_start = base::TimeTicks::Now() - start_time;
+ UMA_HISTOGRAM_CUSTOM_TIMES("Media.AudioOutputControllerDataNotReady",
+ time_since_start,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMilliseconds(1000),
+ 50);
+ return false;
+ }
+
+ return true;
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_sync_reader.h b/chromium/content/browser/renderer_host/media/audio_sync_reader.h
index fdfbf81a601..f3a2833b14e 100644
--- a/chromium/content/browser/renderer_host/media/audio_sync_reader.h
+++ b/chromium/content/browser/renderer_host/media/audio_sync_reader.h
@@ -33,9 +33,8 @@ class AudioSyncReader : public media::AudioOutputController::SyncReader {
// media::AudioOutputController::SyncReader implementations.
virtual void UpdatePendingBytes(uint32 bytes) OVERRIDE;
- virtual int Read(bool block,
- const media::AudioBus* source,
- media::AudioBus* dest) OVERRIDE;
+ virtual void Read(const media::AudioBus* source,
+ media::AudioBus* dest) OVERRIDE;
virtual void Close() OVERRIDE;
bool Init();
@@ -47,20 +46,18 @@ class AudioSyncReader : public media::AudioOutputController::SyncReader {
#endif
private:
- // Indicates whether the renderer has data available for reading.
- bool DataReady();
+ // Blocks until data is ready for reading or a timeout expires. Returns false
+ // if an error or timeout occurs.
+ bool WaitUntilDataIsReady();
- // Blocks until DataReady() is true or a timeout expires.
- void WaitTillDataReady();
-
- base::SharedMemory* shared_memory_;
+ const base::SharedMemory* const shared_memory_;
// Number of input channels for synchronized I/O.
- int input_channels_;
+ const int input_channels_;
// Mutes all incoming samples. This is used to prevent audible sound
// during automated testing.
- bool mute_audio_;
+ const bool mute_audio_;
// Socket for transmitting audio data.
scoped_ptr<base::CancelableSyncSocket> socket_;
@@ -76,13 +73,21 @@ class AudioSyncReader : public media::AudioOutputController::SyncReader {
scoped_ptr<media::AudioBus> input_bus_;
// Maximum amount of audio data which can be transferred in one Read() call.
- int packet_size_;
+ const int packet_size_;
// Track the number of times the renderer missed its real-time deadline and
// report a UMA stat during destruction.
size_t renderer_callback_count_;
size_t renderer_missed_callback_count_;
+ // The maximum amount of time to wait for data from the renderer. Calculated
+ // from the parameters given at construction.
+ const base::TimeDelta maximum_wait_time_;
+
+ // The index of the audio buffer we're expecting to be sent from the renderer;
+ // used to block with timeout for audio data.
+ uint32 buffer_index_;
+
DISALLOW_COPY_AND_ASSIGN(AudioSyncReader);
};
diff --git a/chromium/content/browser/renderer_host/media/desktop_capture_device.cc b/chromium/content/browser/renderer_host/media/desktop_capture_device.cc
index 16e69bf8ad0..e82b96fdb0b 100644
--- a/chromium/content/browser/renderer_host/media/desktop_capture_device.cc
+++ b/chromium/content/browser/renderer_host/media/desktop_capture_device.cc
@@ -12,11 +12,14 @@
#include "base/synchronization/lock.h"
#include "base/threading/sequenced_worker_pool.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/common/desktop_media_id.h"
+#include "content/public/browser/desktop_media_id.h"
#include "media/base/video_util.h"
#include "third_party/libyuv/include/libyuv/scale_argb.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_and_cursor_composer.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
@@ -24,7 +27,11 @@ namespace content {
namespace {
-const int kBytesPerPixel = 4;
+// Maximum CPU time percentage of a single core that can be consumed for desktop
+// capturing. This means that on systems where screen scraping is slow we may
+// need to capture at frame rate lower than requested. This is necessary to keep
+// UI responsive.
+const int kMaximumCpuConsumptionPercentage = 50;
webrtc::DesktopRect ComputeLetterboxRect(
const webrtc::DesktopSize& max_size,
@@ -46,11 +53,9 @@ class DesktopCaptureDevice::Core
scoped_ptr<webrtc::DesktopCapturer> capturer);
// Implementation of VideoCaptureDevice methods.
- void Allocate(const media::VideoCaptureCapability& capture_format,
- EventHandler* event_handler);
- void Start();
- void Stop();
- void DeAllocate();
+ void AllocateAndStart(const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client);
+ void StopAndDeAllocate();
private:
friend class base::RefCountedThreadSafe<Core>;
@@ -62,23 +67,22 @@ class DesktopCaptureDevice::Core
// Helper methods that run on the |task_runner_|. Posted from the
// corresponding public methods.
- void DoAllocate(const media::VideoCaptureCapability& capture_format);
- void DoStart();
- void DoStop();
- void DoDeAllocate();
+ void DoAllocateAndStart(const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client);
+ void DoStopAndDeAllocate();
// Chooses new output properties based on the supplied source size and the
// properties requested to Allocate(), and dispatches OnFrameInfo[Changed]
// notifications.
void RefreshCaptureFormat(const webrtc::DesktopSize& frame_size);
- // Helper to schedule capture tasks.
- void ScheduleCaptureTimer();
-
// Method that is scheduled on |task_runner_| to be called on regular interval
// to capture a frame.
void OnCaptureTimer();
+ // Captures a frame and schedules timer for the next one.
+ void CaptureFrameAndScheduleNext();
+
// Captures a single frame.
void DoCapture();
@@ -88,17 +92,15 @@ class DesktopCaptureDevice::Core
// The underlying DesktopCapturer instance used to capture frames.
scoped_ptr<webrtc::DesktopCapturer> desktop_capturer_;
- // |event_handler_lock_| must be locked whenever |event_handler_| is used.
- // It's necessary because DeAllocate() needs to reset it on the calling thread
- // to ensure that the event handler is not called once DeAllocate() returns.
- base::Lock event_handler_lock_;
- EventHandler* event_handler_;
+ // The device client which proxies device events to the controller. Accessed
+ // on the task_runner_ thread.
+ scoped_ptr<Client> client_;
// Requested video capture format (width, height, frame rate, etc).
- media::VideoCaptureCapability requested_format_;
+ media::VideoCaptureParams requested_params_;
// Actual video capture format being generated.
- media::VideoCaptureCapability capture_format_;
+ media::VideoCaptureFormat capture_format_;
// Size of frame most recently captured from the source.
webrtc::DesktopSize previous_frame_size_;
@@ -112,10 +114,6 @@ class DesktopCaptureDevice::Core
// and/or letterboxed.
webrtc::DesktopRect output_rect_;
- // True between DoStart() and DoStop(). Can't just check |event_handler_|
- // because |event_handler_| is used on the caller thread.
- bool started_;
-
// True when we have delayed OnCaptureTimer() task posted on
// |task_runner_|.
bool capture_task_posted_;
@@ -131,48 +129,27 @@ DesktopCaptureDevice::Core::Core(
scoped_ptr<webrtc::DesktopCapturer> capturer)
: task_runner_(task_runner),
desktop_capturer_(capturer.Pass()),
- event_handler_(NULL),
- started_(false),
capture_task_posted_(false),
- capture_in_progress_(false) {
-}
+ capture_in_progress_(false) {}
DesktopCaptureDevice::Core::~Core() {
}
-void DesktopCaptureDevice::Core::Allocate(
- const media::VideoCaptureCapability& capture_format,
- EventHandler* event_handler) {
- DCHECK_GT(capture_format.width, 0);
- DCHECK_GT(capture_format.height, 0);
- DCHECK_GT(capture_format.frame_rate, 0);
-
- {
- base::AutoLock auto_lock(event_handler_lock_);
- event_handler_ = event_handler;
- }
+void DesktopCaptureDevice::Core::AllocateAndStart(
+ const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client) {
+ DCHECK_GT(params.requested_format.frame_size.GetArea(), 0);
+ DCHECK_GT(params.requested_format.frame_rate, 0);
task_runner_->PostTask(
FROM_HERE,
- base::Bind(&Core::DoAllocate, this, capture_format));
+ base::Bind(
+ &Core::DoAllocateAndStart, this, params, base::Passed(&client)));
}
-void DesktopCaptureDevice::Core::Start() {
- task_runner_->PostTask(
- FROM_HERE, base::Bind(&Core::DoStart, this));
-}
-
-void DesktopCaptureDevice::Core::Stop() {
- task_runner_->PostTask(
- FROM_HERE, base::Bind(&Core::DoStop, this));
-}
-
-void DesktopCaptureDevice::Core::DeAllocate() {
- {
- base::AutoLock auto_lock(event_handler_lock_);
- event_handler_ = NULL;
- }
- task_runner_->PostTask(FROM_HERE, base::Bind(&Core::DoDeAllocate, this));
+void DesktopCaptureDevice::Core::StopAndDeAllocate() {
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&Core::DoStopAndDeAllocate, this));
}
webrtc::SharedMemory*
@@ -189,28 +166,46 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
if (!frame) {
LOG(ERROR) << "Failed to capture a frame.";
- event_handler_->OnError();
+ client_->OnError();
return;
}
+ if (!client_)
+ return;
+
scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
// Handle initial frame size and size changes.
RefreshCaptureFormat(frame->size());
- if (!started_)
- return;
-
- webrtc::DesktopSize output_size(capture_format_.width,
- capture_format_.height);
+ webrtc::DesktopSize output_size(capture_format_.frame_size.width(),
+ capture_format_.frame_size.height());
size_t output_bytes = output_size.width() * output_size.height() *
webrtc::DesktopFrame::kBytesPerPixel;
const uint8_t* output_data = NULL;
+ scoped_ptr<uint8_t[]> flipped_frame_buffer;
if (frame->size().equals(output_size)) {
// If the captured frame matches the output size, we can return the pixel
// data directly, without scaling.
output_data = frame->data();
+
+ // If the |frame| generated by the screen capturer is inverted then we need
+ // to flip |frame|.
+ // This happens only on a specific platform. Refer to crbug.com/306876.
+ if (frame->stride() < 0) {
+ int height = frame->size().height();
+ int bytes_per_row =
+ frame->size().width() * webrtc::DesktopFrame::kBytesPerPixel;
+ flipped_frame_buffer.reset(new uint8_t[output_bytes]);
+ uint8_t* dest = flipped_frame_buffer.get();
+ for (int row = 0; row < height; ++row) {
+ memcpy(dest, output_data, bytes_per_row);
+ dest += bytes_per_row;
+ output_data += frame->stride();
+ }
+ output_data = flipped_frame_buffer.get();
+ }
} else {
// Otherwise we need to down-scale and/or letterbox to the target format.
@@ -236,61 +231,36 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
output_data = output_frame_->data();
}
- base::AutoLock auto_lock(event_handler_lock_);
- if (event_handler_) {
- event_handler_->OnIncomingCapturedFrame(output_data, output_bytes,
- base::Time::Now(), 0, false, false);
- }
+ client_->OnIncomingCapturedFrame(output_data, output_bytes, base::Time::Now(),
+ 0, capture_format_);
}
-void DesktopCaptureDevice::Core::DoAllocate(
- const media::VideoCaptureCapability& capture_format) {
+void DesktopCaptureDevice::Core::DoAllocateAndStart(
+ const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
DCHECK(desktop_capturer_);
+ DCHECK(client.get());
+ DCHECK(!client_.get());
- requested_format_ = capture_format;
+ client_ = client.Pass();
+ requested_params_ = params;
- // Store requested frame rate and calculate expected delay.
- capture_format_.frame_rate = requested_format_.frame_rate;
- capture_format_.expected_capture_delay =
- base::Time::kMillisecondsPerSecond / requested_format_.frame_rate;
-
- // Support dynamic changes in resolution only if requester also does.
- if (requested_format_.frame_size_type ==
- media::VariableResolutionVideoCaptureDevice) {
- capture_format_.frame_size_type =
- media::VariableResolutionVideoCaptureDevice;
- }
+ capture_format_ = requested_params_.requested_format;
// This capturer always outputs ARGB, non-interlaced.
- capture_format_.color = media::PIXEL_FORMAT_ARGB;
- capture_format_.interlaced = false;
+ capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB;
desktop_capturer_->Start(this);
- // Capture first frame, so that we can call OnFrameInfo() callback.
- DoCapture();
-}
-
-void DesktopCaptureDevice::Core::DoStart() {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- started_ = true;
- if (!capture_task_posted_) {
- ScheduleCaptureTimer();
- DoCapture();
- }
+ CaptureFrameAndScheduleNext();
}
-void DesktopCaptureDevice::Core::DoStop() {
+void DesktopCaptureDevice::Core::DoStopAndDeAllocate() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
- started_ = false;
+ client_.reset();
output_frame_.reset();
previous_frame_size_.set(0, 0);
-}
-
-void DesktopCaptureDevice::Core::DoDeAllocate() {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- DoStop();
desktop_capturer_.reset();
}
@@ -304,63 +274,65 @@ void DesktopCaptureDevice::Core::RefreshCaptureFormat(
output_frame_.reset();
if (previous_frame_size_.is_empty() ||
- requested_format_.frame_size_type ==
- media::VariableResolutionVideoCaptureDevice) {
+ requested_params_.allow_resolution_change) {
// If this is the first frame, or the receiver supports variable resolution
// then determine the output size by treating the requested width & height
// as maxima.
- if (frame_size.width() > requested_format_.width ||
- frame_size.height() > requested_format_.height) {
+ if (frame_size.width() >
+ requested_params_.requested_format.frame_size.width() ||
+ frame_size.height() >
+ requested_params_.requested_format.frame_size.height()) {
output_rect_ = ComputeLetterboxRect(
- webrtc::DesktopSize(requested_format_.width,
- requested_format_.height),
+ webrtc::DesktopSize(
+ requested_params_.requested_format.frame_size.width(),
+ requested_params_.requested_format.frame_size.height()),
frame_size);
output_rect_.Translate(-output_rect_.left(), -output_rect_.top());
} else {
output_rect_ = webrtc::DesktopRect::MakeSize(frame_size);
}
- capture_format_.width = output_rect_.width();
- capture_format_.height = output_rect_.height();
-
- {
- base::AutoLock auto_lock(event_handler_lock_);
- if (event_handler_) {
- if (previous_frame_size_.is_empty()) {
- event_handler_->OnFrameInfo(capture_format_);
- } else {
- event_handler_->OnFrameInfoChanged(capture_format_);
- }
- }
- }
+ capture_format_.frame_size.SetSize(output_rect_.width(),
+ output_rect_.height());
} else {
// Otherwise the output frame size cannot change, so just scale and
// letterbox.
output_rect_ = ComputeLetterboxRect(
- webrtc::DesktopSize(capture_format_.width, capture_format_.height),
+ webrtc::DesktopSize(capture_format_.frame_size.width(),
+ capture_format_.frame_size.height()),
frame_size);
}
previous_frame_size_ = frame_size;
}
-void DesktopCaptureDevice::Core::ScheduleCaptureTimer() {
- DCHECK(!capture_task_posted_);
- capture_task_posted_ = true;
- task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&Core::OnCaptureTimer, this),
- base::TimeDelta::FromSeconds(1) / capture_format_.frame_rate);
-}
-
void DesktopCaptureDevice::Core::OnCaptureTimer() {
DCHECK(capture_task_posted_);
capture_task_posted_ = false;
- if (!started_)
+ if (!client_)
return;
- // Schedule a task for the next frame.
- ScheduleCaptureTimer();
+ CaptureFrameAndScheduleNext();
+}
+
+void DesktopCaptureDevice::Core::CaptureFrameAndScheduleNext() {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(!capture_task_posted_);
+
+ base::TimeTicks started_time = base::TimeTicks::Now();
DoCapture();
+ base::TimeDelta last_capture_duration = base::TimeTicks::Now() - started_time;
+
+ // Limit frame-rate to reduce CPU consumption.
+ base::TimeDelta capture_period = std::max(
+ (last_capture_duration * 100) / kMaximumCpuConsumptionPercentage,
+ base::TimeDelta::FromSeconds(1) / capture_format_.frame_rate);
+
+ // Schedule a task for the next frame.
+ capture_task_posted_ = true;
+ task_runner_->PostDelayedTask(
+ FROM_HERE, base::Bind(&Core::OnCaptureTimer, this),
+ capture_period - last_capture_duration);
}
void DesktopCaptureDevice::Core::DoCapture() {
@@ -384,78 +356,65 @@ scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
blocking_pool->GetSequencedTaskRunner(
blocking_pool->GetSequenceToken());
+ webrtc::DesktopCaptureOptions options =
+ webrtc::DesktopCaptureOptions::CreateDefault();
+ // Leave desktop effects enabled during WebRTC captures.
+ options.set_disable_effects(false);
+
+ scoped_ptr<webrtc::DesktopCapturer> capturer;
+
switch (source.type) {
case DesktopMediaID::TYPE_SCREEN: {
- scoped_ptr<webrtc::DesktopCapturer> capturer;
-
-#if defined(OS_CHROMEOS) && defined(USE_X11)
- // ScreenCapturerX11 polls by default, due to poor driver support for
- // DAMAGE. ChromeOS' drivers [can be patched to] support DAMAGE properly,
- // so use it.
- capturer.reset(webrtc::ScreenCapturer::CreateWithXDamage(true));
-#elif defined(OS_WIN)
- // ScreenCapturerWin disables Aero by default. We don't want it disabled
- // for WebRTC screen capture, though.
- capturer.reset(
- webrtc::ScreenCapturer::CreateWithDisableAero(false));
-#else
- capturer.reset(webrtc::ScreenCapturer::Create());
-#endif
-
- return scoped_ptr<media::VideoCaptureDevice>(new DesktopCaptureDevice(
- task_runner, capturer.Pass()));
+ scoped_ptr<webrtc::DesktopCapturer> screen_capturer;
+ screen_capturer.reset(webrtc::ScreenCapturer::Create(options));
+ if (screen_capturer) {
+ capturer.reset(new webrtc::DesktopAndCursorComposer(
+ screen_capturer.release(),
+ webrtc::MouseCursorMonitor::CreateForScreen(options)));
+ }
+ break;
}
case DesktopMediaID::TYPE_WINDOW: {
- scoped_ptr<webrtc::WindowCapturer> capturer(
- webrtc::WindowCapturer::Create());
-
- if (!capturer || !capturer->SelectWindow(source.id)) {
- return scoped_ptr<media::VideoCaptureDevice>();
+ scoped_ptr<webrtc::WindowCapturer> window_capturer(
+ webrtc::WindowCapturer::Create(options));
+ if (window_capturer && window_capturer->SelectWindow(source.id)) {
+ capturer.reset(new webrtc::DesktopAndCursorComposer(
+ window_capturer.release(),
+ webrtc::MouseCursorMonitor::CreateForWindow(options, source.id)));
}
-
- return scoped_ptr<media::VideoCaptureDevice>(new DesktopCaptureDevice(
- task_runner, capturer.PassAs<webrtc::DesktopCapturer>()));
+ break;
}
default: {
NOTREACHED();
- return scoped_ptr<media::VideoCaptureDevice>();
}
}
+
+ scoped_ptr<media::VideoCaptureDevice> result;
+ if (capturer)
+ result.reset(new DesktopCaptureDevice(task_runner, capturer.Pass()));
+
+ return result.Pass();
}
DesktopCaptureDevice::DesktopCaptureDevice(
scoped_refptr<base::SequencedTaskRunner> task_runner,
scoped_ptr<webrtc::DesktopCapturer> capturer)
- : core_(new Core(task_runner, capturer.Pass())),
- name_("", "") {
-}
+ : core_(new Core(task_runner, capturer.Pass())) {}
DesktopCaptureDevice::~DesktopCaptureDevice() {
- DeAllocate();
-}
-
-void DesktopCaptureDevice::Allocate(
- const media::VideoCaptureCapability& capture_format,
- EventHandler* event_handler) {
- core_->Allocate(capture_format, event_handler);
-}
-
-void DesktopCaptureDevice::Start() {
- core_->Start();
-}
-
-void DesktopCaptureDevice::Stop() {
- core_->Stop();
+ StopAndDeAllocate();
}
-void DesktopCaptureDevice::DeAllocate() {
- core_->DeAllocate();
+void DesktopCaptureDevice::AllocateAndStart(
+ const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client) {
+ core_->AllocateAndStart(params, client.Pass());
}
-const media::VideoCaptureDevice::Name& DesktopCaptureDevice::device_name() {
- return name_;
+void DesktopCaptureDevice::StopAndDeAllocate() {
+ core_->StopAndDeAllocate();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/desktop_capture_device.h b/chromium/content/browser/renderer_host/media/desktop_capture_device.h
index 8f60c7de1b8..b418a298d63 100644
--- a/chromium/content/browser/renderer_host/media/desktop_capture_device.h
+++ b/chromium/content/browser/renderer_host/media/desktop_capture_device.h
@@ -25,7 +25,7 @@ struct DesktopMediaID;
// DesktopCaptureDevice implements VideoCaptureDevice for screens and windows.
// It's essentially an adapter between webrtc::DesktopCapturer and
// VideoCaptureDevice.
-class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice1 {
+class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice {
public:
// Creates capturer for the specified |source| and then creates
// DesktopCaptureDevice for it. May return NULL in case of a failure (e.g. if
@@ -38,17 +38,13 @@ class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice1 {
virtual ~DesktopCaptureDevice();
// VideoCaptureDevice interface.
- virtual void Allocate(const media::VideoCaptureCapability& capture_format,
- EventHandler* observer) OVERRIDE;
- virtual void Start() OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void DeAllocate() OVERRIDE;
- virtual const Name& device_name() OVERRIDE;
+ virtual void AllocateAndStart(const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client) OVERRIDE;
+ virtual void StopAndDeAllocate() OVERRIDE;
private:
class Core;
scoped_refptr<Core> core_;
- Name name_;
DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDevice);
};
diff --git a/chromium/content/browser/renderer_host/media/desktop_capture_device_aura.cc b/chromium/content/browser/renderer_host/media/desktop_capture_device_aura.cc
new file mode 100644
index 00000000000..a36d26b8b5f
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/desktop_capture_device_aura.cc
@@ -0,0 +1,442 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/media/desktop_capture_device_aura.h"
+
+#include "base/logging.h"
+#include "base/timer/timer.h"
+#include "cc/output/copy_output_request.h"
+#include "cc/output/copy_output_result.h"
+#include "content/browser/aura/image_transport_factory.h"
+#include "content/browser/renderer_host/media/video_capture_device_impl.h"
+#include "content/common/gpu/client/gl_helper.h"
+#include "content/public/browser/browser_thread.h"
+#include "media/base/video_util.h"
+#include "media/video/capture/video_capture_types.h"
+#include "skia/ext/image_operations.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/aura/env.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
+#include "ui/base/cursor/cursors_aura.h"
+#include "ui/compositor/compositor.h"
+#include "ui/compositor/dip_util.h"
+#include "ui/compositor/layer.h"
+#include "ui/gfx/screen.h"
+
+namespace content {
+
+namespace {
+
+int clip_byte(int x) {
+ return std::max(0, std::min(x, 255));
+}
+
+int alpha_blend(int alpha, int src, int dst) {
+ return (src * alpha + dst * (255 - alpha)) / 255;
+}
+
+// Helper function to composite a cursor bitmap on a YUV420 video frame.
+void RenderCursorOnVideoFrame(
+ const scoped_refptr<media::VideoFrame>& target,
+ const SkBitmap& cursor_bitmap,
+ const gfx::Point& cursor_position) {
+ DCHECK(target);
+ DCHECK(!cursor_bitmap.isNull());
+
+ gfx::Rect rect = gfx::IntersectRects(
+ gfx::Rect(cursor_bitmap.width(), cursor_bitmap.height()) +
+ gfx::Vector2d(cursor_position.x(), cursor_position.y()),
+ target->visible_rect());
+
+ cursor_bitmap.lockPixels();
+ for (int y = rect.y(); y < rect.bottom(); ++y) {
+ int cursor_y = y - cursor_position.y();
+ uint8* yplane = target->data(media::VideoFrame::kYPlane) +
+ y * target->row_bytes(media::VideoFrame::kYPlane);
+ uint8* uplane = target->data(media::VideoFrame::kUPlane) +
+ (y / 2) * target->row_bytes(media::VideoFrame::kUPlane);
+ uint8* vplane = target->data(media::VideoFrame::kVPlane) +
+ (y / 2) * target->row_bytes(media::VideoFrame::kVPlane);
+ for (int x = rect.x(); x < rect.right(); ++x) {
+ int cursor_x = x - cursor_position.x();
+ SkColor color = cursor_bitmap.getColor(cursor_x, cursor_y);
+ int alpha = SkColorGetA(color);
+ int color_r = SkColorGetR(color);
+ int color_g = SkColorGetG(color);
+ int color_b = SkColorGetB(color);
+ int color_y = clip_byte(((color_r * 66 + color_g * 129 + color_b * 25 +
+ 128) >> 8) + 16);
+ yplane[x] = alpha_blend(alpha, color_y, yplane[x]);
+
+ // Only sample U and V at even coordinates.
+ if ((x % 2 == 0) && (y % 2 == 0)) {
+ int color_u = clip_byte(((color_r * -38 + color_g * -74 +
+ color_b * 112 + 128) >> 8) + 128);
+ int color_v = clip_byte(((color_r * 112 + color_g * -94 +
+ color_b * -18 + 128) >> 8) + 128);
+ uplane[x / 2] = alpha_blend(alpha, color_u, uplane[x / 2]);
+ vplane[x / 2] = alpha_blend(alpha, color_v, vplane[x / 2]);
+ }
+ }
+ }
+ cursor_bitmap.unlockPixels();
+}
+
+class DesktopVideoCaptureMachine
+ : public VideoCaptureMachine,
+ public aura::WindowObserver,
+ public ui::CompositorObserver,
+ public base::SupportsWeakPtr<DesktopVideoCaptureMachine> {
+ public:
+ DesktopVideoCaptureMachine(const DesktopMediaID& source);
+ virtual ~DesktopVideoCaptureMachine();
+
+ // VideoCaptureFrameSource overrides.
+ virtual bool Start(
+ const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) OVERRIDE;
+ virtual void Stop() OVERRIDE;
+
+ // Implements aura::WindowObserver.
+ virtual void OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) OVERRIDE;
+ virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
+
+ // Implements ui::CompositorObserver.
+ virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE {}
+ virtual void OnCompositingStarted(ui::Compositor* compositor,
+ base::TimeTicks start_time) OVERRIDE {}
+ virtual void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE;
+ virtual void OnCompositingAborted(ui::Compositor* compositor) OVERRIDE {}
+ virtual void OnCompositingLockStateChanged(
+ ui::Compositor* compositor) OVERRIDE {}
+ virtual void OnUpdateVSyncParameters(ui::Compositor* compositor,
+ base::TimeTicks timebase,
+ base::TimeDelta interval) OVERRIDE {}
+
+ private:
+ // Captures a frame.
+ // |dirty| is false for timer polls and true for compositor updates.
+ void Capture(bool dirty);
+
+ // Update capture size. Must be called on the UI thread.
+ void UpdateCaptureSize();
+
+ // Response callback for cc::Layer::RequestCopyOfOutput().
+ void DidCopyOutput(
+ scoped_refptr<media::VideoFrame> video_frame,
+ base::Time start_time,
+ const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb,
+ scoped_ptr<cc::CopyOutputResult> result);
+
+ // Helper function to update cursor state.
+ // |region_in_frame| defines the desktop bound in the captured frame.
+ // Returns the current cursor position in captured frame.
+ gfx::Point UpdateCursorState(const gfx::Rect& region_in_frame);
+
+ // Clears cursor state.
+ void ClearCursorState();
+
+ // The window associated with the desktop.
+ aura::Window* desktop_window_;
+
+ // The layer associated with the desktop.
+ ui::Layer* desktop_layer_;
+
+ // The timer that kicks off period captures.
+ base::Timer timer_;
+
+ // The id of the window being captured.
+ DesktopMediaID window_id_;
+
+ // Makes all the decisions about which frames to copy, and how.
+ scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_;
+
+ // YUV readback pipeline.
+ scoped_ptr<content::ReadbackYUVInterface> yuv_readback_pipeline_;
+
+ // Cursor state.
+ ui::Cursor last_cursor_;
+ gfx::Point cursor_hot_point_;
+ SkBitmap scaled_cursor_bitmap_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopVideoCaptureMachine);
+};
+
+DesktopVideoCaptureMachine::DesktopVideoCaptureMachine(
+ const DesktopMediaID& source)
+ : desktop_window_(NULL),
+ desktop_layer_(NULL),
+ timer_(true, true),
+ window_id_(source) {}
+
+DesktopVideoCaptureMachine::~DesktopVideoCaptureMachine() {}
+
+bool DesktopVideoCaptureMachine::Start(
+ const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ desktop_window_ = content::DesktopMediaID::GetAuraWindowById(window_id_);
+ if (!desktop_window_)
+ return false;
+
+ // If the desktop layer is already destroyed then return failure.
+ desktop_layer_ = desktop_window_->layer();
+ if (!desktop_layer_)
+ return false;
+
+ DCHECK(oracle_proxy.get());
+ oracle_proxy_ = oracle_proxy;
+
+ // Update capture size.
+ UpdateCaptureSize();
+
+ // Start observing window events.
+ desktop_window_->AddObserver(this);
+
+ // Start observing compositor updates.
+ ui::Compositor* compositor = desktop_layer_->GetCompositor();
+ if (!compositor)
+ return false;
+
+ compositor->AddObserver(this);
+
+ // Starts timer.
+ timer_.Start(FROM_HERE, oracle_proxy_->capture_period(),
+ base::Bind(&DesktopVideoCaptureMachine::Capture, AsWeakPtr(),
+ false));
+
+ started_ = true;
+ return true;
+}
+
+void DesktopVideoCaptureMachine::Stop() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // Stop observing window events.
+ if (desktop_window_)
+ desktop_window_->RemoveObserver(this);
+
+ // Stop observing compositor updates.
+ if (desktop_layer_) {
+ ui::Compositor* compositor = desktop_layer_->GetCompositor();
+ if (compositor)
+ compositor->RemoveObserver(this);
+ }
+
+ // Stop timer.
+ timer_.Stop();
+
+ started_ = false;
+}
+
+void DesktopVideoCaptureMachine::UpdateCaptureSize() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (oracle_proxy_ && desktop_layer_) {
+ oracle_proxy_->UpdateCaptureSize(ui::ConvertSizeToPixel(
+ desktop_layer_, desktop_layer_->bounds().size()));
+ }
+ ClearCursorState();
+}
+
+void DesktopVideoCaptureMachine::Capture(bool dirty) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // Do not capture if the desktop layer is already destroyed.
+ if (!desktop_layer_)
+ return;
+
+ scoped_refptr<media::VideoFrame> frame;
+ ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
+
+ const base::Time start_time = base::Time::Now();
+ const VideoCaptureOracle::Event event =
+ dirty ? VideoCaptureOracle::kCompositorUpdate
+ : VideoCaptureOracle::kTimerPoll;
+ if (oracle_proxy_->ObserveEventAndDecideCapture(
+ event, start_time, &frame, &capture_frame_cb)) {
+ scoped_ptr<cc::CopyOutputRequest> request =
+ cc::CopyOutputRequest::CreateRequest(
+ base::Bind(&DesktopVideoCaptureMachine::DidCopyOutput,
+ AsWeakPtr(), frame, start_time, capture_frame_cb));
+ gfx::Rect window_rect =
+ ui::ConvertRectToPixel(desktop_window_->layer(),
+ gfx::Rect(desktop_window_->bounds().width(),
+ desktop_window_->bounds().height()));
+ request->set_area(window_rect);
+ desktop_layer_->RequestCopyOfOutput(request.Pass());
+ }
+}
+
+void CopyOutputFinishedForVideo(
+ base::Time start_time,
+ const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb,
+ const scoped_refptr<media::VideoFrame>& target,
+ const SkBitmap& cursor_bitmap,
+ const gfx::Point& cursor_position,
+ scoped_ptr<cc::SingleReleaseCallback> release_callback,
+ bool result) {
+ if (!cursor_bitmap.isNull())
+ RenderCursorOnVideoFrame(target, cursor_bitmap, cursor_position);
+ release_callback->Run(0, false);
+ capture_frame_cb.Run(start_time, result);
+}
+
+void DesktopVideoCaptureMachine::DidCopyOutput(
+ scoped_refptr<media::VideoFrame> video_frame,
+ base::Time start_time,
+ const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb,
+ scoped_ptr<cc::CopyOutputResult> result) {
+ if (result->IsEmpty() || result->size().IsEmpty())
+ return;
+
+ // Compute the dest size we want after the letterboxing resize. Make the
+ // coordinates and sizes even because we letterbox in YUV space
+ // (see CopyRGBToVideoFrame). They need to be even for the UV samples to
+ // line up correctly.
+ // The video frame's coded_size() and the result's size() are both physical
+ // pixels.
+ gfx::Rect region_in_frame =
+ media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()),
+ result->size());
+ region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
+ region_in_frame.y() & ~1,
+ region_in_frame.width() & ~1,
+ region_in_frame.height() & ~1);
+ if (region_in_frame.IsEmpty())
+ return;
+
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ GLHelper* gl_helper = factory->GetGLHelper();
+ if (!gl_helper)
+ return;
+
+ cc::TextureMailbox texture_mailbox;
+ scoped_ptr<cc::SingleReleaseCallback> release_callback;
+ result->TakeTexture(&texture_mailbox, &release_callback);
+ DCHECK(texture_mailbox.IsTexture());
+ if (!texture_mailbox.IsTexture())
+ return;
+
+ gfx::Rect result_rect(result->size());
+ if (!yuv_readback_pipeline_ ||
+ yuv_readback_pipeline_->scaler()->SrcSize() != result_rect.size() ||
+ yuv_readback_pipeline_->scaler()->SrcSubrect() != result_rect ||
+ yuv_readback_pipeline_->scaler()->DstSize() != region_in_frame.size()) {
+ yuv_readback_pipeline_.reset(
+ gl_helper->CreateReadbackPipelineYUV(GLHelper::SCALER_QUALITY_FAST,
+ result_rect.size(),
+ result_rect,
+ video_frame->coded_size(),
+ region_in_frame,
+ true,
+ true));
+ }
+
+ gfx::Point cursor_position_in_frame = UpdateCursorState(region_in_frame);
+ yuv_readback_pipeline_->ReadbackYUV(
+ texture_mailbox.name(), texture_mailbox.sync_point(), video_frame.get(),
+ base::Bind(&CopyOutputFinishedForVideo, start_time, capture_frame_cb,
+ video_frame, scaled_cursor_bitmap_, cursor_position_in_frame,
+ base::Passed(&release_callback)));
+}
+
+gfx::Point DesktopVideoCaptureMachine::UpdateCursorState(
+ const gfx::Rect& region_in_frame) {
+ const gfx::Rect desktop_bounds = desktop_layer_->bounds();
+ gfx::NativeCursor cursor = desktop_window_->GetDispatcher()->last_cursor();
+ if (last_cursor_ != cursor) {
+ SkBitmap cursor_bitmap;
+ if (ui::GetCursorBitmap(cursor, &cursor_bitmap, &cursor_hot_point_)) {
+ scaled_cursor_bitmap_ = skia::ImageOperations::Resize(
+ cursor_bitmap,
+ skia::ImageOperations::RESIZE_BEST,
+ cursor_bitmap.width() * region_in_frame.width() /
+ desktop_bounds.width(),
+ cursor_bitmap.height() * region_in_frame.height() /
+ desktop_bounds.height());
+ last_cursor_ = cursor;
+ } else {
+ // Clear cursor state if ui::GetCursorBitmap failed so that we do not
+ // render cursor on the captured frame.
+ ClearCursorState();
+ }
+ }
+
+ gfx::Point cursor_position = aura::Env::GetInstance()->last_mouse_location();
+ const gfx::Point hot_point_in_dip = ui::ConvertPointToDIP(
+ desktop_layer_, cursor_hot_point_);
+ cursor_position.Offset(-desktop_bounds.x() - hot_point_in_dip.x(),
+ -desktop_bounds.y() - hot_point_in_dip.y());
+ return gfx::Point(
+ region_in_frame.x() + cursor_position.x() * region_in_frame.width() /
+ desktop_bounds.width(),
+ region_in_frame.y() + cursor_position.y() * region_in_frame.height() /
+ desktop_bounds.height());
+}
+
+void DesktopVideoCaptureMachine::ClearCursorState() {
+ last_cursor_ = ui::Cursor();
+ cursor_hot_point_ = gfx::Point();
+ scaled_cursor_bitmap_.reset();
+}
+
+void DesktopVideoCaptureMachine::OnWindowBoundsChanged(
+ aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) {
+ DCHECK(desktop_window_ && window == desktop_window_);
+
+ // Post task to update capture size on UI thread.
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
+ &DesktopVideoCaptureMachine::UpdateCaptureSize, AsWeakPtr()));
+}
+
+void DesktopVideoCaptureMachine::OnWindowDestroyed(aura::Window* window) {
+ DCHECK(desktop_window_ && window == desktop_window_);
+ desktop_window_ = NULL;
+ desktop_layer_ = NULL;
+
+ // Post task to stop capture on UI thread.
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
+ &DesktopVideoCaptureMachine::Stop, AsWeakPtr()));
+}
+
+void DesktopVideoCaptureMachine::OnCompositingEnded(
+ ui::Compositor* compositor) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
+ &DesktopVideoCaptureMachine::Capture, AsWeakPtr(), true));
+}
+
+} // namespace
+
+DesktopCaptureDeviceAura::DesktopCaptureDeviceAura(
+ const DesktopMediaID& source)
+ : impl_(new VideoCaptureDeviceImpl(scoped_ptr<VideoCaptureMachine>(
+ new DesktopVideoCaptureMachine(source)))) {}
+
+DesktopCaptureDeviceAura::~DesktopCaptureDeviceAura() {
+ DVLOG(2) << "DesktopCaptureDeviceAura@" << this << " destroying.";
+}
+
+// static
+media::VideoCaptureDevice* DesktopCaptureDeviceAura::Create(
+ const DesktopMediaID& source) {
+ return new DesktopCaptureDeviceAura(source);
+}
+
+void DesktopCaptureDeviceAura::AllocateAndStart(
+ const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client) {
+ DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString();
+ impl_->AllocateAndStart(params, client.Pass());
+}
+
+void DesktopCaptureDeviceAura::StopAndDeAllocate() {
+ impl_->StopAndDeAllocate();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/desktop_capture_device_aura.h b/chromium/content/browser/renderer_host/media/desktop_capture_device_aura.h
new file mode 100644
index 00000000000..faca53b9b6e
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/desktop_capture_device_aura.h
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_AURA_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_AURA_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/desktop_media_id.h"
+#include "media/video/capture/video_capture_device.h"
+
+namespace aura {
+class Window;
+} // namespace aura
+
+namespace content {
+
+class VideoCaptureDeviceImpl;
+
+// An implementation of VideoCaptureDevice that mirrors an Aura window.
+class CONTENT_EXPORT DesktopCaptureDeviceAura
+ : public media::VideoCaptureDevice {
+ public:
+ // Creates a VideoCaptureDevice for the Aura desktop.
+ static media::VideoCaptureDevice* Create(const DesktopMediaID& source);
+
+ virtual ~DesktopCaptureDeviceAura();
+
+ // VideoCaptureDevice implementation.
+ virtual void AllocateAndStart(const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client) OVERRIDE;
+ virtual void StopAndDeAllocate() OVERRIDE;
+
+ private:
+ DesktopCaptureDeviceAura(const DesktopMediaID& source);
+
+ const scoped_ptr<class VideoCaptureDeviceImpl> impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDeviceAura);
+};
+
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_AURA_H_
diff --git a/chromium/content/browser/renderer_host/media/desktop_capture_device_aura_unittest.cc b/chromium/content/browser/renderer_host/media/desktop_capture_device_aura_unittest.cc
new file mode 100644
index 00000000000..8ad1495a70c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/desktop_capture_device_aura_unittest.cc
@@ -0,0 +1,114 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/media/desktop_capture_device_aura.h"
+
+#include "base/synchronization/waitable_event.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/public/browser/desktop_media_id.h"
+#include "media/video/capture/video_capture_types.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/client/window_tree_client.h"
+#include "ui/aura/test/aura_test_helper.h"
+#include "ui/aura/test/test_window_delegate.h"
+#include "ui/aura/window.h"
+
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::DoAll;
+using ::testing::Expectation;
+using ::testing::InvokeWithoutArgs;
+using ::testing::SaveArg;
+
+namespace content {
+namespace {
+
+const int kFrameRate = 30;
+
+class MockDeviceClient : public media::VideoCaptureDevice::Client {
+ public:
+ MOCK_METHOD2(ReserveOutputBuffer,
+ scoped_refptr<Buffer>(media::VideoFrame::Format format,
+ const gfx::Size& dimensions));
+ MOCK_METHOD0(OnError, void());
+ MOCK_METHOD5(OnIncomingCapturedFrame,
+ void(const uint8* data,
+ int length,
+ base::Time timestamp,
+ int rotation,
+ const media::VideoCaptureFormat& frame_format));
+ MOCK_METHOD5(OnIncomingCapturedBuffer,
+ void(const scoped_refptr<Buffer>& buffer,
+ media::VideoFrame::Format format,
+ const gfx::Size& dimensions,
+ base::Time timestamp,
+ int frame_rate));
+};
+
+// Test harness that sets up a minimal environment with necessary stubs.
+class DesktopCaptureDeviceAuraTest : public testing::Test {
+ public:
+ DesktopCaptureDeviceAuraTest()
+ : browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {}
+ virtual ~DesktopCaptureDeviceAuraTest() {}
+
+ protected:
+ virtual void SetUp() OVERRIDE {
+ helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
+ helper_->SetUp();
+
+ // We need a window to cover desktop area so that DesktopCaptureDeviceAura
+ // can use gfx::NativeWindow::GetWindowAtScreenPoint() to locate the
+ // root window associated with the primary display.
+ gfx::Rect desktop_bounds = root_window()->bounds();
+ window_delegate_.reset(new aura::test::TestWindowDelegate());
+ desktop_window_.reset(new aura::Window(window_delegate_.get()));
+ desktop_window_->Init(ui::LAYER_TEXTURED);
+ desktop_window_->SetBounds(desktop_bounds);
+ aura::client::ParentWindowWithContext(
+ desktop_window_.get(), root_window(), desktop_bounds);
+ desktop_window_->Show();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ helper_->RunAllPendingInMessageLoop();
+ root_window()->RemoveChild(desktop_window_.get());
+ desktop_window_.reset();
+ window_delegate_.reset();
+ helper_->TearDown();
+ }
+
+ aura::Window* root_window() { return helper_->root_window(); }
+
+ private:
+ base::MessageLoopForUI message_loop_;
+ BrowserThreadImpl browser_thread_for_ui_;
+ scoped_ptr<aura::test::AuraTestHelper> helper_;
+ scoped_ptr<aura::Window> desktop_window_;
+ scoped_ptr<aura::test::TestWindowDelegate> window_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDeviceAuraTest);
+};
+
+TEST_F(DesktopCaptureDeviceAuraTest, StartAndStop) {
+ scoped_ptr<media::VideoCaptureDevice> capture_device(
+ DesktopCaptureDeviceAura::Create(
+ content::DesktopMediaID::RegisterAuraWindow(root_window())));
+
+ scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
+ EXPECT_CALL(*client, OnError()).Times(0);
+
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(640, 480);
+ capture_params.requested_format.frame_rate = kFrameRate;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
+ capture_device->AllocateAndStart(
+ capture_params, client.PassAs<media::VideoCaptureDevice::Client>());
+ capture_device->StopAndDeAllocate();
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/desktop_capture_device_unittest.cc b/chromium/content/browser/renderer_host/media/desktop_capture_device_unittest.cc
index 2b6479e3cb2..03dbd53059f 100644
--- a/chromium/content/browser/renderer_host/media/desktop_capture_device_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/desktop_capture_device_unittest.cc
@@ -35,26 +35,50 @@ const int kTestFrameWidth1 = 100;
const int kTestFrameHeight1 = 100;
const int kTestFrameWidth2 = 200;
const int kTestFrameHeight2 = 150;
-const int kBufferSize = kTestFrameWidth2 * kTestFrameHeight2 * 4;
const int kFrameRate = 30;
-class MockFrameObserver : public media::VideoCaptureDevice::EventHandler {
+class MockDeviceClient : public media::VideoCaptureDevice::Client {
public:
- MOCK_METHOD0(ReserveOutputBuffer, scoped_refptr<media::VideoFrame>());
+ MOCK_METHOD2(ReserveOutputBuffer,
+ scoped_refptr<Buffer>(media::VideoFrame::Format format,
+ const gfx::Size& dimensions));
MOCK_METHOD0(OnError, void());
- MOCK_METHOD1(OnFrameInfo, void(const media::VideoCaptureCapability& info));
- MOCK_METHOD1(OnFrameInfoChanged,
- void(const media::VideoCaptureCapability& info));
- MOCK_METHOD6(OnIncomingCapturedFrame, void(const uint8* data,
- int length,
- base::Time timestamp,
- int rotation,
- bool flip_vert,
- bool flip_horiz));
- MOCK_METHOD2(OnIncomingCapturedVideoFrame,
- void(const scoped_refptr<media::VideoFrame>& frame,
- base::Time timestamp));
+ MOCK_METHOD5(OnIncomingCapturedFrame,
+ void(const uint8* data,
+ int length,
+ base::Time timestamp,
+ int rotation,
+ const media::VideoCaptureFormat& frame_format));
+ MOCK_METHOD5(OnIncomingCapturedBuffer,
+ void(const scoped_refptr<Buffer>& buffer,
+ media::VideoFrame::Format format,
+ const gfx::Size& dimensions,
+ base::Time timestamp,
+ int frame_rate));
+};
+
+// DesktopFrame wrapper that flips wrapped frame upside down by inverting
+// stride.
+class InvertedDesktopFrame : public webrtc::DesktopFrame {
+ public:
+ // Takes ownership of |frame|.
+ InvertedDesktopFrame(webrtc::DesktopFrame* frame)
+ : webrtc::DesktopFrame(
+ frame->size(), -frame->stride(),
+ frame->data() + (frame->size().height() - 1) * frame->stride(),
+ frame->shared_memory()),
+ original_frame_(frame) {
+ set_dpi(frame->dpi());
+ set_capture_time_ms(frame->capture_time_ms());
+ mutable_updated_region()->Swap(frame->mutable_updated_region());
+ }
+ virtual ~InvertedDesktopFrame() {}
+
+ private:
+ scoped_ptr<webrtc::DesktopFrame> original_frame_;
+
+ DISALLOW_COPY_AND_ASSIGN(InvertedDesktopFrame);
};
// TODO(sergeyu): Move this to a separate file where it can be reused.
@@ -62,10 +86,15 @@ class FakeScreenCapturer : public webrtc::ScreenCapturer {
public:
FakeScreenCapturer()
: callback_(NULL),
- frame_index_(0) {
+ frame_index_(0),
+ generate_inverted_frames_(false) {
}
virtual ~FakeScreenCapturer() {}
+ void set_generate_inverted_frames(bool generate_inverted_frames) {
+ generate_inverted_frames_ = generate_inverted_frames;
+ }
+
// VideoFrameCapturer interface.
virtual void Start(Callback* callback) OVERRIDE {
callback_ = callback;
@@ -79,7 +108,11 @@ class FakeScreenCapturer : public webrtc::ScreenCapturer {
size = webrtc::DesktopSize(kTestFrameWidth2, kTestFrameHeight2);
}
frame_index_++;
- callback_->OnCaptureCompleted(new webrtc::BasicDesktopFrame(size));
+
+ webrtc::DesktopFrame* frame = new webrtc::BasicDesktopFrame(size);
+ if (generate_inverted_frames_)
+ frame = new InvertedDesktopFrame(frame);
+ callback_->OnCaptureCompleted(frame);
}
virtual void SetMouseShapeObserver(
@@ -89,6 +122,7 @@ class FakeScreenCapturer : public webrtc::ScreenCapturer {
private:
Callback* callback_;
int frame_index_;
+ bool generate_inverted_frames_;
};
class DesktopCaptureDeviceTest : public testing::Test {
@@ -117,36 +151,35 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
DesktopCaptureDevice capture_device(
worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
capturer.Pass());
- media::VideoCaptureCapability caps;
+ media::VideoCaptureFormat format;
base::WaitableEvent done_event(false, false);
int frame_size;
- MockFrameObserver frame_observer;
- EXPECT_CALL(frame_observer, OnFrameInfo(_))
- .WillOnce(SaveArg<0>(&caps));
- EXPECT_CALL(frame_observer, OnError())
- .Times(0);
- EXPECT_CALL(frame_observer, OnIncomingCapturedFrame(_, _, _, _, _, _))
- .WillRepeatedly(DoAll(
- SaveArg<1>(&frame_size),
- InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
-
- media::VideoCaptureCapability capture_format(
- 640, 480, kFrameRate, media::PIXEL_FORMAT_I420, 0, false,
- media::ConstantResolutionVideoCaptureDevice);
- capture_device.Allocate(capture_format, &frame_observer);
- capture_device.Start();
+ scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
+ EXPECT_CALL(*client, OnError()).Times(0);
+ EXPECT_CALL(*client, OnIncomingCapturedFrame(_, _, _, _, _))
+ .WillRepeatedly(
+ DoAll(SaveArg<1>(&frame_size),
+ SaveArg<4>(&format),
+ InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
+
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(640, 480);
+ capture_params.requested_format.frame_rate = kFrameRate;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
+ capture_device.AllocateAndStart(
+ capture_params, client.PassAs<media::VideoCaptureDevice::Client>());
EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
- capture_device.Stop();
- capture_device.DeAllocate();
+ capture_device.StopAndDeAllocate();
- EXPECT_GT(caps.width, 0);
- EXPECT_GT(caps.height, 0);
- EXPECT_EQ(kFrameRate, caps.frame_rate);
- EXPECT_EQ(media::PIXEL_FORMAT_ARGB, caps.color);
- EXPECT_FALSE(caps.interlaced);
+ EXPECT_GT(format.frame_size.width(), 0);
+ EXPECT_GT(format.frame_size.height(), 0);
+ EXPECT_EQ(kFrameRate, format.frame_rate);
+ EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format);
- EXPECT_EQ(caps.width * caps.height * 4, frame_size);
+ EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size);
+ worker_pool_->FlushForTesting();
}
// Test that screen capturer behaves correctly if the source frame size changes
@@ -158,34 +191,27 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
- media::VideoCaptureCapability caps;
+ media::VideoCaptureFormat format;
base::WaitableEvent done_event(false, false);
int frame_size;
- MockFrameObserver frame_observer;
- Expectation frame_info_called = EXPECT_CALL(frame_observer, OnFrameInfo(_))
- .WillOnce(SaveArg<0>(&caps));
- EXPECT_CALL(frame_observer, OnFrameInfoChanged(_))
- .Times(0);
- EXPECT_CALL(frame_observer, OnError())
- .Times(0);
- EXPECT_CALL(frame_observer, OnIncomingCapturedFrame(_, _, _, _, _, _))
- .After(frame_info_called)
- .WillRepeatedly(DoAll(
- SaveArg<1>(&frame_size),
- InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
-
- media::VideoCaptureCapability capture_format(
- kTestFrameWidth1,
- kTestFrameHeight1,
- kFrameRate,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice);
-
- capture_device.Allocate(capture_format, &frame_observer);
- capture_device.Start();
+ scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
+ EXPECT_CALL(*client, OnError()).Times(0);
+ EXPECT_CALL(*client, OnIncomingCapturedFrame(_, _, _, _, _))
+ .WillRepeatedly(
+ DoAll(SaveArg<1>(&frame_size),
+ SaveArg<4>(&format),
+ InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
+
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(kTestFrameWidth1,
+ kTestFrameHeight1);
+ capture_params.requested_format.frame_rate = kFrameRate;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
+
+ capture_device.AllocateAndStart(
+ capture_params, client.PassAs<media::VideoCaptureDevice::Client>());
// Capture at least two frames, to ensure that the source frame size has
// changed while capturing.
@@ -193,16 +219,15 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
done_event.Reset();
EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
- capture_device.Stop();
- capture_device.DeAllocate();
+ capture_device.StopAndDeAllocate();
- EXPECT_EQ(kTestFrameWidth1, caps.width);
- EXPECT_EQ(kTestFrameHeight1, caps.height);
- EXPECT_EQ(kFrameRate, caps.frame_rate);
- EXPECT_EQ(media::PIXEL_FORMAT_ARGB, caps.color);
- EXPECT_FALSE(caps.interlaced);
+ EXPECT_EQ(kTestFrameWidth1, format.frame_size.width());
+ EXPECT_EQ(kTestFrameHeight1, format.frame_size.height());
+ EXPECT_EQ(kFrameRate, format.frame_rate);
+ EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format);
- EXPECT_EQ(caps.width * caps.height * 4, frame_size);
+ EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size);
+ worker_pool_->FlushForTesting();
}
// Test that screen capturer behaves correctly if the source frame size changes
@@ -214,41 +239,25 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
- media::VideoCaptureCapability caps;
+ media::VideoCaptureFormat format;
base::WaitableEvent done_event(false, false);
- MockFrameObserver frame_observer;
- Expectation frame_info_called = EXPECT_CALL(frame_observer, OnFrameInfo(_))
- .WillOnce(SaveArg<0>(&caps));
- Expectation first_info_changed = EXPECT_CALL(frame_observer,
- OnFrameInfoChanged(EqualsCaptureCapability(kTestFrameWidth2,
- kTestFrameHeight2)))
- .After(frame_info_called);
- Expectation second_info_changed = EXPECT_CALL(frame_observer,
- OnFrameInfoChanged(EqualsCaptureCapability(kTestFrameWidth1,
- kTestFrameHeight1)))
- .After(first_info_changed);
- EXPECT_CALL(frame_observer, OnFrameInfoChanged(_))
- .Times(AnyNumber())
- .After(second_info_changed);
- EXPECT_CALL(frame_observer, OnError())
- .Times(0);
- EXPECT_CALL(frame_observer, OnIncomingCapturedFrame(_, _, _, _, _, _))
- .After(frame_info_called)
+ scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
+ EXPECT_CALL(*client, OnError()).Times(0);
+ EXPECT_CALL(*client, OnIncomingCapturedFrame(_, _, _, _, _))
.WillRepeatedly(
- InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal));
+ DoAll(SaveArg<4>(&format),
+ InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
- media::VideoCaptureCapability capture_format(
- kTestFrameWidth2,
- kTestFrameHeight2,
- kFrameRate,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::VariableResolutionVideoCaptureDevice);
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(kTestFrameWidth2,
+ kTestFrameHeight2);
+ capture_params.requested_format.frame_rate = kFrameRate;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
- capture_device.Allocate(capture_format, &frame_observer);
- capture_device.Start();
+ capture_device.AllocateAndStart(
+ capture_params, client.PassAs<media::VideoCaptureDevice::Client>());
// Capture at least three frames, to ensure that the source frame size has
// changed at least twice while capturing.
@@ -258,14 +267,13 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
done_event.Reset();
EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
- capture_device.Stop();
- capture_device.DeAllocate();
+ capture_device.StopAndDeAllocate();
- EXPECT_EQ(kTestFrameWidth1, caps.width);
- EXPECT_EQ(kTestFrameHeight1, caps.height);
- EXPECT_EQ(kFrameRate, caps.frame_rate);
- EXPECT_EQ(media::PIXEL_FORMAT_ARGB, caps.color);
- EXPECT_FALSE(caps.interlaced);
+ EXPECT_EQ(kTestFrameWidth1, format.frame_size.width());
+ EXPECT_EQ(kTestFrameHeight1, format.frame_size.height());
+ EXPECT_EQ(kFrameRate, format.frame_rate);
+ EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format);
+ worker_pool_->FlushForTesting();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/device_request_message_filter.cc b/chromium/content/browser/renderer_host/media/device_request_message_filter.cc
index 96a5de2e194..89e632f07d8 100644
--- a/chromium/content/browser/renderer_host/media/device_request_message_filter.cc
+++ b/chromium/content/browser/renderer_host/media/device_request_message_filter.cc
@@ -4,13 +4,10 @@
#include "content/browser/renderer_host/media/device_request_message_filter.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/common/media/media_stream_messages.h"
#include "content/public/browser/resource_context.h"
-#include "crypto/hmac.h"
// Clears the MediaStreamDevice.name from all devices in |device_list|.
static void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) {
@@ -33,7 +30,9 @@ DeviceRequestMessageFilter::DeviceRequestMessageFilter(
}
DeviceRequestMessageFilter::~DeviceRequestMessageFilter() {
- DCHECK(requests_.empty());
+ // CHECK rather than DCHECK to make sure this never happens in the
+ // wild. We want to be sure due to http://crbug.com/341211
+ CHECK(requests_.empty());
}
struct DeviceRequestMessageFilter::DeviceRequest {
@@ -58,24 +57,9 @@ struct DeviceRequestMessageFilter::DeviceRequest {
StreamDeviceInfoArray video_devices;
};
-void DeviceRequestMessageFilter::StreamGenerated(
- const std::string& label,
- const StreamDeviceInfoArray& audio_devices,
- const StreamDeviceInfoArray& video_devices) {
- NOTIMPLEMENTED();
-}
-
-void DeviceRequestMessageFilter::StreamGenerationFailed(
- const std::string& label) {
- NOTIMPLEMENTED();
-}
-
-void DeviceRequestMessageFilter::StopGeneratedStream(
- const std::string& label) {
- NOTIMPLEMENTED();
-}
-
void DeviceRequestMessageFilter::DevicesEnumerated(
+ int render_view_id,
+ int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& new_devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -97,12 +81,12 @@ void DeviceRequestMessageFilter::DevicesEnumerated(
if (label == request_it->audio_devices_label) {
request_it->has_audio_returned = true;
DCHECK(audio_devices->empty());
- HmacDeviceIds(request_it->origin, new_devices, audio_devices);
+ *audio_devices = new_devices;
} else {
DCHECK(label == request_it->video_devices_label);
request_it->has_video_returned = true;
DCHECK(video_devices->empty());
- HmacDeviceIds(request_it->origin, new_devices, video_devices);
+ *video_devices = new_devices;
}
if (!request_it->has_audio_returned || !request_it->has_video_returned) {
@@ -123,18 +107,11 @@ void DeviceRequestMessageFilter::DevicesEnumerated(
Send(new MediaStreamMsg_GetSourcesACK(request_it->request_id, all_devices));
- // TODO(vrk): Rename StopGeneratedStream() to CancelDeviceRequest().
- media_stream_manager_->StopGeneratedStream(request_it->audio_devices_label);
- media_stream_manager_->StopGeneratedStream(request_it->video_devices_label);
+ media_stream_manager_->CancelRequest(request_it->audio_devices_label);
+ media_stream_manager_->CancelRequest(request_it->video_devices_label);
requests_.erase(request_it);
}
-void DeviceRequestMessageFilter::DeviceOpened(
- const std::string& label,
- const StreamDeviceInfo& video_device) {
- NOTIMPLEMENTED();
-}
-
bool DeviceRequestMessageFilter::OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) {
bool handled = true;
@@ -146,75 +123,27 @@ bool DeviceRequestMessageFilter::OnMessageReceived(const IPC::Message& message,
}
void DeviceRequestMessageFilter::OnChannelClosing() {
- BrowserMessageFilter::OnChannelClosing();
-
// Since the IPC channel is gone, cancel outstanding device requests.
- for (DeviceRequestList::iterator it = requests_.begin();
- it != requests_.end();
- ++it) {
- // TODO(vrk): Rename StopGeneratedStream() to CancelDeviceRequest().
- media_stream_manager_->StopGeneratedStream(it->audio_devices_label);
- media_stream_manager_->StopGeneratedStream(it->video_devices_label);
+ for (DeviceRequestList::iterator request_it = requests_.begin();
+ request_it != requests_.end(); ++request_it) {
+ media_stream_manager_->CancelRequest(request_it->audio_devices_label);
+ media_stream_manager_->CancelRequest(request_it->video_devices_label);
}
requests_.clear();
}
-void DeviceRequestMessageFilter::HmacDeviceIds(
- const GURL& origin,
- const StreamDeviceInfoArray& raw_devices,
- StreamDeviceInfoArray* devices_with_guids) {
- DCHECK(devices_with_guids);
-
- // Replace raw ids with hmac'd ids before returning to renderer process.
- for (StreamDeviceInfoArray::const_iterator device_itr = raw_devices.begin();
- device_itr != raw_devices.end();
- ++device_itr) {
- crypto::HMAC hmac(crypto::HMAC::SHA256);
- const size_t digest_length = hmac.DigestLength();
- std::vector<uint8> digest(digest_length);
- bool result = hmac.Init(origin.spec()) &&
- hmac.Sign(device_itr->device.id, &digest[0], digest.size());
- DCHECK(result);
- if (result) {
- StreamDeviceInfo current_device_info = *device_itr;
- current_device_info.device.id =
- StringToLowerASCII(base::HexEncode(&digest[0], digest.size()));
- devices_with_guids->push_back(current_device_info);
- }
- }
-}
-
-bool DeviceRequestMessageFilter::DoesRawIdMatchGuid(
- const GURL& security_origin,
- const std::string& device_guid,
- const std::string& raw_device_id) {
- crypto::HMAC hmac(crypto::HMAC::SHA256);
- bool result = hmac.Init(security_origin.spec());
- DCHECK(result);
- std::vector<uint8> converted_guid;
- // |device_guid| is not guaranteed to be a hex string, so check for success.
- bool success = base::HexStringToBytes(device_guid, &converted_guid);
-
- if (!success)
- return false;
-
- DCHECK_GT(converted_guid.size(), 0u);
- return hmac.Verify(
- raw_device_id,
- base::StringPiece(reinterpret_cast<const char*>(&converted_guid[0]),
- converted_guid.size()));
-}
-
void DeviceRequestMessageFilter::OnGetSources(int request_id,
const GURL& security_origin) {
// Make request to get audio devices.
const std::string& audio_label = media_stream_manager_->EnumerateDevices(
- this, -1, -1, -1, MEDIA_DEVICE_AUDIO_CAPTURE, security_origin);
+ this, -1, -1, resource_context_->GetMediaDeviceIDSalt(), -1,
+ MEDIA_DEVICE_AUDIO_CAPTURE, security_origin);
DCHECK(!audio_label.empty());
// Make request for video devices.
const std::string& video_label = media_stream_manager_->EnumerateDevices(
- this, -1, -1, -1, MEDIA_DEVICE_VIDEO_CAPTURE, security_origin);
+ this, -1, -1, resource_context_->GetMediaDeviceIDSalt(), -1,
+ MEDIA_DEVICE_VIDEO_CAPTURE, security_origin);
DCHECK(!video_label.empty());
requests_.push_back(DeviceRequest(
diff --git a/chromium/content/browser/renderer_host/media/device_request_message_filter.h b/chromium/content/browser/renderer_host/media/device_request_message_filter.h
index b684954384c..2a95c8286ab 100644
--- a/chromium/content/browser/renderer_host/media/device_request_message_filter.h
+++ b/chromium/content/browser/renderer_host/media/device_request_message_filter.h
@@ -31,14 +31,22 @@ class CONTENT_EXPORT DeviceRequestMessageFilter : public BrowserMessageFilter,
// we don't have to override all these callbacks we don't care about.
// (crbug.com/249476)
virtual void StreamGenerated(
- const std::string& label, const StreamDeviceInfoArray& audio_devices,
- const StreamDeviceInfoArray& video_devices) OVERRIDE;
- virtual void StreamGenerationFailed(const std::string& label) OVERRIDE;
- virtual void StopGeneratedStream(const std::string& label) OVERRIDE;
- virtual void DeviceOpened(const std::string& label,
- const StreamDeviceInfo& video_device) OVERRIDE;
+ int render_view_id, int page_request_id, const std::string& label,
+ const StreamDeviceInfoArray& audio_devices,
+ const StreamDeviceInfoArray& video_devices) OVERRIDE {}
+ virtual void StreamGenerationFailed(int render_view_id,
+ int page_request_id) OVERRIDE {}
+ virtual void DeviceStopped(int render_view_id,
+ const std::string& label,
+ const StreamDeviceInfo& device) OVERRIDE {}
+ virtual void DeviceOpened(int render_view_id,
+ int page_request_id,
+ const std::string& label,
+ const StreamDeviceInfo& video_device) OVERRIDE {}
// DevicesEnumerated() is the only callback we're interested in.
- virtual void DevicesEnumerated(const std::string& label,
+ virtual void DevicesEnumerated(int render_view_id,
+ int page_request_id,
+ const std::string& label,
const StreamDeviceInfoArray& devices) OVERRIDE;
// BrowserMessageFilter implementation.
@@ -46,20 +54,11 @@ class CONTENT_EXPORT DeviceRequestMessageFilter : public BrowserMessageFilter,
bool* message_was_ok) OVERRIDE;
virtual void OnChannelClosing() OVERRIDE;
- // Helper method that checks whether the GUID generated by
- // DeviceRequestMessageFilter matches the given |raw_device_id|.
- static bool DoesRawIdMatchGuid(const GURL& security_origin,
- const std::string& device_guid,
- const std::string& raw_device_id);
-
protected:
virtual ~DeviceRequestMessageFilter();
private:
void OnGetSources(int request_id, const GURL& security_origin);
- void HmacDeviceIds(const GURL& origin,
- const StreamDeviceInfoArray& raw_devices,
- StreamDeviceInfoArray* devices_with_guids);
// Owned by ProfileIOData which is guaranteed to outlive DRMF.
ResourceContext* resource_context_;
diff --git a/chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc b/chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc
index 0daad820084..95b9cd854f6 100644
--- a/chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc
@@ -25,18 +25,20 @@ class MockMediaStreamManager : public MediaStreamManager {
virtual ~MockMediaStreamManager() {}
- MOCK_METHOD6(EnumerateDevices,
+ MOCK_METHOD7(EnumerateDevices,
std::string(MediaStreamRequester* requester,
int render_process_id,
int render_view_id,
+ const ResourceContext::SaltCallback& rc,
int page_request_id,
MediaStreamType type,
const GURL& security_origin));
- MOCK_METHOD1(StopGeneratedStream, void(const std::string& label));
+ MOCK_METHOD1(CancelRequest, void(const std::string& label));
std::string DoEnumerateDevices(MediaStreamRequester* requester,
int render_process_id,
int render_view_id,
+ const ResourceContext::SaltCallback& rc,
int page_request_id,
MediaStreamType type,
const GURL& security_origin) {
@@ -93,10 +95,10 @@ class DeviceRequestMessageFilterTest : public testing::Test {
AddVideoDevices(number_video_devices);
GURL origin("https://test.com");
EXPECT_CALL(*media_stream_manager_,
- EnumerateDevices(_, _, _, _, MEDIA_DEVICE_AUDIO_CAPTURE, _))
+ EnumerateDevices(_, _, _, _, _, MEDIA_DEVICE_AUDIO_CAPTURE, _))
.Times(1);
EXPECT_CALL(*media_stream_manager_,
- EnumerateDevices(_, _, _, _, MEDIA_DEVICE_VIDEO_CAPTURE, _))
+ EnumerateDevices(_, _, _, _, _, MEDIA_DEVICE_VIDEO_CAPTURE, _))
.Times(1);
// Send message to get devices. Should trigger 2 EnumerateDevice() requests.
const int kRequestId = 123;
@@ -108,20 +110,15 @@ class DeviceRequestMessageFilterTest : public testing::Test {
EXPECT_EQ(0u, host_->requested_devices().size());
// After the video device callback is fired, |message| should be populated.
- EXPECT_CALL(*media_stream_manager_, StopGeneratedStream(kAudioLabel))
+ EXPECT_CALL(*media_stream_manager_, CancelRequest(kAudioLabel))
.Times(1);
- EXPECT_CALL(*media_stream_manager_, StopGeneratedStream(kVideoLabel))
+ EXPECT_CALL(*media_stream_manager_, CancelRequest(kVideoLabel))
.Times(1);
FireVideoDeviceCallback();
EXPECT_EQ(static_cast<size_t>(number_audio_devices + number_video_devices),
host_->requested_devices().size());
EXPECT_EQ(kRequestId, host_->received_id());
- // Check to make sure no devices have raw ids.
- EXPECT_FALSE(DoesContainRawIds(host_->requested_devices()));
-
- // Check to make sure every GUID produced matches a raw device id.
- EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->requested_devices(), origin));
}
bool AreLabelsPresent(MediaStreamType type) {
@@ -142,7 +139,7 @@ class DeviceRequestMessageFilterTest : public testing::Test {
new TestBrowserThread(BrowserThread::IO, message_loop_.get()));
media_stream_manager_.reset(new MockMediaStreamManager());
- ON_CALL(*media_stream_manager_, EnumerateDevices(_, _, _, _, _, _))
+ ON_CALL(*media_stream_manager_, EnumerateDevices(_, _, _, _, _, _, _))
.WillByDefault(Invoke(media_stream_manager_.get(),
&MockMediaStreamManager::DoEnumerateDevices));
@@ -163,10 +160,10 @@ class DeviceRequestMessageFilterTest : public testing::Test {
void AddAudioDevices(int number_of_devices) {
for (int i = 0; i < number_of_devices; i++) {
physical_audio_devices_.push_back(
- StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE,
- "/dev/audio/" + base::IntToString(next_device_id_),
- "Audio Device" + base::IntToString(next_device_id_),
- false));
+ StreamDeviceInfo(
+ MEDIA_DEVICE_AUDIO_CAPTURE,
+ "/dev/audio/" + base::IntToString(next_device_id_),
+ "Audio Device" + base::IntToString(next_device_id_)));
next_device_id_++;
}
}
@@ -174,10 +171,10 @@ class DeviceRequestMessageFilterTest : public testing::Test {
void AddVideoDevices(int number_of_devices) {
for (int i = 0; i < number_of_devices; i++) {
physical_video_devices_.push_back(
- StreamDeviceInfo(MEDIA_DEVICE_VIDEO_CAPTURE,
- "/dev/video/" + base::IntToString(next_device_id_),
- "Video Device" + base::IntToString(next_device_id_),
- false));
+ StreamDeviceInfo(
+ MEDIA_DEVICE_VIDEO_CAPTURE,
+ "/dev/video/" + base::IntToString(next_device_id_),
+ "Video Device" + base::IntToString(next_device_id_)));
next_device_id_++;
}
}
@@ -191,53 +188,11 @@ class DeviceRequestMessageFilterTest : public testing::Test {
}
void FireAudioDeviceCallback() {
- host_->DevicesEnumerated(kAudioLabel, physical_audio_devices_);
+ host_->DevicesEnumerated(-1, -1, kAudioLabel, physical_audio_devices_);
}
void FireVideoDeviceCallback() {
- host_->DevicesEnumerated(kVideoLabel, physical_video_devices_);
- }
-
- bool DoesContainRawIds(const StreamDeviceInfoArray& devices) {
- for (size_t i = 0; i < devices.size(); i++) {
- for (size_t j = 0; j < physical_audio_devices_.size(); ++j) {
- if (physical_audio_devices_[j].device.id == devices[i].device.id)
- return true;
- }
- for (size_t j = 0; j < physical_video_devices_.size(); ++j) {
- if (physical_video_devices_[j].device.id == devices[i].device.id)
- return true;
- }
- }
- return false;
- }
-
- bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray& devices,
- const GURL& origin) {
- for (size_t i = 0; i < devices.size(); i++) {
- bool found_match = false;
- for (size_t j = 0; j < physical_audio_devices_.size(); ++j) {
- if (DeviceRequestMessageFilter::DoesRawIdMatchGuid(
- origin,
- devices[i].device.id,
- physical_audio_devices_[j].device.id)) {
- EXPECT_FALSE(found_match);
- found_match = true;
- }
- }
- for (size_t j = 0; j < physical_video_devices_.size(); ++j) {
- if (DeviceRequestMessageFilter::DoesRawIdMatchGuid(
- origin,
- devices[i].device.id,
- physical_video_devices_[j].device.id)) {
- EXPECT_FALSE(found_match);
- found_match = true;
- }
- }
- if (!found_match)
- return false;
- }
- return true;
+ host_->DevicesEnumerated(-1, -1, kVideoLabel, physical_video_devices_);
}
int next_device_id_;
@@ -301,20 +256,4 @@ TEST_F(DeviceRequestMessageFilterTest, TestGetSources_AllowMicAllowCamera) {
EXPECT_TRUE(AreLabelsPresent(MEDIA_DEVICE_VIDEO_CAPTURE));
}
-TEST_F(DeviceRequestMessageFilterTest, TestRawIdMatchGuid_EmptyGuid) {
- GURL origin("https://test.com");
- const std::string device_guid = "";
- const std::string raw_device_id = "device";
- EXPECT_FALSE(DeviceRequestMessageFilter::DoesRawIdMatchGuid(
- origin, device_guid, raw_device_id));
-}
-
-TEST_F(DeviceRequestMessageFilterTest, TestRawIdMatchGuid_NonHexGuid) {
- GURL origin("https://test.com");
- const std::string device_guid = "garbage";
- const std::string raw_device_id = "device";
- EXPECT_FALSE(DeviceRequestMessageFilter::DoesRawIdMatchGuid(
- origin, device_guid, raw_device_id));
-}
-
}; // namespace content
diff --git a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
index 9135b719960..68f1c362c70 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
@@ -14,12 +14,16 @@ namespace content {
MediaStreamDispatcherHost::MediaStreamDispatcherHost(
int render_process_id,
+ const ResourceContext::SaltCallback& salt_callback,
MediaStreamManager* media_stream_manager)
: render_process_id_(render_process_id),
+ salt_callback_(salt_callback),
media_stream_manager_(media_stream_manager) {
}
void MediaStreamDispatcherHost::StreamGenerated(
+ int render_view_id,
+ int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices) {
@@ -27,72 +31,58 @@ void MediaStreamDispatcherHost::StreamGenerated(
DVLOG(1) << "MediaStreamDispatcherHost::StreamGenerated("
<< ", {label = " << label << "})";
- StreamMap::iterator it = streams_.find(label);
- DCHECK(it != streams_.end());
- StreamRequest request = it->second;
-
Send(new MediaStreamMsg_StreamGenerated(
- request.render_view_id, request.page_request_id, label, audio_devices,
+ render_view_id, page_request_id, label, audio_devices,
video_devices));
}
-void MediaStreamDispatcherHost::StreamGenerationFailed(
- const std::string& label) {
+void MediaStreamDispatcherHost::StreamGenerationFailed(int render_view_id,
+ int page_request_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "MediaStreamDispatcherHost::StreamGenerationFailed("
- << ", {label = " << label << "})";
+ << ", {page_request_id = " << page_request_id << "})";
- StreamMap::iterator it = streams_.find(label);
- DCHECK(it != streams_.end());
- StreamRequest request = it->second;
- streams_.erase(it);
- Send(new MediaStreamMsg_StreamGenerationFailed(request.render_view_id,
- request.page_request_id));
+ Send(new MediaStreamMsg_StreamGenerationFailed(render_view_id,
+ page_request_id));
}
-void MediaStreamDispatcherHost::StopGeneratedStream(
- const std::string& label) {
+void MediaStreamDispatcherHost::DeviceStopped(int render_view_id,
+ const std::string& label,
+ const StreamDeviceInfo& device) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DVLOG(1) << "MediaStreamDispatcherHost::StopGeneratedStream("
- << ", {label = " << label << "})";
-
- StreamMap::iterator it = streams_.find(label);
- DCHECK(it != streams_.end());
- StreamRequest request = it->second;
- streams_.erase(it);
+ DVLOG(1) << "MediaStreamDispatcherHost::DeviceStopped("
+ << "{label = " << label << "}, "
+ << "{type = " << device.device.type << "}, "
+ << "{device_id = " << device.device.id << "})";
- Send(new MediaStreamMsg_StopGeneratedStream(request.render_view_id, label));
+ Send(new MediaStreamMsg_DeviceStopped(render_view_id, label, device));
}
void MediaStreamDispatcherHost::DevicesEnumerated(
+ int render_view_id,
+ int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "MediaStreamDispatcherHost::DevicesEnumerated("
- << ", {label = " << label << "})";
+ << ", {page_request_id = " << page_request_id << "})";
- StreamMap::iterator it = streams_.find(label);
- DCHECK(it != streams_.end());
- StreamRequest request = it->second;
-
- Send(new MediaStreamMsg_DevicesEnumerated(
- request.render_view_id, request.page_request_id, label, devices));
+ Send(new MediaStreamMsg_DevicesEnumerated(render_view_id, page_request_id,
+ devices));
}
void MediaStreamDispatcherHost::DeviceOpened(
+ int render_view_id,
+ int page_request_id,
const std::string& label,
const StreamDeviceInfo& video_device) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "MediaStreamDispatcherHost::DeviceOpened("
- << ", {label = " << label << "})";
-
- StreamMap::iterator it = streams_.find(label);
- DCHECK(it != streams_.end());
- StreamRequest request = it->second;
+ << ", {page_request_id = " << page_request_id << "})";
Send(new MediaStreamMsg_DeviceOpened(
- request.render_view_id, request.page_request_id, label, video_device));
+ render_view_id, page_request_id, label, video_device));
}
bool MediaStreamDispatcherHost::OnMessageReceived(
@@ -102,34 +92,29 @@ bool MediaStreamDispatcherHost::OnMessageReceived(
IPC_MESSAGE_HANDLER(MediaStreamHostMsg_GenerateStream, OnGenerateStream)
IPC_MESSAGE_HANDLER(MediaStreamHostMsg_CancelGenerateStream,
OnCancelGenerateStream)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_StopGeneratedStream,
- OnStopGeneratedStream)
+ IPC_MESSAGE_HANDLER(MediaStreamHostMsg_StopStreamDevice,
+ OnStopStreamDevice)
IPC_MESSAGE_HANDLER(MediaStreamHostMsg_EnumerateDevices,
OnEnumerateDevices)
+ IPC_MESSAGE_HANDLER(MediaStreamHostMsg_CancelEnumerateDevices,
+ OnCancelEnumerateDevices)
IPC_MESSAGE_HANDLER(MediaStreamHostMsg_OpenDevice,
OnOpenDevice)
+ IPC_MESSAGE_HANDLER(MediaStreamHostMsg_CloseDevice,
+ OnCloseDevice)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
return handled;
}
void MediaStreamDispatcherHost::OnChannelClosing() {
- BrowserMessageFilter::OnChannelClosing();
DVLOG(1) << "MediaStreamDispatcherHost::OnChannelClosing";
// Since the IPC channel is gone, close all requesting/requested streams.
- for (StreamMap::iterator it = streams_.begin();
- it != streams_.end();
- ++it) {
- std::string label = it->first;
- media_stream_manager_->StopGeneratedStream(label);
- }
- // Clear the map after we have stopped all the streams.
- streams_.clear();
+ media_stream_manager_->CancelAllRequests(render_process_id_);
}
MediaStreamDispatcherHost::~MediaStreamDispatcherHost() {
- DCHECK(streams_.empty());
}
void MediaStreamDispatcherHost::OnGenerateStream(
@@ -140,20 +125,14 @@ void MediaStreamDispatcherHost::OnGenerateStream(
DVLOG(1) << "MediaStreamDispatcherHost::OnGenerateStream("
<< render_view_id << ", "
<< page_request_id << ", ["
- << " audio:" << components.audio_type
- << " video:" << components.video_type
+ << " audio:" << components.audio_requested
+ << " video:" << components.video_requested
<< " ], "
<< security_origin.spec() << ")";
- const std::string& label = media_stream_manager_->GenerateStream(
- this, render_process_id_, render_view_id, page_request_id,
- components, security_origin);
- if (label.empty()) {
- Send(new MediaStreamMsg_StreamGenerationFailed(render_view_id,
- page_request_id));
- } else {
- streams_[label] = StreamRequest(render_view_id, page_request_id);
- }
+ media_stream_manager_->GenerateStream(
+ this, render_process_id_, render_view_id, salt_callback_,
+ page_request_id, components, security_origin);
}
void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_view_id,
@@ -161,26 +140,18 @@ void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_view_id,
DVLOG(1) << "MediaStreamDispatcherHost::OnCancelGenerateStream("
<< render_view_id << ", "
<< page_request_id << ")";
-
- for (StreamMap::iterator it = streams_.begin(); it != streams_.end(); ++it) {
- if (it->second.render_view_id == render_view_id &&
- it->second.page_request_id == page_request_id) {
- media_stream_manager_->CancelRequest(it->first);
- }
- }
+ media_stream_manager_->CancelRequest(render_process_id_, render_view_id,
+ page_request_id);
}
-void MediaStreamDispatcherHost::OnStopGeneratedStream(
- int render_view_id, const std::string& label) {
- DVLOG(1) << "MediaStreamDispatcherHost::OnStopGeneratedStream("
- << ", {label = " << label << "})";
-
- StreamMap::iterator it = streams_.find(label);
- if (it == streams_.end())
- return;
-
- media_stream_manager_->StopGeneratedStream(label);
- streams_.erase(it);
+void MediaStreamDispatcherHost::OnStopStreamDevice(
+ int render_view_id,
+ const std::string& device_id) {
+ DVLOG(1) << "MediaStreamDispatcherHost::OnStopStreamDevice("
+ << render_view_id << ", "
+ << device_id << ")";
+ media_stream_manager_->StopStreamDevice(render_process_id_, render_view_id,
+ device_id);
}
void MediaStreamDispatcherHost::OnEnumerateDevices(
@@ -194,11 +165,19 @@ void MediaStreamDispatcherHost::OnEnumerateDevices(
<< type << ", "
<< security_origin.spec() << ")";
- const std::string& label = media_stream_manager_->EnumerateDevices(
- this, render_process_id_, render_view_id, page_request_id,
- type, security_origin);
- DCHECK(!label.empty());
- streams_[label] = StreamRequest(render_view_id, page_request_id);
+ media_stream_manager_->EnumerateDevices(
+ this, render_process_id_, render_view_id, salt_callback_,
+ page_request_id, type, security_origin);
+}
+
+void MediaStreamDispatcherHost::OnCancelEnumerateDevices(
+ int render_view_id,
+ int page_request_id) {
+ DVLOG(1) << "MediaStreamDispatcherHost::OnCancelEnumerateDevices("
+ << render_view_id << ", "
+ << page_request_id << ")";
+ media_stream_manager_->CancelRequest(render_process_id_, render_view_id,
+ page_request_id);
}
void MediaStreamDispatcherHost::OnOpenDevice(
@@ -214,11 +193,20 @@ void MediaStreamDispatcherHost::OnOpenDevice(
<< type << ", "
<< security_origin.spec() << ")";
- const std::string& label = media_stream_manager_->OpenDevice(
- this, render_process_id_, render_view_id, page_request_id,
- device_id, type, security_origin);
- DCHECK(!label.empty());
- streams_[label] = StreamRequest(render_view_id, page_request_id);
+ media_stream_manager_->OpenDevice(
+ this, render_process_id_, render_view_id, salt_callback_,
+ page_request_id, device_id, type, security_origin);
+
+}
+
+void MediaStreamDispatcherHost::OnCloseDevice(
+ int render_view_id,
+ const std::string& label) {
+ DVLOG(1) << "MediaStreamDispatcherHost::OnCloseDevice("
+ << render_view_id << ", "
+ << label << ")";
+
+ media_stream_manager_->CancelRequest(label);
}
} // namespace content
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 cfc69137a39..556a6c187c0 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
@@ -14,8 +14,10 @@
#include "content/common/content_export.h"
#include "content/common/media/media_stream_options.h"
#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/resource_context.h"
namespace content {
+
class MediaStreamManager;
// MediaStreamDispatcherHost is a delegate for Media Stream API messages used by
@@ -24,19 +26,30 @@ class MediaStreamManager;
class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
public MediaStreamRequester {
public:
- MediaStreamDispatcherHost(int render_process_id,
- MediaStreamManager* media_stream_manager);
+ MediaStreamDispatcherHost(
+ int render_process_id,
+ const ResourceContext::SaltCallback& salt_callback,
+ MediaStreamManager* media_stream_manager);
// MediaStreamRequester implementation.
virtual void StreamGenerated(
+ int render_view_id,
+ int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices) OVERRIDE;
- virtual void StreamGenerationFailed(const std::string& label) OVERRIDE;
- virtual void StopGeneratedStream(const std::string& label) OVERRIDE;
- virtual void DevicesEnumerated(const std::string& label,
+ virtual void StreamGenerationFailed(int render_view_id,
+ int page_request_id) OVERRIDE;
+ virtual void DeviceStopped(int render_view_id,
+ const std::string& label,
+ const StreamDeviceInfo& device) OVERRIDE;
+ virtual void DevicesEnumerated(int render_view_id,
+ int page_request_id,
+ const std::string& label,
const StreamDeviceInfoArray& devices) OVERRIDE;
- virtual void DeviceOpened(const std::string& label,
+ virtual void DeviceOpened(int render_view_id,
+ int page_request_id,
+ const std::string& label,
const StreamDeviceInfo& video_device) OVERRIDE;
// BrowserMessageFilter implementation.
@@ -56,37 +69,34 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
const GURL& security_origin);
void OnCancelGenerateStream(int render_view_id,
int page_request_id);
- void OnStopGeneratedStream(int render_view_id, const std::string& label);
+ void OnStopStreamDevice(int render_view_id,
+ const std::string& device_id);
void OnEnumerateDevices(int render_view_id,
int page_request_id,
MediaStreamType type,
const GURL& security_origin);
+ void OnCancelEnumerateDevices(int render_view_id,
+ int page_request_id);
+
void OnOpenDevice(int render_view_id,
int page_request_id,
const std::string& device_id,
MediaStreamType type,
const GURL& security_origin);
+ void OnCloseDevice(int render_view_id,
+ const std::string& label);
+
+ void StoreRequest(int render_view_id,
+ int page_request_id,
+ const std::string& label);;
+
int render_process_id_;
+ ResourceContext::SaltCallback salt_callback_;
MediaStreamManager* media_stream_manager_;
- struct StreamRequest {
- StreamRequest() : render_view_id(0), page_request_id(0) {}
- StreamRequest(int render_view_id, int page_request_id)
- : render_view_id(render_view_id),
- page_request_id(page_request_id ) {
- }
- int render_view_id;
- // Id of the request generated by MediaStreamDispatcher.
- int page_request_id;
- };
-
- typedef std::map<std::string, StreamRequest> StreamMap;
- // Streams generated for this host.
- StreamMap streams_;
-
DISALLOW_COPY_AND_ASSIGN(MediaStreamDispatcherHost);
};
diff --git a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 2b7d6836326..c8132d177cd 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
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <string>
+#include <queue>
#include "base/bind.h"
#include "base/callback_helpers.h"
@@ -12,15 +13,16 @@
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
-#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/media_stream_messages.h"
#include "content/common/media/media_stream_options.h"
+#include "content/public/browser/media_device_id.h"
#include "content/public/test/mock_resource_context.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_content_client.h"
#include "ipc/ipc_message_macros.h"
-#include "media/audio/audio_manager.h"
+#include "media/audio/mock_audio_manager.h"
#include "media/video/capture/fake_video_capture_device.h"
#include "net/url_request/url_request_context.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -42,9 +44,10 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
public TestContentBrowserClient {
public:
MockMediaStreamDispatcherHost(
+ const ResourceContext::SaltCallback salt_callback,
const scoped_refptr<base::MessageLoopProxy>& message_loop,
MediaStreamManager* manager)
- : MediaStreamDispatcherHost(kProcessId, manager),
+ : MediaStreamDispatcherHost(kProcessId, salt_callback, manager),
message_loop_(message_loop) {}
// A list of mock methods.
@@ -52,30 +55,51 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
void(int routing_id, int request_id, int audio_array_size,
int video_array_size));
MOCK_METHOD2(OnStreamGenerationFailed, void(int routing_id, int request_id));
- MOCK_METHOD1(OnStopGeneratedStreamFromBrowser,
- void(int routing_id));
+ MOCK_METHOD1(OnDeviceStopped, void(int routing_id));
+ MOCK_METHOD2(OnDeviceOpened, void(int routing_id, int request_id));
// Accessor to private functions.
- void OnGenerateStream(int page_request_id,
+ void OnGenerateStream(int render_view_id,
+ int page_request_id,
const StreamOptions& components,
+ const GURL& security_origin,
const base::Closure& quit_closure) {
- quit_closure_ = quit_closure;
+ quit_closures_.push(quit_closure);
MediaStreamDispatcherHost::OnGenerateStream(
- kRenderId, page_request_id, components, GURL());
+ render_view_id, page_request_id, components, security_origin);
}
- void OnStopGeneratedStream(const std::string& label) {
- MediaStreamDispatcherHost::OnStopGeneratedStream(kRenderId, label);
+ void OnStopStreamDevice(int render_view_id,
+ const std::string& device_id) {
+ MediaStreamDispatcherHost::OnStopStreamDevice(render_view_id, device_id);
}
- // Return the number of streams that have been opened or is being open.
- size_t NumberOfStreams() {
- return streams_.size();
+ void OnOpenDevice(int render_view_id,
+ int page_request_id,
+ const std::string& device_id,
+ MediaStreamType type,
+ const GURL& security_origin,
+ const base::Closure& quit_closure) {
+ quit_closures_.push(quit_closure);
+ MediaStreamDispatcherHost::OnOpenDevice(
+ render_view_id, page_request_id, device_id, type, security_origin);
+ }
+
+ void OnEnumerateDevices(int render_view_id,
+ int page_request_id,
+ MediaStreamType type,
+ const GURL& security_origin,
+ const base::Closure& quit_closure) {
+ quit_closures_.push(quit_closure);
+ MediaStreamDispatcherHost::OnEnumerateDevices(
+ render_view_id, page_request_id, type, security_origin);
}
std::string label_;
StreamDeviceInfoArray audio_devices_;
StreamDeviceInfoArray video_devices_;
+ StreamDeviceInfo opened_device_;
+ StreamDeviceInfoArray enumerated_devices_;
private:
virtual ~MockMediaStreamDispatcherHost() {}
@@ -93,8 +117,10 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated, OnStreamGenerated)
IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
OnStreamGenerationFailed)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_StopGeneratedStream,
- OnStopGeneratedStreamFromBrowser)
+ IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped, OnDeviceStopped)
+ IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpened)
+ IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated,
+ OnDevicesEnumerated)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
EXPECT_TRUE(handled);
@@ -112,8 +138,11 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
StreamDeviceInfoArray video_device_list) {
OnStreamGenerated(msg.routing_id(), request_id, audio_device_list.size(),
video_device_list.size());
- // Notify that the event have occured.
- message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure_));
+ // Notify that the event have occurred.
+ base::Closure quit_closure = quit_closures_.front();
+ quit_closures_.pop();
+ message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
+
label_ = label;
audio_devices_ = audio_device_list;
video_devices_ = video_device_list;
@@ -121,22 +150,49 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
void OnStreamGenerationFailed(const IPC::Message& msg, int request_id) {
OnStreamGenerationFailed(msg.routing_id(), request_id);
- if (!quit_closure_.is_null())
- message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure_));
+ if (!quit_closures_.empty()) {
+ base::Closure quit_closure = quit_closures_.front();
+ quit_closures_.pop();
+ message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
+ }
+
label_= "";
}
- void OnStopGeneratedStreamFromBrowser(const IPC::Message& msg,
- const std::string& label) {
- OnStopGeneratedStreamFromBrowser(msg.routing_id());
- // Notify that the event have occured.
- if (!quit_closure_.is_null())
- message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure_));
- label_ = "";
+ void OnDeviceStopped(const IPC::Message& msg,
+ const std::string& label,
+ const content::StreamDeviceInfo& device) {
+ if (IsVideoMediaType(device.device.type))
+ EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, video_devices_[0]));
+ if (IsAudioMediaType(device.device.type))
+ EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, audio_devices_[0]));
+
+ OnDeviceStopped(msg.routing_id());
+ }
+
+ void OnDeviceOpened(const IPC::Message& msg,
+ int request_id,
+ const std::string& label,
+ const StreamDeviceInfo& device) {
+ base::Closure quit_closure = quit_closures_.front();
+ quit_closures_.pop();
+ message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
+ label_ = label;
+ opened_device_ = device;
+ }
+
+ void OnDevicesEnumerated(const IPC::Message& msg,
+ int request_id,
+ const StreamDeviceInfoArray& devices) {
+ base::Closure quit_closure = quit_closures_.front();
+ quit_closures_.pop();
+ message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
+ enumerated_devices_ = devices;
}
scoped_refptr<base::MessageLoopProxy> message_loop_;
- base::Closure quit_closure_;
+
+ std::queue<base::Closure> quit_closures_;
};
class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy {
@@ -148,15 +204,19 @@ class MediaStreamDispatcherHostTest : public testing::Test {
public:
MediaStreamDispatcherHostTest()
: old_browser_client_(NULL),
- thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
+ thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ origin_("https://test.com") {
+ audio_manager_.reset(
+ new media::MockAudioManager(base::MessageLoopProxy::current()));
// Create our own MediaStreamManager.
- audio_manager_.reset(media::AudioManager::Create());
media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
// Make sure we use fake devices to avoid long delays.
media_stream_manager_->UseFakeDevice();
- host_ = new MockMediaStreamDispatcherHost(base::MessageLoopProxy::current(),
- media_stream_manager_.get());
+ host_ = new MockMediaStreamDispatcherHost(
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ base::MessageLoopProxy::current(),
+ media_stream_manager_.get());
// Use the fake content client and browser.
content_client_.reset(new TestContentClient());
@@ -165,10 +225,18 @@ class MediaStreamDispatcherHostTest : public testing::Test {
}
virtual ~MediaStreamDispatcherHostTest() {
- // Recover the old browser client and content client.
- SetBrowserClientForTesting(old_browser_client_);
- content_client_.reset();
- media_stream_manager_->WillDestroyCurrentMessageLoop();
+ }
+
+ virtual void SetUp() OVERRIDE {
+ media::FakeVideoCaptureDevice::GetDeviceNames(&physical_video_devices_);
+ ASSERT_GT(physical_video_devices_.size(), 0u);
+
+ audio_manager_->GetAudioInputDeviceNames(&physical_audio_devices_);
+ ASSERT_GT(physical_audio_devices_.size(), 0u);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ host_->OnChannelClosing();
}
protected:
@@ -181,11 +249,119 @@ class MediaStreamDispatcherHostTest : public testing::Test {
stream_ui.PassAs<FakeMediaStreamUIProxy>());
}
- void GenerateStreamAndWaitForResult(int page_request_id,
+ void GenerateStreamAndWaitForResult(int render_view_id,
+ int page_request_id,
const StreamOptions& options) {
base::RunLoop run_loop;
- host_->OnGenerateStream(page_request_id, options, run_loop.QuitClosure());
+ int expected_audio_array_size =
+ (options.audio_requested &&
+ physical_audio_devices_.size() > 0) ? 1 : 0;
+ int expected_video_array_size =
+ (options.video_requested &&
+ physical_video_devices_.size() > 0) ? 1 : 0;
+ EXPECT_CALL(*host_.get(), OnStreamGenerated(render_view_id, page_request_id,
+ expected_audio_array_size,
+ expected_video_array_size));
+ host_->OnGenerateStream(render_view_id, page_request_id, options, origin_,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_FALSE(DoesContainRawIds(host_->audio_devices_));
+ EXPECT_FALSE(DoesContainRawIds(host_->video_devices_));
+ EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->audio_devices_, origin_));
+ EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_));
+ }
+
+ void GenerateStreamAndWaitForFailure(int render_view_id,
+ int page_request_id,
+ const StreamOptions& options) {
+ base::RunLoop run_loop;
+ EXPECT_CALL(*host_.get(),
+ OnStreamGenerationFailed(render_view_id, page_request_id));
+ host_->OnGenerateStream(render_view_id, page_request_id, options, origin_,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ void OpenVideoDeviceAndWaitForResult(int render_view_id,
+ int page_request_id,
+ const std::string& device_id) {
+ base::RunLoop run_loop;
+ host_->OnOpenDevice(render_view_id, page_request_id, device_id,
+ MEDIA_DEVICE_VIDEO_CAPTURE, origin_,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_FALSE(DoesContainRawIds(host_->video_devices_));
+ EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_));
+ }
+
+ void EnumerateDevicesAndWaitForResult(int render_view_id,
+ int page_request_id,
+ MediaStreamType type) {
+ base::RunLoop run_loop;
+ host_->OnEnumerateDevices(render_view_id, page_request_id, type, origin_,
+ run_loop.QuitClosure());
run_loop.Run();
+ ASSERT_FALSE(host_->enumerated_devices_.empty());
+ EXPECT_FALSE(DoesContainRawIds(host_->enumerated_devices_));
+ EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->enumerated_devices_, origin_));
+ }
+
+ bool DoesContainRawIds(const StreamDeviceInfoArray& devices) {
+ for (size_t i = 0; i < devices.size(); ++i) {
+ media::AudioDeviceNames::const_iterator audio_it =
+ physical_audio_devices_.begin();
+ for (; audio_it != physical_audio_devices_.end(); ++audio_it) {
+ if (audio_it->unique_id == devices[i].device.id)
+ return true;
+ }
+ media::VideoCaptureDevice::Names::const_iterator video_it =
+ physical_video_devices_.begin();
+ for (; video_it != physical_video_devices_.end(); ++video_it) {
+ if (video_it->id() == devices[i].device.id)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray& devices,
+ const GURL& origin) {
+ for (size_t i = 0; i < devices.size(); ++i) {
+ bool found_match = false;
+ media::AudioDeviceNames::const_iterator audio_it =
+ physical_audio_devices_.begin();
+ for (; audio_it != physical_audio_devices_.end(); ++audio_it) {
+ if (content::DoesMediaDeviceIDMatchHMAC(
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ origin,
+ devices[i].device.id,
+ audio_it->unique_id)) {
+ EXPECT_FALSE(found_match);
+ found_match = true;
+ }
+ }
+ media::VideoCaptureDevice::Names::const_iterator video_it =
+ physical_video_devices_.begin();
+ for (; video_it != physical_video_devices_.end(); ++video_it) {
+ if (content::DoesMediaDeviceIDMatchHMAC(
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ origin,
+ devices[i].device.id,
+ video_it->id())) {
+ EXPECT_FALSE(found_match);
+ found_match = true;
+ }
+ }
+ if (!found_match)
+ return false;
+ }
+ return true;
+ }
+
+ void AddSourceIdConstraint(const std::string& source_id,
+ StreamOptions::Constraints* constraints) {
+ constraints->push_back(StreamOptions::Constraint(kMediaStreamSourceInfoId,
+ source_id));
}
scoped_refptr<MockMediaStreamDispatcherHost> host_;
@@ -194,130 +370,391 @@ class MediaStreamDispatcherHostTest : public testing::Test {
ContentBrowserClient* old_browser_client_;
scoped_ptr<ContentClient> content_client_;
content::TestBrowserThreadBundle thread_bundle_;
+ content::TestBrowserContext browser_context_;
+ media::AudioDeviceNames physical_audio_devices_;
+ media::VideoCaptureDevice::Names physical_video_devices_;
+ GURL origin_;
};
-TEST_F(MediaStreamDispatcherHostTest, GenerateStream) {
- StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
+TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithVideoOnly) {
+ StreamOptions options(false, true);
SetupFakeUI(true);
- EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
- GenerateStreamAndWaitForResult(kPageRequestId, options);
-
- std::string label = host_->label_;
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
EXPECT_EQ(host_->audio_devices_.size(), 0u);
EXPECT_EQ(host_->video_devices_.size(), 1u);
- EXPECT_EQ(host_->NumberOfStreams(), 1u);
+}
+
+TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioOnly) {
+ StreamOptions options(true, false);
- host_->OnStopGeneratedStream(label);
- EXPECT_EQ(host_->NumberOfStreams(), 0u);
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+
+ EXPECT_EQ(host_->audio_devices_.size(), 1u);
+ EXPECT_EQ(host_->video_devices_.size(), 0u);
+}
+
+TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithNothing) {
+ StreamOptions options(false, false);
+
+ GenerateStreamAndWaitForFailure(kRenderId, kPageRequestId, options);
+}
+
+TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioAndVideo) {
+ StreamOptions options(true, true);
+
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+
+ EXPECT_EQ(host_->audio_devices_.size(), 1u);
+ EXPECT_EQ(host_->video_devices_.size(), 1u);
}
-TEST_F(MediaStreamDispatcherHostTest, GenerateThreeStreams) {
- // This test opens three video capture devices. Two fake devices exists and it
- // is expected the last call to |Open()| will open the first device again, but
- // with a different label.
- StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
+// This test generates two streams with video only using the same render view
+// id. The same capture device with the same device and session id is expected
+// to be used.
+TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) {
+ StreamOptions options(false, true);
// Generate first stream.
SetupFakeUI(true);
- EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
- GenerateStreamAndWaitForResult(kPageRequestId, options);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
// Check the latest generated stream.
EXPECT_EQ(host_->audio_devices_.size(), 0u);
EXPECT_EQ(host_->video_devices_.size(), 1u);
- std::string label1 = host_->label_;
- std::string device_id1 = host_->video_devices_.front().device.id;
-
- // Check that we now have one opened streams.
- EXPECT_EQ(host_->NumberOfStreams(), 1u);
+ const std::string label1 = host_->label_;
+ const std::string device_id1 = host_->video_devices_.front().device.id;
+ const int session_id1 = host_->video_devices_.front().session_id;
// Generate second stream.
SetupFakeUI(true);
- EXPECT_CALL(*host_.get(),
- OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1));
- GenerateStreamAndWaitForResult(kPageRequestId + 1, options);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + 1, options);
// Check the latest generated stream.
EXPECT_EQ(host_->audio_devices_.size(), 0u);
EXPECT_EQ(host_->video_devices_.size(), 1u);
- std::string label2 = host_->label_;
- std::string device_id2 = host_->video_devices_.front().device.id;
+ const std::string label2 = host_->label_;
+ const std::string device_id2 = host_->video_devices_.front().device.id;
+ int session_id2 = host_->video_devices_.front().session_id;
EXPECT_EQ(device_id1, device_id2);
+ EXPECT_EQ(session_id1, session_id2);
EXPECT_NE(label1, label2);
+}
- // Check that we now have two opened streams.
- EXPECT_EQ(2u, host_->NumberOfStreams());
+TEST_F(MediaStreamDispatcherHostTest,
+ GenerateStreamAndOpenDeviceFromSameRenderId) {
+ StreamOptions options(false, true);
- // Generate third stream.
+ // Generate first stream.
SetupFakeUI(true);
- EXPECT_CALL(*host_.get(),
- OnStreamGenerated(kRenderId, kPageRequestId + 2, 0, 1));
- GenerateStreamAndWaitForResult(kPageRequestId + 2, options);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+
+ EXPECT_EQ(host_->audio_devices_.size(), 0u);
+ EXPECT_EQ(host_->video_devices_.size(), 1u);
+ const std::string label1 = host_->label_;
+ const std::string device_id1 = host_->video_devices_.front().device.id;
+ const int session_id1 = host_->video_devices_.front().session_id;
+
+ // Generate second stream.
+ OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId, device_id1);
+
+ const std::string device_id2 = host_->opened_device_.device.id;
+ const int session_id2 = host_->opened_device_.session_id;
+ const std::string label2 = host_->label_;
+
+ EXPECT_EQ(device_id1, device_id2);
+ EXPECT_NE(session_id1, session_id2);
+ EXPECT_NE(label1, label2);
+}
+
+
+// This test generates two streams with video only using two separate render
+// view ids. The same device id but different session ids are expected.
+TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) {
+ StreamOptions options(false, true);
+
+ // Generate first stream.
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+
+ // Check the latest generated stream.
+ EXPECT_EQ(host_->audio_devices_.size(), 0u);
+ EXPECT_EQ(host_->video_devices_.size(), 1u);
+ const std::string label1 = host_->label_;
+ const std::string device_id1 = host_->video_devices_.front().device.id;
+ const int session_id1 = host_->video_devices_.front().session_id;
+
+ // Generate second stream from another render view.
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId+1, kPageRequestId + 1, options);
// Check the latest generated stream.
EXPECT_EQ(host_->audio_devices_.size(), 0u);
EXPECT_EQ(host_->video_devices_.size(), 1u);
- std::string label3 = host_->label_;
- std::string device_id3 = host_->video_devices_.front().device.id;
- EXPECT_EQ(device_id1, device_id3);
- EXPECT_NE(label1, label3);
- EXPECT_NE(label2, label3);
-
- // Check that we now have three opened streams.
- EXPECT_EQ(host_->NumberOfStreams(), 3u);
-
- host_->OnStopGeneratedStream(label1);
- host_->OnStopGeneratedStream(label2);
- host_->OnStopGeneratedStream(label3);
- EXPECT_EQ(host_->NumberOfStreams(), 0u);
+ const std::string label2 = host_->label_;
+ const std::string device_id2 = host_->video_devices_.front().device.id;
+ const int session_id2 = host_->video_devices_.front().session_id;
+ EXPECT_EQ(device_id1, device_id2);
+ EXPECT_NE(session_id1, session_id2);
+ EXPECT_NE(label1, label2);
+}
+
+// This test request two streams with video only without waiting for the first
+// stream to be generated before requesting the second.
+// The same device id and session ids are expected.
+TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithoutWaiting) {
+ StreamOptions options(false, true);
+
+ // Generate first stream.
+ SetupFakeUI(true);
+ EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
+
+ // Generate second stream.
+ EXPECT_CALL(*host_.get(),
+ OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1));
+
+ base::RunLoop run_loop1;
+ base::RunLoop run_loop2;
+ host_->OnGenerateStream(kRenderId, kPageRequestId, options, origin_,
+ run_loop1.QuitClosure());
+ host_->OnGenerateStream(kRenderId, kPageRequestId + 1, options, origin_,
+ run_loop2.QuitClosure());
+
+ run_loop1.Run();
+ run_loop2.Run();
+}
+
+// Test that we can generate streams where a mandatory sourceId is specified in
+// the request.
+TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithMandatorySourceId) {
+ ASSERT_GE(physical_audio_devices_.size(), 1u);
+ ASSERT_GE(physical_video_devices_.size(), 1u);
+
+ media::AudioDeviceNames::const_iterator audio_it =
+ physical_audio_devices_.begin();
+ for (; audio_it != physical_audio_devices_.end(); ++audio_it) {
+ std::string source_id = content::GetHMACForMediaDeviceID(
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ origin_,
+ audio_it->unique_id);
+ ASSERT_FALSE(source_id.empty());
+ StreamOptions options(true, true);
+ AddSourceIdConstraint(source_id, &options.mandatory_audio);
+
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+ EXPECT_EQ(host_->audio_devices_[0].device.id, source_id);
+ }
+
+ media::VideoCaptureDevice::Names::const_iterator video_it =
+ physical_video_devices_.begin();
+ for (; video_it != physical_video_devices_.end(); ++video_it) {
+ std::string source_id = content::GetHMACForMediaDeviceID(
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ origin_,
+ video_it->id());
+ ASSERT_FALSE(source_id.empty());
+ StreamOptions options(true, true);
+ AddSourceIdConstraint(source_id, &options.mandatory_video);
+
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+ EXPECT_EQ(host_->video_devices_[0].device.id, source_id);
+ }
+}
+
+// Test that we can generate streams where a optional sourceId is specified in
+// the request.
+TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithOptionalSourceId) {
+ ASSERT_GE(physical_audio_devices_.size(), 1u);
+ ASSERT_GE(physical_video_devices_.size(), 1u);
+
+ media::AudioDeviceNames::const_iterator audio_it =
+ physical_audio_devices_.begin();
+ for (; audio_it != physical_audio_devices_.end(); ++audio_it) {
+ std::string source_id = content::GetHMACForMediaDeviceID(
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ origin_,
+ audio_it->unique_id);
+ ASSERT_FALSE(source_id.empty());
+ StreamOptions options(true, true);
+ AddSourceIdConstraint(source_id, &options.optional_audio);
+
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+ EXPECT_EQ(host_->audio_devices_[0].device.id, source_id);
+ }
+
+ media::VideoCaptureDevice::Names::const_iterator video_it =
+ physical_video_devices_.begin();
+ for (; video_it != physical_video_devices_.end(); ++video_it) {
+ std::string source_id = content::GetHMACForMediaDeviceID(
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ origin_,
+ video_it->id());
+ ASSERT_FALSE(source_id.empty());
+ StreamOptions options(true, true);
+ AddSourceIdConstraint(source_id, &options.optional_video);
+
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+ EXPECT_EQ(host_->video_devices_[0].device.id, source_id);
+ }
+}
+
+// Test that generating a stream with an invalid mandatory video source id fail.
+TEST_F(MediaStreamDispatcherHostTest,
+ GenerateStreamsWithInvalidMandatoryVideoSourceId) {
+ StreamOptions options(true, true);
+ AddSourceIdConstraint("invalid source id", &options.mandatory_video);
+
+ GenerateStreamAndWaitForFailure(kRenderId, kPageRequestId, options);
+}
+
+// Test that generating a stream with an invalid mandatory audio source id fail.
+TEST_F(MediaStreamDispatcherHostTest,
+ GenerateStreamsWithInvalidMandatoryAudioSourceId) {
+ StreamOptions options(true, true);
+ AddSourceIdConstraint("invalid source id", &options.mandatory_audio);
+
+ GenerateStreamAndWaitForFailure(kRenderId, kPageRequestId, options);
+}
+
+// Test that generating a stream with an invalid optional video source id
+// succeed.
+TEST_F(MediaStreamDispatcherHostTest,
+ GenerateStreamsWithInvalidOptionalVideoSourceId) {
+ StreamOptions options(true, true);
+ AddSourceIdConstraint("invalid source id", &options.optional_video);
+
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+}
+
+// Test that generating a stream with an invalid optional audio source id
+// succeed.
+TEST_F(MediaStreamDispatcherHostTest,
+ GenerateStreamsWithInvalidOptionalAudioSourceId) {
+ StreamOptions options(true, true);
+ AddSourceIdConstraint("invalid source id", &options.optional_audio);
+
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+}
+
+TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsNoAvailableVideoDevice) {
+ size_t number_of_fake_devices = physical_video_devices_.size();
+ media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(0);
+ media::FakeVideoCaptureDevice::GetDeviceNames(&physical_video_devices_);
+ StreamOptions options(true, true);
+
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+ EXPECT_TRUE(host_->video_devices_.empty());
+
+ // Reset the number of fake devices for next test.
+ media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(number_of_fake_devices);
+}
+
+// Test that if a OnStopStreamDevice message is received for a device that has
+// been opened in a MediaStream and by pepper, the device is only stopped for
+// the MediaStream.
+TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) {
+ StreamOptions options(false, true);
+
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+
+ std::string stream_request_label = host_->label_;
+ StreamDeviceInfo video_device_info = host_->video_devices_.front();
+ ASSERT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest(
+ stream_request_label).size());
+
+ // Open the same device by Pepper.
+ OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId,
+ video_device_info.device.id);
+ std::string open_device_request_label = host_->label_;
+
+ // Stop the device in the MediaStream.
+ host_->OnStopStreamDevice(kRenderId, video_device_info.device.id);
+
+ EXPECT_EQ(0u, media_stream_manager_->GetDevicesOpenedByRequest(
+ stream_request_label).size());
+ EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest(
+ open_device_request_label).size());
+}
+
+TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStreamAndRestart) {
+ StreamOptions options(true, true);
+
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+
+ std::string request_label1 = host_->label_;
+ StreamDeviceInfo video_device_info = host_->video_devices_.front();
+ // Expect that 1 audio and 1 video device has been opened.
+ EXPECT_EQ(2u, media_stream_manager_->GetDevicesOpenedByRequest(
+ request_label1).size());
+
+ host_->OnStopStreamDevice(kRenderId, video_device_info.device.id);
+ EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest(
+ request_label1).size());
+
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+ std::string request_label2 = host_->label_;
+
+ StreamDeviceInfoArray request1_devices =
+ media_stream_manager_->GetDevicesOpenedByRequest(request_label1);
+ StreamDeviceInfoArray request2_devices =
+ media_stream_manager_->GetDevicesOpenedByRequest(request_label2);
+
+ ASSERT_EQ(1u, request1_devices.size());
+ ASSERT_EQ(2u, request2_devices.size());
+
+ // Test that the same audio device has been opened in both streams.
+ EXPECT_TRUE(StreamDeviceInfo::IsEqual(request1_devices[0],
+ request2_devices[0]) ||
+ StreamDeviceInfo::IsEqual(request1_devices[0],
+ request2_devices[1]));
}
TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) {
- StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
+ StreamOptions options(false, true);
base::RunLoop run_loop;
// Create multiple GenerateStream requests.
size_t streams = 5;
for (size_t i = 1; i <= streams; ++i) {
- host_->OnGenerateStream(
- kPageRequestId + i, options, run_loop.QuitClosure());
- EXPECT_EQ(host_->NumberOfStreams(), i);
+ host_->OnGenerateStream(kRenderId, kPageRequestId + i, options, origin_,
+ run_loop.QuitClosure());
}
// Calling OnChannelClosing() to cancel all the pending requests.
host_->OnChannelClosing();
run_loop.RunUntilIdle();
-
- // Streams should have been cleaned up.
- EXPECT_EQ(host_->NumberOfStreams(), 0u);
}
TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) {
- StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
+ StreamOptions options(false, true);
// Create first group of streams.
size_t generated_streams = 3;
for (size_t i = 0; i < generated_streams; ++i) {
SetupFakeUI(true);
- EXPECT_CALL(*host_.get(),
- OnStreamGenerated(kRenderId, kPageRequestId + i, 0, 1));
- GenerateStreamAndWaitForResult(kPageRequestId + i, options);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + i, options);
}
- EXPECT_EQ(host_->NumberOfStreams(), generated_streams);
// Calling OnChannelClosing() to cancel all the pending/generated streams.
host_->OnChannelClosing();
base::RunLoop().RunUntilIdle();
-
- // Streams should have been cleaned up.
- EXPECT_EQ(host_->NumberOfStreams(), 0u);
}
TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
- StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
+ StreamOptions options(false, true);
base::Closure close_callback;
scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
@@ -325,19 +762,48 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
.WillOnce(SaveArg<0>(&close_callback));
media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>());
- EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
- EXPECT_CALL(*host_.get(), OnStopGeneratedStreamFromBrowser(kRenderId));
- GenerateStreamAndWaitForResult(kPageRequestId, options);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
EXPECT_EQ(host_->audio_devices_.size(), 0u);
EXPECT_EQ(host_->video_devices_.size(), 1u);
- EXPECT_EQ(host_->NumberOfStreams(), 1u);
ASSERT_FALSE(close_callback.is_null());
+ EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId));
close_callback.Run();
base::RunLoop().RunUntilIdle();
+}
+
+// Test that the dispatcher is notified if a video device that is in use is
+// being unplugged.
+TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) {
+ size_t number_of_fake_devices = physical_video_devices_.size();
+ StreamOptions options(true, true);
+ SetupFakeUI(true);
+ GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
+ EXPECT_EQ(host_->audio_devices_.size(), 1u);
+ EXPECT_EQ(host_->video_devices_.size(), 1u);
+
+ media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(0);
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId))
+ .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+ media_stream_manager_->OnDevicesChanged(
+ base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
+
+ run_loop.Run();
+
+ media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(number_of_fake_devices);
+}
+
+TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevices) {
+ EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
+ MEDIA_DEVICE_AUDIO_CAPTURE);
+}
- EXPECT_EQ(host_->NumberOfStreams(), 0u);
+TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevices) {
+ EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
+ MEDIA_DEVICE_VIDEO_CAPTURE);
}
}; // namespace content
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager.cc b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
index 4c234b66ab1..f6f62fd4d76 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -5,12 +5,14 @@
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include <list>
+#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/rand_util.h"
+#include "base/run_loop.h"
#include "base/threading/thread.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/device_request_message_filter.h"
@@ -20,6 +22,7 @@
#include "content/browser/renderer_host/media/web_contents_capture_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/media_device_id.h"
#include "content/public/browser/media_observer.h"
#include "content/public/browser/media_request_state.h"
#include "content/public/common/content_switches.h"
@@ -35,8 +38,9 @@
namespace content {
+namespace {
// Creates a random label used to identify requests.
-static std::string RandomLabel() {
+std::string RandomLabel() {
// An earlier PeerConnection spec,
// http://dev.w3.org/2011/webrtc/editor/webrtc.html, specified the
// MediaStream::label alphabet as containing 36 characters from
@@ -54,25 +58,140 @@ static std::string RandomLabel() {
return label;
}
-// Helper to verify if a media stream type is part of options or not.
-static bool Requested(const MediaStreamRequest& request,
- MediaStreamType stream_type) {
- return (request.audio_type == stream_type ||
- request.video_type == stream_type);
+void ParseStreamType(const StreamOptions& options,
+ MediaStreamType* audio_type,
+ MediaStreamType* video_type) {
+ *audio_type = MEDIA_NO_SERVICE;
+ *video_type = MEDIA_NO_SERVICE;
+ if (options.audio_requested) {
+ std::string audio_stream_source;
+ bool mandatory = false;
+ if (options.GetFirstAudioConstraintByName(kMediaStreamSource,
+ &audio_stream_source,
+ &mandatory)) {
+ DCHECK(mandatory);
+ // This is tab or screen capture.
+ if (audio_stream_source == kMediaStreamSourceTab) {
+ *audio_type = content::MEDIA_TAB_AUDIO_CAPTURE;
+ } else if (audio_stream_source == kMediaStreamSourceSystem) {
+ *audio_type = content::MEDIA_LOOPBACK_AUDIO_CAPTURE;
+ }
+ } else {
+ // This is normal audio device capture.
+ *audio_type = content::MEDIA_DEVICE_AUDIO_CAPTURE;
+ }
+ }
+ if (options.video_requested) {
+ std::string video_stream_source;
+ bool mandatory = false;
+ if (options.GetFirstVideoConstraintByName(kMediaStreamSource,
+ &video_stream_source,
+ &mandatory)) {
+ DCHECK(mandatory);
+ // This is tab or screen capture.
+ if (video_stream_source == kMediaStreamSourceTab) {
+ *video_type = content::MEDIA_TAB_VIDEO_CAPTURE;
+ } else if (video_stream_source == kMediaStreamSourceScreen) {
+ *video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
+ } else if (video_stream_source == kMediaStreamSourceDesktop) {
+ *video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
+ }
+ } else {
+ // This is normal video device capture.
+ *video_type = content::MEDIA_DEVICE_VIDEO_CAPTURE;
+ }
+ }
+}
+
+// Needed for MediaStreamManager::GenerateStream below.
+std::string ReturnEmptySalt() {
+ return std::string();
}
-// TODO(xians): Merge DeviceRequest with MediaStreamRequest.
+} // namespace
+
+
+// MediaStreamManager::DeviceRequest represents a request to either enumerate
+// available devices or open one or more devices.
+// TODO(perkj): MediaStreamManager still needs refactoring. I propose we create
+// several subclasses of DeviceRequest and move some of the responsibility of
+// the MediaStreamManager to the subclasses to get rid of the way too many if
+// statements in MediaStreamManager.
class MediaStreamManager::DeviceRequest {
public:
DeviceRequest(MediaStreamRequester* requester,
- const MediaStreamRequest& request)
+ int requesting_process_id,
+ int requesting_view_id,
+ int page_request_id,
+ const GURL& security_origin,
+ MediaStreamRequestType request_type,
+ const StreamOptions& options,
+ const ResourceContext::SaltCallback& salt_callback)
: requester(requester),
- request(request),
- state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED) {
+ requesting_process_id(requesting_process_id),
+ requesting_view_id(requesting_view_id),
+ page_request_id(page_request_id),
+ security_origin(security_origin),
+ request_type(request_type),
+ options(options),
+ salt_callback(salt_callback),
+ state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED),
+ audio_type_(MEDIA_NO_SERVICE),
+ video_type_(MEDIA_NO_SERVICE) {
}
~DeviceRequest() {}
+ void SetAudioType(MediaStreamType audio_type) {
+ DCHECK(IsAudioMediaType(audio_type) || audio_type == MEDIA_NO_SERVICE);
+ audio_type_ = audio_type;
+ }
+
+ MediaStreamType audio_type() const { return audio_type_; }
+
+ void SetVideoType(MediaStreamType video_type) {
+ DCHECK(IsVideoMediaType(video_type) || video_type == MEDIA_NO_SERVICE);
+ video_type_ = video_type;
+ }
+
+ MediaStreamType video_type() const { return video_type_; }
+
+ // Creates a MediaStreamRequest object that is used by this request when UI
+ // is asked for permission and device selection.
+ void CreateUIRequest(const std::string& requested_audio_device_id,
+ const std::string& requested_video_device_id) {
+ DCHECK(!ui_request_);
+ ui_request_.reset(new MediaStreamRequest(requesting_process_id,
+ requesting_view_id,
+ page_request_id,
+ security_origin,
+ request_type,
+ requested_audio_device_id,
+ requested_video_device_id,
+ audio_type_,
+ video_type_));
+ }
+
+ // Creates a tab capture specific MediaStreamRequest object that is used by
+ // this request when UI is asked for permission and device selection.
+ void CreateTabCatureUIRequest(int target_render_process_id,
+ int target_render_view_id,
+ const std::string& tab_capture_id) {
+ DCHECK(!ui_request_);
+ ui_request_.reset(new MediaStreamRequest(target_render_process_id,
+ target_render_view_id,
+ page_request_id,
+ security_origin,
+ request_type,
+ "",
+ "",
+ audio_type_,
+ video_type_));
+ ui_request_->tab_capture_device_id = tab_capture_id;
+ }
+
+ const MediaStreamRequest* UIRequest() const { return ui_request_.get(); }
+
// Update the request state and notify observers.
void SetState(MediaStreamType stream_type, MediaRequestState new_state) {
if (stream_type == NUM_MEDIA_TYPES) {
@@ -84,15 +203,14 @@ class MediaStreamManager::DeviceRequest {
state_[stream_type] = new_state;
}
- if (request.video_type != MEDIA_TAB_VIDEO_CAPTURE &&
- request.audio_type != MEDIA_TAB_AUDIO_CAPTURE &&
- new_state != MEDIA_REQUEST_STATE_CLOSING) {
- return;
- }
-
MediaObserver* media_observer =
GetContentClient()->browser()->GetMediaObserver();
- if (media_observer == NULL)
+ if (!media_observer)
+ return;
+
+ // If |ui_request_| doesn't exist, it means that the request has not yet
+ // been setup fully and there are no valid observers.
+ if (!ui_request_)
return;
// If we appended a device_id scheme, we want to remove it when notifying
@@ -100,11 +218,11 @@ class MediaStreamManager::DeviceRequest {
// used internally within the content module.
std::string device_id =
WebContentsCaptureUtil::StripWebContentsDeviceScheme(
- request.tab_capture_device_id);
+ ui_request_->tab_capture_device_id);
media_observer->OnMediaRequestStateChanged(
- request.render_process_id, request.render_view_id,
- request.page_request_id,
+ ui_request_->render_process_id, ui_request_->render_view_id,
+ ui_request_->page_request_id,
MediaStreamDevice(stream_type, device_id, device_id), new_state);
}
@@ -113,7 +231,30 @@ class MediaStreamManager::DeviceRequest {
}
MediaStreamRequester* const requester; // Can be NULL.
- MediaStreamRequest request;
+
+
+ // The render process id that requested this stream to be generated and that
+ // will receive a handle to the MediaStream. This may be different from
+ // MediaStreamRequest::render_process_id which in the tab capture case
+ // specifies the target renderer from which audio and video is captured.
+ const int requesting_process_id;
+
+ // The render view id that requested this stream to be generated and that
+ // will receive a handle to the MediaStream. This may be different from
+ // MediaStreamRequest::render_view_id which in the tab capture case
+ // specifies the target renderer from which audio and video is captured.
+ const int requesting_view_id;
+
+ // An ID the render view provided to identify this request.
+ const int page_request_id;
+
+ const GURL security_origin;
+
+ const MediaStreamRequestType request_type;
+
+ const StreamOptions options;
+
+ ResourceContext::SaltCallback salt_callback;
StreamDeviceInfoArray devices;
@@ -126,6 +267,9 @@ class MediaStreamManager::DeviceRequest {
private:
std::vector<MediaRequestState> state_;
+ scoped_ptr<MediaStreamRequest> ui_request_;
+ MediaStreamType audio_type_;
+ MediaStreamType video_type_;
};
MediaStreamManager::EnumerationCache::EnumerationCache()
@@ -163,6 +307,7 @@ MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager)
}
MediaStreamManager::~MediaStreamManager() {
+ DVLOG(1) << "~MediaStreamManager";
DCHECK(requests_.empty());
DCHECK(!device_thread_.get());
}
@@ -187,171 +332,206 @@ std::string MediaStreamManager::MakeMediaAccessRequest(
const GURL& security_origin,
const MediaRequestResponseCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- // Create a new request based on options.
- MediaStreamRequest stream_request(
- render_process_id, render_view_id, page_request_id, std::string(),
- security_origin, MEDIA_DEVICE_ACCESS, std::string(), std::string(),
- options.audio_type, options.video_type);
- DeviceRequest* request = new DeviceRequest(NULL, stream_request);
- const std::string& label = AddRequest(request);
- request->callback = callback;
+ // 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_view_id,
+ page_request_id,
+ security_origin,
+ MEDIA_DEVICE_ACCESS,
+ options,
+ base::Bind(&ReturnEmptySalt));
- HandleRequest(label);
+ const std::string& label = AddRequest(request);
+ request->callback = callback;
+ // Post a task and handle the request asynchronously. The reason is that the
+ // requester won't have a label for the request until this function returns
+ // and thus can not handle a response. Using base::Unretained is safe since
+ // MediaStreamManager is deleted on the UI thread, after the IO thread has
+ // been stopped.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&MediaStreamManager::SetupRequest,
+ base::Unretained(this), label));
return label;
}
-std::string MediaStreamManager::GenerateStream(
- MediaStreamRequester* requester,
- int render_process_id,
- int render_view_id,
- int page_request_id,
- const StreamOptions& options,
- const GURL& security_origin) {
+void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
+ int render_process_id,
+ int render_view_id,
+ const ResourceContext::SaltCallback& sc,
+ int page_request_id,
+ const StreamOptions& options,
+ const GURL& security_origin) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "GenerateStream()";
if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kUseFakeDeviceForMediaStream)) {
- UseFakeDevice();
- }
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kUseFakeUIForMediaStream)) {
+ switches::kUseFakeUIForMediaStream)) {
UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>());
}
- int target_render_process_id = render_process_id;
- int target_render_view_id = render_view_id;
- std::string tab_capture_device_id;
+ DeviceRequest* request = new DeviceRequest(requester,
+ render_process_id,
+ render_view_id,
+ page_request_id,
+ security_origin,
+ MEDIA_GENERATE_STREAM,
+ options,
+ sc);
- // Customize options for a WebContents based capture.
- if (options.audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
- options.video_type == MEDIA_TAB_VIDEO_CAPTURE) {
- // TODO(justinlin): Can't plumb audio mirroring using stream type right
- // now, so plumbing by device_id. Will revisit once it's refactored.
- // http://crbug.com/163100
- tab_capture_device_id =
- WebContentsCaptureUtil::AppendWebContentsDeviceScheme(
- !options.video_device_id.empty() ?
- options.video_device_id : options.audio_device_id);
-
- bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget(
- tab_capture_device_id, &target_render_process_id,
- &target_render_view_id);
- if (!has_valid_device_id ||
- (options.audio_type != MEDIA_TAB_AUDIO_CAPTURE &&
- options.audio_type != MEDIA_NO_SERVICE) ||
- (options.video_type != MEDIA_TAB_VIDEO_CAPTURE &&
- options.video_type != MEDIA_NO_SERVICE)) {
- LOG(ERROR) << "Invalid request.";
- return std::string();
- }
- }
+ const std::string& label = AddRequest(request);
- std::string translated_audio_device_id;
- std::string translated_video_device_id;
- if (options.audio_type == MEDIA_DEVICE_AUDIO_CAPTURE) {
- bool found_match = TranslateGUIDToRawId(
- MEDIA_DEVICE_AUDIO_CAPTURE, security_origin, options.audio_device_id,
- &translated_audio_device_id);
- DCHECK(found_match || translated_audio_device_id.empty());
- }
-
- if (options.video_type == MEDIA_DEVICE_VIDEO_CAPTURE) {
- bool found_match = TranslateGUIDToRawId(
- MEDIA_DEVICE_VIDEO_CAPTURE, security_origin, options.video_device_id,
- &translated_video_device_id);
- DCHECK(found_match || translated_video_device_id.empty());
- }
-
- if (options.video_type == MEDIA_DESKTOP_VIDEO_CAPTURE ||
- options.audio_type == MEDIA_SYSTEM_AUDIO_CAPTURE) {
- // For screen capture we only support two valid combinations:
- // (1) screen video capture only, or
- // (2) screen video capture with system audio capture.
- if (options.video_type != MEDIA_DESKTOP_VIDEO_CAPTURE ||
- (options.audio_type != MEDIA_NO_SERVICE &&
- options.audio_type != MEDIA_SYSTEM_AUDIO_CAPTURE)) {
- // TODO(sergeyu): Surface error message to the calling JS code.
- LOG(ERROR) << "Invalid screen capture request.";
- return std::string();
+ // Post a task and handle the request asynchronously. The reason is that the
+ // requester won't have a label for the request until this function returns
+ // and thus can not handle a response. Using base::Unretained is safe since
+ // MediaStreamManager is deleted on the UI thread, after the IO thread has
+ // been stopped.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&MediaStreamManager::SetupRequest,
+ base::Unretained(this), label));
+}
+
+void MediaStreamManager::CancelRequest(int render_process_id,
+ int render_view_id,
+ int page_request_id) {
+ for (DeviceRequests::const_iterator request_it = requests_.begin();
+ request_it != requests_.end(); ++request_it) {
+ const DeviceRequest* request = request_it->second;
+ if (request->requesting_process_id == render_process_id &&
+ request->requesting_view_id == render_view_id &&
+ request->page_request_id == page_request_id) {
+ CancelRequest(request_it->first);
+ return;
}
- translated_video_device_id = options.video_device_id;
}
-
- // Create a new request based on options.
- MediaStreamRequest stream_request(
- target_render_process_id, target_render_view_id, page_request_id,
- tab_capture_device_id, security_origin, MEDIA_GENERATE_STREAM,
- translated_audio_device_id, translated_video_device_id,
- options.audio_type, options.video_type);
- DeviceRequest* request = new DeviceRequest(requester, stream_request);
- const std::string& label = AddRequest(request);
- HandleRequest(label);
- return label;
+ NOTREACHED();
}
void MediaStreamManager::CancelRequest(const std::string& label) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "CancelRequest({label = " << label << "})";
+ DeviceRequest* request = FindRequest(label);
+ if (!request) {
+ // The request does not exist.
+ LOG(ERROR) << "The request with label = " << label << " does not exist.";
+ return;
+ }
+ if (request->request_type == MEDIA_ENUMERATE_DEVICES) {
+ DeleteRequest(label);
+ return;
+ }
- DeviceRequests::iterator it = requests_.find(label);
- if (it != requests_.end()) {
- if (!RequestDone(*it->second)) {
- // TODO(xians): update the |state| to STATE_DONE to trigger a state
- // changed notification to UI before deleting the request?
- scoped_ptr<DeviceRequest> request(it->second);
- RemoveRequest(it);
- for (int i = MEDIA_NO_SERVICE + 1; i < NUM_MEDIA_TYPES; ++i) {
- const MediaStreamType stream_type = static_cast<MediaStreamType>(i);
- MediaStreamProvider* device_manager = GetDeviceManager(stream_type);
- if (!device_manager)
- continue;
- if (request->state(stream_type) != MEDIA_REQUEST_STATE_OPENING &&
- request->state(stream_type) != MEDIA_REQUEST_STATE_DONE) {
- continue;
- }
- for (StreamDeviceInfoArray::const_iterator device_it =
- request->devices.begin();
- device_it != request->devices.end(); ++device_it) {
- if (device_it->device.type == stream_type) {
- device_manager->Close(device_it->session_id);
- }
- }
- }
- // Cancel the request if still pending at UI side.
- request->SetState(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_CLOSING);
- } else {
- StopGeneratedStream(label);
+ // This is a request for opening one or more devices.
+ for (StreamDeviceInfoArray::iterator device_it = request->devices.begin();
+ device_it != request->devices.end(); ++device_it) {
+ MediaRequestState state = request->state(device_it->device.type);
+ // If we have not yet requested the device to be opened - just ignore it.
+ if (state != MEDIA_REQUEST_STATE_OPENING &&
+ state != MEDIA_REQUEST_STATE_DONE) {
+ continue;
}
+ // Stop the opening/opened devices of the requests.
+ CloseDevice(device_it->device.type, device_it->session_id);
}
+
+ // Cancel the request if still pending at UI side.
+ request->SetState(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_CLOSING);
+ DeleteRequest(label);
}
-void MediaStreamManager::StopGeneratedStream(const std::string& label) {
+void MediaStreamManager::CancelAllRequests(int render_process_id) {
+ DeviceRequests::iterator request_it = requests_.begin();
+ while (request_it != requests_.end()) {
+ if (request_it->second->requesting_process_id != render_process_id) {
+ ++request_it;
+ continue;
+ }
+
+ std::string label = request_it->first;
+ ++request_it;
+ CancelRequest(label);
+ }
+}
+
+void MediaStreamManager::StopStreamDevice(int render_process_id,
+ int render_view_id,
+ const std::string& device_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "StopStreamDevice({render_view_id = " << render_view_id << "} "
+ << ", {device_id = " << device_id << "})";
+ // Find the first request for this |render_process_id| and |render_view_id|
+ // of type MEDIA_GENERATE_STREAM that has requested to use |device_id| and
+ // stop it.
+ for (DeviceRequests::iterator request_it = requests_.begin();
+ request_it != requests_.end(); ++request_it) {
+ DeviceRequest* request = request_it->second;
+ if (request->requesting_process_id != render_process_id ||
+ request->requesting_view_id != render_view_id ||
+ request->request_type != MEDIA_GENERATE_STREAM) {
+ continue;
+ }
- // Find the request and close all open devices for the request.
- DeviceRequests::iterator it = requests_.find(label);
- if (it != requests_.end()) {
- if (it->second->request.request_type == MEDIA_ENUMERATE_DEVICES) {
- StopEnumerateDevices(label);
- return;
+ StreamDeviceInfoArray& devices = request->devices;
+ for (StreamDeviceInfoArray::iterator device_it = devices.begin();
+ device_it != devices.end(); ++device_it) {
+ if (device_it->device.id == device_id) {
+ StopDevice(device_it->device.type, device_it->session_id);
+ return;
+ }
}
+ }
+}
- scoped_ptr<DeviceRequest> request(it->second);
- RemoveRequest(it);
- for (StreamDeviceInfoArray::const_iterator device_it =
- request->devices.begin();
- device_it != request->devices.end(); ++device_it) {
- GetDeviceManager(device_it->device.type)->Close(device_it->session_id);
+void MediaStreamManager::StopDevice(MediaStreamType type, int session_id) {
+ DVLOG(1) << "StopDevice"
+ << "{type = " << type << "}"
+ << "{session_id = " << session_id << "}";
+ DeviceRequests::iterator request_it = requests_.begin();
+ while (request_it != requests_.end()) {
+ DeviceRequest* request = request_it->second;
+ StreamDeviceInfoArray* devices = &request->devices;
+ StreamDeviceInfoArray::iterator device_it = devices->begin();
+ while (device_it != devices->end()) {
+ if (device_it->device.type != type ||
+ device_it->session_id != session_id) {
+ ++device_it;
+ continue;
+ }
+ if (request->state(type) == MEDIA_REQUEST_STATE_DONE)
+ CloseDevice(type, session_id);
+ device_it = devices->erase(device_it);
}
- if (request->request.request_type == MEDIA_GENERATE_STREAM &&
- RequestDone(*request)) {
- // Notify observers that this device is being closed.
- for (int i = MEDIA_NO_SERVICE + 1; i != NUM_MEDIA_TYPES; ++i) {
- if (request->state(static_cast<MediaStreamType>(i)) !=
- MEDIA_REQUEST_STATE_NOT_REQUESTED) {
- request->SetState(static_cast<MediaStreamType>(i),
- MEDIA_REQUEST_STATE_CLOSING);
- }
+ // If this request doesn't have any active devices, remove the request.
+ if (devices->empty()) {
+ std::string label = request_it->first;
+ ++request_it;
+ DeleteRequest(label);
+ } else {
+ ++request_it;
+ }
+ }
+}
+
+void MediaStreamManager::CloseDevice(MediaStreamType type, int session_id) {
+ DVLOG(1) << "CloseDevice("
+ << "{type = " << type << "} "
+ << "{session_id = " << session_id << "})";
+ GetDeviceManager(type)->Close(session_id);
+
+ for (DeviceRequests::iterator request_it = requests_.begin();
+ request_it != requests_.end() ; ++request_it) {
+ StreamDeviceInfoArray* devices = &request_it->second->devices;
+ for (StreamDeviceInfoArray::iterator device_it = devices->begin();
+ device_it != devices->end(); ++device_it) {
+ if (device_it->session_id == session_id &&
+ device_it->device.type == type) {
+ // Notify observers that this device is being closed.
+ // Note that only one device per type can be opened.
+ request_it->second->SetState(type, MEDIA_REQUEST_STATE_CLOSING);
}
}
}
@@ -361,120 +541,176 @@ std::string MediaStreamManager::EnumerateDevices(
MediaStreamRequester* requester,
int render_process_id,
int render_view_id,
+ const ResourceContext::SaltCallback& sc,
int page_request_id,
MediaStreamType type,
const GURL& security_origin) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(requester);
DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
type == MEDIA_DEVICE_VIDEO_CAPTURE);
- // When the requester is NULL, the request is made by the UI to ensure MSM
- // starts monitoring devices.
- if (!requester) {
- if (!monitoring_started_)
- StartMonitoring();
+ DeviceRequest* request = new DeviceRequest(requester,
+ render_process_id,
+ render_view_id,
+ page_request_id,
+ security_origin,
+ MEDIA_ENUMERATE_DEVICES,
+ StreamOptions(),
+ sc);
+ if (IsAudioMediaType(type))
+ request->SetAudioType(type);
+ else if (IsVideoMediaType(type))
+ request->SetVideoType(type);
- return std::string();
- }
+ const std::string& label = AddRequest(request);
+ // Post a task and handle the request asynchronously. The reason is that the
+ // requester won't have a label for the request until this function returns
+ // and thus can not handle a response. Using base::Unretained is safe since
+ // MediaStreamManager is deleted on the UI thread, after the IO thread has
+ // been stopped.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&MediaStreamManager::DoEnumerateDevices,
+ base::Unretained(this), label));
+ return label;
+}
- // Create a new request.
- StreamOptions options;
- EnumerationCache* cache = NULL;
- if (type == MEDIA_DEVICE_AUDIO_CAPTURE) {
- options.audio_type = type;
+void MediaStreamManager::DoEnumerateDevices(const std::string& label) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DeviceRequest* request = FindRequest(label);
+ if (!request)
+ return; // This can happen if the request has been canceled.
+
+ MediaStreamType type;
+ EnumerationCache* cache;
+ if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE) {
+ DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type());
+ type = MEDIA_DEVICE_AUDIO_CAPTURE;
cache = &audio_enumeration_cache_;
- } else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) {
- options.video_type = type;
- cache = &video_enumeration_cache_;
} else {
- NOTREACHED();
- return std::string();
+ DCHECK_EQ(MEDIA_DEVICE_VIDEO_CAPTURE, request->video_type());
+ type = MEDIA_DEVICE_VIDEO_CAPTURE;
+ cache = &video_enumeration_cache_;
}
- MediaStreamRequest stream_request(
- render_process_id, render_view_id, page_request_id, std::string(),
- security_origin, MEDIA_ENUMERATE_DEVICES, std::string(), std::string(),
- options.audio_type, options.video_type);
- DeviceRequest* request = new DeviceRequest(requester, stream_request);
- const std::string& label = AddRequest(request);
-
if (cache->valid) {
// Cached device list of this type exists. Just send it out.
request->SetState(type, MEDIA_REQUEST_STATE_REQUESTED);
-
- // Need to post a task since the requester won't have label till
- // this function returns.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&MediaStreamManager::SendCachedDeviceList,
- base::Unretained(this), cache, label));
+ request->devices = cache->devices;
+ FinalizeEnumerateDevices(label, request);
} else {
StartEnumeration(request);
}
-
- return label;
+ DVLOG(1) << "Enumerate Devices ({label = " << label << "})";
}
-void MediaStreamManager::StopEnumerateDevices(const std::string& label) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- DeviceRequests::iterator it = requests_.find(label);
- if (it != requests_.end()) {
- DCHECK_EQ(it->second->request.request_type, MEDIA_ENUMERATE_DEVICES);
- // Delete the DeviceRequest.
- scoped_ptr<DeviceRequest> request(it->second);
- RemoveRequest(it);
- }
-}
-
-std::string MediaStreamManager::OpenDevice(
- MediaStreamRequester* requester,
- int render_process_id,
- int render_view_id,
- int page_request_id,
- const std::string& device_id,
- MediaStreamType type,
- const GURL& security_origin) {
+void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
+ int render_process_id,
+ int render_view_id,
+ const ResourceContext::SaltCallback& sc,
+ int page_request_id,
+ const std::string& device_id,
+ MediaStreamType type,
+ const GURL& security_origin) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
type == MEDIA_DEVICE_VIDEO_CAPTURE);
-
- // Create a new request.
+ DVLOG(1) << "OpenDevice ({page_request_id = " << page_request_id << "})";
StreamOptions options;
if (IsAudioMediaType(type)) {
- options.audio_type = type;
- options.audio_device_id = device_id;
+ options.audio_requested = true;
+ options.mandatory_audio.push_back(
+ StreamOptions::Constraint(kMediaStreamSourceInfoId, device_id));
} else if (IsVideoMediaType(type)) {
- options.video_type = type;
- options.video_device_id = device_id;
+ options.video_requested = true;
+ options.mandatory_video.push_back(
+ StreamOptions::Constraint(kMediaStreamSourceInfoId, device_id));
} else {
NOTREACHED();
- return std::string();
}
+ DeviceRequest* request = new DeviceRequest(requester,
+ render_process_id,
+ render_view_id,
+ page_request_id,
+ security_origin,
+ MEDIA_OPEN_DEVICE,
+ options,
+ sc);
- MediaStreamRequest stream_request(
- render_process_id, render_view_id, page_request_id, std::string(),
- security_origin, MEDIA_OPEN_DEVICE, options.audio_device_id,
- options.video_device_id, options.audio_type, options.video_type);
- DeviceRequest* request = new DeviceRequest(requester, stream_request);
const std::string& label = AddRequest(request);
- StartEnumeration(request);
-
- return label;
+ // Post a task and handle the request asynchronously. The reason is that the
+ // requester won't have a label for the request until this function returns
+ // and thus can not handle a response. Using base::Unretained is safe since
+ // MediaStreamManager is deleted on the UI thread, after the IO thread has
+ // been stopped.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&MediaStreamManager::SetupRequest,
+ base::Unretained(this), label));
}
-void MediaStreamManager::SendCachedDeviceList(
- EnumerationCache* cache,
- const std::string& label) {
+void MediaStreamManager::EnsureDeviceMonitorStarted() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (cache->valid) {
- DeviceRequests::iterator it = requests_.find(label);
- if (it != requests_.end()) {
- it->second->requester->DevicesEnumerated(label, cache->devices);
+ if (!monitoring_started_)
+ StartMonitoring();
+}
+
+void MediaStreamManager::StopRemovedDevices(
+ const StreamDeviceInfoArray& old_devices,
+ const StreamDeviceInfoArray& new_devices) {
+ DVLOG(1) << "StopRemovedDevices("
+ << "{#old_devices = " << old_devices.size() << "} "
+ << "{#new_devices = " << new_devices.size() << "})";
+ for (StreamDeviceInfoArray::const_iterator old_dev_it = old_devices.begin();
+ old_dev_it != old_devices.end(); ++old_dev_it) {
+ bool device_found = false;
+ StreamDeviceInfoArray::const_iterator new_dev_it = new_devices.begin();
+ for (; new_dev_it != new_devices.end(); ++new_dev_it) {
+ if (old_dev_it->device.id == new_dev_it->device.id) {
+ device_found = true;
+ break;
+ }
+ }
+
+ if (!device_found) {
+ // A device has been removed. We need to check if it is used by a
+ // MediaStream and in that case cleanup and notify the render process.
+ StopRemovedDevice(old_dev_it->device);
}
}
}
+void MediaStreamManager::StopRemovedDevice(const MediaStreamDevice& device) {
+ std::vector<int> session_ids;
+ for (DeviceRequests::const_iterator it = requests_.begin();
+ it != requests_.end() ; ++it) {
+ const DeviceRequest* request = it->second;
+ for (StreamDeviceInfoArray::const_iterator device_it =
+ request->devices.begin();
+ device_it != request->devices.end(); ++device_it) {
+ std::string source_id = content::GetHMACForMediaDeviceID(
+ request->salt_callback,
+ request->security_origin,
+ device.id);
+ if (device_it->device.id == source_id &&
+ device_it->device.type == device.type) {
+ session_ids.push_back(device_it->session_id);
+ if (it->second->requester) {
+ it->second->requester->DeviceStopped(
+ it->second->requesting_view_id,
+ it->first,
+ *device_it);
+ }
+ }
+ }
+ }
+ for (std::vector<int>::const_iterator it = session_ids.begin();
+ it != session_ids.end(); ++it) {
+ StopDevice(device.type, *it);
+ }
+}
+
void MediaStreamManager::StartMonitoring() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!base::SystemMonitor::Get())
@@ -503,16 +739,84 @@ void MediaStreamManager::StopMonitoring() {
}
}
-bool MediaStreamManager::TranslateGUIDToRawId(MediaStreamType stream_type,
- const GURL& security_origin,
- const std::string& device_guid,
- std::string* raw_device_id) {
+bool MediaStreamManager::GetRequestedDeviceCaptureId(
+ const DeviceRequest* request,
+ MediaStreamType type,
+ std::string* device_id) const {
+ DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ type == MEDIA_DEVICE_VIDEO_CAPTURE);
+ const StreamOptions::Constraints* mandatory =
+ (type == MEDIA_DEVICE_AUDIO_CAPTURE) ?
+ &request->options.mandatory_audio : &request->options.mandatory_video;
+ const StreamOptions::Constraints* optional =
+ (type == MEDIA_DEVICE_AUDIO_CAPTURE) ?
+ &request->options.optional_audio : &request->options.optional_video;
+
+ std::vector<std::string> source_ids;
+ StreamOptions::GetConstraintsByName(*mandatory,
+ kMediaStreamSourceInfoId, &source_ids);
+ if (source_ids.size() > 1) {
+ LOG(ERROR) << "Only one mandatory audio " << kMediaStreamSourceInfoId
+ << " is supported.";
+ return false;
+ }
+ // If a specific device has been requested we need to find the real device
+ // id.
+ if (source_ids.size() == 1 &&
+ !TranslateSourceIdToDeviceId(type,
+ request->salt_callback,
+ request->security_origin,
+ source_ids[0], device_id)) {
+ LOG(WARNING) << "Invalid mandatory audio " << kMediaStreamSourceInfoId
+ << " = " << source_ids[0] << ".";
+ return false;
+ }
+ // Check for optional audio sourceIDs.
+ if (device_id->empty()) {
+ StreamOptions::GetConstraintsByName(*optional,
+ kMediaStreamSourceInfoId,
+ &source_ids);
+ // Find the first sourceID that translates to device. Note that only one
+ // device per type can call to GenerateStream is ever opened.
+ for (std::vector<std::string>::const_iterator it = source_ids.begin();
+ it != source_ids.end(); ++it) {
+ if (TranslateSourceIdToDeviceId(type,
+ request->salt_callback,
+ request->security_origin,
+ *it,
+ device_id)) {
+ break;
+ }
+ }
+ }
+ return true;
+}
+
+void MediaStreamManager::TranslateDeviceIdToSourceId(
+ DeviceRequest* request,
+ MediaStreamDevice* device) {
+ if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE) {
+ device->id = content::GetHMACForMediaDeviceID(
+ request->salt_callback,
+ request->security_origin,
+ device->id);
+ }
+}
+
+bool MediaStreamManager::TranslateSourceIdToDeviceId(
+ MediaStreamType stream_type,
+ const ResourceContext::SaltCallback& sc,
+ const GURL& security_origin,
+ const std::string& source_id,
+ std::string* device_id) const {
DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
- if (device_guid.empty())
+ // The source_id can be empty if the constraint is set but empty.
+ if (source_id.empty())
return false;
- EnumerationCache* cache =
+ const EnumerationCache* cache =
stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
&audio_enumeration_cache_ : &video_enumeration_cache_;
@@ -523,9 +827,9 @@ bool MediaStreamManager::TranslateGUIDToRawId(MediaStreamType stream_type,
for (StreamDeviceInfoArray::const_iterator it = cache->devices.begin();
it != cache->devices.end();
++it) {
- if (DeviceRequestMessageFilter::DoesRawIdMatchGuid(
- security_origin, device_guid, it->device.id)) {
- *raw_device_id = it->device.id;
+ if (content::DoesMediaDeviceIDMatchHMAC(sc, security_origin, source_id,
+ it->device.id)) {
+ *device_id = it->device.id;
return true;
}
}
@@ -546,15 +850,22 @@ void MediaStreamManager::StartEnumeration(DeviceRequest* request) {
}
// Start enumeration for devices of all requested device types.
- for (int i = MEDIA_NO_SERVICE + 1; i < NUM_MEDIA_TYPES; ++i) {
- const MediaStreamType stream_type = static_cast<MediaStreamType>(i);
- if (Requested(request->request, stream_type)) {
- request->SetState(stream_type, MEDIA_REQUEST_STATE_REQUESTED);
- DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
- if (active_enumeration_ref_count_[stream_type] == 0) {
- ++active_enumeration_ref_count_[stream_type];
- GetDeviceManager(stream_type)->EnumerateDevices(stream_type);
- }
+ if (request->audio_type() != MEDIA_NO_SERVICE) {
+ const MediaStreamType stream_type = request->audio_type();
+ request->SetState(stream_type, MEDIA_REQUEST_STATE_REQUESTED);
+ DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
+ if (active_enumeration_ref_count_[stream_type] == 0) {
+ ++active_enumeration_ref_count_[stream_type];
+ GetDeviceManager(stream_type)->EnumerateDevices(stream_type);
+ }
+ }
+ if (request->video_type() != MEDIA_NO_SERVICE) {
+ const MediaStreamType stream_type = request->video_type();
+ request->SetState(stream_type, MEDIA_REQUEST_STATE_REQUESTED);
+ DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
+ if (active_enumeration_ref_count_[stream_type] == 0) {
+ ++active_enumeration_ref_count_[stream_type];
+ GetDeviceManager(stream_type)->EnumerateDevices(stream_type);
}
}
}
@@ -573,13 +884,32 @@ std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
return unique_label;
}
-void MediaStreamManager::RemoveRequest(DeviceRequests::iterator it) {
+MediaStreamManager::DeviceRequest*
+MediaStreamManager::FindRequest(const std::string& label) const {
+ DeviceRequests::const_iterator request_it = requests_.find(label);
+ return request_it == requests_.end() ? NULL : request_it->second;
+}
+
+void MediaStreamManager::DeleteRequest(const std::string& label) {
+ DeviceRequests::iterator it = requests_.find(label);
+ scoped_ptr<DeviceRequest> request(it->second);
requests_.erase(it);
}
-void MediaStreamManager::PostRequestToUI(const std::string& label) {
+void MediaStreamManager::PostRequestToUI(const std::string& label,
+ DeviceRequest* request) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DeviceRequest* request = requests_[label];
+ DCHECK(request->UIRequest());
+ DVLOG(1) << "PostRequestToUI({label= " << label << "})";
+
+ const MediaStreamType audio_type = request->audio_type();
+ const MediaStreamType video_type = request->video_type();
+
+ // Post the request to UI and set the state.
+ if (IsAudioMediaType(audio_type))
+ request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
+ if (IsVideoMediaType(video_type))
+ request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
if (use_fake_ui_) {
if (!fake_ui_)
@@ -609,42 +939,301 @@ void MediaStreamManager::PostRequestToUI(const std::string& label) {
}
request->ui_proxy->RequestAccess(
- request->request,
+ *request->UIRequest(),
base::Bind(&MediaStreamManager::HandleAccessRequestResponse,
base::Unretained(this), label));
}
-void MediaStreamManager::HandleRequest(const std::string& label) {
+void MediaStreamManager::SetupRequest(const std::string& label) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DeviceRequest* request = requests_[label];
+ DeviceRequest* request = FindRequest(label);
+ if (!request) {
+ DVLOG(1) << "SetupRequest label " << label << " doesn't exist!!";
+ return; // This can happen if the request has been canceled.
+ }
+
+ if (!request->security_origin.is_valid()) {
+ LOG(ERROR) << "Invalid security origin. "
+ << request->security_origin;
+ FinalizeRequestFailed(label, request);
+ return;
+ }
- const MediaStreamType audio_type = request->request.audio_type;
- const MediaStreamType video_type = request->request.video_type;
+ MediaStreamType audio_type = MEDIA_NO_SERVICE;
+ MediaStreamType video_type = MEDIA_NO_SERVICE;
+ ParseStreamType(request->options, &audio_type, &video_type);
+ request->SetAudioType(audio_type);
+ request->SetVideoType(video_type);
bool is_web_contents_capture =
audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
video_type == MEDIA_TAB_VIDEO_CAPTURE;
+ if (is_web_contents_capture && !SetupTabCaptureRequest(request)) {
+ FinalizeRequestFailed(label, request);
+ return;
+ }
bool is_screen_capture =
video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
+ if (is_screen_capture && !SetupScreenCaptureRequest(request)) {
+ FinalizeRequestFailed(label, request);
+ return;
+ }
- if (!is_web_contents_capture &&
- !is_screen_capture &&
- ((IsAudioMediaType(audio_type) && !audio_enumeration_cache_.valid) ||
- (IsVideoMediaType(video_type) && !video_enumeration_cache_.valid))) {
- // Enumerate the devices if there is no valid device lists to be used.
- StartEnumeration(request);
+ if (!is_web_contents_capture && !is_screen_capture) {
+ if ((!audio_enumeration_cache_.valid && IsAudioMediaType(audio_type)) ||
+ (!video_enumeration_cache_.valid && IsVideoMediaType(video_type))) {
+ // Enumerate the devices if there is no valid device lists to be used.
+ StartEnumeration(request);
+ return;
+ }
+ if (!SetupDeviceCaptureRequest(request)) {
+ FinalizeRequestFailed(label, request);
+ return;
+ }
+ }
+ PostRequestToUI(label, request);
+}
+
+bool MediaStreamManager::SetupDeviceCaptureRequest(DeviceRequest* request) {
+ DCHECK((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ request->audio_type() == MEDIA_NO_SERVICE) &&
+ (request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE ||
+ request->video_type() == MEDIA_NO_SERVICE));
+ std::string audio_device_id;
+ if (request->options.audio_requested &&
+ !GetRequestedDeviceCaptureId(request, request->audio_type(),
+ &audio_device_id)) {
+ return false;
+ }
+
+ std::string video_device_id;
+ if (request->options.video_requested &&
+ !GetRequestedDeviceCaptureId(request, request->video_type(),
+ &video_device_id)) {
+ return false;
+ }
+ request->CreateUIRequest(audio_device_id, video_device_id);
+ DVLOG(3) << "Audio requested " << request->options.audio_requested
+ << " device id = " << audio_device_id
+ << "Video requested " << request->options.video_requested
+ << " device id = " << video_device_id;
+ return true;
+}
+
+bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
+ DCHECK(request->audio_type() == MEDIA_TAB_AUDIO_CAPTURE ||
+ request->video_type() == MEDIA_TAB_VIDEO_CAPTURE);
+
+ std::string capture_device_id;
+ bool mandatory_audio = false;
+ bool mandatory_video = false;
+ if (!request->options.GetFirstAudioConstraintByName(kMediaStreamSourceId,
+ &capture_device_id,
+ &mandatory_audio) &&
+ !request->options.GetFirstVideoConstraintByName(kMediaStreamSourceId,
+ &capture_device_id,
+ &mandatory_video)) {
+ return false;
+ }
+ DCHECK(mandatory_audio || mandatory_video);
+
+ // Customize options for a WebContents based capture.
+ int target_render_process_id = 0;
+ int target_render_view_id = 0;
+
+ // TODO(justinlin): Can't plumb audio mirroring using stream type right
+ // now, so plumbing by device_id. Will revisit once it's refactored.
+ // http://crbug.com/163100
+ std::string tab_capture_device_id =
+ WebContentsCaptureUtil::AppendWebContentsDeviceScheme(capture_device_id);
+
+ bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget(
+ tab_capture_device_id, &target_render_process_id,
+ &target_render_view_id);
+ if (!has_valid_device_id ||
+ (request->audio_type() != MEDIA_TAB_AUDIO_CAPTURE &&
+ request->audio_type() != MEDIA_NO_SERVICE) ||
+ (request->video_type() != MEDIA_TAB_VIDEO_CAPTURE &&
+ request->video_type() != MEDIA_NO_SERVICE)) {
+ return false;
+ }
+
+ request->CreateTabCatureUIRequest(target_render_process_id,
+ target_render_view_id,
+ tab_capture_device_id);
+
+ DVLOG(3) << "SetupTabCaptureRequest "
+ << ", {tab_capture_device_id = " << tab_capture_device_id << "}"
+ << ", {target_render_process_id = " << target_render_process_id
+ << "}"
+ << ", {target_render_view_id = " << target_render_view_id << "}";
+ return true;
+}
+
+bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) {
+ DCHECK(request->audio_type() == MEDIA_LOOPBACK_AUDIO_CAPTURE ||
+ request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE);
+
+ // For screen capture we only support two valid combinations:
+ // (1) screen video capture only, or
+ // (2) screen video capture with loopback audio capture.
+ if (request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE ||
+ (request->audio_type() != MEDIA_NO_SERVICE &&
+ request->audio_type() != MEDIA_LOOPBACK_AUDIO_CAPTURE)) {
+ LOG(ERROR) << "Invalid screen capture request.";
+ return false;
+ }
+
+ std::string video_device_id;
+ if (request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE) {
+ std::string video_stream_source;
+ bool mandatory = false;
+ if (!request->options.GetFirstVideoConstraintByName(
+ kMediaStreamSource,
+ &video_stream_source,
+ &mandatory)) {
+ LOG(ERROR) << kMediaStreamSource << " not found.";
+ return false;
+ }
+ DCHECK(mandatory);
+
+ if (video_stream_source == kMediaStreamSourceDesktop) {
+ if (!request->options.GetFirstVideoConstraintByName(
+ kMediaStreamSourceId,
+ &video_device_id,
+ &mandatory)) {
+ LOG(ERROR) << kMediaStreamSourceId << " not found.";
+ return false;
+ }
+ DCHECK(mandatory);
+ }
+ }
+
+ request->CreateUIRequest("", video_device_id);
+ return true;
+}
+
+StreamDeviceInfoArray MediaStreamManager::GetDevicesOpenedByRequest(
+ const std::string& label) const {
+ DeviceRequest* request = FindRequest(label);
+ if (!request)
+ return StreamDeviceInfoArray();
+ return request->devices;
+}
+
+bool MediaStreamManager::FindExistingRequestedDeviceInfo(
+ const DeviceRequest& new_request,
+ const MediaStreamDevice& new_device_info,
+ StreamDeviceInfo* existing_device_info,
+ MediaRequestState* existing_request_state) const {
+ DCHECK(existing_device_info);
+ DCHECK(existing_request_state);
+
+ std::string source_id = content::GetHMACForMediaDeviceID(
+ new_request.salt_callback,
+ new_request.security_origin,
+ new_device_info.id);
+
+ for (DeviceRequests::const_iterator it = requests_.begin();
+ it != requests_.end() ; ++it) {
+ const DeviceRequest* request = it->second;
+ if (request->requesting_process_id == new_request.requesting_process_id &&
+ request->requesting_view_id == new_request.requesting_view_id &&
+ request->request_type == new_request.request_type) {
+ for (StreamDeviceInfoArray::const_iterator device_it =
+ request->devices.begin();
+ device_it != request->devices.end(); ++device_it) {
+ if (device_it->device.id == source_id &&
+ device_it->device.type == new_device_info.type) {
+ *existing_device_info = *device_it;
+ *existing_request_state = request->state(device_it->device.type);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void MediaStreamManager::FinalizeGenerateStream(const std::string& label,
+ DeviceRequest* request) {
+ DVLOG(1) << "FinalizeGenerateStream label " << label;
+ const StreamDeviceInfoArray& requested_devices = request->devices;
+
+ // Partition the array of devices into audio vs video.
+ StreamDeviceInfoArray audio_devices, video_devices;
+ for (StreamDeviceInfoArray::const_iterator device_it =
+ requested_devices.begin();
+ device_it != requested_devices.end(); ++device_it) {
+ if (IsAudioMediaType(device_it->device.type)) {
+ audio_devices.push_back(*device_it);
+ } else if (IsVideoMediaType(device_it->device.type)) {
+ video_devices.push_back(*device_it);
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ request->requester->StreamGenerated(
+ request->requesting_view_id,
+ request->page_request_id,
+ label, audio_devices, video_devices);
+}
+
+void MediaStreamManager::FinalizeRequestFailed(
+ const std::string& label,
+ DeviceRequest* request) {
+ if (request->requester)
+ request->requester->StreamGenerationFailed(
+ request->requesting_view_id,
+ request->page_request_id);
+
+ if (request->request_type == MEDIA_DEVICE_ACCESS &&
+ !request->callback.is_null()) {
+ request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass());
+ }
+
+ DeleteRequest(label);
+}
+
+void MediaStreamManager::FinalizeOpenDevice(const std::string& label,
+ DeviceRequest* request) {
+ const StreamDeviceInfoArray& requested_devices = request->devices;
+ request->requester->DeviceOpened(request->requesting_view_id,
+ request->page_request_id,
+ label, requested_devices.front());
+}
+
+void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
+ DeviceRequest* request) {
+ if (!request->security_origin.is_valid()) {
+ request->requester->DevicesEnumerated(
+ request->requesting_view_id,
+ request->page_request_id,
+ label,
+ StreamDeviceInfoArray());
return;
}
+ for (StreamDeviceInfoArray::iterator it = request->devices.begin();
+ it != request->devices.end(); ++it) {
+ TranslateDeviceIdToSourceId(request, &it->device);
+ }
+ request->requester->DevicesEnumerated(request->requesting_view_id,
+ request->page_request_id,
+ label,
+ request->devices);
+}
- // No need to do new device enumerations, post the request to UI
- // immediately.
- if (IsAudioMediaType(audio_type))
- request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
- if (IsVideoMediaType(video_type))
- request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
+void MediaStreamManager::FinalizeMediaAccessRequest(
+ const std::string& label,
+ DeviceRequest* request,
+ const MediaStreamDevices& devices) {
+ if (!request->callback.is_null())
+ request->callback.Run(devices, request->ui_proxy.Pass());
- PostRequestToUI(label);
+ // Delete the request since it is done.
+ DeleteRequest(label);
}
void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
@@ -670,67 +1259,36 @@ void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
// and the device managers.
io_loop_ = base::MessageLoop::current();
io_loop_->AddDestructionObserver(this);
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseFakeDeviceForMediaStream)) {
+ DVLOG(1) << "Using fake device";
+ UseFakeDevice();
+ }
}
void MediaStreamManager::Opened(MediaStreamType stream_type,
int capture_session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- // Find the request containing this device and mark it as used.
- DeviceRequest* request = NULL;
- StreamDeviceInfoArray* devices = NULL;
- std::string label;
+ DVLOG(1) << "Opened({stream_type = " << stream_type << "} "
+ << "{capture_session_id = " << capture_session_id << "})";
+ // Find the request(s) containing this device and mark it as used.
+ // It can be used in several requests since the same device can be
+ // requested from the same web page.
for (DeviceRequests::iterator request_it = requests_.begin();
- request_it != requests_.end() && request == NULL; ++request_it) {
- devices = &(request_it->second->devices);
+ request_it != requests_.end(); ++request_it) {
+ const std::string& label = request_it->first;
+ DeviceRequest* request = request_it->second;
+ StreamDeviceInfoArray* devices = &(request->devices);
for (StreamDeviceInfoArray::iterator device_it = devices->begin();
device_it != devices->end(); ++device_it) {
if (device_it->device.type == stream_type &&
device_it->session_id == capture_session_id) {
- // We've found the request.
- device_it->in_use = true;
- label = request_it->first;
- request = request_it->second;
- break;
- }
- }
- }
- if (request == NULL) {
- // The request doesn't exist.
- return;
- }
-
- DCHECK_NE(request->state(stream_type), MEDIA_REQUEST_STATE_REQUESTED);
-
- // Check if all devices for this stream type are opened. Update the state if
- // they are.
- for (StreamDeviceInfoArray::iterator device_it = devices->begin();
- device_it != devices->end(); ++device_it) {
- if (device_it->device.type != stream_type) {
- continue;
- }
- if (device_it->in_use == false) {
- // Wait for more devices to be opened before we're done.
- return;
- }
- }
-
- request->SetState(stream_type, MEDIA_REQUEST_STATE_DONE);
+ CHECK(request->state(device_it->device.type) ==
+ MEDIA_REQUEST_STATE_OPENING);
+ // We've found a matching request.
+ request->SetState(device_it->device.type, MEDIA_REQUEST_STATE_DONE);
- if (!RequestDone(*request)) {
- // This stream_type is done, but not the other type.
- return;
- }
-
- switch (request->request.request_type) {
- case MEDIA_OPEN_DEVICE:
- request->requester->DeviceOpened(label, devices->front());
- break;
- case MEDIA_GENERATE_STREAM: {
- // Partition the array of devices into audio vs video.
- StreamDeviceInfoArray audio_devices, video_devices;
- for (StreamDeviceInfoArray::iterator device_it = devices->begin();
- device_it != devices->end(); ++device_it) {
if (IsAudioMediaType(device_it->device.type)) {
// Store the native audio parameters in the device struct.
// TODO(xians): Handle the tab capture sample rate/channel layout
@@ -739,28 +1297,42 @@ void MediaStreamManager::Opened(MediaStreamType stream_type,
const StreamDeviceInfo* info =
audio_input_device_manager_->GetOpenedDeviceInfoById(
device_it->session_id);
- DCHECK_EQ(info->device.id, device_it->device.id);
device_it->device.input = info->device.input;
device_it->device.matched_output = info->device.matched_output;
}
- audio_devices.push_back(*device_it);
- } else if (IsVideoMediaType(device_it->device.type)) {
- video_devices.push_back(*device_it);
- } else {
- NOTREACHED();
}
+ if (RequestDone(*request))
+ HandleRequestDone(label, request);
+ break;
}
+ }
+ }
+}
+
+void MediaStreamManager::HandleRequestDone(const std::string& label,
+ DeviceRequest* request) {
+ DCHECK(RequestDone(*request));
+ DVLOG(1) << "HandleRequestDone("
+ << ", {label = " << label << "})";
- request->requester->StreamGenerated(label, audio_devices, video_devices);
- request->ui_proxy->OnStarted(
- base::Bind(&MediaStreamManager::StopStreamFromUI,
- base::Unretained(this), label));
+ switch (request->request_type) {
+ case MEDIA_OPEN_DEVICE:
+ FinalizeOpenDevice(label, request);
+ break;
+ case MEDIA_GENERATE_STREAM: {
+ FinalizeGenerateStream(label, request);
break;
}
default:
NOTREACHED();
break;
}
+
+ if (request->ui_proxy.get()) {
+ request->ui_proxy->OnStarted(
+ base::Bind(&MediaStreamManager::StopMediaStreamFromBrowser,
+ base::Unretained(this), label));
+ }
}
void MediaStreamManager::Closed(MediaStreamType stream_type,
@@ -771,6 +1343,8 @@ void MediaStreamManager::Closed(MediaStreamType stream_type,
void MediaStreamManager::DevicesEnumerated(
MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "DevicesEnumerated("
+ << ", {stream_type = " << stream_type << "})";
// Only cache the device list when the device list has been changed.
bool need_update_clients = false;
@@ -781,9 +1355,15 @@ void MediaStreamManager::DevicesEnumerated(
devices.size() != cache->devices.size() ||
!std::equal(devices.begin(), devices.end(), cache->devices.begin(),
StreamDeviceInfo::IsEqual)) {
- cache->valid = true;
+ StopRemovedDevices(cache->devices, devices);
cache->devices = devices;
need_update_clients = true;
+
+ // The device might not be able to be enumerated when it is not warmed up,
+ // for example, when the machine just wakes up from sleep. We set the cache
+ // to be invalid so that the next media request will trigger the
+ // enumeration again. See issue/317673.
+ cache->valid = !devices.empty();
}
if (need_update_clients && monitoring_started_)
@@ -797,33 +1377,37 @@ void MediaStreamManager::DevicesEnumerated(
for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
++it) {
if (it->second->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED &&
- Requested(it->second->request, stream_type)) {
- if (it->second->request.request_type != MEDIA_ENUMERATE_DEVICES)
+ (it->second->audio_type() == stream_type ||
+ it->second->video_type() == stream_type)) {
+ if (it->second->request_type != MEDIA_ENUMERATE_DEVICES)
it->second->SetState(stream_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
label_list.push_back(it->first);
}
}
for (std::list<std::string>::iterator it = label_list.begin();
it != label_list.end(); ++it) {
- DeviceRequest* request = requests_[*it];
- switch (request->request.request_type) {
+ DeviceRequest* request = FindRequest(*it);
+ switch (request->request_type) {
case MEDIA_ENUMERATE_DEVICES:
- if (need_update_clients && request->requester)
- request->requester->DevicesEnumerated(*it, devices);
+ if (need_update_clients && request->requester) {
+ request->devices = devices;
+ FinalizeEnumerateDevices(*it, request);
+ }
break;
default:
- if (request->state(request->request.audio_type) ==
+ if (request->state(request->audio_type()) ==
MEDIA_REQUEST_STATE_REQUESTED ||
- request->state(request->request.video_type) ==
+ request->state(request->video_type()) ==
MEDIA_REQUEST_STATE_REQUESTED) {
// We are doing enumeration for other type of media, wait until it is
// all done before posting the request to UI because UI needs
// the device lists to handle the request.
break;
}
-
- // Post the request to UI for permission approval.
- PostRequestToUI(*it);
+ if (!SetupDeviceCaptureRequest(request))
+ FinalizeRequestFailed(*it, request);
+ else
+ PostRequestToUI(*it, request);
break;
}
}
@@ -832,98 +1416,31 @@ void MediaStreamManager::DevicesEnumerated(
DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
}
-void MediaStreamManager::Error(MediaStreamType stream_type,
- int capture_session_id,
- MediaStreamProviderError error) {
- // Find the device for the error call.
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
- ++it) {
- StreamDeviceInfoArray& devices = it->second->devices;
-
- // TODO(miu): BUG. It's possible for the audio (or video) device array in
- // the "requester" to become out-of-sync with the order of devices we have
- // here. See http://crbug.com/147650
- int audio_device_idx = -1;
- int video_device_idx = -1;
- for (StreamDeviceInfoArray::iterator device_it = devices.begin();
- device_it != devices.end(); ++device_it) {
- if (IsAudioMediaType(device_it->device.type)) {
- ++audio_device_idx;
- } else if (IsVideoMediaType(device_it->device.type)) {
- ++video_device_idx;
- } else {
- NOTREACHED();
- continue;
- }
- if (device_it->device.type != stream_type ||
- device_it->session_id != capture_session_id) {
- continue;
- }
- // We've found the failing device. Find the error case:
- // An error should only be reported to the MediaStreamManager if
- // the request has not been fulfilled yet.
- DCHECK(it->second->state(stream_type) != MEDIA_REQUEST_STATE_DONE);
- if (it->second->state(stream_type) != MEDIA_REQUEST_STATE_DONE) {
- // Request is not done, devices are not opened in this case.
- if (devices.size() <= 1) {
- scoped_ptr<DeviceRequest> request(it->second);
- // 1. Device not opened and no other devices for this request ->
- // signal stream error and remove the request.
- if (request->requester)
- request->requester->StreamGenerationFailed(it->first);
-
- RemoveRequest(it);
- } else {
- // 2. Not opened but other devices exists for this request -> remove
- // device from list, but don't signal an error.
- devices.erase(device_it); // NOTE: This invalidates device_it!
- }
- }
- return;
- }
- }
-}
-
void MediaStreamManager::HandleAccessRequestResponse(
const std::string& label,
const MediaStreamDevices& devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "HandleAccessRequestResponse("
+ << ", {label = " << label << "})";
- DeviceRequests::iterator request_it = requests_.find(label);
- if (request_it == requests_.end()) {
+ DeviceRequest* request = FindRequest(label);
+ if (!request) {
+ // The request has been canceled before the UI returned.
return;
}
- // Handle the case when the request was denied.
- if (devices.empty()) {
- // Notify the users about the request result.
- scoped_ptr<DeviceRequest> request(request_it->second);
- if (request->requester)
- request->requester->StreamGenerationFailed(label);
-
- if (request->request.request_type == MEDIA_DEVICE_ACCESS &&
- !request->callback.is_null()) {
- request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass());
- }
-
- RemoveRequest(request_it);
+ if (request->request_type == MEDIA_DEVICE_ACCESS) {
+ FinalizeMediaAccessRequest(label, request, devices);
return;
}
- if (request_it->second->request.request_type == MEDIA_DEVICE_ACCESS) {
- scoped_ptr<DeviceRequest> request(request_it->second);
- if (!request->callback.is_null())
- request->callback.Run(devices, request->ui_proxy.Pass());
-
- // Delete the request since it is done.
- RemoveRequest(request_it);
+ // Handle the case when the request was denied.
+ if (devices.empty()) {
+ FinalizeRequestFailed(label, request);
return;
}
// Process all newly-accepted devices for this request.
- DeviceRequest* request = request_it->second;
bool found_audio = false;
bool found_video = false;
for (MediaStreamDevices::const_iterator device_it = devices.begin();
@@ -935,7 +1452,7 @@ void MediaStreamManager::HandleAccessRequestResponse(
// Re-append the device's id since we lost it when posting request to UI.
if (device_info.device.type == content::MEDIA_TAB_VIDEO_CAPTURE ||
device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE) {
- device_info.device.id = request->request.tab_capture_device_id;
+ device_info.device.id = request->UIRequest()->tab_capture_device_id;
// Initialize the sample_rate and channel_layout here since for audio
// mirroring, we don't go through EnumerateDevices where these are usually
@@ -954,43 +1471,73 @@ void MediaStreamManager::HandleAccessRequestResponse(
}
}
- // Set in_use to false to be able to track if this device has been
- // opened. in_use might be true if the device type can be used in more
- // than one session.
- device_info.in_use = false;
+ if (device_info.device.type == request->audio_type()) {
+ found_audio = true;
+ } else if (device_info.device.type == request->video_type()) {
+ found_video = true;
+ }
+ // If this is request for a new MediaStream, a device is only opened once
+ // per render view. This is so that the permission to use a device can be
+ // revoked by a single call to StopStreamDevice regardless of how many
+ // MediaStreams it is being used in.
+ if (request->request_type == MEDIA_GENERATE_STREAM) {
+ MediaRequestState state;
+ if (FindExistingRequestedDeviceInfo(*request,
+ device_info.device,
+ &device_info,
+ &state)) {
+ request->devices.push_back(device_info);
+ request->SetState(device_info.device.type, state);
+ DVLOG(1) << "HandleAccessRequestResponse - device already opened "
+ << ", {label = " << label << "}"
+ << ", device_id = " << device_it->id << "}";
+ continue;
+ }
+ }
device_info.session_id =
GetDeviceManager(device_info.device.type)->Open(device_info);
- request->SetState(device_info.device.type, MEDIA_REQUEST_STATE_OPENING);
+ TranslateDeviceIdToSourceId(request, &device_info.device);
request->devices.push_back(device_info);
- if (device_info.device.type == request->request.audio_type) {
- found_audio = true;
- } else if (device_info.device.type == request->request.video_type) {
- found_video = true;
- }
+ request->SetState(device_info.device.type, MEDIA_REQUEST_STATE_OPENING);
+ DVLOG(1) << "HandleAccessRequestResponse - opening device "
+ << ", {label = " << label << "}"
+ << ", {device_id = " << device_info.device.id << "}"
+ << ", {session_id = " << device_info.session_id << "}";
}
// Check whether we've received all stream types requested.
- if (!found_audio && IsAudioMediaType(request->request.audio_type))
- request->SetState(request->request.audio_type, MEDIA_REQUEST_STATE_ERROR);
+ if (!found_audio && IsAudioMediaType(request->audio_type())) {
+ request->SetState(request->audio_type(), MEDIA_REQUEST_STATE_ERROR);
+ DVLOG(1) << "Set no audio found label " << label;
+ }
+
+ if (!found_video && IsVideoMediaType(request->video_type()))
+ request->SetState(request->video_type(), MEDIA_REQUEST_STATE_ERROR);
- if (!found_video && IsVideoMediaType(request->request.video_type))
- request->SetState(request->request.video_type, MEDIA_REQUEST_STATE_ERROR);
+ if (RequestDone(*request))
+ HandleRequestDone(label, request);
}
-void MediaStreamManager::StopStreamFromUI(const std::string& label) {
+void MediaStreamManager::StopMediaStreamFromBrowser(const std::string& label) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DeviceRequests::iterator it = requests_.find(label);
- if (it == requests_.end())
+ DeviceRequest* request = FindRequest(label);
+ if (!request)
return;
- // Notify renderers that the stream has been stopped.
- if (it->second->requester)
- it->second->requester->StopGeneratedStream(label);
+ // Notify renderers that the devices in the stream will be stopped.
+ if (request->requester) {
+ for (StreamDeviceInfoArray::iterator device_it = request->devices.begin();
+ device_it != request->devices.end(); ++device_it) {
+ request->requester->DeviceStopped(request->requesting_view_id,
+ label,
+ *device_it);
+ }
+ }
- StopGeneratedStream(label);
+ CancelRequest(label);
}
void MediaStreamManager::UseFakeDevice() {
@@ -1006,6 +1553,7 @@ void MediaStreamManager::UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui) {
}
void MediaStreamManager::WillDestroyCurrentMessageLoop() {
+ DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()";
DCHECK_EQ(base::MessageLoop::current(), io_loop_);
DCHECK(requests_.empty());
if (device_thread_) {
@@ -1048,33 +1596,23 @@ void MediaStreamManager::NotifyDevicesChanged(
bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- const bool requested_audio = IsAudioMediaType(request.request.audio_type);
- const bool requested_video = IsVideoMediaType(request.request.video_type);
+ const bool requested_audio = IsAudioMediaType(request.audio_type());
+ const bool requested_video = IsVideoMediaType(request.video_type());
const bool audio_done =
!requested_audio ||
- request.state(request.request.audio_type) ==
- MEDIA_REQUEST_STATE_DONE ||
- request.state(request.request.audio_type) ==
- MEDIA_REQUEST_STATE_ERROR;
+ request.state(request.audio_type()) == MEDIA_REQUEST_STATE_DONE ||
+ request.state(request.audio_type()) == MEDIA_REQUEST_STATE_ERROR;
if (!audio_done)
return false;
const bool video_done =
!requested_video ||
- request.state(request.request.video_type) ==
- MEDIA_REQUEST_STATE_DONE ||
- request.state(request.request.video_type) ==
- MEDIA_REQUEST_STATE_ERROR;
+ request.state(request.video_type()) == MEDIA_REQUEST_STATE_DONE ||
+ request.state(request.video_type()) == MEDIA_REQUEST_STATE_ERROR;
if (!video_done)
return false;
- for (StreamDeviceInfoArray::const_iterator it = request.devices.begin();
- it != request.devices.end(); ++it) {
- if (it->in_use == false)
- return false;
- }
-
return true;
}
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 5a444ef4403..590d24171b6 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.h
@@ -34,6 +34,8 @@
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/common/content_export.h"
#include "content/common/media/media_stream_options.h"
+#include "content/public/browser/media_request_state.h"
+#include "content/public/browser/resource_context.h"
namespace base {
class Thread;
@@ -53,16 +55,14 @@ class MediaStreamUIProxy;
class VideoCaptureManager;
// MediaStreamManager is used to generate and close new media devices, not to
-// start the media flow.
-// The classes requesting new media streams are answered using
-// MediaStreamManager::Listener.
+// start the media flow. The classes requesting new media streams are answered
+// using MediaStreamRequester.
class CONTENT_EXPORT MediaStreamManager
: public MediaStreamProviderListener,
public base::MessageLoop::DestructionObserver,
public base::SystemMonitor::DevicesChangedObserver {
public:
- // Callback to deliver the result of a media request. |label| is the string
- // to identify the request,
+ // Callback to deliver the result of a media request.
typedef base::Callback<void(const MediaStreamDevices& devices,
scoped_ptr<MediaStreamUIProxy> ui)>
MediaRequestResponseCallback;
@@ -86,7 +86,7 @@ class CONTENT_EXPORT MediaStreamManager
int render_process_id,
int render_view_id,
int page_request_id,
- const StreamOptions& components,
+ const StreamOptions& options,
const GURL& security_origin,
const MediaRequestResponseCallback& callback);
@@ -94,17 +94,29 @@ class CONTENT_EXPORT MediaStreamManager
// creates a new request which is identified by a unique string that's
// returned to the caller. |render_process_id| and |render_view_id| refer to
// the view where the infobar will appear to the user.
- std::string GenerateStream(MediaStreamRequester* requester,
- int render_process_id,
- int render_view_id,
- int page_request_id,
- const StreamOptions& components,
- const GURL& security_origin);
-
- void CancelRequest(const std::string& label);
-
- // Closes generated stream.
- virtual void StopGeneratedStream(const std::string& label);
+ void GenerateStream(MediaStreamRequester* requester,
+ int render_process_id,
+ int render_view_id,
+ const ResourceContext::SaltCallback& sc,
+ int page_request_id,
+ const StreamOptions& components,
+ const GURL& security_origin);
+
+ void CancelRequest(int render_process_id,
+ int render_view_id,
+ int page_request_id);
+
+ // Cancel an open request identified by |label|.
+ virtual void CancelRequest(const std::string& label);
+
+ // Cancel all requests for the given |render_process_id|.
+ void CancelAllRequests(int render_process_id);
+
+ // Closes the stream device for a certain render view. The stream must have
+ // been opened by a call to GenerateStream.
+ void StopStreamDevice(int render_process_id,
+ int render_view_id,
+ const std::string& device_id);
// Gets a list of devices of |type|, which must be MEDIA_DEVICE_AUDIO_CAPTURE
// or MEDIA_DEVICE_VIDEO_CAPTURE.
@@ -116,6 +128,7 @@ class CONTENT_EXPORT MediaStreamManager
virtual std::string EnumerateDevices(MediaStreamRequester* requester,
int render_process_id,
int render_view_id,
+ const ResourceContext::SaltCallback& sc,
int page_request_id,
MediaStreamType type,
const GURL& security_origin);
@@ -123,13 +136,18 @@ class CONTENT_EXPORT MediaStreamManager
// Open a device identified by |device_id|. |type| must be either
// MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE.
// The request is identified using string returned to the caller.
- std::string OpenDevice(MediaStreamRequester* requester,
- int render_process_id,
- int render_view_id,
- int page_request_id,
- const std::string& device_id,
- MediaStreamType type,
- const GURL& security_origin);
+ void OpenDevice(MediaStreamRequester* requester,
+ int render_process_id,
+ int render_view_id,
+ const ResourceContext::SaltCallback& sc,
+ int page_request_id,
+ const std::string& device_id,
+ MediaStreamType type,
+ const GURL& security_origin);
+
+ // Called by UI to make sure the device monitor is started so that UI receive
+ // notifications about device changes.
+ void EnsureDeviceMonitorStarted();
// Implements MediaStreamProviderListener.
virtual void Opened(MediaStreamType stream_type,
@@ -138,9 +156,6 @@ class CONTENT_EXPORT MediaStreamManager
int capture_session_id) OVERRIDE;
virtual void DevicesEnumerated(MediaStreamType stream_type,
const StreamDeviceInfoArray& devices) OVERRIDE;
- virtual void Error(MediaStreamType stream_type,
- int capture_session_id,
- MediaStreamProviderError error) OVERRIDE;
// Implements base::SystemMonitor::DevicesChangedObserver.
virtual void OnDevicesChanged(
@@ -155,12 +170,19 @@ class CONTENT_EXPORT MediaStreamManager
// generated stream (or when using --use-fake-ui-for-media-stream).
void UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui);
+ // Returns all devices currently opened by a request with label |label|.
+ // If no request with |label| exist, an empty array is returned.
+ StreamDeviceInfoArray GetDevicesOpenedByRequest(
+ const std::string& label) const;
+
// This object gets deleted on the UI thread after the IO thread has been
// destroyed. So we need to know when IO thread is being destroyed so that
- // we can delete VideoCaptureManager and AudioInputDeviceManager.
- // We also must call this function explicitly in tests which use
- // TestBrowserThreadBundle, because the notification happens too late in that
- // case (see http://crbug.com/247525#c14).
+ // we can delete VideoCaptureManager and AudioInputDeviceManager. Normally
+ // this is handled by
+ // base::MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop.
+ // But for some tests which use TestBrowserThreadBundle, we need to call
+ // WillDestroyCurrentMessageLoop explicitly because the notification happens
+ // too late. (see http://crbug.com/247525#c14).
virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
protected:
@@ -191,40 +213,106 @@ class CONTENT_EXPORT MediaStreamManager
void NotifyDevicesChanged(MediaStreamType stream_type,
const StreamDeviceInfoArray& devices);
-
void HandleAccessRequestResponse(const std::string& label,
const MediaStreamDevices& devices);
- void StopStreamFromUI(const std::string& label);
+ void StopMediaStreamFromBrowser(const std::string& label);
+
+ void DoEnumerateDevices(const std::string& label);
// Helpers.
+ // Checks if all devices that was requested in the request identififed by
+ // |label| has been opened and set the request state accordingly.
+ void HandleRequestDone(const std::string& label,
+ DeviceRequest* request);
+ // Stop the use of the device associated with |session_id| of type |type| in
+ // all |requests_|. The device is removed from the request. If a request
+ /// doesn't use any devices as a consequence, the request is deleted.
+ void StopDevice(MediaStreamType type, int session_id);
+ // Calls the correct capture manager and close the device with |session_id|.
+ // All requests that uses the device are updated.
+ void CloseDevice(MediaStreamType type, int session_id);
+ // Returns true if a request for devices has been completed and the devices
+ // has either been opened or an error has occurred.
bool RequestDone(const DeviceRequest& request) const;
MediaStreamProvider* GetDeviceManager(MediaStreamType stream_type);
void StartEnumeration(DeviceRequest* request);
std::string AddRequest(DeviceRequest* request);
- void RemoveRequest(DeviceRequests::iterator it);
+ DeviceRequest* FindRequest(const std::string& label) const;
+ void DeleteRequest(const std::string& label);
void ClearEnumerationCache(EnumerationCache* cache);
- void PostRequestToUI(const std::string& label);
- void HandleRequest(const std::string& label);
-
- // Sends cached device list to a client corresponding to the request
- // identified by |label|.
- void SendCachedDeviceList(EnumerationCache* cache, const std::string& label);
-
- // Stop the request of enumerating devices indentified by |label|.
- void StopEnumerateDevices(const std::string& label);
+ // Prepare the request with label |label| by starting device enumeration if
+ // needed.
+ void SetupRequest(const std::string& label);
+ // Prepare |request| of type MEDIA_DEVICE_AUDIO_CAPTURE and/or
+ // MEDIA_DEVICE_VIDEO_CAPTURE for being posted to the UI by parsing
+ // StreamOptions::Constraints for requested device IDs.
+ bool SetupDeviceCaptureRequest(DeviceRequest* request);
+ // Prepare |request| of type MEDIA_TAB_AUDIO_CAPTURE and/or
+ // MEDIA_TAB_VIDEO_CAPTURE for being posted to the UI by parsing
+ // StreamOptions::Constraints for requested tab capture IDs.
+ bool SetupTabCaptureRequest(DeviceRequest* request);
+ // Prepare |request| of type MEDIA_LOOPBACK_AUDIO_CAPTURE and/or
+ // MEDIA_DESKTOP_VIDEO_CAPTURE for being posted to the UI by parsing
+ // StreamOptions::Constraints for the requested desktop ID.
+ bool SetupScreenCaptureRequest(DeviceRequest* request);
+ // Called when a request has been setup and devices have been enumerated if
+ // needed.
+ void PostRequestToUI(const std::string& label, DeviceRequest* request);
+ // Returns true if a device with |device_id| has already been requested with
+ // a render procecss_id and render_view_id and type equal to the the values
+ // in |request|. If it has been requested, |device_info| contain information
+ // about the device.
+ bool FindExistingRequestedDeviceInfo(
+ const DeviceRequest& new_request,
+ const MediaStreamDevice& new_device_info,
+ StreamDeviceInfo* existing_device_info,
+ MediaRequestState* existing_request_state) const;
+
+ void FinalizeGenerateStream(const std::string& label,
+ DeviceRequest* request);
+ void FinalizeRequestFailed(const std::string& label,
+ DeviceRequest* request);
+ void FinalizeOpenDevice(const std::string& label,
+ DeviceRequest* request);
+ void FinalizeMediaAccessRequest(const std::string& label,
+ DeviceRequest* request,
+ const MediaStreamDevices& devices);
+ void FinalizeEnumerateDevices(const std::string& label,
+ DeviceRequest* request);
+
+ // This method is called when an audio or video device is plugged in or
+ // removed. It make sure all MediaStreams that use a removed device is
+ // stopped and that the render process is notified. |old_devices| is the list
+ // of previously available devices. |new_devices| is the new
+ // list of currently available devices.
+ void StopRemovedDevices(const StreamDeviceInfoArray& old_devices,
+ const StreamDeviceInfoArray& new_devices);
+ // Helper method used by StopRemovedDevices to stop the use of a certain
+ // device.
+ void StopRemovedDevice(const MediaStreamDevice& device);
// Helpers to start and stop monitoring devices.
void StartMonitoring();
void StopMonitoring();
- // Finds and returns the raw device id corresponding to the given
- // |device_guid|. Returns true if there was a raw device id that matched the
- // given |device_guid|, false if nothing matched it.
- bool TranslateGUIDToRawId(
+ // Finds the requested device id from constraints. The requested device type
+ // must be MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE.
+ bool GetRequestedDeviceCaptureId(const DeviceRequest* request,
+ MediaStreamType type,
+ std::string* device_id) const;
+
+ void TranslateDeviceIdToSourceId(DeviceRequest* request,
+ MediaStreamDevice* device);
+
+ // Finds and returns the device id corresponding to the given
+ // |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 GURL& security_origin,
- const std::string& device_guid,
- std::string* raw_device_id);
+ const std::string& source_id,
+ std::string* device_id) const;
// Device thread shared by VideoCaptureManager and AudioInputDeviceManager.
scoped_ptr<base::Thread> device_thread_;
@@ -252,8 +340,6 @@ class CONTENT_EXPORT MediaStreamManager
// managers on the right thread.
base::MessageLoop* io_loop_;
- bool screen_capture_active_;
-
bool use_fake_ui_;
scoped_ptr<FakeMediaStreamUIProxy> fake_ui_;
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 a67237a1ed9..be4d498f87d 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
@@ -13,30 +13,36 @@
#include "content/common/media/media_stream_options.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_manager_base.h"
-#if defined(OS_ANDROID)
+#include "media/audio/fake_audio_log_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(USE_ALSA)
+#include "media/audio/alsa/audio_manager_alsa.h"
+#elif defined(OS_ANDROID)
#include "media/audio/android/audio_manager_android.h"
-#elif defined(OS_LINUX) || defined(OS_OPENBSD)
-#include "media/audio/linux/audio_manager_linux.h"
#elif defined(OS_MACOSX)
#include "media/audio/mac/audio_manager_mac.h"
#elif defined(OS_WIN)
#include "media/audio/win/audio_manager_win.h"
+#else
+#include "media/audio/fake_audio_manager.h"
#endif
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
namespace content {
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
-typedef media::AudioManagerLinux AudioManagerPlatform;
+#if defined(USE_ALSA)
+typedef media::AudioManagerAlsa AudioManagerPlatform;
#elif defined(OS_MACOSX)
typedef media::AudioManagerMac AudioManagerPlatform;
#elif defined(OS_WIN)
typedef media::AudioManagerWin AudioManagerPlatform;
#elif defined(OS_ANDROID)
typedef media::AudioManagerAndroid AudioManagerPlatform;
+#else
+typedef media::FakeAudioManager AudioManagerPlatform;
#endif
@@ -45,7 +51,7 @@ typedef media::AudioManagerAndroid AudioManagerPlatform;
// the buildbots. media::AudioManagerBase
class MockAudioManager : public AudioManagerPlatform {
public:
- MockAudioManager() {}
+ MockAudioManager() : AudioManagerPlatform(&fake_audio_log_factory_) {}
virtual ~MockAudioManager() {}
virtual void GetAudioInputDeviceNames(
@@ -60,6 +66,7 @@ class MockAudioManager : public AudioManagerPlatform {
}
private:
+ media::FakeAudioLogFactory fake_audio_log_factory_;
DISALLOW_COPY_AND_ASSIGN(MockAudioManager);
};
@@ -77,7 +84,6 @@ class MediaStreamManagerTest : public ::testing::Test {
}
virtual ~MediaStreamManagerTest() {
- media_stream_manager_->WillDestroyCurrentMessageLoop();
}
MOCK_METHOD1(Response, void(int index));
@@ -93,16 +99,15 @@ class MediaStreamManagerTest : public ::testing::Test {
const int render_process_id = 1;
const int render_view_id = 1;
const int page_request_id = 1;
- StreamOptions components(MEDIA_DEVICE_AUDIO_CAPTURE,
- MEDIA_DEVICE_VIDEO_CAPTURE);
const GURL security_origin;
MediaStreamManager::MediaRequestResponseCallback callback =
base::Bind(&MediaStreamManagerTest::ResponseCallback,
base::Unretained(this), index);
+ StreamOptions options(true, true);
return media_stream_manager_->MakeMediaAccessRequest(render_process_id,
render_view_id,
page_request_id,
- components,
+ options,
security_origin,
callback);
}
@@ -129,6 +134,8 @@ TEST_F(MediaStreamManagerTest, MakeAndCancelMediaAccessRequest) {
std::string label = MakeMediaAccessRequest(0);
// No callback is expected.
media_stream_manager_->CancelRequest(label);
+ run_loop_.RunUntilIdle();
+ media_stream_manager_->WillDestroyCurrentMessageLoop();
}
TEST_F(MediaStreamManagerTest, MakeMultipleRequests) {
@@ -139,9 +146,8 @@ TEST_F(MediaStreamManagerTest, MakeMultipleRequests) {
int render_process_id = 2;
int render_view_id = 2;
int page_request_id = 2;
- StreamOptions components(MEDIA_DEVICE_AUDIO_CAPTURE,
- MEDIA_DEVICE_VIDEO_CAPTURE);
GURL security_origin;
+ StreamOptions options(true, true);
MediaStreamManager::MediaRequestResponseCallback callback =
base::Bind(&MediaStreamManagerTest::ResponseCallback,
base::Unretained(this), 1);
@@ -149,7 +155,7 @@ TEST_F(MediaStreamManagerTest, MakeMultipleRequests) {
render_process_id,
render_view_id,
page_request_id,
- components,
+ options,
security_origin,
callback);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_provider.h b/chromium/content/browser/renderer_host/media/media_stream_provider.h
index 7f0ff17eb34..3389388d8df 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_provider.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_provider.h
@@ -52,11 +52,6 @@ class CONTENT_EXPORT MediaStreamProviderListener {
virtual void DevicesEnumerated(MediaStreamType stream_type,
const StreamDeviceInfoArray& devices) = 0;
- // Called by a MediaStreamProvider when an error has occured.
- virtual void Error(MediaStreamType stream_type,
- int capture_session_id,
- MediaStreamProviderError error) = 0;
-
protected:
virtual ~MediaStreamProviderListener() {}
};
diff --git a/chromium/content/browser/renderer_host/media/media_stream_requester.h b/chromium/content/browser/renderer_host/media/media_stream_requester.h
index 50858fa3393..146ef1a489e 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_requester.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_requester.h
@@ -18,20 +18,29 @@ namespace content {
class CONTENT_EXPORT MediaStreamRequester {
public:
// Called as a reply of a successful call to GenerateStream.
- virtual void StreamGenerated(const std::string& label,
+ virtual void StreamGenerated(int render_view_id,
+ int page_request_id,
+ const std::string& label,
const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices) = 0;
// Called if GenerateStream failed.
- virtual void StreamGenerationFailed(const std::string& label) = 0;
-
- // Called if stream has been stopped by user request.
- virtual void StopGeneratedStream(const std::string& label) = 0;
-
+ virtual void StreamGenerationFailed(int render_view_id,
+ int page_request_id) = 0;
+ // Called if a device has been stopped by a user from UI or the device
+ // has become unavailable. |render_view_id| is the render view that requested
+ // the device and |label| is the label of the request|.
+ virtual void DeviceStopped(int render_view_id,
+ const std::string& label,
+ const StreamDeviceInfo& device) = 0;
// Called as a reply of a successful call to EnumerateDevices.
- virtual void DevicesEnumerated(const std::string& label,
+ virtual void DevicesEnumerated(int render_view_id,
+ int page_request_id,
+ const std::string& label,
const StreamDeviceInfoArray& devices) = 0;
// Called as a reply of a successful call to OpenDevice.
- virtual void DeviceOpened(const std::string& label,
+ virtual void DeviceOpened(int render_view_id,
+ int page_request_id,
+ const std::string& label,
const StreamDeviceInfo& device_info) = 0;
protected:
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
index 00a2cc25270..f65936eff74 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
@@ -58,9 +58,7 @@ class MediaStreamDeviceUIControllerTest
void CreateDummyRequest(const std::string& label, bool audio, bool video) {
int dummy_render_process_id = 1;
int dummy_render_view_id = 1;
- StreamOptions components(
- audio ? MEDIA_DEVICE_AUDIO_CAPTURE : MEDIA_NO_SERVICE,
- video ? MEDIA_DEVICE_VIDEO_CAPTURE : MEDIA_NO_SERVICE);
+ StreamOptions components(audio, video );
GURL security_origin;
ui_controller_->MakeUIRequest(label,
dummy_render_process_id,
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
index 3e4edbc0ac0..b91ccb12095 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
@@ -193,12 +193,16 @@ void FakeMediaStreamUIProxy::RequestAccess(
it != devices_.end(); ++it) {
if (!accepted_audio &&
IsAudioMediaType(request.audio_type) &&
- IsAudioMediaType(it->type)) {
+ IsAudioMediaType(it->type) &&
+ (request.requested_audio_device_id.empty() ||
+ request.requested_audio_device_id == it->id)) {
devices_to_use.push_back(*it);
accepted_audio = true;
} else if (!accepted_video &&
IsVideoMediaType(request.video_type) &&
- IsVideoMediaType(it->type)) {
+ IsVideoMediaType(it->type) &&
+ (request.requested_video_device_id.empty() ||
+ request.requested_video_device_id == it->id)) {
devices_to_use.push_back(*it);
accepted_video = true;
}
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
index 82219a6e872..bff55c618cc 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
@@ -92,7 +92,7 @@ MATCHER_P(SameRequest, expected, "") {
}
TEST_F(MediaStreamUIProxyTest, Deny) {
- MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"),
+ MediaStreamRequest request(0, 0, 0, GURL("http://origin/"),
MEDIA_GENERATE_STREAM, std::string(),
std::string(),
MEDIA_DEVICE_AUDIO_CAPTURE,
@@ -118,7 +118,7 @@ TEST_F(MediaStreamUIProxyTest, Deny) {
}
TEST_F(MediaStreamUIProxyTest, AcceptAndStart) {
- MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"),
+ MediaStreamRequest request(0, 0, 0, GURL("http://origin/"),
MEDIA_GENERATE_STREAM, std::string(),
std::string(),
MEDIA_DEVICE_AUDIO_CAPTURE,
@@ -152,7 +152,7 @@ TEST_F(MediaStreamUIProxyTest, AcceptAndStart) {
// Verify that the proxy can be deleted before the request is processed.
TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) {
- MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"),
+ MediaStreamRequest request(0, 0, 0, GURL("http://origin/"),
MEDIA_GENERATE_STREAM, std::string(),
std::string(),
MEDIA_DEVICE_AUDIO_CAPTURE,
@@ -174,7 +174,7 @@ TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) {
}
TEST_F(MediaStreamUIProxyTest, StopFromUI) {
- MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"),
+ MediaStreamRequest request(0, 0, 0, GURL("http://origin/"),
MEDIA_GENERATE_STREAM, std::string(),
std::string(),
MEDIA_DEVICE_AUDIO_CAPTURE,
diff --git a/chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc b/chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc
index 53f5a769313..2181dccdd72 100644
--- a/chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/media/midi_dispatcher_host.cc
@@ -29,6 +29,8 @@ bool MIDIDispatcherHost::OnMessageReceived(const IPC::Message& message,
IPC_BEGIN_MESSAGE_MAP_EX(MIDIDispatcherHost, message, *message_was_ok)
IPC_MESSAGE_HANDLER(MIDIHostMsg_RequestSysExPermission,
OnRequestSysExPermission)
+ IPC_MESSAGE_HANDLER(MIDIHostMsg_CancelSysExPermissionRequest,
+ OnCancelSysExPermissionRequest)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
return handled;
@@ -36,31 +38,42 @@ bool MIDIDispatcherHost::OnMessageReceived(const IPC::Message& message,
void MIDIDispatcherHost::OverrideThreadForMessage(
const IPC::Message& message, BrowserThread::ID* thread) {
- if (message.type() == MIDIHostMsg_RequestSysExPermission::ID)
+ if (IPC_MESSAGE_CLASS(message) == MIDIMsgStart)
*thread = BrowserThread::UI;
}
void MIDIDispatcherHost::OnRequestSysExPermission(int render_view_id,
- int client_id,
+ int bridge_id,
const GURL& origin) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
browser_context_->RequestMIDISysExPermission(
render_process_id_,
render_view_id,
+ bridge_id,
origin,
base::Bind(&MIDIDispatcherHost::WasSysExPermissionGranted,
base::Unretained(this),
render_view_id,
- client_id));
+ bridge_id));
}
+void MIDIDispatcherHost::OnCancelSysExPermissionRequest(
+ int render_view_id,
+ int bridge_id,
+ const GURL& requesting_frame) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":" << render_view_id
+ << ":" << bridge_id;
+ browser_context_->CancelMIDISysExPermissionRequest(
+ render_process_id_, render_view_id, bridge_id, requesting_frame);
+}
void MIDIDispatcherHost::WasSysExPermissionGranted(int render_view_id,
- int client_id,
+ int bridge_id,
bool success) {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantSendMIDISysExMessage(
render_process_id_);
- Send(new MIDIMsg_SysExPermissionApproved(render_view_id, client_id, success));
+ Send(new MIDIMsg_SysExPermissionApproved(render_view_id, bridge_id, success));
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/midi_dispatcher_host.h b/chromium/content/browser/renderer_host/media/midi_dispatcher_host.h
index ee861551b44..068f71918f5 100644
--- a/chromium/content/browser/renderer_host/media/midi_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/media/midi_dispatcher_host.h
@@ -31,10 +31,13 @@ class MIDIDispatcherHost : public BrowserMessageFilter {
private:
void OnRequestSysExPermission(int render_view_id,
- int client_id,
+ int bridge_id,
const GURL& origin);
+ void OnCancelSysExPermissionRequest(int render_view_id,
+ int bridge_id,
+ const GURL& requesting_frame);
void WasSysExPermissionGranted(int render_view_id,
- int client_id,
+ int bridge_id,
bool success);
int render_process_id_;
diff --git a/chromium/content/browser/renderer_host/media/midi_host.cc b/chromium/content/browser/renderer_host/media/midi_host.cc
index 0467404bda3..d6781f61df5 100644
--- a/chromium/content/browser/renderer_host/media/midi_host.cc
+++ b/chromium/content/browser/renderer_host/media/midi_host.cc
@@ -16,26 +16,41 @@
#include "content/public/browser/media_observer.h"
#include "content/public/browser/user_metrics.h"
#include "media/midi/midi_manager.h"
+#include "media/midi/midi_message_queue.h"
+#include "media/midi/midi_message_util.h"
using media::MIDIManager;
using media::MIDIPortInfoList;
+namespace content {
+namespace {
+
// The total number of bytes which we're allowed to send to the OS
// before knowing that they have been successfully sent.
-static const size_t kMaxInFlightBytes = 10 * 1024 * 1024; // 10 MB.
+const size_t kMaxInFlightBytes = 10 * 1024 * 1024; // 10 MB.
// We keep track of the number of bytes successfully sent to
// the hardware. Every once in a while we report back to the renderer
// the number of bytes sent since the last report. This threshold determines
// how many bytes will be sent before reporting back to the renderer.
-static const size_t kAcknowledgementThresholdBytes = 1024 * 1024; // 1 MB.
+const size_t kAcknowledgementThresholdBytes = 1024 * 1024; // 1 MB.
-static const uint8 kSysExMessage = 0xf0;
+const uint8 kSysExMessage = 0xf0;
+const uint8 kEndOfSysExMessage = 0xf7;
-namespace content {
+bool IsDataByte(uint8 data) {
+ return (data & 0x80) == 0;
+}
+
+bool IsSystemRealTimeMessage(uint8 data) {
+ return 0xf8 <= data && data <= 0xff;
+}
+
+} // namespace
MIDIHost::MIDIHost(int renderer_process_id, media::MIDIManager* midi_manager)
: renderer_process_id_(renderer_process_id),
+ has_sys_ex_permission_(false),
midi_manager_(midi_manager),
sent_bytes_in_flight_(0),
bytes_sent_since_last_acknowledgement_(0) {
@@ -46,12 +61,6 @@ MIDIHost::~MIDIHost() {
midi_manager_->EndSession(this);
}
-void MIDIHost::OnChannelClosing() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- BrowserMessageFilter::OnChannelClosing();
-}
-
void MIDIHost::OnDestruct() const {
BrowserThread::DeleteOnIOThread::Destruct(this);
}
@@ -81,6 +90,12 @@ void MIDIHost::OnStartSession(int client_id) {
if (success) {
input_ports = midi_manager_->input_ports();
output_ports = midi_manager_->output_ports();
+ received_messages_queues_.clear();
+ received_messages_queues_.resize(input_ports.size());
+ // ChildSecurityPolicy is set just before OnStartSession by
+ // MIDIDispatcherHost. So we can safely cache the policy.
+ has_sys_ex_permission_ = ChildProcessSecurityPolicyImpl::GetInstance()->
+ CanSendMIDISysExMessage(renderer_process_id_);
}
}
@@ -100,32 +115,26 @@ void MIDIHost::OnSendData(uint32 port,
if (data.empty())
return;
- base::AutoLock auto_lock(in_flight_lock_);
-
- // Sanity check that we won't send too much.
- if (sent_bytes_in_flight_ > kMaxInFlightBytes ||
- data.size() > kMaxInFlightBytes ||
- data.size() + sent_bytes_in_flight_ > kMaxInFlightBytes)
+ // Blink running in a renderer checks permission to raise a SecurityError
+ // in JavaScript. The actual permission check for security purposes
+ // happens here in the browser process.
+ if (!has_sys_ex_permission_ &&
+ (std::find(data.begin(), data.end(), kSysExMessage) != data.end())) {
+ RecordAction(UserMetricsAction("BadMessageTerminate_MIDI"));
+ BadMessageReceived();
return;
-
- if (data[0] >= kSysExMessage) {
- // Blink running in a renderer checks permission to raise a SecurityError in
- // JavaScript. The actual permission check for security perposes happens
- // here in the browser process.
- if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanSendMIDISysExMessage(
- renderer_process_id_)) {
- RecordAction(UserMetricsAction("BadMessageTerminate_MIDI"));
- BadMessageReceived();
- return;
- }
}
- midi_manager_->DispatchSendMIDIData(
- this,
- port,
- data,
- timestamp);
+ if (!IsValidWebMIDIData(data))
+ return;
+ base::AutoLock auto_lock(in_flight_lock_);
+ // Sanity check that we won't send too much data.
+ // TODO(yukawa): Consider to send an error event back to the renderer
+ // after some future discussion in W3C.
+ if (data.size() + sent_bytes_in_flight_ > kMaxInFlightBytes)
+ return;
+ midi_manager_->DispatchSendMIDIData(this, port, data, timestamp);
sent_bytes_in_flight_ += data.size();
}
@@ -136,20 +145,29 @@ void MIDIHost::ReceiveMIDIData(
double timestamp) {
TRACE_EVENT0("midi", "MIDIHost::ReceiveMIDIData");
- // Check a process security policy to receive a system exclusive message.
- if (length > 0 && data[0] >= kSysExMessage) {
- if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanSendMIDISysExMessage(
- renderer_process_id_)) {
- // MIDI devices may send a system exclusive messages even if the renderer
- // doesn't have a permission to receive it. Don't kill the renderer as
- // OnSendData() does.
- return;
- }
- }
+ if (received_messages_queues_.size() <= port)
+ return;
- // Send to the renderer.
- std::vector<uint8> v(data, data + length);
- Send(new MIDIMsg_DataReceived(port, v, timestamp));
+ // Lazy initialization
+ if (received_messages_queues_[port] == NULL)
+ received_messages_queues_[port] = new media::MIDIMessageQueue(true);
+
+ received_messages_queues_[port]->Add(data, length);
+ std::vector<uint8> message;
+ while (true) {
+ received_messages_queues_[port]->Get(&message);
+ if (message.empty())
+ break;
+
+ // MIDI devices may send a system exclusive messages even if the renderer
+ // doesn't have a permission to receive it. Don't kill the renderer as
+ // OnSendData() does.
+ if (message[0] == kSysExMessage && !has_sys_ex_permission_)
+ continue;
+
+ // Send to the renderer.
+ Send(new MIDIMsg_DataReceived(port, message, timestamp));
+ }
}
void MIDIHost::AccumulateMIDIBytesSent(size_t n) {
@@ -171,4 +189,37 @@ void MIDIHost::AccumulateMIDIBytesSent(size_t n) {
}
}
+// static
+bool MIDIHost::IsValidWebMIDIData(const std::vector<uint8>& data) {
+ bool in_sysex = false;
+ size_t waiting_data_length = 0;
+ for (size_t i = 0; i < data.size(); ++i) {
+ const uint8 current = data[i];
+ if (IsSystemRealTimeMessage(current))
+ continue; // Real time message can be placed at any point.
+ if (waiting_data_length > 0) {
+ if (!IsDataByte(current))
+ return false; // Error: |current| should have been data byte.
+ --waiting_data_length;
+ continue; // Found data byte as expected.
+ }
+ if (in_sysex) {
+ if (data[i] == kEndOfSysExMessage)
+ in_sysex = false;
+ else if (!IsDataByte(current))
+ return false; // Error: |current| should have been data byte.
+ continue; // Found data byte as expected.
+ }
+ if (current == kSysExMessage) {
+ in_sysex = true;
+ continue; // Found SysEX
+ }
+ waiting_data_length = media::GetMIDIMessageLength(current);
+ if (waiting_data_length == 0)
+ return false; // Error: |current| should have been a valid status byte.
+ --waiting_data_length; // Found status byte
+ }
+ return waiting_data_length == 0 && !in_sysex;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/midi_host.h b/chromium/content/browser/renderer_host/media/midi_host.h
index 944325d99a0..153863fe603 100644
--- a/chromium/content/browser/renderer_host/media/midi_host.h
+++ b/chromium/content/browser/renderer_host/media/midi_host.h
@@ -7,8 +7,10 @@
#include <vector>
+#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
@@ -16,6 +18,7 @@
namespace media {
class MIDIManager;
+class MIDIMessageQueue;
}
namespace content {
@@ -28,17 +31,15 @@ class CONTENT_EXPORT MIDIHost
MIDIHost(int renderer_process_id, media::MIDIManager* midi_manager);
// BrowserMessageFilter implementation.
- virtual void OnChannelClosing() OVERRIDE;
virtual void OnDestruct() const OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) OVERRIDE;
// MIDIManagerClient implementation.
- virtual void ReceiveMIDIData(
- uint32 port,
- const uint8* data,
- size_t length,
- double timestamp) OVERRIDE;
+ virtual void ReceiveMIDIData(uint32 port,
+ const uint8* data,
+ size_t length,
+ double timestamp) OVERRIDE;
virtual void AccumulateMIDIBytesSent(size_t n) OVERRIDE;
// Start session to access MIDI hardware.
@@ -50,13 +51,25 @@ class CONTENT_EXPORT MIDIHost
double timestamp);
private:
+ FRIEND_TEST_ALL_PREFIXES(MIDIHostTest, IsValidWebMIDIData);
friend class base::DeleteHelper<MIDIHost>;
friend class BrowserThread;
virtual ~MIDIHost();
+ // Returns true if |data| fulfills the requirements of MIDIOutput.send API
+ // defined in the WebMIDI spec.
+ // - |data| must be any number of complete MIDI messages (data abbreviation
+ // called "running status" is disallowed).
+ // - 1-byte MIDI realtime messages can be placed at any position of |data|.
+ static bool IsValidWebMIDIData(const std::vector<uint8>& data);
+
int renderer_process_id_;
+ // Represents if the renderer has a permission to send/receive MIDI SysEX
+ // messages.
+ bool has_sys_ex_permission_;
+
// |midi_manager_| talks to the platform-specific MIDI APIs.
// It can be NULL if the platform (or our current implementation)
// does not support MIDI. If not supported then a call to
@@ -64,6 +77,9 @@ class CONTENT_EXPORT MIDIHost
// OnSendData() will do nothing.
media::MIDIManager* const midi_manager_;
+ // Buffers where data sent from each MIDI input port is stored.
+ ScopedVector<media::MIDIMessageQueue> received_messages_queues_;
+
// The number of bytes sent to the platform-specific MIDI sending
// system, but not yet completed.
size_t sent_bytes_in_flight_;
diff --git a/chromium/content/browser/renderer_host/media/midi_host_unittest.cc b/chromium/content/browser/renderer_host/media/midi_host_unittest.cc
new file mode 100644
index 00000000000..fedb4265b9b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/midi_host_unittest.cc
@@ -0,0 +1,90 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/media/midi_host.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+const uint8 kGMOn[] = { 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7 };
+const uint8 kGSOn[] = {
+ 0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41, 0xf7,
+};
+const uint8 kNoteOn[] = { 0x90, 0x3c, 0x7f };
+const uint8 kNoteOnWithRunningStatus[] = {
+ 0x90, 0x3c, 0x7f, 0x3c, 0x7f, 0x3c, 0x7f,
+};
+const uint8 kChannelPressure[] = { 0xd0, 0x01 };
+const uint8 kChannelPressureWithRunningStatus[] = {
+ 0xd0, 0x01, 0x01, 0x01,
+};
+const uint8 kTimingClock[] = { 0xf8 };
+const uint8 kBrokenData1[] = { 0x90 };
+const uint8 kBrokenData2[] = { 0xf7 };
+const uint8 kBrokenData3[] = { 0xf2, 0x00 };
+const uint8 kDataByte0[] = { 0x00 };
+
+template <typename T, size_t N>
+const std::vector<T> AsVector(const T(&data)[N]) {
+ std::vector<T> buffer;
+ buffer.insert(buffer.end(), data, data + N);
+ return buffer;
+}
+
+template <typename T, size_t N>
+void PushToVector(const T(&data)[N], std::vector<T>* buffer) {
+ buffer->insert(buffer->end(), data, data + N);
+}
+
+} // namespace
+
+TEST(MIDIHostTest, IsValidWebMIDIData) {
+ // Test single event scenario
+ EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kGMOn)));
+ EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kGSOn)));
+ EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kNoteOn)));
+ EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kChannelPressure)));
+ EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kTimingClock)));
+ EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(AsVector(kBrokenData1)));
+ EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(AsVector(kBrokenData2)));
+ EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(AsVector(kBrokenData3)));
+ EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(AsVector(kDataByte0)));
+
+ // MIDI running status should be disallowed
+ EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(
+ AsVector(kNoteOnWithRunningStatus)));
+ EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(
+ AsVector(kChannelPressureWithRunningStatus)));
+
+ // Multiple messages are allowed as long as each of them is complete.
+ {
+ std::vector<uint8> buffer;
+ PushToVector(kGMOn, &buffer);
+ PushToVector(kNoteOn, &buffer);
+ PushToVector(kGSOn, &buffer);
+ PushToVector(kTimingClock, &buffer);
+ PushToVector(kNoteOn, &buffer);
+ EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(buffer));
+ PushToVector(kBrokenData1, &buffer);
+ EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(buffer));
+ }
+
+ // MIDI realtime message can be placed at any position.
+ {
+ const uint8 kNoteOnWithRealTimeClock[] = {
+ 0x90, 0xf8, 0x3c, 0x7f, 0x90, 0xf8, 0x3c, 0xf8, 0x7f, 0xf8,
+ };
+ EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(
+ AsVector(kNoteOnWithRealTimeClock)));
+
+ const uint8 kGMOnWithRealTimeClock[] = {
+ 0xf0, 0xf8, 0x7e, 0x7f, 0x09, 0x01, 0xf8, 0xf7,
+ };
+ EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kGMOnWithRealTimeClock)));
+ }
+}
+
+} // namespace conent
diff --git a/chromium/content/browser/renderer_host/media/mock_media_observer.cc b/chromium/content/browser/renderer_host/media/mock_media_observer.cc
index f6d4e56cbab..731801fe798 100644
--- a/chromium/content/browser/renderer_host/media/mock_media_observer.cc
+++ b/chromium/content/browser/renderer_host/media/mock_media_observer.cc
@@ -10,8 +10,4 @@ MockMediaObserver::MockMediaObserver() {}
MockMediaObserver::~MockMediaObserver() {}
-MockMediaInternals::MockMediaInternals() {}
-
-MockMediaInternals::~MockMediaInternals() {}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/mock_media_observer.h b/chromium/content/browser/renderer_host/media/mock_media_observer.h
index 5f7fb847b3c..c3543f3002b 100644
--- a/chromium/content/browser/renderer_host/media/mock_media_observer.h
+++ b/chromium/content/browser/renderer_host/media/mock_media_observer.h
@@ -8,7 +8,6 @@
#include <string>
#include "base/basictypes.h"
-#include "content/browser/media/media_internals.h"
#include "content/public/browser/media_observer.h"
#include "media/audio/audio_parameters.h"
#include "media/base/media_log_event.h"
@@ -39,27 +38,6 @@ class MockMediaObserver : public MediaObserver {
bool clipped));
};
-class MockMediaInternals : public MediaInternals {
- public:
- MockMediaInternals();
- virtual ~MockMediaInternals();
-
- MOCK_METHOD2(OnDeleteAudioStream,
- void(void* host, int stream_id));
- MOCK_METHOD3(OnSetAudioStreamPlaying,
- void(void* host, int stream_id, bool playing));
- MOCK_METHOD4(OnAudioStreamCreated,
- void(void* host, int stream_id,
- const media::AudioParameters& params,
- const std::string& input_device_id));
- MOCK_METHOD3(OnSetAudioStreamStatus,
- void(void* host, int stream_id, const std::string& status));
- MOCK_METHOD3(OnSetAudioStreamVolume,
- void(void* host, int stream_id, double volume));
- MOCK_METHOD2(OnMediaEvent,
- void(int source, const media::MediaLogEvent& event));
-};
-
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MOCK_MEDIA_OBSERVER_H_
diff --git a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc
index 3e30834feb2..92523756eff 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc
@@ -7,71 +7,71 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
namespace content {
-VideoCaptureBufferPool::VideoCaptureBufferPool(size_t size, int count)
- : size_(size),
- count_(count) {
-}
+const int VideoCaptureBufferPool::kInvalidId = -1;
-VideoCaptureBufferPool::~VideoCaptureBufferPool() {
+VideoCaptureBufferPool::VideoCaptureBufferPool(int count)
+ : count_(count),
+ next_buffer_id_(0) {
}
-bool VideoCaptureBufferPool::Allocate() {
- base::AutoLock lock(lock_);
- DCHECK(!IsAllocated());
- buffers_.resize(count_);
- for (int buffer_id = 0; buffer_id < count(); ++buffer_id) {
- Buffer* buffer = new Buffer();
- buffers_[buffer_id] = buffer;
- if (!buffer->shared_memory.CreateAndMapAnonymous(GetMemorySize()))
- return false;
- }
- return true;
+VideoCaptureBufferPool::~VideoCaptureBufferPool() {
+ STLDeleteValues(&buffers_);
}
base::SharedMemoryHandle VideoCaptureBufferPool::ShareToProcess(
int buffer_id,
- base::ProcessHandle process_handle) {
+ base::ProcessHandle process_handle,
+ size_t* memory_size) {
base::AutoLock lock(lock_);
- DCHECK(IsAllocated());
- DCHECK(buffer_id >= 0);
- DCHECK(buffer_id < count_);
- Buffer* buffer = buffers_[buffer_id];
+
+ Buffer* buffer = GetBuffer(buffer_id);
+ if (!buffer) {
+ NOTREACHED() << "Invalid buffer_id.";
+ return base::SharedMemory::NULLHandle();
+ }
base::SharedMemoryHandle remote_handle;
buffer->shared_memory.ShareToProcess(process_handle, &remote_handle);
+ *memory_size = buffer->shared_memory.requested_size();
return remote_handle;
}
-base::SharedMemoryHandle VideoCaptureBufferPool::GetHandle(int buffer_id) {
+bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id,
+ void** memory,
+ size_t* size) {
base::AutoLock lock(lock_);
- DCHECK(IsAllocated());
- DCHECK(buffer_id >= 0);
- DCHECK(buffer_id < count_);
- return buffers_[buffer_id]->shared_memory.handle();
-}
-void* VideoCaptureBufferPool::GetMemory(int buffer_id) {
- base::AutoLock lock(lock_);
- DCHECK(IsAllocated());
- DCHECK(buffer_id >= 0);
- DCHECK(buffer_id < count_);
- return buffers_[buffer_id]->shared_memory.memory();
+ Buffer* buffer = GetBuffer(buffer_id);
+ if (!buffer) {
+ NOTREACHED() << "Invalid buffer_id.";
+ return false;
+ }
+
+ DCHECK(buffer->held_by_producer);
+ *memory = buffer->shared_memory.memory();
+ *size = buffer->shared_memory.mapped_size();
+ return true;
}
-int VideoCaptureBufferPool::ReserveForProducer() {
+int VideoCaptureBufferPool::ReserveForProducer(size_t size,
+ int* buffer_id_to_drop) {
base::AutoLock lock(lock_);
- return ReserveForProducerInternal();
+ return ReserveForProducerInternal(size, buffer_id_to_drop);
}
void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) {
base::AutoLock lock(lock_);
- DCHECK(buffer_id >= 0);
- DCHECK(buffer_id < count());
- Buffer* buffer = buffers_[buffer_id];
+ Buffer* buffer = GetBuffer(buffer_id);
+ if (!buffer) {
+ NOTREACHED() << "Invalid buffer_id.";
+ return;
+ }
DCHECK(buffer->held_by_producer);
buffer->held_by_producer = false;
}
@@ -80,134 +80,91 @@ void VideoCaptureBufferPool::HoldForConsumers(
int buffer_id,
int num_clients) {
base::AutoLock lock(lock_);
- DCHECK(buffer_id >= 0);
- DCHECK(buffer_id < count());
- DCHECK(IsAllocated());
- Buffer* buffer = buffers_[buffer_id];
+ Buffer* buffer = GetBuffer(buffer_id);
+ if (!buffer) {
+ NOTREACHED() << "Invalid buffer_id.";
+ return;
+ }
DCHECK(buffer->held_by_producer);
DCHECK(!buffer->consumer_hold_count);
buffer->consumer_hold_count = num_clients;
// Note: |held_by_producer| will stay true until
// RelinquishProducerReservation() (usually called by destructor of the object
- // wrapping this buffer, e.g. a media::VideoFrame
+ // wrapping this buffer, e.g. a media::VideoFrame).
}
void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id,
int num_clients) {
base::AutoLock lock(lock_);
- DCHECK(buffer_id >= 0);
- DCHECK(buffer_id < count());
- DCHECK_GT(num_clients, 0);
- DCHECK(IsAllocated());
- Buffer* buffer = buffers_[buffer_id];
+ Buffer* buffer = GetBuffer(buffer_id);
+ if (!buffer) {
+ NOTREACHED() << "Invalid buffer_id.";
+ return;
+ }
DCHECK_GE(buffer->consumer_hold_count, num_clients);
buffer->consumer_hold_count -= num_clients;
}
-// State query functions.
-size_t VideoCaptureBufferPool::GetMemorySize() const {
- // No need to take |lock_| currently.
- return size_;
-}
-
-int VideoCaptureBufferPool::RecognizeReservedBuffer(
- base::SharedMemoryHandle maybe_belongs_to_pool) {
- base::AutoLock lock(lock_);
- for (int buffer_id = 0; buffer_id < count(); ++buffer_id) {
- Buffer* buffer = buffers_[buffer_id];
- if (buffer->shared_memory.handle() == maybe_belongs_to_pool) {
- DCHECK(buffer->held_by_producer);
- return buffer_id;
- }
- }
- return -1; // Buffer is not from our pool.
-}
-
-scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveI420VideoFrame(
- const gfx::Size& size,
- int rotation) {
- if (GetMemorySize() !=
- media::VideoFrame::AllocationSize(media::VideoFrame::I420, size)) {
- DCHECK_EQ(GetMemorySize(),
- media::VideoFrame::AllocationSize(media::VideoFrame::I420, size));
- return NULL;
- }
-
- base::AutoLock lock(lock_);
-
- int buffer_id = ReserveForProducerInternal();
- if (buffer_id < 0)
- return NULL;
-
- base::Closure disposal_handler = base::Bind(
- &VideoCaptureBufferPool::RelinquishProducerReservation,
- this,
- buffer_id);
-
- Buffer* buffer = buffers_[buffer_id];
- // Wrap the buffer in a VideoFrame container.
- scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapExternalSharedMemory(
- media::VideoFrame::I420,
- size,
- gfx::Rect(size),
- size,
- static_cast<uint8*>(buffer->shared_memory.memory()),
- GetMemorySize(),
- buffer->shared_memory.handle(),
- base::TimeDelta(),
- disposal_handler);
-
- if (buffer->rotation != rotation) {
- // TODO(nick): Generalize the |rotation| mechanism.
- media::FillYUV(frame.get(), 0, 128, 128);
- buffer->rotation = rotation;
- }
+VideoCaptureBufferPool::Buffer::Buffer()
+ : held_by_producer(false), consumer_hold_count(0) {}
- return frame;
-}
+int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size,
+ int* buffer_id_to_drop) {
+ lock_.AssertAcquired();
-bool VideoCaptureBufferPool::IsAnyBufferHeldForConsumers() {
- base::AutoLock lock(lock_);
- for (int buffer_id = 0; buffer_id < count(); ++buffer_id) {
- Buffer* buffer = buffers_[buffer_id];
- if (buffer->consumer_hold_count > 0)
- return true;
+ // Look for a buffer that's allocated, big enough, and not in use. Track the
+ // largest one that's not big enough, in case we have to reallocate a buffer.
+ *buffer_id_to_drop = kInvalidId;
+ size_t realloc_size = 0;
+ BufferMap::iterator realloc = buffers_.end();
+ for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); ++it) {
+ Buffer* buffer = it->second;
+ if (!buffer->consumer_hold_count && !buffer->held_by_producer) {
+ if (buffer->shared_memory.requested_size() >= size) {
+ // Existing buffer is big enough. Reuse it.
+ buffer->held_by_producer = true;
+ return it->first;
+ }
+ if (buffer->shared_memory.requested_size() > realloc_size) {
+ realloc_size = buffer->shared_memory.requested_size();
+ realloc = it;
+ }
+ }
}
- return false;
-}
-VideoCaptureBufferPool::Buffer::Buffer()
- : rotation(0),
- held_by_producer(false),
- consumer_hold_count(0) {}
-
-int VideoCaptureBufferPool::ReserveForProducerInternal() {
- lock_.AssertAcquired();
- DCHECK(IsAllocated());
-
- int buffer_id = -1;
- for (int candidate_id = 0; candidate_id < count(); ++candidate_id) {
- Buffer* candidate = buffers_[candidate_id];
- if (!candidate->consumer_hold_count && !candidate->held_by_producer) {
- buffer_id = candidate_id;
- break;
+ // Preferentially grow the pool by creating a new buffer. If we're at maximum
+ // size, then reallocate by deleting an existing one instead.
+ if (buffers_.size() == static_cast<size_t>(count_)) {
+ if (realloc == buffers_.end()) {
+ // We're out of space, and can't find an unused buffer to reallocate.
+ return kInvalidId;
}
+ *buffer_id_to_drop = realloc->first;
+ delete realloc->second;
+ buffers_.erase(realloc);
}
- if (buffer_id == -1)
- return -1;
- Buffer* buffer = buffers_[buffer_id];
- CHECK_GE(buffer->shared_memory.requested_size(), size_);
+ // Create the new buffer.
+ int buffer_id = next_buffer_id_++;
+ scoped_ptr<Buffer> buffer(new Buffer());
+ if (size) {
+ // |size| can be 0 for buffers that do not require memory backing.
+ if (!buffer->shared_memory.CreateAndMapAnonymous(size))
+ return kInvalidId;
+ }
buffer->held_by_producer = true;
+ buffers_[buffer_id] = buffer.release();
return buffer_id;
}
-bool VideoCaptureBufferPool::IsAllocated() const {
- lock_.AssertAcquired();
- return !buffers_.empty();
+VideoCaptureBufferPool::Buffer* VideoCaptureBufferPool::GetBuffer(
+ int buffer_id) {
+ BufferMap::iterator it = buffers_.find(buffer_id);
+ if (it == buffers_.end())
+ return NULL;
+ return it->second;
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.h b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.h
index 6d9607737dc..0ee32a78223 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_BUFFER_POOL_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_BUFFER_POOL_H_
+#include <map>
+
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
@@ -25,43 +27,53 @@ namespace content {
// A thread-safe class that does the bookkeeping and lifetime management for a
// pool of shared-memory pixel buffers cycled between an in-process producer
// (e.g. a VideoCaptureDevice) and a set of out-of-process consumers. The pool
-// is intended to be allocated and orchestrated by a VideoCaptureController, but
-// is designed to outlive the controller if necessary.
+// is intended to be orchestrated by a VideoCaptureController, but is designed
+// to outlive the controller if necessary.
+//
+// Producers get a buffer by calling ReserveForProducer(), and may pass on their
+// ownership to the consumer by calling HoldForConsumers(), or drop the buffer
+// (without further processing) by calling RelinquishProducerReservation().
+// Consumers signal that they are done with the buffer by calling
+// RelinquishConsumerHold().
//
-// Buffers are identified by an int value called |buffer_id|. Callers may depend
-// on the buffer IDs being dense in the range [0, count()), so long as the
-// Allocate() step succeeded. -1 is never a valid ID, and is returned by some
-// methods to indicate failure. Producers get a buffer by calling
-// ReserveForProducer(), and may pass on their ownership to the consumer by
-// calling HoldForConsumers(), or drop the buffer (without further processing)
-// by calling ReserveForProducer(). Consumers signal that they are done with the
-// buffer by calling RelinquishConsumerHold().
+// Buffers are allocated on demand, but there will never be more than |count|
+// buffers in existence at any time. Buffers are identified by an int value
+// called |buffer_id|. -1 (kInvalidId) is never a valid ID, and is returned by
+// some methods to indicate failure. The active set of buffer ids may change
+// over the lifetime of the buffer pool, as existing buffers are freed and
+// reallocated at larger size. When reallocation occurs, new buffer IDs will
+// circulate.
class CONTENT_EXPORT VideoCaptureBufferPool
: public base::RefCountedThreadSafe<VideoCaptureBufferPool> {
public:
- VideoCaptureBufferPool(size_t size, int count);
-
- // One-time initialization to allocate the shared memory buffers. Returns true
- // on success.
- bool Allocate();
+ static const int kInvalidId;
+ explicit VideoCaptureBufferPool(int count);
// One-time (per client/per-buffer) initialization to share a particular
- // buffer to a process.
+ // buffer to a process. The size of the allocation is returned as
+ // |memory_size|.
base::SharedMemoryHandle ShareToProcess(int buffer_id,
- base::ProcessHandle process_handle);
-
- // Get the shared memory handle for a particular buffer index.
- base::SharedMemoryHandle GetHandle(int buffer_id);
-
- // Get the mapped buffer memory for a particular buffer index.
- void* GetMemory(int buffer_id);
-
- // Locate the index of a buffer (if any) that's not in use by the producer or
- // consumers, and reserve it. The buffer remains reserved (and writable by the
+ base::ProcessHandle process_handle,
+ size_t* memory_size);
+
+ // Query the memory parameters of |buffer_id|. Fills in parameters in the
+ // pointer arguments, and returns true iff the buffer exists.
+ bool GetBufferInfo(int buffer_id, void** memory, size_t* size);
+
+ // Reserve or allocate a buffer of at least |size| bytes and return its id.
+ // This will fail (returning kInvalidId) if the pool already is at its |count|
+ // limit of the number of allocations, and all allocated buffers are in use by
+ // the producer and/or consumers.
+ //
+ // If successful, the reserved buffer remains reserved (and writable by the
// producer) until ownership is transferred either to the consumer via
// HoldForConsumers(), or back to the pool with
// RelinquishProducerReservation().
- int ReserveForProducer();
+ //
+ // On occasion, this call will decide to free an old buffer to make room for a
+ // new allocation at a larger size. If so, the ID of the destroyed buffer is
+ // returned via |buffer_id_to_drop|.
+ int ReserveForProducer(size_t size, int* buffer_id_to_drop);
// Indicate that a buffer held for the producer should be returned back to the
// pool without passing on to the consumer. This effectively is the opposite
@@ -78,20 +90,7 @@ class CONTENT_EXPORT VideoCaptureBufferPool
// done, a buffer is returned to the pool for reuse.
void RelinquishConsumerHold(int buffer_id, int num_clients);
- // Detect whether a particular SharedMemoryHandle is exported by a buffer that
- // belongs to this pool -- that is, whether it was allocated by an earlier
- // call to ReserveForProducer(). If so, return its buffer_id (a value on the
- // range [0, count())). If not, return -1, indicating the buffer is not
- // recognized (it may be a valid frame, but we didn't allocate it).
- int RecognizeReservedBuffer(base::SharedMemoryHandle maybe_belongs_to_pool);
-
- // Utility functions to return a buffer wrapped in a useful type.
- scoped_refptr<media::VideoFrame> ReserveI420VideoFrame(const gfx::Size& size,
- int rotation);
-
int count() const { return count_; }
- size_t GetMemorySize() const;
- bool IsAnyBufferHeldForConsumers();
private:
friend class base::RefCountedThreadSafe<VideoCaptureBufferPool>;
@@ -103,9 +102,6 @@ class CONTENT_EXPORT VideoCaptureBufferPool
// The memory created to be shared with renderer processes.
base::SharedMemory shared_memory;
- // Rotation in degrees of the buffer.
- int rotation;
-
// Tracks whether this buffer is currently referenced by the producer.
bool held_by_producer;
@@ -113,20 +109,25 @@ class CONTENT_EXPORT VideoCaptureBufferPool
int consumer_hold_count;
};
+ typedef std::map<int, Buffer*> BufferMap;
+
virtual ~VideoCaptureBufferPool();
- int ReserveForProducerInternal();
+ int ReserveForProducerInternal(size_t size, int* buffer_id_to_drop);
- bool IsAllocated() const;
+ Buffer* GetBuffer(int buffer_id);
- // Protects |buffers_| and contents thereof.
+ // The max number of buffers that the pool is allowed to have at any moment.
+ const int count_;
+
+ // Protects everything below it.
base::Lock lock_;
- // The buffers, indexed by |buffer_id|. Element 0 is always NULL.
- ScopedVector<Buffer> buffers_;
+ // The ID of the next buffer.
+ int next_buffer_id_;
- const size_t size_;
- const int count_;
+ // The buffers, indexed by |buffer_id|.
+ BufferMap buffers_;
DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureBufferPool);
};
diff --git a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
index 30509a34c75..39fd9857b3e 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
@@ -16,144 +16,187 @@
namespace content {
-TEST(VideoCaptureBufferPoolTest, BufferPool) {
- const gfx::Size size = gfx::Size(640, 480);
+class VideoCaptureBufferPoolTest : public testing::Test {
+ protected:
+ class Buffer {
+ public:
+ Buffer(const scoped_refptr<VideoCaptureBufferPool> pool,
+ int id,
+ void* data,
+ size_t size)
+ : pool_(pool), id_(id), data_(data), size_(size) {}
+ ~Buffer() { pool_->RelinquishProducerReservation(id()); }
+ int id() const { return id_; }
+ void* data() const { return data_; }
+ size_t size() const { return size_; }
+
+ private:
+ const scoped_refptr<VideoCaptureBufferPool> pool_;
+ const int id_;
+ void* const data_;
+ const size_t size_;
+ };
+ VideoCaptureBufferPoolTest()
+ : expected_dropped_id_(0),
+ pool_(new VideoCaptureBufferPool(3)) {}
+
+ void ExpectDroppedId(int expected_dropped_id) {
+ expected_dropped_id_ = expected_dropped_id;
+ }
+
+ scoped_ptr<Buffer> ReserveI420Buffer(const gfx::Size& dimensions) {
+ const size_t frame_bytes =
+ media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions);
+ // To verify that ReserveI420Buffer always sets |buffer_id_to_drop|,
+ // initialize it to something different than the expected value.
+ int buffer_id_to_drop = ~expected_dropped_id_;
+ int buffer_id = pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop);
+ if (buffer_id == VideoCaptureBufferPool::kInvalidId)
+ return scoped_ptr<Buffer>();
+
+ void* memory;
+ size_t size;
+ pool_->GetBufferInfo(buffer_id, &memory, &size);
+ EXPECT_EQ(expected_dropped_id_, buffer_id_to_drop);
+ return scoped_ptr<Buffer>(new Buffer(pool_, buffer_id, memory, size));
+ }
+
+ int expected_dropped_id_;
+ scoped_refptr<VideoCaptureBufferPool> pool_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VideoCaptureBufferPoolTest);
+};
+
+TEST_F(VideoCaptureBufferPoolTest, BufferPool) {
+ const gfx::Size size_lo = gfx::Size(640, 480);
+ const gfx::Size size_hi = gfx::Size(1024, 768);
scoped_refptr<media::VideoFrame> non_pool_frame =
- media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size,
- gfx::Rect(size), size, base::TimeDelta());
- scoped_refptr<VideoCaptureBufferPool> pool = new VideoCaptureBufferPool(
- media::VideoFrame::AllocationSize(media::VideoFrame::I420, size), 3);
-
- ASSERT_EQ(460800u, pool->GetMemorySize());
- ASSERT_TRUE(pool->Allocate());
-
- scoped_refptr<media::VideoFrame> frame1 =
- pool->ReserveI420VideoFrame(size, 0);
- ASSERT_TRUE(NULL != frame1.get());
- ASSERT_EQ(size, frame1->coded_size());
- scoped_refptr<media::VideoFrame> frame2 =
- pool->ReserveI420VideoFrame(size, 0);
- ASSERT_TRUE(NULL != frame2.get());
- ASSERT_EQ(size, frame2->coded_size());
- scoped_refptr<media::VideoFrame> frame3 =
- pool->ReserveI420VideoFrame(size, 0);
- ASSERT_TRUE(NULL != frame3.get());
+ media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size_lo,
+ gfx::Rect(size_lo), size_lo,
+ base::TimeDelta());
+
+ // Reallocation won't happen for the first part of the test.
+ ExpectDroppedId(VideoCaptureBufferPool::kInvalidId);
+
+ scoped_ptr<Buffer> buffer1 = ReserveI420Buffer(size_lo);
+ ASSERT_TRUE(NULL != buffer1.get());
+ ASSERT_LE(media::VideoFrame::AllocationSize(media::VideoFrame::I420, size_lo),
+ buffer1->size());
+ scoped_ptr<Buffer> buffer2 = ReserveI420Buffer(size_lo);
+ ASSERT_TRUE(NULL != buffer2.get());
+ ASSERT_LE(media::VideoFrame::AllocationSize(media::VideoFrame::I420, size_lo),
+ buffer2->size());
+ scoped_ptr<Buffer> buffer3 = ReserveI420Buffer(size_lo);
+ ASSERT_TRUE(NULL != buffer3.get());
+ ASSERT_LE(media::VideoFrame::AllocationSize(media::VideoFrame::I420, size_lo),
+ buffer3->size());
// Touch the memory.
- media::FillYUV(frame1.get(), 0x11, 0x22, 0x33);
- media::FillYUV(frame2.get(), 0x44, 0x55, 0x66);
- media::FillYUV(frame3.get(), 0x77, 0x88, 0x99);
+ memset(buffer1->data(), 0x11, buffer1->size());
+ memset(buffer2->data(), 0x44, buffer2->size());
+ memset(buffer3->data(), 0x77, buffer3->size());
- // Fourth frame should fail.
- ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get())
- << "Pool should be empty";
+ // Fourth buffer should fail.
+ ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
- // Release 1st frame and retry; this should succeed.
- frame1 = NULL;
- scoped_refptr<media::VideoFrame> frame4 =
- pool->ReserveI420VideoFrame(size, 0);
- ASSERT_TRUE(NULL != frame4.get());
+ // Release 1st buffer and retry; this should succeed.
+ buffer1.reset();
+ scoped_ptr<Buffer> buffer4 = ReserveI420Buffer(size_lo);
+ ASSERT_TRUE(NULL != buffer4.get());
- ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get())
- << "Pool should be empty";
+ ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
+ ASSERT_FALSE(ReserveI420Buffer(size_hi)) << "Pool should be empty";
// Validate the IDs
- int buffer_id2 =
- pool->RecognizeReservedBuffer(frame2->shared_memory_handle());
- ASSERT_LE(0, buffer_id2);
- int buffer_id3 =
- pool->RecognizeReservedBuffer(frame3->shared_memory_handle());
- ASSERT_LE(0, buffer_id3);
- int buffer_id4 =
- pool->RecognizeReservedBuffer(frame4->shared_memory_handle());
- ASSERT_LE(0, buffer_id4);
- int buffer_id_non_pool =
- pool->RecognizeReservedBuffer(non_pool_frame->shared_memory_handle());
- ASSERT_GT(0, buffer_id_non_pool);
-
- ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers());
-
- // Deliver a frame.
- pool->HoldForConsumers(buffer_id3, 2);
-
- ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers());
- ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get())
- << "Pool should be empty";
- frame3 = NULL; // Old producer releases frame. Should be a noop.
- ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers());
- ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get())
- << "Pool should be empty";
- frame2 = NULL; // Active producer releases frame. Should free a frame.
- buffer_id2 = 0;
-
- ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers());
- frame1 = pool->ReserveI420VideoFrame(size, 0);
- ASSERT_TRUE(NULL != frame1.get());
- ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get())
- << "Pool should be empty";
- ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers());
+ int buffer_id2 = buffer2->id();
+ ASSERT_EQ(1, buffer_id2);
+ int buffer_id3 = buffer3->id();
+ ASSERT_EQ(2, buffer_id3);
+ void* const memory_pointer3 = buffer3->data();
+ int buffer_id4 = buffer4->id();
+ ASSERT_EQ(0, buffer_id4);
+
+ // Deliver a buffer.
+ pool_->HoldForConsumers(buffer_id3, 2);
+
+ ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
+
+ buffer3.reset(); // Old producer releases buffer. Should be a noop.
+ ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
+ ASSERT_FALSE(ReserveI420Buffer(size_hi)) << "Pool should be empty";
+
+ buffer2.reset(); // Active producer releases buffer. Should free a buffer.
+
+ buffer1 = ReserveI420Buffer(size_lo);
+ ASSERT_TRUE(NULL != buffer1.get());
+ ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
// First consumer finishes.
- pool->RelinquishConsumerHold(buffer_id3, 1);
- ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get())
- << "Pool should be empty";
- ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers());
-
- // Second consumer finishes. This should free that frame.
- pool->RelinquishConsumerHold(buffer_id3, 1);
- ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers());
- frame3 = pool->ReserveI420VideoFrame(size, 0);
- ASSERT_TRUE(NULL != frame3.get());
- ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers());
- ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get())
- << "Pool should be empty";
-
- // Now deliver & consume frame1, but don't release the VideoFrame.
- int buffer_id1 =
- pool->RecognizeReservedBuffer(frame1->shared_memory_handle());
- ASSERT_LE(0, buffer_id1);
- pool->HoldForConsumers(buffer_id1, 5);
- ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers());
- pool->RelinquishConsumerHold(buffer_id1, 5);
- ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers());
+ pool_->RelinquishConsumerHold(buffer_id3, 1);
+ ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
+
+ // Second consumer finishes. This should free that buffer.
+ pool_->RelinquishConsumerHold(buffer_id3, 1);
+ buffer3 = ReserveI420Buffer(size_lo);
+ ASSERT_TRUE(NULL != buffer3.get());
+ ASSERT_EQ(buffer_id3, buffer3->id()) << "Buffer ID should be reused.";
+ ASSERT_EQ(memory_pointer3, buffer3->data());
+ ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
+
+ // Now deliver & consume buffer1, but don't release the buffer.
+ int buffer_id1 = buffer1->id();
+ ASSERT_EQ(1, buffer_id1);
+ pool_->HoldForConsumers(buffer_id1, 5);
+ pool_->RelinquishConsumerHold(buffer_id1, 5);
// Even though the consumer is done with the buffer at |buffer_id1|, it cannot
- // be re-allocated to the producer, because |frame1| still references it. But
- // when |frame1| goes away, we should be able to re-reserve the buffer (and
+ // be re-allocated to the producer, because |buffer1| still references it. But
+ // when |buffer1| goes away, we should be able to re-reserve the buffer (and
// the ID ought to be the same).
- ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get())
- << "Pool should be empty";
- frame1 = NULL; // Should free the frame.
- frame2 = pool->ReserveI420VideoFrame(size, 0);
- ASSERT_TRUE(NULL != frame2.get());
- ASSERT_EQ(buffer_id1,
- pool->RecognizeReservedBuffer(frame2->shared_memory_handle()));
- ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get())
- << "Pool should be empty";
-
- // For good measure, do one more cycle of free/realloc without delivery, now
- // that this buffer has been through the consumer-hold cycle.
- frame2 = NULL;
- frame1 = pool->ReserveI420VideoFrame(size, 0);
- ASSERT_TRUE(NULL != frame1.get());
- ASSERT_EQ(buffer_id1,
- pool->RecognizeReservedBuffer(frame1->shared_memory_handle()));
- ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get())
- << "Pool should be empty";
-
- // Tear down the pool, writing into the frames. The VideoFrame should
- // preserve the lifetime of the underlying memory.
- frame3 = NULL;
- pool = NULL;
+ ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
+ buffer1.reset(); // Should free the buffer.
+ buffer2 = ReserveI420Buffer(size_lo);
+ ASSERT_TRUE(NULL != buffer2.get());
+ ASSERT_EQ(buffer_id1, buffer2->id());
+ buffer_id2 = buffer_id1;
+ ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
+
+ // Now try reallocation with different resolutions. We expect reallocation
+ // to occur only when the old buffer is too small.
+ buffer2.reset();
+ ExpectDroppedId(buffer_id2);
+ buffer2 = ReserveI420Buffer(size_hi);
+ ASSERT_TRUE(NULL != buffer2.get());
+ ASSERT_LE(media::VideoFrame::AllocationSize(media::VideoFrame::I420, size_hi),
+ buffer2->size());
+ ASSERT_EQ(3, buffer2->id());
+ void* const memory_pointer_hi = buffer2->data();
+ buffer2.reset(); // Frees it.
+ ExpectDroppedId(VideoCaptureBufferPool::kInvalidId);
+ buffer2 = ReserveI420Buffer(size_lo);
+ void* const memory_pointer_lo = buffer2->data();
+ ASSERT_EQ(memory_pointer_hi, memory_pointer_lo)
+ << "Decrease in resolution should not reallocate buffer";
+ ASSERT_TRUE(NULL != buffer2.get());
+ ASSERT_EQ(3, buffer2->id());
+ ASSERT_LE(media::VideoFrame::AllocationSize(media::VideoFrame::I420, size_lo),
+ buffer2->size());
+ ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
+
+ // Tear down the pool_, writing into the buffers. The buffer should preserve
+ // the lifetime of the underlying memory.
+ buffer3.reset();
+ pool_ = NULL;
// Touch the memory.
- media::FillYUV(frame1.get(), 0x11, 0x22, 0x33);
- media::FillYUV(frame4.get(), 0x44, 0x55, 0x66);
+ memset(buffer2->data(), 0x22, buffer2->size());
+ memset(buffer4->data(), 0x55, buffer4->size());
- frame1 = NULL;
+ buffer2.reset();
- media::FillYUV(frame4.get(), 0x44, 0x55, 0x66);
- frame4 = NULL;
+ memset(buffer4->data(), 0x77, buffer4->size());
+ buffer4.reset();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller.cc b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
index 687a21a4996..1840af2c3af 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/debug/trace_event.h"
-#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
@@ -17,68 +16,66 @@
#include "media/base/video_util.h"
#include "media/base/yuv_convert.h"
-#if !defined(OS_IOS) && !defined(OS_ANDROID)
+#if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW)
#include "third_party/libyuv/include/libyuv.h"
#endif
+using media::VideoCaptureFormat;
+
+namespace content {
+
namespace {
-#if defined(OS_IOS) || defined(OS_ANDROID)
-// TODO(wjia): Support stride.
-void RotatePackedYV12Frame(
- const uint8* src,
- uint8* dest_yplane,
- uint8* dest_uplane,
- uint8* dest_vplane,
- int width,
- int height,
- int rotation,
- bool flip_vert,
- bool flip_horiz) {
- media::RotatePlaneByPixels(
- src, dest_yplane, width, height, rotation, flip_vert, flip_horiz);
- int y_size = width * height;
- src += y_size;
- media::RotatePlaneByPixels(
- src, dest_uplane, width/2, height/2, rotation, flip_vert, flip_horiz);
- src += y_size/4;
- media::RotatePlaneByPixels(
- src, dest_vplane, width/2, height/2, rotation, flip_vert, flip_horiz);
-}
-#endif // #if defined(OS_IOS) || defined(OS_ANDROID)
+// The number of buffers that VideoCaptureBufferPool should allocate.
+const int kNoOfBuffers = 3;
-} // namespace
+class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer {
+ public:
+ PoolBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool,
+ int buffer_id,
+ void* data,
+ size_t size)
+ : Buffer(buffer_id, data, size), pool_(pool) {
+ DCHECK(pool_);
+ }
-namespace content {
+ private:
+ virtual ~PoolBuffer() { pool_->RelinquishProducerReservation(id()); }
-// The number of buffers that VideoCaptureBufferPool should allocate.
-static const int kNoOfBuffers = 3;
+ const scoped_refptr<VideoCaptureBufferPool> pool_;
+};
+
+} // anonymous namespace
struct VideoCaptureController::ControllerClient {
- ControllerClient(
- const VideoCaptureControllerID& id,
- VideoCaptureControllerEventHandler* handler,
- base::ProcessHandle render_process,
- const media::VideoCaptureParams& params)
+ ControllerClient(const VideoCaptureControllerID& id,
+ VideoCaptureControllerEventHandler* handler,
+ base::ProcessHandle render_process,
+ media::VideoCaptureSessionId session_id,
+ const media::VideoCaptureParams& params)
: controller_id(id),
event_handler(handler),
render_process_handle(render_process),
+ session_id(session_id),
parameters(params),
- session_closed(false) {
- }
+ session_closed(false) {}
~ControllerClient() {}
// ID used for identifying this object.
- VideoCaptureControllerID controller_id;
- VideoCaptureControllerEventHandler* event_handler;
+ const VideoCaptureControllerID controller_id;
+ VideoCaptureControllerEventHandler* const event_handler;
// Handle to the render process that will receive the capture buffers.
- base::ProcessHandle render_process_handle;
- media::VideoCaptureParams parameters;
+ const base::ProcessHandle render_process_handle;
+ const media::VideoCaptureSessionId session_id;
+ const media::VideoCaptureParams parameters;
- // Buffers used by this client.
- std::set<int> buffers;
+ // Buffers that are currently known to this client.
+ std::set<int> known_buffers;
+
+ // Buffers currently held by this client.
+ std::set<int> active_buffers;
// State of capture session, controlled by VideoCaptureManager directly. This
// transitions to true as soon as StopSession() occurs, at which point the
@@ -102,63 +99,51 @@ struct VideoCaptureController::ControllerClient {
// device type; including, for example, the DirectShow thread on Windows, the
// v4l2_thread on Linux, and the UI thread for tab capture.
class VideoCaptureController::VideoCaptureDeviceClient
- : public media::VideoCaptureDevice::EventHandler {
+ : public media::VideoCaptureDevice::Client {
public:
explicit VideoCaptureDeviceClient(
- const base::WeakPtr<VideoCaptureController>& controller);
+ const base::WeakPtr<VideoCaptureController>& controller,
+ const scoped_refptr<VideoCaptureBufferPool>& buffer_pool);
virtual ~VideoCaptureDeviceClient();
- // VideoCaptureDevice::EventHandler implementation.
- virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE;
+ // VideoCaptureDevice::Client implementation.
+ virtual scoped_refptr<Buffer> ReserveOutputBuffer(
+ media::VideoFrame::Format format,
+ const gfx::Size& size) OVERRIDE;
virtual void OnIncomingCapturedFrame(const uint8* data,
int length,
base::Time timestamp,
int rotation,
- bool flip_vert,
- bool flip_horiz) OVERRIDE;
- virtual void OnIncomingCapturedVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame,
- base::Time timestamp) OVERRIDE;
+ const VideoCaptureFormat& frame_format)
+ OVERRIDE;
+ virtual void OnIncomingCapturedBuffer(const scoped_refptr<Buffer>& buffer,
+ media::VideoFrame::Format format,
+ const gfx::Size& dimensions,
+ base::Time timestamp,
+ int frame_rate) OVERRIDE;
virtual void OnError() OVERRIDE;
- virtual void OnFrameInfo(
- const media::VideoCaptureCapability& info) OVERRIDE;
- virtual void OnFrameInfoChanged(
- const media::VideoCaptureCapability& info) OVERRIDE;
private:
+ scoped_refptr<Buffer> DoReserveOutputBuffer(media::VideoFrame::Format format,
+ const gfx::Size& dimensions);
+
// The controller to which we post events.
const base::WeakPtr<VideoCaptureController> controller_;
// The pool of shared-memory buffers used for capturing.
- scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
-
- // Chopped pixels in width/height in case video capture device has odd
- // numbers for width/height.
- int chopped_width_;
- int chopped_height_;
-
- // Tracks the current frame format.
- media::VideoCaptureCapability frame_info_;
-
- // For NV21 we have to do color conversion into the intermediate buffer and
- // from there the rotations. This variable won't be needed after
- // http://crbug.com/292400
-#if defined(OS_IOS) || defined(OS_ANDROID)
- scoped_ptr<uint8[]> i420_intermediate_buffer_;
-#endif // #if defined(OS_IOS) || defined(OS_ANDROID)
+ const scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
};
VideoCaptureController::VideoCaptureController()
- : state_(VIDEO_CAPTURE_STATE_STARTED),
+ : buffer_pool_(new VideoCaptureBufferPool(kNoOfBuffers)),
+ state_(VIDEO_CAPTURE_STATE_STARTED),
weak_ptr_factory_(this) {
- memset(&current_params_, 0, sizeof(current_params_));
}
VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient(
- const base::WeakPtr<VideoCaptureController>& controller)
- : controller_(controller),
- chopped_width_(0),
- chopped_height_(0) {}
+ const base::WeakPtr<VideoCaptureController>& controller,
+ const scoped_refptr<VideoCaptureBufferPool>& buffer_pool)
+ : controller_(controller), buffer_pool_(buffer_pool) {}
VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {}
@@ -166,10 +151,10 @@ base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
-scoped_ptr<media::VideoCaptureDevice::EventHandler>
+scoped_ptr<media::VideoCaptureDevice::Client>
VideoCaptureController::NewDeviceClient() {
- scoped_ptr<media::VideoCaptureDevice::EventHandler> result(
- new VideoCaptureDeviceClient(this->GetWeakPtr()));
+ scoped_ptr<media::VideoCaptureDevice::Client> result(
+ new VideoCaptureDeviceClient(this->GetWeakPtr(), buffer_pool_));
return result.Pass();
}
@@ -177,15 +162,19 @@ void VideoCaptureController::AddClient(
const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler,
base::ProcessHandle render_process,
+ media::VideoCaptureSessionId session_id,
const media::VideoCaptureParams& params) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id
- << ", (" << params.width
- << ", " << params.height
- << ", " << params.frame_rate
- << ", " << params.session_id
+ << ", " << params.requested_format.frame_size.ToString()
+ << ", " << params.requested_format.frame_rate
+ << ", " << session_id
<< ")";
+ // If this is the first client added to the controller, cache the parameters.
+ if (!controller_clients_.size())
+ video_capture_format_ = params.requested_format;
+
// Signal error in case device is already in error state.
if (state_ == VIDEO_CAPTURE_STATE_ERROR) {
event_handler->OnError(id);
@@ -196,14 +185,11 @@ void VideoCaptureController::AddClient(
if (FindClient(id, event_handler, controller_clients_))
return;
- ControllerClient* client = new ControllerClient(id, event_handler,
- render_process, params);
+ ControllerClient* client = new ControllerClient(
+ id, event_handler, render_process, session_id, params);
// If we already have gotten frame_info from the device, repeat it to the new
// client.
if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
- if (frame_info_.IsValid()) {
- SendFrameInfoAndBuffers(client);
- }
controller_clients_.push_back(client);
return;
}
@@ -220,17 +206,15 @@ int VideoCaptureController::RemoveClient(
return kInvalidMediaCaptureSessionId;
// Take back all buffers held by the |client|.
- if (buffer_pool_.get()) {
- for (std::set<int>::iterator buffer_it = client->buffers.begin();
- buffer_it != client->buffers.end();
- ++buffer_it) {
- int buffer_id = *buffer_it;
- buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
- }
+ for (std::set<int>::iterator buffer_it = client->active_buffers.begin();
+ buffer_it != client->active_buffers.end();
+ ++buffer_it) {
+ int buffer_id = *buffer_it;
+ buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
}
- client->buffers.clear();
+ client->active_buffers.clear();
- int session_id = client->parameters.session_id;
+ int session_id = client->session_id;
controller_clients_.remove(client);
delete client;
@@ -259,83 +243,111 @@ void VideoCaptureController::ReturnBuffer(
// If this buffer is not held by this client, or this client doesn't exist
// in controller, do nothing.
- if (!client ||
- client->buffers.find(buffer_id) == client->buffers.end()) {
+ if (!client || !client->active_buffers.erase(buffer_id)) {
NOTREACHED();
return;
}
- client->buffers.erase(buffer_id);
buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
}
-scoped_refptr<media::VideoFrame>
-VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer() {
- return buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
- frame_info_.height),
- 0);
+const media::VideoCaptureFormat&
+VideoCaptureController::GetVideoCaptureFormat() const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ return video_capture_format_;
+}
+
+scoped_refptr<media::VideoCaptureDevice::Client::Buffer>
+VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer(
+ media::VideoFrame::Format format,
+ const gfx::Size& size) {
+ return DoReserveOutputBuffer(format, size);
}
-#if !defined(OS_IOS) && !defined(OS_ANDROID)
void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
const uint8* data,
int length,
base::Time timestamp,
int rotation,
- bool flip_vert,
- bool flip_horiz) {
+ const VideoCaptureFormat& frame_format) {
TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
- if (!buffer_pool_.get())
+ if (!frame_format.IsValid())
return;
- scoped_refptr<media::VideoFrame> dst = buffer_pool_->ReserveI420VideoFrame(
- gfx::Size(frame_info_.width, frame_info_.height), rotation);
- if (!dst.get())
- return;
+ // Chopped pixels in width/height in case video capture device has odd
+ // numbers for width/height.
+ int chopped_width = 0;
+ int chopped_height = 0;
+ int new_unrotated_width = frame_format.frame_size.width();
+ int new_unrotated_height = frame_format.frame_size.height();
+
+ if (new_unrotated_width & 1) {
+ --new_unrotated_width;
+ chopped_width = 1;
+ }
+ if (new_unrotated_height & 1) {
+ --new_unrotated_height;
+ chopped_height = 1;
+ }
+
+ int destination_width = new_unrotated_width;
+ int destination_height = new_unrotated_height;
+ if (rotation == 90 || rotation == 270) {
+ destination_width = new_unrotated_height;
+ destination_height = new_unrotated_width;
+ }
+ const gfx::Size dimensions(destination_width, destination_height);
+ scoped_refptr<Buffer> buffer =
+ DoReserveOutputBuffer(media::VideoFrame::I420, dimensions);
- uint8* yplane = dst->data(media::VideoFrame::kYPlane);
- uint8* uplane = dst->data(media::VideoFrame::kUPlane);
- uint8* vplane = dst->data(media::VideoFrame::kVPlane);
- int yplane_stride = frame_info_.width;
- int uv_plane_stride = (frame_info_.width + 1) / 2;
+ if (!buffer)
+ return;
+#if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW)
+ uint8* yplane = reinterpret_cast<uint8*>(buffer->data());
+ uint8* uplane =
+ yplane +
+ media::VideoFrame::PlaneAllocationSize(
+ media::VideoFrame::I420, media::VideoFrame::kYPlane, dimensions);
+ uint8* vplane =
+ uplane +
+ media::VideoFrame::PlaneAllocationSize(
+ media::VideoFrame::I420, media::VideoFrame::kUPlane, dimensions);
+ int yplane_stride = dimensions.width();
+ int uv_plane_stride = yplane_stride / 2;
int crop_x = 0;
int crop_y = 0;
libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY;
- // Assuming rotation happens first and flips next, we can consolidate both
- // vertical and horizontal flips together with rotation into two variables:
- // new_rotation = (rotation + 180 * vertical_flip) modulo 360
- // new_vertical_flip = horizontal_flip XOR vertical_flip
- int new_rotation_angle = (rotation + 180 * flip_vert) % 360;
+
libyuv::RotationMode rotation_mode = libyuv::kRotate0;
- if (new_rotation_angle == 90)
+ if (rotation == 90)
rotation_mode = libyuv::kRotate90;
- else if (new_rotation_angle == 180)
+ else if (rotation == 180)
rotation_mode = libyuv::kRotate180;
- else if (new_rotation_angle == 270)
+ else if (rotation == 270)
rotation_mode = libyuv::kRotate270;
- switch (frame_info_.color) {
+ switch (frame_format.pixel_format) {
case media::PIXEL_FORMAT_UNKNOWN: // Color format not set.
break;
case media::PIXEL_FORMAT_I420:
- DCHECK(!chopped_width_ && !chopped_height_);
+ DCHECK(!chopped_width && !chopped_height);
origin_colorspace = libyuv::FOURCC_I420;
break;
case media::PIXEL_FORMAT_YV12:
- DCHECK(!chopped_width_ && !chopped_height_);
+ DCHECK(!chopped_width && !chopped_height);
origin_colorspace = libyuv::FOURCC_YV12;
break;
case media::PIXEL_FORMAT_NV21:
- DCHECK(!chopped_width_ && !chopped_height_);
- origin_colorspace = libyuv::FOURCC_NV12;
+ DCHECK(!chopped_width && !chopped_height);
+ origin_colorspace = libyuv::FOURCC_NV21;
break;
case media::PIXEL_FORMAT_YUY2:
- DCHECK(!chopped_width_ && !chopped_height_);
+ DCHECK(!chopped_width && !chopped_height);
origin_colorspace = libyuv::FOURCC_YUY2;
break;
case media::PIXEL_FORMAT_UYVY:
- DCHECK(!chopped_width_ && !chopped_height_);
+ DCHECK(!chopped_width && !chopped_height);
origin_colorspace = libyuv::FOURCC_UYVY;
break;
case media::PIXEL_FORMAT_RGB24:
@@ -353,265 +365,84 @@ void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
int need_convert_rgb24_on_win = false;
#if defined(OS_WIN)
- // kRGB24 on Windows start at the bottom line and has a negative stride. This
- // is not supported by libyuv, so the media API is used instead.
- if (frame_info_.color == media::PIXEL_FORMAT_RGB24) {
- // Rotation and flipping is not supported in kRGB24 and OS_WIN case.
- DCHECK(!rotation && !flip_vert && !flip_horiz);
+ // TODO(wjia): Use libyuv::ConvertToI420 since support for image inversion
+ // (vertical flipping) has been added. Use negative src_height as indicator.
+ if (frame_format.pixel_format == media::PIXEL_FORMAT_RGB24) {
+ // Rotation is not supported in kRGB24 and OS_WIN case.
+ DCHECK(!rotation);
need_convert_rgb24_on_win = true;
}
#endif
if (need_convert_rgb24_on_win) {
- int rgb_stride = -3 * (frame_info_.width + chopped_width_);
+ int rgb_stride = -3 * (new_unrotated_width + chopped_width);
const uint8* rgb_src =
- data + 3 * (frame_info_.width + chopped_width_) *
- (frame_info_.height - 1 + chopped_height_);
+ data + 3 * (new_unrotated_width + chopped_width) *
+ (new_unrotated_height - 1 + chopped_height);
media::ConvertRGB24ToYUV(rgb_src,
yplane,
uplane,
vplane,
- frame_info_.width,
- frame_info_.height,
+ new_unrotated_width,
+ new_unrotated_height,
rgb_stride,
yplane_stride,
uv_plane_stride);
} else {
- libyuv::ConvertToI420(
- data,
- length,
- yplane,
- yplane_stride,
- uplane,
- uv_plane_stride,
- vplane,
- uv_plane_stride,
- crop_x,
- crop_y,
- frame_info_.width + chopped_width_,
- frame_info_.height * (flip_vert ^ flip_horiz ? -1 : 1),
- frame_info_.width,
- frame_info_.height,
- rotation_mode,
- origin_colorspace);
+ libyuv::ConvertToI420(data,
+ length,
+ yplane,
+ yplane_stride,
+ uplane,
+ uv_plane_stride,
+ vplane,
+ uv_plane_stride,
+ crop_x,
+ crop_y,
+ new_unrotated_width + chopped_width,
+ new_unrotated_height,
+ new_unrotated_width,
+ new_unrotated_height,
+ rotation_mode,
+ origin_colorspace);
}
+#else
+ // Libyuv is not linked in for Android WebView builds, but video capture is
+ // not used in those builds either. Whenever libyuv is added in that build,
+ // address all these #ifdef parts, see http://crbug.com/299611 .
+ NOTREACHED();
+#endif // if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW)
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- controller_,
- dst,
- timestamp));
-}
-#else
-void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
- const uint8* data,
- int length,
- base::Time timestamp,
- int rotation,
- bool flip_vert,
- bool flip_horiz) {
- DCHECK(frame_info_.color == media::PIXEL_FORMAT_I420 ||
- frame_info_.color == media::PIXEL_FORMAT_YV12 ||
- frame_info_.color == media::PIXEL_FORMAT_NV21 ||
- (rotation == 0 && !flip_vert && !flip_horiz));
-
- TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
-
- if (!buffer_pool_)
- return;
- scoped_refptr<media::VideoFrame> dst =
- buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
- frame_info_.height),
- rotation);
-
- if (!dst.get())
- return;
-
- uint8* yplane = dst->data(media::VideoFrame::kYPlane);
- uint8* uplane = dst->data(media::VideoFrame::kUPlane);
- uint8* vplane = dst->data(media::VideoFrame::kVPlane);
-
- // Do color conversion from the camera format to I420.
- switch (frame_info_.color) {
- case media::PIXEL_FORMAT_UNKNOWN: // Color format not set.
- break;
- case media::PIXEL_FORMAT_I420:
- DCHECK(!chopped_width_ && !chopped_height_);
- RotatePackedYV12Frame(
- data, yplane, uplane, vplane, frame_info_.width, frame_info_.height,
- rotation, flip_vert, flip_horiz);
- break;
- case media::PIXEL_FORMAT_YV12:
- DCHECK(!chopped_width_ && !chopped_height_);
- RotatePackedYV12Frame(
- data, yplane, vplane, uplane, frame_info_.width, frame_info_.height,
- rotation, flip_vert, flip_horiz);
- break;
- case media::PIXEL_FORMAT_NV21: {
- DCHECK(!chopped_width_ && !chopped_height_);
- int num_pixels = frame_info_.width * frame_info_.height;
- media::ConvertNV21ToYUV(data,
- &i420_intermediate_buffer_[0],
- &i420_intermediate_buffer_[num_pixels],
- &i420_intermediate_buffer_[num_pixels * 5 / 4],
- frame_info_.width,
- frame_info_.height);
- RotatePackedYV12Frame(
- i420_intermediate_buffer_.get(), yplane, uplane, vplane,
- frame_info_.width, frame_info_.height,
- rotation, flip_vert, flip_horiz);
- break;
- }
- case media::PIXEL_FORMAT_YUY2:
- DCHECK(!chopped_width_ && !chopped_height_);
- if (frame_info_.width * frame_info_.height * 2 != length) {
- // If |length| of |data| does not match the expected width and height
- // we can't convert the frame to I420. YUY2 is 2 bytes per pixel.
- break;
- }
-
- media::ConvertYUY2ToYUV(data, yplane, uplane, vplane, frame_info_.width,
- frame_info_.height);
- break;
- case media::PIXEL_FORMAT_RGB24: {
- int ystride = frame_info_.width;
- int uvstride = frame_info_.width / 2;
- int rgb_stride = 3 * (frame_info_.width + chopped_width_);
- const uint8* rgb_src = data;
- media::ConvertRGB24ToYUV(rgb_src, yplane, uplane, vplane,
- frame_info_.width, frame_info_.height,
- rgb_stride, ystride, uvstride);
- break;
- }
- case media::PIXEL_FORMAT_ARGB:
- media::ConvertRGB32ToYUV(data, yplane, uplane, vplane, frame_info_.width,
- frame_info_.height,
- (frame_info_.width + chopped_width_) * 4,
- frame_info_.width, frame_info_.width / 2);
- break;
- default:
- NOTREACHED();
- }
-
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- controller_, dst, timestamp));
+ base::Bind(
+ &VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread,
+ controller_,
+ buffer,
+ dimensions,
+ frame_format.frame_rate,
+ timestamp));
}
-#endif // #if !defined(OS_IOS) && !defined(OS_ANDROID)
-void
-VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame,
- base::Time timestamp) {
- if (!buffer_pool_)
- return;
-
- // If this is a frame that belongs to the buffer pool, we can forward it
- // directly to the IO thread and be done.
- if (buffer_pool_->RecognizeReservedBuffer(
- frame->shared_memory_handle()) >= 0) {
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- controller_, frame, timestamp));
- return;
- }
-
- // Otherwise, this is a frame that belongs to the caller, and we must copy
- // it to a frame from the buffer pool.
- scoped_refptr<media::VideoFrame> target =
- buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
- frame_info_.height),
- 0);
-
- if (!target.get())
- return;
-
- // Validate the inputs.
- if (frame->coded_size() != target->coded_size())
- return; // Only exact copies are supported.
- if (!(frame->format() == media::VideoFrame::I420 ||
- frame->format() == media::VideoFrame::YV12 ||
- frame->format() == media::VideoFrame::RGB32)) {
- NOTREACHED() << "Unsupported format passed to OnIncomingCapturedVideoFrame";
- return;
- }
-
- const int kYPlane = media::VideoFrame::kYPlane;
- const int kUPlane = media::VideoFrame::kUPlane;
- const int kVPlane = media::VideoFrame::kVPlane;
- const int kAPlane = media::VideoFrame::kAPlane;
- const int kRGBPlane = media::VideoFrame::kRGBPlane;
-
- // Do color conversion from the camera format to I420.
- switch (frame->format()) {
-#if defined(GOOGLE_TV)
- case media::VideoFrame::HOLE:
- // Fall-through to NOTREACHED() block.
-#endif
- case media::VideoFrame::INVALID:
- case media::VideoFrame::YV16:
- case media::VideoFrame::EMPTY:
- case media::VideoFrame::NATIVE_TEXTURE: {
- NOTREACHED();
- break;
- }
- case media::VideoFrame::I420:
- case media::VideoFrame::YV12: {
- DCHECK(!chopped_width_ && !chopped_height_);
- media::CopyYPlane(frame->data(kYPlane),
- frame->stride(kYPlane),
- frame->rows(kYPlane),
- target.get());
- media::CopyUPlane(frame->data(kUPlane),
- frame->stride(kUPlane),
- frame->rows(kUPlane),
- target.get());
- media::CopyVPlane(frame->data(kVPlane),
- frame->stride(kVPlane),
- frame->rows(kVPlane),
- target.get());
- break;
- }
- case media::VideoFrame::YV12A: {
- DCHECK(!chopped_width_ && !chopped_height_);
- media::CopyYPlane(frame->data(kYPlane),
- frame->stride(kYPlane),
- frame->rows(kYPlane),
- target.get());
- media::CopyUPlane(frame->data(kUPlane),
- frame->stride(kUPlane),
- frame->rows(kUPlane),
- target.get());
- media::CopyVPlane(frame->data(kVPlane),
- frame->stride(kVPlane),
- frame->rows(kVPlane),
- target.get());
- media::CopyAPlane(frame->data(kAPlane),
- frame->stride(kAPlane),
- frame->rows(kAPlane),
- target.get());
- break;
- }
- case media::VideoFrame::RGB32: {
- media::ConvertRGB32ToYUV(frame->data(kRGBPlane),
- target->data(kYPlane),
- target->data(kUPlane),
- target->data(kVPlane),
- target->coded_size().width(),
- target->coded_size().height(),
- frame->stride(kRGBPlane),
- target->stride(kYPlane),
- target->stride(kUPlane));
- break;
- }
- }
+void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedBuffer(
+ const scoped_refptr<Buffer>& buffer,
+ media::VideoFrame::Format format,
+ const gfx::Size& dimensions,
+ base::Time timestamp,
+ int frame_rate) {
+ // The capture pipeline expects I420 for now.
+ DCHECK_EQ(format, media::VideoFrame::I420)
+ << "Non-I420 output buffer returned";
- BrowserThread::PostTask(BrowserThread::IO,
+ BrowserThread::PostTask(
+ BrowserThread::IO,
FROM_HERE,
- base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
- controller_, target, timestamp));
+ base::Bind(
+ &VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread,
+ controller_,
+ buffer,
+ dimensions,
+ frame_rate,
+ timestamp));
}
void VideoCaptureController::VideoCaptureDeviceClient::OnError() {
@@ -620,167 +451,112 @@ void VideoCaptureController::VideoCaptureDeviceClient::OnError() {
base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_));
}
-void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo(
- const media::VideoCaptureCapability& info) {
- frame_info_ = info;
- // Handle cases when |info| has odd numbers for width/height.
- if (info.width & 1) {
- --frame_info_.width;
- chopped_width_ = 1;
- } else {
- chopped_width_ = 0;
- }
- if (info.height & 1) {
- --frame_info_.height;
- chopped_height_ = 1;
- } else {
- chopped_height_ = 0;
- }
-#if defined(OS_IOS) || defined(OS_ANDROID)
- if (frame_info_.color == media::PIXEL_FORMAT_NV21 &&
- !i420_intermediate_buffer_) {
- i420_intermediate_buffer_.reset(
- new uint8[frame_info_.width * frame_info_.height * 12 / 8]);
- }
-#endif // #if defined(OS_IOS) || defined(OS_ANDROID)
-
- DCHECK(!buffer_pool_.get());
-
- // TODO(nick): Give BufferPool the same lifetime as the controller, have it
- // support frame size changes, and stop checking it for NULL everywhere.
- // http://crbug.com/266082
- buffer_pool_ = new VideoCaptureBufferPool(
- media::VideoFrame::AllocationSize(
- media::VideoFrame::I420,
- gfx::Size(frame_info_.width, frame_info_.height)),
- kNoOfBuffers);
-
- // Check whether all buffers were created successfully.
- if (!buffer_pool_->Allocate()) {
- // Transition to the error state.
- buffer_pool_ = NULL;
- OnError();
- return;
+scoped_refptr<media::VideoCaptureDevice::Client::Buffer>
+VideoCaptureController::VideoCaptureDeviceClient::DoReserveOutputBuffer(
+ media::VideoFrame::Format format,
+ const gfx::Size& dimensions) {
+ // The capture pipeline expects I420 for now.
+ DCHECK_EQ(format, media::VideoFrame::I420)
+ << "Non-I420 output buffer requested";
+
+ int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId;
+ const size_t frame_bytes =
+ media::VideoFrame::AllocationSize(format, dimensions);
+
+ int buffer_id =
+ buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop);
+ if (buffer_id == VideoCaptureBufferPool::kInvalidId)
+ return NULL;
+ void* data;
+ size_t size;
+ buffer_pool_->GetBufferInfo(buffer_id, &data, &size);
+
+ scoped_refptr<media::VideoCaptureDevice::Client::Buffer> output_buffer(
+ new PoolBuffer(buffer_pool_, buffer_id, data, size));
+
+ if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) {
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread,
+ controller_, buffer_id_to_drop));
}
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, controller_,
- frame_info_, buffer_pool_));
-}
-
-void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged(
- const media::VideoCaptureCapability& info) {
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureController::DoFrameInfoChangedOnIOThread,
- controller_, info));
+ return output_buffer;
}
VideoCaptureController::~VideoCaptureController() {
- buffer_pool_ = NULL; // Release all buffers.
STLDeleteContainerPointers(controller_clients_.begin(),
controller_clients_.end());
}
-void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
- const scoped_refptr<media::VideoFrame>& reserved_frame,
+void VideoCaptureController::DoIncomingCapturedI420BufferOnIOThread(
+ scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer,
+ const gfx::Size& dimensions,
+ int frame_rate,
base::Time timestamp) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK_NE(buffer->id(), VideoCaptureBufferPool::kInvalidId);
- if (!buffer_pool_.get())
- return;
-
- int buffer_id = buffer_pool_->RecognizeReservedBuffer(
- reserved_frame->shared_memory_handle());
- if (buffer_id < 0) {
- NOTREACHED();
- return;
- }
+ VideoCaptureFormat frame_format(
+ dimensions, frame_rate, media::PIXEL_FORMAT_I420);
int count = 0;
if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
for (ControllerClients::iterator client_it = controller_clients_.begin();
client_it != controller_clients_.end(); ++client_it) {
- if ((*client_it)->session_closed)
+ ControllerClient* client = *client_it;
+ if (client->session_closed)
continue;
- (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id,
- buffer_id, timestamp);
- (*client_it)->buffers.insert(buffer_id);
+ bool is_new_buffer = client->known_buffers.insert(buffer->id()).second;
+ if (is_new_buffer) {
+ // On the first use of a buffer on a client, share the memory handle.
+ size_t memory_size = 0;
+ base::SharedMemoryHandle remote_handle = buffer_pool_->ShareToProcess(
+ buffer->id(), client->render_process_handle, &memory_size);
+ client->event_handler->OnBufferCreated(
+ client->controller_id, remote_handle, memory_size, buffer->id());
+ }
+
+ client->event_handler->OnBufferReady(
+ client->controller_id, buffer->id(), timestamp, frame_format);
+ bool inserted = client->active_buffers.insert(buffer->id()).second;
+ DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer->id();
count++;
}
}
- buffer_pool_->HoldForConsumers(buffer_id, count);
+ buffer_pool_->HoldForConsumers(buffer->id(), count);
}
-void VideoCaptureController::DoFrameInfoOnIOThread(
- const media::VideoCaptureCapability& frame_info,
- const scoped_refptr<VideoCaptureBufferPool>& buffer_pool) {
+void VideoCaptureController::DoErrorOnIOThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(!buffer_pool_.get()) << "Frame info should happen only once.";
-
- // Allocate memory only when device has been started.
- if (state_ != VIDEO_CAPTURE_STATE_STARTED)
- return;
-
- frame_info_ = frame_info;
- buffer_pool_ = buffer_pool;
+ state_ = VIDEO_CAPTURE_STATE_ERROR;
for (ControllerClients::iterator client_it = controller_clients_.begin();
client_it != controller_clients_.end(); ++client_it) {
- if ((*client_it)->session_closed)
- continue;
+ ControllerClient* client = *client_it;
+ if (client->session_closed)
+ continue;
- SendFrameInfoAndBuffers(*client_it);
+ client->event_handler->OnError(client->controller_id);
}
}
-void VideoCaptureController::DoFrameInfoChangedOnIOThread(
- const media::VideoCaptureCapability& info) {
+void VideoCaptureController::DoBufferDestroyedOnIOThread(
+ int buffer_id_to_drop) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- // TODO(mcasas): Here we should reallocate the VideoCaptureBufferPool, if
- // needed, to support the new video capture format. See crbug.com/266082.
- for (ControllerClients::iterator client_it = controller_clients_.begin();
- client_it != controller_clients_.end(); ++client_it) {
- if ((*client_it)->session_closed)
- continue;
- (*client_it)->event_handler->OnFrameInfoChanged(
- (*client_it)->controller_id,
- info.width,
- info.height,
- info.frame_rate);
- }
-}
-
-void VideoCaptureController::DoErrorOnIOThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- state_ = VIDEO_CAPTURE_STATE_ERROR;
- ControllerClients::iterator client_it;
- for (client_it = controller_clients_.begin();
+ for (ControllerClients::iterator client_it = controller_clients_.begin();
client_it != controller_clients_.end(); ++client_it) {
- if ((*client_it)->session_closed)
- continue;
-
- (*client_it)->event_handler->OnError((*client_it)->controller_id);
- }
-}
+ ControllerClient* client = *client_it;
+ if (client->session_closed)
+ continue;
-void VideoCaptureController::SendFrameInfoAndBuffers(ControllerClient* client) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(frame_info_.IsValid());
- client->event_handler->OnFrameInfo(client->controller_id,
- frame_info_);
- for (int buffer_id = 0; buffer_id < buffer_pool_->count(); ++buffer_id) {
- base::SharedMemoryHandle remote_handle =
- buffer_pool_->ShareToProcess(buffer_id, client->render_process_handle);
-
- client->event_handler->OnBufferCreated(client->controller_id,
- remote_handle,
- buffer_pool_->GetMemorySize(),
- buffer_id);
+ if (client->known_buffers.erase(buffer_id_to_drop)) {
+ client->event_handler->OnBufferDestroyed(client->controller_id,
+ buffer_id_to_drop);
+ }
}
}
@@ -805,7 +581,7 @@ VideoCaptureController::FindClient(
const ControllerClients& clients) {
for (ControllerClients::const_iterator client_it = clients.begin();
client_it != clients.end(); ++client_it) {
- if ((*client_it)->parameters.session_id == session_id) {
+ if ((*client_it)->session_id == session_id) {
return *client_it;
}
}
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 eda4ce31e01..8658cdeb278 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.h
@@ -30,7 +30,7 @@
//
// * VideoCaptureController indirectly observes a VideoCaptureDevice
// by means of its proxy, VideoCaptureDeviceClient, which implements
-// the VideoCaptureDevice::EventHandler interface. The proxy forwards
+// the VideoCaptureDevice::Client interface. The proxy forwards
// observed events to the VideoCaptureController on the IO thread.
// * A VideoCaptureController interacts with its clients (VideoCaptureHosts)
// via the VideoCaptureControllerEventHandler interface.
@@ -48,14 +48,12 @@
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_H_
#include <list>
-#include <map>
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
-#include "base/synchronization/lock.h"
#include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/common/content_export.h"
@@ -76,15 +74,15 @@ class CONTENT_EXPORT VideoCaptureController {
// Return a new VideoCaptureDeviceClient to forward capture events to this
// instance.
- scoped_ptr<media::VideoCaptureDevice::EventHandler> NewDeviceClient();
+ scoped_ptr<media::VideoCaptureDevice::Client> NewDeviceClient();
- // Start video capturing and try to use the resolution specified in
- // |params|.
- // When capturing starts, the |event_handler| will receive an OnFrameInfo()
- // call informing it of the resolution that was actually picked by the device.
+ // Start video capturing and try to use the resolution specified in |params|.
+ // Buffers will be shared to the client as necessary. The client will continue
+ // to receive frames from the device until RemoveClient() is called.
void AddClient(const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler,
base::ProcessHandle render_process,
+ media::VideoCaptureSessionId session_id,
const media::VideoCaptureParams& params);
// Stop video capture. This will take back all buffers held by by
@@ -106,6 +104,8 @@ class CONTENT_EXPORT VideoCaptureController {
VideoCaptureControllerEventHandler* event_handler,
int buffer_id);
+ const media::VideoCaptureFormat& GetVideoCaptureFormat() const;
+
private:
class VideoCaptureDeviceClient;
@@ -113,18 +113,14 @@ class CONTENT_EXPORT VideoCaptureController {
typedef std::list<ControllerClient*> ControllerClients;
// Worker functions on IO thread. Called by the VideoCaptureDeviceClient.
- void DoIncomingCapturedFrameOnIOThread(
- const scoped_refptr<media::VideoFrame>& captured_frame,
+ void DoIncomingCapturedI420BufferOnIOThread(
+ scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer,
+ const gfx::Size& dimensions,
+ int frame_rate,
base::Time timestamp);
- void DoFrameInfoOnIOThread(
- const media::VideoCaptureCapability& frame_info,
- const scoped_refptr<VideoCaptureBufferPool>& buffer_pool);
- void DoFrameInfoChangedOnIOThread(const media::VideoCaptureCapability& info);
void DoErrorOnIOThread();
void DoDeviceStoppedOnIOThread();
-
- // Send frame info and init buffers to |client|.
- void SendFrameInfoAndBuffers(ControllerClient* client);
+ void DoBufferDestroyedOnIOThread(int buffer_id_to_drop);
// Find a client of |id| and |handler| in |clients|.
ControllerClient* FindClient(
@@ -138,21 +134,17 @@ class CONTENT_EXPORT VideoCaptureController {
const ControllerClients& clients);
// The pool of shared-memory buffers used for capturing.
- scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
+ const scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
// All clients served by this controller.
ControllerClients controller_clients_;
- // The parameter that currently used for the capturing.
- media::VideoCaptureParams current_params_;
-
- // Tracks the current frame format.
- media::VideoCaptureCapability frame_info_;
-
// Takes on only the states 'STARTED' and 'ERROR'. 'ERROR' is an absorbing
// state which stops the flow of data to clients.
VideoCaptureState state_;
+ media::VideoCaptureFormat video_capture_format_;
+
base::WeakPtrFactory<VideoCaptureController> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureController);
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 4a2c294b0ba..6559a530b1d 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
@@ -8,10 +8,7 @@
#include "base/memory/shared_memory.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
-
-namespace media {
-class VideoCaptureCapability;
-}
+#include "media/video/capture/video_capture_types.h"
namespace content {
@@ -36,22 +33,19 @@ class CONTENT_EXPORT VideoCaptureControllerEventHandler {
// A buffer has been newly created.
virtual void OnBufferCreated(const VideoCaptureControllerID& id,
base::SharedMemoryHandle handle,
- int length, int buffer_id) = 0;
-
- // A buffer has been filled with I420 video.
- virtual void OnBufferReady(const VideoCaptureControllerID& id,
- int buffer_id,
- base::Time timestamp) = 0;
+ int length,
+ int buffer_id) = 0;
- // The frame resolution the VideoCaptureDevice capture video in.
- virtual void OnFrameInfo(const VideoCaptureControllerID& id,
- const media::VideoCaptureCapability& format) = 0;
+ // A previously created buffer has been freed and will no longer be used.
+ virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
+ int buffer_id) = 0;
- // The frame resolution the VideoCaptureDevice capture video in.
- virtual void OnFrameInfoChanged(const VideoCaptureControllerID& id,
- int width,
- int height,
- int frame_rate) {};
+ // A buffer has been filled with I420 video.
+ virtual void OnBufferReady(
+ const VideoCaptureControllerID& id,
+ int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format) = 0;
// The capture session has ended and no more frames will be sent.
virtual void OnEnded(const 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 fec0942dde0..20cc4e41a89 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
@@ -40,8 +40,8 @@ class MockVideoCaptureControllerEventHandler
// These mock methods are delegated to by our fake implementation of
// VideoCaptureControllerEventHandler, to be used in EXPECT_CALL().
MOCK_METHOD1(DoBufferCreated, void(const VideoCaptureControllerID&));
+ MOCK_METHOD1(DoBufferDestroyed, void(const VideoCaptureControllerID&));
MOCK_METHOD1(DoBufferReady, void(const VideoCaptureControllerID&));
- MOCK_METHOD1(DoFrameInfo, void(const VideoCaptureControllerID&));
MOCK_METHOD1(DoEnded, void(const VideoCaptureControllerID&));
MOCK_METHOD1(DoError, void(const VideoCaptureControllerID&));
@@ -53,19 +53,19 @@ class MockVideoCaptureControllerEventHandler
int length, int buffer_id) OVERRIDE {
DoBufferCreated(id);
}
+ virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
+ int buffer_id) OVERRIDE {
+ DoBufferDestroyed(id);
+ }
virtual void OnBufferReady(const VideoCaptureControllerID& id,
int buffer_id,
- base::Time timestamp) OVERRIDE {
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format) OVERRIDE {
DoBufferReady(id);
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(&VideoCaptureController::ReturnBuffer,
base::Unretained(controller_), id, this, buffer_id));
}
- virtual void OnFrameInfo(
- const VideoCaptureControllerID& id,
- const media::VideoCaptureCapability& format) OVERRIDE {
- DoFrameInfo(id);
- }
virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {
DoEnded(id);
// OnEnded() must respond by (eventually) unregistering the client.
@@ -103,7 +103,7 @@ class VideoCaptureControllerTest : public testing::Test {
scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_;
scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_;
scoped_ptr<VideoCaptureController> controller_;
- scoped_ptr<media::VideoCaptureDevice::EventHandler> device_;
+ scoped_ptr<media::VideoCaptureDevice::Client> device_;
private:
DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest);
@@ -113,19 +113,13 @@ class VideoCaptureControllerTest : public testing::Test {
// track of clients.
TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
media::VideoCaptureParams session_100;
- session_100.session_id = 100;
- session_100.width = 320;
- session_100.height = 240;
- session_100.frame_rate = 30;
-
+ session_100.requested_format = media::VideoCaptureFormat(
+ gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
media::VideoCaptureParams session_200 = session_100;
- session_200.session_id = 200;
media::VideoCaptureParams session_300 = session_100;
- session_300.session_id = 300;
media::VideoCaptureParams session_400 = session_100;
- session_400.session_id = 400;
// Intentionally use the same route ID for two of the clients: the device_ids
// are a per-VideoCaptureHost namespace, and can overlap across hosts.
@@ -137,18 +131,27 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
// Clients in controller: []
ASSERT_EQ(0, controller_->GetClientCount())
<< "Client count should initially be zero.";
- controller_->AddClient(client_a_route_1, client_a_.get(),
- base::kNullProcessHandle, session_100);
+ controller_->AddClient(client_a_route_1,
+ client_a_.get(),
+ base::kNullProcessHandle,
+ 100,
+ session_100);
// Clients in controller: [A/1]
ASSERT_EQ(1, controller_->GetClientCount())
<< "Adding client A/1 should bump client count.";;
- controller_->AddClient(client_a_route_2, client_a_.get(),
- base::kNullProcessHandle, session_200);
+ controller_->AddClient(client_a_route_2,
+ client_a_.get(),
+ base::kNullProcessHandle,
+ 200,
+ session_200);
// Clients in controller: [A/1, A/2]
ASSERT_EQ(2, controller_->GetClientCount())
<< "Adding client A/2 should bump client count.";
- controller_->AddClient(client_b_route_1, client_b_.get(),
- base::kNullProcessHandle, session_300);
+ controller_->AddClient(client_b_route_1,
+ client_b_.get(),
+ base::kNullProcessHandle,
+ 300,
+ session_300);
// Clients in controller: [A/1, A/2, B/1]
ASSERT_EQ(3, controller_->GetClientCount())
<< "Adding client B/1 should bump client count.";
@@ -167,8 +170,11 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
<< "Removing client B/1 should return its session_id.";
// Clients in controller: [A/1]
ASSERT_EQ(1, controller_->GetClientCount());
- controller_->AddClient(client_b_route_2, client_b_.get(),
- base::kNullProcessHandle, session_400);
+ controller_->AddClient(client_b_route_2,
+ client_b_.get(),
+ base::kNullProcessHandle,
+ 400,
+ session_400);
// Clients in controller: [A/1, B/2]
EXPECT_CALL(*client_a_, DoEnded(client_a_route_1)).Times(1);
@@ -208,27 +214,21 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
// thread and is intended to behave deterministically.
TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
media::VideoCaptureParams session_100;
- session_100.session_id = 100;
- session_100.width = 320;
- session_100.height = 240;
- session_100.frame_rate = 30;
+ session_100.requested_format = media::VideoCaptureFormat(
+ gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
media::VideoCaptureParams session_200 = session_100;
- session_200.session_id = 200;
media::VideoCaptureParams session_300 = session_100;
- session_300.session_id = 300;
- // session_id of 1 is kStartOpenSessionId, which should have special meaning
- // to VideoCaptureManager, but not to VideoCaptureController ... so test it.
media::VideoCaptureParams session_1 = session_100;
- session_1.session_id = VideoCaptureManager::kStartOpenSessionId;
+
+ gfx::Size capture_resolution(444, 200);
// The device format needn't match the VideoCaptureParams (the camera can do
- // what it wants). Pick something random to use for OnFrameInfo.
- media::VideoCaptureCapability device_format(
- 10, 10, 25, media::PIXEL_FORMAT_RGB24, 10, false,
- media::ConstantResolutionVideoCaptureDevice);
+ // what it wants). Pick something random.
+ media::VideoCaptureFormat device_format(
+ gfx::Size(10, 10), 25, media::PIXEL_FORMAT_RGB24);
const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1);
const VideoCaptureControllerID client_a_route_2(0xa2a2a2a2);
@@ -236,126 +236,155 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
const VideoCaptureControllerID client_b_route_2(0xb2b2b2b2);
// Start with two clients.
- controller_->AddClient(client_a_route_1, client_a_.get(),
- base::kNullProcessHandle, session_100);
- controller_->AddClient(client_b_route_1, client_b_.get(),
- base::kNullProcessHandle, session_300);
- ASSERT_EQ(2, controller_->GetClientCount());
-
- // The OnFrameInfo() event from the device, when processed by the controller,
- // should generate client OnFrameInfo() and OnBufferCreated() events.
+ controller_->AddClient(client_a_route_1,
+ client_a_.get(),
+ base::kNullProcessHandle,
+ 100,
+ session_100);
+ controller_->AddClient(client_b_route_1,
+ client_b_.get(),
+ base::kNullProcessHandle,
+ 300,
+ session_300);
+ controller_->AddClient(client_a_route_2,
+ client_a_.get(),
+ base::kNullProcessHandle,
+ 200,
+ session_200);
+ ASSERT_EQ(3, controller_->GetClientCount());
+
+ // Now, simulate an incoming captured buffer from the capture device. As a
+ // side effect this will cause the first buffer to be shared with clients.
+ uint8 buffer_no = 1;
+ scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer;
+ buffer =
+ device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
+ ASSERT_TRUE(buffer);
+ memset(buffer->data(), buffer_no++, buffer->size());
{
InSequence s;
- EXPECT_CALL(*client_a_, DoFrameInfo(client_a_route_1)).Times(1);
- EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(kPoolSize);
+ EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1);
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
}
{
InSequence s;
- EXPECT_CALL(*client_b_, DoFrameInfo(client_b_route_1)).Times(1);
- EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(kPoolSize);
+ EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1);
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
}
- device_->OnFrameInfo(device_format);
- base::RunLoop().RunUntilIdle();
- Mock::VerifyAndClearExpectations(client_a_.get());
- Mock::VerifyAndClearExpectations(client_b_.get());
-
- // When a third clients is subsequently added, the frame info and buffers
- // should immediately be shared to the new clients.
{
InSequence s;
- EXPECT_CALL(*client_a_, DoFrameInfo(client_a_route_2)).Times(1);
- EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(kPoolSize);
+ EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1);
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
}
- controller_->AddClient(client_a_route_2, client_a_.get(),
- base::kNullProcessHandle, session_200);
- Mock::VerifyAndClearExpectations(client_a_.get());
+ device_->OnIncomingCapturedBuffer(buffer,
+ media::VideoFrame::I420,
+ capture_resolution,
+ base::Time(),
+ device_format.frame_rate);
+ buffer = NULL;
- // Now, simulate an incoming captured frame from the capture device.
- uint8 frame_no = 1;
- scoped_refptr<media::VideoFrame> frame;
- frame = device_->ReserveOutputBuffer();
- ASSERT_TRUE(frame);
- media::FillYUV(frame, frame_no++, 0x22, 0x44);
- device_->OnIncomingCapturedVideoFrame(frame, base::Time());
- frame = NULL;
-
- // The buffer should be delivered to the clients in any order.
- EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
- EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
- EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
Mock::VerifyAndClearExpectations(client_b_.get());
- // Second frame. In this case pretend that the VideoFrame pointer is held
- // by the device for a long delay. This shouldn't affect anything.
- frame = device_->ReserveOutputBuffer();
- ASSERT_TRUE(frame);
- media::FillYUV(frame, frame_no++, 0x22, 0x44);
- device_->OnIncomingCapturedVideoFrame(frame, base::Time());
+ // Second buffer which ought to use the same shared memory buffer. In this
+ // case pretend that the Buffer pointer is held by the device for a long
+ // delay. This shouldn't affect anything.
+ buffer =
+ device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
+ ASSERT_TRUE(buffer);
+ memset(buffer->data(), buffer_no++, buffer->size());
+ device_->OnIncomingCapturedBuffer(buffer,
+ media::VideoFrame::I420,
+ capture_resolution,
+ base::Time(),
+ device_format.frame_rate);
+ buffer = NULL;
// The buffer should be delivered to the clients in any order.
EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(1);
- EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(1);
+ EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
Mock::VerifyAndClearExpectations(client_b_.get());
- frame = NULL;
- // Add a fourth client now that some frames have come through. It should get
- // the buffer info, but it won't get any frames until new ones are captured.
- {
- InSequence s;
- EXPECT_CALL(*client_b_, DoFrameInfo(client_b_route_2)).Times(1);
- EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
- }
- controller_->AddClient(client_b_route_2, client_b_.get(),
- base::kNullProcessHandle, session_1);
+ // Add a fourth client now that some buffers have come through.
+ controller_->AddClient(client_b_route_2,
+ client_b_.get(),
+ base::kNullProcessHandle,
+ 1,
+ session_1);
Mock::VerifyAndClearExpectations(client_b_.get());
- // Third, fourth, and fifth frames. Pretend they all arrive at the same time.
+ // Third, fourth, and fifth buffers. Pretend they all arrive at the same time.
for (int i = 0; i < kPoolSize; i++) {
- frame = device_->ReserveOutputBuffer();
- ASSERT_TRUE(frame);
- ASSERT_EQ(media::VideoFrame::I420, frame->format());
- media::FillYUV(frame, frame_no++, 0x22, 0x44);
- device_->OnIncomingCapturedVideoFrame(frame, base::Time());
-
+ buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420,
+ capture_resolution);
+ ASSERT_TRUE(buffer);
+ memset(buffer->data(), buffer_no++, buffer->size());
+ device_->OnIncomingCapturedBuffer(buffer,
+ media::VideoFrame::I420,
+ capture_resolution,
+ base::Time(),
+ device_format.frame_rate);
+ buffer = NULL;
}
// ReserveOutputBuffer ought to fail now, because the pool is depleted.
- ASSERT_FALSE(device_->ReserveOutputBuffer());
+ ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420,
+ capture_resolution));
+
+ // The new client needs to be told of 3 buffers; the old clients only 2.
+ EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
+ EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(kPoolSize);
+ EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1))
+ .Times(kPoolSize - 1);
EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1)).Times(kPoolSize);
+ EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2))
+ .Times(kPoolSize - 1);
EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(kPoolSize);
+ EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1))
+ .Times(kPoolSize - 1);
EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1)).Times(kPoolSize);
- EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(kPoolSize);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
Mock::VerifyAndClearExpectations(client_b_.get());
- // Now test the interaction of client shutdown and frame delivery.
+ // Now test the interaction of client shutdown and buffer delivery.
// Kill A1 via renderer disconnect (synchronous).
controller_->RemoveClient(client_a_route_1, client_a_.get());
// Kill B1 via session close (posts a task to disconnect).
EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1);
controller_->StopSession(300);
- // Queue up another frame.
- frame = device_->ReserveOutputBuffer();
- ASSERT_TRUE(frame);
- media::FillYUV(frame, frame_no++, 0x22, 0x44);
- device_->OnIncomingCapturedVideoFrame(frame, base::Time());
- frame = device_->ReserveOutputBuffer();
+ // Queue up another buffer.
+ buffer =
+ device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
+ ASSERT_TRUE(buffer);
+ memset(buffer->data(), buffer_no++, buffer->size());
+ device_->OnIncomingCapturedBuffer(buffer,
+ media::VideoFrame::I420,
+ capture_resolution,
+ base::Time(),
+ device_format.frame_rate);
+ buffer = NULL;
+ buffer =
+ device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
{
// Kill A2 via session close (posts a task to disconnect, but A2 must not
- // be sent either of these two frames)..
+ // be sent either of these two buffers).
EXPECT_CALL(*client_a_, DoEnded(client_a_route_2)).Times(1);
controller_->StopSession(200);
}
- ASSERT_TRUE(frame);
- media::FillYUV(frame, frame_no++, 0x22, 0x44);
- device_->OnIncomingCapturedVideoFrame(frame, base::Time());
+ ASSERT_TRUE(buffer);
+ memset(buffer->data(), buffer_no++, buffer->size());
+ device_->OnIncomingCapturedBuffer(buffer,
+ media::VideoFrame::I420,
+ capture_resolution,
+ base::Time(),
+ device_format.frame_rate);
+ buffer = NULL;
// B2 is the only client left, and is the only one that should
- // get the frame.
+ // get the buffer.
EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(2);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
@@ -366,19 +395,18 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// behavior of various operations after the error state has been signalled.
TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
media::VideoCaptureParams session_100;
- session_100.session_id = 100;
- session_100.width = 320;
- session_100.height = 240;
- session_100.frame_rate = 30;
+ session_100.requested_format = media::VideoCaptureFormat(
+ gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
media::VideoCaptureParams session_200 = session_100;
- session_200.session_id = 200;
+
+ const gfx::Size capture_resolution(320, 240);
const VideoCaptureControllerID route_id(0x99);
// Start with one client.
- controller_->AddClient(route_id, client_a_.get(),
- base::kNullProcessHandle, session_100);
+ controller_->AddClient(
+ route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
device_->OnError();
EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
base::RunLoop().RunUntilIdle();
@@ -387,17 +415,19 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
// Second client connects after the error state. It also should get told of
// the error.
EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
- controller_->AddClient(route_id, client_b_.get(),
- base::kNullProcessHandle, session_200);
+ controller_->AddClient(
+ route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_b_.get());
- // OnFrameInfo from the VCD should become a no-op after the error occurs.
- media::VideoCaptureCapability device_format(
- 10, 10, 25, media::PIXEL_FORMAT_ARGB, 10, false,
- media::ConstantResolutionVideoCaptureDevice);
+ scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
+ device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
+ ASSERT_TRUE(buffer);
+
+ device_->OnIncomingCapturedBuffer(
+ buffer, media::VideoFrame::I420, capture_resolution, base::Time(), 30);
+ buffer = NULL;
- device_->OnFrameInfo(device_format);
base::RunLoop().RunUntilIdle();
}
@@ -405,39 +435,37 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
// behavior of various operations after the error state has been signalled.
TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
media::VideoCaptureParams session_100;
- session_100.session_id = 100;
- session_100.width = 320;
- session_100.height = 240;
- session_100.frame_rate = 30;
+ session_100.requested_format = media::VideoCaptureFormat(
+ gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
media::VideoCaptureParams session_200 = session_100;
- session_200.session_id = 200;
const VideoCaptureControllerID route_id(0x99);
// Start with one client.
- controller_->AddClient(route_id, client_a_.get(),
- base::kNullProcessHandle, session_100);
- // OnFrameInfo from the VCD should become a no-op after the error occurs.
- media::VideoCaptureCapability device_format(
- 10, 10, 25, media::PIXEL_FORMAT_ARGB, 10, false,
- media::ConstantResolutionVideoCaptureDevice);
-
- // Start the device and get as far as exchanging buffers with the subprocess.
- // Then, signal an error and deliver the frame. The error should be propagated
- // to clients; the frame should not be.
- device_->OnFrameInfo(device_format);
- EXPECT_CALL(*client_a_, DoFrameInfo(route_id)).Times(1);
- EXPECT_CALL(*client_a_, DoBufferCreated(route_id)).Times(kPoolSize);
+ controller_->AddClient(
+ route_id, client_a_.get(), base::kNullProcessHandle, 100, session_100);
+ media::VideoCaptureFormat device_format(
+ gfx::Size(10, 10), 25, media::PIXEL_FORMAT_ARGB);
+
+ // Start the device. Then, before the first buffer, signal an error and
+ // deliver the buffer. The error should be propagated to clients; the buffer
+ // should not be.
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
- scoped_refptr<media::VideoFrame> frame = device_->ReserveOutputBuffer();
- ASSERT_TRUE(frame);
+ const gfx::Size dims(320, 240);
+ scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
+ device_->ReserveOutputBuffer(media::VideoFrame::I420, dims);
+ ASSERT_TRUE(buffer);
device_->OnError();
- device_->OnIncomingCapturedVideoFrame(frame, base::Time());
- frame = NULL;
+ device_->OnIncomingCapturedBuffer(buffer,
+ media::VideoFrame::I420,
+ dims,
+ base::Time(),
+ device_format.frame_rate);
+ buffer = NULL;
EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
base::RunLoop().RunUntilIdle();
@@ -446,8 +474,8 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
// Second client connects after the error state. It also should get told of
// the error.
EXPECT_CALL(*client_b_, DoError(route_id)).Times(1);
- controller_->AddClient(route_id, client_b_.get(),
- base::kNullProcessHandle, session_200);
+ controller_->AddClient(
+ route_id, client_b_.get(), base::kNullProcessHandle, 200, session_200);
Mock::VerifyAndClearExpectations(client_b_.get());
}
diff --git a/chromium/content/browser/renderer_host/media/video_capture_device_impl.cc b/chromium/content/browser/renderer_host/media/video_capture_device_impl.cc
new file mode 100644
index 00000000000..9b37b296c4f
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/video_capture_device_impl.cc
@@ -0,0 +1,304 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/media/video_capture_device_impl.h"
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback_forward.h"
+#include "base/callback_helpers.h"
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/metrics/histogram.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/stringprintf.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
+#include "content/public/browser/browser_thread.h"
+#include "media/base/bind_to_loop.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_util.h"
+#include "media/video/capture/video_capture_types.h"
+#include "ui/gfx/rect.h"
+
+namespace content {
+
+namespace {
+
+void DeleteCaptureMachineOnUIThread(
+ scoped_ptr<VideoCaptureMachine> capture_machine) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (capture_machine) {
+ capture_machine->Stop();
+ capture_machine.reset();
+ }
+}
+
+} // namespace
+
+ThreadSafeCaptureOracle::ThreadSafeCaptureOracle(
+ scoped_ptr<media::VideoCaptureDevice::Client> client,
+ scoped_ptr<VideoCaptureOracle> oracle,
+ const media::VideoCaptureParams& params)
+ : client_(client.Pass()),
+ oracle_(oracle.Pass()),
+ params_(params),
+ capture_size_updated_(false) {
+ // Frame dimensions must each be an even integer since the client wants (or
+ // will convert to) YUV420.
+ capture_size_ = gfx::Size(
+ MakeEven(params.requested_format.frame_size.width()),
+ MakeEven(params.requested_format.frame_size.height()));
+ frame_rate_ = params.requested_format.frame_rate;
+}
+
+ThreadSafeCaptureOracle::~ThreadSafeCaptureOracle() {}
+
+bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
+ VideoCaptureOracle::Event event,
+ base::Time event_time,
+ scoped_refptr<media::VideoFrame>* storage,
+ CaptureFrameCallback* callback) {
+ base::AutoLock guard(lock_);
+
+ if (!client_)
+ return false; // Capture is stopped.
+
+ scoped_refptr<media::VideoCaptureDevice::Client::Buffer> output_buffer =
+ client_->ReserveOutputBuffer(media::VideoFrame::I420, capture_size_);
+ const bool should_capture =
+ oracle_->ObserveEventAndDecideCapture(event, event_time);
+ const bool content_is_dirty =
+ (event == VideoCaptureOracle::kCompositorUpdate ||
+ event == VideoCaptureOracle::kSoftwarePaint);
+ const char* event_name =
+ (event == VideoCaptureOracle::kTimerPoll ? "poll" :
+ (event == VideoCaptureOracle::kCompositorUpdate ? "gpu" :
+ "paint"));
+
+ // Consider the various reasons not to initiate a capture.
+ if (should_capture && !output_buffer) {
+ TRACE_EVENT_INSTANT1("mirroring",
+ "EncodeLimited",
+ TRACE_EVENT_SCOPE_THREAD,
+ "trigger",
+ event_name);
+ return false;
+ } else if (!should_capture && output_buffer) {
+ if (content_is_dirty) {
+ // This is a normal and acceptable way to drop a frame. We've hit our
+ // capture rate limit: for example, the content is animating at 60fps but
+ // we're capturing at 30fps.
+ TRACE_EVENT_INSTANT1("mirroring", "FpsRateLimited",
+ TRACE_EVENT_SCOPE_THREAD,
+ "trigger", event_name);
+ }
+ return false;
+ } else if (!should_capture && !output_buffer) {
+ // We decided not to capture, but we wouldn't have been able to if we wanted
+ // to because no output buffer was available.
+ TRACE_EVENT_INSTANT1("mirroring", "NearlyEncodeLimited",
+ TRACE_EVENT_SCOPE_THREAD,
+ "trigger", event_name);
+ return false;
+ }
+ int frame_number = oracle_->RecordCapture();
+ TRACE_EVENT_ASYNC_BEGIN2("mirroring", "Capture", output_buffer.get(),
+ "frame_number", frame_number,
+ "trigger", event_name);
+ *callback = base::Bind(&ThreadSafeCaptureOracle::DidCaptureFrame,
+ this,
+ output_buffer,
+ frame_number);
+ *storage = media::VideoFrame::WrapExternalPackedMemory(
+ media::VideoFrame::I420,
+ capture_size_,
+ gfx::Rect(capture_size_),
+ capture_size_,
+ static_cast<uint8*>(output_buffer->data()),
+ output_buffer->size(),
+ base::SharedMemory::NULLHandle(),
+ base::TimeDelta(),
+ base::Closure());
+ return true;
+}
+
+void ThreadSafeCaptureOracle::UpdateCaptureSize(const gfx::Size& source_size) {
+ base::AutoLock guard(lock_);
+
+ // If this is the first call to UpdateCaptureSize(), or the receiver supports
+ // variable resolution, then determine the capture size by treating the
+ // requested width and height as maxima.
+ if (!capture_size_updated_ || params_.allow_resolution_change) {
+ // The capture resolution should not exceed the source frame size.
+ // In other words it should downscale the image but not upscale it.
+ if (source_size.width() > params_.requested_format.frame_size.width() ||
+ source_size.height() > params_.requested_format.frame_size.height()) {
+ gfx::Rect capture_rect = media::ComputeLetterboxRegion(
+ gfx::Rect(params_.requested_format.frame_size), source_size);
+ capture_size_ = gfx::Size(MakeEven(capture_rect.width()),
+ MakeEven(capture_rect.height()));
+ } else {
+ capture_size_ = gfx::Size(MakeEven(source_size.width()),
+ MakeEven(source_size.height()));
+ }
+ capture_size_updated_ = true;
+ }
+}
+
+void ThreadSafeCaptureOracle::Stop() {
+ base::AutoLock guard(lock_);
+ client_.reset();
+}
+
+void ThreadSafeCaptureOracle::ReportError() {
+ base::AutoLock guard(lock_);
+ if (client_)
+ client_->OnError();
+}
+
+void ThreadSafeCaptureOracle::DidCaptureFrame(
+ scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer,
+ int frame_number,
+ base::Time timestamp,
+ bool success) {
+ base::AutoLock guard(lock_);
+ TRACE_EVENT_ASYNC_END2("mirroring", "Capture", buffer.get(),
+ "success", success,
+ "timestamp", timestamp.ToInternalValue());
+
+ if (!client_)
+ return; // Capture is stopped.
+
+ if (success) {
+ if (oracle_->CompleteCapture(frame_number, timestamp)) {
+ client_->OnIncomingCapturedBuffer(buffer,
+ media::VideoFrame::I420,
+ capture_size_,
+ timestamp,
+ frame_rate_);
+ }
+ }
+}
+
+void VideoCaptureDeviceImpl::AllocateAndStart(
+ const media::VideoCaptureParams& params,
+ scoped_ptr<media::VideoCaptureDevice::Client> client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (state_ != kIdle) {
+ DVLOG(1) << "Allocate() invoked when not in state Idle.";
+ return;
+ }
+
+ if (params.requested_format.frame_rate <= 0) {
+ DVLOG(1) << "invalid frame_rate: " << params.requested_format.frame_rate;
+ client->OnError();
+ return;
+ }
+
+ if (params.requested_format.frame_size.width() < kMinFrameWidth ||
+ params.requested_format.frame_size.height() < kMinFrameHeight) {
+ DVLOG(1) << "invalid frame size: "
+ << params.requested_format.frame_size.ToString();
+ client->OnError();
+ return;
+ }
+
+ base::TimeDelta capture_period = base::TimeDelta::FromMicroseconds(
+ 1000000.0 / params.requested_format.frame_rate + 0.5);
+
+ scoped_ptr<VideoCaptureOracle> oracle(
+ new VideoCaptureOracle(capture_period,
+ kAcceleratedSubscriberIsSupported));
+ oracle_proxy_ =
+ new ThreadSafeCaptureOracle(client.Pass(), oracle.Pass(), params);
+
+ // Starts the capture machine asynchronously.
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&VideoCaptureMachine::Start,
+ base::Unretained(capture_machine_.get()),
+ oracle_proxy_),
+ base::Bind(&VideoCaptureDeviceImpl::CaptureStarted,
+ AsWeakPtr()));
+
+ TransitionStateTo(kCapturing);
+}
+
+void VideoCaptureDeviceImpl::StopAndDeAllocate() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (state_ != kCapturing)
+ return;
+
+ oracle_proxy_->Stop();
+ oracle_proxy_ = NULL;
+
+ TransitionStateTo(kIdle);
+
+ // Stops the capture machine asynchronously.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE, base::Bind(
+ &VideoCaptureMachine::Stop,
+ base::Unretained(capture_machine_.get())));
+}
+
+void VideoCaptureDeviceImpl::CaptureStarted(bool success) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!success) {
+ DVLOG(1) << "Failed to start capture machine.";
+ Error();
+ }
+}
+
+VideoCaptureDeviceImpl::VideoCaptureDeviceImpl(
+ scoped_ptr<VideoCaptureMachine> capture_machine)
+ : state_(kIdle),
+ capture_machine_(capture_machine.Pass()) {}
+
+VideoCaptureDeviceImpl::~VideoCaptureDeviceImpl() {
+ // If capture_machine is not NULL, then we need to return to the UI thread to
+ // safely stop the capture machine.
+ if (capture_machine_) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE, base::Bind(
+ &DeleteCaptureMachineOnUIThread, base::Passed(&capture_machine_)));
+ }
+ DVLOG(1) << "VideoCaptureDeviceImpl@" << this << " destroying.";
+}
+
+void VideoCaptureDeviceImpl::TransitionStateTo(State next_state) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+#ifndef NDEBUG
+ static const char* kStateNames[] = {
+ "Idle", "Allocated", "Capturing", "Error"
+ };
+ DVLOG(1) << "State change: " << kStateNames[state_]
+ << " --> " << kStateNames[next_state];
+#endif
+
+ state_ = next_state;
+}
+
+void VideoCaptureDeviceImpl::Error() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (state_ == kIdle)
+ return;
+
+ if (oracle_proxy_)
+ oracle_proxy_->ReportError();
+
+ StopAndDeAllocate();
+ TransitionStateTo(kError);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_device_impl.h b/chromium/content/browser/renderer_host/media/video_capture_device_impl.h
new file mode 100644
index 00000000000..d9329b6aa43
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/video_capture_device_impl.h
@@ -0,0 +1,191 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_DEVICE_IMPL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_DEVICE_IMPL_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_checker.h"
+#include "content/browser/renderer_host/media/video_capture_oracle.h"
+#include "content/common/content_export.h"
+#include "media/video/capture/video_capture_device.h"
+
+namespace content {
+
+const int kMinFrameWidth = 2;
+const int kMinFrameHeight = 2;
+
+// Returns the nearest even integer closer to zero.
+template<typename IntType>
+IntType MakeEven(IntType x) {
+ return x & static_cast<IntType>(-2);
+}
+
+// TODO(nick): Remove this once frame subscription is supported on Aura and
+// Linux.
+#if (defined(OS_WIN) || defined(OS_MACOSX)) || defined(USE_AURA)
+const bool kAcceleratedSubscriberIsSupported = true;
+#else
+const bool kAcceleratedSubscriberIsSupported = false;
+#endif
+
+class VideoCaptureMachine;
+
+// Thread-safe, refcounted proxy to the VideoCaptureOracle. This proxy wraps
+// the VideoCaptureOracle, which decides which frames to capture, and a
+// VideoCaptureDevice::Client, which allocates and receives the captured
+// frames, in a lock to synchronize state between the two.
+class ThreadSafeCaptureOracle
+ : public base::RefCountedThreadSafe<ThreadSafeCaptureOracle> {
+ public:
+ ThreadSafeCaptureOracle(scoped_ptr<media::VideoCaptureDevice::Client> client,
+ scoped_ptr<VideoCaptureOracle> oracle,
+ const media::VideoCaptureParams& params);
+
+ // Called when a captured frame is available or an error has occurred.
+ // If |success| is true then the frame provided is valid and |timestamp|
+ // indicates when the frame was painted.
+ // If |success| is false, both the frame provided and |timestamp| are invalid.
+ typedef base::Callback<void(base::Time timestamp, bool success)>
+ CaptureFrameCallback;
+
+ bool ObserveEventAndDecideCapture(VideoCaptureOracle::Event event,
+ base::Time event_time,
+ scoped_refptr<media::VideoFrame>* storage,
+ CaptureFrameCallback* callback);
+
+ base::TimeDelta capture_period() const {
+ return oracle_->capture_period();
+ }
+
+ // Updates capture resolution based on the supplied source size and the
+ // maximum frame size.
+ void UpdateCaptureSize(const gfx::Size& source_size);
+
+ // Stop new captures from happening (but doesn't forget the client).
+ void Stop();
+
+ // Signal an error to the client.
+ void ReportError();
+
+ private:
+ friend class base::RefCountedThreadSafe<ThreadSafeCaptureOracle>;
+ virtual ~ThreadSafeCaptureOracle();
+
+ // Callback invoked on completion of all captures.
+ void DidCaptureFrame(
+ scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer,
+ int frame_number,
+ base::Time timestamp,
+ bool success);
+ // Protects everything below it.
+ base::Lock lock_;
+
+ // Recipient of our capture activity.
+ scoped_ptr<media::VideoCaptureDevice::Client> client_;
+
+ // Makes the decision to capture a frame.
+ const scoped_ptr<VideoCaptureOracle> oracle_;
+
+ // The video capture parameters used to construct the oracle proxy.
+ const media::VideoCaptureParams params_;
+
+ // Indicates if capture size has been updated after construction.
+ bool capture_size_updated_;
+
+ // The current capturing resolution and frame rate.
+ gfx::Size capture_size_;
+ int frame_rate_;
+};
+
+// Keeps track of the video capture source frames and executes copying on the
+// UI BrowserThread.
+class VideoCaptureMachine {
+ public:
+ VideoCaptureMachine() : started_(false) {}
+ virtual ~VideoCaptureMachine() {}
+
+ // This should only be checked on the UI thread.
+ bool started() const { return started_; }
+
+ // Starts capturing. Returns true if succeeded.
+ // Must be run on the UI BrowserThread.
+ virtual bool Start(
+ const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) = 0;
+
+ // Stops capturing. Must be run on the UI BrowserThread.
+ virtual void Stop() = 0;
+
+ protected:
+ bool started_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VideoCaptureMachine);
+};
+
+// The "meat" of the video capture implementation.
+//
+// Separating this from the "shell classes" WebContentsVideoCaptureDevice and
+// BrowserCompositorCaptureDevice allows safe destruction without needing to
+// block any threads (e.g., the IO BrowserThread), as well as code sharing.
+//
+// VideoCaptureDeviceImpl manages a simple state machine and the pipeline (see
+// notes at top of this file). It times the start of successive
+// captures and facilitates the processing of each through the stages of the
+// pipeline.
+class CONTENT_EXPORT VideoCaptureDeviceImpl
+ : public base::SupportsWeakPtr<VideoCaptureDeviceImpl> {
+ public:
+ VideoCaptureDeviceImpl(scoped_ptr<VideoCaptureMachine> capture_machine);
+ virtual ~VideoCaptureDeviceImpl();
+
+ // Asynchronous requests to change VideoCaptureDeviceImpl state.
+ void AllocateAndStart(const media::VideoCaptureParams& params,
+ scoped_ptr<media::VideoCaptureDevice::Client> client);
+ void StopAndDeAllocate();
+
+ private:
+ // Flag indicating current state.
+ enum State {
+ kIdle,
+ kCapturing,
+ kError
+ };
+
+ void TransitionStateTo(State next_state);
+
+ // Called on the IO thread in response to StartCaptureMachine().
+ // |success| is true if capture machine succeeded to start.
+ void CaptureStarted(bool success);
+
+ // Stops capturing and notifies client_ of an error state.
+ void Error();
+
+ // Tracks that all activity occurs on the media stream manager's thread.
+ base::ThreadChecker thread_checker_;
+
+ // Current lifecycle state.
+ State state_;
+
+ // Tracks the CaptureMachine that's doing work on our behalf on the UI thread.
+ // This value should never be dereferenced by this class, other than to
+ // create and destroy it on the UI thread.
+ scoped_ptr<VideoCaptureMachine> capture_machine_;
+
+ // Our thread-safe capture oracle which serves as the gateway to the video
+ // capture pipeline. Besides the WCVCD itself, it is the only component of the
+ // system with direct access to |client_|.
+ scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceImpl);
+};
+
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_DEVICE_IMPL_H_
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 7ed77ae53d3..039d9815ab6 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.cc
@@ -20,8 +20,6 @@ VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager)
VideoCaptureHost::~VideoCaptureHost() {}
void VideoCaptureHost::OnChannelClosing() {
- BrowserMessageFilter::OnChannelClosing();
-
// Since the IPC channel is gone, close all requested VideoCaptureDevices.
for (EntryMap::iterator it = entries_.begin(); it != entries_.end(); it++) {
const base::WeakPtr<VideoCaptureController>& controller = it->second;
@@ -59,35 +57,25 @@ void VideoCaptureHost::OnBufferCreated(
this, controller_id, handle, length, buffer_id));
}
-void VideoCaptureHost::OnBufferReady(
+void VideoCaptureHost::OnBufferDestroyed(
const VideoCaptureControllerID& controller_id,
- int buffer_id,
- base::Time timestamp) {
+ int buffer_id) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureHost::DoSendFilledBufferOnIOThread,
- this, controller_id, buffer_id, timestamp));
-}
-
-void VideoCaptureHost::OnFrameInfo(
- const VideoCaptureControllerID& controller_id,
- const media::VideoCaptureCapability& format) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&VideoCaptureHost::DoSendFrameInfoOnIOThread,
- this, controller_id, format));
+ base::Bind(&VideoCaptureHost::DoSendFreeBufferOnIOThread,
+ this, controller_id, buffer_id));
}
-void VideoCaptureHost::OnFrameInfoChanged(
+void VideoCaptureHost::OnBufferReady(
const VideoCaptureControllerID& controller_id,
- int width,
- int height,
- int frame_rate) {
+ int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& frame_format) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureHost::DoSendFrameInfoChangedOnIOThread,
- this, controller_id, width, height, frame_rate));
+ base::Bind(&VideoCaptureHost::DoSendFilledBufferOnIOThread,
+ this, controller_id, buffer_id, timestamp,
+ frame_format));
}
void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) {
@@ -111,16 +99,28 @@ void VideoCaptureHost::DoSendNewBufferOnIOThread(
length, buffer_id));
}
+void VideoCaptureHost::DoSendFreeBufferOnIOThread(
+ const VideoCaptureControllerID& controller_id,
+ int buffer_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ if (entries_.find(controller_id) == entries_.end())
+ return;
+
+ Send(new VideoCaptureMsg_FreeBuffer(controller_id.device_id, buffer_id));
+}
+
void VideoCaptureHost::DoSendFilledBufferOnIOThread(
const VideoCaptureControllerID& controller_id,
- int buffer_id, base::Time timestamp) {
+ int buffer_id, base::Time timestamp,
+ const media::VideoCaptureFormat& format) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (entries_.find(controller_id) == entries_.end())
return;
Send(new VideoCaptureMsg_BufferReady(controller_id.device_id, buffer_id,
- timestamp));
+ timestamp, format));
}
void VideoCaptureHost::DoHandleErrorOnIOThread(
@@ -147,41 +147,6 @@ void VideoCaptureHost::DoEndedOnIOThread(
DeleteVideoCaptureControllerOnIOThread(controller_id);
}
-void VideoCaptureHost::DoSendFrameInfoOnIOThread(
- const VideoCaptureControllerID& controller_id,
- const media::VideoCaptureCapability& format) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- if (entries_.find(controller_id) == entries_.end())
- return;
-
- media::VideoCaptureParams params;
- params.width = format.width;
- params.height = format.height;
- params.frame_rate = format.frame_rate;
- params.frame_size_type = format.frame_size_type;
- Send(new VideoCaptureMsg_DeviceInfo(controller_id.device_id, params));
- Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
- VIDEO_CAPTURE_STATE_STARTED));
-}
-
-void VideoCaptureHost::DoSendFrameInfoChangedOnIOThread(
- const VideoCaptureControllerID& controller_id,
- int width,
- int height,
- int frame_rate) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- if (entries_.find(controller_id) == entries_.end())
- return;
-
- media::VideoCaptureParams params;
- params.width = width;
- params.height = height;
- params.frame_rate = frame_rate;
- Send(new VideoCaptureMsg_DeviceInfoChanged(controller_id.device_id, params));
-}
-
///////////////////////////////////////////////////////////////////////////////
// IPC Messages handler.
bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message,
@@ -199,35 +164,43 @@ bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message,
}
void VideoCaptureHost::OnStartCapture(int device_id,
+ media::VideoCaptureSessionId session_id,
const media::VideoCaptureParams& params) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DVLOG(1) << "VideoCaptureHost::OnStartCapture, device_id " << device_id
- << ", (" << params.width << ", " << params.height << ", "
- << params.frame_rate << ", " << params.session_id
- << ", variable resolution device:"
- << ((params.frame_size_type ==
- media::VariableResolutionVideoCaptureDevice) ? "yes" : "no")
- << ")";
+ DVLOG(1) << "VideoCaptureHost::OnStartCapture:"
+ << " session_id=" << session_id
+ << ", device_id=" << device_id
+ << ", format=" << params.requested_format.frame_size.ToString()
+ << "@" << params.requested_format.frame_rate
+ << " (" << (params.allow_resolution_change ? "variable" : "constant")
+ << ")";
VideoCaptureControllerID controller_id(device_id);
DCHECK(entries_.find(controller_id) == entries_.end());
entries_[controller_id] = base::WeakPtr<VideoCaptureController>();
media_stream_manager_->video_capture_manager()->StartCaptureForClient(
- params, PeerHandle(), controller_id, this, base::Bind(
- &VideoCaptureHost::OnControllerAdded, this, device_id, params));
+ session_id,
+ params,
+ PeerHandle(),
+ controller_id,
+ this,
+ base::Bind(&VideoCaptureHost::OnControllerAdded, this, device_id));
}
void VideoCaptureHost::OnControllerAdded(
- int device_id, const media::VideoCaptureParams& params,
+ int device_id,
const base::WeakPtr<VideoCaptureController>& controller) {
BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ BrowserThread::IO,
+ FROM_HERE,
base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread,
- this, device_id, params, controller));
+ this,
+ device_id,
+ controller));
}
void VideoCaptureHost::DoControllerAddedOnIOThread(
- int device_id, const media::VideoCaptureParams params,
+ int device_id,
const base::WeakPtr<VideoCaptureController>& controller) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
VideoCaptureControllerID controller_id(device_id);
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 6ce395631eb..b71aac3715c 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.h
@@ -5,33 +5,48 @@
// VideoCaptureHost serves video capture related messages from
// VideoCaptureMessageFilter which lives inside the render process.
//
-// This class is owned by BrowserRenderProcessHost, and instantiated on UI
+// This class is owned by RenderProcessHostImpl, and instantiated on UI
// thread, but all other operations and method calls happen on IO thread.
//
// Here's an example of a typical IPC dialog for video capture:
//
-// Renderer VideoCaptureHost
-// | |
-// | VideoCaptureHostMsg_Start > |
-// | < VideoCaptureMsg_DeviceInfo |
-// | |
-// | < VideoCaptureMsg_StateChanged |
-// | (kStarted) |
-// | < VideoCaptureMsg_BufferReady |
-// | ... |
-// | < VideoCaptureMsg_BufferReady |
-// | ... |
-// | VideoCaptureHostMsg_BufferReady > |
-// | VideoCaptureHostMsg_BufferReady > |
-// | |
-// | ... |
-// | |
-// | < VideoCaptureMsg_BufferReady |
-// | VideoCaptureHostMsg_Stop > |
-// | VideoCaptureHostMsg_BufferReady > |
-// | < VideoCaptureMsg_StateChanged |
-// | (kStopped) |
-// v v
+// Renderer VideoCaptureHost
+// | |
+// | VideoCaptureHostMsg_Start > |
+// | < VideoCaptureMsg_StateChanged |
+// | (VIDEO_CAPTURE_STATE_STARTED) |
+// | < VideoCaptureMsg_NewBuffer(1) |
+// | < VideoCaptureMsg_NewBuffer(2) |
+// | < VideoCaptureMsg_NewBuffer(3) |
+// | |
+// | < VideoCaptureMsg_BufferReady(1) |
+// | < VideoCaptureMsg_BufferReady(2) |
+// | VideoCaptureHostMsg_BufferReady(1) > |
+// | < VideoCaptureMsg_BufferReady(3) |
+// | VideoCaptureHostMsg_BufferReady(2) > |
+// | < VideoCaptureMsg_BufferReady(1) |
+// | VideoCaptureHostMsg_BufferReady(3) > |
+// | < VideoCaptureMsg_BufferReady(2) |
+// | VideoCaptureHostMsg_BufferReady(1) > |
+// | ... |
+// | < VideoCaptureMsg_BufferReady(3) |
+// | |
+// | ... (resolution change) |
+// | < VideoCaptureMsg_FreeBuffer(1) | Buffers are re-allocated
+// | < VideoCaptureMsg_NewBuffer(4) | at a larger size, as
+// | < VideoCaptureMsg_BufferReady(4) | needed.
+// | VideoCaptureHostMsg_BufferReady(2) > |
+// | < VideoCaptureMsg_FreeBuffer(2) |
+// | < VideoCaptureMsg_NewBuffer(5) |
+// | < VideoCaptureMsg_BufferReady(5) |
+// | ... |
+// | |
+// | < VideoCaptureMsg_BufferReady |
+// | VideoCaptureHostMsg_Stop > |
+// | VideoCaptureHostMsg_BufferReady > |
+// | < VideoCaptureMsg_StateChanged |
+// | (VIDEO_CAPTURE_STATE_STOPPED) |
+// v v
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_HOST_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_HOST_H_
@@ -46,10 +61,6 @@
#include "content/public/browser/browser_message_filter.h"
#include "ipc/ipc_message.h"
-namespace media {
-class VideoCaptureCapability;
-}
-
namespace content {
class MediaStreamManager;
@@ -69,17 +80,15 @@ class CONTENT_EXPORT VideoCaptureHost
virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE;
virtual void OnBufferCreated(const VideoCaptureControllerID& id,
base::SharedMemoryHandle handle,
- int length, int buffer_id) OVERRIDE;
- virtual void OnBufferReady(const VideoCaptureControllerID& id,
- int buffer_id,
- base::Time timestamp) OVERRIDE;
- virtual void OnFrameInfo(
+ int length,
+ int buffer_id) OVERRIDE;
+ virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
+ int buffer_id) OVERRIDE;
+ virtual void OnBufferReady(
const VideoCaptureControllerID& id,
- const media::VideoCaptureCapability& format) OVERRIDE;
- virtual void OnFrameInfoChanged(const VideoCaptureControllerID& id,
- int width,
- int height,
- int frame_per_second) OVERRIDE;
+ int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format) OVERRIDE;
virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE;
private:
@@ -91,16 +100,17 @@ class CONTENT_EXPORT VideoCaptureHost
virtual ~VideoCaptureHost();
// IPC message: Start capture on the VideoCaptureDevice referenced by
- // VideoCaptureParams::session_id. |device_id| is an id created by
- // VideoCaptureMessageFilter to identify a session
- // between a VideoCaptureMessageFilter and a VideoCaptureHost.
+ // |session_id|. |device_id| is an id created by VideoCaptureMessageFilter
+ // to identify a session between a VideoCaptureMessageFilter and a
+ // VideoCaptureHost.
void OnStartCapture(int device_id,
+ media::VideoCaptureSessionId session_id,
const media::VideoCaptureParams& params);
void OnControllerAdded(
- int device_id, const media::VideoCaptureParams& params,
+ int device_id,
const base::WeakPtr<VideoCaptureController>& controller);
void DoControllerAddedOnIOThread(
- int device_id, const media::VideoCaptureParams params,
+ int device_id,
const base::WeakPtr<VideoCaptureController>& controller);
// IPC message: Stop capture on device referenced by |device_id|.
@@ -120,24 +130,16 @@ class CONTENT_EXPORT VideoCaptureHost
int length,
int buffer_id);
+ void DoSendFreeBufferOnIOThread(
+ const VideoCaptureControllerID& controller_id,
+ int buffer_id);
+
// Send a filled buffer to the VideoCaptureMessageFilter.
void DoSendFilledBufferOnIOThread(
const VideoCaptureControllerID& controller_id,
int buffer_id,
- base::Time timestamp);
-
- // Send information about the capture parameters (resolution, frame rate etc)
- // to the VideoCaptureMessageFilter.
- void DoSendFrameInfoOnIOThread(const VideoCaptureControllerID& controller_id,
- const media::VideoCaptureCapability& format);
-
- // Send newly changed information about frame resolution and frame rate
- // to the VideoCaptureMessageFilter.
- void DoSendFrameInfoChangedOnIOThread(
- const VideoCaptureControllerID& controller_id,
- int width,
- int height,
- int frame_per_second);
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format);
// Handle error coming from VideoCaptureDevice.
void DoHandleErrorOnIOThread(const VideoCaptureControllerID& controller_id);
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
index ca1891dc426..c7ffcd5c69f 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
@@ -14,11 +14,15 @@
#include "base/strings/stringprintf.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/browser/renderer_host/media/media_stream_requester.h"
+#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
#include "content/browser/renderer_host/media/video_capture_host.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/video_capture_messages.h"
#include "content/public/test/mock_resource_context.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/test_content_browser_client.h"
#include "media/audio/audio_manager.h"
#include "media/base/video_frame.h"
#include "media/video/capture/video_capture_types.h"
@@ -33,15 +37,14 @@ using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Mock;
using ::testing::Return;
+using ::testing::SaveArg;
+using ::testing::StrictMock;
namespace content {
// Id used to identify the capture session between renderer and
// video_capture_host. This is an arbitrary value.
static const int kDeviceId = 555;
-// Id of a video capture device
-static const media::VideoCaptureSessionId kTestFakeSessionId =
- VideoCaptureManager::kStartOpenSessionId;
// Define to enable test where video is dumped to file.
// #define DUMP_VIDEO
@@ -57,13 +60,13 @@ class DumpVideo {
void StartDump(int width, int height) {
base::FilePath file_name = base::FilePath(base::StringPrintf(
FILE_PATH_LITERAL("dump_w%d_h%d.yuv"), width, height));
- file_.reset(file_util::OpenFile(file_name, "wb"));
+ file_.reset(base::OpenFile(file_name, "wb"));
expected_size_ = media::VideoFrame::AllocationSize(
media::VideoFrame::I420, gfx::Size(width, height));
}
void NewVideoFrame(const void* buffer) {
if (file_.get() != NULL) {
- fwrite(buffer, expected_size_, 1, file_.get());
+ ASSERT_EQ(1U, fwrite(buffer, expected_size_, 1, file_.get()));
}
}
@@ -72,6 +75,36 @@ class DumpVideo {
int expected_size_;
};
+class MockMediaStreamRequester : public MediaStreamRequester {
+ public:
+ MockMediaStreamRequester() {}
+ virtual ~MockMediaStreamRequester() {}
+
+ // MediaStreamRequester implementation.
+ MOCK_METHOD5(StreamGenerated,
+ void(int render_view_id,
+ int page_request_id,
+ const std::string& label,
+ const StreamDeviceInfoArray& audio_devices,
+ const StreamDeviceInfoArray& video_devices));
+ MOCK_METHOD2(StreamGenerationFailed, void(int render_view_id,
+ int page_request_id));
+ MOCK_METHOD3(DeviceStopped, void(int render_view_id,
+ const std::string& label,
+ const StreamDeviceInfo& device));
+ MOCK_METHOD4(DevicesEnumerated, void(int render_view_id,
+ int page_request_id,
+ const std::string& label,
+ const StreamDeviceInfoArray& devices));
+ MOCK_METHOD4(DeviceOpened, void(int render_view_id,
+ int page_request_id,
+ const std::string& label,
+ const StreamDeviceInfo& device_info));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockMediaStreamRequester);
+};
+
class MockVideoCaptureHost : public VideoCaptureHost {
public:
MockVideoCaptureHost(MediaStreamManager* manager)
@@ -83,17 +116,19 @@ class MockVideoCaptureHost : public VideoCaptureHost {
MOCK_METHOD4(OnNewBufferCreated,
void(int device_id, base::SharedMemoryHandle handle,
int length, int buffer_id));
- MOCK_METHOD3(OnBufferFilled,
- void(int device_id, int buffer_id, base::Time timestamp));
+ MOCK_METHOD2(OnBufferFreed,
+ void(int device_id, int buffer_id));
+ MOCK_METHOD4(OnBufferFilled,
+ void(int device_id, int buffer_id, base::Time timestamp,
+ const media::VideoCaptureFormat& format));
MOCK_METHOD2(OnStateChanged, void(int device_id, VideoCaptureState state));
- MOCK_METHOD1(OnDeviceInfo, void(int device_id));
// Use class DumpVideo to write I420 video to file.
void SetDumpVideo(bool enable) {
dump_video_ = enable;
}
- void SetReturnReceviedDibs(bool enable) {
+ void SetReturnReceivedDibs(bool enable) {
return_buffers_ = enable;
}
@@ -134,9 +169,9 @@ class MockVideoCaptureHost : public VideoCaptureHost {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MockVideoCaptureHost, *message)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnNewBufferCreatedDispatch)
+ IPC_MESSAGE_HANDLER(VideoCaptureMsg_FreeBuffer, OnBufferFreedDispatch)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_BufferReady, OnBufferFilledDispatch)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_StateChanged, OnStateChangedDispatch)
- IPC_MESSAGE_HANDLER(VideoCaptureMsg_DeviceInfo, OnDeviceInfoDispatch)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
EXPECT_TRUE(handled);
@@ -156,15 +191,36 @@ class MockVideoCaptureHost : public VideoCaptureHost {
filled_dib_[buffer_id] = dib;
}
- void OnBufferFilledDispatch(int device_id, int buffer_id,
- base::Time timestamp) {
+ void OnBufferFreedDispatch(int device_id, int buffer_id) {
+ OnBufferFreed(device_id, buffer_id);
+
+ std::map<int, base::SharedMemory*>::iterator it =
+ filled_dib_.find(buffer_id);
+ ASSERT_TRUE(it != filled_dib_.end());
+ delete it->second;
+ filled_dib_.erase(it);
+ }
+
+ void OnBufferFilledDispatch(int device_id,
+ int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& frame_format) {
+ base::SharedMemory* dib = filled_dib_[buffer_id];
+ ASSERT_TRUE(dib != NULL);
if (dump_video_) {
- base::SharedMemory* dib = filled_dib_[buffer_id];
- ASSERT_TRUE(dib != NULL);
+ if (!format_.IsValid()) {
+ dumper_.StartDump(frame_format.frame_size.width(),
+ frame_format.frame_size.height());
+ format_ = frame_format;
+ }
+ ASSERT_EQ(format_.frame_size.width(), frame_format.frame_size.width())
+ << "Dump format does not handle variable resolution.";
+ ASSERT_EQ(format_.frame_size.height(), frame_format.frame_size.height())
+ << "Dump format does not handle variable resolution.";
dumper_.NewVideoFrame(dib->memory());
}
- OnBufferFilled(device_id, buffer_id, timestamp);
+ OnBufferFilled(device_id, buffer_id, timestamp, frame_format);
if (return_buffers_) {
VideoCaptureHost::OnReceiveEmptyBuffer(device_id, buffer_id);
}
@@ -174,17 +230,10 @@ class MockVideoCaptureHost : public VideoCaptureHost {
OnStateChanged(device_id, state);
}
- void OnDeviceInfoDispatch(int device_id,
- media::VideoCaptureParams params) {
- if (dump_video_) {
- dumper_.StartDump(params.width, params.height);
- }
- OnDeviceInfo(device_id);
- }
-
std::map<int, base::SharedMemory*> filled_dib_;
bool return_buffers_;
bool dump_video_;
+ media::VideoCaptureFormat format_;
DumpVideo dumper_;
};
@@ -192,32 +241,40 @@ ACTION_P2(ExitMessageLoop, message_loop, quit_closure) {
message_loop->PostTask(FROM_HERE, quit_closure);
}
+// This is an integration test of VideoCaptureHost in conjunction with
+// MediaStreamManager, VideoCaptureManager, VideoCaptureController, and
+// VideoCaptureDevice.
class VideoCaptureHostTest : public testing::Test {
public:
VideoCaptureHostTest()
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
- message_loop_(base::MessageLoopProxy::current()) {
+ message_loop_(base::MessageLoopProxy::current()),
+ opened_session_id_(kInvalidMediaCaptureSessionId) {}
+
+ virtual void SetUp() OVERRIDE {
+ SetBrowserClientForTesting(&browser_client_);
// Create our own MediaStreamManager.
- audio_manager_.reset(media::AudioManager::Create());
+ audio_manager_.reset(media::AudioManager::CreateForTesting());
media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
#ifndef TEST_REAL_CAPTURE_DEVICE
media_stream_manager_->UseFakeDevice();
#endif
+ media_stream_manager_->UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>());
+ // Create a Host and connect it to a simulated IPC channel.
host_ = new MockVideoCaptureHost(media_stream_manager_.get());
-
- // Simulate IPC channel connected.
host_->OnChannelConnected(base::GetCurrentProcId());
+
+ OpenSession();
}
- virtual ~VideoCaptureHostTest() {
+ virtual void TearDown() OVERRIDE {
// Verifies and removes the expectations on host_ and
// returns true iff successful.
Mock::VerifyAndClearExpectations(host_.get());
+ EXPECT_EQ(0u, host_->entries_.size());
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED))
- .Times(AnyNumber());
+ CloseSession();
// Simulate closing the IPC channel.
host_->OnChannelClosing();
@@ -225,36 +282,92 @@ class VideoCaptureHostTest : public testing::Test {
// Release the reference to the mock object. The object will be destructed
// on the current message loop.
host_ = NULL;
+ }
+
+ void OpenSession() {
+ const int render_process_id = 1;
+ const int render_view_id = 1;
+ const int page_request_id = 1;
+ const GURL security_origin("http://test.com");
+
+ ASSERT_TRUE(opened_device_label_.empty());
+
+ // Enumerate video devices.
+ StreamDeviceInfoArray devices;
+ {
+ base::RunLoop run_loop;
+ std::string label = media_stream_manager_->EnumerateDevices(
+ &stream_requester_,
+ render_process_id,
+ render_view_id,
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ page_request_id,
+ MEDIA_DEVICE_VIDEO_CAPTURE,
+ security_origin);
+ EXPECT_CALL(stream_requester_, DevicesEnumerated(render_view_id,
+ page_request_id,
+ label,
+ _))
+ .Times(1).WillOnce(
+ DoAll(ExitMessageLoop(message_loop_, run_loop.QuitClosure()),
+ SaveArg<3>(&devices)));
+ run_loop.Run();
+ Mock::VerifyAndClearExpectations(&stream_requester_);
+ media_stream_manager_->CancelRequest(label);
+ }
+ ASSERT_FALSE(devices.empty());
+ ASSERT_EQ(StreamDeviceInfo::kNoId, devices[0].session_id);
+
+ // Open the first device.
+ {
+ base::RunLoop run_loop;
+ StreamDeviceInfo opened_device;
+ media_stream_manager_->OpenDevice(
+ &stream_requester_,
+ render_process_id,
+ render_view_id,
+ browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
+ page_request_id,
+ devices[0].device.id,
+ MEDIA_DEVICE_VIDEO_CAPTURE,
+ security_origin);
+ EXPECT_CALL(stream_requester_, DeviceOpened(render_view_id,
+ page_request_id,
+ _,
+ _))
+ .Times(1).WillOnce(
+ DoAll(ExitMessageLoop(message_loop_, run_loop.QuitClosure()),
+ SaveArg<2>(&opened_device_label_),
+ SaveArg<3>(&opened_device)));
+ run_loop.Run();
+ Mock::VerifyAndClearExpectations(&stream_requester_);
+ ASSERT_NE(StreamDeviceInfo::kNoId, opened_device.session_id);
+ opened_session_id_ = opened_device.session_id;
+ }
+ }
- media_stream_manager_->WillDestroyCurrentMessageLoop();
+ void CloseSession() {
+ if (opened_device_label_.empty())
+ return;
+ media_stream_manager_->CancelRequest(opened_device_label_);
+ opened_device_label_.clear();
+ opened_session_id_ = kInvalidMediaCaptureSessionId;
}
protected:
void StartCapture() {
- InSequence s;
- // 1. First - get info about the new resolution
- EXPECT_CALL(*host_.get(), OnDeviceInfo(kDeviceId));
-
- // 2. Change state to started
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STARTED));
-
- // 3. Newly created buffers will arrive.
- EXPECT_CALL(*host_.get(), OnNewBufferCreated(kDeviceId, _, _, _))
+ EXPECT_CALL(*host_, OnNewBufferCreated(kDeviceId, _, _, _))
.Times(AnyNumber()).WillRepeatedly(Return());
- // 4. First filled buffer will arrive.
base::RunLoop run_loop;
- EXPECT_CALL(*host_.get(), OnBufferFilled(kDeviceId, _, _))
+ EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _))
.Times(AnyNumber()).WillOnce(ExitMessageLoop(
message_loop_, run_loop.QuitClosure()));
media::VideoCaptureParams params;
- params.width = 352;
- params.height = 288;
- params.frame_rate = 30;
- params.session_id = kTestFakeSessionId;
- host_->OnStartCapture(kDeviceId, params);
+ params.requested_format = media::VideoCaptureFormat(
+ gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
+ host_->OnStartCapture(kDeviceId, opened_session_id_, params);
run_loop.Run();
}
@@ -263,14 +376,11 @@ class VideoCaptureHostTest : public testing::Test {
// asynchronous start operations to complete.
InSequence s;
base::RunLoop run_loop;
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED));
media::VideoCaptureParams params;
- params.width = 352;
- params.height = 288;
- params.frame_rate = 30;
- params.session_id = kTestFakeSessionId;
- host_->OnStartCapture(kDeviceId, params);
+ params.requested_format = media::VideoCaptureFormat(
+ gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
+ host_->OnStartCapture(kDeviceId, opened_session_id_, params);
host_->OnStopCapture(kDeviceId);
run_loop.RunUntilIdle();
}
@@ -278,49 +388,42 @@ class VideoCaptureHostTest : public testing::Test {
#ifdef DUMP_VIDEO
void CaptureAndDumpVideo(int width, int height, int frame_rate) {
InSequence s;
- // 1. First - get info about the new resolution
- EXPECT_CALL(*host_, OnDeviceInfo(kDeviceId));
-
- // 2. Change state to started
- EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*host_.get(), OnNewBufferCreated(kDeviceId, _, _, _))
+ .Times(AnyNumber()).WillRepeatedly(Return());
- // 3. First filled buffer will arrive.
base::RunLoop run_loop;
- EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _))
+ EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _))
.Times(AnyNumber())
.WillOnce(ExitMessageLoop(message_loop_, run_loop.QuitClosure()));
media::VideoCaptureParams params;
- params.width = width;
- params.height = height;
- params.frame_rate = frame_rate;
- params.session_id = kTestFakeSessionId;
+ params.requested_format =
+ media::VideoCaptureFormat(gfx::Size(width, height), frame_rate);
host_->SetDumpVideo(true);
- host_->OnStartCapture(kDeviceId, params);
+ host_->OnStartCapture(kDeviceId, opened_session_id_, params);
run_loop.Run();
}
#endif
void StopCapture() {
base::RunLoop run_loop;
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED))
+ EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED))
.WillOnce(ExitMessageLoop(message_loop_, run_loop.QuitClosure()));
host_->OnStopCapture(kDeviceId);
- host_->SetReturnReceviedDibs(true);
+ host_->SetReturnReceivedDibs(true);
host_->ReturnReceivedDibs(kDeviceId);
run_loop.Run();
- host_->SetReturnReceviedDibs(false);
+ host_->SetReturnReceivedDibs(false);
// Expect the VideoCaptureDevice has been stopped
EXPECT_EQ(0u, host_->entries_.size());
}
void NotifyPacketReady() {
base::RunLoop run_loop;
- EXPECT_CALL(*host_.get(), OnBufferFilled(kDeviceId, _, _))
+ EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _))
.Times(AnyNumber()).WillOnce(ExitMessageLoop(
message_loop_, run_loop.QuitClosure()))
.RetiresOnSaturation();
@@ -332,9 +435,9 @@ class VideoCaptureHostTest : public testing::Test {
}
void SimulateError() {
- // Expect a change state to error state sent through IPC.
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ERROR)).Times(1);
+ // Expect a change state to error state sent through IPC.
+ EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ERROR))
+ .Times(1);
VideoCaptureControllerID id(kDeviceId);
host_->OnError(id);
// Wait for the error callback.
@@ -344,21 +447,31 @@ class VideoCaptureHostTest : public testing::Test {
scoped_refptr<MockVideoCaptureHost> host_;
private:
+ StrictMock<MockMediaStreamRequester> stream_requester_;
scoped_ptr<media::AudioManager> audio_manager_;
scoped_ptr<MediaStreamManager> media_stream_manager_;
content::TestBrowserThreadBundle thread_bundle_;
+ content::TestBrowserContext browser_context_;
+ content::TestContentBrowserClient browser_client_;
scoped_refptr<base::MessageLoopProxy> message_loop_;
+ int opened_session_id_;
+ std::string opened_device_label_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest);
};
-TEST_F(VideoCaptureHostTest, StartCapture) {
+TEST_F(VideoCaptureHostTest, CloseSessionWithoutStopping) {
StartCapture();
+
+ // When the session is closed via the stream without stopping capture, the
+ // ENDED event is sent.
+ EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ENDED))
+ .Times(1);
+ CloseSession();
+ base::RunLoop().RunUntilIdle();
}
-// Disabled because of a sometimes race between completion of implicit device
-// enumeration and the capture stop. http://crbug.com/289684
-TEST_F(VideoCaptureHostTest, DISABLED_StopWhileStartOpening) {
+TEST_F(VideoCaptureHostTest, StopWhileStartPending) {
StartStopCapture();
}
@@ -377,8 +490,8 @@ TEST_F(VideoCaptureHostTest, StartCaptureErrorStop) {
}
TEST_F(VideoCaptureHostTest, StartCaptureError) {
- EXPECT_CALL(*host_.get(),
- OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED)).Times(0);
+ EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED))
+ .Times(0);
StartCapture();
NotifyPacketReady();
SimulateError();
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 f61aa83d093..a581580bf38 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
@@ -11,29 +11,30 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
+#include "base/task_runner_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/browser/renderer_host/media/web_contents_video_capture_device.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/desktop_media_id.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/desktop_media_id.h"
#include "content/public/common/media_stream_request.h"
+#include "media/base/media_switches.h"
#include "media/base/scoped_histogram_timer.h"
#include "media/video/capture/fake_video_capture_device.h"
+#include "media/video/capture/file_video_capture_device.h"
#include "media/video/capture/video_capture_device.h"
#if defined(ENABLE_SCREEN_CAPTURE)
#include "content/browser/renderer_host/media/desktop_capture_device.h"
+#if defined(USE_AURA)
+#include "content/browser/renderer_host/media/desktop_capture_device_aura.h"
+#endif
#endif
namespace content {
-// Starting id for the first capture session.
-// VideoCaptureManager::kStartOpenSessionId is used as default id without
-// explicitly calling open device.
-enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 };
-
VideoCaptureManager::DeviceEntry::DeviceEntry(
MediaStreamType stream_type,
const std::string& id,
@@ -44,10 +45,20 @@ VideoCaptureManager::DeviceEntry::DeviceEntry(
VideoCaptureManager::DeviceEntry::~DeviceEntry() {}
+VideoCaptureManager::DeviceInfo::DeviceInfo() {}
+
+VideoCaptureManager::DeviceInfo::DeviceInfo(
+ const media::VideoCaptureDevice::Name& name,
+ const media::VideoCaptureFormats& supported_formats)
+ : name(name),
+ supported_formats(supported_formats) {}
+
+VideoCaptureManager::DeviceInfo::~DeviceInfo() {}
+
VideoCaptureManager::VideoCaptureManager()
: listener_(NULL),
- new_capture_session_id_(kFirstSessionId),
- use_fake_device_(false) {
+ new_capture_session_id_(1),
+ artificial_device_source_for_testing_(DISABLED) {
}
VideoCaptureManager::~VideoCaptureManager() {
@@ -74,9 +85,10 @@ void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) {
DCHECK(listener_);
base::PostTaskAndReplyWithResult(
device_loop_, FROM_HERE,
- base::Bind(&VideoCaptureManager::GetAvailableDevicesOnDeviceThread, this,
- stream_type),
- base::Bind(&VideoCaptureManager::OnDevicesEnumerated, this, stream_type));
+ base::Bind(&VideoCaptureManager::GetAvailableDevicesInfoOnDeviceThread,
+ this, stream_type, devices_info_cache_),
+ base::Bind(&VideoCaptureManager::OnDevicesInfoEnumerated, this,
+ stream_type));
}
int VideoCaptureManager::Open(const StreamDeviceInfo& device_info) {
@@ -133,13 +145,18 @@ void VideoCaptureManager::Close(int capture_session_id) {
}
void VideoCaptureManager::UseFakeDevice() {
- use_fake_device_ = true;
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseFileForFakeVideoCapture)) {
+ artificial_device_source_for_testing_ = Y4M_FILE;
+ } else {
+ artificial_device_source_for_testing_ = TEST_PATTERN;
+ }
}
void VideoCaptureManager::DoStartDeviceOnDeviceThread(
DeviceEntry* entry,
- const media::VideoCaptureCapability& capture_params,
- scoped_ptr<media::VideoCaptureDevice::EventHandler> device_client) {
+ const media::VideoCaptureParams& params,
+ scoped_ptr<media::VideoCaptureDevice::Client> device_client) {
SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
DCHECK(IsOnDeviceThread());
@@ -149,12 +166,22 @@ void VideoCaptureManager::DoStartDeviceOnDeviceThread(
// 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.
- media::VideoCaptureDevice::Name* found =
- video_capture_devices_.FindById(entry->id);
+ DeviceInfo* found = FindDeviceInfoById(entry->id, devices_info_cache_);
if (found) {
- video_capture_device.reset(use_fake_device_ ?
- media::FakeVideoCaptureDevice::Create(*found) :
- media::VideoCaptureDevice::Create(*found));
+ switch (artificial_device_source_for_testing_) {
+ case DISABLED:
+ video_capture_device.reset(
+ media::VideoCaptureDevice::Create(found->name));
+ break;
+ case TEST_PATTERN:
+ video_capture_device.reset(
+ media::FakeVideoCaptureDevice::Create(found->name));
+ break;
+ case Y4M_FILE:
+ video_capture_device.reset(
+ media::FileVideoCaptureDevice::Create(found->name));
+ break;
+ }
}
break;
}
@@ -166,7 +193,13 @@ void VideoCaptureManager::DoStartDeviceOnDeviceThread(
case MEDIA_DESKTOP_VIDEO_CAPTURE: {
#if defined(ENABLE_SCREEN_CAPTURE)
DesktopMediaID id = DesktopMediaID::Parse(entry->id);
- if (id.type != DesktopMediaID::TYPE_NONE) {
+#if defined(USE_AURA)
+ if (id.type == DesktopMediaID::TYPE_AURA_WINDOW) {
+ video_capture_device.reset(DesktopCaptureDeviceAura::Create(id));
+ } else
+#endif
+ if (id.type != DesktopMediaID::TYPE_NONE &&
+ id.type != DesktopMediaID::TYPE_AURA_WINDOW) {
video_capture_device = DesktopCaptureDevice::Create(id);
}
#endif // defined(ENABLE_SCREEN_CAPTURE)
@@ -183,49 +216,23 @@ void VideoCaptureManager::DoStartDeviceOnDeviceThread(
return;
}
- video_capture_device->AllocateAndStart(capture_params, device_client.Pass());
+ video_capture_device->AllocateAndStart(params, device_client.Pass());
entry->video_capture_device = video_capture_device.Pass();
}
void VideoCaptureManager::StartCaptureForClient(
- const media::VideoCaptureParams& capture_params,
+ media::VideoCaptureSessionId session_id,
+ const media::VideoCaptureParams& params,
base::ProcessHandle client_render_process,
VideoCaptureControllerID client_id,
VideoCaptureControllerEventHandler* client_handler,
const DoneCB& done_cb) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, ("
- << capture_params.width
- << ", " << capture_params.height
- << ", " << capture_params.frame_rate
- << ", #" << capture_params.session_id
- << ")";
-
- if (capture_params.session_id == kStartOpenSessionId) {
- // Solution for not using MediaStreamManager. Enumerate the devices and
- // open the first one, and then start it.
- base::PostTaskAndReplyWithResult(device_loop_, FROM_HERE,
- base::Bind(&VideoCaptureManager::GetAvailableDevicesOnDeviceThread,
- this, MEDIA_DEVICE_VIDEO_CAPTURE),
- base::Bind(&VideoCaptureManager::OpenAndStartDefaultSession, this,
- capture_params, client_render_process, client_id,
- client_handler, done_cb));
- return;
- } else {
- DoStartCaptureForClient(capture_params, client_render_process, client_id,
- client_handler, done_cb);
- }
-}
+ DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, "
+ << params.requested_format.frame_size.ToString() << ", "
+ << params.requested_format.frame_rate << ", #" << session_id << ")";
-void VideoCaptureManager::DoStartCaptureForClient(
- const media::VideoCaptureParams& capture_params,
- base::ProcessHandle client_render_process,
- VideoCaptureControllerID client_id,
- VideoCaptureControllerEventHandler* client_handler,
- const DoneCB& done_cb) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- DeviceEntry* entry = GetOrCreateDeviceEntry(capture_params.session_id);
+ DeviceEntry* entry = GetOrCreateDeviceEntry(session_id);
if (!entry) {
done_cb.Run(base::WeakPtr<VideoCaptureController>());
return;
@@ -238,24 +245,19 @@ void VideoCaptureManager::DoStartCaptureForClient(
DVLOG(1) << "VideoCaptureManager starting device (type = "
<< entry->stream_type << ", id = " << entry->id << ")";
- media::VideoCaptureCapability params_as_capability;
- params_as_capability.width = capture_params.width;
- params_as_capability.height = capture_params.height;
- params_as_capability.frame_rate = capture_params.frame_rate;
- params_as_capability.session_id = capture_params.session_id;
- params_as_capability.frame_size_type = capture_params.frame_size_type;
-
- device_loop_->PostTask(FROM_HERE, base::Bind(
- &VideoCaptureManager::DoStartDeviceOnDeviceThread, this,
- entry, params_as_capability,
- base::Passed(entry->video_capture_controller->NewDeviceClient())));
+ device_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &VideoCaptureManager::DoStartDeviceOnDeviceThread,
+ this,
+ entry,
+ params,
+ base::Passed(entry->video_capture_controller->NewDeviceClient())));
}
// Run the callback first, as AddClient() may trigger OnFrameInfo().
done_cb.Run(entry->video_capture_controller->GetWeakPtr());
- entry->video_capture_controller->AddClient(client_id,
- client_handler,
- client_render_process,
- capture_params);
+ entry->video_capture_controller->AddClient(
+ client_id, client_handler, client_render_process, session_id, params);
}
void VideoCaptureManager::StopCaptureForClient(
@@ -279,13 +281,33 @@ void VideoCaptureManager::StopCaptureForClient(
// If controller has no more clients, delete controller and device.
DestroyDeviceEntryIfNoClients(entry);
+}
+
+void VideoCaptureManager::GetDeviceSupportedFormats(
+ int capture_session_id,
+ media::VideoCaptureFormats* supported_formats) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ supported_formats->clear();
- // Close the session if it was auto-opened by StartCaptureForClient().
- if (session_id == kStartOpenSessionId) {
- sessions_.erase(session_id);
- base::MessageLoop::current()->PostTask(FROM_HERE,
- base::Bind(&VideoCaptureManager::OnClosed, this,
- MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId));
+ std::map<int, MediaStreamDevice>::iterator it =
+ sessions_.find(capture_session_id);
+ DCHECK(it != sessions_.end());
+ DVLOG(1) << "GetDeviceSupportedFormats for device: " << it->second.name;
+
+ DeviceInfo* device_in_use =
+ FindDeviceInfoById(it->second.id, devices_info_cache_);
+ if (device_in_use) {
+ DeviceEntry* const existing_device =
+ GetDeviceEntryForMediaStreamDevice(it->second);
+ if (!existing_device) {
+ // If the device is not in use, return all its cached supported formats.
+ *supported_formats = device_in_use->supported_formats;
+ return;
+ }
+ // Otherwise, get the video capture parameters in use from the controller
+ // associated to the device.
+ supported_formats->push_back(
+ existing_device->video_capture_controller->GetVideoCaptureFormat());
}
}
@@ -318,24 +340,25 @@ void VideoCaptureManager::OnClosed(MediaStreamType stream_type,
listener_->Closed(stream_type, capture_session_id);
}
-void VideoCaptureManager::OnDevicesEnumerated(
+void VideoCaptureManager::OnDevicesInfoEnumerated(
MediaStreamType stream_type,
- const media::VideoCaptureDevice::Names& device_names) {
+ const DeviceInfos& new_devices_info_cache) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!listener_) {
// Listener has been removed.
return;
}
+ devices_info_cache_ = new_devices_info_cache;
- // Transform from VCD::Name to StreamDeviceInfo.
+ // Walk the |devices_info_cache_| and transform from VCD::Name to
+ // StreamDeviceInfo for return purposes.
StreamDeviceInfoArray devices;
- for (media::VideoCaptureDevice::Names::const_iterator it =
- device_names.begin(); it != device_names.end(); ++it) {
+ for (DeviceInfos::const_iterator it = devices_info_cache_.begin();
+ it != devices_info_cache_.end(); ++it) {
devices.push_back(StreamDeviceInfo(
- stream_type, it->GetNameAndModel(), it->id(), false));
+ stream_type, it->name.GetNameAndModel(), it->name.id()));
}
-
listener_->DevicesEnumerated(stream_type, devices);
}
@@ -343,29 +366,30 @@ bool VideoCaptureManager::IsOnDeviceThread() const {
return device_loop_->BelongsToCurrentThread();
}
-media::VideoCaptureDevice::Names
-VideoCaptureManager::GetAvailableDevicesOnDeviceThread(
- MediaStreamType stream_type) {
+VideoCaptureManager::DeviceInfos
+VideoCaptureManager::GetAvailableDevicesInfoOnDeviceThread(
+ MediaStreamType stream_type,
+ const DeviceInfos& old_device_info_cache) {
SCOPED_UMA_HISTOGRAM_TIMER(
- "Media.VideoCaptureManager.GetAvailableDevicesTime");
+ "Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime");
DCHECK(IsOnDeviceThread());
- media::VideoCaptureDevice::Names result;
-
+ media::VideoCaptureDevice::Names names_snapshot;
switch (stream_type) {
case MEDIA_DEVICE_VIDEO_CAPTURE:
// Cache the latest enumeration of video capture devices.
// We'll refer to this list again in OnOpen to avoid having to
// enumerate the devices again.
- if (!use_fake_device_) {
- media::VideoCaptureDevice::GetDeviceNames(&result);
- } else {
- media::FakeVideoCaptureDevice::GetDeviceNames(&result);
+ switch (artificial_device_source_for_testing_) {
+ case DISABLED:
+ media::VideoCaptureDevice::GetDeviceNames(&names_snapshot);
+ break;
+ case TEST_PATTERN:
+ media::FakeVideoCaptureDevice::GetDeviceNames(&names_snapshot);
+ break;
+ case Y4M_FILE:
+ media::FileVideoCaptureDevice::GetDeviceNames(&names_snapshot);
+ break;
}
-
- // TODO(nick): The correctness of device start depends on this cache being
- // maintained, but it seems a little odd to keep a cache here. Can we
- // eliminate it?
- video_capture_devices_ = result;
break;
case MEDIA_DESKTOP_VIDEO_CAPTURE:
@@ -376,7 +400,48 @@ VideoCaptureManager::GetAvailableDevicesOnDeviceThread(
NOTREACHED();
break;
}
- return result;
+
+ // 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.
+ DeviceInfos new_devices_info_cache;
+ for (DeviceInfos::const_iterator it_device_info =
+ old_device_info_cache.begin();
+ it_device_info != old_device_info_cache.end(); ++it_device_info) {
+ for (media::VideoCaptureDevice::Names::iterator it =
+ names_snapshot.begin();
+ it != names_snapshot.end(); ++it) {
+ if (it_device_info->name.id() == it->id()) {
+ new_devices_info_cache.push_back(*it_device_info);
+ names_snapshot.erase(it);
+ break;
+ }
+ }
+ }
+
+ // Get the supported capture formats for the new devices in |names_snapshot|.
+ for (media::VideoCaptureDevice::Names::const_iterator it =
+ names_snapshot.begin();
+ it != names_snapshot.end(); ++it) {
+ media::VideoCaptureFormats supported_formats;
+ DeviceInfo device_info(*it, media::VideoCaptureFormats());
+ switch (artificial_device_source_for_testing_) {
+ case DISABLED:
+ media::VideoCaptureDevice::GetDeviceSupportedFormats(
+ *it, &(device_info.supported_formats));
+ break;
+ case TEST_PATTERN:
+ media::FakeVideoCaptureDevice::GetDeviceSupportedFormats(
+ *it, &(device_info.supported_formats));
+ break;
+ case Y4M_FILE:
+ media::FileVideoCaptureDevice::GetDeviceSupportedFormats(
+ *it, &(device_info.supported_formats));
+ break;
+ }
+ new_devices_info_cache.push_back(device_info);
+ }
+ return new_devices_info_cache;
}
VideoCaptureManager::DeviceEntry*
@@ -408,38 +473,6 @@ VideoCaptureManager::GetDeviceEntryForController(
return NULL;
}
-void VideoCaptureManager::OpenAndStartDefaultSession(
- const media::VideoCaptureParams& capture_params,
- base::ProcessHandle client_render_process,
- VideoCaptureControllerID client_id,
- VideoCaptureControllerEventHandler* client_handler,
- const DoneCB& done_cb,
- const media::VideoCaptureDevice::Names& device_names) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- // |device_names| is a value returned by GetAvailableDevicesOnDeviceThread().
- // We'll mimic an Open() operation on the first element in that list.
- DCHECK(capture_params.session_id == kStartOpenSessionId);
- if (device_names.empty() ||
- sessions_.count(capture_params.session_id) != 0) {
- done_cb.Run(base::WeakPtr<VideoCaptureController>());
- return;
- }
-
- // Open the device by creating a |sessions_| entry.
- sessions_[capture_params.session_id] =
- MediaStreamDevice(MEDIA_DEVICE_VIDEO_CAPTURE,
- device_names.front().id(),
- device_names.front().GetNameAndModel());
-
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureManager::OnOpened, this,
- MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId));
-
- DoStartCaptureForClient(capture_params, client_render_process, client_id,
- client_handler, done_cb);
-}
-
void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Removal of the last client stops the device.
@@ -474,7 +507,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);
+ GetDeviceEntryForMediaStreamDevice(device_info);
if (existing_device) {
DCHECK_EQ(device_info.type, existing_device->stream_type);
return existing_device;
@@ -489,4 +522,15 @@ VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
return new_device;
}
+VideoCaptureManager::DeviceInfo* VideoCaptureManager::FindDeviceInfoById(
+ const std::string& id,
+ DeviceInfos& device_vector) {
+ for (DeviceInfos::iterator it = device_vector.begin();
+ it != device_vector.end(); ++it) {
+ if (it->name.id() == id)
+ return &(*it);
+ }
+ return NULL;
+}
+
} // namespace content
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 fc6dd92fecd..5f3630eb679 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.h
@@ -37,11 +37,6 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
typedef base::Callback<
void(const base::WeakPtr<VideoCaptureController>&)> DoneCB;
- // Calling |Start| of this id will open the first device, even though open has
- // not been called. This is used to be able to use video capture devices
- // before MediaStream is implemented in Chrome and WebKit.
- enum { kStartOpenSessionId = 1 };
-
VideoCaptureManager();
// Implements MediaStreamProvider.
@@ -63,7 +58,7 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// Called by VideoCaptureHost to locate a capture device for |capture_params|,
// adding the Host as a client of the device's controller if successful. The
- // value of |capture_params.session_id| controls which device is selected;
+ // value of |session_id| controls which device is selected;
// this value should be a session id previously returned by Open().
//
// If the device is not already started (i.e., no other client is currently
@@ -73,7 +68,8 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// On success, the controller is returned via calling |done_cb|, indicating
// that the client was successfully added. A NULL controller is passed to
// the callback on failure.
- void StartCaptureForClient(const media::VideoCaptureParams& capture_params,
+ void StartCaptureForClient(media::VideoCaptureSessionId session_id,
+ const media::VideoCaptureParams& capture_params,
base::ProcessHandle client_render_process,
VideoCaptureControllerID client_id,
VideoCaptureControllerEventHandler* client_handler,
@@ -87,26 +83,27 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
VideoCaptureControllerID client_id,
VideoCaptureControllerEventHandler* client_handler);
+ // Retrieves the available capture supported formats for a particular device.
+ // The supported formats are cached during device(s) enumeration.
+ void GetDeviceSupportedFormats(int capture_session_id,
+ media::VideoCaptureFormats* supported_formats);
+
private:
virtual ~VideoCaptureManager();
struct DeviceEntry;
- // Helper for the kStartOpenSessionId case.
- void OpenAndStartDefaultSession(
- const media::VideoCaptureParams& capture_params,
- base::ProcessHandle client_render_process,
- VideoCaptureControllerID client_id,
- VideoCaptureControllerEventHandler* client_handler,
- const DoneCB& done_cb,
- const media::VideoCaptureDevice::Names& device_names);
-
- // Helper routine implementing StartCaptureForClient().
- void DoStartCaptureForClient(
- const media::VideoCaptureParams& capture_params,
- base::ProcessHandle client_render_process,
- VideoCaptureControllerID client_id,
- VideoCaptureControllerEventHandler* client_handler,
- const DoneCB& done_cb);
+ // This data structure is a convenient wrap of a devices' name and associated
+ // video capture supported formats.
+ struct DeviceInfo {
+ DeviceInfo();
+ DeviceInfo(const media::VideoCaptureDevice::Name& name,
+ const media::VideoCaptureFormats& supported_formats);
+ ~DeviceInfo();
+
+ media::VideoCaptureDevice::Name name;
+ media::VideoCaptureFormats supported_formats;
+ };
+ typedef std::vector<DeviceInfo> DeviceInfos;
// Check 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|
@@ -116,8 +113,9 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// Helpers to report an event to our Listener.
void OnOpened(MediaStreamType type, int capture_session_id);
void OnClosed(MediaStreamType type, int capture_session_id);
- void OnDevicesEnumerated(MediaStreamType stream_type,
- const media::VideoCaptureDevice::Names& names);
+ void OnDevicesInfoEnumerated(
+ MediaStreamType stream_type,
+ const DeviceInfos& new_devices_info_cache);
// Find a DeviceEntry by its device ID and type, if it is already opened.
DeviceEntry* GetDeviceEntryForMediaStreamDevice(
@@ -133,22 +131,29 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
bool IsOnDeviceThread() const;
- // Queries and returns the available device IDs.
- media::VideoCaptureDevice::Names GetAvailableDevicesOnDeviceThread(
- MediaStreamType stream_type);
+ // Queries the Names of the devices in the system; the formats supported by
+ // the new devices are also queried, and consolidated with the copy of the
+ // local device info cache passed. The consolidated list of devices and
+ // supported formats is returned.
+ DeviceInfos GetAvailableDevicesInfoOnDeviceThread(
+ MediaStreamType stream_type,
+ const DeviceInfos& old_device_info_cache);
// Create and Start a new VideoCaptureDevice, storing the result in
- // |entry->video_capture_device|. Ownership of |handler| passes to
+ // |entry->video_capture_device|. Ownership of |client| passes to
// the device.
void DoStartDeviceOnDeviceThread(
DeviceEntry* entry,
- const media::VideoCaptureCapability& capture_params,
- scoped_ptr<media::VideoCaptureDevice::EventHandler> handler);
+ const media::VideoCaptureParams& params,
+ scoped_ptr<media::VideoCaptureDevice::Client> client);
// Stop and destroy the VideoCaptureDevice held in
// |entry->video_capture_device|.
void DoStopDeviceOnDeviceThread(DeviceEntry* entry);
+ DeviceInfo* FindDeviceInfoById(const std::string& id,
+ DeviceInfos& device_vector);
+
// The message loop of media stream device thread, where VCD's live.
scoped_refptr<base::MessageLoopProxy> device_loop_;
@@ -189,15 +194,24 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
typedef std::set<DeviceEntry*> DeviceEntries;
DeviceEntries devices_;
- // Set to true if using fake video capture devices for testing, false by
- // default. This is only used for the MEDIA_DEVICE_VIDEO_CAPTURE device type.
- bool use_fake_device_;
-
- // We cache the enumerated video capture devices in
- // GetAvailableDevicesOnDeviceThread() and then later look up the requested ID
- // when a device is created in DoStartDeviceOnDeviceThread(). Used only on the
- // device thread.
- media::VideoCaptureDevice::Names video_capture_devices_;
+ // Local cache of the enumerated video capture devices' names and capture
+ // supported formats. A snapshot of the current devices and their capabilities
+ // is composed in GetAvailableDevicesInfoOnDeviceThread() --coming
+ // from EnumerateDevices()--, and this snapshot is used to update this list in
+ // OnDevicesInfoEnumerated(). GetDeviceSupportedFormats() will
+ // use this list if the device is not started, otherwise it will retrieve the
+ // active device capture format from the VideoCaptureController associated.
+ DeviceInfos devices_info_cache_;
+
+ // For unit testing and for performance/quality tests, a test device can be
+ // used instead of a real one. The device can be a simple fake device (a
+ // rolling pacman), or a file that is played in a loop continuously. This only
+ // applies to the MEDIA_DEVICE_VIDEO_CAPTURE device type.
+ enum {
+ DISABLED,
+ TEST_PATTERN,
+ Y4M_FILE
+ } artificial_device_source_for_testing_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureManager);
};
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 34172d78cb4..bc89159e011 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
@@ -16,6 +16,7 @@
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/media_stream_options.h"
+#include "media/video/capture/fake_video_capture_device.h"
#include "media/video/capture/video_capture_device.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -23,8 +24,8 @@
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::InSequence;
-using testing::SaveArg;
using ::testing::Return;
+using ::testing::SaveArg;
namespace content {
@@ -49,18 +50,15 @@ class MockFrameObserver : public VideoCaptureControllerEventHandler {
virtual void OnBufferCreated(const VideoCaptureControllerID& id,
base::SharedMemoryHandle handle,
- int length, int buffer_id) OVERRIDE {};
- virtual void OnBufferReady(const VideoCaptureControllerID& id,
- int buffer_id,
- base::Time timestamp) OVERRIDE {};
- virtual void OnFrameInfo(
+ int length, int buffer_id) OVERRIDE {}
+ virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
+ int buffer_id) OVERRIDE {}
+ virtual void OnBufferReady(
const VideoCaptureControllerID& id,
- const media::VideoCaptureCapability& format) OVERRIDE {};
- virtual void OnFrameInfoChanged(const VideoCaptureControllerID& id,
- int width,
- int height,
- int frame_rate) OVERRIDE {};
- virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {};
+ int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format) OVERRIDE {}
+ virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {}
void OnGotControllerCallback(VideoCaptureControllerID) {}
};
@@ -102,17 +100,21 @@ class VideoCaptureManagerTest : public testing::Test {
VideoCaptureControllerID StartClient(int session_id, bool expect_success) {
media::VideoCaptureParams params;
- params.session_id = session_id;
- params.width = 320;
- params.height = 240;
- params.frame_rate = 30;
+ params.requested_format = media::VideoCaptureFormat(
+ gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
VideoCaptureControllerID client_id(next_client_id_++);
base::RunLoop run_loop;
vcm_->StartCaptureForClient(
- params, base::kNullProcessHandle, client_id, frame_observer_.get(),
+ session_id,
+ params,
+ base::kNullProcessHandle,
+ client_id,
+ frame_observer_.get(),
base::Bind(&VideoCaptureManagerTest::OnGotControllerCallback,
- base::Unretained(this), client_id, run_loop.QuitClosure(),
+ base::Unretained(this),
+ client_id,
+ run_loop.QuitClosure(),
expect_success));
run_loop.Run();
return client_id;
@@ -195,6 +197,97 @@ TEST_F(VideoCaptureManagerTest, OpenTwice) {
vcm_->Unregister();
}
+// Connect and disconnect devices.
+TEST_F(VideoCaptureManagerTest, ConnectAndDisconnectDevices) {
+ StreamDeviceInfoArray devices;
+ int number_of_devices_keep =
+ media::FakeVideoCaptureDevice::NumberOfFakeDevices();
+
+ InSequence s;
+ EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
+ .Times(1).WillOnce(SaveArg<1>(&devices));
+ vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
+ message_loop_->RunUntilIdle();
+ ASSERT_EQ(devices.size(), 2u);
+
+ // Simulate we remove 1 fake device.
+ media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(1);
+ EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
+ .Times(1).WillOnce(SaveArg<1>(&devices));
+ vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
+ message_loop_->RunUntilIdle();
+ ASSERT_EQ(devices.size(), 1u);
+
+ // Simulate we add 2 fake devices.
+ media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(3);
+ EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
+ .Times(1).WillOnce(SaveArg<1>(&devices));
+ vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
+ message_loop_->RunUntilIdle();
+ ASSERT_EQ(devices.size(), 3u);
+
+ vcm_->Unregister();
+ media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(number_of_devices_keep);
+}
+
+// Enumerate devices and open the first, then check the list of supported
+// formats. Then start the opened device. The capability list should be reduced
+// to just one format, and this should be the one used when configuring-starting
+// the device. Finally stop the device and check that the capabilities have been
+// restored.
+TEST_F(VideoCaptureManagerTest, ManipulateDeviceAndCheckCapabilities) {
+ StreamDeviceInfoArray devices;
+
+ InSequence s;
+ EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
+ .Times(1).WillOnce(SaveArg<1>(&devices));
+ vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
+ message_loop_->RunUntilIdle();
+
+ EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
+ int video_session_id = vcm_->Open(devices.front());
+ message_loop_->RunUntilIdle();
+
+ // When the device has been opened, we should see all the devices'
+ // supported formats.
+ media::VideoCaptureFormats supported_formats;
+ vcm_->GetDeviceSupportedFormats(video_session_id, &supported_formats);
+ ASSERT_EQ(devices.size(), 2u);
+ ASSERT_GT(supported_formats.size(), 1u);
+ EXPECT_GT(supported_formats[0].frame_size.width(), 1);
+ EXPECT_GT(supported_formats[0].frame_size.height(), 1);
+ EXPECT_GT(supported_formats[0].frame_rate, 1);
+ EXPECT_GT(supported_formats[1].frame_size.width(), 1);
+ EXPECT_GT(supported_formats[1].frame_size.height(), 1);
+ EXPECT_GT(supported_formats[1].frame_rate, 1);
+
+ VideoCaptureControllerID client_id = StartClient(video_session_id, true);
+ message_loop_->RunUntilIdle();
+ // After StartClient(), device's supported formats should be reduced to one.
+ vcm_->GetDeviceSupportedFormats(video_session_id, &supported_formats);
+ ASSERT_EQ(supported_formats.size(), 1u);
+ EXPECT_GT(supported_formats[0].frame_size.width(), 1);
+ EXPECT_GT(supported_formats[0].frame_size.height(), 1);
+ EXPECT_GT(supported_formats[0].frame_rate, 1);
+
+ EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
+ StopClient(client_id);
+ // After StopClient(), the device's list of supported formats should be
+ // restored to the original one.
+ vcm_->GetDeviceSupportedFormats(video_session_id, &supported_formats);
+ ASSERT_GT(supported_formats.size(), 1u);
+ EXPECT_GT(supported_formats[0].frame_size.width(), 1);
+ EXPECT_GT(supported_formats[0].frame_size.height(), 1);
+ EXPECT_GT(supported_formats[0].frame_rate, 1);
+ EXPECT_GT(supported_formats[1].frame_size.width(), 1);
+ EXPECT_GT(supported_formats[1].frame_size.height(), 1);
+ EXPECT_GT(supported_formats[1].frame_rate, 1);
+
+ vcm_->Close(video_session_id);
+ message_loop_->RunUntilIdle();
+ vcm_->Unregister();
+}
+
// Open two different devices.
TEST_F(VideoCaptureManagerTest, OpenTwo) {
StreamDeviceInfoArray devices;
@@ -243,7 +336,7 @@ TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
MediaStreamType stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
std::string device_name("device_doesnt_exist");
std::string device_id("id_doesnt_exist");
- StreamDeviceInfo dummy_device(stream_type, device_name, device_id, false);
+ StreamDeviceInfo dummy_device(stream_type, device_name, device_id);
// This should fail with an error to the controller.
int session_id = vcm_->Open(dummy_device);
@@ -257,24 +350,6 @@ TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
vcm_->Unregister();
}
-// Start a device using "magic" id, i.e. call Start without calling Open.
-TEST_F(VideoCaptureManagerTest, StartUsingId) {
- InSequence s;
- EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
- EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
-
- // Start shall trigger the Open callback.
- VideoCaptureControllerID client_id = StartClient(
- VideoCaptureManager::kStartOpenSessionId, true);
-
- // Stop shall trigger the Close callback
- StopClient(client_id);
-
- // Wait to check callbacks before removing the listener.
- message_loop_->RunUntilIdle();
- vcm_->Unregister();
-}
-
// Start a device without calling Open, using a non-magic ID.
TEST_F(VideoCaptureManagerTest, StartInvalidSession) {
StartClient(22, false);
diff --git a/chromium/content/browser/renderer_host/media/video_capture_oracle.cc b/chromium/content/browser/renderer_host/media/video_capture_oracle.cc
index c05ac0f8a37..fb41ec2fe4e 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_oracle.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_oracle.cc
@@ -130,11 +130,11 @@ void SmoothEventSampler::RecordSample() {
}
bool is_paused = overdue_sample_count_ == redundant_capture_goal_;
- LOG_IF(INFO, !was_paused && is_paused)
- << "Tab content unchanged for " << redundant_capture_goal_
- << " frames; capture will halt until content changes.";
- LOG_IF(INFO, was_paused && !is_paused)
- << "Content changed; capture will resume.";
+ VLOG_IF(0, !was_paused && is_paused)
+ << "Tab content unchanged for " << redundant_capture_goal_
+ << " frames; capture will halt until content changes.";
+ VLOG_IF(0, was_paused && !is_paused)
+ << "Content changed; capture will resume.";
}
bool SmoothEventSampler::IsOverdueForSamplingAt(base::Time event_time) const {
diff --git a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.cc b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.cc
index 91feb4d4873..15258a04523 100644
--- a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.cc
+++ b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.cc
@@ -7,9 +7,9 @@
// performance. Spanning several threads, the process of capturing has been
// split up into four conceptual stages:
//
-// 1. Reserve Buffer: Before a frame can be captured, a slot in the consumer's
+// 1. Reserve Buffer: Before a frame can be captured, a slot in the client's
// shared-memory IPC buffer is reserved. There are only a few of these;
-// when they run out, it indicates that the downstream consumer -- likely a
+// when they run out, it indicates that the downstream client -- likely a
// video encoder -- is the performance bottleneck, and that the rate of
// frame capture should be throttled back.
//
@@ -27,9 +27,9 @@
// bitmap returned by Capture, and writes into the reserved slot in the
// shared-memory buffer.
//
-// 4. Deliver: The rendered video frame is returned to the consumer (which
-// implements the VideoCaptureDevice::EventHandler interface). Because
-// all paths have written the frame into the IPC buffer, this step should
+// 4. Deliver: The rendered video frame is returned to the client (which
+// implements the VideoCaptureDevice::Client interface). Because all
+// paths have written the frame into the IPC buffer, this step should
// never need to do an additional copy of the pixel data.
//
// In the best-performing case, the Render step is bypassed: Capture produces
@@ -50,26 +50,18 @@
#include "content/browser/renderer_host/media/web_contents_video_capture_device.h"
-#include <algorithm>
-#include <list>
-#include <string>
-
#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/callback_forward.h"
#include "base/callback_helpers.h"
-#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
#include "base/sequenced_task_runner.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
+#include "content/browser/renderer_host/media/video_capture_device_impl.h"
#include "content/browser/renderer_host/media/video_capture_oracle.h"
#include "content/browser/renderer_host/media/web_contents_capture_util.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -79,45 +71,19 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
-#include "media/base/bind_to_loop.h"
-#include "media/base/video_frame.h"
#include "media/base/video_util.h"
-#include "media/base/yuv_convert.h"
#include "media/video/capture/video_capture_types.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/skia_util.h"
namespace content {
namespace {
-const int kMinFrameWidth = 2;
-const int kMinFrameHeight = 2;
-const int kMaxFramesInFlight = 2;
-const int kMaxSnapshotsInFlight = 1;
-
-// TODO(nick): Remove this once frame subscription is supported on Aura and
-// Linux.
-#if (defined(OS_WIN) || defined(OS_MACOSX)) || defined(USE_AURA)
-const bool kAcceleratedSubscriberIsSupported = true;
-#else
-const bool kAcceleratedSubscriberIsSupported = false;
-#endif
-
-// Returns the nearest even integer closer to zero.
-template<typename IntType>
-IntType MakeEven(IntType x) {
- return x & static_cast<IntType>(-2);
-}
-
// Compute a letterbox region, aligned to even coordinates.
gfx::Rect ComputeYV12LetterboxRegion(const gfx::Size& frame_size,
const gfx::Size& content_size) {
@@ -133,61 +99,14 @@ gfx::Rect ComputeYV12LetterboxRegion(const gfx::Size& frame_size,
return result;
}
-// Thread-safe, refcounted proxy to the VideoCaptureOracle. This proxy wraps
-// the VideoCaptureOracle, which decides which frames to capture, and a
-// VideoCaptureDevice::EventHandler, which allocates and receives the captured
-// frames, in a lock to synchronize state between the two.
-class ThreadSafeCaptureOracle
- : public base::RefCountedThreadSafe<ThreadSafeCaptureOracle> {
- public:
- ThreadSafeCaptureOracle(media::VideoCaptureDevice::EventHandler* consumer,
- scoped_ptr<VideoCaptureOracle> oracle);
-
- bool ObserveEventAndDecideCapture(
- VideoCaptureOracle::Event event,
- base::Time event_time,
- scoped_refptr<media::VideoFrame>* storage,
- RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback);
-
- base::TimeDelta capture_period() const {
- return oracle_->capture_period();
- }
-
- // Allow new captures to start occurring.
- void Start();
-
- // Stop new captures from happening (but doesn't forget the consumer).
- void Stop();
-
- // Signal an error to the consumer.
- void ReportError();
-
- // Permanently stop capturing. Immediately cease all activity on the
- // VCD::EventHandler.
- void InvalidateConsumer();
-
- private:
- friend class base::RefCountedThreadSafe<ThreadSafeCaptureOracle>;
- virtual ~ThreadSafeCaptureOracle() {}
-
- // Callback invoked on completion of all captures.
- void DidCaptureFrame(const scoped_refptr<media::VideoFrame>& frame,
- int frame_number,
- base::Time timestamp,
- bool success);
-
- // Protects everything below it.
- base::Lock lock_;
-
- // Recipient of our capture activity. Becomes null after it is invalidated.
- media::VideoCaptureDevice::EventHandler* consumer_;
-
- // Makes the decision to capture a frame.
- const scoped_ptr<VideoCaptureOracle> oracle_;
-
- // Whether capturing is currently allowed. Can toggle back and forth.
- bool is_started_;
-};
+// Wrapper function to invoke ThreadSafeCaptureOracle::CaptureFrameCallback, is
+// compatible with RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback.
+void InvokeCaptureFrameCallback(
+ const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb,
+ base::Time timestamp,
+ bool frame_captured) {
+ capture_frame_cb.Run(timestamp, frame_captured);
+}
// FrameSubscriber is a proxy to the ThreadSafeCaptureOracle that's compatible
// with RenderWidgetHostViewFrameSubscriber. We create one per event type.
@@ -281,18 +200,18 @@ void RenderVideoFrame(const SkBitmap& input,
// implementation is currently asynchronous -- in our case, the "rvh changed"
// notification would get posted back to the UI thread and processed later, and
// this seems disadvantageous.
-class CaptureMachine : public WebContentsObserver,
- public base::SupportsWeakPtr<CaptureMachine> {
+class WebContentsCaptureMachine
+ : public VideoCaptureMachine,
+ public WebContentsObserver,
+ public base::SupportsWeakPtr<WebContentsCaptureMachine> {
public:
- virtual ~CaptureMachine();
+ WebContentsCaptureMachine(int render_process_id, int render_view_id);
+ virtual ~WebContentsCaptureMachine();
- // Creates a CaptureMachine. Must be run on the UI BrowserThread. Returns
- // NULL if the indicated render view cannot be found.
- static scoped_ptr<CaptureMachine> Create(
- int render_process_id,
- int render_view_id,
- const scoped_refptr<base::SequencedTaskRunner>& render_task_runner,
- const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy);
+ // VideoCaptureMachine overrides.
+ virtual bool Start(
+ const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) OVERRIDE;
+ virtual void Stop() OVERRIDE;
// Starts a copy from the backing store or the composited surface. Must be run
// on the UI BrowserThread. |deliver_frame_cb| will be run when the operation
@@ -334,13 +253,8 @@ class CaptureMachine : public WebContentsObserver,
virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
private:
- CaptureMachine(
- const scoped_refptr<base::SequencedTaskRunner>& render_task_runner,
- const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy);
-
// Starts observing the web contents, returning false if lookup fails.
- bool StartObservingWebContents(int initial_render_process_id,
- int initial_render_view_id);
+ bool StartObservingWebContents();
// Helper function to determine the view that we are currently tracking.
RenderWidgetHost* GetTarget();
@@ -366,12 +280,16 @@ class CaptureMachine : public WebContentsObserver,
// attached views.
void RenewFrameSubscription();
- // The task runner of the thread on which SkBitmap->VideoFrame conversion will
+ // Parameters saved in constructor.
+ const int initial_render_process_id_;
+ const int initial_render_view_id_;
+
+ // A dedicated worker thread on which SkBitmap->VideoFrame conversion will
// occur. Only used when this activity cannot be done on the GPU.
- const scoped_refptr<base::SequencedTaskRunner> render_task_runner_;
+ base::Thread render_thread_;
// Makes all the decisions about which frames to copy, and how.
- const scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_;
+ scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_;
// Routing ID of any active fullscreen render widget or MSG_ROUTING_NONE
// otherwise.
@@ -384,7 +302,7 @@ class CaptureMachine : public WebContentsObserver,
// oracle, and initiating captures accordingly.
scoped_ptr<ContentCaptureSubscription> subscription_;
- DISALLOW_COPY_AND_ASSIGN(CaptureMachine);
+ DISALLOW_COPY_AND_ASSIGN(WebContentsCaptureMachine);
};
// Responsible for logging the effective frame rate.
@@ -407,117 +325,6 @@ class VideoFrameDeliveryLog {
DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliveryLog);
};
-ThreadSafeCaptureOracle::ThreadSafeCaptureOracle(
- media::VideoCaptureDevice::EventHandler* consumer,
- scoped_ptr<VideoCaptureOracle> oracle)
- : consumer_(consumer),
- oracle_(oracle.Pass()),
- is_started_(false) {
-}
-
-bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
- VideoCaptureOracle::Event event,
- base::Time event_time,
- scoped_refptr<media::VideoFrame>* storage,
- RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback) {
- base::AutoLock guard(lock_);
-
- if (!consumer_ || !is_started_)
- return false; // Capture is stopped.
-
- scoped_refptr<media::VideoFrame> output_buffer =
- consumer_->ReserveOutputBuffer();
- const bool should_capture =
- oracle_->ObserveEventAndDecideCapture(event, event_time);
- const bool content_is_dirty =
- (event == VideoCaptureOracle::kCompositorUpdate ||
- event == VideoCaptureOracle::kSoftwarePaint);
- const char* event_name =
- (event == VideoCaptureOracle::kTimerPoll ? "poll" :
- (event == VideoCaptureOracle::kCompositorUpdate ? "gpu" :
- "paint"));
-
- // Consider the various reasons not to initiate a capture.
- if (should_capture && !output_buffer.get()) {
- TRACE_EVENT_INSTANT1("mirroring",
- "EncodeLimited",
- TRACE_EVENT_SCOPE_THREAD,
- "trigger",
- event_name);
- return false;
- } else if (!should_capture && output_buffer.get()) {
- if (content_is_dirty) {
- // This is a normal and acceptable way to drop a frame. We've hit our
- // capture rate limit: for example, the content is animating at 60fps but
- // we're capturing at 30fps.
- TRACE_EVENT_INSTANT1("mirroring", "FpsRateLimited",
- TRACE_EVENT_SCOPE_THREAD,
- "trigger", event_name);
- }
- return false;
- } else if (!should_capture && !output_buffer.get()) {
- // We decided not to capture, but we wouldn't have been able to if we wanted
- // to because no output buffer was available.
- TRACE_EVENT_INSTANT1("mirroring", "NearlyEncodeLimited",
- TRACE_EVENT_SCOPE_THREAD,
- "trigger", event_name);
- return false;
- }
- int frame_number = oracle_->RecordCapture();
- TRACE_EVENT_ASYNC_BEGIN2("mirroring", "Capture", output_buffer.get(),
- "frame_number", frame_number,
- "trigger", event_name);
- *storage = output_buffer;
- *callback = base::Bind(&ThreadSafeCaptureOracle::DidCaptureFrame,
- this, output_buffer, frame_number);
- return true;
-}
-
-void ThreadSafeCaptureOracle::Start() {
- base::AutoLock guard(lock_);
- is_started_ = true;
-}
-
-void ThreadSafeCaptureOracle::Stop() {
- base::AutoLock guard(lock_);
- is_started_ = false;
-}
-
-void ThreadSafeCaptureOracle::ReportError() {
- base::AutoLock guard(lock_);
- if (consumer_)
- consumer_->OnError();
-}
-
-void ThreadSafeCaptureOracle::InvalidateConsumer() {
- base::AutoLock guard(lock_);
-
- TRACE_EVENT_INSTANT0("mirroring", "InvalidateConsumer",
- TRACE_EVENT_SCOPE_THREAD);
-
- is_started_ = false;
- consumer_ = NULL;
-}
-
-void ThreadSafeCaptureOracle::DidCaptureFrame(
- const scoped_refptr<media::VideoFrame>& frame,
- int frame_number,
- base::Time timestamp,
- bool success) {
- base::AutoLock guard(lock_);
-
- TRACE_EVENT_ASYNC_END2("mirroring", "Capture", frame.get(),
- "success", success,
- "timestamp", timestamp.ToInternalValue());
-
- if (!consumer_ || !is_started_)
- return; // Capture is stopped.
-
- if (success)
- if (oracle_->CompleteCapture(frame_number, timestamp))
- consumer_->OnIncomingCapturedVideoFrame(frame, timestamp);
-}
-
bool FrameSubscriber::ShouldCaptureFrame(
base::Time present_time,
scoped_refptr<media::VideoFrame>* storage,
@@ -525,8 +332,12 @@ bool FrameSubscriber::ShouldCaptureFrame(
TRACE_EVENT1("mirroring", "FrameSubscriber::ShouldCaptureFrame",
"instance", this);
- return oracle_proxy_->ObserveEventAndDecideCapture(event_type_, present_time,
- storage, deliver_frame_cb);
+ ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
+ bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture(
+ event_type_, present_time, storage, &capture_frame_cb);
+
+ *deliver_frame_cb = base::Bind(&InvokeCaptureFrameCallback, capture_frame_cb);
+ return oracle_decision;
}
ContentCaptureSubscription::ContentCaptureSubscription(
@@ -554,7 +365,8 @@ ContentCaptureSubscription::ContentCaptureSubscription(
}
// Subscribe to software paint events. This instance will service these by
- // reflecting them back to the CaptureMachine via |capture_callback|.
+ // reflecting them back to the WebContentsCaptureMachine via
+ // |capture_callback|.
registrar_.Add(
this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
Source<RenderWidgetHost>(&source));
@@ -673,7 +485,7 @@ void RenderVideoFrame(const SkBitmap& input,
method = skia::ImageOperations::RESIZE_BOX;
}
- TRACE_EVENT_ASYNC_STEP0("mirroring", "Capture", output.get(), "Scale");
+ TRACE_EVENT_ASYNC_STEP_INTO0("mirroring", "Capture", output.get(), "Scale");
scaled_bitmap = skia::ImageOperations::Resize(input, method,
region_in_frame.width(),
region_in_frame.height());
@@ -681,7 +493,7 @@ void RenderVideoFrame(const SkBitmap& input,
scaled_bitmap = input;
}
- TRACE_EVENT_ASYNC_STEP0("mirroring", "Capture", output.get(), "YUV");
+ TRACE_EVENT_ASYNC_STEP_INTO0("mirroring", "Capture", output.get(), "YUV");
{
SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap);
@@ -736,44 +548,47 @@ void VideoFrameDeliveryLog::ChronicleFrameDelivery(int frame_number) {
}
}
-// static
-scoped_ptr<CaptureMachine> CaptureMachine::Create(
- int render_process_id,
- int render_view_id,
- const scoped_refptr<base::SequencedTaskRunner>& render_task_runner,
+WebContentsCaptureMachine::WebContentsCaptureMachine(int render_process_id,
+ int render_view_id)
+ : initial_render_process_id_(render_process_id),
+ initial_render_view_id_(render_view_id),
+ render_thread_("WebContentsVideo_RenderThread"),
+ fullscreen_widget_id_(MSG_ROUTING_NONE) {}
+
+WebContentsCaptureMachine::~WebContentsCaptureMachine() {}
+
+bool WebContentsCaptureMachine::Start(
const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(render_task_runner.get());
- DCHECK(oracle_proxy.get());
- scoped_ptr<CaptureMachine> machine(
- new CaptureMachine(render_task_runner, oracle_proxy));
+ DCHECK(!started_);
- if (!machine->StartObservingWebContents(render_process_id, render_view_id))
- machine.reset();
+ DCHECK(oracle_proxy.get());
+ oracle_proxy_ = oracle_proxy;
- return machine.Pass();
-}
+ if (!render_thread_.Start()) {
+ DVLOG(1) << "Failed to spawn render thread.";
+ return false;
+ }
-CaptureMachine::CaptureMachine(
- const scoped_refptr<base::SequencedTaskRunner>& render_task_runner,
- const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy)
- : render_task_runner_(render_task_runner),
- oracle_proxy_(oracle_proxy),
- fullscreen_widget_id_(MSG_ROUTING_NONE) {}
+ if (!StartObservingWebContents())
+ return false;
-CaptureMachine::~CaptureMachine() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
- !BrowserThread::IsMessageLoopValid(BrowserThread::UI));
+ started_ = true;
+ return true;
+}
- // Stop observing the web contents.
+void WebContentsCaptureMachine::Stop() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
subscription_.reset();
if (web_contents()) {
web_contents()->DecrementCapturerCount();
Observe(NULL);
}
+ render_thread_.Stop();
+ started_ = false;
}
-void CaptureMachine::Capture(
+void WebContentsCaptureMachine::Capture(
const base::Time& start_time,
const scoped_refptr<media::VideoFrame>& target,
const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
@@ -808,27 +623,25 @@ void CaptureMachine::Capture(
// backing store are not accessible.
rwh->GetSnapshotFromRenderer(
gfx::Rect(),
- base::Bind(&CaptureMachine::DidCopyFromBackingStore, this->AsWeakPtr(),
- start_time, target, deliver_frame_cb));
+ base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore,
+ this->AsWeakPtr(), start_time, target, deliver_frame_cb));
} else if (view->CanCopyToVideoFrame()) {
view->CopyFromCompositingSurfaceToVideoFrame(
gfx::Rect(view_size),
target,
- base::Bind(&CaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame,
+ base::Bind(&WebContentsCaptureMachine::
+ DidCopyFromCompositingSurfaceToVideoFrame,
this->AsWeakPtr(), start_time, deliver_frame_cb));
} else {
rwh->CopyFromBackingStore(
gfx::Rect(),
fitted_size, // Size here is a request not always honored.
- base::Bind(&CaptureMachine::DidCopyFromBackingStore, this->AsWeakPtr(),
- start_time, target, deliver_frame_cb));
+ base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore,
+ this->AsWeakPtr(), start_time, target, deliver_frame_cb));
}
}
-bool CaptureMachine::StartObservingWebContents(int initial_render_process_id,
- int initial_render_view_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
+bool WebContentsCaptureMachine::StartObservingWebContents() {
// Look-up the RenderViewHost and, from that, the WebContents that wraps it.
// If successful, begin observing the WebContents instance.
//
@@ -839,11 +652,11 @@ bool CaptureMachine::StartObservingWebContents(int initial_render_process_id,
// a bit of indirection across threads. It's easily possible that, in the
// meantime, the original RenderView may have gone away.
RenderViewHost* const rvh =
- RenderViewHost::FromID(initial_render_process_id,
- initial_render_view_id);
+ RenderViewHost::FromID(initial_render_process_id_,
+ initial_render_view_id_);
DVLOG_IF(1, !rvh) << "RenderViewHost::FromID("
- << initial_render_process_id << ", "
- << initial_render_view_id << ") returned NULL.";
+ << initial_render_process_id_ << ", "
+ << initial_render_view_id_ << ") returned NULL.";
Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL);
WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents());
@@ -858,7 +671,8 @@ bool CaptureMachine::StartObservingWebContents(int initial_render_process_id,
return false;
}
-void CaptureMachine::WebContentsDestroyed(WebContents* web_contents) {
+void WebContentsCaptureMachine::WebContentsDestroyed(
+ WebContents* web_contents) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
subscription_.reset();
@@ -866,7 +680,7 @@ void CaptureMachine::WebContentsDestroyed(WebContents* web_contents) {
oracle_proxy_->ReportError();
}
-RenderWidgetHost* CaptureMachine::GetTarget() {
+RenderWidgetHost* WebContentsCaptureMachine::GetTarget() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!web_contents())
return NULL;
@@ -883,7 +697,7 @@ RenderWidgetHost* CaptureMachine::GetTarget() {
return rwh;
}
-void CaptureMachine::DidCopyFromBackingStore(
+void WebContentsCaptureMachine::DidCopyFromBackingStore(
const base::Time& start_time,
const scoped_refptr<media::VideoFrame>& target,
const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
@@ -895,8 +709,9 @@ void CaptureMachine::DidCopyFromBackingStore(
base::Time now = base::Time::Now();
if (success) {
UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeBitmap", now - start_time);
- TRACE_EVENT_ASYNC_STEP0("mirroring", "Capture", target.get(), "Render");
- render_task_runner_->PostTask(FROM_HERE, base::Bind(
+ TRACE_EVENT_ASYNC_STEP_INTO0("mirroring", "Capture", target.get(),
+ "Render");
+ render_thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
&RenderVideoFrame, bitmap, target,
base::Bind(deliver_frame_cb, start_time)));
} else {
@@ -906,7 +721,7 @@ void CaptureMachine::DidCopyFromBackingStore(
}
}
-void CaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
+void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
const base::Time& start_time,
const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
deliver_frame_cb,
@@ -923,7 +738,7 @@ void CaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
deliver_frame_cb.Run(start_time, success);
}
-void CaptureMachine::RenewFrameSubscription() {
+void WebContentsCaptureMachine::RenewFrameSubscription() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Always destroy the old subscription before creating a new one.
@@ -934,345 +749,43 @@ void CaptureMachine::RenewFrameSubscription() {
return;
subscription_.reset(new ContentCaptureSubscription(*rwh, oracle_proxy_,
- base::Bind(&CaptureMachine::Capture, this->AsWeakPtr())));
-}
-
-void DeleteCaptureMachineOnUIThread(
- scoped_ptr<CaptureMachine> capture_machine) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- capture_machine.reset();
+ base::Bind(&WebContentsCaptureMachine::Capture, this->AsWeakPtr())));
}
} // namespace
-// The "meat" of the video capture implementation, which is a ref-counted class.
-// Separating this from the "shell class" WebContentsVideoCaptureDevice allows
-// safe destruction without needing to block any threads (e.g., the IO
-// BrowserThread).
-//
-// WebContentsVideoCaptureDevice::Impl manages a simple state machine and the
-// pipeline (see notes at top of this file). It times the start of successive
-// captures and facilitates the processing of each through the stages of the
-// pipeline.
-class WebContentsVideoCaptureDevice::Impl : public base::SupportsWeakPtr<Impl> {
- public:
-
- Impl(int render_process_id, int render_view_id);
- virtual ~Impl();
-
- // Asynchronous requests to change WebContentsVideoCaptureDevice::Impl state.
- void Allocate(int width,
- int height,
- int frame_rate,
- media::VideoCaptureDevice::EventHandler* consumer);
- void Start();
- void Stop();
- void DeAllocate();
-
- private:
-
- // Flag indicating current state.
- enum State {
- kIdle,
- kAllocated,
- kCapturing,
- kError
- };
-
- void TransitionStateTo(State next_state);
-
- // Stops capturing and notifies consumer_ of an error state.
- void Error();
-
- // Called in response to CaptureMachine::Create that runs on the UI thread.
- // It will assign the capture machine to the Impl class if it still exists
- // otherwise it will post a task to delete CaptureMachine on the UI thread.
- static void AssignCaptureMachine(
- base::WeakPtr<WebContentsVideoCaptureDevice::Impl> impl,
- scoped_ptr<CaptureMachine> capture_machine);
-
- // Tracks that all activity occurs on the media stream manager's thread.
- base::ThreadChecker thread_checker_;
-
- // These values identify the starting view that will be captured. After
- // capture starts, the target view IDs will change as navigation occurs, and
- // so these values are not relevant after the initial bootstrapping.
- const int initial_render_process_id_;
- const int initial_render_view_id_;
-
- // Our event handler, which gobbles the frames we capture.
- VideoCaptureDevice::EventHandler* consumer_;
-
- // Current lifecycle state.
- State state_;
-
- // A dedicated worker thread for doing image operations. Started/joined here,
- // but used by the CaptureMachine.
- base::Thread render_thread_;
-
- // Tracks the CaptureMachine that's doing work on our behalf on the UI thread.
- // This value should never be dereferenced by this class, other than to
- // create and destroy it on the UI thread.
- scoped_ptr<CaptureMachine> capture_machine_;
-
- // Our thread-safe capture oracle which serves as the gateway to the video
- // capture pipeline. Besides the WCVCD itself, it is the only component of the
- // system with direct access to |consumer_|.
- scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_;
-
- DISALLOW_COPY_AND_ASSIGN(Impl);
-};
-
-WebContentsVideoCaptureDevice::Impl::Impl(int render_process_id,
- int render_view_id)
- : initial_render_process_id_(render_process_id),
- initial_render_view_id_(render_view_id),
- consumer_(NULL),
- state_(kIdle),
- render_thread_("WebContentsVideo_RenderThread") {
-}
-
-void WebContentsVideoCaptureDevice::Impl::Allocate(
- int width,
- int height,
- int frame_rate,
- VideoCaptureDevice::EventHandler* consumer) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (state_ != kIdle) {
- DVLOG(1) << "Allocate() invoked when not in state Idle.";
- return;
- }
-
- if (frame_rate <= 0) {
- DVLOG(1) << "invalid frame_rate: " << frame_rate;
- consumer->OnError();
- return;
- }
-
- if (!render_thread_.Start()) {
- DVLOG(1) << "Failed to spawn render thread.";
- consumer->OnError();
- return;
- }
-
- // Frame dimensions must each be a positive, even integer, since the consumer
- // wants (or will convert to) YUV420.
- width = MakeEven(width);
- height = MakeEven(height);
- if (width < kMinFrameWidth || height < kMinFrameHeight) {
- DVLOG(1) << "invalid width (" << width << ") and/or height ("
- << height << ")";
- consumer->OnError();
- return;
- }
-
- // Initialize capture settings which will be consistent for the
- // duration of the capture.
- media::VideoCaptureCapability settings;
-
- settings.width = width;
- settings.height = height;
- settings.frame_rate = frame_rate;
- // Note: the value of |settings.color| doesn't matter if we use only the
- // VideoFrame based methods on |consumer|.
- settings.color = media::PIXEL_FORMAT_I420;
- settings.expected_capture_delay = 0;
- settings.interlaced = false;
-
- base::TimeDelta capture_period = base::TimeDelta::FromMicroseconds(
- 1000000.0 / settings.frame_rate + 0.5);
-
- consumer_ = consumer;
- consumer_->OnFrameInfo(settings);
- scoped_ptr<VideoCaptureOracle> oracle(
- new VideoCaptureOracle(capture_period,
- kAcceleratedSubscriberIsSupported));
- oracle_proxy_ = new ThreadSafeCaptureOracle(
- consumer_,
- oracle.Pass());
-
- // Allocates the CaptureMachine. The CaptureMachine will be tracking render
- // view swapping over its lifetime, and we don't want to lose our reference to
- // the current render view by starting over with the stale
- // |initial_render_view_id_|.
- DCHECK(!capture_machine_.get());
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&CaptureMachine::Create,
- initial_render_process_id_,
- initial_render_view_id_,
- render_thread_.message_loop_proxy(), oracle_proxy_),
- base::Bind(&Impl::AssignCaptureMachine, AsWeakPtr()));
-
- TransitionStateTo(kAllocated);
-}
-
-void WebContentsVideoCaptureDevice::Impl::Start() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (state_ != kAllocated) {
- return;
- }
-
- TransitionStateTo(kCapturing);
-
- oracle_proxy_->Start();
-}
-
-// static
-void WebContentsVideoCaptureDevice::Impl::AssignCaptureMachine(
- base::WeakPtr<WebContentsVideoCaptureDevice::Impl> impl,
- scoped_ptr<CaptureMachine> capture_machine) {
- DCHECK(!impl.get() || impl->thread_checker_.CalledOnValidThread());
-
- if (!impl.get()) {
- // If WCVD::Impl was destroyed before we got back on it's thread and
- // capture_machine is not NULL, then we need to return to the UI thread to
- // safely cleanup the CaptureMachine.
- if (capture_machine) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(
- &DeleteCaptureMachineOnUIThread, base::Passed(&capture_machine)));
- return;
- }
- } else if (!capture_machine) {
- impl->Error();
- } else {
- impl->capture_machine_ = capture_machine.Pass();
- }
-}
-
-void WebContentsVideoCaptureDevice::Impl::Stop() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (state_ != kCapturing) {
- return;
- }
- oracle_proxy_->Stop();
-
- TransitionStateTo(kAllocated);
-}
-
-void WebContentsVideoCaptureDevice::Impl::DeAllocate() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (state_ == kCapturing) {
- Stop();
- }
- if (state_ == kAllocated) {
- // |consumer_| is about to be deleted, so we mustn't use it anymore.
- oracle_proxy_->InvalidateConsumer();
- consumer_ = NULL;
- oracle_proxy_ = NULL;
- render_thread_.Stop();
-
- TransitionStateTo(kIdle);
- }
-}
-
-WebContentsVideoCaptureDevice::Impl::~Impl() {
- // There is still a capture pipeline running that is checking in with the
- // oracle, and processing captures that are already started in flight. That
- // pipeline must be shut down asynchronously, on the UI thread.
- if (capture_machine_) {
- // The task that is posted to the UI thread might not run if we are shutting
- // down, so we transfer ownership of CaptureMachine to the closure so that
- // it is still cleaned up when the closure is deleted.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(
- &DeleteCaptureMachineOnUIThread, base::Passed(&capture_machine_)));
- }
-
- DCHECK(!capture_machine_) << "Cleanup on UI thread did not happen.";
- DCHECK(!consumer_) << "Device not DeAllocated -- possible data race.";
- DVLOG(1) << "WebContentsVideoCaptureDevice::Impl@" << this << " destroying.";
-}
-
-void WebContentsVideoCaptureDevice::Impl::TransitionStateTo(State next_state) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
-#ifndef NDEBUG
- static const char* kStateNames[] = {
- "Idle", "Allocated", "Capturing", "Error"
- };
- DVLOG(1) << "State change: " << kStateNames[state_]
- << " --> " << kStateNames[next_state];
-#endif
-
- state_ = next_state;
-}
-
-void WebContentsVideoCaptureDevice::Impl::Error() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (state_ == kIdle)
- return;
-
- if (consumer_)
- consumer_->OnError();
-
- DeAllocate();
- TransitionStateTo(kError);
-}
-
WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
- const media::VideoCaptureDevice::Name& name,
- int render_process_id,
- int render_view_id)
- : device_name_(name),
- impl_(new WebContentsVideoCaptureDevice::Impl(render_process_id,
- render_view_id)) {}
+ int render_process_id, int render_view_id)
+ : impl_(new VideoCaptureDeviceImpl(scoped_ptr<VideoCaptureMachine>(
+ new WebContentsCaptureMachine(render_process_id, render_view_id)))) {}
WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying.";
}
// static
-media::VideoCaptureDevice1* WebContentsVideoCaptureDevice::Create(
+media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create(
const std::string& device_id) {
// Parse device_id into render_process_id and render_view_id.
int render_process_id = -1;
int render_view_id = -1;
- if (!WebContentsCaptureUtil::ExtractTabCaptureTarget(device_id,
- &render_process_id,
- &render_view_id))
+ if (!WebContentsCaptureUtil::ExtractTabCaptureTarget(
+ device_id, &render_process_id, &render_view_id)) {
return NULL;
+ }
- std::string device_name;
- base::SStringPrintf(&device_name,
- "WebContents[%.*s]",
- static_cast<int>(device_id.size()), device_id.data());
- return new WebContentsVideoCaptureDevice(
- media::VideoCaptureDevice::Name(device_name, device_id),
- render_process_id, render_view_id);
-}
-
-void WebContentsVideoCaptureDevice::Allocate(
- const media::VideoCaptureCapability& capture_format,
- VideoCaptureDevice::EventHandler* observer) {
- DVLOG(1) << "Allocating " << capture_format.width << "x"
- << capture_format.height;
- impl_->Allocate(capture_format.width,
- capture_format.height,
- capture_format.frame_rate,
- observer);
-}
-
-void WebContentsVideoCaptureDevice::Start() {
- impl_->Start();
-}
-
-void WebContentsVideoCaptureDevice::Stop() {
- impl_->Stop();
+ return new WebContentsVideoCaptureDevice(render_process_id, render_view_id);
}
-void WebContentsVideoCaptureDevice::DeAllocate() {
- impl_->DeAllocate();
+void WebContentsVideoCaptureDevice::AllocateAndStart(
+ const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client) {
+ DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString();
+ impl_->AllocateAndStart(params, client.Pass());
}
-const media::VideoCaptureDevice::Name&
-WebContentsVideoCaptureDevice::device_name() {
- return device_name_;
+void WebContentsVideoCaptureDevice::StopAndDeAllocate() {
+ impl_->StopAndDeAllocate();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.h b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.h
index 0dfe1d6e2f0..e9140d3dd8f 100644
--- a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.h
+++ b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device.h
@@ -13,7 +13,7 @@
namespace content {
-class RenderWidgetHost;
+class VideoCaptureDeviceImpl;
// A virtualized VideoCaptureDevice that mirrors the displayed contents of a
// tab (accessed via its associated WebContents instance), producing a stream of
@@ -27,7 +27,7 @@ class RenderWidgetHost;
// underlying render view to be swapped out (e.g., due to navigation or
// crashes/reloads), without any interruption in capturing.
class CONTENT_EXPORT WebContentsVideoCaptureDevice
- : public media::VideoCaptureDevice1 {
+ : public media::VideoCaptureDevice {
public:
// Construct from a |device_id| string of the form:
// "virtual-media-stream://render_process_id:render_view_id", where
@@ -37,32 +37,19 @@ class CONTENT_EXPORT WebContentsVideoCaptureDevice
// WebContentsVideoCaptureDevice is itself deleted.
// TODO(miu): Passing a destroy callback suggests needing to revisit the
// design philosophy of an asynchronous DeAllocate(). http://crbug.com/158641
- static media::VideoCaptureDevice1* Create(const std::string& device_id);
+ static media::VideoCaptureDevice* Create(const std::string& device_id);
virtual ~WebContentsVideoCaptureDevice();
// VideoCaptureDevice implementation.
- virtual void Allocate(const media::VideoCaptureCapability& capture_format,
- VideoCaptureDevice::EventHandler* observer) OVERRIDE;
- virtual void Start() OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void DeAllocate() OVERRIDE;
-
- // Note: The following is just a pass-through of the device_id provided to the
- // constructor. It does not change when the content of the page changes
- // (e.g., due to navigation), or when the underlying RenderView is
- // swapped-out.
- virtual const Name& device_name() OVERRIDE;
+ virtual void AllocateAndStart(const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client) OVERRIDE;
+ virtual void StopAndDeAllocate() OVERRIDE;
private:
- class Impl;
-
- WebContentsVideoCaptureDevice(const Name& name,
- int render_process_id,
- int render_view_id);
+ WebContentsVideoCaptureDevice(int render_process_id, int render_view_id);
- Name device_name_;
- const scoped_ptr<Impl> impl_;
+ const scoped_ptr<VideoCaptureDeviceImpl> impl_;
DISALLOW_COPY_AND_ASSIGN(WebContentsVideoCaptureDevice);
};
diff --git a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
index 3420b09eb7b..db766cd7378 100644
--- a/chromium/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
@@ -16,7 +16,6 @@
#include "content/browser/renderer_host/media/web_contents_capture_util.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
@@ -24,6 +23,7 @@
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
+#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "media/base/video_util.h"
#include "media/base/yuv_convert.h"
@@ -228,13 +228,14 @@ class CaptureTestRenderViewHost : public TestRenderViewHost {
public:
CaptureTestRenderViewHost(SiteInstance* instance,
RenderViewHostDelegate* delegate,
+ RenderFrameHostDelegate* frame_delegate,
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
bool swapped_out,
CaptureTestSourceController* controller)
- : TestRenderViewHost(instance, delegate, widget_delegate, routing_id,
- main_frame_routing_id, swapped_out),
+ : TestRenderViewHost(instance, delegate, frame_delegate, widget_delegate,
+ routing_id, main_frame_routing_id, swapped_out),
controller_(controller) {
// Override the default view installed by TestRenderViewHost; we need
// our special subclass which has mocked-out tab capture support.
@@ -289,13 +290,15 @@ class CaptureTestRenderViewHostFactory : public RenderViewHostFactory {
virtual RenderViewHost* CreateRenderViewHost(
SiteInstance* instance,
RenderViewHostDelegate* delegate,
+ RenderFrameHostDelegate* frame_delegate,
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
bool swapped_out) OVERRIDE {
- return new CaptureTestRenderViewHost(instance, delegate, widget_delegate,
- routing_id, main_frame_routing_id,
- swapped_out, controller_);
+ return new CaptureTestRenderViewHost(instance, delegate, frame_delegate,
+ widget_delegate, routing_id,
+ main_frame_routing_id, swapped_out,
+ controller_);
}
private:
CaptureTestSourceController* controller_;
@@ -305,22 +308,105 @@ class CaptureTestRenderViewHostFactory : public RenderViewHostFactory {
// A stub consumer of captured video frames, which checks the output of
// WebContentsVideoCaptureDevice.
-class StubConsumer : public media::VideoCaptureDevice::EventHandler {
+class StubClient : public media::VideoCaptureDevice::Client {
public:
- StubConsumer()
+ StubClient(const base::Callback<void(SkColor)>& color_callback,
+ const base::Closure& error_callback)
+ : color_callback_(color_callback),
+ error_callback_(error_callback) {
+ buffer_pool_ = new VideoCaptureBufferPool(2);
+ }
+ virtual ~StubClient() {}
+
+ virtual scoped_refptr<media::VideoCaptureDevice::Client::Buffer>
+ ReserveOutputBuffer(media::VideoFrame::Format format,
+ const gfx::Size& dimensions) OVERRIDE {
+ const size_t frame_bytes =
+ media::VideoFrame::AllocationSize(format, dimensions);
+ int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; // Ignored.
+ int buffer_id =
+ buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop);
+ if (buffer_id == VideoCaptureBufferPool::kInvalidId)
+ return NULL;
+ void* data;
+ size_t size;
+ buffer_pool_->GetBufferInfo(buffer_id, &data, &size);
+ return scoped_refptr<media::VideoCaptureDevice::Client::Buffer>(
+ new PoolBuffer(buffer_pool_, buffer_id, data, size));
+ }
+
+ virtual void OnIncomingCapturedFrame(
+ const uint8* data,
+ int length,
+ base::Time timestamp,
+ int rotation,
+ const media::VideoCaptureFormat& frame_format) OVERRIDE {
+ FAIL();
+ }
+
+ virtual void OnIncomingCapturedBuffer(const scoped_refptr<Buffer>& buffer,
+ media::VideoFrame::Format format,
+ const gfx::Size& dimensions,
+ base::Time timestamp,
+ int frame_rate) OVERRIDE {
+ EXPECT_EQ(gfx::Size(kTestWidth, kTestHeight), dimensions);
+ EXPECT_EQ(media::VideoFrame::I420, format);
+ uint8 yuv[3];
+ size_t offset = 0;
+ for (int plane = 0; plane < 3; ++plane) {
+ yuv[plane] = reinterpret_cast<uint8*>(buffer->data())[offset];
+ offset += media::VideoFrame::PlaneAllocationSize(
+ media::VideoFrame::I420, plane, dimensions);
+ }
+ // TODO(nick): We just look at the first pixel presently, because if
+ // the analysis is too slow, the backlog of frames will grow without bound
+ // and trouble erupts. http://crbug.com/174519
+ color_callback_.Run((SkColorSetRGB(yuv[0], yuv[1], yuv[2])));
+ }
+
+ virtual void OnError() OVERRIDE {
+ error_callback_.Run();
+ }
+
+ private:
+ class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer {
+ public:
+ PoolBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool,
+ int buffer_id,
+ void* data,
+ size_t size)
+ : Buffer(buffer_id, data, size), pool_(pool) {}
+
+ private:
+ virtual ~PoolBuffer() { pool_->RelinquishProducerReservation(id()); }
+ const scoped_refptr<VideoCaptureBufferPool> pool_;
+ };
+
+ scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
+ base::Callback<void(SkColor)> color_callback_;
+ base::Closure error_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(StubClient);
+};
+
+class StubClientObserver {
+ public:
+ StubClientObserver()
: error_encountered_(false),
wait_color_yuv_(0xcafe1950) {
- buffer_pool_ = new VideoCaptureBufferPool(
- media::VideoFrame::AllocationSize(media::VideoFrame::I420,
- gfx::Size(kTestWidth, kTestHeight)),
- 2);
- EXPECT_TRUE(buffer_pool_->Allocate());
+ client_.reset(new StubClient(
+ base::Bind(&StubClientObserver::OnColor, base::Unretained(this)),
+ base::Bind(&StubClientObserver::OnError, base::Unretained(this))));
+ }
+
+ virtual ~StubClientObserver() {}
+
+ scoped_ptr<media::VideoCaptureDevice::Client> PassClient() {
+ return client_.PassAs<media::VideoCaptureDevice::Client>();
}
- virtual ~StubConsumer() {}
void QuitIfConditionMet(SkColor color) {
base::AutoLock guard(lock_);
-
if (wait_color_yuv_ == color || error_encountered_)
base::MessageLoop::current()->Quit();
}
@@ -356,67 +442,31 @@ class StubConsumer : public media::VideoCaptureDevice::EventHandler {
return error_encountered_;
}
- virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE {
- return buffer_pool_->ReserveI420VideoFrame(gfx::Size(kTestWidth,
- kTestHeight),
- 0);
- }
-
- virtual void OnIncomingCapturedFrame(
- const uint8* data,
- int length,
- base::Time timestamp,
- int rotation,
- bool flip_vert,
- bool flip_horiz) OVERRIDE {
- FAIL();
- }
-
- virtual void OnIncomingCapturedVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame,
- base::Time timestamp) OVERRIDE {
- EXPECT_EQ(gfx::Size(kTestWidth, kTestHeight), frame->coded_size());
- EXPECT_EQ(media::VideoFrame::I420, frame->format());
- EXPECT_LE(
- 0,
- buffer_pool_->RecognizeReservedBuffer(frame->shared_memory_handle()));
- uint8 yuv[3];
- for (int plane = 0; plane < 3; ++plane) {
- yuv[plane] = frame->data(plane)[0];
- }
- // TODO(nick): We just look at the first pixel presently, because if
- // the analysis is too slow, the backlog of frames will grow without bound
- // and trouble erupts. http://crbug.com/174519
- PostColorOrError(SkColorSetRGB(yuv[0], yuv[1], yuv[2]));
- }
-
- void PostColorOrError(SkColor new_color) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &StubConsumer::QuitIfConditionMet, base::Unretained(this), new_color));
- }
-
- virtual void OnError() OVERRIDE {
+ void OnError() {
{
base::AutoLock guard(lock_);
error_encountered_ = true;
}
- PostColorOrError(kNothingYet);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
+ &StubClientObserver::QuitIfConditionMet,
+ base::Unretained(this),
+ kNothingYet));
}
- virtual void OnFrameInfo(const media::VideoCaptureCapability& info) OVERRIDE {
- EXPECT_EQ(kTestWidth, info.width);
- EXPECT_EQ(kTestHeight, info.height);
- EXPECT_EQ(kTestFramesPerSecond, info.frame_rate);
- EXPECT_EQ(media::PIXEL_FORMAT_I420, info.color);
+ void OnColor(SkColor color) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
+ &StubClientObserver::QuitIfConditionMet,
+ base::Unretained(this),
+ color));
}
private:
base::Lock lock_;
bool error_encountered_;
SkColor wait_color_yuv_;
- scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
+ scoped_ptr<StubClient> client_;
- DISALLOW_COPY_AND_ASSIGN(StubConsumer);
+ DISALLOW_COPY_AND_ASSIGN(StubClientObserver);
};
// Test harness that sets up a minimal environment with necessary stubs.
@@ -474,7 +524,7 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
// CaptureTestSourceController when it finishes destruction.
// Trigger this, and wait.
if (device_) {
- device_->DeAllocate();
+ device_->StopAndDeAllocate();
device_.reset();
}
@@ -493,8 +543,7 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
// Accessors.
CaptureTestSourceController* source() { return &controller_; }
- media::VideoCaptureDevice1* device() { return device_.get(); }
- StubConsumer* consumer() { return &consumer_; }
+ media::VideoCaptureDevice* device() { return device_.get(); }
void SimulateDrawEvent() {
if (source()->CanUseFrameSubscriber()) {
@@ -513,9 +562,12 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
void DestroyVideoCaptureDevice() { device_.reset(); }
+ StubClientObserver* client_observer() {
+ return &client_observer_;
+ }
+
private:
- // The consumer is the ultimate recipient of captured pixel data.
- StubConsumer consumer_;
+ StubClientObserver client_observer_;
// The controller controls which pixel patterns to produce.
CaptureTestSourceController controller_;
@@ -532,7 +584,7 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
scoped_ptr<WebContents> web_contents_;
// Finally, the WebContentsVideoCaptureDevice under test.
- scoped_ptr<media::VideoCaptureDevice1> device_;
+ scoped_ptr<media::VideoCaptureDevice> device_;
TestBrowserThreadBundle thread_bundle_;
};
@@ -543,38 +595,29 @@ TEST_F(WebContentsVideoCaptureDeviceTest, InvalidInitialWebContentsError) {
// practice; we should be able to recover gracefully.
ResetWebContents();
- media::VideoCaptureCapability capture_format(
- kTestWidth,
- kTestHeight,
- kTestFramesPerSecond,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice);
- device()->Allocate(capture_format, consumer());
- device()->Start();
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForError());
- device()->DeAllocate();
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
+ capture_params.requested_format.frame_rate = kTestFramesPerSecond;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
+ device()->AllocateAndStart(capture_params, client_observer()->PassClient());
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError());
+ device()->StopAndDeAllocate();
}
TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) {
// We'll simulate the tab being closed after the capture pipeline is up and
// running.
- media::VideoCaptureCapability capture_format(
- kTestWidth,
- kTestHeight,
- kTestFramesPerSecond,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice);
- device()->Allocate(capture_format, consumer());
- device()->Start();
-
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
+ capture_params.requested_format.frame_rate = kTestFramesPerSecond;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
+ device()->AllocateAndStart(capture_params, client_observer()->PassClient());
// Do one capture to prove
source()->SetSolidColor(SK_ColorRED);
SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED));
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED));
base::RunLoop().RunUntilIdle();
@@ -583,25 +626,21 @@ TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&WebContentsVideoCaptureDeviceTest::ResetWebContents,
base::Unretained(this)));
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForError());
- device()->DeAllocate();
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError());
+ device()->StopAndDeAllocate();
}
TEST_F(WebContentsVideoCaptureDeviceTest,
StopDeviceBeforeCaptureMachineCreation) {
- media::VideoCaptureCapability capture_format(
- kTestWidth,
- kTestHeight,
- kTestFramesPerSecond,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice);
- device()->Allocate(capture_format, consumer());
- device()->Start();
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
+ capture_params.requested_format.frame_rate = kTestFramesPerSecond;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
+ device()->AllocateAndStart(capture_params, client_observer()->PassClient());
+
// Make a point of not running the UI messageloop here.
- device()->Stop();
- device()->DeAllocate();
+ device()->StopAndDeAllocate();
DestroyVideoCaptureDevice();
// Currently, there should be CreateCaptureMachineOnUIThread() and
@@ -615,71 +654,58 @@ TEST_F(WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) {
// Set up the test to use RGB copies and an normal
source()->SetCanCopyToVideoFrame(false);
source()->SetUseFrameSubscriber(false);
- media::VideoCaptureCapability capture_format(
- kTestWidth,
- kTestHeight,
- kTestFramesPerSecond,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice);
- device()->Allocate(capture_format, consumer());
-
- device()->Start();
- // Make a point of not running the UI messageloop here.
- // TODO(ajwong): Why do we care?
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
+ capture_params.requested_format.frame_rate = kTestFramesPerSecond;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
+ device()->AllocateAndStart(capture_params, client_observer()->PassClient());
+
base::RunLoop().RunUntilIdle();
for (int i = 0; i < 10; ++i)
SimulateDrawEvent();
- device()->Stop();
- device()->DeAllocate();
- // Currently, there should be CreateCaptureMachineOnUIThread() and
- // DestroyCaptureMachineOnUIThread() tasks pending on the current message
- // loop. These should both succeed without crashing, and the machine should
- // wind up in the idle state.
- ASSERT_FALSE(consumer()->HasError());
+ ASSERT_FALSE(client_observer()->HasError());
+ device()->StopAndDeAllocate();
+ ASSERT_FALSE(client_observer()->HasError());
base::RunLoop().RunUntilIdle();
- ASSERT_FALSE(consumer()->HasError());
+ ASSERT_FALSE(client_observer()->HasError());
}
TEST_F(WebContentsVideoCaptureDeviceTest, DeviceRestart) {
- media::VideoCaptureCapability capture_format(
- kTestWidth,
- kTestHeight,
- kTestFramesPerSecond,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice);
- device()->Allocate(capture_format, consumer());
- device()->Start();
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
+ capture_params.requested_format.frame_rate = kTestFramesPerSecond;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
+ device()->AllocateAndStart(capture_params, client_observer()->PassClient());
base::RunLoop().RunUntilIdle();
source()->SetSolidColor(SK_ColorRED);
SimulateDrawEvent();
SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED));
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED));
SimulateDrawEvent();
SimulateDrawEvent();
source()->SetSolidColor(SK_ColorGREEN);
SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorGREEN));
- device()->Stop();
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN));
+ device()->StopAndDeAllocate();
// Device is stopped, but content can still be animating.
SimulateDrawEvent();
SimulateDrawEvent();
base::RunLoop().RunUntilIdle();
- device()->Start();
+ StubClientObserver observer2;
+ device()->AllocateAndStart(capture_params, observer2.PassClient());
source()->SetSolidColor(SK_ColorBLUE);
SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorBLUE));
+ ASSERT_NO_FATAL_FAILURE(observer2.WaitForNextColor(SK_ColorBLUE));
source()->SetSolidColor(SK_ColorYELLOW);
SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorYELLOW));
- device()->DeAllocate();
+ ASSERT_NO_FATAL_FAILURE(observer2.WaitForNextColor(SK_ColorYELLOW));
+ device()->StopAndDeAllocate();
}
// The "happy case" test. No scaling is needed, so we should be able to change
@@ -687,17 +713,12 @@ TEST_F(WebContentsVideoCaptureDeviceTest, DeviceRestart) {
// consumer. The test will alternate between the three capture paths, simulating
// falling in and out of accelerated compositing.
TEST_F(WebContentsVideoCaptureDeviceTest, GoesThroughAllTheMotions) {
- media::VideoCaptureCapability capture_format(
- kTestWidth,
- kTestHeight,
- kTestFramesPerSecond,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice);
- device()->Allocate(capture_format, consumer());
-
- device()->Start();
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
+ capture_params.requested_format.frame_rate = kTestFramesPerSecond;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
+ device()->AllocateAndStart(capture_params, client_observer()->PassClient());
for (int i = 0; i < 6; i++) {
const char* name = NULL;
@@ -725,56 +746,55 @@ TEST_F(WebContentsVideoCaptureDeviceTest, GoesThroughAllTheMotions) {
source()->SetSolidColor(SK_ColorRED);
SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED));
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED));
source()->SetSolidColor(SK_ColorGREEN);
SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorGREEN));
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN));
source()->SetSolidColor(SK_ColorBLUE);
SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorBLUE));
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorBLUE));
source()->SetSolidColor(SK_ColorBLACK);
SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorBLACK));
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorBLACK));
}
- device()->DeAllocate();
+ device()->StopAndDeAllocate();
}
TEST_F(WebContentsVideoCaptureDeviceTest, RejectsInvalidAllocateParams) {
- media::VideoCaptureCapability capture_format(
- 1280,
- 720,
- -2,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice);
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- base::Bind(&media::VideoCaptureDevice1::Allocate,
- base::Unretained(device()),
- capture_format,
- consumer()));
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForError());
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(1280, 720);
+ capture_params.requested_format.frame_rate = -2;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&media::VideoCaptureDevice::AllocateAndStart,
+ base::Unretained(device()),
+ capture_params,
+ base::Passed(client_observer()->PassClient())));
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError());
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&media::VideoCaptureDevice::StopAndDeAllocate,
+ base::Unretained(device())));
+ base::RunLoop().RunUntilIdle();
}
TEST_F(WebContentsVideoCaptureDeviceTest, BadFramesGoodFrames) {
- media::VideoCaptureCapability capture_format(
- kTestWidth,
- kTestHeight,
- kTestFramesPerSecond,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice);
- device()->Allocate(capture_format, consumer());
-
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
+ capture_params.requested_format.frame_rate = kTestFramesPerSecond;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
// 1x1 is too small to process; we intend for this to result in an error.
source()->SetCopyResultSize(1, 1);
source()->SetSolidColor(SK_ColorRED);
- device()->Start();
+ device()->AllocateAndStart(capture_params, client_observer()->PassClient());
// These frames ought to be dropped during the Render stage. Let
// several captures to happen.
@@ -787,12 +807,11 @@ TEST_F(WebContentsVideoCaptureDeviceTest, BadFramesGoodFrames) {
// Now push some good frames through; they should be processed normally.
source()->SetCopyResultSize(kTestWidth, kTestHeight);
source()->SetSolidColor(SK_ColorGREEN);
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorGREEN));
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN));
source()->SetSolidColor(SK_ColorRED);
- ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED));
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED));
- device()->Stop();
- device()->DeAllocate();
+ device()->StopAndDeAllocate();
}
} // namespace
diff --git a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc
index 76c536baf7c..16f7b6e278b 100644
--- a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc
+++ b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc
@@ -15,9 +15,10 @@ namespace content {
WebRTCIdentityServiceHost::WebRTCIdentityServiceHost(
int renderer_process_id,
- WebRTCIdentityStore* identity_store)
+ scoped_refptr<WebRTCIdentityStore> identity_store)
: renderer_process_id_(renderer_process_id),
- identity_store_(identity_store) {}
+ identity_store_(identity_store),
+ weak_factory_(this) {}
WebRTCIdentityServiceHost::~WebRTCIdentityServiceHost() {
if (!cancel_callback_.is_null())
@@ -60,7 +61,7 @@ void WebRTCIdentityServiceHost::OnRequestIdentity(
identity_name,
common_name,
base::Bind(&WebRTCIdentityServiceHost::OnComplete,
- base::Unretained(this),
+ weak_factory_.GetWeakPtr(),
sequence_number));
if (cancel_callback_.is_null()) {
SendErrorMessage(sequence_number, net::ERR_UNEXPECTED);
@@ -68,7 +69,10 @@ void WebRTCIdentityServiceHost::OnRequestIdentity(
}
void WebRTCIdentityServiceHost::OnCancelRequest() {
- base::ResetAndReturn(&cancel_callback_).Run();
+ // cancel_callback_ may be null if we have sent the reponse to the renderer
+ // but the renderer has not received it.
+ if (!cancel_callback_.is_null())
+ base::ResetAndReturn(&cancel_callback_).Run();
}
void WebRTCIdentityServiceHost::OnComplete(int sequence_number,
diff --git a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h
index 3a5921c5c2d..079e3077a65 100644
--- a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h
+++ b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h
@@ -26,8 +26,8 @@ class WebRTCIdentityStore;
// ERR_INSUFFICIENT_RESOURCES will be sent back to the renderer.
class CONTENT_EXPORT WebRTCIdentityServiceHost : public BrowserMessageFilter {
public:
- explicit WebRTCIdentityServiceHost(int renderer_process_id,
- WebRTCIdentityStore* identity_store);
+ WebRTCIdentityServiceHost(int renderer_process_id,
+ scoped_refptr<WebRTCIdentityStore> identity_store);
protected:
virtual ~WebRTCIdentityServiceHost();
@@ -60,7 +60,8 @@ class CONTENT_EXPORT WebRTCIdentityServiceHost : public BrowserMessageFilter {
int renderer_process_id_;
base::Closure cancel_callback_;
- WebRTCIdentityStore* identity_store_;
+ scoped_refptr<WebRTCIdentityStore> identity_store_;
+ base::WeakPtrFactory<WebRTCIdentityServiceHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityServiceHost);
};
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 cbedf512bc5..9e336d1db62 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
@@ -17,13 +17,12 @@ namespace content {
namespace {
-static const char FAKE_ORIGIN[] = "http://fake.com";
-static const char FAKE_IDENTITY_NAME[] = "fake identity";
-static const char FAKE_COMMON_NAME[] = "fake common name";
-static const char FAKE_CERTIFICATE[] = "fake cert";
-static const char FAKE_PRIVATE_KEY[] = "fake private key";
-static const int FAKE_ERROR = 100;
-static const int FAKE_RENDERER_ID = 10;
+const char FAKE_ORIGIN[] = "http://fake.com";
+const char FAKE_IDENTITY_NAME[] = "fake identity";
+const char FAKE_COMMON_NAME[] = "fake common name";
+const char FAKE_CERTIFICATE[] = "fake cert";
+const char FAKE_PRIVATE_KEY[] = "fake private key";
+const int FAKE_RENDERER_ID = 10;
const int FAKE_SEQUENCE_NUMBER = 1;
class MockWebRTCIdentityStore : public WebRTCIdentityStore {
@@ -189,4 +188,11 @@ TEST_F(WebRTCIdentityServiceHostTest, TestOriginAccessDenied) {
VerifyRequestFailedMessage(net::ERR_ACCESS_DENIED);
}
+// Verifies that we do not crash if we try to cancel a completed request.
+TEST_F(WebRTCIdentityServiceHostTest, TestCancelAfterRequestCompleted) {
+ SendRequestToHost();
+ store_->RunCompletionCallback(net::OK, FAKE_CERTIFICATE, FAKE_PRIVATE_KEY);
+ SendCancelRequestToHost();
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
index ad5f1f176eb..d2029180f54 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
@@ -30,7 +30,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent()
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(
- WebKit::WebInputEvent::Type type,
+ blink::WebInputEvent::Type type,
int modifiers, double time_secs, int keycode, int unicode_character,
bool is_system_key)
: WebKeyboardEvent(WebKeyboardEventBuilder::Build(
@@ -41,7 +41,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(
- jobject android_key_event, WebKit::WebInputEvent::Type type,
+ jobject android_key_event, blink::WebInputEvent::Type type,
int modifiers, double time_secs, int keycode, int unicode_character,
bool is_system_key)
: WebKeyboardEvent(WebKeyboardEventBuilder::Build(
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 ad3aae357cb..c33f12ffc74 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
@@ -15,20 +15,20 @@ namespace {
// RenderViewHostDelegate::HandledKeybardEvent after the original aura
// event is destroyed.
ui::Event* CopyEvent(ui::Event* event) {
- return event ? static_cast<ui::KeyEvent*>(event)->Copy() : NULL;
+ return event ? new ui::KeyEvent(*static_cast<ui::KeyEvent*>(event)) : NULL;
}
int EventFlagsToWebInputEventModifiers(int flags) {
return
- (flags & ui::EF_SHIFT_DOWN ? WebKit::WebInputEvent::ShiftKey : 0) |
- (flags & ui::EF_CONTROL_DOWN ? WebKit::WebInputEvent::ControlKey : 0) |
- (flags & ui::EF_CAPS_LOCK_DOWN ? WebKit::WebInputEvent::CapsLockOn : 0) |
- (flags & ui::EF_ALT_DOWN ? WebKit::WebInputEvent::AltKey : 0);
+ (flags & ui::EF_SHIFT_DOWN ? blink::WebInputEvent::ShiftKey : 0) |
+ (flags & ui::EF_CONTROL_DOWN ? blink::WebInputEvent::ControlKey : 0) |
+ (flags & ui::EF_CAPS_LOCK_DOWN ? blink::WebInputEvent::CapsLockOn : 0) |
+ (flags & ui::EF_ALT_DOWN ? blink::WebInputEvent::AltKey : 0);
}
} // namespace
-using WebKit::WebKeyboardEvent;
+using blink::WebKeyboardEvent;
namespace content {
@@ -61,11 +61,11 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(
skip_in_browser(false) {
switch (key_event_type) {
case ui::ET_KEY_PRESSED:
- type = is_char ? WebKit::WebInputEvent::Char :
- WebKit::WebInputEvent::RawKeyDown;
+ type = is_char ? blink::WebInputEvent::Char :
+ blink::WebInputEvent::RawKeyDown;
break;
case ui::ET_KEY_RELEASED:
- type = WebKit::WebInputEvent::KeyUp;
+ type = blink::WebInputEvent::KeyUp;
break;
default:
NOTREACHED();
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm b/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm
index 5b4f38ca11a..fea2939f2c1 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm
@@ -8,7 +8,7 @@
#include "third_party/WebKit/public/web/mac/WebInputEventFactory.h"
-using WebKit::WebInputEventFactory;
+using blink::WebInputEventFactory;
namespace content {
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_win.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_win.cc
index 42d3cce10fe..0f54a893c86 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_win.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_win.cc
@@ -6,7 +6,7 @@
#include "content/browser/renderer_host/input/web_input_event_builders_win.h"
-using WebKit::WebKeyboardEvent;
+using blink::WebKeyboardEvent;
namespace content {
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.cc b/chromium/content/browser/renderer_host/overscroll_controller.cc
index f07efab61f4..4c33aa8c20e 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller.cc
@@ -4,19 +4,27 @@
#include "content/browser/renderer_host/overscroll_controller.h"
+#include "base/command_line.h"
+#include "base/logging.h"
#include "content/browser/renderer_host/overscroll_controller_delegate.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/overscroll_configuration.h"
-#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/common/content_switches.h"
-using WebKit::WebInputEvent;
+using blink::WebInputEvent;
+
+namespace {
+
+bool IsScrollEndEffectEnabled() {
+ return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kScrollEndEffect) == "1";
+}
+
+} // namespace
namespace content {
-OverscrollController::OverscrollController(
- RenderWidgetHostImpl* render_widget_host)
- : render_widget_host_(render_widget_host),
- overscroll_mode_(OVERSCROLL_NONE),
+OverscrollController::OverscrollController()
+ : overscroll_mode_(OVERSCROLL_NONE),
scroll_state_(STATE_UNKNOWN),
overscroll_delta_x_(0.f),
overscroll_delta_y_(0.f),
@@ -26,30 +34,30 @@ OverscrollController::OverscrollController(
OverscrollController::~OverscrollController() {
}
-bool OverscrollController::WillDispatchEvent(
- const WebKit::WebInputEvent& event,
+OverscrollController::Disposition OverscrollController::DispatchEvent(
+ const blink::WebInputEvent& event,
const ui::LatencyInfo& latency_info) {
if (scroll_state_ != STATE_UNKNOWN) {
switch (event.type) {
- case WebKit::WebInputEvent::GestureScrollEnd:
- case WebKit::WebInputEvent::GestureFlingStart:
+ case blink::WebInputEvent::GestureScrollEnd:
+ case blink::WebInputEvent::GestureFlingStart:
scroll_state_ = STATE_UNKNOWN;
break;
- case WebKit::WebInputEvent::MouseWheel: {
- const WebKit::WebMouseWheelEvent& wheel =
- static_cast<const WebKit::WebMouseWheelEvent&>(event);
+ case blink::WebInputEvent::MouseWheel: {
+ const blink::WebMouseWheelEvent& wheel =
+ static_cast<const blink::WebMouseWheelEvent&>(event);
if (!wheel.hasPreciseScrollingDeltas ||
- wheel.phase == WebKit::WebMouseWheelEvent::PhaseEnded ||
- wheel.phase == WebKit::WebMouseWheelEvent::PhaseCancelled) {
+ wheel.phase == blink::WebMouseWheelEvent::PhaseEnded ||
+ wheel.phase == blink::WebMouseWheelEvent::PhaseCancelled) {
scroll_state_ = STATE_UNKNOWN;
}
break;
}
default:
- if (WebKit::WebInputEvent::isMouseEventType(event.type) ||
- WebKit::WebInputEvent::isKeyboardEventType(event.type)) {
+ if (blink::WebInputEvent::isMouseEventType(event.type) ||
+ blink::WebInputEvent::isKeyboardEventType(event.type)) {
scroll_state_ = STATE_UNKNOWN;
}
break;
@@ -64,53 +72,47 @@ bool OverscrollController::WillDispatchEvent(
// touch-scrolls maintain state in the renderer side (in the compositor, for
// example), and the event that completes this action needs to be sent to
// the renderer so that those states can be updated/reset appropriately.
- if (WebKit::WebInputEvent::isGestureEventType(event.type)) {
+ if (blink::WebInputEvent::isGestureEventType(event.type)) {
// A gesture-event isn't sent to the GestureEventFilter when overscroll is
// in progress. So dispatch the event through the RenderWidgetHost so that
// it can reach the GestureEventFilter.
- const WebKit::WebGestureEvent& gevent =
- static_cast<const WebKit::WebGestureEvent&>(event);
- return render_widget_host_->ShouldForwardGestureEvent(
- GestureEventWithLatencyInfo(gevent, latency_info));
+ return SHOULD_FORWARD_TO_GESTURE_FILTER;
}
- return true;
+ return SHOULD_FORWARD_TO_RENDERER;
}
if (overscroll_mode_ != OVERSCROLL_NONE && DispatchEventResetsState(event)) {
SetOverscrollMode(OVERSCROLL_NONE);
- if (WebKit::WebInputEvent::isGestureEventType(event.type)) {
+ if (blink::WebInputEvent::isGestureEventType(event.type)) {
// A gesture-event isn't sent to the GestureEventFilter when overscroll is
// in progress. So dispatch the event through the RenderWidgetHost so that
// it can reach the GestureEventFilter.
- const WebKit::WebGestureEvent& gevent =
- static_cast<const WebKit::WebGestureEvent&>(event);
- return render_widget_host_->ShouldForwardGestureEvent(
- GestureEventWithLatencyInfo(gevent, latency_info));
+ return SHOULD_FORWARD_TO_GESTURE_FILTER;
}
// Let the event be dispatched to the renderer.
- return true;
+ return SHOULD_FORWARD_TO_RENDERER;
}
if (overscroll_mode_ != OVERSCROLL_NONE) {
// Consume the event only if it updates the overscroll state.
if (ProcessEventForOverscroll(event))
- return false;
+ return CONSUMED;
}
- return true;
+ return SHOULD_FORWARD_TO_RENDERER;
}
-void OverscrollController::ReceivedEventACK(const WebKit::WebInputEvent& event,
+void OverscrollController::ReceivedEventACK(const blink::WebInputEvent& event,
bool processed) {
if (processed) {
// If a scroll event is consumed by the page, i.e. some content on the page
// has been scrolled, then there is not going to be an overscroll gesture,
// until the current scroll ends, and a new scroll gesture starts.
if (scroll_state_ == STATE_UNKNOWN &&
- (event.type == WebKit::WebInputEvent::MouseWheel ||
- event.type == WebKit::WebInputEvent::GestureScrollUpdate)) {
+ (event.type == blink::WebInputEvent::MouseWheel ||
+ event.type == blink::WebInputEvent::GestureScrollUpdate)) {
scroll_state_ = STATE_CONTENT_SCROLLING;
}
return;
@@ -119,10 +121,10 @@ void OverscrollController::ReceivedEventACK(const WebKit::WebInputEvent& event,
}
void OverscrollController::DiscardingGestureEvent(
- const WebKit::WebGestureEvent& gesture) {
+ const blink::WebGestureEvent& gesture) {
if (scroll_state_ != STATE_UNKNOWN &&
- (gesture.type == WebKit::WebInputEvent::GestureScrollEnd ||
- gesture.type == WebKit::WebInputEvent::GestureFlingStart)) {
+ (gesture.type == blink::WebInputEvent::GestureScrollEnd ||
+ gesture.type == blink::WebInputEvent::GestureFlingStart)) {
scroll_state_ = STATE_UNKNOWN;
}
}
@@ -140,29 +142,28 @@ void OverscrollController::Cancel() {
}
bool OverscrollController::DispatchEventCompletesAction (
- const WebKit::WebInputEvent& event) const {
+ const blink::WebInputEvent& event) const {
if (overscroll_mode_ == OVERSCROLL_NONE)
return false;
// Complete the overscroll gesture if there was a mouse move or a scroll-end
// after the threshold.
- if (event.type != WebKit::WebInputEvent::MouseMove &&
- event.type != WebKit::WebInputEvent::GestureScrollEnd &&
- event.type != WebKit::WebInputEvent::GestureFlingStart)
+ if (event.type != blink::WebInputEvent::MouseMove &&
+ event.type != blink::WebInputEvent::GestureScrollEnd &&
+ event.type != blink::WebInputEvent::GestureFlingStart)
return false;
- RenderWidgetHostView* view = render_widget_host_->GetView();
- if (!view->IsShowing())
+ if (!delegate_)
return false;
- const gfx::Rect& bounds = view->GetViewBounds();
+ gfx::Rect bounds = delegate_->GetVisibleBounds();
if (bounds.IsEmpty())
return false;
- if (event.type == WebKit::WebInputEvent::GestureFlingStart) {
+ if (event.type == blink::WebInputEvent::GestureFlingStart) {
// Check to see if the fling is in the same direction of the overscroll.
- const WebKit::WebGestureEvent gesture =
- static_cast<const WebKit::WebGestureEvent&>(event);
+ const blink::WebGestureEvent gesture =
+ static_cast<const blink::WebGestureEvent&>(event);
switch (overscroll_mode_) {
case OVERSCROLL_EAST:
if (gesture.data.flingStart.velocityX < 0)
@@ -200,34 +201,34 @@ bool OverscrollController::DispatchEventCompletesAction (
}
bool OverscrollController::DispatchEventResetsState(
- const WebKit::WebInputEvent& event) const {
+ const blink::WebInputEvent& event) const {
switch (event.type) {
- case WebKit::WebInputEvent::MouseWheel: {
+ case blink::WebInputEvent::MouseWheel: {
// Only wheel events with precise deltas (i.e. from trackpad) contribute
// to the overscroll gesture.
- const WebKit::WebMouseWheelEvent& wheel =
- static_cast<const WebKit::WebMouseWheelEvent&>(event);
+ const blink::WebMouseWheelEvent& wheel =
+ static_cast<const blink::WebMouseWheelEvent&>(event);
return !wheel.hasPreciseScrollingDeltas;
}
- case WebKit::WebInputEvent::GestureScrollUpdate:
- case WebKit::WebInputEvent::GestureFlingCancel:
+ case blink::WebInputEvent::GestureScrollUpdate:
+ case blink::WebInputEvent::GestureFlingCancel:
return false;
default:
// Touch events can arrive during an overscroll gesture initiated by
// touch-scrolling. These events should not reset the overscroll state.
- return !WebKit::WebInputEvent::isTouchEventType(event.type);
+ return !blink::WebInputEvent::isTouchEventType(event.type);
}
}
bool OverscrollController::ProcessEventForOverscroll(
- const WebKit::WebInputEvent& event) {
+ const blink::WebInputEvent& event) {
bool event_processed = false;
switch (event.type) {
- case WebKit::WebInputEvent::MouseWheel: {
- const WebKit::WebMouseWheelEvent& wheel =
- static_cast<const WebKit::WebMouseWheelEvent&>(event);
+ case blink::WebInputEvent::MouseWheel: {
+ const blink::WebMouseWheelEvent& wheel =
+ static_cast<const blink::WebMouseWheelEvent&>(event);
if (!wheel.hasPreciseScrollingDeltas)
break;
@@ -237,19 +238,19 @@ bool OverscrollController::ProcessEventForOverscroll(
event_processed = true;
break;
}
- case WebKit::WebInputEvent::GestureScrollUpdate: {
- const WebKit::WebGestureEvent& gesture =
- static_cast<const WebKit::WebGestureEvent&>(event);
+ case blink::WebInputEvent::GestureScrollUpdate: {
+ const blink::WebGestureEvent& gesture =
+ static_cast<const blink::WebGestureEvent&>(event);
ProcessOverscroll(gesture.data.scrollUpdate.deltaX,
gesture.data.scrollUpdate.deltaY,
gesture.type);
event_processed = true;
break;
}
- case WebKit::WebInputEvent::GestureFlingStart: {
+ case blink::WebInputEvent::GestureFlingStart: {
const float kFlingVelocityThreshold = 1100.f;
- const WebKit::WebGestureEvent& gesture =
- static_cast<const WebKit::WebGestureEvent&>(event);
+ const blink::WebGestureEvent& gesture =
+ static_cast<const blink::WebGestureEvent&>(event);
float velocity_x = gesture.data.flingStart.velocityX;
float velocity_y = gesture.data.flingStart.velocityY;
if (fabs(velocity_x) > kFlingVelocityThreshold) {
@@ -274,8 +275,8 @@ bool OverscrollController::ProcessEventForOverscroll(
}
default:
- DCHECK(WebKit::WebInputEvent::isGestureEventType(event.type) ||
- WebKit::WebInputEvent::isTouchEventType(event.type))
+ DCHECK(blink::WebInputEvent::isGestureEventType(event.type) ||
+ blink::WebInputEvent::isTouchEventType(event.type))
<< "Received unexpected event: " << event.type;
}
return event_processed;
@@ -283,7 +284,7 @@ bool OverscrollController::ProcessEventForOverscroll(
void OverscrollController::ProcessOverscroll(float delta_x,
float delta_y,
- WebKit::WebInputEvent::Type type) {
+ blink::WebInputEvent::Type type) {
if (scroll_state_ != STATE_CONTENT_SCROLLING)
overscroll_delta_x_ += delta_x;
overscroll_delta_y_ += delta_y;
@@ -312,6 +313,12 @@ void OverscrollController::ProcessOverscroll(float delta_x,
fabs(overscroll_delta_y_) > fabs(overscroll_delta_x_) * kMinRatio)
new_mode = overscroll_delta_y_ > 0.f ? OVERSCROLL_SOUTH : OVERSCROLL_NORTH;
+ // The vertical oversrcoll currently does not have any UX effects other then
+ // for the scroll end effect, so testing if it is enabled.
+ if ((new_mode == OVERSCROLL_SOUTH || new_mode == OVERSCROLL_NORTH) &&
+ !IsScrollEndEffectEnabled())
+ new_mode = OVERSCROLL_NONE;
+
if (overscroll_mode_ == OVERSCROLL_NONE)
SetOverscrollMode(new_mode);
else if (new_mode != overscroll_mode_)
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.h b/chromium/content/browser/renderer_host/overscroll_controller.h
index fab531947ee..c68eb9b1573 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller.h
@@ -17,7 +17,6 @@ namespace content {
class MockRenderWidgetHost;
class OverscrollControllerDelegate;
-class RenderWidgetHostImpl;
// Indicates the direction that the scroll is heading in relative to the screen,
// with the top being NORTH.
@@ -36,25 +35,29 @@ enum OverscrollMode {
// status accordingly.
class OverscrollController {
public:
- // Creates an overscroll controller for the specified RenderWidgetHost.
- // The RenderWidgetHost owns this overscroll controller.
- explicit OverscrollController(RenderWidgetHostImpl* widget_host);
+ OverscrollController();
virtual ~OverscrollController();
+ // The result of |DispatchEvent()|, indicating either how the event was
+ // handled, or how it should be handled by the caller.
+ enum Disposition {
+ CONSUMED,
+ SHOULD_FORWARD_TO_RENDERER,
+ SHOULD_FORWARD_TO_GESTURE_FILTER
+ };
// This must be called when dispatching any event from the
// RenderWidgetHostView so that the state of the overscroll gesture can be
// updated properly.
- // Returns true if the event should be dispatched, false otherwise.
- bool WillDispatchEvent(const WebKit::WebInputEvent& event,
- const ui::LatencyInfo& latency_info);
+ Disposition DispatchEvent(const blink::WebInputEvent& event,
+ const ui::LatencyInfo& latency_info);
// This must be called when the ACK for any event comes in. This updates the
// overscroll gesture status as appropriate.
- void ReceivedEventACK(const WebKit::WebInputEvent& event, bool processed);
+ void ReceivedEventACK(const blink::WebInputEvent& event, bool processed);
// This must be called when a gesture event is filtered out and not sent to
// the renderer.
- void DiscardingGestureEvent(const WebKit::WebGestureEvent& event);
+ void DiscardingGestureEvent(const blink::WebGestureEvent& event);
OverscrollMode overscroll_mode() const { return overscroll_mode_; }
@@ -83,22 +86,22 @@ class OverscrollController {
// Returns true if the event indicates that the in-progress overscroll gesture
// can now be completed.
bool DispatchEventCompletesAction(
- const WebKit::WebInputEvent& event) const;
+ const blink::WebInputEvent& event) const;
// Returns true to indicate that dispatching the event should reset the
// overscroll gesture status.
- bool DispatchEventResetsState(const WebKit::WebInputEvent& event) const;
+ bool DispatchEventResetsState(const blink::WebInputEvent& event) const;
// Processes an event to update the internal state for overscroll. Returns
// true if the state is updated, false otherwise.
- bool ProcessEventForOverscroll(const WebKit::WebInputEvent& event);
+ bool ProcessEventForOverscroll(const blink::WebInputEvent& event);
// Processes horizontal overscroll. This can update both the overscroll mode
// and the over scroll amount (i.e. |overscroll_mode_|, |overscroll_delta_x_|
// and |overscroll_delta_y_|).
void ProcessOverscroll(float delta_x,
float delta_y,
- WebKit::WebInputEvent::Type event_type);
+ blink::WebInputEvent::Type event_type);
// Completes the desired action from the current gesture.
void CompleteAction();
@@ -107,9 +110,6 @@ class OverscrollController {
// appropriate).
void SetOverscrollMode(OverscrollMode new_mode);
- // The RenderWidgetHost that owns this overscroll controller.
- RenderWidgetHostImpl* render_widget_host_;
-
// The current state of overscroll gesture.
OverscrollMode overscroll_mode_;
diff --git a/chromium/content/browser/renderer_host/overscroll_controller_delegate.h b/chromium/content/browser/renderer_host/overscroll_controller_delegate.h
index 6d40ed12095..59295ce4127 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller_delegate.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller_delegate.h
@@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "content/browser/renderer_host/overscroll_controller.h"
+#include "ui/gfx/rect.h"
namespace content {
@@ -18,6 +19,10 @@ class OverscrollControllerDelegate {
OverscrollControllerDelegate() {}
virtual ~OverscrollControllerDelegate() {}
+ // Get the bounds of the view corresponding to the delegate. Overscroll-ending
+ // events will only be processed if the visible bounds are non-empty.
+ virtual gfx::Rect GetVisibleBounds() const = 0;
+
// This is called for each update in the overscroll amount.
virtual void OnOverscrollUpdate(float delta_x, float delta_y) = 0;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index d1a60b451a8..1608ae0f40c 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -22,6 +22,8 @@ using content::BrowserThread;
namespace content {
+const size_t kMaximumPacketSize = 32768;
+
class P2PSocketDispatcherHost::DnsRequest {
public:
typedef base::Callback<void(const net::IPAddressNumber&)> DoneCallback;
@@ -94,8 +96,6 @@ P2PSocketDispatcherHost::P2PSocketDispatcherHost(
}
void P2PSocketDispatcherHost::OnChannelClosing() {
- BrowserMessageFilter::OnChannelClosing();
-
// Since the IPC channel is gone, close pending connections.
STLDeleteContainerPairSecondPointers(sockets_.begin(), sockets_.end());
sockets_.clear();
@@ -223,13 +223,25 @@ void P2PSocketDispatcherHost::OnAcceptIncomingTcpConnection(
void P2PSocketDispatcherHost::OnSend(int socket_id,
const net::IPEndPoint& socket_address,
- const std::vector<char>& data) {
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp,
+ uint64 packet_id) {
P2PSocketHost* socket = LookupSocket(socket_id);
if (!socket) {
LOG(ERROR) << "Received P2PHostMsg_Send for invalid socket_id.";
return;
}
- socket->Send(socket_address, data);
+
+ if (data.size() > kMaximumPacketSize) {
+ LOG(ERROR) << "Received P2PHostMsg_Send with a packet that is too big: "
+ << data.size();
+ Send(new P2PMsg_OnError(socket_id));
+ delete socket;
+ sockets_.erase(socket_id);
+ return;
+ }
+
+ socket->Send(socket_address, data, dscp, packet_id);
}
void P2PSocketDispatcherHost::OnDestroySocket(int socket_id) {
diff --git a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
index 2369eb2dbea..813da993b9a 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
@@ -6,11 +6,14 @@
#define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_DISPATCHER_HOST_H_
#include <map>
+#include <set>
+#include <string>
+#include <vector>
#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
-#include "content/common/p2p_sockets.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/p2p_socket_type.h"
#include "net/base/ip_endpoint.h"
#include "net/base/network_change_notifier.h"
@@ -68,7 +71,9 @@ class P2PSocketDispatcherHost
int connected_socket_id);
void OnSend(int socket_id,
const net::IPEndPoint& socket_address,
- const std::vector<char>& data);
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp,
+ uint64 packet_id);
void OnDestroySocket(int socket_id);
void DoGetNetworkList();
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.h b/chromium/content/browser/renderer_host/p2p/socket_host.h
index fa186c84b49..a11488451af 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.h
@@ -6,8 +6,9 @@
#define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_H_
#include "content/common/content_export.h"
-#include "content/common/p2p_sockets.h"
+#include "content/public/common/p2p_socket_type.h"
#include "net/base/ip_endpoint.h"
+#include "net/udp/datagram_socket.h"
namespace IPC {
class Sender;
@@ -38,7 +39,9 @@ class CONTENT_EXPORT P2PSocketHost {
// Sends |data| on the socket to |to|.
virtual void Send(const net::IPEndPoint& to,
- const std::vector<char>& data) = 0;
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp,
+ uint64 packet_id) = 0;
virtual P2PSocketHost* AcceptIncomingTcpConnection(
const net::IPEndPoint& remote_address, int id) = 0;
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 de9927a7168..e367e7f3b53 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -26,6 +26,8 @@ const int kPacketHeaderSize = sizeof(PacketLength);
const int kReadBufferSize = 4096;
const int kPacketLengthOffset = 2;
const int kTurnChannelDataHeaderSize = 4;
+const int kRecvSocketBufferSize = 128 * 1024;
+const int kSendSocketBufferSize = 128 * 1024;
bool IsTlsClientSocket(content::P2PSocketType type) {
return (type == content::P2P_SOCKET_STUN_TLS_CLIENT ||
@@ -198,6 +200,17 @@ void P2PSocketHostTcpBase::ProcessTlsSslConnectDone(int status) {
void P2PSocketHostTcpBase::OnOpen() {
state_ = STATE_OPEN;
+ // Setting socket send and receive buffer size.
+ if (!socket_->SetReceiveBufferSize(kRecvSocketBufferSize)) {
+ LOG(WARNING) << "Failed to set socket receive buffer size to "
+ << kRecvSocketBufferSize;
+ }
+
+ if (!socket_->SetSendBufferSize(kSendSocketBufferSize)) {
+ LOG(WARNING) << "Failed to set socket send buffer size to "
+ << kSendSocketBufferSize;
+ }
+
DoSendSocketCreateMsg();
DoRead();
}
@@ -268,11 +281,16 @@ void P2PSocketHostTcpBase::OnPacket(const std::vector<char>& data) {
}
}
- message_sender_->Send(new P2PMsg_OnDataReceived(id_, remote_address_, data));
+ message_sender_->Send(new P2PMsg_OnDataReceived(
+ id_, remote_address_, data, base::TimeTicks::Now()));
}
+// Note: dscp is not actually used on TCP sockets as this point,
+// but may be honored in the future.
void P2PSocketHostTcpBase::Send(const net::IPEndPoint& to,
- const std::vector<char>& data) {
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp,
+ uint64 packet_id) {
if (!socket_) {
// The Send message may be sent after the an OnError message was
// sent by hasn't been processed the renderer.
@@ -287,7 +305,7 @@ void P2PSocketHostTcpBase::Send(const net::IPEndPoint& to,
}
if (!connected_) {
- P2PSocketHost::StunMessageType type;
+ P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType();
bool stun = GetStunPacketType(&*data.begin(), data.size(), &type);
if (!stun || type == STUN_DATA_INDICATION) {
LOG(ERROR) << "Page tried to send a data packet to " << to.ToString()
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
index c0047a1c26a..b84efc7c282 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
@@ -13,7 +13,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "content/browser/renderer_host/p2p/socket_host.h"
-#include "content/common/p2p_sockets.h"
+#include "content/public/common/p2p_socket_type.h"
#include "net/base/completion_callback.h"
#include "net/base/ip_endpoint.h"
@@ -41,7 +41,9 @@ class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
virtual bool Init(const net::IPEndPoint& local_address,
const net::IPEndPoint& remote_address) OVERRIDE;
virtual void Send(const net::IPEndPoint& to,
- const std::vector<char>& data) OVERRIDE;
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp,
+ uint64 packet_id) OVERRIDE;
virtual P2PSocketHost* AcceptIncomingTcpConnection(
const net::IPEndPoint& remote_address, int id) OVERRIDE;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
index 146e5c81c52..fc6c7f6c729 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
@@ -115,7 +115,9 @@ void P2PSocketHostTcpServer::OnAccepted(int result) {
}
void P2PSocketHostTcpServer::Send(const net::IPEndPoint& to,
- const std::vector<char>& data) {
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp,
+ uint64 packet_id) {
NOTREACHED();
OnError();
}
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h
index c9aa8eb92b5..2581e83ee7e 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h
@@ -13,7 +13,7 @@
#include "base/message_loop/message_loop.h"
#include "content/browser/renderer_host/p2p/socket_host.h"
#include "content/common/content_export.h"
-#include "content/common/p2p_sockets.h"
+#include "content/public/common/p2p_socket_type.h"
#include "ipc/ipc_sender.h"
#include "net/base/completion_callback.h"
#include "net/socket/tcp_server_socket.h"
@@ -36,7 +36,9 @@ class CONTENT_EXPORT P2PSocketHostTcpServer : public P2PSocketHost {
virtual bool Init(const net::IPEndPoint& local_address,
const net::IPEndPoint& remote_address) OVERRIDE;
virtual void Send(const net::IPEndPoint& to,
- const std::vector<char>& data) OVERRIDE;
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp,
+ uint64 packet_id) OVERRIDE;
virtual P2PSocketHost* AcceptIncomingTcpConnection(
const net::IPEndPoint& remote_address, int id) OVERRIDE;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc
index 9eba7412236..39b864edb63 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc
@@ -4,6 +4,8 @@
#include "content/browser/renderer_host/p2p/socket_host_tcp_server.h"
+#include <list>
+
#include "content/browser/renderer_host/p2p/socket_host_tcp.h"
#include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
#include "net/base/completion_callback.h"
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
index 340c6b57a5e..cae88bd1c70 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
@@ -94,15 +94,15 @@ TEST_F(P2PSocketHostTcpTest, SendStunNoAuth) {
std::vector<char> packet1;
CreateStunRequest(&packet1);
- socket_host_->Send(dest_, packet1);
+ socket_host_->Send(dest_, packet1, net::DSCP_NO_CHANGE, 0);
std::vector<char> packet2;
CreateStunResponse(&packet2);
- socket_host_->Send(dest_, packet2);
+ socket_host_->Send(dest_, packet2, net::DSCP_NO_CHANGE, 0);
std::vector<char> packet3;
CreateStunError(&packet3);
- socket_host_->Send(dest_, packet3);
+ socket_host_->Send(dest_, packet3, net::DSCP_NO_CHANGE, 0);
std::string expected_data;
expected_data.append(IntToSize(packet1.size()));
@@ -125,15 +125,15 @@ TEST_F(P2PSocketHostTcpTest, ReceiveStun) {
std::vector<char> packet1;
CreateStunRequest(&packet1);
- socket_host_->Send(dest_, packet1);
+ socket_host_->Send(dest_, packet1, net::DSCP_NO_CHANGE, 0);
std::vector<char> packet2;
CreateStunResponse(&packet2);
- socket_host_->Send(dest_, packet2);
+ socket_host_->Send(dest_, packet2, net::DSCP_NO_CHANGE, 0);
std::vector<char> packet3;
CreateStunError(&packet3);
- socket_host_->Send(dest_, packet3);
+ socket_host_->Send(dest_, packet3, net::DSCP_NO_CHANGE, 0);
std::string received_data;
received_data.append(IntToSize(packet1.size()));
@@ -171,7 +171,7 @@ TEST_F(P2PSocketHostTcpTest, SendDataNoAuth) {
std::vector<char> packet;
CreateRandomPacket(&packet);
- socket_host_->Send(dest_, packet);
+ socket_host_->Send(dest_, packet, net::DSCP_NO_CHANGE, 0);
EXPECT_EQ(0U, sent_data_.size());
}
@@ -197,7 +197,7 @@ TEST_F(P2PSocketHostTcpTest, SendAfterStunRequest) {
// Now we should be able to send any data to |dest_|.
std::vector<char> packet;
CreateRandomPacket(&packet);
- socket_host_->Send(dest_, packet);
+ socket_host_->Send(dest_, packet, net::DSCP_NO_CHANGE, 0);
std::string expected_data;
expected_data.append(IntToSize(packet.size()));
@@ -219,11 +219,12 @@ TEST_F(P2PSocketHostTcpTest, AsyncWrites) {
std::vector<char> packet1;
CreateStunRequest(&packet1);
- socket_host_->Send(dest_, packet1);
+
+ socket_host_->Send(dest_, packet1, net::DSCP_NO_CHANGE, 0);
std::vector<char> packet2;
CreateStunResponse(&packet2);
- socket_host_->Send(dest_, packet2);
+ socket_host_->Send(dest_, packet2, net::DSCP_NO_CHANGE, 0);
message_loop.RunUntilIdle();
@@ -246,15 +247,15 @@ TEST_F(P2PSocketHostStunTcpTest, SendStunNoAuth) {
std::vector<char> packet1;
CreateStunRequest(&packet1);
- socket_host_->Send(dest_, packet1);
+ socket_host_->Send(dest_, packet1, net::DSCP_NO_CHANGE, 0);
std::vector<char> packet2;
CreateStunResponse(&packet2);
- socket_host_->Send(dest_, packet2);
+ socket_host_->Send(dest_, packet2, net::DSCP_NO_CHANGE, 0);
std::vector<char> packet3;
CreateStunError(&packet3);
- socket_host_->Send(dest_, packet3);
+ socket_host_->Send(dest_, packet3, net::DSCP_NO_CHANGE, 0);
std::string expected_data;
expected_data.append(packet1.begin(), packet1.end());
@@ -274,15 +275,15 @@ TEST_F(P2PSocketHostStunTcpTest, ReceiveStun) {
std::vector<char> packet1;
CreateStunRequest(&packet1);
- socket_host_->Send(dest_, packet1);
+ socket_host_->Send(dest_, packet1, net::DSCP_NO_CHANGE, 0);
std::vector<char> packet2;
CreateStunResponse(&packet2);
- socket_host_->Send(dest_, packet2);
+ socket_host_->Send(dest_, packet2, net::DSCP_NO_CHANGE, 0);
std::vector<char> packet3;
CreateStunError(&packet3);
- socket_host_->Send(dest_, packet3);
+ socket_host_->Send(dest_, packet3, net::DSCP_NO_CHANGE, 0);
std::string received_data;
received_data.append(packet1.begin(), packet1.end());
@@ -317,7 +318,7 @@ TEST_F(P2PSocketHostStunTcpTest, SendDataNoAuth) {
std::vector<char> packet;
CreateRandomPacket(&packet);
- socket_host_->Send(dest_, packet);
+ socket_host_->Send(dest_, packet, net::DSCP_NO_CHANGE, 0);
EXPECT_EQ(0U, sent_data_.size());
}
@@ -335,11 +336,11 @@ TEST_F(P2PSocketHostStunTcpTest, AsyncWrites) {
std::vector<char> packet1;
CreateStunRequest(&packet1);
- socket_host_->Send(dest_, packet1);
+ socket_host_->Send(dest_, packet1, net::DSCP_NO_CHANGE,0);
std::vector<char> packet2;
CreateStunResponse(&packet2);
- socket_host_->Send(dest_, packet2);
+ socket_host_->Send(dest_, packet2, net::DSCP_NO_CHANGE, 0);
message_loop.RunUntilIdle();
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
new file mode 100644
index 00000000000..67c461a6b97
--- /dev/null
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
@@ -0,0 +1,210 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
+
+#include "base/sys_byteorder.h"
+#include "base/thread_task_runner_handle.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+
+const int kStunHeaderSize = 20;
+const uint16 kStunBindingRequest = 0x0001;
+const uint16 kStunBindingResponse = 0x0102;
+const uint16 kStunBindingError = 0x0111;
+const uint32 kStunMagicCookie = 0x2112A442;
+
+MockIPCSender::MockIPCSender() { }
+MockIPCSender::~MockIPCSender() { }
+
+FakeSocket::FakeSocket(std::string* written_data)
+ : read_pending_(false),
+ input_pos_(0),
+ written_data_(written_data),
+ async_write_(false),
+ write_pending_(false) {
+}
+
+FakeSocket::~FakeSocket() { }
+
+void FakeSocket::AppendInputData(const char* data, int data_size) {
+ input_data_.insert(input_data_.end(), data, data + data_size);
+ // Complete pending read if any.
+ if (read_pending_) {
+ read_pending_ = false;
+ int result = std::min(read_buffer_size_,
+ static_cast<int>(input_data_.size() - input_pos_));
+ CHECK(result > 0);
+ memcpy(read_buffer_->data(), &input_data_[0] + input_pos_, result);
+ input_pos_ += result;
+ read_buffer_ = NULL;
+ net::CompletionCallback cb = read_callback_;
+ read_callback_.Reset();
+ cb.Run(result);
+ }
+}
+
+void FakeSocket::SetPeerAddress(const net::IPEndPoint& peer_address) {
+ peer_address_ = peer_address;
+}
+
+void FakeSocket::SetLocalAddress(const net::IPEndPoint& local_address) {
+ local_address_ = local_address;
+}
+
+int FakeSocket::Read(net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback) {
+ DCHECK(buf);
+ if (input_pos_ < static_cast<int>(input_data_.size())){
+ int result = std::min(buf_len,
+ static_cast<int>(input_data_.size()) - input_pos_);
+ memcpy(buf->data(), &(*input_data_.begin()) + input_pos_, result);
+ input_pos_ += result;
+ return result;
+ } else {
+ read_pending_ = true;
+ read_buffer_ = buf;
+ read_buffer_size_ = buf_len;
+ read_callback_ = callback;
+ return net::ERR_IO_PENDING;
+ }
+}
+
+int FakeSocket::Write(net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback) {
+ DCHECK(buf);
+ DCHECK(!write_pending_);
+
+ if (async_write_) {
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(
+ &FakeSocket::DoAsyncWrite, base::Unretained(this),
+ scoped_refptr<net::IOBuffer>(buf), buf_len, callback));
+ write_pending_ = true;
+ return net::ERR_IO_PENDING;
+ }
+
+ if (written_data_) {
+ written_data_->insert(written_data_->end(),
+ buf->data(), buf->data() + buf_len);
+ }
+ return buf_len;
+}
+
+void FakeSocket::DoAsyncWrite(scoped_refptr<net::IOBuffer> buf, int buf_len,
+ const net::CompletionCallback& callback) {
+ write_pending_ = false;
+
+ if (written_data_) {
+ written_data_->insert(written_data_->end(),
+ buf->data(), buf->data() + buf_len);
+ }
+ callback.Run(buf_len);
+}
+
+bool FakeSocket::SetReceiveBufferSize(int32 size) {
+ NOTIMPLEMENTED();
+ return false;
+}
+bool FakeSocket::SetSendBufferSize(int32 size) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+int FakeSocket::Connect(const net::CompletionCallback& callback) {
+ return 0;
+}
+
+void FakeSocket::Disconnect() {
+ NOTREACHED();
+}
+
+bool FakeSocket::IsConnected() const {
+ return true;
+}
+
+bool FakeSocket::IsConnectedAndIdle() const {
+ return false;
+}
+
+int FakeSocket::GetPeerAddress(net::IPEndPoint* address) const {
+ *address = peer_address_;
+ return net::OK;
+}
+
+int FakeSocket::GetLocalAddress(net::IPEndPoint* address) const {
+ *address = local_address_;
+ return net::OK;
+}
+
+const net::BoundNetLog& FakeSocket::NetLog() const {
+ NOTREACHED();
+ return net_log_;
+}
+
+void FakeSocket::SetSubresourceSpeculation() {
+ NOTREACHED();
+}
+
+void FakeSocket::SetOmniboxSpeculation() {
+ NOTREACHED();
+}
+
+bool FakeSocket::WasEverUsed() const {
+ return true;
+}
+
+bool FakeSocket::UsingTCPFastOpen() const {
+ return false;
+}
+
+bool FakeSocket::WasNpnNegotiated() const {
+ return false;
+}
+
+net::NextProto FakeSocket::GetNegotiatedProtocol() const {
+ return net::kProtoUnknown;
+}
+
+bool FakeSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
+ return false;
+}
+
+void CreateRandomPacket(std::vector<char>* packet) {
+ size_t size = kStunHeaderSize + rand() % 1000;
+ packet->resize(size);
+ for (size_t i = 0; i < size; i++) {
+ (*packet)[i] = rand() % 256;
+ }
+ // Always set the first bit to ensure that generated packet is not
+ // valid STUN packet.
+ (*packet)[0] = (*packet)[0] | 0x80;
+}
+
+static void CreateStunPacket(std::vector<char>* packet, uint16 type) {
+ CreateRandomPacket(packet);
+ *reinterpret_cast<uint16*>(&*packet->begin()) = base::HostToNet16(type);
+ *reinterpret_cast<uint16*>(&*packet->begin() + 2) =
+ base::HostToNet16(packet->size() - kStunHeaderSize);
+ *reinterpret_cast<uint32*>(&*packet->begin() + 4) =
+ base::HostToNet32(kStunMagicCookie);
+}
+
+void CreateStunRequest(std::vector<char>* packet) {
+ CreateStunPacket(packet, kStunBindingRequest);
+}
+
+void CreateStunResponse(std::vector<char>* packet) {
+ CreateStunPacket(packet, kStunBindingResponse);
+}
+
+void CreateStunError(std::vector<char>* packet) {
+ CreateStunPacket(packet, kStunBindingError);
+}
+
+net::IPEndPoint ParseAddress(const std::string ip_str, int port) {
+ net::IPAddressNumber ip;
+ EXPECT_TRUE(net::ParseIPLiteralToNumber(ip_str, &ip));
+ return net::IPEndPoint(ip, 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 77da0cdb792..86a93a81e50 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,35 +7,19 @@
#include <vector>
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/sys_byteorder.h"
-#include "base/thread_task_runner_handle.h"
#include "content/common/p2p_messages.h"
-#include "ipc/ipc_message_utils.h"
#include "ipc/ipc_sender.h"
-#include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
-#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/socket/stream_socket.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace {
-
const char kTestLocalIpAddress[] = "123.44.22.4";
const char kTestIpAddress1[] = "123.44.22.31";
const int kTestPort1 = 234;
const char kTestIpAddress2[] = "133.11.22.33";
const int kTestPort2 = 543;
-const int kStunHeaderSize = 20;
-const uint16 kStunBindingRequest = 0x0001;
-const uint16 kStunBindingResponse = 0x0102;
-const uint16 kStunBindingError = 0x0111;
-const uint32 kStunMagicCookie = 0x2112A442;
-
class MockIPCSender : public IPC::Sender {
public:
MockIPCSender();
@@ -44,9 +28,6 @@ class MockIPCSender : public IPC::Sender {
MOCK_METHOD1(Send, bool(IPC::Message* msg));
};
-MockIPCSender::MockIPCSender() { }
-MockIPCSender::~MockIPCSender() { }
-
class FakeSocket : public net::StreamSocket {
public:
FakeSocket(std::string* written_data);
@@ -103,196 +84,12 @@ class FakeSocket : public net::StreamSocket {
net::BoundNetLog net_log_;
};
-FakeSocket::FakeSocket(std::string* written_data)
- : read_pending_(false),
- input_pos_(0),
- written_data_(written_data),
- async_write_(false),
- write_pending_(false) {
-}
-
-FakeSocket::~FakeSocket() { }
-
-void FakeSocket::AppendInputData(const char* data, int data_size) {
- input_data_.insert(input_data_.end(), data, data + data_size);
- // Complete pending read if any.
- if (read_pending_) {
- read_pending_ = false;
- int result = std::min(read_buffer_size_,
- static_cast<int>(input_data_.size() - input_pos_));
- CHECK(result > 0);
- memcpy(read_buffer_->data(), &input_data_[0] + input_pos_, result);
- input_pos_ += result;
- read_buffer_ = NULL;
- net::CompletionCallback cb = read_callback_;
- read_callback_.Reset();
- cb.Run(result);
- }
-}
-
-void FakeSocket::SetPeerAddress(const net::IPEndPoint& peer_address) {
- peer_address_ = peer_address;
-}
-
-void FakeSocket::SetLocalAddress(const net::IPEndPoint& local_address) {
- local_address_ = local_address;
-}
-
-int FakeSocket::Read(net::IOBuffer* buf, int buf_len,
- const net::CompletionCallback& callback) {
- DCHECK(buf);
- if (input_pos_ < static_cast<int>(input_data_.size())){
- int result = std::min(buf_len,
- static_cast<int>(input_data_.size()) - input_pos_);
- memcpy(buf->data(), &(*input_data_.begin()) + input_pos_, result);
- input_pos_ += result;
- return result;
- } else {
- read_pending_ = true;
- read_buffer_ = buf;
- read_buffer_size_ = buf_len;
- read_callback_ = callback;
- return net::ERR_IO_PENDING;
- }
-}
-
-int FakeSocket::Write(net::IOBuffer* buf, int buf_len,
- const net::CompletionCallback& callback) {
- DCHECK(buf);
- DCHECK(!write_pending_);
-
- if (async_write_) {
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(
- &FakeSocket::DoAsyncWrite, base::Unretained(this),
- scoped_refptr<net::IOBuffer>(buf), buf_len, callback));
- write_pending_ = true;
- return net::ERR_IO_PENDING;
- }
-
- if (written_data_) {
- written_data_->insert(written_data_->end(),
- buf->data(), buf->data() + buf_len);
- }
- return buf_len;
-}
-
-void FakeSocket::DoAsyncWrite(scoped_refptr<net::IOBuffer> buf, int buf_len,
- const net::CompletionCallback& callback) {
- write_pending_ = false;
-
- if (written_data_) {
- written_data_->insert(written_data_->end(),
- buf->data(), buf->data() + buf_len);
- }
- callback.Run(buf_len);
-}
-
-bool FakeSocket::SetReceiveBufferSize(int32 size) {
- NOTIMPLEMENTED();
- return false;
-}
-bool FakeSocket::SetSendBufferSize(int32 size) {
- NOTIMPLEMENTED();
- return false;
-}
-
-int FakeSocket::Connect(const net::CompletionCallback& callback) {
- return 0;
-}
-
-void FakeSocket::Disconnect() {
- NOTREACHED();
-}
-
-bool FakeSocket::IsConnected() const {
- return true;
-}
-
-bool FakeSocket::IsConnectedAndIdle() const {
- return false;
-}
-
-int FakeSocket::GetPeerAddress(net::IPEndPoint* address) const {
- *address = peer_address_;
- return net::OK;
-}
-
-int FakeSocket::GetLocalAddress(net::IPEndPoint* address) const {
- *address = local_address_;
- return net::OK;
-}
-
-const net::BoundNetLog& FakeSocket::NetLog() const {
- NOTREACHED();
- return net_log_;
-}
-
-void FakeSocket::SetSubresourceSpeculation() {
- NOTREACHED();
-}
-
-void FakeSocket::SetOmniboxSpeculation() {
- NOTREACHED();
-}
-
-bool FakeSocket::WasEverUsed() const {
- return true;
-}
-
-bool FakeSocket::UsingTCPFastOpen() const {
- return false;
-}
-
-bool FakeSocket::WasNpnNegotiated() const {
- return false;
-}
-
-net::NextProto FakeSocket::GetNegotiatedProtocol() const {
- return net::kProtoUnknown;
-}
-
-bool FakeSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
- return false;
-}
-
-void CreateRandomPacket(std::vector<char>* packet) {
- size_t size = kStunHeaderSize + rand() % 1000;
- packet->resize(size);
- for (size_t i = 0; i < size; i++) {
- (*packet)[i] = rand() % 256;
- }
- // Always set the first bit to ensure that generated packet is not
- // valid STUN packet.
- (*packet)[0] = (*packet)[0] | 0x80;
-}
-
-void CreateStunPacket(std::vector<char>* packet, uint16 type) {
- CreateRandomPacket(packet);
- *reinterpret_cast<uint16*>(&*packet->begin()) = base::HostToNet16(type);
- *reinterpret_cast<uint16*>(&*packet->begin() + 2) =
- base::HostToNet16(packet->size() - kStunHeaderSize);
- *reinterpret_cast<uint32*>(&*packet->begin() + 4) =
- base::HostToNet32(kStunMagicCookie);
-}
-
-void CreateStunRequest(std::vector<char>* packet) {
- CreateStunPacket(packet, kStunBindingRequest);
-}
-
-void CreateStunResponse(std::vector<char>* packet) {
- CreateStunPacket(packet, kStunBindingResponse);
-}
-
-void CreateStunError(std::vector<char>* packet) {
- CreateStunPacket(packet, kStunBindingError);
-}
+void CreateRandomPacket(std::vector<char>* packet);
+void CreateStunRequest(std::vector<char>* packet);
+void CreateStunResponse(std::vector<char>* packet);
+void CreateStunError(std::vector<char>* packet);
-net::IPEndPoint ParseAddress(const std::string ip_str, int port) {
- net::IPAddressNumber ip;
- EXPECT_TRUE(net::ParseIPLiteralToNumber(ip_str, &ip));
- return net::IPEndPoint(ip, port);
-}
+net::IPEndPoint ParseAddress(const std::string ip_str, int port);
MATCHER_P(MatchMessage, type, "") {
return arg->type() == type;
@@ -315,6 +112,4 @@ MATCHER_P(MatchIncomingSocketMessage, address, "") {
return params.b == address;
}
-} // namespace
-
#endif // CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TEST_UTILS_H_
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc b/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
index 54c2b4cd4ed..8a14669a7ff 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
@@ -5,9 +5,12 @@
#include "content/browser/renderer_host/p2p/socket_host_udp.h"
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/debug/trace_event.h"
+#include "base/stl_util.h"
#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
#include "content/common/p2p_messages.h"
+#include "content/public/common/content_switches.h"
#include "ipc/ipc_sender.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
@@ -17,6 +20,8 @@ namespace {
// UDP packets cannot be bigger than 64k.
const int kReadBufferSize = 65536;
+// Socket receive buffer size.
+const int kRecvSocketBufferSize = 65536; // 64K
// Defines set of transient errors. These errors are ignored when we get them
// from sendto() or recvfrom() calls.
@@ -38,12 +43,9 @@ bool IsTransientError(int error) {
error == net::ERR_OUT_OF_MEMORY;
}
-uint64 GetUniqueEventId(const content::P2PSocketHostUdp* obj,
- uint64 packet_id) {
- uint64 uid = reinterpret_cast<uintptr_t>(obj);
- uid <<= 32;
- uid |= packet_id;
- return uid;
+bool AllowUDPWithoutSTUN() {
+ return CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableP2PSocketSTUNFilter);
}
} // namespace
@@ -51,10 +53,14 @@ uint64 GetUniqueEventId(const content::P2PSocketHostUdp* obj,
namespace content {
P2PSocketHostUdp::PendingPacket::PendingPacket(
- const net::IPEndPoint& to, const std::vector<char>& content, uint64 id)
+ const net::IPEndPoint& to,
+ const std::vector<char>& content,
+ net::DiffServCodePoint dscp_,
+ uint64 id)
: to(to),
data(new net::IOBuffer(content.size())),
size(content.size()),
+ dscp(dscp_),
id(id) {
memcpy(data->data(), &content[0], size);
}
@@ -68,7 +74,7 @@ P2PSocketHostUdp::P2PSocketHostUdp(IPC::Sender* message_sender,
: P2PSocketHost(message_sender, id),
socket_(new net::UDPServerSocket(NULL, net::NetLog::Source())),
send_pending_(false),
- send_packet_count_(0),
+ last_dscp_(net::DSCP_CS0),
throttler_(throttler) {
}
@@ -90,6 +96,12 @@ bool P2PSocketHostUdp::Init(const net::IPEndPoint& local_address,
return false;
}
+ // Setting recv socket buffer size.
+ if (!socket_->SetReceiveBufferSize(kRecvSocketBufferSize)) {
+ LOG(WARNING) << "Failed to set socket receive buffer size to "
+ << kRecvSocketBufferSize;
+ }
+
net::IPEndPoint address;
result = socket_->GetLocalAddress(&address);
if (result < 0) {
@@ -142,15 +154,15 @@ void P2PSocketHostUdp::OnRecv(int result) {
}
void P2PSocketHostUdp::HandleReadResult(int result) {
- DCHECK_EQ(state_, STATE_OPEN);
+ DCHECK_EQ(STATE_OPEN, state_);
if (result > 0) {
std::vector<char> data(recv_buffer_->data(), recv_buffer_->data() + result);
- if (connected_peers_.find(recv_address_) == connected_peers_.end()) {
+ if (!ContainsKey(connected_peers_, recv_address_)) {
P2PSocketHost::StunMessageType type;
bool stun = GetStunPacketType(&*data.begin(), data.size(), &type);
- if (stun && IsRequestOrResponse(type)) {
+ if ((stun && IsRequestOrResponse(type)) || AllowUDPWithoutSTUN()) {
connected_peers_.insert(recv_address_);
} else if (!stun || type == STUN_DATA_INDICATION) {
LOG(ERROR) << "Received unexpected data packet from "
@@ -160,7 +172,8 @@ void P2PSocketHostUdp::HandleReadResult(int result) {
}
}
- message_sender_->Send(new P2PMsg_OnDataReceived(id_, recv_address_, data));
+ message_sender_->Send(new P2PMsg_OnDataReceived(
+ id_, recv_address_, data, base::TimeTicks::Now()));
} else if (result < 0 && !IsTransientError(result)) {
LOG(ERROR) << "Error when reading from UDP socket: " << result;
OnError();
@@ -168,15 +181,17 @@ void P2PSocketHostUdp::HandleReadResult(int result) {
}
void P2PSocketHostUdp::Send(const net::IPEndPoint& to,
- const std::vector<char>& data) {
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp,
+ uint64 packet_id) {
if (!socket_) {
// The Send message may be sent after the an OnError message was
// sent by hasn't been processed the renderer.
return;
}
- if (connected_peers_.find(to) == connected_peers_.end()) {
- P2PSocketHost::StunMessageType type;
+ if (!ContainsKey(connected_peers_, to) && !AllowUDPWithoutSTUN()) {
+ P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType();
bool stun = GetStunPacketType(&*data.begin(), data.size(), &type);
if (!stun || type == STUN_DATA_INDICATION) {
LOG(ERROR) << "Page tried to send a data packet to " << to.ToString()
@@ -186,25 +201,39 @@ void P2PSocketHostUdp::Send(const net::IPEndPoint& to,
}
if (throttler_->DropNextPacket(data.size())) {
- LOG(INFO) << "STUN message is dropped due to high volume.";
+ VLOG(0) << "STUN message is dropped due to high volume.";
// Do not reset socket.
return;
}
}
if (send_pending_) {
- send_queue_.push_back(PendingPacket(to, data, send_packet_count_));
+ send_queue_.push_back(PendingPacket(to, data, dscp, packet_id));
} else {
- PendingPacket packet(to, data, send_packet_count_);
+ PendingPacket packet(to, data, dscp, packet_id);
DoSend(packet);
}
- ++send_packet_count_;
}
void P2PSocketHostUdp::DoSend(const PendingPacket& packet) {
- TRACE_EVENT_ASYNC_BEGIN1("p2p", "Udp::DoSend",
- GetUniqueEventId(this, packet.id),
- "size", packet.size);
+ TRACE_EVENT_ASYNC_STEP_INTO1("p2p", "Send", packet.id, "UdpAsyncSendTo",
+ "size", packet.size);
+ // Don't try to set DSCP in following conditions,
+ // 1. If the outgoing packet is set to DSCP_NO_CHANGE
+ // 2. If no change in DSCP value from last packet
+ // 3. If there is any error in setting DSCP on socket.
+ if (packet.dscp != net::DSCP_NO_CHANGE &&
+ last_dscp_ != packet.dscp && last_dscp_ != net::DSCP_NO_CHANGE) {
+ int result = socket_->SetDiffServCodePoint(packet.dscp);
+ if (result == net::OK) {
+ last_dscp_ = packet.dscp;
+ } else if (!IsTransientError(result) && last_dscp_ != net::DSCP_CS0) {
+ // We receieved a non-transient error, and it seems we have
+ // not changed the DSCP in the past, disable DSCP as it unlikely
+ // to work in the future.
+ last_dscp_ = net::DSCP_NO_CHANGE;
+ }
+ }
int result = socket_->SendTo(
packet.data.get(),
packet.size,
@@ -246,13 +275,12 @@ void P2PSocketHostUdp::OnSend(uint64 packet_id, int result) {
}
void P2PSocketHostUdp::HandleSendResult(uint64 packet_id, int result) {
- TRACE_EVENT_ASYNC_END1("p2p", "Udp::DoSend",
- GetUniqueEventId(this, packet_id),
+ TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id,
"result", result);
if (result > 0) {
message_sender_->Send(new P2PMsg_OnSendComplete(id_));
} else if (IsTransientError(result)) {
- LOG(INFO) << "sendto() has failed twice returning a "
+ VLOG(0) << "sendto() has failed twice returning a "
" transient error. Dropping the packet.";
} else if (result < 0) {
LOG(ERROR) << "Error when sending data in UDP socket: " << result;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
index befac2cae12..96b22444829 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
@@ -15,7 +15,7 @@
#include "base/message_loop/message_loop.h"
#include "content/browser/renderer_host/p2p/socket_host.h"
#include "content/common/content_export.h"
-#include "content/common/p2p_sockets.h"
+#include "content/public/common/p2p_socket_type.h"
#include "net/base/ip_endpoint.h"
#include "net/udp/udp_server_socket.h"
@@ -33,7 +33,9 @@ class CONTENT_EXPORT P2PSocketHostUdp : public P2PSocketHost {
virtual bool Init(const net::IPEndPoint& local_address,
const net::IPEndPoint& remote_address) OVERRIDE;
virtual void Send(const net::IPEndPoint& to,
- const std::vector<char>& data) OVERRIDE;
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp,
+ uint64 packet_id) OVERRIDE;
virtual P2PSocketHost* AcceptIncomingTcpConnection(
const net::IPEndPoint& remote_address, int id) OVERRIDE;
@@ -45,11 +47,13 @@ class CONTENT_EXPORT P2PSocketHostUdp : public P2PSocketHost {
struct PendingPacket {
PendingPacket(const net::IPEndPoint& to,
const std::vector<char>& content,
+ net::DiffServCodePoint dscp,
uint64 id);
~PendingPacket();
net::IPEndPoint to;
scoped_refptr<net::IOBuffer> data;
int size;
+ net::DiffServCodePoint dscp;
uint64 id;
};
@@ -69,7 +73,7 @@ class CONTENT_EXPORT P2PSocketHostUdp : public P2PSocketHost {
std::deque<PendingPacket> send_queue_;
bool send_pending_;
- uint64 send_packet_count_;
+ net::DiffServCodePoint last_dscp_;
// Set of peer for which we have received STUN binding request or
// response or relay allocation request or response.
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
index d42efbe3c35..3ccacfc2889 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
@@ -140,6 +140,11 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
return net::ERR_NOT_IMPLEMENTED;
}
+ virtual int SetMulticastInterface(uint32 interface_index) OVERRIDE {
+ NOTIMPLEMENTED();
+ return net::ERR_NOT_IMPLEMENTED;
+ }
+
virtual int SetMulticastTimeToLive(int time_to_live) OVERRIDE {
NOTIMPLEMENTED();
return net::ERR_NOT_IMPLEMENTED;
@@ -150,6 +155,11 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
return net::ERR_NOT_IMPLEMENTED;
}
+ virtual int SetDiffServCodePoint(net::DiffServCodePoint dscp) OVERRIDE {
+ NOTIMPLEMENTED();
+ return net::ERR_NOT_IMPLEMENTED;
+ }
+
private:
net::IPEndPoint address_;
std::deque<UDPPacket>* sent_packets_;
@@ -209,15 +219,15 @@ TEST_F(P2PSocketHostUdpTest, SendStunNoAuth) {
std::vector<char> packet1;
CreateStunRequest(&packet1);
- socket_host_->Send(dest1_, packet1);
+ socket_host_->Send(dest1_, packet1, net::DSCP_NO_CHANGE, 0);
std::vector<char> packet2;
CreateStunResponse(&packet2);
- socket_host_->Send(dest1_, packet2);
+ socket_host_->Send(dest1_, packet2, net::DSCP_NO_CHANGE, 0);
std::vector<char> packet3;
CreateStunError(&packet3);
- socket_host_->Send(dest1_, packet3);
+ socket_host_->Send(dest1_, packet3, net::DSCP_NO_CHANGE, 0);
ASSERT_EQ(sent_packets_.size(), 3U);
ASSERT_EQ(sent_packets_[0].second, packet1);
@@ -234,7 +244,7 @@ TEST_F(P2PSocketHostUdpTest, SendDataNoAuth) {
std::vector<char> packet;
CreateRandomPacket(&packet);
- socket_host_->Send(dest1_, packet);
+ socket_host_->Send(dest1_, packet, net::DSCP_NO_CHANGE, 0);
ASSERT_EQ(sent_packets_.size(), 0U);
}
@@ -256,7 +266,7 @@ TEST_F(P2PSocketHostUdpTest, SendAfterStunRequest) {
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
std::vector<char> packet;
CreateRandomPacket(&packet);
- socket_host_->Send(dest1_, packet);
+ socket_host_->Send(dest1_, packet, net::DSCP_NO_CHANGE, 0);
ASSERT_EQ(1U, sent_packets_.size());
ASSERT_EQ(dest1_, sent_packets_[0].first);
@@ -279,7 +289,7 @@ TEST_F(P2PSocketHostUdpTest, SendAfterStunResponse) {
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
std::vector<char> packet;
CreateRandomPacket(&packet);
- socket_host_->Send(dest1_, packet);
+ socket_host_->Send(dest1_, packet, net::DSCP_NO_CHANGE, 0);
ASSERT_EQ(1U, sent_packets_.size());
ASSERT_EQ(dest1_, sent_packets_[0].first);
@@ -302,7 +312,7 @@ TEST_F(P2PSocketHostUdpTest, SendAfterStunResponseDifferentHost) {
EXPECT_CALL(sender_, Send(
MatchMessage(static_cast<uint32>(P2PMsg_OnError::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- socket_host_->Send(dest2_, packet);
+ socket_host_->Send(dest2_, packet, net::DSCP_NO_CHANGE, 0);
}
// Verify throttler not allowing unlimited sending of ICE messages to
@@ -316,12 +326,12 @@ TEST_F(P2PSocketHostUdpTest, ThrottleAfterLimit) {
std::vector<char> packet1;
CreateStunRequest(&packet1);
throttler_.SetSendIceBandwidth(packet1.size() * 2);
- socket_host_->Send(dest1_, packet1);
- socket_host_->Send(dest2_, packet1);
+ socket_host_->Send(dest1_, packet1, net::DSCP_NO_CHANGE, 0);
+ socket_host_->Send(dest2_, packet1, net::DSCP_NO_CHANGE, 0);
net::IPEndPoint dest3 = ParseAddress(kTestIpAddress1, 2222);
// This packet must be dropped by the throttler.
- socket_host_->Send(dest3, packet1);
+ socket_host_->Send(dest3, packet1, net::DSCP_NO_CHANGE, 0);
ASSERT_EQ(sent_packets_.size(), 2U);
}
@@ -345,21 +355,21 @@ TEST_F(P2PSocketHostUdpTest, ThrottleAfterLimitAfterReceive) {
CreateStunRequest(&packet1);
throttler_.SetSendIceBandwidth(packet1.size());
// |dest1_| is known address, throttling will not be applied.
- socket_host_->Send(dest1_, packet1);
+ socket_host_->Send(dest1_, packet1, net::DSCP_NO_CHANGE, 0);
// Trying to send the packet to dest1_ in the same window. It should go.
- socket_host_->Send(dest1_, packet1);
+ socket_host_->Send(dest1_, packet1, net::DSCP_NO_CHANGE, 0);
// Throttler should allow this packet to go through.
- socket_host_->Send(dest2_, packet1);
+ socket_host_->Send(dest2_, packet1, net::DSCP_NO_CHANGE, 0);
net::IPEndPoint dest3 = ParseAddress(kTestIpAddress1, 2223);
// This packet will be dropped, as limit only for a single packet.
- socket_host_->Send(dest3, packet1);
+ socket_host_->Send(dest3, packet1, net::DSCP_NO_CHANGE, 0);
net::IPEndPoint dest4 = ParseAddress(kTestIpAddress1, 2224);
// This packet should also be dropped.
- socket_host_->Send(dest4, packet1);
+ socket_host_->Send(dest4, packet1, net::DSCP_NO_CHANGE, 0);
// |dest1| is known, we can send as many packets to it.
- socket_host_->Send(dest1_, packet1);
+ socket_host_->Send(dest1_, packet1, net::DSCP_NO_CHANGE, 0);
ASSERT_EQ(sent_packets_.size(), 4U);
}
diff --git a/chromium/content/browser/renderer_host/pepper/OWNERS b/chromium/content/browser/renderer_host/pepper/OWNERS
index 33d4c55751a..4523b30354e 100644
--- a/chromium/content/browser/renderer_host/pepper/OWNERS
+++ b/chromium/content/browser/renderer_host/pepper/OWNERS
@@ -1,4 +1,5 @@
bbudge@chromium.org
dmichael@chromium.org
raymes@chromium.org
+teravest@chromium.org
yzshen@chromium.org
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
index db3f8eff2ae..c3c2c6f3932 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
@@ -25,14 +25,16 @@ BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess(
// The plugin name and path shouldn't be needed for external plugins.
BrowserPpapiHostImpl* browser_ppapi_host =
new BrowserPpapiHostImpl(sender, permissions, std::string(),
- base::FilePath(), profile_directory, true);
+ base::FilePath(), profile_directory,
+ false /* in_process */,
+ true /* external_plugin */);
browser_ppapi_host->set_plugin_process_handle(plugin_child_process);
scoped_refptr<PepperMessageFilter> pepper_message_filter(
new PepperMessageFilter());
- channel->AddFilter(pepper_message_filter);
- channel->AddFilter(browser_ppapi_host->message_filter().get());
- channel->AddFilter(new TraceMessageFilter());
+ channel->AddFilter(pepper_message_filter->GetFilter());
+ channel->AddFilter(browser_ppapi_host->message_filter());
+ channel->AddFilter((new TraceMessageFilter())->GetFilter());
return browser_ppapi_host;
}
@@ -43,12 +45,14 @@ BrowserPpapiHostImpl::BrowserPpapiHostImpl(
const std::string& plugin_name,
const base::FilePath& plugin_path,
const base::FilePath& profile_data_directory,
+ bool in_process,
bool external_plugin)
: ppapi_host_(new ppapi::host::PpapiHost(sender, permissions)),
plugin_process_handle_(base::kNullProcessHandle),
plugin_name_(plugin_name),
plugin_path_(plugin_path),
profile_data_directory_(profile_data_directory),
+ in_process_(in_process),
external_plugin_(external_plugin),
ssl_context_helper_(new SSLContextHelper()) {
message_filter_ = new HostMessageFilter(ppapi_host_.get());
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
index f16d1d82c18..5d953422c1b 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
@@ -36,6 +36,7 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
const std::string& plugin_name,
const base::FilePath& plugin_path,
const base::FilePath& profile_data_directory,
+ bool in_process,
bool external_plugin);
virtual ~BrowserPpapiHostImpl();
@@ -56,7 +57,8 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
plugin_process_handle_ = handle;
}
- bool external_plugin() { return external_plugin_; }
+ bool in_process() const { return in_process_; }
+ bool external_plugin() const { return external_plugin_; }
// These two functions are notifications that an instance has been created
// or destroyed. They allow us to maintain a mapping of PP_Instance to data
@@ -100,6 +102,9 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
base::FilePath plugin_path_;
base::FilePath profile_data_directory_;
+ // If true, this refers to a plugin running in the renderer process.
+ bool in_process_;
+
// If true, this is an external plugin, i.e. created by the embedder using
// BrowserPpapiHost::CreateExternalPluginProcess.
bool external_plugin_;
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc
index c338a990f59..ecbcd0e120a 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_test.cc
@@ -16,7 +16,8 @@ BrowserPpapiHostTest::BrowserPpapiHostTest()
std::string(),
base::FilePath(),
base::FilePath(),
- false));
+ false /* in_process */,
+ false /* external_plugin */));
ppapi_host_->set_plugin_process_handle(base::GetCurrentProcessHandle());
}
diff --git a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
index 39e778dfe6b..afa539608af 100644
--- a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
+++ b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
@@ -6,6 +6,7 @@
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.h"
+#include "content/browser/renderer_host/pepper/pepper_file_io_host.h"
#include "content/browser/renderer_host/pepper/pepper_file_ref_host.h"
#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
#include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h"
@@ -67,6 +68,10 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
// Public interfaces.
switch (message.type()) {
+ case PpapiHostMsg_FileIO_Create::ID: {
+ return scoped_ptr<ResourceHost>(new PepperFileIOHost(
+ host_, instance, params.pp_resource()));
+ }
case PpapiHostMsg_FileSystem_Create::ID: {
PP_FileSystemType file_system_type;
if (!ppapi::UnpackMessage<PpapiHostMsg_FileSystem_Create>(message,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
index 096b908266f..4517e3725c0 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
@@ -100,6 +100,10 @@ fileapi::FileSystemURL PepperExternalFileRefBackend::GetFileSystemURL() const {
return fileapi::FileSystemURL();
}
+base::FilePath PepperExternalFileRefBackend::GetExternalFilePath() const {
+ return path_;
+}
+
int32_t PepperExternalFileRefBackend::CanRead() const {
if (!ChildProcessSecurityPolicyImpl::GetInstance()->
CanReadFile(render_process_id_, path_)) {
@@ -109,26 +113,18 @@ int32_t PepperExternalFileRefBackend::CanRead() const {
}
int32_t PepperExternalFileRefBackend::CanWrite() const {
- if (!ChildProcessSecurityPolicyImpl::GetInstance()->
- CanWriteFile(render_process_id_, path_)) {
- return PP_ERROR_NOACCESS;
- }
- return PP_OK;
+ // Platform files have coarse-grained grants in ChildProcessSecurityPolicy.
+ return CanReadWrite();
}
int32_t PepperExternalFileRefBackend::CanCreate() const {
- if (!ChildProcessSecurityPolicyImpl::GetInstance()->
- CanCreateFile(render_process_id_, path_)) {
- return PP_ERROR_NOACCESS;
- }
- return PP_OK;
+ // Platform files have coarse-grained grants in ChildProcessSecurityPolicy.
+ return CanReadWrite();
}
int32_t PepperExternalFileRefBackend::CanReadWrite() const {
- ChildProcessSecurityPolicyImpl* policy =
- ChildProcessSecurityPolicyImpl::GetInstance();
- if (!policy->CanReadFile(render_process_id_, path_) ||
- !policy->CanWriteFile(render_process_id_, path_)) {
+ if (!ChildProcessSecurityPolicyImpl::GetInstance()->
+ CanCreateReadWriteFile(render_process_id_, path_)) {
return PP_ERROR_NOACCESS;
}
return PP_OK;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h
index cbfaf6ed511..525749d7893 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h
@@ -41,6 +41,7 @@ class PepperExternalFileRefBackend : public PepperFileRefBackend {
virtual int32_t GetAbsolutePath(ppapi::host::ReplyMessageContext context)
OVERRIDE;
virtual fileapi::FileSystemURL GetFileSystemURL() const OVERRIDE;
+ virtual base::FilePath GetExternalFilePath() const OVERRIDE;
virtual int32_t CanRead() const OVERRIDE;
virtual int32_t CanWrite() const OVERRIDE;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
new file mode 100644
index 00000000000..66a0ad2ae40
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
@@ -0,0 +1,611 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/pepper_file_io_host.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/files/file_util_proxy.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/renderer_host/pepper/pepper_file_ref_host.h"
+#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
+#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
+#include "content/common/fileapi/file_system_messages.h"
+#include "content/common/sandbox_util.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/render_process_host.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_client.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_file_io.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/file_system_util.h"
+#include "ppapi/shared_impl/file_type_conversion.h"
+#include "ppapi/shared_impl/time_conversion.h"
+#include "webkit/browser/fileapi/file_observers.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_operation_runner.h"
+#include "webkit/browser/fileapi/task_runner_bound_observer_list.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+namespace content {
+
+using ppapi::FileIOStateManager;
+using ppapi::PPTimeToTime;
+
+namespace {
+
+int32_t ErrorOrByteNumber(int32_t pp_error, int32_t byte_number) {
+ // On the plugin side, some callbacks expect a parameter that means different
+ // things depending on whether it is negative or not. We translate for those
+ // callbacks here.
+ return pp_error == PP_OK ? byte_number : pp_error;
+}
+
+PepperFileIOHost::UIThreadStuff
+GetUIThreadStuffForInternalFileSystems(int render_process_id) {
+ PepperFileIOHost::UIThreadStuff stuff;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
+ if (host) {
+ stuff.resolved_render_process_id = base::GetProcId(host->GetHandle());
+ StoragePartition* storage_partition = host->GetStoragePartition();
+ if (storage_partition)
+ stuff.file_system_context = storage_partition->GetFileSystemContext();
+ }
+ return stuff;
+}
+
+base::ProcessId GetResolvedRenderProcessId(int render_process_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
+ if (!host)
+ return base::kNullProcessId;
+ return base::GetProcId(host->GetHandle());
+}
+
+bool GetPluginAllowedToCallRequestOSFileHandle(int render_process_id,
+ const GURL& document_url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ ContentBrowserClient* client = GetContentClient()->browser();
+ RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
+ return client->IsPluginAllowedToCallRequestOSFileHandle(
+ host->GetBrowserContext(), document_url);
+}
+
+} // namespace
+
+PepperFileIOHost::PepperFileIOHost(BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ PP_Resource resource)
+ : ResourceHost(host->GetPpapiHost(), instance, resource),
+ browser_ppapi_host_(host),
+ render_process_host_(NULL),
+ file_(base::kInvalidPlatformFileValue),
+ open_flags_(0),
+ file_system_type_(PP_FILESYSTEMTYPE_INVALID),
+ max_written_offset_(0),
+ check_quota_(false),
+ weak_factory_(this) {
+ int unused;
+ if (!host->GetRenderViewIDsForInstance(instance,
+ &render_process_id_,
+ &unused)) {
+ render_process_id_ = -1;
+ }
+ file_message_loop_ = BrowserThread::GetMessageLoopProxyForThread(
+ BrowserThread::FILE);
+}
+
+PepperFileIOHost::~PepperFileIOHost() {
+ OnHostMsgClose(NULL);
+}
+
+int32_t PepperFileIOHost::OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) {
+ IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open,
+ OnHostMsgOpen)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch,
+ OnHostMsgTouch)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Write,
+ OnHostMsgWrite)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength,
+ OnHostMsgSetLength)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Flush,
+ OnHostMsgFlush)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Close,
+ OnHostMsgClose)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_RequestOSFileHandle,
+ OnHostMsgRequestOSFileHandle)
+ IPC_END_MESSAGE_MAP()
+ return PP_ERROR_FAILED;
+}
+
+PepperFileIOHost::UIThreadStuff::UIThreadStuff() {
+ resolved_render_process_id = base::kNullProcessId;
+}
+
+PepperFileIOHost::UIThreadStuff::~UIThreadStuff() {
+}
+
+int32_t PepperFileIOHost::OnHostMsgOpen(
+ ppapi::host::HostMessageContext* context,
+ PP_Resource file_ref_resource,
+ int32_t open_flags) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, false);
+ if (rv != PP_OK)
+ return rv;
+
+ int platform_file_flags = 0;
+ if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags,
+ &platform_file_flags))
+ return PP_ERROR_BADARGUMENT;
+
+ ppapi::host::ResourceHost* resource_host =
+ host()->GetResourceHost(file_ref_resource);
+ if (!resource_host || !resource_host->IsFileRefHost())
+ return PP_ERROR_BADRESOURCE;
+ PepperFileRefHost* file_ref_host =
+ static_cast<PepperFileRefHost*>(resource_host);
+ if (file_ref_host->GetFileSystemType() == PP_FILESYSTEMTYPE_INVALID)
+ return PP_ERROR_FAILED;
+
+ file_system_host_ = file_ref_host->GetFileSystemHost();
+
+ open_flags_ = open_flags;
+ file_system_type_ = file_ref_host->GetFileSystemType();
+ file_system_url_ = file_ref_host->GetFileSystemURL();
+
+ if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
+ if (!file_system_url_.is_valid())
+ return PP_ERROR_BADARGUMENT;
+ if (!CanOpenFileSystemURLWithPepperFlags(open_flags,
+ render_process_id_,
+ file_system_url_))
+ return PP_ERROR_NOACCESS;
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&GetUIThreadStuffForInternalFileSystems,
+ render_process_id_),
+ base::Bind(&PepperFileIOHost::GotUIThreadStuffForInternalFileSystems,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext(),
+ platform_file_flags));
+ } else {
+ base::FilePath path = file_ref_host->GetExternalFilePath();
+ if (!CanOpenWithPepperFlags(open_flags, render_process_id_, path))
+ return PP_ERROR_NOACCESS;
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&GetResolvedRenderProcessId, render_process_id_),
+ base::Bind(&PepperFileIOHost::GotResolvedRenderProcessId,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext(),
+ path,
+ platform_file_flags));
+ }
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void PepperFileIOHost::GotUIThreadStuffForInternalFileSystems(
+ ppapi::host::ReplyMessageContext reply_context,
+ int platform_file_flags,
+ UIThreadStuff ui_thread_stuff) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ file_system_context_ = ui_thread_stuff.file_system_context;
+ resolved_render_process_id_ = ui_thread_stuff.resolved_render_process_id;
+ if (resolved_render_process_id_ == base::kNullProcessId ||
+ !file_system_context_.get()) {
+ reply_context.params.set_result(PP_ERROR_FAILED);
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply());
+ return;
+ }
+
+ if (!file_system_context_->GetFileSystemBackend(file_system_url_.type())) {
+ reply_context.params.set_result(PP_ERROR_FAILED);
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply());
+ return;
+ }
+
+ DCHECK(file_system_host_.get());
+ DCHECK(file_system_host_->GetFileSystemOperationRunner());
+ file_system_host_->GetFileSystemOperationRunner()->OpenFile(
+ file_system_url_,
+ platform_file_flags,
+ base::Bind(&PepperFileIOHost::DidOpenInternalFile,
+ weak_factory_.GetWeakPtr(),
+ reply_context));
+}
+
+void PepperFileIOHost::DidOpenInternalFile(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError result,
+ base::PlatformFile file,
+ const base::Closure& on_close_callback) {
+ if (result == base::PLATFORM_FILE_OK) {
+ on_close_callback_ = on_close_callback;
+
+ check_quota_ = file_system_host_ && file_system_host_->ChecksQuota();
+ if (check_quota_) {
+ file_system_host_->OpenQuotaFile(
+ this,
+ file_system_url_,
+ base::Bind(&PepperFileIOHost::DidOpenQuotaFile,
+ weak_factory_.GetWeakPtr(),
+ reply_context,
+ file));
+ return;
+ }
+ }
+
+ ExecutePlatformOpenFileCallback(
+ reply_context, result, base::PassPlatformFile(&file), true);
+}
+
+void PepperFileIOHost::GotResolvedRenderProcessId(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::FilePath path,
+ int platform_file_flags,
+ base::ProcessId resolved_render_process_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ resolved_render_process_id_ = resolved_render_process_id;
+ base::FileUtilProxy::CreateOrOpen(
+ file_message_loop_,
+ path,
+ platform_file_flags,
+ base::Bind(&PepperFileIOHost::ExecutePlatformOpenFileCallback,
+ weak_factory_.GetWeakPtr(),
+ reply_context));
+}
+
+int32_t PepperFileIOHost::OnHostMsgTouch(
+ ppapi::host::HostMessageContext* context,
+ PP_Time last_access_time,
+ PP_Time last_modified_time) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, true);
+ if (rv != PP_OK)
+ return rv;
+
+ if (!base::FileUtilProxy::Touch(
+ file_message_loop_,
+ file_,
+ PPTimeToTime(last_access_time),
+ PPTimeToTime(last_modified_time),
+ base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext())))
+ return PP_ERROR_FAILED;
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperFileIOHost::OnHostMsgWrite(
+ ppapi::host::HostMessageContext* context,
+ int64_t offset,
+ const std::string& buffer) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_WRITE, true);
+ if (rv != PP_OK)
+ return rv;
+ if (offset < 0)
+ return PP_ERROR_BADARGUMENT;
+
+ if (check_quota_) {
+ int64_t actual_offset =
+ (open_flags_ & PP_FILEOPENFLAG_APPEND) ? max_written_offset_ : offset;
+
+ uint64_t max_offset = actual_offset + buffer.size();
+ if (max_offset > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()))
+ return PP_ERROR_FAILED; // max_offset overflows.
+ int64_t amount = static_cast<int64_t>(max_offset) - max_written_offset_;
+
+ // Quota request amounts are restricted to 32 bits so we can use atomics
+ // when we move this code to the plugin side of the proxy.
+ if (amount > std::numeric_limits<int32_t>::max())
+ return PP_ERROR_NOQUOTA;
+
+ if (amount > 0) {
+ int32_t result = file_system_host_->RequestQuota(
+ static_cast<int32_t>(amount),
+ base::Bind(&PepperFileIOHost::GotWriteQuota,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext(),
+ offset, buffer));
+ if (result == PP_OK_COMPLETIONPENDING) {
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE);
+ return result;
+ }
+ // RequestQuota returns either PP_OK_COMPLETIONPENDING or the requested
+ // quota amount.
+ DCHECK(result > 0);
+ }
+ }
+
+ if (!CallWrite(context->MakeReplyMessageContext(), offset, buffer))
+ return PP_ERROR_FAILED;
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperFileIOHost::OnHostMsgSetLength(
+ ppapi::host::HostMessageContext* context,
+ int64_t length) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, true);
+ if (rv != PP_OK)
+ return rv;
+ if (length < 0)
+ return PP_ERROR_BADARGUMENT;
+
+ if (check_quota_) {
+ int64_t amount = length - max_written_offset_;
+ // Quota request amounts are restricted to 32 bits so we can use atomics
+ // when we move this code to the plugin side of the proxy.
+ if (amount > std::numeric_limits<int32_t>::max())
+ return PP_ERROR_NOQUOTA;
+
+ if (amount > 0) {
+ int32_t result = file_system_host_->RequestQuota(
+ static_cast<int32_t>(amount),
+ base::Bind(&PepperFileIOHost::GotSetLengthQuota,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext(),
+ length));
+ if (result == PP_OK_COMPLETIONPENDING) {
+ state_manager_.SetPendingOperation(
+ FileIOStateManager::OPERATION_EXCLUSIVE);
+ return result;
+ }
+ // RequestQuota returns either PP_OK_COMPLETIONPENDING or the requested
+ // quota amount.
+ DCHECK(result > 0);
+ }
+ }
+
+ if (!CallSetLength(context->MakeReplyMessageContext(), length))
+ return PP_ERROR_FAILED;
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperFileIOHost::OnHostMsgFlush(
+ ppapi::host::HostMessageContext* context) {
+ int32_t rv = state_manager_.CheckOperationState(
+ FileIOStateManager::OPERATION_EXCLUSIVE, true);
+ if (rv != PP_OK)
+ return rv;
+
+ if (!base::FileUtilProxy::Flush(
+ file_message_loop_,
+ file_,
+ base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext())))
+ return PP_ERROR_FAILED;
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperFileIOHost::OnHostMsgClose(
+ ppapi::host::HostMessageContext* context) {
+ if (check_quota_) {
+ file_system_host_->CloseQuotaFile(this);
+ check_quota_ = false;
+ }
+
+ if (file_ != base::kInvalidPlatformFileValue) {
+ base::FileUtilProxy::Close(
+ file_message_loop_,
+ file_,
+ base::Bind(&PepperFileIOHost::DidCloseFile,
+ weak_factory_.GetWeakPtr()));
+ file_ = base::kInvalidPlatformFileValue;
+ }
+ return PP_OK;
+}
+
+void PepperFileIOHost::DidOpenQuotaFile(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFile file,
+ int64_t max_written_offset) {
+ max_written_offset_ = max_written_offset;
+ DCHECK_LE(0, max_written_offset_);
+
+ ExecutePlatformOpenFileCallback(
+ reply_context, base::PLATFORM_FILE_OK, base::PassPlatformFile(&file),
+ true);
+}
+
+void PepperFileIOHost::GotWriteQuota(
+ ppapi::host::ReplyMessageContext reply_context,
+ int64_t offset,
+ const std::string& buffer,
+ int32_t granted) {
+ if (granted == 0) {
+ reply_context.params.set_result(PP_ERROR_NOQUOTA);
+ } else if (!CallWrite(reply_context, offset, buffer)) {
+ reply_context.params.set_result(PP_ERROR_FAILED);
+ } else {
+ max_written_offset_ += granted;
+ return;
+ }
+ // Return the error result set above.
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
+ state_manager_.SetOperationFinished();
+}
+
+void PepperFileIOHost::GotSetLengthQuota(
+ ppapi::host::ReplyMessageContext reply_context,
+ int64_t length,
+ int32_t granted) {
+ if (granted == 0) {
+ reply_context.params.set_result(PP_ERROR_NOQUOTA);
+ } else if (!CallSetLength(reply_context, length)) {
+ reply_context.params.set_result(PP_ERROR_FAILED);
+ } else {
+ max_written_offset_ += granted;
+ return;
+ }
+ // Return the error result set above.
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
+ state_manager_.SetOperationFinished();
+}
+
+bool PepperFileIOHost::CallWrite(
+ ppapi::host::ReplyMessageContext reply_context,
+ int64_t offset,
+ const std::string& buffer) {
+ return base::FileUtilProxy::Write(
+ file_message_loop_,
+ file_,
+ offset,
+ buffer.c_str(),
+ buffer.size(),
+ base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback,
+ weak_factory_.GetWeakPtr(),
+ reply_context));
+}
+
+bool PepperFileIOHost::CallSetLength(
+ ppapi::host::ReplyMessageContext reply_context,
+ int64_t length) {
+ return base::FileUtilProxy::Truncate(
+ file_message_loop_,
+ file_,
+ length,
+ base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
+ weak_factory_.GetWeakPtr(),
+ reply_context));
+}
+
+void PepperFileIOHost::DidCloseFile(base::PlatformFileError error) {
+ // Silently ignore if we fail to close the file.
+ if (!on_close_callback_.is_null()) {
+ on_close_callback_.Run();
+ on_close_callback_.Reset();
+ }
+}
+
+int32_t PepperFileIOHost::OnHostMsgRequestOSFileHandle(
+ ppapi::host::HostMessageContext* context) {
+ if (open_flags_ != PP_FILEOPENFLAG_READ && file_system_host_->ChecksQuota())
+ return PP_ERROR_FAILED;
+
+ GURL document_url =
+ browser_ppapi_host_->GetDocumentURLForInstance(pp_instance());
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&GetPluginAllowedToCallRequestOSFileHandle,
+ render_process_id_,
+ document_url),
+ base::Bind(&PepperFileIOHost::GotPluginAllowedToCallRequestOSFileHandle,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext()));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void PepperFileIOHost::GotPluginAllowedToCallRequestOSFileHandle(
+ ppapi::host::ReplyMessageContext reply_context,
+ bool plugin_allowed) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!browser_ppapi_host_->external_plugin() ||
+ host()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE) ||
+ plugin_allowed) {
+ if (!AddFileToReplyContext(open_flags_, &reply_context))
+ reply_context.params.set_result(PP_ERROR_FAILED);
+ } else {
+ reply_context.params.set_result(PP_ERROR_NOACCESS);
+ }
+ host()->SendReply(reply_context,
+ PpapiPluginMsg_FileIO_RequestOSFileHandleReply());
+}
+
+void PepperFileIOHost::ExecutePlatformGeneralCallback(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError error_code) {
+ reply_context.params.set_result(
+ ppapi::PlatformFileErrorToPepperError(error_code));
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
+ state_manager_.SetOperationFinished();
+}
+
+void PepperFileIOHost::ExecutePlatformOpenFileCallback(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError error_code,
+ base::PassPlatformFile file,
+ bool unused_created) {
+ int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
+ if (pp_error == PP_OK)
+ state_manager_.SetOpenSucceed();
+
+ DCHECK(file_ == base::kInvalidPlatformFileValue);
+ file_ = file.ReleaseValue();
+
+ if (file_ != base::kInvalidPlatformFileValue) {
+ int32_t flags_to_send = open_flags_;
+ if (!host()->permissions().HasPermission(ppapi::PERMISSION_DEV)) {
+ // IMPORTANT: Clear PP_FILEOPENFLAG_WRITE and PP_FILEOPENFLAG_APPEND so
+ // the plugin can't write and so bypass our quota checks.
+ flags_to_send =
+ open_flags_ & ~(PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_APPEND);
+ }
+ if (!AddFileToReplyContext(flags_to_send, &reply_context))
+ pp_error = PP_ERROR_FAILED;
+ }
+ reply_context.params.set_result(pp_error);
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply());
+ state_manager_.SetOperationFinished();
+}
+
+void PepperFileIOHost::ExecutePlatformWriteCallback(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError error_code,
+ int bytes_written) {
+ // On the plugin side, the callback expects a parameter with different meaning
+ // depends on whether is negative or not. It is the result here. We translate
+ // for the callback.
+ int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
+ reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written));
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
+ state_manager_.SetOperationFinished();
+}
+
+bool PepperFileIOHost::AddFileToReplyContext(
+ int32_t open_flags,
+ ppapi::host::ReplyMessageContext* reply_context) const {
+ base::ProcessId plugin_process_id;
+ if (browser_ppapi_host_->in_process()) {
+ plugin_process_id = resolved_render_process_id_;
+ } else {
+ plugin_process_id = base::GetProcId(
+ browser_ppapi_host_->GetPluginProcessHandle());
+ }
+ IPC::PlatformFileForTransit transit_file = BrokerGetFileHandleForProcess(
+ file_, plugin_process_id, false);
+ if (transit_file == IPC::InvalidPlatformFileForTransit())
+ return false;
+ ppapi::proxy::SerializedHandle file_handle;
+ file_handle.set_file_handle(transit_file, open_flags);
+ reply_context->params.AppendHandle(file_handle);
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h
new file mode 100644
index 00000000000..9394e6c7f28
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h
@@ -0,0 +1,165 @@
+// 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_PEPPER_PEPPER_FILE_IO_HOST_H_
+#define CONTENT_RENDERER_PEPPER_PEPPER_FILE_IO_HOST_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
+#include "ipc/ipc_listener.h"
+#include "ipc/ipc_platform_file.h"
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/pp_time.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/resource_host.h"
+#include "ppapi/shared_impl/file_io_state_manager.h"
+#include "url/gurl.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+
+namespace content {
+class PepperFileSystemBrowserHost;
+
+class PepperFileIOHost : public ppapi::host::ResourceHost,
+ public base::SupportsWeakPtr<PepperFileIOHost> {
+ public:
+ typedef base::Callback<void (base::PlatformFileError)>
+ NotifyCloseFileCallback;
+
+ PepperFileIOHost(BrowserPpapiHostImpl* host,
+ PP_Instance instance,
+ PP_Resource resource);
+ virtual ~PepperFileIOHost();
+
+ // ppapi::host::ResourceHost override.
+ virtual int32_t OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) OVERRIDE;
+
+ // Direct access for PepperFileSystemBrowserHost.
+ int64_t max_written_offset() const { return max_written_offset_; }
+ void set_max_written_offset(int64_t max_written_offset) {
+ max_written_offset_ = max_written_offset;
+ }
+
+ struct UIThreadStuff {
+ UIThreadStuff();
+ ~UIThreadStuff();
+ base::ProcessId resolved_render_process_id;
+ scoped_refptr<fileapi::FileSystemContext> file_system_context;
+ };
+ private:
+ int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
+ PP_Resource file_ref_resource,
+ int32_t open_flags);
+ int32_t OnHostMsgTouch(ppapi::host::HostMessageContext* context,
+ PP_Time last_access_time,
+ PP_Time last_modified_time);
+ int32_t OnHostMsgWrite(ppapi::host::HostMessageContext* context,
+ int64_t offset,
+ const std::string& buffer);
+ int32_t OnHostMsgSetLength(ppapi::host::HostMessageContext* context,
+ int64_t length);
+ int32_t OnHostMsgClose(ppapi::host::HostMessageContext* context);
+ int32_t OnHostMsgFlush(ppapi::host::HostMessageContext* context);
+ int32_t OnHostMsgRequestOSFileHandle(
+ ppapi::host::HostMessageContext* context);
+
+ void GotPluginAllowedToCallRequestOSFileHandle(
+ ppapi::host::ReplyMessageContext reply_context,
+ bool plugin_allowed);
+
+ // Callback handlers. These mostly convert the PlatformFileError to the
+ // PP_Error code and send back the reply. Note that the argument
+ // ReplyMessageContext is copied so that we have a closure containing all
+ // necessary information to reply.
+ void ExecutePlatformGeneralCallback(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError error_code);
+ void ExecutePlatformOpenFileCallback(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError error_code,
+ base::PassPlatformFile file,
+ bool unused_created);
+ void ExecutePlatformWriteCallback(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError error_code,
+ int bytes_written);
+
+ void GotUIThreadStuffForInternalFileSystems(
+ ppapi::host::ReplyMessageContext reply_context,
+ int platform_file_flags,
+ UIThreadStuff ui_thread_stuff);
+ void DidOpenInternalFile(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFileError result,
+ base::PlatformFile file,
+ const base::Closure& on_close_callback);
+ void GotResolvedRenderProcessId(
+ ppapi::host::ReplyMessageContext reply_context,
+ base::FilePath path,
+ int platform_file_flags,
+ base::ProcessId resolved_render_process_id);
+
+ void DidOpenQuotaFile(ppapi::host::ReplyMessageContext reply_context,
+ base::PlatformFile file,
+ int64_t max_written_offset);
+ void GotWriteQuota(ppapi::host::ReplyMessageContext reply_context,
+ int64_t offset,
+ const std::string& buffer,
+ int32_t granted);
+ void GotSetLengthQuota(ppapi::host::ReplyMessageContext reply_context,
+ int64_t length,
+ int32_t granted);
+ bool CallWrite(ppapi::host::ReplyMessageContext reply_context,
+ int64_t offset,
+ const std::string& buffer);
+ bool CallSetLength(ppapi::host::ReplyMessageContext reply_context,
+ int64_t length);
+
+ void DidCloseFile(base::PlatformFileError error);
+
+ // Adds file_ to |reply_context| with the specified |open_flags|.
+ bool AddFileToReplyContext(
+ int32_t open_flags,
+ ppapi::host::ReplyMessageContext* reply_context) const;
+
+ BrowserPpapiHostImpl* browser_ppapi_host_;
+
+ RenderProcessHost* render_process_host_;
+ int render_process_id_;
+ base::ProcessId resolved_render_process_id_;
+
+ base::PlatformFile file_;
+ int32_t open_flags_;
+
+ // The file system type specified in the Open() call. This will be
+ // PP_FILESYSTEMTYPE_INVALID before open was called. This value does not
+ // indicate that the open command actually succeeded.
+ PP_FileSystemType file_system_type_;
+ base::WeakPtr<PepperFileSystemBrowserHost> file_system_host_;
+
+ // Valid only for PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY}.
+ scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ fileapi::FileSystemURL file_system_url_;
+ base::Closure on_close_callback_;
+ int64_t max_written_offset_;
+ bool check_quota_;
+
+ ppapi::FileIOStateManager state_manager_;
+
+ scoped_refptr<base::MessageLoopProxy> file_message_loop_;
+
+ base::WeakPtrFactory<PepperFileIOHost> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperFileIOHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_PEPPER_PEPPER_FILE_IO_HOST_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
index c38f8826534..75350a03632 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
@@ -53,15 +53,15 @@ PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host,
return;
}
- PepperFileSystemBrowserHost* fs_host = NULL;
- if (fs_resource_host->IsFileSystemHost())
- fs_host = static_cast<PepperFileSystemBrowserHost*>(fs_resource_host);
- if (fs_host == NULL) {
+ if (!fs_resource_host->IsFileSystemHost()) {
DLOG(ERROR) << "Filesystem PP_Resource is not PepperFileSystemBrowserHost";
return;
}
- fs_type_ = fs_host->GetType();
+ PepperFileSystemBrowserHost* file_system_host =
+ static_cast<PepperFileSystemBrowserHost*>(fs_resource_host);
+ file_system_host_ = file_system_host->AsWeakPtr();
+ fs_type_ = file_system_host->GetType();
if ((fs_type_ != PP_FILESYSTEMTYPE_LOCALPERSISTENT) &&
(fs_type_ != PP_FILESYSTEMTYPE_LOCALTEMPORARY) &&
(fs_type_ != PP_FILESYSTEMTYPE_ISOLATED)) {
@@ -72,7 +72,7 @@ PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host,
backend_.reset(new PepperInternalFileRefBackend(
host->GetPpapiHost(),
render_process_id,
- base::AsWeakPtr(fs_host),
+ file_system_host->AsWeakPtr(),
path));
}
@@ -116,6 +116,17 @@ fileapi::FileSystemURL PepperFileRefHost::GetFileSystemURL() const {
return fileapi::FileSystemURL();
}
+base::FilePath PepperFileRefHost::GetExternalFilePath() const {
+ if (backend_)
+ return backend_->GetExternalFilePath();
+ return base::FilePath();
+}
+
+base::WeakPtr<PepperFileSystemBrowserHost>
+PepperFileRefHost::GetFileSystemHost() const {
+ return file_system_host_;
+}
+
int32_t PepperFileRefHost::CanRead() const {
if (backend_)
return backend_->CanRead();
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h
index b97ff331ac0..10d9a3ee76e 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h
@@ -18,8 +18,8 @@
#include "webkit/browser/fileapi/file_system_url.h"
namespace content {
-
class PepperFileRefHost;
+class PepperFileSystemBrowserHost;
// Internal and external filesystems have very different codepaths for
// performing FileRef operations. The logic is split into separate classes
@@ -42,6 +42,7 @@ class PepperFileRefBackend {
virtual int32_t GetAbsolutePath(
ppapi::host::ReplyMessageContext context) = 0;
virtual fileapi::FileSystemURL GetFileSystemURL() const = 0;
+ virtual base::FilePath GetExternalFilePath() const = 0;
// Returns an error from the pp_errors.h enum.
virtual int32_t CanRead() const = 0;
@@ -77,6 +78,10 @@ class CONTENT_EXPORT PepperFileRefHost
PP_FileSystemType GetFileSystemType() const;
fileapi::FileSystemURL GetFileSystemURL() const;
+ // Required to support FileIO.
+ base::FilePath GetExternalFilePath() const;
+ base::WeakPtr<PepperFileSystemBrowserHost> GetFileSystemHost() const;
+
int32_t CanRead() const;
int32_t CanWrite() const;
int32_t CanCreate() const;
@@ -97,6 +102,7 @@ class CONTENT_EXPORT PepperFileRefHost
BrowserPpapiHost* host_;
scoped_ptr<PepperFileRefBackend> backend_;
+ base::WeakPtr<PepperFileSystemBrowserHost> file_system_host_;
PP_FileSystemType fs_type_;
DISALLOW_COPY_AND_ASSIGN(PepperFileRefHost);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
index fce371d8f99..740e9b861f8 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
@@ -6,45 +6,41 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "content/browser/renderer_host/pepper/pepper_file_io_host.h"
+#include "content/browser/renderer_host/pepper/quota_reservation.h"
#include "content/public/browser/browser_ppapi_host.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/common/pepper_plugin_info.h"
+#include "net/base/mime_util.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/file_system_util.h"
#include "ppapi/shared_impl/file_type_conversion.h"
-#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_operation_runner.h"
+#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/quota/quota_manager.h"
#include "webkit/common/fileapi/file_system_util.h"
+#include "webkit/common/quota/quota_types.h"
namespace content {
namespace {
-// TODO(teravest): Move this function to be shared and public in fileapi.
-bool LooksLikeAGuid(const std::string& fsid) {
- const size_t kExpectedFsIdSize = 32;
- if (fsid.size() != kExpectedFsIdSize)
- return false;
- for (std::string::const_iterator it = fsid.begin(); it != fsid.end(); ++it) {
- if (('A' <= *it && *it <= 'F') || ('0' <= *it && *it <= '9'))
- continue;
- return false;
- }
- return true;
-}
+// This is the minimum amount of quota we reserve per file system.
+const int64_t kMinimumQuotaReservationSize = 1024 * 1024; // 1 MB
scoped_refptr<fileapi::FileSystemContext>
GetFileSystemContextFromRenderId(int render_process_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RenderProcessHost* render_process_host =
- RenderProcessHost::FromID(render_process_id);
- if (!render_process_host)
+ RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
+ if (!host)
return NULL;
- StoragePartition* storage_partition =
- render_process_host->GetStoragePartition();
+ StoragePartition* storage_partition = host->GetStoragePartition();
if (!storage_partition)
return NULL;
return storage_partition->GetFileSystemContext();
@@ -52,6 +48,16 @@ GetFileSystemContextFromRenderId(int render_process_id) {
} // namespace
+PepperFileSystemBrowserHost::QuotaRequest::QuotaRequest(
+ int32_t amount_arg,
+ const RequestQuotaCallback& callback_arg)
+ : amount(amount_arg),
+ callback(callback_arg) {
+}
+
+PepperFileSystemBrowserHost::QuotaRequest::~QuotaRequest() {
+}
+
PepperFileSystemBrowserHost::PepperFileSystemBrowserHost(BrowserPpapiHost* host,
PP_Instance instance,
PP_Resource resource,
@@ -59,16 +65,39 @@ PepperFileSystemBrowserHost::PepperFileSystemBrowserHost(BrowserPpapiHost* host,
: ResourceHost(host->GetPpapiHost(), instance, resource),
browser_ppapi_host_(host),
type_(type),
- opened_(false),
- fs_context_(NULL),
called_open_(false),
+ opened_(false),
+ file_system_context_(NULL),
+ reserved_quota_(0),
+ reserving_quota_(false),
weak_factory_(this) {
}
PepperFileSystemBrowserHost::~PepperFileSystemBrowserHost() {
- // TODO(teravest): Create a FileSystemOperationRunner
- // per-PepperFileSystemBrowserHost, force users of this FileSystem to use it,
- // and call Shutdown() on it here.
+ // All FileRefs and FileIOs that reference us must have been destroyed. Cancel
+ // all pending file system operations.
+ if (file_system_operation_runner_)
+ file_system_operation_runner_->Shutdown();
+}
+
+void PepperFileSystemBrowserHost::OpenExisting(const GURL& root_url,
+ const base::Closure& callback) {
+ root_url_ = root_url;
+ int render_process_id = 0;
+ int unused;
+ if (!browser_ppapi_host_->GetRenderViewIDsForInstance(
+ pp_instance(), &render_process_id, &unused)) {
+ NOTREACHED();
+ }
+ called_open_ = true;
+ // Get the file system context asynchronously, and then complete the Open
+ // operation by calling |callback|.
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
+ base::Bind(&PepperFileSystemBrowserHost::OpenExistingFileSystem,
+ weak_factory_.GetWeakPtr(), callback));
}
int32_t PepperFileSystemBrowserHost::OnResourceMessageReceived(
@@ -89,6 +118,67 @@ bool PepperFileSystemBrowserHost::IsFileSystemHost() {
return true;
}
+void PepperFileSystemBrowserHost::OpenQuotaFile(
+ PepperFileIOHost* file_io_host,
+ const fileapi::FileSystemURL& url,
+ const OpenQuotaFileCallback& callback) {
+ int32_t id = file_io_host->pp_resource();
+ std::pair<FileMap::iterator, bool> insert_result =
+ files_.insert(std::make_pair(id, file_io_host));
+ if (insert_result.second) {
+ base::PostTaskAndReplyWithResult(
+ file_system_context_->default_file_task_runner(),
+ FROM_HERE,
+ base::Bind(&QuotaReservation::OpenFile,
+ quota_reservation_,
+ id,
+ url),
+ callback);
+ } else {
+ NOTREACHED();
+ }
+}
+
+void PepperFileSystemBrowserHost::CloseQuotaFile(
+ PepperFileIOHost* file_io_host) {
+ int32_t id = file_io_host->pp_resource();
+ int64_t max_written_offset = 0;
+ FileMap::iterator it = files_.find(id);
+ if (it != files_.end()) {
+ max_written_offset = file_io_host->max_written_offset();
+ files_.erase(it);
+ } else {
+ NOTREACHED();
+ return;
+ }
+
+ file_system_context_->default_file_task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&QuotaReservation::CloseFile,
+ quota_reservation_,
+ id,
+ max_written_offset));
+}
+
+int32_t PepperFileSystemBrowserHost::RequestQuota(
+ int32_t amount,
+ const RequestQuotaCallback& callback) {
+ DCHECK(amount >= 0);
+ if (!reserving_quota_ && reserved_quota_ >= amount) {
+ reserved_quota_ -= amount;
+ return amount;
+ }
+
+ // Queue up a pending quota request.
+ pending_quota_requests_.push(QuotaRequest(amount, callback));
+
+ // Reserve more quota if we haven't already.
+ if (!reserving_quota_)
+ ReserveQuota(amount);
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
int32_t PepperFileSystemBrowserHost::OnHostMsgOpen(
ppapi::host::HostMessageContext* context,
int64_t /* unused */) {
@@ -100,20 +190,10 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgOpen(
return PP_ERROR_INPROGRESS;
called_open_ = true;
- fileapi::FileSystemType file_system_type;
- switch (type_) {
- case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
- file_system_type = fileapi::kFileSystemTypeTemporary;
- break;
- case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
- file_system_type = fileapi::kFileSystemTypePersistent;
- break;
- case PP_FILESYSTEMTYPE_EXTERNAL:
- file_system_type = fileapi::kFileSystemTypeExternal;
- break;
- default:
- return PP_ERROR_FAILED;
- }
+ fileapi::FileSystemType file_system_type =
+ ppapi::PepperFileSystemTypeToFileSystemType(type_);
+ if (file_system_type == fileapi::kFileSystemTypeUnknown)
+ return PP_ERROR_FAILED;
int render_process_id = 0;
int unused;
@@ -122,90 +202,348 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgOpen(
&unused)) {
return PP_ERROR_FAILED;
}
+
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::UI,
FROM_HERE,
base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
- base::Bind(&PepperFileSystemBrowserHost::GotFileSystemContext,
+ base::Bind(&PepperFileSystemBrowserHost::OpenFileSystem,
weak_factory_.GetWeakPtr(),
context->MakeReplyMessageContext(),
file_system_type));
return PP_OK_COMPLETIONPENDING;
}
-void PepperFileSystemBrowserHost::GotFileSystemContext(
+void PepperFileSystemBrowserHost::OpenExistingFileSystem(
+ const base::Closure& callback,
+ scoped_refptr<fileapi::FileSystemContext> file_system_context) {
+ if (file_system_context.get()) {
+ opened_ = true;
+ } else {
+ // If there is no file system context, we log a warning and continue with an
+ // invalid resource (which will produce errors when used), since we have no
+ // way to communicate the error to the caller.
+ LOG(WARNING) << "Could not retrieve file system context.";
+ }
+ SetFileSystemContext(file_system_context);
+
+ if (ShouldCreateQuotaReservation())
+ CreateQuotaReservation(callback);
+ else
+ callback.Run();
+}
+
+void PepperFileSystemBrowserHost::OpenFileSystem(
ppapi::host::ReplyMessageContext reply_context,
fileapi::FileSystemType file_system_type,
- scoped_refptr<fileapi::FileSystemContext> fs_context) {
- if (!fs_context.get()) {
+ scoped_refptr<fileapi::FileSystemContext> file_system_context) {
+ if (!file_system_context.get()) {
OpenFileSystemComplete(
- reply_context, base::PLATFORM_FILE_ERROR_FAILED, std::string(), GURL());
+ reply_context, GURL(), std::string(), base::PLATFORM_FILE_ERROR_FAILED);
return;
}
+
+ SetFileSystemContext(file_system_context);
+
GURL origin = browser_ppapi_host_->GetDocumentURLForInstance(
pp_instance()).GetOrigin();
- fs_context->OpenFileSystem(origin, file_system_type,
+ file_system_context_->OpenFileSystem(origin, file_system_type,
fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&PepperFileSystemBrowserHost::OpenFileSystemComplete,
weak_factory_.GetWeakPtr(),
reply_context));
- fs_context_ = fs_context;
-}
-
-void PepperFileSystemBrowserHost::GotIsolatedFileSystemContext(
- ppapi::host::ReplyMessageContext reply_context,
- scoped_refptr<fileapi::FileSystemContext> fs_context) {
- fs_context_ = fs_context;
- if (fs_context.get())
- reply_context.params.set_result(PP_OK);
- else
- reply_context.params.set_result(PP_ERROR_FAILED);
- host()->SendReply(reply_context,
- PpapiPluginMsg_FileSystem_InitIsolatedFileSystemReply());
}
void PepperFileSystemBrowserHost::OpenFileSystemComplete(
ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError error,
+ const GURL& root,
const std::string& /* unused */,
- const GURL& root) {
+ base::PlatformFileError error) {
int32 pp_error = ppapi::PlatformFileErrorToPepperError(error);
if (pp_error == PP_OK) {
opened_ = true;
root_url_ = root;
+
+ if (ShouldCreateQuotaReservation()) {
+ CreateQuotaReservation(
+ base::Bind(&PepperFileSystemBrowserHost::SendReplyForFileSystem,
+ weak_factory_.GetWeakPtr(),
+ reply_context,
+ static_cast<int32_t>(PP_OK)));
+ return;
+ }
}
- reply_context.params.set_result(pp_error);
- host()->SendReply(reply_context, PpapiPluginMsg_FileSystem_OpenReply());
+ SendReplyForFileSystem(reply_context, pp_error);
+}
+
+void PepperFileSystemBrowserHost::OpenIsolatedFileSystem(
+ ppapi::host::ReplyMessageContext reply_context,
+ const std::string& fsid,
+ PP_IsolatedFileSystemType_Private type,
+ scoped_refptr<fileapi::FileSystemContext> file_system_context) {
+ if (!file_system_context.get()) {
+ SendReplyForIsolatedFileSystem(reply_context, fsid, PP_ERROR_FAILED);
+ return;
+ }
+ SetFileSystemContext(file_system_context);
+
+ root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
+ browser_ppapi_host_->GetDocumentURLForInstance(pp_instance()).GetOrigin(),
+ fsid, ppapi::IsolatedFileSystemTypeToRootName(type)));
+ if (!root_url_.is_valid()) {
+ SendReplyForIsolatedFileSystem(reply_context, fsid, PP_ERROR_FAILED);
+ return;
+ }
+
+ switch (type) {
+ case PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_CRX:
+ opened_ = true;
+ SendReplyForIsolatedFileSystem(reply_context, fsid, PP_OK);
+ return;
+ case PP_ISOLATEDFILESYSTEMTYPE_PRIVATE_PLUGINPRIVATE:
+ OpenPluginPrivateFileSystem(reply_context, fsid, file_system_context_);
+ return;
+ default:
+ NOTREACHED();
+ SendReplyForIsolatedFileSystem(reply_context, fsid, PP_ERROR_BADARGUMENT);
+ return;
+ }
+}
+
+void PepperFileSystemBrowserHost::OpenPluginPrivateFileSystem(
+ ppapi::host::ReplyMessageContext reply_context,
+ const std::string& fsid,
+ scoped_refptr<fileapi::FileSystemContext> file_system_context) {
+ GURL origin = browser_ppapi_host_->GetDocumentURLForInstance(
+ pp_instance()).GetOrigin();
+ if (!origin.is_valid()) {
+ SendReplyForIsolatedFileSystem(reply_context, fsid, PP_ERROR_FAILED);
+ return;
+ }
+
+ const std::string& plugin_id = GeneratePluginId(GetPluginMimeType());
+ if (plugin_id.empty()) {
+ SendReplyForIsolatedFileSystem(reply_context, fsid, PP_ERROR_BADARGUMENT);
+ return;
+ }
+
+ file_system_context->OpenPluginPrivateFileSystem(
+ origin, fileapi::kFileSystemTypePluginPrivate, fsid, plugin_id,
+ fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(
+ &PepperFileSystemBrowserHost::OpenPluginPrivateFileSystemComplete,
+ weak_factory_.GetWeakPtr(), reply_context, fsid));
+}
+
+void PepperFileSystemBrowserHost::OpenPluginPrivateFileSystemComplete(
+ ppapi::host::ReplyMessageContext reply_context,
+ const std::string& fsid,
+ base::PlatformFileError error) {
+ int32 pp_error = ppapi::PlatformFileErrorToPepperError(error);
+ if (pp_error == PP_OK)
+ opened_ = true;
+ SendReplyForIsolatedFileSystem(reply_context, fsid, pp_error);
}
int32_t PepperFileSystemBrowserHost::OnHostMsgInitIsolatedFileSystem(
ppapi::host::HostMessageContext* context,
- const std::string& fsid) {
+ const std::string& fsid,
+ PP_IsolatedFileSystemType_Private type) {
+ // Do not allow multiple opens.
+ if (called_open_)
+ return PP_ERROR_INPROGRESS;
called_open_ = true;
+
// Do a sanity check.
- if (!LooksLikeAGuid(fsid))
+ if (!fileapi::ValidateIsolatedFileSystemId(fsid))
return PP_ERROR_BADARGUMENT;
- const GURL& url =
- browser_ppapi_host_->GetDocumentURLForInstance(pp_instance());
- root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
- url.GetOrigin(), fsid, "crxfs"));
- opened_ = true;
int render_process_id = 0;
int unused;
if (!browser_ppapi_host_->GetRenderViewIDsForInstance(pp_instance(),
&render_process_id,
&unused)) {
+ fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
return PP_ERROR_FAILED;
}
+
+ root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
+ browser_ppapi_host_->GetDocumentURLForInstance(pp_instance()).GetOrigin(),
+ fsid, ppapi::IsolatedFileSystemTypeToRootName(type)));
+
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::UI,
FROM_HERE,
base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
- base::Bind(&PepperFileSystemBrowserHost::GotIsolatedFileSystemContext,
+ base::Bind(&PepperFileSystemBrowserHost::OpenIsolatedFileSystem,
weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext()));
+ context->MakeReplyMessageContext(), fsid, type));
return PP_OK_COMPLETIONPENDING;
}
+void PepperFileSystemBrowserHost::SendReplyForFileSystem(
+ ppapi::host::ReplyMessageContext reply_context,
+ int32_t pp_error) {
+ reply_context.params.set_result(pp_error);
+ host()->SendReply(reply_context, PpapiPluginMsg_FileSystem_OpenReply());
+}
+
+void PepperFileSystemBrowserHost::SendReplyForIsolatedFileSystem(
+ ppapi::host::ReplyMessageContext reply_context,
+ const std::string& fsid,
+ int32_t error) {
+ if (error != PP_OK)
+ fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
+ reply_context.params.set_result(error);
+ host()->SendReply(reply_context,
+ PpapiPluginMsg_FileSystem_InitIsolatedFileSystemReply());
+}
+
+void PepperFileSystemBrowserHost::SetFileSystemContext(
+ scoped_refptr<fileapi::FileSystemContext> file_system_context) {
+ file_system_context_ = file_system_context;
+ if (type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
+ file_system_operation_runner_ =
+ file_system_context_->CreateFileSystemOperationRunner();
+ }
+}
+
+bool PepperFileSystemBrowserHost::ShouldCreateQuotaReservation() const {
+ // Some file system types don't have quota.
+ if (!ppapi::FileSystemTypeHasQuota(type_))
+ return false;
+
+ // For file system types with quota, ome origins have unlimited storage.
+ quota::QuotaManagerProxy* quota_manager_proxy =
+ file_system_context_->quota_manager_proxy();
+ CHECK(quota_manager_proxy);
+ CHECK(quota_manager_proxy->quota_manager());
+ fileapi::FileSystemType file_system_type =
+ ppapi::PepperFileSystemTypeToFileSystemType(type_);
+ return !quota_manager_proxy->quota_manager()->IsStorageUnlimited(
+ root_url_.GetOrigin(),
+ fileapi::FileSystemTypeToQuotaStorageType(file_system_type));
+}
+
+void PepperFileSystemBrowserHost::CreateQuotaReservation(
+ const base::Closure& callback) {
+ DCHECK(root_url_.is_valid());
+ base::PostTaskAndReplyWithResult(
+ file_system_context_->default_file_task_runner(),
+ FROM_HERE,
+ base::Bind(&QuotaReservation::Create,
+ file_system_context_,
+ root_url_.GetOrigin(),
+ ppapi::PepperFileSystemTypeToFileSystemType(type_)),
+ base::Bind(&PepperFileSystemBrowserHost::GotQuotaReservation,
+ weak_factory_.GetWeakPtr(),
+ callback));
+}
+
+void PepperFileSystemBrowserHost::GotQuotaReservation(
+ const base::Closure& callback,
+ scoped_refptr<QuotaReservation> quota_reservation) {
+ quota_reservation_ = quota_reservation;
+ callback.Run();
+}
+
+void PepperFileSystemBrowserHost::ReserveQuota(int32_t amount) {
+ DCHECK(!reserving_quota_);
+ reserving_quota_ = true;
+
+ // Get the max_written_offset for each open file.
+ QuotaReservation::OffsetMap max_written_offsets;
+ for (FileMap::iterator it = files_.begin(); it != files_.end(); ++ it) {
+ max_written_offsets.insert(
+ std::make_pair(it->first, it->second->max_written_offset()));
+ }
+
+ int64_t reservation_amount = std::max<int64_t>(kMinimumQuotaReservationSize,
+ amount);
+ file_system_context_->default_file_task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&QuotaReservation::ReserveQuota,
+ quota_reservation_,
+ reservation_amount,
+ max_written_offsets,
+ base::Bind(&PepperFileSystemBrowserHost::GotReservedQuota,
+ weak_factory_.GetWeakPtr())));
+}
+
+void PepperFileSystemBrowserHost::GotReservedQuota(
+ int64_t amount,
+ const QuotaReservation::OffsetMap& max_written_offsets) {
+ DCHECK(reserving_quota_);
+ reserving_quota_ = false;
+ reserved_quota_ = amount;
+
+ // Update open files with their new base sizes. This won't write over any
+ // updates since the files are waiting for quota and can't write.
+ for (FileMap::iterator it = files_.begin(); it != files_.end(); ++ it) {
+ QuotaReservation::OffsetMap::const_iterator offset_it =
+ max_written_offsets.find(it->first);
+ if (offset_it != max_written_offsets.end())
+ it->second->set_max_written_offset(offset_it->second);
+ else
+ NOTREACHED();
+ }
+
+ DCHECK(!pending_quota_requests_.empty());
+ // If we can't grant the first request after refreshing reserved_quota_, then
+ // fail all pending quota requests to avoid an infinite refresh/fail loop.
+ bool fail_all = reserved_quota_ < pending_quota_requests_.front().amount;
+ while (!pending_quota_requests_.empty()) {
+ QuotaRequest& request = pending_quota_requests_.front();
+ if (fail_all) {
+ request.callback.Run(0);
+ pending_quota_requests_.pop();
+ } else if (reserved_quota_ >= request.amount) {
+ reserved_quota_ -= request.amount;
+ request.callback.Run(request.amount);
+ pending_quota_requests_.pop();
+ } else {
+ // Refresh the quota reservation for the first pending request that we
+ // can't satisfy.
+ ReserveQuota(request.amount);
+ break;
+ }
+ }
+}
+
+std::string PepperFileSystemBrowserHost::GetPluginMimeType() const {
+ base::FilePath plugin_path = browser_ppapi_host_->GetPluginPath();
+ PepperPluginInfo* info =
+ PluginService::GetInstance()->GetRegisteredPpapiPluginInfo(plugin_path);
+ if (!info || info->mime_types.empty())
+ return std::string();
+ // Use the first element in |info->mime_types| even if several elements exist.
+ return info->mime_types[0].mime_type;
+}
+
+std::string PepperFileSystemBrowserHost::GeneratePluginId(
+ const std::string& mime_type) const {
+ // TODO(nhiroki): This function is very specialized for specific plugins (MIME
+ // types). If we bring this API to stable, we might have to make it more
+ // general.
+
+ if (!net::IsMimeType(mime_type))
+ return std::string();
+ std::string output = mime_type;
+
+ // Replace a slash used for type/subtype separator with an underscore.
+ // NOTE: This assumes there is only one slash in the MIME type.
+ ReplaceFirstSubstringAfterOffset(&output, 0, "/", "_");
+
+ // Verify |output| contains only alphabets, digits, or "._-".
+ for (std::string::const_iterator it = output.begin();
+ it != output.end(); ++it) {
+ if (!IsAsciiAlpha(*it) && !IsAsciiDigit(*it) &&
+ *it != '.' && *it != '_' && *it != '-') {
+ LOG(WARNING) << "Failed to generate a plugin id.";
+ return std::string();
+ }
+ }
+ return output;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h
index ed648fb9938..f97ddde671d 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h
@@ -5,30 +5,46 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FILE_SYSTEM_BROWSER_HOST_H_
#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FILE_SYSTEM_BROWSER_HOST_H_
+#include <queue>
+#include <string>
+#include <vector>
+
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/memory/weak_ptr.h"
+#include "content/browser/renderer_host/pepper/quota_reservation.h"
+#include "content/common/content_export.h"
#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/private/ppb_isolated_file_system_private.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
#include "url/gurl.h"
#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/common/fileapi/file_system_types.h"
namespace content {
class BrowserPpapiHost;
+class PepperFileIOHost;
-class PepperFileSystemBrowserHost :
- public ppapi::host::ResourceHost,
- public base::SupportsWeakPtr<PepperFileSystemBrowserHost> {
+class CONTENT_EXPORT PepperFileSystemBrowserHost
+ : public ppapi::host::ResourceHost,
+ public base::SupportsWeakPtr<PepperFileSystemBrowserHost> {
public:
+ // Creates a new PepperFileSystemBrowserHost for a file system of a given
+ // |type|. The host must be opened before use.
PepperFileSystemBrowserHost(BrowserPpapiHost* host,
PP_Instance instance,
PP_Resource resource,
PP_FileSystemType type);
virtual ~PepperFileSystemBrowserHost();
- // ppapi::host::ResourceHost override.
+ // Opens the PepperFileSystemBrowserHost to use an existing file system at the
+ // given |root_url|. The file system at |root_url| must already be opened and
+ // have the type given by GetType().
+ // Calls |callback| when complete.
+ void OpenExisting(const GURL& root_url, const base::Closure& callback);
+
+ // ppapi::host::ResourceHost overrides.
virtual int32_t OnResourceMessageReceived(
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) OVERRIDE;
@@ -39,36 +55,125 @@ class PepperFileSystemBrowserHost :
bool IsOpened() const { return opened_; }
GURL GetRootUrl() const { return root_url_; }
scoped_refptr<fileapi::FileSystemContext> GetFileSystemContext() const {
- return fs_context_;
+ return file_system_context_;
}
+ // Supports FileIOs direct access on the host side.
+ // Non-NULL only for PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY}.
+ fileapi::FileSystemOperationRunner* GetFileSystemOperationRunner() const {
+ return file_system_operation_runner_.get();
+ }
+ bool ChecksQuota() const { return quota_reservation_ != NULL; }
+ // Opens a file for writing with quota checks. Returns the file size in the
+ // callback.
+ typedef base::Callback<void(int64_t)> OpenQuotaFileCallback;
+ void OpenQuotaFile(PepperFileIOHost* file_io_host,
+ const fileapi::FileSystemURL& url,
+ const OpenQuotaFileCallback& callback);
+ // Closes the file. This must be called after OpenQuotaFile and before the
+ // PepperFileIOHost is destroyed.
+ void CloseQuotaFile(PepperFileIOHost* file_io_host);
+ // Requests the given amount of quota. Returns the amount requested or
+ // PP_OK_COMPLETIONPENDING, in which case the amount granted is returned in
+ // the callback. Requests can't partially succeed so the amount granted is
+ // either 0 or the amount of the request. Requesting an amount of 0 will
+ // return immediately with a 0 result.
+ typedef base::Callback<void(int32_t)> RequestQuotaCallback;
+ int32_t RequestQuota(int32_t amount,
+ const RequestQuotaCallback& callback);
private:
- void GotFileSystemContext(
+ friend class PepperFileSystemBrowserHostTest;
+
+ struct QuotaRequest {
+ QuotaRequest(int32_t amount, const RequestQuotaCallback& callback);
+ ~QuotaRequest();
+
+ int32_t amount;
+ RequestQuotaCallback callback;
+ };
+
+ void OpenExistingFileSystem(
+ const base::Closure& callback,
+ scoped_refptr<fileapi::FileSystemContext> file_system_context);
+ void OpenFileSystem(
ppapi::host::ReplyMessageContext reply_context,
fileapi::FileSystemType file_system_type,
- scoped_refptr<fileapi::FileSystemContext> fs_context);
- void GotIsolatedFileSystemContext(
- ppapi::host::ReplyMessageContext reply_context,
- scoped_refptr<fileapi::FileSystemContext> fs_context);
+ scoped_refptr<fileapi::FileSystemContext> file_system_context);
void OpenFileSystemComplete(
ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError error,
+ const GURL& root,
const std::string& name,
- const GURL& root);
+ base::PlatformFileError error);
+ void OpenIsolatedFileSystem(
+ ppapi::host::ReplyMessageContext reply_context,
+ const std::string& fsid,
+ PP_IsolatedFileSystemType_Private type,
+ scoped_refptr<fileapi::FileSystemContext> file_system_context);
+ void OpenPluginPrivateFileSystem(
+ ppapi::host::ReplyMessageContext reply_context,
+ const std::string& fsid,
+ scoped_refptr<fileapi::FileSystemContext> file_system_context);
+ void OpenPluginPrivateFileSystemComplete(
+ ppapi::host::ReplyMessageContext reply_context,
+ const std::string& fsid,
+ base::PlatformFileError error);
int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
int64_t expected_size);
int32_t OnHostMsgInitIsolatedFileSystem(
ppapi::host::HostMessageContext* context,
- const std::string& fsid);
+ const std::string& fsid,
+ PP_IsolatedFileSystemType_Private type);
+
+ void SendReplyForFileSystem(
+ ppapi::host::ReplyMessageContext reply_context,
+ int32_t pp_error);
+ void SendReplyForIsolatedFileSystem(
+ ppapi::host::ReplyMessageContext reply_context,
+ const std::string& fsid,
+ int32_t error);
+
+ void SetFileSystemContext(
+ scoped_refptr<fileapi::FileSystemContext> file_system_context);
+
+ bool ShouldCreateQuotaReservation() const;
+ void CreateQuotaReservation(const base::Closure& callback);
+ void GotQuotaReservation(
+ const base::Closure& callback,
+ scoped_refptr<QuotaReservation> quota_reservation);
+
+ void ReserveQuota(int32_t amount);
+ void GotReservedQuota(int64_t amount,
+ const QuotaReservation::OffsetMap& max_written_offsets);
+
+ std::string GetPluginMimeType() const;
+
+ // Returns plugin ID generated from plugin's MIME type.
+ std::string GeneratePluginId(const std::string& mime_type) const;
BrowserPpapiHost* browser_ppapi_host_;
PP_FileSystemType type_;
- bool opened_; // whether open is successful.
- GURL root_url_;
- scoped_refptr<fileapi::FileSystemContext> fs_context_;
bool called_open_; // whether open has been called.
+ bool opened_; // whether open succeeded.
+ GURL root_url_;
+ scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+
+ scoped_ptr<fileapi::FileSystemOperationRunner> file_system_operation_runner_;
+
+ // Used only for file systems with quota.
+ // When a PepperFileIOHost calls OpenQuotaFile, we add the id and a non-owning
+ // pointer to this map. CloseQuotaFile must be called when before the host is
+ // destroyed.
+ typedef std::map<int32_t, PepperFileIOHost*> FileMap;
+ FileMap files_;
+ std::queue<QuotaRequest> pending_quota_requests_;
+ int64_t reserved_quota_;
+ bool reserving_quota_;
+ // Access only on the FileSystemContext's default_file_task_runner().
+ scoped_refptr<QuotaReservation> quota_reservation_;
+
+ std::string fsid_; // used only for isolated filesystems.
base::WeakPtrFactory<PepperFileSystemBrowserHost> weak_factory_;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc
new file mode 100644
index 00000000000..fa07e3938ab
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc
@@ -0,0 +1,80 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/renderer_host/pepper/browser_ppapi_host_test.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class PepperFileSystemBrowserHostTest
+ : public testing::Test,
+ public BrowserPpapiHostTest {
+ public:
+ PepperFileSystemBrowserHostTest() {}
+ virtual ~PepperFileSystemBrowserHostTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ PP_Instance pp_instance = 12345;
+ PP_Resource pp_resource = 67890;
+ host_.reset(new PepperFileSystemBrowserHost(
+ GetBrowserPpapiHost(), pp_instance, pp_resource,
+ PP_FILESYSTEMTYPE_ISOLATED));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ host_.reset();
+ }
+
+ protected:
+ std::string GeneratePluginId(const std::string& mime_type) {
+ return host_->GeneratePluginId(mime_type);
+ }
+
+ private:
+ scoped_ptr<PepperFileSystemBrowserHost> host_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperFileSystemBrowserHostTest);
+};
+
+TEST_F(PepperFileSystemBrowserHostTest, GeneratePluginId) {
+ // Should not contain wild card characters.
+ EXPECT_TRUE(GeneratePluginId("*").empty());
+ EXPECT_TRUE(GeneratePluginId("*/*").empty());
+
+ // Should contain only one slash.
+ EXPECT_TRUE(GeneratePluginId(".").empty());
+ EXPECT_TRUE(GeneratePluginId("..").empty());
+ EXPECT_TRUE(GeneratePluginId("application").empty());
+ EXPECT_TRUE(GeneratePluginId("application/mime/type").empty());
+
+ // Should start with "legal_top_level_types"
+ // (ex. "application", "audio", "x-"). See "mime_util.cc" for more details.
+ EXPECT_TRUE(GeneratePluginId("/mime").empty());
+ EXPECT_TRUE(GeneratePluginId("./mime").empty());
+ EXPECT_TRUE(GeneratePluginId("../mime").empty());
+ EXPECT_TRUE(GeneratePluginId("app/mime").empty());
+
+ // Should not contain characters other than alphanumeric or "._-".
+ EXPECT_TRUE(GeneratePluginId("application/mime+type").empty());
+ EXPECT_TRUE(GeneratePluginId("application/mime:type").empty());
+ EXPECT_TRUE(GeneratePluginId("application/mime;type").empty());
+
+ // Valid cases.
+ EXPECT_EQ("application_mime", GeneratePluginId("application/mime"));
+ EXPECT_EQ("x-app_mime", GeneratePluginId("x-app/mime"));
+ EXPECT_EQ("application_mime.type", GeneratePluginId("application/mime.type"));
+ EXPECT_EQ("application_mime_type", GeneratePluginId("application/mime_type"));
+ EXPECT_EQ("application_mime-type", GeneratePluginId("application/mime-type"));
+ EXPECT_EQ("application_..", GeneratePluginId("application/.."));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
index ef740625bd3..ba8a8b91368 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
@@ -31,16 +31,9 @@ bool CanRead(int process_id, const base::FilePath& path) {
CanReadFile(process_id, path);
}
-bool CanWrite(int process_id, const base::FilePath& path) {
+bool CanCreateReadWrite(int process_id, const base::FilePath& path) {
return ChildProcessSecurityPolicyImpl::GetInstance()->
- CanWriteFile(process_id, path);
-}
-
-bool CanReadWrite(int process_id, const base::FilePath& path) {
- ChildProcessSecurityPolicyImpl* policy =
- ChildProcessSecurityPolicyImpl::GetInstance();
- return policy->CanReadFile(process_id, path) &&
- policy->CanWriteFile(process_id, path);
+ CanCreateReadWriteFile(process_id, path);
}
} // namespace
@@ -163,9 +156,9 @@ int32_t PepperFlashFileMessageFilter::OnRenameFile(
const ppapi::PepperFilePath& from_path,
const ppapi::PepperFilePath& to_path) {
base::FilePath from_full_path = ValidateAndConvertPepperFilePath(
- from_path, base::Bind(&CanWrite));
+ from_path, base::Bind(&CanCreateReadWrite));
base::FilePath to_full_path = ValidateAndConvertPepperFilePath(
- to_path, base::Bind(&CanWrite));
+ to_path, base::Bind(&CanCreateReadWrite));
if (from_full_path.empty() || to_full_path.empty()) {
return ppapi::PlatformFileErrorToPepperError(
base::PLATFORM_FILE_ERROR_ACCESS_DENIED);
@@ -181,7 +174,7 @@ int32_t PepperFlashFileMessageFilter::OnDeleteFileOrDir(
const ppapi::PepperFilePath& path,
bool recursive) {
base::FilePath full_path = ValidateAndConvertPepperFilePath(
- path, base::Bind(&CanWrite));
+ path, base::Bind(&CanCreateReadWrite));
if (full_path.empty()) {
return ppapi::PlatformFileErrorToPepperError(
base::PLATFORM_FILE_ERROR_ACCESS_DENIED);
@@ -195,13 +188,13 @@ int32_t PepperFlashFileMessageFilter::OnCreateDir(
ppapi::host::HostMessageContext* context,
const ppapi::PepperFilePath& path) {
base::FilePath full_path = ValidateAndConvertPepperFilePath(
- path, base::Bind(&CanWrite));
+ path, base::Bind(&CanCreateReadWrite));
if (full_path.empty()) {
return ppapi::PlatformFileErrorToPepperError(
base::PLATFORM_FILE_ERROR_ACCESS_DENIED);
}
- bool result = file_util::CreateDirectory(full_path);
+ bool result = base::CreateDirectory(full_path);
return ppapi::PlatformFileErrorToPepperError(result ?
base::PLATFORM_FILE_OK : base::PLATFORM_FILE_ERROR_ACCESS_DENIED);
}
@@ -217,7 +210,7 @@ int32_t PepperFlashFileMessageFilter::OnQueryFile(
}
base::PlatformFileInfo info;
- bool result = file_util::GetFileInfo(full_path, &info);
+ bool result = base::GetFileInfo(full_path, &info);
context->reply_msg = PpapiPluginMsg_FlashFile_QueryFileReply(info);
return ppapi::PlatformFileErrorToPepperError(result ?
base::PLATFORM_FILE_OK : base::PLATFORM_FILE_ERROR_ACCESS_DENIED);
@@ -257,16 +250,16 @@ int32_t PepperFlashFileMessageFilter::OnCreateTemporaryFile(
ppapi::PepperFilePath dir_path(
ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL, base::FilePath());
base::FilePath validated_dir_path = ValidateAndConvertPepperFilePath(
- dir_path, base::Bind(&CanReadWrite));
+ dir_path, base::Bind(&CanCreateReadWrite));
if (validated_dir_path.empty() ||
(!base::DirectoryExists(validated_dir_path) &&
- !file_util::CreateDirectory(validated_dir_path))) {
+ !base::CreateDirectory(validated_dir_path))) {
return ppapi::PlatformFileErrorToPepperError(
base::PLATFORM_FILE_ERROR_ACCESS_DENIED);
}
base::FilePath file_path;
- if (!file_util::CreateTemporaryFileInDir(validated_dir_path, &file_path)) {
+ if (!base::CreateTemporaryFileInDir(validated_dir_path, &file_path)) {
return ppapi::PlatformFileErrorToPepperError(
base::PLATFORM_FILE_ERROR_FAILED);
}
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 3dfbe2bb198..43ff1170354 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
@@ -31,7 +31,7 @@ class PepperGamepadHostTest
virtual ~PepperGamepadHostTest() {
}
- void ConstructService(const WebKit::WebGamepads& test_data) {
+ void ConstructService(const blink::WebGamepads& test_data) {
service_.reset(new GamepadServiceTestConstructor(test_data));
}
@@ -68,15 +68,15 @@ TEST_F(PepperGamepadHostTest, ValidateHardwareBuffersMatch) {
TEST_F(PepperGamepadHostTest, ValidateGamepadsMatch) {
// Gamepads.
COMPILE_ASSERT(sizeof(ppapi::WebKitGamepads) ==
- sizeof(WebKit::WebGamepads),
+ sizeof(blink::WebGamepads),
gamepads_data_must_match);
ppapi::WebKitGamepads ppapi_gamepads;
- WebKit::WebGamepads web_gamepads;
+ blink::WebGamepads web_gamepads;
EXPECT_EQ(AddressDiff(&web_gamepads.length, &web_gamepads),
AddressDiff(&ppapi_gamepads.length, &ppapi_gamepads));
// See comment below on storage & the EXPECT macro.
- size_t webkit_items_length_cap = WebKit::WebGamepads::itemsLengthCap;
+ size_t webkit_items_length_cap = blink::WebGamepads::itemsLengthCap;
size_t ppapi_items_length_cap = ppapi::WebKitGamepads::kItemsLengthCap;
EXPECT_EQ(webkit_items_length_cap, ppapi_items_length_cap);
@@ -89,23 +89,23 @@ TEST_F(PepperGamepadHostTest, ValidateGamepadsMatch) {
TEST_F(PepperGamepadHostTest, ValidateGamepadMatch) {
// Gamepad.
COMPILE_ASSERT(sizeof(ppapi::WebKitGamepad) ==
- sizeof(WebKit::WebGamepad),
+ sizeof(blink::WebGamepad),
gamepad_data_must_match);
ppapi::WebKitGamepad ppapi_gamepad;
- WebKit::WebGamepad web_gamepad;
+ blink::WebGamepad web_gamepad;
// Using EXPECT seems to force storage for the parameter, which the constants
// in the WebKit/PPAPI headers don't have. So we have to use temporaries
// before comparing them.
- size_t webkit_id_length_cap = WebKit::WebGamepad::idLengthCap;
+ size_t webkit_id_length_cap = blink::WebGamepad::idLengthCap;
size_t ppapi_id_length_cap = ppapi::WebKitGamepad::kIdLengthCap;
EXPECT_EQ(webkit_id_length_cap, ppapi_id_length_cap);
- size_t webkit_axes_length_cap = WebKit::WebGamepad::axesLengthCap;
+ size_t webkit_axes_length_cap = blink::WebGamepad::axesLengthCap;
size_t ppapi_axes_length_cap = ppapi::WebKitGamepad::kAxesLengthCap;
EXPECT_EQ(webkit_axes_length_cap, ppapi_axes_length_cap);
- size_t webkit_buttons_length_cap = WebKit::WebGamepad::buttonsLengthCap;
+ size_t webkit_buttons_length_cap = blink::WebGamepad::buttonsLengthCap;
size_t ppapi_buttons_length_cap = ppapi::WebKitGamepad::kButtonsLengthCap;
EXPECT_EQ(webkit_buttons_length_cap, ppapi_buttons_length_cap);
@@ -126,8 +126,8 @@ TEST_F(PepperGamepadHostTest, ValidateGamepadMatch) {
}
TEST_F(PepperGamepadHostTest, WaitForReply) {
- WebKit::WebGamepads default_data;
- memset(&default_data, 0, sizeof(WebKit::WebGamepads));
+ blink::WebGamepads default_data;
+ memset(&default_data, 0, sizeof(blink::WebGamepads));
default_data.length = 1;
default_data.items[0].connected = true;
default_data.items[0].buttonsLength = 1;
@@ -163,7 +163,7 @@ TEST_F(PepperGamepadHostTest, WaitForReply) {
// will issue the callback on our thread. Waiting for it to read twice
// ensures that it was able to issue callbacks for the first read (if it
// issued one) before we try to check for it.
- WebKit::WebGamepads button_down_data = default_data;
+ blink::WebGamepads button_down_data = default_data;
button_down_data.items[0].buttons[0] = 1.f;
fetcher->SetTestData(button_down_data);
fetcher->WaitForDataRead();
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
index 3b8c801ec1a..e57a237c503 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
@@ -71,6 +71,10 @@ fileapi::FileSystemURL PepperInternalFileRefBackend::GetFileSystemURL() const {
return fs_url_;
}
+base::FilePath PepperInternalFileRefBackend::GetExternalFilePath() const {
+ return base::FilePath();
+}
+
scoped_refptr<fileapi::FileSystemContext>
PepperInternalFileRefBackend::GetFileSystemContext() const {
if (!fs_host_.get())
@@ -151,6 +155,7 @@ int32_t PepperInternalFileRefBackend::Rename(
GetFileSystemContext()->operation_runner()->Move(
GetFileSystemURL(),
new_url,
+ fileapi::FileSystemOperation::OPTION_NONE,
base::Bind(&PepperInternalFileRefBackend::DidFinish,
weak_factory_.GetWeakPtr(),
reply_context,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
index 81d6ab624cd..93dbab97a3e 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
@@ -44,8 +44,8 @@ class PepperInternalFileRefBackend : public PepperFileRefBackend {
ppapi::host::ReplyMessageContext context) OVERRIDE;
virtual int32_t GetAbsolutePath(ppapi::host::ReplyMessageContext context)
OVERRIDE;
-
virtual fileapi::FileSystemURL GetFileSystemURL() const OVERRIDE;
+ virtual base::FilePath GetExternalFilePath() const OVERRIDE;
virtual int32_t CanRead() const OVERRIDE;
virtual int32_t CanWrite() const OVERRIDE;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc
index 6434729b734..1394d956f0d 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_message_filter.cc
@@ -31,10 +31,8 @@ void PepperMessageFilter::OnX509CertificateParseDER(
const std::vector<char>& der,
bool* succeeded,
ppapi::PPB_X509Certificate_Fields* result) {
- if (der.size() == 0)
- *succeeded = false;
- *succeeded =
- pepper_socket_utils::GetCertificateFields(&der[0], der.size(), result);
+ *succeeded = (der.size() != 0 && pepper_socket_utils::GetCertificateFields(
+ &der[0], der.size(), result));
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
index e4c8aa71dc1..1c00388870c 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
@@ -4,12 +4,15 @@
#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/ppapi_plugin_process_host.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/common/pepper_renderer_instance_data.h"
#include "content/common/view_messages.h"
#include "content/browser/renderer_host/pepper/pepper_file_ref_host.h"
+#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "ipc/ipc_message_macros.h"
@@ -21,6 +24,68 @@
namespace content {
+namespace {
+
+// Responsible for creating the pending resource hosts, holding their IDs until
+// all of them have been created for a single message, and sending the reply to
+// say that the hosts have been created.
+class PendingHostCreator
+ : public base::RefCounted<PendingHostCreator> {
+ public:
+ PendingHostCreator(BrowserPpapiHostImpl* host,
+ BrowserMessageFilter* connection,
+ int routing_id,
+ int sequence_id,
+ size_t nested_msgs_size);
+
+ // Adds the given resource host as a pending one. The host is remembered as
+ // host number |index|, and will ultimately be sent to the plugin to be
+ // attached to a real resource.
+ void AddPendingResourceHost(
+ size_t index,
+ scoped_ptr<ppapi::host::ResourceHost> resource_host);
+
+ private:
+ friend class base::RefCounted<PendingHostCreator>;
+
+ // When the last reference to this class is released, all of the resource
+ // hosts would have been added. This destructor sends the message to the
+ // plugin to tell it to attach real hosts to all of the pending hosts that
+ // have been added by this object.
+ ~PendingHostCreator();
+
+ BrowserPpapiHostImpl* host_;
+ BrowserMessageFilter* connection_;
+ int routing_id_;
+ int sequence_id_;
+ std::vector<int> pending_resource_host_ids_;
+};
+
+PendingHostCreator::PendingHostCreator(BrowserPpapiHostImpl* host,
+ BrowserMessageFilter* connection,
+ int routing_id,
+ int sequence_id,
+ size_t nested_msgs_size)
+ : host_(host),
+ connection_(connection),
+ routing_id_(routing_id),
+ sequence_id_(sequence_id),
+ pending_resource_host_ids_(nested_msgs_size, 0) {}
+
+void PendingHostCreator::AddPendingResourceHost(
+ size_t index,
+ scoped_ptr<ppapi::host::ResourceHost> resource_host) {
+ pending_resource_host_ids_[index] =
+ host_->GetPpapiHost()->AddPendingResourceHost(resource_host.Pass());
+}
+
+PendingHostCreator::~PendingHostCreator() {
+ connection_->Send(new PpapiHostMsg_CreateResourceHostsFromHostReply(
+ routing_id_, sequence_id_, pending_resource_host_ids_));
+}
+
+} // namespace
+
PepperRendererConnection::PepperRendererConnection(int render_process_id)
: render_process_id_(render_process_id) {
// Only give the renderer permission for stable APIs.
@@ -29,7 +94,8 @@ PepperRendererConnection::PepperRendererConnection(int render_process_id)
"",
base::FilePath(),
base::FilePath(),
- false));
+ true /* in_process */,
+ false /* external_plugin */));
}
PepperRendererConnection::~PepperRendererConnection() {
@@ -91,41 +157,71 @@ void PepperRendererConnection::OnMsgCreateResourceHostsFromHost(
PP_Instance instance,
const std::vector<IPC::Message>& nested_msgs) {
BrowserPpapiHostImpl* host = GetHostForChildProcess(child_process_id);
-
- std::vector<int> pending_resource_host_ids(nested_msgs.size(), 0);
if (!host) {
DLOG(ERROR) << "Invalid plugin process ID.";
- } else {
- for (size_t i = 0; i < nested_msgs.size(); ++i) {
- // FileRef_CreateExternal is only permitted from the renderer. Because of
- // this, we handle this message here and not in
- // content_browser_pepper_host_factory.cc.
- scoped_ptr<ppapi::host::ResourceHost> resource_host;
- if (host->IsValidInstance(instance)) {
- if (nested_msgs[i].type() == PpapiHostMsg_FileRef_CreateExternal::ID) {
- base::FilePath external_path;
- if (ppapi::UnpackMessage<PpapiHostMsg_FileRef_CreateExternal>(
- nested_msgs[i], &external_path)) {
- resource_host.reset(new PepperFileRefHost(
- host, instance, params.pp_resource(), external_path));
- }
- }
- }
+ return;
+ }
- if (!resource_host.get()) {
- resource_host = host->GetPpapiHost()->CreateResourceHost(
- params, instance, nested_msgs[i]);
+ scoped_refptr<PendingHostCreator> creator = new PendingHostCreator(
+ host, this, routing_id, params.sequence(), nested_msgs.size());
+ for (size_t i = 0; i < nested_msgs.size(); ++i) {
+ const IPC::Message& nested_msg = nested_msgs[i];
+ scoped_ptr<ppapi::host::ResourceHost> resource_host;
+ if (host->IsValidInstance(instance)) {
+ if (nested_msg.type() == PpapiHostMsg_FileRef_CreateExternal::ID) {
+ // FileRef_CreateExternal is only permitted from the renderer. Because
+ // of this, we handle this message here and not in
+ // content_browser_pepper_host_factory.cc.
+ base::FilePath external_path;
+ if (ppapi::UnpackMessage<PpapiHostMsg_FileRef_CreateExternal>(
+ nested_msg, &external_path)) {
+ resource_host.reset(new PepperFileRefHost(
+ host, instance, params.pp_resource(), external_path));
+ }
+ } else if (nested_msg.type() ==
+ PpapiHostMsg_FileSystem_CreateFromRenderer::ID) {
+ // Similarly, FileSystem_CreateFromRenderer is only permitted from the
+ // renderer.
+ std::string root_url;
+ PP_FileSystemType file_system_type;
+ if (ppapi::UnpackMessage<PpapiHostMsg_FileSystem_CreateFromRenderer>(
+ nested_msg, &root_url, &file_system_type)) {
+ PepperFileSystemBrowserHost* browser_host =
+ new PepperFileSystemBrowserHost(host,
+ instance,
+ params.pp_resource(),
+ file_system_type);
+ resource_host.reset(browser_host);
+ // Open the file system resource host. This is an asynchronous
+ // operation, and we must only add the pending resource host and
+ // send the message once it completes.
+ browser_host->OpenExisting(
+ GURL(root_url),
+ base::Bind(
+ &PendingHostCreator::AddPendingResourceHost,
+ creator,
+ i,
+ base::Passed(&resource_host)));
+ // Do not fall through; the fall-through case adds the pending
+ // resource host to the list. We must do this asynchronously.
+ continue;
+ }
}
+ }
- if (resource_host.get()) {
- pending_resource_host_ids[i] =
- host->GetPpapiHost()->AddPendingResourceHost(resource_host.Pass());
- }
+ if (!resource_host.get()) {
+ resource_host = host->GetPpapiHost()->CreateResourceHost(
+ params, instance, nested_msg);
}
+
+ if (resource_host.get())
+ creator->AddPendingResourceHost(i, resource_host.Pass());
}
- Send(new PpapiHostMsg_CreateResourceHostsFromHostReply(
- routing_id, params.sequence(), pending_resource_host_ids));
+ // Note: All of the pending host IDs that were added as part of this
+ // operation will automatically be sent to the plugin when |creator| is
+ // released. This may happen immediately, or (if there are asynchronous
+ // requests to create resource hosts), once all of them complete.
}
void PepperRendererConnection::OnMsgDidCreateInProcessInstance(
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc
index 5816ce4831f..4e1306eb816 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc
@@ -13,12 +13,12 @@ namespace content {
namespace {
template <typename CanRead, typename CanWrite,
- typename CanCreate, typename CanCreateWrite,
+ typename CanCreate, typename CanCreateReadWrite,
typename FileID>
bool CanOpenFileWithPepperFlags(CanRead can_read,
CanWrite can_write,
CanCreate can_create,
- CanCreateWrite can_create_write,
+ CanCreateReadWrite can_create_read_write,
int pp_open_flags,
int child_id,
const FileID& file) {
@@ -39,7 +39,7 @@ bool CanOpenFileWithPepperFlags(CanRead can_read,
return false;
// TODO(tommycli): Maybe tighten up required permission. crbug.com/284792
- if (pp_append && !(policy->*can_create_write)(child_id, file))
+ if (pp_append && !(policy->*can_create_read_write)(child_id, file))
return false;
if (pp_truncate && !pp_write)
@@ -50,10 +50,10 @@ bool CanOpenFileWithPepperFlags(CanRead can_read,
return (policy->*can_create)(child_id, file);
} else {
// Asks for too much, but this is the only grant that allows overwrite.
- return (policy->*can_create_write)(child_id, file);
+ return (policy->*can_create_read_write)(child_id, file);
}
} else if (pp_truncate) {
- return (policy->*can_create_write)(child_id, file);
+ return (policy->*can_create_read_write)(child_id, file);
}
return true;
@@ -65,9 +65,9 @@ bool CanOpenWithPepperFlags(int pp_open_flags, int child_id,
const base::FilePath& file) {
return CanOpenFileWithPepperFlags(
&ChildProcessSecurityPolicyImpl::CanReadFile,
- &ChildProcessSecurityPolicyImpl::CanWriteFile,
- &ChildProcessSecurityPolicyImpl::CanCreateFile,
- &ChildProcessSecurityPolicyImpl::CanCreateWriteFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile,
pp_open_flags, child_id, file);
}
@@ -77,7 +77,7 @@ bool CanOpenFileSystemURLWithPepperFlags(int pp_open_flags, int child_id,
&ChildProcessSecurityPolicyImpl::CanReadFileSystemFile,
&ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile,
&ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile,
- &ChildProcessSecurityPolicyImpl::CanCreateWriteFileSystemFile,
+ &ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile,
pp_open_flags, child_id, url);
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc
index 1b2aa668f04..ceeb73e3df1 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc
@@ -82,13 +82,9 @@ int32_t FontMessageFilter::OnHostMsgGetFontFamilies(
// Sort the names in case the host platform returns them out of order.
std::sort(font_families.begin(), font_families.end());
- int32_t result = base::checked_numeric_cast<int32_t>(font_families.size());
- ppapi::host::ReplyMessageContext reply_context =
- context->MakeReplyMessageContext();
- reply_context.params.set_result(result);
context->reply_msg =
PpapiPluginMsg_TrueTypeFontSingleton_GetFontFamiliesReply(font_families);
- return result;
+ return base::checked_numeric_cast<int32_t>(font_families.size());
}
int32_t FontMessageFilter::OnHostMsgGetFontsInFamily(
@@ -98,14 +94,10 @@ int32_t FontMessageFilter::OnHostMsgGetFontsInFamily(
std::vector<ppapi::proxy::SerializedTrueTypeFontDesc> fonts_in_family;
GetFontsInFamily_SlowBlocking(family, &fonts_in_family);
- int32_t result = base::checked_numeric_cast<int32_t>(fonts_in_family.size());
- ppapi::host::ReplyMessageContext reply_context =
- context->MakeReplyMessageContext();
- reply_context.params.set_result(result);
context->reply_msg =
PpapiPluginMsg_TrueTypeFontSingleton_GetFontsInFamilyReply(
fonts_in_family);
- return result;
+ return base::checked_numeric_cast<int32_t>(fonts_in_family.size());
}
} // namespace
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_ozone.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_ozone.cc
new file mode 100644
index 00000000000..12e2c61a8cf
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_ozone.cc
@@ -0,0 +1,20 @@
+// 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 "base/logging.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font_list.h"
+
+namespace content {
+
+void GetFontFamilies_SlowBlocking(std::vector<std::string>* font_families) {
+ NOTIMPLEMENTED();
+}
+
+void GetFontsInFamily_SlowBlocking(
+ const std::string& family,
+ std::vector<ppapi::proxy::SerializedTrueTypeFontDesc>* fonts_in_family) {
+ NOTIMPLEMENTED();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_linux.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_pango.cc
index 24c3f5df2f5..cd1a5e579dc 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_linux.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_pango.cc
@@ -54,6 +54,7 @@ void GetFontsInFamily_SlowBlocking(
desc.charset = PP_TRUETYPEFONTCHARSET_DEFAULT;
fonts_in_family->push_back(desc);
+ ::pango_font_description_free(font_desc);
}
g_free(font_faces);
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc
index e5cdcc6b01f..3530e1e1b5e 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc
@@ -73,7 +73,7 @@ void GetFontsInFamily_SlowBlocking(const std::string& family,
LOGFONTW logfont;
memset(&logfont, 0, sizeof(logfont));
logfont.lfCharSet = DEFAULT_CHARSET;
- string16 family16 = UTF8ToUTF16(family);
+ base::string16 family16 = UTF8ToUTF16(family);
memcpy(&logfont.lfFaceName, &family16[0], sizeof(logfont.lfFaceName));
base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
::EnumFontFamiliesExW(hdc, &logfont, (FONTENUMPROCW)&EnumFontsInFamilyProc,
diff --git a/chromium/content/browser/renderer_host/pepper/quota_reservation.cc b/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
new file mode 100644
index 00000000000..221b374f110
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
@@ -0,0 +1,147 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/quota_reservation.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "content/public/browser/browser_thread.h"
+#include "webkit/browser/fileapi/file_system_operation_runner.h"
+#include "webkit/browser/fileapi/quota/open_file_handle.h"
+#include "webkit/browser/fileapi/quota/quota_reservation.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+namespace content {
+
+// static
+scoped_refptr<QuotaReservation> QuotaReservation::Create(
+ scoped_refptr<fileapi::FileSystemContext> file_system_context,
+ const GURL& origin_url,
+ fileapi::FileSystemType type) {
+ return scoped_refptr<QuotaReservation>(new QuotaReservation(
+ file_system_context, origin_url, type));
+}
+
+QuotaReservation::QuotaReservation(
+ scoped_refptr<fileapi::FileSystemContext> file_system_context,
+ const GURL& origin_url,
+ fileapi::FileSystemType file_system_type)
+ : file_system_context_(file_system_context) {
+ quota_reservation_ =
+ file_system_context->CreateQuotaReservationOnFileTaskRunner(
+ origin_url,
+ file_system_type);
+}
+
+// For unit testing only.
+QuotaReservation::QuotaReservation(
+ scoped_refptr<fileapi::QuotaReservation> quota_reservation,
+ const GURL& /* origin_url */,
+ fileapi::FileSystemType /* file_system_type */)
+ : quota_reservation_(quota_reservation) {
+}
+
+QuotaReservation::~QuotaReservation() {
+ // We should have no open files at this point.
+ DCHECK(files_.size() == 0);
+ for (FileMap::iterator it = files_.begin(); it != files_.end(); ++ it)
+ delete it->second;
+}
+
+int64_t QuotaReservation::OpenFile(int32_t id,
+ const fileapi::FileSystemURL& url) {
+ base::FilePath platform_file_path;
+ if (file_system_context_) {
+ base::PlatformFileError error =
+ file_system_context_->operation_runner()->SyncGetPlatformPath(
+ url, &platform_file_path);
+ if (error != base::PLATFORM_FILE_OK) {
+ NOTREACHED();
+ return 0;
+ }
+ } else {
+ // For test.
+ platform_file_path = url.path();
+ }
+
+ scoped_ptr<fileapi::OpenFileHandle> file_handle =
+ quota_reservation_->GetOpenFileHandle(platform_file_path);
+ std::pair<FileMap::iterator, bool> insert_result =
+ files_.insert(std::make_pair(id, file_handle.get()));
+ if (insert_result.second) {
+ int64_t max_written_offset = file_handle->base_file_size();
+ ignore_result(file_handle.release());
+ return max_written_offset;
+ }
+ NOTREACHED();
+ return 0;
+}
+
+void QuotaReservation::CloseFile(int32_t id,
+ int64_t max_written_offset) {
+ FileMap::iterator it = files_.find(id);
+ if (it != files_.end()) {
+ it->second->UpdateMaxWrittenOffset(max_written_offset);
+ delete it->second;
+ files_.erase(it);
+ } else {
+ NOTREACHED();
+ }
+}
+
+void QuotaReservation::ReserveQuota(
+ int64_t amount,
+ const OffsetMap& max_written_offsets,
+ const ReserveQuotaCallback& callback) {
+ for (FileMap::iterator it = files_.begin(); it != files_.end(); ++ it) {
+ OffsetMap::const_iterator offset_it = max_written_offsets.find(it->first);
+ if (offset_it != max_written_offsets.end())
+ it->second->UpdateMaxWrittenOffset(offset_it->second);
+ else
+ NOTREACHED();
+ }
+
+ quota_reservation_->RefreshReservation(
+ amount,
+ base::Bind(&QuotaReservation::GotReservedQuota,
+ this,
+ callback));
+}
+
+void QuotaReservation::GotReservedQuota(
+ const ReserveQuotaCallback& callback,
+ base::PlatformFileError error) {
+ OffsetMap max_written_offsets;
+ for (FileMap::iterator it = files_.begin(); it != files_.end(); ++ it) {
+ max_written_offsets.insert(
+ std::make_pair(it->first, it->second->base_file_size()));
+ }
+
+ if (file_system_context_) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback,
+ quota_reservation_->remaining_quota(),
+ max_written_offsets));
+ } else {
+ // Unit testing code path.
+ callback.Run(quota_reservation_->remaining_quota(), max_written_offsets);
+ }
+}
+
+void QuotaReservation::DeleteOnCorrectThread() const {
+ if (file_system_context_ &&
+ !file_system_context_->
+ default_file_task_runner()->RunsTasksOnCurrentThread()) {
+ file_system_context_->default_file_task_runner()->DeleteSoon(
+ FROM_HERE,
+ this);
+ } else {
+ // We're on the right thread to delete, or unit test.
+ delete this;
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/quota_reservation.h b/chromium/content/browser/renderer_host/pepper/quota_reservation.h
new file mode 100644
index 00000000000..845b868d345
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation.h
@@ -0,0 +1,97 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_RESERVATION_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_RESERVATION_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/platform_file.h"
+#include "content/common/content_export.h"
+#include "ppapi/c/pp_stdint.h" // For int64_t on Windows.
+#include "url/gurl.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+
+namespace fileapi {
+class FileSystemURL;
+class OpenFileHandle;
+class QuotaReservation;
+}
+
+namespace content {
+
+struct QuotaReservationDeleter;
+
+// This class holds a QuotaReservation and manages OpenFileHandles for checking
+// quota. It should be created, used, and destroyed on a FileSystemContext's
+// default_file_task_runner() instance. This is a RefCountedThreadSafe object
+// because it needs to be passed to the file thread and kept alive during
+// potentially long-running quota operations.
+class CONTENT_EXPORT QuotaReservation
+ : public base::RefCountedThreadSafe<QuotaReservation,
+ QuotaReservationDeleter> {
+ public:
+ // Static method to facilitate construction on the file task runner.
+ static scoped_refptr<QuotaReservation> Create(
+ scoped_refptr<fileapi::FileSystemContext> file_system_context,
+ const GURL& origin_url,
+ fileapi::FileSystemType file_system_type);
+
+ // Opens a file with the given id and path and returns its current size.
+ int64_t OpenFile(int32_t id, const fileapi::FileSystemURL& url);
+ // Closes the file opened by OpenFile with the given id.
+ void CloseFile(int32_t id, int64_t max_written_offset);
+ // Refreshes the quota reservation to a new amount. A map that associates file
+ // ids with maximum written offsets is provided as input. The callback will
+ // receive a similar map with the updated file sizes.
+ typedef std::map<int32_t, int64_t> OffsetMap;
+ typedef base::Callback<void(int64_t, const OffsetMap&)> ReserveQuotaCallback;
+ void ReserveQuota(int64_t amount,
+ const OffsetMap& max_written_offsets,
+ const ReserveQuotaCallback& callback);
+ private:
+ friend class base::RefCountedThreadSafe<QuotaReservation,
+ QuotaReservationDeleter>;
+ friend class base::DeleteHelper<QuotaReservation>;
+ friend struct QuotaReservationDeleter;
+ friend class QuotaReservationTest;
+
+ QuotaReservation(
+ scoped_refptr<fileapi::FileSystemContext> file_system_context,
+ const GURL& origin_url,
+ fileapi::FileSystemType file_system_type);
+
+ // For unit testing only. A QuotaReservation intended for unit testing will
+ // have file_system_context_ == NULL.
+ QuotaReservation(
+ scoped_refptr<fileapi::QuotaReservation> quota_reservation,
+ const GURL& origin_url,
+ fileapi::FileSystemType file_system_type);
+
+ ~QuotaReservation();
+
+ void GotReservedQuota(const ReserveQuotaCallback& callback,
+ base::PlatformFileError error);
+
+ void DeleteOnCorrectThread() const;
+
+ scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<fileapi::QuotaReservation> quota_reservation_;
+ typedef std::map<int32_t, fileapi::OpenFileHandle*> FileMap;
+ FileMap files_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuotaReservation);
+};
+
+struct QuotaReservationDeleter {
+ static void Destruct(const QuotaReservation* quota_reservation) {
+ quota_reservation->DeleteOnCorrectThread();
+ }
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_RESERVATION_H_
diff --git a/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc b/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
new file mode 100644
index 00000000000..3f760e55664
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
@@ -0,0 +1,248 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/pepper/quota_reservation.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/quota/quota_reservation.h"
+
+using fileapi::FileSystemType;
+using fileapi::QuotaReservationManager;
+
+namespace content {
+
+namespace {
+
+const char kOrigin[] = "http://example.com";
+const FileSystemType kType = fileapi::kFileSystemTypeTemporary;
+
+const base::FilePath::StringType file1_name = FILE_PATH_LITERAL("file1");
+const base::FilePath::StringType file2_name = FILE_PATH_LITERAL("file2");
+const base::FilePath::StringType file3_name = FILE_PATH_LITERAL("file3");
+const int kFile1ID = 1;
+const int kFile2ID = 2;
+const int kFile3ID = 3;
+
+class FakeBackend : public QuotaReservationManager::QuotaBackend {
+ public:
+ FakeBackend() {}
+ virtual ~FakeBackend() {}
+
+ virtual void ReserveQuota(
+ const GURL& origin,
+ FileSystemType type,
+ int64 delta,
+ const QuotaReservationManager::ReserveQuotaCallback& callback) OVERRIDE {
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(callback), base::PLATFORM_FILE_OK));
+ }
+
+ virtual void ReleaseReservedQuota(const GURL& origin,
+ FileSystemType type,
+ int64 size) OVERRIDE {
+ }
+
+ virtual void CommitQuotaUsage(const GURL& origin,
+ FileSystemType type,
+ int64 delta) OVERRIDE {
+ }
+
+ virtual void IncrementDirtyCount(const GURL& origin,
+ FileSystemType type) OVERRIDE {}
+ virtual void DecrementDirtyCount(const GURL& origin,
+ FileSystemType type) OVERRIDE {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FakeBackend);
+};
+
+} // namespace
+
+class QuotaReservationTest : public testing::Test {
+ public:
+ QuotaReservationTest() {}
+ virtual ~QuotaReservationTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(work_dir_.CreateUniqueTempDir());
+
+ reservation_manager_.reset(new QuotaReservationManager(
+ scoped_ptr<QuotaReservationManager::QuotaBackend>(new FakeBackend)));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ reservation_manager_.reset();
+ }
+
+ base::FilePath MakeFilePath(const base::FilePath::StringType& file_name) {
+ return work_dir_.path().Append(file_name);
+ }
+
+ fileapi::FileSystemURL MakeFileSystemURL(
+ const base::FilePath::StringType& file_name) {
+ return fileapi::FileSystemURL::CreateForTest(
+ GURL(kOrigin), kType, MakeFilePath(file_name));
+ }
+
+ scoped_refptr<QuotaReservation> CreateQuotaReservation(
+ scoped_refptr<fileapi::QuotaReservation> reservation,
+ const GURL& origin,
+ FileSystemType type) {
+ // Sets reservation_ as a side effect.
+ return scoped_refptr<QuotaReservation>(
+ new QuotaReservation(reservation, origin, type));
+ }
+
+ void SetFileSize(const base::FilePath::StringType& file_name, int64 size) {
+ bool created = false;
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ base::PlatformFile file = CreatePlatformFile(
+ MakeFilePath(file_name),
+ base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE,
+ &created, &error);
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+ ASSERT_TRUE(base::TruncatePlatformFile(file, size));
+ ASSERT_TRUE(base::ClosePlatformFile(file));
+ }
+
+ QuotaReservationManager* reservation_manager() {
+ return reservation_manager_.get();
+ }
+
+ private:
+ base::MessageLoop message_loop_;
+ base::ScopedTempDir work_dir_;
+ scoped_ptr<fileapi::QuotaReservationManager> reservation_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuotaReservationTest);
+};
+
+void GotReservedQuota(
+ int64* reserved_quota_ptr,
+ QuotaReservation::OffsetMap* maximum_written_offsets_ptr,
+ int64 reserved_quota,
+ const QuotaReservation::OffsetMap& maximum_written_offsets) {
+ *reserved_quota_ptr = reserved_quota;
+ *maximum_written_offsets_ptr = maximum_written_offsets;
+}
+
+void ReserveQuota(
+ scoped_refptr<QuotaReservation> quota_reservation,
+ int64 amount,
+ int64* reserved_quota,
+ QuotaReservation::OffsetMap* max_written_offsets) {
+ quota_reservation->ReserveQuota(amount,
+ *max_written_offsets,
+ base::Bind(&GotReservedQuota,
+ reserved_quota,
+ max_written_offsets));
+ base::RunLoop().RunUntilIdle();
+}
+
+// Tests that:
+// 1) We can reserve quota with no files open.
+// 2) Open a file, grow it, close it, and reserve quota with correct sizes.
+TEST_F(QuotaReservationTest, DISABLED_ReserveQuota) {
+ GURL origin(kOrigin);
+ FileSystemType type = kType;
+
+ scoped_refptr<fileapi::QuotaReservation> reservation(
+ reservation_manager()->CreateReservation(origin, type));
+ scoped_refptr<QuotaReservation> test =
+ CreateQuotaReservation(reservation, origin, type);
+
+ // Reserve quota with no files open.
+ int64 amount = 100;
+ int64 reserved_quota;
+ QuotaReservation::OffsetMap max_written_offsets;
+ ReserveQuota(test, amount, &reserved_quota, &max_written_offsets);
+ EXPECT_EQ(amount, reserved_quota);
+ EXPECT_EQ(0U, max_written_offsets.size());
+
+ // Open a file, refresh the reservation, extend the file, and close it.
+ int64 file_size = 10;
+ SetFileSize(file1_name, file_size);
+ int64 open_file_size = test->OpenFile(kFile1ID,
+ MakeFileSystemURL(file1_name));
+ EXPECT_EQ(file_size, open_file_size);
+
+ max_written_offsets[kFile1ID] = file_size; // 1 file open.
+ ReserveQuota(test, amount, &reserved_quota, &max_written_offsets);
+ EXPECT_EQ(amount, reserved_quota);
+ EXPECT_EQ(1U, max_written_offsets.size());
+ EXPECT_EQ(file_size, max_written_offsets[kFile1ID]);
+
+ int64 new_file_size = 30;
+ SetFileSize(file1_name, new_file_size);
+
+ EXPECT_EQ(amount, reservation->remaining_quota());
+ test->CloseFile(kFile1ID, new_file_size);
+ EXPECT_EQ(amount - (new_file_size - file_size),
+ reservation->remaining_quota());
+}
+
+// Tests that:
+// 1) We can open and close multiple files.
+TEST_F(QuotaReservationTest, DISABLED_MultipleFiles) {
+ GURL origin(kOrigin);
+ FileSystemType type = kType;
+
+ scoped_refptr<fileapi::QuotaReservation> reservation(
+ reservation_manager()->CreateReservation(origin, type));
+ scoped_refptr<QuotaReservation> test =
+ CreateQuotaReservation(reservation, origin, type);
+
+ // Open some files of different sizes.
+ int64 file1_size = 10;
+ SetFileSize(file1_name, file1_size);
+ int64 open_file1_size = test->OpenFile(kFile1ID,
+ MakeFileSystemURL(file1_name));
+ EXPECT_EQ(file1_size, open_file1_size);
+ int64 file2_size = 20;
+ SetFileSize(file2_name, file2_size);
+ int64 open_file2_size = test->OpenFile(kFile2ID,
+ MakeFileSystemURL(file2_name));
+ EXPECT_EQ(file2_size, open_file2_size);
+ int64 file3_size = 30;
+ SetFileSize(file3_name, file3_size);
+ int64 open_file3_size = test->OpenFile(kFile3ID,
+ MakeFileSystemURL(file3_name));
+ EXPECT_EQ(file3_size, open_file3_size);
+
+ // Reserve quota.
+ int64 amount = 100;
+ int64 reserved_quota;
+ QuotaReservation::OffsetMap max_written_offsets;
+ max_written_offsets[kFile1ID] = file1_size; // 3 files open.
+ max_written_offsets[kFile2ID] = file2_size;
+ max_written_offsets[kFile3ID] = file3_size;
+
+ ReserveQuota(test, amount, &reserved_quota, &max_written_offsets);
+ EXPECT_EQ(amount, reserved_quota);
+ EXPECT_EQ(3U, max_written_offsets.size());
+ EXPECT_EQ(file1_size, max_written_offsets[kFile1ID]);
+ EXPECT_EQ(file2_size, max_written_offsets[kFile2ID]);
+ EXPECT_EQ(file3_size, max_written_offsets[kFile3ID]);
+
+ test->CloseFile(kFile2ID, file2_size);
+
+ max_written_offsets.erase(max_written_offsets.find(kFile2ID));
+ ReserveQuota(test, amount, &reserved_quota, &max_written_offsets);
+ EXPECT_EQ(amount, reserved_quota);
+ EXPECT_EQ(2U, max_written_offsets.size());
+ EXPECT_EQ(file1_size, max_written_offsets[kFile1ID]);
+ EXPECT_EQ(file3_size, max_written_offsets[kFile3ID]);
+
+ test->CloseFile(kFile1ID, file1_size);
+ test->CloseFile(kFile3ID, file3_size);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_frame_host_impl.cc b/chromium/content/browser/renderer_host/render_frame_host_impl.cc
deleted file mode 100644
index ec621c10dca..00000000000
--- a/chromium/content/browser/renderer_host/render_frame_host_impl.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/render_frame_host_impl.h"
-
-#include "base/containers/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-
-namespace content {
-
-// The (process id, routing id) pair that identifies one RenderFrame.
-typedef std::pair<int32, int32> RenderFrameHostID;
-typedef base::hash_map<RenderFrameHostID, RenderFrameHostImpl*>
- RoutingIDFrameMap;
-static base::LazyInstance<RoutingIDFrameMap> g_routing_id_frame_map =
- LAZY_INSTANCE_INITIALIZER;
-
-// static
-RenderFrameHostImpl* RenderFrameHostImpl::FromID(
- int process_id, int routing_id) {
- RoutingIDFrameMap* frames = g_routing_id_frame_map.Pointer();
- RoutingIDFrameMap::iterator it = frames->find(
- RenderFrameHostID(process_id, routing_id));
- return it == frames->end() ? NULL : it->second;
-}
-
-RenderFrameHostImpl::RenderFrameHostImpl(
- RenderViewHostImpl* render_view_host,
- int routing_id,
- bool is_swapped_out)
- : render_view_host_(render_view_host),
- routing_id_(routing_id),
- is_swapped_out_(is_swapped_out) {
- GetProcess()->AddRoute(routing_id_, this);
- g_routing_id_frame_map.Get().insert(std::make_pair(
- RenderFrameHostID(GetProcess()->GetID(), routing_id_),
- this));
-}
-
-RenderFrameHostImpl::~RenderFrameHostImpl() {
- GetProcess()->RemoveRoute(routing_id_);
- g_routing_id_frame_map.Get().erase(
- RenderFrameHostID(GetProcess()->GetID(), routing_id_));
-
-}
-
-bool RenderFrameHostImpl::Send(IPC::Message* message) {
- return GetProcess()->Send(message);
-}
-
-bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
- return false;
-}
-
-void RenderFrameHostImpl::Init() {
- GetProcess()->ResumeRequestsForView(routing_id());
-}
-
-RenderProcessHost* RenderFrameHostImpl::GetProcess() const {
- // TODO(ajwong): This should return its own process once cross-process
- // subframe navigations are supported.
- return render_view_host_->GetProcess();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_frame_host_impl.h b/chromium/content/browser/renderer_host/render_frame_host_impl.h
deleted file mode 100644
index 78df3331efd..00000000000
--- a/chromium/content/browser/renderer_host/render_frame_host_impl.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_FRAME_HOST_IMPL_H_
-#define CONTENT_BROWSER_RENDERER_HOST_RENDER_FRAME_HOST_IMPL_H_
-
-#include "base/compiler_specific.h"
-#include "content/public/browser/render_frame_host.h"
-
-namespace content {
-
-class RenderProcessHost;
-class RenderViewHostImpl;
-
-class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
- public:
- static RenderFrameHostImpl* FromID(int process_id, int routing_id);
-
- RenderFrameHostImpl(RenderViewHostImpl* render_view_host,
- int routing_id,
- bool is_swapped_out);
- virtual ~RenderFrameHostImpl();
-
- // IPC::Sender
- virtual bool Send(IPC::Message* msg) OVERRIDE;
-
- // IPC::Listener
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
-
- void Init();
- RenderProcessHost* GetProcess() const;
- int routing_id() const { return routing_id_; }
-
- private:
- bool is_swapped_out() { return is_swapped_out_; }
-
- RenderViewHostImpl* render_view_host_; // Not owned. Outlives this object.
- int routing_id_;
- bool is_swapped_out_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderFrameHostImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_FRAME_HOST_IMPL_H_
diff --git a/chromium/content/browser/renderer_host/render_message_filter.cc b/chromium/content/browser/renderer_host/render_message_filter.cc
index 29e1e1f199a..fc084e1d2f3 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.cc
+++ b/chromium/content/browser/renderer_host/render_message_filter.cc
@@ -33,6 +33,8 @@
#include "content/common/child_process_messages.h"
#include "content/common/cookie_data.h"
#include "content/common/desktop_notification_messages.h"
+#include "content/common/frame_messages.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
#include "content/common/media/media_param_traits.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_child_process_host.h"
@@ -68,7 +70,9 @@
#include "ui/gfx/color_profile.h"
#if defined(OS_MACOSX)
+#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h"
#include "content/common/mac/font_descriptor.h"
+#include "ui/gl/io_surface_support_mac.h"
#else
#include "gpu/GLES2/gl2extchromium.h"
#include "third_party/khronos/GLES2/gl2.h"
@@ -90,17 +94,21 @@ using net::CookieStore;
namespace content {
namespace {
+#if defined(ENABLE_PLUGINS)
const int kPluginsRefreshThresholdInSeconds = 3;
+#endif
// When two CPU usage queries arrive within this interval, we sample the CPU
// usage only once and send it as a response for both queries.
static const int64 kCPUUsageSampleIntervalMs = 900;
+#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
// Common functionality for converting a sync renderer message to a callback
// function in the browser. Derive from this, create it on the heap when
@@ -202,6 +210,23 @@ class OpenChannelToPpapiBrokerCallback
int routing_id_;
};
+#if defined(OS_MACOSX)
+void AddBooleanValue(CFMutableDictionaryRef dictionary,
+ const CFStringRef key,
+ bool value) {
+ CFDictionaryAddValue(
+ dictionary, key, value ? kCFBooleanTrue : kCFBooleanFalse);
+}
+
+void AddIntegerValue(CFMutableDictionaryRef dictionary,
+ const CFStringRef key,
+ int32 value) {
+ base::ScopedCFTypeRef<CFNumberRef> number(
+ CFNumberCreate(NULL, kCFNumberSInt32Type, &value));
+ CFDictionaryAddValue(dictionary, key, number.get());
+}
+#endif
+
} // namespace
class RenderMessageFilter::OpenChannelToNpapiPluginCallback
@@ -274,8 +299,8 @@ class RenderMessageFilter::OpenChannelToNpapiPluginCallback
private:
void WriteReplyAndDeleteThis(const IPC::ChannelHandle& handle) {
- ViewHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg(),
- handle, info_);
+ FrameHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg(),
+ handle, info_);
filter()->OnCompletedOpenChannelToNpapiPlugin(this);
SendReplyAndDeleteThis();
}
@@ -321,7 +346,6 @@ RenderMessageFilter::~RenderMessageFilter() {
}
void RenderMessageFilter::OnChannelClosing() {
- BrowserMessageFilter::OnChannelClosing();
#if defined(ENABLE_PLUGINS)
for (std::set<OpenChannelToNpapiPluginCallback*>::iterator it =
plugin_host_clients_.begin(); it != plugin_host_clients_.end(); ++it) {
@@ -342,7 +366,6 @@ void RenderMessageFilter::OnChannelClosing() {
}
void RenderMessageFilter::OnChannelConnected(int32 peer_id) {
- BrowserMessageFilter::OnChannelConnected(peer_id);
base::ProcessHandle handle = PeerHandle();
#if defined(OS_MACOSX)
process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle,
@@ -380,8 +403,8 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl)
#if defined(ENABLE_PLUGINS)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins)
- IPC_MESSAGE_HANDLER(ViewHostMsg_GetPluginInfo, OnGetPluginInfo)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin,
+ IPC_MESSAGE_HANDLER(FrameHostMsg_GetPluginInfo, OnGetPluginInfo)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_OpenChannelToPlugin,
OnOpenChannelToPlugin)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin,
OnOpenChannelToPepperPlugin)
@@ -391,7 +414,6 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
OnDidDeleteOutOfProcessPepperInstance)
IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToPpapiBroker,
OnOpenChannelToPpapiBroker)
- IPC_MESSAGE_HANDLER(ViewHostMsg_AsyncOpenPepperFile, OnAsyncOpenPepperFile)
#endif
IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect,
render_widget_helper_->DidReceiveBackingStoreMsg(message))
@@ -400,6 +422,8 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
OnCheckNotificationPermission)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
OnAllocateSharedMemory)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
+ OnAllocateGpuMemoryBuffer)
#if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, OnAllocTransportDIB)
IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, OnFreeTransportDIB)
@@ -410,8 +434,10 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPUUsage, OnGetCPUUsage)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetAudioHardwareConfig,
OnGetAudioHardwareConfig)
+#if defined(OS_WIN)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetMonitorColorProfile,
OnGetMonitorColorProfile)
+#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvents, OnMediaLogEvents)
IPC_MESSAGE_HANDLER(ViewHostMsg_Are3DAPIsBlocked, OnAre3DAPIsBlocked)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidLose3DContext, OnDidLose3DContext)
@@ -440,8 +466,6 @@ base::TaskRunner* RenderMessageFilter::OverrideTaskRunnerForMessage(
if (message.type() == ViewHostMsg_GetAudioHardwareConfig::ID)
return audio_manager_->GetMessageLoop().get();
#endif
- if (message.type() == ViewHostMsg_AsyncOpenPepperFile::ID)
- return BrowserThread::GetBlockingPool();
return NULL;
}
@@ -456,6 +480,18 @@ void RenderMessageFilter::OnCreateWindow(
int* surface_id,
int64* cloned_session_storage_namespace_id) {
bool no_javascript_access;
+
+ // Merge the additional features into the WebWindowFeatures struct before we
+ // pass it on.
+ blink::WebVector<blink::WebString> additional_features(
+ params.additional_features.size());
+
+ for (size_t i = 0; i < params.additional_features.size(); ++i)
+ additional_features[i] = blink::WebString(params.additional_features[i]);
+
+ blink::WebWindowFeatures features = params.features;
+ features.additionalFeatures.swap(additional_features);
+
bool can_create_window =
GetContentClient()->browser()->CanCreateWindow(
params.opener_url,
@@ -465,7 +501,7 @@ void RenderMessageFilter::OnCreateWindow(
params.target_url,
params.referrer,
params.disposition,
- params.features,
+ features,
params.user_gesture,
params.opener_suppressed,
resource_context_,
@@ -497,7 +533,7 @@ void RenderMessageFilter::OnCreateWindow(
}
void RenderMessageFilter::OnCreateWidget(int opener_id,
- WebKit::WebPopupType popup_type,
+ blink::WebPopupType popup_type,
int* route_id,
int* surface_id) {
render_widget_helper_->CreateNewWidget(
@@ -651,6 +687,7 @@ void RenderMessageFilter::SendLoadFontReply(IPC::Message* reply,
}
#endif // OS_MACOSX
+#if defined(ENABLE_PLUGINS)
void RenderMessageFilter::OnGetPlugins(
bool refresh,
IPC::Message* reply_msg) {
@@ -702,7 +739,7 @@ void RenderMessageFilter::GetPluginsCallback(
}
void RenderMessageFilter::OnGetPluginInfo(
- int routing_id,
+ int render_frame_id,
const GURL& url,
const GURL& page_url,
const std::string& mime_type,
@@ -711,12 +748,12 @@ void RenderMessageFilter::OnGetPluginInfo(
std::string* actual_mime_type) {
bool allow_wildcard = true;
*found = plugin_service_->GetPluginInfo(
- render_process_id_, routing_id, resource_context_,
+ render_process_id_, render_frame_id, resource_context_,
url, page_url, mime_type, allow_wildcard,
NULL, info, actual_mime_type);
}
-void RenderMessageFilter::OnOpenChannelToPlugin(int routing_id,
+void RenderMessageFilter::OnOpenChannelToPlugin(int render_frame_id,
const GURL& url,
const GURL& policy_url,
const std::string& mime_type,
@@ -726,7 +763,7 @@ void RenderMessageFilter::OnOpenChannelToPlugin(int routing_id,
DCHECK(!ContainsKey(plugin_host_clients_, client));
plugin_host_clients_.insert(client);
plugin_service_->OpenChannelToNpapiPlugin(
- render_process_id_, routing_id,
+ render_process_id_, render_frame_id,
url, policy_url, mime_type, client);
}
@@ -791,6 +828,7 @@ void RenderMessageFilter::OnOpenChannelToPpapiBroker(
path,
new OpenChannelToPpapiBrokerCallback(this, routing_id));
}
+#endif // defined(ENABLE_PLUGINS)
void RenderMessageFilter::OnGenerateRoutingID(int* route_id) {
*route_id = render_widget_helper_->GetNextRoutingID();
@@ -818,23 +856,24 @@ void RenderMessageFilter::OnGetAudioHardwareConfig(
media::AudioManagerBase::kDefaultDeviceId);
}
-void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) {
#if defined(OS_WIN)
+void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
if (BackingStoreWin::ColorManagementEnabled())
return;
-#endif
*profile = g_color_profile.Get().profile();
}
+#endif
void RenderMessageFilter::OnDownloadUrl(const IPC::Message& message,
const GURL& url,
const Referrer& referrer,
- const string16& suggested_name) {
+ const base::string16& suggested_name) {
scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
save_info->suggested_name = suggested_name;
scoped_ptr<net::URLRequest> request(
- resource_context_->GetRequestContext()->CreateRequest(url, NULL));
+ resource_context_->GetRequestContext()->CreateRequest(
+ url, net::DEFAULT_PRIORITY, NULL));
RecordDownloadSource(INITIATED_BY_RENDERER);
resource_dispatcher_host_->BeginDownload(
request.Pass(),
@@ -856,7 +895,7 @@ void RenderMessageFilter::OnCheckNotificationPermission(
CheckDesktopNotificationPermission(source_origin, resource_context_,
render_process_id_);
#else
- *result = WebKit::WebNotificationPresenter::PermissionAllowed;
+ *result = blink::WebNotificationPresenter::PermissionAllowed;
#endif
}
@@ -950,71 +989,44 @@ void RenderMessageFilter::OnKeygen(uint32 key_size_index,
return;
}
+ resource_context_->CreateKeygenHandler(
+ key_size_in_bits,
+ challenge_string,
+ url,
+ base::Bind(
+ &RenderMessageFilter::PostKeygenToWorkerThread, this, reply_msg));
+}
+
+void RenderMessageFilter::PostKeygenToWorkerThread(
+ IPC::Message* reply_msg,
+ scoped_ptr<net::KeygenHandler> keygen_handler) {
VLOG(1) << "Dispatching keygen task to worker pool.";
// Dispatch to worker pool, so we do not block the IO thread.
if (!base::WorkerPool::PostTask(
FROM_HERE,
- base::Bind(
- &RenderMessageFilter::OnKeygenOnWorkerThread, this,
- key_size_in_bits, challenge_string, url, reply_msg),
+ base::Bind(&RenderMessageFilter::OnKeygenOnWorkerThread,
+ this,
+ base::Passed(&keygen_handler),
+ reply_msg),
true)) {
NOTREACHED() << "Failed to dispatch keygen task to worker pool";
ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string());
Send(reply_msg);
- return;
}
}
void RenderMessageFilter::OnKeygenOnWorkerThread(
- int key_size_in_bits,
- const std::string& challenge_string,
- const GURL& url,
+ scoped_ptr<net::KeygenHandler> keygen_handler,
IPC::Message* reply_msg) {
DCHECK(reply_msg);
// Generate a signed public key and challenge, then send it back.
- net::KeygenHandler keygen_handler(key_size_in_bits, challenge_string, url);
-
-#if defined(USE_NSS)
- // Attach a password delegate so we can authenticate.
- keygen_handler.set_crypto_module_password_delegate(
- GetContentClient()->browser()->GetCryptoPasswordDelegate(url));
-#endif // defined(USE_NSS)
-
ViewHostMsg_Keygen::WriteReplyParams(
reply_msg,
- keygen_handler.GenKeyAndSignChallenge());
+ keygen_handler->GenKeyAndSignChallenge());
Send(reply_msg);
}
-void RenderMessageFilter::OnAsyncOpenPepperFile(int routing_id,
- const base::FilePath& path,
- int pp_open_flags,
- int message_id) {
- int platform_file_flags = 0;
- if (!CanOpenWithPepperFlags(pp_open_flags, render_process_id_, path) ||
- !ppapi::PepperFileOpenFlagsToPlatformFileFlags(
- pp_open_flags, &platform_file_flags)) {
- DLOG(ERROR) <<
- "Bad pp_open_flags in ViewMsgHost_AsyncOpenPepperFile message: " <<
- pp_open_flags;
- RecordAction(UserMetricsAction("BadMessageTerminate_AOF"));
- BadMessageReceived();
- return;
- }
-
- base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
- base::PlatformFile file = base::CreatePlatformFile(
- path, platform_file_flags, NULL, &error_code);
- IPC::PlatformFileForTransit file_for_transit =
- file != base::kInvalidPlatformFileValue ?
- IPC::GetFileHandleForProcess(file, PeerHandle(), true) :
- IPC::InvalidPlatformFileForTransit();
-
- Send(new ViewMsg_AsyncOpenPepperFile_ACK(
- routing_id, error_code, file_for_transit, message_id));
-}
-
void RenderMessageFilter::OnMediaLogEvents(
const std::vector<media::MediaLogEvent>& events) {
if (media_internals_)
@@ -1126,7 +1138,7 @@ void RenderMessageFilter::OnDidLose3DContext(
#if defined(OS_WIN)
void RenderMessageFilter::OnPreCacheFontCharacters(const LOGFONT& font,
- const string16& str) {
+ const base::string16& str) {
// First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too.
// Except that for True Type fonts,
// GetTextMetrics will not load the font in memory.
@@ -1168,4 +1180,80 @@ void RenderMessageFilter::OnWebAudioMediaCodec(
true);
}
#endif
+
+void RenderMessageFilter::OnAllocateGpuMemoryBuffer(
+ uint32 width,
+ uint32 height,
+ uint32 internalformat,
+ gfx::GpuMemoryBufferHandle* handle) {
+ if (!GpuMemoryBufferImpl::IsFormatValid(internalformat)) {
+ handle->type = gfx::EMPTY_BUFFER;
+ return;
+ }
+
+#if defined(OS_MACOSX)
+ if (GpuMemoryBufferImplIOSurface::IsFormatSupported(internalformat)) {
+ IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
+ if (io_surface_support) {
+ base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
+ properties.reset(
+ CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ AddIntegerValue(properties,
+ io_surface_support->GetKIOSurfaceWidth(),
+ width);
+ AddIntegerValue(properties,
+ io_surface_support->GetKIOSurfaceHeight(),
+ height);
+ AddIntegerValue(properties,
+ io_surface_support->GetKIOSurfaceBytesPerElement(),
+ GpuMemoryBufferImpl::BytesPerPixel(internalformat));
+ AddIntegerValue(properties,
+ io_surface_support->GetKIOSurfacePixelFormat(),
+ GpuMemoryBufferImplIOSurface::PixelFormat(
+ internalformat));
+ // TODO(reveman): Remove this when using a mach_port_t to transfer
+ // IOSurface to renderer process. crbug.com/323304
+ AddBooleanValue(properties,
+ io_surface_support->GetKIOSurfaceIsGlobal(),
+ true);
+
+ base::ScopedCFTypeRef<CFTypeRef> io_surface(
+ io_surface_support->IOSurfaceCreate(properties));
+ if (io_surface) {
+ handle->type = gfx::IO_SURFACE_BUFFER;
+ handle->io_surface_id = io_surface_support->IOSurfaceGetID(io_surface);
+
+ // TODO(reveman): This makes the assumption that the renderer will
+ // grab a reference to the surface before sending another message.
+ // crbug.com/325045
+ last_io_surface_ = io_surface;
+ return;
+ }
+ }
+ }
+#endif
+
+ uint64 stride = static_cast<uint64>(width) *
+ GpuMemoryBufferImpl::BytesPerPixel(internalformat);
+ if (stride > std::numeric_limits<uint32>::max()) {
+ handle->type = gfx::EMPTY_BUFFER;
+ return;
+ }
+
+ uint64 buffer_size = stride * static_cast<uint64>(height);
+ if (buffer_size > std::numeric_limits<size_t>::max()) {
+ handle->type = gfx::EMPTY_BUFFER;
+ return;
+ }
+
+ // Fallback to fake GpuMemoryBuffer that is backed by shared memory and
+ // requires an upload before it can be used as a texture.
+ handle->type = gfx::SHARED_MEMORY_BUFFER;
+ ChildProcessHostImpl::AllocateSharedMemory(
+ static_cast<size_t>(buffer_size), PeerHandle(), &handle->handle);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_message_filter.h b/chromium/content/browser/renderer_host/render_message_filter.h
index 4eb986471c9..ed879dc585a 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.h
+++ b/chromium/content/browser/renderer_host/render_message_filter.h
@@ -30,6 +30,7 @@
#include "ui/surface/transport_dib.h"
#if defined(OS_MACOSX)
+#include "base/mac/scoped_cftyperef.h"
#include "content/common/mac/font_loader.h"
#endif
@@ -40,7 +41,7 @@
struct FontDescriptor;
struct ViewHostMsg_CreateWindow_Params;
-namespace WebKit {
+namespace blink {
struct WebScreenInfo;
}
@@ -52,6 +53,7 @@ class TaskRunner;
namespace gfx {
class Rect;
+struct GpuMemoryBufferHandle;
}
namespace media {
@@ -60,6 +62,7 @@ struct MediaLogEvent;
}
namespace net {
+class KeygenHandler;
class URLRequestContext;
class URLRequestContextGetter;
}
@@ -125,7 +128,7 @@ class RenderMessageFilter : public BrowserMessageFilter {
int* surface_id,
int64* cloned_session_storage_namespace_id);
void OnCreateWidget(int opener_id,
- WebKit::WebPopupType popup_type,
+ blink::WebPopupType popup_type,
int* route_id,
int* surface_id);
void OnCreateFullscreenWidget(int opener_id,
@@ -155,20 +158,20 @@ class RenderMessageFilter : public BrowserMessageFilter {
#if defined(OS_WIN)
void OnPreCacheFontCharacters(const LOGFONT& log_font,
- const string16& characters);
+ const base::string16& characters);
#endif
void OnGetPlugins(bool refresh, IPC::Message* reply_msg);
void GetPluginsCallback(IPC::Message* reply_msg,
const std::vector<WebPluginInfo>& plugins);
- void OnGetPluginInfo(int routing_id,
+ void OnGetPluginInfo(int render_frame_id,
const GURL& url,
const GURL& policy_url,
const std::string& mime_type,
bool* found,
WebPluginInfo* info,
std::string* actual_mime_type);
- void OnOpenChannelToPlugin(int routing_id,
+ void OnOpenChannelToPlugin(int render_frame_id,
const GURL& url,
const GURL& policy_url,
const std::string& mime_type,
@@ -189,7 +192,7 @@ class RenderMessageFilter : public BrowserMessageFilter {
void OnDownloadUrl(const IPC::Message& message,
const GURL& url,
const Referrer& referrer,
- const string16& suggested_name);
+ const base::string16& suggested_name);
void OnCheckNotificationPermission(const GURL& source_origin,
int* permission_level);
@@ -198,8 +201,10 @@ class RenderMessageFilter : public BrowserMessageFilter {
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
// Used to ask the browser to allocate a block of shared memory for the
// renderer to send back data in, since shared memory can't be created
@@ -218,15 +223,10 @@ class RenderMessageFilter : public BrowserMessageFilter {
const std::vector<char>& data);
void OnKeygen(uint32 key_size_index, const std::string& challenge_string,
const GURL& url, IPC::Message* reply_msg);
- void OnKeygenOnWorkerThread(
- int key_size_in_bits,
- const std::string& challenge_string,
- const GURL& url,
- IPC::Message* reply_msg);
- void OnAsyncOpenPepperFile(int routing_id,
- const base::FilePath& path,
- int pp_open_flags,
- int message_id);
+ void PostKeygenToWorkerThread(IPC::Message* reply_msg,
+ scoped_ptr<net::KeygenHandler> keygen_handler);
+ void OnKeygenOnWorkerThread(scoped_ptr<net::KeygenHandler> keygen_handler,
+ IPC::Message* reply_msg);
void OnMediaLogEvents(const std::vector<media::MediaLogEvent>&);
// Check the policy for getting cookies. Gets the cookies if allowed.
@@ -262,6 +262,11 @@ class RenderMessageFilter : public BrowserMessageFilter {
uint32_t data_size);
#endif
+ void OnAllocateGpuMemoryBuffer(uint32 width,
+ uint32 height,
+ uint32 internalformat,
+ gfx::GpuMemoryBufferHandle* handle);
+
// Cached resource request dispatcher host and plugin service, guaranteed to
// be non-null if Init succeeds. We do not own the objects, they are managed
// by the BrowserProcess, which has a wider scope than we do.
@@ -302,6 +307,10 @@ class RenderMessageFilter : public BrowserMessageFilter {
media::AudioManager* audio_manager_;
MediaInternals* media_internals_;
+#if defined(OS_MACOSX)
+ base::ScopedCFTypeRef<CFTypeRef> last_io_surface_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(RenderMessageFilter);
};
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 de64924d717..95cfcba2007 100644
--- a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/common/child_process_messages.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
@@ -16,6 +17,18 @@
namespace content {
namespace {
+int RenderProcessHostCount() {
+ content::RenderProcessHost::iterator hosts =
+ content::RenderProcessHost::AllHostsIterator();
+ int count = 0;
+ while (!hosts.IsAtEnd()) {
+ if (hosts.GetCurrentValue()->HasConnection())
+ count++;
+ hosts.Advance();
+ }
+ return count;
+}
+
class RenderProcessHostTest : public ContentBrowserTest {};
// Sometimes the renderer process's ShutdownRequest (corresponding to the
@@ -46,5 +59,32 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
EXPECT_EQ(0U, termination_watcher.size());
}
+IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
+ GuestsAreNotSuitableHosts) {
+ // Set max renderers to 1 to force running out of processes.
+ content::RenderProcessHost::SetMaxRendererProcessCount(1);
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
+ NavigateToURL(shell(), test_url);
+ RenderProcessHost* rph =
+ shell()->web_contents()->GetRenderViewHost()->GetProcess();
+ // Make it believe it's a guest.
+ reinterpret_cast<RenderProcessHostImpl*>(rph)->SetIsGuestForTesting(true);
+ EXPECT_EQ(1, RenderProcessHostCount());
+
+ // Navigate to a different page.
+ GURL::Replacements replace_host;
+ std::string host_str("localhost"); // Must stay in scope with replace_host.
+ replace_host.SetHostStr(host_str);
+ GURL another_url = embedded_test_server()->GetURL("/simple_page.html");
+ another_url = another_url.ReplaceComponents(replace_host);
+ NavigateToURL(CreateBrowser(), another_url);
+
+ // Expect that we got another process (the guest renderer was not reused).
+ EXPECT_EQ(2, RenderProcessHostCount());
+}
+
} // 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 73cb5e11f9c..5d975e9119d 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -45,13 +45,12 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/device_orientation/device_motion_message_filter.h"
#include "content/browser/device_orientation/device_orientation_message_filter.h"
-#include "content/browser/device_orientation/orientation_message_filter.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/dom_storage_message_filter.h"
#include "content/browser/download/mhtml_generation_manager.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/fileapi/fileapi_message_filter.h"
-#include "content/browser/geolocation/geolocation_dispatcher_host.h"
+#include "content/browser/frame_host/render_frame_message_filter.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
@@ -63,6 +62,7 @@
#include "content/browser/loader/resource_scheduler_filter.h"
#include "content/browser/media/android/browser_demuxer_android.h"
#include "content/browser/media/media_internals.h"
+#include "content/browser/message_port_message_filter.h"
#include "content/browser/mime_registry_message_filter.h"
#include "content/browser/plugin_service_impl.h"
#include "content/browser/profiler_message_filter.h"
@@ -92,14 +92,16 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
#include "content/browser/renderer_host/text_input_client_message_filter.h"
+#include "content/browser/renderer_host/websocket_dispatcher_host.h"
#include "content/browser/resolve_proxy_msg_helper.h"
-#include "content/browser/service_worker/service_worker_context.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/speech/input_tag_speech_dispatcher_host.h"
#include "content/browser/speech/speech_recognition_dispatcher_host.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/streams/stream_context.h"
#include "content/browser/tracing/trace_message_filter.h"
+#include "content/browser/vibration/vibration_message_filter.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/worker_host/worker_message_filter.h"
#include "content/browser/worker_host/worker_storage_partition.h"
@@ -114,6 +116,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host_factory.h"
+#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/resource_context.h"
@@ -132,15 +135,12 @@
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/shared_impl/ppapi_switches.h"
#include "ui/base/ui_base_switches.h"
+#include "ui/events/event_switches.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
#include "webkit/common/resource_type.h"
-#if defined(OS_ANDROID)
-#include "content/browser/android/vibration_message_filter.h"
-#endif
-
#if defined(OS_WIN)
#include "base/win/scoped_com_initializer.h"
#include "content/common/font_cache_dispatcher_win.h"
@@ -355,6 +355,9 @@ RenderProcessHostImpl::RenderProcessHostImpl(
bool is_guest)
: fast_shutdown_started_(false),
deleting_soon_(false),
+#ifndef NDEBUG
+ is_self_deleted_(false),
+#endif
pending_views_(0),
visible_widgets_(0),
backgrounded_(true),
@@ -370,7 +373,8 @@ RenderProcessHostImpl::RenderProcessHostImpl(
supports_browser_plugin_(supports_browser_plugin),
is_guest_(is_guest),
gpu_observer_registered_(false),
- power_monitor_broadcaster_(this) {
+ power_monitor_broadcaster_(this),
+ geolocation_dispatcher_host_(NULL) {
widget_helper_ = new RenderWidgetHelper();
ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID());
@@ -395,8 +399,37 @@ RenderProcessHostImpl::RenderProcessHostImpl(
// creation.
}
+// static
+void RenderProcessHostImpl::ShutDownInProcessRenderer() {
+ DCHECK(g_run_renderer_in_process_);
+
+ switch (g_all_hosts.Pointer()->size()) {
+ case 0:
+ return;
+ case 1: {
+ RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
+ AllHostsIterator().GetCurrentValue());
+ FOR_EACH_OBSERVER(RenderProcessHostObserver,
+ host->observers_,
+ RenderProcessHostDestroyed(host));
+#ifndef NDEBUG
+ host->is_self_deleted_ = true;
+#endif
+ delete host;
+ return;
+ }
+ default:
+ NOTREACHED() << "There should be only one RenderProcessHost when running "
+ << "in-process.";
+ }
+}
+
RenderProcessHostImpl::~RenderProcessHostImpl() {
- DCHECK(!run_renderer_in_process());
+#ifndef NDEBUG
+ DCHECK(is_self_deleted_)
+ << "RenderProcessHostImpl is destroyed by something other than itself";
+#endif
+
ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID());
if (gpu_observer_registered_) {
@@ -468,8 +501,8 @@ bool RenderProcessHostImpl::Init() {
CreateMessageFilters();
- // Single-process mode not supported in multiple-dll mode currently.
- if (run_renderer_in_process() && g_renderer_main_thread_factory) {
+ if (run_renderer_in_process()) {
+ DCHECK(g_renderer_main_thread_factory);
// Crank up a thread and run the initialization there. With the way that
// messages flow between the browser and renderer, this thread is required
// to prevent a deadlock in single-process mode. Since the primordial
@@ -530,7 +563,7 @@ bool RenderProcessHostImpl::Init() {
void RenderProcessHostImpl::CreateMessageFilters() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- channel_->AddFilter(new ResourceSchedulerFilter(GetID()));
+ AddFilter(new ResourceSchedulerFilter(GetID()));
MediaInternals* media_internals = MediaInternals::GetInstance();;
media::AudioManager* audio_manager =
BrowserMainLoop::GetInstance()->audio_manager();
@@ -539,7 +572,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
if (supports_browser_plugin_) {
scoped_refptr<BrowserPluginMessageFilter> bp_message_filter(
new BrowserPluginMessageFilter(GetID(), IsGuest()));
- channel_->AddFilter(bp_message_filter.get());
+ AddFilter(bp_message_filter.get());
}
scoped_refptr<RenderMessageFilter> render_message_filter(
@@ -557,7 +590,9 @@ void RenderProcessHostImpl::CreateMessageFilters() {
audio_manager,
media_internals,
storage_partition_impl_->GetDOMStorageContext()));
- channel_->AddFilter(render_message_filter.get());
+ AddFilter(render_message_filter.get());
+ AddFilter(
+ new RenderFrameMessageFilter(GetID(), widget_helper_.get()));
BrowserContext* browser_context = GetBrowserContext();
ResourceContext* resource_context = browser_context->GetResourceContext();
@@ -577,86 +612,95 @@ void RenderProcessHostImpl::CreateMessageFilters() {
storage_partition_impl_->GetFileSystemContext(),
get_contexts_callback);
- channel_->AddFilter(resource_message_filter);
+ AddFilter(resource_message_filter);
MediaStreamManager* media_stream_manager =
BrowserMainLoop::GetInstance()->media_stream_manager();
- channel_->AddFilter(new AudioInputRendererHost(
+ AddFilter(new AudioInputRendererHost(
audio_manager,
media_stream_manager,
BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
BrowserMainLoop::GetInstance()->user_input_monitor()));
- channel_->AddFilter(new AudioRendererHost(
+ // The AudioRendererHost needs to be available for lookup, so it's
+ // stashed in a member variable.
+ audio_renderer_host_ = new AudioRendererHost(
GetID(),
audio_manager,
BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
media_internals,
- media_stream_manager));
- channel_->AddFilter(
+ media_stream_manager);
+ AddFilter(audio_renderer_host_);
+ AddFilter(
new MIDIHost(GetID(), BrowserMainLoop::GetInstance()->midi_manager()));
- channel_->AddFilter(new MIDIDispatcherHost(GetID(), browser_context));
- channel_->AddFilter(new VideoCaptureHost(media_stream_manager));
- channel_->AddFilter(new AppCacheDispatcherHost(
+ AddFilter(new MIDIDispatcherHost(GetID(), browser_context));
+ AddFilter(new VideoCaptureHost(media_stream_manager));
+ AddFilter(new AppCacheDispatcherHost(
storage_partition_impl_->GetAppCacheService(),
GetID()));
- channel_->AddFilter(new ClipboardMessageFilter);
- channel_->AddFilter(new DOMStorageMessageFilter(
+ AddFilter(new ClipboardMessageFilter);
+ AddFilter(new DOMStorageMessageFilter(
GetID(),
storage_partition_impl_->GetDOMStorageContext()));
- channel_->AddFilter(new IndexedDBDispatcherHost(
- GetID(),
+ AddFilter(new IndexedDBDispatcherHost(
storage_partition_impl_->GetIndexedDBContext()));
- channel_->AddFilter(new ServiceWorkerDispatcherHost(
- storage_partition_impl_->GetServiceWorkerContext()));
+
+ scoped_refptr<ServiceWorkerDispatcherHost> service_worker_filter =
+ new ServiceWorkerDispatcherHost(GetID());
+ service_worker_filter->Init(
+ storage_partition_impl_->GetServiceWorkerContext());
+ AddFilter(service_worker_filter);
+
if (IsGuest()) {
if (!g_browser_plugin_geolocation_context.Get().get()) {
g_browser_plugin_geolocation_context.Get() =
new BrowserPluginGeolocationPermissionContext();
}
- channel_->AddFilter(GeolocationDispatcherHost::New(
- GetID(), g_browser_plugin_geolocation_context.Get().get()));
+ geolocation_dispatcher_host_ = GeolocationDispatcherHost::New(
+ GetID(), g_browser_plugin_geolocation_context.Get().get());
} else {
- channel_->AddFilter(GeolocationDispatcherHost::New(
- GetID(), browser_context->GetGeolocationPermissionContext()));
+ geolocation_dispatcher_host_ = GeolocationDispatcherHost::New(
+ GetID(), browser_context->GetGeolocationPermissionContext());
}
+ AddFilter(geolocation_dispatcher_host_);
gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get());
- channel_->AddFilter(gpu_message_filter_);
+ AddFilter(gpu_message_filter_);
#if defined(ENABLE_WEBRTC)
- channel_->AddFilter(new WebRTCIdentityServiceHost(
+ AddFilter(new WebRTCIdentityServiceHost(
GetID(), storage_partition_impl_->GetWebRTCIdentityStore()));
peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID());
- channel_->AddFilter(peer_connection_tracker_host_.get());
- channel_->AddFilter(new MediaStreamDispatcherHost(
- GetID(), media_stream_manager));
- channel_->AddFilter(
+ AddFilter(peer_connection_tracker_host_.get());
+ AddFilter(new MediaStreamDispatcherHost(
+ GetID(),
+ browser_context->GetResourceContext()->GetMediaDeviceIDSalt(),
+ media_stream_manager));
+ AddFilter(
new DeviceRequestMessageFilter(resource_context, media_stream_manager));
#endif
#if defined(ENABLE_PLUGINS)
- channel_->AddFilter(new PepperRendererConnection(GetID()));
+ AddFilter(new PepperRendererConnection(GetID()));
#endif
#if defined(ENABLE_INPUT_SPEECH)
- channel_->AddFilter(new InputTagSpeechDispatcherHost(
+ AddFilter(new InputTagSpeechDispatcherHost(
IsGuest(), GetID(), storage_partition_impl_->GetURLRequestContext()));
#endif
- channel_->AddFilter(new SpeechRecognitionDispatcherHost(
- GetID(), storage_partition_impl_->GetURLRequestContext()));
- channel_->AddFilter(new FileAPIMessageFilter(
+ AddFilter(new SpeechRecognitionDispatcherHost(
+ IsGuest(), GetID(), storage_partition_impl_->GetURLRequestContext()));
+ AddFilter(new FileAPIMessageFilter(
GetID(),
storage_partition_impl_->GetURLRequestContext(),
storage_partition_impl_->GetFileSystemContext(),
ChromeBlobStorageContext::GetFor(browser_context),
StreamContext::GetFor(browser_context)));
- channel_->AddFilter(new OrientationMessageFilter());
- channel_->AddFilter(new FileUtilitiesMessageFilter(GetID()));
- channel_->AddFilter(new MimeRegistryMessageFilter());
- channel_->AddFilter(new DatabaseMessageFilter(
+ AddFilter(new FileUtilitiesMessageFilter(GetID()));
+ AddFilter(new MimeRegistryMessageFilter());
+ AddFilter(new DatabaseMessageFilter(
storage_partition_impl_->GetDatabaseTracker()));
#if defined(OS_MACOSX)
- channel_->AddFilter(new TextInputClientMessageFilter(GetID()));
+ AddFilter(new TextInputClientMessageFilter(GetID()));
#elif defined(OS_WIN)
channel_->AddFilter(new FontCacheDispatcher());
#elif defined(OS_ANDROID)
browser_demuxer_android_ = new BrowserDemuxerAndroid();
- channel_->AddFilter(browser_demuxer_android_);
+ AddFilter(browser_demuxer_android_);
#endif
SocketStreamDispatcherHost::GetRequestContextCallback
@@ -667,9 +711,21 @@ void RenderProcessHostImpl::CreateMessageFilters() {
SocketStreamDispatcherHost* socket_stream_dispatcher_host =
new SocketStreamDispatcherHost(
GetID(), request_context_callback, resource_context);
- channel_->AddFilter(socket_stream_dispatcher_host);
+ AddFilter(socket_stream_dispatcher_host);
+
+ WebSocketDispatcherHost::GetRequestContextCallback
+ websocket_request_context_callback(
+ base::Bind(&GetRequestContext, request_context,
+ media_request_context, ResourceType::SUB_RESOURCE));
+
+ AddFilter(new WebSocketDispatcherHost(websocket_request_context_callback));
- channel_->AddFilter(new WorkerMessageFilter(
+ message_port_message_filter_ = new MessagePortMessageFilter(
+ base::Bind(&RenderWidgetHelper::GetNextRoutingID,
+ base::Unretained(widget_helper_.get())));
+ AddFilter(message_port_message_filter_);
+
+ AddFilter(new WorkerMessageFilter(
GetID(),
resource_context,
WorkerStoragePartition(
@@ -680,35 +736,32 @@ void RenderProcessHostImpl::CreateMessageFilters() {
storage_partition_impl_->GetFileSystemContext(),
storage_partition_impl_->GetDatabaseTracker(),
storage_partition_impl_->GetIndexedDBContext()),
- base::Bind(&RenderWidgetHelper::GetNextRoutingID,
- base::Unretained(widget_helper_.get()))));
+ message_port_message_filter_));
#if defined(ENABLE_WEBRTC)
- channel_->AddFilter(new P2PSocketDispatcherHost(
+ AddFilter(new P2PSocketDispatcherHost(
resource_context,
browser_context->GetRequestContextForRenderProcess(GetID())));
#endif
- channel_->AddFilter(new TraceMessageFilter());
- channel_->AddFilter(new ResolveProxyMsgHelper(
+ AddFilter(new TraceMessageFilter());
+ AddFilter(new ResolveProxyMsgHelper(
browser_context->GetRequestContextForRenderProcess(GetID())));
- channel_->AddFilter(new QuotaDispatcherHost(
+ AddFilter(new QuotaDispatcherHost(
GetID(),
storage_partition_impl_->GetQuotaManager(),
GetContentClient()->browser()->CreateQuotaPermissionContext()));
- channel_->AddFilter(new GamepadBrowserMessageFilter());
- channel_->AddFilter(new DeviceMotionMessageFilter());
- channel_->AddFilter(new DeviceOrientationMessageFilter());
- channel_->AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER));
- channel_->AddFilter(new HistogramMessageFilter());
+ AddFilter(new GamepadBrowserMessageFilter());
+ AddFilter(new DeviceMotionMessageFilter());
+ AddFilter(new DeviceOrientationMessageFilter());
+ AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER));
+ AddFilter(new HistogramMessageFilter());
#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableMemoryBenchmarking))
- channel_->AddFilter(new MemoryBenchmarkMessageFilter());
-#endif
-#if defined(OS_ANDROID)
- channel_->AddFilter(new VibrationMessageFilter());
+ AddFilter(new MemoryBenchmarkMessageFilter());
#endif
+ AddFilter(new VibrationMessageFilter());
}
int RenderProcessHostImpl::GetNextRoutingID() {
@@ -749,6 +802,15 @@ void RenderProcessHostImpl::RemoveRoute(int32 routing_id) {
Cleanup();
}
+void RenderProcessHostImpl::AddObserver(RenderProcessHostObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void RenderProcessHostImpl::RemoveObserver(
+ RenderProcessHostObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
bool RenderProcessHostImpl::WaitForBackingStoreMsg(
int render_widget_id,
const base::TimeDelta& max_delay,
@@ -763,6 +825,10 @@ bool RenderProcessHostImpl::WaitForBackingStoreMsg(
}
void RenderProcessHostImpl::ReceivedBadMessage() {
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC))
+ return;
+
if (run_renderer_in_process()) {
// In single process mode it is better if we don't suicide but just
// crash.
@@ -856,166 +922,135 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
// Propagate the following switches to the renderer command line (along
// with any associated values) if present in the browser command line.
static const char* const kSwitchNames[] = {
- switches::kAllowFiltersOverIPC,
switches::kAudioBufferSize,
switches::kAuditAllHandles,
switches::kAuditHandles,
switches::kBlockCrossSiteDocuments,
- switches::kDirectNPAPIRequests,
+ switches::kDefaultTileWidth,
+ switches::kDefaultTileHeight,
switches::kDisable3DAPIs,
switches::kDisableAcceleratedCompositing,
+ switches::kDisableAcceleratedFixedRootBackground,
+ switches::kDisableAcceleratedScrollableFrames,
switches::kDisableAcceleratedVideoDecode,
switches::kDisableApplicationCache,
switches::kDisableAudio,
switches::kDisableBreakpad,
+ switches::kDisableCompositedScrollingForFrames,
+ switches::kDisableCompositingForFixedPosition,
+ switches::kDisableCompositingForTransition,
switches::kDisableDatabases,
switches::kDisableDeadlineScheduling,
switches::kDisableDelegatedRenderer,
switches::kDisableDesktopNotifications,
+ switches::kDisableDeviceMotion,
switches::kDisableDeviceOrientation,
+ switches::kDisableDirectNPAPIRequests,
switches::kDisableFileSystem,
+ switches::kDisableFiltersOverIPC,
+ switches::kDisableFullScreen,
switches::kDisableGeolocation,
- switches::kDisableGLMultisampling,
- switches::kDisableGpuVsync,
switches::kDisableGpu,
switches::kDisableGpuCompositing,
+ switches::kDisableGpuVsync,
switches::kDisableHistogramCustomizer,
+ switches::kDisableLayerSquashing,
switches::kDisableLocalStorage,
switches::kDisableLogging,
+ switches::kDisableOpusPlayback,
+ switches::kDisablePinch,
+ switches::kDisablePrefixedEncryptedMedia,
switches::kDisableSeccompFilterSandbox,
switches::kDisableSessionStorage,
switches::kDisableSharedWorkers,
switches::kDisableSpeechInput,
+ switches::kDisableThreadedCompositing,
+ switches::kDisableTouchAdjustment,
switches::kDisableTouchDragDrop,
switches::kDisableTouchEditing,
-#if defined(OS_ANDROID)
- switches::kDisableWebRTC,
- switches::kEnableSpeechRecognition,
-#endif
- switches::kDisableWebAudio,
-#if defined(ENABLE_WEBRTC)
- switches::kDisableDeviceEnumeration,
- switches::kDisableSCTPDataChannels,
- switches::kDisableWebRtcHWDecoding,
- switches::kDisableWebRtcHWEncoding,
-#endif
- switches::kEnableWebAnimationsCSS,
- switches::kEnableWebAnimationsSVG,
- switches::kEnableWebMIDI,
- switches::kEnableExperimentalCanvasFeatures,
- switches::kEnableExperimentalWebSocket,
+ switches::kDisableUniversalAcceleratedOverflowScroll,
+ switches::kDisableUnprefixedMediaSource,
+ switches::kDisableVp8AlphaPlayback,
+ switches::kDisableWebAnimationsCSS,
+ switches::kDisableWebKitMediaSource,
switches::kDomAutomationController,
+ switches::kEnableAcceleratedFixedRootBackground,
+ switches::kEnableAcceleratedOverflowScroll,
+ switches::kEnableAcceleratedScrollableFrames,
switches::kEnableAccessibilityLogging,
switches::kEnableBeginFrameScheduling,
- switches::kEnableBrowserInputController,
switches::kEnableBrowserPluginForAllViewTypes,
+ switches::kEnableCompositedScrollingForFrames,
+ switches::kEnableCompositingForFixedPosition,
+ switches::kEnableCompositingForTransition,
switches::kEnableDCHECK,
switches::kEnableDeadlineScheduling,
+ switches::kEnableDeferredImageDecoding,
switches::kEnableDelegatedRenderer,
+ switches::kEnableEac3Playback,
switches::kEnableEncryptedMedia,
- switches::kDisableLegacyEncryptedMedia,
- switches::kOverrideEncryptedMediaCanPlayType,
-#if defined(OS_ANDROID)
- switches::kEnableMediaDrm,
- switches::kMediaDrmEnableNonCompositing,
-#endif
+ switches::kEnableExperimentalCanvasFeatures,
switches::kEnableExperimentalWebPlatformFeatures,
- switches::kEnableFixedLayout,
- switches::kEnableDeferredImageDecoding,
- switches::kEnableGPUServiceLogging,
+ switches::kEnableExperimentalWebSocket,
+ switches::kEnableFastTextAutosizing,
+ switches::kEnableGpuBenchmarking,
switches::kEnableGPUClientLogging,
switches::kEnableGpuClientTracing,
- switches::kEnableGpuBenchmarking,
-#if defined(OS_WIN)
- switches::kEnableHighResolutionTime,
-#endif
+ switches::kEnableGPUServiceLogging,
+ switches::kEnableHighDpiCompositingForFixedPosition,
+ switches::kEnableHTMLImports,
+ switches::kEnableInbandTextTracks,
+ switches::kEnableInputModeAttribute,
+ switches::kEnableLayerSquashing,
+ switches::kEnableLogging,
switches::kEnableMP3StreamParser,
switches::kEnableMemoryBenchmarking,
switches::kEnableOverlayFullscreenVideo,
switches::kEnableOverlayScrollbars,
- switches::kEnableSkiaBenchmarking,
- switches::kEnableLogging,
- switches::kEnableSpeechSynthesis,
- switches::kEnableTouchDragDrop,
- switches::kEnableTouchEditing,
-#if defined(ENABLE_WEBRTC)
- switches::kEnableWebRtcAecRecordings,
- switches::kEnableWebRtcTcpServerSocket,
-#endif
- switches::kDisableWebKitMediaSource,
switches::kEnableOverscrollNotifications,
- switches::kEnableStrictSiteIsolation,
- switches::kDisableFullScreen,
-#if defined(ENABLE_PLUGINS)
- switches::kEnablePepperTesting,
- switches::kDisablePepper3d,
-#endif
+ switches::kEnablePinch,
switches::kEnablePreparsedJsCaching,
switches::kEnablePruneGpuCommandBuffers,
- switches::kEnablePinch,
- switches::kDisablePinch,
-#if defined(OS_MACOSX)
- // Allow this to be set when invoking the browser and relayed along.
- switches::kEnableSandboxLogging,
-#endif
+ switches::kEnableRepaintAfterLayout,
+ switches::kEnableServiceWorker,
+ switches::kEnableSkiaBenchmarking,
switches::kEnableSoftwareCompositing,
+ switches::kEnableSpeechSynthesis,
switches::kEnableStatsTable,
+ switches::kEnableStrictSiteIsolation,
switches::kEnableThreadedCompositing,
- switches::kEnableCompositingForFixedPosition,
- switches::kEnableHighDpiCompositingForFixedPosition,
- switches::kDisableCompositingForFixedPosition,
- switches::kEnableAcceleratedOverflowScroll,
- switches::kEnableCompositingForTransition,
- switches::kDisableCompositingForTransition,
- switches::kEnableAcceleratedFixedRootBackground,
- switches::kDisableAcceleratedFixedRootBackground,
- switches::kDisableThreadedCompositing,
- switches::kDisableTouchAdjustment,
- switches::kDefaultTileWidth,
- switches::kDefaultTileHeight,
- switches::kMaxUntiledLayerWidth,
- switches::kMaxUntiledLayerHeight,
+ switches::kEnableUniversalAcceleratedOverflowScroll,
+ switches::kEnableTouchDragDrop,
+ switches::kEnableTouchEditing,
switches::kEnableViewport,
- switches::kEnableInbandTextTracks,
- switches::kEnableOpusPlayback,
- switches::kDisableVp8AlphaPlayback,
- switches::kEnableEac3Playback,
+ switches::kEnableViewportMeta,
+ switches::kMainFrameResizesAreOrientationChanges,
+ switches::kEnableVtune,
+ switches::kEnableWebAnimationsCSS,
+ switches::kEnableWebAnimationsSVG,
+ switches::kEnableWebGLDraftExtensions,
+ switches::kEnableWebMIDI,
switches::kForceDeviceScaleFactor,
switches::kFullMemoryCrashReport,
-#if defined(OS_ANDROID)
- switches::kHideScrollbars,
-#endif
-#if !defined (GOOGLE_CHROME_BUILD)
- // These are unsupported and not fully tested modes, so don't enable them
- // for official Google Chrome builds.
- switches::kInProcessPlugins,
-#endif // GOOGLE_CHROME_BUILD
switches::kJavaScriptFlags,
switches::kLoggingLevel,
+ switches::kMaxUntiledLayerWidth,
+ switches::kMaxUntiledLayerHeight,
switches::kMemoryMetrics,
-#if defined(OS_ANDROID)
- switches::kNetworkCountryIso,
- switches::kDisableGestureRequirementForMediaPlayback,
-#endif
-#if defined(GOOGLE_TV)
- switches::kUseExternalVideoSurfaceThresholdInPixels,
-#endif
switches::kNoReferrers,
switches::kNoSandbox,
- switches::kEnableVtune,
switches::kPpapiInProcess,
+ switches::kProfilerTiming,
+ switches::kReduceSecurityForTesting,
switches::kRegisterPepperPlugins,
switches::kRendererAssertTest,
-#if defined(OS_POSIX)
- switches::kChildCleanExit,
-#endif
switches::kRendererStartupDialog,
switches::kShowPaintRects,
switches::kSitePerProcess,
switches::kStatsCollectionController,
switches::kTestSandbox,
switches::kTouchEvents,
- switches::kTraceStartup,
+ switches::kTraceToConsole,
// This flag needs to be propagated to the renderer process for
// --in-process-webgl.
switches::kUseGL,
@@ -1025,20 +1060,18 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kVideoThreads,
switches::kVModule,
switches::kWebCoreLogChannels,
- switches::kEnableWebGLDraftExtensions,
- switches::kEnableHTMLImports,
- switches::kEnableInputModeAttribute,
- switches::kTraceToConsole,
- switches::kDisableDeviceMotion,
+ switches::kWebGLCommandBufferSizeKb,
// Please keep these in alphabetical order. Compositor switches here should
// also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
cc::switches::kBackgroundColorInsteadOfCheckerboard,
cc::switches::kCompositeToMailbox,
cc::switches::kDisableCompositedAntialiasing,
+ cc::switches::kDisableCompositorTouchHitTesting,
cc::switches::kDisableImplSidePainting,
cc::switches::kDisableLCDText,
cc::switches::kDisableMapImage,
cc::switches::kDisableThreadedAnimation,
+ cc::switches::kEnableGPURasterization,
cc::switches::kEnableImplSidePainting,
cc::switches::kEnableLCDText,
cc::switches::kEnableMapImage,
@@ -1046,13 +1079,12 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
cc::switches::kEnablePerTilePainting,
cc::switches::kEnablePinchVirtualViewport,
cc::switches::kEnableTopControlsPositionCalculation,
- cc::switches::kForceDirectLayerDrawing,
- cc::switches::kLowResolutionContentsScaleFactor,
cc::switches::kMaxTilesForInterestArea,
cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
cc::switches::kNumRasterThreads,
cc::switches::kShowCompositedLayerBorders,
cc::switches::kShowFPSCounter,
+ cc::switches::kShowLayerAnimationBounds,
cc::switches::kShowNonOccludingRects,
cc::switches::kShowOccludingRects,
cc::switches::kShowPropertyChangedRects,
@@ -1065,10 +1097,69 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
cc::switches::kTopControlsHideThreshold,
cc::switches::kTopControlsShowThreshold,
cc::switches::kTraceOverdraw,
+#if defined(ENABLE_PLUGINS)
+ switches::kEnablePepperTesting,
+ switches::kDisablePepper3d,
+#endif
+#if defined(ENABLE_WEBRTC)
+ switches::kEnableAudioTrackProcessing,
+ switches::kDisableDeviceEnumeration,
+ switches::kDisableSCTPDataChannels,
+ switches::kDisableWebRtcHWDecoding,
+ switches::kDisableWebRtcHWEncoding,
+ switches::kEnableWebRtcAecRecordings,
+ switches::kEnableWebRtcHWVp8Encoding,
+ switches::kEnableWebRtcTcpServerSocket,
+#endif
+#if !defined (GOOGLE_CHROME_BUILD)
+ // These are unsupported and not fully tested modes, so don't enable them
+ // for official Google Chrome builds.
+ switches::kInProcessPlugins,
+#endif // GOOGLE_CHROME_BUILD
+#if defined(GOOGLE_TV)
+ switches::kUseExternalVideoSurfaceThresholdInPixels,
+#endif
+#if defined(OS_ANDROID)
+ switches::kDisableGestureRequirementForMediaPlayback,
+ switches::kDisableLowEndDeviceMode,
+ switches::kDisableWebRTC,
+ switches::kEnableLowEndDeviceMode,
+ switches::kEnableSpeechRecognition,
+ switches::kHideScrollbars,
+ switches::kMediaDrmEnableNonCompositing,
+ switches::kNetworkCountryIso,
+#endif
+#if defined(OS_ANDROID) && defined(ARCH_CPU_X86)
+ switches::kEnableWebAudio,
+#else
+ // Need to be able to disable webaudio on other platforms where it
+ // is enabled by default.
+ switches::kDisableWebAudio,
+#endif
+#if defined(OS_MACOSX)
+ // Allow this to be set when invoking the browser and relayed along.
+ switches::kEnableSandboxLogging,
+#endif
+#if defined(OS_POSIX)
+ switches::kChildCleanExit,
+#endif
+#if defined(OS_WIN)
+ switches::kEnableDirectWrite,
+ switches::kEnableHighResolutionTime,
+#endif
};
renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
arraysize(kSwitchNames));
+ if (browser_cmd.HasSwitch(switches::kTraceStartup) &&
+ BrowserMainLoop::GetInstance()->is_tracing_startup()) {
+ // Pass kTraceStartup switch to renderer only if startup tracing has not
+ // finished.
+ renderer_cmd->AppendSwitchASCII(
+ switches::kTraceStartup,
+ browser_cmd.GetSwitchValueASCII(switches::kTraceStartup));
+ }
+
// Disable databases in incognito mode.
if (GetBrowserContext()->IsOffTheRecord() &&
!browser_cmd.HasSwitch(switches::kDisableDatabases)) {
@@ -1114,8 +1205,11 @@ bool RenderProcessHostImpl::FastShutdownIfPossible() {
if (!SuddenTerminationAllowed())
return false;
- ProcessDied(false /* already_dead */);
+ // Set this before ProcessDied() so observers can tell if the render process
+ // died due to fast shutdown versus another cause.
fast_shutdown_started_ = true;
+
+ ProcessDied(false /* already_dead */);
return true;
}
@@ -1291,6 +1385,8 @@ void RenderProcessHostImpl::OnChannelConnected(int32 peer_pid) {
tracked_objects::ThreadData::Status status =
tracked_objects::ThreadData::status();
Send(new ChildProcessMsg_SetProfilerStatus(status));
+
+ Send(new ViewMsg_SetRendererProcessID(GetID()));
}
void RenderProcessHostImpl::OnChannelError() {
@@ -1323,14 +1419,20 @@ bool RenderProcessHostImpl::IgnoreInputEvents() const {
}
void RenderProcessHostImpl::Cleanup() {
- // When no other owners of this object, we can delete ourselves
+ // When there are no other owners of this object, we can delete ourselves.
if (listeners_.IsEmpty()) {
DCHECK_EQ(0, pending_views_);
+ FOR_EACH_OBSERVER(RenderProcessHostObserver,
+ observers_,
+ RenderProcessHostDestroyed(this));
NotificationService::current()->Notify(
NOTIFICATION_RENDERER_PROCESS_TERMINATED,
Source<RenderProcessHost>(this),
NotificationService::NoDetails());
+#ifndef NDEBUG
+ is_self_deleted_ = true;
+#endif
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
deleting_soon_ = true;
// It's important not to wait for the DeleteTask to delete the channel
@@ -1340,6 +1442,8 @@ void RenderProcessHostImpl::Cleanup() {
// OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread.
channel_.reset();
gpu_message_filter_ = NULL;
+ message_port_message_filter_ = NULL;
+ geolocation_dispatcher_host_ = NULL;
// Remove ourself from the list of renderer processes so that we can't be
// reused in between now and when the Delete task runs.
@@ -1385,6 +1489,10 @@ IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() {
return channel_.get();
}
+void RenderProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
+ channel_->AddFilter(filter->GetFilter());
+}
+
bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count) {
if (static_cast<size_t>(GetActiveViewCount()) == count)
return FastShutdownIfPossible();
@@ -1427,25 +1535,21 @@ bool RenderProcessHostImpl::IsSuitableHost(
if (host->GetBrowserContext() != browser_context)
return false;
+ // Do not allow sharing of guest hosts. This is to prevent bugs where guest
+ // and non-guest storage gets mixed. In the future, we might consider enabling
+ // the sharing of guests, in this case this check should be removed and
+ // InSameStoragePartition should handle the possible sharing.
+ if (host->IsGuest())
+ return false;
+
// Check whether the given host and the intended site_url will be using the
// same StoragePartition, since a RenderProcessHost can only support a single
- // StoragePartition. This is relevant for packaged apps, browser tags, and
- // isolated sites.
+ // StoragePartition. This is relevant for packaged apps and isolated sites.
StoragePartition* dest_partition =
BrowserContext::GetStoragePartitionForSite(browser_context, site_url);
if (!host->InSameStoragePartition(dest_partition))
return false;
- // All URLs are suitable if this is associated with a guest renderer process.
- // TODO(fsamuel, creis): Further validation is needed to ensure that only
- // normal web URLs are permitted in guest processes. We need to investigate
- // where this validation should happen.
- if (host->IsGuest())
- return true;
-
- if (!host->IsGuest() && site_url.SchemeIs(chrome::kGuestScheme))
- return false;
-
if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
host->GetID()) !=
WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL(
@@ -1475,6 +1579,7 @@ void RenderProcessHost::SetRunRendererInProcess(bool value) {
}
}
+// static
RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return iterator(g_all_hosts.Pointer());
@@ -1635,6 +1740,8 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead) {
child_process_launcher_.reset();
channel_.reset();
gpu_message_filter_ = NULL;
+ message_port_message_filter_ = NULL;
+ geolocation_dispatcher_host_ = NULL;
IDMap<IPC::Listener>::iterator iter(&listeners_);
while (!iter.IsAtEnd()) {
@@ -1768,6 +1875,11 @@ void RenderProcessHostImpl::OnProcessLaunched() {
}
}
+scoped_refptr<AudioRendererHost>
+RenderProcessHostImpl::audio_renderer_host() const {
+ return audio_renderer_host_;
+}
+
void RenderProcessHostImpl::OnUserMetricsRecordAction(
const std::string& action) {
RecordComputedAction(action);
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 0e9ae1b2ad1..49ce3634163 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -10,9 +10,11 @@
#include <string>
#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
#include "base/process/process.h"
#include "base/timer/timer.h"
#include "content/browser/child_process_launcher.h"
+#include "content/browser/geolocation/geolocation_dispatcher_host.h"
#include "content/browser/power_monitor_message_broadcaster.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
@@ -33,8 +35,11 @@ class Size;
}
namespace content {
+class AudioRendererHost;
class BrowserDemuxerAndroid;
+class GeolocationDispatcherHost;
class GpuMessageFilter;
+class MessagePortMessageFilter;
class PeerConnectionTrackerHost;
class RendererMainThread;
class RenderWidgetHelper;
@@ -80,6 +85,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
virtual int GetNextRoutingID() OVERRIDE;
virtual void AddRoute(int32 routing_id, IPC::Listener* listener) OVERRIDE;
virtual void RemoveRoute(int32 routing_id) OVERRIDE;
+ virtual void AddObserver(RenderProcessHostObserver* observer) OVERRIDE;
+ virtual void RemoveObserver(RenderProcessHostObserver* observer) OVERRIDE;
virtual bool WaitForBackingStoreMsg(int render_widget_id,
const base::TimeDelta& max_delay,
IPC::Message* msg) OVERRIDE;
@@ -107,6 +114,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
virtual void SetSuddenTerminationAllowed(bool enabled) OVERRIDE;
virtual bool SuddenTerminationAllowed() const OVERRIDE;
virtual IPC::ChannelProxy* GetChannel() OVERRIDE;
+ virtual void AddFilter(BrowserMessageFilter* filter) OVERRIDE;
virtual bool FastShutdownForPageCount(size_t count) OVERRIDE;
virtual bool FastShutdownStarted() const OVERRIDE;
virtual base::TimeDelta GetChildProcessIdleTime() const OVERRIDE;
@@ -124,6 +132,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
// ChildProcessLauncher::Client implementation.
virtual void OnProcessLaunched() OVERRIDE;
+ scoped_refptr<AudioRendererHost> audio_renderer_host() const;
+
// Tells the ResourceDispatcherHost to resume a deferred navigation without
// transferring it to a new renderer process.
void ResumeDeferredNavigation(const GlobalRequestID& request_id);
@@ -145,6 +155,11 @@ class CONTENT_EXPORT RenderProcessHostImpl
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber);
void EndFrameSubscription(int route_id);
+ scoped_refptr<GeolocationDispatcherHost>
+ geolocation_dispatcher_host() const {
+ return make_scoped_refptr(geolocation_dispatcher_host_);
+ }
+
// Register/unregister the host identified by the host id in the global host
// list.
static void RegisterHost(int host_id, RenderProcessHost* host);
@@ -178,12 +193,23 @@ class CONTENT_EXPORT RenderProcessHostImpl
static base::MessageLoop* GetInProcessRendererThreadForTesting();
+ // This forces a renderer that is running "in process" to shut down.
+ static void ShutDownInProcessRenderer();
+
#if defined(OS_ANDROID)
const scoped_refptr<BrowserDemuxerAndroid>& browser_demuxer_android() {
return browser_demuxer_android_;
}
#endif
+ MessagePortMessageFilter* message_port_message_filter() const {
+ return message_port_message_filter_;
+ }
+
+ void SetIsGuestForTesting(bool is_guest) {
+ is_guest_ = is_guest;
+ }
+
protected:
// A proxy for our IPC::Channel that lives on the IO thread (see
// browser_process.h)
@@ -195,6 +221,11 @@ class CONTENT_EXPORT RenderProcessHostImpl
// True if we've posted a DeleteTask and will be deleted soon.
bool deleting_soon_;
+#ifndef NDEBUG
+ // True if this object has deleted itself.
+ bool is_self_deleted_;
+#endif
+
// The count of currently swapped out but pending RenderViews. We have
// started to swap these in, so the renderer process should not exit if
// this count is non-zero.
@@ -259,6 +290,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
// it's valid if non-NULL.
GpuMessageFilter* gpu_message_filter_;
+ // The filter for MessagePort messages coming from the renderer.
+ scoped_refptr<MessagePortMessageFilter> message_port_message_filter_;
+
// A map of transport DIB ids to cached TransportDIBs
std::map<TransportDIB::Id, TransportDIB*> cached_dibs_;
@@ -295,6 +329,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Owned by |browser_context_|.
StoragePartitionImpl* storage_partition_impl_;
+ // The observers watching our lifetime.
+ ObserverList<RenderProcessHostObserver> observers_;
+
// True if the process can be shut down suddenly. If this is true, then we're
// sure that all the RenderViews in the process can be shutdown suddenly. If
// it's false, then specific RenderViews might still be allowed to be shutdown
@@ -329,10 +366,15 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Forwards power state messages to the renderer process.
PowerMonitorMessageBroadcaster power_monitor_broadcaster_;
+ scoped_refptr<AudioRendererHost> audio_renderer_host_;
+
#if defined(OS_ANDROID)
scoped_refptr<BrowserDemuxerAndroid> browser_demuxer_android_;
#endif
+ // Message filter for geolocation messages.
+ GeolocationDispatcherHost* geolocation_dispatcher_host_;
+
DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImpl);
};
diff --git a/chromium/content/browser/renderer_host/render_process_host_unittest.cc b/chromium/content/browser/renderer_host/render_process_host_unittest.cc
new file mode 100644
index 00000000000..6a830f9d61b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/render_process_host_unittest.cc
@@ -0,0 +1,29 @@
+// 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/public/test/mock_render_process_host.h"
+#include "content/test/test_render_view_host.h"
+
+namespace content {
+
+class RenderProcessHostUnitTest : public RenderViewHostTestHarness {};
+
+// Tests that guest RenderProcessHosts are not considered suitable hosts when
+// searching for RenderProcessHost.
+TEST_F(RenderProcessHostUnitTest, GuestsAreNotSuitableHosts) {
+ GURL test_url("http://foo.com");
+
+ MockRenderProcessHost guest_host(browser_context());
+ guest_host.SetIsGuest(true);
+
+ EXPECT_FALSE(RenderProcessHostImpl::IsSuitableHost(
+ &guest_host, browser_context(), test_url));
+ EXPECT_TRUE(RenderProcessHostImpl::IsSuitableHost(
+ process(), browser_context(), test_url));
+ EXPECT_EQ(
+ process(),
+ RenderProcessHost::GetExistingProcessHost(browser_context(), test_url));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_sandbox_host_linux.cc b/chromium/content/browser/renderer_host/render_sandbox_host_linux.cc
index 81537181532..19cbc5b4b35 100644
--- a/chromium/content/browser/renderer_host/render_sandbox_host_linux.cc
+++ b/chromium/content/browser/renderer_host/render_sandbox_host_linux.cc
@@ -25,24 +25,25 @@
#include "base/posix/eintr_wrapper.h"
#include "base/posix/unix_domain_socket_linux.h"
#include "base/process/launch.h"
+#include "base/process/process_metrics.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "content/child/webkitplatformsupport_impl.h"
#include "content/common/font_config_ipc_linux.h"
-#include "content/common/sandbox_linux.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/common/set_process_title.h"
#include "content/public/common/content_switches.h"
#include "skia/ext/skia_utils_base.h"
+#include "third_party/WebKit/public/platform/linux/WebFontInfo.h"
#include "third_party/WebKit/public/web/WebKit.h"
-#include "third_party/WebKit/public/web/linux/WebFontInfo.h"
#include "third_party/npapi/bindings/npapi_extensions.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#include "ui/gfx/font_render_params_linux.h"
-using WebKit::WebCString;
-using WebKit::WebFontInfo;
-using WebKit::WebUChar;
-using WebKit::WebUChar32;
+using blink::WebCString;
+using blink::WebFontInfo;
+using blink::WebUChar;
+using blink::WebUChar32;
namespace content {
@@ -240,7 +241,7 @@ class SandboxIPCProcess {
SendRendererReply(fds, reply, result_fd);
if (result_fd >= 0) {
- int err = HANDLE_EINTR(close(result_fd));
+ int err = IGNORE_EINTR(close(result_fd));
DCHECK(!err);
}
}
@@ -260,7 +261,7 @@ class SandboxIPCProcess {
if (!pickle.ReadString(&iter, &preferred_locale))
return;
- WebKit::WebFontFamily family;
+ blink::WebFontFamily family;
WebFontInfo::familyForChar(c, preferred_locale.c_str(), &family);
Pickle reply;
@@ -286,7 +287,7 @@ class SandboxIPCProcess {
}
EnsureWebKitInitialized();
- WebKit::WebFontRenderStyle style;
+ blink::WebFontRenderStyle style;
WebFontInfo::renderStyleForStrike(family.c_str(), sizeAndStyle, &style);
Pickle reply;
@@ -515,7 +516,7 @@ class SandboxIPCProcess {
SendRendererReply(fds, reply, font_fd);
if (font_fd >= 0) {
- if (HANDLE_EINTR(close(font_fd)) < 0)
+ if (IGNORE_EINTR(close(font_fd)) < 0)
PLOG(ERROR) << "close";
}
}
@@ -654,14 +655,14 @@ class SandboxIPCProcess {
SandboxIPCProcess::~SandboxIPCProcess() {
paths_.deleteAll();
if (webkit_platform_support_)
- WebKit::shutdownWithoutV8();
+ blink::shutdownWithoutV8();
}
void SandboxIPCProcess::EnsureWebKitInitialized() {
if (webkit_platform_support_)
return;
webkit_platform_support_.reset(new WebKitPlatformSupportImpl);
- WebKit::initializeWithoutV8(webkit_platform_support_.get());
+ blink::initializeWithoutV8(webkit_platform_support_.get());
}
// -----------------------------------------------------------------------------
@@ -707,11 +708,18 @@ void RenderSandboxHostLinux::Init(const std::string& sandbox_path) {
const int child_lifeline_fd = pipefds[0];
childs_lifeline_fd_ = pipefds[1];
+ // We need to be monothreaded before we fork().
+#if !defined(TOOLKIT_GTK)
+ // Exclude gtk port as TestSuite in base/tests/test_suite.cc is calling
+ // gtk_init.
+ // TODO(oshima): Remove ifdef when above issues are resolved.
+ DCHECK_EQ(1, base::GetNumberOfThreads(base::GetCurrentProcessHandle()));
+#endif
pid_ = fork();
if (pid_ == 0) {
- if (HANDLE_EINTR(close(fds[0])) < 0)
+ if (IGNORE_EINTR(close(fds[0])) < 0)
DPLOG(ERROR) << "close";
- if (HANDLE_EINTR(close(pipefds[1])) < 0)
+ if (IGNORE_EINTR(close(pipefds[1])) < 0)
DPLOG(ERROR) << "close";
SandboxIPCProcess handler(child_lifeline_fd, browser_socket, sandbox_path);
@@ -722,9 +730,9 @@ void RenderSandboxHostLinux::Init(const std::string& sandbox_path) {
RenderSandboxHostLinux::~RenderSandboxHostLinux() {
if (initialized_) {
- if (HANDLE_EINTR(close(renderer_socket_)) < 0)
+ if (IGNORE_EINTR(close(renderer_socket_)) < 0)
PLOG(ERROR) << "close";
- if (HANDLE_EINTR(close(childs_lifeline_fd_)) < 0)
+ if (IGNORE_EINTR(close(childs_lifeline_fd_)) < 0)
PLOG(ERROR) << "close";
}
}
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 20fec727501..386ff521afb 100644
--- a/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -102,7 +102,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostTest, BasicRenderFrameHost) {
RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
shell()->web_contents()->GetRenderViewHost());
- EXPECT_TRUE(rvh->main_render_frame_host_.get());
+ EXPECT_TRUE(rvh->main_render_frame_host());
ShellAddedObserver new_shell_observer;
EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "window.open();"));
@@ -110,9 +110,9 @@ IN_PROC_BROWSER_TEST_F(RenderViewHostTest, BasicRenderFrameHost) {
RenderViewHostImpl* new_rvh = static_cast<RenderViewHostImpl*>(
new_shell->web_contents()->GetRenderViewHost());
- EXPECT_TRUE(new_rvh->main_render_frame_host_.get());
- EXPECT_NE(rvh->main_render_frame_host_->routing_id(),
- new_rvh->main_render_frame_host_->routing_id());
+ EXPECT_TRUE(new_rvh->main_render_frame_host());
+ EXPECT_NE(rvh->main_render_frame_host()->routing_id(),
+ new_rvh->main_render_frame_host()->routing_id());
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate.cc b/chromium/content/browser/renderer_host/render_view_host_delegate.cc
index 5ef5dc0a82c..4786909c928 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.cc
@@ -24,8 +24,8 @@ bool RenderViewHostDelegate::OnMessageReceived(RenderViewHost* render_view_host,
}
bool RenderViewHostDelegate::AddMessageToConsole(
- int32 level, const string16& message, int32 line_no,
- const string16& source_id) {
+ int32 level, const base::string16& message, int32 line_no,
+ const base::string16& source_id) {
return false;
}
@@ -50,4 +50,8 @@ SessionStorageNamespace* RenderViewHostDelegate::GetSessionStorageNamespace(
return NULL;
}
+FrameTree* RenderViewHostDelegate::GetFrameTree() {
+ return NULL;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate.h b/chromium/content/browser/renderer_host/render_view_host_delegate.h
index 997452aeb54..a258c367405 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.h
@@ -15,6 +15,7 @@
#include "content/common/content_export.h"
#include "content/public/common/javascript_message_type.h"
#include "content/public/common/media_stream_request.h"
+#include "content/public/common/page_transition_types.h"
#include "net/base/load_states.h"
#include "third_party/WebKit/public/web/WebPopupType.h"
#include "ui/base/window_open_disposition.h"
@@ -46,6 +47,7 @@ class Size;
namespace content {
class BrowserContext;
+class FrameTree;
class PageState;
class RenderViewHost;
class RenderViewHostDelegateView;
@@ -77,7 +79,7 @@ class CONTENT_EXPORT RenderViewHostDelegate {
public:
// RendererManagerment -------------------------------------------------------
// Functions for managing switching of Renderers. For WebContents, this is
- // implemented by the RenderViewHostManager.
+ // implemented by the RenderFrameHostManager.
class CONTENT_EXPORT RendererManagement {
public:
@@ -93,10 +95,17 @@ class CONTENT_EXPORT RenderViewHostDelegate {
const base::TimeTicks& proceed_time) = 0;
// The |pending_render_view_host| is ready to commit a page. The delegate
- // should ensure that the old RenderViewHost runs its unload handler first.
+ // should ensure that the old RenderViewHost runs its unload handler first
+ // and determine whether a RenderViewHost transfer is needed.
virtual void OnCrossSiteResponse(
RenderViewHost* pending_render_view_host,
- const GlobalRequestID& global_request_id) = 0;
+ const GlobalRequestID& global_request_id,
+ bool is_transfer,
+ const std::vector<GURL>& transfer_url_chain,
+ const Referrer& referrer,
+ PageTransition page_transition,
+ int64 frame_id,
+ bool should_replace_current_entry) = 0;
protected:
virtual ~RendererManagement() {}
@@ -142,14 +151,6 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// RenderView is going to be destroyed
virtual void RenderViewDeleted(RenderViewHost* render_view_host) {}
- // The RenderView started a provisional load for a given frame.
- virtual void DidStartProvisionalLoadForFrame(
- RenderViewHost* render_view_host,
- int64 frame_id,
- int64 parent_frame_id,
- bool main_frame,
- const GURL& url) {}
-
// The RenderView processed a redirect during a provisional load.
//
// TODO(creis): Remove this method and have the pre-rendering code listen to
@@ -186,7 +187,7 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// The page's title was changed and should be updated.
virtual void UpdateTitle(RenderViewHost* render_view_host,
int32 page_id,
- const string16& title,
+ const base::string16& title,
base::i18n::TextDirection title_direction) {}
// The page's encoding was changed and should be updated.
@@ -249,9 +250,13 @@ class CONTENT_EXPORT RenderViewHostDelegate {
bool user_gesture) {}
// The page wants to transfer the request to a new renderer.
+ // |redirect_chain| contains any redirect URLs (excluding |url|) that happened
+ // before the transfer.
virtual void RequestTransferURL(
const GURL& url,
+ const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
+ PageTransition page_transition,
WindowOpenDisposition disposition,
int64 source_frame_id,
const GlobalRequestID& old_request_id,
@@ -268,23 +273,23 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// A javascript message, confirmation or prompt should be shown.
virtual void RunJavaScriptMessage(RenderViewHost* rvh,
- const string16& message,
- const string16& default_prompt,
+ const base::string16& message,
+ const base::string16& default_prompt,
const GURL& frame_url,
JavaScriptMessageType type,
IPC::Message* reply_msg,
bool* did_suppress_message) {}
virtual void RunBeforeUnloadConfirm(RenderViewHost* rvh,
- const string16& message,
+ const base::string16& message,
bool is_reload,
IPC::Message* reply_msg) {}
// A message was added to to the console.
virtual bool AddMessageToConsole(int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id);
+ const base::string16& source_id);
// Return a dummy RendererPreferences object that will be used by the renderer
// associated with the owning RenderViewHost.
@@ -369,8 +374,9 @@ class CONTENT_EXPORT RenderViewHostDelegate {
virtual void LostMouseLock() {}
// The page is trying to open a new page (e.g. a popup window). The window
- // should be created associated with the given route, but it should not be
- // shown yet. That should happen in response to ShowCreatedWindow.
+ // should be created associated with the given |route_id| in process
+ // |render_process_id|, but it should not be shown yet. That should happen in
+ // response to ShowCreatedWindow.
// |params.window_container_type| describes the type of RenderViewHost
// container that is requested -- in particular, the window.open call may
// have specified 'background' and 'persistent' in the feature string.
@@ -381,21 +387,24 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// Note: this is not called "CreateWindow" because that will clash with
// the Windows function which is actually a #define.
virtual void CreateNewWindow(
+ int render_process_id,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
SessionStorageNamespace* session_storage_namespace) {}
// The page is trying to open a new widget (e.g. a select popup). The
- // widget should be created associated with the given route, but it should
- // not be shown yet. That should happen in response to ShowCreatedWidget.
+ // widget should be created associated with the given |route_id| in the
+ // process |render_process_id|, but it should not be shown yet. That should
+ // happen in response to ShowCreatedWidget.
// |popup_type| indicates if the widget is a popup and what kind of popup it
// is (select, autofill...).
- virtual void CreateNewWidget(int route_id,
- WebKit::WebPopupType popup_type) {}
+ virtual void CreateNewWidget(int render_process_id,
+ int route_id,
+ blink::WebPopupType popup_type) {}
// Creates a full screen RenderWidget. Similar to above.
- virtual void CreateNewFullscreenWidget(int route_id) {}
+ virtual void CreateNewFullscreenWidget(int render_process_id, int route_id) {}
// Show a previously created page with the specified disposition and bounds.
// The window is identified by the route_id passed to CreateNewWindow.
@@ -431,6 +440,13 @@ class CONTENT_EXPORT RenderViewHostDelegate {
virtual SessionStorageNamespace* GetSessionStorageNamespace(
SiteInstance* instance);
+ // Returns the FrameTree the render view should use. Guaranteed to be constant
+ // for the lifetime of the render view.
+ //
+ // TODO(ajwong): Remove once the main frame RenderFrameHost is no longer
+ // created by the RenderViewHost.
+ virtual FrameTree* GetFrameTree();
+
protected:
virtual ~RenderViewHostDelegate() {}
};
diff --git a/chromium/content/browser/renderer_host/render_view_host_factory.cc b/chromium/content/browser/renderer_host/render_view_host_factory.cc
index 5cffd134b8e..fe51c7efe69 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.cc
@@ -16,17 +16,19 @@ RenderViewHostFactory* RenderViewHostFactory::factory_ = NULL;
RenderViewHost* RenderViewHostFactory::Create(
SiteInstance* instance,
RenderViewHostDelegate* delegate,
+ RenderFrameHostDelegate* frame_delegate,
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
bool swapped_out,
bool hidden) {
if (factory_) {
- return factory_->CreateRenderViewHost(instance, delegate, widget_delegate,
- routing_id, main_frame_routing_id,
- swapped_out);
+ return factory_->CreateRenderViewHost(instance, delegate, frame_delegate,
+ widget_delegate, routing_id,
+ main_frame_routing_id, swapped_out);
}
- return new RenderViewHostImpl(instance, delegate, widget_delegate, routing_id,
+ return new RenderViewHostImpl(instance, delegate, frame_delegate,
+ widget_delegate, routing_id,
main_frame_routing_id, swapped_out, hidden);
}
diff --git a/chromium/content/browser/renderer_host/render_view_host_factory.h b/chromium/content/browser/renderer_host/render_view_host_factory.h
index b0466355d49..cf6a0f1b3fb 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.h
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.h
@@ -9,6 +9,7 @@
#include "content/common/content_export.h"
namespace content {
+class RenderFrameHostDelegate;
class RenderViewHost;
class RenderViewHostDelegate;
class RenderWidgetHostDelegate;
@@ -26,6 +27,7 @@ class RenderViewHostFactory {
static RenderViewHost* Create(
SiteInstance* instance,
RenderViewHostDelegate* delegate,
+ RenderFrameHostDelegate* frame_delegate,
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
@@ -46,6 +48,7 @@ class RenderViewHostFactory {
virtual RenderViewHost* CreateRenderViewHost(
SiteInstance* instance,
RenderViewHostDelegate* delegate,
+ RenderFrameHostDelegate* frame_delegate,
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
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 68204fb746a..5c246dbb186 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -14,20 +14,28 @@
#include "base/debug/trace_event.h"
#include "base/i18n/rtl.h"
#include "base/json/json_reader.h"
-#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/sys_info.h"
#include "base/time/time.h"
#include "base/values.h"
+#include "cc/base/switches.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/cross_site_request_manager.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/render_frame_host_factory.h"
+#include "content/browser/gpu/compositor_util.h"
+#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/host_zoom_map_impl.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/renderer_host/dip_util.h"
+#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/common/accessibility_messages.h"
@@ -50,7 +58,6 @@
#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_view_host_observer.h"
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/bindings_policy.h"
@@ -62,28 +69,33 @@
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "net/base/net_util.h"
+#include "net/base/network_change_notifier.h"
#include "net/url_request/url_request_context_getter.h"
#include "third_party/skia/include/core/SkBitmap.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/image/image_skia.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/shell_dialogs/selected_file_info.h"
-#include "ui/snapshot/snapshot.h"
#include "webkit/browser/fileapi/isolated_context.h"
#if defined(OS_MACOSX)
#include "content/browser/renderer_host/popup_menu_helper_mac.h"
#elif defined(OS_ANDROID)
#include "content/browser/media/android/browser_media_player_manager.h"
+#elif defined(OS_WIN)
+#include "base/win/win_util.h"
#endif
using base::TimeDelta;
-using WebKit::WebConsoleMessage;
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationNone;
-using WebKit::WebDragOperationsMask;
-using WebKit::WebInputEvent;
-using WebKit::WebMediaPlayerAction;
-using WebKit::WebPluginAction;
+using blink::WebConsoleMessage;
+using blink::WebDragOperation;
+using blink::WebDragOperationNone;
+using blink::WebDragOperationsMask;
+using blink::WebInputEvent;
+using blink::WebMediaPlayerAction;
+using blink::WebPluginAction;
namespace content {
namespace {
@@ -94,11 +106,11 @@ const int kUnloadTimeoutMS = 1000;
// Translate a WebKit text direction into a base::i18n one.
base::i18n::TextDirection WebTextDirectionToChromeTextDirection(
- WebKit::WebTextDirection dir) {
+ blink::WebTextDirection dir) {
switch (dir) {
- case WebKit::WebTextDirectionLeftToRight:
+ case blink::WebTextDirectionLeftToRight:
return base::i18n::LEFT_TO_RIGHT;
- case WebKit::WebTextDirectionRightToLeft:
+ case blink::WebTextDirectionRightToLeft:
return base::i18n::RIGHT_TO_LEFT;
default:
NOTREACHED();
@@ -106,8 +118,28 @@ base::i18n::TextDirection WebTextDirectionToChromeTextDirection(
}
}
-base::LazyInstance<std::vector<RenderViewHost::CreatedCallback> >
-g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
+#if defined(OS_WIN) && defined(USE_AURA)
+
+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;
+ }
+ }
+}
+#endif
} // namespace
@@ -150,6 +182,7 @@ RenderViewHostImpl* RenderViewHostImpl::FromID(int render_process_id,
RenderViewHostImpl::RenderViewHostImpl(
SiteInstance* instance,
RenderViewHostDelegate* delegate,
+ RenderFrameHostDelegate* frame_delegate,
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
@@ -176,34 +209,49 @@ RenderViewHostImpl::RenderViewHostImpl(
unload_ack_is_for_cross_site_transition_(false),
are_javascript_messages_suppressed_(false),
sudden_termination_allowed_(false),
- render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) {
+ render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING),
+ virtual_keyboard_requested_(false) {
DCHECK(instance_.get());
CHECK(delegate_); // http://crbug.com/82827
if (main_frame_routing_id == MSG_ROUTING_NONE)
main_frame_routing_id = GetProcess()->GetNextRoutingID();
- main_render_frame_host_.reset(
- new RenderFrameHostImpl(this, main_frame_routing_id, is_swapped_out_));
+ main_render_frame_host_ = RenderFrameHostFactory::Create(
+ this, frame_delegate, delegate_->GetFrameTree(),
+ delegate_->GetFrameTree()->root(),
+ main_frame_routing_id, is_swapped_out_);
+ delegate_->GetFrameTree()->root()->set_render_frame_host(
+ main_render_frame_host_.get(), false);
GetProcess()->EnableSendQueue();
- for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
- g_created_callbacks.Get().at(i).Run(this);
-
if (!swapped_out)
instance_->increment_active_view_count();
+ if (ResourceDispatcherHostImpl::Get()) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostCreated,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ GetProcess()->GetID(), GetRoutingID()));
+ }
+
#if defined(OS_ANDROID)
- media_player_manager_ = BrowserMediaPlayerManager::Create(this);
+ media_player_manager_.reset(BrowserMediaPlayerManager::Create(this));
#endif
}
RenderViewHostImpl::~RenderViewHostImpl() {
- FOR_EACH_OBSERVER(
- RenderViewHostObserver, observers_, RenderViewHostDestruction());
+ if (ResourceDispatcherHostImpl::Get()) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostDeleted,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ GetProcess()->GetID(), GetRoutingID()));
+ }
- GetDelegate()->RenderViewDeleted(this);
+ delegate_->RenderViewDeleted(this);
// Be sure to clean up any leftover state from cross-site requests.
CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
@@ -224,7 +272,7 @@ SiteInstance* RenderViewHostImpl::GetSiteInstance() const {
}
bool RenderViewHostImpl::CreateRenderView(
- const string16& frame_name,
+ const base::string16& frame_name,
int opener_route_id,
int32 max_page_id) {
TRACE_EVENT0("renderer_host", "RenderViewHostImpl::CreateRenderView");
@@ -255,7 +303,7 @@ bool RenderViewHostImpl::CreateRenderView(
delegate_->GetRendererPrefs(GetProcess()->GetBrowserContext());
params.web_preferences = delegate_->GetWebkitPrefs();
params.view_id = GetRoutingID();
- params.main_frame_routing_id = main_render_frame_host_->routing_id();
+ params.main_frame_routing_id = main_render_frame_host()->routing_id();
params.surface_id = surface_id();
params.session_storage_namespace_id =
delegate_->GetSessionStorageNamespace(instance_)->id();
@@ -279,9 +327,6 @@ bool RenderViewHostImpl::CreateRenderView(
// Let our delegate know that we created a RenderView.
delegate_->RenderViewCreated(this);
- FOR_EACH_OBSERVER(
- RenderViewHostObserver, observers_, RenderViewHostInitialized());
-
return true;
}
@@ -299,6 +344,243 @@ void RenderViewHostImpl::SyncRendererPrefs() {
GetProcess()->GetBrowserContext())));
}
+WebPreferences RenderViewHostImpl::GetWebkitPrefs(const GURL& url) {
+ TRACE_EVENT0("browser", "RenderViewHostImpl::GetWebkitPrefs");
+ WebPreferences prefs;
+
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+
+ prefs.javascript_enabled =
+ !command_line.HasSwitch(switches::kDisableJavaScript);
+ prefs.web_security_enabled =
+ !command_line.HasSwitch(switches::kDisableWebSecurity);
+ prefs.plugins_enabled =
+ !command_line.HasSwitch(switches::kDisablePlugins);
+ prefs.java_enabled =
+ !command_line.HasSwitch(switches::kDisableJava);
+
+ prefs.remote_fonts_enabled =
+ !command_line.HasSwitch(switches::kDisableRemoteFonts);
+ prefs.xslt_enabled =
+ !command_line.HasSwitch(switches::kDisableXSLT);
+ prefs.xss_auditor_enabled =
+ !command_line.HasSwitch(switches::kDisableXSSAuditor);
+ prefs.application_cache_enabled =
+ !command_line.HasSwitch(switches::kDisableApplicationCache);
+
+ prefs.local_storage_enabled =
+ !command_line.HasSwitch(switches::kDisableLocalStorage);
+ prefs.databases_enabled =
+ !command_line.HasSwitch(switches::kDisableDatabases);
+#if defined(OS_ANDROID) && defined(ARCH_CPU_X86)
+ prefs.webaudio_enabled =
+ command_line.HasSwitch(switches::kEnableWebAudio);
+#else
+ prefs.webaudio_enabled =
+ !command_line.HasSwitch(switches::kDisableWebAudio);
+#endif
+
+ prefs.experimental_webgl_enabled =
+ GpuProcessHost::gpu_enabled() &&
+ !command_line.HasSwitch(switches::kDisable3DAPIs) &&
+ !command_line.HasSwitch(switches::kDisableExperimentalWebGL);
+
+ prefs.flash_3d_enabled =
+ GpuProcessHost::gpu_enabled() &&
+ !command_line.HasSwitch(switches::kDisableFlash3d);
+ prefs.flash_stage3d_enabled =
+ GpuProcessHost::gpu_enabled() &&
+ !command_line.HasSwitch(switches::kDisableFlashStage3d);
+ prefs.flash_stage3d_baseline_enabled =
+ GpuProcessHost::gpu_enabled() &&
+ !command_line.HasSwitch(switches::kDisableFlashStage3d);
+
+ prefs.gl_multisampling_enabled =
+ !command_line.HasSwitch(switches::kDisableGLMultisampling);
+ prefs.privileged_webgl_extensions_enabled =
+ command_line.HasSwitch(switches::kEnablePrivilegedWebGLExtensions);
+ prefs.site_specific_quirks_enabled =
+ !command_line.HasSwitch(switches::kDisableSiteSpecificQuirks);
+ prefs.allow_file_access_from_file_urls =
+ command_line.HasSwitch(switches::kAllowFileAccessFromFiles);
+
+ prefs.accelerated_compositing_for_overflow_scroll_enabled = false;
+ if (command_line.HasSwitch(switches::kEnableAcceleratedOverflowScroll))
+ prefs.accelerated_compositing_for_overflow_scroll_enabled = true;
+ if (command_line.HasSwitch(switches::kDisableAcceleratedOverflowScroll))
+ prefs.accelerated_compositing_for_overflow_scroll_enabled = false;
+
+ prefs.layer_squashing_enabled = false;
+ if (command_line.HasSwitch(switches::kEnableLayerSquashing))
+ prefs.layer_squashing_enabled = true;
+ if (command_line.HasSwitch(switches::kDisableLayerSquashing))
+ prefs.layer_squashing_enabled = false;
+
+ prefs.accelerated_compositing_for_scrollable_frames_enabled = false;
+ if (command_line.HasSwitch(switches::kEnableAcceleratedScrollableFrames))
+ prefs.accelerated_compositing_for_scrollable_frames_enabled = true;
+ if (command_line.HasSwitch(switches::kDisableAcceleratedScrollableFrames))
+ prefs.accelerated_compositing_for_scrollable_frames_enabled = false;
+
+ prefs.composited_scrolling_for_frames_enabled = false;
+ if (command_line.HasSwitch(switches::kEnableCompositedScrollingForFrames))
+ prefs.composited_scrolling_for_frames_enabled = true;
+ if (command_line.HasSwitch(switches::kDisableCompositedScrollingForFrames))
+ prefs.composited_scrolling_for_frames_enabled = false;
+
+ prefs.universal_accelerated_compositing_for_overflow_scroll_enabled = false;
+ if (command_line.HasSwitch(
+ switches::kEnableUniversalAcceleratedOverflowScroll))
+ prefs.universal_accelerated_compositing_for_overflow_scroll_enabled = true;
+ if (command_line.HasSwitch(
+ switches::kDisableUniversalAcceleratedOverflowScroll))
+ prefs.universal_accelerated_compositing_for_overflow_scroll_enabled = false;
+
+ prefs.show_paint_rects =
+ command_line.HasSwitch(switches::kShowPaintRects);
+ prefs.accelerated_compositing_enabled =
+ GpuProcessHost::gpu_enabled() &&
+ !command_line.HasSwitch(switches::kDisableAcceleratedCompositing);
+ prefs.force_compositing_mode =
+ content::IsForceCompositingModeEnabled() &&
+ !command_line.HasSwitch(switches::kDisableForceCompositingMode);
+ prefs.accelerated_2d_canvas_enabled =
+ GpuProcessHost::gpu_enabled() &&
+ !command_line.HasSwitch(switches::kDisableAccelerated2dCanvas);
+ prefs.antialiased_2d_canvas_disabled =
+ command_line.HasSwitch(switches::kDisable2dCanvasAntialiasing);
+ prefs.accelerated_2d_canvas_msaa_sample_count =
+ atoi(command_line.GetSwitchValueASCII(
+ switches::kAcceleratedCanvas2dMSAASampleCount).c_str());
+ prefs.accelerated_filters_enabled =
+ GpuProcessHost::gpu_enabled() &&
+ command_line.HasSwitch(switches::kEnableAcceleratedFilters);
+ prefs.accelerated_compositing_for_3d_transforms_enabled =
+ prefs.accelerated_compositing_for_animation_enabled =
+ !command_line.HasSwitch(switches::kDisableAcceleratedLayers);
+ prefs.accelerated_compositing_for_plugins_enabled =
+ !command_line.HasSwitch(switches::kDisableAcceleratedPlugins);
+ prefs.accelerated_compositing_for_video_enabled =
+ !command_line.HasSwitch(switches::kDisableAcceleratedVideo);
+ prefs.fullscreen_enabled =
+ !command_line.HasSwitch(switches::kDisableFullScreen);
+ prefs.lazy_layout_enabled =
+ command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures);
+ prefs.region_based_columns_enabled =
+ command_line.HasSwitch(switches::kEnableRegionBasedColumns);
+ prefs.threaded_html_parser =
+ !command_line.HasSwitch(switches::kDisableThreadedHTMLParser);
+ prefs.experimental_websocket_enabled =
+ command_line.HasSwitch(switches::kEnableExperimentalWebSocket);
+ if (command_line.HasSwitch(cc::switches::kEnablePinchVirtualViewport)) {
+ prefs.pinch_virtual_viewport_enabled = true;
+ prefs.pinch_overlay_scrollbar_thickness = 10;
+ }
+ prefs.use_solid_color_scrollbars = command_line.HasSwitch(
+ switches::kEnableOverlayScrollbars);
+
+#if defined(OS_ANDROID)
+ prefs.user_gesture_required_for_media_playback = !command_line.HasSwitch(
+ switches::kDisableGestureRequirementForMediaPlayback);
+ prefs.user_gesture_required_for_media_fullscreen = !command_line.HasSwitch(
+ switches::kDisableGestureRequirementForMediaFullscreen);
+#endif
+
+ prefs.touch_enabled = ui::AreTouchEventsEnabled();
+ prefs.device_supports_touch = prefs.touch_enabled &&
+ ui::IsTouchDevicePresent();
+#if defined(OS_ANDROID)
+ prefs.device_supports_mouse = false;
+#endif
+
+ prefs.pointer_events_max_touch_points = ui::MaxTouchPoints();
+
+ prefs.touch_adjustment_enabled =
+ !command_line.HasSwitch(switches::kDisableTouchAdjustment);
+ prefs.compositor_touch_hit_testing =
+ !command_line.HasSwitch(cc::switches::kDisableCompositorTouchHitTesting);
+
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
+ bool default_enable_scroll_animator = true;
+#else
+ bool default_enable_scroll_animator = false;
+#endif
+ prefs.enable_scroll_animator = default_enable_scroll_animator;
+ if (command_line.HasSwitch(switches::kEnableSmoothScrolling))
+ prefs.enable_scroll_animator = true;
+ if (command_line.HasSwitch(switches::kDisableSmoothScrolling))
+ prefs.enable_scroll_animator = false;
+
+ prefs.visual_word_movement_enabled =
+ command_line.HasSwitch(switches::kEnableVisualWordMovement);
+
+ // Certain GPU features might have been blacklisted.
+ GpuDataManagerImpl::GetInstance()->UpdateRendererWebPrefs(&prefs);
+
+ if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ GetProcess()->GetID())) {
+ prefs.loads_images_automatically = true;
+ prefs.javascript_enabled = true;
+ }
+
+ prefs.is_online = !net::NetworkChangeNotifier::IsOffline();
+
+#if !defined(USE_AURA)
+ // Force accelerated compositing and 2d canvas off for chrome: and about:
+ // pages (unless it's specifically allowed).
+ if ((url.SchemeIs(chrome::kChromeUIScheme) ||
+ (url.SchemeIs(chrome::kAboutScheme) &&
+ url.spec() != kAboutBlankURL)) &&
+ !command_line.HasSwitch(switches::kAllowWebUICompositing)) {
+ prefs.accelerated_compositing_enabled = false;
+ prefs.accelerated_2d_canvas_enabled = false;
+ }
+#endif
+
+ prefs.fixed_position_creates_stacking_context = !command_line.HasSwitch(
+ switches::kDisableFixedPositionCreatesStackingContext);
+
+#if defined(OS_CHROMEOS)
+ prefs.gesture_tap_highlight_enabled = !command_line.HasSwitch(
+ switches::kDisableGestureTapHighlight);
+#else
+ prefs.gesture_tap_highlight_enabled = command_line.HasSwitch(
+ switches::kEnableGestureTapHighlight);
+#endif
+
+ prefs.number_of_cpu_cores = base::SysInfo::NumberOfProcessors();
+
+ prefs.viewport_meta_enabled =
+ command_line.HasSwitch(switches::kEnableViewportMeta);
+
+ prefs.viewport_enabled =
+ command_line.HasSwitch(switches::kEnableViewport) ||
+ prefs.viewport_meta_enabled;
+
+ prefs.main_frame_resizes_are_orientation_changes =
+ command_line.HasSwitch(switches::kMainFrameResizesAreOrientationChanges);
+
+ prefs.deferred_image_decoding_enabled =
+ command_line.HasSwitch(switches::kEnableDeferredImageDecoding) ||
+ cc::switches::IsImplSidePaintingEnabled();
+
+ prefs.spatial_navigation_enabled = command_line.HasSwitch(
+ switches::kEnableSpatialNavigation);
+
+ GetContentClient()->browser()->OverrideWebkitPrefs(this, url, &prefs);
+
+ // Disable compositing in guests until we have compositing path implemented
+ // for guests.
+ bool guest_compositing_enabled = !command_line.HasSwitch(
+ switches::kDisableBrowserPluginCompositing);
+ if (GetProcess()->IsGuest() && !guest_compositing_enabled) {
+ prefs.force_compositing_mode = false;
+ prefs.accelerated_compositing_enabled = false;
+ }
+
+ return prefs;
+}
+
void RenderViewHostImpl::Navigate(const ViewMsg_Navigate_Params& params) {
TRACE_EVENT0("renderer_host", "RenderViewHostImpl::Navigate");
// Browser plugin guests are not allowed to navigate outside web-safe schemes,
@@ -345,8 +627,6 @@ void RenderViewHostImpl::Navigate(const ViewMsg_Navigate_Params& params) {
// don't want to either.
if (!params.url.SchemeIs(kJavaScriptScheme))
delegate_->DidStartLoading(this);
-
- FOR_EACH_OBSERVER(RenderViewHostObserver, observers_, Navigate(params.url));
}
void RenderViewHostImpl::NavigateToURL(const GURL& url) {
@@ -425,6 +705,27 @@ void RenderViewHostImpl::FirePageBeforeUnload(bool for_cross_site_transition) {
}
}
+void RenderViewHostImpl::OnCrossSiteResponse(
+ const GlobalRequestID& global_request_id,
+ bool is_transfer,
+ const std::vector<GURL>& transfer_url_chain,
+ const Referrer& referrer,
+ PageTransition page_transition,
+ int64 frame_id,
+ bool should_replace_current_entry) {
+ RenderViewHostDelegate::RendererManagement* manager =
+ delegate_->GetRendererManagementDelegate();
+ if (manager) {
+ manager->OnCrossSiteResponse(this, global_request_id, is_transfer,
+ transfer_url_chain, referrer, page_transition,
+ frame_id, should_replace_current_entry);
+ }
+}
+
+void RenderViewHostImpl::SuppressDialogsUntilSwapOut() {
+ Send(new ViewMsg_SuppressDialogsUntilSwapOut(GetRoutingID()));
+}
+
void RenderViewHostImpl::SwapOut() {
// This will be set back to false in OnSwapOutACK, just before we replace
// this RVH with the pending RVH.
@@ -576,6 +877,10 @@ void RenderViewHostImpl::ActivateNearestFindResult(int request_id,
void RenderViewHostImpl::RequestFindMatchRects(int current_version) {
Send(new ViewMsg_FindMatchRects(GetRoutingID(), current_version));
}
+
+void RenderViewHostImpl::DisableFullscreenEncryptedMediaPlayback() {
+ media_player_manager_->DisableFullscreenEncryptedMediaPlayback();
+}
#endif
void RenderViewHostImpl::DragTargetDragEnter(
@@ -625,12 +930,8 @@ void RenderViewHostImpl::DragTargetDragEnter(
// 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, path)) {
+ if (!policy->CanReadFile(renderer_id, path))
policy->GrantReadFile(renderer_id, path);
- // Allow dragged directories to be enumerated by the child process.
- // Note that we can't tell a file from a directory at this point.
- policy->GrantReadDirectory(renderer_id, path);
- }
}
fileapi::IsolatedContext* isolated_context =
@@ -681,8 +982,9 @@ void RenderViewHostImpl::DesktopNotificationPostDisplay(int callback_context) {
callback_context));
}
-void RenderViewHostImpl::DesktopNotificationPostError(int notification_id,
- const string16& message) {
+void RenderViewHostImpl::DesktopNotificationPostError(
+ int notification_id,
+ const base::string16& message) {
Send(new DesktopNotificationMsg_PostError(
GetRoutingID(), notification_id, message));
}
@@ -698,15 +1000,15 @@ void RenderViewHostImpl::DesktopNotificationPostClick(int notification_id) {
}
void RenderViewHostImpl::ExecuteJavascriptInWebFrame(
- const string16& frame_xpath,
- const string16& jscript) {
+ const base::string16& frame_xpath,
+ const base::string16& jscript) {
Send(new ViewMsg_ScriptEvalRequest(GetRoutingID(), frame_xpath, jscript,
0, false));
}
void RenderViewHostImpl::ExecuteJavascriptInWebFrameCallbackResult(
- const string16& frame_xpath,
- const string16& jscript,
+ const base::string16& frame_xpath,
+ const base::string16& jscript,
const JavascriptResultCallback& callback) {
static int next_id = 1;
int key = next_id++;
@@ -715,9 +1017,10 @@ void RenderViewHostImpl::ExecuteJavascriptInWebFrameCallbackResult(
javascript_callbacks_.insert(std::make_pair(key, callback));
}
-void RenderViewHostImpl::JavaScriptDialogClosed(IPC::Message* reply_msg,
- bool success,
- const string16& user_input) {
+void RenderViewHostImpl::JavaScriptDialogClosed(
+ IPC::Message* reply_msg,
+ bool success,
+ const base::string16& user_input) {
GetProcess()->SetIgnoreInputEvents(false);
bool is_waiting =
is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_;
@@ -848,7 +1151,7 @@ void RenderViewHostImpl::FilesSelectedInChooser(
for (size_t i = 0; i < files.size(); ++i) {
const ui::SelectedFileInfo& file = files[i];
if (permissions == FileChooserParams::Save) {
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantCreateWriteFile(
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantCreateReadWriteFile(
GetProcess()->GetID(), file.local_path);
} else {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
@@ -909,20 +1212,9 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
}
}
- ObserverListBase<RenderViewHostObserver>::Iterator it(observers_);
- RenderViewHostObserver* observer;
- while ((observer = it.GetNext()) != NULL) {
- if (observer->OnMessageReceived(msg))
- return true;
- }
-
if (delegate_->OnMessageReceived(this, msg))
return true;
- // TODO(jochen): Consider removing message handlers that only add a this
- // pointer and forward the messages to the RenderViewHostDelegate. The
- // respective delegates can handle the messages themselves in their
- // OnMessageReceived implementation.
bool handled = true;
bool msg_is_ok = true;
IPC_BEGIN_MESSAGE_MAP_EX(RenderViewHostImpl, msg, msg_is_ok)
@@ -933,8 +1225,6 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunModal, OnRunModal)
IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady)
IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone, OnRenderProcessGone)
- IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartProvisionalLoadForFrame,
- OnDidStartProvisionalLoadForFrame)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidRedirectProvisionalLoad,
OnDidRedirectProvisionalLoad)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidFailProvisionalLoadWithError,
@@ -991,7 +1281,6 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
OnSelectionBoundsChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_ScriptEvalResponse, OnScriptEvalResponse)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidZoomURL, OnDidZoomURL)
- IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowSnapshot, OnGetWindowSnapshot)
IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_RequestPermission,
OnRequestDesktopNotificationPermission)
IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_Show,
@@ -1007,6 +1296,7 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_DomOperationResponse,
OnDomOperationResponse)
IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Events, OnAccessibilityEvents)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
// Have the super handle all other messages.
IPC_MESSAGE_UNHANDLED(
handled = RenderWidgetHostImpl::OnMessageReceived(msg))
@@ -1063,17 +1353,18 @@ void RenderViewHostImpl::CreateNewWindow(
FilterURL(policy, GetProcess(), true,
&validated_params.opener_security_origin);
- delegate_->CreateNewWindow(route_id, main_frame_route_id,
- validated_params, session_storage_namespace);
+ delegate_->CreateNewWindow(
+ GetProcess()->GetID(), route_id, main_frame_route_id, validated_params,
+ session_storage_namespace);
}
void RenderViewHostImpl::CreateNewWidget(int route_id,
- WebKit::WebPopupType popup_type) {
- delegate_->CreateNewWidget(route_id, popup_type);
+ blink::WebPopupType popup_type) {
+ delegate_->CreateNewWidget(GetProcess()->GetID(), route_id, popup_type);
}
void RenderViewHostImpl::CreateNewFullscreenWidget(int route_id) {
- delegate_->CreateNewFullscreenWidget(route_id);
+ delegate_->CreateNewFullscreenWidget(GetProcess()->GetID(), route_id);
}
void RenderViewHostImpl::OnShowView(int route_id,
@@ -1133,8 +1424,11 @@ void RenderViewHostImpl::OnRenderProcessGone(int status, int exit_code) {
render_view_termination_status_ =
static_cast<base::TerminationStatus>(status);
- // Reset state.
+ // Reset frame tree state.
+ // TODO(creis): Once subframes can be in different processes, we'll need to
+ // clear just the FrameTreeNodes affected by the crash (and their subtrees).
main_frame_id_ = -1;
+ delegate_->GetFrameTree()->SwapMainFrame(main_render_frame_host_.get());
// Our base class RenderWidgetHost needs to reset some stuff.
RendererExited(render_view_termination_status_, exit_code);
@@ -1149,8 +1443,7 @@ void RenderViewHostImpl::OnDidStartProvisionalLoadForFrame(
int64 parent_frame_id,
bool is_main_frame,
const GURL& url) {
- delegate_->DidStartProvisionalLoadForFrame(
- this, frame_id, parent_frame_id, is_main_frame, url);
+ NOTREACHED();
}
void RenderViewHostImpl::OnDidRedirectProvisionalLoad(
@@ -1274,8 +1567,8 @@ void RenderViewHostImpl::OnUpdateState(int32 page_id, const PageState& state) {
void RenderViewHostImpl::OnUpdateTitle(
int32 page_id,
- const string16& title,
- WebKit::WebTextDirection title_direction) {
+ const base::string16& title,
+ blink::WebTextDirection title_direction) {
if (title.length() > kMaxTitleChars) {
NOTREACHED() << "Renderer sent too many characters in title.";
return;
@@ -1408,7 +1701,7 @@ void RenderViewHostImpl::OnDidChangeScrollOffsetPinningForMainFrame(
void RenderViewHostImpl::OnDidChangeNumWheelEvents(int count) {
}
-void RenderViewHostImpl::OnSelectionChanged(const string16& text,
+void RenderViewHostImpl::OnSelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) {
if (view_)
@@ -1434,8 +1727,8 @@ void RenderViewHostImpl::OnRouteMessageEvent(
}
void RenderViewHostImpl::OnRunJavaScriptMessage(
- const string16& message,
- const string16& default_prompt,
+ const base::string16& message,
+ const base::string16& default_prompt,
const GURL& frame_url,
JavaScriptMessageType type,
IPC::Message* reply_msg) {
@@ -1449,7 +1742,7 @@ void RenderViewHostImpl::OnRunJavaScriptMessage(
}
void RenderViewHostImpl::OnRunBeforeUnloadConfirm(const GURL& frame_url,
- const string16& message,
+ const base::string16& message,
bool is_reload,
IPC::Message* reply_msg) {
// While a JS before unload dialog is showing, tabs in the same process
@@ -1494,8 +1787,8 @@ void RenderViewHostImpl::OnStartDragging(
if (policy->CanReadFile(GetProcess()->GetID(), path))
filtered_data.filenames.push_back(*it);
}
- ui::ScaleFactor scale_factor = GetScaleFactorForView(GetView());
- gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, scale_factor));
+ float scale = ui::GetImageScale(GetScaleFactorForView(GetView()));
+ gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, scale));
view->StartDragging(filtered_data, drag_operations_mask, image,
bitmap_offset_in_dip, event_info);
}
@@ -1520,6 +1813,15 @@ void RenderViewHostImpl::OnTakeFocus(bool reverse) {
}
void RenderViewHostImpl::OnFocusedNodeChanged(bool is_editable_node) {
+#if defined(OS_WIN) && defined(USE_AURA)
+ if (!is_editable_node && virtual_keyboard_requested_) {
+ virtual_keyboard_requested_ = false;
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(base::IgnoreResult(&DismissVirtualKeyboardTask)),
+ TimeDelta::FromMilliseconds(kVirtualKeyboardDisplayWaitTimeoutMs));
+ }
+#endif
NotificationService::current()->Notify(
NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
Source<RenderViewHost>(this),
@@ -1528,9 +1830,9 @@ void RenderViewHostImpl::OnFocusedNodeChanged(bool is_editable_node) {
void RenderViewHostImpl::OnAddMessageToConsole(
int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id) {
+ const base::string16& source_id) {
if (delegate_->AddMessageToConsole(level, message, line_no, source_id))
return;
@@ -1543,14 +1845,6 @@ void RenderViewHostImpl::OnAddMessageToConsole(
}
}
-void RenderViewHostImpl::AddObserver(RenderViewHostObserver* observer) {
- observers_.AddObserver(observer);
-}
-
-void RenderViewHostImpl::RemoveObserver(RenderViewHostObserver* observer) {
- observers_.RemoveObserver(observer);
-}
-
void RenderViewHostImpl::OnUserGesture() {
delegate_->OnUserGesture();
}
@@ -1638,11 +1932,11 @@ gfx::Rect RenderViewHostImpl::GetRootWindowResizerRect() const {
}
void RenderViewHostImpl::ForwardMouseEvent(
- const WebKit::WebMouseEvent& mouse_event) {
+ const blink::WebMouseEvent& mouse_event) {
// We make a copy of the mouse event because
// RenderWidgetHost::ForwardMouseEvent will delete |mouse_event|.
- WebKit::WebMouseEvent event_copy(mouse_event);
+ blink::WebMouseEvent event_copy(mouse_event);
RenderWidgetHostImpl::ForwardMouseEvent(event_copy);
switch (event_copy.type) {
@@ -1765,19 +2059,6 @@ void RenderViewHostImpl::FilterURL(ChildProcessSecurityPolicyImpl* policy,
}
}
-void RenderViewHost::AddCreatedCallback(const CreatedCallback& callback) {
- g_created_callbacks.Get().push_back(callback);
-}
-
-void RenderViewHost::RemoveCreatedCallback(const CreatedCallback& callback) {
- for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
- if (g_created_callbacks.Get().at(i).Equals(callback)) {
- g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
- return;
- }
- }
-}
-
void RenderViewHostImpl::SetAltErrorPageURL(const GURL& url) {
Send(new ViewMsg_SetAltErrorPageURL(GetRoutingID(), url));
}
@@ -1800,7 +2081,7 @@ void RenderViewHostImpl::DisownOpener() {
}
void RenderViewHostImpl::SetAccessibilityCallbackForTesting(
- const base::Callback<void(WebKit::WebAXEvent)>& callback) {
+ const base::Callback<void(blink::WebAXEvent)>& callback) {
accessibility_testing_callback_ = callback;
}
@@ -1812,12 +2093,15 @@ void RenderViewHostImpl::NotifyTimezoneChange() {
Send(new ViewMsg_TimezoneChange(GetRoutingID()));
}
-void RenderViewHostImpl::ClearFocusedNode() {
- Send(new ViewMsg_ClearFocusedNode(GetRoutingID()));
+void RenderViewHostImpl::GetAudioOutputControllers(
+ const GetAudioOutputControllersCallback& callback) const {
+ AudioRendererHost* audio_host =
+ static_cast<RenderProcessHostImpl*>(GetProcess())->audio_renderer_host();
+ audio_host->GetOutputControllers(GetRoutingID(), callback);
}
-void RenderViewHostImpl::SetZoomLevel(double level) {
- Send(new ViewMsg_SetZoomLevel(GetRoutingID(), level));
+void RenderViewHostImpl::ClearFocusedNode() {
+ Send(new ViewMsg_ClearFocusedNode(GetRoutingID()));
}
void RenderViewHostImpl::Zoom(PageZoom zoom) {
@@ -1829,12 +2113,12 @@ void RenderViewHostImpl::ReloadFrame() {
}
void RenderViewHostImpl::Find(int request_id,
- const string16& search_text,
- const WebKit::WebFindOptions& options) {
+ const base::string16& search_text,
+ const blink::WebFindOptions& options) {
Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options));
}
-void RenderViewHostImpl::InsertCSS(const string16& frame_xpath,
+void RenderViewHostImpl::InsertCSS(const base::string16& frame_xpath,
const std::string& css) {
Send(new ViewMsg_CSSInsertRequest(GetRoutingID(), frame_xpath, css));
}
@@ -1873,12 +2157,12 @@ void RenderViewHostImpl::CopyImageAt(int x, int y) {
}
void RenderViewHostImpl::ExecuteMediaPlayerActionAtLocation(
- const gfx::Point& location, const WebKit::WebMediaPlayerAction& action) {
+ const gfx::Point& location, const blink::WebMediaPlayerAction& action) {
Send(new ViewMsg_MediaPlayerActionAt(GetRoutingID(), location, action));
}
void RenderViewHostImpl::ExecutePluginActionAtLocation(
- const gfx::Point& location, const WebKit::WebPluginAction& action) {
+ const gfx::Point& location, const blink::WebPluginAction& action) {
Send(new ViewMsg_PluginActionAt(GetRoutingID(), location, action));
}
@@ -1905,9 +2189,9 @@ void RenderViewHostImpl::OnAccessibilityEvents(
for (unsigned i = 0; i < params.size(); i++) {
const AccessibilityHostMsg_EventParams& param = params[i];
- WebKit::WebAXEvent src_type = param.event_type;
- if (src_type == WebKit::WebAXEventLayoutComplete ||
- src_type == WebKit::WebAXEventLoadComplete) {
+ blink::WebAXEvent src_type = param.event_type;
+ if (src_type == blink::WebAXEventLayoutComplete ||
+ src_type == blink::WebAXEventLoadComplete) {
MakeAccessibilityNodeDataTree(param.nodes, &accessibility_tree_);
}
accessibility_testing_callback_.Run(src_type);
@@ -1956,15 +2240,6 @@ void RenderViewHostImpl::OnRequestDesktopNotificationPermission(
void RenderViewHostImpl::OnShowDesktopNotification(
const ShowDesktopNotificationHostMsgParams& params) {
- // Disallow HTML notifications from javascript: and file: schemes as this
- // allows unwanted cross-domain access.
- GURL url = params.contents_url;
- if (params.is_html &&
- (url.SchemeIs(kJavaScriptScheme) ||
- url.SchemeIs(chrome::kFileScheme))) {
- return;
- }
-
GetContentClient()->browser()->ShowDesktopNotification(
params, GetProcess()->GetID(), GetRoutingID(), false);
}
@@ -1992,27 +2267,15 @@ void RenderViewHostImpl::OnDomOperationResponse(
Details<DomOperationNotificationDetails>(&details));
}
-void RenderViewHostImpl::OnGetWindowSnapshot(const int snapshot_id) {
- std::vector<unsigned char> png;
-
- // This feature is behind the kEnableGpuBenchmarking command line switch
- // because it poses security concerns and should only be used for testing.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kEnableGpuBenchmarking)) {
- gfx::Rect view_bounds = GetView()->GetViewBounds();
- gfx::Rect snapshot_bounds(view_bounds.size());
- gfx::Size snapshot_size = snapshot_bounds.size();
-
- if (ui::GrabViewSnapshot(GetView()->GetNativeView(),
- &png, snapshot_bounds)) {
- Send(new ViewMsg_WindowSnapshotCompleted(
- GetRoutingID(), snapshot_id, snapshot_size, png));
- return;
- }
+void RenderViewHostImpl::OnFocusedNodeTouched(bool editable) {
+#if defined(OS_WIN) && defined(USE_AURA)
+ if (editable) {
+ virtual_keyboard_requested_ = base::win::DisplayVirtualKeyboard();
+ } else {
+ virtual_keyboard_requested_ = false;
+ base::win::DismissVirtualKeyboard();
}
-
- Send(new ViewMsg_WindowSnapshotCompleted(
- GetRoutingID(), snapshot_id, gfx::Size(), png));
+#endif
}
#if defined(OS_MACOSX) || defined(OS_ANDROID)
@@ -2031,11 +2294,6 @@ void RenderViewHostImpl::OnShowPopup(
}
#endif
-RenderFrameHostImpl* RenderViewHostImpl::main_render_frame_host() const {
- DCHECK_EQ(GetProcess(), main_render_frame_host_->GetProcess());
- return main_render_frame_host_.get();
-}
-
void RenderViewHostImpl::SetSwappedOut(bool is_swapped_out) {
// We update the number of RenderViews in a SiteInstance when the
// swapped out status of this RenderView gets flipped.
@@ -2068,4 +2326,13 @@ bool RenderViewHostImpl::CanAccessFilesOfPageState(
return true;
}
+void RenderViewHostImpl::AttachToFrameTree() {
+ FrameTree* frame_tree = delegate_->GetFrameTree();
+
+ frame_tree->SwapMainFrame(main_render_frame_host_.get());
+ if (main_frame_id() != FrameTreeNode::kInvalidFrameId) {
+ frame_tree->OnFirstNavigationAfterSwap(main_frame_id());
+ }
+}
+
} // 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 c4bfb7876d1..e92b9397c70 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -12,9 +12,8 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
-#include "base/observer_list.h"
#include "base/process/kill.h"
-#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/accessibility_node_data.h"
@@ -22,6 +21,7 @@
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/javascript_message_type.h"
+#include "content/public/common/page_transition_types.h"
#include "content/public/common/window_container_type.h"
#include "net/base/load_states.h"
#include "third_party/WebKit/public/web/WebAXEnums.h"
@@ -61,8 +61,8 @@ namespace content {
class BrowserMediaPlayerManager;
class ChildProcessSecurityPolicyImpl;
class PageState;
+class RenderFrameHostDelegate;
class RenderFrameHostImpl;
-class RenderViewHostObserver;
class RenderWidgetHostDelegate;
class SessionStorageNamespace;
class SessionStorageNamespaceImpl;
@@ -119,6 +119,7 @@ class CONTENT_EXPORT RenderViewHostImpl
RenderViewHostImpl(
SiteInstance* instance,
RenderViewHostDelegate* delegate,
+ RenderFrameHostDelegate* frame_delegate,
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
@@ -134,8 +135,9 @@ class CONTENT_EXPORT RenderViewHostImpl
virtual void DesktopNotificationPermissionRequestDone(
int callback_context) OVERRIDE;
virtual void DesktopNotificationPostDisplay(int callback_context) OVERRIDE;
- virtual void DesktopNotificationPostError(int notification_id,
- const string16& message) OVERRIDE;
+ virtual void DesktopNotificationPostError(
+ int notification_id,
+ const base::string16& message) OVERRIDE;
virtual void DesktopNotificationPostClose(int notification_id,
bool by_user) OVERRIDE;
virtual void DesktopNotificationPostClick(int notification_id) OVERRIDE;
@@ -145,7 +147,7 @@ class CONTENT_EXPORT RenderViewHostImpl
virtual void DisableScrollbarsForThreshold(const gfx::Size& size) OVERRIDE;
virtual void DragSourceEndedAt(
int client_x, int client_y, int screen_x, int screen_y,
- WebKit::WebDragOperation operation) OVERRIDE;
+ blink::WebDragOperation operation) OVERRIDE;
virtual void DragSourceMovedTo(
int client_x, int client_y, int screen_x, int screen_y) OVERRIDE;
virtual void DragSourceSystemDragEnded() OVERRIDE;
@@ -153,12 +155,12 @@ class CONTENT_EXPORT RenderViewHostImpl
const DropData& drop_data,
const gfx::Point& client_pt,
const gfx::Point& screen_pt,
- WebKit::WebDragOperationsMask operations_allowed,
+ blink::WebDragOperationsMask operations_allowed,
int key_modifiers) OVERRIDE;
virtual void DragTargetDragOver(
const gfx::Point& client_pt,
const gfx::Point& screen_pt,
- WebKit::WebDragOperationsMask operations_allowed,
+ blink::WebDragOperationsMask operations_allowed,
int key_modifiers) OVERRIDE;
virtual void DragTargetDragLeave() OVERRIDE;
virtual void DragTargetDrop(const gfx::Point& client_pt,
@@ -172,19 +174,20 @@ class CONTENT_EXPORT RenderViewHostImpl
int action, const CustomContextMenuContext& context) OVERRIDE;
virtual void ExecuteMediaPlayerActionAtLocation(
const gfx::Point& location,
- const WebKit::WebMediaPlayerAction& action) OVERRIDE;
- virtual void ExecuteJavascriptInWebFrame(const string16& frame_xpath,
- const string16& jscript) OVERRIDE;
+ const blink::WebMediaPlayerAction& action) OVERRIDE;
+ virtual void ExecuteJavascriptInWebFrame(
+ const base::string16& frame_xpath,
+ const base::string16& jscript) OVERRIDE;
virtual void ExecuteJavascriptInWebFrameCallbackResult(
- const string16& frame_xpath,
- const string16& jscript,
+ const base::string16& frame_xpath,
+ const base::string16& jscript,
const JavascriptResultCallback& callback) OVERRIDE;
virtual void ExecutePluginActionAtLocation(
const gfx::Point& location,
- const WebKit::WebPluginAction& action) OVERRIDE;
+ const blink::WebPluginAction& action) OVERRIDE;
virtual void ExitFullscreen() OVERRIDE;
- virtual void Find(int request_id, const string16& search_text,
- const WebKit::WebFindOptions& options) OVERRIDE;
+ virtual void Find(int request_id, const base::string16& search_text,
+ const blink::WebFindOptions& options) OVERRIDE;
virtual void StopFinding(StopFindAction action) OVERRIDE;
virtual void FirePageBeforeUnload(bool for_cross_site_transition) OVERRIDE;
virtual void FilesSelectedInChooser(
@@ -193,7 +196,7 @@ class CONTENT_EXPORT RenderViewHostImpl
virtual RenderViewHostDelegate* GetDelegate() const OVERRIDE;
virtual int GetEnabledBindings() const OVERRIDE;
virtual SiteInstance* GetSiteInstance() const OVERRIDE;
- virtual void InsertCSS(const string16& frame_xpath,
+ virtual void InsertCSS(const base::string16& frame_xpath,
const std::string& css) OVERRIDE;
virtual bool IsRenderViewLive() const OVERRIDE;
virtual bool IsSubframe() const OVERRIDE;
@@ -204,7 +207,6 @@ class CONTENT_EXPORT RenderViewHostImpl
virtual void SetAltErrorPageURL(const GURL& url) OVERRIDE;
virtual void SetWebUIProperty(const std::string& name,
const std::string& value) OVERRIDE;
- virtual void SetZoomLevel(double level) OVERRIDE;
virtual void Zoom(PageZoom zoom) OVERRIDE;
virtual void SyncRendererPrefs() OVERRIDE;
virtual void ToggleSpeechInput() OVERRIDE;
@@ -212,12 +214,15 @@ class CONTENT_EXPORT RenderViewHostImpl
virtual void UpdateWebkitPreferences(
const WebPreferences& prefs) OVERRIDE;
virtual void NotifyTimezoneChange() OVERRIDE;
+ virtual void GetAudioOutputControllers(
+ const GetAudioOutputControllersCallback& callback) const OVERRIDE;
#if defined(OS_ANDROID)
virtual void ActivateNearestFindResult(int request_id,
float x,
float y) OVERRIDE;
virtual void RequestFindMatchRects(int current_version) OVERRIDE;
+ virtual void DisableFullscreenEncryptedMediaPlayback() OVERRIDE;
#endif
void set_delegate(RenderViewHostDelegate* d) {
@@ -231,7 +236,7 @@ class CONTENT_EXPORT RenderViewHostImpl
// The |opener_route_id| parameter indicates which RenderView created this
// (MSG_ROUTING_NONE if none). If |max_page_id| is larger than -1, the
// RenderView is told to start issuing page IDs at |max_page_id| + 1.
- virtual bool CreateRenderView(const string16& frame_name,
+ virtual bool CreateRenderView(const base::string16& frame_name,
int opener_route_id,
int32 max_page_id);
@@ -239,6 +244,9 @@ class CONTENT_EXPORT RenderViewHostImpl
return render_view_termination_status_;
}
+ // Returns the content specific prefs for this RenderViewHost.
+ WebPreferences GetWebkitPrefs(const GURL& url);
+
// Sends the given navigation message. Use this rather than sending it
// yourself since this does the internal bookkeeping described below. This
// function takes ownership of the provided message pointer.
@@ -286,6 +294,25 @@ class CONTENT_EXPORT RenderViewHostImpl
// different process.
bool is_swapped_out() const { return is_swapped_out_; }
+ // Called on the pending RenderViewHost when the network response is ready to
+ // commit. We should ensure that the old RenderViewHost runs its unload
+ // handler and determine whether a transfer to a different RenderViewHost is
+ // needed.
+ void OnCrossSiteResponse(
+ const GlobalRequestID& global_request_id,
+ bool is_transfer,
+ const std::vector<GURL>& transfer_url_chain,
+ const Referrer& referrer,
+ PageTransition page_transition,
+ int64 frame_id,
+ bool should_replace_current_entry);
+
+ // Tells the renderer that this RenderView will soon be swapped out, and thus
+ // not to create any new modal dialogs until it happens. This must be done
+ // separately so that the PageGroupLoadDeferrers of any current dialogs are no
+ // longer on the stack when we attempt to swap it out.
+ void SuppressDialogsUntilSwapOut();
+
// Tells the renderer that this RenderView is being swapped out for one in a
// different renderer process. It should run its unload handler and move to
// a blank document. The renderer should preserve the Frame object until it
@@ -324,7 +351,7 @@ class CONTENT_EXPORT RenderViewHostImpl
// closed by the user.
void JavaScriptDialogClosed(IPC::Message* reply_msg,
bool success,
- const string16& user_input);
+ const base::string16& user_input);
// Tells the renderer view to focus the first (last if reverse is true) node.
void SetInitialFocus(bool reverse);
@@ -361,7 +388,7 @@ class CONTENT_EXPORT RenderViewHostImpl
virtual void LostCapture() OVERRIDE;
virtual void LostMouseLock() OVERRIDE;
virtual void ForwardMouseEvent(
- const WebKit::WebMouseEvent& mouse_event) OVERRIDE;
+ const blink::WebMouseEvent& mouse_event) OVERRIDE;
virtual void OnPointerEventActivate() OVERRIDE;
virtual void ForwardKeyboardEvent(
const NativeWebKeyboardEvent& key_event) OVERRIDE;
@@ -376,7 +403,7 @@ class CONTENT_EXPORT RenderViewHostImpl
// Creates a new RenderWidget with the given route id. |popup_type| indicates
// if this widget is a popup and what kind of popup it is (select, autofill).
- void CreateNewWidget(int route_id, WebKit::WebPopupType popup_type);
+ void CreateNewWidget(int route_id, blink::WebPopupType popup_type);
// Creates a full screen RenderWidget.
void CreateNewFullscreenWidget(int route_id);
@@ -389,7 +416,7 @@ class CONTENT_EXPORT RenderViewHostImpl
#if defined(OS_ANDROID)
BrowserMediaPlayerManager* media_player_manager() {
- return media_player_manager_;
+ return media_player_manager_.get();
}
void DidSelectPopupMenuItems(const std::vector<int>& selected_indices);
@@ -405,6 +432,8 @@ class CONTENT_EXPORT RenderViewHostImpl
is_subframe_ = is_subframe;
}
+ // TODO(creis): Remove this when we replace frame IDs with RenderFrameHost
+ // routing IDs.
int64 main_frame_id() const {
return main_frame_id_;
}
@@ -417,7 +446,7 @@ class CONTENT_EXPORT RenderViewHostImpl
// renderer process, and the accessibility tree it sent can be
// retrieved using accessibility_tree_for_testing().
void SetAccessibilityCallbackForTesting(
- const base::Callback<void(WebKit::WebAXEvent)>& callback);
+ const base::Callback<void(blink::WebAXEvent)>& callback);
// Only valid if SetAccessibilityCallbackForTesting was called and
// the callback was run at least once. Returns a snapshot of the
@@ -456,19 +485,29 @@ class CONTENT_EXPORT RenderViewHostImpl
bool empty_allowed,
GURL* url);
+ // Update the FrameTree to use this RenderViewHost's main frame
+ // RenderFrameHost. Called when the RenderViewHost is committed.
+ //
+ // TODO(ajwong): Remove once RenderViewHost no longer owns the main frame
+ // RenderFrameHost.
+ void AttachToFrameTree();
+
+ // The following IPC handlers are public so RenderFrameHost can call them,
+ // while we transition the code to not use RenderViewHost.
+ //
+ // TODO(nasko): Remove those methods once we are done moving navigation
+ // into RenderFrameHost.
+ void OnDidStartProvisionalLoadForFrame(int64 frame_id,
+ int64 parent_frame_id,
+ bool main_frame,
+ const GURL& url);
+
// NOTE: Do not add functions that just send an IPC message that are called in
// one or two places. Have the caller send the IPC message directly (unless
// the caller places are in different platforms, in which case it's better
// to keep them consistent).
protected:
- friend class RenderViewHostObserver;
-
- // Add and remove observers for filtering IPC messages. Clients must be sure
- // to remove the observer before they go away.
- void AddObserver(RenderViewHostObserver* observer);
- void RemoveObserver(RenderViewHostObserver* observer);
-
// RenderWidgetHost protected overrides.
virtual void OnUserGesture() OVERRIDE;
virtual void NotifyRendererUnresponsive() OVERRIDE;
@@ -490,10 +529,6 @@ class CONTENT_EXPORT RenderViewHostImpl
void OnRunModal(int opener_id, IPC::Message* reply_msg);
void OnRenderViewReady();
void OnRenderProcessGone(int status, int error_code);
- void OnDidStartProvisionalLoadForFrame(int64 frame_id,
- int64 parent_frame_id,
- bool main_frame,
- const GURL& url);
void OnDidRedirectProvisionalLoad(int32 page_id,
const GURL& source_url,
const GURL& target_url);
@@ -502,8 +537,8 @@ class CONTENT_EXPORT RenderViewHostImpl
void OnNavigate(const IPC::Message& msg);
void OnUpdateState(int32 page_id, const PageState& state);
void OnUpdateTitle(int32 page_id,
- const string16& title,
- WebKit::WebTextDirection title_direction);
+ const base::string16& title,
+ blink::WebTextDirection title_direction);
void OnUpdateEncoding(const std::string& encoding);
void OnUpdateTargetURL(int32 page_id, const GURL& url);
void OnClose();
@@ -524,7 +559,7 @@ class CONTENT_EXPORT RenderViewHostImpl
void OnDidChangeScrollOffsetPinningForMainFrame(bool is_pinned_to_left,
bool is_pinned_to_right);
void OnDidChangeNumWheelEvents(int count);
- void OnSelectionChanged(const string16& text,
+ void OnSelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range);
void OnSelectionBoundsChanged(
@@ -532,28 +567,28 @@ class CONTENT_EXPORT RenderViewHostImpl
void OnPasteFromSelectionClipboard();
void OnRouteCloseEvent();
void OnRouteMessageEvent(const ViewMsg_PostMessage_Params& params);
- void OnRunJavaScriptMessage(const string16& message,
- const string16& default_prompt,
+ void OnRunJavaScriptMessage(const base::string16& message,
+ const base::string16& default_prompt,
const GURL& frame_url,
JavaScriptMessageType type,
IPC::Message* reply_msg);
void OnRunBeforeUnloadConfirm(const GURL& frame_url,
- const string16& message,
+ const base::string16& message,
bool is_reload,
IPC::Message* reply_msg);
void OnStartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask operations_allowed,
+ blink::WebDragOperationsMask operations_allowed,
const SkBitmap& bitmap,
const gfx::Vector2d& bitmap_offset_in_dip,
const DragEventSourceInfo& event_info);
- void OnUpdateDragCursor(WebKit::WebDragOperation drag_operation);
+ void OnUpdateDragCursor(blink::WebDragOperation drag_operation);
void OnTargetDropACK();
void OnTakeFocus(bool reverse);
void OnFocusedNodeChanged(bool is_editable_node);
void OnAddMessageToConsole(int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id);
+ const base::string16& source_id);
void OnUpdateInspectorSetting(const std::string& key,
const std::string& value);
void OnShouldCloseACK(
@@ -575,31 +610,37 @@ class CONTENT_EXPORT RenderViewHostImpl
void OnDidAccessInitialDocument();
void OnDomOperationResponse(const std::string& json_string,
int automation_id);
- void OnGetWindowSnapshot(const int snapshot_id);
+ void OnFocusedNodeTouched(bool editable);
#if defined(OS_MACOSX) || defined(OS_ANDROID)
void OnShowPopup(const ViewHostMsg_ShowPopup_Params& params);
#endif
+ // TODO(nasko): Remove this accessor once RenderFrameHost moves into the frame
+ // tree.
+ RenderFrameHostImpl* main_render_frame_host() const {
+ return main_render_frame_host_.get();
+ }
+
private:
friend class TestRenderViewHost;
FRIEND_TEST_ALL_PREFIXES(RenderViewHostTest, BasicRenderFrameHost);
FRIEND_TEST_ALL_PREFIXES(RenderViewHostTest, RoutingIdSane);
- // TODO(nasko): Remove this accessor once RenderFrameHost moves into the frame
- // tree.
- RenderFrameHostImpl* main_render_frame_host() const;
-
// Sets whether this RenderViewHost is swapped out in favor of another,
// and clears any waiting state that is no longer relevant.
void SetSwappedOut(bool is_swapped_out);
bool CanAccessFilesOfPageState(const PageState& state) const;
- // This is an RenderFrameHost object associated with the top-level frame in
- // the page rendered by this RenderViewHost.
- // TODO(nasko): Remove this pointer once we have enough infrastructure to
- // move this to the top-level FrameTreeNode.
+ // All RenderViewHosts must have a RenderFrameHost for its main frame.
+ // Currently the RenderFrameHost is created in lock step on construction
+ // and a pointer to the main frame is given to the FrameTreeNode
+ // when the RenderViewHost commits (see AttachToFrameTree()).
+ //
+ // TODO(ajwong): Make this reference non-owning. The root FrameTreeNode of
+ // the FrameTree should be responsible for owning the main frame's
+ // RenderFrameHost.
scoped_ptr<RenderFrameHostImpl> main_render_frame_host_;
// Our delegate, which wants to know about changes in the RenderView.
@@ -683,7 +724,7 @@ class CONTENT_EXPORT RenderViewHostImpl
std::map<int, JavascriptResultCallback> javascript_callbacks_;
// Accessibility callback for testing.
- base::Callback<void(WebKit::WebAXEvent)> accessibility_testing_callback_;
+ base::Callback<void(blink::WebAXEvent)> accessibility_testing_callback_;
// The most recently received accessibility tree - for testing only.
AccessibilityNodeDataTreeNode accessibility_tree_;
@@ -694,16 +735,15 @@ class CONTENT_EXPORT RenderViewHostImpl
// The termination status of the last render view that terminated.
base::TerminationStatus render_view_termination_status_;
- // A list of observers that filter messages. Weak references.
- ObserverList<RenderViewHostObserver> observers_;
-
// When the last ShouldClose message was sent.
base::TimeTicks send_should_close_start_time_;
+ // Set to true if we requested the on screen keyboard to be displayed.
+ bool virtual_keyboard_requested_;
+
#if defined(OS_ANDROID)
// Manages all the android mediaplayer objects and handling IPCs for video.
- // This class inherits from RenderViewHostObserver.
- BrowserMediaPlayerManager* media_player_manager_;
+ scoped_ptr<BrowserMediaPlayerManager> media_player_manager_;
#endif
DISALLOW_COPY_AND_ASSIGN(RenderViewHostImpl);
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 f4d694fae42..e81e67fc34a 100644
--- a/chromium/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
@@ -5,8 +5,6 @@
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
-#include "content/browser/web_contents/navigation_controller_impl.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/port/browser/render_view_host_delegate_view.h"
@@ -17,6 +15,7 @@
#include "content/public/common/url_constants.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/test/test_content_browser_client.h"
+#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "net/base/net_util.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
@@ -62,8 +61,8 @@ class RenderViewHostTest : public RenderViewHostImplTestHarness {
// See RenderViewHost::OnNavigate for a discussion.
TEST_F(RenderViewHostTest, FilterAbout) {
test_rvh()->SendNavigate(1, GURL("about:cache"));
- ASSERT_TRUE(controller().GetActiveEntry());
- EXPECT_EQ(GURL(kAboutBlankURL), controller().GetActiveEntry()->GetURL());
+ ASSERT_TRUE(controller().GetVisibleEntry());
+ EXPECT_EQ(GURL(kAboutBlankURL), controller().GetVisibleEntry()->GetURL());
}
// Create a full screen popup RenderWidgetHost and View.
@@ -126,14 +125,14 @@ class MockDraggingRenderViewHostDelegateView
bool right_aligned,
bool allow_multiple_selection) OVERRIDE {}
virtual void StartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask allowed_ops,
+ blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) OVERRIDE {
drag_url_ = drop_data.url;
html_base_url_ = drop_data.html_base_url;
}
- virtual void UpdateDragCursor(WebKit::WebDragOperation operation) OVERRIDE {}
+ virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE {}
virtual void GotFocus() OVERRIDE {}
virtual void TakeFocus(bool reverse) OVERRIDE {}
virtual void UpdatePreferredSize(const gfx::Size& pref_size) {}
@@ -200,10 +199,10 @@ TEST_F(RenderViewHostTest, DragEnteredFileURLsStillBlocked) {
GURL sensitive_file_url = net::FilePathToFileURL(sensitive_file_path);
dropped_data.url = highlighted_file_url;
dropped_data.filenames.push_back(DropData::FileInfo(
- UTF8ToUTF16(dragged_file_path.AsUTF8Unsafe()), string16()));
+ UTF8ToUTF16(dragged_file_path.AsUTF8Unsafe()), base::string16()));
rvh()->DragTargetDragEnter(dropped_data, client_point, screen_point,
- WebKit::WebDragOperationNone, 0);
+ blink::WebDragOperationNone, 0);
int id = process()->GetID();
ChildProcessSecurityPolicyImpl* policy =
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.cc b/chromium/content/browser/renderer_host/render_widget_helper.cc
index e7e25953c40..10e4e0ffa1f 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.cc
+++ b/chromium/content/browser/renderer_host/render_widget_helper.cc
@@ -300,7 +300,7 @@ void RenderWidgetHelper::OnResumeRequestsForView(int route_id) {
}
void RenderWidgetHelper::CreateNewWidget(int opener_id,
- WebKit::WebPopupType popup_type,
+ blink::WebPopupType popup_type,
int* route_id,
int* surface_id) {
*route_id = GetNextRoutingID();
@@ -327,7 +327,7 @@ void RenderWidgetHelper::CreateNewFullscreenWidget(int opener_id,
}
void RenderWidgetHelper::OnCreateWidgetOnUI(
- int opener_id, int route_id, WebKit::WebPopupType popup_type) {
+ int opener_id, int route_id, blink::WebPopupType popup_type) {
RenderViewHostImpl* host = RenderViewHostImpl::FromID(
render_process_id_, opener_id);
if (host)
@@ -381,7 +381,7 @@ void RenderWidgetHelper::FreeTransportDIB(TransportDIB::Id dib_id) {
i = allocated_dibs_.find(dib_id);
if (i != allocated_dibs_.end()) {
- if (HANDLE_EINTR(close(i->second)) < 0)
+ if (IGNORE_EINTR(close(i->second)) < 0)
PLOG(ERROR) << "close";
allocated_dibs_.erase(i);
} else {
@@ -392,7 +392,7 @@ void RenderWidgetHelper::FreeTransportDIB(TransportDIB::Id dib_id) {
void RenderWidgetHelper::ClearAllocatedDIBs() {
for (std::map<TransportDIB::Id, int>::iterator
i = allocated_dibs_.begin(); i != allocated_dibs_.end(); ++i) {
- if (HANDLE_EINTR(close(i->second)) < 0)
+ if (IGNORE_EINTR(close(i->second)) < 0)
PLOG(ERROR) << "close: " << i->first;
}
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.h b/chromium/content/browser/renderer_host/render_widget_helper.h
index c5e80a1a296..a81b1ded47d 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.h
+++ b/chromium/content/browser/renderer_host/render_widget_helper.h
@@ -153,7 +153,7 @@ class RenderWidgetHelper
int* surface_id,
SessionStorageNamespace* session_storage_namespace);
void CreateNewWidget(int opener_id,
- WebKit::WebPopupType popup_type,
+ blink::WebPopupType popup_type,
int* route_id,
int* surface_id);
void CreateNewFullscreenWidget(int opener_id, int* route_id, int* surface_id);
@@ -207,7 +207,7 @@ class RenderWidgetHelper
// Called on the UI thread to finish creating a widget.
void OnCreateWidgetOnUI(int opener_id,
int route_id,
- WebKit::WebPopupType popup_type);
+ blink::WebPopupType popup_type);
// Called on the UI thread to create a fullscreen widget.
void OnCreateFullscreenWidgetOnUI(int opener_id, int route_id);
diff --git a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
index bfdf6a5450a..f9b3fd3519e 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -47,7 +47,8 @@ class RenderWidgetHostBrowserTest : public ContentBrowserTest {
};
// Disabled on Windows and CrOS because it is flaky: crbug.com/272379.
-#if defined(OS_WIN) || defined(OS_CHROMEOS)
+// Disabled on Ozone due to flake: crbug.com/315392.
+#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(USE_OZONE)
#define MAYBE_GetSnapshotFromRendererTest DISABLED_GetSnapshotFromRendererTest
#else
#define MAYBE_GetSnapshotFromRendererTest GetSnapshotFromRendererTest
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 73f5325f5dd..efc1915c87e 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -13,7 +13,7 @@ bool RenderWidgetHostDelegate::PreHandleKeyboardEvent(
}
bool RenderWidgetHostDelegate::PreHandleWheelEvent(
- const WebKit::WebMouseWheelEvent& event) {
+ const blink::WebMouseWheelEvent& event) {
return false;
}
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 9e8d36ea092..22f5a19a489 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
@@ -9,7 +9,7 @@
#include "content/common/content_export.h"
#include "ui/gfx/native_widget_types.h"
-namespace WebKit {
+namespace blink {
class WebMouseWheelEvent;
}
@@ -44,7 +44,7 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// Callback to give the browser a chance to handle the specified mouse wheel
// event before sending it to the renderer.
// Returns true if the |event| was handled.
- virtual bool PreHandleWheelEvent(const WebKit::WebMouseWheelEvent& event);
+ virtual bool PreHandleWheelEvent(const blink::WebMouseWheelEvent& event);
// Notifies that screen rects were sent to renderer process.
virtual void DidSendScreenRects(RenderWidgetHostImpl* rwh) {}
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 4fce8d8cb2d..fa181508f38 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -5,6 +5,7 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include <math.h>
+#include <set>
#include <utility>
#include "base/auto_reset.h"
@@ -29,8 +30,11 @@
#include "content/browser/renderer_host/backing_store.h"
#include "content/browser/renderer_host/backing_store_manager.h"
#include "content/browser/renderer_host/dip_util.h"
-#include "content/browser/renderer_host/input/buffered_input_router.h"
-#include "content/browser/renderer_host/input/immediate_input_router.h"
+#include "content/browser/renderer_host/input/input_router_impl.h"
+#include "content/browser/renderer_host/input/synthetic_gesture.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
+#include "content/browser/renderer_host/input/timeout_monitor.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -58,6 +62,7 @@
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/skbitmap_operations.h"
#include "ui/gfx/vector2d_conversions.h"
+#include "ui/snapshot/snapshot.h"
#include "webkit/common/cursors/webcursor.h"
#include "webkit/common/webpreferences.h"
@@ -72,12 +77,12 @@
using base::Time;
using base::TimeDelta;
using base::TimeTicks;
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebKeyboardEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebTextDirection;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTextDirection;
namespace content {
namespace {
@@ -90,9 +95,6 @@ bool g_check_for_pending_resize_ack = true;
// This timeout impacts the "choppiness" of our window resize perf.
const int kPaintMsgTimeoutMS = 50;
-base::LazyInstance<std::vector<RenderWidgetHost::CreatedCallback> >
-g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
-
typedef std::pair<int32, int32> RenderWidgetHostID;
typedef base::hash_map<RenderWidgetHostID, RenderWidgetHostImpl*>
RoutingIDWidgetMap;
@@ -181,14 +183,14 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
ignore_input_events_(false),
input_method_active_(false),
text_direction_updated_(false),
- text_direction_(WebKit::WebTextDirectionLeftToRight),
+ text_direction_(blink::WebTextDirectionLeftToRight),
text_direction_canceled_(false),
suppress_next_char_events_(false),
pending_mouse_lock_request_(false),
allow_privileged_mouse_lock_(false),
has_touch_handler_(false),
weak_factory_(this),
- last_input_number_(0) {
+ last_input_number_(static_cast<int64>(GetProcess()->GetID()) << 32) {
CHECK(delegate_);
if (routing_id_ == MSG_ROUTING_NONE) {
routing_id_ = process_->GetNextRoutingID();
@@ -211,8 +213,10 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
is_threaded_compositing_enabled_ = IsThreadedCompositingEnabled();
- g_routing_id_widget_map.Get().insert(std::make_pair(
- RenderWidgetHostID(process->GetID(), routing_id_), this));
+ std::pair<RoutingIDWidgetMap::iterator, bool> result =
+ g_routing_id_widget_map.Get().insert(std::make_pair(
+ RenderWidgetHostID(process->GetID(), routing_id_), this));
+ CHECK(result.second) << "Inserting a duplicate item!";
process_->AddRoute(routing_id_, this);
// If we're initially visible, tell the process host that we're alive.
@@ -223,17 +227,20 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
accessibility_mode_ =
BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
- for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
- g_created_callbacks.Get().at(i).Run(this);
-
- input_router_.reset(
- new ImmediateInputRouter(process_, this, this, routing_id_));
+ input_router_.reset(new InputRouterImpl(process_, this, this, routing_id_));
#if defined(USE_AURA)
bool overscroll_enabled = CommandLine::ForCurrentProcess()->
GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
SetOverscrollControllerEnabled(overscroll_enabled);
#endif
+
+ if (GetProcess()->IsGuest() || !CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableHangMonitor)) {
+ hang_monitor_timeout_.reset(new TimeoutMonitor(
+ base::Bind(&RenderWidgetHostImpl::RendererIsUnresponsive,
+ weak_factory_.GetWeakPtr())));
+ }
}
RenderWidgetHostImpl::~RenderWidgetHostImpl() {
@@ -313,21 +320,6 @@ RenderWidgetHostImpl* RenderWidgetHostImpl::From(RenderWidgetHost* rwh) {
return rwh->AsRenderWidgetHostImpl();
}
-// static
-void RenderWidgetHost::AddCreatedCallback(const CreatedCallback& callback) {
- g_created_callbacks.Get().push_back(callback);
-}
-
-// static
-void RenderWidgetHost::RemoveCreatedCallback(const CreatedCallback& callback) {
- for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
- if (g_created_callbacks.Get().at(i).Equals(callback)) {
- g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
- return;
- }
- }
-}
-
void RenderWidgetHostImpl::SetView(RenderWidgetHostView* view) {
view_ = RenderWidgetHostViewPort::FromRWHV(view);
@@ -335,6 +327,8 @@ void RenderWidgetHostImpl::SetView(RenderWidgetHostView* view) {
GpuSurfaceTracker::Get()->SetSurfaceHandle(
surface_id_, gfx::GLSurfaceHandle());
}
+
+ synthetic_gesture_controller_.reset();
}
RenderProcessHost* RenderWidgetHostImpl::GetProcess() const {
@@ -403,22 +397,28 @@ void RenderWidgetHostImpl::SendScreenRects() {
waiting_for_screen_rects_ack_ = true;
}
-base::TimeDelta
- RenderWidgetHostImpl::GetSyntheticGestureMessageInterval() const {
- return synthetic_gesture_controller_.GetSyntheticGestureMessageInterval();
-}
-
void RenderWidgetHostImpl::SetOverscrollControllerEnabled(bool enabled) {
if (!enabled)
overscroll_controller_.reset();
else if (!overscroll_controller_)
- overscroll_controller_.reset(new OverscrollController(this));
+ overscroll_controller_.reset(new OverscrollController());
}
void RenderWidgetHostImpl::SuppressNextCharEvents() {
suppress_next_char_events_ = true;
}
+void RenderWidgetHostImpl::FlushInput() {
+ input_router_->Flush();
+ if (synthetic_gesture_controller_)
+ synthetic_gesture_controller_->Flush(base::TimeTicks::Now());
+}
+
+void RenderWidgetHostImpl::SetNeedsFlush() {
+ if (view_)
+ view_->OnSetNeedsFlushInput();
+}
+
void RenderWidgetHostImpl::Init() {
DCHECK(process_->HasConnection());
@@ -458,6 +458,8 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
bool handled = true;
bool msg_is_ok = true;
IPC_BEGIN_MESSAGE_MAP_EX(RenderWidgetHostImpl, msg, msg_is_ok)
+ IPC_MESSAGE_HANDLER(InputHostMsg_QueueSyntheticGesture,
+ OnQueueSyntheticGesture)
IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady)
IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone, OnRenderProcessGone)
IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
@@ -475,8 +477,6 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_DidOverscroll, OnOverscrolled)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed, OnUpdateIsDelayed)
- IPC_MESSAGE_HANDLER(ViewHostMsg_BeginSmoothScroll, OnBeginSmoothScroll)
- IPC_MESSAGE_HANDLER(ViewHostMsg_BeginPinch, OnBeginPinch)
IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnFocus)
IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnBlur)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
@@ -625,7 +625,7 @@ void RenderWidgetHostImpl::WasResized() {
return;
if (!screen_info_) {
- screen_info_.reset(new WebKit::WebScreenInfo);
+ screen_info_.reset(new blink::WebScreenInfo);
GetWebScreenInfo(screen_info_.get());
}
@@ -905,156 +905,30 @@ bool RenderWidgetHostImpl::ScheduleComposite() {
return true;
}
-void RenderWidgetHostImpl::StartHangMonitorTimeout(TimeDelta delay) {
- if (!GetProcess()->IsGuest() && CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableHangMonitor)) {
- return;
- }
-
- // Set time_when_considered_hung_ if it's null. Also, update
- // time_when_considered_hung_ if the caller's request is sooner than the
- // existing one. This will have the side effect that the existing timeout will
- // be forgotten.
- Time requested_end_time = Time::Now() + delay;
- if (time_when_considered_hung_.is_null() ||
- time_when_considered_hung_ > requested_end_time)
- time_when_considered_hung_ = requested_end_time;
-
- // If we already have a timer with the same or shorter duration, then we can
- // wait for it to finish.
- if (hung_renderer_timer_.IsRunning() &&
- hung_renderer_timer_.GetCurrentDelay() <= delay) {
- // If time_when_considered_hung_ was null, this timer may fire early.
- // CheckRendererIsUnresponsive handles that by calling
- // StartHangMonitorTimeout with the remaining time.
- // If time_when_considered_hung_ was non-null, it means we still haven't
- // heard from the renderer so we leave time_when_considered_hung_ as is.
- return;
- }
-
- // Either the timer is not yet running, or we need to adjust the timer to
- // fire sooner.
- time_when_considered_hung_ = requested_end_time;
- hung_renderer_timer_.Stop();
- hung_renderer_timer_.Start(FROM_HERE, delay, this,
- &RenderWidgetHostImpl::CheckRendererIsUnresponsive);
+void RenderWidgetHostImpl::StartHangMonitorTimeout(base::TimeDelta delay) {
+ if (hang_monitor_timeout_)
+ hang_monitor_timeout_->Start(delay);
}
void RenderWidgetHostImpl::RestartHangMonitorTimeout() {
- // Setting to null will cause StartHangMonitorTimeout to restart the timer.
- time_when_considered_hung_ = Time();
- StartHangMonitorTimeout(
- TimeDelta::FromMilliseconds(hung_renderer_delay_ms_));
+ if (hang_monitor_timeout_)
+ hang_monitor_timeout_->Restart(
+ base::TimeDelta::FromMilliseconds(hung_renderer_delay_ms_));
}
void RenderWidgetHostImpl::StopHangMonitorTimeout() {
- time_when_considered_hung_ = Time();
+ if (hang_monitor_timeout_)
+ hang_monitor_timeout_->Stop();
RendererIsResponsive();
- // We do not bother to stop the hung_renderer_timer_ here in case it will be
- // started again shortly, which happens to be the common use case.
}
void RenderWidgetHostImpl::EnableFullAccessibilityMode() {
SetAccessibilityMode(AccessibilityModeComplete);
}
-static WebGestureEvent MakeGestureEvent(WebInputEvent::Type type,
- double timestamp_seconds,
- int x,
- int y,
- int modifiers) {
- WebGestureEvent result;
-
- result.type = type;
- result.x = x;
- result.y = y;
- result.sourceDevice = WebGestureEvent::Touchscreen;
- result.timeStampSeconds = timestamp_seconds;
- result.modifiers = modifiers;
-
- return result;
-}
-
-void RenderWidgetHostImpl::SimulateTouchGestureWithMouse(
- const WebMouseEvent& mouse_event) {
- int x = mouse_event.x, y = mouse_event.y;
- float dx = mouse_event.movementX, dy = mouse_event.movementY;
- static int startX = 0, startY = 0;
-
- switch (mouse_event.button) {
- case WebMouseEvent::ButtonLeft:
- if (mouse_event.type == WebInputEvent::MouseDown) {
- startX = x;
- startY = y;
- ForwardGestureEvent(MakeGestureEvent(
- WebInputEvent::GestureScrollBegin, mouse_event.timeStampSeconds,
- x, y, 0));
- }
- if (dx != 0 || dy != 0) {
- WebGestureEvent event = MakeGestureEvent(
- WebInputEvent::GestureScrollUpdate, mouse_event.timeStampSeconds,
- x, y, 0);
- event.data.scrollUpdate.deltaX = dx;
- event.data.scrollUpdate.deltaY = dy;
- ForwardGestureEvent(event);
- }
- if (mouse_event.type == WebInputEvent::MouseUp) {
- ForwardGestureEvent(MakeGestureEvent(
- WebInputEvent::GestureScrollEnd, mouse_event.timeStampSeconds,
- x, y, 0));
- }
- break;
- case WebMouseEvent::ButtonMiddle:
- if (mouse_event.type == WebInputEvent::MouseDown) {
- startX = x;
- startY = y;
- ForwardGestureEvent(MakeGestureEvent(
- WebInputEvent::GestureTapDown, mouse_event.timeStampSeconds,
- x, y, 0));
- }
- if (mouse_event.type == WebInputEvent::MouseUp) {
- ForwardGestureEvent(MakeGestureEvent(
- WebInputEvent::GestureTap, mouse_event.timeStampSeconds,
- x, y, 0));
- }
- break;
- case WebMouseEvent::ButtonRight:
- if (mouse_event.type == WebInputEvent::MouseDown) {
- startX = x;
- startY = y;
- ForwardGestureEvent(MakeGestureEvent(
- WebInputEvent::GestureScrollBegin, mouse_event.timeStampSeconds,
- x, y, 0));
- ForwardGestureEvent(MakeGestureEvent(
- WebInputEvent::GesturePinchBegin, mouse_event.timeStampSeconds,
- x, y, 0));
- }
- if (dx != 0 || dy != 0) {
- dx = pow(dy < 0 ? 0.998f : 1.002f, fabs(dy));
- WebGestureEvent event = MakeGestureEvent(
- WebInputEvent::GesturePinchUpdate, mouse_event.timeStampSeconds,
- startX, startY, 0);
- event.data.pinchUpdate.scale = dx;
- ForwardGestureEvent(event);
- }
- if (mouse_event.type == WebInputEvent::MouseUp) {
- ForwardGestureEvent(MakeGestureEvent(
- WebInputEvent::GesturePinchEnd, mouse_event.timeStampSeconds,
- x, y, 0));
- ForwardGestureEvent(MakeGestureEvent(
- WebInputEvent::GestureScrollEnd, mouse_event.timeStampSeconds,
- x, y, 0));
- }
- break;
- case WebMouseEvent::ButtonNone:
- break;
- }
-}
-
void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
- ForwardMouseEventWithLatencyInfo(
- MouseEventWithLatencyInfo(mouse_event,
- CreateRWHLatencyInfoIfNotExist(NULL)));
+ ForwardMouseEventWithLatencyInfo(MouseEventWithLatencyInfo(
+ mouse_event, CreateRWHLatencyInfoIfNotExist(NULL, mouse_event.type)));
}
void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
@@ -1067,6 +941,9 @@ void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
return;
}
+ if (IgnoreInputEvents())
+ return;
+
input_router_->SendMouseEvent(mouse_event);
}
@@ -1075,33 +952,39 @@ void RenderWidgetHostImpl::OnPointerEventActivate() {
void RenderWidgetHostImpl::ForwardWheelEvent(
const WebMouseWheelEvent& wheel_event) {
- ForwardWheelEventWithLatencyInfo(
- MouseWheelEventWithLatencyInfo(wheel_event,
- CreateRWHLatencyInfoIfNotExist(NULL)));
+ ForwardWheelEventWithLatencyInfo(MouseWheelEventWithLatencyInfo(
+ wheel_event, CreateRWHLatencyInfoIfNotExist(NULL, wheel_event.type)));
}
void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
const MouseWheelEventWithLatencyInfo& wheel_event) {
TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardWheelEvent");
+ if (IgnoreInputEvents())
+ return;
+
+ if (delegate_->PreHandleWheelEvent(wheel_event.event))
+ return;
+
input_router_->SendWheelEvent(wheel_event);
}
void RenderWidgetHostImpl::ForwardGestureEvent(
- const WebKit::WebGestureEvent& gesture_event) {
+ const blink::WebGestureEvent& gesture_event) {
ForwardGestureEventWithLatencyInfo(gesture_event, ui::LatencyInfo());
}
void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
- const WebKit::WebGestureEvent& gesture_event,
+ const blink::WebGestureEvent& gesture_event,
const ui::LatencyInfo& ui_latency) {
TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardGestureEvent");
// Early out if necessary, prior to performing latency logic.
if (IgnoreInputEvents())
return;
- ui::LatencyInfo latency_info = CreateRWHLatencyInfoIfNotExist(&ui_latency);
+ ui::LatencyInfo latency_info =
+ CreateRWHLatencyInfoIfNotExist(&ui_latency, gesture_event.type);
- if (gesture_event.type == WebKit::WebInputEvent::GestureScrollUpdate) {
+ if (gesture_event.type == blink::WebInputEvent::GestureScrollUpdate) {
latency_info.AddLatencyNumber(
ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_RWH_COMPONENT,
GetLatencyComponentId(),
@@ -1119,7 +1002,8 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
GetLatencyComponentId(),
original_component.sequence_number,
original_component.event_time,
- original_component.event_count);
+ original_component.event_count,
+ true);
}
}
@@ -1128,10 +1012,15 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
}
void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
- const WebKit::WebTouchEvent& touch_event,
+ const blink::WebTouchEvent& touch_event,
const ui::LatencyInfo& ui_latency) {
TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardTouchEvent");
- ui::LatencyInfo latency_info = CreateRWHLatencyInfoIfNotExist(&ui_latency);
+
+ // Always forward TouchEvents for touch stream consistency. They will be
+ // ignored if appropriate in FilterInputEvent().
+
+ ui::LatencyInfo latency_info =
+ CreateRWHLatencyInfoIfNotExist(&ui_latency, touch_event.type);
TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info);
input_router_->SendTouchEvent(touch_with_latency);
}
@@ -1139,8 +1028,68 @@ void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
void RenderWidgetHostImpl::ForwardKeyboardEvent(
const NativeWebKeyboardEvent& key_event) {
TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardKeyboardEvent");
- input_router_->SendKeyboardEvent(key_event,
- CreateRWHLatencyInfoIfNotExist(NULL));
+ if (IgnoreInputEvents())
+ return;
+
+ if (!process_->HasConnection())
+ return;
+
+ // First, let keypress listeners take a shot at handling the event. If a
+ // listener handles the event, it should not be propagated to the renderer.
+ if (KeyPressListenersHandleEvent(key_event)) {
+ // Some keypresses that are accepted by the listener might have follow up
+ // char events, which should be ignored.
+ if (key_event.type == WebKeyboardEvent::RawKeyDown)
+ suppress_next_char_events_ = true;
+ return;
+ }
+
+ if (key_event.type == WebKeyboardEvent::Char &&
+ (key_event.windowsKeyCode == ui::VKEY_RETURN ||
+ key_event.windowsKeyCode == ui::VKEY_SPACE)) {
+ OnUserGesture();
+ }
+
+ // Double check the type to make sure caller hasn't sent us nonsense that
+ // will mess up our key queue.
+ if (!WebInputEvent::isKeyboardEventType(key_event.type))
+ return;
+
+ if (suppress_next_char_events_) {
+ // If preceding RawKeyDown event was handled by the browser, then we need
+ // suppress all Char events generated by it. Please note that, one
+ // RawKeyDown event may generate multiple Char events, so we can't reset
+ // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown.
+ if (key_event.type == WebKeyboardEvent::Char)
+ return;
+ // We get a KeyUp or a RawKeyDown event.
+ suppress_next_char_events_ = false;
+ }
+
+ bool is_shortcut = false;
+
+ // Only pre-handle the key event if it's not handled by the input method.
+ if (delegate_ && !key_event.skip_in_browser) {
+ // We need to set |suppress_next_char_events_| to true if
+ // PreHandleKeyboardEvent() returns true, but |this| may already be
+ // destroyed at that time. So set |suppress_next_char_events_| true here,
+ // then revert it afterwards when necessary.
+ if (key_event.type == WebKeyboardEvent::RawKeyDown)
+ suppress_next_char_events_ = true;
+
+ // Tab switching/closing accelerators aren't sent to the renderer to avoid
+ // a hung/malicious renderer from interfering.
+ if (delegate_->PreHandleKeyboardEvent(key_event, &is_shortcut))
+ return;
+
+ if (key_event.type == WebKeyboardEvent::RawKeyDown)
+ suppress_next_char_events_ = false;
+ }
+
+ input_router_->SendKeyboardEvent(
+ key_event,
+ CreateRWHLatencyInfoIfNotExist(NULL, key_event.type),
+ is_shortcut);
}
void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible) {
@@ -1157,18 +1106,19 @@ void RenderWidgetHostImpl::DisableResizeAckCheckForTesting() {
}
ui::LatencyInfo RenderWidgetHostImpl::CreateRWHLatencyInfoIfNotExist(
- const ui::LatencyInfo* original) {
+ const ui::LatencyInfo* original, WebInputEvent::Type type) {
ui::LatencyInfo info;
if (original)
info = *original;
// In Aura, gesture event will already carry its original touch event's
// INPUT_EVENT_LATENCY_RWH_COMPONENT.
- if (!info.FindLatency(ui::INPUT_EVENT_LATENCY_RWH_COMPONENT,
+ if (!info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
GetLatencyComponentId(),
NULL)) {
- info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_RWH_COMPONENT,
+ info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
GetLatencyComponentId(),
++last_input_number_);
+ info.TraceEventType(WebInputEventTraits::GetName(type));
}
return info;
}
@@ -1205,7 +1155,7 @@ void RenderWidgetHostImpl::RemoveMouseEventCallback(
}
}
-void RenderWidgetHostImpl::GetWebScreenInfo(WebKit::WebScreenInfo* result) {
+void RenderWidgetHostImpl::GetWebScreenInfo(blink::WebScreenInfo* result) {
TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::GetWebScreenInfo");
if (GetView())
static_cast<RenderWidgetHostViewPort*>(GetView())->GetScreenInfo(result);
@@ -1236,6 +1186,11 @@ void RenderWidgetHostImpl::GetSnapshotFromRenderer(
const gfx::Rect& src_subrect,
const base::Callback<void(bool, const SkBitmap&)>& callback) {
TRACE_EVENT0("browser", "RenderWidgetHostImpl::GetSnapshotFromRenderer");
+ if (!view_) {
+ callback.Run(false, SkBitmap());
+ return;
+ }
+
pending_snapshots_.push(callback);
gfx::Rect copy_rect = src_subrect.IsEmpty() ?
@@ -1279,8 +1234,7 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
waiting_for_screen_rects_ack_ = false;
// Reset to ensure that input routing works with a new renderer.
- input_router_.reset(
- new ImmediateInputRouter(process_, this, this, routing_id_));
+ input_router_.reset(new InputRouterImpl(process_, this, this, routing_id_));
if (overscroll_controller_)
overscroll_controller_->Reset();
@@ -1305,6 +1259,8 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
}
BackingStoreManager::RemoveBackingStore(this);
+
+ synthetic_gesture_controller_.reset();
}
void RenderWidgetHostImpl::UpdateTextDirection(WebTextDirection direction) {
@@ -1331,9 +1287,21 @@ void RenderWidgetHostImpl::SetInputMethodActive(bool activate) {
Send(new ViewMsg_SetInputMethodActive(GetRoutingID(), activate));
}
+void RenderWidgetHostImpl::CandidateWindowShown() {
+ Send(new ViewMsg_CandidateWindowShown(GetRoutingID()));
+}
+
+void RenderWidgetHostImpl::CandidateWindowUpdated() {
+ Send(new ViewMsg_CandidateWindowUpdated(GetRoutingID()));
+}
+
+void RenderWidgetHostImpl::CandidateWindowHidden() {
+ Send(new ViewMsg_CandidateWindowHidden(GetRoutingID()));
+}
+
void RenderWidgetHostImpl::ImeSetComposition(
- const string16& text,
- const std::vector<WebKit::WebCompositionUnderline>& underlines,
+ const base::string16& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
int selection_end) {
Send(new ViewMsg_ImeSetComposition(
@@ -1341,7 +1309,7 @@ void RenderWidgetHostImpl::ImeSetComposition(
}
void RenderWidgetHostImpl::ImeConfirmComposition(
- const string16& text,
+ const base::string16& text,
const gfx::Range& replacement_range,
bool keep_selection) {
Send(new ViewMsg_ImeConfirmComposition(
@@ -1349,8 +1317,8 @@ void RenderWidgetHostImpl::ImeConfirmComposition(
}
void RenderWidgetHostImpl::ImeCancelComposition() {
- Send(new ViewMsg_ImeSetComposition(GetRoutingID(), string16(),
- std::vector<WebKit::WebCompositionUnderline>(), 0, 0));
+ Send(new ViewMsg_ImeSetComposition(GetRoutingID(), base::string16(),
+ std::vector<blink::WebCompositionUnderline>(), 0, 0));
}
void RenderWidgetHostImpl::ExtendSelectionAndDelete(
@@ -1392,11 +1360,6 @@ void RenderWidgetHostImpl::SetShouldAutoResize(bool enable) {
should_auto_resize_ = enable;
}
-bool RenderWidgetHostImpl::IsInOverscrollGesture() const {
- return overscroll_controller_.get() &&
- overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE;
-}
-
void RenderWidgetHostImpl::Destroy() {
NotificationService::current()->Notify(
NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
@@ -1413,21 +1376,9 @@ void RenderWidgetHostImpl::Destroy() {
delete this;
}
-void RenderWidgetHostImpl::CheckRendererIsUnresponsive() {
- // If we received a call to StopHangMonitorTimeout.
- if (time_when_considered_hung_.is_null())
- return;
-
- // If we have not waited long enough, then wait some more.
- Time now = Time::Now();
- if (now < time_when_considered_hung_) {
- StartHangMonitorTimeout(time_when_considered_hung_ - now);
- return;
- }
-
- // OK, looks like we have a hung renderer!
+void RenderWidgetHostImpl::RendererIsUnresponsive() {
NotificationService::current()->Notify(
- NOTIFICATION_RENDERER_PROCESS_HANG,
+ NOTIFICATION_RENDER_WIDGET_HOST_HANG,
Source<RenderWidgetHost>(this),
NotificationService::NoDetails());
is_unresponsive_ = true;
@@ -1458,7 +1409,7 @@ void RenderWidgetHostImpl::OnClose() {
}
void RenderWidgetHostImpl::OnSetTooltipText(
- const string16& tooltip_text,
+ const base::string16& tooltip_text,
WebTextDirection text_direction_hint) {
// First, add directionality marks around tooltip text if necessary.
// A naive solution would be to simply always wrap the text. However, on
@@ -1473,13 +1424,13 @@ void RenderWidgetHostImpl::OnSetTooltipText(
// trying to detect the directionality from the tooltip text rather than the
// element direction. One could argue that would be a preferable solution
// but we use the current approach to match Fx & IE's behavior.
- string16 wrapped_tooltip_text = tooltip_text;
+ base::string16 wrapped_tooltip_text = tooltip_text;
if (!tooltip_text.empty()) {
- if (text_direction_hint == WebKit::WebTextDirectionLeftToRight) {
+ if (text_direction_hint == blink::WebTextDirectionLeftToRight) {
// Force the tooltip to have LTR directionality.
wrapped_tooltip_text =
base::i18n::GetDisplayStringInLTRDirectionality(wrapped_tooltip_text);
- } else if (text_direction_hint == WebKit::WebTextDirectionRightToLeft &&
+ } else if (text_direction_hint == blink::WebTextDirectionRightToLeft &&
!base::i18n::IsRTL()) {
// Force the tooltip to have RTL directionality.
base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text);
@@ -1503,7 +1454,6 @@ void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
}
void RenderWidgetHostImpl::OnRequestMove(const gfx::Rect& pos) {
- // Note that we ignore the position.
if (view_) {
view_->SetBounds(pos);
Send(new ViewMsg_Move_ACK(routing_id_));
@@ -1553,6 +1503,13 @@ bool RenderWidgetHostImpl::OnSwapCompositorFrame(
uint32 output_surface_id = param.a;
param.b.AssignTo(frame.get());
+ bool fixed_page_scale =
+ frame->metadata.min_page_scale_factor ==
+ frame->metadata.max_page_scale_factor;
+ int updated_view_flags = fixed_page_scale ? InputRouter::FIXED_PAGE_SCALE
+ : InputRouter::VIEW_FLAGS_NONE;
+ input_router_->OnViewUpdated(updated_view_flags);
+
if (view_) {
view_->OnSwapCompositorFrame(output_surface_id, frame.Pass());
view_->DidReceiveRendererFrame();
@@ -1743,18 +1700,18 @@ void RenderWidgetHostImpl::DidUpdateBackingStore(
UMA_HISTOGRAM_TIMES("MPArch.RWH_TotalPaintTime", delta);
}
-void RenderWidgetHostImpl::OnBeginSmoothScroll(
- const ViewHostMsg_BeginSmoothScroll_Params& params) {
- if (!view_)
- return;
- synthetic_gesture_controller_.BeginSmoothScroll(view_, params);
-}
+void RenderWidgetHostImpl::OnQueueSyntheticGesture(
+ const SyntheticGesturePacket& gesture_packet) {
+ if (!synthetic_gesture_controller_) {
+ if (!view_)
+ return;
+ synthetic_gesture_controller_.reset(
+ new SyntheticGestureController(
+ view_->CreateSyntheticGestureTarget().Pass()));
+ }
-void RenderWidgetHostImpl::OnBeginPinch(
- const ViewHostMsg_BeginPinch_Params& params) {
- if (!view_)
- return;
- synthetic_gesture_controller_.BeginPinch(view_, params);
+ synthetic_gesture_controller_->QueueSyntheticGesture(
+ SyntheticGesture::Create(*gesture_packet.gesture_params()));
}
void RenderWidgetHostImpl::OnFocus() {
@@ -1875,7 +1832,8 @@ void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowCreated(
return;
}
- SetParent(hwnd, reinterpret_cast<HWND>(GetNativeViewId()));
+ SetParent(hwnd,
+ reinterpret_cast<HWND>(view_->GetParentForWindowlessPlugin()));
dummy_windows_for_activation_.push_back(hwnd);
}
@@ -1951,11 +1909,11 @@ void RenderWidgetHostImpl::ScrollBackingStoreRect(const gfx::Vector2d& delta,
backing_store->ScrollBackingStore(delta, clip_rect, view_size);
}
-void RenderWidgetHostImpl::Replace(const string16& word) {
+void RenderWidgetHostImpl::Replace(const base::string16& word) {
Send(new InputMsg_Replace(routing_id_, word));
}
-void RenderWidgetHostImpl::ReplaceMisspelling(const string16& word) {
+void RenderWidgetHostImpl::ReplaceMisspelling(const base::string16& word) {
Send(new InputMsg_ReplaceMisspelling(routing_id_, word));
}
@@ -1969,19 +1927,35 @@ bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
return false;
for (size_t i = 0; i < key_press_event_callbacks_.size(); i++) {
+ size_t original_size = key_press_event_callbacks_.size();
if (key_press_event_callbacks_[i].Run(event))
return true;
+
+ // Check whether the callback that just ran removed itself, in which case
+ // the iterator needs to be decremented to properly account for the removal.
+ size_t current_size = key_press_event_callbacks_.size();
+ if (current_size != original_size) {
+ DCHECK_EQ(original_size - 1, current_size);
+ --i;
+ }
}
return false;
}
InputEventAckState RenderWidgetHostImpl::FilterInputEvent(
- const WebKit::WebInputEvent& event, const ui::LatencyInfo& latency_info) {
- if (overscroll_controller() &&
- !overscroll_controller()->WillDispatchEvent(event, latency_info)) {
+ const blink::WebInputEvent& event, const ui::LatencyInfo& latency_info) {
+ // Don't ignore touch cancel events, since they may be sent while input
+ // events are being ignored in order to keep the renderer from getting
+ // confused about how many touches are active.
+ if (IgnoreInputEvents() && event.type != WebInputEvent::TouchCancel)
+ return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+
+ if (!process_->HasConnection())
return INPUT_EVENT_ACK_STATE_UNKNOWN;
- }
+
+ if (event.type == WebInputEvent::MouseDown)
+ OnUserGesture();
return view_ ? view_->FilterInputEvent(event)
: INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
@@ -2010,154 +1984,13 @@ void RenderWidgetHostImpl::OnHasTouchEventHandlers(bool has_handlers) {
#endif
}
-bool RenderWidgetHostImpl::OnSendKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info,
- bool* is_shortcut) {
- if (IgnoreInputEvents())
- return false;
-
- if (!process_->HasConnection())
- return false;
-
- // First, let keypress listeners take a shot at handling the event. If a
- // listener handles the event, it should not be propagated to the renderer.
- if (KeyPressListenersHandleEvent(key_event)) {
- // Some keypresses that are accepted by the listener might have follow up
- // char events, which should be ignored.
- if (key_event.type == WebKeyboardEvent::RawKeyDown)
- suppress_next_char_events_ = true;
- return false;
- }
-
- if (key_event.type == WebKeyboardEvent::Char &&
- (key_event.windowsKeyCode == ui::VKEY_RETURN ||
- key_event.windowsKeyCode == ui::VKEY_SPACE)) {
- OnUserGesture();
- }
-
- // Double check the type to make sure caller hasn't sent us nonsense that
- // will mess up our key queue.
- if (!WebInputEvent::isKeyboardEventType(key_event.type))
- return false;
-
- if (suppress_next_char_events_) {
- // If preceding RawKeyDown event was handled by the browser, then we need
- // suppress all Char events generated by it. Please note that, one
- // RawKeyDown event may generate multiple Char events, so we can't reset
- // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown.
- if (key_event.type == WebKeyboardEvent::Char)
- return false;
- // We get a KeyUp or a RawKeyDown event.
- suppress_next_char_events_ = false;
- }
-
- // Only pre-handle the key event if it's not handled by the input method.
- if (delegate_ && !key_event.skip_in_browser) {
- // We need to set |suppress_next_char_events_| to true if
- // PreHandleKeyboardEvent() returns true, but |this| may already be
- // destroyed at that time. So set |suppress_next_char_events_| true here,
- // then revert it afterwards when necessary.
- if (key_event.type == WebKeyboardEvent::RawKeyDown)
- suppress_next_char_events_ = true;
-
- // Tab switching/closing accelerators aren't sent to the renderer to avoid
- // a hung/malicious renderer from interfering.
- if (delegate_->PreHandleKeyboardEvent(key_event, is_shortcut))
- return false;
-
- if (key_event.type == WebKeyboardEvent::RawKeyDown)
- suppress_next_char_events_ = false;
- }
-
- return true;
-}
-
-bool RenderWidgetHostImpl::OnSendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) {
- if (IgnoreInputEvents())
- return false;
-
- if (delegate_->PreHandleWheelEvent(wheel_event.event))
- return false;
-
- return true;
-}
-
-bool RenderWidgetHostImpl::OnSendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) {
- if (IgnoreInputEvents())
- return false;
-
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSimulateTouchScreenWithMouse)) {
- SimulateTouchGestureWithMouse(mouse_event.event);
- return false;
- }
-
- return true;
-}
-
-bool RenderWidgetHostImpl::OnSendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) {
- return !IgnoreInputEvents();
-}
-
-bool RenderWidgetHostImpl::OnSendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) {
- if (IgnoreInputEvents())
- return false;
-
- if (!IsInOverscrollGesture() &&
- !input_router_->ShouldForwardGestureEvent(gesture_event)) {
- if (overscroll_controller_.get())
- overscroll_controller_->DiscardingGestureEvent(gesture_event.event);
- return false;
- }
-
- return true;
-}
-
-bool RenderWidgetHostImpl::OnSendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) {
- TRACE_EVENT_INSTANT0("input",
- "RenderWidgetHostImpl::OnSendMouseEventImmediately",
- TRACE_EVENT_SCOPE_THREAD);
- if (IgnoreInputEvents())
- return false;
-
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSimulateTouchScreenWithMouse)) {
- SimulateTouchGestureWithMouse(mouse_event.event);
- return false;
- }
-
- if (mouse_event.event.type == WebInputEvent::MouseDown)
- OnUserGesture();
-
- return true;
-}
-
-bool RenderWidgetHostImpl::OnSendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) {
- TRACE_EVENT_INSTANT0("input",
- "RenderWidgetHostImpl::OnSendTouchEventImmediately",
- TRACE_EVENT_SCOPE_THREAD);
- return !IgnoreInputEvents();
-}
-
-bool RenderWidgetHostImpl::OnSendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) {
- TRACE_EVENT_INSTANT0("input",
- "RenderWidgetHostImpl::OnSendGestureEventImmediately",
- TRACE_EVENT_SCOPE_THREAD);
- return !IgnoreInputEvents();
-}
-
-void RenderWidgetHostImpl::SetNeedsFlush() {
+OverscrollController* RenderWidgetHostImpl::GetOverscrollController() const {
+ return overscroll_controller_.get();
}
void RenderWidgetHostImpl::DidFlush() {
+ if (view_)
+ view_->OnDidFlushInput();
}
void RenderWidgetHostImpl::OnKeyboardEventAck(
@@ -2182,33 +2015,49 @@ void RenderWidgetHostImpl::OnKeyboardEventAck(
}
void RenderWidgetHostImpl::OnWheelEventAck(
- const WebKit::WebMouseWheelEvent& wheel_event,
+ const MouseWheelEventWithLatencyInfo& wheel_event,
InputEventAckState ack_result) {
- const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
- if (overscroll_controller_)
- overscroll_controller_->ReceivedEventACK(wheel_event, processed);
+ if (!wheel_event.latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL)) {
+ // MouseWheelEvent latency ends when it is acked but does not cause any
+ // rendering scheduled.
+ ui::LatencyInfo latency = wheel_event.latency;
+ latency.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, 0);
+ }
+ const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
if (!processed && !is_hidden() && view_)
- view_->UnhandledWheelEvent(wheel_event);
+ view_->UnhandledWheelEvent(wheel_event.event);
}
void RenderWidgetHostImpl::OnGestureEventAck(
- const WebKit::WebGestureEvent& event,
+ const GestureEventWithLatencyInfo& event,
InputEventAckState ack_result) {
- const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
- if (overscroll_controller_)
- overscroll_controller_->ReceivedEventACK(event, processed);
+ if (!event.latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL)) {
+ // GestureEvent latency ends when it is acked but does not cause any
+ // rendering scheduled.
+ ui::LatencyInfo latency = event.latency;
+ latency.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0 ,0);
+ }
if (view_)
- view_->GestureEventAck(event.type, ack_result);
+ view_->GestureEventAck(event.event.type, ack_result);
}
void RenderWidgetHostImpl::OnTouchEventAck(
const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) {
- ComputeTouchLatency(event.latency);
+ TouchEventWithLatencyInfo touch_event = event;
+ // TouchEvent latency does not end when acked since it could later on
+ // become gesture events.
+ touch_event.latency.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT, 0, 0);
+ ComputeTouchLatency(touch_event.latency);
if (view_)
- view_->ProcessAckedTouchEvent(event, ack_result);
+ view_->ProcessAckedTouchEvent(touch_event, ack_result);
}
void RenderWidgetHostImpl::OnUnexpectedEventAck(UnexpectedEventAckType type) {
@@ -2232,11 +2081,6 @@ bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const {
return input_router_->ShouldForwardTouchEvent();
}
-bool RenderWidgetHostImpl::ShouldForwardGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) const {
- return input_router_->ShouldForwardGestureEvent(gesture_event);
-}
-
void RenderWidgetHostImpl::StartUserGesture() {
OnUserGesture();
}
@@ -2445,10 +2289,12 @@ void RenderWidgetHostImpl::ParentChanged(gfx::NativeViewId new_parent) {
HWND hwnd = reinterpret_cast<HWND>(new_parent);
if (!hwnd)
hwnd = GetDesktopWindow();
- for (std::list<HWND>::iterator i = dummy_windows_for_activation_.begin();
- i != dummy_windows_for_activation_.end(); ++i) {
- SetParent(*i, hwnd);
- }
+ // On Windows GetParentForWindowlessPlugin returns the dummy window used as
+ // the parent for windowless NPAPI plugins. Reparenting this window to the
+ // new parent should be good enough.
+ if (view_ && view_->GetParentForWindowlessPlugin())
+ SetParent(reinterpret_cast<HWND>(view_->GetParentForWindowlessPlugin()),
+ reinterpret_cast<HWND>(new_parent));
#endif
}
@@ -2479,7 +2325,7 @@ void RenderWidgetHostImpl::ComputeTouchLatency(
if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT,
0,
&ui_component) ||
- !latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_RWH_COMPONENT,
+ !latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
GetLatencyComponentId(),
&rwh_component))
return;
@@ -2498,7 +2344,7 @@ void RenderWidgetHostImpl::ComputeTouchLatency(
20000,
100);
- if (latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_ACKED_COMPONENT,
+ if (latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT,
0,
&acked_component)) {
DCHECK(acked_component.event_count == 1);
@@ -2520,16 +2366,29 @@ void RenderWidgetHostImpl::ComputeTouchLatency(
}
void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
+ ui::LatencyInfo::LatencyComponent window_snapshot_component;
+ if (latency_info.FindLatency(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT,
+ GetLatencyComponentId(),
+ &window_snapshot_component)) {
+ WindowSnapshotReachedScreen(
+ static_cast<int>(window_snapshot_component.sequence_number));
+ }
+
ui::LatencyInfo::LatencyComponent rwh_component;
- if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_RWH_COMPONENT,
+ ui::LatencyInfo::LatencyComponent swap_component;
+ if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
GetLatencyComponentId(),
- &rwh_component))
+ &rwh_component) ||
+ !latency_info.FindLatency(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT,
+ 0, &swap_component)) {
return;
+ }
rendering_stats_.input_event_count += rwh_component.event_count;
rendering_stats_.total_input_latency +=
rwh_component.event_count *
- (latency_info.swap_timestamp - rwh_component.event_time);
+ (swap_component.event_time - rwh_component.event_time);
ui::LatencyInfo::LatencyComponent original_component;
if (latency_info.FindLatency(
@@ -2540,7 +2399,7 @@ void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
// created (averaged if there are multiple) to when the scroll gesture
// results in final frame swap.
base::TimeDelta delta =
- latency_info.swap_timestamp - original_component.event_time;
+ swap_component.event_time - original_component.event_time;
for (size_t i = 0; i < original_component.event_count; i++) {
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Event.Latency.TouchToScrollUpdateSwap",
@@ -2552,7 +2411,7 @@ void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
rendering_stats_.scroll_update_count += original_component.event_count;
rendering_stats_.total_scroll_update_latency +=
original_component.event_count *
- (latency_info.swap_timestamp - original_component.event_time);
+ (swap_component.event_time - original_component.event_time);
}
if (CommandLine::ForCurrentProcess()->HasSwitch(
@@ -2564,23 +2423,54 @@ void RenderWidgetHostImpl::DidReceiveRendererFrame() {
view_->DidReceiveRendererFrame();
}
+void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id) {
+ DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_UI));
+
+ std::vector<unsigned char> png;
+
+ // This feature is behind the kEnableGpuBenchmarking command line switch
+ // because it poses security concerns and should only be used for testing.
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kEnableGpuBenchmarking)) {
+ gfx::Rect view_bounds = GetView()->GetViewBounds();
+ gfx::Rect snapshot_bounds(view_bounds.size());
+ gfx::Size snapshot_size = snapshot_bounds.size();
+
+ if (ui::GrabViewSnapshot(GetView()->GetNativeView(),
+ &png, snapshot_bounds)) {
+ Send(new ViewMsg_WindowSnapshotCompleted(
+ GetRoutingID(), snapshot_id, snapshot_size, png));
+ return;
+ }
+ }
+
+ Send(new ViewMsg_WindowSnapshotCompleted(
+ GetRoutingID(), snapshot_id, gfx::Size(), png));
+}
+
// static
void RenderWidgetHostImpl::CompositorFrameDrawn(
const ui::LatencyInfo& latency_info) {
+ std::set<RenderWidgetHostImpl*> rwhi_set;
+
for (ui::LatencyInfo::LatencyMap::const_iterator b =
latency_info.latency_components.begin();
b != latency_info.latency_components.end();
++b) {
- if (b->first.first != ui::INPUT_EVENT_LATENCY_RWH_COMPONENT)
- continue;
- // Matches with GetLatencyComponentId
- int routing_id = b->first.second & 0xffffffff;
- int process_id = (b->first.second >> 32) & 0xffffffff;
- RenderWidgetHost* rwh =
- RenderWidgetHost::FromID(process_id, routing_id);
- if (!rwh)
- continue;
- RenderWidgetHostImpl::From(rwh)->FrameSwapped(latency_info);
+ if (b->first.first == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT ||
+ b->first.first == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
+ // Matches with GetLatencyComponentId
+ int routing_id = b->first.second & 0xffffffff;
+ int process_id = (b->first.second >> 32) & 0xffffffff;
+ RenderWidgetHost* rwh =
+ RenderWidgetHost::FromID(process_id, routing_id);
+ if (!rwh) {
+ continue;
+ }
+ RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
+ if (rwhi_set.insert(rwhi).second)
+ rwhi->FrameSwapped(latency_info);
+ }
}
}
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 613177c9a81..22dbdbe0084 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -25,8 +25,8 @@
#include "build/build_config.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/synthetic_gesture_controller.h"
#include "content/common/browser_rendering_stats.h"
+#include "content/common/input/synthetic_gesture_packet.h"
#include "content/common/view_message_enums.h"
#include "content/port/browser/event_with_latency_info.h"
#include "content/port/common/input_event_ack_state.h"
@@ -62,7 +62,7 @@ namespace ui {
class KeyEvent;
}
-namespace WebKit {
+namespace blink {
class WebInputEvent;
class WebMouseEvent;
struct WebCompositionUnderline;
@@ -70,7 +70,7 @@ struct WebScreenInfo;
}
#if defined(OS_ANDROID)
-namespace WebKit {
+namespace blink {
class WebLayer;
}
#endif
@@ -83,6 +83,7 @@ class OverscrollController;
class RenderWidgetHostDelegate;
class RenderWidgetHostViewPort;
class SyntheticGestureController;
+class TimeoutMonitor;
struct EditCommand;
// This implements the RenderWidgetHost interface that is exposed to
@@ -130,7 +131,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
virtual void Delete() OVERRIDE;
virtual void SelectAll() OVERRIDE;
virtual void Unselect() OVERRIDE;
- virtual void UpdateTextDirection(WebKit::WebTextDirection direction) OVERRIDE;
+ virtual void UpdateTextDirection(blink::WebTextDirection direction) OVERRIDE;
virtual void NotifyTextDirection() OVERRIDE;
virtual void Focus() OVERRIDE;
virtual void Blur() OVERRIDE;
@@ -149,9 +150,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
#endif
virtual void EnableFullAccessibilityMode() OVERRIDE;
virtual void ForwardMouseEvent(
- const WebKit::WebMouseEvent& mouse_event) OVERRIDE;
+ const blink::WebMouseEvent& mouse_event) OVERRIDE;
virtual void ForwardWheelEvent(
- const WebKit::WebMouseWheelEvent& wheel_event) OVERRIDE;
+ const blink::WebMouseWheelEvent& wheel_event) OVERRIDE;
virtual void ForwardKeyboardEvent(
const NativeWebKeyboardEvent& key_event) OVERRIDE;
virtual const gfx::Vector2d& GetLastScrollOffset() const OVERRIDE;
@@ -164,8 +165,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
int tag,
const gfx::Size& page_size,
const gfx::Size& desired_size) OVERRIDE;
- virtual void Replace(const string16& word) OVERRIDE;
- virtual void ReplaceMisspelling(const string16& word) OVERRIDE;
+ virtual void Replace(const base::string16& word) OVERRIDE;
+ virtual void ReplaceMisspelling(const base::string16& word) OVERRIDE;
virtual void ResizeRectChanged(const gfx::Rect& new_rect) OVERRIDE;
virtual void RestartHangMonitorTimeout() OVERRIDE;
virtual void SetIgnoreInputEvents(bool ignore_input_events) OVERRIDE;
@@ -179,7 +180,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
const MouseEventCallback& callback) OVERRIDE;
virtual void RemoveMouseEventCallback(
const MouseEventCallback& callback) OVERRIDE;
- virtual void GetWebScreenInfo(WebKit::WebScreenInfo* result) OVERRIDE;
+ virtual void GetWebScreenInfo(blink::WebScreenInfo* result) OVERRIDE;
virtual void GetSnapshotFromRenderer(
const gfx::Rect& src_subrect,
const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE;
@@ -287,12 +288,12 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// Forwards the given message to the renderer. These are called by the view
// when it has received a message.
- void ForwardGestureEvent(const WebKit::WebGestureEvent& gesture_event);
+ void ForwardGestureEvent(const blink::WebGestureEvent& gesture_event);
void ForwardGestureEventWithLatencyInfo(
- const WebKit::WebGestureEvent& gesture_event,
+ const blink::WebGestureEvent& gesture_event,
const ui::LatencyInfo& ui_latency);
void ForwardTouchEventWithLatencyInfo(
- const WebKit::WebTouchEvent& touch_event,
+ const blink::WebTouchEvent& touch_event,
const ui::LatencyInfo& ui_latency);
void ForwardMouseEventWithLatencyInfo(
const MouseEventWithLatencyInfo& mouse_event);
@@ -312,6 +313,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// display input method windows under the cursor.)
void SetInputMethodActive(bool activate);
+ // Notifies the renderer changes of IME candidate window state.
+ void CandidateWindowShown();
+ void CandidateWindowUpdated();
+ void CandidateWindowHidden();
+
// Update the composition node of the renderer (or WebKit).
// WebKit has a special node (a composition node) for input method to change
// its text without affecting any other DOM nodes. When the input method
@@ -328,8 +334,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// * when it receives a "preedit_changed" signal of GtkIMContext (on Linux);
// * when markedText of NSTextInput is called (on Mac).
void ImeSetComposition(
- const string16& text,
- const std::vector<WebKit::WebCompositionUnderline>& underlines,
+ const base::string16& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
int selection_end);
@@ -339,7 +345,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// (on Windows);
// * when it receives a "commit" signal of GtkIMContext (on Linux);
// * when insertText of NSTextInput is called (on Mac).
- void ImeConfirmComposition(const string16& text,
+ void ImeConfirmComposition(const base::string16& text,
const gfx::Range& replacement_range,
bool keep_selection);
@@ -368,8 +374,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// Event queries delegated to the |input_router_|.
bool ShouldForwardTouchEvent() const;
- bool ShouldForwardGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) const;
bool has_touch_handler() const { return has_touch_handler_; }
@@ -513,8 +517,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
return overscroll_controller_.get();
}
- base::TimeDelta GetSyntheticGestureMessageInterval() const;
-
// Sets whether the overscroll controller should be enabled for this page.
void SetOverscrollControllerEnabled(bool enabled);
@@ -522,6 +524,12 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// suppress_next_char_events_.
void SuppressNextCharEvents();
+ // Called by RenderWidgetHostView in response to OnSetNeedsFlushInput.
+ void FlushInput();
+
+ // InputRouterClient
+ virtual void SetNeedsFlush() OVERRIDE;
+
// Indicates whether the renderer drives the RenderWidgetHosts's size or the
// other way around.
bool should_auto_resize() { return should_auto_resize_; }
@@ -546,7 +554,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// component if it is not already in |original|. And if |original| is
// not NULL, it is also merged into the resulting LatencyInfo.
ui::LatencyInfo CreateRWHLatencyInfoIfNotExist(
- const ui::LatencyInfo* original);
+ const ui::LatencyInfo* original, blink::WebInputEvent::Type type);
// Called when we receive a notification indicating that the renderer
// process has gone. This will reset our state so that our state will be
@@ -566,7 +574,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// its delegate.
// Called when a mousewheel event was not processed by the renderer.
- virtual void UnhandledWheelEvent(const WebKit::WebMouseWheelEvent& event) {}
+ virtual void UnhandledWheelEvent(const blink::WebMouseWheelEvent& event) {}
// Notification that the user has made some kind of input that could
// perform an action. The gestures that count are 1) any mouse down
@@ -629,9 +637,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// Tell this object to destroy itself.
void Destroy();
- // Checks whether the renderer is hung and calls NotifyRendererUnresponsive
- // if it is.
- void CheckRendererIsUnresponsive();
+ // Called by |hang_timeout_monitor_| on delayed response from the renderer.
+ void RendererIsUnresponsive();
// Called if we know the renderer is responsive. When we currently think the
// renderer is unresponsive, this will clear that state and call
@@ -644,8 +651,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
void OnClose();
void OnUpdateScreenRectsAck();
void OnRequestMove(const gfx::Rect& pos);
- void OnSetTooltipText(const string16& tooltip_text,
- WebKit::WebTextDirection text_direction_hint);
+ void OnSetTooltipText(const base::string16& tooltip_text,
+ blink::WebTextDirection text_direction_hint);
void OnPaintAtSizeAck(int tag, const gfx::Size& size);
#if defined(OS_MACOSX)
void OnCompositorSurfaceBuffersSwapped(
@@ -656,10 +663,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
gfx::Vector2dF current_fling_velocity);
void OnUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
void OnUpdateIsDelayed();
- void OnBeginSmoothScroll(
- const ViewHostMsg_BeginSmoothScroll_Params& params);
- void OnBeginPinch(
- const ViewHostMsg_BeginPinch_Params& params);
+ void OnQueueSyntheticGesture(const SyntheticGesturePacket& gesture_packet);
virtual void OnFocus();
virtual void OnBlur();
void OnSetCursor(const WebCursor& cursor);
@@ -718,49 +722,31 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// InputRouterClient
virtual InputEventAckState FilterInputEvent(
- const WebKit::WebInputEvent& event,
+ const blink::WebInputEvent& event,
const ui::LatencyInfo& latency_info) OVERRIDE;
virtual void IncrementInFlightEventCount() OVERRIDE;
virtual void DecrementInFlightEventCount() OVERRIDE;
virtual void OnHasTouchEventHandlers(bool has_handlers) OVERRIDE;
- virtual bool OnSendKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info,
- bool* is_shortcut) OVERRIDE;
- virtual bool OnSendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE;
- virtual bool OnSendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
- virtual bool OnSendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
- virtual bool OnSendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
- virtual bool OnSendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
- virtual bool OnSendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
- virtual bool OnSendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
- virtual void SetNeedsFlush() OVERRIDE;
+ virtual OverscrollController* GetOverscrollController() const OVERRIDE;
virtual void DidFlush() OVERRIDE;
// InputAckHandler
virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
InputEventAckState ack_result) OVERRIDE;
- virtual void OnWheelEventAck(const WebKit::WebMouseWheelEvent& event,
+ virtual void OnWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
InputEventAckState ack_result) OVERRIDE;
virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) OVERRIDE;
- virtual void OnGestureEventAck(const WebKit::WebGestureEvent& event,
+ virtual void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
InputEventAckState ack_result) OVERRIDE;
virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) OVERRIDE;
- void SimulateTouchGestureWithMouse(const WebKit::WebMouseEvent& mouse_event);
-
// Called when there is a new auto resize (using a post to avoid a stack
// which may get in recursive loops).
void DelayedAutoResized();
+ void WindowSnapshotReachedScreen(int snapshot_id);
+
// Our delegate, which wants to know mainly about keyboard events.
// It will remain non-NULL until DetachDelegate() is called.
RenderWidgetHostDelegate* delegate_;
@@ -799,7 +785,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// Cached copy of the screen info so that it doesn't need to be updated every
// time the window is resized.
- scoped_ptr<WebKit::WebScreenInfo> screen_info_;
+ scoped_ptr<blink::WebScreenInfo> screen_info_;
// Set if screen_info_ may have changed and should be recomputed and force a
// resize message.
@@ -882,7 +868,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
// Set when we update the text direction of the selected input element.
bool text_direction_updated_;
- WebKit::WebTextDirection text_direction_;
+ blink::WebTextDirection text_direction_;
// Set when we cancel updating the text direction.
// This flag also ignores succeeding update requests until we call
@@ -917,13 +903,15 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
- SyntheticGestureController synthetic_gesture_controller_;
+ scoped_ptr<SyntheticGestureController> synthetic_gesture_controller_;
// Receives and handles all input events.
scoped_ptr<InputRouter> input_router_;
scoped_ptr<OverscrollController> overscroll_controller_;
+ scoped_ptr<TimeoutMonitor> hang_monitor_timeout_;
+
#if defined(OS_WIN)
std::list<HWND> dummy_windows_for_activation_;
#endif
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 21c368ab488..967c8142715 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -10,14 +10,14 @@
#include "content/browser/browser_thread_impl.h"
#include "content/browser/renderer_host/backing_store.h"
#include "content/browser/renderer_host/input/gesture_event_filter.h"
-#include "content/browser/renderer_host/input/immediate_input_router.h"
+#include "content/browser/renderer_host/input/input_router_impl.h"
#include "content/browser/renderer_host/input/tap_suppression_controller.h"
#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
#include "content/browser/renderer_host/input/touch_event_queue.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/overscroll_controller_delegate.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/port/browser/render_widget_host_view_port.h"
@@ -28,6 +28,7 @@
#include "content/public/browser/notification_types.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
+#include "content/test/test_render_view_host.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
@@ -45,11 +46,12 @@
#endif
using base::TimeDelta;
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebTouchEvent;
-using WebKit::WebTouchPoint;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
namespace content {
@@ -57,8 +59,9 @@ namespace content {
class TestOverscrollDelegate : public OverscrollControllerDelegate {
public:
- TestOverscrollDelegate()
- : current_mode_(OVERSCROLL_NONE),
+ explicit TestOverscrollDelegate(RenderWidgetHostView* view)
+ : view_(view),
+ current_mode_(OVERSCROLL_NONE),
completed_mode_(OVERSCROLL_NONE),
delta_x_(0.f),
delta_y_(0.f) {
@@ -79,6 +82,10 @@ class TestOverscrollDelegate : public OverscrollControllerDelegate {
private:
// Overridden from OverscrollControllerDelegate:
+ virtual gfx::Rect GetVisibleBounds() const OVERRIDE {
+ return view_->IsShowing() ? view_->GetViewBounds() : gfx::Rect();
+ }
+
virtual void OnOverscrollUpdate(float delta_x, float delta_y) OVERRIDE {
delta_x_ = delta_x;
delta_y_ = delta_y;
@@ -97,6 +104,7 @@ class TestOverscrollDelegate : public OverscrollControllerDelegate {
delta_x_ = delta_y_ = 0.f;
}
+ RenderWidgetHostView* view_;
OverscrollMode current_mode_;
OverscrollMode completed_mode_;
float delta_x_;
@@ -131,46 +139,34 @@ class MockInputRouter : public InputRouter {
}
virtual void SendMouseEvent(
const MouseEventWithLatencyInfo& mouse_event) OVERRIDE {
- if (client_->OnSendMouseEvent(mouse_event))
- sent_mouse_event_ = true;
+ sent_mouse_event_ = true;
}
virtual void SendWheelEvent(
const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE {
- if (client_->OnSendWheelEvent(wheel_event))
- sent_wheel_event_ = true;
+ sent_wheel_event_ = true;
}
virtual void SendKeyboardEvent(
const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info) OVERRIDE {
- bool is_shortcut = false;
- if (client_->OnSendKeyboardEvent(key_event, latency_info, &is_shortcut))
- sent_keyboard_event_ = true;
+ const ui::LatencyInfo& latency_info,
+ bool is_shortcut) OVERRIDE {
+ sent_keyboard_event_ = true;
}
virtual void SendGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) OVERRIDE {
- if (client_->OnSendGestureEvent(gesture_event))
- sent_gesture_event_ = true;
+ sent_gesture_event_ = true;
}
virtual void SendTouchEvent(
const TouchEventWithLatencyInfo& touch_event) OVERRIDE {
- if (client_->OnSendTouchEvent(touch_event))
- send_touch_event_not_cancelled_ = true;
- }
- virtual void SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE {}
- virtual void SendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE {}
- virtual void SendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE {}
+ send_touch_event_not_cancelled_ =
+ client_->FilterInputEvent(touch_event.event, touch_event.latency) ==
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+ }
virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const OVERRIDE {
NOTREACHED();
return NULL;
}
virtual bool ShouldForwardTouchEvent() const OVERRIDE { return true; }
- virtual bool ShouldForwardGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) const OVERRIDE {
- return true;
- }
+ virtual void OnViewUpdated(int view_flags) OVERRIDE {}
// IPC::Listener
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
@@ -203,8 +199,7 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
int routing_id)
: RenderWidgetHostImpl(delegate, process, routing_id, false),
unresponsive_timer_fired_(false) {
- immediate_input_router_ =
- static_cast<ImmediateInputRouter*>(input_router_.get());
+ input_router_impl_ = static_cast<InputRouterImpl*>(input_router_.get());
}
// Allow poking at a few private members.
@@ -224,59 +219,56 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
hung_renderer_delay_ms_ = delay_ms;
}
- unsigned GestureEventLastQueueEventSize() {
+ unsigned GestureEventLastQueueEventSize() const {
return gesture_event_filter()->coalesced_gesture_events_.size();
}
- WebGestureEvent GestureEventSecondFromLastQueueEvent() {
+ WebGestureEvent GestureEventSecondFromLastQueueEvent() const {
return gesture_event_filter()->coalesced_gesture_events_.at(
GestureEventLastQueueEventSize() - 2).event;
}
- WebGestureEvent GestureEventLastQueueEvent() {
+ WebGestureEvent GestureEventLastQueueEvent() const {
return gesture_event_filter()->coalesced_gesture_events_.back().event;
}
- unsigned GestureEventDebouncingQueueSize() {
+ unsigned GestureEventDebouncingQueueSize() const {
return gesture_event_filter()->debouncing_deferral_queue_.size();
}
- WebGestureEvent GestureEventQueueEventAt(int i) {
+ WebGestureEvent GestureEventQueueEventAt(int i) const {
return gesture_event_filter()->coalesced_gesture_events_.at(i).event;
}
- bool shouldDeferTapDownEvents() {
- return gesture_event_filter()->maximum_tap_gap_time_ms_ != 0;
- }
-
- bool ScrollingInProgress() {
+ bool ScrollingInProgress() const {
return gesture_event_filter()->scrolling_in_progress_;
}
- bool FlingInProgress() {
+ bool FlingInProgress() const {
return gesture_event_filter()->fling_in_progress_;
}
- bool WillIgnoreNextACK() {
+ bool WillIgnoreNextACK() const {
return gesture_event_filter()->ignore_next_ack_;
}
void SetupForOverscrollControllerTest() {
SetOverscrollControllerEnabled(true);
- overscroll_delegate_.reset(new TestOverscrollDelegate);
+ overscroll_delegate_.reset(new TestOverscrollDelegate(GetView()));
overscroll_controller_->set_delegate(overscroll_delegate_.get());
}
- void set_maximum_tap_gap_time_ms(int delay_ms) {
- gesture_event_filter()->maximum_tap_gap_time_ms_ = delay_ms;
+ void DisableGestureDebounce() {
+ gesture_event_filter()->set_debounce_enabled_for_testing(false);
}
void set_debounce_interval_time_ms(int delay_ms) {
- gesture_event_filter()->debounce_interval_time_ms_ = delay_ms;
+ gesture_event_filter()->
+ set_debounce_interval_time_ms_for_testing(delay_ms);
}
- size_t TouchEventQueueSize() {
- return touch_event_queue()->GetQueueSize();
+ bool TouchEventQueueEmpty() const {
+ return touch_event_queue()->empty();
}
bool ScrollStateIsContentScrolling() const {
@@ -295,10 +287,6 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
return overscroll_controller_->scroll_state_;
}
- const WebTouchEvent& latest_event() const {
- return touch_event_queue()->GetLatestEvent().event;
- }
-
OverscrollMode overscroll_mode() const {
return overscroll_controller_->overscroll_mode_;
}
@@ -329,21 +317,25 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
unresponsive_timer_fired_ = true;
}
- TouchEventQueue* touch_event_queue() const {
- return immediate_input_router_->touch_event_queue();
+ const TouchEventQueue* touch_event_queue() const {
+ return input_router_impl_->touch_event_queue_.get();
+ }
+
+ const GestureEventFilter* gesture_event_filter() const {
+ return input_router_impl_->gesture_event_filter_.get();
}
- GestureEventFilter* gesture_event_filter() const {
- return immediate_input_router_->gesture_event_filter();
+ GestureEventFilter* gesture_event_filter() {
+ return input_router_impl_->gesture_event_filter_.get();
}
private:
bool unresponsive_timer_fired_;
- // |immediate_input_router_| and |mock_input_router_| are owned by
- // RenderWidgetHostImpl |input_router_|. Below are provided for convenience so
+ // |input_router_impl_| and |mock_input_router_| are owned by
+ // RenderWidgetHostImpl. The handles below are provided for convenience so
// that we don't have to reinterpret_cast it all the time.
- ImmediateInputRouter* immediate_input_router_;
+ InputRouterImpl* input_router_impl_;
MockInputRouter* mock_input_router_;
scoped_ptr<TestOverscrollDelegate> overscroll_delegate_;
@@ -453,7 +445,7 @@ class TestView : public TestRenderWidgetHostView {
const WebTouchEvent& acked_event() const { return acked_event_; }
int acked_event_count() const { return acked_event_count_; }
void ClearAckedEvent() {
- acked_event_.type = WebKit::WebInputEvent::Undefined;
+ acked_event_.type = blink::WebInputEvent::Undefined;
acked_event_count_ = 0;
}
@@ -615,7 +607,7 @@ class RenderWidgetHostTest : public testing::Test {
bool KeyPressEventCallback(const NativeWebKeyboardEvent& /* event */) {
return handle_key_press_event_;
}
- bool MouseEventCallback(const WebKit::WebMouseEvent& /* event */) {
+ bool MouseEventCallback(const blink::WebMouseEvent& /* event */) {
return handle_mouse_event_;
}
@@ -626,6 +618,7 @@ class RenderWidgetHostTest : public testing::Test {
delegate_.reset(new MockRenderWidgetHostDelegate());
process_ = new RenderWidgetHostProcess(browser_context_.get());
#if defined(USE_AURA)
+ aura::Env::CreateInstance();
screen_.reset(aura::TestScreen::Create());
gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
#endif
@@ -660,80 +653,59 @@ class RenderWidgetHostTest : public testing::Test {
}
void SimulateKeyboardEvent(WebInputEvent::Type type) {
- NativeWebKeyboardEvent key_event;
- key_event.type = type;
- key_event.windowsKeyCode = ui::VKEY_L; // non-null made up value.
- host_->ForwardKeyboardEvent(key_event);
+ WebKeyboardEvent event = SyntheticWebKeyboardEventBuilder::Build(type);
+ NativeWebKeyboardEvent native_event;
+ memcpy(&native_event, &event, sizeof(event));
+ host_->ForwardKeyboardEvent(native_event);
}
void SimulateMouseEvent(WebInputEvent::Type type) {
- WebKit::WebMouseEvent mouse_event;
- mouse_event.type = type;
- host_->ForwardMouseEvent(mouse_event);
+ host_->ForwardMouseEvent(SyntheticWebMouseEventBuilder::Build(type));
}
void SimulateWheelEvent(float dX, float dY, int modifiers, bool precise) {
- WebMouseWheelEvent wheel_event;
- wheel_event.type = WebInputEvent::MouseWheel;
- wheel_event.deltaX = dX;
- wheel_event.deltaY = dY;
- wheel_event.modifiers = modifiers;
- wheel_event.hasPreciseScrollingDeltas = precise;
- host_->ForwardWheelEvent(wheel_event);
+ host_->ForwardWheelEvent(
+ SyntheticWebMouseWheelEventBuilder::Build(dX, dY, modifiers, precise));
}
void SimulateMouseMove(int x, int y, int modifiers) {
- WebKit::WebMouseEvent mouse_event;
- mouse_event.type = WebInputEvent::MouseMove;
- mouse_event.x = mouse_event.windowX = x;
- mouse_event.y = mouse_event.windowY = y;
- mouse_event.modifiers = modifiers;
- host_->ForwardMouseEvent(mouse_event);
+ host_->ForwardMouseEvent(
+ SyntheticWebMouseEventBuilder::Build(WebInputEvent::MouseMove,
+ x,
+ y,
+ modifiers));
}
void SimulateWheelEventWithPhase(WebMouseWheelEvent::Phase phase) {
- WebMouseWheelEvent wheel_event;
- wheel_event.type = WebInputEvent::MouseWheel;
- wheel_event.phase = phase;
- host_->ForwardWheelEvent(wheel_event);
+ host_->ForwardWheelEvent(SyntheticWebMouseWheelEventBuilder::Build(phase));
}
// Inject provided synthetic WebGestureEvent instance.
- void SimulateGestureEventCore(WebInputEvent::Type type,
- WebGestureEvent::SourceDevice sourceDevice,
- WebGestureEvent* gesture_event) {
- gesture_event->type = type;
- gesture_event->sourceDevice = sourceDevice;
- host_->ForwardGestureEvent(*gesture_event);
+ void SimulateGestureEventCore(const WebGestureEvent& gesture_event) {
+ host_->ForwardGestureEvent(gesture_event);
}
// Inject simple synthetic WebGestureEvent instances.
void SimulateGestureEvent(WebInputEvent::Type type,
WebGestureEvent::SourceDevice sourceDevice) {
- WebGestureEvent gesture_event;
- SimulateGestureEventCore(type, sourceDevice, &gesture_event);
+ SimulateGestureEventCore(
+ SyntheticWebGestureEventBuilder::Build(type, sourceDevice));
}
void SimulateGestureScrollUpdateEvent(float dX, float dY, int modifiers) {
- WebGestureEvent gesture_event;
- gesture_event.data.scrollUpdate.deltaX = dX;
- gesture_event.data.scrollUpdate.deltaY = dY;
- gesture_event.modifiers = modifiers;
- SimulateGestureEventCore(WebInputEvent::GestureScrollUpdate,
- WebGestureEvent::Touchscreen, &gesture_event);
+ SimulateGestureEventCore(
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(dX, dY, modifiers));
}
void SimulateGesturePinchUpdateEvent(float scale,
float anchorX,
float anchorY,
int modifiers) {
- WebGestureEvent gesture_event;
- gesture_event.data.pinchUpdate.scale = scale;
- gesture_event.x = anchorX;
- gesture_event.y = anchorY;
- gesture_event.modifiers = modifiers;
- SimulateGestureEventCore(WebInputEvent::GesturePinchUpdate,
- WebGestureEvent::Touchscreen, &gesture_event);
+ SimulateGestureEventCore(
+ SyntheticWebGestureEventBuilder::BuildPinchUpdate(scale,
+ anchorX,
+ anchorY,
+ modifiers));
}
// Inject synthetic GestureFlingStart events.
@@ -741,16 +713,15 @@ class RenderWidgetHostTest : public testing::Test {
float velocityX,
float velocityY,
WebGestureEvent::SourceDevice sourceDevice) {
- WebGestureEvent gesture_event;
- gesture_event.data.flingStart.velocityX = velocityX;
- gesture_event.data.flingStart.velocityY = velocityY;
- SimulateGestureEventCore(WebInputEvent::GestureFlingStart, sourceDevice,
- &gesture_event);
+ SimulateGestureEventCore(
+ SyntheticWebGestureEventBuilder::BuildFling(velocityX,
+ velocityY,
+ sourceDevice));
}
// Set the timestamp for the touch-event.
void SetTouchTimestamp(base::TimeDelta timestamp) {
- touch_event_.timeStampSeconds = timestamp.InSecondsF();
+ touch_event_.SetTimestamp(timestamp);
}
// Sends a touch event (irrespective of whether the page has a touch-event
@@ -758,50 +729,19 @@ class RenderWidgetHostTest : public testing::Test {
void SendTouchEvent() {
host_->ForwardTouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo());
- // Mark all the points as stationary. And remove the points that have been
- // released.
- int point = 0;
- for (unsigned int i = 0; i < touch_event_.touchesLength; ++i) {
- if (touch_event_.touches[i].state == WebKit::WebTouchPoint::StateReleased)
- continue;
-
- touch_event_.touches[point] = touch_event_.touches[i];
- touch_event_.touches[point].state =
- WebKit::WebTouchPoint::StateStationary;
- ++point;
- }
- touch_event_.touchesLength = point;
- touch_event_.type = WebInputEvent::Undefined;
+ touch_event_.ResetPoints();
}
int PressTouchPoint(int x, int y) {
- if (touch_event_.touchesLength == touch_event_.touchesLengthCap)
- return -1;
- WebKit::WebTouchPoint& point =
- touch_event_.touches[touch_event_.touchesLength];
- point.id = touch_event_.touchesLength;
- point.position.x = point.screenPosition.x = x;
- point.position.y = point.screenPosition.y = y;
- point.state = WebKit::WebTouchPoint::StatePressed;
- point.radiusX = point.radiusY = 1.f;
- ++touch_event_.touchesLength;
- touch_event_.type = WebInputEvent::TouchStart;
- return point.id;
+ return touch_event_.PressPoint(x, y);
}
void MoveTouchPoint(int index, int x, int y) {
- CHECK(index >= 0 && index < touch_event_.touchesLengthCap);
- WebKit::WebTouchPoint& point = touch_event_.touches[index];
- point.position.x = point.screenPosition.x = x;
- point.position.y = point.screenPosition.y = y;
- touch_event_.touches[index].state = WebKit::WebTouchPoint::StateMoved;
- touch_event_.type = WebInputEvent::TouchMove;
+ touch_event_.MovePoint(index, x, y);
}
void ReleaseTouchPoint(int index) {
- CHECK(index >= 0 && index < touch_event_.touchesLengthCap);
- touch_event_.touches[index].state = WebKit::WebTouchPoint::StateReleased;
- touch_event_.type = WebInputEvent::TouchEnd;
+ touch_event_.ReleasePoint(index);
}
const WebInputEvent* GetInputEventFromMessage(const IPC::Message& message) {
@@ -825,7 +765,7 @@ class RenderWidgetHostTest : public testing::Test {
bool handle_mouse_event_;
private:
- WebTouchEvent touch_event_;
+ SyntheticWebTouchEvent touch_event_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest);
};
@@ -990,7 +930,7 @@ TEST_F(RenderWidgetHostTest, Background) {
host_->SetView(view.get());
// Create a checkerboard background to test with.
- gfx::Canvas canvas(gfx::Size(4, 4), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(4, 4), 1.0f, true);
canvas.FillRect(gfx::Rect(0, 0, 2, 2), SK_ColorBLACK);
canvas.FillRect(gfx::Rect(2, 0, 2, 2), SK_ColorWHITE);
canvas.FillRect(gfx::Rect(0, 2, 2, 2), SK_ColorWHITE);
@@ -1230,7 +1170,7 @@ TEST_F(RenderWidgetHostTest, UnhandledWheelEvent) {
}
TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) {
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ SimulateGestureEvent(WebInputEvent::GestureScrollUpdate,
WebGestureEvent::Touchscreen);
// Make sure we sent the input event to the renderer.
@@ -1239,9 +1179,9 @@ TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) {
process_->sink().ClearMessages();
// Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(WebInputEvent::GestureScrollBegin, view_->gesture_event_type());
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, view_->gesture_event_type());
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, view_->ack_result());
}
@@ -1419,7 +1359,7 @@ TEST_F(RenderWidgetHostTest, WheelScrollConsumedDoNotHorizOverscroll) {
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
- EXPECT_EQ(0U, process_->sink().message_count());
+ EXPECT_EQ(1U, process_->sink().message_count());
process_->sink().ClearMessages();
SendInputEventACK(WebInputEvent::MouseWheel,
@@ -1616,7 +1556,7 @@ TEST_F(RenderWidgetHostTest, ScrollEventsOverscrollWithZeroFling) {
// overscroll nav instead of completing it.
TEST_F(RenderWidgetHostTest, ReverseFlingCancelsOverscroll) {
host_->SetupForOverscrollControllerTest();
- host_->set_debounce_interval_time_ms(0);
+ host_->DisableGestureDebounce();
process_->sink().ClearMessages();
view_->set_bounds(gfx::Rect(0, 0, 400, 200));
view_->Show();
@@ -1675,7 +1615,7 @@ TEST_F(RenderWidgetHostTest, ReverseFlingCancelsOverscroll) {
TEST_F(RenderWidgetHostTest, GestureScrollOverscrolls) {
// Turn off debounce handling for test isolation.
host_->SetupForOverscrollControllerTest();
- host_->set_debounce_interval_time_ms(0);
+ host_->DisableGestureDebounce();
process_->sink().ClearMessages();
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
@@ -1720,7 +1660,9 @@ TEST_F(RenderWidgetHostTest, GestureScrollOverscrolls) {
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
+ // The scroll end event will have received a synthetic ack from the input
+ // router.
+ EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
}
// Tests that if the page is scrolled because of a scroll-gesture, then that
@@ -1729,7 +1671,7 @@ TEST_F(RenderWidgetHostTest, GestureScrollOverscrolls) {
TEST_F(RenderWidgetHostTest, GestureScrollConsumedHorizontal) {
// Turn off debounce handling for test isolation.
host_->SetupForOverscrollControllerTest();
- host_->set_debounce_interval_time_ms(0);
+ host_->DisableGestureDebounce();
process_->sink().ClearMessages();
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
@@ -1756,41 +1698,6 @@ TEST_F(RenderWidgetHostTest, GestureScrollConsumedHorizontal) {
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
}
-// Tests that if the page is scrolled because of a scroll-gesture, then that
-// particular scroll sequence never generates overscroll if the scroll direction
-// is vertical.
-TEST_F(RenderWidgetHostTest, GestureScrollConsumedVertical) {
- // Turn off debounce handling for test isolation.
- host_->SetupForOverscrollControllerTest();
- host_->set_debounce_interval_time_ms(0);
- process_->sink().ClearMessages();
-
- SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
- WebGestureEvent::Touchscreen);
- SimulateGestureScrollUpdateEvent(0, -1, 0);
-
- // Start scrolling on content. ACK both events as being processed.
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- SendInputEventACK(WebInputEvent::GestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
- EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
-
- // Send another gesture event and ACK as not being processed. This should
- // initiate overscroll because the scroll was in the vertical direction even
- // though the beginning of the scroll did scroll content.
- SimulateGestureScrollUpdateEvent(0, -50, 0);
- SendInputEventACK(WebInputEvent::GestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(OVERSCROLL_NORTH, host_->overscroll_mode());
-
- // Changing direction of scroll to be horizontal to test that this causes the
- // vertical overscroll to stop.
- SimulateGestureScrollUpdateEvent(500, 0, 0);
- EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
-}
-
// Tests that the overscroll controller plays nice with touch-scrolls and the
// gesture event filter with debounce filtering turned on.
TEST_F(RenderWidgetHostTest, GestureScrollDebounceOverscrolls) {
@@ -1926,7 +1833,9 @@ TEST_F(RenderWidgetHostTest, GestureScrollDebounceTimerOverscroll) {
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
- EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
+ // The scroll end event will have received a synthetic ack from the input
+ // router.
+ EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
EXPECT_EQ(0U, host_->GestureEventDebouncingQueueSize());
EXPECT_EQ(1U, process_->sink().message_count());
}
@@ -1988,7 +1897,7 @@ TEST_F(RenderWidgetHostTest, OverscrollWithTouchEvents) {
EXPECT_EQ(65.f, host_->overscroll_delta_x());
EXPECT_EQ(15.f, host_->overscroll_delegate()->delta_x());
EXPECT_EQ(0.f, host_->overscroll_delegate()->delta_y());
- EXPECT_EQ(0U, host_->TouchEventQueueSize());
+ EXPECT_TRUE(host_->TouchEventQueueEmpty());
process_->sink().ClearMessages();
// Send another touch event. The page should get the touch-move event, even
@@ -1996,7 +1905,7 @@ TEST_F(RenderWidgetHostTest, OverscrollWithTouchEvents) {
MoveTouchPoint(0, 55, 5);
SendTouchEvent();
EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, host_->TouchEventQueueSize());
+ EXPECT_FALSE(host_->TouchEventQueueEmpty());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->current_mode());
EXPECT_EQ(65.f, host_->overscroll_delta_x());
@@ -2005,12 +1914,12 @@ TEST_F(RenderWidgetHostTest, OverscrollWithTouchEvents) {
SendInputEventACK(WebInputEvent::TouchMove,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, host_->TouchEventQueueSize());
+ EXPECT_TRUE(host_->TouchEventQueueEmpty());
process_->sink().ClearMessages();
SimulateGestureScrollUpdateEvent(-10, 0, 0);
EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, host_->TouchEventQueueSize());
+ EXPECT_TRUE(host_->TouchEventQueueEmpty());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->current_mode());
EXPECT_EQ(55.f, host_->overscroll_delta_x());
@@ -2020,14 +1929,14 @@ TEST_F(RenderWidgetHostTest, OverscrollWithTouchEvents) {
MoveTouchPoint(0, 255, 5);
SendTouchEvent();
EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, host_->TouchEventQueueSize());
+ EXPECT_FALSE(host_->TouchEventQueueEmpty());
process_->sink().ClearMessages();
SendInputEventACK(WebInputEvent::TouchMove,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
SimulateGestureScrollUpdateEvent(200, 0, 0);
EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, host_->TouchEventQueueSize());
+ EXPECT_TRUE(host_->TouchEventQueueEmpty());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->current_mode());
EXPECT_EQ(255.f, host_->overscroll_delta_x());
@@ -2039,15 +1948,15 @@ TEST_F(RenderWidgetHostTest, OverscrollWithTouchEvents) {
ReleaseTouchPoint(0);
SendTouchEvent();
EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, host_->TouchEventQueueSize());
+ EXPECT_FALSE(host_->TouchEventQueueEmpty());
process_->sink().ClearMessages();
SendInputEventACK(WebInputEvent::TouchEnd,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, host_->TouchEventQueueSize());
+ EXPECT_TRUE(host_->TouchEventQueueEmpty());
- SimulateGestureEvent(WebKit::WebInputEvent::GestureScrollEnd,
+ SimulateGestureEvent(blink::WebInputEvent::GestureScrollEnd,
WebGestureEvent::Touchscreen);
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
@@ -2055,7 +1964,7 @@ TEST_F(RenderWidgetHostTest, OverscrollWithTouchEvents) {
TimeDelta::FromMilliseconds(10));
base::MessageLoop::current()->Run();
EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(0U, host_->TouchEventQueueSize());
+ EXPECT_TRUE(host_->TouchEventQueueEmpty());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->completed_mode());
@@ -2075,7 +1984,9 @@ TEST_F(RenderWidgetHostTest, TouchGestureEndDispatchedAfterOverscrollComplete) {
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
WebGestureEvent::Touchscreen);
EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
+ // The scroll begin event will have received a synthetic ack from the input
+ // router.
+ EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
process_->sink().ClearMessages();
SendInputEventACK(WebInputEvent::GestureScrollBegin,
INPUT_EVENT_ACK_STATE_CONSUMED);
@@ -2105,7 +2016,7 @@ TEST_F(RenderWidgetHostTest, TouchGestureEndDispatchedAfterOverscrollComplete) {
EXPECT_EQ(-5.f, host_->overscroll_delegate()->delta_y());
// Send end event.
- SimulateGestureEvent(WebKit::WebInputEvent::GestureScrollEnd,
+ SimulateGestureEvent(blink::WebInputEvent::GestureScrollEnd,
WebGestureEvent::Touchscreen);
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
@@ -2120,10 +2031,12 @@ TEST_F(RenderWidgetHostTest, TouchGestureEndDispatchedAfterOverscrollComplete) {
base::MessageLoop::current()->Run();
EXPECT_EQ(1U, process_->sink().message_count());
process_->sink().ClearMessages();
- EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
+ // The scroll end event will have received a synthetic ack from the input
+ // router.
+ EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
EXPECT_EQ(0U, host_->GestureEventDebouncingQueueSize());
- SendInputEventACK(WebKit::WebInputEvent::GestureScrollEnd,
+ SendInputEventACK(blink::WebInputEvent::GestureScrollEnd,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
@@ -2133,7 +2046,9 @@ TEST_F(RenderWidgetHostTest, TouchGestureEndDispatchedAfterOverscrollComplete) {
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
WebGestureEvent::Touchscreen);
EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
+ // The scroll begin event will have received a synthetic ack from the input
+ // router.
+ EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
process_->sink().ClearMessages();
SendInputEventACK(WebInputEvent::GestureScrollBegin,
INPUT_EVENT_ACK_STATE_CONSUMED);
@@ -2163,7 +2078,7 @@ TEST_F(RenderWidgetHostTest, TouchGestureEndDispatchedAfterOverscrollComplete) {
EXPECT_EQ(-5.f, host_->overscroll_delegate()->delta_y());
// Send end event.
- SimulateGestureEvent(WebKit::WebInputEvent::GestureScrollEnd,
+ SimulateGestureEvent(blink::WebInputEvent::GestureScrollEnd,
WebGestureEvent::Touchscreen);
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
@@ -2179,10 +2094,12 @@ TEST_F(RenderWidgetHostTest, TouchGestureEndDispatchedAfterOverscrollComplete) {
base::MessageLoop::current()->Run();
EXPECT_EQ(1U, process_->sink().message_count());
process_->sink().ClearMessages();
- EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
+ // The scroll end event will have received a synthetic ack from the input
+ // router.
+ EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
EXPECT_EQ(0U, host_->GestureEventDebouncingQueueSize());
- SendInputEventACK(WebKit::WebInputEvent::GestureScrollEnd,
+ SendInputEventACK(blink::WebInputEvent::GestureScrollEnd,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
@@ -2233,7 +2150,7 @@ TEST_F(RenderWidgetHostTest, OverscrollDirectionChange) {
// move events do reach the renderer.
TEST_F(RenderWidgetHostTest, OverscrollMouseMoveCompletion) {
host_->SetupForOverscrollControllerTest();
- host_->set_debounce_interval_time_ms(0);
+ host_->DisableGestureDebounce();
process_->sink().ClearMessages();
view_->set_bounds(gfx::Rect(0, 0, 400, 200));
view_->Show();
@@ -2328,7 +2245,7 @@ TEST_F(RenderWidgetHostTest, OverscrollMouseMoveCompletion) {
// reset after the end of the scroll.
TEST_F(RenderWidgetHostTest, OverscrollStateResetsAfterScroll) {
host_->SetupForOverscrollControllerTest();
- host_->set_debounce_interval_time_ms(0);
+ host_->DisableGestureDebounce();
process_->sink().ClearMessages();
view_->set_bounds(gfx::Rect(0, 0, 400, 200));
view_->Show();
@@ -2463,13 +2380,13 @@ TEST_InputRouterRoutes_NOARGS(LostCapture);
TEST_F(RenderWidgetHostTest, InputRouterRoutesReplace) {
host_->SetupForInputRouterTest();
- host_->Replace(EmptyString16());
+ host_->Replace(base::string16());
EXPECT_TRUE(host_->mock_input_router()->send_event_called_);
}
TEST_F(RenderWidgetHostTest, InputRouterRoutesReplaceMisspelling) {
host_->SetupForInputRouterTest();
- host_->ReplaceMisspelling(EmptyString16());
+ host_->ReplaceMisspelling(base::string16());
EXPECT_TRUE(host_->mock_input_router()->send_event_called_);
}
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 3b94566748f..e3e7fb802de 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
@@ -14,6 +14,8 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/worker_pool.h"
+#include "cc/base/latency_info_swap_promise.h"
+#include "cc/layers/delegated_frame_provider.h"
#include "cc/layers/delegated_renderer_layer.h"
#include "cc/layers/layer.h"
#include "cc/layers/texture_layer.h"
@@ -27,21 +29,29 @@
#include "content/browser/android/content_view_core_impl.h"
#include "content/browser/android/in_process/synchronous_compositor_impl.h"
#include "content/browser/android/overscroll_glow.h"
+#include "content/browser/devtools/render_view_devtools_agent_host.h"
+#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/compositor_impl_android.h"
#include "content/browser/renderer_host/dip_util.h"
-#include "content/browser/renderer_host/generic_touch_gesture_android.h"
#include "content/browser/renderer_host/image_transport_factory_android.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/browser/renderer_host/surface_texture_transport_client_android.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/devtools_agent_host.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/common/content_switches.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "skia/ext/image_operations.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/base/android/window_android.h"
#include "ui/gfx/android/device_display_info.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/display.h"
@@ -53,18 +63,6 @@ namespace content {
namespace {
const int kUndefinedOutputSurfaceId = -1;
-const int kMinimumPointerDistance = 50;
-
-void InsertSyncPointAndAckForGpu(
- int gpu_host_id, int route_id, const std::string& return_mailbox) {
- uint32 sync_point =
- ImageTransportFactoryAndroid::GetInstance()->InsertSyncPoint();
- AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
- ack_params.mailbox_name = return_mailbox;
- ack_params.sync_point = sync_point;
- RenderWidgetHostImpl::AcknowledgeBufferPresent(
- route_id, gpu_host_id, ack_params);
-}
void InsertSyncPointAndAckForCompositor(
int renderer_host_id,
@@ -100,6 +98,11 @@ void CopyFromCompositingSurfaceFinished(
callback.Run(result, *bitmap);
}
+bool UsingDelegatedRenderer() {
+ return CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableDelegatedRenderer);
+}
+
} // anonymous namespace
RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
@@ -112,34 +115,20 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
ime_adapter_android_(this),
cached_background_color_(SK_ColorWHITE),
texture_id_in_layer_(0),
- current_mailbox_output_surface_id_(kUndefinedOutputSurfaceId),
+ last_output_surface_id_(kUndefinedOutputSurfaceId),
weak_ptr_factory_(this),
- overscroll_effect_enabled_(true) {
- if (CompositorImpl::UsesDirectGL()) {
- surface_texture_transport_.reset(new SurfaceTextureTransportClient());
- layer_ = surface_texture_transport_->Initialize();
- layer_->SetIsDrawable(true);
- } else {
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableDelegatedRenderer)) {
- delegated_renderer_layer_ = cc::DelegatedRendererLayer::Create(this);
- layer_ = delegated_renderer_layer_;
- } else {
- texture_layer_ = cc::TextureLayer::Create(this);
- layer_ = texture_layer_;
- }
- }
-
- layer_->SetContentsOpaque(true);
-
- overscroll_effect_enabled_ = !CommandLine::ForCurrentProcess()->
- HasSwitch(switches::kDisableOverscrollEdgeEffect);
- // Don't block the main thread with effect resource loading.
- // Actual effect creation is deferred until an overscroll event is received.
- if (overscroll_effect_enabled_) {
- base::WorkerPool::PostTask(FROM_HERE,
- base::Bind(&OverscrollGlow::EnsureResources),
- true);
+ overscroll_effect_enabled_(
+ !CommandLine::ForCurrentProcess()->
+ HasSwitch(switches::kDisableOverscrollEdgeEffect)),
+ overscroll_effect_(OverscrollGlow::Create(overscroll_effect_enabled_)),
+ flush_input_requested_(false),
+ accelerated_surface_route_id_(0),
+ using_synchronous_compositor_(SynchronousCompositorImpl::FromID(
+ widget_host->GetProcess()->GetID(),
+ widget_host->GetRoutingID()) != NULL) {
+ if (!UsingDelegatedRenderer()) {
+ texture_layer_ = cc::TextureLayer::Create(NULL);
+ layer_ = texture_layer_;
}
host_->SetView(this);
@@ -158,6 +147,9 @@ RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
if (texture_layer_.get())
texture_layer_->ClearClient();
+
+ if (resource_collection_.get())
+ resource_collection_->SetClient(NULL);
}
@@ -165,8 +157,6 @@ bool RenderWidgetHostViewAndroid::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ImeBatchStateChanged_ACK,
- OnProcessImeBatchStateAck)
IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
OnDidChangeBodyBackgroundColor)
@@ -174,6 +164,8 @@ bool RenderWidgetHostViewAndroid::OnMessageReceived(
OnSetNeedsBeginFrame)
IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
OnTextInputStateChanged)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
+ OnSmartClipDataExtracted)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -203,6 +195,9 @@ void RenderWidgetHostViewAndroid::WasShown() {
return;
host_->WasShown();
+
+ if (content_view_core_ && !using_synchronous_compositor_)
+ content_view_core_->GetWindowAndroid()->AddObserver(this);
}
void RenderWidgetHostViewAndroid::WasHidden() {
@@ -214,19 +209,19 @@ void RenderWidgetHostViewAndroid::WasHidden() {
// Inform the renderer that we are being hidden so it can reduce its resource
// utilization.
host_->WasHidden();
+
+ if (content_view_core_ && !using_synchronous_compositor_)
+ content_view_core_->GetWindowAndroid()->RemoveObserver(this);
}
void RenderWidgetHostViewAndroid::WasResized() {
- if (surface_texture_transport_.get() && content_view_core_)
- surface_texture_transport_->SetSize(
- content_view_core_->GetPhysicalBackingSize());
-
host_->WasResized();
}
void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
// Ignore the given size as only the Java code has the power to
// resize the view on Android.
+ default_size_ = size;
WasResized();
}
@@ -234,7 +229,7 @@ void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
SetSize(rect.size());
}
-WebKit::WebGLId RenderWidgetHostViewAndroid::GetScaledContentTexture(
+blink::WebGLId RenderWidgetHostViewAndroid::GetScaledContentTexture(
float scale,
gfx::Size* out_size) {
gfx::Size size(gfx::ToCeiledSize(
@@ -274,7 +269,7 @@ bool RenderWidgetHostViewAndroid::PopulateBitmapWithContents(jobject jbitmap) {
GLHelper* helper = ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
- WebKit::WebGLId texture = helper->CopyAndScaleTexture(
+ blink::WebGLId texture = helper->CopyAndScaleTexture(
texture_id_in_layer_,
texture_size_in_layer_,
bitmap.size(),
@@ -287,7 +282,7 @@ bool RenderWidgetHostViewAndroid::PopulateBitmapWithContents(jobject jbitmap) {
gfx::Rect(bitmap.size()),
static_cast<unsigned char*> (bitmap.pixels()));
- WebKit::WebGraphicsContext3D* context =
+ blink::WebGraphicsContext3D* context =
ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
context->deleteTexture(texture);
@@ -295,9 +290,20 @@ bool RenderWidgetHostViewAndroid::PopulateBitmapWithContents(jobject jbitmap) {
}
bool RenderWidgetHostViewAndroid::HasValidFrame() const {
- return texture_id_in_layer_ != 0 &&
- content_view_core_ &&
- !texture_size_in_layer_.IsEmpty();
+ if (!content_view_core_)
+ return false;
+ if (texture_size_in_layer_.IsEmpty())
+ return false;
+
+ if (UsingDelegatedRenderer()) {
+ if (!delegated_renderer_layer_.get())
+ return false;
+ } else {
+ if (texture_id_in_layer_ == 0)
+ return false;
+ }
+
+ return true;
}
gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
@@ -327,16 +333,15 @@ void RenderWidgetHostViewAndroid::Focus() {
host_->Focus();
host_->SetInputMethodActive(true);
ResetClipping();
- if (overscroll_effect_)
- overscroll_effect_->SetEnabled(true);
+ if (overscroll_effect_enabled_)
+ overscroll_effect_->Enable();
}
void RenderWidgetHostViewAndroid::Blur() {
host_->ExecuteEditCommand("Unselect", "");
host_->SetInputMethodActive(false);
host_->Blur();
- if (overscroll_effect_)
- overscroll_effect_->SetEnabled(false);
+ overscroll_effect_->Disable();
}
bool RenderWidgetHostViewAndroid::HasFocus() const {
@@ -379,7 +384,7 @@ bool RenderWidgetHostViewAndroid::IsShowing() {
gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
if (!content_view_core_)
- return gfx::Rect();
+ return gfx::Rect(default_size_);
gfx::Size size = content_view_core_->GetViewportSizeDip();
gfx::Size offset = content_view_core_->GetViewportSizeOffsetDip();
@@ -439,12 +444,7 @@ void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
static_cast<int>(params.type),
params.value, params.selection_start, params.selection_end,
params.composition_start, params.composition_end,
- params.show_ime_if_needed);
-}
-
-void RenderWidgetHostViewAndroid::OnProcessImeBatchStateAck(bool is_begin) {
- if (content_view_core_)
- content_view_core_->ProcessImeBatchStateAck(is_begin);
+ params.show_ime_if_needed, params.require_ack);
}
void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
@@ -460,8 +460,16 @@ void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
void RenderWidgetHostViewAndroid::SendBeginFrame(
const cc::BeginFrameArgs& args) {
TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame");
- if (host_)
- host_->Send(new ViewMsg_BeginFrame(host_->GetRoutingID(), args));
+ if (!host_)
+ return;
+
+ if (flush_input_requested_) {
+ flush_input_requested_ = false;
+ host_->FlushInput();
+ content_view_core_->RemoveBeginFrameSubscriber();
+ }
+
+ host_->Send(new ViewMsg_BeginFrame(host_->GetRoutingID(), args));
}
void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(
@@ -469,10 +477,14 @@ void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(
TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
"enabled", enabled);
// ContentViewCoreImpl handles multiple subscribers to the BeginFrame, so
- // we have to make sure calls to ContentViewCoreImpl's SetNeedsBeginFrame
- // are balanced, even if RenderWidgetHostViewAndroid's may not be.
+ // we have to make sure calls to ContentViewCoreImpl's
+ // {Add,Remove}BeginFrameSubscriber are balanced, even if
+ // RenderWidgetHostViewAndroid's may not be.
if (content_view_core_ && needs_begin_frame_ != enabled) {
- content_view_core_->SetNeedsBeginFrame(enabled);
+ if (enabled)
+ content_view_core_->AddBeginFrameSubscriber();
+ else
+ content_view_core_->RemoveBeginFrameSubscriber();
needs_begin_frame_ = enabled;
}
}
@@ -483,6 +495,16 @@ void RenderWidgetHostViewAndroid::OnStartContentIntent(
content_view_core_->StartContentIntent(content_url);
}
+void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
+ const string16& result) {
+ // Custom serialization over IPC isn't allowed normally for security reasons.
+ // Since this feature is only used in (single-process) WebView, there are no
+ // security issues. Enforce that it's only called in single process mode.
+ CHECK(RenderProcessHost::run_renderer_in_process());
+ if (content_view_core_)
+ content_view_core_->OnSmartClipDataExtracted(result);
+}
+
void RenderWidgetHostViewAndroid::ImeCancelComposition() {
ime_adapter_android_.CancelComposition();
}
@@ -502,7 +524,7 @@ void RenderWidgetHostViewAndroid::RenderProcessGone(
void RenderWidgetHostViewAndroid::Destroy() {
RemoveLayers();
- content_view_core_ = NULL;
+ SetContentViewCore(NULL);
// The RenderWidgetHost's destruction led here, so don't call it.
host_ = NULL;
@@ -511,11 +533,11 @@ void RenderWidgetHostViewAndroid::Destroy() {
}
void RenderWidgetHostViewAndroid::SetTooltipText(
- const string16& tooltip_text) {
+ const base::string16& tooltip_text) {
// Tooltips don't makes sense on Android.
}
-void RenderWidgetHostViewAndroid::SelectionChanged(const string16& text,
+void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) {
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
@@ -561,7 +583,7 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback) {
- if (!IsSurfaceAvailableForCopy()) {
+ if (!using_synchronous_compositor_ && !IsSurfaceAvailableForCopy()) {
callback.Run(false, SkBitmap());
return;
}
@@ -571,12 +593,17 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
float device_scale_factor = display.device_scale_factor();
DCHECK_EQ(device_scale_factor,
- ui::GetScaleFactorScale(GetScaleFactorForView(this)));
+ ui::GetImageScale(GetScaleFactorForView(this)));
const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size);
gfx::Rect src_subrect_in_pixel =
ConvertRectToPixel(device_scale_factor, src_subrect);
+ if (using_synchronous_compositor_) {
+ SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback);
+ return;
+ }
+
scoped_ptr<cc::CopyOutputRequest> request;
if (src_subrect_in_pixel.size() == dst_size_in_pixel) {
request = cc::CopyOutputRequest::CreateBitmapRequest(base::Bind(
@@ -613,28 +640,10 @@ void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
content_view_core_->ShowDisambiguationPopup(target_rect, zoomed_bitmap);
}
-SyntheticGesture* RenderWidgetHostViewAndroid::CreateSmoothScrollGesture(
- bool scroll_down, int pixels_to_scroll, int mouse_event_x,
- int mouse_event_y) {
- return new GenericTouchGestureAndroid(
- GetRenderWidgetHost(),
- content_view_core_->CreateOnePointTouchGesture(
- mouse_event_x, mouse_event_y,
- 0, scroll_down ? -pixels_to_scroll : pixels_to_scroll));
-}
-
-SyntheticGesture* RenderWidgetHostViewAndroid::CreatePinchGesture(
- bool zoom_in, int pixels_to_move, int anchor_x,
- int anchor_y) {
- int distance_between_pointers = zoom_in ?
- kMinimumPointerDistance : (kMinimumPointerDistance + pixels_to_move);
- return new GenericTouchGestureAndroid(
- GetRenderWidgetHost(),
- content_view_core_->CreateTwoPointTouchGesture(
- anchor_x, anchor_y - distance_between_pointers / 2,
- 0, (zoom_in ? -pixels_to_move : pixels_to_move) / 2,
- anchor_x, anchor_y + distance_between_pointers / 2,
- 0, (zoom_in ? pixels_to_move : -pixels_to_move) / 2));
+scoped_ptr<SyntheticGestureTarget>
+RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
+ return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid(
+ host_, content_view_core_->CreateTouchEventSynthesizer()));
}
void RenderWidgetHostViewAndroid::OnAcceleratedCompositingStateChange() {
@@ -643,25 +652,77 @@ void RenderWidgetHostViewAndroid::OnAcceleratedCompositingStateChange() {
void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
uint32 output_surface_id) {
cc::CompositorFrameAck ack;
- delegated_renderer_layer_->TakeUnusedResourcesForChildCompositor(
- &ack.resources);
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(
- host_->GetRoutingID(), output_surface_id,
- host_->GetProcess()->GetID(), ack);
+ if (resource_collection_.get())
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
+ RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(),
+ output_surface_id,
+ host_->GetProcess()->GetID(),
+ ack);
+}
+
+void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
+ // TODO(danakj): If no ack is pending, collect and send resources now.
+}
+
+void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
+ if (are_layers_attached_)
+ RemoveLayers();
+ frame_provider_ = NULL;
+ delegated_renderer_layer_ = NULL;
+ layer_ = NULL;
}
void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
uint32 output_surface_id,
scoped_ptr<cc::DelegatedFrameData> frame_data) {
- bool has_frame = frame_data.get() && !frame_data->render_pass_list.empty();
+ bool has_content = !texture_size_in_layer_.IsEmpty();
+
+ if (output_surface_id != last_output_surface_id_) {
+ // TODO(danakj): Lose all resources and send them back here, such as:
+ // resource_collection_->LoseAllResources();
+ // SendReturnedDelegatedResources(last_output_surface_id_);
+
+ // Drop the cc::DelegatedFrameResourceCollection so that we will not return
+ // any resources from the old output surface with the new output surface id.
+ if (resource_collection_.get()) {
+ resource_collection_->SetClient(NULL);
+ resource_collection_ = NULL;
+ }
+ DestroyDelegatedContent();
+
+ last_output_surface_id_ = output_surface_id;
+ }
- if (has_frame) {
- delegated_renderer_layer_->SetFrameData(frame_data.Pass());
+ if (!has_content) {
+ DestroyDelegatedContent();
+ } else {
+ if (!resource_collection_.get()) {
+ resource_collection_ = new cc::DelegatedFrameResourceCollection;
+ resource_collection_->SetClient(this);
+ }
+ if (!frame_provider_ ||
+ texture_size_in_layer_ != frame_provider_->frame_size()) {
+ if (are_layers_attached_)
+ RemoveLayers();
+ frame_provider_ = new cc::DelegatedFrameProvider(
+ resource_collection_.get(), frame_data.Pass());
+ delegated_renderer_layer_ =
+ cc::DelegatedRendererLayer::Create(frame_provider_);
+ layer_ = delegated_renderer_layer_;
+ if (are_layers_attached_)
+ AttachLayers();
+ } else {
+ frame_provider_->SetFrameData(frame_data.Pass());
+ }
+ }
+
+ if (delegated_renderer_layer_.get()) {
delegated_renderer_layer_->SetDisplaySize(texture_size_in_layer_);
- layer_->SetIsDrawable(true);
+ delegated_renderer_layer_->SetIsDrawable(true);
+ delegated_renderer_layer_->SetContentsOpaque(true);
+ delegated_renderer_layer_->SetBounds(content_size_in_layer_);
+ delegated_renderer_layer_->SetNeedsDisplay();
}
- layer_->SetBounds(content_size_in_layer_);
- layer_->SetNeedsDisplay();
base::Closure ack_callback =
base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
@@ -697,22 +758,28 @@ void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
UpdateContentViewCoreFrameMetadata(frame->metadata);
if (frame->delegated_frame_data) {
- if (!frame->delegated_frame_data->render_pass_list.empty()) {
- texture_size_in_layer_ = frame->delegated_frame_data->render_pass_list
- .back()->output_rect.size();
- }
+ DCHECK(UsingDelegatedRenderer());
+
+ DCHECK(frame->delegated_frame_data);
+ DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
+
+ cc::RenderPass* root_pass =
+ frame->delegated_frame_data->render_pass_list.back();
+ texture_size_in_layer_ = root_pass->output_rect.size();
ComputeContentsSize(frame->metadata);
SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
return;
}
+ DCHECK(!UsingDelegatedRenderer());
+
if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero())
return;
- if (output_surface_id != current_mailbox_output_surface_id_) {
+ if (output_surface_id != last_output_surface_id_) {
current_mailbox_ = gpu::Mailbox();
- current_mailbox_output_surface_id_ = kUndefinedOutputSurfaceId;
+ last_output_surface_id_ = kUndefinedOutputSurfaceId;
}
base::Closure callback = base::Bind(&InsertSyncPointAndAckForCompositor,
@@ -727,8 +794,11 @@ void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
texture_size_in_layer_ = frame->gl_frame_data->size;
ComputeContentsSize(frame->metadata);
- if (layer_->layer_tree_host())
- layer_->layer_tree_host()->SetLatencyInfo(frame->metadata.latency_info);
+ if (layer_->layer_tree_host()) {
+ scoped_ptr<cc::SwapPromise> swap_promise(
+ new cc::LatencyInfoSwapPromise(frame->metadata.latency_info));
+ layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass());
+ }
BuffersSwapped(frame->gl_frame_data->mailbox, output_surface_id, callback);
}
@@ -739,6 +809,44 @@ void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
// compositor flow.
UpdateContentViewCoreFrameMetadata(frame_metadata);
ComputeContentsSize(frame_metadata);
+
+ // DevTools ScreenCast support for Android WebView.
+ if (DevToolsAgentHost::HasFor(RenderViewHost::From(GetRenderWidgetHost()))) {
+ scoped_refptr<DevToolsAgentHost> dtah =
+ DevToolsAgentHost::GetOrCreateFor(
+ RenderViewHost::From(GetRenderWidgetHost()));
+ // Unblock the compositor.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame,
+ static_cast<RenderViewDevToolsAgentHost*>(dtah.get()),
+ frame_metadata));
+ }
+}
+
+void RenderWidgetHostViewAndroid::SynchronousCopyContents(
+ const gfx::Rect& src_subrect_in_pixel,
+ const gfx::Size& dst_size_in_pixel,
+ const base::Callback<void(bool, const SkBitmap&)>& callback) {
+ SynchronousCompositor* compositor =
+ SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
+ host_->GetRoutingID());
+ if (!compositor) {
+ callback.Run(false, SkBitmap());
+ return;
+ }
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ dst_size_in_pixel.width(),
+ dst_size_in_pixel.height());
+ bitmap.allocPixels();
+ SkCanvas canvas(bitmap);
+ canvas.scale(
+ (float)dst_size_in_pixel.width() / (float)src_subrect_in_pixel.width(),
+ (float)dst_size_in_pixel.height() / (float)src_subrect_in_pixel.height());
+ compositor->DemandDrawSw(&canvas);
+ callback.Run(true, bitmap);
}
void RenderWidgetHostViewAndroid::UpdateContentViewCoreFrameMetadata(
@@ -758,34 +866,15 @@ void RenderWidgetHostViewAndroid::UpdateContentViewCoreFrameMetadata(
}
}
+void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int host_id,
+ int route_id) {
+ accelerated_surface_route_id_ = route_id;
+}
+
void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
int gpu_host_id) {
- NOTREACHED() << "Deprecated. Use --composite-to-mailbox.";
-
- if (params.mailbox_name.empty())
- return;
-
- std::string return_mailbox;
- if (!current_mailbox_.IsZero()) {
- return_mailbox.assign(
- reinterpret_cast<const char*>(current_mailbox_.name),
- sizeof(current_mailbox_.name));
- }
-
- base::Closure callback = base::Bind(&InsertSyncPointAndAckForGpu,
- gpu_host_id, params.route_id,
- return_mailbox);
-
- gpu::Mailbox mailbox;
- std::copy(params.mailbox_name.data(),
- params.mailbox_name.data() + params.mailbox_name.length(),
- reinterpret_cast<char*>(mailbox.name));
-
- texture_size_in_layer_ = params.size;
- content_size_in_layer_ = params.size;
-
- BuffersSwapped(mailbox, kUndefinedOutputSurfaceId, callback);
+ NOTREACHED() << "Need --composite-to-mailbox or --enable-delegated-renderer";
}
void RenderWidgetHostViewAndroid::BuffersSwapped(
@@ -795,14 +884,11 @@ void RenderWidgetHostViewAndroid::BuffersSwapped(
ImageTransportFactoryAndroid* factory =
ImageTransportFactoryAndroid::GetInstance();
- // TODO(sievers): When running the impl thread in the browser we
- // need to delay the ACK until after commit and use more than a single
- // texture.
- DCHECK(!CompositorImpl::IsThreadingEnabled());
-
if (!texture_id_in_layer_) {
texture_id_in_layer_ = factory->CreateTexture();
+ texture_layer_->SetTextureId(texture_id_in_layer_);
texture_layer_->SetIsDrawable(true);
+ texture_layer_->SetContentsOpaque(true);
}
ImageTransportFactoryAndroid::GetInstance()->AcquireTexture(
@@ -811,7 +897,7 @@ void RenderWidgetHostViewAndroid::BuffersSwapped(
ResetClipping();
current_mailbox_ = mailbox;
- current_mailbox_output_surface_id_ = output_surface_id;
+ last_output_surface_id_ = output_surface_id;
if (host_->is_hidden())
ack_callback.Run();
@@ -822,47 +908,30 @@ void RenderWidgetHostViewAndroid::BuffersSwapped(
void RenderWidgetHostViewAndroid::AttachLayers() {
if (!content_view_core_)
return;
+ if (!layer_.get())
+ return;
content_view_core_->AttachLayer(layer_);
-
- if (overscroll_effect_)
- content_view_core_->AttachLayer(overscroll_effect_->root_layer());
+ if (overscroll_effect_enabled_)
+ overscroll_effect_->Enable();
}
void RenderWidgetHostViewAndroid::RemoveLayers() {
if (!content_view_core_)
return;
-
- if (overscroll_effect_)
- content_view_core_->RemoveLayer(overscroll_effect_->root_layer());
+ if (!layer_.get())
+ return;
content_view_core_->RemoveLayer(layer_);
+ overscroll_effect_->Disable();
}
bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
- if (!overscroll_effect_)
- return false;
return overscroll_effect_->Animate(frame_time);
}
-void RenderWidgetHostViewAndroid::CreateOverscrollEffectIfNecessary() {
- if (!overscroll_effect_enabled_ || overscroll_effect_)
- return;
-
- overscroll_effect_ = OverscrollGlow::Create(true, content_size_in_layer_);
-
- // Prevent future creation attempts on failure.
- if (!overscroll_effect_)
- overscroll_effect_enabled_ = false;
-
- if (overscroll_effect_ && content_view_core_ && are_layers_attached_)
- content_view_core_->AttachLayer(overscroll_effect_->root_layer());
-}
-
void RenderWidgetHostViewAndroid::UpdateAnimationSize(
const cc::CompositorFrameMetadata& frame_metadata) {
- if (!overscroll_effect_)
- return;
// Disable edge effects for axes on which scrolling is impossible.
gfx::SizeF ceiled_viewport_size =
gfx::ToCeiledSize(frame_metadata.viewport_size);
@@ -873,13 +942,6 @@ void RenderWidgetHostViewAndroid::UpdateAnimationSize(
overscroll_effect_->set_size(content_size_in_layer_);
}
-void RenderWidgetHostViewAndroid::ScheduleAnimationIfNecessary() {
- if (!content_view_core_)
- return;
- if (overscroll_effect_ && overscroll_effect_->NeedsAnimate())
- content_view_core_->SetNeedsAnimate();
-}
-
void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer(
const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
int gpu_host_id) {
@@ -899,8 +961,10 @@ void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() {
texture_id_in_layer_);
texture_id_in_layer_ = 0;
current_mailbox_ = gpu::Mailbox();
- current_mailbox_output_surface_id_ = kUndefinedOutputSurfaceId;
+ last_output_surface_id_ = kUndefinedOutputSurfaceId;
}
+ if (delegated_renderer_layer_.get())
+ DestroyDelegatedContent();
}
bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
@@ -909,7 +973,7 @@ bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
return false;
}
-void RenderWidgetHostViewAndroid::GetScreenInfo(WebKit::WebScreenInfo* result) {
+void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) {
// ScreenInfo isn't tied to the widget on Android. Always return the default.
RenderWidgetHostViewBase::GetDefaultScreenInfo(result);
}
@@ -921,12 +985,13 @@ gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
}
gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
- if (surface_texture_transport_) {
- return surface_texture_transport_->GetCompositingSurface(
- host_->surface_id());
- } else {
- return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::TEXTURE_TRANSPORT);
+ gfx::GLSurfaceHandle handle =
+ gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_TRANSPORT);
+ if (CompositorImpl::IsInitialized()) {
+ handle.parent_client_id =
+ ImageTransportFactoryAndroid::GetInstance()->GetChannelID();
}
+ return handle;
}
void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
@@ -946,45 +1011,65 @@ void RenderWidgetHostViewAndroid::SetScrollOffsetPinning(
}
void RenderWidgetHostViewAndroid::UnhandledWheelEvent(
- const WebKit::WebMouseWheelEvent& event) {
+ const blink::WebMouseWheelEvent& event) {
// intentionally empty, like RenderWidgetHostViewViews
}
void RenderWidgetHostViewAndroid::GestureEventAck(
int gesture_event_type,
InputEventAckState ack_result) {
- if (gesture_event_type == WebKit::WebInputEvent::GestureFlingStart &&
+ if (gesture_event_type == blink::WebInputEvent::GestureScrollUpdate &&
+ ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
+ content_view_core_->OnScrollUpdateGestureConsumed();
+ }
+ if (gesture_event_type == blink::WebInputEvent::GestureFlingStart &&
ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
content_view_core_->UnhandledFlingStartEvent();
}
}
InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
- const WebKit::WebInputEvent& input_event) {
- if (host_) {
- SynchronousCompositorImpl* compositor =
- SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
- host_->GetRoutingID());
- if (compositor)
- return compositor->HandleInputEvent(input_event);
+ const blink::WebInputEvent& input_event) {
+ if (!host_)
+ return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+
+ if (input_event.type == blink::WebInputEvent::GestureTapDown ||
+ input_event.type == blink::WebInputEvent::TouchStart) {
+ GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance();
+ GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
+ if (shim && gpu_data && accelerated_surface_route_id_ &&
+ gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING))
+ shim->Send(
+ new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_));
}
+
+ SynchronousCompositorImpl* compositor =
+ SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
+ host_->GetRoutingID());
+ if (compositor)
+ return compositor->HandleInputEvent(input_event);
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
+void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
+ if (flush_input_requested_ || !content_view_core_)
+ return;
+ flush_input_requested_ = true;
+ content_view_core_->AddBeginFrameSubscriber();
+}
+
void RenderWidgetHostViewAndroid::OnAccessibilityEvents(
const std::vector<AccessibilityHostMsg_EventParams>& params) {
- if (!host_ ||
- host_->accessibility_mode() != AccessibilityModeComplete ||
- !content_view_core_) {
+ if (!host_ || host_->accessibility_mode() != AccessibilityModeComplete)
return;
- }
if (!GetBrowserAccessibilityManager()) {
+ base::android::ScopedJavaLocalRef<jobject> obj;
+ if (content_view_core_)
+ obj = content_view_core_->GetJavaObject();
SetBrowserAccessibilityManager(
new BrowserAccessibilityManagerAndroid(
- content_view_core_->GetJavaObject(),
- BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
- this));
+ obj, BrowserAccessibilityManagerAndroid::GetEmptyDocument(), this));
}
GetBrowserAccessibilityManager()->OnAccessibilityEvents(params);
}
@@ -1060,32 +1145,29 @@ void RenderWidgetHostViewAndroid::SendKeyEvent(
}
void RenderWidgetHostViewAndroid::SendTouchEvent(
- const WebKit::WebTouchEvent& event) {
+ const blink::WebTouchEvent& event) {
if (host_)
host_->ForwardTouchEventWithLatencyInfo(event, ui::LatencyInfo());
}
void RenderWidgetHostViewAndroid::SendMouseEvent(
- const WebKit::WebMouseEvent& event) {
+ const blink::WebMouseEvent& event) {
if (host_)
host_->ForwardMouseEvent(event);
}
void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
- const WebKit::WebMouseWheelEvent& event) {
+ const blink::WebMouseWheelEvent& event) {
if (host_)
host_->ForwardWheelEvent(event);
}
void RenderWidgetHostViewAndroid::SendGestureEvent(
- const WebKit::WebGestureEvent& event) {
+ const blink::WebGestureEvent& event) {
// Sending a gesture that may trigger overscroll should resume the effect.
- if (overscroll_effect_) {
- overscroll_effect_->SetEnabled(true);
- if (event.type == WebKit::WebInputEvent::GestureScrollEnd)
- overscroll_effect_->Release(base::TimeTicks::Now());
- }
+ if (overscroll_effect_enabled_)
+ overscroll_effect_->Enable();
if (host_)
host_->ForwardGestureEvent(event);
@@ -1153,14 +1235,15 @@ SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
void RenderWidgetHostViewAndroid::OnOverscrolled(
gfx::Vector2dF accumulated_overscroll,
gfx::Vector2dF current_fling_velocity) {
- CreateOverscrollEffectIfNecessary();
- if (!overscroll_effect_)
+ if (!content_view_core_ || !are_layers_attached_)
return;
- overscroll_effect_->OnOverscrolled(base::TimeTicks::Now(),
- accumulated_overscroll,
- current_fling_velocity);
- ScheduleAnimationIfNecessary();
+ if (overscroll_effect_->OnOverscrolled(content_view_core_->GetLayer(),
+ base::TimeTicks::Now(),
+ accumulated_overscroll,
+ current_fling_velocity)) {
+ content_view_core_->SetNeedsAnimate();
+ }
}
void RenderWidgetHostViewAndroid::SetContentViewCore(
@@ -1170,10 +1253,29 @@ void RenderWidgetHostViewAndroid::SetContentViewCore(
if (are_layers_attached_)
RemoveLayers();
+ if (content_view_core_ && !using_synchronous_compositor_)
+ content_view_core_->GetWindowAndroid()->RemoveObserver(this);
+
content_view_core_ = content_view_core;
- if (are_layers_attached_)
+ if (GetBrowserAccessibilityManager()) {
+ base::android::ScopedJavaLocalRef<jobject> obj;
+ if (content_view_core_)
+ obj = content_view_core_->GetJavaObject();
+ GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerAndroid()->
+ SetContentViewCore(obj);
+ }
+
+ if (are_layers_attached_) {
AttachLayers();
+ if (content_view_core_ && !using_synchronous_compositor_)
+ content_view_core_->GetWindowAndroid()->AddObserver(this);
+ }
+
+ // Ensure ContentsViewCore is aware of the current touch handling state, eg.
+ // in case we've already been running JS for the page as part of preload.
+ if (content_view_core_ && host_)
+ content_view_core_->HasTouchEventHandlers(host_->has_touch_handler());
}
void RenderWidgetHostViewAndroid::RunAckCallbacks() {
@@ -1189,29 +1291,21 @@ void RenderWidgetHostViewAndroid::HasTouchEventHandlers(
content_view_core_->HasTouchEventHandlers(need_touch_events);
}
-unsigned RenderWidgetHostViewAndroid::PrepareTexture() {
+void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
RunAckCallbacks();
- return texture_id_in_layer_;
}
-void RenderWidgetHostViewAndroid::DidCommitFrameData() {
+void RenderWidgetHostViewAndroid::OnDetachCompositor() {
+ DCHECK(content_view_core_);
+ DCHECK(!using_synchronous_compositor_);
RunAckCallbacks();
}
-WebKit::WebGraphicsContext3D* RenderWidgetHostViewAndroid::Context3d() {
- return ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
-}
-
-bool RenderWidgetHostViewAndroid::PrepareTextureMailbox(
- cc::TextureMailbox* mailbox,
- scoped_ptr<cc::SingleReleaseCallback>* release_callback,
- bool use_shared_memory) {
- return false;
-}
-
void RenderWidgetHostViewAndroid::OnLostResources() {
- if (texture_layer_)
+ if (texture_layer_.get())
texture_layer_->SetIsDrawable(false);
+ if (delegated_renderer_layer_.get())
+ DestroyDelegatedContent();
texture_id_in_layer_ = 0;
RunAckCallbacks();
}
@@ -1230,10 +1324,10 @@ void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
scoped_ptr<SkBitmap> bitmap(new SkBitmap);
bitmap->setConfig(SkBitmap::kARGB_8888_Config,
- dst_size_in_pixel.width(), dst_size_in_pixel.height());
+ dst_size_in_pixel.width(), dst_size_in_pixel.height(),
+ 0, kOpaque_SkAlphaType);
if (!bitmap->allocPixels())
return;
- bitmap->setIsOpaque(true);
ImageTransportFactoryAndroid* factory =
ImageTransportFactoryAndroid::GetInstance();
@@ -1294,7 +1388,7 @@ void RenderWidgetHostViewAndroid::PrepareBitmapCopyOutputResult(
// static
void RenderWidgetHostViewPort::GetDefaultScreenInfo(
- WebKit::WebScreenInfo* results) {
+ blink::WebScreenInfo* results) {
const gfx::Display& display =
gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
results->rect = display.bounds();
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 6f248076e97..62bd7669647 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
@@ -14,7 +14,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
-#include "cc/layers/delegated_renderer_layer_client.h"
+#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/layers/texture_layer_client.h"
#include "cc/output/begin_frame_args.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
@@ -24,6 +24,7 @@
#include "gpu/command_buffer/common/mailbox.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "ui/base/android/window_android_observer.h"
#include "ui/gfx/size.h"
#include "ui/gfx/vector2d_f.h"
@@ -34,13 +35,14 @@ struct GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params;
namespace cc {
class CopyOutputResult;
+class DelegatedFrameProvider;
class DelegatedRendererLayer;
class Layer;
class SingleReleaseCallback;
class TextureLayer;
}
-namespace WebKit {
+namespace blink {
class WebExternalTextureLayer;
class WebTouchEvent;
class WebMouseEvent;
@@ -51,7 +53,6 @@ class ContentViewCoreImpl;
class OverscrollGlow;
class RenderWidgetHost;
class RenderWidgetHostImpl;
-class SurfaceTextureTransportClient;
struct NativeWebKeyboardEvent;
// -----------------------------------------------------------------------------
@@ -60,9 +61,9 @@ struct NativeWebKeyboardEvent;
class RenderWidgetHostViewAndroid
: public RenderWidgetHostViewBase,
public BrowserAccessibilityDelegate,
- public cc::TextureLayerClient,
- public cc::DelegatedRendererLayerClient,
- public ImageTransportFactoryAndroidObserver {
+ public cc::DelegatedFrameResourceCollectionClient,
+ public ImageTransportFactoryAndroidObserver,
+ public ui::WindowAndroidObserver {
public:
RenderWidgetHostViewAndroid(RenderWidgetHostImpl* widget,
ContentViewCoreImpl* content_view_core);
@@ -110,8 +111,8 @@ class RenderWidgetHostViewAndroid
virtual void RenderProcessGone(base::TerminationStatus status,
int error_code) OVERRIDE;
virtual void Destroy() OVERRIDE;
- virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
- virtual void SelectionChanged(const string16& text,
+ virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE;
+ virtual void SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
@@ -119,6 +120,8 @@ class RenderWidgetHostViewAndroid
virtual void ScrollOffsetChanged() OVERRIDE;
virtual BackingStore* AllocBackingStore(const gfx::Size& size) OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
+ virtual void AcceleratedSurfaceInitialized(int host_id,
+ int route_id) OVERRIDE;
virtual void AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
int gpu_host_id) OVERRIDE;
@@ -138,7 +141,7 @@ class RenderWidgetHostViewAndroid
const scoped_refptr<media::VideoFrame>& target,
const base::Callback<void(bool)>& callback) OVERRIDE;
virtual bool CanCopyToVideoFrame() const OVERRIDE;
- virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE;
+ virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE;
virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE;
virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
@@ -148,9 +151,10 @@ class RenderWidgetHostViewAndroid
virtual void SetScrollOffsetPinning(
bool is_pinned_to_left, bool is_pinned_to_right) OVERRIDE;
virtual void UnhandledWheelEvent(
- const WebKit::WebMouseWheelEvent& event) OVERRIDE;
+ const blink::WebMouseWheelEvent& event) OVERRIDE;
virtual InputEventAckState FilterInputEvent(
- const WebKit::WebInputEvent& input_event) OVERRIDE;
+ const blink::WebInputEvent& input_event) OVERRIDE;
+ virtual void OnSetNeedsFlushInput() OVERRIDE;
virtual void GestureEventAck(int gesture_event_type,
InputEventAckState ack_result) OVERRIDE;
virtual void OnAccessibilityEvents(
@@ -166,12 +170,8 @@ class RenderWidgetHostViewAndroid
gfx::Vector2dF current_fling_velocity) OVERRIDE;
virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect,
const SkBitmap& zoomed_bitmap) OVERRIDE;
- virtual SyntheticGesture* CreateSmoothScrollGesture(
- bool scroll_down, int pixels_to_scroll, int mouse_event_x,
- int mouse_event_y) OVERRIDE;
- virtual SyntheticGesture* CreatePinchGesture(
- bool zoom_in, int pixels_to_move, int anchor_x,
- int anchor_y) OVERRIDE;
+ virtual scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
+ OVERRIDE;
// Implementation of BrowserAccessibilityDelegate:
virtual void SetAccessibilityFocus(int acc_obj_id) OVERRIDE;
@@ -185,16 +185,13 @@ class RenderWidgetHostViewAndroid
virtual gfx::Point GetLastTouchEventLocation() const OVERRIDE;
virtual void FatalAccessibilityTreeError() OVERRIDE;
- // cc::TextureLayerClient implementation.
- virtual unsigned PrepareTexture() OVERRIDE;
- virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE;
- virtual bool PrepareTextureMailbox(
- cc::TextureMailbox* mailbox,
- scoped_ptr<cc::SingleReleaseCallback>* release_callback,
- bool use_shared_memory) OVERRIDE;
+ // cc::DelegatedFrameResourceCollectionClient implementation.
+ virtual void UnusedResourcesAreAvailable() OVERRIDE;
- // cc::DelegatedRendererLayerClient implementation.
- virtual void DidCommitFrameData() OVERRIDE;
+ // ui::WindowAndroidObserver implementation.
+ virtual void OnCompositingDidCommit() OVERRIDE;
+ virtual void OnAttachCompositor() OVERRIDE {}
+ virtual void OnDetachCompositor() OVERRIDE;
// ImageTransportFactoryAndroidObserver implementation.
virtual void OnLostResources() OVERRIDE;
@@ -203,23 +200,23 @@ class RenderWidgetHostViewAndroid
void SetContentViewCore(ContentViewCoreImpl* content_view_core);
SkColor GetCachedBackgroundColor() const;
void SendKeyEvent(const NativeWebKeyboardEvent& event);
- void SendTouchEvent(const WebKit::WebTouchEvent& event);
- void SendMouseEvent(const WebKit::WebMouseEvent& event);
- void SendMouseWheelEvent(const WebKit::WebMouseWheelEvent& event);
- void SendGestureEvent(const WebKit::WebGestureEvent& event);
+ void SendTouchEvent(const blink::WebTouchEvent& event);
+ void SendMouseEvent(const blink::WebMouseEvent& event);
+ void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event);
+ void SendGestureEvent(const blink::WebGestureEvent& event);
void SendBeginFrame(const cc::BeginFrameArgs& args);
void OnTextInputStateChanged(const ViewHostMsg_TextInputState_Params& params);
- void OnProcessImeBatchStateAck(bool is_begin);
void OnDidChangeBodyBackgroundColor(SkColor color);
void OnStartContentIntent(const GURL& content_url);
void OnSetNeedsBeginFrame(bool enabled);
+ void OnSmartClipDataExtracted(const string16& result);
int GetNativeImeAdapter();
void WasResized();
- WebKit::WebGLId GetScaledContentTexture(float scale, gfx::Size* out_size);
+ blink::WebGLId GetScaledContentTexture(float scale, gfx::Size* out_size);
bool PopulateBitmapWithContents(jobject jbitmap);
bool HasValidFrame() const;
@@ -246,6 +243,7 @@ class RenderWidgetHostViewAndroid
void RunAckCallbacks();
+ void DestroyDelegatedContent();
void SwapDelegatedFrame(uint32 output_surface_id,
scoped_ptr<cc::DelegatedFrameData> frame_data);
void SendDelegatedFrameAck(uint32 output_surface_id);
@@ -259,9 +257,7 @@ class RenderWidgetHostViewAndroid
void AttachLayers();
void RemoveLayers();
- void CreateOverscrollEffectIfNecessary();
void UpdateAnimationSize(const cc::CompositorFrameMetadata& frame_metadata);
- void ScheduleAnimationIfNecessary();
// Called after async screenshot task completes. Scales and crops the result
// of the copy.
@@ -274,6 +270,12 @@ class RenderWidgetHostViewAndroid
const base::Callback<void(bool, const SkBitmap&)>& callback,
scoped_ptr<cc::CopyOutputResult> result);
+ // DevTools ScreenCast support for Android WebView.
+ void SynchronousCopyContents(
+ const gfx::Rect& src_subrect_in_pixel,
+ const gfx::Size& dst_size_in_pixel,
+ const base::Callback<void(bool, const SkBitmap&)>& callback);
+
// The model object.
RenderWidgetHostImpl* host_;
@@ -297,6 +299,8 @@ class RenderWidgetHostViewAndroid
// The texture layer for this view when using browser-side compositing.
scoped_refptr<cc::TextureLayer> texture_layer_;
+ scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection_;
+ scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
scoped_refptr<cc::DelegatedRendererLayer> delegated_renderer_layer_;
// The layer used for rendering the contents of this view.
@@ -313,21 +317,30 @@ class RenderWidgetHostViewAndroid
// The most recent content size that was pushed to the texture layer.
gfx::Size content_size_in_layer_;
- // Used for image transport when needing to share resources across threads.
- scoped_ptr<SurfaceTextureTransportClient> surface_texture_transport_;
-
// The mailbox of the previously received frame.
gpu::Mailbox current_mailbox_;
- uint32_t current_mailbox_output_surface_id_;
+
+ // The output surface id of the last received frame.
+ uint32_t last_output_surface_id_;
base::WeakPtrFactory<RenderWidgetHostViewAndroid> weak_ptr_factory_;
std::queue<base::Closure> ack_callbacks_;
+ const bool overscroll_effect_enabled_;
// Used to render overscroll overlays.
- bool overscroll_effect_enabled_;
+ // Note: |overscroll_effect_| will never be NULL, even if it's never enabled.
scoped_ptr<OverscrollGlow> overscroll_effect_;
+ bool flush_input_requested_;
+
+ int accelerated_surface_route_id_;
+
+ // Size to use if we have no backing ContentViewCore
+ gfx::Size default_size_;
+
+ const bool using_synchronous_compositor_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroid);
};
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 2eb34b98d38..7f98b5d8ead 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
@@ -4,6 +4,7 @@
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "base/auto_reset.h"
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
@@ -12,6 +13,7 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "cc/layers/delegated_frame_provider.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_ack.h"
#include "cc/output/copy_output_request.h"
@@ -24,10 +26,10 @@
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/backing_store_aura.h"
#include "content/browser/renderer_host/dip_util.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "content/browser/renderer_host/web_input_event_aura.h"
#include "content/common/gpu/client/gl_helper.h"
@@ -43,17 +45,17 @@
#include "content/public/common/content_switches.h"
#include "media/base/video_util.h"
#include "skia/ext/image_operations.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "third_party/WebKit/public/web/WebScreenInfo.h"
#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/cursor_client_observer.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/stacking_client.h"
#include "ui/aura/client/tooltip_client.h"
+#include "ui/aura/client/window_tree_client.h"
#include "ui/aura/client/window_types.h"
#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
@@ -61,13 +63,13 @@
#include "ui/aura/window_observer.h"
#include "ui/aura/window_tracker.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
-#include "ui/base/gestures/gesture_recognizer.h"
#include "ui/base/hit_test.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/layer.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
+#include "ui/events/gestures/gesture_recognizer.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/display.h"
#include "ui/gfx/rect_conversions.h"
@@ -79,6 +81,7 @@
#include "base/win/windows_version.h"
#include "content/browser/accessibility/browser_accessibility_manager_win.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
+#include "content/common/plugin_constants_win.h"
#include "ui/base/win/hidden_window.h"
#include "ui/gfx/gdi_util.h"
#include "ui/gfx/win/dpi.h"
@@ -87,40 +90,11 @@
using gfx::RectToSkIRect;
using gfx::SkIRectToRect;
-using WebKit::WebScreenInfo;
-using WebKit::WebTouchEvent;
+using blink::WebScreenInfo;
+using blink::WebTouchEvent;
namespace content {
-void ReleaseMailbox(scoped_refptr<MemoryHolder> holder,
- unsigned sync_point,
- bool lost_resource) {}
-
-class MemoryHolder : public base::RefCounted<MemoryHolder> {
- public:
- MemoryHolder(scoped_ptr<base::SharedMemory> shared_memory,
- gfx::Size frame_size,
- base::Callback<void()> callback)
- : shared_memory_(shared_memory.Pass()),
- frame_size_(frame_size),
- callback_(callback) {}
-
- void GetMailbox(cc::TextureMailbox* mailbox,
- scoped_ptr<cc::SingleReleaseCallback>* release_callback) {
- *mailbox = cc::TextureMailbox(shared_memory_.get(), frame_size_);
- *release_callback = cc::SingleReleaseCallback::Create(
- base::Bind(ReleaseMailbox, make_scoped_refptr(this)));
- }
-
- private:
- friend class base::RefCounted<MemoryHolder>;
- ~MemoryHolder() { callback_.Run(); }
-
- scoped_ptr<base::SharedMemory> shared_memory_;
- gfx::Size frame_size_;
- base::Callback<void()> callback_;
-};
-
namespace {
void MailboxReleaseCallback(scoped_ptr<base::SharedMemory> shared_memory,
@@ -170,9 +144,10 @@ BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
RenderWidgetHostViewAura* widget =
reinterpret_cast<RenderWidgetHostViewAura*>(param);
- if (GetProp(window, kWidgetOwnerProperty) == widget) {
- HWND parent =
- widget->GetNativeView()->GetRootWindow()->GetAcceleratedWidget();
+ if (GetProp(window, kWidgetOwnerProperty) == widget &&
+ widget->GetNativeView()->GetDispatcher()) {
+ HWND parent = widget->GetNativeView()->GetDispatcher()->host()->
+ GetAcceleratedWidget();
SetParent(window, parent);
}
return TRUE;
@@ -194,8 +169,8 @@ BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
// First calculate the offset of this plugin from the root window, since
// the cutouts are relative to the root window.
- HWND parent = params->widget->GetNativeView()->GetRootWindow()->
- GetAcceleratedWidget();
+ HWND parent = params->widget->GetNativeView()->GetDispatcher()->
+ host()->GetAcceleratedWidget();
POINT offset;
offset.x = offset.y = 0;
MapWindowPoints(window, parent, &offset, 1);
@@ -227,7 +202,10 @@ BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
cutout_rects.push_back(offset_cutout);
}
gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
- SetWindowRgn(window, hrgn, TRUE);
+ // If we don't have any cutout rects then no point in messing with the
+ // window region.
+ if (cutout_rects.size())
+ SetWindowRgn(window, hrgn, TRUE);
}
return TRUE;
}
@@ -248,10 +226,10 @@ BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
}
#endif
-void UpdateWebTouchEventAfterDispatch(WebKit::WebTouchEvent* event,
- WebKit::WebTouchPoint* point) {
- if (point->state != WebKit::WebTouchPoint::StateReleased &&
- point->state != WebKit::WebTouchPoint::StateCancelled)
+void UpdateWebTouchEventAfterDispatch(blink::WebTouchEvent* event,
+ blink::WebTouchPoint* point) {
+ if (point->state != blink::WebTouchPoint::StateReleased &&
+ point->state != blink::WebTouchPoint::StateCancelled)
return;
--event->touchesLength;
for (unsigned i = point - event->touches;
@@ -273,6 +251,15 @@ bool CanRendererHandleEvent(const ui::MouseEvent* event) {
case WM_XBUTTONDBLCLK:
case WM_NCMOUSELEAVE:
case WM_NCMOUSEMOVE:
+ case WM_NCLBUTTONDOWN:
+ case WM_NCLBUTTONUP:
+ case WM_NCLBUTTONDBLCLK:
+ case WM_NCRBUTTONDOWN:
+ case WM_NCRBUTTONUP:
+ case WM_NCRBUTTONDBLCLK:
+ case WM_NCMBUTTONDOWN:
+ case WM_NCMBUTTONUP:
+ case WM_NCMBUTTONDBLCLK:
case WM_NCXBUTTONDOWN:
case WM_NCXBUTTONUP:
case WM_NCXBUTTONDBLCLK:
@@ -397,13 +384,13 @@ class RenderWidgetHostViewAura::EventFilterForPopupExit :
explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
: rwhva_(rwhva) {
DCHECK(rwhva_);
- aura::RootWindow* root_window = rwhva_->window_->GetRootWindow();
+ aura::Window* root_window = rwhva_->window_->GetRootWindow();
DCHECK(root_window);
root_window->AddPreTargetHandler(this);
}
virtual ~EventFilterForPopupExit() {
- aura::RootWindow* root_window = rwhva_->window_->GetRootWindow();
+ aura::Window* root_window = rwhva_->window_->GetRootWindow();
DCHECK(root_window);
root_window->RemovePreTargetHandler(this);
}
@@ -470,113 +457,6 @@ class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
DISALLOW_COPY_AND_ASSIGN(WindowObserver);
};
-#if defined(OS_WIN)
-// On Windows, we need to watch the top level window for changes to transient
-// windows because they can cover the view and we need to ensure that they're
-// rendered on top of windowed NPAPI plugins.
-class RenderWidgetHostViewAura::TransientWindowObserver
- : public aura::WindowObserver {
- public:
- explicit TransientWindowObserver(RenderWidgetHostViewAura* view)
- : view_(view), top_level_(NULL) {
- view_->window_->AddObserver(this);
- }
-
- virtual ~TransientWindowObserver() {
- view_->window_->RemoveObserver(this);
- StopObserving();
- }
-
- // Overridden from aura::WindowObserver:
- virtual void OnWindowHierarchyChanged(
- const aura::WindowObserver::HierarchyChangeParams& params) OVERRIDE {
- aura::Window* top_level = GetToplevelWindow();
- if (top_level == top_level_)
- return;
-
- StopObserving();
- top_level_ = top_level;
- if (top_level_ && top_level_ != view_->window_)
- top_level_->AddObserver(this);
- }
-
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
- if (window == top_level_)
- StopObserving();
- }
-
- virtual void OnWindowBoundsChanged(aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) OVERRIDE {
- if (window->transient_parent())
- SendPluginCutoutRects();
- }
-
- virtual void OnWindowVisibilityChanged(aura::Window* window,
- bool visible) OVERRIDE {
- if (window->transient_parent())
- SendPluginCutoutRects();
- }
-
- virtual void OnAddTransientChild(aura::Window* window,
- aura::Window* transient) OVERRIDE {
- transient->AddObserver(this);
- // Just wait for the OnWindowBoundsChanged of the transient, since the size
- // is not known now.
- }
-
- virtual void OnRemoveTransientChild(aura::Window* window,
- aura::Window* transient) OVERRIDE {
- transient->RemoveObserver(this);
- SendPluginCutoutRects();
- }
-
- aura::Window* GetToplevelWindow() {
- aura::RootWindow* root = view_->window_->GetRootWindow();
- if (!root)
- return NULL;
- aura::client::ActivationClient* activation_client =
- aura::client::GetActivationClient(root);
- if (!activation_client)
- return NULL;
- return activation_client->GetToplevelWindow(view_->window_);
- }
-
- void StopObserving() {
- if (!top_level_)
- return;
-
- const aura::Window::Windows& transients = top_level_->transient_children();
- for (size_t i = 0; i < transients.size(); ++i)
- transients[i]->RemoveObserver(this);
-
- if (top_level_ != view_->window_)
- top_level_->RemoveObserver(this);
- top_level_ = NULL;
- }
-
- void SendPluginCutoutRects() {
- std::vector<gfx::Rect> cutouts;
- if (top_level_) {
- const aura::Window::Windows& transients =
- top_level_->transient_children();
- for (size_t i = 0; i < transients.size(); ++i) {
- if (transients[i]->IsVisible())
- cutouts.push_back(transients[i]->GetBoundsInRootWindow());
- }
- }
-
- view_->UpdateTransientRects(cutouts);
- }
- private:
- RenderWidgetHostViewAura* view_;
- aura::Window* top_level_;
-
- DISALLOW_COPY_AND_ASSIGN(TransientWindowObserver);
-};
-
-#endif
-
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, public:
@@ -584,6 +464,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
: host_(RenderWidgetHostImpl::From(host)),
window_(new aura::Window(this)),
in_shutdown_(false),
+ in_bounds_changed_(false),
is_fullscreen_(false),
popup_parent_host_view_(NULL),
popup_child_host_view_(NULL),
@@ -592,7 +473,9 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
can_compose_inline_(true),
has_composition_text_(false),
+ accept_return_character_(false),
last_output_surface_id_(0),
+ pending_delegated_ack_count_(0),
skipped_frames_(false),
last_swapped_surface_scale_factor_(1.f),
paint_canvas_(NULL),
@@ -601,7 +484,9 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
can_lock_compositor_(YES),
cursor_visibility_state_in_renderer_(UNKNOWN),
paint_observer_(NULL),
- touch_editing_client_(NULL) {
+ touch_editing_client_(NULL),
+ delegated_frame_evictor_(new DelegatedFrameEvictor(this)),
+ weak_ptr_factory_(this) {
host_->SetView(this);
window_observer_.reset(new WindowObserver(this));
aura::client::SetTooltipText(window_, &tooltip_);
@@ -609,8 +494,10 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
aura::client::SetActivationChangeObserver(window_, this);
aura::client::SetFocusChangeObserver(window_, this);
gfx::Screen::GetScreenFor(window_)->AddObserver(this);
+ software_frame_manager_.reset(new SoftwareFrameManager(
+ weak_ptr_factory_.GetWeakPtr()));
#if defined(OS_WIN)
- transient_observer_.reset(new TransientWindowObserver(this));
+ plugin_parent_window_ = NULL;
#endif
}
@@ -636,6 +523,7 @@ void RenderWidgetHostViewAura::InitAsPopup(
// similar mechanism to ensure a second popup doesn't cause the first one
// to never get a chance to filter events. See crbug.com/160589.
DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
+ popup_parent_host_view_->window_->RemoveTransientChild(old_child->window_);
old_child->popup_parent_host_view_ = NULL;
}
popup_parent_host_view_->popup_child_host_view_ = this;
@@ -643,20 +531,14 @@ void RenderWidgetHostViewAura::InitAsPopup(
window_->Init(ui::LAYER_TEXTURED);
window_->SetName("RenderWidgetHostViewAura");
- aura::RootWindow* root = popup_parent_host_view_->window_->GetRootWindow();
- window_->SetDefaultParentByRootWindow(root, bounds_in_screen);
+ aura::Window* root = popup_parent_host_view_->window_->GetRootWindow();
+ aura::client::ParentWindowWithContext(window_, root, bounds_in_screen);
+ // Setting the transient child allows for the popup to get mouse events when
+ // in a system modal dialog.
+ // This fixes crbug.com/328593.
+ popup_parent_host_view_->window_->AddTransientChild(window_);
- // TODO(erg): While I could make sure details of the StackingClient are
- // hidden behind aura, hiding the details of the ScreenPositionClient will
- // take another effort.
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(root);
- gfx::Point origin_in_parent(bounds_in_screen.origin());
- if (screen_position_client) {
- screen_position_client->ConvertPointFromScreen(
- window_->parent(), &origin_in_parent);
- }
- SetBounds(gfx::Rect(origin_in_parent, bounds_in_screen.size()));
+ SetBounds(bounds_in_screen);
Show();
}
@@ -668,7 +550,7 @@ void RenderWidgetHostViewAura::InitAsFullscreen(
window_->SetName("RenderWidgetHostViewAura");
window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
- aura::RootWindow* parent = NULL;
+ aura::Window* parent = NULL;
gfx::Rect bounds;
if (reference_host_view) {
aura::Window* reference_window =
@@ -682,7 +564,7 @@ void RenderWidgetHostViewAura::InitAsFullscreen(
parent = reference_window->GetRootWindow();
bounds = display.bounds();
}
- window_->SetDefaultParentByRootWindow(parent, bounds);
+ aura::client::ParentWindowWithContext(window_, parent, bounds);
Show();
Focus();
}
@@ -696,10 +578,10 @@ void RenderWidgetHostViewAura::WasShown() {
if (!host_->is_hidden())
return;
host_->WasShown();
- if (framebuffer_holder_)
- FrameMemoryManager::GetInstance()->SetFrameVisibility(this, true);
+ software_frame_manager_->SetVisibility(true);
+ delegated_frame_evictor_->SetVisible(true);
- aura::RootWindow* root = window_->GetRootWindow();
+ aura::Window* root = window_->GetRootWindow();
if (root) {
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(root);
@@ -717,7 +599,13 @@ void RenderWidgetHostViewAura::WasShown() {
#if defined(OS_WIN)
LPARAM lparam = reinterpret_cast<LPARAM>(this);
EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
- transient_observer_->SendPluginCutoutRects();
+
+ if (::IsWindow(plugin_parent_window_)) {
+ gfx::Rect window_bounds = window_->GetBoundsInRootWindow();
+ ::SetWindowPos(plugin_parent_window_, NULL, window_bounds.x(),
+ window_bounds.y(), window_bounds.width(),
+ window_bounds.height(), 0);
+ }
#endif
}
@@ -725,47 +613,57 @@ void RenderWidgetHostViewAura::WasHidden() {
if (!host_ || host_->is_hidden())
return;
host_->WasHidden();
- if (framebuffer_holder_)
- FrameMemoryManager::GetInstance()->SetFrameVisibility(this, false);
-
+ software_frame_manager_->SetVisibility(false);
+ delegated_frame_evictor_->SetVisible(false);
released_front_lock_ = NULL;
#if defined(OS_WIN)
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (root_window) {
- HWND parent = root_window->GetAcceleratedWidget();
+ constrained_rects_.clear();
+ aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
+ if (dispatcher) {
+ HWND parent = dispatcher->host()->GetAcceleratedWidget();
LPARAM lparam = reinterpret_cast<LPARAM>(this);
EnumChildWindows(parent, HideWindowsCallback, lparam);
}
+ if (::IsWindow(plugin_parent_window_))
+ ::SetWindowPos(plugin_parent_window_, NULL, 0, 0, 0, 0, 0);
#endif
}
void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
- SetBounds(gfx::Rect(window_->bounds().origin(), size));
+ // For a SetSize operation, we don't care what coordinate system the origin
+ // of the window is in, it's only important to make sure that the origin
+ // remains constant after the operation.
+ InternalSetBounds(gfx::Rect(window_->bounds().origin(), size));
}
void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
- if (HasDisplayPropertyChanged(window_))
- host_->InvalidateScreenInfo();
+ gfx::Point relative_origin(rect.origin());
- window_->SetBounds(rect);
- host_->WasResized();
- MaybeCreateResizeLock();
- if (touch_editing_client_) {
- touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
- selection_focus_rect_);
+ // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
+ // Window::SetBounds() takes parent coordinates, so do the conversion here.
+ aura::Window* root = window_->GetRootWindow();
+ if (root) {
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(root);
+ if (screen_position_client) {
+ screen_position_client->ConvertPointFromScreen(
+ window_->parent(), &relative_origin);
+ }
}
+
+ InternalSetBounds(gfx::Rect(relative_origin, rect.size()));
}
void RenderWidgetHostViewAura::MaybeCreateResizeLock() {
if (!ShouldCreateResizeLock())
return;
- DCHECK(window_->GetRootWindow());
- DCHECK(window_->GetRootWindow()->compositor());
+ DCHECK(window_->GetDispatcher());
+ DCHECK(window_->GetDispatcher()->compositor());
// Listen to changes in the compositor lock state.
- ui::Compositor* compositor = window_->GetRootWindow()->compositor();
+ ui::Compositor* compositor = window_->GetDispatcher()->compositor();
if (!compositor->HasObserver(this))
compositor->AddObserver(this);
@@ -803,11 +701,11 @@ bool RenderWidgetHostViewAura::ShouldCreateResizeLock() {
if (desired_size == current_frame_size_)
return false;
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (!root_window)
+ aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
+ if (!dispatcher)
return false;
- ui::Compositor* compositor = root_window->compositor();
+ ui::Compositor* compositor = dispatcher->compositor();
if (!compositor)
return false;
@@ -818,7 +716,7 @@ scoped_ptr<ResizeLock> RenderWidgetHostViewAura::CreateResizeLock(
bool defer_compositor_lock) {
gfx::Size desired_size = window_->bounds().size();
return scoped_ptr<ResizeLock>(new CompositorResizeLock(
- window_->GetRootWindow(),
+ window_->GetDispatcher(),
desired_size,
defer_compositor_lock,
base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
@@ -830,21 +728,20 @@ gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
#if defined(OS_WIN)
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (root_window) {
- HWND window = root_window->GetAcceleratedWidget();
- return reinterpret_cast<gfx::NativeViewId>(window);
- }
+ aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
+ if (dispatcher)
+ return reinterpret_cast<gfx::NativeViewId>(
+ dispatcher->host()->GetAcceleratedWidget());
#endif
return static_cast<gfx::NativeViewId>(NULL);
}
gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
#if defined(OS_WIN)
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (!root_window)
+ aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
+ if (!dispatcher)
return static_cast<gfx::NativeViewAccessible>(NULL);
- HWND hwnd = root_window->GetAcceleratedWidget();
+ HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
BrowserAccessibilityManager* manager =
GetOrCreateBrowserAccessibilityManager();
@@ -863,10 +760,10 @@ RenderWidgetHostViewAura::GetOrCreateBrowserAccessibilityManager() {
return manager;
#if defined(OS_WIN)
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (!root_window)
+ aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
+ if (!dispatcher)
return NULL;
- HWND hwnd = root_window->GetAcceleratedWidget();
+ HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
// The accessible_parent may be NULL at this point. The WebContents will pass
// it down to this instance (by way of the RenderViewHost and
@@ -887,6 +784,16 @@ RenderWidgetHostViewAura::GetOrCreateBrowserAccessibilityManager() {
return manager;
}
+void RenderWidgetHostViewAura::SetKeyboardFocus() {
+#if defined(OS_WIN)
+ if (CanFocus()) {
+ aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
+ if (dispatcher)
+ ::SetFocus(dispatcher->host()->GetAcceleratedWidget());
+ }
+#endif
+}
+
void RenderWidgetHostViewAura::MovePluginWindows(
const gfx::Vector2d& scroll_offset,
const std::vector<WebPluginGeometry>& plugin_window_moves) {
@@ -897,7 +804,7 @@ void RenderWidgetHostViewAura::MovePluginWindows(
DCHECK(plugin_window_moves.empty());
return;
}
- HWND parent = window_->GetRootWindow()->GetAcceleratedWidget();
+ HWND parent = window_->GetDispatcher()->host()->GetAcceleratedWidget();
gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
std::vector<WebPluginGeometry> moves = plugin_window_moves;
@@ -917,14 +824,10 @@ void RenderWidgetHostViewAura::MovePluginWindows(
plugin_window_moves_[moves[i].window] = moves[i];
- // transient_rects_ and constrained_rects_ are relative to the root window.
- // We want to convert them to be relative to the plugin window.
- std::vector<gfx::Rect> cutout_rects;
- cutout_rects.assign(transient_rects_.begin(), transient_rects_.end());
- cutout_rects.insert(cutout_rects.end(), constrained_rects_.begin(),
- constrained_rects_.end());
- for (size_t j = 0; j < cutout_rects.size(); ++j) {
- gfx::Rect offset_cutout = cutout_rects[j];
+ // constrained_rects_ are relative to the root window. We want to convert
+ // them to be relative to the plugin window.
+ for (size_t j = 0; j < constrained_rects_.size(); ++j) {
+ gfx::Rect offset_cutout = constrained_rects_[j];
offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
moves[i].cutout_rects.push_back(offset_cutout);
}
@@ -938,7 +841,6 @@ void RenderWidgetHostViewAura::MovePluginWindows(
HWND window = moves[i].window;
if (GetParent(window) != parent) {
window = GetParent(window);
- DCHECK(GetParent(window) == parent);
}
if (!GetProp(window, kWidgetOwnerProperty))
SetProp(window, kWidgetOwnerProperty, this);
@@ -1072,7 +974,7 @@ void RenderWidgetHostViewAura::DidUpdateBackingStore(
SchedulePaintIfNotInClip(scroll_rect, clip_rect);
#if defined(OS_WIN)
- aura::RootWindow* root_window = window_->GetRootWindow();
+ aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
#endif
for (size_t i = 0; i < copy_rects.size(); ++i) {
gfx::Rect rect = gfx::SubtractRects(copy_rects[i], scroll_rect);
@@ -1082,12 +984,12 @@ void RenderWidgetHostViewAura::DidUpdateBackingStore(
SchedulePaintIfNotInClip(rect, clip_rect);
#if defined(OS_WIN)
- if (root_window) {
+ if (dispatcher) {
// Send the invalid rect in screen coordinates.
gfx::Rect screen_rect = GetViewBounds();
gfx::Rect invalid_screen_rect(rect);
invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
- HWND hwnd = root_window->GetAcceleratedWidget();
+ HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
PaintPluginWindowsHelper(hwnd, invalid_screen_rect);
}
#endif // defined(OS_WIN)
@@ -1108,9 +1010,10 @@ void RenderWidgetHostViewAura::Destroy() {
delete window_;
}
-void RenderWidgetHostViewAura::SetTooltipText(const string16& tooltip_text) {
+void RenderWidgetHostViewAura::SetTooltipText(
+ const base::string16& tooltip_text) {
tooltip_ = tooltip_text;
- aura::RootWindow* root_window = window_->GetRootWindow();
+ aura::Window* root_window = window_->GetRootWindow();
aura::client::TooltipClient* tooltip_client =
aura::client::GetTooltipClient(root_window);
if (tooltip_client) {
@@ -1120,7 +1023,7 @@ void RenderWidgetHostViewAura::SetTooltipText(const string16& tooltip_text) {
}
}
-void RenderWidgetHostViewAura::SelectionChanged(const string16& text,
+void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) {
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
@@ -1129,10 +1032,10 @@ void RenderWidgetHostViewAura::SelectionChanged(const string16& text,
if (text.empty() || range.is_empty())
return;
- // Set the BUFFER_SELECTION to the ui::Clipboard.
+ // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
ui::ScopedClipboardWriter clipboard_writer(
ui::Clipboard::GetForCurrentThread(),
- ui::Clipboard::BUFFER_SELECTION);
+ ui::CLIPBOARD_TYPE_SELECTION);
clipboard_writer.WriteText(text);
#endif // defined(USE_X11) && !defined(OS_CHROMEOS)
}
@@ -1156,7 +1059,7 @@ void RenderWidgetHostViewAura::SelectionBoundsChanged(
}
void RenderWidgetHostViewAura::ScrollOffsetChanged() {
- aura::RootWindow* root = window_->GetRootWindow();
+ aura::Window* root = window_->GetRootWindow();
if (!root)
return;
aura::client::CursorClient* cursor_client =
@@ -1200,16 +1103,33 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
return;
}
+ // Try get a texture to reuse.
+ scoped_refptr<OwnedMailbox> subscriber_texture;
+ if (frame_subscriber_) {
+ if (!idle_frame_subscriber_textures_.empty()) {
+ subscriber_texture = idle_frame_subscriber_textures_.back();
+ idle_frame_subscriber_textures_.pop_back();
+ } else if (GLHelper* helper =
+ ImageTransportFactory::GetInstance()->GetGLHelper()) {
+ subscriber_texture = new OwnedMailbox(helper);
+ }
+ }
+
scoped_ptr<cc::CopyOutputRequest> request =
cc::CopyOutputRequest::CreateRequest(base::Bind(
&RenderWidgetHostViewAura::
- CopyFromCompositingSurfaceHasResultForVideo,
+ CopyFromCompositingSurfaceHasResultForVideo,
AsWeakPtr(), // For caching the ReadbackYUVInterface on this class.
+ subscriber_texture,
target,
callback));
gfx::Rect src_subrect_in_pixel =
ConvertRectToPixel(current_device_scale_factor_, src_subrect);
request->set_area(src_subrect_in_pixel);
+ if (subscriber_texture) {
+ request->SetTextureMailbox(cc::TextureMailbox(
+ subscriber_texture->mailbox(), subscriber_texture->sync_point()));
+ }
window_->layer()->RequestCopyOfOutput(request.Pass());
}
@@ -1233,10 +1153,10 @@ void RenderWidgetHostViewAura::BeginFrameSubscription(
}
void RenderWidgetHostViewAura::EndFrameSubscription() {
+ idle_frame_subscriber_textures_.clear();
frame_subscriber_.reset();
}
-
void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
// Delay processing the state change until we either get a software frame if
// switching to software mode or receive a buffers swapped notification
@@ -1249,6 +1169,10 @@ void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
accelerated_compositing_state_changed_ = true;
}
+void RenderWidgetHostViewAura::AcceleratedSurfaceInitialized(int host_id,
+ int route_id) {
+}
+
bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const {
if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
can_lock_compositor_ == NO_PENDING_COMMIT ||
@@ -1258,6 +1182,45 @@ bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const {
return size_in_dip != resize_lock_->expected_size();
}
+void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
+ if (HasDisplayPropertyChanged(window_))
+ host_->InvalidateScreenInfo();
+
+ // Don't recursively call SetBounds if this bounds update is the result of
+ // a Window::SetBoundsInternal call.
+ if (!in_bounds_changed_)
+ window_->SetBounds(rect);
+ host_->WasResized();
+ MaybeCreateResizeLock();
+ if (touch_editing_client_) {
+ touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
+ selection_focus_rect_);
+ }
+#if defined(OS_WIN)
+ // Create the dummy plugin parent window which will be passed as the
+ // container window to windowless plugins.
+ // Plugins like Flash assume the container window which is returned via the
+ // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
+ // This is not true in Aura where we have only HWND which is the main Aura
+ // window. If we return this window to plugins like Flash then it causes the
+ // coordinate translations done by these plugins to break.
+ if (!plugin_parent_window_ && GetNativeViewId()) {
+ plugin_parent_window_ = ::CreateWindowEx(
+ 0, L"Static", NULL, WS_CHILDWINDOW, 0, 0, 0, 0,
+ reinterpret_cast<HWND>(GetNativeViewId()), NULL, NULL, NULL);
+ if (::IsWindow(plugin_parent_window_))
+ ::SetProp(plugin_parent_window_, content::kPluginDummyParentProperty,
+ reinterpret_cast<HANDLE>(true));
+ }
+ if (::IsWindow(plugin_parent_window_)) {
+ gfx::Rect window_bounds = window_->GetBoundsInRootWindow();
+ ::SetWindowPos(plugin_parent_window_, NULL, window_bounds.x(),
+ window_bounds.y(), window_bounds.width(),
+ window_bounds.height(), 0);
+ }
+#endif
+}
+
void RenderWidgetHostViewAura::CheckResizeLock() {
if (!resize_lock_ || resize_lock_->expected_size() != current_frame_size_)
return;
@@ -1286,12 +1249,12 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() {
current_frame_size_ = ConvertSizeToDIP(
current_surface_->device_scale_factor(), current_surface_->size());
CheckResizeLock();
- framebuffer_holder_ = NULL;
- FrameMemoryManager::GetInstance()->RemoveFrame(this);
- } else if (is_compositing_active && framebuffer_holder_) {
+ software_frame_manager_->DiscardCurrentFrame();
+ } else if (is_compositing_active &&
+ software_frame_manager_->HasCurrentFrame()) {
cc::TextureMailbox mailbox;
scoped_ptr<cc::SingleReleaseCallback> callback;
- framebuffer_holder_->GetMailbox(&mailbox, &callback);
+ software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback);
window_->layer()->SetTextureMailbox(mailbox,
callback.Pass(),
last_swapped_surface_scale_factor_);
@@ -1299,11 +1262,10 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() {
mailbox.shared_memory_size());
CheckResizeLock();
} else {
- window_->layer()->SetExternalTexture(NULL);
+ window_->layer()->SetShowPaintedContent();
resize_lock_.reset();
host_->WasResized();
- framebuffer_holder_ = NULL;
- FrameMemoryManager::GetInstance()->RemoveFrame(this);
+ software_frame_manager_->DiscardCurrentFrame();
}
}
@@ -1376,28 +1338,22 @@ void RenderWidgetHostViewAura::DidReceiveFrameFromRenderer() {
}
#if defined(OS_WIN)
-void RenderWidgetHostViewAura::UpdateTransientRects(
- const std::vector<gfx::Rect>& rects) {
- transient_rects_ = rects;
- UpdateCutoutRects();
-}
-
void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
const std::vector<gfx::Rect>& rects) {
- constrained_rects_ = rects;
- UpdateCutoutRects();
-}
+ // Check this before setting constrained_rects_, so that next time they're set
+ // and we have a root window we don't early return.
+ if (!window_->GetDispatcher())
+ return;
-void RenderWidgetHostViewAura::UpdateCutoutRects() {
- if (!window_->GetRootWindow())
+ if (rects == constrained_rects_)
return;
- HWND parent = window_->GetRootWindow()->GetAcceleratedWidget();
+
+ constrained_rects_ = rects;
+
+ HWND parent = window_->GetDispatcher()->host()->GetAcceleratedWidget();
CutoutRectsParams params;
params.widget = this;
- params.cutout_rects.assign(transient_rects_.begin(), transient_rects_.end());
- params.cutout_rects.insert(params.cutout_rects.end(),
- constrained_rects_.begin(),
- constrained_rects_.end());
+ params.cutout_rects = constrained_rects_;
params.geometry = &plugin_window_moves_;
LPARAM lparam = reinterpret_cast<LPARAM>(&params);
EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
@@ -1425,25 +1381,20 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame(
scoped_ptr<cc::DelegatedFrameData> frame_data,
float frame_device_scale_factor,
const ui::LatencyInfo& latency_info) {
- gfx::Size frame_size;
- gfx::Size frame_size_in_dip;
- gfx::Rect damage_rect;
- gfx::Rect damage_rect_in_dip;
+ DCHECK_NE(0u, frame_data->render_pass_list.size());
- if (!frame_data->render_pass_list.empty()) {
- cc::RenderPass* root_pass = frame_data->render_pass_list.back();
+ cc::RenderPass* root_pass = frame_data->render_pass_list.back();
- frame_size = root_pass->output_rect.size();
- frame_size_in_dip = ConvertSizeToDIP(frame_device_scale_factor, frame_size);
+ gfx::Size frame_size = root_pass->output_rect.size();
+ gfx::Size frame_size_in_dip =
+ ConvertSizeToDIP(frame_device_scale_factor, frame_size);
- damage_rect = gfx::ToEnclosingRect(root_pass->damage_rect);
- damage_rect.Intersect(gfx::Rect(frame_size));
- damage_rect_in_dip = ConvertRectToDIP(frame_device_scale_factor,
- damage_rect);
- }
+ gfx::Rect damage_rect = gfx::ToEnclosingRect(root_pass->damage_rect);
+ damage_rect.Intersect(gfx::Rect(frame_size));
+ gfx::Rect damage_rect_in_dip =
+ ConvertRectToDIP(frame_device_scale_factor, damage_rect);
- framebuffer_holder_ = NULL;
- FrameMemoryManager::GetInstance()->RemoveFrame(this);
+ software_frame_manager_->DiscardCurrentFrame();
if (ShouldSkipFrame(frame_size_in_dip)) {
cc::CompositorFrameAck ack;
@@ -1472,12 +1423,45 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame(
// indicates the renderer's output surface may have been recreated, in which
// case we should recreate the DelegatedRendererLayer, to avoid matching
// resources from the old one with resources from the new one which would
- // have the same id.
- window_->layer()->SetDelegatedFrame(scoped_ptr<cc::DelegatedFrameData>(),
- frame_size_in_dip);
+ // have the same id. Changing the layer to showing painted content destroys
+ // the DelegatedRendererLayer.
+ EvictDelegatedFrame();
+
+ // Drop the cc::DelegatedFrameResourceCollection so that we will not return
+ // any resources from the old output surface with the new output surface id.
+ if (resource_collection_.get()) {
+ resource_collection_->SetClient(NULL);
+
+ if (resource_collection_->LoseAllResources())
+ SendReturnedDelegatedResources(last_output_surface_id_);
+
+ resource_collection_ = NULL;
+ }
last_output_surface_id_ = output_surface_id;
}
- window_->layer()->SetDelegatedFrame(frame_data.Pass(), frame_size_in_dip);
+ if (frame_size.IsEmpty()) {
+ DCHECK_EQ(0u, frame_data->resource_list.size());
+ EvictDelegatedFrame();
+ } else {
+ if (!resource_collection_) {
+ resource_collection_ = new cc::DelegatedFrameResourceCollection;
+ resource_collection_->SetClient(this);
+ }
+ // If the physical frame size changes, we need a new |frame_provider_|. If
+ // the physical frame size is the same, but the size in DIP changed, we
+ // need to adjust the scale at which the frames will be drawn, and we do
+ // this by making a new |frame_provider_| also to ensure the scale change
+ // is presented in sync with the new frame content.
+ if (!frame_provider_.get() || frame_size != frame_provider_->frame_size() ||
+ frame_size_in_dip != current_frame_size_) {
+ frame_provider_ = new cc::DelegatedFrameProvider(
+ resource_collection_.get(), frame_data.Pass());
+ window_->layer()->SetShowDelegatedContent(frame_provider_.get(),
+ frame_size_in_dip);
+ } else {
+ frame_provider_->SetFrameData(frame_data.Pass());
+ }
+ }
released_front_lock_ = NULL;
current_frame_size_ = frame_size_in_dip;
CheckResizeLock();
@@ -1486,6 +1470,8 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame(
paint_observer_->OnUpdateCompositorContent();
window_->SchedulePaintInRect(damage_rect_in_dip);
+ pending_delegated_ack_count_++;
+
ui::Compositor* compositor = GetCompositor();
if (!compositor) {
SendDelegatedFrameAck(output_surface_id);
@@ -1497,14 +1483,47 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame(
output_surface_id));
}
DidReceiveFrameFromRenderer();
+ if (frame_provider_.get())
+ delegated_frame_evictor_->SwappedFrame(!host_->is_hidden());
+ // Note: the frame may have been evicted immediately.
}
void RenderWidgetHostViewAura::SendDelegatedFrameAck(uint32 output_surface_id) {
cc::CompositorFrameAck ack;
- window_->layer()->TakeUnusedResourcesForChildCompositor(&ack.resources);
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(
- host_->GetRoutingID(), output_surface_id,
- host_->GetProcess()->GetID(), ack);
+ if (resource_collection_)
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
+ RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(),
+ output_surface_id,
+ host_->GetProcess()->GetID(),
+ ack);
+ DCHECK_GT(pending_delegated_ack_count_, 0);
+ pending_delegated_ack_count_--;
+}
+
+void RenderWidgetHostViewAura::UnusedResourcesAreAvailable() {
+ if (pending_delegated_ack_count_)
+ return;
+
+ SendReturnedDelegatedResources(last_output_surface_id_);
+}
+
+void RenderWidgetHostViewAura::SendReturnedDelegatedResources(
+ uint32 output_surface_id) {
+ cc::CompositorFrameAck ack;
+ if (resource_collection_)
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
+ DCHECK(!ack.resources.empty());
+ RenderWidgetHostImpl::SendReclaimCompositorResources(
+ host_->GetRoutingID(),
+ output_surface_id,
+ host_->GetProcess()->GetID(),
+ ack);
+}
+
+void RenderWidgetHostViewAura::EvictDelegatedFrame() {
+ window_->layer()->SetShowPaintedContent();
+ frame_provider_ = NULL;
+ delegated_frame_evictor_->DiscardedFrame();
}
void RenderWidgetHostViewAura::SwapSoftwareFrame(
@@ -1522,18 +1541,13 @@ void RenderWidgetHostViewAura::SwapSoftwareFrame(
return;
}
- const size_t size_in_bytes = 4 * frame_size.GetArea();
-#ifdef OS_WIN
- scoped_ptr<base::SharedMemory> shared_memory(
- new base::SharedMemory(frame_data->handle, true,
- host_->GetProcess()->GetHandle()));
-#else
- scoped_ptr<base::SharedMemory> shared_memory(
- new base::SharedMemory(frame_data->handle, true));
-#endif
-
- if (!shared_memory->Map(size_in_bytes)) {
- host_->GetProcess()->ReceivedBadMessage();
+ if (!software_frame_manager_->SwapToNewFrame(
+ output_surface_id,
+ frame_data.get(),
+ frame_device_scale_factor,
+ host_->GetProcess()->GetHandle())) {
+ ReleaseSoftwareFrame(output_surface_id, frame_data->id);
+ SendSoftwareFrameAck(output_surface_id);
return;
}
@@ -1544,17 +1558,9 @@ void RenderWidgetHostViewAura::SwapSoftwareFrame(
last_swapped_surface_size_ = frame_size;
last_swapped_surface_scale_factor_ = frame_device_scale_factor;
- scoped_refptr<MemoryHolder> holder(new MemoryHolder(
- shared_memory.Pass(),
- frame_size,
- base::Bind(&RenderWidgetHostViewAura::ReleaseSoftwareFrame,
- AsWeakPtr(),
- output_surface_id,
- frame_data->id)));
- framebuffer_holder_.swap(holder);
cc::TextureMailbox mailbox;
scoped_ptr<cc::SingleReleaseCallback> callback;
- framebuffer_holder_->GetMailbox(&mailbox, &callback);
+ software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback);
DCHECK(mailbox.IsSharedMemory());
current_frame_size_ = frame_size_in_dip;
@@ -1573,22 +1579,22 @@ void RenderWidgetHostViewAura::SwapSoftwareFrame(
base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
AsWeakPtr(),
output_surface_id));
+ } else {
+ SendSoftwareFrameAck(output_surface_id);
}
if (paint_observer_)
paint_observer_->OnUpdateCompositorContent();
DidReceiveFrameFromRenderer();
- FrameMemoryManager::GetInstance()->AddFrame(this, !host_->is_hidden());
+
+ software_frame_manager_->SwapToNewFrameComplete(!host_->is_hidden());
}
void RenderWidgetHostViewAura::SendSoftwareFrameAck(uint32 output_surface_id) {
unsigned software_frame_id = 0;
- if (!released_software_frames_.empty()) {
- unsigned released_output_surface_id =
- released_software_frames_.back().output_surface_id;
- if (released_output_surface_id == output_surface_id) {
- software_frame_id = released_software_frames_.back().frame_id;
- released_software_frames_.pop_back();
- }
+ if (released_software_frame_ &&
+ released_software_frame_->output_surface_id == output_surface_id) {
+ software_frame_id = released_software_frame_->frame_id;
+ released_software_frame_.reset();
}
cc::CompositorFrameAck ack;
@@ -1600,24 +1606,25 @@ void RenderWidgetHostViewAura::SendSoftwareFrameAck(uint32 output_surface_id) {
}
void RenderWidgetHostViewAura::SendReclaimSoftwareFrames() {
- while (!released_software_frames_.empty()) {
- cc::CompositorFrameAck ack;
- ack.last_software_frame_id = released_software_frames_.back().frame_id;
- RenderWidgetHostImpl::SendReclaimCompositorResources(
- host_->GetRoutingID(),
- released_software_frames_.back().output_surface_id,
- host_->GetProcess()->GetID(),
- ack);
- released_software_frames_.pop_back();
- }
+ if (!released_software_frame_)
+ return;
+ cc::CompositorFrameAck ack;
+ ack.last_software_frame_id = released_software_frame_->frame_id;
+ RenderWidgetHostImpl::SendReclaimCompositorResources(
+ host_->GetRoutingID(),
+ released_software_frame_->output_surface_id,
+ host_->GetProcess()->GetID(),
+ ack);
+ released_software_frame_.reset();
}
void RenderWidgetHostViewAura::ReleaseSoftwareFrame(
uint32 output_surface_id,
unsigned software_frame_id) {
SendReclaimSoftwareFrames();
- released_software_frames_.push_back(
- ReleasedFrameInfo(output_surface_id, software_frame_id));
+ DCHECK(!released_software_frame_);
+ released_software_frame_.reset(new ReleasedFrameInfo(
+ output_surface_id, software_frame_id));
}
void RenderWidgetHostViewAura::OnSwapCompositorFrame(
@@ -1676,6 +1683,11 @@ void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
->set_parent_iaccessible(accessible_parent);
}
}
+
+gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
+ const {
+ return reinterpret_cast<gfx::NativeViewId>(plugin_parent_window_);
+}
#endif
void RenderWidgetHostViewAura::BuffersSwapped(
@@ -1687,8 +1699,7 @@ void RenderWidgetHostViewAura::BuffersSwapped(
const BufferPresentedCallback& ack_callback) {
scoped_refptr<ui::Texture> previous_texture(current_surface_);
const gfx::Rect surface_rect = gfx::Rect(surface_size);
- framebuffer_holder_ = NULL;
- FrameMemoryManager::GetInstance()->RemoveFrame(this);
+ software_frame_manager_->DiscardCurrentFrame();
if (!SwapBuffersPrepare(surface_rect,
surface_scale_factor,
@@ -1781,8 +1792,7 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
// We need to wait for a commit to clear to guarantee that all we
// will not issue any more GL referencing the previous surface.
AddOnCommitCallbackAndDisableLocks(
- base::Bind(&RenderWidgetHostViewAura::
- SetSurfaceNotInUseByCompositor,
+ base::Bind(&RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor,
AsWeakPtr(),
current_surface_)); // Hold a ref so the texture will not
// get deleted until after commit.
@@ -1848,10 +1858,10 @@ void RenderWidgetHostViewAura::PrepareTextureCopyOutputResult(
scoped_ptr<SkBitmap> bitmap(new SkBitmap);
bitmap->setConfig(SkBitmap::kARGB_8888_Config,
- dst_size_in_pixel.width(), dst_size_in_pixel.height());
+ dst_size_in_pixel.width(), dst_size_in_pixel.height(),
+ 0, kOpaque_SkAlphaType);
if (!bitmap->allocPixels())
return;
- bitmap->setIsOpaque(true);
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
GLHelper* gl_helper = factory->GetGLHelper();
@@ -1912,17 +1922,34 @@ void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult(
callback.Run(true, bitmap);
}
-static void CopyFromCompositingSurfaceFinishedForVideo(
+void RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo(
+ base::WeakPtr<RenderWidgetHostViewAura> rwhva,
const base::Callback<void(bool)>& callback,
+ scoped_refptr<OwnedMailbox> subscriber_texture,
scoped_ptr<cc::SingleReleaseCallback> release_callback,
bool result) {
- release_callback->Run(0, false);
callback.Run(result);
+
+ GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
+ uint32 sync_point = gl_helper ? gl_helper->InsertSyncPoint() : 0;
+ if (release_callback) {
+ DCHECK(!subscriber_texture);
+ release_callback->Run(sync_point, false);
+ } else {
+ // If there's no release callback, then the texture is from
+ // idle_frame_subscriber_textures_ and we can put it back there.
+ DCHECK(subscriber_texture);
+ subscriber_texture->UpdateSyncPoint(sync_point);
+ if (rwhva && rwhva->frame_subscriber_ && subscriber_texture->texture_id())
+ rwhva->idle_frame_subscriber_textures_.push_back(subscriber_texture);
+ subscriber_texture = NULL;
+ }
}
// static
void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
base::WeakPtr<RenderWidgetHostViewAura> rwhva,
+ scoped_refptr<OwnedMailbox> subscriber_texture,
scoped_refptr<media::VideoFrame> video_frame,
const base::Callback<void(bool)>& callback,
scoped_ptr<cc::CopyOutputResult> result) {
@@ -1930,7 +1957,6 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
if (!rwhva)
return;
-
if (result->IsEmpty())
return;
if (result->size().IsEmpty())
@@ -2027,14 +2053,16 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo(
video_frame->coded_size(),
region_in_frame,
true,
- false));
+ true));
yuv_readback_pipeline = rwhva->yuv_readback_pipeline_.get();
}
ignore_result(scoped_callback_runner.Release());
base::Callback<void(bool result)> finished_callback = base::Bind(
- &CopyFromCompositingSurfaceFinishedForVideo,
+ &RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo,
+ rwhva->AsWeakPtr(),
callback,
+ subscriber_texture,
base::Passed(&release_callback));
yuv_readback_pipeline->ReadbackYUV(
texture_mailbox.name(),
@@ -2054,10 +2082,10 @@ gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
RECT window_rect = {0};
aura::Window* top_level = window_->GetToplevelWindow();
- aura::RootWindow* root_window = top_level->GetRootWindow();
- if (!root_window)
+ aura::WindowEventDispatcher* dispatcher = top_level->GetDispatcher();
+ if (!dispatcher)
return top_level->GetBoundsInScreen();
- HWND hwnd = root_window->GetAcceleratedWidget();
+ HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
::GetWindowRect(hwnd, &window_rect);
gfx::Rect rect(window_rect);
@@ -2089,29 +2117,23 @@ void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
SCREEN_COORDINATES))
return;
- aura::RootWindow* root = window_->GetRootWindow();
- // |root| is NULL during tests.
- if (!root)
+ aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
+ // |dispatcher| is NULL during tests.
+ if (!dispatcher)
return;
ui::EventResult result = (ack_result ==
INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
end = events.end(); iter != end; ++iter) {
- root->ProcessedTouchEvent((*iter), window_, result);
+ dispatcher->ProcessedTouchEvent((*iter), window_, result);
}
}
-SyntheticGesture* RenderWidgetHostViewAura::CreateSmoothScrollGesture(
- bool scroll_down,
- int pixels_to_scroll,
- int mouse_event_x,
- int mouse_event_y) {
- return new TouchSmoothScrollGestureAura(scroll_down,
- pixels_to_scroll,
- mouse_event_x,
- mouse_event_y,
- window_);
+scoped_ptr<SyntheticGestureTarget>
+RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
+ return scoped_ptr<SyntheticGestureTarget>(
+ new SyntheticGestureTargetAura(host_));
}
void RenderWidgetHostViewAura::SetHasHorizontalScrollbar(
@@ -2143,7 +2165,7 @@ gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
}
bool RenderWidgetHostViewAura::LockMouse() {
- aura::RootWindow* root_window = window_->GetRootWindow();
+ aura::Window* root_window = window_->GetRootWindow();
if (!root_window)
return false;
@@ -2151,7 +2173,9 @@ bool RenderWidgetHostViewAura::LockMouse() {
return true;
mouse_locked_ = true;
+#if !defined(OS_WIN)
window_->SetCapture();
+#endif
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(root_window);
if (cursor_client) {
@@ -2165,17 +2189,21 @@ bool RenderWidgetHostViewAura::LockMouse() {
}
if (aura::client::GetTooltipClient(root_window))
aura::client::GetTooltipClient(root_window)->SetTooltipsEnabled(false);
+
+ root_window->GetDispatcher()->host()->ConfineCursorToRootWindow();
return true;
}
void RenderWidgetHostViewAura::UnlockMouse() {
- aura::RootWindow* root_window = window_->GetRootWindow();
+ aura::Window* root_window = window_->GetRootWindow();
if (!mouse_locked_ || !root_window)
return;
mouse_locked_ = false;
+#if !defined(OS_WIN)
window_->ReleaseCapture();
+#endif
window_->MoveCursorTo(unlocked_mouse_position_);
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(root_window);
@@ -2188,6 +2216,7 @@ void RenderWidgetHostViewAura::UnlockMouse() {
aura::client::GetTooltipClient(root_window)->SetTooltipsEnabled(true);
host_->LostMouseLock();
+ root_window->GetDispatcher()->host()->UnConfineCursor();
}
////////////////////////////////////////////////////////////////////////////////
@@ -2198,15 +2227,15 @@ void RenderWidgetHostViewAura::SetCompositionText(
return;
// ui::CompositionUnderline should be identical to
- // WebKit::WebCompositionUnderline, so that we can do reinterpret_cast safely.
+ // blink::WebCompositionUnderline, so that we can do reinterpret_cast safely.
COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
- sizeof(WebKit::WebCompositionUnderline),
+ sizeof(blink::WebCompositionUnderline),
ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
// TODO(suzhe): convert both renderer_host and renderer to use
// ui::CompositionText.
- const std::vector<WebKit::WebCompositionUnderline>& underlines =
- reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
+ const std::vector<blink::WebCompositionUnderline>& underlines =
+ reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>(
composition.underlines);
// TODO(suzhe): due to a bug of webkit, we can't use selection range with
@@ -2219,8 +2248,10 @@ void RenderWidgetHostViewAura::SetCompositionText(
}
void RenderWidgetHostViewAura::ConfirmCompositionText() {
- if (host_ && has_composition_text_)
- host_->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), false);
+ if (host_ && has_composition_text_) {
+ host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
+ false);
+ }
has_composition_text_ = false;
}
@@ -2230,7 +2261,7 @@ void RenderWidgetHostViewAura::ClearCompositionText() {
has_composition_text_ = false;
}
-void RenderWidgetHostViewAura::InsertText(const string16& text) {
+void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
if (host_)
host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
@@ -2243,9 +2274,10 @@ void RenderWidgetHostViewAura::InsertChar(char16 ch, int flags) {
return;
}
- if (host_) {
+ // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
+ if (host_ && (accept_return_character_ || ch != ui::VKEY_RETURN)) {
double now = ui::EventTimeForNow().InSecondsF();
- // Send a WebKit::WebInputEvent::Char event to |host_|.
+ // Send a blink::WebInputEvent::Char event to |host_|.
NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED,
true /* is_char */,
ch,
@@ -2271,11 +2303,12 @@ bool RenderWidgetHostViewAura::CanComposeInline() const {
return can_compose_inline_;
}
-gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(const gfx::Rect& rect) {
+gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(
+ const gfx::Rect& rect) const {
gfx::Point origin = rect.origin();
gfx::Point end = gfx::Point(rect.right(), rect.bottom());
- aura::RootWindow* root_window = window_->GetRootWindow();
+ aura::Window* root_window = window_->GetRootWindow();
if (!root_window)
return rect;
aura::client::ScreenPositionClient* screen_position_client =
@@ -2291,11 +2324,11 @@ gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(const gfx::Rect& rect) {
}
gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
- const gfx::Rect& rect) {
+ const gfx::Rect& rect) const {
gfx::Point origin = rect.origin();
gfx::Point end = gfx::Point(rect.right(), rect.bottom());
- aura::RootWindow* root_window = window_->GetRootWindow();
+ aura::Window* root_window = window_->GetRootWindow();
if (root_window) {
aura::client::ScreenPositionClient* screen_position_client =
aura::client::GetScreenPositionClient(root_window);
@@ -2310,14 +2343,15 @@ gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
return rect;
}
-gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() {
+gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
const gfx::Rect rect =
gfx::UnionRects(selection_anchor_rect_, selection_focus_rect_);
return ConvertRectToScreen(rect);
}
-bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(uint32 index,
- gfx::Rect* rect) {
+bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
+ uint32 index,
+ gfx::Rect* rect) const {
DCHECK(rect);
if (index >= composition_character_bounds_.size())
return false;
@@ -2325,23 +2359,24 @@ bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(uint32 index,
return true;
}
-bool RenderWidgetHostViewAura::HasCompositionText() {
+bool RenderWidgetHostViewAura::HasCompositionText() const {
return has_composition_text_;
}
-bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) {
+bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const {
range->set_start(selection_text_offset_);
range->set_end(selection_text_offset_ + selection_text_.length());
return true;
}
-bool RenderWidgetHostViewAura::GetCompositionTextRange(gfx::Range* range) {
+bool RenderWidgetHostViewAura::GetCompositionTextRange(
+ gfx::Range* range) const {
// TODO(suzhe): implement this method when fixing http://crbug.com/55130.
NOTIMPLEMENTED();
return false;
}
-bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) {
+bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
range->set_start(selection_range_.start());
range->set_end(selection_range_.end());
return true;
@@ -2361,7 +2396,7 @@ bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
bool RenderWidgetHostViewAura::GetTextFromRange(
const gfx::Range& range,
- string16* text) {
+ base::string16* text) const {
gfx::Range selection_text_range(selection_text_offset_,
selection_text_offset_ + selection_text_.length());
@@ -2397,8 +2432,8 @@ bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
return false;
host_->UpdateTextDirection(
direction == base::i18n::RIGHT_TO_LEFT ?
- WebKit::WebTextDirectionRightToLeft :
- WebKit::WebTextDirectionLeftToRight);
+ blink::WebTextDirectionRightToLeft :
+ blink::WebTextDirectionLeftToRight);
host_->NotifyTextDirection();
return true;
}
@@ -2420,6 +2455,18 @@ void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
ConvertRectFromScreen(intersected_rect));
}
+void RenderWidgetHostViewAura::OnCandidateWindowShown() {
+ host_->CandidateWindowShown();
+}
+
+void RenderWidgetHostViewAura::OnCandidateWindowUpdated() {
+ host_->CandidateWindowUpdated();
+}
+
+void RenderWidgetHostViewAura::OnCandidateWindowHidden() {
+ host_->CandidateWindowHidden();
+}
+
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
@@ -2454,6 +2501,7 @@ gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) {
+ base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true);
// We care about this only in fullscreen mode, where there is no
// WebContentsViewAura. We are sized via SetSize() or SetBounds() by
// WebContentsViewAura in other cases.
@@ -2479,7 +2527,7 @@ bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
}
bool RenderWidgetHostViewAura::CanFocus() {
- return popup_type_ == WebKit::WebPopupTypeNone;
+ return popup_type_ == blink::WebPopupTypeNone;
}
void RenderWidgetHostViewAura::OnCaptureLost() {
@@ -2539,7 +2587,7 @@ void RenderWidgetHostViewAura::OnWindowDestroying() {
if (!window_->GetRootWindow() || host_->is_hidden()) {
parent = ui::GetHiddenWindow();
} else {
- parent = window_->GetRootWindow()->GetAcceleratedWidget();
+ parent = window_->GetDispatcher()->host()->GetAcceleratedWidget();
}
LPARAM lparam = reinterpret_cast<LPARAM>(this);
EnumChildWindows(parent, WindowDestroyingCallback, lparam);
@@ -2583,7 +2631,7 @@ void RenderWidgetHostViewAura::DidRecreateLayer(ui::Layer *old_layer,
scoped_refptr<ui::Texture> new_texture;
if (host_->is_accelerated_compositing_active() &&
gl_helper && current_surface_.get()) {
- WebKit::WebGLId texture_id =
+ blink::WebGLId texture_id =
gl_helper->CopyTexture(current_surface_->PrepareTexture(),
current_surface_->size());
if (texture_id) {
@@ -2592,8 +2640,11 @@ void RenderWidgetHostViewAura::DidRecreateLayer(ui::Layer *old_layer,
current_surface_->device_scale_factor(), texture_id);
}
}
- old_layer->SetExternalTexture(new_texture);
- new_layer->SetExternalTexture(old_texture);
+ if (new_texture.get())
+ old_layer->SetExternalTexture(new_texture.get());
+ else
+ old_layer->SetShowPaintedContent();
+ new_layer->SetExternalTexture(old_texture.get());
} else if (old_mailbox.IsSharedMemory()) {
base::SharedMemory* old_buffer = old_mailbox.shared_memory();
const size_t size = old_mailbox.shared_memory_size_in_bytes();
@@ -2613,8 +2664,10 @@ void RenderWidgetHostViewAura::DidRecreateLayer(ui::Layer *old_layer,
callback.Pass(),
mailbox_scale_factor);
}
+ } else if (frame_provider_.get()) {
+ new_layer->SetShowDelegatedContent(frame_provider_.get(),
+ current_frame_size_);
}
- // TODO(piman): handle delegated frames.
}
////////////////////////////////////////////////////////////////////////////////
@@ -2655,6 +2708,14 @@ void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
host_->Shutdown();
}
} else {
+ if (event->key_code() == ui::VKEY_RETURN) {
+ // Do not forward return key release events if no press event was handled.
+ if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_)
+ return;
+ // Accept return key character events between press and release events.
+ accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
+ }
+
// We don't have to communicate with an input method here.
if (!event->HasNativeEvent()) {
NativeWebKeyboardEvent webkit_event(
@@ -2684,16 +2745,26 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
if (event->type() == ui::ET_MOUSEWHEEL) {
- WebKit::WebMouseWheelEvent mouse_wheel_event =
+ blink::WebMouseWheelEvent mouse_wheel_event =
MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
host_->ForwardWheelEvent(mouse_wheel_event);
return;
}
- WebKit::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
+ // If we receive non client mouse messages while we are in the locked state
+ // it probably means that the mouse left the borders of our window and
+ // needs to be moved back to the center.
+ if (event->flags() & ui::EF_IS_NON_CLIENT) {
+ synthetic_move_sent_ = true;
+ window_->MoveCursorTo(center);
+ return;
+ }
+
+ blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
+
bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
event->type() == ui::ET_MOUSE_DRAGGED) &&
mouse_event.x == center.x() && mouse_event.y == center.y();
@@ -2711,8 +2782,13 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
}
// Forward event to renderer.
if (CanRendererHandleEvent(event) &&
- !(event->flags() & ui::EF_FROM_TOUCH))
+ !(event->flags() & ui::EF_FROM_TOUCH)) {
host_->ForwardMouseEvent(mouse_event);
+ // Ensure that we get keyboard focus on mouse down as a plugin window
+ // may have grabbed keyboard focus.
+ if (event->type() == ui::ET_MOUSE_PRESSED)
+ SetKeyboardFocus();
+ }
}
return;
}
@@ -2738,24 +2814,28 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
// We get mouse wheel/scroll messages even if we are not in the foreground.
// So here we check if we have any owned popup windows in the foreground and
// dismiss them.
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (root_window) {
- HWND parent = root_window->GetAcceleratedWidget();
+ aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
+ if (dispatcher) {
+ HWND parent = dispatcher->host()->GetAcceleratedWidget();
HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
EnumThreadWindows(GetCurrentThreadId(),
DismissOwnedPopups,
reinterpret_cast<LPARAM>(toplevel_hwnd));
}
#endif
- WebKit::WebMouseWheelEvent mouse_wheel_event =
+ blink::WebMouseWheelEvent mouse_wheel_event =
MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
host_->ForwardWheelEvent(mouse_wheel_event);
} else if (CanRendererHandleEvent(event) &&
!(event->flags() & ui::EF_FROM_TOUCH)) {
- WebKit::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
+ blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
ModifyEventMovementAndCoords(&mouse_event);
host_->ForwardMouseEvent(mouse_event);
+ // Ensure that we get keyboard focus on mouse down as a plugin window may
+ // have grabbed keyboard focus.
+ if (event->type() == ui::ET_MOUSE_PRESSED)
+ SetKeyboardFocus();
}
switch (event->type()) {
@@ -2791,18 +2871,22 @@ void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
return;
if (event->type() == ui::ET_SCROLL) {
+#if !defined(OS_WIN)
+ // TODO(ananta)
+ // Investigate if this is true for Windows 8 Metro ASH as well.
if (event->finger_count() != 2)
return;
- WebKit::WebGestureEvent gesture_event =
+#endif
+ blink::WebGestureEvent gesture_event =
MakeWebGestureEventFlingCancel();
host_->ForwardGestureEvent(gesture_event);
- WebKit::WebMouseWheelEvent mouse_wheel_event =
+ blink::WebMouseWheelEvent mouse_wheel_event =
MakeWebMouseWheelEvent(event);
host_->ForwardWheelEvent(mouse_wheel_event);
RecordAction(UserMetricsAction("TrackpadScroll"));
} else if (event->type() == ui::ET_SCROLL_FLING_START ||
event->type() == ui::ET_SCROLL_FLING_CANCEL) {
- WebKit::WebGestureEvent gesture_event =
+ blink::WebGestureEvent gesture_event =
MakeWebGestureEvent(event);
host_->ForwardGestureEvent(gesture_event);
if (event->type() == ui::ET_SCROLL_FLING_START)
@@ -2818,7 +2902,7 @@ void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
return;
// Update the touch event first.
- WebKit::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event,
+ blink::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event,
&touch_event_);
// Forward the touch event only if a touch point was updated, and there's a
@@ -2851,7 +2935,7 @@ void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
return;
RenderViewHostDelegate* delegate = NULL;
- if (popup_type_ == WebKit::WebPopupTypeNone && !is_fullscreen_)
+ if (popup_type_ == blink::WebPopupTypeNone && !is_fullscreen_)
delegate = RenderViewHost::From(host_)->GetDelegate();
if (delegate && event->type() == ui::ET_GESTURE_BEGIN &&
@@ -2859,17 +2943,17 @@ void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
delegate->HandleGestureBegin();
}
- WebKit::WebGestureEvent gesture = MakeWebGestureEvent(event);
+ blink::WebGestureEvent gesture = MakeWebGestureEvent(event);
if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
// Webkit does not stop a fling-scroll on tap-down. So explicitly send an
// event to stop any in-progress flings.
- WebKit::WebGestureEvent fling_cancel = gesture;
- fling_cancel.type = WebKit::WebInputEvent::GestureFlingCancel;
- fling_cancel.sourceDevice = WebKit::WebGestureEvent::Touchscreen;
+ blink::WebGestureEvent fling_cancel = gesture;
+ fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
+ fling_cancel.sourceDevice = blink::WebGestureEvent::Touchscreen;
host_->ForwardGestureEvent(fling_cancel);
}
- if (gesture.type != WebKit::WebInputEvent::Undefined) {
+ if (gesture.type != blink::WebInputEvent::Undefined) {
host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
@@ -2895,10 +2979,10 @@ void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
// RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
bool RenderWidgetHostViewAura::ShouldActivate() const {
- aura::RootWindow* root_window = window_->GetRootWindow();
- if (!root_window)
+ aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
+ if (!dispatcher)
return true;
- const ui::Event* event = root_window->current_event();
+ const ui::Event* event = dispatcher->current_event();
if (!event)
return true;
return is_fullscreen_;
@@ -2912,7 +2996,7 @@ void RenderWidgetHostViewAura::OnWindowActivated(aura::Window* gained_active,
aura::Window* lost_active) {
DCHECK(window_ == gained_active || window_ == lost_active);
if (window_ == gained_active) {
- const ui::Event* event = window_->GetRootWindow()->current_event();
+ const ui::Event* event = window_->GetDispatcher()->current_event();
if (event && PointerEventActivates(*event))
host_->OnPointerEventActivate();
}
@@ -2974,6 +3058,17 @@ void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
(screen->GetDisplayNearestWindow(window_).id() !=
screen->GetDisplayNearestWindow(gained_focus).id());
if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
+#if defined(OS_WIN)
+ // On Windows, if we are switching to a non Aura Window on a different
+ // screen we should not close the fullscreen window.
+ if (!gained_focus) {
+ POINT point = {0};
+ ::GetCursorPos(&point);
+ if (screen->GetDisplayNearestWindow(window_).id() !=
+ screen->GetDisplayNearestPoint(gfx::Point(point)).id())
+ return;
+ }
+#endif
in_shutdown_ = true;
host_->Shutdown();
}
@@ -2986,19 +3081,27 @@ void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
void RenderWidgetHostViewAura::OnRootWindowHostMoved(
const aura::RootWindow* root,
const gfx::Point& new_origin) {
+ TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnRootWindowHostMoved",
+ "new_origin", new_origin.ToString());
+
UpdateScreenInfo(window_);
}
-void RenderWidgetHostViewAura::ReleaseCurrentFrame() {
- if (framebuffer_holder_.get() && !current_surface_.get()) {
- framebuffer_holder_ = NULL;
- ui::Compositor* compositor = GetCompositor();
- if (compositor) {
- AddOnCommitCallbackAndDisableLocks(base::Bind(
- &RenderWidgetHostViewAura::SendReclaimSoftwareFrames, AsWeakPtr()));
- }
- UpdateExternalTexture();
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, SoftwareFrameManagerClient implementation:
+
+void RenderWidgetHostViewAura::SoftwareFrameWasFreed(
+ uint32 output_surface_id, unsigned frame_id) {
+ ReleaseSoftwareFrame(output_surface_id, frame_id);
+}
+
+void RenderWidgetHostViewAura::ReleaseReferencesToSoftwareFrame() {
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor) {
+ AddOnCommitCallbackAndDisableLocks(base::Bind(
+ &RenderWidgetHostViewAura::SendReclaimSoftwareFrames, AsWeakPtr()));
}
+ UpdateExternalTexture();
}
////////////////////////////////////////////////////////////////////////////////
@@ -3122,6 +3225,8 @@ void RenderWidgetHostViewAura::OnLostResources() {
current_surface_ = NULL;
UpdateExternalTexture();
+ idle_frame_subscriber_textures_.clear();
+
// Make sure all ImageTransportClients are deleted now that the context those
// are using is becoming invalid. This sends pending ACKs and needs to happen
// after calling UpdateExternalTexture() which syncs with the impl thread.
@@ -3149,13 +3254,10 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
factory->RemoveObserver(this);
}
window_observer_.reset();
-#if defined(OS_WIN)
- transient_observer_.reset();
-#endif
- if (window_->GetRootWindow())
- window_->GetRootWindow()->RemoveRootWindowObserver(this);
+ if (window_->GetDispatcher())
+ window_->GetDispatcher()->RemoveRootWindowObserver(this);
UnlockMouse();
- if (popup_type_ != WebKit::WebPopupTypeNone && popup_parent_host_view_) {
+ if (popup_parent_host_view_) {
DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
popup_parent_host_view_->popup_child_host_view_ == this);
popup_parent_host_view_->popup_child_host_view_ = NULL;
@@ -3172,13 +3274,20 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
// Aura root window and we don't have a way to get an input method object
// associated with the window, but just in case.
DetachFromInputMethod();
- FrameMemoryManager::GetInstance()->RemoveFrame(this);
+
+ if (resource_collection_.get())
+ resource_collection_->SetClient(NULL);
+
+#if defined(OS_WIN)
+ if (::IsWindow(plugin_parent_window_))
+ ::DestroyWindow(plugin_parent_window_);
+#endif
}
void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
const gfx::Point screen_point =
gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
- aura::RootWindow* root_window = window_->GetRootWindow();
+ aura::Window* root_window = window_->GetRootWindow();
if (!root_window)
return;
@@ -3186,10 +3295,17 @@ void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
gfx::Point local_point = screen_point;
local_point.Offset(-screen_rect.x(), -screen_rect.y());
- if (!root_window->HasFocus() ||
- root_window->GetEventHandlerForPoint(local_point) != window_) {
+#if defined(OS_WIN)
+ // If there's another toplevel window above us at this point (for example a
+ // menu), we don't want to update the cursor.
+ POINT windows_point = { screen_point.x(), screen_point.y() };
+ aura::WindowEventDispatcher* dispatcher = root_window->GetDispatcher();
+ if (dispatcher->host()->GetAcceleratedWidget() !=
+ ::WindowFromPoint(windows_point))
+ return;
+#endif
+ if (root_window->GetEventHandlerForPoint(local_point) != window_)
return;
- }
gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
// Do not show loading cursor when the cursor is currently hidden.
@@ -3204,30 +3320,32 @@ void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
}
ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
- aura::RootWindow* root_window = window_->GetRootWindow();
+ aura::Window* root_window = window_->GetRootWindow();
if (!root_window)
return NULL;
return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
}
bool RenderWidgetHostViewAura::NeedsInputGrab() {
- return popup_type_ == WebKit::WebPopupTypeSelect;
+ return popup_type_ == blink::WebPopupTypeSelect;
}
void RenderWidgetHostViewAura::FinishImeCompositionSession() {
if (!has_composition_text_)
return;
- if (host_)
- host_->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), false);
+ if (host_) {
+ host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
+ false);
+ }
ImeCancelComposition();
}
void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
- WebKit::WebMouseEvent* event) {
+ blink::WebMouseEvent* event) {
// If the mouse has just entered, we must report zero movementX/Y. Hence we
// reset any global_mouse_position set previously.
- if (event->type == WebKit::WebInputEvent::MouseEnter ||
- event->type == WebKit::WebInputEvent::MouseLeave)
+ if (event->type == blink::WebInputEvent::MouseEnter ||
+ event->type == blink::WebInputEvent::MouseLeave)
global_mouse_position_.SetPoint(event->globalX, event->globalY);
// Movement is computed by taking the difference of the new cursor position
@@ -3313,10 +3431,10 @@ void RenderWidgetHostViewAura::AddOnCommitCallbackAndDisableLocks(
}
void RenderWidgetHostViewAura::AddedToRootWindow() {
- window_->GetRootWindow()->AddRootWindowObserver(this);
+ window_->GetDispatcher()->AddRootWindowObserver(this);
host_->ParentChanged(GetNativeViewId());
UpdateScreenInfo(window_);
- if (popup_type_ != WebKit::WebPopupTypeNone)
+ if (popup_type_ != blink::WebPopupTypeNone)
event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
aura::client::CursorClient* cursor_client =
@@ -3325,7 +3443,13 @@ void RenderWidgetHostViewAura::AddedToRootWindow() {
cursor_client->AddObserver(this);
NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
}
- UpdateExternalTexture();
+ if (current_surface_.get())
+ UpdateExternalTexture();
+ if (HasFocus()) {
+ ui::InputMethod* input_method = GetInputMethod();
+ if (input_method)
+ input_method->SetFocusedTextInputClient(this);
+ }
}
void RenderWidgetHostViewAura::RemovingFromRootWindow() {
@@ -3334,15 +3458,20 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() {
if (cursor_client)
cursor_client->RemoveObserver(this);
+ DetachFromInputMethod();
+
event_filter_for_popup_exit_.reset();
- window_->GetRootWindow()->RemoveRootWindowObserver(this);
+ window_->GetDispatcher()->RemoveRootWindowObserver(this);
host_->ParentChanged(0);
ui::Compositor* compositor = GetCompositor();
- // We can't get notification for commits after this point, which would
- // guarantee that the compositor isn't using an old texture any more, so
- // instead we force the texture to NULL which synchronizes with the compositor
- // thread, and makes it safe to run the callback.
- window_->layer()->SetExternalTexture(NULL);
+ if (current_surface_.get()) {
+ // We can't get notification for commits after this point, which would
+ // guarantee that the compositor isn't using an old texture any more, so
+ // instead we force the layer to stop using any external resources which
+ // synchronizes with the compositor thread, and makes it safe to run the
+ // callback.
+ window_->layer()->SetShowPaintedContent();
+ }
RunOnCommitCallbacks();
resize_lock_.reset();
host_->WasResized();
@@ -3351,8 +3480,8 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() {
}
ui::Compositor* RenderWidgetHostViewAura::GetCompositor() const {
- aura::RootWindow* root_window = window_->GetRootWindow();
- return root_window ? root_window->compositor() : NULL;
+ aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
+ return dispatcher ? dispatcher->compositor() : NULL;
}
void RenderWidgetHostViewAura::DetachFromInputMethod() {
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 f5939df0fc7..041b61dfd77 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -15,11 +15,15 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "cc/layers/delegated_frame_provider.h"
+#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/resources/texture_mailbox.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/aura/image_transport_factory.h"
-#include "content/browser/renderer_host/frame_memory_manager.h"
+#include "content/browser/aura/owned_mailbox.h"
+#include "content/browser/renderer_host/delegated_frame_evictor.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/renderer_host/software_frame_manager.h"
#include "content/common/content_export.h"
#include "content/common/gpu/client/gl_helper.h"
#include "third_party/skia/include/core/SkRegion.h"
@@ -57,7 +61,6 @@ class Texture;
}
namespace content {
-class MemoryHolder;
class RenderWidgetHostImpl;
class RenderWidgetHostView;
class ResizeLock;
@@ -76,8 +79,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
public aura::client::CursorClientObserver,
public ImageTransportFactoryObserver,
public BrowserAccessibilityDelegate,
- public FrameContainer,
- public base::SupportsWeakPtr<RenderWidgetHostViewAura> {
+ public SoftwareFrameManagerClient,
+ public DelegatedFrameEvictorClient,
+ public base::SupportsWeakPtr<RenderWidgetHostViewAura>,
+ public cc::DelegatedFrameResourceCollectionClient {
public:
// Used to notify whenever the paint-content of the view changes.
class PaintObserver {
@@ -188,8 +193,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
virtual void RenderProcessGone(base::TerminationStatus status,
int error_code) OVERRIDE;
virtual void Destroy() OVERRIDE;
- virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
- virtual void SelectionChanged(const string16& text,
+ virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE;
+ virtual void SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
@@ -210,6 +215,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
virtual void EndFrameSubscription() OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
+ virtual void AcceleratedSurfaceInitialized(int host_id,
+ int route_id) OVERRIDE;
virtual void AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
int gpu_host_id) OVERRIDE;
@@ -219,18 +226,15 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
virtual void AcceleratedSurfaceSuspend() OVERRIDE;
virtual void AcceleratedSurfaceRelease() OVERRIDE;
virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE;
- virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE;
+ virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE;
virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE;
virtual void GestureEventAck(int gesture_event_type,
InputEventAckState ack_result) OVERRIDE;
virtual void ProcessAckedTouchEvent(
const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) OVERRIDE;
- virtual SyntheticGesture* CreateSmoothScrollGesture(
- bool scroll_down,
- int pixels_to_scroll,
- int mouse_event_x,
- int mouse_event_y) OVERRIDE;
+ virtual scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
+ OVERRIDE;
virtual void SetHasHorizontalScrollbar(
bool has_horizontal_scrollbar) OVERRIDE;
virtual void SetScrollOffsetPinning(
@@ -247,6 +251,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
#if defined(OS_WIN)
virtual void SetParentNativeViewAccessible(
gfx::NativeViewAccessible accessible_parent) OVERRIDE;
+ virtual gfx::NativeViewId GetParentForWindowlessPlugin() const OVERRIDE;
#endif
// Overridden from ui::TextInputClient:
@@ -254,28 +259,31 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
const ui::CompositionText& composition) OVERRIDE;
virtual void ConfirmCompositionText() OVERRIDE;
virtual void ClearCompositionText() OVERRIDE;
- virtual void InsertText(const string16& text) OVERRIDE;
+ virtual void InsertText(const base::string16& text) OVERRIDE;
virtual void InsertChar(char16 ch, int flags) OVERRIDE;
virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
virtual ui::TextInputType GetTextInputType() const OVERRIDE;
virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
virtual bool CanComposeInline() const OVERRIDE;
- virtual gfx::Rect GetCaretBounds() OVERRIDE;
+ virtual gfx::Rect GetCaretBounds() const OVERRIDE;
virtual bool GetCompositionCharacterBounds(uint32 index,
- gfx::Rect* rect) OVERRIDE;
- virtual bool HasCompositionText() OVERRIDE;
- virtual bool GetTextRange(gfx::Range* range) OVERRIDE;
- virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE;
- virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE;
+ gfx::Rect* rect) const OVERRIDE;
+ virtual bool HasCompositionText() const OVERRIDE;
+ virtual bool GetTextRange(gfx::Range* range) const OVERRIDE;
+ virtual bool GetCompositionTextRange(gfx::Range* range) const OVERRIDE;
+ virtual bool GetSelectionRange(gfx::Range* range) const OVERRIDE;
virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE;
virtual bool DeleteRange(const gfx::Range& range) OVERRIDE;
virtual bool GetTextFromRange(const gfx::Range& range,
- string16* text) OVERRIDE;
+ base::string16* text) const OVERRIDE;
virtual void OnInputMethodChanged() OVERRIDE;
virtual bool ChangeTextDirectionAndLayoutAlignment(
base::i18n::TextDirection direction) OVERRIDE;
virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE;
virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE;
+ virtual void OnCandidateWindowShown() OVERRIDE;
+ virtual void OnCandidateWindowUpdated() OVERRIDE;
+ virtual void OnCandidateWindowHidden() OVERRIDE;
// Overridden from gfx::DisplayObserver:
virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE;
@@ -329,8 +337,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
virtual void OnRootWindowHostMoved(const aura::RootWindow* root,
const gfx::Point& new_origin) OVERRIDE;
- // FrameContainer implementation:
- virtual void ReleaseCurrentFrame() OVERRIDE;
+ // SoftwareFrameManagerClient implementation:
+ virtual void SoftwareFrameWasFreed(
+ uint32 output_surface_id, unsigned frame_id) OVERRIDE;
+ virtual void ReleaseReferencesToSoftwareFrame() OVERRIDE;
bool CanCopyToBitmap() const;
@@ -341,6 +351,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void UpdateConstrainedWindowRects(const std::vector<gfx::Rect>& rects);
#endif
+ // Method to indicate if this instance is shutting down or closing.
+ // TODO(shrikant): Discuss around to see if it makes sense to add this method
+ // as part of RenderWidgetHostView.
+ bool IsClosing() const { return in_shutdown_; };
+
protected:
friend class RenderWidgetHostView;
virtual ~RenderWidgetHostViewAura();
@@ -378,13 +393,13 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SwapNotifiesWindow);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
SkippedDelegatedFrames);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
+ DiscardDelegatedFrames);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SoftwareDPIChange);
class WindowObserver;
friend class WindowObserver;
-#if defined(OS_WIN)
- class TransientWindowObserver;
- friend class TransientWindowObserver;
-#endif
// Overridden from ImageTransportFactoryObserver:
virtual void OnLostResources() OVERRIDE;
@@ -404,6 +419,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void UpdateCursorIfOverSelf();
bool ShouldSkipFrame(gfx::Size size_in_dip) const;
+ // Set the bounds of the window and handle size changes. Assumes the caller
+ // has already adjusted the origin of |rect| to conform to whatever coordinate
+ // space is required by the aura::Window.
+ void InternalSetBounds(const gfx::Rect& rect);
+
// Lazily grab a resize lock if the aura window size doesn't match the current
// frame size, to give time to the renderer.
void MaybeCreateResizeLock();
@@ -423,7 +443,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// This method computes movementX/Y and keeps track of mouse location for
// mouse lock on all mouse move events.
- void ModifyEventMovementAndCoords(WebKit::WebMouseEvent* event);
+ void ModifyEventMovementAndCoords(blink::WebMouseEvent* event);
// Sends an IPC to the renderer process to communicate whether or not
// the mouse cursor is visible anywhere on the screen.
@@ -469,9 +489,16 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
scoped_ptr<cc::CopyOutputResult> result);
static void CopyFromCompositingSurfaceHasResultForVideo(
base::WeakPtr<RenderWidgetHostViewAura> rwhva,
+ scoped_refptr<OwnedMailbox> subscriber_texture,
scoped_refptr<media::VideoFrame> video_frame,
const base::Callback<void(bool)>& callback,
scoped_ptr<cc::CopyOutputResult> result);
+ static void CopyFromCompositingSurfaceFinishedForVideo(
+ base::WeakPtr<RenderWidgetHostViewAura> rwhva,
+ const base::Callback<void(bool)>& callback,
+ scoped_refptr<OwnedMailbox> subscriber_texture,
+ scoped_ptr<cc::SingleReleaseCallback> release_callback,
+ bool result);
ui::Compositor* GetCompositor() const;
@@ -482,10 +509,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void ApplyEventFilterForPopupExit(ui::MouseEvent* event);
// Converts |rect| from window coordinate to screen coordinate.
- gfx::Rect ConvertRectToScreen(const gfx::Rect& rect);
+ gfx::Rect ConvertRectToScreen(const gfx::Rect& rect) const;
// Converts |rect| from screen coordinate to window coordinate.
- gfx::Rect ConvertRectFromScreen(const gfx::Rect& rect);
+ gfx::Rect ConvertRectFromScreen(const gfx::Rect& rect) const;
typedef base::Callback<void(bool, const scoped_refptr<ui::Texture>&)>
BufferPresentedCallback;
@@ -515,12 +542,18 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
float frame_device_scale_factor,
const ui::LatencyInfo& latency_info);
void SendDelegatedFrameAck(uint32 output_surface_id);
+ void SendReturnedDelegatedResources(uint32 output_surface_id);
- void SwapSoftwareFrame(
- uint32 output_surface_id,
- scoped_ptr<cc::SoftwareFrameData> frame_data,
- float frame_device_scale_factor,
- const ui::LatencyInfo& latency_info);
+ // DelegatedFrameEvictorClient implementation.
+ virtual void EvictDelegatedFrame() OVERRIDE;
+
+ // cc::DelegatedFrameProviderClient implementation.
+ virtual void UnusedResourcesAreAvailable() OVERRIDE;
+
+ void SwapSoftwareFrame(uint32 output_surface_id,
+ scoped_ptr<cc::SoftwareFrameData> frame_data,
+ float frame_device_scale_factor,
+ const ui::LatencyInfo& latency_info);
void SendSoftwareFrameAck(uint32 output_surface_id);
void SendReclaimSoftwareFrames();
void ReleaseSoftwareFrame(uint32 output_surface_id,
@@ -530,16 +563,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
BrowserAccessibilityManager* GetOrCreateBrowserAccessibilityManager();
-#if defined(OS_WIN)
- // Sets the cutout rects from transient windows. These are rectangles that
- // windowed NPAPI plugins shouldn't paint in. Overwrites any previous cutout
- // rects.
- void UpdateTransientRects(const std::vector<gfx::Rect>& rects);
-
- // Updates the total list of cutout rects, which is the union of transient
- // windows and constrained windows.
- void UpdateCutoutRects();
-#endif
+ // Helper function to set keyboard focus to the main window.
+ void SetKeyboardFocus();
// The model object.
RenderWidgetHostImpl* host_;
@@ -553,6 +578,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// after requesting shutdown for another reason (e.g. Escape key).
bool in_shutdown_;
+ // True if in the process of handling a window bounds changed notification.
+ bool in_bounds_changed_;
+
// Is this a fullscreen view?
bool is_fullscreen_;
@@ -575,7 +603,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// The touch-event. Its touch-points are updated as necessary. A new
// touch-point is added from an ET_TOUCH_PRESSED event, and a touch-point is
// removed from the list on an ET_TOUCH_RELEASED event.
- WebKit::WebTouchEvent touch_event_;
+ blink::WebTouchEvent touch_event_;
// The current text input type.
ui::TextInputType text_input_type_;
@@ -593,22 +621,29 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Indicates if there is onging composition text.
bool has_composition_text_;
+ // Whether return characters should be passed on to the RenderWidgetHostImpl.
+ bool accept_return_character_;
+
// Current tooltip text.
- string16 tooltip_;
+ base::string16 tooltip_;
std::vector<base::Closure> on_compositing_did_commit_callbacks_;
// The current frontbuffer texture.
scoped_refptr<ui::Texture> current_surface_;
- // This holds the current software framebuffer.
- scoped_refptr<MemoryHolder> framebuffer_holder_;
+ // This holds the current software framebuffer, if any.
+ scoped_ptr<SoftwareFrameManager> software_frame_manager_;
// With delegated renderer, this is the last output surface, used to
// disambiguate resources with the same id coming from different output
// surfaces.
uint32 last_output_surface_id_;
+ // The number of delegated frame acks that are pending, to delay resource
+ // returns until the acks are sent.
+ int pending_delegated_ack_count_;
+
// The damage in the previously presented buffer.
SkRegion previous_damage_;
@@ -619,6 +654,14 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// skipped.
bool skipped_frames_;
+ // Holds delegated resources that have been given to a DelegatedFrameProvider,
+ // and gives back resources when they are no longer in use for return to the
+ // renderer.
+ scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection_;
+
+ // Provides delegated frame updates to the cc::DelegatedRendererLayer.
+ scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
+
// The size of the last frame that was swapped (even if we skipped it).
// Used to determine when the skipped_damage_ needs to be reset due to
// size changes between front- and backbuffer.
@@ -694,11 +737,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
PaintObserver* paint_observer_;
#if defined(OS_WIN)
- scoped_ptr<TransientWindowObserver> transient_observer_;
-
- // The list of rectangles from transient and constrained windows over this
- // view. Windowed NPAPI plugins shouldn't draw over them.
- std::vector<gfx::Rect> transient_rects_;
+ // The list of rectangles from constrained windows over this view. Windowed
+ // NPAPI plugins shouldn't draw over them.
std::vector<gfx::Rect> constrained_rects_;
typedef std::map<HWND, WebPluginGeometry> PluginWindowMoves;
@@ -713,6 +753,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Subscriber that listens to frame presentation events.
scoped_ptr<RenderWidgetHostViewFrameSubscriber> frame_subscriber_;
+ std::vector<scoped_refptr<OwnedMailbox> > idle_frame_subscriber_textures_;
// YUV readback pipeline.
scoped_ptr<content::ReadbackYUVInterface>
@@ -728,8 +769,17 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
uint32 output_surface_id;
unsigned frame_id;
};
- std::vector<ReleasedFrameInfo> released_software_frames_;
+ scoped_ptr<ReleasedFrameInfo> released_software_frame_;
+ scoped_ptr<DelegatedFrameEvictor> delegated_frame_evictor_;
+ base::WeakPtrFactory<RenderWidgetHostViewAura> weak_ptr_factory_;
+
+#if defined(OS_WIN)
+ // The dummy HWND which corresponds to the bounds of the web page. This is
+ // passed to windowless plugins like Flash/Silverlight, etc as the
+ // container window.
+ HWND plugin_parent_window_;
+#endif
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura);
};
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 824db746ceb..120956067df 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
@@ -25,6 +25,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/client/window_tree_client.h"
#include "ui/aura/env.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/root_window.h"
@@ -35,6 +37,8 @@
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/base/ui_base_types.h"
+#include "ui/compositor/compositor.h"
+#include "ui/compositor/test/test_context_factory.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
@@ -42,6 +46,36 @@ using testing::_;
namespace content {
namespace {
+
+// Simple screen position client to test coordinate system conversion.
+class TestScreenPositionClient
+ : public aura::client::ScreenPositionClient {
+ public:
+ TestScreenPositionClient() {}
+ virtual ~TestScreenPositionClient() {}
+
+ // aura::client::ScreenPositionClient overrides:
+ virtual void ConvertPointToScreen(const aura::Window* window,
+ gfx::Point* point) OVERRIDE {
+ point->Offset(-1, -1);
+ }
+
+ virtual void ConvertPointFromScreen(const aura::Window* window,
+ gfx::Point* point) OVERRIDE {
+ point->Offset(1, 1);
+ }
+
+ virtual void ConvertHostPointToScreen(aura::Window* window,
+ gfx::Point* point) OVERRIDE {
+ ConvertPointToScreen(window, point);
+ }
+
+ virtual void SetBounds(aura::Window* window,
+ const gfx::Rect& bounds,
+ const gfx::Display& display) OVERRIDE {
+ }
+};
+
class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
public:
MockRenderWidgetHostDelegate() {}
@@ -99,7 +133,7 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
}
void RunOnCompositingDidCommit() {
- OnCompositingDidCommit(window()->GetRootWindow()->compositor());
+ OnCompositingDidCommit(window()->GetDispatcher()->compositor());
}
// A lock that doesn't actually do anything to the compositor, and does not
@@ -120,26 +154,27 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
: browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {}
virtual void SetUp() {
- ImageTransportFactory::InitializeForUnitTests();
+ ImageTransportFactory::InitializeForUnitTests(
+ scoped_ptr<ui::ContextFactory>(new ui::TestContextFactory));
aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
aura_test_helper_->SetUp();
browser_context_.reset(new TestBrowserContext);
- MockRenderProcessHost* process_host =
- new MockRenderProcessHost(browser_context_.get());
+ process_host_ = new MockRenderProcessHost(browser_context_.get());
- sink_ = &process_host->sink();
+ sink_ = &process_host_->sink();
parent_host_ = new RenderWidgetHostImpl(
- &delegate_, process_host, MSG_ROUTING_NONE, false);
+ &delegate_, process_host_, MSG_ROUTING_NONE, false);
parent_view_ = static_cast<RenderWidgetHostViewAura*>(
RenderWidgetHostView::CreateViewForWidget(parent_host_));
parent_view_->InitAsChild(NULL);
- parent_view_->GetNativeView()->SetDefaultParentByRootWindow(
- aura_test_helper_->root_window(), gfx::Rect());
+ aura::client::ParentWindowWithContext(parent_view_->GetNativeView(),
+ aura_test_helper_->root_window(),
+ gfx::Rect());
widget_host_ = new RenderWidgetHostImpl(
- &delegate_, process_host, MSG_ROUTING_NONE, false);
+ &delegate_, process_host_, MSG_ROUTING_NONE, false);
widget_host_->Init();
widget_host_->OnMessageReceived(
ViewHostMsg_DidActivateAcceleratedCompositing(0, true));
@@ -148,6 +183,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
virtual void TearDown() {
sink_ = NULL;
+ process_host_ = NULL;
if (view_)
view_->Destroy();
delete widget_host_;
@@ -169,6 +205,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
scoped_ptr<BrowserContext> browser_context_;
MockRenderWidgetHostDelegate delegate_;
+ MockRenderProcessHost* process_host_;
// Tests should set these to NULL if they've already triggered their
// destruction.
@@ -189,7 +226,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
// A layout manager that always resizes a child to the root window size.
class FullscreenLayoutManager : public aura::LayoutManager {
public:
- explicit FullscreenLayoutManager(aura::RootWindow* owner)
+ explicit FullscreenLayoutManager(aura::Window* owner)
: owner_(owner) {}
virtual ~FullscreenLayoutManager() {}
@@ -216,7 +253,7 @@ class FullscreenLayoutManager : public aura::LayoutManager {
}
private:
- aura::RootWindow* owner_;
+ aura::Window* owner_;
DISALLOW_COPY_AND_ASSIGN(FullscreenLayoutManager);
};
@@ -244,6 +281,44 @@ TEST_F(RenderWidgetHostViewAuraTest, FocusFullscreen) {
EXPECT_TRUE(view_->ShouldActivate());
}
+// Checks that a popup is positioned correctly relative to its parent using
+// screen coordinates.
+TEST_F(RenderWidgetHostViewAuraTest, PositionChildPopup) {
+ TestScreenPositionClient screen_position_client;
+
+ aura::Window* window = parent_view_->GetNativeView();
+ aura::Window* root = window->GetRootWindow();
+ aura::client::SetScreenPositionClient(root, &screen_position_client);
+
+ parent_view_->SetBounds(gfx::Rect(10, 10, 800, 600));
+ gfx::Rect bounds_in_screen = parent_view_->GetViewBounds();
+ int horiz = bounds_in_screen.width() / 4;
+ int vert = bounds_in_screen.height() / 4;
+ bounds_in_screen.Inset(horiz, vert);
+
+ // Verify that when the popup is initialized for the first time, it correctly
+ // treats the input bounds as screen coordinates.
+ view_->InitAsPopup(parent_view_, bounds_in_screen);
+
+ gfx::Rect final_bounds_in_screen = view_->GetViewBounds();
+ EXPECT_EQ(final_bounds_in_screen.ToString(), bounds_in_screen.ToString());
+
+ // Verify that directly setting the bounds via SetBounds() treats the input
+ // as screen coordinates.
+ bounds_in_screen = gfx::Rect(60, 60, 100, 100);
+ view_->SetBounds(bounds_in_screen);
+ final_bounds_in_screen = view_->GetViewBounds();
+ EXPECT_EQ(final_bounds_in_screen.ToString(), bounds_in_screen.ToString());
+
+ // Verify that setting the size does not alter the origin.
+ gfx::Point original_origin = window->bounds().origin();
+ view_->SetSize(gfx::Size(120, 120));
+ gfx::Point new_origin = window->bounds().origin();
+ EXPECT_EQ(original_origin.ToString(), new_origin.ToString());
+
+ aura::client::SetScreenPositionClient(root, NULL);
+}
+
// Checks that a fullscreen view is destroyed when it loses the focus.
TEST_F(RenderWidgetHostViewAuraTest, DestroyFullscreenOnBlur) {
view_->InitAsFullscreen(parent_view_);
@@ -341,21 +416,21 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) {
view_->OnTouchEvent(&press);
EXPECT_FALSE(press.handled());
- EXPECT_EQ(WebKit::WebInputEvent::TouchStart, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type);
EXPECT_EQ(1U, view_->touch_event_.touchesLength);
- EXPECT_EQ(WebKit::WebTouchPoint::StatePressed,
+ EXPECT_EQ(blink::WebTouchPoint::StatePressed,
view_->touch_event_.touches[0].state);
view_->OnTouchEvent(&move);
EXPECT_FALSE(move.handled());
- EXPECT_EQ(WebKit::WebInputEvent::TouchMove, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type);
EXPECT_EQ(1U, view_->touch_event_.touchesLength);
- EXPECT_EQ(WebKit::WebTouchPoint::StateMoved,
+ EXPECT_EQ(blink::WebTouchPoint::StateMoved,
view_->touch_event_.touches[0].state);
view_->OnTouchEvent(&release);
EXPECT_FALSE(release.handled());
- EXPECT_EQ(WebKit::WebInputEvent::TouchEnd, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type);
EXPECT_EQ(0U, view_->touch_event_.touchesLength);
// Now install some touch-event handlers and do the same steps. The touch
@@ -366,29 +441,29 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) {
view_->OnTouchEvent(&press);
EXPECT_TRUE(press.stopped_propagation());
- EXPECT_EQ(WebKit::WebInputEvent::TouchStart, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type);
EXPECT_EQ(1U, view_->touch_event_.touchesLength);
- EXPECT_EQ(WebKit::WebTouchPoint::StatePressed,
+ EXPECT_EQ(blink::WebTouchPoint::StatePressed,
view_->touch_event_.touches[0].state);
view_->OnTouchEvent(&move);
EXPECT_TRUE(move.stopped_propagation());
- EXPECT_EQ(WebKit::WebInputEvent::TouchMove, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type);
EXPECT_EQ(1U, view_->touch_event_.touchesLength);
- EXPECT_EQ(WebKit::WebTouchPoint::StateMoved,
+ EXPECT_EQ(blink::WebTouchPoint::StateMoved,
view_->touch_event_.touches[0].state);
view_->OnTouchEvent(&release);
EXPECT_TRUE(release.stopped_propagation());
- EXPECT_EQ(WebKit::WebInputEvent::TouchEnd, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type);
EXPECT_EQ(0U, view_->touch_event_.touchesLength);
// Now start a touch event, and remove the event-handlers before the release.
view_->OnTouchEvent(&press);
EXPECT_TRUE(press.stopped_propagation());
- EXPECT_EQ(WebKit::WebInputEvent::TouchStart, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type);
EXPECT_EQ(1U, view_->touch_event_.touchesLength);
- EXPECT_EQ(WebKit::WebTouchPoint::StatePressed,
+ EXPECT_EQ(blink::WebTouchPoint::StatePressed,
view_->touch_event_.touches[0].state);
widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
@@ -398,16 +473,16 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) {
base::Time::NowFromSystemTime() - base::Time());
view_->OnTouchEvent(&move2);
EXPECT_FALSE(move2.handled());
- EXPECT_EQ(WebKit::WebInputEvent::TouchMove, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type);
EXPECT_EQ(1U, view_->touch_event_.touchesLength);
- EXPECT_EQ(WebKit::WebTouchPoint::StateMoved,
+ EXPECT_EQ(blink::WebTouchPoint::StateMoved,
view_->touch_event_.touches[0].state);
ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(20, 20), 0,
base::Time::NowFromSystemTime() - base::Time());
view_->OnTouchEvent(&release2);
EXPECT_FALSE(release2.handled());
- EXPECT_EQ(WebKit::WebInputEvent::TouchEnd, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type);
EXPECT_EQ(0U, view_->touch_event_.touchesLength);
}
@@ -435,37 +510,39 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventSyncAsync) {
view_->OnTouchEvent(&press);
EXPECT_TRUE(press.stopped_propagation());
- EXPECT_EQ(WebKit::WebInputEvent::TouchStart, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type);
EXPECT_EQ(1U, view_->touch_event_.touchesLength);
- EXPECT_EQ(WebKit::WebTouchPoint::StatePressed,
+ EXPECT_EQ(blink::WebTouchPoint::StatePressed,
view_->touch_event_.touches[0].state);
view_->OnTouchEvent(&move);
EXPECT_TRUE(move.stopped_propagation());
- EXPECT_EQ(WebKit::WebInputEvent::TouchMove, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type);
EXPECT_EQ(1U, view_->touch_event_.touchesLength);
- EXPECT_EQ(WebKit::WebTouchPoint::StateMoved,
+ EXPECT_EQ(blink::WebTouchPoint::StateMoved,
view_->touch_event_.touches[0].state);
// Send the same move event. Since the point hasn't moved, it won't affect the
// queue. However, the view should consume the event.
view_->OnTouchEvent(&move);
EXPECT_TRUE(move.stopped_propagation());
- EXPECT_EQ(WebKit::WebInputEvent::TouchMove, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type);
EXPECT_EQ(1U, view_->touch_event_.touchesLength);
- EXPECT_EQ(WebKit::WebTouchPoint::StateMoved,
+ EXPECT_EQ(blink::WebTouchPoint::StateMoved,
view_->touch_event_.touches[0].state);
view_->OnTouchEvent(&release);
EXPECT_TRUE(release.stopped_propagation());
- EXPECT_EQ(WebKit::WebInputEvent::TouchEnd, view_->touch_event_.type);
+ EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type);
EXPECT_EQ(0U, view_->touch_event_.touchesLength);
}
TEST_F(RenderWidgetHostViewAuraTest, PhysicalBackingSizeWithScale) {
view_->InitAsChild(NULL);
- view_->GetNativeView()->SetDefaultParentByRootWindow(
- parent_view_->GetNativeView()->GetRootWindow(), gfx::Rect());
+ aura::client::ParentWindowWithContext(
+ view_->GetNativeView(),
+ parent_view_->GetNativeView()->GetRootWindow(),
+ gfx::Rect());
sink_->ClearMessages();
view_->SetSize(gfx::Size(100, 100));
EXPECT_EQ("100x100", view_->GetPhysicalBackingSize().ToString());
@@ -522,8 +599,10 @@ TEST_F(RenderWidgetHostViewAuraTest, PhysicalBackingSizeWithScale) {
// to the renderer at the correct times.
TEST_F(RenderWidgetHostViewAuraTest, CursorVisibilityChange) {
view_->InitAsChild(NULL);
- view_->GetNativeView()->SetDefaultParentByRootWindow(
- parent_view_->GetNativeView()->GetRootWindow(), gfx::Rect());
+ aura::client::ParentWindowWithContext(
+ view_->GetNativeView(),
+ parent_view_->GetNativeView()->GetRootWindow(),
+ gfx::Rect());
view_->SetSize(gfx::Size(100, 100));
aura::test::TestCursorClient cursor_client(
@@ -599,46 +678,6 @@ TEST_F(RenderWidgetHostViewAuraTest, CursorVisibilityChange) {
cursor_client.RemoveObserver(view_);
}
-// Resizing in fullscreen mode should send the up-to-date screen info.
-TEST_F(RenderWidgetHostViewAuraTest, FullscreenResize) {
- aura::RootWindow* root_window = aura_test_helper_->root_window();
- root_window->SetLayoutManager(new FullscreenLayoutManager(root_window));
- view_->InitAsFullscreen(parent_view_);
- view_->WasShown();
- widget_host_->ResetSizeAndRepaintPendingFlags();
- sink_->ClearMessages();
-
- // Call WasResized to flush the old screen info.
- view_->GetRenderWidgetHost()->WasResized();
- {
- // 0 is CreatingNew message.
- const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
- EXPECT_EQ("0,0 800x600",
- gfx::Rect(params.a.screen_info.availableRect).ToString());
- EXPECT_EQ("800x600", params.a.new_size.ToString());
- }
-
- widget_host_->ResetSizeAndRepaintPendingFlags();
- sink_->ClearMessages();
-
- // Make sure the corrent screen size is set along in the resize
- // request when the screen size has changed.
- aura_test_helper_->test_screen()->SetUIScale(0.5);
- EXPECT_EQ(1u, sink_->message_count());
- {
- const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
- EXPECT_EQ("0,0 1600x1200",
- gfx::Rect(params.a.screen_info.availableRect).ToString());
- EXPECT_EQ("1600x1200", params.a.new_size.ToString());
- }
-}
-
scoped_ptr<cc::CompositorFrame> MakeGLFrame(float scale_factor,
gfx::Size size,
gfx::Rect damage) {
@@ -684,14 +723,66 @@ scoped_ptr<cc::CompositorFrame> MakeDelegatedFrame(float scale_factor,
return frame.Pass();
}
+// Resizing in fullscreen mode should send the up-to-date screen info.
+TEST_F(RenderWidgetHostViewAuraTest, FullscreenResize) {
+ aura::Window* root_window = aura_test_helper_->root_window();
+ root_window->SetLayoutManager(new FullscreenLayoutManager(root_window));
+ view_->InitAsFullscreen(parent_view_);
+ view_->WasShown();
+ widget_host_->ResetSizeAndRepaintPendingFlags();
+ sink_->ClearMessages();
+
+ // Call WasResized to flush the old screen info.
+ view_->GetRenderWidgetHost()->WasResized();
+ {
+ // 0 is CreatingNew message.
+ const IPC::Message* msg = sink_->GetMessageAt(0);
+ EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
+ ViewMsg_Resize::Param params;
+ ViewMsg_Resize::Read(msg, &params);
+ EXPECT_EQ("0,0 800x600",
+ gfx::Rect(params.a.screen_info.availableRect).ToString());
+ EXPECT_EQ("800x600", params.a.new_size.ToString());
+ // Resizes are blocked until we swapped a frame of the correct size, and
+ // we've committed it.
+ view_->OnSwapCompositorFrame(
+ 0, MakeGLFrame(1.f, params.a.new_size, gfx::Rect(params.a.new_size)));
+ ui::DrawWaiterForTest::WaitForCommit(
+ root_window->GetDispatcher()->compositor());
+ }
+
+ widget_host_->ResetSizeAndRepaintPendingFlags();
+ sink_->ClearMessages();
+
+ // Make sure the corrent screen size is set along in the resize
+ // request when the screen size has changed.
+ aura_test_helper_->test_screen()->SetUIScale(0.5);
+ EXPECT_EQ(1u, sink_->message_count());
+ {
+ const IPC::Message* msg = sink_->GetMessageAt(0);
+ EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
+ ViewMsg_Resize::Param params;
+ ViewMsg_Resize::Read(msg, &params);
+ EXPECT_EQ("0,0 1600x1200",
+ gfx::Rect(params.a.screen_info.availableRect).ToString());
+ EXPECT_EQ("1600x1200", params.a.new_size.ToString());
+ view_->OnSwapCompositorFrame(
+ 0, MakeGLFrame(1.f, params.a.new_size, gfx::Rect(params.a.new_size)));
+ ui::DrawWaiterForTest::WaitForCommit(
+ root_window->GetDispatcher()->compositor());
+ }
+}
+
// Swapping a frame should notify the window.
TEST_F(RenderWidgetHostViewAuraTest, SwapNotifiesWindow) {
gfx::Size view_size(100, 100);
gfx::Rect view_rect(view_size);
view_->InitAsChild(NULL);
- view_->GetNativeView()->SetDefaultParentByRootWindow(
- parent_view_->GetNativeView()->GetRootWindow(), gfx::Rect());
+ aura::client::ParentWindowWithContext(
+ view_->GetNativeView(),
+ parent_view_->GetNativeView()->GetRootWindow(),
+ gfx::Rect());
view_->SetSize(view_size);
view_->WasShown();
@@ -778,8 +869,10 @@ TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
gfx::Size frame_size = view_rect.size();
view_->InitAsChild(NULL);
- view_->GetNativeView()->SetDefaultParentByRootWindow(
- parent_view_->GetNativeView()->GetRootWindow(), gfx::Rect());
+ aura::client::ParentWindowWithContext(
+ view_->GetNativeView(),
+ parent_view_->GetNativeView()->GetRootWindow(),
+ gfx::Rect());
view_->SetSize(view_rect.size());
MockWindowObserver observer;
@@ -844,4 +937,178 @@ TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
view_->window_->RemoveObserver(&observer);
}
+TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
+ gfx::Rect view_rect(100, 100);
+ gfx::Size frame_size = view_rect.size();
+
+ view_->InitAsChild(NULL);
+ aura::client::ParentWindowWithContext(
+ view_->GetNativeView(),
+ parent_view_->GetNativeView()->GetRootWindow(),
+ gfx::Rect());
+ view_->SetSize(view_rect.size());
+
+ MockWindowObserver observer;
+ view_->window_->AddObserver(&observer);
+
+ // Swap a frame.
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(
+ 0, MakeDelegatedFrame(1.f, frame_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ // Swap a frame with a different surface id.
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(
+ 1, MakeDelegatedFrame(1.f, frame_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ // Swap an empty frame, with a different surface id.
+ view_->OnSwapCompositorFrame(
+ 2, MakeDelegatedFrame(1.f, gfx::Size(), gfx::Rect()));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ // Swap another frame, with a different surface id.
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(3,
+ MakeDelegatedFrame(1.f, frame_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ view_->RunOnCompositingDidCommit();
+
+ view_->window_->RemoveObserver(&observer);
+}
+
+TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames) {
+ size_t max_renderer_frames =
+ RendererFrameManager::GetInstance()->max_number_of_saved_frames();
+ ASSERT_LE(2u, max_renderer_frames);
+ size_t renderer_count = max_renderer_frames + 1;
+ gfx::Rect view_rect(100, 100);
+ gfx::Size frame_size = view_rect.size();
+
+ scoped_ptr<RenderWidgetHostImpl * []> hosts(
+ new RenderWidgetHostImpl* [renderer_count]);
+ scoped_ptr<FakeRenderWidgetHostViewAura * []> views(
+ new FakeRenderWidgetHostViewAura* [renderer_count]);
+
+ // Create a bunch of renderers.
+ for (size_t i = 0; i < renderer_count; ++i) {
+ hosts[i] = new RenderWidgetHostImpl(
+ &delegate_, process_host_, MSG_ROUTING_NONE, false);
+ hosts[i]->Init();
+ hosts[i]->OnMessageReceived(
+ ViewHostMsg_DidActivateAcceleratedCompositing(0, true));
+ views[i] = new FakeRenderWidgetHostViewAura(hosts[i]);
+ views[i]->InitAsChild(NULL);
+ aura::client::ParentWindowWithContext(
+ views[i]->GetNativeView(),
+ parent_view_->GetNativeView()->GetRootWindow(),
+ gfx::Rect());
+ views[i]->SetSize(view_rect.size());
+ }
+
+ // Make each renderer visible, and swap a frame on it, then make it invisible.
+ for (size_t i = 0; i < renderer_count; ++i) {
+ views[i]->WasShown();
+ views[i]->OnSwapCompositorFrame(
+ 1, MakeDelegatedFrame(1.f, frame_size, view_rect));
+ EXPECT_TRUE(views[i]->frame_provider_);
+ views[i]->WasHidden();
+ }
+
+ // There should be max_renderer_frames with a frame in it, and one without it.
+ // Since the logic is LRU eviction, the first one should be without.
+ EXPECT_FALSE(views[0]->frame_provider_);
+ for (size_t i = 1; i < renderer_count; ++i)
+ EXPECT_TRUE(views[i]->frame_provider_);
+
+ // LRU renderer is [0], make it visible, it shouldn't evict anything yet.
+ views[0]->WasShown();
+ EXPECT_FALSE(views[0]->frame_provider_);
+ EXPECT_TRUE(views[1]->frame_provider_);
+
+ // Swap a frame on it, it should evict the next LRU [1].
+ views[0]->OnSwapCompositorFrame(
+ 1, MakeDelegatedFrame(1.f, frame_size, view_rect));
+ EXPECT_TRUE(views[0]->frame_provider_);
+ EXPECT_FALSE(views[1]->frame_provider_);
+ views[0]->WasHidden();
+
+ // LRU renderer is [1], still hidden. Swap a frame on it, it should evict
+ // the next LRU [2].
+ views[1]->OnSwapCompositorFrame(
+ 1, MakeDelegatedFrame(1.f, frame_size, view_rect));
+ EXPECT_TRUE(views[0]->frame_provider_);
+ EXPECT_TRUE(views[1]->frame_provider_);
+ EXPECT_FALSE(views[2]->frame_provider_);
+ for (size_t i = 3; i < renderer_count; ++i)
+ EXPECT_TRUE(views[i]->frame_provider_);
+
+ // Make all renderers but [0] visible and swap a frame on them, keep [0]
+ // hidden, it becomes the LRU.
+ for (size_t i = 1; i < renderer_count; ++i) {
+ views[i]->WasShown();
+ views[i]->OnSwapCompositorFrame(
+ 1, MakeDelegatedFrame(1.f, frame_size, view_rect));
+ EXPECT_TRUE(views[i]->frame_provider_);
+ }
+ EXPECT_FALSE(views[0]->frame_provider_);
+
+ // Swap a frame on [0], it should be evicted immediately.
+ views[0]->OnSwapCompositorFrame(
+ 1, MakeDelegatedFrame(1.f, frame_size, view_rect));
+ EXPECT_FALSE(views[0]->frame_provider_);
+
+ // Make [0] visible, and swap a frame on it. Nothing should be evicted
+ // although we're above the limit.
+ views[0]->WasShown();
+ views[0]->OnSwapCompositorFrame(
+ 1, MakeDelegatedFrame(1.f, frame_size, view_rect));
+ for (size_t i = 0; i < renderer_count; ++i)
+ EXPECT_TRUE(views[i]->frame_provider_);
+
+ // Make [0] hidden, it should evict its frame.
+ views[0]->WasHidden();
+ EXPECT_FALSE(views[0]->frame_provider_);
+
+ for (size_t i = 0; i < renderer_count; ++i) {
+ views[i]->Destroy();
+ delete hosts[i];
+ }
+}
+
+TEST_F(RenderWidgetHostViewAuraTest, SoftwareDPIChange) {
+ gfx::Rect view_rect(100, 100);
+ gfx::Size frame_size(100, 100);
+
+ view_->InitAsChild(NULL);
+ aura::client::ParentWindowWithContext(
+ view_->GetNativeView(),
+ parent_view_->GetNativeView()->GetRootWindow(),
+ gfx::Rect());
+ view_->SetSize(view_rect.size());
+ view_->WasShown();
+
+ // With a 1x DPI UI and 1x DPI Renderer.
+ view_->OnSwapCompositorFrame(
+ 1, MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)));
+
+ // Save the frame provider.
+ scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
+ view_->frame_provider_;
+
+ // This frame will have the same number of physical pixels, but has a new
+ // scale on it.
+ view_->OnSwapCompositorFrame(
+ 1, MakeDelegatedFrame(2.f, frame_size, gfx::Rect(frame_size)));
+
+ // When we get a new frame with the same frame size in physical pixels, but a
+ // different scale, we should generate a new frame provider, as the final
+ // result will need to be scaled differently to the screen.
+ EXPECT_NE(frame_provider.get(), view_->frame_provider_.get());
+}
+
} // 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 57181031f22..8347b6d57fa 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
@@ -7,12 +7,11 @@
#include "base/logging.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
-#include "content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h"
+#include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
-#include "content/port/browser/synthetic_gesture.h"
-#include "third_party/WebKit/public/web/WebScreenInfo.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size_conversions.h"
@@ -119,7 +118,7 @@ LRESULT CALLBACK PluginWrapperWindowProc(HWND window, unsigned int message,
bool IsPluginWrapperWindow(HWND window) {
return gfx::GetClassNameW(window) ==
- string16(kWrapperNativeWindowClassName);
+ base::string16(kWrapperNativeWindowClassName);
}
// Create an intermediate window between the given HWND and its parent.
@@ -377,8 +376,15 @@ void RenderWidgetHostViewBase::DetachPluginsHelper(HWND parent) {
#endif // OS_WIN
+namespace {
+
+// How many microseconds apart input events should be flushed.
+const int kFlushInputRateInUs = 16666;
+
+}
+
RenderWidgetHostViewBase::RenderWidgetHostViewBase()
- : popup_type_(WebKit::WebPopupTypeNone),
+ : popup_type_(blink::WebPopupTypeNone),
mouse_locked_(false),
showing_context_menu_(false),
selection_text_offset_(0),
@@ -415,7 +421,7 @@ float RenderWidgetHostViewBase::GetOverdrawBottomHeight() const {
return 0.f;
}
-void RenderWidgetHostViewBase::SelectionChanged(const string16& text,
+void RenderWidgetHostViewBase::SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) {
selection_text_ = text;
@@ -433,9 +439,9 @@ void RenderWidgetHostViewBase::SetShowingContextMenu(bool showing) {
showing_context_menu_ = showing;
}
-string16 RenderWidgetHostViewBase::GetSelectedText() const {
+base::string16 RenderWidgetHostViewBase::GetSelectedText() const {
if (!selection_range_.IsValid())
- return string16();
+ return base::string16();
return selection_text_.substr(
selection_range_.GetMin() - selection_text_offset_,
selection_range_.length());
@@ -446,24 +452,39 @@ bool RenderWidgetHostViewBase::IsMouseLocked() {
}
void RenderWidgetHostViewBase::UnhandledWheelEvent(
- const WebKit::WebMouseWheelEvent& event) {
+ const blink::WebMouseWheelEvent& event) {
// Most implementations don't need to do anything here.
}
InputEventAckState RenderWidgetHostViewBase::FilterInputEvent(
- const WebKit::WebInputEvent& input_event) {
+ const blink::WebInputEvent& input_event) {
// By default, input events are simply forwarded to the renderer.
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
+void RenderWidgetHostViewBase::OnDidFlushInput() {
+ // The notification can safely be ignored by most implementations.
+}
+
+void RenderWidgetHostViewBase::OnSetNeedsFlushInput() {
+ if (flush_input_timer_.IsRunning())
+ return;
+
+ flush_input_timer_.Start(
+ FROM_HERE,
+ base::TimeDelta::FromMicroseconds(kFlushInputRateInUs),
+ this,
+ &RenderWidgetHostViewBase::FlushInput);
+}
+
void RenderWidgetHostViewBase::GestureEventAck(int gesture_event_type,
InputEventAckState ack_result) {}
-void RenderWidgetHostViewBase::SetPopupType(WebKit::WebPopupType popup_type) {
+void RenderWidgetHostViewBase::SetPopupType(blink::WebPopupType popup_type) {
popup_type_ = popup_type;
}
-WebKit::WebPopupType RenderWidgetHostViewBase::GetPopupType() {
+blink::WebPopupType RenderWidgetHostViewBase::GetPopupType() {
return popup_type_;
}
@@ -501,25 +522,18 @@ bool RenderWidgetHostViewBase::HasDisplayPropertyChanged(gfx::NativeView view) {
return true;
}
-SyntheticGesture* RenderWidgetHostViewBase::CreateSmoothScrollGesture(
- bool scroll_down, int pixels_to_scroll, int mouse_event_x,
- int mouse_event_y) {
- return new BasicMouseWheelSmoothScrollGesture(scroll_down, pixels_to_scroll,
- mouse_event_x, mouse_event_y);
-}
-
-SyntheticGesture* RenderWidgetHostViewBase::CreatePinchGesture(
- bool zoom_in, int pixels_to_move, int anchor_x,
- int anchor_y) {
- // There is no generic implementation for pinch gestures.
- NOTIMPLEMENTED();
- return NULL;
-}
-
void RenderWidgetHostViewBase::ProcessAckedTouchEvent(
const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
}
+scoped_ptr<SyntheticGestureTarget>
+RenderWidgetHostViewBase::CreateSyntheticGestureTarget() {
+ RenderWidgetHostImpl* host =
+ RenderWidgetHostImpl::From(GetRenderWidgetHost());
+ return scoped_ptr<SyntheticGestureTarget>(
+ new SyntheticGestureTargetBase(host));
+}
+
// Platform implementation should override this method to allow frame
// subscription. Frame subscriber is set to RenderProcessHost, which is
// platform independent. It should be set to the specific presenter on each
@@ -569,4 +583,13 @@ void RenderWidgetHostViewBase::DidReceiveRendererFrame() {
++renderer_frame_number_;
}
+void RenderWidgetHostViewBase::FlushInput() {
+ RenderWidgetHostImpl* impl = NULL;
+ if (GetRenderWidgetHost())
+ impl = RenderWidgetHostImpl::From(GetRenderWidgetHost());
+ if (!impl)
+ return;
+ impl->FlushInput();
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.h b/chromium/content/browser/renderer_host/render_widget_host_view_base.h
index 0472153b275..eadf92b87d2 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base.h
@@ -18,6 +18,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/callback_forward.h"
+#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "content/port/browser/render_widget_host_view_port.h"
#include "ui/gfx/native_widget_types.h"
@@ -46,7 +47,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// RenderWidgetHostViewPort implementation.
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void SelectionChanged(const string16& text,
+ virtual void SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) OVERRIDE;
virtual void SetBackground(const SkBitmap& background) OVERRIDE;
@@ -55,26 +56,24 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual float GetOverdrawBottomHeight() const OVERRIDE;
virtual bool IsShowingContextMenu() const OVERRIDE;
virtual void SetShowingContextMenu(bool showing_menu) OVERRIDE;
- virtual string16 GetSelectedText() const OVERRIDE;
+ virtual base::string16 GetSelectedText() const OVERRIDE;
virtual bool IsMouseLocked() OVERRIDE;
virtual void UnhandledWheelEvent(
- const WebKit::WebMouseWheelEvent& event) OVERRIDE;
+ const blink::WebMouseWheelEvent& event) OVERRIDE;
virtual InputEventAckState FilterInputEvent(
- const WebKit::WebInputEvent& input_event) OVERRIDE;
+ const blink::WebInputEvent& input_event) OVERRIDE;
+ virtual void OnSetNeedsFlushInput() OVERRIDE;
+ virtual void OnDidFlushInput() OVERRIDE;
virtual void GestureEventAck(int gesture_event_type,
InputEventAckState ack_result) OVERRIDE;
- virtual void SetPopupType(WebKit::WebPopupType popup_type) OVERRIDE;
- virtual WebKit::WebPopupType GetPopupType() OVERRIDE;
+ virtual void SetPopupType(blink::WebPopupType popup_type) OVERRIDE;
+ virtual blink::WebPopupType GetPopupType() OVERRIDE;
virtual BrowserAccessibilityManager*
GetBrowserAccessibilityManager() const OVERRIDE;
virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) OVERRIDE;
- virtual SyntheticGesture* CreateSmoothScrollGesture(
- bool scroll_down, int pixels_to_scroll, int mouse_event_x,
- int mouse_event_y) OVERRIDE;
- virtual SyntheticGesture* CreatePinchGesture(
- bool zoom_in, int pixels_to_move, int anchor_x,
- int anchor_y) OVERRIDE;
+ virtual scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
+ OVERRIDE;
virtual bool CanSubscribeFrame() const OVERRIDE;
virtual void BeginFrameSubscription(
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
@@ -82,6 +81,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual void OnSwapCompositorFrame(
uint32 output_surface_id,
scoped_ptr<cc::CompositorFrame> frame) OVERRIDE {}
+ virtual void ResizeCompositingSurface(const gfx::Size&) OVERRIDE {}
virtual void OnOverscrolled(gfx::Vector2dF accumulated_overscroll,
gfx::Vector2dF current_fling_velocity) OVERRIDE;
virtual uint32 RendererFrameNumber() OVERRIDE;
@@ -123,7 +123,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// Whether this view is a popup and what kind of popup it is (select,
// autofill...).
- WebKit::WebPopupType popup_type_;
+ blink::WebPopupType popup_type_;
// A custom background to paint behind the web content. This will be tiled
// horizontally. Can be null, in which case we fall back to painting white.
@@ -140,7 +140,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
bool showing_context_menu_;
// A buffer containing the text inside and around the current selection range.
- string16 selection_text_;
+ base::string16 selection_text_;
// The offset of the text stored in |selection_text_| relative to the start of
// the web page.
@@ -154,6 +154,8 @@ protected:
float current_device_scale_factor_;
private:
+ void FlushInput();
+
// Manager of the tree representation of the WebKit render tree.
scoped_ptr<BrowserAccessibilityManager> browser_accessibility_manager_;
@@ -161,6 +163,8 @@ protected:
uint32 renderer_frame_number_;
+ base::OneShotTimer<RenderWidgetHostViewBase> flush_input_timer_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewBase);
};
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 0fe376e65b3..60172d38635 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -12,6 +12,7 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
#include "content/port/browser/render_widget_host_view_port.h"
+#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
@@ -57,7 +58,7 @@ namespace {
// Convenience macro: Short-circuit a pass for platforms where setting up
// high-DPI fails.
#define PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(factor) \
- if (ui::GetScaleFactorScale( \
+ if (ui::GetImageScale( \
GetScaleFactorForView(GetRenderWidgetHostViewPort())) != factor) { \
LOG(WARNING) << "Blindly passing this test: failed to set up " \
"scale factor: " << factor; \
@@ -343,14 +344,6 @@ class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
// is enabled.
IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
CopyFromBackingStore) {
- // Disable the test for WinXP. See http://crbug/294116.
-#if defined(OS_WIN)
- if (base::win::GetVersion() < base::win::VERSION_VISTA) {
- LOG(WARNING) << "Test disabled due to unknown bug on WinXP.";
- return;
- }
-#endif
-
RunBasicCopyFromBackingStoreTest();
}
@@ -430,14 +423,6 @@ IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest,
// until at least one DeliverFrameCallback has been invoked.
IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
FrameSubscriberTest) {
- // Disable the test for WinXP. See http://crbug/294116.
-#if defined(OS_WIN)
- if (base::win::GetVersion() < base::win::VERSION_VISTA) {
- LOG(WARNING) << "Test disabled due to unknown bug on WinXP.";
- return;
- }
-#endif
-
SET_UP_SURFACE_OR_PASS_TEST(NULL);
RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
if (!view->CanSubscribeFrame()) {
@@ -463,14 +448,6 @@ IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest,
// Test that we can copy twice from an accelerated composited page.
IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest, CopyTwice) {
- // Disable the test for WinXP. See http://crbug/294116.
-#if defined(OS_WIN)
- if (base::win::GetVersion() < base::win::VERSION_VISTA) {
- LOG(WARNING) << "Test disabled due to unknown bug on WinXP.";
- return;
- }
-#endif
-
SET_UP_SURFACE_OR_PASS_TEST(NULL);
RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
if (!view->CanCopyToVideoFrame()) {
@@ -590,9 +567,9 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config,
video_frame->visible_rect().width(),
- video_frame->visible_rect().height());
+ video_frame->visible_rect().height(),
+ 0, kOpaque_SkAlphaType);
bitmap.allocPixels();
- bitmap.setIsOpaque(true);
SkBitmapDevice device(bitmap);
SkCanvas canvas(&device);
@@ -671,6 +648,20 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
return;
RenderWidgetHostViewPort* rwhvp = GetRenderWidgetHostViewPort();
+ if (video_frame && !rwhvp->CanCopyToVideoFrame()) {
+ // This should only happen on Mac when using the software compositor.
+ // Otherwise, raise an error. This can be removed when Mac is moved to a
+ // browser compositor.
+ // http://crbug.com/314190
+#if defined(OS_MACOSX)
+ if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL)) {
+ LOG(WARNING) << ("Blindly passing this test because copying to "
+ "video frames is not supported on this platform.");
+ return;
+ }
+#endif
+ NOTREACHED();
+ }
// The page is loaded in the renderer, wait for a new frame to arrive.
uint32 frame = rwhvp->RendererFrameNumber();
@@ -708,6 +699,17 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
video_frame,
callback);
} else {
+#if defined(USE_AURA)
+ if (!content::GpuDataManager::GetInstance()
+ ->CanUseGpuBrowserCompositor()) {
+ // Skia rendering can cause color differences, particularly in the
+ // middle two columns.
+ SetAllowableError(2);
+ SetExcludeRect(
+ gfx::Rect(output_size.width() / 2 - 1, 0, 2, output_size.height()));
+ }
+#endif
+
base::Callback<void(bool, const SkBitmap&)> callback =
base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
CopyFromCompositingSurfaceCallback,
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_gtk.cc b/chromium/content/browser/renderer_host/render_widget_host_view_gtk.cc
index 61512ef7506..e50bd045652 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -39,8 +39,8 @@
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/common/content_switches.h"
#include "skia/ext/platform_canvas.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "third_party/WebKit/public/web/WebScreenInfo.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/x/active_window_watcher_x.h"
#include "ui/base/x/x11_util.h"
@@ -50,8 +50,8 @@
#include "ui/gfx/text_elider.h"
#include "webkit/common/cursors/webcursor_gtk_data.h"
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebScreenInfo;
+using blink::WebMouseWheelEvent;
+using blink::WebScreenInfo;
namespace content {
namespace {
@@ -94,7 +94,7 @@ GdkCursor* GetMozSpinningCursor() {
return moz_spinning_cursor;
}
-bool MovedToPoint(const WebKit::WebMouseEvent& mouse_event,
+bool MovedToPoint(const blink::WebMouseEvent& mouse_event,
const gfx::Point& center) {
return mouse_event.globalX == center.x() &&
mouse_event.globalY == center.y();
@@ -140,6 +140,8 @@ class RenderWidgetHostViewGtkWidget {
G_CALLBACK(OnRealize), host_view);
g_signal_connect(widget, "configure-event",
G_CALLBACK(OnConfigureEvent), host_view);
+ g_signal_connect(widget, "size-allocate",
+ G_CALLBACK(OnSizeAllocate), host_view);
g_signal_connect(widget, "key-press-event",
G_CALLBACK(OnKeyPressReleaseEvent), host_view);
g_signal_connect(widget, "key-release-event",
@@ -180,7 +182,7 @@ class RenderWidgetHostViewGtkWidget {
static gboolean OnExposeEvent(GtkWidget* widget,
GdkEventExpose* expose,
RenderWidgetHostViewGtk* host_view) {
- if (host_view->is_hidden_)
+ if (host_view->host_->is_hidden())
return FALSE;
const gfx::Rect damage_rect(expose->area);
host_view->Paint(damage_rect);
@@ -205,6 +207,14 @@ class RenderWidgetHostViewGtkWidget {
return FALSE;
}
+ static gboolean OnSizeAllocate(GtkWidget* widget,
+ GdkRectangle* allocation,
+ RenderWidgetHostViewGtk* host_view) {
+ if (!host_view->IsPopup() && !host_view->is_fullscreen_)
+ host_view->SetSize(gfx::Size(allocation->width, allocation->height));
+ return FALSE;
+ }
+
static gboolean OnKeyPressReleaseEvent(GtkWidget* widget,
GdkEventKey* event,
RenderWidgetHostViewGtk* host_view) {
@@ -375,7 +385,7 @@ class RenderWidgetHostViewGtkWidget {
host_view->ModifyEventForEdgeDragging(widget, event);
- WebKit::WebMouseEvent mouse_event = WebMouseEventBuilder::Build(event);
+ blink::WebMouseEvent mouse_event = WebMouseEventBuilder::Build(event);
if (host_view->mouse_locked_) {
gfx::Point center = host_view->GetWidgetCenter();
@@ -425,7 +435,7 @@ class RenderWidgetHostViewGtkWidget {
// additionally send this crossing event with the state indicating the
// button is down, it causes problems with drag and drop in WebKit.)
if (!(event->state & any_button_mask)) {
- WebKit::WebMouseEvent mouse_event = WebMouseEventBuilder::Build(event);
+ blink::WebMouseEvent mouse_event = WebMouseEventBuilder::Build(event);
host_view->ModifyEventMovementAndCoords(&mouse_event);
// When crossing out and back into a render view the movement values
// must represent the instantaneous movement of the mouse, not the jump
@@ -541,7 +551,6 @@ class RenderWidgetHostViewGtkWidget {
RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host)
: host_(RenderWidgetHostImpl::From(widget_host)),
about_to_validate_and_paint_(false),
- is_hidden_(host_->is_hidden()),
is_loading_(false),
parent_(NULL),
is_popup_first_mouse_release_(true),
@@ -681,25 +690,19 @@ RenderWidgetHost* RenderWidgetHostViewGtk::GetRenderWidgetHost() const {
}
void RenderWidgetHostViewGtk::WasShown() {
- if (!host_ || !is_hidden_)
+ if (!host_ || !host_->is_hidden())
return;
if (web_contents_switch_paint_time_.is_null())
web_contents_switch_paint_time_ = base::TimeTicks::Now();
- is_hidden_ = false;
host_->WasShown();
}
void RenderWidgetHostViewGtk::WasHidden() {
- if (!host_ || is_hidden_)
+ if (!host_ || host_->is_hidden())
return;
- // If we receive any more paint messages while we are hidden, we want to
- // ignore them so we don't re-allocate the backing store. We will paint
- // everything again when we become selected again.
- is_hidden_ = true;
-
// If we have a renderer, then inform it that we are being hidden so it can
// reduce its resource utilization.
host_->WasHidden();
@@ -852,7 +855,7 @@ void RenderWidgetHostViewGtk::DidUpdateBackingStore(
TRACE_EVENT0("ui::gtk", "RenderWidgetHostViewGtk::DidUpdateBackingStore");
software_latency_info_.MergeWith(latency_info);
- if (is_hidden_)
+ if (host_->is_hidden())
return;
// TODO(darin): Implement the equivalent of Win32's ScrollWindowEX. Can that
@@ -926,14 +929,15 @@ void RenderWidgetHostViewGtk::Destroy() {
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
-void RenderWidgetHostViewGtk::SetTooltipText(const string16& tooltip_text) {
+void RenderWidgetHostViewGtk::SetTooltipText(
+ const base::string16& tooltip_text) {
// Maximum number of characters we allow in a tooltip.
const int kMaxTooltipLength = 8 << 10;
// Clamp the tooltip length to kMaxTooltipLength so that we don't
// accidentally DOS the user with a mega tooltip (since GTK doesn't do
// this itself).
// I filed https://bugzilla.gnome.org/show_bug.cgi?id=604641 upstream.
- const string16 clamped_tooltip =
+ const base::string16 clamped_tooltip =
gfx::TruncateString(tooltip_text, kMaxTooltipLength);
if (clamped_tooltip.empty()) {
@@ -944,7 +948,7 @@ void RenderWidgetHostViewGtk::SetTooltipText(const string16& tooltip_text) {
}
}
-void RenderWidgetHostViewGtk::SelectionChanged(const string16& text,
+void RenderWidgetHostViewGtk::SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) {
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
@@ -960,10 +964,10 @@ void RenderWidgetHostViewGtk::SelectionChanged(const string16& text,
return;
}
- // Set the BUFFER_SELECTION to the ui::Clipboard.
+ // Set the CLIPBOARD_TYPE SELECTION to the ui::Clipboard.
ui::ScopedClipboardWriter clipboard_writer(
ui::Clipboard::GetForCurrentThread(),
- ui::Clipboard::BUFFER_SELECTION);
+ ui::CLIPBOARD_TYPE_SELECTION);
clipboard_writer.WriteText(text.substr(pos, n));
}
@@ -990,11 +994,11 @@ void RenderWidgetHostViewGtk::OnDestroy(GtkWidget* widget) {
}
bool RenderWidgetHostViewGtk::NeedsInputGrab() {
- return popup_type_ == WebKit::WebPopupTypeSelect;
+ return popup_type_ == blink::WebPopupTypeSelect;
}
bool RenderWidgetHostViewGtk::IsPopup() const {
- return popup_type_ != WebKit::WebPopupTypeNone;
+ return popup_type_ != blink::WebPopupTypeNone;
}
void RenderWidgetHostViewGtk::DoSharedInit() {
@@ -1060,6 +1064,10 @@ bool RenderWidgetHostViewGtk::CanCopyToVideoFrame() const {
return false;
}
+void RenderWidgetHostViewGtk::AcceleratedSurfaceInitialized(int host_id,
+ int route_id) {
+}
+
void RenderWidgetHostViewGtk::AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
int gpu_host_id) {
@@ -1067,7 +1075,7 @@ void RenderWidgetHostViewGtk::AcceleratedSurfaceBuffersSwapped(
ack_params.sync_point = 0;
RenderWidgetHostImpl::AcknowledgeBufferPresent(
params.route_id, gpu_host_id, ack_params);
- host_->FrameSwapped(params.latency_info);
+ RenderWidgetHostImpl::CompositorFrameDrawn(params.latency_info);
}
void RenderWidgetHostViewGtk::AcceleratedSurfacePostSubBuffer(
@@ -1077,7 +1085,7 @@ void RenderWidgetHostViewGtk::AcceleratedSurfacePostSubBuffer(
ack_params.sync_point = 0;
RenderWidgetHostImpl::AcknowledgeBufferPresent(
params.route_id, gpu_host_id, ack_params);
- host_->FrameSwapped(params.latency_info);
+ RenderWidgetHostImpl::CompositorFrameDrawn(params.latency_info);
}
void RenderWidgetHostViewGtk::AcceleratedSurfaceSuspend() {
@@ -1207,7 +1215,8 @@ void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) {
// recorded.
web_contents_switch_paint_time_ = base::TimeTicks();
}
- software_latency_info_.swap_timestamp = base::TimeTicks::HighResNow();
+ software_latency_info_.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
render_widget_host->FrameSwapped(software_latency_info_);
software_latency_info_.Clear();
} else {
@@ -1292,6 +1301,16 @@ gfx::GLSurfaceHandle RenderWidgetHostViewGtk::GetCompositingSurface() {
return gfx::GLSurfaceHandle(compositing_surface_, gfx::NATIVE_TRANSPORT);
}
+void RenderWidgetHostViewGtk::ResizeCompositingSurface(const gfx::Size& size) {
+ GtkWidget* widget = view_.get();
+ GdkWindow* window = gtk_widget_get_window(widget);
+ if (window) {
+ Display* display = GDK_WINDOW_XDISPLAY(window);
+ gdk_window_resize(window, size.width(), size.height());
+ XSync(display, False);
+ }
+}
+
bool RenderWidgetHostViewGtk::LockMouse() {
if (mouse_locked_)
return true;
@@ -1329,13 +1348,20 @@ bool RenderWidgetHostViewGtk::LockMouse() {
}
// Clear the tooltip window.
- SetTooltipText(string16());
+ SetTooltipText(base::string16());
// Ensure that the widget center location will be relevant for this mouse
// lock session. It is updated whenever the window geometry moves
// but may be out of date due to switching tabs.
MarkCachedWidgetCenterStale();
+ // Ensure that if we were previously warping the cursor to a specific point
+ // that we no longer track doing so when entering lock. It should be cleared
+ // by the cursor moving to the warp point, and this shouldn't be necessary.
+ // But, this is a small effort to ensure robustness in the event a warp isn't
+ // completed.
+ mouse_is_being_warped_to_unlocked_position_ = false;
+
return true;
}
@@ -1393,7 +1419,7 @@ bool RenderWidgetHostViewGtk::RetrieveSurrounding(std::string* text,
*text = base::UTF16ToUTF8AndAdjustOffset(
base::StringPiece16(selection_text_), &offset);
- if (offset == string16::npos) {
+ if (offset == base::string16::npos) {
NOTREACHED() << "Invalid offset in UTF16 string.";
return false;
}
@@ -1436,7 +1462,7 @@ gfx::Point RenderWidgetHostViewGtk::GetWidgetCenter() {
}
void RenderWidgetHostViewGtk::ModifyEventMovementAndCoords(
- WebKit::WebMouseEvent* event) {
+ blink::WebMouseEvent* event) {
// Movement is computed by taking the difference of the new cursor position
// and the previous. Under mouse lock the cursor will be warped back to the
// center so that we are not limited by clipping boundaries.
@@ -1466,7 +1492,7 @@ void RenderWidgetHostViewGtk::ModifyEventMovementAndCoords(
event->windowY = unlocked_mouse_position_.y();
event->globalX = unlocked_global_mouse_position_.x();
event->globalY = unlocked_global_mouse_position_.y();
- } else {
+ } else if (!mouse_is_being_warped_to_unlocked_position_) {
unlocked_mouse_position_.SetPoint(event->windowX, event->windowY);
unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_gtk.h b/chromium/content/browser/renderer_host/render_widget_host_view_gtk.h
index fc57a1a5aad..e01181ab4cc 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_gtk.h
@@ -93,8 +93,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
int error_code) OVERRIDE;
virtual void Destroy() OVERRIDE;
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {}
- virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
- virtual void SelectionChanged(const string16& text,
+ virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE;
+ virtual void SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
@@ -111,6 +111,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
const base::Callback<void(bool)>& callback) OVERRIDE;
virtual bool CanCopyToVideoFrame() const OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
+ virtual void AcceleratedSurfaceInitialized(int host_id,
+ int route_id) OVERRIDE;
virtual void AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
int gpu_host_id) OVERRIDE;
@@ -124,9 +126,10 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
bool has_horizontal_scrollbar) OVERRIDE;
virtual void SetScrollOffsetPinning(
bool is_pinned_to_left, bool is_pinned_to_right) OVERRIDE;
- virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE;
+ virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE;
virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE;
virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
+ virtual void ResizeCompositingSurface(const gfx::Size&) OVERRIDE;
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
virtual void OnAccessibilityEvents(
@@ -148,7 +151,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
// Mouse events always provide a movementX/Y which needs to be computed.
// Also, mouse lock requires knowledge of last unlocked cursor coordinates.
// State is stored on the host view to do this, and the mouse event modified.
- void ModifyEventMovementAndCoords(WebKit::WebMouseEvent* event);
+ void ModifyEventMovementAndCoords(blink::WebMouseEvent* event);
void Paint(const gfx::Rect&);
@@ -232,9 +235,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk
// This is the rectangle which we'll paint.
gfx::Rect invalid_rect_;
- // Whether or not this widget is hidden.
- bool is_hidden_;
-
// Whether we are currently loading.
bool is_loading_;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_guest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_guest.cc
index 05730b92545..bbe5c8b4b86 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_guest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_guest.cc
@@ -15,7 +15,7 @@
#include "content/common/webplugin_geometry.h"
#include "content/public/common/content_switches.h"
#include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/public/web/WebScreenInfo.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#if defined(OS_MACOSX)
#import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
@@ -29,19 +29,21 @@ namespace content {
namespace {
+#if defined(OS_WIN) || defined(USE_AURA)
bool ShouldSendPinchGesture() {
static bool pinch_allowed =
CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch);
return pinch_allowed;
}
-WebKit::WebGestureEvent CreateFlingCancelEvent(double time_stamp) {
- WebKit::WebGestureEvent gesture_event;
+blink::WebGestureEvent CreateFlingCancelEvent(double time_stamp) {
+ blink::WebGestureEvent gesture_event;
gesture_event.timeStampSeconds = time_stamp;
- gesture_event.type = WebKit::WebGestureEvent::GestureFlingCancel;
- gesture_event.sourceDevice = WebKit::WebGestureEvent::Touchscreen;
+ gesture_event.type = blink::WebGestureEvent::GestureFlingCancel;
+ gesture_event.sourceDevice = blink::WebGestureEvent::Touchscreen;
return gesture_event;
}
+#endif // defined(OS_WIN) || defined(USE_AURA)
} // namespace
@@ -51,15 +53,18 @@ RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
RenderWidgetHostView* platform_view)
: host_(RenderWidgetHostImpl::From(widget_host)),
guest_(guest),
- is_hidden_(host_->is_hidden()),
platform_view_(static_cast<RenderWidgetHostViewPort*>(platform_view)) {
#if defined(OS_WIN) || defined(USE_AURA)
- gesture_recognizer_.reset(ui::GestureRecognizer::Create(this));
+ gesture_recognizer_.reset(ui::GestureRecognizer::Create());
+ gesture_recognizer_->AddGestureEventHelper(this);
#endif // defined(OS_WIN) || defined(USE_AURA)
host_->SetView(this);
}
RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
+#if defined(OS_WIN) || defined(USE_AURA)
+ gesture_recognizer_->RemoveGestureEventHelper(this);
+#endif // defined(OS_WIN) || defined(USE_AURA)
}
RenderWidgetHost* RenderWidgetHostViewGuest::GetRenderWidgetHost() const {
@@ -74,17 +79,15 @@ void RenderWidgetHostViewGuest::WasShown() {
// first place: http://crbug.com/273089.
//
// |guest_| is NULL during test.
- if (!is_hidden_ || (guest_ && guest_->is_in_destruction()))
+ if ((guest_ && guest_->is_in_destruction()) || !host_->is_hidden())
return;
- is_hidden_ = false;
host_->WasShown();
}
void RenderWidgetHostViewGuest::WasHidden() {
// |guest_| is NULL during test.
- if (is_hidden_ || (guest_ && guest_->is_in_destruction()))
+ if ((guest_ && guest_->is_in_destruction()) || host_->is_hidden())
return;
- is_hidden_ = true;
host_->WasHidden();
}
@@ -135,7 +138,7 @@ void RenderWidgetHostViewGuest::Hide() {
}
bool RenderWidgetHostViewGuest::IsShowing() {
- return !is_hidden_;
+ return !host_->is_hidden();
}
gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
@@ -166,10 +169,15 @@ void RenderWidgetHostViewGuest::Destroy() {
platform_view_->Destroy();
}
-void RenderWidgetHostViewGuest::SetTooltipText(const string16& tooltip_text) {
+void RenderWidgetHostViewGuest::SetTooltipText(
+ const base::string16& tooltip_text) {
platform_view_->SetTooltipText(tooltip_text);
}
+void RenderWidgetHostViewGuest::AcceleratedSurfaceInitialized(int host_id,
+ int route_id) {
+}
+
void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
int gpu_host_id) {
@@ -251,7 +259,9 @@ gfx::NativeView RenderWidgetHostViewGuest::GetNativeView() const {
}
gfx::NativeViewId RenderWidgetHostViewGuest::GetNativeViewId() const {
- return guest_->GetEmbedderRenderWidgetHostView()->GetNativeViewId();
+ if (guest_->GetEmbedderRenderWidgetHostView())
+ return guest_->GetEmbedderRenderWidgetHostView()->GetNativeViewId();
+ return static_cast<gfx::NativeViewId>(NULL);
}
gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() {
@@ -291,19 +301,38 @@ void RenderWidgetHostViewGuest::TextInputTypeChanged(
ui::TextInputType type,
ui::TextInputMode input_mode,
bool can_compose_inline) {
- RenderWidgetHostViewPort::FromRWHV(
- guest_->GetEmbedderRenderWidgetHostView())->
- TextInputTypeChanged(type, input_mode, can_compose_inline);
+ RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
+ guest_->GetEmbedderRenderWidgetHostView());
+ if (!rwhv)
+ return;
+ // Forward the information to embedding RWHV.
+ rwhv->TextInputTypeChanged(type, input_mode, can_compose_inline);
}
void RenderWidgetHostViewGuest::ImeCancelComposition() {
- platform_view_->ImeCancelComposition();
+ RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
+ guest_->GetEmbedderRenderWidgetHostView());
+ if (!rwhv)
+ return;
+ // Forward the information to embedding RWHV.
+ rwhv->ImeCancelComposition();
}
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
+ RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
+ guest_->GetEmbedderRenderWidgetHostView());
+ if (!rwhv)
+ return;
+ std::vector<gfx::Rect> guest_character_bounds;
+ for (size_t i = 0; i < character_bounds.size(); ++i) {
+ gfx::Rect guest_rect = guest_->ToGuestRect(character_bounds[i]);
+ guest_character_bounds.push_back(guest_rect);
+ }
+ // Forward the information to embedding RWHV.
+ rwhv->ImeCompositionRangeChanged(range, guest_character_bounds);
}
#endif
@@ -315,15 +344,27 @@ void RenderWidgetHostViewGuest::DidUpdateBackingStore(
NOTREACHED();
}
-void RenderWidgetHostViewGuest::SelectionChanged(const string16& text,
+void RenderWidgetHostViewGuest::SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) {
- platform_view_->SelectionChanged(text, offset, range);
+ RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
+ guest_->GetEmbedderRenderWidgetHostView());
+ if (!rwhv)
+ return;
+ // Forward the information to embedding RWHV.
+ rwhv->SelectionChanged(text, offset, range);
}
void RenderWidgetHostViewGuest::SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) {
- platform_view_->SelectionBoundsChanged(params);
+ RenderWidgetHostViewPort* rwhv = RenderWidgetHostViewPort::FromRWHV(
+ guest_->GetEmbedderRenderWidgetHostView());
+ if (!rwhv)
+ return;
+ ViewHostMsg_SelectionBounds_Params guest_params(params);
+ guest_params.anchor_rect = guest_->ToGuestRect(params.anchor_rect);
+ guest_params.focus_rect = guest_->ToGuestRect(params.focus_rect);
+ rwhv->SelectionBoundsChanged(guest_params);
}
void RenderWidgetHostViewGuest::ScrollOffsetChanged() {
@@ -337,9 +378,10 @@ BackingStore* RenderWidgetHostViewGuest::AllocBackingStore(
void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
- const gfx::Size& /* dst_size */,
+ const gfx::Size& dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback) {
- callback.Run(false, SkBitmap());
+ CHECK(guest_);
+ guest_->CopyFromCompositingSurface(src_subrect, dst_size, callback);
}
void RenderWidgetHostViewGuest::CopyFromCompositingSurfaceToVideoFrame(
@@ -397,11 +439,12 @@ void RenderWidgetHostViewGuest::UnlockMouse() {
return platform_view_->UnlockMouse();
}
-void RenderWidgetHostViewGuest::GetScreenInfo(WebKit::WebScreenInfo* results) {
+void RenderWidgetHostViewGuest::GetScreenInfo(blink::WebScreenInfo* results) {
RenderWidgetHostViewPort* embedder_view =
RenderWidgetHostViewPort::FromRWHV(
guest_->GetEmbedderRenderWidgetHostView());
- embedder_view->GetScreenInfo(results);
+ if (embedder_view)
+ embedder_view->GetScreenInfo(results);
}
void RenderWidgetHostViewGuest::OnAccessibilityEvents(
@@ -499,6 +542,11 @@ void RenderWidgetHostViewGuest::WillWmDestroy() {
void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
gfx::NativeViewAccessible accessible_parent) {
}
+
+gfx::NativeViewId RenderWidgetHostViewGuest::GetParentForWindowlessPlugin()
+ const {
+ return NULL;
+}
#endif
void RenderWidgetHostViewGuest::DestroyGuestView() {
@@ -507,21 +555,26 @@ void RenderWidgetHostViewGuest::DestroyGuestView() {
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
-bool RenderWidgetHostViewGuest::DispatchLongPressGestureEvent(
+bool RenderWidgetHostViewGuest::CanDispatchToConsumer(
+ ui::GestureConsumer* consumer) {
+ CHECK_EQ(static_cast<RenderWidgetHostViewGuest*>(consumer), this);
+ return true;
+}
+
+void RenderWidgetHostViewGuest::DispatchPostponedGestureEvent(
ui::GestureEvent* event) {
- return ForwardGestureEventToRenderer(event);
+ ForwardGestureEventToRenderer(event);
}
-bool RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
+void RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
ui::TouchEvent* event) {
if (!host_)
- return false;
+ return;
- WebKit::WebTouchEvent cancel_event;
- cancel_event.type = WebKit::WebInputEvent::TouchCancel;
+ blink::WebTouchEvent cancel_event;
+ cancel_event.type = blink::WebInputEvent::TouchCancel;
cancel_event.timeStampSeconds = event->time_stamp().InSecondsF();
host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency());
- return true;
}
bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
@@ -539,7 +592,7 @@ bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
return true;
}
- WebKit::WebGestureEvent web_gesture =
+ blink::WebGestureEvent web_gesture =
MakeWebGestureEventFromUIEvent(*gesture);
const gfx::Point& client_point = gesture->location();
const gfx::Point& screen_point = gesture->location();
@@ -549,9 +602,9 @@ bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
web_gesture.globalX = screen_point.x();
web_gesture.globalY = screen_point.y();
- if (web_gesture.type == WebKit::WebGestureEvent::Undefined)
+ if (web_gesture.type == blink::WebGestureEvent::Undefined)
return false;
- if (web_gesture.type == WebKit::WebGestureEvent::GestureTapDown) {
+ if (web_gesture.type == blink::WebGestureEvent::GestureTapDown) {
host_->ForwardGestureEvent(
CreateFlingCancelEvent(gesture->time_stamp().InSecondsF()));
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_guest.h b/chromium/content/browser/renderer_host/render_widget_host_view_guest.h
index 82f2eab1bac..ac9fa0ee2cb 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_guest.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_guest.h
@@ -10,9 +10,9 @@
#include "base/memory/scoped_ptr.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
-#include "ui/base/gestures/gesture_recognizer.h"
-#include "ui/base/gestures/gesture_types.h"
#include "ui/events/event.h"
+#include "ui/events/gestures/gesture_recognizer.h"
+#include "ui/events/gestures/gesture_types.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/vector2d_f.h"
@@ -98,8 +98,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
int error_code) OVERRIDE;
virtual void Destroy() OVERRIDE;
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {}
- virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
- virtual void SelectionChanged(const string16& text,
+ virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE;
+ virtual void SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
@@ -116,6 +116,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
const base::Callback<void(bool)>& callback) OVERRIDE;
virtual bool CanCopyToVideoFrame() const OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
+ virtual void AcceleratedSurfaceInitialized(int host_id,
+ int route_id) OVERRIDE;
virtual void AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
int gpu_host_id) OVERRIDE;
@@ -141,7 +143,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
#endif // defined(OS_WIN) || defined(USE_AURA)
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
- virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE;
+ virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE;
virtual void OnAccessibilityEvents(
const std::vector<AccessibilityHostMsg_EventParams>&
params) OVERRIDE;
@@ -183,11 +185,13 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
#if defined(OS_WIN) && defined(USE_AURA)
virtual void SetParentNativeViewAccessible(
gfx::NativeViewAccessible accessible_parent) OVERRIDE;
+ virtual gfx::NativeViewId GetParentForWindowlessPlugin() const OVERRIDE;
#endif
// Overridden from ui::GestureEventHelper.
- virtual bool DispatchLongPressGestureEvent(ui::GestureEvent* event) OVERRIDE;
- virtual bool DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE;
+ virtual bool CanDispatchToConsumer(ui::GestureConsumer* consumer) OVERRIDE;
+ virtual void DispatchPostponedGestureEvent(ui::GestureEvent* event) OVERRIDE;
+ virtual void DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE;
protected:
friend class RenderWidgetHostView;
@@ -206,7 +210,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
RenderWidgetHostImpl* host_;
BrowserPluginGuest *guest_;
- bool is_hidden_;
gfx::Size size_;
// The platform view for this RenderWidgetHostView.
// RenderWidgetHostViewGuest mostly only cares about stuff related to
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc
index a112634b69d..b99743aa5ff 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc
@@ -8,11 +8,11 @@
#include "base/message_loop/message_loop.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
#include "content/common/view_messages.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
+#include "content/test/test_render_view_host.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
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 11b1d973a42..b6825b07ab5 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
@@ -18,6 +18,7 @@
#include "base/time/time.h"
#include "content/browser/accessibility/browser_accessibility_delegate_mac.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/renderer_host/software_frame_manager.h"
#include "content/common/edit_command.h"
#import "content/public/browser/render_widget_host_view_mac_base.h"
#include "ipc/ipc_sender.h"
@@ -107,13 +108,13 @@ class RenderWidgetHostViewMacEditCommandHelper;
NSRange selectedRange_;
// Text to be inserted which was generated by handling a key down event.
- string16 textToBeInserted_;
+ base::string16 textToBeInserted_;
// Marked text which was generated by handling a key down event.
- string16 markedText_;
+ base::string16 markedText_;
// Underline information of the |markedText_|.
- std::vector<WebKit::WebCompositionUnderline> underlines_;
+ std::vector<blink::WebCompositionUnderline> underlines_;
// Indicates if doCommandBySelector method receives any edit command when
// handling a key down event.
@@ -196,7 +197,8 @@ class RenderWidgetHostImpl;
//
// RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
- public IPC::Sender {
+ public IPC::Sender,
+ public SoftwareFrameManagerClient {
public:
virtual ~RenderWidgetHostViewMac();
@@ -262,8 +264,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
virtual void RenderProcessGone(base::TerminationStatus status,
int error_code) OVERRIDE;
virtual void Destroy() OVERRIDE;
- virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
- virtual void SelectionChanged(const string16& text,
+ virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE;
+ virtual void SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) OVERRIDE;
virtual void SelectionBoundsChanged(
@@ -283,7 +285,11 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
virtual void BeginFrameSubscription(
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
virtual void EndFrameSubscription() OVERRIDE;
+ virtual void OnSwapCompositorFrame(
+ uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
+ virtual void AcceleratedSurfaceInitialized(int host_id,
+ int route_id) OVERRIDE;
virtual void OnAccessibilityEvents(
const std::vector<AccessibilityHostMsg_EventParams>& params
) OVERRIDE;
@@ -300,7 +306,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
virtual void AcceleratedSurfaceRelease() OVERRIDE;
virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE;
virtual void AboutToWaitForBackingStoreMsg() OVERRIDE;
- virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE;
+ virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE;
virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE;
virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
@@ -311,13 +317,18 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
virtual bool LockMouse() OVERRIDE;
virtual void UnlockMouse() OVERRIDE;
virtual void UnhandledWheelEvent(
- const WebKit::WebMouseWheelEvent& event) OVERRIDE;
+ const blink::WebMouseWheelEvent& event) OVERRIDE;
// IPC::Sender implementation.
virtual bool Send(IPC::Message* message) OVERRIDE;
+ // SoftwareFrameManagerClient implementation:
+ virtual void SoftwareFrameWasFreed(
+ uint32 output_surface_id, unsigned frame_id) OVERRIDE;
+ virtual void ReleaseReferencesToSoftwareFrame() OVERRIDE;
+
// Forwards the mouse event to the renderer.
- void ForwardMouseEvent(const WebKit::WebMouseEvent& event);
+ void ForwardMouseEvent(const blink::WebMouseEvent& event);
void KillSelf();
@@ -327,7 +338,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
void EnableCoreAnimation();
// Sends completed plugin IME notification and text back to the renderer.
- void PluginImeCompositionCompleted(const string16& text, int plugin_id);
+ void PluginImeCompositionCompleted(const base::string16& text, int plugin_id);
const std::string& selected_text() const { return selected_text_; }
@@ -344,6 +355,15 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
// Called when a GPU error is detected. Deletes all compositing state.
void GotAcceleratedCompositingError();
+ // Sets the overlay view, which should be drawn in the same IOSurface
+ // atop of this view, if both views are drawing accelerated content.
+ // Overlay is stored as a weak ptr.
+ void SetOverlayView(RenderWidgetHostViewMac* overlay,
+ const gfx::Point& offset);
+
+ // Removes the previously set overlay view.
+ void RemoveOverlayView();
+
// Returns true and stores first rectangle for character range if the
// requested |range| is already cached, otherwise returns false.
// Exposed for testing.
@@ -412,6 +432,13 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
scoped_ptr<CompositingIOSurfaceMac> compositing_iosurface_;
scoped_refptr<CompositingIOSurfaceContext> compositing_iosurface_context_;
+ // This holds the current software compositing framebuffer, if any.
+ scoped_ptr<SoftwareFrameManager> software_frame_manager_;
+
+ // This is set when a new software frame is received and un-set when the
+ // frame's ack is sent back to the renderer.
+ bool software_frame_needs_to_send_ack_;
+
// Whether to allow overlapping views.
bool allow_overlapping_views_;
@@ -438,8 +465,6 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
float scale_factor() const;
- bool is_hidden() const { return is_hidden_; }
-
void FrameSwapped();
private:
@@ -513,11 +538,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
// Indicates if the page is loading.
bool is_loading_;
- // true if the View is not visible.
- bool is_hidden_;
-
// The text to be shown in the tooltip, supplied by the renderer.
- string16 tooltip_text_;
+ base::string16 tooltip_text_;
// Factory used to safely scope delayed calls to ShutdownHost().
base::WeakPtrFactory<RenderWidgetHostViewMac> weak_factory_;
@@ -542,6 +564,27 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
base::WeakPtrFactory<RenderWidgetHostViewMac>
pending_swap_buffers_acks_weak_factory_;
+ // The overlay view which is rendered above this one in the same
+ // accelerated IOSurface.
+ // Overlay view has |underlay_view_| set to this view.
+ base::WeakPtr<RenderWidgetHostViewMac> overlay_view_;
+
+ // Offset at which overlay view should be rendered.
+ gfx::Point overlay_view_offset_;
+
+ // The underlay view which this view is rendered above in the same
+ // accelerated IOSurface.
+ // Underlay view has |overlay_view_| set to this view.
+ base::WeakPtr<RenderWidgetHostViewMac> underlay_view_;
+
+ // Set to true when |underlay_view_| has drawn this view. After that point,
+ // this view should not draw again until |underlay_view_| is changed.
+ bool underlay_view_has_drawn_;
+
+ // Factory used to safely reference overlay view set in SetOverlayView.
+ base::WeakPtrFactory<RenderWidgetHostViewMac>
+ overlay_view_weak_factory_;
+
// The earliest time at which the next swap ack may be sent. Only relevant
// when swaps are not being throttled by the renderer (when threaded
// compositing is off).
@@ -557,6 +600,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase,
// Subscriber that listens to frame presentation events.
scoped_ptr<RenderWidgetHostViewFrameSubscriber> frame_subscriber_;
+ base::WeakPtrFactory<RenderWidgetHostViewMac>
+ software_frame_weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewMac);
};
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 b6a6c180bdf..23a6e3c5f24 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
@@ -46,10 +46,11 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/native_web_keyboard_event.h"
#import "content/public/browser/render_widget_host_view_mac_delegate.h"
+#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
#include "skia/ext/platform_canvas.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "third_party/WebKit/public/web/WebScreenInfo.h"
#include "third_party/WebKit/public/web/mac/WebInputEventFactory.h"
#import "third_party/mozilla/ComplexTextInputPanel.h"
#include "ui/base/cocoa/animation_utils.h"
@@ -75,10 +76,10 @@ using content::RenderWidgetHostImpl;
using content::RenderWidgetHostViewMac;
using content::RenderWidgetHostViewMacEditCommandHelper;
using content::TextInputClientMac;
-using WebKit::WebInputEvent;
-using WebKit::WebInputEventFactory;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
+using blink::WebInputEvent;
+using blink::WebInputEventFactory;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
enum CoreAnimationStatus {
CORE_ANIMATION_DISABLED,
@@ -130,15 +131,6 @@ static NSString* const NSBackingPropertyOldScaleFactorKey =
#endif // 10.7
-static inline int ToWebKitModifiers(NSUInteger flags) {
- int modifiers = 0;
- if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey;
- if (flags & NSShiftKeyMask) modifiers |= WebInputEvent::ShiftKey;
- if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey;
- if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey;
- return modifiers;
-}
-
// This method will return YES for OS X versions 10.7.3 and later, and NO
// otherwise.
// Used to prevent a crash when building with the 10.7 SDK and accessing the
@@ -163,7 +155,7 @@ static BOOL SupportsBackingPropertiesChangedNotification() {
}
static float ScaleFactor(NSView* view) {
- return ui::GetScaleFactorScale(ui::GetScaleFactorForNativeView(view));
+ return ui::GetImageScale(ui::GetScaleFactorForNativeView(view));
}
// Private methods:
@@ -189,9 +181,6 @@ static float ScaleFactor(NSView* view) {
- (void)updateTabBackingStoreScaleFactor;
@end
-// NSEvent subtype for scroll gestures events.
-static const short kIOHIDEventTypeScroll = 6;
-
// A window subclass that allows the fullscreen window to become main and gain
// keyboard focus. This is only used for pepper flash. Normal fullscreen is
// handled by the browser.
@@ -289,7 +278,7 @@ namespace {
const size_t kMaxTooltipLength = 1024;
// TODO(suzhe): Upstream this function.
-WebKit::WebColor WebColorFromNSColor(NSColor *color) {
+blink::WebColor WebColorFromNSColor(NSColor *color) {
CGFloat r, g, b, a;
[color getRed:&r green:&g blue:&b alpha:&a];
@@ -304,7 +293,7 @@ WebKit::WebColor WebColorFromNSColor(NSColor *color) {
// third_party/WebKit/Source/WebKit/mac/WebView/WebHTMLView.mm
void ExtractUnderlines(
NSAttributedString* string,
- std::vector<WebKit::WebCompositionUnderline>* underlines) {
+ std::vector<blink::WebCompositionUnderline>* underlines) {
int length = [[string string] length];
int i = 0;
while (i < length) {
@@ -313,13 +302,13 @@ void ExtractUnderlines(
longestEffectiveRange:&range
inRange:NSMakeRange(i, length - i)];
if (NSNumber *style = [attrs objectForKey:NSUnderlineStyleAttributeName]) {
- WebKit::WebColor color = SK_ColorBLACK;
+ blink::WebColor color = SK_ColorBLACK;
if (NSColor *colorAttr =
[attrs objectForKey:NSUnderlineColorAttributeName]) {
color = WebColorFromNSColor(
[colorAttr colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
}
- underlines->push_back(WebKit::WebCompositionUnderline(
+ underlines->push_back(blink::WebCompositionUnderline(
range.location, NSMaxRange(range), color, [style intValue] > 1));
}
i = range.location + range.length;
@@ -376,13 +365,13 @@ NSWindow* ApparentWindowForView(NSView* view) {
return enclosing_window;
}
-WebKit::WebScreenInfo GetWebScreenInfo(NSView* view) {
+blink::WebScreenInfo GetWebScreenInfo(NSView* view) {
gfx::Display display =
gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(view);
NSScreen* screen = [NSScreen deepestScreen];
- WebKit::WebScreenInfo results;
+ blink::WebScreenInfo results;
results.deviceScaleFactor = static_cast<int>(display.device_scale_factor());
results.depth = NSBitsPerPixelFromDepth([screen depth]);
@@ -409,7 +398,7 @@ RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
// static
void RenderWidgetHostViewPort::GetDefaultScreenInfo(
- WebKit::WebScreenInfo* results) {
+ blink::WebScreenInfo* results) {
*results = GetWebScreenInfo(NULL);
}
@@ -423,14 +412,19 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget)
last_frame_was_accelerated_(false),
text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
can_compose_inline_(true),
+ software_frame_needs_to_send_ack_(false),
allow_overlapping_views_(false),
use_core_animation_(false),
is_loading_(false),
- is_hidden_(render_widget_host_->is_hidden()),
weak_factory_(this),
fullscreen_parent_host_view_(NULL),
pending_swap_buffers_acks_weak_factory_(this),
- next_swap_ack_time_(base::Time::Now()) {
+ underlay_view_has_drawn_(false),
+ overlay_view_weak_factory_(this),
+ next_swap_ack_time_(base::Time::Now()),
+ software_frame_weak_ptr_factory_(this) {
+ software_frame_manager_.reset(new SoftwareFrameManager(
+ software_frame_weak_ptr_factory_.GetWeakPtr()));
// |cocoa_view_| owns us and we will be deleted when |cocoa_view_|
// goes away. Since we autorelease it, our caller must put
// |GetNativeView()| into the view hierarchy right after calling us.
@@ -520,32 +514,43 @@ void RenderWidgetHostViewMac::EnableCoreAnimation() {
}
bool RenderWidgetHostViewMac::CreateCompositedIOSurface() {
- if (compositing_iosurface_context_ && compositing_iosurface_)
+ int current_window_number = window_number();
+ bool new_surface_needed = !compositing_iosurface_;
+ bool new_context_needed =
+ !compositing_iosurface_context_ ||
+ (compositing_iosurface_context_ &&
+ compositing_iosurface_context_->window_number() !=
+ current_window_number);
+
+ if (!new_surface_needed && !new_context_needed)
return true;
ScopedCAActionDisabler disabler;
// Create the GL context and shaders.
- if (!compositing_iosurface_context_) {
- compositing_iosurface_context_ =
- CompositingIOSurfaceContext::Get(window_number());
- if (!compositing_iosurface_context_) {
+ if (new_context_needed) {
+ scoped_refptr<CompositingIOSurfaceContext> new_context =
+ CompositingIOSurfaceContext::Get(current_window_number);
+ // Un-bind the GL context from this view before binding the new GL
+ // context. Having two GL contexts bound to a view will result in
+ // crashes and corruption.
+ // http://crbug.com/230883
+ ClearBoundContextDrawable();
+ if (!new_context) {
LOG(ERROR) << "Failed to create CompositingIOSurfaceContext";
return false;
}
+ compositing_iosurface_context_ = new_context;
}
+
// Create the IOSurface texture.
- if (!compositing_iosurface_) {
- compositing_iosurface_.reset(CompositingIOSurfaceMac::Create(
- compositing_iosurface_context_));
+ if (new_surface_needed) {
+ compositing_iosurface_.reset(CompositingIOSurfaceMac::Create());
if (!compositing_iosurface_) {
LOG(ERROR) << "Failed to create CompositingIOSurface";
return false;
}
}
- // Make sure that the IOSurface is updated to use the context that is owned
- // by the view.
- compositing_iosurface_->SetContext(compositing_iosurface_context_);
return true;
}
@@ -605,6 +610,9 @@ void RenderWidgetHostViewMac::ClearBoundContextDrawable() {
cocoa_view_ &&
[[compositing_iosurface_context_->nsgl_context() view]
isEqual:cocoa_view_]) {
+ // Disable screen updates because removing the GL context from below can
+ // cause flashes.
+ [[cocoa_view_ window] disableScreenUpdatesUntilFlush];
[compositing_iosurface_context_->nsgl_context() clearDrawable];
}
}
@@ -626,7 +634,7 @@ void RenderWidgetHostViewMac::InitAsChild(
void RenderWidgetHostViewMac::InitAsPopup(
RenderWidgetHostView* parent_host_view,
const gfx::Rect& pos) {
- bool activatable = popup_type_ == WebKit::WebPopupTypeNone;
+ bool activatable = popup_type_ == blink::WebPopupTypeNone;
[cocoa_view_ setCloseOnDeactivate:YES];
[cocoa_view_ setCanBeKeyView:activatable ? YES : NO];
@@ -730,13 +738,13 @@ RenderWidgetHost* RenderWidgetHostViewMac::GetRenderWidgetHost() const {
}
void RenderWidgetHostViewMac::WasShown() {
- if (!is_hidden_)
+ if (!render_widget_host_->is_hidden())
return;
if (web_contents_switch_paint_time_.is_null())
web_contents_switch_paint_time_ = base::TimeTicks::Now();
- is_hidden_ = false;
render_widget_host_->WasShown();
+ software_frame_manager_->SetVisibility(true);
// We're messing with the window, so do this to ensure no flashes.
if (!use_core_animation_)
@@ -746,21 +754,17 @@ void RenderWidgetHostViewMac::WasShown() {
}
void RenderWidgetHostViewMac::WasHidden() {
- if (is_hidden_)
+ if (render_widget_host_->is_hidden())
return;
// Send ACKs for any pending SwapBuffers (if any) since we won't be displaying
// them and the GPU process is waiting.
AckPendingSwapBuffers();
- // If we receive any more paint messages while we are hidden, we want to
- // ignore them so we don't re-allocate the backing store. We will paint
- // everything again when we become selected again.
- is_hidden_ = true;
-
// If we have a renderer, then inform it that we are being hidden so it can
// reduce its resource utilization.
render_widget_host_->WasHidden();
+ software_frame_manager_->SetVisibility(false);
// There can be a transparent flash as this view is removed and the next is
// added, because of OSX windowing races between displaying the contents of
@@ -782,7 +786,7 @@ void RenderWidgetHostViewMac::SetSize(const gfx::Size& size) {
void RenderWidgetHostViewMac::SetBounds(const gfx::Rect& rect) {
// |rect.size()| is view coordinates, |rect.origin| is screen coordinates,
// TODO(thakis): fix, http://crbug.com/73362
- if (is_hidden_)
+ if (render_widget_host_->is_hidden())
return;
// During the initial creation of the RenderWidgetHostView in
@@ -859,8 +863,9 @@ bool RenderWidgetHostViewMac::HasFocus() const {
}
bool RenderWidgetHostViewMac::IsSurfaceAvailableForCopy() const {
- return !!render_widget_host_->GetBackingStore(false) ||
- (compositing_iosurface_ && compositing_iosurface_->HasIOSurface());
+ return software_frame_manager_->HasCurrentFrame() ||
+ (compositing_iosurface_ && compositing_iosurface_->HasIOSurface()) ||
+ !!render_widget_host_->GetBackingStore(false);
}
void RenderWidgetHostViewMac::Show() {
@@ -953,46 +958,46 @@ void RenderWidgetHostViewMac::DidUpdateBackingStore(
software_latency_info_.MergeWith(latency_info);
- if (!is_hidden_) {
- std::vector<gfx::Rect> rects(copy_rects);
-
- // Because the findbar might be open, we cannot use scrollRect:by: here. For
- // now, simply mark all of scroll rect as dirty.
- if (!scroll_rect.IsEmpty())
- rects.push_back(scroll_rect);
-
- for (size_t i = 0; i < rects.size(); ++i) {
- NSRect ns_rect = [cocoa_view_ flipRectToNSRect:rects[i]];
-
- if (about_to_validate_and_paint_) {
- // As much as we'd like to use -setNeedsDisplayInRect: here, we can't.
- // We're in the middle of executing a -drawRect:, and as soon as it
- // returns Cocoa will clear its record of what needs display. We
- // instead use |performSelector:| to call |setNeedsDisplayInRect:|
- // after returning to the main loop, at which point |drawRect:| is no
- // longer on the stack.
- DCHECK([NSThread isMainThread]);
- if (!call_set_needs_display_in_rect_pending_) {
- [cocoa_view_ performSelector:@selector(callSetNeedsDisplayInRect)
- withObject:nil
- afterDelay:0];
- call_set_needs_display_in_rect_pending_ = true;
- invalid_rect_ = ns_rect;
- } else {
- // The old invalid rect is probably invalid now, since the view has
- // most likely been resized, but there's no harm in dirtying the
- // union. In the limit, this becomes equivalent to dirtying the
- // whole view.
- invalid_rect_ = NSUnionRect(invalid_rect_, ns_rect);
- }
+ if (render_widget_host_->is_hidden())
+ return;
+
+ std::vector<gfx::Rect> rects(copy_rects);
+
+ // Because the findbar might be open, we cannot use scrollRect:by: here. For
+ // now, simply mark all of scroll rect as dirty.
+ if (!scroll_rect.IsEmpty())
+ rects.push_back(scroll_rect);
+
+ for (size_t i = 0; i < rects.size(); ++i) {
+ NSRect ns_rect = [cocoa_view_ flipRectToNSRect:rects[i]];
+
+ if (about_to_validate_and_paint_) {
+ // As much as we'd like to use -setNeedsDisplayInRect: here, we can't.
+ // We're in the middle of executing a -drawRect:, and as soon as it
+ // returns Cocoa will clear its record of what needs display. We instead
+ // use |performSelector:| to call |setNeedsDisplayInRect:| after returning
+ // to the main loop, at which point |drawRect:| is no longer on the
+ // stack.
+ DCHECK([NSThread isMainThread]);
+ if (!call_set_needs_display_in_rect_pending_) {
+ [cocoa_view_ performSelector:@selector(callSetNeedsDisplayInRect)
+ withObject:nil
+ afterDelay:0];
+ call_set_needs_display_in_rect_pending_ = true;
+ invalid_rect_ = ns_rect;
} else {
- [cocoa_view_ setNeedsDisplayInRect:ns_rect];
+ // The old invalid rect is probably invalid now, since the view has most
+ // likely been resized, but there's no harm in dirtying the union. In
+ // the limit, this becomes equivalent to dirtying the whole view.
+ invalid_rect_ = NSUnionRect(invalid_rect_, ns_rect);
}
+ } else {
+ [cocoa_view_ setNeedsDisplayInRect:ns_rect];
}
-
- if (!about_to_validate_and_paint_)
- [cocoa_view_ displayIfNeeded];
}
+
+ if (!about_to_validate_and_paint_)
+ [cocoa_view_ displayIfNeeded];
}
void RenderWidgetHostViewMac::RenderProcessGone(base::TerminationStatus status,
@@ -1036,7 +1041,8 @@ void RenderWidgetHostViewMac::Destroy() {
// Called from the renderer to tell us what the tooltip text should be. It
// calls us frequently so we need to cache the value to prevent doing a lot
// of repeat work.
-void RenderWidgetHostViewMac::SetTooltipText(const string16& tooltip_text) {
+void RenderWidgetHostViewMac::SetTooltipText(
+ const base::string16& tooltip_text) {
if (tooltip_text != tooltip_text_ && [[cocoa_view_ window] isKeyWindow]) {
tooltip_text_ = tooltip_text;
@@ -1044,7 +1050,7 @@ void RenderWidgetHostViewMac::SetTooltipText(const string16& tooltip_text) {
// Windows; we're just trying to be polite. Don't persist the trimmed
// string, as then the comparison above will always fail and we'll try to
// set it again every single time the mouse moves.
- string16 display_text = tooltip_text_;
+ base::string16 display_text = tooltip_text_;
if (tooltip_text_.length() > kMaxTooltipLength)
display_text = tooltip_text_.substr(0, kMaxTooltipLength);
@@ -1077,7 +1083,7 @@ void RenderWidgetHostViewMac::StopSpeaking() {
// RenderWidgetHostViewCocoa uses the stored selection text,
// which implements NSServicesRequests protocol.
//
-void RenderWidgetHostViewMac::SelectionChanged(const string16& text,
+void RenderWidgetHostViewMac::SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) {
if (range.is_empty() || text.empty()) {
@@ -1143,7 +1149,7 @@ void RenderWidgetHostViewMac::SetShowingContextMenu(bool showing) {
}
bool RenderWidgetHostViewMac::IsPopup() const {
- return popup_type_ != WebKit::WebPopupTypeNone;
+ return popup_type_ != blink::WebPopupTypeNone;
}
BackingStore* RenderWidgetHostViewMac::AllocBackingStore(
@@ -1158,19 +1164,51 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurface(
const base::Callback<void(bool, const SkBitmap&)>& callback) {
base::ScopedClosureRunner scoped_callback_runner(
base::Bind(callback, false, SkBitmap()));
- if (!compositing_iosurface_ ||
- !compositing_iosurface_->HasIOSurface())
- return;
-
float scale = ScaleFactor(cocoa_view_);
gfx::Size dst_pixel_size = gfx::ToFlooredSize(
gfx::ScaleSize(dst_size, scale));
+ if (compositing_iosurface_ && compositing_iosurface_->HasIOSurface()) {
+ ignore_result(scoped_callback_runner.Release());
+ compositing_iosurface_->CopyTo(GetScaledOpenGLPixelRect(src_subrect),
+ dst_pixel_size,
+ callback);
+ } else if (software_frame_manager_->HasCurrentFrame()) {
+ gfx::Rect src_pixel_rect = gfx::ToEnclosingRect(gfx::ScaleRect(
+ src_subrect,
+ software_frame_manager_->GetCurrentFrameDeviceScaleFactor()));
+ SkBitmap source_bitmap;
+ source_bitmap.setConfig(
+ SkBitmap::kARGB_8888_Config,
+ software_frame_manager_->GetCurrentFrameSizeInPixels().width(),
+ software_frame_manager_->GetCurrentFrameSizeInPixels().height(),
+ 0,
+ kOpaque_SkAlphaType);
+ source_bitmap.setPixels(software_frame_manager_->GetCurrentFramePixels());
+
+ SkBitmap target_bitmap;
+ target_bitmap.setConfig(
+ SkBitmap::kARGB_8888_Config,
+ dst_pixel_size.width(),
+ dst_pixel_size.height(),
+ 0,
+ kOpaque_SkAlphaType);
+ if (!target_bitmap.allocPixels())
+ return;
- ignore_result(scoped_callback_runner.Release());
+ SkCanvas target_canvas(target_bitmap);
+ SkRect src_pixel_skrect = SkRect::MakeXYWH(
+ src_pixel_rect.x(), src_pixel_rect.y(),
+ src_pixel_rect.width(), src_pixel_rect.height());
+ target_canvas.drawBitmapRectToRect(
+ source_bitmap,
+ &src_pixel_skrect,
+ SkRect::MakeXYWH(0, 0, dst_pixel_size.width(), dst_pixel_size.height()),
+ NULL,
+ SkCanvas::kNone_DrawBitmapRectFlag);
- compositing_iosurface_->CopyTo(GetScaledOpenGLPixelRect(src_subrect),
- dst_pixel_size,
- callback);
+ ignore_result(scoped_callback_runner.Release());
+ callback.Run(true, target_bitmap);
+ }
}
void RenderWidgetHostViewMac::CopyFromCompositingSurfaceToVideoFrame(
@@ -1206,13 +1244,14 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurfaceToVideoFrame(
bool RenderWidgetHostViewMac::CanCopyToVideoFrame() const {
return (!render_widget_host_->GetBackingStore(false) &&
+ !software_frame_manager_->HasCurrentFrame() &&
render_widget_host_->is_accelerated_compositing_active() &&
compositing_iosurface_ &&
compositing_iosurface_->HasIOSurface());
}
bool RenderWidgetHostViewMac::CanSubscribeFrame() const {
- return true;
+ return !software_frame_manager_->HasCurrentFrame();
}
void RenderWidgetHostViewMac::BeginFrameSubscription(
@@ -1262,7 +1301,7 @@ bool RenderWidgetHostViewMac::PostProcessEventForPluginIme(
}
void RenderWidgetHostViewMac::PluginImeCompositionCompleted(
- const string16& text, int plugin_id) {
+ const base::string16& text, int plugin_id) {
if (render_widget_host_) {
render_widget_host_->Send(new ViewMsg_PluginImeCompositionCompleted(
render_widget_host_->GetRoutingID(), text, plugin_id));
@@ -1274,7 +1313,7 @@ void RenderWidgetHostViewMac::CompositorSwapBuffers(
const gfx::Size& size,
float surface_scale_factor,
const ui::LatencyInfo& latency_info) {
- if (is_hidden_)
+ if (render_widget_host_->is_hidden())
return;
NSWindow* window = [cocoa_view_ window];
@@ -1287,8 +1326,10 @@ void RenderWidgetHostViewMac::CompositorSwapBuffers(
RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
if (frame_subscriber_->ShouldCaptureFrame(present_time,
&frame, &callback)) {
- compositing_iosurface_->SetIOSurface(
- surface_handle, size, surface_scale_factor, latency_info);
+ CGLSetCurrentContext(compositing_iosurface_context_->cgl_context());
+ compositing_iosurface_->SetIOSurfaceWithContextCurrent(
+ compositing_iosurface_context_, surface_handle, size,
+ surface_scale_factor, latency_info);
compositing_iosurface_->CopyToVideoFrame(
gfx::Rect(size), frame,
base::Bind(callback, present_time));
@@ -1317,19 +1358,44 @@ void RenderWidgetHostViewMac::CompositorSwapBuffers(
return;
}
+ // Ensure compositing_iosurface_ and compositing_iosurface_context_ be
+ // allocated.
if (!CreateCompositedIOSurface()) {
LOG(ERROR) << "Failed to create CompositingIOSurface";
GotAcceleratedCompositingError();
return;
}
- if (!compositing_iosurface_->SetIOSurface(
- surface_handle, size, surface_scale_factor, latency_info)) {
+ // Make the context current and update the IOSurface with the handle
+ // passed in by the swap command.
+ CGLSetCurrentContext(compositing_iosurface_context_->cgl_context());
+ if (!compositing_iosurface_->SetIOSurfaceWithContextCurrent(
+ compositing_iosurface_context_, surface_handle, size,
+ surface_scale_factor, latency_info)) {
LOG(ERROR) << "Failed SetIOSurface on CompositingIOSurfaceMac";
GotAcceleratedCompositingError();
return;
}
+ // Grab video frames now that the IOSurface has been set up. Note that this
+ // will be done in an offscreen context, so it is necessary to re-set the
+ // current context afterward.
+ if (frame_subscriber_) {
+ const base::Time present_time = base::Time::Now();
+ scoped_refptr<media::VideoFrame> frame;
+ RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
+ if (frame_subscriber_->ShouldCaptureFrame(present_time,
+ &frame, &callback)) {
+ // Flush the context that updated the IOSurface, to ensure that the
+ // context that does the copy picks up the correct version.
+ glFlush();
+ compositing_iosurface_->CopyToVideoFrame(
+ gfx::Rect(size), frame,
+ base::Bind(callback, present_time));
+ CGLSetCurrentContext(compositing_iosurface_context_->cgl_context());
+ }
+ }
+
// Create the layer for the composited content only after the IOSurface has
// been initialized.
if (!CreateCompositedIOSurfaceLayer()) {
@@ -1403,8 +1469,8 @@ void RenderWidgetHostViewMac::ThrottledAckPendingSwapBuffers() {
bool throttle_swap_ack =
render_widget_host_ &&
!render_widget_host_->is_threaded_compositing_enabled() &&
- compositing_iosurface_ &&
- !compositing_iosurface_->is_vsync_disabled();
+ compositing_iosurface_context_ &&
+ !compositing_iosurface_context_->is_vsync_disabled();
base::Time now = base::Time::Now();
if (throttle_swap_ack && next_swap_ack_time_ > now) {
base::TimeDelta next_swap_ack_delay = next_swap_ack_time_ - now;
@@ -1423,7 +1489,6 @@ void RenderWidgetHostViewMac::ThrottledAckPendingSwapBuffers() {
bool RenderWidgetHostViewMac::DrawIOSurfaceWithoutCoreAnimation() {
CHECK(!use_core_animation_);
CHECK(compositing_iosurface_);
- CHECK(compositing_iosurface_context_ == compositing_iosurface_->context());
GLint old_gl_surface_order = 0;
GLint new_gl_surface_order = allow_overlapping_views_ ? -1 : 1;
@@ -1436,19 +1501,46 @@ bool RenderWidgetHostViewMac::DrawIOSurfaceWithoutCoreAnimation() {
forParameter:NSOpenGLCPSurfaceOrder];
}
- CGLError cgl_error = CGLSetCurrentContext(
- compositing_iosurface_context_->cgl_context());
- if (cgl_error != kCGLNoError) {
- LOG(ERROR) << "CGLSetCurrentContext error in DrawIOSurface: " << cgl_error;
- return false;
+ // Instead of drawing, request that underlay view redraws.
+ if (underlay_view_ &&
+ underlay_view_->compositing_iosurface_ &&
+ underlay_view_has_drawn_) {
+ [underlay_view_->cocoa_view() setNeedsDisplay:YES];
+ return true;
}
+ bool has_overlay = overlay_view_ && overlay_view_->compositing_iosurface_;
+ if (has_overlay) {
+ // Un-bind the overlay view's OpenGL context, since its content will be
+ // drawn by this context. Not doing this can result in corruption.
+ // http://crbug.com/330701
+ overlay_view_->ClearBoundContextDrawable();
+ }
[compositing_iosurface_context_->nsgl_context() setView:cocoa_view_];
- return compositing_iosurface_->DrawIOSurface(
- gfx::Size(NSSizeToCGSize([cocoa_view_ frame].size)),
- scale_factor(),
- frame_subscriber(),
- false);
+
+ gfx::Rect view_rect(NSRectToCGRect([cocoa_view_ frame]));
+ if (!compositing_iosurface_->DrawIOSurface(
+ compositing_iosurface_context_, view_rect,
+ scale_factor(), !has_overlay)) {
+ return false;
+ }
+
+ if (has_overlay) {
+ overlay_view_->underlay_view_has_drawn_ = true;
+ gfx::Rect overlay_view_rect(
+ NSRectToCGRect([overlay_view_->cocoa_view() frame]));
+ overlay_view_rect.set_x(overlay_view_offset_.x());
+ overlay_view_rect.set_y(view_rect.height() -
+ overlay_view_rect.height() -
+ overlay_view_offset_.y());
+ if (!overlay_view_->compositing_iosurface_->DrawIOSurface(
+ compositing_iosurface_context_, overlay_view_rect,
+ overlay_view_->scale_factor(), true)) {
+ return false;
+ }
+ }
+
+ return true;
}
void RenderWidgetHostViewMac::GotAcceleratedCompositingError() {
@@ -1465,6 +1557,29 @@ void RenderWidgetHostViewMac::GotAcceleratedCompositingError() {
// repeatedly.
}
+void RenderWidgetHostViewMac::SetOverlayView(
+ RenderWidgetHostViewMac* overlay, const gfx::Point& offset) {
+ if (overlay_view_)
+ overlay_view_->underlay_view_.reset();
+
+ overlay_view_ = overlay->overlay_view_weak_factory_.GetWeakPtr();
+ overlay_view_offset_ = offset;
+ overlay_view_->underlay_view_ = overlay_view_weak_factory_.GetWeakPtr();
+ overlay_view_->underlay_view_has_drawn_ = false;
+
+ [cocoa_view_ setNeedsDisplay:YES];
+ [[cocoa_view_ window] disableScreenUpdatesUntilFlush];
+}
+
+void RenderWidgetHostViewMac::RemoveOverlayView() {
+ if (overlay_view_) {
+ overlay_view_->underlay_view_.reset();
+ overlay_view_.reset();
+ }
+ [cocoa_view_ setNeedsDisplay:YES];
+ [[cocoa_view_ window] disableScreenUpdatesUntilFlush];
+}
+
void RenderWidgetHostViewMac::GetVSyncParameters(
base::TimeTicks* timebase, base::TimeDelta* interval) {
if (compositing_iosurface_) {
@@ -1660,21 +1775,63 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() {
bool RenderWidgetHostViewMac::HasAcceleratedSurface(
const gfx::Size& desired_size) {
- return last_frame_was_accelerated_ &&
- compositing_iosurface_ &&
- compositing_iosurface_->HasIOSurface() &&
- (desired_size.IsEmpty() ||
- compositing_iosurface_->dip_io_surface_size() == desired_size);
+ if (last_frame_was_accelerated_) {
+ return compositing_iosurface_ &&
+ compositing_iosurface_->HasIOSurface() &&
+ (desired_size.IsEmpty() ||
+ compositing_iosurface_->dip_io_surface_size() == desired_size);
+ } else {
+ return (software_frame_manager_->HasCurrentFrame() &&
+ (desired_size.IsEmpty() ||
+ software_frame_manager_->GetCurrentFrameSizeInDIP() ==
+ desired_size));
+ }
+ return false;
}
void RenderWidgetHostViewMac::AboutToWaitForBackingStoreMsg() {
AckPendingSwapBuffers();
}
+void RenderWidgetHostViewMac::OnSwapCompositorFrame(
+ uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) {
+ // Only software compositor frames are accepted.
+ if (!frame->software_frame_data) {
+ DLOG(ERROR) << "Received unexpected frame type.";
+ RecordAction(
+ UserMetricsAction("BadMessageTerminate_UnexpectedFrameType"));
+ render_widget_host_->GetProcess()->ReceivedBadMessage();
+ return;
+ }
+
+ // Ack any swaps that didn't make it to the display.
+ if (software_frame_needs_to_send_ack_)
+ FrameSwapped();
+
+ if (!software_frame_manager_->SwapToNewFrame(
+ output_surface_id,
+ frame->software_frame_data.get(),
+ frame->metadata.device_scale_factor,
+ render_widget_host_->GetProcess()->GetHandle())) {
+ render_widget_host_->GetProcess()->ReceivedBadMessage();
+ return;
+ }
+
+ GotSoftwareFrame();
+ software_latency_info_.MergeWith(frame->metadata.latency_info);
+ software_frame_needs_to_send_ack_ = true;
+
+ [cocoa_view_ setNeedsDisplay:YES];
+}
+
void RenderWidgetHostViewMac::OnAcceleratedCompositingStateChange() {
}
-void RenderWidgetHostViewMac::GetScreenInfo(WebKit::WebScreenInfo* results) {
+void RenderWidgetHostViewMac::AcceleratedSurfaceInitialized(int host_id,
+ int route_id) {
+}
+
+void RenderWidgetHostViewMac::GetScreenInfo(blink::WebScreenInfo* results) {
*results = GetWebScreenInfo(GetNativeView());
}
@@ -1718,7 +1875,7 @@ bool RenderWidgetHostViewMac::LockMouse() {
[NSCursor hide];
// Clear the tooltip window.
- SetTooltipText(string16());
+ SetTooltipText(base::string16());
return true;
}
@@ -1737,7 +1894,7 @@ void RenderWidgetHostViewMac::UnlockMouse() {
}
void RenderWidgetHostViewMac::UnhandledWheelEvent(
- const WebKit::WebMouseWheelEvent& event) {
+ const blink::WebMouseWheelEvent& event) {
// 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)
@@ -1751,6 +1908,21 @@ bool RenderWidgetHostViewMac::Send(IPC::Message* message) {
return false;
}
+void RenderWidgetHostViewMac::SoftwareFrameWasFreed(
+ uint32 output_surface_id, unsigned frame_id) {
+ if (!render_widget_host_)
+ return;
+ cc::CompositorFrameAck ack;
+ ack.last_software_frame_id = frame_id;
+ RenderWidgetHostImpl::SendReclaimCompositorResources(
+ render_widget_host_->GetRoutingID(),
+ output_surface_id,
+ render_widget_host_->GetProcess()->GetID(),
+ ack);
+}
+
+void RenderWidgetHostViewMac::ReleaseReferencesToSoftwareFrame() {
+}
void RenderWidgetHostViewMac::ShutdownHost() {
weak_factory_.InvalidateWeakPtrs();
@@ -1774,6 +1946,7 @@ void RenderWidgetHostViewMac::GotAcceleratedFrame() {
// Delete software backingstore.
BackingStoreManager::RemoveBackingStore(render_widget_host_);
+ software_frame_manager_->DiscardCurrentFrame();
}
}
@@ -1835,18 +2008,9 @@ void RenderWidgetHostViewMac::WindowFrameChanged() {
GetViewBounds()));
}
- if (compositing_iosurface_ && use_core_animation_) {
- scoped_refptr<CompositingIOSurfaceContext> new_context =
- CompositingIOSurfaceContext::Get(window_number());
- if (new_context) {
- // Un-bind the GL context from this view before binding the new GL
- // context. Having two GL contexts bound to a view will result in
- // crashes and corruption.
- // http://crbug.com/230883
- ClearBoundContextDrawable();
- compositing_iosurface_context_ = new_context;
- compositing_iosurface_->SetContext(compositing_iosurface_context_);
- }
+ if (compositing_iosurface_) {
+ // This will migrate the context to the appropriate window.
+ CreateCompositedIOSurface();
}
}
@@ -1905,7 +2069,22 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect(
}
void RenderWidgetHostViewMac::FrameSwapped() {
- software_latency_info_.swap_timestamp = base::TimeTicks::HighResNow();
+ if (software_frame_needs_to_send_ack_ &&
+ software_frame_manager_->HasCurrentFrame()) {
+ software_frame_manager_->SwapToNewFrameComplete(
+ !render_widget_host_->is_hidden());
+
+ cc::CompositorFrameAck ack;
+ RenderWidgetHostImpl::SendSwapCompositorFrameAck(
+ render_widget_host_->GetRoutingID(),
+ software_frame_manager_->GetCurrentFrameOutputSurfaceId(),
+ render_widget_host_->GetProcess()->GetID(),
+ ack);
+ software_frame_needs_to_send_ack_ = false;
+ }
+
+ software_latency_info_.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
render_widget_host_->FrameSwapped(software_latency_info_);
software_latency_info_.Clear();
}
@@ -1915,7 +2094,6 @@ void RenderWidgetHostViewMac::FrameSwapped() {
// RenderWidgetHostViewCocoa ---------------------------------------------------
@implementation RenderWidgetHostViewCocoa
-
@synthesize selectedRange = selectedRange_;
@synthesize suppressNextEscapeKeyUp = suppressNextEscapeKeyUp_;
@synthesize markedRange = markedRange_;
@@ -1924,6 +2102,7 @@ void RenderWidgetHostViewMac::FrameSwapped() {
- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r {
self = [super initWithFrame:NSZeroRect];
if (self) {
+ self.acceptsTouchEvents = YES;
editCommand_helper_.reset(new RenderWidgetHostViewMacEditCommandHelper);
editCommand_helper_->AddEditingSelectorsToClass([self class]);
@@ -1977,8 +2156,8 @@ void RenderWidgetHostViewMac::FrameSwapped() {
}
- (void)scrollOffsetPinnedToLeft:(BOOL)left toRight:(BOOL)right {
- if (delegate_ && [delegate_ respondsToSelector:
- @selector(scrollOffsetPinnedToLeft:toRight:)]) {
+ if (delegate_ && [delegate_
+ respondsToSelector:@selector(scrollOffsetPinnedToLeft:toRight:)]) {
[delegate_ scrollOffsetPinnedToLeft:left toRight:right];
}
}
@@ -2057,10 +2236,16 @@ void RenderWidgetHostViewMac::FrameSwapped() {
// The cursor is over a nonWebContentView - ignore this mouse event.
return YES;
}
- if ([view isKindOfClass:[self class]] && ![view isEqual:self]) {
+ if ([view isKindOfClass:[self class]] && ![view isEqual:self] &&
+ !hasOpenMouseDown_) {
// The cursor is over an overlapping render widget. This check is done by
// both views so the one that's returned by -hitTest: will end up
// processing the event.
+ // Note that while dragging, we only get events for the render view where
+ // drag started, even if mouse is actually over another view or outside
+ // the window. Cocoa does this for us. We should handle these events and
+ // not ignore (since there is no other render view to handle them). Thus
+ // the |!hasOpenMouseDown_| check above.
return YES;
}
view = [view superview];
@@ -2181,14 +2366,15 @@ void RenderWidgetHostViewMac::FrameSwapped() {
return YES;
}
-- (void)keyEvent:(NSEvent*)theEvent {
+- (EventHandled)keyEvent:(NSEvent*)theEvent {
if (delegate_ && [delegate_ respondsToSelector:@selector(handleEvent:)]) {
BOOL handled = [delegate_ handleEvent:theEvent];
if (handled)
- return;
+ return kEventHandled;
}
[self keyEvent:theEvent wasKeyEquivalent:NO];
+ return kEventHandled;
}
- (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv {
@@ -2351,7 +2537,7 @@ void RenderWidgetHostViewMac::FrameSwapped() {
} else if (oldHasMarkedText && !hasMarkedText_ && !textInserted) {
if (unmarkTextCalled_) {
widgetHost->ImeConfirmComposition(
- string16(), gfx::Range::InvalidRange(), false);
+ base::string16(), gfx::Range::InvalidRange(), false);
} else {
widgetHost->ImeCancelComposition();
}
@@ -2368,7 +2554,7 @@ void RenderWidgetHostViewMac::FrameSwapped() {
// So before sending the real key down event, we need to send a fake key up
// event to balance it.
NativeWebKeyboardEvent fakeEvent = event;
- fakeEvent.type = WebKit::WebInputEvent::KeyUp;
+ fakeEvent.type = blink::WebInputEvent::KeyUp;
fakeEvent.skip_in_browser = true;
widgetHost->ForwardKeyboardEvent(fakeEvent);
// Not checking |renderWidgetHostView_->render_widget_host_| here because
@@ -2394,7 +2580,7 @@ void RenderWidgetHostViewMac::FrameSwapped() {
if (!textInserted && textToBeInserted_.length() == 1) {
// If a single character was inserted, then we just send it as a keypress
// event.
- event.type = WebKit::WebInputEvent::Char;
+ event.type = blink::WebInputEvent::Char;
event.text[0] = textToBeInserted_[0];
event.text[1] = 0;
event.skip_in_browser = true;
@@ -2406,7 +2592,7 @@ void RenderWidgetHostViewMac::FrameSwapped() {
// We don't get insertText: calls if ctrl or cmd is down, or the key event
// generates an insert command. So synthesize a keypress event for these
// cases, unless the key event generated any other command.
- event.type = WebKit::WebInputEvent::Char;
+ event.type = blink::WebInputEvent::Char;
event.skip_in_browser = true;
widgetHost->ForwardKeyboardEvent(event);
}
@@ -2437,6 +2623,47 @@ void RenderWidgetHostViewMac::FrameSwapped() {
}
}
+- (void)beginGestureWithEvent:(NSEvent*)event {
+ [delegate_ beginGestureWithEvent:event];
+}
+- (void)endGestureWithEvent:(NSEvent*)event {
+ [delegate_ endGestureWithEvent:event];
+}
+- (void)touchesMovedWithEvent:(NSEvent*)event {
+ [delegate_ touchesMovedWithEvent:event];
+}
+- (void)touchesBeganWithEvent:(NSEvent*)event {
+ [delegate_ touchesBeganWithEvent:event];
+}
+- (void)touchesCancelledWithEvent:(NSEvent*)event {
+ [delegate_ touchesCancelledWithEvent:event];
+}
+- (void)touchesEndedWithEvent:(NSEvent*)event {
+ [delegate_ touchesEndedWithEvent:event];
+}
+
+// This method handles 2 different types of hardware events.
+// (Apple does not distinguish between them).
+// a. Scrolling the middle wheel of a mouse.
+// b. Swiping on the track pad.
+//
+// This method is responsible for 2 types of behavior:
+// a. Scrolling the content of window.
+// b. Navigating forwards/backwards in history.
+//
+// This is a brief description of the logic:
+// 1. If the content can be scrolled, scroll the content.
+// (This requires a roundtrip to blink to determine whether the content
+// can be scrolled.)
+// Once this logic is triggered, the navigate logic cannot be triggered
+// until the gesture finishes.
+// 2. If the user is making a horizontal swipe, start the navigate
+// forward/backwards UI.
+// Once this logic is triggered, the user can either cancel or complete
+// the gesture. If the user completes the gesture, all remaining touches
+// are swallowed, and not allowed to scroll the content. If the user
+// cancels the gesture, all remaining touches are forwarded to the content
+// scroll logic. The user cannot trigger the navigation logic again.
- (void)scrollWheel:(NSEvent*)event {
if (delegate_ && [delegate_ respondsToSelector:@selector(handleEvent:)]) {
BOOL handled = [delegate_ handleEvent:event];
@@ -2451,13 +2678,14 @@ void RenderWidgetHostViewMac::FrameSwapped() {
if (base::mac::IsOSLionOrLater() && [event phase] == NSEventPhaseBegan &&
!endWheelMonitor_) {
endWheelMonitor_ =
- [NSEvent addLocalMonitorForEventsMatchingMask:NSScrollWheelMask
- handler:^(NSEvent* blockEvent) {
- [self shortCircuitScrollWheelEvent:blockEvent];
- return blockEvent;
- }];
+ [NSEvent addLocalMonitorForEventsMatchingMask:NSScrollWheelMask
+ handler:^(NSEvent* blockEvent) {
+ [self shortCircuitScrollWheelEvent:blockEvent];
+ return blockEvent;
+ }];
}
+ // This is responsible for content scrolling!
if (renderWidgetHostView_->render_widget_host_) {
const WebMouseWheelEvent& webEvent =
WebInputEventFactory::mouseWheelEvent(event, self);
@@ -2708,6 +2936,8 @@ void RenderWidgetHostViewMac::FrameSwapped() {
NSRectFill(dirtyRect);
}
+ CGLSetCurrentContext(
+ renderWidgetHostView_->compositing_iosurface_context_->cgl_context());
if (renderWidgetHostView_->DrawIOSurfaceWithoutCoreAnimation())
return;
@@ -2726,29 +2956,62 @@ void RenderWidgetHostViewMac::FrameSwapped() {
- (void)drawBackingStore:(BackingStoreMac*)backingStore
dirtyRect:(CGRect)dirtyRect
inContext:(CGContextRef)context {
- if (backingStore) {
+ content::SoftwareFrameManager* software_frame_manager =
+ renderWidgetHostView_->software_frame_manager_.get();
+ // There should never be both a legacy software and software composited
+ // frame.
+ DCHECK(!backingStore || !software_frame_manager->HasCurrentFrame());
+
+ if (backingStore || software_frame_manager->HasCurrentFrame()) {
// Note: All coordinates are in view units, not pixels.
- gfx::Rect bitmapRect(0, 0,
- backingStore->size().width(),
- backingStore->size().height());
+ gfx::Rect bitmapRect(
+ software_frame_manager->HasCurrentFrame() ?
+ software_frame_manager->GetCurrentFrameSizeInDIP() :
+ backingStore->size());
// Specify the proper y offset to ensure that the view is rooted to the
// upper left corner. This can be negative, if the window was resized
// smaller and the renderer hasn't yet repainted.
- int yOffset = NSHeight([self bounds]) - backingStore->size().height();
+ int yOffset = NSHeight([self bounds]) - bitmapRect.height();
NSRect nsDirtyRect = NSRectFromCGRect(dirtyRect);
const gfx::Rect damagedRect([self flipNSRectToRect:nsDirtyRect]);
gfx::Rect paintRect = gfx::IntersectRects(bitmapRect, damagedRect);
if (!paintRect.IsEmpty()) {
- // if we have a CGLayer, draw that into the window
- if (backingStore->cg_layer()) {
+ if (software_frame_manager->HasCurrentFrame()) {
+ // If a software compositor framebuffer is present, draw using that.
+ gfx::Size sizeInPixels =
+ software_frame_manager->GetCurrentFrameSizeInPixels();
+ base::ScopedCFTypeRef<CGDataProviderRef> dataProvider(
+ CGDataProviderCreateWithData(
+ NULL,
+ software_frame_manager->GetCurrentFramePixels(),
+ 4 * sizeInPixels.width() * sizeInPixels.height(),
+ NULL));
+ base::ScopedCFTypeRef<CGImageRef> image(
+ CGImageCreate(
+ sizeInPixels.width(),
+ sizeInPixels.height(),
+ 8,
+ 32,
+ 4 * sizeInPixels.width(),
+ base::mac::GetSystemColorSpace(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+ dataProvider,
+ NULL,
+ false,
+ kCGRenderingIntentDefault));
+ CGRect imageRect = bitmapRect.ToCGRect();
+ imageRect.origin.y = yOffset;
+ CGContextDrawImage(context, imageRect, image);
+ } else if (backingStore->cg_layer()) {
+ // If we have a CGLayer, draw that into the window
// TODO: add clipping to dirtyRect if it improves drawing performance.
CGContextDrawLayerAtPoint(context, CGPointMake(0.0, yOffset),
backingStore->cg_layer());
} else {
- // if we haven't created a layer yet, draw the cached bitmap into
+ // If we haven't created a layer yet, draw the cached bitmap into
// the window. The CGLayer will be created the next time the renderer
// paints.
base::ScopedCFTypeRef<CGImageRef> image(
@@ -2856,8 +3119,9 @@ void RenderWidgetHostViewMac::FrameSwapped() {
}
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
- if (delegate_ && [delegate_ respondsToSelector:
- @selector(validateUserInterfaceItem:isValidItem:)]) {
+ if (delegate_ &&
+ [delegate_ respondsToSelector:@selector(validateUserInterfaceItem:
+ isValidItem:)]) {
BOOL valid;
BOOL known = [delegate_ validateUserInterfaceItem:item
isValidItem:&valid];
@@ -2900,7 +3164,8 @@ void RenderWidgetHostViewMac::FrameSwapped() {
// move) for the given event. Customize here to be more selective about which
// key presses to autohide on.
+ (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event {
- return ([event type] == NSKeyDown) ? YES : NO;
+ return ([event type] == NSKeyDown &&
+ !([event modifierFlags] & NSCommandKeyMask)) ? YES : NO;
}
- (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute
@@ -3008,10 +3273,8 @@ void RenderWidgetHostViewMac::FrameSwapped() {
// Convert a web accessibility's location in web coordinates into a cocoa
// screen coordinate.
-- (NSPoint)accessibilityPointInScreen:
- (BrowserAccessibilityCocoa*)accessibility {
- NSPoint origin = [accessibility origin];
- NSSize size = [[accessibility size] sizeValue];
+- (NSPoint)accessibilityPointInScreen:(NSPoint)origin
+ size:(NSSize)size {
origin.y = NSHeight([self bounds]) - origin.y;
NSPoint originInWindow = [self convertPoint:origin toView:nil];
NSPoint originInScreen = [[self window] convertBaseToScreen:originInWindow];
@@ -3038,8 +3301,9 @@ void RenderWidgetHostViewMac::FrameSwapped() {
- (void)performShowMenuAction:(BrowserAccessibilityCocoa*)accessibility {
// Performs a right click copying WebKit's
// accessibilityPerformShowMenuAction.
- NSPoint location = [self accessibilityPointInScreen:accessibility];
+ NSPoint origin = [accessibility origin];
NSSize size = [[accessibility size] sizeValue];
+ NSPoint location = [self accessibilityPointInScreen:origin size:size];
location = [[self window] convertScreenToBase:location];
location.x += size.width/2;
location.y += size.height/2;
@@ -3431,7 +3695,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
// called in keyEvent: method.
if (!handlingKeyDown_) {
renderWidgetHostView_->render_widget_host_->ImeConfirmComposition(
- string16(), gfx::Range::InvalidRange(), false);
+ base::string16(), gfx::Range::InvalidRange(), false);
} else {
unmarkTextCalled_ = YES;
}
@@ -3459,7 +3723,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
} else {
// Use a thin black underline by default.
underlines_.push_back(
- WebKit::WebCompositionUnderline(0, length, SK_ColorBLACK, false));
+ blink::WebCompositionUnderline(0, length, SK_ColorBLACK, false));
}
// If we are handling a key down event, then SetComposition() will be
@@ -3669,7 +3933,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
if (renderWidgetHostView_->render_widget_host_)
renderWidgetHostView_->render_widget_host_->ImeConfirmComposition(
- string16(), gfx::Range::InvalidRange(), false);
+ base::string16(), gfx::Range::InvalidRange(), false);
[self cancelComposition];
}
@@ -3682,7 +3946,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
if (!active) {
[[ComplexTextInputPanel sharedComplexTextInputPanel] cancelComposition];
renderWidgetHostView_->PluginImeCompositionCompleted(
- string16(), focusedPluginIdentifier_);
+ base::string16(), focusedPluginIdentifier_);
}
}
@@ -3717,7 +3981,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
if (pluginImeActive_ &&
![[ComplexTextInputPanel sharedComplexTextInputPanel] inComposition]) {
renderWidgetHostView_->PluginImeCompositionCompleted(
- string16(), focusedPluginIdentifier_);
+ base::string16(), focusedPluginIdentifier_);
pluginImeActive_ = NO;
}
}
@@ -3792,7 +4056,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
CGRect clipRect = CGContextGetClipBoundingBox(context);
if (!renderWidgetHostView_->render_widget_host_ ||
- renderWidgetHostView_->is_hidden()) {
+ renderWidgetHostView_->render_widget_host_->is_hidden()) {
CGContextSetFillColorWithColor(context,
CGColorGetConstantColor(kCGColorWhite));
CGContextFillRect(context, clipRect);
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 7a152d18da8..25154962167 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
@@ -9,7 +9,6 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
@@ -18,6 +17,7 @@
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_utils.h"
+#include "content/test/test_render_view_host.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/test/cocoa_test_event_utils.h"
@@ -83,6 +83,12 @@ typedef NSUInteger NSEventPhase;
- (void)gotUnhandledWheelEvent {
unhandledWheelEventReceived_ = true;
}
+- (void)touchesBeganWithEvent:(NSEvent*)event{}
+- (void)touchesMovedWithEvent:(NSEvent*)event{}
+- (void)touchesCancelledWithEvent:(NSEvent*)event{}
+- (void)touchesEndedWithEvent:(NSEvent*)event{}
+- (void)beginGestureWithEvent:(NSEvent*)event{}
+- (void)endGestureWithEvent:(NSEvent*)event{}
@end
@@ -318,7 +324,7 @@ TEST_F(RenderWidgetHostViewMacTest, AcceleratorDestroy) {
}
TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharacterRangeCaretCase) {
- const string16 kDummyString = UTF8ToUTF16("hogehoge");
+ const base::string16 kDummyString = UTF8ToUTF16("hogehoge");
const size_t kDummyOffset = 0;
gfx::Rect caret_rect(10, 11, 0, 10);
@@ -329,7 +335,7 @@ TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharacterRangeCaretCase) {
NSRange actual_range;
rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range);
params.anchor_rect = params.focus_rect = caret_rect;
- params.anchor_dir = params.focus_dir = WebKit::WebTextDirectionLeftToRight;
+ params.anchor_dir = params.focus_dir = blink::WebTextDirectionLeftToRight;
rwhv_mac_->SelectionBoundsChanged(params);
EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(
caret_range.ToNSRange(),
@@ -711,7 +717,7 @@ TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
// Send an ACK for the first wheel event, so that the queue will be flushed.
scoped_ptr<IPC::Message> response(new InputHostMsg_HandleInputEvent_ACK(
- 0, WebKit::WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED,
+ 0, blink::WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED,
ui::LatencyInfo()));
host->OnMessageReceived(*response);
@@ -756,7 +762,7 @@ TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) {
// Indicate that the wheel event was unhandled.
scoped_ptr<IPC::Message> response1(new InputHostMsg_HandleInputEvent_ACK(0,
- WebKit::WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+ blink::WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
ui::LatencyInfo()));
host->OnMessageReceived(*response1);
@@ -771,7 +777,7 @@ TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) {
// Indicate that the wheel event was also unhandled.
scoped_ptr<IPC::Message> response2(new InputHostMsg_HandleInputEvent_ACK(0,
- WebKit::WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+ blink::WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
ui::LatencyInfo()));
host->OnMessageReceived(*response2);
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_win.cc b/chromium/content/browser/renderer_host/render_widget_host_view_win.cc
index de2aa656a0d..8238a82b4ca 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_win.cc
@@ -61,7 +61,6 @@
#include "ui/base/ime/win/imm32_manager.h"
#include "ui/base/ime/win/tsf_input_scope.h"
#include "ui/base/l10n/l10n_util_win.h"
-#include "ui/base/sequential_id_generator.h"
#include "ui/base/touch/touch_device.h"
#include "ui/base/touch/touch_enabled.h"
#include "ui/base/ui_base_switches.h"
@@ -74,6 +73,7 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/screen.h"
+#include "ui/gfx/sequential_id_generator.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/win/dpi.h"
#include "ui/gfx/win/hwnd_util.h"
@@ -83,9 +83,9 @@
using base::TimeDelta;
using base::TimeTicks;
using ui::ViewProp;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebTextDirection;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebTextDirection;
namespace content {
namespace {
@@ -202,10 +202,10 @@ bool DecodeScrollGesture(const GESTUREINFO& gi,
return true;
}
-WebKit::WebMouseWheelEvent MakeFakeScrollWheelEvent(HWND hwnd,
+blink::WebMouseWheelEvent MakeFakeScrollWheelEvent(HWND hwnd,
POINT start,
POINT delta) {
- WebKit::WebMouseWheelEvent result;
+ blink::WebMouseWheelEvent result;
result.type = WebInputEvent::MouseWheel;
result.timeStampSeconds = ::GetMessageTime() / 1000.0;
result.button = WebMouseEvent::ButtonNone;
@@ -236,17 +236,17 @@ inline void SetTouchType(TOUCHINPUT* point, int type) {
point->dwFlags = (point->dwFlags & kTouchMask) | type;
}
-ui::EventType ConvertToUIEvent(WebKit::WebTouchPoint::State t) {
+ui::EventType ConvertToUIEvent(blink::WebTouchPoint::State t) {
switch (t) {
- case WebKit::WebTouchPoint::StatePressed:
+ case blink::WebTouchPoint::StatePressed:
return ui::ET_TOUCH_PRESSED;
- case WebKit::WebTouchPoint::StateMoved:
+ case blink::WebTouchPoint::StateMoved:
return ui::ET_TOUCH_MOVED;
- case WebKit::WebTouchPoint::StateStationary:
+ case blink::WebTouchPoint::StateStationary:
return ui::ET_TOUCH_STATIONARY;
- case WebKit::WebTouchPoint::StateReleased:
+ case blink::WebTouchPoint::StateReleased:
return ui::ET_TOUCH_RELEASED;
- case WebKit::WebTouchPoint::StateCancelled:
+ case blink::WebTouchPoint::StateCancelled:
return ui::ET_TOUCH_CANCELLED;
default:
DCHECK(false) << "Unexpected ui type. " << t;
@@ -255,9 +255,9 @@ ui::EventType ConvertToUIEvent(WebKit::WebTouchPoint::State t) {
}
// Creates a WebGestureEvent corresponding to the given |gesture|
-WebKit::WebGestureEvent CreateWebGestureEvent(HWND hwnd,
+blink::WebGestureEvent CreateWebGestureEvent(HWND hwnd,
const ui::GestureEvent& gesture) {
- WebKit::WebGestureEvent gesture_event =
+ blink::WebGestureEvent gesture_event =
MakeWebGestureEventFromUIEvent(gesture);
POINT client_point = gesture.location().ToPOINT();
@@ -272,17 +272,17 @@ WebKit::WebGestureEvent CreateWebGestureEvent(HWND hwnd,
return gesture_event;
}
-WebKit::WebGestureEvent CreateFlingCancelEvent(double time_stamp) {
- WebKit::WebGestureEvent gesture_event;
+blink::WebGestureEvent CreateFlingCancelEvent(double time_stamp) {
+ blink::WebGestureEvent gesture_event;
gesture_event.timeStampSeconds = time_stamp;
- gesture_event.type = WebKit::WebGestureEvent::GestureFlingCancel;
- gesture_event.sourceDevice = WebKit::WebGestureEvent::Touchscreen;
+ gesture_event.type = blink::WebGestureEvent::GestureFlingCancel;
+ gesture_event.sourceDevice = blink::WebGestureEvent::Touchscreen;
return gesture_event;
}
class TouchEventFromWebTouchPoint : public ui::TouchEvent {
public:
- TouchEventFromWebTouchPoint(const WebKit::WebTouchPoint& touch_point,
+ TouchEventFromWebTouchPoint(const blink::WebTouchPoint& touch_point,
base::TimeDelta& timestamp)
: ui::TouchEvent(ConvertToUIEvent(touch_point.state),
touch_point.position,
@@ -307,7 +307,7 @@ bool ShouldSendPinchGesture() {
}
void GetScreenInfoForWindow(gfx::NativeViewId id,
- WebKit::WebScreenInfo* results) {
+ blink::WebScreenInfo* results) {
HWND window = gfx::NativeViewFromId(id);
HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
@@ -322,9 +322,9 @@ void GetScreenInfoForWindow(gfx::NativeViewId id,
dev_mode.dmDriverExtra = 0;
EnumDisplaySettings(monitor_info.szDevice, ENUM_CURRENT_SETTINGS, &dev_mode);
- WebKit::WebScreenInfo screen_info;
+ blink::WebScreenInfo screen_info;
screen_info.depth = dev_mode.dmBitsPerPel;
- screen_info.depthPerComponent = dev_mode.dmBitsPerPel / 3; // Assumes RGB
+ screen_info.depthPerComponent = 8;
screen_info.deviceScaleFactor = gfx::win::GetDeviceScaleFactor();
screen_info.isMonochrome = dev_mode.dmColor == DMCOLOR_MONOCHROME;
screen_info.rect = gfx::Rect(monitor_info.rcMonitor);
@@ -351,18 +351,18 @@ class WebTouchState {
bool ReleaseTouchPoints();
// The contained WebTouchEvent.
- const WebKit::WebTouchEvent& touch_event() { return touch_event_; }
+ const blink::WebTouchEvent& touch_event() { return touch_event_; }
// Returns if any touches are modified in the event.
bool is_changed() { return touch_event_.changedTouchesLength != 0; }
private:
// Adds a touch point or returns NULL if there's not enough space.
- WebKit::WebTouchPoint* AddTouchPoint(TOUCHINPUT* touch_input);
+ blink::WebTouchPoint* AddTouchPoint(TOUCHINPUT* touch_input);
// Copy details from a TOUCHINPUT to an existing WebTouchPoint, returning
// true if the resulting point is a stationary move.
- bool UpdateTouchPoint(WebKit::WebTouchPoint* touch_point,
+ bool UpdateTouchPoint(blink::WebTouchPoint* touch_point,
TOUCHINPUT* touch_input);
// Find (or create) a mapping for _os_touch_id_.
@@ -371,7 +371,7 @@ class WebTouchState {
// Remove any mappings that are no longer in use.
void RemoveExpiredMappings();
- WebKit::WebTouchEvent touch_event_;
+ blink::WebTouchEvent touch_event_;
const RenderWidgetHostViewWin* const window_;
ui::SequentialIDGenerator id_generator_;
@@ -393,7 +393,6 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
imm32_manager_(new ui::IMM32Manager),
ime_notification_(false),
capture_enter_key_(false),
- is_hidden_(render_widget_host_->is_hidden()),
about_to_validate_and_paint_(false),
close_on_deactivate_(false),
being_destroyed_(false),
@@ -411,14 +410,16 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
pointer_down_context_(false),
last_touch_location_(-1, -1),
touch_events_enabled_(ui::AreTouchEventsEnabled()),
- gesture_recognizer_(ui::GestureRecognizer::Create(this)) {
+ gesture_recognizer_(ui::GestureRecognizer::Create()) {
render_widget_host_->SetView(this);
registrar_.Add(this,
NOTIFICATION_RENDERER_PROCESS_TERMINATED,
NotificationService::AllBrowserContextsAndSources());
+ gesture_recognizer_->AddGestureEventHelper(this);
}
RenderWidgetHostViewWin::~RenderWidgetHostViewWin() {
+ gesture_recognizer_->RemoveGestureEventHelper(this);
UnlockMouse();
ResetTooltip();
}
@@ -456,34 +457,34 @@ RenderWidgetHost* RenderWidgetHostViewWin::GetRenderWidgetHost() const {
}
void RenderWidgetHostViewWin::WasShown() {
- if (!is_hidden_)
+ // |render_widget_host_| may be NULL if the WebContentsImpl is in the process
+ // of closing.
+ if (!render_widget_host_)
+ return;
+
+ if (!render_widget_host_->is_hidden())
return;
if (web_contents_switch_paint_time_.is_null())
web_contents_switch_paint_time_ = TimeTicks::Now();
- is_hidden_ = false;
- // |render_widget_host_| may be NULL if the WebContentsImpl is in the process
- // of closing.
- if (render_widget_host_)
- render_widget_host_->WasShown();
+ render_widget_host_->WasShown();
}
void RenderWidgetHostViewWin::WasHidden() {
- if (is_hidden_)
+ // |render_widget_host_| may be NULL if the WebContentsImpl is in the process
+ // of closing.
+ if (!render_widget_host_)
return;
- // If we receive any more paint messages while we are hidden, we want to
- // ignore them so we don't re-allocate the backing store. We will paint
- // everything again when we become selected again.
- is_hidden_ = true;
+ if (render_widget_host_->is_hidden())
+ return;
ResetTooltip();
- // If we have a renderer, then inform it that we are being hidden so it can
- // reduce its resource utilization.
- if (render_widget_host_)
- render_widget_host_->WasHidden();
+ // Inform the renderer that we are being hidden so it can reduce its resource
+ // utilization.
+ render_widget_host_->WasHidden();
if (accelerated_surface_)
accelerated_surface_->WasHidden();
@@ -594,7 +595,7 @@ void RenderWidgetHostViewWin::CleanupCompositorWindow() {
bool RenderWidgetHostViewWin::IsActivatable() const {
// Popups should not be activated.
- return popup_type_ == WebKit::WebPopupTypeNone;
+ return popup_type_ == blink::WebPopupTypeNone;
}
void RenderWidgetHostViewWin::Focus() {
@@ -762,7 +763,7 @@ void RenderWidgetHostViewWin::DidUpdateBackingStore(
const ui::LatencyInfo& latency_info) {
TRACE_EVENT0("content", "RenderWidgetHostViewWin::DidUpdateBackingStore");
software_latency_info_.MergeWith(latency_info);
- if (is_hidden_)
+ if (render_widget_host_->is_hidden())
return;
// Schedule invalidations first so that the ScrollWindowEx call is closer to
@@ -835,14 +836,15 @@ void RenderWidgetHostViewWin::Destroy() {
DestroyWindow();
}
-void RenderWidgetHostViewWin::SetTooltipText(const string16& tooltip_text) {
- if (!is_hidden_)
+void RenderWidgetHostViewWin::SetTooltipText(
+ const base::string16& tooltip_text) {
+ if (!render_widget_host_->is_hidden())
EnsureTooltip();
// Clamp the tooltip length to kMaxTooltipLength so that we don't
// accidentally DOS the user with a mega tooltip (since Windows doesn't seem
// to do this itself).
- const string16 new_tooltip_text =
+ const base::string16 new_tooltip_text =
gfx::TruncateString(tooltip_text, kMaxTooltipLength);
if (new_tooltip_text != tooltip_text_) {
@@ -944,24 +946,29 @@ void RenderWidgetHostViewWin::UpdateDesiredTouchMode() {
}
}
-bool RenderWidgetHostViewWin::DispatchLongPressGestureEvent(
+bool RenderWidgetHostViewWin::CanDispatchToConsumer(
+ ui::GestureConsumer* consumer) {
+ CHECK_EQ(static_cast<RenderWidgetHostViewWin*>(consumer), this);
+ return true;
+}
+
+void RenderWidgetHostViewWin::DispatchPostponedGestureEvent(
ui::GestureEvent* event) {
- return ForwardGestureEventToRenderer(event);
+ ForwardGestureEventToRenderer(event);
}
-bool RenderWidgetHostViewWin::DispatchCancelTouchEvent(
+void RenderWidgetHostViewWin::DispatchCancelTouchEvent(
ui::TouchEvent* event) {
if (!render_widget_host_ || !touch_events_enabled_ ||
!render_widget_host_->ShouldForwardTouchEvent()) {
- return false;
+ return;
}
- DCHECK(event->type() == WebKit::WebInputEvent::TouchCancel);
- WebKit::WebTouchEvent cancel_event;
- cancel_event.type = WebKit::WebInputEvent::TouchCancel;
+ DCHECK(event->type() == blink::WebInputEvent::TouchCancel);
+ blink::WebTouchEvent cancel_event;
+ cancel_event.type = blink::WebInputEvent::TouchCancel;
cancel_event.timeStampSeconds = event->time_stamp().InSecondsF();
render_widget_host_->ForwardTouchEventWithLatencyInfo(
cancel_event, *event->latency());
- return true;
}
void RenderWidgetHostViewWin::SetHasHorizontalScrollbar(
@@ -981,12 +988,12 @@ void RenderWidgetHostViewWin::SetCompositionText(
if (!render_widget_host_)
return;
// ui::CompositionUnderline should be identical to
- // WebKit::WebCompositionUnderline, so that we can do reinterpret_cast safely.
+ // blink::WebCompositionUnderline, so that we can do reinterpret_cast safely.
COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
- sizeof(WebKit::WebCompositionUnderline),
+ sizeof(blink::WebCompositionUnderline),
ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
- const std::vector<WebKit::WebCompositionUnderline>& underlines =
- reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
+ const std::vector<blink::WebCompositionUnderline>& underlines =
+ reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>(
composition.underlines);
render_widget_host_->ImeSetComposition(composition.text, underlines,
composition.selection.end(),
@@ -1011,7 +1018,7 @@ void RenderWidgetHostViewWin::ClearCompositionText() {
NOTIMPLEMENTED();
}
-void RenderWidgetHostViewWin::InsertText(const string16& text) {
+void RenderWidgetHostViewWin::InsertText(const base::string16& text) {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return;
@@ -1061,7 +1068,7 @@ bool RenderWidgetHostViewWin::CanComposeInline() const {
return false;
}
-gfx::Rect RenderWidgetHostViewWin::GetCaretBounds() {
+gfx::Rect RenderWidgetHostViewWin::GetCaretBounds() const {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return gfx::Rect(0, 0, 0, 0);
@@ -1072,7 +1079,7 @@ gfx::Rect RenderWidgetHostViewWin::GetCaretBounds() {
}
bool RenderWidgetHostViewWin::GetCompositionCharacterBounds(
- uint32 index, gfx::Rect* rect) {
+ uint32 index, gfx::Rect* rect) const {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1086,7 +1093,7 @@ bool RenderWidgetHostViewWin::GetCompositionCharacterBounds(
return true;
}
-bool RenderWidgetHostViewWin::HasCompositionText() {
+bool RenderWidgetHostViewWin::HasCompositionText() const {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1096,7 +1103,7 @@ bool RenderWidgetHostViewWin::HasCompositionText() {
return false;
}
-bool RenderWidgetHostViewWin::GetTextRange(gfx::Range* range) {
+bool RenderWidgetHostViewWin::GetTextRange(gfx::Range* range) const {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1106,7 +1113,7 @@ bool RenderWidgetHostViewWin::GetTextRange(gfx::Range* range) {
return false;
}
-bool RenderWidgetHostViewWin::GetCompositionTextRange(gfx::Range* range) {
+bool RenderWidgetHostViewWin::GetCompositionTextRange(gfx::Range* range) const {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1116,7 +1123,7 @@ bool RenderWidgetHostViewWin::GetCompositionTextRange(gfx::Range* range) {
return false;
}
-bool RenderWidgetHostViewWin::GetSelectionRange(gfx::Range* range) {
+bool RenderWidgetHostViewWin::GetSelectionRange(gfx::Range* range) const {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1147,7 +1154,7 @@ bool RenderWidgetHostViewWin::DeleteRange(const gfx::Range& range) {
}
bool RenderWidgetHostViewWin::GetTextFromRange(const gfx::Range& range,
- string16* text) {
+ base::string16* text) const {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
return false;
@@ -1205,6 +1212,15 @@ void RenderWidgetHostViewWin::EnsureCaretInRect(const gfx::Rect& rect) {
NOTIMPLEMENTED();
}
+void RenderWidgetHostViewWin::OnCandidateWindowShown() {
+}
+
+void RenderWidgetHostViewWin::OnCandidateWindowUpdated() {
+}
+
+void RenderWidgetHostViewWin::OnCandidateWindowHidden() {
+}
+
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewWin, private:
@@ -1396,7 +1412,8 @@ void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) {
web_contents_switch_paint_time_ = TimeTicks();
}
- software_latency_info_.swap_timestamp = TimeTicks::HighResNow();
+ software_latency_info_.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
render_widget_host_->FrameSwapped(software_latency_info_);
software_latency_info_.Clear();
} else {
@@ -1410,7 +1427,7 @@ void RenderWidgetHostViewWin::DrawBackground(const RECT& dirty_rect,
CPaintDC* dc) {
if (!background_.empty()) {
gfx::Rect dirty_area(dirty_rect);
- gfx::Canvas canvas(dirty_area.size(), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(dirty_area.size(), 1.0f, true);
canvas.Translate(-dirty_area.OffsetFromOrigin());
gfx::Rect dc_rect(dc->m_ps.rcPaint);
@@ -1657,9 +1674,9 @@ LRESULT RenderWidgetHostViewWin::OnImeComposition(
imm32_manager_->UpdateImeWindow(m_hWnd);
// ui::CompositionUnderline should be identical to
- // WebKit::WebCompositionUnderline, so that we can do reinterpret_cast safely.
+ // blink::WebCompositionUnderline, so that we can do reinterpret_cast safely.
COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
- sizeof(WebKit::WebCompositionUnderline),
+ sizeof(blink::WebCompositionUnderline),
ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
// Retrieve the result string and its attributes of the ongoing composition
@@ -1683,8 +1700,8 @@ LRESULT RenderWidgetHostViewWin::OnImeComposition(
// TODO(suzhe): convert both renderer_host and renderer to use
// ui::CompositionText.
- const std::vector<WebKit::WebCompositionUnderline>& underlines =
- reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
+ const std::vector<blink::WebCompositionUnderline>& underlines =
+ reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>(
composition.underlines);
render_widget_host_->ImeSetComposition(
composition.text, underlines,
@@ -1921,8 +1938,8 @@ LRESULT RenderWidgetHostViewWin::OnKeyEvent(UINT message, WPARAM wparam,
if (ui::IMM32Manager::IsCtrlShiftPressed(&dir)) {
render_widget_host_->UpdateTextDirection(
dir == base::i18n::RIGHT_TO_LEFT ?
- WebKit::WebTextDirectionRightToLeft :
- WebKit::WebTextDirectionLeftToRight);
+ blink::WebTextDirectionRightToLeft :
+ blink::WebTextDirectionLeftToRight);
}
} else if (wparam != VK_CONTROL) {
// Bug 9762: http://crbug.com/9762 A user pressed a key except shift
@@ -1999,7 +2016,7 @@ LRESULT RenderWidgetHostViewWin::OnWheelEvent(UINT message, WPARAM wparam,
}
if (render_widget_host_) {
- WebKit::WebMouseWheelEvent wheel_event =
+ blink::WebMouseWheelEvent wheel_event =
WebMouseWheelEventBuilder::Build(m_hWnd, message, wparam, lparam);
float scale = gfx::win::GetDeviceScaleFactor();
wheel_event.x /= scale;
@@ -2025,14 +2042,14 @@ size_t WebTouchState::UpdateTouchPoints(
// and alter/add any touchpoints (from the touch input buffer) that we can
// coalesce into a single message. The return value is the number of consumed
// input message.
- WebKit::WebTouchPoint* point = touch_event_.touches;
- WebKit::WebTouchPoint* end = point + touch_event_.touchesLength;
+ blink::WebTouchPoint* point = touch_event_.touches;
+ blink::WebTouchPoint* end = point + touch_event_.touchesLength;
while (point < end) {
- if (point->state == WebKit::WebTouchPoint::StateReleased) {
+ if (point->state == blink::WebTouchPoint::StateReleased) {
*point = *(--end);
--touch_event_.touchesLength;
} else {
- point->state = WebKit::WebTouchPoint::StateStationary;
+ point->state = blink::WebTouchPoint::StateStationary;
point++;
}
}
@@ -2045,7 +2062,7 @@ size_t WebTouchState::UpdateTouchPoints(
for (size_t i = 0; i < count; ++i) {
unsigned int mapped_id = GetMappedTouch(points[i].dwID);
- WebKit::WebTouchPoint* point = NULL;
+ blink::WebTouchPoint* point = NULL;
for (unsigned j = 0; j < touch_event_.touchesLength; ++j) {
if (static_cast<DWORD>(touch_event_.touches[j].id) == mapped_id) {
point = &touch_event_.touches[j];
@@ -2069,26 +2086,26 @@ size_t WebTouchState::UpdateTouchPoints(
case TOUCHEVENTF_DOWN: {
if (!(point = AddTouchPoint(&points[i])))
continue;
- touch_event_.type = WebKit::WebInputEvent::TouchStart;
+ touch_event_.type = blink::WebInputEvent::TouchStart;
break;
}
case TOUCHEVENTF_UP: {
if (!point) // Just throw away a stray up.
continue;
- point->state = WebKit::WebTouchPoint::StateReleased;
+ point->state = blink::WebTouchPoint::StateReleased;
UpdateTouchPoint(point, &points[i]);
- touch_event_.type = WebKit::WebInputEvent::TouchEnd;
+ touch_event_.type = blink::WebInputEvent::TouchEnd;
break;
}
case TOUCHEVENTF_MOVE: {
if (point) {
- point->state = WebKit::WebTouchPoint::StateMoved;
+ point->state = blink::WebTouchPoint::StateMoved;
// Don't update the message if the point didn't really move.
if (UpdateTouchPoint(point, &points[i]))
continue;
- touch_event_.type = WebKit::WebInputEvent::TouchMove;
+ touch_event_.type = blink::WebInputEvent::TouchMove;
} else if (touch_event_.changedTouchesLength) {
RemoveExpiredMappings();
// Can't add a point if we're already handling move events.
@@ -2099,7 +2116,7 @@ size_t WebTouchState::UpdateTouchPoints(
continue;
last_type = TOUCHEVENTF_DOWN;
SetTouchType(&points[i], TOUCHEVENTF_DOWN);
- touch_event_.type = WebKit::WebInputEvent::TouchStart;
+ touch_event_.type = blink::WebInputEvent::TouchStart;
}
break;
}
@@ -2116,10 +2133,10 @@ size_t WebTouchState::UpdateTouchPoints(
}
void WebTouchState::RemoveExpiredMappings() {
- WebKit::WebTouchPoint* point = touch_event_.touches;
- WebKit::WebTouchPoint* end = point + touch_event_.touchesLength;
+ blink::WebTouchPoint* point = touch_event_.touches;
+ blink::WebTouchPoint* end = point + touch_event_.touchesLength;
for (; point < end; ++point) {
- if (point->state == WebKit::WebTouchPoint::StateReleased)
+ if (point->state == blink::WebTouchPoint::StateReleased)
id_generator_.ReleaseGeneratedID(point->id);
}
}
@@ -2129,34 +2146,34 @@ bool WebTouchState::ReleaseTouchPoints() {
if (touch_event_.touchesLength == 0)
return false;
// Mark every active touchpoint as released.
- touch_event_.type = WebKit::WebInputEvent::TouchEnd;
+ touch_event_.type = blink::WebInputEvent::TouchEnd;
touch_event_.changedTouchesLength = touch_event_.touchesLength;
for (unsigned int i = 0; i < touch_event_.touchesLength; ++i) {
- touch_event_.touches[i].state = WebKit::WebTouchPoint::StateReleased;
+ touch_event_.touches[i].state = blink::WebTouchPoint::StateReleased;
touch_event_.changedTouches[i].state =
- WebKit::WebTouchPoint::StateReleased;
+ blink::WebTouchPoint::StateReleased;
}
return true;
}
-WebKit::WebTouchPoint* WebTouchState::AddTouchPoint(
+blink::WebTouchPoint* WebTouchState::AddTouchPoint(
TOUCHINPUT* touch_input) {
DCHECK(touch_event_.touchesLength <
- WebKit::WebTouchEvent::touchesLengthCap);
+ blink::WebTouchEvent::touchesLengthCap);
if (touch_event_.touchesLength >=
- WebKit::WebTouchEvent::touchesLengthCap)
+ blink::WebTouchEvent::touchesLengthCap)
return NULL;
- WebKit::WebTouchPoint* point =
+ blink::WebTouchPoint* point =
&touch_event_.touches[touch_event_.touchesLength++];
- point->state = WebKit::WebTouchPoint::StatePressed;
+ point->state = blink::WebTouchPoint::StatePressed;
point->id = GetMappedTouch(touch_input->dwID);
UpdateTouchPoint(point, touch_input);
return point;
}
bool WebTouchState::UpdateTouchPoint(
- WebKit::WebTouchPoint* touch_point,
+ blink::WebTouchPoint* touch_point,
TOUCHINPUT* touch_input) {
CPoint coordinates(
TOUCH_COORD_TO_PIXEL(touch_input->x) /
@@ -2181,7 +2198,7 @@ bool WebTouchState::UpdateTouchPoint(
touch_point->screenPosition.y == coordinates.y &&
touch_point->radiusX == radius_x &&
touch_point->radiusY == radius_y) {
- touch_point->state = WebKit::WebTouchPoint::StateStationary;
+ touch_point->state = blink::WebTouchPoint::StateStationary;
return true;
}
@@ -2216,8 +2233,8 @@ LRESULT RenderWidgetHostViewWin::OnTouchEvent(UINT message, WPARAM wparam,
// TODO(jschuh): Add support for an arbitrary number of touchpoints.
size_t total = std::min(static_cast<int>(LOWORD(wparam)),
- static_cast<int>(WebKit::WebTouchEvent::touchesLengthCap));
- TOUCHINPUT points[WebKit::WebTouchEvent::touchesLengthCap];
+ static_cast<int>(blink::WebTouchEvent::touchesLengthCap));
+ TOUCHINPUT points[blink::WebTouchEvent::touchesLengthCap];
if (!total || !ui::GetTouchInputInfoWrapper((HTOUCHINPUT)lparam, total,
points, sizeof(TOUCHINPUT))) {
@@ -2245,7 +2262,7 @@ LRESULT RenderWidgetHostViewWin::OnTouchEvent(UINT message, WPARAM wparam,
render_widget_host_->ForwardTouchEventWithLatencyInfo(
touch_state_->touch_event(), ui::LatencyInfo());
} else {
- const WebKit::WebTouchEvent& touch_event = touch_state_->touch_event();
+ const blink::WebTouchEvent& touch_event = touch_state_->touch_event();
base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds(
touch_event.timeStampSeconds * 1000);
for (size_t i = 0; i < touch_event.touchesLength; ++i) {
@@ -2476,7 +2493,7 @@ void RenderWidgetHostViewWin::AcceleratedPaint(HDC dc) {
accelerated_surface_->Present(dc);
}
-void RenderWidgetHostViewWin::GetScreenInfo(WebKit::WebScreenInfo* results) {
+void RenderWidgetHostViewWin::GetScreenInfo(blink::WebScreenInfo* results) {
GetScreenInfoForWindow(GetNativeViewId(), results);
}
@@ -2554,6 +2571,18 @@ gfx::GLSurfaceHandle RenderWidgetHostViewWin::GetCompositingSurface() {
return surface_handle;
}
+void RenderWidgetHostViewWin::ResizeCompositingSurface(const gfx::Size& size) {
+ // Ensure window does not have zero area because D3D cannot create a zero
+ // area swap chain.
+ ::SetWindowPos(compositor_host_window_,
+ NULL,
+ 0, 0,
+ std::max(1, size.width()),
+ std::max(1, size.height()),
+ SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER |
+ SWP_NOACTIVATE | SWP_DEFERERASE | SWP_NOMOVE);
+}
+
void RenderWidgetHostViewWin::OnAcceleratedCompositingStateChange() {
bool show = render_widget_host_->is_accelerated_compositing_active();
// When we first create the compositor, we will get a show request from
@@ -2602,6 +2631,10 @@ void RenderWidgetHostViewWin::OnAcceleratedCompositingStateChange() {
}
}
+void RenderWidgetHostViewWin::AcceleratedSurfaceInitialized(int host_id,
+ int route_id) {
+}
+
void RenderWidgetHostViewWin::AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
int gpu_host_id) {
@@ -2764,7 +2797,7 @@ LRESULT RenderWidgetHostViewWin::OnSessionChange(UINT message,
break;
case WTS_SESSION_UNLOCK:
// Force a repaint to update the window contents.
- if (!is_hidden_)
+ if (!render_widget_host_->is_hidden())
InvalidateRect(NULL, FALSE);
accelerated_surface_->SetIsSessionLocked(false);
break;
@@ -2856,10 +2889,10 @@ bool RenderWidgetHostViewWin::ForwardGestureEventToRenderer(
return true;
}
- WebKit::WebGestureEvent web_gesture = CreateWebGestureEvent(m_hWnd, *gesture);
- if (web_gesture.type == WebKit::WebGestureEvent::Undefined)
+ blink::WebGestureEvent web_gesture = CreateWebGestureEvent(m_hWnd, *gesture);
+ if (web_gesture.type == blink::WebGestureEvent::Undefined)
return false;
- if (web_gesture.type == WebKit::WebGestureEvent::GestureTapDown) {
+ if (web_gesture.type == blink::WebGestureEvent::GestureTapDown) {
render_widget_host_->ForwardGestureEvent(
CreateFlingCancelEvent(gesture->time_stamp().InSecondsF()));
}
@@ -3185,7 +3218,7 @@ RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
// static
void RenderWidgetHostViewPort::GetDefaultScreenInfo(
- WebKit::WebScreenInfo* results) {
+ blink::WebScreenInfo* results) {
GetScreenInfoForWindow(0, results);
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_win.h b/chromium/content/browser/renderer_host/render_widget_host_view_win.h
index 6650ae4ba8b..b9a87bf61e8 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_win.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_win.h
@@ -23,11 +23,10 @@
#include "content/common/content_export.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
-#include "ui/base/gestures/gesture_recognizer.h"
-#include "ui/base/gestures/gesture_types.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/win/tsf_bridge.h"
-#include "ui/base/win/extra_sdk_defines.h"
+#include "ui/events/gestures/gesture_recognizer.h"
+#include "ui/events/gestures/gesture_types.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/point.h"
#include "ui/surface/accelerated_surface_win.h"
@@ -49,7 +48,7 @@ class IMM32Manager;
class ViewProp;
}
-namespace WebKit {
+namespace blink {
struct WebScreenInfo;
}
@@ -203,7 +202,7 @@ class RenderWidgetHostViewWin
// called by WebContentsImpl before DestroyWindow
virtual void WillWmDestroy() OVERRIDE;
virtual void Destroy() OVERRIDE;
- virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE;
+ virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE;
virtual BackingStore* AllocBackingStore(const gfx::Size& size) OVERRIDE;
virtual void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
@@ -215,15 +214,18 @@ class RenderWidgetHostViewWin
const base::Callback<void(bool)>& callback) OVERRIDE;
virtual bool CanCopyToVideoFrame() const OVERRIDE;
virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
+ virtual void AcceleratedSurfaceInitialized(int host_id,
+ int route_id) OVERRIDE;
virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) OVERRIDE;
virtual void SetHasHorizontalScrollbar(
bool has_horizontal_scrollbar) OVERRIDE;
virtual void SetScrollOffsetPinning(
bool is_pinned_to_left, bool is_pinned_to_right) OVERRIDE;
- virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE;
+ virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE;
virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE;
virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
+ virtual void ResizeCompositingSurface(const gfx::Size&) OVERRIDE;
virtual void AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
int gpu_host_id) OVERRIDE;
@@ -258,37 +260,41 @@ class RenderWidgetHostViewWin
virtual void FatalAccessibilityTreeError() OVERRIDE;
// Overridden from ui::GestureEventHelper.
- virtual bool DispatchLongPressGestureEvent(ui::GestureEvent* event) OVERRIDE;
- virtual bool DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE;
+ virtual bool CanDispatchToConsumer(ui::GestureConsumer* consumer) OVERRIDE;
+ virtual void DispatchPostponedGestureEvent(ui::GestureEvent* event) OVERRIDE;
+ virtual void DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE;
// Overridden from ui::TextInputClient for Win8/metro TSF support.
// Following methods are not used in existing IMM32 related implementation.
virtual void SetCompositionText(
const ui::CompositionText& composition) OVERRIDE;
- virtual void ConfirmCompositionText() OVERRIDE;
+ virtual void ConfirmCompositionText() OVERRIDE;
virtual void ClearCompositionText() OVERRIDE;
- virtual void InsertText(const string16& text) OVERRIDE;
+ virtual void InsertText(const base::string16& text) OVERRIDE;
virtual void InsertChar(char16 ch, int flags) OVERRIDE;
virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
virtual ui::TextInputType GetTextInputType() const OVERRIDE;
virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
virtual bool CanComposeInline() const OVERRIDE;
- virtual gfx::Rect GetCaretBounds() OVERRIDE;
+ virtual gfx::Rect GetCaretBounds() const OVERRIDE;
virtual bool GetCompositionCharacterBounds(uint32 index,
- gfx::Rect* rect) OVERRIDE;
- virtual bool HasCompositionText() OVERRIDE;
- virtual bool GetTextRange(gfx::Range* range) OVERRIDE;
- virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE;
- virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE;
+ gfx::Rect* rect) const OVERRIDE;
+ virtual bool HasCompositionText() const OVERRIDE;
+ virtual bool GetTextRange(gfx::Range* range) const OVERRIDE;
+ virtual bool GetCompositionTextRange(gfx::Range* range) const OVERRIDE;
+ virtual bool GetSelectionRange(gfx::Range* range) const OVERRIDE;
virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE;
virtual bool DeleteRange(const gfx::Range& range) OVERRIDE;
virtual bool GetTextFromRange(const gfx::Range& range,
- string16* text) OVERRIDE;
+ base::string16* text) const OVERRIDE;
virtual void OnInputMethodChanged() OVERRIDE;
virtual bool ChangeTextDirectionAndLayoutAlignment(
base::i18n::TextDirection direction) OVERRIDE;
virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE;
virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE;
+ virtual void OnCandidateWindowShown() OVERRIDE;
+ virtual void OnCandidateWindowUpdated() OVERRIDE;
+ virtual void OnCandidateWindowHidden() OVERRIDE;
protected:
friend class RenderWidgetHostView;
@@ -489,9 +495,6 @@ class RenderWidgetHostViewWin
// true if Enter was hit when render widget host was in focus.
bool capture_enter_key_;
- // true if the View is not visible.
- bool is_hidden_;
-
// The touch-state. Its touch-points are updated as necessary. A new
// touch-point is added from an TOUCHEVENTF_DOWN message, and a touch-point
// is removed from the list on an TOUCHEVENTF_UP message.
@@ -513,7 +516,7 @@ class RenderWidgetHostViewWin
// Tooltips
// The text to be shown in the tooltip, supplied by the renderer.
- string16 tooltip_text_;
+ base::string16 tooltip_text_;
// The tooltip control hwnd
HWND tooltip_hwnd_;
// Whether or not a tooltip is currently visible. We use this to track
@@ -580,12 +583,11 @@ class RenderWidgetHostViewWin
// A cached latest caret rectangle sent from renderer.
gfx::Rect caret_rect_;
- // TODO(ananta)
- // The WM_POINTERDOWN and touch related members should be moved to an
+ // TODO(ananta): The pointer and touch related members should be moved to an
// independent class to reduce the clutter. This includes members
- // pointer_down_context_ and last_touch_location_;
+ // pointer_down_context_ and last_touch_location_.
- // Set to true if we are in the context of a WM_POINTERDOWN message
+ // Set to true if we are in the context of a pointer down message.
bool pointer_down_context_;
// The global x, y coordinates of the last point a touch event was
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc
deleted file mode 100644
index fc73601fb6c..00000000000
--- a/chromium/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc
+++ /dev/null
@@ -1,226 +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 <vector>
-
-#include "base/command_line.h"
-#include "base/win/metro.h"
-#include "content/browser/renderer_host/render_widget_host_view_win.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
-#include "ui/base/ime/composition_text.h"
-#include "ui/base/ime/text_input_type.h"
-#include "ui/base/ime/win/imm32_manager.h"
-#include "ui/base/ime/win/mock_tsf_bridge.h"
-#include "ui/base/ime/win/tsf_bridge.h"
-
-namespace content {
-namespace {
-
-class MockIMM32Manager : public ui::IMM32Manager {
- public:
- MockIMM32Manager()
- : window_handle_(NULL),
- input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
- call_count_(0) {
- }
- virtual ~MockIMM32Manager() {}
-
- virtual void SetTextInputMode(HWND window_handle,
- ui::TextInputMode input_mode) OVERRIDE {
- ++call_count_;
- window_handle_ = window_handle;
- input_mode_ = input_mode;
- }
-
- void Reset() {
- window_handle_ = NULL;
- input_mode_ = ui::TEXT_INPUT_MODE_DEFAULT;
- call_count_ = 0;
- }
-
- HWND window_handle() const { return window_handle_; }
- ui::TextInputMode input_mode() const { return input_mode_; }
- size_t call_count() const { return call_count_; }
-
- private:
- HWND window_handle_;
- ui::TextInputMode input_mode_;
- size_t call_count_;
-
- DISALLOW_COPY_AND_ASSIGN(MockIMM32Manager);
-};
-
-// Testing class serving initialized RenderWidgetHostViewWin instance;
-class RenderWidgetHostViewWinBrowserTest : public ContentBrowserTest {
- public:
- RenderWidgetHostViewWinBrowserTest() {}
-
- virtual void SetUpOnMainThread() OVERRIDE {
- ContentBrowserTest::SetUpOnMainThread();
-
- NavigateToURL(shell(), GURL("about:blank"));
-
- view_ = static_cast<RenderWidgetHostViewWin*>(
- RenderWidgetHostViewPort::FromRWHV(
- shell()->web_contents()->GetRenderViewHost()->GetView()));
- CHECK(view_);
- }
-
- protected:
- RenderWidgetHostViewWin* view_;
-};
-
-} // namespace
-
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinBrowserTest,
- TextInputTypeChanged) {
- ASSERT_TRUE(view_->m_hWnd);
-
- MockIMM32Manager* mock = new MockIMM32Manager();
- mock->Reset();
- view_->imm32_manager_.reset(mock);
- view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE,
- ui::TEXT_INPUT_MODE_EMAIL, false);
-
- EXPECT_EQ(1, mock->call_count());
- EXPECT_EQ(view_->m_hWnd, mock->window_handle());
- EXPECT_EQ(ui::TEXT_INPUT_MODE_EMAIL, mock->input_mode());
-
- mock->Reset();
- view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE,
- ui::TEXT_INPUT_MODE_EMAIL, false);
- EXPECT_EQ(0, mock->call_count());
-}
-
-class RenderWidgetHostViewWinTSFTest : public ContentBrowserTest {
- public:
- RenderWidgetHostViewWinTSFTest() {}
-
- virtual void SetUpCommandLine(CommandLine* command_line) {
- command_line->AppendSwitch(switches::kEnableTextServicesFramework);
- }
-};
-
-// crbug.com/151798
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTSFTest,
- DISABLED_SwichToPasswordField) {
- ui::MockTSFBridge mock_bridge;
- ui::TSFBridge* old_bridge = ui::TSFBridge::ReplaceForTesting(&mock_bridge);
- GURL test_url = GetTestUrl("textinput", "ime_enable_disable_test.html");
-
- NavigateToURL(shell(), test_url);
- WaitForLoadStop(shell()->web_contents());
- RunAllPendingInMessageLoop();
-
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, mock_bridge.latest_text_iput_type());
-
- // Focus to the text field, the IME should be enabled.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(text01_focus());",
- &success));
- EXPECT_TRUE(success);
- WaitForLoadStop(shell()->web_contents());
- RunAllPendingInMessageLoop();
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, mock_bridge.latest_text_iput_type());
-
- // Focus to the password field, the IME should be disabled.
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(password02_focus());",
- &success));
- EXPECT_TRUE(success);
- WaitForLoadStop(shell()->web_contents());
- RunAllPendingInMessageLoop();
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, mock_bridge.latest_text_iput_type());
-
- ui::TSFBridge::ReplaceForTesting(old_bridge);
-}
-
-// crbug.com/151798
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTSFTest,
- DISABLED_SwitchToSameField) {
- ui::MockTSFBridge mock_bridge;
- ui::TSFBridge* old_bridge = ui::TSFBridge::ReplaceForTesting(&mock_bridge);
- GURL test_url = GetTestUrl("textinput", "ime_enable_disable_test.html");
-
- NavigateToURL(shell(), test_url);
- WaitForLoadStop(shell()->web_contents());
- RunAllPendingInMessageLoop();
-
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, mock_bridge.latest_text_iput_type());
-
- // Focus to the text field, the IME should be enabled.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(text01_focus());",
- &success));
- EXPECT_TRUE(success);
- WaitForLoadStop(shell()->web_contents());
- RunAllPendingInMessageLoop();
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, mock_bridge.latest_text_iput_type());
-
- // Focus to another text field, the IME should be enabled.
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(text02_focus());",
- &success));
- EXPECT_TRUE(success);
- WaitForLoadStop(shell()->web_contents());
- RunAllPendingInMessageLoop();
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, mock_bridge.latest_text_iput_type());
-
- ui::TSFBridge::ReplaceForTesting(old_bridge);
-}
-
-// crbug.com/151798
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTSFTest,
- DISABLED_SwitchToSamePasswordField) {
- ui::MockTSFBridge mock_bridge;
- ui::TSFBridge* old_bridge = ui::TSFBridge::ReplaceForTesting(&mock_bridge);
- GURL test_url = GetTestUrl("textinput", "ime_enable_disable_test.html");
-
- NavigateToURL(shell(), test_url);
- WaitForLoadStop(shell()->web_contents());
- RunAllPendingInMessageLoop();
-
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, mock_bridge.latest_text_iput_type());
-
- // Focus to the password field, the IME should be disabled.
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(password01_focus());",
- &success));
- EXPECT_TRUE(success);
- WaitForLoadStop(shell()->web_contents());
- RunAllPendingInMessageLoop();
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, mock_bridge.latest_text_iput_type());
-
- // Focus to the another password field, the IME should be disabled.
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(password02_focus());",
- &success));
- EXPECT_TRUE(success);
- WaitForLoadStop(shell()->web_contents());
- RunAllPendingInMessageLoop();
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, mock_bridge.latest_text_iput_type());
-
- ui::TSFBridge::ReplaceForTesting(old_bridge);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/frame_memory_manager.cc b/chromium/content/browser/renderer_host/renderer_frame_manager.cc
index 708bddfa61b..3d16361828d 100644
--- a/chromium/content/browser/renderer_host/frame_memory_manager.cc
+++ b/chromium/content/browser/renderer_host/renderer_frame_manager.cc
@@ -2,27 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/renderer_host/frame_memory_manager.h"
+#include "content/browser/renderer_host/renderer_frame_manager.h"
#include "base/logging.h"
-#include "base/memory/singleton.h"
#include "base/sys_info.h"
namespace content {
-namespace {
-
-size_t MaxNumberOfSavedFrames() {
- return std::min(5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256));
-}
-
-} // namespace
-
-FrameMemoryManager* FrameMemoryManager::GetInstance() {
- return Singleton<FrameMemoryManager>::get();
+RendererFrameManager* RendererFrameManager::GetInstance() {
+ return Singleton<RendererFrameManager>::get();
}
-void FrameMemoryManager::AddFrame(FrameContainer* frame, bool visible) {
+void RendererFrameManager::AddFrame(RendererFrameManagerClient* frame,
+ bool visible) {
RemoveFrame(frame);
if (visible)
visible_frames_.insert(frame);
@@ -31,13 +23,13 @@ void FrameMemoryManager::AddFrame(FrameContainer* frame, bool visible) {
CullHiddenFrames();
}
-void FrameMemoryManager::RemoveFrame(FrameContainer* frame) {
+void RendererFrameManager::RemoveFrame(RendererFrameManagerClient* frame) {
visible_frames_.erase(frame);
hidden_frames_.remove(frame);
}
-void FrameMemoryManager::SetFrameVisibility(FrameContainer* frame,
- bool visible) {
+void RendererFrameManager::SetFrameVisibility(RendererFrameManagerClient* frame,
+ bool visible) {
if (visible) {
hidden_frames_.remove(frame);
visible_frames_.insert(frame);
@@ -48,17 +40,19 @@ void FrameMemoryManager::SetFrameVisibility(FrameContainer* frame,
}
}
-FrameMemoryManager::FrameMemoryManager() {}
+RendererFrameManager::RendererFrameManager()
+ : max_number_of_saved_frames_(
+ std::min(5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256))) {}
-FrameMemoryManager::~FrameMemoryManager() {}
+RendererFrameManager::~RendererFrameManager() {}
-void FrameMemoryManager::CullHiddenFrames() {
+void RendererFrameManager::CullHiddenFrames() {
while (!hidden_frames_.empty() &&
hidden_frames_.size() + visible_frames_.size() >
- MaxNumberOfSavedFrames()) {
+ max_number_of_saved_frames()) {
size_t old_size = hidden_frames_.size();
// Should remove self from list.
- hidden_frames_.back()->ReleaseCurrentFrame();
+ hidden_frames_.back()->EvictCurrentFrame();
DCHECK_EQ(hidden_frames_.size() + 1, old_size);
}
}
diff --git a/chromium/content/browser/renderer_host/renderer_frame_manager.h b/chromium/content/browser/renderer_host/renderer_frame_manager.h
new file mode 100644
index 00000000000..134e1ef6a04
--- /dev/null
+++ b/chromium/content/browser/renderer_host/renderer_frame_manager.h
@@ -0,0 +1,50 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDERER_FRAME_MANAGER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_RENDERER_FRAME_MANAGER_H_
+
+#include <list>
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/memory/singleton.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class CONTENT_EXPORT RendererFrameManagerClient {
+ public:
+ virtual ~RendererFrameManagerClient() {}
+ virtual void EvictCurrentFrame() = 0;
+};
+
+class CONTENT_EXPORT RendererFrameManager {
+ public:
+ static RendererFrameManager* GetInstance();
+
+ void AddFrame(RendererFrameManagerClient*, bool visible);
+ void RemoveFrame(RendererFrameManagerClient*);
+ void SetFrameVisibility(RendererFrameManagerClient*, bool visible);
+
+ size_t max_number_of_saved_frames() const {
+ return max_number_of_saved_frames_;
+ }
+
+ private:
+ RendererFrameManager();
+ ~RendererFrameManager();
+ void CullHiddenFrames();
+ friend struct DefaultSingletonTraits<RendererFrameManager>;
+
+ std::set<RendererFrameManagerClient*> visible_frames_;
+ std::list<RendererFrameManagerClient*> hidden_frames_;
+ size_t max_number_of_saved_frames_;
+
+ DISALLOW_COPY_AND_ASSIGN(RendererFrameManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_RENDERER_FRAME_MANAGER_H_
diff --git a/chromium/content/browser/renderer_host/software_frame_manager.cc b/chromium/content/browser/renderer_host/software_frame_manager.cc
new file mode 100644
index 00000000000..147c21eab65
--- /dev/null
+++ b/chromium/content/browser/renderer_host/software_frame_manager.cc
@@ -0,0 +1,202 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/software_frame_manager.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/debug/alias.h"
+#include "content/browser/renderer_host/dip_util.h"
+#include "content/public/browser/user_metrics.h"
+
+namespace {
+
+void ReleaseMailbox(scoped_refptr<content::SoftwareFrame> frame,
+ unsigned sync_point,
+ bool lost_resource) {}
+
+} // namespace
+
+namespace content {
+
+////////////////////////////////////////////////////////////////////////////////
+// SoftwareFrame
+
+class CONTENT_EXPORT SoftwareFrame : public base::RefCounted<SoftwareFrame> {
+ private:
+ friend class base::RefCounted<SoftwareFrame>;
+ friend class SoftwareFrameManager;
+
+ SoftwareFrame(
+ base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client,
+ uint32 output_surface_id,
+ unsigned frame_id,
+ float frame_device_scale_factor,
+ gfx::Size frame_size_pixels,
+ scoped_ptr<base::SharedMemory> shared_memory);
+ ~SoftwareFrame();
+
+ base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client_;
+ const uint32 output_surface_id_;
+ const unsigned frame_id_;
+ float frame_device_scale_factor_;
+ const gfx::Size frame_size_pixels_;
+ scoped_ptr<base::SharedMemory> shared_memory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareFrame);
+};
+
+SoftwareFrame::SoftwareFrame(
+ base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client,
+ uint32 output_surface_id,
+ unsigned frame_id,
+ float frame_device_scale_factor,
+ gfx::Size frame_size_pixels,
+ scoped_ptr<base::SharedMemory> shared_memory)
+ : frame_manager_client_(frame_manager_client),
+ output_surface_id_(output_surface_id),
+ frame_id_(frame_id),
+ frame_device_scale_factor_(frame_device_scale_factor),
+ frame_size_pixels_(frame_size_pixels),
+ shared_memory_(shared_memory.Pass()) {}
+
+SoftwareFrame::~SoftwareFrame() {
+ if (frame_manager_client_) {
+ frame_manager_client_->SoftwareFrameWasFreed(
+ output_surface_id_, frame_id_);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// SoftwareFrameManager
+
+SoftwareFrameManager::SoftwareFrameManager(
+ base::WeakPtr<SoftwareFrameManagerClient> client)
+ : client_(client) {}
+
+SoftwareFrameManager::~SoftwareFrameManager() {
+ DiscardCurrentFrame();
+}
+
+bool SoftwareFrameManager::SwapToNewFrame(
+ uint32 output_surface_id,
+ const cc::SoftwareFrameData* frame_data,
+ float frame_device_scale_factor,
+ base::ProcessHandle process_handle) {
+
+#ifdef OS_WIN
+ scoped_ptr<base::SharedMemory> shared_memory(
+ new base::SharedMemory(frame_data->handle, true,
+ process_handle));
+#else
+ scoped_ptr<base::SharedMemory> shared_memory(
+ new base::SharedMemory(frame_data->handle, true));
+#endif
+
+ // The NULL handle is used in testing.
+ if (base::SharedMemory::IsHandleValid(shared_memory->handle())) {
+ const size_t size_in_bytes = 4 * frame_data->size.GetArea();
+#ifdef OS_WIN
+ if (!shared_memory->Map(0)) {
+ DLOG(ERROR) << "Unable to map renderer memory.";
+ RecordAction(
+ UserMetricsAction("BadMessageTerminate_SharedMemoryManager1"));
+ return false;
+ }
+
+ if (shared_memory->mapped_size() < size_in_bytes) {
+ DLOG(ERROR) << "Shared memory too small for given rectangle";
+ RecordAction(
+ UserMetricsAction("BadMessageTerminate_SharedMemoryManager2"));
+ return false;
+ }
+#else
+ if (!shared_memory->Map(size_in_bytes)) {
+ DLOG(ERROR) << "Unable to map renderer memory.";
+ RecordAction(
+ UserMetricsAction("BadMessageTerminate_SharedMemoryManager1"));
+ return false;
+ }
+#endif
+ }
+
+ scoped_refptr<SoftwareFrame> next_frame(new SoftwareFrame(
+ client_,
+ output_surface_id,
+ frame_data->id,
+ frame_device_scale_factor,
+ frame_data->size,
+ shared_memory.Pass()));
+ current_frame_.swap(next_frame);
+ return true;
+}
+
+bool SoftwareFrameManager::HasCurrentFrame() const {
+ return current_frame_.get() ? true : false;
+}
+
+void SoftwareFrameManager::DiscardCurrentFrame() {
+ if (!HasCurrentFrame())
+ return;
+ current_frame_ = NULL;
+ RendererFrameManager::GetInstance()->RemoveFrame(this);
+}
+
+void SoftwareFrameManager::SwapToNewFrameComplete(bool visible) {
+ DCHECK(HasCurrentFrame());
+ RendererFrameManager::GetInstance()->AddFrame(this, visible);
+}
+
+void SoftwareFrameManager::SetVisibility(bool visible) {
+ if (HasCurrentFrame()) {
+ RendererFrameManager::GetInstance()->SetFrameVisibility(this, visible);
+ }
+}
+
+uint32 SoftwareFrameManager::GetCurrentFrameOutputSurfaceId() const {
+ DCHECK(HasCurrentFrame());
+ return current_frame_->output_surface_id_;
+}
+
+void SoftwareFrameManager::GetCurrentFrameMailbox(
+ cc::TextureMailbox* mailbox,
+ scoped_ptr<cc::SingleReleaseCallback>* callback) {
+ DCHECK(HasCurrentFrame());
+ *mailbox = cc::TextureMailbox(
+ current_frame_->shared_memory_.get(), current_frame_->frame_size_pixels_);
+ *callback = cc::SingleReleaseCallback::Create(
+ base::Bind(ReleaseMailbox, current_frame_));
+}
+
+void* SoftwareFrameManager::GetCurrentFramePixels() const {
+ DCHECK(HasCurrentFrame());
+ DCHECK(base::SharedMemory::IsHandleValid(
+ current_frame_->shared_memory_->handle()));
+ return current_frame_->shared_memory_->memory();
+}
+
+float SoftwareFrameManager::GetCurrentFrameDeviceScaleFactor() const {
+ DCHECK(HasCurrentFrame());
+ return current_frame_->frame_device_scale_factor_;
+}
+
+gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInPixels() const {
+ DCHECK(HasCurrentFrame());
+ return current_frame_->frame_size_pixels_;
+}
+
+gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInDIP() const {
+ DCHECK(HasCurrentFrame());
+ return ConvertSizeToDIP(current_frame_->frame_device_scale_factor_,
+ current_frame_->frame_size_pixels_);
+}
+
+void SoftwareFrameManager::EvictCurrentFrame() {
+ DCHECK(HasCurrentFrame());
+ DiscardCurrentFrame();
+ if (client_)
+ client_->ReleaseReferencesToSoftwareFrame();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/software_frame_manager.h b/chromium/content/browser/renderer_host/software_frame_manager.h
new file mode 100644
index 00000000000..6d19afd972f
--- /dev/null
+++ b/chromium/content/browser/renderer_host/software_frame_manager.h
@@ -0,0 +1,79 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_SOFTWARE_FRAME_MANAGER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_SOFTWARE_FRAME_MANAGER_H_
+
+#include <list>
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory.h"
+#include "base/memory/weak_ptr.h"
+#include "cc/output/software_frame_data.h"
+#include "cc/resources/single_release_callback.h"
+#include "cc/resources/texture_mailbox.h"
+#include "content/browser/renderer_host/renderer_frame_manager.h"
+#include "content/common/content_export.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+class SoftwareFrame;
+
+class CONTENT_EXPORT SoftwareFrameManagerClient {
+ public:
+ // Called when the memory for the current software frame was freed.
+ virtual void SoftwareFrameWasFreed(
+ uint32 output_surface_id, unsigned frame_id) = 0;
+
+ // Called when the SoftwareFrameMemoryManager has requested that the frame
+ // be evicted. Upon receiving this callback, the client should release any
+ // references that it may hold to the current frame, to ensure that its memory
+ // is freed expediently.
+ virtual void ReleaseReferencesToSoftwareFrame() = 0;
+};
+
+class CONTENT_EXPORT SoftwareFrameManager : public RendererFrameManagerClient {
+ public:
+ explicit SoftwareFrameManager(
+ base::WeakPtr<SoftwareFrameManagerClient> client);
+ virtual ~SoftwareFrameManager();
+
+ // Swaps to a new frame from shared memory. This frame is guaranteed to
+ // not be evicted until SwapToNewFrameComplete is called.
+ bool SwapToNewFrame(
+ uint32 output_surface_id,
+ const cc::SoftwareFrameData* frame_data,
+ float frame_device_scale_factor,
+ base::ProcessHandle process_handle);
+ void SwapToNewFrameComplete(bool visible);
+ void SetVisibility(bool visible);
+ bool HasCurrentFrame() const;
+ void DiscardCurrentFrame();
+ uint32 GetCurrentFrameOutputSurfaceId() const;
+ void GetCurrentFrameMailbox(
+ cc::TextureMailbox* mailbox,
+ scoped_ptr<cc::SingleReleaseCallback>* callback);
+ void* GetCurrentFramePixels() const;
+ float GetCurrentFrameDeviceScaleFactor() const;
+ gfx::Size GetCurrentFrameSizeInPixels() const;
+ gfx::Size GetCurrentFrameSizeInDIP() const;
+
+ private:
+ // Called by SoftwareFrameMemoryManager to demand that the current frame
+ // be evicted.
+ virtual void EvictCurrentFrame() OVERRIDE;
+
+ base::WeakPtr<SoftwareFrameManagerClient> client_;
+
+ // This holds the current software framebuffer.
+ scoped_refptr<SoftwareFrame> current_frame_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareFrameManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_SOFTWARE_FRAME_MANAGER_H_
diff --git a/chromium/content/browser/renderer_host/software_frame_manager_unittest.cc b/chromium/content/browser/renderer_host/software_frame_manager_unittest.cc
new file mode 100644
index 00000000000..e234f57605a
--- /dev/null
+++ b/chromium/content/browser/renderer_host/software_frame_manager_unittest.cc
@@ -0,0 +1,255 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/software_frame_manager.h"
+
+#include <vector>
+
+#include "base/sys_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class FakeSoftwareFrameManagerClient : public SoftwareFrameManagerClient {
+ public:
+ FakeSoftwareFrameManagerClient()
+ : evicted_count_(0), weak_ptr_factory_(this) {
+ software_frame_manager_.reset(new SoftwareFrameManager(
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+ virtual ~FakeSoftwareFrameManagerClient() {}
+ virtual void SoftwareFrameWasFreed(
+ uint32 output_surface_id, unsigned frame_id) OVERRIDE {
+ freed_frames_.push_back(std::make_pair(output_surface_id, frame_id));
+ }
+ virtual void ReleaseReferencesToSoftwareFrame() OVERRIDE {
+ ++evicted_count_;
+ }
+
+ bool SwapToNewFrame(uint32 output_surface, unsigned frame_id) {
+ cc::SoftwareFrameData frame;
+ frame.id = frame_id;
+ frame.size = gfx::Size(1, 1);
+ frame.damage_rect = gfx::Rect(frame.size);
+ frame.handle = base::SharedMemory::NULLHandle();
+ return software_frame_manager_->SwapToNewFrame(
+ output_surface, &frame, 1.0, base::GetCurrentProcessHandle());
+ }
+
+ SoftwareFrameManager* software_frame_manager() {
+ return software_frame_manager_.get();
+ }
+ size_t freed_frame_count() const { return freed_frames_.size(); }
+ size_t evicted_frame_count() const { return evicted_count_; }
+
+ private:
+ std::vector<std::pair<uint32,unsigned> > freed_frames_;
+ size_t evicted_count_;
+
+ scoped_ptr<SoftwareFrameManager> software_frame_manager_;
+ base::WeakPtrFactory<FakeSoftwareFrameManagerClient>
+ weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeSoftwareFrameManagerClient);
+};
+
+class SoftwareFrameManagerTest : public testing::Test {
+ public:
+ SoftwareFrameManagerTest() {}
+ void AllocateClients(size_t num_clients) {
+ for (size_t i = 0; i < num_clients; ++i)
+ clients_.push_back(new FakeSoftwareFrameManagerClient);
+ }
+ void FreeClients() {
+ for (size_t i = 0; i < clients_.size(); ++i)
+ delete clients_[i];
+ clients_.clear();
+ }
+ size_t MaxNumberOfSavedFrames() const {
+ size_t result =
+ RendererFrameManager::GetInstance()->max_number_of_saved_frames();
+ return result;
+ }
+
+ protected:
+ std::vector<FakeSoftwareFrameManagerClient*> clients_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SoftwareFrameManagerTest);
+};
+
+TEST_F(SoftwareFrameManagerTest, DoNotEvictVisible) {
+ // Create twice as many frames as are allowed.
+ AllocateClients(2 * MaxNumberOfSavedFrames());
+
+ // Swap a visible frame to all clients_. Because they are all visible,
+ // the should not be evicted.
+ for (size_t i = 0; i < clients_.size(); ++i) {
+ bool swap_result = clients_[i]->SwapToNewFrame(
+ static_cast<uint32>(i), 0);
+ clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true);
+ EXPECT_TRUE(swap_result);
+ EXPECT_EQ(0u, clients_[i]->evicted_frame_count());
+ EXPECT_EQ(0u, clients_[i]->freed_frame_count());
+ }
+ for (size_t i = 0; i < clients_.size(); ++i) {
+ EXPECT_EQ(0u, clients_[i]->evicted_frame_count());
+ EXPECT_EQ(0u, clients_[i]->freed_frame_count());
+ }
+
+ // Swap another frame and make sure the original was freed (but not evicted).
+ for (size_t i = 0; i < clients_.size(); ++i) {
+ bool swap_result = clients_[i]->SwapToNewFrame(
+ static_cast<uint32>(i), 1);
+ clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true);
+ EXPECT_TRUE(swap_result);
+ EXPECT_EQ(0u, clients_[i]->evicted_frame_count());
+ EXPECT_EQ(1u, clients_[i]->freed_frame_count());
+ }
+ for (size_t i = 0; i < clients_.size(); ++i) {
+ EXPECT_EQ(0u, clients_[i]->evicted_frame_count());
+ EXPECT_EQ(1u, clients_[i]->freed_frame_count());
+ }
+
+ // Mark the frames as nonvisible and make sure they start getting evicted.
+ for (size_t i = 0; i < clients_.size(); ++i) {
+ clients_[i]->software_frame_manager()->SetVisibility(false);
+ if (clients_.size() - i > MaxNumberOfSavedFrames()) {
+ EXPECT_EQ(1u, clients_[i]->evicted_frame_count());
+ EXPECT_EQ(2u, clients_[i]->freed_frame_count());
+ } else {
+ EXPECT_EQ(0u, clients_[i]->evicted_frame_count());
+ EXPECT_EQ(1u, clients_[i]->freed_frame_count());
+ }
+ }
+
+ // Clean up.
+ FreeClients();
+}
+
+TEST_F(SoftwareFrameManagerTest, DoNotEvictDuringSwap) {
+ // Create twice as many frames as are allowed.
+ AllocateClients(2 * MaxNumberOfSavedFrames());
+
+ // Swap a visible frame to all clients_. Because they are all visible,
+ // the should not be evicted.
+ for (size_t i = 0; i < clients_.size(); ++i) {
+ bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0);
+ clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true);
+ EXPECT_TRUE(swap_result);
+ EXPECT_EQ(0u, clients_[i]->evicted_frame_count());
+ EXPECT_EQ(0u, clients_[i]->freed_frame_count());
+ }
+ for (size_t i = 0; i < clients_.size(); ++i) {
+ EXPECT_EQ(0u, clients_[i]->evicted_frame_count());
+ EXPECT_EQ(0u, clients_[i]->freed_frame_count());
+ }
+
+ // Now create a test non-visible client, and swap a non-visible frame in.
+ scoped_ptr<FakeSoftwareFrameManagerClient> test_client(
+ new FakeSoftwareFrameManagerClient);
+ test_client->software_frame_manager()->SetVisibility(false);
+ {
+ bool swap_result = test_client->SwapToNewFrame(
+ static_cast<uint32>(500), 0);
+ EXPECT_TRUE(swap_result);
+ EXPECT_EQ(0u, test_client->evicted_frame_count());
+ EXPECT_EQ(0u, test_client->freed_frame_count());
+ test_client->software_frame_manager()->SwapToNewFrameComplete(false);
+ EXPECT_EQ(1u, test_client->evicted_frame_count());
+ EXPECT_EQ(1u, test_client->freed_frame_count());
+ }
+
+ // Clean up.
+ FreeClients();
+}
+
+TEST_F(SoftwareFrameManagerTest, Cleanup) {
+ // Create twice as many frames as are allowed.
+ AllocateClients(2 * MaxNumberOfSavedFrames());
+
+ // Swap a visible frame to all clients_. Because they are all visible,
+ // the should not be evicted.
+ for (size_t i = 0; i < clients_.size(); ++i) {
+ bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0);
+ clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true);
+ EXPECT_TRUE(swap_result);
+ EXPECT_EQ(0u, clients_[i]->evicted_frame_count());
+ EXPECT_EQ(0u, clients_[i]->freed_frame_count());
+ }
+
+ // Destroy them.
+ FreeClients();
+
+ // Create the maximum number of frames, all non-visible. They should not
+ // be evicted, because the previous frames were cleaned up at destruction.
+ AllocateClients(MaxNumberOfSavedFrames());
+ for (size_t i = 0; i < clients_.size(); ++i) {
+ cc::SoftwareFrameData frame;
+ bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0);
+ clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true);
+ EXPECT_TRUE(swap_result);
+ EXPECT_EQ(0u, clients_[i]->evicted_frame_count());
+ EXPECT_EQ(0u, clients_[i]->freed_frame_count());
+ }
+ for (size_t i = 0; i < clients_.size(); ++i) {
+ EXPECT_EQ(0u, clients_[i]->evicted_frame_count());
+ EXPECT_EQ(0u, clients_[i]->freed_frame_count());
+ }
+
+ // Clean up.
+ FreeClients();
+}
+
+TEST_F(SoftwareFrameManagerTest, EvictVersusFree) {
+ // Create twice as many frames as are allowed and swap a visible frame to all
+ // clients_. Because they are all visible, the should not be evicted.
+ AllocateClients(2 * MaxNumberOfSavedFrames());
+ for (size_t i = 0; i < clients_.size(); ++i) {
+ clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0);
+ clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true);
+ }
+
+ // Create a test client with a frame that is not evicted.
+ scoped_ptr<FakeSoftwareFrameManagerClient> test_client(
+ new FakeSoftwareFrameManagerClient);
+ bool swap_result = test_client->SwapToNewFrame(static_cast<uint32>(500), 0);
+ EXPECT_TRUE(swap_result);
+ test_client->software_frame_manager()->SwapToNewFrameComplete(true);
+ EXPECT_EQ(0u, test_client->evicted_frame_count());
+ EXPECT_EQ(0u, test_client->freed_frame_count());
+
+ // Take out a reference on the current frame and make the memory manager
+ // evict it. The frame will not be freed until this reference is released.
+ cc::TextureMailbox mailbox;
+ scoped_ptr<cc::SingleReleaseCallback> callback;
+ test_client->software_frame_manager()->GetCurrentFrameMailbox(
+ &mailbox, &callback);
+ test_client->software_frame_manager()->SetVisibility(false);
+ EXPECT_EQ(1u, test_client->evicted_frame_count());
+ EXPECT_EQ(0u, test_client->freed_frame_count());
+
+ // Swap a few frames. The frames will be freed as they are swapped out.
+ for (size_t frame = 0; frame < 10; ++frame) {
+ bool swap_result = test_client->SwapToNewFrame(
+ static_cast<uint32>(500), 1 + static_cast<int>(frame));
+ EXPECT_TRUE(swap_result);
+ test_client->software_frame_manager()->SwapToNewFrameComplete(true);
+ EXPECT_EQ(frame, test_client->freed_frame_count());
+ EXPECT_EQ(1u, test_client->evicted_frame_count());
+ }
+
+ // The reference to the frame that we didn't free is in the callback
+ // object. It will go away when the callback is destroyed.
+ EXPECT_EQ(9u, test_client->freed_frame_count());
+ EXPECT_EQ(1u, test_client->evicted_frame_count());
+ callback->Run(0, false);
+ callback.reset();
+ EXPECT_EQ(10u, test_client->freed_frame_count());
+ EXPECT_EQ(1u, test_client->evicted_frame_count());
+
+ FreeClients();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc b/chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc
deleted file mode 100644
index d382cd57565..00000000000
--- a/chromium/content/browser/renderer_host/surface_texture_transport_client_android.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/surface_texture_transport_client_android.h"
-
-#include <android/native_window_jni.h>
-
-#include "base/bind.h"
-#include "cc/layers/video_layer.h"
-#include "content/browser/gpu/gpu_surface_tracker.h"
-#include "content/browser/renderer_host/compositor_impl_android.h"
-#include "content/browser/renderer_host/image_transport_factory_android.h"
-#include "content/public/browser/browser_thread.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-#include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/khronos/GLES2/gl2ext.h"
-#include "ui/gl/android/surface_texture.h"
-
-namespace content {
-
-namespace {
-
-static const uint32 kGLTextureExternalOES = 0x8D65;
-
-class SurfaceRefAndroid : public GpuSurfaceTracker::SurfaceRef {
- public:
- SurfaceRefAndroid(
- const scoped_refptr<gfx::SurfaceTexture>& surface,
- ANativeWindow* window)
- : surface_(surface),
- window_(window) {
- ANativeWindow_acquire(window_);
- }
-
- private:
- virtual ~SurfaceRefAndroid() {
- DCHECK(window_);
- ANativeWindow_release(window_);
- }
-
- scoped_refptr<gfx::SurfaceTexture> surface_;
- ANativeWindow* window_;
-};
-
-} // anonymous namespace
-
-SurfaceTextureTransportClient::SurfaceTextureTransportClient()
- : window_(NULL),
- texture_id_(0),
- texture_mailbox_sync_point_(0),
- surface_id_(0),
- weak_factory_(this) {
-}
-
-SurfaceTextureTransportClient::~SurfaceTextureTransportClient() {
-}
-
-scoped_refptr<cc::Layer> SurfaceTextureTransportClient::Initialize() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // Use a SurfaceTexture to stream frames to the UI thread.
- video_layer_ = cc::VideoLayer::Create(this);
-
- surface_texture_ = new gfx::SurfaceTexture(0);
- surface_texture_->SetFrameAvailableCallback(
- base::Bind(
- &SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable,
- weak_factory_.GetWeakPtr()));
- surface_texture_->DetachFromGLContext();
- return video_layer_.get();
-}
-
-gfx::GLSurfaceHandle
-SurfaceTextureTransportClient::GetCompositingSurface(int surface_id) {
- DCHECK(surface_id);
- surface_id_ = surface_id;
-
- if (!window_) {
- window_ = surface_texture_->CreateSurface();
-
- GpuSurfaceTracker::Get()->SetNativeWidget(
- surface_id, window_, new SurfaceRefAndroid(surface_texture_, window_));
- // SurfaceRefAndroid took ownership (and an extra ref to) window_.
- ANativeWindow_release(window_);
- }
-
- return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_DIRECT);
-}
-
-void SurfaceTextureTransportClient::SetSize(const gfx::Size& size) {
- if (size.width() > 0 && size.height() > 0) {
- surface_texture_->SetDefaultBufferSize(size.width(), size.height());
- }
- video_layer_->SetBounds(size);
- video_frame_ = NULL;
-}
-
-scoped_refptr<media::VideoFrame> SurfaceTextureTransportClient::
- GetCurrentFrame() {
- if (!texture_id_) {
- WebKit::WebGraphicsContext3D* context =
- ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
- context->makeContextCurrent();
- texture_id_ = context->createTexture();
- context->bindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
- context->flush();
- surface_texture_->AttachToGLContext();
-
- context->genMailboxCHROMIUM(texture_mailbox_.name);
- context->produceTextureCHROMIUM(kGLTextureExternalOES,
- texture_mailbox_.name);
- texture_mailbox_sync_point_ = context->insertSyncPoint();
- }
- if (!video_frame_.get()) {
- const gfx::Size size = video_layer_->bounds();
- video_frame_ = media::VideoFrame::WrapNativeTexture(
- new media::VideoFrame::MailboxHolder(
- texture_mailbox_,
- texture_mailbox_sync_point_,
- media::VideoFrame::MailboxHolder::TextureNoLongerNeededCallback()),
- kGLTextureExternalOES,
- size,
- gfx::Rect(gfx::Point(), size),
- size,
- base::TimeDelta(),
- media::VideoFrame::ReadPixelsCB(),
- base::Closure());
- }
- surface_texture_->UpdateTexImage();
-
- return video_frame_;
-}
-
-void SurfaceTextureTransportClient::PutCurrentFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
-}
-
-void SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- video_layer_->SetNeedsDisplay();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/surface_texture_transport_client_android.h b/chromium/content/browser/renderer_host/surface_texture_transport_client_android.h
deleted file mode 100644
index 5a000bb246e..00000000000
--- a/chromium/content/browser/renderer_host/surface_texture_transport_client_android.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.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_SURFACE_TEXTURE_TRANSPORT_CLIENT_ANDROID_H_
-#define CONTENT_BROWSER_RENDERER_HOST_SURFACE_TEXTURE_TRANSPORT_CLIENT_ANDROID_H_
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "cc/layers/video_frame_provider.h"
-#include "gpu/command_buffer/common/mailbox.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/size.h"
-
-struct ANativeWindow;
-
-namespace cc {
-class Layer;
-class VideoLayer;
-}
-
-namespace gfx {
-class SurfaceTexture;
-}
-
-namespace content {
-
-class SurfaceTextureTransportClient : public cc::VideoFrameProvider {
- public:
- SurfaceTextureTransportClient();
- virtual ~SurfaceTextureTransportClient();
-
- scoped_refptr<cc::Layer> Initialize();
- gfx::GLSurfaceHandle GetCompositingSurface(int surface_id);
- void SetSize(const gfx::Size& size);
-
- // cc::VideoFrameProvider implementation.
- virtual void SetVideoFrameProviderClient(Client*) OVERRIDE {}
- virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE;
- virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame)
- OVERRIDE;
-
- private:
- void OnSurfaceTextureFrameAvailable();
-
- scoped_refptr<cc::VideoLayer> video_layer_;
- scoped_refptr<gfx::SurfaceTexture> surface_texture_;
- ANativeWindow* window_;
- scoped_refptr<media::VideoFrame> video_frame_;
- uint32 texture_id_;
- gpu::Mailbox texture_mailbox_;
- uint32 texture_mailbox_sync_point_;
- int surface_id_;
- base::WeakPtrFactory<SurfaceTextureTransportClient> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(SurfaceTextureTransportClient);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_SURFACE_TEXTURE_TRANSPORT_CLIENT_ANDROID_H_
diff --git a/chromium/content/browser/renderer_host/synthetic_gesture_calculator.cc b/chromium/content/browser/renderer_host/synthetic_gesture_calculator.cc
deleted file mode 100644
index 9816df93b48..00000000000
--- a/chromium/content/browser/renderer_host/synthetic_gesture_calculator.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/synthetic_gesture_calculator.h"
-
-
-namespace {
-
-const float kDefaultPositionDelta = 10.0f;
-
-}
-
-
-namespace content {
-
-SyntheticGestureCalculator::SyntheticGestureCalculator() {
-}
-
-SyntheticGestureCalculator::~SyntheticGestureCalculator() {
-}
-
-float SyntheticGestureCalculator::GetDelta(
- base::TimeTicks now, base::TimeDelta desired_interval) {
- float position_delta = kDefaultPositionDelta;
- if (!last_tick_time_.is_null()) {
- float velocity = kDefaultPositionDelta /
- (float)desired_interval.InMillisecondsF();
- float time_delta = (now - last_tick_time_).InMillisecondsF();
- position_delta = velocity * time_delta;
- }
-
- last_tick_time_ = now;
- return position_delta;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/synthetic_gesture_calculator.h b/chromium/content/browser/renderer_host/synthetic_gesture_calculator.h
deleted file mode 100644
index c2af4978ac4..00000000000
--- a/chromium/content/browser/renderer_host/synthetic_gesture_calculator.h
+++ /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.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CALCULATOR_H_
-#define CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CALCULATOR_H_
-
-#include "base/time/time.h"
-
-namespace content {
-
-// A utility class to calculate the delta for synthetic gesture events.
-class SyntheticGestureCalculator {
- public:
- SyntheticGestureCalculator();
- ~SyntheticGestureCalculator();
-
- float GetDelta(base::TimeTicks now, base::TimeDelta desired_interval);
-
- private:
- base::TimeTicks last_tick_time_;
-
- DISALLOW_COPY_AND_ASSIGN(SyntheticGestureCalculator);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CALCULATOR_H_
diff --git a/chromium/content/browser/renderer_host/synthetic_gesture_controller.cc b/chromium/content/browser/renderer_host/synthetic_gesture_controller.cc
deleted file mode 100644
index 46c4329da6b..00000000000
--- a/chromium/content/browser/renderer_host/synthetic_gesture_controller.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/synthetic_gesture_controller.h"
-
-#include "base/debug/trace_event.h"
-#include "base/message_loop/message_loop.h"
-#include "content/common/view_messages.h"
-#include "content/port/browser/render_widget_host_view_port.h"
-#include "content/port/browser/synthetic_gesture.h"
-#include "content/public/browser/render_widget_host.h"
-
-namespace content {
-
-namespace {
-
-// How many milliseconds apart synthetic scroll messages should be sent.
-const int kSyntheticGestureMessageIntervalMs = 7;
-
-} // namespace
-
-SyntheticGestureController::SyntheticGestureController()
- : rwh_(NULL) {
-}
-
-SyntheticGestureController::~SyntheticGestureController() {
-}
-
-void SyntheticGestureController::BeginSmoothScroll(
- RenderWidgetHostViewPort* view,
- const ViewHostMsg_BeginSmoothScroll_Params& params) {
- if (pending_synthetic_gesture_.get())
- return;
-
- rwh_ = view->GetRenderWidgetHost();
- pending_synthetic_gesture_ = view->CreateSmoothScrollGesture(
- params.scroll_down,
- params.pixels_to_scroll,
- params.mouse_event_x,
- params.mouse_event_y);
-
- TRACE_EVENT_ASYNC_BEGIN0("benchmark", "SyntheticGestureController::running",
- pending_synthetic_gesture_);
- timer_.Start(FROM_HERE, GetSyntheticGestureMessageInterval(), this,
- &SyntheticGestureController::OnTimer);
-}
-
-void SyntheticGestureController::BeginPinch(
- RenderWidgetHostViewPort* view,
- const ViewHostMsg_BeginPinch_Params& params) {
- if (pending_synthetic_gesture_.get())
- return;
-
- rwh_ = view->GetRenderWidgetHost();
- pending_synthetic_gesture_ = view->CreatePinchGesture(
- params.zoom_in,
- params.pixels_to_move,
- params.anchor_x,
- params.anchor_y);
-
- TRACE_EVENT_ASYNC_BEGIN0("benchmark", "SyntheticGestureController::running",
- pending_synthetic_gesture_);
- timer_.Start(FROM_HERE, GetSyntheticGestureMessageInterval(), this,
- &SyntheticGestureController::OnTimer);
-}
-
-base::TimeDelta
- SyntheticGestureController::GetSyntheticGestureMessageInterval() const {
- return base::TimeDelta::FromMilliseconds(kSyntheticGestureMessageIntervalMs);
-}
-
-void SyntheticGestureController::OnTimer() {
- base::TimeTicks now = base::TimeTicks::Now();
- if (!pending_synthetic_gesture_->ForwardInputEvents(now, rwh_)) {
- timer_.Stop();
- TRACE_EVENT_ASYNC_END0("benchmark", "SyntheticGestureController::running",
- pending_synthetic_gesture_);
- pending_synthetic_gesture_ = NULL;
- rwh_->Send(new ViewMsg_SyntheticGestureCompleted(rwh_->GetRoutingID()));
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/synthetic_gesture_controller.h b/chromium/content/browser/renderer_host/synthetic_gesture_controller.h
deleted file mode 100644
index 8826aaddf3a..00000000000
--- a/chromium/content/browser/renderer_host/synthetic_gesture_controller.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CONTROLLER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CONTROLLER_H_
-
-#include <map>
-
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "content/common/content_export.h"
-
-struct ViewHostMsg_BeginPinch_Params;
-struct ViewHostMsg_BeginSmoothScroll_Params;
-
-namespace content {
-
-class RenderWidgetHost;
-class RenderWidgetHostViewPort;
-class SyntheticGesture;
-
-// Controls SyntheticGestures, used to inject synthetic events
-// for performance test harness.
-class CONTENT_EXPORT SyntheticGestureController {
- public:
- SyntheticGestureController();
- ~SyntheticGestureController();
-
- // Initiates a synthetic event stream to simulate a smooth scroll.
- void BeginSmoothScroll(RenderWidgetHostViewPort* view,
- const ViewHostMsg_BeginSmoothScroll_Params& params);
-
- // Initiates a synthetic event stream to simulate a pinch-to-zoom.
- void BeginPinch(RenderWidgetHostViewPort* view,
- const ViewHostMsg_BeginPinch_Params& params);
-
- base::TimeDelta GetSyntheticGestureMessageInterval() const;
-
- private:
- // Called periodically to advance the active scroll gesture after being
- // initiated by OnBeginSmoothScroll.
- void OnTimer();
-
- base::RepeatingTimer<SyntheticGestureController> timer_;
-
- RenderWidgetHost* rwh_;
-
- scoped_refptr<SyntheticGesture> pending_synthetic_gesture_;
-
- DISALLOW_COPY_AND_ASSIGN(SyntheticGestureController);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_SYNTHETIC_GESTURE_CONTROLLER_H_
diff --git a/chromium/content/browser/renderer_host/synthetic_gesture_controller_unittest.cc b/chromium/content/browser/renderer_host/synthetic_gesture_controller_unittest.cc
deleted file mode 100644
index 7fb9ba9e601..00000000000
--- a/chromium/content/browser/renderer_host/synthetic_gesture_controller_unittest.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/time/time.h"
-#include "content/browser/renderer_host/render_widget_host_delegate.h"
-#include "content/browser/renderer_host/synthetic_gesture_controller.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
-#include "content/common/view_messages.h"
-#include "content/port/browser/render_widget_host_view_port.h"
-#include "content/port/browser/synthetic_gesture.h"
-#include "content/public/test/mock_render_process_host.h"
-#include "content/public/test/test_browser_context.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(USE_AURA)
-#include "ui/aura/env.h"
-#include "ui/aura/test/test_screen.h"
-#endif
-
-using base::TimeDelta;
-
-namespace content {
-
-namespace {
-
-class MockSyntheticGesture : public SyntheticGesture {
- public:
- MockSyntheticGesture() :
- called_(0) {
- }
-
- // SmoothScrollGesture implementation:
- virtual bool ForwardInputEvents(base::TimeTicks now,
- RenderWidgetHost* host) OVERRIDE {
- ++called_;
- return true;
- }
-
- int called_;
-
- protected:
- virtual ~MockSyntheticGesture() {
- }
-};
-
-class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
- public:
- MockRenderWidgetHostDelegate() {
- }
- virtual ~MockRenderWidgetHostDelegate() {}
-};
-
-class MockRenderWidgetHost : public RenderWidgetHostImpl {
- public:
- MockRenderWidgetHost(
- RenderWidgetHostDelegate* delegate,
- RenderProcessHost* process,
- int routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id, false) {
- }
- virtual ~MockRenderWidgetHost() {}
-};
-
-class TestView : public TestRenderWidgetHostView {
- public:
- explicit TestView(RenderWidgetHostImpl* rwh)
- : TestRenderWidgetHostView(rwh),
- mock_gesture_(NULL) {
- }
- virtual ~TestView() {}
-
- // TestRenderWidgetHostView implementation:
- virtual SyntheticGesture* CreateSmoothScrollGesture(
- bool scroll_down, int pixels_to_scroll, int mouse_event_x,
- int mouse_event_y) OVERRIDE {
- mock_gesture_ = new MockSyntheticGesture();
- return mock_gesture_;
- }
-
- virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE {
- return rwh_;
- }
-
- MockSyntheticGesture* mock_gesture_;
-};
-
-class SyntheticGestureControllerTest : public testing::Test {
- public:
- SyntheticGestureControllerTest() : process_(NULL) {
- }
- virtual ~SyntheticGestureControllerTest() {}
-
- protected:
- // testing::Test implementation:
- virtual void SetUp() OVERRIDE {
- browser_context_.reset(new TestBrowserContext());
- delegate_.reset(new MockRenderWidgetHostDelegate());
- process_ = new MockRenderProcessHost(browser_context_.get());
-#if defined(USE_AURA)
- screen_.reset(aura::TestScreen::Create());
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
-#endif
- host_.reset(
- new MockRenderWidgetHost(delegate_.get(), process_, MSG_ROUTING_NONE));
- view_.reset(new TestView(host_.get()));
- host_->SetView(view_.get());
- host_->Init();
- }
-
- virtual void TearDown() OVERRIDE {
- view_.reset();
- host_.reset();
- delegate_.reset();
- process_ = NULL;
- browser_context_.reset();
-
-#if defined(USE_AURA)
- aura::Env::DeleteInstance();
- screen_.reset();
-#endif
-
- // Process all pending tasks to avoid leaks.
- base::MessageLoop::current()->RunUntilIdle();
- }
-
- void PostQuitMessageAndRun() {
- // Allow the message loop to process pending synthetic scrolls, then quit.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitClosure(),
- TimeDelta::FromMilliseconds(
- controller_.GetSyntheticGestureMessageInterval().InMilliseconds() *
- 3));
- base::MessageLoop::current()->Run();
- }
-
- base::MessageLoopForUI message_loop_;
-
- scoped_ptr<TestBrowserContext> browser_context_;
- MockRenderProcessHost* process_; // Deleted automatically by the widget.
- scoped_ptr<MockRenderWidgetHostDelegate> delegate_;
- scoped_ptr<MockRenderWidgetHost> host_;
- scoped_ptr<TestView> view_;
-#if defined(USE_AURA)
- scoped_ptr<gfx::Screen> screen_;
-#endif
-
- SyntheticGestureController controller_;
-};
-
-TEST_F(SyntheticGestureControllerTest, Tick) {
- ViewHostMsg_BeginSmoothScroll_Params params;
- params.scroll_down = true;
- params.pixels_to_scroll = 10;
- params.mouse_event_x = 20;
- params.mouse_event_y = 30;
-
- // Begin a smooth scroll, |mock_gesture_| won't be |called| until we post
- // message.
- controller_.BeginSmoothScroll(view_.get(), params);
- EXPECT_TRUE(view_->mock_gesture_ != NULL);
- EXPECT_EQ(0, view_->mock_gesture_->called_);
-
- PostQuitMessageAndRun();
- const int current_ticks = view_->mock_gesture_->called_;
- EXPECT_LT(0, current_ticks);
-
- // Ensure it won't start another smooth scroll.
- MockSyntheticGesture* original_gesture = view_->mock_gesture_;
- controller_.BeginSmoothScroll(view_.get(), params);
- PostQuitMessageAndRun();
- EXPECT_EQ(original_gesture, view_->mock_gesture_);
-
- // Ensure the smooth scroll is ticked.
- PostQuitMessageAndRun();
- EXPECT_LT(current_ticks, view_->mock_gesture_->called_);
-}
-
-} // namespace
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/test_backing_store.cc b/chromium/content/browser/renderer_host/test_backing_store.cc
deleted file mode 100644
index 74fa44d4872..00000000000
--- a/chromium/content/browser/renderer_host/test_backing_store.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/test_backing_store.h"
-
-namespace content {
-
-TestBackingStore::TestBackingStore(RenderWidgetHost* widget,
- const gfx::Size& size)
- : BackingStore(widget, size) {
-}
-
-TestBackingStore::~TestBackingStore() {
-}
-
-void TestBackingStore::PaintToBackingStore(
- RenderProcessHost* process,
- TransportDIB::Id bitmap,
- const gfx::Rect& bitmap_rect,
- const std::vector<gfx::Rect>& copy_rects,
- float scale_factor,
- const base::Closure& completion_callback,
- bool* scheduled_completion_callback) {
- *scheduled_completion_callback = false;
-}
-
-bool TestBackingStore::CopyFromBackingStore(const gfx::Rect& rect,
- skia::PlatformBitmap* output) {
- return false;
-}
-
-void TestBackingStore::ScrollBackingStore(const gfx::Vector2d& delta,
- const gfx::Rect& clip_rect,
- const gfx::Size& view_size) {
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/test_backing_store.h b/chromium/content/browser/renderer_host/test_backing_store.h
deleted file mode 100644
index 4b76851c742..00000000000
--- a/chromium/content/browser/renderer_host/test_backing_store.h
+++ /dev/null
@@ -1,39 +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_RENDERER_HOST_TEST_TEST_BACKING_STORE_H_
-#define CONTENT_BROWSER_RENDERER_HOST_TEST_TEST_BACKING_STORE_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "content/browser/renderer_host/backing_store.h"
-
-namespace content {
-
-class TestBackingStore : public BackingStore {
- public:
- TestBackingStore(RenderWidgetHost* widget, const gfx::Size& size);
- virtual ~TestBackingStore();
-
- // BackingStore implementation.
- virtual void PaintToBackingStore(
- RenderProcessHost* process,
- TransportDIB::Id bitmap,
- const gfx::Rect& bitmap_rect,
- const std::vector<gfx::Rect>& copy_rects,
- float scale_factor,
- const base::Closure& completion_callback,
- bool* scheduled_completion_callback) OVERRIDE;
- virtual bool CopyFromBackingStore(const gfx::Rect& rect,
- skia::PlatformBitmap* output) OVERRIDE;
- virtual void ScrollBackingStore(const gfx::Vector2d& delta,
- const gfx::Rect& clip_rect,
- const gfx::Size& view_size) OVERRIDE;
- private:
- DISALLOW_COPY_AND_ASSIGN(TestBackingStore);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_TEST_TEST_BACKING_STORE_H_
diff --git a/chromium/content/browser/renderer_host/test_render_view_host.cc b/chromium/content/browser/renderer_host/test_render_view_host.cc
deleted file mode 100644
index caf79cf8583..00000000000
--- a/chromium/content/browser/renderer_host/test_render_view_host.cc
+++ /dev/null
@@ -1,418 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/test_render_view_host.h"
-
-#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
-#include "content/browser/dom_storage/session_storage_namespace_impl.h"
-#include "content/browser/renderer_host/test_backing_store.h"
-#include "content/browser/site_instance_impl.h"
-#include "content/common/dom_storage/dom_storage_types.h"
-#include "content/common/view_messages.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/page_state.h"
-#include "content/test/test_web_contents.h"
-#include "media/base/video_frame.h"
-#include "ui/gfx/rect.h"
-#include "webkit/common/webpreferences.h"
-
-namespace content {
-
-namespace {
-
-const int64 kFrameId = 13UL;
-
-} // namespace
-
-
-void InitNavigateParams(ViewHostMsg_FrameNavigate_Params* params,
- int page_id,
- const GURL& url,
- PageTransition transition) {
- params->page_id = page_id;
- params->url = url;
- params->referrer = Referrer();
- params->transition = transition;
- params->redirects = std::vector<GURL>();
- params->should_update_history = false;
- params->searchable_form_url = GURL();
- params->searchable_form_encoding = std::string();
- params->security_info = std::string();
- params->gesture = NavigationGestureUser;
- params->was_within_same_page = false;
- params->is_post = false;
- params->page_state = PageState::CreateFromURL(url);
-}
-
-TestRenderWidgetHostView::TestRenderWidgetHostView(RenderWidgetHost* rwh)
- : rwh_(RenderWidgetHostImpl::From(rwh)),
- is_showing_(false),
- did_swap_compositor_frame_(false) {
- rwh_->SetView(this);
-}
-
-TestRenderWidgetHostView::~TestRenderWidgetHostView() {
-}
-
-RenderWidgetHost* TestRenderWidgetHostView::GetRenderWidgetHost() const {
- return NULL;
-}
-
-gfx::NativeView TestRenderWidgetHostView::GetNativeView() const {
- return NULL;
-}
-
-gfx::NativeViewId TestRenderWidgetHostView::GetNativeViewId() const {
- return 0;
-}
-
-gfx::NativeViewAccessible TestRenderWidgetHostView::GetNativeViewAccessible() {
- return NULL;
-}
-
-bool TestRenderWidgetHostView::HasFocus() const {
- return true;
-}
-
-bool TestRenderWidgetHostView::IsSurfaceAvailableForCopy() const {
- return true;
-}
-
-void TestRenderWidgetHostView::Show() {
- is_showing_ = true;
-}
-
-void TestRenderWidgetHostView::Hide() {
- is_showing_ = false;
-}
-
-bool TestRenderWidgetHostView::IsShowing() {
- return is_showing_;
-}
-
-void TestRenderWidgetHostView::RenderProcessGone(base::TerminationStatus status,
- int error_code) {
- delete this;
-}
-
-void TestRenderWidgetHostView::Destroy() { delete this; }
-
-gfx::Rect TestRenderWidgetHostView::GetViewBounds() const {
- return gfx::Rect();
-}
-
-BackingStore* TestRenderWidgetHostView::AllocBackingStore(
- const gfx::Size& size) {
- return new TestBackingStore(rwh_, size);
-}
-
-void TestRenderWidgetHostView::CopyFromCompositingSurface(
- const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback) {
- callback.Run(false, SkBitmap());
-}
-
-void TestRenderWidgetHostView::CopyFromCompositingSurfaceToVideoFrame(
- const gfx::Rect& src_subrect,
- const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback) {
- callback.Run(false);
-}
-
-bool TestRenderWidgetHostView::CanCopyToVideoFrame() const {
- return false;
-}
-
-void TestRenderWidgetHostView::OnAcceleratedCompositingStateChange() {
-}
-
-void TestRenderWidgetHostView::AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
- int gpu_host_id) {
-}
-
-void TestRenderWidgetHostView::AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
- int gpu_host_id) {
-}
-
-void TestRenderWidgetHostView::AcceleratedSurfaceSuspend() {
-}
-
-bool TestRenderWidgetHostView::HasAcceleratedSurface(
- const gfx::Size& desired_size) {
- return false;
-}
-
-#if defined(OS_MACOSX)
-
-void TestRenderWidgetHostView::AboutToWaitForBackingStoreMsg() {
-}
-
-void TestRenderWidgetHostView::SetActive(bool active) {
- // <viettrungluu@gmail.com>: Do I need to do anything here?
-}
-
-bool TestRenderWidgetHostView::SupportsSpeech() const {
- return false;
-}
-
-void TestRenderWidgetHostView::SpeakSelection() {
-}
-
-bool TestRenderWidgetHostView::IsSpeaking() const {
- return false;
-}
-
-void TestRenderWidgetHostView::StopSpeaking() {
-}
-
-bool TestRenderWidgetHostView::PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) {
- return false;
-}
-
-#elif defined(OS_WIN) && !defined(USE_AURA)
-void TestRenderWidgetHostView::WillWmDestroy() {
-}
-#endif
-
-gfx::Rect TestRenderWidgetHostView::GetBoundsInRootWindow() {
- return gfx::Rect();
-}
-
-#if defined(TOOLKIT_GTK)
-GdkEventButton* TestRenderWidgetHostView::GetLastMouseDown() {
- return NULL;
-}
-
-gfx::NativeView TestRenderWidgetHostView::BuildInputMethodsGtkMenu() {
- return NULL;
-}
-#endif // defined(TOOLKIT_GTK)
-
-void TestRenderWidgetHostView::OnSwapCompositorFrame(
- uint32 output_surface_id,
- scoped_ptr<cc::CompositorFrame> frame) {
- did_swap_compositor_frame_ = true;
-}
-
-
-gfx::GLSurfaceHandle TestRenderWidgetHostView::GetCompositingSurface() {
- return gfx::GLSurfaceHandle();
-}
-
-#if defined(OS_WIN) && !defined(USE_AURA)
-void TestRenderWidgetHostView::SetClickthroughRegion(SkRegion* region) {
-}
-#endif
-
-bool TestRenderWidgetHostView::LockMouse() {
- return false;
-}
-
-void TestRenderWidgetHostView::UnlockMouse() {
-}
-
-#if defined(OS_WIN) && defined(USE_AURA)
-void TestRenderWidgetHostView::SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) {
-}
-#endif
-
-TestRenderViewHost::TestRenderViewHost(
- SiteInstance* instance,
- RenderViewHostDelegate* delegate,
- RenderWidgetHostDelegate* widget_delegate,
- int routing_id,
- int main_frame_routing_id,
- bool swapped_out)
- : RenderViewHostImpl(instance,
- delegate,
- widget_delegate,
- routing_id,
- main_frame_routing_id,
- swapped_out,
- false /* hidden */),
- render_view_created_(false),
- delete_counter_(NULL),
- simulate_fetch_via_proxy_(false),
- simulate_history_list_was_cleared_(false),
- contents_mime_type_("text/html"),
- opener_route_id_(MSG_ROUTING_NONE) {
- // TestRenderWidgetHostView installs itself into this->view_ in its
- // constructor, and deletes itself when TestRenderWidgetHostView::Destroy() is
- // called.
- new TestRenderWidgetHostView(this);
-
- main_frame_id_ = kFrameId;
-}
-
-TestRenderViewHost::~TestRenderViewHost() {
- if (delete_counter_)
- ++*delete_counter_;
-}
-
-bool TestRenderViewHost::CreateRenderView(
- const string16& frame_name,
- int opener_route_id,
- int32 max_page_id) {
- DCHECK(!render_view_created_);
- render_view_created_ = true;
- opener_route_id_ = opener_route_id;
- return true;
-}
-
-bool TestRenderViewHost::IsRenderViewLive() const {
- return render_view_created_;
-}
-
-void TestRenderViewHost::SendNavigate(int page_id, const GURL& url) {
- SendNavigateWithTransition(page_id, url, PAGE_TRANSITION_LINK);
-}
-
-void TestRenderViewHost::SendFailedNavigate(int page_id, const GURL& url) {
- SendNavigateWithTransitionAndResponseCode(
- page_id, url, PAGE_TRANSITION_LINK, 500);
-}
-
-void TestRenderViewHost::SendNavigateWithTransition(
- int page_id, const GURL& url, PageTransition transition) {
- SendNavigateWithTransitionAndResponseCode(page_id, url, transition, 200);
-}
-
-void TestRenderViewHost::SendNavigateWithOriginalRequestURL(
- int page_id, const GURL& url, const GURL& original_request_url) {
- OnDidStartProvisionalLoadForFrame(kFrameId, -1, true, url);
- SendNavigateWithParameters(page_id, url, PAGE_TRANSITION_LINK,
- original_request_url, 200, 0);
-}
-
-void TestRenderViewHost::SendNavigateWithFile(
- int page_id, const GURL& url, const base::FilePath& file_path) {
- SendNavigateWithParameters(page_id, url, PAGE_TRANSITION_LINK,
- url, 200, &file_path);
-}
-
-void TestRenderViewHost::SendNavigateWithTransitionAndResponseCode(
- int page_id, const GURL& url, PageTransition transition,
- int response_code) {
- // DidStartProvisionalLoad may delete the pending entry that holds |url|,
- // so we keep a copy of it to use in SendNavigateWithParameters.
- GURL url_copy(url);
- OnDidStartProvisionalLoadForFrame(kFrameId, -1, true, url_copy);
- SendNavigateWithParameters(page_id, url_copy, transition, url_copy,
- response_code, 0);
-}
-
-void TestRenderViewHost::SendNavigateWithParameters(
- int page_id, const GURL& url, PageTransition transition,
- const GURL& original_request_url, int response_code,
- const base::FilePath* file_path_for_history_item) {
- ViewHostMsg_FrameNavigate_Params params;
- params.page_id = page_id;
- params.frame_id = kFrameId;
- params.url = url;
- params.referrer = Referrer();
- params.transition = transition;
- params.redirects = std::vector<GURL>();
- params.should_update_history = true;
- params.searchable_form_url = GURL();
- params.searchable_form_encoding = std::string();
- params.security_info = std::string();
- params.gesture = NavigationGestureUser;
- params.contents_mime_type = contents_mime_type_;
- params.is_post = false;
- params.was_within_same_page = false;
- params.http_status_code = response_code;
- params.socket_address.set_host("2001:db8::1");
- params.socket_address.set_port(80);
- params.was_fetched_via_proxy = simulate_fetch_via_proxy_;
- params.history_list_was_cleared = simulate_history_list_was_cleared_;
- params.original_request_url = original_request_url;
-
- params.page_state = PageState::CreateForTesting(
- url,
- false,
- file_path_for_history_item ? "data" : NULL,
- file_path_for_history_item);
-
- ViewHostMsg_FrameNavigate msg(1, params);
- OnNavigate(msg);
-}
-
-void TestRenderViewHost::SendShouldCloseACK(bool proceed) {
- base::TimeTicks now = base::TimeTicks::Now();
- OnShouldCloseACK(proceed, now, now);
-}
-
-void TestRenderViewHost::SetContentsMimeType(const std::string& mime_type) {
- contents_mime_type_ = mime_type;
-}
-
-void TestRenderViewHost::SimulateSwapOutACK() {
- OnSwappedOut(false);
-}
-
-void TestRenderViewHost::SimulateWasHidden() {
- WasHidden();
-}
-
-void TestRenderViewHost::SimulateWasShown() {
- WasShown();
-}
-
-void TestRenderViewHost::TestOnStartDragging(
- const DropData& drop_data) {
- WebKit::WebDragOperationsMask drag_operation = WebKit::WebDragOperationEvery;
- DragEventSourceInfo event_info;
- OnStartDragging(drop_data, drag_operation, SkBitmap(), gfx::Vector2d(),
- event_info);
-}
-
-void TestRenderViewHost::TestOnUpdateStateWithFile(
- int process_id,
- const base::FilePath& file_path) {
- OnUpdateState(process_id,
- PageState::CreateForTesting(GURL("http://www.google.com"),
- false,
- "data",
- &file_path));
-}
-
-void TestRenderViewHost::set_simulate_fetch_via_proxy(bool proxy) {
- simulate_fetch_via_proxy_ = proxy;
-}
-
-void TestRenderViewHost::set_simulate_history_list_was_cleared(bool cleared) {
- simulate_history_list_was_cleared_ = cleared;
-}
-
-RenderViewHostImplTestHarness::RenderViewHostImplTestHarness() {
-}
-
-RenderViewHostImplTestHarness::~RenderViewHostImplTestHarness() {
-}
-
-TestRenderViewHost* RenderViewHostImplTestHarness::test_rvh() {
- return static_cast<TestRenderViewHost*>(rvh());
-}
-
-TestRenderViewHost* RenderViewHostImplTestHarness::pending_test_rvh() {
- return static_cast<TestRenderViewHost*>(pending_rvh());
-}
-
-TestRenderViewHost* RenderViewHostImplTestHarness::active_test_rvh() {
- return static_cast<TestRenderViewHost*>(active_rvh());
-}
-
-TestWebContents* RenderViewHostImplTestHarness::contents() {
- return static_cast<TestWebContents*>(web_contents());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/test_render_view_host.h b/chromium/content/browser/renderer_host/test_render_view_host.h
deleted file mode 100644
index 1eb7583bec0..00000000000
--- a/chromium/content/browser/renderer_host/test_render_view_host.h
+++ /dev/null
@@ -1,378 +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_RENDERER_HOST_TEST_RENDER_VIEW_HOST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_TEST_RENDER_VIEW_HOST_H_
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
-#include "build/build_config.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/public/common/page_transition_types.h"
-#include "content/public/test/test_renderer_host.h"
-#include "ui/gfx/vector2d_f.h"
-
-// This file provides a testing framework for mocking out the RenderProcessHost
-// layer. It allows you to test RenderViewHost, WebContentsImpl,
-// NavigationController, and other layers above that without running an actual
-// renderer process.
-//
-// To use, derive your test base class from RenderViewHostImplTestHarness.
-
-struct ViewHostMsg_FrameNavigate_Params;
-
-namespace gfx {
-class Rect;
-}
-
-namespace content {
-
-class SiteInstance;
-class TestWebContents;
-
-// Utility function to initialize ViewHostMsg_NavigateParams_Params
-// with given |page_id|, |url| and |transition_type|.
-void InitNavigateParams(ViewHostMsg_FrameNavigate_Params* params,
- int page_id,
- const GURL& url,
- PageTransition transition_type);
-
-// TestRenderViewHostView ------------------------------------------------------
-
-// Subclass the RenderViewHost's view so that we can call Show(), etc.,
-// without having side-effects.
-class TestRenderWidgetHostView : public RenderWidgetHostViewBase {
- public:
- explicit TestRenderWidgetHostView(RenderWidgetHost* rwh);
- virtual ~TestRenderWidgetHostView();
-
- // RenderWidgetHostView implementation.
- virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE {}
- virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE;
- virtual void SetSize(const gfx::Size& size) OVERRIDE {}
- virtual void SetBounds(const gfx::Rect& rect) OVERRIDE {}
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual gfx::NativeViewId GetNativeViewId() const OVERRIDE;
- virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE;
- virtual bool HasFocus() const OVERRIDE;
- virtual bool IsSurfaceAvailableForCopy() const OVERRIDE;
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual bool IsShowing() OVERRIDE;
- virtual gfx::Rect GetViewBounds() const OVERRIDE;
-#if defined(OS_MACOSX)
- virtual void SetActive(bool active) OVERRIDE;
- virtual void SetTakesFocusOnlyOnMouseDown(bool flag) OVERRIDE {}
- virtual void SetWindowVisibility(bool visible) OVERRIDE {}
- virtual void WindowFrameChanged() OVERRIDE {}
- virtual void ShowDefinitionForSelection() OVERRIDE {}
- virtual bool SupportsSpeech() const OVERRIDE;
- virtual void SpeakSelection() OVERRIDE;
- virtual bool IsSpeaking() const OVERRIDE;
- virtual void StopSpeaking() OVERRIDE;
-#endif // defined(OS_MACOSX)
-#if defined(TOOLKIT_GTK)
- virtual GdkEventButton* GetLastMouseDown() OVERRIDE;
- virtual gfx::NativeView BuildInputMethodsGtkMenu() OVERRIDE;
-#endif // defined(TOOLKIT_GTK)
- virtual void OnSwapCompositorFrame(
- uint32 output_surface_id,
- scoped_ptr<cc::CompositorFrame> frame) OVERRIDE;
-
- // RenderWidgetHostViewPort implementation.
- virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
- const gfx::Rect& pos) OVERRIDE {}
- virtual void InitAsFullscreen(
- RenderWidgetHostView* reference_host_view) OVERRIDE {}
- virtual void WasShown() OVERRIDE {}
- virtual void WasHidden() OVERRIDE {}
- virtual void MovePluginWindows(
- const gfx::Vector2d& scroll_offset,
- const std::vector<WebPluginGeometry>& moves) OVERRIDE {}
- virtual void Focus() OVERRIDE {}
- virtual void Blur() OVERRIDE {}
- virtual void SetIsLoading(bool is_loading) OVERRIDE {}
- virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE {}
- virtual void TextInputTypeChanged(ui::TextInputType type,
- ui::TextInputMode input_mode,
- bool can_compose_inline) OVERRIDE {}
- virtual void ImeCancelComposition() OVERRIDE {}
-#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
- virtual void ImeCompositionRangeChanged(
- const gfx::Range& range,
- const std::vector<gfx::Rect>& character_bounds) OVERRIDE {}
-#endif
- virtual void DidUpdateBackingStore(
- const gfx::Rect& scroll_rect,
- const gfx::Vector2d& scroll_delta,
- const std::vector<gfx::Rect>& rects,
- const ui::LatencyInfo& latency_info) OVERRIDE {}
- virtual void RenderProcessGone(base::TerminationStatus status,
- int error_code) OVERRIDE;
- virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) { }
- virtual void Destroy() OVERRIDE;
- virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE {}
- virtual void SelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE {}
- virtual void ScrollOffsetChanged() OVERRIDE {}
- virtual BackingStore* AllocBackingStore(const gfx::Size& size) OVERRIDE;
- virtual void CopyFromCompositingSurface(
- const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE;
- virtual void CopyFromCompositingSurfaceToVideoFrame(
- const gfx::Rect& src_subrect,
- const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback) OVERRIDE;
- virtual bool CanCopyToVideoFrame() const OVERRIDE;
- virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
- virtual void AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
- int gpu_host_id) OVERRIDE;
- virtual void AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
- int gpu_host_id) OVERRIDE;
- virtual void AcceleratedSurfaceSuspend() OVERRIDE;
- virtual void AcceleratedSurfaceRelease() OVERRIDE {}
- virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE;
-#if defined(OS_MACOSX)
- virtual void AboutToWaitForBackingStoreMsg() OVERRIDE;
- virtual bool PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) OVERRIDE;
-#elif defined(OS_ANDROID)
- virtual void ShowDisambiguationPopup(
- const gfx::Rect& target_rect,
- const SkBitmap& zoomed_bitmap) OVERRIDE {}
- virtual void HasTouchEventHandlers(bool need_touch_events) OVERRIDE {}
-#elif defined(OS_WIN) && !defined(USE_AURA)
- virtual void WillWmDestroy() OVERRIDE;
-#endif
- virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE {}
- virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE;
- virtual void SetHasHorizontalScrollbar(
- bool has_horizontal_scrollbar) OVERRIDE { }
- virtual void SetScrollOffsetPinning(
- bool is_pinned_to_left, bool is_pinned_to_right) OVERRIDE { }
- virtual void OnAccessibilityEvents(
- const std::vector<AccessibilityHostMsg_EventParams>& params) OVERRIDE {}
- virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
-#if defined(OS_WIN) && !defined(USE_AURA)
- virtual void SetClickthroughRegion(SkRegion* region) OVERRIDE;
-#endif
- virtual bool LockMouse() OVERRIDE;
- virtual void UnlockMouse() OVERRIDE;
-#if defined(OS_WIN) && defined(USE_AURA)
- virtual void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) OVERRIDE;
-#endif
-
- bool is_showing() const { return is_showing_; }
- bool did_swap_compositor_frame() const { return did_swap_compositor_frame_; }
-
- protected:
- RenderWidgetHostImpl* rwh_;
-
- private:
- bool is_showing_;
- bool did_swap_compositor_frame_;
-};
-
-#if defined(COMPILER_MSVC)
-// See comment for same warning on RenderViewHostImpl.
-#pragma warning(push)
-#pragma warning(disable: 4250)
-#endif
-
-// TestRenderViewHost ----------------------------------------------------------
-
-// TODO(brettw) this should use a TestWebContents which should be generalized
-// from the WebContentsImpl test. We will probably also need that class' version
-// of CreateRenderViewForRenderManager when more complicated tests start using
-// this.
-//
-// Note that users outside of content must use this class by getting
-// the separate RenderViewHostTester interface via
-// RenderViewHostTester::For(rvh) on the RenderViewHost they want to
-// drive tests on.
-//
-// Users within content may directly static_cast from a
-// RenderViewHost* to a TestRenderViewHost*.
-//
-// The reasons we do it this way rather than extending the parallel
-// inheritance hierarchy we have for RenderWidgetHost/RenderViewHost
-// vs. RenderWidgetHostImpl/RenderViewHostImpl are:
-//
-// a) Extending the parallel class hierarchy further would require
-// more classes to use virtual inheritance. This is a complexity that
-// is better to avoid, especially when it would be introduced in the
-// production code solely to facilitate testing code.
-//
-// b) While users outside of content only need to drive tests on a
-// RenderViewHost, content needs a test version of the full
-// RenderViewHostImpl so that it can test all methods on that concrete
-// class (e.g. overriding a method such as
-// RenderViewHostImpl::CreateRenderView). This would have complicated
-// the dual class hierarchy even further.
-//
-// The reason we do it this way instead of using composition is
-// similar to (b) above, essentially it gets very tricky. By using
-// the split interface we avoid complexity within content and maintain
-// reasonable utility for embedders.
-class TestRenderViewHost
- : public RenderViewHostImpl,
- public RenderViewHostTester {
- public:
- TestRenderViewHost(SiteInstance* instance,
- RenderViewHostDelegate* delegate,
- RenderWidgetHostDelegate* widget_delegate,
- int routing_id,
- int main_frame_routing_id,
- bool swapped_out);
- virtual ~TestRenderViewHost();
-
- // RenderViewHostTester implementation. Note that CreateRenderView
- // is not specified since it is synonymous with the one from
- // RenderViewHostImpl, see below.
- virtual void SendNavigate(int page_id, const GURL& url) OVERRIDE;
- virtual void SendFailedNavigate(int page_id, const GURL& url) OVERRIDE;
- virtual void SendNavigateWithTransition(int page_id, const GURL& url,
- PageTransition transition) OVERRIDE;
- virtual void SendShouldCloseACK(bool proceed) OVERRIDE;
- virtual void SetContentsMimeType(const std::string& mime_type) OVERRIDE;
- virtual void SimulateSwapOutACK() OVERRIDE;
- virtual void SimulateWasHidden() OVERRIDE;
- virtual void SimulateWasShown() OVERRIDE;
-
- // Calls OnNavigate on the RenderViewHost with the given information,
- // including a custom original request URL. Sets the rest of the
- // parameters in the message to the "typical" values. This is a helper
- // function for simulating the most common types of loads.
- void SendNavigateWithOriginalRequestURL(
- int page_id, const GURL& url, const GURL& original_request_url);
-
- void SendNavigateWithFile(
- int page_id, const GURL& url, const base::FilePath& file_path);
-
- void TestOnUpdateStateWithFile(
- int process_id, const base::FilePath& file_path);
-
- void TestOnStartDragging(const DropData& drop_data);
-
- // If set, *delete_counter is incremented when this object destructs.
- void set_delete_counter(int* delete_counter) {
- delete_counter_ = delete_counter;
- }
-
- // Sets whether the RenderView currently exists or not. This controls the
- // return value from IsRenderViewLive, which the rest of the system uses to
- // check whether the RenderView has crashed or not.
- void set_render_view_created(bool created) {
- render_view_created_ = created;
- }
-
- // Returns whether the RenderViewHost is currently waiting to hear the result
- // of a before unload handler from the renderer.
- bool is_waiting_for_beforeunload_ack() const {
- return is_waiting_for_beforeunload_ack_;
- }
-
- // Returns whether the RenderViewHost is currently waiting to hear the result
- // of an unload handler from the renderer.
- bool is_waiting_for_unload_ack() const {
- return is_waiting_for_unload_ack_;
- }
-
- // Sets whether the RenderViewHost is currently swapped out, and thus
- // filtering messages from the renderer.
- void set_is_swapped_out(bool is_swapped_out) {
- is_swapped_out_ = is_swapped_out;
- }
-
- // If set, navigations will appear to have loaded through a proxy
- // (ViewHostMsg_FrameNavigte_Params::was_fetched_via_proxy).
- // False by default.
- void set_simulate_fetch_via_proxy(bool proxy);
-
- // If set, navigations will appear to have cleared the history list in the
- // RenderView (ViewHostMsg_FrameNavigate_Params::history_list_was_cleared).
- // False by default.
- void set_simulate_history_list_was_cleared(bool cleared);
-
- // The opener route id passed to CreateRenderView().
- int opener_route_id() const { return opener_route_id_; }
-
- // RenderViewHost overrides --------------------------------------------------
-
- virtual bool CreateRenderView(const string16& frame_name,
- int opener_route_id,
- int32 max_page_id) OVERRIDE;
- virtual bool IsRenderViewLive() const OVERRIDE;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(RenderViewHostTest, FilterNavigate);
-
- void SendNavigateWithTransitionAndResponseCode(int page_id,
- const GURL& url,
- PageTransition transition,
- int response_code);
-
- // Calls OnNavigate on the RenderViewHost with the given information.
- // Sets the rest of the parameters in the message to the "typical" values.
- // This is a helper function for simulating the most common types of loads.
- void SendNavigateWithParameters(
- int page_id,
- const GURL& url,
- PageTransition transition,
- const GURL& original_request_url,
- int response_code,
- const base::FilePath* file_path_for_history_item);
-
- // Tracks if the caller thinks if it created the RenderView. This is so we can
- // respond to IsRenderViewLive appropriately.
- bool render_view_created_;
-
- // See set_delete_counter() above. May be NULL.
- int* delete_counter_;
-
- // See set_simulate_fetch_via_proxy() above.
- bool simulate_fetch_via_proxy_;
-
- // See set_simulate_history_list_was_cleared() above.
- bool simulate_history_list_was_cleared_;
-
- // See SetContentsMimeType() above.
- std::string contents_mime_type_;
-
- // See opener_route_id() above.
- int opener_route_id_;
-
- DISALLOW_COPY_AND_ASSIGN(TestRenderViewHost);
-};
-
-#if defined(COMPILER_MSVC)
-#pragma warning(pop)
-#endif
-
-// Adds methods to get straight at the impl classes.
-class RenderViewHostImplTestHarness : public RenderViewHostTestHarness {
- public:
- RenderViewHostImplTestHarness();
- virtual ~RenderViewHostImplTestHarness();
-
- TestRenderViewHost* test_rvh();
- TestRenderViewHost* pending_test_rvh();
- TestRenderViewHost* active_test_rvh();
- TestWebContents* contents();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RenderViewHostImplTestHarness);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_TEST_RENDER_VIEW_HOST_H_
diff --git a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc
deleted file mode 100644
index 5df932dfa3b..00000000000
--- a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h"
-
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "ui/aura/root_window.h"
-#include "ui/events/event.h"
-#include "ui/events/event_utils.h"
-#include "ui/gfx/transform.h"
-
-namespace {
-
-void InjectTouchEvent(const gfx::Point& location,
- ui::EventType type,
- aura::Window* window) {
- gfx::Point screen_location = location;
- // First convert the location from Window to RootWindow.
- aura::RootWindow* root_window = window->GetRootWindow();
- aura::Window::ConvertPointToTarget(window, root_window, &screen_location);
- // Then convert the location from RootWindow to screen.
- root_window->ConvertPointToHost(&screen_location);
- ui::TouchEvent touch(type, screen_location, 0, 0, ui::EventTimeForNow(),
- 1.0f, 1.0f, 1.0f, 1.0f);
- aura::RootWindowHostDelegate* root_window_host_delegate =
- root_window->AsRootWindowHostDelegate();
- root_window_host_delegate->OnHostTouchEvent(&touch);
-}
-
-} // namespace
-
-namespace content {
-
-TouchSmoothScrollGestureAura::TouchSmoothScrollGestureAura(bool scroll_down,
- int pixels_to_scroll,
- int mouse_event_x,
- int mouse_event_y,
- aura::Window* window)
- : scroll_down_(scroll_down),
- pixels_to_scroll_(pixels_to_scroll),
- pixels_scrolled_(0),
- location_(mouse_event_x, mouse_event_y),
- window_(window) {
-}
-
-TouchSmoothScrollGestureAura::~TouchSmoothScrollGestureAura() {}
-
-bool TouchSmoothScrollGestureAura::ForwardInputEvents(
- base::TimeTicks now,
- RenderWidgetHost* host) {
- if (pixels_scrolled_ >= pixels_to_scroll_)
- return false;
-
- RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(host);
- float position_delta = synthetic_gesture_calculator_.GetDelta(now,
- host_impl->GetSyntheticGestureMessageInterval());
-
- if (pixels_scrolled_ == 0) {
- InjectTouchEvent(location_, ui::ET_TOUCH_PRESSED, window_);
- }
-
- location_.Offset(0, scroll_down_ ? -position_delta : position_delta);
- InjectTouchEvent(location_, ui::ET_TOUCH_MOVED, window_);
-
- pixels_scrolled_ += abs(position_delta);
-
- if (pixels_scrolled_ >= pixels_to_scroll_) {
- InjectTouchEvent(location_, ui::ET_TOUCH_RELEASED, window_);
- }
-
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h b/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h
deleted file mode 100644
index 890b1467d68..00000000000
--- a/chromium/content/browser/renderer_host/touch_smooth_scroll_gesture_aura.h
+++ /dev/null
@@ -1,45 +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_RENDERER_HOST_TOUCH_SMOOTH_SCROLL_GESTURE_
-#define CONTENT_BROWSER_RENDERER_HOST_TOUCH_SMOOTH_SCROLL_GESTURE_
-
-#include "base/time/time.h"
-#include "content/browser/renderer_host/synthetic_gesture_calculator.h"
-#include "content/port/browser/synthetic_gesture.h"
-#include "ui/gfx/point.h"
-
-namespace aura {
-class Window;
-}
-
-namespace content {
-
-class TouchSmoothScrollGestureAura : public SyntheticGesture {
- public:
- TouchSmoothScrollGestureAura(bool scroll_down,
- int pixels_to_scroll,
- int mouse_event_x,
- int mouse_event_y,
- aura::Window* window);
- private:
- virtual ~TouchSmoothScrollGestureAura();
-
- // Overridden from SmoothScrollGesture.
- virtual bool ForwardInputEvents(base::TimeTicks now,
- RenderWidgetHost* host) OVERRIDE;
-
- bool scroll_down_;
- int pixels_to_scroll_;
- int pixels_scrolled_;
- gfx::Point location_;
- aura::Window* window_;
- SyntheticGestureCalculator synthetic_gesture_calculator_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchSmoothScrollGestureAura);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_TOUCH_SMOOTH_SCROLL_GESTURE_
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.cc b/chromium/content/browser/renderer_host/ui_events_helper.cc
index 78a7bff4f74..1dc312db591 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.cc
+++ b/chromium/content/browser/renderer_host/ui_events_helper.cc
@@ -13,39 +13,39 @@ namespace {
int WebModifiersToUIFlags(int modifiers) {
int flags = ui::EF_NONE;
- if (modifiers & WebKit::WebInputEvent::ShiftKey)
+ if (modifiers & blink::WebInputEvent::ShiftKey)
flags |= ui::EF_SHIFT_DOWN;
- if (modifiers & WebKit::WebInputEvent::ControlKey)
+ if (modifiers & blink::WebInputEvent::ControlKey)
flags |= ui::EF_CONTROL_DOWN;
- if (modifiers & WebKit::WebInputEvent::AltKey)
+ if (modifiers & blink::WebInputEvent::AltKey)
flags |= ui::EF_ALT_DOWN;
- if (modifiers & WebKit::WebInputEvent::LeftButtonDown)
+ if (modifiers & blink::WebInputEvent::LeftButtonDown)
flags |= ui::EF_LEFT_MOUSE_BUTTON;
- if (modifiers & WebKit::WebInputEvent::RightButtonDown)
+ if (modifiers & blink::WebInputEvent::RightButtonDown)
flags |= ui::EF_RIGHT_MOUSE_BUTTON;
- if (modifiers & WebKit::WebInputEvent::MiddleButtonDown)
+ if (modifiers & blink::WebInputEvent::MiddleButtonDown)
flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
- if (modifiers & WebKit::WebInputEvent::CapsLockOn)
+ if (modifiers & blink::WebInputEvent::CapsLockOn)
flags |= ui::EF_CAPS_LOCK_DOWN;
return flags;
}
ui::EventType WebTouchPointStateToEventType(
- WebKit::WebTouchPoint::State state) {
+ blink::WebTouchPoint::State state) {
switch (state) {
- case WebKit::WebTouchPoint::StateReleased:
+ case blink::WebTouchPoint::StateReleased:
return ui::ET_TOUCH_RELEASED;
- case WebKit::WebTouchPoint::StatePressed:
+ case blink::WebTouchPoint::StatePressed:
return ui::ET_TOUCH_PRESSED;
- case WebKit::WebTouchPoint::StateMoved:
+ case blink::WebTouchPoint::StateMoved:
return ui::ET_TOUCH_MOVED;
- case WebKit::WebTouchPoint::StateCancelled:
+ case blink::WebTouchPoint::StateCancelled:
return ui::ET_TOUCH_CANCELLED;
default:
@@ -53,35 +53,35 @@ ui::EventType WebTouchPointStateToEventType(
}
}
-WebKit::WebTouchPoint::State TouchPointStateFromEvent(
+blink::WebTouchPoint::State TouchPointStateFromEvent(
const ui::TouchEvent& event) {
switch (event.type()) {
case ui::ET_TOUCH_PRESSED:
- return WebKit::WebTouchPoint::StatePressed;
+ return blink::WebTouchPoint::StatePressed;
case ui::ET_TOUCH_RELEASED:
- return WebKit::WebTouchPoint::StateReleased;
+ return blink::WebTouchPoint::StateReleased;
case ui::ET_TOUCH_MOVED:
- return WebKit::WebTouchPoint::StateMoved;
+ return blink::WebTouchPoint::StateMoved;
case ui::ET_TOUCH_CANCELLED:
- return WebKit::WebTouchPoint::StateCancelled;
+ return blink::WebTouchPoint::StateCancelled;
default:
- return WebKit::WebTouchPoint::StateUndefined;
+ return blink::WebTouchPoint::StateUndefined;
}
}
-WebKit::WebInputEvent::Type TouchEventTypeFromEvent(
+blink::WebInputEvent::Type TouchEventTypeFromEvent(
const ui::TouchEvent& event) {
switch (event.type()) {
case ui::ET_TOUCH_PRESSED:
- return WebKit::WebInputEvent::TouchStart;
+ return blink::WebInputEvent::TouchStart;
case ui::ET_TOUCH_RELEASED:
- return WebKit::WebInputEvent::TouchEnd;
+ return blink::WebInputEvent::TouchEnd;
case ui::ET_TOUCH_MOVED:
- return WebKit::WebInputEvent::TouchMove;
+ return blink::WebInputEvent::TouchMove;
case ui::ET_TOUCH_CANCELLED:
- return WebKit::WebInputEvent::TouchCancel;
+ return blink::WebInputEvent::TouchCancel;
default:
- return WebKit::WebInputEvent::Undefined;
+ return blink::WebInputEvent::Undefined;
}
}
@@ -93,19 +93,19 @@ bool MakeUITouchEventsFromWebTouchEvents(
const TouchEventWithLatencyInfo& touch_with_latency,
ScopedVector<ui::TouchEvent>* list,
TouchEventCoordinateSystem coordinate_system) {
- const WebKit::WebTouchEvent& touch = touch_with_latency.event;
+ const blink::WebTouchEvent& touch = touch_with_latency.event;
ui::EventType type = ui::ET_UNKNOWN;
switch (touch.type) {
- case WebKit::WebInputEvent::TouchStart:
+ case blink::WebInputEvent::TouchStart:
type = ui::ET_TOUCH_PRESSED;
break;
- case WebKit::WebInputEvent::TouchEnd:
+ case blink::WebInputEvent::TouchEnd:
type = ui::ET_TOUCH_RELEASED;
break;
- case WebKit::WebInputEvent::TouchMove:
+ case blink::WebInputEvent::TouchMove:
type = ui::ET_TOUCH_MOVED;
break;
- case WebKit::WebInputEvent::TouchCancel:
+ case blink::WebInputEvent::TouchCancel:
type = ui::ET_TOUCH_CANCELLED;
break;
default:
@@ -117,7 +117,7 @@ bool MakeUITouchEventsFromWebTouchEvents(
base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
static_cast<int64>(touch.timeStampSeconds * 1000000));
for (unsigned i = 0; i < touch.touchesLength; ++i) {
- const WebKit::WebTouchPoint& point = touch.touches[i];
+ const blink::WebTouchPoint& point = touch.touches[i];
if (WebTouchPointStateToEventType(point.state) != type)
continue;
// In aura, the touch-event needs to be in the screen coordinate, since the
@@ -148,72 +148,79 @@ bool MakeUITouchEventsFromWebTouchEvents(
return true;
}
-WebKit::WebGestureEvent MakeWebGestureEventFromUIEvent(
+blink::WebGestureEvent MakeWebGestureEventFromUIEvent(
const ui::GestureEvent& event) {
- WebKit::WebGestureEvent gesture_event;
+ blink::WebGestureEvent gesture_event;
switch (event.type()) {
case ui::ET_GESTURE_TAP:
- gesture_event.type = WebKit::WebInputEvent::GestureTap;
+ gesture_event.type = blink::WebInputEvent::GestureTap;
gesture_event.data.tap.tapCount = event.details().tap_count();
gesture_event.data.tap.width = event.details().bounding_box().width();
gesture_event.data.tap.height = event.details().bounding_box().height();
break;
case ui::ET_GESTURE_TAP_DOWN:
- gesture_event.type = WebKit::WebInputEvent::GestureTapDown;
+ gesture_event.type = blink::WebInputEvent::GestureTapDown;
gesture_event.data.tapDown.width =
event.details().bounding_box().width();
gesture_event.data.tapDown.height =
event.details().bounding_box().height();
break;
+ case ui::ET_GESTURE_SHOW_PRESS:
+ gesture_event.type = blink::WebInputEvent::GestureShowPress;
+ gesture_event.data.showPress.width =
+ event.details().bounding_box().width();
+ gesture_event.data.showPress.height =
+ event.details().bounding_box().height();
+ break;
case ui::ET_GESTURE_TAP_CANCEL:
- gesture_event.type = WebKit::WebInputEvent::GestureTapCancel;
+ gesture_event.type = blink::WebInputEvent::GestureTapCancel;
break;
case ui::ET_GESTURE_SCROLL_BEGIN:
- gesture_event.type = WebKit::WebInputEvent::GestureScrollBegin;
+ gesture_event.type = blink::WebInputEvent::GestureScrollBegin;
break;
case ui::ET_GESTURE_SCROLL_UPDATE:
- gesture_event.type = WebKit::WebInputEvent::GestureScrollUpdate;
+ gesture_event.type = blink::WebInputEvent::GestureScrollUpdate;
gesture_event.data.scrollUpdate.deltaX = event.details().scroll_x();
gesture_event.data.scrollUpdate.deltaY = event.details().scroll_y();
break;
case ui::ET_GESTURE_SCROLL_END:
- gesture_event.type = WebKit::WebInputEvent::GestureScrollEnd;
+ gesture_event.type = blink::WebInputEvent::GestureScrollEnd;
break;
case ui::ET_GESTURE_PINCH_BEGIN:
- gesture_event.type = WebKit::WebInputEvent::GesturePinchBegin;
+ gesture_event.type = blink::WebInputEvent::GesturePinchBegin;
break;
case ui::ET_GESTURE_PINCH_UPDATE:
- gesture_event.type = WebKit::WebInputEvent::GesturePinchUpdate;
+ gesture_event.type = blink::WebInputEvent::GesturePinchUpdate;
gesture_event.data.pinchUpdate.scale = event.details().scale();
break;
case ui::ET_GESTURE_PINCH_END:
- gesture_event.type = WebKit::WebInputEvent::GesturePinchEnd;
+ gesture_event.type = blink::WebInputEvent::GesturePinchEnd;
break;
case ui::ET_SCROLL_FLING_START:
- gesture_event.type = WebKit::WebInputEvent::GestureFlingStart;
+ gesture_event.type = blink::WebInputEvent::GestureFlingStart;
gesture_event.data.flingStart.velocityX = event.details().velocity_x();
gesture_event.data.flingStart.velocityY = event.details().velocity_y();
break;
case ui::ET_SCROLL_FLING_CANCEL:
- gesture_event.type = WebKit::WebInputEvent::GestureFlingCancel;
+ gesture_event.type = blink::WebInputEvent::GestureFlingCancel;
break;
case ui::ET_GESTURE_LONG_PRESS:
- gesture_event.type = WebKit::WebInputEvent::GestureLongPress;
+ gesture_event.type = blink::WebInputEvent::GestureLongPress;
gesture_event.data.longPress.width =
event.details().bounding_box().width();
gesture_event.data.longPress.height =
event.details().bounding_box().height();
break;
case ui::ET_GESTURE_LONG_TAP:
- gesture_event.type = WebKit::WebInputEvent::GestureLongTap;
+ gesture_event.type = blink::WebInputEvent::GestureLongTap;
gesture_event.data.longPress.width =
event.details().bounding_box().width();
gesture_event.data.longPress.height =
event.details().bounding_box().height();
break;
case ui::ET_GESTURE_TWO_FINGER_TAP:
- gesture_event.type = WebKit::WebInputEvent::GestureTwoFingerTap;
+ gesture_event.type = blink::WebInputEvent::GestureTwoFingerTap;
gesture_event.data.twoFingerTap.firstFingerWidth =
event.details().first_finger_width();
gesture_event.data.twoFingerTap.firstFingerHeight =
@@ -222,13 +229,13 @@ WebKit::WebGestureEvent MakeWebGestureEventFromUIEvent(
case ui::ET_GESTURE_BEGIN:
case ui::ET_GESTURE_END:
case ui::ET_GESTURE_MULTIFINGER_SWIPE:
- gesture_event.type = WebKit::WebInputEvent::Undefined;
+ gesture_event.type = blink::WebInputEvent::Undefined;
break;
default:
NOTREACHED() << "Unknown gesture type: " << event.type();
}
- gesture_event.sourceDevice = WebKit::WebGestureEvent::Touchscreen;
+ gesture_event.sourceDevice = blink::WebGestureEvent::Touchscreen;
gesture_event.modifiers = EventFlagsToWebEventModifiers(event.flags());
gesture_event.timeStampSeconds = event.time_stamp().InSecondsF();
@@ -239,31 +246,31 @@ int EventFlagsToWebEventModifiers(int flags) {
int modifiers = 0;
if (flags & ui::EF_SHIFT_DOWN)
- modifiers |= WebKit::WebInputEvent::ShiftKey;
+ modifiers |= blink::WebInputEvent::ShiftKey;
if (flags & ui::EF_CONTROL_DOWN)
- modifiers |= WebKit::WebInputEvent::ControlKey;
+ modifiers |= blink::WebInputEvent::ControlKey;
if (flags & ui::EF_ALT_DOWN)
- modifiers |= WebKit::WebInputEvent::AltKey;
+ modifiers |= blink::WebInputEvent::AltKey;
// TODO(beng): MetaKey/META_MASK
if (flags & ui::EF_LEFT_MOUSE_BUTTON)
- modifiers |= WebKit::WebInputEvent::LeftButtonDown;
+ modifiers |= blink::WebInputEvent::LeftButtonDown;
if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
- modifiers |= WebKit::WebInputEvent::MiddleButtonDown;
+ modifiers |= blink::WebInputEvent::MiddleButtonDown;
if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
- modifiers |= WebKit::WebInputEvent::RightButtonDown;
+ modifiers |= blink::WebInputEvent::RightButtonDown;
if (flags & ui::EF_CAPS_LOCK_DOWN)
- modifiers |= WebKit::WebInputEvent::CapsLockOn;
+ modifiers |= blink::WebInputEvent::CapsLockOn;
return modifiers;
}
-WebKit::WebTouchPoint* UpdateWebTouchEventFromUIEvent(
+blink::WebTouchPoint* UpdateWebTouchEventFromUIEvent(
const ui::TouchEvent& event,
- WebKit::WebTouchEvent* web_event) {
- WebKit::WebTouchPoint* point = NULL;
+ blink::WebTouchEvent* web_event) {
+ blink::WebTouchPoint* point = NULL;
switch (event.type()) {
case ui::ET_TOUCH_PRESSED:
// Add a new touch point.
- if (web_event->touchesLength < WebKit::WebTouchEvent::touchesLengthCap) {
+ if (web_event->touchesLength < blink::WebTouchEvent::touchesLengthCap) {
point = &web_event->touches[web_event->touchesLength++];
point->id = event.touch_id();
}
@@ -299,7 +306,7 @@ WebKit::WebTouchPoint* UpdateWebTouchEventFromUIEvent(
// Update the location and state of the point.
point->state = TouchPointStateFromEvent(event);
- if (point->state == WebKit::WebTouchPoint::StateMoved) {
+ if (point->state == blink::WebTouchPoint::StateMoved) {
// It is possible for badly written touch drivers to emit Move events even
// when the touch location hasn't changed. In such cases, consume the event
// and pretend nothing happened.
@@ -315,9 +322,9 @@ WebKit::WebTouchPoint* UpdateWebTouchEventFromUIEvent(
// Mark the rest of the points as stationary.
for (unsigned i = 0; i < web_event->touchesLength; ++i) {
- WebKit::WebTouchPoint* iter = web_event->touches + i;
+ blink::WebTouchPoint* iter = web_event->touches + i;
if (iter != point)
- iter->state = WebKit::WebTouchPoint::StateStationary;
+ iter->state = blink::WebTouchPoint::StateStationary;
}
// Update the type of the touch event.
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.h b/chromium/content/browser/renderer_host/ui_events_helper.h
index 734a3146ef5..51fd46f0a50 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.h
+++ b/chromium/content/browser/renderer_host/ui_events_helper.h
@@ -9,7 +9,7 @@
#include "content/common/content_export.h"
#include "content/port/browser/event_with_latency_info.h"
-namespace WebKit {
+namespace blink {
class WebGestureEvent;
class WebTouchEvent;
class WebTouchPoint;
@@ -41,7 +41,7 @@ CONTENT_EXPORT bool MakeUITouchEventsFromWebTouchEvents(
// 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.
-WebKit::WebGestureEvent MakeWebGestureEventFromUIEvent(
+blink::WebGestureEvent MakeWebGestureEventFromUIEvent(
const ui::GestureEvent& event);
int EventFlagsToWebEventModifiers(int flags);
@@ -49,9 +49,9 @@ int EventFlagsToWebEventModifiers(int flags);
// Updates the WebTouchEvent based on the TouchEvent. It returns the updated
// WebTouchPoint contained in the WebTouchEvent, or NULL if no point was
// updated.
-WebKit::WebTouchPoint* UpdateWebTouchEventFromUIEvent(
+blink::WebTouchPoint* UpdateWebTouchEventFromUIEvent(
const ui::TouchEvent& event,
- WebKit::WebTouchEvent* web_event);
+ blink::WebTouchEvent* web_event);
}
#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 6bb5e5838af..f35d37740e5 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aura.cc
@@ -9,11 +9,15 @@
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
+#if defined(USE_OZONE)
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#endif
+
namespace content {
#if defined(USE_X11) || defined(USE_OZONE)
// From third_party/WebKit/Source/web/gtk/WebInputEventFactory.cpp:
-WebKit::WebUChar GetControlCharacter(int windows_key_code, bool shift) {
+blink::WebUChar GetControlCharacter(int windows_key_code, bool shift) {
if (windows_key_code >= ui::VKEY_A &&
windows_key_code <= ui::VKEY_Z) {
// ctrl-A ~ ctrl-Z map to \x01 ~ \x1A
@@ -58,40 +62,40 @@ WebKit::WebUChar GetControlCharacter(int windows_key_code, bool shift) {
}
#endif
#if defined(OS_WIN)
-WebKit::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
+blink::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
base::NativeEvent native_event);
-WebKit::WebMouseWheelEvent MakeUntranslatedWebMouseWheelEventFromNativeEvent(
+blink::WebMouseWheelEvent MakeUntranslatedWebMouseWheelEventFromNativeEvent(
base::NativeEvent native_event);
-WebKit::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
+blink::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
base::NativeEvent native_event);
-WebKit::WebGestureEvent MakeWebGestureEventFromNativeEvent(
+blink::WebGestureEvent MakeWebGestureEventFromNativeEvent(
base::NativeEvent native_event);
#elif defined(USE_X11)
-WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
+blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
ui::KeyEvent* event);
#elif defined(USE_OZONE)
-WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
+blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
ui::KeyEvent* event) {
base::NativeEvent native_event = event->native_event();
ui::EventType type = ui::EventTypeFromNative(native_event);
- WebKit::WebKeyboardEvent webkit_event;
+ blink::WebKeyboardEvent webkit_event;
webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
switch (type) {
case ui::ET_KEY_PRESSED:
- webkit_event.type = event->is_char() ? WebKit::WebInputEvent::Char :
- WebKit::WebInputEvent::RawKeyDown;
+ webkit_event.type = event->is_char() ? blink::WebInputEvent::Char :
+ blink::WebInputEvent::RawKeyDown;
break;
case ui::ET_KEY_RELEASED:
- webkit_event.type = WebKit::WebInputEvent::KeyUp;
+ webkit_event.type = blink::WebInputEvent::KeyUp;
break;
default:
NOTREACHED();
}
- if (webkit_event.modifiers & WebKit::WebInputEvent::AltKey)
+ if (webkit_event.modifiers & blink::WebInputEvent::AltKey)
webkit_event.isSystemKey = true;
wchar_t character = ui::KeyboardCodeFromNative(native_event);
@@ -101,13 +105,15 @@ WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
if (webkit_event.windowsKeyCode == ui::VKEY_RETURN)
webkit_event.unmodifiedText[0] = '\r';
else
- webkit_event.unmodifiedText[0] = character;
+ webkit_event.unmodifiedText[0] = ui::GetCharacterFromKeyCode(
+ ui::KeyboardCodeFromNative(native_event),
+ ui::EventFlagsFromNative(native_event));
- if (webkit_event.modifiers & WebKit::WebInputEvent::ControlKey) {
+ if (webkit_event.modifiers & blink::WebInputEvent::ControlKey) {
webkit_event.text[0] =
GetControlCharacter(
webkit_event.windowsKeyCode,
- webkit_event.modifiers & WebKit::WebInputEvent::ShiftKey);
+ webkit_event.modifiers & blink::WebInputEvent::ShiftKey);
} else {
webkit_event.text[0] = webkit_event.unmodifiedText[0];
}
@@ -118,12 +124,12 @@ WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
}
#endif
#if defined(USE_X11) || defined(USE_OZONE)
-WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
+blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
ui::ScrollEvent* event) {
- WebKit::WebMouseWheelEvent webkit_event;
+ blink::WebMouseWheelEvent webkit_event;
- webkit_event.type = WebKit::WebInputEvent::MouseWheel;
- webkit_event.button = WebKit::WebMouseEvent::ButtonNone;
+ webkit_event.type = blink::WebInputEvent::MouseWheel;
+ webkit_event.button = blink::WebMouseEvent::ButtonNone;
webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
webkit_event.hasPreciseScrollingDeltas = true;
@@ -142,18 +148,18 @@ WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
return webkit_event;
}
-WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent(
+blink::WebGestureEvent MakeWebGestureEventFromAuraEvent(
ui::ScrollEvent* event) {
- WebKit::WebGestureEvent webkit_event;
+ blink::WebGestureEvent webkit_event;
switch (event->type()) {
case ui::ET_SCROLL_FLING_START:
- webkit_event.type = WebKit::WebInputEvent::GestureFlingStart;
+ webkit_event.type = blink::WebInputEvent::GestureFlingStart;
webkit_event.data.flingStart.velocityX = event->x_offset();
webkit_event.data.flingStart.velocityY = event->y_offset();
break;
case ui::ET_SCROLL_FLING_CANCEL:
- webkit_event.type = WebKit::WebInputEvent::GestureFlingCancel;
+ webkit_event.type = blink::WebInputEvent::GestureFlingCancel;
break;
case ui::ET_SCROLL:
NOTREACHED() << "Invalid gesture type: " << event->type();
@@ -162,7 +168,7 @@ WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent(
NOTREACHED() << "Unknown gesture type: " << event->type();
}
- webkit_event.sourceDevice = WebKit::WebGestureEvent::Touchpad;
+ webkit_event.sourceDevice = blink::WebGestureEvent::Touchpad;
webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
return webkit_event;
@@ -170,9 +176,9 @@ WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent(
#endif
-WebKit::WebMouseEvent MakeWebMouseEventFromAuraEvent(
+blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(
ui::MouseEvent* event);
-WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
+blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
ui::MouseWheelEvent* event);
// General approach:
@@ -187,7 +193,7 @@ WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
// provide coordinates relative to the aura::Window that is hosting the
// renderer, not the top level platform window.
//
-// The approach is to fully construct a WebKit::WebInputEvent from the
+// The approach is to fully construct a blink::WebInputEvent from the
// ui::Event's base::NativeEvent, and then replace the coordinate fields with
// the translated values from the ui::Event.
//
@@ -198,9 +204,9 @@ WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
// ui::MouseEvent. This will not be necessary once only XInput2 is supported.
//
-WebKit::WebMouseEvent MakeWebMouseEvent(ui::MouseEvent* event) {
+blink::WebMouseEvent MakeWebMouseEvent(ui::MouseEvent* event) {
// Construct an untranslated event from the platform event data.
- WebKit::WebMouseEvent webkit_event =
+ blink::WebMouseEvent webkit_event =
#if defined(OS_WIN)
// On Windows we have WM_ events comming from desktop and pure aura
// events comming from metro mode.
@@ -226,14 +232,14 @@ WebKit::WebMouseEvent MakeWebMouseEvent(ui::MouseEvent* event) {
return webkit_event;
}
-WebKit::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::MouseWheelEvent* event) {
+blink::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::MouseWheelEvent* event) {
#if defined(OS_WIN)
// Construct an untranslated event from the platform event data.
- WebKit::WebMouseWheelEvent webkit_event = event->native_event().message ?
+ blink::WebMouseWheelEvent webkit_event = event->native_event().message ?
MakeUntranslatedWebMouseWheelEventFromNativeEvent(event->native_event()) :
MakeWebMouseWheelEventFromAuraEvent(event);
#else
- WebKit::WebMouseWheelEvent webkit_event =
+ blink::WebMouseWheelEvent webkit_event =
MakeWebMouseWheelEventFromAuraEvent(event);
#endif
@@ -249,13 +255,13 @@ WebKit::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::MouseWheelEvent* event) {
return webkit_event;
}
-WebKit::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::ScrollEvent* event) {
+blink::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::ScrollEvent* event) {
#if defined(OS_WIN)
// Construct an untranslated event from the platform event data.
- WebKit::WebMouseWheelEvent webkit_event =
+ blink::WebMouseWheelEvent webkit_event =
MakeUntranslatedWebMouseWheelEventFromNativeEvent(event->native_event());
#else
- WebKit::WebMouseWheelEvent webkit_event =
+ blink::WebMouseWheelEvent webkit_event =
MakeWebMouseWheelEventFromAuraEvent(event);
#endif
@@ -271,7 +277,7 @@ WebKit::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::ScrollEvent* event) {
return webkit_event;
}
-WebKit::WebKeyboardEvent MakeWebKeyboardEvent(ui::KeyEvent* event) {
+blink::WebKeyboardEvent MakeWebKeyboardEvent(ui::KeyEvent* event) {
// Windows can figure out whether or not to construct a RawKeyDown or a Char
// WebInputEvent based on the type of message carried in
// event->native_event(). X11 is not so fortunate, there is no separate
@@ -286,8 +292,8 @@ WebKit::WebKeyboardEvent MakeWebKeyboardEvent(ui::KeyEvent* event) {
#endif
}
-WebKit::WebGestureEvent MakeWebGestureEvent(ui::GestureEvent* event) {
- WebKit::WebGestureEvent gesture_event;
+blink::WebGestureEvent MakeWebGestureEvent(ui::GestureEvent* event) {
+ blink::WebGestureEvent gesture_event;
#if defined(OS_WIN)
if (event->HasNativeEvent())
gesture_event = MakeWebGestureEventFromNativeEvent(event->native_event());
@@ -307,8 +313,8 @@ WebKit::WebGestureEvent MakeWebGestureEvent(ui::GestureEvent* event) {
return gesture_event;
}
-WebKit::WebGestureEvent MakeWebGestureEvent(ui::ScrollEvent* event) {
- WebKit::WebGestureEvent gesture_event;
+blink::WebGestureEvent MakeWebGestureEvent(ui::ScrollEvent* event) {
+ blink::WebGestureEvent gesture_event;
#if defined(OS_WIN)
gesture_event = MakeWebGestureEventFromNativeEvent(event->native_event());
@@ -326,43 +332,43 @@ WebKit::WebGestureEvent MakeWebGestureEvent(ui::ScrollEvent* event) {
return gesture_event;
}
-WebKit::WebGestureEvent MakeWebGestureEventFlingCancel() {
- WebKit::WebGestureEvent gesture_event;
+blink::WebGestureEvent MakeWebGestureEventFlingCancel() {
+ blink::WebGestureEvent gesture_event;
// All other fields are ignored on a GestureFlingCancel event.
- gesture_event.type = WebKit::WebInputEvent::GestureFlingCancel;
- gesture_event.sourceDevice = WebKit::WebGestureEvent::Touchpad;
+ gesture_event.type = blink::WebInputEvent::GestureFlingCancel;
+ gesture_event.sourceDevice = blink::WebGestureEvent::Touchpad;
return gesture_event;
}
-WebKit::WebMouseEvent MakeWebMouseEventFromAuraEvent(ui::MouseEvent* event) {
- WebKit::WebMouseEvent webkit_event;
+blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(ui::MouseEvent* event) {
+ blink::WebMouseEvent webkit_event;
webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
- webkit_event.button = WebKit::WebMouseEvent::ButtonNone;
+ webkit_event.button = blink::WebMouseEvent::ButtonNone;
if (event->flags() & ui::EF_LEFT_MOUSE_BUTTON)
- webkit_event.button = WebKit::WebMouseEvent::ButtonLeft;
+ webkit_event.button = blink::WebMouseEvent::ButtonLeft;
if (event->flags() & ui::EF_MIDDLE_MOUSE_BUTTON)
- webkit_event.button = WebKit::WebMouseEvent::ButtonMiddle;
+ webkit_event.button = blink::WebMouseEvent::ButtonMiddle;
if (event->flags() & ui::EF_RIGHT_MOUSE_BUTTON)
- webkit_event.button = WebKit::WebMouseEvent::ButtonRight;
+ webkit_event.button = blink::WebMouseEvent::ButtonRight;
switch (event->type()) {
case ui::ET_MOUSE_PRESSED:
- webkit_event.type = WebKit::WebInputEvent::MouseDown;
+ webkit_event.type = blink::WebInputEvent::MouseDown;
webkit_event.clickCount = event->GetClickCount();
break;
case ui::ET_MOUSE_RELEASED:
- webkit_event.type = WebKit::WebInputEvent::MouseUp;
+ webkit_event.type = blink::WebInputEvent::MouseUp;
webkit_event.clickCount = event->GetClickCount();
break;
case ui::ET_MOUSE_ENTERED:
case ui::ET_MOUSE_EXITED:
case ui::ET_MOUSE_MOVED:
case ui::ET_MOUSE_DRAGGED:
- webkit_event.type = WebKit::WebInputEvent::MouseMove;
+ webkit_event.type = blink::WebInputEvent::MouseMove;
break;
default:
NOTIMPLEMENTED() << "Received unexpected event: " << event->type();
@@ -372,12 +378,12 @@ WebKit::WebMouseEvent MakeWebMouseEventFromAuraEvent(ui::MouseEvent* event) {
return webkit_event;
}
-WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
+blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
ui::MouseWheelEvent* event) {
- WebKit::WebMouseWheelEvent webkit_event;
+ blink::WebMouseWheelEvent webkit_event;
- webkit_event.type = WebKit::WebInputEvent::MouseWheel;
- webkit_event.button = WebKit::WebMouseEvent::ButtonNone;
+ webkit_event.type = blink::WebInputEvent::MouseWheel;
+ webkit_event.button = blink::WebMouseEvent::ButtonNone;
webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
webkit_event.deltaX = event->x_offset();
diff --git a/chromium/content/browser/renderer_host/web_input_event_aura.h b/chromium/content/browser/renderer_host/web_input_event_aura.h
index 3c4c8945bed..eeff8866a82 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura.h
+++ b/chromium/content/browser/renderer_host/web_input_event_aura.h
@@ -23,22 +23,22 @@ namespace content {
const int kPixelsPerTick = 53;
#if defined(USE_X11) || defined(USE_OZONE)
-CONTENT_EXPORT WebKit::WebUChar GetControlCharacter(
+CONTENT_EXPORT blink::WebUChar GetControlCharacter(
int windows_key_code, bool shift);
#endif
-CONTENT_EXPORT WebKit::WebMouseEvent MakeWebMouseEvent(
+CONTENT_EXPORT blink::WebMouseEvent MakeWebMouseEvent(
ui::MouseEvent* event);
-CONTENT_EXPORT WebKit::WebMouseWheelEvent MakeWebMouseWheelEvent(
+CONTENT_EXPORT blink::WebMouseWheelEvent MakeWebMouseWheelEvent(
ui::MouseWheelEvent* event);
-CONTENT_EXPORT WebKit::WebMouseWheelEvent MakeWebMouseWheelEvent(
+CONTENT_EXPORT blink::WebMouseWheelEvent MakeWebMouseWheelEvent(
ui::ScrollEvent* event);
-CONTENT_EXPORT WebKit::WebKeyboardEvent MakeWebKeyboardEvent(
+CONTENT_EXPORT blink::WebKeyboardEvent MakeWebKeyboardEvent(
ui::KeyEvent* event);
-CONTENT_EXPORT WebKit::WebGestureEvent MakeWebGestureEvent(
+CONTENT_EXPORT blink::WebGestureEvent MakeWebGestureEvent(
ui::GestureEvent* event);
-CONTENT_EXPORT WebKit::WebGestureEvent MakeWebGestureEvent(
+CONTENT_EXPORT blink::WebGestureEvent MakeWebGestureEvent(
ui::ScrollEvent* event);
-CONTENT_EXPORT WebKit::WebGestureEvent MakeWebGestureEventFlingCancel();
+CONTENT_EXPORT blink::WebGestureEvent MakeWebGestureEventFlingCancel();
} // namespace content
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 818250c0dd6..d67d0cd2278 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
@@ -11,8 +11,8 @@
#if defined(USE_X11)
#include <X11/keysym.h>
#include <X11/Xlib.h>
+#include "ui/events/test/events_test_utils_x11.h"
#include "ui/gfx/x/x11_types.h"
-#include "ui/base/x/x11_util.h"
#endif
namespace content {
@@ -21,26 +21,20 @@ namespace content {
// crbug.com/127142
TEST(WebInputEventAuraTest, TestMakeWebKeyboardEvent) {
#if defined(USE_X11)
- XEvent xev;
+ ui::ScopedXI2Event xev;
{
// Press Ctrl.
- ui::InitXKeyEventForTesting(ui::ET_KEY_PRESSED,
- ui::VKEY_CONTROL,
- 0, // X does not set ControlMask for KeyPress.
- &xev);
- ui::KeyEvent event(&xev, false /* is_char */);
- WebKit::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
+ xev.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, 0);
+ ui::KeyEvent event(xev, false /* is_char */);
+ blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// However, modifier bit for Control in |webkit_event| should be set.
- EXPECT_EQ(webkit_event.modifiers, WebKit::WebInputEvent::ControlKey);
+ EXPECT_EQ(webkit_event.modifiers, blink::WebInputEvent::ControlKey);
}
{
// Release Ctrl.
- ui::InitXKeyEventForTesting(ui::ET_KEY_RELEASED,
- ui::VKEY_CONTROL,
- ControlMask, // X sets the mask for KeyRelease.
- &xev);
- ui::KeyEvent event(&xev, false /* is_char */);
- WebKit::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
+ xev.InitKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, ControlMask);
+ ui::KeyEvent event(xev, false /* is_char */);
+ blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// However, modifier bit for Control in |webkit_event| shouldn't be set.
EXPECT_EQ(webkit_event.modifiers, 0);
}
@@ -50,28 +44,24 @@ TEST(WebInputEventAuraTest, TestMakeWebKeyboardEvent) {
// Checks that MakeWebKeyboardEvent returns a correct windowsKeyCode.
TEST(WebInputEventAuraTest, TestMakeWebKeyboardEventWindowsKeyCode) {
#if defined(USE_X11)
- XEvent xev;
+ ui::ScopedXI2Event xev;
{
// Press left Ctrl.
- ui::InitXKeyEventForTesting(ui::ET_KEY_PRESSED,
- ui::VKEY_CONTROL,
- 0, // X does not set ControlMask for KeyPress.
- &xev);
- xev.xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_L);
- ui::KeyEvent event(&xev, false /* is_char */);
- WebKit::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
+ xev.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, 0);
+ XEvent* xevent = xev;
+ xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_L);
+ ui::KeyEvent event(xev, false /* is_char */);
+ blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// ui::VKEY_LCONTROL, instead of ui::VKEY_CONTROL, should be filled.
EXPECT_EQ(ui::VKEY_LCONTROL, webkit_event.windowsKeyCode);
}
{
// Press right Ctrl.
- ui::InitXKeyEventForTesting(ui::ET_KEY_PRESSED,
- ui::VKEY_CONTROL,
- 0, // X does not set ControlMask for KeyPress.
- &xev);
- xev.xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_R);
- ui::KeyEvent event(&xev, false /* is_char */);
- WebKit::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
+ xev.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, 0);
+ XEvent* xevent = xev;
+ xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_R);
+ ui::KeyEvent event(xev, false /* is_char */);
+ blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// ui::VKEY_RCONTROL, instead of ui::VKEY_CONTROL, should be filled.
EXPECT_EQ(ui::VKEY_RCONTROL, webkit_event.windowsKeyCode);
}
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 771b79208c9..06e2dbf4592 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aurawin.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aurawin.cc
@@ -13,7 +13,7 @@ namespace content {
// On Windows, we can just use the builtin WebKit factory methods to fully
// construct our pre-translated events.
-WebKit::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
+blink::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
base::NativeEvent native_event) {
return WebMouseEventBuilder::Build(native_event.hwnd,
native_event.message,
@@ -21,7 +21,7 @@ WebKit::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
native_event.lParam);
}
-WebKit::WebMouseWheelEvent MakeUntranslatedWebMouseWheelEventFromNativeEvent(
+blink::WebMouseWheelEvent MakeUntranslatedWebMouseWheelEventFromNativeEvent(
base::NativeEvent native_event) {
return WebMouseWheelEventBuilder::Build(native_event.hwnd,
native_event.message,
@@ -29,7 +29,7 @@ WebKit::WebMouseWheelEvent MakeUntranslatedWebMouseWheelEventFromNativeEvent(
native_event.lParam);
}
-WebKit::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
+blink::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
base::NativeEvent native_event) {
return WebKeyboardEventBuilder::Build(native_event.hwnd,
native_event.message,
@@ -37,11 +37,11 @@ WebKit::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
native_event.lParam);
}
-WebKit::WebGestureEvent MakeWebGestureEventFromNativeEvent(
+blink::WebGestureEvent MakeWebGestureEventFromNativeEvent(
base::NativeEvent native_event) {
// TODO: Create gestures from native event.
NOTIMPLEMENTED();
- return WebKit::WebGestureEvent();
+ return blink::WebGestureEvent();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/web_input_event_aurax11.cc b/chromium/content/browser/renderer_host/web_input_event_aurax11.cc
index 76ae55f5f19..6bec4934bd7 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aurax11.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aurax11.cc
@@ -89,10 +89,10 @@ int XKeyEventToWindowsKeyCode(XKeyEvent* event) {
} // namespace
-WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
+blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
ui::KeyEvent* event) {
base::NativeEvent native_event = event->native_event();
- WebKit::WebKeyboardEvent webkit_event;
+ blink::WebKeyboardEvent webkit_event;
XKeyEvent* native_key_event = &native_event->xkey;
webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
@@ -100,17 +100,17 @@ WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
switch (native_event->type) {
case KeyPress:
- webkit_event.type = event->is_char() ? WebKit::WebInputEvent::Char :
- WebKit::WebInputEvent::RawKeyDown;
+ webkit_event.type = event->is_char() ? blink::WebInputEvent::Char :
+ blink::WebInputEvent::RawKeyDown;
break;
case KeyRelease:
- webkit_event.type = WebKit::WebInputEvent::KeyUp;
+ webkit_event.type = blink::WebInputEvent::KeyUp;
break;
default:
NOTREACHED();
}
- if (webkit_event.modifiers & WebKit::WebInputEvent::AltKey)
+ if (webkit_event.modifiers & blink::WebInputEvent::AltKey)
webkit_event.isSystemKey = true;
webkit_event.windowsKeyCode = XKeyEventToWindowsKeyCode(native_key_event);
@@ -121,11 +121,11 @@ WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
else
webkit_event.unmodifiedText[0] = ui::GetCharacterFromXEvent(native_event);
- if (webkit_event.modifiers & WebKit::WebInputEvent::ControlKey) {
+ if (webkit_event.modifiers & blink::WebInputEvent::ControlKey) {
webkit_event.text[0] =
GetControlCharacter(
webkit_event.windowsKeyCode,
- webkit_event.modifiers & WebKit::WebInputEvent::ShiftKey);
+ webkit_event.modifiers & blink::WebInputEvent::ShiftKey);
} else {
webkit_event.text[0] = webkit_event.unmodifiedText[0];
}
diff --git a/chromium/content/browser/renderer_host/webmenurunner_mac.mm b/chromium/content/browser/renderer_host/webmenurunner_mac.mm
index a81d2c9e2f6..bb33a007aa6 100644
--- a/chromium/content/browser/renderer_host/webmenurunner_mac.mm
+++ b/chromium/content/browser/renderer_host/webmenurunner_mac.mm
@@ -82,6 +82,14 @@
[[NSAttributedString alloc] initWithString:title attributes:attrs]);
[menuItem setAttributedTitle:attrTitle];
+ // We set the title as well as the attributed title here. The attributed title
+ // will be displayed in the menu, but typeahead will use the non-attributed
+ // string that doesn't contain any leading or trailing whitespace. This is
+ // what Apple uses in WebKit as well:
+ // http://trac.webkit.org/browser/trunk/Source/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.mm#L90
+ NSCharacterSet* whitespaceSet = [NSCharacterSet whitespaceCharacterSet];
+ [menuItem setTitle:[title stringByTrimmingCharactersInSet:whitespaceSet]];
+
[menuItem setTag:[menu_ numberOfItems] - 1];
}
diff --git a/chromium/content/browser/renderer_host/websocket_dispatcher_host.cc b/chromium/content/browser/renderer_host/websocket_dispatcher_host.cc
new file mode 100644
index 00000000000..e7bb0286a81
--- /dev/null
+++ b/chromium/content/browser/renderer_host/websocket_dispatcher_host.cc
@@ -0,0 +1,168 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/websocket_dispatcher_host.h"
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "content/browser/renderer_host/websocket_host.h"
+#include "content/common/websocket_messages.h"
+
+namespace content {
+
+namespace {
+
+// Many methods defined in this file return a WebSocketHostState enum
+// value. Make WebSocketHostState visible at file scope so it doesn't have to be
+// fully-qualified every time.
+typedef WebSocketDispatcherHost::WebSocketHostState WebSocketHostState;
+
+} // namespace
+
+WebSocketDispatcherHost::WebSocketDispatcherHost(
+ const GetRequestContextCallback& get_context_callback)
+ : get_context_callback_(get_context_callback),
+ websocket_host_factory_(
+ base::Bind(&WebSocketDispatcherHost::CreateWebSocketHost,
+ base::Unretained(this))) {}
+
+WebSocketDispatcherHost::WebSocketDispatcherHost(
+ const GetRequestContextCallback& get_context_callback,
+ const WebSocketHostFactory& websocket_host_factory)
+ : get_context_callback_(get_context_callback),
+ websocket_host_factory_(websocket_host_factory) {}
+
+WebSocketHost* WebSocketDispatcherHost::CreateWebSocketHost(int routing_id) {
+ return new WebSocketHost(routing_id, this, get_context_callback_.Run());
+}
+
+bool WebSocketDispatcherHost::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+ switch (message.type()) {
+ case WebSocketHostMsg_AddChannelRequest::ID:
+ case WebSocketMsg_SendFrame::ID:
+ case WebSocketMsg_FlowControl::ID:
+ case WebSocketMsg_DropChannel::ID:
+ break;
+
+ default:
+ // Every message that has not been handled by a previous filter passes
+ // through here, so it is good to pass them on as efficiently as possible.
+ return false;
+ }
+
+ int routing_id = message.routing_id();
+ WebSocketHost* host = GetHost(routing_id);
+ if (message.type() == WebSocketHostMsg_AddChannelRequest::ID) {
+ if (host) {
+ DVLOG(1) << "routing_id=" << routing_id << " already in use.";
+ // The websocket multiplexing spec says to should drop the physical
+ // connection in this case, but there isn't a real physical connection
+ // to the renderer, and killing the renderer for this would seem to be a
+ // little extreme. So for now just ignore the bogus request.
+ return true; // We handled the message (by ignoring it).
+ }
+ host = websocket_host_factory_.Run(routing_id);
+ hosts_.insert(WebSocketHostTable::value_type(routing_id, host));
+ }
+ if (!host) {
+ DVLOG(1) << "Received invalid routing ID " << routing_id
+ << " from renderer.";
+ return true; // We handled the message (by ignoring it).
+ }
+ return host->OnMessageReceived(message, message_was_ok);
+}
+
+WebSocketHost* WebSocketDispatcherHost::GetHost(int routing_id) const {
+ WebSocketHostTable::const_iterator it = hosts_.find(routing_id);
+ return it == hosts_.end() ? NULL : it->second;
+}
+
+WebSocketHostState WebSocketDispatcherHost::SendOrDrop(IPC::Message* message) {
+ const uint32 message_type = message->type();
+ const int32 message_routing_id = message->routing_id();
+ if (!Send(message)) {
+ message = NULL;
+ DVLOG(1) << "Sending of message type " << message_type
+ << " failed. Dropping channel.";
+ DeleteWebSocketHost(message_routing_id);
+ return WEBSOCKET_HOST_DELETED;
+ }
+ return WEBSOCKET_HOST_ALIVE;
+}
+
+WebSocketHostState WebSocketDispatcherHost::SendAddChannelResponse(
+ int routing_id,
+ bool fail,
+ const std::string& selected_protocol,
+ const std::string& extensions) {
+ if (SendOrDrop(new WebSocketMsg_AddChannelResponse(
+ routing_id, fail, selected_protocol, extensions)) ==
+ WEBSOCKET_HOST_DELETED)
+ return WEBSOCKET_HOST_DELETED;
+ if (fail) {
+ DeleteWebSocketHost(routing_id);
+ return WEBSOCKET_HOST_DELETED;
+ }
+ return WEBSOCKET_HOST_ALIVE;
+}
+
+WebSocketHostState WebSocketDispatcherHost::SendFrame(
+ int routing_id,
+ bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data) {
+ return SendOrDrop(new WebSocketMsg_SendFrame(routing_id, fin, type, data));
+}
+
+WebSocketHostState WebSocketDispatcherHost::SendFlowControl(int routing_id,
+ int64 quota) {
+ return SendOrDrop(new WebSocketMsg_FlowControl(routing_id, quota));
+}
+
+WebSocketHostState WebSocketDispatcherHost::SendClosing(int routing_id) {
+ // TODO(ricea): Implement the SendClosing IPC.
+ return WEBSOCKET_HOST_ALIVE;
+}
+
+WebSocketHostState WebSocketDispatcherHost::SendStartOpeningHandshake(
+ int routing_id, const WebSocketHandshakeRequest& request) {
+ return SendOrDrop(new WebSocketMsg_NotifyStartOpeningHandshake(
+ routing_id, request));
+}
+
+WebSocketHostState WebSocketDispatcherHost::SendFinishOpeningHandshake(
+ int routing_id, const WebSocketHandshakeResponse& response) {
+ return SendOrDrop(new WebSocketMsg_NotifyFinishOpeningHandshake(
+ routing_id, response));
+}
+
+WebSocketHostState WebSocketDispatcherHost::DoDropChannel(
+ int routing_id,
+ uint16 code,
+ const std::string& reason) {
+ bool was_clean = true;
+ if (SendOrDrop(
+ new WebSocketMsg_DropChannel(routing_id, was_clean, code, reason)) ==
+ WEBSOCKET_HOST_DELETED)
+ return WEBSOCKET_HOST_DELETED;
+ DeleteWebSocketHost(routing_id);
+ return WEBSOCKET_HOST_DELETED;
+}
+
+WebSocketDispatcherHost::~WebSocketDispatcherHost() {
+ STLDeleteContainerPairSecondPointers(hosts_.begin(), hosts_.end());
+}
+
+void WebSocketDispatcherHost::DeleteWebSocketHost(int routing_id) {
+ WebSocketHostTable::iterator it = hosts_.find(routing_id);
+ DCHECK(it != hosts_.end());
+ delete it->second;
+ hosts_.erase(it);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/websocket_dispatcher_host.h b/chromium/content/browser/renderer_host/websocket_dispatcher_host.h
new file mode 100644
index 00000000000..638178ee9b3
--- /dev/null
+++ b/chromium/content/browser/renderer_host/websocket_dispatcher_host.h
@@ -0,0 +1,140 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_DISPATCHER_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_DISPATCHER_HOST_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/containers/hash_tables.h"
+#include "content/common/content_export.h"
+#include "content/common/websocket.h"
+#include "content/public/browser/browser_message_filter.h"
+
+namespace net {
+class URLRequestContext;
+} // namespace net
+
+namespace content {
+
+struct WebSocketHandshakeRequest;
+struct WebSocketHandshakeResponse;
+class WebSocketHost;
+
+// Creates a WebSocketHost object for each WebSocket channel, and dispatches
+// WebSocketMsg_* messages sent from renderer to the appropriate WebSocketHost.
+class CONTENT_EXPORT WebSocketDispatcherHost : public BrowserMessageFilter {
+ public:
+ typedef base::Callback<net::URLRequestContext*()> GetRequestContextCallback;
+
+ // Given a routing_id, WebSocketHostFactory returns a new instance of
+ // WebSocketHost or its subclass.
+ typedef base::Callback<WebSocketHost*(int)> WebSocketHostFactory; // NOLINT
+
+ // Return value for methods that may delete the WebSocketHost. This enum is
+ // binary-compatible with net::WebSocketEventInterface::ChannelState, to make
+ // conversion cheap. By using a separate enum including net/ header files can
+ // be avoided.
+ enum WebSocketHostState {
+ WEBSOCKET_HOST_ALIVE,
+ WEBSOCKET_HOST_DELETED
+ };
+
+ explicit WebSocketDispatcherHost(
+ const GetRequestContextCallback& get_context_callback);
+
+ // For testing. Specify a factory method that creates mock version of
+ // WebSocketHost.
+ WebSocketDispatcherHost(
+ const GetRequestContextCallback& get_context_callback,
+ const WebSocketHostFactory& websocket_host_factory);
+
+ // BrowserMessageFilter:
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) OVERRIDE;
+
+ // The following methods are used by WebSocketHost::EventInterface to send
+ // IPCs from the browser to the renderer or child process. Any of them may
+ // return WEBSOCKET_HOST_DELETED and delete the WebSocketHost on failure,
+ // leading to the WebSocketChannel and EventInterface also being deleted.
+
+ // Sends a WebSocketMsg_AddChannelResponse IPC, and then deletes and
+ // unregisters the WebSocketHost if |fail| is true.
+ WebSocketHostState SendAddChannelResponse(
+ int routing_id,
+ bool fail,
+ const std::string& selected_protocol,
+ const std::string& extensions) WARN_UNUSED_RESULT;
+
+ // Sends a WebSocketMsg_SendFrame IPC.
+ WebSocketHostState SendFrame(int routing_id,
+ bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data);
+
+ // Sends a WebSocketMsg_FlowControl IPC.
+ WebSocketHostState SendFlowControl(int routing_id,
+ int64 quota) WARN_UNUSED_RESULT;
+
+ // Sends a WebSocketMsg_SendClosing IPC
+ WebSocketHostState SendClosing(int routing_id) WARN_UNUSED_RESULT;
+
+ // Sends a WebSocketMsg_NotifyStartOpeningHandshake IPC.
+ WebSocketHostState SendStartOpeningHandshake(
+ int routing_id,
+ const WebSocketHandshakeRequest& request) WARN_UNUSED_RESULT;
+
+ // Sends a WebSocketMsg_NotifyFinishOpeningHandshake IPC.
+ WebSocketHostState SendFinishOpeningHandshake(
+ int routing_id,
+ const WebSocketHandshakeResponse& response) WARN_UNUSED_RESULT;
+
+ // Sends a WebSocketMsg_DropChannel IPC and deletes and unregisters the
+ // channel.
+ WebSocketHostState DoDropChannel(
+ int routing_id,
+ uint16 code,
+ const std::string& reason) WARN_UNUSED_RESULT;
+
+ private:
+ typedef base::hash_map<int, WebSocketHost*> WebSocketHostTable;
+
+ virtual ~WebSocketDispatcherHost();
+
+ WebSocketHost* CreateWebSocketHost(int routing_id);
+
+ // Looks up a WebSocketHost object by |routing_id|. Returns the object if one
+ // is found, or NULL otherwise.
+ WebSocketHost* GetHost(int routing_id) const;
+
+ // Sends the passed in IPC::Message via the BrowserMessageFilter::Send()
+ // method. If sending the IPC fails, assumes that this connection is no
+ // longer useable, calls DeleteWebSocketHost(), and returns
+ // WEBSOCKET_HOST_DELETED. The behaviour is the same for all message types.
+ WebSocketHostState SendOrDrop(IPC::Message* message) WARN_UNUSED_RESULT;
+
+ // Deletes the WebSocketHost object associated with the given |routing_id| and
+ // removes it from the |hosts_| table.
+ void DeleteWebSocketHost(int routing_id);
+
+ // Table of WebSocketHost objects, owned by this object, indexed by
+ // routing_id.
+ WebSocketHostTable hosts_;
+
+ // A callback which returns the appropriate net::URLRequestContext for us to
+ // use.
+ GetRequestContextCallback get_context_callback_;
+
+ WebSocketHostFactory websocket_host_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketDispatcherHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_DISPATCHER_HOST_H_
diff --git a/chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc b/chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
new file mode 100644
index 00000000000..e771a2c0002
--- /dev/null
+++ b/chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
@@ -0,0 +1,158 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/websocket_dispatcher_host.h"
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/ref_counted.h"
+#include "content/browser/renderer_host/websocket_host.h"
+#include "content/common/websocket.h"
+#include "content/common/websocket_messages.h"
+#include "ipc/ipc_message.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace {
+
+// A mock of WebsocketHost which records received messages.
+class MockWebSocketHost : public WebSocketHost {
+ public:
+ MockWebSocketHost(int routing_id,
+ WebSocketDispatcherHost* dispatcher,
+ net::URLRequestContext* url_request_context)
+ : WebSocketHost(routing_id, dispatcher, url_request_context) {
+ }
+
+ virtual ~MockWebSocketHost() {}
+
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) OVERRIDE{
+ received_messages_.push_back(message);
+ return true;
+ }
+
+ std::vector<IPC::Message> received_messages_;
+};
+
+class WebSocketDispatcherHostTest : public ::testing::Test {
+ public:
+ WebSocketDispatcherHostTest() {
+ dispatcher_host_ =
+ new WebSocketDispatcherHost(
+ base::Bind(&WebSocketDispatcherHostTest::OnGetRequestContext,
+ base::Unretained(this)),
+ base::Bind(&WebSocketDispatcherHostTest::CreateWebSocketHost,
+ base::Unretained(this)));
+ }
+
+ virtual ~WebSocketDispatcherHostTest() {}
+
+ protected:
+ scoped_refptr<WebSocketDispatcherHost> dispatcher_host_;
+
+ // Stores allocated MockWebSocketHost instances. Doesn't take ownership of
+ // them.
+ std::vector<MockWebSocketHost*> mock_hosts_;
+
+ private:
+ net::URLRequestContext* OnGetRequestContext() {
+ return NULL;
+ }
+
+ WebSocketHost* CreateWebSocketHost(int routing_id) {
+ MockWebSocketHost* host =
+ new MockWebSocketHost(routing_id, dispatcher_host_.get(), NULL);
+ mock_hosts_.push_back(host);
+ return host;
+ }
+};
+
+TEST_F(WebSocketDispatcherHostTest, Construct) {
+ // Do nothing.
+}
+
+TEST_F(WebSocketDispatcherHostTest, UnrelatedMessage) {
+ bool message_was_ok = false;
+ IPC::Message message;
+ EXPECT_FALSE(dispatcher_host_->OnMessageReceived(message, &message_was_ok));
+}
+
+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");
+ GURL origin("http://example.com/test");
+ WebSocketHostMsg_AddChannelRequest message(
+ routing_id, socket_url, requested_protocols, origin);
+
+ bool message_was_ok = false;
+ ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message, &message_was_ok));
+
+ ASSERT_EQ(1U, mock_hosts_.size());
+ MockWebSocketHost* host = mock_hosts_[0];
+
+ ASSERT_EQ(1U, host->received_messages_.size());
+ const IPC::Message& forwarded_message = host->received_messages_[0];
+ EXPECT_EQ(WebSocketHostMsg_AddChannelRequest::ID, forwarded_message.type());
+ EXPECT_EQ(routing_id, forwarded_message.routing_id());
+}
+
+TEST_F(WebSocketDispatcherHostTest, SendFrameButNoHostYet) {
+ int routing_id = 123;
+ std::vector<char> data;
+ WebSocketMsg_SendFrame message(
+ routing_id, true, WEB_SOCKET_MESSAGE_TYPE_TEXT, data);
+
+ bool message_was_ok = false;
+ // Expected to be ignored.
+ EXPECT_TRUE(dispatcher_host_->OnMessageReceived(message, &message_was_ok));
+
+ EXPECT_EQ(0U, mock_hosts_.size());
+}
+
+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");
+ GURL origin("http://example.com/test");
+ WebSocketHostMsg_AddChannelRequest add_channel_message(
+ routing_id, socket_url, requested_protocols, origin);
+
+ bool message_was_ok = false;
+
+ ASSERT_TRUE(dispatcher_host_->OnMessageReceived(
+ add_channel_message, &message_was_ok));
+
+ std::vector<char> data;
+ WebSocketMsg_SendFrame send_frame_message(
+ routing_id, true, WEB_SOCKET_MESSAGE_TYPE_TEXT, data);
+
+ EXPECT_TRUE(dispatcher_host_->OnMessageReceived(
+ send_frame_message, &message_was_ok));
+
+ ASSERT_EQ(1U, mock_hosts_.size());
+ MockWebSocketHost* host = mock_hosts_[0];
+
+ ASSERT_EQ(2U, host->received_messages_.size());
+ {
+ const IPC::Message& forwarded_message = host->received_messages_[0];
+ EXPECT_EQ(WebSocketHostMsg_AddChannelRequest::ID, forwarded_message.type());
+ EXPECT_EQ(routing_id, forwarded_message.routing_id());
+ }
+ {
+ const IPC::Message& forwarded_message = host->received_messages_[1];
+ EXPECT_EQ(WebSocketMsg_SendFrame::ID, forwarded_message.type());
+ EXPECT_EQ(routing_id, forwarded_message.routing_id());
+ }
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/websocket_host.cc b/chromium/content/browser/renderer_host/websocket_host.cc
new file mode 100644
index 00000000000..aff172cb869
--- /dev/null
+++ b/chromium/content/browser/renderer_host/websocket_host.cc
@@ -0,0 +1,223 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/websocket_host.h"
+
+#include "base/basictypes.h"
+#include "base/strings/string_util.h"
+#include "content/browser/renderer_host/websocket_dispatcher_host.h"
+#include "content/common/websocket_messages.h"
+#include "ipc/ipc_message_macros.h"
+#include "net/websockets/websocket_channel.h"
+#include "net/websockets/websocket_event_interface.h"
+#include "net/websockets/websocket_frame.h" // for WebSocketFrameHeader::OpCode
+
+namespace content {
+
+namespace {
+
+typedef net::WebSocketEventInterface::ChannelState ChannelState;
+
+// Convert a content::WebSocketMessageType to a
+// net::WebSocketFrameHeader::OpCode
+net::WebSocketFrameHeader::OpCode MessageTypeToOpCode(
+ WebSocketMessageType type) {
+ DCHECK(type == WEB_SOCKET_MESSAGE_TYPE_CONTINUATION ||
+ type == WEB_SOCKET_MESSAGE_TYPE_TEXT ||
+ type == WEB_SOCKET_MESSAGE_TYPE_BINARY);
+ typedef net::WebSocketFrameHeader::OpCode OpCode;
+ // These compile asserts verify that the same underlying values are used for
+ // both types, so we can simply cast between them.
+ COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_CONTINUATION) ==
+ net::WebSocketFrameHeader::kOpCodeContinuation,
+ enum_values_must_match_for_opcode_continuation);
+ COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_TEXT) ==
+ net::WebSocketFrameHeader::kOpCodeText,
+ enum_values_must_match_for_opcode_text);
+ COMPILE_ASSERT(static_cast<OpCode>(WEB_SOCKET_MESSAGE_TYPE_BINARY) ==
+ net::WebSocketFrameHeader::kOpCodeBinary,
+ enum_values_must_match_for_opcode_binary);
+ return static_cast<OpCode>(type);
+}
+
+WebSocketMessageType OpCodeToMessageType(
+ net::WebSocketFrameHeader::OpCode opCode) {
+ DCHECK(opCode == net::WebSocketFrameHeader::kOpCodeContinuation ||
+ opCode == net::WebSocketFrameHeader::kOpCodeText ||
+ opCode == net::WebSocketFrameHeader::kOpCodeBinary);
+ // This cast is guaranteed valid by the COMPILE_ASSERT() statements above.
+ return static_cast<WebSocketMessageType>(opCode);
+}
+
+ChannelState StateCast(WebSocketDispatcherHost::WebSocketHostState host_state) {
+ const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_ALIVE =
+ WebSocketDispatcherHost::WEBSOCKET_HOST_ALIVE;
+ const WebSocketDispatcherHost::WebSocketHostState WEBSOCKET_HOST_DELETED =
+ WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED;
+
+ DCHECK(host_state == WEBSOCKET_HOST_ALIVE ||
+ host_state == WEBSOCKET_HOST_DELETED);
+ // These compile asserts verify that we can get away with using static_cast<>
+ // for the conversion.
+ COMPILE_ASSERT(static_cast<ChannelState>(WEBSOCKET_HOST_ALIVE) ==
+ net::WebSocketEventInterface::CHANNEL_ALIVE,
+ enum_values_must_match_for_state_alive);
+ COMPILE_ASSERT(static_cast<ChannelState>(WEBSOCKET_HOST_DELETED) ==
+ net::WebSocketEventInterface::CHANNEL_DELETED,
+ enum_values_must_match_for_state_deleted);
+ return static_cast<ChannelState>(host_state);
+}
+
+// Implementation of net::WebSocketEventInterface. Receives events from our
+// WebSocketChannel object. Each event is translated to an IPC and sent to the
+// renderer or child process via WebSocketDispatcherHost.
+class WebSocketEventHandler : public net::WebSocketEventInterface {
+ public:
+ WebSocketEventHandler(WebSocketDispatcherHost* dispatcher, int routing_id);
+ virtual ~WebSocketEventHandler();
+
+ // net::WebSocketEventInterface implementation
+
+ // TODO(ricea): Add |extensions| parameter to pass the list of enabled
+ // WebSocket extensions through to the renderer to make it visible to
+ // Javascript.
+ virtual ChannelState OnAddChannelResponse(
+ bool fail,
+ const std::string& selected_subprotocol) OVERRIDE;
+ virtual ChannelState OnDataFrame(bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data) OVERRIDE;
+ virtual ChannelState OnClosingHandshake() OVERRIDE;
+ virtual ChannelState OnFlowControl(int64 quota) OVERRIDE;
+ virtual ChannelState OnDropChannel(uint16 code,
+ const std::string& reason) OVERRIDE;
+
+ private:
+ WebSocketDispatcherHost* const dispatcher_;
+ const int routing_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
+};
+
+WebSocketEventHandler::WebSocketEventHandler(
+ WebSocketDispatcherHost* dispatcher,
+ int routing_id)
+ : dispatcher_(dispatcher), routing_id_(routing_id) {}
+
+WebSocketEventHandler::~WebSocketEventHandler() {
+ DVLOG(1) << "WebSocketEventHandler destroyed routing_id=" << routing_id_;
+}
+
+ChannelState WebSocketEventHandler::OnAddChannelResponse(
+ bool fail,
+ const std::string& selected_protocol) {
+ DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse"
+ << " routing_id=" << routing_id_ << " fail=" << fail
+ << " selected_protocol=\"" << selected_protocol << "\"";
+ return StateCast(dispatcher_->SendAddChannelResponse(
+ routing_id_, fail, selected_protocol, std::string()));
+}
+
+ChannelState WebSocketEventHandler::OnDataFrame(
+ bool fin,
+ net::WebSocketFrameHeader::OpCode type,
+ const std::vector<char>& data) {
+ DVLOG(3) << "WebSocketEventHandler::OnDataFrame"
+ << " routing_id=" << routing_id_ << " fin=" << fin
+ << " type=" << type << " data is " << data.size() << " bytes";
+ return StateCast(dispatcher_->SendFrame(
+ routing_id_, fin, OpCodeToMessageType(type), data));
+}
+
+ChannelState WebSocketEventHandler::OnClosingHandshake() {
+ DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake"
+ << " routing_id=" << routing_id_;
+ return StateCast(dispatcher_->SendClosing(routing_id_));
+}
+
+ChannelState WebSocketEventHandler::OnFlowControl(int64 quota) {
+ DVLOG(3) << "WebSocketEventHandler::OnFlowControl"
+ << " routing_id=" << routing_id_ << " quota=" << quota;
+ return StateCast(dispatcher_->SendFlowControl(routing_id_, quota));
+}
+
+ChannelState WebSocketEventHandler::OnDropChannel(uint16 code,
+ const std::string& reason) {
+ DVLOG(3) << "WebSocketEventHandler::OnDropChannel"
+ << " routing_id=" << routing_id_ << " code=" << code
+ << " reason=\"" << reason << "\"";
+ return StateCast(dispatcher_->DoDropChannel(routing_id_, code, reason));
+}
+
+} // namespace
+
+WebSocketHost::WebSocketHost(int routing_id,
+ WebSocketDispatcherHost* dispatcher,
+ net::URLRequestContext* url_request_context)
+ : routing_id_(routing_id) {
+ DVLOG(1) << "WebSocketHost: created routing_id=" << routing_id;
+ scoped_ptr<net::WebSocketEventInterface> event_interface(
+ new WebSocketEventHandler(dispatcher, routing_id));
+ channel_.reset(
+ new net::WebSocketChannel(event_interface.Pass(), url_request_context));
+}
+
+WebSocketHost::~WebSocketHost() {}
+
+bool WebSocketHost::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(WebSocketHost, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(WebSocketHostMsg_AddChannelRequest, OnAddChannelRequest)
+ IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, OnSendFrame)
+ IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, OnFlowControl)
+ IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, OnDropChannel)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP_EX()
+ return handled;
+}
+
+void WebSocketHost::OnAddChannelRequest(
+ const GURL& socket_url,
+ const std::vector<std::string>& requested_protocols,
+ const GURL& origin) {
+ DVLOG(3) << "WebSocketHost::OnAddChannelRequest"
+ << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url
+ << "\" requested_protocols=\""
+ << JoinString(requested_protocols, ", ") << "\" origin=\"" << origin
+ << "\"";
+
+ channel_->SendAddChannelRequest(socket_url, requested_protocols, origin);
+}
+
+void WebSocketHost::OnSendFrame(bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data) {
+ DVLOG(3) << "WebSocketHost::OnSendFrame"
+ << " routing_id=" << routing_id_ << " fin=" << fin
+ << " type=" << type << " data is " << data.size() << " bytes";
+
+ channel_->SendFrame(fin, MessageTypeToOpCode(type), data);
+}
+
+void WebSocketHost::OnFlowControl(int64 quota) {
+ DVLOG(3) << "WebSocketHost::OnFlowControl"
+ << " routing_id=" << routing_id_ << " quota=" << quota;
+
+ channel_->SendFlowControl(quota);
+}
+
+void WebSocketHost::OnDropChannel(bool was_clean,
+ uint16 code,
+ const std::string& reason) {
+ DVLOG(3) << "WebSocketHost::OnDropChannel"
+ << " routing_id=" << routing_id_ << " was_clean=" << was_clean
+ << " code=" << code << " reason=\"" << reason << "\"";
+
+ // TODO(yhirano): Handle |was_clean| appropriately.
+ channel_->StartClosingHandshake(code, reason);
+}
+
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/websocket_host.h b/chromium/content/browser/renderer_host/websocket_host.h
new file mode 100644
index 00000000000..ba10f1c3885
--- /dev/null
+++ b/chromium/content/browser/renderer_host/websocket_host.h
@@ -0,0 +1,71 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_HOST_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "content/common/websocket.h"
+
+class GURL;
+
+namespace net {
+class WebSocketChannel;
+class URLRequestContext;
+} // namespace net
+
+namespace IPC {
+class Message;
+} // namespace IPC
+
+namespace content {
+
+class WebSocketDispatcherHost;
+
+// Host of net::WebSocketChannel. The lifetime of an instance of this class is
+// completely controlled by the WebSocketDispatcherHost object.
+class CONTENT_EXPORT WebSocketHost {
+ public:
+ WebSocketHost(int routing_id,
+ WebSocketDispatcherHost* dispatcher,
+ net::URLRequestContext* url_request_context);
+ virtual ~WebSocketHost();
+
+ // General message dispatch. WebSocketDispatcherHost::OnMessageReceived
+ // delegates to this method after looking up the |routing_id|.
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok);
+
+ private:
+ // 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 GURL& origin);
+
+ void OnSendFrame(bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data);
+
+ void OnFlowControl(int64 quota);
+
+ void OnDropChannel(bool was_clean, uint16 code, const std::string& reason);
+
+ // The channel we use to send events to the network.
+ scoped_ptr<net::WebSocketChannel> channel_;
+
+ // The ID used to route messages.
+ int routing_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_HOST_H_
diff --git a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
index 628df860641..91f0243b2e7 100644
--- a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
+++ b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
@@ -27,6 +27,25 @@ class MockProxyConfigService : public net::ProxyConfigService {
}
};
+class TestResolveProxyMsgHelper : public ResolveProxyMsgHelper {
+ public:
+ TestResolveProxyMsgHelper(
+ net::ProxyService* proxy_service,
+ IPC::Listener* listener)
+ : ResolveProxyMsgHelper(proxy_service),
+ listener_(listener) {}
+ virtual bool Send(IPC::Message* message) OVERRIDE {
+ listener_->OnMessageReceived(*message);
+ delete message;
+ return true;
+ }
+
+ protected:
+ virtual ~TestResolveProxyMsgHelper() {}
+
+ IPC::Listener* listener_;
+};
+
class ResolveProxyMsgHelperTest : public testing::Test, public IPC::Listener {
public:
struct PendingResult {
@@ -43,11 +62,10 @@ class ResolveProxyMsgHelperTest : public testing::Test, public IPC::Listener {
: resolver_(new net::MockAsyncProxyResolver),
service_(
new net::ProxyService(new MockProxyConfigService, resolver_, NULL)),
- helper_(new ResolveProxyMsgHelper(service_.get())),
+ helper_(new TestResolveProxyMsgHelper(service_.get(), this)),
message_loop_(base::MessageLoop::TYPE_IO),
io_thread_(BrowserThread::IO, &message_loop_) {
test_sink_.AddFilter(this);
- helper_->OnFilterAdded(&test_sink_);
}
protected:
diff --git a/chromium/content/browser/resource_context_impl.cc b/chromium/content/browser/resource_context_impl.cc
index 448015888f0..14115a4887c 100644
--- a/chromium/content/browser/resource_context_impl.cc
+++ b/chromium/content/browser/resource_context_impl.cc
@@ -13,6 +13,8 @@
#include "content/browser/webui/url_data_manager_backend.h"
#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;
@@ -35,6 +37,11 @@ class NonOwningZoomData : public base::SupportsUserData::Data {
HostZoomMap* host_zoom_map_;
};
+// Used by the default implementation of GetMediaDeviceIDSalt, below.
+std::string ReturnEmptySalt() {
+ return std::string();
+}
+
} // namespace
@@ -54,6 +61,23 @@ ResourceContext::~ResourceContext() {
DetachUserDataThread();
}
+ResourceContext::SaltCallback ResourceContext::GetMediaDeviceIDSalt() {
+ return base::Bind(&ReturnEmptySalt);
+}
+
+scoped_ptr<net::ClientCertStore> ResourceContext::CreateClientCertStore() {
+ return scoped_ptr<net::ClientCertStore>();
+}
+
+void ResourceContext::CreateKeygenHandler(
+ uint32 key_size_in_bits,
+ const std::string& challenge_string,
+ const GURL& url,
+ const base::Callback<void(scoped_ptr<net::KeygenHandler>)>& callback) {
+ callback.Run(make_scoped_ptr(
+ new net::KeygenHandler(key_size_in_bits, challenge_string, url)));
+}
+
ChromeBlobStorageContext* GetChromeBlobStorageContextForResourceContext(
ResourceContext* resource_context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
diff --git a/chromium/content/browser/resources/gpu/gpu_internals.html b/chromium/content/browser/resources/gpu/gpu_internals.html
index ad59aa817aa..ef4def79b32 100644
--- a/chromium/content/browser/resources/gpu/gpu_internals.html
+++ b/chromium/content/browser/resources/gpu/gpu_internals.html
@@ -40,8 +40,8 @@ tabbox tabpanels {
<script src="chrome://resources/js/cr/ui/focus_outline_manager.js"></script>
<script src="chrome://resources/js/cr/ui/tabs.js"></script>
<script src="chrome://resources/js/util.js"></script>
-<script src="chrome://gpu/gpu_internals.js"></script>
-<script src="chrome://gpu/strings.js"></script>
+<script src="gpu_internals.js"></script>
+<script src="strings.js"></script>
</head>
<body>
<div id="debug-div">
diff --git a/chromium/content/browser/resources/gpu/info_view.js b/chromium/content/browser/resources/gpu/info_view.js
index d7d21d5a749..e736d8e49a8 100644
--- a/chromium/content/browser/resources/gpu/info_view.js
+++ b/chromium/content/browser/resources/gpu/info_view.js
@@ -37,6 +37,11 @@ cr.define('gpu', function() {
// Client info
if (browserBridge.clientInfo) {
var clientInfo = browserBridge.clientInfo;
+
+ var commandLineParts = clientInfo.command_line.split(' ');
+ commandLineParts.shift(); // Pop off the exe path
+ var commandLineString = commandLineParts.join(' ')
+
this.setTable_('client-info', [
{
description: 'Data exported',
@@ -65,6 +70,10 @@ cr.define('gpu', function() {
{
description: '2D graphics backend',
value: clientInfo.graphics_backend
+ },
+ {
+ description: 'Command Line Args',
+ value: commandLineString
}]);
} else {
this.setText_('client-info', '... loading...');
@@ -83,6 +92,7 @@ cr.define('gpu', function() {
'flash_stage3d_baseline': 'Flash Stage3D Baseline profile',
'texture_sharing': 'Texture Sharing',
'video_decode': 'Video Decode',
+ 'video_encode': 'Video Encode',
'video': 'Video',
// GPU Switching
'gpu_switching': 'GPU Switching',
@@ -151,24 +161,24 @@ cr.define('gpu', function() {
if (gpuInfo.featureStatus) {
// feature status list
featureStatusList.textContent = '';
- for (i = 0; i < gpuInfo.featureStatus.featureStatus.length;
- i++) {
- var feature = gpuInfo.featureStatus.featureStatus[i];
+ for (var featureName in gpuInfo.featureStatus.featureStatus) {
+ var featureStatus =
+ gpuInfo.featureStatus.featureStatus[featureName];
var featureEl = document.createElement('li');
var nameEl = document.createElement('span');
- if (!featureLabelMap[feature.name])
- console.log('Missing featureLabel for', feature.name);
- nameEl.textContent = featureLabelMap[feature.name] + ': ';
+ if (!featureLabelMap[featureName])
+ console.log('Missing featureLabel for', featureName);
+ nameEl.textContent = featureLabelMap[featureName] + ': ';
featureEl.appendChild(nameEl);
var statusEl = document.createElement('span');
- if (!statusLabelMap[feature.status])
- console.log('Missing statusLabel for', feature.status);
- if (!statusClassMap[feature.status])
- console.log('Missing statusClass for', feature.status);
- statusEl.textContent = statusLabelMap[feature.status];
- statusEl.className = statusClassMap[feature.status];
+ if (!statusLabelMap[featureStatus])
+ console.log('Missing statusLabel for', featureStatus);
+ if (!statusClassMap[featureStatus])
+ console.log('Missing statusClass for', featureStatus);
+ statusEl.textContent = statusLabelMap[featureStatus];
+ statusEl.className = statusClassMap[featureStatus];
featureEl.appendChild(statusEl);
featureStatusList.appendChild(featureEl);
diff --git a/chromium/content/browser/resources/media/client_renderer.js b/chromium/content/browser/resources/media/client_renderer.js
index cac70e8b839..5cdedaabb47 100644
--- a/chromium/content/browser/resources/media/client_renderer.js
+++ b/chromium/content/browser/resources/media/client_renderer.js
@@ -5,13 +5,16 @@
var ClientRenderer = (function() {
var ClientRenderer = function() {
this.playerListElement = document.getElementById('player-list');
- this.audioStreamListElement = document.getElementById('audio-stream-list');
- this.propertiesTable = document.getElementById('property-table');
- this.logTable = document.getElementById('log');
+ this.propertiesTable =
+ document.getElementById('property-table').querySelector('tbody');
+ this.logTable = document.getElementById('log').querySelector('tbody');
this.graphElement = document.getElementById('graphs');
+ this.propertyName = document.getElementById('property-name');
this.selectedPlayer = null;
- this.selectedStream = null;
+ this.selectedAudioComponentType = null;
+ this.selectedAudioComponentId = null;
+ this.selectedAudioCompontentData = null;
this.selectedPlayerLogIndex = 0;
@@ -26,6 +29,8 @@ var ClientRenderer = (function() {
this.clipboardTextarea = document.getElementById('clipboard-textarea');
this.clipboardButton = document.getElementById('copy-button');
this.clipboardButton.onclick = this.copyToClipboard_.bind(this);
+
+ this.hiddenKeys = ['component_id', 'component_type', 'owner_id'];
};
function removeChildren(element) {
@@ -46,18 +51,39 @@ var ClientRenderer = (function() {
};
ClientRenderer.prototype = {
- audioStreamAdded: function(audioStreams, audioStreamAdded) {
- this.redrawAudioStreamList_(audioStreams);
- },
-
- audioStreamUpdated: function(audioStreams, stream, key, value) {
- if (stream === this.selectedStream) {
- this.drawProperties_(stream);
+ /**
+ * Called when an audio component is added to the collection.
+ * @param componentType Integer AudioComponent enum value; must match values
+ * from the AudioLogFactory::AudioComponent enum.
+ * @param components The entire map of components (name -> dict).
+ */
+ audioComponentAdded: function(componentType, components) {
+ this.redrawAudioComponentList_(componentType, components);
+
+ // Redraw the component if it's currently selected.
+ if (this.selectedAudioComponentType == componentType &&
+ this.selectedAudioComponentId &&
+ this.selectedAudioComponentId in components) {
+ this.selectAudioComponent_(
+ componentType, this.selectedAudioComponentId,
+ components[this.selectedAudioComponentId]);
}
},
- audioStreamRemoved: function(audioStreams, audioStreamRemoved) {
- this.redrawAudioStreamList_(audioStreams);
+ /**
+ * Called when an audio component is removed from the collection.
+ * @param componentType Integer AudioComponent enum value; must match values
+ * from the AudioLogFactory::AudioComponent enum.
+ * @param components The entire map of components (name -> dict).
+ */
+ audioComponentRemoved: function(componentType, components) {
+ this.redrawAudioComponentList_(componentType, components);
+
+ // Clear the component if it was previously currently selected.
+ if (this.selectedAudioComponentType == componentType &&
+ !(this.selectedAudioComponentId in components)) {
+ this.selectAudioComponent_(null, null, {});
+ }
},
/**
@@ -96,59 +122,95 @@ var ClientRenderer = (function() {
}
},
- redrawAudioStreamList_: function(streams) {
- removeChildren(this.audioStreamListElement);
+ redrawAudioComponentList_: function(componentType, components) {
+ function redrawList(renderer, baseName, element) {
+ var fragment = document.createDocumentFragment();
+ for (id in components) {
+ var li = document.createElement('li');
+ var friendlyName = baseName + ' ' + id;
+ li.appendChild(createButton(
+ friendlyName, renderer.selectAudioComponent_.bind(
+ renderer, componentType, id, components[id], friendlyName)));
+ fragment.appendChild(li);
+ }
+ removeChildren(element);
+ element.appendChild(fragment);
+ }
- for (id in streams) {
- var li = document.createElement('li');
- li.appendChild(createButton(
- id, this.selectAudioStream_.bind(this, streams[id])));
- this.audioStreamListElement.appendChild(li);
+ switch (componentType) {
+ case 0:
+ redrawList(this, 'Controller', document.getElementById(
+ 'audio-input-controller-list'));
+ break;
+ case 1:
+ redrawList(this, 'Controller', document.getElementById(
+ 'audio-output-controller-list'));
+ break;
+ case 2:
+ redrawList(this, 'Stream', document.getElementById(
+ 'audio-output-stream-list'));
+ break;
+ default:
+ break;
}
},
- selectAudioStream_: function(audioStream) {
- this.selectedStream = audioStream;
+ selectAudioComponent_: function(
+ componentType, componentId, componentData, friendlyName) {
this.selectedPlayer = null;
- this.drawProperties_(audioStream);
- removeChildren(this.logTable.querySelector('tbody'));
+ this.selectedAudioComponentType = componentType;
+ this.selectedAudioComponentId = componentId;
+ this.selectedAudioCompontentData = componentData;
+ this.drawProperties_(componentData);
+ removeChildren(this.logTable);
removeChildren(this.graphElement);
+
+ removeChildren(this.propertyName);
+ this.propertyName.appendChild(document.createTextNode(friendlyName));
},
redrawPlayerList_: function(players) {
- removeChildren(this.playerListElement);
-
+ var fragment = document.createDocumentFragment();
for (id in players) {
- var li = document.createElement('li');
var player = players[id];
var usableName = player.properties.name ||
player.properties.url ||
- 'player ' + player.id;
+ 'Player ' + player.id;
+ var li = document.createElement('li');
li.appendChild(createButton(
usableName, this.selectPlayer_.bind(this, player)));
- this.playerListElement.appendChild(li);
+ fragment.appendChild(li);
}
+ removeChildren(this.playerListElement);
+ this.playerListElement.appendChild(fragment);
},
selectPlayer_: function(player) {
this.selectedPlayer = player;
this.selectedPlayerLogIndex = 0;
- this.selectedStream = null;
+ this.selectedAudioComponentType = null;
+ this.selectedAudioComponentId = null;
+ this.selectedAudioCompontentData = null;
this.drawProperties_(player.properties);
- removeChildren(this.logTable.querySelector('tbody'));
+ removeChildren(this.logTable);
removeChildren(this.graphElement);
this.drawLog_();
this.drawGraphs_();
+ removeChildren(this.propertyName);
+ this.propertyName.appendChild(document.createTextNode('Player'));
},
drawProperties_: function(propertyMap) {
removeChildren(this.propertiesTable);
+ var sortedKeys = Object.keys(propertyMap).sort();
+ for (var i = 0; i < sortedKeys.length; ++i) {
+ var key = sortedKeys[i];
+ if (this.hiddenKeys.indexOf(key) >= 0)
+ continue;
- for (key in propertyMap) {
var value = propertyMap[key];
-
var row = this.propertiesTable.insertRow(-1);
var keyCell = row.insertCell(-1);
var valueCell = row.insertCell(-1);
@@ -160,9 +222,11 @@ var ClientRenderer = (function() {
appendEventToLog_: function(event) {
if (this.filterFunction(event.key)) {
- var row = this.logTable.querySelector('tbody').insertRow(-1);
+ var row = this.logTable.insertRow(-1);
- row.insertCell(-1).appendChild(document.createTextNode(
+ var timestampCell = row.insertCell(-1);
+ timestampCell.classList.add('timestamp');
+ timestampCell.appendChild(document.createTextNode(
util.millisecondsToString(event.time)));
row.insertCell(-1).appendChild(document.createTextNode(event.key));
row.insertCell(-1).appendChild(document.createTextNode(event.value));
@@ -247,7 +311,7 @@ var ClientRenderer = (function() {
},
copyToClipboard_: function() {
- var properties = this.selectedStream ||
+ var properties = this.selectedAudioCompontentData ||
this.selectedPlayer.properties || false;
if (!properties) {
return;
@@ -263,18 +327,14 @@ var ClientRenderer = (function() {
}
this.clipboardTextarea.value = stringBuffer.join('');
- this.clipboardTextarea.classList.remove('hidden');
+ this.clipboardTextarea.classList.remove('hiddenClipboard');
this.clipboardTextarea.focus();
this.clipboardTextarea.select();
- // The act of copying anything from the textarea gets canceled
- // if the element in question gets the class 'hidden' (which contains the
- // css property display:none) before the event is finished. For this, it
- // is necessary put the property setting on the event loop to be executed
- // after the copy has taken place.
- this.clipboardTextarea.oncopy = function(event) {
+ // Hide the clipboard element when it loses focus.
+ this.clipboardTextarea.onblur = function(event) {
setTimeout(function(element) {
- event.target.classList.add('hidden');
+ event.target.classList.add('hiddenClipboard');
}, 0);
};
},
@@ -295,7 +355,7 @@ var ClientRenderer = (function() {
};
if (this.selectedPlayer) {
- removeChildren(this.logTable.querySelector('tbody'));
+ removeChildren(this.logTable);
this.selectedPlayerLogIndex = 0;
this.drawLog_();
}
diff --git a/chromium/content/browser/resources/media/dump_creator.js b/chromium/content/browser/resources/media/dump_creator.js
index 5daddabc61c..af17cf3a4ee 100644
--- a/chromium/content/browser/resources/media/dump_creator.js
+++ b/chromium/content/browser/resources/media/dump_creator.js
@@ -55,12 +55,12 @@ var DumpCreator = (function() {
this.root_.appendChild(content);
content.innerHTML = '<button disabled></button> Status: <span></span>' +
- '<div><form><button>' +
+ '<div><a><button>' +
'Download the PeerConnection updates and stats data' +
- '</button></form></div>';
+ '</button></a></div>';
content.getElementsByTagName('button')[0].addEventListener(
'click', this.onRtpToggled_.bind(this));
- content.getElementsByTagName('button')[1].addEventListener(
+ content.getElementsByTagName('a')[0].addEventListener(
'click', this.onDownloadData_.bind(this));
this.updateDisplay_();
@@ -77,8 +77,8 @@ var DumpCreator = (function() {
new Blob([JSON.stringify(peerConnectionDataStore, null, ' ')],
{type: 'octet/stream'});
var URL = window.webkitURL.createObjectURL(textBlob);
- this.root_.getElementsByTagName('form')[0].action = URL;
- // The default action of the button will submit the form.
+ this.root_.getElementsByTagName('a')[0].href = URL;
+ // The default action of the anchor will download the URL.
},
/**
diff --git a/chromium/content/browser/resources/media/main.js b/chromium/content/browser/resources/media/main.js
index 14b9918a2de..cb239da2d54 100644
--- a/chromium/content/browser/resources/media/main.js
+++ b/chromium/content/browser/resources/media/main.js
@@ -40,8 +40,8 @@ var media = (function() {
};
media.onReceiveEverything = function(everything) {
- for (var key in everything.audio_streams) {
- media.updateAudioStream(everything.audio_streams[key]);
+ for (var component in everything) {
+ media.updateAudioComponent(everything[component]);
}
};
@@ -123,31 +123,20 @@ var media = (function() {
});
};
- // For whatever reason, addAudioStream is also called on
- // the removal of audio streams.
- media.addAudioStream = function(event) {
- switch (event.status) {
- case 'created':
- manager.addAudioStream(event.id);
- manager.updateAudioStream(event.id, { 'playing': event.playing });
- break;
+ media.updateAudioComponent = function(component) {
+ var uniqueComponentId = component.owner_id + ':' + component.component_id;
+ switch (component.status) {
case 'closed':
- manager.removeAudioStream(event.id);
+ manager.removeAudioComponent(
+ component.component_type, uniqueComponentId);
+ break;
+ default:
+ manager.updateAudioComponent(
+ component.component_type, uniqueComponentId, component);
break;
}
};
- media.updateAudioStream = function(stream) {
- manager.addAudioStream(stream.id);
- manager.updateAudioStream(stream.id, stream);
- };
-
- media.onItemDeleted = function() {
- // This only gets called when an audio stream is removed, which
- // for whatever reason is also handled by addAudioStream...
- // Because it is already handled, we can safely ignore it.
- };
-
media.onPlayerOpen = function(id, timestamp) {
manager.addPlayer(id, timestamp);
};
diff --git a/chromium/content/browser/resources/media/manager.js b/chromium/content/browser/resources/media/manager.js
index 1ba130181e5..80cd03273b7 100644
--- a/chromium/content/browser/resources/media/manager.js
+++ b/chromium/content/browser/resources/media/manager.js
@@ -14,45 +14,47 @@ var Manager = (function() {
function Manager(clientRenderer) {
this.players_ = {};
- this.audioStreams_ = {};
+ this.audioComponents_ = [];
this.clientRenderer_ = clientRenderer;
}
Manager.prototype = {
/**
- * Adds an audio-stream to the dictionary of audio-streams to manage.
- * @param id The unique-id of the audio-stream.
- */
- addAudioStream: function(id) {
- this.audioStreams_[id] = this.audioStreams_[id] || {};
- this.clientRenderer_.audioStreamAdded(this.audioStreams_,
- this.audioStreams_[id]);
- },
-
- /**
- * Sets properties of an audiostream.
- * @param id The unique-id of the audio-stream.
- * @param properties A dictionary of properties to be added to the
- * audio-stream.
+ * Updates an audio-component.
+ * @param componentType Integer AudioComponent enum value; must match values
+ * from the AudioLogFactory::AudioComponent enum.
+ * @param componentId The unique-id of the audio-component.
+ * @param componentData The actual component data dictionary.
*/
- updateAudioStream: function(id, properties) {
- for (var key in properties) {
- this.audioStreams_[id][key] = properties[key];
+ updateAudioComponent: function(componentType, componentId, componentData) {
+ if (!(componentType in this.audioComponents_))
+ this.audioComponents_[componentType] = {};
+ if (!(componentId in this.audioComponents_[componentType])) {
+ this.audioComponents_[componentType][componentId] = componentData;
+ } else {
+ for (var key in componentData) {
+ this.audioComponents_[componentType][componentId][key] =
+ componentData[key];
+ }
}
- this.clientRenderer_.audioStreamAdded(
- this.audioStreams_, this.audioStreams_[id]);
+ this.clientRenderer_.audioComponentAdded(
+ componentType, this.audioComponents_[componentType]);
},
/**
* Removes an audio-stream from the manager.
* @param id The unique-id of the audio-stream.
*/
- removeAudioStream: function(id) {
- this.clientRenderer_.audioStreamRemoved(
- this.audioStreams_, this.audioStreams_[id]);
- delete this.audioStreams_[id];
- },
+ removeAudioComponent: function(componentType, componentId) {
+ if (!(componentType in this.audioComponents_) ||
+ !(componentId in this.audioComponents_[componentType])) {
+ return;
+ }
+ delete this.audioComponents_[componentType][componentId];
+ this.clientRenderer_.audioComponentRemoved(
+ componentType, this.audioComponents_[componentType]);
+ },
/**
* Adds a player to the list of players to manage.
diff --git a/chromium/content/browser/resources/media/media_internals.css b/chromium/content/browser/resources/media/media_internals.css
index 9e6ab7608f2..041527f951c 100644
--- a/chromium/content/browser/resources/media/media_internals.css
+++ b/chromium/content/browser/resources/media/media_internals.css
@@ -9,21 +9,30 @@ body,
padding: 0;
width: 100%;
height: 100%;
-
- font-family: 'Lucida Grande', sans-serif;
}
table {
- border-collapse: collapse;
+ font-family: sans-serif;
+ -webkit-font-smoothing: antialiased;
+ font-size: 115%;
+ width: auto;
+ overflow: auto;
+ display: block;
+}
+th {
+ background-color: rgb(112, 196, 105);
+ font-weight: normal;
+ color: white;
+ padding: 2px;
+ text-align: center;
+ min-width: 230px;
}
td {
- border: 1px solid black;
+ background-color: rgb(238, 238, 238);
+ padding: 2px;
+ color: rgb(111, 111, 111);
word-wrap: break-word;
- max-width: 200px;
-}
-thead {
- color: rgb(50,50,50);
- font-size: 1.1em;
+ min-width: 230px;
}
h1,
@@ -56,26 +65,22 @@ h3 {
}
#player-list-wrapper,
-#audio-stream-list-wrapper {
+#audio-component-list-wrapper {
flex-grow: 1;
align-self: stretch;
min-width: 200px;
- max-width: 200px;
overflow: auto;
}
#player-list-wrapper ul,
#player-list-wrapper li,
-#audio-stream-list-wrapper ul,
-#audio-stream-list-wrapper li {
- margin: 0;
- padding: 0;
+#audio-component-list-wrapper ul,
+#audio-component-list-wrapper li {
+ padding: 0px;
list-style-type: none;
}
#list-wrapper button {
- margin: 0;
- padding: 0;
- width: 170px;
+ padding: 0px;
}
#property-wrapper,
@@ -103,6 +108,10 @@ h3 {
top: 25%;
}
-.hidden {
+.hiddenClipboard {
display: none;
}
+
+.timestamp {
+ min-width: 115px;
+} \ No newline at end of file
diff --git a/chromium/content/browser/resources/media/media_internals.html b/chromium/content/browser/resources/media/media_internals.html
index 6bfc48198d4..1f762305598 100644
--- a/chromium/content/browser/resources/media/media_internals.html
+++ b/chromium/content/browser/resources/media/media_internals.html
@@ -13,26 +13,39 @@ found in the LICENSE file.
</head>
<body>
- <textarea id="clipboard-textarea" class="hidden"></textarea>
+ <textarea id="clipboard-textarea" class="hiddenClipboard"></textarea>
<div id="container">
<div id="list-wrapper">
<div id="player-list-wrapper">
<h2>Players</h2>
<ul id="player-list"></ul>
</div>
- <div id="audio-stream-list-wrapper">
- <h2>Audio Streams</h2>
- <ul id="audio-stream-list"></ul>
+ <div id="audio-component-list-wrapper">
+ <h2>Input Controllers</h2>
+ <ul id="audio-input-controller-list"></ul>
+ </div>
+ <div id="audio-component-list-wrapper">
+ <h2>Output Controllers</h2>
+ <ul id="audio-output-controller-list"></ul>
+ </div>
+ <div id="audio-component-list-wrapper">
+ <h2>Output Streams</h2>
+ <ul id="audio-output-stream-list"></ul>
</div>
</div>
<div id="property-wrapper">
- <h2>Properties <button id="copy-button">copy to clipboard</button> </h2>
+ <h2>
+ <span id="property-name"></span> Properties
+ <button id="copy-button">copy to clipboard</button>
+ </h2>
<table id="property-table">
<thead>
<tr>
- <td>Property Name</td> <td>Value</td>
+ <th>Property</th>
+ <th>Value</th>
</tr>
</thead>
+ <tbody></tbody>
</table>
<ul id="graphs"></ul>
</div>
@@ -43,15 +56,15 @@ found in the LICENSE file.
<table id="log">
<thead>
<tr>
- <td>Timestamp</td>
- <td>Property</td>
- <td>Value</td>
+ <th class="timestamp">Timestamp</th>
+ <th>Property</th>
+ <th>Value</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
- <script src="chrome://media-internals/media_internals.js"></script>
+ <script src="media_internals.js"></script>
</body>
</html>
diff --git a/chromium/content/browser/resources/media/stats_graph_helper.js b/chromium/content/browser/resources/media/stats_graph_helper.js
index ce9e7185776..1a20666dad6 100644
--- a/chromium/content/browser/resources/media/stats_graph_helper.js
+++ b/chromium/content/browser/resources/media/stats_graph_helper.js
@@ -87,6 +87,7 @@ var statsNameBlackList = {
'googComponent': true,
'googLocalAddress': true,
'googRemoteAddress': true,
+ 'googFingerprint': true,
};
var graphViews = {};
diff --git a/chromium/content/browser/resources/media/stats_table.js b/chromium/content/browser/resources/media/stats_table.js
index 6b3ae5230de..313484702e3 100644
--- a/chromium/content/browser/resources/media/stats_table.js
+++ b/chromium/content/browser/resources/media/stats_table.js
@@ -56,6 +56,9 @@ var StatsTable = (function(ssrcInfoManager) {
container = document.createElement('div');
container.id = containerId;
container.className = 'stats-table-container';
+ var head = document.createElement('div');
+ head.textContent = 'Stats Tables';
+ container.appendChild(head);
peerConnectionElement.appendChild(container);
}
return container;
@@ -78,8 +81,14 @@ var StatsTable = (function(ssrcInfoManager) {
var table = $(tableId);
if (!table) {
var container = this.ensureStatsTableContainer_(peerConnectionElement);
+ var details = document.createElement('details');
+ container.appendChild(details);
+ var summary = document.createElement('summary');
+ summary.textContent = report.id;
+ details.appendChild(summary);
+
table = document.createElement('table');
- container.appendChild(table);
+ details.appendChild(table);
table.id = tableId;
table.border = 1;
diff --git a/chromium/content/browser/resources/media/tab_view.js b/chromium/content/browser/resources/media/tab_view.js
new file mode 100644
index 00000000000..953ec2fae11
--- /dev/null
+++ b/chromium/content/browser/resources/media/tab_view.js
@@ -0,0 +1,119 @@
+// 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.
+
+/**
+ * A TabView provides the ability to create tabs and switch between tabs. It's
+ * responsible for creating the DOM and managing the visibility of each tab.
+ * The first added tab is active by default and the others hidden.
+ */
+var TabView = (function() {
+ 'use strict';
+
+ /**
+ * @constructor
+ * @param {Element} root The root DOM element containing the tabs.
+ */
+ function TabView(root) {
+ this.root_ = root;
+ this.ACTIVE_TAB_HEAD_CLASS_ = 'active-tab-head';
+ this.ACTIVE_TAB_BODY_CLASS_ = 'active-tab-body';
+ this.TAB_HEAD_CLASS_ = 'tab-head';
+ this.TAB_BODY_CLASS_ = 'tab-body';
+
+ /**
+ * A mapping for an id to the tab elements.
+ * @type {!Object<string, !TabDom>}
+ * @private
+ */
+ this.tabElements_ = {};
+
+ this.headBar_ = null;
+ this.activeTabId_ = null;
+ this.initializeHeadBar_();
+ }
+
+ // Creates a simple object containing the tab head and body elements.
+ function TabDom(h, b) {
+ this.head = h;
+ this.body = b;
+ }
+
+ TabView.prototype = {
+ /**
+ * Adds a tab with the specified id and title.
+ * @param {string} id
+ * @param {string} title
+ * @return {!Element} The tab body element.
+ */
+ addTab: function(id, title) {
+ if (this.tabElements_[id])
+ throw 'Tab already exists: ' + id;
+
+ var head = document.createElement('div');
+ head.className = this.TAB_HEAD_CLASS_;
+ head.textContent = id;
+ head.title = title;
+ this.headBar_.appendChild(head);
+ head.addEventListener('click', this.switchTab_.bind(this, id));
+
+ var body = document.createElement('div');
+ body.className = this.TAB_BODY_CLASS_;
+ body.id = id;
+ this.root_.appendChild(body);
+
+ this.tabElements_[id] = new TabDom(head, body);
+
+ if (!this.activeTabId_) {
+ this.switchTab_(id);
+ }
+ return this.tabElements_[id].body;
+ },
+
+ /** Removes the tab. @param {string} id */
+ removeTab: function(id) {
+ if (!this.tabElements_[id])
+ return;
+ this.tabElements_[id].head.parentNode.removeChild(
+ this.tabElements_[id].head);
+ this.tabElements_[id].body.parentNode.removeChild(
+ this.tabElements_[id].body);
+
+ delete this.tabElements_[id];
+ if (this.activeTabId_ == id) {
+ this.switchTab_(Object.keys(this.tabElements_)[0]);
+ }
+ },
+
+ /**
+ * Switches the specified tab into view.
+ *
+ * @param {string} activeId The id the of the tab that should be switched to
+ * active state.
+ * @private
+ */
+ switchTab_: function(activeId) {
+ if (this.activeTabId_ && this.tabElements_[this.activeTabId_]) {
+ this.tabElements_[this.activeTabId_].body.classList.remove(
+ this.ACTIVE_TAB_BODY_CLASS_);
+ this.tabElements_[this.activeTabId_].head.classList.remove(
+ this.ACTIVE_TAB_HEAD_CLASS_);
+ }
+ this.activeTabId_ = activeId;
+ if (this.tabElements_[activeId]) {
+ this.tabElements_[activeId].body.classList.add(
+ this.ACTIVE_TAB_BODY_CLASS_);
+ this.tabElements_[activeId].head.classList.add(
+ this.ACTIVE_TAB_HEAD_CLASS_);
+ }
+ },
+
+ /** Initializes the bar containing the tab heads. */
+ initializeHeadBar_: function() {
+ this.headBar_ = document.createElement('div');
+ this.root_.appendChild(this.headBar_);
+ this.headBar_.style.textAlign = 'center';
+ },
+ };
+ return TabView;
+})();
diff --git a/chromium/content/browser/resources/media/webrtc_internals.css b/chromium/content/browser/resources/media/webrtc_internals.css
index c0ac402728f..096a227b523 100644
--- a/chromium/content/browser/resources/media/webrtc_internals.css
+++ b/chromium/content/browser/resources/media/webrtc_internals.css
@@ -8,12 +8,10 @@
padding-bottom: 3px;
}
-.peer-connection-hidden > *:not(h3) {
- display:none;
-}
-
.update-log-container {
float: left;
+ width: 50em;
+ overflow: auto;
}
.ssrc-info-block {
@@ -47,43 +45,19 @@
.stats-table-container {
float: left;
padding: 0 0 0 0;
+ width: 50em;
+ overflow: auto;
}
-body {
- font-family: 'Lucida Grande', sans-serif;
- padding: 20px;
-}
-
-details {
- min-width: 30em;
-}
-
-h3 + div {
+.stats-table-container >div:first-child {
font-size: 0.8em;
- margin: 0 0 1.2em 0;
-}
-
-h2 {
- border-bottom: 1px solid #eee;
- color: #666;
- font-size: 1.1em;
- margin: 0 0 1.6em 0;
- padding: 0 0 0.7em 0;
-}
-
-h3 {
- color: #555;
- cursor: pointer;
- font-size: 0.9em;
- margin: 2em 0 0.5em 0;
- text-decoration: underline;
+ font-weight: bold;
+ text-align: center;
+ padding: 0 0 1em 0;
}
-li {
- clear: both;
- list-style-type: none;
- margin: none;
- padding: none;
+body {
+ font-family: 'Lucida Grande', sans-serif;
}
table {
@@ -95,10 +69,8 @@ td {
border: none;
font-size: 0.8em;
padding: 0 1em 0.5em 0;
-}
-
-td:first-child {
- padding-top: 0.3em;
+ min-width: 10em;
+ word-break: break-all;
}
table > tr {
@@ -111,8 +83,24 @@ th {
padding: 0 0 0.5em 0;
}
-ul {
- margin: none;
- padding: none;
- -webkit-padding-start: 0px;
+.tab-head {
+ background-color: rgb(220, 220, 220);
+ margin: 10px 5px 0 5px;
+ text-decoration: underline;
+ cursor: pointer;
+ display: inline-block;
+ width: 32%;
+}
+.active-tab-head {
+ background-color: turquoise;
+ font-weight: bold;
+}
+.tab-body {
+ border: 1px solid turquoise;
+ border-top-width: 3px;
+ padding: 0 10px 500px 10px;
+ display: none;
+}
+.active-tab-body {
+ display: block;
}
diff --git a/chromium/content/browser/resources/media/webrtc_internals.html b/chromium/content/browser/resources/media/webrtc_internals.html
index 72576207f88..b6a538f4e2b 100644
--- a/chromium/content/browser/resources/media/webrtc_internals.html
+++ b/chromium/content/browser/resources/media/webrtc_internals.html
@@ -5,13 +5,10 @@
<title>WebRTC Internals</title>
<link rel="stylesheet" href="webrtc_internals.css">
<script src="chrome://resources/js/util.js"></script>
- <script src="chrome://webrtc-internals/webrtc_internals.js"></script>
+ <script src="webrtc_internals.js"></script>
</head>
<body>
- <h2>WebRTC Internals</h2>
- <p>
- <ul id="peer-connections-list">
- </ul>
+ <p id='content-root'>
</p>
</body>
</html>
diff --git a/chromium/content/browser/resources/media/webrtc_internals.js b/chromium/content/browser/resources/media/webrtc_internals.js
index 5bc56da3ebe..6d3cfc16e3a 100644
--- a/chromium/content/browser/resources/media/webrtc_internals.js
+++ b/chromium/content/browser/resources/media/webrtc_internals.js
@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
-var peerConnectionsListElem = null;
+var tabView = null;
var ssrcInfoManager = null;
var peerConnectionUpdateTable = null;
var statsTable = null;
@@ -79,6 +78,7 @@ var PeerConnectionRecord = (function() {
// will be shifted out when the buffer is full.
var MAX_STATS_DATA_POINT_BUFFER_SIZE = 1000;
+<include src="tab_view.js"/>
<include src="data_series.js"/>
<include src="ssrc_info_manager.js"/>
<include src="stats_graph_helper.js"/>
@@ -88,8 +88,8 @@ var MAX_STATS_DATA_POINT_BUFFER_SIZE = 1000;
function initialize() {
- peerConnectionsListElem = $('peer-connections-list');
- dumpCreator = new DumpCreator(peerConnectionsListElem);
+ dumpCreator = new DumpCreator($('content-root'));
+ tabView = new TabView($('content-root'));
ssrcInfoManager = new SsrcInfoManager();
peerConnectionUpdateTable = new PeerConnectionUpdateTable();
statsTable = new StatsTable(ssrcInfoManager);
@@ -98,7 +98,7 @@ function initialize() {
// Requests stats from all peer connections every second.
window.setInterval(function() {
- if (peerConnectionsListElem.getElementsByTagName('li').length > 0)
+ if (Object.keys(peerConnectionDataStore).length > 0)
chrome.send('getAllStats');
}, 1000);
}
@@ -158,7 +158,7 @@ function removePeerConnection(data) {
var element = $(getPeerConnectionId(data));
if (element) {
delete peerConnectionDataStore[element.id];
- peerConnectionsListElem.removeChild(element);
+ tabView.removeTab(element.id);
}
}
@@ -180,23 +180,11 @@ function addPeerConnection(data) {
var peerConnectionElement = $(id);
if (!peerConnectionElement) {
- peerConnectionElement = document.createElement('li');
- peerConnectionsListElem.appendChild(peerConnectionElement);
- peerConnectionElement.id = id;
+ peerConnectionElement = tabView.addTab(id, data.url);
}
peerConnectionElement.innerHTML =
- '<h3>PeerConnection ' + peerConnectionElement.id + '</h3>' +
- '<div>' + data.url + ' ' + data.servers + ' ' + data.constraints +
- '</div>';
-
- // Clicking the heading can expand or collapse the peer connection item.
- peerConnectionElement.firstChild.title = 'Click to collapse or expand';
- peerConnectionElement.firstChild.addEventListener('click', function(e) {
- if (e.target.parentElement.className == '')
- e.target.parentElement.className = 'peer-connection-hidden';
- else
- e.target.parentElement.className = '';
- });
+ '<p>' + data.url + ' ' + data.servers + ' ' + data.constraints +
+ '</p>';
return peerConnectionElement;
}
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index 2eb7b51885b..fc648f0000f 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -3,11 +3,19 @@
// found in the LICENSE file.
#include "base/command_line.h"
+#include "base/containers/hash_tables.h"
+#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
+#include "content/browser/dom_storage/session_storage_namespace_impl.h"
+#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/view_messages.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
@@ -15,6 +23,61 @@
namespace content {
+namespace {
+
+// This is a helper function for the tests which attempt to create a
+// duplicate RenderViewHost or RenderWidgetHost. It tries to create two objects
+// with the same process and routing ids, which causes a collision.
+// It creates a couple of windows in process 1, which causes a few routing ids
+// to be allocated. Then a cross-process navigation is initiated, which causes a
+// new process 2 to be created and have a pending RenderViewHost for it. The
+// routing id of the RenderViewHost which is target for a duplicate is set
+// into |target_routing_id| and the pending RenderViewHost which is used for
+// the attempt is the return value.
+RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
+ int* target_routing_id) {
+ GURL foo("http://foo.com/files/simple_page.html");
+
+ // Start off with initial navigation, so we get the first process allocated.
+ NavigateToURL(shell, foo);
+
+ // Open another window, so we generate some more routing ids.
+ ShellAddedObserver shell2_observer;
+ EXPECT_TRUE(ExecuteScript(
+ shell->web_contents(), "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.
+ EXPECT_EQ(shell->web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
+ shell2->web_contents()->GetRenderViewHost()->GetProcess()->GetID());
+ *target_routing_id =
+ shell2->web_contents()->GetRenderViewHost()->GetRoutingID();
+ EXPECT_NE(*target_routing_id,
+ shell->web_contents()->GetRenderViewHost()->GetRoutingID());
+
+ // Now, simulate a link click coming from the renderer.
+ GURL extension_url("https://bar.com/files/simple_page.html");
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents());
+ wc->RequestOpenURL(
+ shell->web_contents()->GetRenderViewHost(), extension_url,
+ Referrer(), CURRENT_TAB, wc->GetFrameTree()->root()->frame_id(),
+ false, true);
+
+ // Since the navigation above requires a cross-process swap, there will be a
+ // pending RenderViewHost. Ensure it exists and is in a different process
+ // than the initial page.
+ RenderViewHostImpl* pending_rvh =
+ wc->GetRenderManagerForTesting()->pending_render_view_host();
+ EXPECT_TRUE(pending_rvh != NULL);
+ EXPECT_NE(shell->web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
+ pending_rvh->GetProcess()->GetID());
+
+ return pending_rvh;
+}
+
+} // namespace
+
+
// The goal of these tests will be to "simulate" exploited renderer processes,
// which can send arbitrary IPC messages and confuse browser process internal
// state, leading to security bugs. We are trying to verify that the browser
@@ -52,4 +115,54 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, SetWebUIProperty) {
terminated.Wait();
}
+// This is a test for crbug.com/312016 attempting to create duplicate
+// RenderViewHosts. SetupForDuplicateHosts sets up this test case and leaves
+// it in a state with pending RenderViewHost. Before the commit of the new
+// pending RenderViewHost, this test case creates a new window through the new
+// process.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+ AttemptDuplicateRenderViewHost) {
+ int duplicate_routing_id = MSG_ROUTING_NONE;
+ RenderViewHostImpl* pending_rvh =
+ PrepareToDuplicateHosts(shell(), &duplicate_routing_id);
+ EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id);
+
+ // Since this test executes on the UI thread and hopping threads might cause
+ // different timing in the test, let's simulate a CreateNewWindow call coming
+ // from the IO thread.
+ ViewHostMsg_CreateWindow_Params params;
+ DOMStorageContextWrapper* dom_storage_context =
+ static_cast<DOMStorageContextWrapper*>(
+ BrowserContext::GetStoragePartition(
+ shell()->web_contents()->GetBrowserContext(),
+ pending_rvh->GetSiteInstance())->GetDOMStorageContext());
+ scoped_refptr<SessionStorageNamespaceImpl> session_storage(
+ new SessionStorageNamespaceImpl(dom_storage_context));
+ // Cause a deliberate collision in routing ids.
+ int main_frame_routing_id = duplicate_routing_id + 1;
+ pending_rvh->CreateNewWindow(
+ duplicate_routing_id, main_frame_routing_id, params, session_storage);
+
+ // If the above operation doesn't cause a crash, the test has succeeded!
}
+
+// This is a test for crbug.com/312016. It tries to create two RenderWidgetHosts
+// with the same process and routing ids, which causes a collision. It is almost
+// identical to the AttemptDuplicateRenderViewHost test case.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+ AttemptDuplicateRenderWidgetHost) {
+ int duplicate_routing_id = MSG_ROUTING_NONE;
+ RenderViewHostImpl* pending_rvh =
+ PrepareToDuplicateHosts(shell(), &duplicate_routing_id);
+ EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id);
+
+ // Since this test executes on the UI thread and hopping threads might cause
+ // different timing in the test, let's simulate a CreateNewWidget call coming
+ // from the IO thread. Use the existing window routing id to cause a
+ // deliberate collision.
+ pending_rvh->CreateNewWidget(duplicate_routing_id, blink::WebPopupTypeSelect);
+
+ // If the above operation doesn't crash, the test has succeeded!
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
new file mode 100644
index 00000000000..07998845986
--- /dev/null
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -0,0 +1,99 @@
+// 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/service_worker/embedded_worker_instance.h"
+
+#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "url/gurl.h"
+
+namespace content {
+
+EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
+ registry_->RemoveWorker(embedded_worker_id_);
+}
+
+bool EmbeddedWorkerInstance::Start(
+ int64 service_worker_version_id,
+ const GURL& script_url) {
+ DCHECK(status_ == STOPPED);
+ if (!ChooseProcess())
+ return false;
+ status_ = STARTING;
+ bool success = registry_->StartWorker(
+ process_id_,
+ embedded_worker_id_,
+ service_worker_version_id,
+ script_url);
+ if (!success) {
+ status_ = STOPPED;
+ process_id_ = -1;
+ }
+ return success;
+}
+
+bool EmbeddedWorkerInstance::Stop() {
+ DCHECK(status_ == STARTING || status_ == RUNNING);
+ const bool success = registry_->StopWorker(process_id_, embedded_worker_id_);
+ if (success)
+ status_ = STOPPING;
+ return success;
+}
+
+void EmbeddedWorkerInstance::AddProcessReference(int process_id) {
+ ProcessRefMap::iterator found = process_refs_.find(process_id);
+ if (found == process_refs_.end())
+ found = process_refs_.insert(std::make_pair(process_id, 0)).first;
+ ++found->second;
+}
+
+void EmbeddedWorkerInstance::ReleaseProcessReference(int process_id) {
+ ProcessRefMap::iterator found = process_refs_.find(process_id);
+ if (found == process_refs_.end()) {
+ NOTREACHED() << "Releasing unknown process ref " << process_id;
+ return;
+ }
+ if (--found->second == 0)
+ process_refs_.erase(found);
+}
+
+EmbeddedWorkerInstance::EmbeddedWorkerInstance(
+ EmbeddedWorkerRegistry* registry,
+ int embedded_worker_id)
+ : registry_(registry),
+ embedded_worker_id_(embedded_worker_id),
+ status_(STOPPED),
+ process_id_(-1),
+ thread_id_(-1) {
+}
+
+void EmbeddedWorkerInstance::OnStarted(int thread_id) {
+ DCHECK(status_ == STARTING);
+ status_ = RUNNING;
+ thread_id_ = thread_id;
+}
+
+void EmbeddedWorkerInstance::OnStopped() {
+ status_ = STOPPED;
+ process_id_ = -1;
+ thread_id_ = -1;
+}
+
+bool EmbeddedWorkerInstance::ChooseProcess() {
+ DCHECK_EQ(-1, process_id_);
+ // Naive implementation; chooses a process which has the biggest number of
+ // associated providers (so that hopefully likely live longer).
+ ProcessRefMap::iterator max_ref_iter = process_refs_.end();
+ for (ProcessRefMap::iterator iter = process_refs_.begin();
+ iter != process_refs_.end(); ++iter) {
+ if (max_ref_iter == process_refs_.end() ||
+ max_ref_iter->second < iter->second)
+ max_ref_iter = iter;
+ }
+ if (max_ref_iter == process_refs_.end())
+ return false;
+ process_id_ = max_ref_iter->first;
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
new file mode 100644
index 00000000000..fb0fe19bb6c
--- /dev/null
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -0,0 +1,102 @@
+// 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_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/gtest_prod_util.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+
+class GURL;
+
+namespace content {
+
+class EmbeddedWorkerRegistry;
+
+// This gives an interface to control one EmbeddedWorker instance, which
+// may be 'in-waiting' or running in one of the child processes added by
+// AddProcessReference().
+class CONTENT_EXPORT EmbeddedWorkerInstance {
+ public:
+ enum Status {
+ STOPPED,
+ STARTING,
+ RUNNING,
+ STOPPING,
+ };
+
+ ~EmbeddedWorkerInstance();
+
+ // Starts the worker. It is invalid to call this when the worker is
+ // not in STOPPED status.
+ // This returns false if starting a worker fails immediately, e.g. when
+ // IPC couldn't be sent to the worker or no process was available.
+ bool Start(int64 service_worker_version_id,
+ const GURL& script_url);
+
+ // Stops the worker. It is invalid to call this when the worker is
+ // not in STARTING or RUNNING status.
+ // This returns false if stopping a worker fails immediately, e.g. when
+ // IPC couldn't be sent to the worker.
+ bool Stop();
+
+ // Add or remove |process_id| to the internal process set where this
+ // worker can be started.
+ void AddProcessReference(int process_id);
+ void ReleaseProcessReference(int process_id);
+
+ int embedded_worker_id() const { return embedded_worker_id_; }
+ Status status() const { return status_; }
+ int process_id() const { return process_id_; }
+ int thread_id() const { return thread_id_; }
+
+ private:
+ friend class EmbeddedWorkerRegistry;
+ FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, StartAndStop);
+
+ typedef std::map<int, int> ProcessRefMap;
+
+ // Constructor is called via EmbeddedWorkerRegistry::CreateWorker().
+ // This instance holds a ref of |registry|.
+ EmbeddedWorkerInstance(EmbeddedWorkerRegistry* registry,
+ int embedded_worker_id);
+
+ // Called back from Registry when the worker instance has ack'ed that
+ // its WorkerGlobalScope is actually started on |thread_id| in the
+ // child process.
+ // This will change the internal status from STARTING to RUNNING.
+ void OnStarted(int thread_id);
+
+ // Called back from Registry when the worker instance has ack'ed that
+ // its WorkerGlobalScope is actually stopped in the child process.
+ // This will change the internal status from STARTING or RUNNING to
+ // STOPPED.
+ void OnStopped();
+
+ // Chooses a process to start this worker and populate process_id_.
+ // Returns false when no process is available.
+ bool ChooseProcess();
+
+ scoped_refptr<EmbeddedWorkerRegistry> registry_;
+ const int embedded_worker_id_;
+ Status status_;
+
+ // Current running information. -1 indicates the worker is not running.
+ int process_id_;
+ int thread_id_;
+
+ ProcessRefMap process_refs_;
+
+ DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstance);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
new file mode 100644
index 00000000000..45b2f29dc7f
--- /dev/null
+++ b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -0,0 +1,137 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/stl_util.h"
+#include "content/browser/service_worker/embedded_worker_instance.h"
+#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/common/service_worker_messages.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sender.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+typedef std::vector<IPC::Message*> MessageList;
+
+class FakeSender : public IPC::Sender {
+ public:
+ FakeSender() {}
+ virtual ~FakeSender() {
+ STLDeleteContainerPointers(sent_messages_.begin(), sent_messages_.end());
+ }
+
+ // IPC::Sender implementation.
+ virtual bool Send(IPC::Message* message) OVERRIDE {
+ sent_messages_.push_back(message);
+ return true;
+ }
+
+ const MessageList& sent_messages() { return sent_messages_; }
+
+ private:
+ MessageList sent_messages_;
+ DISALLOW_COPY_AND_ASSIGN(FakeSender);
+};
+
+} // namespace
+
+class EmbeddedWorkerInstanceTest : public testing::Test {
+ protected:
+ EmbeddedWorkerInstanceTest()
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+ virtual void SetUp() OVERRIDE {
+ context_.reset(new ServiceWorkerContextCore(base::FilePath(), NULL));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ context_.reset();
+ }
+
+ EmbeddedWorkerRegistry* embedded_worker_registry() {
+ DCHECK(context_);
+ return context_->embedded_worker_registry();
+ }
+
+ TestBrowserThreadBundle thread_bundle_;
+ scoped_ptr<ServiceWorkerContextCore> context_;
+
+ DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest);
+};
+
+TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
+ scoped_ptr<EmbeddedWorkerInstance> worker =
+ embedded_worker_registry()->CreateWorker();
+ EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+
+ FakeSender fake_sender;
+ const int process_id = 11;
+ const int thread_id = 33;
+ const int64 service_worker_version_id = 55L;
+ const GURL url("http://example.com/worker.js");
+
+ // This fails as we have no available process yet.
+ EXPECT_FALSE(worker->Start(service_worker_version_id, url));
+ EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+
+ // Simulate adding one process to the worker.
+ worker->AddProcessReference(process_id);
+ embedded_worker_registry()->AddChildProcessSender(process_id, &fake_sender);
+
+ // Start should succeed.
+ EXPECT_TRUE(worker->Start(service_worker_version_id, url));
+ EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
+
+ // Simulate an upcall from embedded worker to notify that it's started.
+ worker->OnStarted(thread_id);
+ EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+ EXPECT_EQ(process_id, worker->process_id());
+ EXPECT_EQ(thread_id, worker->thread_id());
+
+ // Stop the worker.
+ EXPECT_TRUE(worker->Stop());
+ EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, worker->status());
+
+ // Simulate an upcall from embedded worker to notify that it's stopped.
+ worker->OnStopped();
+ EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+
+ // Verify that we've sent two messages to start and terminate the worker.
+ const MessageList& messages = fake_sender.sent_messages();
+ ASSERT_EQ(2U, messages.size());
+ ASSERT_EQ(ServiceWorkerMsg_StartWorker::ID, messages[0]->type());
+ ASSERT_EQ(ServiceWorkerMsg_TerminateWorker::ID, messages[1]->type());
+}
+
+TEST_F(EmbeddedWorkerInstanceTest, ChooseProcess) {
+ scoped_ptr<EmbeddedWorkerInstance> worker =
+ embedded_worker_registry()->CreateWorker();
+ EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+
+ FakeSender fake_sender;
+
+ // Simulate adding processes to the worker.
+ // Process 1 has 1 ref, 2 has 2 refs and 3 has 3 refs.
+ worker->AddProcessReference(1);
+ worker->AddProcessReference(2);
+ worker->AddProcessReference(2);
+ worker->AddProcessReference(3);
+ worker->AddProcessReference(3);
+ worker->AddProcessReference(3);
+ embedded_worker_registry()->AddChildProcessSender(1, &fake_sender);
+ embedded_worker_registry()->AddChildProcessSender(2, &fake_sender);
+ embedded_worker_registry()->AddChildProcessSender(3, &fake_sender);
+
+ // Process 3 has the biggest # of references and it should be chosen.
+ EXPECT_TRUE(worker->Start(1L, GURL("http://example.com/worker.js")));
+ EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
+ EXPECT_EQ(3, worker->process_id());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.cc b/chromium/content/browser/service_worker/embedded_worker_registry.cc
new file mode 100644
index 00000000000..f8f0fbe7d5f
--- /dev/null
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.cc
@@ -0,0 +1,70 @@
+// 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/service_worker/embedded_worker_registry.h"
+
+#include "base/stl_util.h"
+#include "content/browser/service_worker/embedded_worker_instance.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/common/service_worker_messages.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sender.h"
+
+namespace content {
+
+EmbeddedWorkerRegistry::EmbeddedWorkerRegistry(
+ base::WeakPtr<ServiceWorkerContextCore> context)
+ : context_(context),
+ next_embedded_worker_id_(0) {}
+
+scoped_ptr<EmbeddedWorkerInstance> EmbeddedWorkerRegistry::CreateWorker() {
+ scoped_ptr<EmbeddedWorkerInstance> worker(
+ new EmbeddedWorkerInstance(this, next_embedded_worker_id_));
+ worker_map_[next_embedded_worker_id_++] = worker.get();
+ return worker.Pass();
+}
+
+void EmbeddedWorkerRegistry::RemoveWorker(int embedded_worker_id) {
+ DCHECK(ContainsKey(worker_map_, embedded_worker_id));
+ worker_map_.erase(embedded_worker_id);
+}
+
+bool EmbeddedWorkerRegistry::StartWorker(
+ int process_id,
+ int embedded_worker_id,
+ int64 service_worker_version_id,
+ const GURL& script_url) {
+ return Send(process_id,
+ new ServiceWorkerMsg_StartWorker(embedded_worker_id,
+ service_worker_version_id,
+ script_url));
+}
+
+bool EmbeddedWorkerRegistry::StopWorker(int process_id,
+ int embedded_worker_id) {
+ return Send(process_id,
+ new ServiceWorkerMsg_TerminateWorker(embedded_worker_id));
+}
+
+void EmbeddedWorkerRegistry::AddChildProcessSender(
+ int process_id, IPC::Sender* sender) {
+ process_sender_map_[process_id] = sender;
+}
+
+void EmbeddedWorkerRegistry::RemoveChildProcessSender(int process_id) {
+ process_sender_map_.erase(process_id);
+}
+
+EmbeddedWorkerRegistry::~EmbeddedWorkerRegistry() {}
+
+bool EmbeddedWorkerRegistry::Send(int process_id, IPC::Message* message) {
+ if (!context_)
+ return false;
+ ProcessToSenderMap::iterator found = process_sender_map_.find(process_id);
+ if (found == process_sender_map_.end())
+ return false;
+ return found->second->Send(message);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.h b/chromium/content/browser/service_worker/embedded_worker_registry.h
new file mode 100644
index 00000000000..8860e374b5c
--- /dev/null
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.h
@@ -0,0 +1,77 @@
+// 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_SERVICE_WORKER_EMBEDDED_WORKER_REGISTRY_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_REGISTRY_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+
+class GURL;
+
+namespace IPC {
+class Message;
+class Sender;
+}
+
+namespace content {
+
+class EmbeddedWorkerInstance;
+class ServiceWorkerContextCore;
+
+// Acts as a thin stub between MessageFilter and each EmbeddedWorkerInstance,
+// which sends/receives messages to/from each EmbeddedWorker in child process.
+//
+// Hangs off ServiceWorkerContextCore (its reference is also held by each
+// EmbeddedWorkerInstance). Operated only on IO thread.
+class CONTENT_EXPORT EmbeddedWorkerRegistry
+ : public NON_EXPORTED_BASE(base::RefCounted<EmbeddedWorkerRegistry>) {
+ public:
+ explicit EmbeddedWorkerRegistry(
+ base::WeakPtr<ServiceWorkerContextCore> context);
+
+ // Creates and removes a new worker instance entry for bookkeeping.
+ // This doesn't actually start or stop the worker.
+ scoped_ptr<EmbeddedWorkerInstance> CreateWorker();
+ void RemoveWorker(int embedded_worker_id);
+
+ // Called from EmbeddedWorkerInstance, relayed to the child process.
+ bool StartWorker(int process_id,
+ int embedded_worker_id,
+ int64 service_worker_version_id,
+ const GURL& script_url);
+ bool StopWorker(int process_id,
+ int embedded_worker_id);
+
+ // Keeps a map from process_id to sender information.
+ void AddChildProcessSender(int process_id, IPC::Sender* sender);
+ void RemoveChildProcessSender(int process_id);
+
+ private:
+ friend class base::RefCounted<EmbeddedWorkerRegistry>;
+
+ ~EmbeddedWorkerRegistry();
+ bool Send(int process_id, IPC::Message* message);
+
+ typedef std::map<int, EmbeddedWorkerInstance*> WorkerInstanceMap;
+ typedef std::map<int, IPC::Sender*> ProcessToSenderMap;
+
+ base::WeakPtr<ServiceWorkerContextCore> context_;
+
+ WorkerInstanceMap worker_map_;
+ ProcessToSenderMap process_sender_map_;
+
+ int next_embedded_worker_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerRegistry);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_REGISTRY_H_
diff --git a/chromium/content/browser/service_worker/service_worker_context.cc b/chromium/content/browser/service_worker/service_worker_context.cc
deleted file mode 100644
index ed9f669d7f4..00000000000
--- a/chromium/content/browser/service_worker/service_worker_context.cc
+++ /dev/null
@@ -1,25 +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/service_worker/service_worker_context.h"
-
-#include "base/files/file_path.h"
-#include "webkit/browser/quota/quota_manager.h"
-
-namespace content {
-
-const base::FilePath::CharType kServiceWorkerDirectory[] =
- FILE_PATH_LITERAL("ServiceWorker");
-
-ServiceWorkerContext::ServiceWorkerContext(
- const base::FilePath& path,
- quota::QuotaManagerProxy* quota_manager_proxy)
- : quota_manager_proxy_(quota_manager_proxy) {
- if (!path.empty())
- path_ = path.Append(kServiceWorkerDirectory);
-}
-
-ServiceWorkerContext::~ServiceWorkerContext() {}
-
-} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context.h b/chromium/content/browser/service_worker/service_worker_context.h
index 5b290b7a317..d9f51f3165c 100644
--- a/chromium/content/browser/service_worker/service_worker_context.h
+++ b/chromium/content/browser/service_worker/service_worker_context.h
@@ -5,38 +5,22 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_H_
-#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace quota {
-class QuotaManagerProxy;
-}
+#include "base/basictypes.h"
namespace content {
-// This class manages metadata associated with all service workers,
-// including:
-// - persistent storage of pattern -> service worker scripts
-// - initialization and initial installation of service workers
-// - dispatching of non-fetch events to service workers
-class ServiceWorkerContext
- : public base::RefCountedThreadSafe<ServiceWorkerContext> {
+// Represents the per-BrowserContext ServiceWorker data.
+class ServiceWorkerContext {
public:
- // This is owned by the StoragePartition, which will supply it with
- // the local path on disk.
- ServiceWorkerContext(const base::FilePath& path,
- quota::QuotaManagerProxy* quota_manager_proxy);
+ // TODO(michaeln): This class is a place holder for content/public api
+ // which will come later. Promote this class when we get there.
- private:
- friend class base::RefCountedThreadSafe<ServiceWorkerContext>;
- ~ServiceWorkerContext();
+ protected:
+ ServiceWorkerContext() {}
+ virtual ~ServiceWorkerContext() {}
- scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_;
- base::FilePath path_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContext);
};
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.cc b/chromium/content/browser/service_worker/service_worker_context_core.cc
new file mode 100644
index 00000000000..048d33bd836
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_context_core.cc
@@ -0,0 +1,99 @@
+// 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/service_worker/service_worker_context_core.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/strings/string_util.h"
+#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/browser/service_worker/service_worker_register_job.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_switches.h"
+#include "url/gurl.h"
+
+namespace content {
+
+ServiceWorkerContextCore::ServiceWorkerContextCore(
+ const base::FilePath& path,
+ quota::QuotaManagerProxy* quota_manager_proxy)
+ : storage_(new ServiceWorkerStorage(path, quota_manager_proxy)),
+ embedded_worker_registry_(new EmbeddedWorkerRegistry(AsWeakPtr())) {}
+
+ServiceWorkerContextCore::~ServiceWorkerContextCore() {}
+
+ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
+ int process_id, int provider_id) {
+ ProviderMap* map = GetProviderMapForProcess(process_id);
+ if (!map)
+ return NULL;
+ return map->Lookup(provider_id);
+}
+
+void ServiceWorkerContextCore::AddProviderHost(
+ scoped_ptr<ServiceWorkerProviderHost> host) {
+ ServiceWorkerProviderHost* host_ptr = host.release(); // we take ownership
+ ProviderMap* map = GetProviderMapForProcess(host_ptr->process_id());
+ if (!map) {
+ map = new ProviderMap;
+ providers_.AddWithID(map, host_ptr->process_id());
+ }
+ map->AddWithID(host_ptr, host_ptr->provider_id());
+}
+
+void ServiceWorkerContextCore::RemoveProviderHost(
+ int process_id, int provider_id) {
+ ProviderMap* map = GetProviderMapForProcess(process_id);
+ DCHECK(map);
+ map->Remove(provider_id);
+}
+
+void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
+ int process_id) {
+ if (providers_.Lookup(process_id))
+ providers_.Remove(process_id);
+}
+
+bool ServiceWorkerContextCore::IsEnabled() {
+ return CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableServiceWorker);
+}
+
+void ServiceWorkerContextCore::RegisterServiceWorker(
+ const GURL& pattern,
+ const GURL& script_url,
+ const RegistrationCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ storage_->Register(pattern,
+ script_url,
+ base::Bind(&ServiceWorkerContextCore::RegistrationComplete,
+ AsWeakPtr(),
+ callback));
+}
+
+void ServiceWorkerContextCore::UnregisterServiceWorker(
+ const GURL& pattern,
+ const UnregistrationCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ storage_->Unregister(pattern, callback);
+}
+
+void ServiceWorkerContextCore::RegistrationComplete(
+ const ServiceWorkerContextCore::RegistrationCallback& callback,
+ ServiceWorkerRegistrationStatus status,
+ const scoped_refptr<ServiceWorkerRegistration>& registration) {
+ if (status != REGISTRATION_OK) {
+ DCHECK(!registration);
+ callback.Run(status, -1L);
+ }
+
+ callback.Run(status, registration->id());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.h b/chromium/content/browser/service_worker/service_worker_context_core.h
new file mode 100644
index 00000000000..b7b26537bec
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_context_core.h
@@ -0,0 +1,104 @@
+// 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_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CORE_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CORE_H_
+
+#include <map>
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/id_map.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/browser/service_worker/service_worker_registration_status.h"
+#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/common/content_export.h"
+
+class GURL;
+
+namespace base {
+class FilePath;
+}
+
+namespace quota {
+class QuotaManagerProxy;
+}
+
+namespace content {
+
+class EmbeddedWorkerRegistry;
+class ServiceWorkerProviderHost;
+class ServiceWorkerRegistration;
+class ServiceWorkerStorage;
+
+// This class manages data associated with service workers.
+// The class is single threaded and should only be used on the IO thread.
+// In chromium, there is one instance per storagepartition. This class
+// is the root of the containment hierarchy for service worker data
+// associated with a particular partition.
+class CONTENT_EXPORT ServiceWorkerContextCore
+ : NON_EXPORTED_BASE(
+ public base::SupportsWeakPtr<ServiceWorkerContextCore>) {
+ public:
+ typedef base::Callback<void(ServiceWorkerRegistrationStatus status,
+ int64 registration_id)> RegistrationCallback;
+ typedef base::Callback<
+ void(ServiceWorkerRegistrationStatus status)> UnregistrationCallback;
+
+ // This is owned by the StoragePartition, which will supply it with
+ // the local path on disk. Given an empty |user_data_directory|,
+ // nothing will be stored on disk.
+ ServiceWorkerContextCore(const base::FilePath& user_data_directory,
+ quota::QuotaManagerProxy* quota_manager_proxy);
+ ~ServiceWorkerContextCore();
+
+ ServiceWorkerStorage* storage() { return storage_.get(); }
+
+ // The context class owns the set of ProviderHosts.
+ ServiceWorkerProviderHost* GetProviderHost(int process_id, int provider_id);
+ void AddProviderHost(scoped_ptr<ServiceWorkerProviderHost> provider_host);
+ void RemoveProviderHost(int process_id, int provider_id);
+ void RemoveAllProviderHostsForProcess(int process_id);
+
+ // Checks the cmdline flag.
+ bool IsEnabled();
+
+ // The callback will be called on the IO thread.
+ void RegisterServiceWorker(const GURL& pattern,
+ const GURL& script_url,
+ const RegistrationCallback& callback);
+
+ // The callback will be called on the IO thread.
+ void UnregisterServiceWorker(const GURL& pattern,
+ const UnregistrationCallback& callback);
+
+ EmbeddedWorkerRegistry* embedded_worker_registry() {
+ return embedded_worker_registry_.get();
+ }
+
+ private:
+ typedef IDMap<ServiceWorkerProviderHost, IDMapOwnPointer> ProviderMap;
+ typedef IDMap<ProviderMap, IDMapOwnPointer> ProcessToProviderMap;
+
+ ProviderMap* GetProviderMapForProcess(int process_id) {
+ return providers_.Lookup(process_id);
+ }
+
+ void RegistrationComplete(
+ const RegistrationCallback& callback,
+ ServiceWorkerRegistrationStatus status,
+ const scoped_refptr<ServiceWorkerRegistration>& registration);
+
+ ProcessToProviderMap providers_;
+ scoped_ptr<ServiceWorkerStorage> storage_;
+ scoped_refptr<EmbeddedWorkerRegistry> embedded_worker_registry_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextCore);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CORE_H_
diff --git a/chromium/content/browser/service_worker/service_worker_context_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
new file mode 100644
index 00000000000..e7c230f93a0
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
@@ -0,0 +1,168 @@
+// 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/service_worker/service_worker_context.h"
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+void SaveResponseCallback(bool* called,
+ int64* store_result,
+ ServiceWorkerRegistrationStatus status,
+ int64 result) {
+ *called = true;
+ *store_result = result;
+}
+
+ServiceWorkerContextCore::RegistrationCallback MakeRegisteredCallback(
+ bool* called,
+ int64* store_result) {
+ return base::Bind(&SaveResponseCallback, called, store_result);
+}
+
+void CallCompletedCallback(bool* called, ServiceWorkerRegistrationStatus) {
+ *called = true;
+}
+
+ServiceWorkerContextCore::UnregistrationCallback MakeUnregisteredCallback(
+ bool* called) {
+ return base::Bind(&CallCompletedCallback, called);
+}
+
+} // namespace
+
+class ServiceWorkerContextTest : public testing::Test {
+ public:
+ ServiceWorkerContextTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+ virtual void SetUp() OVERRIDE {
+ context_.reset(new ServiceWorkerContextCore(base::FilePath(), NULL));
+ }
+
+ virtual void TearDown() OVERRIDE { context_.reset(); }
+
+ protected:
+ TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_ptr<ServiceWorkerContextCore> context_;
+};
+
+void RegistrationCallback(
+ scoped_refptr<ServiceWorkerRegistration>* registration,
+ const scoped_refptr<ServiceWorkerRegistration>& result) {
+ *registration = result;
+}
+
+// Make sure basic registration is working.
+TEST_F(ServiceWorkerContextTest, Register) {
+ int64 registration_id = -1L;
+ bool called = false;
+ context_->RegisterServiceWorker(
+ GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/service_worker.js"),
+ MakeRegisteredCallback(&called, &registration_id));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_NE(-1L, registration_id);
+}
+
+// Make sure registrations are cleaned up when they are unregistered.
+TEST_F(ServiceWorkerContextTest, Unregister) {
+ GURL pattern("http://www.example.com/*");
+
+ bool called = false;
+ int64 registration_id = -1L;
+ context_->RegisterServiceWorker(
+ pattern,
+ GURL("http://www.example.com/service_worker.js"),
+ MakeRegisteredCallback(&called, &registration_id));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ called = false;
+ context_->UnregisterServiceWorker(pattern, MakeUnregisteredCallback(&called));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+}
+
+// Make sure that when a new registration replaces an existing
+// registration, that the old one is cleaned up.
+TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
+ GURL pattern("http://www.example.com/*");
+
+ bool called = false;
+ int64 old_registration_id = -1L;
+ context_->RegisterServiceWorker(
+ pattern,
+ GURL("http://www.example.com/service_worker.js"),
+ MakeRegisteredCallback(&called, &old_registration_id));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ called = false;
+ int64 new_registration_id = -1L;
+ context_->RegisterServiceWorker(
+ pattern,
+ GURL("http://www.example.com/service_worker_new.js"),
+ MakeRegisteredCallback(&called, &new_registration_id));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_NE(old_registration_id, new_registration_id);
+}
+
+// Make sure that when registering a duplicate pattern+script_url
+// combination, that the same registration is used.
+TEST_F(ServiceWorkerContextTest, RegisterDuplicateScript) {
+ GURL pattern("http://www.example.com/*");
+ GURL script_url("http://www.example.com/service_worker.js");
+
+ bool called = false;
+ int64 old_registration_id = -1L;
+ context_->RegisterServiceWorker(
+ pattern,
+ script_url,
+ MakeRegisteredCallback(&called, &old_registration_id));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ called = false;
+ int64 new_registration_id = -1L;
+ context_->RegisterServiceWorker(
+ pattern,
+ script_url,
+ MakeRegisteredCallback(&called, &new_registration_id));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_EQ(old_registration_id, new_registration_id);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
new file mode 100644
index 00000000000..49a6842968b
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -0,0 +1,52 @@
+// 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/service_worker/service_worker_context_wrapper.h"
+
+#include "base/files/file_path.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/public/browser/browser_thread.h"
+#include "webkit/browser/quota/quota_manager.h"
+
+namespace content {
+
+ServiceWorkerContextWrapper::ServiceWorkerContextWrapper() {
+}
+
+ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() {
+}
+
+void ServiceWorkerContextWrapper::Init(
+ const base::FilePath& user_data_directory,
+ quota::QuotaManagerProxy* quota_manager_proxy) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&ServiceWorkerContextWrapper::Init, this,
+ user_data_directory,
+ make_scoped_refptr(quota_manager_proxy)));
+ return;
+ }
+ DCHECK(!context_core_);
+ context_core_.reset(
+ new ServiceWorkerContextCore(
+ user_data_directory, quota_manager_proxy));
+}
+
+void ServiceWorkerContextWrapper::Shutdown() {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&ServiceWorkerContextWrapper::Shutdown, this));
+ return;
+ }
+ context_core_.reset();
+}
+
+ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ return context_core_.get();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_wrapper.h b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
new file mode 100644
index 00000000000..1b9b6523907
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
@@ -0,0 +1,54 @@
+// 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_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_WRAPPER_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_WRAPPER_H_
+
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/service_worker/service_worker_context.h"
+#include "content/common/content_export.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace quota {
+class QuotaManagerProxy;
+}
+
+namespace content {
+
+class ServiceWorkerContextCore;
+
+// A refcounted wrapper class for our core object. Higher level content lib
+// classes keep references to this class on mutliple threads. The inner core
+// instance is strictly single threaded and is not refcounted, the core object
+// is what is used internally in the service worker lib.
+class CONTENT_EXPORT ServiceWorkerContextWrapper
+ : NON_EXPORTED_BASE(public ServiceWorkerContext),
+ public base::RefCountedThreadSafe<ServiceWorkerContextWrapper> {
+ public:
+ ServiceWorkerContextWrapper();
+
+ // Init and Shutdown are for use on the UI thread when the profile,
+ // storagepartition is being setup and torn down.
+ void Init(const base::FilePath& user_data_directory,
+ quota::QuotaManagerProxy* quota_manager_proxy);
+ void Shutdown();
+
+ // The core context is only for use on the IO thread.
+ ServiceWorkerContextCore* context();
+
+ private:
+ friend class base::RefCountedThreadSafe<ServiceWorkerContextWrapper>;
+ virtual ~ServiceWorkerContextWrapper();
+
+ scoped_ptr<ServiceWorkerContextCore> context_core_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_WRAPPER_H_
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
index c531e915e88..76e7ff746ae 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -4,22 +4,63 @@
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
-#include "content/browser/service_worker/service_worker_context.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/common/service_worker_messages.h"
#include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
#include "url/gurl.h"
+using blink::WebServiceWorkerError;
+
+namespace {
+
+const char kDisabledErrorMessage[] =
+ "ServiceWorker is disabled";
+const char kDomainMismatchErrorMessage[] =
+ "Scope and scripts do not have the same origin";
+
+} // namespace
+
namespace content {
ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
- ServiceWorkerContext* context)
- : context_(context) {}
+ int render_process_id)
+ : render_process_id_(render_process_id) {
+}
-ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {}
+ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
+ if (context_) {
+ context_->RemoveAllProviderHostsForProcess(render_process_id_);
+ context_->embedded_worker_registry()->RemoveChildProcessSender(
+ render_process_id_);
+ }
+}
-bool ServiceWorkerDispatcherHost::OnMessageReceived(const IPC::Message& message,
- bool* message_was_ok) {
+void ServiceWorkerDispatcherHost::Init(
+ ServiceWorkerContextWrapper* context_wrapper) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&ServiceWorkerDispatcherHost::Init,
+ this, make_scoped_refptr(context_wrapper)));
+ return;
+ }
+ context_ = context_wrapper->context()->AsWeakPtr();
+ context_->embedded_worker_registry()->AddChildProcessSender(
+ render_process_id_, this);
+}
+void ServiceWorkerDispatcherHost::OnDestruct() const {
+ BrowserThread::DeleteOnIOThread::Destruct(this);
+}
+
+bool ServiceWorkerDispatcherHost::OnMessageReceived(
+ const IPC::Message& message,
+ bool* message_was_ok) {
if (IPC_MESSAGE_CLASS(message) != ServiceWorkerMsgStart)
return false;
@@ -30,21 +71,133 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived(const IPC::Message& message,
OnRegisterServiceWorker)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
OnUnregisterServiceWorker)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated,
+ OnProviderCreated)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
+ OnProviderDestroyed)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(int32 registry_id,
- const string16& scope,
- const GURL& script_url) {
- // TODO(alecflett): Enforce that script_url must have the same
- // origin as the registering document.
+void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
+ int32 thread_id,
+ int32 request_id,
+ const GURL& pattern,
+ const GURL& script_url) {
+ if (!context_ || !context_->IsEnabled()) {
+ Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ thread_id,
+ request_id,
+ WebServiceWorkerError::DisabledError,
+ ASCIIToUTF16(kDisabledErrorMessage)));
+ return;
+ }
+
+ // TODO(alecflett): This check is insufficient for release. Add a
+ // ServiceWorker-specific policy query in
+ // ChildProcessSecurityImpl. See http://crbug.com/311631.
+ if (pattern.GetOrigin() != script_url.GetOrigin()) {
+ Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ thread_id,
+ request_id,
+ WebServiceWorkerError::SecurityError,
+ ASCIIToUTF16(kDomainMismatchErrorMessage)));
+ return;
+ }
+
+ context_->RegisterServiceWorker(
+ pattern,
+ script_url,
+ base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
+ this,
+ thread_id,
+ request_id));
}
void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
- int32 registry_id,
- const string16& scope) {}
+ int32 thread_id,
+ int32 request_id,
+ const GURL& pattern) {
+ // TODO(alecflett): This check is insufficient for release. Add a
+ // ServiceWorker-specific policy query in
+ // ChildProcessSecurityImpl. See http://crbug.com/311631.
+ if (!context_ || !context_->IsEnabled()) {
+ Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ thread_id,
+ request_id,
+ blink::WebServiceWorkerError::DisabledError,
+ ASCIIToUTF16(kDisabledErrorMessage)));
+ return;
+ }
+
+ context_->UnregisterServiceWorker(
+ pattern,
+ base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
+ this,
+ thread_id,
+ request_id));
+}
+
+void ServiceWorkerDispatcherHost::OnProviderCreated(int provider_id) {
+ if (!context_)
+ return;
+ if (context_->GetProviderHost(render_process_id_, provider_id)) {
+ BadMessageReceived();
+ return;
+ }
+ scoped_ptr<ServiceWorkerProviderHost> provider_host(
+ new ServiceWorkerProviderHost(render_process_id_, provider_id));
+ context_->AddProviderHost(provider_host.Pass());
+}
+
+void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
+ if (!context_)
+ return;
+ if (!context_->GetProviderHost(render_process_id_, provider_id)) {
+ BadMessageReceived();
+ return;
+ }
+ context_->RemoveProviderHost(render_process_id_, provider_id);
+}
+
+void ServiceWorkerDispatcherHost::RegistrationComplete(
+ int32 thread_id,
+ int32 request_id,
+ ServiceWorkerRegistrationStatus status,
+ int64 registration_id) {
+ if (status != REGISTRATION_OK) {
+ SendRegistrationError(thread_id, request_id, status);
+ return;
+ }
+
+ Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
+ thread_id, request_id, registration_id));
+}
+
+void ServiceWorkerDispatcherHost::UnregistrationComplete(
+ int32 thread_id,
+ int32 request_id,
+ ServiceWorkerRegistrationStatus status) {
+ if (status != REGISTRATION_OK) {
+ SendRegistrationError(thread_id, request_id, status);
+ return;
+ }
+
+ Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id, request_id));
+}
+
+void ServiceWorkerDispatcherHost::SendRegistrationError(
+ int32 thread_id,
+ int32 request_id,
+ ServiceWorkerRegistrationStatus status) {
+ base::string16 error_message;
+ blink::WebServiceWorkerError::ErrorType error_type;
+ GetServiceWorkerRegistrationStatusResponse(
+ status, &error_type, &error_message);
+ Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ thread_id, request_id, error_type, error_message));
+}
} // namespace content
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 36927819f69..be008018ec5 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -5,19 +5,26 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_HOST_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_HOST_H_
+#include "base/memory/weak_ptr.h"
+#include "content/browser/service_worker/service_worker_registration_status.h"
#include "content/public/browser/browser_message_filter.h"
class GURL;
namespace content {
-class ServiceWorkerContext;
+class ServiceWorkerContextCore;
+class ServiceWorkerContextWrapper;
+class ServiceWorkerProviderHost;
-class ServiceWorkerDispatcherHost : public BrowserMessageFilter {
+class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
public:
- explicit ServiceWorkerDispatcherHost(ServiceWorkerContext* context);
+ explicit ServiceWorkerDispatcherHost(int render_process_id);
+
+ void Init(ServiceWorkerContextWrapper* context_wrapper);
// BrowserIOMessageFilter implementation
+ virtual void OnDestruct() const OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) OVERRIDE;
@@ -25,14 +32,36 @@ class ServiceWorkerDispatcherHost : public BrowserMessageFilter {
virtual ~ServiceWorkerDispatcherHost();
private:
+ friend class BrowserThread;
+ friend class base::DeleteHelper<ServiceWorkerDispatcherHost>;
+ friend class TestingServiceWorkerDispatcherHost;
+
// IPC Message handlers
+ void OnRegisterServiceWorker(int32 thread_id,
+ int32 request_id,
+ const GURL& pattern,
+ const GURL& script_url);
+ void OnUnregisterServiceWorker(int32 thread_id,
+ int32 request_id,
+ const GURL& pattern);
+ void OnProviderCreated(int provider_id);
+ void OnProviderDestroyed(int provider_id);
+
+ // Callbacks from ServiceWorkerContextCore
+ void RegistrationComplete(int32 thread_id,
+ int32 request_id,
+ ServiceWorkerRegistrationStatus status,
+ int64 registration_id);
- void OnRegisterServiceWorker(int32 registry_id,
- const string16& scope,
- const GURL& script_url);
- void OnUnregisterServiceWorker(int32 registry_id, const string16& scope);
+ void UnregistrationComplete(int32 thread_id,
+ int32 request_id,
+ ServiceWorkerRegistrationStatus status);
- scoped_refptr<ServiceWorkerContext> context_;
+ void SendRegistrationError(int32 thread_id,
+ int32 request_id,
+ ServiceWorkerRegistrationStatus status);
+ int render_process_id_;
+ base::WeakPtr<ServiceWorkerContextCore> context_;
};
} // namespace content
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
new file mode 100644
index 00000000000..da9e83c8ed8
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -0,0 +1,190 @@
+// 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/service_worker/service_worker_dispatcher_host.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/run_loop.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/common/service_worker_messages.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class ServiceWorkerDispatcherHostTest : public testing::Test {
+ protected:
+ ServiceWorkerDispatcherHostTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+ virtual void SetUp() {
+ context_wrapper_ = new ServiceWorkerContextWrapper;
+ context_wrapper_->Init(base::FilePath(), NULL);
+ }
+
+ virtual void TearDown() {
+ if (context_wrapper_) {
+ context_wrapper_->Shutdown();
+ context_wrapper_ = NULL;
+ }
+ }
+
+ ServiceWorkerContextCore* context() { return context_wrapper_->context(); }
+
+ TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
+};
+
+static const int kRenderProcessId = 1;
+
+class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
+ public:
+ TestingServiceWorkerDispatcherHost(
+ int process_id,
+ ServiceWorkerContextWrapper* context_wrapper)
+ : ServiceWorkerDispatcherHost(process_id),
+ bad_messages_received_count_(0) {
+ Init(context_wrapper);
+ }
+
+ virtual bool Send(IPC::Message* message) OVERRIDE {
+ sent_messages_.push_back(message);
+ return true;
+ }
+
+ virtual void BadMessageReceived() OVERRIDE {
+ ++bad_messages_received_count_;
+ }
+
+ ScopedVector<IPC::Message> sent_messages_;
+ int bad_messages_received_count_;
+
+ protected:
+ virtual ~TestingServiceWorkerDispatcherHost() {}
+};
+
+TEST_F(ServiceWorkerDispatcherHostTest, DisabledCausesError) {
+ DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableServiceWorker));
+
+ scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host =
+ new TestingServiceWorkerDispatcherHost(kRenderProcessId,
+ context_wrapper_.get());
+
+ bool handled;
+ dispatcher_host->OnMessageReceived(
+ ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, GURL(), GURL()),
+ &handled);
+ EXPECT_TRUE(handled);
+
+ // TODO(alecflett): Pump the message loop when this becomes async.
+ ASSERT_EQ(1UL, dispatcher_host->sent_messages_.size());
+ EXPECT_EQ(
+ static_cast<uint32>(ServiceWorkerMsg_ServiceWorkerRegistrationError::ID),
+ dispatcher_host->sent_messages_[0]->type());
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, Enabled) {
+ DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableServiceWorker));
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableServiceWorker);
+
+ scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host =
+ new TestingServiceWorkerDispatcherHost(kRenderProcessId,
+ context_wrapper_.get());
+
+ bool handled;
+ dispatcher_host->OnMessageReceived(
+ ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, GURL(), GURL()),
+ &handled);
+ EXPECT_TRUE(handled);
+ base::RunLoop().RunUntilIdle();
+
+ // TODO(alecflett): Pump the message loop when this becomes async.
+ ASSERT_EQ(1UL, dispatcher_host->sent_messages_.size());
+ EXPECT_EQ(static_cast<uint32>(ServiceWorkerMsg_ServiceWorkerRegistered::ID),
+ dispatcher_host->sent_messages_[0]->type());
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, EarlyContextDeletion) {
+ DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableServiceWorker));
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableServiceWorker);
+
+ scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host =
+ new TestingServiceWorkerDispatcherHost(kRenderProcessId,
+ context_wrapper_.get());
+
+ context_wrapper_->Shutdown();
+ context_wrapper_ = NULL;
+
+ bool handled;
+ dispatcher_host->OnMessageReceived(
+ ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, GURL(), GURL()),
+ &handled);
+ EXPECT_TRUE(handled);
+
+ // TODO(alecflett): Pump the message loop when this becomes async.
+ ASSERT_EQ(1UL, dispatcher_host->sent_messages_.size());
+ EXPECT_EQ(
+ static_cast<uint32>(ServiceWorkerMsg_ServiceWorkerRegistrationError::ID),
+ dispatcher_host->sent_messages_[0]->type());
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
+ scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host =
+ new TestingServiceWorkerDispatcherHost(kRenderProcessId,
+ context_wrapper_.get());
+
+ const int kProviderId = 1001; // Test with a value != kRenderProcessId.
+
+ bool handled = false;
+ dispatcher_host->OnMessageReceived(
+ ServiceWorkerHostMsg_ProviderCreated(kProviderId),
+ &handled);
+ EXPECT_TRUE(handled);
+ EXPECT_TRUE(context()->GetProviderHost(kRenderProcessId, kProviderId));
+
+ // Two with the same ID should be seen as a bad message.
+ handled = false;
+ dispatcher_host->OnMessageReceived(
+ ServiceWorkerHostMsg_ProviderCreated(kProviderId),
+ &handled);
+ EXPECT_TRUE(handled);
+ EXPECT_EQ(1, dispatcher_host->bad_messages_received_count_);
+
+ handled = false;
+ dispatcher_host->OnMessageReceived(
+ ServiceWorkerHostMsg_ProviderDestroyed(kProviderId),
+ &handled);
+ EXPECT_TRUE(handled);
+ EXPECT_FALSE(context()->GetProviderHost(kRenderProcessId, kProviderId));
+
+ // Destroying an ID that does not exist warrants a bad message.
+ handled = false;
+ dispatcher_host->OnMessageReceived(
+ ServiceWorkerHostMsg_ProviderDestroyed(kProviderId),
+ &handled);
+ EXPECT_TRUE(handled);
+ EXPECT_EQ(2, dispatcher_host->bad_messages_received_count_);
+
+ // Deletion of the dispatcher_host should cause providers for that
+ // process to get deleted as well.
+ dispatcher_host->OnMessageReceived(
+ ServiceWorkerHostMsg_ProviderCreated(kProviderId),
+ &handled);
+ EXPECT_TRUE(handled);
+ EXPECT_TRUE(context()->GetProviderHost(kRenderProcessId, kProviderId));
+ EXPECT_TRUE(dispatcher_host->HasOneRef());
+ dispatcher_host = NULL;
+ EXPECT_FALSE(context()->GetProviderHost(kRenderProcessId, kProviderId));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host.cc b/chromium/content/browser/service_worker/service_worker_provider_host.cc
new file mode 100644
index 00000000000..871343bac69
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.cc
@@ -0,0 +1,19 @@
+// 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/service_worker/service_worker_provider_host.h"
+
+#include "content/browser/service_worker/service_worker_version.h"
+
+namespace content {
+
+ServiceWorkerProviderHost::ServiceWorkerProviderHost(
+ int process_id, int provider_id)
+ : process_id_(process_id), provider_id_(provider_id) {
+}
+
+ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host.h b/chromium/content/browser/service_worker/service_worker_provider_host.h
new file mode 100644
index 00000000000..09990b61126
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.h
@@ -0,0 +1,42 @@
+// 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_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_HOST_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_HOST_H_
+
+#include "base/memory/ref_counted.h"
+
+namespace content {
+
+class ServiceWorkerVersion;
+
+// This class is the browser-process representation of a serice worker
+// provider. There is a provider per document and the lifetime of this
+// object is tied to the lifetime of its document in the renderer process.
+// This class holds service worker state this is scoped to an individual
+// document.
+class ServiceWorkerProviderHost {
+ public:
+ ServiceWorkerProviderHost(int process_id,
+ int provider_id);
+ ~ServiceWorkerProviderHost();
+
+ int process_id() const { return process_id_; }
+ int provider_id() const { return provider_id_; }
+
+ // The service worker version that corresponds with navigator.serviceWorker
+ // for our document.
+ ServiceWorkerVersion* associated_version() const {
+ return associated_version_.get();
+ }
+
+ private:
+ const int process_id_;
+ const int provider_id_;
+ scoped_refptr<ServiceWorkerVersion> associated_version_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_HOST_H_
diff --git a/chromium/content/browser/service_worker/service_worker_register_job.cc b/chromium/content/browser/service_worker/service_worker_register_job.cc
new file mode 100644
index 00000000000..90333595891
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_register_job.cc
@@ -0,0 +1,117 @@
+// 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/service_worker/service_worker_register_job.h"
+
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/public/browser/browser_thread.h"
+#include "url/gurl.h"
+
+namespace content {
+
+ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
+ const base::WeakPtr<ServiceWorkerStorage>& storage,
+ const RegistrationCompleteCallback& callback)
+ : storage_(storage), callback_(callback), weak_factory_(this) {}
+
+ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() {}
+
+void ServiceWorkerRegisterJob::StartRegister(const GURL& pattern,
+ const GURL& script_url) {
+ // Set up a chain of callbacks, in reverse order. Each of these
+ // callbacks may be called asynchronously by the previous callback.
+ ServiceWorkerStorage::RegistrationCallback finish_registration(base::Bind(
+ &ServiceWorkerRegisterJob::RegisterComplete, weak_factory_.GetWeakPtr()));
+
+ ServiceWorkerStorage::UnregistrationCallback register_new(
+ base::Bind(&ServiceWorkerRegisterJob::RegisterPatternAndContinue,
+ weak_factory_.GetWeakPtr(),
+ pattern,
+ script_url,
+ finish_registration));
+
+ ServiceWorkerStorage::FindRegistrationCallback unregister_old(
+ base::Bind(&ServiceWorkerRegisterJob::UnregisterPatternAndContinue,
+ weak_factory_.GetWeakPtr(),
+ pattern,
+ script_url,
+ register_new));
+
+ storage_->FindRegistrationForPattern(pattern, unregister_old);
+}
+
+void ServiceWorkerRegisterJob::StartUnregister(const GURL& pattern) {
+ // Set up a chain of callbacks, in reverse order. Each of these
+ // callbacks may be called asynchronously by the previous callback.
+ ServiceWorkerStorage::UnregistrationCallback finish_unregistration(
+ base::Bind(&ServiceWorkerRegisterJob::UnregisterComplete,
+ weak_factory_.GetWeakPtr()));
+
+ ServiceWorkerStorage::FindRegistrationCallback unregister(
+ base::Bind(&ServiceWorkerRegisterJob::UnregisterPatternAndContinue,
+ weak_factory_.GetWeakPtr(),
+ pattern,
+ GURL(),
+ finish_unregistration));
+
+ storage_->FindRegistrationForPattern(pattern, unregister);
+}
+
+void ServiceWorkerRegisterJob::RegisterPatternAndContinue(
+ const GURL& pattern,
+ const GURL& script_url,
+ const ServiceWorkerStorage::RegistrationCallback& callback,
+ ServiceWorkerRegistrationStatus previous_status) {
+ if (previous_status != REGISTRATION_OK) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback,
+ previous_status,
+ scoped_refptr<ServiceWorkerRegistration>()));
+ return;
+ }
+
+ // TODO: Eventually RegisterInternal will be replaced by an asynchronous
+ // operation. Pass its resulting status through 'callback'.
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ storage_->RegisterInternal(pattern, script_url);
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback, REGISTRATION_OK, registration));
+}
+
+void ServiceWorkerRegisterJob::UnregisterPatternAndContinue(
+ const GURL& pattern,
+ const GURL& new_script_url,
+ const ServiceWorkerStorage::UnregistrationCallback& callback,
+ bool found,
+ ServiceWorkerRegistrationStatus previous_status,
+ const scoped_refptr<ServiceWorkerRegistration>& previous_registration) {
+
+ // The previous registration may not exist, which is ok.
+ if (previous_status == REGISTRATION_OK && found &&
+ (new_script_url.is_empty() ||
+ previous_registration->script_url() != new_script_url)) {
+ // TODO: Eventually UnregisterInternal will be replaced by an
+ // asynchronous operation. Pass its resulting status though
+ // 'callback'.
+ storage_->UnregisterInternal(pattern);
+ }
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE, base::Bind(callback, previous_status));
+}
+
+void ServiceWorkerRegisterJob::UnregisterComplete(
+ ServiceWorkerRegistrationStatus status) {
+ callback_.Run(this, status, NULL);
+}
+
+void ServiceWorkerRegisterJob::RegisterComplete(
+ ServiceWorkerRegistrationStatus status,
+ const scoped_refptr<ServiceWorkerRegistration>& registration) {
+ callback_.Run(this, status, registration);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_register_job.h b/chromium/content/browser/service_worker/service_worker_register_job.h
new file mode 100644
index 00000000000..9e12eb51854
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_register_job.h
@@ -0,0 +1,80 @@
+// 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_SERVICE_WORKER_SERVICE_WORKER_REGISTER_JOB_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTER_JOB_H_
+
+#include "base/memory/weak_ptr.h"
+#include "content/browser/service_worker/service_worker_registration_status.h"
+#include "content/browser/service_worker/service_worker_storage.h"
+
+namespace content {
+
+// A ServiceWorkerRegisterJob lives only for the lifetime of a single
+// registration or unregistration.
+class ServiceWorkerRegisterJob {
+ public:
+ typedef base::Callback<void(
+ ServiceWorkerRegisterJob* job,
+ ServiceWorkerRegistrationStatus status,
+ ServiceWorkerRegistration* registration)> RegistrationCompleteCallback;
+
+ // All type of jobs (Register and Unregister) complete through a
+ // single call to this callback on the IO thread.
+ ServiceWorkerRegisterJob(const base::WeakPtr<ServiceWorkerStorage>& storage,
+ const RegistrationCompleteCallback& callback);
+ ~ServiceWorkerRegisterJob();
+
+ // The Registration flow includes most or all of the following,
+ // depending on what is already registered:
+ // - creating a ServiceWorkerRegistration instance if there isn't
+ // already something registered
+ // - creating a ServiceWorkerVersion for the new registration instance.
+ // - starting a worker for the ServiceWorkerVersion
+ // - telling the Version to evaluate the script
+ // - firing the 'install' event at the ServiceWorkerVersion
+ // - firing the 'activate' event at the ServiceWorkerVersion
+ // - Waiting for older ServiceWorkerVersions to deactivate
+ // - designating the new version to be the 'active' version
+ // This method should be called once and only once per job.
+ void StartRegister(const GURL& pattern, const GURL& script_url);
+
+ // The Unregistration process is primarily cleanup, removing
+ // everything that was created during the Registration process,
+ // including the ServiceWorkerRegistration itself.
+ // This method should be called once and only once per job.
+ void StartUnregister(const GURL& pattern);
+
+ private:
+ // These are all steps in the registration and unregistration pipeline.
+ void RegisterPatternAndContinue(
+ const GURL& pattern,
+ const GURL& script_url,
+ const ServiceWorkerStorage::RegistrationCallback& callback,
+ ServiceWorkerRegistrationStatus previous_status);
+
+ void UnregisterPatternAndContinue(
+ const GURL& pattern,
+ const GURL& script_url,
+ const ServiceWorkerStorage::UnregistrationCallback& callback,
+ bool found,
+ ServiceWorkerRegistrationStatus previous_status,
+ const scoped_refptr<ServiceWorkerRegistration>& previous_registration);
+
+ // These methods are the last internal callback in the callback
+ // chain, and ultimately call callback_.
+ void UnregisterComplete(ServiceWorkerRegistrationStatus status);
+ void RegisterComplete(
+ ServiceWorkerRegistrationStatus status,
+ const scoped_refptr<ServiceWorkerRegistration>& registration);
+
+ const base::WeakPtr<ServiceWorkerStorage> storage_;
+ const RegistrationCompleteCallback callback_;
+ base::WeakPtrFactory<ServiceWorkerRegisterJob> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegisterJob);
+};
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTER_JOB_H_
diff --git a/chromium/content/browser/service_worker/service_worker_registration.cc b/chromium/content/browser/service_worker/service_worker_registration.cc
new file mode 100644
index 00000000000..060de04608f
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_registration.cc
@@ -0,0 +1,43 @@
+// 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/service_worker/service_worker_registration.h"
+
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+ServiceWorkerRegistration::ServiceWorkerRegistration(const GURL& pattern,
+ const GURL& script_url,
+ int64 registration_id)
+ : pattern_(pattern),
+ script_url_(script_url),
+ registration_id_(registration_id),
+ is_shutdown_(false) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+}
+
+ServiceWorkerRegistration::~ServiceWorkerRegistration() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(is_shutdown_);
+}
+
+void ServiceWorkerRegistration::Shutdown() {
+ DCHECK(!is_shutdown_);
+ if (active_version_)
+ active_version_->Shutdown();
+ active_version_ = NULL;
+ if (pending_version_)
+ pending_version_->Shutdown();
+ pending_version_ = NULL;
+ is_shutdown_ = true;
+}
+
+void ServiceWorkerRegistration::ActivatePendingVersion() {
+ active_version_->Shutdown();
+ active_version_ = pending_version_;
+ pending_version_ = NULL;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_registration.h b/chromium/content/browser/service_worker/service_worker_registration.h
new file mode 100644
index 00000000000..680fcfacbcc
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_registration.h
@@ -0,0 +1,88 @@
+// 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_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_H_
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class ServiceWorkerVersion;
+
+// This class manages all persistence of service workers:
+// - Registrations
+// - Mapping of caches to registrations / versions
+//
+// This is the place where we manage simultaneous
+// requests for the same registrations and caches, making sure that
+// two pages that are registering the same pattern at the same time
+// have their registrations coalesced rather than overwriting each
+// other.
+//
+// This class also manages the state of the upgrade process, which
+// includes managing which ServiceWorkerVersion is "active" vs "in
+// waiting" (or "pending")
+class CONTENT_EXPORT ServiceWorkerRegistration
+ : NON_EXPORTED_BASE(public base::RefCounted<ServiceWorkerRegistration>) {
+ public:
+ ServiceWorkerRegistration(const GURL& pattern,
+ const GURL& script_url,
+ int64 registration_id);
+
+ void Shutdown();
+ bool is_shutdown() const { return is_shutdown_; }
+
+ int64 id() const { return registration_id_; }
+ const GURL& script_url() const { return script_url_; }
+ const GURL& pattern() const { return pattern_; }
+
+ ServiceWorkerVersion* active_version() const {
+ DCHECK(!is_shutdown_);
+ return active_version_.get();
+ }
+
+ ServiceWorkerVersion* pending_version() const {
+ DCHECK(!is_shutdown_);
+ return pending_version_.get();
+ }
+
+ void set_active_version(ServiceWorkerVersion* version) {
+ DCHECK(!is_shutdown_);
+ active_version_ = version;
+ }
+
+ void set_pending_version(ServiceWorkerVersion* version) {
+ DCHECK(!is_shutdown_);
+ pending_version_ = version;
+ }
+
+ // The final synchronous switchover after all events have been
+ // fired, and the old "active version" is being shut down.
+ void ActivatePendingVersion();
+
+ private:
+ virtual ~ServiceWorkerRegistration();
+ friend class base::RefCounted<ServiceWorkerRegistration>;
+
+ const GURL pattern_;
+ const GURL script_url_;
+ const int64 registration_id_;
+
+ scoped_refptr<ServiceWorkerVersion> active_version_;
+ scoped_refptr<ServiceWorkerVersion> pending_version_;
+
+ bool is_shutdown_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistration);
+};
+} // namespace content
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_H_
diff --git a/chromium/content/browser/service_worker/service_worker_registration_status.cc b/chromium/content/browser/service_worker/service_worker_registration_status.cc
new file mode 100644
index 00000000000..4556b5f537f
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_registration_status.cc
@@ -0,0 +1,41 @@
+// 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/service_worker/service_worker_registration_status.h"
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+
+namespace {
+const char kInstallFailedErrorMessage[] = "ServiceWorker failed to install";
+const char kActivateFailedErrorMessage[] = "ServiceWorker failed to activate";
+}
+
+namespace content {
+
+using blink::WebServiceWorkerError;
+
+void GetServiceWorkerRegistrationStatusResponse(
+ ServiceWorkerRegistrationStatus status,
+ blink::WebServiceWorkerError::ErrorType* error_type,
+ base::string16* message) {
+ switch (status) {
+ case REGISTRATION_OK:
+ NOTREACHED() << "Consumers should check registration status before "
+ "calling this function.";
+ return;
+
+ case REGISTRATION_INSTALL_FAILED:
+ *error_type = WebServiceWorkerError::InstallError;
+ *message = ASCIIToUTF16(kInstallFailedErrorMessage);
+ return;
+
+ case REGISTRATION_ACTIVATE_FAILED:
+ *error_type = WebServiceWorkerError::ActivateError;
+ *message = ASCIIToUTF16(kActivateFailedErrorMessage);
+ return;
+ }
+ NOTREACHED();
+}
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_registration_status.h b/chromium/content/browser/service_worker/service_worker_registration_status.h
new file mode 100644
index 00000000000..1676b495cde
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_registration_status.h
@@ -0,0 +1,29 @@
+// 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_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_STATUS_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_STATUS_H_
+
+#include "base/strings/string16.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
+
+namespace content {
+
+// This enum describes the reason a registration or unregistration succeeds or
+// fails.
+enum ServiceWorkerRegistrationStatus {
+ REGISTRATION_OK,
+ REGISTRATION_INSTALL_FAILED,
+ REGISTRATION_ACTIVATE_FAILED,
+};
+
+// This should only be called for errors, where status != REGISTRATION_OK.
+void GetServiceWorkerRegistrationStatusResponse(
+ ServiceWorkerRegistrationStatus status,
+ blink::WebServiceWorkerError::ErrorType* error_type,
+ base::string16* message);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_STATUS_H_
diff --git a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
new file mode 100644
index 00000000000..3fb6611a2f3
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -0,0 +1,85 @@
+// 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/service_worker/service_worker_registration.h"
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "content/browser/browser_thread_impl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class ServiceWorkerRegistrationTest : public testing::Test {
+ public:
+ ServiceWorkerRegistrationTest()
+ : io_thread_(BrowserThread::IO, &message_loop_) {}
+
+ virtual void SetUp() OVERRIDE {}
+
+ protected:
+ base::MessageLoopForIO message_loop_;
+ BrowserThreadImpl io_thread_;
+};
+
+TEST_F(ServiceWorkerRegistrationTest, Shutdown) {
+ const int64 registration_id = -1L;
+ const int64 version_id = -1L;
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ new ServiceWorkerRegistration(
+ GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/service_worker.js"),
+ registration_id);
+
+ scoped_refptr<ServiceWorkerVersion> active_version =
+ new ServiceWorkerVersion(registration, NULL, version_id);
+ registration->set_active_version(active_version);
+
+ registration->Shutdown();
+
+ DCHECK(registration->is_shutdown());
+ DCHECK(active_version->is_shutdown());
+ DCHECK(registration->HasOneRef());
+ DCHECK(active_version->HasOneRef());
+}
+
+// Make sure that activation does not leak
+TEST_F(ServiceWorkerRegistrationTest, ActivatePending) {
+ int64 registration_id = -1L;
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ new ServiceWorkerRegistration(
+ GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/service_worker.js"),
+ registration_id);
+
+ const int64 version_1_id = 1L;
+ const int64 version_2_id = 2L;
+ scoped_refptr<ServiceWorkerVersion> version_1 =
+ new ServiceWorkerVersion(registration, NULL, version_1_id);
+ registration->set_active_version(version_1);
+
+ scoped_refptr<ServiceWorkerVersion> version_2 =
+ new ServiceWorkerVersion(registration, NULL, version_2_id);
+ registration->set_pending_version(version_2);
+
+ registration->ActivatePendingVersion();
+ DCHECK_EQ(version_2, registration->active_version());
+ DCHECK(version_1->is_shutdown());
+ DCHECK(version_1->HasOneRef());
+ version_1 = NULL;
+
+ DCHECK(!version_2->is_shutdown());
+ DCHECK(!version_2->HasOneRef());
+
+ registration->Shutdown();
+
+ DCHECK(registration->is_shutdown());
+ DCHECK(version_2->is_shutdown());
+ DCHECK(registration->HasOneRef());
+ DCHECK(version_2->HasOneRef());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_storage.cc b/chromium/content/browser/service_worker/service_worker_storage.cc
new file mode 100644
index 00000000000..16a671e20b8
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_storage.cc
@@ -0,0 +1,194 @@
+// 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/service_worker/service_worker_storage.h"
+
+#include <string>
+
+#include "base/strings/string_util.h"
+#include "content/browser/service_worker/service_worker_register_job.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/public/browser/browser_thread.h"
+#include "webkit/browser/quota/quota_manager.h"
+
+namespace {
+// This is temporary until we figure out how registration ids will be
+// calculated.
+int64 NextRegistrationId() {
+ static int64 worker_id = 0;
+ return worker_id++;
+}
+} // namespace
+
+namespace content {
+
+const base::FilePath::CharType kServiceWorkerDirectory[] =
+ FILE_PATH_LITERAL("ServiceWorker");
+
+ServiceWorkerStorage::ServiceWorkerStorage(
+ const base::FilePath& path,
+ quota::QuotaManagerProxy* quota_manager_proxy)
+ : quota_manager_proxy_(quota_manager_proxy), weak_factory_(this) {
+ if (!path.empty())
+ path_ = path.Append(kServiceWorkerDirectory);
+}
+
+ServiceWorkerStorage::~ServiceWorkerStorage() {
+ for (PatternToRegistrationMap::const_iterator iter =
+ registration_by_pattern_.begin();
+ iter != registration_by_pattern_.end();
+ ++iter) {
+ iter->second->Shutdown();
+ }
+ registration_by_pattern_.clear();
+}
+
+void ServiceWorkerStorage::FindRegistrationForPattern(
+ const GURL& pattern,
+ const FindRegistrationCallback& callback) {
+ PatternToRegistrationMap::const_iterator match =
+ registration_by_pattern_.find(pattern);
+ if (match == registration_by_pattern_.end()) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback,
+ false /* found */,
+ REGISTRATION_OK,
+ scoped_refptr<ServiceWorkerRegistration>()));
+ return;
+ }
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback, true /* found */, REGISTRATION_OK, match->second));
+}
+
+void ServiceWorkerStorage::FindRegistrationForDocument(
+ const GURL& document_url,
+ const FindRegistrationCallback& callback) {
+ // TODO(alecflett): This needs to be synchronous in the fast path,
+ // but asynchronous in the slow path (when the patterns have to be
+ // loaded from disk). For now it is always pessimistically async.
+ for (PatternToRegistrationMap::const_iterator it =
+ registration_by_pattern_.begin();
+ it != registration_by_pattern_.end();
+ ++it) {
+ if (PatternMatches(it->first, document_url)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback,
+ true /* found */,
+ REGISTRATION_OK,
+ scoped_refptr<ServiceWorkerRegistration>(it->second)));
+ return;
+ }
+ }
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback,
+ false /* found */,
+ REGISTRATION_OK,
+ scoped_refptr<ServiceWorkerRegistration>()));
+}
+
+void ServiceWorkerStorage::Register(const GURL& pattern,
+ const GURL& script_url,
+ const RegistrationCallback& callback) {
+ scoped_ptr<ServiceWorkerRegisterJob> job(new ServiceWorkerRegisterJob(
+ weak_factory_.GetWeakPtr(),
+ base::Bind(&ServiceWorkerStorage::RegisterComplete,
+ weak_factory_.GetWeakPtr(),
+ callback)));
+ job->StartRegister(pattern, script_url);
+ registration_jobs_.push_back(job.release());
+}
+
+void ServiceWorkerStorage::Unregister(const GURL& pattern,
+ const UnregistrationCallback& callback) {
+ scoped_ptr<ServiceWorkerRegisterJob> job(new ServiceWorkerRegisterJob(
+ weak_factory_.GetWeakPtr(),
+ base::Bind(&ServiceWorkerStorage::UnregisterComplete,
+ weak_factory_.GetWeakPtr(),
+ callback)));
+ job->StartUnregister(pattern);
+ registration_jobs_.push_back(job.release());
+}
+
+scoped_refptr<ServiceWorkerRegistration> ServiceWorkerStorage::RegisterInternal(
+ const GURL& pattern,
+ const GURL& script_url) {
+
+ PatternToRegistrationMap::const_iterator current(
+ registration_by_pattern_.find(pattern));
+ DCHECK(current == registration_by_pattern_.end() ||
+ current->second->script_url() == script_url);
+
+ if (current == registration_by_pattern_.end()) {
+ scoped_refptr<ServiceWorkerRegistration> registration(
+ new ServiceWorkerRegistration(
+ pattern, script_url, NextRegistrationId()));
+ // TODO(alecflett): version upgrade path.
+ registration_by_pattern_[pattern] = registration;
+ return registration;
+ }
+
+ return current->second;
+}
+
+void ServiceWorkerStorage::UnregisterInternal(const GURL& pattern) {
+ PatternToRegistrationMap::iterator match =
+ registration_by_pattern_.find(pattern);
+ if (match != registration_by_pattern_.end()) {
+ match->second->Shutdown();
+ registration_by_pattern_.erase(match);
+ }
+}
+
+bool ServiceWorkerStorage::PatternMatches(const GURL& pattern,
+ const GURL& url) {
+ // This is a really basic, naive
+ // TODO(alecflett): Formalize what pattern matches mean.
+ // Temporarily borrowed directly from appcache::Namespace::IsMatch().
+ // We have to escape '?' characters since MatchPattern also treats those
+ // as wildcards which we don't want here, we only do '*'s.
+ std::string pattern_spec(pattern.spec());
+ if (pattern.has_query())
+ ReplaceSubstringsAfterOffset(&pattern_spec, 0, "?", "\\?");
+ return MatchPattern(url.spec(), pattern_spec);
+}
+
+void ServiceWorkerStorage::EraseJob(ServiceWorkerRegisterJob* job) {
+ ScopedVector<ServiceWorkerRegisterJob>::iterator job_position =
+ registration_jobs_.begin();
+ for (; job_position != registration_jobs_.end(); ++job_position) {
+ if (*job_position == job) {
+ registration_jobs_.erase(job_position);
+ return;
+ }
+ }
+ NOTREACHED() << "Deleting non-existent job. ";
+}
+
+void ServiceWorkerStorage::UnregisterComplete(
+ const UnregistrationCallback& callback,
+ ServiceWorkerRegisterJob* job,
+ ServiceWorkerRegistrationStatus status,
+ ServiceWorkerRegistration* previous_registration) {
+ callback.Run(status);
+ EraseJob(job);
+}
+
+void ServiceWorkerStorage::RegisterComplete(
+ const RegistrationCallback& callback,
+ ServiceWorkerRegisterJob* job,
+ ServiceWorkerRegistrationStatus status,
+ ServiceWorkerRegistration* registration) {
+ callback.Run(status, registration);
+ EraseJob(job);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_storage.h b/chromium/content/browser/service_worker/service_worker_storage.h
new file mode 100644
index 00000000000..b3f1dbfaf69
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_storage.h
@@ -0,0 +1,108 @@
+// 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_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_vector.h"
+#include "content/browser/service_worker/service_worker_registration_status.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace quota {
+class QuotaManagerProxy;
+}
+
+namespace content {
+
+class ServiceWorkerRegistration;
+class ServiceWorkerRegisterJob;
+
+// This class provides an interface to load registration data and
+// instantiate ServiceWorkerRegistration objects. Any asynchronous
+// operations are run through instances of ServiceWorkerRegisterJob.
+class CONTENT_EXPORT ServiceWorkerStorage {
+ public:
+ ServiceWorkerStorage(const base::FilePath& path,
+ quota::QuotaManagerProxy* quota_manager_proxy);
+ ~ServiceWorkerStorage();
+
+ typedef base::Callback<void(ServiceWorkerRegistrationStatus status,
+ const scoped_refptr<ServiceWorkerRegistration>&
+ registration)> RegistrationCallback;
+ typedef base::Callback<
+ void(ServiceWorkerRegistrationStatus status)> UnregistrationCallback;
+
+ // `found` is only valid if status == REGISTRATION_OK.
+ typedef base::Callback<void(bool found,
+ ServiceWorkerRegistrationStatus status,
+ const scoped_refptr<ServiceWorkerRegistration>&
+ registration)> FindRegistrationCallback;
+
+ void FindRegistrationForDocument(const GURL& document_url,
+ const FindRegistrationCallback& callback);
+ void FindRegistrationForPattern(const GURL& pattern,
+ const FindRegistrationCallback& callback);
+
+ void Register(const GURL& pattern,
+ const GURL& script_url,
+ const RegistrationCallback& callback);
+
+ void Unregister(const GURL& pattern, const UnregistrationCallback& callback);
+
+ private:
+ friend class ServiceWorkerRegisterJob;
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStorageTest, PatternMatches);
+
+ typedef std::map<GURL, scoped_refptr<ServiceWorkerRegistration> >
+ PatternToRegistrationMap;
+ typedef ScopedVector<ServiceWorkerRegisterJob> RegistrationJobList;
+
+ // TODO(alecflett): These are temporary internal methods providing
+ // synchronous in-memory registration. Eventually these will be
+ // replaced by asynchronous methods that persist registration to disk.
+ scoped_refptr<ServiceWorkerRegistration> RegisterInternal(
+ const GURL& pattern,
+ const GURL& script_url);
+ void UnregisterInternal(const GURL& pattern);
+ static bool PatternMatches(const GURL& pattern, const GURL& script_url);
+
+ // Jobs are removed whenever they are finished or canceled.
+ void EraseJob(ServiceWorkerRegisterJob* job);
+
+ // Called at ServiceWorkerRegisterJob completion.
+ void RegisterComplete(const RegistrationCallback& callback,
+ ServiceWorkerRegisterJob* job,
+ ServiceWorkerRegistrationStatus status,
+ ServiceWorkerRegistration* registration);
+
+ // Called at ServiceWorkerRegisterJob completion.
+ void UnregisterComplete(const UnregistrationCallback& callback,
+ ServiceWorkerRegisterJob* job,
+ ServiceWorkerRegistrationStatus status,
+ ServiceWorkerRegistration* registration);
+
+ // This is the in-memory registration. Eventually the registration will be
+ // persisted to disk.
+ // A list of currently running jobs. This is a temporary structure until we
+ // start managing overlapping registrations explicitly.
+ RegistrationJobList registration_jobs_;
+
+ // in-memory map, to eventually be replaced with persistence
+ PatternToRegistrationMap registration_by_pattern_;
+ scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_;
+ base::FilePath path_;
+ base::WeakPtrFactory<ServiceWorkerStorage> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerStorage);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_
diff --git a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
new file mode 100644
index 00000000000..bd6d629eb80
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -0,0 +1,384 @@
+// 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/service_worker/service_worker_storage.h"
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+void SaveRegistrationCallback(
+ ServiceWorkerRegistrationStatus expected_status,
+ bool* called,
+ scoped_refptr<ServiceWorkerRegistration>* registration,
+ ServiceWorkerRegistrationStatus status,
+ const scoped_refptr<ServiceWorkerRegistration>& result) {
+ EXPECT_EQ(expected_status, status);
+ *called = true;
+ *registration = result;
+}
+
+void SaveFoundRegistrationCallback(
+ bool expected_found,
+ ServiceWorkerRegistrationStatus expected_status,
+ bool* called,
+ scoped_refptr<ServiceWorkerRegistration>* registration,
+ bool found,
+ ServiceWorkerRegistrationStatus status,
+ const scoped_refptr<ServiceWorkerRegistration>& result) {
+ EXPECT_EQ(expected_found, found);
+ EXPECT_EQ(expected_status, status);
+ *called = true;
+ *registration = result;
+}
+
+// Creates a callback which both keeps track of if it's been called,
+// as well as the resulting registration. Whent the callback is fired,
+// it ensures that the resulting status matches the expectation.
+// 'called' is useful for making sure a sychronous callback is or
+// isn't called.
+ServiceWorkerStorage::RegistrationCallback SaveRegistration(
+ ServiceWorkerRegistrationStatus expected_status,
+ bool* called,
+ scoped_refptr<ServiceWorkerRegistration>* registration) {
+ *called = false;
+ return base::Bind(
+ &SaveRegistrationCallback, expected_status, called, registration);
+}
+
+ServiceWorkerStorage::FindRegistrationCallback SaveFoundRegistration(
+ bool expected_found,
+ ServiceWorkerRegistrationStatus expected_status,
+ bool* called,
+ scoped_refptr<ServiceWorkerRegistration>* registration) {
+ *called = false;
+ return base::Bind(&SaveFoundRegistrationCallback,
+ expected_found,
+ expected_status,
+ called,
+ registration);
+}
+
+void SaveUnregistrationCallback(ServiceWorkerRegistrationStatus expected_status,
+ bool* called,
+ ServiceWorkerRegistrationStatus status) {
+ EXPECT_EQ(expected_status, status);
+ *called = true;
+}
+
+ServiceWorkerStorage::UnregistrationCallback SaveUnregistration(
+ ServiceWorkerRegistrationStatus expected_status,
+ bool* called) {
+ *called = false;
+ return base::Bind(&SaveUnregistrationCallback, expected_status, called);
+}
+
+} // namespace
+
+class ServiceWorkerStorageTest : public testing::Test {
+ public:
+ ServiceWorkerStorageTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+ virtual void SetUp() OVERRIDE {
+ storage_.reset(new ServiceWorkerStorage(base::FilePath(), NULL));
+ }
+
+ virtual void TearDown() OVERRIDE { storage_.reset(); }
+
+ protected:
+ TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_ptr<ServiceWorkerStorage> storage_;
+};
+
+TEST_F(ServiceWorkerStorageTest, PatternMatches) {
+ ASSERT_TRUE(ServiceWorkerStorage::PatternMatches(
+ GURL("http://www.example.com/*"), GURL("http://www.example.com/")));
+ ASSERT_TRUE(ServiceWorkerStorage::PatternMatches(
+ GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/page.html")));
+
+ ASSERT_FALSE(ServiceWorkerStorage::PatternMatches(
+ GURL("http://www.example.com/*"), GURL("https://www.example.com/")));
+ ASSERT_FALSE(ServiceWorkerStorage::PatternMatches(
+ GURL("http://www.example.com/*"),
+ GURL("https://www.example.com/page.html")));
+
+ ASSERT_FALSE(ServiceWorkerStorage::PatternMatches(
+ GURL("http://www.example.com/*"), GURL("http://www.foo.com/")));
+ ASSERT_FALSE(ServiceWorkerStorage::PatternMatches(
+ GURL("http://www.example.com/*"), GURL("https://www.foo.com/page.html")));
+}
+
+TEST_F(ServiceWorkerStorageTest, SameDocumentSameRegistration) {
+ scoped_refptr<ServiceWorkerRegistration> original_registration;
+ bool called;
+ storage_->Register(
+ GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/service_worker.js"),
+ SaveRegistration(REGISTRATION_OK, &called, &original_registration));
+ EXPECT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+
+ scoped_refptr<ServiceWorkerRegistration> registration1;
+ storage_->FindRegistrationForDocument(
+ GURL("http://www.example.com/"),
+ SaveFoundRegistration(true, REGISTRATION_OK, &called, &registration1));
+ scoped_refptr<ServiceWorkerRegistration> registration2;
+ storage_->FindRegistrationForDocument(
+ GURL("http://www.example.com/"),
+ SaveFoundRegistration(true, REGISTRATION_OK, &called, &registration2));
+
+ ServiceWorkerRegistration* null_registration(NULL);
+ ASSERT_EQ(null_registration, registration1);
+ ASSERT_EQ(null_registration, registration2);
+ EXPECT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ ASSERT_NE(null_registration, registration1);
+ ASSERT_NE(null_registration, registration2);
+
+ ASSERT_EQ(registration1, registration2);
+}
+
+TEST_F(ServiceWorkerStorageTest, SameMatchSameRegistration) {
+ bool called;
+ scoped_refptr<ServiceWorkerRegistration> original_registration;
+ storage_->Register(
+ GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/service_worker.js"),
+ SaveRegistration(REGISTRATION_OK, &called, &original_registration));
+ EXPECT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ ASSERT_NE(static_cast<ServiceWorkerRegistration*>(NULL),
+ original_registration.get());
+
+ scoped_refptr<ServiceWorkerRegistration> registration1;
+ storage_->FindRegistrationForDocument(
+ GURL("http://www.example.com/one"),
+ SaveFoundRegistration(true, REGISTRATION_OK, &called, &registration1));
+
+ EXPECT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+
+ scoped_refptr<ServiceWorkerRegistration> registration2;
+ storage_->FindRegistrationForDocument(
+ GURL("http://www.example.com/two"),
+ SaveFoundRegistration(true, REGISTRATION_OK, &called, &registration2));
+ EXPECT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+
+ ASSERT_EQ(registration1, registration2);
+}
+
+TEST_F(ServiceWorkerStorageTest, DifferentMatchDifferentRegistration) {
+ bool called1;
+ scoped_refptr<ServiceWorkerRegistration> original_registration1;
+ storage_->Register(
+ GURL("http://www.example.com/one/*"),
+ GURL("http://www.example.com/service_worker.js"),
+ SaveRegistration(REGISTRATION_OK, &called1, &original_registration1));
+
+ bool called2;
+ scoped_refptr<ServiceWorkerRegistration> original_registration2;
+ storage_->Register(
+ GURL("http://www.example.com/two/*"),
+ GURL("http://www.example.com/service_worker.js"),
+ SaveRegistration(REGISTRATION_OK, &called2, &original_registration2));
+
+ EXPECT_FALSE(called1);
+ EXPECT_FALSE(called2);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called2);
+ EXPECT_TRUE(called1);
+
+ scoped_refptr<ServiceWorkerRegistration> registration1;
+ storage_->FindRegistrationForDocument(
+ GURL("http://www.example.com/one/"),
+ SaveFoundRegistration(true, REGISTRATION_OK, &called1, &registration1));
+ scoped_refptr<ServiceWorkerRegistration> registration2;
+ storage_->FindRegistrationForDocument(
+ GURL("http://www.example.com/two/"),
+ SaveFoundRegistration(true, REGISTRATION_OK, &called2, &registration2));
+
+ EXPECT_FALSE(called1);
+ EXPECT_FALSE(called2);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called2);
+ EXPECT_TRUE(called1);
+
+ ASSERT_NE(registration1, registration2);
+}
+
+// Make sure basic registration is working.
+TEST_F(ServiceWorkerStorageTest, Register) {
+ bool called = false;
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ storage_->Register(GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/service_worker.js"),
+ SaveRegistration(REGISTRATION_OK, &called, &registration));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_NE(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
+}
+
+// Make sure registrations are cleaned up when they are unregistered.
+TEST_F(ServiceWorkerStorageTest, Unregister) {
+ GURL pattern("http://www.example.com/*");
+
+ bool called;
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ storage_->Register(pattern,
+ GURL("http://www.example.com/service_worker.js"),
+ SaveRegistration(REGISTRATION_OK, &called, &registration));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ storage_->Unregister(pattern, SaveUnregistration(REGISTRATION_OK, &called));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_TRUE(registration->HasOneRef());
+
+ storage_->FindRegistrationForPattern(
+ pattern,
+ SaveFoundRegistration(false, REGISTRATION_OK, &called, &registration));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
+}
+
+// Make sure that when a new registration replaces an existing
+// registration, that the old one is cleaned up.
+TEST_F(ServiceWorkerStorageTest, RegisterNewScript) {
+ GURL pattern("http://www.example.com/*");
+
+ bool called;
+ scoped_refptr<ServiceWorkerRegistration> old_registration;
+ storage_->Register(
+ pattern,
+ GURL("http://www.example.com/service_worker.js"),
+ SaveRegistration(REGISTRATION_OK, &called, &old_registration));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern;
+ storage_->FindRegistrationForPattern(
+ pattern,
+ SaveFoundRegistration(
+ true, REGISTRATION_OK, &called, &old_registration_by_pattern));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_EQ(old_registration, old_registration_by_pattern);
+ old_registration_by_pattern = NULL;
+
+ scoped_refptr<ServiceWorkerRegistration> new_registration;
+ storage_->Register(
+ pattern,
+ GURL("http://www.example.com/service_worker_new.js"),
+ SaveRegistration(REGISTRATION_OK, &called, &new_registration));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_TRUE(old_registration->HasOneRef());
+
+ ASSERT_NE(old_registration, new_registration);
+
+ scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern;
+ storage_->FindRegistrationForPattern(
+ pattern,
+ SaveFoundRegistration(true, REGISTRATION_OK, &called, &new_registration));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_NE(new_registration_by_pattern, old_registration);
+}
+
+// Make sure that when registering a duplicate pattern+script_url
+// combination, that the same registration is used.
+TEST_F(ServiceWorkerStorageTest, RegisterDuplicateScript) {
+ GURL pattern("http://www.example.com/*");
+ GURL script_url("http://www.example.com/service_worker.js");
+
+ bool called;
+ scoped_refptr<ServiceWorkerRegistration> old_registration;
+ storage_->Register(
+ pattern,
+ script_url,
+ SaveRegistration(REGISTRATION_OK, &called, &old_registration));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern;
+ storage_->FindRegistrationForPattern(
+ pattern,
+ SaveFoundRegistration(
+ true, REGISTRATION_OK, &called, &old_registration_by_pattern));
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_TRUE(old_registration_by_pattern);
+
+ scoped_refptr<ServiceWorkerRegistration> new_registration;
+ storage_->Register(
+ pattern,
+ script_url,
+ SaveRegistration(REGISTRATION_OK, &called, &new_registration));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_EQ(old_registration, new_registration);
+
+ ASSERT_FALSE(old_registration->HasOneRef());
+
+ scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern;
+ storage_->FindRegistrationForPattern(
+ pattern,
+ SaveFoundRegistration(
+ true, REGISTRATION_OK, &called, &new_registration_by_pattern));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ ASSERT_EQ(new_registration, old_registration);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
new file mode 100644
index 00000000000..a91ac6e9aa9
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -0,0 +1,56 @@
+// 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/service_worker/service_worker_version.h"
+
+#include "base/stl_util.h"
+#include "content/browser/service_worker/embedded_worker_instance.h"
+#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+
+namespace content {
+
+ServiceWorkerVersion::ServiceWorkerVersion(
+ ServiceWorkerRegistration* registration,
+ EmbeddedWorkerRegistry* worker_registry,
+ int64 version_id)
+ : version_id_(version_id),
+ is_shutdown_(false),
+ registration_(registration) {
+ if (worker_registry)
+ embedded_worker_ = worker_registry->CreateWorker();
+}
+
+ServiceWorkerVersion::~ServiceWorkerVersion() { DCHECK(is_shutdown_); }
+
+void ServiceWorkerVersion::Shutdown() {
+ is_shutdown_ = true;
+ registration_ = NULL;
+ embedded_worker_.reset();
+}
+
+void ServiceWorkerVersion::StartWorker() {
+ DCHECK(!is_shutdown_);
+ DCHECK(registration_);
+ embedded_worker_->Start(version_id_, registration_->script_url());
+}
+
+void ServiceWorkerVersion::StopWorker() {
+ DCHECK(!is_shutdown_);
+ embedded_worker_->Stop();
+}
+
+void ServiceWorkerVersion::OnAssociateProvider(
+ ServiceWorkerProviderHost* provider_host) {
+ DCHECK(!is_shutdown_);
+ embedded_worker_->AddProcessReference(provider_host->process_id());
+}
+
+void ServiceWorkerVersion::OnUnassociateProvider(
+ ServiceWorkerProviderHost* provider_host) {
+ embedded_worker_->ReleaseProcessReference(provider_host->process_id());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
new file mode 100644
index 00000000000..46b75bd6866
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -0,0 +1,94 @@
+// 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_SERVICE_WORKER_SERVICE_WORKER_VERSION_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_VERSION_H_
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+
+class GURL;
+
+namespace content {
+
+class EmbeddedWorkerInstance;
+class EmbeddedWorkerRegistry;
+class ServiceWorkerProviderHost;
+class ServiceWorkerRegistration;
+
+// This class corresponds to a specific version of a ServiceWorker
+// script for a given pattern. When a script is upgraded, there may be
+// more than one ServiceWorkerVersion "running" at a time, but only
+// one of them is active. This class connects the actual script with a
+// running worker.
+// Instances of this class are in one of two install states:
+// - Pending: The script is in the process of being installed. There
+// may be another active script running.
+// - Active: The script is the only worker handling requests for the
+// registration's pattern.
+//
+// In addition, a version has a running state (this is a rough
+// sketch). Since a service worker can be stopped and started at any
+// time, it will transition among these states multiple times during
+// its lifetime.
+// - Stopped: The script is not running
+// - Starting: A request to fire an event against the version has been
+// queued, but the worker is not yet
+// loaded/initialized/etc.
+// - Started: The worker is ready to receive events
+// - Stopping: The worker is returning to the stopped state.
+//
+// The worker can "run" in both the Pending and the Active
+// install states above. During the Pending state, the worker is only
+// started in order to fire the 'install' and 'activate'
+// events. During the Active state, it can receive other events such
+// as 'fetch'.
+//
+// And finally, is_shutdown_ is detects the live-ness of the object
+// itself. If the object is shut down, then it is in the process of
+// being deleted from memory. This happens when a version is replaced
+// as well as at browser shutdown.
+class CONTENT_EXPORT ServiceWorkerVersion
+ : NON_EXPORTED_BASE(public base::RefCounted<ServiceWorkerVersion>) {
+ public:
+ ServiceWorkerVersion(
+ ServiceWorkerRegistration* registration,
+ EmbeddedWorkerRegistry* worker_registry,
+ int64 version_id);
+
+ int64 version_id() const { return version_id_; }
+
+ void Shutdown();
+ bool is_shutdown() const { return is_shutdown_; }
+
+ // Starts and stops an embedded worker for this version.
+ void StartWorker();
+ void StopWorker();
+
+ // Called when this version is associated to a provider host.
+ // Non-null |provider_host| must be given.
+ void OnAssociateProvider(ServiceWorkerProviderHost* provider_host);
+ void OnUnassociateProvider(ServiceWorkerProviderHost* provider_host);
+
+ private:
+ friend class base::RefCounted<ServiceWorkerVersion>;
+
+ ~ServiceWorkerVersion();
+
+ const int64 version_id_;
+
+ bool is_shutdown_;
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+
+ scoped_ptr<EmbeddedWorkerInstance> embedded_worker_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersion);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_VERSION_H_
diff --git a/chromium/content/browser/session_history_browsertest.cc b/chromium/content/browser/session_history_browsertest.cc
index 7d006b606f6..bec8293a6b8 100644
--- a/chromium/content/browser/session_history_browsertest.cc
+++ b/chromium/content/browser/session_history_browsertest.cc
@@ -99,7 +99,7 @@ class SessionHistoryTest : public ContentBrowserTest {
void NavigateAndCheckTitle(const char* filename,
const std::string& expected_title) {
- string16 expected_title16(ASCIIToUTF16(expected_title));
+ base::string16 expected_title16(ASCIIToUTF16(expected_title));
TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
NavigateToURL(shell(), GetURL(filename));
ASSERT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
diff --git a/chromium/content/browser/signed_certificate_timestamp_store_impl.cc b/chromium/content/browser/signed_certificate_timestamp_store_impl.cc
new file mode 100644
index 00000000000..9397ebdf5c2
--- /dev/null
+++ b/chromium/content/browser/signed_certificate_timestamp_store_impl.cc
@@ -0,0 +1,39 @@
+// 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/signed_certificate_timestamp_store_impl.h"
+
+#include "base/memory/singleton.h"
+
+namespace content {
+
+// static
+SignedCertificateTimestampStore*
+SignedCertificateTimestampStore::GetInstance() {
+ return SignedCertificateTimestampStoreImpl::GetInstance();
+}
+
+// static
+SignedCertificateTimestampStoreImpl*
+SignedCertificateTimestampStoreImpl::GetInstance() {
+ return Singleton<SignedCertificateTimestampStoreImpl>::get();
+}
+
+SignedCertificateTimestampStoreImpl::SignedCertificateTimestampStoreImpl() {}
+
+SignedCertificateTimestampStoreImpl::~SignedCertificateTimestampStoreImpl() {}
+
+int SignedCertificateTimestampStoreImpl::Store(
+ net::ct::SignedCertificateTimestamp* sct,
+ int process_id) {
+ return store_.Store(sct, process_id);
+}
+
+bool SignedCertificateTimestampStoreImpl::Retrieve(
+ int sct_id,
+ scoped_refptr<net::ct::SignedCertificateTimestamp>* sct) {
+ return store_.Retrieve(sct_id, sct);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/signed_certificate_timestamp_store_impl.h b/chromium/content/browser/signed_certificate_timestamp_store_impl.h
new file mode 100644
index 00000000000..4cd98ccb041
--- /dev/null
+++ b/chromium/content/browser/signed_certificate_timestamp_store_impl.h
@@ -0,0 +1,43 @@
+// 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_SIGNED_CERTIFICATE_STORE_IMPL_H_
+#define CONTENT_BROWSER_SIGNED_CERTIFICATE_STORE_IMPL_H_
+
+#include "content/browser/renderer_data_memoizing_store.h"
+#include "content/public/browser/signed_certificate_timestamp_store.h"
+#include "net/cert/signed_certificate_timestamp.h"
+
+template <typename T> struct DefaultSingletonTraits;
+
+namespace content {
+
+class SignedCertificateTimestampStoreImpl
+ : public SignedCertificateTimestampStore {
+ public:
+ // Returns the singleton instance of the SignedCertificateTimestampStore.
+ static SignedCertificateTimestampStoreImpl* GetInstance();
+
+ // SignedCertificateTimestampStore implementation:
+ virtual int Store(
+ net::ct::SignedCertificateTimestamp* sct,
+ int render_process_host_id) OVERRIDE;
+ virtual bool Retrieve(
+ int sct_id,
+ scoped_refptr<net::ct::SignedCertificateTimestamp>* sct) OVERRIDE;
+
+ private:
+ friend struct DefaultSingletonTraits<SignedCertificateTimestampStoreImpl>;
+
+ SignedCertificateTimestampStoreImpl();
+ virtual ~SignedCertificateTimestampStoreImpl();
+
+ RendererDataMemoizingStore<net::ct::SignedCertificateTimestamp> store_;
+
+ DISALLOW_COPY_AND_ASSIGN(SignedCertificateTimestampStoreImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SIGNED_CERTIFICATE_STORE_IMPL_H_
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index ade96cba840..c003eb73484 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -7,11 +7,10 @@
#include "base/command_line.h"
#include "content/browser/browsing_instance.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host_factory.h"
#include "content/public/browser/web_ui_controller_factory.h"
#include "content/public/common/content_switches.h"
@@ -20,21 +19,6 @@
namespace content {
-static bool IsURLSameAsAnySiteInstance(const GURL& url) {
- if (!url.is_valid())
- return false;
-
- // We treat javascript: as the same site as any URL since it is actually
- // a modifier on existing pages.
- if (url.SchemeIs(kJavaScriptScheme))
- return true;
-
- return url == GURL(kChromeUICrashURL) ||
- url == GURL(kChromeUIKillURL) ||
- url == GURL(kChromeUIHangURL) ||
- url == GURL(kChromeUIShorthangURL);
-}
-
const RenderProcessHostFactory*
SiteInstanceImpl::g_render_process_host_factory_ = NULL;
int32 SiteInstanceImpl::next_site_instance_id_ = 1;
@@ -46,14 +30,14 @@ SiteInstanceImpl::SiteInstanceImpl(BrowsingInstance* browsing_instance)
process_(NULL),
has_site_(false) {
DCHECK(browsing_instance);
-
- registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
- NotificationService::AllBrowserContextsAndSources());
}
SiteInstanceImpl::~SiteInstanceImpl() {
GetContentClient()->browser()->SiteInstanceDeleting(this);
+ if (process_)
+ process_->RemoveObserver(this);
+
// Now that no one is referencing us, we can safely remove ourselves from
// the BrowsingInstance. Any future visits to a page from this site
// (within the same BrowsingInstance) can safely create a new SiteInstance.
@@ -122,13 +106,14 @@ RenderProcessHost* SiteInstanceImpl::GetProcess() {
BrowserContext::GetStoragePartition(browser_context, this));
bool supports_browser_plugin = GetContentClient()->browser()->
SupportsBrowserPlugin(browser_context, site_);
- process_ =
- new RenderProcessHostImpl(browser_context, partition,
- supports_browser_plugin,
- site_.SchemeIs(chrome::kGuestScheme));
+ process_ = new RenderProcessHostImpl(browser_context,
+ partition,
+ supports_browser_plugin,
+ site_.SchemeIs(kGuestScheme));
}
}
CHECK(process_);
+ process_->AddObserver(this);
// If we are using process-per-site, we need to register this process
// for the current site so that we can find it again. (If no site is set
@@ -211,7 +196,7 @@ bool SiteInstanceImpl::HasWrongProcessForURL(const GURL& url) {
// If the URL to navigate to can be associated with any site instance,
// we want to keep it in the same process.
- if (IsURLSameAsAnySiteInstance(url))
+ if (IsRendererDebugURL(url))
return false;
// If the site URL is an extension (e.g., for hosted apps or WebUI) but the
@@ -260,7 +245,7 @@ bool SiteInstance::IsSameWebSite(BrowserContext* browser_context,
// Some special URLs will match the site instance of any other URL. This is
// done before checking both of them for validity, since we want these URLs
// to have the same site instance as even an invalid one.
- if (IsURLSameAsAnySiteInstance(url1) || IsURLSameAsAnySiteInstance(url2))
+ if (IsRendererDebugURL(url1) || IsRendererDebugURL(url2))
return true;
// If either URL is invalid, they aren't part of the same site.
@@ -281,7 +266,7 @@ bool SiteInstance::IsSameWebSite(BrowserContext* browser_context,
GURL SiteInstance::GetSiteForURL(BrowserContext* browser_context,
const GURL& real_url) {
// TODO(fsamuel, creis): For some reason appID is not recognized as a host.
- if (real_url.SchemeIs(chrome::kGuestScheme))
+ if (real_url.SchemeIs(kGuestScheme))
return real_url;
GURL url = SiteInstanceImpl::GetEffectiveURL(browser_context, real_url);
@@ -326,13 +311,10 @@ GURL SiteInstanceImpl::GetEffectiveURL(BrowserContext* browser_context,
GetEffectiveURL(browser_context, url);
}
-void SiteInstanceImpl::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- DCHECK(type == NOTIFICATION_RENDERER_PROCESS_TERMINATED);
- RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
- if (rph == process_)
- process_ = NULL;
+void SiteInstanceImpl::RenderProcessHostDestroyed(RenderProcessHost* host) {
+ DCHECK_EQ(process_, host);
+ process_->RemoveObserver(this);
+ process_ = NULL;
}
void SiteInstanceImpl::LockToOrigin() {
diff --git a/chromium/content/browser/site_instance_impl.h b/chromium/content/browser/site_instance_impl.h
index 714fee0c23b..edaeb3e702d 100644
--- a/chromium/content/browser/site_instance_impl.h
+++ b/chromium/content/browser/site_instance_impl.h
@@ -7,8 +7,7 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/common/content_export.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/site_instance.h"
#include "url/gurl.h"
@@ -16,12 +15,12 @@ namespace content {
class RenderProcessHostFactory;
class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
- public NotificationObserver {
+ public RenderProcessHostObserver {
public:
// SiteInstance interface overrides.
virtual int32 GetId() OVERRIDE;
virtual bool HasProcess() const OVERRIDE;
- virtual RenderProcessHost* GetProcess() OVERRIDE;
+ virtual RenderProcessHost* GetProcess() OVERRIDE;
virtual const GURL& GetSiteURL() const OVERRIDE;
virtual SiteInstance* GetRelatedSiteInstance(const GURL& url) OVERRIDE;
virtual bool IsRelatedSiteInstance(const SiteInstance* instance) OVERRIDE;
@@ -67,6 +66,15 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
static void set_render_process_host_factory(
const RenderProcessHostFactory* rph_factory);
+ // Get the effective URL for the given actual URL. This allows the
+ // ContentBrowserClient to override the SiteInstance's site for certain URLs.
+ // For example, Chrome uses this to replace hosted app URLs with extension
+ // hosts.
+ // Only public so that we can make a consistent process swap decision in
+ // RenderFrameHostManager.
+ static GURL GetEffectiveURL(BrowserContext* browser_context,
+ const GURL& url);
+
protected:
friend class BrowsingInstance;
friend class SiteInstance;
@@ -80,14 +88,8 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
explicit SiteInstanceImpl(BrowsingInstance* browsing_instance);
private:
- // Get the effective URL for the given actual URL.
- static GURL GetEffectiveURL(BrowserContext* browser_context,
- const GURL& url);
-
- // NotificationObserver implementation.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ // RenderProcessHostObserver implementation.
+ virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE;
// Used to restrict a process' origin access rights.
void LockToOrigin();
@@ -104,15 +106,9 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
// The number of active views under this SiteInstance.
size_t active_view_count_;
- NotificationRegistrar registrar_;
-
// BrowsingInstance to which this SiteInstance belongs.
scoped_refptr<BrowsingInstance> browsing_instance_;
- // Factory for new RenderProcessHosts, not owned by this class. NULL indiactes
- // that the default BrowserRenderProcessHost should be created.
- const RenderProcessHostFactory* render_process_host_factory_;
-
// Current RenderProcessHost that is rendering pages for this SiteInstance.
// This pointer will only change once the RenderProcessHost is destructed. It
// will still remain the same even if the process crashes, since in that
diff --git a/chromium/content/browser/site_instance_impl_unittest.cc b/chromium/content/browser/site_instance_impl_unittest.cc
index d61c70b353d..ac3c1927c92 100644
--- a/chromium/content/browser/site_instance_impl_unittest.cc
+++ b/chromium/content/browser/site_instance_impl_unittest.cc
@@ -9,11 +9,10 @@
#include "content/browser/browser_thread_impl.h"
#include "content/browser/browsing_instance.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
#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/test_render_view_host.h"
#include "content/browser/site_instance_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/public/common/content_client.h"
@@ -26,14 +25,13 @@
#include "content/public/test/test_browser_thread.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_content_client.h"
+#include "content/test/test_render_view_host.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/url_util.h"
namespace content {
namespace {
-const char kSameAsAnyInstanceURL[] = "about:internets";
-
const char kPrivilegedScheme[] = "privileged";
class SiteInstanceTestWebUIControllerFactory : public WebUIControllerFactory {
@@ -96,6 +94,8 @@ class SiteInstanceTest : public testing::Test {
old_browser_client_ = SetBrowserClientForTesting(&browser_client_);
url_util::AddStandardScheme(kPrivilegedScheme);
url_util::AddStandardScheme(chrome::kChromeUIScheme);
+
+ SiteInstanceImpl::set_render_process_host_factory(&rph_factory_);
}
virtual void TearDown() {
@@ -137,6 +137,7 @@ class SiteInstanceTest : public testing::Test {
SiteInstanceTestBrowserClient browser_client_;
ContentBrowserClient* old_browser_client_;
+ MockRenderProcessHostFactory rph_factory_;
};
// Subclass of BrowsingInstance that updates a counter when deleted and
@@ -203,7 +204,8 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
EXPECT_EQ(0, site_delete_counter);
NavigationEntryImpl* e1 = new NavigationEntryImpl(
- instance, 0, url, Referrer(), string16(), PAGE_TRANSITION_LINK, false);
+ instance, 0, url, Referrer(), base::string16(), PAGE_TRANSITION_LINK,
+ false);
// Redundantly setting e1's SiteInstance shouldn't affect the ref count.
e1->set_site_instance(instance);
@@ -211,7 +213,8 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
// Add a second reference
NavigationEntryImpl* e2 = new NavigationEntryImpl(
- instance, 0, url, Referrer(), string16(), PAGE_TRANSITION_LINK, false);
+ instance, 0, url, Referrer(), base::string16(), PAGE_TRANSITION_LINK,
+ false);
// Now delete both entries and be sure the SiteInstance goes away.
delete e1;
@@ -263,7 +266,8 @@ TEST_F(SiteInstanceTest, CloneNavigationEntry) {
&browsing_delete_counter);
NavigationEntryImpl* e1 = new NavigationEntryImpl(
- instance1, 0, url, Referrer(), string16(), PAGE_TRANSITION_LINK, false);
+ instance1, 0, url, Referrer(), base::string16(), PAGE_TRANSITION_LINK,
+ false);
// Clone the entry
NavigationEntryImpl* e2 = new NavigationEntryImpl(*e1);
@@ -345,7 +349,7 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
test_url = GURL("file:///C:/Downloads/");
EXPECT_EQ(GURL(), SiteInstanceImpl::GetSiteForURL(NULL, test_url));
- std::string guest_url(chrome::kGuestScheme);
+ std::string guest_url(kGuestScheme);
guest_url.append("://abc123");
test_url = GURL(guest_url);
EXPECT_EQ(test_url, SiteInstanceImpl::GetSiteForURL(NULL, test_url));
@@ -553,8 +557,6 @@ static SiteInstanceImpl* CreateSiteInstance(BrowserContext* browser_context,
// Test to ensure that pages that require certain privileges are grouped
// in processes with similar pages.
TEST_F(SiteInstanceTest, ProcessSharingByType) {
- MockRenderProcessHostFactory rph_factory;
- SiteInstanceImpl::set_render_process_host_factory(&rph_factory);
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index e37ac97cce8..cca1df07c00 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -5,17 +5,25 @@
#include "base/command_line.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents_observer.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/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_content_browser_client.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
+#include "net/base/escape.h"
+#include "net/dns/mock_host_resolver.h"
namespace content {
@@ -28,10 +36,11 @@ class SitePerProcessWebContentsObserver: public WebContentsObserver {
virtual void DidFailProvisionalLoad(
int64 frame_id,
+ const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& validated_url,
int error_code,
- const string16& error_description,
+ const base::string16& error_description,
RenderViewHost* render_view_host) OVERRIDE {
navigation_url_ = validated_url;
navigation_succeeded_ = false;
@@ -39,6 +48,7 @@ class SitePerProcessWebContentsObserver: public WebContentsObserver {
virtual void DidCommitProvisionalLoadForFrame(
int64 frame_id,
+ const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& url,
PageTransition transition_type,
@@ -139,9 +149,7 @@ void RedirectNotificationObserver::Observe(
}
class SitePerProcessBrowserTest : public ContentBrowserTest {
- public:
- SitePerProcessBrowserTest() {}
-
+ protected:
bool NavigateIframeToURL(Shell* window,
const GURL& url,
std::string iframe_id) {
@@ -157,6 +165,20 @@ class SitePerProcessBrowserTest : public ContentBrowserTest {
return result;
}
+ void NavigateToURLContentInitiated(Shell* window,
+ const GURL& url,
+ bool should_replace_current_entry) {
+ std::string script;
+ if (should_replace_current_entry)
+ script = base::StringPrintf("location.replace('%s')", url.spec().c_str());
+ 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);
+ EXPECT_TRUE(result);
+ load_observer.Wait();
+ }
+
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
command_line->AppendSwitch(switches::kSitePerProcess);
}
@@ -399,4 +421,304 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
}
+// Ensures FrameTree correctly reflects page structure during navigations.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ FrameTreeShape) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL base_url = test_server()->GetURL("files/site_isolation/");
+ GURL::Replacements replace_host;
+ std::string host_str("A.com"); // Must stay in scope with replace_host.
+ replace_host.SetHostStr(host_str);
+ base_url = base_url.ReplaceComponents(replace_host);
+
+ // Load doc without iframes. Verify FrameTree just has root.
+ // Frame tree:
+ // Site-A Root
+ NavigateToURL(shell(), base_url.Resolve("blank.html"));
+ FrameTreeNode* root =
+ static_cast<WebContentsImpl*>(shell()->web_contents())->
+ GetFrameTree()->root();
+ EXPECT_EQ(0U, root->child_count());
+
+ // Add 2 same-site frames. Verify 3 nodes in tree with proper names.
+ // Frame tree:
+ // Site-A Root -- Site-A frame1
+ // \-- Site-A frame2
+ WindowedNotificationObserver observer1(
+ content::NOTIFICATION_LOAD_STOP,
+ content::Source<NavigationController>(
+ &shell()->web_contents()->GetController()));
+ NavigateToURL(shell(), base_url.Resolve("frames-X-X.html"));
+ observer1.Wait();
+ ASSERT_EQ(2U, root->child_count());
+ EXPECT_EQ(0U, root->child_at(0)->child_count());
+ EXPECT_EQ(0U, root->child_at(1)->child_count());
}
+
+// TODO(ajwong): Talk with nasko and merge this functionality with
+// FrameTreeShape.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ FrameTreeShape2) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(test_server()->Start());
+
+ NavigateToURL(shell(),
+ test_server()->GetURL("files/frame_tree/top.html"));
+
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
+ wc->GetRenderViewHost());
+ FrameTreeNode* root = wc->GetFrameTree()->root();
+
+ // Check that the root node is properly created with the frame id of the
+ // initial navigation.
+ ASSERT_EQ(3UL, root->child_count());
+ EXPECT_EQ(std::string(), root->frame_name());
+ EXPECT_EQ(rvh->main_frame_id(), root->frame_id());
+
+ ASSERT_EQ(2UL, root->child_at(0)->child_count());
+ EXPECT_STREQ("1-1-name", root->child_at(0)->frame_name().c_str());
+
+ // Verify the deepest node exists and has the right name.
+ ASSERT_EQ(2UL, root->child_at(2)->child_count());
+ EXPECT_EQ(1UL, root->child_at(2)->child_at(1)->child_count());
+ EXPECT_EQ(0UL, root->child_at(2)->child_at(1)->child_at(0)->child_count());
+ EXPECT_STREQ("3-1-id",
+ root->child_at(2)->child_at(1)->child_at(0)->frame_name().c_str());
+
+ // Navigate to about:blank, which should leave only the root node of the frame
+ // tree in the browser process.
+ NavigateToURL(shell(), test_server()->GetURL("files/title1.html"));
+
+ root = wc->GetFrameTree()->root();
+ EXPECT_EQ(0UL, root->child_count());
+ EXPECT_EQ(std::string(), root->frame_name());
+ EXPECT_EQ(rvh->main_frame_id(), root->frame_id());
+}
+
+// Test that we can navigate away if the previous renderer doesn't clean up its
+// child frames.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, FrameTreeAfterCrash) {
+ ASSERT_TRUE(test_server()->Start());
+ NavigateToURL(shell(),
+ test_server()->GetURL("files/frame_tree/top.html"));
+
+ // Crash the renderer so that it doesn't send any FrameDetached messages.
+ WindowedNotificationObserver crash_observer(
+ NOTIFICATION_RENDERER_PROCESS_CLOSED,
+ NotificationService::AllSources());
+ NavigateToURL(shell(), GURL(kChromeUICrashURL));
+ crash_observer.Wait();
+
+ // The frame tree should be cleared, and the frame ID should be reset.
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
+ wc->GetRenderViewHost());
+ FrameTreeNode* root = wc->GetFrameTree()->root();
+ EXPECT_EQ(0UL, root->child_count());
+ EXPECT_EQ(FrameTreeNode::kInvalidFrameId, root->frame_id());
+ EXPECT_EQ(rvh->main_frame_id(), root->frame_id());
+
+ // Navigate to a new URL.
+ NavigateToURL(shell(), test_server()->GetURL("files/title1.html"));
+
+ // The frame ID should now be set.
+ EXPECT_EQ(0UL, root->child_count());
+ EXPECT_NE(FrameTreeNode::kInvalidFrameId, root->frame_id());
+ EXPECT_EQ(rvh->main_frame_id(), root->frame_id());
+}
+
+// Test that we can navigate away if the previous renderer doesn't clean up its
+// child frames.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateWithLeftoverFrames) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(test_server()->Start());
+
+ GURL base_url = test_server()->GetURL("files/site_isolation/");
+ GURL::Replacements replace_host;
+ std::string host_str("A.com"); // Must stay in scope with replace_host.
+ replace_host.SetHostStr(host_str);
+ base_url = base_url.ReplaceComponents(replace_host);
+
+ NavigateToURL(shell(),
+ test_server()->GetURL("files/frame_tree/top.html"));
+
+ // Hang the renderer so that it doesn't send any FrameDetached messages.
+ // (This navigation will never complete, so don't wait for it.)
+ shell()->LoadURL(GURL(kChromeUIHangURL));
+
+ // Check that the frame tree still has children.
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTreeNode* root = wc->GetFrameTree()->root();
+ ASSERT_EQ(3UL, root->child_count());
+
+ // Navigate to a new URL. We use LoadURL because NavigateToURL will try to
+ // wait for the previous navigation to stop.
+ TestNavigationObserver tab_observer(wc, 1);
+ shell()->LoadURL(base_url.Resolve("blank.html"));
+ tab_observer.Wait();
+
+ // The frame tree should now be cleared, and the frame ID should be valid.
+ EXPECT_EQ(0UL, root->child_count());
+ EXPECT_NE(FrameTreeNode::kInvalidFrameId, root->frame_id());
+}
+
+// Tests that the |should_replace_current_entry| flag persists correctly across
+// request transfers that began with a cross-process navigation.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ReplaceEntryCrossProcessThenTranfers) {
+ const NavigationController& controller =
+ shell()->web_contents()->GetController();
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(test_server()->Start());
+
+ // These must all stay in scope with replace_host.
+ GURL::Replacements replace_host;
+ std::string a_com("A.com");
+ std::string b_com("B.com");
+
+ // Navigate to a starting URL, so there is a history entry to replace.
+ GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
+ NavigateToURL(shell(), url1);
+
+ // Force all future navigations to transfer. Note that this includes same-site
+ // navigiations which may cause double process swaps (via OpenURL and then via
+ // transfer). This test intentionally exercises that case.
+ ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
+
+ // Navigate to a page on A.com with entry replacement. This navigation is
+ // cross-site, so the renderer will send it to the browser via OpenURL to give
+ // to a new process. It will then be transferred into yet another process due
+ // to the call above.
+ GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
+ replace_host.SetHostStr(a_com);
+ url2 = url2.ReplaceComponents(replace_host);
+ NavigateToURLContentInitiated(shell(), url2, true);
+
+ // There should be one history entry. url2 should have replaced url1.
+ EXPECT_TRUE(controller.GetPendingEntry() == NULL);
+ EXPECT_EQ(1, controller.GetEntryCount());
+ EXPECT_EQ(0, controller.GetCurrentEntryIndex());
+ EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
+
+ // Now navigate as before to a page on B.com, but normally (without
+ // replacement). This will still perform a double process-swap as above, via
+ // OpenURL and then transfer.
+ GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3");
+ replace_host.SetHostStr(b_com);
+ url3 = url3.ReplaceComponents(replace_host);
+ NavigateToURLContentInitiated(shell(), url3, false);
+
+ // There should be two history entries. url2 should have replaced url1. url2
+ // should not have replaced url3.
+ EXPECT_TRUE(controller.GetPendingEntry() == NULL);
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetCurrentEntryIndex());
+ EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
+ EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL());
+}
+
+// Tests that the |should_replace_current_entry| flag persists correctly across
+// request transfers that began with a content-initiated in-process
+// navigation. This test is the same as the test above, except transfering from
+// in-process.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ReplaceEntryInProcessThenTranfers) {
+ const NavigationController& controller =
+ shell()->web_contents()->GetController();
+ ASSERT_TRUE(test_server()->Start());
+
+ // Navigate to a starting URL, so there is a history entry to replace.
+ GURL url = test_server()->GetURL("files/site_isolation/blank.html?1");
+ NavigateToURL(shell(), url);
+
+ // Force all future navigations to transfer. Note that this includes same-site
+ // navigiations which may cause double process swaps (via OpenURL and then via
+ // transfer). All navigations in this test are same-site, so it only swaps
+ // processes via request transfer.
+ ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
+
+ // Navigate in-process with entry replacement. It will then be transferred
+ // into a new one due to the call above.
+ GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
+ NavigateToURLContentInitiated(shell(), url2, true);
+
+ // There should be one history entry. url2 should have replaced url1.
+ EXPECT_TRUE(controller.GetPendingEntry() == NULL);
+ EXPECT_EQ(1, controller.GetEntryCount());
+ EXPECT_EQ(0, controller.GetCurrentEntryIndex());
+ EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
+
+ // Now navigate as before, but without replacement.
+ GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3");
+ NavigateToURLContentInitiated(shell(), url3, false);
+
+ // There should be two history entries. url2 should have replaced url1. url2
+ // should not have replaced url3.
+ EXPECT_TRUE(controller.GetPendingEntry() == NULL);
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetCurrentEntryIndex());
+ EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL());
+ EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL());
+}
+
+// Tests that the |should_replace_current_entry| flag persists correctly across
+// request transfers that cross processes twice from renderer policy.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ReplaceEntryCrossProcessTwice) {
+ const NavigationController& controller =
+ shell()->web_contents()->GetController();
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(test_server()->Start());
+
+ // These must all stay in scope with replace_host.
+ GURL::Replacements replace_host;
+ std::string a_com("A.com");
+ std::string b_com("B.com");
+
+ // Navigate to a starting URL, so there is a history entry to replace.
+ GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
+ NavigateToURL(shell(), url1);
+
+ // Navigate to a page on A.com which redirects to B.com with entry
+ // replacement. This will switch processes via OpenURL twice. First to A.com,
+ // and second in response to the server redirect to B.com. The second swap is
+ // also renderer-initiated via OpenURL because decidePolicyForNavigation is
+ // currently applied on redirects.
+ GURL url2b = test_server()->GetURL("files/site_isolation/blank.html?2");
+ replace_host.SetHostStr(b_com);
+ url2b = url2b.ReplaceComponents(replace_host);
+ GURL url2a = test_server()->GetURL(
+ "server-redirect?" + net::EscapeQueryParamValue(url2b.spec(), false));
+ replace_host.SetHostStr(a_com);
+ url2a = url2a.ReplaceComponents(replace_host);
+ NavigateToURLContentInitiated(shell(), url2a, true);
+
+ // There should be one history entry. url2b should have replaced url1.
+ EXPECT_TRUE(controller.GetPendingEntry() == NULL);
+ EXPECT_EQ(1, controller.GetEntryCount());
+ EXPECT_EQ(0, controller.GetCurrentEntryIndex());
+ EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL());
+
+ // Now repeat without replacement.
+ GURL url3b = test_server()->GetURL("files/site_isolation/blank.html?3");
+ replace_host.SetHostStr(b_com);
+ url3b = url3b.ReplaceComponents(replace_host);
+ GURL url3a = test_server()->GetURL(
+ "server-redirect?" + net::EscapeQueryParamValue(url3b.spec(), false));
+ replace_host.SetHostStr(a_com);
+ url3a = url3a.ReplaceComponents(replace_host);
+ NavigateToURLContentInitiated(shell(), url3a, false);
+
+ // There should be two history entries. url2b should have replaced url1. url2b
+ // should not have replaced url3b.
+ EXPECT_TRUE(controller.GetPendingEntry() == NULL);
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetCurrentEntryIndex());
+ EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL());
+ EXPECT_EQ(url3b, controller.GetEntryAtIndex(1)->GetURL());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/speech/OWNERS b/chromium/content/browser/speech/OWNERS
index 2c6195ec94b..b38caa6f1ff 100644
--- a/chromium/content/browser/speech/OWNERS
+++ b/chromium/content/browser/speech/OWNERS
@@ -1,4 +1,3 @@
hans@chromium.org
-primiano@chromium.org
tommi@chromium.org
xians@chromium.org
diff --git a/chromium/content/browser/speech/google_one_shot_remote_engine.cc b/chromium/content/browser/speech/google_one_shot_remote_engine.cc
index a421e79c228..575dd5fda6d 100644
--- a/chromium/content/browser/speech/google_one_shot_remote_engine.cc
+++ b/chromium/content/browser/speech/google_one_shot_remote_engine.cc
@@ -121,7 +121,7 @@ bool ParseServerResponse(const std::string& response_body,
const base::DictionaryValue* hypothesis_value =
static_cast<const base::DictionaryValue*>(hypothesis);
- string16 utterance;
+ base::string16 utterance;
if (!hypothesis_value->GetString(kUtteranceString, &utterance)) {
LOG(WARNING) << "ParseServerResponse: Missing utterance value.";
diff --git a/chromium/content/browser/speech/google_streaming_remote_engine.cc b/chromium/content/browser/speech/google_streaming_remote_engine.cc
index beacb22be94..b6b68d17ced 100644
--- a/chromium/content/browser/speech/google_streaming_remote_engine.cc
+++ b/chromium/content/browser/speech/google_streaming_remote_engine.cc
@@ -35,10 +35,9 @@ const char kWebServiceBaseUrl[] =
"https://www.google.com/speech-api/full-duplex/v1";
const char kDownstreamUrl[] = "/down?";
const char kUpstreamUrl[] = "/up?";
-const int kAudioPacketIntervalMs = 100;
const AudioEncoder::Codec kDefaultAudioCodec = AudioEncoder::CODEC_FLAC;
-// This mathces the maximum maxAlternatives value supported by the server.
+// This matches the maximum maxAlternatives value supported by the server.
const uint32 kMaxMaxAlternatives = 30;
// TODO(hans): Remove this and other logging when we don't need it anymore.
@@ -86,8 +85,9 @@ std::string GetAPIKey() {
} // namespace
-const int GoogleStreamingRemoteEngine::kUpstreamUrlFetcherIdForTests = 0;
-const int GoogleStreamingRemoteEngine::kDownstreamUrlFetcherIdForTests = 1;
+const int GoogleStreamingRemoteEngine::kAudioPacketIntervalMs = 100;
+const int GoogleStreamingRemoteEngine::kUpstreamUrlFetcherIdForTesting = 0;
+const int GoogleStreamingRemoteEngine::kDownstreamUrlFetcherIdForTesting = 1;
const int GoogleStreamingRemoteEngine::kWebserviceStatusNoError = 0;
const int GoogleStreamingRemoteEngine::kWebserviceStatusErrorNoMatch = 5;
@@ -324,7 +324,8 @@ GoogleStreamingRemoteEngine::ConnectBothStreams(const FSMEventArgs&) {
JoinString(downstream_args, '&'));
downstream_fetcher_.reset(URLFetcher::Create(
- kDownstreamUrlFetcherIdForTests, downstream_url, URLFetcher::GET, this));
+ kDownstreamUrlFetcherIdForTesting, downstream_url, URLFetcher::GET,
+ this));
downstream_fetcher_->SetRequestContext(url_context_.get());
downstream_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DO_NOT_SEND_COOKIES |
@@ -363,7 +364,7 @@ GoogleStreamingRemoteEngine::ConnectBothStreams(const FSMEventArgs&) {
JoinString(upstream_args, '&'));
upstream_fetcher_.reset(URLFetcher::Create(
- kUpstreamUrlFetcherIdForTests, upstream_url, URLFetcher::POST, this));
+ kUpstreamUrlFetcherIdForTesting, upstream_url, URLFetcher::POST, this));
upstream_fetcher_->SetChunkedUpload(encoder_->mime_type());
upstream_fetcher_->SetRequestContext(url_context_.get());
upstream_fetcher_->SetReferrer(config_.origin_url);
diff --git a/chromium/content/browser/speech/google_streaming_remote_engine.h b/chromium/content/browser/speech/google_streaming_remote_engine.h
index 488971ba1a6..11afae00e6c 100644
--- a/chromium/content/browser/speech/google_streaming_remote_engine.h
+++ b/chromium/content/browser/speech/google_streaming_remote_engine.h
@@ -49,6 +49,13 @@ class CONTENT_EXPORT GoogleStreamingRemoteEngine
public net::URLFetcherDelegate,
public NON_EXPORTED_BASE(base::NonThreadSafe) {
public:
+ // Duration of each audio packet.
+ static const int kAudioPacketIntervalMs;
+
+ // IDs passed to URLFetcher::Create(). Used for testing.
+ static const int kUpstreamUrlFetcherIdForTesting;
+ static const int kDownstreamUrlFetcherIdForTesting;
+
explicit GoogleStreamingRemoteEngine(net::URLRequestContextGetter* context);
virtual ~GoogleStreamingRemoteEngine();
@@ -67,12 +74,6 @@ class CONTENT_EXPORT GoogleStreamingRemoteEngine
int64 current, int64 total) OVERRIDE;
private:
- friend class GoogleStreamingRemoteEngineTest;
-
- // IDs passed to URLFetcher::Create(). Used for testing.
- static const int kUpstreamUrlFetcherIdForTests;
- static const int kDownstreamUrlFetcherIdForTests;
-
// Response status codes from the speech recognition webservice.
static const int kWebserviceStatusNoError;
static const int kWebserviceStatusErrorNoMatch;
diff --git a/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc b/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc
index 397250631fb..dd0ef89cad9 100644
--- a/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc
+++ b/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc
@@ -337,12 +337,12 @@ void GoogleStreamingRemoteEngineTest::TearDown() {
TestURLFetcher* GoogleStreamingRemoteEngineTest::GetUpstreamFetcher() {
return url_fetcher_factory_.GetFetcherByID(
- GoogleStreamingRemoteEngine::kUpstreamUrlFetcherIdForTests);
+ GoogleStreamingRemoteEngine::kUpstreamUrlFetcherIdForTesting);
}
TestURLFetcher* GoogleStreamingRemoteEngineTest::GetDownstreamFetcher() {
return url_fetcher_factory_.GetFetcherByID(
- GoogleStreamingRemoteEngine::kDownstreamUrlFetcherIdForTests);
+ GoogleStreamingRemoteEngine::kDownstreamUrlFetcherIdForTesting);
}
// Starts recognition on the engine, ensuring that both stream fetchers are
diff --git a/chromium/content/browser/speech/input_tag_speech_browsertest.cc b/chromium/content/browser/speech/input_tag_speech_browsertest.cc
index 0a1b2a9ca86..10c18785dd9 100644
--- a/chromium/content/browser/speech/input_tag_speech_browsertest.cc
+++ b/chromium/content/browser/speech/input_tag_speech_browsertest.cc
@@ -40,9 +40,9 @@ class InputTagSpeechBrowserTest : public ContentBrowserTest {
GURL test_url = GetTestUrl("speech", filename);
NavigateToURL(shell(), test_url);
- WebKit::WebMouseEvent mouse_event;
- mouse_event.type = WebKit::WebInputEvent::MouseDown;
- mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
+ blink::WebMouseEvent mouse_event;
+ mouse_event.type = blink::WebInputEvent::MouseDown;
+ mouse_event.button = blink::WebMouseEvent::ButtonLeft;
mouse_event.x = 0;
mouse_event.y = 0;
mouse_event.clickCount = 1;
@@ -52,7 +52,7 @@ class InputTagSpeechBrowserTest : public ContentBrowserTest {
NOTIFICATION_LOAD_STOP,
Source<NavigationController>(&web_contents->GetController()));
web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
- mouse_event.type = WebKit::WebInputEvent::MouseUp;
+ mouse_event.type = blink::WebInputEvent::MouseUp;
web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
fake_speech_recognition_manager_.WaitForRecognitionStarted();
@@ -79,7 +79,7 @@ class InputTagSpeechBrowserTest : public ContentBrowserTest {
// Inject the fake manager factory so that the test result is returned to
// the web page.
- SpeechRecognitionManager::SetManagerForTests(speech_recognition_manager_);
+ SpeechRecognitionManager::SetManagerForTesting(speech_recognition_manager_);
}
virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
diff --git a/chromium/content/browser/speech/input_tag_speech_dispatcher_host.cc b/chromium/content/browser/speech/input_tag_speech_dispatcher_host.cc
index 4a3af54ef37..23169c78105 100644
--- a/chromium/content/browser/speech/input_tag_speech_dispatcher_host.cc
+++ b/chromium/content/browser/speech/input_tag_speech_dispatcher_host.cc
@@ -22,19 +22,27 @@ const uint32 kMaxHypothesesForSpeechInputTag = 6;
namespace content {
InputTagSpeechDispatcherHost::InputTagSpeechDispatcherHost(
- bool guest,
+ bool is_guest,
int render_process_id,
net::URLRequestContextGetter* url_request_context_getter)
- : guest_(guest),
+ : is_guest_(is_guest),
render_process_id_(render_process_id),
- url_request_context_getter_(url_request_context_getter) {
+ url_request_context_getter_(url_request_context_getter),
+ weak_factory_(this) {
// Do not add any non-trivial initialization here, instead do it lazily when
// required (e.g. see the method |SpeechRecognitionManager::GetInstance()|) or
// add an Init() method.
}
InputTagSpeechDispatcherHost::~InputTagSpeechDispatcherHost() {
- SpeechRecognitionManager::GetInstance()->AbortAllSessionsForListener(this);
+ SpeechRecognitionManager::GetInstance()->AbortAllSessionsForRenderProcess(
+ render_process_id_);
+}
+
+base::WeakPtr<InputTagSpeechDispatcherHost>
+InputTagSpeechDispatcherHost::AsWeakPtr() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ return weak_factory_.GetWeakPtr();
}
bool InputTagSpeechDispatcherHost::OnMessageReceived(
@@ -60,15 +68,19 @@ void InputTagSpeechDispatcherHost::OverrideThreadForMessage(
*thread = BrowserThread::UI;
}
+void InputTagSpeechDispatcherHost::OnChannelClosing() {
+ weak_factory_.InvalidateWeakPtrs();
+}
+
void InputTagSpeechDispatcherHost::OnStartRecognition(
- const InputTagSpeechHostMsg_StartRecognition_Params& params) {
+ const InputTagSpeechHostMsg_StartRecognition_Params& params) {
InputTagSpeechHostMsg_StartRecognition_Params input_params(params);
int render_process_id = render_process_id_;
// The chrome layer is mostly oblivious to BrowserPlugin guests and so it
// cannot correctly place the speech bubble relative to a guest. Thus, we
// set up the speech recognition context relative to the embedder.
- int guest_render_view_id = 0;
- if (guest_) {
+ int guest_render_view_id = MSG_ROUTING_NONE;
+ if (is_guest_) {
RenderViewHostImpl* render_view_host =
RenderViewHostImpl::FromID(render_process_id_, params.render_view_id);
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
@@ -108,6 +120,8 @@ void InputTagSpeechDispatcherHost::StartRecognitionOnIO(
context.render_process_id = render_process_id;
context.render_view_id = params.render_view_id;
context.guest_render_view_id = guest_render_view_id;
+ // Keep context.embedder_render_process_id and context.embedder_render_view_id
+ // unset.
context.request_id = params.request_id;
context.element_rect = params.element_rect;
@@ -121,7 +135,7 @@ void InputTagSpeechDispatcherHost::StartRecognitionOnIO(
config.initial_context = context;
config.url_request_context_getter = url_request_context_getter_.get();
config.filter_profanities = filter_profanities;
- config.event_listener = this;
+ config.event_listener = AsWeakPtr();
int session_id = SpeechRecognitionManager::GetInstance()->CreateSession(
config);
@@ -162,8 +176,9 @@ void InputTagSpeechDispatcherHost::OnRecognitionResults(
const SpeechRecognitionSessionContext& context =
SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
- int render_view_id = context.guest_render_view_id ?
- context.guest_render_view_id : context.render_view_id;
+ int render_view_id =
+ context.guest_render_view_id == MSG_ROUTING_NONE ?
+ context.render_view_id : context.guest_render_view_id;
Send(new InputTagSpeechMsg_SetRecognitionResults(
render_view_id,
context.request_id,
@@ -176,8 +191,9 @@ void InputTagSpeechDispatcherHost::OnAudioEnd(int session_id) {
const SpeechRecognitionSessionContext& context =
SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
- int render_view_id = context.guest_render_view_id ?
- context.guest_render_view_id : context.render_view_id;
+ int render_view_id =
+ context.guest_render_view_id == MSG_ROUTING_NONE ?
+ context.render_view_id : context.guest_render_view_id;
Send(new InputTagSpeechMsg_RecordingComplete(render_view_id,
context.request_id));
DVLOG(1) << "InputTagSpeechDispatcherHost::OnAudioEnd exit";
@@ -187,8 +203,9 @@ void InputTagSpeechDispatcherHost::OnRecognitionEnd(int session_id) {
DVLOG(1) << "InputTagSpeechDispatcherHost::OnRecognitionEnd enter";
const SpeechRecognitionSessionContext& context =
SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
- int render_view_id = context.guest_render_view_id ?
- context.guest_render_view_id : context.render_view_id;
+ int render_view_id =
+ context.guest_render_view_id == MSG_ROUTING_NONE ?
+ context.render_view_id : context.guest_render_view_id;
Send(new InputTagSpeechMsg_RecognitionComplete(render_view_id,
context.request_id));
DVLOG(1) << "InputTagSpeechDispatcherHost::OnRecognitionEnd exit";
diff --git a/chromium/content/browser/speech/input_tag_speech_dispatcher_host.h b/chromium/content/browser/speech/input_tag_speech_dispatcher_host.h
index cb0bf3ba4f0..4d5eb60bf17 100644
--- a/chromium/content/browser/speech/input_tag_speech_dispatcher_host.h
+++ b/chromium/content/browser/speech/input_tag_speech_dispatcher_host.h
@@ -7,6 +7,7 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/speech_recognition_event_listener.h"
@@ -32,6 +33,8 @@ class CONTENT_EXPORT InputTagSpeechDispatcherHost
int render_process_id,
net::URLRequestContextGetter* url_request_context_getter);
+ base::WeakPtr<InputTagSpeechDispatcherHost> AsWeakPtr();
+
// SpeechRecognitionEventListener methods.
virtual void OnRecognitionStart(int session_id) OVERRIDE;
virtual void OnAudioStart(int session_id) OVERRIDE;
@@ -57,6 +60,8 @@ class CONTENT_EXPORT InputTagSpeechDispatcherHost
const IPC::Message& message,
BrowserThread::ID* thread) OVERRIDE;
+ virtual void OnChannelClosing() OVERRIDE;
+
private:
virtual ~InputTagSpeechDispatcherHost();
@@ -66,15 +71,20 @@ class CONTENT_EXPORT InputTagSpeechDispatcherHost
void OnStopRecording(int render_view_id, int request_id);
void StartRecognitionOnIO(
- int render_process_id,
- int guest_render_view_id,
+ int embedder_render_process_id,
+ int embedder_render_view_id,
const InputTagSpeechHostMsg_StartRecognition_Params& params,
bool filter_profanities);
- bool guest_;
+ bool is_guest_;
int render_process_id_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+ // Used for posting asynchronous tasks (on the IO thread) without worrying
+ // about this class being destroyed in the meanwhile (due to browser shutdown)
+ // since tasks pending on a destroyed WeakPtr are automatically discarded.
+ base::WeakPtrFactory<InputTagSpeechDispatcherHost> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(InputTagSpeechDispatcherHost);
};
diff --git a/chromium/content/browser/speech/speech_recognition_browsertest.cc b/chromium/content/browser/speech/speech_recognition_browsertest.cc
new file mode 100644
index 00000000000..82daf323ff3
--- /dev/null
+++ b/chromium/content/browser/speech/speech_recognition_browsertest.cc
@@ -0,0 +1,202 @@
+// 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 <list>
+
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/speech/google_streaming_remote_engine.h"
+#include "content/browser/speech/speech_recognition_manager_impl.h"
+#include "content/browser/speech/speech_recognizer_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
+#include "content/test/mock_google_streaming_server.h"
+#include "media/audio/mock_audio_manager.h"
+#include "media/audio/test_audio_input_controller_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::RunLoop;
+
+namespace content {
+
+class SpeechRecognitionBrowserTest :
+ public ContentBrowserTest,
+ public MockGoogleStreamingServer::Delegate,
+ public media::TestAudioInputControllerDelegate {
+ public:
+ enum StreamingServerState {
+ kIdle,
+ kTestAudioControllerOpened,
+ kClientConnected,
+ kClientAudioUpload,
+ kClientAudioUploadComplete,
+ kTestAudioControllerClosed,
+ kClientDisconnected
+ };
+
+ // MockGoogleStreamingServerDelegate methods.
+ virtual void OnClientConnected() OVERRIDE {
+ ASSERT_EQ(kTestAudioControllerOpened, streaming_server_state_);
+ streaming_server_state_ = kClientConnected;
+ }
+
+ virtual void OnClientAudioUpload() OVERRIDE {
+ if (streaming_server_state_ == kClientConnected)
+ streaming_server_state_ = kClientAudioUpload;
+ }
+
+ virtual void OnClientAudioUploadComplete() OVERRIDE {
+ ASSERT_EQ(kTestAudioControllerClosed, streaming_server_state_);
+ streaming_server_state_ = kClientAudioUploadComplete;
+ }
+
+ virtual void OnClientDisconnected() OVERRIDE {
+ ASSERT_EQ(kClientAudioUploadComplete, streaming_server_state_);
+ streaming_server_state_ = kClientDisconnected;
+ }
+
+ // media::TestAudioInputControllerDelegate methods.
+ virtual void TestAudioControllerOpened(
+ media::TestAudioInputController* controller) OVERRIDE {
+ ASSERT_EQ(kIdle, streaming_server_state_);
+ streaming_server_state_ = kTestAudioControllerOpened;
+ const int capture_packet_interval_ms =
+ (1000 * controller->audio_parameters().frames_per_buffer()) /
+ controller->audio_parameters().sample_rate();
+ ASSERT_EQ(GoogleStreamingRemoteEngine::kAudioPacketIntervalMs,
+ capture_packet_interval_ms);
+ FeedAudioController(500 /* ms */, /*noise=*/ false);
+ FeedAudioController(1000 /* ms */, /*noise=*/ true);
+ FeedAudioController(1000 /* ms */, /*noise=*/ false);
+ }
+
+ virtual void TestAudioControllerClosed(
+ media::TestAudioInputController* controller) OVERRIDE {
+ ASSERT_EQ(kClientAudioUpload, streaming_server_state_);
+ streaming_server_state_ = kTestAudioControllerClosed;
+ mock_streaming_server_->MockGoogleStreamingServer::SimulateResult(
+ GetGoodSpeechResult());
+ }
+
+ // Helper methods used by test fixtures.
+ GURL GetTestUrlFromFragment(const std::string fragment) {
+ return GURL(GetTestUrl("speech", "web_speech_recognition.html").spec() +
+ "#" + fragment);
+ }
+
+ std::string GetPageFragment() {
+ return shell()->web_contents()->GetURL().ref();
+ }
+
+ const StreamingServerState &streaming_server_state() {
+ return streaming_server_state_;
+ }
+
+ protected:
+ // ContentBrowserTest methods.
+ virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+ test_audio_input_controller_factory_.set_delegate(this);
+ media::AudioInputController::set_factory_for_testing(
+ &test_audio_input_controller_factory_);
+ mock_streaming_server_.reset(new MockGoogleStreamingServer(this));
+ streaming_server_state_ = kIdle;
+ }
+
+ virtual void SetUpOnMainThread() OVERRIDE {
+ ASSERT_TRUE(SpeechRecognitionManagerImpl::GetInstance());
+ SpeechRecognizerImpl::SetAudioManagerForTesting(
+ new media::MockAudioManager(BrowserThread::GetMessageLoopProxyForThread(
+ BrowserThread::IO)));
+ }
+
+ virtual void TearDownOnMainThread() OVERRIDE {
+ SpeechRecognizerImpl::SetAudioManagerForTesting(NULL);
+ }
+
+ virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
+ test_audio_input_controller_factory_.set_delegate(NULL);
+ mock_streaming_server_.reset();
+ }
+
+ private:
+ static void FeedSingleBufferToAudioController(
+ scoped_refptr<media::TestAudioInputController> controller,
+ size_t buffer_size,
+ bool fill_with_noise) {
+ DCHECK(controller.get());
+ scoped_ptr<uint8[]> audio_buffer(new uint8[buffer_size]);
+ if (fill_with_noise) {
+ for (size_t i = 0; i < buffer_size; ++i)
+ audio_buffer[i] = static_cast<uint8>(127 * sin(i * 3.14F /
+ (16 * buffer_size)));
+ } else {
+ memset(audio_buffer.get(), 0, buffer_size);
+ }
+ controller->event_handler()->OnData(controller,
+ audio_buffer.get(),
+ buffer_size);
+ }
+
+ void FeedAudioController(int duration_ms, bool feed_with_noise) {
+ media::TestAudioInputController* controller =
+ test_audio_input_controller_factory_.controller();
+ ASSERT_TRUE(controller);
+ const media::AudioParameters& audio_params = controller->audio_parameters();
+ const size_t buffer_size = audio_params.GetBytesPerBuffer();
+ const int ms_per_buffer = audio_params.frames_per_buffer() * 1000 /
+ audio_params.sample_rate();
+ // We can only simulate durations that are integer multiples of the
+ // buffer size. In this regard see
+ // SpeechRecognitionEngine::GetDesiredAudioChunkDurationMs().
+ ASSERT_EQ(0, duration_ms % ms_per_buffer);
+
+ const int n_buffers = duration_ms / ms_per_buffer;
+ for (int i = 0; i < n_buffers; ++i) {
+ base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ &FeedSingleBufferToAudioController,
+ scoped_refptr<media::TestAudioInputController>(controller),
+ buffer_size,
+ feed_with_noise));
+ }
+ }
+
+ SpeechRecognitionResult GetGoodSpeechResult() {
+ SpeechRecognitionResult result;
+ result.hypotheses.push_back(SpeechRecognitionHypothesis(
+ UTF8ToUTF16("Pictures of the moon"), 1.0F));
+ return result;
+ }
+
+ StreamingServerState streaming_server_state_;
+ scoped_ptr<MockGoogleStreamingServer> mock_streaming_server_;
+ media::TestAudioInputControllerFactory test_audio_input_controller_factory_;
+};
+
+// Simply loads the test page and checks if it was able to create a Speech
+// Recognition object in JavaScript, to make sure the Web Speech API is enabled.
+IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, Precheck) {
+ NavigateToURLBlockUntilNavigationsComplete(
+ shell(), GetTestUrlFromFragment("precheck"), 2);
+
+ EXPECT_EQ(kIdle, streaming_server_state());
+ EXPECT_EQ("success", GetPageFragment());
+}
+
+IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, OneShotRecognition) {
+ NavigateToURLBlockUntilNavigationsComplete(
+ shell(), GetTestUrlFromFragment("oneshot"), 2);
+
+ EXPECT_EQ(kClientDisconnected, streaming_server_state());
+ EXPECT_EQ("goodresult1", GetPageFragment());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
index e506675c816..5b08dd2529f 100644
--- a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
+++ b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
@@ -7,7 +7,10 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/lazy_instance.h"
+#include "content/browser/browser_plugin/browser_plugin_guest.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/speech/speech_recognition_manager_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/speech_recognition_messages.h"
#include "content/public/browser/speech_recognition_manager_delegate.h"
#include "content/public/browser/speech_recognition_session_config.h"
@@ -17,17 +20,26 @@
namespace content {
SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost(
+ bool is_guest,
int render_process_id,
net::URLRequestContextGetter* context_getter)
- : render_process_id_(render_process_id),
- context_getter_(context_getter) {
+ : is_guest_(is_guest),
+ render_process_id_(render_process_id),
+ context_getter_(context_getter),
+ weak_factory_(this) {
// Do not add any non-trivial initialization here, instead do it lazily when
// required (e.g. see the method |SpeechRecognitionManager::GetInstance()|) or
// add an Init() method.
}
SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() {
- SpeechRecognitionManager::GetInstance()->AbortAllSessionsForListener(this);
+ SpeechRecognitionManager::GetInstance()->AbortAllSessionsForRenderProcess(
+ render_process_id_);
+}
+
+base::WeakPtr<SpeechRecognitionDispatcherHost>
+SpeechRecognitionDispatcherHost::AsWeakPtr() {
+ return weak_factory_.GetWeakPtr();
}
bool SpeechRecognitionDispatcherHost::OnMessageReceived(
@@ -53,8 +65,36 @@ void SpeechRecognitionDispatcherHost::OverrideThreadForMessage(
*thread = BrowserThread::UI;
}
+void SpeechRecognitionDispatcherHost::OnChannelClosing() {
+ weak_factory_.InvalidateWeakPtrs();
+}
+
void SpeechRecognitionDispatcherHost::OnStartRequest(
const SpeechRecognitionHostMsg_StartRequest_Params& params) {
+ SpeechRecognitionHostMsg_StartRequest_Params input_params(params);
+
+ int embedder_render_process_id = 0;
+ int embedder_render_view_id = MSG_ROUTING_NONE;
+ if (is_guest_) {
+ // If the speech API request was from a guest, save the context of the
+ // embedder since we will use it to decide permission.
+ RenderViewHostImpl* render_view_host =
+ RenderViewHostImpl::FromID(render_process_id_, params.render_view_id);
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderViewHost(render_view_host));
+ BrowserPluginGuest* guest = web_contents->GetBrowserPluginGuest();
+
+ embedder_render_process_id =
+ guest->embedder_web_contents()->GetRenderProcessHost()->GetID();
+ DCHECK_NE(embedder_render_process_id, 0);
+ embedder_render_view_id =
+ guest->embedder_web_contents()->GetRenderViewHost()->GetRoutingID();
+ DCHECK_NE(embedder_render_view_id, MSG_ROUTING_NONE);
+ }
+
+ // TODO(lazyboy): Check if filter_profanities should use |render_process_id|
+ // instead of |render_process_id_|. We are also using the same value in
+ // input_tag_dispatcher_host.cc
bool filter_profanities =
SpeechRecognitionManagerImpl::GetInstance() &&
SpeechRecognitionManagerImpl::GetInstance()->delegate() &&
@@ -65,16 +105,26 @@ void SpeechRecognitionDispatcherHost::OnStartRequest(
BrowserThread::IO,
FROM_HERE,
base::Bind(&SpeechRecognitionDispatcherHost::OnStartRequestOnIO,
- this, params, filter_profanities));
+ this,
+ embedder_render_process_id,
+ embedder_render_view_id,
+ input_params,
+ filter_profanities));
}
void SpeechRecognitionDispatcherHost::OnStartRequestOnIO(
+ int embedder_render_process_id,
+ int embedder_render_view_id,
const SpeechRecognitionHostMsg_StartRequest_Params& params,
bool filter_profanities) {
SpeechRecognitionSessionContext context;
context.context_name = params.origin_url;
context.render_process_id = render_process_id_;
context.render_view_id = params.render_view_id;
+ context.embedder_render_process_id = embedder_render_process_id;
+ context.embedder_render_view_id = embedder_render_view_id;
+ if (embedder_render_process_id)
+ context.guest_render_view_id = params.render_view_id;
context.request_id = params.request_id;
context.requested_by_page_element = false;
@@ -89,7 +139,7 @@ void SpeechRecognitionDispatcherHost::OnStartRequestOnIO(
config.filter_profanities = filter_profanities;
config.continuous = params.continuous;
config.interim_results = params.interim_results;
- config.event_listener = this;
+ config.event_listener = AsWeakPtr();
int session_id = SpeechRecognitionManager::GetInstance()->CreateSession(
config);
diff --git a/chromium/content/browser/speech/speech_recognition_dispatcher_host.h b/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
index 1bc12a10580..e74447139a9 100644
--- a/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
+++ b/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_SPEECH_SPEECH_RECOGNITION_DISPATCHER_HOST_H_
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/speech_recognition_event_listener.h"
@@ -27,9 +28,12 @@ class CONTENT_EXPORT SpeechRecognitionDispatcherHost
public SpeechRecognitionEventListener {
public:
SpeechRecognitionDispatcherHost(
+ bool is_guest,
int render_process_id,
net::URLRequestContextGetter* context_getter);
+ base::WeakPtr<SpeechRecognitionDispatcherHost> AsWeakPtr();
+
// SpeechRecognitionEventListener methods.
virtual void OnRecognitionStart(int session_id) OVERRIDE;
virtual void OnAudioStart(int session_id) OVERRIDE;
@@ -55,20 +59,30 @@ class CONTENT_EXPORT SpeechRecognitionDispatcherHost
const IPC::Message& message,
BrowserThread::ID* thread) OVERRIDE;
+ virtual void OnChannelClosing() OVERRIDE;
+
private:
virtual ~SpeechRecognitionDispatcherHost();
void OnStartRequest(
const SpeechRecognitionHostMsg_StartRequest_Params& params);
void OnStartRequestOnIO(
+ int embedder_render_process_id,
+ int embedder_render_view_id,
const SpeechRecognitionHostMsg_StartRequest_Params& params,
bool filter_profanities);
void OnAbortRequest(int render_view_id, int request_id);
void OnStopCaptureRequest(int render_view_id, int request_id);
+ bool is_guest_;
int render_process_id_;
scoped_refptr<net::URLRequestContextGetter> context_getter_;
+ // Used for posting asynchronous tasks (on the IO thread) without worrying
+ // about this class being destroyed in the meanwhile (due to browser shutdown)
+ // since tasks pending on a destroyed WeakPtr are automatically discarded.
+ base::WeakPtrFactory<SpeechRecognitionDispatcherHost> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionDispatcherHost);
};
diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.cc b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
index 2c1b31735a9..c88cc9fca9f 100644
--- a/chromium/content/browser/speech/speech_recognition_manager_impl.cc
+++ b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
@@ -51,7 +51,7 @@ SpeechRecognitionManager* SpeechRecognitionManager::GetInstance() {
return SpeechRecognitionManagerImpl::GetInstance();
}
-void SpeechRecognitionManager::SetManagerForTests(
+void SpeechRecognitionManager::SetManagerForTesting(
SpeechRecognitionManager* manager) {
manager_for_tests_ = manager;
}
@@ -184,15 +184,20 @@ void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id,
if (!SessionExists(session_id))
return;
+ SessionsTable::iterator iter = sessions_.find(session_id);
+ DCHECK(iter != sessions_.end());
+ Session* session = iter->second;
+
+ if (session->abort_requested)
+ return;
+
if (ask_user) {
- SessionsTable::iterator iter = sessions_.find(session_id);
- DCHECK(iter != sessions_.end());
- SpeechRecognitionSessionContext& context = iter->second->context;
+ SpeechRecognitionSessionContext& context = session->context;
context.label = media_stream_manager_->MakeMediaAccessRequest(
context.render_process_id,
context.render_view_id,
context.request_id,
- StreamOptions(MEDIA_DEVICE_AUDIO_CAPTURE, MEDIA_NO_SERVICE),
+ StreamOptions(true, false),
GURL(context.context_name),
base::Bind(
&SpeechRecognitionManagerImpl::MediaRequestPermissionCallback,
@@ -253,6 +258,11 @@ void SpeechRecognitionManagerImpl::AbortSession(int session_id) {
SessionsTable::iterator iter = sessions_.find(session_id);
iter->second->ui.reset();
+ if (iter->second->abort_requested)
+ return;
+
+ iter->second->abort_requested = true;
+
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent,
@@ -439,8 +449,8 @@ SpeechRecognitionManagerImpl::GetSessionContext(int session_id) const {
return GetSession(session_id)->context;
}
-void SpeechRecognitionManagerImpl::AbortAllSessionsForListener(
- SpeechRecognitionEventListener* listener) {
+void SpeechRecognitionManagerImpl::AbortAllSessionsForRenderProcess(
+ int render_process_id) {
// This method gracefully destroys sessions for the listener. However, since
// the listener itself is likely to be destroyed after this call, we avoid
// dispatching further events to it, marking the |listener_is_active| flag.
@@ -448,7 +458,7 @@ void SpeechRecognitionManagerImpl::AbortAllSessionsForListener(
for (SessionsTable::iterator it = sessions_.begin(); it != sessions_.end();
++it) {
Session* session = it->second;
- if (session->config.event_listener == listener) {
+ if (session->context.render_process_id == render_process_id) {
AbortSession(session->id);
session->listener_is_active = false;
}
@@ -609,6 +619,8 @@ void SpeechRecognitionManagerImpl::SessionDelete(Session* session) {
DCHECK(session->recognizer.get() == NULL || !session->recognizer->IsActive());
if (primary_session_id_ == session->id)
primary_session_id_ = kSessionIDInvalid;
+ if (!session->context.label.empty())
+ media_stream_manager_->CancelRequest(session->context.label);
sessions_.erase(session->id);
delete session;
}
@@ -643,7 +655,9 @@ SpeechRecognitionManagerImpl::GetSession(int session_id) const {
SpeechRecognitionEventListener* SpeechRecognitionManagerImpl::GetListener(
int session_id) const {
Session* session = GetSession(session_id);
- return session->listener_is_active ? session->config.event_listener : NULL;
+ if (session->listener_is_active && session->config.event_listener)
+ return session->config.event_listener.get();
+ return NULL;
}
SpeechRecognitionEventListener*
@@ -660,7 +674,7 @@ bool SpeechRecognitionManagerImpl::HasAudioInputDevices() {
return audio_manager_->HasAudioInputDevices();
}
-string16 SpeechRecognitionManagerImpl::GetAudioInputDeviceModel() {
+base::string16 SpeechRecognitionManagerImpl::GetAudioInputDeviceModel() {
return audio_manager_->GetAudioInputDeviceModel();
}
@@ -674,6 +688,7 @@ void SpeechRecognitionManagerImpl::ShowAudioInputSettings() {
SpeechRecognitionManagerImpl::Session::Session()
: id(kSessionIDInvalid),
+ abort_requested(false),
listener_is_active(true) {
}
diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.h b/chromium/content/browser/speech/speech_recognition_manager_impl.h
index 043257024cb..9a60e077437 100644
--- a/chromium/content/browser/speech/speech_recognition_manager_impl.h
+++ b/chromium/content/browser/speech/speech_recognition_manager_impl.h
@@ -62,8 +62,7 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl :
const SpeechRecognitionSessionConfig& config) OVERRIDE;
virtual void StartSession(int session_id) OVERRIDE;
virtual void AbortSession(int session_id) OVERRIDE;
- virtual void AbortAllSessionsForListener(
- SpeechRecognitionEventListener* listener) OVERRIDE;
+ virtual void AbortAllSessionsForRenderProcess(int render_process_id) OVERRIDE;
virtual void AbortAllSessionsForRenderView(int render_process_id,
int render_view_id) OVERRIDE;
virtual void StopAudioCaptureForSession(int session_id) OVERRIDE;
@@ -75,7 +74,7 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl :
int render_view_id,
int request_id) const OVERRIDE;
virtual bool HasAudioInputDevices() OVERRIDE;
- virtual string16 GetAudioInputDeviceModel() OVERRIDE;
+ virtual base::string16 GetAudioInputDeviceModel() OVERRIDE;
virtual void ShowAudioInputSettings() OVERRIDE;
// SpeechRecognitionEventListener methods.
@@ -127,6 +126,7 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl :
~Session();
int id;
+ bool abort_requested;
bool listener_is_active;
SpeechRecognitionSessionConfig config;
SpeechRecognitionSessionContext context;
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.cc b/chromium/content/browser/speech/speech_recognizer_impl.cc
index 2dae43087eb..ecd24ab9d87 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl.cc
@@ -802,7 +802,7 @@ void SpeechRecognizerImpl::UpdateSignalAndNoiseLevels(const float& rms,
session_id(), clip_detected ? 1.0f : audio_level_, noise_level);
}
-void SpeechRecognizerImpl::SetAudioManagerForTests(
+void SpeechRecognizerImpl::SetAudioManagerForTesting(
AudioManager* audio_manager) {
audio_manager_for_tests_ = audio_manager;
}
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.h b/chromium/content/browser/speech/speech_recognizer_impl.h
index 4945132deb7..c2abb339e65 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.h
+++ b/chromium/content/browser/speech/speech_recognizer_impl.h
@@ -37,7 +37,7 @@ class CONTENT_EXPORT SpeechRecognizerImpl
static const int kNoSpeechTimeoutMs;
static const int kEndpointerEstimationTimeMs;
- static void SetAudioManagerForTests(media::AudioManager* audio_manager);
+ static void SetAudioManagerForTesting(media::AudioManager* audio_manager);
SpeechRecognizerImpl(SpeechRecognitionEventListener* listener,
int session_id,
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_android.cc b/chromium/content/browser/speech/speech_recognizer_impl_android.cc
index eb3f7934b7e..2e8c57e87b2 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_android.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_android.cc
@@ -55,7 +55,7 @@ void SpeechRecognizerImplAndroid::StartRecognitionOnUIThread(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
JNIEnv* env = AttachCurrentThread();
j_recognition_.Reset(Java_SpeechRecognition_createSpeechRecognition(env,
- GetApplicationContext(), reinterpret_cast<jint>(this)));
+ GetApplicationContext(), reinterpret_cast<intptr_t>(this)));
Java_SpeechRecognition_startRecognition(env, j_recognition_.obj(),
ConvertUTF8ToJavaString(env, language).obj(), continuous,
interim_results);
@@ -146,7 +146,7 @@ void SpeechRecognizerImplAndroid::OnAudioEnd(JNIEnv* env, jobject obj) {
void SpeechRecognizerImplAndroid::OnRecognitionResults(JNIEnv* env, jobject obj,
jobjectArray strings, jfloatArray floats, jboolean provisional) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- std::vector<string16> options;
+ std::vector<base::string16> options;
AppendJavaStringArrayToStringVector(env, strings, &options);
std::vector<float> scores(options.size(), 0.0);
if (floats != NULL)
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
index dcd4d5be538..54d970906da 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -59,7 +59,7 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
this, kTestingSessionId, kOneShotMode, sr_engine);
audio_manager_.reset(new media::MockAudioManager(
base::MessageLoop::current()->message_loop_proxy().get()));
- recognizer_->SetAudioManagerForTests(audio_manager_.get());
+ recognizer_->SetAudioManagerForTesting(audio_manager_.get());
int audio_packet_length_bytes =
(SpeechRecognizerImpl::kAudioSampleRate *
diff --git a/chromium/content/browser/ssl/ssl_client_auth_handler.cc b/chromium/content/browser/ssl/ssl_client_auth_handler.cc
index 3340334f183..60d57d40c6e 100644
--- a/chromium/content/browser/ssl/ssl_client_auth_handler.cc
+++ b/chromium/content/browser/ssl/ssl_client_auth_handler.cc
@@ -11,18 +11,21 @@
#include "content/public/browser/content_browser_client.h"
#include "net/cert/x509_certificate.h"
#include "net/http/http_transaction_factory.h"
+#include "net/ssl/client_cert_store.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
namespace content {
SSLClientAuthHandler::SSLClientAuthHandler(
+ scoped_ptr<net::ClientCertStore> client_cert_store,
net::URLRequest* request,
net::SSLCertRequestInfo* cert_request_info)
: request_(request),
http_network_session_(
request_->context()->http_transaction_factory()->GetSession()),
- cert_request_info_(cert_request_info) {
+ cert_request_info_(cert_request_info),
+ client_cert_store_(client_cert_store.Pass()) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
@@ -39,6 +42,43 @@ void SSLClientAuthHandler::SelectCertificate() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(request_);
+ if (client_cert_store_) {
+ client_cert_store_->GetClientCerts(
+ *cert_request_info_,
+ &cert_request_info_->client_certs,
+ base::Bind(&SSLClientAuthHandler::DidGetClientCerts, this));
+ } else {
+ DidGetClientCerts();
+ }
+}
+
+void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ VLOG(1) << this << " CertificateSelected " << cert;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(
+ &SSLClientAuthHandler::DoCertificateSelected, this,
+ make_scoped_refptr(cert)));
+}
+
+void SSLClientAuthHandler::DidGetClientCerts() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Request may have cancelled while we were getting client certs.
+ if (!request_)
+ return;
+
+ // Note that if |client_cert_store_| is NULL, we intentionally fall through to
+ // DoCertificateSelected. This is for platforms where the client cert matching
+ // is not performed by Chrome, the platform can handle the cert matching
+ // before showing the dialog.
+ if (client_cert_store_ && cert_request_info_->client_certs.empty()) {
+ // No need to query the user if there are no certs to choose from.
+ DoCertificateSelected(NULL);
+ return;
+ }
+
int render_process_host_id;
int render_view_host_id;
if (!ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderView(
@@ -57,17 +97,6 @@ void SSLClientAuthHandler::SelectCertificate() {
render_process_host_id, render_view_host_id));
}
-void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- VLOG(1) << this << " CertificateSelected " << cert;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(
- &SSLClientAuthHandler::DoCertificateSelected, this,
- make_scoped_refptr(cert)));
-}
-
void SSLClientAuthHandler::DoCertificateSelected(net::X509Certificate* cert) {
VLOG(1) << this << " DoCertificateSelected " << cert;
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
diff --git a/chromium/content/browser/ssl/ssl_client_auth_handler.h b/chromium/content/browser/ssl/ssl_client_auth_handler.h
index 9bd82756525..bbc77470f66 100644
--- a/chromium/content/browser/ssl/ssl_client_auth_handler.h
+++ b/chromium/content/browser/ssl/ssl_client_auth_handler.h
@@ -13,6 +13,7 @@
#include "net/ssl/ssl_cert_request_info.h"
namespace net {
+class ClientCertStore;
class HttpNetworkSession;
class URLRequest;
class X509Certificate;
@@ -20,6 +21,8 @@ class X509Certificate;
namespace content {
+class ResourceContext;
+
// This class handles the approval and selection of a certificate for SSL client
// authentication by the user.
// It is self-owned and deletes itself when the UI reports the user selection or
@@ -28,7 +31,8 @@ class CONTENT_EXPORT SSLClientAuthHandler
: public base::RefCountedThreadSafe<
SSLClientAuthHandler, BrowserThread::DeleteOnIOThread> {
public:
- SSLClientAuthHandler(net::URLRequest* request,
+ SSLClientAuthHandler(scoped_ptr<net::ClientCertStore> client_cert_store,
+ net::URLRequest* request,
net::SSLCertRequestInfo* cert_request_info);
// Selects a certificate and resumes the URL request with that certificate.
@@ -53,6 +57,9 @@ class CONTENT_EXPORT SSLClientAuthHandler
friend class BrowserThread;
friend class base::DeleteHelper<SSLClientAuthHandler>;
+ // Called when ClientCertStore is done retrieving the cert list.
+ void DidGetClientCerts();
+
// Notifies that the user has selected a cert.
// Called on the IO thread.
void DoCertificateSelected(net::X509Certificate* cert);
@@ -70,6 +77,8 @@ class CONTENT_EXPORT SSLClientAuthHandler
// The certs to choose from.
scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
+ scoped_ptr<net::ClientCertStore> client_cert_store_;
+
DISALLOW_COPY_AND_ASSIGN(SSLClientAuthHandler);
};
diff --git a/chromium/content/browser/ssl/ssl_error_handler.cc b/chromium/content/browser/ssl/ssl_error_handler.cc
index 85cb3a4beda..8a322f7570d 100644
--- a/chromium/content/browser/ssl/ssl_error_handler.cc
+++ b/chromium/content/browser/ssl/ssl_error_handler.cc
@@ -5,9 +5,9 @@
#include "content/browser/ssl/ssl_error_handler.h"
#include "base/bind.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/ssl/ssl_cert_error_handler.h"
-#include "content/browser/web_contents/navigation_controller_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
diff --git a/chromium/content/browser/ssl/ssl_manager.cc b/chromium/content/browser/ssl/ssl_manager.cc
index 42ee02fbb1c..b1eb51e3207 100644
--- a/chromium/content/browser/ssl/ssl_manager.cc
+++ b/chromium/content/browser/ssl/ssl_manager.cc
@@ -9,12 +9,12 @@
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "base/supports_user_data.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/ssl/ssl_cert_error_handler.h"
#include "content/browser/ssl/ssl_policy.h"
#include "content/browser/ssl/ssl_request_info.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/ssl_status_serialization.h"
#include "content/public/browser/browser_context.h"
@@ -87,7 +87,7 @@ void SSLManager::NotifySSLInternalStateChanged(BrowserContext* context) {
for (std::set<SSLManager*>::iterator i = managers->get().begin();
i != managers->get().end(); ++i) {
(*i)->UpdateEntry(NavigationEntryImpl::FromNavigationEntry(
- (*i)->controller()->GetActiveEntry()));
+ (*i)->controller()->GetLastCommittedEntry()));
}
}
@@ -114,7 +114,8 @@ SSLManager::~SSLManager() {
void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) {
NavigationEntryImpl* entry =
- NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry());
+ NavigationEntryImpl::FromNavigationEntry(
+ controller_->GetLastCommittedEntry());
if (details.is_main_frame) {
if (entry) {
@@ -123,11 +124,14 @@ void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) {
net::CertStatus ssl_cert_status;
int ssl_security_bits;
int ssl_connection_status;
+ SignedCertificateTimestampIDStatusList
+ ssl_signed_certificate_timestamp_ids;
DeserializeSecurityInfo(details.serialized_security_info,
&ssl_cert_id,
&ssl_cert_status,
&ssl_security_bits,
- &ssl_connection_status);
+ &ssl_connection_status,
+ &ssl_signed_certificate_timestamp_ids);
// We may not have an entry if this is a navigation to an initial blank
// page. Reset the SSL information and add the new data we have.
@@ -136,6 +140,8 @@ void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) {
entry->GetSSL().cert_status = ssl_cert_status;
entry->GetSSL().security_bits = ssl_security_bits;
entry->GetSSL().connection_status = ssl_connection_status;
+ entry->GetSSL().signed_certificate_timestamp_ids =
+ ssl_signed_certificate_timestamp_ids;
}
}
@@ -144,12 +150,14 @@ void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) {
void SSLManager::DidDisplayInsecureContent() {
UpdateEntry(
- NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry()));
+ NavigationEntryImpl::FromNavigationEntry(
+ controller_->GetLastCommittedEntry()));
}
void SSLManager::DidRunInsecureContent(const std::string& security_origin) {
NavigationEntryImpl* navigation_entry =
- NavigationEntryImpl::FromNavigationEntry(controller_->GetActiveEntry());
+ NavigationEntryImpl::FromNavigationEntry(
+ controller_->GetLastCommittedEntry());
policy()->DidRunInsecureContent(navigation_entry, security_origin);
UpdateEntry(navigation_entry);
}
@@ -204,10 +212,12 @@ void SSLManager::UpdateEntry(NavigationEntryImpl* entry) {
SSLStatus original_ssl_status = entry->GetSSL(); // Copy!
- policy()->UpdateEntry(entry, controller_->web_contents());
+ WebContentsImpl* contents =
+ static_cast<WebContentsImpl*>(controller_->delegate()->GetWebContents());
+ policy()->UpdateEntry(entry, contents);
if (!entry->GetSSL().Equals(original_ssl_status))
- controller_->web_contents()->DidChangeVisibleSSLState();
+ contents->DidChangeVisibleSSLState();
}
} // namespace content
diff --git a/chromium/content/browser/ssl/ssl_policy.cc b/chromium/content/browser/ssl/ssl_policy.cc
index 02af3983bf8..ddf9e4cd3a5 100644
--- a/chromium/content/browser/ssl/ssl_policy.cc
+++ b/chromium/content/browser/ssl/ssl_policy.cc
@@ -10,12 +10,12 @@
#include "base/memory/singleton.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/ssl/ssl_cert_error_handler.h"
#include "content/browser/ssl/ssl_request_info.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/ssl_status.h"
@@ -53,6 +53,7 @@ void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) {
case net::ERR_CERT_AUTHORITY_INVALID:
case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
case net::ERR_CERT_WEAK_KEY:
+ case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION:
OnCertErrorInternal(handler, !handler->fatal(), handler->fatal());
break;
case net::ERR_CERT_NO_REVOCATION_MECHANISM:
@@ -67,6 +68,8 @@ void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) {
case net::ERR_CERT_CONTAINS_ERRORS:
case net::ERR_CERT_REVOKED:
case net::ERR_CERT_INVALID:
+ case net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY:
+ case net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN:
OnCertErrorInternal(handler, false, handler->fatal());
break;
default:
diff --git a/chromium/content/browser/ssl/ssl_policy_backend.cc b/chromium/content/browser/ssl/ssl_policy_backend.cc
index 57e05702c88..3eb4f467e70 100644
--- a/chromium/content/browser/ssl/ssl_policy_backend.cc
+++ b/chromium/content/browser/ssl/ssl_policy_backend.cc
@@ -4,8 +4,8 @@
#include "content/browser/ssl/ssl_policy_backend.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/ssl/ssl_host_state.h"
-#include "content/browser/web_contents/navigation_controller_impl.h"
#include "content/public/browser/browser_context.h"
namespace content {
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index e984e617343..83e9e96df43 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -28,21 +28,6 @@ namespace content {
namespace {
-int GenerateQuotaClientMask(uint32 remove_mask) {
- int quota_client_mask = 0;
-
- if (remove_mask & StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS)
- quota_client_mask |= quota::QuotaClient::kFileSystem;
- if (remove_mask & StoragePartition::REMOVE_DATA_MASK_WEBSQL)
- quota_client_mask |= quota::QuotaClient::kDatabase;
- if (remove_mask & StoragePartition::REMOVE_DATA_MASK_APPCACHE)
- quota_client_mask |= quota::QuotaClient::kAppcache;
- if (remove_mask & StoragePartition::REMOVE_DATA_MASK_INDEXEDDB)
- quota_client_mask |= quota::QuotaClient::kIndexedDatabase;
-
- return quota_client_mask;
-}
-
void OnClearedCookies(const base::Closure& callback, int num_deleted) {
// The final callback needs to happen from UI thread.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
@@ -77,51 +62,29 @@ void ClearCookiesOnIOThread(
}
}
+void CheckQuotaManagedDataDeletionStatus(size_t* deletion_task_count,
+ const base::Closure& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (*deletion_task_count == 0) {
+ delete deletion_task_count;
+ callback.Run();
+ }
+}
+
void OnQuotaManagedOriginDeleted(const GURL& origin,
quota::StorageType type,
- size_t* origins_to_delete_count,
+ size_t* deletion_task_count,
const base::Closure& callback,
quota::QuotaStatusCode status) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK_GT(*origins_to_delete_count, 0u);
+ DCHECK_GT(*deletion_task_count, 0u);
if (status != quota::kQuotaStatusOk) {
DLOG(ERROR) << "Couldn't remove data of type " << type << " for origin "
<< origin << ". Status: " << status;
}
- (*origins_to_delete_count)--;
- if (*origins_to_delete_count == 0) {
- delete origins_to_delete_count;
- callback.Run();
- }
-}
-
-void ClearQuotaManagedOriginsOnIOThread(quota::QuotaManager* quota_manager,
- uint32 remove_mask,
- const base::Closure& callback,
- const std::set<GURL>& origins,
- quota::StorageType quota_storage_type) {
- // The QuotaManager manages all storage other than cookies, LocalStorage,
- // and SessionStorage. This loop wipes out most HTML5 storage for the given
- // origins.
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- if (!origins.size()) {
- // No origins to clear.
- callback.Run();
- return;
- }
-
- size_t* origins_to_delete_count = new size_t(origins.size());
- for (std::set<GURL>::const_iterator origin = origins.begin();
- origin != origins.end(); ++origin) {
- quota_manager->DeleteOriginData(
- *origin, quota_storage_type,
- GenerateQuotaClientMask(remove_mask),
- base::Bind(&OnQuotaManagedOriginDeleted,
- origin->GetOrigin(), quota_storage_type,
- origins_to_delete_count, callback));
- }
+ (*deletion_task_count)--;
+ CheckQuotaManagedDataDeletionStatus(deletion_task_count, callback);
}
void ClearedShaderCache(const base::Closure& callback) {
@@ -145,6 +108,8 @@ void ClearShaderCacheOnIOThread(const base::FilePath& path,
void OnLocalStorageUsageInfo(
const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
+ const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const StoragePartition::OriginMatcherFunction& origin_matcher,
const base::Time delete_begin,
const base::Time delete_end,
const base::Closure& callback,
@@ -152,6 +117,11 @@ void OnLocalStorageUsageInfo(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
for (size_t i = 0; i < infos.size(); ++i) {
+ if (!origin_matcher.is_null() &&
+ !origin_matcher.Run(infos[i].origin, special_storage_policy.get())) {
+ continue;
+ }
+
if (infos[i].last_modified >= delete_begin &&
infos[i].last_modified <= delete_end) {
dom_storage_context->DeleteLocalStorage(infos[i].origin);
@@ -162,18 +132,27 @@ void OnLocalStorageUsageInfo(
void OnSessionStorageUsageInfo(
const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
+ const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const StoragePartition::OriginMatcherFunction& origin_matcher,
const base::Closure& callback,
const std::vector<SessionStorageUsageInfo>& infos) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- for (size_t i = 0; i < infos.size(); ++i)
+ for (size_t i = 0; i < infos.size(); ++i) {
+ if (!origin_matcher.is_null() &&
+ !origin_matcher.Run(infos[i].origin, special_storage_policy.get())) {
+ continue;
+ }
dom_storage_context->DeleteSessionStorage(infos[i]);
+ }
callback.Run();
}
void ClearLocalStorageOnUIThread(
const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
+ const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const StoragePartition::OriginMatcherFunction& origin_matcher,
const GURL& remove_origin,
const base::Time begin,
const base::Time end,
@@ -181,33 +160,66 @@ void ClearLocalStorageOnUIThread(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!remove_origin.is_empty()) {
- dom_storage_context->DeleteLocalStorage(remove_origin);
+ bool can_delete = origin_matcher.is_null() ||
+ origin_matcher.Run(remove_origin,
+ special_storage_policy.get());
+ if (can_delete)
+ dom_storage_context->DeleteLocalStorage(remove_origin);
+
callback.Run();
return;
}
dom_storage_context->GetLocalStorageUsage(
base::Bind(&OnLocalStorageUsageInfo,
- dom_storage_context, begin, end, callback));
+ dom_storage_context, special_storage_policy, origin_matcher,
+ begin, end, callback));
}
void ClearSessionStorageOnUIThread(
const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
+ const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const StoragePartition::OriginMatcherFunction& origin_matcher,
const base::Closure& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
dom_storage_context->GetSessionStorageUsage(
- base::Bind(&OnSessionStorageUsageInfo, dom_storage_context, callback));
+ base::Bind(&OnSessionStorageUsageInfo, dom_storage_context,
+ special_storage_policy, origin_matcher,
+ callback));
}
} // namespace
+// Static.
+int StoragePartitionImpl::GenerateQuotaClientMask(uint32 remove_mask) {
+ int quota_client_mask = 0;
+
+ if (remove_mask & StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS)
+ quota_client_mask |= quota::QuotaClient::kFileSystem;
+ if (remove_mask & StoragePartition::REMOVE_DATA_MASK_WEBSQL)
+ quota_client_mask |= quota::QuotaClient::kDatabase;
+ if (remove_mask & StoragePartition::REMOVE_DATA_MASK_APPCACHE)
+ quota_client_mask |= quota::QuotaClient::kAppcache;
+ if (remove_mask & StoragePartition::REMOVE_DATA_MASK_INDEXEDDB)
+ quota_client_mask |= quota::QuotaClient::kIndexedDatabase;
+
+ return quota_client_mask;
+}
+
// Helper for deleting quota managed data from a partition.
//
// Most of the operations in this class are done on IO thread.
struct StoragePartitionImpl::QuotaManagedDataDeletionHelper {
- QuotaManagedDataDeletionHelper(const base::Closure& callback)
- : callback(callback), task_count(0) {
+ QuotaManagedDataDeletionHelper(uint32 remove_mask,
+ uint32 quota_storage_remove_mask,
+ const GURL& remove_origin,
+ const base::Closure& callback)
+ : remove_mask(remove_mask),
+ quota_storage_remove_mask(quota_storage_remove_mask),
+ remove_origin(remove_origin),
+ callback(callback),
+ task_count(0) {
}
void IncrementTaskCountOnIO();
@@ -216,13 +228,22 @@ struct StoragePartitionImpl::QuotaManagedDataDeletionHelper {
void ClearDataOnIOThread(
const scoped_refptr<quota::QuotaManager>& quota_manager,
const base::Time begin,
- uint32 remove_mask,
- uint32 quota_storage_remove_mask,
- const GURL& remove_origin);
-
- // Accessed on IO thread.
+ const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const StoragePartition::OriginMatcherFunction& origin_matcher);
+
+ void ClearOriginsOnIOThread(
+ quota::QuotaManager* quota_manager,
+ const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const StoragePartition::OriginMatcherFunction& origin_matcher,
+ const base::Closure& callback,
+ const std::set<GURL>& origins,
+ quota::StorageType quota_storage_type);
+
+ // All of these data are accessed on IO thread.
+ uint32 remove_mask;
+ uint32 quota_storage_remove_mask;
+ GURL remove_origin;
const base::Closure callback;
- // Accessed on IO thread.
int task_count;
};
@@ -237,43 +258,63 @@ struct StoragePartitionImpl::QuotaManagedDataDeletionHelper {
// forwarded and updated on each (sub) deletion's callback. The instance is
// finally destroyed when deletion completes (and |callback| is invoked).
struct StoragePartitionImpl::DataDeletionHelper {
- DataDeletionHelper(const base::Closure& callback)
- : callback(callback), task_count(0) {
+ DataDeletionHelper(uint32 remove_mask,
+ uint32 quota_storage_remove_mask,
+ const base::Closure& callback)
+ : remove_mask(remove_mask),
+ quota_storage_remove_mask(quota_storage_remove_mask),
+ callback(callback),
+ task_count(0) {
}
void IncrementTaskCountOnUI();
void DecrementTaskCountOnUI();
- void ClearDataOnUIThread(uint32 remove_mask,
- uint32 quota_storage_remove_mask,
- const GURL& remove_origin,
+ void ClearDataOnUIThread(const GURL* remove_origin,
+ const OriginMatcherFunction& origin_matcher,
const base::FilePath& path,
net::URLRequestContextGetter* rq_context,
DOMStorageContextWrapper* dom_storage_context,
quota::QuotaManager* quota_manager,
+ quota::SpecialStoragePolicy* special_storage_policy,
WebRTCIdentityStore* webrtc_identity_store,
const base::Time begin,
const base::Time end);
+ void ClearQuotaManagedDataOnIOThread(
+ const scoped_refptr<quota::QuotaManager>& quota_manager,
+ const base::Time begin,
+ const GURL& remove_origin,
+ const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const StoragePartition::OriginMatcherFunction& origin_matcher,
+ const base::Closure& callback);
+
+ uint32 remove_mask;
+ uint32 quota_storage_remove_mask;
+
// Accessed on UI thread.
const base::Closure callback;
// Accessed on UI thread.
int task_count;
};
-void ClearQuotaManagedDataOnIOThread(
+void StoragePartitionImpl::DataDeletionHelper::ClearQuotaManagedDataOnIOThread(
const scoped_refptr<quota::QuotaManager>& quota_manager,
const base::Time begin,
- uint32 remove_mask,
- uint32 quota_storage_remove_mask,
const GURL& remove_origin,
+ const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const StoragePartition::OriginMatcherFunction& origin_matcher,
const base::Closure& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
StoragePartitionImpl::QuotaManagedDataDeletionHelper* helper =
- new StoragePartitionImpl::QuotaManagedDataDeletionHelper(callback);
- helper->ClearDataOnIOThread(quota_manager, begin,
- remove_mask, quota_storage_remove_mask, remove_origin);
+ new StoragePartitionImpl::QuotaManagedDataDeletionHelper(
+ remove_mask,
+ quota_storage_remove_mask,
+ remove_origin,
+ callback);
+ helper->ClearDataOnIOThread(quota_manager, begin, special_storage_policy,
+ origin_matcher);
}
StoragePartitionImpl::StoragePartitionImpl(
@@ -284,8 +325,9 @@ StoragePartitionImpl::StoragePartitionImpl(
webkit_database::DatabaseTracker* database_tracker,
DOMStorageContextWrapper* dom_storage_context,
IndexedDBContextImpl* indexed_db_context,
- ServiceWorkerContext* service_worker_context,
- WebRTCIdentityStore* webrtc_identity_store)
+ ServiceWorkerContextWrapper* service_worker_context,
+ WebRTCIdentityStore* webrtc_identity_store,
+ quota::SpecialStoragePolicy* special_storage_policy)
: partition_path_(partition_path),
quota_manager_(quota_manager),
appcache_service_(appcache_service),
@@ -294,7 +336,8 @@ StoragePartitionImpl::StoragePartitionImpl(
dom_storage_context_(dom_storage_context),
indexed_db_context_(indexed_db_context),
service_worker_context_(service_worker_context),
- webrtc_identity_store_(webrtc_identity_store) {}
+ webrtc_identity_store_(webrtc_identity_store),
+ special_storage_policy_(special_storage_policy) {}
StoragePartitionImpl::~StoragePartitionImpl() {
// These message loop checks are just to avoid leaks in unittests.
@@ -311,6 +354,9 @@ StoragePartitionImpl::~StoragePartitionImpl() {
if (GetDOMStorageContext())
GetDOMStorageContext()->Shutdown();
+
+ if (GetServiceWorkerContext())
+ GetServiceWorkerContext()->Shutdown();
}
// TODO(ajwong): Break the direct dependency on |context|. We only
@@ -369,8 +415,9 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
quota_manager->proxy(),
idb_task_runner);
- scoped_refptr<ServiceWorkerContext> service_worker_context =
- new ServiceWorkerContext(path, quota_manager->proxy());
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
+ new ServiceWorkerContextWrapper();
+ service_worker_context->Init(path, quota_manager->proxy());
scoped_refptr<ChromeAppCacheService> appcache_service =
new ChromeAppCacheService(quota_manager->proxy());
@@ -378,6 +425,9 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
scoped_refptr<WebRTCIdentityStore> webrtc_identity_store(
new WebRTCIdentityStore(path, context->GetSpecialStoragePolicy()));
+ scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy(
+ context->GetSpecialStoragePolicy());
+
return new StoragePartitionImpl(partition_path,
quota_manager.get(),
appcache_service.get(),
@@ -386,7 +436,8 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
dom_storage_context.get(),
indexed_db_context.get(),
service_worker_context.get(),
- webrtc_identity_store.get());
+ webrtc_identity_store.get(),
+ special_storage_policy.get());
}
base::FilePath StoragePartitionImpl::GetPath() {
@@ -426,26 +477,29 @@ IndexedDBContextImpl* StoragePartitionImpl::GetIndexedDBContext() {
return indexed_db_context_.get();
}
-ServiceWorkerContext* StoragePartitionImpl::GetServiceWorkerContext() {
+ServiceWorkerContextWrapper* StoragePartitionImpl::GetServiceWorkerContext() {
return service_worker_context_.get();
}
void StoragePartitionImpl::ClearDataImpl(
uint32 remove_mask,
uint32 quota_storage_remove_mask,
- const GURL& remove_origin,
+ const GURL* remove_origin,
+ const OriginMatcherFunction& origin_matcher,
net::URLRequestContextGetter* rq_context,
const base::Time begin,
const base::Time end,
const base::Closure& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DataDeletionHelper* helper = new DataDeletionHelper(callback);
+ DataDeletionHelper* helper = new DataDeletionHelper(remove_mask,
+ quota_storage_remove_mask,
+ callback);
// |helper| deletes itself when done in
// DataDeletionHelper::DecrementTaskCountOnUI().
- helper->ClearDataOnUIThread(
- remove_mask, quota_storage_remove_mask, remove_origin,
- GetPath(), rq_context, dom_storage_context_, quota_manager_,
- webrtc_identity_store_, begin, end);
+ helper->ClearDataOnUIThread(remove_origin, origin_matcher, GetPath(),
+ rq_context, dom_storage_context_, quota_manager_,
+ special_storage_policy_.get(),
+ webrtc_identity_store_, begin, end);
}
void StoragePartitionImpl::
@@ -469,13 +523,8 @@ void StoragePartitionImpl::
void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread(
const scoped_refptr<quota::QuotaManager>& quota_manager,
const base::Time begin,
- uint32 remove_mask,
- uint32 quota_storage_remove_mask,
- const GURL& remove_origin) {
- std::set<GURL> origins;
- if (!remove_origin.is_empty())
- origins.insert(remove_origin);
-
+ const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const StoragePartition::OriginMatcherFunction& origin_matcher) {
IncrementTaskCountOnIO();
base::Closure decrement_callback = base::Bind(
&QuotaManagedDataDeletionHelper::DecrementTaskCountOnIO,
@@ -483,54 +532,92 @@ void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread(
if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_PERSISTENT) {
IncrementTaskCountOnIO();
- if (origins.empty()) { // Remove for all origins.
- // Ask the QuotaManager for all origins with temporary quota modified
- // within the user-specified timeframe, and deal with the resulting set in
- // ClearQuotaManagedOriginsOnIOThread().
- quota_manager->GetOriginsModifiedSince(
- quota::kStorageTypePersistent, begin,
- base::Bind(&ClearQuotaManagedOriginsOnIOThread,
- quota_manager, remove_mask, decrement_callback));
- } else {
- ClearQuotaManagedOriginsOnIOThread(
- quota_manager, remove_mask, decrement_callback,
- origins, quota::kStorageTypePersistent);
- }
+ // Ask the QuotaManager for all origins with persistent quota modified
+ // within the user-specified timeframe, and deal with the resulting set in
+ // ClearQuotaManagedOriginsOnIOThread().
+ quota_manager->GetOriginsModifiedSince(
+ quota::kStorageTypePersistent, begin,
+ base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread,
+ base::Unretained(this),
+ quota_manager,
+ special_storage_policy,
+ origin_matcher,
+ decrement_callback));
}
// Do the same for temporary quota.
if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_TEMPORARY) {
IncrementTaskCountOnIO();
- if (origins.empty()) { // Remove for all origins.
- quota_manager->GetOriginsModifiedSince(
- quota::kStorageTypeTemporary, begin,
- base::Bind(&ClearQuotaManagedOriginsOnIOThread,
- quota_manager, remove_mask, decrement_callback));
- } else {
- ClearQuotaManagedOriginsOnIOThread(
- quota_manager, remove_mask, decrement_callback,
- origins, quota::kStorageTypeTemporary);
- }
+ quota_manager->GetOriginsModifiedSince(
+ quota::kStorageTypeTemporary, begin,
+ base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread,
+ base::Unretained(this),
+ quota_manager,
+ special_storage_policy,
+ origin_matcher,
+ decrement_callback));
}
// Do the same for syncable quota.
if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_SYNCABLE) {
IncrementTaskCountOnIO();
- if (origins.empty()) { // Remove for all origins.
- quota_manager->GetOriginsModifiedSince(
- quota::kStorageTypeSyncable, begin,
- base::Bind(&ClearQuotaManagedOriginsOnIOThread,
- quota_manager, remove_mask, decrement_callback));
- } else {
- ClearQuotaManagedOriginsOnIOThread(
- quota_manager, remove_mask, decrement_callback,
- origins, quota::kStorageTypeSyncable);
- }
+ quota_manager->GetOriginsModifiedSince(
+ quota::kStorageTypeSyncable, begin,
+ base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread,
+ base::Unretained(this),
+ quota_manager,
+ special_storage_policy,
+ origin_matcher,
+ decrement_callback));
}
DecrementTaskCountOnIO();
}
+void StoragePartitionImpl::
+ QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread(
+ quota::QuotaManager* quota_manager,
+ const scoped_refptr<quota::SpecialStoragePolicy>&
+ special_storage_policy,
+ const StoragePartition::OriginMatcherFunction& origin_matcher,
+ const base::Closure& callback,
+ const std::set<GURL>& origins,
+ quota::StorageType quota_storage_type) {
+ // The QuotaManager manages all storage other than cookies, LocalStorage,
+ // and SessionStorage. This loop wipes out most HTML5 storage for the given
+ // origins.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!origins.size()) {
+ callback.Run();
+ return;
+ }
+
+ size_t* deletion_task_count = new size_t(0u);
+ (*deletion_task_count)++;
+ for (std::set<GURL>::const_iterator origin = origins.begin();
+ origin != origins.end(); ++origin) {
+ // TODO(mkwst): Clean this up, it's slow. http://crbug.com/130746
+ if (!remove_origin.is_empty() && origin->GetOrigin() != remove_origin)
+ continue;
+
+ if (!origin_matcher.is_null() &&
+ !origin_matcher.Run(*origin, special_storage_policy.get())) {
+ continue;
+ }
+
+ (*deletion_task_count)++;
+ quota_manager->DeleteOriginData(
+ *origin, quota_storage_type,
+ StoragePartitionImpl::GenerateQuotaClientMask(remove_mask),
+ base::Bind(&OnQuotaManagedOriginDeleted,
+ origin->GetOrigin(), quota_storage_type,
+ deletion_task_count, callback));
+ }
+ (*deletion_task_count)--;
+
+ CheckQuotaManagedDataDeletionStatus(deletion_task_count, callback);
+}
+
void StoragePartitionImpl::DataDeletionHelper::IncrementTaskCountOnUI() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
++task_count;
@@ -553,13 +640,13 @@ void StoragePartitionImpl::DataDeletionHelper::DecrementTaskCountOnUI() {
}
void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
- uint32 remove_mask,
- uint32 quota_storage_remove_mask,
- const GURL& remove_origin,
+ const GURL* remove_origin,
+ const OriginMatcherFunction& origin_matcher,
const base::FilePath& path,
net::URLRequestContextGetter* rq_context,
DOMStorageContextWrapper* dom_storage_context,
quota::QuotaManager* quota_manager,
+ quota::SpecialStoragePolicy* special_storage_policy,
WebRTCIdentityStore* webrtc_identity_store,
const base::Time begin,
const base::Time end) {
@@ -570,13 +657,14 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
base::Closure decrement_callback = base::Bind(
&DataDeletionHelper::DecrementTaskCountOnUI, base::Unretained(this));
+ GURL origin = remove_origin ? *remove_origin : GURL();
if (remove_mask & REMOVE_DATA_MASK_COOKIES) {
// Handle the cookies.
IncrementTaskCountOnUI();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&ClearCookiesOnIOThread,
- make_scoped_refptr(rq_context), begin, end, remove_origin,
+ make_scoped_refptr(rq_context), begin, end, origin,
decrement_callback));
}
@@ -587,9 +675,13 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
IncrementTaskCountOnUI();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ClearQuotaManagedDataOnIOThread,
- make_scoped_refptr(quota_manager), begin,
- remove_mask, quota_storage_remove_mask, remove_origin,
+ base::Bind(&DataDeletionHelper::ClearQuotaManagedDataOnIOThread,
+ base::Unretained(this),
+ make_scoped_refptr(quota_manager),
+ begin,
+ origin,
+ make_scoped_refptr(special_storage_policy),
+ origin_matcher,
decrement_callback));
}
@@ -597,15 +689,21 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
IncrementTaskCountOnUI();
ClearLocalStorageOnUIThread(
make_scoped_refptr(dom_storage_context),
- remove_origin, begin, end, decrement_callback);
+ make_scoped_refptr(special_storage_policy),
+ origin_matcher,
+ origin, begin, end,
+ decrement_callback);
// ClearDataImpl cannot clear session storage data when a particular origin
// is specified. Therefore we ignore clearing session storage in this case.
// TODO(lazyboy): Fix.
- if (remove_origin.is_empty()) {
+ if (origin.is_empty()) {
IncrementTaskCountOnUI();
ClearSessionStorageOnUIThread(
- make_scoped_refptr(dom_storage_context), decrement_callback);
+ make_scoped_refptr(dom_storage_context),
+ make_scoped_refptr(special_storage_policy),
+ origin_matcher,
+ decrement_callback);
}
}
@@ -639,32 +737,37 @@ void StoragePartitionImpl::ClearDataForOrigin(
const GURL& storage_origin,
net::URLRequestContextGetter* request_context_getter) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_origin,
- request_context_getter, base::Time(), base::Time::Max(),
- base::Bind(&base::DoNothing));
+ ClearDataImpl(remove_mask, quota_storage_remove_mask, &storage_origin,
+ OriginMatcherFunction(), request_context_getter,
+ base::Time(), base::Time::Max(), base::Bind(&base::DoNothing));
}
-void StoragePartitionImpl::ClearDataForUnboundedRange(
+void StoragePartitionImpl::ClearData(
uint32 remove_mask,
- uint32 quota_storage_remove_mask) {
- ClearDataImpl(remove_mask, quota_storage_remove_mask, GURL(),
- GetURLRequestContext(), base::Time(), base::Time::Max(),
- base::Bind(&base::DoNothing));
-}
-
-void StoragePartitionImpl::ClearDataForRange(uint32 remove_mask,
- uint32 quota_storage_remove_mask,
- const base::Time& begin,
- const base::Time& end,
- const base::Closure& callback) {
- ClearDataImpl(remove_mask, quota_storage_remove_mask, GURL(),
- GetURLRequestContext(), begin, end, callback);
+ uint32 quota_storage_remove_mask,
+ const GURL* storage_origin,
+ const OriginMatcherFunction& origin_matcher,
+ const base::Time begin,
+ const base::Time end,
+ const base::Closure& callback) {
+ ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_origin,
+ origin_matcher, GetURLRequestContext(), begin, end, callback);
}
WebRTCIdentityStore* StoragePartitionImpl::GetWebRTCIdentityStore() {
return webrtc_identity_store_.get();
}
+void StoragePartitionImpl::OverrideQuotaManagerForTesting(
+ quota::QuotaManager* quota_manager) {
+ quota_manager_ = quota_manager;
+}
+
+void StoragePartitionImpl::OverrideSpecialStoragePolicyForTesting(
+ quota::SpecialStoragePolicy* special_storage_policy) {
+ special_storage_policy_ = special_storage_policy;
+}
+
void StoragePartitionImpl::SetURLRequestContext(
net::URLRequestContextGetter* url_request_context) {
url_request_context_ = url_request_context;
diff --git a/chromium/content/browser/storage_partition_impl.h b/chromium/content/browser/storage_partition_impl.h
index 87130e10bd8..4edf47472e8 100644
--- a/chromium/content/browser/storage_partition_impl.h
+++ b/chromium/content/browser/storage_partition_impl.h
@@ -12,9 +12,10 @@
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/media/webrtc_identity_store.h"
-#include "content/browser/service_worker/service_worker_context.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/content_export.h"
#include "content/public/browser/storage_partition.h"
+#include "webkit/browser/quota/special_storage_policy.h"
namespace content {
@@ -22,6 +23,15 @@ class StoragePartitionImpl : public StoragePartition {
public:
CONTENT_EXPORT virtual ~StoragePartitionImpl();
+ // Quota managed data uses a different bitmask for types than
+ // StoragePartition uses. This method generates that mask.
+ CONTENT_EXPORT static int GenerateQuotaClientMask(uint32 remove_mask);
+
+ CONTENT_EXPORT void OverrideQuotaManagerForTesting(
+ quota::QuotaManager* quota_manager);
+ CONTENT_EXPORT void OverrideSpecialStoragePolicyForTesting(
+ quota::SpecialStoragePolicy* special_storage_policy);
+
// StoragePartition interface.
virtual base::FilePath GetPath() OVERRIDE;
virtual net::URLRequestContextGetter* GetURLRequestContext() OVERRIDE;
@@ -38,16 +48,15 @@ class StoragePartitionImpl : public StoragePartition {
uint32 quota_storage_remove_mask,
const GURL& storage_origin,
net::URLRequestContextGetter* request_context_getter) OVERRIDE;
- virtual void ClearDataForUnboundedRange(
- uint32 remove_mask,
- uint32 quota_storage_remove_mask) OVERRIDE;
- virtual void ClearDataForRange(uint32 remove_mask,
- uint32 quota_storage_remove_mask,
- const base::Time& begin,
- const base::Time& end,
- const base::Closure& callback) OVERRIDE;
+ virtual void ClearData(uint32 remove_mask,
+ uint32 quota_storage_remove_mask,
+ const GURL* storage_origin,
+ const OriginMatcherFunction& origin_matcher,
+ const base::Time begin,
+ const base::Time end,
+ const base::Closure& callback) OVERRIDE;
- ServiceWorkerContext* GetServiceWorkerContext();
+ ServiceWorkerContextWrapper* GetServiceWorkerContext();
WebRTCIdentityStore* GetWebRTCIdentityStore();
@@ -57,6 +66,36 @@ class StoragePartitionImpl : public StoragePartition {
private:
friend class StoragePartitionImplMap;
FRIEND_TEST_ALL_PREFIXES(StoragePartitionShaderClearTest, ClearShaderCache);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveQuotaManagedDataForeverBoth);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveQuotaManagedDataForeverOnlyTemporary);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveQuotaManagedDataForeverOnlyPersistent);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveQuotaManagedDataForeverNeither);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveQuotaManagedDataForeverSpecificOrigin);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveQuotaManagedDataForLastHour);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveQuotaManagedDataForLastWeek);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveQuotaManagedUnprotectedOrigins);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveQuotaManagedProtectedSpecificOrigin);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveQuotaManagedProtectedOrigins);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveQuotaManagedIgnoreDevTools);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest, RemoveCookieForever);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest, RemoveCookieLastHour);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveUnprotectedLocalStorageForever);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveProtectedLocalStorageForever);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveLocalStorageForLastWeek);
// The |partition_path| is the absolute path to the root of this
// StoragePartition's on-disk storage.
@@ -68,10 +107,6 @@ class StoragePartitionImpl : public StoragePartition {
bool in_memory,
const base::FilePath& profile_path);
- // Quota managed data uses a different bitmask for types than
- // StoragePartition uses. This method generates that mask.
- static int GenerateQuotaClientMask(uint32 remove_mask);
-
CONTENT_EXPORT StoragePartitionImpl(
const base::FilePath& partition_path,
quota::QuotaManager* quota_manager,
@@ -80,12 +115,14 @@ class StoragePartitionImpl : public StoragePartition {
webkit_database::DatabaseTracker* database_tracker,
DOMStorageContextWrapper* dom_storage_context,
IndexedDBContextImpl* indexed_db_context,
- ServiceWorkerContext* service_worker_context,
- WebRTCIdentityStore* webrtc_identity_store);
+ ServiceWorkerContextWrapper* service_worker_context,
+ WebRTCIdentityStore* webrtc_identity_store,
+ quota::SpecialStoragePolicy* special_storage_policy);
void ClearDataImpl(uint32 remove_mask,
uint32 quota_storage_remove_mask,
- const GURL& remove_origin,
+ const GURL* remove_origin,
+ const OriginMatcherFunction& origin_matcher,
net::URLRequestContextGetter* rq_context,
const base::Time begin,
const base::Time end,
@@ -103,7 +140,8 @@ class StoragePartitionImpl : public StoragePartition {
// appropriate time. These should move back into the constructor once
// URLRequestContextGetter's lifetime is sorted out. We should also move the
// PostCreateInitialization() out of StoragePartitionImplMap.
- void SetURLRequestContext(net::URLRequestContextGetter* url_request_context);
+ CONTENT_EXPORT void SetURLRequestContext(
+ net::URLRequestContextGetter* url_request_context);
void SetMediaURLRequestContext(
net::URLRequestContextGetter* media_url_request_context);
@@ -116,8 +154,9 @@ class StoragePartitionImpl : public StoragePartition {
scoped_refptr<webkit_database::DatabaseTracker> database_tracker_;
scoped_refptr<DOMStorageContextWrapper> dom_storage_context_;
scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
- scoped_refptr<ServiceWorkerContext> service_worker_context_;
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
scoped_refptr<WebRTCIdentityStore> webrtc_identity_store_;
+ scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
DISALLOW_COPY_AND_ASSIGN(StoragePartitionImpl);
};
diff --git a/chromium/content/browser/storage_partition_impl_map.cc b/chromium/content/browser/storage_partition_impl_map.cc
index feb9515fe67..85934f117b3 100644
--- a/chromium/content/browser/storage_partition_impl_map.cc
+++ b/chromium/content/browser/storage_partition_impl_map.cc
@@ -290,8 +290,8 @@ void BlockingGarbageCollect(
base::FileEnumerator enumerator(storage_root, false, kAllFileTypes);
base::FilePath trash_directory;
- if (!file_util::CreateTemporaryDirInDir(storage_root, kTrashDirname,
- &trash_directory)) {
+ if (!base::CreateTemporaryDirInDir(storage_root, kTrashDirname,
+ &trash_directory)) {
// Unable to continue without creating the trash directory so give up.
return;
}
@@ -460,11 +460,15 @@ void StoragePartitionImplMap::AsyncObliterate(
++it) {
const StoragePartitionConfig& config = it->first;
if (config.partition_domain == partition_domain) {
- it->second->ClearDataForUnboundedRange(
+ it->second->ClearData(
// All except shader cache.
StoragePartition::REMOVE_DATA_MASK_ALL &
(~StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE),
- StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL);
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+ NULL,
+ StoragePartition::OriginMatcherFunction(),
+ base::Time(), base::Time::Max(),
+ base::Bind(&base::DoNothing));
if (!config.in_memory) {
paths_to_keep.push_back(it->second->GetPath());
}
diff --git a/chromium/content/browser/storage_partition_impl_unittest.cc b/chromium/content/browser/storage_partition_impl_unittest.cc
index 4828ae6529f..ef3b67912ac 100644
--- a/chromium/content/browser/storage_partition_impl_unittest.cc
+++ b/chromium/content/browser/storage_partition_impl_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 "base/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
@@ -9,14 +10,57 @@
#include "content/browser/browser_thread_impl.h"
#include "content/browser/gpu/shader_disk_cache.h"
#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/local_storage_usage_info.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/test_completion_callback.h"
+#include "net/cookies/cookie_monster.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/quota/mock_quota_manager.h"
+#include "webkit/browser/quota/mock_special_storage_policy.h"
+#include "webkit/browser/quota/quota_manager.h"
namespace content {
namespace {
+const int kDefaultClientId = 42;
+const char kCacheKey[] = "key";
+const char kCacheValue[] = "cached value";
+
+const char kTestOrigin1[] = "http://host1:1/";
+const char kTestOrigin2[] = "http://host2:1/";
+const char kTestOrigin3[] = "http://host3:1/";
+const char kTestOriginDevTools[] = "chrome-devtools://abcdefghijklmnopqrstuvw/";
+
+const GURL kOrigin1(kTestOrigin1);
+const GURL kOrigin2(kTestOrigin2);
+const GURL kOrigin3(kTestOrigin3);
+const GURL kOriginDevTools(kTestOriginDevTools);
+
+const base::FilePath::CharType kDomStorageOrigin1[] =
+ FILE_PATH_LITERAL("http_host1_1.localstorage");
+
+const base::FilePath::CharType kDomStorageOrigin2[] =
+ FILE_PATH_LITERAL("http_host2_1.localstorage");
+
+const base::FilePath::CharType kDomStorageOrigin3[] =
+ FILE_PATH_LITERAL("http_host3_1.localstorage");
+
+const quota::StorageType kTemporary = quota::kStorageTypeTemporary;
+const quota::StorageType kPersistent = quota::kStorageTypePersistent;
+
+const quota::QuotaClient::ID kClientFile = quota::QuotaClient::kFileSystem;
+
+const uint32 kAllQuotaRemoveMask =
+ StoragePartition::REMOVE_DATA_MASK_INDEXEDDB |
+ StoragePartition::REMOVE_DATA_MASK_WEBSQL |
+ StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
+ StoragePartition::REMOVE_DATA_MASK_APPCACHE;
+
class TestClosureCallback {
public:
TestClosureCallback()
@@ -42,12 +86,290 @@ class TestClosureCallback {
DISALLOW_COPY_AND_ASSIGN(TestClosureCallback);
};
-const int kDefaultClientId = 42;
-const char kCacheKey[] = "key";
-const char kCacheValue[] = "cached value";
+class AwaitCompletionHelper {
+ public:
+ AwaitCompletionHelper() : start_(false), already_quit_(false) {}
+ virtual ~AwaitCompletionHelper() {}
+
+ void BlockUntilNotified() {
+ if (!already_quit_) {
+ DCHECK(!start_);
+ start_ = true;
+ base::MessageLoop::current()->Run();
+ } else {
+ DCHECK(!start_);
+ already_quit_ = false;
+ }
+ }
+
+ void Notify() {
+ if (start_) {
+ DCHECK(!already_quit_);
+ base::MessageLoop::current()->Quit();
+ start_ = false;
+ } else {
+ DCHECK(!already_quit_);
+ already_quit_ = true;
+ }
+ }
+
+ private:
+ // Helps prevent from running message_loop, if the callback invoked
+ // immediately.
+ bool start_;
+ bool already_quit_;
+
+ DISALLOW_COPY_AND_ASSIGN(AwaitCompletionHelper);
+};
+
+class RemoveCookieTester {
+ public:
+ explicit RemoveCookieTester(TestBrowserContext* context)
+ : get_cookie_success_(false), monster_(NULL) {
+ SetMonster(context->GetRequestContext()->GetURLRequestContext()->
+ cookie_store()->GetCookieMonster());
+ }
+
+ // Returns true, if the given cookie exists in the cookie store.
+ bool ContainsCookie() {
+ get_cookie_success_ = false;
+ monster_->GetCookiesWithOptionsAsync(
+ kOrigin1, net::CookieOptions(),
+ base::Bind(&RemoveCookieTester::GetCookieCallback,
+ base::Unretained(this)));
+ await_completion_.BlockUntilNotified();
+ return get_cookie_success_;
+ }
+
+ void AddCookie() {
+ monster_->SetCookieWithOptionsAsync(
+ kOrigin1, "A=1", net::CookieOptions(),
+ base::Bind(&RemoveCookieTester::SetCookieCallback,
+ base::Unretained(this)));
+ await_completion_.BlockUntilNotified();
+ }
+
+ protected:
+ void SetMonster(net::CookieStore* monster) {
+ monster_ = monster;
+ }
+
+ private:
+ void GetCookieCallback(const std::string& cookies) {
+ if (cookies == "A=1") {
+ get_cookie_success_ = true;
+ } else {
+ EXPECT_EQ("", cookies);
+ get_cookie_success_ = false;
+ }
+ await_completion_.Notify();
+ }
+
+ void SetCookieCallback(bool result) {
+ ASSERT_TRUE(result);
+ await_completion_.Notify();
+ }
+
+ bool get_cookie_success_;
+ AwaitCompletionHelper await_completion_;
+ net::CookieStore* monster_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemoveCookieTester);
+};
+
+class RemoveLocalStorageTester {
+ public:
+ explicit RemoveLocalStorageTester(TestBrowserContext* profile)
+ : profile_(profile), dom_storage_context_(NULL) {
+ dom_storage_context_ =
+ content::BrowserContext::GetDefaultStoragePartition(profile)->
+ GetDOMStorageContext();
+ }
+
+ // Returns true, if the given origin URL exists.
+ bool DOMStorageExistsForOrigin(const GURL& origin) {
+ GetLocalStorageUsage();
+ await_completion_.BlockUntilNotified();
+ for (size_t i = 0; i < infos_.size(); ++i) {
+ if (origin == infos_[i].origin)
+ return true;
+ }
+ return false;
+ }
+
+ void AddDOMStorageTestData() {
+ // Note: This test depends on details of how the dom_storage library
+ // stores data in the host file system.
+ base::FilePath storage_path =
+ profile_->GetPath().AppendASCII("Local Storage");
+ base::CreateDirectory(storage_path);
+
+ // Write some files.
+ file_util::WriteFile(storage_path.Append(kDomStorageOrigin1), NULL, 0);
+ file_util::WriteFile(storage_path.Append(kDomStorageOrigin2), NULL, 0);
+ file_util::WriteFile(storage_path.Append(kDomStorageOrigin3), NULL, 0);
+
+ // Tweak their dates.
+ base::Time now = base::Time::Now();
+ base::TouchFile(storage_path.Append(kDomStorageOrigin1), now, now);
+
+ base::Time one_day_ago = now - base::TimeDelta::FromDays(1);
+ base::TouchFile(storage_path.Append(kDomStorageOrigin2),
+ one_day_ago, one_day_ago);
+
+ base::Time sixty_days_ago = now - base::TimeDelta::FromDays(60);
+ base::TouchFile(storage_path.Append(kDomStorageOrigin3),
+ sixty_days_ago, sixty_days_ago);
+ }
+
+ private:
+ void GetLocalStorageUsage() {
+ dom_storage_context_->GetLocalStorageUsage(
+ base::Bind(&RemoveLocalStorageTester::OnGotLocalStorageUsage,
+ base::Unretained(this)));
+ }
+ void OnGotLocalStorageUsage(
+ const std::vector<content::LocalStorageUsageInfo>& infos) {
+ infos_ = infos;
+ await_completion_.Notify();
+ }
+
+ // We don't own these pointers.
+ TestBrowserContext* profile_;
+ content::DOMStorageContext* dom_storage_context_;
+
+ std::vector<content::LocalStorageUsageInfo> infos_;
+
+ AwaitCompletionHelper await_completion_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemoveLocalStorageTester);
+};
+
+bool IsWebSafeSchemeForTest(const std::string& scheme) {
+ return scheme == "http";
+}
+
+bool DoesOriginMatchForUnprotectedWeb(
+ const GURL& origin,
+ quota::SpecialStoragePolicy* special_storage_policy) {
+ if (IsWebSafeSchemeForTest(origin.scheme()))
+ return !special_storage_policy->IsStorageProtected(origin.GetOrigin());
+
+ return false;
+}
+
+bool DoesOriginMatchForBothProtectedAndUnprotectedWeb(
+ const GURL& origin,
+ quota::SpecialStoragePolicy* special_storage_policy) {
+ return true;
+}
+
+bool DoesOriginMatchUnprotected(
+ const GURL& origin,
+ quota::SpecialStoragePolicy* special_storage_policy) {
+ return origin.GetOrigin().scheme() != kOriginDevTools.scheme();
+}
+
+void ClearQuotaData(content::StoragePartition* storage_partition,
+ const base::Closure& cb) {
+ storage_partition->ClearData(
+ kAllQuotaRemoveMask,
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+ NULL, StoragePartition::OriginMatcherFunction(),
+ base::Time(), base::Time::Max(), cb);
+}
+
+void ClearQuotaDataWithOriginMatcher(
+ content::StoragePartition* storage_partition,
+ const GURL& remove_origin,
+ const StoragePartition::OriginMatcherFunction& origin_matcher,
+ const base::Time delete_begin,
+ const base::Closure& cb) {
+ storage_partition->ClearData(kAllQuotaRemoveMask,
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+ &remove_origin, origin_matcher, delete_begin,
+ base::Time::Max(), cb);
+}
+
+void ClearQuotaDataForOrigin(
+ content::StoragePartition* storage_partition,
+ const GURL& remove_origin,
+ const base::Time delete_begin,
+ const base::Closure& cb) {
+ ClearQuotaDataWithOriginMatcher(
+ storage_partition, remove_origin,
+ StoragePartition::OriginMatcherFunction(), delete_begin, cb);
+}
+
+void ClearQuotaDataForNonPersistent(
+ content::StoragePartition* storage_partition,
+ const base::Time delete_begin,
+ const base::Closure& cb) {
+ uint32 quota_storage_remove_mask_no_persistent =
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL &
+ ~StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT;
+ storage_partition->ClearData(
+ kAllQuotaRemoveMask, quota_storage_remove_mask_no_persistent,
+ NULL, StoragePartition::OriginMatcherFunction(),
+ delete_begin, base::Time::Max(), cb);
+}
+
+void ClearCookies(content::StoragePartition* storage_partition,
+ const base::Time delete_begin,
+ const base::Time delete_end,
+ const base::Closure& cb) {
+ storage_partition->ClearData(
+ StoragePartition::REMOVE_DATA_MASK_COOKIES,
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+ NULL, StoragePartition::OriginMatcherFunction(),
+ delete_begin, delete_end, cb);
+}
+
+void ClearStuff(uint32 remove_mask,
+ content::StoragePartition* storage_partition,
+ const base::Time delete_begin,
+ const base::Time delete_end,
+ const StoragePartition::OriginMatcherFunction& origin_matcher,
+ const base::Closure& cb) {
+ storage_partition->ClearData(
+ remove_mask, StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+ NULL, origin_matcher, delete_begin, delete_end, cb);
+}
} // namespace
+class StoragePartitionImplTest : public testing::Test {
+ public:
+ StoragePartitionImplTest()
+ : browser_context_(new TestBrowserContext()),
+ thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
+ }
+ virtual ~StoragePartitionImplTest() {}
+
+ quota::MockQuotaManager* GetMockManager() {
+ if (!quota_manager_.get()) {
+ quota_manager_ = new quota::MockQuotaManager(
+ browser_context_->IsOffTheRecord(),
+ browser_context_->GetPath(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
+ browser_context_->GetSpecialStoragePolicy());
+ }
+ return quota_manager_.get();
+ }
+
+ TestBrowserContext* GetBrowserContext() {
+ return browser_context_.get();
+ }
+
+ private:
+ scoped_ptr<TestBrowserContext> browser_context_;
+ scoped_refptr<quota::MockQuotaManager> quota_manager_;
+ content::TestBrowserThreadBundle thread_bundle_;
+
+ DISALLOW_COPY_AND_ASSIGN(StoragePartitionImplTest);
+};
+
class StoragePartitionShaderClearTest : public testing::Test {
public:
StoragePartitionShaderClearTest()
@@ -98,23 +420,550 @@ class StoragePartitionShaderClearTest : public testing::Test {
void ClearData(content::StoragePartitionImpl* sp,
const base::Closure& cb) {
base::Time time;
- sp->ClearDataForRange(
+ sp->ClearData(
StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+ NULL, StoragePartition::OriginMatcherFunction(),
time, time, cb);
}
+// Tests ---------------------------------------------------------------------
+
TEST_F(StoragePartitionShaderClearTest, ClearShaderCache) {
InitCache();
EXPECT_EQ(1u, Size());
TestClosureCallback clear_cb;
- StoragePartitionImpl sp(
- cache_path(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ StoragePartitionImpl storage_partition(
+ cache_path(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&ClearData, &sp, clear_cb.callback()));
+ FROM_HERE, base::Bind(&ClearData, &storage_partition,
+ clear_cb.callback()));
clear_cb.WaitForResult();
EXPECT_EQ(0u, Size());
}
+TEST_F(StoragePartitionImplTest, QuotaClientMaskGeneration) {
+ EXPECT_EQ(quota::QuotaClient::kFileSystem,
+ StoragePartitionImpl::GenerateQuotaClientMask(
+ StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS));
+ EXPECT_EQ(quota::QuotaClient::kDatabase,
+ StoragePartitionImpl::GenerateQuotaClientMask(
+ StoragePartition::REMOVE_DATA_MASK_WEBSQL));
+ EXPECT_EQ(quota::QuotaClient::kAppcache,
+ StoragePartitionImpl::GenerateQuotaClientMask(
+ StoragePartition::REMOVE_DATA_MASK_APPCACHE));
+ EXPECT_EQ(quota::QuotaClient::kIndexedDatabase,
+ StoragePartitionImpl::GenerateQuotaClientMask(
+ StoragePartition::REMOVE_DATA_MASK_INDEXEDDB));
+ EXPECT_EQ(quota::QuotaClient::kFileSystem |
+ quota::QuotaClient::kDatabase |
+ quota::QuotaClient::kAppcache |
+ quota::QuotaClient::kIndexedDatabase,
+ StoragePartitionImpl::GenerateQuotaClientMask(
+ StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
+ StoragePartition::REMOVE_DATA_MASK_WEBSQL |
+ StoragePartition::REMOVE_DATA_MASK_APPCACHE |
+ StoragePartition::REMOVE_DATA_MASK_INDEXEDDB));
+}
+
+void PopulateTestQuotaManagedPersistentData(quota::MockQuotaManager* manager) {
+ manager->AddOrigin(kOrigin2, kPersistent, kClientFile, base::Time());
+ manager->AddOrigin(kOrigin3, kPersistent, kClientFile,
+ base::Time::Now() - base::TimeDelta::FromDays(1));
+
+ EXPECT_FALSE(manager->OriginHasData(kOrigin1, kPersistent, kClientFile));
+ EXPECT_TRUE(manager->OriginHasData(kOrigin2, kPersistent, kClientFile));
+ EXPECT_TRUE(manager->OriginHasData(kOrigin3, kPersistent, kClientFile));
+}
+
+void PopulateTestQuotaManagedTemporaryData(quota::MockQuotaManager* manager) {
+ manager->AddOrigin(kOrigin1, kTemporary, kClientFile, base::Time::Now());
+ manager->AddOrigin(kOrigin3, kTemporary, kClientFile,
+ base::Time::Now() - base::TimeDelta::FromDays(1));
+
+ EXPECT_TRUE(manager->OriginHasData(kOrigin1, kTemporary, kClientFile));
+ EXPECT_FALSE(manager->OriginHasData(kOrigin2, kTemporary, kClientFile));
+ EXPECT_TRUE(manager->OriginHasData(kOrigin3, kTemporary, kClientFile));
+}
+
+void PopulateTestQuotaManagedData(quota::MockQuotaManager* manager) {
+ // Set up kOrigin1 with a temporary quota, kOrigin2 with a persistent
+ // quota, and kOrigin3 with both. kOrigin1 is modified now, kOrigin2
+ // is modified at the beginning of time, and kOrigin3 is modified one day
+ // ago.
+ PopulateTestQuotaManagedPersistentData(manager);
+ PopulateTestQuotaManagedTemporaryData(manager);
+}
+
+void PopulateTestQuotaManagedNonBrowsingData(quota::MockQuotaManager* manager) {
+ manager->AddOrigin(kOriginDevTools, kTemporary, kClientFile, base::Time());
+ manager->AddOrigin(kOriginDevTools, kPersistent, kClientFile, base::Time());
+}
+
+TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverBoth) {
+ PopulateTestQuotaManagedData(GetMockManager());
+
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(&sp)->OverrideQuotaManagerForTesting(
+ GetMockManager());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearQuotaData, &sp, clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
+ kClientFile));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverOnlyTemporary) {
+ PopulateTestQuotaManagedTemporaryData(GetMockManager());
+
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(&sp)->OverrideQuotaManagerForTesting(
+ GetMockManager());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearQuotaData, &sp, clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
+ kClientFile));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverOnlyPersistent) {
+ PopulateTestQuotaManagedPersistentData(GetMockManager());
+
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(&sp)->OverrideQuotaManagerForTesting(
+ GetMockManager());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearQuotaData, &sp, clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
+ kClientFile));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverNeither) {
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(&sp)->OverrideQuotaManagerForTesting(
+ GetMockManager());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearQuotaData, &sp, clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
+ kClientFile));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverSpecificOrigin) {
+ PopulateTestQuotaManagedData(GetMockManager());
+
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(&sp)->OverrideQuotaManagerForTesting(
+ GetMockManager());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearQuotaDataForOrigin,
+ &sp, kOrigin1, base::Time(), clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
+ kClientFile));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForLastHour) {
+ PopulateTestQuotaManagedData(GetMockManager());
+
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(&sp)->OverrideQuotaManagerForTesting(
+ GetMockManager());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearQuotaDataForOrigin,
+ &sp, GURL(),
+ base::Time::Now() - base::TimeDelta::FromHours(1),
+ clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
+ kClientFile));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForLastWeek) {
+ PopulateTestQuotaManagedData(GetMockManager());
+
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(&sp)->OverrideQuotaManagerForTesting(
+ GetMockManager());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearQuotaDataForNonPersistent,
+ &sp,
+ base::Time::Now() - base::TimeDelta::FromDays(7),
+ clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
+ kClientFile));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveQuotaManagedUnprotectedOrigins) {
+ // Protect kOrigin1.
+ scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy =
+ new quota::MockSpecialStoragePolicy;
+ mock_policy->AddProtected(kOrigin1.GetOrigin());
+
+ PopulateTestQuotaManagedData(GetMockManager());
+
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(&sp)->OverrideQuotaManagerForTesting(
+ GetMockManager());
+ static_cast<StoragePartitionImpl*>(
+ &sp)->OverrideSpecialStoragePolicyForTesting(mock_policy);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearQuotaDataWithOriginMatcher,
+ &sp, GURL(),
+ base::Bind(&DoesOriginMatchForUnprotectedWeb),
+ base::Time(), clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
+ kClientFile));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveQuotaManagedProtectedSpecificOrigin) {
+ // Protect kOrigin1.
+ scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy =
+ new quota::MockSpecialStoragePolicy;
+ mock_policy->AddProtected(kOrigin1.GetOrigin());
+
+ PopulateTestQuotaManagedData(GetMockManager());
+
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(&sp)->OverrideQuotaManagerForTesting(
+ GetMockManager());
+ static_cast<StoragePartitionImpl*>(
+ &sp)->OverrideSpecialStoragePolicyForTesting(mock_policy);
+
+ // Try to remove kOrigin1. Expect failure.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearQuotaDataWithOriginMatcher,
+ &sp, kOrigin1,
+ base::Bind(&DoesOriginMatchForUnprotectedWeb),
+ base::Time(), clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
+ kClientFile));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveQuotaManagedProtectedOrigins) {
+ // Protect kOrigin1.
+ scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy =
+ new quota::MockSpecialStoragePolicy;
+ mock_policy->AddProtected(kOrigin1.GetOrigin());
+
+ PopulateTestQuotaManagedData(GetMockManager());
+
+ // Try to remove kOrigin1. Expect success.
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(&sp)->OverrideQuotaManagerForTesting(
+ GetMockManager());
+ static_cast<StoragePartitionImpl*>(
+ &sp)->OverrideSpecialStoragePolicyForTesting(mock_policy);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&ClearQuotaDataWithOriginMatcher,
+ &sp, GURL(),
+ base::Bind(&DoesOriginMatchForBothProtectedAndUnprotectedWeb),
+ base::Time(), clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
+ kClientFile));
+ EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
+ kClientFile));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveQuotaManagedIgnoreDevTools) {
+ PopulateTestQuotaManagedNonBrowsingData(GetMockManager());
+
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(&sp)->OverrideQuotaManagerForTesting(
+ GetMockManager());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearQuotaDataWithOriginMatcher,
+ &sp, GURL(),
+ base::Bind(&DoesOriginMatchUnprotected),
+ base::Time(), clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ // Check that devtools data isn't removed.
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOriginDevTools, kTemporary,
+ kClientFile));
+ EXPECT_TRUE(GetMockManager()->OriginHasData(kOriginDevTools, kPersistent,
+ kClientFile));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveCookieForever) {
+ RemoveCookieTester tester(GetBrowserContext());
+
+ tester.AddCookie();
+ ASSERT_TRUE(tester.ContainsCookie());
+
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ sp.SetURLRequestContext(GetBrowserContext()->GetRequestContext());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearCookies,
+ &sp, base::Time(), base::Time::Max(),
+ clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_FALSE(tester.ContainsCookie());
+}
+
+TEST_F(StoragePartitionImplTest, RemoveCookieLastHour) {
+ RemoveCookieTester tester(GetBrowserContext());
+
+ tester.AddCookie();
+ ASSERT_TRUE(tester.ContainsCookie());
+
+ TestClosureCallback clear_cb;
+ StoragePartitionImpl sp(
+ base::FilePath(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ base::Time an_hour_ago = base::Time::Now() - base::TimeDelta::FromHours(1);
+ sp.SetURLRequestContext(GetBrowserContext()->GetRequestContext());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&ClearCookies,
+ &sp, an_hour_ago, base::Time::Max(),
+ clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_FALSE(tester.ContainsCookie());
+}
+
+TEST_F(StoragePartitionImplTest, RemoveUnprotectedLocalStorageForever) {
+ // Protect kOrigin1.
+ scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy =
+ new quota::MockSpecialStoragePolicy;
+ mock_policy->AddProtected(kOrigin1.GetOrigin());
+
+ RemoveLocalStorageTester tester(GetBrowserContext());
+
+ tester.AddDOMStorageTestData();
+ EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin1));
+ EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin2));
+ EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin3));
+
+ TestClosureCallback clear_cb;
+ DOMStorageContextWrapper* dom_storage_context =
+ static_cast<DOMStorageContextWrapper*>(
+ content::BrowserContext::GetDefaultStoragePartition(
+ GetBrowserContext())->GetDOMStorageContext());
+ StoragePartitionImpl sp(base::FilePath(), NULL, NULL, NULL, NULL,
+ dom_storage_context, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(
+ &sp)->OverrideSpecialStoragePolicyForTesting(mock_policy);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&ClearStuff,
+ StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE,
+ &sp, base::Time(), base::Time::Max(),
+ base::Bind(&DoesOriginMatchForUnprotectedWeb),
+ clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin1));
+ EXPECT_FALSE(tester.DOMStorageExistsForOrigin(kOrigin2));
+ EXPECT_FALSE(tester.DOMStorageExistsForOrigin(kOrigin3));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveProtectedLocalStorageForever) {
+ // Protect kOrigin1.
+ scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy =
+ new quota::MockSpecialStoragePolicy;
+ mock_policy->AddProtected(kOrigin1.GetOrigin());
+
+ RemoveLocalStorageTester tester(GetBrowserContext());
+
+ tester.AddDOMStorageTestData();
+ EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin1));
+ EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin2));
+ EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin3));
+
+ TestClosureCallback clear_cb;
+ DOMStorageContextWrapper* dom_storage_context =
+ static_cast<DOMStorageContextWrapper*>(
+ content::BrowserContext::GetDefaultStoragePartition(
+ GetBrowserContext())->GetDOMStorageContext());
+ StoragePartitionImpl sp(base::FilePath(), NULL, NULL, NULL, NULL,
+ dom_storage_context, NULL, NULL, NULL, NULL);
+ static_cast<StoragePartitionImpl*>(
+ &sp)->OverrideSpecialStoragePolicyForTesting(mock_policy);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&ClearStuff,
+ StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE,
+ &sp, base::Time(), base::Time::Max(),
+ base::Bind(&DoesOriginMatchForBothProtectedAndUnprotectedWeb),
+ clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ // Even if kOrigin1 is protected, it will be deleted since we specify
+ // ClearData to delete protected data.
+ EXPECT_FALSE(tester.DOMStorageExistsForOrigin(kOrigin1));
+ EXPECT_FALSE(tester.DOMStorageExistsForOrigin(kOrigin2));
+ EXPECT_FALSE(tester.DOMStorageExistsForOrigin(kOrigin3));
+}
+
+TEST_F(StoragePartitionImplTest, RemoveLocalStorageForLastWeek) {
+ RemoveLocalStorageTester tester(GetBrowserContext());
+
+ tester.AddDOMStorageTestData();
+ EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin1));
+ EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin2));
+ EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin3));
+
+ TestClosureCallback clear_cb;
+ DOMStorageContextWrapper* dom_storage_context =
+ static_cast<DOMStorageContextWrapper*>(
+ content::BrowserContext::GetDefaultStoragePartition(
+ GetBrowserContext())->GetDOMStorageContext());
+ StoragePartitionImpl sp(base::FilePath(), NULL, NULL, NULL, NULL,
+ dom_storage_context, NULL, NULL, NULL, NULL);
+ base::Time a_week_ago = base::Time::Now() - base::TimeDelta::FromDays(7);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&ClearStuff,
+ StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE,
+ &sp, a_week_ago, base::Time::Max(),
+ base::Bind(&DoesOriginMatchForBothProtectedAndUnprotectedWeb),
+ clear_cb.callback()));
+ clear_cb.WaitForResult();
+
+ // kOrigin1 and kOrigin2 do not have age more than a week.
+ EXPECT_FALSE(tester.DOMStorageExistsForOrigin(kOrigin1));
+ EXPECT_FALSE(tester.DOMStorageExistsForOrigin(kOrigin2));
+ EXPECT_TRUE(tester.DOMStorageExistsForOrigin(kOrigin3));
+}
+
} // namespace content
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 8914fe5c50c..d3378032080 100644
--- a/chromium/content/browser/streams/stream_url_request_job_unittest.cc
+++ b/chromium/content/browser/streams/stream_url_request_job_unittest.cc
@@ -8,6 +8,8 @@
#include "content/browser/streams/stream_registry.h"
#include "content/browser/streams/stream_url_request_job.h"
#include "content/browser/streams/stream_write_observer.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_byte_range.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
@@ -73,7 +75,8 @@ class StreamURLRequestJobTest : public testing::Test {
int expected_status_code,
const std::string& expected_response) {
net::TestDelegate delegate;
- request_.reset(url_request_context_.CreateRequest(url, &delegate));
+ request_ = url_request_context_.CreateRequest(
+ url, net::DEFAULT_PRIORITY, &delegate);
request_->set_method(method);
if (!extra_headers.IsEmpty())
request_->SetExtraRequestHeaders(extra_headers);
@@ -130,7 +133,8 @@ TEST_F(StreamURLRequestJobTest, TestGetLargeStreamRequest) {
TEST_F(StreamURLRequestJobTest, TestGetNonExistentStreamRequest) {
net::TestDelegate delegate;
- request_.reset(url_request_context_.CreateRequest(kStreamURL, &delegate));
+ request_ = url_request_context_.CreateRequest(
+ kStreamURL, net::DEFAULT_PRIORITY, &delegate);
request_->set_method("GET");
request_->Start();
@@ -151,7 +155,8 @@ TEST_F(StreamURLRequestJobTest, TestRangeDataRequest) {
stream->Finalize();
net::HttpRequestHeaders extra_headers;
- extra_headers.SetHeader(net::HttpRequestHeaders::kRange, "bytes=0-3");
+ extra_headers.SetHeader(net::HttpRequestHeaders::kRange,
+ net::HttpByteRange::Bounded(0, 3).GetHeaderValue());
TestRequest("GET", kStreamURL, extra_headers,
200, std::string(kTestData2, 4));
}
@@ -167,7 +172,8 @@ TEST_F(StreamURLRequestJobTest, TestInvalidRangeDataRequest) {
stream->Finalize();
net::HttpRequestHeaders extra_headers;
- extra_headers.SetHeader(net::HttpRequestHeaders::kRange, "bytes=1-3");
+ extra_headers.SetHeader(net::HttpRequestHeaders::kRange,
+ net::HttpByteRange::Bounded(1, 3).GetHeaderValue());
TestRequest("GET", kStreamURL, extra_headers, 405, std::string());
}
diff --git a/chromium/content/browser/theme_helper_mac.h b/chromium/content/browser/theme_helper_mac.h
new file mode 100644
index 00000000000..ab04337209d
--- /dev/null
+++ b/chromium/content/browser/theme_helper_mac.h
@@ -0,0 +1,44 @@
+// 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_THEME_HELPER_MAC_H_
+#define CONTENT_BROWSER_THEME_HELPER_MAC_H_
+
+#include "base/memory/singleton.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+namespace content {
+
+class ThemeHelperMac : public NotificationObserver {
+ public:
+ // Return pointer to the singleton instance for the current process, or NULL
+ // if none.
+ static ThemeHelperMac* GetInstance();
+
+ static void SendThemeChangeToAllRenderers(
+ float initial_button_delay,
+ float autoscroll_button_delay,
+ bool jump_on_track_click,
+ bool redraw);
+
+ private:
+ friend struct DefaultSingletonTraits<ThemeHelperMac>;
+
+ ThemeHelperMac();
+ virtual ~ThemeHelperMac();
+
+ // Overridden from NotificationObserver:
+ virtual void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) OVERRIDE;
+
+ NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThemeHelperMac);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_THEME_HELPER_MAC_H_
diff --git a/chromium/content/browser/theme_helper_mac.mm b/chromium/content/browser/theme_helper_mac.mm
new file mode 100644
index 00000000000..3b952cc79b8
--- /dev/null
+++ b/chromium/content/browser/theme_helper_mac.mm
@@ -0,0 +1,117 @@
+// 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/theme_helper_mac.h"
+
+#include <Foundation/Foundation.h>
+
+#include "content/common/view_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_process_host.h"
+
+@interface ScrollbarPrefsObserver : NSObject
+
++ (void)registerAsObserver;
++ (void)appearancePrefsChanged:(NSNotification*)notification;
++ (void)behaviorPrefsChanged:(NSNotification*)notification;
++ (void)notifyPrefsChangedWithRedraw:(BOOL)redraw;
+
+@end
+
+@implementation ScrollbarPrefsObserver
+
++ (void)registerAsObserver {
+ [[NSDistributedNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(appearancePrefsChanged:)
+ name:@"AppleAquaScrollBarVariantChanged"
+ object:nil
+suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
+
+ [[NSDistributedNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(behaviorPrefsChanged:)
+ name:@"AppleNoRedisplayAppearancePreferenceChanged"
+ object:nil
+suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
+}
+
++ (void)appearancePrefsChanged:(NSNotification*)notification {
+ [self notifyPrefsChangedWithRedraw:YES];
+}
+
++ (void)behaviorPrefsChanged:(NSNotification*)notification {
+ [self notifyPrefsChangedWithRedraw:NO];
+}
+
++ (void)notifyPrefsChangedWithRedraw:(BOOL)redraw {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+ [defaults synchronize];
+
+ content::ThemeHelperMac::SendThemeChangeToAllRenderers(
+ [defaults floatForKey:@"NSScrollerButtonDelay"],
+ [defaults floatForKey:@"NSScrollerButtonPeriod"],
+ [defaults boolForKey:@"AppleScrollerPagingBehavior"],
+ redraw);
+}
+
+@end
+
+namespace content {
+
+ThemeHelperMac::ThemeHelperMac() {
+ [ScrollbarPrefsObserver registerAsObserver];
+ registrar_.Add(this,
+ NOTIFICATION_RENDERER_PROCESS_CREATED,
+ NotificationService::AllSources());
+}
+
+ThemeHelperMac::~ThemeHelperMac() {
+}
+
+// static
+ThemeHelperMac* ThemeHelperMac::GetInstance() {
+ return Singleton<ThemeHelperMac,
+ LeakySingletonTraits<ThemeHelperMac> >::get();
+}
+
+
+void ThemeHelperMac::Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK_EQ(NOTIFICATION_RENDERER_PROCESS_CREATED, type);
+
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+ [defaults synchronize];
+
+ RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
+ rph->Send(new ViewMsg_UpdateScrollbarTheme(
+ [defaults floatForKey:@"NSScrollerButtonDelay"],
+ [defaults floatForKey:@"NSScrollerButtonPeriod"],
+ [defaults boolForKey:@"AppleScrollerPagingBehavior"],
+ false));
+}
+
+// static
+void ThemeHelperMac::SendThemeChangeToAllRenderers(
+ float initial_button_delay,
+ float autoscroll_button_delay,
+ bool jump_on_track_click,
+ bool redraw) {
+ for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
+ !it.IsAtEnd();
+ it.Advance()) {
+ it.GetCurrentValue()->Send(new ViewMsg_UpdateScrollbarTheme(
+ initial_button_delay,
+ autoscroll_button_delay,
+ jump_on_track_click,
+ redraw));
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/tracing/trace_controller_impl.cc b/chromium/content/browser/tracing/trace_controller_impl.cc
deleted file mode 100644
index fe08639876d..00000000000
--- a/chromium/content/browser/tracing/trace_controller_impl.cc
+++ /dev/null
@@ -1,417 +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/tracing/trace_controller_impl.h"
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/debug/trace_event.h"
-#include "base/strings/string_number_conversions.h"
-#include "content/browser/tracing/trace_message_filter.h"
-#include "content/browser/tracing/trace_subscriber_stdio.h"
-#include "content/common/child_process_messages.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "content/public/common/content_switches.h"
-
-using base::debug::TraceLog;
-
-namespace content {
-
-namespace {
-
-base::LazyInstance<TraceControllerImpl>::Leaky g_controller =
- LAZY_INSTANCE_INITIALIZER;
-
-class AutoStopTraceSubscriberStdio : public TraceSubscriberStdio {
- public:
- AutoStopTraceSubscriberStdio(const base::FilePath& file_path)
- : TraceSubscriberStdio(file_path,
- FILE_TYPE_PROPERTY_LIST,
- false) {}
-
- static void EndStartupTrace(AutoStopTraceSubscriberStdio* subscriber) {
- if (!TraceControllerImpl::GetInstance()->EndTracingAsync(subscriber))
- delete subscriber;
- // else, the tracing will end asynchronously in OnEndTracingComplete().
- }
-
- virtual void OnEndTracingComplete() OVERRIDE {
- TraceSubscriberStdio::OnEndTracingComplete();
- delete this;
- // TODO(joth): this would be the time to automatically open up
- // chrome://tracing/ and load up the trace data collected.
- }
-};
-
-} // namespace
-
-TraceController* TraceController::GetInstance() {
- return TraceControllerImpl::GetInstance();
-}
-
-TraceControllerImpl::TraceControllerImpl() :
- subscriber_(NULL),
- pending_end_ack_count_(0),
- pending_bpf_ack_count_(0),
- maximum_bpf_(0.0f),
- is_tracing_(false),
- is_get_category_groups_(false),
- category_filter_(
- base::debug::CategoryFilter::kDefaultCategoryFilterString) {
- TraceLog::GetInstance()->SetNotificationCallback(
- base::Bind(&TraceControllerImpl::OnTraceNotification,
- base::Unretained(this)));
-}
-
-TraceControllerImpl::~TraceControllerImpl() {
- // No need to SetNotificationCallback(nil) on the TraceLog since this is a
- // Leaky instance.
- NOTREACHED();
-}
-
-TraceControllerImpl* TraceControllerImpl::GetInstance() {
- return g_controller.Pointer();
-}
-
-void TraceControllerImpl::InitStartupTracing(const CommandLine& command_line) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- base::FilePath trace_file = command_line.GetSwitchValuePath(
- switches::kTraceStartupFile);
- // trace_file = "none" means that startup events will show up for the next
- // begin/end tracing (via about:tracing or AutomationProxy::BeginTracing/
- // EndTracing, for example).
- if (trace_file == base::FilePath().AppendASCII("none"))
- return;
-
- if (trace_file.empty()) {
- // Default to saving the startup trace into the current dir.
- trace_file = base::FilePath().AppendASCII("chrometrace.log");
- }
- scoped_ptr<AutoStopTraceSubscriberStdio> subscriber(
- new AutoStopTraceSubscriberStdio(trace_file));
- DCHECK(can_begin_tracing(subscriber.get()));
-
- std::string delay_str = command_line.GetSwitchValueASCII(
- switches::kTraceStartupDuration);
- int delay_secs = 5;
- if (!delay_str.empty() && !base::StringToInt(delay_str, &delay_secs)) {
- DLOG(WARNING) << "Could not parse --" << switches::kTraceStartupDuration
- << "=" << delay_str << " defaulting to 5 (secs)";
- delay_secs = 5;
- }
-
- OnTracingBegan(subscriber.get());
- BrowserThread::PostDelayedTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&AutoStopTraceSubscriberStdio::EndStartupTrace,
- base::Unretained(subscriber.release())),
- base::TimeDelta::FromSeconds(delay_secs));
-}
-
-bool TraceControllerImpl::GetKnownCategoryGroupsAsync(
- TraceSubscriber* subscriber) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- // Known categories come back from child processes with the EndTracingAck
- // message. So to get known categories, just begin and end tracing immediately
- // afterwards. This will ping all the child processes for categories.
- is_get_category_groups_ = true;
- bool success = BeginTracing(subscriber, "*",
- TraceLog::GetInstance()->trace_options()) &&
- EndTracingAsync(subscriber);
- is_get_category_groups_ = success;
- return success;
-}
-
-bool TraceControllerImpl::BeginTracing(TraceSubscriber* subscriber,
- const std::string& category_patterns,
- base::debug::TraceLog::Options options) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (!can_begin_tracing(subscriber))
- return false;
-
- // Enable tracing
- TraceLog::GetInstance()->SetEnabled(
- base::debug::CategoryFilter(category_patterns), options);
-
- OnTracingBegan(subscriber);
-
- return true;
-}
-
-bool TraceControllerImpl::EndTracingAsync(TraceSubscriber* subscriber) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (!can_end_tracing() || subscriber != subscriber_)
- return false;
-
- // Disable local trace early to avoid traces during end-tracing process from
- // interfering with the process.
- TraceLog::GetInstance()->SetDisabled();
-
- // There could be a case where there are no child processes and filters_
- // is empty. In that case we can immediately tell the subscriber that tracing
- // has ended. To avoid recursive calls back to the subscriber, we will just
- // use the existing asynchronous OnEndTracingAck code.
- // Count myself (local trace) in pending_end_ack_count_, acked below.
- pending_end_ack_count_ = filters_.size() + 1;
-
- // Handle special case of zero child processes.
- if (pending_end_ack_count_ == 1) {
- // Ack asynchronously now, because we don't have any children to wait for.
- std::vector<std::string> category_groups;
- TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TraceControllerImpl::OnEndTracingAck,
- base::Unretained(this), category_groups));
- }
-
- // Notify all child processes.
- for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
- it->get()->SendEndTracing();
- }
-
- return true;
-}
-
-bool TraceControllerImpl::GetTraceBufferPercentFullAsync(
- TraceSubscriber* subscriber) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (!can_get_buffer_percent_full() || subscriber != subscriber_)
- return false;
-
- maximum_bpf_ = 0.0f;
- pending_bpf_ack_count_ = filters_.size() + 1;
-
- // Handle special case of zero child processes.
- if (pending_bpf_ack_count_ == 1) {
- // Ack asynchronously now, because we don't have any children to wait for.
- float bpf = TraceLog::GetInstance()->GetBufferPercentFull();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TraceControllerImpl::OnTraceBufferPercentFullReply,
- base::Unretained(this), bpf));
- }
-
- // Message all child processes.
- for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
- it->get()->SendGetTraceBufferPercentFull();
- }
-
- return true;
-}
-
-bool TraceControllerImpl::SetWatchEvent(TraceSubscriber* subscriber,
- const std::string& category_name,
- const std::string& event_name) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (subscriber != subscriber_)
- return false;
-
- watch_category_ = category_name;
- watch_name_ = event_name;
-
- TraceLog::GetInstance()->SetWatchEvent(category_name, event_name);
- for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it)
- it->get()->SendSetWatchEvent(category_name, event_name);
-
- return true;
-}
-
-bool TraceControllerImpl::CancelWatchEvent(TraceSubscriber* subscriber) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (subscriber != subscriber_)
- return false;
-
- watch_category_.clear();
- watch_name_.clear();
-
- TraceLog::GetInstance()->CancelWatchEvent();
- for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it)
- it->get()->SendCancelWatchEvent();
-
- return true;
-}
-
-void TraceControllerImpl::CancelSubscriber(TraceSubscriber* subscriber) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (subscriber == subscriber_) {
- subscriber_ = NULL;
- // End tracing if necessary.
- if (is_tracing_ && pending_end_ack_count_ == 0)
- EndTracingAsync(NULL);
- }
-}
-
-void TraceControllerImpl::AddFilter(TraceMessageFilter* filter) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TraceControllerImpl::AddFilter, base::Unretained(this),
- make_scoped_refptr(filter)));
- return;
- }
-
- filters_.insert(filter);
- if (is_tracing_enabled()) {
- std::string cf_str = category_filter_.ToString();
- filter->SendBeginTracing(cf_str, trace_options_);
- if (!watch_category_.empty())
- filter->SendSetWatchEvent(watch_category_, watch_name_);
- }
-}
-
-void TraceControllerImpl::RemoveFilter(TraceMessageFilter* filter) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TraceControllerImpl::RemoveFilter, base::Unretained(this),
- make_scoped_refptr(filter)));
- return;
- }
-
- filters_.erase(filter);
-}
-
-void TraceControllerImpl::OnTracingBegan(TraceSubscriber* subscriber) {
- is_tracing_ = true;
-
- subscriber_ = subscriber;
-
- category_filter_ = TraceLog::GetInstance()->GetCurrentCategoryFilter();
- trace_options_ = TraceLog::GetInstance()->trace_options();
-
- // Notify all child processes.
- for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
- it->get()->SendBeginTracing(category_filter_.ToString(), trace_options_);
- }
-}
-
-void TraceControllerImpl::OnEndTracingAck(
- const std::vector<std::string>& known_category_groups) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TraceControllerImpl::OnEndTracingAck,
- base::Unretained(this), known_category_groups));
- return;
- }
-
- // Merge known_category_groups with known_category_groups_
- known_category_groups_.insert(known_category_groups.begin(),
- known_category_groups.end());
-
- if (pending_end_ack_count_ == 0)
- return;
-
-
- if (--pending_end_ack_count_ == 1) {
- // All acks from subprocesses have been received. Now flush the local trace.
- // During or after this call, our OnLocalTraceDataCollected will be
- // called with the last of the local trace data.
- TraceLog::GetInstance()->Flush(
- base::Bind(&TraceControllerImpl::OnLocalTraceDataCollected,
- base::Unretained(this)));
- }
-
- if (pending_end_ack_count_ == 0) {
- // All acks (including from the subprocesses and the local trace) have been
- // received.
- is_tracing_ = false;
-
- // Trigger callback if one is set.
- if (subscriber_) {
- if (is_get_category_groups_)
- subscriber_->OnKnownCategoriesCollected(known_category_groups_);
- else
- subscriber_->OnEndTracingComplete();
- // Clear subscriber so that others can use TraceController.
- subscriber_ = NULL;
- }
-
- is_get_category_groups_ = false;
- }
-}
-
-void TraceControllerImpl::OnTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& events_str_ptr) {
- // OnTraceDataCollected may be called from any browser thread, either by the
- // local event trace system or from child processes via TraceMessageFilter.
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TraceControllerImpl::OnTraceDataCollected,
- base::Unretained(this), events_str_ptr));
- return;
- }
-
- // Drop trace events if we are just getting categories.
- if (subscriber_ && !is_get_category_groups_)
- subscriber_->OnTraceDataCollected(events_str_ptr);
-}
-
-void TraceControllerImpl::OnLocalTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& events_str_ptr,
- bool has_more_events) {
- if (events_str_ptr->data().size())
- OnTraceDataCollected(events_str_ptr);
-
- if (!has_more_events) {
- // Simulate an EndTrackingAck for the local trace.
- std::vector<std::string> category_groups;
- TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
- OnEndTracingAck(category_groups);
- }
-}
-
-void TraceControllerImpl::OnTraceNotification(int notification) {
- // OnTraceNotification may be called from any browser thread, either by the
- // local event trace system or from child processes via TraceMessageFilter.
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TraceControllerImpl::OnTraceNotification,
- base::Unretained(this), notification));
- return;
- }
-
- if (notification & base::debug::TraceLog::TRACE_BUFFER_FULL) {
- // EndTracingAsync may return false if tracing is already in the process
- // of being ended. That is ok.
- EndTracingAsync(subscriber_);
- }
- if (notification & base::debug::TraceLog::EVENT_WATCH_NOTIFICATION) {
- if (subscriber_)
- subscriber_->OnEventWatchNotification();
- }
-}
-
-void TraceControllerImpl::OnTraceBufferPercentFullReply(float percent_full) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TraceControllerImpl::OnTraceBufferPercentFullReply,
- base::Unretained(this), percent_full));
- return;
- }
-
- if (pending_bpf_ack_count_ == 0)
- return;
-
- maximum_bpf_ = (maximum_bpf_ > percent_full)? maximum_bpf_ : percent_full;
-
- if (--pending_bpf_ack_count_ == 0) {
- // Trigger callback if one is set.
- if (subscriber_)
- subscriber_->OnTraceBufferPercentFullReply(maximum_bpf_);
- }
-
- if (pending_bpf_ack_count_ == 1) {
- // The last ack represents local trace, so we need to ack it now. Note that
- // this code only executes if there were child processes.
- float bpf = TraceLog::GetInstance()->GetBufferPercentFull();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TraceControllerImpl::OnTraceBufferPercentFullReply,
- base::Unretained(this), bpf));
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/tracing/trace_controller_impl.h b/chromium/content/browser/tracing/trace_controller_impl.h
deleted file mode 100644
index 6f2ccb5d481..00000000000
--- a/chromium/content/browser/tracing/trace_controller_impl.h
+++ /dev/null
@@ -1,109 +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_TRACING_TRACE_CONTROLLER_IMPL_H_
-#define CONTENT_BROWSER_TRACING_TRACE_CONTROLLER_IMPL_H_
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/debug/trace_event.h"
-#include "base/lazy_instance.h"
-#include "content/public/browser/trace_controller.h"
-
-class CommandLine;
-
-namespace content {
-class TraceMessageFilter;
-
-class TraceControllerImpl : public TraceController {
- public:
- static TraceControllerImpl* GetInstance();
-
- // Called on the main thread of the browser process to initialize
- // startup tracing.
- void InitStartupTracing(const CommandLine& command_line);
-
- // TraceController implementation:
- virtual bool BeginTracing(TraceSubscriber* subscriber,
- const std::string& category_patterns,
- base::debug::TraceLog::Options options) OVERRIDE;
- virtual bool EndTracingAsync(TraceSubscriber* subscriber) OVERRIDE;
- virtual bool GetTraceBufferPercentFullAsync(
- TraceSubscriber* subscriber) OVERRIDE;
- virtual bool SetWatchEvent(TraceSubscriber* subscriber,
- const std::string& category_name,
- const std::string& event_name) OVERRIDE;
- virtual bool CancelWatchEvent(TraceSubscriber* subscriber) OVERRIDE;
- virtual void CancelSubscriber(TraceSubscriber* subscriber) OVERRIDE;
- virtual bool GetKnownCategoryGroupsAsync(TraceSubscriber* subscriber)
- OVERRIDE;
-
- private:
- typedef std::set<scoped_refptr<TraceMessageFilter> > FilterMap;
-
- friend struct base::DefaultLazyInstanceTraits<TraceControllerImpl>;
- friend class TraceMessageFilter;
-
- TraceControllerImpl();
- virtual ~TraceControllerImpl();
-
- bool is_tracing_enabled() const {
- return can_end_tracing();
- }
-
- bool can_end_tracing() const {
- return is_tracing_ && pending_end_ack_count_ == 0;
- }
-
- // Can get Buffer Percent Full
- bool can_get_buffer_percent_full() const {
- return is_tracing_ &&
- pending_end_ack_count_ == 0 &&
- pending_bpf_ack_count_ == 0;
- }
-
- bool can_begin_tracing(TraceSubscriber* subscriber) const {
- return !is_tracing_ &&
- (subscriber_ == NULL || subscriber == subscriber_);
- }
-
- // Methods for use by TraceMessageFilter.
-
- void AddFilter(TraceMessageFilter* filter);
- void RemoveFilter(TraceMessageFilter* filter);
- void OnTracingBegan(TraceSubscriber* subscriber);
- void OnEndTracingAck(const std::vector<std::string>& known_category_groups);
- void OnTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& events_str_ptr);
- void OnTraceNotification(int notification);
- void OnTraceBufferPercentFullReply(float percent_full);
-
- // Callback of TraceLog::Flush() for the local trace.
- void OnLocalTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& events_str_ptr,
- bool has_more_events);
-
- FilterMap filters_;
- TraceSubscriber* subscriber_;
- // Pending acks for EndTracingAsync:
- int pending_end_ack_count_;
- // Pending acks for GetTraceBufferPercentFullAsync:
- int pending_bpf_ack_count_;
- float maximum_bpf_;
- bool is_tracing_;
- bool is_get_category_groups_;
- std::set<std::string> known_category_groups_;
- std::string watch_category_;
- std::string watch_name_;
- base::debug::TraceLog::Options trace_options_;
- base::debug::CategoryFilter category_filter_;
-
- DISALLOW_COPY_AND_ASSIGN(TraceControllerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_TRACING_TRACE_CONTROLLER_IMPL_H_
diff --git a/chromium/content/browser/tracing/trace_message_filter.cc b/chromium/content/browser/tracing/trace_message_filter.cc
index e75d786142d..35f23dc1025 100644
--- a/chromium/content/browser/tracing/trace_message_filter.cc
+++ b/chromium/content/browser/tracing/trace_message_filter.cc
@@ -5,33 +5,31 @@
#include "content/browser/tracing/trace_message_filter.h"
#include "components/tracing/tracing_messages.h"
-#include "content/browser/tracing/trace_controller_impl.h"
+#include "content/browser/tracing/tracing_controller_impl.h"
namespace content {
TraceMessageFilter::TraceMessageFilter() :
has_child_(false),
is_awaiting_end_ack_(false),
+ is_awaiting_capture_monitoring_snapshot_ack_(false),
is_awaiting_buffer_percent_full_ack_(false) {
}
-void TraceMessageFilter::OnFilterAdded(IPC::Channel* channel) {
- // Always on IO thread (BrowserMessageFilter guarantee).
- BrowserMessageFilter::OnFilterAdded(channel);
-}
+TraceMessageFilter::~TraceMessageFilter() {}
void TraceMessageFilter::OnChannelClosing() {
- // Always on IO thread (BrowserMessageFilter guarantee).
- BrowserMessageFilter::OnChannelClosing();
-
if (has_child_) {
if (is_awaiting_end_ack_)
OnEndTracingAck(std::vector<std::string>());
+ if (is_awaiting_capture_monitoring_snapshot_ack_)
+ OnCaptureMonitoringSnapshotAcked();
+
if (is_awaiting_buffer_percent_full_ack_)
OnTraceBufferPercentFullReply(0.0f);
- TraceControllerImpl::GetInstance()->RemoveFilter(this);
+ TracingControllerImpl::GetInstance()->RemoveTraceMessageFilter(this);
}
}
@@ -43,10 +41,14 @@ bool TraceMessageFilter::OnMessageReceived(const IPC::Message& message,
IPC_MESSAGE_HANDLER(TracingHostMsg_ChildSupportsTracing,
OnChildSupportsTracing)
IPC_MESSAGE_HANDLER(TracingHostMsg_EndTracingAck, OnEndTracingAck)
+ IPC_MESSAGE_HANDLER(TracingHostMsg_CaptureMonitoringSnapshotAck,
+ OnCaptureMonitoringSnapshotAcked)
IPC_MESSAGE_HANDLER(TracingHostMsg_TraceDataCollected,
OnTraceDataCollected)
- IPC_MESSAGE_HANDLER(TracingHostMsg_TraceNotification,
- OnTraceNotification)
+ IPC_MESSAGE_HANDLER(TracingHostMsg_MonitoringTraceDataCollected,
+ OnMonitoringTraceDataCollected)
+ IPC_MESSAGE_HANDLER(TracingHostMsg_WatchEventMatched,
+ OnWatchEventMatched)
IPC_MESSAGE_HANDLER(TracingHostMsg_TraceBufferPercentFullReply,
OnTraceBufferPercentFullReply)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -70,6 +72,27 @@ void TraceMessageFilter::SendEndTracing() {
Send(new TracingMsg_EndTracing);
}
+void TraceMessageFilter::SendEnableMonitoring(
+ const std::string& category_filter_str,
+ base::debug::TraceLog::Options options) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ Send(new TracingMsg_EnableMonitoring(category_filter_str,
+ base::TimeTicks::NowFromSystemTraceTime(),
+ options));
+}
+
+void TraceMessageFilter::SendDisableMonitoring() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ Send(new TracingMsg_DisableMonitoring);
+}
+
+void TraceMessageFilter::SendCaptureMonitoringSnapshot() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!is_awaiting_capture_monitoring_snapshot_ack_);
+ is_awaiting_capture_monitoring_snapshot_ack_ = true;
+ Send(new TracingMsg_CaptureMonitoringSnapshot);
+}
+
void TraceMessageFilter::SendGetTraceBufferPercentFull() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!is_awaiting_buffer_percent_full_ack_);
@@ -86,11 +109,9 @@ void TraceMessageFilter::SendCancelWatchEvent() {
Send(new TracingMsg_CancelWatchEvent);
}
-TraceMessageFilter::~TraceMessageFilter() {}
-
void TraceMessageFilter::OnChildSupportsTracing() {
has_child_ = true;
- TraceControllerImpl::GetInstance()->AddFilter(this);
+ TracingControllerImpl::GetInstance()->AddTraceMessageFilter(this);
}
void TraceMessageFilter::OnEndTracingAck(
@@ -99,7 +120,19 @@ void TraceMessageFilter::OnEndTracingAck(
// child process is compromised.
if (is_awaiting_end_ack_) {
is_awaiting_end_ack_ = false;
- TraceControllerImpl::GetInstance()->OnEndTracingAck(known_categories);
+ TracingControllerImpl::GetInstance()->OnDisableRecordingAcked(
+ known_categories);
+ } else {
+ NOTREACHED();
+ }
+}
+
+void TraceMessageFilter::OnCaptureMonitoringSnapshotAcked() {
+ // is_awaiting_capture_monitoring_snapshot_ack_ should always be true here,
+ // but check in case the child process is compromised.
+ if (is_awaiting_capture_monitoring_snapshot_ack_) {
+ is_awaiting_capture_monitoring_snapshot_ack_ = false;
+ TracingControllerImpl::GetInstance()->OnCaptureMonitoringSnapshotAcked();
} else {
NOTREACHED();
}
@@ -108,17 +141,25 @@ void TraceMessageFilter::OnEndTracingAck(
void TraceMessageFilter::OnTraceDataCollected(const std::string& data) {
scoped_refptr<base::RefCountedString> data_ptr(new base::RefCountedString());
data_ptr->data() = data;
- TraceControllerImpl::GetInstance()->OnTraceDataCollected(data_ptr);
+ TracingControllerImpl::GetInstance()->OnTraceDataCollected(data_ptr);
+}
+
+void TraceMessageFilter::OnMonitoringTraceDataCollected(
+ const std::string& data) {
+ scoped_refptr<base::RefCountedString> data_ptr(new base::RefCountedString());
+ data_ptr->data() = data;
+ TracingControllerImpl::GetInstance()->OnMonitoringTraceDataCollected(
+ data_ptr);
}
-void TraceMessageFilter::OnTraceNotification(int notification) {
- TraceControllerImpl::GetInstance()->OnTraceNotification(notification);
+void TraceMessageFilter::OnWatchEventMatched() {
+ TracingControllerImpl::GetInstance()->OnWatchEventMatched();
}
void TraceMessageFilter::OnTraceBufferPercentFullReply(float percent_full) {
if (is_awaiting_buffer_percent_full_ack_) {
is_awaiting_buffer_percent_full_ack_ = false;
- TraceControllerImpl::GetInstance()->OnTraceBufferPercentFullReply(
+ TracingControllerImpl::GetInstance()->OnTraceBufferPercentFullReply(
percent_full);
} else {
NOTREACHED();
diff --git a/chromium/content/browser/tracing/trace_message_filter.h b/chromium/content/browser/tracing/trace_message_filter.h
index 41fd017827f..0f9e18ed9c3 100644
--- a/chromium/content/browser/tracing/trace_message_filter.h
+++ b/chromium/content/browser/tracing/trace_message_filter.h
@@ -20,9 +20,6 @@ class TraceMessageFilter : public BrowserMessageFilter {
public:
TraceMessageFilter();
- // BrowserMessageFilter override.
- virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE;
-
// BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message,
@@ -31,6 +28,10 @@ class TraceMessageFilter : public BrowserMessageFilter {
void SendBeginTracing(const std::string& category_filter_str,
base::debug::TraceLog::Options options);
void SendEndTracing();
+ void SendEnableMonitoring(const std::string& category_filter_str,
+ base::debug::TraceLog::Options options);
+ void SendDisableMonitoring();
+ void SendCaptureMonitoringSnapshot();
void SendGetTraceBufferPercentFull();
void SendSetWatchEvent(const std::string& category_name,
const std::string& event_name);
@@ -43,15 +44,19 @@ class TraceMessageFilter : public BrowserMessageFilter {
// Message handlers.
void OnChildSupportsTracing();
void OnEndTracingAck(const std::vector<std::string>& known_categories);
- void OnTraceNotification(int notification);
+ void OnCaptureMonitoringSnapshotAcked();
+ void OnWatchEventMatched();
void OnTraceBufferPercentFullReply(float percent_full);
void OnTraceDataCollected(const std::string& data);
+ void OnMonitoringTraceDataCollected(const std::string& data);
// ChildTraceMessageFilter exists:
bool has_child_;
// Awaiting ack for previously sent SendEndTracing
bool is_awaiting_end_ack_;
+ // Awaiting ack for previously sent SendCaptureMonitoringSnapshot
+ bool is_awaiting_capture_monitoring_snapshot_ack_;
// Awaiting ack for previously sent SendGetTraceBufferPercentFull
bool is_awaiting_buffer_percent_full_ack_;
diff --git a/chromium/content/browser/tracing/trace_subscriber_stdio.cc b/chromium/content/browser/tracing/trace_subscriber_stdio.cc
deleted file mode 100644
index 2c6aede56ce..00000000000
--- a/chromium/content/browser/tracing/trace_subscriber_stdio.cc
+++ /dev/null
@@ -1,201 +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/tracing/trace_subscriber_stdio.h"
-
-#include "base/bind.h"
-#include "base/debug/trace_event.h"
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-
-// All method calls on this class are done on a SequencedWorkerPool thread.
-class TraceSubscriberStdio::TraceSubscriberStdioWorker
- : public base::RefCountedThreadSafe<TraceSubscriberStdioWorker> {
- public:
- TraceSubscriberStdioWorker(const base::FilePath& path,
- FileType file_type,
- bool has_system_trace)
- : path_(path),
- file_type_(file_type),
- has_system_trace_(has_system_trace),
- file_(0),
- needs_comma_(false),
- wrote_trace_(false),
- has_pending_system_trace_(false),
- wrote_system_trace_(false) {}
-
- void OnTraceStart() {
- DCHECK(!file_);
- file_ = file_util::OpenFile(path_, "w+");
- if (!IsValid()) {
- LOG(ERROR) << "Failed to open performance trace file: " << path_.value();
- return;
- }
-
- LOG(INFO) << "Logging performance trace to file: " << path_.value();
- if (file_type_ == FILE_TYPE_PROPERTY_LIST)
- WriteString("{\"traceEvents\":");
- WriteString("[");
- }
-
- void OnTraceData(const scoped_refptr<base::RefCountedString>& data_ptr) {
- if (!IsValid())
- return;
- DCHECK(!data_ptr->data().empty());
- if (needs_comma_)
- WriteString(",");
- WriteString(data_ptr->data());
- needs_comma_ = true;
- }
-
- void OnSystemTraceData(
- const scoped_refptr<base::RefCountedString>& data_ptr) {
- if (wrote_trace_) {
- WriteSystemTrace(data_ptr);
- End();
- } else {
- pending_system_trace_ = data_ptr;
- has_pending_system_trace_ = true;
- }
- }
-
- void OnTraceEnd() {
- if (!IsValid())
- return;
- WriteString("]");
-
- wrote_trace_ = true;
-
- if (!has_system_trace_ || wrote_system_trace_) {
- End();
- return;
- }
-
- WriteString(",");
- if (has_pending_system_trace_) {
- WriteSystemTrace(pending_system_trace_);
- End();
- }
- }
-
- private:
- friend class base::RefCountedThreadSafe<TraceSubscriberStdioWorker>;
-
- ~TraceSubscriberStdioWorker() {
- CloseFile();
- }
-
- bool IsValid() const {
- return file_ && (0 == ferror(file_));
- }
-
- void CloseFile() {
- if (file_) {
- fclose(file_);
- file_ = 0;
-
- }
- }
-
- void End() {
- if (file_type_ == FILE_TYPE_PROPERTY_LIST)
- WriteString("}");
- CloseFile();
- }
-
- void WriteSystemTrace(const scoped_refptr<base::RefCountedString>& data_ptr) {
- // Newlines need to be replaced with the string "\n" to be parsed correctly.
- // Double quotes need to be replaced with the string "\"".
- // System logs are ASCII.
- const std::string& data = data_ptr->data();
- const char* chars = data.c_str();
- WriteString("\"systemTraceEvents\":\"");
- size_t old_index = 0;
- for (size_t new_index = data.find_first_of("\n\"");
- std::string::npos != new_index;
- old_index = new_index + 1,
- new_index = data.find_first_of("\n\"", old_index)) {
- WriteChars(chars + old_index, new_index - old_index);
- if (chars[new_index] == '\n')
- WriteChars("\\n", 2);
- else
- WriteChars("\\\"", 2);
- }
- WriteChars(chars + old_index, data.size() - old_index);
- WriteString("\"");
- wrote_system_trace_ = true;
- }
-
- void WriteChars(const char* output_chars, size_t size) {
- if (size == 0)
- return;
-
- if (IsValid()) {
- size_t written = fwrite(output_chars, 1, size, file_);
- if (written != size) {
- LOG(ERROR) << "Error " << ferror(file_) << " in fwrite() to trace file";
- CloseFile();
- }
- }
- }
-
- void WriteString(const std::string& output_str) {
- WriteChars(output_str.data(), output_str.size());
- }
-
- base::FilePath path_;
- const FileType file_type_;
- const bool has_system_trace_;
- FILE* file_;
- bool needs_comma_;
- bool wrote_trace_;
- bool has_pending_system_trace_;
- bool wrote_system_trace_;
- scoped_refptr<base::RefCountedString> pending_system_trace_;
- DISALLOW_COPY_AND_ASSIGN(TraceSubscriberStdioWorker);
-};
-
-TraceSubscriberStdio::TraceSubscriberStdio(const base::FilePath& path,
- FileType file_type,
- bool has_system_trace)
- : worker_(new TraceSubscriberStdioWorker(path,
- file_type,
- has_system_trace)) {
- if (has_system_trace)
- CHECK_EQ(FILE_TYPE_PROPERTY_LIST, file_type);
- BrowserThread::PostBlockingPoolSequencedTask(
- __FILE__, FROM_HERE,
- base::Bind(&TraceSubscriberStdioWorker::OnTraceStart, worker_));
-}
-
-TraceSubscriberStdio::~TraceSubscriberStdio() {
-}
-
-void TraceSubscriberStdio::OnEndTracingComplete() {
- BrowserThread::PostBlockingPoolSequencedTask(
- __FILE__, FROM_HERE,
- base::Bind(&TraceSubscriberStdioWorker::OnTraceEnd, worker_));
-}
-
-void TraceSubscriberStdio::OnTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& data_ptr) {
- BrowserThread::PostBlockingPoolSequencedTask(
- __FILE__, FROM_HERE,
- base::Bind(&TraceSubscriberStdioWorker::OnTraceData, worker_, data_ptr));
-}
-
-void TraceSubscriberStdio::OnEndSystemTracing(
- const scoped_refptr<base::RefCountedString>& events_str_ptr) {
- BrowserThread::PostBlockingPoolSequencedTask(
- __FILE__, FROM_HERE,
- base::Bind(&TraceSubscriberStdioWorker::OnSystemTraceData,
- worker_,
- events_str_ptr));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/tracing/trace_subscriber_stdio.h b/chromium/content/browser/tracing/trace_subscriber_stdio.h
deleted file mode 100644
index b9fc4f74c19..00000000000
--- a/chromium/content/browser/tracing/trace_subscriber_stdio.h
+++ /dev/null
@@ -1,57 +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_TRACING_TRACE_SUBSCRIBER_STDIO_H_
-#define CONTENT_BROWSER_TRACING_TRACE_SUBSCRIBER_STDIO_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "content/public/browser/trace_subscriber.h"
-#include "content/common/content_export.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace content {
-
-// Stdio implementation of TraceSubscriber. Use this to write traces to a file.
-class CONTENT_EXPORT TraceSubscriberStdio
- : NON_EXPORTED_BASE(public TraceSubscriber) {
- public:
- enum FileType {
- // Output file as array, representing trace events:
- // [event1, event2, ...]
- FILE_TYPE_ARRAY,
- // Output file as property list with one or two items:
- // {traceEvents: [event1, event2, ...],
- // systemTraceEvents: "event1\nevent2\n..." // optional}
- FILE_TYPE_PROPERTY_LIST
- };
-
- // has_system_trace indicates whether system trace events are expected.
- TraceSubscriberStdio(const base::FilePath& path,
- FileType file_type,
- bool has_system_trace);
- virtual ~TraceSubscriberStdio();
-
- // Implementation of TraceSubscriber
- virtual void OnEndTracingComplete() OVERRIDE;
- virtual void OnTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& data_ptr) OVERRIDE;
-
- // To be used as callback to DebugDaemonClient::RequestStopSystemTracing().
- virtual void OnEndSystemTracing(
- const scoped_refptr<base::RefCountedString>& events_str_ptr);
-
- private:
- class TraceSubscriberStdioWorker;
- scoped_refptr<TraceSubscriberStdioWorker> worker_;
- DISALLOW_COPY_AND_ASSIGN(TraceSubscriberStdio);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_TRACING_TRACE_SUBSCRIBER_STDIO_H_
diff --git a/chromium/content/browser/tracing/trace_subscriber_stdio_unittest.cc b/chromium/content/browser/tracing/trace_subscriber_stdio_unittest.cc
deleted file mode 100644
index 10e51a968df..00000000000
--- a/chromium/content/browser/tracing/trace_subscriber_stdio_unittest.cc
+++ /dev/null
@@ -1,132 +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/tracing/trace_subscriber_stdio.h"
-
-#include "base/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "content/public/browser/browser_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class TraceSubscriberStdioTest : public ::testing::Test {};
-
-TEST_F(TraceSubscriberStdioTest, CanWriteArray) {
- base::ScopedTempDir trace_dir;
- ASSERT_TRUE(trace_dir.CreateUniqueTempDir());
- base::FilePath trace_file(trace_dir.path().AppendASCII("trace.txt"));
- {
- TraceSubscriberStdio subscriber(trace_file,
- TraceSubscriberStdio::FILE_TYPE_ARRAY,
- false);
-
- std::string foo("foo");
- subscriber.OnTraceDataCollected(
- make_scoped_refptr(base::RefCountedString::TakeString(&foo)));
-
- std::string bar("bar");
- subscriber.OnTraceDataCollected(
- make_scoped_refptr(base::RefCountedString::TakeString(&bar)));
-
- subscriber.OnEndTracingComplete();
- }
- BrowserThread::GetBlockingPool()->FlushForTesting();
- std::string result;
- EXPECT_TRUE(base::ReadFileToString(trace_file, &result));
- EXPECT_EQ("[foo,bar]", result);
-}
-
-TEST_F(TraceSubscriberStdioTest, CanWritePropertyList) {
- base::ScopedTempDir trace_dir;
- ASSERT_TRUE(trace_dir.CreateUniqueTempDir());
- base::FilePath trace_file(trace_dir.path().AppendASCII("trace.txt"));
- {
- TraceSubscriberStdio subscriber(
- trace_file,
- TraceSubscriberStdio::FILE_TYPE_PROPERTY_LIST,
- false);
-
- std::string foo("foo");
- subscriber.OnTraceDataCollected(
- make_scoped_refptr(base::RefCountedString::TakeString(&foo)));
-
- std::string bar("bar");
- subscriber.OnTraceDataCollected(
- make_scoped_refptr(base::RefCountedString::TakeString(&bar)));
-
- subscriber.OnEndTracingComplete();
- }
- BrowserThread::GetBlockingPool()->FlushForTesting();
- std::string result;
- EXPECT_TRUE(base::ReadFileToString(trace_file, &result));
- EXPECT_EQ("{\"traceEvents\":[foo,bar]}", result);
-}
-
-TEST_F(TraceSubscriberStdioTest, CanWriteSystemDataFirst) {
- base::ScopedTempDir trace_dir;
- ASSERT_TRUE(trace_dir.CreateUniqueTempDir());
- base::FilePath trace_file(trace_dir.path().AppendASCII("trace.txt"));
- {
- TraceSubscriberStdio subscriber(
- trace_file,
- TraceSubscriberStdio::FILE_TYPE_PROPERTY_LIST,
- true);
-
- std::string foo("foo");
- subscriber.OnTraceDataCollected(
- make_scoped_refptr(base::RefCountedString::TakeString(&foo)));
-
- std::string bar("bar");
- subscriber.OnTraceDataCollected(
- make_scoped_refptr(base::RefCountedString::TakeString(&bar)));
-
- std::string systemTrace("event1\nev\"ent\"2\n");
- subscriber.OnEndSystemTracing(
- make_scoped_refptr(base::RefCountedString::TakeString(&systemTrace)));
- subscriber.OnEndTracingComplete();
- }
- BrowserThread::GetBlockingPool()->FlushForTesting();
- std::string result;
- EXPECT_TRUE(base::ReadFileToString(trace_file, &result));
- EXPECT_EQ(
- "{\"traceEvents\":[foo,bar],\""
- "systemTraceEvents\":\"event1\\nev\\\"ent\\\"2\\n\"}",
- result);
-}
-
-TEST_F(TraceSubscriberStdioTest, CanWriteSystemDataLast) {
- base::ScopedTempDir trace_dir;
- ASSERT_TRUE(trace_dir.CreateUniqueTempDir());
- base::FilePath trace_file(trace_dir.path().AppendASCII("trace.txt"));
- {
- TraceSubscriberStdio subscriber(
- trace_file,
- TraceSubscriberStdio::FILE_TYPE_PROPERTY_LIST,
- true);
-
- std::string foo("foo");
- subscriber.OnTraceDataCollected(
- make_scoped_refptr(base::RefCountedString::TakeString(&foo)));
-
- std::string bar("bar");
- subscriber.OnTraceDataCollected(
- make_scoped_refptr(base::RefCountedString::TakeString(&bar)));
-
- std::string systemTrace("event1\nev\"ent\"2\n");
- subscriber.OnEndTracingComplete();
- subscriber.OnEndSystemTracing(
- make_scoped_refptr(base::RefCountedString::TakeString(&systemTrace)));
- }
- BrowserThread::GetBlockingPool()->FlushForTesting();
- std::string result;
- EXPECT_TRUE(base::ReadFileToString(trace_file, &result));
- EXPECT_EQ(
- "{\"traceEvents\":[foo,bar],\""
- "systemTraceEvents\":\"event1\\nev\\\"ent\\\"2\\n\"}",
- result);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/tracing/tracing_controller_browsertest.cc b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
index c88932e0597..bccf90af44a 100644
--- a/chromium/content/browser/tracing/tracing_controller_browsertest.cc
+++ b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
@@ -20,6 +20,9 @@ class TracingControllerTest : public ContentBrowserTest {
get_categories_done_callback_count_ = 0;
enable_recording_done_callback_count_ = 0;
disable_recording_done_callback_count_ = 0;
+ enable_monitoring_done_callback_count_ = 0;
+ disable_monitoring_done_callback_count_ = 0;
+ capture_monitoring_snapshot_done_callback_count_ = 0;
ContentBrowserTest::SetUp();
}
@@ -44,10 +47,35 @@ class TracingControllerTest : public ContentBrowserTest {
}
void DisableRecordingDoneCallbackTest(base::Closure quit_callback,
- scoped_ptr<base::FilePath> file_path) {
+ const base::FilePath& file_path) {
disable_recording_done_callback_count_++;
- EXPECT_TRUE(PathExists(*file_path));
+ EXPECT_TRUE(PathExists(file_path));
+ int64 file_size;
+ base::GetFileSize(file_path, &file_size);
+ EXPECT_TRUE(file_size > 0);
quit_callback.Run();
+ last_actual_recording_file_path_ = file_path;
+ }
+
+ void EnableMonitoringDoneCallbackTest(base::Closure quit_callback) {
+ enable_monitoring_done_callback_count_++;
+ quit_callback.Run();
+ }
+
+ void DisableMonitoringDoneCallbackTest(base::Closure quit_callback) {
+ disable_monitoring_done_callback_count_++;
+ quit_callback.Run();
+ }
+
+ void CaptureMonitoringSnapshotDoneCallbackTest(
+ base::Closure quit_callback, const base::FilePath& file_path) {
+ capture_monitoring_snapshot_done_callback_count_++;
+ EXPECT_TRUE(PathExists(file_path));
+ int64 file_size;
+ base::GetFileSize(file_path, &file_size);
+ EXPECT_TRUE(file_size > 0);
+ quit_callback.Run();
+ last_actual_monitoring_file_path_ = file_path;
}
int get_categories_done_callback_count() const {
@@ -62,10 +90,111 @@ class TracingControllerTest : public ContentBrowserTest {
return disable_recording_done_callback_count_;
}
+ int enable_monitoring_done_callback_count() const {
+ return enable_monitoring_done_callback_count_;
+ }
+
+ int disable_monitoring_done_callback_count() const {
+ return disable_monitoring_done_callback_count_;
+ }
+
+ int capture_monitoring_snapshot_done_callback_count() const {
+ return capture_monitoring_snapshot_done_callback_count_;
+ }
+
+ base::FilePath last_actual_recording_file_path() const {
+ return last_actual_recording_file_path_;
+ }
+
+ base::FilePath last_actual_monitoring_file_path() const {
+ return last_actual_monitoring_file_path_;
+ }
+
+ void TestEnableAndDisableRecording(const base::FilePath& result_file_path) {
+ Navigate(shell());
+
+ TracingController* controller = TracingController::GetInstance();
+
+ {
+ base::RunLoop run_loop;
+ TracingController::EnableRecordingDoneCallback callback =
+ base::Bind(&TracingControllerTest::EnableRecordingDoneCallbackTest,
+ base::Unretained(this),
+ run_loop.QuitClosure());
+ bool result = controller->EnableRecording(
+ "", TracingController::DEFAULT_OPTIONS, callback);
+ ASSERT_TRUE(result);
+ run_loop.Run();
+ EXPECT_EQ(enable_recording_done_callback_count(), 1);
+ }
+
+ {
+ base::RunLoop run_loop;
+ TracingController::TracingFileResultCallback callback =
+ base::Bind(&TracingControllerTest::DisableRecordingDoneCallbackTest,
+ base::Unretained(this),
+ run_loop.QuitClosure());
+ bool result = controller->DisableRecording(result_file_path, callback);
+ ASSERT_TRUE(result);
+ run_loop.Run();
+ EXPECT_EQ(disable_recording_done_callback_count(), 1);
+ }
+ }
+
+ void TestEnableCaptureAndDisableMonitoring(
+ const base::FilePath& result_file_path) {
+ Navigate(shell());
+
+ TracingController* controller = TracingController::GetInstance();
+
+ {
+ base::RunLoop run_loop;
+ TracingController::EnableMonitoringDoneCallback callback =
+ base::Bind(&TracingControllerTest::EnableMonitoringDoneCallbackTest,
+ base::Unretained(this),
+ run_loop.QuitClosure());
+ bool result = controller->EnableMonitoring(
+ "", TracingController::ENABLE_SAMPLING, callback);
+ ASSERT_TRUE(result);
+ run_loop.Run();
+ EXPECT_EQ(enable_monitoring_done_callback_count(), 1);
+ }
+
+ {
+ base::RunLoop run_loop;
+ TracingController::TracingFileResultCallback callback =
+ base::Bind(&TracingControllerTest::
+ CaptureMonitoringSnapshotDoneCallbackTest,
+ base::Unretained(this),
+ run_loop.QuitClosure());
+ ASSERT_TRUE(controller->CaptureMonitoringSnapshot(result_file_path,
+ callback));
+ run_loop.Run();
+ EXPECT_EQ(capture_monitoring_snapshot_done_callback_count(), 1);
+ }
+
+ {
+ base::RunLoop run_loop;
+ TracingController::DisableMonitoringDoneCallback callback =
+ base::Bind(&TracingControllerTest::DisableMonitoringDoneCallbackTest,
+ base::Unretained(this),
+ run_loop.QuitClosure());
+ bool result = controller->DisableMonitoring(callback);
+ ASSERT_TRUE(result);
+ run_loop.Run();
+ EXPECT_EQ(disable_monitoring_done_callback_count(), 1);
+ }
+ }
+
private:
int get_categories_done_callback_count_;
int enable_recording_done_callback_count_;
int disable_recording_done_callback_count_;
+ int enable_monitoring_done_callback_count_;
+ int disable_monitoring_done_callback_count_;
+ int capture_monitoring_snapshot_done_callback_count_;
+ base::FilePath last_actual_recording_file_path_;
+ base::FilePath last_actual_monitoring_file_path_;
};
IN_PROC_BROWSER_TEST_F(TracingControllerTest, GetCategories) {
@@ -78,38 +207,64 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, GetCategories) {
base::Bind(&TracingControllerTest::GetCategoriesDoneCallbackTest,
base::Unretained(this),
run_loop.QuitClosure());
- controller->GetCategories(callback);
+ ASSERT_TRUE(controller->GetCategories(callback));
run_loop.Run();
EXPECT_EQ(get_categories_done_callback_count(), 1);
}
IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableAndDisableRecording) {
+ TestEnableAndDisableRecording(base::FilePath());
+}
+
+IN_PROC_BROWSER_TEST_F(TracingControllerTest,
+ EnableAndDisableRecordingWithFilePath) {
+ base::FilePath file_path;
+ base::CreateTemporaryFile(&file_path);
+ TestEnableAndDisableRecording(file_path);
+ EXPECT_EQ(file_path.value(), last_actual_recording_file_path().value());
+}
+
+IN_PROC_BROWSER_TEST_F(TracingControllerTest,
+ EnableAndDisableRecordingWithEmptyFileAndNullCallback) {
Navigate(shell());
TracingController* controller = TracingController::GetInstance();
+ EXPECT_TRUE(controller->EnableRecording(
+ "", TracingController::DEFAULT_OPTIONS,
+ TracingController::EnableRecordingDoneCallback()));
+ EXPECT_TRUE(controller->DisableRecording(
+ base::FilePath(), TracingController::TracingFileResultCallback()));
+ base::RunLoop().RunUntilIdle();
+}
- {
- base::RunLoop run_loop;
- TracingController::EnableRecordingDoneCallback callback =
- base::Bind(&TracingControllerTest::EnableRecordingDoneCallbackTest,
- base::Unretained(this),
- run_loop.QuitClosure());
- controller->EnableRecording(base::debug::CategoryFilter("*"),
- TracingController::Options(), callback);
- run_loop.Run();
- EXPECT_EQ(enable_recording_done_callback_count(), 1);
- }
-
- {
- base::RunLoop run_loop;
- TracingController::TracingFileResultCallback callback =
- base::Bind(&TracingControllerTest::DisableRecordingDoneCallbackTest,
- base::Unretained(this),
- run_loop.QuitClosure());
- controller->DisableRecording(callback);
- run_loop.Run();
- EXPECT_EQ(disable_recording_done_callback_count(), 1);
- }
+IN_PROC_BROWSER_TEST_F(TracingControllerTest,
+ EnableCaptureAndDisableMonitoring) {
+ TestEnableCaptureAndDisableMonitoring(base::FilePath());
+}
+
+IN_PROC_BROWSER_TEST_F(TracingControllerTest,
+ EnableCaptureAndDisableMonitoringWithFilePath) {
+ base::FilePath file_path;
+ base::CreateTemporaryFile(&file_path);
+ TestEnableCaptureAndDisableMonitoring(file_path);
+ EXPECT_EQ(file_path.value(), last_actual_monitoring_file_path().value());
+}
+
+IN_PROC_BROWSER_TEST_F(
+ TracingControllerTest,
+ EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback) {
+ Navigate(shell());
+
+ TracingController* controller = TracingController::GetInstance();
+ EXPECT_TRUE(controller->EnableMonitoring(
+ "", TracingController::ENABLE_SAMPLING,
+ TracingController::EnableMonitoringDoneCallback()));
+ controller->CaptureMonitoringSnapshot(
+ base::FilePath(), TracingController::TracingFileResultCallback());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(controller->DisableMonitoring(
+ TracingController::DisableMonitoringDoneCallback()));
+ base::RunLoop().RunUntilIdle();
}
} // namespace content
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.cc b/chromium/content/browser/tracing/tracing_controller_impl.cc
index 1c1c43aabf9..bc7cee2f930 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -5,6 +5,7 @@
#include "content/browser/tracing/tracing_controller_impl.h"
#include "base/bind.h"
+#include "base/debug/trace_event.h"
#include "base/file_util.h"
#include "base/json/string_escape.h"
#include "base/strings/string_number_conversions.h"
@@ -28,11 +29,97 @@ TracingController* TracingController::GetInstance() {
return TracingControllerImpl::GetInstance();
}
+class TracingControllerImpl::ResultFile {
+ public:
+ explicit ResultFile(const base::FilePath& path);
+ void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) {
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&TracingControllerImpl::ResultFile::WriteTask,
+ base::Unretained(this), events_str_ptr));
+ }
+ void Close(const base::Closure& callback) {
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&TracingControllerImpl::ResultFile::CloseTask,
+ base::Unretained(this), callback));
+ }
+ const base::FilePath& path() const { return path_; }
+
+ private:
+ void OpenTask();
+ void WriteTask(const scoped_refptr<base::RefCountedString>& events_str_ptr);
+ void CloseTask(const base::Closure& callback);
+
+ FILE* file_;
+ base::FilePath path_;
+ bool has_at_least_one_result_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResultFile);
+};
+
+TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path)
+ : file_(NULL),
+ path_(path),
+ has_at_least_one_result_(false) {
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&TracingControllerImpl::ResultFile::OpenTask,
+ base::Unretained(this)));
+}
+
+void TracingControllerImpl::ResultFile::OpenTask() {
+ if (path_.empty())
+ base::CreateTemporaryFile(&path_);
+ file_ = base::OpenFile(path_, "w");
+ if (!file_) {
+ LOG(ERROR) << "Failed to open " << path_.value();
+ return;
+ }
+ const char* preamble = "{\"traceEvents\": [";
+ size_t written = fwrite(preamble, strlen(preamble), 1, file_);
+ DCHECK(written == 1);
+}
+
+void TracingControllerImpl::ResultFile::WriteTask(
+ const scoped_refptr<base::RefCountedString>& events_str_ptr) {
+ if (!file_)
+ return;
+
+ // If there is already a result in the file, then put a commma
+ // before the next batch of results.
+ if (has_at_least_one_result_) {
+ size_t written = fwrite(",", 1, 1, file_);
+ DCHECK(written == 1);
+ }
+ has_at_least_one_result_ = true;
+ size_t written = fwrite(events_str_ptr->data().c_str(),
+ events_str_ptr->data().size(), 1,
+ file_);
+ DCHECK(written == 1);
+}
+
+void TracingControllerImpl::ResultFile::CloseTask(
+ const base::Closure& callback) {
+ if (!file_)
+ return;
+
+ const char* trailout = "]}";
+ size_t written = fwrite(trailout, strlen(trailout), 1, file_);
+ DCHECK(written == 1);
+ base::CloseFile(file_);
+ file_ = NULL;
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
+}
+
+
TracingControllerImpl::TracingControllerImpl() :
- pending_end_ack_count_(0),
- is_recording_(false),
- category_filter_(
- base::debug::CategoryFilter::kDefaultCategoryFilterString) {
+ pending_disable_recording_ack_count_(0),
+ pending_capture_monitoring_snapshot_ack_count_(0),
+ pending_trace_buffer_percent_full_ack_count_(0),
+ maximum_trace_buffer_percent_full_(0),
+ // Tracing may have been enabled by ContentMainRunner if kTraceStartup
+ // is specified in command line.
+ is_recording_(TraceLog::GetInstance()->IsEnabled()),
+ is_monitoring_(false) {
}
TracingControllerImpl::~TracingControllerImpl() {
@@ -44,7 +131,7 @@ TracingControllerImpl* TracingControllerImpl::GetInstance() {
return g_controller.Pointer();
}
-void TracingControllerImpl::GetCategories(
+bool TracingControllerImpl::GetCategories(
const GetCategoriesDoneCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -52,42 +139,61 @@ void TracingControllerImpl::GetCategories(
// message. So to get known categories, just begin and end tracing immediately
// afterwards. This will ping all the child processes for categories.
pending_get_categories_done_callback_ = callback;
- EnableRecording(base::debug::CategoryFilter("*"),
- TracingController::Options(),
- EnableRecordingDoneCallback());
- DisableRecording(TracingFileResultCallback());
+ if (!EnableRecording("*", TracingController::Options(),
+ EnableRecordingDoneCallback())) {
+ pending_get_categories_done_callback_.Reset();
+ return false;
+ }
+
+ bool ok = DisableRecording(base::FilePath(), TracingFileResultCallback());
+ DCHECK(ok);
+ return true;
}
-void TracingControllerImpl::EnableRecording(
- const base::debug::CategoryFilter& filter,
+bool TracingControllerImpl::EnableRecording(
+ const std::string& category_filter,
TracingController::Options options,
const EnableRecordingDoneCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!can_enable_recording())
- return;
-
- trace_options_ = TraceLog::GetInstance()->trace_options();
- TraceLog::GetInstance()->SetEnabled(filter, trace_options_);
+ return false;
+
+#if defined(OS_ANDROID)
+ if (pending_get_categories_done_callback_.is_null())
+ TraceLog::GetInstance()->AddClockSyncMetadataEvent();
+#endif
+
+ TraceLog::Options trace_options = (options & RECORD_CONTINUOUSLY) ?
+ TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL;
+ if (options & ENABLE_SAMPLING) {
+ trace_options = static_cast<TraceLog::Options>(
+ trace_options | TraceLog::ENABLE_SAMPLING);
+ }
+ // TODO(haraken): How to handle ENABLE_SYSTRACE?
+ TraceLog::GetInstance()->SetEnabled(
+ base::debug::CategoryFilter(category_filter), trace_options);
is_recording_ = true;
- category_filter_ = TraceLog::GetInstance()->GetCurrentCategoryFilter();
// Notify all child processes.
- for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
- it->get()->SendBeginTracing(category_filter_.ToString(), trace_options_);
+ for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
+ it != trace_message_filters_.end(); ++it) {
+ it->get()->SendBeginTracing(category_filter, trace_options);
}
if (!callback.is_null())
callback.Run();
+ return true;
}
-void TracingControllerImpl::DisableRecording(
+bool TracingControllerImpl::DisableRecording(
+ const base::FilePath& result_file_path,
const TracingFileResultCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!can_end_recording())
- return;
+ if (!can_disable_recording())
+ return false;
pending_disable_recording_done_callback_ = callback;
@@ -95,22 +201,22 @@ void TracingControllerImpl::DisableRecording(
// interfering with the process.
TraceLog::GetInstance()->SetDisabled();
- // We don't need to create a temporary file when getting categories.
- if (pending_get_categories_done_callback_.is_null()) {
- base::FilePath temporary_file;
- file_util::CreateTemporaryFile(&temporary_file);
- recording_result_file_.reset(new base::FilePath(temporary_file));
- }
+#if defined(OS_ANDROID)
+ if (pending_get_categories_done_callback_.is_null())
+ TraceLog::GetInstance()->AddClockSyncMetadataEvent();
+#endif
- // There could be a case where there are no child processes and filters_
- // is empty. In that case we can immediately tell the subscriber that tracing
- // has ended. To avoid recursive calls back to the subscriber, we will just
- // use the existing asynchronous OnDisableRecordingAcked code.
- // Count myself (local trace) in pending_end_ack_count_, acked below.
- pending_end_ack_count_ = filters_.size() + 1;
+ if (!callback.is_null() || !result_file_path.empty())
+ result_file_.reset(new ResultFile(result_file_path));
- // Handle special case of zero child processes.
- if (pending_end_ack_count_ == 1) {
+ // Count myself (local trace) in pending_disable_recording_ack_count_,
+ // acked below.
+ pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1;
+
+ // Handle special case of zero child processes by immediately telling the
+ // caller that tracing has ended. Use asynchronous OnDisableRecordingAcked
+ // to avoid recursive call back to the caller.
+ if (pending_disable_recording_ack_count_ == 1) {
// Ack asynchronously now, because we don't have any children to wait for.
std::vector<std::string> category_groups;
TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
@@ -120,59 +226,221 @@ void TracingControllerImpl::DisableRecording(
}
// Notify all child processes.
- for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
+ for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
+ it != trace_message_filters_.end(); ++it) {
it->get()->SendEndTracing();
}
+ return true;
}
-void TracingControllerImpl::EnableMonitoring(
- const base::debug::CategoryFilter& filter,
+bool TracingControllerImpl::EnableMonitoring(
+ const std::string& category_filter,
TracingController::Options options,
const EnableMonitoringDoneCallback& callback) {
- NOTIMPLEMENTED();
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!can_enable_monitoring())
+ return false;
+ is_monitoring_ = true;
+
+#if defined(OS_ANDROID)
+ TraceLog::GetInstance()->AddClockSyncMetadataEvent();
+#endif
+
+ int monitoring_tracing_options = 0;
+ if (options & ENABLE_SAMPLING)
+ monitoring_tracing_options |= base::debug::TraceLog::MONITOR_SAMPLING;
+
+ TraceLog::GetInstance()->SetEnabled(
+ base::debug::CategoryFilter(category_filter),
+ static_cast<TraceLog::Options>(monitoring_tracing_options));
+
+ // Notify all child processes.
+ for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
+ it != trace_message_filters_.end(); ++it) {
+ it->get()->SendEnableMonitoring(category_filter,
+ static_cast<TraceLog::Options>(monitoring_tracing_options));
+ }
+
+ if (!callback.is_null())
+ callback.Run();
+ return true;
}
-void TracingControllerImpl::DisableMonitoring(
+bool TracingControllerImpl::DisableMonitoring(
const DisableMonitoringDoneCallback& callback) {
- NOTIMPLEMENTED();
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!can_disable_monitoring())
+ return false;
+ is_monitoring_ = false;
+
+ TraceLog::GetInstance()->SetDisabled();
+
+ // Notify all child processes.
+ for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
+ it != trace_message_filters_.end(); ++it) {
+ it->get()->SendDisableMonitoring();
+ }
+
+ if (!callback.is_null())
+ callback.Run();
+ return true;
}
void TracingControllerImpl::GetMonitoringStatus(
bool* out_enabled,
- base::debug::CategoryFilter* out_filter,
+ std::string* out_category_filter,
TracingController::Options* out_options) {
NOTIMPLEMENTED();
}
-void TracingControllerImpl::CaptureCurrentMonitoringSnapshot(
+bool TracingControllerImpl::CaptureMonitoringSnapshot(
+ const base::FilePath& result_file_path,
const TracingFileResultCallback& callback) {
- NOTIMPLEMENTED();
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!can_disable_monitoring())
+ return false;
+
+ if (callback.is_null() && result_file_path.empty())
+ return false;
+
+ pending_capture_monitoring_snapshot_done_callback_ = callback;
+ monitoring_snapshot_file_.reset(new ResultFile(result_file_path));
+
+ // Count myself in pending_capture_monitoring_snapshot_ack_count_,
+ // acked below.
+ pending_capture_monitoring_snapshot_ack_count_ =
+ trace_message_filters_.size() + 1;
+
+ // Handle special case of zero child processes by immediately telling the
+ // caller that capturing snapshot has ended. Use asynchronous
+ // OnCaptureMonitoringSnapshotAcked to avoid recursive call back to the
+ // caller.
+ if (pending_capture_monitoring_snapshot_ack_count_ == 1) {
+ // Ack asynchronously now, because we don't have any children to wait for.
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
+ base::Unretained(this)));
+ }
+
+ // Notify all child processes.
+ for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
+ it != trace_message_filters_.end(); ++it) {
+ it->get()->SendCaptureMonitoringSnapshot();
+ }
+
+#if defined(OS_ANDROID)
+ TraceLog::GetInstance()->AddClockSyncMetadataEvent();
+#endif
+
+ return true;
+}
+
+bool TracingControllerImpl::GetTraceBufferPercentFull(
+ const GetTraceBufferPercentFullCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!can_get_trace_buffer_percent_full() || callback.is_null())
+ return false;
+
+ pending_trace_buffer_percent_full_callback_ = callback;
+
+ // Count myself in pending_trace_buffer_percent_full_ack_count_, acked below.
+ pending_trace_buffer_percent_full_ack_count_ =
+ trace_message_filters_.size() + 1;
+ maximum_trace_buffer_percent_full_ = 0;
+
+ // Handle special case of zero child processes.
+ if (pending_trace_buffer_percent_full_ack_count_ == 1) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
+ base::Unretained(this),
+ TraceLog::GetInstance()->GetBufferPercentFull()));
+ }
+
+ // Notify all child processes.
+ for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
+ it != trace_message_filters_.end(); ++it) {
+ it->get()->SendGetTraceBufferPercentFull();
+ }
+ return true;
+}
+
+bool TracingControllerImpl::SetWatchEvent(
+ const std::string& category_name,
+ const std::string& event_name,
+ const WatchEventCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (callback.is_null())
+ return false;
+
+ watch_category_name_ = category_name;
+ watch_event_name_ = event_name;
+ watch_event_callback_ = callback;
+
+ TraceLog::GetInstance()->SetWatchEvent(
+ category_name, event_name,
+ base::Bind(&TracingControllerImpl::OnWatchEventMatched,
+ base::Unretained(this)));
+
+ for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
+ it != trace_message_filters_.end(); ++it) {
+ it->get()->SendSetWatchEvent(category_name, event_name);
+ }
+ return true;
+}
+
+bool TracingControllerImpl::CancelWatchEvent() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!can_cancel_watch_event())
+ return false;
+
+ for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
+ it != trace_message_filters_.end(); ++it) {
+ it->get()->SendCancelWatchEvent();
+ }
+
+ watch_event_callback_.Reset();
+ return true;
}
-void TracingControllerImpl::AddFilter(TraceMessageFilter* filter) {
+void TracingControllerImpl::AddTraceMessageFilter(
+ TraceMessageFilter* trace_message_filter) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::AddFilter, base::Unretained(this),
- make_scoped_refptr(filter)));
+ base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
+ base::Unretained(this),
+ make_scoped_refptr(trace_message_filter)));
return;
}
- filters_.insert(filter);
- if (is_recording_enabled()) {
- std::string cf_str = category_filter_.ToString();
- filter->SendBeginTracing(cf_str, trace_options_);
+ trace_message_filters_.insert(trace_message_filter);
+ if (can_cancel_watch_event()) {
+ trace_message_filter->SendSetWatchEvent(watch_category_name_,
+ watch_event_name_);
+ }
+ if (can_disable_recording()) {
+ trace_message_filter->SendBeginTracing(
+ TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(),
+ TraceLog::GetInstance()->trace_options());
}
}
-void TracingControllerImpl::RemoveFilter(TraceMessageFilter* filter) {
+void TracingControllerImpl::RemoveTraceMessageFilter(
+ TraceMessageFilter* trace_message_filter) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::RemoveFilter, base::Unretained(this),
- make_scoped_refptr(filter)));
+ base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
+ base::Unretained(this),
+ make_scoped_refptr(trace_message_filter)));
return;
}
- filters_.erase(filter);
+ trace_message_filters_.erase(trace_message_filter);
}
void TracingControllerImpl::OnDisableRecordingAcked(
@@ -188,19 +456,20 @@ void TracingControllerImpl::OnDisableRecordingAcked(
known_category_groups_.insert(known_category_groups.begin(),
known_category_groups.end());
- if (pending_end_ack_count_ == 0)
+ if (pending_disable_recording_ack_count_ == 0)
return;
- if (--pending_end_ack_count_ == 1) {
+ if (--pending_disable_recording_ack_count_ == 1) {
// All acks from subprocesses have been received. Now flush the local trace.
// During or after this call, our OnLocalTraceDataCollected will be
// called with the last of the local trace data.
TraceLog::GetInstance()->Flush(
base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
base::Unretained(this)));
+ return;
}
- if (pending_end_ack_count_ != 0)
+ if (pending_disable_recording_ack_count_ != 0)
return;
// All acks (including from the subprocesses and the local trace) have been
@@ -211,17 +480,69 @@ void TracingControllerImpl::OnDisableRecordingAcked(
if (!pending_get_categories_done_callback_.is_null()) {
pending_get_categories_done_callback_.Run(known_category_groups_);
pending_get_categories_done_callback_.Reset();
- } else {
- OnEndTracingComplete();
+ } else if (result_file_) {
+ result_file_->Close(
+ base::Bind(&TracingControllerImpl::OnResultFileClosed,
+ base::Unretained(this)));
}
}
-void TracingControllerImpl::OnEndTracingComplete() {
- if (pending_disable_recording_done_callback_.is_null())
+void TracingControllerImpl::OnResultFileClosed() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!result_file_)
return;
- pending_disable_recording_done_callback_.Run(recording_result_file_.Pass());
- pending_disable_recording_done_callback_.Reset();
+ if (!pending_disable_recording_done_callback_.is_null()) {
+ pending_disable_recording_done_callback_.Run(result_file_->path());
+ pending_disable_recording_done_callback_.Reset();
+ }
+ result_file_.reset();
+}
+
+void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked() {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
+ base::Unretained(this)));
+ return;
+ }
+
+ if (pending_capture_monitoring_snapshot_ack_count_ == 0)
+ return;
+
+ if (--pending_capture_monitoring_snapshot_ack_count_ == 1) {
+ // All acks from subprocesses have been received. Now flush the local trace.
+ // During or after this call, our OnLocalMonitoringTraceDataCollected
+ // will be called with the last of the local trace data.
+ TraceLog::GetInstance()->FlushButLeaveBufferIntact(
+ base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
+ base::Unretained(this)));
+ return;
+ }
+
+ if (pending_capture_monitoring_snapshot_ack_count_ != 0)
+ return;
+
+ if (monitoring_snapshot_file_) {
+ monitoring_snapshot_file_->Close(
+ base::Bind(&TracingControllerImpl::OnMonitoringSnapshotFileClosed,
+ base::Unretained(this)));
+ }
+}
+
+void TracingControllerImpl::OnMonitoringSnapshotFileClosed() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (!monitoring_snapshot_file_)
+ return;
+
+ if (!pending_capture_monitoring_snapshot_done_callback_.is_null()) {
+ pending_capture_monitoring_snapshot_done_callback_.Run(
+ monitoring_snapshot_file_->path());
+ pending_capture_monitoring_snapshot_done_callback_.Reset();
+ }
+ monitoring_snapshot_file_.reset();
}
void TracingControllerImpl::OnTraceDataCollected(
@@ -235,21 +556,21 @@ void TracingControllerImpl::OnTraceDataCollected(
return;
}
- // Drop trace events if we are just getting categories.
- if (!pending_get_categories_done_callback_.is_null())
- return;
-
- std::string javascript;
- javascript.reserve(events_str_ptr->size() * 2);
- base::JsonDoubleQuote(events_str_ptr->data(), false, &javascript);
+ if (result_file_)
+ result_file_->Write(events_str_ptr);
+}
- // Intentionally append a , to the traceData. This technically causes all
- // traceData that we pass back to JS to end with a comma, but that is
- // actually something the JS side strips away anyway
- javascript.append(",");
+void TracingControllerImpl::OnMonitoringTraceDataCollected(
+ const scoped_refptr<base::RefCountedString>& events_str_ptr) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected,
+ base::Unretained(this), events_str_ptr));
+ return;
+ }
- file_util::WriteFile(*recording_result_file_,
- javascript.c_str(), javascript.length());
+ if (monitoring_snapshot_file_)
+ monitoring_snapshot_file_->Write(events_str_ptr);
}
void TracingControllerImpl::OnLocalTraceDataCollected(
@@ -267,4 +588,60 @@ void TracingControllerImpl::OnLocalTraceDataCollected(
OnDisableRecordingAcked(category_groups);
}
+void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
+ const scoped_refptr<base::RefCountedString>& events_str_ptr,
+ bool has_more_events) {
+ if (events_str_ptr->data().size())
+ OnMonitoringTraceDataCollected(events_str_ptr);
+
+ if (has_more_events)
+ return;
+
+ // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
+ OnCaptureMonitoringSnapshotAcked();
+}
+
+void TracingControllerImpl::OnTraceBufferPercentFullReply(float percent_full) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
+ base::Unretained(this), percent_full));
+ return;
+ }
+
+ if (pending_trace_buffer_percent_full_ack_count_ == 0)
+ return;
+
+ maximum_trace_buffer_percent_full_ =
+ std::max(maximum_trace_buffer_percent_full_, percent_full);
+
+ if (--pending_trace_buffer_percent_full_ack_count_ == 0) {
+ // Trigger callback if one is set.
+ pending_trace_buffer_percent_full_callback_.Run(
+ maximum_trace_buffer_percent_full_);
+ pending_trace_buffer_percent_full_callback_.Reset();
+ }
+
+ if (pending_trace_buffer_percent_full_ack_count_ == 1) {
+ // The last ack represents local trace, so we need to ack it now. Note that
+ // this code only executes if there were child processes.
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&TracingControllerImpl::OnTraceBufferPercentFullReply,
+ base::Unretained(this),
+ TraceLog::GetInstance()->GetBufferPercentFull()));
+ }
+}
+
+void TracingControllerImpl::OnWatchEventMatched() {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&TracingControllerImpl::OnWatchEventMatched,
+ base::Unretained(this)));
+ return;
+ }
+
+ if (!watch_event_callback_.is_null())
+ watch_event_callback_.Run();
+}
+
} // namespace content
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.h b/chromium/content/browser/tracing/tracing_controller_impl.h
index 22192255444..ed3c8fd6519 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.h
+++ b/chromium/content/browser/tracing/tracing_controller_impl.h
@@ -9,42 +9,54 @@
#include <string>
#include <vector>
+#include "base/files/file_path.h"
#include "base/lazy_instance.h"
-#include "content/public/browser/trace_subscriber.h"
#include "content/public/browser/tracing_controller.h"
+namespace base {
+class RefCountedString;
+}
+
namespace content {
class TraceMessageFilter;
-class TracingControllerImpl :
- public TracingController, public TraceSubscriber {
+class TracingControllerImpl : public TracingController {
public:
static TracingControllerImpl* GetInstance();
// TracingController implementation.
- virtual void GetCategories(
+ virtual bool GetCategories(
const GetCategoriesDoneCallback& callback) OVERRIDE;
- virtual void EnableRecording(
- const base::debug::CategoryFilter& filter,
+ virtual bool EnableRecording(
+ const std::string& category_filter,
TracingController::Options options,
const EnableRecordingDoneCallback& callback) OVERRIDE;
- virtual void DisableRecording(
+ virtual bool DisableRecording(
+ const base::FilePath& result_file_path,
const TracingFileResultCallback& callback) OVERRIDE;
- virtual void EnableMonitoring(const base::debug::CategoryFilter& filter,
+ virtual bool EnableMonitoring(const std::string& category_filter,
TracingController::Options options,
const EnableMonitoringDoneCallback& callback) OVERRIDE;
- virtual void DisableMonitoring(
+ virtual bool DisableMonitoring(
const DisableMonitoringDoneCallback& callback) OVERRIDE;
virtual void GetMonitoringStatus(
bool* out_enabled,
- base::debug::CategoryFilter* out_filter,
+ std::string* out_category_filter,
TracingController::Options* out_options) OVERRIDE;
- virtual void CaptureCurrentMonitoringSnapshot(
+ virtual bool CaptureMonitoringSnapshot(
+ const base::FilePath& result_file_path,
const TracingFileResultCallback& callback) OVERRIDE;
+ virtual bool GetTraceBufferPercentFull(
+ const GetTraceBufferPercentFullCallback& callback) OVERRIDE;
+ virtual bool SetWatchEvent(const std::string& category_name,
+ const std::string& event_name,
+ const WatchEventCallback& callback) OVERRIDE;
+ virtual bool CancelWatchEvent() OVERRIDE;
private:
- typedef std::set<scoped_refptr<TraceMessageFilter> > FilterMap;
+ typedef std::set<scoped_refptr<TraceMessageFilter> > TraceMessageFilterMap;
+ class ResultFile;
friend struct base::DefaultLazyInstanceTraits<TracingControllerImpl>;
friend class TraceMessageFilter;
@@ -52,46 +64,83 @@ class TracingControllerImpl :
TracingControllerImpl();
virtual ~TracingControllerImpl();
- // TraceSubscriber implementation.
- virtual void OnEndTracingComplete() OVERRIDE;
- virtual void OnTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& events_str_ptr) OVERRIDE;
-
bool can_enable_recording() const {
return !is_recording_;
}
- bool can_end_recording() const {
- return is_recording_ && pending_end_ack_count_ == 0;
+ bool can_disable_recording() const {
+ return is_recording_ && !result_file_;
+ }
+
+ bool can_enable_monitoring() const {
+ return !is_monitoring_;
+ }
+
+ bool can_disable_monitoring() const {
+ return is_monitoring_ && !monitoring_snapshot_file_;
+ }
+
+ bool can_get_trace_buffer_percent_full() const {
+ return pending_trace_buffer_percent_full_callback_.is_null();
}
- bool is_recording_enabled() const {
- return can_end_recording();
+ bool can_cancel_watch_event() const {
+ return !watch_event_callback_.is_null();
}
// Methods for use by TraceMessageFilter.
- void AddFilter(TraceMessageFilter* filter);
- void RemoveFilter(TraceMessageFilter* filter);
+ void AddTraceMessageFilter(TraceMessageFilter* trace_message_filter);
+ void RemoveTraceMessageFilter(TraceMessageFilter* trace_message_filter);
+
+ void OnTraceDataCollected(
+ const scoped_refptr<base::RefCountedString>& events_str_ptr);
+ void OnMonitoringTraceDataCollected(
+ const scoped_refptr<base::RefCountedString>& events_str_ptr);
// Callback of TraceLog::Flush() for the local trace.
void OnLocalTraceDataCollected(
const scoped_refptr<base::RefCountedString>& events_str_ptr,
bool has_more_events);
+ // Callback of TraceLog::FlushMonitoring() for the local trace.
+ void OnLocalMonitoringTraceDataCollected(
+ const scoped_refptr<base::RefCountedString>& events_str_ptr,
+ bool has_more_events);
void OnDisableRecordingAcked(
const std::vector<std::string>& known_category_groups);
+ void OnResultFileClosed();
+
+ void OnCaptureMonitoringSnapshotAcked();
+ void OnMonitoringSnapshotFileClosed();
+
+ void OnTraceBufferPercentFullReply(float percent_full);
- FilterMap filters_;
+ void OnWatchEventMatched();
+
+ TraceMessageFilterMap trace_message_filters_;
// Pending acks for DisableRecording.
- int pending_end_ack_count_;
+ int pending_disable_recording_ack_count_;
+ // Pending acks for CaptureMonitoringSnapshot.
+ int pending_capture_monitoring_snapshot_ack_count_;
+ // Pending acks for GetTraceBufferPercentFull.
+ int pending_trace_buffer_percent_full_ack_count_;
+ float maximum_trace_buffer_percent_full_;
+
bool is_recording_;
+ bool is_monitoring_;
+
GetCategoriesDoneCallback pending_get_categories_done_callback_;
TracingFileResultCallback pending_disable_recording_done_callback_;
- std::set<std::string> known_category_groups_;
- base::debug::TraceLog::Options trace_options_;
- base::debug::CategoryFilter category_filter_;
- scoped_ptr<base::FilePath> recording_result_file_;
+ TracingFileResultCallback pending_capture_monitoring_snapshot_done_callback_;
+ GetTraceBufferPercentFullCallback pending_trace_buffer_percent_full_callback_;
+ std::string watch_category_name_;
+ std::string watch_event_name_;
+ WatchEventCallback watch_event_callback_;
+
+ std::set<std::string> known_category_groups_;
+ scoped_ptr<ResultFile> result_file_;
+ scoped_ptr<ResultFile> monitoring_snapshot_file_;
DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl);
};
diff --git a/chromium/content/browser/tracing/tracing_ui.cc b/chromium/content/browser/tracing/tracing_ui.cc
index 15bd2cf2590..e59f5667cb4 100644
--- a/chromium/content/browser/tracing/tracing_ui.cc
+++ b/chromium/content/browser/tracing/tracing_ui.cc
@@ -6,540 +6,143 @@
#include <string>
+#include "base/base64.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "base/debug/trace_event.h"
#include "base/file_util.h"
-#include "base/json/string_escape.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
-#include "base/safe_numerics.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/trace_controller.h"
-#include "content/public/browser/trace_subscriber.h"
+#include "content/public/browser/tracing_controller.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
-#include "content/public/browser/web_ui_message_handler.h"
#include "content/public/common/url_constants.h"
#include "grit/tracing_resources.h"
-#include "ipc/ipc_channel.h"
-#include "ui/shell_dialogs/select_file_dialog.h"
-
-#if defined(OS_CHROMEOS)
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/debug_daemon_client.h"
-#endif
namespace content {
namespace {
-WebUIDataSource* CreateTracingHTMLSource() {
- WebUIDataSource* source = WebUIDataSource::Create(kChromeUITracingHost);
-
- source->SetJsonPath("strings.js");
- source->SetDefaultResource(IDR_TRACING_HTML);
- source->AddResourcePath("tracing.js", IDR_TRACING_JS);
- return source;
-}
-
-// This class receives javascript messages from the renderer.
-// Note that the WebUI infrastructure runs on the UI thread, therefore all of
-// this class's methods are expected to run on the UI thread.
-class TracingMessageHandler
- : public WebUIMessageHandler,
- public ui::SelectFileDialog::Listener,
- public base::SupportsWeakPtr<TracingMessageHandler>,
- public TraceSubscriber {
- public:
- TracingMessageHandler();
- virtual ~TracingMessageHandler();
-
- // WebUIMessageHandler implementation.
- virtual void RegisterMessages() OVERRIDE;
-
- // SelectFileDialog::Listener implementation
- virtual void FileSelected(const base::FilePath& path,
- int index,
- void* params) OVERRIDE;
- virtual void FileSelectionCanceled(void* params) OVERRIDE;
-
- // TraceSubscriber implementation.
- virtual void OnEndTracingComplete() OVERRIDE;
- virtual void OnTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& trace_fragment) OVERRIDE;
- virtual void OnTraceBufferPercentFullReply(float percent_full) OVERRIDE;
- virtual void OnKnownCategoriesCollected(
- const std::set<std::string>& known_categories) OVERRIDE;
-
- // Messages.
- void OnTracingControllerInitialized(const base::ListValue* list);
- void OnBeginTracing(const base::ListValue* list);
- void OnEndTracingAsync(const base::ListValue* list);
- void OnBeginRequestBufferPercentFull(const base::ListValue* list);
- void OnLoadTraceFile(const base::ListValue* list);
- void OnSaveTraceFile(const base::ListValue* list);
- void OnGetKnownCategories(const base::ListValue* list);
-
- // Callbacks.
- void LoadTraceFileComplete(string16* file_contents,
- const base::FilePath &path);
- void SaveTraceFileComplete();
+void OnGotCategories(const WebUIDataSource::GotDataCallback& callback,
+ const std::set<std::string>& categorySet) {
- private:
- // The file dialog to select a file for loading or saving traces.
- scoped_refptr<ui::SelectFileDialog> select_trace_file_dialog_;
-
- // The type of the file dialog as the same one is used for loading or saving
- // traces.
- ui::SelectFileDialog::Type select_trace_file_dialog_type_;
-
- // The trace data that is to be written to the file on saving.
- scoped_ptr<std::string> trace_data_to_save_;
-
- // True while tracing is active.
- bool trace_enabled_;
-
- // True while system tracing is active.
- bool system_trace_in_progress_;
-
- void OnEndSystemTracingAck(
- const scoped_refptr<base::RefCountedString>& events_str_ptr);
-
- DISALLOW_COPY_AND_ASSIGN(TracingMessageHandler);
-};
-
-// A proxy passed to the Read and Write tasks used when loading or saving trace
-// data.
-class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> {
- public:
- explicit TaskProxy(const base::WeakPtr<TracingMessageHandler>& handler)
- : handler_(handler) {}
- void LoadTraceFileCompleteProxy(string16* file_contents,
- const base::FilePath& path) {
- if (handler_.get())
- handler_->LoadTraceFileComplete(file_contents, path);
- delete file_contents;
- }
-
- void SaveTraceFileCompleteProxy() {
- if (handler_.get())
- handler_->SaveTraceFileComplete();
+ scoped_ptr<base::ListValue> category_list(new base::ListValue());
+ for (std::set<std::string>::const_iterator it = categorySet.begin();
+ it != categorySet.end(); it++) {
+ category_list->AppendString(*it);
}
- private:
- friend class base::RefCountedThreadSafe<TaskProxy>;
- ~TaskProxy() {}
-
- // The message handler to call callbacks on.
- base::WeakPtr<TracingMessageHandler> handler_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskProxy);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// TracingMessageHandler
-//
-////////////////////////////////////////////////////////////////////////////////
-
-TracingMessageHandler::TracingMessageHandler()
- : select_trace_file_dialog_type_(ui::SelectFileDialog::SELECT_NONE),
- trace_enabled_(false),
- system_trace_in_progress_(false) {
+ base::RefCountedString* res = new base::RefCountedString();
+ base::JSONWriter::Write(category_list.get(), &res->data());
+ callback.Run(res);
}
-TracingMessageHandler::~TracingMessageHandler() {
- if (select_trace_file_dialog_.get())
- select_trace_file_dialog_->ListenerDestroyed();
-
- // If we are the current subscriber, this will result in ending tracing.
- TraceController::GetInstance()->CancelSubscriber(this);
-
- // Shutdown any system tracing too.
- if (system_trace_in_progress_) {
-#if defined(OS_CHROMEOS)
- chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
- RequestStopSystemTracing(
- chromeos::DebugDaemonClient::EmptyStopSystemTracingCallback());
-#endif
- }
-}
-
-void TracingMessageHandler::RegisterMessages() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- web_ui()->RegisterMessageCallback("tracingControllerInitialized",
- base::Bind(&TracingMessageHandler::OnTracingControllerInitialized,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback("beginTracing",
- base::Bind(&TracingMessageHandler::OnBeginTracing,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback("endTracingAsync",
- base::Bind(&TracingMessageHandler::OnEndTracingAsync,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback("beginRequestBufferPercentFull",
- base::Bind(&TracingMessageHandler::OnBeginRequestBufferPercentFull,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback("loadTraceFile",
- base::Bind(&TracingMessageHandler::OnLoadTraceFile,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback("saveTraceFile",
- base::Bind(&TracingMessageHandler::OnSaveTraceFile,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback("getKnownCategories",
- base::Bind(&TracingMessageHandler::OnGetKnownCategories,
- base::Unretained(this)));
-}
-
-void TracingMessageHandler::OnTracingControllerInitialized(
- const base::ListValue* args) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- // Send the client info to the tracingController
- {
- scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
- dict->SetString("version", GetContentClient()->GetProduct());
+void OnRecordingEnabledAck(const WebUIDataSource::GotDataCallback& callback);
- dict->SetString("command_line",
- CommandLine::ForCurrentProcess()->GetCommandLineString());
-
- web_ui()->CallJavascriptFunction("tracingController.onClientInfoUpdate",
- *dict);
+bool OnBeginRecording(const std::string& data64,
+ const WebUIDataSource::GotDataCallback& callback) {
+ std::string data;
+ if (!base::Base64Decode(data64, &data)) {
+ LOG(ERROR) << "Options were not base64 encoded.";
+ return false;
}
-}
-
-void TracingMessageHandler::OnBeginRequestBufferPercentFull(
- const base::ListValue* list) {
- TraceController::GetInstance()->GetTraceBufferPercentFullAsync(this);
-}
-
-// A callback used for asynchronously reading a file to a string. Calls the
-// TaskProxy callback when reading is complete.
-void ReadTraceFileCallback(TaskProxy* proxy, const base::FilePath& path) {
- std::string file_contents;
- if (!base::ReadFileToString(path, &file_contents))
- return;
- // We need to escape the file contents, because it will go into a javascript
- // quoted string in TracingMessageHandler::LoadTraceFileComplete. We need to
- // escape control characters (to have well-formed javascript statements), as
- // well as \ and ' (the only special characters in a ''-quoted string).
- // Do the escaping on this thread, it may take a little while for big files
- // and we don't want to block the UI during that time. Also do the UTF-16
- // conversion here.
- // Note: we're using UTF-16 because we'll need to cut the string into slices
- // to give to Javascript, and it's easier to cut than UTF-8 (since JS strings
- // are arrays of 16-bit values, UCS-2 really, whereas we can't cut inside of a
- // multibyte UTF-8 codepoint).
- size_t size = file_contents.size();
- std::string escaped_contents;
- escaped_contents.reserve(size);
- for (size_t i = 0; i < size; ++i) {
- char c = file_contents[i];
- if (c < ' ') {
- escaped_contents += base::StringPrintf("\\u%04x", c);
- continue;
- }
- if (c == '\\' || c == '\'')
- escaped_contents.push_back('\\');
- escaped_contents.push_back(c);
+ scoped_ptr<base::Value> optionsRaw(base::JSONReader::Read(data));
+ if (!optionsRaw) {
+ LOG(ERROR) << "Options were not valid JSON";
+ return false;
}
- file_contents.clear();
-
- scoped_ptr<string16> contents16(new string16);
- UTF8ToUTF16(escaped_contents).swap(*contents16);
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&TaskProxy::LoadTraceFileCompleteProxy, proxy,
- contents16.release(),
- path));
-}
-
-// A callback used for asynchronously writing a file from a string. Calls the
-// TaskProxy callback when writing is complete.
-void WriteTraceFileCallback(TaskProxy* proxy,
- const base::FilePath& path,
- std::string* contents) {
- int size = base::checked_numeric_cast<int>(contents->size());
- if (file_util::WriteFile(path, contents->c_str(), size) != size)
- return;
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&TaskProxy::SaveTraceFileCompleteProxy, proxy));
-}
-
-void TracingMessageHandler::FileSelected(
- const base::FilePath& path, int index, void* params) {
- if (select_trace_file_dialog_type_ ==
- ui::SelectFileDialog::SELECT_OPEN_FILE) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&ReadTraceFileCallback,
- make_scoped_refptr(new TaskProxy(AsWeakPtr())), path));
- } else {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&WriteTraceFileCallback,
- make_scoped_refptr(new TaskProxy(AsWeakPtr())), path,
- trace_data_to_save_.release()));
+ base::DictionaryValue* options;
+ if (!optionsRaw->GetAsDictionary(&options)) {
+ LOG(ERROR) << "Options must be dict";
+ return false;
}
- select_trace_file_dialog_ = NULL;
-}
-
-void TracingMessageHandler::FileSelectionCanceled(void* params) {
- select_trace_file_dialog_ = NULL;
- if (select_trace_file_dialog_type_ ==
- ui::SelectFileDialog::SELECT_OPEN_FILE) {
- web_ui()->CallJavascriptFunction(
- "tracingController.onLoadTraceFileCanceled");
- } else {
- web_ui()->CallJavascriptFunction(
- "tracingController.onSaveTraceFileCanceled");
+ std::string category_filter_string;
+ bool use_system_tracing;
+ bool use_continuous_tracing;
+ bool use_sampling;
+
+ bool options_ok = true;
+ options_ok &= options->GetString("categoryFilter", &category_filter_string);
+ options_ok &= options->GetBoolean("useSystemTracing", &use_system_tracing);
+ options_ok &= options->GetBoolean("useContinuousTracing",
+ &use_continuous_tracing);
+ options_ok &= options->GetBoolean("useSampling", &use_sampling);
+ if (!options_ok) {
+ LOG(ERROR) << "Malformed options";
+ return false;
}
-}
-
-void TracingMessageHandler::OnLoadTraceFile(const base::ListValue* list) {
- // Only allow a single dialog at a time.
- if (select_trace_file_dialog_.get())
- return;
- select_trace_file_dialog_type_ = ui::SelectFileDialog::SELECT_OPEN_FILE;
- select_trace_file_dialog_ = ui::SelectFileDialog::Create(
- this,
- GetContentClient()->browser()->CreateSelectFilePolicy(
- web_ui()->GetWebContents()));
- select_trace_file_dialog_->SelectFile(
- ui::SelectFileDialog::SELECT_OPEN_FILE,
- string16(),
- base::FilePath(),
- NULL,
- 0,
- base::FilePath::StringType(),
- web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow(),
- NULL);
-}
-void TracingMessageHandler::LoadTraceFileComplete(string16* contents,
- const base::FilePath& path) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ int tracing_options = 0;
+ if (use_system_tracing)
+ tracing_options |= TracingController::ENABLE_SYSTRACE;
+ if (use_sampling)
+ tracing_options |= TracingController::ENABLE_SAMPLING;
+ if (use_continuous_tracing)
+ tracing_options |= TracingController::RECORD_CONTINUOUSLY;
- // We need to pass contents to tracingController.onLoadTraceFileComplete, but
- // that may be arbitrarily big, and IPCs messages are limited in size. So we
- // need to cut it into pieces and rebuild the string in Javascript.
- // |contents| has already been escaped in ReadTraceFileCallback.
- // IPC::Channel::kMaximumMessageSize is in bytes, and we need to account for
- // overhead.
- const size_t kMaxSize = IPC::Channel::kMaximumMessageSize / 2 - 128;
- string16 first_prefix = UTF8ToUTF16("window.traceData = '");
- string16 prefix = UTF8ToUTF16("window.traceData += '");
- string16 suffix = UTF8ToUTF16("';");
-
- RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
- for (size_t i = 0; i < contents->size(); i += kMaxSize) {
- string16 javascript = i == 0 ? first_prefix : prefix;
- javascript += contents->substr(i, kMaxSize) + suffix;
- rvh->ExecuteJavascriptInWebFrame(string16(), javascript);
- }
-
- // The CallJavascriptFunction is not used because we need to pass
- // the first param |window.traceData| through as an un-quoted string.
- rvh->ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(
- "tracingController.onLoadTraceFileComplete(window.traceData," +
- base::GetDoubleQuotedJson(path.value()) + ");" +
- "delete window.traceData;"));
+ return TracingController::GetInstance()->EnableRecording(
+ category_filter_string,
+ static_cast<TracingController::Options>(tracing_options),
+ base::Bind(&OnRecordingEnabledAck, callback));
}
-void TracingMessageHandler::OnSaveTraceFile(const base::ListValue* list) {
- // Only allow a single dialog at a time.
- if (select_trace_file_dialog_.get())
- return;
-
- DCHECK_EQ(1U, list->GetSize());
-
- std::string* trace_data = new std::string();
- bool ok = list->GetString(0, trace_data);
- DCHECK(ok);
- trace_data_to_save_.reset(trace_data);
-
- select_trace_file_dialog_type_ = ui::SelectFileDialog::SELECT_SAVEAS_FILE;
- select_trace_file_dialog_ = ui::SelectFileDialog::Create(
- this,
- GetContentClient()->browser()->CreateSelectFilePolicy(
- web_ui()->GetWebContents()));
- select_trace_file_dialog_->SelectFile(
- ui::SelectFileDialog::SELECT_SAVEAS_FILE,
- string16(),
- base::FilePath(),
- NULL,
- 0,
- base::FilePath::StringType(),
- web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow(),
- NULL);
+void OnRecordingEnabledAck(const WebUIDataSource::GotDataCallback& callback) {
+ base::RefCountedString* res = new base::RefCountedString();
+ callback.Run(res);
}
-void TracingMessageHandler::SaveTraceFileComplete() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- web_ui()->CallJavascriptFunction("tracingController.onSaveTraceFileComplete");
+void OnTraceBufferPercentFullResult(
+ const WebUIDataSource::GotDataCallback& callback, float result) {
+ std::string str = base::DoubleToString(result);
+ callback.Run(base::RefCountedString::TakeString(&str));
}
-void TracingMessageHandler::OnBeginTracing(const base::ListValue* args) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_GE(args->GetSize(), (size_t) 2);
- DCHECK_LE(args->GetSize(), (size_t) 3);
-
- bool system_tracing_requested = false;
- bool ok = args->GetBoolean(0, &system_tracing_requested);
- DCHECK(ok);
-
- std::string chrome_categories;
- ok = args->GetString(1, &chrome_categories);
- DCHECK(ok);
-
- base::debug::TraceLog::Options options =
- base::debug::TraceLog::RECORD_UNTIL_FULL;
- if (args->GetSize() >= 3) {
- std::string options_;
- ok = args->GetString(2, &options_);
- DCHECK(ok);
- options = base::debug::TraceLog::TraceOptionsFromString(options_);
- }
-
- trace_enabled_ = true;
- // TODO(jbates) This may fail, but that's OK for current use cases.
- // Ex: Multiple about:gpu traces can not trace simultaneously.
- // TODO(nduca) send feedback to javascript about whether or not BeginTracing
- // was successful.
- TraceController::GetInstance()->BeginTracing(this, chrome_categories,
- options);
-
- if (system_tracing_requested) {
-#if defined(OS_CHROMEOS)
- DCHECK(!system_trace_in_progress_);
- chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
- StartSystemTracing();
- // TODO(sleffler) async, could wait for completion
- system_trace_in_progress_ = true;
-#endif
- }
+void ReadRecordingResult(const WebUIDataSource::GotDataCallback& callback,
+ const base::FilePath& path) {
+ std::string tmp;
+ if (!base::ReadFileToString(path, &tmp))
+ LOG(ERROR) << "Failed to read file " << path.value();
+ base::DeleteFile(path, false);
+ callback.Run(base::RefCountedString::TakeString(&tmp));
}
-void TracingMessageHandler::OnEndTracingAsync(const base::ListValue* list) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- // This is really us beginning to end tracing, rather than tracing being truly
- // over. When this function yields, we expect to get some number of
- // OnTraceDataCollected callbacks, which will append data to window.traceData.
- // To set up for this, set window.traceData to the empty string.
- web_ui()->GetWebContents()->GetRenderViewHost()->
- ExecuteJavascriptInWebFrame(string16(),
- UTF8ToUTF16("window.traceData = '';"));
-
- // TODO(nduca): fix javascript code to make sure trace_enabled_ is always true
- // here. triggered a false condition by just clicking stop
- // trace a few times when it was going slow, and maybe switching
- // between tabs.
- if (trace_enabled_ &&
- !TraceController::GetInstance()->EndTracingAsync(this)) {
- // Set to false now, since it turns out we never were the trace subscriber.
- OnEndTracingComplete();
- }
+void BeginReadingRecordingResult(
+ const WebUIDataSource::GotDataCallback& callback,
+ const base::FilePath& path) {
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(ReadRecordingResult, callback, path));
}
-void TracingMessageHandler::OnEndTracingComplete() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- trace_enabled_ = false;
- if (system_trace_in_progress_) {
- // Disable system tracing now that the local trace has shutdown.
- // This must be done last because we potentially need to push event
- // records into the system event log for synchronizing system event
- // timestamps with chrome event timestamps--and since the system event
- // log is a ring-buffer (on linux) adding them at the end is the only
- // way we're confident we'll have them in the final result.
- system_trace_in_progress_ = false;
-#if defined(OS_CHROMEOS)
- chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
- RequestStopSystemTracing(
- base::Bind(&TracingMessageHandler::OnEndSystemTracingAck,
- base::Unretained(this)));
- return;
-#endif
+bool OnBeginRequest(const std::string& path,
+ const WebUIDataSource::GotDataCallback& callback) {
+ if (path == "json/categories") {
+ TracingController::GetInstance()->GetCategories(
+ base::Bind(OnGotCategories, callback));
+ return true;
}
-
- RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
- rvh->ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(
- "tracingController.onEndTracingComplete(window.traceData);"
- "delete window.traceData;"));
-}
-
-void TracingMessageHandler::OnEndSystemTracingAck(
- const scoped_refptr<base::RefCountedString>& events_str_ptr) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- web_ui()->CallJavascriptFunction(
- "tracingController.onSystemTraceDataCollected",
- *scoped_ptr<base::Value>(new base::StringValue(events_str_ptr->data())));
- DCHECK(!system_trace_in_progress_);
-
- OnEndTracingComplete();
-}
-
-void TracingMessageHandler::OnTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& trace_fragment) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- std::string javascript;
- javascript.reserve(trace_fragment->size() * 2);
- javascript.append("window.traceData += \"");
- base::JsonDoubleQuote(trace_fragment->data(), false, &javascript);
-
- // Intentionally append a , to the traceData. This technically causes all
- // traceData that we pass back to JS to end with a comma, but that is actually
- // something the JS side strips away anyway
- javascript.append(",\";");
-
- web_ui()->GetWebContents()->GetRenderViewHost()->
- ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(javascript));
-}
-
-void TracingMessageHandler::OnTraceBufferPercentFullReply(float percent_full) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- web_ui()->CallJavascriptFunction(
- "tracingController.onRequestBufferPercentFullComplete",
- *scoped_ptr<base::Value>(new base::FundamentalValue(percent_full)));
-}
-
-void TracingMessageHandler::OnGetKnownCategories(const base::ListValue* list) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!TraceController::GetInstance()->GetKnownCategoryGroupsAsync(this)) {
- std::set<std::string> ret;
- OnKnownCategoriesCollected(ret);
+ const char* beginRecordingPath = "json/begin_recording?";
+ if (path.find(beginRecordingPath) == 0) {
+ std::string data = path.substr(strlen(beginRecordingPath));
+ return OnBeginRecording(data, callback);
}
-}
-
-void TracingMessageHandler::OnKnownCategoriesCollected(
- const std::set<std::string>& known_categories) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- scoped_ptr<base::ListValue> categories(new base::ListValue());
- for (std::set<std::string>::const_iterator iter = known_categories.begin();
- iter != known_categories.end();
- ++iter) {
- categories->AppendString(*iter);
+ if (path == "json/get_buffer_percent_full") {
+ return TracingController::GetInstance()->GetTraceBufferPercentFull(
+ base::Bind(OnTraceBufferPercentFullResult, callback));
}
-
- web_ui()->CallJavascriptFunction(
- "tracingController.onKnownCategoriesCollected", *categories);
+ if (path == "json/end_recording") {
+ return TracingController::GetInstance()->DisableRecording(
+ base::FilePath(), base::Bind(BeginReadingRecordingResult, callback));
+ }
+ if (StartsWithASCII(path, "json/", true))
+ LOG(ERROR) << "Unhandled request to " << path;
+ return false;
}
} // namespace
@@ -552,12 +155,16 @@ void TracingMessageHandler::OnKnownCategoriesCollected(
////////////////////////////////////////////////////////////////////////////////
TracingUI::TracingUI(WebUI* web_ui) : WebUIController(web_ui) {
- web_ui->AddMessageHandler(new TracingMessageHandler());
-
// Set up the chrome://tracing/ source.
BrowserContext* browser_context =
web_ui->GetWebContents()->GetBrowserContext();
- WebUIDataSource::Add(browser_context, CreateTracingHTMLSource());
+
+ WebUIDataSource* source = WebUIDataSource::Create(kChromeUITracingHost);
+ source->SetJsonPath("strings.js");
+ source->SetDefaultResource(IDR_TRACING_HTML);
+ source->AddResourcePath("tracing.js", IDR_TRACING_JS);
+ source->SetRequestFilter(base::Bind(OnBeginRequest));
+ WebUIDataSource::Add(browser_context, source);
}
} // namespace content
diff --git a/chromium/content/browser/utility_process_host_impl.cc b/chromium/content/browser/utility_process_host_impl.cc
index f2b3bc31dee..ed53fe82c61 100644
--- a/chromium/content/browser/utility_process_host_impl.cc
+++ b/chromium/content/browser/utility_process_host_impl.cc
@@ -78,7 +78,6 @@ UtilityProcessHostImpl::UtilityProcessHostImpl(
#else
child_flags_(ChildProcessHost::CHILD_NORMAL),
#endif
- use_linux_zygote_(false),
started_(false) {
}
@@ -120,10 +119,6 @@ void UtilityProcessHostImpl::DisableSandbox() {
no_sandbox_ = true;
}
-void UtilityProcessHostImpl::EnableZygote() {
- use_linux_zygote_ = true;
-}
-
const ChildProcessData& UtilityProcessHostImpl::GetData() {
return process_->GetData();
}
@@ -153,9 +148,8 @@ bool UtilityProcessHostImpl::StartProcess() {
if (channel_id.empty())
return false;
- // Single process not supported in multiple dll mode currently.
- if (RenderProcessHost::run_renderer_in_process() &&
- g_utility_main_thread_factory) {
+ if (RenderProcessHost::run_renderer_in_process()) {
+ DCHECK(g_utility_main_thread_factory);
// See comment in RenderProcessHostImpl::Init() for the background on why we
// support single process mode this way.
in_process_thread_.reset(g_utility_main_thread_factory(channel_id));
@@ -200,17 +194,17 @@ bool UtilityProcessHostImpl::StartProcess() {
cmd_line->AppendSwitch(switches::kDebugPluginLoading);
#if defined(OS_POSIX)
- // TODO(port): Sandbox this on Linux. Also, zygote this to work with
- // Linux updating.
if (has_cmd_prefix) {
- // launch the utility child process with some prefix
+ // Launch the utility child process with some prefix
// (usually "xterm -e gdb --args").
cmd_line->PrependWrapper(browser_command_line.GetSwitchValueNative(
switches::kUtilityCmdPrefix));
}
- cmd_line->AppendSwitchPath(switches::kUtilityProcessAllowedDir,
- exposed_dir_);
+ if (!exposed_dir_.empty()) {
+ cmd_line->AppendSwitchPath(switches::kUtilityProcessAllowedDir,
+ exposed_dir_);
+ }
#endif
if (is_mdns_enabled_)
@@ -219,7 +213,9 @@ bool UtilityProcessHostImpl::StartProcess() {
bool use_zygote = false;
#if defined(OS_LINUX)
- use_zygote = !no_sandbox_ && use_linux_zygote_;
+ // The Linux sandbox does not support granting access to a single directory,
+ // so we need to bypass the zygote in that case.
+ use_zygote = !no_sandbox_ && exposed_dir_.empty();
#endif
process_->Launch(
diff --git a/chromium/content/browser/utility_process_host_impl.h b/chromium/content/browser/utility_process_host_impl.h
index 039e20f8c50..3083b229410 100644
--- a/chromium/content/browser/utility_process_host_impl.h
+++ b/chromium/content/browser/utility_process_host_impl.h
@@ -40,7 +40,6 @@ class CONTENT_EXPORT UtilityProcessHostImpl
virtual void SetExposedDir(const base::FilePath& dir) OVERRIDE;
virtual void EnableMDns() OVERRIDE;
virtual void DisableSandbox() OVERRIDE;
- virtual void EnableZygote() OVERRIDE;
virtual const ChildProcessData& GetData() OVERRIDE;
#if defined(OS_POSIX)
virtual void SetEnv(const base::EnvironmentMap& env) OVERRIDE;
@@ -66,7 +65,8 @@ class CONTENT_EXPORT UtilityProcessHostImpl
base::FilePath exposed_dir_;
- // Whether utility process needs perform presandbox initialization for MDns.
+ // Whether the utility process needs to perform presandbox initialization
+ // for mDNS.
bool is_mdns_enabled_;
// Whether to pass switches::kNoSandbox to the child.
@@ -75,9 +75,6 @@ class CONTENT_EXPORT UtilityProcessHostImpl
// Flags defined in ChildProcessHost with which to start the process.
int child_flags_;
- // Launch the utility process from the zygote. Defaults to false.
- bool use_linux_zygote_;
-
base::EnvironmentMap env_;
bool started_;
diff --git a/chromium/content/browser/android/vibration_message_filter.cc b/chromium/content/browser/vibration/vibration_message_filter.cc
index 578fbfdf6e9..9a6ed0cb2c0 100644
--- a/chromium/content/browser/android/vibration_message_filter.cc
+++ b/chromium/content/browser/vibration/vibration_message_filter.cc
@@ -2,33 +2,31 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/android/vibration_message_filter.h"
+#include "content/browser/vibration/vibration_message_filter.h"
#include <algorithm>
#include "base/safe_numerics.h"
#include "content/common/view_messages.h"
-#include "jni/VibrationMessageFilter_jni.h"
+#include "content/port/browser/vibration_provider.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
#include "third_party/WebKit/public/platform/WebVibration.h"
-using base::android::AttachCurrentThread;
-
namespace content {
// Minimum duration of a vibration is 1 millisecond.
const int64 kMinimumVibrationDurationMs = 1;
VibrationMessageFilter::VibrationMessageFilter() {
+ provider_.reset(GetContentClient()->browser()->OverrideVibrationProvider());
+ if (!provider_.get())
+ provider_.reset(CreateProvider());
}
VibrationMessageFilter::~VibrationMessageFilter() {
}
-// static
-bool VibrationMessageFilter::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
bool VibrationMessageFilter::OnMessageReceived(
const IPC::Message& message,
bool* message_was_ok) {
@@ -44,26 +42,28 @@ bool VibrationMessageFilter::OnMessageReceived(
}
void VibrationMessageFilter::OnVibrate(int64 milliseconds) {
+ if (!provider_.get())
+ return;
+
// Though the Blink implementation already sanitizes vibration times, don't
// trust any values passed from the renderer.
- milliseconds = std::max(kMinimumVibrationDurationMs,
- std::min(milliseconds,
- base::checked_numeric_cast<int64>(WebKit::kVibrationDurationMax)));
+ milliseconds = std::max(kMinimumVibrationDurationMs, std::min(milliseconds,
+ base::checked_numeric_cast<int64>(blink::kVibrationDurationMax)));
- if (j_vibration_message_filter_.is_null()) {
- j_vibration_message_filter_.Reset(
- Java_VibrationMessageFilter_create(
- AttachCurrentThread(),
- base::android::GetApplicationContext()));
- }
- Java_VibrationMessageFilter_vibrate(AttachCurrentThread(),
- j_vibration_message_filter_.obj(),
- milliseconds);
+ provider_->Vibrate(milliseconds);
}
void VibrationMessageFilter::OnCancelVibration() {
- Java_VibrationMessageFilter_cancelVibration(AttachCurrentThread(),
- j_vibration_message_filter_.obj());
+ if (!provider_.get())
+ return;
+
+ provider_->CancelVibration();
}
+#if !defined(OS_ANDROID)
+// static
+VibrationProvider* VibrationMessageFilter::CreateProvider() {
+ return NULL;
+}
+#endif
} // namespace content
diff --git a/chromium/content/browser/android/vibration_message_filter.h b/chromium/content/browser/vibration/vibration_message_filter.h
index 935b6106625..086cc562aa8 100644
--- a/chromium/content/browser/android/vibration_message_filter.h
+++ b/chromium/content/browser/vibration/vibration_message_filter.h
@@ -2,33 +2,34 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_ANDROID_VIBRATION_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_ANDROID_VIBRATION_MESSAGE_FILTER_H_
+#ifndef CONTENT_BROWSER_VIBRATION_VIBRATION_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_VIBRATION_VIBRATION_MESSAGE_FILTER_H_
-#include "base/android/jni_android.h"
#include "content/public/browser/browser_message_filter.h"
namespace content {
+class VibrationProvider;
+
+// VibrationMessageFilter is a browser filter for Vibration messages.
class VibrationMessageFilter : public BrowserMessageFilter {
public:
VibrationMessageFilter();
- static bool Register(JNIEnv* env);
-
private:
virtual ~VibrationMessageFilter();
-
// BrowserMessageFilter implementation.
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) OVERRIDE;
void OnVibrate(int64 milliseconds);
void OnCancelVibration();
+ static VibrationProvider* CreateProvider();
- base::android::ScopedJavaGlobalRef<jobject> j_vibration_message_filter_;
+ scoped_ptr<VibrationProvider> provider_;
+ DISALLOW_COPY_AND_ASSIGN(VibrationMessageFilter);
};
} // namespace content
-#endif // CONTENT_BROWSER_ANDROID_VIBRATION_MESSAGE_FILTER_H_
+#endif // CONTENT_BROWSER_VIBRATION_VIBRATION_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/vibration/vibration_provider_android.cc b/chromium/content/browser/vibration/vibration_provider_android.cc
new file mode 100644
index 00000000000..ba62b159e81
--- /dev/null
+++ b/chromium/content/browser/vibration/vibration_provider_android.cc
@@ -0,0 +1,57 @@
+// 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/vibration/vibration_provider_android.h"
+
+#include <algorithm>
+
+#include "base/safe_numerics.h"
+#include "content/browser/vibration/vibration_message_filter.h"
+#include "content/common/view_messages.h"
+#include "jni/VibrationProvider_jni.h"
+#include "third_party/WebKit/public/platform/WebVibration.h"
+
+using base::android::AttachCurrentThread;
+
+namespace content {
+
+VibrationProviderAndroid::VibrationProviderAndroid() {
+}
+
+VibrationProviderAndroid::~VibrationProviderAndroid() {
+}
+
+// static
+bool VibrationProviderAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+void VibrationProviderAndroid::Vibrate(int64 milliseconds) {
+ if (j_vibration_provider_.is_null()) {
+ j_vibration_provider_.Reset(
+ Java_VibrationProvider_create(
+ AttachCurrentThread(),
+ base::android::GetApplicationContext()));
+ }
+ Java_VibrationProvider_vibrate(AttachCurrentThread(),
+ j_vibration_provider_.obj(),
+ milliseconds);
+}
+
+void VibrationProviderAndroid::CancelVibration() {
+ // If somehow a cancel message is received before this object was
+ // instantiated, it means there is no current vibration anyway. Just return.
+ if (j_vibration_provider_.is_null())
+ return;
+
+ Java_VibrationProvider_cancelVibration(AttachCurrentThread(),
+ j_vibration_provider_.obj());
+}
+
+// static
+VibrationProvider* VibrationMessageFilter::CreateProvider() {
+ return new VibrationProviderAndroid();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/vibration/vibration_provider_android.h b/chromium/content/browser/vibration/vibration_provider_android.h
new file mode 100644
index 00000000000..58ada973730
--- /dev/null
+++ b/chromium/content/browser/vibration/vibration_provider_android.h
@@ -0,0 +1,30 @@
+// 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_VIBRATION_VIBRATION_PROVIDER_ANDROID_H_
+#define CONTENT_BROWSER_VIBRATION_VIBRATION_PROVIDER_ANDROID_H_
+
+#include "base/android/jni_android.h"
+#include "content/port/browser/vibration_provider.h"
+
+namespace content {
+
+class VibrationProviderAndroid : public VibrationProvider {
+ public:
+ VibrationProviderAndroid();
+
+ static bool Register(JNIEnv* env);
+
+ private:
+ virtual ~VibrationProviderAndroid();
+
+ virtual void Vibrate(int64 milliseconds) OVERRIDE;
+ virtual void CancelVibration() OVERRIDE;
+
+ base::android::ScopedJavaGlobalRef<jobject> j_vibration_provider_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_VIBRATION_VIBRATION_PROVIDER_ANDROID_H_
diff --git a/chromium/content/browser/web_contents/OWNERS b/chromium/content/browser/web_contents/OWNERS
index 58cb48d8766..4966076abb0 100644
--- a/chromium/content/browser/web_contents/OWNERS
+++ b/chromium/content/browser/web_contents/OWNERS
@@ -1,4 +1,2 @@
-jochen@chromium.org
-
# for *aura*
per-file *aura*=ben@chromium.org
diff --git a/chromium/content/browser/web_contents/aura/window_slider_unittest.cc b/chromium/content/browser/web_contents/aura/window_slider_unittest.cc
index c1ffe983275..d56d1e77e01 100644
--- a/chromium/content/browser/web_contents/aura/window_slider_unittest.cc
+++ b/chromium/content/browser/web_contents/aura/window_slider_unittest.cc
@@ -15,14 +15,14 @@
namespace content {
-void DispatchEventDuringScrollCallback(aura::RootWindow* root_window,
+void DispatchEventDuringScrollCallback(aura::WindowEventDispatcher* dispatcher,
ui::Event* event,
ui::EventType type,
const gfx::Vector2dF& delta) {
if (type != ui::ET_GESTURE_SCROLL_UPDATE)
return;
aura::RootWindowHostDelegate* delegate =
- root_window->AsRootWindowHostDelegate();
+ dispatcher->AsRootWindowHostDelegate();
if (event->IsMouseEvent())
delegate->OnHostMouseEvent(static_cast<ui::MouseEvent*>(event));
else if (event->IsKeyEvent())
@@ -269,7 +269,7 @@ TEST_F(WindowSliderTest, WindowSlideIsCancelledOnEvent) {
base::TimeDelta::FromMilliseconds(10),
1,
base::Bind(&DispatchEventDuringScrollCallback,
- root_window(),
+ root_window()->GetDispatcher(),
base::Owned(events[i])));
EXPECT_TRUE(slider_delegate.created_back_layer());
EXPECT_TRUE(slider_delegate.slide_aborted());
diff --git a/chromium/content/browser/web_contents/debug_urls.h b/chromium/content/browser/web_contents/debug_urls.h
deleted file mode 100644
index 79da209c53a..00000000000
--- a/chromium/content/browser/web_contents/debug_urls.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_BROWSER_WEB_CONTENTS_DEBUG_URLS_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_DEBUG_URLS_H_
-
-#include "content/public/common/page_transition_types.h"
-
-class GURL;
-
-namespace content {
-
-// Checks if the given url is a url used for debugging purposes, and if so
-// handles it and returns true.
-bool HandleDebugURL(const GURL& url, PageTransition transition);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_WEB_CONTENTS_DEBUG_URLS_H_
diff --git a/chromium/content/browser/web_contents/drag_utils_gtk.cc b/chromium/content/browser/web_contents/drag_utils_gtk.cc
index 8164c5392e6..279ae9daa48 100644
--- a/chromium/content/browser/web_contents/drag_utils_gtk.cc
+++ b/chromium/content/browser/web_contents/drag_utils_gtk.cc
@@ -4,12 +4,12 @@
#include "content/browser/web_contents/drag_utils_gtk.h"
-using WebKit::WebDragOperationsMask;
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationNone;
-using WebKit::WebDragOperationCopy;
-using WebKit::WebDragOperationLink;
-using WebKit::WebDragOperationMove;
+using blink::WebDragOperationsMask;
+using blink::WebDragOperation;
+using blink::WebDragOperationNone;
+using blink::WebDragOperationCopy;
+using blink::WebDragOperationLink;
+using blink::WebDragOperationMove;
namespace content {
diff --git a/chromium/content/browser/web_contents/drag_utils_gtk.h b/chromium/content/browser/web_contents/drag_utils_gtk.h
index 7232df136ca..f6d883924c8 100644
--- a/chromium/content/browser/web_contents/drag_utils_gtk.h
+++ b/chromium/content/browser/web_contents/drag_utils_gtk.h
@@ -15,8 +15,8 @@ namespace content {
// Convenience methods for converting between web drag operations and the GDK
// equivalent.
CONTENT_EXPORT GdkDragAction WebDragOpToGdkDragAction(
- WebKit::WebDragOperationsMask op);
-CONTENT_EXPORT WebKit::WebDragOperationsMask GdkDragActionToWebDragOp(
+ blink::WebDragOperationsMask op);
+CONTENT_EXPORT blink::WebDragOperationsMask GdkDragActionToWebDragOp(
GdkDragAction action);
} // namespace content
diff --git a/chromium/content/browser/web_contents/frame_tree_node.cc b/chromium/content/browser/web_contents/frame_tree_node.cc
deleted file mode 100644
index dba0977df25..00000000000
--- a/chromium/content/browser/web_contents/frame_tree_node.cc
+++ /dev/null
@@ -1,37 +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/web_contents/frame_tree_node.h"
-
-#include <queue>
-
-#include "base/stl_util.h"
-
-namespace content {
-
-FrameTreeNode::FrameTreeNode(int64 frame_id, const std::string& name)
- : frame_id_(frame_id),
- frame_name_(name) {
-}
-
-FrameTreeNode::~FrameTreeNode() {
-}
-
-void FrameTreeNode::AddChild(FrameTreeNode* child) {
- children_.push_back(child);
-}
-
-void FrameTreeNode::RemoveChild(int64 child_id) {
- std::vector<FrameTreeNode*>::iterator iter;
-
- for (iter = children_.begin(); iter != children_.end(); ++iter) {
- if ((*iter)->frame_id() == child_id)
- break;
- }
-
- if (iter != children_.end())
- children_.erase(iter);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/web_contents/frame_tree_node.h b/chromium/content/browser/web_contents/frame_tree_node.h
deleted file mode 100644
index 76d2194d5c4..00000000000
--- a/chromium/content/browser/web_contents/frame_tree_node.h
+++ /dev/null
@@ -1,76 +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_WEB_CONTENTS_FRAME_TREE_NODE_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_FRAME_TREE_NODE_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_vector.h"
-#include "content/common/content_export.h"
-#include "url/gurl.h"
-
-namespace content {
-
-// Any page that contains iframes has a tree structure of the frames in the
-// renderer process. We are mirroring this tree in the browser process. This
-// class represents a node in this tree and is a wrapper for all objects that
-// are frame-specific (as opposed to page-specific).
-class CONTENT_EXPORT FrameTreeNode {
- public:
- FrameTreeNode(int64 frame_id, const std::string& name);
- ~FrameTreeNode();
-
- // This method takes ownership of the child pointer.
- void AddChild(FrameTreeNode* child);
- void RemoveChild(int64 child_id);
-
- int64 frame_id() const {
- return frame_id_;
- }
-
- const std::string& frame_name() const {
- return frame_name_;
- }
-
- size_t child_count() const {
- return children_.size();
- }
-
- FrameTreeNode* child_at(size_t index) const {
- return children_[index];
- }
-
- const GURL& current_url() const {
- return current_url_;
- }
-
- void set_current_url(const GURL& url) {
- current_url_ = url;
- }
-
- private:
- // The unique identifier for the frame in the page.
- int64 frame_id_;
-
- // The assigned name of the frame. This name can be empty, unlike the unique
- // name generated internally in the DOM tree.
- std::string frame_name_;
-
- // The immediate children of this specific frame.
- ScopedVector<FrameTreeNode> children_;
-
- // Track the current frame's last committed URL, so we can estimate the
- // process impact of out-of-process iframes.
- // TODO(creis): Remove this when we can store subframe URLs in the
- // NavigationController.
- GURL current_url_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameTreeNode);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_WEB_CONTENTS_FRAME_TREE_NODE_H_
diff --git a/chromium/content/browser/web_contents/touch_editable_impl_aura.cc b/chromium/content/browser/web_contents/touch_editable_impl_aura.cc
index ada5976aa7b..ed002c7d9c6 100644
--- a/chromium/content/browser/web_contents/touch_editable_impl_aura.cc
+++ b/chromium/content/browser/web_contents/touch_editable_impl_aura.cc
@@ -94,6 +94,9 @@ void TouchEditableImplAura::OverscrollCompleted() {
// implementation:
void TouchEditableImplAura::StartTouchEditing() {
+ if (!rwhva_ || !rwhva_->HasFocus())
+ return;
+
if (!touch_selection_controller_) {
touch_selection_controller_.reset(
ui::TouchSelectionController::create(this));
@@ -195,7 +198,7 @@ bool TouchEditableImplAura::HandleInputEvent(const ui::Event* event) {
void TouchEditableImplAura::GestureEventAck(int gesture_event_type) {
DCHECK(rwhva_);
- if (gesture_event_type == WebKit::WebInputEvent::GestureTap &&
+ if (gesture_event_type == blink::WebInputEvent::GestureTap &&
text_input_type_ != ui::TEXT_INPUT_TYPE_NONE &&
is_tap_on_focused_textfield_) {
StartTouchEditing();
@@ -203,9 +206,9 @@ void TouchEditableImplAura::GestureEventAck(int gesture_event_type) {
touch_selection_controller_->SelectionChanged();
}
- if (gesture_event_type == WebKit::WebInputEvent::GestureLongPress)
+ if (gesture_event_type == blink::WebInputEvent::GestureLongPress)
selection_gesture_in_process_ = false;
- if (gesture_event_type == WebKit::WebInputEvent::GestureTap) {
+ if (gesture_event_type == blink::WebInputEvent::GestureTap) {
if (tap_gesture_tap_count_queue_.front() > 1)
selection_gesture_in_process_ = false;
tap_gesture_tap_count_queue_.pop();
@@ -304,9 +307,9 @@ bool TouchEditableImplAura::IsCommandIdEnabled(int command_id) const {
case IDS_APP_COPY:
return has_selection;
case IDS_APP_PASTE: {
- string16 result;
+ base::string16 result;
ui::Clipboard::GetForCurrentThread()->ReadText(
- ui::Clipboard::BUFFER_STANDARD, &result);
+ ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
return editable && !result.empty();
}
case IDS_APP_DELETE:
diff --git a/chromium/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc b/chromium/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
index 6c5fa2a1bbf..f8c1f5f91b0 100644
--- a/chromium/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
+++ b/chromium/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
@@ -28,7 +28,6 @@
namespace content {
-// TODO(mohsen): Remove logs if the test showed no flakiness anymore.
class TestTouchEditableImplAura : public TouchEditableImplAura {
public:
TestTouchEditableImplAura()
@@ -37,62 +36,29 @@ class TestTouchEditableImplAura : public TouchEditableImplAura {
gesture_ack_callback_arrived_(false),
waiting_for_gesture_ack_callback_(false) {}
- void Reset() {
- LOG(INFO) << "TestTouchEditableImplAura::Reset()";
+ virtual void Reset() {
selection_changed_callback_arrived_ = false;
waiting_for_selection_changed_callback_ = false;
gesture_ack_callback_arrived_ = false;
waiting_for_gesture_ack_callback_ = false;
}
- virtual void StartTouchEditing() OVERRIDE {
- LOG(INFO) << "TestTouchEditableImplAura::StartTouchEditing()";
- TouchEditableImplAura::StartTouchEditing();
- }
-
- virtual void EndTouchEditing() OVERRIDE {
- LOG(INFO) << "TestTouchEditableImplAura::EndTouchEditing()";
- TouchEditableImplAura::EndTouchEditing();
- }
-
virtual void OnSelectionOrCursorChanged(const gfx::Rect& anchor,
const gfx::Rect& focus) OVERRIDE {
- LOG(INFO) << "TestTouchEditableImplAura::OnSelectionOrCursorChanged("
- << anchor.ToString() << ", " << focus.ToString() << ")";
selection_changed_callback_arrived_ = true;
TouchEditableImplAura::OnSelectionOrCursorChanged(anchor, focus);
if (waiting_for_selection_changed_callback_)
selection_changed_wait_run_loop_->Quit();
}
- virtual void OnTextInputTypeChanged(ui::TextInputType type) OVERRIDE {
- LOG(INFO) << "TestTouchEditableImplAura::OnTextInputTypeChanged("
- << type << ")";
- TouchEditableImplAura::OnTextInputTypeChanged(type);
- }
-
- virtual bool HandleInputEvent(const ui::Event* event) OVERRIDE {
- LOG(INFO) << "TestTouchEditableImplAura::HandleInputEvent("
- << event->type() << ")";
- return TouchEditableImplAura::HandleInputEvent(event);
- }
-
virtual void GestureEventAck(int gesture_event_type) OVERRIDE {
- LOG(INFO) << "TestTouchEditableImplAura::GestureEventAck("
- << gesture_event_type << ")";
gesture_ack_callback_arrived_ = true;
TouchEditableImplAura::GestureEventAck(gesture_event_type);
if (waiting_for_gesture_ack_callback_)
gesture_ack_wait_run_loop_->Quit();
}
- virtual void OnViewDestroyed() OVERRIDE {
- LOG(INFO) << "TestTouchEditableImplAura::OnViewDestroyed()";
- TouchEditableImplAura::OnViewDestroyed();
- }
-
- void WaitForSelectionChangeCallback() {
- LOG(INFO) << "TestTouchEditableImplAura::WaitForSelectionChangeCallback()";
+ virtual void WaitForSelectionChangeCallback() {
if (selection_changed_callback_arrived_)
return;
waiting_for_selection_changed_callback_ = true;
@@ -100,8 +66,7 @@ class TestTouchEditableImplAura : public TouchEditableImplAura {
selection_changed_wait_run_loop_->Run();
}
- void WaitForGestureAck() {
- LOG(INFO) << "TestTouchEditableImplAura::WaitForGestureAck()";
+ virtual void WaitForGestureAck() {
if (gesture_ack_callback_arrived_)
return;
waiting_for_gesture_ack_callback_ = true;
@@ -123,6 +88,31 @@ class TestTouchEditableImplAura : public TouchEditableImplAura {
DISALLOW_COPY_AND_ASSIGN(TestTouchEditableImplAura);
};
+// This class ignores mouse-moved, mouse-entered and mouse-exited events
+// without passing them to TouchEditableImplAura. Normally, we should not
+// receive these events; but, sometimes we receive them which breaks the tests
+// and makes them flaky: crbug.com/276992.
+class TestTouchEditableImplAuraIgnoreMouseMovement
+ : public TestTouchEditableImplAura {
+ public:
+ TestTouchEditableImplAuraIgnoreMouseMovement() {}
+
+ virtual bool HandleInputEvent(const ui::Event* event) OVERRIDE {
+ if (event->type() == ui::ET_MOUSE_ENTERED ||
+ event->type() == ui::ET_MOUSE_MOVED ||
+ event->type() == ui::ET_MOUSE_EXITED) {
+ return false;
+ }
+ return TestTouchEditableImplAura::HandleInputEvent(event);
+ }
+
+ protected:
+ virtual ~TestTouchEditableImplAuraIgnoreMouseMovement() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestTouchEditableImplAuraIgnoreMouseMovement);
+};
+
class TouchEditableImplAuraTest : public ContentBrowserTest {
public:
TouchEditableImplAuraTest() {}
@@ -147,10 +137,9 @@ class TouchEditableImplAuraTest : public ContentBrowserTest {
NavigateToURL(shell(), test_url);
aura::Window* content =
shell()->web_contents()->GetView()->GetContentNativeView();
- content->GetRootWindow()->SetHostSize(gfx::Size(800, 600));
+ content->GetDispatcher()->SetHostSize(gfx::Size(800, 600));
}
- // TODO(mohsen): Remove logs if the test showed no flakiness anymore.
void TestTouchSelectionOriginatingFromWebpage() {
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/touch_selection.html"));
@@ -160,7 +149,8 @@ class TouchEditableImplAuraTest : public ContentBrowserTest {
web_contents->GetRenderViewHost());
WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
web_contents->GetView());
- TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
+ TestTouchEditableImplAura* touch_editable =
+ new TestTouchEditableImplAuraIgnoreMouseMovement;
view_aura->SetTouchEditableForTest(touch_editable);
RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
web_contents->GetRenderWidgetHostView());
@@ -168,28 +158,23 @@ class TouchEditableImplAuraTest : public ContentBrowserTest {
aura::test::EventGenerator generator(content->GetRootWindow(), content);
gfx::Rect bounds = content->GetBoundsInRootWindow();
- LOG(INFO) << "Select text and wait for selection change.";
touch_editable->Reset();
ExecuteSyncJSFunction(view_host, "select_all_text()");
touch_editable->WaitForSelectionChangeCallback();
- LOG(INFO) << "Tap on selection to bring up handles.";
// Tap inside selection to bring up selection handles.
generator.GestureTapAt(gfx::Point(bounds.x() + 10, bounds.y() + 10));
EXPECT_EQ(touch_editable->rwhva_, rwhva);
- LOG(INFO) << "Get selection.";
scoped_ptr<base::Value> value =
content::ExecuteScriptAndGetValue(view_host, "get_selection()");
std::string selection;
value->GetAsString(&selection);
- LOG(INFO) << "Test handles and selection.";
// Check if selection handles are showing.
EXPECT_TRUE(touch_editable->touch_selection_controller_.get());
EXPECT_STREQ("Some text we can select", selection.c_str());
- LOG(INFO) << "Drag handles to modify the selection.";
// Lets move the handles a bit to modify the selection
touch_editable->Reset();
generator.GestureScrollSequence(
@@ -197,11 +182,8 @@ class TouchEditableImplAuraTest : public ContentBrowserTest {
gfx::Point(30, 47),
base::TimeDelta::FromMilliseconds(20),
5);
- LOG(INFO) << "Handle moved. Now, waiting for selection to change.";
touch_editable->WaitForSelectionChangeCallback();
- LOG(INFO) << "Selection changed.";
- LOG(INFO) << "Test selection.";
EXPECT_TRUE(touch_editable->touch_selection_controller_.get());
value = content::ExecuteScriptAndGetValue(view_host, "get_selection()");
value->GetAsString(&selection);
@@ -321,7 +303,6 @@ class TouchEditableImplAuraTest : public ContentBrowserTest {
EXPECT_TRUE(touch_editable->touch_selection_controller_.get());
}
- // TODO(mohsen): Remove logs if the test showed no flakiness anymore.
void TestTouchCursorInTextfield() {
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/touch_selection.html"));
@@ -331,7 +312,8 @@ class TouchEditableImplAuraTest : public ContentBrowserTest {
web_contents->GetRenderViewHost());
WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
web_contents->GetView());
- TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
+ TestTouchEditableImplAura* touch_editable =
+ new TestTouchEditableImplAuraIgnoreMouseMovement;
view_aura->SetTouchEditableForTest(touch_editable);
RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
web_contents->GetRenderWidgetHostView());
@@ -340,31 +322,23 @@ class TouchEditableImplAuraTest : public ContentBrowserTest {
gfx::Rect bounds = content->GetBoundsInRootWindow();
EXPECT_EQ(touch_editable->rwhva_, rwhva);
- LOG(INFO) << "Focus the textfield.";
ExecuteSyncJSFunction(view_host, "focus_textfield()");
- LOG(INFO) << "Wait for selection to change.";
touch_editable->WaitForSelectionChangeCallback();
// Tap textfield
touch_editable->Reset();
- LOG(INFO) << "Tap in the textfield.";
generator.GestureTapAt(gfx::Point(bounds.x() + 50, bounds.y() + 40));
- LOG(INFO) << "Wait for selection to change.";
touch_editable->WaitForSelectionChangeCallback();
- LOG(INFO) << "Wait for tap-down ACK.";
- touch_editable->WaitForGestureAck(); // Wait for Tap Down Ack
+ // No Tap Down Ack is coming, it's async.
touch_editable->Reset();
- LOG(INFO) << "Wait for tap ACK.";
touch_editable->WaitForGestureAck(); // Wait for Tap Ack.
- LOG(INFO) << "Test the touch selection handle.";
// Check if cursor handle is showing.
ui::TouchSelectionController* controller =
touch_editable->touch_selection_controller_.get();
EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, touch_editable->text_input_type_);
EXPECT_TRUE(controller);
- LOG(INFO) << "Test cursor position.";
scoped_ptr<base::Value> value =
content::ExecuteScriptAndGetValue(view_host, "get_cursor_position()");
int cursor_pos = -1;
@@ -372,15 +346,12 @@ class TouchEditableImplAuraTest : public ContentBrowserTest {
EXPECT_NE(-1, cursor_pos);
// Move the cursor handle.
- LOG(INFO) << "Drag the touch selection handle to change its position.";
generator.GestureScrollSequence(
gfx::Point(50, 59),
gfx::Point(10, 59),
base::TimeDelta::FromMilliseconds(20),
1);
- LOG(INFO) << "Wait for cursor position to change.";
touch_editable->WaitForSelectionChangeCallback();
- LOG(INFO) << "Check cursor position is changed.";
EXPECT_TRUE(touch_editable->touch_selection_controller_.get());
value = content::ExecuteScriptAndGetValue(view_host,
"get_cursor_position()");
diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc
new file mode 100644
index 00000000000..88922b1922a
--- /dev/null
+++ b/chromium/content/browser/web_contents/web_contents_android.cc
@@ -0,0 +1,58 @@
+// 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/web_contents/web_contents_android.h"
+
+#include "base/android/jni_android.h"
+#include "base/logging.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "jni/WebContentsImpl_jni.h"
+
+using base::android::AttachCurrentThread;
+
+namespace content {
+
+// static
+WebContents* WebContents::FromJavaWebContents(
+ jobject jweb_contents_android) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!jweb_contents_android)
+ return NULL;
+
+ WebContentsAndroid* web_contents_android =
+ reinterpret_cast<WebContentsAndroid*>(
+ Java_WebContentsImpl_getNativePointer(AttachCurrentThread(),
+ jweb_contents_android));
+ if (!web_contents_android)
+ return NULL;
+ return web_contents_android->web_contents();
+}
+
+// static
+bool WebContentsAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+WebContentsAndroid::WebContentsAndroid(WebContents* web_contents)
+ : web_contents_(web_contents),
+ navigation_controller_(&(web_contents->GetController())) {
+ JNIEnv* env = AttachCurrentThread();
+ obj_.Reset(env,
+ Java_WebContentsImpl_create(
+ env,
+ reinterpret_cast<intptr_t>(this),
+ navigation_controller_.GetJavaObject().obj()).obj());
+}
+
+WebContentsAndroid::~WebContentsAndroid() {
+ Java_WebContentsImpl_destroy(AttachCurrentThread(), obj_.obj());
+}
+
+base::android::ScopedJavaLocalRef<jobject>
+WebContentsAndroid::GetJavaObject() {
+ return base::android::ScopedJavaLocalRef<jobject>(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
new file mode 100644
index 00000000000..a9595e2a4dc
--- /dev/null
+++ b/chromium/content/browser/web_contents/web_contents_android.h
@@ -0,0 +1,46 @@
+// 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_WEB_CONTENTS_WEB_CONTENTS_ANDROID_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_ANDROID_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/supports_user_data.h"
+#include "content/browser/frame_host/navigation_controller_android.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class WebContents;
+
+// Android wrapper around WebContents that provides safer passage from java and
+// back to native and provides java with a means of communicating with its
+// native counterpart.
+class CONTENT_EXPORT WebContentsAndroid
+ : public base::SupportsUserData::Data {
+ public:
+ static bool Register(JNIEnv* env);
+
+ explicit WebContentsAndroid(WebContents* web_contents);
+ virtual ~WebContentsAndroid();
+
+ WebContents* web_contents() const { return web_contents_; }
+
+ base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
+
+ private:
+ WebContents* web_contents_;
+ NavigationControllerAndroid navigation_controller_;
+ base::android::ScopedJavaGlobalRef<jobject> obj_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebContentsAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_ANDROID_H_
diff --git a/chromium/content/browser/web_contents/web_contents_delegate_unittest.cc b/chromium/content/browser/web_contents/web_contents_delegate_unittest.cc
index d5d60c37252..0de5919edd2 100644
--- a/chromium/content/browser/web_contents/web_contents_delegate_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_delegate_unittest.cc
@@ -5,10 +5,10 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/test/test_browser_context.h"
+#include "content/test/test_render_view_host.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
diff --git a/chromium/content/browser/web_contents/web_contents_drag_win.cc b/chromium/content/browser/web_contents/web_contents_drag_win.cc
index cb24210c3b9..ffc8713f860 100644
--- a/chromium/content/browser/web_contents/web_contents_drag_win.cc
+++ b/chromium/content/browser/web_contents/web_contents_drag_win.cc
@@ -38,10 +38,10 @@
#include "ui/gfx/screen.h"
#include "ui/gfx/size.h"
-using WebKit::WebDragOperationsMask;
-using WebKit::WebDragOperationCopy;
-using WebKit::WebDragOperationLink;
-using WebKit::WebDragOperationMove;
+using blink::WebDragOperationsMask;
+using blink::WebDragOperationCopy;
+using blink::WebDragOperationLink;
+using blink::WebDragOperationMove;
namespace content {
namespace {
@@ -227,7 +227,7 @@ void WebContentsDragWin::PrepareDragForDownload(
const GURL& page_url,
const std::string& page_encoding) {
// Parse the download metadata.
- string16 mime_type;
+ base::string16 mime_type;
base::FilePath file_name;
GURL download_url;
if (!ParseDownloadMetadata(drop_data.download_metadata,
@@ -247,8 +247,8 @@ void WebContentsDragWin::PrepareDragForDownload(
UTF16ToUTF8(mime_type),
default_name);
base::FilePath temp_dir_path;
- if (!file_util::CreateNewTempDirectory(
- FILE_PATH_LITERAL("chrome_drag"), &temp_dir_path))
+ if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_drag"),
+ &temp_dir_path))
return;
base::FilePath download_path =
temp_dir_path.Append(generated_download_file_name);
@@ -284,7 +284,7 @@ void WebContentsDragWin::PrepareDragForFileContents(
// Images without ALT text will only have a file extension so we need to
// synthesize one from the provided extension and URL.
if (file_name.BaseName().RemoveExtension().empty()) {
- const string16 extension = file_name.Extension();
+ const base::string16 extension = file_name.Extension();
// Retrieve the name from the URL.
file_name = base::FilePath(
net::GetSuggestedFilename(drop_data.url, "", "", "", "", ""));
diff --git a/chromium/content/browser/web_contents/web_contents_drag_win.h b/chromium/content/browser/web_contents/web_contents_drag_win.h
index b6a98058196..943cc7d1108 100644
--- a/chromium/content/browser/web_contents/web_contents_drag_win.h
+++ b/chromium/content/browser/web_contents/web_contents_drag_win.h
@@ -46,7 +46,7 @@ class CONTENT_EXPORT WebContentsDragWin
// Called on UI thread.
void StartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask ops,
+ blink::WebDragOperationsMask ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset);
void CancelDrag();
@@ -74,7 +74,7 @@ class CONTENT_EXPORT WebContentsDragWin
// progress. No further processing should be done beyond this return point
// because the instance has been destroyed.
bool DoDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask ops,
+ blink::WebDragOperationsMask ops,
const GURL& page_url,
const std::string& page_encoding,
const gfx::ImageSkia& image,
@@ -82,7 +82,7 @@ class CONTENT_EXPORT WebContentsDragWin
// Called on drag-and-drop thread.
void StartBackgroundDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask ops,
+ blink::WebDragOperationsMask ops,
const GURL& page_url,
const std::string& page_encoding,
const gfx::ImageSkia& image,
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index 26e6baa746d..6b6cf00819e 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -12,13 +12,12 @@
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/metrics/stats_counters.h"
+#include "base/process/process.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/sys_info.h"
#include "base/time/time.h"
-#include "cc/base/switches.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
@@ -29,24 +28,26 @@
#include "content/browser/download/download_stats.h"
#include "content/browser/download/mhtml_generation_manager.h"
#include "content/browser/download/save_package.h"
-#include "content/browser/gpu/compositor_util.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
-#include "content/browser/gpu/gpu_process_host.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigator_impl.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/host_zoom_map_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/message_port_message_filter.h"
+#include "content/browser/message_port_service.h"
#include "content/browser/power_save_blocker_impl.h"
#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_host_impl.h"
#include "content/browser/site_instance_impl.h"
-#include "content/browser/web_contents/interstitial_page_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/browser/web_contents/web_contents_view_guest.h"
#include "content/browser/webui/generic_handler.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/webui/web_ui_impl.h"
#include "content/common/browser_plugin/browser_plugin_constants.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
+#include "content/common/frame_messages.h"
#include "content/common/image_messages.h"
#include "content/common/ssl_status_serialization.h"
#include "content/common/view_messages.h"
@@ -75,18 +76,16 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/page_zoom.h"
+#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
+#include "content/public/common/url_utils.h"
#include "net/base/mime_util.h"
#include "net/base/net_util.h"
-#include "net/base/network_change_notifier.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 "ui/base/layout.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/display.h"
#include "ui/gfx/screen.h"
#include "ui/gl/gl_switches.h"
@@ -94,6 +93,9 @@
#if defined(OS_ANDROID)
#include "content/browser/android/date_time_chooser_android.h"
+#include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
+#include "content/browser/web_contents/web_contents_android.h"
+#include "content/common/java_bridge_messages.h"
#include "content/public/browser/android/content_view_core.h"
#endif
@@ -102,10 +104,6 @@
#include "ui/gl/io_surface_support_mac.h"
#endif
-#if defined(OS_ANDROID)
-#include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
-#endif
-
// Cross-Site Navigations
//
// If a WebContentsImpl is told to navigate to a different web site (as
@@ -113,53 +111,60 @@
// a new RenderViewHost dedicated to the new SiteInstance. This works as
// follows:
//
-// - Navigate determines whether the destination is cross-site, and if so,
+// - RVHM::Navigate determines whether the destination is cross-site, and if so,
// it creates a pending_render_view_host_.
// - The pending RVH is "suspended," so that no navigation messages are sent to
-// its renderer until the onbeforeunload JavaScript handler has a chance to
+// its renderer until the beforeunload JavaScript handler has a chance to
// run in the current RVH.
// - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
-// that it has a pending cross-site request. ResourceDispatcherHost will
-// check for this when the response arrives.
-// - The current RVH runs its onbeforeunload handler. If it returns false, we
+// that it has a pending cross-site request. We will check this on the IO
+// thread when deciding how to handle the response.
+// - The current RVH runs its beforeunload handler. If it returns false, we
// cancel all the pending logic. Otherwise we allow the pending RVH to send
// the navigation request to its renderer.
// - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
-// main resource load on the pending RVH. It checks CrossSiteRequestManager
-// to see that it is a cross-site request, and installs a
-// CrossSiteResourceHandler.
+// main resource load on the pending RVH. It creates a
+// CrossSiteResourceHandler to check whether a process swap is needed when
+// the request is ready to commit.
// - When RDH receives a response, the BufferedResourceHandler determines
// whether it is a download. If so, it sends a message to the new renderer
// causing it to cancel the request, and the download proceeds. For now, the
// pending RVH remains until the next DidNavigate event for this
// WebContentsImpl. This isn't ideal, but it doesn't affect any functionality.
// - After RDH receives a response and determines that it is safe and not a
-// download, it pauses the response to first run the old page's onunload
-// handler. It does this by asynchronously calling the OnCrossSiteResponse
-// method of WebContentsImpl on the UI thread, which sends a SwapOut message
-// to the current RVH.
-// - Once the onunload handler is finished, a SwapOut_ACK message is sent to
-// the ResourceDispatcherHost, who unpauses the response. Data is then sent
-// to the pending RVH.
+// download, the CrossSiteResourceHandler checks whether a process swap is
+// needed (either because CrossSiteRequestManager has state for it or because
+// a transfer was needed for a redirect).
+// - If so, CrossSiteResourceHandler pauses the response to first run the old
+// page's unload handler. It does this by asynchronously calling the
+// OnCrossSiteResponse method of RenderFrameHostManager on the UI thread,
+// which sends a SwapOut message to the current RVH.
+// - Once the unload handler is finished, RVHM::SwappedOut checks if a transfer
+// to a new process is needed, based on the stored pending_nav_params_. (This
+// is independent of whether we started out with a cross-process navigation.)
+// - If not, it just tells the ResourceDispatcherHost to resume the response
+// to its current RenderViewHost.
+// - If so, it cancels the current pending RenderViewHost and sets up a new
+// navigation using RequestTransferURL. When the transferred request
+// arrives in the ResourceDispatcherHost, we transfer the response and
+// resume it.
// - The pending renderer sends a FrameNavigate message that invokes the
// DidNavigate method. This replaces the current RVH with the
// pending RVH.
-// - The previous renderer is kept swapped out in RenderViewHostManager in case
+// - The previous renderer is kept swapped out in RenderFrameHostManager in case
// the user goes back. The process only stays live if another tab is using
// it, but if so, the existing frame relationships will be maintained.
namespace content {
namespace {
-// Amount of time we wait between when a key event is received and the renderer
-// is queried for its state and pushed to the NavigationEntry.
-const int kQueryStateDelay = 5000;
-
-const int kSyncWaitDelay = 40;
-
const char kDotGoogleDotCom[] = ".google.com";
-base::LazyInstance<std::vector<WebContents::CreatedCallback> >
+#if defined(OS_ANDROID)
+const char kWebContentsAndroidKey[] = "web_contents_android";
+#endif // OS_ANDROID
+
+base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> >
g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
static int StartDownload(content::RenderViewHost* rvh,
@@ -208,6 +213,7 @@ void MakeNavigateParams(const NavigationEntryImpl& entry,
ViewMsg_Navigate_Params* params) {
params->page_id = entry.GetPageID();
params->should_clear_history_list = entry.should_clear_history_list();
+ params->should_replace_current_entry = entry.should_replace_entry();
if (entry.should_clear_history_list()) {
// Set the history list related parameters to the same values a
// NavigationController would return before its first navigation. This will
@@ -221,6 +227,7 @@ void MakeNavigateParams(const NavigationEntryImpl& entry,
controller.GetLastCommittedEntryIndex();
params->current_history_list_length = controller.GetEntryCount();
}
+ params->url = entry.GetURL();
if (!entry.GetBaseURLForDataURL().is_empty()) {
params->base_url_for_data_url = entry.GetBaseURLForDataURL();
params->history_url_for_data_url = entry.GetVirtualURL();
@@ -240,24 +247,14 @@ void MakeNavigateParams(const NavigationEntryImpl& entry,
// Avoid downloading when in view-source mode.
params->allow_download = !entry.IsViewSourceMode();
params->is_post = entry.GetHasPostData();
- if(entry.GetBrowserInitiatedPostData()) {
- params->browser_initiated_post_data.assign(
- entry.GetBrowserInitiatedPostData()->front(),
- entry.GetBrowserInitiatedPostData()->front() +
- entry.GetBrowserInitiatedPostData()->size());
-
+ if (entry.GetBrowserInitiatedPostData()) {
+ params->browser_initiated_post_data.assign(
+ entry.GetBrowserInitiatedPostData()->front(),
+ entry.GetBrowserInitiatedPostData()->front() +
+ entry.GetBrowserInitiatedPostData()->size());
}
- if (reload_type == NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL &&
- entry.GetOriginalRequestURL().is_valid() && !entry.GetHasPostData()) {
- // We may have been redirected when navigating to the current URL.
- // Use the URL the user originally intended to visit, if it's valid and if a
- // POST wasn't involved; the latter case avoids issues with sending data to
- // the wrong page.
- params->url = entry.GetOriginalRequestURL();
- } else {
- params->url = entry.GetURL();
- }
+ params->redirects = entry.redirect_chain();
params->can_load_local_resources = entry.GetCanLoadLocalResources();
params->frame_to_navigate = entry.GetFrameToNavigate();
@@ -274,6 +271,14 @@ void NotifyCacheOnIO(
GetCache()->OnExternalCacheHit(url, http_method);
}
+// Helper function for retrieving all the sites in a frame tree.
+bool CollectSites(BrowserContext* context,
+ std::set<GURL>* sites,
+ FrameTreeNode* node) {
+ sites->insert(SiteInstance::GetSiteForURL(context, node->current_url()));
+ return true;
+}
+
} // namespace
WebContents* WebContents::Create(const WebContents::CreateParams& params) {
@@ -299,11 +304,11 @@ WebContents* WebContents::CreateWithSessionStorage(
return new_contents;
}
-void WebContents::AddCreatedCallback(const CreatedCallback& callback) {
+void WebContentsImpl::AddCreatedCallback(const CreatedCallback& callback) {
g_created_callbacks.Get().push_back(callback);
}
-void WebContents::RemoveCreatedCallback(const CreatedCallback& callback) {
+void WebContentsImpl::RemoveCreatedCallback(const CreatedCallback& callback) {
for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
if (g_created_callbacks.Get().at(i).Equals(callback)) {
g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
@@ -348,12 +353,13 @@ WebContentsImpl::WebContentsImpl(
#if defined(OS_WIN) && defined(USE_AURA)
accessible_parent_(NULL),
#endif
- render_manager_(this, this, this),
+ frame_tree_(new NavigatorImpl(&controller_, this),
+ this, this, this, this),
is_loading_(false),
crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
crashed_error_code_(0),
waiting_for_response_(false),
- load_state_(net::LOAD_STATE_IDLE, string16()),
+ load_state_(net::LOAD_STATE_IDLE, base::string16()),
upload_size_(0),
upload_position_(0),
displayed_insecure_content_(false),
@@ -368,10 +374,13 @@ WebContentsImpl::WebContentsImpl(
maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor * 100)),
temporary_zoom_settings_(false),
color_chooser_identifier_(0),
- message_source_(NULL),
+ render_view_message_source_(NULL),
fullscreen_widget_routing_id_(MSG_ROUTING_NONE) {
for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
g_created_callbacks.Get().at(i).Run(this);
+ frame_tree_.SetFrameRemoveListener(
+ base::Bind(&WebContentsImpl::OnFrameRemoved,
+ base::Unretained(this)));
}
WebContentsImpl::~WebContentsImpl() {
@@ -411,6 +420,17 @@ WebContentsImpl::~WebContentsImpl() {
}
#endif
+ RenderViewHost* pending_rvh = GetRenderManager()->pending_render_view_host();
+ if (pending_rvh) {
+ FOR_EACH_OBSERVER(WebContentsObserver,
+ observers_,
+ RenderViewDeleted(pending_rvh));
+ }
+
+ FOR_EACH_OBSERVER(WebContentsObserver,
+ observers_,
+ RenderViewDeleted(GetRenderManager()->current_host()));
+
FOR_EACH_OBSERVER(WebContentsObserver,
observers_,
WebContentsImplDestroyed());
@@ -443,7 +463,7 @@ BrowserPluginGuest* WebContentsImpl::CreateGuest(
// This makes |new_contents| act as a guest.
// For more info, see comment above class BrowserPluginGuest.
BrowserPluginGuest::Create(
- guest_instance_id, new_contents, extra_params.Pass());
+ guest_instance_id, site_instance, new_contents, extra_params.Pass());
WebContents::CreateParams create_params(browser_context, site_instance);
new_contents->Init(create_params);
@@ -456,209 +476,19 @@ BrowserPluginGuest* WebContentsImpl::CreateGuest(
return new_contents->browser_plugin_guest_.get();
}
-WebPreferences WebContentsImpl::GetWebkitPrefs(RenderViewHost* rvh,
- const GURL& url) {
- TRACE_EVENT0("browser", "WebContentsImpl::GetWebkitPrefs");
- WebPreferences prefs;
-
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-
- prefs.javascript_enabled =
- !command_line.HasSwitch(switches::kDisableJavaScript);
- prefs.web_security_enabled =
- !command_line.HasSwitch(switches::kDisableWebSecurity);
- prefs.plugins_enabled =
- !command_line.HasSwitch(switches::kDisablePlugins);
- prefs.java_enabled =
- !command_line.HasSwitch(switches::kDisableJava);
-
- prefs.remote_fonts_enabled =
- !command_line.HasSwitch(switches::kDisableRemoteFonts);
- prefs.xss_auditor_enabled =
- !command_line.HasSwitch(switches::kDisableXSSAuditor);
- prefs.application_cache_enabled =
- !command_line.HasSwitch(switches::kDisableApplicationCache);
-
- prefs.local_storage_enabled =
- !command_line.HasSwitch(switches::kDisableLocalStorage);
- prefs.databases_enabled =
- !command_line.HasSwitch(switches::kDisableDatabases);
- prefs.webaudio_enabled =
- !command_line.HasSwitch(switches::kDisableWebAudio);
-
- prefs.experimental_webgl_enabled =
- GpuProcessHost::gpu_enabled() &&
- !command_line.HasSwitch(switches::kDisable3DAPIs) &&
- !command_line.HasSwitch(switches::kDisableExperimentalWebGL);
-
- prefs.flash_3d_enabled =
- GpuProcessHost::gpu_enabled() &&
- !command_line.HasSwitch(switches::kDisableFlash3d);
- prefs.flash_stage3d_enabled =
- GpuProcessHost::gpu_enabled() &&
- !command_line.HasSwitch(switches::kDisableFlashStage3d);
- prefs.flash_stage3d_baseline_enabled =
- GpuProcessHost::gpu_enabled() &&
- !command_line.HasSwitch(switches::kDisableFlashStage3d);
-
- prefs.gl_multisampling_enabled =
- !command_line.HasSwitch(switches::kDisableGLMultisampling);
- prefs.privileged_webgl_extensions_enabled =
- command_line.HasSwitch(switches::kEnablePrivilegedWebGLExtensions);
- prefs.site_specific_quirks_enabled =
- !command_line.HasSwitch(switches::kDisableSiteSpecificQuirks);
- prefs.allow_file_access_from_file_urls =
- command_line.HasSwitch(switches::kAllowFileAccessFromFiles);
-
- prefs.accelerated_compositing_for_overflow_scroll_enabled = false;
- if (command_line.HasSwitch(switches::kEnableAcceleratedOverflowScroll))
- prefs.accelerated_compositing_for_overflow_scroll_enabled = true;
- if (command_line.HasSwitch(switches::kDisableAcceleratedOverflowScroll))
- prefs.accelerated_compositing_for_overflow_scroll_enabled = false;
-
- prefs.accelerated_compositing_for_scrollable_frames_enabled =
- command_line.HasSwitch(switches::kEnableAcceleratedScrollableFrames);
- prefs.composited_scrolling_for_frames_enabled =
- command_line.HasSwitch(switches::kEnableCompositedScrollingForFrames);
- prefs.show_paint_rects =
- command_line.HasSwitch(switches::kShowPaintRects);
- prefs.accelerated_compositing_enabled =
- GpuProcessHost::gpu_enabled() &&
- !command_line.HasSwitch(switches::kDisableAcceleratedCompositing);
- prefs.force_compositing_mode =
- content::IsForceCompositingModeEnabled() &&
- !command_line.HasSwitch(switches::kDisableForceCompositingMode);
- prefs.accelerated_2d_canvas_enabled =
- GpuProcessHost::gpu_enabled() &&
- !command_line.HasSwitch(switches::kDisableAccelerated2dCanvas);
- prefs.antialiased_2d_canvas_disabled =
- command_line.HasSwitch(switches::kDisable2dCanvasAntialiasing);
- prefs.accelerated_filters_enabled =
- GpuProcessHost::gpu_enabled() &&
- command_line.HasSwitch(switches::kEnableAcceleratedFilters);
- prefs.accelerated_compositing_for_3d_transforms_enabled =
- prefs.accelerated_compositing_for_animation_enabled =
- !command_line.HasSwitch(switches::kDisableAcceleratedLayers);
- prefs.accelerated_compositing_for_plugins_enabled =
- !command_line.HasSwitch(switches::kDisableAcceleratedPlugins);
- prefs.accelerated_compositing_for_video_enabled =
- !command_line.HasSwitch(switches::kDisableAcceleratedVideo);
- prefs.fullscreen_enabled =
- !command_line.HasSwitch(switches::kDisableFullScreen);
- prefs.css_sticky_position_enabled =
- command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures);
- prefs.css_shaders_enabled =
- command_line.HasSwitch(switches::kEnableCssShaders);
- prefs.lazy_layout_enabled =
- command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures);
- prefs.region_based_columns_enabled =
- command_line.HasSwitch(switches::kEnableRegionBasedColumns);
- prefs.threaded_html_parser =
- !command_line.HasSwitch(switches::kDisableThreadedHTMLParser);
- prefs.experimental_websocket_enabled =
- command_line.HasSwitch(switches::kEnableExperimentalWebSocket);
- if (command_line.HasSwitch(cc::switches::kEnablePinchVirtualViewport)) {
- prefs.pinch_virtual_viewport_enabled = true;
- prefs.pinch_overlay_scrollbar_thickness = 10;
- }
-
-#if defined(OS_ANDROID)
- prefs.use_solid_color_scrollbars = true;
- prefs.user_gesture_required_for_media_playback = !command_line.HasSwitch(
- switches::kDisableGestureRequirementForMediaPlayback);
- prefs.user_gesture_required_for_media_fullscreen = !command_line.HasSwitch(
- switches::kDisableGestureRequirementForMediaFullscreen);
-#endif
-
- prefs.touch_enabled = ui::AreTouchEventsEnabled();
- prefs.device_supports_touch = prefs.touch_enabled &&
- ui::IsTouchDevicePresent();
-#if defined(OS_ANDROID)
- prefs.device_supports_mouse = false;
-#endif
-
- prefs.touch_adjustment_enabled =
- !command_line.HasSwitch(switches::kDisableTouchAdjustment);
-
-#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
- bool default_enable_scroll_animator = true;
-#else
- bool default_enable_scroll_animator = false;
-#endif
- prefs.enable_scroll_animator = default_enable_scroll_animator;
- if (command_line.HasSwitch(switches::kEnableSmoothScrolling))
- prefs.enable_scroll_animator = true;
- if (command_line.HasSwitch(switches::kDisableSmoothScrolling))
- prefs.enable_scroll_animator = false;
-
- prefs.visual_word_movement_enabled =
- command_line.HasSwitch(switches::kEnableVisualWordMovement);
-
- // Certain GPU features might have been blacklisted.
- GpuDataManagerImpl::GetInstance()->UpdateRendererWebPrefs(&prefs);
-
- if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
- rvh->GetProcess()->GetID())) {
- prefs.loads_images_automatically = true;
- prefs.javascript_enabled = true;
- }
-
- prefs.is_online = !net::NetworkChangeNotifier::IsOffline();
-
-#if !defined(USE_AURA)
- // Force accelerated compositing and 2d canvas off for chrome: and about:
- // pages (unless it's specifically allowed).
- if ((url.SchemeIs(chrome::kChromeUIScheme) ||
- (url.SchemeIs(chrome::kAboutScheme) &&
- url.spec() != kAboutBlankURL)) &&
- !command_line.HasSwitch(switches::kAllowWebUICompositing)) {
- prefs.accelerated_compositing_enabled = false;
- prefs.accelerated_2d_canvas_enabled = false;
- }
-#endif
-
- prefs.fixed_position_creates_stacking_context = !command_line.HasSwitch(
- switches::kDisableFixedPositionCreatesStackingContext);
-
-#if defined(OS_CHROMEOS)
- prefs.gesture_tap_highlight_enabled = !command_line.HasSwitch(
- switches::kDisableGestureTapHighlight);
-#else
- prefs.gesture_tap_highlight_enabled = command_line.HasSwitch(
- switches::kEnableGestureTapHighlight);
-#endif
-
- prefs.number_of_cpu_cores = base::SysInfo::NumberOfProcessors();
-
- prefs.viewport_enabled = command_line.HasSwitch(switches::kEnableViewport);
-
- prefs.deferred_image_decoding_enabled =
- command_line.HasSwitch(switches::kEnableDeferredImageDecoding) ||
- cc::switches::IsImplSidePaintingEnabled();
-
- prefs.spatial_navigation_enabled = command_line.HasSwitch(
- switches::kEnableSpatialNavigation);
-
- GetContentClient()->browser()->OverrideWebkitPrefs(rvh, url, &prefs);
-
- // Disable compositing in guests until we have compositing path implemented
- // for guests.
- bool guest_compositing_enabled = !command_line.HasSwitch(
- switches::kDisableBrowserPluginCompositing);
- if (rvh->GetProcess()->IsGuest() && !guest_compositing_enabled) {
- prefs.force_compositing_mode = false;
- prefs.accelerated_compositing_enabled = false;
- }
-
- return prefs;
+RenderFrameHostManager* WebContentsImpl::GetRenderManagerForTesting() {
+ return GetRenderManager();
}
-RenderViewHostManager* WebContentsImpl::GetRenderManagerForTesting() {
- return &render_manager_;
+bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
+ const IPC::Message& message) {
+ return OnMessageReceived(render_view_host, NULL, message);
}
bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
+ RenderFrameHost* render_frame_host,
const IPC::Message& message) {
+ DCHECK(render_view_host || render_frame_host);
if (GetWebUI() &&
static_cast<WebUIImpl*>(GetWebUI())->OnMessageReceived(message)) {
return true;
@@ -671,11 +501,13 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
return true;
// Message handlers should be aware of which RenderViewHost sent the
- // message, which is temporarily stored in message_source_.
- message_source_ = render_view_host;
+ // message, which is temporarily stored in render_view_message_source_.
+ render_view_message_source_ = render_view_host;
bool handled = true;
bool message_is_ok = true;
IPC_BEGIN_MESSAGE_MAP_EX(WebContentsImpl, message, message_is_ok)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung, OnPepperPluginHung)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed, OnPluginCrashed)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
OnDidLoadResourceFromMemoryCache)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent,
@@ -694,15 +526,11 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler,
OnRegisterProtocolHandler)
IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply)
- IPC_MESSAGE_HANDLER(ViewHostMsg_DidProgrammaticallyScroll,
- OnDidProgrammaticallyScroll)
- IPC_MESSAGE_HANDLER(ViewHostMsg_CrashedPlugin, OnCrashedPlugin)
IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed)
IPC_MESSAGE_HANDLER(ViewHostMsg_OpenColorChooser, OnOpenColorChooser)
IPC_MESSAGE_HANDLER(ViewHostMsg_EndColorChooser, OnEndColorChooser)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetSelectedColorInColorChooser,
OnSetSelectedColorInColorChooser)
- IPC_MESSAGE_HANDLER(ViewHostMsg_PepperPluginHung, OnPepperPluginHung)
IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend)
IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission,
OnRequestPpapiBrokerPermission)
@@ -717,13 +545,21 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
OnFindMatchRectsReply)
IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog,
OnOpenDateTimeDialog)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(JavaBridgeHostMsg_GetChannelHandle,
+ OnJavaBridgeGetChannelHandle)
#endif
- IPC_MESSAGE_HANDLER(ViewHostMsg_FrameAttached, OnFrameAttached)
- IPC_MESSAGE_HANDLER(ViewHostMsg_FrameDetached, OnFrameDetached)
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaNotification, OnMediaNotification)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidFirstVisuallyNonEmptyPaint,
+ OnFirstVisuallyNonEmptyPaint)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ShowValidationMessage,
+ OnShowValidationMessage)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_HideValidationMessage,
+ OnHideValidationMessage)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_MoveValidationMessage,
+ OnMoveValidationMessage)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
- message_source_ = NULL;
+ render_view_message_source_ = NULL;
if (!message_is_ok) {
RecordAction(UserMetricsAction("BadMessageTerminate_RVD"));
@@ -790,12 +626,16 @@ void WebContentsImpl::SetDelegate(WebContentsDelegate* delegate) {
}
RenderProcessHost* WebContentsImpl::GetRenderProcessHost() const {
- RenderViewHostImpl* host = render_manager_.current_host();
+ RenderViewHostImpl* host = GetRenderManager()->current_host();
return host ? host->GetProcess() : NULL;
}
+RenderFrameHost* WebContentsImpl::GetMainFrame() {
+ return frame_tree_.root()->render_frame_host();
+}
+
RenderViewHost* WebContentsImpl::GetRenderViewHost() const {
- return render_manager_.current_host();
+ return GetRenderManager()->current_host();
}
void WebContentsImpl::GetRenderViewHostAtPosition(
@@ -835,7 +675,7 @@ int WebContentsImpl::GetFullscreenWidgetRoutingID() const {
}
RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() const {
- return render_manager_.GetRenderWidgetHostView();
+ return GetRenderManager()->GetRenderWidgetHostView();
}
RenderWidgetHostViewPort* WebContentsImpl::GetRenderWidgetHostViewPort() const {
@@ -873,12 +713,12 @@ WebUI* WebContentsImpl::CreateWebUI(const GURL& url) {
}
WebUI* WebContentsImpl::GetWebUI() const {
- return render_manager_.web_ui() ? render_manager_.web_ui()
- : render_manager_.pending_web_ui();
+ return GetRenderManager()->web_ui() ? GetRenderManager()->web_ui()
+ : GetRenderManager()->pending_web_ui();
}
WebUI* WebContentsImpl::GetCommittedWebUI() const {
- return render_manager_.web_ui();
+ return GetRenderManager()->web_ui();
}
void WebContentsImpl::SetUserAgentOverride(const std::string& override) {
@@ -894,7 +734,7 @@ void WebContentsImpl::SetUserAgentOverride(const std::string& override) {
// Reload the page if a load is currently in progress to avoid having
// different parts of the page loaded using different user agents.
- NavigationEntry* entry = controller_.GetActiveEntry();
+ NavigationEntry* entry = controller_.GetVisibleEntry();
if (is_loading_ && entry != NULL && entry->GetIsOverridingUserAgent())
controller_.ReloadIgnoringCache(true);
@@ -915,7 +755,7 @@ gfx::NativeViewAccessible accessible_parent) {
}
#endif
-const string16& WebContentsImpl::GetTitle() const {
+const base::string16& WebContentsImpl::GetTitle() const {
// Transient entries take precedence. They are used for interstitial pages
// that are shown on top of existing pages.
NavigationEntry* entry = controller_.GetTransientEntry();
@@ -925,14 +765,14 @@ const string16& WebContentsImpl::GetTitle() const {
if (entry) {
return entry->GetTitleForDisplay(accept_languages);
}
- WebUI* our_web_ui = render_manager_.pending_web_ui() ?
- render_manager_.pending_web_ui() : render_manager_.web_ui();
+ WebUI* our_web_ui = GetRenderManager()->pending_web_ui() ?
+ GetRenderManager()->pending_web_ui() : GetRenderManager()->web_ui();
if (our_web_ui) {
// Don't override the title in view source mode.
entry = controller_.GetVisibleEntry();
if (!(entry && entry->IsViewSourceMode())) {
// Give the Web UI the chance to override our title.
- const string16& title = our_web_ui->GetOverriddenTitle();
+ const base::string16& title = our_web_ui->GetOverriddenTitle();
if (!title.empty())
return title;
}
@@ -944,11 +784,22 @@ const string16& WebContentsImpl::GetTitle() const {
// title.
entry = controller_.GetLastCommittedEntry();
- // We make an exception for initial navigations, because we can have a
- // committed entry for an initial navigation when doing a history navigation
- // in a new tab, such as Ctrl+Back.
- if (entry && controller_.IsInitialNavigation())
- entry = controller_.GetVisibleEntry();
+ // We make an exception for initial navigations.
+ if (controller_.IsInitialNavigation()) {
+ // We only want to use the title from the visible entry in one of two cases:
+ // 1. There's already a committed entry for an initial navigation, in which
+ // case we are doing a history navigation in a new tab (e.g., Ctrl+Back).
+ // 2. The pending entry has been explicitly assigned a title to display.
+ //
+ // If there's no last committed entry and no assigned title, we should fall
+ // back to |page_title_when_no_navigation_entry_| rather than showing the
+ // URL.
+ if (entry ||
+ (controller_.GetVisibleEntry() &&
+ !controller_.GetVisibleEntry()->GetTitle().empty())) {
+ entry = controller_.GetVisibleEntry();
+ }
+ }
if (entry) {
return entry->GetTitleForDisplay(accept_languages);
@@ -981,18 +832,19 @@ void WebContentsImpl::UpdateMaxPageIDForSiteInstance(
max_page_ids_[site_instance->GetId()] = page_id;
}
-void WebContentsImpl::CopyMaxPageIDsFrom(WebContentsImpl* web_contents) {
- max_page_ids_ = web_contents->max_page_ids_;
+void WebContentsImpl::CopyMaxPageIDsFrom(WebContents* web_contents) {
+ WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents);
+ max_page_ids_ = contents->max_page_ids_;
}
SiteInstance* WebContentsImpl::GetSiteInstance() const {
- return render_manager_.current_host()->GetSiteInstance();
+ return GetRenderManager()->current_host()->GetSiteInstance();
}
SiteInstance* WebContentsImpl::GetPendingSiteInstance() const {
- RenderViewHost* dest_rvh = render_manager_.pending_render_view_host() ?
- render_manager_.pending_render_view_host() :
- render_manager_.current_host();
+ RenderViewHost* dest_rvh = GetRenderManager()->pending_render_view_host() ?
+ GetRenderManager()->pending_render_view_host() :
+ GetRenderManager()->current_host();
return dest_rvh->GetSiteInstance();
}
@@ -1008,7 +860,7 @@ const net::LoadStateWithParam& WebContentsImpl::GetLoadState() const {
return load_state_;
}
-const string16& WebContentsImpl::GetLoadStateHost() const {
+const base::string16& WebContentsImpl::GetLoadStateHost() const {
return load_state_host_;
}
@@ -1021,27 +873,10 @@ uint64 WebContentsImpl::GetUploadPosition() const {
}
std::set<GURL> WebContentsImpl::GetSitesInTab() const {
- BrowserContext* browser_context = GetBrowserContext();
std::set<GURL> sites;
- if (!frame_tree_root_.get())
- return sites;
-
- // Iterates over the FrameTreeNodes to find each unique site URL that is
- // currently committed.
- FrameTreeNode* node = NULL;
- std::queue<FrameTreeNode*> queue;
- queue.push(frame_tree_root_.get());
-
- while (!queue.empty()) {
- node = queue.front();
- queue.pop();
- sites.insert(SiteInstance::GetSiteForURL(browser_context,
- node->current_url()));
-
- for (size_t i = 0; i < node->child_count(); ++i)
- queue.push(node->child_at(i));
- }
-
+ frame_tree_.ForEach(Bind(&CollectSites,
+ base::Unretained(GetBrowserContext()),
+ base::Unretained(&sites)));
return sites;
}
@@ -1125,8 +960,6 @@ void WebContentsImpl::WasShown() {
last_selected_time_ = base::TimeTicks::Now();
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown());
-
// The resize rect might have changed while this was inactive -- send the new
// one to make sure it's up to date.
RenderViewHostImpl* rvh =
@@ -1135,11 +968,9 @@ void WebContentsImpl::WasShown() {
rvh->ResizeRectChanged(GetRootWindowResizerRect());
}
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown());
+
should_normally_be_visible_ = true;
- NotificationService::current()->Notify(
- NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
- Source<WebContents>(this),
- Details<const bool>(&should_normally_be_visible_));
}
void WebContentsImpl::WasHidden() {
@@ -1158,11 +989,9 @@ void WebContentsImpl::WasHidden() {
rwhv->Hide();
}
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden());
+
should_normally_be_visible_ = false;
- NotificationService::current()->Notify(
- NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
- Source<WebContents>(this),
- Details<const bool>(&should_normally_be_visible_));
}
bool WebContentsImpl::NeedToFireBeforeUnload() {
@@ -1174,7 +1003,7 @@ bool WebContentsImpl::NeedToFireBeforeUnload() {
}
void WebContentsImpl::Stop() {
- render_manager_.Stop();
+ GetRenderManager()->Stop();
FOR_EACH_OBSERVER(WebContentsObserver, observers_, NavigationStopped());
}
@@ -1212,12 +1041,17 @@ void WebContentsImpl::Observe(int type,
}
}
+WebContents* WebContentsImpl::GetWebContents() {
+ return this;
+}
+
void WebContentsImpl::Init(const WebContents::CreateParams& params) {
- // This is set before initializing the render_manager_ since render_manager_
- // init calls back into us via its delegate to ask if it should be hidden.
+ // This is set before initializing the render manager since
+ // RenderFrameHostManager::Init calls back into us via its delegate to ask if
+ // it should be hidden.
should_normally_be_visible_ = !params.initially_hidden;
- render_manager_.Init(
+ GetRenderManager()->Init(
params.browser_context, params.site_instance, params.routing_id,
params.main_frame_routing_id);
@@ -1260,9 +1094,6 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
#if defined(OS_ANDROID)
java_bridge_dispatcher_host_manager_.reset(
new JavaBridgeDispatcherHostManager(this));
-#endif
-
-#if defined(OS_ANDROID)
date_time_chooser_.reset(new DateTimeChooserAndroid());
#endif
}
@@ -1368,7 +1199,7 @@ void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
}
bool WebContentsImpl::PreHandleWheelEvent(
- const WebKit::WebMouseWheelEvent& event) {
+ const blink::WebMouseWheelEvent& event) {
#if !defined(OS_MACOSX)
// On platforms other than Mac, control+mousewheel changes zoom. On Mac, this
// isn't done for two reasons:
@@ -1378,7 +1209,7 @@ bool WebContentsImpl::PreHandleWheelEvent(
// with control key set which isn't what the user wants
if (delegate_ &&
event.wheelTicksY &&
- (event.modifiers & WebKit::WebInputEvent::ControlKey)) {
+ (event.modifiers & blink::WebInputEvent::ControlKey)) {
delegate_->ContentsZoomChange(event.wheelTicksY > 0);
return true;
}
@@ -1449,6 +1280,7 @@ void WebContentsImpl::LostMouseLock() {
}
void WebContentsImpl::CreateNewWindow(
+ int render_process_id,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
@@ -1459,11 +1291,30 @@ void WebContentsImpl::CreateNewWindow(
// SiteInstance in its own BrowsingInstance.
bool is_guest = GetRenderProcessHost()->IsGuest();
+ // If the opener is to be suppressed, the new window can be in any process.
+ // Since routing ids are process specific, we must not have one passed in
+ // as argument here.
+ DCHECK(!params.opener_suppressed || route_id == MSG_ROUTING_NONE);
+
scoped_refptr<SiteInstance> site_instance =
params.opener_suppressed && !is_guest ?
SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) :
GetSiteInstance();
+ // A message to create a new window can only come from the active process for
+ // this WebContentsImpl instance. If any other process sends the request,
+ // it is invalid and the process must be terminated.
+ if (GetRenderProcessHost()->GetID() != render_process_id) {
+ base::ProcessHandle process_handle =
+ RenderProcessHost::FromID(render_process_id)->GetHandle();
+ if (process_handle != base::kNullProcessHandle) {
+ RecordAction(
+ UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow"));
+ base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false);
+ }
+ return;
+ }
+
// We must assign the SessionStorageNamespace before calling Init().
//
// http://crbug.com/142685
@@ -1514,8 +1365,10 @@ void WebContentsImpl::CreateNewWindow(
int instance_id = GetBrowserPluginGuestManager()->get_next_instance_id();
WebContentsImpl* new_contents_impl =
static_cast<WebContentsImpl*>(new_contents);
- BrowserPluginGuest::CreateWithOpener(instance_id, new_contents_impl,
- GetBrowserPluginGuest(), !!new_contents_impl->opener());
+ BrowserPluginGuest::CreateWithOpener(instance_id,
+ new_contents_impl->opener() != NULL,
+ new_contents_impl,
+ GetBrowserPluginGuest());
}
if (params.disposition == NEW_BACKGROUND_TAB)
create_params.initially_hidden = true;
@@ -1566,19 +1419,36 @@ void WebContentsImpl::CreateNewWindow(
}
}
-void WebContentsImpl::CreateNewWidget(int route_id,
- WebKit::WebPopupType popup_type) {
- CreateNewWidget(route_id, false, popup_type);
+void WebContentsImpl::CreateNewWidget(int render_process_id,
+ int route_id,
+ blink::WebPopupType popup_type) {
+ CreateNewWidget(render_process_id, route_id, false, popup_type);
}
-void WebContentsImpl::CreateNewFullscreenWidget(int route_id) {
- CreateNewWidget(route_id, true, WebKit::WebPopupTypeNone);
+void WebContentsImpl::CreateNewFullscreenWidget(int render_process_id,
+ int route_id) {
+ CreateNewWidget(render_process_id, route_id, true, blink::WebPopupTypeNone);
}
-void WebContentsImpl::CreateNewWidget(int route_id,
+void WebContentsImpl::CreateNewWidget(int render_process_id,
+ int route_id,
bool is_fullscreen,
- WebKit::WebPopupType popup_type) {
+ blink::WebPopupType popup_type) {
RenderProcessHost* process = GetRenderProcessHost();
+ // A message to create a new widget can only come from the active process for
+ // this WebContentsImpl instance. If any other process sends the request,
+ // it is invalid and the process must be terminated.
+ if (process->GetID() != render_process_id) {
+ base::ProcessHandle process_handle =
+ RenderProcessHost::FromID(render_process_id)->GetHandle();
+ if (process_handle != base::kNullProcessHandle) {
+ RecordAction(
+ UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget"));
+ base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false);
+ }
+ return;
+ }
+
RenderWidgetHostImpl* widget_host =
new RenderWidgetHostImpl(this, process, route_id, IsHidden());
created_widgets_.insert(widget_host);
@@ -1634,20 +1504,15 @@ void WebContentsImpl::ShowCreatedWidget(int route_id,
RenderWidgetHostViewPort::FromRWHV(GetCreatedWidget(route_id));
if (!widget_host_view)
return;
- bool allow_privileged = false;
if (is_fullscreen) {
+ DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_);
+ fullscreen_widget_routing_id_ = route_id;
if (delegate_ && delegate_->EmbedsFullscreenWidget()) {
widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView());
delegate_->ToggleFullscreenModeForTab(this, true);
} else {
widget_host_view->InitAsFullscreen(GetRenderWidgetHostViewPort());
- // Only allow privileged mouse lock for fullscreen render widget, which is
- // used to implement Pepper Flash fullscreen.
- allow_privileged = true;
}
-
- DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_);
- fullscreen_widget_routing_id_ = route_id;
FOR_EACH_OBSERVER(WebContentsObserver,
observers_,
DidShowFullscreenWidget(route_id));
@@ -1660,9 +1525,9 @@ void WebContentsImpl::ShowCreatedWidget(int route_id,
RenderWidgetHostImpl* render_widget_host_impl =
RenderWidgetHostImpl::From(widget_host_view->GetRenderWidgetHost());
render_widget_host_impl->Init();
- render_widget_host_impl->set_allow_privileged_mouse_lock(allow_privileged);
- // TODO(miu): For now, all mouse lock requests by embedded Flash fullscreen
- // will be denied. This is to be rectified in a soon-upcoming change.
+ // Only allow privileged mouse lock for fullscreen render widget, which is
+ // used to implement Pepper Flash fullscreen.
+ render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen);
#if defined(OS_MACOSX)
// A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's
@@ -1739,6 +1604,30 @@ SessionStorageNamespace* WebContentsImpl::GetSessionStorageNamespace(
return controller_.GetSessionStorageNamespace(instance);
}
+FrameTree* WebContentsImpl::GetFrameTree() {
+ return &frame_tree_;
+}
+
+void WebContentsImpl::OnShowValidationMessage(
+ const gfx::Rect& anchor_in_root_view,
+ const string16& main_text,
+ const string16& sub_text) {
+ if (delegate_)
+ delegate_->ShowValidationMessage(
+ this, anchor_in_root_view, main_text, sub_text);
+}
+
+void WebContentsImpl::OnHideValidationMessage() {
+ if (delegate_)
+ delegate_->HideValidationMessage(this);
+}
+
+void WebContentsImpl::OnMoveValidationMessage(
+ const gfx::Rect& anchor_in_root_view) {
+ if (delegate_)
+ delegate_->MoveValidationMessage(this, anchor_in_root_view);
+}
+
void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) {
if (browser_plugin_embedder_)
browser_plugin_embedder_->DidSendScreenRects();
@@ -1788,7 +1677,7 @@ void WebContentsImpl::RenderViewForInterstitialPageCreated(
void WebContentsImpl::AttachInterstitialPage(
InterstitialPageImpl* interstitial_page) {
DCHECK(interstitial_page);
- render_manager_.set_interstitial_page(interstitial_page);
+ GetRenderManager()->set_interstitial_page(interstitial_page);
// Cancel any visible dialogs so that they don't interfere with the
// interstitial.
@@ -1801,7 +1690,7 @@ void WebContentsImpl::AttachInterstitialPage(
void WebContentsImpl::DetachInterstitialPage() {
if (GetInterstitialPage())
- render_manager_.remove_interstitial_page();
+ GetRenderManager()->remove_interstitial_page();
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidDetachInterstitialPage());
}
@@ -1813,14 +1702,16 @@ bool WebContentsImpl::NavigateToEntry(
// The renderer will reject IPC messages with URLs longer than
// this limit, so don't attempt to navigate with a longer URL.
- if (entry.GetURL().spec().size() > kMaxURLChars) {
- LOG(WARNING) << "Refusing to load URL as it exceeds " << kMaxURLChars
+ if (entry.GetURL().spec().size() > GetMaxURLChars()) {
+ LOG(WARNING) << "Refusing to load URL as it exceeds " << GetMaxURLChars()
<< " characters.";
return false;
}
+ // TODO(creis): Use entry->frame_tree_node_id() to pick which
+ // RenderFrameHostManager to use.
RenderViewHostImpl* dest_render_view_host =
- static_cast<RenderViewHostImpl*>(render_manager_.Navigate(entry));
+ static_cast<RenderViewHostImpl*>(GetRenderManager()->Navigate(entry));
if (!dest_render_view_host)
return false; // Unable to create the desired render view host.
@@ -1863,9 +1754,10 @@ bool WebContentsImpl::NavigateToEntry(
}
// Notify observers about navigation.
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- NavigateToPendingEntry(entry.GetURL(), reload_type));
+ FOR_EACH_OBSERVER(
+ WebContentsObserver,
+ observers_,
+ DidStartNavigationToPendingEntry(entry.GetURL(), reload_type));
if (delegate_)
delegate_->DidNavigateToPendingEntry(this);
@@ -1879,7 +1771,7 @@ void WebContentsImpl::SetHistoryLengthAndPrune(
int32 minimum_page_id) {
// SetHistoryLengthAndPrune doesn't work when there are pending cross-site
// navigations. Callers should ensure that this is the case.
- if (render_manager_.pending_render_view_host()) {
+ if (GetRenderManager()->pending_render_view_host()) {
NOTREACHED();
return;
}
@@ -1899,18 +1791,18 @@ void WebContentsImpl::SetHistoryLengthAndPrune(
void WebContentsImpl::FocusThroughTabTraversal(bool reverse) {
if (ShowingInterstitialPage()) {
- render_manager_.interstitial_page()->FocusThroughTabTraversal(reverse);
+ GetRenderManager()->interstitial_page()->FocusThroughTabTraversal(reverse);
return;
}
GetRenderViewHostImpl()->SetInitialFocus(reverse);
}
bool WebContentsImpl::ShowingInterstitialPage() const {
- return render_manager_.interstitial_page() != NULL;
+ return GetRenderManager()->interstitial_page() != NULL;
}
InterstitialPage* WebContentsImpl::GetInterstitialPage() const {
- return render_manager_.interstitial_page();
+ return GetRenderManager()->interstitial_page();
}
bool WebContentsImpl::IsSavable() {
@@ -1966,7 +1858,7 @@ void WebContentsImpl::SaveFrame(const GURL& url,
return;
int64 post_id = -1;
if (is_main_frame) {
- const NavigationEntry* entry = controller_.GetActiveEntry();
+ const NavigationEntry* entry = controller_.GetLastCommittedEntry();
if (entry)
post_id = entry->GetPostID();
}
@@ -1987,12 +1879,13 @@ void WebContentsImpl::GenerateMHTML(
MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file, callback);
}
+// TODO(nasko): Rename this method to IsVisibleEntry.
bool WebContentsImpl::IsActiveEntry(int32 page_id) {
- NavigationEntryImpl* active_entry =
- NavigationEntryImpl::FromNavigationEntry(controller_.GetActiveEntry());
- return (active_entry != NULL &&
- active_entry->site_instance() == GetSiteInstance() &&
- active_entry->GetPageID() == page_id);
+ NavigationEntryImpl* visible_entry =
+ NavigationEntryImpl::FromNavigationEntry(controller_.GetVisibleEntry());
+ return (visible_entry != NULL &&
+ visible_entry->site_instance() == GetSiteInstance() &&
+ visible_entry->GetPageID() == page_id);
}
const std::string& WebContentsImpl::GetContentsMimeType() const {
@@ -2022,7 +1915,7 @@ void WebContentsImpl::Close() {
}
void WebContentsImpl::DragSourceEndedAt(int client_x, int client_y,
- int screen_x, int screen_y, WebKit::WebDragOperation operation) {
+ int screen_x, int screen_y, blink::WebDragOperation operation) {
if (browser_plugin_embedder_.get())
browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y,
screen_x, screen_y, operation);
@@ -2074,10 +1967,10 @@ double WebContentsImpl::GetZoomLevel() const {
GetRenderProcessHost()->GetID(), GetRenderViewHost()->GetRoutingID());
} else {
GURL url;
- NavigationEntry* active_entry = GetController().GetActiveEntry();
+ NavigationEntry* entry = GetController().GetLastCommittedEntry();
// Since zoom map is updated using rewritten URL, use rewritten URL
// to get the zoom level.
- url = active_entry ? active_entry->GetURL() : GURL::EmptyGURL();
+ url = entry ? entry->GetURL() : GURL::EmptyGURL();
zoom_level = zoom_map->GetZoomLevelForHostAndScheme(url.scheme(),
net::GetHostOrSpecFromURL(url));
}
@@ -2100,11 +1993,11 @@ void WebContentsImpl::ViewSource() {
if (!delegate_)
return;
- NavigationEntry* active_entry = GetController().GetActiveEntry();
- if (!active_entry)
+ NavigationEntry* entry = GetController().GetLastCommittedEntry();
+ if (!entry)
return;
- delegate_->ViewSourceForTab(this, active_entry->GetURL());
+ delegate_->ViewSourceForTab(this, entry->GetURL());
}
void WebContentsImpl::ViewFrameSource(const GURL& url,
@@ -2158,8 +2051,15 @@ int WebContentsImpl::DownloadImage(const GURL& url,
return id;
}
+void WebContentsImpl::SetZoomLevel(double level) {
+ Send(new ViewMsg_SetZoomLevel(GetRoutingID(), level));
+ BrowserPluginEmbedder* embedder = GetBrowserPluginEmbedder();
+ if (embedder)
+ embedder->SetZoomLevel(level);
+}
+
bool WebContentsImpl::FocusLocationBarByDefault() {
- NavigationEntry* entry = controller_.GetActiveEntry();
+ NavigationEntry* entry = controller_.GetVisibleEntry();
if (entry && entry->GetURL() == GURL(kAboutBlankURL))
return true;
return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this);
@@ -2170,67 +2070,37 @@ void WebContentsImpl::SetFocusToLocationBar(bool select_all) {
delegate_->SetFocusToLocationBar(select_all);
}
-void WebContentsImpl::DidStartProvisionalLoadForFrame(
- RenderViewHost* render_view_host,
+void WebContentsImpl::DidStartProvisionalLoad(
+ RenderFrameHostImpl* render_frame_host,
int64 frame_id,
int64 parent_frame_id,
bool is_main_frame,
- const GURL& url) {
- bool is_error_page = (url.spec() == kUnreachableWebDataURL);
- bool is_iframe_srcdoc = (url.spec() == kAboutSrcDocURL);
- GURL validated_url(url);
- RenderProcessHost* render_process_host =
- render_view_host->GetProcess();
- RenderViewHost::FilterURL(render_process_host, false, &validated_url);
-
- if (is_main_frame) {
+ const GURL& validated_url,
+ bool is_error_page,
+ bool is_iframe_srcdoc) {
+ if (is_main_frame)
DidChangeLoadProgress(0);
- // If there is no browser-initiated pending entry for this navigation and it
- // is not for the error URL, create a pending entry using the current
- // SiteInstance, and ensure the address bar updates accordingly. We don't
- // know the referrer or extra headers at this point, but the referrer will
- // be set properly upon commit.
- NavigationEntry* pending_entry = controller_.GetPendingEntry();
- bool has_browser_initiated_pending_entry = pending_entry &&
- !NavigationEntryImpl::FromNavigationEntry(pending_entry)->
- is_renderer_initiated();
- if (!has_browser_initiated_pending_entry && !is_error_page) {
- NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
- controller_.CreateNavigationEntry(validated_url,
- content::Referrer(),
- content::PAGE_TRANSITION_LINK,
- true /* is_renderer_initiated */,
- std::string(),
- GetBrowserContext()));
- entry->set_site_instance(
- static_cast<SiteInstanceImpl*>(GetSiteInstance()));
- // TODO(creis): If there's a pending entry already, find a safe way to
- // update it instead of replacing it and copying over things like this.
- if (pending_entry &&
- NavigationEntryImpl::FromNavigationEntry(pending_entry)->
- should_replace_entry()) {
- entry->set_should_replace_entry(true);
- }
- controller_.SetPendingEntry(entry);
- NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL);
- }
- }
-
// Notify observers about the start of the provisional load.
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidStartProvisionalLoadForFrame(frame_id, parent_frame_id,
is_main_frame, validated_url, is_error_page,
- is_iframe_srcdoc, render_view_host));
+ is_iframe_srcdoc, render_frame_host->render_view_host()));
if (is_main_frame) {
- // Notify observers about the provisional change in the main frame URL.
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- ProvisionalChangeToMainFrameUrl(validated_url,
- render_view_host));
+ FOR_EACH_OBSERVER(
+ WebContentsObserver,
+ observers_,
+ ProvisionalChangeToMainFrameUrl(validated_url,
+ render_frame_host->render_view_host()));
}
}
+void WebContentsImpl::NotifyChangedNavigationState(
+ InvalidateTypes changed_flags) {
+ NotifyNavigationStateChanged(changed_flags);
+}
+
void WebContentsImpl::DidRedirectProvisionalLoad(
RenderViewHost* render_view_host,
int32 page_id,
@@ -2286,7 +2156,7 @@ void WebContentsImpl::DidFailProvisionalLoadWithError(
//
// We can't tell this apart, so we think we're tearing down the current page
// which will cause a crash later one. There is also some code in
- // RenderViewHostManager::RendererAbortedProvisionalLoad that is commented
+ // RenderFrameHostManager::RendererAbortedProvisionalLoad that is commented
// out because of this problem.
//
// http://code.google.com/p/chromium/issues/detail?id=2855
@@ -2300,7 +2170,7 @@ void WebContentsImpl::DidFailProvisionalLoadWithError(
return;
}
- render_manager_.RendererAbortedProvisionalLoad(render_view_host);
+ GetRenderManager()->RendererAbortedProvisionalLoad(render_view_host);
}
// Do not usually clear the pending entry if one exists, so that the user's
@@ -2318,6 +2188,7 @@ void WebContentsImpl::DidFailProvisionalLoadWithError(
FOR_EACH_OBSERVER(WebContentsObserver,
observers_,
DidFailProvisionalLoad(params.frame_id,
+ params.frame_unique_name,
params.is_main_frame,
validated_url,
params.error_code,
@@ -2339,8 +2210,11 @@ void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
net::CertStatus cert_status = 0;
int security_bits = -1;
int connection_status = 0;
+ SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
DeserializeSecurityInfo(security_info, &cert_id, &cert_status,
- &security_bits, &connection_status);
+ &security_bits, &connection_status,
+ &signed_certificate_timestamp_ids);
+ // TODO(alcutter,eranm): Pass signed_certificate_timestamp_ids into details
LoadFromMemoryCacheDetails details(
url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method,
mime_type, resource_type);
@@ -2350,12 +2224,6 @@ void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidLoadResourceFromMemoryCache(details));
- // TODO(avi): Remove. http://crbug.com/170921
- NotificationService::current()->Notify(
- NOTIFICATION_LOAD_FROM_MEMORY_CACHE,
- Source<NavigationController>(&controller_),
- Details<LoadFromMemoryCacheDetails>(&details));
-
if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) {
scoped_refptr<net::URLRequestContextGetter> request_context(
resource_type == ResourceType::MEDIA ?
@@ -2379,8 +2247,8 @@ void WebContentsImpl::OnDidDisplayInsecureContent() {
void WebContentsImpl::OnDidRunInsecureContent(
const std::string& security_origin, const GURL& target_url) {
- LOG(INFO) << security_origin << " ran insecure content from "
- << target_url.possibly_invalid_spec();
+ LOG(WARNING) << security_origin << " ran insecure content from "
+ << target_url.possibly_invalid_spec();
RecordAction(UserMetricsAction("SSL.RanInsecureContent"));
if (EndsWith(security_origin, kDotGoogleDotCom, false))
RecordAction(UserMetricsAction("SSL.RanInsecureContentGoogle"));
@@ -2391,8 +2259,9 @@ void WebContentsImpl::OnDidRunInsecureContent(
}
void WebContentsImpl::OnDocumentLoadedInFrame(int64 frame_id) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DocumentLoadedInFrame(frame_id, message_source_));
+ FOR_EACH_OBSERVER(
+ WebContentsObserver, observers_,
+ DocumentLoadedInFrame(frame_id, render_view_message_source_));
}
void WebContentsImpl::OnDidFinishLoad(
@@ -2400,11 +2269,12 @@ void WebContentsImpl::OnDidFinishLoad(
const GURL& url,
bool is_main_frame) {
GURL validated_url(url);
- RenderProcessHost* render_process_host = message_source_->GetProcess();
+ RenderProcessHost* render_process_host =
+ render_view_message_source_->GetProcess();
RenderViewHost::FilterURL(render_process_host, false, &validated_url);
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidFinishLoad(frame_id, validated_url, is_main_frame,
- message_source_));
+ render_view_message_source_));
}
void WebContentsImpl::OnDidFailLoadWithError(
@@ -2412,14 +2282,15 @@ void WebContentsImpl::OnDidFailLoadWithError(
const GURL& url,
bool is_main_frame,
int error_code,
- const string16& error_description) {
+ const base::string16& error_description) {
GURL validated_url(url);
- RenderProcessHost* render_process_host = message_source_->GetProcess();
+ RenderProcessHost* render_process_host =
+ render_view_message_source_->GetProcess();
RenderViewHost::FilterURL(render_process_host, false, &validated_url);
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidFailLoad(frame_id, validated_url, is_main_frame,
error_code, error_description,
- message_source_));
+ render_view_message_source_));
}
void WebContentsImpl::OnGoToEntryAtOffset(int offset) {
@@ -2462,7 +2333,7 @@ void WebContentsImpl::OnEnumerateDirectory(int request_id,
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
- if (policy->CanReadDirectory(GetRenderProcessHost()->GetID(), path))
+ if (policy->CanReadFile(GetRenderProcessHost()->GetID(), path))
delegate_->EnumerateDirectory(this, request_id, path);
}
@@ -2473,7 +2344,7 @@ void WebContentsImpl::OnJSOutOfMemory() {
void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol,
const GURL& url,
- const string16& title,
+ const base::string16& title,
bool user_gesture) {
if (!delegate_)
return;
@@ -2497,12 +2368,6 @@ void WebContentsImpl::OnFindReply(int request_id,
}
}
-void WebContentsImpl::OnDidProgrammaticallyScroll(
- const gfx::Vector2d& scroll_point) {
- if (delegate_)
- delegate_->DidProgrammaticallyScroll(this, scroll_point);
-}
-
#if defined(OS_ANDROID)
void WebContentsImpl::OnFindMatchRectsReply(
int version,
@@ -2517,22 +2382,30 @@ void WebContentsImpl::OnOpenDateTimeDialog(
date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this),
GetRenderViewHost(),
value.dialog_type,
- value.year,
- value.month,
- value.day,
- value.hour,
- value.minute,
- value.second,
- value.milli,
- value.week,
+ value.dialog_value,
value.minimum,
value.maximum,
- value.step);
+ value.step,
+ value.suggestions);
+}
+
+void WebContentsImpl::OnJavaBridgeGetChannelHandle(IPC::Message* reply_msg) {
+ java_bridge_dispatcher_host_manager_->OnGetChannelHandle(
+ render_view_message_source_, reply_msg);
}
#endif
-void WebContentsImpl::OnCrashedPlugin(const base::FilePath& plugin_path,
+void WebContentsImpl::OnPepperPluginHung(int plugin_child_id,
+ const base::FilePath& path,
+ bool is_hung) {
+ UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
+
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ PluginHungStatusChanged(plugin_child_id, path, is_hung));
+}
+
+void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path,
base::ProcessId plugin_pid) {
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
PluginCrashed(plugin_path, plugin_pid));
@@ -2545,11 +2418,16 @@ void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url,
AppCacheAccessed(manifest_url, blocked_by_policy));
}
-void WebContentsImpl::OnOpenColorChooser(int color_chooser_id,
- SkColor color) {
- ColorChooser* new_color_chooser = delegate_->OpenColorChooser(this, color);
- if (color_chooser_ == new_color_chooser)
+void WebContentsImpl::OnOpenColorChooser(
+ int color_chooser_id,
+ SkColor color,
+ const std::vector<ColorSuggestion>& suggestions) {
+ ColorChooser* new_color_chooser =
+ delegate_->OpenColorChooser(this, color, suggestions);
+ if (!new_color_chooser)
return;
+ if (color_chooser_)
+ color_chooser_->End();
color_chooser_.reset(new_color_chooser);
color_chooser_identifier_ = color_chooser_id;
}
@@ -2567,15 +2445,6 @@ void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id,
color_chooser_->SetSelectedColor(color);
}
-void WebContentsImpl::OnPepperPluginHung(int plugin_child_id,
- const base::FilePath& path,
- bool is_hung) {
- UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
-
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- PluginHungStatusChanged(plugin_child_id, path, is_hung));
-}
-
// This exists for render views that don't have a WebUI, but do have WebUI
// bindings enabled.
void WebContentsImpl::OnWebUISend(const GURL& source_url,
@@ -2625,6 +2494,9 @@ void WebContentsImpl::OnDidDownloadImage(
const GURL& image_url,
const std::vector<SkBitmap>& bitmaps,
const std::vector<gfx::Size>& original_bitmap_sizes) {
+ if (bitmaps.size() != original_bitmap_sizes.size())
+ return;
+
ImageDownloadMap::iterator iter = image_download_map_.find(id);
if (iter == image_download_map_.end()) {
// Currently WebContents notifies us of ANY downloads so that it is
@@ -2645,52 +2517,6 @@ void WebContentsImpl::OnUpdateFaviconURL(
DidUpdateFaviconURL(page_id, candidates));
}
-FrameTreeNode* WebContentsImpl::FindFrameTreeNodeByID(int64 frame_id) {
- // TODO(nasko): Remove this check once we move to creating the root node
- // through RenderFrameHost creation.
- if (!frame_tree_root_.get())
- return NULL;
-
- FrameTreeNode* node = NULL;
- std::queue<FrameTreeNode*> queue;
- queue.push(frame_tree_root_.get());
-
- while (!queue.empty()) {
- node = queue.front();
- queue.pop();
- if (node->frame_id() == frame_id)
- return node;
-
- for (size_t i = 0; i < node->child_count(); ++i)
- queue.push(node->child_at(i));
- }
-
- return NULL;
-}
-
-void WebContentsImpl::OnFrameAttached(
- int64 parent_frame_id,
- int64 frame_id,
- const std::string& frame_name) {
- FrameTreeNode* parent = FindFrameTreeNodeByID(parent_frame_id);
- if (!parent)
- return;
-
- FrameTreeNode* node = new FrameTreeNode(frame_id, frame_name);
- parent->AddChild(node);
-}
-
-void WebContentsImpl::OnFrameDetached(int64 parent_frame_id, int64 frame_id) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- FrameDetached(message_source_, frame_id));
-
- FrameTreeNode* parent = FindFrameTreeNodeByID(parent_frame_id);
- if (!parent)
- return;
-
- parent->RemoveChild(frame_id);
-}
-
void WebContentsImpl::OnMediaNotification(int64 player_cookie,
bool has_video,
bool has_audio,
@@ -2713,15 +2539,21 @@ void WebContentsImpl::OnMediaNotification(int64 player_cookie,
"Playing audio");
}
- if (blocker)
- power_save_blockers_[message_source_][player_cookie] = blocker.release();
+ if (blocker) {
+ power_save_blockers_[render_view_message_source_][player_cookie] =
+ blocker.release();
+ }
} else {
- delete power_save_blockers_[message_source_][player_cookie];
- power_save_blockers_[message_source_].erase(player_cookie);
+ delete power_save_blockers_[render_view_message_source_][player_cookie];
+ power_save_blockers_[render_view_message_source_].erase(player_cookie);
}
#endif // !defined(OS_CHROMEOS)
}
+void WebContentsImpl::OnFirstVisuallyNonEmptyPaint(int32 page_id) {
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ DidFirstVisuallyNonEmptyPaint(page_id));
+}
void WebContentsImpl::DidChangeVisibleSSLState() {
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
@@ -2733,21 +2565,30 @@ void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
BeforeFormRepostWarningShow());
}
+
+void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
+ Activate();
+ if (delegate_)
+ delegate_->ShowRepostFormWarningDialog(this);
+}
+
// Notifies the RenderWidgetHost instance about the fact that the page is
-// loading, or done loading and calls the base implementation.
-void WebContentsImpl::SetIsLoading(bool is_loading,
+// loading, or done loading.
+void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host,
+ bool is_loading,
LoadNotificationDetails* details) {
if (is_loading == is_loading_)
return;
if (!is_loading) {
- load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE, string16());
+ load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE,
+ base::string16());
load_state_host_.clear();
upload_size_ = 0;
upload_position_ = 0;
}
- render_manager_.SetIsLoading(is_loading);
+ GetRenderManager()->SetIsLoading(is_loading);
is_loading_ = is_loading;
waiting_for_response_ = is_loading;
@@ -2756,10 +2597,20 @@ void WebContentsImpl::SetIsLoading(bool is_loading,
delegate_->LoadingStateChanged(this);
NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
- if (is_loading)
- TRACE_EVENT_ASYNC_BEGIN0("browser", "WebContentsImpl Loading", this);
- else
- TRACE_EVENT_ASYNC_END0("browser", "WebContentsImpl Loading", this);
+ std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
+ if (is_loading) {
+ TRACE_EVENT_ASYNC_BEGIN1("browser", "WebContentsImpl Loading", this,
+ "URL", url);
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ DidStartLoading(render_view_host));
+ } else {
+ TRACE_EVENT_ASYNC_END1("browser", "WebContentsImpl Loading", this,
+ "URL", url);
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ DidStopLoading(render_view_host));
+ }
+
+ // TODO(avi): Remove. http://crbug.com/170921
int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP;
NotificationDetails det = NotificationService::NoDetails();
if (details)
@@ -2833,11 +2684,11 @@ void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) {
}
bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry,
- const string16& title) {
+ const base::string16& title) {
// For file URLs without a title, use the pathname instead. In the case of a
// synthesized title, we don't want the update to count toward the "one set
// per page of the title to history."
- string16 final_title;
+ base::string16 final_title;
bool explicit_set;
if (entry && entry->GetURL().SchemeIsFile() && title.empty()) {
final_title = UTF8ToUTF16(entry->GetURL().ExtractFileName());
@@ -2865,9 +2716,12 @@ bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry,
// Lastly, set the title for the view.
view_->SetPageTitle(final_title);
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ TitleWasSet(entry, explicit_set));
+
+ // TODO(avi): Remove. http://crbug.com/170921
std::pair<NavigationEntry*, bool> details =
std::make_pair(entry, explicit_set);
-
NotificationService::current()->Notify(
NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
Source<WebContents>(this),
@@ -2876,19 +2730,22 @@ bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry,
return true;
}
-void WebContentsImpl::NotifySwapped(RenderViewHost* old_render_view_host) {
+void WebContentsImpl::NotifySwapped(RenderViewHost* old_host,
+ RenderViewHost* new_host) {
// After sending out a swap notification, we need to send a disconnect
// notification so that clients that pick up a pointer to |this| can NULL the
// pointer. See Bug 1230284.
notify_disconnection_ = true;
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- RenderViewHostSwapped(old_render_view_host));
+ RenderViewHostChanged(old_host, new_host));
// TODO(avi): Remove. http://crbug.com/170921
+ std::pair<RenderViewHost*, RenderViewHost*> details =
+ std::make_pair(old_host, new_host);
NotificationService::current()->Notify(
- NOTIFICATION_WEB_CONTENTS_SWAPPED,
+ NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
Source<WebContents>(this),
- Details<RenderViewHost>(old_render_view_host));
+ Details<std::pair<RenderViewHost*, RenderViewHost*> >(&details));
// Ensure that the associated embedder gets cleared after a RenderViewHost
// gets swapped, so we don't reuse the same embedder next time a
@@ -2915,13 +2772,32 @@ void WebContentsImpl::NotifyNavigationEntryCommitted(
WebContentsObserver, observers_, NavigationEntryCommitted(load_details));
}
+bool WebContentsImpl::OnMessageReceived(RenderFrameHost* render_frame_host,
+ const IPC::Message& message) {
+ return OnMessageReceived(NULL, render_frame_host, message);
+}
+
+void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
+ // Note this is only for subframes, the notification for the main frame
+ // happens in RenderViewCreated.
+ FOR_EACH_OBSERVER(WebContentsObserver,
+ observers_,
+ RenderFrameCreated(render_frame_host));
+}
+
+void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
+ FOR_EACH_OBSERVER(WebContentsObserver,
+ observers_,
+ RenderFrameDeleted(render_frame_host));
+}
+
RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() {
return render_view_host_delegate_view_;
}
RenderViewHostDelegate::RendererManagement*
WebContentsImpl::GetRendererManagementDelegate() {
- return &render_manager_;
+ return GetRenderManager();
}
RendererPreferences WebContentsImpl::GetRendererPrefs(
@@ -2961,10 +2837,10 @@ void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
// When we're creating views, we're still doing initial setup, so we always
// use the pending Web UI rather than any possibly existing committed one.
- if (render_manager_.pending_web_ui())
- render_manager_.pending_web_ui()->RenderViewCreated(render_view_host);
+ if (GetRenderManager()->pending_web_ui())
+ GetRenderManager()->pending_web_ui()->RenderViewCreated(render_view_host);
- NavigationEntry* entry = controller_.GetActiveEntry();
+ NavigationEntry* entry = controller_.GetPendingEntry();
if (entry && entry->IsViewSourceMode()) {
// Put the renderer in view source mode.
render_view_host->Send(
@@ -2975,6 +2851,13 @@ void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
FOR_EACH_OBSERVER(
WebContentsObserver, observers_, RenderViewCreated(render_view_host));
+
+ // We tell the observers now instead of when the main RenderFrameHostImpl is
+ // constructed because otherwise it would be too early (i.e. IPCs sent to the
+ // frame would be dropped because it's not created yet).
+ RenderFrameHost* main_frame = GetMainFrame();
+ FOR_EACH_OBSERVER(
+ WebContentsObserver, observers_, RenderFrameCreated(main_frame));
}
void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
@@ -3012,8 +2895,12 @@ void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
return;
}
+ // Cancel any visible dialogs so they are not left dangling over the sad tab.
+ if (dialog_manager_)
+ dialog_manager_->CancelActiveAndPendingDialogs(this);
+
ClearPowerSaveBlockers(rvh);
- SetIsLoading(false, NULL);
+ SetIsLoading(rvh, false, NULL);
NotifyDisconnected();
SetIsCrashed(status, error_code);
GetView()->OnTabCrashed(GetCrashedStatus(), crashed_error_code_);
@@ -3025,7 +2912,7 @@ void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
ClearPowerSaveBlockers(rvh);
- render_manager_.RenderViewDeleted(rvh);
+ GetRenderManager()->RenderViewDeleted(rvh);
FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
}
@@ -3060,31 +2947,25 @@ void WebContentsImpl::DidGetRedirectForResourceRequest(
void WebContentsImpl::DidNavigate(
RenderViewHost* rvh,
const ViewHostMsg_FrameNavigate_Params& params) {
- // If we don't have a frame tree root yet, this is the first navigation in
- // using the current RenderViewHost, so we need to create it with the proper
- // frame id.
- if (!frame_tree_root_.get()) {
+ if (frame_tree_.IsFirstNavigationAfterSwap()) {
+ // First navigation should be a main frame navigation.
DCHECK(PageTransitionIsMainFrame(params.transition));
- frame_tree_root_.reset(new FrameTreeNode(params.frame_id, std::string()));
+ frame_tree_.OnFirstNavigationAfterSwap(params.frame_id);
}
if (PageTransitionIsMainFrame(params.transition)) {
// When overscroll navigation gesture is enabled, a screenshot of the page
// in its current state is taken so that it can be used during the
// nav-gesture. It is necessary to take the screenshot here, before calling
- // RenderViewHostManager::DidNavigateMainFrame, because that can change
+ // RenderFrameHostManager::DidNavigateMainFrame, because that can change
// WebContents::GetRenderViewHost to return the new host, instead of the one
// that may have just been swapped out.
if (delegate_ && delegate_->CanOverscrollContent())
controller_.TakeScreenshot();
- render_manager_.DidNavigateMainFrame(rvh);
+ GetRenderManager()->DidNavigateMainFrame(rvh);
}
- // We expect to have a valid frame tree root node at all times when
- // navigating.
- DCHECK(frame_tree_root_.get());
-
// Update the site of the SiteInstance if it doesn't have one yet, unless
// assigning a site is not necessary for this URL. In that case, the
// SiteInstance can still be considered unused until a navigation to a real
@@ -3111,9 +2992,7 @@ void WebContentsImpl::DidNavigate(
// For now, keep track of each frame's URL in its FrameTreeNode. This lets
// us estimate our process count for implementing OOP iframes.
// TODO(creis): Remove this when we track which pages commit in each frame.
- FrameTreeNode* node = FindFrameTreeNodeByID(params.frame_id);
- if (node)
- node->set_current_url(params.url);
+ frame_tree_.SetFrameUrl(params.frame_id, params.url);
// Send notification about committed provisional loads. This notification is
// different from the NAV_ENTRY_COMMITTED notification which doesn't include
@@ -3129,15 +3008,20 @@ void WebContentsImpl::DidNavigate(
// forward in the history is only stored in the navigation controller's
// entry list.
if (did_navigate &&
- (controller_.GetActiveEntry()->GetTransitionType() &
+ (controller_.GetLastCommittedEntry()->GetTransitionType() &
PAGE_TRANSITION_FORWARD_BACK)) {
transition_type = PageTransitionFromInt(
params.transition | PAGE_TRANSITION_FORWARD_BACK);
}
// Notify observers about the commit of the provisional load.
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidCommitProvisionalLoadForFrame(params.frame_id,
- is_main_frame, params.url, transition_type, rvh));
+ DidCommitProvisionalLoadForFrame(
+ params.frame_id,
+ params.frame_unique_name,
+ is_main_frame,
+ params.url,
+ transition_type,
+ rvh));
}
if (!did_navigate)
@@ -3164,7 +3048,8 @@ void WebContentsImpl::UpdateState(RenderViewHost* rvh,
const PageState& page_state) {
// Ensure that this state update comes from either the active RVH or one of
// the swapped out RVHs. We don't expect to hear from any other RVHs.
- DCHECK(rvh == GetRenderViewHost() || render_manager_.IsOnSwappedOutList(rvh));
+ DCHECK(rvh == GetRenderViewHost() ||
+ GetRenderManager()->IsOnSwappedOutList(rvh));
// We must be prepared to handle state updates for any page, these occur
// when the user is scrolling and entering form data, as well as when we're
@@ -3186,7 +3071,7 @@ void WebContentsImpl::UpdateState(RenderViewHost* rvh,
void WebContentsImpl::UpdateTitle(RenderViewHost* rvh,
int32 page_id,
- const string16& title,
+ const base::string16& title,
base::i18n::TextDirection title_direction) {
// If we have a title, that's a pretty good indication that we've started
// getting useful data.
@@ -3247,7 +3132,7 @@ void WebContentsImpl::SwappedOut(RenderViewHost* rvh) {
delegate_->SwappedOut(this);
// Allow the navigation to proceed.
- render_manager_.SwappedOut(rvh);
+ GetRenderManager()->SwappedOut(rvh);
}
void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) {
@@ -3256,11 +3141,7 @@ void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) {
}
void WebContentsImpl::DidStartLoading(RenderViewHost* render_view_host) {
- SetIsLoading(true, NULL);
-
- // Notify observers about navigation.
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidStartLoading(render_view_host));
+ SetIsLoading(render_view_host, true, NULL);
}
void WebContentsImpl::DidStopLoading(RenderViewHost* render_view_host) {
@@ -3283,11 +3164,7 @@ void WebContentsImpl::DidStopLoading(RenderViewHost* render_view_host) {
controller_.GetCurrentEntryIndex()));
}
- SetIsLoading(false, details.get());
-
- // Notify observers about navigation.
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidStopLoading(render_view_host));
+ SetIsLoading(render_view_host, false, details.get());
}
void WebContentsImpl::DidCancelLoading() {
@@ -3313,7 +3190,7 @@ void WebContentsImpl::DidDisownOpener(RenderViewHost* rvh) {
// Notify all swapped out RenderViewHosts for this tab. This is important
// in case we go back to them, or if another window in those processes tries
// to access window.opener.
- render_manager_.DidDisownOpener(rvh);
+ GetRenderManager()->DidDisownOpener(rvh);
}
void WebContentsImpl::DidAccessInitialDocument() {
@@ -3330,6 +3207,10 @@ void WebContentsImpl::DocumentAvailableInMainFrame(
void WebContentsImpl::DocumentOnLoadCompletedInMainFrame(
RenderViewHost* render_view_host,
int32 page_id) {
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ DocumentOnLoadCompletedInMainFrame(page_id));
+
+ // TODO(avi): Remove. http://crbug.com/170921
NotificationService::current()->Notify(
NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
Source<WebContents>(this),
@@ -3352,49 +3233,61 @@ void WebContentsImpl::RequestOpenURL(RenderViewHost* rvh,
// Delegate to RequestTransferURL because this is just the generic
// case where |old_request_id| is empty.
- RequestTransferURL(url, referrer, disposition, source_frame_id,
- GlobalRequestID(),
+ // TODO(creis): Pass the redirect_chain into this method to support client
+ // redirects. http://crbug.com/311721.
+ std::vector<GURL> redirect_chain;
+ RequestTransferURL(url, redirect_chain, referrer, PAGE_TRANSITION_LINK,
+ disposition, source_frame_id, GlobalRequestID(),
should_replace_current_entry, user_gesture);
}
void WebContentsImpl::RequestTransferURL(
const GURL& url,
+ const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
+ PageTransition page_transition,
WindowOpenDisposition disposition,
int64 source_frame_id,
const GlobalRequestID& old_request_id,
bool should_replace_current_entry,
bool user_gesture) {
WebContents* new_contents = NULL;
- PageTransition transition_type = PAGE_TRANSITION_LINK;
GURL dest_url(url);
if (!GetContentClient()->browser()->ShouldAllowOpenURL(
- GetSiteInstance(), url))
+ GetSiteInstance(), url))
dest_url = GURL(kAboutBlankURL);
- if (render_manager_.web_ui()) {
- // When we're a Web UI, it will provide a page transition type for us (this
- // is so the new tab page can specify AUTO_BOOKMARK for automatically
- // generated suggestions).
- //
+ // TODO(creis): Look up the FrameTreeNode ID corresponding to source_frame_id.
+ int frame_tree_node_id = -1;
+ OpenURLParams params(dest_url, referrer, source_frame_id,
+ frame_tree_node_id, disposition,
+ page_transition, true /* is_renderer_initiated */);
+ if (redirect_chain.size() > 0)
+ params.redirect_chain = redirect_chain;
+ params.transferred_global_request_id = old_request_id;
+ params.should_replace_current_entry = should_replace_current_entry;
+ params.user_gesture = user_gesture;
+
+ if (GetRenderManager()->web_ui()) {
+ // Web UI pages sometimes want to override the page transition type for
+ // link clicks (e.g., so the new tab page can specify AUTO_BOOKMARK for
+ // automatically generated suggestions). We don't override other types
+ // like TYPED because they have different implications (e.g., autocomplete).
+ if (PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_LINK))
+ params.transition = GetRenderManager()->web_ui()->GetLinkTransitionType();
+
// Note also that we hide the referrer for Web UI pages. We don't really
// want web sites to see a referrer of "chrome://blah" (and some
// chrome: URLs might have search terms or other stuff we don't want to
// send to the site), so we send no referrer.
- OpenURLParams params(dest_url, Referrer(), source_frame_id, disposition,
- render_manager_.web_ui()->GetLinkTransitionType(),
- false /* is_renderer_initiated */);
- params.transferred_global_request_id = old_request_id;
- new_contents = OpenURL(params);
- transition_type = render_manager_.web_ui()->GetLinkTransitionType();
- } else {
- OpenURLParams params(dest_url, referrer, source_frame_id, disposition,
- PAGE_TRANSITION_LINK, true /* is_renderer_initiated */);
- params.transferred_global_request_id = old_request_id;
- params.should_replace_current_entry = should_replace_current_entry;
- params.user_gesture = user_gesture;
- new_contents = OpenURL(params);
+ params.referrer = Referrer();
+
+ // Navigations in Web UI pages count as browser-initiated navigations.
+ params.is_renderer_initiated = false;
}
+
+ new_contents = OpenURL(params);
+
if (new_contents) {
// Notify observers.
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
@@ -3402,7 +3295,7 @@ void WebContentsImpl::RequestTransferURL(
dest_url,
referrer,
disposition,
- transition_type,
+ params.transition,
source_frame_id));
}
}
@@ -3433,6 +3326,21 @@ void WebContentsImpl::RouteMessageEvent(
ViewMsg_PostMessage_Params new_params(params);
+ if (!params.message_port_ids.empty()) {
+ MessagePortMessageFilter* message_port_message_filter =
+ static_cast<RenderProcessHostImpl*>(GetRenderProcessHost())
+ ->message_port_message_filter();
+ std::vector<int> new_routing_ids(params.message_port_ids.size());
+ for (size_t i = 0; i < params.message_port_ids.size(); ++i) {
+ new_routing_ids[i] = message_port_message_filter->GetNextRoutingID();
+ MessagePortService::GetInstance()->UpdateMessagePort(
+ params.message_port_ids[i],
+ message_port_message_filter,
+ new_routing_ids[i]);
+ }
+ new_params.new_routing_ids = new_routing_ids;
+ }
+
// If there is a source_routing_id, translate it to the routing ID for
// the equivalent swapped out RVH in the target process. If we need
// to create a swapped out RVH for the source tab, we create its opener
@@ -3472,8 +3380,8 @@ void WebContentsImpl::RouteMessageEvent(
void WebContentsImpl::RunJavaScriptMessage(
RenderViewHost* rvh,
- const string16& message,
- const string16& default_prompt,
+ const base::string16& message,
+ const base::string16& default_prompt,
const GURL& frame_url,
JavaScriptMessageType javascript_message_type,
IPC::Message* reply_msg,
@@ -3511,7 +3419,7 @@ void WebContentsImpl::RunJavaScriptMessage(
if (suppress_this_message) {
// If we are suppressing messages, just reply as if the user immediately
// pressed "Cancel".
- OnDialogClosed(rvh, reply_msg, false, string16());
+ OnDialogClosed(rvh, reply_msg, false, base::string16());
}
// OnDialogClosed (two lines up) may have caused deletion of this object (see
@@ -3519,7 +3427,7 @@ void WebContentsImpl::RunJavaScriptMessage(
}
void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh,
- const string16& message,
+ const base::string16& message,
bool is_reload,
IPC::Message* reply_msg) {
RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh);
@@ -3533,7 +3441,7 @@ void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh,
!delegate_->GetJavaScriptDialogManager();
if (suppress_this_message) {
// The reply must be sent to the RVH that sent the request.
- rvhi->JavaScriptDialogClosed(reply_msg, true, string16());
+ rvhi->JavaScriptDialogClosed(reply_msg, true, base::string16());
return;
}
@@ -3546,9 +3454,9 @@ void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh,
}
bool WebContentsImpl::AddMessageToConsole(int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id) {
+ const base::string16& source_id) {
if (!delegate_)
return false;
return delegate_->AddMessageToConsole(this, level, message, line_no,
@@ -3556,17 +3464,20 @@ bool WebContentsImpl::AddMessageToConsole(int32 level,
}
WebPreferences WebContentsImpl::GetWebkitPrefs() {
- // We want to base the page config off of the real URL, rather than the
- // display URL.
+ // We want to base the page config off of the actual URL, rather than the
+ // virtual URL.
+ // TODO(nasko): Investigate how to remove the GetActiveEntry usage here,
+ // as it is deprecated and can be out of sync with GetRenderViewHost().
GURL url = controller_.GetActiveEntry()
? controller_.GetActiveEntry()->GetURL() : GURL::EmptyGURL();
- return GetWebkitPrefs(GetRenderViewHost(), url);
+
+ return GetRenderManager()->current_host()->GetWebkitPrefs(url);
}
int WebContentsImpl::CreateSwappedOutRenderView(
SiteInstance* instance) {
- return render_manager_.CreateRenderView(instance, MSG_ROUTING_NONE,
- true, true);
+ return GetRenderManager()->CreateRenderView(instance, MSG_ROUTING_NONE,
+ true, true);
}
void WebContentsImpl::OnUserGesture() {
@@ -3603,7 +3514,7 @@ void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
// Pretend the handler fired so tab closing continues as if it had.
rvhi->set_sudden_termination_allowed(true);
- if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer())
+ if (!GetRenderManager()->ShouldCloseTabOnUnresponsiveRenderer())
return;
// If the tab hangs in the beforeunload/unload handler there's really
@@ -3690,32 +3601,15 @@ void WebContentsImpl::CancelModalDialogsForRenderManager() {
dialog_manager_->CancelActiveAndPendingDialogs(this);
}
-void WebContentsImpl::NotifySwappedFromRenderManager(RenderViewHost* rvh) {
- NotifySwapped(rvh);
+void WebContentsImpl::NotifySwappedFromRenderManager(RenderViewHost* old_host,
+ RenderViewHost* new_host) {
+ NotifySwapped(old_host, new_host);
// Make sure the visible RVH reflects the new delegate's preferences.
if (delegate_)
view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent());
- view_->RenderViewSwappedIn(render_manager_.current_host());
-
- FrameTreeNode* root = NULL;
- RenderViewHostImpl* new_rvh = static_cast<RenderViewHostImpl*>(
- render_manager_.current_host());
-
- // We are doing a cross-site navigation and swapping processes. Since frame
- // ids are unique to a process, we need to recreate the frame tree with the
- // proper main frame id.
- // Note that it is possible for this method to be called before the new RVH
- // has committed a navigation (if RenderViewHostManager short-circuits the
- // CommitPending call because the current RVH is dead). In that case, we
- // haven't heard a valid frame id to use to initialize the root node, so clear
- // out the root node and the first subsequent navigation message will set it
- // correctly.
- if (new_rvh->main_frame_id() != -1)
- root = new FrameTreeNode(new_rvh->main_frame_id(), std::string());
-
- frame_tree_root_.reset(root);
+ view_->RenderViewSwappedIn(new_host);
}
int WebContentsImpl::CreateOpenerRenderViewsForRenderManager(
@@ -3737,22 +3631,23 @@ int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) {
// If any of the renderers (current, pending, or swapped out) for this
// WebContents has the same SiteInstance, use it.
- if (render_manager_.current_host()->GetSiteInstance() == instance)
- return render_manager_.current_host()->GetRoutingID();
+ if (GetRenderManager()->current_host()->GetSiteInstance() == instance)
+ return GetRenderManager()->current_host()->GetRoutingID();
- if (render_manager_.pending_render_view_host() &&
- render_manager_.pending_render_view_host()->GetSiteInstance() == instance)
- return render_manager_.pending_render_view_host()->GetRoutingID();
+ if (GetRenderManager()->pending_render_view_host() &&
+ GetRenderManager()->pending_render_view_host()->GetSiteInstance() ==
+ instance)
+ return GetRenderManager()->pending_render_view_host()->GetRoutingID();
- RenderViewHostImpl* rvh = render_manager_.GetSwappedOutRenderViewHost(
+ RenderViewHostImpl* rvh = GetRenderManager()->GetSwappedOutRenderViewHost(
instance);
if (rvh)
return rvh->GetRoutingID();
// Create a swapped out RenderView in the given SiteInstance if none exists,
// setting its opener to the given route_id. Return the new view's route_id.
- return render_manager_.CreateRenderView(instance, opener_route_id,
- true, true);
+ return GetRenderManager()->CreateRenderView(instance, opener_route_id,
+ true, true);
}
NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() {
@@ -3784,7 +3679,7 @@ bool WebContentsImpl::CreateRenderViewForRenderManager(
GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance());
if (!static_cast<RenderViewHostImpl*>(
- render_view_host)->CreateRenderView(string16(),
+ render_view_host)->CreateRenderView(base::string16(),
opener_route_id,
max_page_id)) {
return false;
@@ -3803,6 +3698,19 @@ bool WebContentsImpl::CreateRenderViewForRenderManager(
}
#if defined(OS_ANDROID)
+base::android::ScopedJavaLocalRef<jobject>
+WebContentsImpl::GetJavaWebContents() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ WebContentsAndroid* web_contents_android =
+ static_cast<WebContentsAndroid*>(GetUserData(kWebContentsAndroidKey));
+ if (!web_contents_android) {
+ web_contents_android = new WebContentsAndroid(this);
+ SetUserData(kWebContentsAndroidKey, web_contents_android);
+ }
+ return web_contents_android->GetJavaObject();
+}
+
bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
return CreateRenderViewForRenderManager(GetRenderViewHost(),
MSG_ROUTING_NONE);
@@ -3812,7 +3720,7 @@ bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
void WebContentsImpl::OnDialogClosed(RenderViewHost* rvh,
IPC::Message* reply_msg,
bool success,
- const string16& user_input) {
+ const base::string16& user_input) {
if (is_showing_before_unload_dialog_ && !success) {
// If a beforeunload dialog is canceled, we need to stop the throbber from
// spinning, since we forced it to start spinning in Navigate.
@@ -3843,6 +3751,10 @@ bool WebContentsImpl::IsHidden() {
return capturer_count_ == 0 && !should_normally_be_visible_;
}
+RenderFrameHostManager* WebContentsImpl::GetRenderManager() const {
+ return frame_tree_.root()->render_manager();
+}
+
RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() {
return static_cast<RenderViewHostImpl*>(GetRenderViewHost());
}
@@ -3889,4 +3801,11 @@ gfx::Size WebContentsImpl::GetSizeForNewRenderView() const {
return size;
}
+void WebContentsImpl::OnFrameRemoved(
+ RenderViewHostImpl* render_view_host,
+ int64 frame_id) {
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ FrameDetached(render_view_host, frame_id));
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h
index c60aebacb30..49202248fa9 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -15,22 +15,25 @@
#include "base/observer_list.h"
#include "base/process/process.h"
#include "base/values.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/navigation_controller_delegate.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigator_delegate.h"
+#include "content/browser/frame_host/render_frame_host_delegate.h"
+#include "content/browser/frame_host/render_frame_host_manager.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
-#include "content/browser/web_contents/frame_tree_node.h"
-#include "content/browser/web_contents/navigation_controller_impl.h"
-#include "content/browser/web_contents/render_view_host_manager.h"
#include "content/common/content_export.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/page_transition_types.h"
#include "content/public/common/renderer_preferences.h"
#include "content/public/common/three_d_api_types.h"
#include "net/base/load_states.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
#include "ui/gfx/rect_f.h"
#include "ui/gfx/size.h"
-#include "ui/gfx/vector2d.h"
#include "webkit/common/resource_type.h"
struct BrowserPluginHostMsg_ResizeGuest_Params;
@@ -62,6 +65,7 @@ class WebContentsImpl;
class WebContentsObserver;
class WebContentsViewPort;
class WebContentsViewDelegate;
+struct ColorSuggestion;
struct FaviconURL;
struct LoadNotificationDetails;
@@ -74,10 +78,13 @@ WebContentsViewPort* CreateWebContentsView(
class CONTENT_EXPORT WebContentsImpl
: public NON_EXPORTED_BASE(WebContents),
+ public NON_EXPORTED_BASE(RenderFrameHostDelegate),
public RenderViewHostDelegate,
public RenderWidgetHostDelegate,
- public RenderViewHostManager::Delegate,
- public NotificationObserver {
+ public RenderFrameHostManager::Delegate,
+ public NotificationObserver,
+ public NON_EXPORTED_BASE(NavigationControllerDelegate),
+ public NON_EXPORTED_BASE(NavigatorDelegate) {
public:
virtual ~WebContentsImpl();
@@ -96,10 +103,6 @@ class CONTENT_EXPORT WebContentsImpl
int guest_instance_id,
scoped_ptr<base::DictionaryValue> extra_params);
- // Returns the content specific prefs for the given RVH.
- static WebPreferences GetWebkitPrefs(
- RenderViewHost* rvh, const GURL& url);
-
// Creates a swapped out RenderView. This is used by the browser plugin to
// create a swapped out RenderView in the embedder render process for the
// guest, to expose the guest's window object to the embedder.
@@ -113,42 +116,6 @@ class CONTENT_EXPORT WebContentsImpl
// Returns the SavePackage which manages the page saving job. May be NULL.
SavePackage* save_package() const { return save_package_.get(); }
- // Updates the max page ID for the current SiteInstance in this
- // WebContentsImpl to be at least |page_id|.
- void UpdateMaxPageID(int32 page_id);
-
- // Updates the max page ID for the given SiteInstance in this WebContentsImpl
- // to be at least |page_id|.
- void UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance,
- int32 page_id);
-
- // Copy the current map of SiteInstance ID to max page ID from another tab.
- // This is necessary when this tab adopts the NavigationEntries from
- // |web_contents|.
- void CopyMaxPageIDsFrom(WebContentsImpl* web_contents);
-
- // Called by the NavigationController to cause the WebContentsImpl to navigate
- // to the current pending entry. The NavigationController should be called
- // back with RendererDidNavigate on success or DiscardPendingEntry on failure.
- // The callbacks can be inside of this function, or at some future time.
- //
- // The entry has a PageID of -1 if newly created (corresponding to navigation
- // to a new URL).
- //
- // If this method returns false, then the navigation is discarded (equivalent
- // to calling DiscardPendingEntry on the NavigationController).
- bool NavigateToPendingEntry(NavigationController::ReloadType reload_type);
-
- // Called by InterstitialPageImpl when it creates a RenderViewHost.
- void RenderViewForInterstitialPageCreated(RenderViewHost* render_view_host);
-
- // Sets the passed interstitial as the currently showing interstitial.
- // No interstitial page should already be attached.
- void AttachInterstitialPage(InterstitialPageImpl* interstitial_page);
-
- // Unsets the currently showing interstitial.
- void DetachInterstitialPage();
-
#if defined(OS_ANDROID)
JavaBridgeDispatcherHostManager* java_bridge_dispatcher_host_manager() const {
return java_bridge_dispatcher_host_manager_.get();
@@ -163,7 +130,7 @@ class CONTENT_EXPORT WebContentsImpl
#endif
// Expose the render manager for testing.
- RenderViewHostManager* GetRenderManagerForTesting();
+ RenderFrameHostManager* GetRenderManagerForTesting();
// Returns guest browser plugin object, or NULL if this WebContents is not a
// guest.
@@ -189,24 +156,16 @@ class CONTENT_EXPORT WebContentsImpl
// Invoked when visible SSL state (as defined by SSLStatus) changes.
void DidChangeVisibleSSLState();
- // Invoked before a form repost warning is shown.
- void NotifyBeforeFormRepostWarningShow();
-
-
// Informs the render view host and the BrowserPluginEmbedder, if present, of
// a Drag Source End.
void DragSourceEndedAt(int client_x, int client_y, int screen_x,
- int screen_y, WebKit::WebDragOperation operation);
+ int screen_y, blink::WebDragOperation operation);
// Informs the render view host and the BrowserPluginEmbedder, if present, of
// a Drag Source Move.
void DragSourceMovedTo(int client_x, int client_y,
int screen_x, int screen_y);
- FrameTreeNode* GetFrameTreeRootForTesting() {
- return frame_tree_root_.get();
- }
-
// WebContents ------------------------------------------------------
virtual WebContentsDelegate* GetDelegate() OVERRIDE;
virtual void SetDelegate(WebContentsDelegate* delegate) OVERRIDE;
@@ -214,6 +173,7 @@ class CONTENT_EXPORT WebContentsImpl
virtual const NavigationControllerImpl& GetController() const OVERRIDE;
virtual BrowserContext* GetBrowserContext() const OVERRIDE;
virtual RenderProcessHost* GetRenderProcessHost() const OVERRIDE;
+ virtual RenderFrameHost* GetMainFrame() OVERRIDE;
virtual RenderViewHost* GetRenderViewHost() const OVERRIDE;
virtual void GetRenderViewHostAtPosition(
int x,
@@ -235,7 +195,7 @@ class CONTENT_EXPORT WebContentsImpl
virtual void SetParentNativeViewAccessible(
gfx::NativeViewAccessible accessible_parent) OVERRIDE;
#endif
- virtual const string16& GetTitle() const OVERRIDE;
+ virtual const base::string16& GetTitle() const OVERRIDE;
virtual int32 GetMaxPageID() OVERRIDE;
virtual int32 GetMaxPageIDForSiteInstance(
SiteInstance* site_instance) OVERRIDE;
@@ -244,7 +204,7 @@ class CONTENT_EXPORT WebContentsImpl
virtual bool IsLoading() const OVERRIDE;
virtual bool IsWaitingForResponse() const OVERRIDE;
virtual const net::LoadStateWithParam& GetLoadState() const OVERRIDE;
- virtual const string16& GetLoadStateHost() const OVERRIDE;
+ virtual const base::string16& GetLoadStateHost() const OVERRIDE;
virtual uint64 GetUploadSize() const OVERRIDE;
virtual uint64 GetUploadPosition() const OVERRIDE;
virtual std::set<GURL> GetSitesInTab() const OVERRIDE;
@@ -308,6 +268,11 @@ class CONTENT_EXPORT WebContentsImpl
bool is_favicon,
uint32_t max_bitmap_size,
const ImageDownloadCallback& callback) OVERRIDE;
+ virtual void SetZoomLevel(double level) OVERRIDE;
+#if defined(OS_ANDROID)
+ virtual base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents()
+ OVERRIDE;
+#endif
// Implementation of PageNavigator.
virtual WebContents* OpenURL(const OpenURLParams& params) OVERRIDE;
@@ -315,8 +280,13 @@ class CONTENT_EXPORT WebContentsImpl
// Implementation of IPC::Sender.
virtual bool Send(IPC::Message* message) OVERRIDE;
- // RenderViewHostDelegate ----------------------------------------------------
+ // RenderFrameHostDelegate ---------------------------------------------------
+ virtual bool OnMessageReceived(RenderFrameHost* render_frame_host,
+ const IPC::Message& message) OVERRIDE;
+ virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE;
+ virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE;
+ // RenderViewHostDelegate ----------------------------------------------------
virtual RenderViewHostDelegateView* GetDelegateView() OVERRIDE;
virtual RenderViewHostDelegate::RendererManagement*
GetRendererManagementDelegate() OVERRIDE;
@@ -333,12 +303,6 @@ class CONTENT_EXPORT WebContentsImpl
base::TerminationStatus status,
int error_code) OVERRIDE;
virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE;
- virtual void DidStartProvisionalLoadForFrame(
- RenderViewHost* render_view_host,
- int64 frame_id,
- int64 parent_frame_id,
- bool main_frame,
- const GURL& url) OVERRIDE;
virtual void DidRedirectProvisionalLoad(
RenderViewHost* render_view_host,
int32 page_id,
@@ -360,7 +324,7 @@ class CONTENT_EXPORT WebContentsImpl
const PageState& page_state) OVERRIDE;
virtual void UpdateTitle(RenderViewHost* render_view_host,
int32 page_id,
- const string16& title,
+ const base::string16& title,
base::i18n::TextDirection title_direction) OVERRIDE;
virtual void UpdateEncoding(RenderViewHost* render_view_host,
const std::string& encoding) OVERRIDE;
@@ -388,7 +352,9 @@ class CONTENT_EXPORT WebContentsImpl
bool user_gesture) OVERRIDE;
virtual void RequestTransferURL(
const GURL& url,
+ const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
+ PageTransition page_transition,
WindowOpenDisposition disposition,
int64 source_frame_id,
const GlobalRequestID& transferred_global_request_id,
@@ -399,20 +365,20 @@ class CONTENT_EXPORT WebContentsImpl
RenderViewHost* rvh,
const ViewMsg_PostMessage_Params& params) OVERRIDE;
virtual void RunJavaScriptMessage(RenderViewHost* rvh,
- const string16& message,
- const string16& default_prompt,
+ const base::string16& message,
+ const base::string16& default_prompt,
const GURL& frame_url,
JavaScriptMessageType type,
IPC::Message* reply_msg,
bool* did_suppress_message) OVERRIDE;
virtual void RunBeforeUnloadConfirm(RenderViewHost* rvh,
- const string16& message,
+ const base::string16& message,
bool is_reload,
IPC::Message* reply_msg) OVERRIDE;
virtual bool AddMessageToConsole(int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id) OVERRIDE;
+ const base::string16& source_id) OVERRIDE;
virtual RendererPreferences GetRendererPrefs(
BrowserContext* browser_context) const OVERRIDE;
virtual WebPreferences GetWebkitPrefs() OVERRIDE;
@@ -446,13 +412,16 @@ class CONTENT_EXPORT WebContentsImpl
bool last_unlocked_by_target) OVERRIDE;
virtual void LostMouseLock() OVERRIDE;
virtual void CreateNewWindow(
+ int render_process_id,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
SessionStorageNamespace* session_storage_namespace) OVERRIDE;
- virtual void CreateNewWidget(int route_id,
- WebKit::WebPopupType popup_type) OVERRIDE;
- virtual void CreateNewFullscreenWidget(int route_id) OVERRIDE;
+ virtual void CreateNewWidget(int render_process_id,
+ int route_id,
+ blink::WebPopupType popup_type) OVERRIDE;
+ virtual void CreateNewFullscreenWidget(int render_process_id,
+ int route_id) OVERRIDE;
virtual void ShowCreatedWindow(int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_pos,
@@ -466,6 +435,20 @@ class CONTENT_EXPORT WebContentsImpl
const MediaResponseCallback& callback) OVERRIDE;
virtual SessionStorageNamespace* GetSessionStorageNamespace(
SiteInstance* instance) OVERRIDE;
+ virtual FrameTree* GetFrameTree() OVERRIDE;
+
+ // NavigatorDelegate ---------------------------------------------------------
+
+ virtual void DidStartProvisionalLoad(
+ RenderFrameHostImpl* render_frame_host,
+ int64 frame_id,
+ int64 parent_frame_id,
+ bool is_main_frame,
+ const GURL& validated_url,
+ bool is_error_page,
+ bool is_iframe_srcdoc) OVERRIDE;
+ virtual void NotifyChangedNavigationState(
+ InvalidateTypes changed_flags) OVERRIDE;
// RenderWidgetHostDelegate --------------------------------------------------
@@ -477,13 +460,13 @@ class CONTENT_EXPORT WebContentsImpl
virtual void HandleKeyboardEvent(
const NativeWebKeyboardEvent& event) OVERRIDE;
virtual bool PreHandleWheelEvent(
- const WebKit::WebMouseWheelEvent& event) OVERRIDE;
+ const blink::WebMouseWheelEvent& event) OVERRIDE;
virtual void DidSendScreenRects(RenderWidgetHostImpl* rwh) OVERRIDE;
#if defined(OS_WIN) && defined(USE_AURA)
virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() OVERRIDE;
#endif
- // RenderViewHostManager::Delegate -------------------------------------------
+ // RenderFrameHostManager::Delegate ------------------------------------------
virtual bool CreateRenderViewForRenderManager(
RenderViewHost* render_view_host, int opener_route_id) OVERRIDE;
@@ -495,7 +478,7 @@ class CONTENT_EXPORT WebContentsImpl
virtual void UpdateRenderViewSizeForRenderManager() OVERRIDE;
virtual void CancelModalDialogsForRenderManager() OVERRIDE;
virtual void NotifySwappedFromRenderManager(
- RenderViewHost* old_render_view_host) OVERRIDE;
+ RenderViewHost* old_host, RenderViewHost* new_host) OVERRIDE;
virtual int CreateOpenerRenderViewsForRenderManager(
SiteInstance* instance) OVERRIDE;
virtual NavigationControllerImpl&
@@ -514,9 +497,78 @@ class CONTENT_EXPORT WebContentsImpl
const NotificationSource& source,
const NotificationDetails& details) OVERRIDE;
+ // NavigationControllerDelegate ----------------------------------------------
+
+ virtual WebContents* GetWebContents() OVERRIDE;
+ virtual void NotifyNavigationEntryCommitted(
+ const LoadCommittedDetails& load_details) OVERRIDE;
+
+ // Invoked before a form repost warning is shown.
+ virtual void NotifyBeforeFormRepostWarningShow() OVERRIDE;
+
+ // Activate this WebContents and show a form repost warning.
+ virtual void ActivateAndShowRepostFormWarningDialog() OVERRIDE;
+
+ // Updates the max page ID for the current SiteInstance in this
+ // WebContentsImpl to be at least |page_id|.
+ virtual void UpdateMaxPageID(int32 page_id) OVERRIDE;
+
+ // Updates the max page ID for the given SiteInstance in this WebContentsImpl
+ // to be at least |page_id|.
+ virtual void UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance,
+ int32 page_id) OVERRIDE;
+
+ // Copy the current map of SiteInstance ID to max page ID from another tab.
+ // This is necessary when this tab adopts the NavigationEntries from
+ // |web_contents|.
+ virtual void CopyMaxPageIDsFrom(WebContents* web_contents) OVERRIDE;
+
+ // Called by the NavigationController to cause the WebContentsImpl to navigate
+ // to the current pending entry. The NavigationController should be called
+ // back with RendererDidNavigate on success or DiscardPendingEntry on failure.
+ // The callbacks can be inside of this function, or at some future time.
+ //
+ // The entry has a PageID of -1 if newly created (corresponding to navigation
+ // to a new URL).
+ //
+ // If this method returns false, then the navigation is discarded (equivalent
+ // to calling DiscardPendingEntry on the NavigationController).
+ virtual bool NavigateToPendingEntry(
+ NavigationController::ReloadType reload_type) OVERRIDE;
+
+ // Sets the history for this WebContentsImpl to |history_length| entries, and
+ // moves the current page_id to the last entry in the list if it's valid.
+ // This is mainly used when a prerendered page is swapped into the current
+ // tab. The method is virtual for testing.
+ virtual void SetHistoryLengthAndPrune(
+ const SiteInstance* site_instance,
+ int merge_history_length,
+ int32 minimum_page_id) OVERRIDE;
+
+ // Called by InterstitialPageImpl when it creates a RenderViewHost.
+ virtual void RenderViewForInterstitialPageCreated(
+ RenderViewHost* render_view_host) OVERRIDE;
+
+ // Sets the passed interstitial as the currently showing interstitial.
+ // No interstitial page should already be attached.
+ virtual void AttachInterstitialPage(
+ InterstitialPageImpl* interstitial_page) OVERRIDE;
+
+ // Unsets the currently showing interstitial.
+ virtual void DetachInterstitialPage() OVERRIDE;
+
+ // Changes the IsLoading state and notifies the delegate as needed.
+ // |details| is used to provide details on the load that just finished
+ // (but can be null if not applicable).
+ virtual void SetIsLoading(RenderViewHost* render_view_host,
+ bool is_loading,
+ LoadNotificationDetails* details) OVERRIDE;
+
+ typedef base::Callback<void(WebContents*)> CreatedCallback;
private:
friend class NavigationControllerImpl;
+ friend class TestNavigationObserver;
friend class WebContentsObserver;
friend class WebContents; // To implement factory methods.
@@ -529,7 +581,7 @@ class CONTENT_EXPORT WebContentsImpl
FRIEND_TEST_ALL_PREFIXES(WebContentsImplTest, FrameTreeShape);
FRIEND_TEST_ALL_PREFIXES(FormStructureBrowserTest, HTMLFiles);
FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest, HistoryNavigate);
- FRIEND_TEST_ALL_PREFIXES(RenderViewHostManagerTest, PageDoesBackAndReload);
+ FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, PageDoesBackAndReload);
// So InterstitialPageImpl can access SetIsLoading.
friend class InterstitialPageImpl;
@@ -543,10 +595,9 @@ class CONTENT_EXPORT WebContentsImpl
WebContentsImpl(BrowserContext* browser_context,
WebContentsImpl* opener);
- // Add and remove observers for page navigation notifications. Adding or
- // removing multiple times has no effect. The order in which notifications
- // are sent to observers is undefined. Clients must be sure to remove the
- // observer before they go away.
+ // Add and remove observers for page navigation notifications. The order in
+ // which notifications are sent to observers is undefined. Clients must be
+ // sure to remove the observer before they go away.
void AddObserver(WebContentsObserver* observer);
void RemoveObserver(WebContentsObserver* observer);
@@ -565,12 +616,16 @@ class CONTENT_EXPORT WebContentsImpl
void OnDialogClosed(RenderViewHost* rvh,
IPC::Message* reply_msg,
bool success,
- const string16& user_input);
+ const base::string16& user_input);
// Callback function when requesting permission to access the PPAPI broker.
// |result| is true if permission was granted.
void OnPpapiBrokerPermissionResult(int routing_id, bool result);
+ bool OnMessageReceived(RenderViewHost* render_view_host,
+ RenderFrameHost* render_frame_host,
+ const IPC::Message& message);
+
// IPC message handlers.
void OnDidLoadResourceFromMemoryCache(const GURL& url,
const std::string& security_info,
@@ -588,7 +643,7 @@ class CONTENT_EXPORT WebContentsImpl
const GURL& url,
bool is_main_frame,
int error_code,
- const string16& error_description);
+ const base::string16& error_description);
void OnGoToEntryAtOffset(int offset);
void OnUpdateZoomLimits(int minimum_percent,
int maximum_percent,
@@ -598,14 +653,13 @@ class CONTENT_EXPORT WebContentsImpl
void OnRegisterProtocolHandler(const std::string& protocol,
const GURL& url,
- const string16& title,
+ const base::string16& title,
bool user_gesture);
void OnFindReply(int request_id,
int number_of_matches,
const gfx::Rect& selection_rect,
int active_match_ordinal,
bool final_update);
- void OnDidProgrammaticallyScroll(const gfx::Vector2d& scroll_point);
#if defined(OS_ANDROID)
void OnFindMatchRectsReply(int version,
const std::vector<gfx::RectF>& rects,
@@ -613,16 +667,19 @@ class CONTENT_EXPORT WebContentsImpl
void OnOpenDateTimeDialog(
const ViewHostMsg_DateTimeDialogValue_Params& value);
+ void OnJavaBridgeGetChannelHandle(IPC::Message* reply_msg);
#endif
- void OnCrashedPlugin(const base::FilePath& plugin_path,
+ void OnPepperPluginHung(int plugin_child_id,
+ const base::FilePath& path,
+ bool is_hung);
+ void OnPluginCrashed(const base::FilePath& plugin_path,
base::ProcessId plugin_pid);
void OnAppCacheAccessed(const GURL& manifest_url, bool blocked_by_policy);
- void OnOpenColorChooser(int color_chooser_id, SkColor color);
+ void OnOpenColorChooser(int color_chooser_id,
+ SkColor color,
+ const std::vector<ColorSuggestion>& suggestions);
void OnEndColorChooser(int color_chooser_id);
void OnSetSelectedColorInColorChooser(int color_chooser_id, SkColor color);
- void OnPepperPluginHung(int plugin_child_id,
- const base::FilePath& path,
- bool is_hung);
void OnWebUISend(const GURL& source_url,
const std::string& name,
const base::ListValue& args);
@@ -637,21 +694,17 @@ class CONTENT_EXPORT WebContentsImpl
const std::vector<gfx::Size>& original_bitmap_sizes);
void OnUpdateFaviconURL(int32 page_id,
const std::vector<FaviconURL>& candidates);
- void OnFrameAttached(int64 parent_frame_id,
- int64 frame_id,
- const std::string& frame_name);
- void OnFrameDetached(int64 parent_frame_id, int64 frame_id);
-
+ void OnFirstVisuallyNonEmptyPaint(int32 page_id);
void OnMediaNotification(int64 player_cookie,
bool has_video,
bool has_audio,
bool is_playing);
+ void OnShowValidationMessage(const gfx::Rect& anchor_in_root_view,
+ const string16& main_text,
+ const string16& sub_text);
+ void OnHideValidationMessage();
+ void OnMoveValidationMessage(const gfx::Rect& anchor_in_root_view);
- // Changes the IsLoading state and notifies delegate as needed
- // |details| is used to provide details on the load that just finished
- // (but can be null if not applicable). Can be overridden.
- void SetIsLoading(bool is_loading,
- LoadNotificationDetails* details);
// Called by derived classes to indicate that we're no longer waiting for a
// response. This won't actually update the throbber, but it will get picked
@@ -693,7 +746,7 @@ class CONTENT_EXPORT WebContentsImpl
// or the dedicated set title message. It returns true if the new title is
// different and was therefore updated.
bool UpdateTitleForEntry(NavigationEntryImpl* entry,
- const string16& title);
+ const base::string16& title);
// Causes the WebContentsImpl to navigate in the right renderer to |entry|,
// which must be already part of the entries in the navigation controller.
@@ -701,15 +754,6 @@ class CONTENT_EXPORT WebContentsImpl
bool NavigateToEntry(const NavigationEntryImpl& entry,
NavigationController::ReloadType reload_type);
- // Sets the history for this WebContentsImpl to |history_length| entries, and
- // moves the current page_id to the last entry in the list if it's valid.
- // This is mainly used when a prerendered page is swapped into the current
- // tab. The method is virtual for testing.
- virtual void SetHistoryLengthAndPrune(
- const SiteInstance* site_instance,
- int merge_history_length,
- int32 minimum_page_id);
-
// Recursively creates swapped out RenderViews for this tab's opener chain
// (including this tab) in the given SiteInstance, allowing other tabs to send
// cross-process JavaScript calls to their opener(s). Returns the route ID of
@@ -717,9 +761,10 @@ class CONTENT_EXPORT WebContentsImpl
int CreateOpenerRenderViews(SiteInstance* instance);
// Helper for CreateNewWidget/CreateNewFullscreenWidget.
- void CreateNewWidget(int route_id,
+ void CreateNewWidget(int render_process_id,
+ int route_id,
bool is_fullscreen,
- WebKit::WebPopupType popup_type);
+ blink::WebPopupType popup_type);
// Helper for ShowCreatedWidget/ShowCreatedFullscreenWidget.
void ShowCreatedWidget(int route_id,
@@ -745,15 +790,16 @@ class CONTENT_EXPORT WebContentsImpl
// Misc non-view stuff -------------------------------------------------------
// Helper functions for sending notifications.
- void NotifySwapped(RenderViewHost* old_render_view_host);
+ void NotifySwapped(RenderViewHost* old_host, RenderViewHost* new_host);
void NotifyDisconnected();
- void NotifyNavigationEntryCommitted(const LoadCommittedDetails& load_details);
void SetEncoding(const std::string& encoding);
- RenderViewHostImpl* GetRenderViewHostImpl();
+ // TODO(creis): This should take in a FrameTreeNode to know which node's
+ // render manager to return. For now, we just return the root's.
+ RenderFrameHostManager* GetRenderManager() const;
- FrameTreeNode* FindFrameTreeNodeByID(int64 frame_id);
+ RenderViewHostImpl* GetRenderViewHostImpl();
// Removes browser plugin embedder if there is one.
void RemoveBrowserPluginEmbedder();
@@ -767,6 +813,13 @@ class CONTENT_EXPORT WebContentsImpl
// Helper function to invoke WebContentsDelegate::GetSizeForNewRenderView().
gfx::Size GetSizeForNewRenderView() const;
+ void OnFrameRemoved(RenderViewHostImpl* render_view_host, int64 frame_id);
+
+ // Adds/removes a callback called on creation of each new WebContents.
+ // Deprecated, about to remove.
+ static void AddCreatedCallback(const CreatedCallback& callback);
+ static void RemoveCreatedCallback(const CreatedCallback& callback);
+
// Data for core operation ---------------------------------------------------
// Delegate for notifying our owner about stuff. Not owned by us.
@@ -797,7 +850,7 @@ class CONTENT_EXPORT WebContentsImpl
DestructionObservers destruction_observers_;
// A list of observers notified when page state changes. Weak references.
- // This MUST be listed above render_manager_ since at destruction time the
+ // This MUST be listed above frame_tree_ since at destruction time the
// latter might cause RenderViewHost's destructor to call us and we might use
// the observer list then.
ObserverList<WebContentsObserver> observers_;
@@ -819,8 +872,8 @@ class CONTENT_EXPORT WebContentsImpl
PowerSaveBlockerMap;
PowerSaveBlockerMap power_save_blockers_;
- // Manages creation and swapping of render views.
- RenderViewHostManager render_manager_;
+ // Manages the frame tree of the page and process swaps in each node.
+ FrameTree frame_tree_;
#if defined(OS_ANDROID)
// Manages injecting Java objects into all RenderViewHosts associated with
@@ -856,7 +909,7 @@ class CONTENT_EXPORT WebContentsImpl
// The current load state and the URL associated with it.
net::LoadStateWithParam load_state_;
- string16 load_state_host_;
+ base::string16 load_state_host_;
// Upload progress, for displaying in the status bar.
// Set to zero when there is no significant upload happening.
uint64 upload_size_;
@@ -865,7 +918,7 @@ class CONTENT_EXPORT WebContentsImpl
// Data for current page -----------------------------------------------------
// When a title cannot be taken from any entry, this title will be used.
- string16 page_title_when_no_navigation_entry_;
+ base::string16 page_title_when_no_navigation_entry_;
// When a navigation occurs, we record its contents MIME type. It can be
// used to check whether we can do something for some special contents.
@@ -877,9 +930,6 @@ class CONTENT_EXPORT WebContentsImpl
// True if this is a secure page which displayed insecure content.
bool displayed_insecure_content_;
- // The frame tree structure of the current page.
- scoped_ptr<FrameTreeNode> frame_tree_root_;
-
// Data for misc internal state ----------------------------------------------
// When > 0, the WebContents is currently being captured (e.g., for
@@ -957,9 +1007,10 @@ class CONTENT_EXPORT WebContentsImpl
// member variables that are gone.
NotificationRegistrar registrar_;
- // Used during IPC message dispatching so that the handlers can get a pointer
- // to the RVH through which the message was received.
- RenderViewHost* message_source_;
+ // Used during IPC message dispatching from the RenderView so that the
+ // handlers can get a pointer to the RVH through which the message was
+ // received.
+ RenderViewHost* render_view_message_source_;
// All live RenderWidgetHostImpls that are created by this object and may
// outlive it.
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 651c2b7d637..b06a62884df 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -3,13 +3,14 @@
// found in the LICENSE file.
#include "base/values.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/load_notification_details.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_view.h"
@@ -32,7 +33,7 @@ void ResizeWebContentsView(Shell* shell, const gfx::Size& size,
// The cleaner and shorter SizeContents is preferred as more platforms convert
// to Aura.
#if defined(TOOLKIT_GTK) || defined(OS_MACOSX)
- shell->SizeTo(size.width(), size.height());
+ shell->SizeTo(size);
// If |set_start_page| is true, start with blank page to make sure resize
// takes effect.
if (set_start_page)
@@ -134,7 +135,7 @@ class RenderViewSizeObserver : public WebContentsObserver {
rwhv_create_size_ = rvh->GetView()->GetViewBounds().size();
}
- virtual void NavigateToPendingEntry(
+ virtual void DidStartNavigationToPendingEntry(
const GURL& url,
NavigationController::ReloadType reload_type) OVERRIDE {
ResizeWebContentsView(shell_, wcv_new_size_, false);
@@ -148,8 +149,16 @@ class RenderViewSizeObserver : public WebContentsObserver {
gfx::Size rwhv_create_size_;
};
+// See: http://crbug.com/298193
+#if defined(OS_WIN)
+#define MAYBE_DidStopLoadingDetails DISABLED_DidStopLoadingDetails
+#else
+#define MAYBE_DidStopLoadingDetails DidStopLoadingDetails
+#endif
+
// Test that DidStopLoading includes the correct URL in the details.
-IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DidStopLoadingDetails) {
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ MAYBE_DidStopLoadingDetails) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
LoadStopNotificationObserver load_observer(
@@ -163,10 +172,18 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DidStopLoadingDetails) {
load_observer.controller_);
}
+// See: http://crbug.com/298193
+#if defined(OS_WIN)
+#define MAYBE_DidStopLoadingDetailsWithPending \
+ DISABLED_DidStopLoadingDetailsWithPending
+#else
+#define MAYBE_DidStopLoadingDetailsWithPending DidStopLoadingDetailsWithPending
+#endif
+
// Test that DidStopLoading includes the correct URL in the details when a
// pending entry is present.
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
- DidStopLoadingDetailsWithPending) {
+ MAYBE_DidStopLoadingDetailsWithPending) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
// Listen for the first load to stop.
@@ -213,45 +230,6 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
shell()->web_contents()->GetVisibleURL());
}
-// Test that the browser receives the proper frame attach/detach messages from
-// the renderer and builds proper frame tree.
-IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, FrameTree) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
-
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/frame_tree/top.html"));
-
- WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
- wc->GetRenderViewHost());
- FrameTreeNode* root = wc->GetFrameTreeRootForTesting();
-
- // Check that the root node is properly created with the frame id of the
- // initial navigation.
- EXPECT_EQ(3UL, root->child_count());
- EXPECT_EQ(std::string(), root->frame_name());
- EXPECT_EQ(rvh->main_frame_id(), root->frame_id());
-
- EXPECT_EQ(2UL, root->child_at(0)->child_count());
- EXPECT_STREQ("1-1-name", root->child_at(0)->frame_name().c_str());
-
- // Verify the deepest node exists and has the right name.
- EXPECT_EQ(2UL, root->child_at(2)->child_count());
- EXPECT_EQ(1UL, root->child_at(2)->child_at(1)->child_count());
- EXPECT_EQ(0UL, root->child_at(2)->child_at(1)->child_at(0)->child_count());
- EXPECT_STREQ("3-1-id",
- root->child_at(2)->child_at(1)->child_at(0)->frame_name().c_str());
-
- // Navigate to about:blank, which should leave only the root node of the frame
- // tree in the browser process.
- NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
-
- root = wc->GetFrameTreeRootForTesting();
- EXPECT_EQ(0UL, root->child_count());
- EXPECT_EQ(std::string(), root->frame_name());
- EXPECT_EQ(rvh->main_frame_id(), root->frame_id());
-}
-
// TODO(sail): enable this for MAC when auto resizing of WebContentsViewCocoa is
// fixed.
// TODO(shrikant): enable this for Windows when issue with
@@ -310,8 +288,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// RenderWidgetHostView is created at specified size.
init_size.Enlarge(size_insets.width(), size_insets.height());
EXPECT_EQ(init_size, observer.rwhv_create_size());
- // RenderViewSizeObserver resizes WebContentsView in NavigateToPendingEntry,
- // so both WebContentsView and RenderWidgetHostView adopt this new size.
+ // RenderViewSizeObserver resizes WebContentsView in
+ // DidStartNavigationToPendingEntry, so both WebContentsView and
+ // RenderWidgetHostView adopt this new size.
new_size.Enlarge(size_insets.width(), size_insets.height());
EXPECT_EQ(new_size,
shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
@@ -319,4 +298,20 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_EQ(new_size, shell()->web_contents()->GetView()->GetContainerSize());
}
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, OpenURLSubframe) {
+
+ // Navigate with source_frame_id 3, FrameTreeNode ID 4.
+ const GURL url("http://foo");
+ OpenURLParams params(url, Referrer(), 3, 4, CURRENT_TAB, PAGE_TRANSITION_LINK,
+ true);
+ shell()->web_contents()->OpenURL(params);
+
+ // Make sure the NavigationEntry ends up with the FrameTreeNode ID.
+ NavigationController* controller = &shell()->web_contents()->GetController();
+ EXPECT_TRUE(controller->GetPendingEntry());
+ EXPECT_EQ(4, NavigationEntryImpl::FromNavigationEntry(
+ controller->GetPendingEntry())->frame_tree_node_id());
+}
+
+
} // 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 aded7ae002f..1be4a3c0026 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -4,12 +4,10 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
#include "content/browser/site_instance_impl.h"
-#include "content/browser/web_contents/frame_tree_node.h"
-#include "content/browser/web_contents/interstitial_page_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/view_messages.h"
#include "content/public/browser/global_request_id.h"
@@ -23,11 +21,13 @@
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/url_constants.h"
+#include "content/public/common/url_utils.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_content_client.h"
+#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -114,8 +114,9 @@ class TestInterstitialPage : public InterstitialPageImpl {
InterstitialState* state,
bool* deleted)
: InterstitialPageImpl(
- contents, new_navigation, url,
- new TestInterstitialPageDelegate(this)),
+ contents,
+ static_cast<RenderWidgetHostDelegate*>(contents),
+ new_navigation, url, new TestInterstitialPageDelegate(this)),
state_(state),
deleted_(deleted),
command_received_count_(0),
@@ -183,7 +184,7 @@ class TestInterstitialPage : public InterstitialPageImpl {
virtual RenderViewHost* CreateRenderViewHost() OVERRIDE {
return new TestRenderViewHost(
SiteInstance::Create(web_contents()->GetBrowserContext()),
- this, this, MSG_ROUTING_NONE, MSG_ROUTING_NONE, false);
+ this, this, this, MSG_ROUTING_NONE, MSG_ROUTING_NONE, false);
}
virtual WebContentsView* CreateWebContentsView() OVERRIDE {
@@ -284,7 +285,7 @@ class TestWebContentsObserver : public WebContentsObserver {
const GURL& validated_url,
bool is_main_frame,
int error_code,
- const string16& error_description,
+ const base::string16& error_description,
RenderViewHost* render_view_host) OVERRIDE {
last_url_ = validated_url;
}
@@ -314,6 +315,26 @@ TEST_F(WebContentsImplTest, UpdateTitle) {
EXPECT_EQ(ASCIIToUTF16("Lots O' Whitespace"), contents()->GetTitle());
}
+TEST_F(WebContentsImplTest, DontUseTitleFromPendingEntry) {
+ const GURL kGURL("chrome://blah");
+ controller().LoadURL(
+ kGURL, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ EXPECT_EQ(base::string16(), contents()->GetTitle());
+}
+
+TEST_F(WebContentsImplTest, UseTitleFromPendingEntryIfSet) {
+ const GURL kGURL("chrome://blah");
+ const base::string16 title = ASCIIToUTF16("My Title");
+ controller().LoadURL(
+ kGURL, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+
+ NavigationEntry* entry = controller().GetVisibleEntry();
+ ASSERT_EQ(kGURL, entry->GetURL());
+ entry->SetTitle(title);
+
+ EXPECT_EQ(title, contents()->GetTitle());
+}
+
// Test view source mode for a webui page.
TEST_F(WebContentsImplTest, NTPViewSource) {
NavigationControllerImpl& cont =
@@ -376,7 +397,7 @@ TEST_F(WebContentsImplTest, SimpleNavigation) {
// Controller's pending entry will have a NULL site instance until we assign
// it in DidNavigate.
EXPECT_TRUE(
- NavigationEntryImpl::FromNavigationEntry(controller().GetActiveEntry())->
+ NavigationEntryImpl::FromNavigationEntry(controller().GetVisibleEntry())->
site_instance() == NULL);
// DidNavigate from the page
@@ -388,7 +409,7 @@ TEST_F(WebContentsImplTest, SimpleNavigation) {
// able to find it later.
EXPECT_EQ(
instance1,
- NavigationEntryImpl::FromNavigationEntry(controller().GetActiveEntry())->
+ NavigationEntryImpl::FromNavigationEntry(controller().GetVisibleEntry())->
site_instance());
}
@@ -396,11 +417,11 @@ TEST_F(WebContentsImplTest, SimpleNavigation) {
TEST_F(WebContentsImplTest, NavigateToExcessivelyLongURL) {
// Construct a URL that's kMaxURLChars + 1 long of all 'a's.
const GURL url(std::string("http://example.org/").append(
- kMaxURLChars + 1, 'a'));
+ GetMaxURLChars() + 1, 'a'));
controller().LoadURL(
url, Referrer(), PAGE_TRANSITION_GENERATED, std::string());
- EXPECT_TRUE(controller().GetActiveEntry() == NULL);
+ EXPECT_TRUE(controller().GetVisibleEntry() == NULL);
}
// Test that navigating across a site boundary creates a new RenderViewHost
@@ -1061,8 +1082,11 @@ TEST_F(WebContentsImplTest, CrossSiteCantPreemptAfterUnload) {
// Simulate the pending renderer's response, which leads to an unload request
// being sent to orig_rvh.
+ std::vector<GURL> url_chain;
+ url_chain.push_back(GURL());
contents()->GetRenderManagerForTesting()->OnCrossSiteResponse(
- pending_rvh, GlobalRequestID(0, 0));
+ pending_rvh, GlobalRequestID(0, 0), false, url_chain, Referrer(),
+ PAGE_TRANSITION_TYPED, 1, false);
// Suppose the original renderer navigates now, while the unload request is in
// flight. We should ignore it, wait for the unload ack, and let the pending
@@ -1233,7 +1257,7 @@ TEST_F(WebContentsImplTest,
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
- NavigationEntry* entry = controller().GetActiveEntry();
+ NavigationEntry* entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == url2);
@@ -1242,7 +1266,7 @@ TEST_F(WebContentsImplTest,
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == NULL);
- entry = controller().GetActiveEntry();
+ entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == url1);
EXPECT_EQ(1, controller().GetEntryCount());
@@ -1280,7 +1304,7 @@ TEST_F(WebContentsImplTest,
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
- NavigationEntry* entry = controller().GetActiveEntry();
+ NavigationEntry* entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == url2);
@@ -1289,7 +1313,7 @@ TEST_F(WebContentsImplTest,
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == NULL);
- entry = controller().GetActiveEntry();
+ entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == url1);
EXPECT_EQ(1, controller().GetEntryCount());
@@ -1325,7 +1349,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationDontProceed) {
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
- NavigationEntry* entry = controller().GetActiveEntry();
+ NavigationEntry* entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
// The URL specified to the interstitial should have been ignored.
EXPECT_TRUE(entry->GetURL() == url1);
@@ -1335,7 +1359,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationDontProceed) {
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == NULL);
- entry = controller().GetActiveEntry();
+ entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == url1);
EXPECT_EQ(1, controller().GetEntryCount());
@@ -1376,7 +1400,7 @@ TEST_F(WebContentsImplTest,
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
- NavigationEntry* entry = controller().GetActiveEntry();
+ NavigationEntry* entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == url2);
@@ -1396,7 +1420,7 @@ TEST_F(WebContentsImplTest,
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == NULL);
- entry = controller().GetActiveEntry();
+ entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == url3);
@@ -1434,7 +1458,7 @@ TEST_F(WebContentsImplTest,
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
- NavigationEntry* entry = controller().GetActiveEntry();
+ NavigationEntry* entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == url2);
@@ -1454,7 +1478,7 @@ TEST_F(WebContentsImplTest,
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == NULL);
- entry = controller().GetActiveEntry();
+ entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == url3);
@@ -1491,7 +1515,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationProceed) {
EXPECT_TRUE(interstitial->is_showing());
EXPECT_TRUE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial);
- NavigationEntry* entry = controller().GetActiveEntry();
+ NavigationEntry* entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
// The URL specified to the interstitial should have been ignored.
EXPECT_TRUE(entry->GetURL() == url1);
@@ -1503,7 +1527,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationProceed) {
EXPECT_EQ(TestInterstitialPage::OKED, state);
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == NULL);
- entry = controller().GetActiveEntry();
+ entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == url1);
@@ -1562,7 +1586,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) {
// Make sure we are back to the original page and that the interstitial is
// gone.
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
- NavigationEntry* entry = controller().GetActiveEntry();
+ NavigationEntry* entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry);
EXPECT_EQ(url1.spec(), entry->GetURL().spec());
@@ -1602,7 +1626,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) {
// Make sure we are back to the original page and that the interstitial is
// gone.
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
- NavigationEntry* entry = controller().GetActiveEntry();
+ NavigationEntry* entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry);
EXPECT_EQ(url1.spec(), entry->GetURL().spec());
@@ -1769,7 +1793,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == NULL);
- NavigationEntry* entry = controller().GetActiveEntry();
+ NavigationEntry* entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == landing_url);
EXPECT_EQ(2, controller().GetEntryCount());
@@ -1828,7 +1852,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) {
EXPECT_TRUE(deleted2);
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == NULL);
- NavigationEntry* entry = controller().GetActiveEntry();
+ NavigationEntry* entry = controller().GetVisibleEntry();
ASSERT_TRUE(entry != NULL);
EXPECT_TRUE(entry->GetURL() == landing_url);
EXPECT_EQ(2, controller().GetEntryCount());
@@ -2054,7 +2078,7 @@ TEST_F(WebContentsImplTest, CopyStateFromAndPruneSourceInterstitial) {
NavigationEntryImpl::FromNavigationEntry(
other_controller.GetEntryAtIndex(0))->site_instance(), 1,
other_controller.GetEntryAtIndex(0)->GetPageID());
- other_controller.CopyStateFromAndPrune(&controller());
+ other_controller.CopyStateFromAndPrune(&controller(), false);
// The merged controller should only have two entries: url1 and url2.
ASSERT_EQ(2, other_controller.GetEntryCount());
@@ -2098,7 +2122,7 @@ TEST_F(WebContentsImplTest, CopyStateFromAndPruneTargetInterstitial) {
// Ensure that we do not allow calling CopyStateFromAndPrune when an
// interstitial is showing in the target.
- EXPECT_FALSE(other_controller.CanPruneAllButVisible());
+ EXPECT_FALSE(other_controller.CanPruneAllButLastCommitted());
}
// Regression test for http://crbug.com/168611 - the URLs passed by the
@@ -2129,7 +2153,7 @@ TEST_F(WebContentsImplTest, FilterURLs) {
// Check that an IPC with about:whatever is correctly normalized.
other_contents->TestDidFailLoadWithError(
- 1, url_from_ipc, true, 1, string16());
+ 1, url_from_ipc, true, 1, base::string16());
EXPECT_EQ(url_normalized, other_observer.last_url());
}
@@ -2144,82 +2168,4 @@ TEST_F(WebContentsImplTest, PendingContents) {
EXPECT_EQ(NULL, contents()->GetCreatedWindow(route_id));
}
-// This test asserts the shape of the frame tree is correct, based on incoming
-// frame attached/detached messages.
-TEST_F(WebContentsImplTest, FrameTreeShape) {
- std::string no_children_node("no children node");
- std::string deep_subtree("node with deep subtree");
-
- // The initial navigation will create a frame_tree_root_ node with the top
- // level frame id. Simulate that by just creating it here.
- contents()->frame_tree_root_.reset(
- new FrameTreeNode(5, std::string("top-level")));
-
- // Let's send a series of messages for frame attached and build the
- // frame tree.
- contents()->OnFrameAttached(5, 14, std::string());
- contents()->OnFrameAttached(5, 15, std::string());
- contents()->OnFrameAttached(5, 16, std::string());
-
- contents()->OnFrameAttached(14, 244, std::string());
- contents()->OnFrameAttached(14, 245, std::string());
-
- contents()->OnFrameAttached(15, 255, no_children_node);
-
- contents()->OnFrameAttached(16, 264, std::string());
- contents()->OnFrameAttached(16, 265, std::string());
- contents()->OnFrameAttached(16, 266, std::string());
- contents()->OnFrameAttached(16, 267, deep_subtree);
- contents()->OnFrameAttached(16, 268, std::string());
-
- contents()->OnFrameAttached(267, 365, std::string());
- contents()->OnFrameAttached(365, 455, std::string());
- contents()->OnFrameAttached(455, 555, std::string());
- contents()->OnFrameAttached(555, 655, std::string());
-
- // Now, verify the tree structure is as expected.
- FrameTreeNode* root = contents()->frame_tree_root_.get();
- EXPECT_EQ(5, root->frame_id());
- EXPECT_EQ(3UL, root->child_count());
-
- EXPECT_EQ(2UL, root->child_at(0)->child_count());
- EXPECT_EQ(0UL, root->child_at(0)->child_at(0)->child_count());
- EXPECT_EQ(0UL, root->child_at(0)->child_at(1)->child_count());
-
- EXPECT_EQ(1UL, root->child_at(1)->child_count());
- EXPECT_EQ(0UL, root->child_at(1)->child_at(0)->child_count());
- EXPECT_STREQ(no_children_node.c_str(),
- root->child_at(1)->child_at(0)->frame_name().c_str());
-
- EXPECT_EQ(5UL, root->child_at(2)->child_count());
- EXPECT_EQ(0UL, root->child_at(2)->child_at(0)->child_count());
- EXPECT_EQ(0UL, root->child_at(2)->child_at(1)->child_count());
- EXPECT_EQ(0UL, root->child_at(2)->child_at(2)->child_count());
- EXPECT_EQ(1UL, root->child_at(2)->child_at(3)->child_count());
- EXPECT_STREQ(deep_subtree.c_str(),
- root->child_at(2)->child_at(3)->frame_name().c_str());
- EXPECT_EQ(0UL, root->child_at(2)->child_at(4)->child_count());
-
- FrameTreeNode* deep_tree = root->child_at(2)->child_at(3)->child_at(0);
- EXPECT_EQ(365, deep_tree->frame_id());
- EXPECT_EQ(1UL, deep_tree->child_count());
- EXPECT_EQ(455, deep_tree->child_at(0)->frame_id());
- EXPECT_EQ(1UL, deep_tree->child_at(0)->child_count());
- EXPECT_EQ(555, deep_tree->child_at(0)->child_at(0)->frame_id());
- EXPECT_EQ(1UL, deep_tree->child_at(0)->child_at(0)->child_count());
- EXPECT_EQ(655, deep_tree->child_at(0)->child_at(0)->child_at(0)->frame_id());
- EXPECT_EQ(0UL,
- deep_tree->child_at(0)->child_at(0)->child_at(0)->child_count());
-
- // Test removing of nodes.
- contents()->OnFrameDetached(555, 655);
- EXPECT_EQ(0UL, deep_tree->child_at(0)->child_at(0)->child_count());
-
- contents()->OnFrameDetached(16, 265);
- EXPECT_EQ(4UL, root->child_at(2)->child_count());
-
- contents()->OnFrameDetached(5, 15);
- EXPECT_EQ(2UL, root->child_count());
-}
-
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_view_android.cc b/chromium/content/browser/web_contents/web_contents_view_android.cc
index b51449e2e40..21fcf542bb5 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_android.cc
@@ -6,11 +6,11 @@
#include "base/logging.h"
#include "content/browser/android/content_view_core_impl.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/media/android/browser_media_player_manager.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/web_contents/interstitial_page_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents_delegate.h"
@@ -54,13 +54,13 @@ void WebContentsViewAndroid::SetContentViewCore(
}
}
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
void WebContentsViewAndroid::NotifyExternalSurface(
int player_id, bool is_request, const gfx::RectF& rect) {
if (content_view_core_)
content_view_core_->NotifyExternalSurface(player_id, is_request, rect);
}
-#endif
+#endif // defined(VIDEO_HOLE)
gfx::NativeView WebContentsViewAndroid::GetNativeView() const {
return content_view_core_ ? content_view_core_->GetViewAndroid() : NULL;
@@ -80,7 +80,7 @@ void WebContentsViewAndroid::GetContainerBounds(gfx::Rect* out) const {
*out = rwhv->GetViewBounds();
}
-void WebContentsViewAndroid::SetPageTitle(const string16& title) {
+void WebContentsViewAndroid::SetPageTitle(const base::string16& title) {
if (content_view_core_)
content_view_core_->SetTitle(title);
}
@@ -199,14 +199,14 @@ void WebContentsViewAndroid::ShowPopupMenu(
void WebContentsViewAndroid::StartDragging(
const DropData& drop_data,
- WebKit::WebDragOperationsMask allowed_ops,
+ blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) {
NOTIMPLEMENTED();
}
-void WebContentsViewAndroid::UpdateDragCursor(WebKit::WebDragOperation op) {
+void WebContentsViewAndroid::UpdateDragCursor(blink::WebDragOperation op) {
NOTIMPLEMENTED();
}
diff --git a/chromium/content/browser/web_contents/web_contents_view_android.h b/chromium/content/browser/web_contents/web_contents_view_android.h
index 594bc5c340d..48cfee9b39e 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.h
+++ b/chromium/content/browser/web_contents/web_contents_view_android.h
@@ -29,11 +29,11 @@ class WebContentsViewAndroid : public WebContentsViewPort,
// by the UI frontend.
void SetContentViewCore(ContentViewCoreImpl* content_view_core);
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
void NotifyExternalSurface(int player_id,
bool is_request,
const gfx::RectF& rect);
-#endif
+#endif // defined(VIDEO_HOLE)
// WebContentsView implementation --------------------------------------------
virtual gfx::NativeView GetNativeView() const OVERRIDE;
@@ -57,7 +57,7 @@ class WebContentsViewAndroid : public WebContentsViewPort,
RenderWidgetHost* render_widget_host) OVERRIDE;
virtual RenderWidgetHostView* CreateViewForPopupWidget(
RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual void SetPageTitle(const string16& title) OVERRIDE;
+ virtual void SetPageTitle(const base::string16& title) OVERRIDE;
virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE;
virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE;
virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
@@ -72,11 +72,11 @@ class WebContentsViewAndroid : public WebContentsViewPort,
bool right_aligned,
bool allow_multiple_selection) OVERRIDE;
virtual void StartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask allowed_ops,
+ blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) OVERRIDE;
- virtual void UpdateDragCursor(WebKit::WebDragOperation operation) OVERRIDE;
+ virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE;
virtual void GotFocus() OVERRIDE;
virtual void TakeFocus(bool reverse) OVERRIDE;
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura.cc b/chromium/content/browser/web_contents/web_contents_view_aura.cc
index f3822f8b1c6..484d04b33de 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -6,8 +6,12 @@
#include "base/auto_reset.h"
#include "base/command_line.h"
+#include "base/file_util.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/download/drag_download_util.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
@@ -17,10 +21,9 @@
#include "content/browser/web_contents/aura/image_window_delegate.h"
#include "content/browser/web_contents/aura/shadow_layer_delegate.h"
#include "content/browser/web_contents/aura/window_slider.h"
-#include "content/browser/web_contents/interstitial_page_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/browser/web_contents/touch_editable_impl_aura.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
@@ -33,6 +36,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_view_delegate.h"
#include "content/public/browser/web_drag_dest_delegate.h"
+#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/drop_data.h"
#include "net/base/net_util.h"
@@ -40,6 +44,8 @@
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/drag_drop_delegate.h"
+#include "ui/aura/client/window_tree_client.h"
+#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
#include "ui/aura/root_window_observer.h"
#include "ui/aura/window.h"
@@ -48,6 +54,7 @@
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drag_utils.h"
+#include "ui/base/dragdrop/drop_target_event.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/hit_test.h"
#include "ui/compositor/layer.h"
@@ -123,7 +130,8 @@ class OverscrollWindowDelegate : public ImageWindowDelegate {
if (entry && entry->screenshot().get()) {
std::vector<gfx::ImagePNGRep> image_reps;
image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
- ui::GetScaleFactorForNativeView(web_contents_window())));
+ ui::GetImageScale(
+ ui::GetScaleFactorForNativeView(web_contents_window()))));
image = gfx::Image(image_reps);
}
SetImage(image);
@@ -245,19 +253,83 @@ void PrepareDragForFileContents(const DropData& drop_data,
// Images without ALT text will only have a file extension so we need to
// synthesize one from the provided extension and URL.
if (file_name.BaseName().RemoveExtension().empty()) {
- const string16 extension = file_name.Extension();
+ const base::string16 extension = file_name.Extension();
// Retrieve the name from the URL.
file_name = base::FilePath(net::GetSuggestedFilename(
drop_data.url, "", "", "", "", "")).ReplaceExtension(extension);
}
provider->SetFileContents(file_name, drop_data.file_contents);
}
+
+void PrepareDragForDownload(
+ const DropData& drop_data,
+ ui::OSExchangeData::Provider* provider,
+ WebContentsImpl* web_contents) {
+ const GURL& page_url = web_contents->GetLastCommittedURL();
+ const std::string& page_encoding = web_contents->GetEncoding();
+
+ // Parse the download metadata.
+ base::string16 mime_type;
+ base::FilePath file_name;
+ GURL download_url;
+ if (!ParseDownloadMetadata(drop_data.download_metadata,
+ &mime_type,
+ &file_name,
+ &download_url))
+ return;
+
+ // Generate the file name based on both mime type and proposed file name.
+ std::string default_name =
+ GetContentClient()->browser()->GetDefaultDownloadName();
+ base::FilePath generated_download_file_name =
+ net::GenerateFileName(download_url,
+ std::string(),
+ std::string(),
+ base::UTF16ToUTF8(file_name.value()),
+ base::UTF16ToUTF8(mime_type),
+ default_name);
+
+ // http://crbug.com/332579
+ base::ThreadRestrictions::ScopedAllowIO allow_file_operations;
+
+ base::FilePath temp_dir_path;
+ if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_drag"),
+ &temp_dir_path))
+ return;
+
+ base::FilePath download_path =
+ temp_dir_path.Append(generated_download_file_name);
+
+ // We cannot know when the target application will be done using the temporary
+ // file, so schedule it to be deleted after rebooting.
+ base::DeleteFileAfterReboot(download_path);
+ base::DeleteFileAfterReboot(temp_dir_path);
+
+ // Provide the data as file (CF_HDROP). A temporary download file with the
+ // Zone.Identifier ADS (Alternate Data Stream) attached will be created.
+ scoped_refptr<DragDownloadFile> download_file =
+ new DragDownloadFile(
+ download_path,
+ scoped_ptr<net::FileStream>(),
+ download_url,
+ Referrer(page_url, drop_data.referrer_policy),
+ page_encoding,
+ web_contents);
+ ui::OSExchangeData::DownloadFileInfo file_download(base::FilePath(),
+ download_file.get());
+ provider->SetDownloadFileInfo(file_download);
+}
#endif
// Utility to fill a ui::OSExchangeDataProvider object from DropData.
void PrepareDragData(const DropData& drop_data,
- ui::OSExchangeData::Provider* provider) {
+ ui::OSExchangeData::Provider* provider,
+ WebContentsImpl* web_contents) {
#if defined(OS_WIN)
+ // Put download before file contents to prefer the download of a image over
+ // its thumbnail link.
+ if (!drop_data.download_metadata.empty())
+ PrepareDragForDownload(drop_data, provider, web_contents);
// We set the file contents before the URL because the URL also sets file
// contents (to a .URL shortcut). We want to prefer file content data over
// a shortcut so we add it first.
@@ -292,20 +364,21 @@ void PrepareDragData(const DropData& drop_data,
// Utility to fill a DropData object from ui::OSExchangeData.
void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
- string16 plain_text;
+ base::string16 plain_text;
data.GetString(&plain_text);
if (!plain_text.empty())
drop_data->text = base::NullableString16(plain_text, false);
GURL url;
- string16 url_title;
- data.GetURLAndTitle(&url, &url_title);
+ base::string16 url_title;
+ data.GetURLAndTitle(
+ ui::OSExchangeData::DO_NOT_CONVERT_FILENAMES, &url, &url_title);
if (url.is_valid()) {
drop_data->url = url;
drop_data->url_title = url_title;
}
- string16 html;
+ base::string16 html;
GURL html_base_url;
data.GetHtml(&html, &html_base_url);
if (!html.empty())
@@ -330,40 +403,40 @@ void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
pickle.data(), pickle.size(), &drop_data->custom_data);
}
-// Utilities to convert between WebKit::WebDragOperationsMask and
+// Utilities to convert between blink::WebDragOperationsMask and
// ui::DragDropTypes.
-int ConvertFromWeb(WebKit::WebDragOperationsMask ops) {
+int ConvertFromWeb(blink::WebDragOperationsMask ops) {
int drag_op = ui::DragDropTypes::DRAG_NONE;
- if (ops & WebKit::WebDragOperationCopy)
+ if (ops & blink::WebDragOperationCopy)
drag_op |= ui::DragDropTypes::DRAG_COPY;
- if (ops & WebKit::WebDragOperationMove)
+ if (ops & blink::WebDragOperationMove)
drag_op |= ui::DragDropTypes::DRAG_MOVE;
- if (ops & WebKit::WebDragOperationLink)
+ if (ops & blink::WebDragOperationLink)
drag_op |= ui::DragDropTypes::DRAG_LINK;
return drag_op;
}
-WebKit::WebDragOperationsMask ConvertToWeb(int drag_op) {
- int web_drag_op = WebKit::WebDragOperationNone;
+blink::WebDragOperationsMask ConvertToWeb(int drag_op) {
+ int web_drag_op = blink::WebDragOperationNone;
if (drag_op & ui::DragDropTypes::DRAG_COPY)
- web_drag_op |= WebKit::WebDragOperationCopy;
+ web_drag_op |= blink::WebDragOperationCopy;
if (drag_op & ui::DragDropTypes::DRAG_MOVE)
- web_drag_op |= WebKit::WebDragOperationMove;
+ web_drag_op |= blink::WebDragOperationMove;
if (drag_op & ui::DragDropTypes::DRAG_LINK)
- web_drag_op |= WebKit::WebDragOperationLink;
- return (WebKit::WebDragOperationsMask) web_drag_op;
+ web_drag_op |= blink::WebDragOperationLink;
+ return (blink::WebDragOperationsMask) web_drag_op;
}
int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) {
int web_input_event_modifiers = 0;
if (aura_event_flags & ui::EF_SHIFT_DOWN)
- web_input_event_modifiers |= WebKit::WebInputEvent::ShiftKey;
+ web_input_event_modifiers |= blink::WebInputEvent::ShiftKey;
if (aura_event_flags & ui::EF_CONTROL_DOWN)
- web_input_event_modifiers |= WebKit::WebInputEvent::ControlKey;
+ web_input_event_modifiers |= blink::WebInputEvent::ControlKey;
if (aura_event_flags & ui::EF_ALT_DOWN)
- web_input_event_modifiers |= WebKit::WebInputEvent::AltKey;
+ web_input_event_modifiers |= blink::WebInputEvent::AltKey;
if (aura_event_flags & ui::EF_COMMAND_DOWN)
- web_input_event_modifiers |= WebKit::WebInputEvent::MetaKey;
+ web_input_event_modifiers |= blink::WebInputEvent::MetaKey;
return web_input_event_modifiers;
}
@@ -515,7 +588,8 @@ class OverscrollNavigationOverlay :
if (entry && entry->screenshot().get()) {
std::vector<gfx::ImagePNGRep> image_reps;
image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
- ui::GetScaleFactorForNativeView(window_.get())));
+ ui::GetImageScale(
+ ui::GetScaleFactorForNativeView(window_.get()))));
image = gfx::Image(image_reps);
}
layer_delegate_.SetImage(image);
@@ -650,49 +724,176 @@ class WebContentsViewAura::WindowObserver
: view_(view),
parent_(NULL) {
view_->window_->AddObserver(this);
+
+#if defined(OS_WIN)
+ if (view_->window_->GetRootWindow())
+ view_->window_->GetRootWindow()->AddObserver(this);
+#endif
}
virtual ~WindowObserver() {
view_->window_->RemoveObserver(this);
- if (view_->window_->GetRootWindow())
- view_->window_->GetRootWindow()->RemoveRootWindowObserver(this);
+ if (view_->window_->GetDispatcher())
+ view_->window_->GetDispatcher()->RemoveRootWindowObserver(this);
if (parent_)
parent_->RemoveObserver(this);
+
+#if defined(OS_WIN)
+ if (parent_) {
+ const aura::Window::Windows& children = parent_->children();
+ for (size_t i = 0; i < children.size(); ++i)
+ children[i]->RemoveObserver(this);
+ }
+
+ aura::Window* root_window = view_->window_->GetRootWindow();
+ if (root_window) {
+ root_window->RemoveObserver(this);
+ const aura::Window::Windows& root_children = root_window->children();
+ for (size_t i = 0; i < root_children.size(); ++i)
+ root_children[i]->RemoveObserver(this);
+ }
+#endif
}
// Overridden from aura::WindowObserver:
+#if defined(OS_WIN)
+ // Constrained windows are added as children of the parent's parent's view
+ // which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
+ // so that it can update the plugins' cutout rects accordingly.
+ // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
+ // going to be deprecated in a year, this is ok for now. The test for this is
+ // PrintPreviewTest.WindowedNPAPIPluginHidden.
+ virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE {
+ if (new_window == view_->window_)
+ return;
+
+ if (new_window == parent_)
+ return; // This happens if the parent moves to the root window.
+
+ // Observe sibling windows of the WebContents, or children of the root
+ // window.
+ if (new_window->parent() == parent_ ||
+ new_window->parent() == view_->window_->GetRootWindow()) {
+ new_window->AddObserver(this);
+ UpdateConstrainedWindows(NULL);
+ }
+ }
+
+ virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE {
+ if (window == view_->window_)
+ return;
+
+ window->RemoveObserver(this);
+ UpdateConstrainedWindows(window);
+ }
+
+ virtual void OnWindowVisibilityChanged(aura::Window* window,
+ bool visible) OVERRIDE {
+ if (window == view_->window_ ||
+ window->parent() == parent_ ||
+ window->parent() == view_->window_->GetRootWindow()) {
+ UpdateConstrainedWindows(NULL);
+ }
+ }
+#endif
+
virtual void OnWindowParentChanged(aura::Window* window,
aura::Window* parent) OVERRIDE {
- if (window == parent_)
+ if (window != view_->window_)
return;
if (parent_)
parent_->RemoveObserver(this);
+
+#if defined(OS_WIN)
+ if (parent_) {
+ const aura::Window::Windows& children = parent_->children();
+ for (size_t i = 0; i < children.size(); ++i)
+ children[i]->RemoveObserver(this);
+
+ RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
+ view_->web_contents_->GetRenderWidgetHostView());
+ if (view)
+ view->UpdateConstrainedWindowRects(std::vector<gfx::Rect>());
+ }
+
+ // When we get parented to the root window, the code below will watch the
+ // parent, aka root window. Since we already watch the root window on
+ // Windows, unregister first so that the debug check doesn't fire.
+ if (parent && parent == window->GetRootWindow())
+ parent->RemoveObserver(this);
+
+ // We need to undo the above if we were parented to the root window and then
+ // got parented to another window. At that point, the code before the ifdef
+ // would have stopped watching the root window.
+ if (window->GetRootWindow() &&
+ parent != window->GetRootWindow() &&
+ !window->GetRootWindow()->HasObserver(this)) {
+ window->GetRootWindow()->AddObserver(this);
+ }
+#endif
+
parent_ = parent;
- if (parent)
+ if (parent) {
parent->AddObserver(this);
+#if defined(OS_WIN)
+ if (parent != window->GetRootWindow()) {
+ const aura::Window::Windows& children = parent->children();
+ for (size_t i = 0; i < children.size(); ++i) {
+ if (children[i] != view_->window_)
+ children[i]->AddObserver(this);
+ }
+ }
+#endif
+ }
}
virtual void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) OVERRIDE {
- SendScreenRects();
- if (view_->touch_editable_)
- view_->touch_editable_->UpdateEditingController();
+ if (window == parent_ || window == view_->window_) {
+ SendScreenRects();
+ if (view_->touch_editable_)
+ view_->touch_editable_->UpdateEditingController();
+#if defined(OS_WIN)
+ } else {
+ UpdateConstrainedWindows(NULL);
+#endif
+ }
}
virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
- if (window != parent_)
- window->GetRootWindow()->AddRootWindowObserver(this);
+ if (window == view_->window_) {
+ window->GetDispatcher()->AddRootWindowObserver(this);
+#if defined(OS_WIN)
+ if (!window->GetRootWindow()->HasObserver(this))
+ window->GetRootWindow()->AddObserver(this);
+#endif
+ }
}
virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE {
- if (window != parent_)
- window->GetRootWindow()->RemoveRootWindowObserver(this);
+ if (window == view_->window_) {
+ window->GetDispatcher()->RemoveRootWindowObserver(this);
+#if defined(OS_WIN)
+ window->GetRootWindow()->RemoveObserver(this);
+
+ const aura::Window::Windows& root_children =
+ window->GetRootWindow()->children();
+ for (size_t i = 0; i < root_children.size(); ++i) {
+ if (root_children[i] != view_->window_ && root_children[i] != parent_)
+ root_children[i]->RemoveObserver(this);
+ }
+#endif
+ }
}
// Overridden RootWindowObserver:
virtual void OnRootWindowHostMoved(const aura::RootWindow* root,
const gfx::Point& new_origin) OVERRIDE {
+ TRACE_EVENT1("ui",
+ "WebContentsViewAura::WindowObserver::OnRootWindowHostMoved",
+ "new_origin", new_origin.ToString());
+
// This is for the desktop case (i.e. Aura desktop).
SendScreenRects();
}
@@ -703,104 +904,49 @@ class WebContentsViewAura::WindowObserver
SendScreenRects();
}
- WebContentsViewAura* view_;
-
- // We cache the old parent so that we can unregister when it's not the parent
- // anymore.
- aura::Window* parent_;
-
- DISALLOW_COPY_AND_ASSIGN(WindowObserver);
-};
-
#if defined(OS_WIN)
-// Constrained windows are added as children of the WebContent's view which may
-// overlap with windowed NPAPI plugins. In that case, tell the RWHV so that it
-// can update the plugins' cutout rects accordingly.
-class WebContentsViewAura::ChildWindowObserver : public aura::WindowObserver,
- public WebContentsObserver {
- public:
- explicit ChildWindowObserver(WebContentsViewAura* view)
- : WebContentsObserver(view->web_contents_),
- view_(view),
- web_contents_destroyed_(false) {
- view_->window_->AddObserver(this);
- }
-
- virtual ~ChildWindowObserver() {
- view_->window_->RemoveObserver(this);
- const aura::Window::Windows& children = view_->window_->children();
- for (size_t i = 0; i < children.size(); ++i)
- children[i]->RemoveObserver(this);
- }
-
- // Overridden from aura::WindowObserver:
- virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE {
- // If new child windows are added to the WebContent's view, tell the RWHV.
- // We also start watching them to know when their size is updated. Of
- // course, ignore the shadow window that contains the RWHV and child windows
- // of the child windows that we are watching.
- RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
- view_->web_contents_->GetRenderWidgetHostView());
- aura::Window* content_window = view ? view->GetNativeView() : NULL;
- if (new_window->parent() == view_->window_ &&
- new_window != content_window) {
- new_window->AddObserver(this);
- UpdateConstrainedWindows(NULL);
- }
- }
-
- virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE {
- RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
- view_->web_contents_->GetRenderWidgetHostView());
- aura::Window* content_window = view ? view->GetNativeView() : NULL;
- if (window->parent() == view_->window_ &&
- window != content_window) {
- window->RemoveObserver(this);
- UpdateConstrainedWindows(window);
- }
- }
-
- virtual void OnWindowBoundsChanged(aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) OVERRIDE {
- if (window->parent() == view_->window_ &&
- window != view_->GetContentNativeView()) {
- UpdateConstrainedWindows(NULL);
- }
- }
-
- // Overridden from WebContentsObserver:
- virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
- web_contents_destroyed_ = true;
- }
-
- private:
void UpdateConstrainedWindows(aura::Window* exclude) {
- if (web_contents_destroyed_)
- return;
-
RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
view_->web_contents_->GetRenderWidgetHostView());
if (!view)
return;
std::vector<gfx::Rect> constrained_windows;
- const aura::Window::Windows& children = view_->window_->children();
- aura::Window* content = view_->GetContentNativeView();
- for (size_t i = 0; i < children.size(); ++i) {
- if (children[i] != content && children[i] != exclude)
- constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
+ if (parent_) {
+ const aura::Window::Windows& children = parent_->children();
+ for (size_t i = 0; i < children.size(); ++i) {
+ if (children[i] != view_->window_ &&
+ children[i] != exclude &&
+ children[i]->IsVisible()) {
+ constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
+ }
+ }
+ }
+
+ aura::Window* root_window = view_->window_->GetRootWindow();
+ const aura::Window::Windows& root_children = root_window->children();
+ if (root_window) {
+ for (size_t i = 0; i < root_children.size(); ++i) {
+ if (root_children[i]->IsVisible() &&
+ !root_children[i]->Contains(view_->window_.get())) {
+ constrained_windows.push_back(
+ root_children[i]->GetBoundsInRootWindow());
+ }
+ }
}
view->UpdateConstrainedWindowRects(constrained_windows);
}
+#endif
WebContentsViewAura* view_;
- bool web_contents_destroyed_;
- DISALLOW_COPY_AND_ASSIGN(ChildWindowObserver);
+ // We cache the old parent so that we can unregister when it's not the parent
+ // anymore.
+ aura::Window* parent_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowObserver);
};
-#endif
////////////////////////////////////////////////////////////////////////////////
// WebContentsViewAura, public:
@@ -810,7 +956,7 @@ WebContentsViewAura::WebContentsViewAura(
WebContentsViewDelegate* delegate)
: web_contents_(web_contents),
delegate_(delegate),
- current_drag_op_(WebKit::WebDragOperationNone),
+ current_drag_op_(blink::WebDragOperationNone),
drag_dest_delegate_(NULL),
current_rvh_for_drag_(NULL),
overscroll_change_brightness_(false),
@@ -827,9 +973,7 @@ WebContentsViewAura::~WebContentsViewAura() {
return;
window_observer_.reset();
-#if defined(OS_WIN)
- child_window_observer_.reset();
-#endif
+
// Window needs a valid delegate during its destructor, so we explicitly
// delete it here.
window_.reset();
@@ -855,8 +999,8 @@ void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
rwhv->SetSize(size);
}
-void WebContentsViewAura::EndDrag(WebKit::WebDragOperationsMask ops) {
- aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
+void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops) {
+ aura::Window* root_window = GetNativeView()->GetRootWindow();
gfx::Point screen_loc =
gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
gfx::Point client_loc = screen_loc;
@@ -1073,10 +1217,6 @@ void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const {
void WebContentsViewAura::OnTabCrashed(base::TerminationStatus status,
int error_code) {
- // Set the focus to the parent because neither the view window nor this
- // window can handle key events.
- if (window_->HasFocus() && window_->parent())
- window_->parent()->Focus();
}
void WebContentsViewAura::SizeContents(const gfx::Size& size) {
@@ -1139,12 +1279,13 @@ void WebContentsViewAura::CreateView(
// if the bookmark bar is not shown and you create a new tab). The right
// value is set shortly after this, so its safe to ignore.
+ aura::Env::CreateInstance();
window_.reset(new aura::Window(this));
window_->set_owned_by_parent(false);
window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
window_->SetTransparent(false);
window_->Init(ui::LAYER_NOT_DRAWN);
- aura::RootWindow* root_window = context ? context->GetRootWindow() : NULL;
+ aura::Window* root_window = context ? context->GetRootWindow() : NULL;
if (root_window) {
// There are places where there is no context currently because object
// hierarchies are built before they're attached to a Widget. (See
@@ -1155,17 +1296,20 @@ void WebContentsViewAura::CreateView(
// explicitly add this WebContentsViewAura to their tree after they create
// us.
if (root_window) {
- window_->SetDefaultParentByRootWindow(
- root_window, root_window->GetBoundsInScreen());
+ aura::client::ParentWindowWithContext(
+ window_.get(), root_window, root_window->GetBoundsInScreen());
}
}
window_->layer()->SetMasksToBounds(true);
window_->SetName("WebContentsViewAura");
- window_observer_.reset(new WindowObserver(this));
-#if defined(OS_WIN)
- child_window_observer_.reset(new ChildWindowObserver(this));
-#endif
+ // WindowObserver is not interesting and is problematic for Browser Plugin
+ // guests.
+ // The use cases for WindowObserver do not apply to Browser Plugins:
+ // 1) guests do not support NPAPI plugins.
+ // 2) guests' window bounds are supposed to come from its embedder.
+ if (!web_contents_->GetRenderProcessHost()->IsGuest())
+ window_observer_.reset(new WindowObserver(this));
// delegate_->GetDragDestDelegate() creates a new delegate on every call.
// Hence, we save a reference to it locally. Similar model is used on other
@@ -1221,7 +1365,7 @@ RenderWidgetHostView* WebContentsViewAura::CreateViewForPopupWidget(
return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host);
}
-void WebContentsViewAura::SetPageTitle(const string16& title) {
+void WebContentsViewAura::SetPageTitle(const base::string16& title) {
window_->set_title(title);
}
@@ -1276,11 +1420,11 @@ void WebContentsViewAura::ShowPopupMenu(const gfx::Rect& bounds,
void WebContentsViewAura::StartDragging(
const DropData& drop_data,
- WebKit::WebDragOperationsMask operations,
+ blink::WebDragOperationsMask operations,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) {
- aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
+ aura::Window* root_window = GetNativeView()->GetRootWindow();
if (!aura::client::GetDragDropClient(root_window)) {
web_contents_->SystemDragEnded();
return;
@@ -1290,7 +1434,7 @@ void WebContentsViewAura::StartDragging(
touch_editable_->EndTouchEditing();
ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider();
- PrepareDragData(drop_data, provider);
+ PrepareDragData(drop_data, provider, web_contents_);
ui::OSExchangeData data(provider); // takes ownership of |provider|.
@@ -1332,7 +1476,7 @@ void WebContentsViewAura::StartDragging(
web_contents_->SystemDragEnded();
}
-void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) {
+void WebContentsViewAura::UpdateDragCursor(blink::WebDragOperation operation) {
current_drag_op_ = operation;
}
@@ -1352,6 +1496,14 @@ void WebContentsViewAura::TakeFocus(bool reverse) {
////////////////////////////////////////////////////////////////////////////////
// WebContentsViewAura, OverscrollControllerDelegate implementation:
+gfx::Rect WebContentsViewAura::GetVisibleBounds() const {
+ RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
+ if (!rwhv || !rwhv->IsShowing())
+ return gfx::Rect();
+
+ return rwhv->GetViewBounds();
+}
+
void WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
if (current_overscroll_gesture_ == OVERSCROLL_NONE)
return;
@@ -1494,9 +1646,15 @@ bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
}
bool WebContentsViewAura::CanFocus() {
- // Do not take the focus if the render widget host view is gone because
- // neither the view window nor this window can handle key events.
- return web_contents_->GetRenderWidgetHostView() != NULL;
+ // Do not take the focus if the render widget host view aura is gone or
+ // is in the process of shutting down because neither the view window nor
+ // this window can handle key events.
+ RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
+ web_contents_->GetRenderWidgetHostView());
+ if (view != NULL && !view->IsClosing())
+ return true;
+
+ return false;
}
void WebContentsViewAura::OnCaptureLost() {
@@ -1576,7 +1734,7 @@ void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
current_drop_data_.reset(new DropData());
PrepareDropData(current_drop_data_.get(), event.data());
- WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
+ blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
gfx::Point screen_pt =
gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
@@ -1596,7 +1754,7 @@ int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
OnDragEntered(event);
- WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
+ blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
gfx::Point screen_pt =
gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
web_contents_->GetRenderViewHost()->DragTargetDragOver(
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 aca720e0763..a0597d38fa0 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.h
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.h
@@ -50,15 +50,12 @@ class CONTENT_EXPORT WebContentsViewAura
private:
class WindowObserver;
-#if defined(OS_WIN)
- class ChildWindowObserver;
-#endif
virtual ~WebContentsViewAura();
void SizeChangedCommon(const gfx::Size& size);
- void EndDrag(WebKit::WebDragOperationsMask ops);
+ void EndDrag(blink::WebDragOperationsMask ops);
// Creates and sets up the overlay window that will be displayed during the
// overscroll gesture.
@@ -121,7 +118,7 @@ class CONTENT_EXPORT WebContentsViewAura
RenderWidgetHost* render_widget_host) OVERRIDE;
virtual RenderWidgetHostView* CreateViewForPopupWidget(
RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual void SetPageTitle(const string16& title) OVERRIDE;
+ virtual void SetPageTitle(const base::string16& title) OVERRIDE;
virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE;
virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE;
virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
@@ -136,15 +133,16 @@ class CONTENT_EXPORT WebContentsViewAura
bool right_aligned,
bool allow_multiple_selection) OVERRIDE;
virtual void StartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask operations,
+ blink::WebDragOperationsMask operations,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) OVERRIDE;
- virtual void UpdateDragCursor(WebKit::WebDragOperation operation) OVERRIDE;
+ virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE;
virtual void GotFocus() OVERRIDE;
virtual void TakeFocus(bool reverse) OVERRIDE;
// Overridden from OverscrollControllerDelegate:
+ virtual gfx::Rect GetVisibleBounds() const OVERRIDE;
virtual void OnOverscrollUpdate(float delta_x, float delta_y) OVERRIDE;
virtual void OnOverscrollComplete(OverscrollMode overscroll_mode) OVERRIDE;
virtual void OnOverscrollModeChange(OverscrollMode old_mode,
@@ -192,16 +190,13 @@ class CONTENT_EXPORT WebContentsViewAura
scoped_ptr<aura::Window> overscroll_window_;
scoped_ptr<WindowObserver> window_observer_;
-#if defined(OS_WIN)
- scoped_ptr<ChildWindowObserver> child_window_observer_;
-#endif
// The WebContentsImpl whose contents we display.
WebContentsImpl* web_contents_;
scoped_ptr<WebContentsViewDelegate> delegate_;
- WebKit::WebDragOperationsMask current_drag_op_;
+ blink::WebDragOperationsMask current_drag_op_;
scoped_ptr<DropData> current_drop_data_;
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 a48cde5b170..687ce57606f 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
@@ -12,11 +12,11 @@
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
+#include "content/browser/frame_host/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/web_contents/navigation_controller_impl.h"
-#include "content/browser/web_contents/navigation_entry_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/web_contents/web_contents_screenshot_manager.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/content_switches.h"
@@ -33,10 +33,10 @@
namespace content {
// This class keeps track of the RenderViewHost whose screenshot was captured.
-class ScreenshotTracker : public WebContentsScreenshotManager {
+class ScreenshotTracker : public NavigationEntryScreenshotManager {
public:
explicit ScreenshotTracker(NavigationControllerImpl* controller)
- : WebContentsScreenshotManager(controller),
+ : NavigationEntryScreenshotManager(controller),
screenshot_taken_for_(NULL),
waiting_for_screenshots_(0) {
}
@@ -67,18 +67,18 @@ class ScreenshotTracker : public WebContentsScreenshotManager {
}
private:
- // Overridden from WebContentsScreenshotManager:
+ // Overridden from NavigationEntryScreenshotManager:
virtual void TakeScreenshotImpl(RenderViewHost* host,
NavigationEntryImpl* entry) OVERRIDE {
++waiting_for_screenshots_;
screenshot_taken_for_ = host;
- WebContentsScreenshotManager::TakeScreenshotImpl(host, entry);
+ NavigationEntryScreenshotManager::TakeScreenshotImpl(host, entry);
}
virtual void OnScreenshotSet(NavigationEntryImpl* entry) OVERRIDE {
--waiting_for_screenshots_;
screenshot_set_[entry] = true;
- WebContentsScreenshotManager::OnScreenshotSet(entry);
+ NavigationEntryScreenshotManager::OnScreenshotSet(entry);
if (waiting_for_screenshots_ == 0 && message_loop_runner_.get())
message_loop_runner_->Quit();
}
@@ -148,9 +148,6 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
ASSERT_TRUE(test_server()->Start());
GURL test_url(test_server()->GetURL(url));
NavigateToURL(shell(), test_url);
- aura::Window* content =
- shell()->web_contents()->GetView()->GetContentNativeView();
- content->GetRootWindow()->SetHostSize(gfx::Size(800, 600));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
@@ -199,14 +196,14 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
{
// Do a swipe-right now. That should navigate backwards.
- string16 expected_title = ASCIIToUTF16("Title: #1");
+ base::string16 expected_title = ASCIIToUTF16("Title: #1");
content::TitleWatcher title_watcher(web_contents, expected_title);
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(kScrollDurationMs),
kScrollSteps);
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
value = content::ExecuteScriptAndGetValue(view_host, "get_current()");
ASSERT_TRUE(value->GetAsInteger(&index));
@@ -217,14 +214,14 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
{
// Do a fling-right now. That should navigate backwards.
- string16 expected_title = ASCIIToUTF16("Title:");
+ base::string16 expected_title = ASCIIToUTF16("Title:");
content::TitleWatcher title_watcher(web_contents, expected_title);
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(kScrollDurationMs),
kScrollSteps);
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
value = content::ExecuteScriptAndGetValue(view_host, "get_current()");
ASSERT_TRUE(value->GetAsInteger(&index));
@@ -235,14 +232,14 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
{
// Do a swipe-left now. That should navigate forward.
- string16 expected_title = ASCIIToUTF16("Title: #1");
+ base::string16 expected_title = ASCIIToUTF16("Title: #1");
content::TitleWatcher title_watcher(web_contents, expected_title);
generator.GestureScrollSequence(
gfx::Point(bounds.right() - 10, bounds.y() + 10),
gfx::Point(bounds.x() + 2, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(kScrollDurationMs),
kScrollSteps);
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
value = content::ExecuteScriptAndGetValue(view_host, "get_current()");
ASSERT_TRUE(value->GetAsInteger(&index));
@@ -277,13 +274,26 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
};
-IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
- OverscrollNavigation) {
+// Flaky on Windows (perhaps just Win-Aura): http://crbug.com/305722
+#if defined(OS_WIN)
+#define MAYBE_OverscrollNavigation DISABLED_OverscrollNavigation
+#else
+#define MAYBE_OverscrollNavigation OverscrollNavigation
+#endif
+IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollNavigation) {
TestOverscrollNavigation(false);
}
+// Flaky on Windows (perhaps just Win-Aura): http://crbug.com/305722
+#if defined(OS_WIN)
+#define MAYBE_OverscrollNavigationWithTouchHandler \
+ DISABLED_OverscrollNavigationWithTouchHandler
+#else
+#define MAYBE_OverscrollNavigationWithTouchHandler \
+ OverscrollNavigationWithTouchHandler
+#endif
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
- OverscrollNavigationWithTouchHandler) {
+ MAYBE_OverscrollNavigationWithTouchHandler) {
TestOverscrollNavigation(true);
}
@@ -318,21 +328,21 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
EXPECT_EQ(1, GetCurrentIndex());
aura::Window* content = web_contents->GetView()->GetContentNativeView();
- aura::RootWindow* root_window = content->GetRootWindow();
+ aura::WindowEventDispatcher* dispatcher = content->GetDispatcher();
gfx::Rect bounds = content->GetBoundsInRootWindow();
base::TimeDelta timestamp;
ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
0, timestamp);
- root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ dispatcher->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
EXPECT_EQ(1, GetCurrentIndex());
timestamp += base::TimeDelta::FromMilliseconds(10);
ui::TouchEvent move1(ui::ET_TOUCH_MOVED,
gfx::Point(bounds.right() - 10, bounds.y() + 5),
0, timestamp);
- root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&move1);
+ dispatcher->AsRootWindowHostDelegate()->OnHostTouchEvent(&move1);
EXPECT_EQ(1, GetCurrentIndex());
// Swipe back from the right edge, back to the left edge, back to the right
@@ -343,7 +353,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
ui::TouchEvent inc(ui::ET_TOUCH_MOVED,
gfx::Point(x, bounds.y() + 5),
0, timestamp);
- root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc);
+ dispatcher->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc);
EXPECT_EQ(1, GetCurrentIndex());
}
@@ -352,7 +362,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
ui::TouchEvent inc(ui::ET_TOUCH_MOVED,
gfx::Point(x, bounds.y() + 5),
0, timestamp);
- root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc);
+ dispatcher->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc);
EXPECT_EQ(1, GetCurrentIndex());
}
@@ -361,7 +371,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
ui::TouchEvent inc(ui::ET_TOUCH_MOVED,
gfx::Point(x, bounds.y() + 5),
0, timestamp);
- root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc);
+ dispatcher->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc);
EXPECT_EQ(1, GetCurrentIndex());
}
@@ -428,7 +438,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, OverscrollScreenshot) {
{
// Now, swipe right to navigate backwards. This should navigate away from
// index 3 to index 2, and index 3 should have a screenshot.
- string16 expected_title = ASCIIToUTF16("Title: #2");
+ base::string16 expected_title = ASCIIToUTF16("Title: #2");
content::TitleWatcher title_watcher(web_contents, expected_title);
aura::Window* content = web_contents->GetView()->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
@@ -438,7 +448,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, OverscrollScreenshot) {
gfx::Point(bounds.right() - 10, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(20),
1);
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
EXPECT_EQ(2, GetCurrentIndex());
screenshot_manager()->WaitUntilScreenshotIsReady();
@@ -459,10 +469,10 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, OverscrollScreenshot) {
{
// Navigate back in history.
- string16 expected_title = ASCIIToUTF16("Title: #3");
+ base::string16 expected_title = ASCIIToUTF16("Title: #3");
content::TitleWatcher title_watcher(web_contents, expected_title);
web_contents->GetController().GoBack();
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
EXPECT_EQ(3, GetCurrentIndex());
screenshot_manager()->WaitUntilScreenshotIsReady();
@@ -522,7 +532,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
entry = NavigationEntryImpl::FromNavigationEntry(
- web_contents->GetController().GetActiveEntry());
+ web_contents->GetController().GetLastCommittedEntry());
EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
EXPECT_FALSE(entry->screenshot().get());
screenshot_manager()->Reset();
@@ -542,15 +552,15 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
EXPECT_EQ(NULL, screenshot_manager()->screenshot_taken_for());
}
-// Failing on win7_aura trybot (see crbug.com/260983).
-#if defined(OS_WIN)
-#define MAYBE_ContentWindowReparent \
- DISABLED_ContentWindowReparent
-#else
-#define MAYBE_ContentWindowReparent ContentWindowReparent
-#endif
+// TODO(sadrul): This test is disabled because it reparents in a way the
+// FocusController does not support. This code would crash in
+// a production build. It only passed prior to this revision
+// because testing used the old FocusManager which did some
+// different (osbolete) processing. TODO(sadrul) to figure out
+// how this test should work that mimics production code a bit
+// better.
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
- MAYBE_ContentWindowReparent) {
+ DISABLED_ContentWindowReparent) {
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/overscroll_navigation.html"));
@@ -631,7 +641,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
// Do a swipe left to start a forward navigation. Then quickly do a swipe
// right.
- string16 expected_title = ASCIIToUTF16("Title: #2");
+ base::string16 expected_title = ASCIIToUTF16("Title: #2");
content::TitleWatcher title_watcher(web_contents, expected_title);
NavigationWatcher nav_watcher(web_contents);
@@ -647,7 +657,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
gfx::Point(bounds.right() - 10, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(2000),
10);
- string16 actual_title = title_watcher.WaitAndGetTitle();
+ base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
EXPECT_EQ(2, GetCurrentIndex());
diff --git a/chromium/content/browser/web_contents/web_contents_view_gtk.cc b/chromium/content/browser/web_contents/web_contents_view_gtk.cc
index cdc36c8d11e..bf4dcb7fd3b 100644
--- a/chromium/content/browser/web_contents/web_contents_view_gtk.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_gtk.cc
@@ -13,10 +13,10 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
#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_gtk.h"
-#include "content/browser/web_contents/interstitial_page_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_drag_dest_gtk.h"
#include "content/browser/web_contents/web_drag_source_gtk.h"
@@ -29,8 +29,8 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationsMask;
+using blink::WebDragOperation;
+using blink::WebDragOperationsMask;
namespace content {
namespace {
@@ -175,6 +175,8 @@ void WebContentsViewGtk::RestoreFocus() {
}
DropData* WebContentsViewGtk::GetDropData() const {
+ if (!drag_dest_)
+ return NULL;
return drag_dest_->current_drop_data();
}
@@ -244,7 +246,7 @@ RenderWidgetHostView* WebContentsViewGtk::CreateViewForPopupWidget(
return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host);
}
-void WebContentsViewGtk::SetPageTitle(const string16& title) {
+void WebContentsViewGtk::SetPageTitle(const base::string16& title) {
// Set the window name to include the page title so it's easier to spot
// when debugging (e.g. via xwininfo -tree).
gfx::NativeView content_view = GetContentNativeView();
@@ -281,6 +283,8 @@ WebContents* WebContentsViewGtk::web_contents() {
}
void WebContentsViewGtk::UpdateDragCursor(WebDragOperation operation) {
+ if (!drag_dest_)
+ return;
drag_dest_->UpdateDragStatus(operation);
}
@@ -306,6 +310,15 @@ void WebContentsViewGtk::InsertIntoContentArea(GtkWidget* widget) {
}
void WebContentsViewGtk::UpdateDragDest(RenderViewHost* host) {
+ // Drag-and-drop is entirely managed by BrowserPluginGuest for guest
+ // processes in a largely platform independent way. WebDragDestGtk
+ // will result in spurious messages being sent to the guest process which
+ // will violate assumptions.
+ if (host->GetProcess() && host->GetProcess()->IsGuest()) {
+ DCHECK(!drag_dest_);
+ return;
+ }
+
gfx::NativeView content_view = host->GetView()->GetNativeView();
// If the host is already used by the drag_dest_, there's no point in deleting
diff --git a/chromium/content/browser/web_contents/web_contents_view_gtk.h b/chromium/content/browser/web_contents/web_contents_view_gtk.h
index 4a456fcf0b2..7a8d25e450a 100644
--- a/chromium/content/browser/web_contents/web_contents_view_gtk.h
+++ b/chromium/content/browser/web_contents/web_contents_view_gtk.h
@@ -66,7 +66,7 @@ class CONTENT_EXPORT WebContentsViewGtk
RenderWidgetHost* render_widget_host) OVERRIDE;
virtual RenderWidgetHostView* CreateViewForPopupWidget(
RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual void SetPageTitle(const string16& title) OVERRIDE;
+ virtual void SetPageTitle(const base::string16& title) OVERRIDE;
virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE;
virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE;
virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
@@ -81,11 +81,11 @@ class CONTENT_EXPORT WebContentsViewGtk
bool right_aligned,
bool allow_multiple_selection) OVERRIDE;
virtual void StartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask allowed_ops,
+ blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) OVERRIDE;
- virtual void UpdateDragCursor(WebKit::WebDragOperation operation) OVERRIDE;
+ virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE;
virtual void GotFocus() OVERRIDE;
virtual void TakeFocus(bool reverse) OVERRIDE;
diff --git a/chromium/content/browser/web_contents/web_contents_view_guest.cc b/chromium/content/browser/web_contents/web_contents_view_guest.cc
index a9fc40f1894..cbfb7903da5 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.cc
@@ -7,10 +7,10 @@
#include "build/build_config.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
#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_guest.h"
-#include "content/browser/web_contents/interstitial_page_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/drag_messages.h"
#include "content/public/browser/web_contents_delegate.h"
@@ -25,8 +25,8 @@
#include "ui/aura/window.h"
#endif
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationsMask;
+using blink::WebDragOperation;
+using blink::WebDragOperationsMask;
namespace content {
@@ -106,6 +106,15 @@ void WebContentsViewGuest::SetAllowOverlappingViews(bool overlapping) {
bool WebContentsViewGuest::GetAllowOverlappingViews() const {
return platform_view_->GetAllowOverlappingViews();
}
+
+void WebContentsViewGuest::SetOverlayView(
+ WebContentsView* overlay, const gfx::Point& offset) {
+ platform_view_->SetOverlayView(overlay, offset);
+}
+
+void WebContentsViewGuest::RemoveOverlayView() {
+ platform_view_->RemoveOverlayView();
+}
#endif
void WebContentsViewGuest::CreateView(const gfx::Size& initial_size,
@@ -142,7 +151,7 @@ RenderWidgetHostView* WebContentsViewGuest::CreateViewForPopupWidget(
return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host);
}
-void WebContentsViewGuest::SetPageTitle(const string16& title) {
+void WebContentsViewGuest::SetPageTitle(const base::string16& title) {
}
void WebContentsViewGuest::RenderViewCreated(RenderViewHost* host) {
diff --git a/chromium/content/browser/web_contents/web_contents_view_guest.h b/chromium/content/browser/web_contents/web_contents_view_guest.h
index 81bf8d94693..68fb473d709 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.h
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.h
@@ -56,6 +56,9 @@ class CONTENT_EXPORT WebContentsViewGuest
#if defined(OS_MACOSX)
virtual void SetAllowOverlappingViews(bool overlapping) OVERRIDE;
virtual bool GetAllowOverlappingViews() const OVERRIDE;
+ virtual void SetOverlayView(WebContentsView* overlay,
+ const gfx::Point& offset) OVERRIDE;
+ virtual void RemoveOverlayView() OVERRIDE;
#endif
// WebContentsViewPort implementation ----------------------------------------
@@ -65,7 +68,7 @@ class CONTENT_EXPORT WebContentsViewGuest
RenderWidgetHost* render_widget_host) OVERRIDE;
virtual RenderWidgetHostView* CreateViewForPopupWidget(
RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual void SetPageTitle(const string16& title) OVERRIDE;
+ virtual void SetPageTitle(const base::string16& title) OVERRIDE;
virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE;
virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE;
virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
@@ -84,11 +87,11 @@ class CONTENT_EXPORT WebContentsViewGuest
bool right_aligned,
bool allow_multiple_selection) OVERRIDE;
virtual void StartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask allowed_ops,
+ blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) OVERRIDE;
- virtual void UpdateDragCursor(WebKit::WebDragOperation operation) OVERRIDE;
+ virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE;
virtual void GotFocus() OVERRIDE;
virtual void TakeFocus(bool reverse) OVERRIDE;
diff --git a/chromium/content/browser/web_contents/web_contents_view_mac.h b/chromium/content/browser/web_contents/web_contents_view_mac.h
index a8e7bb33123..0dadbad9ebe 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.h
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.h
@@ -80,6 +80,9 @@ class WebContentsViewMac : public WebContentsViewPort,
virtual gfx::Rect GetViewBounds() const OVERRIDE;
virtual void SetAllowOverlappingViews(bool overlapping) OVERRIDE;
virtual bool GetAllowOverlappingViews() const OVERRIDE;
+ virtual void SetOverlayView(WebContentsView* overlay,
+ const gfx::Point& offset) OVERRIDE;
+ virtual void RemoveOverlayView() OVERRIDE;
// WebContentsViewPort implementation ----------------------------------------
virtual void CreateView(
@@ -88,7 +91,7 @@ class WebContentsViewMac : public WebContentsViewPort,
RenderWidgetHost* render_widget_host) OVERRIDE;
virtual RenderWidgetHostView* CreateViewForPopupWidget(
RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual void SetPageTitle(const string16& title) OVERRIDE;
+ virtual void SetPageTitle(const base::string16& title) OVERRIDE;
virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE;
virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE;
virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
@@ -105,11 +108,11 @@ class WebContentsViewMac : public WebContentsViewPort,
bool right_aligned,
bool allow_multiple_selection) OVERRIDE;
virtual void StartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask allowed_operations,
+ blink::WebDragOperationsMask allowed_operations,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) OVERRIDE;
- virtual void UpdateDragCursor(WebKit::WebDragOperation operation) OVERRIDE;
+ virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE;
virtual void GotFocus() OVERRIDE;
virtual void TakeFocus(bool reverse) OVERRIDE;
@@ -121,6 +124,9 @@ class WebContentsViewMac : public WebContentsViewPort,
WebContentsViewDelegate* delegate() { return delegate_.get(); }
private:
+ // Updates overlay view on current RenderWidgetHostView.
+ void UpdateRenderWidgetHostViewOverlay();
+
// The WebContentsImpl whose contents we display.
WebContentsImpl* web_contents_;
@@ -137,6 +143,17 @@ class WebContentsViewMac : public WebContentsViewPort,
// Whether to allow overlapping views.
bool allow_overlapping_views_;
+ // The overlay view which is rendered above this one.
+ // Overlay view has |underlay_view_| set to this view.
+ WebContentsViewMac* overlay_view_;
+
+ // The offset of overlay view relative to this view.
+ gfx::Point overlay_view_offset_;
+
+ // The underlay view which this view is rendered above.
+ // Underlay view has |overlay_view_| set to this view.
+ WebContentsViewMac* underlay_view_;
+
DISALLOW_COPY_AND_ASSIGN(WebContentsViewMac);
};
diff --git a/chromium/content/browser/web_contents/web_contents_view_mac.mm b/chromium/content/browser/web_contents/web_contents_view_mac.mm
index d1ab628b33e..527ebc024d8 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -28,8 +28,8 @@
#include "ui/base/dragdrop/cocoa_dnd_util.h"
#include "ui/gfx/image/image_skia_util_mac.h"
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationsMask;
+using blink::WebDragOperation;
+using blink::WebDragOperationsMask;
using content::DropData;
using content::PopupMenuHelper;
using content::RenderViewHostFactory;
@@ -39,10 +39,10 @@ using content::WebContents;
using content::WebContentsImpl;
using content::WebContentsViewMac;
-// Ensure that the WebKit::WebDragOperation enum values stay in sync with
+// Ensure that the blink::WebDragOperation enum values stay in sync with
// NSDragOperation constants, since the code below static_casts between 'em.
#define COMPILE_ASSERT_MATCHING_ENUM(name) \
- COMPILE_ASSERT(int(NS##name) == int(WebKit::Web##name), enum_mismatch_##name)
+ COMPILE_ASSERT(int(NS##name) == int(blink::Web##name), enum_mismatch_##name)
COMPILE_ASSERT_MATCHING_ENUM(DragOperationNone);
COMPILE_ASSERT_MATCHING_ENUM(DragOperationCopy);
COMPILE_ASSERT_MATCHING_ENUM(DragOperationLink);
@@ -81,7 +81,9 @@ WebContentsViewMac::WebContentsViewMac(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate)
: web_contents_(web_contents),
delegate_(delegate),
- allow_overlapping_views_(false) {
+ allow_overlapping_views_(false),
+ overlay_view_(NULL),
+ underlay_view_(NULL) {
}
WebContentsViewMac::~WebContentsViewMac() {
@@ -277,6 +279,54 @@ bool WebContentsViewMac::GetAllowOverlappingViews() const {
return allow_overlapping_views_;
}
+void WebContentsViewMac::SetOverlayView(
+ WebContentsView* overlay, const gfx::Point& offset) {
+ DCHECK(!underlay_view_);
+ if (overlay_view_)
+ RemoveOverlayView();
+
+ overlay_view_ = static_cast<WebContentsViewMac*>(overlay);
+ DCHECK(!overlay_view_->overlay_view_);
+ overlay_view_->underlay_view_ = this;
+ overlay_view_offset_ = offset;
+ UpdateRenderWidgetHostViewOverlay();
+}
+
+void WebContentsViewMac::RemoveOverlayView() {
+ DCHECK(overlay_view_);
+
+ RenderWidgetHostViewMac* rwhv = static_cast<RenderWidgetHostViewMac*>(
+ web_contents_->GetRenderWidgetHostView());
+ if (rwhv)
+ rwhv->RemoveOverlayView();
+
+ overlay_view_->underlay_view_ = NULL;
+ overlay_view_ = NULL;
+}
+
+void WebContentsViewMac::UpdateRenderWidgetHostViewOverlay() {
+ RenderWidgetHostViewMac* rwhv = static_cast<RenderWidgetHostViewMac*>(
+ web_contents_->GetRenderWidgetHostView());
+ if (!rwhv)
+ return;
+
+ if (overlay_view_) {
+ RenderWidgetHostViewMac* overlay_rwhv =
+ static_cast<RenderWidgetHostViewMac*>(
+ overlay_view_->web_contents_->GetRenderWidgetHostView());
+ if (overlay_rwhv)
+ rwhv->SetOverlayView(overlay_rwhv, overlay_view_offset_);
+ }
+
+ if (underlay_view_) {
+ RenderWidgetHostViewMac* underlay_rwhv =
+ static_cast<RenderWidgetHostViewMac*>(
+ underlay_view_->web_contents_->GetRenderWidgetHostView());
+ if (underlay_rwhv)
+ underlay_rwhv->SetOverlayView(rwhv, underlay_view_->overlay_view_offset_);
+ }
+}
+
void WebContentsViewMac::CreateView(
const gfx::Size& initial_size, gfx::NativeView context) {
WebContentsViewCocoa* view =
@@ -332,7 +382,7 @@ RenderWidgetHostView* WebContentsViewMac::CreateViewForPopupWidget(
return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host);
}
-void WebContentsViewMac::SetPageTitle(const string16& title) {
+void WebContentsViewMac::SetPageTitle(const base::string16& title) {
// Meaningless on the Mac; widgets don't have a "title" attribute
}
@@ -345,6 +395,7 @@ void WebContentsViewMac::RenderViewCreated(RenderViewHost* host) {
}
void WebContentsViewMac::RenderViewSwappedIn(RenderViewHost* host) {
+ UpdateRenderWidgetHostViewOverlay();
}
void WebContentsViewMac::SetOverscrollControllerEnabled(bool enabled) {
diff --git a/chromium/content/browser/web_contents/web_contents_view_win.cc b/chromium/content/browser/web_contents/web_contents_view_win.cc
index 0c65b1dc181..8360d8c5f59 100644
--- a/chromium/content/browser/web_contents/web_contents_view_win.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_win.cc
@@ -6,10 +6,10 @@
#include "base/bind.h"
#include "base/memory/scoped_vector.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
#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_win.h"
-#include "content/browser/web_contents/interstitial_page_impl.h"
#include "content/browser/web_contents/web_contents_drag_win.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_drag_dest_win.h"
@@ -228,7 +228,7 @@ RenderWidgetHostView* WebContentsViewWin::CreateViewForPopupWidget(
return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host);
}
-void WebContentsViewWin::SetPageTitle(const string16& title) {
+void WebContentsViewWin::SetPageTitle(const base::string16& title) {
// It's possible to get this after the hwnd has been destroyed.
if (GetNativeView())
::SetWindowText(GetNativeView(), title.c_str());
@@ -261,7 +261,7 @@ void WebContentsViewWin::ShowPopupMenu(const gfx::Rect& bounds,
}
void WebContentsViewWin::StartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask operations,
+ blink::WebDragOperationsMask operations,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) {
@@ -273,7 +273,7 @@ void WebContentsViewWin::StartDragging(const DropData& drop_data,
drag_handler_->StartDragging(drop_data, operations, image, image_offset);
}
-void WebContentsViewWin::UpdateDragCursor(WebKit::WebDragOperation operation) {
+void WebContentsViewWin::UpdateDragCursor(blink::WebDragOperation operation) {
drag_dest_->set_drag_cursor(operation);
}
diff --git a/chromium/content/browser/web_contents/web_contents_view_win.h b/chromium/content/browser/web_contents/web_contents_view_win.h
index adfe6751fad..9b052e20a2b 100644
--- a/chromium/content/browser/web_contents/web_contents_view_win.h
+++ b/chromium/content/browser/web_contents/web_contents_view_win.h
@@ -73,7 +73,7 @@ class CONTENT_EXPORT WebContentsViewWin
RenderWidgetHost* render_widget_host) OVERRIDE;
virtual RenderWidgetHostView* CreateViewForPopupWidget(
RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual void SetPageTitle(const string16& title) OVERRIDE;
+ virtual void SetPageTitle(const base::string16& title) OVERRIDE;
virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE;
virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE;
virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
@@ -88,11 +88,11 @@ class CONTENT_EXPORT WebContentsViewWin
bool right_aligned,
bool allow_multiple_selection) OVERRIDE;
virtual void StartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask operations,
+ blink::WebDragOperationsMask operations,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) OVERRIDE;
- virtual void UpdateDragCursor(WebKit::WebDragOperation operation) OVERRIDE;
+ virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE;
virtual void GotFocus() OVERRIDE;
virtual void TakeFocus(bool reverse) OVERRIDE;
diff --git a/chromium/content/browser/web_contents/web_drag_dest_gtk.cc b/chromium/content/browser/web_contents/web_drag_dest_gtk.cc
index 55f0d9c04a2..738d6b59a80 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_gtk.cc
+++ b/chromium/content/browser/web_contents/web_drag_dest_gtk.cc
@@ -22,8 +22,8 @@
#include "ui/base/dragdrop/gtk_dnd_util.h"
#include "ui/base/gtk/gtk_screen_util.h"
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationNone;
+using blink::WebDragOperation;
+using blink::WebDragOperationNone;
namespace content {
@@ -36,13 +36,13 @@ int GetModifierFlags(GtkWidget* widget) {
gdk_window_get_pointer(gtk_widget_get_window(widget), NULL, NULL, &state);
if (state & GDK_SHIFT_MASK)
- modifier_state |= WebKit::WebInputEvent::ShiftKey;
+ modifier_state |= blink::WebInputEvent::ShiftKey;
if (state & GDK_CONTROL_MASK)
- modifier_state |= WebKit::WebInputEvent::ControlKey;
+ modifier_state |= blink::WebInputEvent::ControlKey;
if (state & GDK_MOD1_MASK)
- modifier_state |= WebKit::WebInputEvent::AltKey;
+ modifier_state |= blink::WebInputEvent::AltKey;
if (state & GDK_META_MASK)
- modifier_state |= WebKit::WebInputEvent::MetaKey;
+ modifier_state |= blink::WebInputEvent::MetaKey;
return modifier_state;
}
@@ -204,7 +204,8 @@ void WebDragDestGtk::OnDragDataReceived(
if (url.SchemeIs(chrome::kFileScheme) &&
net::FileURLToFilePath(url, &file_path)) {
drop_data_->filenames.push_back(
- DropData::FileInfo(UTF8ToUTF16(file_path.value()), string16()));
+ DropData::FileInfo(UTF8ToUTF16(file_path.value()),
+ base::string16()));
// This is a hack. Some file managers also populate text/plain with
// a file URL when dragging files, so we clear it to avoid exposing
// it to the web content.
diff --git a/chromium/content/browser/web_contents/web_drag_dest_gtk.h b/chromium/content/browser/web_contents/web_drag_dest_gtk.h
index b912afa9d3c..7258e1bc43c 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_gtk.h
+++ b/chromium/content/browser/web_contents/web_drag_dest_gtk.h
@@ -32,7 +32,7 @@ class CONTENT_EXPORT WebDragDestGtk {
// This is called when the renderer responds to a drag motion event. We must
// update the system drag cursor.
- void UpdateDragStatus(WebKit::WebDragOperation operation);
+ void UpdateDragStatus(blink::WebDragOperation operation);
// Informs the renderer when a system drag has left the render view.
// See OnDragLeave().
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 8a529e838fd..8768bed657b 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_dest_mac.mm
@@ -18,7 +18,7 @@
#import "ui/base/dragdrop/cocoa_dnd_util.h"
#include "ui/base/window_open_disposition.h"
-using WebKit::WebDragOperationsMask;
+using blink::WebDragOperationsMask;
using content::DropData;
using content::OpenURLParams;
using content::Referrer;
@@ -28,13 +28,13 @@ int GetModifierFlags() {
int modifier_state = 0;
UInt32 currentModifiers = GetCurrentKeyModifiers();
if (currentModifiers & ::shiftKey)
- modifier_state |= WebKit::WebInputEvent::ShiftKey;
+ modifier_state |= blink::WebInputEvent::ShiftKey;
if (currentModifiers & ::controlKey)
- modifier_state |= WebKit::WebInputEvent::ControlKey;
+ modifier_state |= blink::WebInputEvent::ControlKey;
if (currentModifiers & ::optionKey)
- modifier_state |= WebKit::WebInputEvent::AltKey;
+ modifier_state |= blink::WebInputEvent::AltKey;
if (currentModifiers & ::cmdKey)
- modifier_state |= WebKit::WebInputEvent::MetaKey;
+ modifier_state |= blink::WebInputEvent::MetaKey;
return modifier_state;
}
@@ -290,7 +290,7 @@ int GetModifierFlags() {
if (exists) {
data->filenames.push_back(
DropData::FileInfo(
- base::SysNSStringToUTF16(filename), string16()));
+ base::SysNSStringToUTF16(filename), base::string16()));
}
}
}
diff --git a/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm b/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm
index 48719de7b75..a7dcedecb03 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm
+++ b/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm
@@ -6,9 +6,9 @@
#import "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "content/browser/renderer_host/test_render_view_host.h"
#import "content/browser/web_contents/web_drag_dest_mac.h"
#include "content/public/common/drop_data.h"
+#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
@@ -85,7 +85,7 @@ TEST_F(WebDragDestTest, URL) {
NSString* url = nil;
NSString* title = nil;
GURL result_url;
- string16 result_title;
+ base::string16 result_title;
// Put a URL on the pasteboard and check it.
pboard = [NSPasteboard pasteboardWithUniqueName];
diff --git a/chromium/content/browser/web_contents/web_drag_dest_win.cc b/chromium/content/browser/web_contents/web_drag_dest_win.cc
index 60f0c0593a9..e497f860d65 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_win.cc
+++ b/chromium/content/browser/web_contents/web_drag_dest_win.cc
@@ -23,11 +23,11 @@
#include "ui/gfx/point.h"
#include "url/gurl.h"
-using WebKit::WebDragOperationNone;
-using WebKit::WebDragOperationCopy;
-using WebKit::WebDragOperationLink;
-using WebKit::WebDragOperationMove;
-using WebKit::WebDragOperationGeneric;
+using blink::WebDragOperationNone;
+using blink::WebDragOperationCopy;
+using blink::WebDragOperationLink;
+using blink::WebDragOperationMove;
+using blink::WebDragOperationGeneric;
namespace content {
namespace {
@@ -48,15 +48,15 @@ DWORD GetPreferredDropEffect(DWORD effect) {
int GetModifierFlags() {
int modifier_state = 0;
if (base::win::IsShiftPressed())
- modifier_state |= WebKit::WebInputEvent::ShiftKey;
+ modifier_state |= blink::WebInputEvent::ShiftKey;
if (base::win::IsCtrlPressed())
- modifier_state |= WebKit::WebInputEvent::ControlKey;
+ modifier_state |= blink::WebInputEvent::ControlKey;
if (base::win::IsAltPressed())
- modifier_state |= WebKit::WebInputEvent::AltKey;
+ modifier_state |= blink::WebInputEvent::AltKey;
if (::GetKeyState(VK_LWIN) & kHighBitMaskShort)
- modifier_state |= WebKit::WebInputEvent::MetaKey;
+ modifier_state |= blink::WebInputEvent::MetaKey;
if (::GetKeyState(VK_RWIN) & kHighBitMaskShort)
- modifier_state |= WebKit::WebInputEvent::MetaKey;
+ modifier_state |= blink::WebInputEvent::MetaKey;
return modifier_state;
}
diff --git a/chromium/content/browser/web_contents/web_drag_dest_win.h b/chromium/content/browser/web_contents/web_drag_dest_win.h
index 5ddb7edc2c8..9e3ca8daa2e 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_win.h
+++ b/chromium/content/browser/web_contents/web_drag_dest_win.h
@@ -29,7 +29,7 @@ class CONTENT_EXPORT WebDragDest : public ui::DropTargetWin {
DropData* current_drop_data() const { return drop_data_.get(); }
- void set_drag_cursor(WebKit::WebDragOperation op) {
+ void set_drag_cursor(blink::WebDragOperation op) {
drag_cursor_ = op;
}
@@ -66,7 +66,7 @@ class CONTENT_EXPORT WebDragDest : public ui::DropTargetWin {
// Used to determine what cursor we should display when dragging over web
// content area. This can be updated async during a drag operation.
- WebKit::WebDragOperation drag_cursor_;
+ blink::WebDragOperation drag_cursor_;
// A special drop target handler for when we try to d&d while an interstitial
// page is showing.
diff --git a/chromium/content/browser/web_contents/web_drag_source_gtk.cc b/chromium/content/browser/web_contents/web_drag_source_gtk.cc
index 0ad27de95c8..2f9e58707f9 100644
--- a/chromium/content/browser/web_contents/web_drag_source_gtk.cc
+++ b/chromium/content/browser/web_contents/web_drag_source_gtk.cc
@@ -28,9 +28,9 @@
#include "ui/gfx/gtk_compat.h"
#include "ui/gfx/gtk_util.h"
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationsMask;
-using WebKit::WebDragOperationNone;
+using blink::WebDragOperation;
+using blink::WebDragOperationsMask;
+using blink::WebDragOperationNone;
namespace content {
diff --git a/chromium/content/browser/web_contents/web_drag_source_gtk.h b/chromium/content/browser/web_contents/web_drag_source_gtk.h
index bcf9a01725a..8a7c7b28a9c 100644
--- a/chromium/content/browser/web_contents/web_drag_source_gtk.h
+++ b/chromium/content/browser/web_contents/web_drag_source_gtk.h
@@ -39,7 +39,7 @@ class CONTENT_EXPORT WebDragSourceGtk :
// Starts a drag for the WebContents this WebDragSourceGtk was created for.
// Returns false if the drag could not be started.
bool StartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask allowed_ops,
+ blink::WebDragOperationsMask allowed_ops,
GdkEventButton* last_mouse_down,
const SkBitmap& image,
const gfx::Vector2d& image_offset);
@@ -92,7 +92,7 @@ class CONTENT_EXPORT WebDragSourceGtk :
GdkDragContext* drag_context_;
// The file mime type for a drag-out download.
- string16 wide_download_mime_type_;
+ base::string16 wide_download_mime_type_;
// The file name to be saved to for a drag-out download.
base::FilePath download_file_name_;
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac.mm b/chromium/content/browser/web_contents/web_drag_source_mac.mm
index 041737935e9..c66732050c9 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_source_mac.mm
@@ -49,10 +49,10 @@ namespace {
// |NSURLPboardType|.
NSString* const kNSURLTitlePboardType = @"public.url-name";
-// Converts a string16 into a FilePath. Use this method instead of
+// Converts a base::string16 into a FilePath. Use this method instead of
// -[NSString fileSystemRepresentation] to prevent exceptions from being thrown.
// See http://crbug.com/78782 for more info.
-base::FilePath FilePathFromFilename(const string16& filename) {
+base::FilePath FilePathFromFilename(const base::string16& filename) {
NSString* str = SysUTF16ToNSString(filename);
char buf[MAXPATHLEN];
if (![str getFileSystemRepresentation:buf maxLength:sizeof(buf)])
@@ -71,7 +71,7 @@ base::FilePath GetFileNameFromDragData(const DropData& drop_data) {
// synthesize one from the provided extension and URL.
if (file_name.empty()) {
// Retrieve the name from the URL.
- string16 suggested_filename =
+ base::string16 suggested_filename =
net::GetSuggestedFilename(drop_data.url, "", "", "", "", "");
const std::string extension = file_name.Extension();
file_name = FilePathFromFilename(suggested_filename);
@@ -147,7 +147,7 @@ void PromiseWriterHelper(const DropData& drop_data,
- (void)lazyWriteToPasteboard:(NSPasteboard*)pboard forType:(NSString*)type {
// NSHTMLPboardType requires the character set to be declared. Otherwise, it
// assumes US-ASCII. Awesome.
- const string16 kHtmlHeader = ASCIIToUTF16(
+ const base::string16 kHtmlHeader = ASCIIToUTF16(
"<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">");
// Be extra paranoid; avoid crashing.
@@ -285,7 +285,7 @@ void PromiseWriterHelper(const DropData& drop_data,
operation &= ~NSDragOperationMove;
contents_->DragSourceEndedAt(localPoint.x, localPoint.y, screenPoint.x,
- screenPoint.y, static_cast<WebKit::WebDragOperation>(operation));
+ screenPoint.y, static_cast<blink::WebDragOperation>(operation));
}
// Make sure the pasteboard owner isn't us.
@@ -386,7 +386,7 @@ void PromiseWriterHelper(const DropData& drop_data,
downloadFileName_ = GetFileNameFromDragData(*dropData_);
net::GetMimeTypeFromExtension(downloadFileName_.Extension(), &mimeType);
} else {
- string16 mimeType16;
+ base::string16 mimeType16;
base::FilePath fileName;
if (content::ParseDownloadMetadata(
dropData_->download_metadata,
diff --git a/chromium/content/browser/web_contents/web_drag_source_win.cc b/chromium/content/browser/web_contents/web_drag_source_win.cc
index 53df4e81725..6697d73ac2e 100644
--- a/chromium/content/browser/web_contents/web_drag_source_win.cc
+++ b/chromium/content/browser/web_contents/web_drag_source_win.cc
@@ -13,7 +13,7 @@
#include "content/public/browser/notification_types.h"
#include "ui/base/dragdrop/os_exchange_data.h"
-using WebKit::WebDragOperationNone;
+using blink::WebDragOperationNone;
namespace content {
namespace {
@@ -39,7 +39,7 @@ WebDragSource::WebDragSource(gfx::NativeWindow source_wnd,
web_contents_(static_cast<WebContentsImpl*>(web_contents)),
effect_(DROPEFFECT_NONE),
data_(NULL) {
- registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_SWAPPED,
+ registrar_.Add(this, NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
Source<WebContents>(web_contents));
registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
Source<WebContents>(web_contents));
@@ -114,7 +114,7 @@ void WebDragSource::OnDragSourceMove() {
void WebDragSource::Observe(int type,
const NotificationSource& source,
const NotificationDetails& details) {
- if (type == NOTIFICATION_WEB_CONTENTS_SWAPPED) {
+ if (type == NOTIFICATION_RENDER_VIEW_HOST_CHANGED) {
// When the WebContents get swapped, our render view host goes away.
// That's OK, we can continue the drag, we just can't send messages back to
// our drag source.
diff --git a/chromium/content/browser/web_contents/web_drag_utils_win.cc b/chromium/content/browser/web_contents/web_drag_utils_win.cc
index bada2456f86..8558c826a21 100644
--- a/chromium/content/browser/web_contents/web_drag_utils_win.cc
+++ b/chromium/content/browser/web_contents/web_drag_utils_win.cc
@@ -7,13 +7,13 @@
#include <oleidl.h>
#include "base/logging.h"
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationsMask;
-using WebKit::WebDragOperationNone;
-using WebKit::WebDragOperationCopy;
-using WebKit::WebDragOperationLink;
-using WebKit::WebDragOperationMove;
-using WebKit::WebDragOperationGeneric;
+using blink::WebDragOperation;
+using blink::WebDragOperationsMask;
+using blink::WebDragOperationNone;
+using blink::WebDragOperationCopy;
+using blink::WebDragOperationLink;
+using blink::WebDragOperationMove;
+using blink::WebDragOperationGeneric;
namespace content {
diff --git a/chromium/content/browser/web_contents/web_drag_utils_win.h b/chromium/content/browser/web_contents/web_drag_utils_win.h
index 8721da94511..d45cb8e28d2 100644
--- a/chromium/content/browser/web_contents/web_drag_utils_win.h
+++ b/chromium/content/browser/web_contents/web_drag_utils_win.h
@@ -11,11 +11,11 @@
namespace content {
-WebKit::WebDragOperation WinDragOpToWebDragOp(DWORD effect);
-WebKit::WebDragOperationsMask WinDragOpMaskToWebDragOpMask(DWORD effects);
+blink::WebDragOperation WinDragOpToWebDragOp(DWORD effect);
+blink::WebDragOperationsMask WinDragOpMaskToWebDragOpMask(DWORD effects);
-DWORD WebDragOpToWinDragOp(WebKit::WebDragOperation op);
-DWORD WebDragOpMaskToWinDragOpMask(WebKit::WebDragOperationsMask ops);
+DWORD WebDragOpToWinDragOp(blink::WebDragOperation op);
+DWORD WebDragOpMaskToWinDragOpMask(blink::WebDragOperationsMask ops);
} // namespace content
diff --git a/chromium/content/browser/webui/url_data_manager_backend.cc b/chromium/content/browser/webui/url_data_manager_backend.cc
index 1bcbdb76e9e..1e378007502 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend.cc
@@ -17,6 +17,7 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/histogram_internals_request_job.h"
#include "content/browser/net/view_blob_internals_job_factory.h"
@@ -147,6 +148,10 @@ class URLRequestChromeJob : public net::URLRequestJob,
deny_xframe_options_ = deny_xframe_options;
}
+ void set_send_content_type_header(bool send_content_type_header) {
+ send_content_type_header_ = send_content_type_header;
+ }
+
// Returns true when job was generated from an incognito profile.
bool is_incognito() const {
return is_incognito_;
@@ -188,6 +193,9 @@ class URLRequestChromeJob : public net::URLRequestJob,
// If true, sets the "X-Frame-Options: DENY" header.
bool deny_xframe_options_;
+ // If true, sets the "Content-Type: <mime-type>" header.
+ bool send_content_type_header_;
+
// True when job is generated from an incognito profile.
const bool is_incognito_;
@@ -211,6 +219,7 @@ URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request,
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),
backend_(backend),
weak_factory_(this) {
@@ -267,6 +276,13 @@ void URLRequestChromeJob::GetResponseInfo(net::HttpResponseInfo* info) {
if (!allow_caching_)
info->headers->AddHeader("Cache-Control: no-cache");
+
+ if (send_content_type_header_ && !mime_type_.empty()) {
+ std::string content_type =
+ base::StringPrintf("%s:%s", net::HttpRequestHeaders::kContentType,
+ mime_type_.c_str());
+ info->headers->AddHeader(content_type);
+ }
}
void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) {
@@ -511,6 +527,8 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
source->source()->GetContentSecurityPolicyFrameSrc());
job->set_deny_xframe_options(
source->source()->ShouldDenyXFrameOptions());
+ job->set_send_content_type_header(
+ source->source()->ShouldServeMimeTypeAsContentTypeHeader());
// Look up additional request info to pass down.
int render_process_id = -1;
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 9d0d17128a6..6775eb739da 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.cc
@@ -10,8 +10,8 @@
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_util.h"
#include "content/public/common/content_client.h"
-#include "ui/webui/jstemplate_builder.h"
-#include "ui/webui/web_ui_util.h"
+#include "ui/base/webui/jstemplate_builder.h"
+#include "ui/base/webui/web_ui_util.h"
namespace content {
@@ -52,6 +52,9 @@ class WebUIDataSourceImpl::InternalDataSource : public URLDataSource {
virtual bool ShouldReplaceExistingSource() const OVERRIDE {
return parent_->replace_existing_source_;
}
+ virtual bool AllowCaching() const OVERRIDE {
+ return false;
+ }
virtual bool ShouldAddContentSecurityPolicy() const OVERRIDE {
return parent_->add_csp_;
}
@@ -92,7 +95,7 @@ WebUIDataSourceImpl::~WebUIDataSourceImpl() {
}
void WebUIDataSourceImpl::AddString(const std::string& name,
- const string16& value) {
+ const base::string16& value) {
localized_strings_.SetString(name, value);
}
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 1f8100469e7..91ec087cfc0 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.h
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.h
@@ -28,7 +28,7 @@ class CONTENT_EXPORT WebUIDataSourceImpl
public:
// WebUIDataSource implementation:
virtual void AddString(const std::string& name,
- const string16& value) OVERRIDE;
+ const base::string16& value) OVERRIDE;
virtual void AddString(const std::string& name,
const std::string& value) OVERRIDE;
virtual void AddLocalizedString(const std::string& name, int ids) OVERRIDE;
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 f384a43e94a..a5da7eb8211 100644
--- a/chromium/content/browser/webui/web_ui_data_source_unittest.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_unittest.cc
@@ -25,10 +25,10 @@ class TestClient : public TestContentClient {
TestClient() {}
virtual ~TestClient() {}
- virtual string16 GetLocalizedString(int message_id) const OVERRIDE {
+ virtual base::string16 GetLocalizedString(int message_id) const OVERRIDE {
if (message_id == kDummyStringId)
return UTF8ToUTF16(kDummyString);
- return string16();
+ return base::string16();
}
diff --git a/chromium/content/browser/webui/web_ui_impl.cc b/chromium/content/browser/webui/web_ui_impl.cc
index e54a6d8c27d..4774e4f17ac 100644
--- a/chromium/content/browser/webui/web_ui_impl.cc
+++ b/chromium/content/browser/webui/web_ui_impl.cc
@@ -27,10 +27,10 @@ namespace content {
const WebUI::TypeID WebUI::kNoWebUI = NULL;
// static
-string16 WebUI::GetJavascriptCall(
+base::string16 WebUI::GetJavascriptCall(
const std::string& function_name,
const std::vector<const Value*>& arg_list) {
- string16 parameters;
+ base::string16 parameters;
std::string json;
for (size_t i = 0; i < arg_list.size(); ++i) {
if (i > 0)
@@ -106,11 +106,11 @@ ui::ScaleFactor WebUIImpl::GetDeviceScaleFactor() const {
return GetScaleFactorForView(web_contents_->GetRenderWidgetHostView());
}
-const string16& WebUIImpl::GetOverriddenTitle() const {
+const base::string16& WebUIImpl::GetOverriddenTitle() const {
return overridden_title_;
}
-void WebUIImpl::OverrideTitle(const string16& title) {
+void WebUIImpl::OverrideTitle(const base::string16& title) {
overridden_title_ = title;
}
@@ -144,7 +144,7 @@ void WebUIImpl::SetController(WebUIController* controller) {
void WebUIImpl::CallJavascriptFunction(const std::string& function_name) {
DCHECK(IsStringASCII(function_name));
- string16 javascript = ASCIIToUTF16(function_name + "();");
+ base::string16 javascript = ASCIIToUTF16(function_name + "();");
ExecuteJavascript(javascript);
}
@@ -230,7 +230,7 @@ void WebUIImpl::AddMessageHandler(WebUIMessageHandler* handler) {
handlers_.push_back(handler);
}
-void WebUIImpl::ExecuteJavascript(const string16& javascript) {
+void WebUIImpl::ExecuteJavascript(const base::string16& javascript) {
static_cast<RenderViewHostImpl*>(
web_contents_->GetRenderViewHost())->ExecuteJavascriptInWebFrame(
ASCIIToUTF16(frame_xpath_), javascript);
diff --git a/chromium/content/browser/webui/web_ui_impl.h b/chromium/content/browser/webui/web_ui_impl.h
index de3059fcd49..8715e43e226 100644
--- a/chromium/content/browser/webui/web_ui_impl.h
+++ b/chromium/content/browser/webui/web_ui_impl.h
@@ -25,7 +25,7 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
// Called by WebContentsImpl when the RenderView is first created. This is
// *not* called for every page load because in some cases
- // RenderViewHostManager will reuse RenderView instances.
+ // RenderFrameHostManager will reuse RenderView instances.
void RenderViewCreated(RenderViewHost* render_view_host);
// WebUI implementation:
@@ -33,8 +33,8 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
virtual WebUIController* GetController() const OVERRIDE;
virtual void SetController(WebUIController* controller) OVERRIDE;
virtual ui::ScaleFactor GetDeviceScaleFactor() const OVERRIDE;
- virtual const string16& GetOverriddenTitle() const OVERRIDE;
- virtual void OverrideTitle(const string16& title) OVERRIDE;
+ virtual const base::string16& GetOverriddenTitle() const OVERRIDE;
+ virtual void OverrideTitle(const base::string16& title) OVERRIDE;
virtual PageTransition GetLinkTransitionType() const OVERRIDE;
virtual void SetLinkTransitionType(PageTransition type) OVERRIDE;
virtual int GetBindings() const OVERRIDE;
@@ -78,7 +78,7 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
const base::ListValue& args);
// Execute a string of raw Javascript on the page.
- void ExecuteJavascript(const string16& javascript);
+ void ExecuteJavascript(const base::string16& javascript);
// A map of message name -> message handling callback.
typedef std::map<std::string, MessageCallback> MessageCallbackMap;
@@ -86,7 +86,7 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
// Options that may be overridden by individual Web UI implementations. The
// bool options default to false. See the public getters for more information.
- string16 overridden_title_; // Defaults to empty string.
+ base::string16 overridden_title_; // Defaults to empty string.
PageTransition link_transition_type_; // Defaults to LINK.
int bindings_; // The bindings from BindingsPolicy that should be enabled for
// this page.
diff --git a/chromium/content/browser/webui/web_ui_message_handler.cc b/chromium/content/browser/webui/web_ui_message_handler.cc
index db554c0ed85..57b2c46b86d 100644
--- a/chromium/content/browser/webui/web_ui_message_handler.cc
+++ b/chromium/content/browser/webui/web_ui_message_handler.cc
@@ -36,12 +36,12 @@ bool WebUIMessageHandler::ExtractDoubleValue(const ListValue* value,
return false;
}
-string16 WebUIMessageHandler::ExtractStringValue(const ListValue* value) {
- string16 string16_value;
+base::string16 WebUIMessageHandler::ExtractStringValue(const ListValue* value) {
+ base::string16 string16_value;
if (value->GetString(0, &string16_value))
return string16_value;
NOTREACHED();
- return string16();
+ return base::string16();
}
} // 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 e38acd7e311..33cdb61fb11 100644
--- a/chromium/content/browser/webui/web_ui_message_handler_unittest.cc
+++ b/chromium/content/browser/webui/web_ui_message_handler_unittest.cc
@@ -14,9 +14,9 @@ namespace content {
TEST(WebUIMessageHandlerTest, ExtractIntegerValue) {
ListValue list;
int value, zero_value = 0, neg_value = -1234, pos_value = 1234;
- string16 zero_string(UTF8ToUTF16("0"));
- string16 neg_string(UTF8ToUTF16("-1234"));
- string16 pos_string(UTF8ToUTF16("1234"));
+ base::string16 zero_string(UTF8ToUTF16("0"));
+ base::string16 neg_string(UTF8ToUTF16("-1234"));
+ base::string16 pos_string(UTF8ToUTF16("1234"));
list.Append(new base::FundamentalValue(zero_value));
EXPECT_TRUE(WebUIMessageHandler::ExtractIntegerValue(&list, &value));
@@ -51,9 +51,9 @@ TEST(WebUIMessageHandlerTest, ExtractIntegerValue) {
TEST(WebUIMessageHandlerTest, ExtractDoubleValue) {
base::ListValue list;
double value, zero_value = 0.0, neg_value = -1234.5, pos_value = 1234.5;
- string16 zero_string(UTF8ToUTF16("0"));
- string16 neg_string(UTF8ToUTF16("-1234.5"));
- string16 pos_string(UTF8ToUTF16("1234.5"));
+ base::string16 zero_string(UTF8ToUTF16("0"));
+ base::string16 neg_string(UTF8ToUTF16("-1234.5"));
+ base::string16 pos_string(UTF8ToUTF16("1234.5"));
list.Append(new base::FundamentalValue(zero_value));
EXPECT_TRUE(WebUIMessageHandler::ExtractDoubleValue(&list, &value));
@@ -87,10 +87,10 @@ TEST(WebUIMessageHandlerTest, ExtractDoubleValue) {
TEST(WebUIMessageHandlerTest, ExtractStringValue) {
base::ListValue list;
- string16 in_string(UTF8ToUTF16(
+ base::string16 in_string(UTF8ToUTF16(
"The facts, though interesting, are irrelevant."));
list.Append(new base::StringValue(in_string));
- string16 out_string = WebUIMessageHandler::ExtractStringValue(&list);
+ base::string16 out_string = WebUIMessageHandler::ExtractStringValue(&list);
EXPECT_EQ(in_string, out_string);
}
diff --git a/chromium/content/browser/worker_host/worker_message_filter.cc b/chromium/content/browser/worker_host/worker_message_filter.cc
index faedbdce08b..49fe7f6f3e8 100644
--- a/chromium/content/browser/worker_host/worker_message_filter.cc
+++ b/chromium/content/browser/worker_host/worker_message_filter.cc
@@ -4,7 +4,7 @@
#include "content/browser/worker_host/worker_message_filter.h"
-#include "content/browser/worker_host/message_port_service.h"
+#include "content/browser/message_port_message_filter.h"
#include "content/browser/worker_host/worker_service_impl.h"
#include "content/common/view_messages.h"
#include "content/common/worker_messages.h"
@@ -16,11 +16,11 @@ WorkerMessageFilter::WorkerMessageFilter(
int render_process_id,
ResourceContext* resource_context,
const WorkerStoragePartition& partition,
- const NextRoutingIDCallback& callback)
+ MessagePortMessageFilter* message_port_message_filter)
: render_process_id_(render_process_id),
resource_context_(resource_context),
partition_(partition),
- next_routing_id_(callback) {
+ message_port_message_filter_(message_port_message_filter) {
// Note: This constructor is called on both IO or UI thread.
DCHECK(resource_context);
}
@@ -30,9 +30,6 @@ WorkerMessageFilter::~WorkerMessageFilter() {
}
void WorkerMessageFilter::OnChannelClosing() {
- BrowserMessageFilter::OnChannelClosing();
-
- MessagePortService::GetInstance()->OnWorkerMessageFilterClosing(this);
WorkerServiceImpl::GetInstance()->OnWorkerMessageFilterClosing(this);
}
@@ -48,24 +45,6 @@ bool WorkerMessageFilter::OnMessageReceived(const IPC::Message& message,
IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, OnForwardToWorker)
// Only sent from renderer.
IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentDetached, OnDocumentDetached)
- // Message Port related messages.
- IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_CreateMessagePort,
- OnCreateMessagePort)
- IPC_MESSAGE_FORWARD(WorkerProcessHostMsg_DestroyMessagePort,
- MessagePortService::GetInstance(),
- MessagePortService::Destroy)
- IPC_MESSAGE_FORWARD(WorkerProcessHostMsg_Entangle,
- MessagePortService::GetInstance(),
- MessagePortService::Entangle)
- IPC_MESSAGE_FORWARD(WorkerProcessHostMsg_PostMessage,
- MessagePortService::GetInstance(),
- MessagePortService::PostMessage)
- IPC_MESSAGE_FORWARD(WorkerProcessHostMsg_QueueMessages,
- MessagePortService::GetInstance(),
- MessagePortService::QueueMessages)
- IPC_MESSAGE_FORWARD(WorkerProcessHostMsg_SendQueuedMessages,
- MessagePortService::GetInstance(),
- MessagePortService::SendQueuedMessages)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
@@ -73,14 +52,14 @@ bool WorkerMessageFilter::OnMessageReceived(const IPC::Message& message,
}
int WorkerMessageFilter::GetNextRoutingID() {
- return next_routing_id_.Run();
+ return message_port_message_filter_->GetNextRoutingID();
}
void WorkerMessageFilter::OnCreateWorker(
const ViewHostMsg_CreateWorker_Params& params,
int* route_id) {
*route_id = params.route_id != MSG_ROUTING_NONE ?
- params.route_id : next_routing_id_.Run();
+ params.route_id : GetNextRoutingID();
WorkerServiceImpl::GetInstance()->CreateWorker(
params, *route_id, this, resource_context_, partition_);
}
@@ -90,7 +69,7 @@ void WorkerMessageFilter::OnLookupSharedWorker(
bool* exists,
int* route_id,
bool* url_error) {
- *route_id = next_routing_id_.Run();
+ *route_id = GetNextRoutingID();
WorkerServiceImpl::GetInstance()->LookupSharedWorker(
params, *route_id, this, resource_context_, partition_, exists,
@@ -105,10 +84,4 @@ void WorkerMessageFilter::OnDocumentDetached(unsigned long long document_id) {
WorkerServiceImpl::GetInstance()->DocumentDetached(document_id, this);
}
-void WorkerMessageFilter::OnCreateMessagePort(int *route_id,
- int* message_port_id) {
- *route_id = next_routing_id_.Run();
- MessagePortService::GetInstance()->Create(*route_id, this, message_port_id);
-}
-
} // namespace content
diff --git a/chromium/content/browser/worker_host/worker_message_filter.h b/chromium/content/browser/worker_host/worker_message_filter.h
index 47f96efc517..0d495fae302 100644
--- a/chromium/content/browser/worker_host/worker_message_filter.h
+++ b/chromium/content/browser/worker_host/worker_message_filter.h
@@ -13,18 +13,15 @@ class ResourceDispatcherHost;
struct ViewHostMsg_CreateWorker_Params;
namespace content {
+class MessagePortMessageFilter;
class ResourceContext;
class WorkerMessageFilter : public BrowserMessageFilter {
public:
- typedef base::Callback<int(void)> NextRoutingIDCallback;
-
- // |next_routing_id| is owned by this object. It can be used up until
- // OnChannelClosing.
WorkerMessageFilter(int render_process_id,
ResourceContext* resource_context,
const WorkerStoragePartition& partition,
- const NextRoutingIDCallback& callback);
+ MessagePortMessageFilter* message_port_filter);
// BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
@@ -34,6 +31,10 @@ class WorkerMessageFilter : public BrowserMessageFilter {
int GetNextRoutingID();
int render_process_id() const { return render_process_id_; }
+ MessagePortMessageFilter* message_port_message_filter() const {
+ return message_port_message_filter_;
+ }
+
private:
virtual ~WorkerMessageFilter();
@@ -52,10 +53,7 @@ class WorkerMessageFilter : public BrowserMessageFilter {
ResourceContext* const resource_context_;
WorkerStoragePartition partition_;
- // This is guaranteed to be valid until OnChannelClosing is closed, and it's
- // not used after.
- NextRoutingIDCallback next_routing_id_;
-
+ MessagePortMessageFilter* message_port_message_filter_;
DISALLOW_IMPLICIT_CONSTRUCTORS(WorkerMessageFilter);
};
diff --git a/chromium/content/browser/worker_host/worker_process_host.cc b/chromium/content/browser/worker_host/worker_process_host.cc
index a228f9cf0eb..fae589bf476 100644
--- a/chromium/content/browser/worker_host/worker_process_host.cc
+++ b/chromium/content/browser/worker_host/worker_process_host.cc
@@ -25,6 +25,8 @@
#include "content/browser/fileapi/fileapi_message_filter.h"
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/message_port_message_filter.h"
+#include "content/browser/message_port_service.h"
#include "content/browser/mime_registry_message_filter.h"
#include "content/browser/quota_dispatcher_host.h"
#include "content/browser/renderer_host/database_message_filter.h"
@@ -33,7 +35,6 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
#include "content/browser/resource_context_impl.h"
-#include "content/browser/worker_host/message_port_service.h"
#include "content/browser/worker_host/worker_message_filter.h"
#include "content/browser/worker_host/worker_service_impl.h"
#include "content/common/child_process_host_impl.h"
@@ -152,9 +153,11 @@ bool WorkerProcessHost::Init(int render_process_id) {
switches::kDisableFileSystem,
switches::kDisableSeccompFilterSandbox,
switches::kEnableExperimentalWebPlatformFeatures,
+ switches::kEnableServiceWorker,
#if defined(OS_MACOSX)
switches::kEnableSandboxLogging,
#endif
+ switches::kJavaScriptFlags
};
cmd_line->CopySwitchesFrom(*CommandLine::ForCurrentProcess(), kSwitchNames,
arraysize(kSwitchNames));
@@ -221,27 +224,31 @@ void WorkerProcessHost::CreateMessageFilters(int render_process_id) {
blob_storage_context,
partition_.filesystem_context(),
get_contexts_callback);
- process_->GetHost()->AddFilter(resource_message_filter);
-
- worker_message_filter_ = new WorkerMessageFilter(
- render_process_id, resource_context_, partition_,
- base::Bind(&WorkerServiceImpl::next_worker_route_id,
- base::Unretained(WorkerServiceImpl::GetInstance())));
- process_->GetHost()->AddFilter(worker_message_filter_.get());
- process_->GetHost()->AddFilter(new AppCacheDispatcherHost(
+ process_->AddFilter(resource_message_filter);
+
+ MessagePortMessageFilter* message_port_message_filter =
+ new MessagePortMessageFilter(
+ base::Bind(&WorkerServiceImpl::next_worker_route_id,
+ base::Unretained(WorkerServiceImpl::GetInstance())));
+ process_->AddFilter(message_port_message_filter);
+ worker_message_filter_ = new WorkerMessageFilter(render_process_id,
+ resource_context_,
+ partition_,
+ message_port_message_filter);
+ process_->AddFilter(worker_message_filter_.get());
+ process_->AddFilter(new AppCacheDispatcherHost(
partition_.appcache_service(), process_->GetData().id));
- process_->GetHost()->AddFilter(new FileAPIMessageFilter(
+ process_->AddFilter(new FileAPIMessageFilter(
process_->GetData().id,
url_request_context,
partition_.filesystem_context(),
blob_storage_context,
stream_context));
- process_->GetHost()->AddFilter(new FileUtilitiesMessageFilter(
+ process_->AddFilter(new FileUtilitiesMessageFilter(
process_->GetData().id));
- process_->GetHost()->AddFilter(new MimeRegistryMessageFilter());
- process_->GetHost()->AddFilter(
- new DatabaseMessageFilter(partition_.database_tracker()));
- process_->GetHost()->AddFilter(new QuotaDispatcherHost(
+ process_->AddFilter(new MimeRegistryMessageFilter());
+ process_->AddFilter(new DatabaseMessageFilter(partition_.database_tracker()));
+ process_->AddFilter(new QuotaDispatcherHost(
process_->GetData().id,
partition_.quota_manager(),
GetContentClient()->browser()->CreateQuotaPermissionContext()));
@@ -257,11 +264,10 @@ void WorkerProcessHost::CreateMessageFilters(int render_process_id) {
request_context_callback,
resource_context_);
socket_stream_dispatcher_host_ = socket_stream_dispatcher_host;
- process_->GetHost()->AddFilter(socket_stream_dispatcher_host);
- process_->GetHost()->AddFilter(
- new WorkerDevToolsMessageFilter(process_->GetData().id));
- process_->GetHost()->AddFilter(new IndexedDBDispatcherHost(
- process_->GetData().id, partition_.indexed_db_context()));
+ process_->AddFilter(socket_stream_dispatcher_host);
+ process_->AddFilter(new WorkerDevToolsMessageFilter(process_->GetData().id));
+ process_->AddFilter(
+ new IndexedDBDispatcherHost(partition_.indexed_db_context()));
}
void WorkerProcessHost::CreateWorker(const WorkerInstance& instance) {
@@ -318,6 +324,8 @@ bool WorkerProcessHost::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowDatabase, OnAllowDatabase)
IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowFileSystem, OnAllowFileSystem)
IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowIndexedDB, OnAllowIndexedDB)
+ IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_ForceKillWorker,
+ OnForceKillWorkerProcess)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
@@ -364,8 +372,8 @@ void WorkerProcessHost::OnWorkerContextClosed(int worker_route_id) {
void WorkerProcessHost::OnAllowDatabase(int worker_route_id,
const GURL& url,
- const string16& name,
- const string16& display_name,
+ const base::string16& name,
+ const base::string16& display_name,
unsigned long estimated_size,
bool* result) {
*result = GetContentClient()->browser()->AllowWorkerDatabase(
@@ -382,46 +390,25 @@ void WorkerProcessHost::OnAllowFileSystem(int worker_route_id,
void WorkerProcessHost::OnAllowIndexedDB(int worker_route_id,
const GURL& url,
- const string16& name,
+ const base::string16& name,
bool* result) {
*result = GetContentClient()->browser()->AllowWorkerIndexedDB(
url, name, resource_context_, GetRenderViewIDsForWorker(worker_route_id));
}
+void WorkerProcessHost::OnForceKillWorkerProcess() {
+ if (process_ && process_launched_)
+ base::KillProcess(
+ process_->GetData().handle, RESULT_CODE_NORMAL_EXIT, false);
+ else
+ RecordAction(UserMetricsAction("WorkerProcess_BadProcessToKill"));
+}
+
void WorkerProcessHost::RelayMessage(
const IPC::Message& message,
WorkerMessageFilter* filter,
int route_id) {
- if (message.type() == WorkerMsg_PostMessage::ID) {
- // We want to send the receiver a routing id for the new channel, so
- // crack the message first.
- string16 msg;
- std::vector<int> sent_message_port_ids;
- std::vector<int> new_routing_ids;
- if (!WorkerMsg_PostMessage::Read(
- &message, &msg, &sent_message_port_ids, &new_routing_ids)) {
- return;
- }
- if (sent_message_port_ids.size() != new_routing_ids.size())
- return;
-
- for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
- new_routing_ids[i] = filter->GetNextRoutingID();
- MessagePortService::GetInstance()->UpdateMessagePort(
- sent_message_port_ids[i], filter, new_routing_ids[i]);
- }
-
- filter->Send(new WorkerMsg_PostMessage(
- route_id, msg, sent_message_port_ids, new_routing_ids));
-
- // Send any queued messages to the sent message ports. We can only do this
- // after sending the above message, since it's the one that sets up the
- // message port route which the queued messages are sent to.
- for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
- MessagePortService::GetInstance()->
- SendQueuedMessagesIfPossible(sent_message_port_ids[i]);
- }
- } else if (message.type() == WorkerMsg_Connect::ID) {
+ if (message.type() == WorkerMsg_Connect::ID) {
// Crack the SharedWorker Connect message to setup routing for the port.
int sent_message_port_id;
int new_routing_id;
@@ -431,7 +418,9 @@ void WorkerProcessHost::RelayMessage(
}
new_routing_id = filter->GetNextRoutingID();
MessagePortService::GetInstance()->UpdateMessagePort(
- sent_message_port_id, filter, new_routing_id);
+ sent_message_port_id,
+ filter->message_port_message_filter(),
+ new_routing_id);
// Resend the message with the new routing id.
filter->Send(new WorkerMsg_Connect(
@@ -583,7 +572,7 @@ net::URLRequestContext* WorkerProcessHost::GetRequestContext(
WorkerProcessHost::WorkerInstance::WorkerInstance(
const GURL& url,
- const string16& name,
+ const base::string16& name,
int worker_route_id,
int parent_process_id,
int64 main_resource_appcache_id,
@@ -604,7 +593,7 @@ WorkerProcessHost::WorkerInstance::WorkerInstance(
WorkerProcessHost::WorkerInstance::WorkerInstance(
const GURL& url,
bool shared,
- const string16& name,
+ const base::string16& name,
ResourceContext* resource_context,
const WorkerStoragePartition& partition)
: url_(url),
@@ -629,7 +618,7 @@ WorkerProcessHost::WorkerInstance::~WorkerInstance() {
// b) the names are both empty, and the urls are equal
bool WorkerProcessHost::WorkerInstance::Matches(
const GURL& match_url,
- const string16& match_name,
+ const base::string16& match_name,
const WorkerStoragePartition& partition,
ResourceContext* resource_context) const {
// Only match open shared workers.
diff --git a/chromium/content/browser/worker_host/worker_process_host.h b/chromium/content/browser/worker_host/worker_process_host.h
index 7bc6884e64a..c3fa64d6d74 100644
--- a/chromium/content/browser/worker_host/worker_process_host.h
+++ b/chromium/content/browser/worker_host/worker_process_host.h
@@ -57,7 +57,7 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate,
class WorkerInstance {
public:
WorkerInstance(const GURL& url,
- const string16& name,
+ const base::string16& name,
int worker_route_id,
int parent_process_id,
int64 main_resource_appcache_id,
@@ -66,7 +66,7 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate,
// Used for pending instances. Rest of the parameters are ignored.
WorkerInstance(const GURL& url,
bool shared,
- const string16& name,
+ const base::string16& name,
ResourceContext* resource_context,
const WorkerStoragePartition& partition);
~WorkerInstance();
@@ -92,7 +92,7 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate,
// applies to shared workers.
bool Matches(
const GURL& url,
- const string16& name,
+ const base::string16& name,
const WorkerStoragePartition& partition,
ResourceContext* resource_context) const;
@@ -107,7 +107,7 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate,
bool closed() const { return closed_; }
void set_closed(bool closed) { closed_ = closed; }
const GURL& url() const { return url_; }
- const string16 name() const { return name_; }
+ const base::string16 name() const { return name_; }
int worker_route_id() const { return worker_route_id_; }
int parent_process_id() const { return parent_process_id_; }
int64 main_resource_appcache_id() const {
@@ -127,7 +127,7 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate,
// Set of all filters (clients) associated with this worker.
GURL url_;
bool closed_;
- string16 name_;
+ base::string16 name_;
int worker_route_id_;
int parent_process_id_;
int64 main_resource_appcache_id_;
@@ -196,8 +196,8 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate,
void OnWorkerContextClosed(int worker_route_id);
void OnAllowDatabase(int worker_route_id,
const GURL& url,
- const string16& name,
- const string16& display_name,
+ const base::string16& name,
+ const base::string16& display_name,
unsigned long estimated_size,
bool* result);
void OnAllowFileSystem(int worker_route_id,
@@ -205,8 +205,9 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate,
bool* result);
void OnAllowIndexedDB(int worker_route_id,
const GURL& url,
- const string16& name,
+ const base::string16& name,
bool* result);
+ void OnForceKillWorkerProcess();
// Relays a message to the given endpoint. Takes care of parsing the message
// if it contains a message port and sending it a valid route id.
diff --git a/chromium/content/browser/worker_host/worker_service_impl.cc b/chromium/content/browser/worker_host/worker_service_impl.cc
index d2ab272922d..3ebab469ff7 100644
--- a/chromium/content/browser/worker_host/worker_service_impl.cc
+++ b/chromium/content/browser/worker_host/worker_service_impl.cc
@@ -650,7 +650,7 @@ void WorkerServiceImpl::NotifyWorkerProcessCreated() {
WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance(
const GURL& url,
- const string16& name,
+ const base::string16& name,
const WorkerStoragePartition& partition,
ResourceContext* resource_context) {
for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
@@ -667,7 +667,7 @@ WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance(
WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindPendingInstance(
const GURL& url,
- const string16& name,
+ const base::string16& name,
const WorkerStoragePartition& partition,
ResourceContext* resource_context) {
// Walk the pending instances looking for a matching pending worker.
@@ -684,7 +684,7 @@ WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindPendingInstance(
void WorkerServiceImpl::RemovePendingInstances(
const GURL& url,
- const string16& name,
+ const base::string16& name,
const WorkerStoragePartition& partition,
ResourceContext* resource_context) {
// Walk the pending instances looking for a matching pending worker.
@@ -701,7 +701,7 @@ void WorkerServiceImpl::RemovePendingInstances(
WorkerProcessHost::WorkerInstance* WorkerServiceImpl::CreatePendingInstance(
const GURL& url,
- const string16& name,
+ const base::string16& name,
ResourceContext* resource_context,
const WorkerStoragePartition& partition) {
// Look for an existing pending shared worker.
diff --git a/chromium/content/browser/worker_host/worker_service_impl.h b/chromium/content/browser/worker_host/worker_service_impl.h
index 9da0d19cd21..4d5127aec25 100644
--- a/chromium/content/browser/worker_host/worker_service_impl.h
+++ b/chromium/content/browser/worker_host/worker_service_impl.h
@@ -108,23 +108,23 @@ class CONTENT_EXPORT WorkerServiceImpl
// APIs for manipulating our set of pending shared worker instances.
WorkerProcessHost::WorkerInstance* CreatePendingInstance(
const GURL& url,
- const string16& name,
+ const base::string16& name,
ResourceContext* resource_context,
const WorkerStoragePartition& worker_partition);
WorkerProcessHost::WorkerInstance* FindPendingInstance(
const GURL& url,
- const string16& name,
+ const base::string16& name,
const WorkerStoragePartition& worker_partition,
ResourceContext* resource_context);
void RemovePendingInstances(
const GURL& url,
- const string16& name,
+ const base::string16& name,
const WorkerStoragePartition& worker_partition,
ResourceContext* resource_context);
WorkerProcessHost::WorkerInstance* FindSharedWorkerInstance(
const GURL& url,
- const string16& name,
+ const base::string16& name,
const WorkerStoragePartition& worker_partition,
ResourceContext* resource_context);
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 fea43b50b17..18e9b693094 100644
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
+++ b/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
@@ -52,16 +52,18 @@ ZygoteHost* ZygoteHost::GetInstance() {
ZygoteHostImpl::ZygoteHostImpl()
: control_fd_(-1),
+ control_lock_(),
pid_(-1),
init_(false),
using_suid_sandbox_(false),
+ sandbox_binary_(),
have_read_sandbox_status_word_(false),
- sandbox_status_(0) {}
+ sandbox_status_(0),
+ child_tracking_lock_(),
+ list_of_running_zygote_children_(),
+ should_teardown_after_last_child_exits_(false) {}
-ZygoteHostImpl::~ZygoteHostImpl() {
- if (init_)
- close(control_fd_);
-}
+ZygoteHostImpl::~ZygoteHostImpl() { TearDown(); }
// static
ZygoteHostImpl* ZygoteHostImpl::GetInstance() {
@@ -217,8 +219,56 @@ void ZygoteHostImpl::Init(const std::string& sandbox_cmd) {
// We don't wait for the reply. We'll read it in ReadReply.
}
+void ZygoteHostImpl::TearDownAfterLastChild() {
+ bool do_teardown = false;
+ {
+ base::AutoLock lock(child_tracking_lock_);
+ should_teardown_after_last_child_exits_ = true;
+ do_teardown = list_of_running_zygote_children_.empty();
+ }
+ if (do_teardown) {
+ TearDown();
+ }
+}
+
+// Note: this is also called from the destructor.
+void ZygoteHostImpl::TearDown() {
+ base::AutoLock lock(control_lock_);
+ if (control_fd_ > -1) {
+ // Closing the IPC channel will act as a notification to exit
+ // to the Zygote.
+ if (IGNORE_EINTR(close(control_fd_))) {
+ PLOG(ERROR) << "Could not close Zygote control channel.";
+ NOTREACHED();
+ }
+ control_fd_ = -1;
+ }
+}
+
+void ZygoteHostImpl::ZygoteChildBorn(pid_t process) {
+ base::AutoLock lock(child_tracking_lock_);
+ bool new_element_inserted =
+ list_of_running_zygote_children_.insert(process).second;
+ DCHECK(new_element_inserted);
+}
+
+void ZygoteHostImpl::ZygoteChildDied(pid_t process) {
+ bool do_teardown = false;
+ {
+ base::AutoLock lock(child_tracking_lock_);
+ size_t num_erased = list_of_running_zygote_children_.erase(process);
+ DCHECK_EQ(1U, num_erased);
+ do_teardown = should_teardown_after_last_child_exits_ &&
+ list_of_running_zygote_children_.empty();
+ }
+ if (do_teardown) {
+ TearDown();
+ }
+}
+
bool ZygoteHostImpl::SendMessage(const Pickle& data,
const std::vector<int>* fds) {
+ DCHECK_NE(-1, control_fd_);
CHECK(data.size() <= kZygoteMaxMessageLength)
<< "Trying to send too-large message to zygote (sending " << data.size()
<< " bytes, max is " << kZygoteMaxMessageLength << ")";
@@ -233,6 +283,7 @@ bool ZygoteHostImpl::SendMessage(const Pickle& data,
}
ssize_t ZygoteHostImpl::ReadReply(void* buf, size_t buf_len) {
+ DCHECK_NE(-1, control_fd_);
// 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.
@@ -336,6 +387,7 @@ pid_t ZygoteHostImpl::ForkRequest(
AdjustRendererOOMScore(pid, kLowestRendererOomScore);
#endif
+ ZygoteChildBorn(pid);
return pid;
}
@@ -407,41 +459,6 @@ void ZygoteHostImpl::AdjustRendererOOMScore(base::ProcessHandle pid,
}
#endif
-void ZygoteHostImpl::AdjustLowMemoryMargin(int64 margin_mb) {
-#if defined(OS_CHROMEOS)
- // You can't change the low memory margin unless you're root. Because of this,
- // we can't set the low memory margin from the browser process.
- // So, we use the SUID binary to change it for us.
- if (using_suid_sandbox_) {
-#if defined(USE_TCMALLOC)
- // If heap profiling is running, these processes are not exiting, at least
- // on ChromeOS. The easiest thing to do is not launch them when profiling.
- // TODO(stevenjb): Investigate further and fix.
- if (IsHeapProfilerRunning())
- return;
-#endif
- std::vector<std::string> adj_low_mem_commandline;
- adj_low_mem_commandline.push_back(sandbox_binary_);
- adj_low_mem_commandline.push_back(sandbox::kAdjustLowMemMarginSwitch);
- adj_low_mem_commandline.push_back(base::Int64ToString(margin_mb));
-
- base::ProcessHandle sandbox_helper_process;
- if (base::LaunchProcess(adj_low_mem_commandline, base::LaunchOptions(),
- &sandbox_helper_process)) {
- base::EnsureProcessGetsReaped(sandbox_helper_process);
- } else {
- LOG(ERROR) << "Unable to run suid sandbox to set low memory margin.";
- }
- }
- // Don't adjust memory margin if we're not running with the sandbox: this
- // isn't very common, and not doing it has little impact.
-#else
- // Low memory notification is currently only implemented on ChromeOS.
- NOTREACHED() << "AdjustLowMemoryMargin not implemented";
-#endif // defined(OS_CHROMEOS)
-}
-
-
void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) {
DCHECK(init_);
Pickle pickle;
@@ -450,6 +467,7 @@ void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) {
pickle.WriteInt(process);
if (!SendMessage(pickle, NULL))
LOG(ERROR) << "Failed to send Reap message to zygote";
+ ZygoteChildDied(process);
}
base::TerminationStatus ZygoteHostImpl::GetTerminationStatus(
@@ -462,10 +480,6 @@ base::TerminationStatus ZygoteHostImpl::GetTerminationStatus(
pickle.WriteBool(known_dead);
pickle.WriteInt(handle);
- // Set this now to handle the early termination cases.
- if (exit_code)
- *exit_code = RESULT_CODE_NORMAL_EXIT;
-
static const unsigned kMaxMessageLength = 128;
char buf[kMaxMessageLength];
ssize_t len;
@@ -476,26 +490,33 @@ base::TerminationStatus ZygoteHostImpl::GetTerminationStatus(
len = ReadReply(buf, sizeof(buf));
}
+ // Set this now to handle the error cases.
+ if (exit_code)
+ *exit_code = RESULT_CODE_NORMAL_EXIT;
+ int status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
+
if (len == -1) {
LOG(WARNING) << "Error reading message from zygote: " << errno;
- return base::TERMINATION_STATUS_NORMAL_TERMINATION;
} else if (len == 0) {
LOG(WARNING) << "Socket closed prematurely.";
- return base::TERMINATION_STATUS_NORMAL_TERMINATION;
+ } else {
+ Pickle read_pickle(buf, len);
+ int tmp_status, tmp_exit_code;
+ PickleIterator iter(read_pickle);
+ if (!read_pickle.ReadInt(&iter, &tmp_status) ||
+ !read_pickle.ReadInt(&iter, &tmp_exit_code)) {
+ LOG(WARNING)
+ << "Error parsing GetTerminationStatus response from zygote.";
+ } else {
+ if (exit_code)
+ *exit_code = tmp_exit_code;
+ status = tmp_status;
+ }
}
- Pickle read_pickle(buf, len);
- int status, tmp_exit_code;
- PickleIterator iter(read_pickle);
- if (!read_pickle.ReadInt(&iter, &status) ||
- !read_pickle.ReadInt(&iter, &tmp_exit_code)) {
- LOG(WARNING) << "Error parsing GetTerminationStatus response from zygote.";
- return base::TERMINATION_STATUS_NORMAL_TERMINATION;
+ if (status != base::TERMINATION_STATUS_STILL_RUNNING) {
+ ZygoteChildDied(handle);
}
-
- if (exit_code)
- *exit_code = tmp_exit_code;
-
return static_cast<base::TerminationStatus>(status);
}
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 6a1aca5ba79..08044fa5a88 100644
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
+++ b/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_HOST_IMPL_LINUX_H_
#define CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_HOST_IMPL_LINUX_H_
+#include <set>
#include <string>
#include <vector>
@@ -26,6 +27,9 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
void Init(const std::string& sandbox_cmd);
+ // After the last known Zygote child exits, notify the Zygote to exit.
+ void TearDownAfterLastChild();
+
// Tries to start a process of type indicated by process_type.
// Returns its pid on success, otherwise
// base::kNullProcessHandle;
@@ -55,7 +59,6 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
virtual int GetSandboxStatus() const OVERRIDE;
virtual void AdjustRendererOOMScore(base::ProcessHandle process_handle,
int score) OVERRIDE;
- virtual void AdjustLowMemoryMargin(int64 margin_mb) OVERRIDE;
private:
friend struct DefaultSingletonTraits<ZygoteHostImpl>;
@@ -63,6 +66,16 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
ZygoteHostImpl();
virtual ~ZygoteHostImpl();
+ // Notify the Zygote to exit immediately. This object should not be
+ // used afterwards.
+ void TearDown();
+
+ // Should be called every time a Zygote child is born.
+ void ZygoteChildBorn(pid_t process);
+
+ // Should be called every time a Zygote child died.
+ void ZygoteChildDied(pid_t process);
+
// Sends |data| to the zygote via |control_fd_|. If |fds| is non-NULL, the
// included file descriptors will also be passed. The caller is responsible
// for acquiring |control_lock_|.
@@ -81,6 +94,11 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
std::string sandbox_binary_;
bool have_read_sandbox_status_word_;
int sandbox_status_;
+ // A lock protecting list_of_running_zygote_children_ and
+ // should_teardown_after_last_child_exits_.
+ base::Lock child_tracking_lock_;
+ std::set<pid_t> list_of_running_zygote_children_;
+ bool should_teardown_after_last_child_exits_;
};
} // namespace content
diff --git a/chromium/content/child/DEPS b/chromium/content/child/DEPS
index e962861d546..911b3c9175e 100644
--- a/chromium/content/child/DEPS
+++ b/chromium/content/child/DEPS
@@ -1,4 +1,5 @@
include_rules = [
"+components/tracing",
"+content/public/child",
+ "+media/base/android",
]
diff --git a/chromium/content/child/OWNERS b/chromium/content/child/OWNERS
index 95f1dec14d5..b212a3fd8e7 100644
--- a/chromium/content/child/OWNERS
+++ b/chromium/content/child/OWNERS
@@ -1 +1,6 @@
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
diff --git a/chromium/content/child/appcache/appcache_frontend_impl.cc b/chromium/content/child/appcache/appcache_frontend_impl.cc
index 0163df2d1cd..ee7f5566a90 100644
--- a/chromium/content/child/appcache/appcache_frontend_impl.cc
+++ b/chromium/content/child/appcache/appcache_frontend_impl.cc
@@ -9,8 +9,8 @@
#include "third_party/WebKit/public/web/WebApplicationCacheHost.h"
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
-using WebKit::WebApplicationCacheHost;
-using WebKit::WebConsoleMessage;
+using blink::WebApplicationCacheHost;
+using blink::WebConsoleMessage;
namespace content {
diff --git a/chromium/content/child/appcache/web_application_cache_host_impl.cc b/chromium/content/child/appcache/web_application_cache_host_impl.cc
index b4a15f37750..2088bc6ace8 100644
--- a/chromium/content/child/appcache/web_application_cache_host_impl.cc
+++ b/chromium/content/child/appcache/web_application_cache_host_impl.cc
@@ -14,14 +14,14 @@
#include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebFrame.h"
-using WebKit::WebApplicationCacheHost;
-using WebKit::WebApplicationCacheHostClient;
-using WebKit::WebDataSource;
-using WebKit::WebFrame;
-using WebKit::WebURLRequest;
-using WebKit::WebURL;
-using WebKit::WebURLResponse;
-using WebKit::WebVector;
+using blink::WebApplicationCacheHost;
+using blink::WebApplicationCacheHostClient;
+using blink::WebDataSource;
+using blink::WebFrame;
+using blink::WebURLRequest;
+using blink::WebURL;
+using blink::WebURLResponse;
+using blink::WebVector;
using appcache::AppCacheBackend;
using appcache::AppCacheResourceInfo;
diff --git a/chromium/content/child/appcache/web_application_cache_host_impl.h b/chromium/content/child/appcache/web_application_cache_host_impl.h
index c0cdea97692..afda8a0593d 100644
--- a/chromium/content/child/appcache/web_application_cache_host_impl.h
+++ b/chromium/content/child/appcache/web_application_cache_host_impl.h
@@ -13,28 +13,28 @@
#include "url/gurl.h"
#include "webkit/common/appcache/appcache_interfaces.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
}
namespace content {
class WebApplicationCacheHostImpl
- : NON_EXPORTED_BASE(public WebKit::WebApplicationCacheHost) {
+ : NON_EXPORTED_BASE(public blink::WebApplicationCacheHost) {
public:
// Returns the host having given id or NULL if there is no such host.
static WebApplicationCacheHostImpl* FromId(int id);
// Returns the host associated with the current document in frame.
- static WebApplicationCacheHostImpl* FromFrame(const WebKit::WebFrame* frame);
+ static WebApplicationCacheHostImpl* FromFrame(const blink::WebFrame* frame);
- WebApplicationCacheHostImpl(WebKit::WebApplicationCacheHostClient* client,
+ WebApplicationCacheHostImpl(blink::WebApplicationCacheHostClient* client,
appcache::AppCacheBackend* backend);
virtual ~WebApplicationCacheHostImpl();
int host_id() const { return host_id_; }
appcache::AppCacheBackend* backend() const { return backend_; }
- WebKit::WebApplicationCacheHostClient* client() const { return client_; }
+ blink::WebApplicationCacheHostClient* client() const { return client_; }
virtual void OnCacheSelected(const appcache::AppCacheInfo& info);
void OnStatusChanged(appcache::Status);
@@ -45,19 +45,19 @@ class WebApplicationCacheHostImpl
const std::string& message) {}
virtual void OnContentBlocked(const GURL& manifest_url) {}
- // WebKit::WebApplicationCacheHost:
- virtual void willStartMainResourceRequest(WebKit::WebURLRequest&,
- const WebKit::WebFrame*);
- virtual void willStartSubResourceRequest(WebKit::WebURLRequest&);
+ // blink::WebApplicationCacheHost:
+ virtual void willStartMainResourceRequest(blink::WebURLRequest&,
+ const blink::WebFrame*);
+ virtual void willStartSubResourceRequest(blink::WebURLRequest&);
virtual void selectCacheWithoutManifest();
- virtual bool selectCacheWithManifest(const WebKit::WebURL& manifestURL);
- virtual void didReceiveResponseForMainResource(const WebKit::WebURLResponse&);
+ virtual bool selectCacheWithManifest(const blink::WebURL& manifestURL);
+ virtual void didReceiveResponseForMainResource(const blink::WebURLResponse&);
virtual void didReceiveDataForMainResource(const char* data, int len);
virtual void didFinishLoadingMainResource(bool success);
- virtual WebKit::WebApplicationCacheHost::Status status();
+ virtual blink::WebApplicationCacheHost::Status status();
virtual bool startUpdate();
virtual bool swapCache();
- virtual void getResourceList(WebKit::WebVector<ResourceInfo>* resources);
+ virtual void getResourceList(blink::WebVector<ResourceInfo>* resources);
virtual void getAssociatedCacheInfo(CacheInfo* info);
private:
@@ -67,11 +67,11 @@ class WebApplicationCacheHostImpl
NO
};
- WebKit::WebApplicationCacheHostClient* client_;
+ blink::WebApplicationCacheHostClient* client_;
appcache::AppCacheBackend* backend_;
int host_id_;
appcache::Status status_;
- WebKit::WebURLResponse document_response_;
+ blink::WebURLResponse document_response_;
GURL document_url_;
bool is_scheme_supported_;
bool is_get_method_;
diff --git a/chromium/content/child/browser_font_resource_trusted.cc b/chromium/content/child/browser_font_resource_trusted.cc
index d31ede098b3..be4a8b618b5 100644
--- a/chromium/content/child/browser_font_resource_trusted.cc
+++ b/chromium/content/child/browser_font_resource_trusted.cc
@@ -27,13 +27,13 @@
using ppapi::StringVar;
using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_ImageData_API;
-using WebKit::WebFloatPoint;
-using WebKit::WebFloatRect;
-using WebKit::WebFont;
-using WebKit::WebFontDescription;
-using WebKit::WebRect;
-using WebKit::WebTextRun;
-using WebKit::WebCanvas;
+using blink::WebFloatPoint;
+using blink::WebFloatRect;
+using blink::WebFont;
+using blink::WebFontDescription;
+using blink::WebRect;
+using blink::WebTextRun;
+using blink::WebCanvas;
namespace content {
@@ -43,14 +43,14 @@ namespace {
// undefined reference linker error.
const char kCommonScript[] = "Zyyy";
-string16 GetFontFromMap(
+base::string16 GetFontFromMap(
const webkit_glue::ScriptFontFamilyMap& map,
const std::string& script) {
webkit_glue::ScriptFontFamilyMap::const_iterator it =
map.find(script);
if (it != map.end())
return it->second;
- return string16();
+ return base::string16();
}
// Splits a PP_BrowserFont_Trusted_TextRun into a sequence or LTR and RTL
@@ -85,7 +85,7 @@ class TextRunCollection {
ubidi_close(bidi_);
}
- const string16& text() const { return text_; }
+ const base::string16& text() const { return text_; }
int num_runs() const { return num_runs_; }
// Returns a WebTextRun with the info for the run at the given index.
@@ -94,7 +94,7 @@ class TextRunCollection {
DCHECK(index < num_runs_);
if (bidi_) {
bool run_rtl = !!ubidi_getVisualRun(bidi_, index, run_start, run_len);
- return WebTextRun(string16(&text_[*run_start], *run_len),
+ return WebTextRun(base::string16(&text_[*run_start], *run_len),
run_rtl, true);
}
@@ -110,7 +110,7 @@ class TextRunCollection {
UBiDi* bidi_;
// Text of all the runs.
- string16 text_;
+ base::string16 text_;
int num_runs_;
@@ -167,7 +167,7 @@ WebFontDescription PPFontDescToWebFontDesc(
StringVar* face_name = StringVar::FromPPVar(font.face); // Possibly null.
WebFontDescription result;
- string16 resolved_family;
+ base::string16 resolved_family;
if (!face_name || face_name->value().empty()) {
// Resolve the generic family.
switch (font.family) {
diff --git a/chromium/content/child/browser_font_resource_trusted.h b/chromium/content/child/browser_font_resource_trusted.h
index 23a434423c8..09afe0c0a48 100644
--- a/chromium/content/child/browser_font_resource_trusted.h
+++ b/chromium/content/child/browser_font_resource_trusted.h
@@ -19,7 +19,7 @@
class SkCanvas;
-namespace WebKit {
+namespace blink {
class WebFont;
}
@@ -72,7 +72,7 @@ class BrowserFontResource_Trusted
PP_Bool image_data_is_opaque);
private:
- scoped_ptr<WebKit::WebFont> font_;
+ scoped_ptr<blink::WebFont> font_;
DISALLOW_COPY_AND_ASSIGN(BrowserFontResource_Trusted);
};
diff --git a/chromium/content/child/child_histogram_message_filter.cc b/chromium/content/child/child_histogram_message_filter.cc
index 427dd0d7d26..f05d111cf8b 100644
--- a/chromium/content/child/child_histogram_message_filter.cc
+++ b/chromium/content/child/child_histogram_message_filter.cc
@@ -8,8 +8,7 @@
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
-#include "base/metrics/statistics_recorder.h"
-#include "base/pickle.h"
+#include "base/metrics/histogram_delta_serialization.h"
#include "content/child/child_process.h"
#include "content/child/child_thread.h"
#include "content/common/child_process_messages.h"
@@ -18,8 +17,7 @@ namespace content {
ChildHistogramMessageFilter::ChildHistogramMessageFilter()
: channel_(NULL),
- io_message_loop_(ChildProcess::current()->io_message_loop_proxy()),
- histogram_snapshot_manager_(this) {
+ io_message_loop_(ChildProcess::current()->io_message_loop_proxy()) {
}
ChildHistogramMessageFilter::~ChildHistogramMessageFilter() {
@@ -54,53 +52,19 @@ void ChildHistogramMessageFilter::OnGetChildHistogramData(int sequence_number) {
}
void ChildHistogramMessageFilter::UploadAllHistograms(int sequence_number) {
- DCHECK_EQ(0u, pickled_histograms_.size());
+ if (!histogram_delta_serialization_) {
+ histogram_delta_serialization_.reset(
+ new base::HistogramDeltaSerialization("ChildProcess"));
+ }
- // Push snapshots into our pickled_histograms_ vector.
- // Note: Before serializing, we set the kIPCSerializationSourceFlag for all
- // the histograms, so that the receiving process can distinguish them from the
- // local histograms.
- histogram_snapshot_manager_.PrepareDeltas(
- base::Histogram::kIPCSerializationSourceFlag, false);
+ std::vector<std::string> deltas;
+ histogram_delta_serialization_->PrepareAndSerializeDeltas(&deltas);
+ channel_->Send(
+ new ChildProcessHostMsg_ChildHistogramData(sequence_number, deltas));
- channel_->Send(new ChildProcessHostMsg_ChildHistogramData(
- sequence_number, pickled_histograms_));
-
- pickled_histograms_.clear();
static int count = 0;
count++;
DHISTOGRAM_COUNTS("Histogram.ChildProcessHistogramSentCount", count);
}
-void ChildHistogramMessageFilter::RecordDelta(
- const base::HistogramBase& histogram,
- const base::HistogramSamples& snapshot) {
- DCHECK_NE(0, snapshot.TotalCount());
-
- Pickle pickle;
- histogram.SerializeInfo(&pickle);
- snapshot.Serialize(&pickle);
-
- pickled_histograms_.push_back(
- std::string(static_cast<const char*>(pickle.data()), pickle.size()));
-}
-
-void ChildHistogramMessageFilter::InconsistencyDetected(
- base::HistogramBase::Inconsistency problem) {
- UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesChildProcess",
- problem, base::HistogramBase::NEVER_EXCEEDED_VALUE);
-}
-
-void ChildHistogramMessageFilter::UniqueInconsistencyDetected(
- base::HistogramBase::Inconsistency problem) {
- UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesChildProcessUnique",
- problem, base::HistogramBase::NEVER_EXCEEDED_VALUE);
-}
-
-void ChildHistogramMessageFilter::InconsistencyDetectedInLoggedCount(
- int amount) {
- UMA_HISTOGRAM_COUNTS("Histogram.InconsistentSnapshotChildProcess",
- std::abs(amount));
-}
-
} // namespace content
diff --git a/chromium/content/child/child_histogram_message_filter.h b/chromium/content/child/child_histogram_message_filter.h
index 85d2e2097f1..98a30a21554 100644
--- a/chromium/content/child/child_histogram_message_filter.h
+++ b/chromium/content/child/child_histogram_message_filter.h
@@ -9,20 +9,16 @@
#include <vector>
#include "base/basictypes.h"
-#include "base/metrics/histogram_base.h"
-#include "base/metrics/histogram_flattener.h"
-#include "base/metrics/histogram_snapshot_manager.h"
#include "ipc/ipc_channel_proxy.h"
namespace base {
-class HistogramSamples;
+class HistogramDeltaSerialization;
class MessageLoopProxy;
} // namespace base
namespace content {
-class ChildHistogramMessageFilter : public base::HistogramFlattener,
- public IPC::ChannelProxy::MessageFilter {
+class ChildHistogramMessageFilter : public IPC::ChannelProxy::MessageFilter {
public:
ChildHistogramMessageFilter();
@@ -33,15 +29,6 @@ class ChildHistogramMessageFilter : public base::HistogramFlattener,
void SendHistograms(int sequence_number);
- // HistogramFlattener interface (override) methods.
- virtual void RecordDelta(const base::HistogramBase& histogram,
- const base::HistogramSamples& snapshot) OVERRIDE;
- virtual void InconsistencyDetected(
- base::HistogramBase::Inconsistency problem) OVERRIDE;
- virtual void UniqueInconsistencyDetected(
- base::HistogramBase::Inconsistency problem) OVERRIDE;
- virtual void InconsistencyDetectedInLoggedCount(int amount) OVERRIDE;
-
private:
typedef std::vector<std::string> HistogramPickledList;
@@ -58,11 +45,8 @@ class ChildHistogramMessageFilter : public base::HistogramFlattener,
scoped_refptr<base::MessageLoopProxy> io_message_loop_;
- // Collection of histograms to send to the browser.
- HistogramPickledList pickled_histograms_;
-
- // |histogram_snapshot_manager_| prepares histogram deltas for transmission.
- base::HistogramSnapshotManager histogram_snapshot_manager_;
+ // Prepares histogram deltas for transmission.
+ scoped_ptr<base::HistogramDeltaSerialization> histogram_delta_serialization_;
DISALLOW_COPY_AND_ASSIGN(ChildHistogramMessageFilter);
};
diff --git a/chromium/content/child/child_message_filter.cc b/chromium/content/child/child_message_filter.cc
new file mode 100644
index 00000000000..c325632235f
--- /dev/null
+++ b/chromium/content/child/child_message_filter.cc
@@ -0,0 +1,64 @@
+// 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/child/child_message_filter.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/task_runner.h"
+#include "content/child/child_thread.h"
+#include "content/child/thread_safe_sender.h"
+
+namespace content {
+
+class ChildMessageFilter::Internal : public IPC::ChannelProxy::MessageFilter {
+ public:
+ explicit Internal(ChildMessageFilter* filter) : filter_(filter) {}
+
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE {
+ scoped_refptr<base::TaskRunner> runner =
+ filter_->OverrideTaskRunnerForMessage(msg);
+ if (runner && !runner->RunsTasksOnCurrentThread()) {
+ if (!runner->PostTask(
+ FROM_HERE,
+ base::Bind(
+ base::IgnoreResult(&ChildMessageFilter::OnMessageReceived),
+ filter_, msg)))
+ filter_->OnStaleMessageReceived(msg);
+ return true;
+ }
+
+ return filter_->OnMessageReceived(msg);
+ }
+
+ private:
+ virtual ~Internal() {}
+ scoped_refptr<ChildMessageFilter> filter_;
+
+ DISALLOW_COPY_AND_ASSIGN(Internal);
+};
+
+bool ChildMessageFilter::Send(IPC::Message* message) {
+ return thread_safe_sender_->Send(message);
+}
+
+base::TaskRunner* ChildMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) {
+ return NULL;
+}
+
+ChildMessageFilter::ChildMessageFilter()
+ : internal_(NULL),
+ thread_safe_sender_(ChildThread::current()->thread_safe_sender()) {}
+
+ChildMessageFilter::~ChildMessageFilter() {}
+
+IPC::ChannelProxy::MessageFilter* ChildMessageFilter::GetFilter() {
+ if (!internal_)
+ internal_ = new Internal(this);
+ return internal_;
+}
+
+} // namespace content
diff --git a/chromium/content/child/child_message_filter.h b/chromium/content/child/child_message_filter.h
new file mode 100644
index 00000000000..21cccac065a
--- /dev/null
+++ b/chromium/content/child/child_message_filter.h
@@ -0,0 +1,68 @@
+// 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_CHILD_CROSS_MESSAGE_FILTER_H_
+#define CONTENT_CHILD_CROSS_MESSAGE_FILTER_H_
+
+#include "ipc/ipc_channel_proxy.h"
+
+namespace base {
+class TaskRunner;
+}
+
+namespace content {
+
+class ThreadSafeSender;
+
+// A base class for implementing IPC MessageFilter's that run on a different
+// thread or TaskRunner than the main thread.
+class ChildMessageFilter
+ : public base::RefCountedThreadSafe<ChildMessageFilter>,
+ public IPC::Sender {
+ public:
+ // IPC::Sender implementation. Can be called on any threads.
+ virtual bool Send(IPC::Message* message) OVERRIDE;
+
+ // If implementers want to run OnMessageReceived on a different task
+ // runner it should override this and return the TaskRunner for the message.
+ // Returning NULL runs OnMessageReceived() on the current IPC thread.
+ virtual base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) = 0;
+
+ // If OverrideTaskRunnerForMessage is overriden and returns non-null
+ // this will be called on the returned TaskRunner.
+ virtual bool OnMessageReceived(const IPC::Message& msg) = 0;
+
+ // This method is called when WorkerTaskRunner::PostTask() returned false
+ // for the target thread. Note that there's still a little chance that
+ // PostTask() returns true but OnMessageReceived() is never called on the
+ // target thread. By default this does nothing.
+ virtual void OnStaleMessageReceived(const IPC::Message& msg) {}
+
+ protected:
+ ChildMessageFilter();
+ virtual ~ChildMessageFilter();
+
+ private:
+ class Internal;
+ friend class ChildThread;
+ friend class RenderThreadImpl;
+ friend class WorkerThread;
+
+ friend class base::RefCountedThreadSafe<ChildMessageFilter>;
+
+ IPC::ChannelProxy::MessageFilter* GetFilter();
+
+ // This implements IPC::ChannelProxy::MessageFilter to hide the actual
+ // filter methods from child classes.
+ Internal* internal_;
+
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChildMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_CROSS_MESSAGE_FILTER_H_
diff --git a/chromium/content/child/child_thread.cc b/chromium/content/child/child_thread.cc
index d5df5821596..5b54ee041f9 100644
--- a/chromium/content/child/child_thread.cc
+++ b/chromium/content/child/child_thread.cc
@@ -4,14 +4,19 @@
#include "content/child/child_thread.h"
+#include <string>
+
#include "base/allocator/allocator_extension.h"
#include "base/base_switches.h"
#include "base/command_line.h"
+#include "base/debug/leak_annotations.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/process/kill.h"
#include "base/process/process_handle.h"
#include "base/strings/string_util.h"
+#include "base/synchronization/condition_variable.h"
+#include "base/synchronization/lock.h"
#include "base/threading/thread_local.h"
#include "base/tracked_objects.h"
#include "components/tracing/child_trace_message_filter.h"
@@ -23,15 +28,17 @@
#include "content/child/quota_dispatcher.h"
#include "content/child/quota_message_filter.h"
#include "content/child/resource_dispatcher.h"
+#include "content/child/service_worker/service_worker_dispatcher.h"
+#include "content/child/service_worker/service_worker_message_filter.h"
#include "content/child/socket_stream_dispatcher.h"
#include "content/child/thread_safe_sender.h"
+#include "content/child/websocket_dispatcher.h"
#include "content/common/child_process_messages.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_logging.h"
#include "ipc/ipc_switches.h"
#include "ipc/ipc_sync_channel.h"
#include "ipc/ipc_sync_message_filter.h"
-#include "webkit/glue/webkit_glue.h"
#if defined(OS_WIN)
#include "content/common/handle_enumerator_win.h"
@@ -83,6 +90,11 @@ class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter {
// that write profile data to disk (which happens under profile collection
// mode).
alarm(60);
+#if defined(LEAK_SANITIZER)
+ // Invoke LeakSanitizer early to avoid detecting shutdown-only leaks. If
+ // leaks are found, the process will exit here.
+ __lsan_do_leak_check();
+#endif
} else {
_exit(0);
}
@@ -95,7 +107,31 @@ class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter {
#endif // OS(POSIX)
#if defined(OS_ANDROID)
-ChildThread* g_child_thread;
+ChildThread* g_child_thread = NULL;
+
+// A lock protects g_child_thread.
+base::LazyInstance<base::Lock> g_lazy_child_thread_lock =
+ LAZY_INSTANCE_INITIALIZER;
+
+// base::ConditionVariable has an explicit constructor that takes
+// a base::Lock pointer as parameter. The base::DefaultLazyInstanceTraits
+// doesn't handle the case. Thus, we need our own class here.
+struct CondVarLazyInstanceTraits {
+ static const bool kRegisterOnExit = true;
+ static const bool kAllowedToAccessOnNonjoinableThread ALLOW_UNUSED = false;
+ static base::ConditionVariable* New(void* instance) {
+ return new (instance) base::ConditionVariable(
+ g_lazy_child_thread_lock.Pointer());
+ }
+ static void Delete(base::ConditionVariable* instance) {
+ instance->~ConditionVariable();
+ }
+};
+
+// A condition variable that synchronize threads initializing and waiting
+// for g_child_thread.
+base::LazyInstance<base::ConditionVariable, CondVarLazyInstanceTraits>
+ g_lazy_child_thread_cv = LAZY_INSTANCE_INITIALIZER;
void QuitMainThreadMessageLoop() {
base::MessageLoop::current()->Quit();
@@ -106,7 +142,8 @@ void QuitMainThreadMessageLoop() {
} // namespace
ChildThread::ChildThread()
- : channel_connected_factory_(this) {
+ : channel_connected_factory_(this),
+ in_browser_process_(false) {
channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessChannelID);
Init();
@@ -114,7 +151,8 @@ ChildThread::ChildThread()
ChildThread::ChildThread(const std::string& channel_name)
: channel_name_(channel_name),
- channel_connected_factory_(this) {
+ channel_connected_factory_(this),
+ in_browser_process_(true) {
Init();
}
@@ -136,7 +174,8 @@ void ChildThread::Init() {
true,
ChildProcess::current()->GetShutDownEvent()));
#ifdef IPC_MESSAGE_LOG_ENABLED
- IPC::Logging::GetInstance()->SetIPCSender(this);
+ if (!in_browser_process_)
+ IPC::Logging::GetInstance()->SetIPCSender(this);
#endif
sync_message_filter_ =
@@ -146,12 +185,18 @@ void ChildThread::Init() {
resource_dispatcher_.reset(new ResourceDispatcher(this));
socket_stream_dispatcher_.reset(new SocketStreamDispatcher());
+ websocket_dispatcher_.reset(new WebSocketDispatcher);
file_system_dispatcher_.reset(new FileSystemDispatcher());
histogram_message_filter_ = new ChildHistogramMessageFilter();
resource_message_filter_ =
new ChildResourceMessageFilter(resource_dispatcher());
+ service_worker_message_filter_ =
+ new ServiceWorkerMessageFilter(thread_safe_sender_.get());
+ service_worker_dispatcher_.reset(
+ new ServiceWorkerDispatcher(thread_safe_sender_.get()));
+
quota_message_filter_ =
new QuotaMessageFilter(thread_safe_sender_.get());
quota_dispatcher_.reset(new QuotaDispatcher(thread_safe_sender_.get(),
@@ -162,7 +207,8 @@ void ChildThread::Init() {
channel_->AddFilter(new tracing::ChildTraceMessageFilter(
ChildProcess::current()->io_message_loop_proxy()));
channel_->AddFilter(resource_message_filter_.get());
- channel_->AddFilter(quota_message_filter_.get());
+ channel_->AddFilter(quota_message_filter_->GetFilter());
+ channel_->AddFilter(service_worker_message_filter_->GetFilter());
// In single process mode we may already have a power monitor
if (!base::PowerMonitor::Get()) {
@@ -181,19 +227,6 @@ void ChildThread::Init() {
channel_->AddFilter(new SuicideOnChannelErrorFilter());
#endif
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToConsole)) {
- std::string category_string =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kTraceToConsole);
-
- if (!category_string.size())
- category_string = "*";
-
- base::debug::TraceLog::GetInstance()->SetEnabled(
- base::debug::CategoryFilter(category_string),
- base::debug::TraceLog::ECHO_TO_CONSOLE);
- }
-
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&ChildThread::EnsureConnected,
@@ -201,7 +234,13 @@ void ChildThread::Init() {
base::TimeDelta::FromSeconds(kConnectionTimeoutS));
#if defined(OS_ANDROID)
- g_child_thread = this;
+ {
+ base::AutoLock lock(g_lazy_child_thread_lock.Get());
+ g_child_thread = this;
+ }
+ // Signalling without locking is fine here because only
+ // one thread can wait on the condition variable.
+ g_lazy_child_thread_cv.Get().Signal();
#endif
#if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
@@ -218,7 +257,6 @@ ChildThread::~ChildThread() {
IPC::Logging::GetInstance()->SetIPCSender(NULL);
#endif
- channel_->RemoveFilter(quota_message_filter_.get());
channel_->RemoveFilter(histogram_message_filter_.get());
channel_->RemoveFilter(sync_message_filter_.get());
@@ -322,6 +360,8 @@ bool ChildThread::OnMessageReceived(const IPC::Message& msg) {
return true;
if (socket_stream_dispatcher_->OnMessageReceived(msg))
return true;
+ if (websocket_dispatcher_->OnMessageReceived(msg))
+ return true;
if (file_system_dispatcher_->OnMessageReceived(msg))
return true;
@@ -410,7 +450,16 @@ ChildThread* ChildThread::current() {
}
#if defined(OS_ANDROID)
+// The method must NOT be called on the child thread itself.
+// It may block the child thread if so.
void ChildThread::ShutdownThread() {
+ DCHECK(!ChildThread::current()) <<
+ "this method should NOT be called from child thread itself";
+ {
+ base::AutoLock lock(g_lazy_child_thread_lock.Get());
+ while (!g_child_thread)
+ g_lazy_child_thread_cv.Get().Wait();
+ }
DCHECK_NE(base::MessageLoop::current(), g_child_thread->message_loop());
g_child_thread->message_loop()->PostTask(
FROM_HERE, base::Bind(&QuitMainThreadMessageLoop));
@@ -434,7 +483,7 @@ void ChildThread::OnProcessFinalRelease() {
}
void ChildThread::EnsureConnected() {
- LOG(INFO) << "ChildThread::EnsureConnected()";
+ VLOG(0) << "ChildThread::EnsureConnected()";
base::KillProcess(base::GetCurrentProcessHandle(), 0, false);
}
diff --git a/chromium/content/child/child_thread.h b/chromium/content/child/child_thread.h
index b2095abf501..89156baadcc 100644
--- a/chromium/content/child/child_thread.h
+++ b/chromium/content/child/child_thread.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_CHILD_CHILD_THREAD_H_
#define CONTENT_CHILD_CHILD_THREAD_H_
+#include <string>
+
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
@@ -29,26 +31,29 @@ class SyncChannel;
class SyncMessageFilter;
} // namespace IPC
-namespace WebKit {
+namespace blink {
class WebFrame;
-} // namespace WebKit
+} // namespace blink
namespace content {
class ChildHistogramMessageFilter;
class ChildResourceMessageFilter;
class FileSystemDispatcher;
+class ServiceWorkerDispatcher;
+class ServiceWorkerMessageFilter;
class QuotaDispatcher;
class QuotaMessageFilter;
class ResourceDispatcher;
class SocketStreamDispatcher;
class ThreadSafeSender;
+class WebSocketDispatcher;
// The main thread of a child process derives from this class.
class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
public:
// Creates the thread.
ChildThread();
- // Used for single-process mode.
+ // Used for single-process mode and for in process gpu mode.
explicit ChildThread(const std::string& channel_name);
// ChildProcess::main_thread() is reset after Shutdown(), and before the
// destructor, so any subsystem that relies on ChildProcess::main_thread()
@@ -91,10 +96,18 @@ class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
return socket_stream_dispatcher_.get();
}
+ WebSocketDispatcher* websocket_dispatcher() const {
+ return websocket_dispatcher_.get();
+ }
+
FileSystemDispatcher* file_system_dispatcher() const {
return file_system_dispatcher_.get();
}
+ ServiceWorkerDispatcher* service_worker_dispatcher() const {
+ return service_worker_dispatcher_.get();
+ }
+
QuotaDispatcher* quota_dispatcher() const {
return quota_dispatcher_.get();
}
@@ -114,6 +127,10 @@ class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
return histogram_message_filter_.get();
}
+ ServiceWorkerMessageFilter* service_worker_message_filter() const {
+ return service_worker_message_filter_.get();
+ }
+
QuotaMessageFilter* quota_message_filter() const {
return quota_message_filter_.get();
}
@@ -180,6 +197,8 @@ class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
// Handles SocketStream for this process.
scoped_ptr<SocketStreamDispatcher> socket_stream_dispatcher_;
+ scoped_ptr<WebSocketDispatcher> websocket_dispatcher_;
+
// The OnChannelError() callback was invoked - the channel is dead, don't
// attempt to communicate.
bool on_channel_error_called_;
@@ -188,12 +207,16 @@ class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
scoped_ptr<FileSystemDispatcher> file_system_dispatcher_;
+ scoped_ptr<ServiceWorkerDispatcher> service_worker_dispatcher_;
+
scoped_ptr<QuotaDispatcher> quota_dispatcher_;
scoped_refptr<ChildHistogramMessageFilter> histogram_message_filter_;
scoped_refptr<ChildResourceMessageFilter> resource_message_filter_;
+ scoped_refptr<ServiceWorkerMessageFilter> service_worker_message_filter_;
+
scoped_refptr<QuotaMessageFilter> quota_message_filter_;
base::WeakPtrFactory<ChildThread> channel_connected_factory_;
@@ -204,6 +227,8 @@ class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
scoped_ptr<base::PowerMonitor> power_monitor_;
+ bool in_browser_process_;
+
DISALLOW_COPY_AND_ASSIGN(ChildThread);
};
diff --git a/chromium/content/child/database_util.cc b/chromium/content/child/database_util.cc
index e6a028b9049..34cf1575a38 100644
--- a/chromium/content/child/database_util.cc
+++ b/chromium/content/child/database_util.cc
@@ -9,8 +9,8 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/sqlite/sqlite3.h"
-using WebKit::Platform;
-using WebKit::WebString;
+using blink::Platform;
+using blink::WebString;
namespace content {
diff --git a/chromium/content/child/database_util.h b/chromium/content/child/database_util.h
index 8b85623d635..284a147cbfd 100644
--- a/chromium/content/child/database_util.h
+++ b/chromium/content/child/database_util.h
@@ -16,22 +16,22 @@ namespace content {
// WorkerWebKitPlatformSupportImpl to handle database file accesses.
class DatabaseUtil {
public:
- static WebKit::Platform::FileHandle DatabaseOpenFile(
- const WebKit::WebString& vfs_file_name,
+ static blink::Platform::FileHandle DatabaseOpenFile(
+ const blink::WebString& vfs_file_name,
int desired_flags,
IPC::SyncMessageFilter* sync_message_filter);
static int DatabaseDeleteFile(
- const WebKit::WebString& vfs_file_name,
+ const blink::WebString& vfs_file_name,
bool sync_dir,
IPC::SyncMessageFilter* sync_message_filter);
static long DatabaseGetFileAttributes(
- const WebKit::WebString& vfs_file_name,
+ const blink::WebString& vfs_file_name,
IPC::SyncMessageFilter* sync_message_filter);
static long long DatabaseGetFileSize(
- const WebKit::WebString& vfs_file_name,
+ const blink::WebString& vfs_file_name,
IPC::SyncMessageFilter* sync_message_filter);
static long long DatabaseGetSpaceAvailable(
- const WebKit::WebString& origin_identifier,
+ const blink::WebString& origin_identifier,
IPC::SyncMessageFilter* sync_message_filter);
};
diff --git a/chromium/content/child/db_message_filter.cc b/chromium/content/child/db_message_filter.cc
index 6fc8103f7da..f50d080b8d8 100644
--- a/chromium/content/child/db_message_filter.cc
+++ b/chromium/content/child/db_message_filter.cc
@@ -8,7 +8,7 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebDatabase.h"
-using WebKit::WebString;
+using blink::WebString;
namespace content {
@@ -31,29 +31,29 @@ bool DBMessageFilter::OnMessageReceived(const IPC::Message& message) {
}
void DBMessageFilter::OnDatabaseUpdateSize(const std::string& origin_identifier,
- const string16& database_name,
+ const base::string16& database_name,
int64 database_size) {
- WebKit::WebDatabase::updateDatabaseSize(
+ blink::WebDatabase::updateDatabaseSize(
WebString::fromUTF8(origin_identifier), database_name, database_size);
}
void DBMessageFilter::OnDatabaseUpdateSpaceAvailable(
const std::string& origin_identifier,
int64 space_available) {
- WebKit::WebDatabase::updateSpaceAvailable(
+ blink::WebDatabase::updateSpaceAvailable(
WebString::fromUTF8(origin_identifier), space_available);
}
void DBMessageFilter::OnDatabaseResetSpaceAvailable(
const std::string& origin_identifier) {
- WebKit::WebDatabase::resetSpaceAvailable(
+ blink::WebDatabase::resetSpaceAvailable(
WebString::fromUTF8(origin_identifier));
}
void DBMessageFilter::OnDatabaseCloseImmediately(
const std::string& origin_identifier,
- const string16& database_name) {
- WebKit::WebDatabase::closeDatabaseImmediately(
+ const base::string16& database_name) {
+ blink::WebDatabase::closeDatabaseImmediately(
WebString::fromUTF8(origin_identifier), database_name);
}
diff --git a/chromium/content/child/db_message_filter.h b/chromium/content/child/db_message_filter.h
index e918df6c4b6..4950006f4da 100644
--- a/chromium/content/child/db_message_filter.h
+++ b/chromium/content/child/db_message_filter.h
@@ -23,13 +23,13 @@ class DBMessageFilter : public IPC::ChannelProxy::MessageFilter {
private:
void OnDatabaseUpdateSize(const std::string& origin_identifier,
- const string16& database_name,
+ const base::string16& database_name,
int64 database_size);
void OnDatabaseUpdateSpaceAvailable(const std::string& origin_identifier,
int64 space_available);
void OnDatabaseResetSpaceAvailable(const std::string& origin_identifier);
void OnDatabaseCloseImmediately(const std::string& origin_identifier,
- const string16& database_name);
+ const base::string16& database_name);
};
} // namespace content
diff --git a/chromium/content/child/fileapi/OWNERS b/chromium/content/child/fileapi/OWNERS
index 4db30b6cede..76dd015b4ff 100644
--- a/chromium/content/child/fileapi/OWNERS
+++ b/chromium/content/child/fileapi/OWNERS
@@ -9,6 +9,5 @@ per-file *_messages*.h=cdn@chromium.org
per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
per-file *_messages*.h=kenrb@chromium.org
diff --git a/chromium/content/child/fileapi/file_system_dispatcher.cc b/chromium/content/child/fileapi/file_system_dispatcher.cc
index fa73ad118df..8810c03000d 100644
--- a/chromium/content/child/fileapi/file_system_dispatcher.cc
+++ b/chromium/content/child/fileapi/file_system_dispatcher.cc
@@ -181,14 +181,14 @@ bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) {
}
void FileSystemDispatcher::OpenFileSystem(
- const GURL& origin_url, fileapi::FileSystemType type,
- long long size, bool create,
+ const GURL& origin_url,
+ fileapi::FileSystemType type,
const OpenFileSystemCallback& success_callback,
const StatusCallback& error_callback) {
int request_id = dispatchers_.Add(
CallbackDispatcher::Create(success_callback, error_callback));
- ChildThread::current()->Send(new FileSystemHostMsg_Open(
- request_id, origin_url, type, size, create));
+ ChildThread::current()->Send(new FileSystemHostMsg_OpenFileSystem(
+ request_id, origin_url, type));
}
void FileSystemDispatcher::ResolveURL(
@@ -234,7 +234,7 @@ void FileSystemDispatcher::Remove(
const StatusCallback& callback) {
int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
ChildThread::current()->Send(
- new FileSystemMsg_Remove(request_id, path, recursive));
+ new FileSystemHostMsg_Remove(request_id, path, recursive));
}
void FileSystemDispatcher::ReadMetadata(
@@ -351,23 +351,6 @@ void FileSystemDispatcher::TouchFile(
request_id, path, last_access_time, last_modified_time));
}
-void FileSystemDispatcher::OpenPepperFile(
- const GURL& file_path,
- int pp_open_flags,
- const OpenFileCallback& success_callback,
- const StatusCallback& error_callback) {
- int request_id = dispatchers_.Add(
- CallbackDispatcher::Create(success_callback, error_callback));
- ChildThread::current()->Send(
- new FileSystemHostMsg_OpenPepperFile(
- request_id, file_path, pp_open_flags));
-}
-
-void FileSystemDispatcher::NotifyCloseFile(int file_open_id) {
- ChildThread::current()->Send(
- new FileSystemHostMsg_NotifyCloseFile(file_open_id));
-}
-
void FileSystemDispatcher::CreateSnapshotFile(
const GURL& file_path,
const CreateSnapshotFileCallback& success_callback,
diff --git a/chromium/content/child/fileapi/file_system_dispatcher.h b/chromium/content/child/fileapi/file_system_dispatcher.h
index 72ecee668c8..55bb2996523 100644
--- a/chromium/content/child/fileapi/file_system_dispatcher.h
+++ b/chromium/content/child/fileapi/file_system_dispatcher.h
@@ -69,8 +69,6 @@ class FileSystemDispatcher : public IPC::Listener {
void OpenFileSystem(const GURL& origin_url,
fileapi::FileSystemType type,
- long long size,
- bool create,
const OpenFileSystemCallback& success_callback,
const StatusCallback& error_callback);
void ResolveURL(const GURL& filesystem_url,
@@ -128,16 +126,6 @@ class FileSystemDispatcher : public IPC::Listener {
const base::Time& last_modified_time,
const StatusCallback& callback);
- // This returns a raw open PlatformFile, unlike the above, which are
- // self-contained operations.
- void OpenPepperFile(const GURL& file_path,
- int pp_open_flags,
- const OpenFileCallback& success_callback,
- const StatusCallback& error_callback);
- // This must be paired with OpenFile, and called after finished using the
- // raw PlatformFile returned from OpenFile.
- void NotifyCloseFile(int file_open_id);
-
// The caller must send FileSystemHostMsg_DidReceiveSnapshot message
// with |request_id| passed to |success_callback| after the snapshot file
// is successfully received.
diff --git a/chromium/content/child/fileapi/webfilesystem_impl.cc b/chromium/content/child/fileapi/webfilesystem_impl.cc
index ae3be406f29..640c1a90514 100644
--- a/chromium/content/child/fileapi/webfilesystem_impl.cc
+++ b/chromium/content/child/fileapi/webfilesystem_impl.cc
@@ -25,12 +25,12 @@
#include "webkit/common/fileapi/file_system_util.h"
#include "webkit/glue/webkit_glue.h"
-using WebKit::WebFileInfo;
-using WebKit::WebFileSystemCallbacks;
-using WebKit::WebFileSystemEntry;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebVector;
+using blink::WebFileInfo;
+using blink::WebFileSystemCallbacks;
+using blink::WebFileSystemEntry;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebVector;
using webkit_glue::WorkerTaskRunner;
namespace content {
@@ -165,7 +165,7 @@ void ResolveURLCallbackAdapter(
thread_id, callbacks_id, waitable_results,
&WebFileSystemCallbacks::didResolveURL,
MakeTuple(UTF8ToUTF16(info.name), info.root_url,
- static_cast<WebKit::WebFileSystemType>(info.mount_type),
+ static_cast<blink::WebFileSystemType>(info.mount_type),
normalized_path.AsUTF16Unsafe(), is_directory));
}
@@ -214,7 +214,7 @@ void ReadDirectoryCallbackAdapater(
void DidCreateFileWriter(
int callbacks_id,
const GURL& path,
- WebKit::WebFileWriterClient* client,
+ blink::WebFileWriterClient* client,
base::MessageLoopProxy* main_thread_loop,
const base::PlatformFileInfo& file_info) {
WebFileSystemImpl* filesystem =
@@ -226,7 +226,7 @@ void DidCreateFileWriter(
filesystem->GetAndUnregisterCallbacks(callbacks_id);
if (file_info.is_directory || file_info.size < 0) {
- callbacks.didFail(WebKit::WebFileErrorInvalidState);
+ callbacks.didFail(blink::WebFileErrorInvalidState);
return;
}
WebFileWriterImpl::Type type =
@@ -242,7 +242,7 @@ void CreateFileWriterCallbackAdapter(
WaitableCallbackResults* waitable_results,
base::MessageLoopProxy* main_thread_loop,
const GURL& path,
- WebKit::WebFileWriterClient* client,
+ blink::WebFileWriterClient* client,
const base::PlatformFileInfo& file_info) {
DispatchResultsClosure(
thread_id, callbacks_id, waitable_results,
@@ -325,9 +325,8 @@ void WebFileSystemImpl::OnWorkerRunLoopStopped() {
}
void WebFileSystemImpl::openFileSystem(
- const WebKit::WebURL& storage_partition,
- WebKit::WebFileSystemType type,
- bool create,
+ const blink::WebURL& storage_partition,
+ blink::WebFileSystemType type,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -337,7 +336,6 @@ void WebFileSystemImpl::openFileSystem(
&FileSystemDispatcher::OpenFileSystem,
MakeTuple(GURL(storage_partition),
static_cast<fileapi::FileSystemType>(type),
- 0 /* size (not used) */, create,
base::Bind(&OpenFileSystemCallbackAdapter,
CurrentWorkerId(), callbacks_id,
base::Unretained(waitable_results)),
@@ -348,7 +346,7 @@ void WebFileSystemImpl::openFileSystem(
}
void WebFileSystemImpl::resolveURL(
- const WebKit::WebURL& filesystem_url,
+ const blink::WebURL& filesystem_url,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -367,8 +365,8 @@ void WebFileSystemImpl::resolveURL(
}
void WebFileSystemImpl::deleteFileSystem(
- const WebKit::WebURL& storage_partition,
- WebKit::WebFileSystemType type,
+ const blink::WebURL& storage_partition,
+ blink::WebFileSystemType type,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -385,8 +383,8 @@ void WebFileSystemImpl::deleteFileSystem(
}
void WebFileSystemImpl::move(
- const WebKit::WebURL& src_path,
- const WebKit::WebURL& dest_path,
+ const blink::WebURL& src_path,
+ const blink::WebURL& dest_path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -402,8 +400,8 @@ void WebFileSystemImpl::move(
}
void WebFileSystemImpl::copy(
- const WebKit::WebURL& src_path,
- const WebKit::WebURL& dest_path,
+ const blink::WebURL& src_path,
+ const blink::WebURL& dest_path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -419,7 +417,7 @@ void WebFileSystemImpl::copy(
}
void WebFileSystemImpl::remove(
- const WebKit::WebURL& path,
+ const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -435,7 +433,7 @@ void WebFileSystemImpl::remove(
}
void WebFileSystemImpl::removeRecursively(
- const WebKit::WebURL& path,
+ const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -451,7 +449,7 @@ void WebFileSystemImpl::removeRecursively(
}
void WebFileSystemImpl::readMetadata(
- const WebKit::WebURL& path,
+ const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -470,7 +468,7 @@ void WebFileSystemImpl::readMetadata(
}
void WebFileSystemImpl::createFile(
- const WebKit::WebURL& path,
+ const blink::WebURL& path,
bool exclusive,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
@@ -487,7 +485,7 @@ void WebFileSystemImpl::createFile(
}
void WebFileSystemImpl::createDirectory(
- const WebKit::WebURL& path,
+ const blink::WebURL& path,
bool exclusive,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
@@ -504,7 +502,7 @@ void WebFileSystemImpl::createDirectory(
}
void WebFileSystemImpl::fileExists(
- const WebKit::WebURL& path,
+ const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -520,7 +518,7 @@ void WebFileSystemImpl::fileExists(
}
void WebFileSystemImpl::directoryExists(
- const WebKit::WebURL& path,
+ const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -536,7 +534,7 @@ void WebFileSystemImpl::directoryExists(
}
void WebFileSystemImpl::readDirectory(
- const WebKit::WebURL& path,
+ const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -556,7 +554,7 @@ base::Unretained(waitable_results))),
void WebFileSystemImpl::createFileWriter(
const WebURL& path,
- WebKit::WebFileWriterClient* client,
+ blink::WebFileWriterClient* client,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
@@ -576,7 +574,7 @@ void WebFileSystemImpl::createFileWriter(
}
void WebFileSystemImpl::createSnapshotFileAndReadMetadata(
- const WebKit::WebURL& path,
+ const blink::WebURL& path,
WebFileSystemCallbacks callbacks) {
int callbacks_id = RegisterCallbacks(callbacks);
WaitableCallbackResults* waitable_results =
diff --git a/chromium/content/child/fileapi/webfilesystem_impl.h b/chromium/content/child/fileapi/webfilesystem_impl.h
index 8f390ffaadc..d37f9a3165b 100644
--- a/chromium/content/child/fileapi/webfilesystem_impl.h
+++ b/chromium/content/child/fileapi/webfilesystem_impl.h
@@ -18,7 +18,7 @@ namespace base {
class MessageLoopProxy;
}
-namespace WebKit {
+namespace blink {
class WebURL;
class WebFileWriter;
class WebFileWriterClient;
@@ -27,7 +27,7 @@ class WebFileWriterClient;
namespace content {
class WebFileSystemImpl
- : public WebKit::WebFileSystem,
+ : public blink::WebFileSystem,
public webkit_glue::WorkerTaskRunner::Observer,
public base::NonThreadSafe {
public:
@@ -50,65 +50,64 @@ class WebFileSystemImpl
// WebFileSystem implementation.
virtual void openFileSystem(
- const WebKit::WebURL& storage_partition,
- const WebKit::WebFileSystemType type,
- bool create,
- WebKit::WebFileSystemCallbacks);
+ const blink::WebURL& storage_partition,
+ const blink::WebFileSystemType type,
+ blink::WebFileSystemCallbacks);
virtual void resolveURL(
- const WebKit::WebURL& filesystem_url,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ const blink::WebURL& filesystem_url,
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void deleteFileSystem(
- const WebKit::WebURL& storage_partition,
- const WebKit::WebFileSystemType type,
- WebKit::WebFileSystemCallbacks);
+ const blink::WebURL& storage_partition,
+ const blink::WebFileSystemType type,
+ blink::WebFileSystemCallbacks);
virtual void move(
- const WebKit::WebURL& src_path,
- const WebKit::WebURL& dest_path,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ const blink::WebURL& src_path,
+ const blink::WebURL& dest_path,
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void copy(
- const WebKit::WebURL& src_path,
- const WebKit::WebURL& dest_path,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ const blink::WebURL& src_path,
+ const blink::WebURL& dest_path,
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void remove(
- const WebKit::WebURL& path,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ const blink::WebURL& path,
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void removeRecursively(
- const WebKit::WebURL& path,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ const blink::WebURL& path,
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void readMetadata(
- const WebKit::WebURL& path,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ const blink::WebURL& path,
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void createFile(
- const WebKit::WebURL& path,
+ const blink::WebURL& path,
bool exclusive,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void createDirectory(
- const WebKit::WebURL& path,
+ const blink::WebURL& path,
bool exclusive,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void fileExists(
- const WebKit::WebURL& path,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ const blink::WebURL& path,
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void directoryExists(
- const WebKit::WebURL& path,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ const blink::WebURL& path,
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void readDirectory(
- const WebKit::WebURL& path,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ const blink::WebURL& path,
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void createFileWriter(
- const WebKit::WebURL& path,
- WebKit::WebFileWriterClient*,
- WebKit::WebFileSystemCallbacks) OVERRIDE;
+ const blink::WebURL& path,
+ blink::WebFileWriterClient*,
+ blink::WebFileSystemCallbacks) OVERRIDE;
virtual void createSnapshotFileAndReadMetadata(
- const WebKit::WebURL& path,
- WebKit::WebFileSystemCallbacks);
+ const blink::WebURL& path,
+ blink::WebFileSystemCallbacks);
- int RegisterCallbacks(const WebKit::WebFileSystemCallbacks& callbacks);
- WebKit::WebFileSystemCallbacks GetAndUnregisterCallbacks(
+ int RegisterCallbacks(const blink::WebFileSystemCallbacks& callbacks);
+ blink::WebFileSystemCallbacks GetAndUnregisterCallbacks(
int callbacks_id);
private:
- typedef std::map<int, WebKit::WebFileSystemCallbacks> CallbacksMap;
+ typedef std::map<int, blink::WebFileSystemCallbacks> CallbacksMap;
scoped_refptr<base::MessageLoopProxy> main_thread_loop_;
diff --git a/chromium/content/child/fileapi/webfilewriter_base.cc b/chromium/content/child/fileapi/webfilewriter_base.cc
index 705f211cc83..cde644ba867 100644
--- a/chromium/content/child/fileapi/webfilewriter_base.cc
+++ b/chromium/content/child/fileapi/webfilewriter_base.cc
@@ -15,7 +15,7 @@ using fileapi::PlatformFileErrorToWebFileError;
namespace content {
WebFileWriterBase::WebFileWriterBase(const GURL& path,
- WebKit::WebFileWriterClient* client)
+ blink::WebFileWriterClient* client)
: path_(path),
client_(client),
operation_(kOperationNone),
@@ -30,17 +30,9 @@ void WebFileWriterBase::truncate(long long length) {
DoTruncate(path_, length);
}
-void WebFileWriterBase::write(long long position,
- const WebKit::WebURL& blob_url) {
- DCHECK_EQ(kOperationNone, operation_);
- DCHECK_EQ(kCancelNotInProgress, cancel_state_);
- operation_ = kOperationWrite;
- DoWriteDeprecated(path_, blob_url, position);
-}
-
void WebFileWriterBase::write(
long long position,
- const WebKit::WebString& id) {
+ const blink::WebString& id) {
DCHECK_EQ(kOperationNone, operation_);
DCHECK_EQ(kCancelNotInProgress, cancel_state_);
operation_ = kOperationWrite;
@@ -155,7 +147,7 @@ void WebFileWriterBase::FinishCancel() {
DCHECK(kOperationNone != operation_);
cancel_state_ = kCancelNotInProgress;
operation_ = kOperationNone;
- client_->didFail(WebKit::WebFileErrorAbort);
+ client_->didFail(blink::WebFileErrorAbort);
}
} // namespace content
diff --git a/chromium/content/child/fileapi/webfilewriter_base.h b/chromium/content/child/fileapi/webfilewriter_base.h
index 415d286c7f7..5168e3cf545 100644
--- a/chromium/content/child/fileapi/webfilewriter_base.h
+++ b/chromium/content/child/fileapi/webfilewriter_base.h
@@ -10,7 +10,7 @@
#include "third_party/WebKit/public/platform/WebFileWriter.h"
#include "url/gurl.h"
-namespace WebKit {
+namespace blink {
class WebFileWriterClient;
class WebURL;
}
@@ -18,19 +18,16 @@ class WebURL;
namespace content {
class CONTENT_EXPORT WebFileWriterBase
- : public NON_EXPORTED_BASE(WebKit::WebFileWriter) {
+ : public NON_EXPORTED_BASE(blink::WebFileWriter) {
public:
- WebFileWriterBase(const GURL& path, WebKit::WebFileWriterClient* client);
+ WebFileWriterBase(const GURL& path, blink::WebFileWriterClient* client);
virtual ~WebFileWriterBase();
// WebFileWriter implementation
virtual void truncate(long long length);
- virtual void write(long long position, const WebKit::WebString& id);
+ virtual void write(long long position, const blink::WebString& id);
virtual void cancel();
- // DEPRECATED: see crbug/174200
- virtual void write(long long position, const WebKit::WebURL& blobURL);
-
protected:
// This calls DidSucceed() or DidFail() based on the value of |error_code|.
void DidFinish(base::PlatformFileError error_code);
@@ -43,9 +40,6 @@ class CONTENT_EXPORT WebFileWriterBase
// the requested operation, and they must call the appropiate DidSomething
// method upon completion and as progress is made in the Write case.
virtual void DoTruncate(const GURL& path, int64 offset) = 0;
- virtual void DoWriteDeprecated(const GURL& path,
- const GURL& blob_url,
- int64 offset) = 0;
virtual void DoWrite(const GURL& path,
const std::string& blob_id,
int64 offset) = 0;
@@ -67,7 +61,7 @@ class CONTENT_EXPORT WebFileWriterBase
void FinishCancel();
GURL path_;
- WebKit::WebFileWriterClient* client_;
+ blink::WebFileWriterClient* client_;
OperationType operation_;
CancelState cancel_state_;
};
diff --git a/chromium/content/child/fileapi/webfilewriter_base_unittest.cc b/chromium/content/child/fileapi/webfilewriter_base_unittest.cc
index 329665a189b..95e0ba5fd34 100644
--- a/chromium/content/child/fileapi/webfilewriter_base_unittest.cc
+++ b/chromium/content/child/fileapi/webfilewriter_base_unittest.cc
@@ -39,7 +39,7 @@ GURL mock_path_as_gurl() {
class TestableFileWriter : public WebFileWriterBase {
public:
- explicit TestableFileWriter(WebKit::WebFileWriterClient* client)
+ explicit TestableFileWriter(blink::WebFileWriterClient* client)
: WebFileWriterBase(mock_path_as_gurl(), client) {
reset();
}
@@ -51,7 +51,6 @@ class TestableFileWriter : public WebFileWriterBase {
received_write_ = false;
received_write_path_ = GURL();
received_write_offset_ = kNoOffset;
- received_write_blob_url_ = GURL();
received_write_blob_uuid_ = std::string();
received_cancel_ = false;
}
@@ -61,7 +60,6 @@ class TestableFileWriter : public WebFileWriterBase {
int64 received_truncate_offset_;
bool received_write_;
GURL received_write_path_;
- GURL received_write_blob_url_;
std::string received_write_blob_uuid_;
int64 received_write_offset_;
bool received_cancel_;
@@ -89,41 +87,6 @@ class TestableFileWriter : public WebFileWriterBase {
}
}
- virtual void DoWriteDeprecated(
- const GURL& path, const GURL& blob_url,
- int64 offset) OVERRIDE {
- received_write_ = true;
- received_write_path_ = path;
- received_write_offset_ = offset;
- received_write_blob_url_ = blob_url;
-
- if (offset == kBasicFileWrite_Offset) {
- DidWrite(1, true);
- } else if (offset == kErrorFileWrite_Offset) {
- DidFail(base::PLATFORM_FILE_ERROR_NOT_FOUND);
- } else if (offset == kMultiFileWrite_Offset) {
- DidWrite(1, false);
- DidWrite(1, false);
- DidWrite(1, true);
- } else if (offset == kCancelFileWriteBeforeCompletion_Offset) {
- DidWrite(1, false);
- cancel();
- DidWrite(1, false);
- DidWrite(1, false);
- DidFail(base::PLATFORM_FILE_ERROR_FAILED); // write completion
- DidSucceed(); // cancel completion
- } else if (offset == kCancelFileWriteAfterCompletion_Offset) {
- DidWrite(1, false);
- cancel();
- DidWrite(1, false);
- DidWrite(1, false);
- DidWrite(1, true); // write completion
- DidFail(base::PLATFORM_FILE_ERROR_FAILED); // cancel completion
- } else {
- FAIL();
- }
- }
-
virtual void DoWrite(
const GURL& path, const std::string& blob_uuid,
int64 offset) OVERRIDE {
@@ -165,13 +128,13 @@ class TestableFileWriter : public WebFileWriterBase {
};
class FileWriterTest : public testing::Test,
- public WebKit::WebFileWriterClient {
+ public blink::WebFileWriterClient {
public:
FileWriterTest() {
reset();
}
- WebKit::WebFileWriter* writer() {
+ blink::WebFileWriter* writer() {
return testable_writer_.get();
}
@@ -194,7 +157,7 @@ class FileWriterTest : public testing::Test,
testable_writer_.reset(NULL);
}
- virtual void didFail(WebKit::WebFileError error) {
+ virtual void didFail(blink::WebFileError error) {
EXPECT_FALSE(received_did_fail_);
received_did_fail_ = true;
fail_error_received_ = error;
@@ -211,7 +174,7 @@ class FileWriterTest : public testing::Test,
received_did_write_complete_ = false;
received_did_truncate_ = false;
received_did_fail_ = false;
- fail_error_received_ = static_cast<WebKit::WebFileError>(0);
+ fail_error_received_ = static_cast<blink::WebFileError>(0);
}
scoped_ptr<TestableFileWriter> testable_writer_;
@@ -223,18 +186,16 @@ class FileWriterTest : public testing::Test,
bool received_did_write_complete_;
bool received_did_truncate_;
bool received_did_fail_;
- WebKit::WebFileError fail_error_received_;
+ blink::WebFileError fail_error_received_;
DISALLOW_COPY_AND_ASSIGN(FileWriterTest);
};
-
-// TODO(michaeln): crbug/174200, update the tests once blink is migrated.
-
TEST_F(FileWriterTest, BasicFileWrite) {
// Call the webkit facing api.
- const GURL kBlobUrl("blob://bloburl/");
- writer()->write(kBasicFileWrite_Offset, kBlobUrl);
+ const std::string kBlobId("1234");
+ writer()->write(kBasicFileWrite_Offset,
+ blink::WebString::fromUTF8(kBlobId));
// Check that the derived class gets called correctly.
EXPECT_TRUE(testable_writer_->received_write_);
@@ -242,7 +203,7 @@ TEST_F(FileWriterTest, BasicFileWrite) {
mock_path_as_gurl());
EXPECT_EQ(kBasicFileWrite_Offset,
testable_writer_->received_write_offset_);
- EXPECT_EQ(kBlobUrl, testable_writer_->received_write_blob_url_);
+ EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_);
EXPECT_FALSE(testable_writer_->received_truncate_);
EXPECT_FALSE(testable_writer_->received_cancel_);
@@ -275,8 +236,9 @@ TEST_F(FileWriterTest, BasicFileTruncate) {
TEST_F(FileWriterTest, ErrorFileWrite) {
// Call the webkit facing api.
- const GURL kBlobUrl("blob://bloburl/");
- writer()->write(kErrorFileWrite_Offset, kBlobUrl);
+ const std::string kBlobId("1234");
+ writer()->write(kErrorFileWrite_Offset,
+ blink::WebString::fromUTF8(kBlobId));
// Check that the derived class gets called correctly.
EXPECT_TRUE(testable_writer_->received_write_);
@@ -284,13 +246,13 @@ TEST_F(FileWriterTest, ErrorFileWrite) {
mock_path_as_gurl());
EXPECT_EQ(kErrorFileWrite_Offset,
testable_writer_->received_write_offset_);
- EXPECT_EQ(kBlobUrl, testable_writer_->received_write_blob_url_);
+ EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_);
EXPECT_FALSE(testable_writer_->received_truncate_);
EXPECT_FALSE(testable_writer_->received_cancel_);
// Check that the client gets called correctly.
EXPECT_TRUE(received_did_fail_);
- EXPECT_EQ(WebKit::WebFileErrorNotFound, fail_error_received_);
+ EXPECT_EQ(blink::WebFileErrorNotFound, fail_error_received_);
EXPECT_EQ(0, received_did_write_count_);
EXPECT_FALSE(received_did_truncate_);
}
@@ -310,15 +272,16 @@ TEST_F(FileWriterTest, ErrorFileTruncate) {
// Check that the client gets called correctly.
EXPECT_TRUE(received_did_fail_);
- EXPECT_EQ(WebKit::WebFileErrorNotFound, fail_error_received_);
+ EXPECT_EQ(blink::WebFileErrorNotFound, fail_error_received_);
EXPECT_FALSE(received_did_truncate_);
EXPECT_EQ(0, received_did_write_count_);
}
TEST_F(FileWriterTest, MultiFileWrite) {
// Call the webkit facing api.
- const GURL kBlobUrl("blob://bloburl/");
- writer()->write(kMultiFileWrite_Offset, kBlobUrl);
+ const std::string kBlobId("1234");
+ writer()->write(kMultiFileWrite_Offset,
+ blink::WebString::fromUTF8(kBlobId));
// Check that the derived class gets called correctly.
EXPECT_TRUE(testable_writer_->received_write_);
@@ -326,7 +289,7 @@ TEST_F(FileWriterTest, MultiFileWrite) {
mock_path_as_gurl());
EXPECT_EQ(kMultiFileWrite_Offset,
testable_writer_->received_write_offset_);
- EXPECT_EQ(kBlobUrl, testable_writer_->received_write_blob_url_);
+ EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_);
EXPECT_FALSE(testable_writer_->received_truncate_);
EXPECT_FALSE(testable_writer_->received_cancel_);
@@ -340,8 +303,9 @@ TEST_F(FileWriterTest, MultiFileWrite) {
TEST_F(FileWriterTest, CancelFileWriteBeforeCompletion) {
// Call the webkit facing api.
- const GURL kBlobUrl("blob://bloburl/");
- writer()->write(kCancelFileWriteBeforeCompletion_Offset, kBlobUrl);
+ const std::string kBlobId("1234");
+ writer()->write(kCancelFileWriteBeforeCompletion_Offset,
+ blink::WebString::fromUTF8(kBlobId));
// Check that the derived class gets called correctly.
EXPECT_TRUE(testable_writer_->received_write_);
@@ -349,13 +313,13 @@ TEST_F(FileWriterTest, CancelFileWriteBeforeCompletion) {
mock_path_as_gurl());
EXPECT_EQ(kCancelFileWriteBeforeCompletion_Offset,
testable_writer_->received_write_offset_);
- EXPECT_EQ(kBlobUrl, testable_writer_->received_write_blob_url_);
+ EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_);
EXPECT_TRUE(testable_writer_->received_cancel_);
EXPECT_FALSE(testable_writer_->received_truncate_);
// Check that the client gets called correctly.
EXPECT_TRUE(received_did_fail_);
- EXPECT_EQ(WebKit::WebFileErrorAbort, fail_error_received_);
+ EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_);
EXPECT_EQ(1, received_did_write_count_);
EXPECT_FALSE(received_did_write_complete_);
EXPECT_EQ(1, received_did_write_bytes_total_);
@@ -364,8 +328,9 @@ TEST_F(FileWriterTest, CancelFileWriteBeforeCompletion) {
TEST_F(FileWriterTest, CancelFileWriteAfterCompletion) {
// Call the webkit facing api.
- const GURL kBlobUrl("blob://bloburl/");
- writer()->write(kCancelFileWriteAfterCompletion_Offset, kBlobUrl);
+ const std::string kBlobId("1234");
+ writer()->write(kCancelFileWriteAfterCompletion_Offset,
+ blink::WebString::fromUTF8(kBlobId));
// Check that the derived class gets called correctly.
EXPECT_TRUE(testable_writer_->received_write_);
@@ -373,13 +338,13 @@ TEST_F(FileWriterTest, CancelFileWriteAfterCompletion) {
mock_path_as_gurl());
EXPECT_EQ(kCancelFileWriteAfterCompletion_Offset,
testable_writer_->received_write_offset_);
- EXPECT_EQ(kBlobUrl, testable_writer_->received_write_blob_url_);
+ EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_);
EXPECT_TRUE(testable_writer_->received_cancel_);
EXPECT_FALSE(testable_writer_->received_truncate_);
// Check that the client gets called correctly.
EXPECT_TRUE(received_did_fail_);
- EXPECT_EQ(WebKit::WebFileErrorAbort, fail_error_received_);
+ EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_);
EXPECT_EQ(1, received_did_write_count_);
EXPECT_FALSE(received_did_write_complete_);
EXPECT_EQ(1, received_did_write_bytes_total_);
@@ -401,7 +366,7 @@ TEST_F(FileWriterTest, CancelFileTruncate) {
// Check that the client gets called correctly.
EXPECT_TRUE(received_did_fail_);
- EXPECT_EQ(WebKit::WebFileErrorAbort, fail_error_received_);
+ EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_);
EXPECT_FALSE(received_did_truncate_);
EXPECT_EQ(0, received_did_write_count_);
}
@@ -421,14 +386,16 @@ TEST_F(FileWriterTest, CancelFailedTruncate) {
// Check that the client gets called correctly.
EXPECT_TRUE(received_did_fail_);
- EXPECT_EQ(WebKit::WebFileErrorAbort, fail_error_received_);
+ EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_);
EXPECT_FALSE(received_did_truncate_);
EXPECT_EQ(0, received_did_write_count_);
}
TEST_F(FileWriterTest, DeleteInCompletionCallbacks) {
+ const std::string kBlobId("1234");
delete_in_client_callback_ = true;
- writer()->write(kBasicFileWrite_Offset, GURL("blob://bloburl/"));
+ writer()->write(kBasicFileWrite_Offset,
+ blink::WebString::fromUTF8(kBlobId));
EXPECT_FALSE(testable_writer_.get());
reset();
@@ -438,7 +405,8 @@ TEST_F(FileWriterTest, DeleteInCompletionCallbacks) {
reset();
delete_in_client_callback_ = true;
- writer()->write(kErrorFileWrite_Offset, GURL("blob://bloburl/"));
+ writer()->write(kErrorFileWrite_Offset,
+ blink::WebString::fromUTF8(kBlobId));
EXPECT_FALSE(testable_writer_.get());
reset();
diff --git a/chromium/content/child/fileapi/webfilewriter_impl.cc b/chromium/content/child/fileapi/webfilewriter_impl.cc
index bcdc0d2b9f8..7077e9a220b 100644
--- a/chromium/content/child/fileapi/webfilewriter_impl.cc
+++ b/chromium/content/child/fileapi/webfilewriter_impl.cc
@@ -50,20 +50,6 @@ class WebFileWriterImpl::WriterBridge
base::Bind(&WriterBridge::DidFinish, this));
}
- void WriteDeprecated(
- const GURL& path, const GURL& blob_url, int64 offset,
- const WriteCallback& write_callback,
- const StatusCallback& error_callback) {
- write_callback_ = write_callback;
- status_callback_ = error_callback;
- if (!GetFileSystemDispatcher())
- return;
- ChildThread::current()->file_system_dispatcher()->WriteDeprecated(
- path, blob_url, offset, &request_id_,
- base::Bind(&WriterBridge::DidWrite, this),
- base::Bind(&WriterBridge::DidFinish, this));
- }
-
void Write(const GURL& path, const std::string& id, int64 offset,
const WriteCallback& write_callback,
const StatusCallback& error_callback) {
@@ -136,7 +122,7 @@ class WebFileWriterImpl::WriterBridge
};
WebFileWriterImpl::WebFileWriterImpl(
- const GURL& path, WebKit::WebFileWriterClient* client,
+ const GURL& path, blink::WebFileWriterClient* client,
Type type,
base::MessageLoopProxy* main_thread_loop)
: WebFileWriterBase(path, client),
@@ -153,14 +139,6 @@ void WebFileWriterImpl::DoTruncate(const GURL& path, int64 offset) {
base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr())));
}
-void WebFileWriterImpl::DoWriteDeprecated(
- const GURL& path, const GURL& blob_url, int64 offset) {
- RunOnMainThread(base::Bind(&WriterBridge::WriteDeprecated, bridge_,
- path, blob_url, offset,
- base::Bind(&WebFileWriterImpl::DidWrite, AsWeakPtr()),
- base::Bind(&WebFileWriterImpl::DidFinish, AsWeakPtr())));
-}
-
void WebFileWriterImpl::DoWrite(
const GURL& path, const std::string& blob_id, int64 offset) {
RunOnMainThread(base::Bind(&WriterBridge::Write, bridge_,
diff --git a/chromium/content/child/fileapi/webfilewriter_impl.h b/chromium/content/child/fileapi/webfilewriter_impl.h
index c4a59956121..34f63bd3fb1 100644
--- a/chromium/content/child/fileapi/webfilewriter_impl.h
+++ b/chromium/content/child/fileapi/webfilewriter_impl.h
@@ -24,7 +24,7 @@ class WebFileWriterImpl : public WebFileWriterBase,
};
WebFileWriterImpl(const GURL& path,
- WebKit::WebFileWriterClient* client,
+ blink::WebFileWriterClient* client,
Type type,
base::MessageLoopProxy* main_thread_loop);
virtual ~WebFileWriterImpl();
@@ -32,8 +32,6 @@ class WebFileWriterImpl : public WebFileWriterBase,
protected:
// WebFileWriterBase overrides
virtual void DoTruncate(const GURL& path, int64 offset) OVERRIDE;
- virtual void DoWriteDeprecated(
- const GURL& path, const GURL& blob_url, int64 offset) OVERRIDE;
virtual void DoWrite(const GURL& path, const std::string& blob_id,
int64 offset) OVERRIDE;
virtual void DoCancel() OVERRIDE;
diff --git a/chromium/content/child/image_decoder.cc b/chromium/content/child/image_decoder.cc
index c5043bec0d8..333395eaeb3 100644
--- a/chromium/content/child/image_decoder.cc
+++ b/chromium/content/child/image_decoder.cc
@@ -10,8 +10,8 @@
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/skia/include/core/SkBitmap.h"
-using WebKit::WebData;
-using WebKit::WebImage;
+using blink::WebData;
+using blink::WebImage;
namespace content {
@@ -41,7 +41,7 @@ SkBitmap ImageDecoder::Decode(const unsigned char* data, size_t size) const {
// static
std::vector<SkBitmap> ImageDecoder::DecodeAll(
const unsigned char* data, size_t size) {
- const WebKit::WebVector<WebImage>& images = WebImage::framesFromData(
+ const blink::WebVector<WebImage>& images = WebImage::framesFromData(
WebData(reinterpret_cast<const char*>(data), size));
std::vector<SkBitmap> result;
for (size_t i = 0; i < images.size(); ++i)
diff --git a/chromium/content/child/indexed_db/indexed_db_dispatcher.cc b/chromium/content/child/indexed_db/indexed_db_dispatcher.cc
index 9e92b711c65..1f242fcd7aa 100644
--- a/chromium/content/child/indexed_db/indexed_db_dispatcher.cc
+++ b/chromium/content/child/indexed_db/indexed_db_dispatcher.cc
@@ -9,24 +9,25 @@
#include "base/strings/stringprintf.h"
#include "base/threading/thread_local.h"
#include "content/child/indexed_db/indexed_db_key_builders.h"
-#include "content/child/indexed_db/proxy_webidbcursor_impl.h"
-#include "content/child/indexed_db/proxy_webidbdatabase_impl.h"
+#include "content/child/indexed_db/webidbcursor_impl.h"
+#include "content/child/indexed_db/webidbdatabase_impl.h"
#include "content/child/thread_safe_sender.h"
+#include "content/common/indexed_db/indexed_db_constants.h"
#include "content/common/indexed_db/indexed_db_messages.h"
#include "ipc/ipc_channel.h"
#include "third_party/WebKit/public/platform/WebIDBDatabaseCallbacks.h"
#include "third_party/WebKit/public/platform/WebIDBDatabaseError.h"
#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
-using WebKit::WebData;
-using WebKit::WebIDBCallbacks;
-using WebKit::WebIDBDatabase;
-using WebKit::WebIDBDatabaseCallbacks;
-using WebKit::WebIDBDatabaseError;
-using WebKit::WebIDBKey;
-using WebKit::WebIDBMetadata;
-using WebKit::WebString;
-using WebKit::WebVector;
+using blink::WebData;
+using blink::WebIDBCallbacks;
+using blink::WebIDBDatabase;
+using blink::WebIDBDatabaseCallbacks;
+using blink::WebIDBDatabaseError;
+using blink::WebIDBKey;
+using blink::WebIDBMetadata;
+using blink::WebString;
+using blink::WebVector;
using base::ThreadLocalPointer;
using webkit_glue::WorkerTaskRunner;
@@ -39,9 +40,6 @@ namespace {
IndexedDBDispatcher* const kHasBeenDeleted =
reinterpret_cast<IndexedDBDispatcher*>(0x1);
-int32 CurrentWorkerId() {
- return WorkerTaskRunner::Instance()->CurrentWorkerId();
-}
} // unnamed namespace
const size_t kMaxIDBValueSizeInBytes = 64 * 1024 * 1024;
@@ -183,6 +181,7 @@ void IndexedDBDispatcher::RequestIDBCursorAdvance(
void IndexedDBDispatcher::RequestIDBCursorContinue(
const IndexedDBKey& key,
+ const IndexedDBKey& primary_key,
WebIDBCallbacks* callbacks_ptr,
int32 ipc_cursor_id) {
// Reset all cursor prefetch caches except for this cursor.
@@ -192,7 +191,7 @@ void IndexedDBDispatcher::RequestIDBCursorContinue(
int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
Send(new IndexedDBHostMsg_CursorContinue(
- ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, key));
+ ipc_cursor_id, CurrentWorkerId(), ipc_callbacks_id, key, primary_key));
}
void IndexedDBDispatcher::RequestIDBCursorPrefetch(
@@ -214,7 +213,7 @@ void IndexedDBDispatcher::RequestIDBCursorPrefetchReset(int used_prefetches,
}
void IndexedDBDispatcher::RequestIDBFactoryOpen(
- const string16& name,
+ const base::string16& name,
int64 version,
int64 transaction_id,
WebIDBCallbacks* callbacks_ptr,
@@ -251,7 +250,7 @@ void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
}
void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
- const string16& name,
+ const base::string16& name,
WebIDBCallbacks* callbacks_ptr,
const std::string& database_identifier) {
ResetCursorPrefetchCaches();
@@ -331,7 +330,7 @@ void IndexedDBDispatcher::RequestIDBDatabasePut(
if (value.size() > kMaxIDBValueSizeInBytes) {
callbacks->onError(WebIDBDatabaseError(
- WebKit::WebIDBDatabaseExceptionUnknownError,
+ blink::WebIDBDatabaseExceptionUnknownError,
WebString::fromUTF8(base::StringPrintf(
"The serialized value is too large"
" (size=%" PRIuS " bytes, max=%" PRIuS " bytes).",
@@ -460,11 +459,17 @@ void IndexedDBDispatcher::OnSuccessIDBDatabase(
return;
WebIDBMetadata metadata(ConvertMetadata(idb_metadata));
// If an upgrade was performed, count will be non-zero.
- if (!databases_.count(ipc_object_id))
- databases_[ipc_object_id] = new RendererWebIDBDatabaseImpl(
+ WebIDBDatabase* database = NULL;
+
+ // Back-end will send kNoDatabase if it was already sent in OnUpgradeNeeded.
+ // May already be deleted and removed from the table, but do not recreate..
+ if (ipc_object_id != kNoDatabase) {
+ DCHECK(!databases_.count(ipc_object_id));
+ database = databases_[ipc_object_id] = new WebIDBDatabaseImpl(
ipc_object_id, ipc_database_callbacks_id, thread_safe_sender_.get());
- DCHECK_EQ(databases_.count(ipc_object_id), 1u);
- callbacks->onSuccess(databases_[ipc_object_id], metadata);
+ }
+
+ callbacks->onSuccess(database, metadata);
pending_callbacks_.Remove(ipc_callbacks_id);
}
@@ -482,7 +487,7 @@ void IndexedDBDispatcher::OnSuccessIndexedDBKey(int32 ipc_thread_id,
void IndexedDBDispatcher::OnSuccessStringList(
int32 ipc_thread_id,
int32 ipc_callbacks_id,
- const std::vector<string16>& value) {
+ const std::vector<base::string16>& value) {
DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
if (!callbacks)
@@ -560,8 +565,8 @@ void IndexedDBDispatcher::OnSuccessOpenCursor(
if (!callbacks)
return;
- RendererWebIDBCursorImpl* cursor =
- new RendererWebIDBCursorImpl(ipc_object_id, thread_safe_sender_.get());
+ WebIDBCursorImpl* cursor =
+ new WebIDBCursorImpl(ipc_object_id, thread_safe_sender_.get());
cursors_[ipc_object_id] = cursor;
callbacks->onSuccess(cursor, WebIDBKeyBuilder::Build(key),
WebIDBKeyBuilder::Build(primary_key), web_value);
@@ -578,7 +583,7 @@ void IndexedDBDispatcher::OnSuccessCursorContinue(
const IndexedDBKey& primary_key = p.primary_key;
const std::string& value = p.value;
- RendererWebIDBCursorImpl* cursor = cursors_[ipc_cursor_id];
+ WebIDBCursorImpl* cursor = cursors_[ipc_cursor_id];
DCHECK(cursor);
WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
@@ -606,7 +611,7 @@ void IndexedDBDispatcher::OnSuccessCursorPrefetch(
if (p.values[i].size())
values[i].assign(&*p.values[i].begin(), p.values[i].size());
}
- RendererWebIDBCursorImpl* cursor = cursors_[ipc_cursor_id];
+ WebIDBCursorImpl* cursor = cursors_[ipc_cursor_id];
DCHECK(cursor);
cursor->SetPrefetchData(keys, primary_keys, values);
@@ -633,20 +638,21 @@ void IndexedDBDispatcher::OnUpgradeNeeded(
WebIDBMetadata metadata(ConvertMetadata(p.idb_metadata));
DCHECK(!databases_.count(p.ipc_database_id));
databases_[p.ipc_database_id] =
- new RendererWebIDBDatabaseImpl(p.ipc_database_id,
- p.ipc_database_callbacks_id,
- thread_safe_sender_.get());
+ new WebIDBDatabaseImpl(p.ipc_database_id,
+ p.ipc_database_callbacks_id,
+ thread_safe_sender_.get());
callbacks->onUpgradeNeeded(
p.old_version,
databases_[p.ipc_database_id],
metadata,
- static_cast<WebIDBCallbacks::DataLoss>(p.data_loss));
+ static_cast<blink::WebIDBDataLoss>(p.data_loss),
+ WebString::fromUTF8(p.data_loss_message));
}
void IndexedDBDispatcher::OnError(int32 ipc_thread_id,
int32 ipc_callbacks_id,
int code,
- const string16& message) {
+ const base::string16& message) {
DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
if (!callbacks)
@@ -662,7 +668,7 @@ void IndexedDBDispatcher::OnAbort(int32 ipc_thread_id,
int32 ipc_database_callbacks_id,
int64 transaction_id,
int code,
- const string16& message) {
+ const base::string16& message) {
DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
WebIDBDatabaseCallbacks* callbacks =
pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
@@ -711,7 +717,7 @@ void IndexedDBDispatcher::OnIntVersionChange(int32 ipc_thread_id,
void IndexedDBDispatcher::ResetCursorPrefetchCaches(
int32 ipc_exception_cursor_id) {
- typedef std::map<int32, RendererWebIDBCursorImpl*>::iterator Iterator;
+ typedef std::map<int32, WebIDBCursorImpl*>::iterator Iterator;
for (Iterator i = cursors_.begin(); i != cursors_.end(); ++i) {
if (i->first == ipc_exception_cursor_id)
continue;
diff --git a/chromium/content/child/indexed_db/indexed_db_dispatcher.h b/chromium/content/child/indexed_db/indexed_db_dispatcher.h
index 686461f0073..5baf565ec26 100644
--- a/chromium/content/child/indexed_db/indexed_db_dispatcher.h
+++ b/chromium/content/child/indexed_db/indexed_db_dispatcher.h
@@ -26,7 +26,7 @@ struct IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params;
struct IndexedDBMsg_CallbacksSuccessIDBCursor_Params;
struct IndexedDBMsg_CallbacksUpgradeNeeded_Params;
-namespace WebKit {
+namespace blink {
class WebData;
}
@@ -34,8 +34,8 @@ namespace content {
class IndexedDBKey;
class IndexedDBKeyPath;
class IndexedDBKeyRange;
-class RendererWebIDBCursorImpl;
-class RendererWebIDBDatabaseImpl;
+class WebIDBCursorImpl;
+class WebIDBDatabaseImpl;
class ThreadSafeSender;
CONTENT_EXPORT extern const size_t kMaxIDBValueSizeInBytes;
@@ -60,38 +60,39 @@ class CONTENT_EXPORT IndexedDBDispatcher
// webkit_glue::WorkerTaskRunner::Observer implementation.
virtual void OnWorkerRunLoopStopped() OVERRIDE;
- static WebKit::WebIDBMetadata ConvertMetadata(
+ static blink::WebIDBMetadata ConvertMetadata(
const IndexedDBDatabaseMetadata& idb_metadata);
void OnMessageReceived(const IPC::Message& msg);
bool Send(IPC::Message* msg);
void RequestIDBFactoryGetDatabaseNames(
- WebKit::WebIDBCallbacks* callbacks,
+ blink::WebIDBCallbacks* callbacks,
const std::string& database_identifier);
void RequestIDBFactoryOpen(
- const string16& name,
+ const base::string16& name,
int64 version,
int64 transaction_id,
- WebKit::WebIDBCallbacks* callbacks,
- WebKit::WebIDBDatabaseCallbacks* database_callbacks,
+ blink::WebIDBCallbacks* callbacks,
+ blink::WebIDBDatabaseCallbacks* database_callbacks,
const std::string& database_identifier);
- void RequestIDBFactoryDeleteDatabase(const string16& name,
- WebKit::WebIDBCallbacks* callbacks,
+ void RequestIDBFactoryDeleteDatabase(const base::string16& name,
+ blink::WebIDBCallbacks* callbacks,
const std::string& database_identifier);
void RequestIDBCursorAdvance(unsigned long count,
- WebKit::WebIDBCallbacks* callbacks_ptr,
+ blink::WebIDBCallbacks* callbacks_ptr,
int32 ipc_cursor_id);
virtual void RequestIDBCursorContinue(const IndexedDBKey& key,
- WebKit::WebIDBCallbacks* callbacks_ptr,
+ const IndexedDBKey& primary_key,
+ blink::WebIDBCallbacks* callbacks_ptr,
int32 ipc_cursor_id);
virtual void RequestIDBCursorPrefetch(int n,
- WebKit::WebIDBCallbacks* callbacks_ptr,
+ blink::WebIDBCallbacks* callbacks_ptr,
int32 ipc_cursor_id);
void RequestIDBCursorPrefetchReset(int used_prefetches,
@@ -104,8 +105,8 @@ class CONTENT_EXPORT IndexedDBDispatcher
void RequestIDBDatabaseCreateTransaction(
int32 ipc_database_id,
int64 transaction_id,
- WebKit::WebIDBDatabaseCallbacks* database_callbacks_ptr,
- WebKit::WebVector<long long> object_store_ids,
+ blink::WebIDBDatabaseCallbacks* database_callbacks_ptr,
+ blink::WebVector<long long> object_store_ids,
unsigned short mode);
void RequestIDBDatabaseGet(int32 ipc_database_id,
@@ -114,18 +115,18 @@ class CONTENT_EXPORT IndexedDBDispatcher
int64 index_id,
const IndexedDBKeyRange& key_range,
bool key_only,
- WebKit::WebIDBCallbacks* callbacks);
+ blink::WebIDBCallbacks* callbacks);
void RequestIDBDatabasePut(
int32 ipc_database_id,
int64 transaction_id,
int64 object_store_id,
- const WebKit::WebData& value,
+ const blink::WebData& value,
const IndexedDBKey& key,
- WebKit::WebIDBDatabase::PutMode put_mode,
- WebKit::WebIDBCallbacks* callbacks,
- const WebKit::WebVector<long long>& index_ids,
- const WebKit::WebVector<WebKit::WebVector<WebKit::WebIDBKey> >&
+ blink::WebIDBDatabase::PutMode put_mode,
+ blink::WebIDBCallbacks* callbacks,
+ const blink::WebVector<long long>& index_ids,
+ const blink::WebVector<blink::WebVector<blink::WebIDBKey> >&
index_keys);
void RequestIDBDatabaseOpenCursor(int32 ipc_database_id,
@@ -135,26 +136,26 @@ class CONTENT_EXPORT IndexedDBDispatcher
const IndexedDBKeyRange& key_range,
unsigned short direction,
bool key_only,
- WebKit::WebIDBDatabase::TaskType task_type,
- WebKit::WebIDBCallbacks* callbacks);
+ blink::WebIDBDatabase::TaskType task_type,
+ blink::WebIDBCallbacks* callbacks);
void RequestIDBDatabaseCount(int32 ipc_database_id,
int64 transaction_id,
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& key_range,
- WebKit::WebIDBCallbacks* callbacks);
+ blink::WebIDBCallbacks* callbacks);
void RequestIDBDatabaseDeleteRange(int32 ipc_database_id,
int64 transaction_id,
int64 object_store_id,
const IndexedDBKeyRange& key_range,
- WebKit::WebIDBCallbacks* callbacks);
+ blink::WebIDBCallbacks* callbacks);
void RequestIDBDatabaseClear(int32 ipc_database_id,
int64 transaction_id,
int64 object_store_id,
- WebKit::WebIDBCallbacks* callbacks);
+ blink::WebIDBCallbacks* callbacks);
virtual void CursorDestroyed(int32 ipc_cursor_id);
void DatabaseDestroyed(int32 ipc_database_id);
@@ -167,8 +168,8 @@ class CONTENT_EXPORT IndexedDBDispatcher
}
template <typename T>
- void init_params(T& params, WebKit::WebIDBCallbacks* callbacks_ptr) {
- scoped_ptr<WebKit::WebIDBCallbacks> callbacks(callbacks_ptr);
+ void init_params(T& params, blink::WebIDBCallbacks* callbacks_ptr) {
+ scoped_ptr<blink::WebIDBCallbacks> callbacks(callbacks_ptr);
params.ipc_thread_id = CurrentWorkerId();
params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
}
@@ -191,7 +192,7 @@ class CONTENT_EXPORT IndexedDBDispatcher
const IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params& p);
void OnSuccessStringList(int32 ipc_thread_id,
int32 ipc_callbacks_id,
- const std::vector<string16>& value);
+ const std::vector<base::string16>& value);
void OnSuccessValue(int32 ipc_thread_id,
int32 ipc_callbacks_id,
const std::string& value);
@@ -207,7 +208,7 @@ class CONTENT_EXPORT IndexedDBDispatcher
void OnError(int32 ipc_thread_id,
int32 ipc_callbacks_id,
int code,
- const string16& message);
+ const base::string16& message);
void OnIntBlocked(int32 ipc_thread_id,
int32 ipc_callbacks_id,
int64 existing_version);
@@ -216,7 +217,7 @@ class CONTENT_EXPORT IndexedDBDispatcher
int32 ipc_database_id,
int64 transaction_id,
int code,
- const string16& message);
+ const base::string16& message);
void OnComplete(int32 ipc_thread_id,
int32 ipc_database_id,
int64 transaction_id);
@@ -233,14 +234,14 @@ class CONTENT_EXPORT IndexedDBDispatcher
// Careful! WebIDBCallbacks wraps non-threadsafe data types. It must be
// destroyed and used on the same thread it was created on.
- IDMap<WebKit::WebIDBCallbacks, IDMapOwnPointer> pending_callbacks_;
- IDMap<WebKit::WebIDBDatabaseCallbacks, IDMapOwnPointer>
+ IDMap<blink::WebIDBCallbacks, IDMapOwnPointer> pending_callbacks_;
+ IDMap<blink::WebIDBDatabaseCallbacks, IDMapOwnPointer>
pending_database_callbacks_;
- // Map from cursor id to RendererWebIDBCursorImpl.
- std::map<int32, RendererWebIDBCursorImpl*> cursors_;
+ // Map from cursor id to WebIDBCursorImpl.
+ std::map<int32, WebIDBCursorImpl*> cursors_;
- std::map<int32, RendererWebIDBDatabaseImpl*> databases_;
+ std::map<int32, WebIDBDatabaseImpl*> databases_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcher);
};
diff --git a/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc b/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
index 8e8c6c21a1f..61f3b0e6e39 100644
--- a/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
+++ b/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
@@ -13,12 +13,12 @@
#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
-using WebKit::WebData;
-using WebKit::WebIDBCallbacks;
-using WebKit::WebIDBDatabase;
-using WebKit::WebIDBDatabaseError;
-using WebKit::WebIDBKey;
-using WebKit::WebVector;
+using blink::WebData;
+using blink::WebIDBCallbacks;
+using blink::WebIDBDatabase;
+using blink::WebIDBDatabaseError;
+using blink::WebIDBKey;
+using blink::WebVector;
namespace content {
namespace {
@@ -55,7 +55,7 @@ TEST(IndexedDBDispatcherTest, ValueSizeTest) {
MockCallbacks callbacks;
IndexedDBDispatcher dispatcher(thread_safe_sender.get());
- IndexedDBKey key(0, WebKit::WebIDBKeyTypeNumber);
+ IndexedDBKey key(0, blink::WebIDBKeyTypeNumber);
dispatcher.RequestIDBDatabasePut(ipc_dummy_id,
transaction_id,
object_store_id,
diff --git a/chromium/content/child/indexed_db/indexed_db_key_builders.cc b/chromium/content/child/indexed_db/indexed_db_key_builders.cc
index 380c0cb5c24..ed84ac41c2c 100644
--- a/chromium/content/child/indexed_db/indexed_db_key_builders.cc
+++ b/chromium/content/child/indexed_db/indexed_db_key_builders.cc
@@ -7,17 +7,18 @@
#include "base/logging.h"
#include "third_party/WebKit/public/platform/WebVector.h"
-using WebKit::WebIDBKey;
-using WebKit::WebIDBKeyRange;
-using WebKit::WebIDBKeyTypeArray;
-using WebKit::WebIDBKeyTypeDate;
-using WebKit::WebIDBKeyTypeInvalid;
-using WebKit::WebIDBKeyTypeMin;
-using WebKit::WebIDBKeyTypeNull;
-using WebKit::WebIDBKeyTypeNumber;
-using WebKit::WebIDBKeyTypeString;
-using WebKit::WebVector;
-using WebKit::WebString;
+using blink::WebIDBKey;
+using blink::WebIDBKeyRange;
+using blink::WebIDBKeyTypeArray;
+using blink::WebIDBKeyTypeBinary;
+using blink::WebIDBKeyTypeDate;
+using blink::WebIDBKeyTypeInvalid;
+using blink::WebIDBKeyTypeMin;
+using blink::WebIDBKeyTypeNull;
+using blink::WebIDBKeyTypeNumber;
+using blink::WebIDBKeyTypeString;
+using blink::WebVector;
+using blink::WebString;
static content::IndexedDBKey::KeyArray CopyKeyArray(const WebIDBKey& other) {
content::IndexedDBKey::KeyArray result;
@@ -29,9 +30,9 @@ static content::IndexedDBKey::KeyArray CopyKeyArray(const WebIDBKey& other) {
return result;
}
-static std::vector<string16> CopyArray(
+static std::vector<base::string16> CopyArray(
const WebVector<WebString>& array) {
- std::vector<string16> copy(array.size());
+ std::vector<base::string16> copy(array.size());
for (size_t i = 0; i < array.size(); ++i)
copy[i] = array[i];
return copy;
@@ -40,10 +41,13 @@ static std::vector<string16> CopyArray(
namespace content {
-IndexedDBKey IndexedDBKeyBuilder::Build(const WebKit::WebIDBKey& key) {
+IndexedDBKey IndexedDBKeyBuilder::Build(const blink::WebIDBKey& key) {
switch (key.keyType()) {
case WebIDBKeyTypeArray:
return IndexedDBKey(CopyKeyArray(key));
+ case WebIDBKeyTypeBinary:
+ return IndexedDBKey(
+ std::string(key.binary().data(), key.binary().size()));
case WebIDBKeyTypeString:
return IndexedDBKey(key.string());
case WebIDBKeyTypeDate:
@@ -54,6 +58,7 @@ IndexedDBKey IndexedDBKeyBuilder::Build(const WebKit::WebIDBKey& key) {
case WebIDBKeyTypeInvalid:
return IndexedDBKey(key.keyType());
case WebIDBKeyTypeMin:
+ default:
NOTREACHED();
return IndexedDBKey();
}
@@ -65,12 +70,14 @@ WebIDBKey WebIDBKeyBuilder::Build(const IndexedDBKey& key) {
switch (key.type()) {
case WebIDBKeyTypeArray: {
const IndexedDBKey::KeyArray& array = key.array();
- WebKit::WebVector<WebIDBKey> web_array(array.size());
+ blink::WebVector<WebIDBKey> web_array(array.size());
for (size_t i = 0; i < array.size(); ++i) {
web_array[i] = Build(array[i]);
}
return WebIDBKey::createArray(web_array);
}
+ case WebIDBKeyTypeBinary:
+ return WebIDBKey::createBinary(key.binary());
case WebIDBKeyTypeString:
return WebIDBKey::createString(key.string());
case WebIDBKeyTypeDate:
@@ -82,6 +89,7 @@ WebIDBKey WebIDBKeyBuilder::Build(const IndexedDBKey& key) {
case WebIDBKeyTypeNull:
return WebIDBKey::createNull();
case WebIDBKeyTypeMin:
+ default:
NOTREACHED();
return WebIDBKey::createInvalid();
}
@@ -99,31 +107,31 @@ IndexedDBKeyRange IndexedDBKeyRangeBuilder::Build(
}
IndexedDBKeyPath IndexedDBKeyPathBuilder::Build(
- const WebKit::WebIDBKeyPath& key_path) {
+ const blink::WebIDBKeyPath& key_path) {
switch (key_path.keyPathType()) {
- case WebKit::WebIDBKeyPathTypeString:
+ case blink::WebIDBKeyPathTypeString:
return IndexedDBKeyPath(key_path.string());
- case WebKit::WebIDBKeyPathTypeArray:
+ case blink::WebIDBKeyPathTypeArray:
return IndexedDBKeyPath(CopyArray(key_path.array()));
- case WebKit::WebIDBKeyPathTypeNull:
+ case blink::WebIDBKeyPathTypeNull:
return IndexedDBKeyPath();
}
NOTREACHED();
return IndexedDBKeyPath();
}
-WebKit::WebIDBKeyPath WebIDBKeyPathBuilder::Build(
+blink::WebIDBKeyPath WebIDBKeyPathBuilder::Build(
const IndexedDBKeyPath& key_path) {
switch (key_path.type()) {
- case WebKit::WebIDBKeyPathTypeString:
- return WebKit::WebIDBKeyPath::create(WebString(key_path.string()));
- case WebKit::WebIDBKeyPathTypeArray:
- return WebKit::WebIDBKeyPath::create(CopyArray(key_path.array()));
- case WebKit::WebIDBKeyPathTypeNull:
- return WebKit::WebIDBKeyPath::createNull();
+ case blink::WebIDBKeyPathTypeString:
+ return blink::WebIDBKeyPath::create(WebString(key_path.string()));
+ case blink::WebIDBKeyPathTypeArray:
+ return blink::WebIDBKeyPath::create(CopyArray(key_path.array()));
+ case blink::WebIDBKeyPathTypeNull:
+ return blink::WebIDBKeyPath::createNull();
}
NOTREACHED();
- return WebKit::WebIDBKeyPath::createNull();
+ return blink::WebIDBKeyPath::createNull();
}
} // namespace content
diff --git a/chromium/content/child/indexed_db/indexed_db_key_builders.h b/chromium/content/child/indexed_db/indexed_db_key_builders.h
index e15b63bd47a..5a51a8a4c66 100644
--- a/chromium/content/child/indexed_db/indexed_db_key_builders.h
+++ b/chromium/content/child/indexed_db/indexed_db_key_builders.h
@@ -13,7 +13,7 @@
#include "third_party/WebKit/public/platform/WebIDBKeyPath.h"
#include "third_party/WebKit/public/platform/WebIDBKeyRange.h"
-namespace WebKit {
+namespace blink {
class WebIDBKey;
}
@@ -21,27 +21,27 @@ namespace content {
class CONTENT_EXPORT IndexedDBKeyBuilder {
public:
- static IndexedDBKey Build(const WebKit::WebIDBKey& key);
+ static IndexedDBKey Build(const blink::WebIDBKey& key);
};
class CONTENT_EXPORT WebIDBKeyBuilder {
public:
- static WebKit::WebIDBKey Build(const content::IndexedDBKey& key);
+ static blink::WebIDBKey Build(const content::IndexedDBKey& key);
};
class CONTENT_EXPORT IndexedDBKeyRangeBuilder {
public:
- static IndexedDBKeyRange Build(const WebKit::WebIDBKeyRange& key_range);
+ static IndexedDBKeyRange Build(const blink::WebIDBKeyRange& key_range);
};
class CONTENT_EXPORT IndexedDBKeyPathBuilder {
public:
- static IndexedDBKeyPath Build(const WebKit::WebIDBKeyPath& key_path);
+ static IndexedDBKeyPath Build(const blink::WebIDBKeyPath& key_path);
};
class CONTENT_EXPORT WebIDBKeyPathBuilder {
public:
- static WebKit::WebIDBKeyPath Build(const IndexedDBKeyPath& key_path);
+ static blink::WebIDBKeyPath Build(const IndexedDBKeyPath& key_path);
};
} // namespace content
diff --git a/chromium/content/child/indexed_db/indexed_db_message_filter.cc b/chromium/content/child/indexed_db/indexed_db_message_filter.cc
index 7022925e6d0..ac3c01f608f 100644
--- a/chromium/content/child/indexed_db/indexed_db_message_filter.cc
+++ b/chromium/content/child/indexed_db/indexed_db_message_filter.cc
@@ -4,50 +4,39 @@
#include "content/child/indexed_db/indexed_db_message_filter.h"
-#include "base/bind.h"
-#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "base/pickle.h"
#include "content/child/indexed_db/indexed_db_dispatcher.h"
#include "content/child/thread_safe_sender.h"
+#include "content/child/worker_thread_task_runner.h"
#include "content/common/indexed_db/indexed_db_messages.h"
-#include "webkit/child/worker_task_runner.h"
-
-using webkit_glue::WorkerTaskRunner;
namespace content {
IndexedDBMessageFilter::IndexedDBMessageFilter(
ThreadSafeSender* thread_safe_sender)
- : main_thread_loop_proxy_(base::MessageLoopProxy::current()),
- thread_safe_sender_(thread_safe_sender) {
+ : main_thread_loop_(base::MessageLoopProxy::current()),
+ thread_safe_sender_(thread_safe_sender) {}
+
+IndexedDBMessageFilter::~IndexedDBMessageFilter() {}
+
+base::TaskRunner* IndexedDBMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) {
+ if (IPC_MESSAGE_CLASS(msg) != IndexedDBMsgStart)
+ return NULL;
+ int ipc_thread_id = 0;
+ const bool success = PickleIterator(msg).ReadInt(&ipc_thread_id);
+ DCHECK(success);
+ if (!ipc_thread_id)
+ return main_thread_loop_.get();
+ return new WorkerThreadTaskRunner(ipc_thread_id);
}
bool IndexedDBMessageFilter::OnMessageReceived(const IPC::Message& msg) {
if (IPC_MESSAGE_CLASS(msg) != IndexedDBMsgStart)
return false;
- int ipc_thread_id = -1;
- bool result = PickleIterator(msg).ReadInt(&ipc_thread_id);
- DCHECK(result);
- base::Closure closure = base::Bind(
- &IndexedDBMessageFilter::DispatchMessage, this, msg);
- if (!ipc_thread_id) {
- main_thread_loop_proxy_->PostTask(FROM_HERE, closure);
- return true;
- }
- if (WorkerTaskRunner::Instance()->PostTask(ipc_thread_id, closure))
- return true;
-
- // Message for a terminated worker - perform necessary cleanup
- OnStaleMessageReceived(msg);
- return true;
-}
-
-IndexedDBMessageFilter::~IndexedDBMessageFilter() {}
-
-void IndexedDBMessageFilter::DispatchMessage(const IPC::Message& msg) {
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get())
->OnMessageReceived(msg);
+ return true;
}
void IndexedDBMessageFilter::OnStaleMessageReceived(const IPC::Message& msg) {
diff --git a/chromium/content/child/indexed_db/indexed_db_message_filter.h b/chromium/content/child/indexed_db/indexed_db_message_filter.h
index da11adf5e90..11744879ea6 100644
--- a/chromium/content/child/indexed_db/indexed_db_message_filter.h
+++ b/chromium/content/child/indexed_db/indexed_db_message_filter.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_CHILD_INDEXED_DB_INDEXED_DB_MESSAGE_FILTER_H_
#define CONTENT_CHILD_INDEXED_DB_INDEXED_DB_MESSAGE_FILTER_H_
-#include "ipc/ipc_channel_proxy.h"
+#include "content/child/child_message_filter.h"
struct IndexedDBDatabaseMetadata;
struct IndexedDBMsg_CallbacksUpgradeNeeded_Params;
@@ -15,22 +15,23 @@ class MessageLoopProxy;
} // namespace base
namespace content {
-class IndexedDBDispatcher;
+
class ThreadSafeSender;
-class IndexedDBMessageFilter : public IPC::ChannelProxy::MessageFilter {
+class IndexedDBMessageFilter : public ChildMessageFilter {
public:
explicit IndexedDBMessageFilter(ThreadSafeSender* thread_safe_sender);
- // IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
-
protected:
virtual ~IndexedDBMessageFilter();
private:
- void DispatchMessage(const IPC::Message& msg);
- void OnStaleMessageReceived(const IPC::Message& msg);
+ // ChildMessageFilter implementation:
+ virtual base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ virtual void OnStaleMessageReceived(const IPC::Message& msg) OVERRIDE;
+
void OnStaleSuccessIDBDatabase(int32 ipc_thread_id,
int32 ipc_callbacks_id,
int32 ipc_database_callbacks_id,
@@ -38,7 +39,7 @@ class IndexedDBMessageFilter : public IPC::ChannelProxy::MessageFilter {
const IndexedDBDatabaseMetadata&);
void OnStaleUpgradeNeeded(const IndexedDBMsg_CallbacksUpgradeNeeded_Params&);
- scoped_refptr<base::MessageLoopProxy> main_thread_loop_proxy_;
+ scoped_refptr<base::MessageLoopProxy> main_thread_loop_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBMessageFilter);
diff --git a/chromium/content/child/indexed_db/proxy_webidbcursor_impl.cc b/chromium/content/child/indexed_db/webidbcursor_impl.cc
index 0907647a7f4..df99ba4f8fe 100644
--- a/chromium/content/child/indexed_db/proxy_webidbcursor_impl.cc
+++ b/chromium/content/child/indexed_db/webidbcursor_impl.cc
@@ -2,24 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/child/indexed_db/proxy_webidbcursor_impl.h"
+#include "content/child/indexed_db/webidbcursor_impl.h"
#include <vector>
-#include "content/child/thread_safe_sender.h"
#include "content/child/indexed_db/indexed_db_dispatcher.h"
#include "content/child/indexed_db/indexed_db_key_builders.h"
+#include "content/child/thread_safe_sender.h"
#include "content/common/indexed_db/indexed_db_messages.h"
-using WebKit::WebData;
-using WebKit::WebIDBCallbacks;
-using WebKit::WebIDBKey;
+using blink::WebData;
+using blink::WebIDBCallbacks;
+using blink::WebIDBKey;
namespace content {
-RendererWebIDBCursorImpl::RendererWebIDBCursorImpl(
- int32 ipc_cursor_id,
- ThreadSafeSender* thread_safe_sender)
+WebIDBCursorImpl::WebIDBCursorImpl(int32 ipc_cursor_id,
+ ThreadSafeSender* thread_safe_sender)
: ipc_cursor_id_(ipc_cursor_id),
continue_count_(0),
used_prefetches_(0),
@@ -27,7 +26,7 @@ RendererWebIDBCursorImpl::RendererWebIDBCursorImpl(
prefetch_amount_(kMinPrefetchAmount),
thread_safe_sender_(thread_safe_sender) {}
-RendererWebIDBCursorImpl::~RendererWebIDBCursorImpl() {
+WebIDBCursorImpl::~WebIDBCursorImpl() {
// It's not possible for there to be pending callbacks that address this
// object since inside WebKit, they hold a reference to the object which owns
// this object. But, if that ever changed, then we'd need to invalidate
@@ -43,8 +42,8 @@ RendererWebIDBCursorImpl::~RendererWebIDBCursorImpl() {
dispatcher->CursorDestroyed(ipc_cursor_id_);
}
-void RendererWebIDBCursorImpl::advance(unsigned long count,
- WebIDBCallbacks* callbacks_ptr) {
+void WebIDBCursorImpl::advance(unsigned long count,
+ WebIDBCallbacks* callbacks_ptr) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
@@ -53,15 +52,21 @@ void RendererWebIDBCursorImpl::advance(unsigned long count,
count, callbacks.release(), ipc_cursor_id_);
}
-void RendererWebIDBCursorImpl::continueFunction(
- const WebIDBKey& key,
- WebIDBCallbacks* callbacks_ptr) {
+void WebIDBCursorImpl::continueFunction(const WebIDBKey& key,
+ WebIDBCallbacks* callbacks_ptr) {
+ continueFunction(key, WebIDBKey::createNull(), callbacks_ptr);
+}
+
+void WebIDBCursorImpl::continueFunction(const WebIDBKey& key,
+ const WebIDBKey& primary_key,
+ WebIDBCallbacks* callbacks_ptr) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
- if (key.keyType() == WebKit::WebIDBKeyTypeNull) {
- // No key, so this would qualify for a prefetch.
+ if (key.keyType() == blink::WebIDBKeyTypeNull &&
+ primary_key.keyType() == blink::WebIDBKeyTypeNull) {
+ // No key(s), so this would qualify for a prefetch.
++continue_count_;
if (!prefetch_keys_.empty()) {
@@ -88,11 +93,13 @@ void RendererWebIDBCursorImpl::continueFunction(
ResetPrefetchCache();
}
- dispatcher->RequestIDBCursorContinue(
- IndexedDBKeyBuilder::Build(key), callbacks.release(), ipc_cursor_id_);
+ dispatcher->RequestIDBCursorContinue(IndexedDBKeyBuilder::Build(key),
+ IndexedDBKeyBuilder::Build(primary_key),
+ callbacks.release(),
+ ipc_cursor_id_);
}
-void RendererWebIDBCursorImpl::postSuccessHandlerCallback() {
+void WebIDBCursorImpl::postSuccessHandlerCallback() {
pending_onsuccess_callbacks_--;
// If the onsuccess callback called continue() on the cursor again,
@@ -105,7 +112,7 @@ void RendererWebIDBCursorImpl::postSuccessHandlerCallback() {
ResetPrefetchCache();
}
-void RendererWebIDBCursorImpl::SetPrefetchData(
+void WebIDBCursorImpl::SetPrefetchData(
const std::vector<IndexedDBKey>& keys,
const std::vector<IndexedDBKey>& primary_keys,
const std::vector<WebData>& values) {
@@ -117,7 +124,7 @@ void RendererWebIDBCursorImpl::SetPrefetchData(
pending_onsuccess_callbacks_ = 0;
}
-void RendererWebIDBCursorImpl::CachedContinue(WebIDBCallbacks* callbacks) {
+void WebIDBCursorImpl::CachedContinue(WebIDBCallbacks* callbacks) {
DCHECK_GT(prefetch_keys_.size(), 0ul);
DCHECK(prefetch_primary_keys_.size() == prefetch_keys_.size());
DCHECK(prefetch_values_.size() == prefetch_keys_.size());
@@ -135,10 +142,11 @@ void RendererWebIDBCursorImpl::CachedContinue(WebIDBCallbacks* callbacks) {
pending_onsuccess_callbacks_++;
callbacks->onSuccess(WebIDBKeyBuilder::Build(key),
- WebIDBKeyBuilder::Build(primary_key), value);
+ WebIDBKeyBuilder::Build(primary_key),
+ value);
}
-void RendererWebIDBCursorImpl::ResetPrefetchCache() {
+void WebIDBCursorImpl::ResetPrefetchCache() {
continue_count_ = 0;
prefetch_amount_ = kMinPrefetchAmount;
diff --git a/chromium/content/child/indexed_db/proxy_webidbcursor_impl.h b/chromium/content/child/indexed_db/webidbcursor_impl.h
index 2c8b8f28968..3d8c3e8ac41 100644
--- a/chromium/content/child/indexed_db/proxy_webidbcursor_impl.h
+++ b/chromium/content/child/indexed_db/webidbcursor_impl.h
@@ -22,34 +22,36 @@
namespace content {
class ThreadSafeSender;
-class CONTENT_EXPORT RendererWebIDBCursorImpl
- : NON_EXPORTED_BASE(public WebKit::WebIDBCursor) {
+class CONTENT_EXPORT WebIDBCursorImpl
+ : NON_EXPORTED_BASE(public blink::WebIDBCursor) {
public:
- RendererWebIDBCursorImpl(int32 ipc_cursor_id,
- ThreadSafeSender* thread_safe_sender);
- virtual ~RendererWebIDBCursorImpl();
-
- virtual void advance(unsigned long count, WebKit::WebIDBCallbacks* callback);
- virtual void continueFunction(const WebKit::WebIDBKey& key,
- WebKit::WebIDBCallbacks* callback);
+ WebIDBCursorImpl(int32 ipc_cursor_id, ThreadSafeSender* thread_safe_sender);
+ virtual ~WebIDBCursorImpl();
+
+ virtual void advance(unsigned long count, blink::WebIDBCallbacks* callback);
+ virtual void continueFunction(const blink::WebIDBKey& key,
+ blink::WebIDBCallbacks* callback);
+ virtual void continueFunction(const blink::WebIDBKey& key,
+ const blink::WebIDBKey& primary_key,
+ blink::WebIDBCallbacks* callback);
virtual void postSuccessHandlerCallback();
void SetPrefetchData(const std::vector<IndexedDBKey>& keys,
const std::vector<IndexedDBKey>& primary_keys,
- const std::vector<WebKit::WebData>& values);
+ const std::vector<blink::WebData>& values);
- void CachedContinue(WebKit::WebIDBCallbacks* callbacks);
+ void CachedContinue(blink::WebIDBCallbacks* callbacks);
void ResetPrefetchCache();
private:
- FRIEND_TEST_ALL_PREFIXES(RendererWebIDBCursorImplTest, PrefetchTest);
+ FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchTest);
int32 ipc_cursor_id_;
// Prefetch cache.
std::deque<IndexedDBKey> prefetch_keys_;
std::deque<IndexedDBKey> prefetch_primary_keys_;
- std::deque<WebKit::WebData> prefetch_values_;
+ std::deque<blink::WebData> prefetch_values_;
// Number of continue calls that would qualify for a pre-fetch.
int continue_count_;
diff --git a/chromium/content/child/indexed_db/proxy_webidbcursor_impl_unittest.cc b/chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc
index 9e7c69dbf6a..d8494d435d2 100644
--- a/chromium/content/child/indexed_db/proxy_webidbcursor_impl_unittest.cc
+++ b/chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc
@@ -6,7 +6,7 @@
#include "base/values.h"
#include "content/child/indexed_db/indexed_db_dispatcher.h"
#include "content/child/indexed_db/indexed_db_key_builders.h"
-#include "content/child/indexed_db/proxy_webidbcursor_impl.h"
+#include "content/child/indexed_db/webidbcursor_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/indexed_db/indexed_db_key.h"
#include "ipc/ipc_sync_message_filter.h"
@@ -14,11 +14,11 @@
#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
-using WebKit::WebData;
-using WebKit::WebIDBCallbacks;
-using WebKit::WebIDBDatabase;
-using WebKit::WebIDBKey;
-using WebKit::WebIDBKeyTypeNumber;
+using blink::WebData;
+using blink::WebIDBCallbacks;
+using blink::WebIDBDatabase;
+using blink::WebIDBKey;
+using blink::WebIDBKeyTypeNumber;
namespace content {
@@ -41,7 +41,8 @@ class MockDispatcher : public IndexedDBDispatcher {
callbacks_.reset(callbacks);
}
- virtual void RequestIDBCursorContinue(const IndexedDBKey&,
+ virtual void RequestIDBCursorContinue(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key,
WebIDBCallbacks* callbacks,
int32 ipc_cursor_id) OVERRIDE {
++continue_calls_;
@@ -83,7 +84,7 @@ class MockContinueCallbacks : public WebIDBCallbacks {
} // namespace
-TEST(RendererWebIDBCursorImplTest, PrefetchTest) {
+TEST(WebIDBCursorImplTest, PrefetchTest) {
WebIDBKey null_key;
null_key.assignNull();
@@ -98,14 +99,13 @@ TEST(RendererWebIDBCursorImplTest, PrefetchTest) {
MockDispatcher dispatcher(thread_safe_sender.get());
{
- RendererWebIDBCursorImpl cursor(RendererWebIDBCursorImpl::kInvalidCursorId,
- thread_safe_sender.get());
+ WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
+ thread_safe_sender.get());
// Call continue() until prefetching should kick in.
int continue_calls = 0;
EXPECT_EQ(dispatcher.continue_calls(), 0);
- for (int i = 0; i < RendererWebIDBCursorImpl::kPrefetchContinueThreshold;
- ++i) {
+ for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
cursor.continueFunction(null_key, new MockContinueCallbacks());
EXPECT_EQ(++continue_calls, dispatcher.continue_calls());
EXPECT_EQ(0, dispatcher.prefetch_calls());
@@ -157,7 +157,7 @@ TEST(RendererWebIDBCursorImplTest, PrefetchTest) {
}
EXPECT_EQ(dispatcher.destroyed_cursor_id(),
- RendererWebIDBCursorImpl::kInvalidCursorId);
+ WebIDBCursorImpl::kInvalidCursorId);
}
} // namespace content
diff --git a/chromium/content/child/indexed_db/proxy_webidbdatabase_impl.cc b/chromium/content/child/indexed_db/webidbdatabase_impl.cc
index 1cf9778c275..8a9a7619e5f 100644
--- a/chromium/content/child/indexed_db/proxy_webidbdatabase_impl.cc
+++ b/chromium/content/child/indexed_db/webidbdatabase_impl.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/child/indexed_db/proxy_webidbdatabase_impl.h"
+#include "content/child/indexed_db/webidbdatabase_impl.h"
#include <vector>
-#include "content/child/thread_safe_sender.h"
#include "content/child/indexed_db/indexed_db_dispatcher.h"
#include "content/child/indexed_db/indexed_db_key_builders.h"
+#include "content/child/thread_safe_sender.h"
#include "content/common/indexed_db/indexed_db_messages.h"
#include "third_party/WebKit/public/platform/WebIDBKeyPath.h"
#include "third_party/WebKit/public/platform/WebIDBMetadata.h"
@@ -16,44 +16,42 @@
#include "third_party/WebKit/public/platform/WebVector.h"
#include "webkit/child/worker_task_runner.h"
-using WebKit::WebIDBCallbacks;
-using WebKit::WebIDBDatabaseCallbacks;
-using WebKit::WebIDBMetadata;
-using WebKit::WebIDBKey;
-using WebKit::WebIDBKeyPath;
-using WebKit::WebIDBKeyRange;
-using WebKit::WebString;
-using WebKit::WebVector;
+using blink::WebIDBCallbacks;
+using blink::WebIDBDatabaseCallbacks;
+using blink::WebIDBMetadata;
+using blink::WebIDBKey;
+using blink::WebIDBKeyPath;
+using blink::WebIDBKeyRange;
+using blink::WebString;
+using blink::WebVector;
using webkit_glue::WorkerTaskRunner;
namespace content {
-RendererWebIDBDatabaseImpl::RendererWebIDBDatabaseImpl(
- int32 ipc_database_id,
- int32 ipc_database_callbacks_id,
- ThreadSafeSender* thread_safe_sender)
+WebIDBDatabaseImpl::WebIDBDatabaseImpl(int32 ipc_database_id,
+ int32 ipc_database_callbacks_id,
+ ThreadSafeSender* thread_safe_sender)
: ipc_database_id_(ipc_database_id),
ipc_database_callbacks_id_(ipc_database_callbacks_id),
thread_safe_sender_(thread_safe_sender) {}
-RendererWebIDBDatabaseImpl::~RendererWebIDBDatabaseImpl() {
+WebIDBDatabaseImpl::~WebIDBDatabaseImpl() {
// It's not possible for there to be pending callbacks that address this
// object since inside WebKit, they hold a reference to the object which owns
// this object. But, if that ever changed, then we'd need to invalidate
// any such pointers.
- thread_safe_sender_->Send(new IndexedDBHostMsg_DatabaseDestroyed(
- ipc_database_id_));
+ thread_safe_sender_->Send(
+ new IndexedDBHostMsg_DatabaseDestroyed(ipc_database_id_));
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
dispatcher->DatabaseDestroyed(ipc_database_id_);
}
-void RendererWebIDBDatabaseImpl::createObjectStore(
- long long transaction_id,
- long long object_store_id,
- const WebString& name,
- const WebIDBKeyPath& key_path,
- bool auto_increment) {
+void WebIDBDatabaseImpl::createObjectStore(long long transaction_id,
+ long long object_store_id,
+ const WebString& name,
+ const WebIDBKeyPath& key_path,
+ bool auto_increment) {
IndexedDBHostMsg_DatabaseCreateObjectStore_Params params;
params.ipc_database_id = ipc_database_id_;
params.transaction_id = transaction_id;
@@ -66,17 +64,13 @@ void RendererWebIDBDatabaseImpl::createObjectStore(
new IndexedDBHostMsg_DatabaseCreateObjectStore(params));
}
-void RendererWebIDBDatabaseImpl::deleteObjectStore(
- long long transaction_id,
- long long object_store_id) {
- thread_safe_sender_->Send(
- new IndexedDBHostMsg_DatabaseDeleteObjectStore(
- ipc_database_id_,
- transaction_id,
- object_store_id));
+void WebIDBDatabaseImpl::deleteObjectStore(long long transaction_id,
+ long long object_store_id) {
+ thread_safe_sender_->Send(new IndexedDBHostMsg_DatabaseDeleteObjectStore(
+ ipc_database_id_, transaction_id, object_store_id));
}
-void RendererWebIDBDatabaseImpl::createTransaction(
+void WebIDBDatabaseImpl::createTransaction(
long long transaction_id,
WebIDBDatabaseCallbacks* callbacks,
const WebVector<long long>& object_store_ids,
@@ -87,41 +81,38 @@ void RendererWebIDBDatabaseImpl::createTransaction(
ipc_database_id_, transaction_id, callbacks, object_store_ids, mode);
}
-void RendererWebIDBDatabaseImpl::close() {
+void WebIDBDatabaseImpl::close() {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
dispatcher->RequestIDBDatabaseClose(ipc_database_id_,
ipc_database_callbacks_id_);
}
-void RendererWebIDBDatabaseImpl::get(
- long long transaction_id,
- long long object_store_id,
- long long index_id,
- const WebIDBKeyRange& key_range,
- bool key_only,
- WebIDBCallbacks* callbacks) {
+void WebIDBDatabaseImpl::get(long long transaction_id,
+ long long object_store_id,
+ long long index_id,
+ const WebIDBKeyRange& key_range,
+ bool key_only,
+ WebIDBCallbacks* callbacks) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
- dispatcher->RequestIDBDatabaseGet(
- ipc_database_id_,
- transaction_id,
- object_store_id,
- index_id,
- IndexedDBKeyRangeBuilder::Build(key_range),
- key_only,
- callbacks);
+ dispatcher->RequestIDBDatabaseGet(ipc_database_id_,
+ transaction_id,
+ object_store_id,
+ index_id,
+ IndexedDBKeyRangeBuilder::Build(key_range),
+ key_only,
+ callbacks);
}
-void RendererWebIDBDatabaseImpl::put(
- long long transaction_id,
- long long object_store_id,
- const WebKit::WebData& value,
- const WebIDBKey& key,
- PutMode put_mode,
- WebIDBCallbacks* callbacks,
- const WebVector<long long>& web_index_ids,
- const WebVector<WebIndexKeys>& web_index_keys) {
+void WebIDBDatabaseImpl::put(long long transaction_id,
+ long long object_store_id,
+ const blink::WebData& value,
+ const WebIDBKey& key,
+ PutMode put_mode,
+ WebIDBCallbacks* callbacks,
+ const WebVector<long long>& web_index_ids,
+ const WebVector<WebIndexKeys>& web_index_keys) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
dispatcher->RequestIDBDatabasePut(ipc_database_id_,
@@ -135,7 +126,7 @@ void RendererWebIDBDatabaseImpl::put(
web_index_keys);
}
-void RendererWebIDBDatabaseImpl::setIndexKeys(
+void WebIDBDatabaseImpl::setIndexKeys(
long long transaction_id,
long long object_store_id,
const WebIDBKey& primary_key,
@@ -146,8 +137,8 @@ void RendererWebIDBDatabaseImpl::setIndexKeys(
params.transaction_id = transaction_id;
params.object_store_id = object_store_id;
params.primary_key = IndexedDBKeyBuilder::Build(primary_key);
- COMPILE_ASSERT(sizeof(params.index_ids[0]) ==
- sizeof(index_ids[0]), Cant_copy);
+ COMPILE_ASSERT(sizeof(params.index_ids[0]) == sizeof(index_ids[0]),
+ Cant_copy);
params.index_ids.assign(index_ids.data(),
index_ids.data() + index_ids.size());
@@ -161,7 +152,7 @@ void RendererWebIDBDatabaseImpl::setIndexKeys(
thread_safe_sender_->Send(new IndexedDBHostMsg_DatabaseSetIndexKeys(params));
}
-void RendererWebIDBDatabaseImpl::setIndexesReady(
+void WebIDBDatabaseImpl::setIndexesReady(
long long transaction_id,
long long object_store_id,
const WebVector<long long>& web_index_ids) {
@@ -171,15 +162,14 @@ void RendererWebIDBDatabaseImpl::setIndexesReady(
ipc_database_id_, transaction_id, object_store_id, index_ids));
}
-void RendererWebIDBDatabaseImpl::openCursor(
- long long transaction_id,
- long long object_store_id,
- long long index_id,
- const WebIDBKeyRange& key_range,
- unsigned short direction,
- bool key_only,
- TaskType task_type,
- WebIDBCallbacks* callbacks) {
+void WebIDBDatabaseImpl::openCursor(long long transaction_id,
+ long long object_store_id,
+ long long index_id,
+ const WebIDBKeyRange& key_range,
+ unsigned short direction,
+ bool key_only,
+ TaskType task_type,
+ WebIDBCallbacks* callbacks) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
dispatcher->RequestIDBDatabaseOpenCursor(
@@ -194,12 +184,11 @@ void RendererWebIDBDatabaseImpl::openCursor(
callbacks);
}
-void RendererWebIDBDatabaseImpl::count(
- long long transaction_id,
- long long object_store_id,
- long long index_id,
- const WebIDBKeyRange& key_range,
- WebIDBCallbacks* callbacks) {
+void WebIDBDatabaseImpl::count(long long transaction_id,
+ long long object_store_id,
+ long long index_id,
+ const WebIDBKeyRange& key_range,
+ WebIDBCallbacks* callbacks) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
dispatcher->RequestIDBDatabaseCount(
@@ -211,11 +200,10 @@ void RendererWebIDBDatabaseImpl::count(
callbacks);
}
-void RendererWebIDBDatabaseImpl::deleteRange(
- long long transaction_id,
- long long object_store_id,
- const WebIDBKeyRange& key_range,
- WebIDBCallbacks* callbacks) {
+void WebIDBDatabaseImpl::deleteRange(long long transaction_id,
+ long long object_store_id,
+ const WebIDBKeyRange& key_range,
+ WebIDBCallbacks* callbacks) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
dispatcher->RequestIDBDatabaseDeleteRange(
@@ -226,25 +214,22 @@ void RendererWebIDBDatabaseImpl::deleteRange(
callbacks);
}
-void RendererWebIDBDatabaseImpl::clear(
- long long transaction_id,
- long long object_store_id,
- WebIDBCallbacks* callbacks) {
+void WebIDBDatabaseImpl::clear(long long transaction_id,
+ long long object_store_id,
+ WebIDBCallbacks* callbacks) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
dispatcher->RequestIDBDatabaseClear(
ipc_database_id_, transaction_id, object_store_id, callbacks);
}
-void RendererWebIDBDatabaseImpl::createIndex(
- long long transaction_id,
- long long object_store_id,
- long long index_id,
- const WebString& name,
- const WebIDBKeyPath& key_path,
- bool unique,
- bool multi_entry)
-{
+void WebIDBDatabaseImpl::createIndex(long long transaction_id,
+ long long object_store_id,
+ long long index_id,
+ const WebString& name,
+ const WebIDBKeyPath& key_path,
+ bool unique,
+ bool multi_entry) {
IndexedDBHostMsg_DatabaseCreateIndex_Params params;
params.ipc_database_id = ipc_database_id_;
params.transaction_id = transaction_id;
@@ -258,26 +243,21 @@ void RendererWebIDBDatabaseImpl::createIndex(
thread_safe_sender_->Send(new IndexedDBHostMsg_DatabaseCreateIndex(params));
}
-void RendererWebIDBDatabaseImpl::deleteIndex(
- long long transaction_id,
- long long object_store_id,
- long long index_id)
-{
- thread_safe_sender_->Send(
- new IndexedDBHostMsg_DatabaseDeleteIndex(
- ipc_database_id_,
- transaction_id,
- object_store_id, index_id));
+void WebIDBDatabaseImpl::deleteIndex(long long transaction_id,
+ long long object_store_id,
+ long long index_id) {
+ thread_safe_sender_->Send(new IndexedDBHostMsg_DatabaseDeleteIndex(
+ ipc_database_id_, transaction_id, object_store_id, index_id));
}
-void RendererWebIDBDatabaseImpl::abort(long long transaction_id) {
- thread_safe_sender_->Send(new IndexedDBHostMsg_DatabaseAbort(
- ipc_database_id_, transaction_id));
+void WebIDBDatabaseImpl::abort(long long transaction_id) {
+ thread_safe_sender_->Send(
+ new IndexedDBHostMsg_DatabaseAbort(ipc_database_id_, transaction_id));
}
-void RendererWebIDBDatabaseImpl::commit(long long transaction_id) {
- thread_safe_sender_->Send(new IndexedDBHostMsg_DatabaseCommit(
- ipc_database_id_, transaction_id));
+void WebIDBDatabaseImpl::commit(long long transaction_id) {
+ thread_safe_sender_->Send(
+ new IndexedDBHostMsg_DatabaseCommit(ipc_database_id_, transaction_id));
}
} // namespace content
diff --git a/chromium/content/child/indexed_db/proxy_webidbdatabase_impl.h b/chromium/content/child/indexed_db/webidbdatabase_impl.h
index ce8f0f333eb..07a732be2fd 100644
--- a/chromium/content/child/indexed_db/proxy_webidbdatabase_impl.h
+++ b/chromium/content/child/indexed_db/webidbdatabase_impl.h
@@ -9,7 +9,7 @@
#include "base/memory/ref_counted.h"
#include "third_party/WebKit/public/platform/WebIDBDatabase.h"
-namespace WebKit {
+namespace blink {
class WebIDBCallbacks;
class WebIDBDatabaseCallbacks;
class WebString;
@@ -18,80 +18,77 @@ class WebString;
namespace content {
class ThreadSafeSender;
-class RendererWebIDBDatabaseImpl : public WebKit::WebIDBDatabase {
+class WebIDBDatabaseImpl : public blink::WebIDBDatabase {
public:
- RendererWebIDBDatabaseImpl(int32 ipc_database_id,
- int32 ipc_database_callbacks_id,
- ThreadSafeSender* thread_safe_sender);
- virtual ~RendererWebIDBDatabaseImpl();
+ WebIDBDatabaseImpl(int32 ipc_database_id,
+ int32 ipc_database_callbacks_id,
+ ThreadSafeSender* thread_safe_sender);
+ virtual ~WebIDBDatabaseImpl();
- // WebKit::WebIDBDatabase
- virtual void createObjectStore(
- long long transaction_id,
- long long objectstore_id,
- const WebKit::WebString& name,
- const WebKit::WebIDBKeyPath& key_path,
- bool auto_increment);
- virtual void deleteObjectStore(
- long long transaction_id,
- long long object_store_id);
- virtual void createTransaction(
- long long transaction_id,
- WebKit::WebIDBDatabaseCallbacks* callbacks,
- const WebKit::WebVector<long long>& scope,
- unsigned short mode);
+ // blink::WebIDBDatabase
+ virtual void createObjectStore(long long transaction_id,
+ long long objectstore_id,
+ const blink::WebString& name,
+ const blink::WebIDBKeyPath& key_path,
+ bool auto_increment);
+ virtual void deleteObjectStore(long long transaction_id,
+ long long object_store_id);
+ virtual void createTransaction(long long transaction_id,
+ blink::WebIDBDatabaseCallbacks* callbacks,
+ const blink::WebVector<long long>& scope,
+ unsigned short mode);
virtual void close();
virtual void get(long long transactionId,
long long objectStoreId,
long long indexId,
- const WebKit::WebIDBKeyRange&,
+ const blink::WebIDBKeyRange&,
bool keyOnly,
- WebKit::WebIDBCallbacks*);
+ blink::WebIDBCallbacks*);
virtual void put(long long transactionId,
long long objectStoreId,
- const WebKit::WebData& value,
- const WebKit::WebIDBKey&,
+ const blink::WebData& value,
+ const blink::WebIDBKey&,
PutMode,
- WebKit::WebIDBCallbacks*,
- const WebKit::WebVector<long long>& indexIds,
- const WebKit::WebVector<WebIndexKeys>&);
+ blink::WebIDBCallbacks*,
+ const blink::WebVector<long long>& indexIds,
+ const blink::WebVector<WebIndexKeys>&);
virtual void setIndexKeys(long long transactionId,
long long objectStoreId,
- const WebKit::WebIDBKey&,
- const WebKit::WebVector<long long>& indexIds,
- const WebKit::WebVector<WebIndexKeys>&);
+ const blink::WebIDBKey&,
+ const blink::WebVector<long long>& indexIds,
+ const blink::WebVector<WebIndexKeys>&);
virtual void setIndexesReady(long long transactionId,
long long objectStoreId,
- const WebKit::WebVector<long long>& indexIds);
+ const blink::WebVector<long long>& indexIds);
virtual void openCursor(long long transactionId,
long long objectStoreId,
long long indexId,
- const WebKit::WebIDBKeyRange&,
+ const blink::WebIDBKeyRange&,
unsigned short direction,
bool keyOnly,
TaskType,
- WebKit::WebIDBCallbacks*);
+ blink::WebIDBCallbacks*);
virtual void count(long long transactionId,
long long objectStoreId,
long long indexId,
- const WebKit::WebIDBKeyRange&,
- WebKit::WebIDBCallbacks*);
+ const blink::WebIDBKeyRange&,
+ blink::WebIDBCallbacks*);
virtual void deleteRange(long long transactionId,
long long objectStoreId,
- const WebKit::WebIDBKeyRange&,
- WebKit::WebIDBCallbacks*);
+ const blink::WebIDBKeyRange&,
+ blink::WebIDBCallbacks*);
virtual void clear(long long transactionId,
long long objectStoreId,
- WebKit::WebIDBCallbacks*);
+ blink::WebIDBCallbacks*);
virtual void createIndex(long long transactionId,
long long objectStoreId,
long long indexId,
- const WebKit::WebString& name,
- const WebKit::WebIDBKeyPath&,
+ const blink::WebString& name,
+ const blink::WebIDBKeyPath&,
bool unique,
bool multiEntry);
- virtual void deleteIndex(long long transactionId, long
- long objectStoreId,
+ virtual void deleteIndex(long long transactionId,
+ long long objectStoreId,
long long indexId);
virtual void abort(long long transaction_id);
virtual void commit(long long transaction_id);
diff --git a/chromium/content/child/indexed_db/proxy_webidbfactory_impl.cc b/chromium/content/child/indexed_db/webidbfactory_impl.cc
index 1e3d861f324..4ed0316ef99 100644
--- a/chromium/content/child/indexed_db/proxy_webidbfactory_impl.cc
+++ b/chromium/content/child/indexed_db/webidbfactory_impl.cc
@@ -2,44 +2,39 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/child/indexed_db/proxy_webidbfactory_impl.h"
+#include "content/child/indexed_db/webidbfactory_impl.h"
-#include "content/child/thread_safe_sender.h"
#include "content/child/indexed_db/indexed_db_dispatcher.h"
+#include "content/child/thread_safe_sender.h"
#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebString.h"
-using WebKit::WebIDBCallbacks;
-using WebKit::WebIDBDatabase;
-using WebKit::WebIDBDatabaseCallbacks;
-using WebKit::WebString;
+using blink::WebIDBCallbacks;
+using blink::WebIDBDatabase;
+using blink::WebIDBDatabaseCallbacks;
+using blink::WebString;
namespace content {
-RendererWebIDBFactoryImpl::RendererWebIDBFactoryImpl(
- ThreadSafeSender* thread_safe_sender)
- : thread_safe_sender_(thread_safe_sender) {
-}
+WebIDBFactoryImpl::WebIDBFactoryImpl(ThreadSafeSender* thread_safe_sender)
+ : thread_safe_sender_(thread_safe_sender) {}
-RendererWebIDBFactoryImpl::~RendererWebIDBFactoryImpl() {
-}
+WebIDBFactoryImpl::~WebIDBFactoryImpl() {}
-void RendererWebIDBFactoryImpl::getDatabaseNames(
- WebIDBCallbacks* callbacks,
- const WebString& database_identifier) {
+void WebIDBFactoryImpl::getDatabaseNames(WebIDBCallbacks* callbacks,
+ const WebString& database_identifier) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
dispatcher->RequestIDBFactoryGetDatabaseNames(callbacks,
database_identifier.utf8());
}
-void RendererWebIDBFactoryImpl::open(
- const WebString& name,
- long long version,
- long long transaction_id,
- WebIDBCallbacks* callbacks,
- WebIDBDatabaseCallbacks* database_callbacks,
- const WebString& database_identifier) {
+void WebIDBFactoryImpl::open(const WebString& name,
+ long long version,
+ long long transaction_id,
+ WebIDBCallbacks* callbacks,
+ WebIDBDatabaseCallbacks* database_callbacks,
+ const WebString& database_identifier) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
dispatcher->RequestIDBFactoryOpen(name,
@@ -50,10 +45,9 @@ void RendererWebIDBFactoryImpl::open(
database_identifier.utf8());
}
-void RendererWebIDBFactoryImpl::deleteDatabase(
- const WebString& name,
- WebIDBCallbacks* callbacks,
- const WebString& database_identifier) {
+void WebIDBFactoryImpl::deleteDatabase(const WebString& name,
+ WebIDBCallbacks* callbacks,
+ const WebString& database_identifier) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
dispatcher->RequestIDBFactoryDeleteDatabase(
diff --git a/chromium/content/child/indexed_db/proxy_webidbfactory_impl.h b/chromium/content/child/indexed_db/webidbfactory_impl.h
index 9b7852d3ace..1484cd67568 100644
--- a/chromium/content/child/indexed_db/proxy_webidbfactory_impl.h
+++ b/chromium/content/child/indexed_db/webidbfactory_impl.h
@@ -11,33 +11,30 @@
#include "third_party/WebKit/public/platform/WebIDBFactory.h"
#include "third_party/WebKit/public/platform/WebVector.h"
-namespace WebKit {
+namespace blink {
class WebString;
}
namespace content {
class ThreadSafeSender;
-class RendererWebIDBFactoryImpl : public WebKit::WebIDBFactory {
+class WebIDBFactoryImpl : public blink::WebIDBFactory {
public:
- explicit RendererWebIDBFactoryImpl(ThreadSafeSender* thread_safe_sender);
- virtual ~RendererWebIDBFactoryImpl();
+ explicit WebIDBFactoryImpl(ThreadSafeSender* thread_safe_sender);
+ virtual ~WebIDBFactoryImpl();
// See WebIDBFactory.h for documentation on these functions.
- virtual void getDatabaseNames(
- WebKit::WebIDBCallbacks* callbacks,
- const WebKit::WebString& database_identifier);
- virtual void open(
- const WebKit::WebString& name,
- long long version,
- long long transaction_id,
- WebKit::WebIDBCallbacks* callbacks,
- WebKit::WebIDBDatabaseCallbacks* databaseCallbacks,
- const WebKit::WebString& database_identifier);
- virtual void deleteDatabase(
- const WebKit::WebString& name,
- WebKit::WebIDBCallbacks* callbacks,
- const WebKit::WebString& database_identifier);
+ virtual void getDatabaseNames(blink::WebIDBCallbacks* callbacks,
+ const blink::WebString& database_identifier);
+ virtual void open(const blink::WebString& name,
+ long long version,
+ long long transaction_id,
+ blink::WebIDBCallbacks* callbacks,
+ blink::WebIDBDatabaseCallbacks* databaseCallbacks,
+ const blink::WebString& database_identifier);
+ virtual void deleteDatabase(const blink::WebString& name,
+ blink::WebIDBCallbacks* callbacks,
+ const blink::WebString& database_identifier);
private:
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
diff --git a/chromium/content/child/npapi/np_channel_base.cc b/chromium/content/child/npapi/np_channel_base.cc
index da77c44f5f3..85ade5a2539 100644
--- a/chromium/content/child/npapi/np_channel_base.cc
+++ b/chromium/content/child/npapi/np_channel_base.cc
@@ -4,36 +4,78 @@
#include "content/child/npapi/np_channel_base.h"
-#include <stack>
-
#include "base/auto_reset.h"
#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
+#include "base/threading/thread_local.h"
#include "ipc/ipc_sync_message.h"
#if defined(OS_POSIX)
+#include "base/file_util.h"
#include "ipc/ipc_channel_posix.h"
#endif
namespace content {
+namespace {
+
typedef base::hash_map<std::string, scoped_refptr<NPChannelBase> > ChannelMap;
-static base::LazyInstance<ChannelMap>::Leaky
- g_channels = LAZY_INSTANCE_INITIALIZER;
-typedef std::stack<scoped_refptr<NPChannelBase> > NPChannelRefStack;
-static base::LazyInstance<NPChannelRefStack>::Leaky
- g_lazy_channel_stack = LAZY_INSTANCE_INITIALIZER;
+struct ChannelGlobals {
+ ChannelMap channel_map;
+ scoped_refptr<NPChannelBase> current_channel;
+};
+
+#if defined(OS_ANDROID)
+// Workaround for http://crbug.com/298179 - NPChannelBase is only intended
+// for use on one thread per process. Using TLS to store the globals removes the
+// worst thread hostility in this class, especially needed for webview which
+// runs in single-process mode. TODO(joth): Make a complete fix, most likely
+// as part of addressing http://crbug.com/258510.
+base::LazyInstance<base::ThreadLocalPointer<ChannelGlobals> >::Leaky
+ g_channels_tls_ptr = LAZY_INSTANCE_INITIALIZER;
+
+ChannelGlobals* GetChannelGlobals() {
+ ChannelGlobals* globals = g_channels_tls_ptr.Get().Get();
+ if (!globals) {
+ globals = new ChannelGlobals;
+ g_channels_tls_ptr.Get().Set(globals);
+ }
+ return globals;
+}
+
+#else
+
+base::LazyInstance<ChannelGlobals>::Leaky g_channels_globals =
+ LAZY_INSTANCE_INITIALIZER;
+
+ChannelGlobals* GetChannelGlobals() { return g_channels_globals.Pointer(); }
+
+#endif // OS_ANDROID
+
+ChannelMap* GetChannelMap() {
+ return &GetChannelGlobals()->channel_map;
+}
+
+} // namespace
NPChannelBase* NPChannelBase::GetChannel(
const IPC::ChannelHandle& channel_handle, IPC::Channel::Mode mode,
ChannelFactory factory, base::MessageLoopProxy* ipc_message_loop,
bool create_pipe_now, base::WaitableEvent* shutdown_event) {
+#if defined(OS_POSIX)
+ // On POSIX the channel_handle conveys an FD (socket) which is duped by the
+ // kernel during the IPC message exchange (via the SCM_RIGHTS mechanism).
+ // Ensure we do not leak this FD.
+ int fd = channel_handle.socket.auto_close ? channel_handle.socket.fd : -1;
+ file_util::ScopedFD auto_close_fd(&fd);
+#endif
+
scoped_refptr<NPChannelBase> channel;
std::string channel_key = channel_handle.name;
- ChannelMap::const_iterator iter = g_channels.Get().find(channel_key);
- if (iter == g_channels.Get().end()) {
+ ChannelMap::const_iterator iter = GetChannelMap()->find(channel_key);
+ if (iter == GetChannelMap()->end()) {
channel = factory();
} else {
channel = iter->second;
@@ -43,13 +85,16 @@ NPChannelBase* NPChannelBase::GetChannel(
if (!channel->channel_valid()) {
channel->channel_handle_ = channel_handle;
+#if defined(OS_POSIX)
+ ignore_result(auto_close_fd.release());
+#endif
if (mode & IPC::Channel::MODE_SERVER_FLAG) {
channel->channel_handle_.name =
IPC::Channel::GenerateVerifiedChannelID(channel_key);
}
channel->mode_ = mode;
if (channel->Init(ipc_message_loop, create_pipe_now, shutdown_event)) {
- g_channels.Get()[channel_key] = channel;
+ (*GetChannelMap())[channel_key] = channel;
} else {
channel = NULL;
}
@@ -59,8 +104,8 @@ NPChannelBase* NPChannelBase::GetChannel(
}
void NPChannelBase::Broadcast(IPC::Message* message) {
- for (ChannelMap::iterator iter = g_channels.Get().begin();
- iter != g_channels.Get().end();
+ for (ChannelMap::iterator iter = GetChannelMap()->begin();
+ iter != GetChannelMap()->end();
++iter) {
iter->second->Send(new IPC::Message(*message));
}
@@ -88,15 +133,15 @@ NPChannelBase::~NPChannelBase() {
}
NPChannelBase* NPChannelBase::GetCurrentChannel() {
- return g_lazy_channel_stack.Pointer()->top().get();
+ return GetChannelGlobals()->current_channel.get();
}
void NPChannelBase::CleanupChannels() {
// Make a copy of the references as we can't iterate the map since items will
// be removed from it as we clean them up.
std::vector<scoped_refptr<NPChannelBase> > channels;
- for (ChannelMap::const_iterator iter = g_channels.Get().begin();
- iter != g_channels.Get().end();
+ for (ChannelMap::const_iterator iter = GetChannelMap()->begin();
+ iter != GetChannelMap()->end();
++iter) {
channels.push_back(iter->second);
}
@@ -106,7 +151,7 @@ void NPChannelBase::CleanupChannels() {
// This will clean up channels added to the map for which subsequent
// AddRoute wasn't called
- g_channels.Get().clear();
+ GetChannelMap()->clear();
}
NPObjectBase* NPChannelBase::GetNPObjectListenerForRoute(int route_id) {
@@ -164,14 +209,15 @@ bool NPChannelBase::Send(IPC::Message* message) {
}
int NPChannelBase::Count() {
- return static_cast<int>(g_channels.Get().size());
+ return static_cast<int>(GetChannelMap()->size());
}
bool NPChannelBase::OnMessageReceived(const IPC::Message& message) {
- // This call might cause us to be deleted, so keep an extra reference to
- // ourself so that we can send the reply and decrement back in_dispatch_.
- g_lazy_channel_stack.Pointer()->push(
- scoped_refptr<NPChannelBase>(this));
+ // Push this channel as the current channel being processed. This also forms
+ // a stack of scoped_refptr avoiding ourselves (or any instance higher
+ // up the callstack) from being deleted while processing a message.
+ base::AutoReset<scoped_refptr<NPChannelBase> > keep_alive(
+ &GetChannelGlobals()->current_channel, this);
bool handled;
if (message.should_unblock())
@@ -191,7 +237,6 @@ bool NPChannelBase::OnMessageReceived(const IPC::Message& message) {
if (message.should_unblock())
in_unblock_dispatch_--;
- g_lazy_channel_stack.Pointer()->pop();
return handled;
}
@@ -242,10 +287,10 @@ void NPChannelBase::RemoveRoute(int route_id) {
}
}
- for (ChannelMap::iterator iter = g_channels.Get().begin();
- iter != g_channels.Get().end(); ++iter) {
+ for (ChannelMap::iterator iter = GetChannelMap()->begin();
+ iter != GetChannelMap()->end(); ++iter) {
if (iter->second.get() == this) {
- g_channels.Get().erase(iter);
+ GetChannelMap()->erase(iter);
return;
}
}
@@ -267,12 +312,12 @@ void NPChannelBase::OnChannelError() {
// Once an error is seen on a channel, remap the channel to prevent
// it from being vended again. Keep the channel in the map so
// RemoveRoute() can clean things up correctly.
- for (ChannelMap::iterator iter = g_channels.Get().begin();
- iter != g_channels.Get().end(); ++iter) {
+ for (ChannelMap::iterator iter = GetChannelMap()->begin();
+ iter != GetChannelMap()->end(); ++iter) {
if (iter->second.get() == this) {
// Insert new element before invalidating |iter|.
- g_channels.Get()[iter->first + "-error"] = iter->second;
- g_channels.Get().erase(iter);
+ (*GetChannelMap())[iter->first + "-error"] = iter->second;
+ GetChannelMap()->erase(iter);
break;
}
}
diff --git a/chromium/content/child/npapi/npobject_proxy.cc b/chromium/content/child/npapi/npobject_proxy.cc
index fa28bbd4d4d..45dc68d665e 100644
--- a/chromium/content/child/npapi/npobject_proxy.cc
+++ b/chromium/content/child/npapi/npobject_proxy.cc
@@ -13,7 +13,7 @@
#include "content/child/npapi/plugin_instance.h"
#endif
-using WebKit::WebBindings;
+using blink::WebBindings;
namespace content {
diff --git a/chromium/content/child/npapi/npobject_stub.cc b/chromium/content/child/npapi/npobject_stub.cc
index b58eccafcb6..9746623767d 100644
--- a/chromium/content/child/npapi/npobject_stub.cc
+++ b/chromium/content/child/npapi/npobject_stub.cc
@@ -18,7 +18,7 @@
#include "content/common/plugin_constants_win.h"
#endif
-using WebKit::WebBindings;
+using blink::WebBindings;
namespace content {
diff --git a/chromium/content/child/npapi/npobject_util.cc b/chromium/content/child/npapi/npobject_util.cc
index fe7d365b661..e8f5b4ee2ce 100644
--- a/chromium/content/child/npapi/npobject_util.cc
+++ b/chromium/content/child/npapi/npobject_util.cc
@@ -11,9 +11,8 @@
#include "content/child/plugin_messages.h"
#include "third_party/WebKit/public/web/WebBindings.h"
#include "third_party/npapi/bindings/nphostapi.h"
-#include "webkit/glue/webkit_glue.h"
-using WebKit::WebBindings;
+using blink::WebBindings;
namespace content {
@@ -21,6 +20,7 @@ namespace content {
static bool g_plugin_process;
namespace {
+#if defined(ENABLE_PLUGINS)
// The next 7 functions are called by the plugin code when it's using the
// NPObject. Plugins always ignore the functions in NPClass (except allocate
// and deallocate), and instead just use the function pointers that were
@@ -124,13 +124,16 @@ NPNetscapeFuncs *GetHostFunctions() {
return &host_funcs;
}
+#endif // defined(ENABLE_PLUGINS)
}
+#if defined(ENABLE_PLUGINS)
void PatchNPNFunctions() {
g_plugin_process = true;
NPNetscapeFuncs* funcs = GetHostFunctions();
PluginHost::Singleton()->PatchNPNetscapeFuncs(funcs);
}
+#endif
bool IsPluginProcess() {
return g_plugin_process;
diff --git a/chromium/content/child/npapi/npruntime_util.cc b/chromium/content/child/npapi/npruntime_util.cc
index 745406a6848..da2f42c66ae 100644
--- a/chromium/content/child/npapi/npruntime_util.cc
+++ b/chromium/content/child/npapi/npruntime_util.cc
@@ -7,7 +7,7 @@
#include "base/pickle.h"
#include "third_party/WebKit/public/web/WebBindings.h"
-using WebKit::WebBindings;
+using blink::WebBindings;
namespace content {
diff --git a/chromium/content/child/npapi/plugin_host.cc b/chromium/content/child/npapi/plugin_host.cc
index 814964fd7ff..e53f9002215 100644
--- a/chromium/content/child/npapi/plugin_host.cc
+++ b/chromium/content/child/npapi/plugin_host.cc
@@ -31,7 +31,7 @@
#include "base/mac/mac_util.h"
#endif
-using WebKit::WebBindings;
+using blink::WebBindings;
// Declarations for stub implementations of deprecated functions, which are no
// longer listed in npapi.h.
@@ -331,7 +331,7 @@ uint32_t NPN_MemFlush(uint32_t size) {
// This is for dynamic discovery of new plugins.
// Should force a re-scan of the plugins directory to load new ones.
void NPN_ReloadPlugins(NPBool reload_pages) {
- WebKit::resetPluginCache(reload_pages ? true : false);
+ blink::resetPluginCache(reload_pages ? true : false);
}
// Requests a range of bytes for a seekable stream.
@@ -470,7 +470,7 @@ static NPError PostURLNotify(NPP id,
}
base::PlatformFileInfo post_file_info;
- if (!file_util::GetFileInfo(file_path, &post_file_info) ||
+ if (!base::GetFileInfo(file_path, &post_file_info) ||
post_file_info.is_directory)
return NPERR_FILE_NOT_FOUND;
diff --git a/chromium/content/child/npapi/plugin_instance_mac.mm b/chromium/content/child/npapi/plugin_instance_mac.mm
index 5453f8f6a56..bc8edb2295b 100644
--- a/chromium/content/child/npapi/plugin_instance_mac.mm
+++ b/chromium/content/child/npapi/plugin_instance_mac.mm
@@ -19,56 +19,6 @@
namespace content {
-namespace {
-
-// Returns an autoreleased NSEvent constructed from the given np_event,
-// targeting the given window.
-NSEvent* NSEventForNPCocoaEvent(NPCocoaEvent* np_event, NSWindow* window) {
- bool mouse_down = 1;
- switch (np_event->type) {
- case NPCocoaEventMouseDown:
- mouse_down = 1;
- break;
- case NPCocoaEventMouseUp:
- mouse_down = 0;
- break;
- default:
- // If plugins start bringing up context menus for things other than
- // clicks, this will need more plumbing; for now just log it and proceed
- // as if it were a mouse down.
- NOTREACHED();
- }
- NSEventType event_type = NSLeftMouseDown;
- switch (np_event->data.mouse.buttonNumber) {
- case 0:
- event_type = mouse_down ? NSLeftMouseDown : NSLeftMouseUp;
- break;
- case 1:
- event_type = mouse_down ? NSRightMouseDown : NSRightMouseUp;
- break;
- default:
- event_type = mouse_down ? NSOtherMouseDown : NSOtherMouseUp;
- break;
- }
-
- NSInteger click_count = np_event->data.mouse.clickCount;
- NSInteger modifiers = np_event->data.mouse.modifierFlags;
- // NPCocoaEvent doesn't have a timestamp, so just use the current time.
- NSEvent* event =
- [NSEvent mouseEventWithType:event_type
- location:NSZeroPoint
- modifierFlags:modifiers
- timestamp:[[NSApp currentEvent] timestamp]
- windowNumber:[window windowNumber]
- context:[NSGraphicsContext currentContext]
- eventNumber:0
- clickCount:click_count
- pressure:1.0];
- return event;
-}
-
-} // namespace
-
NPError PluginInstance::PopUpContextMenu(NPMenu* menu) {
if (!currently_handled_event_)
return NPERR_GENERIC_ERROR;
diff --git a/chromium/content/child/npapi/plugin_stream_posix.cc b/chromium/content/child/npapi/plugin_stream_posix.cc
index 478126888ad..8c74d83cd2c 100644
--- a/chromium/content/child/npapi/plugin_stream_posix.cc
+++ b/chromium/content/child/npapi/plugin_stream_posix.cc
@@ -33,8 +33,8 @@ size_t PluginStream::WriteBytes(const char* buf, size_t length) {
bool PluginStream::OpenTempFile() {
DCHECK_EQ(static_cast<FILE*>(NULL), temp_file_);
- if (file_util::CreateTemporaryFile(&temp_file_path_))
- temp_file_ = file_util::OpenFile(temp_file_path_, "a");
+ if (base::CreateTemporaryFile(&temp_file_path_))
+ temp_file_ = base::OpenFile(temp_file_path_, "a");
if (!temp_file_) {
base::DeleteFile(temp_file_path_, false);
@@ -48,7 +48,7 @@ void PluginStream::CloseTempFile() {
if (!TempFileIsValid())
return;
- file_util::CloseFile(temp_file_);
+ base::CloseFile(temp_file_);
ResetTempFileHandle();
}
diff --git a/chromium/content/child/npapi/plugin_stream_url.cc b/chromium/content/child/npapi/plugin_stream_url.cc
index 98ea4b1a923..d042e1cbe3b 100644
--- a/chromium/content/child/npapi/plugin_stream_url.cc
+++ b/chromium/content/child/npapi/plugin_stream_url.cc
@@ -173,6 +173,16 @@ void PluginStreamUrl::AddRangeRequestResourceId(unsigned long resource_id) {
}
void PluginStreamUrl::SetDeferLoading(bool value) {
+ // If we determined that the request had failed via the HTTP headers in the
+ // response then we send out a failure notification to the plugin process, as
+ // certain plugins don't handle HTTP failure codes correctly.
+ if (!value &&
+ plugin_url_fetcher_.get() &&
+ plugin_url_fetcher_->pending_failure_notification()) {
+ // This object may be deleted now.
+ DidFail(id_);
+ return;
+ }
if (id_ > 0)
instance()->webplugin()->SetDeferResourceLoading(id_, value);
for (size_t i = 0; i < range_requests_.size(); ++i)
diff --git a/chromium/content/child/npapi/plugin_url_fetcher.cc b/chromium/content/child/npapi/plugin_url_fetcher.cc
index 082619979e8..682bbe8cff7 100644
--- a/chromium/content/child/npapi/plugin_url_fetcher.cc
+++ b/chromium/content/child/npapi/plugin_url_fetcher.cc
@@ -4,6 +4,7 @@
#include "content/child/npapi/plugin_url_fetcher.h"
+#include "base/memory/scoped_ptr.h"
#include "content/child/child_thread.h"
#include "content/child/npapi/webplugin.h"
#include "content/child/npapi/plugin_host.h"
@@ -31,15 +32,15 @@ namespace {
// TODO(jam): this is similar to MultiPartResponseClient in webplugin_impl.cc,
// we should remove that other class once we switch to loading from the plugin
// process by default.
-class MultiPartResponseClient : public WebKit::WebURLLoaderClient {
+class MultiPartResponseClient : public blink::WebURLLoaderClient {
public:
explicit MultiPartResponseClient(PluginStreamUrl* plugin_stream)
: byte_range_lower_bound_(0), plugin_stream_(plugin_stream) {}
- // WebKit::WebURLLoaderClient implementation:
+ // blink::WebURLLoaderClient implementation:
virtual void didReceiveResponse(
- WebKit::WebURLLoader* loader,
- const WebKit::WebURLResponse& response) OVERRIDE {
+ blink::WebURLLoader* loader,
+ const blink::WebURLResponse& response) OVERRIDE {
int64 byte_range_upper_bound, instance_size;
if (!webkit_glue::MultipartResponseDelegate::ReadContentRanges(
response, &byte_range_lower_bound_, &byte_range_upper_bound,
@@ -47,15 +48,17 @@ class MultiPartResponseClient : public WebKit::WebURLLoaderClient {
NOTREACHED();
}
}
- virtual void didReceiveData(WebKit::WebURLLoader* loader,
+ virtual void didReceiveData(blink::WebURLLoader* loader,
const char* data,
int data_length,
int encoded_data_length) OVERRIDE {
// TODO(ananta)
// We should defer further loads on multipart resources on the same lines
// as regular resources requested by plugins to prevent reentrancy.
- plugin_stream_->DidReceiveData(data, data_length, byte_range_lower_bound_);
+ int64 data_offset = byte_range_lower_bound_;
byte_range_lower_bound_ += data_length;
+ plugin_stream_->DidReceiveData(data, data_length, data_offset);
+ // DANGER: this instance may be deleted at this point.
}
private:
@@ -78,7 +81,8 @@ PluginURLFetcher::PluginURLFetcher(PluginStreamUrl* plugin_stream,
bool is_plugin_src_load,
int origin_pid,
int render_view_id,
- unsigned long resource_id)
+ unsigned long resource_id,
+ bool copy_stream_data)
: plugin_stream_(plugin_stream),
url_(url),
first_party_for_cookies_(first_party_for_cookies),
@@ -87,7 +91,9 @@ PluginURLFetcher::PluginURLFetcher(PluginStreamUrl* plugin_stream,
notify_redirects_(notify_redirects),
is_plugin_src_load_(is_plugin_src_load),
resource_id_(resource_id),
- data_offset_(0) {
+ copy_stream_data_(copy_stream_data),
+ data_offset_(0),
+ pending_failure_notification_(false) {
webkit_glue::ResourceLoaderBridge::RequestInfo request_info;
request_info.method = method;
request_info.url = url;
@@ -142,7 +148,7 @@ void PluginURLFetcher::Cancel() {
void PluginURLFetcher::URLRedirectResponse(bool allow) {
if (allow) {
- bridge_->SetDefersLoading(true);
+ bridge_->SetDefersLoading(false);
} else {
bridge_->Cancel();
plugin_stream_->DidFail(resource_id_); // That will delete |this|.
@@ -210,7 +216,7 @@ void PluginURLFetcher::OnReceivedResponse(
if (plugin_stream_->seekable()) {
int response_code = info.headers->response_code();
if (response_code == 206) {
- WebKit::WebURLResponse response;
+ blink::WebURLResponse response;
response.initialize();
webkit_glue::WebURLLoaderImpl::PopulateURLResponse(url_, info, &response);
@@ -255,7 +261,8 @@ void PluginURLFetcher::OnReceivedResponse(
last_modified = static_cast<uint32>(temp.ToDoubleT());
// TODO(darin): Shouldn't we also report HTTP version numbers?
- headers = base::StringPrintf("HTTP %d ", info.headers->response_code());
+ int response_code = info.headers->response_code();
+ headers = base::StringPrintf("HTTP %d ", response_code);
headers += info.headers->GetStatusText();
headers += "\n";
@@ -266,6 +273,16 @@ void PluginURLFetcher::OnReceivedResponse(
if (!name.empty() && !value.empty())
headers += name + ": " + value + "\n";
}
+
+ // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP
+ // error codes in the stream header and as a result, was unaware of the fate
+ // of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF destroy
+ // the stream and invoke the NPP_DestroyStream function on the plugin if the
+ // HTTPrequest fails.
+ if ((url_.SchemeIs("http") || url_.SchemeIs("https")) &&
+ (response_code < 100 || response_code >= 400)) {
+ pending_failure_notification_ = true;
+ }
}
plugin_stream_->DidReceiveResponse(info.mime_type,
@@ -285,8 +302,20 @@ void PluginURLFetcher::OnReceivedData(const char* data,
if (multipart_delegate_) {
multipart_delegate_->OnReceivedData(data, data_length, encoded_data_length);
} else {
- plugin_stream_->DidReceiveData(data, data_length, data_offset_);
+ int64 offset = data_offset_;
data_offset_ += data_length;
+
+ if (copy_stream_data_) {
+ // QuickTime writes to this memory, and since we got it from
+ // ResourceDispatcher it's not mapped for write access in this process.
+ // http://crbug.com/308466.
+ scoped_ptr<char[]> data_copy(new char[data_length]);
+ memcpy(data_copy.get(), data, data_length);
+ plugin_stream_->DidReceiveData(data_copy.get(), data_length, offset);
+ } else {
+ plugin_stream_->DidReceiveData(data, data_length, offset);
+ }
+ // DANGER: this instance may be deleted at this point.
}
}
diff --git a/chromium/content/child/npapi/plugin_url_fetcher.h b/chromium/content/child/npapi/plugin_url_fetcher.h
index bbc2c8a429b..8281427595e 100644
--- a/chromium/content/child/npapi/plugin_url_fetcher.h
+++ b/chromium/content/child/npapi/plugin_url_fetcher.h
@@ -33,7 +33,8 @@ class PluginURLFetcher : public webkit_glue::ResourceLoaderBridge::Peer {
bool is_plugin_src_load,
int origin_pid,
int render_view_id,
- unsigned long resource_id);
+ unsigned long resource_id,
+ bool copy_stream_data);
virtual ~PluginURLFetcher();
// Cancels the current request.
@@ -42,6 +43,8 @@ class PluginURLFetcher : public webkit_glue::ResourceLoaderBridge::Peer {
// Called with the plugin's reply to NPP_URLRedirectNotify.
void URLRedirectResponse(bool allow);
+ bool pending_failure_notification() { return pending_failure_notification_; }
+
private:
// webkit_glue::ResourceLoaderBridge::Peer implementation:
virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
@@ -69,7 +72,9 @@ class PluginURLFetcher : public webkit_glue::ResourceLoaderBridge::Peer {
bool notify_redirects_;
bool is_plugin_src_load_;
unsigned long resource_id_;
+ bool copy_stream_data_;
int64 data_offset_;
+ bool pending_failure_notification_;
scoped_ptr<webkit_glue::MultipartResponseDelegate> multipart_delegate_;
diff --git a/chromium/content/child/npapi/plugin_web_event_converter_mac.h b/chromium/content/child/npapi/plugin_web_event_converter_mac.h
index 3c943f688ee..a1fc326ef0c 100644
--- a/chromium/content/child/npapi/plugin_web_event_converter_mac.h
+++ b/chromium/content/child/npapi/plugin_web_event_converter_mac.h
@@ -7,7 +7,7 @@
#include "third_party/npapi/bindings/npapi.h"
-namespace WebKit {
+namespace blink {
class WebInputEvent;
class WebKeyboardEvent;
class WebMouseEvent;
@@ -25,7 +25,7 @@ class PluginWebEventConverter {
// Initializes a converter for the given web event. Returns false if the event
// could not be converted.
- bool InitWithEvent(const WebKit::WebInputEvent& web_event);
+ bool InitWithEvent(const blink::WebInputEvent& web_event);
// Returns a pointer to a plugin event--suitable for passing to
// NPP_HandleEvent--corresponding to the the web event this converter was
@@ -37,12 +37,12 @@ class PluginWebEventConverter {
// Stores a converted plugin representation of the given web event, suitable
// for returning from plugin_event.
// Returns true if the event was successfully converted.
- bool ConvertKeyboardEvent(const WebKit::WebKeyboardEvent& web_event);
- bool ConvertMouseEvent(const WebKit::WebMouseEvent& web_event);
- bool ConvertMouseWheelEvent(const WebKit::WebMouseWheelEvent& web_event);
+ bool ConvertKeyboardEvent(const blink::WebKeyboardEvent& web_event);
+ bool ConvertMouseEvent(const blink::WebMouseEvent& web_event);
+ bool ConvertMouseWheelEvent(const blink::WebMouseWheelEvent& web_event);
// Returns the Cocoa translation of web_event's modifiers.
- static NSUInteger CocoaModifiers(const WebKit::WebInputEvent& web_event);
+ static NSUInteger CocoaModifiers(const blink::WebInputEvent& web_event);
NPCocoaEvent cocoa_event_;
diff --git a/chromium/content/child/npapi/plugin_web_event_converter_mac.mm b/chromium/content/child/npapi/plugin_web_event_converter_mac.mm
index 091fd718ed8..b9d7df706e9 100644
--- a/chromium/content/child/npapi/plugin_web_event_converter_mac.mm
+++ b/chromium/content/child/npapi/plugin_web_event_converter_mac.mm
@@ -8,10 +8,10 @@
#include "content/child/npapi/plugin_web_event_converter_mac.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-using WebKit::WebInputEvent;
-using WebKit::WebKeyboardEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
namespace content {
diff --git a/chromium/content/child/npapi/webplugin_delegate.h b/chromium/content/child/npapi/webplugin_delegate.h
index 0e1148fda05..c419a3f2e4b 100644
--- a/chromium/content/child/npapi/webplugin_delegate.h
+++ b/chromium/content/child/npapi/webplugin_delegate.h
@@ -18,7 +18,7 @@ class GURL;
class SkCanvas;
struct NPObject;
-namespace WebKit {
+namespace blink {
class WebInputEvent;
}
@@ -73,7 +73,7 @@ class WebPluginDelegate {
// For windowless plugins, gives them a user event like mouse/keyboard.
// Returns whether the event was handled. This is only called in windowsless
// mode. See NPAPI NPP_HandleEvent for more information.
- virtual bool HandleInputEvent(const WebKit::WebInputEvent& event,
+ virtual bool HandleInputEvent(const blink::WebInputEvent& event,
WebCursor::CursorInfo* cursor) = 0;
// Gets the NPObject associated with the plugin for scripting.
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl.cc b/chromium/content/child/npapi/webplugin_delegate_impl.cc
index 27e3dbd102a..420766b5380 100644
--- a/chromium/content/child/npapi/webplugin_delegate_impl.cc
+++ b/chromium/content/child/npapi/webplugin_delegate_impl.cc
@@ -11,15 +11,15 @@
#include "base/message_loop/message_loop.h"
#include "base/process/process_handle.h"
#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "content/child/npapi/plugin_instance.h"
#include "content/child/npapi/plugin_lib.h"
#include "content/child/npapi/plugin_stream_url.h"
#include "content/child/npapi/plugin_url_fetcher.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "webkit/glue/webkit_glue.h"
-using WebKit::WebCursorInfo;
-using WebKit::WebInputEvent;
+using blink::WebCursorInfo;
+using blink::WebInputEvent;
namespace content {
@@ -52,6 +52,11 @@ bool WebPluginDelegateImpl::Initialize(
const std::vector<std::string>& arg_names,
const std::vector<std::string>& arg_values,
bool load_manually) {
+ if (instance_->plugin_lib()->plugin_info().name.find(
+ base::ASCIIToUTF16("QuickTime Plug-in")) != std::wstring::npos) {
+ quirks_ |= PLUGIN_QUIRK_COPY_STREAM_DATA;
+ }
+
instance_->set_web_plugin(plugin_);
if (quirks_ & PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES) {
PluginLib* plugin_lib = instance()->plugin_lib();
@@ -317,10 +322,11 @@ void WebPluginDelegateImpl::FetchURL(unsigned long resource_id,
PluginStreamUrl* plugin_stream = instance()->CreateStream(
resource_id, url, std::string(), notify_id);
+ bool copy_stream_data = !!(quirks_ & PLUGIN_QUIRK_COPY_STREAM_DATA);
plugin_stream->SetPluginURLFetcher(new PluginURLFetcher(
plugin_stream, url, first_party_for_cookies, method, buf, len,
referrer, notify_redirects, is_plugin_src_load, origin_pid,
- render_view_id, resource_id));
+ render_view_id, resource_id, copy_stream_data));
}
} // namespace content
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl.h b/chromium/content/child/npapi/webplugin_delegate_impl.h
index a7a134493a9..a3417e2b6b6 100644
--- a/chromium/content/child/npapi/webplugin_delegate_impl.h
+++ b/chromium/content/child/npapi/webplugin_delegate_impl.h
@@ -42,7 +42,6 @@ class CARenderer;
namespace content {
class PluginInstance;
-class PluginURLFetcher;
class WebPlugin;
#if defined(OS_MACOSX)
@@ -76,6 +75,8 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK = 32768, // Linux
PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL = 65536, // Windows.
PLUGIN_QUIRK_EMULATE_IME = 131072, // Windows.
+ PLUGIN_QUIRK_FAKE_WINDOW_FROM_POINT = 262144, // Windows.
+ PLUGIN_QUIRK_COPY_STREAM_DATA = 524288, // All platforms
};
static WebPluginDelegateImpl* Create(WebPlugin* plugin,
@@ -92,7 +93,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
const gfx::Rect& clip_rect) OVERRIDE;
virtual void Paint(SkCanvas* canvas, const gfx::Rect& rect) OVERRIDE;
virtual void SetFocus(bool focused) OVERRIDE;
- virtual bool HandleInputEvent(const WebKit::WebInputEvent& event,
+ virtual bool HandleInputEvent(const blink::WebInputEvent& event,
WebCursor::CursorInfo* cursor_info) OVERRIDE;
virtual NPObject* GetPluginScriptableObject() OVERRIDE;
virtual NPP GetPluginNPP() OVERRIDE;
@@ -281,7 +282,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// Does platform-specific event handling. Arguments and return are identical
// to HandleInputEvent.
- bool PlatformHandleInputEvent(const WebKit::WebInputEvent& event,
+ bool PlatformHandleInputEvent(const blink::WebInputEvent& event,
WebCursor::CursorInfo* cursor_info);
// Closes down and destroys our plugin instance.
@@ -386,6 +387,14 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// GetProcAddress intercepter for windowless plugins.
static FARPROC WINAPI GetProcAddressPatch(HMODULE module, LPCSTR name);
+#if defined(USE_AURA)
+ // WindowFromPoint patch for Flash windowless plugins. When flash receives
+ // mouse move messages it calls the WindowFromPoint API to eventually convert
+ // the mouse coordinates to screen. We need to return the dummy plugin parent
+ // window for Aura to ensure that these conversions occur correctly.
+ static HWND WINAPI WindowFromPointPatch(POINT point);
+#endif
+
// The mouse hook proc which handles mouse capture in windowed plugins.
static LRESULT CALLBACK MouseHookProc(int code, WPARAM wParam,
LPARAM lParam);
@@ -441,7 +450,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
void OnModalLoopEntered();
// Returns true if the message passed in corresponds to a user gesture.
- static bool IsUserGesture(const WebKit::WebInputEvent& event);
+ static bool IsUserGesture(const blink::WebInputEvent& event);
// The url with which the plugin was instantiated.
std::string plugin_url_;
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl_android.cc b/chromium/content/child/npapi/webplugin_delegate_impl_android.cc
index fadaeeeef8f..f484d5f43e8 100644
--- a/chromium/content/child/npapi/webplugin_delegate_impl_android.cc
+++ b/chromium/content/child/npapi/webplugin_delegate_impl_android.cc
@@ -10,7 +10,7 @@
#include "content/child/npapi/webplugin.h"
#include "webkit/common/cursors/webcursor.h"
-using WebKit::WebInputEvent;
+using blink::WebInputEvent;
namespace content {
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl_aura.cc b/chromium/content/child/npapi/webplugin_delegate_impl_aura.cc
index 3416990c824..6abf5f98fcd 100644
--- a/chromium/content/child/npapi/webplugin_delegate_impl_aura.cc
+++ b/chromium/content/child/npapi/webplugin_delegate_impl_aura.cc
@@ -7,7 +7,7 @@
#include "content/child/npapi/plugin_instance.h"
#include "webkit/common/cursors/webcursor.h"
-using WebKit::WebInputEvent;
+using blink::WebInputEvent;
namespace content {
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl_gtk.cc b/chromium/content/child/npapi/webplugin_delegate_impl_gtk.cc
index 371d834fb14..39ecee8b7b3 100644
--- a/chromium/content/child/npapi/webplugin_delegate_impl_gtk.cc
+++ b/chromium/content/child/npapi/webplugin_delegate_impl_gtk.cc
@@ -22,9 +22,9 @@
#include "third_party/npapi/bindings/npapi_x11.h"
-using WebKit::WebKeyboardEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
+using blink::WebKeyboardEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
namespace content {
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl_mac.mm b/chromium/content/child/npapi/webplugin_delegate_impl_mac.mm
index 2951fca3e86..c125dc8110f 100644
--- a/chromium/content/child/npapi/webplugin_delegate_impl_mac.mm
+++ b/chromium/content/child/npapi/webplugin_delegate_impl_mac.mm
@@ -27,10 +27,10 @@
#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
#include "webkit/common/cursors/webcursor.h"
-using WebKit::WebKeyboardEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
+using blink::WebKeyboardEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
// Important implementation notes: The Mac definition of NPAPI, particularly
// the distinction between windowed and windowless modes, differs from the
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl_win.cc b/chromium/content/child/npapi/webplugin_delegate_impl_win.cc
index f6d054082ae..73bb4422808 100644
--- a/chromium/content/child/npapi/webplugin_delegate_impl_win.cc
+++ b/chromium/content/child/npapi/webplugin_delegate_impl_win.cc
@@ -35,9 +35,9 @@
#include "ui/gfx/win/hwnd_util.h"
#include "webkit/common/cursors/webcursor.h"
-using WebKit::WebKeyboardEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
+using blink::WebKeyboardEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
namespace content {
@@ -88,6 +88,11 @@ base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w =
base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_proc_address =
LAZY_INSTANCE_INITIALIZER;
+#if defined(USE_AURA)
+base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_window_from_point =
+ LAZY_INSTANCE_INITIALIZER;
+#endif
+
// http://crbug.com/16114
// Enforces providing a valid device context in NPWindow, so that NPP_SetWindow
// is never called with NPNWindoTypeDrawable and NPWindow set to NULL.
@@ -261,6 +266,9 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS;
quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE;
quirks_ |= PLUGIN_QUIRK_EMULATE_IME;
+#if defined(USE_AURA)
+ quirks_ |= PLUGIN_QUIRK_FAKE_WINDOW_FROM_POINT;
+#endif
} else if (filename == kAcrobatReaderPlugin) {
// Check for the version number above or equal 9.
int major_version = GetPluginMajorVersion(plugin_info);
@@ -414,6 +422,14 @@ bool WebPluginDelegateImpl::PlatformInitialize() {
GetProcAddressPatch);
}
+#if defined(USE_AURA)
+ if (windowless_ && !g_iat_patch_window_from_point.Pointer()->is_patched() &&
+ (quirks_ & PLUGIN_QUIRK_FAKE_WINDOW_FROM_POINT)) {
+ g_iat_patch_window_from_point.Pointer()->Patch(
+ GetPluginPath().value().c_str(), "user32.dll", "WindowFromPoint",
+ WebPluginDelegateImpl::WindowFromPointPatch);
+ }
+#endif
return true;
}
@@ -434,6 +450,11 @@ void WebPluginDelegateImpl::PlatformDestroyInstance() {
if (g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched())
g_iat_patch_reg_enum_key_ex_w.Pointer()->Unpatch();
+#if defined(USE_AURA)
+ if (g_iat_patch_window_from_point.Pointer()->is_patched())
+ g_iat_patch_window_from_point.Pointer()->Unpatch();
+#endif
+
if (mouse_hook_) {
UnhookWindowsHookEx(mouse_hook_);
mouse_hook_ = NULL;
@@ -1001,7 +1022,13 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
result = CallWindowProc(
delegate->plugin_wnd_proc_, hwnd, message, wparam, lparam);
- delegate->is_calling_wndproc = false;
+ // The plugin instance may have been destroyed in the CallWindowProc call
+ // above. This will also destroy the plugin window. Before attempting to
+ // access the WebPluginDelegateImpl instance we validate if the window is
+ // still valid.
+ if (::IsWindow(hwnd))
+ delegate->is_calling_wndproc = false;
+
g_current_plugin_instance = last_plugin_instance;
if (message == WM_NCDESTROY) {
@@ -1017,7 +1044,8 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
ClearThrottleQueueForWindow(hwnd);
}
}
- delegate->last_message_ = old_message;
+ if (::IsWindow(hwnd))
+ delegate->last_message_ = old_message;
return result;
}
@@ -1311,6 +1339,12 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent(
ResetEvent(handle_event_pump_messages_event_);
}
+ // If we didn't enter a modal loop, need to unhook the filter.
+ if (handle_event_message_filter_hook_) {
+ UnhookWindowsHookEx(handle_event_message_filter_hook_);
+ handle_event_message_filter_hook_ = NULL;
+ }
+
if (::IsWindow(last_focus_window)) {
// Restore the nestable tasks allowed state in the message loop and reset
// the os modal loop state as the plugin returned from the TrackPopupMenu
@@ -1460,6 +1494,19 @@ FARPROC WINAPI WebPluginDelegateImpl::GetProcAddressPatch(HMODULE module,
return ::GetProcAddress(module, name);
}
+#if defined(USE_AURA)
+HWND WINAPI WebPluginDelegateImpl::WindowFromPointPatch(POINT point) {
+ HWND window = WindowFromPoint(point);
+ if (::ScreenToClient(window, &point)) {
+ HWND child = ChildWindowFromPoint(window, point);
+ if (::IsWindow(child) &&
+ ::GetProp(child, content::kPluginDummyParentProperty))
+ return child;
+ }
+ return window;
+}
+#endif
+
void WebPluginDelegateImpl::HandleCaptureForMessage(HWND window,
UINT message) {
if (gfx::GetClassName(window) != base::string16(kNativeWindowClassName))
diff --git a/chromium/content/child/plugin_messages.h b/chromium/content/child/plugin_messages.h
index 021fa5b59f0..92651e94492 100644
--- a/chromium/content/child/plugin_messages.h
+++ b/chromium/content/child/plugin_messages.h
@@ -111,7 +111,7 @@ IPC_SYNC_MESSAGE_ROUTED0_1(PluginMsg_GetPluginScriptableObject,
// Gets the form value of the plugin instance synchronously.
IPC_SYNC_MESSAGE_ROUTED0_2(PluginMsg_GetFormValue,
- string16 /* value */,
+ base::string16 /* value */,
bool /* success */)
IPC_MESSAGE_ROUTED3(PluginMsg_DidFinishLoadWithReason,
@@ -192,15 +192,18 @@ IPC_MESSAGE_CONTROL1(PluginMsg_ResetModalDialogEvent,
IPC_MESSAGE_ROUTED1(PluginMsg_FetchURL,
PluginMsg_FetchURL_Params)
+IPC_MESSAGE_CONTROL1(PluginHostMsg_DidAbortLoading,
+ int /* render_view_id */)
+
#if defined(OS_WIN)
IPC_MESSAGE_ROUTED4(PluginMsg_ImeCompositionUpdated,
- string16 /* text */,
+ base::string16 /* text */,
std::vector<int> /* clauses */,
std::vector<int>, /* target */
int /* cursor_position */)
IPC_MESSAGE_ROUTED1(PluginMsg_ImeCompositionCompleted,
- string16 /* text */)
+ base::string16 /* text */)
#endif
#if defined(OS_MACOSX)
@@ -219,7 +222,7 @@ IPC_MESSAGE_ROUTED2(PluginMsg_WindowFrameChanged,
gfx::Rect /* view_frame */)
IPC_MESSAGE_ROUTED1(PluginMsg_ImeCompositionCompleted,
- string16 /* text */)
+ base::string16 /* text */)
// This message, used only on 10.6 and later, transmits the "fake"
// window handle allocated by the browser on behalf of the renderer
diff --git a/chromium/content/child/plugin_param_traits.cc b/chromium/content/child/plugin_param_traits.cc
index 7a3908d2962..27b21dd2e68 100644
--- a/chromium/content/child/plugin_param_traits.cc
+++ b/chromium/content/child/plugin_param_traits.cc
@@ -123,13 +123,13 @@ bool ParamTraits<NPIdentifier_Param>::Read(const Message* m,
}
void ParamTraits<NPIdentifier_Param>::Log(const param_type& p, std::string* l) {
- if (WebKit::WebBindings::identifierIsString(p.identifier)) {
- NPUTF8* str = WebKit::WebBindings::utf8FromIdentifier(p.identifier);
+ if (blink::WebBindings::identifierIsString(p.identifier)) {
+ NPUTF8* str = blink::WebBindings::utf8FromIdentifier(p.identifier);
l->append(str);
free(str);
} else {
l->append(base::IntToString(
- WebKit::WebBindings::intFromIdentifier(p.identifier)));
+ blink::WebBindings::intFromIdentifier(p.identifier)));
}
}
diff --git a/chromium/content/child/quota_dispatcher.cc b/chromium/content/child/quota_dispatcher.cc
index 2db02946de9..e6b71145002 100644
--- a/chromium/content/child/quota_dispatcher.cc
+++ b/chromium/content/child/quota_dispatcher.cc
@@ -11,16 +11,16 @@
#include "content/child/quota_message_filter.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/quota_messages.h"
-#include "third_party/WebKit/public/web/WebStorageQuotaCallbacks.h"
-#include "third_party/WebKit/public/web/WebStorageQuotaType.h"
+#include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
+#include "third_party/WebKit/public/platform/WebStorageQuotaType.h"
#include "url/gurl.h"
using quota::QuotaStatusCode;
using quota::StorageType;
-using WebKit::WebStorageQuotaCallbacks;
-using WebKit::WebStorageQuotaError;
-using WebKit::WebStorageQuotaType;
+using blink::WebStorageQuotaCallbacks;
+using blink::WebStorageQuotaError;
+using blink::WebStorageQuotaType;
using webkit_glue::WorkerTaskRunner;
@@ -34,7 +34,7 @@ namespace {
// QuotaDispatcher::Callback implementation for WebStorageQuotaCallbacks.
class WebStorageQuotaDispatcherCallback : public QuotaDispatcher::Callback {
public:
- WebStorageQuotaDispatcherCallback(WebKit::WebStorageQuotaCallbacks* callback)
+ WebStorageQuotaDispatcherCallback(blink::WebStorageQuotaCallbacks* callback)
: callbacks_(callback) {
DCHECK(callbacks_);
}
@@ -51,7 +51,7 @@ class WebStorageQuotaDispatcherCallback : public QuotaDispatcher::Callback {
private:
// Not owned (self-destructed).
- WebKit::WebStorageQuotaCallbacks* callbacks_;
+ blink::WebStorageQuotaCallbacks* callbacks_;
};
int CurrentWorkerId() {
@@ -112,8 +112,8 @@ void QuotaDispatcher::QueryStorageUsageAndQuota(
StorageType type,
Callback* callback) {
DCHECK(callback);
- int request_id = pending_quota_callbacks_.Add(callback);
- quota_message_filter_->RegisterRequestID(request_id, CurrentWorkerId());
+ int request_id = quota_message_filter_->GenerateRequestID(CurrentWorkerId());
+ pending_quota_callbacks_.AddWithID(callback, request_id);
thread_safe_sender_->Send(new QuotaHostMsg_QueryStorageUsageAndQuota(
request_id, origin_url, type));
}
@@ -126,8 +126,8 @@ void QuotaDispatcher::RequestStorageQuota(
Callback* callback) {
DCHECK(callback);
DCHECK(CurrentWorkerId() == 0);
- int request_id = pending_quota_callbacks_.Add(callback);
- quota_message_filter_->RegisterRequestID(request_id, CurrentWorkerId());
+ int request_id = quota_message_filter_->GenerateRequestID(CurrentWorkerId());
+ pending_quota_callbacks_.AddWithID(callback, request_id);
thread_safe_sender_->Send(new QuotaHostMsg_RequestStorageQuota(
render_view_id, request_id, origin_url, type, requested_size));
}
@@ -135,7 +135,7 @@ void QuotaDispatcher::RequestStorageQuota(
// static
QuotaDispatcher::Callback*
QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(
- WebKit::WebStorageQuotaCallbacks* callbacks) {
+ blink::WebStorageQuotaCallbacks* callbacks) {
return new WebStorageQuotaDispatcherCallback(callbacks);
}
@@ -167,14 +167,14 @@ void QuotaDispatcher::DidFail(
pending_quota_callbacks_.Remove(request_id);
}
-COMPILE_ASSERT(int(WebKit::WebStorageQuotaTypeTemporary) == \
+COMPILE_ASSERT(int(blink::WebStorageQuotaTypeTemporary) == \
int(quota::kStorageTypeTemporary), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebStorageQuotaTypePersistent) == \
+COMPILE_ASSERT(int(blink::WebStorageQuotaTypePersistent) == \
int(quota::kStorageTypePersistent), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebStorageQuotaErrorNotSupported) == \
+COMPILE_ASSERT(int(blink::WebStorageQuotaErrorNotSupported) == \
int(quota::kQuotaErrorNotSupported), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebStorageQuotaErrorAbort) == \
+COMPILE_ASSERT(int(blink::WebStorageQuotaErrorAbort) == \
int(quota::kQuotaErrorAbort), mismatching_enums);
} // namespace content
diff --git a/chromium/content/child/quota_dispatcher.h b/chromium/content/child/quota_dispatcher.h
index 8a8754f37a8..d42d02d8d91 100644
--- a/chromium/content/child/quota_dispatcher.h
+++ b/chromium/content/child/quota_dispatcher.h
@@ -20,7 +20,7 @@ namespace IPC {
class Message;
}
-namespace WebKit {
+namespace blink {
class WebStorageQuotaCallbacks;
}
@@ -69,7 +69,7 @@ class QuotaDispatcher : public webkit_glue::WorkerTaskRunner::Observer {
// Creates a new Callback instance for WebStorageQuotaCallbacks.
static Callback* CreateWebStorageQuotaCallbacksWrapper(
- WebKit::WebStorageQuotaCallbacks* callbacks);
+ blink::WebStorageQuotaCallbacks* callbacks);
private:
// Message handlers.
diff --git a/chromium/content/child/quota_message_filter.cc b/chromium/content/child/quota_message_filter.cc
index db512393b24..139be2550de 100644
--- a/chromium/content/child/quota_message_filter.cc
+++ b/chromium/content/child/quota_message_filter.cc
@@ -4,34 +4,49 @@
#include "content/child/quota_message_filter.h"
-#include "base/bind.h"
-#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "base/pickle.h"
#include "content/child/quota_dispatcher.h"
#include "content/child/thread_safe_sender.h"
+#include "content/child/worker_thread_task_runner.h"
#include "content/common/quota_messages.h"
-#include "webkit/child/worker_task_runner.h"
-
-using webkit_glue::WorkerTaskRunner;
namespace content {
QuotaMessageFilter::QuotaMessageFilter(
ThreadSafeSender* thread_safe_sender)
: main_thread_loop_proxy_(base::MessageLoopProxy::current()),
- thread_safe_sender_(thread_safe_sender) {
+ thread_safe_sender_(thread_safe_sender),
+ next_request_id_(0) {
}
-bool QuotaMessageFilter::OnMessageReceived(const IPC::Message& msg) {
+QuotaMessageFilter::~QuotaMessageFilter() {}
+
+int QuotaMessageFilter::GenerateRequestID(int thread_id) {
+ base::AutoLock lock(request_id_map_lock_);
+ request_id_map_[next_request_id_] = thread_id;
+ return next_request_id_++;
+}
+
+void QuotaMessageFilter::ClearThreadRequests(int thread_id) {
+ base::AutoLock lock(request_id_map_lock_);
+ for (RequestIdToThreadId::iterator iter = request_id_map_.begin();
+ iter != request_id_map_.end();) {
+ if (iter->second == thread_id)
+ request_id_map_.erase(iter++);
+ else
+ iter++;
+ }
+}
+
+base::TaskRunner* QuotaMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) {
if (IPC_MESSAGE_CLASS(msg) != QuotaMsgStart)
- return false;
- int request_id = -1;
- bool result = PickleIterator(msg).ReadInt(&request_id);
- DCHECK(result);
- base::Closure closure = base::Bind(
- &QuotaMessageFilter::DispatchMessage, this, msg);
- int thread_id = 0;
+ return NULL;
+
+ int request_id = -1, thread_id = 0;
+ const bool success = PickleIterator(msg).ReadInt(&request_id);
+ DCHECK(success);
+
{
base::AutoLock lock(request_id_map_lock_);
RequestIdToThreadId::iterator found = request_id_map_.find(request_id);
@@ -40,24 +55,18 @@ bool QuotaMessageFilter::OnMessageReceived(const IPC::Message& msg) {
request_id_map_.erase(found);
}
}
- if (!thread_id) {
- main_thread_loop_proxy_->PostTask(FROM_HERE, closure);
- return true;
- }
- WorkerTaskRunner::Instance()->PostTask(thread_id, closure);
- return true;
-}
-void QuotaMessageFilter::RegisterRequestID(int request_id, int thread_id) {
- base::AutoLock lock(request_id_map_lock_);
- request_id_map_[request_id] = thread_id;
+ if (!thread_id)
+ return main_thread_loop_proxy_.get();
+ return new WorkerThreadTaskRunner(thread_id);
}
-QuotaMessageFilter::~QuotaMessageFilter() {}
-
-void QuotaMessageFilter::DispatchMessage(const IPC::Message& msg) {
+bool QuotaMessageFilter::OnMessageReceived(const IPC::Message& msg) {
+ if (IPC_MESSAGE_CLASS(msg) != QuotaMsgStart)
+ return false;
QuotaDispatcher::ThreadSpecificInstance(thread_safe_sender_.get(), this)
->OnMessageReceived(msg);
+ return true;
}
} // namespace content
diff --git a/chromium/content/child/quota_message_filter.h b/chromium/content/child/quota_message_filter.h
index 5e90c6ccc83..eabff1bf8ca 100644
--- a/chromium/content/child/quota_message_filter.h
+++ b/chromium/content/child/quota_message_filter.h
@@ -8,7 +8,7 @@
#include <map>
#include "base/synchronization/lock.h"
-#include "ipc/ipc_channel_proxy.h"
+#include "content/child/child_message_filter.h"
namespace base {
class MessageLoopProxy;
@@ -18,30 +18,35 @@ namespace content {
class ThreadSafeSender;
-class QuotaMessageFilter : public IPC::ChannelProxy::MessageFilter {
+class QuotaMessageFilter : public ChildMessageFilter {
public:
explicit QuotaMessageFilter(ThreadSafeSender* thread_safe_sender);
- // IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
-
- // Registers { request_id, thread_id } map to the message filter.
+ // Generates a new request_id, registers { request_id, thread_id } map to
+ // the message filter and returns the request_id.
// This method can be called on any thread.
- void RegisterRequestID(int request_id, int thread_id);
+ int GenerateRequestID(int thread_id);
+
+ // Clears all requests from the thread_id.
+ void ClearThreadRequests(int thread_id);
protected:
virtual ~QuotaMessageFilter();
private:
- typedef std::map<int, int> RequestIdToThreadId;
+ // ChildMessageFilter implementation:
+ virtual base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- void DispatchMessage(const IPC::Message& msg);
+ typedef std::map<int, int> RequestIdToThreadId;
scoped_refptr<base::MessageLoopProxy> main_thread_loop_proxy_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
base::Lock request_id_map_lock_;
RequestIdToThreadId request_id_map_;
+ int next_request_id_;
DISALLOW_COPY_AND_ASSIGN(QuotaMessageFilter);
};
diff --git a/chromium/content/child/request_extra_data.cc b/chromium/content/child/request_extra_data.cc
index 2c935cee34b..965066dfd92 100644
--- a/chromium/content/child/request_extra_data.cc
+++ b/chromium/content/child/request_extra_data.cc
@@ -4,14 +4,15 @@
#include "content/child/request_extra_data.h"
-using WebKit::WebReferrerPolicy;
-using WebKit::WebString;
+using blink::WebReferrerPolicy;
+using blink::WebString;
namespace content {
RequestExtraData::RequestExtraData(WebReferrerPolicy referrer_policy,
const WebString& custom_user_agent,
bool was_after_preconnect_request,
+ int render_frame_id,
bool is_main_frame,
int64 frame_id,
const GURL& frame_origin,
@@ -19,11 +20,13 @@ RequestExtraData::RequestExtraData(WebReferrerPolicy referrer_policy,
int64 parent_frame_id,
bool allow_download,
PageTransition transition_type,
+ bool should_replace_current_entry,
int transferred_request_child_id,
int transferred_request_request_id)
: webkit_glue::WebURLRequestExtraDataImpl(referrer_policy,
custom_user_agent,
was_after_preconnect_request),
+ render_frame_id_(render_frame_id),
is_main_frame_(is_main_frame),
frame_id_(frame_id),
frame_origin_(frame_origin),
@@ -31,6 +34,7 @@ RequestExtraData::RequestExtraData(WebReferrerPolicy referrer_policy,
parent_frame_id_(parent_frame_id),
allow_download_(allow_download),
transition_type_(transition_type),
+ should_replace_current_entry_(should_replace_current_entry),
transferred_request_child_id_(transferred_request_child_id),
transferred_request_request_id_(transferred_request_request_id) {
}
diff --git a/chromium/content/child/request_extra_data.h b/chromium/content/child/request_extra_data.h
index 0b3d30a2fc0..bdb2a72bc50 100644
--- a/chromium/content/child/request_extra_data.h
+++ b/chromium/content/child/request_extra_data.h
@@ -13,13 +13,14 @@
namespace content {
// The RenderView stores an instance of this class in the "extra data" of each
-// ResourceRequest (see RenderView::willSendRequest).
+// ResourceRequest (see RenderFrameImpl::willSendRequest).
class CONTENT_EXPORT RequestExtraData
: NON_EXPORTED_BASE(public webkit_glue::WebURLRequestExtraDataImpl) {
public:
- RequestExtraData(WebKit::WebReferrerPolicy referrer_policy,
- const WebKit::WebString& custom_user_agent,
+ RequestExtraData(blink::WebReferrerPolicy referrer_policy,
+ const blink::WebString& custom_user_agent,
bool was_after_preconnect_request,
+ int render_frame_id,
bool is_main_frame,
int64 frame_id,
const GURL& frame_origin,
@@ -27,10 +28,12 @@ class CONTENT_EXPORT RequestExtraData
int64 parent_frame_id,
bool allow_download,
PageTransition transition_type,
+ bool should_replace_current_entry,
int transferred_request_child_id,
int transferred_request_request_id);
virtual ~RequestExtraData();
+ int render_frame_id() const { return render_frame_id_; }
bool is_main_frame() const { return is_main_frame_; }
int64 frame_id() const { return frame_id_; }
GURL frame_origin() const { return frame_origin_; }
@@ -38,6 +41,9 @@ class CONTENT_EXPORT RequestExtraData
int64 parent_frame_id() const { return parent_frame_id_; }
bool allow_download() const { return allow_download_; }
PageTransition transition_type() const { return transition_type_; }
+ bool should_replace_current_entry() const {
+ return should_replace_current_entry_;
+ }
int transferred_request_child_id() const {
return transferred_request_child_id_;
}
@@ -46,6 +52,7 @@ class CONTENT_EXPORT RequestExtraData
}
private:
+ int render_frame_id_;
bool is_main_frame_;
int64 frame_id_;
GURL frame_origin_;
@@ -53,6 +60,7 @@ class CONTENT_EXPORT RequestExtraData
int64 parent_frame_id_;
bool allow_download_;
PageTransition transition_type_;
+ bool should_replace_current_entry_;
int transferred_request_child_id_;
int transferred_request_request_id_;
diff --git a/chromium/content/child/resource_dispatcher.cc b/chromium/content/child/resource_dispatcher.cc
index 003a360bac9..c5243b56dde 100644
--- a/chromium/content/child/resource_dispatcher.cc
+++ b/chromium/content/child/resource_dispatcher.cc
@@ -129,24 +129,29 @@ IPCResourceLoaderBridge::IPCResourceLoaderBridge(
if (request_info.extra_data) {
RequestExtraData* extra_data =
static_cast<RequestExtraData*>(request_info.extra_data);
+ request_.render_frame_id = extra_data->render_frame_id();
request_.is_main_frame = extra_data->is_main_frame();
request_.frame_id = extra_data->frame_id();
request_.parent_is_main_frame = extra_data->parent_is_main_frame();
request_.parent_frame_id = extra_data->parent_frame_id();
request_.allow_download = extra_data->allow_download();
request_.transition_type = extra_data->transition_type();
+ request_.should_replace_current_entry =
+ extra_data->should_replace_current_entry();
request_.transferred_request_child_id =
extra_data->transferred_request_child_id();
request_.transferred_request_request_id =
extra_data->transferred_request_request_id();
frame_origin_ = extra_data->frame_origin();
} else {
+ request_.render_frame_id = MSG_ROUTING_NONE;
request_.is_main_frame = false;
request_.frame_id = -1;
request_.parent_is_main_frame = false;
request_.parent_frame_id = -1;
request_.allow_download = true;
request_.transition_type = PAGE_TRANSITION_LINK;
+ request_.should_replace_current_entry = false;
request_.transferred_request_child_id = -1;
request_.transferred_request_request_id = -1;
}
@@ -338,6 +343,7 @@ void ResourceDispatcher::OnUploadProgress(int request_id, int64 position,
void ResourceDispatcher::OnReceivedResponse(
int request_id, const ResourceResponseHead& response_head) {
+ TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedResponse");
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
return;
@@ -376,6 +382,7 @@ void ResourceDispatcher::OnSetDataBuffer(int request_id,
base::SharedMemoryHandle shm_handle,
int shm_size,
base::ProcessId renderer_pid) {
+ TRACE_EVENT0("loader", "ResourceDispatcher::OnSetDataBuffer");
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
return;
@@ -406,6 +413,8 @@ void ResourceDispatcher::OnReceivedData(int request_id,
int data_offset,
int data_length,
int encoded_data_length) {
+ TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedData");
+ DCHECK_GT(data_length, 0);
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (request_info && data_length > 0) {
CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle()));
@@ -467,6 +476,7 @@ void ResourceDispatcher::OnReceivedRedirect(
int request_id,
const GURL& new_url,
const ResourceResponseHead& response_head) {
+ TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedRedirect");
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
return;
@@ -513,6 +523,7 @@ void ResourceDispatcher::OnRequestComplete(
bool was_ignored_by_handler,
const std::string& security_info,
const base::TimeTicks& browser_completion_time) {
+ TRACE_EVENT0("loader", "ResourceDispatcher::OnRequestComplete");
SiteIsolationPolicy::OnRequestComplete(request_id);
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
diff --git a/chromium/content/child/resource_dispatcher_unittest.cc b/chromium/content/child/resource_dispatcher_unittest.cc
index b072ecf55b1..349ce8ca9de 100644
--- a/chromium/content/child/resource_dispatcher_unittest.cc
+++ b/chromium/content/child/resource_dispatcher_unittest.cc
@@ -173,11 +173,11 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
request_info.request_type = ResourceType::SUB_RESOURCE;
request_info.appcache_host_id = appcache::kNoHostId;
request_info.routing_id = 0;
- RequestExtraData extra_data(WebKit::WebReferrerPolicyDefault,
- WebKit::WebString(),
- false, true, 0, GURL(),
+ RequestExtraData extra_data(blink::WebReferrerPolicyDefault,
+ blink::WebString(),
+ false, MSG_ROUTING_NONE, true, 0, GURL(),
false, -1, true,
- PAGE_TRANSITION_LINK, -1, -1);
+ PAGE_TRANSITION_LINK, false, -1, -1);
request_info.extra_data = &extra_data;
return dispatcher_->CreateBridge(request_info);
diff --git a/chromium/content/child/runtime_features.cc b/chromium/content/child/runtime_features.cc
index f3af7207df3..66fa73a25fc 100644
--- a/chromium/content/child/runtime_features.cc
+++ b/chromium/content/child/runtime_features.cc
@@ -10,41 +10,38 @@
#if defined(OS_ANDROID)
#include <cpu-features.h>
-#include "base/android/build_info.h"
+#include "media/base/android/media_codec_bridge.h"
#endif
-using WebKit::WebRuntimeFeatures;
+using blink::WebRuntimeFeatures;
namespace content {
static void SetRuntimeFeatureDefaultsForPlatform() {
#if defined(OS_ANDROID)
#if !defined(GOOGLE_TV)
- // MSE/EME implementation needs Android MediaCodec API that was introduced
- // in JellyBrean.
- if (base::android::BuildInfo::GetInstance()->sdk_int() < 16) {
+ // MSE/EME implementation needs Android MediaCodec API.
+ if (!media::MediaCodecBridge::IsAvailable()) {
WebRuntimeFeatures::enableWebKitMediaSource(false);
WebRuntimeFeatures::enableMediaSource(false);
- WebRuntimeFeatures::enableLegacyEncryptedMedia(false);
+ WebRuntimeFeatures::enablePrefixedEncryptedMedia(false);
}
#endif // !defined(GOOGLE_TV)
- bool enable_webaudio = false;
-#if defined(ARCH_CPU_ARMEL)
- // WebAudio needs Android MediaCodec API that was introduced in
- // JellyBean, and also currently needs NEON support for the FFT.
- enable_webaudio =
- (base::android::BuildInfo::GetInstance()->sdk_int() >= 16) &&
- ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0);
-#endif // defined(ARCH_CPU_ARMEL)
- WebRuntimeFeatures::enableWebAudio(enable_webaudio);
+ // WebAudio is enabled by default only on ARM and only when the
+ // MediaCodec API is available.
+ WebRuntimeFeatures::enableWebAudio(
+ media::MediaCodecBridge::IsAvailable() &&
+ (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM));
// Android does not support the Gamepad API.
WebRuntimeFeatures::enableGamepad(false);
// Android does not have support for PagePopup
WebRuntimeFeatures::enablePagePopup(false);
- // datalist on Android is not enabled
- WebRuntimeFeatures::enableDataListElement(false);
// Android does not yet support the Web Notification API. crbug.com/115320
WebRuntimeFeatures::enableNotifications(false);
+ // Android does not yet support SharedWorker. crbug.com/154571
+ WebRuntimeFeatures::enableSharedWorker(false);
+ // Android does not yet support NavigatorContentUtils.
+ WebRuntimeFeatures::enableNavigatorContentUtils(false);
#endif // defined(OS_ANDROID)
}
@@ -66,6 +63,9 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kDisableDesktopNotifications))
WebRuntimeFeatures::enableNotifications(false);
+ if (command_line.HasSwitch(switches::kDisableNavigatorContentUtils))
+ WebRuntimeFeatures::enableNavigatorContentUtils(false);
+
if (command_line.HasSwitch(switches::kDisableLocalStorage))
WebRuntimeFeatures::enableLocalStorage(false);
@@ -81,6 +81,9 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kDisableUnprefixedMediaSource))
WebRuntimeFeatures::enableMediaSource(false);
+ if (command_line.HasSwitch(switches::kDisableSharedWorkers))
+ WebRuntimeFeatures::enableSharedWorker(false);
+
#if defined(OS_ANDROID)
if (command_line.HasSwitch(switches::kDisableWebRTC)) {
WebRuntimeFeatures::enableMediaStream(false);
@@ -91,8 +94,28 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::enableScriptedSpeech(false);
#endif
+ if (command_line.HasSwitch(switches::kEnableServiceWorker))
+ WebRuntimeFeatures::enableServiceWorker(true);
+
+#if defined(OS_ANDROID)
+ // WebAudio requires the MediaCodec API.
+#if defined(ARCH_CPU_X86)
+ // WebAudio is disabled by default on x86.
+ WebRuntimeFeatures::enableWebAudio(
+ command_line.HasSwitch(switches::kEnableWebAudio) &&
+ media::MediaCodecBridge::IsAvailable());
+#elif defined(ARCH_CPU_ARMEL)
+ // WebAudio is enabled by default on ARM.
+ WebRuntimeFeatures::enableWebAudio(
+ !command_line.HasSwitch(switches::kDisableWebAudio) &&
+ media::MediaCodecBridge::IsAvailable());
+#else
+ WebRuntimeFeatures::enableWebAudio(false);
+#endif
+#else
if (command_line.HasSwitch(switches::kDisableWebAudio))
WebRuntimeFeatures::enableWebAudio(false);
+#endif
if (command_line.HasSwitch(switches::kDisableFullScreen))
WebRuntimeFeatures::enableFullscreen(false);
@@ -100,14 +123,18 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kEnableEncryptedMedia))
WebRuntimeFeatures::enableEncryptedMedia(true);
- if (command_line.HasSwitch(switches::kDisableLegacyEncryptedMedia))
- WebRuntimeFeatures::enableLegacyEncryptedMedia(false);
+ if (command_line.HasSwitch(switches::kDisablePrefixedEncryptedMedia))
+ WebRuntimeFeatures::enablePrefixedEncryptedMedia(false);
+ // FIXME: Remove the enable switch once Web Animations CSS is enabled by
+ // default in Blink.
if (command_line.HasSwitch(switches::kEnableWebAnimationsCSS))
- WebRuntimeFeatures::enableWebAnimationsCSS();
+ WebRuntimeFeatures::enableWebAnimationsCSS(true);
+ else if (command_line.HasSwitch(switches::kDisableWebAnimationsCSS))
+ WebRuntimeFeatures::enableWebAnimationsCSS(false);
if (command_line.HasSwitch(switches::kEnableWebAnimationsSVG))
- WebRuntimeFeatures::enableWebAnimationsSVG();
+ WebRuntimeFeatures::enableWebAnimationsSVG(true);
if (command_line.HasSwitch(switches::kEnableWebMIDI))
WebRuntimeFeatures::enableWebMIDI(true);
@@ -124,6 +151,11 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kDisableFileSystem))
WebRuntimeFeatures::enableFileSystem(false);
+#if defined(OS_WIN)
+ if (command_line.HasSwitch(switches::kEnableDirectWrite))
+ WebRuntimeFeatures::enableDirectWrite(true);
+#endif
+
if (command_line.HasSwitch(switches::kEnableExperimentalCanvasFeatures))
WebRuntimeFeatures::enableExperimentalCanvasFeatures(true);
@@ -144,6 +176,12 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kEnableInputModeAttribute))
WebRuntimeFeatures::enableInputModeAttribute(true);
+
+ if (command_line.HasSwitch(switches::kEnableFastTextAutosizing))
+ WebRuntimeFeatures::enableFastTextAutosizing(true);
+
+ if (command_line.HasSwitch(switches::kEnableRepaintAfterLayout))
+ WebRuntimeFeatures::enableRepaintAfterLayout(true);
}
} // namespace content
diff --git a/chromium/content/child/scoped_child_process_reference.cc b/chromium/content/child/scoped_child_process_reference.cc
new file mode 100644
index 00000000000..f7d35fb2842
--- /dev/null
+++ b/chromium/content/child/scoped_child_process_reference.cc
@@ -0,0 +1,34 @@
+// 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/child/scoped_child_process_reference.h"
+
+#include "base/bind.h"
+#include "base/time/time.h"
+#include "content/child/child_process.h"
+
+namespace content {
+
+ScopedChildProcessReference::ScopedChildProcessReference()
+ : has_reference_(true) {
+ ChildProcess::current()->AddRefProcess();
+}
+
+ScopedChildProcessReference::~ScopedChildProcessReference() {
+ if (has_reference_)
+ ChildProcess::current()->ReleaseProcess();
+}
+
+void ScopedChildProcessReference::ReleaseWithDelay(
+ const base::TimeDelta& delay) {
+ DCHECK(has_reference_);
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&ChildProcess::ReleaseProcess,
+ base::Unretained(ChildProcess::current())),
+ delay);
+ has_reference_ = false;
+}
+
+} // namespace content
diff --git a/chromium/content/child/scoped_child_process_reference.h b/chromium/content/child/scoped_child_process_reference.h
new file mode 100644
index 00000000000..3f9ba6cbb6f
--- /dev/null
+++ b/chromium/content/child/scoped_child_process_reference.h
@@ -0,0 +1,37 @@
+// 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_CHILD_SCOPED_CHILD_PROCESS_REFERENCE_H_
+#define CONTENT_CHILD_SCOPED_CHILD_PROCESS_REFERENCE_H_
+
+#include "base/basictypes.h"
+
+namespace base {
+class TimeDelta;
+}
+
+namespace content {
+
+// Scoper class that automatically adds a reference to the current child
+// process in constructor and releases the reference on scope out.
+// Consumers of this class can call ReleaseWithDelay() to explicitly release
+// the reference with a certain delay.
+class ScopedChildProcessReference {
+ public:
+ ScopedChildProcessReference();
+ ~ScopedChildProcessReference();
+
+ // Releases the process reference after |delay|. Once this is called
+ // scoping out has no effect.
+ // It is not valid to call this more than once.
+ void ReleaseWithDelay(const base::TimeDelta& delay);
+
+ private:
+ bool has_reference_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedChildProcessReference);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_SCOPED_CHILD_PROCESS_REFERENCE_H_
diff --git a/chromium/content/child/service_worker/OWNERS b/chromium/content/child/service_worker/OWNERS
new file mode 100644
index 00000000000..633b8a4fd96
--- /dev/null
+++ b/chromium/content/child/service_worker/OWNERS
@@ -0,0 +1,3 @@
+alecflett@chromium.org
+kinuko@chromium.org
+michaeln@chromium.org
diff --git a/chromium/content/child/service_worker/service_worker_dispatcher.cc b/chromium/content/child/service_worker/service_worker_dispatcher.cc
new file mode 100644
index 00000000000..30941221eea
--- /dev/null
+++ b/chromium/content/child/service_worker/service_worker_dispatcher.cc
@@ -0,0 +1,150 @@
+// 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/child/service_worker/service_worker_dispatcher.h"
+
+#include "base/lazy_instance.h"
+#include "base/threading/thread_local.h"
+#include "content/child/service_worker/web_service_worker_impl.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/common/service_worker_messages.h"
+#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
+
+using blink::WebServiceWorkerError;
+using blink::WebServiceWorkerProvider;
+using base::ThreadLocalPointer;
+using webkit_glue::WorkerTaskRunner;
+
+namespace content {
+
+namespace {
+
+base::LazyInstance<ThreadLocalPointer<ServiceWorkerDispatcher> >::Leaky
+ g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
+
+ServiceWorkerDispatcher* const kHasBeenDeleted =
+ reinterpret_cast<ServiceWorkerDispatcher*>(0x1);
+
+int CurrentWorkerId() {
+ return WorkerTaskRunner::Instance()->CurrentWorkerId();
+}
+
+} // namespace
+
+ServiceWorkerDispatcher::ServiceWorkerDispatcher(
+ ThreadSafeSender* thread_safe_sender)
+ : thread_safe_sender_(thread_safe_sender) {
+ g_dispatcher_tls.Pointer()->Set(this);
+}
+
+ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
+ g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
+}
+
+void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered,
+ OnUnregistered)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
+ OnRegistrationError)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ DCHECK(handled) << "Unhandled message:" << msg.type();
+}
+
+bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
+ return thread_safe_sender_->Send(msg);
+}
+
+void ServiceWorkerDispatcher::RegisterServiceWorker(
+ const GURL& pattern,
+ const GURL& script_url,
+ WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks) {
+ DCHECK(callbacks);
+ int request_id = pending_callbacks_.Add(callbacks);
+ thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
+ CurrentWorkerId(), request_id, pattern, script_url));
+}
+
+void ServiceWorkerDispatcher::UnregisterServiceWorker(
+ const GURL& pattern,
+ WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks) {
+ DCHECK(callbacks);
+ int request_id = pending_callbacks_.Add(callbacks);
+ thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
+ CurrentWorkerId(), request_id, pattern));
+}
+
+ServiceWorkerDispatcher* ServiceWorkerDispatcher::ThreadSpecificInstance(
+ ThreadSafeSender* thread_safe_sender) {
+ if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
+ NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
+ g_dispatcher_tls.Pointer()->Set(NULL);
+ }
+ if (g_dispatcher_tls.Pointer()->Get())
+ return g_dispatcher_tls.Pointer()->Get();
+
+ ServiceWorkerDispatcher* dispatcher =
+ new ServiceWorkerDispatcher(thread_safe_sender);
+ if (WorkerTaskRunner::Instance()->CurrentWorkerId())
+ webkit_glue::WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
+ return dispatcher;
+}
+
+void ServiceWorkerDispatcher::OnRegistered(int32 thread_id,
+ int32 request_id,
+ int64 registration_id) {
+ WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
+ pending_callbacks_.Lookup(request_id);
+ DCHECK(callbacks);
+ if (!callbacks)
+ return;
+
+ // the browser has to generate the registration_id so the same
+ // worker can be called from different renderer contexts. However,
+ // the impl object doesn't have to be the same instance across calls
+ // unless we require the DOM objects to be identical when there's a
+ // duplicate registration. So for now we mint a new object each
+ // time.
+ scoped_ptr<WebServiceWorkerImpl> worker(
+ new WebServiceWorkerImpl(registration_id));
+ callbacks->onSuccess(worker.release());
+ pending_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerDispatcher::OnUnregistered(
+ int32 thread_id,
+ int32 request_id) {
+ WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
+ pending_callbacks_.Lookup(request_id);
+ DCHECK(callbacks);
+ if (!callbacks)
+ return;
+
+ callbacks->onSuccess(NULL);
+ pending_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerDispatcher::OnRegistrationError(
+ int32 thread_id,
+ int32 request_id,
+ WebServiceWorkerError::ErrorType error_type,
+ const base::string16& message) {
+ WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
+ pending_callbacks_.Lookup(request_id);
+ DCHECK(callbacks);
+ if (!callbacks)
+ return;
+
+ scoped_ptr<WebServiceWorkerError> error(
+ new WebServiceWorkerError(error_type, message));
+ callbacks->onError(error.release());
+ pending_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() { delete this; }
+
+} // namespace content
diff --git a/chromium/content/child/service_worker/service_worker_dispatcher.h b/chromium/content/child/service_worker/service_worker_dispatcher.h
new file mode 100644
index 00000000000..72be7064eee
--- /dev/null
+++ b/chromium/content/child/service_worker/service_worker_dispatcher.h
@@ -0,0 +1,80 @@
+// 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_CHILD_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_H_
+#define CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_H_
+
+#include "base/id_map.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string16.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerProvider.h"
+#include "webkit/child/worker_task_runner.h"
+
+class GURL;
+
+namespace blink {
+class WebURL;
+}
+
+namespace IPC {
+class Message;
+}
+
+namespace content {
+class ServiceWorkerMessageFilter;
+class ThreadSafeSender;
+class WebServiceWorkerImpl;
+
+// This class manages communication with the browser process about
+// registration of the service worker, exposed to renderer and worker
+// scripts through methods like navigator.registerServiceWorker().
+class ServiceWorkerDispatcher : public webkit_glue::WorkerTaskRunner::Observer {
+ public:
+ explicit ServiceWorkerDispatcher(ThreadSafeSender* thread_safe_sender);
+ virtual ~ServiceWorkerDispatcher();
+
+ void OnMessageReceived(const IPC::Message& msg);
+ bool Send(IPC::Message* msg);
+
+ // Corresponds to navigator.registerServiceWorker()
+ void RegisterServiceWorker(
+ const GURL& pattern,
+ const GURL& script_url,
+ blink::WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks);
+ // Corresponds to navigator.unregisterServiceWorker()
+ void UnregisterServiceWorker(
+ const GURL& pattern,
+ blink::WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks);
+
+ // |thread_safe_sender| needs to be passed in because if the call leads to
+ // construction it will be needed.
+ static ServiceWorkerDispatcher* ThreadSpecificInstance(
+ ThreadSafeSender* thread_safe_sender);
+
+ private:
+ // webkit_glue::WorkerTaskRunner::Observer implementation.
+ virtual void OnWorkerRunLoopStopped() OVERRIDE;
+
+ // The asynchronous success response to RegisterServiceWorker.
+ void OnRegistered(int32 thread_id, int32 request_id, int64 registration_id);
+ // The asynchronous success response to UregisterServiceWorker.
+ void OnUnregistered(int32 thread_id,
+ int32 request_id);
+ void OnRegistrationError(int32 thread_id,
+ int32 request_id,
+ blink::WebServiceWorkerError::ErrorType error_type,
+ const base::string16& message);
+
+ IDMap<blink::WebServiceWorkerProvider::WebServiceWorkerCallbacks,
+ IDMapOwnPointer> pending_callbacks_;
+
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_H_
diff --git a/chromium/content/child/service_worker/service_worker_message_filter.cc b/chromium/content/child/service_worker/service_worker_message_filter.cc
new file mode 100644
index 00000000000..e6b5ff1d14b
--- /dev/null
+++ b/chromium/content/child/service_worker/service_worker_message_filter.cc
@@ -0,0 +1,41 @@
+// 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/child/service_worker/service_worker_message_filter.h"
+
+#include "base/message_loop/message_loop_proxy.h"
+#include "content/child/service_worker/service_worker_dispatcher.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/child/worker_thread_task_runner.h"
+#include "ipc/ipc_message_macros.h"
+
+namespace content {
+
+ServiceWorkerMessageFilter::ServiceWorkerMessageFilter(ThreadSafeSender* sender)
+ : main_thread_loop_proxy_(base::MessageLoopProxy::current()),
+ thread_safe_sender_(sender) {}
+
+ServiceWorkerMessageFilter::~ServiceWorkerMessageFilter() {}
+
+base::TaskRunner* ServiceWorkerMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) {
+ if (IPC_MESSAGE_CLASS(msg) != ServiceWorkerMsgStart)
+ return NULL;
+ int ipc_thread_id = 0;
+ const bool success = PickleIterator(msg).ReadInt(&ipc_thread_id);
+ DCHECK(success);
+ if (!ipc_thread_id)
+ return main_thread_loop_proxy_.get();
+ return new WorkerThreadTaskRunner(ipc_thread_id);
+}
+
+bool ServiceWorkerMessageFilter::OnMessageReceived(const IPC::Message& msg) {
+ if (IPC_MESSAGE_CLASS(msg) != ServiceWorkerMsgStart)
+ return false;
+ ServiceWorkerDispatcher::ThreadSpecificInstance(thread_safe_sender_.get())
+ ->OnMessageReceived(msg);
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/child/service_worker/service_worker_message_filter.h b/chromium/content/child/service_worker/service_worker_message_filter.h
new file mode 100644
index 00000000000..f14cbcf5cd6
--- /dev/null
+++ b/chromium/content/child/service_worker/service_worker_message_filter.h
@@ -0,0 +1,41 @@
+// 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_CHILD_SERVICE_WORKER_SERVICE_WORKER_MESSAGE_FILTER_H_
+#define CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_MESSAGE_FILTER_H_
+
+#include "content/child/child_message_filter.h"
+#include "content/common/content_export.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace content {
+
+class ThreadSafeSender;
+
+class CONTENT_EXPORT ServiceWorkerMessageFilter
+ : public NON_EXPORTED_BASE(ChildMessageFilter) {
+ public:
+ explicit ServiceWorkerMessageFilter(ThreadSafeSender* thread_safe_sender);
+
+ protected:
+ virtual ~ServiceWorkerMessageFilter();
+
+ private:
+ // ChildMessageFilter implementation:
+ virtual base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ scoped_refptr<base::MessageLoopProxy> main_thread_loop_proxy_;
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_MESSAGE_FILTER_H_
diff --git a/chromium/content/child/service_worker/web_service_worker_impl.cc b/chromium/content/child/service_worker/web_service_worker_impl.cc
new file mode 100644
index 00000000000..02d9cf8ca77
--- /dev/null
+++ b/chromium/content/child/service_worker/web_service_worker_impl.cc
@@ -0,0 +1,11 @@
+// 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/child/service_worker/web_service_worker_impl.h"
+
+namespace content {
+
+WebServiceWorkerImpl::~WebServiceWorkerImpl() {}
+
+} // namespace content
diff --git a/chromium/content/child/service_worker/web_service_worker_impl.h b/chromium/content/child/service_worker/web_service_worker_impl.h
new file mode 100644
index 00000000000..de6010e212c
--- /dev/null
+++ b/chromium/content/child/service_worker/web_service_worker_impl.h
@@ -0,0 +1,29 @@
+// 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_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_IMPL_H_
+#define CONTENT_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_IMPL_H_
+
+#include "base/compiler_specific.h"
+#include "third_party/WebKit/public/platform/WebServiceWorker.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+
+namespace content {
+
+class WebServiceWorkerImpl
+ : NON_EXPORTED_BASE(public blink::WebServiceWorker) {
+ public:
+ explicit WebServiceWorkerImpl(int64 registration_id)
+ : registration_id_(registration_id) {}
+ virtual ~WebServiceWorkerImpl();
+
+ private:
+ int64 registration_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_IMPL_H_
diff --git a/chromium/content/child/service_worker/web_service_worker_provider_impl.cc b/chromium/content/child/service_worker/web_service_worker_provider_impl.cc
new file mode 100644
index 00000000000..c259f181375
--- /dev/null
+++ b/chromium/content/child/service_worker/web_service_worker_provider_impl.cc
@@ -0,0 +1,59 @@
+// 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/child/service_worker/web_service_worker_provider_impl.h"
+
+#include "base/atomic_sequence_num.h"
+#include "base/logging.h"
+#include "content/child/child_thread.h"
+#include "content/child/service_worker/service_worker_dispatcher.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/common/service_worker_messages.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+
+using blink::WebURL;
+
+namespace content {
+
+namespace {
+
+// Must be unique in the child process.
+int GetNextProviderId() {
+ static base::StaticAtomicSequenceNumber sequence;
+ return sequence.GetNext() + 1; // We want to start at 1.
+}
+
+} // namespace
+
+WebServiceWorkerProviderImpl::WebServiceWorkerProviderImpl(
+ ThreadSafeSender* thread_safe_sender,
+ scoped_ptr<blink::WebServiceWorkerProviderClient> client)
+ : provider_id_(GetNextProviderId()),
+ thread_safe_sender_(thread_safe_sender),
+ client_(client.Pass()) {
+ thread_safe_sender_->Send(
+ new ServiceWorkerHostMsg_ProviderCreated(provider_id_));
+}
+
+WebServiceWorkerProviderImpl::~WebServiceWorkerProviderImpl() {
+ thread_safe_sender_->Send(
+ new ServiceWorkerHostMsg_ProviderDestroyed(provider_id_));
+}
+
+void WebServiceWorkerProviderImpl::registerServiceWorker(
+ const WebURL& pattern,
+ const WebURL& script_url,
+ WebServiceWorkerCallbacks* callbacks) {
+ ServiceWorkerDispatcher::ThreadSpecificInstance(thread_safe_sender_)
+ ->RegisterServiceWorker(pattern, script_url, callbacks);
+}
+
+void WebServiceWorkerProviderImpl::unregisterServiceWorker(
+ const WebURL& pattern,
+ WebServiceWorkerCallbacks* callbacks) {
+ ServiceWorkerDispatcher::ThreadSpecificInstance(thread_safe_sender_)
+ ->UnregisterServiceWorker(pattern, callbacks);
+}
+
+} // namespace content
diff --git a/chromium/content/child/service_worker/web_service_worker_provider_impl.h b/chromium/content/child/service_worker/web_service_worker_provider_impl.h
new file mode 100644
index 00000000000..45fe4aca96a
--- /dev/null
+++ b/chromium/content/child/service_worker/web_service_worker_provider_impl.h
@@ -0,0 +1,49 @@
+// 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_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_PROVIDER_IMPL_H_
+#define CONTENT_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_PROVIDER_IMPL_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerProvider.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
+
+namespace blink {
+class WebURL;
+}
+
+namespace content {
+
+class ThreadSafeSender;
+
+class WebServiceWorkerProviderImpl
+ : NON_EXPORTED_BASE(public blink::WebServiceWorkerProvider) {
+ public:
+ WebServiceWorkerProviderImpl(
+ ThreadSafeSender* thread_safe_sender,
+ scoped_ptr<blink::WebServiceWorkerProviderClient> client);
+ virtual ~WebServiceWorkerProviderImpl();
+
+ int provider_id() const { return provider_id_; }
+
+ virtual void registerServiceWorker(const blink::WebURL& pattern,
+ const blink::WebURL& script_url,
+ WebServiceWorkerCallbacks*);
+
+ virtual void unregisterServiceWorker(const blink::WebURL& pattern,
+ WebServiceWorkerCallbacks*);
+
+ private:
+ const int provider_id_;
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+ scoped_ptr<blink::WebServiceWorkerProviderClient> client_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerProviderImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_PROVIDER_IMPL_H_
diff --git a/chromium/content/child/site_isolation_policy.cc b/chromium/content/child/site_isolation_policy.cc
index 9782f068878..e98d744194d 100644
--- a/chromium/content/child/site_isolation_policy.cc
+++ b/chromium/content/child/site_isolation_policy.cc
@@ -6,10 +6,12 @@
#include "base/basictypes.h"
#include "base/command_line.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
+#include "content/child/child_thread.h"
#include "content/public/common/content_switches.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/http/http_response_headers.h"
@@ -23,16 +25,33 @@
#include "third_party/WebKit/public/web/WebFrameClient.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
-using WebKit::WebDocument;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebURLResponse;
-using WebKit::WebURLRequest;
+using base::StringPiece;
+using blink::WebDocument;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebURLResponse;
+using blink::WebURLRequest;
namespace content {
namespace {
+// Maintain the bookkeeping data between OnReceivedResponse and
+// OnReceivedData. The key is a request id maintained by ResourceDispatcher.
+static base::LazyInstance<SiteIsolationPolicy::RequestIdToMetaDataMap>
+ g_metadata_map = LAZY_INSTANCE_INITIALIZER;
+
+// Maintain the bookkeeping data for OnReceivedData. Blocking decision is made
+// when OnReceivedData is called for the first time for a request, and the
+// decision will remain the same for following data. This map maintains the
+// decision. The key is a request id maintained by ResourceDispatcher.
+static base::LazyInstance<SiteIsolationPolicy::RequestIdToResultMap>
+ g_result_map = LAZY_INSTANCE_INITIALIZER;
+
+// The cross-site document blocking/UMA data collection is deactivated by
+// default, and only activated in renderer processes.
+static bool g_policy_enabled = false;
+
// MIME types
const char kTextHtml[] = "text/html";
const char kTextXml[] = "text/xml";
@@ -43,13 +62,105 @@ const char kTextJson[] = "text/json";
const char kTextXjson[] = "text/x-json";
const char kTextPlain[] = "text/plain";
-} // anonymous namespace
+// TODO(dsjang): this is only needed for collecting UMA stat. Will be deleted
+// when this class is used for actual blocking.
+bool IsRenderableStatusCode(int status_code) {
+ // Chrome only uses the content of a response with one of these status codes
+ // for CSS/JavaScript. For images, Chrome just ignores status code.
+ const int renderable_status_code[] = {200, 201, 202, 203, 206, 300,
+ 301, 302, 303, 305, 306, 307};
+ for (size_t i = 0; i < arraysize(renderable_status_code); ++i) {
+ if (renderable_status_code[i] == status_code)
+ return true;
+ }
+ return false;
+}
-SiteIsolationPolicy::ResponseMetaData::ResponseMetaData() {}
+bool MatchesSignature(StringPiece data,
+ const StringPiece signatures[],
+ size_t arr_size) {
-// The cross-site document blocking/UMA data collection is deactivated by
-// default, and only activated in renderer processes.
-bool SiteIsolationPolicy::g_policy_enabled = false;
+ size_t offset = data.find_first_not_of(" \t\r\n");
+ // There is no not-whitespace character in this document.
+ if (offset == base::StringPiece::npos)
+ return false;
+
+ data.remove_prefix(offset);
+ size_t length = data.length();
+
+ for (size_t sig_index = 0; sig_index < arr_size; ++sig_index) {
+ const StringPiece& signature = signatures[sig_index];
+ size_t signature_length = signature.length();
+ if (length < signature_length)
+ continue;
+
+ if (LowerCaseEqualsASCII(
+ data.begin(), data.begin() + signature_length, signature.data()))
+ return true;
+ }
+ return false;
+}
+
+void IncrementHistogramCount(const std::string& name) {
+ // The default value of min, max, bucket_count are copied from histogram.h.
+ base::HistogramBase* histogram_pointer = base::Histogram::FactoryGet(
+ name, 1, 100000, 50, base::HistogramBase::kUmaTargetedHistogramFlag);
+ histogram_pointer->Add(1);
+}
+
+void IncrementHistogramEnum(const std::string& name,
+ uint32 sample,
+ uint32 boundary_value) {
+ // The default value of min, max, bucket_count are copied from histogram.h.
+ base::HistogramBase* histogram_pointer = base::LinearHistogram::FactoryGet(
+ name,
+ 1,
+ boundary_value,
+ boundary_value + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ histogram_pointer->Add(sample);
+}
+
+void HistogramCountBlockedResponse(
+ const std::string& bucket_prefix,
+ const SiteIsolationPolicy::ResponseMetaData& resp_data,
+ bool nosniff_block) {
+ std::string block_label(nosniff_block ? ".NoSniffBlocked" : ".Blocked");
+ IncrementHistogramCount(bucket_prefix + block_label);
+
+ // The content is blocked if it is sniffed as HTML/JSON/XML. When
+ // the blocked response is with an error status code, it is not
+ // disruptive for the following reasons : 1) the blocked content is
+ // not a binary object (such as an image) since it is sniffed as
+ // text; 2) then, this blocking only breaks the renderer behavior
+ // only if it is either JavaScript or CSS. However, the renderer
+ // doesn't use the contents of JS/CSS with unaffected status code
+ // (e.g, 404). 3) the renderer is expected not to use the cross-site
+ // document content for purposes other than JS/CSS (e.g, XHR).
+ bool renderable_status_code =
+ IsRenderableStatusCode(resp_data.http_status_code);
+
+ if (renderable_status_code) {
+ IncrementHistogramEnum(
+ bucket_prefix + block_label + ".RenderableStatusCode",
+ resp_data.resource_type,
+ ResourceType::LAST_TYPE);
+ } else {
+ IncrementHistogramCount(bucket_prefix + block_label +
+ ".NonRenderableStatusCode");
+ }
+}
+
+void HistogramCountNotBlockedResponse(const std::string& bucket_prefix,
+ bool sniffed_as_js) {
+ IncrementHistogramCount(bucket_prefix + ".NotBlocked");
+ if (sniffed_as_js)
+ IncrementHistogramCount(bucket_prefix + ".NotBlocked.MaybeJS");
+}
+
+} // namespace
+
+SiteIsolationPolicy::ResponseMetaData::ResponseMetaData() {}
void SiteIsolationPolicy::SetPolicyEnabled(bool enabled) {
g_policy_enabled = enabled;
@@ -57,8 +168,8 @@ void SiteIsolationPolicy::SetPolicyEnabled(bool enabled) {
void SiteIsolationPolicy::OnReceivedResponse(
int request_id,
- GURL& frame_origin,
- GURL& response_url,
+ const GURL& frame_origin,
+ const GURL& response_url,
ResourceType::Type resource_type,
int origin_pid,
const webkit_glue::ResourceResponseInfo& info) {
@@ -116,76 +227,24 @@ void SiteIsolationPolicy::OnReceivedResponse(
resp_data.http_status_code = info.headers->response_code();
resp_data.no_sniff = LowerCaseEqualsASCII(no_sniff, "nosniff");
- RequestIdToMetaDataMap* metadata_map = GetRequestIdToMetaDataMap();
- (*metadata_map)[request_id] = resp_data;
+ (g_metadata_map.Get())[request_id] = resp_data;
}
-// These macros are defined here so that we prevent code size bloat-up due to
-// the UMA_HISTOGRAM_* macros. Similar logic is used for recording UMA stats for
-// different MIME types, but we cannot create a helper function for this since
-// UMA_HISTOGRAM_* macros do not accept variables as their bucket names. As a
-// solution, macros are used instead to capture the repeated pattern for
-// recording UMA stats. TODO(dsjang): this is only needed for collecting UMA
-// stat. Will be deleted when this class is used for actual blocking.
-
-#define SITE_ISOLATION_POLICY_COUNT_BLOCK(BUCKET_PREFIX) \
- UMA_HISTOGRAM_COUNTS( BUCKET_PREFIX ".Blocked", 1); \
- result = true; \
- if (renderable_status_code) { \
- UMA_HISTOGRAM_ENUMERATION( \
- BUCKET_PREFIX ".Blocked.RenderableStatusCode", \
- resp_data.resource_type, \
- WebURLRequest::TargetIsUnspecified + 1); \
- } else { \
- UMA_HISTOGRAM_COUNTS(BUCKET_PREFIX ".Blocked.NonRenderableStatusCode",1);\
- }
-
-#define SITE_ISOLATION_POLICY_COUNT_NO_SNIFF_BLOCK(BUCKET_PREFIX) \
- UMA_HISTOGRAM_COUNTS( BUCKET_PREFIX ".NoSniffBlocked", 1); \
- result = true; \
- if (renderable_status_code) { \
- UMA_HISTOGRAM_ENUMERATION( \
- BUCKET_PREFIX ".NoSniffBlocked.RenderableStatusCode", \
- resp_data.resource_type, \
- WebURLRequest::TargetIsUnspecified + 1); \
- } else { \
- UMA_HISTOGRAM_ENUMERATION( \
- BUCKET_PREFIX ".NoSniffBlocked.NonRenderableStatusCode", \
- resp_data.resource_type, \
- WebURLRequest::TargetIsUnspecified + 1); \
- }
-
-#define SITE_ISOLATION_POLICY_COUNT_NOTBLOCK(BUCKET_PREFIX) \
- UMA_HISTOGRAM_COUNTS(BUCKET_PREFIX ".NotBlocked", 1); \
- if (is_sniffed_for_js) \
- UMA_HISTOGRAM_COUNTS(BUCKET_PREFIX ".NotBlocked.MaybeJS", 1); \
-
-#define SITE_ISOLATION_POLICY_SNIFF_AND_COUNT(SNIFF_EXPR,BUCKET_PREFIX) \
- if (SNIFF_EXPR) { \
- SITE_ISOLATION_POLICY_COUNT_BLOCK(BUCKET_PREFIX) \
- } else { \
- if (resp_data.no_sniff) { \
- SITE_ISOLATION_POLICY_COUNT_NO_SNIFF_BLOCK(BUCKET_PREFIX) \
- } else { \
- SITE_ISOLATION_POLICY_COUNT_NOTBLOCK(BUCKET_PREFIX) \
- } \
- }
-
bool SiteIsolationPolicy::ShouldBlockResponse(
int request_id,
- const char* data,
- int length,
+ const char* raw_data,
+ int raw_length,
std::string* alternative_data) {
if (!g_policy_enabled)
return false;
- RequestIdToMetaDataMap* metadata_map = GetRequestIdToMetaDataMap();
- RequestIdToResultMap* result_map = GetRequestIdToResultMap();
+ RequestIdToMetaDataMap& metadata_map = g_metadata_map.Get();
+ RequestIdToResultMap& result_map = g_result_map.Get();
// If there's an entry for |request_id| in blocked_map, this request's first
// data packet has already been examined. We can return the result here.
- if (result_map->count(request_id) != 0) {
- if ((*result_map)[request_id]) {
+ if (result_map.count(request_id) != 0) {
+ if (result_map[request_id]) {
// Here, the blocking result has been set for the previous run of
// ShouldBlockResponse(), so we set alternative data to an empty string so
// that ResourceDispatcher doesn't call its peer's onReceivedData() with
@@ -199,19 +258,21 @@ bool SiteIsolationPolicy::ShouldBlockResponse(
// If result_map doesn't have an entry for |request_id|, we're receiving the
// first data packet for request_id. If request_id is not registered, this
// request is identified as a non-target of our policy. So we return true.
- if (metadata_map->count(request_id) == 0) {
+ if (metadata_map.count(request_id) == 0) {
// We set request_id to true so that we always return true for this request.
- (*result_map)[request_id] = false;
+ result_map[request_id] = false;
return false;
}
+ StringPiece data(raw_data, raw_length);
+
// We now look at the first data packet received for request_id.
- ResponseMetaData resp_data = (*metadata_map)[request_id];
- metadata_map->erase(request_id);
+ ResponseMetaData resp_data = metadata_map[request_id];
+ metadata_map.erase(request_id);
// Record the length of the first received network packet to see if it's
// enough for sniffing.
- UMA_HISTOGRAM_COUNTS("SiteIsolation.XSD.DataLength", length);
+ UMA_HISTOGRAM_COUNTS("SiteIsolation.XSD.DataLength", raw_length);
// Record the number of cross-site document responses with a specific mime
// type (text/html, text/xml, etc).
@@ -220,94 +281,90 @@ bool SiteIsolationPolicy::ShouldBlockResponse(
resp_data.canonical_mime_type,
SiteIsolationPolicy::ResponseMetaData::MaxCanonicalMimeType);
- // Store the result of cross-site document blocking analysis. True means we
- // can return this document to the renderer, false means that we have to block
- // the response data.
- bool result = false;
-
- // The content is blocked if it is sniffed for HTML/JSON/XML. When the blocked
- // response is with an error status code, it is not disruptive by the
- // following reasons : 1) the blocked content is not a binary object (such as
- // an image) since it is sniffed for text; 2) then, this blocking only breaks
- // the renderer behavior only if it is either JavaScript or CSS. However, the
- // renderer doesn't use the contents of JS/CSS with unaffected status code
- // (e.g, 404). 3) the renderer is expected not to use the cross-site document
- // content for purposes other than JS/CSS (e.g, XHR).
- bool renderable_status_code = IsRenderableStatusCodeForDocument(
- resp_data.http_status_code);
-
- // This is only used for false-negative analysis for non-blocked resources.
- bool is_sniffed_for_js = SniffForJS(data, length);
+ // Store the result of cross-site document blocking analysis.
+ bool is_blocked = false;
+ bool sniffed_as_js = SniffForJS(data);
// Record the number of responses whose content is sniffed for what its mime
// type claims it to be. For example, we apply a HTML sniffer for a document
// tagged with text/html here. Whenever this check becomes true, we'll block
// the response.
- switch (resp_data.canonical_mime_type) {
- case SiteIsolationPolicy::ResponseMetaData::HTML:
- SITE_ISOLATION_POLICY_SNIFF_AND_COUNT(SniffForHTML(data, length),
- "SiteIsolation.XSD.HTML");
- break;
- case SiteIsolationPolicy::ResponseMetaData::XML:
- SITE_ISOLATION_POLICY_SNIFF_AND_COUNT(SniffForXML(data, length),
- "SiteIsolation.XSD.XML");
- break;
- case SiteIsolationPolicy::ResponseMetaData::JSON:
- SITE_ISOLATION_POLICY_SNIFF_AND_COUNT(SniffForJSON(data, length),
- "SiteIsolation.XSD.JSON");
- break;
- case SiteIsolationPolicy::ResponseMetaData::Plain:
- if (SniffForHTML(data, length)) {
- SITE_ISOLATION_POLICY_COUNT_BLOCK(
- "SiteIsolation.XSD.Plain.HTML");
- } else if (SniffForXML(data, length)) {
- SITE_ISOLATION_POLICY_COUNT_BLOCK(
- "SiteIsolation.XSD.Plain.XML");
- } else if (SniffForJSON(data, length)) {
- SITE_ISOLATION_POLICY_COUNT_BLOCK(
- "SiteIsolation.XSD.Plain.JSON");
- } else if (is_sniffed_for_js) {
- if (resp_data.no_sniff) {
- SITE_ISOLATION_POLICY_COUNT_NO_SNIFF_BLOCK(
- "SiteIsolation.XSD.Plain");
- } else {
- SITE_ISOLATION_POLICY_COUNT_NOTBLOCK(
- "SiteIsolation.XSD.Plain");
- }
+ if (resp_data.canonical_mime_type !=
+ SiteIsolationPolicy::ResponseMetaData::Plain) {
+ std::string bucket_prefix;
+ bool sniffed_as_target_document = false;
+ if (resp_data.canonical_mime_type ==
+ SiteIsolationPolicy::ResponseMetaData::HTML) {
+ bucket_prefix = "SiteIsolation.XSD.HTML";
+ sniffed_as_target_document = SniffForHTML(data);
+ } else if (resp_data.canonical_mime_type ==
+ SiteIsolationPolicy::ResponseMetaData::XML) {
+ bucket_prefix = "SiteIsolation.XSD.XML";
+ sniffed_as_target_document = SniffForXML(data);
+ } else if (resp_data.canonical_mime_type ==
+ SiteIsolationPolicy::ResponseMetaData::JSON) {
+ bucket_prefix = "SiteIsolation.XSD.JSON";
+ sniffed_as_target_document = SniffForJSON(data);
+ } else {
+ NOTREACHED() << "Not a blockable mime type: "
+ << resp_data.canonical_mime_type;
+ }
+
+ if (sniffed_as_target_document) {
+ is_blocked = true;
+ HistogramCountBlockedResponse(bucket_prefix, resp_data, false);
+ } else {
+ if (resp_data.no_sniff) {
+ is_blocked = true;
+ HistogramCountBlockedResponse(bucket_prefix, resp_data, true);
+ } else {
+ HistogramCountNotBlockedResponse(bucket_prefix, sniffed_as_js);
}
- break;
- default :
- NOTREACHED() <<
- "Not a blockable mime type. This mime type shouldn't reach here.";
- break;
+ }
+ } else {
+ // This block is for plain text documents. We apply our HTML, XML,
+ // and JSON sniffer to a text document in the order, and block it
+ // if any of them succeeds in sniffing.
+ std::string bucket_prefix;
+ if (SniffForHTML(data))
+ bucket_prefix = "SiteIsolation.XSD.Plain.HTML";
+ else if (SniffForXML(data))
+ bucket_prefix = "SiteIsolation.XSD.Plain.XML";
+ else if (SniffForJSON(data))
+ bucket_prefix = "SiteIsolation.XSD.Plain.JSON";
+
+ if (bucket_prefix.size() > 0) {
+ is_blocked = true;
+ HistogramCountBlockedResponse(bucket_prefix, resp_data, false);
+ } else if (resp_data.no_sniff) {
+ is_blocked = true;
+ HistogramCountBlockedResponse("SiteIsolation.XSD.Plain", resp_data, true);
+ } else {
+ HistogramCountNotBlockedResponse("SiteIsolation.XSD.Plain",
+ sniffed_as_js);
+ }
}
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (!command_line.HasSwitch(switches::kBlockCrossSiteDocuments))
- result = false;
- (*result_map)[request_id] = result;
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kBlockCrossSiteDocuments))
+ is_blocked = false;
+ result_map[request_id] = is_blocked;
- if (result) {
+ if (is_blocked) {
alternative_data->erase();
alternative_data->insert(0, " ");
LOG(ERROR) << resp_data.response_url
<< " is blocked as an illegal cross-site document from "
<< resp_data.frame_origin;
}
- return result;
+ return is_blocked;
}
-#undef SITE_ISOLATION_POLICY_COUNT_NOTBLOCK
-#undef SITE_ISOLATION_POLICY_SNIFF_AND_COUNT
-#undef SITE_ISOLATION_POLICY_COUNT_BLOCK
-
void SiteIsolationPolicy::OnRequestComplete(int request_id) {
if (!g_policy_enabled)
return;
- RequestIdToMetaDataMap* metadata_map = GetRequestIdToMetaDataMap();
- RequestIdToResultMap* result_map = GetRequestIdToResultMap();
- metadata_map->erase(request_id);
- result_map->erase(request_id);
+ g_metadata_map.Get().erase(request_id);
+ g_result_map.Get().erase(request_id);
}
SiteIsolationPolicy::ResponseMetaData::CanonicalMimeType
@@ -333,7 +390,6 @@ SiteIsolationPolicy::GetCanonicalMimeType(const std::string& mime_type) {
}
return SiteIsolationPolicy::ResponseMetaData::Others;
-
}
bool SiteIsolationPolicy::IsBlockableScheme(const GURL& url) {
@@ -362,25 +418,14 @@ bool SiteIsolationPolicy::IsSameSite(const GURL& frame_origin,
net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
}
-bool SiteIsolationPolicy::IsFrameNavigating(WebKit::WebFrame* frame) {
- // When a navigation starts, frame->provisionalDataSource() is set
- // to a not-null value which stands for the request made for the
- // navigation. As soon as the network request is committed to the
- // frame, frame->provisionalDataSource() is converted to null, and
- // the committed data source is moved to frame->dataSource(). This
- // is the most reliable way to detect whether the frame is in
- // navigation or not.
- return frame->provisionalDataSource() != NULL;
-}
-
// We don't use Webkit's existing CORS policy implementation since
// their policy works in terms of origins, not sites. For example,
// when frame is sub.a.com and it is not allowed to access a document
// with sub1.a.com. But under Site Isolation, it's allowed.
bool SiteIsolationPolicy::IsValidCorsHeaderSet(
- GURL& frame_origin,
- GURL& website_origin,
- std::string access_control_origin) {
+ const GURL& frame_origin,
+ const GURL& website_origin,
+ const std::string& access_control_origin) {
// Many websites are sending back "\"*\"" instead of "*". This is
// non-standard practice, and not supported by Chrome. Refer to
// CrossOriginAccessControl::passesAccessControlCheck().
@@ -405,7 +450,7 @@ bool SiteIsolationPolicy::IsValidCorsHeaderSet(
}
// This function is a slight modification of |net::SniffForHTML|.
-bool SiteIsolationPolicy::SniffForHTML(const char* data, size_t length) {
+bool SiteIsolationPolicy::SniffForHTML(StringPiece data) {
// The content sniffer used by Chrome and Firefox are using "<!--"
// as one of the HTML signatures, but it also appears in valid
// JavaScript, considered as well-formed JS by the browser. Since
@@ -415,99 +460,104 @@ bool SiteIsolationPolicy::SniffForHTML(const char* data, size_t length) {
// TODO(dsjang): parameterize |net::SniffForHTML| with an option
// that decides whether to include <!-- or not, so that we can
// remove this function.
- const char* html_signatures[] = {"<!DOCTYPE html", // HTML5 spec
- "<script", // HTML5 spec, Mozilla
- "<html", // HTML5 spec, Mozilla
- "<head", // HTML5 spec, Mozilla
- "<iframe", // Mozilla
- "<h1", // Mozilla
- "<div", // Mozilla
- "<font", // Mozilla
- "<table", // Mozilla
- "<a", // Mozilla
- "<style", // Mozilla
- "<title", // Mozilla
- "<b", // Mozilla
- "<body", // Mozilla
- "<br", "<p", // Mozilla
- "<?xml" // Mozilla
+ // TODO(dsjang): Once SiteIsolationPolicy is moved into the browser
+ // process, we should do single-thread checking here for the static
+ // initializer.
+ static const StringPiece kHtmlSignatures[] = {
+ StringPiece("<!DOCTYPE html"), // HTML5 spec
+ StringPiece("<script"), // HTML5 spec, Mozilla
+ StringPiece("<html"), // HTML5 spec, Mozilla
+ StringPiece("<head"), // HTML5 spec, Mozilla
+ StringPiece("<iframe"), // Mozilla
+ StringPiece("<h1"), // Mozilla
+ StringPiece("<div"), // Mozilla
+ StringPiece("<font"), // Mozilla
+ StringPiece("<table"), // Mozilla
+ StringPiece("<a"), // Mozilla
+ StringPiece("<style"), // Mozilla
+ StringPiece("<title"), // Mozilla
+ StringPiece("<b"), // Mozilla
+ StringPiece("<body"), // Mozilla
+ StringPiece("<br"), // Mozilla
+ StringPiece("<p"), // Mozilla
+ StringPiece("<?xml") // Mozilla
};
- if (MatchesSignature(
- data, length, html_signatures, arraysize(html_signatures)))
- return true;
+ while (data.length() > 0) {
+ if (MatchesSignature(
+ data, kHtmlSignatures, arraysize(kHtmlSignatures)))
+ return true;
- // "<!--" is specially treated since web JS can use "<!--" "-->" pair for
- // comments.
- static const char* comment_begins[] = {"<!--"};
+ // If we cannot find "<!--", we fail sniffing this as HTML.
+ static const StringPiece kCommentBegins[] = { StringPiece("<!--") };
+ if (!MatchesSignature(data, kCommentBegins, arraysize(kCommentBegins)))
+ break;
- if (MatchesSignature(
- data, length, comment_begins, arraysize(comment_begins))) {
// Search for --> and do SniffForHTML after that. If we can find the
// comment's end, we start HTML sniffing from there again.
- static const char end_comment[] = "-->";
- base::StringPiece data_as_stringpiece(data, length);
-
- size_t offset = data_as_stringpiece.find(end_comment);
- if (offset != base::StringPiece::npos) {
- size_t new_start_offset = offset + strlen(end_comment);
- if (new_start_offset < length) {
- return SniffForHTML(data + new_start_offset,
- length - new_start_offset);
- }
- }
+ static const char kEndComment[] = "-->";
+ size_t offset = data.find(kEndComment);
+ if (offset == base::StringPiece::npos)
+ break;
+
+ // Proceed to the index next to the ending comment (-->).
+ data.remove_prefix(offset + strlen(kEndComment));
}
return false;
}
-bool SiteIsolationPolicy::SniffForXML(const char* data, size_t length) {
+bool SiteIsolationPolicy::SniffForXML(base::StringPiece data) {
// TODO(dsjang): Chrome's mime_sniffer is using strncasecmp() for
// this signature. However, XML is case-sensitive. Don't we have to
// be more lenient only to block documents starting with the exact
// string <?xml rather than <?XML ?
- const char* xml_signatures[] = {"<?xml" // Mozilla
- };
- return MatchesSignature(
- data, length, xml_signatures, arraysize(xml_signatures));
+ // TODO(dsjang): Once SiteIsolationPolicy is moved into the browser
+ // process, we should do single-thread checking here for the static
+ // initializer.
+ static const StringPiece kXmlSignatures[] = { StringPiece("<?xml") };
+ return MatchesSignature(data, kXmlSignatures, arraysize(kXmlSignatures));
}
-bool SiteIsolationPolicy::SniffForJSON(const char* data, size_t length) {
+bool SiteIsolationPolicy::SniffForJSON(base::StringPiece data) {
// TODO(dsjang): We have to come up with a better way to sniff
// JSON. However, even RE cannot help us that much due to the fact
// that we don't do full parsing. This DFA starts with state 0, and
// finds {, "/' and : in that order. We're avoiding adding a
// dependency on a regular expression library.
- const int kInitState = 0;
- const int kLeftBraceState = 1;
- const int kLeftQuoteState = 2;
- const int kColonState = 3;
- const int kDeadState = 4;
-
- int state = kInitState;
+ enum {
+ kStartState,
+ kLeftBraceState,
+ kLeftQuoteState,
+ kColonState,
+ kTerminalState,
+ } state = kStartState;
+
+ size_t length = data.length();
for (size_t i = 0; i < length && state < kColonState; ++i) {
const char c = data[i];
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
continue;
switch (state) {
- case kInitState:
+ case kStartState:
if (c == '{')
state = kLeftBraceState;
else
- state = kDeadState;
+ state = kTerminalState;
break;
case kLeftBraceState:
if (c == '\"' || c == '\'')
state = kLeftQuoteState;
else
- state = kDeadState;
+ state = kTerminalState;
break;
case kLeftQuoteState:
if (c == ':')
state = kColonState;
break;
- default:
+ case kColonState:
+ case kTerminalState:
NOTREACHED();
break;
}
@@ -515,71 +565,14 @@ bool SiteIsolationPolicy::SniffForJSON(const char* data, size_t length) {
return state == kColonState;
}
-bool SiteIsolationPolicy::MatchesSignature(const char* raw_data,
- size_t raw_length,
- const char* signatures[],
- size_t arr_size) {
- size_t start = 0;
- // Skip white characters at the beginning of the document.
- for (start = 0; start < raw_length; ++start) {
- char c = raw_data[start];
- if (!(c == ' ' || c == '\t' || c == '\r' || c == '\n'))
- break;
- }
-
- // There is no not-whitespace character in this document.
- if (!(start < raw_length))
- return false;
-
- const char* data = raw_data + start;
- size_t length = raw_length - start;
-
- for (size_t sig_index = 0; sig_index < arr_size; ++sig_index) {
- const char* signature = signatures[sig_index];
- size_t signature_length = strlen(signature);
-
- if (length < signature_length)
- continue;
-
- if (!base::strncasecmp(signature, data, signature_length))
- return true;
- }
- return false;
-}
-
-bool SiteIsolationPolicy::IsRenderableStatusCodeForDocument(int status_code) {
- // Chrome only uses the content of a response with one of these status codes
- // for CSS/JavaScript. For images, Chrome just ignores status code.
- const int renderable_status_code[] = {200, 201, 202, 203, 206, 300, 301, 302,
- 303, 305, 306, 307};
- for (size_t i = 0; i < arraysize(renderable_status_code); ++i) {
- if (renderable_status_code[i] == status_code)
- return true;
- }
- return false;
-}
-
-bool SiteIsolationPolicy::SniffForJS(const char* data, size_t length) {
+bool SiteIsolationPolicy::SniffForJS(StringPiece data) {
// TODO(dsjang): This is a real hack. The only purpose of this function is to
// try to see if there's any possibility that this data can be JavaScript
// (superset of JS). This function will be removed once UMA stats are
// gathered.
// Search for "var " for JS detection.
- return base::StringPiece(data, length).find("var ") !=
- base::StringPiece::npos;
-}
-
-SiteIsolationPolicy::RequestIdToMetaDataMap*
-SiteIsolationPolicy::GetRequestIdToMetaDataMap() {
- CR_DEFINE_STATIC_LOCAL(RequestIdToMetaDataMap, metadata_map_, ());
- return &metadata_map_;
-}
-
-SiteIsolationPolicy::RequestIdToResultMap*
-SiteIsolationPolicy::GetRequestIdToResultMap() {
- CR_DEFINE_STATIC_LOCAL(RequestIdToResultMap, result_map_, ());
- return &result_map_;
+ return data.find("var ") != base::StringPiece::npos;
}
} // namespace content
diff --git a/chromium/content/child/site_isolation_policy.h b/chromium/content/child/site_isolation_policy.h
index ec5d889409d..28cabed6062 100644
--- a/chromium/content/child/site_isolation_policy.h
+++ b/chromium/content/child/site_isolation_policy.h
@@ -62,8 +62,8 @@ class CONTENT_EXPORT SiteIsolationPolicy {
// ShouldBlockResponse. We have to make sure to call OnRequestComplete to free
// the bookkeeping data.
static void OnReceivedResponse(int request_id,
- GURL& frame_origin,
- GURL& response_url,
+ const GURL& frame_origin,
+ const GURL& response_url,
ResourceType::Type resource_type,
int origin_pid,
const webkit_glue::ResourceResponseInfo& info);
@@ -135,44 +135,17 @@ private:
// not allowed by actual CORS rules by ignoring 1) credentials and 2)
// methods. Preflight requests don't matter here since they are not used to
// decide whether to block a document or not on the client side.
- static bool IsValidCorsHeaderSet(GURL& frame_origin,
- GURL& website_origin,
- std::string access_control_origin);
+ static bool IsValidCorsHeaderSet(const GURL& frame_origin,
+ const GURL& website_origin,
+ const std::string& access_control_origin);
- // Returns whether the given frame is navigating. When this is true, the frame
- // is requesting is a web page to be loaded.
- static bool IsFrameNavigating(WebKit::WebFrame* frame);
-
- static bool SniffForHTML(const char* data, size_t length);
- static bool SniffForXML(const char* data, size_t length);
- static bool SniffForJSON(const char* data, size_t length);
-
- static bool MatchesSignature(const char* data,
- size_t length,
- const char* signatures[],
- size_t arr_size);
-
- // TODO(dsjang): this is only needed for collecting UMA stat. Will be deleted
- // when this class is used for actual blocking.
- static bool SniffForJS(const char* data, size_t length);
+ static bool SniffForHTML(base::StringPiece data);
+ static bool SniffForXML(base::StringPiece data);
+ static bool SniffForJSON(base::StringPiece data);
// TODO(dsjang): this is only needed for collecting UMA stat. Will be deleted
// when this class is used for actual blocking.
- static bool IsRenderableStatusCodeForDocument(int status_code);
-
- // Maintain the bookkeeping data between OnReceivedResponse and
- // OnReceivedData. The key is a request id maintained by ResourceDispatcher.
- static RequestIdToMetaDataMap* GetRequestIdToMetaDataMap();
-
- // Maintain the bookkeeping data for OnReceivedData. Blocking decision is made
- // when OnReceivedData is called for the first time for a request, and the
- // decision will remain the same for following data. This map maintains the
- // decision. The key is a request id maintained by ResourceDispatcher.
- static RequestIdToResultMap* GetRequestIdToResultMap();
-
- // This is false by default, but enables UMA logging and cross-site document
- // blocking.
- static bool g_policy_enabled;
+ static bool SniffForJS(base::StringPiece data);
// Never needs to be constructed/destructed.
SiteIsolationPolicy() {}
diff --git a/chromium/content/child/site_isolation_policy_unittest.cc b/chromium/content/child/site_isolation_policy_unittest.cc
index 856a5f2bb7e..041b7c624b7 100644
--- a/chromium/content/child/site_isolation_policy_unittest.cc
+++ b/chromium/content/child/site_isolation_policy_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 "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "content/child/site_isolation_policy.h"
#include "content/public/common/context_menu_params.h"
@@ -9,6 +10,8 @@
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "ui/gfx/range/range.h"
+using base::StringPiece;
+
namespace content {
TEST(SiteIsolationPolicyTest, IsBlockableScheme) {
@@ -67,71 +70,65 @@ TEST(SiteIsolationPolicyTest, IsValidCorsHeaderSet) {
}
TEST(SiteIsolationPolicyTest, SniffForHTML) {
- const char html_data[] = " \t\r\n <HtMladfokadfkado";
- const char comment_html_data[] = " <!-- this is comment --> <html><body>";
- const char two_comments_html_data[] =
- "<!-- this is comment -->\n<!-- this is comment --><html><body>";
- const char mixed_comments_html_data[] =
- "<!-- this is comment <!-- --> <script></script>";
- const char non_html_data[] = " var name=window.location;\nadfadf";
- const char comment_js_data[] = " <!-- this is comment -> document.write(1); ";
-
- EXPECT_TRUE(
- SiteIsolationPolicy::SniffForHTML(html_data, arraysize(html_data)));
- EXPECT_TRUE(SiteIsolationPolicy::SniffForHTML(comment_html_data,
- arraysize(comment_html_data)));
- EXPECT_TRUE(SiteIsolationPolicy::SniffForHTML(
- two_comments_html_data, arraysize(two_comments_html_data)));
- EXPECT_TRUE(SiteIsolationPolicy::SniffForHTML(
- mixed_comments_html_data, arraysize(mixed_comments_html_data)));
- EXPECT_FALSE(SiteIsolationPolicy::SniffForHTML(non_html_data,
- arraysize(non_html_data)));
- EXPECT_FALSE(SiteIsolationPolicy::SniffForHTML(comment_js_data,
- arraysize(comment_js_data)));
+ StringPiece html_data(" \t\r\n <HtMladfokadfkado");
+ StringPiece comment_html_data(" <!-- this is comment --> <html><body>");
+ StringPiece two_comments_html_data(
+ "<!-- this is comment -->\n<!-- this is comment --><html><body>");
+ StringPiece mixed_comments_html_data(
+ "<!-- this is comment <!-- --> <script></script>");
+ StringPiece non_html_data(" var name=window.location;\nadfadf");
+ StringPiece comment_js_data(" <!-- this is comment -> document.write(1); ");
+ StringPiece empty_data("");
+
+ EXPECT_TRUE(SiteIsolationPolicy::SniffForHTML(html_data));
+ EXPECT_TRUE(SiteIsolationPolicy::SniffForHTML(comment_html_data));
+ EXPECT_TRUE(SiteIsolationPolicy::SniffForHTML(two_comments_html_data));
+ EXPECT_TRUE(SiteIsolationPolicy::SniffForHTML(mixed_comments_html_data));
+ EXPECT_FALSE(SiteIsolationPolicy::SniffForHTML(non_html_data));
+ EXPECT_FALSE(SiteIsolationPolicy::SniffForHTML(comment_js_data));
// Basic bounds check.
- EXPECT_FALSE(SiteIsolationPolicy::SniffForHTML(html_data, 0));
+ EXPECT_FALSE(SiteIsolationPolicy::SniffForHTML(empty_data));
}
TEST(SiteIsolationPolicyTest, SniffForXML) {
- const char xml_data[] = " \t \r \n <?xml version=\"1.0\"?>\n <catalog";
- const char non_xml_data[] = " var name=window.location;\nadfadf";
+ StringPiece xml_data(" \t \r \n <?xml version=\"1.0\"?>\n <catalog");
+ StringPiece non_xml_data(" var name=window.location;\nadfadf");
+ StringPiece empty_data("");
- EXPECT_TRUE(SiteIsolationPolicy::SniffForXML(xml_data, arraysize(xml_data)));
- EXPECT_FALSE(
- SiteIsolationPolicy::SniffForXML(non_xml_data, arraysize(non_xml_data)));
+ EXPECT_TRUE(SiteIsolationPolicy::SniffForXML(xml_data));
+ EXPECT_FALSE(SiteIsolationPolicy::SniffForXML(non_xml_data));
// Basic bounds check.
- EXPECT_FALSE(SiteIsolationPolicy::SniffForXML(xml_data, 0));
+ EXPECT_FALSE(SiteIsolationPolicy::SniffForXML(empty_data));
}
TEST(SiteIsolationPolicyTest, SniffForJSON) {
- const char json_data[] = "\t\t\r\n { \"name\" : \"chrome\", ";
- const char non_json_data0[] = "\t\t\r\n { name : \"chrome\", ";
- const char non_json_data1[] = "\t\t\r\n foo({ \"name\" : \"chrome\", ";
+ StringPiece json_data("\t\t\r\n { \"name\" : \"chrome\", ");
+ StringPiece non_json_data0("\t\t\r\n { name : \"chrome\", ");
+ StringPiece non_json_data1("\t\t\r\n foo({ \"name\" : \"chrome\", ");
+ StringPiece empty_data("");
EXPECT_TRUE(
- SiteIsolationPolicy::SniffForJSON(json_data, arraysize(json_data)));
- EXPECT_FALSE(SiteIsolationPolicy::SniffForJSON(non_json_data0,
- arraysize(non_json_data0)));
- EXPECT_FALSE(SiteIsolationPolicy::SniffForJSON(non_json_data1,
- arraysize(non_json_data1)));
+ SiteIsolationPolicy::SniffForJSON(json_data));
+ EXPECT_FALSE(SiteIsolationPolicy::SniffForJSON(non_json_data0));
+ EXPECT_FALSE(SiteIsolationPolicy::SniffForJSON(non_json_data1));
// Basic bounds check.
- EXPECT_FALSE(SiteIsolationPolicy::SniffForJSON(json_data, 0));
+ EXPECT_FALSE(SiteIsolationPolicy::SniffForJSON(empty_data));
}
TEST(SiteIsolationPolicyTest, SniffForJS) {
- const char basic_js_data[] = "var a = 4";
- const char js_data[] = "\t\t\r\n var a = 4";
- const char json_data[] = "\t\t\r\n { \"name\" : \"chrome\", ";
+ StringPiece basic_js_data("var a = 4");
+ StringPiece js_data("\t\t\r\n var a = 4");
+ StringPiece json_data("\t\t\r\n { \"name\" : \"chrome\", ");
+ StringPiece empty_data("");
- EXPECT_TRUE(SiteIsolationPolicy::SniffForJS(js_data, arraysize(js_data)));
- EXPECT_FALSE(
- SiteIsolationPolicy::SniffForJS(json_data, arraysize(json_data)));
+ EXPECT_TRUE(SiteIsolationPolicy::SniffForJS(js_data));
+ EXPECT_FALSE(SiteIsolationPolicy::SniffForJS(json_data));
// Basic bounds check.
- EXPECT_FALSE(SiteIsolationPolicy::SniffForJS(basic_js_data, 0));
+ EXPECT_FALSE(SiteIsolationPolicy::SniffForJS(empty_data));
}
} // namespace content
diff --git a/chromium/content/child/socket_stream_dispatcher.cc b/chromium/content/child/socket_stream_dispatcher.cc
index 87f299f0bf3..9370f087cc5 100644
--- a/chromium/content/child/socket_stream_dispatcher.cc
+++ b/chromium/content/child/socket_stream_dispatcher.cc
@@ -30,7 +30,7 @@ class IPCWebSocketStreamHandleBridge
: public webkit_glue::WebSocketStreamHandleBridge {
public:
IPCWebSocketStreamHandleBridge(
- WebKit::WebSocketStreamHandle* handle,
+ blink::WebSocketStreamHandle* handle,
webkit_glue::WebSocketStreamHandleDelegate* delegate)
: socket_id_(kNoSocketId),
handle_(handle),
@@ -58,7 +58,7 @@ class IPCWebSocketStreamHandleBridge
// browser process.
int socket_id_;
- WebKit::WebSocketStreamHandle* handle_;
+ blink::WebSocketStreamHandle* handle_;
webkit_glue::WebSocketStreamHandleDelegate* delegate_;
// Map from ID to bridge instance.
@@ -177,7 +177,7 @@ SocketStreamDispatcher::SocketStreamDispatcher() {
/* static */
webkit_glue::WebSocketStreamHandleBridge*
SocketStreamDispatcher::CreateBridge(
- WebKit::WebSocketStreamHandle* handle,
+ blink::WebSocketStreamHandle* handle,
webkit_glue::WebSocketStreamHandleDelegate* delegate) {
return new IPCWebSocketStreamHandleBridge(handle, delegate);
}
diff --git a/chromium/content/child/socket_stream_dispatcher.h b/chromium/content/child/socket_stream_dispatcher.h
index ba23c8005ec..a52907afe2d 100644
--- a/chromium/content/child/socket_stream_dispatcher.h
+++ b/chromium/content/child/socket_stream_dispatcher.h
@@ -11,7 +11,7 @@
#include "base/compiler_specific.h"
#include "ipc/ipc_listener.h"
-namespace WebKit {
+namespace blink {
class WebSocketStreamHandle;
}
@@ -32,7 +32,7 @@ class SocketStreamDispatcher : public IPC::Listener {
virtual ~SocketStreamDispatcher() {}
static webkit_glue::WebSocketStreamHandleBridge* CreateBridge(
- WebKit::WebSocketStreamHandle* handle,
+ blink::WebSocketStreamHandle* handle,
webkit_glue::WebSocketStreamHandleDelegate* delegate);
// IPC::Listener implementation.
diff --git a/chromium/content/child/thread_safe_sender.h b/chromium/content/child/thread_safe_sender.h
index c300d9d124c..c399915ad96 100644
--- a/chromium/content/child/thread_safe_sender.h
+++ b/chromium/content/child/thread_safe_sender.h
@@ -32,7 +32,7 @@ class CONTENT_EXPORT ThreadSafeSender
friend class ChildThread; // for construction
friend class base::RefCountedThreadSafe<ThreadSafeSender>;
FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, ValueSizeTest);
- FRIEND_TEST_ALL_PREFIXES(RendererWebIDBCursorImplTest, PrefetchTest);
+ FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchTest);
ThreadSafeSender(base::MessageLoopProxy* main_loop,
IPC::SyncMessageFilter* sync_filter);
diff --git a/chromium/content/child/web_database_observer_impl.cc b/chromium/content/child/web_database_observer_impl.cc
index 8b6d157acce..f06823eee6c 100644
--- a/chromium/content/child/web_database_observer_impl.cc
+++ b/chromium/content/child/web_database_observer_impl.cc
@@ -9,12 +9,12 @@
#include "content/common/database_messages.h"
#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/web/WebDatabase.h"
#include "third_party/sqlite/sqlite3.h"
-using WebKit::WebDatabase;
+using blink::WebString;
namespace content {
+
namespace {
const int kResultHistogramSize = 50;
@@ -38,12 +38,12 @@ int DetermineHistogramResult(int websql_error, int sqlite_error) {
return std::min(websql_error + 30, kResultHistogramSize - 1);
}
-#define HISTOGRAM_WEBSQL_RESULT(name, database, callsite, \
- websql_error, sqlite_error) \
+#define HISTOGRAM_WEBSQL_RESULT(name, is_sync_database, \
+ callsite, websql_error, sqlite_error) \
do { \
DCHECK(callsite < kCallsiteHistogramSize); \
int result = DetermineHistogramResult(websql_error, sqlite_error); \
- if (database.isSyncDatabase()) { \
+ if (is_sync_database) { \
UMA_HISTOGRAM_ENUMERATION("websql.Sync." name, \
result, kResultHistogramSize); \
if (result) { \
@@ -73,83 +73,97 @@ WebDatabaseObserverImpl::~WebDatabaseObserverImpl() {
}
void WebDatabaseObserverImpl::databaseOpened(
- const WebDatabase& database) {
- std::string origin_identifier =
- database.securityOrigin().databaseIdentifier().utf8();
- string16 database_name = database.name();
- open_connections_->AddOpenConnection(origin_identifier, database_name);
+ const WebString& origin_identifier,
+ const WebString& database_name,
+ const WebString& database_display_name,
+ unsigned long estimated_size) {
+ open_connections_->AddOpenConnection(origin_identifier.utf8(),
+ database_name);
sender_->Send(new DatabaseHostMsg_Opened(
- origin_identifier, database_name,
- database.displayName(), database.estimatedSize()));
+ origin_identifier.utf8(), database_name,
+ database_display_name, estimated_size));
}
void WebDatabaseObserverImpl::databaseModified(
- const WebDatabase& database) {
+ const WebString& origin_identifier,
+ const WebString& database_name) {
sender_->Send(new DatabaseHostMsg_Modified(
- database.securityOrigin().databaseIdentifier().utf8(), database.name()));
+ origin_identifier.utf8(), database_name));
}
void WebDatabaseObserverImpl::databaseClosed(
- const WebDatabase& database) {
- std::string origin_identifier =
- database.securityOrigin().databaseIdentifier().utf8();
- string16 database_name = database.name();
+ const WebString& origin_identifier,
+ const WebString& database_name) {
sender_->Send(new DatabaseHostMsg_Closed(
- origin_identifier, database_name));
- open_connections_->RemoveOpenConnection(origin_identifier, database_name);
+ origin_identifier.utf8(), database_name));
+ open_connections_->RemoveOpenConnection(origin_identifier.utf8(),
+ database_name);
}
void WebDatabaseObserverImpl::reportOpenDatabaseResult(
- const WebDatabase& database, int callsite, int websql_error,
- int sqlite_error) {
- HISTOGRAM_WEBSQL_RESULT("OpenResult", database, callsite,
- websql_error, sqlite_error);
- HandleSqliteError(database, sqlite_error);
+ const WebString& origin_identifier,
+ const WebString& database_name,
+ bool is_sync_database,
+ int callsite, int websql_error, int sqlite_error) {
+ HISTOGRAM_WEBSQL_RESULT("OpenResult", is_sync_database,
+ callsite, websql_error, sqlite_error);
+ HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportChangeVersionResult(
- const WebDatabase& database, int callsite, int websql_error,
- int sqlite_error) {
- HISTOGRAM_WEBSQL_RESULT("ChangeVersionResult", database, callsite,
- websql_error, sqlite_error);
- HandleSqliteError(database, sqlite_error);
+ const WebString& origin_identifier,
+ const WebString& database_name,
+ bool is_sync_database,
+ int callsite, int websql_error, int sqlite_error) {
+ HISTOGRAM_WEBSQL_RESULT("ChangeVersionResult", is_sync_database,
+ callsite, websql_error, sqlite_error);
+ HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportStartTransactionResult(
- const WebDatabase& database, int callsite, int websql_error,
- int sqlite_error) {
- HISTOGRAM_WEBSQL_RESULT("BeginResult", database, callsite,
- websql_error, sqlite_error);
- HandleSqliteError(database, sqlite_error);
+ const WebString& origin_identifier,
+ const WebString& database_name,
+ bool is_sync_database,
+ int callsite, int websql_error, int sqlite_error) {
+ HISTOGRAM_WEBSQL_RESULT("BeginResult", is_sync_database,
+ callsite, websql_error, sqlite_error);
+ HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportCommitTransactionResult(
- const WebDatabase& database, int callsite, int websql_error,
- int sqlite_error) {
- HISTOGRAM_WEBSQL_RESULT("CommitResult", database, callsite,
- websql_error, sqlite_error);
- HandleSqliteError(database, sqlite_error);
+ const WebString& origin_identifier,
+ const WebString& database_name,
+ bool is_sync_database,
+ int callsite, int websql_error, int sqlite_error) {
+ HISTOGRAM_WEBSQL_RESULT("CommitResult", is_sync_database,
+ callsite, websql_error, sqlite_error);
+ HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportExecuteStatementResult(
- const WebDatabase& database, int callsite, int websql_error,
- int sqlite_error) {
- HISTOGRAM_WEBSQL_RESULT("StatementResult", database, callsite,
- websql_error, sqlite_error);
- HandleSqliteError(database, sqlite_error);
+ const WebString& origin_identifier,
+ const WebString& database_name,
+ bool is_sync_database,
+ int callsite, int websql_error, int sqlite_error) {
+ HISTOGRAM_WEBSQL_RESULT("StatementResult", is_sync_database,
+ callsite, websql_error, sqlite_error);
+ HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportVacuumDatabaseResult(
- const WebDatabase& database, int sqlite_error) {
+ const WebString& origin_identifier,
+ const WebString& database_name,
+ bool is_sync_database,
+ int sqlite_error) {
int result = DetermineHistogramResult(-1, sqlite_error);
- if (database.isSyncDatabase()) {
+ if (is_sync_database) {
UMA_HISTOGRAM_ENUMERATION("websql.Sync.VacuumResult",
result, kResultHistogramSize);
} else {
UMA_HISTOGRAM_ENUMERATION("websql.Async.VacuumResult",
result, kResultHistogramSize);
}
- HandleSqliteError(database, sqlite_error);
+ HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::WaitForAllDatabasesToClose() {
@@ -157,14 +171,16 @@ void WebDatabaseObserverImpl::WaitForAllDatabasesToClose() {
}
void WebDatabaseObserverImpl::HandleSqliteError(
- const WebDatabase& database, int error) {
+ const WebString& origin_identifier,
+ const WebString& database_name,
+ int error) {
// We filter out errors which the backend doesn't act on to avoid
// 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(
- database.securityOrigin().databaseIdentifier().utf8(),
- database.name(),
+ origin_identifier.utf8(),
+ database_name,
error));
}
}
diff --git a/chromium/content/child/web_database_observer_impl.h b/chromium/content/child/web_database_observer_impl.h
index 67631a2f967..ed85b9213b5 100644
--- a/chromium/content/child/web_database_observer_impl.h
+++ b/chromium/content/child/web_database_observer_impl.h
@@ -7,45 +7,69 @@
#include "base/memory/ref_counted.h"
#include "ipc/ipc_sync_message_filter.h"
-#include "third_party/WebKit/public/web/WebDatabaseObserver.h"
+#include "third_party/WebKit/public/platform/WebDatabaseObserver.h"
#include "webkit/common/database/database_connections.h"
namespace content {
-class WebDatabaseObserverImpl : public WebKit::WebDatabaseObserver {
+class WebDatabaseObserverImpl : public blink::WebDatabaseObserver {
public:
explicit WebDatabaseObserverImpl(IPC::SyncMessageFilter* sender);
virtual ~WebDatabaseObserverImpl();
- virtual void databaseOpened(const WebKit::WebDatabase& database) OVERRIDE;
- virtual void databaseModified(const WebKit::WebDatabase& database) OVERRIDE;
- virtual void databaseClosed(const WebKit::WebDatabase& database) OVERRIDE;
-
+ virtual void databaseOpened(
+ const blink::WebString& origin_identifier,
+ const blink::WebString& database_name,
+ const blink::WebString& database_display_name,
+ unsigned long estimated_size);
+ virtual void databaseModified(
+ const blink::WebString& origin_identifier,
+ const blink::WebString& database_name);
+ virtual void databaseClosed(
+ const blink::WebString& origin_identifier,
+ const blink::WebString& database_name);
virtual void reportOpenDatabaseResult(
- const WebKit::WebDatabase& database, int callsite,
- int websql_error, int sqlite_error) OVERRIDE;
+ const blink::WebString& origin_identifier,
+ const blink::WebString& database_name,
+ bool is_sync_database,
+ int callsite, int websql_error, int sqlite_error);
virtual void reportChangeVersionResult(
- const WebKit::WebDatabase& database, int callsite,
- int websql_error, int sqlite_error) OVERRIDE;
+ const blink::WebString& origin_identifier,
+ const blink::WebString& database_name,
+ bool is_sync_database,
+ int callsite, int websql_error, int sqlite_error);
virtual void reportStartTransactionResult(
- const WebKit::WebDatabase& database, int callsite,
- int websql_error, int sqlite_error) OVERRIDE;
+ const blink::WebString& origin_identifier,
+ const blink::WebString& database_name,
+ bool is_sync_database,
+ int callsite, int websql_error, int sqlite_error);
virtual void reportCommitTransactionResult(
- const WebKit::WebDatabase& database, int callsite,
- int websql_error, int sqlite_error) OVERRIDE;
+ const blink::WebString& origin_identifier,
+ const blink::WebString& database_name,
+ bool is_sync_database,
+ int callsite, int websql_error, int sqlite_error);
virtual void reportExecuteStatementResult(
- const WebKit::WebDatabase& database, int callsite,
- int websql_error, int sqlite_error) OVERRIDE;
+ const blink::WebString& origin_identifier,
+ const blink::WebString& database_name,
+ bool is_sync_database,
+ int callsite, int websql_error, int sqlite_error);
virtual void reportVacuumDatabaseResult(
- const WebKit::WebDatabase& database, int sqlite_error) OVERRIDE;
+ const blink::WebString& origin_identifier,
+ const blink::WebString& database_name,
+ bool is_sync_database,
+ int sqlite_error);
void WaitForAllDatabasesToClose();
private:
- void HandleSqliteError(const WebKit::WebDatabase& database, int error);
+ void HandleSqliteError(const blink::WebString& origin_identifier,
+ const blink::WebString& database_name,
+ int error);
scoped_refptr<IPC::SyncMessageFilter> sender_;
scoped_refptr<webkit_database::DatabaseConnectionsWrapper> open_connections_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebDatabaseObserverImpl);
};
} // namespace content
diff --git a/chromium/content/child/webblobregistry_impl.cc b/chromium/content/child/webblobregistry_impl.cc
index b701c033bc0..fcc3ebf051a 100644
--- a/chromium/content/child/webblobregistry_impl.cc
+++ b/chromium/content/child/webblobregistry_impl.cc
@@ -18,10 +18,10 @@
#include "third_party/WebKit/public/platform/WebURL.h"
#include "webkit/common/blob/blob_data.h"
-using WebKit::WebBlobData;
-using WebKit::WebString;
-using WebKit::WebThreadSafeData;
-using WebKit::WebURL;
+using blink::WebBlobData;
+using blink::WebString;
+using blink::WebThreadSafeData;
+using blink::WebURL;
namespace content {
@@ -40,7 +40,7 @@ WebBlobRegistryImpl::~WebBlobRegistryImpl() {
}
void WebBlobRegistryImpl::registerBlobData(
- const WebKit::WebString& uuid, const WebKit::WebBlobData& data) {
+ const blink::WebString& uuid, const blink::WebBlobData& data) {
const std::string uuid_str(uuid.utf8());
sender_->Send(new BlobHostMsg_StartBuilding(uuid_str));
@@ -69,21 +69,21 @@ void WebBlobRegistryImpl::registerBlobData(
case WebBlobData::Item::TypeBlob:
if (data_item.length) {
webkit_blob::BlobData::Item item;
- item.SetToBlobUrlRange(
- data_item.blobURL,
+ item.SetToBlobRange(
+ data_item.blobUUID.utf8(),
static_cast<uint64>(data_item.offset),
static_cast<uint64>(data_item.length));
sender_->Send(
new BlobHostMsg_AppendBlobDataItem(uuid_str, item));
}
break;
- case WebBlobData::Item::TypeURL:
+ case WebBlobData::Item::TypeFileSystemURL:
if (data_item.length) {
// We only support filesystem URL as of now.
- DCHECK(GURL(data_item.url).SchemeIsFileSystem());
+ DCHECK(GURL(data_item.fileSystemURL).SchemeIsFileSystem());
webkit_blob::BlobData::Item item;
item.SetToFileSystemUrlRange(
- data_item.url,
+ data_item.fileSystemURL,
static_cast<uint64>(data_item.offset),
static_cast<uint64>(data_item.length),
base::Time::FromDoubleT(data_item.expectedModificationTime));
@@ -148,33 +148,6 @@ void WebBlobRegistryImpl::SendDataForBlob(const std::string& uuid_str,
}
}
-// DEPRECATED, almost. Until blink is updated, we implement these older methods
-// in terms of our newer blob storage system. We create a uuid for each 'data'
-// we see and construct a mapping from the private blob urls we're given to
-// that uuid. The mapping is maintained in the browser process.
-//
-// Chromium is setup to speak in terms of old-style private blob urls or
-// new-style uuid identifiers. Once blink has been migrated support for
-// the old-style will be deleted. Search for the term deprecated.
-
-void WebBlobRegistryImpl::registerBlobURL(
- const WebURL& url, WebBlobData& data) {
- std::string uuid = base::GenerateGUID();
- registerBlobData(WebKit::WebString::fromUTF8(uuid), data);
- sender_->Send(new BlobHostMsg_DeprecatedRegisterBlobURL(url, uuid));
- sender_->Send(new BlobHostMsg_DecrementRefCount(uuid));
-}
-
-void WebBlobRegistryImpl::registerBlobURL(
- const WebURL& url, const WebURL& src_url) {
- sender_->Send(new BlobHostMsg_DeprecatedCloneBlobURL(url, src_url));
-}
-
-void WebBlobRegistryImpl::unregisterBlobURL(const WebURL& url) {
- sender_->Send(new BlobHostMsg_DeprecatedRevokeBlobURL(url));
-}
-
-
// ------ streams stuff -----
void WebBlobRegistryImpl::registerStreamURL(
diff --git a/chromium/content/child/webblobregistry_impl.h b/chromium/content/child/webblobregistry_impl.h
index 1d6e54ed489..6588a529073 100644
--- a/chromium/content/child/webblobregistry_impl.h
+++ b/chromium/content/child/webblobregistry_impl.h
@@ -9,7 +9,7 @@
#include "third_party/WebKit/public/platform/WebBlobRegistry.h"
#include "webkit/common/blob/blob_data.h"
-namespace WebKit {
+namespace blink {
class WebBlobData;
class WebString;
class WebThreadSafeData;
@@ -19,41 +19,33 @@ class WebURL;
namespace content {
class ThreadSafeSender;
-class WebBlobRegistryImpl : public WebKit::WebBlobRegistry {
+class WebBlobRegistryImpl : public blink::WebBlobRegistry {
public:
explicit WebBlobRegistryImpl(ThreadSafeSender* sender);
virtual ~WebBlobRegistryImpl();
- virtual void registerBlobData(const WebKit::WebString& uuid,
- const WebKit::WebBlobData& data);
- virtual void addBlobDataRef(const WebKit::WebString& uuid);
- virtual void removeBlobDataRef(const WebKit::WebString& uuid);
- virtual void registerPublicBlobURL(const WebKit::WebURL&,
- const WebKit::WebString& uuid);
- virtual void revokePublicBlobURL(const WebKit::WebURL&);
-
- // DEPRECATED
- // TODO(michaeln): crbug/174200
- virtual void registerBlobURL(const WebKit::WebURL& url,
- WebKit::WebBlobData& data);
- virtual void registerBlobURL(const WebKit::WebURL& url,
- const WebKit::WebURL& src_url);
- virtual void unregisterBlobURL(const WebKit::WebURL& url);
+ virtual void registerBlobData(const blink::WebString& uuid,
+ const blink::WebBlobData& data);
+ virtual void addBlobDataRef(const blink::WebString& uuid);
+ virtual void removeBlobDataRef(const blink::WebString& uuid);
+ virtual void registerPublicBlobURL(const blink::WebURL&,
+ const blink::WebString& uuid);
+ virtual void revokePublicBlobURL(const blink::WebURL&);
// Additional support for Streams.
- virtual void registerStreamURL(const WebKit::WebURL& url,
- const WebKit::WebString& content_type);
- virtual void registerStreamURL(const WebKit::WebURL& url,
- const WebKit::WebURL& src_url);
- virtual void addDataToStream(const WebKit::WebURL& url,
- WebKit::WebThreadSafeData& data);
- virtual void finalizeStream(const WebKit::WebURL& url);
- virtual void abortStream(const WebKit::WebURL& url);
- virtual void unregisterStreamURL(const WebKit::WebURL& url);
+ virtual void registerStreamURL(const blink::WebURL& url,
+ const blink::WebString& content_type);
+ virtual void registerStreamURL(const blink::WebURL& url,
+ const blink::WebURL& src_url);
+ virtual void addDataToStream(const blink::WebURL& url,
+ blink::WebThreadSafeData& data);
+ virtual void finalizeStream(const blink::WebURL& url);
+ virtual void abortStream(const blink::WebURL& url);
+ virtual void unregisterStreamURL(const blink::WebURL& url);
private:
void SendDataForBlob(const std::string& uuid_str,
- const WebKit::WebThreadSafeData& data);
+ const blink::WebThreadSafeData& data);
scoped_refptr<ThreadSafeSender> sender_;
};
diff --git a/chromium/content/child/webkitplatformsupport_impl.cc b/chromium/content/child/webkitplatformsupport_impl.cc
index 191b2f85099..5b8cc79ac49 100644
--- a/chromium/content/child/webkitplatformsupport_impl.cc
+++ b/chromium/content/child/webkitplatformsupport_impl.cc
@@ -6,6 +6,7 @@
#include "content/child/child_thread.h"
#include "content/child/socket_stream_dispatcher.h"
#include "content/child/webkitplatformsupport_impl.h"
+#include "content/child/websocket_bridge.h"
#include "content/public/common/content_client.h"
namespace content {
@@ -16,7 +17,7 @@ WebKitPlatformSupportImpl::WebKitPlatformSupportImpl() {
WebKitPlatformSupportImpl::~WebKitPlatformSupportImpl() {
}
-string16 WebKitPlatformSupportImpl::GetLocalizedString(int message_id) {
+base::string16 WebKitPlatformSupportImpl::GetLocalizedString(int message_id) {
return GetContentClient()->GetLocalizedString(message_id);
}
@@ -33,12 +34,16 @@ WebKitPlatformSupportImpl::CreateResourceLoader(
}
webkit_glue::WebSocketStreamHandleBridge*
-WebKitPlatformSupportImpl::CreateWebSocketBridge(
- WebKit::WebSocketStreamHandle* handle,
+WebKitPlatformSupportImpl::CreateWebSocketStreamBridge(
+ blink::WebSocketStreamHandle* handle,
webkit_glue::WebSocketStreamHandleDelegate* delegate) {
SocketStreamDispatcher* dispatcher =
ChildThread::current()->socket_stream_dispatcher();
return dispatcher->CreateBridge(handle, delegate);
}
+blink::WebSocketHandle* WebKitPlatformSupportImpl::createWebSocketHandle() {
+ return new WebSocketBridge;
+}
+
} // namespace content
diff --git a/chromium/content/child/webkitplatformsupport_impl.h b/chromium/content/child/webkitplatformsupport_impl.h
index f74fcd9351c..b4d5fc7e4c9 100644
--- a/chromium/content/child/webkitplatformsupport_impl.h
+++ b/chromium/content/child/webkitplatformsupport_impl.h
@@ -17,21 +17,22 @@ namespace content {
class CONTENT_EXPORT WebKitPlatformSupportImpl
: NON_EXPORTED_BASE(public webkit_glue::WebKitPlatformSupportChildImpl) {
public:
- typedef WebKit::WebGraphicsContext3D* (OffscreenContextFactory)();
+ typedef blink::WebGraphicsContext3D* (OffscreenContextFactory)();
WebKitPlatformSupportImpl();
virtual ~WebKitPlatformSupportImpl();
- virtual string16 GetLocalizedString(int message_id) OVERRIDE;
+ virtual base::string16 GetLocalizedString(int message_id) OVERRIDE;
virtual base::StringPiece GetDataResource(
int resource_id,
ui::ScaleFactor scale_factor) OVERRIDE;
virtual webkit_glue::ResourceLoaderBridge* CreateResourceLoader(
const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info)
OVERRIDE;
- virtual webkit_glue::WebSocketStreamHandleBridge* CreateWebSocketBridge(
- WebKit::WebSocketStreamHandle* handle,
+ virtual webkit_glue::WebSocketStreamHandleBridge* CreateWebSocketStreamBridge(
+ blink::WebSocketStreamHandle* handle,
webkit_glue::WebSocketStreamHandleDelegate* delegate) OVERRIDE;
+ virtual blink::WebSocketHandle* createWebSocketHandle() OVERRIDE;
};
} // namespace content
diff --git a/chromium/content/child/webmessageportchannel_impl.cc b/chromium/content/child/webmessageportchannel_impl.cc
index ed621adf008..7b0658ec665 100644
--- a/chromium/content/child/webmessageportchannel_impl.cc
+++ b/chromium/content/child/webmessageportchannel_impl.cc
@@ -8,14 +8,14 @@
#include "base/message_loop/message_loop_proxy.h"
#include "content/child/child_process.h"
#include "content/child/child_thread.h"
-#include "content/common/worker_messages.h"
+#include "content/common/message_port_messages.h"
#include "third_party/WebKit/public/platform/WebMessagePortChannelClient.h"
#include "third_party/WebKit/public/platform/WebString.h"
-using WebKit::WebMessagePortChannel;
-using WebKit::WebMessagePortChannelArray;
-using WebKit::WebMessagePortChannelClient;
-using WebKit::WebString;
+using blink::WebMessagePortChannel;
+using blink::WebMessagePortChannelArray;
+using blink::WebMessagePortChannelClient;
+using blink::WebString;
namespace content {
@@ -53,7 +53,7 @@ WebMessagePortChannelImpl::~WebMessagePortChannelImpl() {
}
if (message_port_id_ != MSG_ROUTING_NONE)
- Send(new WorkerProcessHostMsg_DestroyMessagePort(message_port_id_));
+ Send(new MessagePortHostMsg_DestroyMessagePort(message_port_id_));
if (route_id_ != MSG_ROUTING_NONE)
ChildThread::current()->RemoveRoute(route_id_);
@@ -106,7 +106,7 @@ void WebMessagePortChannelImpl::postMessage(
delete channels;
}
- IPC::Message* msg = new WorkerProcessHostMsg_PostMessage(
+ IPC::Message* msg = new MessagePortHostMsg_PostMessage(
message_port_id_, message, message_port_ids);
Send(msg);
}
@@ -140,7 +140,7 @@ void WebMessagePortChannelImpl::Init() {
if (route_id_ == MSG_ROUTING_NONE) {
DCHECK(message_port_id_ == MSG_ROUTING_NONE);
- Send(new WorkerProcessHostMsg_CreateMessagePort(
+ Send(new MessagePortHostMsg_CreateMessagePort(
&route_id_, &message_port_id_));
}
@@ -156,7 +156,7 @@ void WebMessagePortChannelImpl::Entangle(
return;
}
- Send(new WorkerProcessHostMsg_Entangle(
+ Send(new MessagePortHostMsg_Entangle(
message_port_id_, channel->message_port_id()));
}
@@ -172,7 +172,7 @@ void WebMessagePortChannelImpl::QueueMessages() {
// sends us an ack, whose receipt we know means that no more messages are
// in-flight. We then send the queued messages to the browser, which prepends
// them to the ones it queued and it sends them to the new endpoint.
- Send(new WorkerProcessHostMsg_QueueMessages(message_port_id_));
+ Send(new MessagePortHostMsg_QueueMessages(message_port_id_));
// The process could potentially go away while we're still waiting for
// in-flight messages. Ensure it stays alive.
@@ -194,15 +194,15 @@ void WebMessagePortChannelImpl::Send(IPC::Message* message) {
bool WebMessagePortChannelImpl::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(WebMessagePortChannelImpl, message)
- IPC_MESSAGE_HANDLER(WorkerProcessMsg_Message, OnMessage)
- IPC_MESSAGE_HANDLER(WorkerProcessMsg_MessagesQueued, OnMessagesQueued)
+ IPC_MESSAGE_HANDLER(MessagePortMsg_Message, OnMessage)
+ IPC_MESSAGE_HANDLER(MessagePortMsg_MessagesQueued, OnMessagesQueued)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void WebMessagePortChannelImpl::OnMessage(
- const string16& message,
+ const base::string16& message,
const std::vector<int>& sent_message_port_ids,
const std::vector<int>& new_routing_ids) {
base::AutoLock auto_lock(lock_);
@@ -230,7 +230,7 @@ void WebMessagePortChannelImpl::OnMessagesQueued() {
base::AutoLock auto_lock(lock_);
queued_messages.reserve(message_queue_.size());
while (!message_queue_.empty()) {
- string16 message = message_queue_.front().message;
+ base::string16 message = message_queue_.front().message;
const std::vector<WebMessagePortChannelImpl*>& channel_array =
message_queue_.front().ports;
std::vector<int> port_ids(channel_array.size());
@@ -243,7 +243,7 @@ void WebMessagePortChannelImpl::OnMessagesQueued() {
}
}
- Send(new WorkerProcessHostMsg_SendQueuedMessages(
+ Send(new MessagePortHostMsg_SendQueuedMessages(
message_port_id_, queued_messages));
message_port_id_ = MSG_ROUTING_NONE;
diff --git a/chromium/content/child/webmessageportchannel_impl.h b/chromium/content/child/webmessageportchannel_impl.h
index 84d3f0e067d..efc1e041678 100644
--- a/chromium/content/child/webmessageportchannel_impl.h
+++ b/chromium/content/child/webmessageportchannel_impl.h
@@ -24,7 +24,7 @@ class ChildThread;
// This is thread safe.
class WebMessagePortChannelImpl
- : public WebKit::WebMessagePortChannel,
+ : public blink::WebMessagePortChannel,
public IPC::Listener,
public base::RefCountedThreadSafe<WebMessagePortChannelImpl> {
public:
@@ -43,13 +43,13 @@ class WebMessagePortChannelImpl
virtual ~WebMessagePortChannelImpl();
// WebMessagePortChannel implementation.
- virtual void setClient(WebKit::WebMessagePortChannelClient* client);
+ virtual void setClient(blink::WebMessagePortChannelClient* client);
virtual void destroy();
- virtual void entangle(WebKit::WebMessagePortChannel* channel);
- virtual void postMessage(const WebKit::WebString& message,
- WebKit::WebMessagePortChannelArray* channels);
- virtual bool tryGetMessage(WebKit::WebString* message,
- WebKit::WebMessagePortChannelArray& channels);
+ virtual void entangle(blink::WebMessagePortChannel* channel);
+ virtual void postMessage(const blink::WebString& message,
+ blink::WebMessagePortChannelArray* channels);
+ virtual bool tryGetMessage(blink::WebString* message,
+ blink::WebMessagePortChannelArray& channels);
void Init();
void Entangle(scoped_refptr<WebMessagePortChannelImpl> channel);
@@ -58,7 +58,7 @@ class WebMessagePortChannelImpl
// IPC::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- void OnMessage(const string16& message,
+ void OnMessage(const base::string16& message,
const std::vector<int>& sent_message_port_ids,
const std::vector<int>& new_routing_ids);
void OnMessagesQueued();
@@ -67,14 +67,14 @@ class WebMessagePortChannelImpl
Message();
~Message();
- string16 message;
+ base::string16 message;
std::vector<WebMessagePortChannelImpl*> ports;
};
typedef std::queue<Message> MessageQueue;
MessageQueue message_queue_;
- WebKit::WebMessagePortChannelClient* client_;
+ blink::WebMessagePortChannelClient* client_;
base::Lock lock_; // Locks access to above.
int route_id_; // The routing id for this object.
diff --git a/chromium/content/child/websocket_bridge.cc b/chromium/content/child/websocket_bridge.cc
new file mode 100644
index 00000000000..c8e74ef9b43
--- /dev/null
+++ b/chromium/content/child/websocket_bridge.cc
@@ -0,0 +1,284 @@
+// 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/child/websocket_bridge.h"
+
+#include <stdint.h>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "content/child/child_thread.h"
+#include "content/child/websocket_dispatcher.h"
+#include "content/common/websocket.h"
+#include "content/common/websocket_messages.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_macros.h"
+#include "url/gurl.h"
+#include "third_party/WebKit/public/platform/WebSocketHandle.h"
+#include "third_party/WebKit/public/platform/WebSocketHandleClient.h"
+#include "third_party/WebKit/public/platform/WebSocketHandshakeRequestInfo.h"
+#include "third_party/WebKit/public/platform/WebSocketHandshakeResponseInfo.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
+
+using blink::WebSocketHandle;
+using blink::WebSocketHandleClient;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebVector;
+
+namespace content {
+
+namespace {
+
+const unsigned short kAbnormalShutdownOpCode = 1006;
+
+} // namespace
+
+WebSocketBridge::WebSocketBridge()
+ : channel_id_(kInvalidChannelId), client_(NULL) {}
+
+WebSocketBridge::~WebSocketBridge() {
+ if (channel_id_ != kInvalidChannelId) {
+ // The connection is abruptly disconnected by the renderer without
+ // closing handshake.
+ ChildThread::current()->Send(
+ new WebSocketMsg_DropChannel(channel_id_,
+ false,
+ kAbnormalShutdownOpCode,
+ std::string()));
+ }
+ Disconnect();
+}
+
+bool WebSocketBridge::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(WebSocketBridge, msg)
+ IPC_MESSAGE_HANDLER(WebSocketMsg_AddChannelResponse, DidConnect)
+ IPC_MESSAGE_HANDLER(WebSocketMsg_NotifyStartOpeningHandshake,
+ DidStartOpeningHandshake)
+ IPC_MESSAGE_HANDLER(WebSocketMsg_NotifyFinishOpeningHandshake,
+ DidFinishOpeningHandshake)
+ IPC_MESSAGE_HANDLER(WebSocketMsg_NotifyFailure, DidFail)
+ IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, DidReceiveData)
+ IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, DidReceiveFlowControl)
+ IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, DidClose)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void WebSocketBridge::DidConnect(bool fail,
+ const std::string& selected_protocol,
+ const std::string& extensions) {
+ WebSocketHandleClient* client = client_;
+ DVLOG(1) << "WebSocketBridge::DidConnect("
+ << fail << ", "
+ << selected_protocol << ", "
+ << extensions << ")";
+ if (fail)
+ Disconnect();
+ if (!client)
+ return;
+
+ WebString protocol_to_pass = WebString::fromUTF8(selected_protocol);
+ WebString extensions_to_pass = WebString::fromUTF8(extensions);
+ client->didConnect(this, fail, protocol_to_pass, extensions_to_pass);
+ // |this| can be deleted here.
+}
+
+void WebSocketBridge::DidStartOpeningHandshake(
+ const WebSocketHandshakeRequest& request) {
+ DVLOG(1) << "WebSocketBridge::DidStartOpeningHandshake("
+ << request.url << ")";
+ // All strings are already encoded to ASCII in the browser.
+ blink::WebSocketHandshakeRequestInfo request_to_pass;
+ request_to_pass.setURL(WebURL(request.url));
+ for (size_t i = 0; i < request.headers.size(); ++i) {
+ const std::pair<std::string, std::string>& header = request.headers[i];
+ request_to_pass.addHeaderField(WebString::fromLatin1(header.first),
+ WebString::fromLatin1(header.second));
+ }
+ client_->didStartOpeningHandshake(this, request_to_pass);
+}
+
+void WebSocketBridge::DidFinishOpeningHandshake(
+ const WebSocketHandshakeResponse& response) {
+ DVLOG(1) << "WebSocketBridge::DidFinishOpeningHandshake("
+ << response.url << ")";
+ // All strings are already encoded to ASCII in the browser.
+ blink::WebSocketHandshakeResponseInfo response_to_pass;
+ response_to_pass.setStatusCode(response.status_code);
+ response_to_pass.setStatusText(WebString::fromLatin1(response.status_text));
+ for (size_t i = 0; i < response.headers.size(); ++i) {
+ const std::pair<std::string, std::string>& header = response.headers[i];
+ response_to_pass.addHeaderField(WebString::fromLatin1(header.first),
+ WebString::fromLatin1(header.second));
+ }
+ client_->didFinishOpeningHandshake(this, response_to_pass);
+}
+
+void WebSocketBridge::DidFail(const std::string& message) {
+ DVLOG(1) << "WebSocketBridge::DidFail(" << message << ")";
+ WebSocketHandleClient* client = client_;
+ Disconnect();
+ if (!client)
+ return;
+
+ WebString message_to_pass = WebString::fromUTF8(message);
+ client->didFail(this, message_to_pass);
+ // |this| can be deleted here.
+}
+
+void WebSocketBridge::DidReceiveData(bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data) {
+ DVLOG(1) << "WebSocketBridge::DidReceiveData("
+ << fin << ", "
+ << type << ", "
+ << "(data size = " << data.size() << "))";
+ if (!client_)
+ return;
+
+ WebSocketHandle::MessageType type_to_pass =
+ WebSocketHandle::MessageTypeContinuation;
+ switch (type) {
+ case WEB_SOCKET_MESSAGE_TYPE_CONTINUATION:
+ type_to_pass = WebSocketHandle::MessageTypeContinuation;
+ break;
+ case WEB_SOCKET_MESSAGE_TYPE_TEXT:
+ type_to_pass = WebSocketHandle::MessageTypeText;
+ break;
+ case WEB_SOCKET_MESSAGE_TYPE_BINARY:
+ type_to_pass = WebSocketHandle::MessageTypeBinary;
+ break;
+ }
+ const char* data_to_pass = data.empty() ? NULL : &data[0];
+ client_->didReceiveData(this, fin, type_to_pass, data_to_pass, data.size());
+ // |this| can be deleted here.
+}
+
+void WebSocketBridge::DidReceiveFlowControl(int64_t quota) {
+ DVLOG(1) << "WebSocketBridge::DidReceiveFlowControl(" << quota << ")";
+ if (!client_)
+ return;
+
+ client_->didReceiveFlowControl(this, quota);
+ // |this| can be deleted here.
+}
+
+void WebSocketBridge::DidClose(bool was_clean,
+ unsigned short code,
+ const std::string& reason) {
+ DVLOG(1) << "WebSocketBridge::DidClose("
+ << was_clean << ", "
+ << code << ", "
+ << reason << ")";
+ WebSocketHandleClient* client = client_;
+ Disconnect();
+ if (!client)
+ return;
+
+ WebString reason_to_pass = WebString::fromUTF8(reason);
+ client->didClose(this, was_clean, code, reason_to_pass);
+ // |this| can be deleted here.
+}
+
+void WebSocketBridge::connect(
+ const WebURL& url,
+ const WebVector<WebString>& protocols,
+ const WebString& origin,
+ WebSocketHandleClient* client) {
+ DCHECK_EQ(kInvalidChannelId, channel_id_);
+ WebSocketDispatcher* dispatcher =
+ ChildThread::current()->websocket_dispatcher();
+ channel_id_ = dispatcher->AddBridge(this);
+ client_ = client;
+
+ std::vector<std::string> protocols_to_pass;
+ for (size_t i = 0; i < protocols.size(); ++i)
+ protocols_to_pass.push_back(protocols[i].utf8());
+ GURL origin_to_pass(origin.utf8());
+
+ DVLOG(1) << "Bridge#" << channel_id_ << " Connect("
+ << url << ", (" << JoinString(protocols_to_pass, ", ") << "), "
+ << origin_to_pass << ")";
+
+ ChildThread::current()->Send(
+ new WebSocketHostMsg_AddChannelRequest(channel_id_,
+ url,
+ protocols_to_pass,
+ origin_to_pass));
+}
+
+void WebSocketBridge::send(bool fin,
+ WebSocketHandle::MessageType type,
+ const char* data,
+ size_t size) {
+ if (channel_id_ == kInvalidChannelId)
+ return;
+
+ WebSocketMessageType type_to_pass = WEB_SOCKET_MESSAGE_TYPE_CONTINUATION;
+ switch (type) {
+ case WebSocketHandle::MessageTypeContinuation:
+ type_to_pass = WEB_SOCKET_MESSAGE_TYPE_CONTINUATION;
+ break;
+ case WebSocketHandle::MessageTypeText:
+ type_to_pass = WEB_SOCKET_MESSAGE_TYPE_TEXT;
+ break;
+ case WebSocketHandle::MessageTypeBinary:
+ type_to_pass = WEB_SOCKET_MESSAGE_TYPE_BINARY;
+ break;
+ }
+
+ DVLOG(1) << "Bridge #" << channel_id_ << " Send("
+ << fin << ", " << type_to_pass << ", "
+ << "(data size = " << size << "))";
+
+ ChildThread::current()->Send(
+ new WebSocketMsg_SendFrame(channel_id_,
+ fin,
+ type_to_pass,
+ std::vector<char>(data, data + size)));
+}
+
+void WebSocketBridge::flowControl(int64_t quota) {
+ if (channel_id_ == kInvalidChannelId)
+ return;
+
+ DVLOG(1) << "Bridge #" << channel_id_ << " FlowControl(" << quota << ")";
+
+ ChildThread::current()->Send(
+ new WebSocketMsg_FlowControl(channel_id_, quota));
+}
+
+void WebSocketBridge::close(unsigned short code,
+ const WebString& reason) {
+ if (channel_id_ == kInvalidChannelId)
+ return;
+
+ std::string reason_to_pass = reason.utf8();
+ DVLOG(1) << "Bridge #" << channel_id_ << " Close("
+ << code << ", " << reason_to_pass << ")";
+ // This method is for closing handshake and hence |was_clean| shall be true.
+ ChildThread::current()->Send(
+ new WebSocketMsg_DropChannel(channel_id_, true, code, reason_to_pass));
+}
+
+void WebSocketBridge::Disconnect() {
+ if (channel_id_ == kInvalidChannelId)
+ return;
+ WebSocketDispatcher* dispatcher =
+ ChildThread::current()->websocket_dispatcher();
+ dispatcher->RemoveBridge(channel_id_);
+
+ channel_id_ = kInvalidChannelId;
+ client_ = NULL;
+}
+
+} // namespace content
diff --git a/chromium/content/child/websocket_bridge.h b/chromium/content/child/websocket_bridge.h
new file mode 100644
index 00000000000..830939b9295
--- /dev/null
+++ b/chromium/content/child/websocket_bridge.h
@@ -0,0 +1,67 @@
+// 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_CHILD_WEBSOCKET_BRIDGE_H_
+#define CONTENT_CHILD_WEBSOCKET_BRIDGE_H_
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "content/common/websocket.h"
+#include "ipc/ipc_message.h"
+#include "third_party/WebKit/public/platform/WebSocketHandle.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
+
+namespace content {
+
+class WebSocketBridge : public blink::WebSocketHandle {
+ public:
+ WebSocketBridge();
+
+ // Handles an IPC message from the browser process.
+ bool OnMessageReceived(const IPC::Message& message);
+
+ // WebSocketHandle functions.
+ virtual void connect(const blink::WebURL& url,
+ const blink::WebVector<blink::WebString>& protocols,
+ const blink::WebString& origin,
+ blink::WebSocketHandleClient* client) OVERRIDE;
+ virtual void send(bool fin,
+ WebSocketHandle::MessageType type,
+ const char* data,
+ size_t size) OVERRIDE;
+ virtual void flowControl(int64_t quota) OVERRIDE;
+ virtual void close(unsigned short code,
+ const blink::WebString& reason) OVERRIDE;
+
+ virtual void Disconnect();
+
+ private:
+ virtual ~WebSocketBridge();
+
+ void DidConnect(bool fail,
+ const std::string& selected_protocol,
+ const std::string& extensions);
+ void DidStartOpeningHandshake(const WebSocketHandshakeRequest& request);
+ void DidFinishOpeningHandshake(const WebSocketHandshakeResponse& response);
+ void DidFail(const std::string& message);
+ void DidReceiveData(bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data);
+ void DidReceiveFlowControl(int64_t quota);
+ void DidClose(bool was_clean, unsigned short code, const std::string& reason);
+
+ int channel_id_;
+ blink::WebSocketHandleClient* client_;
+
+ static const int kInvalidChannelId = -1;
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBSOCKET_BRIDGE_H_
diff --git a/chromium/content/child/websocket_dispatcher.cc b/chromium/content/child/websocket_dispatcher.cc
new file mode 100644
index 00000000000..6c32dd4cd4e
--- /dev/null
+++ b/chromium/content/child/websocket_dispatcher.cc
@@ -0,0 +1,67 @@
+// 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/child/websocket_dispatcher.h"
+
+#include <stdint.h>
+#include <map>
+
+#include "base/logging.h"
+#include "content/child/websocket_bridge.h"
+#include "content/common/websocket_messages.h"
+#include "ipc/ipc_message.h"
+#include "url/gurl.h"
+
+namespace content {
+
+WebSocketDispatcher::WebSocketDispatcher() : channel_id_max_(0) {}
+
+WebSocketDispatcher::~WebSocketDispatcher() {}
+
+int WebSocketDispatcher::AddBridge(WebSocketBridge* bridge) {
+ ++channel_id_max_;
+ bridges_.insert(std::make_pair(channel_id_max_, bridge));
+ return channel_id_max_;
+}
+
+void WebSocketDispatcher::RemoveBridge(int channel_id) {
+ std::map<int, WebSocketBridge*>::iterator iter = bridges_.find(channel_id);
+ if (iter == bridges_.end()) {
+ DVLOG(1) << "Remove a non-existent bridge(" << channel_id << ")";
+ return;
+ }
+ bridges_.erase(iter);
+}
+
+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:
+ break;
+ default:
+ return false;
+ }
+
+ WebSocketBridge* bridge = GetBridge(msg.routing_id(), msg.type());
+ if (!bridge)
+ return true;
+ return bridge->OnMessageReceived(msg);
+}
+
+WebSocketBridge* WebSocketDispatcher::GetBridge(int channel_id, uint32 type) {
+ std::map<int, WebSocketBridge*>::iterator iter = bridges_.find(channel_id);
+ if (iter == bridges_.end()) {
+ DVLOG(1) << "No bridge for channel_id=" << channel_id
+ << ", type=" << type;
+ return NULL;
+ }
+ return iter->second;
+}
+
+} // namespace content
diff --git a/chromium/content/child/websocket_dispatcher.h b/chromium/content/child/websocket_dispatcher.h
new file mode 100644
index 00000000000..5356c3b5daa
--- /dev/null
+++ b/chromium/content/child/websocket_dispatcher.h
@@ -0,0 +1,48 @@
+// 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_CHILD_WEBSOCKET_DISPATCHER_H_
+#define CONTENT_CHILD_WEBSOCKET_DISPATCHER_H_
+
+#include <stdint.h>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ipc/ipc_listener.h"
+
+namespace content {
+
+class WebSocketBridge;
+
+// Dispatches WebSocket related messages sent to a child process from the
+// main browser process. There is one instance per child process. Messages
+// are dispatched on the main child thread. The ChildThread class
+// creates an instance of WebSocketDispatcher and delegates calls to it.
+class WebSocketDispatcher : public IPC::Listener {
+ public:
+ WebSocketDispatcher();
+ virtual ~WebSocketDispatcher();
+
+ // Returns a unique channel id
+ int AddBridge(WebSocketBridge* bridge);
+ void RemoveBridge(int channel_id);
+
+ // IPC::Listener implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ private:
+ WebSocketBridge* GetBridge(int channel_id, uint32 type);
+
+ std::map<int, WebSocketBridge*> bridges_;
+ int channel_id_max_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBSOCKET_DISPATCHER_H_
diff --git a/chromium/content/child/worker_thread_task_runner.cc b/chromium/content/child/worker_thread_task_runner.cc
new file mode 100644
index 00000000000..fb2a5a89c90
--- /dev/null
+++ b/chromium/content/child/worker_thread_task_runner.cc
@@ -0,0 +1,40 @@
+// 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/child/worker_thread_task_runner.h"
+
+#include "base/logging.h"
+#include "webkit/child/worker_task_runner.h"
+
+using webkit_glue::WorkerTaskRunner;
+
+namespace content {
+
+WorkerThreadTaskRunner::WorkerThreadTaskRunner(int worker_thread_id)
+ : worker_thread_id_(worker_thread_id) {
+}
+
+scoped_refptr<WorkerThreadTaskRunner> WorkerThreadTaskRunner::current() {
+ int worker_thread_id = WorkerTaskRunner::Instance()->CurrentWorkerId();
+ if (!worker_thread_id)
+ return scoped_refptr<WorkerThreadTaskRunner>();
+ return make_scoped_refptr(new WorkerThreadTaskRunner(worker_thread_id));
+}
+
+bool WorkerThreadTaskRunner::PostDelayedTask(
+ const tracked_objects::Location& /* from_here */,
+ const base::Closure& task,
+ base::TimeDelta delay) {
+ // Currently non-zero delay is not supported.
+ DCHECK(!delay.ToInternalValue());
+ return WorkerTaskRunner::Instance()->PostTask(worker_thread_id_, task);
+}
+
+bool WorkerThreadTaskRunner::RunsTasksOnCurrentThread() const {
+ return worker_thread_id_ == WorkerTaskRunner::Instance()->CurrentWorkerId();
+}
+
+WorkerThreadTaskRunner::~WorkerThreadTaskRunner() {}
+
+} // namespace content
diff --git a/chromium/content/child/worker_thread_task_runner.h b/chromium/content/child/worker_thread_task_runner.h
new file mode 100644
index 00000000000..a4fbc913bdf
--- /dev/null
+++ b/chromium/content/child/worker_thread_task_runner.h
@@ -0,0 +1,39 @@
+// 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_CHILD_WORKER_THREAD_TASK_RUNNER_H_
+#define CONTENT_CHILD_WORKER_THREAD_TASK_RUNNER_H_
+
+#include "base/task_runner.h"
+
+namespace content {
+
+// A task runner that runs tasks on a single webkit worker thread which
+// is managed by webkit_glue::WorkerTaskRunner.
+// Note that this implementation ignores the delay duration for PostDelayedTask
+// and have it behave the same as PostTask.
+class WorkerThreadTaskRunner : public base::TaskRunner {
+ public:
+ explicit WorkerThreadTaskRunner(int worker_thread_id);
+
+ // Gets the WorkerThreadTaskRunner for the current worker thread.
+ // This returns non-null value only when it is called on a worker thread.
+ static scoped_refptr<WorkerThreadTaskRunner> current();
+
+ // TaskRunner overrides.
+ virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) OVERRIDE;
+ virtual bool RunsTasksOnCurrentThread() const OVERRIDE;
+
+ protected:
+ virtual ~WorkerThreadTaskRunner();
+
+ private:
+ const int worker_thread_id_;
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WORKER_THREAD_TASK_RUNNER_H_
diff --git a/chromium/content/common/DEPS b/chromium/content/common/DEPS
index 7168a14f05c..8cc7f01ebd9 100644
--- a/chromium/content/common/DEPS
+++ b/chromium/content/common/DEPS
@@ -20,12 +20,12 @@ include_rules = [
"+third_party/WebKit/public/platform/WebGamepads.h",
"+third_party/WebKit/public/platform/WebGraphicsContext3D.h",
"+third_party/WebKit/public/platform/WebHTTPBody.h",
- "+third_party/WebKit/public/platform/WebIDBCallbacks.h",
"+third_party/WebKit/public/platform/WebIDBCursor.h",
"+third_party/WebKit/public/platform/WebIDBDatabase.h",
"+third_party/WebKit/public/platform/WebIDBTypes.h",
"+third_party/WebKit/public/platform/WebReferrerPolicy.h",
"+third_party/WebKit/public/platform/WebScreenInfo.h",
+ "+third_party/WebKit/public/platform/WebServiceWorkerError.h",
"+third_party/WebKit/public/platform/WebStorageArea.h",
"+third_party/WebKit/public/platform/WebString.h",
"+third_party/WebKit/public/platform/linux/WebFontFamily.h",
@@ -40,7 +40,6 @@ include_rules = [
"+third_party/WebKit/public/web/WebMediaPlayerAction.h",
"+third_party/WebKit/public/web/WebPluginAction.h",
"+third_party/WebKit/public/web/WebPopupType.h",
- "+third_party/WebKit/public/web/WebScreenInfo.h",
"+third_party/WebKit/public/web/WebTextDirection.h",
"+third_party/WebKit/public/web/WebWindowFeatures.h",
]
diff --git a/chromium/content/common/OWNERS b/chromium/content/common/OWNERS
index 0b4c0b728a7..1e5943d59ce 100644
--- a/chromium/content/common/OWNERS
+++ b/chromium/content/common/OWNERS
@@ -13,6 +13,8 @@ per-file sandbox_mac*=jeremy@chromium.org
per-file *.sb=set noparent
per-file *.sb=jeremy@chromium.org
+per-file pepper*=ananta@chromium.org
+per-file pepper*=bauerb@chromium.org
per-file plugin*=ananta@chromium.org
per-file plugin*=bauerb@chromium.org
@@ -21,12 +23,18 @@ per-file plugin*=bauerb@chromium.org
per-file *_messages*.h=set noparent
per-file *_messages*.h=cdn@chromium.org
per-file *_messages*.h=cevans@chromium.org
+per-file *_messages*.h=dcheng@chromium.org
per-file *_messages*.h=jln@chromium.org
per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=nasko@chromium.org
# Accessibility
per-file accessibility_node_data.*=dmazzoni@chromium.org
per-file accessibility_node_data.*=dtseng@chromium.org
+
+# WebSocket
+per-file websocket.*=ricea@chromium.org
+per-file websocket.*=tyoshino@chromium.org
+per-file websocket.*=yhirano@chromium.org
diff --git a/chromium/content/common/accessibility_messages.h b/chromium/content/common/accessibility_messages.h
index 70d5211ec37..6504802dafb 100644
--- a/chromium/content/common/accessibility_messages.h
+++ b/chromium/content/common/accessibility_messages.h
@@ -21,8 +21,8 @@
#define IPC_MESSAGE_START AccessibilityMsgStart
-IPC_ENUM_TRAITS(WebKit::WebAXEvent)
-IPC_ENUM_TRAITS(WebKit::WebAXRole)
+IPC_ENUM_TRAITS(blink::WebAXEvent)
+IPC_ENUM_TRAITS(blink::WebAXRole)
IPC_ENUM_TRAITS(content::AccessibilityNodeData::BoolAttribute)
IPC_ENUM_TRAITS(content::AccessibilityNodeData::FloatAttribute)
@@ -50,7 +50,7 @@ IPC_STRUCT_BEGIN(AccessibilityHostMsg_EventParams)
IPC_STRUCT_MEMBER(std::vector<content::AccessibilityNodeData>, nodes)
// Type of event.
- IPC_STRUCT_MEMBER(WebKit::WebAXEvent, event_type)
+ IPC_STRUCT_MEMBER(blink::WebAXEvent, event_type)
// ID of the node that the event applies to.
IPC_STRUCT_MEMBER(int, id)
diff --git a/chromium/content/common/accessibility_node_data.cc b/chromium/content/common/accessibility_node_data.cc
index 8f244df4251..29a83f1016a 100644
--- a/chromium/content/common/accessibility_node_data.cc
+++ b/chromium/content/common/accessibility_node_data.cc
@@ -34,7 +34,7 @@ namespace content {
AccessibilityNodeData::AccessibilityNodeData()
: id(-1),
- role(WebKit::WebAXRoleUnknown),
+ role(blink::WebAXRoleUnknown),
state(-1) {
}
@@ -70,6 +70,10 @@ void AccessibilityNodeData::SetName(std::string name) {
string_attributes.push_back(std::make_pair(ATTR_NAME, name));
}
+void AccessibilityNodeData::SetValue(std::string value) {
+ string_attributes.push_back(std::make_pair(ATTR_VALUE, value));
+}
+
AccessibilityNodeDataTreeNode::AccessibilityNodeDataTreeNode()
: AccessibilityNodeData() {
}
@@ -138,160 +142,161 @@ std::string AccessibilityNodeData::DebugString(bool recursive) const {
result += "id=" + IntToString(id);
switch (role) {
- case WebKit::WebAXRoleAlert: result += " ALERT"; break;
- case WebKit::WebAXRoleAlertDialog: result += " ALERT_DIALOG"; break;
- case WebKit::WebAXRoleAnnotation: result += " ANNOTATION"; break;
- case WebKit::WebAXRoleApplication: result += " APPLICATION"; break;
- case WebKit::WebAXRoleArticle: result += " ARTICLE"; break;
- case WebKit::WebAXRoleBanner: result += " L_BANNER"; break;
- case WebKit::WebAXRoleBrowser: result += " BROWSER"; break;
- case WebKit::WebAXRoleBusyIndicator: result += " BUSY_INDICATOR"; break;
- case WebKit::WebAXRoleButton: result += " BUTTON"; break;
- case WebKit::WebAXRoleCanvas: result += " CANVAS"; break;
- case WebKit::WebAXRoleCell: result += " CELL"; break;
- case WebKit::WebAXRoleCheckBox: result += " CHECKBOX"; break;
- case WebKit::WebAXRoleColorWell: result += " COLOR_WELL"; break;
- case WebKit::WebAXRoleColumn: result += " COLUMN"; break;
- case WebKit::WebAXRoleColumnHeader: result += " COLUMN_HEADER"; break;
- case WebKit::WebAXRoleComboBox: result += " COMBO_BOX"; break;
- case WebKit::WebAXRoleComplementary: result += " L_COMPLEMENTARY"; break;
- case WebKit::WebAXRoleContentInfo: result += " L_CONTENTINFO"; break;
- case WebKit::WebAXRoleDefinition: result += " DEFINITION"; break;
- case WebKit::WebAXRoleDescriptionListDetail: result += " DD"; break;
- case WebKit::WebAXRoleDescriptionListTerm: result += " DT"; break;
- case WebKit::WebAXRoleDialog: result += " DIALOG"; break;
- case WebKit::WebAXRoleDirectory: result += " DIRECTORY"; break;
- case WebKit::WebAXRoleDisclosureTriangle:
+ case blink::WebAXRoleAlert: result += " ALERT"; break;
+ case blink::WebAXRoleAlertDialog: result += " ALERT_DIALOG"; break;
+ case blink::WebAXRoleAnnotation: result += " ANNOTATION"; break;
+ case blink::WebAXRoleApplication: result += " APPLICATION"; break;
+ case blink::WebAXRoleArticle: result += " ARTICLE"; break;
+ case blink::WebAXRoleBanner: result += " L_BANNER"; break;
+ case blink::WebAXRoleBrowser: result += " BROWSER"; break;
+ case blink::WebAXRoleBusyIndicator: result += " BUSY_INDICATOR"; break;
+ case blink::WebAXRoleButton: result += " BUTTON"; break;
+ case blink::WebAXRoleCanvas: result += " CANVAS"; break;
+ case blink::WebAXRoleCell: result += " CELL"; break;
+ case blink::WebAXRoleCheckBox: result += " CHECKBOX"; break;
+ case blink::WebAXRoleColorWell: result += " COLOR_WELL"; break;
+ case blink::WebAXRoleColumn: result += " COLUMN"; break;
+ case blink::WebAXRoleColumnHeader: result += " COLUMN_HEADER"; break;
+ case blink::WebAXRoleComboBox: result += " COMBO_BOX"; break;
+ case blink::WebAXRoleComplementary: result += " L_COMPLEMENTARY"; break;
+ case blink::WebAXRoleContentInfo: result += " L_CONTENTINFO"; break;
+ case blink::WebAXRoleDefinition: result += " DEFINITION"; break;
+ case blink::WebAXRoleDescriptionListDetail: result += " DD"; break;
+ case blink::WebAXRoleDescriptionListTerm: result += " DT"; break;
+ case blink::WebAXRoleDialog: result += " DIALOG"; break;
+ case blink::WebAXRoleDirectory: result += " DIRECTORY"; break;
+ case blink::WebAXRoleDisclosureTriangle:
result += " DISCLOSURE_TRIANGLE"; break;
- case WebKit::WebAXRoleDiv: result += " DIV"; break;
- case WebKit::WebAXRoleDocument: result += " DOCUMENT"; break;
- case WebKit::WebAXRoleDrawer: result += " DRAWER"; break;
- case WebKit::WebAXRoleEditableText: result += " EDITABLE_TEXT"; break;
- case WebKit::WebAXRoleFooter: result += " FOOTER"; break;
- case WebKit::WebAXRoleForm: result += " FORM"; break;
- case WebKit::WebAXRoleGrid: result += " GRID"; break;
- case WebKit::WebAXRoleGroup: result += " GROUP"; break;
- case WebKit::WebAXRoleGrowArea: result += " GROW_AREA"; break;
- case WebKit::WebAXRoleHeading: result += " HEADING"; break;
- case WebKit::WebAXRoleHelpTag: result += " HELP_TAG"; break;
- case WebKit::WebAXRoleHorizontalRule: result += " HORIZONTAL_RULE"; break;
- case WebKit::WebAXRoleIgnored: result += " IGNORED"; break;
- case WebKit::WebAXRoleImage: result += " IMAGE"; break;
- case WebKit::WebAXRoleImageMap: result += " IMAGE_MAP"; break;
- case WebKit::WebAXRoleImageMapLink: result += " IMAGE_MAP_LINK"; break;
- case WebKit::WebAXRoleIncrementor: result += " INCREMENTOR"; break;
- case WebKit::WebAXRoleLabel: result += " LABEL"; break;
- case WebKit::WebAXRoleLink: result += " LINK"; break;
- case WebKit::WebAXRoleList: result += " LIST"; break;
- case WebKit::WebAXRoleListBox: result += " LISTBOX"; break;
- case WebKit::WebAXRoleListBoxOption: result += " LISTBOX_OPTION"; break;
- case WebKit::WebAXRoleListItem: result += " LIST_ITEM"; break;
- case WebKit::WebAXRoleListMarker: result += " LIST_MARKER"; break;
- case WebKit::WebAXRoleLog: result += " LOG"; break;
- case WebKit::WebAXRoleMain: result += " L_MAIN"; break;
- case WebKit::WebAXRoleMarquee: result += " MARQUEE"; break;
- case WebKit::WebAXRoleMath: result += " MATH"; break;
- case WebKit::WebAXRoleMatte: result += " MATTE"; break;
- case WebKit::WebAXRoleMenu: result += " MENU"; break;
- case WebKit::WebAXRoleMenuBar: result += " MENU_BAR"; break;
- case WebKit::WebAXRoleMenuButton: result += " MENU_BUTTON"; break;
- case WebKit::WebAXRoleMenuItem: result += " MENU_ITEM"; break;
- case WebKit::WebAXRoleMenuListOption: result += " MENU_LIST_OPTION"; break;
- case WebKit::WebAXRoleMenuListPopup: result += " MENU_LIST_POPUP"; break;
- case WebKit::WebAXRoleNavigation: result += " L_NAVIGATION"; break;
- case WebKit::WebAXRoleNote: result += " NOTE"; break;
- case WebKit::WebAXRoleOutline: result += " OUTLINE"; break;
- case WebKit::WebAXRoleParagraph: result += " PARAGRAPH"; break;
- case WebKit::WebAXRolePopUpButton: result += " POPUP_BUTTON"; break;
- case WebKit::WebAXRolePresentational: result += " PRESENTATIONAL"; break;
- case WebKit::WebAXRoleProgressIndicator:
+ case blink::WebAXRoleDiv: result += " DIV"; break;
+ case blink::WebAXRoleDocument: result += " DOCUMENT"; break;
+ case blink::WebAXRoleDrawer: result += " DRAWER"; break;
+ case blink::WebAXRoleEditableText: result += " EDITABLE_TEXT"; break;
+ case blink::WebAXRoleFooter: result += " FOOTER"; break;
+ case blink::WebAXRoleForm: result += " FORM"; break;
+ case blink::WebAXRoleGrid: result += " GRID"; break;
+ case blink::WebAXRoleGroup: result += " GROUP"; break;
+ case blink::WebAXRoleGrowArea: result += " GROW_AREA"; break;
+ case blink::WebAXRoleHeading: result += " HEADING"; break;
+ case blink::WebAXRoleHelpTag: result += " HELP_TAG"; break;
+ case blink::WebAXRoleHorizontalRule: result += " HORIZONTAL_RULE"; break;
+ case blink::WebAXRoleIgnored: result += " IGNORED"; break;
+ case blink::WebAXRoleImage: result += " IMAGE"; break;
+ case blink::WebAXRoleImageMap: result += " IMAGE_MAP"; break;
+ case blink::WebAXRoleImageMapLink: result += " IMAGE_MAP_LINK"; break;
+ case blink::WebAXRoleIncrementor: result += " INCREMENTOR"; break;
+ case blink::WebAXRoleInlineTextBox: result += " INLINE_TEXT_BOX"; break;
+ case blink::WebAXRoleLabel: result += " LABEL"; break;
+ case blink::WebAXRoleLink: result += " LINK"; break;
+ case blink::WebAXRoleList: result += " LIST"; break;
+ case blink::WebAXRoleListBox: result += " LISTBOX"; break;
+ case blink::WebAXRoleListBoxOption: result += " LISTBOX_OPTION"; break;
+ case blink::WebAXRoleListItem: result += " LIST_ITEM"; break;
+ case blink::WebAXRoleListMarker: result += " LIST_MARKER"; break;
+ case blink::WebAXRoleLog: result += " LOG"; break;
+ case blink::WebAXRoleMain: result += " L_MAIN"; break;
+ case blink::WebAXRoleMarquee: result += " MARQUEE"; break;
+ case blink::WebAXRoleMath: result += " MATH"; break;
+ case blink::WebAXRoleMatte: result += " MATTE"; break;
+ case blink::WebAXRoleMenu: result += " MENU"; break;
+ case blink::WebAXRoleMenuBar: result += " MENU_BAR"; break;
+ case blink::WebAXRoleMenuButton: result += " MENU_BUTTON"; break;
+ case blink::WebAXRoleMenuItem: result += " MENU_ITEM"; break;
+ case blink::WebAXRoleMenuListOption: result += " MENU_LIST_OPTION"; break;
+ case blink::WebAXRoleMenuListPopup: result += " MENU_LIST_POPUP"; break;
+ case blink::WebAXRoleNavigation: result += " L_NAVIGATION"; break;
+ case blink::WebAXRoleNote: result += " NOTE"; break;
+ case blink::WebAXRoleOutline: result += " OUTLINE"; break;
+ case blink::WebAXRoleParagraph: result += " PARAGRAPH"; break;
+ case blink::WebAXRolePopUpButton: result += " POPUP_BUTTON"; break;
+ case blink::WebAXRolePresentational: result += " PRESENTATIONAL"; break;
+ case blink::WebAXRoleProgressIndicator:
result += " PROGRESS_INDICATOR"; break;
- case WebKit::WebAXRoleRadioButton: result += " RADIO_BUTTON"; break;
- case WebKit::WebAXRoleRadioGroup: result += " RADIO_GROUP"; break;
- case WebKit::WebAXRoleRegion: result += " REGION"; break;
- case WebKit::WebAXRoleRootWebArea: result += " ROOT_WEB_AREA"; break;
- case WebKit::WebAXRoleRow: result += " ROW"; break;
- case WebKit::WebAXRoleRowHeader: result += " ROW_HEADER"; break;
- case WebKit::WebAXRoleRuler: result += " RULER"; break;
- case WebKit::WebAXRoleRulerMarker: result += " RULER_MARKER"; break;
- case WebKit::WebAXRoleSVGRoot: result += " SVG_ROOT"; break;
- case WebKit::WebAXRoleScrollArea: result += " SCROLLAREA"; break;
- case WebKit::WebAXRoleScrollBar: result += " SCROLLBAR"; break;
- case WebKit::WebAXRoleSearch: result += " L_SEARCH"; break;
- case WebKit::WebAXRoleSheet: result += " SHEET"; break;
- case WebKit::WebAXRoleSlider: result += " SLIDER"; break;
- case WebKit::WebAXRoleSliderThumb: result += " SLIDER_THUMB"; break;
- case WebKit::WebAXRoleSpinButton: result += " SPIN_BUTTON"; break;
- case WebKit::WebAXRoleSpinButtonPart: result += " SPIN_BUTTON_PART"; break;
- case WebKit::WebAXRoleSplitGroup: result += " SPLIT_GROUP"; break;
- case WebKit::WebAXRoleSplitter: result += " SPLITTER"; break;
- case WebKit::WebAXRoleStaticText: result += " STATIC_TEXT"; break;
- case WebKit::WebAXRoleStatus: result += " STATUS"; break;
- case WebKit::WebAXRoleSystemWide: result += " SYSTEM_WIDE"; break;
- case WebKit::WebAXRoleTab: result += " TAB"; break;
- case WebKit::WebAXRoleTabList: result += " TAB_LIST"; break;
- case WebKit::WebAXRoleTabPanel: result += " TAB_PANEL"; break;
- case WebKit::WebAXRoleTable: result += " TABLE"; break;
- case WebKit::WebAXRoleTableHeaderContainer:
+ case blink::WebAXRoleRadioButton: result += " RADIO_BUTTON"; break;
+ case blink::WebAXRoleRadioGroup: result += " RADIO_GROUP"; break;
+ case blink::WebAXRoleRegion: result += " REGION"; break;
+ case blink::WebAXRoleRootWebArea: result += " ROOT_WEB_AREA"; break;
+ case blink::WebAXRoleRow: result += " ROW"; break;
+ case blink::WebAXRoleRowHeader: result += " ROW_HEADER"; break;
+ case blink::WebAXRoleRuler: result += " RULER"; break;
+ case blink::WebAXRoleRulerMarker: result += " RULER_MARKER"; break;
+ case blink::WebAXRoleSVGRoot: result += " SVG_ROOT"; break;
+ case blink::WebAXRoleScrollArea: result += " SCROLLAREA"; break;
+ case blink::WebAXRoleScrollBar: result += " SCROLLBAR"; break;
+ case blink::WebAXRoleSearch: result += " L_SEARCH"; break;
+ case blink::WebAXRoleSheet: result += " SHEET"; break;
+ case blink::WebAXRoleSlider: result += " SLIDER"; break;
+ case blink::WebAXRoleSliderThumb: result += " SLIDER_THUMB"; break;
+ case blink::WebAXRoleSpinButton: result += " SPIN_BUTTON"; break;
+ case blink::WebAXRoleSpinButtonPart: result += " SPIN_BUTTON_PART"; break;
+ case blink::WebAXRoleSplitGroup: result += " SPLIT_GROUP"; break;
+ case blink::WebAXRoleSplitter: result += " SPLITTER"; break;
+ case blink::WebAXRoleStaticText: result += " STATIC_TEXT"; break;
+ case blink::WebAXRoleStatus: result += " STATUS"; break;
+ case blink::WebAXRoleSystemWide: result += " SYSTEM_WIDE"; break;
+ case blink::WebAXRoleTab: result += " TAB"; break;
+ case blink::WebAXRoleTabList: result += " TAB_LIST"; break;
+ case blink::WebAXRoleTabPanel: result += " TAB_PANEL"; break;
+ case blink::WebAXRoleTable: result += " TABLE"; break;
+ case blink::WebAXRoleTableHeaderContainer:
result += " TABLE_HDR_CONTAINER"; break;
- case WebKit::WebAXRoleTextArea: result += " TEXTAREA"; break;
- case WebKit::WebAXRoleTextField: result += " TEXT_FIELD"; break;
- case WebKit::WebAXRoleTimer: result += " TIMER"; break;
- case WebKit::WebAXRoleToggleButton: result += " TOGGLE_BUTTON"; break;
- case WebKit::WebAXRoleToolbar: result += " TOOLBAR"; break;
- case WebKit::WebAXRoleTree: result += " TREE"; break;
- case WebKit::WebAXRoleTreeGrid: result += " TREE_GRID"; break;
- case WebKit::WebAXRoleTreeItem: result += " TREE_ITEM"; break;
- case WebKit::WebAXRoleUnknown: result += " UNKNOWN"; break;
- case WebKit::WebAXRoleUserInterfaceTooltip: result += " TOOLTIP"; break;
- case WebKit::WebAXRoleValueIndicator: result += " VALUE_INDICATOR"; break;
- case WebKit::WebAXRoleWebArea: result += " WEB_AREA"; break;
- case WebKit::WebAXRoleWindow: result += " WINDOW"; break;
+ case blink::WebAXRoleTextArea: result += " TEXTAREA"; break;
+ case blink::WebAXRoleTextField: result += " TEXT_FIELD"; break;
+ case blink::WebAXRoleTimer: result += " TIMER"; break;
+ case blink::WebAXRoleToggleButton: result += " TOGGLE_BUTTON"; break;
+ case blink::WebAXRoleToolbar: result += " TOOLBAR"; break;
+ case blink::WebAXRoleTree: result += " TREE"; break;
+ case blink::WebAXRoleTreeGrid: result += " TREE_GRID"; break;
+ case blink::WebAXRoleTreeItem: result += " TREE_ITEM"; break;
+ case blink::WebAXRoleUnknown: result += " UNKNOWN"; break;
+ case blink::WebAXRoleUserInterfaceTooltip: result += " TOOLTIP"; break;
+ case blink::WebAXRoleValueIndicator: result += " VALUE_INDICATOR"; break;
+ case blink::WebAXRoleWebArea: result += " WEB_AREA"; break;
+ case blink::WebAXRoleWindow: result += " WINDOW"; break;
default:
assert(false);
}
- if (state & (1 << WebKit::WebAXStateBusy))
+ if (state & (1 << blink::WebAXStateBusy))
result += " BUSY";
- if (state & (1 << WebKit::WebAXStateChecked))
+ if (state & (1 << blink::WebAXStateChecked))
result += " CHECKED";
- if (state & (1 << WebKit::WebAXStateCollapsed))
+ if (state & (1 << blink::WebAXStateCollapsed))
result += " COLLAPSED";
- if (state & (1 << WebKit::WebAXStateExpanded))
+ if (state & (1 << blink::WebAXStateExpanded))
result += " EXPANDED";
- if (state & (1 << WebKit::WebAXStateFocusable))
+ if (state & (1 << blink::WebAXStateFocusable))
result += " FOCUSABLE";
- if (state & (1 << WebKit::WebAXStateFocused))
+ if (state & (1 << blink::WebAXStateFocused))
result += " FOCUSED";
- if (state & (1 << WebKit::WebAXStateHaspopup))
+ if (state & (1 << blink::WebAXStateHaspopup))
result += " HASPOPUP";
- if (state & (1 << WebKit::WebAXStateHovered))
+ if (state & (1 << blink::WebAXStateHovered))
result += " HOTTRACKED";
- if (state & (1 << WebKit::WebAXStateIndeterminate))
+ if (state & (1 << blink::WebAXStateIndeterminate))
result += " INDETERMINATE";
- if (state & (1 << WebKit::WebAXStateInvisible))
+ if (state & (1 << blink::WebAXStateInvisible))
result += " INVISIBLE";
- if (state & (1 << WebKit::WebAXStateLinked))
+ if (state & (1 << blink::WebAXStateLinked))
result += " LINKED";
- if (state & (1 << WebKit::WebAXStateMultiselectable))
+ if (state & (1 << blink::WebAXStateMultiselectable))
result += " MULTISELECTABLE";
- if (state & (1 << WebKit::WebAXStateOffscreen))
+ if (state & (1 << blink::WebAXStateOffscreen))
result += " OFFSCREEN";
- if (state & (1 << WebKit::WebAXStatePressed))
+ if (state & (1 << blink::WebAXStatePressed))
result += " PRESSED";
- if (state & (1 << WebKit::WebAXStateProtected))
+ if (state & (1 << blink::WebAXStateProtected))
result += " PROTECTED";
- if (state & (1 << WebKit::WebAXStateReadonly))
+ if (state & (1 << blink::WebAXStateReadonly))
result += " READONLY";
- if (state & (1 << WebKit::WebAXStateRequired))
+ if (state & (1 << blink::WebAXStateRequired))
result += " REQUIRED";
- if (state & (1 << WebKit::WebAXStateSelectable))
+ if (state & (1 << blink::WebAXStateSelectable))
result += " SELECTABLE";
- if (state & (1 << WebKit::WebAXStateSelected))
+ if (state & (1 << blink::WebAXStateSelected))
result += " SELECTED";
- if (state & (1 << WebKit::WebAXStateVertical))
+ if (state & (1 << blink::WebAXStateVertical))
result += " VERTICAL";
- if (state & (1 << WebKit::WebAXStateVisited))
+ if (state & (1 << blink::WebAXStateVisited))
result += " VISITED";
result += " (" + IntToString(location.x()) + ", " +
@@ -374,6 +379,23 @@ std::string AccessibilityNodeData::DebugString(bool recursive) const {
case ATTR_COLOR_VALUE_BLUE:
result += " color_value_blue=" + value;
break;
+ case ATTR_TEXT_DIRECTION:
+ switch (int_attributes[i].second) {
+ case blink::WebAXTextDirectionLR:
+ default:
+ result += " text_direction=lr";
+ break;
+ case blink::WebAXTextDirectionRL:
+ result += " text_direction=rl";
+ break;
+ case blink::WebAXTextDirectionTB:
+ result += " text_direction=tb";
+ break;
+ case blink::WebAXTextDirectionBT:
+ result += " text_direction=bt";
+ break;
+ }
+ break;
}
}
@@ -509,6 +531,15 @@ std::string AccessibilityNodeData::DebugString(bool recursive) const {
case ATTR_UNIQUE_CELL_IDS:
result += " unique_cell_ids=" + IntVectorToString(values);
break;
+ case ATTR_CHARACTER_OFFSETS:
+ result += " character_offsets=" + IntVectorToString(values);
+ break;
+ case ATTR_WORD_STARTS:
+ result += " word_starts=" + IntVectorToString(values);
+ break;
+ case ATTR_WORD_ENDS:
+ result += " word_ends=" + IntVectorToString(values);
+ break;
}
}
diff --git a/chromium/content/common/accessibility_node_data.h b/chromium/content/common/accessibility_node_data.h
index 34e93479c6a..ed39508bb2d 100644
--- a/chromium/content/common/accessibility_node_data.h
+++ b/chromium/content/common/accessibility_node_data.h
@@ -85,10 +85,13 @@ struct CONTENT_EXPORT AccessibilityNodeData {
// Relationships between this element and other elements.
ATTR_TITLE_UI_ELEMENT,
- // Color value for WebKit::WebAXRoleColorWell, each component is 0..255
+ // Color value for blink::WebAXRoleColorWell, each component is 0..255
ATTR_COLOR_VALUE_RED,
ATTR_COLOR_VALUE_GREEN,
- ATTR_COLOR_VALUE_BLUE
+ ATTR_COLOR_VALUE_BLUE,
+
+ // Inline text attributes.
+ ATTR_TEXT_DIRECTION
};
enum FloatAttribute {
@@ -145,7 +148,20 @@ struct CONTENT_EXPORT AccessibilityNodeData {
// For a table, the unique cell ids in row-major order of their first
// occurrence.
- ATTR_UNIQUE_CELL_IDS
+ ATTR_UNIQUE_CELL_IDS,
+
+ // For inline text. This is the pixel position of the end of this
+ // character within the bounding rectangle of this object, in the
+ // direction given by ATTR_TEXT_DIRECTION. For example, for left-to-right
+ // text, the first offset is the right coordinate of the first character
+ // within the object's bounds, the second offset is the right coordinate
+ // of the second character, and so on.
+ ATTR_CHARACTER_OFFSETS,
+
+ // For inline text. These int lists must be the same size; they represent
+ // the start and end character index of each word within this text.
+ ATTR_WORD_STARTS,
+ ATTR_WORD_ENDS,
};
AccessibilityNodeData();
@@ -159,9 +175,11 @@ struct CONTENT_EXPORT AccessibilityNodeData {
void AddIntListAttribute(IntListAttribute attribute,
const std::vector<int32>& value);
- // Convenience function, mainly for writing unit tests.
+ // Convenience functions, mainly for writing unit tests.
// Equivalent to AddStringAttribute(ATTR_NAME, name).
void SetName(std::string name);
+ // Equivalent to AddStringAttribute(ATTR_VALUE, value).
+ void SetValue(std::string value);
#ifndef NDEBUG
virtual std::string DebugString(bool recursive) const;
@@ -170,7 +188,7 @@ struct CONTENT_EXPORT AccessibilityNodeData {
// This is a simple serializable struct. All member variables should be
// public and copyable.
int32 id;
- WebKit::WebAXRole role;
+ blink::WebAXRole role;
uint32 state;
gfx::Rect location;
std::vector<std::pair<StringAttribute, std::string> > string_attributes;
diff --git a/chromium/content/common/android/OWNERS b/chromium/content/common/android/OWNERS
index 7b7df6dc836..29d0acf8c4e 100644
--- a/chromium/content/common/android/OWNERS
+++ b/chromium/content/common/android/OWNERS
@@ -1,4 +1,3 @@
bulach@chromium.org
-joth@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
diff --git a/chromium/content/common/android/address_parser.cc b/chromium/content/common/android/address_parser.cc
index ea1aa476887..15874fd38ee 100644
--- a/chromium/content/common/android/address_parser.cc
+++ b/chromium/content/common/android/address_parser.cc
@@ -48,7 +48,7 @@ namespace address_parser {
using namespace internal;
-bool FindAddress(const string16& text, string16* address) {
+bool FindAddress(const base::string16& text, base::string16* address) {
size_t start, end;
if (FindAddress(text.begin(), text.end(), &start, &end)) {
address->assign(text.substr(start, end));
@@ -57,8 +57,8 @@ bool FindAddress(const string16& text, string16* address) {
return false;
}
-bool FindAddress(const string16::const_iterator& begin,
- const string16::const_iterator& end,
+bool FindAddress(const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end,
size_t* start_pos,
size_t* end_pos) {
HouseNumberParser house_number_parser;
@@ -69,9 +69,9 @@ bool FindAddress(const string16::const_iterator& begin,
// by a valid zip code for that state. Also keep a look for any other
// possible house numbers to continue from in case of no match and for
// state names not followed by a zip code (e.g. New York, NY 10000).
- const string16 newline_delimiters = kNewlineDelimiters;
- const string16 delimiters = kWhitespaceUTF16 + newline_delimiters;
- for (string16::const_iterator it = begin; it != end; ) {
+ const base::string16 newline_delimiters = kNewlineDelimiters;
+ const base::string16 delimiters = base::kWhitespaceUTF16 + newline_delimiters;
+ for (base::string16::const_iterator it = begin; it != end; ) {
Word house_number;
if (!house_number_parser.Parse(it, end, &house_number))
return false;
@@ -100,7 +100,7 @@ bool FindAddress(const string16::const_iterator& begin,
// Check the number of address lines.
if (tokenizer.token_is_delim() && newline_delimiters.find(
- *tokenizer.token_begin()) != string16::npos) {
+ *tokenizer.token_begin()) != base::string16::npos) {
++num_lines;
}
} while (tokenizer.token_is_delim());
diff --git a/chromium/content/common/android/address_parser.h b/chromium/content/common/android/address_parser.h
index 71a3aba77d4..1a12a32c14d 100644
--- a/chromium/content/common/android/address_parser.h
+++ b/chromium/content/common/android/address_parser.h
@@ -17,14 +17,14 @@ namespace address_parser {
// Find the first address in some chunk of text. If an address is found in
// |text| true is returned and the address is copied into |address|.
// Otherwise, false is returned.
-bool FindAddress(const string16& text, string16* address);
+bool FindAddress(const base::string16& text, base::string16* address);
// Find the first address in some chunk of test. |begin| is the starting
// position to search from, |end| is the position to search to. |start_pos|
// and |end_pos| are set to the starting and ending position of the address,
// if found.
-CONTENT_EXPORT bool FindAddress(const string16::const_iterator& begin,
- const string16::const_iterator& end,
+CONTENT_EXPORT bool FindAddress(const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end,
size_t* start_pos,
size_t* end_pos);
diff --git a/chromium/content/common/android/address_parser_internal.cc b/chromium/content/common/android/address_parser_internal.cc
index 0970b1775a8..fe14d3b53b5 100644
--- a/chromium/content/common/android/address_parser_internal.cc
+++ b/chromium/content/common/android/address_parser_internal.cc
@@ -20,23 +20,23 @@ const size_t kZipPlus4Digits = 9;
// Maximum number of digits of a house number, including possible hyphens.
const size_t kMaxHouseDigits = 5;
-char16 SafePreviousChar(const string16::const_iterator& it,
- const string16::const_iterator& begin) {
+char16 SafePreviousChar(const base::string16::const_iterator& it,
+ const base::string16::const_iterator& begin) {
if (it == begin)
return ' ';
return *(it - 1);
}
-char16 SafeNextChar(const string16::const_iterator& it,
- const string16::const_iterator& end) {
+char16 SafeNextChar(const base::string16::const_iterator& it,
+ const base::string16::const_iterator& end) {
if (it == end)
return ' ';
return *(it + 1);
}
-bool WordLowerCaseEqualsASCII(string16::const_iterator word_begin,
- string16::const_iterator word_end, const char* ascii_to_match) {
- for (string16::const_iterator it = word_begin; it != word_end;
+bool WordLowerCaseEqualsASCII(base::string16::const_iterator word_begin,
+ base::string16::const_iterator word_end, const char* ascii_to_match) {
+ for (base::string16::const_iterator it = word_begin; it != word_end;
++it, ++ascii_to_match) {
if (!*ascii_to_match || base::ToLowerASCII(*it) != *ascii_to_match)
return false;
@@ -44,10 +44,10 @@ bool WordLowerCaseEqualsASCII(string16::const_iterator word_begin,
return *ascii_to_match == 0 || *ascii_to_match == ' ';
}
-bool LowerCaseEqualsASCIIWithPlural(string16::const_iterator word_begin,
- string16::const_iterator word_end, const char* ascii_to_match,
+bool LowerCaseEqualsASCIIWithPlural(base::string16::const_iterator word_begin,
+ base::string16::const_iterator word_end, const char* ascii_to_match,
bool allow_plural) {
- for (string16::const_iterator it = word_begin; it != word_end;
+ for (base::string16::const_iterator it = word_begin; it != word_end;
++it, ++ascii_to_match) {
if (!*ascii_to_match && allow_plural && *it == 's' && it + 1 == word_end)
return true;
@@ -66,8 +66,8 @@ namespace address_parser {
namespace internal {
-Word::Word(const string16::const_iterator& begin,
- const string16::const_iterator& end)
+Word::Word(const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end)
: begin(begin),
end(end) {
DCHECK(begin <= end);
@@ -115,8 +115,8 @@ bool HouseNumberParser::CheckFinished(Word* word) const {
}
bool HouseNumberParser::Parse(
- const string16::const_iterator& begin,
- const string16::const_iterator& end, Word* word) {
+ const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end, Word* word) {
it_ = begin_ = begin;
end_ = end;
ResetState();
@@ -417,7 +417,7 @@ bool IsZipValid(const Word& word, size_t state_index) {
if (length != kZipDigits && length != kZipPlus4Digits + 1)
return false;
- for (string16::const_iterator it = word.begin; it != word.end; ++it) {
+ for (base::string16::const_iterator it = word.begin; it != word.end; ++it) {
size_t pos = it - word.begin;
if (IsAsciiDigit(*it) || (*it == '-' && pos == kZipDigits))
continue;
diff --git a/chromium/content/common/android/address_parser_internal.h b/chromium/content/common/android/address_parser_internal.h
index f236afc2d48..74af6c388d4 100644
--- a/chromium/content/common/android/address_parser_internal.h
+++ b/chromium/content/common/android/address_parser_internal.h
@@ -19,12 +19,12 @@ namespace internal {
// Exposed for tests.
struct CONTENT_EXPORT Word {
- string16::const_iterator begin;
- string16::const_iterator end;
+ base::string16::const_iterator begin;
+ base::string16::const_iterator end;
Word() {}
- Word(const string16::const_iterator& begin,
- const string16::const_iterator& end);
+ Word(const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end);
};
// Exposed for tests.
@@ -32,8 +32,8 @@ class CONTENT_EXPORT HouseNumberParser {
public:
HouseNumberParser() {}
- bool Parse(const string16::const_iterator& begin,
- const string16::const_iterator& end,
+ bool Parse(const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end,
Word* word);
private:
@@ -48,9 +48,9 @@ class CONTENT_EXPORT HouseNumberParser {
// Iterators to the beginning, current position and ending of the string
// being currently parsed.
- string16::const_iterator begin_;
- string16::const_iterator it_;
- string16::const_iterator end_;
+ base::string16::const_iterator begin_;
+ base::string16::const_iterator it_;
+ base::string16::const_iterator end_;
// Number of digits found in the current result candidate.
size_t num_digits_;
@@ -63,7 +63,7 @@ class CONTENT_EXPORT HouseNumberParser {
};
typedef std::vector<Word> WordList;
-typedef base::StringTokenizerT<string16, string16::const_iterator>
+typedef base::StringTokenizerT<base::string16, base::string16::const_iterator>
String16Tokenizer;
// These are exposed for tests.
diff --git a/chromium/content/common/android/address_parser_unittest.cc b/chromium/content/common/android/address_parser_unittest.cc
index c1f61f09a99..1a8d17eeff8 100644
--- a/chromium/content/common/android/address_parser_unittest.cc
+++ b/chromium/content/common/android/address_parser_unittest.cc
@@ -16,22 +16,22 @@ class AddressParserTest : public testing::Test {
public:
AddressParserTest() {}
- void TokenizeWords(const string16& content, WordList* words) const {
+ void TokenizeWords(const base::string16& content, WordList* words) const {
String16Tokenizer tokenizer(content.begin(), content.end(),
- kWhitespaceUTF16);
+ base::kWhitespaceUTF16);
while (tokenizer.GetNext()) {
words->push_back(Word(tokenizer.token_begin(), tokenizer.token_end()));
}
}
std::string GetHouseNumber(const std::string& content) const {
- string16 content_16 = UTF8ToUTF16(content);
- string16 result;
+ base::string16 content_16 = UTF8ToUTF16(content);
+ base::string16 result;
HouseNumberParser parser;
Word word;
if (parser.Parse(content_16.begin(), content_16.end(), &word))
- result = string16(word.begin, word.end);
+ result = base::string16(word.begin, word.end);
return UTF16ToUTF8(result);
}
@@ -40,9 +40,9 @@ class AddressParserTest : public testing::Test {
}
bool GetState(const std::string& state, size_t* state_index) const {
- string16 state_16 = UTF8ToUTF16(state);
+ base::string16 state_16 = UTF8ToUTF16(state);
String16Tokenizer tokenizer(state_16.begin(), state_16.end(),
- kWhitespaceUTF16);
+ base::kWhitespaceUTF16);
if (!tokenizer.GetNext())
return false;
@@ -62,7 +62,7 @@ class AddressParserTest : public testing::Test {
size_t state_index;
EXPECT_TRUE(GetState(state, &state_index));
- string16 zip_16 = UTF8ToUTF16(zip);
+ base::string16 zip_16 = UTF8ToUTF16(zip);
WordList words;
TokenizeWords(zip_16, &words);
EXPECT_TRUE(words.size() == 1);
@@ -70,7 +70,7 @@ class AddressParserTest : public testing::Test {
}
bool IsLocationName(const std::string& street) const {
- string16 street_16 = UTF8ToUTF16(street);
+ base::string16 street_16 = UTF8ToUTF16(street);
WordList words;
TokenizeWords(street_16, &words);
EXPECT_TRUE(words.size() == 1);
@@ -78,8 +78,8 @@ class AddressParserTest : public testing::Test {
}
std::string FindAddress(const std::string& content) const {
- string16 content_16 = UTF8ToUTF16(content);
- string16 result_16;
+ base::string16 content_16 = UTF8ToUTF16(content);
+ base::string16 result_16;
size_t start, end;
if (::FindAddress(content_16.begin(), content_16.end(), &start, &end))
result_16 = content_16.substr(start, end - start);
diff --git a/chromium/content/common/android/command_line.cc b/chromium/content/common/android/command_line.cc
deleted file mode 100644
index 8ac58c2bc5c..00000000000
--- a/chromium/content/common/android/command_line.cc
+++ /dev/null
@@ -1,79 +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/android/command_line.h"
-
-#include "base/android/jni_array.h"
-#include "base/android/jni_string.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "jni/CommandLine_jni.h"
-
-using base::android::AppendJavaStringArrayToStringVector;
-using base::android::ConvertJavaStringToUTF8;
-
-namespace {
-
-void AppendJavaStringArrayToCommandLine(JNIEnv* env,
- jobjectArray array,
- bool includes_program) {
- std::vector<std::string> vec;
- if (array)
- AppendJavaStringArrayToStringVector(env, array, &vec);
- if (!includes_program)
- vec.insert(vec.begin(), "");
- CommandLine extra_command_line(vec);
- CommandLine::ForCurrentProcess()->AppendArguments(extra_command_line,
- includes_program);
-}
-
-} // namespace
-
-static void Reset(JNIEnv* env, jclass clazz) {
- CommandLine::Reset();
-}
-
-static jboolean HasSwitch(JNIEnv* env, jclass clazz, jstring jswitch) {
- std::string switch_string(ConvertJavaStringToUTF8(env, jswitch));
- return CommandLine::ForCurrentProcess()->HasSwitch(switch_string);
-}
-
-static jstring GetSwitchValue(JNIEnv* env, jclass clazz, jstring jswitch) {
- std::string switch_string(ConvertJavaStringToUTF8(env, jswitch));
- std::string value(CommandLine::ForCurrentProcess()->GetSwitchValueNative(
- switch_string));
- if (value.empty())
- return 0;
- // OK to release, JNI binding.
- return base::android::ConvertUTF8ToJavaString(env, value).Release();
-}
-
-static void AppendSwitch(JNIEnv* env, jclass clazz, jstring jswitch) {
- std::string switch_string(ConvertJavaStringToUTF8(env, jswitch));
- CommandLine::ForCurrentProcess()->AppendSwitch(switch_string);
-}
-
-static void AppendSwitchWithValue(JNIEnv* env, jclass clazz,
- jstring jswitch, jstring jvalue) {
- std::string switch_string(ConvertJavaStringToUTF8(env, jswitch));
- std::string value_string (ConvertJavaStringToUTF8(env, jvalue));
- CommandLine::ForCurrentProcess()->AppendSwitchASCII(switch_string,
- value_string);
-}
-
-static void AppendSwitchesAndArguments(JNIEnv* env, jclass clazz,
- jobjectArray array) {
- AppendJavaStringArrayToCommandLine(env, array, false);
-}
-
-void InitNativeCommandLineFromJavaArray(JNIEnv* env, jobjectArray array) {
- // TODO(port): Make an overload of Init() that takes StringVector rather than
- // have to round-trip via AppendArguments.
- CommandLine::Init(0, NULL);
- AppendJavaStringArrayToCommandLine(env, array, true);
-}
-
-bool RegisterCommandLine(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
diff --git a/chromium/content/common/android/command_line.h b/chromium/content/common/android/command_line.h
deleted file mode 100644
index 3fe5efb3123..00000000000
--- a/chromium/content/common/android/command_line.h
+++ /dev/null
@@ -1,17 +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_ANDROID_COMMAND_LINE_H_
-#define CONTENT_COMMON_ANDROID_COMMAND_LINE_H_
-
-#include <jni.h>
-
-// Appends all strings in the given array as flags to the Chrome command line.
-void InitNativeCommandLineFromJavaArray(JNIEnv* env,
- jobjectArray init_command_line);
-
-// JNI registration boilerplate.
-bool RegisterCommandLine(JNIEnv* env);
-
-#endif // CONTENT_COMMON_ANDROID_COMMAND_LINE_H_
diff --git a/chromium/content/common/android/linker/DEPS b/chromium/content/common/android/linker/DEPS
new file mode 100644
index 00000000000..220b4c49e9b
--- /dev/null
+++ b/chromium/content/common/android/linker/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+ # This code cannot depend on anything from base/ or content/
+ "-base",
+ "-content",
+]
diff --git a/chromium/content/common/browser_plugin/OWNERS b/chromium/content/common/browser_plugin/OWNERS
index 3da5cc714c2..8028520cd54 100644
--- a/chromium/content/common/browser_plugin/OWNERS
+++ b/chromium/content/common/browser_plugin/OWNERS
@@ -7,6 +7,5 @@ per-file *_messages*.h=cdn@chromium.org
per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
per-file *_messages*.h=kenrb@chromium.org
diff --git a/chromium/content/common/browser_plugin/browser_plugin_constants.cc b/chromium/content/common/browser_plugin/browser_plugin_constants.cc
index 6da58e96c53..ea3925dfd0e 100644
--- a/chromium/content/common/browser_plugin/browser_plugin_constants.cc
+++ b/chromium/content/common/browser_plugin/browser_plugin_constants.cc
@@ -31,6 +31,7 @@ const char kEventInternalInstanceIDAllocated[] = "instanceid-allocated";
const char kEventInternalTrackedObjectGone[] = "trackedobjectgone";
// Attributes.
+const char kAttributeAllowTransparency[] = "allowtransparency";
const char kAttributeApi[] = "api";
const char kAttributeAutoSize[] = "autosize";
const char kAttributeContentWindow[] = "contentWindow";
@@ -42,9 +43,6 @@ const char kAttributeName[] = "name";
const char kAttributePartition[] = "partition";
const char kAttributeSrc[] = "src";
-// Events.
-const char kEventSizeChanged[] = "sizechanged";
-
// Parameters/properties on events.
const char kDefaultPromptText[] = "defaultPromptText";
const char kId[] = "id";
diff --git a/chromium/content/common/browser_plugin/browser_plugin_constants.h b/chromium/content/common/browser_plugin/browser_plugin_constants.h
index 8e911f04ef2..f870c48ff2b 100644
--- a/chromium/content/common/browser_plugin/browser_plugin_constants.h
+++ b/chromium/content/common/browser_plugin/browser_plugin_constants.h
@@ -31,6 +31,7 @@ extern const char kEventInternalInstanceIDAllocated[];
extern const char kEventInternalTrackedObjectGone[];
// Attributes.
+extern const char kAttributeAllowTransparency[];
extern const char kAttributeApi[];
extern const char kAttributeAutoSize[];
extern const char kAttributeContentWindow[];
diff --git a/chromium/content/common/browser_plugin/browser_plugin_messages.h b/chromium/content/common/browser_plugin/browser_plugin_messages.h
index b4345c628dd..c85b2299c95 100644
--- a/chromium/content/common/browser_plugin/browser_plugin_messages.h
+++ b/chromium/content/common/browser_plugin/browser_plugin_messages.h
@@ -21,11 +21,14 @@
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_message_utils.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
#include "third_party/WebKit/public/web/WebDragStatus.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
+#include "url/gurl.h"
#include "webkit/common/cursors/webcursor.h"
#undef IPC_MESSAGE_EXPORT
@@ -34,7 +37,7 @@
#define IPC_MESSAGE_START BrowserPluginMsgStart
-IPC_ENUM_TRAITS(WebKit::WebDragStatus)
+IPC_ENUM_TRAITS(blink::WebDragStatus)
IPC_STRUCT_BEGIN(BrowserPluginHostMsg_AutoSize_Params)
IPC_STRUCT_MEMBER(bool, enable)
@@ -67,8 +70,10 @@ IPC_STRUCT_BEGIN(BrowserPluginHostMsg_Attach_Params)
IPC_STRUCT_MEMBER(bool, persist_storage)
IPC_STRUCT_MEMBER(bool, focused)
IPC_STRUCT_MEMBER(bool, visible)
+ IPC_STRUCT_MEMBER(bool, opaque)
IPC_STRUCT_MEMBER(std::string, name)
IPC_STRUCT_MEMBER(std::string, src)
+ IPC_STRUCT_MEMBER(GURL, embedder_frame_url)
IPC_STRUCT_MEMBER(BrowserPluginHostMsg_AutoSize_Params, auto_size_params)
IPC_STRUCT_MEMBER(BrowserPluginHostMsg_ResizeGuest_Params,
resize_guest_params)
@@ -151,6 +156,30 @@ IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
int /* instance_id */,
std::vector<content::EditCommand> /* edit_commands */)
+// This message is sent from BrowserPlugin to BrowserPluginGuest whenever IME
+// composition state is updated.
+IPC_MESSAGE_ROUTED5(
+ BrowserPluginHostMsg_ImeSetComposition,
+ int /* instance_id */,
+ std::string /* text */,
+ std::vector<blink::WebCompositionUnderline> /* underlines */,
+ int /* selectiont_start */,
+ int /* selection_end */)
+
+// This message is sent from BrowserPlugin to BrowserPluginGuest to notify that
+// confirming the current composition is requested.
+IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_ImeConfirmComposition,
+ int /* instance_id */,
+ std::string /* text */,
+ bool /* keep selection */)
+
+// Deletes the current selection plus the specified number of characters before
+// and after the selection or caret.
+IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_ExtendSelectionAndDelete,
+ int /* instance_id */,
+ int /* before */,
+ int /* after */)
+
// This message is sent to the browser process to enable or disable autosize
// mode.
IPC_MESSAGE_ROUTED3(
@@ -209,6 +238,11 @@ IPC_MESSAGE_ROUTED5(BrowserPluginHostMsg_BuffersSwappedACK,
std::string /* mailbox_name */,
uint32 /* sync_point */)
+IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
+ int /* instance_id */,
+ int /* request_id */,
+ SkBitmap);
+
// Acknowledge that we presented an ubercomp frame.
IPC_MESSAGE_ROUTED5(BrowserPluginHostMsg_CompositorFrameACK,
int /* instance_id */,
@@ -217,6 +251,15 @@ IPC_MESSAGE_ROUTED5(BrowserPluginHostMsg_CompositorFrameACK,
int /* renderer_host_id */,
cc::CompositorFrameAck /* ack */)
+// Notify the guest renderer that some resources given to the embededer
+// are not used any more.
+IPC_MESSAGE_ROUTED5(BrowserPluginHostMsg_ReclaimCompositorResources,
+ int /* instance_id */,
+ int /* route_id */,
+ uint32 /* output_surface_id */,
+ int /* renderer_host_id */,
+ cc::CompositorFrameAck /* ack */)
+
// When a BrowserPlugin has been removed from the embedder's DOM, it informs
// the browser process to cleanup the guest.
IPC_MESSAGE_ROUTED1(BrowserPluginHostMsg_PluginDestroyed,
@@ -227,12 +270,17 @@ IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_SetVisibility,
int /* instance_id */,
bool /* visible */)
+// Tells the guest to change its background opacity.
+IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_SetContentsOpaque,
+ int /* instance_id */,
+ bool /* opaque */)
+
// Tells the guest that a drag event happened on the plugin.
IPC_MESSAGE_ROUTED5(BrowserPluginHostMsg_DragStatusUpdate,
int /* instance_id */,
- WebKit::WebDragStatus /* drag_status */,
+ blink::WebDragStatus /* drag_status */,
content::DropData /* drop_data */,
- WebKit::WebDragOperationsMask /* operation_mask */,
+ blink::WebDragOperationsMask /* operation_mask */,
gfx::Point /* plugin_location */)
// Response to BrowserPluginMsg_PluginAtPositionRequest, returns the browser
@@ -321,6 +369,12 @@ IPC_MESSAGE_CONTROL2(BrowserPluginMsg_UpdateRect,
int /* instance_id */,
BrowserPluginMsg_UpdateRect_Params)
+IPC_MESSAGE_CONTROL4(BrowserPluginMsg_CopyFromCompositingSurface,
+ int /* instance_id */,
+ int /* request_id */,
+ gfx::Rect /* source_rect */,
+ gfx::Size /* dest_size */)
+
// Requests the renderer to find out if a browser plugin is at position
// (|x|, |y|) within the embedder.
// The response message is BrowserPluginHostMsg_PluginAtPositionResponse.
@@ -353,4 +407,3 @@ IPC_MESSAGE_CONTROL5(BrowserPluginMsg_CompositorFrameSwapped,
IPC_MESSAGE_CONTROL2(BrowserPluginMsg_SetMouseLock,
int /* instance_id */,
bool /* enable */)
-
diff --git a/chromium/content/common/cc_messages.cc b/chromium/content/common/cc_messages.cc
index a122ed80095..b5718866e29 100644
--- a/chromium/content/common/cc_messages.cc
+++ b/chromium/content/common/cc_messages.cc
@@ -44,6 +44,9 @@ void ParamTraits<cc::FilterOperation>::Write(
WriteParam(m, p.amount());
WriteParam(m, p.zoom_inset());
break;
+ case cc::FilterOperation::REFERENCE:
+ WriteParam(m, p.image_filter());
+ break;
}
}
@@ -109,6 +112,16 @@ bool ParamTraits<cc::FilterOperation>::Read(
success = true;
}
break;
+ case cc::FilterOperation::REFERENCE: {
+ skia::RefPtr<SkImageFilter> filter;
+ if (!ReadParam(m, iter, &filter)) {
+ success = false;
+ break;
+ }
+ r->set_image_filter(filter);
+ success = true;
+ break;
+ }
}
return success;
}
@@ -151,6 +164,9 @@ void ParamTraits<cc::FilterOperation>::Log(
l->append(", ");
LogParam(p.zoom_inset(), l);
break;
+ case cc::FilterOperation::REFERENCE:
+ LogParam(p.image_filter(), l);
+ break;
}
l->append(")");
}
@@ -193,8 +209,9 @@ void ParamTraits<skia::RefPtr<SkImageFilter> >::Write(
Message* m, const param_type& p) {
SkImageFilter* filter = p.get();
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (filter && command_line.HasSwitch(switches::kAllowFiltersOverIPC)) {
- skia::RefPtr<SkData> data = skia::AdoptRef(SkSerializeFlattenable(filter));
+ if (filter && !command_line.HasSwitch(switches::kDisableFiltersOverIPC)) {
+ skia::RefPtr<SkData> data =
+ skia::AdoptRef(SkValidatingSerializeFlattenable(filter));
m->WriteData(static_cast<const char*>(data->data()), data->size());
} else {
m->WriteData(0, 0);
@@ -208,8 +225,10 @@ bool ParamTraits<skia::RefPtr<SkImageFilter> >::Read(
if (!m->ReadData(iter, &data, &length))
return false;
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if ((length > 0) && command_line.HasSwitch(switches::kAllowFiltersOverIPC)) {
- SkFlattenable* flattenable = SkDeserializeFlattenable(data, length);
+ if ((length > 0) &&
+ !command_line.HasSwitch(switches::kDisableFiltersOverIPC)) {
+ SkFlattenable* flattenable = SkValidatingDeserializeFlattenable(
+ data, length, SkImageFilter::GetFlattenableType());
*r = skia::AdoptRef(static_cast<SkImageFilter*>(flattenable));
} else {
r->clear();
@@ -226,106 +245,41 @@ void ParamTraits<skia::RefPtr<SkImageFilter> >::Log(
void ParamTraits<gfx::Transform>::Write(
Message* m, const param_type& p) {
- WriteParam(m, p.matrix().getDouble(0, 0));
- WriteParam(m, p.matrix().getDouble(1, 0));
- WriteParam(m, p.matrix().getDouble(2, 0));
- WriteParam(m, p.matrix().getDouble(3, 0));
- WriteParam(m, p.matrix().getDouble(0, 1));
- WriteParam(m, p.matrix().getDouble(1, 1));
- WriteParam(m, p.matrix().getDouble(2, 1));
- WriteParam(m, p.matrix().getDouble(3, 1));
- WriteParam(m, p.matrix().getDouble(0, 2));
- WriteParam(m, p.matrix().getDouble(1, 2));
- WriteParam(m, p.matrix().getDouble(2, 2));
- WriteParam(m, p.matrix().getDouble(3, 2));
- WriteParam(m, p.matrix().getDouble(0, 3));
- WriteParam(m, p.matrix().getDouble(1, 3));
- WriteParam(m, p.matrix().getDouble(2, 3));
- WriteParam(m, p.matrix().getDouble(3, 3));
+#ifdef SK_MSCALAR_IS_FLOAT
+ float column_major_data[16];
+ p.matrix().asColMajorf(column_major_data);
+#else
+ double column_major_data[16];
+ p.matrix().asColMajord(column_major_data);
+#endif
+ m->WriteBytes(&column_major_data, sizeof(SkMScalar) * 16);
}
bool ParamTraits<gfx::Transform>::Read(
const Message* m, PickleIterator* iter, param_type* r) {
- // Note: In this function, "m12" means 1st row, 2nd column of the matrix.
- // This is consistent with Skia's row-column notation, but backwards from
- // WebCore's column-row notation.
- double m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34,
- m41, m42, m43, m44;
-
- bool success =
- ReadParam(m, iter, &m11) &&
- ReadParam(m, iter, &m21) &&
- ReadParam(m, iter, &m31) &&
- ReadParam(m, iter, &m41) &&
- ReadParam(m, iter, &m12) &&
- ReadParam(m, iter, &m22) &&
- ReadParam(m, iter, &m32) &&
- ReadParam(m, iter, &m42) &&
- ReadParam(m, iter, &m13) &&
- ReadParam(m, iter, &m23) &&
- ReadParam(m, iter, &m33) &&
- ReadParam(m, iter, &m43) &&
- ReadParam(m, iter, &m14) &&
- ReadParam(m, iter, &m24) &&
- ReadParam(m, iter, &m34) &&
- ReadParam(m, iter, &m44);
-
- if (success) {
- r->matrix().setDouble(0, 0, m11);
- r->matrix().setDouble(1, 0, m21);
- r->matrix().setDouble(2, 0, m31);
- r->matrix().setDouble(3, 0, m41);
- r->matrix().setDouble(0, 1, m12);
- r->matrix().setDouble(1, 1, m22);
- r->matrix().setDouble(2, 1, m32);
- r->matrix().setDouble(3, 1, m42);
- r->matrix().setDouble(0, 2, m13);
- r->matrix().setDouble(1, 2, m23);
- r->matrix().setDouble(2, 2, m33);
- r->matrix().setDouble(3, 2, m43);
- r->matrix().setDouble(0, 3, m14);
- r->matrix().setDouble(1, 3, m24);
- r->matrix().setDouble(2, 3, m34);
- r->matrix().setDouble(3, 3, m44);
- }
-
- return success;
+ const char* column_major_data;
+ if (!m->ReadBytes(iter, &column_major_data, sizeof(SkMScalar) * 16))
+ return false;
+ r->matrix().setColMajor(
+ reinterpret_cast<const SkMScalar*>(column_major_data));
+ return true;
}
void ParamTraits<gfx::Transform>::Log(
const param_type& p, std::string* l) {
+#ifdef SK_MSCALAR_IS_FLOAT
+ float row_major_data[16];
+ p.matrix().asRowMajorf(row_major_data);
+#else
+ double row_major_data[16];
+ p.matrix().asRowMajord(row_major_data);
+#endif
l->append("(");
- LogParam(p.matrix().getDouble(0, 0), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(1, 0), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(2, 0), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(3, 0), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(0, 1), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(1, 1), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(2, 1), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(3, 1), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(0, 2), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(1, 2), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(2, 2), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(3, 2), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(0, 3), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(1, 3), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(2, 3), l);
- l->append(", ");
- LogParam(p.matrix().getDouble(3, 3), l);
+ for (int i = 0; i < 16; ++i) {
+ if (i > 0)
+ l->append(", ");
+ LogParam(row_major_data[i], l);
+ }
l->append(") ");
}
@@ -336,16 +290,20 @@ void ParamTraits<cc::RenderPass>::Write(
WriteParam(m, p.damage_rect);
WriteParam(m, p.transform_to_root_target);
WriteParam(m, p.has_transparent_background);
- WriteParam(m, p.has_occlusion_from_outside_target_surface);
WriteParam(m, p.shared_quad_state_list.size());
WriteParam(m, p.quad_list.size());
- for (size_t i = 0; i < p.shared_quad_state_list.size(); ++i)
- WriteParam(m, *p.shared_quad_state_list[i]);
-
size_t shared_quad_state_index = 0;
+ size_t last_shared_quad_state_index = kuint32max;
for (size_t i = 0; i < p.quad_list.size(); ++i) {
const cc::DrawQuad* quad = p.quad_list[i];
+ DCHECK(quad->rect.Contains(quad->visible_rect))
+ << quad->material << " rect: " << quad->rect.ToString()
+ << " visible_rect: " << quad->visible_rect.ToString();
+ DCHECK(quad->opaque_rect.IsEmpty() ||
+ quad->rect.Contains(quad->opaque_rect))
+ << quad->material << " rect: " << quad->rect.ToString()
+ << " opaque_rect: " << quad->opaque_rect.ToString();
switch (quad->material) {
case cc::DrawQuad::CHECKERBOARD:
@@ -407,11 +365,27 @@ void ParamTraits<cc::RenderPass>::Write(
continue;
}
- DCHECK_LT(shared_quad_state_index, p.shared_quad_state_list.size());
WriteParam(m, shared_quad_state_index);
+ if (shared_quad_state_index != last_shared_quad_state_index) {
+ WriteParam(m, *sqs_list[shared_quad_state_index]);
+ last_shared_quad_state_index = shared_quad_state_index;
+ }
}
}
+static size_t ReserveSizeForRenderPassWrite(const cc::RenderPass& p) {
+ size_t to_reserve = sizeof(cc::RenderPass);
+
+ to_reserve += p.shared_quad_state_list.size() * sizeof(cc::SharedQuadState);
+
+ // The shared_quad_state_index for each quad.
+ to_reserve += p.quad_list.size() * sizeof(size_t);
+
+ // The largest quad type, verified by a unit test.
+ to_reserve += p.quad_list.size() * sizeof(cc::RenderPassDrawQuad);
+ return to_reserve;
+}
+
template<typename QuadType>
static scoped_ptr<cc::DrawQuad> ReadDrawQuad(const Message* m,
PickleIterator* iter) {
@@ -428,7 +402,6 @@ bool ParamTraits<cc::RenderPass>::Read(
gfx::RectF damage_rect;
gfx::Transform transform_to_root_target;
bool has_transparent_background;
- bool has_occlusion_from_outside_target_surface;
size_t shared_quad_state_list_size;
size_t quad_list_size;
@@ -437,7 +410,6 @@ bool ParamTraits<cc::RenderPass>::Read(
!ReadParam(m, iter, &damage_rect) ||
!ReadParam(m, iter, &transform_to_root_target) ||
!ReadParam(m, iter, &has_transparent_background) ||
- !ReadParam(m, iter, &has_occlusion_from_outside_target_surface) ||
!ReadParam(m, iter, &shared_quad_state_list_size) ||
!ReadParam(m, iter, &quad_list_size))
return false;
@@ -446,17 +418,9 @@ bool ParamTraits<cc::RenderPass>::Read(
output_rect,
damage_rect,
transform_to_root_target,
- has_transparent_background,
- has_occlusion_from_outside_target_surface);
-
- for (size_t i = 0; i < shared_quad_state_list_size; ++i) {
- scoped_ptr<cc::SharedQuadState> state(cc::SharedQuadState::Create());
- if (!ReadParam(m, iter, state.get()))
- return false;
- p->shared_quad_state_list.push_back(state.Pass());
- }
+ has_transparent_background);
- size_t last_shared_quad_state_index = 0;
+ size_t last_shared_quad_state_index = kuint32max;
for (size_t i = 0; i < quad_list_size; ++i) {
cc::DrawQuad::Material material;
PickleIterator temp_iter = *iter;
@@ -500,19 +464,40 @@ bool ParamTraits<cc::RenderPass>::Read(
}
if (!draw_quad)
return false;
+ if (!draw_quad->rect.Contains(draw_quad->visible_rect)) {
+ LOG(ERROR) << "Quad with invalid visible rect " << draw_quad->material
+ << " rect: " << draw_quad->rect.ToString()
+ << " visible_rect: " << draw_quad->visible_rect.ToString();
+ return false;
+ }
+ if (!draw_quad->opaque_rect.IsEmpty() &&
+ !draw_quad->rect.Contains(draw_quad->opaque_rect)) {
+ LOG(ERROR) << "Quad with invalid opaque rect " << draw_quad->material
+ << " rect: " << draw_quad->rect.ToString()
+ << " opaque_rect: " << draw_quad->opaque_rect.ToString();
+ return false;
+ }
size_t shared_quad_state_index;
- if (!ReadParam(m, iter, &shared_quad_state_index) ||
- shared_quad_state_index >= p->shared_quad_state_list.size())
+ if (!ReadParam(m, iter, &shared_quad_state_index))
+ return false;
+ if (shared_quad_state_index >= shared_quad_state_list_size)
return false;
// SharedQuadState indexes should be in ascending order.
- if (shared_quad_state_index < last_shared_quad_state_index)
+ if (last_shared_quad_state_index != kuint32max &&
+ shared_quad_state_index < last_shared_quad_state_index)
return false;
- last_shared_quad_state_index = shared_quad_state_index;
- draw_quad->shared_quad_state =
- p->shared_quad_state_list[shared_quad_state_index];
+ // If the quad has a new shared quad state, read it in.
+ if (last_shared_quad_state_index != shared_quad_state_index) {
+ scoped_ptr<cc::SharedQuadState> state(cc::SharedQuadState::Create());
+ if (!ReadParam(m, iter, state.get()))
+ return false;
+ p->shared_quad_state_list.push_back(state.Pass());
+ last_shared_quad_state_index = shared_quad_state_index;
+ }
+ draw_quad->shared_quad_state = p->shared_quad_state_list.back();
p->quad_list.push_back(draw_quad.Pass());
}
@@ -532,8 +517,6 @@ void ParamTraits<cc::RenderPass>::Log(
l->append(", ");
LogParam(p.has_transparent_background, l);
l->append(", ");
- LogParam(p.has_occlusion_from_outside_target_surface, l);
- l->append(", ");
l->append("[");
for (size_t i = 0; i < p.shared_quad_state_list.size(); ++i) {
@@ -714,6 +697,15 @@ void ParamTraits<cc::CompositorFrameAck>::Log(const param_type& p,
void ParamTraits<cc::DelegatedFrameData>::Write(Message* m,
const param_type& p) {
+ DCHECK_NE(0u, p.render_pass_list.size());
+
+ size_t to_reserve = p.resource_list.size() * sizeof(cc::TransferableResource);
+ for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
+ const cc::RenderPass* pass = p.render_pass_list[i];
+ to_reserve += ReserveSizeForRenderPassWrite(*pass);
+ }
+ m->Reserve(to_reserve);
+
WriteParam(m, p.resource_list);
WriteParam(m, p.render_pass_list.size());
for (size_t i = 0; i < p.render_pass_list.size(); ++i)
@@ -728,7 +720,7 @@ bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
size_t num_render_passes;
if (!ReadParam(m, iter, &p->resource_list) ||
!ReadParam(m, iter, &num_render_passes) ||
- num_render_passes > kMaxRenderPasses)
+ num_render_passes > kMaxRenderPasses || num_render_passes == 0)
return false;
for (size_t i = 0; i < num_render_passes; ++i) {
scoped_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
diff --git a/chromium/content/common/cc_messages.h b/chromium/content/common/cc_messages.h
index 5c8b0b722b5..c9e72ba48f0 100644
--- a/chromium/content/common/cc_messages.h
+++ b/chromium/content/common/cc_messages.h
@@ -119,6 +119,7 @@ IPC_ENUM_TRAITS(cc::DrawQuad::Material)
IPC_ENUM_TRAITS(cc::IOSurfaceDrawQuad::Orientation)
IPC_ENUM_TRAITS(cc::FilterOperation::FilterType)
IPC_ENUM_TRAITS_MAX_VALUE(cc::ResourceFormat, cc::RESOURCE_FORMAT_MAX)
+IPC_ENUM_TRAITS_MAX_VALUE(SkXfermode::Mode, SkXfermode::kLastMode)
IPC_STRUCT_TRAITS_BEGIN(cc::RenderPass::Id)
IPC_STRUCT_TRAITS_MEMBER(layer_id)
@@ -159,7 +160,6 @@ IPC_STRUCT_TRAITS_BEGIN(cc::RenderPassDrawQuad)
IPC_STRUCT_TRAITS_MEMBER(contents_changed_since_last_frame)
IPC_STRUCT_TRAITS_MEMBER(mask_uv_rect)
IPC_STRUCT_TRAITS_MEMBER(filters)
- IPC_STRUCT_TRAITS_MEMBER(filter)
IPC_STRUCT_TRAITS_MEMBER(background_filters)
IPC_STRUCT_TRAITS_END()
@@ -213,15 +213,18 @@ IPC_STRUCT_TRAITS_BEGIN(cc::SharedQuadState)
IPC_STRUCT_TRAITS_MEMBER(clip_rect)
IPC_STRUCT_TRAITS_MEMBER(is_clipped)
IPC_STRUCT_TRAITS_MEMBER(opacity)
+ IPC_STRUCT_TRAITS_MEMBER(blend_mode)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::TransferableResource)
IPC_STRUCT_TRAITS_MEMBER(id)
IPC_STRUCT_TRAITS_MEMBER(sync_point)
IPC_STRUCT_TRAITS_MEMBER(format)
+ IPC_STRUCT_TRAITS_MEMBER(target)
IPC_STRUCT_TRAITS_MEMBER(filter)
IPC_STRUCT_TRAITS_MEMBER(size)
IPC_STRUCT_TRAITS_MEMBER(mailbox)
+ IPC_STRUCT_TRAITS_MEMBER(is_software)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::ReturnedResource)
diff --git a/chromium/content/common/cc_messages_perftest.cc b/chromium/content/common/cc_messages_perftest.cc
new file mode 100644
index 00000000000..87aa2e89e15
--- /dev/null
+++ b/chromium/content/common/cc_messages_perftest.cc
@@ -0,0 +1,157 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/cc_messages.h"
+
+#include "base/test/launcher/unit_test_launcher.h"
+#include "base/test/test_suite.h"
+#include "cc/output/compositor_frame.h"
+#include "ipc/ipc_message.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/perf/perf_test.h"
+
+using cc::CompositorFrame;
+using cc::DelegatedFrameData;
+using cc::DrawQuad;
+using cc::PictureDrawQuad;
+using cc::RenderPass;
+using cc::SharedQuadState;
+
+namespace content {
+namespace {
+
+static const int kTimeLimitMillis = 2000;
+static const int kNumWarmupRuns = 20;
+static const int kTimeCheckInterval = 10;
+
+class CCMessagesPerfTest : public testing::Test {
+ protected:
+ static void RunTest(std::string test_name, const CompositorFrame& frame) {
+ for (int i = 0; i < kNumWarmupRuns; ++i) {
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::ParamTraits<CompositorFrame>::Write(&msg, frame);
+ }
+
+ base::TimeTicks start = base::TimeTicks::HighResNow();
+ base::TimeTicks end =
+ start + base::TimeDelta::FromMilliseconds(kTimeLimitMillis);
+ base::TimeDelta min_time;
+ int count = 0;
+ while (start < end) {
+ for (int i = 0; i < kTimeCheckInterval; ++i) {
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::ParamTraits<CompositorFrame>::Write(&msg, frame);
+ ++count;
+ }
+
+ base::TimeTicks now = base::TimeTicks::HighResNow();
+ if (now - start < min_time || min_time == base::TimeDelta())
+ min_time = now - start;
+ start = base::TimeTicks::HighResNow();
+ }
+
+ perf_test::PrintResult(
+ "min_frame_serialization_time",
+ "",
+ test_name,
+ min_time.InMillisecondsF() / kTimeCheckInterval * 1000,
+ "us",
+ true);
+ }
+};
+
+TEST_F(CCMessagesPerfTest, DelegatedFrame_ManyQuads_1_4000) {
+ scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+ render_pass->shared_quad_state_list.push_back(SharedQuadState::Create());
+ for (int i = 0; i < 4000; ++i) {
+ render_pass->quad_list.push_back(
+ PictureDrawQuad::Create().PassAs<DrawQuad>());
+ render_pass->quad_list.back()->shared_quad_state =
+ render_pass->shared_quad_state_list.back();
+ }
+
+ frame->delegated_frame_data.reset(new DelegatedFrameData);
+ frame->delegated_frame_data->render_pass_list.push_back(render_pass.Pass());
+
+ RunTest("DelegatedFrame_ManyQuads_1_4000", *frame);
+}
+
+TEST_F(CCMessagesPerfTest, DelegatedFrame_ManyQuads_1_100000) {
+ scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+ render_pass->shared_quad_state_list.push_back(SharedQuadState::Create());
+ for (int i = 0; i < 100000; ++i) {
+ render_pass->quad_list.push_back(
+ PictureDrawQuad::Create().PassAs<DrawQuad>());
+ render_pass->quad_list.back()->shared_quad_state =
+ render_pass->shared_quad_state_list.back();
+ }
+
+ frame->delegated_frame_data.reset(new DelegatedFrameData);
+ frame->delegated_frame_data->render_pass_list.push_back(render_pass.Pass());
+
+ RunTest("DelegatedFrame_ManyQuads_1_100000", *frame);
+}
+
+TEST_F(CCMessagesPerfTest, DelegatedFrame_ManyQuads_4000_4000) {
+ scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+ for (int i = 0; i < 4000; ++i) {
+ render_pass->shared_quad_state_list.push_back(SharedQuadState::Create());
+ render_pass->quad_list.push_back(
+ PictureDrawQuad::Create().PassAs<DrawQuad>());
+ render_pass->quad_list.back()->shared_quad_state =
+ render_pass->shared_quad_state_list.back();
+ }
+
+ frame->delegated_frame_data.reset(new DelegatedFrameData);
+ frame->delegated_frame_data->render_pass_list.push_back(render_pass.Pass());
+
+ RunTest("DelegatedFrame_ManyQuads_4000_4000", *frame);
+}
+
+TEST_F(CCMessagesPerfTest, DelegatedFrame_ManyQuads_100000_100000) {
+ scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+ for (int i = 0; i < 100000; ++i) {
+ render_pass->shared_quad_state_list.push_back(SharedQuadState::Create());
+ render_pass->quad_list.push_back(
+ PictureDrawQuad::Create().PassAs<DrawQuad>());
+ render_pass->quad_list.back()->shared_quad_state =
+ render_pass->shared_quad_state_list.back();
+ }
+
+ frame->delegated_frame_data.reset(new DelegatedFrameData);
+ frame->delegated_frame_data->render_pass_list.push_back(render_pass.Pass());
+
+ RunTest("DelegatedFrame_ManyQuads_100000_100000", *frame);
+}
+
+TEST_F(CCMessagesPerfTest,
+ DelegatedFrame_ManyRenderPasses_10000_100) {
+ scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+ frame->delegated_frame_data.reset(new DelegatedFrameData);
+
+ for (int i = 0; i < 1000; ++i) {
+ scoped_ptr<RenderPass> render_pass = RenderPass::Create();
+ for (int j = 0; j < 100; ++j) {
+ render_pass->shared_quad_state_list.push_back(SharedQuadState::Create());
+ render_pass->quad_list.push_back(
+ PictureDrawQuad::Create().PassAs<DrawQuad>());
+ render_pass->quad_list.back()->shared_quad_state =
+ render_pass->shared_quad_state_list.back();
+ }
+ frame->delegated_frame_data->render_pass_list.push_back(render_pass.Pass());
+ }
+
+ RunTest("DelegatedFrame_ManyRenderPasses_10000_100", *frame);
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/common/cc_messages_unittest.cc b/chromium/content/common/cc_messages_unittest.cc
index 6be248da55b..ccd41fc9070 100644
--- a/chromium/content/common/cc_messages_unittest.cc
+++ b/chromium/content/common/cc_messages_unittest.cc
@@ -6,11 +6,12 @@
#include <string.h>
-#include "base/command_line.h"
+#include <algorithm>
+
#include "cc/output/compositor_frame.h"
-#include "content/public/common/content_switches.h"
#include "ipc/ipc_message.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/effects/SkBlurImageFilter.h"
using cc::CheckerboardDrawQuad;
@@ -45,8 +46,6 @@ class CCMessagesTest : public testing::Test {
EXPECT_EQ(a->damage_rect.ToString(), b->damage_rect.ToString());
EXPECT_EQ(a->transform_to_root_target, b->transform_to_root_target);
EXPECT_EQ(a->has_transparent_background, b->has_transparent_background);
- EXPECT_EQ(a->has_occlusion_from_outside_target_surface,
- b->has_occlusion_from_outside_target_surface);
}
void Compare(const SharedQuadState* a, const SharedQuadState* b) {
@@ -56,6 +55,7 @@ class CCMessagesTest : public testing::Test {
EXPECT_EQ(a->clip_rect, b->clip_rect);
EXPECT_EQ(a->is_clipped, b->is_clipped);
EXPECT_EQ(a->opacity, b->opacity);
+ EXPECT_EQ(a->blend_mode, b->blend_mode);
}
void Compare(const DrawQuad* a, const DrawQuad* b) {
@@ -136,11 +136,16 @@ class CCMessagesTest : public testing::Test {
EXPECT_EQ(a->contents_changed_since_last_frame,
b->contents_changed_since_last_frame);
EXPECT_EQ(a->mask_uv_rect.ToString(), b->mask_uv_rect.ToString());
- EXPECT_EQ(a->filters, b->filters);
- if (!a->filter || !b->filter)
- EXPECT_EQ(a->filter, b->filter);
- else
- EXPECT_EQ(a->filter->countInputs(), b->filter->countInputs());
+ EXPECT_EQ(a->filters.size(), b->filters.size());
+ for (size_t i = 0; i < a->filters.size(); ++i) {
+ if (a->filters.at(i).type() != cc::FilterOperation::REFERENCE) {
+ EXPECT_EQ(a->filters.at(i), b->filters.at(i));
+ } else {
+ EXPECT_EQ(b->filters.at(i).type(), cc::FilterOperation::REFERENCE);
+ EXPECT_EQ(a->filters.at(i).image_filter()->countInputs(),
+ b->filters.at(i).image_filter()->countInputs());
+ }
+ }
EXPECT_EQ(a->background_filters, b->background_filters);
}
@@ -186,6 +191,7 @@ class CCMessagesTest : public testing::Test {
EXPECT_EQ(a.id, b.id);
EXPECT_EQ(a.sync_point, b.sync_point);
EXPECT_EQ(a.format, b.format);
+ EXPECT_EQ(a.target, b.target);
EXPECT_EQ(a.filter, b.filter);
EXPECT_EQ(a.size.ToString(), b.size.ToString());
for (size_t i = 0; i < arraysize(a.mailbox.name); ++i)
@@ -194,10 +200,6 @@ class CCMessagesTest : public testing::Test {
};
TEST_F(CCMessagesTest, AllQuads) {
- CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (!command_line.HasSwitch(switches::kAllowFiltersOverIPC))
- command_line.AppendSwitch(switches::kAllowFiltersOverIPC);
-
IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
Transform arbitrary_matrix;
@@ -205,8 +207,14 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_matrix.Translate(-5, 20);
arbitrary_matrix.Rotate(15);
gfx::Rect arbitrary_rect1(-5, 9, 3, 15);
+ gfx::Rect arbitrary_rect1_inside_rect1(-4, 12, 2, 8);
+ gfx::Rect arbitrary_rect2_inside_rect1(-5, 11, 1, 2);
gfx::Rect arbitrary_rect2(40, 23, 11, 7);
+ gfx::Rect arbitrary_rect1_inside_rect2(44, 23, 4, 2);
+ gfx::Rect arbitrary_rect2_inside_rect2(41, 25, 3, 5);
gfx::Rect arbitrary_rect3(7, -53, 22, 19);
+ gfx::Rect arbitrary_rect1_inside_rect3(10, -40, 6, 3);
+ gfx::Rect arbitrary_rect2_inside_rect3(12, -51, 5, 12);
gfx::Size arbitrary_size1(15, 19);
gfx::Size arbitrary_size2(3, 99);
gfx::Size arbitrary_size3(75, 1281);
@@ -223,6 +231,9 @@ TEST_F(CCMessagesTest, AllQuads) {
bool arbitrary_bool3 = true;
int arbitrary_int = 5;
SkColor arbitrary_color = SkColorSetARGB(25, 36, 47, 58);
+ SkXfermode::Mode arbitrary_blend_mode1 = SkXfermode::kScreen_Mode;
+ SkXfermode::Mode arbitrary_blend_mode2 = SkXfermode::kLighten_Mode;
+ SkXfermode::Mode arbitrary_blend_mode3 = SkXfermode::kOverlay_Mode;
IOSurfaceDrawQuad::Orientation arbitrary_orientation =
IOSurfaceDrawQuad::UNFLIPPED;
RenderPass::Id arbitrary_id(10, 14);
@@ -235,29 +246,31 @@ TEST_F(CCMessagesTest, AllQuads) {
FilterOperations arbitrary_filters1;
arbitrary_filters1.Append(FilterOperation::CreateGrayscaleFilter(
arbitrary_float1));
+ skia::RefPtr<SkImageFilter> arbitrary_filter = skia::AdoptRef(
+ new SkBlurImageFilter(arbitrary_sigma, arbitrary_sigma));
+ arbitrary_filters1.Append(
+ cc::FilterOperation::CreateReferenceFilter(arbitrary_filter));
FilterOperations arbitrary_filters2;
arbitrary_filters2.Append(FilterOperation::CreateBrightnessFilter(
arbitrary_float2));
- skia::RefPtr<SkImageFilter> arbitrary_filter = skia::AdoptRef(
- new SkBlurImageFilter(arbitrary_sigma, arbitrary_sigma));
-
scoped_ptr<SharedQuadState> shared_state1_in = SharedQuadState::Create();
shared_state1_in->SetAll(arbitrary_matrix,
arbitrary_size1,
arbitrary_rect1,
arbitrary_rect2,
arbitrary_bool1,
- arbitrary_float1);
+ arbitrary_float1,
+ arbitrary_blend_mode1);
scoped_ptr<SharedQuadState> shared_state1_cmp = shared_state1_in->Copy();
scoped_ptr<CheckerboardDrawQuad> checkerboard_in =
CheckerboardDrawQuad::Create();
checkerboard_in->SetAll(shared_state1_in.get(),
arbitrary_rect1,
- arbitrary_rect2,
- arbitrary_rect3,
+ arbitrary_rect2_inside_rect1,
+ arbitrary_rect1_inside_rect1,
arbitrary_bool1,
arbitrary_color);
scoped_ptr<DrawQuad> checkerboard_cmp = checkerboard_in->Copy(
@@ -267,8 +280,8 @@ TEST_F(CCMessagesTest, AllQuads) {
DebugBorderDrawQuad::Create();
debugborder_in->SetAll(shared_state1_in.get(),
arbitrary_rect3,
- arbitrary_rect1,
- arbitrary_rect2,
+ arbitrary_rect1_inside_rect3,
+ arbitrary_rect2_inside_rect3,
arbitrary_bool1,
arbitrary_color,
arbitrary_int);
@@ -279,8 +292,8 @@ TEST_F(CCMessagesTest, AllQuads) {
IOSurfaceDrawQuad::Create();
iosurface_in->SetAll(shared_state1_in.get(),
arbitrary_rect2,
- arbitrary_rect3,
- arbitrary_rect1,
+ arbitrary_rect2_inside_rect2,
+ arbitrary_rect1_inside_rect2,
arbitrary_bool1,
arbitrary_size1,
arbitrary_resourceid3,
@@ -288,12 +301,22 @@ TEST_F(CCMessagesTest, AllQuads) {
scoped_ptr<DrawQuad> iosurface_cmp = iosurface_in->Copy(
iosurface_in->shared_quad_state);
+ scoped_ptr<SharedQuadState> shared_state2_in = SharedQuadState::Create();
+ shared_state2_in->SetAll(arbitrary_matrix,
+ arbitrary_size2,
+ arbitrary_rect2,
+ arbitrary_rect3,
+ arbitrary_bool1,
+ arbitrary_float2,
+ arbitrary_blend_mode2);
+ scoped_ptr<SharedQuadState> shared_state2_cmp = shared_state2_in->Copy();
+
scoped_ptr<RenderPassDrawQuad> renderpass_in =
RenderPassDrawQuad::Create();
- renderpass_in->SetAll(shared_state1_in.get(),
+ renderpass_in->SetAll(shared_state2_in.get(),
arbitrary_rect1,
- arbitrary_rect2,
- arbitrary_rect3,
+ arbitrary_rect2_inside_rect1,
+ arbitrary_rect1_inside_rect1,
arbitrary_bool1,
arbitrary_id,
arbitrary_bool2,
@@ -301,35 +324,26 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rect1,
arbitrary_rectf1,
arbitrary_filters1,
- arbitrary_filter,
arbitrary_filters2);
scoped_ptr<RenderPassDrawQuad> renderpass_cmp = renderpass_in->Copy(
renderpass_in->shared_quad_state, renderpass_in->render_pass_id);
- scoped_ptr<SharedQuadState> shared_state2_in = SharedQuadState::Create();
- shared_state2_in->SetAll(arbitrary_matrix,
- arbitrary_size2,
- arbitrary_rect2,
- arbitrary_rect3,
- arbitrary_bool1,
- arbitrary_float2);
- scoped_ptr<SharedQuadState> shared_state2_cmp = shared_state2_in->Copy();
-
scoped_ptr<SharedQuadState> shared_state3_in = SharedQuadState::Create();
shared_state3_in->SetAll(arbitrary_matrix,
arbitrary_size3,
arbitrary_rect3,
arbitrary_rect1,
arbitrary_bool1,
- arbitrary_float3);
+ arbitrary_float3,
+ arbitrary_blend_mode3);
scoped_ptr<SharedQuadState> shared_state3_cmp = shared_state3_in->Copy();
scoped_ptr<SolidColorDrawQuad> solidcolor_in =
SolidColorDrawQuad::Create();
- solidcolor_in->SetAll(shared_state1_in.get(),
+ solidcolor_in->SetAll(shared_state3_in.get(),
arbitrary_rect3,
- arbitrary_rect1,
- arbitrary_rect2,
+ arbitrary_rect1_inside_rect3,
+ arbitrary_rect2_inside_rect3,
arbitrary_bool1,
arbitrary_color,
arbitrary_bool2);
@@ -338,10 +352,10 @@ TEST_F(CCMessagesTest, AllQuads) {
scoped_ptr<StreamVideoDrawQuad> streamvideo_in =
StreamVideoDrawQuad::Create();
- streamvideo_in->SetAll(shared_state1_in.get(),
+ streamvideo_in->SetAll(shared_state3_in.get(),
arbitrary_rect2,
- arbitrary_rect3,
- arbitrary_rect1,
+ arbitrary_rect2_inside_rect2,
+ arbitrary_rect1_inside_rect2,
arbitrary_bool1,
arbitrary_resourceid2,
arbitrary_matrix);
@@ -349,10 +363,10 @@ TEST_F(CCMessagesTest, AllQuads) {
streamvideo_in->shared_quad_state);
scoped_ptr<TextureDrawQuad> texture_in = TextureDrawQuad::Create();
- texture_in->SetAll(shared_state1_in.get(),
+ texture_in->SetAll(shared_state3_in.get(),
arbitrary_rect2,
- arbitrary_rect3,
- arbitrary_rect1,
+ arbitrary_rect2_inside_rect2,
+ arbitrary_rect1_inside_rect2,
arbitrary_bool1,
arbitrary_resourceid1,
arbitrary_bool2,
@@ -365,10 +379,10 @@ TEST_F(CCMessagesTest, AllQuads) {
texture_in->shared_quad_state);
scoped_ptr<TileDrawQuad> tile_in = TileDrawQuad::Create();
- tile_in->SetAll(shared_state1_in.get(),
+ tile_in->SetAll(shared_state3_in.get(),
arbitrary_rect2,
- arbitrary_rect3,
- arbitrary_rect1,
+ arbitrary_rect2_inside_rect2,
+ arbitrary_rect1_inside_rect2,
arbitrary_bool1,
arbitrary_resourceid3,
arbitrary_rectf1,
@@ -379,10 +393,10 @@ TEST_F(CCMessagesTest, AllQuads) {
scoped_ptr<YUVVideoDrawQuad> yuvvideo_in =
YUVVideoDrawQuad::Create();
- yuvvideo_in->SetAll(shared_state1_in.get(),
+ yuvvideo_in->SetAll(shared_state3_in.get(),
arbitrary_rect1,
- arbitrary_rect2,
- arbitrary_rect3,
+ arbitrary_rect2_inside_rect1,
+ arbitrary_rect1_inside_rect1,
arbitrary_bool1,
arbitrary_sizef1,
arbitrary_resourceid1,
@@ -397,8 +411,7 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rect1,
arbitrary_rectf1,
arbitrary_matrix,
- arbitrary_bool1,
- arbitrary_bool2);
+ arbitrary_bool1);
pass_in->shared_quad_state_list.push_back(shared_state1_in.Pass());
pass_in->quad_list.push_back(checkerboard_in.PassAs<DrawQuad>());
@@ -418,8 +431,7 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rect1,
arbitrary_rectf1,
arbitrary_matrix,
- arbitrary_bool1,
- arbitrary_bool2);
+ arbitrary_bool1);
pass_cmp->shared_quad_state_list.push_back(shared_state1_cmp.Pass());
pass_cmp->quad_list.push_back(checkerboard_cmp.PassAs<DrawQuad>());
@@ -487,6 +499,118 @@ TEST_F(CCMessagesTest, AllQuads) {
}
}
+TEST_F(CCMessagesTest, UnusedSharedQuadStates) {
+ scoped_ptr<CheckerboardDrawQuad> quad;
+
+ scoped_ptr<RenderPass> pass_in = RenderPass::Create();
+ pass_in->SetAll(RenderPass::Id(1, 1),
+ gfx::Rect(100, 100),
+ gfx::RectF(),
+ gfx::Transform(),
+ false);
+
+ // The first SharedQuadState is used.
+ scoped_ptr<SharedQuadState> shared_state1_in = SharedQuadState::Create();
+ shared_state1_in->SetAll(gfx::Transform(),
+ gfx::Size(1, 1),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
+
+ quad = CheckerboardDrawQuad::Create();
+ quad->SetAll(shared_state1_in.get(),
+ gfx::Rect(10, 10),
+ gfx::Rect(10, 10),
+ gfx::Rect(10, 10),
+ false,
+ SK_ColorRED);
+ pass_in->quad_list.push_back(quad.PassAs<DrawQuad>());
+
+ // The second and third SharedQuadStates are not used.
+ scoped_ptr<SharedQuadState> shared_state2_in = SharedQuadState::Create();
+ shared_state2_in->SetAll(gfx::Transform(),
+ gfx::Size(2, 2),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
+
+ scoped_ptr<SharedQuadState> shared_state3_in = SharedQuadState::Create();
+ shared_state3_in->SetAll(gfx::Transform(),
+ gfx::Size(3, 3),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
+
+ // The fourth SharedQuadState is used.
+ scoped_ptr<SharedQuadState> shared_state4_in = SharedQuadState::Create();
+ shared_state4_in->SetAll(gfx::Transform(),
+ gfx::Size(4, 4),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
+
+ quad = CheckerboardDrawQuad::Create();
+ quad->SetAll(shared_state4_in.get(),
+ gfx::Rect(10, 10),
+ gfx::Rect(10, 10),
+ gfx::Rect(10, 10),
+ false,
+ SK_ColorRED);
+ pass_in->quad_list.push_back(quad.PassAs<DrawQuad>());
+
+ // The fifth is not used again.
+ scoped_ptr<SharedQuadState> shared_state5_in = SharedQuadState::Create();
+ shared_state5_in->SetAll(gfx::Transform(),
+ gfx::Size(5, 5),
+ gfx::Rect(),
+ gfx::Rect(),
+ false,
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
+
+ pass_in->shared_quad_state_list.push_back(shared_state1_in.Pass());
+ pass_in->shared_quad_state_list.push_back(shared_state2_in.Pass());
+ pass_in->shared_quad_state_list.push_back(shared_state3_in.Pass());
+ pass_in->shared_quad_state_list.push_back(shared_state4_in.Pass());
+ pass_in->shared_quad_state_list.push_back(shared_state5_in.Pass());
+
+ // 5 SharedQuadStates go in.
+ ASSERT_EQ(5u, pass_in->shared_quad_state_list.size());
+ ASSERT_EQ(2u, pass_in->quad_list.size());
+
+ DelegatedFrameData frame_in;
+ frame_in.render_pass_list.push_back(pass_in.Pass());
+
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::ParamTraits<DelegatedFrameData>::Write(&msg, frame_in);
+
+ DelegatedFrameData frame_out;
+ PickleIterator iter(msg);
+ EXPECT_TRUE(
+ IPC::ParamTraits<DelegatedFrameData>::Read(&msg, &iter, &frame_out));
+
+ scoped_ptr<RenderPass> pass_out =
+ frame_out.render_pass_list.take(frame_out.render_pass_list.begin());
+
+ // 2 SharedQuadStates come out. The first and fourth SharedQuadStates were
+ // used by quads, and so serialized. Others were not.
+ ASSERT_EQ(2u, pass_out->shared_quad_state_list.size());
+ ASSERT_EQ(2u, pass_out->quad_list.size());
+
+ EXPECT_EQ(gfx::Size(1, 1).ToString(),
+ pass_out->shared_quad_state_list[0]->content_bounds.ToString());
+ EXPECT_EQ(gfx::Size(4, 4).ToString(),
+ pass_out->shared_quad_state_list[1]->content_bounds.ToString());
+}
+
TEST_F(CCMessagesTest, Resources) {
IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
gfx::Size arbitrary_size(757, 1281);
@@ -511,21 +635,28 @@ TEST_F(CCMessagesTest, Resources) {
arbitrary_resource1.id = 2178312;
arbitrary_resource1.sync_point = arbitrary_uint1;
arbitrary_resource1.format = cc::RGBA_8888;
+ arbitrary_resource1.target = GL_TEXTURE_2D;
arbitrary_resource1.filter = 53;
arbitrary_resource1.size = gfx::Size(37189, 123123);
arbitrary_resource1.mailbox.SetName(arbitrary_mailbox1);
TransferableResource arbitrary_resource2;
arbitrary_resource2.id = 789132;
- arbitrary_resource1.sync_point = arbitrary_uint2;
+ arbitrary_resource2.sync_point = arbitrary_uint2;
arbitrary_resource2.format = cc::RGBA_4444;
- arbitrary_resource1.filter = 47;
+ arbitrary_resource2.target = GL_TEXTURE_EXTERNAL_OES;
+ arbitrary_resource2.filter = 47;
arbitrary_resource2.size = gfx::Size(89123, 23789);
arbitrary_resource2.mailbox.SetName(arbitrary_mailbox2);
+ scoped_ptr<RenderPass> renderpass_in = RenderPass::Create();
+ renderpass_in->SetNew(
+ RenderPass::Id(1, 1), gfx::Rect(), gfx::Rect(), gfx::Transform());
+
DelegatedFrameData frame_in;
frame_in.resource_list.push_back(arbitrary_resource1);
frame_in.resource_list.push_back(arbitrary_resource2);
+ frame_in.render_pass_list.push_back(renderpass_in.Pass());
IPC::ParamTraits<DelegatedFrameData>::Write(&msg, frame_in);
@@ -539,5 +670,54 @@ TEST_F(CCMessagesTest, Resources) {
Compare(arbitrary_resource2, frame_out.resource_list[1]);
}
+TEST_F(CCMessagesTest, LargestQuadType) {
+ size_t largest = 0;
+
+ bool done = false;
+ for (int i = 0; !done; ++i) {
+ switch (static_cast<DrawQuad::Material>(i)) {
+ case cc::DrawQuad::CHECKERBOARD:
+ largest = std::max(largest, sizeof(cc::CheckerboardDrawQuad));
+ break;
+ case cc::DrawQuad::DEBUG_BORDER:
+ largest = std::max(largest, sizeof(cc::DebugBorderDrawQuad));
+ break;
+ case cc::DrawQuad::IO_SURFACE_CONTENT:
+ largest = std::max(largest, sizeof(cc::IOSurfaceDrawQuad));
+ break;
+ case cc::DrawQuad::PICTURE_CONTENT:
+ largest = std::max(largest, sizeof(cc::PictureDrawQuad));
+ break;
+ case cc::DrawQuad::TEXTURE_CONTENT:
+ largest = std::max(largest, sizeof(cc::TextureDrawQuad));
+ break;
+ case cc::DrawQuad::RENDER_PASS:
+ largest = std::max(largest, sizeof(cc::RenderPassDrawQuad));
+ break;
+ case cc::DrawQuad::SOLID_COLOR:
+ largest = std::max(largest, sizeof(cc::SolidColorDrawQuad));
+ break;
+ case cc::DrawQuad::TILED_CONTENT:
+ largest = std::max(largest, sizeof(cc::TileDrawQuad));
+ break;
+ case cc::DrawQuad::STREAM_VIDEO_CONTENT:
+ largest = std::max(largest, sizeof(cc::StreamVideoDrawQuad));
+ break;
+ case cc::DrawQuad::YUV_VIDEO_CONTENT:
+ largest = std::max(largest, sizeof(cc::YUVVideoDrawQuad));
+ break;
+ case cc::DrawQuad::INVALID:
+ break;
+ default:
+ done = true;
+ }
+ }
+
+ // Verify the largest DrawQuad type is RenderPassDrawQuad. If this ever
+ // changes, then the ReserveSizeForRenderPassWrite() method needs to be
+ // updated as well to use the new largest quad.
+ EXPECT_EQ(sizeof(RenderPassDrawQuad), largest);
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/common/child_process_host_impl.cc b/chromium/content/common/child_process_host_impl.cc
index 2208376cdbf..260749655a9 100644
--- a/chromium/content/common/child_process_host_impl.cc
+++ b/chromium/content/common/child_process_host_impl.cc
@@ -17,6 +17,7 @@
#include "base/strings/stringprintf.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "content/common/child_process_messages.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
#include "content/public/common/child_process_host_delegate.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
@@ -247,6 +248,8 @@ bool ChildProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
OnShutdownRequest)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
OnAllocateSharedMemory)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
+ OnAllocateGpuMemoryBuffer)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -293,4 +296,16 @@ void ChildProcessHostImpl::OnShutdownRequest() {
Send(new ChildProcessMsg_Shutdown());
}
+void ChildProcessHostImpl::OnAllocateGpuMemoryBuffer(
+ uint32 width,
+ uint32 height,
+ uint32 internalformat,
+ gfx::GpuMemoryBufferHandle* handle) {
+ handle->type = gfx::SHARED_MEMORY_BUFFER;
+ AllocateSharedMemory(
+ width * height * GpuMemoryBufferImpl::BytesPerPixel(internalformat),
+ peer_handle_,
+ &handle->handle);
+}
+
} // namespace content
diff --git a/chromium/content/common/child_process_host_impl.h b/chromium/content/common/child_process_host_impl.h
index a24f3b835ed..e0e4bbf39d6 100644
--- a/chromium/content/common/child_process_host_impl.h
+++ b/chromium/content/common/child_process_host_impl.h
@@ -22,6 +22,10 @@ namespace base {
class FilePath;
}
+namespace gfx {
+struct GpuMemoryBufferHandle;
+}
+
namespace content {
class ChildProcessHostDelegate;
@@ -75,6 +79,10 @@ class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost,
void OnShutdownRequest();
void OnAllocateSharedMemory(uint32 buffer_size,
base::SharedMemoryHandle* handle);
+ void OnAllocateGpuMemoryBuffer(uint32 width,
+ uint32 height,
+ uint32 internalformat,
+ gfx::GpuMemoryBufferHandle* handle);
ChildProcessHostDelegate* delegate_;
base::ProcessHandle peer_handle_;
diff --git a/chromium/content/common/child_process_messages.h b/chromium/content/common/child_process_messages.h
index 3f70bc38ab2..7c1dce52398 100644
--- a/chromium/content/common/child_process_messages.h
+++ b/chromium/content/common/child_process_messages.h
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
+#include "ui/gfx/gpu_memory_buffer.h"
IPC_ENUM_TRAITS(tracked_objects::ThreadData::Status)
@@ -54,6 +55,16 @@ IPC_STRUCT_TRAITS_BEGIN(tracked_objects::ProcessDataSnapshot)
IPC_STRUCT_TRAITS_MEMBER(process_id)
IPC_STRUCT_TRAITS_END()
+IPC_ENUM_TRAITS(gfx::GpuMemoryBufferType)
+
+IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferHandle)
+ IPC_STRUCT_TRAITS_MEMBER(type)
+ IPC_STRUCT_TRAITS_MEMBER(handle)
+#if defined(OS_MACOSX)
+ IPC_STRUCT_TRAITS_MEMBER(io_surface_id)
+#endif
+IPC_STRUCT_TRAITS_END()
+
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -138,3 +149,10 @@ IPC_SYNC_MESSAGE_CONTROL1_1(ChildProcessHostMsg_SyncAllocateSharedMemory,
IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_TcmallocStats,
std::string /* output */)
#endif
+
+// Asks the browser to create a gpu memory buffer.
+IPC_SYNC_MESSAGE_CONTROL3_1(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
+ uint32 /* width */,
+ uint32 /* height */,
+ uint32 /* internalformat */,
+ gfx::GpuMemoryBufferHandle)
diff --git a/chromium/content/common/child_process_sandbox_support_impl_linux.cc b/chromium/content/common/child_process_sandbox_support_impl_linux.cc
index 62f14727bd5..62124ae186a 100644
--- a/chromium/content/common/child_process_sandbox_support_impl_linux.cc
+++ b/chromium/content/common/child_process_sandbox_support_impl_linux.cc
@@ -13,7 +13,7 @@
#include "base/posix/unix_domain_socket_linux.h"
#include "base/safe_numerics.h"
#include "base/sys_byteorder.h"
-#include "content/common/sandbox_linux.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
#include "third_party/WebKit/public/platform/linux/WebFontFamily.h"
#include "third_party/WebKit/public/platform/linux/WebFontRenderStyle.h"
@@ -21,7 +21,7 @@ namespace content {
void GetFontFamilyForCharacter(int32_t character,
const char* preferred_locale,
- WebKit::WebFontFamily* family) {
+ blink::WebFontFamily* family) {
TRACE_EVENT0("sandbox_ipc", "GetFontFamilyForCharacter");
Pickle request;
@@ -50,7 +50,7 @@ void GetFontFamilyForCharacter(int32_t character,
}
void GetRenderStyleForStrike(const char* family, int sizeAndStyle,
- WebKit::WebFontRenderStyle* out) {
+ blink::WebFontRenderStyle* out) {
TRACE_EVENT0("sandbox_ipc", "GetRenderStyleForStrike");
Pickle request;
diff --git a/chromium/content/common/child_process_sandbox_support_impl_linux.h b/chromium/content/common/child_process_sandbox_support_impl_linux.h
index 23e003e4adc..556652fdd28 100644
--- a/chromium/content/common/child_process_sandbox_support_impl_linux.h
+++ b/chromium/content/common/child_process_sandbox_support_impl_linux.h
@@ -9,7 +9,7 @@
#include "content/public/common/child_process_sandbox_support_linux.h"
#include "content/public/common/content_descriptors.h"
-namespace WebKit {
+namespace blink {
struct WebFontFamily;
struct WebFontRenderStyle;
}
@@ -25,10 +25,10 @@ namespace content {
// The instance has an empty font name if the request could not be satisfied.
void GetFontFamilyForCharacter(const int32_t character,
const char* preferred_locale,
- WebKit::WebFontFamily* family);
+ blink::WebFontFamily* family);
void GetRenderStyleForStrike(const char* family, int sizeAndStyle,
- WebKit::WebFontRenderStyle* out);
+ blink::WebFontRenderStyle* out);
inline int GetSandboxFD() {
return kSandboxIPCChannel + base::GlobalDescriptors::kBaseDescriptor;
diff --git a/chromium/content/common/child_process_sandbox_support_impl_shm_linux.cc b/chromium/content/common/child_process_sandbox_support_impl_shm_linux.cc
index 1aaa1c0a950..0c634c109a9 100644
--- a/chromium/content/common/child_process_sandbox_support_impl_shm_linux.cc
+++ b/chromium/content/common/child_process_sandbox_support_impl_shm_linux.cc
@@ -6,7 +6,7 @@
#include "base/pickle.h"
#include "base/posix/unix_domain_socket_linux.h"
-#include "content/common/sandbox_linux.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
namespace content {
diff --git a/chromium/content/common/clipboard_messages.h b/chromium/content/common/clipboard_messages.h
index d17f89f3c81..d212638ee67 100644
--- a/chromium/content/common/clipboard_messages.h
+++ b/chromium/content/common/clipboard_messages.h
@@ -32,7 +32,7 @@ struct ParamTraits<ui::Clipboard::FormatType> {
#endif // CONTENT_COMMON_CLIPBOARD_MESSAGES_H_
-IPC_ENUM_TRAITS(ui::Clipboard::Buffer)
+IPC_ENUM_TRAITS(ui::ClipboardType)
// Clipboard IPC messages sent from the renderer to the browser.
@@ -46,46 +46,46 @@ IPC_SYNC_MESSAGE_CONTROL2_0(ClipboardHostMsg_WriteObjectsSync,
ui::Clipboard::ObjectMap /* objects */,
base::SharedMemoryHandle /* bitmap handle */)
IPC_SYNC_MESSAGE_CONTROL1_1(ClipboardHostMsg_GetSequenceNumber,
- ui::Clipboard::Buffer /* buffer */,
+ ui::ClipboardType /* type */,
uint64 /* result */)
IPC_SYNC_MESSAGE_CONTROL2_1(ClipboardHostMsg_IsFormatAvailable,
ui::Clipboard::FormatType /* format */,
- ui::Clipboard::Buffer /* buffer */,
+ ui::ClipboardType /* type */,
bool /* result */)
IPC_MESSAGE_CONTROL1(ClipboardHostMsg_Clear,
- ui::Clipboard::Buffer /* buffer */)
+ ui::ClipboardType /* type */)
IPC_SYNC_MESSAGE_CONTROL1_2(ClipboardHostMsg_ReadAvailableTypes,
- ui::Clipboard::Buffer /* buffer */,
- std::vector<string16> /* types */,
+ ui::ClipboardType /* type */,
+ std::vector<base::string16> /* types */,
bool /* contains filenames */)
IPC_SYNC_MESSAGE_CONTROL1_1(ClipboardHostMsg_ReadText,
- ui::Clipboard::Buffer /* buffer */,
- string16 /* result */)
+ ui::ClipboardType /* type */,
+ base::string16 /* result */)
IPC_SYNC_MESSAGE_CONTROL1_1(ClipboardHostMsg_ReadAsciiText,
- ui::Clipboard::Buffer /* buffer */,
+ ui::ClipboardType /* type */,
std::string /* result */)
IPC_SYNC_MESSAGE_CONTROL1_4(ClipboardHostMsg_ReadHTML,
- ui::Clipboard::Buffer /* buffer */,
- string16 /* markup */,
+ ui::ClipboardType /* type */,
+ base::string16 /* markup */,
GURL /* url */,
uint32 /* fragment start */,
uint32 /* fragment end */)
IPC_SYNC_MESSAGE_CONTROL1_1(ClipboardHostMsg_ReadRTF,
- ui::Clipboard::Buffer /* buffer */,
+ ui::ClipboardType /* type */,
std::string /* result */)
IPC_SYNC_MESSAGE_CONTROL1_2(ClipboardHostMsg_ReadImage,
- ui::Clipboard::Buffer /* buffer */,
+ ui::ClipboardType /* type */,
base::SharedMemoryHandle /* PNG-encoded image */,
uint32 /* image size */)
IPC_SYNC_MESSAGE_CONTROL2_1(ClipboardHostMsg_ReadCustomData,
- ui::Clipboard::Buffer /* buffer */,
- string16 /* type */,
- string16 /* result */)
+ ui::ClipboardType /* type */,
+ base::string16 /* type */,
+ base::string16 /* result */)
IPC_SYNC_MESSAGE_CONTROL1_1(ClipboardHostMsg_ReadData,
ui::Clipboard::FormatType /* format */,
std::string /* result */)
#if defined(OS_MACOSX)
IPC_MESSAGE_CONTROL1(ClipboardHostMsg_FindPboardWriteStringAsync,
- string16 /* text */)
+ base::string16 /* text */)
#endif
diff --git a/chromium/content/common/common_param_traits_unittest.cc b/chromium/content/common/common_param_traits_unittest.cc
index 1b4ef7ee661..95669507179 100644
--- a/chromium/content/common/common_param_traits_unittest.cc
+++ b/chromium/content/common/common_param_traits_unittest.cc
@@ -109,7 +109,7 @@ TEST(IPCMessageTest, Bitmap) {
const char* fixed_data;
int fixed_data_size;
iter = PickleIterator(msg);
- msg.ReadData(&iter, &fixed_data, &fixed_data_size);
+ EXPECT_TRUE(msg.ReadData(&iter, &fixed_data, &fixed_data_size));
bad_msg.WriteData(fixed_data, fixed_data_size);
// Add some bogus pixel data.
const size_t bogus_pixels_size = bitmap.getSize() * 2;
diff --git a/chromium/content/common/content_message_generator.h b/chromium/content/common/content_message_generator.h
index b0af11d68e6..78e7c530032 100644
--- a/chromium/content/common/content_message_generator.h
+++ b/chromium/content/common/content_message_generator.h
@@ -22,6 +22,7 @@
#include "content/common/file_utilities_messages.h"
#include "content/common/fileapi/file_system_messages.h"
#include "content/common/fileapi/webblob_messages.h"
+#include "content/common/frame_messages.h"
#include "content/common/gamepad_messages.h"
#include "content/common/geolocation_messages.h"
#include "content/common/gpu/gpu_messages.h"
@@ -39,6 +40,7 @@
#include "content/common/media/video_capture_messages.h"
#include "content/common/media/webrtc_identity_messages.h"
#include "content/common/memory_benchmark_messages.h"
+#include "content/common/message_port_messages.h"
#include "content/common/mime_registry_messages.h"
#include "content/common/p2p_messages.h"
#include "content/common/pepper_messages.h"
diff --git a/chromium/content/common/content_param_traits.cc b/chromium/content/common/content_param_traits.cc
index 6b607558f92..3b0ab981106 100644
--- a/chromium/content/common/content_param_traits.cc
+++ b/chromium/content/common/content_param_traits.cc
@@ -5,28 +5,10 @@
#include "content/common/content_param_traits.h"
#include "base/strings/string_number_conversions.h"
+#include "content/common/input/web_input_event_traits.h"
#include "net/base/ip_endpoint.h"
#include "ui/gfx/range/range.h"
-namespace {
-
-int WebInputEventSizeForType(WebKit::WebInputEvent::Type type) {
- if (WebKit::WebInputEvent::isMouseEventType(type))
- return sizeof(WebKit::WebMouseEvent);
- if (type == WebKit::WebInputEvent::MouseWheel)
- return sizeof(WebKit::WebMouseWheelEvent);
- if (WebKit::WebInputEvent::isKeyboardEventType(type))
- return sizeof(WebKit::WebKeyboardEvent);
- if (WebKit::WebInputEvent::isTouchEventType(type))
- return sizeof(WebKit::WebTouchEvent);
- if (WebKit::WebInputEvent::isGestureEventType(type))
- return sizeof(WebKit::WebGestureEvent);
- NOTREACHED() << "Unknown webkit event type " << type;
- return 0;
-}
-
-} // namespace
-
namespace IPC {
void ParamTraits<net::IPEndPoint>::Write(Message* m, const param_type& p) {
@@ -81,7 +63,7 @@ bool ParamTraits<WebInputEventPointer>::Read(const Message* m,
NOTREACHED();
return false;
}
- if (data_length < static_cast<int>(sizeof(WebKit::WebInputEvent))) {
+ if (data_length < static_cast<int>(sizeof(blink::WebInputEvent))) {
NOTREACHED();
return false;
}
@@ -91,7 +73,9 @@ bool ParamTraits<WebInputEventPointer>::Read(const Message* m,
NOTREACHED();
return false;
}
- if (data_length != WebInputEventSizeForType(event->type)) {
+ const size_t expected_size_for_type =
+ content::WebInputEventTraits::GetSize(event->type);
+ if (data_length != static_cast<int>(expected_size_for_type)) {
NOTREACHED();
return false;
}
diff --git a/chromium/content/common/content_param_traits.h b/chromium/content/common/content_param_traits.h
index 5a1e5fa00a6..d4bc359863e 100644
--- a/chromium/content/common/content_param_traits.h
+++ b/chromium/content/common/content_param_traits.h
@@ -58,7 +58,7 @@ struct ParamTraits<WebCursor> {
}
};
-typedef const WebKit::WebInputEvent* WebInputEventPointer;
+typedef const blink::WebInputEvent* WebInputEventPointer;
template <>
struct ParamTraits<WebInputEventPointer> {
typedef WebInputEventPointer param_type;
diff --git a/chromium/content/common/content_param_traits_macros.h b/chromium/content/common/content_param_traits_macros.h
index ef56f2663b6..f54b071792b 100644
--- a/chromium/content/common/content_param_traits_macros.h
+++ b/chromium/content/common/content_param_traits_macros.h
@@ -18,7 +18,7 @@
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
IPC_ENUM_TRAITS(ResourceType::Type)
-IPC_ENUM_TRAITS(WebKit::WebInputEvent::Type)
+IPC_ENUM_TRAITS(blink::WebInputEvent::Type)
IPC_ENUM_TRAITS(ui::LatencyComponentType)
IPC_STRUCT_TRAITS_BEGIN(ui::LatencyInfo::LatencyComponent)
@@ -29,7 +29,8 @@ IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(ui::LatencyInfo)
IPC_STRUCT_TRAITS_MEMBER(latency_components)
- IPC_STRUCT_TRAITS_MEMBER(swap_timestamp)
+ IPC_STRUCT_TRAITS_MEMBER(trace_id)
+ IPC_STRUCT_TRAITS_MEMBER(terminated)
IPC_STRUCT_TRAITS_END()
#endif // CONTENT_COMMON_CONTENT_PARAM_TRAITS_MACROS_H_
diff --git a/chromium/content/common/database_messages.h b/chromium/content/common/database_messages.h
index 2a209470dc3..849b34794ec 100644
--- a/chromium/content/common/database_messages.h
+++ b/chromium/content/common/database_messages.h
@@ -15,7 +15,7 @@
// Notifies the child process of the new database size
IPC_MESSAGE_CONTROL3(DatabaseMsg_UpdateSize,
std::string /* the origin */,
- string16 /* the database name */,
+ base::string16 /* the database name */,
int64 /* the new database size */)
// Notifies the child process of the new space available
@@ -30,30 +30,30 @@ IPC_MESSAGE_CONTROL1(DatabaseMsg_ResetSpaceAvailable,
// Asks the child process to close a database immediately
IPC_MESSAGE_CONTROL2(DatabaseMsg_CloseImmediately,
std::string /* the origin */,
- string16 /* the database name */)
+ base::string16 /* the database name */)
// Database messages sent from the renderer to the browser.
// Asks the browser process to open a DB file with the given name.
IPC_SYNC_MESSAGE_CONTROL2_1(DatabaseHostMsg_OpenFile,
- string16 /* vfs file name */,
+ base::string16 /* vfs file name */,
int /* desired flags */,
IPC::PlatformFileForTransit /* file_handle */)
// Asks the browser process to delete a DB file
IPC_SYNC_MESSAGE_CONTROL2_1(DatabaseHostMsg_DeleteFile,
- string16 /* vfs file name */,
+ base::string16 /* vfs file name */,
bool /* whether or not to sync the directory */,
int /* SQLite error code */)
// Asks the browser process to return the attributes of a DB file
IPC_SYNC_MESSAGE_CONTROL1_1(DatabaseHostMsg_GetFileAttributes,
- string16 /* vfs file name */,
+ base::string16 /* vfs file name */,
int32 /* the attributes for the given DB file */)
// Asks the browser process to return the size of a DB file
IPC_SYNC_MESSAGE_CONTROL1_1(DatabaseHostMsg_GetFileSize,
- string16 /* vfs file name */,
+ base::string16 /* vfs file name */,
int64 /* the size of the given DB file */)
// Asks the browser process for the amount of space available to an origin
@@ -64,22 +64,22 @@ IPC_SYNC_MESSAGE_CONTROL1_1(DatabaseHostMsg_GetSpaceAvailable,
// Notifies the browser process that a new database has been opened
IPC_MESSAGE_CONTROL4(DatabaseHostMsg_Opened,
std::string /* origin identifier */,
- string16 /* database name */,
- string16 /* database description */,
+ base::string16 /* database name */,
+ base::string16 /* database description */,
int64 /* estimated size */)
// Notifies the browser process that a database might have been modified
IPC_MESSAGE_CONTROL2(DatabaseHostMsg_Modified,
std::string /* origin identifier */,
- string16 /* database name */)
+ base::string16 /* database name */)
// Notifies the browser process that a database is about to close
IPC_MESSAGE_CONTROL2(DatabaseHostMsg_Closed,
std::string /* origin identifier */,
- string16 /* database name */)
+ base::string16 /* database name */)
// Sent when a sqlite error indicates the database is corrupt.
IPC_MESSAGE_CONTROL3(DatabaseHostMsg_HandleSqliteError,
std::string /* origin identifier */,
- string16 /* database name */,
+ base::string16 /* database name */,
int /* error */)
diff --git a/chromium/content/common/date_time_suggestion.h b/chromium/content/common/date_time_suggestion.h
new file mode 100644
index 00000000000..ce35430ca81
--- /dev/null
+++ b/chromium/content/common/date_time_suggestion.h
@@ -0,0 +1,31 @@
+// 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_COMMON_DATE_TIME_SUGGESTION_H_
+#define CONTENT_COMMON_DATE_TIME_SUGGESTION_H_
+
+#include <vector>
+
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace content {
+
+// Container for information about datalist suggestion for the date/time input
+// control. Keep in sync with DateTimeSuggestion.java
+struct CONTENT_EXPORT DateTimeSuggestion {
+ DateTimeSuggestion() {}
+
+ // The date/time value represented as a double.
+ double value;
+ // The localized value to be shown to the user.
+ base::string16 localized_value;
+ // The label for the suggestion.
+ base::string16 label;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_DATE_TIME_SUGGESTION_H_
diff --git a/chromium/content/common/desktop_notification_messages.h b/chromium/content/common/desktop_notification_messages.h
index 562c22bc65c..6f1f0c4682e 100644
--- a/chromium/content/common/desktop_notification_messages.h
+++ b/chromium/content/common/desktop_notification_messages.h
@@ -12,8 +12,6 @@
IPC_STRUCT_TRAITS_BEGIN(content::ShowDesktopNotificationHostMsgParams)
IPC_STRUCT_TRAITS_MEMBER(origin)
- IPC_STRUCT_TRAITS_MEMBER(is_html)
- IPC_STRUCT_TRAITS_MEMBER(contents_url)
IPC_STRUCT_TRAITS_MEMBER(icon_url)
IPC_STRUCT_TRAITS_MEMBER(title)
IPC_STRUCT_TRAITS_MEMBER(body)
@@ -33,7 +31,7 @@ IPC_MESSAGE_ROUTED1(DesktopNotificationMsg_PostDisplay,
// trying to display a notification.
IPC_MESSAGE_ROUTED2(DesktopNotificationMsg_PostError,
int /* notification_id */,
- string16 /* message */)
+ base::string16 /* message */)
// Informs the renderer that the one if its notifications has closed.
IPC_MESSAGE_ROUTED2(DesktopNotificationMsg_PostClose,
diff --git a/chromium/content/common/device_motion_hardware_buffer.h b/chromium/content/common/device_orientation/device_motion_hardware_buffer.h
index 0ff855a0a81..71282290be5 100644
--- a/chromium/content/common/device_motion_hardware_buffer.h
+++ b/chromium/content/common/device_orientation/device_motion_hardware_buffer.h
@@ -2,18 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_DEVICE_MOTION_HARDWARE_BUFFER_H_
-#define CONTENT_COMMON_DEVICE_MOTION_HARDWARE_BUFFER_H_
+#ifndef CONTENT_COMMON_DEVICE_ORIENTATION_DEVICE_MOTION_HARDWARE_BUFFER_H_
+#define CONTENT_COMMON_DEVICE_ORIENTATION_DEVICE_MOTION_HARDWARE_BUFFER_H_
#include "content/common/shared_memory_seqlock_buffer.h"
#include "third_party/WebKit/public/platform/WebDeviceMotionData.h"
-// TODO(timvolodine): move this file to content/common/device_orientation/.
namespace content {
-typedef SharedMemorySeqLockBuffer<WebKit::WebDeviceMotionData>
+typedef SharedMemorySeqLockBuffer<blink::WebDeviceMotionData>
DeviceMotionHardwareBuffer;
} // namespace content
-#endif // CONTENT_COMMON_DEVICE_MOTION_HARDWARE_BUFFER_H_
+#endif // CONTENT_COMMON_DEVICE_ORIENTATION_DEVICE_MOTION_HARDWARE_BUFFER_H_
diff --git a/chromium/content/common/device_orientation/device_motion_messages.h b/chromium/content/common/device_orientation/device_motion_messages.h
index 657d3d70138..4f8435d6ced 100644
--- a/chromium/content/common/device_orientation/device_motion_messages.h
+++ b/chromium/content/common/device_orientation/device_motion_messages.h
@@ -12,14 +12,17 @@
#define IPC_MESSAGE_START DeviceMotionMsgStart
-// Messages sent from the renderer to the browser.
-
-// Asks the browser process to start polling, and return a shared memory
-// handles that will hold the data from the hardware. See
-// device_motion_hardware_buffer.h for a description of how synchronization is
-// handled. The number of Starts should match the number of Stops.
+// Asks the browser process to activate Device Motion sensors if necessary.
IPC_MESSAGE_CONTROL0(DeviceMotionHostMsg_StartPolling)
+
+// The browser process asynchronously returns the shared memory handle that will
+// hold the data from the hardware sensors.
+// See device_motion_hardware_buffer.h for a description of how
+// synchronization is handled.
IPC_MESSAGE_CONTROL1(DeviceMotionMsg_DidStartPolling,
base::SharedMemoryHandle /* handle */)
+// Notifies the browser process that the renderer process is not using the
+// Device Motion data anymore. The number of Starts should match the number
+// of Stops.
IPC_MESSAGE_CONTROL0(DeviceMotionHostMsg_StopPolling)
diff --git a/chromium/content/common/device_orientation/device_orientation_hardware_buffer.h b/chromium/content/common/device_orientation/device_orientation_hardware_buffer.h
index c1dc831881d..0d43bb54f44 100644
--- a/chromium/content/common/device_orientation/device_orientation_hardware_buffer.h
+++ b/chromium/content/common/device_orientation/device_orientation_hardware_buffer.h
@@ -10,7 +10,7 @@
namespace content {
-typedef SharedMemorySeqLockBuffer<WebKit::WebDeviceOrientationData>
+typedef SharedMemorySeqLockBuffer<blink::WebDeviceOrientationData>
DeviceOrientationHardwareBuffer;
} // namespace content
diff --git a/chromium/content/common/device_orientation/device_orientation_messages.h b/chromium/content/common/device_orientation/device_orientation_messages.h
index f4114dfb93e..43406c6be25 100644
--- a/chromium/content/common/device_orientation/device_orientation_messages.h
+++ b/chromium/content/common/device_orientation/device_orientation_messages.h
@@ -10,45 +10,17 @@
#define IPC_MESSAGE_START DeviceOrientationMsgStart
-// Messages sent from the renderer to the browser.
-
-// Asks the browser process to start polling, and return a shared memory
-// handle that will hold the data from the hardware. See
-// device_orientation_hardware_buffer.h for a description of how synchronization
-// is handled. The number of Starts should match the number of Stops.
+// Asks the browser process to activate Device Orientation sensors if necessary.
IPC_MESSAGE_CONTROL0(DeviceOrientationHostMsg_StartPolling)
+
+// The browser process asynchronously returns the shared memory handle that will
+// hold the data from the hardware sensors.
+// See device_orientation_hardware_buffer.h for a description of how
+// synchronization is handled.
IPC_MESSAGE_CONTROL1(DeviceOrientationMsg_DidStartPolling,
base::SharedMemoryHandle /* handle */)
+// Notifies the browser process that the renderer process is not using the
+// Device Orientation data anymore. The number of Starts should match the
+// number of Stops.
IPC_MESSAGE_CONTROL0(DeviceOrientationHostMsg_StopPolling)
-
-// TODO(timvolodine): remove the methods below once the shared memory
-// Device Orientation is implemented.
-
-IPC_STRUCT_BEGIN(DeviceOrientationMsg_Updated_Params)
- // These fields have the same meaning as in content::Orientation.
- IPC_STRUCT_MEMBER(bool, can_provide_alpha)
- IPC_STRUCT_MEMBER(double, alpha)
- IPC_STRUCT_MEMBER(bool, can_provide_beta)
- IPC_STRUCT_MEMBER(double, beta)
- IPC_STRUCT_MEMBER(bool, can_provide_gamma)
- IPC_STRUCT_MEMBER(double, gamma)
- IPC_STRUCT_MEMBER(bool, can_provide_absolute)
- IPC_STRUCT_MEMBER(bool, absolute)
-IPC_STRUCT_END()
-
-// Messages sent from the browser to the renderer.
-
-// Notification that the device's orientation has changed.
-IPC_MESSAGE_ROUTED1(DeviceOrientationMsg_Updated,
- DeviceOrientationMsg_Updated_Params)
-
-// Messages sent from the renderer to the browser.
-
-// A RenderView requests to start receiving device orientation updates.
-IPC_MESSAGE_CONTROL1(DeviceOrientationHostMsg_StartUpdating,
- int /* render_view_id */)
-
-// A RenderView requests to stop receiving device orientation updates.
-IPC_MESSAGE_CONTROL1(DeviceOrientationHostMsg_StopUpdating,
- int /* render_view_id */)
diff --git a/chromium/content/common/devtools_messages.h b/chromium/content/common/devtools_messages.h
index b8d4c7e843d..cd4c4b51ddf 100644
--- a/chromium/content/common/devtools_messages.h
+++ b/chromium/content/common/devtools_messages.h
@@ -122,6 +122,19 @@ IPC_MESSAGE_ROUTED0(DevToolsHostMsg_ClearBrowserCache)
// Clears browser cookies.
IPC_MESSAGE_ROUTED0(DevToolsHostMsg_ClearBrowserCookies)
+//-----------------------------------------------------------------------------
+// These are messages sent from the GPU process to the inspected renderer.
+
+IPC_STRUCT_BEGIN(GpuTaskInfo)
+ IPC_STRUCT_MEMBER(double, timestamp)
+ IPC_STRUCT_MEMBER(int, phase)
+ IPC_STRUCT_MEMBER(bool, foreign)
+ IPC_STRUCT_MEMBER(uint64, used_gpu_memory_bytes)
+IPC_STRUCT_END()
+
+// Recorded events are passed in chunks to the renderer process.
+IPC_MESSAGE_ROUTED1(DevToolsAgentMsg_GpuTasksChunk,
+ std::vector<GpuTaskInfo> /* gpu_tasks */)
//-----------------------------------------------------------------------------
// These are messages sent from the inspected page renderer to the worker
diff --git a/chromium/content/common/dom_storage/dom_storage_messages.h b/chromium/content/common/dom_storage/dom_storage_messages.h
index 11c05e8ff9b..2cf46e17681 100644
--- a/chromium/content/common/dom_storage/dom_storage_messages.h
+++ b/chromium/content/common/dom_storage/dom_storage_messages.h
@@ -38,7 +38,7 @@ IPC_STRUCT_BEGIN(DOMStorageMsg_Event_Params)
IPC_STRUCT_MEMBER(int64, namespace_id)
IPC_STRUCT_END()
-IPC_ENUM_TRAITS(WebKit::WebStorageArea::Result)
+IPC_ENUM_TRAITS(blink::WebStorageArea::Result)
// DOM Storage messages sent from the browser to the renderer.
@@ -52,6 +52,11 @@ IPC_MESSAGE_CONTROL1(DOMStorageMsg_Event,
IPC_MESSAGE_CONTROL1(DOMStorageMsg_AsyncOperationComplete,
bool /* success */)
+// Notification instructing the renderer to refresh all cached values for
+// the given namespace.
+IPC_MESSAGE_CONTROL1(DOMStorageMsg_ResetCachedValues,
+ int64 /* namespace_id */)
+
// DOM Storage messages sent from the renderer to the browser.
// Note: The 'connection_id' must be the first parameter in these message.
@@ -67,23 +72,32 @@ IPC_MESSAGE_CONTROL1(DOMStorageHostMsg_CloseStorageArea,
// Retrieves the set of key/value pairs for the area. Used to prime
// the renderer-side cache. A completion notification is sent in response.
-IPC_SYNC_MESSAGE_CONTROL1_1(DOMStorageHostMsg_LoadStorageArea,
+// The response will also indicate whether the renderer should send
+// messagse to the browser for get operations for logging purposes.
+IPC_SYNC_MESSAGE_CONTROL1_2(DOMStorageHostMsg_LoadStorageArea,
int /* connection_id */,
- content::DOMStorageValuesMap)
+ content::DOMStorageValuesMap,
+ bool /* send_log_get_messages */)
// Set a value that's associated with a key in a storage area.
// A completion notification is sent in response.
IPC_MESSAGE_CONTROL4(DOMStorageHostMsg_SetItem,
int /* connection_id */,
- string16 /* key */,
- string16 /* value */,
+ base::string16 /* key */,
+ base::string16 /* value */,
GURL /* page_url */)
+// Logs that a get operation was performed on a key/value pair.
+IPC_MESSAGE_CONTROL3(DOMStorageHostMsg_LogGetItem,
+ int /* connection_id */,
+ base::string16 /* key */,
+ base::NullableString16 /* value */)
+
// Remove the value associated with a key in a storage area.
// A completion notification is sent in response.
IPC_MESSAGE_CONTROL3(DOMStorageHostMsg_RemoveItem,
int /* connection_id */,
- string16 /* key */,
+ base::string16 /* key */,
GURL /* page_url */)
// Clear the storage area. A completion notification is sent in response.
diff --git a/chromium/content/common/drag_messages.h b/chromium/content/common/drag_messages.h
index 3e2147886e3..1da3c7232f3 100644
--- a/chromium/content/common/drag_messages.h
+++ b/chromium/content/common/drag_messages.h
@@ -22,13 +22,13 @@ IPC_MESSAGE_ROUTED5(DragMsg_TargetDragEnter,
content::DropData /* drop_data */,
gfx::Point /* client_pt */,
gfx::Point /* screen_pt */,
- WebKit::WebDragOperationsMask /* ops_allowed */,
+ blink::WebDragOperationsMask /* ops_allowed */,
int /* key_modifiers */)
IPC_MESSAGE_ROUTED4(DragMsg_TargetDragOver,
gfx::Point /* client_pt */,
gfx::Point /* screen_pt */,
- WebKit::WebDragOperationsMask /* ops_allowed */,
+ blink::WebDragOperationsMask /* ops_allowed */,
int /* key_modifiers */)
IPC_MESSAGE_ROUTED0(DragMsg_TargetDragLeave)
@@ -44,7 +44,7 @@ IPC_MESSAGE_ROUTED4(DragMsg_SourceEndedOrMoved,
gfx::Point /* client_pt */,
gfx::Point /* screen_pt */,
bool /* ended */,
- WebKit::WebDragOperation /* drag_operation */)
+ blink::WebDragOperation /* drag_operation */)
// Notifies the renderer that the system DoDragDrop call has ended.
IPC_MESSAGE_ROUTED0(DragMsg_SourceSystemDragEnded)
@@ -57,7 +57,7 @@ IPC_MESSAGE_ROUTED0(DragMsg_SourceSystemDragEnded)
// drag session at the OS level.
IPC_MESSAGE_ROUTED5(DragHostMsg_StartDragging,
content::DropData /* drop_data */,
- WebKit::WebDragOperationsMask /* ops_allowed */,
+ blink::WebDragOperationsMask /* ops_allowed */,
SkBitmap /* image */,
gfx::Vector2d /* image_offset */,
content::DragEventSourceInfo /* event_info */)
@@ -65,7 +65,7 @@ IPC_MESSAGE_ROUTED5(DragHostMsg_StartDragging,
// The page wants to update the mouse cursor during a drag & drop operation.
// |is_drop_target| is true if the mouse is over a valid drop target.
IPC_MESSAGE_ROUTED1(DragHostMsg_UpdateDragCursor,
- WebKit::WebDragOperation /* drag_operation */)
+ blink::WebDragOperation /* drag_operation */)
// Notifies the host that the renderer finished a drop operation.
IPC_MESSAGE_ROUTED0(DragHostMsg_TargetDrop_ACK)
diff --git a/chromium/content/common/drag_traits.h b/chromium/content/common/drag_traits.h
index 87d52ffd4c4..e462680d34f 100644
--- a/chromium/content/common/drag_traits.h
+++ b/chromium/content/common/drag_traits.h
@@ -11,7 +11,7 @@
#define IPC_MESSAGE_START DragMsgStart
-IPC_ENUM_TRAITS(WebKit::WebDragOperation)
+IPC_ENUM_TRAITS(blink::WebDragOperation)
IPC_STRUCT_TRAITS_BEGIN(content::DropData::FileInfo)
IPC_STRUCT_TRAITS_MEMBER(path)
diff --git a/chromium/content/common/fileapi/OWNERS b/chromium/content/common/fileapi/OWNERS
index 4db30b6cede..76dd015b4ff 100644
--- a/chromium/content/common/fileapi/OWNERS
+++ b/chromium/content/common/fileapi/OWNERS
@@ -9,6 +9,5 @@ per-file *_messages*.h=cdn@chromium.org
per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
per-file *_messages*.h=kenrb@chromium.org
diff --git a/chromium/content/common/fileapi/file_system_messages.h b/chromium/content/common/fileapi/file_system_messages.h
index 191bf9d96f4..727c6de54e4 100644
--- a/chromium/content/common/fileapi/file_system_messages.h
+++ b/chromium/content/common/fileapi/file_system_messages.h
@@ -74,12 +74,10 @@ IPC_MESSAGE_CONTROL2(FileSystemMsg_DidFail,
// File system messages sent from the child process to the browser.
// WebFrameClient::openFileSystem() message.
-IPC_MESSAGE_CONTROL5(FileSystemHostMsg_Open,
+IPC_MESSAGE_CONTROL3(FileSystemHostMsg_OpenFileSystem,
int /* request_id */,
GURL /* origin_url */,
- fileapi::FileSystemType /* type */,
- int64 /* requested_size */,
- bool /* create */)
+ fileapi::FileSystemType /* type */)
// WevFrameClient::resolveURL() message.
IPC_MESSAGE_CONTROL2(FileSystemHostMsg_ResolveURL,
@@ -105,7 +103,7 @@ IPC_MESSAGE_CONTROL3(FileSystemHostMsg_Copy,
GURL /* dest path */)
// WebFileSystem::remove() message.
-IPC_MESSAGE_CONTROL3(FileSystemMsg_Remove,
+IPC_MESSAGE_CONTROL3(FileSystemHostMsg_Remove,
int /* request_id */,
GURL /* path */,
bool /* recursive */)
@@ -166,16 +164,6 @@ IPC_MESSAGE_CONTROL2(FileSystemHostMsg_CancelWrite,
int /* request id */,
int /* id of request to cancel */)
-// Pepper's OpenFile message.
-IPC_MESSAGE_CONTROL3(FileSystemHostMsg_OpenPepperFile,
- int /* request id */,
- GURL /* file path */,
- int /* pp_open_flags */)
-
-// Pepper's NotifyCloseFile message.
-IPC_MESSAGE_CONTROL1(FileSystemHostMsg_NotifyCloseFile,
- int /* file_open_id */)
-
// WebFileSystem::createSnapshotFileAndReadMetadata() message.
IPC_MESSAGE_CONTROL2(FileSystemHostMsg_CreateSnapshotFile,
int /* request_id */,
@@ -191,11 +179,3 @@ IPC_MESSAGE_CONTROL1(FileSystemHostMsg_DidReceiveSnapshotFile,
IPC_SYNC_MESSAGE_CONTROL1_1(FileSystemHostMsg_SyncGetPlatformPath,
GURL /* file path */,
base::FilePath /* platform_path */)
-
-// Pre- and post-update notifications for ppapi implementation.
-IPC_MESSAGE_CONTROL1(FileSystemHostMsg_WillUpdate,
- GURL /* file_path */)
-
-IPC_MESSAGE_CONTROL2(FileSystemHostMsg_DidUpdate,
- GURL /* file_path */,
- int64 /* delta */)
diff --git a/chromium/content/common/fileapi/webblob_messages.h b/chromium/content/common/fileapi/webblob_messages.h
index 92a98164ca5..b4399e7f472 100644
--- a/chromium/content/common/fileapi/webblob_messages.h
+++ b/chromium/content/common/fileapi/webblob_messages.h
@@ -39,18 +39,6 @@ IPC_MESSAGE_CONTROL2(BlobHostMsg_RegisterPublicURL,
IPC_MESSAGE_CONTROL1(BlobHostMsg_RevokePublicURL,
GURL)
-// Temporary support for mapping old style blobUrls to new style uuids.
-IPC_MESSAGE_CONTROL2(BlobHostMsg_DeprecatedRegisterBlobURL,
- GURL,
- std::string /* uuid */)
-IPC_MESSAGE_CONTROL2(BlobHostMsg_DeprecatedCloneBlobURL,
- GURL,
- GURL)
-IPC_MESSAGE_CONTROL1(BlobHostMsg_DeprecatedRevokeBlobURL,
- GURL)
-
-
-
// Stream messages sent from the renderer to the browser.
// Registers a stream as being built.
diff --git a/chromium/content/common/font_cache_dispatcher_win.cc b/chromium/content/common/font_cache_dispatcher_win.cc
index d6d59ded084..47c9c122404 100644
--- a/chromium/content/common/font_cache_dispatcher_win.cc
+++ b/chromium/content/common/font_cache_dispatcher_win.cc
@@ -13,7 +13,7 @@
namespace content {
namespace {
-typedef std::vector<string16> FontNameVector;
+typedef std::vector<base::string16> FontNameVector;
typedef std::map<FontCacheDispatcher*, FontNameVector> DispatcherToFontNames;
class FontCache {
@@ -23,7 +23,7 @@ class FontCache {
}
void PreCacheFont(const LOGFONT& font, FontCacheDispatcher* dispatcher) {
- typedef std::map<string16, FontCache::CacheElement> FontNameToElement;
+ typedef std::map<base::string16, FontCache::CacheElement> FontNameToElement;
base::AutoLock lock(mutex_);
@@ -41,7 +41,7 @@ class FontCache {
BOOL ret = GetTextMetrics(hdc, &tm);
DCHECK(ret);
- string16 font_name = font.lfFaceName;
+ base::string16 font_name = font.lfFaceName;
int ref_count_inc = 1;
FontNameVector::iterator it =
std::find(dispatcher_font_map_[dispatcher].begin(),
@@ -68,7 +68,7 @@ class FontCache {
}
void ReleaseCachedFonts(FontCacheDispatcher* dispatcher) {
- typedef std::map<string16, FontCache::CacheElement> FontNameToElement;
+ typedef std::map<base::string16, FontCache::CacheElement> FontNameToElement;
base::AutoLock lock(mutex_);
@@ -125,7 +125,7 @@ class FontCache {
FontCache() {
}
- std::map<string16, CacheElement> cache_;
+ std::map<base::string16, CacheElement> cache_;
DispatcherToFontNames dispatcher_font_map_;
base::Lock mutex_;
diff --git a/chromium/content/common/font_config_ipc_linux.cc b/chromium/content/common/font_config_ipc_linux.cc
index b61a8cc0bbd..2d976c48b09 100644
--- a/chromium/content/common/font_config_ipc_linux.cc
+++ b/chromium/content/common/font_config_ipc_linux.cc
@@ -33,7 +33,7 @@ SkStream* StreamFromFD(int fd) {
}
void CloseFD(int fd) {
- int err = HANDLE_EINTR(close(fd));
+ int err = IGNORE_EINTR(close(fd));
DCHECK(!err);
}
diff --git a/chromium/content/common/font_list_mac.mm b/chromium/content/common/font_list_mac.mm
index 4ffb3de1804..64a54cda7f4 100644
--- a/chromium/content/common/font_list_mac.mm
+++ b/chromium/content/common/font_list_mac.mm
@@ -21,9 +21,9 @@ scoped_ptr<base::ListValue> GetFontList_SlowBlocking() {
NSString* localized_family_name =
[fontManager localizedNameForFamily:family_name face:nil];
base::ListValue* font_item = new base::ListValue();
- string16 family = base::SysNSStringToUTF16(family_name);
+ base::string16 family = base::SysNSStringToUTF16(family_name);
font_item->Append(new base::StringValue(family));
- string16 loc_family = base::SysNSStringToUTF16(localized_family_name);
+ base::string16 loc_family = base::SysNSStringToUTF16(localized_family_name);
font_item->Append(new base::StringValue(loc_family));
font_list->Append(font_item);
}
diff --git a/chromium/content/common/font_list_ozone.cc b/chromium/content/common/font_list_ozone.cc
new file mode 100644
index 00000000000..b0a542dcb46
--- /dev/null
+++ b/chromium/content/common/font_list_ozone.cc
@@ -0,0 +1,15 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/font_list.h"
+
+#include "base/values.h"
+
+namespace content {
+
+scoped_ptr<ListValue> GetFontList_SlowBlocking() {
+ return scoped_ptr<ListValue>(new ListValue);
+}
+
+} // namespace content
diff --git a/chromium/content/common/font_list_win.cc b/chromium/content/common/font_list_win.cc
index 0eb84ed7237..bc6c1dcd1ed 100644
--- a/chromium/content/common/font_list_win.cc
+++ b/chromium/content/common/font_list_win.cc
@@ -17,12 +17,12 @@ static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW* logical_font,
NEWTEXTMETRICEXW* physical_font,
DWORD font_type,
LPARAM lparam) {
- std::set<string16>* font_names =
- reinterpret_cast<std::set<string16>*>(lparam);
+ std::set<base::string16>* font_names =
+ reinterpret_cast<std::set<base::string16>*>(lparam);
if (font_names) {
const LOGFONTW& lf = logical_font->elfLogFont;
if (lf.lfFaceName[0] && lf.lfFaceName[0] != '@') {
- string16 face_name(lf.lfFaceName);
+ base::string16 face_name(lf.lfFaceName);
font_names->insert(face_name);
}
}
@@ -30,7 +30,7 @@ static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW* logical_font,
}
scoped_ptr<base::ListValue> GetFontList_SlowBlocking() {
- std::set<string16> font_names;
+ std::set<base::string16> font_names;
LOGFONTW logfont;
memset(&logfont, 0, sizeof(logfont));
@@ -42,7 +42,7 @@ scoped_ptr<base::ListValue> GetFontList_SlowBlocking() {
::ReleaseDC(NULL, hdc);
scoped_ptr<base::ListValue> font_list(new base::ListValue);
- std::set<string16>::iterator iter;
+ std::set<base::string16>::iterator iter;
for (iter = font_names.begin(); iter != font_names.end(); ++iter) {
base::ListValue* font_item = new base::ListValue();
font_item->Append(new base::StringValue(*iter));
diff --git a/chromium/content/common/frame_messages.h b/chromium/content/common/frame_messages.h
new file mode 100644
index 00000000000..87f769b5fd0
--- /dev/null
+++ b/chromium/content/common/frame_messages.h
@@ -0,0 +1,87 @@
+// 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.
+
+// IPC messages for interacting with frames.
+// Multiply-included message file, hence no include guard.
+
+#include "content/common/content_export.h"
+#include "content/public/common/common_param_traits.h"
+#include "ipc/ipc_message_macros.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+
+#define IPC_MESSAGE_START FrameMsgStart
+
+// Sent by the renderer when a child frame is created in the renderer. The
+// |parent_frame_id| and |frame_id| are NOT routing ids. They are
+// renderer-allocated identifiers used for tracking a frame's creation.
+//
+// Each of these messages will have a corresponding FrameHostMsg_Detach message
+// sent when the frame is detached from the DOM.
+//
+// TOOD(ajwong): replace parent_render_frame_id and frame_id with just the
+// routing ids.
+IPC_SYNC_MESSAGE_CONTROL4_1(FrameHostMsg_CreateChildFrame,
+ int32 /* parent_render_frame_id */,
+ int64 /* parent_frame_id */,
+ int64 /* frame_id */,
+ std::string /* frame_name */,
+ int /* new_render_frame_id */)
+
+// Sent by the renderer to the parent RenderFrameHost when a child frame is
+// detached from the DOM.
+IPC_MESSAGE_ROUTED2(FrameHostMsg_Detach,
+ int64 /* parent_frame_id */,
+ int64 /* frame_id */)
+
+// Sent when the renderer starts a provisional load for a frame.
+IPC_MESSAGE_ROUTED4(FrameHostMsg_DidStartProvisionalLoadForFrame,
+ int64 /* frame_id */,
+ int64 /* parent_frame_id */,
+ bool /* true if it is the main frame */,
+ GURL /* url */)
+
+// Sent to the browser when the renderer detects it is blocked on a pepper
+// plugin message for too long. This is also sent when it becomes unhung
+// (according to the value of is_hung). The browser can give the user the
+// option of killing the plugin.
+IPC_MESSAGE_ROUTED3(FrameHostMsg_PepperPluginHung,
+ int /* plugin_child_id */,
+ base::FilePath /* path */,
+ bool /* is_hung */)
+
+// Sent by the renderer process to indicate that a plugin instance has crashed.
+// Note: |plugin_pid| should not be trusted. The corresponding process has
+// probably died. Moreover, the ID may have been reused by a new process. Any
+// usage other than displaying it in a prompt to the user is very likely to be
+// wrong.
+IPC_MESSAGE_ROUTED2(FrameHostMsg_PluginCrashed,
+ base::FilePath /* plugin_path */,
+ base::ProcessId /* plugin_pid */)
+
+// Return information about a plugin for the given URL and MIME
+// type. If there is no matching plugin, |found| is false.
+// |actual_mime_type| is the actual mime type supported by the
+// found plugin.
+IPC_SYNC_MESSAGE_CONTROL4_3(FrameHostMsg_GetPluginInfo,
+ int /* render_frame_id */,
+ GURL /* url */,
+ GURL /* page_url */,
+ std::string /* mime_type */,
+ bool /* found */,
+ content::WebPluginInfo /* plugin info */,
+ std::string /* actual_mime_type */)
+
+// A renderer sends this to the browser process when it wants to
+// create a plugin. The browser will create the plugin process if
+// necessary, and will return a handle to the channel on success.
+// On error an empty string is returned.
+IPC_SYNC_MESSAGE_CONTROL4_2(FrameHostMsg_OpenChannelToPlugin,
+ int /* render_frame_id */,
+ GURL /* url */,
+ GURL /* page_url */,
+ std::string /* mime_type */,
+ IPC::ChannelHandle /* channel_handle */,
+ content::WebPluginInfo /* info */)
diff --git a/chromium/content/common/gamepad_hardware_buffer.h b/chromium/content/common/gamepad_hardware_buffer.h
index 5559d44e68d..4d3182525a3 100644
--- a/chromium/content/common/gamepad_hardware_buffer.h
+++ b/chromium/content/common/gamepad_hardware_buffer.h
@@ -24,9 +24,9 @@ contention is detected by using the associated SeqLock.
*/
struct GamepadHardwareBuffer {
- // FIXME: Use the generic SharedMemorySeqLockBuffer<WebKit::WebGamepads>.
+ // FIXME: Use the generic SharedMemorySeqLockBuffer<blink::WebGamepads>.
OneWriterSeqLock sequence;
- WebKit::WebGamepads buffer;
+ blink::WebGamepads buffer;
};
} // namespace content
diff --git a/chromium/content/common/gamepad_user_gesture.cc b/chromium/content/common/gamepad_user_gesture.cc
index 037a3402686..7b530b1ecf4 100644
--- a/chromium/content/common/gamepad_user_gesture.cc
+++ b/chromium/content/common/gamepad_user_gesture.cc
@@ -10,9 +10,9 @@
namespace content {
-bool GamepadsHaveUserGesture(const WebKit::WebGamepads& gamepads) {
- for (unsigned i = 0; i < WebKit::WebGamepads::itemsLengthCap; i++) {
- const WebKit::WebGamepad& pad = gamepads.items[i];
+bool GamepadsHaveUserGesture(const blink::WebGamepads& gamepads) {
+ for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; i++) {
+ const blink::WebGamepad& pad = gamepads.items[i];
// If the device is physically connected, then check the primary 4 buttons
// to see if there is currently an intentional user action.
diff --git a/chromium/content/common/gamepad_user_gesture.h b/chromium/content/common/gamepad_user_gesture.h
index d17c69cf5b6..6dbd2bf083a 100644
--- a/chromium/content/common/gamepad_user_gesture.h
+++ b/chromium/content/common/gamepad_user_gesture.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_COMMON_GAMEPAD_USER_GESTURE_H_
#define CONTENT_COMMON_GAMEPAD_USER_GESTURE_H_
-namespace WebKit {
+namespace blink {
class WebGamepads;
}
@@ -13,7 +13,7 @@ namespace content {
// Returns true if any of the gamepads have a button pressed that would be
// considerd a user gesture for interaction.
-bool GamepadsHaveUserGesture(const WebKit::WebGamepads& gamepads);
+bool GamepadsHaveUserGesture(const blink::WebGamepads& gamepads);
} // namespace content
diff --git a/chromium/content/common/gpu/OWNERS b/chromium/content/common/gpu/OWNERS
index 41d07ed7999..ee4bfc1cee4 100644
--- a/chromium/content/common/gpu/OWNERS
+++ b/chromium/content/common/gpu/OWNERS
@@ -1,4 +1,3 @@
-apatrick@chromium.org
kbr@chromium.org
piman@chromium.org
sievers@chromium.org
diff --git a/chromium/content/common/gpu/client/command_buffer_proxy_impl.cc b/chromium/content/common/gpu/client/command_buffer_proxy_impl.cc
index 90271647069..768b4270393 100644
--- a/chromium/content/common/gpu/client/command_buffer_proxy_impl.cc
+++ b/chromium/content/common/gpu/client/command_buffer_proxy_impl.cc
@@ -10,14 +10,13 @@
#include "base/memory/shared_memory.h"
#include "base/stl_util.h"
#include "content/common/child_process_messages.h"
-#include "content/common/gpu/client/gl_surface_capturer_host.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/gpu/client/gpu_video_decode_accelerator_host.h"
-#include "content/common/gpu/gpu_memory_allocation.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
#include "gpu/command_buffer/common/cmd_buffer_common.h"
#include "gpu/command_buffer/common/command_buffer_shared.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "ui/gfx/size.h"
namespace content {
@@ -99,8 +98,7 @@ void CommandBufferProxyImpl::OnConsoleMessage(
}
void CommandBufferProxyImpl::SetMemoryAllocationChangedCallback(
- const base::Callback<void(const GpuMemoryAllocationForRenderer&)>&
- callback) {
+ const MemoryAllocationChangedCallback& callback) {
if (last_state_.error != gpu::error::kNoError)
return;
@@ -119,7 +117,7 @@ void CommandBufferProxyImpl::RemoveDeletionObserver(
}
void CommandBufferProxyImpl::OnSetMemoryAllocation(
- const GpuMemoryAllocationForRenderer& allocation) {
+ const gpu::MemoryAllocation& allocation) {
if (!memory_allocation_changed_callback_.is_null())
memory_allocation_changed_callback_.Run(allocation);
}
@@ -157,7 +155,8 @@ bool CommandBufferProxyImpl::Initialize() {
return false;
bool result;
- if (!Send(new GpuCommandBufferMsg_Initialize(route_id_, handle, &result))) {
+ if (!Send(new GpuCommandBufferMsg_Initialize(
+ route_id_, handle, &result, &capabilities_))) {
LOG(ERROR) << "Could not send GpuCommandBufferMsg_Initialize.";
return false;
}
@@ -167,6 +166,8 @@ bool CommandBufferProxyImpl::Initialize() {
return false;
}
+ capabilities_.map_image = true;
+
return true;
}
@@ -367,44 +368,84 @@ void CommandBufferProxyImpl::SetContextLostReason(
NOTREACHED();
}
-int CommandBufferProxyImpl::GetRouteID() const {
- return route_id_;
+gpu::Capabilities CommandBufferProxyImpl::GetCapabilities() {
+ return capabilities_;
}
-bool CommandBufferProxyImpl::Echo(const base::Closure& callback) {
- if (last_state_.error != gpu::error::kNoError) {
- return false;
- }
+gfx::GpuMemoryBuffer* CommandBufferProxyImpl::CreateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat,
+ int32* id) {
+ *id = -1;
- if (!Send(new GpuCommandBufferMsg_Echo(route_id_,
- GpuCommandBufferMsg_EchoAck(route_id_)))) {
- return false;
- }
+ if (last_state_.error != gpu::error::kNoError)
+ return NULL;
- echo_tasks_.push(callback);
+ int32 new_id = channel_->ReserveGpuMemoryBufferId();
+ DCHECK(gpu_memory_buffers_.find(new_id) == gpu_memory_buffers_.end());
- return true;
-}
+ scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer(
+ channel_->factory()->AllocateGpuMemoryBuffer(width,
+ height,
+ internalformat));
+ if (!gpu_memory_buffer)
+ return NULL;
-bool CommandBufferProxyImpl::SetSurfaceVisible(bool visible) {
- if (last_state_.error != gpu::error::kNoError)
- return false;
+ DCHECK(GpuChannelHost::IsValidGpuMemoryBuffer(
+ gpu_memory_buffer->GetHandle()));
- return Send(new GpuCommandBufferMsg_SetSurfaceVisible(route_id_, visible));
+ // This handle is owned by the GPU process and must be passed to it or it
+ // will leak. In otherwords, do not early out on error between here and the
+ // sending of the RegisterGpuMemoryBuffer IPC below.
+ gfx::GpuMemoryBufferHandle handle =
+ channel_->ShareGpuMemoryBufferToGpuProcess(
+ gpu_memory_buffer->GetHandle());
+
+ if (!Send(new GpuCommandBufferMsg_RegisterGpuMemoryBuffer(
+ route_id_,
+ new_id,
+ handle,
+ width,
+ height,
+ internalformat))) {
+ return NULL;
+ }
+
+ *id = new_id;
+ gpu_memory_buffers_[new_id] = gpu_memory_buffer.release();
+ return gpu_memory_buffers_[new_id];
}
-bool CommandBufferProxyImpl::DiscardBackbuffer() {
+void CommandBufferProxyImpl::DestroyGpuMemoryBuffer(int32 id) {
if (last_state_.error != gpu::error::kNoError)
- return false;
+ return;
- return Send(new GpuCommandBufferMsg_DiscardBackbuffer(route_id_));
+ // Remove the gpu memory buffer from the client side cache.
+ GpuMemoryBufferMap::iterator it = gpu_memory_buffers_.find(id);
+ if (it != gpu_memory_buffers_.end()) {
+ delete it->second;
+ gpu_memory_buffers_.erase(it);
+ }
+
+ Send(new GpuCommandBufferMsg_DestroyGpuMemoryBuffer(route_id_, id));
}
-bool CommandBufferProxyImpl::EnsureBackbuffer() {
- if (last_state_.error != gpu::error::kNoError)
- return false;
+int CommandBufferProxyImpl::GetRouteID() const {
+ return route_id_;
+}
+
+void CommandBufferProxyImpl::Echo(const base::Closure& callback) {
+ if (last_state_.error != gpu::error::kNoError) {
+ return;
+ }
+
+ if (!Send(new GpuCommandBufferMsg_Echo(
+ route_id_, GpuCommandBufferMsg_EchoAck(route_id_)))) {
+ return;
+ }
- return Send(new GpuCommandBufferMsg_EnsureBackbuffer(route_id_));
+ echo_tasks_.push(callback);
}
uint32 CommandBufferProxyImpl::InsertSyncPoint() {
@@ -416,29 +457,25 @@ uint32 CommandBufferProxyImpl::InsertSyncPoint() {
return sync_point;
}
-bool CommandBufferProxyImpl::SignalSyncPoint(uint32 sync_point,
+void CommandBufferProxyImpl::SignalSyncPoint(uint32 sync_point,
const base::Closure& callback) {
- if (last_state_.error != gpu::error::kNoError) {
- return false;
- }
+ if (last_state_.error != gpu::error::kNoError)
+ return;
uint32 signal_id = next_signal_id_++;
if (!Send(new GpuCommandBufferMsg_SignalSyncPoint(route_id_,
sync_point,
signal_id))) {
- return false;
+ return;
}
signal_tasks_.insert(std::make_pair(signal_id, callback));
-
- return true;
}
-bool CommandBufferProxyImpl::SignalQuery(unsigned query,
+void CommandBufferProxyImpl::SignalQuery(uint32 query,
const base::Closure& callback) {
- if (last_state_.error != gpu::error::kNoError) {
- return false;
- }
+ if (last_state_.error != gpu::error::kNoError)
+ return;
// Signal identifiers are hidden, so nobody outside of this class will see
// them. (And thus, they cannot save them.) The IDs themselves only last
@@ -452,14 +489,27 @@ bool CommandBufferProxyImpl::SignalQuery(unsigned query,
if (!Send(new GpuCommandBufferMsg_SignalQuery(route_id_,
query,
signal_id))) {
- return false;
+ return;
}
signal_tasks_.insert(std::make_pair(signal_id, callback));
+}
- return true;
+void CommandBufferProxyImpl::SetSurfaceVisible(bool visible) {
+ if (last_state_.error != gpu::error::kNoError)
+ return;
+
+ Send(new GpuCommandBufferMsg_SetSurfaceVisible(route_id_, visible));
}
+void CommandBufferProxyImpl::SendManagedMemoryStats(
+ const gpu::ManagedMemoryStats& stats) {
+ if (last_state_.error != gpu::error::kNoError)
+ return;
+
+ Send(new GpuCommandBufferMsg_SendClientManagedMemoryStats(route_id_,
+ stats));
+}
bool CommandBufferProxyImpl::GenerateMailboxNames(
unsigned num,
@@ -501,25 +551,6 @@ CommandBufferProxyImpl::CreateVideoDecoder(
return vda.Pass();
}
-scoped_ptr<SurfaceCapturer> CommandBufferProxyImpl::CreateSurfaceCapturer(
- SurfaceCapturer::Client* client) {
- int capturer_route_id;
- scoped_ptr<SurfaceCapturer> capturer;
- if (!Send(new GpuCommandBufferMsg_CreateSurfaceCapturer(
- route_id_, &capturer_route_id))) {
- LOG(ERROR) << "Send(GpuCommandBufferMsg_CreateSurfaceCapturer) failed";
- return capturer.Pass();
- }
-
- if (capturer_route_id < 0) {
- DLOG(ERROR) << "Failed create surface capturer";
- return capturer.Pass();
- }
-
- capturer.reset(new GLSurfaceCapturerHost(capturer_route_id, client, this));
- return capturer.Pass();
-}
-
gpu::error::Error CommandBufferProxyImpl::GetLastError() {
return last_state_.error;
}
@@ -564,13 +595,4 @@ void CommandBufferProxyImpl::TryUpdateState() {
shared_state()->Read(&last_state_);
}
-void CommandBufferProxyImpl::SendManagedMemoryStats(
- const GpuManagedMemoryStats& stats) {
- if (last_state_.error != gpu::error::kNoError)
- return;
-
- Send(new GpuCommandBufferMsg_SendClientManagedMemoryStats(route_id_,
- stats));
-}
-
} // namespace content
diff --git a/chromium/content/common/gpu/client/command_buffer_proxy_impl.h b/chromium/content/common/gpu/client/command_buffer_proxy_impl.h
index a3f6260e66f..b5b272cd15e 100644
--- a/chromium/content/common/gpu/client/command_buffer_proxy_impl.h
+++ b/chromium/content/common/gpu/client/command_buffer_proxy_impl.h
@@ -9,19 +9,16 @@
#include <queue>
#include <string>
-#include "gpu/ipc/command_buffer_proxy.h"
-
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "content/common/gpu/gpu_memory_allocation.h"
-#include "content/common/gpu/gpu_memory_allocation.h"
-#include "content/common/gpu/surface_capturer.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "gpu/command_buffer/common/command_buffer_shared.h"
+#include "gpu/command_buffer/common/gpu_control.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "ipc/ipc_listener.h"
#include "media/video/video_decode_accelerator.h"
#include "ui/events/latency_info.h"
@@ -32,6 +29,10 @@ namespace base {
class SharedMemory;
}
+namespace gfx {
+class GpuMemoryBuffer;
+}
+
namespace gpu {
struct Mailbox;
}
@@ -42,7 +43,8 @@ class GpuChannelHost;
// Client side proxy that forwards messages synchronously to a
// CommandBufferStub.
class CommandBufferProxyImpl
- : public CommandBufferProxy,
+ : public gpu::CommandBuffer,
+ public gpu::GpuControl,
public IPC::Listener,
public base::SupportsWeakPtr<CommandBufferProxyImpl> {
public:
@@ -71,21 +73,10 @@ class CommandBufferProxyImpl
media::VideoCodecProfile profile,
media::VideoDecodeAccelerator::Client* client);
- // Send an IPC message to create a SurfaceCapturer. Returns NULL on failure
- // to create the SurfaceCapturer.
- scoped_ptr<SurfaceCapturer> CreateSurfaceCapturer(
- SurfaceCapturer::Client* client);
-
// IPC::Listener implementation:
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
virtual void OnChannelError() OVERRIDE;
- // CommandBufferProxy implementation:
- virtual int GetRouteID() const OVERRIDE;
- virtual bool Echo(const base::Closure& callback) OVERRIDE;
- virtual bool ProduceFrontBuffer(const gpu::Mailbox& mailbox) OVERRIDE;
- virtual void SetChannelErrorCallback(const base::Closure& callback) OVERRIDE;
-
// CommandBuffer implementation:
virtual bool Initialize() OVERRIDE;
virtual State GetState() OVERRIDE;
@@ -103,37 +94,40 @@ class CommandBufferProxyImpl
virtual void SetParseError(gpu::error::Error error) OVERRIDE;
virtual void SetContextLostReason(
gpu::error::ContextLostReason reason) OVERRIDE;
- virtual uint32 InsertSyncPoint() OVERRIDE;
+ // gpu::GpuControl implementation:
+ virtual gpu::Capabilities GetCapabilities() OVERRIDE;
+ virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat,
+ int32* id) OVERRIDE;
+ virtual void DestroyGpuMemoryBuffer(int32 id) OVERRIDE;
+ virtual bool GenerateMailboxNames(unsigned num,
+ std::vector<gpu::Mailbox>* names) OVERRIDE;
+ virtual uint32 InsertSyncPoint() OVERRIDE;
+ virtual void SignalSyncPoint(uint32 sync_point,
+ const base::Closure& callback) OVERRIDE;
+ virtual void SignalQuery(uint32 query,
+ const base::Closure& callback) OVERRIDE;
+ virtual void SetSurfaceVisible(bool visible) OVERRIDE;
+ virtual void SendManagedMemoryStats(const gpu::ManagedMemoryStats& stats)
+ OVERRIDE;
+ virtual void Echo(const base::Closure& callback) OVERRIDE;
+
+ int GetRouteID() const;
+ bool ProduceFrontBuffer(const gpu::Mailbox& mailbox);
+ void SetChannelErrorCallback(const base::Closure& callback);
+
+ typedef base::Callback<void(const gpu::MemoryAllocation&)>
+ MemoryAllocationChangedCallback;
void SetMemoryAllocationChangedCallback(
- const base::Callback<void(const GpuMemoryAllocationForRenderer&)>&
- callback);
-
+ const MemoryAllocationChangedCallback& callback);
void AddDeletionObserver(DeletionObserver* observer);
void RemoveDeletionObserver(DeletionObserver* observer);
- bool DiscardBackbuffer();
bool EnsureBackbuffer();
- // Makes this command buffer invoke a task when a sync point is reached, or
- // the command buffer that inserted that sync point is destroyed.
- bool SignalSyncPoint(uint32 sync_point,
- const base::Closure& callback);
-
- // Makes this command buffer invoke a task when a query is completed, or
- // the command buffer that inserted that sync point is destroyed or the
- // query was deleted. Should be invoked after endQuery.
- bool SignalQuery(unsigned query, const base::Closure& callback);
-
- // Generates n unique mailbox names that can be used with
- // GL_texture_mailbox_CHROMIUM. Unlike genMailboxCHROMIUM, this IPC is
- // handled only on the GPU process' IO thread, and so is not effectively
- // a finish.
- bool GenerateMailboxNames(unsigned num, std::vector<gpu::Mailbox>* names);
-
- // Sends an IPC message with the new state of surface visibility.
- bool SetSurfaceVisible(bool visible);
-
void SetOnConsoleMessageCallback(
const GpuConsoleMessageCallback& callback);
@@ -145,13 +139,12 @@ class CommandBufferProxyImpl
// CommandBufferProxyImpl implementation.
virtual gpu::error::Error GetLastError() OVERRIDE;
- void SendManagedMemoryStats(const GpuManagedMemoryStats& stats);
-
GpuChannelHost* channel() const { return channel_; }
private:
typedef std::map<int32, gpu::Buffer> TransferBufferMap;
typedef base::hash_map<uint32, base::Closure> SignalTaskMap;
+ typedef std::map<int32, gfx::GpuMemoryBuffer*> GpuMemoryBufferMap;
// Send an IPC message over the GPU channel. This is private to fully
// encapsulate the channel; all callers of this function must explicitly
@@ -163,7 +156,7 @@ class CommandBufferProxyImpl
void OnDestroyed(gpu::error::ContextLostReason reason);
void OnEchoAck();
void OnConsoleMessage(const GPUCommandBufferConsoleMessage& message);
- void OnSetMemoryAllocation(const GpuMemoryAllocationForRenderer& allocation);
+ void OnSetMemoryAllocation(const gpu::MemoryAllocation& allocation);
void OnSignalSyncPointAck(uint32 id);
void OnGenerateMailboxNamesReply(const std::vector<std::string>& names);
@@ -200,8 +193,7 @@ class CommandBufferProxyImpl
base::Closure channel_error_callback_;
- base::Callback<void(const GpuMemoryAllocationForRenderer&)>
- memory_allocation_changed_callback_;
+ MemoryAllocationChangedCallback memory_allocation_changed_callback_;
GpuConsoleMessageCallback console_message_callback_;
@@ -209,6 +201,11 @@ class CommandBufferProxyImpl
uint32 next_signal_id_;
SignalTaskMap signal_tasks_;
+ // Local cache of id to gpu memory buffer mapping.
+ GpuMemoryBufferMap gpu_memory_buffers_;
+
+ gpu::Capabilities capabilities_;
+
DISALLOW_COPY_AND_ASSIGN(CommandBufferProxyImpl);
};
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 c1ecce9c586..359ba4d0edc 100644
--- a/chromium/content/common/gpu/client/context_provider_command_buffer.cc
+++ b/chromium/content/common/gpu/client/context_provider_command_buffer.cc
@@ -8,17 +8,15 @@
#include <vector>
#include "base/callback_helpers.h"
-#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "cc/output/managed_memory_policy.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "webkit/common/gpu/grcontext_for_webgraphicscontext3d.h"
-#include "webkit/common/gpu/managed_memory_policy_convert.h"
namespace content {
class ContextProviderCommandBuffer::LostContextCallbackProxy
- : public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback {
+ : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
public:
explicit LostContextCallbackProxy(ContextProviderCommandBuffer* provider)
: provider_(provider) {
@@ -37,50 +35,6 @@ class ContextProviderCommandBuffer::LostContextCallbackProxy
ContextProviderCommandBuffer* provider_;
};
-class ContextProviderCommandBuffer::SwapBuffersCompleteCallbackProxy
- : public WebKit::WebGraphicsContext3D::
- WebGraphicsSwapBuffersCompleteCallbackCHROMIUM {
- public:
- explicit SwapBuffersCompleteCallbackProxy(
- ContextProviderCommandBuffer* provider)
- : provider_(provider) {
- provider_->context3d_->setSwapBuffersCompleteCallbackCHROMIUM(this);
- }
-
- virtual ~SwapBuffersCompleteCallbackProxy() {
- provider_->context3d_->setSwapBuffersCompleteCallbackCHROMIUM(NULL);
- }
-
- virtual void onSwapBuffersComplete() {
- provider_->OnSwapBuffersComplete();
- }
-
- private:
- ContextProviderCommandBuffer* provider_;
-};
-
-class ContextProviderCommandBuffer::MemoryAllocationCallbackProxy
- : public WebKit::WebGraphicsContext3D::
- WebGraphicsMemoryAllocationChangedCallbackCHROMIUM {
- public:
- explicit MemoryAllocationCallbackProxy(ContextProviderCommandBuffer* provider)
- : provider_(provider) {
- provider_->context3d_->setMemoryAllocationChangedCallbackCHROMIUM(this);
- }
-
- virtual ~MemoryAllocationCallbackProxy() {
- provider_->context3d_->setMemoryAllocationChangedCallbackCHROMIUM(NULL);
- }
-
- virtual void onMemoryAllocationChanged(
- WebKit::WebGraphicsMemoryAllocation allocation) {
- provider_->OnMemoryAllocationChanged(allocation);
- }
-
- private:
- ContextProviderCommandBuffer* provider_;
-};
-
scoped_refptr<ContextProviderCommandBuffer>
ContextProviderCommandBuffer::Create(
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context3d,
@@ -110,8 +64,10 @@ ContextProviderCommandBuffer::~ContextProviderCommandBuffer() {
base::AutoLock lock(main_thread_lock_);
// Destroy references to the context3d_ before leaking it.
- memory_allocation_callback_proxy_.reset();
- swap_buffers_complete_callback_proxy_.reset();
+ if (context3d_->GetCommandBufferProxy()) {
+ context3d_->GetCommandBufferProxy()->SetMemoryAllocationChangedCallback(
+ CommandBufferProxyImpl::MemoryAllocationChangedCallback());
+ }
lost_context_callback_proxy_.reset();
if (leak_on_destroy_) {
@@ -123,8 +79,6 @@ ContextProviderCommandBuffer::~ContextProviderCommandBuffer() {
}
bool ContextProviderCommandBuffer::BindToCurrentThread() {
- DCHECK(context3d_);
-
// This is called on the thread the context will be used.
DCHECK(context_thread_checker_.CalledOnValidThread());
@@ -141,27 +95,36 @@ bool ContextProviderCommandBuffer::BindToCurrentThread() {
context3d_->pushGroupMarkerEXT(unique_context_name.c_str());
lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this));
- swap_buffers_complete_callback_proxy_.reset(
- new SwapBuffersCompleteCallbackProxy(this));
- memory_allocation_callback_proxy_.reset(
- new MemoryAllocationCallbackProxy(this));
+ context3d_->GetCommandBufferProxy()->SetMemoryAllocationChangedCallback(
+ base::Bind(&ContextProviderCommandBuffer::OnMemoryAllocationChanged,
+ base::Unretained(this)));
return true;
}
WebGraphicsContext3DCommandBufferImpl*
ContextProviderCommandBuffer::Context3d() {
- DCHECK(context3d_);
DCHECK(lost_context_callback_proxy_); // Is bound to thread.
DCHECK(context_thread_checker_.CalledOnValidThread());
return context3d_.get();
}
-class GrContext* ContextProviderCommandBuffer::GrContext() {
+gpu::gles2::GLES2Interface* ContextProviderCommandBuffer::ContextGL() {
DCHECK(context3d_);
DCHECK(lost_context_callback_proxy_); // Is bound to thread.
DCHECK(context_thread_checker_.CalledOnValidThread());
+ return context3d_->GetImplementation();
+}
+
+gpu::ContextSupport* ContextProviderCommandBuffer::ContextSupport() {
+ return context3d_->GetContextSupport();
+}
+
+class GrContext* ContextProviderCommandBuffer::GrContext() {
+ DCHECK(lost_context_callback_proxy_); // Is bound to thread.
+ DCHECK(context_thread_checker_.CalledOnValidThread());
+
if (gr_context_)
return gr_context_->get();
@@ -170,17 +133,30 @@ class GrContext* ContextProviderCommandBuffer::GrContext() {
return gr_context_->get();
}
+void ContextProviderCommandBuffer::MakeGrContextCurrent() {
+ DCHECK(lost_context_callback_proxy_); // Is bound to thread.
+ DCHECK(context_thread_checker_.CalledOnValidThread());
+ DCHECK(gr_context_);
+
+ context3d_->makeContextCurrent();
+}
+
cc::ContextProvider::Capabilities
ContextProviderCommandBuffer::ContextCapabilities() {
- DCHECK(context3d_);
DCHECK(lost_context_callback_proxy_); // Is bound to thread.
DCHECK(context_thread_checker_.CalledOnValidThread());
return capabilities_;
}
+bool ContextProviderCommandBuffer::IsContextLost() {
+ DCHECK(lost_context_callback_proxy_); // Is bound to thread.
+ DCHECK(context_thread_checker_.CalledOnValidThread());
+
+ return context3d_->isContextLost();
+}
+
void ContextProviderCommandBuffer::VerifyContexts() {
- DCHECK(context3d_);
DCHECK(lost_context_callback_proxy_); // Is bound to thread.
DCHECK(context_thread_checker_.CalledOnValidThread());
@@ -200,88 +176,24 @@ void ContextProviderCommandBuffer::OnLostContext() {
base::ResetAndReturn(&lost_context_callback_).Run();
}
-void ContextProviderCommandBuffer::OnSwapBuffersComplete() {
- DCHECK(context_thread_checker_.CalledOnValidThread());
- if (!swap_buffers_complete_callback_.is_null())
- swap_buffers_complete_callback_.Run();
-}
-
void ContextProviderCommandBuffer::OnMemoryAllocationChanged(
- const WebKit::WebGraphicsMemoryAllocation& allocation) {
+ const gpu::MemoryAllocation& allocation) {
DCHECK(context_thread_checker_.CalledOnValidThread());
if (gr_context_) {
- bool nonzero_allocation = !!allocation.gpuResourceSizeInBytes;
+ bool nonzero_allocation = !!allocation.bytes_limit_when_visible;
gr_context_->SetMemoryLimit(nonzero_allocation);
}
if (memory_policy_changed_callback_.is_null())
return;
- bool discard_backbuffer_when_not_visible;
- cc::ManagedMemoryPolicy policy =
- webkit::gpu::ManagedMemoryPolicyConvert::Convert(
- allocation,
- &discard_backbuffer_when_not_visible);
-
- memory_policy_changed_callback_.Run(
- policy, discard_backbuffer_when_not_visible);
+ memory_policy_changed_callback_.Run(cc::ManagedMemoryPolicy(allocation));
}
void ContextProviderCommandBuffer::InitializeCapabilities() {
- // The command buffer provides the following capabilities always.
- // TODO(jamesr): This information is duplicated with
- // gpu::gles2::FeatureInfo::AddFeatures().
- Capabilities caps;
- caps.bind_uniform_location = true;
- caps.discard_backbuffer = true;
- caps.set_visibility = true;
-
- // TODO(jamesr): These are also added in
- // gpu::gles2::GLES2Implementation::GetStringHelper() on the client side.
- caps.map_sub = true;
- caps.shallow_flush = true;
-
- // The swapbuffers complete callback is always supported by multi-process
- // command buffer implementations.
- caps.swapbuffers_complete_callback = true;
-
- std::string extensions = reinterpret_cast<const char*>(
- context3d_->GetImplementation()->GetString(0x1F03 /* GL_EXTENSIONS */));
- std::vector<std::string> extension_list;
- base::SplitString(extensions, ' ', &extension_list);
- std::set<std::string> extension_set(extension_list.begin(),
- extension_list.end());
-
-
- // caps.map_image depends on GL_CHROMIUM_map_image, which is set client-side
- // based on the presence of GpuControl.
- caps.map_image = extension_set.count("GL_CHROMIUM_map_image") > 0;
-
- // caps.fast_npot_mo8_textures depends on
- // workarounds_.enable_chromium_fast_npot_mo8_textures which controls
- // GL_CHROMIUM_fast_NPOT_MO8_textures
- caps.fast_npot_mo8_textures =
- extension_set.count("GL_CHROMIUM_fast_NPOT_MO8_textures") > 0;
-
- caps.egl_image_external =
- extension_set.count("GL_OES_EGL_image_external") > 0;
-
- caps.texture_format_bgra8888 =
- extension_set.count("GL_EXT_texture_format_BGRA8888") > 0;
- caps.texture_rectangle = extension_set.count("GL_ARB_texture_rectangle") > 0;
-
- caps.post_sub_buffer = extension_set.count("GL_CHROMIUM_post_sub_buffer") > 0;
-
- // TODO(jamesr): This is unconditionally true on mac, no need to test for it
- // at runtime.
- caps.iosurface = extension_set.count("GL_CHROMIUM_iosurface") > 0;
-
- caps.texture_usage = extension_set.count("GL_ANGLE_texture_usage") > 0;
- caps.texture_storage = extension_set.count("GL_EXT_texture_storage") > 0;
-
- caps.discard_framebuffer =
- extension_set.count("GL_EXT_discard_framebuffer") > 0;
+ Capabilities caps(context3d_->GetImplementation()->capabilities());
+
size_t mapped_memory_limit = context3d_->GetMappedMemoryLimit();
caps.max_transfer_buffer_usage_bytes =
mapped_memory_limit == WebGraphicsContext3DCommandBufferImpl::kNoLimit
@@ -306,14 +218,6 @@ void ContextProviderCommandBuffer::SetLostContextCallback(
lost_context_callback_ = lost_context_callback;
}
-void ContextProviderCommandBuffer::SetSwapBuffersCompleteCallback(
- const SwapBuffersCompleteCallback& swap_buffers_complete_callback) {
- DCHECK(context_thread_checker_.CalledOnValidThread());
- DCHECK(swap_buffers_complete_callback_.is_null() ||
- swap_buffers_complete_callback.is_null());
- swap_buffers_complete_callback_ = swap_buffers_complete_callback;
-}
-
void ContextProviderCommandBuffer::SetMemoryPolicyChangedCallback(
const MemoryPolicyChangedCallback& memory_policy_changed_callback) {
DCHECK(context_thread_checker_.CalledOnValidThread());
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 6ff446a9ebd..2f8e4f2ee0f 100644
--- a/chromium/content/common/gpu/client/context_provider_command_buffer.h
+++ b/chromium/content/common/gpu/client/context_provider_command_buffer.h
@@ -32,15 +32,16 @@ class CONTENT_EXPORT ContextProviderCommandBuffer
virtual bool BindToCurrentThread() OVERRIDE;
virtual WebGraphicsContext3DCommandBufferImpl* Context3d() OVERRIDE;
+ virtual gpu::gles2::GLES2Interface* ContextGL() OVERRIDE;
+ virtual gpu::ContextSupport* ContextSupport() OVERRIDE;
virtual class GrContext* GrContext() OVERRIDE;
+ virtual void MakeGrContextCurrent() OVERRIDE;
virtual Capabilities ContextCapabilities() OVERRIDE;
+ virtual bool IsContextLost() OVERRIDE;
virtual void VerifyContexts() OVERRIDE;
virtual bool DestroyedOnMainThread() OVERRIDE;
virtual void SetLostContextCallback(
const LostContextCallback& lost_context_callback) OVERRIDE;
- virtual void SetSwapBuffersCompleteCallback(
- const SwapBuffersCompleteCallback& swap_buffers_complete_callback)
- OVERRIDE;
virtual void SetMemoryPolicyChangedCallback(
const MemoryPolicyChangedCallback& memory_policy_changed_callback)
OVERRIDE;
@@ -57,9 +58,7 @@ class CONTENT_EXPORT ContextProviderCommandBuffer
virtual ~ContextProviderCommandBuffer();
void OnLostContext();
- void OnSwapBuffersComplete();
- void OnMemoryAllocationChanged(
- const WebKit::WebGraphicsMemoryAllocation& allocation);
+ void OnMemoryAllocationChanged(const gpu::MemoryAllocation& allocation);
private:
void InitializeCapabilities();
@@ -74,7 +73,6 @@ class CONTENT_EXPORT ContextProviderCommandBuffer
std::string debug_name_;
LostContextCallback lost_context_callback_;
- SwapBuffersCompleteCallback swap_buffers_complete_callback_;
MemoryPolicyChangedCallback memory_policy_changed_callback_;
base::Lock main_thread_lock_;
@@ -83,13 +81,6 @@ class CONTENT_EXPORT ContextProviderCommandBuffer
class LostContextCallbackProxy;
scoped_ptr<LostContextCallbackProxy> lost_context_callback_proxy_;
-
- class SwapBuffersCompleteCallbackProxy;
- scoped_ptr<SwapBuffersCompleteCallbackProxy>
- swap_buffers_complete_callback_proxy_;
-
- class MemoryAllocationCallbackProxy;
- scoped_ptr<MemoryAllocationCallbackProxy> memory_allocation_callback_proxy_;
};
} // namespace content
diff --git a/chromium/content/common/gpu/client/context_provider_command_buffer_browsertest.cc b/chromium/content/common/gpu/client/context_provider_command_buffer_browsertest.cc
index fd68aa41e79..b51db155529 100644
--- a/chromium/content/common/gpu/client/context_provider_command_buffer_browsertest.cc
+++ b/chromium/content/common/gpu/client/context_provider_command_buffer_browsertest.cc
@@ -12,18 +12,41 @@ namespace content {
namespace {
class ContextProviderCommandBufferBrowserTest : public ContentBrowserTest {
+ public:
+ virtual void SetUpOnMainThread() OVERRIDE {
+ if (!BrowserGpuChannelHostFactory::CanUseForTesting())
+ return;
+
+ if (!GetFactory())
+ BrowserGpuChannelHostFactory::Initialize(true);
+
+ CHECK(GetFactory());
+ ContentBrowserTest::SetUpOnMainThread();
+ }
+
protected:
+ BrowserGpuChannelHostFactory* GetFactory() {
+ return BrowserGpuChannelHostFactory::instance();
+ }
+
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext3d() {
+ scoped_refptr<GpuChannelHost> gpu_channel_host(
+ GetFactory()->EstablishGpuChannelSync(
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- BrowserGpuChannelHostFactory::instance(),
- WebKit::WebGraphicsContext3D::Attributes(),
- GURL("chrome://gpu/ContextProviderCommandBufferTest")));
+ gpu_channel_host.get(),
+ blink::WebGraphicsContext3D::Attributes(),
+ GURL("chrome://gpu/ContextProviderCommandBufferTest"),
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits()));
return context.Pass();
}
};
IN_PROC_BROWSER_TEST_F(ContextProviderCommandBufferBrowserTest, LeakOnDestroy) {
+ if (!BrowserGpuChannelHostFactory::CanUseForTesting())
+ return;
+
scoped_refptr<ContextProviderCommandBuffer> provider =
ContextProviderCommandBuffer::Create(CreateContext3d(), "TestContext");
provider->set_leak_on_destroy();
diff --git a/chromium/content/common/gpu/client/gl_helper.cc b/chromium/content/common/gpu/client/gl_helper.cc
index bd5ad4987b4..3ea2557a69d 100644
--- a/chromium/content/common/gpu/client/gl_helper.cc
+++ b/chromium/content/common/gpu/client/gl_helper.cc
@@ -15,8 +15,8 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
-#include "cc/resources/sync_point_helper.h"
#include "content/common/gpu/client/gl_helper_scaling.h"
+#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
@@ -26,8 +26,8 @@
#include "ui/gfx/size.h"
#include "ui/gl/gl_bindings.h"
-using WebKit::WebGLId;
-using WebKit::WebGraphicsContext3D;
+using blink::WebGLId;
+using blink::WebGraphicsContext3D;
namespace {
@@ -84,7 +84,7 @@ class ScalerHolder {
scaler_(scaler) {
}
- void Scale(WebKit::WebGLId src_texture) {
+ void Scale(blink::WebGLId src_texture) {
scaler_->Scale(src_texture, texture_and_framebuffer_.texture());
}
@@ -111,8 +111,10 @@ class GLHelper::CopyTextureToImpl :
public base::SupportsWeakPtr<GLHelper::CopyTextureToImpl> {
public:
CopyTextureToImpl(WebGraphicsContext3D* context,
+ gpu::ContextSupport* context_support,
GLHelper* helper)
: context_(context),
+ context_support_(context_support),
helper_(helper),
flush_(context),
max_draw_buffers_(0) {
@@ -160,7 +162,7 @@ class GLHelper::CopyTextureToImpl :
const gfx::Rect& dst_subrect,
const base::Callback<void(bool)>& callback);
- WebKit::WebGLId CopyAndScaleTexture(WebGLId texture,
+ blink::WebGLId CopyAndScaleTexture(WebGLId texture,
const gfx::Size& src_size,
const gfx::Size& dst_size,
bool vertically_flip_texture,
@@ -177,7 +179,7 @@ class GLHelper::CopyTextureToImpl :
// Returns the maximum number of draw buffers available,
// 0 if GL_EXT_draw_buffers is not available.
- WebKit::WGC3Dint MaxDrawBuffers() const {
+ blink::WGC3Dint MaxDrawBuffers() const {
return max_draw_buffers_;
}
@@ -212,7 +214,7 @@ class GLHelper::CopyTextureToImpl :
unsigned char* pixels;
base::Callback<void(bool)> callback;
GLuint buffer;
- WebKit::WebGLId query;
+ blink::WebGLId query;
};
// A readback pipeline that also converts the data to YUV before
@@ -282,6 +284,7 @@ class GLHelper::CopyTextureToImpl :
CopyTextureToImpl* copy_impl_;
gfx::Size dst_size_;
gfx::Rect dst_subrect_;
+ GLHelper::ScalerQuality quality_;
ScalerHolder scaler_;
scoped_ptr<content::GLHelperScaling::ShaderInterface> pass1_shader_;
scoped_ptr<content::GLHelperScaling::ShaderInterface> pass2_shader_;
@@ -314,6 +317,7 @@ class GLHelper::CopyTextureToImpl :
static const float kRGBtoVColorWeights[];
WebGraphicsContext3D* context_;
+ gpu::ContextSupport* context_support_;
GLHelper* helper_;
// A scoped flush that will ensure all resource deletions are flushed when
@@ -321,7 +325,7 @@ class GLHelper::CopyTextureToImpl :
ScopedFlush flush_;
std::queue<Request*> request_queue_;
- WebKit::WGC3Dint max_draw_buffers_;
+ blink::WGC3Dint max_draw_buffers_;
};
GLHelper::ScalerInterface* GLHelper::CreateScaler(
@@ -400,8 +404,7 @@ void GLHelper::CopyTextureToImpl::ReadbackAsync(
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
context_->endQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM);
context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
- cc::SyncPointHelper::SignalQuery(
- context_,
+ context_support_->SignalQuery(
request->query,
base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), request));
}
@@ -465,7 +468,7 @@ void GLHelper::CopyTextureToImpl::ReadbackTextureSync(
out);
}
-WebKit::WebGLId GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
+blink::WebGLId GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
WebGLId src_texture,
const gfx::Size& src_size,
const gfx::Size& dst_size,
@@ -547,8 +550,10 @@ void GLHelper::CopyTextureToImpl::CancelRequests() {
}
}
-GLHelper::GLHelper(WebKit::WebGraphicsContext3D* context)
- : context_(context) {
+GLHelper::GLHelper(blink::WebGraphicsContext3D* context,
+ gpu::ContextSupport* context_support)
+ : context_(context),
+ context_support_(context_support) {
}
GLHelper::~GLHelper() {
@@ -586,7 +591,7 @@ void GLHelper::CropScaleReadbackAndCleanMailbox(
context_->deleteTexture(mailbox_texture);
}
-void GLHelper::ReadbackTextureSync(WebKit::WebGLId texture,
+void GLHelper::ReadbackTextureSync(blink::WebGLId texture,
const gfx::Rect& src_rect,
unsigned char* out) {
InitCopyTextToImpl();
@@ -595,7 +600,7 @@ void GLHelper::ReadbackTextureSync(WebKit::WebGLId texture,
out);
}
-WebKit::WebGLId GLHelper::CopyTexture(WebKit::WebGLId texture,
+blink::WebGLId GLHelper::CopyTexture(blink::WebGLId texture,
const gfx::Size& size) {
InitCopyTextToImpl();
return copy_texture_to_impl_->CopyAndScaleTexture(
@@ -606,8 +611,8 @@ WebKit::WebGLId GLHelper::CopyTexture(WebKit::WebGLId texture,
GLHelper::SCALER_QUALITY_FAST);
}
-WebKit::WebGLId GLHelper::CopyAndScaleTexture(
- WebKit::WebGLId texture,
+blink::WebGLId GLHelper::CopyAndScaleTexture(
+ blink::WebGLId texture,
const gfx::Size& src_size,
const gfx::Size& dst_size,
bool vertically_flip_texture,
@@ -621,12 +626,12 @@ WebKit::WebGLId GLHelper::CopyAndScaleTexture(
}
WebGLId GLHelper::CompileShaderFromSource(
- const WebKit::WGC3Dchar* source,
- WebKit::WGC3Denum type) {
+ const blink::WGC3Dchar* source,
+ blink::WGC3Denum type) {
ScopedShader shader(context_, context_->createShader(type));
context_->shaderSource(shader, source);
context_->compileShader(shader);
- WebKit::WGC3Dint compile_status = 0;
+ blink::WGC3Dint compile_status = 0;
context_->getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
if (!compile_status) {
LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8());
@@ -638,7 +643,8 @@ WebGLId GLHelper::CompileShaderFromSource(
void GLHelper::InitCopyTextToImpl() {
// Lazily initialize |copy_texture_to_impl_|
if (!copy_texture_to_impl_)
- copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, this));
+ copy_texture_to_impl_.reset(
+ new CopyTextureToImpl(context_, context_support_, this));
}
void GLHelper::InitScalerImpl() {
@@ -647,13 +653,13 @@ void GLHelper::InitScalerImpl() {
scaler_impl_.reset(new GLHelperScaling(context_, this));
}
-WebKit::WGC3Dint GLHelper::MaxDrawBuffers() {
+blink::WGC3Dint GLHelper::MaxDrawBuffers() {
InitCopyTextToImpl();
return copy_texture_to_impl_->MaxDrawBuffers();
}
-void GLHelper::CopySubBufferDamage(WebKit::WebGLId texture,
- WebKit::WebGLId previous_texture,
+void GLHelper::CopySubBufferDamage(blink::WebGLId texture,
+ blink::WebGLId previous_texture,
const SkRegion& new_damage,
const SkRegion& old_damage) {
SkRegion region(old_damage);
@@ -679,8 +685,8 @@ void GLHelper::CopySubBufferDamage(WebKit::WebGLId texture,
}
}
-WebKit::WebGLId GLHelper::CreateTexture() {
- WebKit::WebGLId texture = context_->createTexture();
+blink::WebGLId GLHelper::CreateTexture() {
+ blink::WebGLId texture = context_->createTexture();
content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_,
texture);
context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -690,27 +696,52 @@ WebKit::WebGLId GLHelper::CreateTexture() {
return texture;
}
-WebKit::WebGLId GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
+void GLHelper::DeleteTexture(blink::WebGLId texture_id) {
+ context_->deleteTexture(texture_id);
+}
+
+uint32 GLHelper::InsertSyncPoint() { return context_->insertSyncPoint(); }
+
+void GLHelper::WaitSyncPoint(uint32 sync_point) {
+ context_->waitSyncPoint(sync_point);
+}
+
+gpu::Mailbox GLHelper::ProduceMailboxFromTexture(blink::WebGLId texture_id,
+ uint32* sync_point) {
+ gpu::Mailbox mailbox;
+ context_->genMailboxCHROMIUM(mailbox.name);
+ if (mailbox.IsZero()) {
+ *sync_point = 0;
+ return mailbox;
+ }
+ content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_,
+ texture_id);
+ context_->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+ *sync_point = context_->insertSyncPoint();
+ return mailbox;
+}
+
+blink::WebGLId GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
uint32 sync_point) {
if (mailbox.IsZero())
return 0;
if (sync_point)
context_->waitSyncPoint(sync_point);
- WebKit::WebGLId texture = CreateTexture();
+ blink::WebGLId texture = CreateTexture();
content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_,
texture);
context_->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
return texture;
}
-void GLHelper::ResizeTexture(WebKit::WebGLId texture, const gfx::Size& size) {
+void GLHelper::ResizeTexture(blink::WebGLId texture, const gfx::Size& size) {
content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
context_->texImage2D(GL_TEXTURE_2D, 0, GL_RGB,
size.width(), size.height(), 0,
GL_RGB, GL_UNSIGNED_BYTE, NULL);
}
-void GLHelper::CopyTextureSubImage(WebKit::WebGLId texture,
+void GLHelper::CopyTextureSubImage(blink::WebGLId texture,
const gfx::Rect& rect) {
content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
context_->copyTexSubImage2D(GL_TEXTURE_2D, 0,
@@ -718,7 +749,7 @@ void GLHelper::CopyTextureSubImage(WebKit::WebGLId texture,
rect.x(), rect.y(), rect.width(), rect.height());
}
-void GLHelper::CopyTextureFullImage(WebKit::WebGLId texture,
+void GLHelper::CopyTextureFullImage(blink::WebGLId texture,
const gfx::Size& size) {
content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
context_->copyTexImage2D(GL_TEXTURE_2D, 0,
@@ -886,12 +917,13 @@ GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT(
copy_impl_(copy_impl),
dst_size_(dst_size),
dst_subrect_(dst_subrect),
+ quality_(quality),
scaler_(context, scaler_impl->CreateScaler(
quality,
src_size,
src_subrect,
dst_subrect.size(),
- flip_vertically,
+ false,
false)),
pass1_shader_(scaler_impl->CreateYuvMrtShader(
dst_subrect.size(),
@@ -900,7 +932,7 @@ GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT(
dst_subrect.height()),
gfx::Size((dst_subrect.width() + 3) / 4,
dst_subrect.height()),
- false,
+ flip_vertically,
GLHelperScaling::SHADER_YUV_MRT_PASS1)),
pass2_shader_(scaler_impl->CreateYuvMrtShader(
gfx::Size((dst_subrect.width() + 3) / 4,
@@ -947,15 +979,27 @@ void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV(
WebGLId mailbox_texture =
copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point);
- // Scale texture to right size.
- scaler_.Scale(mailbox_texture);
- context_->deleteTexture(mailbox_texture);
+ WebGLId texture;
+ if (quality_ == GLHelper::SCALER_QUALITY_FAST) {
+ // Optimization: SCALER_QUALITY_FAST is just a single bilinear
+ // pass, which pass1_shader_ can do just as well, so let's skip
+ // the actual scaling in that case.
+ texture = mailbox_texture;
+ } else {
+ // Scale texture to right size.
+ scaler_.Scale(mailbox_texture);
+ texture = scaler_.texture();
+ }
+
- std::vector<WebKit::WebGLId> outputs(2);
+ std::vector<blink::WebGLId> outputs(2);
// Convert the scaled texture in to Y, U and V planes.
outputs[0] = y_.texture();
outputs[1] = uv_;
- pass1_shader_->Execute(scaler_.texture(), outputs);
+ pass1_shader_->Execute(texture, outputs);
+
+ context_->deleteTexture(mailbox_texture);
+
outputs[0] = u_.texture();
outputs[1] = v_.texture();
pass2_shader_->Execute(uv_, outputs);
diff --git a/chromium/content/common/gpu/client/gl_helper.h b/chromium/content/common/gpu/client/gl_helper.h
index b874f977037..bac0560651b 100644
--- a/chromium/content/common/gpu/client/gl_helper.h
+++ b/chromium/content/common/gpu/client/gl_helper.h
@@ -18,6 +18,7 @@ class Size;
}
namespace gpu {
+class ContextSupport;
struct Mailbox;
}
@@ -33,8 +34,8 @@ class GLHelperScaling;
class ScopedWebGLId {
public:
- typedef void (WebKit::WebGraphicsContext3D::*DeleteFunc)(WebGLId);
- ScopedWebGLId(WebKit::WebGraphicsContext3D* context,
+ typedef void (blink::WebGraphicsContext3D::*DeleteFunc)(WebGLId);
+ ScopedWebGLId(blink::WebGraphicsContext3D* context,
WebGLId id,
DeleteFunc delete_func)
: context_(context),
@@ -61,7 +62,7 @@ class ScopedWebGLId {
}
private:
- WebKit::WebGraphicsContext3D* context_;
+ blink::WebGraphicsContext3D* context_;
WebGLId id_;
DeleteFunc delete_func_;
@@ -70,55 +71,55 @@ class ScopedWebGLId {
class ScopedBuffer : public ScopedWebGLId {
public:
- ScopedBuffer(WebKit::WebGraphicsContext3D* context,
+ ScopedBuffer(blink::WebGraphicsContext3D* context,
WebGLId id)
: ScopedWebGLId(context,
id,
- &WebKit::WebGraphicsContext3D::deleteBuffer) {}
+ &blink::WebGraphicsContext3D::deleteBuffer) {}
};
class ScopedFramebuffer : public ScopedWebGLId {
public:
- ScopedFramebuffer(WebKit::WebGraphicsContext3D* context,
+ ScopedFramebuffer(blink::WebGraphicsContext3D* context,
WebGLId id)
: ScopedWebGLId(context,
id,
- &WebKit::WebGraphicsContext3D::deleteFramebuffer) {}
+ &blink::WebGraphicsContext3D::deleteFramebuffer) {}
};
class ScopedProgram : public ScopedWebGLId {
public:
- ScopedProgram(WebKit::WebGraphicsContext3D* context,
+ ScopedProgram(blink::WebGraphicsContext3D* context,
WebGLId id)
: ScopedWebGLId(context,
id,
- &WebKit::WebGraphicsContext3D::deleteProgram) {}
+ &blink::WebGraphicsContext3D::deleteProgram) {}
};
class ScopedShader : public ScopedWebGLId {
public:
- ScopedShader(WebKit::WebGraphicsContext3D* context,
+ ScopedShader(blink::WebGraphicsContext3D* context,
WebGLId id)
: ScopedWebGLId(context,
id,
- &WebKit::WebGraphicsContext3D::deleteShader) {}
+ &blink::WebGraphicsContext3D::deleteShader) {}
};
class ScopedTexture : public ScopedWebGLId {
public:
- ScopedTexture(WebKit::WebGraphicsContext3D* context,
+ ScopedTexture(blink::WebGraphicsContext3D* context,
WebGLId id)
: ScopedWebGLId(context,
id,
- &WebKit::WebGraphicsContext3D::deleteTexture) {}
+ &blink::WebGraphicsContext3D::deleteTexture) {}
};
-template <WebKit::WGC3Denum target>
+template <blink::WGC3Denum target>
class ScopedBinder {
public:
- typedef void (WebKit::WebGraphicsContext3D::*BindFunc)(WebKit::WGC3Denum,
+ typedef void (blink::WebGraphicsContext3D::*BindFunc)(blink::WGC3Denum,
WebGLId);
- ScopedBinder(WebKit::WebGraphicsContext3D* context,
+ ScopedBinder(blink::WebGraphicsContext3D* context,
WebGLId id,
BindFunc bind_func)
: context_(context),
@@ -131,48 +132,48 @@ class ScopedBinder {
}
private:
- WebKit::WebGraphicsContext3D* context_;
+ blink::WebGraphicsContext3D* context_;
BindFunc bind_func_;
DISALLOW_COPY_AND_ASSIGN(ScopedBinder);
};
-template <WebKit::WGC3Denum target>
+template <blink::WGC3Denum target>
class ScopedBufferBinder : ScopedBinder<target> {
public:
- ScopedBufferBinder(WebKit::WebGraphicsContext3D* context,
+ ScopedBufferBinder(blink::WebGraphicsContext3D* context,
WebGLId id)
: ScopedBinder<target>(
context,
id,
- &WebKit::WebGraphicsContext3D::bindBuffer) {}
+ &blink::WebGraphicsContext3D::bindBuffer) {}
};
-template <WebKit::WGC3Denum target>
+template <blink::WGC3Denum target>
class ScopedFramebufferBinder : ScopedBinder<target> {
public:
- ScopedFramebufferBinder(WebKit::WebGraphicsContext3D* context,
+ ScopedFramebufferBinder(blink::WebGraphicsContext3D* context,
WebGLId id)
: ScopedBinder<target>(
context,
id,
- &WebKit::WebGraphicsContext3D::bindFramebuffer) {}
+ &blink::WebGraphicsContext3D::bindFramebuffer) {}
};
-template <WebKit::WGC3Denum target>
+template <blink::WGC3Denum target>
class ScopedTextureBinder : ScopedBinder<target> {
public:
- ScopedTextureBinder(WebKit::WebGraphicsContext3D* context,
+ ScopedTextureBinder(blink::WebGraphicsContext3D* context,
WebGLId id)
: ScopedBinder<target>(
context,
id,
- &WebKit::WebGraphicsContext3D::bindTexture) {}
+ &blink::WebGraphicsContext3D::bindTexture) {}
};
class ScopedFlush {
public:
- explicit ScopedFlush(WebKit::WebGraphicsContext3D* context)
+ explicit ScopedFlush(blink::WebGraphicsContext3D* context)
: context_(context) {
}
@@ -181,7 +182,7 @@ class ScopedFlush {
}
private:
- WebKit::WebGraphicsContext3D* context_;
+ blink::WebGraphicsContext3D* context_;
DISALLOW_COPY_AND_ASSIGN(ScopedFlush);
};
@@ -189,11 +190,12 @@ class ScopedFlush {
class ReadbackYUVInterface;
-// Provides higher level operations on top of the WebKit::WebGraphicsContext3D
+// Provides higher level operations on top of the blink::WebGraphicsContext3D
// interfaces.
class CONTENT_EXPORT GLHelper {
public:
- explicit GLHelper(WebKit::WebGraphicsContext3D* context);
+ GLHelper(blink::WebGraphicsContext3D* context,
+ gpu::ContextSupport* context_support);
~GLHelper();
enum ScalerQuality {
@@ -222,7 +224,7 @@ class CONTENT_EXPORT GLHelper {
// Note that the src_texture will have the min/mag filter set to GL_LINEAR
// and wrap_s/t set to CLAMP_TO_EDGE in this call.
void CropScaleReadbackAndCleanTexture(
- WebKit::WebGLId src_texture,
+ blink::WebGLId src_texture,
const gfx::Size& src_size,
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
@@ -252,55 +254,69 @@ class CONTENT_EXPORT GLHelper {
// texture is assumed to have a format of GL_RGBA with a pixel type of
// GL_UNSIGNED_BYTE. This is a blocking call that calls glReadPixels on this
// current context.
- void ReadbackTextureSync(WebKit::WebGLId texture,
+ void ReadbackTextureSync(blink::WebGLId texture,
const gfx::Rect& src_rect,
unsigned char* out);
// Creates a copy of the specified texture. |size| is the size of the texture.
// Note that the src_texture will have the min/mag filter set to GL_LINEAR
// and wrap_s/t set to CLAMP_TO_EDGE in this call.
- WebKit::WebGLId CopyTexture(WebKit::WebGLId texture,
+ blink::WebGLId CopyTexture(blink::WebGLId texture,
const gfx::Size& size);
// Creates a scaled copy of the specified texture. |src_size| is the size of
// the texture and |dst_size| is the size of the resulting copy.
// Note that the src_texture will have the min/mag filter set to GL_LINEAR
// and wrap_s/t set to CLAMP_TO_EDGE in this call.
- WebKit::WebGLId CopyAndScaleTexture(
- WebKit::WebGLId texture,
+ blink::WebGLId CopyAndScaleTexture(
+ blink::WebGLId texture,
const gfx::Size& src_size,
const gfx::Size& dst_size,
bool vertically_flip_texture,
ScalerQuality quality);
// Returns the shader compiled from the source.
- WebKit::WebGLId CompileShaderFromSource(const WebKit::WGC3Dchar* source,
- WebKit::WGC3Denum type);
+ blink::WebGLId CompileShaderFromSource(const blink::WGC3Dchar* source,
+ blink::WGC3Denum type);
// Copies all pixels from |previous_texture| into |texture| that are
// inside the region covered by |old_damage| but not part of |new_damage|.
- void CopySubBufferDamage(WebKit::WebGLId texture,
- WebKit::WebGLId previous_texture,
+ void CopySubBufferDamage(blink::WebGLId texture,
+ blink::WebGLId previous_texture,
const SkRegion& new_damage,
const SkRegion& old_damage);
// Simply creates a texture.
- WebKit::WebGLId CreateTexture();
+ blink::WebGLId CreateTexture();
+ // Deletes a texture.
+ void DeleteTexture(blink::WebGLId texture_id);
+
+ // Insert a sync point into the GL command buffer.
+ uint32 InsertSyncPoint();
+ // Wait for the sync point before executing further GL commands.
+ void WaitSyncPoint(uint32 sync_point);
+
+ // Creates a mailbox that is attached to the given texture id, and a sync
+ // point to wait on before using the mailbox. Returns an empty mailbox on
+ // failure.
+ // Note the texture is assumed to be GL_TEXTURE_2D.
+ gpu::Mailbox ProduceMailboxFromTexture(blink::WebGLId texture_id,
+ uint32* sync_point);
// Creates a texture and consumes a mailbox into it. Returns 0 on failure.
// Note the mailbox is assumed to be GL_TEXTURE_2D.
- WebKit::WebGLId ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
+ blink::WebGLId ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
uint32 sync_point);
// Resizes the texture's size to |size|.
- void ResizeTexture(WebKit::WebGLId texture, const gfx::Size& size);
+ void ResizeTexture(blink::WebGLId texture, const gfx::Size& size);
// Copies the framebuffer data given in |rect| to |texture|.
- void CopyTextureSubImage(WebKit::WebGLId texture, const gfx::Rect& rect);
+ void CopyTextureSubImage(blink::WebGLId texture, const gfx::Rect& rect);
// Copies the all framebuffer data to |texture|. |size| specifies the
// size of the framebuffer.
- void CopyTextureFullImage(WebKit::WebGLId texture, const gfx::Size& size);
+ void CopyTextureFullImage(blink::WebGLId texture, const gfx::Size& size);
// A scaler will cache all intermediate textures and programs
// needed to scale from a specified size to a destination size.
@@ -313,8 +329,8 @@ class CONTENT_EXPORT GLHelper {
// Note that the src_texture will have the min/mag filter set to GL_LINEAR
// and wrap_s/t set to CLAMP_TO_EDGE in this call.
- virtual void Scale(WebKit::WebGLId source_texture,
- WebKit::WebGLId dest_texture) = 0;
+ virtual void Scale(blink::WebGLId source_texture,
+ blink::WebGLId dest_texture) = 0;
virtual const gfx::Size& SrcSize() = 0;
virtual const gfx::Rect& SrcSubrect() = 0;
virtual const gfx::Size& DstSize() = 0;
@@ -350,7 +366,7 @@ class CONTENT_EXPORT GLHelper {
// Returns the maximum number of draw buffers available,
// 0 if GL_EXT_draw_buffers is not available.
- WebKit::WGC3Dint MaxDrawBuffers();
+ blink::WGC3Dint MaxDrawBuffers();
protected:
class CopyTextureToImpl;
@@ -360,7 +376,8 @@ class CONTENT_EXPORT GLHelper {
// Creates |scaler_impl_| if NULL.
void InitScalerImpl();
- WebKit::WebGraphicsContext3D* context_;
+ blink::WebGraphicsContext3D* context_;
+ gpu::ContextSupport* context_support_;
scoped_ptr<CopyTextureToImpl> copy_texture_to_impl_;
scoped_ptr<GLHelperScaling> scaler_impl_;
diff --git a/chromium/content/common/gpu/client/gl_helper_benchmark.cc b/chromium/content/common/gpu/client/gl_helper_benchmark.cc
index 1c5bee2d300..f9385fdd822 100644
--- a/chromium/content/common/gpu/client/gl_helper_benchmark.cc
+++ b/chromium/content/common/gpu/client/gl_helper_benchmark.cc
@@ -43,8 +43,8 @@
namespace content {
-using WebKit::WebGLId;
-using WebKit::WebGraphicsContext3D;
+using blink::WebGLId;
+using blink::WebGraphicsContext3D;
content::GLHelper::ScalerQuality kQualities[] = {
content::GLHelper::SCALER_QUALITY_BEST,
@@ -66,7 +66,8 @@ class GLHelperTest : public testing::Test {
CreateOffscreenContext(attributes);
context_->makeContextCurrent();
- helper_.reset(new content::GLHelper(context_.get()));
+ helper_.reset(
+ new content::GLHelper(context_.get(), context_->GetContextSupport()));
helper_scaling_.reset(new content::GLHelperScaling(
context_.get(),
helper_.get()));
@@ -101,14 +102,15 @@ class GLHelperTest : public testing::Test {
std::vector<gfx::PNGCodec::Comment>(),
&compressed));
ASSERT_TRUE(compressed.size());
- FILE* f = file_util::OpenFile(filename, "wb");
+ FILE* f = base::OpenFile(filename, "wb");
ASSERT_TRUE(f);
ASSERT_EQ(fwrite(&*compressed.begin(), 1, compressed.size(), f),
compressed.size());
- file_util::CloseFile(f);
+ base::CloseFile(f);
}
- scoped_ptr<WebKit::WebGraphicsContext3D> context_;
+ scoped_ptr<webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl>
+ context_;
scoped_ptr<content::GLHelper> helper_;
scoped_ptr<content::GLHelperScaling> helper_scaling_;
std::deque<GLHelperScaling::ScaleOp> x_ops_, y_ops_;
@@ -294,7 +296,7 @@ TEST_F(GLHelperTest, DISABLED_ScaleTestImage) {
std::string filename = base::StringPrintf("testoutput_%s_%d.ppm",
kQualityNames[q],
percents[p]);
- LOG(INFO) << "Writing " << filename;
+ VLOG(0) << "Writing " << filename;
SaveToFile(&output_pixels, base::FilePath::FromUTF8Unsafe(filename));
}
}
diff --git a/chromium/content/common/gpu/client/gl_helper_scaling.cc b/chromium/content/common/gpu/client/gl_helper_scaling.cc
index ee900168053..ff6a6b7c855 100644
--- a/chromium/content/common/gpu/client/gl_helper_scaling.cc
+++ b/chromium/content/common/gpu/client/gl_helper_scaling.cc
@@ -21,12 +21,12 @@
#include "ui/gfx/size.h"
#include "ui/gl/gl_bindings.h"
-using WebKit::WebGLId;
-using WebKit::WebGraphicsContext3D;
+using blink::WebGLId;
+using blink::WebGraphicsContext3D;
namespace content {
-GLHelperScaling::GLHelperScaling(WebKit::WebGraphicsContext3D* context,
+GLHelperScaling::GLHelperScaling(blink::WebGraphicsContext3D* context,
GLHelper* helper)
: context_(context),
helper_(helper),
@@ -51,8 +51,8 @@ class ShaderProgram : public base::RefCounted<ShaderProgram> {
}
// Compile shader program, return true if successful.
- bool Setup(const WebKit::WGC3Dchar* vertex_shader_text,
- const WebKit::WGC3Dchar* fragment_shader_text);
+ bool Setup(const blink::WGC3Dchar* vertex_shader_text,
+ const blink::WGC3Dchar* fragment_shader_text);
// UseProgram must be called with GL_TEXTURE_2D bound to the
// source texture and GL_ARRAY_BUFFER bound to a vertex
@@ -75,22 +75,22 @@ class ShaderProgram : public base::RefCounted<ShaderProgram> {
ScopedProgram program_;
// The location of the position in the program.
- WebKit::WGC3Dint position_location_;
+ blink::WGC3Dint position_location_;
// The location of the texture coordinate in the program.
- WebKit::WGC3Dint texcoord_location_;
+ blink::WGC3Dint texcoord_location_;
// The location of the source texture in the program.
- WebKit::WGC3Dint texture_location_;
+ blink::WGC3Dint texture_location_;
// The location of the texture coordinate of
// the sub-rectangle in the program.
- WebKit::WGC3Dint src_subrect_location_;
+ blink::WGC3Dint src_subrect_location_;
// Location of size of source image in pixels.
- WebKit::WGC3Dint src_pixelsize_location_;
+ blink::WGC3Dint src_pixelsize_location_;
// Location of size of destination image in pixels.
- WebKit::WGC3Dint dst_pixelsize_location_;
+ blink::WGC3Dint dst_pixelsize_location_;
// Location of vector for scaling direction.
- WebKit::WGC3Dint scaling_vector_location_;
+ blink::WGC3Dint scaling_vector_location_;
// Location of color weights.
- WebKit::WGC3Dint color_weights_location_;
+ blink::WGC3Dint color_weights_location_;
DISALLOW_COPY_AND_ASSIGN(ShaderProgram);
};
@@ -164,8 +164,8 @@ class ScalerImpl :
// GLHelperShader::ShaderInterface implementation.
virtual void Execute(
- WebKit::WebGLId source_texture,
- const std::vector<WebKit::WebGLId>& dest_textures) OVERRIDE {
+ blink::WebGLId source_texture,
+ const std::vector<blink::WebGLId>& dest_textures) OVERRIDE {
if (subscaler_) {
subscaler_->Scale(source_texture, intermediate_texture_);
source_texture = intermediate_texture_;
@@ -175,8 +175,8 @@ class ScalerImpl :
context_,
dst_framebuffer_);
DCHECK_GT(dest_textures.size(), 0U);
- scoped_ptr<WebKit::WGC3Denum[]> buffers(
- new WebKit::WGC3Denum[dest_textures.size()]);
+ scoped_ptr<blink::WGC3Denum[]> buffers(
+ new blink::WGC3Denum[dest_textures.size()]);
for (size_t t = 0; t < dest_textures.size(); t++) {
ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_,
dest_textures[t]);
@@ -224,9 +224,9 @@ class ScalerImpl :
}
// GLHelper::ScalerInterface implementation.
- virtual void Scale(WebKit::WebGLId source_texture,
- WebKit::WebGLId dest_texture) OVERRIDE {
- std::vector<WebKit::WebGLId> tmp(1);
+ virtual void Scale(blink::WebGLId source_texture,
+ blink::WebGLId dest_texture) OVERRIDE {
+ std::vector<blink::WebGLId> tmp(1);
tmp[0] = dest_texture;
Execute(source_texture, tmp);
}
@@ -252,7 +252,7 @@ class ScalerImpl :
GLHelperScaling* scaler_helper_;
GLHelperScaling::ScalerStage spec_;
GLfloat color_weights_[4];
- WebKit::WebGLId intermediate_texture_;
+ blink::WebGLId intermediate_texture_;
scoped_refptr<ShaderProgram> shader_program_;
ScopedFramebuffer dst_framebuffer_;
scoped_ptr<ScalerImpl> subscaler_;
@@ -510,7 +510,7 @@ GLHelperScaling::CreateYuvMrtShader(
return new ScalerImpl(context_, this, stage, NULL, NULL);
}
-const WebKit::WGC3Dfloat GLHelperScaling::kVertexAttributes[] = {
+const blink::WGC3Dfloat GLHelperScaling::kVertexAttributes[] = {
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
@@ -533,12 +533,12 @@ GLHelperScaling::GetShaderProgram(ShaderType type,
scoped_refptr<ShaderProgram>& cache_entry(shader_programs_[key]);
if (!cache_entry.get()) {
cache_entry = new ShaderProgram(context_, helper_);
- std::basic_string<WebKit::WGC3Dchar> vertex_program;
- std::basic_string<WebKit::WGC3Dchar> fragment_program;
- std::basic_string<WebKit::WGC3Dchar> vertex_header;
- std::basic_string<WebKit::WGC3Dchar> fragment_directives;
- std::basic_string<WebKit::WGC3Dchar> fragment_header;
- std::basic_string<WebKit::WGC3Dchar> shared_variables;
+ std::basic_string<blink::WGC3Dchar> vertex_program;
+ std::basic_string<blink::WGC3Dchar> fragment_program;
+ std::basic_string<blink::WGC3Dchar> vertex_header;
+ std::basic_string<blink::WGC3Dchar> fragment_directives;
+ std::basic_string<blink::WGC3Dchar> fragment_header;
+ std::basic_string<blink::WGC3Dchar> shared_variables;
vertex_header.append(
"precision highp float;\n"
@@ -871,8 +871,8 @@ GLHelperScaling::GetShaderProgram(ShaderType type,
return cache_entry;
}
-bool ShaderProgram::Setup(const WebKit::WGC3Dchar* vertex_shader_text,
- const WebKit::WGC3Dchar* fragment_shader_text) {
+bool ShaderProgram::Setup(const blink::WGC3Dchar* vertex_shader_text,
+ const blink::WGC3Dchar* fragment_shader_text) {
// Shaders to map the source texture to |dst_texture_|.
ScopedShader vertex_shader(context_, helper_->CompileShaderFromSource(
vertex_shader_text, GL_VERTEX_SHADER));
@@ -888,7 +888,7 @@ bool ShaderProgram::Setup(const WebKit::WGC3Dchar* vertex_shader_text,
context_->attachShader(program_, fragment_shader);
context_->linkProgram(program_);
- WebKit::WGC3Dint link_status = 0;
+ blink::WGC3Dint link_status = 0;
context_->getProgramiv(program_, GL_LINK_STATUS, &link_status);
if (!link_status) {
LOG(ERROR) << std::string(context_->getProgramInfoLog(program_).utf8());
@@ -918,21 +918,21 @@ void ShaderProgram::UseProgram(
GLfloat color_weights[4]) {
context_->useProgram(program_);
- WebKit::WGC3Dintptr offset = 0;
+ blink::WGC3Dintptr offset = 0;
context_->vertexAttribPointer(position_location_,
2,
GL_FLOAT,
GL_FALSE,
- 4 * sizeof(WebKit::WGC3Dfloat),
+ 4 * sizeof(blink::WGC3Dfloat),
offset);
context_->enableVertexAttribArray(position_location_);
- offset += 2 * sizeof(WebKit::WGC3Dfloat);
+ offset += 2 * sizeof(blink::WGC3Dfloat);
context_->vertexAttribPointer(texcoord_location_,
2,
GL_FLOAT,
GL_FALSE,
- 4 * sizeof(WebKit::WGC3Dfloat),
+ 4 * sizeof(blink::WGC3Dfloat),
offset);
context_->enableVertexAttribArray(texcoord_location_);
diff --git a/chromium/content/common/gpu/client/gl_helper_scaling.h b/chromium/content/common/gpu/client/gl_helper_scaling.h
index eba283cabea..22e47c9c86a 100644
--- a/chromium/content/common/gpu/client/gl_helper_scaling.h
+++ b/chromium/content/common/gpu/client/gl_helper_scaling.h
@@ -41,13 +41,13 @@ class CONTENT_EXPORT GLHelperScaling {
virtual ~ShaderInterface() {}
// Note that the src_texture will have the min/mag filter set to GL_LINEAR
// and wrap_s/t set to CLAMP_TO_EDGE in this call.
- virtual void Execute(WebKit::WebGLId source_texture,
- const std::vector<WebKit::WebGLId>& dest_textures) = 0;
+ virtual void Execute(blink::WebGLId source_texture,
+ const std::vector<blink::WebGLId>& dest_textures) = 0;
};
typedef std::pair<ShaderType, bool> ShaderProgramKeyType;
- GLHelperScaling(WebKit::WebGraphicsContext3D* context,
+ GLHelperScaling(blink::WebGraphicsContext3D* context,
GLHelper* helper);
~GLHelperScaling();
void InitBuffer();
@@ -182,9 +182,9 @@ class CONTENT_EXPORT GLHelperScaling {
// Interleaved array of 2-dimentional vertex positions (x, y) and
// 2-dimentional texture coordinates (s, t).
- static const WebKit::WGC3Dfloat kVertexAttributes[];
+ static const blink::WGC3Dfloat kVertexAttributes[];
- WebKit::WebGraphicsContext3D* context_;
+ blink::WebGraphicsContext3D* context_;
GLHelper* helper_;
// The buffer that holds the vertices and the texture coordinates data for
diff --git a/chromium/content/common/gpu/client/gl_helper_unittests.cc b/chromium/content/common/gpu/client/gl_helper_unittests.cc
index a43f53e1643..548faecc02c 100644
--- a/chromium/content/common/gpu/client/gl_helper_unittests.cc
+++ b/chromium/content/common/gpu/client/gl_helper_unittests.cc
@@ -14,10 +14,13 @@
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/debug/trace_event.h"
#include "base/file_util.h"
+#include "base/json/json_reader.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
+#include "base/synchronization/waitable_event.h"
#include "base/time/time.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/common/gpu/client/gl_helper_scaling.h"
@@ -41,8 +44,9 @@
namespace content {
-using WebKit::WebGLId;
-using WebKit::WebGraphicsContext3D;
+using blink::WebGLId;
+using blink::WebGraphicsContext3D;
+using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
content::GLHelper::ScalerQuality kQualities[] = {
content::GLHelper::SCALER_QUALITY_BEST,
@@ -60,10 +64,11 @@ class GLHelperTest : public testing::Test {
protected:
virtual void SetUp() {
WebGraphicsContext3D::Attributes attributes;
- context_ = webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl::
+ context_ = WebGraphicsContext3DInProcessCommandBufferImpl::
CreateOffscreenContext(attributes);
context_->makeContextCurrent();
- helper_.reset(new content::GLHelper(context_.get()));
+ context_support_ = context_->GetContextSupport();
+ helper_.reset(new content::GLHelper(context_.get(), context_support_));
helper_scaling_.reset(new content::GLHelperScaling(
context_.get(),
helper_.get()));
@@ -75,6 +80,55 @@ class GLHelperTest : public testing::Test {
context_.reset(NULL);
}
+ void StartTracing(const std::string& filter) {
+ base::debug::TraceLog::GetInstance()->SetEnabled(
+ base::debug::CategoryFilter(filter),
+ base::debug::TraceLog::RECORD_UNTIL_FULL);
+ }
+
+ static void TraceDataCB(
+ const base::Callback<void()>& callback,
+ std::string* output,
+ const scoped_refptr<base::RefCountedString>& json_events_str,
+ bool has_more_events) {
+ if (output->size() > 1) {
+ output->append(",");
+ }
+ output->append(json_events_str->data());
+ if (!has_more_events) {
+ callback.Run();
+ }
+ }
+
+ // End tracing, return tracing data in a simple map
+ // of event name->counts.
+ void EndTracing(std::map<std::string, int> *event_counts) {
+ std::string json_data = "[";
+ base::debug::TraceLog::GetInstance()->SetDisabled();
+ base::RunLoop run_loop;
+ base::debug::TraceLog::GetInstance()->Flush(
+ base::Bind(&GLHelperTest::TraceDataCB,
+ run_loop.QuitClosure(),
+ base::Unretained(&json_data)));
+ run_loop.Run();
+ json_data.append("]");
+
+ scoped_ptr<Value> trace_data(base::JSONReader::Read(json_data));
+ ListValue* list;
+ CHECK(trace_data->GetAsList(&list));
+ for (size_t i = 0; i < list->GetSize(); i++) {
+ base::Value *item = NULL;
+ if (list->Get(i, &item)) {
+ base::DictionaryValue *dict;
+ CHECK(item->GetAsDictionary(&dict));
+ std::string name;
+ CHECK(dict->GetString("name", &name));
+ (*event_counts)[name]++;
+ VLOG(1) << "trace name: " << name;
+ }
+ }
+ }
+
// Bicubic filter kernel function.
static float Bicubic(float x) {
const float a = -0.5;
@@ -455,10 +509,23 @@ class GLHelperTest : public testing::Test {
}
}
+ void FlipSKBitmap(SkBitmap* bitmap) {
+ int top_line = 0;
+ int bottom_line = bitmap->height() - 1;
+ while (top_line < bottom_line) {
+ for (int x = 0; x < bitmap->width(); x++) {
+ std::swap(*bitmap->getAddr32(x, top_line),
+ *bitmap->getAddr32(x, bottom_line));
+ }
+ top_line++;
+ bottom_line--;
+ }
+ }
// gl_helper scales recursively, so we'll need to do that
// in the reference implementation too.
- void ScaleSlowRecursive(SkBitmap* input, SkBitmap* output,
+ void ScaleSlowRecursive(SkBitmap* input,
+ SkBitmap* output,
content::GLHelper::ScalerQuality quality) {
if (quality == content::GLHelper::SCALER_QUALITY_FAST ||
quality == content::GLHelper::SCALER_QUALITY_GOOD) {
@@ -510,7 +577,8 @@ class GLHelperTest : public testing::Test {
void TestScale(int xsize, int ysize,
int scaled_xsize, int scaled_ysize,
int test_pattern,
- size_t quality) {
+ size_t quality,
+ bool flip) {
WebGLId src_texture = context_->createTexture();
WebGLId framebuffer = context_->createFramebuffer();
SkBitmap input_pixels;
@@ -570,7 +638,7 @@ class GLHelperTest : public testing::Test {
gfx::Size(xsize, ysize),
gfx::Rect(0, 0, xsize, ysize),
gfx::Size(scaled_xsize, scaled_ysize),
- false,
+ flip,
false,
&stages);
ValidateScalerStages(kQualities[quality], stages, message);
@@ -579,7 +647,7 @@ class GLHelperTest : public testing::Test {
src_texture,
gfx::Size(xsize, ysize),
gfx::Size(scaled_xsize, scaled_ysize),
- false,
+ flip,
kQualities[quality]);
SkBitmap output_pixels;
@@ -592,7 +660,10 @@ class GLHelperTest : public testing::Test {
dst_texture,
gfx::Rect(0, 0, scaled_xsize, scaled_ysize),
static_cast<unsigned char *>(output_pixels.getPixels()));
-
+ if (flip) {
+ // Flip the pixels back.
+ FlipSKBitmap(&output_pixels);
+ }
if (xsize == scaled_xsize && ysize == scaled_ysize) {
Compare(&input_pixels,
&output_pixels,
@@ -737,6 +808,7 @@ class GLHelperTest : public testing::Test {
int ysize,
SkBitmap* source,
std::string message) {
+ int truth_stride = stride;
for (int x = 0; x < xsize; x++) {
for (int y = 0; y < ysize; y++) {
int a = other[y * stride + x];
@@ -747,7 +819,7 @@ class GLHelperTest : public testing::Test {
<< " " << message;
if (std::abs(a - b) > maxdiff) {
printf("-------expected--------\n");
- PrintPlane(truth, xsize, stride, ysize);
+ PrintPlane(truth, xsize, truth_stride, ysize);
printf("-------actual--------\n");
PrintPlane(other, xsize, stride, ysize);
if (source) {
@@ -774,7 +846,9 @@ class GLHelperTest : public testing::Test {
int xmargin,
int ymargin,
int test_pattern,
- bool use_mrt) {
+ bool flip,
+ bool use_mrt,
+ content::GLHelper::ScalerQuality quality) {
WebGLId src_texture = context_->createTexture();
SkBitmap input_pixels;
input_pixels.setConfig(SkBitmap::kARGB_8888_Config, xsize, ysize);
@@ -826,19 +900,21 @@ class GLHelperTest : public testing::Test {
std::string message = base::StringPrintf("input size: %dx%d "
"output size: %dx%d "
"margin: %dx%d "
- "pattern: %d",
+ "pattern: %d %s %s",
xsize, ysize,
output_xsize, output_ysize,
xmargin, ymargin,
- test_pattern);
+ test_pattern,
+ flip ? "flip" : "noflip",
+ flip ? "mrt" : "nomrt");
scoped_ptr<ReadbackYUVInterface> yuv_reader(
helper_->CreateReadbackPipelineYUV(
- content::GLHelper::SCALER_QUALITY_GOOD,
+ quality,
gfx::Size(xsize, ysize),
gfx::Rect(0, 0, xsize, ysize),
gfx::Size(output_xsize, output_ysize),
gfx::Rect(xmargin, ymargin, xsize, ysize),
- false,
+ flip,
use_mrt));
scoped_refptr<media::VideoFrame> output_frame =
@@ -864,6 +940,10 @@ class GLHelperTest : public testing::Test {
base::Bind(&callcallback, run_loop.QuitClosure()));
run_loop.Run();
+ if (flip) {
+ FlipSKBitmap(&input_pixels);
+ }
+
unsigned char* Y = truth_frame->data(media::VideoFrame::kYPlane);
unsigned char* U = truth_frame->data(media::VideoFrame::kUPlane);
unsigned char* V = truth_frame->data(media::VideoFrame::kVPlane);
@@ -901,16 +981,25 @@ class GLHelperTest : public testing::Test {
}
}
- ComparePlane(Y, output_frame->data(media::VideoFrame::kYPlane), 2,
- output_xsize, y_stride, output_ysize,
+ ComparePlane(Y,
+ output_frame->data(media::VideoFrame::kYPlane), 2,
+ output_xsize,
+ y_stride,
+ output_ysize,
&input_pixels,
message + " Y plane");
- ComparePlane(U, output_frame->data(media::VideoFrame::kUPlane), 2,
- output_xsize / 2, u_stride, output_ysize / 2,
+ ComparePlane(U,
+ output_frame->data(media::VideoFrame::kUPlane), 2,
+ output_xsize / 2,
+ u_stride,
+ output_ysize / 2,
&input_pixels,
message + " U plane");
- ComparePlane(V, output_frame->data(media::VideoFrame::kVPlane), 2,
- output_xsize / 2, v_stride, output_ysize / 2,
+ ComparePlane(V,
+ output_frame->data(media::VideoFrame::kVPlane), 2,
+ output_xsize / 2,
+ v_stride,
+ output_ysize / 2,
&input_pixels,
message + " V plane");
@@ -1108,40 +1197,78 @@ class GLHelperTest : public testing::Test {
"8x1 -> 1x1 bilinear4 X\n");
}
- scoped_ptr<WebKit::WebGraphicsContext3D> context_;
+ scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context_;
+ gpu::ContextSupport* context_support_;
scoped_ptr<content::GLHelper> helper_;
scoped_ptr<content::GLHelperScaling> helper_scaling_;
std::deque<GLHelperScaling::ScaleOp> x_ops_, y_ops_;
};
-// Reenable once http://crbug.com/162291 is fixed.
+TEST_F(GLHelperTest, YUVReadbackOptTest) {
+ // This test uses the cb_command tracing events to detect how many
+ // scaling passes are actually performed by the YUV readback pipeline.
+ StartTracing(TRACE_DISABLED_BY_DEFAULT("cb_command"));
+
+ TestYUVReadback(
+ 800, 400,
+ 800, 400,
+ 0, 0,
+ 1,
+ false,
+ true,
+ content::GLHelper::SCALER_QUALITY_FAST);
+
+ std::map<std::string, int> event_counts;
+ EndTracing(&event_counts);
+ int draw_buffer_calls = event_counts["kDrawBuffersEXTImmediate"];
+ int draw_arrays_calls = event_counts["kDrawArrays"];
+ VLOG(1) << "Draw buffer calls: " << draw_buffer_calls;
+ VLOG(1) << "DrawArrays calls: " << draw_arrays_calls;
+
+ if (draw_buffer_calls) {
+ // When using MRT, the YUV readback code should only
+ // execute two draw arrays, and scaling should be integrated
+ // into those two calls since we are using the FAST scalign
+ // quality.
+ EXPECT_EQ(2, draw_arrays_calls);
+ } else {
+ // When not using MRT, there are three passes for the YUV,
+ // and one for the scaling.
+ EXPECT_EQ(4, draw_arrays_calls);
+ }
+}
+
TEST_F(GLHelperTest, YUVReadbackTest) {
int sizes[] = { 2, 4, 14 };
- for (int use_mrt = 0; use_mrt <= 1 ; use_mrt++) {
- for (unsigned int x = 0; x < arraysize(sizes); x++) {
- for (unsigned int y = 0; y < arraysize(sizes); y++) {
- for (unsigned int ox = x; ox < arraysize(sizes); ox++) {
- for (unsigned int oy = y; oy < arraysize(sizes); oy++) {
- // If output is a subsection of the destination frame, (letterbox)
- // then try different variations of where the subsection goes.
- for (Margin xm = x < ox ? MarginLeft : MarginRight;
- xm <= MarginRight;
- xm = NextMargin(xm)) {
- for (Margin ym = y < oy ? MarginLeft : MarginRight;
- ym <= MarginRight;
- ym = NextMargin(ym)) {
- for (int pattern = 0; pattern < 3; pattern++) {
- TestYUVReadback(
- sizes[x],
- sizes[y],
- sizes[ox],
- sizes[oy],
- compute_margin(sizes[x], sizes[ox], xm),
- compute_margin(sizes[y], sizes[oy], ym),
- pattern,
- use_mrt == 1);
- if (HasFailure()) {
- return;
+ for (int flip = 0; flip <= 1; flip++) {
+ for (int use_mrt = 0; use_mrt <= 1; use_mrt++) {
+ for (unsigned int x = 0; x < arraysize(sizes); x++) {
+ for (unsigned int y = 0; y < arraysize(sizes); y++) {
+ for (unsigned int ox = x; ox < arraysize(sizes); ox++) {
+ for (unsigned int oy = y; oy < arraysize(sizes); oy++) {
+ // If output is a subsection of the destination frame, (letterbox)
+ // then try different variations of where the subsection goes.
+ for (Margin xm = x < ox ? MarginLeft : MarginRight;
+ xm <= MarginRight;
+ xm = NextMargin(xm)) {
+ for (Margin ym = y < oy ? MarginLeft : MarginRight;
+ ym <= MarginRight;
+ ym = NextMargin(ym)) {
+ for (int pattern = 0; pattern < 3; pattern++) {
+ TestYUVReadback(
+ sizes[x],
+ sizes[y],
+ sizes[ox],
+ sizes[oy],
+ compute_margin(sizes[x], sizes[ox], xm),
+ compute_margin(sizes[y], sizes[oy], ym),
+ pattern,
+ flip == 1,
+ use_mrt == 1,
+ content::GLHelper::SCALER_QUALITY_GOOD);
+ if (HasFailure()) {
+ return;
+ }
}
}
}
@@ -1153,25 +1280,27 @@ TEST_F(GLHelperTest, YUVReadbackTest) {
}
}
-
// Per pixel tests, all sizes are small so that we can print
// out the generated bitmaps.
TEST_F(GLHelperTest, ScaleTest) {
int sizes[] = {3, 6, 16};
- for (size_t q = 0; q < arraysize(kQualities); q++) {
- for (int x = 0; x < 3; x++) {
- for (int y = 0; y < 3; y++) {
- for (int dst_x = 0; dst_x < 3; dst_x++) {
- for (int dst_y = 0; dst_y < 3; dst_y++) {
- for (int pattern = 0; pattern < 3; pattern++) {
- TestScale(sizes[x],
- sizes[y],
- sizes[dst_x],
- sizes[dst_y],
- pattern,
- q);
- if (HasFailure()) {
- return;
+ for (int flip = 0; flip <= 1; flip++) {
+ for (size_t q = 0; q < arraysize(kQualities); q++) {
+ for (int x = 0; x < 3; x++) {
+ for (int y = 0; y < 3; y++) {
+ for (int dst_x = 0; dst_x < 3; dst_x++) {
+ for (int dst_y = 0; dst_y < 3; dst_y++) {
+ for (int pattern = 0; pattern < 3; pattern++) {
+ TestScale(sizes[x],
+ sizes[y],
+ sizes[dst_x],
+ sizes[dst_y],
+ pattern,
+ q,
+ flip == 1);
+ if (HasFailure()) {
+ return;
+ }
}
}
}
diff --git a/chromium/content/common/gpu/client/gl_surface_capturer_host.cc b/chromium/content/common/gpu/client/gl_surface_capturer_host.cc
deleted file mode 100644
index c34fcfbda9d..00000000000
--- a/chromium/content/common/gpu/client/gl_surface_capturer_host.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gl_surface_capturer_host.h"
-
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "ipc/ipc_message_macros.h"
-
-namespace content {
-
-namespace {
-
-enum {
- kNumCaptureBuffers = 2,
- kMaxCaptureSize = 4096,
-};
-
-} // anonymous namespace
-
-GLSurfaceCapturerHost::GLSurfaceCapturerHost(int32 capturer_route_id,
- SurfaceCapturer::Client* client,
- CommandBufferProxyImpl* impl)
- : thread_checker_(),
- capturer_route_id_(capturer_route_id),
- weak_this_factory_(this),
- client_(client),
- impl_(impl),
- channel_(impl_->channel()),
- next_frame_id_(0) {
- DCHECK(thread_checker_.CalledOnValidThread());
- channel_->AddRoute(capturer_route_id_, weak_this_factory_.GetWeakPtr());
- impl_->AddDeletionObserver(this);
-}
-
-void GLSurfaceCapturerHost::OnChannelError() {
- DLOG(ERROR) << "OnChannelError()";
- DCHECK(thread_checker_.CalledOnValidThread());
- OnNotifyError(kPlatformFailureError);
- if (channel_) {
- weak_this_factory_.InvalidateWeakPtrs();
- channel_->RemoveRoute(capturer_route_id_);
- channel_ = NULL;
- }
-}
-
-bool GLSurfaceCapturerHost::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(GLSurfaceCapturerHost, message)
- IPC_MESSAGE_HANDLER(SurfaceCapturerHostMsg_NotifyCaptureParameters,
- OnNotifyCaptureParameters)
- IPC_MESSAGE_HANDLER(SurfaceCapturerHostMsg_NotifyCopyCaptureDone,
- OnNotifyCopyCaptureDone)
- IPC_MESSAGE_HANDLER(SurfaceCapturerHostMsg_NotifyError, OnNotifyError)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void GLSurfaceCapturerHost::Initialize(media::VideoFrame::Format format) {
- DCHECK(thread_checker_.CalledOnValidThread());
- Send(new SurfaceCapturerMsg_Initialize(capturer_route_id_, format));
-}
-
-void GLSurfaceCapturerHost::TryCapture() {
- DCHECK(thread_checker_.CalledOnValidThread());
- Send(new SurfaceCapturerMsg_TryCapture(capturer_route_id_));
-}
-
-void GLSurfaceCapturerHost::CopyCaptureToVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!channel_)
- return;
- if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) {
- DLOG(ERROR) << "CopyCaptureToVideoFrame(): cannot capture to frame not "
- "backed by shared memory";
- OnNotifyError(kPlatformFailureError);
- return;
- }
- base::SharedMemoryHandle handle =
- channel_->ShareToGpuProcess(frame->shared_memory_handle());
- if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) {
- DLOG(ERROR) << "CopyCaptureToVideoFrame(): failed to duplicate buffer "
- "handle for GPU process";
- OnNotifyError(kPlatformFailureError);
- return;
- }
-
- const size_t plane_count = media::VideoFrame::NumPlanes(frame->format());
- size_t frame_size = 0;
- for (size_t i = 0; i < plane_count; ++i) {
- DCHECK_EQ(reinterpret_cast<void*>(frame->data(i)),
- reinterpret_cast<void*>((frame->data(0) + frame_size)))
- << "plane=" << i;
- frame_size += frame->stride(i) * frame->rows(i);
- }
-
- Send(new SurfaceCapturerMsg_CopyCaptureToVideoFrame(
- capturer_route_id_, next_frame_id_, handle, frame_size));
- frame_map_[next_frame_id_] = frame;
- next_frame_id_ = (next_frame_id_ + 1) & 0x3FFFFFFF;
-}
-
-void GLSurfaceCapturerHost::Destroy() {
- DCHECK(thread_checker_.CalledOnValidThread());
- client_ = NULL;
- Send(new SurfaceCapturerMsg_Destroy(capturer_route_id_));
- delete this;
-}
-
-void GLSurfaceCapturerHost::OnWillDeleteImpl() {
- DCHECK(thread_checker_.CalledOnValidThread());
- impl_ = NULL;
- OnChannelError();
-}
-
-GLSurfaceCapturerHost::~GLSurfaceCapturerHost() {
- DCHECK(thread_checker_.CalledOnValidThread());
- weak_this_factory_.InvalidateWeakPtrs();
- if (channel_)
- channel_->RemoveRoute(capturer_route_id_);
- if (impl_)
- impl_->RemoveDeletionObserver(this);
-}
-
-void GLSurfaceCapturerHost::NotifyError(Error error) {
- DCHECK(thread_checker_.CalledOnValidThread());
- base::MessageLoopProxy::current()->PostTask(
- FROM_HERE,
- base::Bind(&GLSurfaceCapturerHost::OnNotifyError,
- weak_this_factory_.GetWeakPtr(),
- error));
-}
-
-void GLSurfaceCapturerHost::OnNotifyCaptureParameters(
- const gfx::Size& buffer_size,
- const gfx::Rect& visible_rect) {
- DVLOG(2) << "OnNotifyCaptureParameters(): "
- "buffer_size=" << buffer_size.ToString()
- << ", visible_rect=" << visible_rect.ToString();
- DCHECK(thread_checker_.CalledOnValidThread());
- if (buffer_size.width() < 1 || buffer_size.width() > kMaxCaptureSize ||
- buffer_size.height() < 1 || buffer_size.height() > kMaxCaptureSize ||
- visible_rect.x() < 0 || visible_rect.x() > kMaxCaptureSize - 1 ||
- visible_rect.y() < 0 || visible_rect.y() > kMaxCaptureSize - 1 ||
- visible_rect.width() < 1 || visible_rect.width() > kMaxCaptureSize ||
- visible_rect.height() < 1 || visible_rect.height() > kMaxCaptureSize) {
- DLOG(ERROR) << "OnNotifyCaptureParameters(): parameters out of bounds: "
- "buffer_size=" << buffer_size.ToString()
- << ", visible_rect=" << visible_rect.ToString();
- OnNotifyError(kPlatformFailureError);
- return;
- }
- if (client_)
- client_->NotifyCaptureParameters(buffer_size, visible_rect);
-}
-
-void GLSurfaceCapturerHost::OnNotifyCopyCaptureDone(int32 frame_id) {
- DVLOG(3) << "OnNotifyCopyCaptureDone(): frame_id=" << frame_id;
- DCHECK(thread_checker_.CalledOnValidThread());
- FrameMap::iterator iter = frame_map_.find(frame_id);
- if (iter == frame_map_.end()) {
- DLOG(ERROR) << "OnNotifyCopyCaptureDone(): invalid frame_id=" << frame_id;
- OnNotifyError(kPlatformFailureError);
- return;
- }
- if (client_)
- client_->NotifyCopyCaptureDone(iter->second);
- frame_map_.erase(iter);
-}
-
-void GLSurfaceCapturerHost::OnNotifyError(Error error) {
- DVLOG(2) << "OnNotifyError(): error=" << error;
- DCHECK(thread_checker_.CalledOnValidThread());
- if (client_) {
- client_->NotifyError(error);
- client_ = NULL;
- }
-}
-
-void GLSurfaceCapturerHost::Send(IPC::Message* message) {
- DCHECK(thread_checker_.CalledOnValidThread());
- uint32 type = message->type();
- if (!channel_) {
- DLOG(ERROR) << "Send(): no channel";
- delete message;
- NotifyError(kPlatformFailureError);
- } else if (!channel_->Send(message)) {
- DLOG(ERROR) << "Send(): failed: message->type()=" << type;
- NotifyError(kPlatformFailureError);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gl_surface_capturer_host.h b/chromium/content/common/gpu/client/gl_surface_capturer_host.h
deleted file mode 100644
index d90afcd212d..00000000000
--- a/chromium/content/common/gpu/client/gl_surface_capturer_host.h
+++ /dev/null
@@ -1,107 +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_COMMON_GPU_CLIENT_GL_SURFACE_CAPTURER_HOST_H_
-#define CONTENT_COMMON_GPU_CLIENT_GL_SURFACE_CAPTURER_HOST_H_
-
-#include "base/containers/small_map.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "content/common/gpu/client/command_buffer_proxy_impl.h"
-#include "content/common/gpu/surface_capturer.h"
-#include "ipc/ipc_listener.h"
-
-namespace gfx {
-
-class Rect;
-class Size;
-
-} // namespace gfx
-
-namespace media {
-
-class VideoFrame;
-
-} // namespace media
-
-namespace content {
-
-class GpuChannelHost;
-
-// This class is the browser-side host for the SurfaceCapturer in the GPU
-// process, coordinated over IPC.
-class GLSurfaceCapturerHost : public IPC::Listener,
- public SurfaceCapturer,
- public CommandBufferProxyImpl::DeletionObserver {
- public:
- // |client| is expected to outlive this object. We are registered as a
- // DeletionObserver with |impl|, so it will notify us when it is about to
- // be destroyed.
- GLSurfaceCapturerHost(int32 capturer_route_id,
- SurfaceCapturer::Client* client,
- CommandBufferProxyImpl* impl);
-
- // IPC::Listener implementation.
- virtual void OnChannelError() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- // SurfaceCapturer implementation.
- virtual void Initialize(media::VideoFrame::Format format) OVERRIDE;
- virtual void TryCapture() OVERRIDE;
- virtual void CopyCaptureToVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
- virtual void Destroy() OVERRIDE;
-
- // CommandBufferProxyImpl::DeletionObserver implementation.
- virtual void OnWillDeleteImpl() OVERRIDE;
-
- private:
- virtual ~GLSurfaceCapturerHost();
-
- // Notify |client_| when an error has occured. Used when notifying from
- // within a media::VideoEncodeAccelerator entry point, to avoid re-entrancy.
- void NotifyError(Error error);
-
- // IPC handlers, proxying SurfaceCapturer::Client for the GPU process.
- void OnNotifyCaptureParameters(const gfx::Size& buffer_size,
- const gfx::Rect& visible_rect);
- void OnNotifyCopyCaptureDone(int32 frame_id);
- void OnNotifyError(Error error);
-
- void Send(IPC::Message* message);
-
- const base::ThreadChecker thread_checker_;
-
- // Route ID for corresponding GLSurfaceCapturer in the GPU process.
- const int32 capturer_route_id_;
-
- // Weak pointer for registering as a listener for |channel_|.
- base::WeakPtrFactory<GLSurfaceCapturerHost> weak_this_factory_;
-
- // SurfaceEncoder::Client callbacks received over IPC are forwarded to
- // |client_|.
- SurfaceCapturer::Client* client_;
-
- // Unowned reference to the CommandBufferProxyImpl that created us.
- CommandBufferProxyImpl* impl_;
-
- // GPU process channel to send messages on.
- GpuChannelHost* channel_;
-
- // media::VideoFrames sent to the capturer.
- // base::IDMap not used here, since that takes pointers, not scoped_refptr.
- typedef base::SmallMap<std::map<int32, scoped_refptr<media::VideoFrame> > >
- FrameMap;
- FrameMap frame_map_;
-
- // ID serial number for next frame to send to the GPU process.
- int32 next_frame_id_;
-
- DISALLOW_COPY_AND_ASSIGN(GLSurfaceCapturerHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GL_SURFACE_CAPTURER_HOST_H_
diff --git a/chromium/content/common/gpu/client/gpu_channel_host.cc b/chromium/content/common/gpu/client/gpu_channel_host.cc
index 27c71de98a1..705f4b9dc35 100644
--- a/chromium/content/common/gpu/client/gpu_channel_host.cc
+++ b/chromium/content/common/gpu/client/gpu_channel_host.cc
@@ -36,25 +36,37 @@ GpuListenerInfo::~GpuListenerInfo() {}
scoped_refptr<GpuChannelHost> GpuChannelHost::Create(
GpuChannelHostFactory* factory,
int gpu_host_id,
- int client_id,
const gpu::GPUInfo& gpu_info,
const IPC::ChannelHandle& channel_handle) {
DCHECK(factory->IsMainThread());
scoped_refptr<GpuChannelHost> host = new GpuChannelHost(
- factory, gpu_host_id, client_id, gpu_info);
+ factory, gpu_host_id, gpu_info);
host->Connect(channel_handle);
return host;
}
+// static
+bool GpuChannelHost::IsValidGpuMemoryBuffer(
+ gfx::GpuMemoryBufferHandle handle) {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER:
+#if defined(OS_MACOSX)
+ case gfx::IO_SURFACE_BUFFER:
+#endif
+ return true;
+ default:
+ return false;
+ }
+}
+
GpuChannelHost::GpuChannelHost(GpuChannelHostFactory* factory,
int gpu_host_id,
- int client_id,
const gpu::GPUInfo& gpu_info)
: factory_(factory),
- client_id_(client_id),
gpu_host_id_(gpu_host_id),
gpu_info_(gpu_info) {
next_transfer_buffer_id_.GetNext();
+ next_gpu_memory_buffer_id_.GetNext();
}
void GpuChannelHost::Connect(const IPC::ChannelHandle& channel_handle) {
@@ -246,8 +258,8 @@ base::SharedMemoryHandle GpuChannelHost::ShareToGpuProcess(
if (!BrokerDuplicateHandle(source_handle,
channel_->peer_pid(),
&target_handle,
- 0,
- DUPLICATE_SAME_ACCESS)) {
+ FILE_GENERIC_READ | FILE_GENERIC_WRITE,
+ 0)) {
return base::SharedMemory::NULLHandle();
}
@@ -285,6 +297,29 @@ int32 GpuChannelHost::ReserveTransferBufferId() {
return next_transfer_buffer_id_.GetNext();
}
+gfx::GpuMemoryBufferHandle GpuChannelHost::ShareGpuMemoryBufferToGpuProcess(
+ gfx::GpuMemoryBufferHandle source_handle) {
+ switch (source_handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER: {
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::SHARED_MEMORY_BUFFER;
+ handle.handle = ShareToGpuProcess(source_handle.handle);
+ return handle;
+ }
+#if defined(OS_MACOSX)
+ case gfx::IO_SURFACE_BUFFER:
+ return source_handle;
+#endif
+ default:
+ NOTREACHED();
+ return gfx::GpuMemoryBufferHandle();
+ }
+}
+
+int32 GpuChannelHost::ReserveGpuMemoryBufferId() {
+ return next_gpu_memory_buffer_id_.GetNext();
+}
+
GpuChannelHost::~GpuChannelHost() {
// channel_ must be destroyed on the main thread.
if (!factory_->IsMainThread())
diff --git a/chromium/content/common/gpu/client/gpu_channel_host.h b/chromium/content/common/gpu/client/gpu_channel_host.h
index 5efa98dab45..52ffb382bd0 100644
--- a/chromium/content/common/gpu/client/gpu_channel_host.h
+++ b/chromium/content/common/gpu/client/gpu_channel_host.h
@@ -24,6 +24,7 @@
#include "ipc/ipc_sync_channel.h"
#include "media/video/video_decode_accelerator.h"
#include "media/video/video_encode_accelerator.h"
+#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
#include "ui/gl/gpu_preference.h"
@@ -71,12 +72,15 @@ class CONTENT_EXPORT GpuChannelHostFactory {
virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(size_t size) = 0;
virtual int32 CreateViewCommandBuffer(
int32 surface_id, const GPUCreateCommandBufferConfig& init_params) = 0;
- virtual GpuChannelHost* EstablishGpuChannelSync(CauseForGpuLaunch) = 0;
virtual void CreateImage(
gfx::PluginWindowHandle window,
int32 image_id,
const CreateImageCallback& callback) = 0;
virtual void DeleteImage(int32 image_id, int32 sync_point) = 0;
+ virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat) = 0;
};
// Encapsulates an IPC channel between the client and one GPU process.
@@ -90,10 +94,13 @@ class GpuChannelHost : public IPC::Sender,
static scoped_refptr<GpuChannelHost> Create(
GpuChannelHostFactory* factory,
int gpu_host_id,
- int client_id,
const gpu::GPUInfo& gpu_info,
const IPC::ChannelHandle& channel_handle);
+ // Returns true if |handle| is a valid GpuMemoryBuffer handle that
+ // can be shared to the GPU process.
+ static bool IsValidGpuMemoryBuffer(gfx::GpuMemoryBufferHandle handle);
+
bool IsLost() const {
DCHECK(channel_filter_.get());
return channel_filter_->IsLost();
@@ -145,8 +152,6 @@ class GpuChannelHost : public IPC::Sender,
GpuChannelHostFactory* factory() const { return factory_; }
int gpu_host_id() const { return gpu_host_id_; }
- int client_id() const { return client_id_; }
-
// Returns a handle to the shared memory that can be sent via IPC to the
// GPU process. The caller is responsible for ensuring it is closed. Returns
// an invalid handle on failure.
@@ -162,11 +167,19 @@ class GpuChannelHost : public IPC::Sender,
// Reserve one unused transfer buffer ID.
int32 ReserveTransferBufferId();
+ // Returns a GPU memory buffer handle to the buffer that can be sent via
+ // IPC to the GPU process. The caller is responsible for ensuring it is
+ // closed. Returns an invalid handle on failure.
+ gfx::GpuMemoryBufferHandle ShareGpuMemoryBufferToGpuProcess(
+ gfx::GpuMemoryBufferHandle source_handle);
+
+ // Reserve one unused gpu memory buffer ID.
+ int32 ReserveGpuMemoryBufferId();
+
private:
friend class base::RefCountedThreadSafe<GpuChannelHost>;
GpuChannelHost(GpuChannelHostFactory* factory,
int gpu_host_id,
- int client_id,
const gpu::GPUInfo& gpu_info);
virtual ~GpuChannelHost();
void Connect(const IPC::ChannelHandle& channel_handle);
@@ -212,7 +225,7 @@ class GpuChannelHost : public IPC::Sender,
typedef base::hash_map<int, GpuListenerInfo> ListenerMap;
ListenerMap listeners_;
- // Protexts all fields below this one.
+ // Protects all fields below this one.
mutable base::Lock lock_;
// Whether the channel has been lost.
@@ -228,9 +241,9 @@ class GpuChannelHost : public IPC::Sender,
// Threading notes: all fields are constant during the lifetime of |this|
// except:
// - |next_transfer_buffer_id_|, atomic type
+ // - |next_gpu_memory_buffer_id_|, atomic type
// - |proxies_|, protected by |context_lock_|
GpuChannelHostFactory* const factory_;
- const int client_id_;
const int gpu_host_id_;
const gpu::GPUInfo gpu_info_;
@@ -244,6 +257,9 @@ class GpuChannelHost : public IPC::Sender,
// Transfer buffer IDs are allocated in sequence.
base::AtomicSequenceNumber next_transfer_buffer_id_;
+ // Gpu memory buffer IDs are allocated in sequence.
+ base::AtomicSequenceNumber next_gpu_memory_buffer_id_;
+
// Protects proxies_.
mutable base::Lock context_lock_;
// Used to look up a proxy from its routing id.
diff --git a/chromium/content/common/gpu/client/gpu_context_tests.h b/chromium/content/common/gpu/client/gpu_context_tests.h
index c1eb57baf43..5b8fb4970be 100644
--- a/chromium/content/common/gpu/client/gpu_context_tests.h
+++ b/chromium/content/common/gpu/client/gpu_context_tests.h
@@ -8,72 +8,86 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "cc/resources/sync_point_helper.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/context_support.h"
namespace {
class SignalTest : public ContextTestBase {
public:
- static void RunOnlyOnce(base::Closure cb, int *tmp) {
+ static void RunOnlyOnce(base::Closure cb, int* tmp) {
CHECK_EQ(*tmp, 0);
++*tmp;
cb.Run();
}
// These tests should time out if the callback doesn't get called.
- void testSignalSyncPoint(unsigned sync_point) {
+ void TestSignalSyncPoint(unsigned sync_point) {
base::RunLoop run_loop;
- cc::SyncPointHelper::SignalSyncPoint(
- context_.get(), sync_point, run_loop.QuitClosure());
+ context_support_->SignalSyncPoint(sync_point, run_loop.QuitClosure());
run_loop.Run();
}
// These tests should time out if the callback doesn't get called.
- void testSignalQuery(WebKit::WebGLId query) {
+ void TestSignalQuery(blink::WebGLId query) {
base::RunLoop run_loop;
- cc::SyncPointHelper::SignalQuery(
- context_.get(), query,
- base::Bind(&RunOnlyOnce, run_loop.QuitClosure(),
- base::Owned(new int(0))));
+ context_support_->SignalQuery(
+ query,
+ base::Bind(
+ &RunOnlyOnce, run_loop.QuitClosure(), base::Owned(new int(0))));
run_loop.Run();
}
};
CONTEXT_TEST_F(SignalTest, BasicSignalSyncPointTest) {
- testSignalSyncPoint(context_->insertSyncPoint());
+ if (!context_)
+ return;
+
+ TestSignalSyncPoint(context_->insertSyncPoint());
};
CONTEXT_TEST_F(SignalTest, InvalidSignalSyncPointTest) {
+ if (!context_)
+ return;
+
// Signalling something that doesn't exist should run the callback
// immediately.
- testSignalSyncPoint(1297824234);
+ TestSignalSyncPoint(1297824234);
};
CONTEXT_TEST_F(SignalTest, BasicSignalQueryTest) {
+ if (!context_)
+ return;
+
unsigned query = context_->createQueryEXT();
context_->beginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, query);
context_->finish();
context_->endQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
- testSignalQuery(query);
+ TestSignalQuery(query);
context_->deleteQueryEXT(query);
};
CONTEXT_TEST_F(SignalTest, SignalQueryUnboundTest) {
- WebKit::WebGLId query = context_->createQueryEXT();
- testSignalQuery(query);
+ if (!context_)
+ return;
+
+ blink::WebGLId query = context_->createQueryEXT();
+ TestSignalQuery(query);
context_->deleteQueryEXT(query);
};
CONTEXT_TEST_F(SignalTest, InvalidSignalQueryUnboundTest) {
+ if (!context_)
+ return;
+
// Signalling something that doesn't exist should run the callback
// immediately.
- testSignalQuery(928729087);
- testSignalQuery(928729086);
- testSignalQuery(928729085);
- testSignalQuery(928729083);
- testSignalQuery(928729082);
- testSignalQuery(928729081);
+ TestSignalQuery(928729087);
+ TestSignalQuery(928729086);
+ TestSignalQuery(928729085);
+ TestSignalQuery(928729083);
+ TestSignalQuery(928729082);
+ TestSignalQuery(928729081);
};
};
diff --git a/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc b/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc
index dde4285b3e3..7be78905e1f 100644
--- a/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc
+++ b/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc
@@ -14,13 +14,16 @@
namespace {
+using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
+
class ContextTestBase : public testing::Test {
public:
virtual void SetUp() {
- WebKit::WebGraphicsContext3D::Attributes attributes;
- context_ = webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl::
+ blink::WebGraphicsContext3D::Attributes attributes;
+ context_ = WebGraphicsContext3DInProcessCommandBufferImpl::
CreateOffscreenContext(attributes);
context_->makeContextCurrent();
+ context_support_ = context_->GetContextSupport();
}
virtual void TearDown() {
@@ -28,7 +31,8 @@ class ContextTestBase : public testing::Test {
}
protected:
- scoped_ptr<WebKit::WebGraphicsContext3D> context_;
+ scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context_;
+ gpu::ContextSupport* context_support_;
};
} // namespace
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc
new file mode 100644
index 00000000000..c469a078f57
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+
+#include "ui/gl/gl_bindings.h"
+
+namespace content {
+
+GpuMemoryBufferImpl::GpuMemoryBufferImpl(
+ gfx::Size size, unsigned internalformat)
+ : size_(size),
+ internalformat_(internalformat),
+ mapped_(false) {
+ DCHECK(IsFormatValid(internalformat));
+}
+
+GpuMemoryBufferImpl::~GpuMemoryBufferImpl() {
+}
+
+// static
+bool GpuMemoryBufferImpl::IsFormatValid(unsigned internalformat) {
+ switch (internalformat) {
+ case GL_BGRA8_EXT:
+ case GL_RGBA8_OES:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// static
+size_t GpuMemoryBufferImpl::BytesPerPixel(unsigned internalformat) {
+ switch (internalformat) {
+ case GL_BGRA8_EXT:
+ case GL_RGBA8_OES:
+ return 4;
+ default:
+ NOTREACHED();
+ return 0;
+ }
+}
+
+bool GpuMemoryBufferImpl::IsMapped() const {
+ return mapped_;
+}
+
+uint32 GpuMemoryBufferImpl::GetStride() const {
+ return size_.width() * BytesPerPixel(internalformat_);
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl.h
new file mode 100644
index 00000000000..ee85f0f7b57
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl.h
@@ -0,0 +1,43 @@
+// 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_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_H_
+#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+// Provides common implementation of a GPU memory buffer.
+class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
+ public:
+ static scoped_ptr<GpuMemoryBufferImpl> Create(
+ gfx::GpuMemoryBufferHandle handle,
+ gfx::Size size,
+ unsigned internalformat);
+
+ virtual ~GpuMemoryBufferImpl();
+
+ static bool IsFormatValid(unsigned internalformat);
+ static size_t BytesPerPixel(unsigned internalformat);
+
+ // Overridden from gfx::GpuMemoryBuffer:
+ virtual bool IsMapped() const OVERRIDE;
+ virtual uint32 GetStride() const OVERRIDE;
+
+ protected:
+ GpuMemoryBufferImpl(gfx::Size size, unsigned internalformat);
+
+ const gfx::Size size_;
+ unsigned internalformat_;
+ bool mapped_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_android.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_android.cc
new file mode 100644
index 00000000000..ffd4e381c7d
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_android.cc
@@ -0,0 +1,29 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
+
+namespace content {
+
+scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create(
+ gfx::GpuMemoryBufferHandle handle,
+ gfx::Size size,
+ unsigned internalformat) {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER: {
+ scoped_ptr<GpuMemoryBufferImplShm> buffer(
+ new GpuMemoryBufferImplShm(size, internalformat));
+ if (!buffer->Initialize(handle))
+ return scoped_ptr<GpuMemoryBufferImpl>();
+
+ return buffer.PassAs<GpuMemoryBufferImpl>();
+ }
+ default:
+ return scoped_ptr<GpuMemoryBufferImpl>();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc
new file mode 100644
index 00000000000..abc99076d1d
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc
@@ -0,0 +1,79 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h"
+
+#include "base/logging.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/io_surface_support_mac.h"
+
+namespace content {
+
+GpuMemoryBufferImplIOSurface::GpuMemoryBufferImplIOSurface(
+ gfx::Size size, unsigned internalformat)
+ : GpuMemoryBufferImpl(size, internalformat),
+ io_surface_support_(IOSurfaceSupport::Initialize()) {
+ CHECK(io_surface_support_);
+}
+
+GpuMemoryBufferImplIOSurface::~GpuMemoryBufferImplIOSurface() {
+}
+
+// static
+bool GpuMemoryBufferImplIOSurface::IsFormatSupported(unsigned internalformat) {
+ switch (internalformat) {
+ case GL_BGRA8_EXT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// static
+uint32 GpuMemoryBufferImplIOSurface::PixelFormat(unsigned internalformat) {
+ switch (internalformat) {
+ case GL_BGRA8_EXT:
+ return 'BGRA';
+ default:
+ NOTREACHED();
+ return 0;
+ }
+}
+
+bool GpuMemoryBufferImplIOSurface::Initialize(
+ gfx::GpuMemoryBufferHandle handle) {
+ io_surface_.reset(io_surface_support_->IOSurfaceLookup(handle.io_surface_id));
+ if (!io_surface_) {
+ VLOG(1) << "IOSurface lookup failed";
+ return false;
+ }
+
+ return true;
+}
+
+void GpuMemoryBufferImplIOSurface::Map(AccessMode mode, void** vaddr) {
+ DCHECK(!mapped_);
+ io_surface_support_->IOSurfaceLock(io_surface_, 0, NULL);
+ *vaddr = io_surface_support_->IOSurfaceGetBaseAddress(io_surface_);
+ mapped_ = true;
+}
+
+void GpuMemoryBufferImplIOSurface::Unmap() {
+ DCHECK(mapped_);
+ io_surface_support_->IOSurfaceUnlock(io_surface_, 0, NULL);
+ mapped_ = false;
+}
+
+uint32 GpuMemoryBufferImplIOSurface::GetStride() const {
+ return io_surface_support_->IOSurfaceGetBytesPerRow(io_surface_);
+}
+
+gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIOSurface::GetHandle() const {
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::IO_SURFACE_BUFFER;
+ handle.io_surface_id = io_surface_support_->IOSurfaceGetID(io_surface_);
+ return handle;
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h
new file mode 100644
index 00000000000..da2936a3800
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h
@@ -0,0 +1,42 @@
+// 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_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_IO_SURFACE_H_
+#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_IO_SURFACE_H_
+
+#include "base/mac/scoped_cftyperef.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+
+class IOSurfaceSupport;
+
+namespace content {
+
+// Provides implementation of a GPU memory buffer based
+// on an IO surface handle.
+class GpuMemoryBufferImplIOSurface : public GpuMemoryBufferImpl {
+ public:
+ GpuMemoryBufferImplIOSurface(gfx::Size size, unsigned internalformat);
+ virtual ~GpuMemoryBufferImplIOSurface();
+
+ static bool IsFormatSupported(unsigned internalformat);
+ static uint32 PixelFormat(unsigned internalformat);
+
+ bool Initialize(gfx::GpuMemoryBufferHandle handle);
+
+ // Overridden from gfx::GpuMemoryBuffer:
+ virtual void Map(AccessMode mode, void** vaddr) OVERRIDE;
+ virtual void Unmap() OVERRIDE;
+ virtual uint32 GetStride() const OVERRIDE;
+ virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE;
+
+ private:
+ IOSurfaceSupport* io_surface_support_;
+ base::ScopedCFTypeRef<CFTypeRef> io_surface_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplIOSurface);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_IO_SURFACE_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc
new file mode 100644
index 00000000000..ffd4e381c7d
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc
@@ -0,0 +1,29 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
+
+namespace content {
+
+scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create(
+ gfx::GpuMemoryBufferHandle handle,
+ gfx::Size size,
+ unsigned internalformat) {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER: {
+ scoped_ptr<GpuMemoryBufferImplShm> buffer(
+ new GpuMemoryBufferImplShm(size, internalformat));
+ if (!buffer->Initialize(handle))
+ return scoped_ptr<GpuMemoryBufferImpl>();
+
+ return buffer.PassAs<GpuMemoryBufferImpl>();
+ }
+ default:
+ return scoped_ptr<GpuMemoryBufferImpl>();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc
new file mode 100644
index 00000000000..1c8e5521a01
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc
@@ -0,0 +1,38 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
+
+namespace content {
+
+scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create(
+ gfx::GpuMemoryBufferHandle handle,
+ gfx::Size size,
+ unsigned internalformat) {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER: {
+ scoped_ptr<GpuMemoryBufferImplShm> buffer(
+ new GpuMemoryBufferImplShm(size, internalformat));
+ if (!buffer->Initialize(handle))
+ return scoped_ptr<GpuMemoryBufferImpl>();
+
+ return buffer.PassAs<GpuMemoryBufferImpl>();
+ }
+ case gfx::IO_SURFACE_BUFFER: {
+ scoped_ptr<GpuMemoryBufferImplIOSurface> buffer(
+ new GpuMemoryBufferImplIOSurface(size, internalformat));
+ if (!buffer->Initialize(handle))
+ return scoped_ptr<GpuMemoryBufferImpl>();
+
+ return buffer.PassAs<GpuMemoryBufferImpl>();
+ }
+ default:
+ return scoped_ptr<GpuMemoryBufferImpl>();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.cc
new file mode 100644
index 00000000000..7af4452be1a
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.cc
@@ -0,0 +1,56 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+GpuMemoryBufferImplShm::GpuMemoryBufferImplShm(
+ gfx::Size size, unsigned internalformat)
+ : GpuMemoryBufferImpl(size, internalformat) {
+}
+
+GpuMemoryBufferImplShm::~GpuMemoryBufferImplShm() {
+}
+
+bool GpuMemoryBufferImplShm::Initialize(gfx::GpuMemoryBufferHandle handle) {
+ if (!base::SharedMemory::IsHandleValid(handle.handle))
+ return false;
+ shared_memory_.reset(new base::SharedMemory(handle.handle, false));
+ DCHECK(!shared_memory_->memory());
+ return true;
+}
+
+bool GpuMemoryBufferImplShm::InitializeFromSharedMemory(
+ scoped_ptr<base::SharedMemory> shared_memory) {
+ shared_memory_ = shared_memory.Pass();
+ DCHECK(!shared_memory_->memory());
+ return true;
+}
+
+void GpuMemoryBufferImplShm::Map(AccessMode mode, void** vaddr) {
+ DCHECK(!mapped_);
+ *vaddr = NULL;
+ if (!shared_memory_->Map(size_.GetArea() * BytesPerPixel(internalformat_)))
+ return;
+ *vaddr = shared_memory_->memory();
+ mapped_ = true;
+}
+
+void GpuMemoryBufferImplShm::Unmap() {
+ DCHECK(mapped_);
+ shared_memory_->Unmap();
+ mapped_ = false;
+}
+
+gfx::GpuMemoryBufferHandle GpuMemoryBufferImplShm::GetHandle() const {
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::SHARED_MEMORY_BUFFER;
+ handle.handle = shared_memory_->handle();
+ return handle;
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.h
new file mode 100644
index 00000000000..be86aabea3c
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.h
@@ -0,0 +1,36 @@
+// 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_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHM_H_
+#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHM_H_
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+
+namespace content {
+
+// Provides implementation of a GPU memory buffer based
+// on a shared memory handle.
+class GpuMemoryBufferImplShm : public GpuMemoryBufferImpl {
+ public:
+ GpuMemoryBufferImplShm(gfx::Size size, unsigned internalformat);
+ virtual ~GpuMemoryBufferImplShm();
+
+ bool Initialize(gfx::GpuMemoryBufferHandle handle);
+ bool InitializeFromSharedMemory(
+ scoped_ptr<base::SharedMemory> shared_memory);
+
+ // Overridden from gfx::GpuMemoryBuffer:
+ virtual void Map(AccessMode mode, void** vaddr) OVERRIDE;
+ virtual void Unmap() OVERRIDE;
+ virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE;
+
+ private:
+ scoped_ptr<base::SharedMemory> shared_memory_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplShm);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHM_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_win.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_win.cc
new file mode 100644
index 00000000000..ffd4e381c7d
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_win.cc
@@ -0,0 +1,29 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
+
+namespace content {
+
+scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create(
+ gfx::GpuMemoryBufferHandle handle,
+ gfx::Size size,
+ unsigned internalformat) {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER: {
+ scoped_ptr<GpuMemoryBufferImplShm> buffer(
+ new GpuMemoryBufferImplShm(size, internalformat));
+ if (!buffer->Initialize(handle))
+ return scoped_ptr<GpuMemoryBufferImpl>();
+
+ return buffer.PassAs<GpuMemoryBufferImpl>();
+ }
+ default:
+ return scoped_ptr<GpuMemoryBufferImpl>();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc b/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
index fcf36bf4eb3..403d2961cd3 100644
--- a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
+++ b/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
@@ -103,15 +103,17 @@ void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers(
// Rearrange data for IPC command.
std::vector<int32> buffer_ids;
std::vector<uint32> texture_ids;
- std::vector<gfx::Size> sizes;
for (uint32 i = 0; i < buffers.size(); i++) {
const media::PictureBuffer& buffer = buffers[i];
+ if (buffer.size() != picture_buffer_dimensions_) {
+ OnErrorNotification(INVALID_ARGUMENT);
+ return;
+ }
texture_ids.push_back(buffer.texture_id());
buffer_ids.push_back(buffer.id());
- sizes.push_back(buffer.size());
}
Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
- decoder_route_id_, buffer_ids, texture_ids, sizes));
+ decoder_route_id_, buffer_ids, texture_ids));
}
void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
@@ -184,12 +186,13 @@ void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer(
uint32 num_requested_buffers,
- const gfx::Size& buffer_size,
+ const gfx::Size& dimensions,
uint32 texture_target) {
DCHECK(CalledOnValidThread());
+ picture_buffer_dimensions_ = dimensions;
if (client_) {
client_->ProvidePictureBuffers(
- num_requested_buffers, buffer_size, texture_target);
+ num_requested_buffers, dimensions, texture_target);
}
}
diff --git a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h b/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h
index ed67571cefe..704584dbfca 100644
--- a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h
+++ b/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h
@@ -12,6 +12,7 @@
#include "content/common/gpu/client/command_buffer_proxy_impl.h"
#include "ipc/ipc_listener.h"
#include "media/video/video_decode_accelerator.h"
+#include "ui/gfx/size.h"
namespace content {
class GpuChannelHost;
@@ -55,7 +56,7 @@ class GpuVideoDecodeAcceleratorHost
void OnBitstreamBufferProcessed(int32 bitstream_buffer_id);
void OnProvidePictureBuffer(uint32 num_requested_buffers,
- const gfx::Size& buffer_size,
+ const gfx::Size& dimensions,
uint32 texture_target);
void OnDismissPictureBuffer(int32 picture_buffer_id);
void OnPictureReady(int32 picture_buffer_id, int32 bitstream_buffer_id);
@@ -75,6 +76,9 @@ class GpuVideoDecodeAcceleratorHost
// Unowned reference to the CommandBufferProxyImpl that created us.
CommandBufferProxyImpl* impl_;
+ // Requested dimensions of the buffer, from ProvidePictureBuffers().
+ gfx::Size picture_buffer_dimensions_;
+
DISALLOW_COPY_AND_ASSIGN(GpuVideoDecodeAcceleratorHost);
};
diff --git a/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc b/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc
index 36d99e80efb..edfb7b6349b 100644
--- a/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc
+++ b/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc
@@ -177,6 +177,12 @@ void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers(
void GpuVideoEncodeAcceleratorHost::OnNotifyInputDone(int32 frame_id) {
DVLOG(3) << "OnNotifyInputDone(): frame_id=" << frame_id;
+ // Fun-fact: std::hash_map is not spec'd to be re-entrant; since freeing a
+ // frame can trigger a further encode to be kicked off and thus an .insert()
+ // back into the map, we separate the frame's dtor running from the .erase()
+ // running by holding on to the frame temporarily. This isn't "just
+ // theoretical" - Android's std::hash_map crashes if we don't do this.
+ scoped_refptr<media::VideoFrame> frame = frame_map_[frame_id];
if (!frame_map_.erase(frame_id)) {
DLOG(ERROR) << "OnNotifyInputDone(): "
"invalid frame_id=" << frame_id;
@@ -185,6 +191,7 @@ void GpuVideoEncodeAcceleratorHost::OnNotifyInputDone(int32 frame_id) {
OnNotifyError(kPlatformFailureError);
return;
}
+ frame = NULL; // Not necessary but nice to be explicit; see fun-fact above.
}
void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady(
diff --git a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
index edf8de41ca5..90cb9b9d478 100644
--- a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
+++ b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
@@ -11,7 +11,7 @@
#include "third_party/khronos/GLES2/gl2ext.h"
#include <algorithm>
-#include <set>
+#include <map>
#include "base/atomicops.h"
#include "base/bind.h"
@@ -24,8 +24,6 @@
#include "base/metrics/histogram.h"
#include "base/synchronization/lock.h"
#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_memory_allocation.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "gpu/GLES2/gl2extchromium.h"
@@ -35,44 +33,22 @@
#include "gpu/command_buffer/client/gles2_trace_implementation.h"
#include "gpu/command_buffer/client/transfer_buffer.h"
#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "gpu/command_buffer/common/mailbox.h"
-#include "gpu/ipc/command_buffer_proxy.h"
+#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h"
#include "third_party/skia/include/core/SkTypes.h"
-#include "webkit/common/gpu/gl_bindings_skia_cmd_buffer.h"
namespace content {
-static base::LazyInstance<base::Lock>::Leaky
- g_all_shared_contexts_lock = LAZY_INSTANCE_INITIALIZER;
-static base::LazyInstance<std::set<WebGraphicsContext3DCommandBufferImpl*> >
- g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER;
namespace {
-void ClearSharedContextsIfInShareSet(
- WebGraphicsContext3DCommandBufferImpl* context) {
- // If the given context isn't in the share set, that means that it
- // or another context it was previously sharing with already
- // provoked a lost context. Other contexts might have since been
- // successfully created and added to the share set, so do not clear
- // out the share set unless we know that all the contexts in there
- // are supposed to be lost simultaneously.
- base::AutoLock lock(g_all_shared_contexts_lock.Get());
- std::set<WebGraphicsContext3DCommandBufferImpl*>* share_set =
- g_all_shared_contexts.Pointer();
- for (std::set<WebGraphicsContext3DCommandBufferImpl*>::iterator iter =
- share_set->begin(); iter != share_set->end(); ++iter) {
- if (context == *iter) {
- share_set->clear();
- return;
- }
- }
-}
+static base::LazyInstance<base::Lock>::Leaky
+ g_all_shared_contexts_lock = LAZY_INSTANCE_INITIALIZER;
-size_t ClampUint64ToSizeT(uint64 value) {
- value = std::min(value,
- static_cast<uint64>(std::numeric_limits<size_t>::max()));
- return static_cast<size_t>(value);
-}
+typedef std::multimap<GpuChannelHost*, WebGraphicsContext3DCommandBufferImpl*>
+ ContextMap;
+static base::LazyInstance<ContextMap> g_all_shared_contexts =
+ LAZY_INSTANCE_INITIALIZER;
uint32_t GenFlushID() {
static base::subtle::Atomic32 flush_id = 0;
@@ -148,6 +124,11 @@ void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3) { \
gl_->glname(a1, a2, a3); \
}
+#define DELEGATE_TO_GL_3R(name, glname, t1, t2, t3, rt) \
+rt WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3) { \
+ return gl_->glname(a1, a2, a3); \
+}
+
#define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \
void WebGraphicsContext3DCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, \
t4 a4) { \
@@ -214,44 +195,37 @@ void WebGraphicsContext3DErrorMessageCallback::OnErrorMessage(
graphics_context_->OnErrorMessage(msg, id);
}
+WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits::SharedMemoryLimits()
+ : command_buffer_size(kDefaultCommandBufferSize),
+ start_transfer_buffer_size(kDefaultStartTransferBufferSize),
+ min_transfer_buffer_size(kDefaultMinTransferBufferSize),
+ max_transfer_buffer_size(kDefaultMaxTransferBufferSize),
+ mapped_memory_reclaim_limit(gpu::gles2::GLES2Implementation::kNoLimit) {}
+
WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl(
int surface_id,
const GURL& active_url,
- GpuChannelHostFactory* factory,
- const base::WeakPtr<WebGraphicsContext3DSwapBuffersClient>& swap_client)
+ GpuChannelHost* host,
+ const Attributes& attributes,
+ bool bind_generates_resources,
+ const SharedMemoryLimits& limits)
: initialize_failed_(false),
- factory_(factory),
visible_(false),
- free_command_buffer_when_invisible_(false),
- host_(NULL),
+ host_(host),
surface_id_(surface_id),
active_url_(active_url),
- swap_client_(swap_client),
context_lost_callback_(0),
context_lost_reason_(GL_NO_ERROR),
error_message_callback_(0),
- swapbuffers_complete_callback_(0),
- gpu_preference_(gfx::PreferIntegratedGpu),
- cached_width_(0),
- cached_height_(0),
+ attributes_(attributes),
+ gpu_preference_(attributes.preferDiscreteGPU ? gfx::PreferDiscreteGpu
+ : gfx::PreferIntegratedGpu),
weak_ptr_factory_(this),
initialized_(false),
gl_(NULL),
- frame_number_(0),
- bind_generates_resources_(false),
- use_echo_for_swap_ack_(true),
- command_buffer_size_(0),
- start_transfer_buffer_size_(0),
- min_transfer_buffer_size_(0),
- max_transfer_buffer_size_(0),
- mapped_memory_limit_(gpu::gles2::GLES2Implementation::kNoLimit),
+ bind_generates_resources_(bind_generates_resources),
+ mem_limits_(limits),
flush_id_(0) {
-#if (defined(OS_MACOSX) || defined(OS_WIN)) && !defined(USE_AURA)
- // Get ViewMsg_SwapBuffers_ACK from browser for single-threaded path.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- use_echo_for_swap_ack_ =
- command_line.HasSwitch(switches::kEnableThreadedCompositing);
-#endif
}
WebGraphicsContext3DCommandBufferImpl::
@@ -260,61 +234,9 @@ WebGraphicsContext3DCommandBufferImpl::
real_gl_->SetErrorMessageCallback(NULL);
}
- {
- base::AutoLock lock(g_all_shared_contexts_lock.Get());
- g_all_shared_contexts.Pointer()->erase(this);
- }
Destroy();
}
-bool WebGraphicsContext3DCommandBufferImpl::InitializeWithDefaultBufferSizes(
- const WebGraphicsContext3D::Attributes& attributes,
- bool bind_generates_resources,
- CauseForGpuLaunch cause) {
- return Initialize(attributes,
- bind_generates_resources,
- cause,
- kDefaultCommandBufferSize,
- kDefaultStartTransferBufferSize,
- kDefaultMinTransferBufferSize,
- kDefaultMaxTransferBufferSize,
- gpu::gles2::GLES2Implementation::kNoLimit);
-}
-
-bool WebGraphicsContext3DCommandBufferImpl::Initialize(
- const WebGraphicsContext3D::Attributes& attributes,
- bool bind_generates_resources,
- CauseForGpuLaunch cause,
- size_t command_buffer_size,
- size_t start_transfer_buffer_size,
- size_t min_transfer_buffer_size,
- size_t max_transfer_buffer_size,
- size_t mapped_memory_limit) {
- TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::initialize");
-
- attributes_ = attributes;
- bind_generates_resources_ = bind_generates_resources;
- DCHECK(!command_buffer_);
-
- if (!factory_)
- return false;
-
- if (attributes.preferDiscreteGPU)
- gpu_preference_ = gfx::PreferDiscreteGpu;
-
- host_ = factory_->EstablishGpuChannelSync(cause);
- if (!host_.get())
- return false;
-
- command_buffer_size_ = command_buffer_size;
- start_transfer_buffer_size_ = start_transfer_buffer_size;
- min_transfer_buffer_size_ = min_transfer_buffer_size;
- max_transfer_buffer_size_ = max_transfer_buffer_size;
- mapped_memory_limit_ = mapped_memory_limit;
-
- return true;
-}
-
bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() {
if (initialized_)
return true;
@@ -336,7 +258,7 @@ bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() {
gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation");
command_buffer_->SetChannelErrorCallback(
- base::Bind(&WebGraphicsContext3DCommandBufferImpl::OnContextLost,
+ base::Bind(&WebGraphicsContext3DCommandBufferImpl::OnGpuChannelLost,
weak_ptr_factory_.GetWeakPtr()));
command_buffer_->SetOnConsoleMessageCallback(
@@ -347,10 +269,6 @@ bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() {
new WebGraphicsContext3DErrorMessageCallback(this));
real_gl_->SetErrorMessageCallback(client_error_message_callback_.get());
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- free_command_buffer_when_invisible_ =
- command_line.HasSwitch(switches::kEnablePruneGpuCommandBuffers);
-
// Set attributes_ from created offscreen context.
{
static const int pcount = 4;
@@ -386,11 +304,10 @@ bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer(
base::AutoLock lock(g_all_shared_contexts_lock.Get());
CommandBufferProxyImpl* share_group = NULL;
if (attributes_.shareResources) {
- WebGraphicsContext3DCommandBufferImpl* share_group_context =
- g_all_shared_contexts.Pointer()->empty() ?
- NULL : *g_all_shared_contexts.Pointer()->begin();
- share_group = share_group_context ?
- share_group_context->command_buffer_.get() : NULL;
+ ContextMap& all_contexts = g_all_shared_contexts.Get();
+ ContextMap::const_iterator it = all_contexts.find(host_.get());
+ if (it != all_contexts.end())
+ share_group = it->second->command_buffer_.get();
}
std::vector<int32> attribs;
@@ -404,6 +321,8 @@ bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer(
attribs.push_back(attributes_.antialias ? 4 : 0);
attribs.push_back(SAMPLE_BUFFERS);
attribs.push_back(attributes_.antialias ? 1 : 0);
+ attribs.push_back(FAIL_IF_MAJOR_PERF_CAVEAT);
+ attribs.push_back(attributes_.failIfMajorPerformanceCaveat ? 1 : 0);
attribs.push_back(NONE);
// Create a proxy to a command buffer in the GPU process.
@@ -442,7 +361,7 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext(
// Create the GLES2 helper, which writes the command buffer protocol.
gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_.get()));
- if (!gles2_helper_->Initialize(command_buffer_size_))
+ if (!gles2_helper_->Initialize(mem_limits_.command_buffer_size))
return false;
if (attributes_.noAutomaticFlushes)
@@ -452,39 +371,46 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext(
// process and the GPU process.
transfer_buffer_ .reset(new gpu::TransferBuffer(gles2_helper_.get()));
+ DCHECK(host_.get());
scoped_ptr<base::AutoLock> lock;
scoped_refptr<gpu::gles2::ShareGroup> share_group;
if (attributes_.shareResources) {
// Make sure two clients don't try to create a new ShareGroup
// simultaneously.
lock.reset(new base::AutoLock(g_all_shared_contexts_lock.Get()));
- if (!g_all_shared_contexts.Pointer()->empty()) {
- share_group = (*g_all_shared_contexts.Pointer()->begin())
- ->GetImplementation()->share_group();
+ ContextMap& all_contexts = g_all_shared_contexts.Get();
+ ContextMap::const_iterator it = all_contexts.find(host_.get());
+ if (it != all_contexts.end()) {
+ share_group = it->second->GetImplementation()->share_group();
DCHECK(share_group);
}
}
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ bool free_command_buffer_when_invisible =
+ command_line.HasSwitch(switches::kEnablePruneGpuCommandBuffers);
+
// Create the object exposing the OpenGL API.
real_gl_.reset(new gpu::gles2::GLES2Implementation(
gles2_helper_.get(),
share_group,
transfer_buffer_.get(),
bind_generates_resources_,
- NULL));
+ free_command_buffer_when_invisible,
+ command_buffer_.get()));
gl_ = real_gl_.get();
if (attributes_.shareResources) {
// Don't add ourselves to the list before others can get to our ShareGroup.
- g_all_shared_contexts.Pointer()->insert(this);
+ g_all_shared_contexts.Get().insert(std::make_pair(host_.get(), this));
lock.reset();
}
if (!real_gl_->Initialize(
- start_transfer_buffer_size_,
- min_transfer_buffer_size_,
- max_transfer_buffer_size_,
- mapped_memory_limit_)) {
+ mem_limits_.start_transfer_buffer_size,
+ mem_limits_.min_transfer_buffer_size,
+ mem_limits_.max_transfer_buffer_size,
+ mem_limits_.mapped_memory_reclaim_limit)) {
return false;
}
@@ -511,17 +437,21 @@ uint32_t WebGraphicsContext3DCommandBufferImpl::lastFlushID() {
return flush_id_;
}
-int WebGraphicsContext3DCommandBufferImpl::width() {
- return cached_width_;
-}
-
-int WebGraphicsContext3DCommandBufferImpl::height() {
- return cached_height_;
-}
-
DELEGATE_TO_GL_R(insertSyncPoint, InsertSyncPointCHROMIUM, unsigned int)
void WebGraphicsContext3DCommandBufferImpl::Destroy() {
+ if (host_.get()) {
+ base::AutoLock lock(g_all_shared_contexts_lock.Get());
+ ContextMap& all_contexts = g_all_shared_contexts.Get();
+ ContextMap::iterator it = std::find(
+ all_contexts.begin(),
+ all_contexts.end(),
+ std::pair<GpuChannelHost* const,
+ WebGraphicsContext3DCommandBufferImpl*>(host_.get(), this));
+ if (it != all_contexts.end())
+ all_contexts.erase(it);
+ }
+
if (gl_) {
// First flush the context to ensure that any pending frees of resources
// are completed. Otherwise, if this context is part of a share group,
@@ -552,63 +482,21 @@ int WebGraphicsContext3DCommandBufferImpl::GetGPUProcessID() {
return host_.get() ? host_->gpu_host_id() : 0;
}
-int WebGraphicsContext3DCommandBufferImpl::GetChannelID() {
- return host_.get() ? host_->client_id() : 0;
-}
-
-int WebGraphicsContext3DCommandBufferImpl::GetContextID() {
- return command_buffer_->GetRouteID();
+gpu::ContextSupport*
+WebGraphicsContext3DCommandBufferImpl::GetContextSupport() {
+ return real_gl_.get();
}
void WebGraphicsContext3DCommandBufferImpl::prepareTexture() {
- TRACE_EVENT1("gpu",
- "WebGraphicsContext3DCommandBufferImpl::SwapBuffers",
- "frame", frame_number_);
- frame_number_++;
- // Copies the contents of the off-screen render target into the texture
- // used by the compositor.
- if (ShouldUseSwapClient())
- swap_client_->OnViewContextSwapBuffersPosted();
-
- if (command_buffer_->GetLastState().error == gpu::error::kNoError)
- gl_->SwapBuffers();
-
- if (use_echo_for_swap_ack_) {
- command_buffer_->Echo(base::Bind(
- &WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete,
- weak_ptr_factory_.GetWeakPtr()));
- }
-#if defined(OS_MACOSX)
- // It appears that making the compositor's on-screen context current on
- // other platforms implies this flush. TODO(kbr): this means that the
- // TOUCH build and, in the future, other platforms might need this.
- gl_->Flush();
-#endif
+ NOTREACHED();
}
void WebGraphicsContext3DCommandBufferImpl::postSubBufferCHROMIUM(
int x, int y, int width, int height) {
- // Same flow control as WebGraphicsContext3DCommandBufferImpl::prepareTexture
- // (see above).
- if (ShouldUseSwapClient())
- swap_client_->OnViewContextSwapBuffersPosted();
- gl_->PostSubBufferCHROMIUM(x, y, width, height);
- command_buffer_->Echo(base::Bind(
- &WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void WebGraphicsContext3DCommandBufferImpl::reshape(int width, int height) {
- reshapeWithScaleFactor(width, height, 1.f);
+ NOTREACHED();
}
-void WebGraphicsContext3DCommandBufferImpl::reshapeWithScaleFactor(
- int width, int height, float scale_factor) {
- cached_width_ = width;
- cached_height_ = height;
-
- gl_->ResizeCHROMIUM(width, height, scale_factor);
-}
+DELEGATE_TO_GL_3(reshapeWithScaleFactor, ResizeCHROMIUM, int, int, float)
void WebGraphicsContext3DCommandBufferImpl::synthesizeGLError(
WGC3Denum error) {
@@ -643,54 +531,12 @@ DELEGATE_TO_GL_1(unmapTexSubImage2DCHROMIUM, UnmapTexSubImage2DCHROMIUM,
void WebGraphicsContext3DCommandBufferImpl::setVisibilityCHROMIUM(
bool visible) {
- gl_->Flush();
- visible_ = visible;
- command_buffer_->SetSurfaceVisible(visible);
- if (!visible)
- real_gl_->FreeEverything();
+ NOTREACHED();
}
DELEGATE_TO_GL_3(discardFramebufferEXT, DiscardFramebufferEXT, WGC3Denum,
WGC3Dsizei, const WGC3Denum*)
-void WebGraphicsContext3DCommandBufferImpl::discardBackbufferCHROMIUM() {
- gl_->Flush();
- command_buffer_->DiscardBackbuffer();
-}
-
-void WebGraphicsContext3DCommandBufferImpl::ensureBackbufferCHROMIUM() {
- gl_->Flush();
- command_buffer_->EnsureBackbuffer();
-}
-
-void WebGraphicsContext3DCommandBufferImpl::sendManagedMemoryStatsCHROMIUM(
- const WebGraphicsManagedMemoryStats* stats)
-{
- CHECK(command_buffer_);
- command_buffer_->SendManagedMemoryStats(GpuManagedMemoryStats(
- stats->bytesVisible,
- stats->bytesVisibleAndNearby,
- stats->bytesAllocated,
- stats->backbufferRequested));
-}
-
-void WebGraphicsContext3DCommandBufferImpl::
- setMemoryAllocationChangedCallbackCHROMIUM(
- WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) {
- if (!command_buffer_)
- return;
-
- if (callback)
- command_buffer_->SetMemoryAllocationChangedCallback(base::Bind(
- &WebGraphicsContext3DCommandBufferImpl::OnMemoryAllocationChanged,
- weak_ptr_factory_.GetWeakPtr(),
- callback));
- else
- command_buffer_->SetMemoryAllocationChangedCallback(
- base::Callback<void(const GpuMemoryAllocationForRenderer&)>());
-}
-
-
void WebGraphicsContext3DCommandBufferImpl::copyTextureToParentTextureCHROMIUM(
WebGLId texture, WebGLId parentTexture) {
NOTIMPLEMENTED();
@@ -699,9 +545,9 @@ void WebGraphicsContext3DCommandBufferImpl::copyTextureToParentTextureCHROMIUM(
DELEGATE_TO_GL(rateLimitOffscreenContextCHROMIUM,
RateLimitOffscreenContextCHROMIUM)
-WebKit::WebString WebGraphicsContext3DCommandBufferImpl::
+blink::WebString WebGraphicsContext3DCommandBufferImpl::
getRequestableExtensionsCHROMIUM() {
- return WebKit::WebString::fromUTF8(
+ return blink::WebString::fromUTF8(
gl_->GetRequestableExtensionsCHROMIUM());
}
@@ -712,14 +558,14 @@ void WebGraphicsContext3DCommandBufferImpl::blitFramebufferCHROMIUM(
WGC3Dint srcX0, WGC3Dint srcY0, WGC3Dint srcX1, WGC3Dint srcY1,
WGC3Dint dstX0, WGC3Dint dstY0, WGC3Dint dstX1, WGC3Dint dstY1,
WGC3Dbitfield mask, WGC3Denum filter) {
- gl_->BlitFramebufferEXT(
+ gl_->BlitFramebufferCHROMIUM(
srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1,
mask, filter);
}
DELEGATE_TO_GL_5(renderbufferStorageMultisampleCHROMIUM,
- RenderbufferStorageMultisampleEXT, WGC3Denum, WGC3Dsizei,
+ RenderbufferStorageMultisampleCHROMIUM, WGC3Denum, WGC3Dsizei,
WGC3Denum, WGC3Dsizei, WGC3Dsizei)
DELEGATE_TO_GL_1R(createStreamTextureCHROMIUM, CreateStreamTextureCHROMIUM,
@@ -829,15 +675,11 @@ DELEGATE_TO_GL_1(enableVertexAttribArray, EnableVertexAttribArray,
void WebGraphicsContext3DCommandBufferImpl::finish() {
flush_id_ = GenFlushID();
gl_->Finish();
- if (!visible_ && free_command_buffer_when_invisible_)
- real_gl_->FreeEverything();
}
void WebGraphicsContext3DCommandBufferImpl::flush() {
flush_id_ = GenFlushID();
gl_->Flush();
- if (!visible_ && free_command_buffer_when_invisible_)
- real_gl_->FreeEverything();
}
DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbuffer,
@@ -846,6 +688,10 @@ DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbuffer,
DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2D,
WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint)
+DELEGATE_TO_GL_6(framebufferTexture2DMultisampleEXT,
+ FramebufferTexture2DMultisampleEXT,
+ WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint, WGC3Dsizei)
+
DELEGATE_TO_GL_1(frontFace, FrontFace, WGC3Denum)
DELEGATE_TO_GL_1(generateMipmap, GenerateMipmap, WGC3Denum)
@@ -874,7 +720,7 @@ bool WebGraphicsContext3DCommandBufferImpl::getActiveAttrib(
if (size < 0) {
return false;
}
- info.name = WebKit::WebString::fromUTF8(name.get(), length);
+ info.name = blink::WebString::fromUTF8(name.get(), length);
info.type = type;
info.size = size;
return true;
@@ -900,7 +746,7 @@ bool WebGraphicsContext3DCommandBufferImpl::getActiveUniform(
if (size < 0) {
return false;
}
- info.name = WebKit::WebString::fromUTF8(name.get(), length);
+ info.name = blink::WebString::fromUTF8(name.get(), length);
info.type = type;
info.size = size;
return true;
@@ -917,7 +763,7 @@ DELEGATE_TO_GL_2(getBooleanv, GetBooleanv, WGC3Denum, WGC3Dboolean*)
DELEGATE_TO_GL_3(getBufferParameteriv, GetBufferParameteriv,
WGC3Denum, WGC3Denum, WGC3Dint*)
-WebKit::WebGraphicsContext3D::Attributes
+blink::WebGraphicsContext3D::Attributes
WebGraphicsContext3DCommandBufferImpl::getContextAttributes() {
return attributes_;
}
@@ -949,21 +795,21 @@ DELEGATE_TO_GL_2(getIntegerv, GetIntegerv, WGC3Denum, WGC3Dint*)
DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, WGC3Denum, WGC3Dint*)
-WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getProgramInfoLog(
+blink::WebString WebGraphicsContext3DCommandBufferImpl::getProgramInfoLog(
WebGLId program) {
GLint logLength = 0;
gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
if (!logLength)
- return WebKit::WebString();
+ return blink::WebString();
scoped_ptr<GLchar[]> log(new GLchar[logLength]);
if (!log)
- return WebKit::WebString();
+ return blink::WebString();
GLsizei returnedLogLength = 0;
gl_->GetProgramInfoLog(
program, logLength, &returnedLogLength, log.get());
DCHECK_EQ(logLength, returnedLogLength + 1);
- WebKit::WebString res =
- WebKit::WebString::fromUTF8(log.get(), returnedLogLength);
+ blink::WebString res =
+ blink::WebString::fromUTF8(log.get(), returnedLogLength);
return res;
}
@@ -972,71 +818,71 @@ DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameteriv,
DELEGATE_TO_GL_3(getShaderiv, GetShaderiv, WebGLId, WGC3Denum, WGC3Dint*)
-WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getShaderInfoLog(
+blink::WebString WebGraphicsContext3DCommandBufferImpl::getShaderInfoLog(
WebGLId shader) {
GLint logLength = 0;
gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
if (!logLength)
- return WebKit::WebString();
+ return blink::WebString();
scoped_ptr<GLchar[]> log(new GLchar[logLength]);
if (!log)
- return WebKit::WebString();
+ return blink::WebString();
GLsizei returnedLogLength = 0;
gl_->GetShaderInfoLog(
shader, logLength, &returnedLogLength, log.get());
DCHECK_EQ(logLength, returnedLogLength + 1);
- WebKit::WebString res =
- WebKit::WebString::fromUTF8(log.get(), returnedLogLength);
+ blink::WebString res =
+ blink::WebString::fromUTF8(log.get(), returnedLogLength);
return res;
}
DELEGATE_TO_GL_4(getShaderPrecisionFormat, GetShaderPrecisionFormat,
WGC3Denum, WGC3Denum, WGC3Dint*, WGC3Dint*)
-WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getShaderSource(
+blink::WebString WebGraphicsContext3DCommandBufferImpl::getShaderSource(
WebGLId shader) {
GLint logLength = 0;
gl_->GetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &logLength);
if (!logLength)
- return WebKit::WebString();
+ return blink::WebString();
scoped_ptr<GLchar[]> log(new GLchar[logLength]);
if (!log)
- return WebKit::WebString();
+ return blink::WebString();
GLsizei returnedLogLength = 0;
gl_->GetShaderSource(
shader, logLength, &returnedLogLength, log.get());
if (!returnedLogLength)
- return WebKit::WebString();
+ return blink::WebString();
DCHECK_EQ(logLength, returnedLogLength + 1);
- WebKit::WebString res =
- WebKit::WebString::fromUTF8(log.get(), returnedLogLength);
+ blink::WebString res =
+ blink::WebString::fromUTF8(log.get(), returnedLogLength);
return res;
}
-WebKit::WebString WebGraphicsContext3DCommandBufferImpl::
+blink::WebString WebGraphicsContext3DCommandBufferImpl::
getTranslatedShaderSourceANGLE(WebGLId shader) {
GLint logLength = 0;
gl_->GetShaderiv(
shader, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, &logLength);
if (!logLength)
- return WebKit::WebString();
+ return blink::WebString();
scoped_ptr<GLchar[]> log(new GLchar[logLength]);
if (!log)
- return WebKit::WebString();
+ return blink::WebString();
GLsizei returnedLogLength = 0;
gl_->GetTranslatedShaderSourceANGLE(
shader, logLength, &returnedLogLength, log.get());
if (!returnedLogLength)
- return WebKit::WebString();
+ return blink::WebString();
DCHECK_EQ(logLength, returnedLogLength + 1);
- WebKit::WebString res =
- WebKit::WebString::fromUTF8(log.get(), returnedLogLength);
+ blink::WebString res =
+ blink::WebString::fromUTF8(log.get(), returnedLogLength);
return res;
}
-WebKit::WebString WebGraphicsContext3DCommandBufferImpl::getString(
+blink::WebString WebGraphicsContext3DCommandBufferImpl::getString(
WGC3Denum name) {
- return WebKit::WebString::fromUTF8(
+ return blink::WebString::fromUTF8(
reinterpret_cast<const char*>(gl_->GetString(name)));
}
@@ -1239,6 +1085,23 @@ void WebGraphicsContext3DCommandBufferImpl::vertexAttribPointer(
DELEGATE_TO_GL_4(viewport, Viewport,
WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei)
+DELEGATE_TO_GL_2(genBuffers, GenBuffers, WGC3Dsizei, WebGLId*);
+
+DELEGATE_TO_GL_2(genFramebuffers, GenFramebuffers, WGC3Dsizei, WebGLId*);
+
+DELEGATE_TO_GL_2(genRenderbuffers, GenRenderbuffers, WGC3Dsizei, WebGLId*);
+
+DELEGATE_TO_GL_2(genTextures, GenTextures, WGC3Dsizei, WebGLId*);
+
+DELEGATE_TO_GL_2(deleteBuffers, DeleteBuffers, WGC3Dsizei, WebGLId*);
+
+DELEGATE_TO_GL_2(deleteFramebuffers, DeleteFramebuffers, WGC3Dsizei, WebGLId*);
+
+DELEGATE_TO_GL_2(deleteRenderbuffers, DeleteRenderbuffers, WGC3Dsizei,
+ WebGLId*);
+
+DELEGATE_TO_GL_2(deleteTextures, DeleteTextures, WGC3Dsizei, WebGLId*);
+
WebGLId WebGraphicsContext3DCommandBufferImpl::createBuffer() {
GLuint o;
gl_->GenBuffers(1, &o);
@@ -1251,16 +1114,12 @@ WebGLId WebGraphicsContext3DCommandBufferImpl::createFramebuffer() {
return o;
}
-DELEGATE_TO_GL_R(createProgram, CreateProgram, WebGLId)
-
WebGLId WebGraphicsContext3DCommandBufferImpl::createRenderbuffer() {
GLuint o;
gl_->GenRenderbuffers(1, &o);
return o;
}
-DELEGATE_TO_GL_1R(createShader, CreateShader, WGC3Denum, WebGLId)
-
WebGLId WebGraphicsContext3DCommandBufferImpl::createTexture() {
GLuint o;
gl_->GenTextures(1, &o);
@@ -1276,86 +1135,22 @@ void WebGraphicsContext3DCommandBufferImpl::deleteFramebuffer(
gl_->DeleteFramebuffers(1, &framebuffer);
}
-DELEGATE_TO_GL_1(deleteProgram, DeleteProgram, WebGLId)
-
void WebGraphicsContext3DCommandBufferImpl::deleteRenderbuffer(
WebGLId renderbuffer) {
gl_->DeleteRenderbuffers(1, &renderbuffer);
}
-DELEGATE_TO_GL_1(deleteShader, DeleteShader, WebGLId)
-
void WebGraphicsContext3DCommandBufferImpl::deleteTexture(WebGLId texture) {
gl_->DeleteTextures(1, &texture);
}
-bool WebGraphicsContext3DCommandBufferImpl::ShouldUseSwapClient() {
- return factory_ && factory_->IsMainThread() && swap_client_.get();
-}
+DELEGATE_TO_GL_R(createProgram, CreateProgram, WebGLId)
-void WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete() {
- typedef WebGraphicsContext3DSwapBuffersClient WGC3DSwapClient;
- // This may be called after tear-down of the RenderView.
- if (ShouldUseSwapClient()) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&WGC3DSwapClient::OnViewContextSwapBuffersComplete,
- swap_client_));
- }
+DELEGATE_TO_GL_1R(createShader, CreateShader, WGC3Denum, WebGLId)
- if (swapbuffers_complete_callback_)
- swapbuffers_complete_callback_->onSwapBuffersComplete();
-}
-
-WebGraphicsMemoryAllocation::PriorityCutoff
- WebGraphicsContext3DCommandBufferImpl::WebkitPriorityCutoff(
- GpuMemoryAllocationForRenderer::PriorityCutoff priorityCutoff) {
- switch (priorityCutoff) {
- case GpuMemoryAllocationForRenderer::kPriorityCutoffAllowNothing:
- return WebGraphicsMemoryAllocation::PriorityCutoffAllowNothing;
- case GpuMemoryAllocationForRenderer::kPriorityCutoffAllowOnlyRequired:
- return WebGraphicsMemoryAllocation::PriorityCutoffAllowVisibleOnly;
- case GpuMemoryAllocationForRenderer::kPriorityCutoffAllowNiceToHave:
- return WebGraphicsMemoryAllocation::PriorityCutoffAllowVisibleAndNearby;
- case GpuMemoryAllocationForRenderer::kPriorityCutoffAllowEverything:
- return WebGraphicsMemoryAllocation::PriorityCutoffAllowEverything;
- }
- NOTREACHED();
- return WebGraphicsMemoryAllocation::PriorityCutoffAllowEverything;
-}
-
-void WebGraphicsContext3DCommandBufferImpl::OnMemoryAllocationChanged(
- WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback,
- const GpuMemoryAllocationForRenderer& allocation) {
-
- // Convert the gpu structure to the WebKit structure.
- WebGraphicsMemoryAllocation web_allocation;
- web_allocation.bytesLimitWhenVisible =
- ClampUint64ToSizeT(allocation.bytes_limit_when_visible);
- web_allocation.priorityCutoffWhenVisible =
- WebkitPriorityCutoff(allocation.priority_cutoff_when_visible);
- web_allocation.bytesLimitWhenNotVisible =
- ClampUint64ToSizeT(allocation.bytes_limit_when_not_visible);
- web_allocation.priorityCutoffWhenNotVisible =
- WebkitPriorityCutoff(allocation.priority_cutoff_when_not_visible);
- web_allocation.haveBackbufferWhenNotVisible =
- allocation.have_backbuffer_when_not_visible;
-
- // Populate deprecated WebKit fields. These may be removed when references to
- // them in WebKit are removed.
- web_allocation.gpuResourceSizeInBytes =
- ClampUint64ToSizeT(allocation.bytes_limit_when_visible);
- web_allocation.suggestHaveBackbuffer =
- allocation.have_backbuffer_when_not_visible;
-
- if (callback)
- callback->onMemoryAllocationChanged(web_allocation);
-
- // We may have allocated transfer buffers in order to free GL resources in a
- // backgrounded tab. Re-free the transfer buffers.
- if (!visible_)
- real_gl_->FreeEverything();
-}
+DELEGATE_TO_GL_1(deleteProgram, DeleteProgram, WebGLId)
+
+DELEGATE_TO_GL_1(deleteShader, DeleteShader, WebGLId)
void WebGraphicsContext3DCommandBufferImpl::setErrorMessageCallback(
WebGraphicsContext3D::WebGraphicsErrorMessageCallback* cb) {
@@ -1388,26 +1183,18 @@ bool WebGraphicsContext3DCommandBufferImpl::IsCommandBufferContextLost() {
// static
WebGraphicsContext3DCommandBufferImpl*
WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- GpuChannelHostFactory* factory,
+ GpuChannelHost* host,
const WebGraphicsContext3D::Attributes& attributes,
- const GURL& active_url) {
- if (!factory)
+ const GURL& active_url,
+ const SharedMemoryLimits& limits) {
+ if (!host)
return NULL;
- base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> null_client;
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
- new WebGraphicsContext3DCommandBufferImpl(
- 0, active_url, factory, null_client));
- CauseForGpuLaunch cause =
- CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
- if (context->InitializeWithDefaultBufferSizes(attributes, false, cause))
- return context.release();
- return NULL;
-}
-
-void WebGraphicsContext3DCommandBufferImpl::
- setSwapBuffersCompleteCallbackCHROMIUM(
- WebGraphicsContext3D::WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* cb) {
- swapbuffers_complete_callback_ = cb;
+ return new WebGraphicsContext3DCommandBufferImpl(0,
+ active_url,
+ host,
+ attributes,
+ false,
+ limits);
}
DELEGATE_TO_GL_5(texImageIOSurface2DCHROMIUM, TexImageIOSurface2DCHROMIUM,
@@ -1452,51 +1239,13 @@ void WebGraphicsContext3DCommandBufferImpl::shallowFinishCHROMIUM() {
DELEGATE_TO_GL_1(waitSyncPoint, WaitSyncPointCHROMIUM, GLuint)
-static void SignalSyncPointCallback(
- scoped_ptr<
- WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback> callback) {
- callback->onSyncPointReached();
-}
-
-void WebGraphicsContext3DCommandBufferImpl::signalSyncPoint(
- unsigned sync_point,
- WebGraphicsSyncPointCallback* callback) {
- // Take ownership of the callback.
- scoped_ptr<WebGraphicsSyncPointCallback> own_callback(callback);
- command_buffer_->SignalSyncPoint(
- sync_point,
- base::Bind(&SignalSyncPointCallback, base::Passed(&own_callback)));
-}
-
-void WebGraphicsContext3DCommandBufferImpl::signalQuery(
- unsigned query,
- WebGraphicsSyncPointCallback* callback) {
- // Take ownership of the callback.
- scoped_ptr<WebGraphicsSyncPointCallback> own_callback(callback);
- // Flush any pending commands to make sure that the the query
- // has actually been created/started before we try to attach
- // a callback to it.
- gl_->Flush();
- command_buffer_->SignalQuery(
- query,
- base::Bind(&SignalSyncPointCallback, base::Passed(&own_callback)));
-}
-
void WebGraphicsContext3DCommandBufferImpl::loseContextCHROMIUM(
WGC3Denum current, WGC3Denum other) {
gl_->LoseContextCHROMIUM(current, other);
gl_->Flush();
}
-void WebGraphicsContext3DCommandBufferImpl::genMailboxCHROMIUM(
- WGC3Dbyte* name) {
- std::vector<gpu::Mailbox> names;
- if (command_buffer_->GenerateMailboxNames(1, &names))
- memcpy(name, names[0].name, GL_MAILBOX_SIZE_CHROMIUM);
- else
- synthesizeGLError(GL_OUT_OF_MEMORY);
-}
-
+DELEGATE_TO_GL_1(genMailboxCHROMIUM, GenMailboxCHROMIUM, WGC3Dbyte*)
DELEGATE_TO_GL_2(produceTextureCHROMIUM, ProduceTextureCHROMIUM,
WGC3Denum, const WGC3Dbyte*)
DELEGATE_TO_GL_2(consumeTextureCHROMIUM, ConsumeTextureCHROMIUM,
@@ -1567,8 +1316,22 @@ void WebGraphicsContext3DCommandBufferImpl::drawElementsInstancedANGLE(
DELEGATE_TO_GL_2(vertexAttribDivisorANGLE, VertexAttribDivisorANGLE, WGC3Duint,
WGC3Duint)
-GrGLInterface* WebGraphicsContext3DCommandBufferImpl::onCreateGrGLInterface() {
- return webkit::gpu::CreateCommandBufferSkiaGLBinding();
+DELEGATE_TO_GL_3R(createImageCHROMIUM, CreateImageCHROMIUM,
+ WGC3Dsizei, WGC3Dsizei, WGC3Denum,
+ WGC3Duint);
+
+DELEGATE_TO_GL_1(destroyImageCHROMIUM, DestroyImageCHROMIUM, WGC3Duint);
+
+DELEGATE_TO_GL_3(getImageParameterivCHROMIUM, GetImageParameterivCHROMIUM,
+ WGC3Duint, WGC3Denum, GLint*);
+
+DELEGATE_TO_GL_2R(mapImageCHROMIUM, MapImageCHROMIUM,
+ WGC3Duint, WGC3Denum, void*);
+
+DELEGATE_TO_GL_1(unmapImageCHROMIUM, UnmapImageCHROMIUM, WGC3Duint);
+
+GrGLInterface* WebGraphicsContext3DCommandBufferImpl::createGrGLInterface() {
+ return skia_bindings::CreateCommandBufferSkiaGLBinding();
}
namespace {
@@ -1589,22 +1352,24 @@ WGC3Denum convertReason(gpu::error::ContextLostReason reason) {
} // anonymous namespace
-void WebGraphicsContext3DCommandBufferImpl::OnContextLost() {
+void WebGraphicsContext3DCommandBufferImpl::OnGpuChannelLost() {
context_lost_reason_ = convertReason(
command_buffer_->GetLastState().context_lost_reason);
if (context_lost_callback_) {
context_lost_callback_->onContextLost();
}
- if (attributes_.shareResources)
- ClearSharedContextsIfInShareSet(this);
- if (ShouldUseSwapClient())
- swap_client_->OnViewContextSwapBuffersAborted();
+
+ DCHECK(host_.get());
+ {
+ base::AutoLock lock(g_all_shared_contexts_lock.Get());
+ g_all_shared_contexts.Get().erase(host_.get());
+ }
}
void WebGraphicsContext3DCommandBufferImpl::OnErrorMessage(
const std::string& message, int id) {
if (error_message_callback_) {
- WebKit::WebString str = WebKit::WebString::fromUTF8(message.c_str());
+ blink::WebString str = blink::WebString::fromUTF8(message.c_str());
error_message_callback_->onErrorMessage(str, id);
}
}
diff --git a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
index 4688d86c0bd..b5331eb363b 100644
--- a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
+++ b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
@@ -13,7 +13,6 @@
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/common/gpu/client/command_buffer_proxy_impl.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "ui/gfx/native_widget_types.h"
@@ -22,6 +21,7 @@
namespace gpu {
+class ContextSupport;
class TransferBuffer;
namespace gles2 {
@@ -31,89 +31,68 @@ class GLES2Interface;
}
}
-using WebKit::WebGLId;
-
-using WebKit::WGC3Dbyte;
-using WebKit::WGC3Dchar;
-using WebKit::WGC3Denum;
-using WebKit::WGC3Dboolean;
-using WebKit::WGC3Dbitfield;
-using WebKit::WGC3Dint;
-using WebKit::WGC3Dsizei;
-using WebKit::WGC3Duint;
-using WebKit::WGC3Dfloat;
-using WebKit::WGC3Dclampf;
-using WebKit::WGC3Dintptr;
-using WebKit::WGC3Dsizeiptr;
-using WebKit::WebGraphicsManagedMemoryStats;
-using WebKit::WebGraphicsMemoryAllocation;
+using blink::WebGLId;
+
+using blink::WGC3Dbyte;
+using blink::WGC3Dchar;
+using blink::WGC3Denum;
+using blink::WGC3Dboolean;
+using blink::WGC3Dbitfield;
+using blink::WGC3Dint;
+using blink::WGC3Dsizei;
+using blink::WGC3Duint;
+using blink::WGC3Dfloat;
+using blink::WGC3Dclampf;
+using blink::WGC3Dintptr;
+using blink::WGC3Dsizeiptr;
namespace content {
class GpuChannelHost;
-class GpuChannelHostFactory;
-struct GpuMemoryAllocationForRenderer;
const size_t kDefaultCommandBufferSize = 1024 * 1024;
const size_t kDefaultStartTransferBufferSize = 1 * 1024 * 1024;
const size_t kDefaultMinTransferBufferSize = 1 * 256 * 1024;
const size_t kDefaultMaxTransferBufferSize = 16 * 1024 * 1024;
-// TODO(piman): move this logic to the compositor and remove it from the
-// context...
-class WebGraphicsContext3DSwapBuffersClient {
- public:
- virtual void OnViewContextSwapBuffersPosted() = 0;
- virtual void OnViewContextSwapBuffersComplete() = 0;
- virtual void OnViewContextSwapBuffersAborted() = 0;
-
- protected:
- virtual ~WebGraphicsContext3DSwapBuffersClient() {}
-};
-
class WebGraphicsContext3DErrorMessageCallback;
class WebGraphicsContext3DCommandBufferImpl
- : public WebKit::WebGraphicsContext3D {
+ : public blink::WebGraphicsContext3D {
public:
enum MappedMemoryReclaimLimit {
kNoLimit = 0,
};
+ struct CONTENT_EXPORT SharedMemoryLimits {
+ SharedMemoryLimits();
+
+ size_t command_buffer_size;
+ size_t start_transfer_buffer_size;
+ size_t min_transfer_buffer_size;
+ size_t max_transfer_buffer_size;
+ size_t mapped_memory_reclaim_limit;
+ };
+
WebGraphicsContext3DCommandBufferImpl(
int surface_id,
const GURL& active_url,
- GpuChannelHostFactory* factory,
- const base::WeakPtr<WebGraphicsContext3DSwapBuffersClient>& swap_client);
+ GpuChannelHost* host,
+ const Attributes& attributes,
+ bool bind_generates_resources,
+ const SharedMemoryLimits& limits);
virtual ~WebGraphicsContext3DCommandBufferImpl();
- bool Initialize(const Attributes& attributes,
- bool bind_generates_resources,
- CauseForGpuLaunch cause,
- size_t command_buffer_size,
- size_t start_transfer_buffer_size,
- size_t min_transfer_buffer_size,
- size_t max_transfer_buffer_size,
- size_t mapped_memory_reclaim_limit);
-
- bool InitializeWithDefaultBufferSizes(const Attributes& attributes,
- bool bind_generates_resources,
- CauseForGpuLaunch cause);
-
// The following 3 IDs let one uniquely identify this context.
// Gets the GPU process ID for this context.
int GetGPUProcessID();
- // Gets the channel ID for this context.
- int GetChannelID();
-
- // Gets the context ID (relative to the channel).
- int GetContextID();
-
CommandBufferProxyImpl* GetCommandBufferProxy() {
return command_buffer_.get();
}
+ CONTENT_EXPORT gpu::ContextSupport* GetContextSupport();
+
gpu::gles2::GLES2Implementation* GetImplementation() {
return real_gl_.get();
}
@@ -126,12 +105,13 @@ class WebGraphicsContext3DCommandBufferImpl
// on any failure.
static CONTENT_EXPORT WebGraphicsContext3DCommandBufferImpl*
CreateOffscreenContext(
- GpuChannelHostFactory* factory,
+ GpuChannelHost* host,
const WebGraphicsContext3D::Attributes& attributes,
- const GURL& active_url);
+ const GURL& active_url,
+ const SharedMemoryLimits& limits);
size_t GetMappedMemoryLimit() {
- return mapped_memory_limit_;
+ return mem_limits_.mapped_memory_reclaim_limit;
}
//----------------------------------------------------------------------
@@ -144,19 +124,11 @@ class WebGraphicsContext3DCommandBufferImpl
virtual uint32_t lastFlushID();
- virtual int width();
- virtual int height();
-
virtual unsigned int insertSyncPoint();
virtual void waitSyncPoint(unsigned int sync_point);
- virtual void signalSyncPoint(unsigned sync_point,
- WebGraphicsSyncPointCallback* callback);
- virtual void signalQuery(unsigned query,
- WebGraphicsSyncPointCallback* callback);
virtual void loseContextCHROMIUM(WGC3Denum current, WGC3Denum other);
- virtual void reshape(int width, int height);
virtual void reshapeWithScaleFactor(
int width, int height, float scale_factor);
@@ -256,6 +228,12 @@ class WebGraphicsContext3DCommandBufferImpl
WGC3Denum textarget,
WebGLId texture,
WGC3Dint level);
+ virtual void framebufferTexture2DMultisampleEXT(WGC3Denum target,
+ WGC3Denum attachment,
+ WGC3Denum textarget,
+ WebGLId texture,
+ WGC3Dint level,
+ WGC3Dsizei samples);
virtual void frontFace(WGC3Denum mode);
virtual void generateMipmap(WGC3Denum target);
@@ -296,7 +274,7 @@ class WebGraphicsContext3DCommandBufferImpl
virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value);
- virtual WebKit::WebString getProgramInfoLog(WebGLId program);
+ virtual blink::WebString getProgramInfoLog(WebGLId program);
virtual void getRenderbufferParameteriv(WGC3Denum target,
WGC3Denum pname,
@@ -304,15 +282,15 @@ class WebGraphicsContext3DCommandBufferImpl
virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value);
- virtual WebKit::WebString getShaderInfoLog(WebGLId shader);
+ virtual blink::WebString getShaderInfoLog(WebGLId shader);
virtual void getShaderPrecisionFormat(WGC3Denum shadertype,
WGC3Denum precisiontype,
WGC3Dint* range,
WGC3Dint* precision);
- virtual WebKit::WebString getShaderSource(WebGLId shader);
- virtual WebKit::WebString getString(WGC3Denum name);
+ virtual blink::WebString getShaderSource(WebGLId shader);
+ virtual blink::WebString getString(WGC3Denum name);
virtual void getTexParameterfv(WGC3Denum target,
WGC3Denum pname,
@@ -476,20 +454,32 @@ class WebGraphicsContext3DCommandBufferImpl
WGC3Dsizei width, WGC3Dsizei height);
// Support for buffer creation and deletion
+ virtual void genBuffers(WGC3Dsizei count, WebGLId* ids);
+ virtual void genFramebuffers(WGC3Dsizei count, WebGLId* ids);
+ virtual void genRenderbuffers(WGC3Dsizei count, WebGLId* ids);
+ virtual void genTextures(WGC3Dsizei count, WebGLId* ids);
+
+ virtual void deleteBuffers(WGC3Dsizei count, WebGLId* ids);
+ virtual void deleteFramebuffers(WGC3Dsizei count, WebGLId* ids);
+ virtual void deleteRenderbuffers(WGC3Dsizei count, WebGLId* ids);
+ virtual void deleteTextures(WGC3Dsizei count, WebGLId* ids);
+
virtual WebGLId createBuffer();
virtual WebGLId createFramebuffer();
- virtual WebGLId createProgram();
virtual WebGLId createRenderbuffer();
- virtual WebGLId createShader(WGC3Denum);
virtual WebGLId createTexture();
virtual void deleteBuffer(WebGLId);
virtual void deleteFramebuffer(WebGLId);
- virtual void deleteProgram(WebGLId);
virtual void deleteRenderbuffer(WebGLId);
- virtual void deleteShader(WebGLId);
virtual void deleteTexture(WebGLId);
+ virtual WebGLId createProgram();
+ virtual WebGLId createShader(WGC3Denum);
+
+ virtual void deleteProgram(WebGLId);
+ virtual void deleteShader(WebGLId);
+
virtual void synthesizeGLError(WGC3Denum);
virtual void* mapBufferSubDataCHROMIUM(
@@ -513,21 +503,12 @@ class WebGraphicsContext3DCommandBufferImpl
virtual void discardFramebufferEXT(WGC3Denum target,
WGC3Dsizei numAttachments,
const WGC3Denum* attachments);
- virtual void discardBackbufferCHROMIUM();
- virtual void ensureBackbufferCHROMIUM();
-
- virtual void setMemoryAllocationChangedCallbackCHROMIUM(
- WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback);
-
- virtual void sendManagedMemoryStatsCHROMIUM(
- const WebGraphicsManagedMemoryStats* stats);
-
virtual void copyTextureToParentTextureCHROMIUM(
WebGLId texture, WebGLId parentTexture);
virtual void rateLimitOffscreenContextCHROMIUM();
- virtual WebKit::WebString getRequestableExtensionsCHROMIUM();
+ virtual blink::WebString getRequestableExtensionsCHROMIUM();
virtual void requestExtensionCHROMIUM(const char*);
virtual void blitFramebufferCHROMIUM(
@@ -538,7 +519,7 @@ class WebGraphicsContext3DCommandBufferImpl
WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat,
WGC3Dsizei width, WGC3Dsizei height);
- virtual WebKit::WebString getTranslatedShaderSourceANGLE(WebGLId shader);
+ virtual blink::WebString getTranslatedShaderSourceANGLE(WebGLId shader);
virtual void setContextLostCallback(
WebGraphicsContext3D::WebGraphicsContextLostCallback* callback);
@@ -548,10 +529,6 @@ class WebGraphicsContext3DCommandBufferImpl
virtual void setErrorMessageCallback(
WebGraphicsContext3D::WebGraphicsErrorMessageCallback* callback);
- virtual void setSwapBuffersCompleteCallbackCHROMIUM(
- WebGraphicsContext3D::
- WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* callback);
-
virtual void texImageIOSurface2DCHROMIUM(
WGC3Denum target, WGC3Dint width, WGC3Dint height,
WGC3Duint ioSurfaceId, WGC3Duint plane);
@@ -641,8 +618,16 @@ class WebGraphicsContext3DCommandBufferImpl
WGC3Denum type, WGC3Dintptr offset, WGC3Dsizei primcount);
virtual void vertexAttribDivisorANGLE(WGC3Duint index, WGC3Duint divisor);
- protected:
- virtual GrGLInterface* onCreateGrGLInterface();
+ // GL_CHROMIUM_map_image
+ virtual WGC3Duint createImageCHROMIUM(
+ WGC3Dsizei width, WGC3Dsizei height, WGC3Denum internalformat);
+ virtual void destroyImageCHROMIUM(WGC3Duint image_id);
+ virtual void getImageParameterivCHROMIUM(
+ WGC3Duint image_id, WGC3Denum pname, WGC3Dint* params);
+ virtual void* mapImageCHROMIUM(WGC3Duint image_id, WGC3Denum access);
+ virtual void unmapImageCHROMIUM(WGC3Duint image_id);
+
+ virtual GrGLInterface* createGrGLInterface();
private:
// These are the same error codes as used by EGL.
@@ -655,6 +640,9 @@ class WebGraphicsContext3DCommandBufferImpl
// the 16-bit range are the same as used by EGL. Those outside the 16-bit
// range are unique to Chromium. Attributes are matched using a closest fit
// algorithm.
+ // Changes to this enum should also be copied to
+ // gpu/command_buffer/common/gles2_cmd_utils.cc and to
+ // gpu/command_buffer/client/gl_in_process_context.cc
enum Attribute {
ALPHA_SIZE = 0x3021,
BLUE_SIZE = 0x3022,
@@ -668,7 +656,8 @@ class WebGraphicsContext3DCommandBufferImpl
WIDTH = 0x3057,
NONE = 0x3038, // Attrib list = terminator
SHARE_RESOURCES = 0x10000,
- BIND_GENERATES_RESOURCES = 0x10001
+ BIND_GENERATES_RESOURCES = 0x10001,
+ FAIL_IF_MAJOR_PERF_CAVEAT = 0x10002
};
friend class WebGraphicsContext3DErrorMessageCallback;
@@ -697,37 +686,17 @@ class WebGraphicsContext3DCommandBufferImpl
// unnecessary complexity at the moment.
bool CreateContext(bool onscreen);
- // SwapBuffers callback.
- void OnSwapBuffersComplete();
- virtual void OnContextLost();
+ virtual void OnGpuChannelLost();
virtual void OnErrorMessage(const std::string& message, int id);
- // Check if we should call into the swap client. We can only do that on the
- // main thread.
- bool ShouldUseSwapClient();
-
- // MemoryAllocationChanged callback.
- void OnMemoryAllocationChanged(
- WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback,
- const GpuMemoryAllocationForRenderer& allocation);
-
- // Convert the gpu cutoff enum to the WebKit enum.
- static WebGraphicsMemoryAllocation::PriorityCutoff WebkitPriorityCutoff(
- GpuMemoryAllocationForRenderer::PriorityCutoff priorityCutoff);
-
bool initialize_failed_;
- // The channel factory to talk to the GPU process
- GpuChannelHostFactory* factory_;
-
bool visible_;
- bool free_command_buffer_when_invisible_;
// State needed by MaybeInitializeGL.
scoped_refptr<GpuChannelHost> host_;
int32 surface_id_;
GURL active_url_;
- base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> swap_client_;
WebGraphicsContext3D::WebGraphicsContextLostCallback* context_lost_callback_;
WGC3Denum context_lost_reason_;
@@ -737,12 +706,8 @@ class WebGraphicsContext3DCommandBufferImpl
scoped_ptr<WebGraphicsContext3DErrorMessageCallback>
client_error_message_callback_;
- WebGraphicsContext3D::WebGraphicsSwapBuffersCompleteCallbackCHROMIUM*
- swapbuffers_complete_callback_;
-
- WebKit::WebGraphicsContext3D::Attributes attributes_;
+ blink::WebGraphicsContext3D::Attributes attributes_;
gfx::GpuPreference gpu_preference_;
- int cached_width_, cached_height_;
// Errors raised by synthesizeGLError().
std::vector<WGC3Denum> synthetic_errors_;
@@ -757,14 +722,8 @@ class WebGraphicsContext3DCommandBufferImpl
scoped_ptr<gpu::gles2::GLES2Implementation> real_gl_;
scoped_ptr<gpu::gles2::GLES2Interface> trace_gl_;
Error last_error_;
- int frame_number_;
bool bind_generates_resources_;
- bool use_echo_for_swap_ack_;
- size_t command_buffer_size_;
- size_t start_transfer_buffer_size_;
- size_t min_transfer_buffer_size_;
- size_t max_transfer_buffer_size_;
- size_t mapped_memory_limit_;
+ SharedMemoryLimits mem_limits_;
uint32_t flush_id_;
};
diff --git a/chromium/content/common/gpu/devtools_gpu_agent.cc b/chromium/content/common/gpu/devtools_gpu_agent.cc
new file mode 100644
index 00000000000..5c6baa154f3
--- /dev/null
+++ b/chromium/content/common/gpu/devtools_gpu_agent.cc
@@ -0,0 +1,79 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/devtools_gpu_agent.h"
+
+#include "base/logging.h"
+#include "content/common/devtools_messages.h"
+#include "content/common/gpu/gpu_channel.h"
+#include "content/common/gpu/gpu_channel_manager.h"
+
+namespace content {
+
+DevToolsGpuAgent::DevToolsGpuAgent(GpuChannel* gpu_channel) :
+ gpu_channel_(gpu_channel),
+ route_id_(MSG_ROUTING_NONE) {
+}
+
+DevToolsGpuAgent::~DevToolsGpuAgent() {
+}
+
+void DevToolsGpuAgent::StartEventsRecording(int32* route_id) {
+ DCHECK(CalledOnValidThread());
+ if (route_id_ != MSG_ROUTING_NONE) {
+ // Events recording is already in progress, so "fail" the call by
+ // returning MSG_ROUTING_NONE as the route id.
+ *route_id = MSG_ROUTING_NONE;
+ return;
+ }
+ route_id_ = gpu_channel_->GenerateRouteID();
+ *route_id = route_id_;
+ tasks_.reset(new GpuTaskInfoList());
+ GpuEventsDispatcher* dispatcher =
+ gpu_channel_->gpu_channel_manager()->gpu_devtools_events_dispatcher();
+ dispatcher->AddProcessor(this);
+}
+
+void DevToolsGpuAgent::StopEventsRecording() {
+ DCHECK(CalledOnValidThread());
+ if (route_id_ == MSG_ROUTING_NONE)
+ return;
+ GpuEventsDispatcher* dispatcher =
+ gpu_channel_->gpu_channel_manager()->gpu_devtools_events_dispatcher();
+ dispatcher->RemoveProcessor(this);
+ route_id_ = MSG_ROUTING_NONE;
+}
+
+void DevToolsGpuAgent::ProcessEvent(
+ TimeTicks timestamp,
+ GpuEventsDispatcher::EventPhase phase,
+ GpuCommandBufferStub* stub) {
+ DCHECK(CalledOnValidThread());
+ if (route_id_ == MSG_ROUTING_NONE)
+ return;
+
+ GpuTaskInfo task;
+ task.timestamp = (timestamp - TimeTicks()).InSecondsF();
+ task.phase = phase;
+ task.foreign = stub->channel() != gpu_channel_;
+ task.used_gpu_memory_bytes = stub->GetMemoryUsage();
+
+ const int kFlushIntervalMs = 100;
+ const unsigned kMaxPendingItems = 100;
+ if (!tasks_->empty() &&
+ ((timestamp - last_flush_time_).InMilliseconds() >= kFlushIntervalMs ||
+ tasks_->size() >= kMaxPendingItems)) {
+ Send(new DevToolsAgentMsg_GpuTasksChunk(route_id_, *tasks_));
+ tasks_->clear();
+ last_flush_time_ = timestamp;
+ }
+ tasks_->push_back(task);
+}
+
+bool DevToolsGpuAgent::Send(IPC::Message* msg) {
+ scoped_ptr<IPC::Message> message(msg);
+ return gpu_channel_ && gpu_channel_->Send(message.release());
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/devtools_gpu_agent.h b/chromium/content/common/gpu/devtools_gpu_agent.h
new file mode 100644
index 00000000000..6adf54b3aef
--- /dev/null
+++ b/chromium/content/common/gpu/devtools_gpu_agent.h
@@ -0,0 +1,52 @@
+// 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_COMMON_GPU_DEVTOOLS_GPU_AGENT_H_
+#define CONTENT_COMMON_GPU_DEVTOOLS_GPU_AGENT_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/non_thread_safe.h"
+#include "base/time/time.h"
+#include "content/common/gpu/devtools_gpu_instrumentation.h"
+
+using base::TimeTicks;
+struct GpuTaskInfo;
+
+namespace IPC {
+class Message;
+}
+
+namespace content {
+
+class GpuChannel;
+class GpuCommandBufferStub;
+
+class DevToolsGpuAgent : public base::NonThreadSafe {
+ public:
+ explicit DevToolsGpuAgent(GpuChannel* gpu_channel);
+ virtual ~DevToolsGpuAgent();
+
+ void ProcessEvent(TimeTicks timestamp,
+ GpuEventsDispatcher::EventPhase,
+ GpuCommandBufferStub* stub);
+
+ void StartEventsRecording(int32* route_id);
+ void StopEventsRecording();
+
+ private:
+ typedef std::vector<GpuTaskInfo> GpuTaskInfoList;
+
+ bool Send(IPC::Message* msg);
+
+ GpuChannel* gpu_channel_;
+ scoped_ptr<GpuTaskInfoList> tasks_;
+ TimeTicks last_flush_time_;
+ int32 route_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(DevToolsGpuAgent);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_DEVTOOLS_GPU_AGENT_H_
diff --git a/chromium/content/common/gpu/devtools_gpu_instrumentation.cc b/chromium/content/common/gpu/devtools_gpu_instrumentation.cc
new file mode 100644
index 00000000000..1425d133323
--- /dev/null
+++ b/chromium/content/common/gpu/devtools_gpu_instrumentation.cc
@@ -0,0 +1,50 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/devtools_gpu_instrumentation.h"
+
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "content/common/gpu/devtools_gpu_agent.h"
+#include "content/common/gpu/gpu_channel.h"
+#include "content/common/gpu/gpu_channel_manager.h"
+
+namespace content {
+
+bool GpuEventsDispatcher::enabled_ = false;
+
+GpuEventsDispatcher::GpuEventsDispatcher() {
+}
+
+GpuEventsDispatcher::~GpuEventsDispatcher() {
+}
+
+void GpuEventsDispatcher::AddProcessor(DevToolsGpuAgent* processor) {
+ DCHECK(CalledOnValidThread());
+ processors_.push_back(processor);
+ enabled_ = !processors_.empty();
+}
+
+void GpuEventsDispatcher::RemoveProcessor(DevToolsGpuAgent* processor) {
+ DCHECK(CalledOnValidThread());
+ processors_.erase(
+ std::remove(processors_.begin(), processors_.end(), processor),
+ processors_.end());
+ enabled_ = !processors_.empty();
+}
+
+// static
+void GpuEventsDispatcher::DoFireEvent(EventPhase phase,
+ GpuCommandBufferStub* stub) {
+ TimeTicks timestamp = base::TimeTicks::NowFromSystemTraceTime();
+ GpuEventsDispatcher* self =
+ stub->channel()->gpu_channel_manager()->gpu_devtools_events_dispatcher();
+ DCHECK(self->CalledOnValidThread());
+ std::vector<DevToolsGpuAgent*>::iterator it;
+ for (it = self->processors_.begin(); it != self->processors_.end(); ++it) {
+ (*it)->ProcessEvent(timestamp, phase, stub);
+ }
+}
+
+} // namespace
diff --git a/chromium/content/common/gpu/devtools_gpu_instrumentation.h b/chromium/content/common/gpu/devtools_gpu_instrumentation.h
new file mode 100644
index 00000000000..e67d52f2faa
--- /dev/null
+++ b/chromium/content/common/gpu/devtools_gpu_instrumentation.h
@@ -0,0 +1,65 @@
+// 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_COMMON_GPU_DEVTOOLS_GPU_INSTRUMENTATION_H_
+#define CONTENT_COMMON_GPU_DEVTOOLS_GPU_INSTRUMENTATION_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/threading/non_thread_safe.h"
+
+namespace content {
+
+class DevToolsGpuAgent;
+class GpuCommandBufferStub;
+
+class GpuEventsDispatcher : public base::NonThreadSafe {
+ public:
+ enum EventPhase {
+ kEventStart,
+ kEventFinish
+ };
+
+ GpuEventsDispatcher();
+ ~GpuEventsDispatcher();
+
+ void AddProcessor(DevToolsGpuAgent* processor);
+ void RemoveProcessor(DevToolsGpuAgent* processor);
+
+ static void FireEvent(EventPhase phase, GpuCommandBufferStub* stub) {
+ if (!IsEnabled())
+ return;
+ DoFireEvent(phase, stub);
+ }
+
+private:
+ static bool IsEnabled() { return enabled_; }
+ static void DoFireEvent(EventPhase, GpuCommandBufferStub* stub);
+
+ static bool enabled_;
+ std::vector<DevToolsGpuAgent*> processors_;
+};
+
+namespace devtools_gpu_instrumentation {
+
+class ScopedGpuTask {
+ public:
+ explicit ScopedGpuTask(GpuCommandBufferStub* stub) :
+ stub_(stub) {
+ GpuEventsDispatcher::FireEvent(GpuEventsDispatcher::kEventStart, stub_);
+ }
+ ~ScopedGpuTask() {
+ GpuEventsDispatcher::FireEvent(GpuEventsDispatcher::kEventFinish, stub_);
+ }
+ private:
+ GpuCommandBufferStub* stub_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedGpuTask);
+};
+
+} // namespace devtools_gpu_instrumentation
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_DEVTOOLS_GPU_INSTRUMENTATION_H_
diff --git a/chromium/content/common/gpu/gpu_channel.cc b/chromium/content/common/gpu/gpu_channel.cc
index 1876250144d..2e8fd78af28 100644
--- a/chromium/content/common/gpu/gpu_channel.cc
+++ b/chromium/content/common/gpu/gpu_channel.cc
@@ -18,6 +18,7 @@
#include "base/rand_util.h"
#include "base/strings/string_util.h"
#include "base/timer/timer.h"
+#include "content/common/gpu/devtools_gpu_agent.h"
#include "content/common/gpu/gpu_channel_manager.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/gpu/media/gpu_video_encode_accelerator.h"
@@ -487,6 +488,8 @@ bool GpuChannel::Init(base::MessageLoopProxy* io_message_loop,
io_message_loop_ = io_message_loop;
channel_->AddFilter(filter_.get());
+ devtools_gpu_agent_.reset(new DevToolsGpuAgent(this));
+
return true;
}
@@ -617,8 +620,6 @@ void GpuChannel::CreateViewCommandBuffer(
*route_id = MSG_ROUTING_NONE;
-#if defined(ENABLE_GPU)
-
GpuCommandBufferStub* share_group = stubs_.Lookup(init_params.share_group_id);
// Virtualize compositor contexts on OS X to prevent performance regressions
@@ -650,7 +651,6 @@ void GpuChannel::CreateViewCommandBuffer(
stub->SetPreemptByFlag(preempted_flag_);
router_.AddRoute(*route_id, stub.get());
stubs_.AddWithID(stub.release(), *route_id);
-#endif // ENABLE_GPU
}
GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) {
@@ -760,6 +760,10 @@ bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateVideoEncoder, OnCreateVideoEncoder)
IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyVideoEncoder,
OnDestroyVideoEncoder)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_DevToolsStartEventsRecording,
+ OnDevToolsStartEventsRecording)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_DevToolsStopEventsRecording,
+ OnDevToolsStopEventsRecording)
#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(GpuChannelMsg_RegisterStreamTextureProxy,
OnRegisterStreamTextureProxy)
@@ -921,6 +925,14 @@ void GpuChannel::OnDestroyVideoEncoder(int32 route_id) {
video_encoders_.Remove(route_id);
}
+void GpuChannel::OnDevToolsStartEventsRecording(int32* route_id) {
+ devtools_gpu_agent_->StartEventsRecording(route_id);
+}
+
+void GpuChannel::OnDevToolsStopEventsRecording() {
+ devtools_gpu_agent_->StopEventsRecording();
+}
+
#if defined(OS_ANDROID)
void GpuChannel::OnRegisterStreamTextureProxy(
int32 stream_id, int32* route_id) {
@@ -964,6 +976,11 @@ void GpuChannel::OnCollectRenderingStatsForSurface(
stats->total_processing_commands_time += total_processing_commands_time;
}
}
+
+ GPUVideoMemoryUsageStats usage_stats;
+ gpu_channel_manager_->gpu_memory_manager()->GetVideoMemoryUsageStats(
+ &usage_stats);
+ stats->global_video_memory_bytes_allocated = usage_stats.bytes_allocated;
}
void GpuChannel::MessageProcessed() {
diff --git a/chromium/content/common/gpu/gpu_channel.h b/chromium/content/common/gpu/gpu_channel.h
index 23c27e0a0a4..2808ed47c76 100644
--- a/chromium/content/common/gpu/gpu_channel.h
+++ b/chromium/content/common/gpu/gpu_channel.h
@@ -49,6 +49,7 @@ class StreamTextureManagerAndroid;
#endif
namespace content {
+class DevToolsGpuAgent;
class GpuChannelManager;
class GpuChannelMessageFilter;
struct GpuRenderingStats;
@@ -184,6 +185,8 @@ class GpuChannel : public IPC::Listener,
void OnDestroyCommandBuffer(int32 route_id);
void OnCreateVideoEncoder(int32* route_id);
void OnDestroyVideoEncoder(int32 route_id);
+ void OnDevToolsStartEventsRecording(int32* route_id);
+ void OnDevToolsStopEventsRecording();
#if defined(OS_ANDROID)
// Register the StreamTextureProxy class with the gpu process so that all
@@ -244,10 +247,8 @@ class GpuChannel : public IPC::Listener,
scoped_ptr<StreamTextureManagerAndroid> stream_texture_manager_;
#endif
-#if defined(ENABLE_GPU)
typedef IDMap<GpuCommandBufferStub, IDMapOwnPointer> StubMap;
StubMap stubs_;
-#endif // defined (ENABLE_GPU)
typedef IDMap<GpuVideoEncodeAccelerator, IDMapOwnPointer> EncoderMap;
EncoderMap video_encoders_;
@@ -264,6 +265,7 @@ class GpuChannel : public IPC::Listener,
scoped_refptr<GpuChannelMessageFilter> filter_;
scoped_refptr<base::MessageLoopProxy> io_message_loop_;
+ scoped_ptr<DevToolsGpuAgent> devtools_gpu_agent_;
size_t num_stubs_descheduled_;
diff --git a/chromium/content/common/gpu/gpu_channel_manager.h b/chromium/content/common/gpu/gpu_channel_manager.h
index e41a5481734..1ab04d94324 100644
--- a/chromium/content/common/gpu/gpu_channel_manager.h
+++ b/chromium/content/common/gpu/gpu_channel_manager.h
@@ -15,6 +15,7 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "build/build_config.h"
+#include "content/common/gpu/devtools_gpu_instrumentation.h"
#include "content/common/gpu/gpu_memory_manager.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
@@ -93,6 +94,10 @@ class GpuChannelManager : public IPC::Listener,
GpuMemoryManager* gpu_memory_manager() { return &gpu_memory_manager_; }
+ GpuEventsDispatcher* gpu_devtools_events_dispatcher() {
+ return &gpu_devtools_events_dispatcher_;
+ }
+
GpuChannel* LookupChannel(int32 client_id);
SyncPointManager* sync_point_manager() { return sync_point_manager_.get(); }
@@ -144,6 +149,7 @@ class GpuChannelManager : public IPC::Listener,
scoped_refptr<gfx::GLShareGroup> share_group_;
scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_;
GpuMemoryManager gpu_memory_manager_;
+ GpuEventsDispatcher gpu_devtools_events_dispatcher_;
GpuWatchdog* watchdog_;
scoped_refptr<SyncPointManager> sync_point_manager_;
scoped_ptr<gpu::gles2::ProgramCache> program_cache_;
diff --git a/chromium/content/common/gpu/gpu_command_buffer_stub.cc b/chromium/content/common/gpu/gpu_command_buffer_stub.cc
index da3fb0ec65f..44eaf90cc85 100644
--- a/chromium/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/chromium/content/common/gpu/gpu_command_buffer_stub.cc
@@ -10,6 +10,7 @@
#include "base/memory/shared_memory.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "content/common/gpu/devtools_gpu_instrumentation.h"
#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/gpu_channel_manager.h"
#include "content/common/gpu/gpu_command_buffer_stub.h"
@@ -18,7 +19,6 @@
#include "content/common/gpu/gpu_messages.h"
#include "content/common/gpu/gpu_watchdog.h"
#include "content/common/gpu/image_transport_surface.h"
-#include "content/common/gpu/media/gl_surface_capturer.h"
#include "content/common/gpu/media/gpu_video_decode_accelerator.h"
#include "content/common/gpu/sync_point_manager.h"
#include "content/public/common/content_client.h"
@@ -27,6 +27,8 @@
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/service/gl_context_virtual.h"
#include "gpu/command_buffer/service/gl_state_restorer_impl.h"
+#include "gpu/command_buffer/service/gpu_control_service.h"
+#include "gpu/command_buffer/service/image_manager.h"
#include "gpu/command_buffer/service/logger.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/query_manager.h"
@@ -148,6 +150,7 @@ GpuCommandBufferStub::GpuCommandBufferStub(
image_manager,
new GpuCommandBufferMemoryTracker(channel),
stream_texture_manager,
+ NULL,
true);
}
@@ -162,11 +165,12 @@ GpuCommandBufferStub::~GpuCommandBufferStub() {
gpu_channel_manager->Send(new GpuHostMsg_DestroyCommandBuffer(surface_id()));
}
-GpuMemoryManager* GpuCommandBufferStub::GetMemoryManager() {
+GpuMemoryManager* GpuCommandBufferStub::GetMemoryManager() const {
return channel()->gpu_channel_manager()->gpu_memory_manager();
}
bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
+ devtools_gpu_instrumentation::ScopedGpuTask task(this);
FastSetActiveURL(active_url_, active_url_hash_);
// Ensure the appropriate GL context is current before handling any IPC
@@ -207,14 +211,8 @@ bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
OnGetTransferBuffer);
IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_CreateVideoDecoder,
OnCreateVideoDecoder)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_CreateSurfaceCapturer,
- OnCreateSurfaceCapturer)
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetSurfaceVisible,
OnSetSurfaceVisible)
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DiscardBackbuffer,
- OnDiscardBackbuffer)
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_EnsureBackbuffer,
- OnEnsureBackbuffer)
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RetireSyncPoint,
OnRetireSyncPoint)
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalSyncPoint,
@@ -226,6 +224,10 @@ bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(
GpuCommandBufferMsg_SetClientHasMemoryAllocationChangedCallback,
OnSetClientHasMemoryAllocationChangedCallback)
+ IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterGpuMemoryBuffer,
+ OnRegisterGpuMemoryBuffer);
+ IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyGpuMemoryBuffer,
+ OnDestroyGpuMemoryBuffer);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -384,7 +386,8 @@ void GpuCommandBufferStub::Destroy() {
void GpuCommandBufferStub::OnInitializeFailed(IPC::Message* reply_message) {
Destroy();
- GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, false);
+ GpuCommandBufferMsg_Initialize::WriteReplyParams(
+ reply_message, false, gpu::Capabilities());
Send(reply_message);
}
@@ -507,6 +510,13 @@ void GpuCommandBufferStub::OnInitialize(
return;
}
+ gpu_control_.reset(
+ new gpu::GpuControlService(context_group_->image_manager(),
+ NULL,
+ context_group_->mailbox_manager(),
+ NULL,
+ decoder_->GetCapabilities()));
+
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableGPUServiceLogging)) {
decoder_->set_log_commands(true);
@@ -545,7 +555,8 @@ void GpuCommandBufferStub::OnInitialize(
return;
}
- GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, true);
+ GpuCommandBufferMsg_Initialize::WriteReplyParams(
+ reply_message, true, gpu_control_->GetCapabilities());
Send(reply_message);
if (handle_.is_null() && !active_url_.is_empty()) {
@@ -566,6 +577,18 @@ void GpuCommandBufferStub::SetLatencyInfoCallback(
latency_info_callback_ = callback;
}
+int32 GpuCommandBufferStub::GetRequestedAttribute(int attr) const {
+ // The command buffer is pairs of enum, value
+ // search for the requested attribute, return the value.
+ for (std::vector<int32>::const_iterator it = requested_attribs_.begin();
+ it != requested_attribs_.end(); ++it) {
+ if (*it++ == attr) {
+ return *it;
+ }
+ }
+ return -1;
+}
+
void GpuCommandBufferStub::OnSetGetBuffer(int32 shm_id,
IPC::Message* reply_message) {
TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSetGetBuffer");
@@ -727,50 +750,12 @@ void GpuCommandBufferStub::OnCreateVideoDecoder(
// self-delete during destruction of this stub.
}
-void GpuCommandBufferStub::OnCreateSurfaceCapturer(
- IPC::Message* reply_message) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnCreateSurfaceCapturer");
- int capturer_route_id = channel_->GenerateRouteID();
- new GLSurfaceCapturer(capturer_route_id, this);
- // The capturer is registered as a DestructionObserver of this stub and will
- // self-delete during destruction of this stub.
- GpuCommandBufferMsg_CreateSurfaceCapturer::WriteReplyParams(
- reply_message, capturer_route_id);
- Send(reply_message);
-}
-
void GpuCommandBufferStub::OnSetSurfaceVisible(bool visible) {
TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSetSurfaceVisible");
if (memory_manager_client_state_)
memory_manager_client_state_->SetVisible(visible);
}
-void GpuCommandBufferStub::OnDiscardBackbuffer() {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDiscardBackbuffer");
- if (!surface_.get())
- return;
- if (surface_->DeferDraws()) {
- DCHECK(!IsScheduled());
- channel_->RequeueMessage();
- } else {
- if (!surface_->SetBackbufferAllocation(false))
- channel_->DestroySoon();
- }
-}
-
-void GpuCommandBufferStub::OnEnsureBackbuffer() {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnEnsureBackbuffer");
- if (!surface_.get())
- return;
- if (surface_->DeferDraws()) {
- DCHECK(!IsScheduled());
- channel_->RequeueMessage();
- } else {
- if (!surface_->SetBackbufferAllocation(true))
- channel_->DestroySoon();
- }
-}
-
void GpuCommandBufferStub::AddSyncPoint(uint32 sync_point) {
sync_points_.push_back(sync_point);
}
@@ -840,7 +825,7 @@ void GpuCommandBufferStub::OnSignalQuery(uint32 query_id, uint32 id) {
void GpuCommandBufferStub::OnReceivedClientManagedMemoryStats(
- const GpuManagedMemoryStats& stats) {
+ const gpu::ManagedMemoryStats& stats) {
TRACE_EVENT0(
"gpu",
"GpuCommandBufferStub::OnReceivedClientManagedMemoryStats");
@@ -863,6 +848,28 @@ void GpuCommandBufferStub::OnSetClientHasMemoryAllocationChangedCallback(
}
}
+void GpuCommandBufferStub::OnRegisterGpuMemoryBuffer(
+ int32 id,
+ gfx::GpuMemoryBufferHandle gpu_memory_buffer,
+ uint32 width,
+ uint32 height,
+ uint32 internalformat) {
+ TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnRegisterGpuMemoryBuffer");
+ if (gpu_control_) {
+ gpu_control_->RegisterGpuMemoryBuffer(id,
+ gpu_memory_buffer,
+ width,
+ height,
+ internalformat);
+ }
+}
+
+void GpuCommandBufferStub::OnDestroyGpuMemoryBuffer(int32 id) {
+ TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyGpuMemoryBuffer");
+ if (gpu_control_)
+ gpu_control_->DestroyGpuMemoryBuffer(id);
+}
+
void GpuCommandBufferStub::SendConsoleMessage(
int32 id,
const std::string& message) {
@@ -913,28 +920,25 @@ gpu::gles2::MemoryTracker* GpuCommandBufferStub::GetMemoryTracker() const {
}
void GpuCommandBufferStub::SetMemoryAllocation(
- const GpuMemoryAllocation& allocation) {
+ const gpu::MemoryAllocation& allocation) {
if (!last_memory_allocation_valid_ ||
- !allocation.renderer_allocation.Equals(
- last_memory_allocation_.renderer_allocation)) {
+ !allocation.Equals(last_memory_allocation_)) {
Send(new GpuCommandBufferMsg_SetMemoryAllocation(
- route_id_, allocation.renderer_allocation));
- }
-
- if (!last_memory_allocation_valid_ ||
- !allocation.browser_allocation.Equals(
- last_memory_allocation_.browser_allocation)) {
- // This can be called outside of OnMessageReceived, so the context needs
- // to be made current before calling methods on the surface.
- if (surface_.get() && MakeCurrent())
- surface_->SetFrontbufferAllocation(
- allocation.browser_allocation.suggest_have_frontbuffer);
+ route_id_, allocation));
}
last_memory_allocation_valid_ = true;
last_memory_allocation_ = allocation;
}
+void GpuCommandBufferStub::SuggestHaveFrontBuffer(
+ bool suggest_have_frontbuffer) {
+ // This can be called outside of OnMessageReceived, so the context needs
+ // to be made current before calling methods on the surface.
+ if (surface_.get() && MakeCurrent())
+ surface_->SetFrontbufferAllocation(suggest_have_frontbuffer);
+}
+
bool GpuCommandBufferStub::CheckContextLost() {
DCHECK(command_buffer_);
gpu::CommandBuffer::State state = command_buffer_->GetState();
@@ -959,4 +963,8 @@ void GpuCommandBufferStub::MarkContextLost() {
command_buffer_->SetParseError(gpu::error::kLostContext);
}
+uint64 GpuCommandBufferStub::GetMemoryUsage() const {
+ return GetMemoryManager()->GetClientMemoryUsage(this);
+}
+
} // namespace content
diff --git a/chromium/content/common/gpu/gpu_command_buffer_stub.h b/chromium/content/common/gpu/gpu_command_buffer_stub.h
index 7414b26d6eb..247329e51a7 100644
--- a/chromium/content/common/gpu/gpu_command_buffer_stub.h
+++ b/chromium/content/common/gpu/gpu_command_buffer_stub.h
@@ -13,10 +13,10 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "content/common/content_export.h"
-#include "content/common/gpu/gpu_memory_allocation.h"
#include "content/common/gpu/gpu_memory_manager.h"
#include "content/common/gpu/gpu_memory_manager_client.h"
#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
@@ -24,6 +24,7 @@
#include "ipc/ipc_sender.h"
#include "media/base/video_decoder_config.h"
#include "ui/events/latency_info.h"
+#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
#include "ui/gl/gl_surface.h"
@@ -31,6 +32,7 @@
#include "url/gurl.h"
namespace gpu {
+class GpuControlService;
struct Mailbox;
namespace gles2 {
class ImageManager;
@@ -91,7 +93,8 @@ class GpuCommandBufferStub
virtual gfx::Size GetSurfaceSize() const OVERRIDE;
virtual gpu::gles2::MemoryTracker* GetMemoryTracker() const OVERRIDE;
virtual void SetMemoryAllocation(
- const GpuMemoryAllocation& allocation) OVERRIDE;
+ const gpu::MemoryAllocation& allocation) OVERRIDE;
+ virtual void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer) OVERRIDE;
virtual bool GetTotalGpuMemory(uint64* bytes) OVERRIDE;
// Whether this command buffer can currently handle IPC messages.
@@ -118,6 +121,8 @@ class GpuCommandBufferStub
gfx::GpuPreference gpu_preference() { return gpu_preference_; }
+ int32 GetRequestedAttribute(int attr) const;
+
// Sends a message to the console.
void SendConsoleMessage(int32 id, const std::string& message);
@@ -138,8 +143,10 @@ class GpuCommandBufferStub
void MarkContextLost();
+ uint64 GetMemoryUsage() const;
+
private:
- GpuMemoryManager* GetMemoryManager();
+ GpuMemoryManager* GetMemoryManager() const;
bool MakeCurrent();
void Destroy();
@@ -166,11 +173,8 @@ class GpuCommandBufferStub
media::VideoCodecProfile profile,
IPC::Message* reply_message);
- void OnCreateSurfaceCapturer(IPC::Message* reply_message);
-
void OnSetSurfaceVisible(bool visible);
- void OnDiscardBackbuffer();
void OnEnsureBackbuffer();
void OnRetireSyncPoint(uint32 sync_point);
@@ -180,9 +184,16 @@ class GpuCommandBufferStub
void OnSignalSyncPointAck(uint32 id);
void OnSignalQuery(uint32 query, uint32 id);
- void OnReceivedClientManagedMemoryStats(const GpuManagedMemoryStats& stats);
+ void OnReceivedClientManagedMemoryStats(const gpu::ManagedMemoryStats& stats);
void OnSetClientHasMemoryAllocationChangedCallback(bool has_callback);
+ void OnRegisterGpuMemoryBuffer(int32 id,
+ gfx::GpuMemoryBufferHandle gpu_memory_buffer,
+ uint32 width,
+ uint32 height,
+ uint32 internalformat);
+ void OnDestroyGpuMemoryBuffer(int32 id);
+
void OnCommandProcessed();
void OnParseError();
void OnSetLatencyInfo(const ui::LatencyInfo& latency_info);
@@ -225,12 +236,13 @@ class GpuCommandBufferStub
scoped_ptr<gpu::gles2::GLES2Decoder> decoder_;
scoped_ptr<gpu::GpuScheduler> scheduler_;
scoped_refptr<gfx::GLSurface> surface_;
+ scoped_ptr<gpu::GpuControlService> gpu_control_;
scoped_ptr<GpuMemoryManagerClientState> memory_manager_client_state_;
// The last memory allocation received from the GpuMemoryManager (used to
// elide redundant work).
bool last_memory_allocation_valid_;
- GpuMemoryAllocation last_memory_allocation_;
+ gpu::MemoryAllocation last_memory_allocation_;
GpuWatchdog* watchdog_;
diff --git a/chromium/content/common/gpu/gpu_memory_allocation.h b/chromium/content/common/gpu/gpu_memory_allocation.h
deleted file mode 100644
index a2a9b9ac725..00000000000
--- a/chromium/content/common/gpu/gpu_memory_allocation.h
+++ /dev/null
@@ -1,156 +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_GPU_GPU_MEMORY_ALLOCATION_H_
-#define CONTENT_COMMON_GPU_GPU_MEMORY_ALLOCATION_H_
-
-#include "base/basictypes.h"
-
-namespace content {
-
-// These are per context memory allocation limits set by the GpuMemoryManager
-// and assigned to the browser and renderer context.
-// They will change over time, given memory availability, and browser state.
-
-// Memory Allocation which will be assigned to the renderer context.
-struct GpuMemoryAllocationForRenderer {
- enum PriorityCutoff {
- // Allow no allocations.
- kPriorityCutoffAllowNothing,
- // Allow only allocations that are strictly required for correct rendering.
- // For compositors, this is what is visible.
- kPriorityCutoffAllowOnlyRequired,
- // Allow allocations that are not strictly needed for correct rendering, but
- // are nice to have for performance. For compositors, this includes textures
- // that are a few screens away from being visible.
- kPriorityCutoffAllowNiceToHave,
- // Allow all allocations.
- kPriorityCutoffAllowEverything,
- };
-
- // Limits when this renderer is visible.
- uint64 bytes_limit_when_visible;
- PriorityCutoff priority_cutoff_when_visible;
-
- // Limits when this renderer is not visible.
- uint64 bytes_limit_when_not_visible;
- PriorityCutoff priority_cutoff_when_not_visible;
- bool have_backbuffer_when_not_visible;
-
- GpuMemoryAllocationForRenderer()
- : bytes_limit_when_visible(0),
- priority_cutoff_when_visible(kPriorityCutoffAllowNothing),
- bytes_limit_when_not_visible(0),
- priority_cutoff_when_not_visible(kPriorityCutoffAllowNothing),
- have_backbuffer_when_not_visible(false) {
- }
-
- GpuMemoryAllocationForRenderer(uint64 bytes_limit_when_visible)
- : bytes_limit_when_visible(bytes_limit_when_visible),
- priority_cutoff_when_visible(kPriorityCutoffAllowEverything),
- bytes_limit_when_not_visible(0),
- priority_cutoff_when_not_visible(kPriorityCutoffAllowNothing),
- have_backbuffer_when_not_visible(false) {
- }
-
- bool Equals(const GpuMemoryAllocationForRenderer& other) const {
- return bytes_limit_when_visible ==
- other.bytes_limit_when_visible &&
- priority_cutoff_when_visible == other.priority_cutoff_when_visible &&
- bytes_limit_when_not_visible == other.bytes_limit_when_not_visible &&
- priority_cutoff_when_not_visible ==
- other.priority_cutoff_when_not_visible &&
- have_backbuffer_when_not_visible ==
- other.have_backbuffer_when_not_visible;
- }
-};
-
-// Memory Allocation which will be assigned to the browser.
-struct GpuMemoryAllocationForBrowser {
- bool suggest_have_frontbuffer;
-
- GpuMemoryAllocationForBrowser()
- : suggest_have_frontbuffer(false) {
- }
-
- GpuMemoryAllocationForBrowser(bool suggest_have_frontbuffer)
- : suggest_have_frontbuffer(suggest_have_frontbuffer) {
- }
-
- bool Equals(const GpuMemoryAllocationForBrowser& other) const {
- return suggest_have_frontbuffer == other.suggest_have_frontbuffer;
- }
-};
-
-// Combination of the above two Memory Allocations which will be created by the
-// GpuMemoryManager.
-struct GpuMemoryAllocation {
- GpuMemoryAllocationForRenderer renderer_allocation;
- GpuMemoryAllocationForBrowser browser_allocation;
-
- enum BufferAllocation {
- kHasNoFrontbuffer = 0,
- kHasFrontbuffer = 1,
- };
-
- GpuMemoryAllocation() {
- }
-
- GpuMemoryAllocation(uint64 gpu_resource_size_in_bytes,
- BufferAllocation buffer_allocation)
- : renderer_allocation(gpu_resource_size_in_bytes),
- browser_allocation(buffer_allocation == kHasFrontbuffer) {
- }
-
- bool Equals(const GpuMemoryAllocation& other) const {
- return renderer_allocation.Equals(other.renderer_allocation) &&
- browser_allocation.Equals(other.browser_allocation);
- }
-};
-
-// Memory Allocation request which is sent by a client, to help GpuMemoryManager
-// more ideally split memory allocations across clients.
-struct GpuManagedMemoryStats {
- // Bytes required for correct rendering.
- uint64 bytes_required;
-
- // Bytes that are not strictly required for correctness, but, if allocated,
- // will provide good performance.
- uint64 bytes_nice_to_have;
-
- // The number of bytes currently allocated.
- uint64 bytes_allocated;
-
- // Whether or not a backbuffer is currently requested (the memory usage
- // of the buffer is known by the GPU process).
- bool backbuffer_requested;
-
- GpuManagedMemoryStats()
- : bytes_required(0),
- bytes_nice_to_have(0),
- bytes_allocated(0),
- backbuffer_requested(false) {
- }
-
- GpuManagedMemoryStats(uint64 bytes_required,
- uint64 bytes_nice_to_have,
- uint64 bytes_allocated,
- bool backbuffer_requested)
- : bytes_required(bytes_required),
- bytes_nice_to_have(bytes_nice_to_have),
- bytes_allocated(bytes_allocated),
- backbuffer_requested(backbuffer_requested) {
- }
-
- bool Equals(const GpuManagedMemoryStats& other) const {
- return bytes_required == other.bytes_required &&
- bytes_nice_to_have == other.bytes_nice_to_have &&
- bytes_allocated == other.bytes_allocated &&
- backbuffer_requested == other.backbuffer_requested;
- }
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_MEMORY_ALLOCATION_H_
diff --git a/chromium/content/common/gpu/gpu_memory_manager.cc b/chromium/content/common/gpu/gpu_memory_manager.cc
index cb6b6c6893d..5dfd3fb7876 100644
--- a/chromium/content/common/gpu/gpu_memory_manager.cc
+++ b/chromium/content/common/gpu/gpu_memory_manager.cc
@@ -13,13 +13,16 @@
#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
#include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_memory_allocation.h"
#include "content/common/gpu/gpu_memory_manager_client.h"
#include "content/common/gpu/gpu_memory_tracking.h"
#include "content/common/gpu/gpu_memory_uma_stats.h"
#include "content/common/gpu/gpu_messages.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "gpu/command_buffer/service/gpu_switches.h"
+using gpu::ManagedMemoryStats;
+using gpu::MemoryAllocation;
+
namespace content {
namespace {
@@ -51,13 +54,12 @@ GpuMemoryManager::GpuMemoryManager(
manage_immediate_scheduled_(false),
max_surfaces_with_frontbuffer_soft_limit_(
max_surfaces_with_frontbuffer_soft_limit),
+ priority_cutoff_(MemoryAllocation::CUTOFF_ALLOW_EVERYTHING),
bytes_available_gpu_memory_(0),
bytes_available_gpu_memory_overridden_(false),
bytes_minimum_per_client_(0),
bytes_default_per_client_(0),
bytes_allocated_managed_current_(0),
- bytes_allocated_managed_visible_(0),
- bytes_allocated_managed_nonvisible_(0),
bytes_allocated_unmanaged_current_(0),
bytes_allocated_historical_max_(0),
bytes_allocated_unmanaged_high_(0),
@@ -67,29 +69,28 @@ GpuMemoryManager::GpuMemoryManager(
{
CommandLine* command_line = CommandLine::ForCurrentProcess();
+ // Use a more conservative memory allocation policy on Linux and Mac because
+ // the platform is unstable when under memory pressure.
+ // http://crbug.com/145600 (Linux)
+ // http://crbug.com/141377 (Mac)
+#if defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+ priority_cutoff_ = MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
+#endif
+
#if defined(OS_ANDROID)
bytes_default_per_client_ = 8 * 1024 * 1024;
bytes_minimum_per_client_ = 8 * 1024 * 1024;
#elif defined(OS_CHROMEOS)
bytes_default_per_client_ = 64 * 1024 * 1024;
bytes_minimum_per_client_ = 4 * 1024 * 1024;
+#elif defined(OS_MACOSX)
+ bytes_default_per_client_ = 128 * 1024 * 1024;
+ bytes_minimum_per_client_ = 128 * 1024 * 1024;
#else
bytes_default_per_client_ = 64 * 1024 * 1024;
bytes_minimum_per_client_ = 64 * 1024 * 1024;
#endif
- // On Android, always discard everything that is nonvisible.
- // On Linux and Mac, use as little memory as possible to avoid stability
- // issues.
- // http://crbug.com/145600 (Linux)
- // http://crbug.com/141377 (Mac)
-#if defined(OS_ANDROID) || defined(OS_MACOSX) || \
- (defined(OS_LINUX) && !defined(OS_CHROMEOS))
- allow_nonvisible_memory_ = false;
-#else
- allow_nonvisible_memory_ = true;
-#endif
-
if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) {
base::StringToUint64(
command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb),
@@ -107,8 +108,6 @@ GpuMemoryManager::~GpuMemoryManager() {
DCHECK(clients_nonsurface_.empty());
DCHECK(!bytes_allocated_managed_current_);
DCHECK(!bytes_allocated_unmanaged_current_);
- DCHECK(!bytes_allocated_managed_visible_);
- DCHECK(!bytes_allocated_managed_nonvisible_);
}
uint64 GpuMemoryManager::GetAvailableGpuMemory() const {
@@ -295,10 +294,6 @@ GpuMemoryManagerClientState* GpuMemoryManager::CreateClientState(
GpuMemoryManagerClientState* client_state = new GpuMemoryManagerClientState(
this, client, tracking_group, has_surface, visible);
- TrackValueChanged(0, client_state->managed_memory_stats_.bytes_allocated,
- client_state->visible_ ?
- &bytes_allocated_managed_visible_ :
- &bytes_allocated_managed_nonvisible_);
AddClientToList(client_state);
ScheduleManage(kScheduleManageNow);
return client_state;
@@ -307,10 +302,6 @@ GpuMemoryManagerClientState* GpuMemoryManager::CreateClientState(
void GpuMemoryManager::OnDestroyClientState(
GpuMemoryManagerClientState* client_state) {
RemoveClientFromList(client_state);
- TrackValueChanged(client_state->managed_memory_stats_.bytes_allocated, 0,
- client_state->visible_ ?
- &bytes_allocated_managed_visible_ :
- &bytes_allocated_managed_nonvisible_);
ScheduleManage(kScheduleManageLater);
}
@@ -323,27 +314,13 @@ void GpuMemoryManager::SetClientStateVisible(
RemoveClientFromList(client_state);
client_state->visible_ = visible;
AddClientToList(client_state);
-
- TrackValueChanged(client_state->managed_memory_stats_.bytes_allocated, 0,
- client_state->visible_ ?
- &bytes_allocated_managed_nonvisible_ :
- &bytes_allocated_managed_visible_);
- TrackValueChanged(0, client_state->managed_memory_stats_.bytes_allocated,
- client_state->visible_ ?
- &bytes_allocated_managed_visible_ :
- &bytes_allocated_managed_nonvisible_);
ScheduleManage(visible ? kScheduleManageNow : kScheduleManageLater);
}
void GpuMemoryManager::SetClientStateManagedMemoryStats(
GpuMemoryManagerClientState* client_state,
- const GpuManagedMemoryStats& stats)
+ const ManagedMemoryStats& stats)
{
- TrackValueChanged(client_state->managed_memory_stats_.bytes_allocated,
- stats.bytes_allocated,
- client_state->visible_ ?
- &bytes_allocated_managed_visible_ :
- &bytes_allocated_managed_nonvisible_);
client_state->managed_memory_stats_ = stats;
// If this is the first time that stats have been received for this
@@ -365,6 +342,14 @@ void GpuMemoryManager::SetClientStateManagedMemoryStats(
}
}
+uint64 GpuMemoryManager::GetClientMemoryUsage(
+ const GpuMemoryManagerClient* client) const{
+ TrackingGroupMap::const_iterator tracking_group_it =
+ tracking_groups_.find(client->GetMemoryTracker());
+ DCHECK(tracking_group_it != tracking_groups_.end());
+ return tracking_group_it->second->GetSize();
+}
+
GpuMemoryTrackingGroup* GpuMemoryManager::CreateTrackingGroup(
base::ProcessId pid, gpu::gles2::MemoryTracker* memory_tracker) {
GpuMemoryTrackingGroup* tracking_group = new GpuMemoryTrackingGroup(
@@ -474,7 +459,7 @@ uint64 GpuMemoryManager::ComputeClientAllocationWhenVisible(
uint64 bytes_above_required_cap,
uint64 bytes_above_minimum_cap,
uint64 bytes_overall_cap) {
- GpuManagedMemoryStats* stats = &client_state->managed_memory_stats_;
+ ManagedMemoryStats* stats = &client_state->managed_memory_stats_;
if (!client_state->managed_memory_stats_received_)
return GetDefaultClientAllocation();
@@ -498,17 +483,6 @@ uint64 GpuMemoryManager::ComputeClientAllocationWhenVisible(
return allocation;
}
-uint64 GpuMemoryManager::ComputeClientAllocationWhenNonvisible(
- GpuMemoryManagerClientState* client_state) {
- if (!client_state->managed_memory_stats_received_)
- return 0;
-
- if (!allow_nonvisible_memory_)
- return 0;
-
- return 9 * client_state->managed_memory_stats_.bytes_required / 8;
-}
-
void GpuMemoryManager::ComputeVisibleSurfacesAllocations() {
uint64 bytes_available_total = GetAvailableGpuMemory();
uint64 bytes_above_required_cap = std::numeric_limits<uint64>::max();
@@ -607,7 +581,7 @@ void GpuMemoryManager::ComputeVisibleSurfacesAllocations() {
}
// Set the limit for nonvisible clients for when they become visible.
- // Use the same formula, with a lowered overall cap to in case any of the
+ // Use the same formula, with a lowered overall cap in case any of the
// currently-nonvisible clients are much more resource-intensive than any
// of the existing clients.
uint64 bytes_overall_cap_nonvisible = bytes_allocated_max_client_allocation;
@@ -630,75 +604,6 @@ void GpuMemoryManager::ComputeVisibleSurfacesAllocations() {
}
}
-void GpuMemoryManager::ComputeNonvisibleSurfacesAllocations() {
- uint64 bytes_allocated_visible = 0;
- for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
- it != clients_visible_mru_.end();
- ++it) {
- GpuMemoryManagerClientState* client_state = *it;
- bytes_allocated_visible += client_state->bytes_allocation_when_visible_;
- }
-
- // Allow up to 1/4 of the memory that was available for visible clients to
- // go to nonvisible clients.
- uint64 bytes_available_total = GetAvailableGpuMemory();
- uint64 bytes_available_nonvisible = 0;
- uint64 bytes_allocated_nonvisible = 0;
- if (bytes_available_total > bytes_allocated_visible) {
- bytes_available_nonvisible = std::min(
- bytes_available_total / 4,
- bytes_available_total - bytes_allocated_visible);
- }
-
- // Determine which now-visible clients should keep their contents when
- // they are made nonvisible.
- for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
- it != clients_visible_mru_.end();
- ++it) {
- GpuMemoryManagerClientState* client_state = *it;
-
- // Compute the amount of space available have for this renderer when it is
- // nonvisible. Do not count this client's allocation while visible against
- // the nonvisible clients' allocation total.
- uint64 bytes_available_nonvisible_adjusted = std::min(
- bytes_available_nonvisible +
- client_state->bytes_allocation_when_visible_ / 4,
- bytes_available_total / 4);
-
- // Allow this client to keep its contents if they fit in the allocation.
- client_state->bytes_allocation_when_nonvisible_ =
- ComputeClientAllocationWhenNonvisible(client_state);
- if (client_state->bytes_allocation_when_nonvisible_ >
- bytes_available_nonvisible_adjusted)
- client_state->bytes_allocation_when_nonvisible_ = 0;
- }
-
- // Compute which currently nonvisible clients should keep their contents.
- for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin();
- it != clients_nonvisible_mru_.end();
- ++it) {
- GpuMemoryManagerClientState* client_state = *it;
-
- // If this client is nonvisible and has already had its contents discarded,
- // don't re-generate the contents until the client becomes visible again.
- if (!client_state->bytes_allocation_when_nonvisible_)
- continue;
-
- client_state->bytes_allocation_when_nonvisible_ =
- ComputeClientAllocationWhenNonvisible(client_state);
-
- // Take into account all more recently used nonvisible clients, and only if
- // this client still fits, all it to keep its contents.
- if (bytes_allocated_nonvisible +
- client_state->bytes_allocation_when_nonvisible_ >
- bytes_available_nonvisible) {
- client_state->bytes_allocation_when_nonvisible_ = 0;
- }
- bytes_allocated_nonvisible +=
- client_state->bytes_allocation_when_nonvisible_;
- }
-}
-
void GpuMemoryManager::DistributeRemainingMemoryToVisibleSurfaces() {
uint64 bytes_available_total = GetAvailableGpuMemory();
uint64 bytes_allocated_total = 0;
@@ -709,12 +614,6 @@ void GpuMemoryManager::DistributeRemainingMemoryToVisibleSurfaces() {
GpuMemoryManagerClientState* client_state = *it;
bytes_allocated_total += client_state->bytes_allocation_when_visible_;
}
- for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin();
- it != clients_nonvisible_mru_.end();
- ++it) {
- GpuMemoryManagerClientState* client_state = *it;
- bytes_allocated_total += client_state->bytes_allocation_when_nonvisible_;
- }
if (bytes_allocated_total >= bytes_available_total)
return;
@@ -746,7 +645,6 @@ void GpuMemoryManager::DistributeRemainingMemoryToVisibleSurfaces() {
void GpuMemoryManager::AssignSurfacesAllocations() {
// Compute allocation when for all clients.
ComputeVisibleSurfacesAllocations();
- ComputeNonvisibleSurfacesAllocations();
// Distribute the remaining memory to visible clients.
DistributeRemainingMemoryToVisibleSurfaces();
@@ -769,30 +667,14 @@ void GpuMemoryManager::AssignSurfacesAllocations() {
3 * client_state->managed_memory_stats_.bytes_nice_to_have / 4;
// Populate and send the allocation to the client
- GpuMemoryAllocation allocation;
-
- allocation.browser_allocation.suggest_have_frontbuffer =
- !client_state->hibernated_;
+ MemoryAllocation allocation;
- allocation.renderer_allocation.bytes_limit_when_visible =
+ allocation.bytes_limit_when_visible =
client_state->bytes_allocation_when_visible_;
- // Use a more conservative memory allocation policy on Linux and Mac
- // because the platform is unstable when under memory pressure.
- // http://crbug.com/145600 (Linux)
- // http://crbug.com/141377 (Mac)
- allocation.renderer_allocation.priority_cutoff_when_visible =
-#if defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
- GpuMemoryAllocationForRenderer::kPriorityCutoffAllowNiceToHave;
-#else
- GpuMemoryAllocationForRenderer::kPriorityCutoffAllowEverything;
-#endif
-
- allocation.renderer_allocation.bytes_limit_when_not_visible =
- client_state->bytes_allocation_when_nonvisible_;
- allocation.renderer_allocation.priority_cutoff_when_not_visible =
- GpuMemoryAllocationForRenderer::kPriorityCutoffAllowOnlyRequired;
+ allocation.priority_cutoff_when_visible = priority_cutoff_;
client_state->client_->SetMemoryAllocation(allocation);
+ client_state->client_->SuggestHaveFrontBuffer(!client_state->hibernated_);
}
}
@@ -801,13 +683,13 @@ void GpuMemoryManager::AssignNonSurfacesAllocations() {
it != clients_nonsurface_.end();
++it) {
GpuMemoryManagerClientState* client_state = *it;
- GpuMemoryAllocation allocation;
+ MemoryAllocation allocation;
if (!client_state->hibernated_) {
- allocation.renderer_allocation.bytes_limit_when_visible =
+ allocation.bytes_limit_when_visible =
GetMinimumClientAllocation();
- allocation.renderer_allocation.priority_cutoff_when_visible =
- GpuMemoryAllocationForRenderer::kPriorityCutoffAllowEverything;
+ allocation.priority_cutoff_when_visible =
+ MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
}
client_state->client_->SetMemoryAllocation(allocation);
diff --git a/chromium/content/common/gpu/gpu_memory_manager.h b/chromium/content/common/gpu/gpu_memory_manager.h
index 9b2de82eb88..255c20bd29f 100644
--- a/chromium/content/common/gpu/gpu_memory_manager.h
+++ b/chromium/content/common/gpu/gpu_memory_manager.h
@@ -14,8 +14,8 @@
#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
-#include "content/common/gpu/gpu_memory_allocation.h"
#include "content/public/common/gpu_memory_stats.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "gpu/command_buffer/service/memory_tracking.h"
namespace content {
@@ -62,6 +62,8 @@ class CONTENT_EXPORT GpuMemoryManager :
GpuMemoryTrackingGroup* CreateTrackingGroup(
base::ProcessId pid, gpu::gles2::MemoryTracker* memory_tracker);
+ uint64 GetClientMemoryUsage(const GpuMemoryManagerClient* client) const;
+
private:
friend class GpuMemoryManagerTest;
friend class GpuMemoryTrackingGroup;
@@ -116,7 +118,6 @@ class CONTENT_EXPORT GpuMemoryManager :
// Compute the allocation for clients when visible and not visible.
void ComputeVisibleSurfacesAllocations();
- void ComputeNonvisibleSurfacesAllocations();
void DistributeRemainingMemoryToVisibleSurfaces();
// Compute the budget for a client. Allow at most bytes_above_required_cap
@@ -128,8 +129,6 @@ class CONTENT_EXPORT GpuMemoryManager :
uint64 bytes_above_required_cap,
uint64 bytes_above_minimum_cap,
uint64 bytes_overall_cap);
- uint64 ComputeClientAllocationWhenNonvisible(
- GpuMemoryManagerClientState* client_state);
// Update the amount of GPU memory we think we have in the system, based
// on what the stubs' contexts report.
@@ -182,7 +181,7 @@ class CONTENT_EXPORT GpuMemoryManager :
GpuMemoryManagerClientState* client_state, bool visible);
void SetClientStateManagedMemoryStats(
GpuMemoryManagerClientState* client_state,
- const GpuManagedMemoryStats& stats);
+ const gpu::ManagedMemoryStats& stats);
void OnDestroyClientState(GpuMemoryManagerClientState* client);
// Add or remove a client from its clients list (visible, nonvisible, or
@@ -228,21 +227,19 @@ class CONTENT_EXPORT GpuMemoryManager :
uint64 max_surfaces_with_frontbuffer_soft_limit_;
+ // The priority cutoff used for all renderers.
+ gpu::MemoryAllocation::PriorityCutoff priority_cutoff_;
+
// The maximum amount of memory that may be allocated for GPU resources
uint64 bytes_available_gpu_memory_;
bool bytes_available_gpu_memory_overridden_;
- // Whether or not clients can be allocated memory when nonvisible.
- bool allow_nonvisible_memory_;
-
// The minimum and default allocations for a single client.
uint64 bytes_minimum_per_client_;
uint64 bytes_default_per_client_;
// The current total memory usage, and historical maximum memory usage
uint64 bytes_allocated_managed_current_;
- uint64 bytes_allocated_managed_visible_;
- uint64 bytes_allocated_managed_nonvisible_;
uint64 bytes_allocated_unmanaged_current_;
uint64 bytes_allocated_historical_max_;
diff --git a/chromium/content/common/gpu/gpu_memory_manager_client.cc b/chromium/content/common/gpu/gpu_memory_manager_client.cc
index fb3182cc6f3..a31510a282a 100644
--- a/chromium/content/common/gpu/gpu_memory_manager_client.cc
+++ b/chromium/content/common/gpu/gpu_memory_manager_client.cc
@@ -4,8 +4,6 @@
#include "content/common/gpu/gpu_memory_manager_client.h"
-#if defined(ENABLE_GPU)
-
#include "content/common/gpu/gpu_memory_manager.h"
namespace content {
@@ -26,7 +24,6 @@ GpuMemoryManagerClientState::GpuMemoryManagerClientState(
bytes_nicetohave_limit_low_(0),
bytes_nicetohave_limit_high_(0),
bytes_allocation_when_visible_(0),
- bytes_allocation_when_nonvisible_(0),
bytes_allocation_ideal_nicetohave_(0),
bytes_allocation_ideal_required_(0),
bytes_allocation_ideal_minimum_(0),
@@ -42,10 +39,8 @@ void GpuMemoryManagerClientState::SetVisible(bool visible) {
}
void GpuMemoryManagerClientState::SetManagedMemoryStats(
- const GpuManagedMemoryStats& stats) {
+ const gpu::ManagedMemoryStats& stats) {
memory_manager_->SetClientStateManagedMemoryStats(this, stats);
}
} // namespace content
-
-#endif
diff --git a/chromium/content/common/gpu/gpu_memory_manager_client.h b/chromium/content/common/gpu/gpu_memory_manager_client.h
index ca7c002f291..3a941e25898 100644
--- a/chromium/content/common/gpu/gpu_memory_manager_client.h
+++ b/chromium/content/common/gpu/gpu_memory_manager_client.h
@@ -5,13 +5,11 @@
#ifndef CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_CLIENT_H_
#define CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_CLIENT_H_
-#if defined(ENABLE_GPU)
-
#include <list>
#include "base/basictypes.h"
#include "content/common/content_export.h"
-#include "content/common/gpu/gpu_memory_allocation.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "ui/gfx/size.h"
@@ -34,7 +32,9 @@ class CONTENT_EXPORT GpuMemoryManagerClient {
// Sets buffer usage depending on Memory Allocation
virtual void SetMemoryAllocation(
- const GpuMemoryAllocation& allocation) = 0;
+ const gpu::MemoryAllocation& allocation) = 0;
+
+ virtual void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer) = 0;
// Returns in bytes the total amount of GPU memory for the GPU which this
// context is currently rendering on. Returns false if no extension exists
@@ -48,7 +48,7 @@ class CONTENT_EXPORT GpuMemoryManagerClientState {
public:
~GpuMemoryManagerClientState();
void SetVisible(bool visible);
- void SetManagedMemoryStats(const GpuManagedMemoryStats& stats);
+ void SetManagedMemoryStats(const gpu::ManagedMemoryStats& stats);
private:
friend class GpuMemoryManager;
@@ -82,7 +82,7 @@ class CONTENT_EXPORT GpuMemoryManagerClientState {
bool list_iterator_valid_;
// Statistics about memory usage.
- GpuManagedMemoryStats managed_memory_stats_;
+ gpu::ManagedMemoryStats managed_memory_stats_;
bool managed_memory_stats_received_;
// When managed_memory_stats_.bytes_nicetohave leaves the range
@@ -93,7 +93,6 @@ class CONTENT_EXPORT GpuMemoryManagerClientState {
// The allocation for this client, used transiently during memory policy
// calculation.
uint64 bytes_allocation_when_visible_;
- uint64 bytes_allocation_when_nonvisible_;
// The ideal allocation for this client for three performance levels, used
// transiently during memory policy calculation.
@@ -108,6 +107,4 @@ class CONTENT_EXPORT GpuMemoryManagerClientState {
} // namespace content
-#endif
-
#endif // CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_CLIENT_H_
diff --git a/chromium/content/common/gpu/gpu_memory_manager_unittest.cc b/chromium/content/common/gpu/gpu_memory_manager_unittest.cc
index e008a477772..c735e4f6770 100644
--- a/chromium/content/common/gpu/gpu_memory_manager_unittest.cc
+++ b/chromium/content/common/gpu/gpu_memory_manager_unittest.cc
@@ -2,14 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/common/gpu/gpu_memory_allocation.h"
#include "content/common/gpu/gpu_memory_manager.h"
#include "content/common/gpu/gpu_memory_manager_client.h"
#include "content/common/gpu/gpu_memory_tracking.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "ui/gfx/size_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
+using gpu::MemoryAllocation;
+using gpu::ManagedMemoryStats;
+
#if defined(COMPILER_GCC)
namespace BASE_HASH_NAMESPACE {
template<>
@@ -43,7 +46,7 @@ namespace content {
class ClientAssignmentCollector {
public:
struct ClientMemoryStat {
- GpuMemoryAllocation allocation;
+ MemoryAllocation allocation;
};
typedef base::hash_map<GpuMemoryManagerClient*, ClientMemoryStat>
ClientMemoryStatMap;
@@ -55,7 +58,7 @@ class ClientAssignmentCollector {
client_memory_stats_for_last_manage_.clear();
}
static void AddClientStat(GpuMemoryManagerClient* client,
- const GpuMemoryAllocation& allocation) {
+ const MemoryAllocation& allocation) {
DCHECK(!client_memory_stats_for_last_manage_.count(client));
client_memory_stats_for_last_manage_[client].allocation = allocation;
}
@@ -70,7 +73,8 @@ ClientAssignmentCollector::ClientMemoryStatMap
class FakeClient : public GpuMemoryManagerClient {
public:
GpuMemoryManager* memmgr_;
- GpuMemoryAllocation allocation_;
+ bool suggest_have_frontbuffer_;
+ MemoryAllocation allocation_;
uint64 total_gpu_memory_;
gfx::Size surface_size_;
GpuMemoryManagerClient* share_group_;
@@ -81,6 +85,7 @@ class FakeClient : public GpuMemoryManagerClient {
// This will create a client with no surface
FakeClient(GpuMemoryManager* memmgr, GpuMemoryManagerClient* share_group)
: memmgr_(memmgr),
+ suggest_have_frontbuffer_(false),
total_gpu_memory_(0),
share_group_(share_group),
memory_tracker_(NULL) {
@@ -95,6 +100,7 @@ class FakeClient : public GpuMemoryManagerClient {
// This will create a client with a surface
FakeClient(GpuMemoryManager* memmgr, int32 surface_id, bool visible)
: memmgr_(memmgr),
+ suggest_have_frontbuffer_(false),
total_gpu_memory_(0),
share_group_(NULL),
memory_tracker_(NULL) {
@@ -111,11 +117,15 @@ class FakeClient : public GpuMemoryManagerClient {
memory_tracker_ = NULL;
}
- virtual void SetMemoryAllocation(const GpuMemoryAllocation& alloc) OVERRIDE {
+ virtual void SetMemoryAllocation(const MemoryAllocation& alloc) OVERRIDE {
allocation_ = alloc;
ClientAssignmentCollector::AddClientStat(this, alloc);
}
+ virtual void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer) OVERRIDE {
+ suggest_have_frontbuffer_ = suggest_have_frontbuffer;
+ }
+
virtual bool GetTotalGpuMemory(uint64* bytes) OVERRIDE {
if (total_gpu_memory_) {
*bytes = total_gpu_memory_;
@@ -140,16 +150,12 @@ class FakeClient : public GpuMemoryManagerClient {
client_state_->SetVisible(visible);
}
- void SetManagedMemoryStats(const GpuManagedMemoryStats& stats) {
+ void SetManagedMemoryStats(const ManagedMemoryStats& stats) {
client_state_->SetManagedMemoryStats(stats);
}
uint64 BytesWhenVisible() const {
- return allocation_.renderer_allocation.bytes_limit_when_visible;
- }
-
- uint64 BytesWhenNotVisible() const {
- return allocation_.renderer_allocation.bytes_limit_when_not_visible;
+ return allocation_.bytes_limit_when_visible;
}
};
@@ -160,7 +166,6 @@ class GpuMemoryManagerTest : public testing::Test {
GpuMemoryManagerTest()
: memmgr_(0, kFrontbufferLimitForTest) {
memmgr_.TestingDisableScheduleManage();
- memmgr_.allow_nonvisible_memory_ = true;
}
virtual void SetUp() {
@@ -172,39 +177,30 @@ class GpuMemoryManagerTest : public testing::Test {
}
bool IsAllocationForegroundForSurfaceYes(
- const GpuMemoryAllocation& alloc) {
- return alloc.browser_allocation.suggest_have_frontbuffer &&
- !alloc.renderer_allocation.have_backbuffer_when_not_visible;
+ const MemoryAllocation& alloc) {
+ return true;
}
bool IsAllocationBackgroundForSurfaceYes(
- const GpuMemoryAllocation& alloc) {
- return alloc.browser_allocation.suggest_have_frontbuffer &&
- !alloc.renderer_allocation.have_backbuffer_when_not_visible;
+ const MemoryAllocation& alloc) {
+ return true;
}
bool IsAllocationHibernatedForSurfaceYes(
- const GpuMemoryAllocation& alloc) {
- return !alloc.browser_allocation.suggest_have_frontbuffer &&
- !alloc.renderer_allocation.have_backbuffer_when_not_visible;
+ const MemoryAllocation& alloc) {
+ return true;
}
bool IsAllocationForegroundForSurfaceNo(
- const GpuMemoryAllocation& alloc) {
- return !alloc.browser_allocation.suggest_have_frontbuffer &&
- !alloc.renderer_allocation.have_backbuffer_when_not_visible &&
- alloc.renderer_allocation.bytes_limit_when_visible ==
+ const MemoryAllocation& alloc) {
+ return alloc.bytes_limit_when_visible ==
GetMinimumClientAllocation();
}
bool IsAllocationBackgroundForSurfaceNo(
- const GpuMemoryAllocation& alloc) {
- return !alloc.browser_allocation.suggest_have_frontbuffer &&
- !alloc.renderer_allocation.have_backbuffer_when_not_visible &&
- alloc.renderer_allocation.bytes_limit_when_visible ==
+ const MemoryAllocation& alloc) {
+ return alloc.bytes_limit_when_visible ==
GetMinimumClientAllocation();
}
bool IsAllocationHibernatedForSurfaceNo(
- const GpuMemoryAllocation& alloc) {
- return !alloc.browser_allocation.suggest_have_frontbuffer &&
- !alloc.renderer_allocation.have_backbuffer_when_not_visible &&
- alloc.renderer_allocation.bytes_limit_when_visible == 0;
+ const MemoryAllocation& alloc) {
+ return alloc.bytes_limit_when_visible == 0;
}
void Manage() {
@@ -239,7 +235,7 @@ class GpuMemoryManagerTest : public testing::Test {
uint64 required,
uint64 nicetohave) {
client->SetManagedMemoryStats(
- GpuManagedMemoryStats(required, nicetohave, 0, false));
+ ManagedMemoryStats(required, nicetohave, 0, false));
}
GpuMemoryManager memmgr_;
@@ -474,51 +470,6 @@ TEST_F(GpuMemoryManagerTest, TestUpdateAvailableGpuMemory) {
EXPECT_EQ(GetAvailableGpuMemory(), CalcAvailableClamped(bytes_expected));
}
-
-// Test GpuMemoryAllocation comparison operators: Iterate over all possible
-// combinations of gpu_resource_size_in_bytes, suggest_have_backbuffer, and
-// suggest_have_frontbuffer, and make sure allocations with equal values test
-// equal and non equal values test not equal.
-TEST_F(GpuMemoryManagerTest, GpuMemoryAllocationCompareTests) {
- std::vector<int> gpu_resource_size_in_bytes_values;
- gpu_resource_size_in_bytes_values.push_back(0);
- gpu_resource_size_in_bytes_values.push_back(1);
- gpu_resource_size_in_bytes_values.push_back(12345678);
-
- std::vector<GpuMemoryAllocation::BufferAllocation>
- suggested_buffer_allocation_values;
- suggested_buffer_allocation_values.push_back(
- GpuMemoryAllocation::kHasFrontbuffer);
- suggested_buffer_allocation_values.push_back(
- GpuMemoryAllocation::kHasFrontbuffer);
- suggested_buffer_allocation_values.push_back(
- GpuMemoryAllocation::kHasNoFrontbuffer);
- suggested_buffer_allocation_values.push_back(
- GpuMemoryAllocation::kHasNoFrontbuffer);
-
- for (size_t i = 0; i != gpu_resource_size_in_bytes_values.size(); ++i) {
- for (size_t j = 0; j != suggested_buffer_allocation_values.size(); ++j) {
- uint64 sz = gpu_resource_size_in_bytes_values[i];
- GpuMemoryAllocation::BufferAllocation buffer_allocation =
- suggested_buffer_allocation_values[j];
- GpuMemoryAllocation allocation(sz, buffer_allocation);
-
- EXPECT_TRUE(allocation.Equals(
- GpuMemoryAllocation(sz, buffer_allocation)));
- EXPECT_FALSE(allocation.Equals(
- GpuMemoryAllocation(sz+1, buffer_allocation)));
-
- for (size_t k = 0; k != suggested_buffer_allocation_values.size(); ++k) {
- GpuMemoryAllocation::BufferAllocation buffer_allocation_other =
- suggested_buffer_allocation_values[k];
- if (buffer_allocation == buffer_allocation_other) continue;
- EXPECT_FALSE(allocation.Equals(
- GpuMemoryAllocation(sz, buffer_allocation_other)));
- }
- }
- }
-}
-
// Test GpuMemoryManager Stub Memory Stats functionality:
// Creates various surface/non-surface stubs and switches stub visibility and
// tests to see that stats data structure values are correct.
@@ -533,7 +484,7 @@ TEST_F(GpuMemoryManagerTest, StubMemoryStatsForLastManageTests) {
Manage();
stats = ClientAssignmentCollector::GetClientStatsForLastManage();
uint64 stub1allocation1 =
- stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible;
+ stats[&stub1].allocation.bytes_limit_when_visible;
EXPECT_EQ(stats.size(), 1ul);
EXPECT_GT(stub1allocation1, 0ul);
@@ -543,10 +494,10 @@ TEST_F(GpuMemoryManagerTest, StubMemoryStatsForLastManageTests) {
stats = ClientAssignmentCollector::GetClientStatsForLastManage();
EXPECT_EQ(stats.count(&stub1), 1ul);
uint64 stub1allocation2 =
- stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible;
+ stats[&stub1].allocation.bytes_limit_when_visible;
EXPECT_EQ(stats.count(&stub2), 1ul);
uint64 stub2allocation2 =
- stats[&stub2].allocation.renderer_allocation.bytes_limit_when_visible;
+ stats[&stub2].allocation.bytes_limit_when_visible;
EXPECT_EQ(stats.size(), 2ul);
EXPECT_GT(stub1allocation2, 0ul);
@@ -558,11 +509,11 @@ TEST_F(GpuMemoryManagerTest, StubMemoryStatsForLastManageTests) {
Manage();
stats = ClientAssignmentCollector::GetClientStatsForLastManage();
uint64 stub1allocation3 =
- stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible;
+ stats[&stub1].allocation.bytes_limit_when_visible;
uint64 stub2allocation3 =
- stats[&stub2].allocation.renderer_allocation.bytes_limit_when_visible;
+ stats[&stub2].allocation.bytes_limit_when_visible;
uint64 stub3allocation3 =
- stats[&stub3].allocation.renderer_allocation.bytes_limit_when_visible;
+ stats[&stub3].allocation.bytes_limit_when_visible;
EXPECT_EQ(stats.size(), 3ul);
EXPECT_GT(stub1allocation3, 0ul);
@@ -576,11 +527,11 @@ TEST_F(GpuMemoryManagerTest, StubMemoryStatsForLastManageTests) {
Manage();
stats = ClientAssignmentCollector::GetClientStatsForLastManage();
uint64 stub1allocation4 =
- stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible;
+ stats[&stub1].allocation.bytes_limit_when_visible;
uint64 stub2allocation4 =
- stats[&stub2].allocation.renderer_allocation.bytes_limit_when_visible;
+ stats[&stub2].allocation.bytes_limit_when_visible;
uint64 stub3allocation4 =
- stats[&stub3].allocation.renderer_allocation.bytes_limit_when_visible;
+ stats[&stub3].allocation.bytes_limit_when_visible;
EXPECT_EQ(stats.size(), 3ul);
EXPECT_GT(stub1allocation4, 0ul);
@@ -590,201 +541,6 @@ TEST_F(GpuMemoryManagerTest, StubMemoryStatsForLastManageTests) {
EXPECT_GT(stub3allocation4, stub3allocation3);
}
-// Test GpuMemoryManager's managed memory tracking
-TEST_F(GpuMemoryManagerTest, TestManagedUsageTracking) {
- FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
- stub2(&memmgr_, GenerateUniqueSurfaceId(), false);
- EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_nonvisible_);
-
- // Set memory allocations and verify the results are reflected.
- stub1.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 5, false));
- stub2.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 7, false));
- EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_);
-
- // Remove a visible client
- stub1.client_state_.reset();
- EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_);
- EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_);
- stub1.client_state_.reset(memmgr_.CreateClientState(&stub1, true, true));
- EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_);
- stub1.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 5, false));
- EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_);
-
- // Remove a nonvisible client
- stub2.client_state_.reset();
- EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_nonvisible_);
- EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_nonvisible_);
- stub2.client_state_.reset(memmgr_.CreateClientState(&stub2, true, false));
- EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_nonvisible_);
- stub2.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 7, false));
- EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_);
-
- // Create and then destroy some stubs, and verify their allocations go away.
- {
- FakeClient stub3(&memmgr_, GenerateUniqueSurfaceId(), true),
- stub4(&memmgr_, GenerateUniqueSurfaceId(), false);
- stub3.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 1, false));
- stub4.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 2, false));
- EXPECT_EQ(6ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(9ul, memmgr_.bytes_allocated_managed_nonvisible_);
- }
- EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_);
-
- // Do no-op changes to stubs' visibility and make sure nothing chnages.
- stub1.SetVisible(true);
- stub2.SetVisible(false);
- EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_);
-
- // Change visbility state.
- stub1.SetVisible(false);
- stub2.SetVisible(true);
- EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_nonvisible_);
-
- // Increase allocation amounts.
- stub1.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 6, false));
- stub2.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 8, false));
- EXPECT_EQ(8ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(6ul, memmgr_.bytes_allocated_managed_nonvisible_);
-
- // Decrease allocation amounts.
- stub1.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 4, false));
- stub2.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 6, false));
- EXPECT_EQ(6ul, memmgr_.bytes_allocated_managed_visible_);
- EXPECT_EQ(4ul, memmgr_.bytes_allocated_managed_nonvisible_);
-}
-
-// Test nonvisible MRU behavior (the most recently used nonvisible clients
-// keep their contents).
-TEST_F(GpuMemoryManagerTest, BackgroundMru) {
- // Set memory manager constants for this test. Note that the budget
- // for backgrounded content will be 64/4 = 16.
- memmgr_.TestingSetAvailableGpuMemory(64);
- memmgr_.TestingSetMinimumClientAllocation(8);
-
- uint64 bytes_when_not_visible_expected = 6u;
-
- FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true);
- FakeClient stub2(&memmgr_, GenerateUniqueSurfaceId(), true);
- FakeClient stub3(&memmgr_, GenerateUniqueSurfaceId(), true);
-
- // When all are visible, they should all be allowed to have memory
- // should they become nonvisible.
- SetClientStats(&stub1, 6, 23);
- SetClientStats(&stub2, 6, 23);
- SetClientStats(&stub3, 6, 23);
- Manage();
- EXPECT_GE(stub1.BytesWhenVisible(), 20u);
- EXPECT_GE(stub2.BytesWhenVisible(), 20u);
- EXPECT_GE(stub3.BytesWhenVisible(), 20u);
- EXPECT_LT(stub1.BytesWhenVisible(), 22u);
- EXPECT_LT(stub2.BytesWhenVisible(), 22u);
- EXPECT_LT(stub3.BytesWhenVisible(), 22u);
- EXPECT_GE(stub1.BytesWhenNotVisible(), bytes_when_not_visible_expected);
- EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected);
- EXPECT_GE(stub3.BytesWhenNotVisible(), bytes_when_not_visible_expected);
-
- // Background stubs 1 and 2, and they should fit. All stubs should
- // have their full nicetohave budget should they become visible.
- stub2.SetVisible(false);
- stub1.SetVisible(false);
- Manage();
- EXPECT_GE(stub1.BytesWhenVisible(), 23u);
- EXPECT_GE(stub2.BytesWhenVisible(), 23u);
- EXPECT_GE(stub3.BytesWhenVisible(), 23u);
- EXPECT_LT(stub1.BytesWhenVisible(), 32u);
- EXPECT_LT(stub2.BytesWhenVisible(), 32u);
- EXPECT_GE(stub1.BytesWhenNotVisible(), bytes_when_not_visible_expected);
- EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected);
- EXPECT_GE(stub3.BytesWhenNotVisible(), bytes_when_not_visible_expected);
-
- // Now background stub 3, and it should cause stub 2 to be
- // evicted because it was set non-visible first
- stub3.SetVisible(false);
- Manage();
- EXPECT_GE(stub1.BytesWhenNotVisible(), bytes_when_not_visible_expected);
- EXPECT_EQ(stub2.BytesWhenNotVisible(), 0u);
- EXPECT_GE(stub3.BytesWhenNotVisible(), bytes_when_not_visible_expected);
-}
-
-TEST_F(GpuMemoryManagerTest, AllowNonvisibleMemory) {
- memmgr_.TestingSetAvailableGpuMemory(512);
- memmgr_.TestingSetMinimumClientAllocation(16);
-
- FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true);
- FakeClient stub2(&memmgr_, GenerateUniqueSurfaceId(), true);
- FakeClient stub3(&memmgr_, GenerateUniqueSurfaceId(), true);
-
- memmgr_.allow_nonvisible_memory_ = true;
- stub1.SetVisible(true);
- SetClientStats(&stub1, 20, 80);
- SetClientStats(&stub2, 20, 80);
- SetClientStats(&stub3, 20, 80);
- Manage();
- EXPECT_GT(stub1.BytesWhenNotVisible(), 0u);
- EXPECT_GT(stub2.BytesWhenNotVisible(), 0u);
- EXPECT_GT(stub3.BytesWhenNotVisible(), 0u);
-
- memmgr_.allow_nonvisible_memory_ = false;
- Manage();
- EXPECT_EQ(stub1.BytesWhenNotVisible(), 0u);
- EXPECT_EQ(stub2.BytesWhenNotVisible(), 0u);
- EXPECT_EQ(stub3.BytesWhenNotVisible(), 0u);
-}
-
-// Test that once a backgrounded client has dropped its resources, it
-// doesn't get them back until it becomes visible again.
-TEST_F(GpuMemoryManagerTest, BackgroundDiscardPersistent) {
- // Set memory manager constants for this test. Note that the budget
- // for backgrounded content will be 64/4 = 16.
- memmgr_.TestingSetAvailableGpuMemory(64);
- memmgr_.TestingSetMinimumClientAllocation(8);
-
- uint64 bytes_when_not_visible_expected = 10ul;
- if (!memmgr_.allow_nonvisible_memory_)
- bytes_when_not_visible_expected = 0;
-
- FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true);
- FakeClient stub2(&memmgr_, GenerateUniqueSurfaceId(), true);
-
- // Both clients should be able to keep their contents should one of
- // them become nonvisible.
- SetClientStats(&stub1, 10, 20);
- SetClientStats(&stub2, 10, 20);
- Manage();
- EXPECT_GE(stub1.BytesWhenNotVisible(), bytes_when_not_visible_expected);
- EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected);
-
- // If they both go nonvisible, then only the most recently used client
- // should keep its contents.
- stub1.SetVisible(false);
- stub2.SetVisible(false);
- Manage();
- EXPECT_EQ(stub1.BytesWhenNotVisible(), 0u);
- EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected);
-
- // When becoming visible, stub 2 should get its contents back, and
- // retain them next time it is made nonvisible.
- stub2.SetVisible(true);
- Manage();
- EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected);
- stub2.SetVisible(false);
- Manage();
- EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected);
-}
-
// Test tracking of unmanaged (e.g, WebGL) memory.
TEST_F(GpuMemoryManagerTest, UnmanagedTracking) {
// Set memory manager constants for this test
@@ -851,7 +607,6 @@ TEST_F(GpuMemoryManagerTest, DefaultAllocation) {
Manage();
EXPECT_GE(stub1.BytesWhenVisible(),
memmgr_.GetDefaultClientAllocation());
- EXPECT_EQ(stub1.BytesWhenNotVisible(), 0u);
}
} // namespace content
diff --git a/chromium/content/common/gpu/gpu_messages.h b/chromium/content/common/gpu/gpu_messages.h
index 3952d796dab..084b2d80676 100644
--- a/chromium/content/common/gpu/gpu_messages.h
+++ b/chromium/content/common/gpu/gpu_messages.h
@@ -10,15 +10,15 @@
#include "base/memory/shared_memory.h"
#include "content/common/content_export.h"
-#include "content/common/gpu/gpu_memory_allocation.h"
#include "content/common/gpu/gpu_memory_uma_stats.h"
#include "content/common/gpu/gpu_process_launch_causes.h"
#include "content/common/gpu/gpu_rendering_stats.h"
-#include "content/common/gpu/surface_capturer.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/gpu_memory_stats.h"
+#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/config/gpu_info.h"
#include "gpu/ipc/gpu_command_buffer_traits.h"
@@ -28,6 +28,7 @@
#include "media/video/video_decode_accelerator.h"
#include "media/video/video_encode_accelerator.h"
#include "ui/events/latency_info.h"
+#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
#include "ui/gl/gpu_preference.h"
@@ -75,7 +76,6 @@ IPC_STRUCT_END()
IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceRelease_Params)
IPC_STRUCT_MEMBER(int32, surface_id)
- IPC_STRUCT_MEMBER(int32, route_id)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(AcceleratedSurfaceMsg_BufferPresented_Params)
@@ -169,6 +169,20 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::GPUInfo)
#endif
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities)
+ IPC_STRUCT_TRAITS_MEMBER(post_sub_buffer)
+ IPC_STRUCT_TRAITS_MEMBER(fast_npot_mo8_textures)
+ IPC_STRUCT_TRAITS_MEMBER(egl_image_external)
+ IPC_STRUCT_TRAITS_MEMBER(texture_format_bgra8888)
+ IPC_STRUCT_TRAITS_MEMBER(texture_format_etc1)
+ IPC_STRUCT_TRAITS_MEMBER(texture_rectangle)
+ IPC_STRUCT_TRAITS_MEMBER(iosurface)
+ IPC_STRUCT_TRAITS_MEMBER(texture_usage)
+ IPC_STRUCT_TRAITS_MEMBER(texture_storage)
+ IPC_STRUCT_TRAITS_MEMBER(discard_framebuffer)
+ IPC_STRUCT_TRAITS_MEMBER(map_image)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::GPUVideoMemoryUsageStats::ProcessStats)
IPC_STRUCT_TRAITS_MEMBER(video_memory)
IPC_STRUCT_TRAITS_MEMBER(has_duplicates)
@@ -186,16 +200,13 @@ IPC_STRUCT_TRAITS_BEGIN(content::GPUMemoryUmaStats)
IPC_STRUCT_TRAITS_MEMBER(bytes_limit)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(content::GpuMemoryAllocationForRenderer)
+IPC_STRUCT_TRAITS_BEGIN(gpu::MemoryAllocation)
IPC_STRUCT_TRAITS_MEMBER(bytes_limit_when_visible)
IPC_STRUCT_TRAITS_MEMBER(priority_cutoff_when_visible)
- IPC_STRUCT_TRAITS_MEMBER(bytes_limit_when_not_visible)
- IPC_STRUCT_TRAITS_MEMBER(priority_cutoff_when_not_visible)
- IPC_STRUCT_TRAITS_MEMBER(have_backbuffer_when_not_visible)
IPC_STRUCT_TRAITS_END()
-IPC_ENUM_TRAITS(content::GpuMemoryAllocationForRenderer::PriorityCutoff)
+IPC_ENUM_TRAITS(gpu::MemoryAllocation::PriorityCutoff)
-IPC_STRUCT_TRAITS_BEGIN(content::GpuManagedMemoryStats)
+IPC_STRUCT_TRAITS_BEGIN(gpu::ManagedMemoryStats)
IPC_STRUCT_TRAITS_MEMBER(bytes_required)
IPC_STRUCT_TRAITS_MEMBER(bytes_nice_to_have)
IPC_STRUCT_TRAITS_MEMBER(bytes_allocated)
@@ -223,14 +234,13 @@ IPC_STRUCT_TRAITS_BEGIN(content::GpuRenderingStats)
IPC_STRUCT_TRAITS_MEMBER(total_texture_upload_time)
IPC_STRUCT_TRAITS_MEMBER(global_total_processing_commands_time)
IPC_STRUCT_TRAITS_MEMBER(total_processing_commands_time)
+ IPC_STRUCT_TRAITS_MEMBER(global_video_memory_bytes_allocated)
IPC_STRUCT_TRAITS_END()
IPC_ENUM_TRAITS(media::VideoFrame::Format)
IPC_ENUM_TRAITS(media::VideoEncodeAccelerator::Error)
-IPC_ENUM_TRAITS(content::SurfaceCapturer::Error)
-
//------------------------------------------------------------------------------
// GPU Messages
// These are messages from the browser to the GPU process.
@@ -295,6 +305,9 @@ IPC_MESSAGE_ROUTED0(AcceleratedSurfaceMsg_ResizeViewACK)
IPC_MESSAGE_ROUTED1(AcceleratedSurfaceMsg_BufferPresented,
AcceleratedSurfaceMsg_BufferPresented_Params)
+// Tells the GPU process to wake up the GPU because we're about to draw.
+IPC_MESSAGE_ROUTED0(AcceleratedSurfaceMsg_WakeUpGpu)
+
// Tells the GPU process to remove all contexts.
IPC_MESSAGE_CONTROL0(GpuMsg_Clean)
@@ -384,6 +397,11 @@ IPC_MESSAGE_CONTROL3(GpuHostMsg_ResizeView,
int32 /* route_id */,
gfx::Size /* size */)
+// Tells the browser that a new accelerated surface was initialized.
+IPC_MESSAGE_CONTROL2(GpuHostMsg_AcceleratedSurfaceInitialized,
+ int32 /* surface_id */,
+ int32 /* route_id */)
+
// Tells the browser that a frame with the specific latency info was drawn to
// the screen
IPC_MESSAGE_CONTROL1(GpuHostMsg_FrameDrawn,
@@ -493,6 +511,14 @@ IPC_SYNC_MESSAGE_CONTROL1_1(GpuChannelMsg_CollectRenderingStatsForSurface,
int32 /* surface_id */,
content::GpuRenderingStats /* stats */)
+// Sent by DevTools agent in the inspected renderer process to initiate GPU
+// instrumentation events recording.
+IPC_SYNC_MESSAGE_CONTROL0_1(GpuChannelMsg_DevToolsStartEventsRecording,
+ int32 /* route_id */)
+
+// The message is sent when DevTools want to stop events recording.
+IPC_MESSAGE_CONTROL0(GpuChannelMsg_DevToolsStopEventsRecording)
+
#if defined(OS_ANDROID)
//------------------------------------------------------------------------------
// Stream Texture Messages
@@ -511,9 +537,10 @@ IPC_MESSAGE_ROUTED1(GpuStreamTextureMsg_MatrixChanged,
// Initialize a command buffer with the given number of command entries.
// Returns the shared memory handle for the command buffer mapped to the
// calling process.
-IPC_SYNC_MESSAGE_ROUTED1_1(GpuCommandBufferMsg_Initialize,
+IPC_SYNC_MESSAGE_ROUTED1_2(GpuCommandBufferMsg_Initialize,
base::SharedMemoryHandle /* shared_state */,
- bool /* result */)
+ bool /* result */,
+ gpu::Capabilities /* capabilities */)
// Sets the shared memory buffer used for commands.
IPC_SYNC_MESSAGE_ROUTED1_0(GpuCommandBufferMsg_SetGetBuffer,
@@ -554,7 +581,7 @@ IPC_MESSAGE_ROUTED0(GpuCommandBufferMsg_Rescheduled)
IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_ConsoleMsg,
GPUCommandBufferConsoleMessage /* msg */)
-// Register an existing shared memory transfer buffer. Returns an id that can be
+// Register an existing shared memory transfer buffer. The id that can be
// used to identify the transfer buffer from a command buffer.
IPC_MESSAGE_ROUTED3(GpuCommandBufferMsg_RegisterTransferBuffer,
int32 /* id */,
@@ -579,12 +606,6 @@ IPC_SYNC_MESSAGE_ROUTED1_1(GpuCommandBufferMsg_CreateVideoDecoder,
media::VideoCodecProfile /* profile */,
int /* route_id */)
-// Create and initialize a surface capturer, returning its new route_id.
-// Created capturers should be freed with SurfaceCapturerMsg_Destroy when no
-// longer needed.
-IPC_SYNC_MESSAGE_ROUTED0_1(GpuCommandBufferMsg_CreateSurfaceCapturer,
- int /* route_id */)
-
// Tells the proxy that there was an error and the command buffer had to be
// destroyed for some reason.
IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_Destroyed,
@@ -601,18 +622,14 @@ IPC_MESSAGE_ROUTED0(GpuCommandBufferMsg_EchoAck)
// Send to stub on surface visibility change.
IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_SetSurfaceVisible, bool /* visible */)
-IPC_MESSAGE_ROUTED0(GpuCommandBufferMsg_DiscardBackbuffer)
-IPC_MESSAGE_ROUTED0(GpuCommandBufferMsg_EnsureBackbuffer)
-
// Sent to proxy when the gpu memory manager changes its memory allocation.
IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_SetMemoryAllocation,
- content::GpuMemoryAllocationForRenderer /* allocation */)
+ gpu::MemoryAllocation /* allocation */)
// Sent to stub from the proxy with statistics on managed memory usage and
// requirements.
-IPC_MESSAGE_ROUTED1(
- GpuCommandBufferMsg_SendClientManagedMemoryStats,
- content::GpuManagedMemoryStats /* stats */)
+IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_SendClientManagedMemoryStats,
+ gpu::ManagedMemoryStats /* stats */)
// Sent to stub when proxy is assigned a memory allocation changed callback.
IPC_MESSAGE_ROUTED1(
@@ -649,6 +666,19 @@ IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_SignalQuery,
uint32 /* query */,
uint32 /* signal_id */)
+// Register an existing gpu memory buffer. The id that can be
+// used to identify the gpu memory buffer from a command buffer.
+IPC_MESSAGE_ROUTED5(GpuCommandBufferMsg_RegisterGpuMemoryBuffer,
+ int32 /* id */,
+ gfx::GpuMemoryBufferHandle /* gpu_memory_buffer */,
+ uint32 /* width */,
+ uint32 /* height */,
+ uint32 /* internalformat */)
+
+// Destroy a previously created gpu memory buffer.
+IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_DestroyGpuMemoryBuffer,
+ int32 /* id */)
+
//------------------------------------------------------------------------------
// Accelerated Video Decoder Messages
// These messages are sent from Renderer process to GPU process.
@@ -661,10 +691,9 @@ IPC_MESSAGE_ROUTED3(AcceleratedVideoDecoderMsg_Decode,
// Sent from Renderer process to the GPU process to give the texture IDs for
// the textures the decoder will use for output.
-IPC_MESSAGE_ROUTED3(AcceleratedVideoDecoderMsg_AssignPictureBuffers,
- std::vector<int32>, /* Picture buffer ID */
- std::vector<uint32>, /* Texture ID */
- std::vector<gfx::Size>) /* Size */
+IPC_MESSAGE_ROUTED2(AcceleratedVideoDecoderMsg_AssignPictureBuffers,
+ std::vector<int32>, /* Picture buffer ID */
+ std::vector<uint32>) /* Texture ID */
// Send from Renderer process to the GPU process to recycle the given picture
// buffer for further decoding.
@@ -777,40 +806,3 @@ IPC_MESSAGE_ROUTED3(AcceleratedVideoEncoderHostMsg_BitstreamBufferReady,
// Report error condition.
IPC_MESSAGE_ROUTED1(AcceleratedVideoEncoderHostMsg_NotifyError,
media::VideoEncodeAccelerator::Error /* error */)
-
-//------------------------------------------------------------------------------
-// Gpu Surface Capturer Messages
-// These messages are sent from the Browser process to the GPU process.
-
-// Initialize the capturer.
-IPC_MESSAGE_ROUTED1(SurfaceCapturerMsg_Initialize,
- media::VideoFrame::Format /* format */)
-
-// Attempt to start a capture.
-IPC_MESSAGE_ROUTED0(SurfaceCapturerMsg_TryCapture)
-
-// Copy captured contents to a video frame.
-IPC_MESSAGE_ROUTED3(SurfaceCapturerMsg_CopyCaptureToVideoFrame,
- int32 /* buffer_id */,
- base::SharedMemoryHandle /* buffer_shm */,
- uint32 /* buffer_size */)
-
-// Destroy the capturer.
-IPC_MESSAGE_ROUTED0(SurfaceCapturerMsg_Destroy)
-
-//------------------------------------------------------------------------------
-// Gpu Surface Capturer Host Messages
-// These messages are sent from GPU process to Browser process.
-
-// Report the capture output parameters to the Browser process.
-IPC_MESSAGE_ROUTED2(SurfaceCapturerHostMsg_NotifyCaptureParameters,
- gfx::Size /* buffer_size */,
- gfx::Rect /* visible_rect */)
-
-// Report successful copy of a capture of a surface.
-IPC_MESSAGE_ROUTED1(SurfaceCapturerHostMsg_NotifyCopyCaptureDone,
- int32 /* frame_id */)
-
-// Report error.
-IPC_MESSAGE_ROUTED1(SurfaceCapturerHostMsg_NotifyError,
- content::SurfaceCapturer::Error /* error */)
diff --git a/chromium/content/common/gpu/gpu_rendering_stats.cc b/chromium/content/common/gpu/gpu_rendering_stats.cc
index 97a24350f08..88e54f08f6e 100644
--- a/chromium/content/common/gpu/gpu_rendering_stats.cc
+++ b/chromium/content/common/gpu/gpu_rendering_stats.cc
@@ -8,7 +8,8 @@ namespace content {
GpuRenderingStats::GpuRenderingStats()
: global_texture_upload_count(0),
- texture_upload_count(0) {
+ texture_upload_count(0),
+ global_video_memory_bytes_allocated(0) {
}
GpuRenderingStats::~GpuRenderingStats() {
@@ -27,6 +28,8 @@ void GpuRenderingStats::EnumerateFields(
global_total_processing_commands_time);
enumerator->AddTimeDeltaInSecondsF("totalProcessingCommandsTimeInSeconds",
total_processing_commands_time);
+ enumerator->AddInt64("globalVideoMemoryBytesAllocated",
+ global_video_memory_bytes_allocated);
}
} // namespace content
diff --git a/chromium/content/common/gpu/gpu_rendering_stats.h b/chromium/content/common/gpu/gpu_rendering_stats.h
index f91e8810eff..ab248537201 100644
--- a/chromium/content/common/gpu/gpu_rendering_stats.h
+++ b/chromium/content/common/gpu/gpu_rendering_stats.h
@@ -21,6 +21,7 @@ struct CONTENT_EXPORT GpuRenderingStats {
base::TimeDelta total_texture_upload_time;
base::TimeDelta global_total_processing_commands_time;
base::TimeDelta total_processing_commands_time;
+ int64 global_video_memory_bytes_allocated;
// Note: when adding new members, please remember to update enumerateFields
// in gpu_rendering_stats.cc.
diff --git a/chromium/content/common/gpu/image_transport_surface.cc b/chromium/content/common/gpu/image_transport_surface.cc
index d1cb0a88469..4ce6f402031 100644
--- a/chromium/content/common/gpu/image_transport_surface.cc
+++ b/chromium/content/common/gpu/image_transport_surface.cc
@@ -12,11 +12,12 @@
#include "content/common/gpu/gpu_channel_manager.h"
#include "content/common/gpu/gpu_command_buffer_stub.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/sync_point_manager.h"
#include "content/common/gpu/texture_image_transport_surface.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
+#include "ui/gfx/vsync_provider.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_switches.h"
-#include "ui/gl/vsync_provider.h"
namespace content {
@@ -72,6 +73,9 @@ bool ImageTransportHelper::Initialize() {
base::Bind(&ImageTransportHelper::SetLatencyInfo,
base::Unretained(this)));
+ manager_->Send(new GpuHostMsg_AcceleratedSurfaceInitialized(
+ stub_->surface_id(), route_id_));
+
return true;
}
@@ -83,6 +87,7 @@ bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented,
OnBufferPresented)
IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_ResizeViewACK, OnResizeViewACK);
+ IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_WakeUpGpu, OnWakeUpGpu);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -107,10 +112,9 @@ void ImageTransportHelper::SendAcceleratedSurfacePostSubBuffer(
manager_->Send(new GpuHostMsg_AcceleratedSurfacePostSubBuffer(params));
}
-void ImageTransportHelper::SendAcceleratedSurfaceRelease(
- GpuHostMsg_AcceleratedSurfaceRelease_Params params) {
+void ImageTransportHelper::SendAcceleratedSurfaceRelease() {
+ GpuHostMsg_AcceleratedSurfaceRelease_Params params;
params.surface_id = stub_->surface_id();
- params.route_id = route_id_;
manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params));
}
@@ -191,6 +195,10 @@ void ImageTransportHelper::OnResizeViewACK() {
surface_->OnResizeViewACK();
}
+void ImageTransportHelper::OnWakeUpGpu() {
+ surface_->WakeUpGpu();
+}
+
void ImageTransportHelper::Resize(gfx::Size size, float scale_factor) {
surface_->OnResize(size, scale_factor);
@@ -251,7 +259,8 @@ bool PassThroughImageTransportSurface::SwapBuffers() {
// crbug.com/223558.
SendVSyncUpdateIfAvailable();
bool result = gfx::GLSurfaceAdapter::SwapBuffers();
- latency_info_.swap_timestamp = base::TimeTicks::HighResNow();
+ latency_info_.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
if (transport_) {
DCHECK(!is_swap_buffers_pending_);
@@ -274,7 +283,8 @@ bool PassThroughImageTransportSurface::PostSubBuffer(
int x, int y, int width, int height) {
SendVSyncUpdateIfAvailable();
bool result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
- latency_info_.swap_timestamp = base::TimeTicks::HighResNow();
+ latency_info_.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
if (transport_) {
DCHECK(!is_swap_buffers_pending_);
@@ -344,6 +354,10 @@ gfx::Size PassThroughImageTransportSurface::GetSize() {
return GLSurfaceAdapter::GetSize();
}
+void PassThroughImageTransportSurface::WakeUpGpu() {
+ NOTIMPLEMENTED();
+}
+
PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
diff --git a/chromium/content/common/gpu/image_transport_surface.h b/chromium/content/common/gpu/image_transport_surface.h
index 9a7889fb6fa..0bad48c4af9 100644
--- a/chromium/content/common/gpu/image_transport_surface.h
+++ b/chromium/content/common/gpu/image_transport_surface.h
@@ -24,7 +24,6 @@
struct AcceleratedSurfaceMsg_BufferPresented_Params;
struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
struct GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params;
-struct GpuHostMsg_AcceleratedSurfaceRelease_Params;
namespace gfx {
class GLSurface;
@@ -65,6 +64,7 @@ class ImageTransportSurface {
virtual void OnResize(gfx::Size size, float scale_factor) = 0;
virtual void SetLatencyInfo(
const ui::LatencyInfo& latency_info) = 0;
+ virtual void WakeUpGpu() = 0;
// Creates a surface with the given attributes.
static scoped_refptr<gfx::GLSurface> CreateSurface(
@@ -120,8 +120,7 @@ class ImageTransportHelper
GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params);
void SendAcceleratedSurfacePostSubBuffer(
GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params);
- void SendAcceleratedSurfaceRelease(
- GpuHostMsg_AcceleratedSurfaceRelease_Params params);
+ void SendAcceleratedSurfaceRelease();
void SendResizeView(const gfx::Size& size);
void SendUpdateVSyncParameters(
base::TimeTicks timebase, base::TimeDelta interval);
@@ -155,6 +154,7 @@ class ImageTransportHelper
void OnBufferPresented(
const AcceleratedSurfaceMsg_BufferPresented_Params& params);
void OnResizeViewACK();
+ void OnWakeUpGpu();
// Backbuffer resize callback.
void Resize(gfx::Size size, float scale_factor);
@@ -199,6 +199,7 @@ class PassThroughImageTransportSurface
virtual gfx::Size GetSize() OVERRIDE;
virtual void SetLatencyInfo(
const ui::LatencyInfo& latency_info) OVERRIDE;
+ virtual void WakeUpGpu() OVERRIDE;
protected:
virtual ~PassThroughImageTransportSurface();
@@ -207,6 +208,8 @@ class PassThroughImageTransportSurface
// the browser.
virtual void SendVSyncUpdateIfAvailable();
+ ImageTransportHelper* GetHelper() { return helper_.get(); }
+
private:
scoped_ptr<ImageTransportHelper> helper_;
gfx::Size new_size_;
diff --git a/chromium/content/common/gpu/image_transport_surface_android.cc b/chromium/content/common/gpu/image_transport_surface_android.cc
index 5ba2d17c2a8..5f45469d306 100644
--- a/chromium/content/common/gpu/image_transport_surface_android.cc
+++ b/chromium/content/common/gpu/image_transport_surface_android.cc
@@ -4,18 +4,196 @@
#include "content/common/gpu/image_transport_surface.h"
+#include "base/command_line.h"
#include "base/logging.h"
+#include "content/common/gpu/gpu_channel.h"
+#include "content/common/gpu/gpu_channel_manager.h"
#include "content/common/gpu/gpu_command_buffer_stub.h"
#include "content/common/gpu/gpu_surface_lookup.h"
+#include "content/common/gpu/image_transport_surface.h"
+#include "content/public/common/content_switches.h"
#include "ui/gl/gl_surface_egl.h"
namespace content {
+namespace {
+
+// Amount of time the GPU is allowed to idle before it powers down.
+const int kMaxGpuIdleTimeMs = 40;
+// Maximum amount of time we keep pinging the GPU waiting for the client to
+// draw.
+const int kMaxKeepAliveTimeMs = 200;
+// Last time we know the GPU was powered on. Global for tracking across all
+// transport surfaces.
+int64 g_last_gpu_access_ticks;
+
+void DidAccessGpu() {
+ g_last_gpu_access_ticks = base::TimeTicks::Now().ToInternalValue();
+}
+
+class ImageTransportSurfaceAndroid
+ : public PassThroughImageTransportSurface,
+ public base::SupportsWeakPtr<ImageTransportSurfaceAndroid> {
+ public:
+ ImageTransportSurfaceAndroid(GpuChannelManager* manager,
+ GpuCommandBufferStub* stub,
+ gfx::GLSurface* surface,
+ uint32 parent_client_id);
+
+ // gfx::GLSurface implementation.
+ virtual bool Initialize() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual std::string GetExtensions() OVERRIDE;
+ virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
+ virtual void SetFrontbufferAllocation(bool allocated) OVERRIDE;
+ virtual void WakeUpGpu() OVERRIDE;
+
+ protected:
+ virtual ~ImageTransportSurfaceAndroid();
+
+ private:
+ void ScheduleWakeUp();
+ void DoWakeUpGpu();
+
+ uint32 parent_client_id_;
+ bool frontbuffer_suggested_allocation_;
+ base::TimeTicks begin_wake_up_time_;
+};
+
+class DirectSurfaceAndroid : public PassThroughImageTransportSurface {
+ public:
+ DirectSurfaceAndroid(GpuChannelManager* manager,
+ GpuCommandBufferStub* stub,
+ gfx::GLSurface* surface,
+ bool transport);
+
+ // gfx::GLSurface implementation.
+ virtual bool SwapBuffers() OVERRIDE;
+
+ protected:
+ virtual ~DirectSurfaceAndroid();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DirectSurfaceAndroid);
+};
+
+ImageTransportSurfaceAndroid::ImageTransportSurfaceAndroid(
+ GpuChannelManager* manager,
+ GpuCommandBufferStub* stub,
+ gfx::GLSurface* surface,
+ uint32 parent_client_id)
+ : PassThroughImageTransportSurface(manager, stub, surface, true),
+ parent_client_id_(parent_client_id),
+ frontbuffer_suggested_allocation_(true) {}
+
+ImageTransportSurfaceAndroid::~ImageTransportSurfaceAndroid() {}
+
+bool ImageTransportSurfaceAndroid::Initialize() {
+ if (!surface())
+ return false;
+
+ if (!PassThroughImageTransportSurface::Initialize())
+ return false;
+
+ GpuChannel* parent_channel =
+ GetHelper()->manager()->LookupChannel(parent_client_id_);
+ if (parent_channel) {
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess))
+ GetHelper()->SetPreemptByFlag(parent_channel->GetPreemptionFlag());
+ }
+
+ return true;
+}
+
+std::string ImageTransportSurfaceAndroid::GetExtensions() {
+ std::string extensions = gfx::GLSurface::GetExtensions();
+ extensions += extensions.empty() ? "" : " ";
+ extensions += "GL_CHROMIUM_front_buffer_cached ";
+ return extensions;
+}
+
+void ImageTransportSurfaceAndroid::SetFrontbufferAllocation(bool allocation) {
+ if (frontbuffer_suggested_allocation_ == allocation)
+ return;
+ frontbuffer_suggested_allocation_ = allocation;
+ // TODO(sievers): This races with CompositorFrame messages.
+ if (!allocation)
+ GetHelper()->SendAcceleratedSurfaceRelease();
+}
+
+bool ImageTransportSurfaceAndroid::OnMakeCurrent(gfx::GLContext* context) {
+ DidAccessGpu();
+ return PassThroughImageTransportSurface::OnMakeCurrent(context);
+}
+
+bool ImageTransportSurfaceAndroid::SwapBuffers() {
+ NOTREACHED();
+ return false;
+}
+
+void ImageTransportSurfaceAndroid::WakeUpGpu() {
+ begin_wake_up_time_ = base::TimeTicks::Now();
+ ScheduleWakeUp();
+}
+
+void ImageTransportSurfaceAndroid::ScheduleWakeUp() {
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks last_access_time =
+ base::TimeTicks::FromInternalValue(g_last_gpu_access_ticks);
+ TRACE_EVENT2("gpu", "ImageTransportSurfaceAndroid::ScheduleWakeUp",
+ "idle_time", (now - last_access_time).InMilliseconds(),
+ "keep_awake_time", (now - begin_wake_up_time_).InMilliseconds());
+ if (now - last_access_time <
+ base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs))
+ return;
+ if (now - begin_wake_up_time_ >
+ base::TimeDelta::FromMilliseconds(kMaxKeepAliveTimeMs))
+ return;
+
+ DoWakeUpGpu();
+
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&ImageTransportSurfaceAndroid::ScheduleWakeUp, AsWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs));
+}
+
+void ImageTransportSurfaceAndroid::DoWakeUpGpu() {
+ if (!GetHelper()->stub()->decoder() ||
+ !GetHelper()->stub()->decoder()->MakeCurrent())
+ return;
+ glFinish();
+ DidAccessGpu();
+}
+
+DirectSurfaceAndroid::DirectSurfaceAndroid(GpuChannelManager* manager,
+ GpuCommandBufferStub* stub,
+ gfx::GLSurface* surface,
+ bool transport)
+ : PassThroughImageTransportSurface(manager, stub, surface, transport) {}
+
+DirectSurfaceAndroid::~DirectSurfaceAndroid() {}
+
+bool DirectSurfaceAndroid::SwapBuffers() {
+ DidAccessGpu();
+ return PassThroughImageTransportSurface::SwapBuffers();
+}
+
+} // anonymous namespace
// static
scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
GpuChannelManager* manager,
GpuCommandBufferStub* stub,
const gfx::GLSurfaceHandle& handle) {
+ if (handle.transport_type == gfx::NATIVE_TRANSPORT) {
+ return scoped_refptr<gfx::GLSurface>(
+ new ImageTransportSurfaceAndroid(manager,
+ stub,
+ manager->GetDefaultOffscreenSurface(),
+ handle.parent_client_id));
+ }
+
DCHECK(GpuSurfaceLookup::GetInstance());
DCHECK_EQ(handle.transport_type, gfx::NATIVE_DIRECT);
ANativeWindow* window =
@@ -29,8 +207,8 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
if (!initialize_success)
return scoped_refptr<gfx::GLSurface>();
- return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
- manager, stub, surface.get(), false));
+ return scoped_refptr<gfx::GLSurface>(
+ new DirectSurfaceAndroid(manager, stub, surface.get(), false));
}
} // namespace content
diff --git a/chromium/content/common/gpu/image_transport_surface_mac.cc b/chromium/content/common/gpu/image_transport_surface_mac.cc
index 6e6c5804fd5..691d22ce456 100644
--- a/chromium/content/common/gpu/image_transport_surface_mac.cc
+++ b/chromium/content/common/gpu/image_transport_surface_mac.cc
@@ -64,6 +64,7 @@ class IOSurfaceImageTransportSurface
virtual void OnResizeViewACK() OVERRIDE;
virtual void OnResize(gfx::Size size, float scale_factor) OVERRIDE;
virtual void SetLatencyInfo(const ui::LatencyInfo&) OVERRIDE;
+ virtual void WakeUpGpu() OVERRIDE;
// GpuCommandBufferStub::DestructionObserver implementation.
virtual void OnWillDestroyStub() OVERRIDE;
@@ -81,6 +82,7 @@ class IOSurfaceImageTransportSurface
uint32 fbo_id_;
GLuint texture_id_;
+ GLuint depth_stencil_renderbuffer_id_;
base::ScopedCFTypeRef<CFTypeRef> io_surface_;
@@ -134,6 +136,7 @@ IOSurfaceImageTransportSurface::IOSurfaceImageTransportSurface(
frontbuffer_suggested_allocation_(true),
fbo_id_(0),
texture_id_(0),
+ depth_stencil_renderbuffer_id_(0),
io_surface_handle_(0),
context_(NULL),
scale_factor_(1.f),
@@ -325,6 +328,10 @@ void IOSurfaceImageTransportSurface::SetLatencyInfo(
latency_info_ = latency_info;
}
+void IOSurfaceImageTransportSurface::WakeUpGpu() {
+ NOTIMPLEMENTED();
+}
+
void IOSurfaceImageTransportSurface::OnWillDestroyStub() {
helper_->stub()->RemoveDestructionObserver(this);
Destroy();
@@ -333,7 +340,7 @@ void IOSurfaceImageTransportSurface::OnWillDestroyStub() {
void IOSurfaceImageTransportSurface::UnrefIOSurface() {
// If we have resources to destroy, then make sure that we have a current
// context which we can use to delete the resources.
- if (context_ || fbo_id_ || texture_id_) {
+ if (context_ || fbo_id_ || texture_id_ || depth_stencil_renderbuffer_id_) {
DCHECK(gfx::GLContext::GetCurrent() == context_);
DCHECK(context_->IsCurrent(this));
DCHECK(CGLGetCurrentContext());
@@ -349,6 +356,11 @@ void IOSurfaceImageTransportSurface::UnrefIOSurface() {
texture_id_ = 0;
}
+ if (depth_stencil_renderbuffer_id_) {
+ glDeleteRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
+ depth_stencil_renderbuffer_id_ = 0;
+ }
+
io_surface_.reset();
io_surface_handle_ = 0;
}
@@ -397,6 +409,37 @@ void IOSurfaceImageTransportSurface::CreateIOSurface() {
texture_id_,
0);
+
+ // Search through the provided attributes; if the caller has
+ // requested a stencil buffer, try to get one.
+
+ int32 stencil_bits =
+ helper_->stub()->GetRequestedAttribute(EGL_STENCIL_SIZE);
+ if (stencil_bits > 0) {
+ // Create and bind the stencil buffer
+ bool has_packed_depth_stencil =
+ GLSurface::ExtensionsContain(
+ reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)),
+ "GL_EXT_packed_depth_stencil");
+
+ if (has_packed_depth_stencil) {
+ glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,
+ depth_stencil_renderbuffer_id_);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
+ rounded_size_.width(), rounded_size_.height());
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ GL_STENCIL_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT,
+ depth_stencil_renderbuffer_id_);
+ }
+
+ // If we asked for stencil but the extension isn't present,
+ // it's OK to silently fail; subsequent code will/must check
+ // for the presence of a stencil buffer before attempting to
+ // do stencil-based operations.
+ }
+
// Allocate a new IOSurface, which is the GPU resource that can be
// shared across processes.
base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
@@ -434,13 +477,19 @@ void IOSurfaceImageTransportSurface::CreateIOSurface() {
io_surface_.get(),
plane);
if (cglerror != kCGLNoError) {
- DLOG(ERROR) << "CGLTexImageIOSurface2D: " << cglerror;
UnrefIOSurface();
return;
}
glFlush();
+ GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ DLOG(ERROR) << "Framebuffer was incomplete: " << status;
+ UnrefIOSurface();
+ return;
+ }
+
glBindTexture(target, previous_texture_id);
// The FBO remains bound for this GL context.
}
diff --git a/chromium/content/common/gpu/image_transport_surface_win.cc b/chromium/content/common/gpu/image_transport_surface_win.cc
index c69e3cc5264..bd381ee4458 100644
--- a/chromium/content/common/gpu/image_transport_surface_win.cc
+++ b/chromium/content/common/gpu/image_transport_surface_win.cc
@@ -49,6 +49,7 @@ class PbufferImageTransportSurface
virtual void OnResizeViewACK() OVERRIDE;
virtual void OnResize(gfx::Size size, float scale_factor) OVERRIDE;
virtual void SetLatencyInfo(const ui::LatencyInfo&) OVERRIDE;
+ virtual void WakeUpGpu() OVERRIDE;
virtual gfx::Size GetSize() OVERRIDE;
private:
@@ -182,8 +183,7 @@ void PbufferImageTransportSurface::SetFrontbufferAllocation(bool allocation) {
}
void PbufferImageTransportSurface::DestroySurface() {
- GpuHostMsg_AcceleratedSurfaceRelease_Params params;
- helper_->SendAcceleratedSurfaceRelease(params);
+ helper_->SendAcceleratedSurfaceRelease();
}
std::string PbufferImageTransportSurface::GetExtensions() {
@@ -240,6 +240,10 @@ void PbufferImageTransportSurface::SetLatencyInfo(
latency_info_ = latency_info;
}
+void PbufferImageTransportSurface::WakeUpGpu() {
+ NOTIMPLEMENTED();
+}
+
gfx::Size PbufferImageTransportSurface::GetSize() {
return GLSurfaceAdapter::GetSize();
}
diff --git a/chromium/content/common/gpu/media/DEPS b/chromium/content/common/gpu/media/DEPS
index 6c858fb9ceb..987a2b152a8 100644
--- a/chromium/content/common/gpu/media/DEPS
+++ b/chromium/content/common/gpu/media/DEPS
@@ -1,4 +1,5 @@
include_rules = [
"+media",
"+third_party/libva",
+ "+third_party/libyuv",
]
diff --git a/chromium/content/common/gpu/media/android_video_decode_accelerator.cc b/chromium/content/common/gpu/media/android_video_decode_accelerator.cc
index 4bfbba59939..b0bfe0c6a51 100644
--- a/chromium/content/common/gpu/media/android_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/android_video_decode_accelerator.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
#include "content/common/gpu/gpu_channel.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "media/base/bitstream_buffer.h"
@@ -40,8 +41,21 @@ enum { kNumPictureBuffers = media::limits::kMaxVideoFrames + 1 };
// NotifyEndOfBitstreamBuffer() before getting output from the bitstream.
enum { kMaxBitstreamsNotifiedInAdvance = 32 };
-// static
+// Because MediaCodec is thread-hostile (must be poked on a single thread) and
+// has no callback mechanism (b/11990118), we must drive it by polling for
+// complete frames (and available input buffers, when the codec is fully
+// saturated). This function defines the polling delay. The value used is an
+// arbitrary choice that trades off CPU utilization (spinning) against latency.
+// Mirrors android_video_encode_accelerator.cc:EncodePollDelay().
static inline const base::TimeDelta DecodePollDelay() {
+ // An alternative to this polling scheme could be to dedicate a new thread
+ // (instead of using the ChildThread) to run the MediaCodec, and make that
+ // thread use the timeout-based flavor of MediaCodec's dequeue methods when it
+ // believes the codec should complete "soon" (e.g. waiting for an input
+ // buffer, or waiting for a picture when it knows enough complete input
+ // pictures have been fed to saturate any internal buffering). This is
+ // speculative and it's unclear that this would be a win (nor that there's a
+ // reasonably device-agnostic way to fill in the "believes" above).
return base::TimeDelta::FromMilliseconds(10);
}
@@ -59,9 +73,6 @@ AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator(
state_(NO_ERROR),
surface_texture_id_(0),
picturebuffers_requested_(false),
- io_task_is_posted_(false),
- decoder_met_eos_(false),
- num_bytes_used_in_the_pending_buffer_(0),
gl_decoder_(decoder) {
}
@@ -85,6 +96,12 @@ bool AndroidVideoDecodeAccelerator::Initialize(
return false;
}
+ // Only consider using MediaCodec if it's likely backed by hardware.
+ if (media::VideoCodecBridge::IsKnownUnaccelerated(
+ codec_, media::MEDIA_CODEC_DECODER)) {
+ return false;
+ }
+
if (!make_context_current_.Run()) {
LOG(ERROR) << "Failed to make this decoder's GL context current.";
return false;
@@ -121,25 +138,12 @@ bool AndroidVideoDecodeAccelerator::Initialize(
}
void AndroidVideoDecodeAccelerator::DoIOTask() {
- io_task_is_posted_ = false;
if (state_ == ERROR) {
return;
}
- DequeueOutput();
QueueInput();
-
- if (!pending_bitstream_buffers_.empty() ||
- !free_picture_ids_.empty()) {
- io_task_is_posted_ = true;
- // TODO(dwkang): PostDelayedTask() does not guarantee the task will awake
- // at the exact time. Need a better way for polling.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(
- &AndroidVideoDecodeAccelerator::DoIOTask, base::AsWeakPtr(this)),
- DecodePollDelay());
- }
+ DequeueOutput();
}
void AndroidVideoDecodeAccelerator::QueueInput() {
@@ -157,21 +161,24 @@ void AndroidVideoDecodeAccelerator::QueueInput() {
return;
}
- media::BitstreamBuffer& bitstream_buffer =
- pending_bitstream_buffers_.front();
+ base::Time queued_time = pending_bitstream_buffers_.front().second;
+ UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime",
+ base::Time::Now() - queued_time);
+ media::BitstreamBuffer bitstream_buffer =
+ pending_bitstream_buffers_.front().first;
+ pending_bitstream_buffers_.pop();
if (bitstream_buffer.id() == -1) {
media_codec_->QueueEOS(input_buf_index);
- pending_bitstream_buffers_.pop();
return;
}
+
// Abuse the presentation time argument to propagate the bitstream
// buffer ID to the output, so we can report it back to the client in
// PictureReady().
base::TimeDelta timestamp =
base::TimeDelta::FromMicroseconds(bitstream_buffer.id());
- int bytes_written = 0;
scoped_ptr<base::SharedMemory> shm(
new base::SharedMemory(bitstream_buffer.handle(), true));
@@ -179,30 +186,26 @@ void AndroidVideoDecodeAccelerator::QueueInput() {
"Failed to SharedMemory::Map()",
UNREADABLE_INPUT);
- const size_t offset = num_bytes_used_in_the_pending_buffer_;
- bytes_written = media_codec_->QueueInputBuffer(
- input_buf_index,
- static_cast<const uint8*>(shm->memory()) + offset,
- bitstream_buffer.size() - offset, timestamp);
- num_bytes_used_in_the_pending_buffer_ += bytes_written;
- CHECK_LE(num_bytes_used_in_the_pending_buffer_, bitstream_buffer.size());
-
- if (num_bytes_used_in_the_pending_buffer_ == bitstream_buffer.size()) {
- num_bytes_used_in_the_pending_buffer_ = 0;
- pending_bitstream_buffers_.pop();
+ status =
+ media_codec_->QueueInputBuffer(input_buf_index,
+ static_cast<const uint8*>(shm->memory()),
+ bitstream_buffer.size(),
+ timestamp);
+ RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK,
+ "Failed to QueueInputBuffer: " << status,
+ PLATFORM_FAILURE);
- // We should call NotifyEndOfBitstreamBuffer(), when no more decoded output
- // will be returned from the bitstream buffer. However, MediaCodec API is
- // not enough to guarantee it.
- // So, here, we calls NotifyEndOfBitstreamBuffer() in advance in order to
- // keep getting more bitstreams from the client, and throttle them by using
- // |bitstreams_notified_in_advance_|.
- // TODO(dwkang): check if there is a way to remove this workaround.
- base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
- &AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer,
- base::AsWeakPtr(this), bitstream_buffer.id()));
- bitstreams_notified_in_advance_.push_back(bitstream_buffer.id());
- }
+ // We should call NotifyEndOfBitstreamBuffer(), when no more decoded output
+ // will be returned from the bitstream buffer. However, MediaCodec API is
+ // not enough to guarantee it.
+ // So, here, we calls NotifyEndOfBitstreamBuffer() in advance in order to
+ // keep getting more bitstreams from the client, and throttle them by using
+ // |bitstreams_notified_in_advance_|.
+ // TODO(dwkang): check if there is a way to remove this workaround.
+ base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ &AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer,
+ base::AsWeakPtr(this), bitstream_buffer.id()));
+ bitstreams_notified_in_advance_.push_back(bitstream_buffer.id());
}
void AndroidVideoDecodeAccelerator::DequeueOutput() {
@@ -220,10 +223,9 @@ void AndroidVideoDecodeAccelerator::DequeueOutput() {
do {
size_t offset = 0;
size_t size = 0;
- int buf_index = 0;
media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer(
- NoWaitTimeOut(), &buf_index, &offset, &size, &timestamp, &eos);
+ NoWaitTimeOut(), &buf_index, &offset, &size, &timestamp, &eos, NULL);
switch (status) {
case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
case media::MEDIA_CODEC_ERROR:
@@ -240,11 +242,11 @@ void AndroidVideoDecodeAccelerator::DequeueOutput() {
&AndroidVideoDecodeAccelerator::RequestPictureBuffers,
base::AsWeakPtr(this)));
} else {
- // TODO(dwkang): support the dynamic resolution change.
- // Currently, we assume that there is no resolution change in the
- // input stream. So, INFO_OUTPUT_FORMAT_CHANGED should not happen
- // more than once. However, we allows it if resolution is the same
- // as the previous one because |media_codec_| can be reset in Reset().
+ // Dynamic resolution change support is not specified by the Android
+ // platform at and before JB-MR1, so it's not possible to smoothly
+ // continue playback at this point. Instead, error out immediately,
+ // expecting clients to Reset() as appropriate to avoid this.
+ // b/7093648
RETURN_ON_FAILURE(size_ == gfx::Size(width, height),
"Dynamic resolution change is not supported.",
PLATFORM_FAILURE);
@@ -268,13 +270,26 @@ void AndroidVideoDecodeAccelerator::DequeueOutput() {
}
} while (buf_index < 0);
+ // This ignores the emitted ByteBuffer and instead relies on rendering to the
+ // codec's SurfaceTexture and then copying from that texture to the client's
+ // PictureBuffer's texture. This means that each picture's data is written
+ // three times: once to the ByteBuffer, once to the SurfaceTexture, and once
+ // to the client's texture. It would be nicer to either:
+ // 1) Render directly to the client's texture from MediaCodec (one write); or
+ // 2) Upload the ByteBuffer to the client's texture (two writes).
+ // Unfortunately neither is possible:
+ // 1) MediaCodec's use of SurfaceTexture is a singleton, and the texture
+ // written to can't change during the codec's lifetime. b/11990461
+ // 2) The ByteBuffer is likely to contain the pixels in a vendor-specific,
+ // opaque/non-standard format. It's not possible to negotiate the decoder
+ // to emit a specific colorspace, even using HW CSC. b/10706245
+ // So, we live with these two extra copies per picture :(
media_codec_->ReleaseOutputBuffer(buf_index, true);
if (eos) {
base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
&AndroidVideoDecodeAccelerator::NotifyFlushDone,
base::AsWeakPtr(this)));
- decoder_met_eos_ = true;
} else {
int64 bitstream_buffer_id = timestamp.InMicroseconds();
SendCurrentSurfaceToClient(static_cast<int32>(bitstream_buffer_id));
@@ -357,40 +372,52 @@ void AndroidVideoDecodeAccelerator::Decode(
return;
}
- pending_bitstream_buffers_.push(bitstream_buffer);
+ pending_bitstream_buffers_.push(
+ std::make_pair(bitstream_buffer, base::Time::Now()));
- if (!io_task_is_posted_)
- DoIOTask();
+ DoIOTask();
}
void AndroidVideoDecodeAccelerator::AssignPictureBuffers(
const std::vector<media::PictureBuffer>& buffers) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(output_picture_buffers_.empty());
+ DCHECK(free_picture_ids_.empty());
for (size_t i = 0; i < buffers.size(); ++i) {
RETURN_ON_FAILURE(buffers[i].size() == size_,
"Invalid picture buffer size was passed.",
INVALID_ARGUMENT);
- output_picture_buffers_.insert(std::make_pair(buffers[i].id(), buffers[i]));
- free_picture_ids_.push(buffers[i].id());
+ int32 id = buffers[i].id();
+ output_picture_buffers_.insert(std::make_pair(id, buffers[i]));
+ free_picture_ids_.push(id);
+ // Since the client might be re-using |picture_buffer_id| values, forget
+ // about previously-dismissed IDs now. See ReusePictureBuffer() comment
+ // about "zombies" for why we maintain this set in the first place.
+ dismissed_picture_ids_.erase(id);
}
RETURN_ON_FAILURE(output_picture_buffers_.size() == kNumPictureBuffers,
"Invalid picture buffers were passed.",
INVALID_ARGUMENT);
- if (!io_task_is_posted_)
- DoIOTask();
+ DoIOTask();
}
void AndroidVideoDecodeAccelerator::ReusePictureBuffer(
int32 picture_buffer_id) {
DCHECK(thread_checker_.CalledOnValidThread());
+
+ // This ReusePictureBuffer() might have been in a pipe somewhere (queued in
+ // IPC, or in a PostTask either at the sender or receiver) when we sent a
+ // DismissPictureBuffer() for this |picture_buffer_id|. Account for such
+ // potential "zombie" IDs here.
+ if (dismissed_picture_ids_.erase(picture_buffer_id))
+ return;
+
free_picture_ids_.push(picture_buffer_id);
- if (!io_task_is_posted_)
- DoIOTask();
+ DoIOTask();
}
void AndroidVideoDecodeAccelerator::Flush() {
@@ -401,46 +428,57 @@ void AndroidVideoDecodeAccelerator::Flush() {
bool AndroidVideoDecodeAccelerator::ConfigureMediaCodec() {
DCHECK(surface_texture_.get());
- media_codec_.reset(media::VideoCodecBridge::Create(codec_, false));
+ gfx::ScopedJavaSurface surface(surface_texture_.get());
+
+ // Pass a dummy 320x240 canvas size and let the codec signal the real size
+ // when it's known from the bitstream.
+ media_codec_.reset(media::VideoCodecBridge::CreateDecoder(
+ codec_, false, gfx::Size(320, 240), surface.j_surface().obj(), NULL));
if (!media_codec_)
return false;
- gfx::ScopedJavaSurface surface(surface_texture_.get());
- // VDA does not pass the container indicated resolution in the initialization
- // phase. Here, we set 720p by default.
- // TODO(dwkang): find out a way to remove the following hard-coded value.
- media_codec_->Start(
- codec_, gfx::Size(1280, 720), surface.j_surface().obj(), NULL);
- return media_codec_->GetOutputBuffers();
+ io_timer_.Start(FROM_HERE,
+ DecodePollDelay(),
+ this,
+ &AndroidVideoDecodeAccelerator::DoIOTask);
+ return true;
}
void AndroidVideoDecodeAccelerator::Reset() {
DCHECK(thread_checker_.CalledOnValidThread());
while (!pending_bitstream_buffers_.empty()) {
- media::BitstreamBuffer& bitstream_buffer =
- pending_bitstream_buffers_.front();
+ int32 bitstream_buffer_id = pending_bitstream_buffers_.front().first.id();
pending_bitstream_buffers_.pop();
- if (bitstream_buffer.id() != -1) {
+ if (bitstream_buffer_id != -1) {
base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer,
- base::AsWeakPtr(this), bitstream_buffer.id()));
+ base::AsWeakPtr(this), bitstream_buffer_id));
}
}
bitstreams_notified_in_advance_.clear();
- if (!decoder_met_eos_) {
- media_codec_->Reset();
- } else {
- // MediaCodec should be usable after meeting EOS, but it is not on some
- // devices. b/8125974 To avoid the case, we recreate a new one.
- media_codec_->Stop();
- ConfigureMediaCodec();
+ for (OutputBufferMap::iterator it = output_picture_buffers_.begin();
+ it != output_picture_buffers_.end();
+ ++it) {
+ client_->DismissPictureBuffer(it->first);
+ dismissed_picture_ids_.insert(it->first);
}
- decoder_met_eos_ = false;
- num_bytes_used_in_the_pending_buffer_ = 0;
+ output_picture_buffers_.clear();
+ std::queue<int32> empty;
+ std::swap(free_picture_ids_, empty);
+ CHECK(free_picture_ids_.empty());
+ picturebuffers_requested_ = false;
+
+ // On some devices, and up to at least JB-MR1,
+ // - flush() can fail after EOS (b/8125974); and
+ // - mid-stream resolution change is unsupported (b/7093648).
+ // To cope with these facts, we always stop & restart the codec on Reset().
+ io_timer_.Stop();
+ media_codec_->Stop();
+ ConfigureMediaCodec();
state_ = NO_ERROR;
base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
@@ -450,8 +488,10 @@ void AndroidVideoDecodeAccelerator::Reset() {
void AndroidVideoDecodeAccelerator::Destroy() {
DCHECK(thread_checker_.CalledOnValidThread());
- if (media_codec_)
+ if (media_codec_) {
+ io_timer_.Stop();
media_codec_->Stop();
+ }
if (surface_texture_id_)
glDeleteTextures(1, &surface_texture_id_);
if (copier_)
diff --git a/chromium/content/common/gpu/media/android_video_decode_accelerator.h b/chromium/content/common/gpu/media/android_video_decode_accelerator.h
index abcb1db950a..b2270a2ef6c 100644
--- a/chromium/content/common/gpu/media/android_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/android_video_decode_accelerator.h
@@ -5,7 +5,6 @@
#ifndef CONTENT_COMMON_GPU_MEDIA_ANDROID_VIDEO_DECODE_ACCELERATOR_H_
#define CONTENT_COMMON_GPU_MEDIA_ANDROID_VIDEO_DECODE_ACCELERATOR_H_
-#include <dlfcn.h>
#include <list>
#include <map>
#include <queue>
@@ -14,6 +13,7 @@
#include "base/compiler_specific.h"
#include "base/threading/thread_checker.h"
+#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "content/common/gpu/media/video_decode_accelerator_impl.h"
#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
@@ -124,6 +124,11 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// decoded frames to the client.
std::queue<int32> free_picture_ids_;
+ // Picture buffer ids which have been dismissed and not yet re-assigned. Used
+ // to ignore ReusePictureBuffer calls that were in flight when the
+ // DismissPictureBuffer call was made.
+ std::set<int32> dismissed_picture_ids_;
+
// The low-level decoder which Android SDK provides.
scoped_ptr<media::VideoCodecBridge> media_codec_;
@@ -136,23 +141,15 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// Set to true after requesting picture buffers to the client.
bool picturebuffers_requested_;
- // Set to true when DoIOTask is in the message loop.
- bool io_task_is_posted_;
-
- // Set to true when decoder outputs EOS (end of stream).
- bool decoder_met_eos_;
-
// The resolution of the stream.
gfx::Size size_;
- // Encoded bitstream buffers to be passed to media codec, queued until a input
- // buffer is available.
- typedef std::queue<media::BitstreamBuffer> BitstreamBufferList;
- BitstreamBufferList pending_bitstream_buffers_;
-
- // Indicates the number of bytes already passed to the decoder in the first
- // buffer in |pending_bitstream_buffers_|.
- size_t num_bytes_used_in_the_pending_buffer_;
+ // Encoded bitstream buffers to be passed to media codec, queued until an
+ // input buffer is available, along with the time when they were first
+ // enqueued.
+ typedef std::queue<std::pair<media::BitstreamBuffer, base::Time> >
+ PendingBitstreamBuffers;
+ PendingBitstreamBuffers pending_bitstream_buffers_;
// Keeps track of bitstream ids notified to the client with
// NotifyEndOfBitstreamBuffer() before getting output from the bitstream.
@@ -164,6 +161,9 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// Used for copy the texture from |surface_texture_| to picture buffers.
scoped_ptr<gpu::CopyTextureCHROMIUMResourceManager> copier_;
+ // Repeating timer responsible for draining pending IO to the codec.
+ base::RepeatingTimer<AndroidVideoDecodeAccelerator> io_timer_;
+
friend class AndroidVideoDecodeAcceleratorTest;
};
diff --git a/chromium/content/common/gpu/media/android_video_encode_accelerator.cc b/chromium/content/common/gpu/media/android_video_encode_accelerator.cc
new file mode 100644
index 00000000000..79281432c21
--- /dev/null
+++ b/chromium/content/common/gpu/media/android_video_encode_accelerator.cc
@@ -0,0 +1,412 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/media/android_video_encode_accelerator.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
+#include "content/common/gpu/gpu_channel.h"
+#include "content/public/common/content_switches.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "media/base/android/media_codec_bridge.h"
+#include "media/base/bitstream_buffer.h"
+#include "media/base/limits.h"
+#include "media/video/picture.h"
+#include "third_party/libyuv/include/libyuv/convert_from.h"
+#include "ui/gl/android/scoped_java_surface.h"
+#include "ui/gl/gl_bindings.h"
+
+using media::MediaCodecBridge;
+using media::VideoCodecBridge;
+using media::VideoFrame;
+
+namespace content {
+
+enum {
+ // Subset of MediaCodecInfo.CodecCapabilities.
+ COLOR_FORMAT_YUV420_SEMIPLANAR = 21,
+};
+
+// Helper macros for dealing with failure. If |result| evaluates false, emit
+// |log| to DLOG(ERROR), register |error| with the client, and return.
+#define RETURN_ON_FAILURE(result, log, error) \
+ do { \
+ if (!(result)) { \
+ DLOG(ERROR) << log; \
+ if (client_ptr_factory_.GetWeakPtr()) { \
+ client_ptr_factory_.GetWeakPtr()->NotifyError(error); \
+ client_ptr_factory_.InvalidateWeakPtrs(); \
+ } \
+ return; \
+ } \
+ } while (0)
+
+// Because MediaCodec is thread-hostile (must be poked on a single thread) and
+// has no callback mechanism (b/11990118), we must drive it by polling for
+// complete frames (and available input buffers, when the codec is fully
+// saturated). This function defines the polling delay. The value used is an
+// arbitrary choice that trades off CPU utilization (spinning) against latency.
+// Mirrors android_video_decode_accelerator.cc::DecodePollDelay().
+static inline const base::TimeDelta EncodePollDelay() {
+ // An alternative to this polling scheme could be to dedicate a new thread
+ // (instead of using the ChildThread) to run the MediaCodec, and make that
+ // thread use the timeout-based flavor of MediaCodec's dequeue methods when it
+ // believes the codec should complete "soon" (e.g. waiting for an input
+ // buffer, or waiting for a picture when it knows enough complete input
+ // pictures have been fed to saturate any internal buffering). This is
+ // speculative and it's unclear that this would be a win (nor that there's a
+ // reasonably device-agnostic way to fill in the "believes" above).
+ return base::TimeDelta::FromMilliseconds(10);
+}
+
+static inline const base::TimeDelta NoWaitTimeOut() {
+ return base::TimeDelta::FromMicroseconds(0);
+}
+
+AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator(
+ media::VideoEncodeAccelerator::Client* client)
+ : client_ptr_factory_(client),
+ num_buffers_at_codec_(0),
+ num_output_buffers_(-1),
+ output_buffers_capacity_(0),
+ last_set_bitrate_(0) {}
+
+AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+// static
+std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+AndroidVideoEncodeAccelerator::GetSupportedProfiles() {
+ std::vector<MediaCodecBridge::CodecsInfo> codecs_info =
+ MediaCodecBridge::GetCodecsInfo();
+
+ std::vector<SupportedProfile> profiles;
+
+ const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ if (cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding))
+ return profiles;
+
+ for (size_t i = 0; i < codecs_info.size(); ++i) {
+ const MediaCodecBridge::CodecsInfo& info = codecs_info[i];
+ if (info.direction != media::MEDIA_CODEC_ENCODER || info.codecs != "vp8" ||
+ VideoCodecBridge::IsKnownUnaccelerated(media::kCodecVP8,
+ media::MEDIA_CODEC_ENCODER)) {
+ // We're only looking for a HW VP8 encoder.
+ continue;
+ }
+ SupportedProfile profile;
+ profile.profile = media::VP8PROFILE_MAIN;
+ // Wouldn't it be nice if MediaCodec exposed the maximum capabilities of the
+ // encoder? Sure would be. Too bad it doesn't. So we hard-code some
+ // reasonable defaults.
+ profile.max_resolution.SetSize(1920, 1088);
+ profile.max_framerate.numerator = 30;
+ profile.max_framerate.denominator = 1;
+ profiles.push_back(profile);
+ }
+ return profiles;
+}
+
+void AndroidVideoEncodeAccelerator::Initialize(
+ VideoFrame::Format format,
+ const gfx::Size& input_visible_size,
+ media::VideoCodecProfile output_profile,
+ uint32 initial_bitrate) {
+ DVLOG(3) << __PRETTY_FUNCTION__ << " format: " << format
+ << ", input_visible_size: " << input_visible_size.ToString()
+ << ", output_profile: " << output_profile
+ << ", initial_bitrate: " << initial_bitrate;
+ DCHECK(!media_codec_);
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ RETURN_ON_FAILURE(media::MediaCodecBridge::IsAvailable() &&
+ media::MediaCodecBridge::SupportsSetParameters() &&
+ format == VideoFrame::I420 &&
+ output_profile == media::VP8PROFILE_MAIN,
+ "Unexpected combo: " << format << ", " << output_profile,
+ kInvalidArgumentError);
+
+ last_set_bitrate_ = initial_bitrate;
+
+ // Only consider using MediaCodec if it's likely backed by hardware.
+ RETURN_ON_FAILURE(!media::VideoCodecBridge::IsKnownUnaccelerated(
+ media::kCodecVP8, media::MEDIA_CODEC_ENCODER),
+ "No HW support",
+ kPlatformFailureError);
+
+ // TODO(fischman): when there is more HW out there with different color-space
+ // support, this should turn into a negotiation with the codec for supported
+ // formats. For now we use the only format supported by the only available
+ // HW.
+ media_codec_.reset(
+ media::VideoCodecBridge::CreateEncoder(media::kCodecVP8,
+ input_visible_size,
+ initial_bitrate,
+ INITIAL_FRAMERATE,
+ IFRAME_INTERVAL,
+ COLOR_FORMAT_YUV420_SEMIPLANAR));
+
+ RETURN_ON_FAILURE(
+ media_codec_,
+ "Failed to create/start the codec: " << input_visible_size.ToString(),
+ kPlatformFailureError);
+
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&VideoEncodeAccelerator::Client::NotifyInitializeDone,
+ client_ptr_factory_.GetWeakPtr()));
+
+ num_output_buffers_ = media_codec_->GetOutputBuffersCount();
+ output_buffers_capacity_ = media_codec_->GetOutputBuffersCapacity();
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&VideoEncodeAccelerator::Client::RequireBitstreamBuffers,
+ client_ptr_factory_.GetWeakPtr(),
+ num_output_buffers_,
+ input_visible_size,
+ output_buffers_capacity_));
+}
+
+void AndroidVideoEncodeAccelerator::MaybeStartIOTimer() {
+ if (!io_timer_.IsRunning() &&
+ (num_buffers_at_codec_ > 0 || !pending_frames_.empty())) {
+ io_timer_.Start(FROM_HERE,
+ EncodePollDelay(),
+ this,
+ &AndroidVideoEncodeAccelerator::DoIOTask);
+ }
+}
+
+void AndroidVideoEncodeAccelerator::MaybeStopIOTimer() {
+ if (io_timer_.IsRunning() &&
+ (num_buffers_at_codec_ == 0 && pending_frames_.empty())) {
+ io_timer_.Stop();
+ }
+}
+
+void AndroidVideoEncodeAccelerator::Encode(
+ const scoped_refptr<VideoFrame>& frame,
+ bool force_keyframe) {
+ DVLOG(3) << __PRETTY_FUNCTION__ << ": " << force_keyframe;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ RETURN_ON_FAILURE(frame->format() == VideoFrame::I420,
+ "Unexpected format",
+ kInvalidArgumentError);
+
+ // MediaCodec doesn't have a way to specify stride for non-Packed formats, so
+ // we insist on being called with packed frames and no cropping :(
+ RETURN_ON_FAILURE(frame->row_bytes(VideoFrame::kYPlane) ==
+ frame->stride(VideoFrame::kYPlane) &&
+ frame->row_bytes(VideoFrame::kUPlane) ==
+ frame->stride(VideoFrame::kUPlane) &&
+ frame->row_bytes(VideoFrame::kVPlane) ==
+ frame->stride(VideoFrame::kVPlane) &&
+ gfx::Rect(frame->coded_size()) == frame->visible_rect(),
+ "Non-packed frame, or visible rect != coded size",
+ kInvalidArgumentError);
+
+ pending_frames_.push(MakeTuple(frame, force_keyframe, base::Time::Now()));
+ DoIOTask();
+}
+
+void AndroidVideoEncodeAccelerator::UseOutputBitstreamBuffer(
+ const media::BitstreamBuffer& buffer) {
+ DVLOG(3) << __PRETTY_FUNCTION__ << ": bitstream_buffer_id=" << buffer.id();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ RETURN_ON_FAILURE(buffer.size() >= media_codec_->GetOutputBuffersCapacity(),
+ "Output buffers too small!",
+ kInvalidArgumentError);
+ available_bitstream_buffers_.push_back(buffer);
+ DoIOTask();
+}
+
+void AndroidVideoEncodeAccelerator::RequestEncodingParametersChange(
+ uint32 bitrate,
+ uint32 framerate) {
+ DVLOG(3) << __PRETTY_FUNCTION__ << ": bitrate: " << bitrate
+ << ", framerate: " << framerate;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (bitrate != last_set_bitrate_) {
+ last_set_bitrate_ = bitrate;
+ media_codec_->SetVideoBitrate(bitrate);
+ }
+ // Note: Android's MediaCodec doesn't allow mid-stream adjustments to
+ // framerate, so we ignore that here. This is OK because Android only uses
+ // the framerate value from MediaFormat during configure() as a proxy for
+ // bitrate, and we set that explicitly.
+}
+
+void AndroidVideoEncodeAccelerator::Destroy() {
+ DVLOG(3) << __PRETTY_FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ client_ptr_factory_.InvalidateWeakPtrs();
+ if (media_codec_) {
+ if (io_timer_.IsRunning())
+ io_timer_.Stop();
+ media_codec_->Stop();
+ }
+ delete this;
+}
+
+void AndroidVideoEncodeAccelerator::DoIOTask() {
+ QueueInput();
+ DequeueOutput();
+ MaybeStartIOTimer();
+ MaybeStopIOTimer();
+}
+
+void AndroidVideoEncodeAccelerator::QueueInput() {
+ if (!client_ptr_factory_.GetWeakPtr() || pending_frames_.empty())
+ return;
+
+ int input_buf_index = 0;
+ media::MediaCodecStatus status =
+ media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index);
+ if (status != media::MEDIA_CODEC_OK) {
+ DCHECK(status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER ||
+ status == media::MEDIA_CODEC_ERROR);
+ RETURN_ON_FAILURE(status != media::MEDIA_CODEC_ERROR,
+ "MediaCodec error",
+ kPlatformFailureError);
+ return;
+ }
+
+ const PendingFrames::value_type& input = pending_frames_.front();
+ bool is_key_frame = input.b;
+ if (is_key_frame) {
+ // Ideally MediaCodec would honor BUFFER_FLAG_SYNC_FRAME so we could
+ // indicate this in the QueueInputBuffer() call below and guarantee _this_
+ // frame be encoded as a key frame, but sadly that flag is ignored.
+ // Instead, we request a key frame "soon".
+ media_codec_->RequestKeyFrameSoon();
+ }
+ scoped_refptr<VideoFrame> frame = input.a;
+
+ uint8* buffer = NULL;
+ size_t capacity = 0;
+ media_codec_->GetInputBuffer(input_buf_index, &buffer, &capacity);
+
+ size_t queued_size =
+ VideoFrame::AllocationSize(VideoFrame::I420, frame->coded_size());
+ RETURN_ON_FAILURE(capacity >= queued_size,
+ "Failed to get input buffer: " << input_buf_index,
+ kPlatformFailureError);
+
+ uint8* dst_y = buffer;
+ int dst_stride_y = frame->stride(VideoFrame::kYPlane);
+ uint8* dst_uv = buffer + frame->stride(VideoFrame::kYPlane) *
+ frame->rows(VideoFrame::kYPlane);
+ int dst_stride_uv = frame->stride(VideoFrame::kUPlane) * 2;
+ // Why NV12? Because COLOR_FORMAT_YUV420_SEMIPLANAR. See comment at other
+ // mention of that constant.
+ bool converted = !libyuv::I420ToNV12(frame->data(VideoFrame::kYPlane),
+ frame->stride(VideoFrame::kYPlane),
+ frame->data(VideoFrame::kUPlane),
+ frame->stride(VideoFrame::kUPlane),
+ frame->data(VideoFrame::kVPlane),
+ frame->stride(VideoFrame::kVPlane),
+ dst_y,
+ dst_stride_y,
+ dst_uv,
+ dst_stride_uv,
+ frame->coded_size().width(),
+ frame->coded_size().height());
+ RETURN_ON_FAILURE(converted, "Failed to I420ToNV12!", kPlatformFailureError);
+
+ fake_input_timestamp_ += base::TimeDelta::FromMicroseconds(1);
+ status = media_codec_->QueueInputBuffer(
+ input_buf_index, NULL, queued_size, fake_input_timestamp_);
+ UMA_HISTOGRAM_TIMES("Media.AVEA.InputQueueTime", base::Time::Now() - input.c);
+ RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK,
+ "Failed to QueueInputBuffer: " << status,
+ kPlatformFailureError);
+ ++num_buffers_at_codec_;
+ pending_frames_.pop();
+}
+
+bool AndroidVideoEncodeAccelerator::DoOutputBuffersSuffice() {
+ // If this returns false ever, then the VEA::Client interface will need to
+ // grow a DismissBitstreamBuffer() call, and VEA::Client impls will have to be
+ // prepared to field multiple requests to RequireBitstreamBuffers().
+ int count = media_codec_->GetOutputBuffersCount();
+ size_t capacity = media_codec_->GetOutputBuffersCapacity();
+ bool ret = media_codec_->GetOutputBuffers() && count <= num_output_buffers_ &&
+ capacity <= output_buffers_capacity_;
+ LOG_IF(ERROR, !ret) << "Need more/bigger buffers; before: "
+ << num_output_buffers_ << "x" << output_buffers_capacity_
+ << ", now: " << count << "x" << capacity;
+ UMA_HISTOGRAM_BOOLEAN("Media.AVEA.OutputBuffersSuffice", ret);
+ return ret;
+}
+
+void AndroidVideoEncodeAccelerator::DequeueOutput() {
+ if (!client_ptr_factory_.GetWeakPtr() ||
+ available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) {
+ return;
+ }
+
+ int32 buf_index = 0;
+ size_t offset = 0;
+ size_t size = 0;
+ bool key_frame = false;
+ do {
+ media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer(
+ NoWaitTimeOut(), &buf_index, &offset, &size, NULL, NULL, &key_frame);
+ switch (status) {
+ case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
+ return;
+
+ case media::MEDIA_CODEC_ERROR:
+ RETURN_ON_FAILURE(false, "Codec error", kPlatformFailureError);
+ // Unreachable because of previous statement, but included for clarity.
+ return;
+
+ case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: // Fall-through.
+ case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
+ RETURN_ON_FAILURE(DoOutputBuffersSuffice(),
+ "Bitstream now requires more/larger buffers",
+ kPlatformFailureError);
+ break;
+
+ case media::MEDIA_CODEC_OK:
+ DCHECK_GE(buf_index, 0);
+ break;
+
+ default:
+ NOTREACHED();
+ break;
+ }
+ } while (buf_index < 0);
+
+ media::BitstreamBuffer bitstream_buffer = available_bitstream_buffers_.back();
+ available_bitstream_buffers_.pop_back();
+ scoped_ptr<base::SharedMemory> shm(
+ new base::SharedMemory(bitstream_buffer.handle(), false));
+ RETURN_ON_FAILURE(shm->Map(bitstream_buffer.size()),
+ "Failed to map SHM",
+ kPlatformFailureError);
+ RETURN_ON_FAILURE(size <= shm->mapped_size(),
+ "Encoded buffer too large: " << size << ">"
+ << shm->mapped_size(),
+ kPlatformFailureError);
+
+ media_codec_->CopyFromOutputBuffer(buf_index, offset, shm->memory(), size);
+ media_codec_->ReleaseOutputBuffer(buf_index, false);
+ --num_buffers_at_codec_;
+
+ UMA_HISTOGRAM_COUNTS_10000("Media.AVEA.EncodedBufferSizeKB", size / 1024);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady,
+ client_ptr_factory_.GetWeakPtr(),
+ bitstream_buffer.id(),
+ size,
+ key_frame));
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/media/android_video_encode_accelerator.h b/chromium/content/common/gpu/media/android_video_encode_accelerator.h
new file mode 100644
index 00000000000..e519a278c77
--- /dev/null
+++ b/chromium/content/common/gpu/media/android_video_encode_accelerator.h
@@ -0,0 +1,115 @@
+// 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_COMMON_GPU_MEDIA_ANDROID_VIDEO_ENCODE_ACCELERATOR_H_
+#define CONTENT_COMMON_GPU_MEDIA_ANDROID_VIDEO_ENCODE_ACCELERATOR_H_
+
+#include <list>
+#include <queue>
+#include <vector>
+
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "base/timer/timer.h"
+#include "base/tuple.h"
+#include "content/common/content_export.h"
+#include "media/base/android/media_codec_bridge.h"
+#include "media/video/video_encode_accelerator.h"
+
+namespace media {
+class BitstreamBuffer;
+} // namespace media
+
+namespace content {
+
+// Android-specific implementation of media::VideoEncodeAccelerator, enabling
+// hardware-acceleration of video encoding, based on Android's MediaCodec class
+// (http://developer.android.com/reference/android/media/MediaCodec.html). This
+// class expects to live and be called on a single thread (the GPU process'
+// ChildThread).
+class CONTENT_EXPORT AndroidVideoEncodeAccelerator
+ : public media::VideoEncodeAccelerator {
+ public:
+ explicit AndroidVideoEncodeAccelerator(
+ media::VideoEncodeAccelerator::Client* client);
+ virtual ~AndroidVideoEncodeAccelerator();
+
+ static std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+ GetSupportedProfiles();
+
+ // media::VideoEncodeAccelerator implementation.
+ virtual void Initialize(media::VideoFrame::Format format,
+ const gfx::Size& input_visible_size,
+ media::VideoCodecProfile output_profile,
+ uint32 initial_bitrate) OVERRIDE;
+ virtual void Encode(const scoped_refptr<media::VideoFrame>& frame,
+ bool force_keyframe) OVERRIDE;
+ virtual void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer)
+ OVERRIDE;
+ virtual void RequestEncodingParametersChange(uint32 bitrate,
+ uint32 framerate) OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+
+ private:
+ enum {
+ // Arbitrary choice.
+ INITIAL_FRAMERATE = 30,
+ // Until there are non-realtime users, no need for unrequested I-frames.
+ IFRAME_INTERVAL = kint32max,
+ };
+
+ // Impedance-mismatch fixers: MediaCodec is a poll-based API but VEA is a
+ // push-based API; these methods turn the crank to make the two work together.
+ void DoIOTask();
+ void QueueInput();
+ void DequeueOutput();
+
+ // Returns true if we don't need more or bigger output buffers.
+ bool DoOutputBuffersSuffice();
+
+ // Start & stop |io_timer_| if the time seems right.
+ void MaybeStartIOTimer();
+ void MaybeStopIOTimer();
+
+ // Used to DCHECK that we are called on the correct thread.
+ base::ThreadChecker thread_checker_;
+
+ // VideoDecodeAccelerator::Client callbacks go here. Invalidated once any
+ // error triggers.
+ base::WeakPtrFactory<Client> client_ptr_factory_;
+
+ scoped_ptr<media::VideoCodecBridge> media_codec_;
+
+ // Bitstream buffers waiting to be populated & returned to the client.
+ std::vector<media::BitstreamBuffer> available_bitstream_buffers_;
+
+ // Frames waiting to be passed to the codec, queued until an input buffer is
+ // available. Each element is a tuple of <Frame, key_frame, enqueue_time>.
+ typedef std::queue<
+ Tuple3<scoped_refptr<media::VideoFrame>, bool, base::Time> >
+ PendingFrames;
+ PendingFrames pending_frames_;
+
+ // Repeating timer responsible for draining pending IO to the codec.
+ base::RepeatingTimer<AndroidVideoEncodeAccelerator> io_timer_;
+
+ // The difference between number of buffers queued & dequeued at the codec.
+ int32 num_buffers_at_codec_;
+
+ // A monotonically-growing value, used as a fake timestamp just to keep things
+ // appearing to move forward.
+ base::TimeDelta fake_input_timestamp_;
+
+ // Number of requested output buffers and their capacity.
+ int num_output_buffers_; // -1 until RequireBitstreamBuffers.
+ size_t output_buffers_capacity_; // 0 until RequireBitstreamBuffers.
+
+ uint32 last_set_bitrate_; // In bps.
+
+ DISALLOW_COPY_AND_ASSIGN(AndroidVideoEncodeAccelerator);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_MEDIA_ANDROID_VIDEO_ENCODE_ACCELERATOR_H_
diff --git a/chromium/content/common/gpu/media/dxva_video_decode_accelerator.cc b/chromium/content/common/gpu/media/dxva_video_decode_accelerator.cc
index 97c883e22ba..38030305f0f 100644
--- a/chromium/content/common/gpu/media/dxva_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/dxva_video_decode_accelerator.cc
@@ -36,13 +36,6 @@ namespace content {
// it is done with the buffer.
static const int kNumPictureBuffers = 5;
-bool DXVAVideoDecodeAccelerator::pre_sandbox_init_done_ = false;
-uint32 DXVAVideoDecodeAccelerator::dev_manager_reset_token_ = 0;
-IDirect3DDeviceManager9* DXVAVideoDecodeAccelerator::device_manager_ = NULL;
-IDirect3DDevice9Ex* DXVAVideoDecodeAccelerator::device_ = NULL;
-IDirect3DQuery9* DXVAVideoDecodeAccelerator::query_ = NULL;
-IDirect3D9Ex* DXVAVideoDecodeAccelerator::d3d9_ = NULL;
-
#define RETURN_ON_FAILURE(result, log, ret) \
do { \
if (!(result)) { \
@@ -165,14 +158,18 @@ static IMFSample* CreateSampleFromInputBuffer(
struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer {
public:
static linked_ptr<DXVAPictureBuffer> Create(
- const media::PictureBuffer& buffer, EGLConfig egl_config);
+ const DXVAVideoDecodeAccelerator& decoder,
+ const media::PictureBuffer& buffer,
+ EGLConfig egl_config);
~DXVAPictureBuffer();
void ReusePictureBuffer();
// Copies the output sample data to the picture buffer provided by the
// client.
// The dest_surface parameter contains the decoded bits.
- bool CopyOutputSampleDataToPictureBuffer(IDirect3DSurface9* dest_surface);
+ bool CopyOutputSampleDataToPictureBuffer(
+ const DXVAVideoDecodeAccelerator& decoder,
+ IDirect3DSurface9* dest_surface);
bool available() const {
return available_;
@@ -203,8 +200,10 @@ struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer {
// static
linked_ptr<DXVAVideoDecodeAccelerator::DXVAPictureBuffer>
- DXVAVideoDecodeAccelerator::DXVAPictureBuffer::Create(
- const media::PictureBuffer& buffer, EGLConfig egl_config) {
+DXVAVideoDecodeAccelerator::DXVAPictureBuffer::Create(
+ const DXVAVideoDecodeAccelerator& decoder,
+ const media::PictureBuffer& buffer,
+ EGLConfig egl_config) {
linked_ptr<DXVAPictureBuffer> picture_buffer(new DXVAPictureBuffer(buffer));
EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
@@ -236,7 +235,7 @@ linked_ptr<DXVAVideoDecodeAccelerator::DXVAPictureBuffer>
"Failed to query ANGLE surface pointer",
linked_ptr<DXVAPictureBuffer>(NULL));
- HRESULT hr = DXVAVideoDecodeAccelerator::device_->CreateTexture(
+ HRESULT hr = decoder.device_->CreateTexture(
buffer.size().width(),
buffer.size().height(),
1,
@@ -285,7 +284,9 @@ void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() {
}
bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
- CopyOutputSampleDataToPictureBuffer(IDirect3DSurface9* dest_surface) {
+ CopyOutputSampleDataToPictureBuffer(
+ const DXVAVideoDecodeAccelerator& decoder,
+ IDirect3DSurface9* dest_surface) {
DCHECK(dest_surface);
D3DSURFACE_DESC surface_desc;
@@ -301,15 +302,9 @@ bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
return false;
}
- hr = d3d9_->CheckDeviceFormatConversion(D3DADAPTER_DEFAULT,
- D3DDEVTYPE_HAL,
- surface_desc.Format,
- D3DFMT_X8R8G8B8);
- bool device_supports_format_conversion = (hr == S_OK);
-
- RETURN_ON_FAILURE(device_supports_format_conversion,
- "Device does not support format converision",
- false);
+ hr = decoder.d3d9_->CheckDeviceFormatConversion(
+ D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, surface_desc.Format, D3DFMT_X8R8G8B8);
+ RETURN_ON_HR_FAILURE(hr, "Device does not support format converision", false);
// This function currently executes in the context of IPC handlers in the
// GPU process which ensures that there is always an OpenGL context.
@@ -324,17 +319,14 @@ bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
hr = decoding_texture_->GetSurfaceLevel(0, d3d_surface.Receive());
RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false);
- hr = device_->StretchRect(dest_surface,
- NULL,
- d3d_surface,
- NULL,
- D3DTEXF_NONE);
+ hr = decoder.device_->StretchRect(
+ dest_surface, NULL, d3d_surface, NULL, D3DTEXF_NONE);
RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed",
false);
// Ideally, this should be done immediately before the draw call that uses
// the texture. Flush it once here though.
- hr = query_->Issue(D3DISSUE_END);
+ hr = decoder.query_->Issue(D3DISSUE_END);
RETURN_ON_HR_FAILURE(hr, "Failed to issue END", false);
// The DXVA decoder has its own device which it uses for decoding. ANGLE
@@ -351,8 +343,8 @@ bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
// Workaround is to have an upper limit of 10 on the number of iterations to
// wait for the Flush to finish.
int iterations = 0;
- while ((query_->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE) &&
- ++iterations < kMaxIterationsForD3DFlush) {
+ while ((decoder.query_->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE) &&
+ ++iterations < kMaxIterationsForD3DFlush) {
Sleep(1); // Poor-man's Yield().
}
EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
@@ -374,50 +366,10 @@ DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo(
DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {}
// static
-void DXVAVideoDecodeAccelerator::PreSandboxInitialization() {
- // Should be called only once during program startup.
- DCHECK(!pre_sandbox_init_done_);
-
- static const wchar_t* kDecodingDlls[] = {
- L"d3d9.dll",
- L"dxva2.dll",
- L"mf.dll",
- L"mfplat.dll",
- L"msmpeg2vdec.dll",
- };
-
- for (int i = 0; i < arraysize(kDecodingDlls); ++i) {
- if (!::LoadLibrary(kDecodingDlls[i])) {
- DLOG(ERROR) << "Failed to load decoder dll: " << kDecodingDlls[i]
- << ", Error: " << ::GetLastError();
- return;
- }
- }
-
- RETURN_ON_FAILURE(CreateD3DDevManager(),
- "Failed to initialize D3D device and manager",);
-
- if (base::win::GetVersion() == base::win::VERSION_WIN8) {
- // On Windows 8+ mf.dll forwards to mfcore.dll. It does not exist in
- // Windows 7. Loading mfcore.dll fails on Windows 8.1 in the
- // sandbox.
- if (!LoadLibrary(L"mfcore.dll")) {
- DLOG(ERROR) << "Failed to load mfcore.dll, Error: " << ::GetLastError();
- return;
- }
- // MFStartup needs to be called once outside the sandbox. It fails on
- // Windows 8.1 with E_NOTIMPL if it is called the first time in the
- // sandbox.
- RETURN_ON_HR_FAILURE(MFStartup(MF_VERSION, MFSTARTUP_FULL),
- "MFStartup failed.",);
- }
-
- pre_sandbox_init_done_ = true;
-}
-
-// static
bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() {
- HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9_);
+ TRACE_EVENT0("gpu", "DXVAVideoDecodeAccelerator_CreateD3DDevManager");
+
+ HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, d3d9_.Receive());
RETURN_ON_HR_FAILURE(hr, "Direct3DCreate9Ex failed", false);
D3DPRESENT_PARAMETERS present_params = {0};
@@ -441,17 +393,17 @@ bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() {
D3DCREATE_MULTITHREADED,
&present_params,
NULL,
- &device_);
+ device_.Receive());
RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device", false);
hr = DXVA2CreateDirect3DDeviceManager9(&dev_manager_reset_token_,
- &device_manager_);
+ device_manager_.Receive());
RETURN_ON_HR_FAILURE(hr, "DXVA2CreateDirect3DDeviceManager9 failed", false);
hr = device_manager_->ResetDevice(device_, dev_manager_reset_token_);
RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false);
- hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, &query_);
+ hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive());
RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false);
// Ensure query_ API works (to avoid an infinite loop later in
// CopyOutputSampleDataToPictureBuffer).
@@ -464,6 +416,7 @@ DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator(
media::VideoDecodeAccelerator::Client* client,
const base::Callback<bool(void)>& make_context_current)
: client_(client),
+ dev_manager_reset_token_(0),
egl_config_(NULL),
state_(kUninitialized),
pictures_requested_(false),
@@ -480,6 +433,14 @@ DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() {
bool DXVAVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
DCHECK(CalledOnValidThread());
+ // Not all versions of Windows 7 and later include Media Foundation DLLs.
+ // Instead of crashing while delay loading the DLL when calling MFStartup()
+ // below, probe whether we can successfully load the DLL now.
+ //
+ // See http://crbug.com/339678 for details.
+ HMODULE mfplat_dll = ::LoadLibrary(L"MFPlat.dll");
+ RETURN_ON_FAILURE(mfplat_dll, "MFPlat.dll is required for decoding", false);
+
// TODO(ananta)
// H264PROFILE_HIGH video decoding is janky at times. Needs more
// investigation.
@@ -490,9 +451,6 @@ bool DXVAVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
"Unsupported h264 profile", PLATFORM_FAILURE, false);
}
- RETURN_AND_NOTIFY_ON_FAILURE(pre_sandbox_init_done_,
- "PreSandbox initialization not completed", PLATFORM_FAILURE, false);
-
RETURN_AND_NOTIFY_ON_FAILURE(
gfx::g_driver_egl.ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle,
"EGL_ANGLE_surface_d3d_texture_2d_share_handle unavailable",
@@ -506,7 +464,12 @@ bool DXVAVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "MFStartup failed.", PLATFORM_FAILURE,
false);
- RETURN_AND_NOTIFY_ON_FAILURE(InitDecoder(),
+ RETURN_AND_NOTIFY_ON_FAILURE(CreateD3DDevManager(),
+ "Failed to initialize D3D device and manager",
+ PLATFORM_FAILURE,
+ false);
+
+ RETURN_AND_NOTIFY_ON_FAILURE(InitDecoder(profile),
"Failed to initialize decoder", PLATFORM_FAILURE, false);
RETURN_AND_NOTIFY_ON_FAILURE(GetStreamsInfoAndBufferReqs(),
@@ -565,7 +528,7 @@ void DXVAVideoDecodeAccelerator::AssignPictureBuffers(
for (size_t buffer_index = 0; buffer_index < buffers.size();
++buffer_index) {
linked_ptr<DXVAPictureBuffer> picture_buffer =
- DXVAPictureBuffer::Create(buffers[buffer_index], egl_config_);
+ DXVAPictureBuffer::Create(*this, buffers[buffer_index], egl_config_);
RETURN_AND_NOTIFY_ON_FAILURE(picture_buffer.get(),
"Failed to allocate picture buffer", PLATFORM_FAILURE,);
@@ -647,23 +610,26 @@ void DXVAVideoDecodeAccelerator::Destroy() {
delete this;
}
-bool DXVAVideoDecodeAccelerator::InitDecoder() {
- // We cannot use CoCreateInstance to instantiate the decoder object as that
- // fails in the sandbox. We mimic the steps CoCreateInstance uses to
- // instantiate the object.
- HMODULE decoder_dll = ::GetModuleHandle(L"msmpeg2vdec.dll");
+bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) {
+ if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX)
+ return false;
+
+ // We mimic the steps CoCreateInstance uses to instantiate the object. This
+ // was previously done because it failed inside the sandbox, and now is done
+ // as a more minimal approach to avoid other side-effects CCI might have (as
+ // we are still in a reduced sandbox).
+ HMODULE decoder_dll = ::LoadLibrary(L"msmpeg2vdec.dll");
RETURN_ON_FAILURE(decoder_dll,
"msmpeg2vdec.dll required for decoding is not loaded",
false);
- typedef HRESULT (WINAPI* GetClassObject)(const CLSID& clsid,
- const IID& iid,
- void** object);
+ typedef HRESULT(WINAPI * GetClassObject)(
+ const CLSID & clsid, const IID & iid, void * *object);
GetClassObject get_class_object = reinterpret_cast<GetClassObject>(
GetProcAddress(decoder_dll, "DllGetClassObject"));
- RETURN_ON_FAILURE(get_class_object,
- "Failed to get DllGetClassObject pointer", false);
+ RETURN_ON_FAILURE(
+ get_class_object, "Failed to get DllGetClassObject pointer", false);
base::win::ScopedComPtr<IClassFactory> factory;
HRESULT hr = get_class_object(__uuidof(CMSH264DecoderMFT),
@@ -671,7 +637,8 @@ bool DXVAVideoDecodeAccelerator::InitDecoder() {
reinterpret_cast<void**>(factory.Receive()));
RETURN_ON_HR_FAILURE(hr, "DllGetClassObject for decoder failed", false);
- hr = factory->CreateInstance(NULL, __uuidof(IMFTransform),
+ hr = factory->CreateInstance(NULL,
+ __uuidof(IMFTransform),
reinterpret_cast<void**>(decoder_.Receive()));
RETURN_ON_HR_FAILURE(hr, "Failed to create decoder instance", false);
@@ -680,7 +647,7 @@ bool DXVAVideoDecodeAccelerator::InitDecoder() {
hr = decoder_->ProcessMessage(
MFT_MESSAGE_SET_D3D_MANAGER,
- reinterpret_cast<ULONG_PTR>(device_manager_));
+ reinterpret_cast<ULONG_PTR>(device_manager_.get()));
RETURN_ON_HR_FAILURE(hr, "Failed to pass D3D manager to decoder", false);
EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
@@ -953,9 +920,9 @@ void DXVAVideoDecodeAccelerator::ProcessPendingSamples() {
}
RETURN_AND_NOTIFY_ON_FAILURE(
- index->second->CopyOutputSampleDataToPictureBuffer(
- surface),
- "Failed to copy output sample", PLATFORM_FAILURE,);
+ index->second->CopyOutputSampleDataToPictureBuffer(*this, surface),
+ "Failed to copy output sample",
+ PLATFORM_FAILURE, );
media::Picture output_picture(index->second->id(),
sample_info.input_buffer_id);
diff --git a/chromium/content/common/gpu/media/dxva_video_decode_accelerator.h b/chromium/content/common/gpu/media/dxva_video_decode_accelerator.h
index 206099cfd71..870b12e4042 100644
--- a/chromium/content/common/gpu/media/dxva_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/dxva_video_decode_accelerator.h
@@ -57,23 +57,16 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
virtual void Reset() OVERRIDE;
virtual void Destroy() OVERRIDE;
- // Initialization work needed before the process is sandboxed.
- // This includes:-
- // 1. Loads the dlls like mf/mfplat/d3d9, etc required for decoding.
- // 2. Setting up the device manager instance which is shared between all
- // decoder instances.
- static void PreSandboxInitialization();
-
private:
typedef void* EGLConfig;
typedef void* EGLSurface;
// Creates and initializes an instance of the D3D device and the
// corresponding device manager. The device manager instance is eventually
// passed to the IMFTransform interface implemented by the h.264 decoder.
- static bool CreateD3DDevManager();
+ bool CreateD3DDevManager();
// Creates, initializes and sets the media types for the h.264 decoder.
- bool InitDecoder();
+ bool InitDecoder(media::VideoCodecProfile profile);
// Validates whether the h.264 decoder supports hardware video acceleration.
bool CheckDecoderDxvaSupport();
@@ -162,16 +155,16 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
base::win::ScopedComPtr<IMFTransform> decoder_;
- // These interface pointers are initialized before the process is sandboxed.
- // They are not released when the GPU process exits. This is ok for now
- // because the GPU process does not exit normally on Windows. It is always
- // terminated. The device manager instance is shared among all decoder
- // instances. This is OK because there is internal locking performed by the
- // device manager.
- static IDirect3DDeviceManager9* device_manager_;
- static IDirect3DDevice9Ex* device_;
- static IDirect3DQuery9* query_;
- static IDirect3D9Ex* d3d9_;
+ base::win::ScopedComPtr<IDirect3D9Ex> d3d9_;
+ base::win::ScopedComPtr<IDirect3DDevice9Ex> device_;
+ base::win::ScopedComPtr<IDirect3DDeviceManager9> device_manager_;
+ base::win::ScopedComPtr<IDirect3DQuery9> query_;
+ // Ideally the reset token would be a stack variable which is used while
+ // creating the device manager. However it seems that the device manager
+ // holds onto the token and attempts to access it if the underlying device
+ // changes.
+ // TODO(ananta): This needs to be verified.
+ uint32 dev_manager_reset_token_;
// The EGL config to use for decoded frames.
EGLConfig egl_config_;
@@ -203,24 +196,10 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
// Set to true if we requested picture slots from the client.
bool pictures_requested_;
- // Ideally the reset token would be a stack variable which is used while
- // creating the device manager. However it seems that the device manager
- // holds onto the token and attempts to access it if the underlying device
- // changes.
- // TODO(ananta): This needs to be verified.
- static uint32 dev_manager_reset_token_;
-
// Counter which holds the number of input packets before a successful
// decode.
int inputs_before_decode_;
- // Set to true if all necessary initialization needed before the GPU process
- // is sandboxed is done.
- // This includes the following:
- // 1. All required decoder dlls were successfully loaded.
- // 2. The device manager initialization completed.
- static bool pre_sandbox_init_done_;
-
// List of input samples waiting to be processed.
typedef std::list<base::win::ScopedComPtr<IMFSample>> PendingInputs;
PendingInputs pending_input_buffers_;
diff --git a/chromium/content/common/gpu/media/exynos_video_decode_accelerator.cc b/chromium/content/common/gpu/media/exynos_video_decode_accelerator.cc
index 554e760f6ed..9a6175421ad 100644
--- a/chromium/content/common/gpu/media/exynos_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/exynos_video_decode_accelerator.cc
@@ -5,6 +5,7 @@
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
+#include <libdrm/drm_fourcc.h>
#include <linux/videodev2.h>
#include <poll.h>
#include <sys/eventfd.h>
@@ -56,15 +57,7 @@ namespace {
#endif
const char kExynosMfcDevice[] = "/dev/mfc-dec";
-const char kExynosGscDevice[] = "/dev/gsc1";
-const char kMaliDriver[] = "libmali.so";
-typedef EGLBoolean (*MaliEglImageGetBufferExtPhandleFunc)(EGLImageKHR, EGLint*,
- void*);
-
-void* libmali_handle = NULL;
-MaliEglImageGetBufferExtPhandleFunc
- mali_egl_image_get_buffer_ext_phandle = NULL;
} // anonymous namespace
struct ExynosVideoDecodeAccelerator::BitstreamBufferRef {
@@ -84,13 +77,14 @@ struct ExynosVideoDecodeAccelerator::BitstreamBufferRef {
};
struct ExynosVideoDecodeAccelerator::PictureBufferArrayRef {
- PictureBufferArrayRef(EGLDisplay egl_display, size_t count);
+ PictureBufferArrayRef(EGLDisplay egl_display);
~PictureBufferArrayRef();
struct PictureBufferRef {
+ PictureBufferRef(EGLImageKHR egl_image, int32 picture_id)
+ : egl_image(egl_image), picture_id(picture_id) {}
EGLImageKHR egl_image;
- int egl_image_fd;
- int32 client_id;
+ int32 picture_id;
};
EGLDisplay const egl_display;
@@ -104,6 +98,13 @@ struct ExynosVideoDecodeAccelerator::EGLSyncKHRRef {
EGLSyncKHR egl_sync;
};
+struct ExynosVideoDecodeAccelerator::PictureRecord {
+ PictureRecord(bool cleared, const media::Picture& picture);
+ ~PictureRecord();
+ bool cleared; // Whether the texture is cleared and safe to render from.
+ media::Picture picture; // The decoded picture.
+};
+
ExynosVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef(
base::WeakPtr<Client>& client,
scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy,
@@ -124,24 +125,14 @@ ExynosVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() {
}
ExynosVideoDecodeAccelerator::PictureBufferArrayRef::PictureBufferArrayRef(
- EGLDisplay egl_display, size_t count)
- : egl_display(egl_display),
- picture_buffers(count) {
- for (size_t i = 0; i < picture_buffers.size(); ++i) {
- PictureBufferRef& buffer = picture_buffers[i];
- buffer.egl_image = EGL_NO_IMAGE_KHR;
- buffer.egl_image_fd = -1;
- buffer.client_id = -1;
- }
-}
+ EGLDisplay egl_display)
+ : egl_display(egl_display) {}
ExynosVideoDecodeAccelerator::PictureBufferArrayRef::~PictureBufferArrayRef() {
for (size_t i = 0; i < picture_buffers.size(); ++i) {
- PictureBufferRef& buffer = picture_buffers[i];
- if (buffer.egl_image != EGL_NO_IMAGE_KHR)
- eglDestroyImageKHR(egl_display, buffer.egl_image);
- if (buffer.egl_image_fd != -1)
- HANDLE_EINTR(close(buffer.egl_image_fd));
+ EGLImageKHR egl_image = picture_buffers[i].egl_image;
+ if (egl_image != EGL_NO_IMAGE_KHR)
+ eglDestroyImageKHR(egl_display, egl_image);
}
}
@@ -169,37 +160,23 @@ ExynosVideoDecodeAccelerator::MfcInputRecord::~MfcInputRecord() {
ExynosVideoDecodeAccelerator::MfcOutputRecord::MfcOutputRecord()
: at_device(false),
- input_id(-1) {
- bytes_used[0] = 0;
- bytes_used[1] = 0;
- address[0] = NULL;
- address[1] = NULL;
- length[0] = 0;
- length[1] = 0;
-}
-
-ExynosVideoDecodeAccelerator::MfcOutputRecord::~MfcOutputRecord() {
-}
-
-ExynosVideoDecodeAccelerator::GscInputRecord::GscInputRecord()
- : at_device(false),
- mfc_output(-1) {
-}
-
-ExynosVideoDecodeAccelerator::GscInputRecord::~GscInputRecord() {
-}
-
-ExynosVideoDecodeAccelerator::GscOutputRecord::GscOutputRecord()
- : at_device(false),
at_client(false),
- fd(-1),
egl_image(EGL_NO_IMAGE_KHR),
egl_sync(EGL_NO_SYNC_KHR),
- picture_id(-1) {
+ picture_id(-1),
+ cleared(false) {
+ for (size_t i = 0; i < arraysize(fds); ++i)
+ fds[i] = -1;
}
-ExynosVideoDecodeAccelerator::GscOutputRecord::~GscOutputRecord() {
-}
+ExynosVideoDecodeAccelerator::MfcOutputRecord::~MfcOutputRecord() {}
+
+ExynosVideoDecodeAccelerator::PictureRecord::PictureRecord(
+ bool cleared,
+ const media::Picture& picture)
+ : cleared(cleared), picture(picture) {}
+
+ExynosVideoDecodeAccelerator::PictureRecord::~PictureRecord() {}
ExynosVideoDecodeAccelerator::ExynosVideoDecodeAccelerator(
EGLDisplay egl_display,
@@ -231,37 +208,27 @@ ExynosVideoDecodeAccelerator::ExynosVideoDecodeAccelerator(
mfc_output_buffer_queued_count_(0),
mfc_output_buffer_pixelformat_(0),
mfc_output_dpb_size_(0),
- gsc_fd_(-1),
- gsc_input_streamon_(false),
- gsc_input_buffer_queued_count_(0),
- gsc_output_streamon_(false),
- gsc_output_buffer_queued_count_(0),
+ picture_clearing_count_(0),
+ pictures_assigned_(false, false),
device_poll_thread_("ExynosDevicePollThread"),
device_poll_interrupt_fd_(-1),
make_context_current_(make_context_current),
egl_display_(egl_display),
egl_context_(egl_context),
- video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {
-}
+ video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {}
ExynosVideoDecodeAccelerator::~ExynosVideoDecodeAccelerator() {
DCHECK(!decoder_thread_.IsRunning());
DCHECK(!device_poll_thread_.IsRunning());
if (device_poll_interrupt_fd_ != -1) {
- HANDLE_EINTR(close(device_poll_interrupt_fd_));
+ close(device_poll_interrupt_fd_);
device_poll_interrupt_fd_ = -1;
}
- if (gsc_fd_ != -1) {
- DestroyGscInputBuffers();
- DestroyGscOutputBuffers();
- HANDLE_EINTR(close(gsc_fd_));
- gsc_fd_ = -1;
- }
if (mfc_fd_ != -1) {
DestroyMfcInputBuffers();
DestroyMfcOutputBuffers();
- HANDLE_EINTR(close(mfc_fd_));
+ close(mfc_fd_);
mfc_fd_ = -1;
}
@@ -269,8 +236,6 @@ ExynosVideoDecodeAccelerator::~ExynosVideoDecodeAccelerator() {
// descriptors, mmap() segments, etc.
DCHECK(mfc_input_buffer_map_.empty());
DCHECK(mfc_output_buffer_map_.empty());
- DCHECK(gsc_input_buffer_map_.empty());
- DCHECK(gsc_output_buffer_map_.empty());
}
bool ExynosVideoDecodeAccelerator::Initialize(
@@ -298,13 +263,6 @@ bool ExynosVideoDecodeAccelerator::Initialize(
};
video_profile_ = profile;
- static bool sandbox_initialized = PostSandboxInitialization();
- if (!sandbox_initialized) {
- DLOG(ERROR) << "Initialize(): PostSandboxInitialization() failed";
- NOTIFY_ERROR(PLATFORM_FAILURE);
- return false;
- }
-
if (egl_display_ == EGL_NO_DISPLAY) {
DLOG(ERROR) << "Initialize(): could not get EGLDisplay";
NOTIFY_ERROR(PLATFORM_FAILURE);
@@ -340,15 +298,6 @@ bool ExynosVideoDecodeAccelerator::Initialize(
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
- DVLOG(2) << "Initialize(): opening GSC device: " << kExynosGscDevice;
- gsc_fd_ = HANDLE_EINTR(open(kExynosGscDevice,
- O_RDWR | O_NONBLOCK | O_CLOEXEC));
- if (gsc_fd_ == -1) {
- DPLOG(ERROR) << "Initialize(): could not open GSC device: "
- << kExynosGscDevice;
- NOTIFY_ERROR(PLATFORM_FAILURE);
- return false;
- }
// Create the interrupt fd.
DCHECK_EQ(device_poll_interrupt_fd_, -1);
@@ -372,20 +321,11 @@ bool ExynosVideoDecodeAccelerator::Initialize(
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_QUERYCAP, &caps);
- if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
- DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP"
- ", caps check failed: 0x" << std::hex << caps.capabilities;
- NOTIFY_ERROR(PLATFORM_FAILURE);
- return false;
- }
if (!CreateMfcInputBuffers())
return false;
// MFC output format has to be setup before streaming starts.
- // TODO(hshi): set format back to tiled (V4L2_PIX_FMT_NV12MT_16X16) when we
- // fix the underlying driver/firmware issue. http://crbug.com/303300.
struct v4l2_format format;
memset(&format, 0, sizeof(format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
@@ -434,77 +374,79 @@ void ExynosVideoDecodeAccelerator::AssignPictureBuffers(
DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size();
DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
- if (buffers.size() != gsc_output_buffer_map_.size()) {
+ if (buffers.size() != mfc_output_buffer_map_.size()) {
DLOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture"
- " buffers. (Got " << buffers.size() << ", requested " <<
- gsc_output_buffer_map_.size() << ")";
+ " buffers. (Got " << buffers.size()
+ << ", requested " << mfc_output_buffer_map_.size() << ")";
NOTIFY_ERROR(INVALID_ARGUMENT);
return;
}
- for (size_t i = 0; i < buffers.size(); ++i) {
- if (buffers[i].size() != frame_buffer_size_) {
- DLOG(ERROR) << "AssignPictureBuffers(): invalid buffer size";
- NOTIFY_ERROR(INVALID_ARGUMENT);
- return;
- }
- }
-
if (!make_context_current_.Run()) {
DLOG(ERROR) << "AssignPictureBuffers(): could not make context current";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
- scoped_ptr<PictureBufferArrayRef> pic_buffers_ref(
- new PictureBufferArrayRef(egl_display_, buffers.size()));
-
- const static EGLint kImageAttrs[] = {
- EGL_IMAGE_PRESERVED_KHR, 0,
- EGL_NONE,
- };
- Display* x_display = base::MessagePumpForUI::GetDefaultXDisplay();
- gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_2D, 0);
- for (size_t i = 0; i < pic_buffers_ref->picture_buffers.size(); ++i) {
- PictureBufferArrayRef::PictureBufferRef& buffer =
- pic_buffers_ref->picture_buffers[i];
- // Create the X pixmap and then create an EGLImageKHR from it, so we can
- // get dma_buf backing.
- Pixmap pixmap = XCreatePixmap(x_display, RootWindow(x_display, 0),
- buffers[i].size().width(), buffers[i].size().height(), 32);
- if (!pixmap) {
- DLOG(ERROR) << "AssignPictureBuffers(): could not create X pixmap";
- NOTIFY_ERROR(PLATFORM_FAILURE);
- return;
- }
- glBindTexture(GL_TEXTURE_2D, buffers[i].texture_id());
+ // It's safe to manipulate all the buffer state here, because the decoder
+ // thread is waiting on pictures_assigned_.
+ scoped_ptr<PictureBufferArrayRef> picture_buffers_ref(
+ new PictureBufferArrayRef(egl_display_));
+ gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0);
+ EGLint attrs[] = {
+ EGL_WIDTH, 0, EGL_HEIGHT, 0,
+ EGL_LINUX_DRM_FOURCC_EXT, 0, EGL_DMA_BUF_PLANE0_FD_EXT, 0,
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, EGL_DMA_BUF_PLANE0_PITCH_EXT, 0,
+ EGL_DMA_BUF_PLANE1_FD_EXT, 0, EGL_DMA_BUF_PLANE1_OFFSET_EXT, 0,
+ EGL_DMA_BUF_PLANE1_PITCH_EXT, 0, EGL_NONE, };
+ attrs[1] = frame_buffer_size_.width();
+ attrs[3] = frame_buffer_size_.height();
+ attrs[5] = DRM_FORMAT_NV12;
+ for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) {
+ DCHECK(buffers[i].size() == frame_buffer_size_);
+ MfcOutputRecord& output_record = mfc_output_buffer_map_[i];
+ attrs[7] = output_record.fds[0];
+ attrs[9] = 0;
+ attrs[11] = frame_buffer_size_.width();
+ attrs[13] = output_record.fds[1];
+ attrs[15] = 0;
+ attrs[17] = frame_buffer_size_.width();
EGLImageKHR egl_image = eglCreateImageKHR(
- egl_display_, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
- (EGLClientBuffer)pixmap, kImageAttrs);
- // We can free the X pixmap immediately -- according to the
- // EGL_KHR_image_base spec, the backing storage does not go away until the
- // last referencing EGLImage is destroyed.
- XFreePixmap(x_display, pixmap);
+ egl_display_, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrs);
if (egl_image == EGL_NO_IMAGE_KHR) {
DLOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
- buffer.egl_image = egl_image;
- int fd;
- if (!mali_egl_image_get_buffer_ext_phandle(buffer.egl_image, NULL, &fd)) {
- DLOG(ERROR) << "AssignPictureBuffers(): "
- << "could not get EGLImageKHR dmabuf fd";
- NOTIFY_ERROR(PLATFORM_FAILURE);
- return;
- }
- buffer.egl_image_fd = fd;
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image);
- buffer.client_id = buffers[i].id();
+
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, buffers[i].texture_id());
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image);
+ picture_buffers_ref->picture_buffers.push_back(
+ PictureBufferArrayRef::PictureBufferRef(egl_image, buffers[i].id()));
}
- decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
- &ExynosVideoDecodeAccelerator::AssignPictureBuffersTask,
- base::Unretained(this), base::Passed(&pic_buffers_ref)));
+
+ DCHECK(mfc_free_output_buffers_.empty());
+ DCHECK_EQ(picture_buffers_ref->picture_buffers.size(),
+ mfc_output_buffer_map_.size());
+ for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) {
+ MfcOutputRecord& output_record = mfc_output_buffer_map_[i];
+ PictureBufferArrayRef::PictureBufferRef& buffer_ref =
+ picture_buffers_ref->picture_buffers[i];
+ // We should be blank right now.
+ DCHECK(!output_record.at_device);
+ DCHECK(!output_record.at_client);
+ DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR);
+ DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
+ DCHECK_EQ(output_record.picture_id, -1);
+ DCHECK_EQ(output_record.cleared, false);
+ output_record.egl_image = buffer_ref.egl_image;
+ output_record.picture_id = buffer_ref.picture_id;
+ mfc_free_output_buffers_.push(i);
+ DVLOG(3) << "AssignPictureBuffers(): buffer[" << i
+ << "]: picture_id=" << buffer_ref.picture_id;
+ }
+ picture_buffers_ref->picture_buffers.clear();
+ pictures_assigned_.Signal();
}
void ExynosVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
@@ -558,6 +500,7 @@ void ExynosVideoDecodeAccelerator::Destroy() {
if (decoder_thread_.IsRunning()) {
decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
&ExynosVideoDecodeAccelerator::DestroyTask, base::Unretained(this)));
+ pictures_assigned_.Signal();
// DestroyTask() will cause the decoder_thread_ to flush all tasks.
decoder_thread_.Stop();
} else {
@@ -573,39 +516,6 @@ void ExynosVideoDecodeAccelerator::Destroy() {
bool ExynosVideoDecodeAccelerator::CanDecodeOnIOThread() { return true; }
-// static
-void ExynosVideoDecodeAccelerator::PreSandboxInitialization() {
- DVLOG(3) << "PreSandboxInitialization()";
- dlerror();
-
- libmali_handle = dlopen(kMaliDriver, RTLD_LAZY | RTLD_LOCAL);
- if (libmali_handle == NULL) {
- DPLOG(ERROR) << "failed to dlopen() " << kMaliDriver << ": " << dlerror();
- }
-}
-
-// static
-bool ExynosVideoDecodeAccelerator::PostSandboxInitialization() {
- DVLOG(3) << "PostSandboxInitialization()";
- if (libmali_handle == NULL) {
- DLOG(ERROR) << "PostSandboxInitialization(): no " << kMaliDriver
- << " driver handle";
- return false;
- }
-
- dlerror();
- mali_egl_image_get_buffer_ext_phandle =
- reinterpret_cast<MaliEglImageGetBufferExtPhandleFunc>(
- dlsym(libmali_handle, "mali_egl_image_get_buffer_ext_phandle"));
- if (mali_egl_image_get_buffer_ext_phandle == NULL) {
- DPLOG(ERROR) << "PostSandboxInitialization(): failed to dlsym() "
- << "mali_egl_image_get_buffer_ext_phandle: " << dlerror();
- return false;
- }
-
- return true;
-}
-
void ExynosVideoDecodeAccelerator::DecodeTask(
const media::BitstreamBuffer& bitstream_buffer) {
DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id();
@@ -623,7 +533,7 @@ void ExynosVideoDecodeAccelerator::DecodeTask(
NOTIFY_ERROR(UNREADABLE_INPUT);
return;
}
- DVLOG(3) << "Decode(): mapped to addr=" << bitstream_record->shm->memory();
+ DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory();
if (decoder_state_ == kResetting || decoder_flushing_) {
// In the case that we're resetting or flushing, we need to delay decoding
@@ -638,7 +548,7 @@ void ExynosVideoDecodeAccelerator::DecodeTask(
return;
}
- decoder_input_queue_.push_back(
+ decoder_input_queue_.push(
linked_ptr<BitstreamBufferRef>(bitstream_record.release()));
decoder_decode_buffer_tasks_scheduled_++;
DecodeBufferTask();
@@ -676,7 +586,7 @@ void ExynosVideoDecodeAccelerator::DecodeBufferTask() {
// Setup to use the next buffer.
decoder_current_bitstream_buffer_.reset(buffer_ref.release());
- decoder_input_queue_.pop_front();
+ decoder_input_queue_.pop();
DVLOG(3) << "DecodeBufferTask(): reading input_id="
<< decoder_current_bitstream_buffer_->input_id
<< ", addr=" << (decoder_current_bitstream_buffer_->shm ?
@@ -1028,7 +938,7 @@ bool ExynosVideoDecodeAccelerator::FlushInputFrame() {
}
// Queue it to MFC.
- mfc_input_ready_queue_.push_back(decoder_current_input_buffer_);
+ mfc_input_ready_queue_.push(decoder_current_input_buffer_);
decoder_current_input_buffer_ = -1;
DVLOG(3) << "FlushInputFrame(): submitting input_id="
<< input_record.input_id;
@@ -1038,47 +948,6 @@ bool ExynosVideoDecodeAccelerator::FlushInputFrame() {
return (decoder_state_ != kError);
}
-void ExynosVideoDecodeAccelerator::AssignPictureBuffersTask(
- scoped_ptr<PictureBufferArrayRef> pic_buffers) {
- DVLOG(3) << "AssignPictureBuffersTask()";
- DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
- DCHECK_NE(decoder_state_, kUninitialized);
- TRACE_EVENT0("Video Decoder", "EVDA::AssignPictureBuffersTask");
-
- // We run AssignPictureBuffersTask even if we're in kResetting.
- if (decoder_state_ == kError) {
- DVLOG(2) << "AssignPictureBuffersTask(): early out: kError state";
- return;
- }
-
- DCHECK_EQ(pic_buffers->picture_buffers.size(), gsc_output_buffer_map_.size());
- for (size_t i = 0; i < gsc_output_buffer_map_.size(); ++i) {
- // We should be blank right now.
- GscOutputRecord& output_record = gsc_output_buffer_map_[i];
- DCHECK_EQ(output_record.fd, -1);
- DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR);
- DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
- DCHECK_EQ(output_record.picture_id, -1);
- PictureBufferArrayRef::PictureBufferRef& buffer =
- pic_buffers->picture_buffers[i];
- output_record.fd = buffer.egl_image_fd;
- output_record.egl_image = buffer.egl_image;
- output_record.picture_id = buffer.client_id;
-
- // Take ownership of the EGLImage and fd.
- buffer.egl_image = EGL_NO_IMAGE_KHR;
- buffer.egl_image_fd = -1;
- // And add this buffer to the free list.
- gsc_free_output_buffers_.push_back(i);
- }
-
- // We got buffers! Kick the GSC.
- EnqueueGsc();
-
- if (decoder_state_ == kChangingResolution)
- ResumeAfterResolutionChange();
-}
-
void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool mfc_event_pending) {
DVLOG(3) << "ServiceDeviceTask()";
DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
@@ -1101,9 +970,7 @@ void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool mfc_event_pending) {
if (mfc_event_pending)
DequeueMfcEvents();
DequeueMfc();
- DequeueGsc();
EnqueueMfc();
- EnqueueGsc();
// Clear the interrupt fd.
if (!ClearDevicePollInterrupt())
@@ -1114,10 +981,6 @@ void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool mfc_event_pending) {
// MFC can be polled as soon as either input or output buffers are queued.
if (mfc_input_buffer_queued_count_ + mfc_output_buffer_queued_count_ > 0)
poll_fds |= kPollMfc;
- // Add GSC fd, if we should poll on it.
- // GSC has to wait until both input and output buffers are queued.
- if (gsc_input_buffer_queued_count_ > 0 && gsc_output_buffer_queued_count_ > 0)
- poll_fds |= kPollGsc;
// ServiceDeviceTask() should only ever be scheduled from DevicePollTask(),
// so either:
@@ -1140,14 +1003,7 @@ void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool mfc_event_pending) {
<< mfc_input_buffer_map_.size() << "->"
<< mfc_free_output_buffers_.size() << "+"
<< mfc_output_buffer_queued_count_ << "/"
- << mfc_output_buffer_map_.size() << "] => "
- << mfc_output_gsc_input_queue_.size() << " => GSC["
- << gsc_free_input_buffers_.size() << "+"
- << gsc_input_buffer_queued_count_ << "/"
- << gsc_input_buffer_map_.size() << "->"
- << gsc_free_output_buffers_.size() << "+"
- << gsc_output_buffer_queued_count_ << "/"
- << gsc_output_buffer_map_.size() << "] => VDA["
+ << mfc_output_buffer_map_.size() << "] => VDA["
<< decoder_frames_at_client_ << "]";
ScheduleDecodeBufferTaskIfNeeded();
@@ -1201,7 +1057,7 @@ void ExynosVideoDecodeAccelerator::EnqueueMfc() {
void ExynosVideoDecodeAccelerator::DequeueMfcEvents() {
DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
- DCHECK_EQ(decoder_state_, kDecoding);
+ DCHECK_NE(decoder_state_, kUninitialized);
DVLOG(3) << "DequeueMfcEvents()";
struct v4l2_event ev;
@@ -1276,24 +1132,25 @@ void ExynosVideoDecodeAccelerator::DequeueMfc() {
}
MfcOutputRecord& output_record = mfc_output_buffer_map_[dqbuf.index];
DCHECK(output_record.at_device);
+ DCHECK(!output_record.at_client);
+ DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR);
+ DCHECK_NE(output_record.picture_id, -1);
output_record.at_device = false;
- output_record.bytes_used[0] = dqbuf.m.planes[0].bytesused;
- output_record.bytes_used[1] = dqbuf.m.planes[1].bytesused;
- if (output_record.bytes_used[0] + output_record.bytes_used[1] == 0) {
+ if (dqbuf.m.planes[0].bytesused + dqbuf.m.planes[1].bytesused == 0) {
// This is an empty output buffer returned as part of a flush.
- mfc_free_output_buffers_.push_back(dqbuf.index);
- output_record.input_id = -1;
+ mfc_free_output_buffers_.push(dqbuf.index);
} else {
- // This is an output buffer with contents to pass down the pipe.
- mfc_output_gsc_input_queue_.push_back(dqbuf.index);
- output_record.input_id = dqbuf.timestamp.tv_sec;
- DCHECK(output_record.input_id >= 0);
- DVLOG(3) << "DequeueMfc(): dequeued input_id=" << output_record.input_id;
- // We don't count this output buffer dequeued yet, or add it to the free
- // list, as it has data GSC needs to process.
-
- // We have new frames in mfc_output_gsc_input_queue_. Kick the pipe.
- SetDevicePollInterrupt();
+ DCHECK_GE(dqbuf.timestamp.tv_sec, 0);
+ output_record.at_client = true;
+ DVLOG(3) << "DequeueMfc(): returning input_id=" << dqbuf.timestamp.tv_sec
+ << " as picture_id=" << output_record.picture_id;
+ const media::Picture& picture =
+ media::Picture(output_record.picture_id, dqbuf.timestamp.tv_sec);
+ pending_picture_ready_.push(
+ PictureRecord(output_record.cleared, picture));
+ SendPictureReady();
+ output_record.cleared = true;
+ decoder_frames_at_client_++;
}
mfc_output_buffer_queued_count_--;
}
@@ -1301,142 +1158,12 @@ void ExynosVideoDecodeAccelerator::DequeueMfc() {
NotifyFlushDoneIfNeeded();
}
-void ExynosVideoDecodeAccelerator::EnqueueGsc() {
- DVLOG(3) << "EnqueueGsc()";
- DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
- DCHECK_NE(decoder_state_, kUninitialized);
- DCHECK_NE(decoder_state_, kInitialized);
- TRACE_EVENT0("Video Decoder", "EVDA::EnqueueGsc");
-
- // Drain the pipe of completed MFC output buffers.
- const int old_gsc_inputs_queued = gsc_input_buffer_queued_count_;
- while (!mfc_output_gsc_input_queue_.empty() &&
- !gsc_free_input_buffers_.empty()) {
- if (!EnqueueGscInputRecord())
- return;
- }
- if (old_gsc_inputs_queued == 0 && gsc_input_buffer_queued_count_ != 0) {
- // We just started up a previously empty queue.
- // Queue state changed; signal interrupt.
- if (!SetDevicePollInterrupt())
- return;
- // Start VIDIOC_STREAMON if we haven't yet.
- if (!gsc_input_streamon_) {
- __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- IOCTL_OR_ERROR_RETURN(gsc_fd_, VIDIOC_STREAMON, &type);
- gsc_input_streamon_ = true;
- }
- }
-
- if (gsc_input_buffer_queued_count_ != 0 &&
- gsc_output_buffer_queued_count_ == 0 &&
- !gsc_free_output_buffers_.empty()) {
- const int old_gsc_outputs_queued = gsc_output_buffer_queued_count_;
- if (!EnqueueGscOutputRecord())
- return;
- if (old_gsc_outputs_queued == 0 && gsc_output_buffer_queued_count_ != 0) {
- // We just started up a previously empty queue.
- // Queue state changed; signal interrupt.
- if (!SetDevicePollInterrupt())
- return;
- // Start VIDIOC_STREAMON if we haven't yet.
- if (!gsc_output_streamon_) {
- __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- IOCTL_OR_ERROR_RETURN(gsc_fd_, VIDIOC_STREAMON, &type);
- gsc_output_streamon_ = true;
- }
- }
- }
- // Bug check: GSC is liable to race conditions if more than one buffer is
- // simultaneously queued.
- DCHECK_GE(1, gsc_output_buffer_queued_count_);
-}
-
-void ExynosVideoDecodeAccelerator::DequeueGsc() {
- DVLOG(3) << "DequeueGsc()";
- DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
- DCHECK_NE(decoder_state_, kUninitialized);
- DCHECK_NE(decoder_state_, kInitialized);
- DCHECK_NE(decoder_state_, kAfterReset);
- TRACE_EVENT0("Video Decoder", "EVDA::DequeueGsc");
-
- // Dequeue completed GSC input (VIDEO_OUTPUT) buffers, and recycle to the free
- // list. Also recycle the corresponding MFC output buffers at this time.
- struct v4l2_buffer dqbuf;
- struct v4l2_plane planes[2];
- while (gsc_input_buffer_queued_count_ > 0) {
- DCHECK(gsc_input_streamon_);
- memset(&dqbuf, 0, sizeof(dqbuf));
- memset(planes, 0, sizeof(planes));
- dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- dqbuf.memory = V4L2_MEMORY_DMABUF;
- dqbuf.m.planes = planes;
- dqbuf.length = 2;
- if (ioctl(gsc_fd_, VIDIOC_DQBUF, &dqbuf) != 0) {
- if (errno == EAGAIN) {
- // EAGAIN if we're just out of buffers to dequeue.
- break;
- }
- DPLOG(ERROR) << "DequeueGsc(): ioctl() failed: VIDIOC_DQBUF";
- NOTIFY_ERROR(PLATFORM_FAILURE);
- return;
- }
- GscInputRecord& input_record = gsc_input_buffer_map_[dqbuf.index];
- MfcOutputRecord& output_record =
- mfc_output_buffer_map_[input_record.mfc_output];
- DCHECK(input_record.at_device);
- gsc_free_input_buffers_.push_back(dqbuf.index);
- mfc_free_output_buffers_.push_back(input_record.mfc_output);
- input_record.at_device = false;
- input_record.mfc_output = -1;
- output_record.input_id = -1;
- gsc_input_buffer_queued_count_--;
- }
-
- // Dequeue completed GSC output (VIDEO_CAPTURE) buffers, and send them off to
- // the client. Don't recycle to its free list yet -- we can't do that until
- // ReusePictureBuffer() returns it to us.
- while (gsc_output_buffer_queued_count_ > 0) {
- DCHECK(gsc_output_streamon_);
- memset(&dqbuf, 0, sizeof(dqbuf));
- memset(planes, 0, sizeof(planes));
- dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- dqbuf.memory = V4L2_MEMORY_DMABUF;
- dqbuf.m.planes = planes;
- dqbuf.length = 1;
- if (ioctl(gsc_fd_, VIDIOC_DQBUF, &dqbuf) != 0) {
- if (errno == EAGAIN) {
- // EAGAIN if we're just out of buffers to dequeue.
- break;
- }
- DPLOG(ERROR) << "DequeueGsc(): ioctl() failed: VIDIOC_DQBUF";
- NOTIFY_ERROR(PLATFORM_FAILURE);
- return;
- }
- GscOutputRecord& output_record = gsc_output_buffer_map_[dqbuf.index];
- DCHECK(output_record.at_device);
- DCHECK(!output_record.at_client);
- DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
- output_record.at_device = false;
- output_record.at_client = true;
- gsc_output_buffer_queued_count_--;
- DVLOG(3) << "DequeueGsc(): returning input_id=" << dqbuf.timestamp.tv_sec
- << " as picture_id=" << output_record.picture_id;
- io_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &Client::PictureReady, io_client_, media::Picture(
- output_record.picture_id, dqbuf.timestamp.tv_sec)));
- decoder_frames_at_client_++;
- }
-
- NotifyFlushDoneIfNeeded();
-}
-
bool ExynosVideoDecodeAccelerator::EnqueueMfcInputRecord() {
DVLOG(3) << "EnqueueMfcInputRecord()";
DCHECK(!mfc_input_ready_queue_.empty());
// Enqueue a MFC input (VIDEO_OUTPUT) buffer.
- const int buffer = mfc_input_ready_queue_.back();
+ const int buffer = mfc_input_ready_queue_.front();
MfcInputRecord& input_record = mfc_input_buffer_map_[buffer];
DCHECK(!input_record.at_device);
struct v4l2_buffer qbuf;
@@ -1451,11 +1178,11 @@ bool ExynosVideoDecodeAccelerator::EnqueueMfcInputRecord() {
qbuf.m.planes[0].bytesused = input_record.bytes_used;
qbuf.length = 1;
IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QBUF, &qbuf);
- mfc_input_ready_queue_.pop_back();
+ mfc_input_ready_queue_.pop();
input_record.at_device = true;
mfc_input_buffer_queued_count_++;
DVLOG(3) << "EnqueueMfcInputRecord(): enqueued input_id="
- << input_record.input_id;
+ << input_record.input_id << " size=" << input_record.bytes_used;
return true;
}
@@ -1464,83 +1191,17 @@ bool ExynosVideoDecodeAccelerator::EnqueueMfcOutputRecord() {
DCHECK(!mfc_free_output_buffers_.empty());
// Enqueue a MFC output (VIDEO_CAPTURE) buffer.
- const int buffer = mfc_free_output_buffers_.back();
+ const int buffer = mfc_free_output_buffers_.front();
MfcOutputRecord& output_record = mfc_output_buffer_map_[buffer];
DCHECK(!output_record.at_device);
- DCHECK_EQ(output_record.input_id, -1);
- struct v4l2_buffer qbuf;
- struct v4l2_plane qbuf_planes[2];
- memset(&qbuf, 0, sizeof(qbuf));
- memset(qbuf_planes, 0, sizeof(qbuf_planes));
- qbuf.index = buffer;
- qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- qbuf.memory = V4L2_MEMORY_MMAP;
- qbuf.m.planes = qbuf_planes;
- qbuf.length = 2;
- IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QBUF, &qbuf);
- mfc_free_output_buffers_.pop_back();
- output_record.at_device = true;
- mfc_output_buffer_queued_count_++;
- return true;
-}
-
-bool ExynosVideoDecodeAccelerator::EnqueueGscInputRecord() {
- DVLOG(3) << "EnqueueGscInputRecord()";
- DCHECK(!gsc_free_input_buffers_.empty());
-
- // Enqueue a GSC input (VIDEO_OUTPUT) buffer for a complete MFC output
- // (VIDEO_CAPTURE) buffer.
- const int mfc_buffer = mfc_output_gsc_input_queue_.front();
- const int gsc_buffer = gsc_free_input_buffers_.back();
- MfcOutputRecord& output_record = mfc_output_buffer_map_[mfc_buffer];
- DCHECK(!output_record.at_device);
- GscInputRecord& input_record = gsc_input_buffer_map_[gsc_buffer];
- DCHECK(!input_record.at_device);
- DCHECK_EQ(input_record.mfc_output, -1);
- struct v4l2_buffer qbuf;
- struct v4l2_plane qbuf_planes[2];
- memset(&qbuf, 0, sizeof(qbuf));
- memset(qbuf_planes, 0, sizeof(qbuf_planes));
- qbuf.index = gsc_buffer;
- qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- qbuf.timestamp.tv_sec = output_record.input_id;
- qbuf.memory = V4L2_MEMORY_USERPTR;
- qbuf.m.planes = qbuf_planes;
- qbuf.m.planes[0].bytesused = output_record.bytes_used[0];
- qbuf.m.planes[0].length = mfc_output_buffer_size_[0];
- qbuf.m.planes[0].m.userptr = (unsigned long)output_record.address[0];
- qbuf.m.planes[1].bytesused = output_record.bytes_used[1];
- qbuf.m.planes[1].length = mfc_output_buffer_size_[1];
- qbuf.m.planes[1].m.userptr = (unsigned long)output_record.address[1];
- qbuf.length = 2;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_QBUF, &qbuf);
- mfc_output_gsc_input_queue_.pop_front();
- gsc_free_input_buffers_.pop_back();
- input_record.at_device = true;
- input_record.mfc_output = mfc_buffer;
- output_record.bytes_used[0] = 0;
- output_record.bytes_used[1] = 0;
- gsc_input_buffer_queued_count_++;
- DVLOG(3) << "EnqueueGscInputRecord(): enqueued input_id="
- << output_record.input_id;
- return true;
-}
-
-bool ExynosVideoDecodeAccelerator::EnqueueGscOutputRecord() {
- DVLOG(3) << "EnqueueGscOutputRecord()";
- DCHECK(!gsc_free_output_buffers_.empty());
-
- // Enqueue a GSC output (VIDEO_CAPTURE) buffer.
- const int buffer = gsc_free_output_buffers_.front();
- GscOutputRecord& output_record = gsc_output_buffer_map_[buffer];
- DCHECK(!output_record.at_device);
DCHECK(!output_record.at_client);
+ DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR);
+ DCHECK_NE(output_record.picture_id, -1);
if (output_record.egl_sync != EGL_NO_SYNC_KHR) {
- TRACE_EVENT0(
- "Video Decoder",
- "EVDA::EnqueueGscOutputRecord: eglClientWaitSyncKHR");
+ TRACE_EVENT0("Video Decoder",
+ "EVDA::EnqueueMfcOutputRecord: eglClientWaitSyncKHR");
// If we have to wait for completion, wait. Note that
- // gsc_free_output_buffers_ is a FIFO queue, so we always wait on the
+ // mfc_free_output_buffers_ is a FIFO queue, so we always wait on the
// buffer that has been in the queue the longest.
eglClientWaitSyncKHR(egl_display_, output_record.egl_sync, 0,
EGL_FOREVER_KHR);
@@ -1548,19 +1209,18 @@ bool ExynosVideoDecodeAccelerator::EnqueueGscOutputRecord() {
output_record.egl_sync = EGL_NO_SYNC_KHR;
}
struct v4l2_buffer qbuf;
- struct v4l2_plane qbuf_plane;
+ struct v4l2_plane qbuf_planes[arraysize(output_record.fds)];
memset(&qbuf, 0, sizeof(qbuf));
- memset(&qbuf_plane, 0, sizeof(qbuf_plane));
- qbuf.index = buffer;
- qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- qbuf.memory = V4L2_MEMORY_DMABUF;
- qbuf.m.planes = &qbuf_plane;
- qbuf.m.planes[0].m.fd = output_record.fd;
- qbuf.length = 1;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_QBUF, &qbuf);
- gsc_free_output_buffers_.pop_front();
+ memset(qbuf_planes, 0, sizeof(qbuf_planes));
+ qbuf.index = buffer;
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.m.planes = qbuf_planes;
+ qbuf.length = arraysize(output_record.fds);
+ IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QBUF, &qbuf);
+ mfc_free_output_buffers_.pop();
output_record.at_device = true;
- gsc_output_buffer_queued_count_++;
+ mfc_output_buffer_queued_count_++;
return true;
}
@@ -1583,17 +1243,22 @@ void ExynosVideoDecodeAccelerator::ReusePictureBufferTask(
}
size_t index;
- for (index = 0; index < gsc_output_buffer_map_.size(); ++index)
- if (gsc_output_buffer_map_[index].picture_id == picture_buffer_id)
+ for (index = 0; index < mfc_output_buffer_map_.size(); ++index)
+ if (mfc_output_buffer_map_[index].picture_id == picture_buffer_id)
break;
- if (index >= gsc_output_buffer_map_.size()) {
- DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not found";
- NOTIFY_ERROR(INVALID_ARGUMENT);
+ if (index >= mfc_output_buffer_map_.size()) {
+ // It's possible that we've already posted a DismissPictureBuffer for this
+ // picture, but it has not yet executed when this ReusePictureBuffer was
+ // posted to us by the client. In that case just ignore this (we've already
+ // dismissed it and accounted for that) and let the sync object get
+ // destroyed.
+ DVLOG(4) << "ReusePictureBufferTask(): got picture id= "
+ << picture_buffer_id << " not in use (anymore?).";
return;
}
- GscOutputRecord& output_record = gsc_output_buffer_map_[index];
+ MfcOutputRecord& output_record = mfc_output_buffer_map_[index];
if (output_record.at_device || !output_record.at_client) {
DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not reusable";
NOTIFY_ERROR(INVALID_ARGUMENT);
@@ -1601,14 +1266,15 @@ void ExynosVideoDecodeAccelerator::ReusePictureBufferTask(
}
DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
+ DCHECK(!output_record.at_device);
output_record.at_client = false;
output_record.egl_sync = egl_sync_ref->egl_sync;
- gsc_free_output_buffers_.push_back(index);
+ mfc_free_output_buffers_.push(index);
decoder_frames_at_client_--;
// Take ownership of the EGLSync.
egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR;
- // We got a buffer back, so kick the GSC.
- EnqueueGsc();
+ // We got a buffer back, so kick the MFC.
+ EnqueueMfc();
}
void ExynosVideoDecodeAccelerator::FlushTask() {
@@ -1620,8 +1286,8 @@ void ExynosVideoDecodeAccelerator::FlushTask() {
if (decoder_state_ == kInitialized || decoder_state_ == kAfterReset) {
// There's nothing in the pipe, so return done immediately.
DVLOG(3) << "FlushTask(): returning flush";
- child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &Client::NotifyFlushDone, client_));
+ child_message_loop_proxy_->PostTask(
+ FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_));
return;
} else if (decoder_state_ == kError) {
DVLOG(2) << "FlushTask(): early out: kError state";
@@ -1632,10 +1298,11 @@ void ExynosVideoDecodeAccelerator::FlushTask() {
DCHECK(!decoder_flushing_);
// Queue up an empty buffer -- this triggers the flush.
- decoder_input_queue_.push_back(linked_ptr<BitstreamBufferRef>(
- new BitstreamBufferRef(io_client_, io_message_loop_proxy_, NULL, 0,
- kFlushBufferId)));
+ decoder_input_queue_.push(
+ linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef(
+ io_client_, io_message_loop_proxy_, NULL, 0, kFlushBufferId)));
decoder_flushing_ = true;
+ SendPictureReady(); // Send all pending PictureReady.
ScheduleDecodeBufferTaskIfNeeded();
}
@@ -1649,8 +1316,6 @@ void ExynosVideoDecodeAccelerator::NotifyFlushDoneIfNeeded() {
// * There is no currently filling input buffer.
// * MFC input holding queue is empty.
// * All MFC input (VIDEO_OUTPUT) buffers are returned.
- // * MFC -> GSC holding queue is empty.
- // * All GSC input (VIDEO_OUTPUT) buffers are returned.
if (!decoder_input_queue_.empty()) {
if (decoder_input_queue_.front()->input_id !=
decoder_delay_bitstream_buffer_id_)
@@ -1658,9 +1323,7 @@ void ExynosVideoDecodeAccelerator::NotifyFlushDoneIfNeeded() {
}
if (decoder_current_input_buffer_ != -1)
return;
- if ((mfc_input_ready_queue_.size() +
- mfc_input_buffer_queued_count_ + mfc_output_gsc_input_queue_.size() +
- gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ ) != 0)
+ if ((mfc_input_ready_queue_.size() + mfc_input_buffer_queued_count_) != 0)
return;
// TODO(posciak): crbug.com/270039. MFC requires a streamoff-streamon
@@ -1681,8 +1344,8 @@ void ExynosVideoDecodeAccelerator::NotifyFlushDoneIfNeeded() {
decoder_delay_bitstream_buffer_id_ = -1;
decoder_flushing_ = false;
DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush";
- child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &Client::NotifyFlushDone, client_));
+ child_message_loop_proxy_->PostTask(
+ FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_));
// While we were flushing, we early-outed DecodeBufferTask()s.
ScheduleDecodeBufferTaskIfNeeded();
@@ -1714,11 +1377,9 @@ void ExynosVideoDecodeAccelerator::ResetTask() {
if (!StopDevicePoll(false))
return;
- DequeueMfcEvents();
-
- resolution_change_pending_ = false;
decoder_current_bitstream_buffer_.reset();
- decoder_input_queue_.clear();
+ while (!decoder_input_queue_.empty())
+ decoder_input_queue_.pop();
decoder_current_input_buffer_ = -1;
@@ -1729,6 +1390,7 @@ void ExynosVideoDecodeAccelerator::ResetTask() {
// Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening
// jobs will early-out in the kResetting state.
decoder_state_ = kResetting;
+ SendPictureReady(); // Send all pending PictureReady.
decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
&ExynosVideoDecodeAccelerator::ResetDoneTask, base::Unretained(this)));
}
@@ -1743,6 +1405,12 @@ void ExynosVideoDecodeAccelerator::ResetDoneTask() {
return;
}
+ // We might have received a resolution change event while we were waiting
+ // for the reset to finish. The codec will not post another event if the
+ // resolution after reset remains the same as the one to which were just
+ // about to switch, so preserve the event across reset so we can address
+ // it after resuming.
+
// Reset format-specific bits.
if (video_profile_ >= media::H264PROFILE_MIN &&
video_profile_ <= media::H264PROFILE_MAX) {
@@ -1751,7 +1419,14 @@ void ExynosVideoDecodeAccelerator::ResetDoneTask() {
// Jobs drained, we're finished resetting.
DCHECK_EQ(decoder_state_, kResetting);
- decoder_state_ = kAfterReset;
+ if (mfc_output_buffer_map_.empty()) {
+ // We must have gotten Reset() before we had a chance to request buffers
+ // from the client.
+ decoder_state_ = kInitialized;
+ } else {
+ decoder_state_ = kAfterReset;
+ }
+
decoder_partial_frame_pending_ = false;
decoder_delay_bitstream_buffer_id_ = -1;
child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
@@ -1774,7 +1449,8 @@ void ExynosVideoDecodeAccelerator::DestroyTask() {
decoder_current_input_buffer_ = -1;
decoder_decode_buffer_tasks_scheduled_ = 0;
decoder_frames_at_client_ = 0;
- decoder_input_queue_.clear();
+ while (!decoder_input_queue_.empty())
+ decoder_input_queue_.pop();
decoder_flushing_ = false;
// Set our state to kError. Just in case.
@@ -1802,7 +1478,8 @@ bool ExynosVideoDecodeAccelerator::StartDevicePoll() {
bool ExynosVideoDecodeAccelerator::StopDevicePoll(bool keep_mfc_input_state) {
DVLOG(3) << "StopDevicePoll()";
- DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ if (decoder_thread_.IsRunning())
+ DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
// Signal the DevicePollTask() to stop, and stop the device poll thread.
if (!SetDevicePollInterrupt())
@@ -1825,20 +1502,11 @@ bool ExynosVideoDecodeAccelerator::StopDevicePoll(bool keep_mfc_input_state) {
IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type);
}
mfc_output_streamon_ = false;
- if (gsc_input_streamon_) {
- __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type);
- }
- gsc_input_streamon_ = false;
- if (gsc_output_streamon_) {
- __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type);
- }
- gsc_output_streamon_ = false;
// Reset all our accounting info.
if (!keep_mfc_input_state) {
- mfc_input_ready_queue_.clear();
+ while (!mfc_input_ready_queue_.empty())
+ mfc_input_ready_queue_.pop();
mfc_free_input_buffers_.clear();
for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) {
mfc_free_input_buffers_.push_back(i);
@@ -1848,30 +1516,25 @@ bool ExynosVideoDecodeAccelerator::StopDevicePoll(bool keep_mfc_input_state) {
}
mfc_input_buffer_queued_count_ = 0;
}
- mfc_free_output_buffers_.clear();
+
+ while (!mfc_free_output_buffers_.empty())
+ mfc_free_output_buffers_.pop();
+
for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) {
- mfc_free_output_buffers_.push_back(i);
+ MfcOutputRecord& output_record = mfc_output_buffer_map_[i];
+ DCHECK(!(output_record.at_client && output_record.at_device));
+
+ // After streamoff, the device drops ownership of all buffers, even if
+ // we don't dequeue them explicitly.
mfc_output_buffer_map_[i].at_device = false;
- mfc_output_buffer_map_[i].input_id = -1;
- }
- mfc_output_buffer_queued_count_ = 0;
- mfc_output_gsc_input_queue_.clear();
- gsc_free_input_buffers_.clear();
- for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) {
- gsc_free_input_buffers_.push_back(i);
- gsc_input_buffer_map_[i].at_device = false;
- gsc_input_buffer_map_[i].mfc_output = -1;
- }
- gsc_input_buffer_queued_count_ = 0;
- gsc_free_output_buffers_.clear();
- for (size_t i = 0; i < gsc_output_buffer_map_.size(); ++i) {
- // Only mark those free that aren't being held by the VDA.
- if (!gsc_output_buffer_map_[i].at_client) {
- gsc_free_output_buffers_.push_back(i);
- gsc_output_buffer_map_[i].at_device = false;
+ // Some of them may still be owned by the client however.
+ // Reuse only those that aren't.
+ if (!output_record.at_client) {
+ DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
+ mfc_free_output_buffers_.push(i);
}
}
- gsc_output_buffer_queued_count_ = 0;
+ mfc_output_buffer_queued_count_ = 0;
DVLOG(3) << "StopDevicePoll(): device poll stopped";
return true;
@@ -1915,13 +1578,7 @@ void ExynosVideoDecodeAccelerator::StartResolutionChangeIfNeeded() {
if (!resolution_change_pending_)
return;
- if (!mfc_output_gsc_input_queue_.empty() ||
- gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ > 0) {
- DVLOG(3) << "StartResolutionChangeIfNeeded(): waiting for GSC to finish.";
- return;
- }
-
- DVLOG(3) << "No more work for GSC, initiate resolution change";
+ DVLOG(3) << "No more work, initiate resolution change";
// Keep MFC input queue.
if (!StopDevicePoll(true))
@@ -1940,6 +1597,7 @@ void ExynosVideoDecodeAccelerator::StartResolutionChangeIfNeeded() {
void ExynosVideoDecodeAccelerator::FinishResolutionChange() {
DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK_EQ(decoder_state_, kChangingResolution);
DVLOG(3) << "FinishResolutionChange()";
if (decoder_state_ == kError) {
@@ -1962,8 +1620,7 @@ void ExynosVideoDecodeAccelerator::FinishResolutionChange() {
return;
}
- // From here we stay in kChangingResolution and wait for
- // AssignPictureBuffers() before we can resume.
+ ResumeAfterResolutionChange();
}
void ExynosVideoDecodeAccelerator::ResumeAfterResolutionChange() {
@@ -1982,7 +1639,6 @@ void ExynosVideoDecodeAccelerator::ResumeAfterResolutionChange() {
return;
EnqueueMfc();
- // Gsc will get enqueued in AssignPictureBuffersTask().
ScheduleDecodeBufferTaskIfNeeded();
}
@@ -2011,14 +1667,6 @@ void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) {
mfc_pollfd = nfds;
nfds++;
}
- // Add GSC fd, if we should poll on it.
- // GSC has to wait until both input and output buffers are queued.
- if (poll_fds & kPollGsc) {
- DVLOG(3) << "DevicePollTask(): adding GSC to poll() set";
- pollfds[nfds].fd = gsc_fd_;
- pollfds[nfds].events = POLLIN | POLLOUT | POLLERR;
- nfds++;
- }
// Poll it!
if (HANDLE_EINTR(poll(pollfds, nfds, -1)) == -1) {
@@ -2080,7 +1728,7 @@ bool ExynosVideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format,
*again = true;
return true;
} else {
- DPLOG(ERROR) << "DecodeBufferInitial(): ioctl() failed: VIDIOC_G_FMT";
+ DPLOG(ERROR) << __func__ << "(): ioctl() failed: VIDIOC_G_FMT";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -2095,15 +1743,12 @@ bool ExynosVideoDecodeAccelerator::CreateBuffersForFormat(
CHECK_EQ(format.fmt.pix_mp.num_planes, 2);
frame_buffer_size_.SetSize(
format.fmt.pix_mp.width, format.fmt.pix_mp.height);
- mfc_output_buffer_size_[0] = format.fmt.pix_mp.plane_fmt[0].sizeimage;
- mfc_output_buffer_size_[1] = format.fmt.pix_mp.plane_fmt[1].sizeimage;
mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12M);
DVLOG(3) << "CreateBuffersForFormat(): new resolution: "
<< frame_buffer_size_.ToString();
- if (!CreateMfcOutputBuffers() || !CreateGscInputBuffers() ||
- !CreateGscOutputBuffers())
+ if (!CreateMfcOutputBuffers())
return false;
return true;
@@ -2194,145 +1839,50 @@ bool ExynosVideoDecodeAccelerator::CreateMfcOutputBuffers() {
reqbufs.memory = V4L2_MEMORY_MMAP;
IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_REQBUFS, &reqbufs);
- // Fill our free-buffers list, and create DMABUFs from them.
+ // Create DMABUFs from output buffers.
mfc_output_buffer_map_.resize(reqbufs.count);
for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) {
- mfc_free_output_buffers_.push_back(i);
-
- // Query for the MEMORY_MMAP pointer.
- struct v4l2_plane planes[2];
- struct v4l2_buffer buffer;
- memset(&buffer, 0, sizeof(buffer));
- memset(planes, 0, sizeof(planes));
- buffer.index = i;
- buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- buffer.memory = V4L2_MEMORY_MMAP;
- buffer.m.planes = planes;
- buffer.length = 2;
- IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QUERYBUF, &buffer);
-
- // Get their user memory for GSC input.
- for (int j = 0; j < 2; ++j) {
- void* address = mmap(NULL, buffer.m.planes[j].length,
- PROT_READ | PROT_WRITE, MAP_SHARED, mfc_fd_,
- buffer.m.planes[j].m.mem_offset);
- if (address == MAP_FAILED) {
- DPLOG(ERROR) << "CreateMfcInputBuffers(): mmap() failed";
- return false;
- }
- mfc_output_buffer_map_[i].address[j] = address;
- mfc_output_buffer_map_[i].length[j] = buffer.m.planes[j].length;
+ MfcOutputRecord& output_record = mfc_output_buffer_map_[i];
+ for (size_t j = 0; j < arraysize(output_record.fds); ++j) {
+ // Export the DMABUF fd so we can export it as a texture.
+ struct v4l2_exportbuffer expbuf;
+ memset(&expbuf, 0, sizeof(expbuf));
+ expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ expbuf.index = i;
+ expbuf.plane = j;
+ expbuf.flags = O_CLOEXEC;
+ IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_EXPBUF, &expbuf);
+ output_record.fds[j] = expbuf.fd;
}
}
- return true;
-}
-
-bool ExynosVideoDecodeAccelerator::CreateGscInputBuffers() {
- DVLOG(3) << "CreateGscInputBuffers()";
- DCHECK(decoder_state_ == kInitialized ||
- decoder_state_ == kChangingResolution);
- DCHECK(!gsc_input_streamon_);
- DCHECK(gsc_input_buffer_map_.empty());
-
- struct v4l2_format format;
- memset(&format, 0, sizeof(format));
- format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- format.fmt.pix_mp.width = frame_buffer_size_.width();
- format.fmt.pix_mp.height = frame_buffer_size_.height();
- format.fmt.pix_mp.pixelformat = mfc_output_buffer_pixelformat_;
- format.fmt.pix_mp.plane_fmt[0].sizeimage = mfc_output_buffer_size_[0];
- format.fmt.pix_mp.plane_fmt[1].sizeimage = mfc_output_buffer_size_[1];
- // NV12MT_16X16 is a tiled format for which bytesperline doesn't make too much
- // sense. Convention seems to be to assume 8bpp for these tiled formats.
- format.fmt.pix_mp.plane_fmt[0].bytesperline = frame_buffer_size_.width();
- format.fmt.pix_mp.plane_fmt[1].bytesperline = frame_buffer_size_.width();
- format.fmt.pix_mp.num_planes = 2;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_FMT, &format);
-
- struct v4l2_control control;
- memset(&control, 0, sizeof(control));
- control.id = V4L2_CID_ROTATE;
- control.value = 0;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control);
-
- memset(&control, 0, sizeof(control));
- control.id = V4L2_CID_HFLIP;
- control.value = 0;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control);
-
- memset(&control, 0, sizeof(control));
- control.id = V4L2_CID_VFLIP;
- control.value = 0;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control);
-
- memset(&control, 0, sizeof(control));
- control.id = V4L2_CID_GLOBAL_ALPHA;
- control.value = 255;
- if (HANDLE_EINTR(ioctl(gsc_fd_, VIDIOC_S_CTRL, &control)) != 0) {
- memset(&control, 0, sizeof(control));
- control.id = V4L2_CID_ALPHA_COMPONENT;
- control.value = 255;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control);
- }
-
- struct v4l2_requestbuffers reqbufs;
- memset(&reqbufs, 0, sizeof(reqbufs));
- reqbufs.count = kGscInputBufferCount;
- reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- reqbufs.memory = V4L2_MEMORY_USERPTR;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_REQBUFS, &reqbufs);
-
- gsc_input_buffer_map_.resize(reqbufs.count);
- for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) {
- gsc_free_input_buffers_.push_back(i);
- gsc_input_buffer_map_[i].mfc_output = -1;
- }
-
- return true;
-}
-
-bool ExynosVideoDecodeAccelerator::CreateGscOutputBuffers() {
- DVLOG(3) << "CreateGscOutputBuffers()";
- DCHECK(decoder_state_ == kInitialized ||
- decoder_state_ == kChangingResolution);
- DCHECK(!gsc_output_streamon_);
- DCHECK(gsc_output_buffer_map_.empty());
-
- // GSC outputs into the EGLImages we create from the textures we are
- // assigned. Assume RGBA8888 format.
- struct v4l2_format format;
- memset(&format, 0, sizeof(format));
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- format.fmt.pix_mp.width = frame_buffer_size_.width();
- format.fmt.pix_mp.height = frame_buffer_size_.height();
- format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_RGB32;
- format.fmt.pix_mp.plane_fmt[0].sizeimage =
- frame_buffer_size_.width() * frame_buffer_size_.height() * 4;
- format.fmt.pix_mp.plane_fmt[0].bytesperline = frame_buffer_size_.width() * 4;
- format.fmt.pix_mp.num_planes = 1;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_FMT, &format);
-
- struct v4l2_requestbuffers reqbufs;
- memset(&reqbufs, 0, sizeof(reqbufs));
- reqbufs.count = mfc_output_dpb_size_ + kDpbOutputBufferExtraCount;
- reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- reqbufs.memory = V4L2_MEMORY_DMABUF;
- IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_REQBUFS, &reqbufs);
-
- // We don't actually fill in the freelist or the map here. That happens once
- // we have actual usable buffers, after AssignPictureBuffers();
- gsc_output_buffer_map_.resize(reqbufs.count);
-
- DVLOG(3) << "CreateGscOutputBuffers(): ProvidePictureBuffers(): "
- << "buffer_count=" << gsc_output_buffer_map_.size()
+ DVLOG(3) << "CreateMfcOutputBuffers(): ProvidePictureBuffers(): "
+ << "buffer_count=" << mfc_output_buffer_map_.size()
<< ", width=" << frame_buffer_size_.width()
<< ", height=" << frame_buffer_size_.height();
- child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
- &Client::ProvidePictureBuffers, client_, gsc_output_buffer_map_.size(),
- gfx::Size(frame_buffer_size_.width(), frame_buffer_size_.height()),
- GL_TEXTURE_2D));
+ child_message_loop_proxy_->PostTask(FROM_HERE,
+ base::Bind(&Client::ProvidePictureBuffers,
+ client_,
+ mfc_output_buffer_map_.size(),
+ frame_buffer_size_,
+ GL_TEXTURE_EXTERNAL_OES));
+
+ // Wait for the client to call AssignPictureBuffers() on the Child thread.
+ // We do this, because if we continue decoding without finishing buffer
+ // allocation, we may end up Resetting before AssignPictureBuffers arrives,
+ // resulting in unnecessary complications and subtle bugs.
+ // For example, if the client calls Decode(Input1), Reset(), Decode(Input2)
+ // in a sequence, and Decode(Input1) results in us getting here and exiting
+ // without waiting, we might end up running Reset{,Done}Task() before
+ // AssignPictureBuffers is scheduled, thus cleaning up and pushing buffers
+ // to the free_output_buffers_ map twice. If we somehow marked buffers as
+ // not ready, we'd need special handling for restarting the second Decode
+ // task and delaying it anyway.
+ // Waiting here is not very costly and makes reasoning about different
+ // situations much simpler.
+ pictures_assigned_.Wait();
+ EnqueueMfc();
return true;
}
@@ -2365,13 +1915,34 @@ void ExynosVideoDecodeAccelerator::DestroyMfcOutputBuffers() {
DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
DCHECK(!mfc_output_streamon_);
- for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) {
- if (mfc_output_buffer_map_[i].address[0] != NULL)
- munmap(mfc_output_buffer_map_[i].address[0],
- mfc_output_buffer_map_[i].length[0]);
- if (mfc_output_buffer_map_[i].address[1] != NULL)
- munmap(mfc_output_buffer_map_[i].address[1],
- mfc_output_buffer_map_[i].length[1]);
+ if (mfc_output_buffer_map_.size() != 0) {
+ // TODO(sheu, posciak): Making the context current should not be required
+ // anymore. Remove it and verify (crbug.com/327869).
+ if (!make_context_current_.Run()) {
+ DLOG(ERROR) << "DestroyMfcOutputBuffers(): "
+ << "could not make context current";
+ } else {
+ size_t i = 0;
+ do {
+ MfcOutputRecord& output_record = mfc_output_buffer_map_[i];
+ for (size_t j = 0; j < arraysize(output_record.fds); ++j) {
+ if (output_record.fds[j] != -1)
+ close(output_record.fds[j]);
+ if (output_record.egl_image != EGL_NO_IMAGE_KHR)
+ eglDestroyImageKHR(egl_display_, output_record.egl_image);
+ if (output_record.egl_sync != EGL_NO_SYNC_KHR)
+ eglDestroySyncKHR(egl_display_, output_record.egl_sync);
+ }
+ DVLOG(1) << "DestroyMfcOutputBuffers(): dismissing PictureBuffer id="
+ << output_record.picture_id;
+ child_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&Client::DismissPictureBuffer,
+ client_,
+ output_record.picture_id));
+ i++;
+ } while (i < mfc_output_buffer_map_.size());
+ }
}
struct v4l2_requestbuffers reqbufs;
@@ -2383,72 +1954,14 @@ void ExynosVideoDecodeAccelerator::DestroyMfcOutputBuffers() {
DPLOG(ERROR) << "DestroyMfcOutputBuffers() ioctl() failed: VIDIOC_REQBUFS";
mfc_output_buffer_map_.clear();
- mfc_free_output_buffers_.clear();
-}
-
-void ExynosVideoDecodeAccelerator::DestroyGscInputBuffers() {
- DVLOG(3) << "DestroyGscInputBuffers()";
- DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
- DCHECK(!gsc_input_streamon_);
-
- struct v4l2_requestbuffers reqbufs;
- memset(&reqbufs, 0, sizeof(reqbufs));
- reqbufs.count = 0;
- reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- reqbufs.memory = V4L2_MEMORY_DMABUF;
- if (ioctl(gsc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0)
- DPLOG(ERROR) << "DestroyGscInputBuffers(): ioctl() failed: VIDIOC_REQBUFS";
-
- gsc_input_buffer_map_.clear();
- gsc_free_input_buffers_.clear();
-}
-
-void ExynosVideoDecodeAccelerator::DestroyGscOutputBuffers() {
- DVLOG(3) << "DestroyGscOutputBuffers()";
- DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
- DCHECK(!gsc_output_streamon_);
-
- if (gsc_output_buffer_map_.size() != 0) {
- if (!make_context_current_.Run())
- DLOG(ERROR) << "DestroyGscOutputBuffers(): "
- << "could not make context current";
-
- size_t i = 0;
- do {
- GscOutputRecord& output_record = gsc_output_buffer_map_[i];
- if (output_record.fd != -1)
- HANDLE_EINTR(close(output_record.fd));
- if (output_record.egl_image != EGL_NO_IMAGE_KHR)
- eglDestroyImageKHR(egl_display_, output_record.egl_image);
- if (output_record.egl_sync != EGL_NO_SYNC_KHR)
- eglDestroySyncKHR(egl_display_, output_record.egl_sync);
- if (client_) {
- DVLOG(1) << "DestroyGscOutputBuffers(): "
- << "dismissing PictureBuffer id=" << output_record.picture_id;
- client_->DismissPictureBuffer(output_record.picture_id);
- }
- ++i;
- } while (i < gsc_output_buffer_map_.size());
- }
-
- struct v4l2_requestbuffers reqbufs;
- memset(&reqbufs, 0, sizeof(reqbufs));
- reqbufs.count = 0;
- reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- reqbufs.memory = V4L2_MEMORY_DMABUF;
- if (ioctl(gsc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0)
- DPLOG(ERROR) << "DestroyGscOutputBuffers(): ioctl() failed: VIDIOC_REQBUFS";
-
- gsc_output_buffer_map_.clear();
- gsc_free_output_buffers_.clear();
+ while (!mfc_free_output_buffers_.empty())
+ mfc_free_output_buffers_.pop();
}
void ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers() {
DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
DVLOG(3) << "ResolutionChangeDestroyBuffers()";
- DestroyGscInputBuffers();
- DestroyGscOutputBuffers();
DestroyMfcOutputBuffers();
// Finish resolution change on decoder thread.
@@ -2457,4 +1970,54 @@ void ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers() {
base::Unretained(this)));
}
+void ExynosVideoDecodeAccelerator::SendPictureReady() {
+ DVLOG(3) << "SendPictureReady()";
+ DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ bool resetting_or_flushing =
+ (decoder_state_ == kResetting || decoder_flushing_);
+ while (pending_picture_ready_.size() > 0) {
+ bool cleared = pending_picture_ready_.front().cleared;
+ const media::Picture& picture = pending_picture_ready_.front().picture;
+ if (cleared && picture_clearing_count_ == 0) {
+ // This picture is cleared. Post it to IO thread to reduce latency. This
+ // should be the case after all pictures are cleared at the beginning.
+ io_message_loop_proxy_->PostTask(
+ FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture));
+ pending_picture_ready_.pop();
+ } else if (!cleared || resetting_or_flushing) {
+ DVLOG(3) << "SendPictureReady()"
+ << ". cleared=" << pending_picture_ready_.front().cleared
+ << ", decoder_state_=" << decoder_state_
+ << ", decoder_flushing_=" << decoder_flushing_
+ << ", picture_clearing_count_=" << picture_clearing_count_;
+ // If the picture is not cleared, post it to the child thread because it
+ // has to be cleared in the child thread. A picture only needs to be
+ // cleared once. If the decoder is resetting or flushing, send all
+ // pictures to ensure PictureReady arrive before reset or flush done.
+ child_message_loop_proxy_->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&Client::PictureReady, client_, picture),
+ // Unretained is safe. If Client::PictureReady gets to run, |this| is
+ // alive. Destroy() will wait the decode thread to finish.
+ base::Bind(&ExynosVideoDecodeAccelerator::PictureCleared,
+ base::Unretained(this)));
+ picture_clearing_count_++;
+ pending_picture_ready_.pop();
+ } else {
+ // This picture is cleared. But some pictures are about to be cleared on
+ // the child thread. To preserve the order, do not send this until those
+ // pictures are cleared.
+ break;
+ }
+ }
+}
+
+void ExynosVideoDecodeAccelerator::PictureCleared() {
+ DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_;
+ DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK_GT(picture_clearing_count_, 0);
+ picture_clearing_count_--;
+ SendPictureReady();
+}
+
} // namespace content
diff --git a/chromium/content/common/gpu/media/exynos_video_decode_accelerator.h b/chromium/content/common/gpu/media/exynos_video_decode_accelerator.h
index 76b1bb15676..71b5d66da07 100644
--- a/chromium/content/common/gpu/media/exynos_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/exynos_video_decode_accelerator.h
@@ -8,16 +8,19 @@
#ifndef CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_DECODE_ACCELERATOR_H_
#define CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_DECODE_ACCELERATOR_H_
-#include <list>
+#include <queue>
#include <vector>
#include "base/callback_forward.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
#include "content/common/gpu/media/video_decode_accelerator_impl.h"
+#include "media/base/limits.h"
#include "media/base/video_decoder_config.h"
+#include "media/video/picture.h"
#include "ui/gfx/size.h"
#include "ui/gl/gl_bindings.h"
@@ -29,7 +32,7 @@ namespace content {
class H264Parser;
// This class handles Exynos video acceleration directly through the V4L2
-// devices exported by the Multi Format Codec and GScaler hardware blocks.
+// device exported by the Multi Format Codec hardware block.
//
// The threading model of this class is driven by the fact that it needs to
// interface two fundamentally different event queues -- the one Chromium
@@ -44,16 +47,27 @@ class H264Parser;
// media::VideoDecodeAccelerator::Client interface.
// * The decoder_thread_, owned by this class. It services API tasks, through
// the *Task() routines, as well as V4L2 device events, through
-// ServiceDeviceTask(). Almost all state modification is done on this thread.
+// ServiceDeviceTask(). Almost all state modification is done on this thread
+// (this doesn't include buffer (re)allocation sequence, see below).
// * The device_poll_thread_, owned by this class. All it does is epoll() on
// the V4L2 in DevicePollTask() and schedule a ServiceDeviceTask() on the
// decoder_thread_ when something interesting happens.
// TODO(sheu): replace this thread with an TYPE_IO decoder_thread_.
//
-// Note that this class has no locks! Everything's serviced on the
-// decoder_thread_, so there are no synchronization issues.
+// Note that this class has (almost) no locks, apart from the pictures_assigned_
+// WaitableEvent. Everything (apart from buffer (re)allocation) is serviced on
+// the decoder_thread_, so there are no synchronization issues.
// ... well, there are, but it's a matter of getting messages posted in the
// right order, not fiddling with locks.
+// Buffer creation is a two-step process that is serviced partially on the
+// Child thread, because we need to wait for the client to provide textures
+// for the buffers we allocate. We cannot keep the decoder thread running while
+// the client allocates Pictures for us, because we need to REQBUFS first to get
+// the required number of output buffers from the device and that cannot be done
+// unless we free the previous set of buffers, leaving the decoding in a
+// inoperable state for the duration of the wait for Pictures. So to prevent
+// subtle races (esp. if we get Reset() in the meantime), we block the decoder
+// thread while we wait for AssignPictureBuffers from the client.
class CONTENT_EXPORT ExynosVideoDecodeAccelerator
: public VideoDecodeAcceleratorImpl {
public:
@@ -80,13 +94,6 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
// VideoDecodeAcceleratorImpl implementation.
virtual bool CanDecodeOnIOThread() OVERRIDE;
- // Do any necessary initialization before the sandbox is enabled.
- static void PreSandboxInitialization();
-
- // Lazily initialize static data after sandbox is enabled. Return false on
- // init failure.
- static bool PostSandboxInitialization();
-
private:
// These are rather subjectively tuned.
enum {
@@ -94,10 +101,11 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
// TODO(posciak): determine MFC input buffer size based on level limits.
// See http://crbug.com/255116.
kMfcInputBufferMaxSize = 1024 * 1024,
- kGscInputBufferCount = 4,
// Number of output buffers to use for each VDA stage above what's required
- // by the decoder (e.g. DPB size, in H264).
- kDpbOutputBufferExtraCount = 3,
+ // by the decoder (e.g. DPB size, in H264). We need
+ // media::limits::kMaxVideoFrames to fill up the GpuVideoDecode pipeline,
+ // and +1 for a frame in transit.
+ kDpbOutputBufferExtraCount = media::limits::kMaxVideoFrames + 1,
};
// Internal state of the decoder.
@@ -119,7 +127,6 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
// File descriptors we need to poll.
enum PollFds {
kPollMfc = (1 << 0),
- kPollGsc = (1 << 1),
};
// Auto-destruction reference for BitstreamBuffer, for message-passing from
@@ -127,53 +134,38 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
struct BitstreamBufferRef;
// Auto-destruction reference for an array of PictureBuffer, for
- // message-passing from AssignPictureBuffers() to AssignPictureBuffersTask().
+ // simpler EGLImage cleanup if any calls fail in AssignPictureBuffers().
struct PictureBufferArrayRef;
// Auto-destruction reference for EGLSync (for message-passing).
struct EGLSyncKHRRef;
+ // Record for decoded pictures that can be sent to PictureReady.
+ struct PictureRecord;
+
// Record for MFC input buffers.
struct MfcInputRecord {
MfcInputRecord();
~MfcInputRecord();
- bool at_device; // held by device.
- void* address; // mmap() address.
- size_t length; // mmap() length.
- off_t bytes_used; // bytes filled in the mmap() segment.
- int32 input_id; // triggering input_id as given to Decode().
+ bool at_device; // held by device.
+ void* address; // mmap() address.
+ size_t length; // mmap() length.
+ off_t bytes_used; // bytes filled in the mmap() segment.
+ int32 input_id; // triggering input_id as given to Decode().
};
// Record for MFC output buffers.
struct MfcOutputRecord {
MfcOutputRecord();
~MfcOutputRecord();
- bool at_device; // held by device.
- size_t bytes_used[2]; // bytes used in each dmabuf.
- void* address[2]; // mmap() address for each plane.
- size_t length[2]; // mmap() length for each plane.
- int32 input_id; // triggering input_id as given to Decode().
- };
-
- // Record for GSC input buffers.
- struct GscInputRecord {
- GscInputRecord();
- ~GscInputRecord();
- bool at_device; // held by device.
- int mfc_output; // MFC output buffer index to recycle when this input
- // is complete.
- };
-
- // Record for GSC output buffers.
- struct GscOutputRecord {
- GscOutputRecord();
- ~GscOutputRecord();
- bool at_device; // held by device.
- bool at_client; // held by client.
- int fd; // file descriptor from backing EGLImage.
- EGLImageKHR egl_image; // backing EGLImage.
- EGLSyncKHR egl_sync; // sync the compositor's use of the EGLImage.
- int32 picture_id; // picture buffer id as returned to PictureReady().
+ bool at_device; // held by device.
+ bool at_client; // held by client.
+ int fds[2]; // file descriptors for each plane.
+ EGLImageKHR egl_image; // EGLImageKHR for the output buffer.
+ EGLSyncKHR egl_sync; // sync the compositor's use of the EGLImage.
+ int32 picture_id; // picture buffer id as returned to PictureReady().
+ bool cleared; // Whether the texture is cleared and safe to render
+ // from. See TextureManager for details.
};
//
@@ -205,11 +197,6 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
// Flush data for one decoded frame.
bool FlushInputFrame();
- // Process an AssignPictureBuffers() API call. After this, the
- // device_poll_thread_ can be started safely, since we have all our
- // buffers.
- void AssignPictureBuffersTask(scoped_ptr<PictureBufferArrayRef> pic_buffers);
-
// Service I/O on the V4L2 devices. This task should only be scheduled from
// DevicePollTask(). If |mfc_event_pending| is true, one or more events
// on MFC file descriptor are pending.
@@ -217,15 +204,11 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
// Handle the various device queues.
void EnqueueMfc();
void DequeueMfc();
- void EnqueueGsc();
- void DequeueGsc();
// Handle incoming MFC events.
void DequeueMfcEvents();
// Enqueue a buffer on the corresponding queue.
bool EnqueueMfcInputRecord();
bool EnqueueMfcOutputRecord();
- bool EnqueueGscInputRecord();
- bool EnqueueGscOutputRecord();
// Process a ReusePictureBuffer() API call. The API call create an EGLSync
// object on the main (GPU process) thread; we will record this object so we
@@ -269,7 +252,7 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
// Try to get output format from MFC, detected after parsing the beginning
// of the stream. Sets |again| to true if more parsing is needed.
bool GetFormatInfo(struct v4l2_format* format, bool* again);
- // Create MFC output and GSC input and output buffers for the given |format|.
+ // Create MFC output buffers for the given |format|.
bool CreateBuffersForFormat(const struct v4l2_format& format);
//
@@ -299,8 +282,6 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
// Create the buffers we need.
bool CreateMfcInputBuffers();
bool CreateMfcOutputBuffers();
- bool CreateGscInputBuffers();
- bool CreateGscOutputBuffers();
//
// Methods run on child thread.
@@ -309,10 +290,14 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
// Destroy buffers.
void DestroyMfcInputBuffers();
void DestroyMfcOutputBuffers();
- void DestroyGscInputBuffers();
- void DestroyGscOutputBuffers();
void ResolutionChangeDestroyBuffers();
+ // Send decoded pictures to PictureReady.
+ void SendPictureReady();
+
+ // Callback that indicates a picture has been cleared.
+ void PictureCleared();
+
// Our original calling message loop for the child thread.
scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_;
@@ -369,7 +354,7 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
// Got a reset request while we were performing resolution change.
bool resolution_change_reset_pending_;
// Input queue for decoder_thread_: BitstreamBuffers in.
- std::list<linked_ptr<BitstreamBufferRef> > decoder_input_queue_;
+ std::queue<linked_ptr<BitstreamBufferRef> > decoder_input_queue_;
// For H264 decode, hardware requires that we send it frame-sized chunks.
// We'll need to parse the stream.
scoped_ptr<content::H264Parser> decoder_h264_parser_;
@@ -379,10 +364,13 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
//
// Hardware state and associated queues. Since decoder_thread_ services
// the hardware, decoder_thread_ owns these too.
+ // mfc_output_buffer_map_ and free_output_buffers_ are an exception during the
+ // buffer (re)allocation sequence, when the decoder_thread_ is blocked briefly
+ // while the Child thread manipulates them.
//
// Completed decode buffers, waiting for MFC.
- std::list<int> mfc_input_ready_queue_;
+ std::queue<int> mfc_input_ready_queue_;
// MFC decode device.
int mfc_fd_;
@@ -400,39 +388,25 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator
bool mfc_output_streamon_;
// MFC output buffers enqueued to device.
int mfc_output_buffer_queued_count_;
- // Output buffers ready to use, as a LIFO since we don't care about ordering.
- std::vector<int> mfc_free_output_buffers_;
+ // Output buffers ready to use, as a FIFO since we want oldest-first to hide
+ // synchronization latency with GL.
+ std::queue<int> mfc_free_output_buffers_;
// Mapping of int index to MFC output buffer record.
std::vector<MfcOutputRecord> mfc_output_buffer_map_;
- // Required size of MFC output buffers. Two sizes for two planes.
- size_t mfc_output_buffer_size_[2];
+ // MFC output pixel format.
uint32 mfc_output_buffer_pixelformat_;
// Required size of DPB for decoding.
int mfc_output_dpb_size_;
- // Completed MFC outputs, waiting for GSC.
- std::list<int> mfc_output_gsc_input_queue_;
+ // Pictures that are ready but not sent to PictureReady yet.
+ std::queue<PictureRecord> pending_picture_ready_;
- // GSC decode device.
- int gsc_fd_;
+ // The number of pictures that are sent to PictureReady and will be cleared.
+ int picture_clearing_count_;
- // GSC input buffer state.
- bool gsc_input_streamon_;
- // GSC input buffers enqueued to device.
- int gsc_input_buffer_queued_count_;
- // Input buffers ready to use, as a LIFO since we don't care about ordering.
- std::vector<int> gsc_free_input_buffers_;
- // Mapping of int index to GSC input buffer record.
- std::vector<GscInputRecord> gsc_input_buffer_map_;
-
- // GSC output buffer state.
- bool gsc_output_streamon_;
- // GSC output buffers enqueued to device.
- int gsc_output_buffer_queued_count_;
- // Output buffers ready to use. We need a FIFO here.
- std::list<int> gsc_free_output_buffers_;
- // Mapping of int index to GSC output buffer record.
- std::vector<GscOutputRecord> gsc_output_buffer_map_;
+ // Used by the decoder thread to wait for AssignPictureBuffers to arrive
+ // to avoid races with potential Reset requests.
+ base::WaitableEvent pictures_assigned_;
// Output picture size.
gfx::Size frame_buffer_size_;
diff --git a/chromium/content/common/gpu/media/exynos_video_encode_accelerator.cc b/chromium/content/common/gpu/media/exynos_video_encode_accelerator.cc
index a2a30a65aab..e8a2196edc6 100644
--- a/chromium/content/common/gpu/media/exynos_video_encode_accelerator.cc
+++ b/chromium/content/common/gpu/media/exynos_video_encode_accelerator.cc
@@ -12,9 +12,11 @@
#include <sys/mman.h>
#include "base/callback.h"
+#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/posix/eintr_wrapper.h"
+#include "content/public/common/content_switches.h"
#include "media/base/bitstream_buffer.h"
#define NOTIFY_ERROR(x) \
@@ -113,19 +115,19 @@ ExynosVideoEncodeAccelerator::~ExynosVideoEncodeAccelerator() {
DCHECK(!device_poll_thread_.IsRunning());
if (device_poll_interrupt_fd_ != -1) {
- HANDLE_EINTR(close(device_poll_interrupt_fd_));
+ close(device_poll_interrupt_fd_);
device_poll_interrupt_fd_ = -1;
}
if (gsc_fd_ != -1) {
DestroyGscInputBuffers();
DestroyGscOutputBuffers();
- HANDLE_EINTR(close(gsc_fd_));
+ close(gsc_fd_);
gsc_fd_ = -1;
}
if (mfc_fd_ != -1) {
DestroyMfcInputBuffers();
DestroyMfcOutputBuffers();
- HANDLE_EINTR(close(mfc_fd_));
+ close(mfc_fd_);
mfc_fd_ = -1;
}
}
@@ -154,9 +156,6 @@ void ExynosVideoEncodeAccelerator::Initialize(
output_visible_size_ = converted_visible_size_;
switch (input_format) {
- case media::VideoFrame::RGB32:
- input_format_fourcc_ = V4L2_PIX_FMT_RGB32;
- break;
case media::VideoFrame::I420:
input_format_fourcc_ = V4L2_PIX_FMT_YUV420M;
break;
@@ -168,6 +167,9 @@ void ExynosVideoEncodeAccelerator::Initialize(
if (output_profile >= media::H264PROFILE_MIN &&
output_profile <= media::H264PROFILE_MAX) {
output_format_fourcc_ = V4L2_PIX_FMT_H264;
+ } else if (output_profile >= media::VP8PROFILE_MIN &&
+ output_profile <= media::VP8PROFILE_MAX) {
+ output_format_fourcc_ = V4L2_PIX_FMT_VP8;
} else {
NOTIFY_ERROR(kInvalidArgumentError);
return;
@@ -252,6 +254,9 @@ void ExynosVideoEncodeAccelerator::Initialize(
if (!SetMfcFormats())
return;
+ if (!InitMfcControls())
+ return;
+
// VIDIOC_REQBUFS on CAPTURE queue.
if (!CreateMfcOutputBuffers())
return;
@@ -365,12 +370,25 @@ void ExynosVideoEncodeAccelerator::Destroy() {
// static
std::vector<media::VideoEncodeAccelerator::SupportedProfile>
ExynosVideoEncodeAccelerator::GetSupportedProfiles() {
- std::vector<SupportedProfile> profiles(1);
- SupportedProfile& profile = profiles[0];
- profile.profile = media::H264PROFILE_MAIN;
- profile.max_resolution.SetSize(1920, 1088);
- profile.max_framerate.numerator = 30;
- profile.max_framerate.denominator = 1;
+ std::vector<SupportedProfile> profiles;
+
+ SupportedProfile profile;
+
+ const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ if (cmd_line->HasSwitch(switches::kEnableWebRtcHWVp8Encoding)) {
+ profile.profile = media::VP8PROFILE_MAIN;
+ profile.max_resolution.SetSize(1920, 1088);
+ profile.max_framerate.numerator = 30;
+ profile.max_framerate.denominator = 1;
+ profiles.push_back(profile);
+ } else {
+ profile.profile = media::H264PROFILE_MAIN;
+ profile.max_resolution.SetSize(1920, 1088);
+ profile.max_framerate.numerator = 30;
+ profile.max_framerate.denominator = 1;
+ profiles.push_back(profile);
+ }
+
return profiles;
}
@@ -721,21 +739,26 @@ void ExynosVideoEncodeAccelerator::DequeueMfc() {
output_size = output_buffer_byte_size_;
uint8* target_data =
reinterpret_cast<uint8*>(output_record.buffer_ref->shm->memory());
- if (stream_header_size_ == 0) {
- // Assume that the first buffer dequeued is the stream header.
- stream_header_size_ = output_size;
- stream_header_.reset(new uint8[stream_header_size_]);
- memcpy(stream_header_.get(), output_data, stream_header_size_);
- }
- if (key_frame &&
- output_buffer_byte_size_ - stream_header_size_ >= output_size) {
- // Insert stream header before every keyframe.
- memcpy(target_data, stream_header_.get(), stream_header_size_);
- memcpy(target_data + stream_header_size_, output_data, output_size);
- output_size += stream_header_size_;
+ if (output_format_fourcc_ == V4L2_PIX_FMT_H264) {
+ if (stream_header_size_ == 0) {
+ // Assume that the first buffer dequeued is the stream header.
+ stream_header_size_ = output_size;
+ stream_header_.reset(new uint8[stream_header_size_]);
+ memcpy(stream_header_.get(), output_data, stream_header_size_);
+ }
+ if (key_frame &&
+ output_buffer_byte_size_ - stream_header_size_ >= output_size) {
+ // Insert stream header before every keyframe.
+ memcpy(target_data, stream_header_.get(), stream_header_size_);
+ memcpy(target_data + stream_header_size_, output_data, output_size);
+ output_size += stream_header_size_;
+ } else {
+ memcpy(target_data, output_data, output_size);
+ }
} else {
memcpy(target_data, output_data, output_size);
}
+
DVLOG(3) << "DequeueMfc(): returning "
"bitstream_buffer_id=" << output_record.buffer_ref->id
<< ", key_frame=" << key_frame;
@@ -773,14 +796,6 @@ bool ExynosVideoEncodeAccelerator::EnqueueGscInputRecord() {
qbuf.memory = V4L2_MEMORY_USERPTR;
qbuf.m.planes = qbuf_planes;
switch (input_format_fourcc_) {
- case V4L2_PIX_FMT_RGB32: {
- qbuf.m.planes[0].bytesused = input_allocated_size_.GetArea() * 4;
- qbuf.m.planes[0].length = input_allocated_size_.GetArea() * 4;
- qbuf.m.planes[0].m.userptr = reinterpret_cast<unsigned long>(
- frame->data(media::VideoFrame::kRGBPlane));
- qbuf.length = 1;
- break;
- }
case V4L2_PIX_FMT_YUV420M: {
qbuf.m.planes[0].bytesused = input_allocated_size_.GetArea();
qbuf.m.planes[0].length = input_allocated_size_.GetArea();
@@ -1334,7 +1349,11 @@ bool ExynosVideoEncodeAccelerator::SetMfcFormats() {
format.fmt.pix_mp.num_planes = 1;
IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_S_FMT, &format);
- struct v4l2_ext_control ctrls[8];
+ return true;
+}
+
+bool ExynosVideoEncodeAccelerator::InitMfcControls() {
+ struct v4l2_ext_control ctrls[9];
struct v4l2_ext_controls control;
memset(&ctrls, 0, sizeof(ctrls));
memset(&control, 0, sizeof(control));
@@ -1361,9 +1380,12 @@ bool ExynosVideoEncodeAccelerator::SetMfcFormats() {
// Enable macroblock-level bitrate control.
ctrls[6].id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE;
ctrls[6].value = 1;
+ // Use H.264 level 4.0 to match the supported max resolution.
+ ctrls[7].id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
+ ctrls[7].value = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
// Disable periodic key frames.
- ctrls[7].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
- ctrls[7].value = 0;
+ ctrls[8].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
+ ctrls[8].value = 0;
control.ctrl_class = V4L2_CTRL_CLASS_MPEG;
control.count = arraysize(ctrls);
control.controls = ctrls;
@@ -1490,7 +1512,7 @@ void ExynosVideoEncodeAccelerator::DestroyMfcInputBuffers() {
MfcInputRecord& input_record = mfc_input_buffer_map_[buf];
for (size_t plane = 0; plane < arraysize(input_record.fd); ++plane)
- HANDLE_EINTR(close(mfc_input_buffer_map_[buf].fd[plane]));
+ close(mfc_input_buffer_map_[buf].fd[plane]);
}
struct v4l2_requestbuffers reqbufs;
diff --git a/chromium/content/common/gpu/media/exynos_video_encode_accelerator.h b/chromium/content/common/gpu/media/exynos_video_encode_accelerator.h
index bc1687d5d61..3a9bbb4fc72 100644
--- a/chromium/content/common/gpu/media/exynos_video_encode_accelerator.h
+++ b/chromium/content/common/gpu/media/exynos_video_encode_accelerator.h
@@ -11,6 +11,7 @@
#include "base/memory/linked_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
+#include "content/common/content_export.h"
#include "media/video/video_encode_accelerator.h"
#include "ui/gfx/size.h"
@@ -32,7 +33,8 @@ namespace content {
// V4L2 devices exported by the Multi Format Codec and GScaler hardware blocks
// on the Exynos platform. The threading model of this class is the same as the
// ExynosVideoDecodeAccelerator (from which class this was designed).
-class ExynosVideoEncodeAccelerator : public media::VideoEncodeAccelerator {
+class CONTENT_EXPORT ExynosVideoEncodeAccelerator
+ : public media::VideoEncodeAccelerator {
public:
explicit ExynosVideoEncodeAccelerator(
media::VideoEncodeAccelerator::Client* client);
@@ -176,6 +178,7 @@ class ExynosVideoEncodeAccelerator : public media::VideoEncodeAccelerator {
bool CreateGscInputBuffers();
bool CreateGscOutputBuffers();
bool SetMfcFormats();
+ bool InitMfcControls();
bool CreateMfcInputBuffers();
bool CreateMfcOutputBuffers();
diff --git a/chromium/content/common/gpu/media/gl_surface_capturer.cc b/chromium/content/common/gpu/media/gl_surface_capturer.cc
deleted file mode 100644
index 5f76eda7c7e..00000000000
--- a/chromium/content/common/gpu/media/gl_surface_capturer.cc
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/media/gl_surface_capturer.h"
-
-#include "base/message_loop/message_loop_proxy.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "ipc/ipc_message_macros.h"
-
-namespace content {
-
-namespace {
-
-enum {
- kMaxCaptureSize = 4096,
-};
-
-} // anonymous namespace
-
-GLSurfaceCapturer::GLSurfaceCapturer(int32 route_id, GpuCommandBufferStub* stub)
- : thread_checker_(),
- route_id_(route_id),
- stub_(stub),
- output_format_(media::VideoFrame::INVALID) {
- DCHECK(thread_checker_.CalledOnValidThread());
- stub_->AddDestructionObserver(this);
- stub_->channel()->AddRoute(route_id_, this);
-}
-
-GLSurfaceCapturer::~GLSurfaceCapturer() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (surface_capturer_)
- surface_capturer_.release()->Destroy();
-
- stub_->channel()->RemoveRoute(route_id_);
- stub_->RemoveDestructionObserver(this);
-}
-
-bool GLSurfaceCapturer::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(GLSurfaceCapturer, message)
- IPC_MESSAGE_HANDLER(SurfaceCapturerMsg_Initialize, OnInitialize)
- IPC_MESSAGE_HANDLER(SurfaceCapturerMsg_TryCapture, OnTryCapture)
- IPC_MESSAGE_HANDLER(SurfaceCapturerMsg_CopyCaptureToVideoFrame,
- OnCopyCaptureToVideoFrame)
- IPC_MESSAGE_HANDLER(SurfaceCapturerMsg_Destroy, OnDestroy)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void GLSurfaceCapturer::NotifyCaptureParameters(const gfx::Size& buffer_size,
- const gfx::Rect& visible_rect) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (buffer_size.width() < 1 || buffer_size.width() > kMaxCaptureSize ||
- buffer_size.height() < 1 || buffer_size.height() > kMaxCaptureSize ||
- visible_rect.x() < 0 || visible_rect.x() > kMaxCaptureSize - 1 ||
- visible_rect.y() < 0 || visible_rect.y() > kMaxCaptureSize - 1 ||
- visible_rect.width() < 1 || visible_rect.width() > kMaxCaptureSize ||
- visible_rect.height() < 1 || visible_rect.height() > kMaxCaptureSize) {
- DLOG(ERROR) << "NotifyCaptureParameters(): parameters out of bounds: "
- "buffer_size=" << buffer_size.ToString()
- << ", visible_rect=" << visible_rect.ToString();
- NotifyError(SurfaceCapturer::kInvalidArgumentError);
- return;
- }
- output_buffer_size_ = buffer_size;
- output_visible_rect_ = visible_rect;
- Send(new SurfaceCapturerHostMsg_NotifyCaptureParameters(
- route_id_, buffer_size, visible_rect));
-}
-
-void GLSurfaceCapturer::NotifyCopyCaptureDone(
- const scoped_refptr<media::VideoFrame>& frame) {
- DCHECK(thread_checker_.CalledOnValidThread());
- FrameIdMap::iterator iter = frame_id_map_.find(frame);
- if (iter == frame_id_map_.end()) {
- DLOG(ERROR) << "NotifyCopyCaptureDone(): invalid frame";
- NotifyError(SurfaceCapturer::kInvalidArgumentError);
- return;
- }
- Send(new SurfaceCapturerHostMsg_NotifyCopyCaptureDone(route_id_,
- iter->second));
- frame_id_map_.erase(iter);
-}
-
-void GLSurfaceCapturer::NotifyError(SurfaceCapturer::Error error) {
- DCHECK(thread_checker_.CalledOnValidThread());
- Send(new SurfaceCapturerHostMsg_NotifyError(route_id_, error));
-}
-
-void GLSurfaceCapturer::OnWillDestroyStub() {
- DCHECK(thread_checker_.CalledOnValidThread());
- delete this;
-}
-
-void GLSurfaceCapturer::OnInitialize(media::VideoFrame::Format format) {
- DVLOG(2) << "OnInitialize(): format=" << format;
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!surface_capturer_);
-
- // TODO(sheu): actually create a surface capturer.
-
- if (!surface_capturer_) {
- NOTIMPLEMENTED() << "OnInitialize(): GL surface capturing not available";
- NotifyError(SurfaceCapturer::kPlatformFailureError);
- return;
- }
-
- output_format_ = format;
- surface_capturer_->Initialize(output_format_);
-}
-
-void GLSurfaceCapturer::OnTryCapture() {
- DVLOG(3) << "OnTryCapture()";
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!surface_capturer_)
- return;
- surface_capturer_->TryCapture();
-}
-
-static void DeleteShm(scoped_ptr<base::SharedMemory> shm) {
- // Just let shm fall out of scope.
-}
-
-void GLSurfaceCapturer::OnCopyCaptureToVideoFrame(
- int32 frame_id,
- base::SharedMemoryHandle buffer_shm,
- uint32_t buffer_size) {
- DVLOG(3) << "OnCopyCaptureToVideoFrame(): frame_id=" << frame_id
- << ", buffer_size=" << buffer_size;
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!surface_capturer_)
- return;
- if (frame_id < 0) {
- DLOG(ERROR) << "OnCopyCaptureToVideoFrame(): invalid frame_id=" << frame_id;
- NotifyError(SurfaceCapturer::kPlatformFailureError);
- return;
- }
-
- scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(buffer_shm, false));
- if (!shm->Map(buffer_size)) {
- DLOG(ERROR) << "OnCopyCaptureToVideoFrame(): could not map "
- "frame_id=" << frame_id;
- NotifyError(SurfaceCapturer::kPlatformFailureError);
- return;
- }
- scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapExternalSharedMemory(
- output_format_,
- output_buffer_size_,
- output_visible_rect_,
- output_visible_rect_.size(),
- reinterpret_cast<uint8*>(shm->memory()),
- buffer_size,
- buffer_shm,
- base::TimeDelta(),
- base::Bind(&DeleteShm, base::Passed(&shm)));
- if (!frame) {
- DLOG(ERROR) << "OnCopyCaptureToVideoFrame(): could not create frame for"
- "frame_id=" << frame_id;
- NotifyError(SurfaceCapturer::kPlatformFailureError);
- return;
- }
- frame_id_map_[frame] = frame_id;
- surface_capturer_->CopyCaptureToVideoFrame(frame);
-}
-
-void GLSurfaceCapturer::OnDestroy() {
- DVLOG(2) << "OnDestroy()";
- DCHECK(thread_checker_.CalledOnValidThread());
- delete this;
-}
-
-void GLSurfaceCapturer::Send(IPC::Message* message) {
- DCHECK(thread_checker_.CalledOnValidThread());
- uint32 type = message->type();
- if (!stub_->channel()->Send(message)) {
- DLOG(ERROR) << "Send(): send failed: message->type()=" << type;
- NotifyError(SurfaceCapturer::kPlatformFailureError);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/media/gl_surface_capturer.h b/chromium/content/common/gpu/media/gl_surface_capturer.h
deleted file mode 100644
index d40ae99f60c..00000000000
--- a/chromium/content/common/gpu/media/gl_surface_capturer.h
+++ /dev/null
@@ -1,88 +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_COMMON_GPU_MEDIA_GL_SURFACE_CAPTURER_H_
-#define CONTENT_COMMON_GPU_MEDIA_GL_SURFACE_CAPTURER_H_
-
-#include "base/callback.h"
-#include "base/containers/small_map.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "content/common/gpu/gpu_command_buffer_stub.h"
-#include "content/common/gpu/surface_capturer.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
-
-namespace gfx {
-
-class Size;
-class Rect;
-
-} // namespace gfx
-
-namespace content {
-
-class GpuChannelHost;
-
-// This class implements the GPU process side of a SurfaceCapturer,
-// communicating over IPC with a GLSurfaceCapturerHost on the browser process.
-class GLSurfaceCapturer : public IPC::Listener,
- public SurfaceCapturer::Client,
- public GpuCommandBufferStub::DestructionObserver {
- public:
- GLSurfaceCapturer(int32 route_id, GpuCommandBufferStub* stub);
- virtual ~GLSurfaceCapturer();
-
- // IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- // SurfaceCapturer::Client implementation.
- virtual void NotifyCaptureParameters(const gfx::Size& buffer_size,
- const gfx::Rect& visible_rect) OVERRIDE;
- virtual void NotifyCopyCaptureDone(
- const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
- virtual void NotifyError(SurfaceCapturer::Error error) OVERRIDE;
-
- // GpuCommandBufferStub::DestructionObserver implementation.
- virtual void OnWillDestroyStub() OVERRIDE;
-
- private:
- // Handlers for IPC messages.
- void OnInitialize(media::VideoFrame::Format format);
- void OnCopyCaptureToVideoFrame(int32 frame_id,
- base::SharedMemoryHandle buffer_shm,
- uint32 buffer_size);
- void OnTryCapture();
- void OnDestroy();
-
- void Send(IPC::Message* message);
-
- const base::ThreadChecker thread_checker_;
-
- // Route ID assigned by the GpuCommandBufferStub.
- const int32 route_id_;
-
- // The GpuCommandBufferStub this instance belongs to, as an unowned pointer
- // since |stub_| will own (and outlive) this.
- GpuCommandBufferStub* const stub_;
-
- // media::VideoFrames received from the host side.
- typedef base::SmallMap<std::map<scoped_refptr<media::VideoFrame>, int32> >
- FrameIdMap;
- FrameIdMap frame_id_map_;
-
- // The underlying capturer we delegate to.
- scoped_ptr<SurfaceCapturer> surface_capturer_;
-
- // The capture output parameters that the capturer informs us of.
- media::VideoFrame::Format output_format_;
- gfx::Size output_buffer_size_;
- gfx::Rect output_visible_rect_;
-
- DISALLOW_COPY_AND_ASSIGN(GLSurfaceCapturer);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_MEDIA_GL_SURFACE_CAPTURER_H_
diff --git a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc
index c5de2df00e2..b932258173f 100644
--- a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc
@@ -18,6 +18,7 @@
#include "gpu/command_buffer/common/command_buffer.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_message_utils.h"
+#include "media/base/limits.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_surface_egl.h"
@@ -33,11 +34,8 @@
#include "content/common/gpu/media/android_video_decode_accelerator.h"
#endif
-#include "gpu/command_buffer/service/texture_manager.h"
#include "ui/gfx/size.h"
-using gpu::gles2::TextureManager;
-
namespace content {
static bool MakeDecoderContextCurrent(
@@ -55,6 +53,27 @@ static bool MakeDecoderContextCurrent(
return true;
}
+// A helper class that works like AutoLock but only acquires the lock when
+// DCHECK is on.
+class DebugAutoLock {
+ public:
+ explicit DebugAutoLock(base::Lock& lock) : lock_(lock) {
+ if (DCHECK_IS_ON())
+ lock_.Acquire();
+ }
+
+ ~DebugAutoLock() {
+ if (DCHECK_IS_ON()) {
+ lock_.AssertAcquired();
+ lock_.Release();
+ }
+ }
+
+ private:
+ base::Lock& lock_;
+ DISALLOW_COPY_AND_ASSIGN(DebugAutoLock);
+};
+
class GpuVideoDecodeAccelerator::MessageFilter
: public IPC::ChannelProxy::MessageFilter {
public:
@@ -113,6 +132,7 @@ GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
host_route_id_(host_route_id),
stub_(stub),
texture_target_(0),
+ filter_removed_(true, false),
io_message_loop_(io_message_loop),
weak_factory_for_io_(this) {
DCHECK(stub_);
@@ -124,14 +144,15 @@ GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
}
GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
- if (video_decode_accelerator_)
- video_decode_accelerator_.release()->Destroy();
+ // This class can only be self-deleted from OnWillDestroyStub(), which means
+ // the VDA has already been destroyed in there.
+ CHECK(!video_decode_accelerator_.get());
}
bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
- DCHECK(stub_);
if (!video_decode_accelerator_)
return false;
+
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg)
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode)
@@ -151,12 +172,21 @@ void GpuVideoDecodeAccelerator::ProvidePictureBuffers(
uint32 requested_num_of_buffers,
const gfx::Size& dimensions,
uint32 texture_target) {
+ if (dimensions.width() > media::limits::kMaxDimension ||
+ dimensions.height() > media::limits::kMaxDimension ||
+ dimensions.GetArea() > media::limits::kMaxCanvas) {
+ NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
+ return;
+ }
if (!Send(new AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers(
- host_route_id_, requested_num_of_buffers, dimensions,
- texture_target))) {
+ host_route_id_,
+ requested_num_of_buffers,
+ dimensions,
+ texture_target))) {
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers) "
<< "failed";
}
+ texture_dimensions_ = dimensions;
texture_target_ = texture_target;
}
@@ -168,10 +198,25 @@ void GpuVideoDecodeAccelerator::DismissPictureBuffer(
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer) "
<< "failed";
}
+ DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
+ uncleared_textures_.erase(picture_buffer_id);
}
void GpuVideoDecodeAccelerator::PictureReady(
const media::Picture& picture) {
+ // VDA may call PictureReady on IO thread. SetTextureCleared should run on
+ // the child thread. VDA is responsible to call PictureReady on the child
+ // thread when a picture buffer is delivered the first time.
+ if (child_message_loop_->BelongsToCurrentThread()) {
+ SetTextureCleared(picture);
+ } else {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ if (DCHECK_IS_ON()) {
+ DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
+ DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id()));
+ }
+ }
+
if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady(
host_route_id_,
picture.picture_buffer_id(),
@@ -202,7 +247,6 @@ void GpuVideoDecodeAccelerator::NotifyError(
void GpuVideoDecodeAccelerator::Initialize(
const media::VideoCodecProfile profile,
IPC::Message* init_done_msg) {
- DCHECK(stub_);
DCHECK(!video_decode_accelerator_.get());
DCHECK(!init_done_msg_);
DCHECK(init_done_msg);
@@ -223,7 +267,7 @@ void GpuVideoDecodeAccelerator::Initialize(
NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
return;
}
- DLOG(INFO) << "Initializing DXVA HW decoder for windows.";
+ DVLOG(0) << "Initializing DXVA HW decoder for windows.";
video_decode_accelerator_.reset(new DXVAVideoDecodeAccelerator(
this, make_context_current_));
#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
@@ -268,7 +312,7 @@ void GpuVideoDecodeAccelerator::OnDecode(
base::SharedMemoryHandle handle, int32 id, uint32 size) {
DCHECK(video_decode_accelerator_.get());
if (id < 0) {
- DLOG(FATAL) << "BitstreamBuffer id " << id << " out of range";
+ DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range";
if (child_message_loop_->BelongsToCurrentThread()) {
NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
} else {
@@ -284,12 +328,9 @@ void GpuVideoDecodeAccelerator::OnDecode(
}
void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
- const std::vector<int32>& buffer_ids,
- const std::vector<uint32>& texture_ids,
- const std::vector<gfx::Size>& sizes) {
- DCHECK(stub_);
- if (buffer_ids.size() != texture_ids.size() ||
- buffer_ids.size() != sizes.size()) {
+ const std::vector<int32>& buffer_ids,
+ const std::vector<uint32>& texture_ids) {
+ if (buffer_ids.size() != texture_ids.size()) {
NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
return;
}
@@ -299,53 +340,67 @@ void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
command_decoder->GetContextGroup()->texture_manager();
std::vector<media::PictureBuffer> buffers;
+ std::vector<scoped_refptr<gpu::gles2::TextureRef> > textures;
for (uint32 i = 0; i < buffer_ids.size(); ++i) {
if (buffer_ids[i] < 0) {
- DLOG(FATAL) << "Buffer id " << buffer_ids[i] << " out of range";
+ DLOG(ERROR) << "Buffer id " << buffer_ids[i] << " out of range";
NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
return;
}
gpu::gles2::TextureRef* texture_ref = texture_manager->GetTexture(
texture_ids[i]);
if (!texture_ref) {
- DLOG(FATAL) << "Failed to find texture id " << texture_ids[i];
+ DLOG(ERROR) << "Failed to find texture id " << texture_ids[i];
NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
return;
}
gpu::gles2::Texture* info = texture_ref->texture();
if (info->target() != texture_target_) {
- DLOG(FATAL) << "Texture target mismatch for texture id "
+ DLOG(ERROR) << "Texture target mismatch for texture id "
<< texture_ids[i];
NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
return;
}
- // GL_TEXTURE_EXTERNAL_OES textures have their dimensions defined by the
- // underlying EGLImage.
- if (texture_target_ != GL_TEXTURE_EXTERNAL_OES) {
+ if (texture_target_ == GL_TEXTURE_EXTERNAL_OES) {
+ // GL_TEXTURE_EXTERNAL_OES textures have their dimensions defined by the
+ // underlying EGLImage. Use |texture_dimensions_| for this size.
+ texture_manager->SetLevelInfo(texture_ref,
+ GL_TEXTURE_EXTERNAL_OES,
+ 0,
+ 0,
+ texture_dimensions_.width(),
+ texture_dimensions_.height(),
+ 1,
+ 0,
+ 0,
+ 0,
+ false);
+ } else {
+ // For other targets, texture dimensions should already be defined.
GLsizei width = 0, height = 0;
info->GetLevelSize(texture_target_, 0, &width, &height);
- if (width != sizes[i].width() || height != sizes[i].height()) {
- DLOG(FATAL) << "Size mismatch for texture id " << texture_ids[i];
+ if (width != texture_dimensions_.width() ||
+ height != texture_dimensions_.height()) {
+ DLOG(ERROR) << "Size mismatch for texture id " << texture_ids[i];
NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
return;
}
}
- if (!texture_manager->ClearRenderableLevels(command_decoder, texture_ref)) {
- DLOG(FATAL) << "Failed to Clear texture id " << texture_ids[i];
- NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
- return;
- }
uint32 service_texture_id;
if (!command_decoder->GetServiceTextureId(
texture_ids[i], &service_texture_id)) {
- DLOG(FATAL) << "Failed to translate texture!";
+ DLOG(ERROR) << "Failed to translate texture!";
NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
return;
}
buffers.push_back(media::PictureBuffer(
- buffer_ids[i], sizes[i], service_texture_id));
+ buffer_ids[i], texture_dimensions_, service_texture_id));
+ textures.push_back(texture_ref);
}
video_decode_accelerator_->AssignPictureBuffers(buffers);
+ DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
+ for (uint32 i = 0; i < buffer_ids.size(); ++i)
+ uncleared_textures_[buffer_ids[i]] = textures[i];
}
void GpuVideoDecodeAccelerator::OnReusePictureBuffer(
@@ -366,22 +421,13 @@ void GpuVideoDecodeAccelerator::OnReset() {
void GpuVideoDecodeAccelerator::OnDestroy() {
DCHECK(video_decode_accelerator_.get());
- DCHECK(stub_);
- stub_->channel()->RemoveRoute(host_route_id_);
- stub_->RemoveDestructionObserver(this);
- if (filter_.get()) {
- // Remove the filter first because the member variables can be accessed on
- // IO thread. When filter is removed, OnFilterRemoved will delete |this|.
- stub_->channel()->RemoveFilter(filter_.get());
- } else {
- delete this;
- }
+ OnWillDestroyStub();
}
void GpuVideoDecodeAccelerator::OnFilterRemoved() {
// We're destroying; cancel all callbacks.
weak_factory_for_io_.InvalidateWeakPtrs();
- child_message_loop_->DeleteSoon(FROM_HERE, this);
+ filter_removed_.Signal();
}
void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
@@ -412,14 +458,52 @@ void GpuVideoDecodeAccelerator::NotifyResetDone() {
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed";
}
-void GpuVideoDecodeAccelerator::OnWillDestroyStub() { OnDestroy(); }
+void GpuVideoDecodeAccelerator::OnWillDestroyStub() {
+ // The stub is going away, so we have to stop and destroy VDA here, before
+ // returning, because the VDA may need the GL context to run and/or do its
+ // cleanup. We cannot destroy the VDA before the IO thread message filter is
+ // removed however, since we cannot service incoming messages with VDA gone.
+ // We cannot simply check for existence of VDA on IO thread though, because
+ // we don't want to synchronize the IO thread with the ChildThread.
+ // So we have to wait for the RemoveFilter callback here instead and remove
+ // the VDA after it arrives and before returning.
+ if (filter_.get()) {
+ stub_->channel()->RemoveFilter(filter_.get());
+ filter_removed_.Wait();
+ }
+
+ stub_->channel()->RemoveRoute(host_route_id_);
+ stub_->RemoveDestructionObserver(this);
+
+ if (video_decode_accelerator_)
+ video_decode_accelerator_.release()->Destroy();
+
+ delete this;
+}
bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) {
- DCHECK(stub_);
if (filter_.get() && io_message_loop_->BelongsToCurrentThread())
return filter_->SendOnIOThread(message);
DCHECK(child_message_loop_->BelongsToCurrentThread());
return stub_->channel()->Send(message);
}
+void GpuVideoDecodeAccelerator::SetTextureCleared(
+ const media::Picture& picture) {
+ DCHECK(child_message_loop_->BelongsToCurrentThread());
+ DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
+ std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it;
+ it = uncleared_textures_.find(picture.picture_buffer_id());
+ if (it == uncleared_textures_.end())
+ return; // the texture has been cleared
+
+ scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second;
+ GLenum target = texture_ref->texture()->target();
+ gpu::gles2::TextureManager* texture_manager =
+ stub_->decoder()->GetContextGroup()->texture_manager();
+ DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0));
+ texture_manager->SetLevelCleared(texture_ref, target, 0, true);
+ uncleared_textures_.erase(it);
+}
+
} // namespace content
diff --git a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h
index 77946bc59a2..c22608b854f 100644
--- a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h
@@ -5,16 +5,20 @@
#ifndef CONTENT_COMMON_GPU_MEDIA_GPU_VIDEO_DECODE_ACCELERATOR_H_
#define CONTENT_COMMON_GPU_MEDIA_GPU_VIDEO_DECODE_ACCELERATOR_H_
+#include <map>
#include <vector>
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
+#include "base/synchronization/waitable_event.h"
#include "content/common/gpu/gpu_command_buffer_stub.h"
#include "content/common/gpu/media/video_decode_accelerator_impl.h"
+#include "gpu/command_buffer/service/texture_manager.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "media/video/video_decode_accelerator.h"
+#include "ui/gfx/size.h"
namespace base {
class MessageLoopProxy;
@@ -35,7 +39,6 @@ class GpuVideoDecodeAccelerator
int32 host_route_id,
GpuCommandBufferStub* stub,
const scoped_refptr<base::MessageLoopProxy>& io_message_loop);
- virtual ~GpuVideoDecodeAccelerator();
// IPC::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -68,14 +71,14 @@ class GpuVideoDecodeAccelerator
private:
class MessageFilter;
+ // We only allow self-delete, from OnWillDestroyStub(), after cleanup there.
+ virtual ~GpuVideoDecodeAccelerator();
+
// Handlers for IPC messages.
void OnDecode(base::SharedMemoryHandle handle, int32 id, uint32 size);
- void OnAssignPictureBuffers(
- const std::vector<int32>& buffer_ids,
- const std::vector<uint32>& texture_ids,
- const std::vector<gfx::Size>& sizes);
- void OnReusePictureBuffer(
- int32 picture_buffer_id);
+ void OnAssignPictureBuffers(const std::vector<int32>& buffer_ids,
+ const std::vector<uint32>& texture_ids);
+ void OnReusePictureBuffer(int32 picture_buffer_id);
void OnFlush();
void OnReset();
void OnDestroy();
@@ -83,6 +86,9 @@ class GpuVideoDecodeAccelerator
// Called on IO thread when |filter_| has been removed.
void OnFilterRemoved();
+ // Sets the texture to cleared.
+ void SetTextureCleared(const media::Picture& picture);
+
// Message to Send() when initialization is done. Is only non-NULL during
// initialization and is owned by the IPC channel underlying the
// GpuCommandBufferStub.
@@ -101,12 +107,19 @@ class GpuVideoDecodeAccelerator
// Returns false if failed.
base::Callback<bool(void)> make_context_current_;
+ // The texture dimensions as requested by ProvidePictureBuffers().
+ gfx::Size texture_dimensions_;
+
// The texture target as requested by ProvidePictureBuffers().
uint32 texture_target_;
// The message filter to run VDA::Decode on IO thread if VDA supports it.
scoped_refptr<MessageFilter> filter_;
+ // Used to wait on for |filter_| to be removed, before we can safely
+ // destroy the VDA.
+ base::WaitableEvent filter_removed_;
+
// GPU child message loop.
scoped_refptr<base::MessageLoopProxy> child_message_loop_;
@@ -116,6 +129,14 @@ class GpuVideoDecodeAccelerator
// Weak pointers will be invalidated on IO thread.
base::WeakPtrFactory<Client> weak_factory_for_io_;
+ // Protects |uncleared_textures_| when DCHECK is on. This is for debugging
+ // only. We don't want to hold a lock on IO thread. When DCHECK is off,
+ // |uncleared_textures_| is only accessed from the child thread.
+ base::Lock debug_uncleared_textures_lock_;
+
+ // A map from picture buffer ID to TextureRef that have not been cleared.
+ std::map<int32, scoped_refptr<gpu::gles2::TextureRef> > uncleared_textures_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(GpuVideoDecodeAccelerator);
};
diff --git a/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc b/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc
index badd512e080..6ff95441447 100644
--- a/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc
+++ b/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc
@@ -12,10 +12,13 @@
#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/gpu_messages.h"
#include "ipc/ipc_message_macros.h"
+#include "media/base/limits.h"
#include "media/base/video_frame.h"
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
#include "content/common/gpu/media/exynos_video_encode_accelerator.h"
+#elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
+#include "content/common/gpu/media/android_video_encode_accelerator.h"
#endif
namespace content {
@@ -25,7 +28,7 @@ GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(GpuChannel* gpu_channel,
: weak_this_factory_(this),
channel_(gpu_channel),
route_id_(route_id),
- input_format_(media::VideoFrame::INVALID),
+ input_format_(media::VideoFrame::UNKNOWN),
output_buffer_size_(0) {}
GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() {
@@ -87,6 +90,8 @@ GpuVideoEncodeAccelerator::GetSupportedProfiles() {
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
profiles = ExynosVideoEncodeAccelerator::GetSupportedProfiles();
+#elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
+ profiles = AndroidVideoEncodeAccelerator::GetSupportedProfiles();
#endif
// TODO(sheu): return platform-specific profiles.
@@ -94,8 +99,11 @@ GpuVideoEncodeAccelerator::GetSupportedProfiles() {
}
void GpuVideoEncodeAccelerator::CreateEncoder() {
+ DCHECK(!encoder_);
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
encoder_.reset(new ExynosVideoEncodeAccelerator(this));
+#elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
+ encoder_.reset(new AndroidVideoEncodeAccelerator(this));
#endif
}
@@ -111,9 +119,12 @@ void GpuVideoEncodeAccelerator::OnInitialize(
<< ", initial_bitrate=" << initial_bitrate;
DCHECK(!encoder_);
- if (input_visible_size.width() > kint32max / input_visible_size.height()) {
+ if (input_visible_size.width() > media::limits::kMaxDimension ||
+ input_visible_size.height() > media::limits::kMaxDimension ||
+ input_visible_size.GetArea() > media::limits::kMaxCanvas) {
DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnInitialize(): "
- "input_visible_size too large";
+ "input_visible_size " << input_visible_size.ToString()
+ << " too large";
NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
return;
}
@@ -156,13 +167,14 @@ void GpuVideoEncodeAccelerator::OnEncode(int32 frame_id,
return;
}
+ uint8* shm_memory = reinterpret_cast<uint8*>(shm->memory());
scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapExternalSharedMemory(
+ media::VideoFrame::WrapExternalPackedMemory(
input_format_,
input_coded_size_,
gfx::Rect(input_visible_size_),
input_visible_size_,
- reinterpret_cast<uint8*>(shm->memory()),
+ shm_memory,
buffer_size,
buffer_handle,
base::TimeDelta(),
diff --git a/chromium/content/common/gpu/media/h264_bit_reader.cc b/chromium/content/common/gpu/media/h264_bit_reader.cc
index 64e12bee203..dbeb4db23f4 100644
--- a/chromium/content/common/gpu/media/h264_bit_reader.cc
+++ b/chromium/content/common/gpu/media/h264_bit_reader.cc
@@ -9,7 +9,8 @@ namespace content {
H264BitReader::H264BitReader()
: data_(NULL), bytes_left_(0), curr_byte_(0),
- num_remaining_bits_in_curr_byte_(0), prev_two_bytes_(0) {
+ num_remaining_bits_in_curr_byte_(0), prev_two_bytes_(0),
+ emulation_prevention_bytes_(0) {
}
H264BitReader::~H264BitReader() {}
@@ -25,6 +26,7 @@ bool H264BitReader::Initialize(const uint8* data, off_t size) {
num_remaining_bits_in_curr_byte_ = 0;
// Initially set to 0xffff to accept all initial two-byte sequences.
prev_two_bytes_ = 0xffff;
+ emulation_prevention_bytes_ = 0;
return true;
}
@@ -39,6 +41,7 @@ bool H264BitReader::UpdateCurrByte() {
// Detected 0x000003, skip last byte.
++data_;
--bytes_left_;
+ ++emulation_prevention_bytes_;
// Need another full three bytes before we can detect the sequence again.
prev_two_bytes_ = 0xffff;
@@ -101,4 +104,9 @@ bool H264BitReader::HasMoreRBSPData() {
((1 << (num_remaining_bits_in_curr_byte_ - 1)) - 1)) != 0;
}
+size_t H264BitReader::NumEmulationPreventionBytesRead()
+{
+ return emulation_prevention_bytes_;
+}
+
} // namespace content
diff --git a/chromium/content/common/gpu/media/h264_bit_reader.h b/chromium/content/common/gpu/media/h264_bit_reader.h
index c43b6f774ec..a2d32b5c9cc 100644
--- a/chromium/content/common/gpu/media/h264_bit_reader.h
+++ b/chromium/content/common/gpu/media/h264_bit_reader.h
@@ -43,6 +43,9 @@ class CONTENT_EXPORT H264BitReader {
// See the definition of more_rbsp_data() in spec.
bool HasMoreRBSPData();
+ // Return the number of emulation prevention bytes already read.
+ size_t NumEmulationPreventionBytesRead();
+
private:
// Advance to the next byte, loading it into curr_byte_.
// Return false on end of stream.
@@ -65,6 +68,9 @@ class CONTENT_EXPORT H264BitReader {
// Initially set to 0xffff to accept all initial two-byte sequences.
int prev_two_bytes_;
+ // Number of emulation preventation bytes (0x000003) we met.
+ size_t emulation_prevention_bytes_;
+
DISALLOW_COPY_AND_ASSIGN(H264BitReader);
};
diff --git a/chromium/content/common/gpu/media/h264_parser.cc b/chromium/content/common/gpu/media/h264_parser.cc
index 5de0d98ae46..177668bee67 100644
--- a/chromium/content/common/gpu/media/h264_parser.cc
+++ b/chromium/content/common/gpu/media/h264_parser.cc
@@ -1085,7 +1085,8 @@ H264Parser::Result H264Parser::ParseSliceHeader(const H264NALU& nalu,
return kUnsupportedStream;
}
- shdr->header_bit_size = shdr->nalu_size * 8 - br_.NumBitsLeft();
+ size_t epb = br_.NumEmulationPreventionBytesRead();
+ shdr->header_bit_size = (shdr->nalu_size - epb) * 8 - br_.NumBitsLeft();
return kOk;
}
diff --git a/chromium/content/common/gpu/media/rendering_helper_gl.cc b/chromium/content/common/gpu/media/rendering_helper.cc
index 6fedcd158f6..c18cffc5b9f 100644
--- a/chromium/content/common/gpu/media/rendering_helper_gl.cc
+++ b/chromium/content/common/gpu/media/rendering_helper.cc
@@ -1,34 +1,26 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/gpu/media/rendering_helper.h"
-#include <map>
-
#include "base/bind.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringize_macros.h"
#include "base/synchronization/waitable_event.h"
-#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_context_stub.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
-#if !defined(OS_WIN) && defined(ARCH_CPU_X86_FAMILY)
-#define GL_VARIANT_GLX 1
+#ifdef GL_VARIANT_GLX
typedef GLXWindow NativeWindowType;
-typedef GLXContext NativeContextType;
struct ScopedPtrXFree {
void operator()(void* x) const { ::XFree(x); }
};
-#else
-#define GL_VARIANT_EGL 1
+#else // EGL
typedef EGLNativeWindowType NativeWindowType;
-typedef EGLContext NativeContextType;
-typedef EGLSurface NativeSurfaceType;
#endif
// Helper for Shader creation.
@@ -93,69 +85,7 @@ RenderingHelperParams::RenderingHelperParams() {}
RenderingHelperParams::~RenderingHelperParams() {}
-class RenderingHelperGL : public RenderingHelper {
- public:
- RenderingHelperGL();
- virtual ~RenderingHelperGL();
-
- // Implement RenderingHelper.
- virtual void Initialize(const RenderingHelperParams& params,
- base::WaitableEvent* done) OVERRIDE;
- virtual void UnInitialize(base::WaitableEvent* done) OVERRIDE;
- virtual void CreateTexture(int window_id,
- uint32 texture_target,
- uint32* texture_id,
- base::WaitableEvent* done) OVERRIDE;
- virtual void RenderTexture(uint32 texture_id) OVERRIDE;
- virtual void DeleteTexture(uint32 texture_id) OVERRIDE;
- virtual void* GetGLContext() OVERRIDE;
- virtual void* GetGLDisplay() OVERRIDE;
- virtual void GetThumbnailsAsRGB(std::vector<unsigned char>* rgb,
- bool* alpha_solid,
- base::WaitableEvent* done) OVERRIDE;
-
- static const gfx::GLImplementation kGLImplementation;
-
- private:
- void Clear();
-
- // Make window_id's surface current w/ the GL context, or release the context
- // if |window_id < 0|.
- void MakeCurrent(int window_id);
-
-
- base::MessageLoop* message_loop_;
- std::vector<gfx::Size> window_dimensions_;
- std::vector<gfx::Size> frame_dimensions_;
-
- NativeContextType gl_context_;
- std::map<uint32, int> texture_id_to_surface_index_;
-
-#if defined(GL_VARIANT_EGL)
- EGLDisplay gl_display_;
- std::vector<NativeSurfaceType> gl_surfaces_;
-#else
- XVisualInfo* x_visual_;
-#endif
-
-#if defined(OS_WIN)
- std::vector<HWND> windows_;
-#else
- Display* x_display_;
- std::vector<Window> x_windows_;
-#endif
-
- bool render_as_thumbnails_;
- int frame_count_;
- GLuint thumbnails_fbo_id_;
- GLuint thumbnails_texture_id_;
- gfx::Size thumbnails_fbo_size_;
- gfx::Size thumbnail_size_;
- GLuint program_;
-};
-
-// static
-const gfx::GLImplementation RenderingHelperGL::kGLImplementation =
+static const gfx::GLImplementation kGLImplementation =
#if defined(GL_VARIANT_GLX)
gfx::kGLImplementationDesktopGL;
#elif defined(GL_VARIANT_EGL)
@@ -165,22 +95,17 @@ const gfx::GLImplementation RenderingHelperGL::kGLImplementation =
#error "Unknown GL implementation."
#endif
-// static
-RenderingHelper* RenderingHelper::Create() {
- return new RenderingHelperGL;
-}
-
-RenderingHelperGL::RenderingHelperGL() {
+RenderingHelper::RenderingHelper() {
Clear();
}
-RenderingHelperGL::~RenderingHelperGL() {
+RenderingHelper::~RenderingHelper() {
CHECK_EQ(window_dimensions_.size(), 0U) <<
"Must call UnInitialize before dtor.";
Clear();
}
-void RenderingHelperGL::MakeCurrent(int window_id) {
+void RenderingHelper::MakeCurrent(int window_id) {
#if GL_VARIANT_GLX
if (window_id < 0) {
CHECK(glXMakeContextCurrent(x_display_, GLX_NONE, GLX_NONE, NULL));
@@ -200,8 +125,8 @@ void RenderingHelperGL::MakeCurrent(int window_id) {
#endif
}
-void RenderingHelperGL::Initialize(const RenderingHelperParams& params,
- base::WaitableEvent* done) {
+void RenderingHelper::Initialize(const RenderingHelperParams& params,
+ base::WaitableEvent* done) {
// Use window_dimensions_.size() != 0 as a proxy for the class having already
// been Initialize()'d, and UnInitialize() before continuing.
if (window_dimensions_.size()) {
@@ -210,7 +135,7 @@ void RenderingHelperGL::Initialize(const RenderingHelperParams& params,
done.Wait();
}
- gfx::InitializeGLBindings(RenderingHelperGL::kGLImplementation);
+ gfx::InitializeGLBindings(kGLImplementation);
scoped_refptr<GLContextStubWithExtensions> stub_context(
new GLContextStubWithExtensions());
@@ -329,7 +254,7 @@ void RenderingHelperGL::Initialize(const RenderingHelperParams& params,
#endif
#if GL_VARIANT_EGL
- NativeSurfaceType egl_surface =
+ EGLSurface egl_surface =
eglCreateWindowSurface(gl_display_, egl_config, window, NULL);
gl_surfaces_.push_back(egl_surface);
CHECK_NE(egl_surface, EGL_NO_SURFACE);
@@ -405,13 +330,21 @@ void RenderingHelperGL::Initialize(const RenderingHelperParams& params,
});
#if GL_VARIANT_EGL
- static const char kFragmentShader[] = STRINGIZE(
- precision mediump float;
- varying vec2 interp_tc;
- uniform sampler2D tex;
- void main() {
- gl_FragColor = texture2D(tex, interp_tc);
- });
+ static const char kFragmentShader[] =
+ "#extension GL_OES_EGL_image_external : enable\n"
+ "precision mediump float;\n"
+ "varying vec2 interp_tc;\n"
+ "uniform sampler2D tex;\n"
+ "#ifdef GL_OES_EGL_image_external\n"
+ "uniform samplerExternalOES tex_external;\n"
+ "#endif\n"
+ "void main() {\n"
+ " vec4 color = texture2D(tex, interp_tc);\n"
+ "#ifdef GL_OES_EGL_image_external\n"
+ " color += texture2D(tex_external, interp_tc);\n"
+ "#endif\n"
+ " gl_FragColor = color;\n"
+ "}\n";
#else
static const char kFragmentShader[] = STRINGIZE(
varying vec2 interp_tc;
@@ -440,6 +373,10 @@ void RenderingHelperGL::Initialize(const RenderingHelperParams& params,
glUniform1i(glGetUniformLocation(program_, "tex_flip"), 0);
glUniform1i(glGetUniformLocation(program_, "tex"), 0);
+ GLint tex_external = glGetUniformLocation(program_, "tex_external");
+ if (tex_external != -1) {
+ glUniform1i(tex_external, 1);
+ }
int pos_location = glGetAttribLocation(program_, "in_pos");
glEnableVertexAttribArray(pos_location);
glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices);
@@ -449,7 +386,7 @@ void RenderingHelperGL::Initialize(const RenderingHelperParams& params,
done->Signal();
}
-void RenderingHelperGL::UnInitialize(base::WaitableEvent* done) {
+void RenderingHelper::UnInitialize(base::WaitableEvent* done) {
CHECK_EQ(base::MessageLoop::current(), message_loop_);
if (render_as_thumbnails_) {
glDeleteTextures(1, &thumbnails_texture_id_);
@@ -470,10 +407,10 @@ void RenderingHelperGL::UnInitialize(base::WaitableEvent* done) {
done->Signal();
}
-void RenderingHelperGL::CreateTexture(int window_id,
- uint32 texture_target,
- uint32* texture_id,
- base::WaitableEvent* done) {
+void RenderingHelper::CreateTexture(int window_id,
+ uint32 texture_target,
+ uint32* texture_id,
+ base::WaitableEvent* done) {
if (base::MessageLoop::current() != message_loop_) {
message_loop_->PostTask(
FROM_HERE,
@@ -481,32 +418,33 @@ void RenderingHelperGL::CreateTexture(int window_id,
window_id, texture_target, texture_id, done));
return;
}
- CHECK_EQ(static_cast<uint32>(GL_TEXTURE_2D), texture_target);
MakeCurrent(window_id);
glGenTextures(1, texture_id);
- glBindTexture(GL_TEXTURE_2D, *texture_id);
+ glBindTexture(texture_target, *texture_id);
int dimensions_id = window_id % frame_dimensions_.size();
- glTexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- frame_dimensions_[dimensions_id].width(),
- frame_dimensions_[dimensions_id].height(),
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ if (texture_target == GL_TEXTURE_2D) {
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ frame_dimensions_[dimensions_id].width(),
+ frame_dimensions_[dimensions_id].height(),
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ NULL);
+ }
+ glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures.
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
CHECK(texture_id_to_surface_index_.insert(
std::make_pair(*texture_id, window_id)).second);
done->Signal();
}
-void RenderingHelperGL::RenderTexture(uint32 texture_id) {
+void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) {
CHECK_EQ(base::MessageLoop::current(), message_loop_);
size_t window_id = texture_id_to_surface_index_[texture_id];
MakeCurrent(window_id);
@@ -535,8 +473,19 @@ void RenderingHelperGL::RenderTexture(uint32 texture_id) {
glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1);
}
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texture_id);
+ // Unbound texture samplers default to (0, 0, 0, 1). Use this fact to switch
+ // between GL_TEXTURE_2D and GL_TEXTURE_EXTERNAL_OES as appopriate.
+ if (texture_target == GL_TEXTURE_2D) {
+ glActiveTexture(GL_TEXTURE0 + 0);
+ glBindTexture(GL_TEXTURE_2D, texture_id);
+ glActiveTexture(GL_TEXTURE0 + 1);
+ glBindTexture(texture_target, 0);
+ } else if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
+ glActiveTexture(GL_TEXTURE0 + 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glActiveTexture(GL_TEXTURE0 + 1);
+ glBindTexture(texture_target, texture_id);
+ }
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
@@ -548,7 +497,10 @@ void RenderingHelperGL::RenderTexture(uint32 texture_id) {
glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
glViewport(0, 0, width, height);
glScissor(0, 0, width, height);
+ glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, thumbnails_texture_id_);
+ glActiveTexture(GL_TEXTURE0 + 1);
+ glBindTexture(texture_target, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
@@ -560,16 +512,16 @@ void RenderingHelperGL::RenderTexture(uint32 texture_id) {
#endif
}
-void RenderingHelperGL::DeleteTexture(uint32 texture_id) {
+void RenderingHelper::DeleteTexture(uint32 texture_id) {
glDeleteTextures(1, &texture_id);
CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
}
-void* RenderingHelperGL::GetGLContext() {
+void* RenderingHelper::GetGLContext() {
return gl_context_;
}
-void* RenderingHelperGL::GetGLDisplay() {
+void* RenderingHelper::GetGLDisplay() {
#if GL_VARIANT_GLX
return x_display_;
#else // EGL
@@ -577,7 +529,7 @@ void* RenderingHelperGL::GetGLDisplay() {
#endif
}
-void RenderingHelperGL::Clear() {
+void RenderingHelper::Clear() {
window_dimensions_.clear();
frame_dimensions_.clear();
texture_id_to_surface_index_.clear();
@@ -609,9 +561,9 @@ void RenderingHelperGL::Clear() {
#endif
}
-void RenderingHelperGL::GetThumbnailsAsRGB(std::vector<unsigned char>* rgb,
- bool* alpha_solid,
- base::WaitableEvent* done) {
+void RenderingHelper::GetThumbnailsAsRGB(std::vector<unsigned char>* rgb,
+ bool* alpha_solid,
+ base::WaitableEvent* done) {
CHECK(render_as_thumbnails_);
const size_t num_pixels = thumbnails_fbo_size_.GetArea();
@@ -627,6 +579,7 @@ void RenderingHelperGL::GetThumbnailsAsRGB(std::vector<unsigned char>* rgb,
GL_RGBA,
GL_UNSIGNED_BYTE,
&rgba[0]);
+ glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
rgb->resize(num_pixels * 3);
// Drop the alpha channel, but check as we go that it is all 0xff.
bool solid = true;
diff --git a/chromium/content/common/gpu/media/rendering_helper.h b/chromium/content/common/gpu/media/rendering_helper.h
index 2986ad383a6..7890b5332db 100644
--- a/chromium/content/common/gpu/media/rendering_helper.h
+++ b/chromium/content/common/gpu/media/rendering_helper.h
@@ -5,15 +5,26 @@
#ifndef CONTENT_COMMON_GPU_MEDIA_RENDERING_HELPER_H_
#define CONTENT_COMMON_GPU_MEDIA_RENDERING_HELPER_H_
+#include <map>
#include <vector>
#include "base/basictypes.h"
#include "ui/gfx/size.h"
+#include "ui/gl/gl_bindings.h"
namespace base {
+class MessageLoop;
class WaitableEvent;
}
+#if !defined(OS_WIN) && defined(ARCH_CPU_X86_FAMILY)
+#define GL_VARIANT_GLX 1
+typedef GLXContext NativeContextType;
+#else
+#define GL_VARIANT_EGL 1
+typedef EGLContext NativeContextType;
+#endif
+
namespace content {
struct RenderingHelperParams {
@@ -41,43 +52,78 @@ struct RenderingHelperParams {
// (except for ctor/dtor) ensure they're being run on a single thread.
class RenderingHelper {
public:
- // Create a platform specific implementation of this object.
- static RenderingHelper* Create();
-
- RenderingHelper() {}
- virtual ~RenderingHelper() {}
+ RenderingHelper();
+ ~RenderingHelper();
// Create the render context and windows by the specified dimensions.
- virtual void Initialize(const RenderingHelperParams& params,
- base::WaitableEvent* done) = 0;
+ void Initialize(const RenderingHelperParams& params,
+ base::WaitableEvent* done);
// Undo the effects of Initialize() and signal |*done|.
- virtual void UnInitialize(base::WaitableEvent* done) = 0;
+ void UnInitialize(base::WaitableEvent* done);
// Return a newly-created GLES2 texture id rendering to a specific window, and
// signal |*done|.
- virtual void CreateTexture(int window_id,
- uint32 texture_target,
- uint32* texture_id,
- base::WaitableEvent* done) = 0;
+ void CreateTexture(int window_id,
+ uint32 texture_target,
+ uint32* texture_id,
+ base::WaitableEvent* done);
- // Render |texture_id| to the screen.
- virtual void RenderTexture(uint32 texture_id) = 0;
+ // Render |texture_id| to the screen using target |texture_target|.
+ void RenderTexture(uint32 texture_target, uint32 texture_id);
// Delete |texture_id|.
- virtual void DeleteTexture(uint32 texture_id) = 0;
+ void DeleteTexture(uint32 texture_id);
// Get the platform specific handle to the OpenGL context.
- virtual void* GetGLContext() = 0;
+ void* GetGLContext();
// Get the platform specific handle to the OpenGL display.
- virtual void* GetGLDisplay() = 0;
+ void* GetGLDisplay();
// Get rendered thumbnails as RGB.
// Sets alpha_solid to true if the alpha channel is entirely 0xff.
- virtual void GetThumbnailsAsRGB(std::vector<unsigned char>* rgb,
- bool* alpha_solid,
- base::WaitableEvent* done) = 0;
+ void GetThumbnailsAsRGB(std::vector<unsigned char>* rgb,
+ bool* alpha_solid,
+ base::WaitableEvent* done);
+
+ private:
+ void Clear();
+
+ // Make window_id's surface current w/ the GL context, or release the context
+ // if |window_id < 0|.
+ void MakeCurrent(int window_id);
+
+ base::MessageLoop* message_loop_;
+ std::vector<gfx::Size> window_dimensions_;
+ std::vector<gfx::Size> frame_dimensions_;
+
+ NativeContextType gl_context_;
+ std::map<uint32, int> texture_id_to_surface_index_;
+
+#if defined(GL_VARIANT_EGL)
+ EGLDisplay gl_display_;
+ std::vector<EGLSurface> gl_surfaces_;
+#else
+ XVisualInfo* x_visual_;
+#endif
+
+#if defined(OS_WIN)
+ std::vector<HWND> windows_;
+#else
+ Display* x_display_;
+ std::vector<Window> x_windows_;
+#endif
+
+ bool render_as_thumbnails_;
+ int frame_count_;
+ GLuint thumbnails_fbo_id_;
+ GLuint thumbnails_texture_id_;
+ gfx::Size thumbnails_fbo_size_;
+ gfx::Size thumbnail_size_;
+ GLuint program_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderingHelper);
};
} // namespace content
diff --git a/chromium/content/common/gpu/media/vaapi_h264_decoder.cc b/chromium/content/common/gpu/media/vaapi_h264_decoder.cc
index 77739ce434f..402369bb2b3 100644
--- a/chromium/content/common/gpu/media/vaapi_h264_decoder.cc
+++ b/chromium/content/common/gpu/media/vaapi_h264_decoder.cc
@@ -440,9 +440,31 @@ bool VaapiH264Decoder::SendSliceData(const uint8* ptr, size_t size) {
non_const_ptr);
}
+bool VaapiH264Decoder::PrepareRefPicLists(H264SliceHeader* slice_hdr) {
+ ref_pic_list0_.clear();
+ ref_pic_list1_.clear();
+
+ // Fill reference picture lists for B and S/SP slices.
+ if (slice_hdr->IsPSlice() || slice_hdr->IsSPSlice()) {
+ ConstructReferencePicListsP(slice_hdr);
+ return ModifyReferencePicList(slice_hdr, 0);
+ }
+
+ if (slice_hdr->IsBSlice()) {
+ ConstructReferencePicListsB(slice_hdr);
+ return ModifyReferencePicList(slice_hdr, 0) &&
+ ModifyReferencePicList(slice_hdr, 1);
+ }
+
+ return true;
+}
+
bool VaapiH264Decoder::QueueSlice(H264SliceHeader* slice_hdr) {
DCHECK(curr_pic_.get());
+ if (!PrepareRefPicLists(slice_hdr))
+ return false;
+
if (!SendVASliceParam(slice_hdr))
return false;
@@ -1081,21 +1103,6 @@ bool VaapiH264Decoder::StartNewFrame(H264SliceHeader* slice_hdr) {
UpdatePicNums();
- // Prepare reference picture lists if required (B and S/SP slices).
- ref_pic_list0_.clear();
- ref_pic_list1_.clear();
- if (slice_hdr->IsPSlice() || slice_hdr->IsSPSlice()) {
- ConstructReferencePicListsP(slice_hdr);
- if (!ModifyReferencePicList(slice_hdr, 0))
- return false;
- } else if (slice_hdr->IsBSlice()) {
- ConstructReferencePicListsB(slice_hdr);
- if (!ModifyReferencePicList(slice_hdr, 0))
- return false;
- if (!ModifyReferencePicList(slice_hdr, 1))
- return false;
- }
-
// Send parameter buffers before each new picture, before the first slice.
if (!SendPPS())
return false;
@@ -1333,7 +1340,8 @@ bool VaapiH264Decoder::FinishPicture() {
for (; output_candidate != not_outputted.end() &&
(*output_candidate)->pic_order_cnt <= last_output_poc_ + 2;
++output_candidate) {
- DCHECK_GE((*output_candidate)->pic_order_cnt, last_output_poc_);
+ int poc = (*output_candidate)->pic_order_cnt;
+ DCHECK_GE(poc, last_output_poc_);
if (!OutputPic(*output_candidate))
return false;
@@ -1341,9 +1349,9 @@ bool VaapiH264Decoder::FinishPicture() {
// Current picture hasn't been inserted into DPB yet, so don't remove it
// if we managed to output it immediately.
if (*output_candidate != pic)
- dpb_.DeleteByPOC((*output_candidate)->pic_order_cnt);
+ dpb_.DeleteByPOC(poc);
// Mark as unused.
- UnassignSurfaceFromPoC((*output_candidate)->pic_order_cnt);
+ UnassignSurfaceFromPoC(poc);
}
}
diff --git a/chromium/content/common/gpu/media/vaapi_h264_decoder.h b/chromium/content/common/gpu/media/vaapi_h264_decoder.h
index debac3f8816..baab0d88088 100644
--- a/chromium/content/common/gpu/media/vaapi_h264_decoder.h
+++ b/chromium/content/common/gpu/media/vaapi_h264_decoder.h
@@ -143,6 +143,9 @@ class VaapiH264Decoder {
// frame (see spec).
void UpdatePicNums();
+ // Prepare reference picture lists (ref_pic_list[01]_).
+ bool PrepareRefPicLists(H264SliceHeader* slice_hdr);
+
// Construct initial reference picture lists for use in decoding of
// P and B pictures (see 8.2.4 in spec).
void ConstructReferencePicListsP(H264SliceHeader* slice_hdr);
diff --git a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc
index cd18574a8d8..81781198491 100644
--- a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc
@@ -44,7 +44,7 @@ VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {
void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
if (message_loop_ != base::MessageLoop::current()) {
- DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK(decoder_thread_proxy_->BelongsToCurrentThread());
message_loop_->PostTask(FROM_HERE, base::Bind(
&VaapiVideoDecodeAccelerator::NotifyError, weak_this_, error));
return;
@@ -328,6 +328,7 @@ bool VaapiVideoDecodeAccelerator::Initialize(
base::Bind(&ReportToUMA)));
CHECK(decoder_thread_.Start());
+ decoder_thread_proxy_ = decoder_thread_.message_loop_proxy();
state_ = kIdle;
@@ -440,7 +441,7 @@ void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer(
}
bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() {
- DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK(decoder_thread_proxy_->BelongsToCurrentThread());
lock_.AssertAcquired();
if (curr_input_buffer_.get())
@@ -486,7 +487,7 @@ bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() {
void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() {
lock_.AssertAcquired();
- DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK(decoder_thread_proxy_->BelongsToCurrentThread());
DCHECK(curr_input_buffer_.get());
int32 id = curr_input_buffer_->id;
@@ -502,7 +503,7 @@ void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() {
bool VaapiVideoDecodeAccelerator::FeedDecoderWithOutputSurfaces_Locked() {
lock_.AssertAcquired();
- DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK(decoder_thread_proxy_->BelongsToCurrentThread());
while (available_va_surfaces_.empty() &&
(state_ == kDecoding || state_ == kFlushing || state_ == kIdle)) {
@@ -527,7 +528,7 @@ bool VaapiVideoDecodeAccelerator::FeedDecoderWithOutputSurfaces_Locked() {
}
void VaapiVideoDecodeAccelerator::DecodeTask() {
- DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK(decoder_thread_proxy_->BelongsToCurrentThread());
TRACE_EVENT0("Video Decoder", "VAVDA::DecodeTask");
base::AutoLock auto_lock(lock_);
@@ -658,7 +659,7 @@ void VaapiVideoDecodeAccelerator::Decode(
switch (state_) {
case kIdle:
state_ = kDecoding;
- decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ decoder_thread_proxy_->PostTask(FROM_HERE, base::Bind(
&VaapiVideoDecodeAccelerator::DecodeTask,
base::Unretained(this)));
break;
@@ -736,7 +737,7 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
}
state_ = kDecoding;
- decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ decoder_thread_proxy_->PostTask(FROM_HERE, base::Bind(
&VaapiVideoDecodeAccelerator::DecodeTask, base::Unretained(this)));
}
@@ -753,7 +754,7 @@ void VaapiVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
}
void VaapiVideoDecodeAccelerator::FlushTask() {
- DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK(decoder_thread_proxy_->BelongsToCurrentThread());
DVLOG(1) << "Flush task";
// First flush all the pictures that haven't been outputted, notifying the
@@ -776,7 +777,7 @@ void VaapiVideoDecodeAccelerator::Flush() {
base::AutoLock auto_lock(lock_);
state_ = kFlushing;
// Queue a flush task after all existing decoding tasks to clean up.
- decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ decoder_thread_proxy_->PostTask(FROM_HERE, base::Bind(
&VaapiVideoDecodeAccelerator::FlushTask, base::Unretained(this)));
input_ready_.Signal();
@@ -810,7 +811,7 @@ void VaapiVideoDecodeAccelerator::FinishFlush() {
}
void VaapiVideoDecodeAccelerator::ResetTask() {
- DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK(decoder_thread_proxy_->BelongsToCurrentThread());
DVLOG(1) << "ResetTask";
// All the decoding tasks from before the reset request from client are done
@@ -846,7 +847,7 @@ void VaapiVideoDecodeAccelerator::Reset() {
input_buffers_.pop();
}
- decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ decoder_thread_proxy_->PostTask(FROM_HERE, base::Bind(
&VaapiVideoDecodeAccelerator::ResetTask, base::Unretained(this)));
input_ready_.Signal();
@@ -890,7 +891,7 @@ void VaapiVideoDecodeAccelerator::FinishReset() {
// that we are back in kDecoding state.
if (!input_buffers_.empty()) {
state_ = kDecoding;
- decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ decoder_thread_proxy_->PostTask(FROM_HERE, base::Bind(
&VaapiVideoDecodeAccelerator::DecodeTask,
base::Unretained(this)));
}
@@ -914,7 +915,7 @@ void VaapiVideoDecodeAccelerator::Cleanup() {
base::AutoUnlock auto_unlock(lock_);
// Post a dummy task to the decoder_thread_ to ensure it is drained.
base::WaitableEvent waiter(false, false);
- decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ decoder_thread_proxy_->PostTask(FROM_HERE, base::Bind(
&base::WaitableEvent::Signal, base::Unretained(&waiter)));
input_ready_.Signal();
surfaces_available_.Signal();
diff --git a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h
index 1755b98f3d5..1445c54f4be 100644
--- a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h
@@ -249,6 +249,10 @@ private:
// vaapi_wrapper_ is destroyed.
scoped_ptr<VaapiH264Decoder> decoder_;
base::Thread decoder_thread_;
+ // Use this to post tasks to |decoder_thread_| instead of
+ // |decoder_thread_.message_loop()| because the latter will be NULL once
+ // |decoder_thread_.Stop()| returns.
+ scoped_refptr<base::MessageLoopProxy> decoder_thread_proxy_;
int num_frames_at_client_;
int num_stream_bufs_at_decoder_;
diff --git a/chromium/content/common/gpu/media/vaapi_wrapper.cc b/chromium/content/common/gpu/media/vaapi_wrapper.cc
index 5d22e4bd775..53e8b695242 100644
--- a/chromium/content/common/gpu/media/vaapi_wrapper.cc
+++ b/chromium/content/common/gpu/media/vaapi_wrapper.cc
@@ -58,12 +58,24 @@ typedef VAStatus (*VaapiCreateContext)(VADisplay dpy,
VASurfaceID *render_targets,
int num_render_targets,
VAContextID *context);
-typedef VAStatus (*VaapiCreateSurfaces)(VADisplay dpy,
- int width,
- int height,
- int format,
- int num_surfaces,
- VASurfaceID *surfaces);
+// In VAAPI version < 0.34, vaCreateSurface has 6 parameters, but in VAAPI
+// version >= 0.34, vaCreateSurface has 8 parameters.
+// TODO(chihchung): Remove the old path once ChromeOS updates to 1.2.1.
+typedef void *VaapiCreateSurfaces;
+typedef VAStatus (*VaapiCreateSurfaces6)(VADisplay dpy,
+ int width,
+ int height,
+ int format,
+ int num_surfaces,
+ VASurfaceID *surfaces);
+typedef VAStatus (*VaapiCreateSurfaces8)(VADisplay dpy,
+ unsigned int format,
+ unsigned int width,
+ unsigned int height,
+ VASurfaceID *surfaces,
+ unsigned int num_surfaces,
+ VASurfaceAttrib *attrib_list,
+ unsigned int num_attribs);
typedef VAStatus (*VaapiDestroyBuffer)(VADisplay dpy, VABufferID buffer_id);
typedef VAStatus (*VaapiDestroyConfig)(VADisplay dpy, VAConfigID config_id);
typedef VAStatus (*VaapiDestroyContext)(VADisplay dpy, VAContextID context);
@@ -207,11 +219,10 @@ bool VaapiWrapper::Initialize(media::VideoCodecProfile profile,
return false;
}
- int major_version, minor_version;
VAStatus va_res;
- va_res = VAAPI_Initialize(va_display_, &major_version, &minor_version);
+ va_res = VAAPI_Initialize(va_display_, &major_version_, &minor_version_);
VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false);
- DVLOG(1) << "VAAPI version: " << major_version << "." << minor_version;
+ DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_;
VAConfigAttrib attrib = {VAConfigAttribRTFormat, 0};
@@ -249,6 +260,11 @@ void VaapiWrapper::Deinitialize() {
va_display_ = NULL;
}
+bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) {
+ return (major_version_ < major) ||
+ (major_version_ == major && minor_version_ < minor);
+}
+
bool VaapiWrapper::CreateSurfaces(gfx::Size size,
size_t num_surfaces,
std::vector<VASurfaceID>* va_surfaces) {
@@ -260,11 +276,24 @@ bool VaapiWrapper::CreateSurfaces(gfx::Size size,
va_surface_ids_.resize(num_surfaces);
// Allocate surfaces in driver.
- VAStatus va_res = VAAPI_CreateSurfaces(va_display_,
- size.width(), size.height(),
- VA_RT_FORMAT_YUV420,
- va_surface_ids_.size(),
- &va_surface_ids_[0]);
+ VAStatus va_res;
+ if (VAAPIVersionLessThan(0, 34)) {
+ va_res = reinterpret_cast<VaapiCreateSurfaces6>(VAAPI_CreateSurfaces)(
+ va_display_,
+ size.width(), size.height(),
+ VA_RT_FORMAT_YUV420,
+ va_surface_ids_.size(),
+ &va_surface_ids_[0]);
+ } else {
+ va_res = reinterpret_cast<VaapiCreateSurfaces8>(VAAPI_CreateSurfaces)(
+ va_display_,
+ VA_RT_FORMAT_YUV420,
+ size.width(), size.height(),
+ &va_surface_ids_[0],
+ va_surface_ids_.size(),
+ NULL, 0);
+ }
+
VA_LOG_ON_ERROR(va_res, "vaCreateSurfaces failed");
if (va_res != VA_STATUS_SUCCESS) {
va_surface_ids_.clear();
@@ -405,19 +434,11 @@ bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
}
// static
-bool VaapiWrapper::pre_sandbox_init_done_ = false;
-
-// static
-void VaapiWrapper::PreSandboxInitialization() {
- DCHECK(!pre_sandbox_init_done_);
+bool VaapiWrapper::PostSandboxInitialization() {
vaapi_handle = dlopen("libva.so.1", RTLD_NOW);
vaapi_x11_handle = dlopen("libva-x11.so.1", RTLD_NOW);
- pre_sandbox_init_done_ = vaapi_handle && vaapi_x11_handle;
-}
-// static
-bool VaapiWrapper::PostSandboxInitialization() {
- if (!pre_sandbox_init_done_)
+ if (!vaapi_handle || !vaapi_x11_handle)
return false;
#define VAAPI_DLSYM_OR_RETURN_ON_ERROR(name, handle) \
do { \
diff --git a/chromium/content/common/gpu/media/vaapi_wrapper.h b/chromium/content/common/gpu/media/vaapi_wrapper.h
index aa277fd3860..850bebdea38 100644
--- a/chromium/content/common/gpu/media/vaapi_wrapper.h
+++ b/chromium/content/common/gpu/media/vaapi_wrapper.h
@@ -78,8 +78,8 @@ class CONTENT_EXPORT VaapiWrapper {
Pixmap x_pixmap,
gfx::Size dest_size);
- // Do any necessary initialization before the sandbox is enabled.
- static void PreSandboxInitialization();
+ // Returns true if the VAAPI version is less than the specified version.
+ bool VAAPIVersionLessThan(int major, int minor);
private:
VaapiWrapper();
@@ -106,6 +106,9 @@ class CONTENT_EXPORT VaapiWrapper {
// Allocated ids for VASurfaces.
std::vector<VASurfaceID> va_surface_ids_;
+ // The VAAPI version.
+ int major_version_, minor_version_;
+
// VA handles.
// Both valid after successful Initialize() and until Deinitialize().
VADisplay va_display_;
diff --git a/chromium/content/common/gpu/media/video_decode_accelerator_impl.h b/chromium/content/common/gpu/media/video_decode_accelerator_impl.h
index 8b3163ebd8f..30abfa658e1 100644
--- a/chromium/content/common/gpu/media/video_decode_accelerator_impl.h
+++ b/chromium/content/common/gpu/media/video_decode_accelerator_impl.h
@@ -19,7 +19,9 @@ class CONTENT_EXPORT VideoDecodeAcceleratorImpl
// Returns true if VDA::Decode and VDA::Client callbacks can run on the IO
// thread. Otherwise they will run on the GPU child thread. The purpose of
// running Decode on the IO thread is to reduce decode latency. Note Decode
- // should return as soon as possible and not block on the IO thread.
+ // should return as soon as possible and not block on the IO thread. Also,
+ // PictureReady should be run on the child thread if a picture is delivered
+ // the first time so it can be cleared.
virtual bool CanDecodeOnIOThread();
};
diff --git a/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc b/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc
index bd3aeea9031..f1cb85e4c65 100644
--- a/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc
+++ b/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc
@@ -15,10 +15,11 @@
// infrastructure.
#include <fcntl.h>
-#include <math.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <algorithm>
#include <deque>
+#include <map>
// Include gtest.h out of order because <X11/X.h> #define's Bool & None, which
// gtest uses as struct names (inside a namespace). This means that
@@ -45,6 +46,7 @@
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
+#include "content/common/gpu/media/h264_parser.h"
#include "content/common/gpu/media/rendering_helper.h"
#include "content/common/gpu/media/video_accelerator_unittest_helpers.h"
#include "content/public/common/content_switches.h"
@@ -89,9 +91,10 @@ const base::FilePath::CharType* g_test_video_data =
// FILE_PATH_LITERAL("test-25fps.vp8:320:240:250:250:50:175:11");
FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1");
-// The path of the frame delivery time log. We can enable the log and specify
-// the filename by the "--frame_delivery_log" switch.
-const base::FilePath::CharType* g_frame_delivery_log = NULL;
+// The file path of the test output log. This is used to communicate the test
+// results to CrOS autotests. We can enable the log and specify the filename by
+// the "--output_log" switch.
+const base::FilePath::CharType* g_output_log = NULL;
// The value is set by the switch "--rendering_fps".
double g_rendering_fps = 0;
@@ -102,6 +105,8 @@ bool g_disable_rendering = false;
// Magic constants for differentiating the reasons for NotifyResetDone being
// called.
enum ResetPoint {
+ // Reset() just after calling Decode() with a fragment containing config info.
+ RESET_AFTER_FIRST_CONFIG_INFO = -4,
START_OF_STREAM_RESET = -3,
MID_STREAM_RESET = -2,
END_OF_STREAM_RESET = -1
@@ -110,6 +115,8 @@ enum ResetPoint {
const int kMaxResetAfterFrameNum = 100;
const int kMaxFramesToDelayReuse = 64;
const base::TimeDelta kReuseDelay = base::TimeDelta::FromSeconds(1);
+// Simulate WebRTC and call VDA::Decode 30 times per second.
+const int kWebRtcDecodeCallsPerSecond = 30;
struct TestVideoFile {
explicit TestVideoFile(base::FilePath::StringType file_name)
@@ -120,7 +127,7 @@ struct TestVideoFile {
num_fragments(-1),
min_fps_render(-1),
min_fps_no_render(-1),
- profile(-1),
+ profile(media::VIDEO_CODEC_PROFILE_UNKNOWN),
reset_after_frame_num(END_OF_STREAM_RESET) {
}
@@ -131,74 +138,19 @@ struct TestVideoFile {
int num_fragments;
int min_fps_render;
int min_fps_no_render;
- int profile;
+ media::VideoCodecProfile profile;
int reset_after_frame_num;
std::string data_str;
};
// Presumed minimal display size.
-const gfx::Size kThumbnailsDisplaySize(1366, 768);
+// We subtract one pixel from the width because some ARM chromebooks do not
+// support two fullscreen app running at the same time. See crbug.com/270064.
+const gfx::Size kThumbnailsDisplaySize(1366 - 1, 768);
const gfx::Size kThumbnailsPageSize(1600, 1200);
const gfx::Size kThumbnailSize(160, 120);
const int kMD5StringLength = 32;
-// Parse |data| into its constituent parts, set the various output fields
-// accordingly, and read in video stream. CHECK-fails on unexpected or
-// missing required data. Unspecified optional fields are set to -1.
-void ParseAndReadTestVideoData(base::FilePath::StringType data,
- size_t num_concurrent_decoders,
- int reset_point,
- std::vector<TestVideoFile*>* test_video_files) {
- std::vector<base::FilePath::StringType> entries;
- base::SplitString(data, ';', &entries);
- CHECK_GE(entries.size(), 1U) << data;
- for (size_t index = 0; index < entries.size(); ++index) {
- std::vector<base::FilePath::StringType> fields;
- base::SplitString(entries[index], ':', &fields);
- CHECK_GE(fields.size(), 1U) << entries[index];
- CHECK_LE(fields.size(), 8U) << entries[index];
- TestVideoFile* video_file = new TestVideoFile(fields[0]);
- if (!fields[1].empty())
- CHECK(base::StringToInt(fields[1], &video_file->width));
- if (!fields[2].empty())
- CHECK(base::StringToInt(fields[2], &video_file->height));
- if (!fields[3].empty()) {
- CHECK(base::StringToInt(fields[3], &video_file->num_frames));
- // If we reset mid-stream and start playback over, account for frames
- // that are decoded twice in our expectations.
- if (video_file->num_frames > 0 && reset_point == MID_STREAM_RESET) {
- // Reset should not go beyond the last frame; reset after the first
- // frame for short videos.
- video_file->reset_after_frame_num = kMaxResetAfterFrameNum;
- if (video_file->num_frames <= kMaxResetAfterFrameNum)
- video_file->reset_after_frame_num = 1;
- video_file->num_frames += video_file->reset_after_frame_num;
- } else {
- video_file->reset_after_frame_num = reset_point;
- }
- }
- if (!fields[4].empty())
- CHECK(base::StringToInt(fields[4], &video_file->num_fragments));
- if (!fields[5].empty()) {
- CHECK(base::StringToInt(fields[5], &video_file->min_fps_render));
- video_file->min_fps_render /= num_concurrent_decoders;
- }
- if (!fields[6].empty()) {
- CHECK(base::StringToInt(fields[6], &video_file->min_fps_no_render));
- video_file->min_fps_no_render /= num_concurrent_decoders;
- }
- if (!fields[7].empty())
- CHECK(base::StringToInt(fields[7], &video_file->profile));
-
- // Read in the video data.
- base::FilePath filepath(video_file->file_name);
- CHECK(base::ReadFileToString(filepath, &video_file->data_str))
- << "test_video_file: " << filepath.MaybeAsASCII();
-
- test_video_files->push_back(video_file);
- }
-}
-
// Read in golden MD5s for the thumbnailed rendering of this video
void ReadGoldenThumbnailMD5s(const TestVideoFile* video_file,
std::vector<std::string>* md5_strings) {
@@ -213,6 +165,9 @@ void ReadGoldenThumbnailMD5s(const TestVideoFile* video_file,
// Ignore the empty string added by SplitString
if (!md5_string->length())
continue;
+ // Ignore comments
+ if (md5_string->at(0) == '#')
+ continue;
CHECK_EQ(static_cast<int>(md5_string->length()),
kMD5StringLength) << *md5_string;
@@ -398,7 +353,6 @@ class GLRenderingVDAClient
public:
// Doesn't take ownership of |rendering_helper| or |note|, which must outlive
// |*this|.
- // |num_fragments_per_decode| counts NALUs for h264 and frames for VP8.
// |num_play_throughs| indicates how many times to play through the video.
// |reset_after_frame_num| can be a frame number >=0 indicating a mid-stream
// Reset() should be done after that frame number is delivered, or
@@ -413,23 +367,25 @@ class GLRenderingVDAClient
// |suppress_rendering| indicates GL rendering is suppressed or not.
// After |delay_reuse_after_frame_num| frame has been delivered, the client
// will start delaying the call to ReusePictureBuffer() for kReuseDelay.
+ // |decode_calls_per_second| is the number of VDA::Decode calls per second.
+ // If |decode_calls_per_second| > 0, |num_in_flight_decodes| must be 1.
GLRenderingVDAClient(RenderingHelper* rendering_helper,
int rendering_window_id,
ClientStateNotification<ClientState>* note,
const std::string& encoded_data,
- int num_fragments_per_decode,
int num_in_flight_decodes,
int num_play_throughs,
int reset_after_frame_num,
int delete_decoder_state,
int frame_width,
int frame_height,
- int profile,
+ media::VideoCodecProfile profile,
double rendering_fps,
bool suppress_rendering,
- int delay_reuse_after_frame_num);
+ int delay_reuse_after_frame_num,
+ int decode_calls_per_second);
virtual ~GLRenderingVDAClient();
- void CreateDecoder();
+ void CreateAndStartDecoder();
// VideoDecodeAccelerator::Client implementation.
// The heart of the Client.
@@ -455,6 +411,8 @@ class GLRenderingVDAClient
int num_queued_fragments() { return num_queued_fragments_; }
int num_decoded_frames();
double frames_per_second();
+ // Return the median of the decode time in milliseconds.
+ int decode_time_median();
bool decoder_deleted() { return !decoder_.get(); }
private:
@@ -466,24 +424,23 @@ class GLRenderingVDAClient
void DeleteDecoder();
// Compute & return the first encoded bytes (including a start frame) to send
- // to the decoder, starting at |start_pos| and returning
- // |num_fragments_per_decode| units. Skips to the first decodable position.
- std::string GetBytesForFirstFragments(size_t start_pos, size_t* end_pos);
- // Compute & return the next encoded bytes to send to the decoder (based on
- // |start_pos| & |num_fragments_per_decode_|).
- std::string GetBytesForNextFragments(size_t start_pos, size_t* end_pos);
- // Helpers for GetRangeForNextFragments above.
+ // to the decoder, starting at |start_pos| and returning one fragment. Skips
+ // to the first decodable position.
+ std::string GetBytesForFirstFragment(size_t start_pos, size_t* end_pos);
+ // Compute & return the encoded bytes of next fragment to send to the decoder
+ // (based on |start_pos|).
+ std::string GetBytesForNextFragment(size_t start_pos, size_t* end_pos);
+ // Helpers for GetBytesForNextFragment above.
void GetBytesForNextNALU(size_t start_pos, size_t* end_pos); // For h.264.
- std::string GetBytesForNextFrames(
+ std::string GetBytesForNextFrame(
size_t start_pos, size_t* end_pos); // For VP8.
- // Request decode of the next batch of fragments in the encoded data.
- void DecodeNextFragments();
+ // Request decode of the next fragment in the encoded data.
+ void DecodeNextFragment();
RenderingHelper* rendering_helper_;
int rendering_window_id_;
std::string encoded_data_;
- const int num_fragments_per_decode_;
const int num_in_flight_decodes_;
int outstanding_decodes_;
size_t encoded_data_next_pos_to_decode_;
@@ -501,11 +458,18 @@ class GLRenderingVDAClient
int num_done_bitstream_buffers_;
PictureBufferById picture_buffers_by_id_;
base::TimeTicks initialize_done_ticks_;
- int profile_;
+ media::VideoCodecProfile profile_;
+ GLenum texture_target_;
bool suppress_rendering_;
std::vector<base::TimeTicks> frame_delivery_times_;
int delay_reuse_after_frame_num_;
scoped_ptr<ThrottlingVDAClient> throttling_client_;
+ // A map from bitstream buffer id to the decode start time of the buffer.
+ std::map<int, base::TimeTicks> decode_start_time_;
+ // The decode time of all decoded frames.
+ std::vector<base::TimeDelta> decode_time_;
+ // The number of VDA::Decode calls per second. This is to simulate webrtc.
+ int decode_calls_per_second_;
DISALLOW_IMPLICIT_CONSTRUCTORS(GLRenderingVDAClient);
};
@@ -515,21 +479,20 @@ GLRenderingVDAClient::GLRenderingVDAClient(
int rendering_window_id,
ClientStateNotification<ClientState>* note,
const std::string& encoded_data,
- int num_fragments_per_decode,
int num_in_flight_decodes,
int num_play_throughs,
int reset_after_frame_num,
int delete_decoder_state,
int frame_width,
int frame_height,
- int profile,
+ media::VideoCodecProfile profile,
double rendering_fps,
bool suppress_rendering,
- int delay_reuse_after_frame_num)
+ int delay_reuse_after_frame_num,
+ int decode_calls_per_second)
: rendering_helper_(rendering_helper),
rendering_window_id_(rendering_window_id),
encoded_data_(encoded_data),
- num_fragments_per_decode_(num_fragments_per_decode),
num_in_flight_decodes_(num_in_flight_decodes),
outstanding_decodes_(0),
encoded_data_next_pos_to_decode_(0),
@@ -544,12 +507,16 @@ GLRenderingVDAClient::GLRenderingVDAClient(
num_decoded_frames_(0),
num_done_bitstream_buffers_(0),
profile_(profile),
+ texture_target_(0),
suppress_rendering_(suppress_rendering),
- delay_reuse_after_frame_num_(delay_reuse_after_frame_num) {
- CHECK_GT(num_fragments_per_decode, 0);
+ delay_reuse_after_frame_num_(delay_reuse_after_frame_num),
+ decode_calls_per_second_(decode_calls_per_second) {
CHECK_GT(num_in_flight_decodes, 0);
CHECK_GT(num_play_throughs, 0);
CHECK_GE(rendering_fps, 0);
+ // |num_in_flight_decodes_| is unsupported if |decode_calls_per_second_| > 0.
+ if (decode_calls_per_second_ > 0)
+ CHECK_EQ(1, num_in_flight_decodes_);
if (rendering_fps > 0)
throttling_client_.reset(new ThrottlingVDAClient(
this,
@@ -567,7 +534,7 @@ GLRenderingVDAClient::~GLRenderingVDAClient() {
static bool DoNothingReturnTrue() { return true; }
-void GLRenderingVDAClient::CreateDecoder() {
+void GLRenderingVDAClient::CreateAndStartDecoder() {
CHECK(decoder_deleted());
CHECK(!decoder_.get());
@@ -603,10 +570,9 @@ void GLRenderingVDAClient::CreateDecoder() {
return;
// Configure the decoder.
- media::VideoCodecProfile profile = media::H264PROFILE_BASELINE;
- if (profile_ != -1)
- profile = static_cast<media::VideoCodecProfile>(profile_);
- CHECK(decoder_->Initialize(profile));
+ profile_ = (profile_ != media::VIDEO_CODEC_PROFILE_UNKNOWN ?
+ profile_ : media::H264PROFILE_BASELINE);
+ CHECK(decoder_->Initialize(profile_));
}
void GLRenderingVDAClient::ProvidePictureBuffers(
@@ -617,12 +583,13 @@ void GLRenderingVDAClient::ProvidePictureBuffers(
return;
std::vector<media::PictureBuffer> buffers;
+ texture_target_ = texture_target;
for (uint32 i = 0; i < requested_num_of_buffers; ++i) {
uint32 id = picture_buffers_by_id_.size();
uint32 texture_id;
base::WaitableEvent done(false, false);
rendering_helper_->CreateTexture(
- rendering_window_id_, texture_target, &texture_id, &done);
+ rendering_window_id_, texture_target_, &texture_id, &done);
done.Wait();
CHECK(outstanding_texture_ids_.insert(texture_id).second);
media::PictureBuffer* buffer =
@@ -650,7 +617,14 @@ void GLRenderingVDAClient::PictureReady(const media::Picture& picture) {
if (decoder_deleted())
return;
- frame_delivery_times_.push_back(base::TimeTicks::Now());
+ base::TimeTicks now = base::TimeTicks::Now();
+ frame_delivery_times_.push_back(now);
+ // Save the decode time of this picture.
+ std::map<int, base::TimeTicks>::iterator it =
+ decode_start_time_.find(picture.bitstream_buffer_id());
+ ASSERT_NE(decode_start_time_.end(), it);
+ decode_time_.push_back(now - it->second);
+ decode_start_time_.erase(it);
CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_);
++num_decoded_frames_;
@@ -670,7 +644,8 @@ void GLRenderingVDAClient::PictureReady(const media::Picture& picture) {
picture_buffers_by_id_[picture.picture_buffer_id()];
CHECK(picture_buffer);
if (!suppress_rendering_) {
- rendering_helper_->RenderTexture(picture_buffer->texture_id());
+ rendering_helper_->RenderTexture(texture_target_,
+ picture_buffer->texture_id());
}
if (num_decoded_frames() > delay_reuse_after_frame_num_) {
@@ -690,12 +665,13 @@ void GLRenderingVDAClient::NotifyInitializeDone() {
initialize_done_ticks_ = base::TimeTicks::Now();
if (reset_after_frame_num_ == START_OF_STREAM_RESET) {
+ reset_after_frame_num_ = MID_STREAM_RESET;
decoder_->Reset();
return;
}
for (int i = 0; i < num_in_flight_decodes_; ++i)
- DecodeNextFragments();
+ DecodeNextFragment();
DCHECK_EQ(outstanding_decodes_, num_in_flight_decodes_);
}
@@ -707,7 +683,8 @@ void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer(
// VaapiVideoDecodeAccelerator::FinishReset()).
++num_done_bitstream_buffers_;
--outstanding_decodes_;
- DecodeNextFragments();
+ if (decode_calls_per_second_ == 0)
+ DecodeNextFragment();
}
void GLRenderingVDAClient::NotifyFlushDone() {
@@ -728,12 +705,12 @@ void GLRenderingVDAClient::NotifyResetDone() {
if (reset_after_frame_num_ == MID_STREAM_RESET) {
reset_after_frame_num_ = END_OF_STREAM_RESET;
- DecodeNextFragments();
+ DecodeNextFragment();
return;
} else if (reset_after_frame_num_ == START_OF_STREAM_RESET) {
reset_after_frame_num_ = END_OF_STREAM_RESET;
for (int i = 0; i < num_in_flight_decodes_; ++i)
- DecodeNextFragments();
+ DecodeNextFragment();
return;
}
@@ -799,13 +776,13 @@ void GLRenderingVDAClient::DeleteDecoder() {
SetState(static_cast<ClientState>(i));
}
-std::string GLRenderingVDAClient::GetBytesForFirstFragments(
+std::string GLRenderingVDAClient::GetBytesForFirstFragment(
size_t start_pos, size_t* end_pos) {
if (profile_ < media::H264PROFILE_MAX) {
*end_pos = start_pos;
while (*end_pos + 4 < encoded_data_.size()) {
if ((encoded_data_[*end_pos + 4] & 0x1f) == 0x7) // SPS start frame
- return GetBytesForNextFragments(*end_pos, end_pos);
+ return GetBytesForNextFragment(*end_pos, end_pos);
GetBytesForNextNALU(*end_pos, end_pos);
num_skipped_fragments_++;
}
@@ -813,25 +790,21 @@ std::string GLRenderingVDAClient::GetBytesForFirstFragments(
return std::string();
}
DCHECK_LE(profile_, media::VP8PROFILE_MAX);
- return GetBytesForNextFragments(start_pos, end_pos);
+ return GetBytesForNextFragment(start_pos, end_pos);
}
-std::string GLRenderingVDAClient::GetBytesForNextFragments(
+std::string GLRenderingVDAClient::GetBytesForNextFragment(
size_t start_pos, size_t* end_pos) {
if (profile_ < media::H264PROFILE_MAX) {
- size_t new_end_pos = start_pos;
*end_pos = start_pos;
- for (int i = 0; i < num_fragments_per_decode_; ++i) {
- GetBytesForNextNALU(*end_pos, &new_end_pos);
- if (*end_pos == new_end_pos)
- break;
- *end_pos = new_end_pos;
+ GetBytesForNextNALU(*end_pos, end_pos);
+ if (start_pos != *end_pos) {
num_queued_fragments_++;
}
return encoded_data_.substr(start_pos, *end_pos - start_pos);
}
DCHECK_LE(profile_, media::VP8PROFILE_MAX);
- return GetBytesForNextFrames(start_pos, end_pos);
+ return GetBytesForNextFrame(start_pos, end_pos);
}
void GLRenderingVDAClient::GetBytesForNextNALU(
@@ -849,26 +822,45 @@ void GLRenderingVDAClient::GetBytesForNextNALU(
*end_pos = encoded_data_.size();
}
-std::string GLRenderingVDAClient::GetBytesForNextFrames(
+std::string GLRenderingVDAClient::GetBytesForNextFrame(
size_t start_pos, size_t* end_pos) {
// Helpful description: http://wiki.multimedia.cx/index.php?title=IVF
std::string bytes;
if (start_pos == 0)
start_pos = 32; // Skip IVF header.
*end_pos = start_pos;
- for (int i = 0; i < num_fragments_per_decode_; ++i) {
- uint32 frame_size = *reinterpret_cast<uint32*>(&encoded_data_[*end_pos]);
- *end_pos += 12; // Skip frame header.
- bytes.append(encoded_data_.substr(*end_pos, frame_size));
- *end_pos += frame_size;
- num_queued_fragments_++;
- if (*end_pos + 12 >= encoded_data_.size())
- return bytes;
- }
+ uint32 frame_size = *reinterpret_cast<uint32*>(&encoded_data_[*end_pos]);
+ *end_pos += 12; // Skip frame header.
+ bytes.append(encoded_data_.substr(*end_pos, frame_size));
+ *end_pos += frame_size;
+ num_queued_fragments_++;
return bytes;
}
-void GLRenderingVDAClient::DecodeNextFragments() {
+static bool FragmentHasConfigInfo(const uint8* data, size_t size,
+ media::VideoCodecProfile profile) {
+ if (profile >= media::H264PROFILE_MIN &&
+ profile <= media::H264PROFILE_MAX) {
+ content::H264Parser parser;
+ parser.SetStream(data, size);
+ content::H264NALU nalu;
+ content::H264Parser::Result result = parser.AdvanceToNextNALU(&nalu);
+ if (result != content::H264Parser::kOk) {
+ // Let the VDA figure out there's something wrong with the stream.
+ return false;
+ }
+
+ return nalu.nal_unit_type == content::H264NALU::kSPS;
+ } else if (profile >= media::VP8PROFILE_MIN &&
+ profile <= media::VP8PROFILE_MAX) {
+ return (size > 0 && !(data[0] & 0x01));
+ }
+
+ CHECK(false) << "Invalid profile"; // Shouldn't happen at this point.
+ return false;
+}
+
+void GLRenderingVDAClient::DecodeNextFragment() {
if (decoder_deleted())
return;
if (encoded_data_next_pos_to_decode_ == encoded_data_.size()) {
@@ -881,14 +873,27 @@ void GLRenderingVDAClient::DecodeNextFragments() {
size_t end_pos;
std::string next_fragment_bytes;
if (encoded_data_next_pos_to_decode_ == 0) {
- next_fragment_bytes = GetBytesForFirstFragments(0, &end_pos);
+ next_fragment_bytes = GetBytesForFirstFragment(0, &end_pos);
} else {
next_fragment_bytes =
- GetBytesForNextFragments(encoded_data_next_pos_to_decode_, &end_pos);
+ GetBytesForNextFragment(encoded_data_next_pos_to_decode_, &end_pos);
}
size_t next_fragment_size = next_fragment_bytes.size();
- // Populate the shared memory buffer w/ the fragments, duplicate its handle,
+ // Call Reset() just after Decode() if the fragment contains config info.
+ // This tests how the VDA behaves when it gets a reset request before it has
+ // a chance to ProvidePictureBuffers().
+ bool reset_here = false;
+ if (reset_after_frame_num_ == RESET_AFTER_FIRST_CONFIG_INFO) {
+ reset_here = FragmentHasConfigInfo(
+ reinterpret_cast<const uint8*>(next_fragment_bytes.data()),
+ next_fragment_size,
+ profile_);
+ if (reset_here)
+ reset_after_frame_num_ = END_OF_STREAM_RESET;
+ }
+
+ // Populate the shared memory buffer w/ the fragment, duplicate its handle,
// and hand it off to the decoder.
base::SharedMemory shm;
CHECK(shm.CreateAndMapAnonymous(next_fragment_size));
@@ -897,16 +902,31 @@ void GLRenderingVDAClient::DecodeNextFragments() {
CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle));
media::BitstreamBuffer bitstream_buffer(
next_bitstream_buffer_id_, dup_handle, next_fragment_size);
+ decode_start_time_[next_bitstream_buffer_id_] = base::TimeTicks::Now();
// Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
decoder_->Decode(bitstream_buffer);
++outstanding_decodes_;
- encoded_data_next_pos_to_decode_ = end_pos;
-
if (!remaining_play_throughs_ &&
-delete_decoder_state_ == next_bitstream_buffer_id_) {
DeleteDecoder();
}
+
+ if (reset_here) {
+ reset_after_frame_num_ = MID_STREAM_RESET;
+ decoder_->Reset();
+ // Restart from the beginning to re-Decode() the SPS we just sent.
+ encoded_data_next_pos_to_decode_ = 0;
+ } else {
+ encoded_data_next_pos_to_decode_ = end_pos;
+ }
+
+ if (decode_calls_per_second_ > 0) {
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&GLRenderingVDAClient::DecodeNextFragment, AsWeakPtr()),
+ base::TimeDelta::FromSeconds(1) / decode_calls_per_second_);
+ }
}
int GLRenderingVDAClient::num_decoded_frames() {
@@ -921,8 +941,207 @@ double GLRenderingVDAClient::frames_per_second() {
return num_decoded_frames() / delta.InSecondsF();
}
+int GLRenderingVDAClient::decode_time_median() {
+ if (decode_time_.size() == 0)
+ return 0;
+ std::sort(decode_time_.begin(), decode_time_.end());
+ int index = decode_time_.size() / 2;
+ if (decode_time_.size() % 2 != 0)
+ return decode_time_[index].InMilliseconds();
+
+ return (decode_time_[index] + decode_time_[index - 1]).InMilliseconds() / 2;
+}
+
+class VideoDecodeAcceleratorTest : public ::testing::Test {
+ protected:
+ VideoDecodeAcceleratorTest();
+ virtual void SetUp();
+ virtual void TearDown();
+
+ // Parse |data| into its constituent parts, set the various output fields
+ // accordingly, and read in video stream. CHECK-fails on unexpected or
+ // missing required data. Unspecified optional fields are set to -1.
+ void ParseAndReadTestVideoData(base::FilePath::StringType data,
+ std::vector<TestVideoFile*>* test_video_files);
+
+ // Update the parameters of |test_video_files| according to
+ // |num_concurrent_decoders| and |reset_point|. Ex: the expected number of
+ // frames should be adjusted if decoder is reset in the middle of the stream.
+ void UpdateTestVideoFileParams(
+ size_t num_concurrent_decoders,
+ int reset_point,
+ std::vector<TestVideoFile*>* test_video_files);
+
+ void InitializeRenderingHelper(const RenderingHelperParams& helper_params);
+ void CreateAndStartDecoder(GLRenderingVDAClient* client,
+ ClientStateNotification<ClientState>* note);
+ void WaitUntilDecodeFinish(ClientStateNotification<ClientState>* note);
+ void WaitUntilIdle();
+ void OutputLogFile(const base::FilePath::CharType* log_path,
+ const std::string& content);
+
+ std::vector<TestVideoFile*> test_video_files_;
+ RenderingHelper rendering_helper_;
+ scoped_refptr<base::MessageLoopProxy> rendering_loop_proxy_;
+
+ private:
+ base::Thread rendering_thread_;
+ // Required for Thread to work. Not used otherwise.
+ base::ShadowingAtExitManager at_exit_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoDecodeAcceleratorTest);
+};
+
+VideoDecodeAcceleratorTest::VideoDecodeAcceleratorTest()
+ : rendering_thread_("GLRenderingVDAClientThread") {}
+
+void VideoDecodeAcceleratorTest::SetUp() {
+ ParseAndReadTestVideoData(g_test_video_data, &test_video_files_);
+
+ // Initialize the rendering thread.
+ base::Thread::Options options;
+ options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
+#if defined(OS_WIN)
+ // For windows the decoding thread initializes the media foundation decoder
+ // which uses COM. We need the thread to be a UI thread.
+ options.message_loop_type = base::MessageLoop::TYPE_UI;
+#endif // OS_WIN
+
+ rendering_thread_.StartWithOptions(options);
+ rendering_loop_proxy_ = rendering_thread_.message_loop_proxy();
+}
+
+void VideoDecodeAcceleratorTest::TearDown() {
+ rendering_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&STLDeleteElements<std::vector<TestVideoFile*> >,
+ &test_video_files_));
+
+ base::WaitableEvent done(false, false);
+ rendering_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&RenderingHelper::UnInitialize,
+ base::Unretained(&rendering_helper_),
+ &done));
+ done.Wait();
+
+ rendering_thread_.Stop();
+}
+
+void VideoDecodeAcceleratorTest::ParseAndReadTestVideoData(
+ base::FilePath::StringType data,
+ std::vector<TestVideoFile*>* test_video_files) {
+ std::vector<base::FilePath::StringType> entries;
+ base::SplitString(data, ';', &entries);
+ CHECK_GE(entries.size(), 1U) << data;
+ for (size_t index = 0; index < entries.size(); ++index) {
+ std::vector<base::FilePath::StringType> fields;
+ base::SplitString(entries[index], ':', &fields);
+ CHECK_GE(fields.size(), 1U) << entries[index];
+ CHECK_LE(fields.size(), 8U) << entries[index];
+ TestVideoFile* video_file = new TestVideoFile(fields[0]);
+ if (!fields[1].empty())
+ CHECK(base::StringToInt(fields[1], &video_file->width));
+ if (!fields[2].empty())
+ CHECK(base::StringToInt(fields[2], &video_file->height));
+ if (!fields[3].empty())
+ CHECK(base::StringToInt(fields[3], &video_file->num_frames));
+ if (!fields[4].empty())
+ CHECK(base::StringToInt(fields[4], &video_file->num_fragments));
+ if (!fields[5].empty())
+ CHECK(base::StringToInt(fields[5], &video_file->min_fps_render));
+ if (!fields[6].empty())
+ CHECK(base::StringToInt(fields[6], &video_file->min_fps_no_render));
+ int profile = -1;
+ if (!fields[7].empty())
+ CHECK(base::StringToInt(fields[7], &profile));
+ video_file->profile = static_cast<media::VideoCodecProfile>(profile);
+
+ // Read in the video data.
+ base::FilePath filepath(video_file->file_name);
+ CHECK(base::ReadFileToString(filepath, &video_file->data_str))
+ << "test_video_file: " << filepath.MaybeAsASCII();
+
+ test_video_files->push_back(video_file);
+ }
+}
+
+void VideoDecodeAcceleratorTest::UpdateTestVideoFileParams(
+ size_t num_concurrent_decoders,
+ int reset_point,
+ std::vector<TestVideoFile*>* test_video_files) {
+ for (size_t i = 0; i < test_video_files->size(); i++) {
+ TestVideoFile* video_file = (*test_video_files)[i];
+ if (reset_point == MID_STREAM_RESET) {
+ // Reset should not go beyond the last frame;
+ // reset in the middle of the stream for short videos.
+ video_file->reset_after_frame_num = kMaxResetAfterFrameNum;
+ if (video_file->num_frames <= video_file->reset_after_frame_num)
+ video_file->reset_after_frame_num = video_file->num_frames / 2;
+
+ video_file->num_frames += video_file->reset_after_frame_num;
+ } else {
+ video_file->reset_after_frame_num = reset_point;
+ }
+
+ if (video_file->min_fps_render != -1)
+ video_file->min_fps_render /= num_concurrent_decoders;
+ if (video_file->min_fps_no_render != -1)
+ video_file->min_fps_no_render /= num_concurrent_decoders;
+ }
+}
+
+void VideoDecodeAcceleratorTest::InitializeRenderingHelper(
+ const RenderingHelperParams& helper_params) {
+ base::WaitableEvent done(false, false);
+ rendering_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&RenderingHelper::Initialize,
+ base::Unretained(&rendering_helper_),
+ helper_params,
+ &done));
+ done.Wait();
+}
+
+void VideoDecodeAcceleratorTest::CreateAndStartDecoder(
+ GLRenderingVDAClient* client,
+ ClientStateNotification<ClientState>* note) {
+ rendering_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&GLRenderingVDAClient::CreateAndStartDecoder,
+ base::Unretained(client)));
+ ASSERT_EQ(note->Wait(), CS_DECODER_SET);
+}
+
+void VideoDecodeAcceleratorTest::WaitUntilDecodeFinish(
+ ClientStateNotification<ClientState>* note) {
+ for (int i = 0; i < CS_MAX; i++) {
+ if (note->Wait() == CS_DESTROYED)
+ break;
+ }
+}
+
+void VideoDecodeAcceleratorTest::WaitUntilIdle() {
+ base::WaitableEvent done(false, false);
+ rendering_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done)));
+ done.Wait();
+}
+
+void VideoDecodeAcceleratorTest::OutputLogFile(
+ const base::FilePath::CharType* log_path,
+ const std::string& content) {
+ base::PlatformFile file = base::CreatePlatformFile(
+ base::FilePath(log_path),
+ base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
+ NULL,
+ NULL);
+ base::WritePlatformFileAtCurrentPos(file, content.data(), content.length());
+ base::ClosePlatformFile(file);
+}
+
// Test parameters:
-// - Number of fragments per Decode() call.
// - Number of concurrent decoders.
// - Number of concurrent in-flight Decode() calls per decoder.
// - Number of play-throughs.
@@ -930,18 +1149,19 @@ double GLRenderingVDAClient::frames_per_second() {
// - delete_decoder_phase: see GLRenderingVDAClient ctor.
// - whether to test slow rendering by delaying ReusePictureBuffer().
// - whether the video frames are rendered as thumbnails.
-class VideoDecodeAcceleratorTest
- : public ::testing::TestWithParam<
- Tuple8<int, int, int, int, ResetPoint, ClientState, bool, bool> > {
+class VideoDecodeAcceleratorParamTest
+ : public VideoDecodeAcceleratorTest,
+ public ::testing::WithParamInterface<
+ Tuple7<int, int, int, ResetPoint, ClientState, bool, bool> > {
};
// Helper so that gtest failures emit a more readable version of the tuple than
// its byte representation.
::std::ostream& operator<<(
::std::ostream& os,
- const Tuple8<int, int, int, int, ResetPoint, ClientState, bool, bool>& t) {
+ const Tuple7<int, int, int, ResetPoint, ClientState, bool, bool>& t) {
return os << t.a << ", " << t.b << ", " << t.c << ", " << t.d << ", " << t.e
- << ", " << t.f << ", " << t.g << ", " << t.h;
+ << ", " << t.f << ", " << t.g;
}
// Wait for |note| to report a state and if it's not |expected_state| then
@@ -964,81 +1184,51 @@ enum { kMinSupportedNumConcurrentDecoders = 3 };
// Test the most straightforward case possible: data is decoded from a single
// chunk and rendered to the screen.
-TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
- // Required for Thread to work. Not used otherwise.
- base::ShadowingAtExitManager at_exit_manager;
-
- const int num_fragments_per_decode = GetParam().a;
- const size_t num_concurrent_decoders = GetParam().b;
- const size_t num_in_flight_decodes = GetParam().c;
- const int num_play_throughs = GetParam().d;
- const int reset_point = GetParam().e;
- const int delete_decoder_state = GetParam().f;
- bool test_reuse_delay = GetParam().g;
- const bool render_as_thumbnails = GetParam().h;
-
- std::vector<TestVideoFile*> test_video_files;
- ParseAndReadTestVideoData(g_test_video_data,
- num_concurrent_decoders,
- reset_point,
- &test_video_files);
+TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) {
+ const size_t num_concurrent_decoders = GetParam().a;
+ const size_t num_in_flight_decodes = GetParam().b;
+ const int num_play_throughs = GetParam().c;
+ const int reset_point = GetParam().d;
+ const int delete_decoder_state = GetParam().e;
+ bool test_reuse_delay = GetParam().f;
+ const bool render_as_thumbnails = GetParam().g;
+
+ UpdateTestVideoFileParams(
+ num_concurrent_decoders, reset_point, &test_video_files_);
// Suppress GL rendering for all tests when the "--disable_rendering" is set.
- // Otherwise, suppress rendering in all but a few tests, to cut down overall
- // test runtime.
- const bool suppress_rendering =
- num_fragments_per_decode > 1 || g_disable_rendering;
+ const bool suppress_rendering = g_disable_rendering;
std::vector<ClientStateNotification<ClientState>*>
notes(num_concurrent_decoders, NULL);
std::vector<GLRenderingVDAClient*> clients(num_concurrent_decoders, NULL);
- // Initialize the rendering helper.
- base::Thread rendering_thread("GLRenderingVDAClientThread");
- base::Thread::Options options;
- options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
-#if defined(OS_WIN)
- // For windows the decoding thread initializes the media foundation decoder
- // which uses COM. We need the thread to be a UI thread.
- options.message_loop_type = base::MessageLoop::TYPE_UI;
-#endif // OS_WIN
-
- rendering_thread.StartWithOptions(options);
- scoped_ptr<RenderingHelper> rendering_helper(RenderingHelper::Create());
-
- base::WaitableEvent done(false, false);
RenderingHelperParams helper_params;
helper_params.num_windows = num_concurrent_decoders;
helper_params.render_as_thumbnails = render_as_thumbnails;
if (render_as_thumbnails) {
// Only one decoder is supported with thumbnail rendering
CHECK_EQ(num_concurrent_decoders, 1U);
- gfx::Size frame_size(test_video_files[0]->width,
- test_video_files[0]->height);
+ gfx::Size frame_size(test_video_files_[0]->width,
+ test_video_files_[0]->height);
helper_params.frame_dimensions.push_back(frame_size);
helper_params.window_dimensions.push_back(kThumbnailsDisplaySize);
helper_params.thumbnails_page_size = kThumbnailsPageSize;
helper_params.thumbnail_size = kThumbnailSize;
} else {
- for (size_t index = 0; index < test_video_files.size(); ++index) {
- gfx::Size frame_size(test_video_files[index]->width,
- test_video_files[index]->height);
+ for (size_t index = 0; index < test_video_files_.size(); ++index) {
+ gfx::Size frame_size(test_video_files_[index]->width,
+ test_video_files_[index]->height);
helper_params.frame_dimensions.push_back(frame_size);
helper_params.window_dimensions.push_back(frame_size);
}
}
- rendering_thread.message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&RenderingHelper::Initialize,
- base::Unretained(rendering_helper.get()),
- helper_params,
- &done));
- done.Wait();
+ InitializeRenderingHelper(helper_params);
// First kick off all the decoders.
for (size_t index = 0; index < num_concurrent_decoders; ++index) {
TestVideoFile* video_file =
- test_video_files[index % test_video_files.size()];
+ test_video_files_[index % test_video_files_.size()];
ClientStateNotification<ClientState>* note =
new ClientStateNotification<ClientState>();
notes[index] = note;
@@ -1050,11 +1240,10 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
}
GLRenderingVDAClient* client =
- new GLRenderingVDAClient(rendering_helper.get(),
+ new GLRenderingVDAClient(&rendering_helper_,
index,
note,
video_file->data_str,
- num_fragments_per_decode,
num_in_flight_decodes,
num_play_throughs,
video_file->reset_after_frame_num,
@@ -1064,15 +1253,11 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
video_file->profile,
g_rendering_fps,
suppress_rendering,
- delay_after_frame_num);
+ delay_after_frame_num,
+ 0);
clients[index] = client;
- rendering_thread.message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&GLRenderingVDAClient::CreateDecoder,
- base::Unretained(client)));
-
- ASSERT_EQ(note->Wait(), CS_DECODER_SET);
+ CreateAndStartDecoder(client, note);
}
// Then wait for all the decodes to finish.
// Only check performance & correctness later if we play through only once.
@@ -1121,7 +1306,7 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
if (delete_decoder_state < CS_FLUSHED)
continue;
GLRenderingVDAClient* client = clients[i];
- TestVideoFile* video_file = test_video_files[i % test_video_files.size()];
+ TestVideoFile* video_file = test_video_files_[i % test_video_files_.size()];
if (video_file->num_frames > 0) {
// Expect the decoded frames may be more than the video frames as frames
// could still be returned until resetting done.
@@ -1134,10 +1319,9 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
EXPECT_EQ(video_file->num_fragments, client->num_skipped_fragments() +
client->num_queued_fragments());
EXPECT_EQ(client->num_done_bitstream_buffers(),
- ceil(static_cast<double>(client->num_queued_fragments()) /
- num_fragments_per_decode));
+ client->num_queued_fragments());
}
- LOG(INFO) << "Decoder " << i << " fps: " << client->frames_per_second();
+ VLOG(0) << "Decoder " << i << " fps: " << client->frames_per_second();
if (!render_as_thumbnails) {
int min_fps = suppress_rendering ?
video_file->min_fps_no_render : video_file->min_fps_render;
@@ -1149,17 +1333,18 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
if (render_as_thumbnails) {
std::vector<unsigned char> rgb;
bool alpha_solid;
- rendering_thread.message_loop()->PostTask(
+ base::WaitableEvent done(false, false);
+ rendering_loop_proxy_->PostTask(
FROM_HERE,
base::Bind(&RenderingHelper::GetThumbnailsAsRGB,
- base::Unretained(rendering_helper.get()),
+ base::Unretained(&rendering_helper_),
&rgb, &alpha_solid, &done));
done.Wait();
std::vector<std::string> golden_md5s;
std::string md5_string = base::MD5String(
base::StringPiece(reinterpret_cast<char*>(&rgb[0]), rgb.size()));
- ReadGoldenThumbnailMD5s(test_video_files[0], &golden_md5s);
+ ReadGoldenThumbnailMD5s(test_video_files_[0], &golden_md5s);
std::vector<std::string>::iterator match =
find(golden_md5s.begin(), golden_md5s.end(), md5_string);
if (match == golden_md5s.end()) {
@@ -1175,7 +1360,7 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
LOG(ERROR) << "Unknown thumbnails MD5: " << md5_string;
- base::FilePath filepath(test_video_files[0]->file_name);
+ base::FilePath filepath(test_video_files_[0]->file_name);
filepath = filepath.AddExtension(FILE_PATH_LITERAL(".bad_thumbnails"));
filepath = filepath.AddExtension(FILE_PATH_LITERAL(".png"));
int num_bytes = file_util::WriteFile(filepath,
@@ -1190,9 +1375,9 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
// Output the frame delivery time to file
// We can only make performance/correctness assertions if the decoder was
// allowed to finish.
- if (g_frame_delivery_log != NULL && delete_decoder_state >= CS_FLUSHED) {
+ if (g_output_log != NULL && delete_decoder_state >= CS_FLUSHED) {
base::PlatformFile output_file = base::CreatePlatformFile(
- base::FilePath(g_frame_delivery_log),
+ base::FilePath(g_output_log),
base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
NULL,
NULL);
@@ -1202,114 +1387,139 @@ TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) {
base::ClosePlatformFile(output_file);
}
- rendering_thread.message_loop()->PostTask(
+ rendering_loop_proxy_->PostTask(
FROM_HERE,
base::Bind(&STLDeleteElements<std::vector<GLRenderingVDAClient*> >,
&clients));
- rendering_thread.message_loop()->PostTask(
+ rendering_loop_proxy_->PostTask(
FROM_HERE,
base::Bind(&STLDeleteElements<
- std::vector<ClientStateNotification<ClientState>*> >,
- &notes));
- rendering_thread.message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&STLDeleteElements<std::vector<TestVideoFile*> >,
- &test_video_files));
- rendering_thread.message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&RenderingHelper::UnInitialize,
- base::Unretained(rendering_helper.get()),
- &done));
- done.Wait();
- rendering_thread.Stop();
+ std::vector<ClientStateNotification<ClientState>*> >,
+ &notes));
+ WaitUntilIdle();
};
// Test that replay after EOS works fine.
INSTANTIATE_TEST_CASE_P(
- ReplayAfterEOS, VideoDecodeAcceleratorTest,
+ ReplayAfterEOS, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false, false)));
+ MakeTuple(1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false, false)));
-// This hangs on Exynos, preventing further testing and wasting test machine
-// time.
-// TODO(ihf): Enable again once http://crbug.com/269754 is fixed.
-#if defined(ARCH_CPU_X86_FAMILY)
// Test that Reset() before the first Decode() works fine.
INSTANTIATE_TEST_CASE_P(
- ResetBeforeDecode, VideoDecodeAcceleratorTest,
+ ResetBeforeDecode, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, 1, START_OF_STREAM_RESET, CS_RESET, false, false)));
-#endif // ARCH_CPU_X86_FAMILY
+ MakeTuple(1, 1, 1, START_OF_STREAM_RESET, CS_RESET, false, false)));
+
+// Test Reset() immediately after Decode() containing config info.
+INSTANTIATE_TEST_CASE_P(
+ ResetAfterFirstConfigInfo, VideoDecodeAcceleratorParamTest,
+ ::testing::Values(
+ MakeTuple(
+ 1, 1, 1, RESET_AFTER_FIRST_CONFIG_INFO, CS_RESET, false, false)));
// Test that Reset() mid-stream works fine and doesn't affect decoding even when
// Decode() calls are made during the reset.
INSTANTIATE_TEST_CASE_P(
- MidStreamReset, VideoDecodeAcceleratorTest,
+ MidStreamReset, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, 1, MID_STREAM_RESET, CS_RESET, false, false)));
+ MakeTuple(1, 1, 1, MID_STREAM_RESET, CS_RESET, false, false)));
INSTANTIATE_TEST_CASE_P(
- SlowRendering, VideoDecodeAcceleratorTest,
+ SlowRendering, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, true, false)));
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, true, false)));
// Test that Destroy() mid-stream works fine (primarily this is testing that no
// crashes occur).
INSTANTIATE_TEST_CASE_P(
- TearDownTiming, VideoDecodeAcceleratorTest,
+ TearDownTiming, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_DECODER_SET, false,
- false),
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_INITIALIZED, false,
- false),
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHING, false, false),
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHED, false, false),
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING, false, false),
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET,
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_DECODER_SET, false, false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_INITIALIZED, false, false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHING, false, false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHED, false, false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING, false, false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET,
static_cast<ClientState>(-1), false, false),
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET,
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET,
static_cast<ClientState>(-10), false, false),
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET,
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET,
static_cast<ClientState>(-100), false, false)));
-// Test that decoding various variation works: multiple fragments per Decode()
-// call and multiple in-flight decodes.
+// Test that decoding various variation works with multiple in-flight decodes.
INSTANTIATE_TEST_CASE_P(
- DecodeVariations, VideoDecodeAcceleratorTest,
+ DecodeVariations, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
- MakeTuple(1, 1, 10, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
+ MakeTuple(1, 10, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
// Tests queuing.
- MakeTuple(1, 1, 15, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
- MakeTuple(2, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
- MakeTuple(3, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
- MakeTuple(5, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
- MakeTuple(8, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false),
- // TODO(fischman): decoding more than 15 NALUs at once breaks decode -
- // visual artifacts are introduced as well as spurious frames are
- // delivered (more pictures are returned than NALUs are fed to the
- // decoder). Increase the "15" below when
- // http://code.google.com/p/chrome-os-partner/issues/detail?id=4378 is
- // fixed.
- MakeTuple(15, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, false)));
+ MakeTuple(1, 15, 1, END_OF_STREAM_RESET, CS_RESET, false, false)));
// Find out how many concurrent decoders can go before we exhaust system
// resources.
INSTANTIATE_TEST_CASE_P(
- ResourceExhaustion, VideoDecodeAcceleratorTest,
+ ResourceExhaustion, VideoDecodeAcceleratorParamTest,
::testing::Values(
// +0 hack below to promote enum to int.
- MakeTuple(1, kMinSupportedNumConcurrentDecoders + 0, 1, 1,
+ MakeTuple(kMinSupportedNumConcurrentDecoders + 0, 1, 1,
END_OF_STREAM_RESET, CS_RESET, false, false),
- MakeTuple(1, kMinSupportedNumConcurrentDecoders + 1, 1, 1,
+ MakeTuple(kMinSupportedNumConcurrentDecoders + 1, 1, 1,
END_OF_STREAM_RESET, CS_RESET, false, false)));
// Thumbnailing test
INSTANTIATE_TEST_CASE_P(
- Thumbnail, VideoDecodeAcceleratorTest,
+ Thumbnail, VideoDecodeAcceleratorParamTest,
::testing::Values(
- MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, true)));
+ MakeTuple(1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false, true)));
+
+// Measure the median of the decode time when VDA::Decode is called 30 times per
+// second.
+TEST_F(VideoDecodeAcceleratorTest, TestDecodeTimeMedian) {
+ RenderingHelperParams helper_params;
+ helper_params.num_windows = 1;
+ helper_params.render_as_thumbnails = false;
+ gfx::Size frame_size(test_video_files_[0]->width,
+ test_video_files_[0]->height);
+ helper_params.frame_dimensions.push_back(frame_size);
+ helper_params.window_dimensions.push_back(frame_size);
+ InitializeRenderingHelper(helper_params);
+
+ ClientStateNotification<ClientState>* note =
+ new ClientStateNotification<ClientState>();
+ GLRenderingVDAClient* client =
+ new GLRenderingVDAClient(&rendering_helper_,
+ 0,
+ note,
+ test_video_files_[0]->data_str,
+ 1,
+ 1,
+ test_video_files_[0]->reset_after_frame_num,
+ CS_RESET,
+ test_video_files_[0]->width,
+ test_video_files_[0]->height,
+ test_video_files_[0]->profile,
+ g_rendering_fps,
+ true,
+ std::numeric_limits<int>::max(),
+ kWebRtcDecodeCallsPerSecond);
+ CreateAndStartDecoder(client, note);
+ WaitUntilDecodeFinish(note);
+
+ int decode_time_median = client->decode_time_median();
+ std::string output_string =
+ base::StringPrintf("Decode time median: %d ms", decode_time_median);
+ VLOG(0) << output_string;
+ ASSERT_GT(decode_time_median, 0);
+
+ if (g_output_log != NULL)
+ OutputLogFile(g_output_log, output_string);
+
+ rendering_loop_proxy_->DeleteSoon(FROM_HERE, client);
+ rendering_loop_proxy_->DeleteSoon(FROM_HERE, note);
+ WaitUntilIdle();
+};
// TODO(fischman, vrk): add more tests! In particular:
// - Test life-cycle: Seek/Stop/Pause/Play for a single decoder.
@@ -1341,8 +1551,10 @@ int main(int argc, char **argv) {
content::g_test_video_data = it->second.c_str();
continue;
}
- if (it->first == "frame_delivery_log") {
- content::g_frame_delivery_log = it->second.c_str();
+ // TODO(wuchengli): remove frame_deliver_log after CrOS test get updated.
+ // See http://crosreview.com/175426.
+ if (it->first == "frame_delivery_log" || it->first == "output_log") {
+ content::g_output_log = it->second.c_str();
continue;
}
if (it->first == "rendering_fps") {
@@ -1363,15 +1575,5 @@ int main(int argc, char **argv) {
base::ShadowingAtExitManager at_exit_manager;
-#if defined(OS_WIN)
- content::DXVAVideoDecodeAccelerator::PreSandboxInitialization();
-#elif defined(OS_CHROMEOS)
-#if defined(ARCH_CPU_ARMEL)
- content::ExynosVideoDecodeAccelerator::PreSandboxInitialization();
-#elif defined(ARCH_CPU_X86_FAMILY)
- content::VaapiWrapper::PreSandboxInitialization();
-#endif // ARCH_CPU_ARMEL
-#endif // OS_CHROMEOS
-
return RUN_ALL_TESTS();
}
diff --git a/chromium/content/common/gpu/surface_capturer.h b/chromium/content/common/gpu/surface_capturer.h
deleted file mode 100644
index 77bfe5ad310..00000000000
--- a/chromium/content/common/gpu/surface_capturer.h
+++ /dev/null
@@ -1,100 +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_COMMON_GPU_SURFACE_CAPTURER_H_
-#define CONTENT_COMMON_GPU_SURFACE_CAPTURER_H_
-
-#include "content/common/content_export.h"
-#include "media/base/video_frame.h"
-
-namespace gfx {
-
-class Size;
-class Rect;
-
-} // namespace ui
-
-namespace content {
-
-// Surface capturer interface. This interface is implemented by classes
-// that perform image capturing from the backbuffer.
-class CONTENT_EXPORT SurfaceCapturer {
- public:
- enum Error {
- // Invalid argument was passed to an API method.
- kInvalidArgumentError,
- // A failure occurred at the GPU process or one of its dependencies.
- // Examples of such failures include GPU hardware failures, GPU driver
- // failures, GPU library failures, GPU process programming errors, and so
- // on.
- kPlatformFailureError,
- };
-
- class CONTENT_EXPORT Client {
- public:
- // Callback to notify client of parameters of the backbuffer capture. Every
- // time the Client receives this callback, subsequent media::VideoFrames
- // passed to CopyCaptureToVideoFrame() should mind the new parameters.
- // Parameters:
- // |buffer_size| is the required logical size (in pixels) of the buffer
- // to capture to (corresponds to |frame->coded_size()| in
- // CopyCaptureToVideoFrame().
- // |visible_rect| is the visible subrect of the actual screen capture
- // contents in the buffer to capture to (corresponds to
- // |frame->visible_rect()| in CopyCaptureToVideoFrame().
- virtual void NotifyCaptureParameters(const gfx::Size& buffer_size,
- const gfx::Rect& visible_rect) = 0;
-
- // Callback to notify client that CopyCaptureToVideoFrame() has been
- // completed for |frame|. After this call, the capturer will drop all its
- // outstanding references to |frame|.
- // Parameters:
- // |frame| is the completed copied captured frame.
- virtual void NotifyCopyCaptureDone(
- const scoped_refptr<media::VideoFrame>& frame) = 0;
-
- // Error notification callback.
- // Parameters:
- // |error| is the error to report.
- virtual void NotifyError(Error error) = 0;
-
- protected:
- // Clients are not owned by Capturer instances and should not be deleted
- // through these pointers.
- virtual ~Client() {}
- };
-
- // Initialize the capturer to a specific configuration.
- // Parameters:
- // |format| is the format to capture to (corresponds to |frame->format()| in
- // CopyCaptureToVideoFrame()). The NotifyCaptureParameters() callback is
- // made to the Client on success; on failure, a NotifyError() callback is
- // performed.
- virtual void Initialize(media::VideoFrame::Format format) = 0;
-
- // Attempt to capture a single frame. This call is advisory to note to the
- // SurfaceCapturer that capture should be attempted at this time; success is
- // not guaranteed. The most recent captured frame is cached internally, and
- // its contents returned every time CopyCaptureToVideoFrame() is called.
- virtual void TryCapture() = 0;
-
- // Copy the most recent captured contents to |frame|.
- // Parameters:
- // |frame| is the media::VideoFrame to fill with captured contents.
- virtual void CopyCaptureToVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame) = 0;
-
- // Destroys the capturer; all pending inputs and outputs are dropped
- // immediately and the component is freed. This call may asynchronously free
- // system resources, but its client-visible effects are synchronous. After
- // this method returns no more callbacks will be made on the client. Deletes
- // |this| unconditionally, so make sure to drop all pointers to it!
- virtual void Destroy() = 0;
-
- virtual ~SurfaceCapturer();
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_SURFACE_CAPTURER_H_
diff --git a/chromium/content/common/gpu/texture_image_transport_surface.cc b/chromium/content/common/gpu/texture_image_transport_surface.cc
index f42780e2f89..88145e64315 100644
--- a/chromium/content/common/gpu/texture_image_transport_surface.cc
+++ b/chromium/content/common/gpu/texture_image_transport_surface.cc
@@ -196,6 +196,10 @@ void TextureImageTransportSurface::SetLatencyInfo(
latency_info_ = latency_info;
}
+void TextureImageTransportSurface::WakeUpGpu() {
+ NOTIMPLEMENTED();
+}
+
bool TextureImageTransportSurface::SwapBuffers() {
DCHECK(IsContextValid(helper_.get()));
DCHECK(backbuffer_suggested_allocation_);
@@ -369,8 +373,7 @@ void TextureImageTransportSurface::ReleaseFrontTexture() {
front_mailbox_name_ = MailboxName();
glFlush();
CHECK_GL_ERROR();
- GpuHostMsg_AcceleratedSurfaceRelease_Params params;
- helper_->SendAcceleratedSurfaceRelease(params);
+ helper_->SendAcceleratedSurfaceRelease();
}
void TextureImageTransportSurface::CreateBackTexture() {
diff --git a/chromium/content/common/gpu/texture_image_transport_surface.h b/chromium/content/common/gpu/texture_image_transport_surface.h
index 68d81d17e66..4afe53451de 100644
--- a/chromium/content/common/gpu/texture_image_transport_surface.h
+++ b/chromium/content/common/gpu/texture_image_transport_surface.h
@@ -54,6 +54,7 @@ class TextureImageTransportSurface
virtual void OnResize(gfx::Size size, float scale_factor) OVERRIDE;
virtual void SetLatencyInfo(
const ui::LatencyInfo& latency_info) OVERRIDE;
+ virtual void WakeUpGpu() OVERRIDE;
// GpuCommandBufferStub::DestructionObserver implementation.
virtual void OnWillDestroyStub() OVERRIDE;
diff --git a/chromium/content/common/handle_enumerator_win.cc b/chromium/content/common/handle_enumerator_win.cc
index 4e17aa2ca7d..7cda767294f 100644
--- a/chromium/content/common/handle_enumerator_win.cc
+++ b/chromium/content/common/handle_enumerator_win.cc
@@ -19,7 +19,7 @@
namespace content {
namespace {
-typedef std::map<const string16, HandleType> HandleTypeMap;
+typedef std::map<const base::string16, HandleType> HandleTypeMap;
HandleTypeMap& MakeHandleTypeMap() {
HandleTypeMap& handle_types = *(new HandleTypeMap());
@@ -52,7 +52,7 @@ void HandleEnumerator::EnumerateHandles() {
std::string process_type =
CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessType);
- string16 output = ASCIIToUTF16(process_type);
+ base::string16 output = ASCIIToUTF16(process_type);
output.append(ASCIIToUTF16(" process - Handles at shutdown:\n"));
for (sandbox::HandleTable::Iterator sys_handle
= handles.HandlesForProcess(::GetCurrentProcessId());
@@ -75,18 +75,18 @@ void HandleEnumerator::EnumerateHandles() {
output += GetAccessString(current_type,
sys_handle->handle_entry()->GrantedAccess);
}
- DLOG(INFO) << output;
+ DVLOG(0) << output;
}
-HandleType StringToHandleType(const string16& type) {
+HandleType StringToHandleType(const base::string16& type) {
static HandleTypeMap handle_types = MakeHandleTypeMap();
HandleTypeMap::iterator result = handle_types.find(type);
return result != handle_types.end() ? result->second : OtherHandle;
}
-string16 GetAccessString(HandleType handle_type,
+base::string16 GetAccessString(HandleType handle_type,
ACCESS_MASK access) {
- string16 output;
+ base::string16 output;
if (access & GENERIC_READ)
output.append(ASCIIToUTF16("\tGENERIC_READ\n"));
if (access & GENERIC_WRITE)
diff --git a/chromium/content/common/handle_enumerator_win.h b/chromium/content/common/handle_enumerator_win.h
index 5fd49813760..3caba84971e 100644
--- a/chromium/content/common/handle_enumerator_win.h
+++ b/chromium/content/common/handle_enumerator_win.h
@@ -31,9 +31,10 @@ enum HandleType {
OtherHandle
};
-static HandleType StringToHandleType(const string16& type);
+static HandleType StringToHandleType(const base::string16& type);
-static string16 GetAccessString(HandleType handle_type, ACCESS_MASK access);
+static base::string16 GetAccessString(HandleType handle_type,
+ ACCESS_MASK access);
class HandleEnumerator : public base::RefCountedThreadSafe<HandleEnumerator> {
public:
diff --git a/chromium/content/common/indexed_db/indexed_db_constants.h b/chromium/content/common/indexed_db/indexed_db_constants.h
new file mode 100644
index 00000000000..5c7377ba13f
--- /dev/null
+++ b/chromium/content/common/indexed_db/indexed_db_constants.h
@@ -0,0 +1,14 @@
+// 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_COMMON_INDEXED_DB_INDEXED_DB_CONSTANTS_H_
+#define CONTENT_COMMON_INDEXED_DB_INDEXED_DB_CONSTANTS_H_
+
+namespace content {
+
+const int32 kNoDatabase = -1;
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INDEXED_DB_INDEXED_DB_CONSTANTS_H_
diff --git a/chromium/content/common/indexed_db/indexed_db_key.cc b/chromium/content/common/indexed_db/indexed_db_key.cc
index e84d3781ef7..02610bfe241 100644
--- a/chromium/content/common/indexed_db/indexed_db_key.cc
+++ b/chromium/content/common/indexed_db/indexed_db_key.cc
@@ -9,15 +9,16 @@
namespace content {
-using WebKit::WebIDBKey;
-using WebKit::WebIDBKeyType;
-using WebKit::WebIDBKeyTypeArray;
-using WebKit::WebIDBKeyTypeDate;
-using WebKit::WebIDBKeyTypeInvalid;
-using WebKit::WebIDBKeyTypeMin;
-using WebKit::WebIDBKeyTypeNull;
-using WebKit::WebIDBKeyTypeNumber;
-using WebKit::WebIDBKeyTypeString;
+using blink::WebIDBKey;
+using blink::WebIDBKeyType;
+using blink::WebIDBKeyTypeArray;
+using blink::WebIDBKeyTypeBinary;
+using blink::WebIDBKeyTypeDate;
+using blink::WebIDBKeyTypeInvalid;
+using blink::WebIDBKeyTypeMin;
+using blink::WebIDBKeyTypeNull;
+using blink::WebIDBKeyTypeNumber;
+using blink::WebIDBKeyTypeString;
namespace {
@@ -69,11 +70,17 @@ IndexedDBKey::IndexedDBKey(const KeyArray& keys)
number_(0),
size_estimate_(kOverheadSize + CalculateArraySize(keys)) {}
-IndexedDBKey::IndexedDBKey(const string16& key)
+IndexedDBKey::IndexedDBKey(const std::string& key)
+ : type_(WebIDBKeyTypeBinary),
+ binary_(key),
+ size_estimate_(kOverheadSize +
+ (key.length() * sizeof(std::string::value_type))) {}
+
+IndexedDBKey::IndexedDBKey(const base::string16& key)
: type_(WebIDBKeyTypeString),
string_(key),
size_estimate_(kOverheadSize +
- (key.length() * sizeof(string16::value_type))) {}
+ (key.length() * sizeof(base::string16::value_type))) {}
IndexedDBKey::~IndexedDBKey() {}
@@ -94,8 +101,10 @@ int IndexedDBKey::Compare(const IndexedDBKey& other) const {
if (array_.size() > other.array_.size())
return 1;
return 0;
+ case WebIDBKeyTypeBinary:
+ return binary_.compare(other.binary_);
case WebIDBKeyTypeString:
- return -other.string_.compare(string_);
+ return string_.compare(other.string_);
case WebIDBKeyTypeDate:
return (date_ < other.date_) ? -1 : (date_ > other.date_) ? 1 : 0;
case WebIDBKeyTypeNumber:
@@ -103,6 +112,7 @@ int IndexedDBKey::Compare(const IndexedDBKey& other) const {
case WebIDBKeyTypeInvalid:
case WebIDBKeyTypeNull:
case WebIDBKeyTypeMin:
+ default:
NOTREACHED();
return 0;
}
diff --git a/chromium/content/common/indexed_db/indexed_db_key.h b/chromium/content/common/indexed_db/indexed_db_key.h
index f453b3ab865..391b6d63fc6 100644
--- a/chromium/content/common/indexed_db/indexed_db_key.h
+++ b/chromium/content/common/indexed_db/indexed_db_key.h
@@ -13,7 +13,7 @@
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebIDBTypes.h"
-namespace WebKit {
+namespace blink {
class WebIDBKey;
}
@@ -23,12 +23,13 @@ class CONTENT_EXPORT IndexedDBKey {
public:
typedef std::vector<IndexedDBKey> KeyArray;
- IndexedDBKey(); // Defaults to WebKit::WebIDBKeyTypeInvalid.
- IndexedDBKey(WebKit::WebIDBKeyType); // must be Null or Invalid
+ IndexedDBKey(); // Defaults to blink::WebIDBKeyTypeInvalid.
+ IndexedDBKey(blink::WebIDBKeyType); // must be Null or Invalid
explicit IndexedDBKey(const KeyArray& array);
- explicit IndexedDBKey(const string16& str);
+ explicit IndexedDBKey(const std::string& binary);
+ explicit IndexedDBKey(const base::string16& str);
IndexedDBKey(double number,
- WebKit::WebIDBKeyType type); // must be date or number
+ blink::WebIDBKeyType type); // must be date or number
~IndexedDBKey();
bool IsValid() const;
@@ -37,18 +38,20 @@ class CONTENT_EXPORT IndexedDBKey {
bool IsLessThan(const IndexedDBKey& other) const;
bool IsEqual(const IndexedDBKey& other) const;
- WebKit::WebIDBKeyType type() const { return type_; }
+ blink::WebIDBKeyType type() const { return type_; }
const std::vector<IndexedDBKey>& array() const { return array_; }
- const string16& string() const { return string_; }
+ const std::string& binary() const { return binary_; }
+ const base::string16& string() const { return string_; }
double date() const { return date_; }
double number() const { return number_; }
size_t size_estimate() const { return size_estimate_; }
private:
- WebKit::WebIDBKeyType type_;
+ blink::WebIDBKeyType type_;
std::vector<IndexedDBKey> array_;
- string16 string_;
+ std::string binary_;
+ base::string16 string_;
double date_;
double number_;
diff --git a/chromium/content/common/indexed_db/indexed_db_key_path.cc b/chromium/content/common/indexed_db/indexed_db_key_path.cc
index be6adfd31ff..3783d4281a8 100644
--- a/chromium/content/common/indexed_db/indexed_db_key_path.cc
+++ b/chromium/content/common/indexed_db/indexed_db_key_path.cc
@@ -8,27 +8,27 @@
namespace content {
-using WebKit::WebIDBKeyPathTypeArray;
-using WebKit::WebIDBKeyPathTypeNull;
-using WebKit::WebIDBKeyPathTypeString;
+using blink::WebIDBKeyPathTypeArray;
+using blink::WebIDBKeyPathTypeNull;
+using blink::WebIDBKeyPathTypeString;
IndexedDBKeyPath::IndexedDBKeyPath() : type_(WebIDBKeyPathTypeNull) {}
-IndexedDBKeyPath::IndexedDBKeyPath(const string16& string)
+IndexedDBKeyPath::IndexedDBKeyPath(const base::string16& string)
: type_(WebIDBKeyPathTypeString), string_(string) {}
-IndexedDBKeyPath::IndexedDBKeyPath(const std::vector<string16>& array)
+IndexedDBKeyPath::IndexedDBKeyPath(const std::vector<base::string16>& array)
: type_(WebIDBKeyPathTypeArray), array_(array) {}
IndexedDBKeyPath::~IndexedDBKeyPath() {}
-const std::vector<string16>& IndexedDBKeyPath::array() const {
- DCHECK(type_ == WebKit::WebIDBKeyPathTypeArray);
+const std::vector<base::string16>& IndexedDBKeyPath::array() const {
+ DCHECK(type_ == blink::WebIDBKeyPathTypeArray);
return array_;
}
-const string16& IndexedDBKeyPath::string() const {
- DCHECK(type_ == WebKit::WebIDBKeyPathTypeString);
+const base::string16& IndexedDBKeyPath::string() const {
+ DCHECK(type_ == blink::WebIDBKeyPathTypeString);
return string_;
}
diff --git a/chromium/content/common/indexed_db/indexed_db_key_path.h b/chromium/content/common/indexed_db/indexed_db_key_path.h
index 1baae2f00ec..ec5e8611b23 100644
--- a/chromium/content/common/indexed_db/indexed_db_key_path.h
+++ b/chromium/content/common/indexed_db/indexed_db_key_path.h
@@ -16,22 +16,22 @@ namespace content {
class CONTENT_EXPORT IndexedDBKeyPath {
public:
- IndexedDBKeyPath(); // Defaults to WebKit::WebIDBKeyPathTypeNull.
- explicit IndexedDBKeyPath(const string16&);
- explicit IndexedDBKeyPath(const std::vector<string16>&);
+ IndexedDBKeyPath(); // Defaults to blink::WebIDBKeyPathTypeNull.
+ explicit IndexedDBKeyPath(const base::string16&);
+ explicit IndexedDBKeyPath(const std::vector<base::string16>&);
~IndexedDBKeyPath();
- bool IsNull() const { return type_ == WebKit::WebIDBKeyPathTypeNull; }
+ bool IsNull() const { return type_ == blink::WebIDBKeyPathTypeNull; }
bool operator==(const IndexedDBKeyPath& other) const;
- WebKit::WebIDBKeyPathType type() const { return type_; }
- const std::vector<string16>& array() const;
- const string16& string() const;
+ blink::WebIDBKeyPathType type() const { return type_; }
+ const std::vector<base::string16>& array() const;
+ const base::string16& string() const;
private:
- WebKit::WebIDBKeyPathType type_;
- string16 string_;
- std::vector<string16> array_;
+ blink::WebIDBKeyPathType type_;
+ base::string16 string_;
+ std::vector<base::string16> array_;
};
} // namespace content
diff --git a/chromium/content/common/indexed_db/indexed_db_key_range.cc b/chromium/content/common/indexed_db/indexed_db_key_range.cc
index 2c113eefe94..fa16ddf6676 100644
--- a/chromium/content/common/indexed_db/indexed_db_key_range.cc
+++ b/chromium/content/common/indexed_db/indexed_db_key_range.cc
@@ -10,8 +10,8 @@
namespace content {
IndexedDBKeyRange::IndexedDBKeyRange()
- : lower_(WebKit::WebIDBKeyTypeNull),
- upper_(WebKit::WebIDBKeyTypeNull),
+ : lower_(blink::WebIDBKeyTypeNull),
+ upper_(blink::WebIDBKeyTypeNull),
lower_open_(false),
upper_open_(false) {}
diff --git a/chromium/content/common/indexed_db/indexed_db_key_unittest.cc b/chromium/content/common/indexed_db/indexed_db_key_unittest.cc
index 3c5191513c7..ca52cc4a134 100644
--- a/chromium/content/common/indexed_db/indexed_db_key_unittest.cc
+++ b/chromium/content/common/indexed_db/indexed_db_key_unittest.cc
@@ -21,18 +21,18 @@ TEST(IndexedDBKeyTest, KeySizeEstimates) {
keys.push_back(IndexedDBKey());
estimates.push_back(static_cast<size_t>(16)); // Overhead.
- keys.push_back(IndexedDBKey(WebKit::WebIDBKeyTypeNull));
+ keys.push_back(IndexedDBKey(blink::WebIDBKeyTypeNull));
estimates.push_back(static_cast<size_t>(16));
double number = 3.14159;
- keys.push_back(IndexedDBKey(number, WebKit::WebIDBKeyTypeNumber));
+ keys.push_back(IndexedDBKey(number, blink::WebIDBKeyTypeNumber));
estimates.push_back(static_cast<size_t>(24)); // Overhead + sizeof(double).
double date = 1370884329.0;
- keys.push_back(IndexedDBKey(date, WebKit::WebIDBKeyTypeDate));
+ keys.push_back(IndexedDBKey(date, blink::WebIDBKeyTypeDate));
estimates.push_back(static_cast<size_t>(24)); // Overhead + sizeof(double).
- const string16 string(1024, static_cast<char16>('X'));
+ const base::string16 string(1024, static_cast<char16>('X'));
keys.push_back(IndexedDBKey(string));
// Overhead + string length * sizeof(char16).
estimates.push_back(static_cast<size_t>(2064));
@@ -41,7 +41,7 @@ TEST(IndexedDBKeyTest, KeySizeEstimates) {
IndexedDBKey::KeyArray array;
double value = 123.456;
for (size_t i = 0; i < array_size; ++i) {
- array.push_back(IndexedDBKey(value, WebKit::WebIDBKeyTypeNumber));
+ array.push_back(IndexedDBKey(value, blink::WebIDBKeyTypeNumber));
}
keys.push_back(IndexedDBKey(array));
// Overhead + array length * (Overhead + sizeof(double)).
diff --git a/chromium/content/common/indexed_db/indexed_db_messages.h b/chromium/content/common/indexed_db/indexed_db_messages.h
index 918be9d3a01..047fd0ce488 100644
--- a/chromium/content/common/indexed_db/indexed_db_messages.h
+++ b/chromium/content/common/indexed_db/indexed_db_messages.h
@@ -19,12 +19,11 @@
// Argument structures used in messages
-IPC_ENUM_TRAITS(WebKit::WebIDBCursor::Direction)
-IPC_ENUM_TRAITS(WebKit::WebIDBDatabase::PutMode)
-IPC_ENUM_TRAITS(WebKit::WebIDBDatabase::TaskType)
+IPC_ENUM_TRAITS(blink::WebIDBCursor::Direction)
+IPC_ENUM_TRAITS(blink::WebIDBDatabase::PutMode)
+IPC_ENUM_TRAITS(blink::WebIDBDatabase::TaskType)
-IPC_ENUM_TRAITS_MAX_VALUE(WebKit::WebIDBCallbacks::DataLoss,
- WebKit::WebIDBCallbacks::DataLossTotal)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebIDBDataLoss, blink::WebIDBDataLossTotal)
// Used to enumerate indexed databases.
IPC_STRUCT_BEGIN(IndexedDBHostMsg_FactoryGetDatabaseNames_Params)
@@ -46,7 +45,7 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_FactoryOpen_Params)
// The string id of the origin doing the initiating.
IPC_STRUCT_MEMBER(std::string, database_identifier)
// The name of the database.
- IPC_STRUCT_MEMBER(string16, name)
+ IPC_STRUCT_MEMBER(base::string16, name)
// The transaction id used if a database upgrade is needed.
IPC_STRUCT_MEMBER(int64, transaction_id)
// The requested version of the database.
@@ -61,7 +60,7 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_FactoryDeleteDatabase_Params)
// The string id of the origin doing the initiating.
IPC_STRUCT_MEMBER(std::string, database_identifier)
// The name of the database.
- IPC_STRUCT_MEMBER(string16, name)
+ IPC_STRUCT_MEMBER(base::string16, name)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(IndexedDBHostMsg_DatabaseCreateTransaction_Params)
@@ -87,7 +86,7 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_DatabaseCreateObjectStore_Params)
// The storage id of the object store.
IPC_STRUCT_MEMBER(int64, object_store_id)
// The name of the object store.
- IPC_STRUCT_MEMBER(string16, name)
+ IPC_STRUCT_MEMBER(base::string16, name)
// The keyPath of the object store.
IPC_STRUCT_MEMBER(content::IndexedDBKeyPath, key_path)
// Whether the object store created should have a key generator.
@@ -130,7 +129,7 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_DatabasePut_Params)
// The key to set it on (may not be "valid"/set in some cases).
IPC_STRUCT_MEMBER(content::IndexedDBKey, key)
// Whether this is an add or a put.
- IPC_STRUCT_MEMBER(WebKit::WebIDBDatabase::PutMode, put_mode)
+ IPC_STRUCT_MEMBER(blink::WebIDBDatabase::PutMode, put_mode)
// The names of the indexes used below.
IPC_STRUCT_MEMBER(std::vector<int64>, index_ids)
// The keys for each index, such that each inner vector corresponds
@@ -159,7 +158,7 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_DatabaseOpenCursor_Params)
// If this is just retrieving the key
IPC_STRUCT_MEMBER(bool, key_only)
// The priority of this cursor.
- IPC_STRUCT_MEMBER(WebKit::WebIDBDatabase::TaskType, task_type)
+ IPC_STRUCT_MEMBER(blink::WebIDBDatabase::TaskType, task_type)
IPC_STRUCT_END()
// Used to open both cursors and object cursors in IndexedDB.
@@ -220,7 +219,7 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_DatabaseCreateIndex_Params)
// The storage id of the index.
IPC_STRUCT_MEMBER(int64, index_id)
// The name of the index.
- IPC_STRUCT_MEMBER(string16, name)
+ IPC_STRUCT_MEMBER(base::string16, name)
// The keyPath of the index.
IPC_STRUCT_MEMBER(content::IndexedDBKeyPath, key_path)
// Whether the index created has unique keys.
@@ -258,7 +257,7 @@ IPC_STRUCT_END()
IPC_STRUCT_BEGIN(IndexedDBIndexMetadata)
IPC_STRUCT_MEMBER(int64, id)
- IPC_STRUCT_MEMBER(string16, name)
+ IPC_STRUCT_MEMBER(base::string16, name)
IPC_STRUCT_MEMBER(content::IndexedDBKeyPath, keyPath)
IPC_STRUCT_MEMBER(bool, unique)
IPC_STRUCT_MEMBER(bool, multiEntry)
@@ -266,7 +265,7 @@ IPC_STRUCT_END()
IPC_STRUCT_BEGIN(IndexedDBObjectStoreMetadata)
IPC_STRUCT_MEMBER(int64, id)
- IPC_STRUCT_MEMBER(string16, name)
+ IPC_STRUCT_MEMBER(base::string16, name)
IPC_STRUCT_MEMBER(content::IndexedDBKeyPath, keyPath)
IPC_STRUCT_MEMBER(bool, autoIncrement)
IPC_STRUCT_MEMBER(int64, max_index_id)
@@ -275,8 +274,8 @@ IPC_STRUCT_END()
IPC_STRUCT_BEGIN(IndexedDBDatabaseMetadata)
IPC_STRUCT_MEMBER(int64, id)
- IPC_STRUCT_MEMBER(string16, name)
- IPC_STRUCT_MEMBER(string16, version)
+ IPC_STRUCT_MEMBER(base::string16, name)
+ IPC_STRUCT_MEMBER(base::string16, version)
IPC_STRUCT_MEMBER(int64, int_version)
IPC_STRUCT_MEMBER(int64, max_object_store_id)
IPC_STRUCT_MEMBER(std::vector<IndexedDBObjectStoreMetadata>, object_stores)
@@ -288,7 +287,8 @@ IPC_STRUCT_BEGIN(IndexedDBMsg_CallbacksUpgradeNeeded_Params)
IPC_STRUCT_MEMBER(int32, ipc_database_callbacks_id)
IPC_STRUCT_MEMBER(int32, ipc_database_id)
IPC_STRUCT_MEMBER(int64, old_version)
- IPC_STRUCT_MEMBER(WebKit::WebIDBCallbacks::DataLoss, data_loss)
+ IPC_STRUCT_MEMBER(blink::WebIDBDataLoss, data_loss)
+ IPC_STRUCT_MEMBER(std::string, data_loss_message)
IPC_STRUCT_MEMBER(IndexedDBDatabaseMetadata, idb_metadata)
IPC_STRUCT_END()
@@ -341,12 +341,12 @@ IPC_MESSAGE_CONTROL2(IndexedDBMsg_CallbacksSuccessUndefined,
IPC_MESSAGE_CONTROL3(IndexedDBMsg_CallbacksSuccessStringList,
int32 /* ipc_thread_id */,
int32 /* ipc_callbacks_id */,
- std::vector<string16> /* dom_string_list */)
+ std::vector<base::string16> /* dom_string_list */)
IPC_MESSAGE_CONTROL4(IndexedDBMsg_CallbacksError,
int32 /* ipc_thread_id */,
int32 /* ipc_callbacks_id */,
int /* code */,
- string16 /* message */)
+ base::string16 /* message */)
IPC_MESSAGE_CONTROL2(IndexedDBMsg_CallbacksBlocked,
int32 /* ipc_thread_id */,
int32 /* ipc_callbacks_id */)
@@ -371,7 +371,7 @@ IPC_MESSAGE_CONTROL5(IndexedDBMsg_DatabaseCallbacksAbort,
int32, /* ipc_database_callbacks_id */
int64, /* transaction_id */
int, /* code */
- string16) /* message */
+ base::string16) /* message */
IPC_MESSAGE_CONTROL3(IndexedDBMsg_DatabaseCallbacksComplete,
int32, /* ipc_thread_id */
int32, /* ipc_database_callbacks_id */
@@ -387,11 +387,12 @@ IPC_MESSAGE_CONTROL4(IndexedDBHostMsg_CursorAdvance,
unsigned long) /* count */
// WebIDBCursor::continue() message.
-IPC_MESSAGE_CONTROL4(IndexedDBHostMsg_CursorContinue,
+IPC_MESSAGE_CONTROL5(IndexedDBHostMsg_CursorContinue,
int32, /* ipc_cursor_id */
int32, /* ipc_thread_id */
int32, /* ipc_callbacks_id */
- content::IndexedDBKey) /* key */
+ content::IndexedDBKey, /* key */
+ content::IndexedDBKey) /* primary_key */
// WebIDBCursor::prefetchContinue() message.
IPC_MESSAGE_CONTROL4(IndexedDBHostMsg_CursorPrefetch,
diff --git a/chromium/content/common/indexed_db/indexed_db_param_traits.cc b/chromium/content/common/indexed_db/indexed_db_param_traits.cc
index 2098aed985c..0a566e26e10 100644
--- a/chromium/content/common/indexed_db/indexed_db_param_traits.cc
+++ b/chromium/content/common/indexed_db/indexed_db_param_traits.cc
@@ -15,17 +15,18 @@ using content::IndexedDBKey;
using content::IndexedDBKeyPath;
using content::IndexedDBKeyRange;
-using WebKit::WebIDBKeyPathTypeArray;
-using WebKit::WebIDBKeyPathTypeNull;
-using WebKit::WebIDBKeyPathTypeString;
-using WebKit::WebIDBKeyType;
-using WebKit::WebIDBKeyTypeArray;
-using WebKit::WebIDBKeyTypeDate;
-using WebKit::WebIDBKeyTypeInvalid;
-using WebKit::WebIDBKeyTypeMin;
-using WebKit::WebIDBKeyTypeNull;
-using WebKit::WebIDBKeyTypeNumber;
-using WebKit::WebIDBKeyTypeString;
+using blink::WebIDBKeyPathTypeArray;
+using blink::WebIDBKeyPathTypeNull;
+using blink::WebIDBKeyPathTypeString;
+using blink::WebIDBKeyType;
+using blink::WebIDBKeyTypeArray;
+using blink::WebIDBKeyTypeBinary;
+using blink::WebIDBKeyTypeDate;
+using blink::WebIDBKeyTypeInvalid;
+using blink::WebIDBKeyTypeMin;
+using blink::WebIDBKeyTypeNull;
+using blink::WebIDBKeyTypeNumber;
+using blink::WebIDBKeyTypeString;
namespace IPC {
@@ -35,6 +36,9 @@ void ParamTraits<IndexedDBKey>::Write(Message* m, const param_type& p) {
case WebIDBKeyTypeArray:
WriteParam(m, p.array());
return;
+ case WebIDBKeyTypeBinary:
+ WriteParam(m, p.binary());
+ return;
case WebIDBKeyTypeString:
WriteParam(m, p.string());
return;
@@ -48,6 +52,7 @@ void ParamTraits<IndexedDBKey>::Write(Message* m, const param_type& p) {
case WebIDBKeyTypeNull:
return;
case WebIDBKeyTypeMin:
+ default:
NOTREACHED();
return;
}
@@ -69,8 +74,15 @@ bool ParamTraits<IndexedDBKey>::Read(const Message* m,
*r = IndexedDBKey(array);
return true;
}
+ case WebIDBKeyTypeBinary: {
+ std::string binary;
+ if (!ReadParam(m, iter, &binary))
+ return false;
+ *r = IndexedDBKey(binary);
+ return true;
+ }
case WebIDBKeyTypeString: {
- string16 string;
+ base::string16 string;
if (!ReadParam(m, iter, &string))
return false;
*r = IndexedDBKey(string);
@@ -89,6 +101,7 @@ bool ParamTraits<IndexedDBKey>::Read(const Message* m,
*r = IndexedDBKey(web_type);
return true;
case WebIDBKeyTypeMin:
+ default:
NOTREACHED();
return false;
}
@@ -109,6 +122,8 @@ void ParamTraits<IndexedDBKey>::Log(const param_type& p, std::string* l) {
l->append(", ");
}
l->append("], ");
+ LogParam(p.binary(), l);
+ l->append(", ");
LogParam(p.string(), l);
l->append(", ");
LogParam(p.date(), l);
@@ -141,14 +156,14 @@ bool ParamTraits<IndexedDBKeyPath>::Read(const Message* m,
switch (type) {
case WebIDBKeyPathTypeArray: {
- std::vector<string16> array;
+ std::vector<base::string16> array;
if (!ReadParam(m, iter, &array))
return false;
*r = IndexedDBKeyPath(array);
return true;
}
case WebIDBKeyPathTypeString: {
- string16 string;
+ base::string16 string;
if (!ReadParam(m, iter, &string))
return false;
*r = IndexedDBKeyPath(string);
@@ -169,7 +184,7 @@ void ParamTraits<IndexedDBKeyPath>::Log(const param_type& p, std::string* l) {
LogParam(p.string(), l);
l->append(", ");
l->append("[");
- std::vector<string16>::const_iterator it = p.array().begin();
+ std::vector<base::string16>::const_iterator it = p.array().begin();
while (it != p.array().end()) {
LogParam(*it, l);
++it;
diff --git a/chromium/content/common/input/OWNERS b/chromium/content/common/input/OWNERS
index b0089f01cfe..4893edbdf02 100644
--- a/chromium/content/common/input/OWNERS
+++ b/chromium/content/common/input/OWNERS
@@ -1,2 +1,3 @@
aelias@chromium.org
+jdduke@chromium.org
nduca@chromium.org
diff --git a/chromium/content/common/input/event_packet.cc b/chromium/content/common/input/event_packet.cc
deleted file mode 100644
index 0f839cb5926..00000000000
--- a/chromium/content/common/input/event_packet.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/input/event_packet.h"
-
-#include "content/common/input/input_event.h"
-
-namespace content {
-
-EventPacket::EventPacket() : id_(0) {}
-
-EventPacket::~EventPacket() {}
-
-bool EventPacket::Add(scoped_ptr<InputEvent> event) {
- if (!event || !event->valid())
- return false;
- events_.push_back(event.release());
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/common/input/event_packet.h b/chromium/content/common/input/event_packet.h
deleted file mode 100644
index 78ff9a128b8..00000000000
--- a/chromium/content/common/input/event_packet.h
+++ /dev/null
@@ -1,49 +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_COMMON_INPUT_EVENT_PACKET_H_
-#define CONTENT_COMMON_INPUT_EVENT_PACKET_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class InputEvent;
-
-// An id'ed sequence of InputEvents.
-class CONTENT_EXPORT EventPacket {
- public:
- typedef ScopedVector<InputEvent> InputEvents;
-
- EventPacket();
- ~EventPacket();
-
- // Only a non-NULL and valid |event| will be accepted and added to the packet.
- // Returns true if |event| was added, and false otherwise.
- bool Add(scoped_ptr<InputEvent> event);
-
- void set_id(int64 id) { id_ = id; }
- int64 id() const { return id_; }
-
- // Accessor functions for convenience.
- bool empty() const { return events_.empty(); }
- size_t size() const { return events_.size(); }
- InputEvents::const_iterator begin() const { return events_.end(); }
- InputEvents::const_iterator end() const { return events_.end(); }
- const InputEvents& events() const { return events_; }
-
- protected:
- int64 id_;
- InputEvents events_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(EventPacket);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_INPUT_EVENT_PACKET_H_
diff --git a/chromium/content/common/input/input_event.cc b/chromium/content/common/input/input_event.cc
index fd0796816df..93e96911acc 100644
--- a/chromium/content/common/input/input_event.cc
+++ b/chromium/content/common/input/input_event.cc
@@ -4,25 +4,19 @@
#include "content/common/input/input_event.h"
-#include "base/logging.h"
+#include "content/common/input/web_input_event_traits.h"
namespace content {
-InputEvent::InputEvent() : id_(0) {}
+InputEvent::InputEvent() : is_keyboard_shortcut(false) {}
-InputEvent::~InputEvent() {}
-
-scoped_ptr<InputEvent> InputEvent::Create(int64 id,
- scoped_ptr<Payload> payload) {
- scoped_ptr<InputEvent> event(new InputEvent());
- event->Initialize(id, payload.Pass());
- return event.Pass();
-}
+InputEvent::InputEvent(const blink::WebInputEvent& web_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_keyboard_shortcut)
+ : web_event(WebInputEventTraits::Clone(web_event)),
+ latency_info(latency_info),
+ is_keyboard_shortcut(is_keyboard_shortcut) {}
-bool InputEvent::Initialize(int64 id, scoped_ptr<Payload> payload) {
- id_ = id;
- payload_ = payload.Pass();
- return valid();
-}
+InputEvent::~InputEvent() {}
} // namespace content
diff --git a/chromium/content/common/input/input_event.h b/chromium/content/common/input/input_event.h
index a6f9a4b7bfc..4c13e061e16 100644
--- a/chromium/content/common/input/input_event.h
+++ b/chromium/content/common/input/input_event.h
@@ -8,50 +8,29 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
+#include "content/common/input/scoped_web_input_event.h"
+#include "ui/events/latency_info.h"
+
+namespace blink {
+class WebInputEvent;
+}
namespace content {
-// An id'ed event that carries a specific input payload.
+// An content-specific wrapper for WebInputEvents and associated metadata.
class CONTENT_EXPORT InputEvent {
public:
- // Input data carried by the InputEvent.
- class CONTENT_EXPORT Payload {
- public:
- enum Type {
- IPC_MESSAGE,
- WEB_INPUT_EVENT,
- PAYLOAD_TYPE_MAX = WEB_INPUT_EVENT
- };
- virtual ~Payload() {}
- virtual Type GetType() const = 0;
- };
-
- // A valid InputEvent has a non-zero |id| and a non-NULL |payload|.
- static scoped_ptr<InputEvent> Create(int64 id, scoped_ptr<Payload> payload);
-
- template <typename PayloadType>
- static scoped_ptr<InputEvent> Create(int64 id,
- scoped_ptr<PayloadType> payload) {
- return Create(id, payload.template PassAs<Payload>());
- }
-
InputEvent();
- virtual ~InputEvent();
-
- // Returns true if the initialized InputEvent is |valid()|, false otherwise.
- bool Initialize(int64 id, scoped_ptr<Payload> payload);
+ InputEvent(const blink::WebInputEvent& web_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_keyboard_shortcut);
+ ~InputEvent();
- int64 id() const { return id_; }
- const Payload* payload() const { return payload_.get(); }
- bool valid() const { return id() && payload(); }
-
- protected:
- InputEvent(int64 id, scoped_ptr<Payload> payload);
+ ScopedWebInputEvent web_event;
+ ui::LatencyInfo latency_info;
+ bool is_keyboard_shortcut;
private:
- int64 id_;
- scoped_ptr<Payload> payload_;
-
DISALLOW_COPY_AND_ASSIGN(InputEvent);
};
diff --git a/chromium/content/common/input/input_event_disposition.cc b/chromium/content/common/input/input_event_disposition.cc
deleted file mode 100644
index e3a1e77f75b..00000000000
--- a/chromium/content/common/input/input_event_disposition.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/input/input_event_disposition.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-InputEventDisposition ToDisposition(InputEventAckState ack_state,
- bool main_thread,
- bool prevent_default) {
- if (main_thread) {
- switch (ack_state) {
- case INPUT_EVENT_ACK_STATE_CONSUMED:
- return INPUT_EVENT_MAIN_THREAD_CONSUMED;
- case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
- return prevent_default ? INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED
- : INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED;
- case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
- return INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS;
- case INPUT_EVENT_ACK_STATE_UNKNOWN:
- return INPUT_EVENT_UNHANDLED;
- }
- } else {
- switch (ack_state) {
- case INPUT_EVENT_ACK_STATE_CONSUMED:
- return INPUT_EVENT_IMPL_THREAD_CONSUMED;
- case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
- return INPUT_EVENT_IMPL_THREAD_BOUNCE_TO_MAIN;
- case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
- return INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS;
- case INPUT_EVENT_ACK_STATE_UNKNOWN:
- return INPUT_EVENT_UNHANDLED;
- }
- }
- NOTREACHED();
- return INPUT_EVENT_UNHANDLED;
-}
-
-InputEventAckState ToAckState(InputEventDisposition disposition) {
- switch (disposition) {
- case INPUT_EVENT_UNHANDLED:
- return INPUT_EVENT_ACK_STATE_UNKNOWN;
- case INPUT_EVENT_IMPL_THREAD_CONSUMED:
- return INPUT_EVENT_ACK_STATE_CONSUMED;
- case INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS:
- return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
- case INPUT_EVENT_IMPL_THREAD_BOUNCE_TO_MAIN:
- return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
- case INPUT_EVENT_COULD_NOT_DELIVER:
- return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
- case INPUT_EVENT_MAIN_THREAD_CONSUMED:
- return INPUT_EVENT_ACK_STATE_CONSUMED;
- case INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED:
- return INPUT_EVENT_ACK_STATE_CONSUMED;
- case INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED:
- return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
- case INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS:
- return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
- }
- NOTREACHED();
- return INPUT_EVENT_ACK_STATE_UNKNOWN;
-}
-
-} // namespace content
diff --git a/chromium/content/common/input/input_event_disposition.h b/chromium/content/common/input/input_event_disposition.h
deleted file mode 100644
index 8e62935ec7d..00000000000
--- a/chromium/content/common/input/input_event_disposition.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_INPUT_INPUT_EVENT_DISPOSITION_H_
-#define CONTENT_COMMON_INPUT_INPUT_EVENT_DISPOSITION_H_
-
-#include <vector>
-
-#include "content/common/content_export.h"
-#include "content/port/common/input_event_ack_state.h"
-
-namespace content {
-
-// Disposition of input events as they are handled and passed between the
-// browser and renderer.
-enum InputEventDisposition {
- INPUT_EVENT_UNHANDLED,
- INPUT_EVENT_COULD_NOT_DELIVER,
-
- INPUT_EVENT_IMPL_THREAD_CONSUMED,
- INPUT_EVENT_IMPL_THREAD_BOUNCE_TO_MAIN,
- INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS,
-
- INPUT_EVENT_MAIN_THREAD_CONSUMED,
- INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED,
- INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED,
- INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS,
-
- INPUT_EVENT_DISPOSITION_MAX = INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS
-};
-typedef std::vector<InputEventDisposition> InputEventDispositions;
-
-InputEventDisposition CONTENT_EXPORT ToDisposition(InputEventAckState ack,
- bool main_thread,
- bool prevent_default);
-InputEventAckState CONTENT_EXPORT ToAckState(InputEventDisposition disposition);
-
-} // namespace content
-
-#endif // CONTENT_COMMON_INPUT_INPUT_EVENT_DISPOSITION_H_
diff --git a/chromium/content/common/input/input_param_traits.cc b/chromium/content/common/input/input_param_traits.cc
index e3aaf670ffd..2a5297c8a1c 100644
--- a/chromium/content/common/input/input_param_traits.cc
+++ b/chromium/content/common/input/input_param_traits.cc
@@ -5,170 +5,124 @@
#include "content/common/input/input_param_traits.h"
#include "content/common/content_param_traits.h"
-#include "content/common/input/input_event_disposition.h"
-#include "content/common/input/ipc_input_event_payload.h"
-#include "content/common/input/web_input_event_payload.h"
+#include "content/common/input/synthetic_pinch_gesture_params.h"
+#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
+#include "content/common/input/web_input_event_traits.h"
#include "content/common/input_messages.h"
namespace IPC {
namespace {
-template <typename PayloadType>
-scoped_ptr<content::InputEvent::Payload> ReadPayload(const Message* m,
- PickleIterator* iter) {
- scoped_ptr<PayloadType> event = PayloadType::Create();
- if (!ReadParam(m, iter, event.get()))
- return scoped_ptr<content::InputEvent::Payload>();
- return event.template PassAs<content::InputEvent::Payload>();
+template<typename GestureType>
+scoped_ptr<content::SyntheticGestureParams> ReadGestureParams(
+ const Message* m,
+ PickleIterator* iter)
+{
+ scoped_ptr<GestureType> gesture_params(new GestureType);
+ if (!ReadParam(m, iter, gesture_params.get()))
+ return scoped_ptr<content::SyntheticGestureParams>();
+
+ return gesture_params.template PassAs<content::SyntheticGestureParams>();
}
} // namespace
-void ParamTraits<content::EventPacket>::Write(Message* m, const param_type& p) {
- WriteParam(m, p.id());
- WriteParam(m, p.events());
+void ParamTraits<content::ScopedWebInputEvent>::Write(Message* m,
+ const param_type& p) {
+ bool valid_web_event = !!p;
+ WriteParam(m, valid_web_event);
+ if (valid_web_event)
+ WriteParam(m, static_cast<WebInputEventPointer>(p.get()));
}
-bool ParamTraits<content::EventPacket>::Read(const Message* m,
- PickleIterator* iter,
- param_type* p) {
- int64 id;
- content::EventPacket::InputEvents events;
- if (!ReadParam(m, iter, &id) ||
- !ReadParam(m, iter, &events))
+bool ParamTraits<content::ScopedWebInputEvent>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* p) {
+ bool valid_web_event = false;
+ WebInputEventPointer web_event_pointer = NULL;
+ if (!ReadParam(m, iter, &valid_web_event) ||
+ !valid_web_event ||
+ !ReadParam(m, iter, &web_event_pointer) ||
+ !web_event_pointer)
return false;
- p->set_id(id);
- bool events_added_successfully = true;
- for (size_t i = 0; i < events.size(); ++i) {
- // Take ownership of all events.
- scoped_ptr<content::InputEvent> event(events[i]);
- if (!events_added_successfully)
- continue;
- if (!p->Add(event.Pass()))
- events_added_successfully = false;
- }
- events.weak_clear();
- return events_added_successfully;
+ (*p) = content::WebInputEventTraits::Clone(*web_event_pointer);
+ return true;
}
-void ParamTraits<content::EventPacket>::Log(const param_type& p,
- std::string* l) {
- l->append("EventPacket((");
- LogParam(p.id(), l);
- l->append("), Events(");
- LogParam(p.events(), l);
- l->append("))");
+void ParamTraits<content::ScopedWebInputEvent>::Log(const param_type& p,
+ std::string* l) {
+ LogParam(static_cast<WebInputEventPointer>(p.get()), l);
}
-void ParamTraits<content::InputEvent>::Write(Message* m, const param_type& p) {
- WriteParam(m, p.id());
- WriteParam(m, !!p.payload());
- if (!p.valid())
- return;
-
- content::InputEvent::Payload::Type payload_type = p.payload()->GetType();
- WriteParam(m, payload_type);
- switch (payload_type) {
- case content::InputEvent::Payload::IPC_MESSAGE:
- WriteParam(m, *content::IPCInputEventPayload::Cast(p.payload()));
+void ParamTraits<content::SyntheticGesturePacket>::Write(Message* m,
+ const param_type& p) {
+ DCHECK(p.gesture_params());
+ WriteParam(m, p.gesture_params()->GetGestureType());
+ switch (p.gesture_params()->GetGestureType()) {
+ case content::SyntheticGestureParams::SMOOTH_SCROLL_GESTURE:
+ WriteParam(m, *content::SyntheticSmoothScrollGestureParams::Cast(
+ p.gesture_params()));
break;
- case content::InputEvent::Payload::WEB_INPUT_EVENT:
- WriteParam(m, *content::WebInputEventPayload::Cast(p.payload()));
+ case content::SyntheticGestureParams::PINCH_GESTURE:
+ WriteParam(m, *content::SyntheticPinchGestureParams::Cast(
+ p.gesture_params()));
break;
- default:
+ case content::SyntheticGestureParams::TAP_GESTURE:
+ WriteParam(m, *content::SyntheticTapGestureParams::Cast(
+ p.gesture_params()));
break;
}
}
-bool ParamTraits<content::InputEvent>::Read(const Message* m,
- PickleIterator* iter,
- param_type* p) {
- int64 id;
- bool has_payload = false;
- content::InputEvent::Payload::Type payload_type;
- if (!ReadParam(m, iter, &id) ||
- !ReadParam(m, iter, &has_payload) ||
- !id ||
- !has_payload ||
- !ReadParam(m, iter, &payload_type))
+bool ParamTraits<content::SyntheticGesturePacket>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* p) {
+ content::SyntheticGestureParams::GestureType gesture_type;
+ if (!ReadParam(m, iter, &gesture_type))
return false;
-
- scoped_ptr<content::InputEvent::Payload> payload;
- switch (payload_type) {
- case content::InputEvent::Payload::IPC_MESSAGE:
- payload = ReadPayload<content::IPCInputEventPayload>(m, iter);
+ scoped_ptr<content::SyntheticGestureParams> gesture_params;
+ switch (gesture_type) {
+ case content::SyntheticGestureParams::SMOOTH_SCROLL_GESTURE:
+ gesture_params =
+ ReadGestureParams<content::SyntheticSmoothScrollGestureParams>(m,
+ iter);
break;
- case content::InputEvent::Payload::WEB_INPUT_EVENT:
- payload = ReadPayload<content::WebInputEventPayload>(m, iter);
+ case content::SyntheticGestureParams::PINCH_GESTURE:
+ gesture_params =
+ ReadGestureParams<content::SyntheticPinchGestureParams>(m, iter);
+ break;
+ case content::SyntheticGestureParams::TAP_GESTURE:
+ gesture_params =
+ ReadGestureParams<content::SyntheticTapGestureParams>(m, iter);
break;
default:
- NOTREACHED() << "Invalid InputEvent::Payload type.";
return false;
}
- return p->Initialize(id, payload.Pass());
-}
-void ParamTraits<content::InputEvent>::Log(const param_type& p,
- std::string* l) {
- l->append("InputEvent((");
- LogParam(p.id(), l);
- l->append("), Payload (");
- const content::InputEvent::Payload* payload = p.payload();
- if (payload) {
- switch (payload->GetType()) {
- case content::InputEvent::Payload::IPC_MESSAGE:
- LogParam(*content::IPCInputEventPayload::Cast(payload), l);
- break;
- case content::InputEvent::Payload::WEB_INPUT_EVENT:
- LogParam(*content::WebInputEventPayload::Cast(payload), l);
- break;
- default:
- NOTREACHED() << "Invalid InputEvent::Payload type.";
- l->append("INVALID");
- break;
- }
- } else {
- l->append("NULL");
- }
- l->append("))");
+ p->set_gesture_params(gesture_params.Pass());
+ return p->gesture_params() != NULL;
}
-void ParamTraits<content::WebInputEventPayload>::Write(Message* m,
- const param_type& p) {
- bool valid_web_event = !!p.web_event();
- WriteParam(m, valid_web_event);
- if (valid_web_event)
- WriteParam(m, p.web_event());
- WriteParam(m, p.latency_info());
- WriteParam(m, p.is_keyboard_shortcut());
-}
-
-bool ParamTraits<content::WebInputEventPayload>::Read(const Message* m,
- PickleIterator* iter,
- param_type* p) {
- bool valid_web_event;
- WebInputEventPointer web_input_event_pointer;
- ui::LatencyInfo latency_info;
- bool is_keyboard_shortcut;
- if (!ReadParam(m, iter, &valid_web_event) ||
- !valid_web_event ||
- !ReadParam(m, iter, &web_input_event_pointer) ||
- !ReadParam(m, iter, &latency_info) ||
- !ReadParam(m, iter, &is_keyboard_shortcut))
- return false;
-
- p->Initialize(*web_input_event_pointer, latency_info, is_keyboard_shortcut);
- return true;
-}
-
-void ParamTraits<content::WebInputEventPayload>::Log(const param_type& p,
- std::string* l) {
- l->append("WebInputEventPayload(");
- LogParam(p.web_event(), l);
- l->append(", ");
- LogParam(p.latency_info(), l);
- l->append(", ");
- LogParam(p.is_keyboard_shortcut(), l);
- l->append(")");
+void ParamTraits<content::SyntheticGesturePacket>::Log(const param_type& p,
+ std::string* l) {
+ DCHECK(p.gesture_params());
+ switch (p.gesture_params()->GetGestureType()) {
+ case content::SyntheticGestureParams::SMOOTH_SCROLL_GESTURE:
+ LogParam(
+ *content::SyntheticSmoothScrollGestureParams::Cast(
+ p.gesture_params()),
+ l);
+ break;
+ case content::SyntheticGestureParams::PINCH_GESTURE:
+ LogParam(
+ *content::SyntheticPinchGestureParams::Cast(p.gesture_params()),
+ l);
+ break;
+ case content::SyntheticGestureParams::TAP_GESTURE:
+ LogParam(
+ *content::SyntheticTapGestureParams::Cast(p.gesture_params()),
+ l);
+ break;
+ }
}
} // namespace IPC
diff --git a/chromium/content/common/input/input_param_traits.h b/chromium/content/common/input/input_param_traits.h
index a493c4b8691..11724337a82 100644
--- a/chromium/content/common/input/input_param_traits.h
+++ b/chromium/content/common/input/input_param_traits.h
@@ -8,69 +8,24 @@
#ifndef CONTENT_COMMON_INPUT_INPUT_PARAM_TRAITS_H_
#define CONTENT_COMMON_INPUT_INPUT_PARAM_TRAITS_H_
-#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
#include "content/common/content_param_traits_macros.h"
-#include "content/common/input/event_packet.h"
-#include "content/common/input/input_event.h"
-#include "content/common/input/web_input_event_payload.h"
+#include "content/common/input/scoped_web_input_event.h"
+#include "content/common/input/synthetic_gesture_packet.h"
namespace IPC {
-// TODO(jdduke): There should be a common copy of this utility somewhere...
-// Move or remove appropriately.
-template <class P>
-struct ParamTraits<scoped_ptr<P> > {
- typedef scoped_ptr<P> param_type;
- static void Write(Message* m, const param_type& p) {
- bool valid = !!p;
- WriteParam(m, valid);
- if (valid)
- WriteParam(m, *p);
- }
- static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
- bool valid = false;
- if (!ReadParam(m, iter, &valid))
- return false;
-
- if (!valid) {
- r->reset();
- return true;
- }
-
- param_type temp(new P());
- if (!ReadParam(m, iter, temp.get()))
- return false;
-
- r->swap(temp);
- return true;
- }
- static void Log(const param_type& p, std::string* l) {
- if (p)
- LogParam(*p, l);
- else
- l->append("NULL");
- }
-};
-
-template <>
-struct CONTENT_EXPORT ParamTraits<content::EventPacket> {
- typedef content::EventPacket param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
template <>
-struct CONTENT_EXPORT ParamTraits<content::InputEvent> {
- typedef content::InputEvent param_type;
+struct CONTENT_EXPORT ParamTraits<content::ScopedWebInputEvent> {
+ typedef content::ScopedWebInputEvent param_type;
static void Write(Message* m, const param_type& p);
static bool Read(const Message* m, PickleIterator* iter, param_type* r);
static void Log(const param_type& p, std::string* l);
};
-template <>
-struct CONTENT_EXPORT ParamTraits<content::WebInputEventPayload> {
- typedef content::WebInputEventPayload param_type;
+template<>
+struct CONTENT_EXPORT ParamTraits<content::SyntheticGesturePacket> {
+ typedef content::SyntheticGesturePacket param_type;
static void Write(Message* m, const param_type& p);
static bool Read(const Message* m, PickleIterator* iter, param_type* r);
static void Log(const param_type& p, std::string* l);
diff --git a/chromium/content/common/input/input_param_traits_unittest.cc b/chromium/content/common/input/input_param_traits_unittest.cc
index 6fb237c2ca6..c631d9a21cd 100644
--- a/chromium/content/common/input/input_param_traits_unittest.cc
+++ b/chromium/content/common/input/input_param_traits_unittest.cc
@@ -4,10 +4,10 @@
#include "content/common/input/input_param_traits.h"
-#include "content/common/input/event_packet.h"
#include "content/common/input/input_event.h"
-#include "content/common/input/ipc_input_event_payload.h"
-#include "content/common/input/web_input_event_payload.h"
+#include "content/common/input/synthetic_gesture_params.h"
+#include "content/common/input/synthetic_pinch_gesture_params.h"
+#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input_messages.h"
#include "ipc/ipc_message.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -16,193 +16,218 @@
namespace content {
namespace {
+typedef ScopedVector<InputEvent> InputEvents;
+
class InputParamTraitsTest : public testing::Test {
protected:
- void Compare(const WebInputEventPayload* a, const WebInputEventPayload* b) {
- EXPECT_EQ(!!a->web_event(), !!b->web_event());
- if (a->web_event() && b->web_event()) {
- const size_t a_size = a->web_event()->size;
- ASSERT_EQ(a_size, b->web_event()->size);
- EXPECT_EQ(0, memcmp(a->web_event(), b->web_event(), a_size));
+ static void Compare(const InputEvent* a, const InputEvent* b) {
+ EXPECT_EQ(!!a->web_event, !!b->web_event);
+ if (a->web_event && b->web_event) {
+ const size_t a_size = a->web_event->size;
+ ASSERT_EQ(a_size, b->web_event->size);
+ EXPECT_EQ(0, memcmp(a->web_event.get(), b->web_event.get(), a_size));
}
- EXPECT_EQ(a->latency_info().latency_components.size(),
- b->latency_info().latency_components.size());
- EXPECT_EQ(a->is_keyboard_shortcut(), b->is_keyboard_shortcut());
+ EXPECT_EQ(a->latency_info.latency_components.size(),
+ b->latency_info.latency_components.size());
+ EXPECT_EQ(a->is_keyboard_shortcut, b->is_keyboard_shortcut);
}
- void Compare(const IPCInputEventPayload* a, const IPCInputEventPayload* b) {
- EXPECT_EQ(!!a->message, !!b->message);
- if (a->message && b->message) {
- EXPECT_EQ(a->message->type(), b->message->type());
- EXPECT_EQ(a->message->routing_id(), b->message->routing_id());
- }
+ static void Compare(const InputEvents* a, const InputEvents* b) {
+ for (size_t i = 0; i < a->size(); ++i)
+ Compare((*a)[i], (*b)[i]);
+ }
+
+ static void Compare(const SyntheticSmoothScrollGestureParams* a,
+ const SyntheticSmoothScrollGestureParams* b) {
+ EXPECT_EQ(a->gesture_source_type, b->gesture_source_type);
+ EXPECT_EQ(a->distance, b->distance);
+ EXPECT_EQ(a->anchor, b->anchor);
+ EXPECT_EQ(a->prevent_fling, b->prevent_fling);
+ EXPECT_EQ(a->speed_in_pixels_s, b->speed_in_pixels_s);
}
- void Compare(const InputEvent::Payload* a, const InputEvent::Payload* b) {
+ static void Compare(const SyntheticPinchGestureParams* a,
+ const SyntheticPinchGestureParams* b) {
+ EXPECT_EQ(a->gesture_source_type, b->gesture_source_type);
+ EXPECT_EQ(a->zoom_in, b->zoom_in);
+ EXPECT_EQ(a->total_num_pixels_covered, b->total_num_pixels_covered);
+ EXPECT_EQ(a->anchor, b->anchor);
+ EXPECT_EQ(a->relative_pointer_speed_in_pixels_s,
+ b->relative_pointer_speed_in_pixels_s);
+ }
+
+ static void Compare(const SyntheticTapGestureParams* a,
+ const SyntheticTapGestureParams* b) {
+ EXPECT_EQ(a->gesture_source_type, b->gesture_source_type);
+ EXPECT_EQ(a->position, b->position);
+ EXPECT_EQ(a->duration_ms, b->duration_ms);
+ }
+
+ static void Compare(const SyntheticGesturePacket* a,
+ const SyntheticGesturePacket* b) {
ASSERT_EQ(!!a, !!b);
- if (!a)
- return;
- switch (a->GetType()) {
- case InputEvent::Payload::IPC_MESSAGE:
- Compare(IPCInputEventPayload::Cast(a), IPCInputEventPayload::Cast(b));
+ if (!a) return;
+ ASSERT_EQ(!!a->gesture_params(), !!b->gesture_params());
+ if (!a->gesture_params()) return;
+ ASSERT_EQ(a->gesture_params()->GetGestureType(),
+ b->gesture_params()->GetGestureType());
+ switch (a->gesture_params()->GetGestureType()) {
+ case SyntheticGestureParams::SMOOTH_SCROLL_GESTURE:
+ Compare(SyntheticSmoothScrollGestureParams::Cast(a->gesture_params()),
+ SyntheticSmoothScrollGestureParams::Cast(b->gesture_params()));
+ break;
+ case SyntheticGestureParams::PINCH_GESTURE:
+ Compare(SyntheticPinchGestureParams::Cast(a->gesture_params()),
+ SyntheticPinchGestureParams::Cast(b->gesture_params()));
break;
- case InputEvent::Payload::WEB_INPUT_EVENT:
- Compare(WebInputEventPayload::Cast(a), WebInputEventPayload::Cast(b));
- default:
+ case SyntheticGestureParams::TAP_GESTURE:
+ Compare(SyntheticTapGestureParams::Cast(a->gesture_params()),
+ SyntheticTapGestureParams::Cast(b->gesture_params()));
break;
}
}
- void Compare(const InputEvent* a, const InputEvent* b) {
- EXPECT_EQ(a->id(), b->id());
- EXPECT_EQ(a->valid(), b->valid());
- Compare(a->payload(), b->payload());
- }
+ static void Verify(const InputEvents& events_in) {
+ IPC::Message msg;
+ IPC::ParamTraits<InputEvents>::Write(&msg, events_in);
- void Compare(const EventPacket* a, const EventPacket* b) {
- EXPECT_EQ(a->id(), b->id());
- ASSERT_EQ(a->size(), b->size());
- for (size_t i = 0; i < a->size(); ++i)
- Compare(a->events()[i], b->events()[i]);
+ InputEvents events_out;
+ PickleIterator iter(msg);
+ EXPECT_TRUE(IPC::ParamTraits<InputEvents>::Read(&msg, &iter, &events_out));
+
+ Compare(&events_in, &events_out);
+
+ // Perform a sanity check that logging doesn't explode.
+ std::string events_in_string;
+ IPC::ParamTraits<InputEvents>::Log(events_in, &events_in_string);
+ std::string events_out_string;
+ IPC::ParamTraits<InputEvents>::Log(events_out, &events_out_string);
+ ASSERT_FALSE(events_in_string.empty());
+ EXPECT_EQ(events_in_string, events_out_string);
}
- void Verify(const EventPacket& packet_in) {
+ static void Verify(const SyntheticGesturePacket& packet_in) {
IPC::Message msg;
- IPC::ParamTraits<EventPacket>::Write(&msg, packet_in);
+ IPC::ParamTraits<SyntheticGesturePacket>::Write(&msg, packet_in);
- EventPacket packet_out;
+ SyntheticGesturePacket packet_out;
PickleIterator iter(msg);
- EXPECT_TRUE(IPC::ParamTraits<EventPacket>::Read(&msg, &iter, &packet_out));
+ EXPECT_TRUE(IPC::ParamTraits<SyntheticGesturePacket>::Read(&msg, &iter,
+ &packet_out));
Compare(&packet_in, &packet_out);
// Perform a sanity check that logging doesn't explode.
std::string packet_in_string;
- IPC::ParamTraits<EventPacket>::Log(packet_in, &packet_in_string);
+ IPC::ParamTraits<SyntheticGesturePacket>::Log(packet_in, &packet_in_string);
std::string packet_out_string;
- IPC::ParamTraits<EventPacket>::Log(packet_out, &packet_out_string);
+ IPC::ParamTraits<SyntheticGesturePacket>::Log(packet_out,
+ &packet_out_string);
ASSERT_FALSE(packet_in_string.empty());
EXPECT_EQ(packet_in_string, packet_out_string);
}
};
-TEST_F(InputParamTraitsTest, EventPacketEmpty) {
- EventPacket packet_in;
- IPC::Message msg;
- IPC::ParamTraits<EventPacket>::Write(&msg, packet_in);
-
- EventPacket packet_out;
- PickleIterator iter(msg);
- EXPECT_TRUE(IPC::ParamTraits<EventPacket>::Read(&msg, &iter, &packet_out));
-
- Compare(&packet_in, &packet_out);
-}
-
-TEST_F(InputParamTraitsTest, EventPacketUninitializedEvents) {
- EventPacket packet_in;
- packet_in.set_id(1);
- packet_in.Add(InputEvent::Create(1, WebInputEventPayload::Create()));
- packet_in.Add(InputEvent::Create(2, IPCInputEventPayload::Create()));
+TEST_F(InputParamTraitsTest, UninitializedEvents) {
+ InputEvent event;
IPC::Message msg;
- IPC::ParamTraits<EventPacket>::Write(&msg, packet_in);
+ IPC::WriteParam(&msg, event);
- EventPacket packet_out;
+ InputEvent event_out;
PickleIterator iter(msg);
- EXPECT_FALSE(IPC::ParamTraits<EventPacket>::Read(&msg, &iter, &packet_out));
-}
-
-TEST_F(InputParamTraitsTest, EventPacketIPCEvents) {
- EventPacket packet_in;
- packet_in.set_id(1);
-
- packet_in.Add(
- InputEvent::Create(1,
- IPCInputEventPayload::Create(
- scoped_ptr<IPC::Message>(new InputMsg_Undo(1)))));
- packet_in.Add(InputEvent::Create(
- 1,
- IPCInputEventPayload::Create(
- scoped_ptr<IPC::Message>(new InputMsg_SetFocus(2, true)))));
- Verify(packet_in);
+ EXPECT_FALSE(IPC::ReadParam(&msg, &iter, &event_out));
}
-TEST_F(InputParamTraitsTest, EventPacketWebInputEvents) {
- EventPacket packet_in;
- packet_in.set_id(1);
+TEST_F(InputParamTraitsTest, InitializedEvents) {
+ InputEvents events;
ui::LatencyInfo latency;
- int64 next_event_id = 1;
- WebKit::WebKeyboardEvent key_event;
- key_event.type = WebKit::WebInputEvent::RawKeyDown;
+ blink::WebKeyboardEvent key_event;
+ key_event.type = blink::WebInputEvent::RawKeyDown;
key_event.nativeKeyCode = 5;
- packet_in.Add(InputEvent::Create(
- ++next_event_id, WebInputEventPayload::Create(key_event, latency, true)));
+ events.push_back(new InputEvent(key_event, latency, false));
- WebKit::WebMouseWheelEvent wheel_event;
- wheel_event.type = WebKit::WebInputEvent::MouseWheel;
+ blink::WebMouseWheelEvent wheel_event;
+ wheel_event.type = blink::WebInputEvent::MouseWheel;
wheel_event.deltaX = 10;
- latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_RWH_COMPONENT, 1, 1);
- packet_in.Add(InputEvent::Create(
- ++next_event_id,
- WebInputEventPayload::Create(wheel_event, latency, false)));
+ latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 1, 1);
+ events.push_back(new InputEvent(wheel_event, latency, false));
- WebKit::WebMouseEvent mouse_event;
- mouse_event.type = WebKit::WebInputEvent::MouseDown;
+ blink::WebMouseEvent mouse_event;
+ mouse_event.type = blink::WebInputEvent::MouseDown;
mouse_event.x = 10;
latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 2, 2);
- packet_in.Add(InputEvent::Create(
- ++next_event_id,
- WebInputEventPayload::Create(mouse_event, latency, false)));
+ events.push_back(new InputEvent(mouse_event, latency, false));
- WebKit::WebGestureEvent gesture_event;
- gesture_event.type = WebKit::WebInputEvent::GestureScrollBegin;
+ blink::WebGestureEvent gesture_event;
+ gesture_event.type = blink::WebInputEvent::GestureScrollBegin;
gesture_event.x = -1;
- packet_in.Add(InputEvent::Create(
- ++next_event_id,
- WebInputEventPayload::Create(gesture_event, latency, false)));
+ events.push_back(new InputEvent(gesture_event, latency, false));
- WebKit::WebTouchEvent touch_event;
- touch_event.type = WebKit::WebInputEvent::TouchStart;
+ blink::WebTouchEvent touch_event;
+ touch_event.type = blink::WebInputEvent::TouchStart;
touch_event.touchesLength = 1;
touch_event.touches[0].radiusX = 1;
- packet_in.Add(InputEvent::Create(
- ++next_event_id,
- WebInputEventPayload::Create(touch_event, latency, false)));
+ events.push_back(new InputEvent(touch_event, latency, false));
- Verify(packet_in);
+ Verify(events);
}
-TEST_F(InputParamTraitsTest, EventPacketMixedEvents) {
- EventPacket packet_in;
- packet_in.set_id(1);
- int64 next_event_id = 1;
+TEST_F(InputParamTraitsTest, InvalidSyntheticGestureParams) {
+ IPC::Message msg;
+ // Write invalid value for SyntheticGestureParams::GestureType.
+ WriteParam(&msg, -3);
- // Add a mix of IPC and WebInputEvents.
- packet_in.Add(
- InputEvent::Create(++next_event_id,
- IPCInputEventPayload::Create(
- scoped_ptr<IPC::Message>(new InputMsg_Undo(1)))));
+ SyntheticGesturePacket packet_out;
+ PickleIterator iter(msg);
+ ASSERT_FALSE(
+ IPC::ParamTraits<SyntheticGesturePacket>::Read(&msg, &iter, &packet_out));
+}
- ui::LatencyInfo latency;
- WebKit::WebKeyboardEvent key_event;
- key_event.type = WebKit::WebInputEvent::RawKeyDown;
- key_event.nativeKeyCode = 5;
- packet_in.Add(InputEvent::Create(
- ++next_event_id, WebInputEventPayload::Create(key_event, latency, true)));
+TEST_F(InputParamTraitsTest, SyntheticSmoothScrollGestureParams) {
+ scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
+ new SyntheticSmoothScrollGestureParams);
+ gesture_params->gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ gesture_params->distance = gfx::Vector2d(123, -789);
+ gesture_params->anchor.SetPoint(234, 345);
+ gesture_params->prevent_fling = false;
+ gesture_params->speed_in_pixels_s = 456;
+ ASSERT_EQ(SyntheticGestureParams::SMOOTH_SCROLL_GESTURE,
+ gesture_params->GetGestureType());
+ SyntheticGesturePacket packet_in;
+ packet_in.set_gesture_params(gesture_params.PassAs<SyntheticGestureParams>());
- packet_in.Add(InputEvent::Create(
- ++next_event_id,
- IPCInputEventPayload::Create(
- scoped_ptr<IPC::Message>(new InputMsg_SetFocus(2, true)))));
+ Verify(packet_in);
+}
- WebKit::WebMouseWheelEvent wheel_event;
- wheel_event.type = WebKit::WebInputEvent::MouseWheel;
- wheel_event.deltaX = 10;
- packet_in.Add(InputEvent::Create(
- ++next_event_id,
- WebInputEventPayload::Create(wheel_event, latency, false)));
+TEST_F(InputParamTraitsTest, SyntheticPinchGestureParams) {
+ scoped_ptr<SyntheticPinchGestureParams> gesture_params(
+ new SyntheticPinchGestureParams);
+ gesture_params->gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ gesture_params->zoom_in = true;
+ gesture_params->total_num_pixels_covered = 123;
+ gesture_params->anchor.SetPoint(234, 345);
+ gesture_params->relative_pointer_speed_in_pixels_s = 456;
+ ASSERT_EQ(SyntheticGestureParams::PINCH_GESTURE,
+ gesture_params->GetGestureType());
+ SyntheticGesturePacket packet_in;
+ packet_in.set_gesture_params(gesture_params.PassAs<SyntheticGestureParams>());
+
+ Verify(packet_in);
+}
+
+TEST_F(InputParamTraitsTest, SyntheticTapGestureParams) {
+ scoped_ptr<SyntheticTapGestureParams> gesture_params(
+ new SyntheticTapGestureParams);
+ gesture_params->gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ gesture_params->position.SetPoint(798, 233);
+ gesture_params->duration_ms = 13;
+ ASSERT_EQ(SyntheticGestureParams::TAP_GESTURE,
+ gesture_params->GetGestureType());
+ SyntheticGesturePacket packet_in;
+ packet_in.set_gesture_params(gesture_params.PassAs<SyntheticGestureParams>());
Verify(packet_in);
}
diff --git a/chromium/content/common/input/ipc_input_event_payload.cc b/chromium/content/common/input/ipc_input_event_payload.cc
deleted file mode 100644
index 98e8d02b0af..00000000000
--- a/chromium/content/common/input/ipc_input_event_payload.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/input/ipc_input_event_payload.h"
-
-namespace content {
-
-scoped_ptr<IPCInputEventPayload> IPCInputEventPayload::Create() {
- return make_scoped_ptr(new IPCInputEventPayload());
-}
-
-scoped_ptr<IPCInputEventPayload> IPCInputEventPayload::Create(
- scoped_ptr<IPC::Message> message) {
- DCHECK(message);
- scoped_ptr<IPCInputEventPayload> payload = Create();
- payload->message = message.Pass();
- return payload.Pass();
-}
-
-const IPCInputEventPayload* IPCInputEventPayload::Cast(const Payload* payload) {
- DCHECK(payload);
- DCHECK_EQ(IPC_MESSAGE, payload->GetType());
- return static_cast<const IPCInputEventPayload*>(payload);
-}
-
-IPCInputEventPayload::IPCInputEventPayload() {}
-
-IPCInputEventPayload::~IPCInputEventPayload() {}
-
-InputEvent::Payload::Type IPCInputEventPayload::GetType() const {
- return IPC_MESSAGE;
-}
-
-} // namespace content
diff --git a/chromium/content/common/input/ipc_input_event_payload.h b/chromium/content/common/input/ipc_input_event_payload.h
deleted file mode 100644
index 4e95dfa5e2d..00000000000
--- a/chromium/content/common/input/ipc_input_event_payload.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_INPUT_IPC_INPUT_EVENT_PAYLOAD_H_
-#define CONTENT_COMMON_INPUT_IPC_INPUT_EVENT_PAYLOAD_H_
-
-#include "base/basictypes.h"
-#include "content/common/content_export.h"
-#include "content/common/input/input_event.h"
-#include "ipc/ipc_message.h"
-
-namespace content {
-
-// Wraps a generic IPC message of type InputMsg_*.
-class CONTENT_EXPORT IPCInputEventPayload : public InputEvent::Payload {
- public:
- static scoped_ptr<IPCInputEventPayload> Create();
- static scoped_ptr<IPCInputEventPayload> Create(
- scoped_ptr<IPC::Message> message);
-
- static const IPCInputEventPayload* Cast(const Payload* payload);
-
- virtual ~IPCInputEventPayload();
-
- // InputEvent::Payload
- virtual Type GetType() const OVERRIDE;
-
- scoped_ptr<IPC::Message> message;
-
- protected:
- IPCInputEventPayload();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(IPCInputEventPayload);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_INPUT_IPC_INPUT_EVENT_PAYLOAD_H_
diff --git a/chromium/content/common/input/scoped_web_input_event.cc b/chromium/content/common/input/scoped_web_input_event.cc
new file mode 100644
index 00000000000..8cd6e8a3862
--- /dev/null
+++ b/chromium/content/common/input/scoped_web_input_event.cc
@@ -0,0 +1,26 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/input/scoped_web_input_event.h"
+
+#include "base/logging.h"
+#include "content/common/input/web_input_event_traits.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+
+namespace content {
+
+WebInputEventDeleter::WebInputEventDeleter() {}
+
+void WebInputEventDeleter::operator()(WebInputEvent* web_event) const {
+ WebInputEventTraits::Delete(web_event);
+}
+
+} // namespace content
diff --git a/chromium/content/common/input/scoped_web_input_event.h b/chromium/content/common/input/scoped_web_input_event.h
new file mode 100644
index 00000000000..e25cc0c8959
--- /dev/null
+++ b/chromium/content/common/input/scoped_web_input_event.h
@@ -0,0 +1,28 @@
+// 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_COMMON_INPUT_SCOPED_WEB_INPUT_EVENT_H_
+#define CONTENT_COMMON_INPUT_SCOPED_WEB_INPUT_EVENT_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+
+namespace blink {
+class WebInputEvent;
+}
+
+namespace content {
+
+// blink::WebInputEvent does not provide a virtual destructor.
+struct CONTENT_EXPORT WebInputEventDeleter {
+ WebInputEventDeleter();
+ void operator()(blink::WebInputEvent* web_event) const;
+};
+typedef scoped_ptr<blink::WebInputEvent,
+ WebInputEventDeleter> ScopedWebInputEvent;
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_SCOPED_WEB_INPUT_EVENT_H_
diff --git a/chromium/content/common/input/synthetic_gesture_packet.cc b/chromium/content/common/input/synthetic_gesture_packet.cc
new file mode 100644
index 00000000000..1a999b0f25f
--- /dev/null
+++ b/chromium/content/common/input/synthetic_gesture_packet.cc
@@ -0,0 +1,13 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/input/synthetic_gesture_packet.h"
+
+namespace content {
+
+SyntheticGesturePacket::SyntheticGesturePacket() {}
+
+SyntheticGesturePacket::~SyntheticGesturePacket() {}
+
+} // namespace content
diff --git a/chromium/content/common/input/synthetic_gesture_packet.h b/chromium/content/common/input/synthetic_gesture_packet.h
new file mode 100644
index 00000000000..e87205c8282
--- /dev/null
+++ b/chromium/content/common/input/synthetic_gesture_packet.h
@@ -0,0 +1,39 @@
+// 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_COMMON_INPUT_SYNTHETIC_GESTURE_PACKET_H_
+#define CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_PACKET_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "content/common/input/synthetic_gesture_params.h"
+
+namespace content {
+
+// Wraps an object of type SyntheticGestureParams (or one of its subclasses) for
+// sending it over IPC.
+class CONTENT_EXPORT SyntheticGesturePacket {
+ public:
+ SyntheticGesturePacket();
+ ~SyntheticGesturePacket();
+
+ void set_gesture_params(scoped_ptr<SyntheticGestureParams> gesture_params) {
+ gesture_params_ = gesture_params.Pass();
+ }
+ const SyntheticGestureParams* gesture_params() const {
+ return gesture_params_.get();
+ }
+ scoped_ptr<SyntheticGestureParams> pass_gesture_params() {
+ return gesture_params_.Pass();
+ }
+
+ private:
+ scoped_ptr<SyntheticGestureParams> gesture_params_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyntheticGesturePacket);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_PACKET_H_
diff --git a/chromium/content/common/input/synthetic_gesture_params.cc b/chromium/content/common/input/synthetic_gesture_params.cc
new file mode 100644
index 00000000000..68ba38c8511
--- /dev/null
+++ b/chromium/content/common/input/synthetic_gesture_params.cc
@@ -0,0 +1,18 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/input/synthetic_gesture_params.h"
+
+namespace content {
+
+SyntheticGestureParams::SyntheticGestureParams()
+ : gesture_source_type(DEFAULT_INPUT) {}
+
+SyntheticGestureParams::SyntheticGestureParams(
+ const SyntheticGestureParams& other)
+ : gesture_source_type(other.gesture_source_type) {}
+
+SyntheticGestureParams::~SyntheticGestureParams() {}
+
+} // namespace content
diff --git a/chromium/content/common/input/synthetic_gesture_params.h b/chromium/content/common/input/synthetic_gesture_params.h
new file mode 100644
index 00000000000..323bc7d4065
--- /dev/null
+++ b/chromium/content/common/input/synthetic_gesture_params.h
@@ -0,0 +1,57 @@
+// 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_COMMON_INPUT_SYNTHETIC_GESTURE_PARAMS_H_
+#define CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_PARAMS_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Base class for storing parameters of synthetic gestures. Sending an object
+// over IPC is handled by encapsulating it in a SyntheticGesturePacket object.
+//
+// The subclasses of this class only store data on synthetic gestures.
+// The logic for dispatching input events that implement the gesture lives
+// in separate classes in content/browser/renderer_host/input/.
+//
+// Adding new gesture types involves the following steps:
+// 1) Create a new sub-type of SyntheticGestureParams with the parameters
+// needed for the new gesture.
+// 2) Use IPC macros to create serialization methods for the new type in
+// content/common/input_messages.h.
+// 3) Extend ParamTraits<content::SyntheticGesturePacket>::Write/Read/Log in
+// content/common/input/input_param_traits.cc.
+// 4) Add a new unit test to make sure that sending the type over IPC works
+// correctly.
+// The details of each step should become clear when looking at other types.
+struct CONTENT_EXPORT SyntheticGestureParams {
+ SyntheticGestureParams();
+ SyntheticGestureParams(const SyntheticGestureParams& other);
+ virtual ~SyntheticGestureParams();
+
+ // Describes which type of input events synthetic gesture objects should
+ // generate. When specifying DEFAULT_INPUT the platform will be queried for
+ // the preferred input event type.
+ enum GestureSourceType {
+ DEFAULT_INPUT,
+ TOUCH_INPUT,
+ MOUSE_INPUT,
+ GESTURE_SOURCE_TYPE_MAX = MOUSE_INPUT
+ };
+ GestureSourceType gesture_source_type;
+
+ enum GestureType {
+ SMOOTH_SCROLL_GESTURE,
+ PINCH_GESTURE,
+ TAP_GESTURE,
+ SYNTHETIC_GESTURE_TYPE_MAX = TAP_GESTURE
+ };
+ virtual GestureType GetGestureType() const = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_PARAMS_H_
diff --git a/chromium/content/common/input/synthetic_pinch_gesture_params.cc b/chromium/content/common/input/synthetic_pinch_gesture_params.cc
new file mode 100644
index 00000000000..5b4ca448605
--- /dev/null
+++ b/chromium/content/common/input/synthetic_pinch_gesture_params.cc
@@ -0,0 +1,39 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/input/synthetic_pinch_gesture_params.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+SyntheticPinchGestureParams::SyntheticPinchGestureParams()
+ : zoom_in(true),
+ total_num_pixels_covered(100),
+ relative_pointer_speed_in_pixels_s(500) {}
+
+SyntheticPinchGestureParams::SyntheticPinchGestureParams(
+ const SyntheticPinchGestureParams& other)
+ : SyntheticGestureParams(other),
+ zoom_in(other.zoom_in),
+ total_num_pixels_covered(other.total_num_pixels_covered),
+ anchor(other.anchor),
+ relative_pointer_speed_in_pixels_s(
+ other.relative_pointer_speed_in_pixels_s) {}
+
+SyntheticPinchGestureParams::~SyntheticPinchGestureParams() {}
+
+SyntheticGestureParams::GestureType
+SyntheticPinchGestureParams::GetGestureType() const {
+ return PINCH_GESTURE;
+}
+
+const SyntheticPinchGestureParams* SyntheticPinchGestureParams::Cast(
+ const SyntheticGestureParams* gesture_params) {
+ DCHECK(gesture_params);
+ DCHECK_EQ(PINCH_GESTURE, gesture_params->GetGestureType());
+ return static_cast<const SyntheticPinchGestureParams*>(gesture_params);
+}
+
+} // namespace content
diff --git a/chromium/content/common/input/synthetic_pinch_gesture_params.h b/chromium/content/common/input/synthetic_pinch_gesture_params.h
new file mode 100644
index 00000000000..215558d45ba
--- /dev/null
+++ b/chromium/content/common/input/synthetic_pinch_gesture_params.h
@@ -0,0 +1,35 @@
+// 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_COMMON_INPUT_SYNTHETIC_PINCH_GESTURE_PARAMS_H_
+#define CONTENT_COMMON_INPUT_SYNTHETIC_PINCH_GESTURE_PARAMS_H_
+
+#include "content/common/content_export.h"
+#include "content/common/input/synthetic_gesture_params.h"
+#include "ui/gfx/point.h"
+
+namespace content {
+
+struct CONTENT_EXPORT SyntheticPinchGestureParams
+ : public SyntheticGestureParams {
+ public:
+ SyntheticPinchGestureParams();
+ SyntheticPinchGestureParams(
+ const SyntheticPinchGestureParams& other);
+ virtual ~SyntheticPinchGestureParams();
+
+ virtual GestureType GetGestureType() const OVERRIDE;
+
+ bool zoom_in;
+ int total_num_pixels_covered;
+ gfx::Point anchor;
+ int relative_pointer_speed_in_pixels_s;
+
+ static const SyntheticPinchGestureParams* Cast(
+ const SyntheticGestureParams* gesture_params);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_SYNTHETIC_PINCH_GESTURE_PARAMS_H_
diff --git a/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.cc b/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.cc
new file mode 100644
index 00000000000..6d0d3272130
--- /dev/null
+++ b/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.cc
@@ -0,0 +1,42 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
+
+#include "base/logging.h"
+
+namespace content {
+namespace {
+
+const int kDefaultSpeedInPixelsS = 800;
+
+} // namespace
+
+SyntheticSmoothScrollGestureParams::SyntheticSmoothScrollGestureParams()
+ : prevent_fling(true), speed_in_pixels_s(kDefaultSpeedInPixelsS) {}
+
+SyntheticSmoothScrollGestureParams::SyntheticSmoothScrollGestureParams(
+ const SyntheticSmoothScrollGestureParams& other)
+ : SyntheticGestureParams(other),
+ distance(other.distance),
+ anchor(other.anchor),
+ prevent_fling(other.prevent_fling),
+ speed_in_pixels_s(other.speed_in_pixels_s) {}
+
+SyntheticSmoothScrollGestureParams::~SyntheticSmoothScrollGestureParams() {}
+
+SyntheticGestureParams::GestureType
+SyntheticSmoothScrollGestureParams::GetGestureType() const {
+ return SMOOTH_SCROLL_GESTURE;
+}
+
+const SyntheticSmoothScrollGestureParams*
+SyntheticSmoothScrollGestureParams::Cast(
+ const SyntheticGestureParams* gesture_params) {
+ DCHECK(gesture_params);
+ DCHECK_EQ(SMOOTH_SCROLL_GESTURE, gesture_params->GetGestureType());
+ return static_cast<const SyntheticSmoothScrollGestureParams*>(gesture_params);
+}
+
+} // namespace content
diff --git a/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h b/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h
new file mode 100644
index 00000000000..c81df82efb0
--- /dev/null
+++ b/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h
@@ -0,0 +1,36 @@
+// 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_COMMON_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_PARAMS_H_
+#define CONTENT_COMMON_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_PARAMS_H_
+
+#include "content/common/content_export.h"
+#include "content/common/input/synthetic_gesture_params.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/vector2d.h"
+
+namespace content {
+
+struct CONTENT_EXPORT SyntheticSmoothScrollGestureParams
+ : public SyntheticGestureParams {
+ public:
+ SyntheticSmoothScrollGestureParams();
+ SyntheticSmoothScrollGestureParams(
+ const SyntheticSmoothScrollGestureParams& other);
+ virtual ~SyntheticSmoothScrollGestureParams();
+
+ virtual GestureType GetGestureType() const OVERRIDE;
+
+ gfx::Vector2d distance;
+ gfx::Point anchor;
+ bool prevent_fling; // Defaults to true.
+ int speed_in_pixels_s;
+
+ static const SyntheticSmoothScrollGestureParams* Cast(
+ const SyntheticGestureParams* gesture_params);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_PARAMS_H_
diff --git a/chromium/content/common/input/synthetic_tap_gesture_params.cc b/chromium/content/common/input/synthetic_tap_gesture_params.cc
new file mode 100644
index 00000000000..a9f91dae70f
--- /dev/null
+++ b/chromium/content/common/input/synthetic_tap_gesture_params.cc
@@ -0,0 +1,33 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/input/synthetic_tap_gesture_params.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+SyntheticTapGestureParams::SyntheticTapGestureParams() : duration_ms(0) {}
+
+SyntheticTapGestureParams::SyntheticTapGestureParams(
+ const SyntheticTapGestureParams& other)
+ : SyntheticGestureParams(other),
+ position(other.position),
+ duration_ms(other.duration_ms) {}
+
+SyntheticTapGestureParams::~SyntheticTapGestureParams() {}
+
+SyntheticGestureParams::GestureType SyntheticTapGestureParams::GetGestureType()
+ const {
+ return TAP_GESTURE;
+}
+
+const SyntheticTapGestureParams* SyntheticTapGestureParams::Cast(
+ const SyntheticGestureParams* gesture_params) {
+ DCHECK(gesture_params);
+ DCHECK_EQ(TAP_GESTURE, gesture_params->GetGestureType());
+ return static_cast<const SyntheticTapGestureParams*>(gesture_params);
+}
+
+} // namespace content
diff --git a/chromium/content/common/input/synthetic_tap_gesture_params.h b/chromium/content/common/input/synthetic_tap_gesture_params.h
new file mode 100644
index 00000000000..dde22c6b1d8
--- /dev/null
+++ b/chromium/content/common/input/synthetic_tap_gesture_params.h
@@ -0,0 +1,32 @@
+// 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_COMMON_INPUT_SYNTHETIC_TAP_GESTURE_PARAMS_H_
+#define CONTENT_COMMON_INPUT_SYNTHETIC_TAP_GESTURE_PARAMS_H_
+
+#include "content/common/content_export.h"
+#include "content/common/input/synthetic_gesture_params.h"
+#include "ui/gfx/point.h"
+
+namespace content {
+
+struct CONTENT_EXPORT SyntheticTapGestureParams
+ : public SyntheticGestureParams {
+ public:
+ SyntheticTapGestureParams();
+ SyntheticTapGestureParams(const SyntheticTapGestureParams& other);
+ virtual ~SyntheticTapGestureParams();
+
+ virtual GestureType GetGestureType() const OVERRIDE;
+
+ gfx::Point position;
+ int duration_ms;
+
+ static const SyntheticTapGestureParams* Cast(
+ const SyntheticGestureParams* gesture_params);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_SYNTHETIC_PINCH_GESTURE_PARAMS_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
new file mode 100644
index 00000000000..e30ecce8259
--- /dev/null
+++ b/chromium/content/common/input/synthetic_web_input_event_builders.cc
@@ -0,0 +1,192 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/input/synthetic_web_input_event_builders.h"
+
+#include "base/logging.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+namespace content {
+
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebGestureEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+
+WebMouseEvent SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::Type type) {
+ WebMouseEvent result;
+ result.type = type;
+ return result;
+}
+
+WebMouseEvent SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::Type type,
+ int window_x,
+ int window_y,
+ int modifiers) {
+ DCHECK(WebInputEvent::isMouseEventType(type));
+ WebMouseEvent result = Build(type);
+ result.x = window_x;
+ result.y = window_y;
+ result.windowX = window_x;
+ result.windowY = window_y;
+ result.modifiers = modifiers;
+
+ if (type == WebInputEvent::MouseDown || type == WebInputEvent::MouseUp)
+ result.button = WebMouseEvent::ButtonLeft;
+ else
+ result.button = WebMouseEvent::ButtonNone;
+
+ return result;
+}
+
+WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(
+ WebMouseWheelEvent::Phase phase) {
+ WebMouseWheelEvent result;
+ result.type = WebInputEvent::MouseWheel;
+ result.phase = phase;
+ return result;
+}
+
+WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(float dx,
+ float dy,
+ int modifiers,
+ bool precise) {
+ WebMouseWheelEvent result;
+ result.type = WebInputEvent::MouseWheel;
+ result.deltaX = dx;
+ result.deltaY = dy;
+ if (dx)
+ result.wheelTicksX = dx > 0.0f ? 1.0f : -1.0f;
+ if (dy)
+ result.wheelTicksY = dy > 0.0f ? 1.0f : -1.0f;
+ result.modifiers = modifiers;
+ result.hasPreciseScrollingDeltas = precise;
+ return result;
+}
+
+WebKeyboardEvent SyntheticWebKeyboardEventBuilder::Build(
+ WebInputEvent::Type type) {
+ DCHECK(WebInputEvent::isKeyboardEventType(type));
+ WebKeyboardEvent result;
+ result.type = type;
+ result.windowsKeyCode = ui::VKEY_L; // non-null made up value.
+ return result;
+}
+
+WebGestureEvent SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::Type type,
+ WebGestureEvent::SourceDevice source_device) {
+ DCHECK(WebInputEvent::isGestureEventType(type));
+ WebGestureEvent result;
+ result.type = type;
+ result.sourceDevice = source_device;
+ return result;
+}
+
+WebGestureEvent SyntheticWebGestureEventBuilder::BuildScrollUpdate(
+ float dx,
+ float dy,
+ int modifiers) {
+ WebGestureEvent result = Build(WebInputEvent::GestureScrollUpdate,
+ WebGestureEvent::Touchscreen);
+ result.data.scrollUpdate.deltaX = dx;
+ result.data.scrollUpdate.deltaY = dy;
+ result.modifiers = modifiers;
+ return result;
+}
+
+WebGestureEvent SyntheticWebGestureEventBuilder::BuildPinchUpdate(
+ float scale,
+ float anchor_x,
+ float anchor_y,
+ int modifiers) {
+ WebGestureEvent result = Build(WebInputEvent::GesturePinchUpdate,
+ WebGestureEvent::Touchscreen);
+ result.data.pinchUpdate.scale = scale;
+ result.x = anchor_x;
+ result.y = anchor_y;
+ result.modifiers = modifiers;
+ return result;
+}
+
+WebGestureEvent SyntheticWebGestureEventBuilder::BuildFling(
+ float velocity_x,
+ float velocity_y,
+ WebGestureEvent::SourceDevice source_device) {
+ WebGestureEvent result = Build(WebInputEvent::GestureFlingStart,
+ source_device);
+ result.data.flingStart.velocityX = velocity_x;
+ result.data.flingStart.velocityY = velocity_y;
+ return result;
+}
+
+SyntheticWebTouchEvent::SyntheticWebTouchEvent() : WebTouchEvent() {}
+
+void SyntheticWebTouchEvent::ResetPoints() {
+ int point = 0;
+ for (unsigned int i = 0; i < touchesLength; ++i) {
+ if (touches[i].state == WebTouchPoint::StateReleased)
+ continue;
+
+ touches[point] = touches[i];
+ touches[point].state = WebTouchPoint::StateStationary;
+ ++point;
+ }
+ touchesLength = point;
+ type = WebInputEvent::Undefined;
+}
+
+int SyntheticWebTouchEvent::PressPoint(int x, int y) {
+ if (touchesLength == touchesLengthCap)
+ return -1;
+ WebTouchPoint& point = touches[touchesLength];
+ point.id = touchesLength;
+ point.position.x = point.screenPosition.x = x;
+ point.position.y = point.screenPosition.y = y;
+ point.state = WebTouchPoint::StatePressed;
+ point.radiusX = point.radiusY = 1.f;
+ ++touchesLength;
+ type = WebInputEvent::TouchStart;
+ return point.id;
+}
+
+void SyntheticWebTouchEvent::MovePoint(int index, int x, int y) {
+ CHECK(index >= 0 && index < touchesLengthCap);
+ WebTouchPoint& point = touches[index];
+ point.position.x = point.screenPosition.x = x;
+ point.position.y = point.screenPosition.y = y;
+ touches[index].state = WebTouchPoint::StateMoved;
+ type = WebInputEvent::TouchMove;
+}
+
+void SyntheticWebTouchEvent::ReleasePoint(int index) {
+ CHECK(index >= 0 && index < touchesLengthCap);
+ touches[index].state = WebTouchPoint::StateReleased;
+ type = WebInputEvent::TouchEnd;
+}
+
+void SyntheticWebTouchEvent::CancelPoint(int index) {
+ CHECK(index >= 0 && index < touchesLengthCap);
+ touches[index].state = WebTouchPoint::StateCancelled;
+ type = WebInputEvent::TouchCancel;
+}
+
+void SyntheticWebTouchEvent::SetTimestamp(base::TimeDelta timestamp) {
+ timeStampSeconds = timestamp.InSecondsF();
+}
+
+SyntheticWebTouchEvent SyntheticWebTouchEventBuilder::Build(
+ WebInputEvent::Type type) {
+ DCHECK(WebInputEvent::isTouchEventType(type));
+ SyntheticWebTouchEvent result;
+ result.type = type;
+ return result;
+};
+
+} // 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
new file mode 100644
index 00000000000..b52dc4122f2
--- /dev/null
+++ b/chromium/content/common/input/synthetic_web_input_event_builders.h
@@ -0,0 +1,82 @@
+// 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_COMMON_INPUT_SYNTHETIC_WEB_INPUT_EVENT_BUILDERS_H_
+#define CONTENT_COMMON_INPUT_SYNTHETIC_WEB_INPUT_EVENT_BUILDERS_H_
+
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+// Provides sensible creation of default WebInputEvents for testing purposes.
+
+namespace content {
+
+class CONTENT_EXPORT SyntheticWebMouseEventBuilder {
+ public:
+ static blink::WebMouseEvent Build(blink::WebInputEvent::Type type);
+ static blink::WebMouseEvent Build(blink::WebInputEvent::Type type,
+ int window_x,
+ int window_y,
+ int modifiers);
+};
+
+class CONTENT_EXPORT SyntheticWebMouseWheelEventBuilder {
+ public:
+ static blink::WebMouseWheelEvent Build(
+ blink::WebMouseWheelEvent::Phase phase);
+ static blink::WebMouseWheelEvent Build(float dx,
+ float dy,
+ int modifiers,
+ bool precise);
+};
+
+class CONTENT_EXPORT SyntheticWebKeyboardEventBuilder {
+ public:
+ static blink::WebKeyboardEvent Build(blink::WebInputEvent::Type type);
+};
+
+class CONTENT_EXPORT SyntheticWebGestureEventBuilder {
+ public:
+ static blink::WebGestureEvent Build(
+ blink::WebInputEvent::Type type,
+ blink::WebGestureEvent::SourceDevice sourceDevice);
+ static blink::WebGestureEvent BuildScrollUpdate(float dx,
+ float dY,
+ int modifiers);
+ static blink::WebGestureEvent BuildPinchUpdate(float scale,
+ float anchor_x,
+ float anchor_y,
+ int modifiers);
+ static blink::WebGestureEvent BuildFling(
+ float velocity_x,
+ float velocity_y,
+ blink::WebGestureEvent::SourceDevice source_device);
+};
+
+class CONTENT_EXPORT SyntheticWebTouchEvent
+ : public NON_EXPORTED_BASE(blink::WebTouchEvent) {
+ public:
+ SyntheticWebTouchEvent();
+
+ // Mark all the points as stationary, and remove any released points.
+ void ResetPoints();
+
+ // Adds an additional point to the touch list, returning the point's index.
+ int PressPoint(int x, int y);
+ void MovePoint(int index, int x, int y);
+ void ReleasePoint(int index);
+ void CancelPoint(int index);
+
+ void SetTimestamp(base::TimeDelta timestamp);
+};
+
+class CONTENT_EXPORT SyntheticWebTouchEventBuilder {
+ public:
+ static SyntheticWebTouchEvent Build(blink::WebInputEvent::Type type);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_SYNTHETIC_WEB_INPUT_EVENT_BUILDERS_H_
diff --git a/chromium/content/common/input/touch_action.h b/chromium/content/common/input/touch_action.h
new file mode 100644
index 00000000000..95cee2595b2
--- /dev/null
+++ b/chromium/content/common/input/touch_action.h
@@ -0,0 +1,25 @@
+// 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_COMMON_INPUT_TOUCH_ACTION_H_
+#define CONTENT_COMMON_INPUT_TOUCH_ACTION_H_
+
+namespace content {
+
+// The current touch action specifies what accelerated browser operations
+// (panning and zooming) are currently permitted via touch input.
+// See http://www.w3.org/TR/pointerevents/#the-touch-action-css-property.
+enum TouchAction {
+ // No scrolling or zooming allowed.
+ TOUCH_ACTION_NONE,
+
+ // All actions are pemitted (the default).
+ TOUCH_ACTION_AUTO,
+
+ TOUCH_ACTION_MAX = TOUCH_ACTION_AUTO
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_TOUCH_ACTION_H_
diff --git a/chromium/content/common/input/web_input_event_payload.cc b/chromium/content/common/input/web_input_event_payload.cc
deleted file mode 100644
index c50347a1a53..00000000000
--- a/chromium/content/common/input/web_input_event_payload.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/input/web_input_event_payload.h"
-
-#include "base/logging.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-namespace content {
-namespace {
-static WebInputEventPayload::ScopedWebInputEvent CloneWebInputEvent(
- const WebKit::WebInputEvent& event) {
- WebInputEventPayload::ScopedWebInputEvent clone;
- if (WebKit::WebInputEvent::isMouseEventType(event.type))
- clone.reset(new WebKit::WebMouseEvent());
- else if (event.type == WebKit::WebInputEvent::MouseWheel)
- clone.reset(new WebKit::WebMouseWheelEvent());
- else if (WebKit::WebInputEvent::isKeyboardEventType(event.type))
- clone.reset(new WebKit::WebKeyboardEvent());
- else if (WebKit::WebInputEvent::isTouchEventType(event.type))
- clone.reset(new WebKit::WebTouchEvent());
- else if (WebKit::WebInputEvent::isGestureEventType(event.type))
- clone.reset(new WebKit::WebGestureEvent());
- else
- NOTREACHED() << "Unknown webkit event type " << event.type;
-
- if (!clone)
- return clone.Pass();
-
- DCHECK_EQ(event.size, clone->size);
- memcpy(clone.get(), &event, event.size);
- return clone.Pass();
-}
-} // namespace
-
-WebInputEventPayload::WebInputEventDeleter::WebInputEventDeleter() {}
-
-void WebInputEventPayload::WebInputEventDeleter::operator()(
- WebKit::WebInputEvent* event) const {
- if (!event)
- return;
-
- if (WebKit::WebInputEvent::isMouseEventType(event->type))
- delete static_cast<WebKit::WebMouseEvent*>(event);
- else if (event->type == WebKit::WebInputEvent::MouseWheel)
- delete static_cast<WebKit::WebMouseWheelEvent*>(event);
- else if (WebKit::WebInputEvent::isKeyboardEventType(event->type))
- delete static_cast<WebKit::WebKeyboardEvent*>(event);
- else if (WebKit::WebInputEvent::isTouchEventType(event->type))
- delete static_cast<WebKit::WebTouchEvent*>(event);
- else if (WebKit::WebInputEvent::isGestureEventType(event->type))
- delete static_cast<WebKit::WebGestureEvent*>(event);
- else
- NOTREACHED() << "Unknown webkit event type " << event->type;
-}
-
-WebInputEventPayload::WebInputEventPayload() : is_keyboard_shortcut_(false) {}
-
-WebInputEventPayload::~WebInputEventPayload() {}
-
-scoped_ptr<WebInputEventPayload> WebInputEventPayload::Create() {
- return make_scoped_ptr(new WebInputEventPayload());
-}
-
-scoped_ptr<WebInputEventPayload> WebInputEventPayload::Create(
- const WebKit::WebInputEvent& event,
- const ui::LatencyInfo& latency_info,
- bool is_keyboard_shortcut) {
- scoped_ptr<WebInputEventPayload> payload = Create();
- payload->Initialize(event, latency_info, is_keyboard_shortcut);
- return payload.Pass();
-}
-
-const WebInputEventPayload* WebInputEventPayload::Cast(const Payload* payload) {
- DCHECK(payload);
- DCHECK_EQ(WEB_INPUT_EVENT, payload->GetType());
- return static_cast<const WebInputEventPayload*>(payload);
-}
-
-InputEvent::Payload::Type WebInputEventPayload::GetType() const {
- return WEB_INPUT_EVENT;
-}
-
-void WebInputEventPayload::Initialize(const WebKit::WebInputEvent& web_event,
- const ui::LatencyInfo& latency_info,
- bool is_keyboard_shortcut) {
- DCHECK(!web_event_) << "WebInputEventPayload already initialized";
- web_event_ = CloneWebInputEvent(web_event);
- latency_info_ = latency_info;
- is_keyboard_shortcut_ = is_keyboard_shortcut;
-}
-
-bool WebInputEventPayload::CanCreateFollowupEvents() const {
- return WebKit::WebInputEvent::isTouchEventType(web_event()->type);
-}
-
-} // namespace content
diff --git a/chromium/content/common/input/web_input_event_payload.h b/chromium/content/common/input/web_input_event_payload.h
deleted file mode 100644
index 4d35b165a6b..00000000000
--- a/chromium/content/common/input/web_input_event_payload.h
+++ /dev/null
@@ -1,67 +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_COMMON_INPUT_WEB_INPUT_EVENT_PAYLOAD_H_
-#define CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_PAYLOAD_H_
-
-#include "base/basictypes.h"
-#include "content/common/content_export.h"
-#include "content/common/input/input_event.h"
-#include "ui/events/latency_info.h"
-
-namespace WebKit {
-class WebInputEvent;
-}
-
-namespace content {
-
-// Wraps a WebKit::WebInputEvent.
-class CONTENT_EXPORT WebInputEventPayload : public InputEvent::Payload {
- public:
- static scoped_ptr<WebInputEventPayload> Create();
- static scoped_ptr<WebInputEventPayload> Create(
- const WebKit::WebInputEvent& event,
- const ui::LatencyInfo& latency_info,
- bool is_keyboard_shortcut);
-
- static const WebInputEventPayload* Cast(const Payload* payload);
-
- virtual ~WebInputEventPayload();
-
- // InputEvent::Payload
- virtual Type GetType() const OVERRIDE;
-
- void Initialize(const WebKit::WebInputEvent& event,
- const ui::LatencyInfo& latency_info,
- bool is_keyboard_shortcut);
-
- // True for WebTouchEvents only.
- bool CanCreateFollowupEvents() const;
-
- const WebKit::WebInputEvent* web_event() const { return web_event_.get(); }
- const ui::LatencyInfo& latency_info() const { return latency_info_; }
- bool is_keyboard_shortcut() const { return is_keyboard_shortcut_; }
-
- // WebKit::WebInputEvent does not provide a virtual destructor.
- struct WebInputEventDeleter {
- WebInputEventDeleter();
- void operator()(WebKit::WebInputEvent* event) const;
- };
- typedef scoped_ptr<WebKit::WebInputEvent,
- WebInputEventDeleter> ScopedWebInputEvent;
-
- protected:
- WebInputEventPayload();
-
- private:
- ScopedWebInputEvent web_event_;
- ui::LatencyInfo latency_info_;
- bool is_keyboard_shortcut_;
-
- DISALLOW_COPY_AND_ASSIGN(WebInputEventPayload);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_PAYLOAD_H_
diff --git a/chromium/content/common/input/web_input_event_traits.cc b/chromium/content/common/input/web_input_event_traits.cc
new file mode 100644
index 00000000000..5da4d9a833e
--- /dev/null
+++ b/chromium/content/common/input/web_input_event_traits.cc
@@ -0,0 +1,304 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/input/web_input_event_traits.h"
+
+#include "base/logging.h"
+
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+
+namespace content {
+namespace {
+
+bool CanCoalesce(const WebKeyboardEvent& event_to_coalesce,
+ const WebKeyboardEvent& event) {
+ return false;
+}
+
+void Coalesce(const WebKeyboardEvent& event_to_coalesce,
+ WebKeyboardEvent* event) {
+ DCHECK(CanCoalesce(event_to_coalesce, *event));
+}
+
+bool CanCoalesce(const WebMouseEvent& event_to_coalesce,
+ const WebMouseEvent& event) {
+ return event.type == event_to_coalesce.type &&
+ event.type == WebInputEvent::MouseMove;
+}
+
+void Coalesce(const WebMouseEvent& event_to_coalesce, WebMouseEvent* event) {
+ DCHECK(CanCoalesce(event_to_coalesce, *event));
+ // Accumulate movement deltas.
+ int x = event->movementX;
+ int y = event->movementY;
+ *event = event_to_coalesce;
+ event->movementX += x;
+ event->movementY += y;
+}
+
+bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce,
+ const WebMouseWheelEvent& event) {
+ return event.modifiers == event_to_coalesce.modifiers &&
+ event.scrollByPage == event_to_coalesce.scrollByPage &&
+ event.phase == event_to_coalesce.phase &&
+ event.momentumPhase == event_to_coalesce.momentumPhase &&
+ event.hasPreciseScrollingDeltas ==
+ event_to_coalesce.hasPreciseScrollingDeltas;
+}
+
+float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
+ return accelerated_delta * acceleration_ratio;
+}
+
+float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) {
+ if (unaccelerated_delta == 0.f || accelerated_delta == 0.f)
+ return 1.f;
+ return unaccelerated_delta / accelerated_delta;
+}
+
+void Coalesce(const WebMouseWheelEvent& event_to_coalesce,
+ WebMouseWheelEvent* event) {
+ DCHECK(CanCoalesce(event_to_coalesce, *event));
+ float unaccelerated_x =
+ GetUnacceleratedDelta(event->deltaX,
+ event->accelerationRatioX) +
+ GetUnacceleratedDelta(event_to_coalesce.deltaX,
+ event_to_coalesce.accelerationRatioX);
+ float unaccelerated_y =
+ GetUnacceleratedDelta(event->deltaY,
+ event->accelerationRatioY) +
+ GetUnacceleratedDelta(event_to_coalesce.deltaY,
+ event_to_coalesce.accelerationRatioY);
+ event->deltaX += event_to_coalesce.deltaX;
+ event->deltaY += event_to_coalesce.deltaY;
+ event->wheelTicksX += event_to_coalesce.wheelTicksX;
+ event->wheelTicksY += event_to_coalesce.wheelTicksY;
+ event->accelerationRatioX =
+ GetAccelerationRatio(event->deltaX, unaccelerated_x);
+ event->accelerationRatioY =
+ GetAccelerationRatio(event->deltaY, unaccelerated_y);
+ DCHECK_GE(event_to_coalesce.timeStampSeconds, event->timeStampSeconds);
+ event->timeStampSeconds = event_to_coalesce.timeStampSeconds;
+}
+
+bool CanCoalesce(const WebTouchEvent& event_to_coalesce,
+ const WebTouchEvent& event) {
+ return event.type == event_to_coalesce.type &&
+ event.type == WebInputEvent::TouchMove &&
+ event.modifiers == event_to_coalesce.modifiers &&
+ event.touchesLength == event_to_coalesce.touchesLength;
+}
+
+void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) {
+ DCHECK(CanCoalesce(event_to_coalesce, *event));
+ // The WebTouchPoints include absolute position information. So it is
+ // sufficient to simply replace the previous event with the new event->
+ // However, it is necessary to make sure that all the points have the
+ // correct state, i.e. the touch-points that moved in the last event, but
+ // didn't change in the current event, will have Stationary state. It is
+ // necessary to change them back to Moved state.
+ WebTouchEvent old_event = *event;
+ *event = event_to_coalesce;
+ for (unsigned i = 0; i < event->touchesLength; ++i) {
+ if (old_event.touches[i].state == blink::WebTouchPoint::StateMoved)
+ event->touches[i].state = blink::WebTouchPoint::StateMoved;
+ }
+}
+
+bool CanCoalesce(const WebGestureEvent& event_to_coalesce,
+ const WebGestureEvent& event) {
+ return event.type == event_to_coalesce.type &&
+ event.type == WebInputEvent::GestureScrollUpdate &&
+ event.modifiers == event_to_coalesce.modifiers;
+}
+
+void Coalesce(const WebGestureEvent& event_to_coalesce,
+ WebGestureEvent* event) {
+ DCHECK(CanCoalesce(event_to_coalesce, *event));
+ event->data.scrollUpdate.deltaX += event_to_coalesce.data.scrollUpdate.deltaX;
+ event->data.scrollUpdate.deltaY += event_to_coalesce.data.scrollUpdate.deltaY;
+}
+
+struct WebInputEventSize {
+ template <class EventType>
+ bool Execute(WebInputEvent::Type /* type */, size_t* type_size) const {
+ *type_size = sizeof(EventType);
+ return true;
+ }
+};
+
+struct WebInputEventClone {
+ template <class EventType>
+ bool Execute(const WebInputEvent& event,
+ ScopedWebInputEvent* scoped_event) const {
+ DCHECK_EQ(sizeof(EventType), event.size);
+ *scoped_event = ScopedWebInputEvent(
+ new EventType(static_cast<const EventType&>(event)));
+ return true;
+ }
+};
+
+struct WebInputEventDelete {
+ template <class EventType>
+ bool Execute(WebInputEvent* event, bool* /* dummy_var */) const {
+ if (!event)
+ return false;
+ DCHECK_EQ(sizeof(EventType), event->size);
+ delete static_cast<EventType*>(event);
+ return true;
+ }
+};
+
+struct WebInputEventCanCoalesce {
+ template <class EventType>
+ bool Execute(const WebInputEvent& event_to_coalesce,
+ const WebInputEvent* event) const {
+ if (event_to_coalesce.type != event->type)
+ return false;
+ DCHECK_EQ(sizeof(EventType), event->size);
+ DCHECK_EQ(sizeof(EventType), event_to_coalesce.size);
+ return CanCoalesce(static_cast<const EventType&>(event_to_coalesce),
+ *static_cast<const EventType*>(event));
+ }
+};
+
+struct WebInputEventCoalesce {
+ template <class EventType>
+ bool Execute(const WebInputEvent& event_to_coalesce,
+ WebInputEvent* event) const {
+ Coalesce(static_cast<const EventType&>(event_to_coalesce),
+ static_cast<EventType*>(event));
+ return true;
+ }
+};
+
+template <typename Operator, typename ArgIn, typename ArgOut>
+bool Apply(Operator op,
+ WebInputEvent::Type type,
+ const ArgIn& arg_in,
+ ArgOut* arg_out) {
+ if (WebInputEvent::isMouseEventType(type))
+ return op.template Execute<WebMouseEvent>(arg_in, arg_out);
+ else if (type == WebInputEvent::MouseWheel)
+ return op.template Execute<WebMouseWheelEvent>(arg_in, arg_out);
+ else if (WebInputEvent::isKeyboardEventType(type))
+ return op.template Execute<WebKeyboardEvent>(arg_in, arg_out);
+ else if (WebInputEvent::isTouchEventType(type))
+ return op.template Execute<WebTouchEvent>(arg_in, arg_out);
+ else if (WebInputEvent::isGestureEventType(type))
+ return op.template Execute<WebGestureEvent>(arg_in, arg_out);
+
+ NOTREACHED() << "Unknown webkit event type " << type;
+ return false;
+}
+
+} // namespace
+
+const char* WebInputEventTraits::GetName(WebInputEvent::Type type) {
+#define CASE_TYPE(t) case WebInputEvent::t: return #t
+ switch(type) {
+ CASE_TYPE(Undefined);
+ CASE_TYPE(MouseDown);
+ CASE_TYPE(MouseUp);
+ CASE_TYPE(MouseMove);
+ CASE_TYPE(MouseEnter);
+ CASE_TYPE(MouseLeave);
+ CASE_TYPE(ContextMenu);
+ CASE_TYPE(MouseWheel);
+ CASE_TYPE(RawKeyDown);
+ CASE_TYPE(KeyDown);
+ CASE_TYPE(KeyUp);
+ CASE_TYPE(Char);
+ CASE_TYPE(GestureScrollBegin);
+ CASE_TYPE(GestureScrollEnd);
+ CASE_TYPE(GestureScrollUpdate);
+ CASE_TYPE(GestureFlingStart);
+ CASE_TYPE(GestureFlingCancel);
+ CASE_TYPE(GestureShowPress);
+ CASE_TYPE(GestureTap);
+ CASE_TYPE(GestureTapUnconfirmed);
+ CASE_TYPE(GestureTapDown);
+ CASE_TYPE(GestureTapCancel);
+ CASE_TYPE(GestureDoubleTap);
+ CASE_TYPE(GestureTwoFingerTap);
+ CASE_TYPE(GestureLongPress);
+ CASE_TYPE(GestureLongTap);
+ CASE_TYPE(GesturePinchBegin);
+ CASE_TYPE(GesturePinchEnd);
+ CASE_TYPE(GesturePinchUpdate);
+ CASE_TYPE(TouchStart);
+ CASE_TYPE(TouchMove);
+ CASE_TYPE(TouchEnd);
+ CASE_TYPE(TouchCancel);
+ default:
+ // Must include default to let blink::WebInputEvent add new event types
+ // before they're added here.
+ DLOG(WARNING) <<
+ "Unhandled WebInputEvent type in WebInputEventTraits::GetName.\n";
+ break;
+ }
+#undef CASE_TYPE
+ return "";
+}
+
+size_t WebInputEventTraits::GetSize(WebInputEvent::Type type) {
+ size_t size = 0;
+ Apply(WebInputEventSize(), type, type, &size);
+ return size;
+}
+
+ScopedWebInputEvent WebInputEventTraits::Clone(const WebInputEvent& event) {
+ ScopedWebInputEvent scoped_event;
+ Apply(WebInputEventClone(), event.type, event, &scoped_event);
+ return scoped_event.Pass();
+}
+
+void WebInputEventTraits::Delete(WebInputEvent* event) {
+ if (!event)
+ return;
+ bool dummy_var = false;
+ Apply(WebInputEventDelete(), event->type, event, &dummy_var);
+}
+
+bool WebInputEventTraits::CanCoalesce(const WebInputEvent& event_to_coalesce,
+ const WebInputEvent& event) {
+ // Early out before casting.
+ if (event_to_coalesce.type != event.type)
+ return false;
+ return Apply(WebInputEventCanCoalesce(),
+ event.type,
+ event_to_coalesce,
+ &event);
+}
+
+void WebInputEventTraits::Coalesce(const WebInputEvent& event_to_coalesce,
+ WebInputEvent* event) {
+ DCHECK(event);
+ Apply(WebInputEventCoalesce(), event->type, event_to_coalesce, event);
+}
+
+bool WebInputEventTraits::IgnoresAckDisposition(
+ blink::WebInputEvent::Type type) {
+ switch (type) {
+ case WebInputEvent::GestureTapDown:
+ case WebInputEvent::GestureShowPress:
+ case WebInputEvent::GestureTapCancel:
+ case WebInputEvent::GesturePinchBegin:
+ case WebInputEvent::GesturePinchEnd:
+ case WebInputEvent::GestureScrollBegin:
+ case WebInputEvent::GestureScrollEnd:
+ case WebInputEvent::TouchCancel:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/common/input/web_input_event_traits.h b/chromium/content/common/input/web_input_event_traits.h
new file mode 100644
index 00000000000..9751fc088cb
--- /dev/null
+++ b/chromium/content/common/input/web_input_event_traits.h
@@ -0,0 +1,30 @@
+// 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_COMMON_INPUT_WEB_INPUT_EVENT_TRAITS_H_
+#define CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_TRAITS_H_
+
+#include "base/basictypes.h"
+#include "content/common/input/scoped_web_input_event.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace content {
+
+// Utility class for performing operations on and with WebInputEvents.
+class CONTENT_EXPORT WebInputEventTraits {
+ public:
+ static const char* GetName(blink::WebInputEvent::Type type);
+ static size_t GetSize(blink::WebInputEvent::Type type);
+ static ScopedWebInputEvent Clone(const blink::WebInputEvent& event);
+ static void Delete(blink::WebInputEvent* event);
+ static bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce,
+ const blink::WebInputEvent& event);
+ static void Coalesce(const blink::WebInputEvent& event_to_coalesce,
+ blink::WebInputEvent* event);
+ static bool IgnoresAckDisposition(blink::WebInputEvent::Type type);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_TRAITS_H_
diff --git a/chromium/content/common/input_messages.h b/chromium/content/common/input_messages.h
index 5d2e3ed1809..80b0536d054 100644
--- a/chromium/content/common/input_messages.h
+++ b/chromium/content/common/input_messages.h
@@ -11,12 +11,15 @@
#include "content/common/content_param_traits.h"
#include "content/common/edit_command.h"
#include "content/common/input/input_event.h"
-#include "content/common/input/input_event_disposition.h"
#include "content/common/input/input_param_traits.h"
-#include "content/common/input/ipc_input_event_payload.h"
-#include "content/common/input/event_packet.h"
+#include "content/common/input/synthetic_gesture_packet.h"
+#include "content/common/input/synthetic_gesture_params.h"
+#include "content/common/input/synthetic_pinch_gesture_params.h"
+#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
+#include "content/common/input/synthetic_tap_gesture_params.h"
#include "content/port/common/input_event_ack_state.h"
#include "content/public/common/common_param_traits.h"
+#include "content/common/input/touch_action.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/latency_info.h"
@@ -32,20 +35,52 @@
#define IPC_MESSAGE_START InputMsgStart
-IPC_ENUM_TRAITS_MAX_VALUE(content::InputEvent::Payload::Type,
- content::InputEvent::Payload::PAYLOAD_TYPE_MAX)
IPC_ENUM_TRAITS_MAX_VALUE(content::InputEventAckState,
content::INPUT_EVENT_ACK_STATE_MAX)
-IPC_ENUM_TRAITS_MAX_VALUE(content::InputEventDisposition,
- content::INPUT_EVENT_DISPOSITION_MAX)
+IPC_ENUM_TRAITS_MAX_VALUE(
+ content::SyntheticGestureParams::GestureSourceType,
+ content::SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX)
+IPC_ENUM_TRAITS_MAX_VALUE(
+ content::SyntheticGestureParams::GestureType,
+ content::SyntheticGestureParams::SYNTHETIC_GESTURE_TYPE_MAX)
+IPC_ENUM_TRAITS_MAX_VALUE(content::TouchAction,
+ content::TOUCH_ACTION_MAX)
IPC_STRUCT_TRAITS_BEGIN(content::EditCommand)
IPC_STRUCT_TRAITS_MEMBER(name)
IPC_STRUCT_TRAITS_MEMBER(value)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(content::IPCInputEventPayload)
- IPC_STRUCT_TRAITS_MEMBER(message)
+IPC_STRUCT_TRAITS_BEGIN(content::InputEvent)
+ IPC_STRUCT_TRAITS_MEMBER(web_event)
+ IPC_STRUCT_TRAITS_MEMBER(latency_info)
+ IPC_STRUCT_TRAITS_MEMBER(is_keyboard_shortcut)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::SyntheticGestureParams)
+ IPC_STRUCT_TRAITS_MEMBER(gesture_source_type)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::SyntheticSmoothScrollGestureParams)
+ IPC_STRUCT_TRAITS_PARENT(content::SyntheticGestureParams)
+ IPC_STRUCT_TRAITS_MEMBER(distance)
+ IPC_STRUCT_TRAITS_MEMBER(anchor)
+ IPC_STRUCT_TRAITS_MEMBER(prevent_fling)
+ IPC_STRUCT_TRAITS_MEMBER(speed_in_pixels_s)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::SyntheticPinchGestureParams)
+ IPC_STRUCT_TRAITS_PARENT(content::SyntheticGestureParams)
+ IPC_STRUCT_TRAITS_MEMBER(zoom_in)
+ IPC_STRUCT_TRAITS_MEMBER(total_num_pixels_covered)
+ IPC_STRUCT_TRAITS_MEMBER(anchor)
+ IPC_STRUCT_TRAITS_MEMBER(relative_pointer_speed_in_pixels_s)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::SyntheticTapGestureParams)
+ IPC_STRUCT_TRAITS_PARENT(content::SyntheticGestureParams)
+ IPC_STRUCT_TRAITS_MEMBER(position)
+ IPC_STRUCT_TRAITS_MEMBER(duration_ms)
IPC_STRUCT_TRAITS_END()
// Sends an input event to the render widget.
@@ -54,11 +89,6 @@ IPC_MESSAGE_ROUTED3(InputMsg_HandleInputEvent,
ui::LatencyInfo /* latency_info */,
bool /* is_keyboard_shortcut */)
-// Sends an event packet to the render widget.
-IPC_MESSAGE_ROUTED2(InputMsg_HandleEventPacket,
- content::EventPacket /* event_packet */,
- content::InputEventDispositions /* dispositions */)
-
// Sends the cursor visibility state to the render widget.
IPC_MESSAGE_ROUTED1(InputMsg_CursorVisibilityChange,
bool /* is_visible */)
@@ -112,10 +142,10 @@ IPC_MESSAGE_ROUTED0(InputMsg_PasteAndMatchStyle)
// Replaces the selected region or a word around the cursor with the
// specified string.
IPC_MESSAGE_ROUTED1(InputMsg_Replace,
- string16)
+ base::string16)
// Replaces the misspelling in the selected region with the specified string.
IPC_MESSAGE_ROUTED1(InputMsg_ReplaceMisspelling,
- string16)
+ base::string16)
IPC_MESSAGE_ROUTED0(InputMsg_Delete)
IPC_MESSAGE_ROUTED0(InputMsg_SelectAll)
@@ -141,19 +171,23 @@ IPC_MESSAGE_ROUTED3(InputMsg_ActivateNearestFindResult,
float /* y */)
#endif
+IPC_MESSAGE_ROUTED0(InputMsg_SyntheticGestureCompleted);
+
// -----------------------------------------------------------------------------
// Messages sent from the renderer to the browser.
// Acknowledges receipt of a InputMsg_HandleInputEvent message.
IPC_MESSAGE_ROUTED3(InputHostMsg_HandleInputEvent_ACK,
- WebKit::WebInputEvent::Type,
+ blink::WebInputEvent::Type,
content::InputEventAckState /* ack_result */,
ui::LatencyInfo /* latency_info */)
-IPC_MESSAGE_ROUTED2(InputHostMsg_HandleEventPacket_ACK,
- int64 /* event_packet_id */,
- content::InputEventDispositions /* dispositions */)
+IPC_MESSAGE_ROUTED1(InputHostMsg_QueueSyntheticGesture,
+ content::SyntheticGesturePacket)
+// Notifies the allowed touch actions for a new touch point.
+IPC_MESSAGE_ROUTED1(InputHostMsg_SetTouchAction,
+ content::TouchAction /* touch_action */)
// Adding a new message? Stick to the sort order above: first platform
// independent InputMsg, then ifdefs for platform specific InputMsg, then
diff --git a/chromium/content/common/java_bridge_messages.h b/chromium/content/common/java_bridge_messages.h
index 62923c7e222..6bb811631e0 100644
--- a/chromium/content/common/java_bridge_messages.h
+++ b/chromium/content/common/java_bridge_messages.h
@@ -16,17 +16,14 @@
// Messages for handling Java objects injected into JavaScript -----------------
-// Sent from browser to renderer to initialize the Java Bridge.
-IPC_MESSAGE_ROUTED0(JavaBridgeMsg_Init)
-
// Sent from browser to renderer to add a Java object with the given name.
IPC_MESSAGE_ROUTED2(JavaBridgeMsg_AddNamedObject,
- string16 /* name */,
+ base::string16 /* name */,
content::NPVariant_Param) /* object */
// Sent from browser to renderer to remove a Java object with the given name.
IPC_MESSAGE_ROUTED1(JavaBridgeMsg_RemoveNamedObject,
- string16 /* name */)
+ base::string16 /* name */)
// Sent from renderer to browser to request a route ID for a renderer-side (ie
// JavaScript) object.
diff --git a/chromium/content/common/mac/attributed_string_coder.h b/chromium/content/common/mac/attributed_string_coder.h
index 629beedff4e..35b3bf54a55 100644
--- a/chromium/content/common/mac/attributed_string_coder.h
+++ b/chromium/content/common/mac/attributed_string_coder.h
@@ -62,12 +62,12 @@ class CONTENT_EXPORT AttributedStringCoder {
// which can be serialized over IPC.
class EncodedString {
public:
- explicit EncodedString(string16 string);
+ explicit EncodedString(base::string16 string);
EncodedString();
~EncodedString();
// Accessors:
- string16 string() const { return string_; }
+ base::string16 string() const { return string_; }
const std::vector<FontAttribute>& attributes() const {
return attributes_;
}
@@ -75,7 +75,7 @@ class CONTENT_EXPORT AttributedStringCoder {
private:
// The plain-text string.
- string16 string_;
+ base::string16 string_;
// The set of attributes that style |string_|.
std::vector<FontAttribute> attributes_;
};
diff --git a/chromium/content/common/mac/attributed_string_coder.mm b/chromium/content/common/mac/attributed_string_coder.mm
index ba6eca535c1..f14103bde0f 100644
--- a/chromium/content/common/mac/attributed_string_coder.mm
+++ b/chromium/content/common/mac/attributed_string_coder.mm
@@ -65,7 +65,7 @@ NSAttributedString* AttributedStringCoder::Decode(
// Data Types //////////////////////////////////////////////////////////////////
-AttributedStringCoder::EncodedString::EncodedString(string16 string)
+AttributedStringCoder::EncodedString::EncodedString(base::string16 string)
: string_(string) {
}
@@ -129,7 +129,7 @@ bool ParamTraits<AttributedStringCoder::EncodedString>::Read(
const Message* m, PickleIterator* iter, param_type* p) {
bool success = true;
- string16 result;
+ base::string16 result;
success &= ReadParam(m, iter, &result);
*p = AttributedStringCoder::EncodedString(result);
diff --git a/chromium/content/common/mac/font_descriptor.h b/chromium/content/common/mac/font_descriptor.h
index f47eb22aebf..219f1fb2ca8 100644
--- a/chromium/content/common/mac/font_descriptor.h
+++ b/chromium/content/common/mac/font_descriptor.h
@@ -17,7 +17,7 @@ class NSFont;
// Container to allow serializing an NSFont over IPC.
struct CONTENT_EXPORT FontDescriptor {
explicit FontDescriptor(NSFont* font);
- FontDescriptor(string16 name, float size);
+ FontDescriptor(base::string16 name, float size);
FontDescriptor() : font_point_size(0) {}
@@ -25,7 +25,7 @@ struct CONTENT_EXPORT FontDescriptor {
NSFont* ToNSFont() const;
// Name of the font.
- string16 font_name;
+ base::string16 font_name;
// Size in points.
float font_point_size;
diff --git a/chromium/content/common/mac/font_descriptor.mm b/chromium/content/common/mac/font_descriptor.mm
index 3b5a577ad61..e5c04c124be 100644
--- a/chromium/content/common/mac/font_descriptor.mm
+++ b/chromium/content/common/mac/font_descriptor.mm
@@ -13,7 +13,7 @@ FontDescriptor::FontDescriptor(NSFont* font) {
font_point_size = [font pointSize];
}
-FontDescriptor::FontDescriptor(string16 name, float size) {
+FontDescriptor::FontDescriptor(base::string16 name, float size) {
font_name = name;
font_point_size = size;
}
diff --git a/chromium/content/common/mac/font_loader.mm b/chromium/content/common/mac/font_loader.mm
index 6ecb7ca6b70..66b143f0a38 100644
--- a/chromium/content/common/mac/font_loader.mm
+++ b/chromium/content/common/mac/font_loader.mm
@@ -124,7 +124,7 @@ void FontLoader::LoadFont(const FontDescriptor& font,
// Load file into shared memory buffer.
int64 font_file_size_64 = -1;
- if (!file_util::GetFileSize(font_path, &font_file_size_64)) {
+ if (!base::GetFileSize(font_path, &font_file_size_64)) {
DLOG(ERROR) << "Couldn't get font file size for " << font_path.value();
return;
}
@@ -140,9 +140,9 @@ void FontLoader::LoadFont(const FontDescriptor& font,
return;
}
- int32 amt_read = file_util::ReadFile(font_path,
- reinterpret_cast<char*>(result->font_data.memory()),
- font_file_size_32);
+ int32 amt_read = base::ReadFile(font_path,
+ reinterpret_cast<char*>(result->font_data.memory()),
+ font_file_size_32);
if (amt_read != font_file_size_32) {
DLOG(ERROR) << "Failed to read font data for " << font_path.value();
return;
diff --git a/chromium/content/common/media/media_param_traits.cc b/chromium/content/common/media/media_param_traits.cc
index 7c2bca4d722..3ec6a25994c 100644
--- a/chromium/content/common/media/media_param_traits.cc
+++ b/chromium/content/common/media/media_param_traits.cc
@@ -11,8 +11,8 @@
using media::AudioParameters;
using media::ChannelLayout;
-using media::VideoCaptureParams;
-using media::VideoCaptureSessionId;
+using media::VideoCaptureFormat;
+using media::VideoPixelFormat;
namespace IPC {
@@ -25,13 +25,14 @@ void ParamTraits<AudioParameters>::Write(Message* m,
m->WriteInt(p.frames_per_buffer());
m->WriteInt(p.channels());
m->WriteInt(p.input_channels());
+ m->WriteInt(p.effects());
}
bool ParamTraits<AudioParameters>::Read(const Message* m,
PickleIterator* iter,
AudioParameters* r) {
int format, channel_layout, sample_rate, bits_per_sample,
- frames_per_buffer, channels, input_channels;
+ frames_per_buffer, channels, input_channels, effects;
if (!m->ReadInt(iter, &format) ||
!m->ReadInt(iter, &channel_layout) ||
@@ -39,11 +40,14 @@ bool ParamTraits<AudioParameters>::Read(const Message* m,
!m->ReadInt(iter, &bits_per_sample) ||
!m->ReadInt(iter, &frames_per_buffer) ||
!m->ReadInt(iter, &channels) ||
- !m->ReadInt(iter, &input_channels))
+ !m->ReadInt(iter, &input_channels) ||
+ !m->ReadInt(iter, &effects))
return false;
- r->Reset(static_cast<AudioParameters::Format>(format),
- static_cast<ChannelLayout>(channel_layout), channels,
- input_channels, sample_rate, bits_per_sample, frames_per_buffer);
+ AudioParameters params(static_cast<AudioParameters::Format>(format),
+ static_cast<ChannelLayout>(channel_layout), channels,
+ input_channels, sample_rate, bits_per_sample, frames_per_buffer,
+ effects);
+ *r = params;
if (!r->IsValid())
return false;
return true;
@@ -54,38 +58,34 @@ void ParamTraits<AudioParameters>::Log(const AudioParameters& p,
l->append(base::StringPrintf("<AudioParameters>"));
}
-void ParamTraits<VideoCaptureParams>::Write(Message* m,
- const VideoCaptureParams& p) {
- m->WriteInt(p.width);
- m->WriteInt(p.height);
+void ParamTraits<VideoCaptureFormat>::Write(Message* m,
+ const VideoCaptureFormat& p) {
+ m->WriteInt(p.frame_size.width());
+ m->WriteInt(p.frame_size.height());
m->WriteInt(p.frame_rate);
- m->WriteInt(static_cast<int>(p.session_id));
- m->WriteInt(static_cast<int>(p.frame_size_type));
+ m->WriteInt(static_cast<int>(p.pixel_format));
}
-bool ParamTraits<VideoCaptureParams>::Read(const Message* m,
+bool ParamTraits<VideoCaptureFormat>::Read(const Message* m,
PickleIterator* iter,
- VideoCaptureParams* r) {
- int session_id, frame_size_type;
- if (!m->ReadInt(iter, &r->width) ||
- !m->ReadInt(iter, &r->height) ||
+ VideoCaptureFormat* r) {
+ int frame_size_width, frame_size_height, pixel_format;
+ if (!m->ReadInt(iter, &frame_size_width) ||
+ !m->ReadInt(iter, &frame_size_height) ||
!m->ReadInt(iter, &r->frame_rate) ||
- !m->ReadInt(iter, &session_id) ||
- !m->ReadInt(iter, &frame_size_type))
+ !m->ReadInt(iter, &pixel_format))
return false;
- r->session_id = static_cast<VideoCaptureSessionId>(session_id);
- r->frame_size_type =
- static_cast<media::VideoCaptureResolutionType>(
- frame_size_type);
+ r->frame_size.SetSize(frame_size_width, frame_size_height);
+ r->pixel_format = static_cast<VideoPixelFormat>(pixel_format);
if (!r->IsValid())
return false;
return true;
}
-void ParamTraits<VideoCaptureParams>::Log(const VideoCaptureParams& p,
+void ParamTraits<VideoCaptureFormat>::Log(const VideoCaptureFormat& p,
std::string* l) {
- l->append(base::StringPrintf("<VideoCaptureParams>"));
+ l->append(base::StringPrintf("<VideoCaptureFormat>"));
}
}
diff --git a/chromium/content/common/media/media_param_traits.h b/chromium/content/common/media/media_param_traits.h
index f1696197feb..94e2cd0970a 100644
--- a/chromium/content/common/media/media_param_traits.h
+++ b/chromium/content/common/media/media_param_traits.h
@@ -11,7 +11,7 @@
namespace media {
class AudioParameters;
-class VideoCaptureParams;
+class VideoCaptureFormat;
}
namespace IPC {
@@ -25,14 +25,13 @@ struct CONTENT_EXPORT ParamTraits<media::AudioParameters> {
};
template <>
-struct CONTENT_EXPORT ParamTraits<media::VideoCaptureParams> {
- typedef media::VideoCaptureParams param_type;
+struct CONTENT_EXPORT ParamTraits<media::VideoCaptureFormat> {
+ typedef media::VideoCaptureFormat param_type;
static void Write(Message* m, const param_type& p);
static bool Read(const Message* m, PickleIterator* iter, param_type* r);
static void Log(const param_type& p, std::string* l);
};
-
} // namespace IPC
#endif // CONTENT_COMMON_MEDIA_MEDIA_PARAM_TRAITS_H_
diff --git a/chromium/content/common/media/media_player_messages_android.h b/chromium/content/common/media/media_player_messages_android.h
index 8e952d17d89..5addcf1b5e5 100644
--- a/chromium/content/common/media/media_player_messages_android.h
+++ b/chromium/content/common/media/media_player_messages_android.h
@@ -69,6 +69,44 @@ IPC_STRUCT_TRAITS_END()
IPC_ENUM_TRAITS(MediaPlayerHostMsg_Initialize_Type)
+// Chrome for Android seek message sequence is:
+// 1. Renderer->Browser MediaPlayerHostMsg_Seek
+// This is the beginning of actual seek flow in response to web app requests
+// for seeks and browser MediaPlayerMsg_SeekRequests. With this message,
+// the renderer asks browser to perform actual seek. At most one of these
+// actual seeks will be in process between this message and renderer's later
+// receipt of MediaPlayerMsg_SeekCompleted from the browser.
+// 2. Browser->Renderer MediaPlayerMsg_SeekCompleted
+// Once the browser determines the seek is complete, it sends this message to
+// notify the renderer of seek completion.
+//
+// Other seek-related IPC messages:
+// Browser->Renderer MediaPlayerMsg_SeekRequest
+// Browser requests to begin a seek. All browser-initiated seeks must begin
+// with this request. Renderer controls actual seek initiation via the normal
+// seek flow, above, keeping web apps aware of seeks. These requests are
+// also allowed while another actual seek is in progress.
+//
+// If the demuxer is located in the renderer, as in media source players, the
+// browser must ensure the renderer demuxer is appropriately seeked between
+// receipt of MediaPlayerHostMsg_Seek and transmission of
+// MediaPlayerMsg_SeekCompleted. The following two renderer-demuxer control
+// messages book-end the renderer-demuxer seek:
+// 1.1 Browser->Renderer MediaPlayerMsg_DemuxerSeekRequest
+// 1.2 Renderer->Browser MediaPlayerHostMsg_DemuxerSeekDone
+
+// Only in short-term hack to seek to reach I-Frame to feed a newly constructed
+// video decoder may the above IPC sequence be modified to exclude SeekRequest,
+// Seek and SeekCompleted, with condition that DemuxerSeekRequest's
+// |is_browser_seek| parameter be true. Regular seek messages must still be
+// handled even when a hack browser seek is in progress. In this case, the
+// browser seek request's |time_to_seek| may no longer be buffered and the
+// demuxer may instead seek to a future buffered time. The resulting
+// DemuxerSeekDone message's |actual_browser_seek_time| is the time actually
+// seeked-to, and is only meaningful for these hack browser seeks.
+// TODO(wolenetz): Instead of doing browser seek, replay cached data since last
+// keyframe. See http://crbug.com/304234.
+
// Messages for notifying the render process of media playback status -------
// Media buffering has updated.
@@ -93,8 +131,13 @@ IPC_MESSAGE_ROUTED5(MediaPlayerMsg_MediaMetadataChanged,
int /* height */,
bool /* success */)
+// Requests renderer player to ask its client (blink HTMLMediaElement) to seek.
+IPC_MESSAGE_ROUTED2(MediaPlayerMsg_SeekRequest,
+ int /* player_id */,
+ base::TimeDelta /* time_to_seek_to */)
+
// Media seek is completed.
-IPC_MESSAGE_ROUTED2(MediaPlayerMsg_MediaSeekCompleted,
+IPC_MESSAGE_ROUTED2(MediaPlayerMsg_SeekCompleted,
int /* player_id */,
base::TimeDelta /* current_time */)
@@ -129,11 +172,11 @@ IPC_MESSAGE_ROUTED1(MediaPlayerMsg_DidMediaPlayerPlay,
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_DidMediaPlayerPause,
int /* player_id */)
-// Media seek is requested.
-IPC_MESSAGE_CONTROL3(MediaPlayerMsg_MediaSeekRequest,
+// Requests renderer demuxer seek.
+IPC_MESSAGE_CONTROL3(MediaPlayerMsg_DemuxerSeekRequest,
int /* demuxer_client_id */,
base::TimeDelta /* time_to_seek */,
- uint32 /* seek_request_id */)
+ bool /* is_browser_seek */)
// The media source player reads data from demuxer
IPC_MESSAGE_CONTROL2(MediaPlayerMsg_ReadFromDemuxer,
@@ -144,6 +187,16 @@ IPC_MESSAGE_CONTROL2(MediaPlayerMsg_ReadFromDemuxer,
IPC_MESSAGE_CONTROL1(MediaPlayerMsg_MediaConfigRequest,
int /* demuxer_client_id */)
+IPC_MESSAGE_ROUTED1(MediaPlayerMsg_ConnectedToRemoteDevice,
+ int /* player_id */)
+
+IPC_MESSAGE_ROUTED1(MediaPlayerMsg_DisconnectedFromRemoteDevice,
+ int /* player_id */)
+
+// Instructs the video element to enter fullscreen.
+IPC_MESSAGE_ROUTED1(MediaPlayerMsg_RequestFullscreen,
+ int /*player_id */)
+
// Messages for controlling the media playback in browser process ----------
// Destroy the media player object.
@@ -191,16 +244,16 @@ IPC_MESSAGE_ROUTED2(MediaPlayerHostMsg_SetVolume,
int /* player_id */,
double /* volume */)
-// Request the player to enter fullscreen.
+// Requests the player to enter fullscreen.
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_EnterFullscreen, int /* player_id */)
-// Request the player to exit fullscreen.
+// Requests the player to exit fullscreen.
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_ExitFullscreen, int /* player_id */)
-// Sent when the seek request is received by the WebMediaPlayerAndroid.
-IPC_MESSAGE_CONTROL2(MediaPlayerHostMsg_MediaSeekRequestAck,
+// Sent after the renderer demuxer has seeked.
+IPC_MESSAGE_CONTROL2(MediaPlayerHostMsg_DemuxerSeekDone,
int /* demuxer_client_id */,
- uint32 /* seek_request_id */)
+ base::TimeDelta /* actual_browser_seek_time */)
// Inform the media source player that the demuxer is ready.
IPC_MESSAGE_CONTROL2(MediaPlayerHostMsg_DemuxerReady,
@@ -217,14 +270,13 @@ IPC_MESSAGE_CONTROL2(MediaPlayerHostMsg_DurationChanged,
int /* demuxer_client_id */,
base::TimeDelta /* duration */)
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
// Notify the player about the external surface, requesting it if necessary.
IPC_MESSAGE_ROUTED3(MediaPlayerHostMsg_NotifyExternalSurface,
int /* player_id */,
bool /* is_request */,
gfx::RectF /* rect */)
-
-#endif
+#endif // defined(VIDEO_HOLE)
// Messages for encrypted media extensions API ------------------------------
// TODO(xhwang): Move the following messages to a separate file.
@@ -234,33 +286,44 @@ IPC_MESSAGE_ROUTED3(MediaKeysHostMsg_InitializeCDM,
std::vector<uint8> /* uuid */,
GURL /* frame url */)
-IPC_MESSAGE_ROUTED3(MediaKeysHostMsg_GenerateKeyRequest,
+IPC_MESSAGE_ROUTED4(MediaKeysHostMsg_CreateSession,
int /* media_keys_id */,
+ uint32_t /* session_id */,
std::string /* type */,
std::vector<uint8> /* init_data */)
+// TODO(jrummell): Use enum for type (http://crbug.com/327449)
-IPC_MESSAGE_ROUTED4(MediaKeysHostMsg_AddKey,
+IPC_MESSAGE_ROUTED3(MediaKeysHostMsg_UpdateSession,
int /* media_keys_id */,
- std::vector<uint8> /* key */,
- std::vector<uint8> /* init_data */,
- std::string /* session_id */)
+ uint32_t /* session_id */,
+ std::vector<uint8> /* response */)
-IPC_MESSAGE_ROUTED2(MediaKeysHostMsg_CancelKeyRequest,
+IPC_MESSAGE_ROUTED2(MediaKeysHostMsg_ReleaseSession,
int /* media_keys_id */,
- std::string /* session_id */)
+ uint32_t /* session_id */)
-IPC_MESSAGE_ROUTED2(MediaKeysMsg_KeyAdded,
+IPC_MESSAGE_ROUTED3(MediaKeysMsg_SessionCreated,
int /* media_keys_id */,
- std::string /* session_id */)
+ uint32_t /* session_id */,
+ std::string /* web_session_id */)
-IPC_MESSAGE_ROUTED4(MediaKeysMsg_KeyError,
+IPC_MESSAGE_ROUTED4(MediaKeysMsg_SessionMessage,
int /* media_keys_id */,
- std::string /* session_id */,
- media::MediaKeys::KeyError /* error_code */,
- int /* system_code */)
-
-IPC_MESSAGE_ROUTED4(MediaKeysMsg_KeyMessage,
- int /* media_keys_id */,
- std::string /* session_id */,
+ uint32_t /* session_id */,
std::vector<uint8> /* message */,
std::string /* destination_url */)
+// TODO(jrummell): Use GURL for destination_url (http://crbug.com/326663)
+
+IPC_MESSAGE_ROUTED2(MediaKeysMsg_SessionReady,
+ int /* media_keys_id */,
+ uint32_t /* session_id */)
+
+IPC_MESSAGE_ROUTED2(MediaKeysMsg_SessionClosed,
+ int /* media_keys_id */,
+ uint32_t /* session_id */)
+
+IPC_MESSAGE_ROUTED4(MediaKeysMsg_SessionError,
+ int /* media_keys_id */,
+ uint32_t /* session_id */,
+ media::MediaKeys::KeyError /* error_code */,
+ int /* system_code */)
diff --git a/chromium/content/common/media/media_stream_messages.h b/chromium/content/common/media/media_stream_messages.h
index b95f4f6f89d..8c4caf5a1b2 100644
--- a/chromium/content/common/media/media_stream_messages.h
+++ b/chromium/content/common/media/media_stream_messages.h
@@ -22,11 +22,18 @@ IPC_ENUM_TRAITS_MAX_VALUE(content::MediaStreamType,
IPC_ENUM_TRAITS_MAX_VALUE(content::VideoFacingMode,
content::NUM_MEDIA_VIDEO_FACING_MODE - 1)
+IPC_STRUCT_TRAITS_BEGIN(content::StreamOptions::Constraint)
+ IPC_STRUCT_TRAITS_MEMBER(name)
+ IPC_STRUCT_TRAITS_MEMBER(value)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::StreamOptions)
- IPC_STRUCT_TRAITS_MEMBER(audio_type)
- IPC_STRUCT_TRAITS_MEMBER(audio_device_id)
- IPC_STRUCT_TRAITS_MEMBER(video_type)
- IPC_STRUCT_TRAITS_MEMBER(video_device_id)
+ IPC_STRUCT_TRAITS_MEMBER(audio_requested)
+ IPC_STRUCT_TRAITS_MEMBER(mandatory_audio)
+ IPC_STRUCT_TRAITS_MEMBER(optional_audio)
+ IPC_STRUCT_TRAITS_MEMBER(video_requested)
+ IPC_STRUCT_TRAITS_MEMBER(mandatory_video)
+ IPC_STRUCT_TRAITS_MEMBER(optional_video)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::StreamDeviceInfo)
@@ -38,10 +45,10 @@ IPC_STRUCT_TRAITS_BEGIN(content::StreamDeviceInfo)
IPC_STRUCT_TRAITS_MEMBER(device.input.sample_rate)
IPC_STRUCT_TRAITS_MEMBER(device.input.channel_layout)
IPC_STRUCT_TRAITS_MEMBER(device.input.frames_per_buffer)
+ IPC_STRUCT_TRAITS_MEMBER(device.input.effects)
IPC_STRUCT_TRAITS_MEMBER(device.matched_output.sample_rate)
IPC_STRUCT_TRAITS_MEMBER(device.matched_output.channel_layout)
IPC_STRUCT_TRAITS_MEMBER(device.matched_output.frames_per_buffer)
- IPC_STRUCT_TRAITS_MEMBER(in_use)
IPC_STRUCT_TRAITS_MEMBER(session_id)
IPC_STRUCT_TRAITS_END()
@@ -58,24 +65,20 @@ IPC_MESSAGE_ROUTED4(MediaStreamMsg_StreamGenerated,
IPC_MESSAGE_ROUTED1(MediaStreamMsg_StreamGenerationFailed,
int /* request id */)
-// The browser requests to stop streaming.
-// Note that this differs from MediaStreamHostMsg_StopGeneratedStream below
-// which is a request from the renderer.
-IPC_MESSAGE_ROUTED1(MediaStreamMsg_StopGeneratedStream,
- std::string /* label */)
+// The browser reports that a media device has been stopped. Stopping was
+// triggered from the browser process.
+IPC_MESSAGE_ROUTED2(MediaStreamMsg_DeviceStopped,
+ std::string /* label */,
+ content::StreamDeviceInfo /* the device */)
-// The browser has enumerated devices successfully.
+// The browser has enumerated devices. If no devices are found
+// |device_list| is empty.
// Used by Pepper.
// TODO(vrk,wjia): Move this to pepper code.
-IPC_MESSAGE_ROUTED3(MediaStreamMsg_DevicesEnumerated,
+IPC_MESSAGE_ROUTED2(MediaStreamMsg_DevicesEnumerated,
int /* request id */,
- std::string /* label */,
content::StreamDeviceInfoArray /* device_list */)
-// The browser has failed to enumerate devices.
-IPC_MESSAGE_ROUTED1(MediaStreamMsg_DevicesEnumerationFailed,
- int /* request id */)
-
// TODO(wjia): should DeviceOpen* messages be merged with
// StreamGenerat* ones?
// The browser has opened a device successfully.
@@ -107,10 +110,16 @@ IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_CancelGenerateStream,
int /* render view id */,
int /* request id */)
-// Request to stop streaming from the media stream.
-IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_StopGeneratedStream,
+// Request to close a device that has been opened by GenerateStream.
+IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_StopStreamDevice,
int /* render view id */,
- std::string /* label */)
+ std::string /*device_id*/)
+
+// Request to enumerate devices.
+IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_GetSources,
+ int /* request id */,
+ GURL /* origin */)
+
// Request to enumerate devices.
// Used by Pepper.
@@ -121,6 +130,11 @@ IPC_MESSAGE_CONTROL4(MediaStreamHostMsg_EnumerateDevices,
content::MediaStreamType /* type */,
GURL /* security origin */)
+// Request to stop enumerating devices.
+IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_CancelEnumerateDevices,
+ int /* render view id */,
+ int /* request id */)
+
// Request to open the device.
IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_OpenDevice,
int /* render view id */,
@@ -129,7 +143,7 @@ IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_OpenDevice,
content::MediaStreamType /* type */,
GURL /* security origin */)
-// Request to enumerate devices.
-IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_GetSources,
- int /* request id */,
- GURL /* origin */)
+// Request to close a device.
+IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_CloseDevice,
+ int /* render view id */,
+ std::string /*label*/)
diff --git a/chromium/content/common/media/media_stream_options.cc b/chromium/content/common/media/media_stream_options.cc
index 5efaf561761..4ddef015334 100644
--- a/chromium/content/common/media/media_stream_options.cc
+++ b/chromium/content/common/media/media_stream_options.cc
@@ -18,30 +18,91 @@ const char kMediaStreamSourceSystem[] = "system";
const char kMediaStreamRenderToAssociatedSink[] =
"chromeRenderToAssociatedSink";
+namespace {
+
+bool GetFirstConstraintByName(const StreamOptions::Constraints& constraints,
+ const std::string& name,
+ std::string* value) {
+ for (StreamOptions::Constraints::const_iterator it = constraints.begin();
+ it != constraints.end(); ++it ) {
+ if (it->name == name) {
+ *value = it->value;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool GetFirstConstraintByName(const StreamOptions::Constraints& mandatory,
+ const StreamOptions::Constraints& optional,
+ const std::string& name,
+ std::string* value,
+ bool* is_mandatory) {
+ if (GetFirstConstraintByName(mandatory, name, value)) {
+ if (is_mandatory)
+ *is_mandatory = true;
+ return true;
+ }
+ if (is_mandatory)
+ *is_mandatory = false;
+ return GetFirstConstraintByName(optional, name, value);
+}
+
+} // namespace
+
StreamOptions::StreamOptions()
- : audio_type(MEDIA_NO_SERVICE),
- video_type(MEDIA_NO_SERVICE) {}
-
-StreamOptions::StreamOptions(MediaStreamType audio_type,
- MediaStreamType video_type)
- : audio_type(audio_type), video_type(video_type) {
- DCHECK(IsAudioMediaType(audio_type) || audio_type == MEDIA_NO_SERVICE);
- DCHECK(IsVideoMediaType(video_type) || video_type == MEDIA_NO_SERVICE);
+ : audio_requested(false),
+ video_requested(false) {}
+
+StreamOptions::StreamOptions(bool request_audio, bool request_video)
+ : audio_requested(request_audio), video_requested(request_video) {
+}
+
+StreamOptions::~StreamOptions() {}
+
+StreamOptions::Constraint::Constraint() {}
+
+StreamOptions::Constraint::Constraint(const std::string& name,
+ const std::string& value)
+ : name(name), value(value) {
+}
+
+bool StreamOptions::GetFirstAudioConstraintByName(const std::string& name,
+ std::string* value,
+ bool* is_mandatory) const {
+ return GetFirstConstraintByName(mandatory_audio, optional_audio, name, value,
+ is_mandatory);
+}
+
+bool StreamOptions::GetFirstVideoConstraintByName(const std::string& name,
+ std::string* value,
+ bool* is_mandatory) const {
+ return GetFirstConstraintByName(mandatory_video, optional_video, name, value,
+ is_mandatory);
+}
+
+// static
+void StreamOptions::GetConstraintsByName(
+ const StreamOptions::Constraints& constraints,
+ const std::string& name,
+ std::vector<std::string>* values) {
+ for (StreamOptions::Constraints::const_iterator it = constraints.begin();
+ it != constraints.end(); ++it ) {
+ if (it->name == name)
+ values->push_back(it->value);
+ }
}
// static
const int StreamDeviceInfo::kNoId = -1;
StreamDeviceInfo::StreamDeviceInfo()
- : in_use(false),
- session_id(kNoId) {}
+ : session_id(kNoId) {}
StreamDeviceInfo::StreamDeviceInfo(MediaStreamType service_param,
const std::string& name_param,
- const std::string& device_param,
- bool opened)
+ const std::string& device_param)
: device(service_param, device_param, name_param),
- in_use(opened),
session_id(kNoId) {
}
@@ -50,27 +111,16 @@ StreamDeviceInfo::StreamDeviceInfo(MediaStreamType service_param,
const std::string& device_param,
int sample_rate,
int channel_layout,
- int frames_per_buffer,
- bool opened)
+ int frames_per_buffer)
: device(service_param, device_param, name_param, sample_rate,
channel_layout, frames_per_buffer),
- in_use(opened),
session_id(kNoId) {
}
// static
bool StreamDeviceInfo::IsEqual(const StreamDeviceInfo& first,
const StreamDeviceInfo& second) {
- const MediaStreamDevice::AudioDeviceParameters& input_first =
- first.device.input;
- const MediaStreamDevice::AudioDeviceParameters& input_second =
- second.device.input;
- return first.device.type == second.device.type &&
- first.device.name == second.device.name &&
- first.device.id == second.device.id &&
- input_first.sample_rate == input_second.sample_rate &&
- input_first.channel_layout == input_second.channel_layout &&
- first.in_use == second.in_use &&
+ return first.device.IsEqual(second.device) &&
first.session_id == second.session_id;
}
diff --git a/chromium/content/common/media/media_stream_options.h b/chromium/content/common/media/media_stream_options.h
index 96c9511ccc6..1b7401caaa1 100644
--- a/chromium/content/common/media/media_stream_options.h
+++ b/chromium/content/common/media/media_stream_options.h
@@ -28,20 +28,60 @@ CONTENT_EXPORT extern const char kMediaStreamSourceSystem[];
// device belongs to.
CONTENT_EXPORT extern const char kMediaStreamRenderToAssociatedSink[];
-// StreamOptions is a Chromium representation of WebKit's
-// WebUserMediaRequest Options. It describes the components
-// in a request for a new media stream.
-struct CONTENT_EXPORT StreamOptions {
+// StreamOptions is a Chromium representation of constraints
+// used in WebUserMediaRequest.
+// It describes properties requested by JS in a request for a new
+// media stream.
+class CONTENT_EXPORT StreamOptions {
+ public:
StreamOptions();
- StreamOptions(MediaStreamType audio_type, MediaStreamType video_type);
-
- // If not NO_SERVICE, the stream shall contain an audio input stream.
- MediaStreamType audio_type;
- std::string audio_device_id;
-
- // If not NO_SERVICE, the stream shall contain a video input stream.
- MediaStreamType video_type;
- std::string video_device_id;
+ StreamOptions(bool request_audio, bool request_video);
+ ~StreamOptions();
+
+ struct CONTENT_EXPORT Constraint {
+ Constraint();
+ Constraint(const std::string& name,
+ const std::string& value);
+
+ std::string name;
+ std::string value;
+ };
+ typedef std::vector<Constraint> Constraints;
+
+ bool audio_requested;
+ Constraints mandatory_audio;
+ Constraints optional_audio;
+
+ bool video_requested;
+ Constraints mandatory_video;
+ Constraints optional_video;
+
+ // Fetches |value| from the first audio constraint with a name that matches
+ // |name| from |mandatory_audio| and |optional_audio|. First mandatory
+ // constraints are searched, then optional.
+ // |is_mandatory| may be NULL but if it is provided, it is set
+ // to true if the found constraint is mandatory.
+ // Returns false if no constraint is found.
+ bool GetFirstAudioConstraintByName(const std::string& name,
+ std::string* value,
+ bool* is_mandatory) const;
+
+ // Fetches |value| from the first video constraint with a name that matches
+ // |name| from |mandatory_video| and |optional_video|. First mandatory
+ // constraints are searched, then optional.
+ // |is_mandatory| may be NULL but if it is provided, it is set
+ // to true if the found constraint is mandatory.
+ // Returns false if no constraint is found.
+ bool GetFirstVideoConstraintByName(const std::string& name,
+ std::string* value,
+ bool* is_mandatory) const;
+
+ // Fetches |values| from all constraint with a name that matches |name|
+ // from |constraints|.
+ static void GetConstraintsByName(
+ const StreamOptions::Constraints& constraints,
+ const std::string& name,
+ std::vector<std::string>* values);
};
// StreamDeviceInfo describes information about a device.
@@ -51,22 +91,18 @@ struct CONTENT_EXPORT StreamDeviceInfo {
StreamDeviceInfo();
StreamDeviceInfo(MediaStreamType service_param,
const std::string& name_param,
- const std::string& device_param,
- bool opened);
+ const std::string& device_param);
StreamDeviceInfo(MediaStreamType service_param,
const std::string& name_param,
const std::string& device_param,
int sample_rate,
int channel_layout,
- int frames_per_buffer,
- bool opened);
+ int frames_per_buffer);
static bool IsEqual(const StreamDeviceInfo& first,
const StreamDeviceInfo& second);
MediaStreamDevice device;
- // Set to true if the device has been opened, false otherwise.
- bool in_use;
// Id for this capture session. Unique for all sessions of the same type.
int session_id;
};
diff --git a/chromium/content/common/media/midi_messages.h b/chromium/content/common/media/midi_messages.h
index bff0241fe4f..eced85dbb79 100644
--- a/chromium/content/common/media/midi_messages.h
+++ b/chromium/content/common/media/midi_messages.h
@@ -30,6 +30,12 @@ IPC_MESSAGE_CONTROL3(MIDIHostMsg_RequestSysExPermission,
int /* client id */,
GURL /* origin */)
+// Renderer request to browser for canceling a previous permission request.
+IPC_MESSAGE_CONTROL3(MIDIHostMsg_CancelSysExPermissionRequest,
+ int /* render_view_id */,
+ int /* bridge_id */,
+ GURL /* GURL of the frame */)
+
// Messages sent from the browser to the renderer.
IPC_MESSAGE_ROUTED2(MIDIMsg_SysExPermissionApproved,
diff --git a/chromium/content/common/media/video_capture_messages.h b/chromium/content/common/media/video_capture_messages.h
index d1a0e24c300..55cbb38496d 100644
--- a/chromium/content/common/media/video_capture_messages.h
+++ b/chromium/content/common/media/video_capture_messages.h
@@ -15,6 +15,14 @@
IPC_ENUM_TRAITS(content::VideoCaptureState)
+IPC_STRUCT_TRAITS_BEGIN(media::VideoCaptureParams)
+ IPC_STRUCT_TRAITS_MEMBER(requested_format)
+ IPC_STRUCT_TRAITS_MEMBER(allow_resolution_change)
+IPC_STRUCT_TRAITS_END()
+
+// TODO(nick): device_id in these messages is basically just a route_id. We
+// should shift to IPC_MESSAGE_ROUTED and use MessageRouter in the filter impls.
+
// Notify the renderer process about the state update such as
// Start/Pause/Stop.
IPC_MESSAGE_CONTROL2(VideoCaptureMsg_StateChanged,
@@ -28,27 +36,25 @@ IPC_MESSAGE_CONTROL4(VideoCaptureMsg_NewBuffer,
int /* length */,
int /* buffer_id */)
+// Tell the renderer process that it should release a buffer previously
+// allocated by VideoCaptureMsg_NewBuffer.
+IPC_MESSAGE_CONTROL2(VideoCaptureMsg_FreeBuffer,
+ int /* device id */,
+ int /* buffer_id */)
+
// Tell the renderer process that a buffer is available from video capture.
-IPC_MESSAGE_CONTROL3(VideoCaptureMsg_BufferReady,
+IPC_MESSAGE_CONTROL4(VideoCaptureMsg_BufferReady,
int /* device id */,
int /* buffer_id */,
- base::Time /* timestamp */)
-
-// Tell the renderer process the width, height and frame rate the camera use.
-IPC_MESSAGE_CONTROL2(VideoCaptureMsg_DeviceInfo,
- int /* device_id */,
- media::VideoCaptureParams)
-
-// Tell the renderer process the newly changed width, height and frame rate
-// the video capture device will use.
-IPC_MESSAGE_CONTROL2(VideoCaptureMsg_DeviceInfoChanged,
- int /* device_id */,
- media::VideoCaptureParams)
+ base::Time /* timestamp */,
+ media::VideoCaptureFormat /* resolution */)
-// Start the video capture specified by |device_id|.
-IPC_MESSAGE_CONTROL2(VideoCaptureHostMsg_Start,
+// Start a video capture as |device_id|, a new id picked by the renderer
+// process. The session to be started is determined by |params.session_id|.
+IPC_MESSAGE_CONTROL3(VideoCaptureHostMsg_Start,
int /* device_id */,
- media::VideoCaptureParams)
+ media::VideoCaptureSessionId, /* session_id */
+ media::VideoCaptureParams /* params */)
// Pause the video capture specified by |device_id|.
IPC_MESSAGE_CONTROL1(VideoCaptureHostMsg_Pause,
@@ -58,8 +64,8 @@ IPC_MESSAGE_CONTROL1(VideoCaptureHostMsg_Pause,
IPC_MESSAGE_CONTROL1(VideoCaptureHostMsg_Stop,
int /* device_id */)
-// Tell the browser process that the video frame buffer |handle| is ready for
-// device |device_id| to fill up.
+// Tell the browser process that the renderer has finished reading from
+// a buffer previously delivered by VideoCaptureMsg_BufferReady.
IPC_MESSAGE_CONTROL2(VideoCaptureHostMsg_BufferReady,
int /* device_id */,
int /* buffer_id */)
diff --git a/chromium/content/common/message_port_messages.h b/chromium/content/common/message_port_messages.h
new file mode 100644
index 00000000000..4269ade839e
--- /dev/null
+++ b/chromium/content/common/message_port_messages.h
@@ -0,0 +1,85 @@
+// 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.
+
+// Defines messages between the browser and worker process, as well as between
+// the renderer and worker process.
+
+// Multiply-included message file, hence no include guard.
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_utils.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+#define IPC_MESSAGE_START MessagePortMsgStart
+
+// Singly-included section, not converted.
+#ifndef CONTENT_COMMON_MESSAGE_PORT_MESSAGES_H_
+#define CONTENT_COMMON_MESSAGE_PORT_MESSAGES_H_
+
+typedef std::pair<base::string16, std::vector<int> > QueuedMessage;
+
+#endif // CONTENT_COMMON_MESSAGE_PORT_MESSAGES_H_
+
+//-----------------------------------------------------------------------------
+// MessagePort messages
+// These are messages sent from the browser to child processes.
+
+// Sends a message to a message port.
+IPC_MESSAGE_ROUTED3(MessagePortMsg_Message,
+ base::string16 /* message */,
+ std::vector<int> /* sent_message_port_ids */,
+ std::vector<int> /* new_routing_ids */)
+
+// Tells the Message Port Channel object that there are no more in-flight
+// messages arriving.
+IPC_MESSAGE_ROUTED0(MessagePortMsg_MessagesQueued)
+
+//-----------------------------------------------------------------------------
+// MessagePortHost messages
+// These are messages sent from child processes to the browser.
+
+// Creates a new Message Port Channel object. The first paramaeter is the
+// message port channel's routing id in this process. The second parameter
+// is the process-wide-unique identifier for that port.
+IPC_SYNC_MESSAGE_CONTROL0_2(MessagePortHostMsg_CreateMessagePort,
+ int /* route_id */,
+ int /* message_port_id */)
+
+// Sent when a Message Port Channel object is destroyed.
+IPC_MESSAGE_CONTROL1(MessagePortHostMsg_DestroyMessagePort,
+ int /* message_port_id */)
+
+// Sends a message to a message port. Optionally sends a message port as
+// as well if sent_message_port_id != MSG_ROUTING_NONE.
+IPC_MESSAGE_CONTROL3(MessagePortHostMsg_PostMessage,
+ int /* sender_message_port_id */,
+ base::string16 /* message */,
+ std::vector<int> /* sent_message_port_ids */)
+
+// Causes messages sent to the remote port to be delivered to this local port.
+IPC_MESSAGE_CONTROL2(MessagePortHostMsg_Entangle,
+ int /* local_message_port_id */,
+ int /* remote_message_port_id */)
+
+// Causes the browser to queue messages sent to this port until the the port
+// has made sure that all in-flight messages were routed to the new
+// destination.
+IPC_MESSAGE_CONTROL1(MessagePortHostMsg_QueueMessages,
+ int /* message_port_id */)
+
+// Sends the browser all the queued messages that arrived at this message port
+// after it was sent in a postMessage call.
+// NOTE: MSVS can't compile the macro if std::vector<std::pair<string16, int> >
+// is used, so we typedef it in worker_messages.h.
+IPC_MESSAGE_CONTROL2(MessagePortHostMsg_SendQueuedMessages,
+ int /* message_port_id */,
+ std::vector<QueuedMessage> /* queued_messages */)
diff --git a/chromium/content/common/p2p_messages.h b/chromium/content/common/p2p_messages.h
index 6b13831ec96..7e9bf5ef04d 100644
--- a/chromium/content/common/p2p_messages.h
+++ b/chromium/content/common/p2p_messages.h
@@ -5,8 +5,9 @@
// IPC messages for the P2P Transport API.
// Multiply-included message file, hence no include guard.
+#include "base/time/time.h"
#include "content/common/content_export.h"
-#include "content/common/p2p_sockets.h"
+#include "content/public/common/p2p_socket_type.h"
#include "ipc/ipc_message_macros.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_util.h"
@@ -16,6 +17,7 @@
#define IPC_MESSAGE_START P2PMsgStart
IPC_ENUM_TRAITS(content::P2PSocketType)
+IPC_ENUM_TRAITS(net::DiffServCodePoint)
IPC_STRUCT_TRAITS_BEGIN(net::NetworkInterface)
IPC_STRUCT_TRAITS_MEMBER(name)
@@ -45,10 +47,11 @@ IPC_MESSAGE_CONTROL2(P2PMsg_OnIncomingTcpConnection,
int /* socket_id */,
net::IPEndPoint /* socket_address */)
-IPC_MESSAGE_CONTROL3(P2PMsg_OnDataReceived,
+IPC_MESSAGE_CONTROL4(P2PMsg_OnDataReceived,
int /* socket_id */,
net::IPEndPoint /* socket_address */,
- std::vector<char> /* data */)
+ std::vector<char> /* data */,
+ base::TimeTicks /* timestamp */ )
// P2P Socket messages sent from the renderer to the browser.
@@ -73,10 +76,12 @@ IPC_MESSAGE_CONTROL3(P2PHostMsg_AcceptIncomingTcpConnection,
int /* connected_socket_id */)
// TODO(sergeyu): Use shared memory to pass the data.
-IPC_MESSAGE_CONTROL3(P2PHostMsg_Send,
+IPC_MESSAGE_CONTROL5(P2PHostMsg_Send,
int /* socket_id */,
net::IPEndPoint /* socket_address */,
- std::vector<char> /* data */)
+ std::vector<char> /* data */,
+ net::DiffServCodePoint /* dscp */,
+ uint64 /* packet_id */)
IPC_MESSAGE_CONTROL1(P2PHostMsg_DestroySocket,
int /* socket_id */)
diff --git a/chromium/content/common/page_state_serialization.cc b/chromium/content/common/page_state_serialization.cc
index 3656c53a6a3..5384ab55a52 100644
--- a/chromium/content/common/page_state_serialization.cc
+++ b/chromium/content/common/page_state_serialization.cc
@@ -25,7 +25,7 @@ float g_device_scale_factor_for_testing = 0.0;
void AppendDataToHttpBody(ExplodedHttpBody* http_body, const char* data,
int data_length) {
ExplodedHttpBodyElement element;
- element.type = WebKit::WebHTTPBody::Element::TypeData;
+ element.type = blink::WebHTTPBody::Element::TypeData;
element.data.assign(data, data_length);
http_body->elements.push_back(element);
}
@@ -36,7 +36,7 @@ void AppendFileRangeToHttpBody(ExplodedHttpBody* http_body,
int file_length,
double file_modification_time) {
ExplodedHttpBodyElement element;
- element.type = WebKit::WebHTTPBody::Element::TypeFile;
+ element.type = blink::WebHTTPBody::Element::TypeFile;
element.file_path = file_path;
element.file_start = file_start;
element.file_length = file_length;
@@ -50,7 +50,7 @@ void AppendURLRangeToHttpBody(ExplodedHttpBody* http_body,
int file_length,
double file_modification_time) {
ExplodedHttpBodyElement element;
- element.type = WebKit::WebHTTPBody::Element::TypeFileSystemURL;
+ element.type = blink::WebHTTPBody::Element::TypeFileSystemURL;
element.filesystem_url = url;
element.file_start = file_start;
element.file_length = file_length;
@@ -58,11 +58,11 @@ void AppendURLRangeToHttpBody(ExplodedHttpBody* http_body,
http_body->elements.push_back(element);
}
-void DeprecatedAppendBlobToHttpBody(ExplodedHttpBody* http_body,
- const GURL& url) {
+void AppendBlobToHttpBody(ExplodedHttpBody* http_body,
+ const std::string& uuid) {
ExplodedHttpBodyElement element;
- element.type = WebKit::WebHTTPBody::Element::TypeBlob;
- element.deprecated_blob_url = url;
+ element.type = blink::WebHTTPBody::Element::TypeBlob;
+ element.blob_uuid = uuid;
http_body->elements.push_back(element);
}
@@ -72,7 +72,7 @@ void AppendReferencedFilesFromHttpBody(
const std::vector<ExplodedHttpBodyElement>& elements,
std::vector<base::NullableString16>* referenced_files) {
for (size_t i = 0; i < elements.size(); ++i) {
- if (elements[i].type == WebKit::WebHTTPBody::Element::TypeFile)
+ if (elements[i].type == blink::WebHTTPBody::Element::TypeFile)
referenced_files->push_back(elements[i].file_path);
}
}
@@ -185,12 +185,15 @@ struct SerializeObject {
// 12: Adds support for contains_passwords in HTTP body
// 13: Adds support for URL (FileSystem URL)
// 14: Adds list of referenced files, version written only for first item.
+// 15: Removes a bunch of values we defined but never used.
+// 16: Switched from blob urls to blob uuids.
+// 17: Add a target frame id number.
//
// NOTE: If the version is -1, then the pickle contains only a URL string.
// See ReadPageState.
//
const int kMinVersion = 11;
-const int kCurrentVersion = 14;
+const int kCurrentVersion = 17;
// A bunch of convenience functions to read/write to SerializeObjects. The
// de-serializers assume the input data will be in the correct format and fall
@@ -257,6 +260,10 @@ double ReadReal(SerializeObject* obj) {
return value;
}
+void ConsumeReal(SerializeObject* obj) {
+ double unused ALLOW_UNUSED = ReadReal(obj);
+}
+
void WriteBoolean(bool data, SerializeObject* obj) {
obj->pickle.WriteInt(data ? 1 : 0);
}
@@ -269,6 +276,10 @@ bool ReadBoolean(SerializeObject* obj) {
return false;
}
+void ConsumeBoolean(SerializeObject* obj) {
+ bool unused ALLOW_UNUSED = ReadBoolean(obj);
+}
+
void WriteGURL(const GURL& url, SerializeObject* obj) {
obj->pickle.WriteString(url.possibly_invalid_spec());
}
@@ -281,6 +292,18 @@ GURL ReadGURL(SerializeObject* obj) {
return GURL();
}
+void WriteStdString(const std::string& s, SerializeObject* obj) {
+ obj->pickle.WriteString(s);
+}
+
+std::string ReadStdString(SerializeObject* obj) {
+ std::string s;
+ if (obj->pickle.ReadString(&obj->iter, &s))
+ return s;
+ obj->parse_error = true;
+ return std::string();
+}
+
// WriteString pickles the NullableString16 as <int length><char16* data>.
// If length == -1, then the NullableString16 itself is null. Otherwise the
// length is the number of char16 (not bytes) in the NullableString16.
@@ -388,23 +411,23 @@ void WriteHttpBody(const ExplodedHttpBody& http_body, SerializeObject* 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 == WebKit::WebHTTPBody::Element::TypeData) {
+ if (element.type == blink::WebHTTPBody::Element::TypeData) {
WriteData(element.data.data(), static_cast<int>(element.data.size()),
obj);
- } else if (element.type == WebKit::WebHTTPBody::Element::TypeFile) {
+ } 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 ==
- WebKit::WebHTTPBody::Element::TypeFileSystemURL) {
+ 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 == WebKit::WebHTTPBody::Element::TypeBlob);
- WriteGURL(element.deprecated_blob_url, obj);
+ DCHECK(element.type == blink::WebHTTPBody::Element::TypeBlob);
+ WriteStdString(element.blob_uuid, obj);
}
}
WriteInteger64(http_body.identifier, obj);
@@ -421,7 +444,7 @@ void ReadHttpBody(SerializeObject* obj, ExplodedHttpBody* http_body) {
for (int i = 0; i < num_elements; ++i) {
int type = ReadInteger(obj);
- if (type == WebKit::WebHTTPBody::Element::TypeData) {
+ if (type == blink::WebHTTPBody::Element::TypeData) {
const void* data;
int length = -1;
ReadData(obj, &data, &length);
@@ -429,23 +452,27 @@ void ReadHttpBody(SerializeObject* obj, ExplodedHttpBody* http_body) {
AppendDataToHttpBody(http_body, static_cast<const char*>(data),
length);
}
- } else if (type == WebKit::WebHTTPBody::Element::TypeFile) {
+ } else if (type == blink::WebHTTPBody::Element::TypeFile) {
base::NullableString16 file_path = ReadString(obj);
int64 file_start = ReadInteger64(obj);
int64 file_length = ReadInteger64(obj);
double file_modification_time = ReadReal(obj);
AppendFileRangeToHttpBody(http_body, file_path, file_start, file_length,
file_modification_time);
- } else if (type == WebKit::WebHTTPBody::Element::TypeFileSystemURL) {
+ } else if (type == blink::WebHTTPBody::Element::TypeFileSystemURL) {
GURL url = ReadGURL(obj);
int64 file_start = ReadInteger64(obj);
int64 file_length = ReadInteger64(obj);
double file_modification_time = ReadReal(obj);
AppendURLRangeToHttpBody(http_body, url, file_start, file_length,
file_modification_time);
- } else if (type == WebKit::WebHTTPBody::Element::TypeBlob) {
- GURL blob_url = ReadGURL(obj);
- DeprecatedAppendBlobToHttpBody(http_body, blob_url);
+ } else if (type == blink::WebHTTPBody::Element::TypeBlob) {
+ if (obj->version >= 16) {
+ std::string blob_uuid = ReadStdString(obj);
+ AppendBlobToHttpBody(http_body, blob_uuid);
+ } else {
+ ReadGURL(obj); // Skip the obsolete blob url value.
+ }
}
}
http_body->identifier = ReadInteger64(obj);
@@ -467,14 +494,8 @@ void WriteFrameState(
WriteString(state.url_string, obj);
WriteString(state.original_url_string, obj);
WriteString(state.target, obj);
- WriteString(state.parent, obj);
- WriteString(state.title, obj);
- WriteString(state.alternate_title, obj);
- WriteReal(state.visited_time, obj);
WriteInteger(state.scroll_offset.x(), obj);
WriteInteger(state.scroll_offset.y(), obj);
- WriteBoolean(state.is_target_item, obj);
- WriteInteger(state.visit_count, obj);
WriteString(state.referrer, obj);
WriteStringVector(state.document_state, obj);
@@ -482,6 +503,7 @@ void WriteFrameState(
WriteReal(state.page_scale_factor, obj);
WriteInteger64(state.item_sequence_number, obj);
WriteInteger64(state.document_sequence_number, obj);
+ WriteInteger64(state.target_frame_id, obj);
bool has_state_object = !state.state_object.is_null();
WriteBoolean(has_state_object, obj);
@@ -510,17 +532,21 @@ void ReadFrameState(SerializeObject* obj, bool is_top,
state->url_string = ReadString(obj);
state->original_url_string = ReadString(obj);
state->target = ReadString(obj);
- state->parent = ReadString(obj);
- state->title = ReadString(obj);
- state->alternate_title = ReadString(obj);
- state->visited_time = ReadReal(obj);
+ if (obj->version < 15) {
+ ConsumeString(obj); // Skip obsolete parent field.
+ ConsumeString(obj); // Skip obsolete title field.
+ ConsumeString(obj); // Skip obsolete alternate title field.
+ ConsumeReal(obj); // Skip obsolete visited time field.
+ }
int x = ReadInteger(obj);
int y = ReadInteger(obj);
state->scroll_offset = gfx::Point(x, y);
- state->is_target_item = ReadBoolean(obj);
- state->visit_count = ReadInteger(obj);
+ if (obj->version < 15) {
+ ConsumeBoolean(obj); // Skip obsolete target item flag.
+ ConsumeInteger(obj); // Skip obsolete visit count field.
+ }
state->referrer = ReadString(obj);
ReadStringVector(obj, &state->document_state);
@@ -528,6 +554,8 @@ void ReadFrameState(SerializeObject* obj, bool is_top,
state->page_scale_factor = ReadReal(obj);
state->item_sequence_number = ReadInteger64(obj);
state->document_sequence_number = ReadInteger64(obj);
+ if (obj->version >= 17)
+ state->target_frame_id = ReadInteger64(obj);
bool has_state_object = ReadBoolean(obj);
if (has_state_object)
@@ -615,7 +643,7 @@ void ReadPageState(SerializeObject* obj, ExplodedPageState* state) {
} // namespace
ExplodedHttpBodyElement::ExplodedHttpBodyElement()
- : type(WebKit::WebHTTPBody::Element::TypeData),
+ : type(blink::WebHTTPBody::Element::TypeData),
file_start(0),
file_length(-1),
file_modification_time(std::numeric_limits<double>::quiet_NaN()) {
@@ -636,10 +664,8 @@ ExplodedHttpBody::~ExplodedHttpBody() {
ExplodedFrameState::ExplodedFrameState()
: item_sequence_number(0),
document_sequence_number(0),
- visit_count(0),
- visited_time(0.0),
- page_scale_factor(0.0),
- is_target_item(false) {
+ target_frame_id(0),
+ page_scale_factor(0.0) {
}
ExplodedFrameState::~ExplodedFrameState() {
diff --git a/chromium/content/common/page_state_serialization.h b/chromium/content/common/page_state_serialization.h
index 24291ef68fa..da64295fe1e 100644
--- a/chromium/content/common/page_state_serialization.h
+++ b/chromium/content/common/page_state_serialization.h
@@ -16,14 +16,14 @@
namespace content {
struct CONTENT_EXPORT ExplodedHttpBodyElement {
- WebKit::WebHTTPBody::Element::Type type;
+ blink::WebHTTPBody::Element::Type type;
std::string data;
base::NullableString16 file_path;
GURL filesystem_url;
int64 file_start;
int64 file_length;
double file_modification_time;
- GURL deprecated_blob_url;
+ std::string blob_uuid;
ExplodedHttpBodyElement();
~ExplodedHttpBodyElement();
@@ -45,18 +45,13 @@ struct CONTENT_EXPORT ExplodedFrameState {
base::NullableString16 original_url_string;
base::NullableString16 referrer;
base::NullableString16 target;
- base::NullableString16 parent;
- base::NullableString16 title;
- base::NullableString16 alternate_title;
base::NullableString16 state_object;
std::vector<base::NullableString16> document_state;
gfx::Point scroll_offset;
int64 item_sequence_number;
int64 document_sequence_number;
- int visit_count;
- double visited_time;
+ int64 target_frame_id;
double page_scale_factor;
- bool is_target_item;
ExplodedHttpBody http_body;
std::vector<ExplodedFrameState> children;
diff --git a/chromium/content/common/page_state_serialization_unittest.cc b/chromium/content/common/page_state_serialization_unittest.cc
index 07b9cf8181b..b7e5895bb5e 100644
--- a/chromium/content/common/page_state_serialization_unittest.cc
+++ b/chromium/content/common/page_state_serialization_unittest.cc
@@ -52,7 +52,7 @@ void ExpectEquality(const ExplodedHttpBodyElement& a,
EXPECT_EQ(a.file_length, b.file_length);
if (!(isnan(a.file_modification_time) && isnan(b.file_modification_time)))
EXPECT_DOUBLE_EQ(a.file_modification_time, b.file_modification_time);
- EXPECT_EQ(a.deprecated_blob_url, b.deprecated_blob_url);
+ EXPECT_EQ(a.blob_uuid, b.blob_uuid);
}
template <>
@@ -70,18 +70,13 @@ void ExpectEquality(const ExplodedFrameState& a, const ExplodedFrameState& b) {
EXPECT_EQ(a.original_url_string, b.original_url_string);
EXPECT_EQ(a.referrer, b.referrer);
EXPECT_EQ(a.target, b.target);
- EXPECT_EQ(a.parent, b.parent);
- EXPECT_EQ(a.title, b.title);
- EXPECT_EQ(a.alternate_title, b.alternate_title);
EXPECT_EQ(a.state_object, b.state_object);
ExpectEquality(a.document_state, b.document_state);
EXPECT_EQ(a.scroll_offset, b.scroll_offset);
EXPECT_EQ(a.item_sequence_number, b.item_sequence_number);
EXPECT_EQ(a.document_sequence_number, b.document_sequence_number);
- EXPECT_EQ(a.visit_count, b.visit_count);
- EXPECT_EQ(a.visited_time, b.visited_time);
+ EXPECT_EQ(a.target_frame_id, b.target_frame_id);
EXPECT_EQ(a.page_scale_factor, b.page_scale_factor);
- EXPECT_EQ(a.is_target_item, b.is_target_item);
ExpectEquality(a.http_body, b.http_body);
ExpectEquality(a.children, b.children);
}
@@ -101,9 +96,6 @@ class PageStateSerializationTest : public testing::Test {
frame_state->original_url_string = frame_state->url_string;
frame_state->referrer = NS16("https://www.google.com/search?q=dev.chromium.org");
frame_state->target = NS16("foo");
- frame_state->parent = NS16("bar");
- frame_state->title = NS16("The Chromium Projects");
- frame_state->alternate_title = NS16(NULL);
frame_state->state_object = NS16(NULL);
frame_state->document_state.push_back(NS16("1"));
frame_state->document_state.push_back(NS16("q"));
@@ -112,10 +104,8 @@ class PageStateSerializationTest : public testing::Test {
frame_state->scroll_offset = gfx::Point(0, 100);
frame_state->item_sequence_number = 1;
frame_state->document_sequence_number = 2;
- frame_state->visit_count = 10;
- frame_state->visited_time = 12345.0;
+ frame_state->target_frame_id = 3;
frame_state->page_scale_factor = 2.0;
- frame_state->is_target_item = true;
}
void PopulateHttpBody(ExplodedHttpBody* http_body,
@@ -126,12 +116,12 @@ class PageStateSerializationTest : public testing::Test {
http_body->http_content_type = NS16("text/foo");
ExplodedHttpBodyElement e1;
- e1.type = WebKit::WebHTTPBody::Element::TypeData;
+ e1.type = blink::WebHTTPBody::Element::TypeData;
e1.data = "foo";
http_body->elements.push_back(e1);
ExplodedHttpBodyElement e2;
- e2.type = WebKit::WebHTTPBody::Element::TypeFile;
+ e2.type = blink::WebHTTPBody::Element::TypeFile;
e2.file_path = NS16("file.txt");
e2.file_start = 100;
e2.file_length = 1024;
@@ -149,16 +139,11 @@ class PageStateSerializationTest : public testing::Test {
frame_state->referrer = NS16("http://google.com/");
if (!is_child)
frame_state->target = NS16("target");
- frame_state->parent = NS16("parent");
- frame_state->title = NS16("title");
- frame_state->alternate_title = NS16("alternateTitle");
frame_state->scroll_offset = gfx::Point(42, -42);
frame_state->item_sequence_number = 123;
frame_state->document_sequence_number = 456;
- frame_state->visit_count = 42*42;
- frame_state->visited_time = 13.37;
+ frame_state->target_frame_id = 0;
frame_state->page_scale_factor = 2.0f;
- frame_state->is_target_item = true;
frame_state->document_state.push_back(
NS16("\n\r?% WebKit serialized form state version 8 \n\r=&"));
@@ -176,17 +161,17 @@ class PageStateSerializationTest : public testing::Test {
frame_state->http_body.is_null = false;
ExplodedHttpBodyElement e1;
- e1.type = WebKit::WebHTTPBody::Element::TypeData;
+ e1.type = blink::WebHTTPBody::Element::TypeData;
e1.data = "first data block";
frame_state->http_body.elements.push_back(e1);
ExplodedHttpBodyElement e2;
- e2.type = WebKit::WebHTTPBody::Element::TypeFile;
+ e2.type = blink::WebHTTPBody::Element::TypeFile;
e2.file_path = NS16("file.txt");
frame_state->http_body.elements.push_back(e2);
ExplodedHttpBodyElement e3;
- e3.type = WebKit::WebHTTPBody::Element::TypeData;
+ e3.type = blink::WebHTTPBody::Element::TypeData;
e3.data = "data the second";
frame_state->http_body.elements.push_back(e3);
@@ -223,7 +208,7 @@ class PageStateSerializationTest : public testing::Test {
}
std::string trimmed_contents;
- EXPECT_TRUE(RemoveChars(file_contents, "\r\n", &trimmed_contents));
+ EXPECT_TRUE(base::RemoveChars(file_contents, "\r\n", &trimmed_contents));
std::string encoded;
EXPECT_TRUE(base::Base64Decode(trimmed_contents, &encoded));
@@ -367,7 +352,7 @@ TEST_F(PageStateSerializationTest, BadMessagesTest2) {
p.WriteInt(0);
// WebForm
p.WriteInt(1);
- p.WriteInt(WebKit::WebHTTPBody::Element::TypeData);
+ p.WriteInt(blink::WebHTTPBody::Element::TypeData);
std::string s(static_cast<const char*>(p.data()), p.size());
@@ -388,13 +373,13 @@ TEST_F(PageStateSerializationTest, DumpExpectedPageStateForBackwardsCompat) {
EXPECT_TRUE(EncodePageState(state, &encoded));
std::string base64;
- EXPECT_TRUE(base::Base64Encode(encoded, &base64));
+ base::Base64Encode(encoded, &base64);
base::FilePath path;
PathService::Get(base::DIR_TEMP, &path);
path = path.AppendASCII("expected.dat");
- FILE* fp = file_util::OpenFile(path, "wb");
+ FILE* fp = base::OpenFile(path, "wb");
ASSERT_TRUE(fp);
const size_t kRowSize = 76;
@@ -402,7 +387,7 @@ TEST_F(PageStateSerializationTest, DumpExpectedPageStateForBackwardsCompat) {
size_t length = std::min(base64.size() - offset, kRowSize);
std::string segment(&base64[offset], length);
segment.push_back('\n');
- fwrite(segment.data(), segment.size(), 1, fp);
+ ASSERT_EQ(1U, fwrite(segment.data(), segment.size(), 1, fp));
}
fclose(fp);
@@ -428,5 +413,13 @@ TEST_F(PageStateSerializationTest, BackwardsCompat_v14) {
TestBackwardsCompat(14);
}
+TEST_F(PageStateSerializationTest, BackwardsCompat_v15) {
+ TestBackwardsCompat(15);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_v16) {
+ TestBackwardsCompat(16);
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/common/pepper_plugin_list.cc b/chromium/content/common/pepper_plugin_list.cc
index a398ad21d98..ec5f6ae0795 100644
--- a/chromium/content/common/pepper_plugin_list.cc
+++ b/chromium/content/common/pepper_plugin_list.cc
@@ -4,7 +4,9 @@
#include "content/common/pepper_plugin_list.h"
+#include "base/basictypes.h"
#include "base/command_line.h"
+#include "base/file_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -16,8 +18,23 @@
namespace content {
namespace {
+// The maximum number of plugins allowed to be registered from command line.
+const size_t kMaxPluginsToRegisterFromCommandLine = 64;
+
// Appends any plugins from the command line to the given vector.
void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) {
+ // On Linux, once we're sandboxed, we can't know if a plugin is available or
+ // not. But (on Linux) this function is always called once before we're
+ // sandboxed. So when this function is called for the first time we set a
+ // flag if the plugin file is available. Then we can skip the check on file
+ // existence in subsequent calls if the flag is set.
+ // NOTE: In theory we could have unlimited number of plugins registered in
+ // command line. But in practice, 64 plugins should be more than enough.
+ static uint64 skip_file_check_flags = 0;
+ COMPILE_ASSERT(
+ kMaxPluginsToRegisterFromCommandLine <= sizeof(skip_file_check_flags) * 8,
+ max_plugins_to_register_from_command_line_exceeds_limit);
+
bool out_of_process = true;
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiInProcess))
out_of_process = false;
@@ -36,11 +53,20 @@ void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) {
// *1( LWS + ";" + LWS + <mime-type> )
std::vector<std::string> modules;
base::SplitString(value, ',', &modules);
- for (size_t i = 0; i < modules.size(); ++i) {
+
+ size_t plugins_to_register = modules.size();
+ if (plugins_to_register > kMaxPluginsToRegisterFromCommandLine) {
+ VLOG(1) << plugins_to_register << " pepper plugins registered from"
+ << " command line which exceeds the limit (maximum "
+ << kMaxPluginsToRegisterFromCommandLine << " plugins allowed)";
+ plugins_to_register = kMaxPluginsToRegisterFromCommandLine;
+ }
+
+ for (size_t i = 0; i < plugins_to_register; ++i) {
std::vector<std::string> parts;
base::SplitString(modules[i], ';', &parts);
if (parts.size() < 2) {
- DLOG(ERROR) << "Required mime-type not found";
+ VLOG(1) << "Required mime-type not found";
continue;
}
@@ -57,6 +83,17 @@ void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) {
#else
plugin.path = base::FilePath(name_parts[0]);
#endif
+
+ uint64 index_mask = 1ULL << i;
+ if (!(skip_file_check_flags & index_mask)) {
+ if (base::PathExists(plugin.path)) {
+ skip_file_check_flags |= index_mask;
+ } else {
+ VLOG(1) << "Plugin doesn't exist: " << plugin.path.MaybeAsASCII();
+ continue;
+ }
+ }
+
if (name_parts.size() > 1)
plugin.name = name_parts[1];
if (name_parts.size() > 2)
diff --git a/chromium/content/common/plugin_constants_win.cc b/chromium/content/common/plugin_constants_win.cc
index ea7f5fb9d5b..e87a50ecdbe 100644
--- a/chromium/content/common/plugin_constants_win.cc
+++ b/chromium/content/common/plugin_constants_win.cc
@@ -25,5 +25,6 @@ const char16 kSilverlightPlugin[] = L"npctrl.dll";
const char16 kJavaPlugin1[] = L"npjp2.dll";
const char16 kJavaPlugin2[] = L"npdeploytk.dll";
const char kGPUPluginMimeType[] = "application/vnd.google.chrome.gpu-plugin";
+const char16 kPluginDummyParentProperty[] = L"NPAPIPluginDummyParent";
} // namespace content
diff --git a/chromium/content/common/plugin_constants_win.h b/chromium/content/common/plugin_constants_win.h
index c150b639ebb..7d8d2244710 100644
--- a/chromium/content/common/plugin_constants_win.h
+++ b/chromium/content/common/plugin_constants_win.h
@@ -46,6 +46,8 @@ extern const char16 kJavaPlugin2[];
extern const char kGPUPluginMimeType[];
+extern const char16 kPluginDummyParentProperty[];
+
} // namespace content
#endif // CONTENT_COMMON_PLUGIN_CONSTANTS_WIN_H_
diff --git a/chromium/content/common/plugin_list_posix.cc b/chromium/content/common/plugin_list_posix.cc
index 7c04485ce9a..0e822767c02 100644
--- a/chromium/content/common/plugin_list_posix.cc
+++ b/chromium/content/common/plugin_list_posix.cc
@@ -108,7 +108,7 @@ bool IsBlacklistedBySha1sumAndQuirks(const base::FilePath& path) {
};
int64 size;
- if (!file_util::GetFileSize(path, &size))
+ if (!base::GetFileSize(path, &size))
return false;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(bad_entries); i++) {
if (bad_entries[i].size != size)
@@ -174,14 +174,14 @@ bool ELFMatchesCurrentArchitecture(const base::FilePath& filename) {
if (fd < 0)
return false;
bool ret = (fstat(fd, &stat_buf) >= 0 && S_ISREG(stat_buf.st_mode));
- if (HANDLE_EINTR(close(fd)) < 0)
+ if (IGNORE_EINTR(close(fd)) < 0)
return false;
if (!ret)
return false;
const size_t kELFBufferSize = 5;
char buffer[kELFBufferSize];
- if (!file_util::ReadFile(filename, buffer, kELFBufferSize))
+ if (!base::ReadFile(filename, buffer, kELFBufferSize))
return false;
if (buffer[0] != ELFMAG0 ||
@@ -465,7 +465,7 @@ void PluginList::GetPluginDirectories(std::vector<base::FilePath>* plugin_dirs)
// 2) NS_USER_PLUGINS_DIR: ~/.mozilla/plugins.
// This is a de-facto standard, so even though we're not Mozilla, let's
// look in there too.
- base::FilePath home = file_util::GetHomeDir();
+ base::FilePath home = base::GetHomeDir();
if (!home.empty())
plugin_dirs->push_back(home.Append(".mozilla/plugins"));
@@ -546,7 +546,7 @@ void PluginList::GetPluginsInDir(
// Get mtime.
base::PlatformFileInfo info;
- if (!file_util::GetFileInfo(path, &info))
+ if (!base::GetFileInfo(path, &info))
continue;
files.push_back(std::make_pair(path, info.last_modified));
diff --git a/chromium/content/common/plugin_list_win.cc b/chromium/content/common/plugin_list_win.cc
index aa2e4e95f20..7d9706ba39f 100644
--- a/chromium/content/common/plugin_list_win.cc
+++ b/chromium/content/common/plugin_list_win.cc
@@ -372,19 +372,28 @@ void PluginList::GetPluginPathsFromRegistry(
bool PluginList::ShouldLoadPluginUsingPluginList(
const WebPluginInfo& info,
std::vector<WebPluginInfo>* plugins) {
- // Version check
- for (size_t j = 0; j < plugins->size(); ++j) {
- base::FilePath::StringType plugin1 =
- StringToLowerASCII((*plugins)[j].path.BaseName().value());
- base::FilePath::StringType plugin2 =
- StringToLowerASCII(info.path.BaseName().value());
- if ((plugin1 == plugin2 && HaveSharedMimeType((*plugins)[j], info)) ||
- (plugin1 == kJavaDeploy1 && plugin2 == kJavaDeploy2) ||
- (plugin1 == kJavaDeploy2 && plugin2 == kJavaDeploy1)) {
- if (IsNewerVersion(info.version, (*plugins)[j].version))
- return false; // We have loaded a plugin whose version is newer.
- plugins->erase(plugins->begin() + j);
- break;
+ bool should_check_version = true;
+ {
+ base::AutoLock lock(lock_);
+ should_check_version =
+ std::find(extra_plugin_paths_.begin(), extra_plugin_paths_.end(),
+ info.path) == extra_plugin_paths_.end();
+ }
+ // Version check for plugins that are not coming from |extra_plugin_paths_|.
+ if (should_check_version) {
+ for (size_t j = 0; j < plugins->size(); ++j) {
+ base::FilePath::StringType plugin1 =
+ StringToLowerASCII((*plugins)[j].path.BaseName().value());
+ base::FilePath::StringType plugin2 =
+ StringToLowerASCII(info.path.BaseName().value());
+ if ((plugin1 == plugin2 && HaveSharedMimeType((*plugins)[j], info)) ||
+ (plugin1 == kJavaDeploy1 && plugin2 == kJavaDeploy2) ||
+ (plugin1 == kJavaDeploy2 && plugin2 == kJavaDeploy1)) {
+ if (IsNewerVersion(info.version, (*plugins)[j].version))
+ return false; // We have loaded a plugin whose version is newer.
+ plugins->erase(plugins->begin() + j);
+ break;
+ }
}
}
@@ -392,10 +401,13 @@ bool PluginList::ShouldLoadPluginUsingPluginList(
if (info.type != WebPluginInfo::PLUGIN_TYPE_NPAPI)
return true;
- // If the plugin is in our internal list we should load it.
- for (size_t i = 0; i < internal_plugins_.size(); ++i) {
- if (info.path == internal_plugins_[i].path)
- return true;
+ {
+ base::AutoLock lock(lock_);
+ // If the plugin is in our internal list we should load it.
+ for (size_t i = 0; i < internal_plugins_.size(); ++i) {
+ if (info.path == internal_plugins_[i].path)
+ return true;
+ }
}
// Troublemakers.
diff --git a/chromium/content/common/resource_messages.cc b/chromium/content/common/resource_messages.cc
index 72127b9ca38..87f9e9ffbc2 100644
--- a/chromium/content/common/resource_messages.cc
+++ b/chromium/content/common/resource_messages.cc
@@ -59,7 +59,6 @@ void ParamTraits<webkit_common::DataElement>::Write(
default: {
DCHECK(p.type() == webkit_common::DataElement::TYPE_BLOB);
WriteParam(m, p.blob_uuid());
- WriteParam(m, p.blob_url());
WriteParam(m, p.offset());
WriteParam(m, p.length());
break;
@@ -116,20 +115,14 @@ bool ParamTraits<webkit_common::DataElement>::Read(
default: {
DCHECK(type == webkit_common::DataElement::TYPE_BLOB);
std::string blob_uuid;
- GURL blob_url;
uint64 offset, length;
if (!ReadParam(m, iter, &blob_uuid))
return false;
- if (!ReadParam(m, iter, &blob_url))
- return false;
if (!ReadParam(m, iter, &offset))
return false;
if (!ReadParam(m, iter, &length))
return false;
- if (!blob_uuid.empty())
- r->SetToBlobRange(blob_uuid, offset, length);
- else
- r->SetToBlobUrlRange(blob_url, offset, length);
+ r->SetToBlobRange(blob_uuid, offset, length);
break;
}
}
diff --git a/chromium/content/common/resource_messages.h b/chromium/content/common/resource_messages.h
index 082be1aa9ef..0ee74eb5e09 100644
--- a/chromium/content/common/resource_messages.h
+++ b/chromium/content/common/resource_messages.h
@@ -138,7 +138,7 @@ IPC_STRUCT_BEGIN(ResourceHostMsg_Request)
IPC_STRUCT_MEMBER(GURL, referrer)
// The referrer policy to use.
- IPC_STRUCT_MEMBER(WebKit::WebReferrerPolicy, referrer_policy)
+ IPC_STRUCT_MEMBER(blink::WebReferrerPolicy, referrer_policy)
// Additional HTTP request headers.
IPC_STRUCT_MEMBER(std::string, headers)
@@ -176,6 +176,9 @@ IPC_STRUCT_BEGIN(ResourceHostMsg_Request)
// True if the request was user initiated.
IPC_STRUCT_MEMBER(bool, has_user_gesture)
+ // The routing id of the RenderFrame.
+ IPC_STRUCT_MEMBER(int, render_frame_id)
+
// True if |frame_id| is the main frame of a RenderView.
IPC_STRUCT_MEMBER(bool, is_main_frame)
@@ -192,6 +195,10 @@ IPC_STRUCT_BEGIN(ResourceHostMsg_Request)
IPC_STRUCT_MEMBER(content::PageTransition, transition_type)
+ // For navigations, whether this navigation should replace the current session
+ // history entry on commit.
+ IPC_STRUCT_MEMBER(bool, should_replace_current_entry)
+
// The following two members identify a previous request that has been
// created before this navigation has been transferred to a new render view.
// This serves the purpose of recycling the old request.
diff --git a/chromium/content/common/sandbox_init_linux.cc b/chromium/content/common/sandbox_init_linux.cc
deleted file mode 100644
index 8674fc824d2..00000000000
--- a/chromium/content/common/sandbox_init_linux.cc
+++ /dev/null
@@ -1,20 +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/public/common/sandbox_init.h"
-
-#include "base/callback.h"
-#include "content/common/sandbox_seccomp_bpf_linux.h"
-
-namespace content {
-
-bool InitializeSandbox(playground2::BpfSandboxPolicy policy) {
- return SandboxSeccompBpf::StartSandboxWithExternalPolicy(policy);
-}
-
-playground2::BpfSandboxPolicyCallback GetBpfSandboxBaselinePolicy() {
- return SandboxSeccompBpf::GetBaselinePolicy();
-}
-
-} // namespace content
diff --git a/chromium/content/common/sandbox_linux/OWNERS b/chromium/content/common/sandbox_linux/OWNERS
new file mode 100644
index 00000000000..35643d1565f
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/OWNERS
@@ -0,0 +1,3 @@
+cevans@chromium.org
+jln@chromium.org
+jorgelo@chromium.org
diff --git a/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc b/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc
new file mode 100644
index 00000000000..4afb2a06927
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc
@@ -0,0 +1,227 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "build/build_config.h"
+#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
+#include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/services/linux_syscalls.h"
+
+using sandbox::ErrorCode;
+using sandbox::SandboxBPF;
+using sandbox::SyscallSets;
+
+namespace content {
+
+namespace {
+
+inline bool IsChromeOS() {
+#if defined(OS_CHROMEOS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+inline bool IsArchitectureArm() {
+#if defined(__arm__)
+ return true;
+#else
+ return false;
+#endif
+}
+
+void AddArmMaliGpuWhitelist(std::vector<std::string>* read_whitelist,
+ std::vector<std::string>* write_whitelist) {
+ // Device file needed by the ARM GPU userspace.
+ static const char kMali0Path[] = "/dev/mali0";
+
+ // Devices needed for video decode acceleration on ARM.
+ static const char kDevMfcDecPath[] = "/dev/mfc-dec";
+ static const char kDevGsc1Path[] = "/dev/gsc1";
+
+ // Devices needed for video encode acceleration on ARM.
+ static const char kDevMfcEncPath[] = "/dev/mfc-enc";
+
+ read_whitelist->push_back(kMali0Path);
+ read_whitelist->push_back(kDevMfcDecPath);
+ read_whitelist->push_back(kDevGsc1Path);
+ read_whitelist->push_back(kDevMfcEncPath);
+
+ write_whitelist->push_back(kMali0Path);
+ write_whitelist->push_back(kDevMfcDecPath);
+ write_whitelist->push_back(kDevGsc1Path);
+ write_whitelist->push_back(kDevMfcEncPath);
+}
+
+void AddArmTegraGpuWhitelist(std::vector<std::string>* read_whitelist,
+ std::vector<std::string>* write_whitelist) {
+ // Device files needed by the Tegra GPU userspace.
+ static const char kDevNvhostCtrlPath[] = "/dev/nvhost-ctrl";
+ static const char kDevNvhostGr2dPath[] = "/dev/nvhost-gr2d";
+ static const char kDevNvhostGr3dPath[] = "/dev/nvhost-gr3d";
+ static const char kDevNvhostIspPath[] = "/dev/nvhost-isp";
+ static const char kDevNvhostViPath[] = "/dev/nvhost-vi";
+ static const char kDevNvmapPath[] = "/dev/nvmap";
+ static const char kDevTegraSemaPath[] = "/dev/tegra_sema";
+
+ read_whitelist->push_back(kDevNvhostCtrlPath);
+ read_whitelist->push_back(kDevNvhostGr2dPath);
+ read_whitelist->push_back(kDevNvhostGr3dPath);
+ read_whitelist->push_back(kDevNvhostIspPath);
+ read_whitelist->push_back(kDevNvhostViPath);
+ read_whitelist->push_back(kDevNvmapPath);
+ read_whitelist->push_back(kDevTegraSemaPath);
+
+ write_whitelist->push_back(kDevNvhostCtrlPath);
+ write_whitelist->push_back(kDevNvhostGr2dPath);
+ write_whitelist->push_back(kDevNvhostGr3dPath);
+ write_whitelist->push_back(kDevNvhostIspPath);
+ write_whitelist->push_back(kDevNvhostViPath);
+ write_whitelist->push_back(kDevNvmapPath);
+ write_whitelist->push_back(kDevTegraSemaPath);
+}
+
+void AddArmGpuWhitelist(std::vector<std::string>* read_whitelist,
+ std::vector<std::string>* write_whitelist) {
+ // On ARM we're enabling the sandbox before the X connection is made,
+ // so we need to allow access to |.Xauthority|.
+ static const char kXAuthorityPath[] = "/home/chronos/.Xauthority";
+ static const char kLdSoCache[] = "/etc/ld.so.cache";
+
+ // Files needed by the ARM GPU userspace.
+ static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2";
+ static const char kLibEglPath[] = "/usr/lib/libEGL.so.1";
+
+ read_whitelist->push_back(kXAuthorityPath);
+ read_whitelist->push_back(kLdSoCache);
+ read_whitelist->push_back(kLibGlesPath);
+ read_whitelist->push_back(kLibEglPath);
+
+ AddArmMaliGpuWhitelist(read_whitelist, write_whitelist);
+ AddArmTegraGpuWhitelist(read_whitelist, write_whitelist);
+}
+
+class CrosArmGpuBrokerProcessPolicy : public CrosArmGpuProcessPolicy {
+ public:
+ CrosArmGpuBrokerProcessPolicy() : CrosArmGpuProcessPolicy(false) {}
+ virtual ~CrosArmGpuBrokerProcessPolicy() {}
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CrosArmGpuBrokerProcessPolicy);
+};
+
+// A GPU broker policy is the same as a GPU policy with open and
+// openat allowed.
+ErrorCode CrosArmGpuBrokerProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
+ int sysno) const {
+ switch (sysno) {
+ case __NR_access:
+ case __NR_open:
+ case __NR_openat:
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ default:
+ return CrosArmGpuProcessPolicy::EvaluateSyscall(sandbox, sysno);
+ }
+}
+
+bool EnableArmGpuBrokerPolicyCallback() {
+ return SandboxSeccompBPF::StartSandboxWithExternalPolicy(
+ scoped_ptr<sandbox::SandboxBPFPolicy>(new CrosArmGpuBrokerProcessPolicy));
+}
+
+} // namespace
+
+CrosArmGpuProcessPolicy::CrosArmGpuProcessPolicy(bool allow_shmat)
+ : allow_shmat_(allow_shmat) {}
+
+CrosArmGpuProcessPolicy::~CrosArmGpuProcessPolicy() {}
+
+ErrorCode CrosArmGpuProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
+ int sysno) const {
+#if defined(__arm__)
+ if (allow_shmat_ && sysno == __NR_shmat)
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+#endif // defined(__arm__)
+
+ switch (sysno) {
+#if defined(__arm__)
+ // ARM GPU sandbox is started earlier so we need to allow networking
+ // in the sandbox.
+ case __NR_connect:
+ case __NR_getpeername:
+ case __NR_getsockname:
+ case __NR_sysinfo:
+ case __NR_uname:
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ // Allow only AF_UNIX for |domain|.
+ case __NR_socket:
+ case __NR_socketpair:
+ return sandbox->Cond(0, ErrorCode::TP_32BIT,
+ ErrorCode::OP_EQUAL, AF_UNIX,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ ErrorCode(EPERM));
+#endif // defined(__arm__)
+ default:
+ if (SyscallSets::IsAdvancedScheduler(sysno))
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+
+ // Default to the generic GPU policy.
+ return GpuProcessPolicy::EvaluateSyscall(sandbox, sysno);
+ }
+}
+
+bool CrosArmGpuProcessPolicy::PreSandboxHook() {
+ DCHECK(IsChromeOS() && IsArchitectureArm());
+ // Create a new broker process.
+ DCHECK(!broker_process());
+
+ std::vector<std::string> read_whitelist_extra;
+ std::vector<std::string> write_whitelist_extra;
+ // Add ARM-specific files to whitelist in the broker.
+
+ AddArmGpuWhitelist(&read_whitelist_extra, &write_whitelist_extra);
+ InitGpuBrokerProcess(EnableArmGpuBrokerPolicyCallback,
+ read_whitelist_extra,
+ write_whitelist_extra);
+
+ const int dlopen_flag = RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE;
+
+ // Preload the Mali library.
+ dlopen("/usr/lib/libmali.so", dlopen_flag);
+
+ // Preload the Tegra libraries.
+ dlopen("/usr/lib/libnvrm.so", dlopen_flag);
+ dlopen("/usr/lib/libnvrm_graphics.so", dlopen_flag);
+ dlopen("/usr/lib/libnvos.so", dlopen_flag);
+ dlopen("/usr/lib/libnvddk_2d.so", dlopen_flag);
+ dlopen("/usr/lib/libardrv_dynamic.so", dlopen_flag);
+ dlopen("/usr/lib/libnvwsi.so", dlopen_flag);
+ dlopen("/usr/lib/libnvglsi.so", dlopen_flag);
+ dlopen("/usr/lib/libcgdrv.so", dlopen_flag);
+
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h b/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h
new file mode 100644
index 00000000000..0ccc93ce270
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h
@@ -0,0 +1,29 @@
+// 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_COMMON_SANDBOX_LINUX_BPF_CROS_ARM_GPU_POLICY_LINUX_H_
+#define CONTENT_COMMON_SANDBOX_LINUX_BPF_CROS_ARM_GPU_POLICY_LINUX_H_
+
+#include "content/common/sandbox_linux/bpf_gpu_policy_linux.h"
+
+namespace content {
+
+// This policy is for Chrome OS ARM.
+class CrosArmGpuProcessPolicy : public GpuProcessPolicy {
+ public:
+ explicit CrosArmGpuProcessPolicy(bool allow_shmat);
+ virtual ~CrosArmGpuProcessPolicy();
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE;
+ virtual bool PreSandboxHook() OVERRIDE;
+
+ private:
+ const bool allow_shmat_; // Allow shmat(2).
+ DISALLOW_COPY_AND_ASSIGN(CrosArmGpuProcessPolicy);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_SANDBOX_LINUX_BPF_CROS_ARM_GPU_POLICY_LINUX_H_
diff --git a/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.cc b/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
new file mode 100644
index 00000000000..2bdec2b0c67
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
@@ -0,0 +1,248 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/sandbox_linux/bpf_gpu_policy_linux.h"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "build/build_config.h"
+#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
+#include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
+#include "content/public/common/content_switches.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/services/broker_process.h"
+#include "sandbox/linux/services/linux_syscalls.h"
+
+using sandbox::BrokerProcess;
+using sandbox::ErrorCode;
+using sandbox::SandboxBPF;
+using sandbox::SyscallSets;
+using sandbox::arch_seccomp_data;
+
+namespace content {
+
+namespace {
+
+inline bool IsChromeOS() {
+#if defined(OS_CHROMEOS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+inline bool IsArchitectureX86_64() {
+#if defined(__x86_64__)
+ return true;
+#else
+ return false;
+#endif
+}
+
+inline bool IsArchitectureI386() {
+#if defined(__i386__)
+ return true;
+#else
+ return false;
+#endif
+}
+
+inline bool IsArchitectureArm() {
+#if defined(__arm__)
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool IsAcceleratedVideoDecodeEnabled() {
+ // Accelerated video decode is currently enabled on Chrome OS,
+ // but not on Linux: crbug.com/137247.
+ bool is_enabled = IsChromeOS();
+
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ is_enabled &=
+ !command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode);
+
+ return is_enabled;
+}
+
+intptr_t GpuSIGSYS_Handler(const struct arch_seccomp_data& args,
+ void* aux_broker_process) {
+ RAW_CHECK(aux_broker_process);
+ BrokerProcess* broker_process =
+ static_cast<BrokerProcess*>(aux_broker_process);
+ switch (args.nr) {
+ case __NR_access:
+ return broker_process->Access(reinterpret_cast<const char*>(args.args[0]),
+ static_cast<int>(args.args[1]));
+ case __NR_open:
+ return broker_process->Open(reinterpret_cast<const char*>(args.args[0]),
+ static_cast<int>(args.args[1]));
+ case __NR_openat:
+ // Allow using openat() as open().
+ if (static_cast<int>(args.args[0]) == AT_FDCWD) {
+ return
+ broker_process->Open(reinterpret_cast<const char*>(args.args[1]),
+ static_cast<int>(args.args[2]));
+ } else {
+ return -EPERM;
+ }
+ default:
+ RAW_CHECK(false);
+ return -ENOSYS;
+ }
+}
+
+class GpuBrokerProcessPolicy : public GpuProcessPolicy {
+ public:
+ GpuBrokerProcessPolicy() {}
+ virtual ~GpuBrokerProcessPolicy() {}
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GpuBrokerProcessPolicy);
+};
+
+// x86_64/i386 or desktop ARM.
+// A GPU broker policy is the same as a GPU policy with open and
+// openat allowed.
+ErrorCode GpuBrokerProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
+ int sysno) const {
+ switch (sysno) {
+ case __NR_access:
+ case __NR_open:
+ case __NR_openat:
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ default:
+ return GpuProcessPolicy::EvaluateSyscall(sandbox, sysno);
+ }
+}
+
+bool EnableGpuBrokerPolicyCallback() {
+ return SandboxSeccompBPF::StartSandboxWithExternalPolicy(
+ scoped_ptr<sandbox::SandboxBPFPolicy>(new GpuBrokerProcessPolicy));
+}
+
+} // namespace
+
+GpuProcessPolicy::GpuProcessPolicy() : broker_process_(NULL) {}
+
+GpuProcessPolicy::~GpuProcessPolicy() {}
+
+// Main policy for x86_64/i386. Extended by CrosArmGpuProcessPolicy.
+ErrorCode GpuProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
+ int sysno) const {
+ switch (sysno) {
+ case __NR_ioctl:
+#if defined(__i386__) || defined(__x86_64__)
+ // The Nvidia driver uses flags not in the baseline policy
+ // (MAP_LOCKED | MAP_EXECUTABLE | MAP_32BIT)
+ case __NR_mmap:
+#endif
+ // We also hit this on the linux_chromeos bot but don't yet know what
+ // weird flags were involved.
+ case __NR_mprotect:
+ case __NR_sched_getaffinity:
+ case __NR_sched_setaffinity:
+ case __NR_setpriority:
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ case __NR_access:
+ case __NR_open:
+ case __NR_openat:
+ DCHECK(broker_process_);
+ return sandbox->Trap(GpuSIGSYS_Handler, broker_process_);
+ default:
+ if (SyscallSets::IsEventFd(sysno))
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+
+ // Default on the baseline policy.
+ return SandboxBPFBasePolicy::EvaluateSyscall(sandbox, sysno);
+ }
+}
+
+bool GpuProcessPolicy::PreSandboxHook() {
+ // Warm up resources needed by the policy we're about to enable and
+ // eventually start a broker process.
+ const bool chromeos_arm_gpu = IsChromeOS() && IsArchitectureArm();
+ // This policy is for x86 or Desktop.
+ DCHECK(!chromeos_arm_gpu);
+
+ DCHECK(!broker_process());
+ // Create a new broker process.
+ InitGpuBrokerProcess(
+ EnableGpuBrokerPolicyCallback,
+ std::vector<std::string>(), // No extra files in whitelist.
+ std::vector<std::string>());
+
+ if (IsArchitectureX86_64() || IsArchitectureI386()) {
+ // Accelerated video decode dlopen()'s some shared objects
+ // inside the sandbox, so preload them now.
+ if (IsAcceleratedVideoDecodeEnabled()) {
+ const char* I965DrvVideoPath = NULL;
+
+ if (IsArchitectureX86_64()) {
+ I965DrvVideoPath = "/usr/lib64/va/drivers/i965_drv_video.so";
+ } else if (IsArchitectureI386()) {
+ I965DrvVideoPath = "/usr/lib/va/drivers/i965_drv_video.so";
+ }
+
+ dlopen(I965DrvVideoPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
+ dlopen("libva.so.1", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
+ dlopen("libva-x11.so.1", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
+ }
+ }
+
+ return true;
+}
+
+void GpuProcessPolicy::InitGpuBrokerProcess(
+ bool (*broker_sandboxer_callback)(void),
+ const std::vector<std::string>& read_whitelist_extra,
+ const std::vector<std::string>& write_whitelist_extra) {
+ static const char kDriRcPath[] = "/etc/drirc";
+ static const char kDriCard0Path[] = "/dev/dri/card0";
+
+ CHECK(broker_process_ == NULL);
+
+ // All GPU process policies need these files brokered out.
+ std::vector<std::string> read_whitelist;
+ read_whitelist.push_back(kDriCard0Path);
+ read_whitelist.push_back(kDriRcPath);
+ // Add eventual extra files from read_whitelist_extra.
+ read_whitelist.insert(read_whitelist.end(),
+ read_whitelist_extra.begin(),
+ read_whitelist_extra.end());
+
+ std::vector<std::string> write_whitelist;
+ write_whitelist.push_back(kDriCard0Path);
+ // Add eventual extra files from write_whitelist_extra.
+ write_whitelist.insert(write_whitelist.end(),
+ write_whitelist_extra.begin(),
+ write_whitelist_extra.end());
+
+ broker_process_ = new BrokerProcess(GetFSDeniedErrno(),
+ read_whitelist,
+ write_whitelist);
+ // Initialize the broker process and give it a sandbox callback.
+ CHECK(broker_process_->Init(broker_sandboxer_callback));
+}
+
+} // namespace content
diff --git a/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.h b/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.h
new file mode 100644
index 00000000000..6b1ba4a4c31
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.h
@@ -0,0 +1,57 @@
+// 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_COMMON_SANDBOX_LINUX_BPF_GPU_POLICY_LINUX_H_
+#define CONTENT_COMMON_SANDBOX_LINUX_BPF_GPU_POLICY_LINUX_H_
+
+#include <string>
+#include <vector>
+
+#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
+
+namespace sandbox {
+class BrokerProcess;
+}
+
+namespace content {
+
+class GpuProcessPolicy : public SandboxBPFBasePolicy {
+ public:
+ GpuProcessPolicy();
+ virtual ~GpuProcessPolicy();
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE;
+
+ virtual bool PreSandboxHook() OVERRIDE;
+
+ protected:
+ // Start a broker process to handle open() inside the sandbox.
+ // |broker_sandboxer_callback| is a callback that will enable a suitable
+ // sandbox for the broker process itself.
+ // |read_whitelist_extra| and |write_whitelist_extra| are lists of file
+ // names that should be whitelisted by the broker process, in addition to
+ // the basic ones.
+ void InitGpuBrokerProcess(
+ bool (*broker_sandboxer_callback)(void),
+ const std::vector<std::string>& read_whitelist_extra,
+ const std::vector<std::string>& write_whitelist_extra);
+
+ sandbox::BrokerProcess* broker_process() { return broker_process_; }
+
+ private:
+ // A BrokerProcess is a helper that is started before the sandbox is engaged
+ // and will serve requests to access files over an IPC channel. The client of
+ // this runs from a SIGSYS handler triggered by the seccomp-bpf sandbox.
+ // This should never be destroyed, as after the sandbox is started it is
+ // vital to the process.
+ // This is allocated by InitGpuBrokerProcess, called from PreSandboxHook(),
+ // which executes iff the sandbox is going to be enabled afterwards.
+ sandbox::BrokerProcess* broker_process_;
+ DISALLOW_COPY_AND_ASSIGN(GpuProcessPolicy);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_SANDBOX_LINUX_BPF_GPU_POLICY_LINUX_H_
diff --git a/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc b/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc
new file mode 100644
index 00000000000..9e0e257e0b7
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc
@@ -0,0 +1,70 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/sandbox_linux/bpf_ppapi_policy_linux.h"
+
+#include <errno.h>
+
+#include "base/basictypes.h"
+#include "build/build_config.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+#include "sandbox/linux/services/linux_syscalls.h"
+
+using sandbox::SyscallSets;
+
+namespace content {
+
+namespace {
+
+inline bool IsUsingToolKitGtk() {
+#if defined(TOOLKIT_GTK)
+ return true;
+#else
+ return false;
+#endif
+}
+
+} // namespace
+
+PpapiProcessPolicy::PpapiProcessPolicy() {}
+PpapiProcessPolicy::~PpapiProcessPolicy() {}
+
+ErrorCode PpapiProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
+ int sysno) const {
+ switch (sysno) {
+ case __NR_clone:
+ return sandbox::RestrictCloneToThreadsAndEPERMFork(sandbox);
+ case __NR_pread64:
+ case __NR_pwrite64:
+ case __NR_sched_get_priority_max:
+ case __NR_sched_get_priority_min:
+ case __NR_sched_getaffinity:
+ case __NR_sched_getparam:
+ case __NR_sched_getscheduler:
+ case __NR_sched_setscheduler:
+ case __NR_times:
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ case __NR_ioctl:
+ return ErrorCode(ENOTTY); // Flash Access.
+ default:
+ if (IsUsingToolKitGtk()) {
+#if defined(__x86_64__) || defined(__arm__)
+ if (SyscallSets::IsSystemVSharedMemory(sysno))
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+#endif
+#if defined(__i386__)
+ if (SyscallSets::IsSystemVIpc(sysno))
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+#endif
+ }
+
+ // Default on the baseline policy.
+ return SandboxBPFBasePolicy::EvaluateSyscall(sandbox, sysno);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.h b/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.h
new file mode 100644
index 00000000000..1e9038ff129
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.h
@@ -0,0 +1,27 @@
+// 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_COMMON_SANDBOX_LINUX_BPF_PPAPI_POLICY_LINUX_H_
+#define CONTENT_COMMON_SANDBOX_LINUX_BPF_PPAPI_POLICY_LINUX_H_
+
+#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
+
+namespace content {
+
+// Policy for Pepper plugins such as Flash.
+class PpapiProcessPolicy : public SandboxBPFBasePolicy {
+ public:
+ PpapiProcessPolicy();
+ virtual ~PpapiProcessPolicy();
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PpapiProcessPolicy);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_SANDBOX_LINUX_BPF_PPAPI_POLICY_LINUX_H_
diff --git a/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc b/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
new file mode 100644
index 00000000000..ce7dffbef0f
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
@@ -0,0 +1,88 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/sandbox_linux/bpf_renderer_policy_linux.h"
+
+#include <errno.h>
+
+#include "base/basictypes.h"
+#include "build/build_config.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+#include "sandbox/linux/services/linux_syscalls.h"
+
+using sandbox::SyscallSets;
+
+namespace content {
+
+namespace {
+
+inline bool IsUsingToolKitGtk() {
+#if defined(TOOLKIT_GTK)
+ return true;
+#else
+ return false;
+#endif
+}
+
+} // namespace
+
+RendererProcessPolicy::RendererProcessPolicy() {}
+RendererProcessPolicy::~RendererProcessPolicy() {}
+
+ErrorCode RendererProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
+ int sysno) const {
+ switch (sysno) {
+ case __NR_clone:
+ return sandbox::RestrictCloneToThreadsAndEPERMFork(sandbox);
+ case __NR_ioctl:
+ return sandbox::RestrictIoctl(sandbox);
+ case __NR_prctl:
+ return sandbox::RestrictPrctl(sandbox);
+ // Allow the system calls below.
+ case __NR_fdatasync:
+ case __NR_fsync:
+ case __NR_getpriority:
+#if defined(__i386__) || defined(__x86_64__)
+ case __NR_getrlimit:
+#endif
+#if defined(__i386__) || defined(__arm__)
+ case __NR_ugetrlimit:
+#endif
+ case __NR_mremap: // See crbug.com/149834.
+ case __NR_pread64:
+ case __NR_pwrite64:
+ case __NR_sched_getaffinity:
+ case __NR_sched_get_priority_max:
+ case __NR_sched_get_priority_min:
+ case __NR_sched_getparam:
+ case __NR_sched_getscheduler:
+ case __NR_sched_setscheduler:
+ case __NR_setpriority:
+ case __NR_sysinfo:
+ case __NR_times:
+ case __NR_uname:
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ case __NR_prlimit64:
+ return ErrorCode(EPERM); // See crbug.com/160157.
+ default:
+ if (IsUsingToolKitGtk()) {
+#if defined(__x86_64__) || defined(__arm__)
+ if (SyscallSets::IsSystemVSharedMemory(sysno))
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+#endif
+#if defined(__i386__)
+ if (SyscallSets::IsSystemVIpc(sysno))
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+#endif
+ }
+
+ // Default on the content baseline policy.
+ return SandboxBPFBasePolicy::EvaluateSyscall(sandbox, sysno);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.h b/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.h
new file mode 100644
index 00000000000..ce00cd78c0f
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.h
@@ -0,0 +1,27 @@
+// 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_COMMON_SANDBOX_LINUX_BPF_RENDERER_POLICY_LINUX_H_
+#define CONTENT_COMMON_SANDBOX_LINUX_BPF_RENDERER_POLICY_LINUX_H_
+
+#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
+
+namespace content {
+
+// This policy can be used by both renderer and worker processes.
+class RendererProcessPolicy : public SandboxBPFBasePolicy {
+ public:
+ RendererProcessPolicy();
+ virtual ~RendererProcessPolicy();
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RendererProcessPolicy);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_SANDBOX_LINUX_BPF_RENDERER_POLICY_LINUX_H_
diff --git a/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.cc b/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.cc
new file mode 100644
index 00000000000..d1e5af30563
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.cc
@@ -0,0 +1,40 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
+
+#include <errno.h>
+
+#include "base/logging.h"
+#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
+
+namespace content {
+
+namespace {
+
+// The errno used for denied file system access system calls, such as open(2).
+static const int kFSDeniedErrno = EPERM;
+
+} // namespace.
+
+SandboxBPFBasePolicy::SandboxBPFBasePolicy()
+ : baseline_policy_(new sandbox::BaselinePolicy(kFSDeniedErrno)) {}
+SandboxBPFBasePolicy::~SandboxBPFBasePolicy() {}
+
+ErrorCode SandboxBPFBasePolicy::EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const {
+ DCHECK(baseline_policy_);
+ return baseline_policy_->EvaluateSyscall(sandbox_compiler,
+ system_call_number);
+}
+
+bool SandboxBPFBasePolicy::PreSandboxHook() {
+ return true;
+}
+
+int SandboxBPFBasePolicy::GetFSDeniedErrno() {
+ return kFSDeniedErrno;
+}
+
+} // namespace content.
diff --git a/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h b/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h
new file mode 100644
index 00000000000..6d9d83f4fa1
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h
@@ -0,0 +1,49 @@
+// 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_COMMON_SANDBOX_LINUX_SANDBOX_BPF_BASE_POLICY_LINUX_H_
+#define CONTENT_COMMON_SANDBOX_LINUX_SANDBOX_BPF_BASE_POLICY_LINUX_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+
+using sandbox::ErrorCode;
+using sandbox::SandboxBPF;
+
+namespace content {
+
+// The "baseline" BPF policy for content/. Any content/ seccomp-bpf policy
+// should inherit from it.
+// It implements the main SandboxBPFPolicy interface. Due to its nature
+// as a "kernel attack surface reduction" layer, it's implementation-defined.
+class SandboxBPFBasePolicy : public sandbox::SandboxBPFPolicy {
+ public:
+ SandboxBPFBasePolicy();
+ virtual ~SandboxBPFBasePolicy();
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE;
+
+ // A policy can implement this hook to run code right before the policy
+ // is passed to the SandboxBPF class and the sandbox is engaged.
+ // If PreSandboxHook() returns true, the sandbox is guaranteed to be
+ // engaged afterwards.
+ // This will be used when enabling the sandbox though
+ // SandboxSeccompBPF::StartSandbox().
+ virtual bool PreSandboxHook();
+
+ // Get the errno(3) to return for filesystem errors.
+ static int GetFSDeniedErrno();
+
+ private:
+ // Compose the BaselinePolicy from sandbox/.
+ scoped_ptr<sandbox::BaselinePolicy> baseline_policy_;
+ DISALLOW_COPY_AND_ASSIGN(SandboxBPFBasePolicy);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_SANDBOX_LINUX_SANDBOX_BPF_BASE_POLICY_LINUX_H_
diff --git a/chromium/content/common/sandbox_linux/sandbox_init_linux.cc b/chromium/content/common/sandbox_linux/sandbox_init_linux.cc
new file mode 100644
index 00000000000..516c611d2eb
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/sandbox_init_linux.cc
@@ -0,0 +1,21 @@
+// 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/public/common/sandbox_init.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+
+namespace content {
+
+bool InitializeSandbox(scoped_ptr<sandbox::SandboxBPFPolicy> policy) {
+ return SandboxSeccompBPF::StartSandboxWithExternalPolicy(policy.Pass());
+}
+
+scoped_ptr<sandbox::SandboxBPFPolicy> GetBPFSandboxBaselinePolicy() {
+ return SandboxSeccompBPF::GetBaselinePolicy().Pass();
+}
+
+} // namespace content
diff --git a/chromium/content/common/sandbox_linux.cc b/chromium/content/common/sandbox_linux/sandbox_linux.cc
index c2b3aad0e1c..a30e41c4165 100644
--- a/chromium/content/common/sandbox_linux.cc
+++ b/chromium/content/common/sandbox_linux/sandbox_linux.cc
@@ -2,11 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <dirent.h>
#include <fcntl.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <unistd.h>
#include <limits>
@@ -14,17 +16,34 @@
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/posix/eintr_wrapper.h"
+#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
-#include "content/common/sandbox_linux.h"
-#include "content/common/sandbox_seccomp_bpf_linux.h"
+#include "build/build_config.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
+#include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/sandbox_linux.h"
+#include "sandbox/linux/services/credentials.h"
+#include "sandbox/linux/services/thread_helpers.h"
#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
namespace {
+struct FDCloser {
+ inline void operator()(int* fd) const {
+ DCHECK(fd);
+ PCHECK(0 == IGNORE_EINTR(close(*fd)));
+ *fd = -1;
+ }
+};
+
+// Don't use base::ScopedFD since it doesn't CHECK that the file descriptor was
+// closed.
+typedef scoped_ptr<int, FDCloser> SafeScopedFD;
+
void LogSandboxStarted(const std::string& sandbox_name) {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
const std::string process_type =
@@ -60,6 +79,21 @@ bool IsRunningTSAN() {
#endif
}
+// Try to open /proc/self/task/ with the help of |proc_fd|. |proc_fd| can be
+// -1. Will return -1 on error and set errno like open(2).
+int OpenProcTaskFd(int proc_fd) {
+ int proc_self_task = -1;
+ if (proc_fd >= 0) {
+ // If a handle to /proc is available, use it. This allows to bypass file
+ // system restrictions.
+ proc_self_task = openat(proc_fd, "self/task/", O_RDONLY | O_DIRECTORY);
+ } else {
+ // Otherwise, make an attempt to access the file system directly.
+ proc_self_task = open("/proc/self/task/", O_RDONLY | O_DIRECTORY);
+ }
+ return proc_self_task;
+}
+
} // namespace
namespace content {
@@ -67,6 +101,7 @@ namespace content {
LinuxSandbox::LinuxSandbox()
: proc_fd_(-1),
seccomp_bpf_started_(false),
+ sandbox_status_flags_(kSandboxLinuxInvalid),
pre_initialized_(false),
seccomp_bpf_supported_(false),
setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) {
@@ -105,8 +140,8 @@ void LinuxSandbox::PreinitializeSandbox() {
CHECK_GE(proc_fd_, 0);
#endif // !defined(NDEBUG)
// We "pre-warm" the code that detects supports for seccomp BPF.
- if (SandboxSeccompBpf::IsSeccompBpfDesired()) {
- if (!SandboxSeccompBpf::SupportsSandbox()) {
+ if (SandboxSeccompBPF::IsSeccompBPFDesired()) {
+ if (!SandboxSeccompBPF::SupportsSandbox()) {
VLOG(1) << "Lacking support for seccomp-bpf sandbox.";
} else {
seccomp_bpf_supported_ = true;
@@ -116,96 +151,66 @@ void LinuxSandbox::PreinitializeSandbox() {
}
bool LinuxSandbox::InitializeSandbox() {
- bool seccomp_bpf_started = false;
LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
- // We need to make absolutely sure that our sandbox is "sealed" before
- // InitializeSandbox does exit.
- base::ScopedClosureRunner sandbox_sealer(
- base::Bind(&LinuxSandbox::SealSandbox, base::Unretained(linux_sandbox)));
- const std::string process_type =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kProcessType);
-
- // No matter what, it's always an error to call InitializeSandbox() after
- // threads have been created.
- if (!linux_sandbox->IsSingleThreaded()) {
- std::string error_message = "InitializeSandbox() called with multiple "
- "threads in process " + process_type;
- // TSAN starts a helper thread. So we don't start the sandbox and don't
- // even report an error about it.
- if (IsRunningTSAN())
- return false;
- // The GPU process is allowed to call InitializeSandbox() with threads for
- // now, because it loads third party libraries.
- if (process_type != switches::kGpuProcess)
- CHECK(false) << error_message;
- LOG(ERROR) << error_message;
- return false;
- }
-
- // Attempt to limit the future size of the address space of the process.
- linux_sandbox->LimitAddressSpace(process_type);
-
- // First, try to enable seccomp-bpf.
- seccomp_bpf_started = linux_sandbox->StartSeccompBpf(process_type);
+ return linux_sandbox->InitializeSandboxImpl();
+}
- return seccomp_bpf_started;
+void LinuxSandbox::StopThread(base::Thread* thread) {
+ LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
+ linux_sandbox->StopThreadImpl(thread);
}
-int LinuxSandbox::GetStatus() const {
+int LinuxSandbox::GetStatus() {
CHECK(pre_initialized_);
- int sandbox_flags = 0;
- if (setuid_sandbox_client_->IsSandboxed()) {
- sandbox_flags |= kSandboxLinuxSUID;
- if (setuid_sandbox_client_->IsInNewPIDNamespace())
- sandbox_flags |= kSandboxLinuxPIDNS;
- if (setuid_sandbox_client_->IsInNewNETNamespace())
- sandbox_flags |= kSandboxLinuxNetNS;
- }
+ if (kSandboxLinuxInvalid == sandbox_status_flags_) {
+ // Initialize sandbox_status_flags_.
+ sandbox_status_flags_ = 0;
+ if (setuid_sandbox_client_->IsSandboxed()) {
+ sandbox_status_flags_ |= kSandboxLinuxSUID;
+ if (setuid_sandbox_client_->IsInNewPIDNamespace())
+ sandbox_status_flags_ |= kSandboxLinuxPIDNS;
+ if (setuid_sandbox_client_->IsInNewNETNamespace())
+ sandbox_status_flags_ |= kSandboxLinuxNetNS;
+ }
- if (seccomp_bpf_supported() &&
- SandboxSeccompBpf::ShouldEnableSeccompBpf(switches::kRendererProcess)) {
- // We report whether the sandbox will be activated when renderers go
- // through sandbox initialization.
- sandbox_flags |= kSandboxLinuxSeccompBpf;
+ // We report whether the sandbox will be activated when renderers, workers
+ // and PPAPI plugins go through sandbox initialization.
+ if (seccomp_bpf_supported() &&
+ SandboxSeccompBPF::ShouldEnableSeccompBPF(switches::kRendererProcess)) {
+ sandbox_status_flags_ |= kSandboxLinuxSeccompBPF;
+ }
}
- return sandbox_flags;
+ return sandbox_status_flags_;
}
// Threads are counted via /proc/self/task. This is a little hairy because of
// PID namespaces and existing sandboxes, so "self" must really be used instead
// of using the pid.
bool LinuxSandbox::IsSingleThreaded() const {
- struct stat task_stat;
- int fstat_ret;
- if (proc_fd_ >= 0) {
- // If a handle to /proc is available, use it. This allows to bypass file
- // system restrictions.
- fstat_ret = fstatat(proc_fd_, "self/task/", &task_stat, 0);
- } else {
- // Otherwise, make an attempt to access the file system directly.
- fstat_ret = fstatat(AT_FDCWD, "/proc/self/task/", &task_stat, 0);
- }
- // In Debug mode, it's mandatory to be able to count threads to catch bugs.
+ bool is_single_threaded = false;
+ int proc_self_task = OpenProcTaskFd(proc_fd_);
+
+// In Debug mode, it's mandatory to be able to count threads to catch bugs.
#if !defined(NDEBUG)
- // Using DCHECK here would be incorrect. DCHECK can be enabled in non
- // official release mode.
- CHECK_EQ(0, fstat_ret) << "Could not count threads, the sandbox was not "
- << "pre-initialized properly.";
+ // Using CHECK here since we want to check all the cases where
+ // !defined(NDEBUG)
+ // gets built.
+ CHECK_LE(0, proc_self_task) << "Could not count threads, the sandbox was not "
+ << "pre-initialized properly.";
#endif // !defined(NDEBUG)
- if (fstat_ret) {
+
+ if (proc_self_task < 0) {
// Pretend to be monothreaded if it can't be determined (for instance the
// setuid sandbox is already engaged but no proc_fd_ is available).
- return true;
+ is_single_threaded = true;
+ } else {
+ SafeScopedFD task_closer(&proc_self_task);
+ is_single_threaded =
+ sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task);
}
- // At least "..", "." and the current thread should be present.
- CHECK_LE(3UL, task_stat.st_nlink);
- // Counting threads via /proc/self/task could be racy. For the purpose of
- // determining if the current proces is monothreaded it works: if at any
- // time it becomes monothreaded, it'll stay so.
- return task_stat.st_nlink == 3;
+ return is_single_threaded;
}
bool LinuxSandbox::seccomp_bpf_started() const {
@@ -217,13 +222,12 @@ sandbox::SetuidSandboxClient*
return setuid_sandbox_client_.get();
}
-// For seccomp-bpf, we use the SandboxSeccompBpf class.
-bool LinuxSandbox::StartSeccompBpf(const std::string& process_type) {
+// For seccomp-bpf, we use the SandboxSeccompBPF class.
+bool LinuxSandbox::StartSeccompBPF(const std::string& process_type) {
CHECK(!seccomp_bpf_started_);
- if (!pre_initialized_)
- PreinitializeSandbox();
+ CHECK(pre_initialized_);
if (seccomp_bpf_supported())
- seccomp_bpf_started_ = SandboxSeccompBpf::StartSandbox(process_type);
+ seccomp_bpf_started_ = SandboxSeccompBPF::StartSandbox(process_type);
if (seccomp_bpf_started_)
LogSandboxStarted("seccomp-bpf");
@@ -231,6 +235,62 @@ bool LinuxSandbox::StartSeccompBpf(const std::string& process_type) {
return seccomp_bpf_started_;
}
+bool LinuxSandbox::InitializeSandboxImpl() {
+ const std::string process_type =
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kProcessType);
+
+ // We need to make absolutely sure that our sandbox is "sealed" before
+ // returning.
+ // Unretained() since the current object is a Singleton.
+ base::ScopedClosureRunner sandbox_sealer(
+ base::Bind(&LinuxSandbox::SealSandbox, base::Unretained(this)));
+ // Make sure that this function enables sandboxes as promised by GetStatus().
+ // Unretained() since the current object is a Singleton.
+ base::ScopedClosureRunner sandbox_promise_keeper(
+ base::Bind(&LinuxSandbox::CheckForBrokenPromises,
+ base::Unretained(this),
+ process_type));
+
+ // No matter what, it's always an error to call InitializeSandbox() after
+ // threads have been created.
+ if (!IsSingleThreaded()) {
+ std::string error_message = "InitializeSandbox() called with multiple "
+ "threads in process " + process_type;
+ // TSAN starts a helper thread. So we don't start the sandbox and don't
+ // even report an error about it.
+ if (IsRunningTSAN())
+ return false;
+ // The GPU process is allowed to call InitializeSandbox() with threads for
+ // now, because it loads third-party libraries.
+ if (process_type != switches::kGpuProcess)
+ CHECK(false) << error_message;
+ LOG(ERROR) << error_message;
+ return false;
+ }
+
+ // Only one thread is running, pre-initialize if not already done.
+ if (!pre_initialized_)
+ PreinitializeSandbox();
+
+ DCHECK(!HasOpenDirectories()) <<
+ "InitializeSandbox() called after unexpected directories have been " <<
+ "opened. This breaks the security of the setuid sandbox.";
+
+ // Attempt to limit the future size of the address space of the process.
+ LimitAddressSpace(process_type);
+
+ // Try to enable seccomp-bpf.
+ bool seccomp_bpf_started = StartSeccompBPF(process_type);
+
+ return seccomp_bpf_started;
+}
+
+void LinuxSandbox::StopThreadImpl(base::Thread* thread) {
+ DCHECK(thread);
+ StopThreadAndEnsureNotCounted(thread);
+}
+
bool LinuxSandbox::seccomp_bpf_supported() const {
CHECK(pre_initialized_);
return seccomp_bpf_supported_;
@@ -253,10 +313,13 @@ bool LinuxSandbox::LimitAddressSpace(const std::string& process_type) {
// rely on on-demand paging for allocation. Unfortunately, even
// MADV_DONTNEED ranges count towards RLIMIT_AS so this is not an option.
// See crbug.com/169327 for a discussion.
- // For now, increase limit to 16GB for renderer and worker processes to
- // accomodate.
+ // On the GPU process, irrespective of V8, we can exhaust a 4GB address space
+ // under normal usage, see crbug.com/271119
+ // For now, increase limit to 16GB for renderer and worker and gpu processes
+ // to accomodate.
if (process_type == switches::kRendererProcess ||
- process_type == switches::kWorkerProcess) {
+ process_type == switches::kWorkerProcess ||
+ process_type == switches::kGpuProcess) {
address_space_limit = 1L << 34;
}
#endif // defined(__LP64__)
@@ -273,13 +336,40 @@ bool LinuxSandbox::LimitAddressSpace(const std::string& process_type) {
#endif // !defined(ADDRESS_SANITIZER)
}
+bool LinuxSandbox::HasOpenDirectories() const {
+ return sandbox::Credentials().HasOpenDirectory(proc_fd_);
+}
+
void LinuxSandbox::SealSandbox() {
if (proc_fd_ >= 0) {
- int ret = HANDLE_EINTR(close(proc_fd_));
+ int ret = IGNORE_EINTR(close(proc_fd_));
CHECK_EQ(0, ret);
proc_fd_ = -1;
}
}
-} // namespace content
+void LinuxSandbox::CheckForBrokenPromises(const std::string& process_type) {
+ // Make sure that any promise made with GetStatus() wasn't broken.
+ bool promised_seccomp_bpf_would_start = false;
+ if (process_type == switches::kRendererProcess ||
+ process_type == switches::kWorkerProcess ||
+ process_type == switches::kPpapiPluginProcess) {
+ promised_seccomp_bpf_would_start =
+ (sandbox_status_flags_ != kSandboxLinuxInvalid) &&
+ (GetStatus() & kSandboxLinuxSeccompBPF);
+ }
+ if (promised_seccomp_bpf_would_start) {
+ CHECK(seccomp_bpf_started_);
+ }
+}
+void LinuxSandbox::StopThreadAndEnsureNotCounted(base::Thread* thread) const {
+ DCHECK(thread);
+ int proc_self_task = OpenProcTaskFd(proc_fd_);
+ PCHECK(proc_self_task >= 0);
+ SafeScopedFD task_closer(&proc_self_task);
+ CHECK(
+ sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_self_task, thread));
+}
+
+} // namespace content
diff --git a/chromium/content/common/sandbox_linux.h b/chromium/content/common/sandbox_linux/sandbox_linux.h
index 412c04ab20b..8b5876a7b23 100644
--- a/chromium/content/common/sandbox_linux.h
+++ b/chromium/content/common/sandbox_linux/sandbox_linux.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_SANDBOX_LINUX_H_
-#define CONTENT_COMMON_SANDBOX_LINUX_H_
+#ifndef CONTENT_COMMON_SANDBOX_LINUX_SANDBOX_LINUX_H_
+#define CONTENT_COMMON_SANDBOX_LINUX_SANDBOX_LINUX_H_
#include <string>
@@ -12,6 +12,9 @@
#include "content/public/common/sandbox_linux.h"
template <typename T> struct DefaultSingletonTraits;
+namespace base {
+class Thread;
+}
namespace sandbox { class SetuidSandboxClient; }
namespace content {
@@ -45,15 +48,19 @@ class LinuxSandbox {
// seccomp-bpf and address space limitations (the setuid sandbox works
// differently and is set-up in the Zygote). This will instantiate the
// LinuxSandbox singleton if it doesn't already exist.
+ // This function should only be called without any thread running.
static bool InitializeSandbox();
- // Returns the Status of the renderers' sandbox. Can only be queried after
- // going through PreinitializeSandbox(). This is a bitmask and uses the
- // constants defined in "enum LinuxSandboxStatus". Since the status needs to
- // be provided before the sandboxes are actually started, this returns what
- // will actually happen once the various Start* functions are called from
- // inside a renderer.
- int GetStatus() const;
+ // Stop |thread| in a way that can be trusted by the sandbox.
+ static void StopThread(base::Thread* thread);
+
+ // Returns the status of the renderer, worker and ppapi sandbox. Can only
+ // be queried after going through PreinitializeSandbox(). This is a bitmask
+ // and uses the constants defined in "enum LinuxSandboxStatus". Since the
+ // status needs to be provided before the sandboxes are actually started,
+ // this returns what will actually happen once InitializeSandbox()
+ // is called from inside these processes.
+ int GetStatus();
// Returns true if the current process is single-threaded or if the number
// of threads cannot be determined.
bool IsSingleThreaded() const;
@@ -69,7 +76,7 @@ class LinuxSandbox {
// Check the policy and eventually start the seccomp-bpf sandbox. This should
// never be called with threads started. If we detect that threads have
// started we will crash.
- bool StartSeccompBpf(const std::string& process_type);
+ bool StartSeccompBPF(const std::string& process_type);
// Limit the address space of the current process (and its children).
// to make some vulnerabilities harder to exploit.
@@ -78,17 +85,33 @@ class LinuxSandbox {
private:
friend struct DefaultSingletonTraits<LinuxSandbox>;
+ // Some methods are static and get an instance of the Singleton. These
+ // are the non-static implementations.
+ bool InitializeSandboxImpl();
+ void StopThreadImpl(base::Thread* thread);
// We must have been pre_initialized_ before using this.
bool seccomp_bpf_supported() const;
+ // Returns true if it can be determined that the current process has open
+ // directories that are not managed by the LinuxSandbox class. This would
+ // be a vulnerability as it would allow to bypass the setuid sandbox.
+ bool HasOpenDirectories() const;
// The last part of the initialization is to make sure any temporary "hole"
// in the sandbox is closed. For now, this consists of closing proc_fd_.
void SealSandbox();
+ // GetStatus() makes promises as to how the sandbox will behave. This
+ // checks that no promises have been broken.
+ void CheckForBrokenPromises(const std::string& process_type);
+ // Stop |thread| and make sure it does not appear in /proc/self/tasks/
+ // anymore.
+ void StopThreadAndEnsureNotCounted(base::Thread* thread) const;
// A file descriptor to /proc. It's dangerous to have it around as it could
// allow for sandbox bypasses. It needs to be closed before we consider
// ourselves sandboxed.
int proc_fd_;
bool seccomp_bpf_started_;
+ // The value returned by GetStatus(). Gets computed once and then cached.
+ int sandbox_status_flags_;
// Did PreinitializeSandbox() run?
bool pre_initialized_;
bool seccomp_bpf_supported_; // Accurate if pre_initialized_.
@@ -100,5 +123,4 @@ class LinuxSandbox {
} // namespace content
-#endif // CONTENT_COMMON_SANDBOX_LINUX_H_
-
+#endif // CONTENT_COMMON_SANDBOX_LINUX_SANDBOX_LINUX_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
new file mode 100644
index 00000000000..21b7b513563
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc
@@ -0,0 +1,297 @@
+// 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/sandbox_linux/sandbox_seccomp_bpf_linux.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/types.h>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "content/public/common/content_switches.h"
+
+// These are the only architectures supported for now.
+#if defined(__i386__) || defined(__x86_64__) || \
+ (defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__)))
+#define SECCOMP_BPF_SANDBOX
+#endif
+
+#if defined(SECCOMP_BPF_SANDBOX)
+#include "base/posix/eintr_wrapper.h"
+#include "content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h"
+#include "content/common/sandbox_linux/bpf_gpu_policy_linux.h"
+#include "content/common/sandbox_linux/bpf_ppapi_policy_linux.h"
+#include "content/common/sandbox_linux/bpf_renderer_policy_linux.h"
+#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
+#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
+#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+#include "sandbox/linux/services/linux_syscalls.h"
+
+using sandbox::BaselinePolicy;
+using sandbox::SyscallSets;
+
+namespace content {
+
+namespace {
+
+void StartSandboxWithPolicy(sandbox::SandboxBPFPolicy* policy);
+
+inline bool IsChromeOS() {
+#if defined(OS_CHROMEOS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+inline bool IsArchitectureArm() {
+#if defined(__arm__)
+ return true;
+#else
+ return false;
+#endif
+}
+
+class BlacklistDebugAndNumaPolicy : public SandboxBPFBasePolicy {
+ public:
+ BlacklistDebugAndNumaPolicy() {}
+ virtual ~BlacklistDebugAndNumaPolicy() {}
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BlacklistDebugAndNumaPolicy);
+};
+
+ErrorCode BlacklistDebugAndNumaPolicy::EvaluateSyscall(SandboxBPF* sandbox,
+ int sysno) const {
+ if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
+ // TODO(jln) we should not have to do that in a trivial policy.
+ return ErrorCode(ENOSYS);
+ }
+ if (SyscallSets::IsDebug(sysno) || SyscallSets::IsNuma(sysno))
+ return sandbox->Trap(sandbox::CrashSIGSYS_Handler, NULL);
+
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+}
+
+class AllowAllPolicy : public SandboxBPFBasePolicy {
+ public:
+ AllowAllPolicy() {}
+ virtual ~AllowAllPolicy() {}
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy);
+};
+
+// Allow all syscalls.
+// This will still deny x32 or IA32 calls in 64 bits mode or
+// 64 bits system calls in compatibility mode.
+ErrorCode AllowAllPolicy::EvaluateSyscall(SandboxBPF*, int sysno) const {
+ if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
+ // TODO(jln) we should not have to do that in a trivial policy.
+ return ErrorCode(ENOSYS);
+ } else {
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ }
+}
+
+// If a BPF policy is engaged for |process_type|, run a few sanity checks.
+void RunSandboxSanityChecks(const std::string& process_type) {
+ if (process_type == switches::kRendererProcess ||
+ process_type == switches::kWorkerProcess ||
+ process_type == switches::kGpuProcess ||
+ process_type == switches::kPpapiPluginProcess) {
+ int syscall_ret;
+ errno = 0;
+
+ // Without the sandbox, this would EBADF.
+ syscall_ret = fchmod(-1, 07777);
+ CHECK_EQ(-1, syscall_ret);
+ CHECK_EQ(EPERM, errno);
+
+ // Run most of the sanity checks only in DEBUG mode to avoid a perf.
+ // impact.
+#if !defined(NDEBUG)
+ // open() must be restricted.
+ syscall_ret = open("/etc/passwd", O_RDONLY);
+ CHECK_EQ(-1, syscall_ret);
+ CHECK_EQ(SandboxBPFBasePolicy::GetFSDeniedErrno(), errno);
+
+ // We should never allow the creation of netlink sockets.
+ syscall_ret = socket(AF_NETLINK, SOCK_DGRAM, 0);
+ CHECK_EQ(-1, syscall_ret);
+ CHECK_EQ(EPERM, errno);
+#endif // !defined(NDEBUG)
+ }
+}
+
+
+// This function takes ownership of |policy|.
+void StartSandboxWithPolicy(sandbox::SandboxBPFPolicy* policy) {
+ // Starting the sandbox is a one-way operation. The kernel doesn't allow
+ // us to unload a sandbox policy after it has been started. Nonetheless,
+ // in order to make the use of the "Sandbox" object easier, we allow for
+ // the object to be destroyed after the sandbox has been started. Note that
+ // doing so does not stop the sandbox.
+ SandboxBPF sandbox;
+ sandbox.SetSandboxPolicy(policy);
+ sandbox.StartSandbox();
+}
+
+// nacl_helper needs to be tiny and includes only part of content/
+// in its dependencies. Make sure to not link things that are not needed.
+#if !defined(IN_NACL_HELPER)
+scoped_ptr<SandboxBPFBasePolicy> GetGpuProcessSandbox() {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ bool allow_sysv_shm = false;
+ if (command_line.HasSwitch(switches::kGpuSandboxAllowSysVShm)) {
+ DCHECK(IsArchitectureArm());
+ allow_sysv_shm = true;
+ }
+
+ if (IsChromeOS() && IsArchitectureArm()) {
+ return scoped_ptr<SandboxBPFBasePolicy>(
+ new CrosArmGpuProcessPolicy(allow_sysv_shm));
+ } else {
+ return scoped_ptr<SandboxBPFBasePolicy>(new GpuProcessPolicy);
+ }
+}
+
+// Initialize the seccomp-bpf sandbox.
+bool StartBPFSandbox(const CommandLine& command_line,
+ const std::string& process_type) {
+ scoped_ptr<SandboxBPFBasePolicy> policy;
+
+ if (process_type == switches::kGpuProcess) {
+ policy.reset(GetGpuProcessSandbox().release());
+ } else if (process_type == switches::kRendererProcess ||
+ process_type == switches::kWorkerProcess) {
+ policy.reset(new RendererProcessPolicy);
+ } else if (process_type == switches::kPpapiPluginProcess) {
+ policy.reset(new PpapiProcessPolicy);
+ } else if (process_type == switches::kUtilityProcess) {
+ policy.reset(new BlacklistDebugAndNumaPolicy);
+ } else {
+ NOTREACHED();
+ policy.reset(new AllowAllPolicy);
+ }
+
+ CHECK(policy->PreSandboxHook());
+ StartSandboxWithPolicy(policy.release());
+
+ RunSandboxSanityChecks(process_type);
+ return true;
+}
+#else // defined(IN_NACL_HELPER)
+bool StartBPFSandbox(const CommandLine& command_line,
+ const std::string& process_type) {
+ NOTREACHED();
+ // Avoid -Wunused-function with no-op code.
+ ignore_result(IsChromeOS);
+ ignore_result(IsArchitectureArm);
+ ignore_result(RunSandboxSanityChecks);
+ return false;
+}
+#endif // !defined(IN_NACL_HELPER)
+
+} // namespace
+
+#endif // SECCOMP_BPF_SANDBOX
+
+// Is seccomp BPF globally enabled?
+bool SandboxSeccompBPF::IsSeccompBPFDesired() {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ if (!command_line.HasSwitch(switches::kNoSandbox) &&
+ !command_line.HasSwitch(switches::kDisableSeccompFilterSandbox)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool SandboxSeccompBPF::ShouldEnableSeccompBPF(
+ const std::string& process_type) {
+#if defined(SECCOMP_BPF_SANDBOX)
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ if (process_type == switches::kGpuProcess)
+ return !command_line.HasSwitch(switches::kDisableGpuSandbox);
+
+ return true;
+#endif // SECCOMP_BPF_SANDBOX
+ return false;
+}
+
+bool SandboxSeccompBPF::SupportsSandbox() {
+#if defined(SECCOMP_BPF_SANDBOX)
+ // TODO(jln): pass the saved proc_fd_ from the LinuxSandbox singleton
+ // here.
+ SandboxBPF::SandboxStatus bpf_sandbox_status =
+ SandboxBPF::SupportsSeccompSandbox(-1);
+ // Kernel support is what we are interested in here. Other status
+ // such as STATUS_UNAVAILABLE (has threads) still indicate kernel support.
+ // We make this a negative check, since if there is a bug, we would rather
+ // "fail closed" (expect a sandbox to be available and try to start it).
+ if (bpf_sandbox_status != SandboxBPF::STATUS_UNSUPPORTED) {
+ return true;
+ }
+#endif
+ return false;
+}
+
+bool SandboxSeccompBPF::StartSandbox(const std::string& process_type) {
+#if defined(SECCOMP_BPF_SANDBOX)
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+
+ if (IsSeccompBPFDesired() && // Global switches policy.
+ ShouldEnableSeccompBPF(process_type) && // Process-specific policy.
+ SupportsSandbox()) {
+ // If the kernel supports the sandbox, and if the command line says we
+ // should enable it, enable it or die.
+ bool started_sandbox = StartBPFSandbox(command_line, process_type);
+ CHECK(started_sandbox);
+ return true;
+ }
+#endif
+ return false;
+}
+
+bool SandboxSeccompBPF::StartSandboxWithExternalPolicy(
+ scoped_ptr<sandbox::SandboxBPFPolicy> policy) {
+#if defined(SECCOMP_BPF_SANDBOX)
+ if (IsSeccompBPFDesired() && SupportsSandbox()) {
+ CHECK(policy);
+ StartSandboxWithPolicy(policy.release());
+ return true;
+ }
+#endif // defined(SECCOMP_BPF_SANDBOX)
+ return false;
+}
+
+scoped_ptr<sandbox::SandboxBPFPolicy>
+SandboxSeccompBPF::GetBaselinePolicy() {
+#if defined(SECCOMP_BPF_SANDBOX)
+ return scoped_ptr<sandbox::SandboxBPFPolicy>(new BaselinePolicy);
+#else
+ return scoped_ptr<sandbox::SandboxBPFPolicy>();
+#endif // defined(SECCOMP_BPF_SANDBOX)
+}
+
+} // namespace content
diff --git a/chromium/content/common/sandbox_seccomp_bpf_linux.h b/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h
index 6ad6c0fa940..cbf6daf8167 100644
--- a/chromium/content/common/sandbox_seccomp_bpf_linux.h
+++ b/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h
@@ -2,29 +2,33 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_SANDBOX_SECCOMP_BPF_LINUX_H_
-#define CONTENT_COMMON_SANDBOX_SECCOMP_BPF_LINUX_H_
+#ifndef CONTENT_COMMON_SANDBOX_LINUX_SANDBOX_SECCOMP_BPF_LINUX_H_
+#define CONTENT_COMMON_SANDBOX_LINUX_SANDBOX_SECCOMP_BPF_LINUX_H_
#include <string>
#include "base/basictypes.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy_forward.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace sandbox {
+class SandboxBPFPolicy;
+}
namespace content {
// This class has two main sets of APIs. One can be used to start the sandbox
// for internal content process types, the other is indirectly exposed as
// a public content/ API and uses a supplied policy.
-class SandboxSeccompBpf {
+class SandboxSeccompBPF {
public:
// This is the API to enable a seccomp-bpf sandbox for content/
// process-types:
// Is the sandbox globally enabled, can anything use it at all ?
// This looks at global command line flags to see if the sandbox
// should be enabled at all.
- static bool IsSeccompBpfDesired();
+ static bool IsSeccompBPFDesired();
// Should the sandbox be enabled for process_type ?
- static bool ShouldEnableSeccompBpf(const std::string& process_type);
+ static bool ShouldEnableSeccompBPF(const std::string& process_type);
// Check if the kernel supports this sandbox. It's useful to "prewarm"
// this, part of the result will be cached.
static bool SupportsSandbox();
@@ -35,15 +39,15 @@ class SandboxSeccompBpf {
// This is the API to enable a seccomp-bpf sandbox by using an
// external policy.
static bool StartSandboxWithExternalPolicy(
- playground2::BpfSandboxPolicy policy);
+ scoped_ptr<sandbox::SandboxBPFPolicy> policy);
// The "baseline" policy can be a useful base to build a sandbox policy.
- static playground2::BpfSandboxPolicyCallback GetBaselinePolicy();
+ static scoped_ptr<sandbox::SandboxBPFPolicy> GetBaselinePolicy();
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(SandboxSeccompBpf);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SandboxSeccompBPF);
};
} // namespace content
-#endif // CONTENT_COMMON_SANDBOX_SECCOMP_BPF_LINUX_H_
+#endif // CONTENT_COMMON_SANDBOX_LINUX_SANDBOX_SECCOMP_BPF_LINUX_H_
diff --git a/chromium/content/common/sandbox_mac.mm b/chromium/content/common/sandbox_mac.mm
index a9f42e2ec92..0baa2756bdd 100644
--- a/chromium/content/common/sandbox_mac.mm
+++ b/chromium/content/common/sandbox_mac.mm
@@ -36,6 +36,7 @@ extern "C" {
#include "third_party/icu/source/common/unicode/uchar.h"
#include "ui/base/layout.h"
#include "ui/gl/gl_surface.h"
+#include "ui/gl/io_surface_support_mac.h"
namespace content {
namespace {
@@ -307,6 +308,15 @@ void Sandbox::SandboxWarmup(int sandbox_type) {
base::GetUrandomFD();
}
+ { // IOSurfaceLookup() - 10.7
+ // Needed by zero-copy texture update framework - crbug.com/323338
+ IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
+ if (io_surface_support) {
+ base::ScopedCFTypeRef<CFTypeRef> io_surface(
+ io_surface_support->IOSurfaceLookup(0));
+ }
+ }
+
// Process-type dependent warm-up.
if (sandbox_type == SANDBOX_TYPE_UTILITY) {
// CFTimeZoneCopyZone() tries to read /etc and /private/etc/localtime - 10.8
diff --git a/chromium/content/common/sandbox_mac_diraccess_unittest.mm b/chromium/content/common/sandbox_mac_diraccess_unittest.mm
index c8611dfd45a..6d3ddadb367 100644
--- a/chromium/content/common/sandbox_mac_diraccess_unittest.mm
+++ b/chromium/content/common/sandbox_mac_diraccess_unittest.mm
@@ -145,10 +145,11 @@ typedef scoped_ptr_malloc<base::FilePath, ScopedDirectoryDelete>
ScopedDirectory;
TEST_F(MacDirAccessSandboxTest, SandboxAccess) {
- using file_util::CreateDirectory;
+ using base::CreateDirectory;
base::FilePath tmp_dir;
- ASSERT_TRUE(file_util::CreateNewTempDirectory("", &tmp_dir));
+ ASSERT_TRUE(base::CreateNewTempDirectory(base::FilePath::StringType(),
+ &tmp_dir));
// This step is important on OS X since the sandbox only understands "real"
// paths and the paths CreateNewTempDirectory() returns are empirically in
// /var which is a symlink to /private/var .
diff --git a/chromium/content/common/sandbox_mac_fontloading_unittest.mm b/chromium/content/common/sandbox_mac_fontloading_unittest.mm
index d78f2f4859e..12853599a40 100644
--- a/chromium/content/common/sandbox_mac_fontloading_unittest.mm
+++ b/chromium/content/common/sandbox_mac_fontloading_unittest.mm
@@ -103,7 +103,7 @@ bool FontLoadingTestCase::SandboxedTest() {
TEST_F(MacSandboxTest, FontLoadingTest) {
base::FilePath temp_file_path;
- FILE* temp_file = file_util::CreateAndOpenTemporaryFile(&temp_file_path);
+ FILE* temp_file = base::CreateAndOpenTemporaryFile(&temp_file_path);
ASSERT_TRUE(temp_file);
file_util::ScopedFILE temp_file_closer(temp_file);
diff --git a/chromium/content/common/sandbox_mac_unittest_helper.h b/chromium/content/common/sandbox_mac_unittest_helper.h
index 6ad90575a7a..a3c06947759 100644
--- a/chromium/content/common/sandbox_mac_unittest_helper.h
+++ b/chromium/content/common/sandbox_mac_unittest_helper.h
@@ -60,7 +60,7 @@ class MacSandboxTest : public base::MultiProcessTest {
// processes.
//
// DANGER DANGER DANGER:
- // Additional sandbox types defined by the embedder (e.g. the NaCL sandbox)
+ // Additional sandbox types defined by the embedder (e.g. the NaCl sandbox)
// won't be covered by these tests.
bool RunTestInAllSandboxTypes(const char* test_name,
const char* test_data);
diff --git a/chromium/content/common/sandbox_seccomp_bpf_linux.cc b/chromium/content/common/sandbox_seccomp_bpf_linux.cc
deleted file mode 100644
index 1ff54e760bc..00000000000
--- a/chromium/content/common/sandbox_seccomp_bpf_linux.cc
+++ /dev/null
@@ -1,2083 +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 <asm/unistd.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/net.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/prctl.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <ucontext.h>
-#include <unistd.h>
-
-#include <vector>
-
-#if defined(__arm__) && !defined(MAP_STACK)
-#define MAP_STACK 0x20000 // Daisy build environment has old headers.
-#endif
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "content/common/sandbox_linux.h"
-#include "content/common/sandbox_seccomp_bpf_linux.h"
-#include "content/public/common/content_switches.h"
-#include "sandbox/linux/services/broker_process.h"
-
-// These are the only architectures supported for now.
-#if defined(__i386__) || defined(__x86_64__) || \
- (defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__)))
-#define SECCOMP_BPF_SANDBOX
-#endif
-
-#if defined(SECCOMP_BPF_SANDBOX)
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
-#include "sandbox/linux/services/linux_syscalls.h"
-
-using playground2::arch_seccomp_data;
-using playground2::ErrorCode;
-using playground2::Sandbox;
-using sandbox::BrokerProcess;
-
-namespace {
-
-void StartSandboxWithPolicy(Sandbox::EvaluateSyscall syscall_policy,
- BrokerProcess* broker_process);
-
-inline bool RunningOnASAN() {
-#if defined(ADDRESS_SANITIZER)
- return true;
-#else
- return false;
-#endif
-}
-
-inline bool IsChromeOS() {
-#if defined(OS_CHROMEOS)
- return true;
-#else
- return false;
-#endif
-}
-
-inline bool IsArchitectureX86_64() {
-#if defined(__x86_64__)
- return true;
-#else
- return false;
-#endif
-}
-
-inline bool IsArchitectureI386() {
-#if defined(__i386__)
- return true;
-#else
- return false;
-#endif
-}
-
-inline bool IsArchitectureArm() {
-#if defined(__arm__)
- return true;
-#else
- return false;
-#endif
-}
-
-inline bool IsUsingToolKitGtk() {
-#if defined(TOOLKIT_GTK)
- return true;
-#else
- return false;
-#endif
-}
-
-// Write |error_message| to stderr. Similar to RawLog(), but a bit more careful
-// about async-signal safety. |size| is the size to write and should typically
-// not include a terminating \0.
-void WriteToStdErr(const char* error_message, size_t size) {
- while (size > 0) {
- // TODO(jln): query the current policy to check if send() is available and
- // use it to perform a non blocking write.
- const int ret = HANDLE_EINTR(write(STDERR_FILENO, error_message, size));
- // We can't handle any type of error here.
- if (ret <= 0 || static_cast<size_t>(ret) > size) break;
- size -= ret;
- error_message += ret;
- }
-}
-
-// Print a seccomp-bpf failure to handle |sysno| to stderr in an
-// async-signal safe way.
-void PrintSyscallError(uint32_t sysno) {
- if (sysno >= 1024)
- sysno = 0;
- // TODO(markus): replace with async-signal safe snprintf when available.
- const size_t kNumDigits = 4;
- char sysno_base10[kNumDigits];
- uint32_t rem = sysno;
- uint32_t mod = 0;
- for (int i = kNumDigits - 1; i >= 0; i--) {
- mod = rem % 10;
- rem /= 10;
- sysno_base10[i] = '0' + mod;
- }
- static const char kSeccompErrorPrefix[] =
- __FILE__":**CRASHING**:seccomp-bpf failure in syscall ";
- static const char kSeccompErrorPostfix[] = "\n";
- WriteToStdErr(kSeccompErrorPrefix, sizeof(kSeccompErrorPrefix) - 1);
- WriteToStdErr(sysno_base10, sizeof(sysno_base10));
- WriteToStdErr(kSeccompErrorPostfix, sizeof(kSeccompErrorPostfix) - 1);
-}
-
-intptr_t CrashSIGSYS_Handler(const struct arch_seccomp_data& args, void* aux) {
- uint32_t syscall = args.nr;
- if (syscall >= 1024)
- syscall = 0;
- PrintSyscallError(syscall);
-
- // Encode 8-bits of the 1st two arguments too, so we can discern which socket
- // type, which fcntl, ... etc., without being likely to hit a mapped
- // address.
- // Do not encode more bits here without thinking about increasing the
- // likelihood of collision with mapped pages.
- syscall |= ((args.args[0] & 0xffUL) << 12);
- syscall |= ((args.args[1] & 0xffUL) << 20);
- // Purposefully dereference the syscall as an address so it'll show up very
- // clearly and easily in crash dumps.
- volatile char* addr = reinterpret_cast<volatile char*>(syscall);
- *addr = '\0';
- // In case we hit a mapped address, hit the null page with just the syscall,
- // for paranoia.
- syscall &= 0xfffUL;
- addr = reinterpret_cast<volatile char*>(syscall);
- *addr = '\0';
- for (;;)
- _exit(1);
-}
-
-// TODO(jln): rewrite reporting functions.
-intptr_t SIGSYSCloneFailure(const struct arch_seccomp_data& args, void* aux) {
- // "flags" in the first argument in the kernel's clone().
- // Mark as volatile to be able to find the value on the stack in a minidump.
-#if !defined(NDEBUG)
- RAW_LOG(ERROR, __FILE__":**CRASHING**:clone() failure\n");
-#endif
- volatile uint64_t clone_flags = args.args[0];
- volatile char* addr;
- if (IsArchitectureX86_64()) {
- addr = reinterpret_cast<volatile char*>(clone_flags & 0xFFFFFF);
- *addr = '\0';
- }
- // Hit the NULL page if this fails to fault.
- addr = reinterpret_cast<volatile char*>(clone_flags & 0xFFF);
- *addr = '\0';
- for (;;)
- _exit(1);
-}
-
-// TODO(jln): rewrite reporting functions.
-intptr_t SIGSYSPrctlFailure(const struct arch_seccomp_data& args,
- void* /* aux */) {
- // Mark as volatile to be able to find the value on the stack in a minidump.
-#if !defined(NDEBUG)
- RAW_LOG(ERROR, __FILE__":**CRASHING**:prctl() failure\n");
-#endif
- volatile uint64_t option = args.args[0];
- volatile char* addr =
- reinterpret_cast<volatile char*>(option & 0xFFF);
- *addr = '\0';
- for (;;)
- _exit(1);
-}
-
-intptr_t SIGSYSIoctlFailure(const struct arch_seccomp_data& args,
- void* /* aux */) {
- // Make "request" volatile so that we can see it on the stack in a minidump.
-#if !defined(NDEBUG)
- RAW_LOG(ERROR, __FILE__":**CRASHING**:ioctl() failure\n");
-#endif
- volatile uint64_t request = args.args[1];
- volatile char* addr = reinterpret_cast<volatile char*>(request & 0xFFFF);
- *addr = '\0';
- // Hit the NULL page if this fails.
- addr = reinterpret_cast<volatile char*>(request & 0xFFF);
- *addr = '\0';
- for (;;)
- _exit(1);
-}
-
-bool IsAcceleratedVideoDecodeEnabled() {
- // Accelerated video decode is currently enabled on Chrome OS,
- // but not on Linux: crbug.com/137247.
- bool is_enabled = IsChromeOS();
-
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- is_enabled = is_enabled &&
- !command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode);
-
- return is_enabled;
-}
-
-intptr_t GpuSIGSYS_Handler(const struct arch_seccomp_data& args,
- void* aux_broker_process) {
- RAW_CHECK(aux_broker_process);
- BrokerProcess* broker_process =
- static_cast<BrokerProcess*>(aux_broker_process);
- switch (args.nr) {
- case __NR_access:
- return broker_process->Access(reinterpret_cast<const char*>(args.args[0]),
- static_cast<int>(args.args[1]));
- case __NR_open:
- return broker_process->Open(reinterpret_cast<const char*>(args.args[0]),
- static_cast<int>(args.args[1]));
- case __NR_openat:
- // Allow using openat() as open().
- if (static_cast<int>(args.args[0]) == AT_FDCWD) {
- return
- broker_process->Open(reinterpret_cast<const char*>(args.args[1]),
- static_cast<int>(args.args[2]));
- } else {
- return -EPERM;
- }
- default:
- RAW_CHECK(false);
- return -ENOSYS;
- }
-}
-
-// The functions below cover all existing i386, x86_64, and ARM system calls;
-// excluding syscalls made obsolete in ARM EABI.
-// The implicitly defined sets form a partition of the sets of
-// system calls.
-
-// TODO(jln) we need to restrict the first parameter!
-bool IsKill(int sysno) {
- switch (sysno) {
- case __NR_kill:
- case __NR_tkill:
- case __NR_tgkill:
- return true;
- default:
- return false;
- }
-}
-
-bool IsAllowedGettime(int sysno) {
- switch (sysno) {
- case __NR_clock_gettime:
- case __NR_gettimeofday:
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_time:
-#endif
- return true;
- case __NR_adjtimex: // Privileged.
- case __NR_clock_adjtime: // Privileged.
- case __NR_clock_getres: // Could be allowed.
- case __NR_clock_nanosleep: // Could be allowed.
- case __NR_clock_settime: // Privileged.
-#if defined(__i386__)
- case __NR_ftime: // Obsolete.
-#endif
- case __NR_settimeofday: // Privileged.
-#if defined(__i386__)
- case __NR_stime:
-#endif
- default:
- return false;
- }
-}
-
-bool IsCurrentDirectory(int sysno) {
- switch (sysno) {
- case __NR_getcwd:
- case __NR_chdir:
- case __NR_fchdir:
- return true;
- default:
- return false;
- }
-}
-
-bool IsUmask(int sysno) {
- switch (sysno) {
- case __NR_umask:
- return true;
- default:
- return false;
- }
-}
-
-// System calls that directly access the file system. They might acquire
-// a new file descriptor or otherwise perform an operation directly
-// via a path.
-// Both EPERM and ENOENT are valid errno unless otherwise noted in comment.
-bool IsFileSystem(int sysno) {
- switch (sysno) {
- case __NR_access: // EPERM not a valid errno.
- case __NR_chmod:
- case __NR_chown:
-#if defined(__i386__) || defined(__arm__)
- case __NR_chown32:
-#endif
- case __NR_creat:
- case __NR_execve:
- case __NR_faccessat: // EPERM not a valid errno.
- case __NR_fchmodat:
- case __NR_fchownat: // Should be called chownat ?
-#if defined(__x86_64__)
- case __NR_newfstatat: // fstatat(). EPERM not a valid errno.
-#elif defined(__i386__) || defined(__arm__)
- case __NR_fstatat64:
-#endif
- case __NR_futimesat: // Should be called utimesat ?
- case __NR_lchown:
-#if defined(__i386__) || defined(__arm__)
- case __NR_lchown32:
-#endif
- case __NR_link:
- case __NR_linkat:
- case __NR_lookup_dcookie: // ENOENT not a valid errno.
- case __NR_lstat: // EPERM not a valid errno.
-#if defined(__i386__)
- case __NR_oldlstat:
-#endif
-#if defined(__i386__) || defined(__arm__)
- case __NR_lstat64:
-#endif
- case __NR_mkdir:
- case __NR_mkdirat:
- case __NR_mknod:
- case __NR_mknodat:
- case __NR_open:
- case __NR_openat:
- case __NR_readlink: // EPERM not a valid errno.
- case __NR_readlinkat:
- case __NR_rename:
- case __NR_renameat:
- case __NR_rmdir:
- case __NR_stat: // EPERM not a valid errno.
-#if defined(__i386__)
- case __NR_oldstat:
-#endif
-#if defined(__i386__) || defined(__arm__)
- case __NR_stat64:
-#endif
- case __NR_statfs: // EPERM not a valid errno.
-#if defined(__i386__) || defined(__arm__)
- case __NR_statfs64:
-#endif
- case __NR_symlink:
- case __NR_symlinkat:
- case __NR_truncate:
-#if defined(__i386__) || defined(__arm__)
- case __NR_truncate64:
-#endif
- case __NR_unlink:
- case __NR_unlinkat:
- case __NR_uselib: // Neither EPERM, nor ENOENT are valid errno.
- case __NR_ustat: // Same as above. Deprecated.
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_utime:
-#endif
- case __NR_utimensat: // New.
- case __NR_utimes:
- return true;
- default:
- return false;
- }
-}
-
-bool IsAllowedFileSystemAccessViaFd(int sysno) {
- switch (sysno) {
- case __NR_fstat:
-#if defined(__i386__) || defined(__arm__)
- case __NR_fstat64:
-#endif
- return true;
- // TODO(jln): these should be denied gracefully as well (moved below).
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_fadvise64: // EPERM not a valid errno.
-#endif
-#if defined(__i386__)
- case __NR_fadvise64_64:
-#endif
-#if defined(__arm__)
- case __NR_arm_fadvise64_64:
-#endif
- case __NR_fdatasync: // EPERM not a valid errno.
- case __NR_flock: // EPERM not a valid errno.
- case __NR_fstatfs: // Give information about the whole filesystem.
-#if defined(__i386__) || defined(__arm__)
- case __NR_fstatfs64:
-#endif
- case __NR_fsync: // EPERM not a valid errno.
-#if defined(__i386__)
- case __NR_oldfstat:
-#endif
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_sync_file_range: // EPERM not a valid errno.
-#elif defined(__arm__)
- case __NR_arm_sync_file_range: // EPERM not a valid errno.
-#endif
- default:
- return false;
- }
-}
-
-// EPERM is a good errno for any of these.
-bool IsDeniedFileSystemAccessViaFd(int sysno) {
- switch (sysno) {
- case __NR_fallocate:
- case __NR_fchmod:
- case __NR_fchown:
- case __NR_ftruncate:
-#if defined(__i386__) || defined(__arm__)
- case __NR_fchown32:
- case __NR_ftruncate64:
-#endif
- case __NR_getdents: // EPERM not a valid errno.
- case __NR_getdents64: // EPERM not a valid errno.
-#if defined(__i386__)
- case __NR_readdir:
-#endif
- return true;
- default:
- return false;
- }
-}
-
-bool IsGetSimpleId(int sysno) {
- switch (sysno) {
- case __NR_capget:
- case __NR_getegid:
- case __NR_geteuid:
- case __NR_getgid:
- case __NR_getgroups:
- case __NR_getpid:
- case __NR_getppid:
- case __NR_getresgid:
- case __NR_getsid:
- case __NR_gettid:
- case __NR_getuid:
- case __NR_getresuid:
-#if defined(__i386__) || defined(__arm__)
- case __NR_getegid32:
- case __NR_geteuid32:
- case __NR_getgid32:
- case __NR_getgroups32:
- case __NR_getresgid32:
- case __NR_getresuid32:
- case __NR_getuid32:
-#endif
- return true;
- default:
- return false;
- }
-}
-
-bool IsProcessPrivilegeChange(int sysno) {
- switch (sysno) {
- case __NR_capset:
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_ioperm: // Intel privilege.
- case __NR_iopl: // Intel privilege.
-#endif
- case __NR_setfsgid:
- case __NR_setfsuid:
- case __NR_setgid:
- case __NR_setgroups:
- case __NR_setregid:
- case __NR_setresgid:
- case __NR_setresuid:
- case __NR_setreuid:
- case __NR_setuid:
-#if defined(__i386__) || defined(__arm__)
- case __NR_setfsgid32:
- case __NR_setfsuid32:
- case __NR_setgid32:
- case __NR_setgroups32:
- case __NR_setregid32:
- case __NR_setresgid32:
- case __NR_setresuid32:
- case __NR_setreuid32:
- case __NR_setuid32:
-#endif
- return true;
- default:
- return false;
- }
-}
-
-bool IsProcessGroupOrSession(int sysno) {
- switch (sysno) {
- case __NR_setpgid:
- case __NR_getpgrp:
- case __NR_setsid:
- case __NR_getpgid:
- return true;
- default:
- return false;
- }
-}
-
-bool IsAllowedSignalHandling(int sysno) {
- switch (sysno) {
- case __NR_rt_sigaction:
- case __NR_rt_sigprocmask:
- case __NR_rt_sigreturn:
-#if defined(__i386__) || defined(__arm__)
- case __NR_sigaction:
- case __NR_sigprocmask:
- case __NR_sigreturn:
-#endif
- return true;
- case __NR_rt_sigpending:
- case __NR_rt_sigqueueinfo:
- case __NR_rt_sigsuspend:
- case __NR_rt_sigtimedwait:
- case __NR_rt_tgsigqueueinfo:
- case __NR_sigaltstack:
- case __NR_signalfd:
- case __NR_signalfd4:
-#if defined(__i386__) || defined(__arm__)
- case __NR_sigpending:
- case __NR_sigsuspend:
-#endif
-#if defined(__i386__)
- case __NR_signal:
- case __NR_sgetmask: // Obsolete.
- case __NR_ssetmask:
-#endif
- default:
- return false;
- }
-}
-
-bool IsAllowedOperationOnFd(int sysno) {
- switch (sysno) {
- case __NR_close:
- case __NR_dup:
- case __NR_dup2:
- case __NR_dup3:
-#if defined(__x86_64__) || defined(__arm__)
- case __NR_shutdown:
-#endif
- return true;
- case __NR_fcntl:
-#if defined(__i386__) || defined(__arm__)
- case __NR_fcntl64:
-#endif
- default:
- return false;
- }
-}
-
-bool IsKernelInternalApi(int sysno) {
- switch (sysno) {
- case __NR_restart_syscall:
-#if defined(__arm__)
- case __ARM_NR_cmpxchg:
-#endif
- return true;
- default:
- return false;
- }
-}
-
-// This should be thought through in conjunction with IsFutex().
-bool IsAllowedProcessStartOrDeath(int sysno) {
- switch (sysno) {
- case __NR_clone: // TODO(jln): restrict flags.
- case __NR_exit:
- case __NR_exit_group:
- case __NR_wait4:
- case __NR_waitid:
-#if defined(__i386__)
- case __NR_waitpid:
-#endif
- return true;
- case __NR_setns: // Privileged.
- case __NR_fork:
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_get_thread_area:
- case __NR_set_thread_area:
-#endif
- case __NR_set_tid_address:
- case __NR_unshare:
- case __NR_vfork:
- default:
- return false;
- }
-}
-
-// It's difficult to restrict those, but there is attack surface here.
-bool IsFutex(int sysno) {
- switch (sysno) {
- case __NR_futex:
- case __NR_get_robust_list:
- case __NR_set_robust_list:
- return true;
- default:
- return false;
- }
-}
-
-bool IsAllowedEpoll(int sysno) {
- switch (sysno) {
- case __NR_epoll_create:
- case __NR_epoll_create1:
- case __NR_epoll_ctl:
- case __NR_epoll_wait:
- return true;
- default:
-#if defined(__x86_64__)
- case __NR_epoll_ctl_old:
-#endif
- case __NR_epoll_pwait:
-#if defined(__x86_64__)
- case __NR_epoll_wait_old:
-#endif
- return false;
- }
-}
-
-bool IsAllowedGetOrModifySocket(int sysno) {
- switch (sysno) {
- case __NR_pipe:
- case __NR_pipe2:
- return true;
- default:
-#if defined(__x86_64__) || defined(__arm__)
- case __NR_socketpair: // We will want to inspect its argument.
-#endif
- return false;
- }
-}
-
-bool IsDeniedGetOrModifySocket(int sysno) {
- switch (sysno) {
-#if defined(__x86_64__) || defined(__arm__)
- case __NR_accept:
- case __NR_accept4:
- case __NR_bind:
- case __NR_connect:
- case __NR_socket:
- case __NR_listen:
- return true;
-#endif
- default:
- return false;
- }
-}
-
-#if defined(__i386__)
-// Big multiplexing system call for sockets.
-bool IsSocketCall(int sysno) {
- switch (sysno) {
- case __NR_socketcall:
- return true;
- default:
- return false;
- }
-}
-#endif
-
-#if defined(__x86_64__) || defined(__arm__)
-bool IsNetworkSocketInformation(int sysno) {
- switch (sysno) {
- case __NR_getpeername:
- case __NR_getsockname:
- case __NR_getsockopt:
- case __NR_setsockopt:
- return true;
- default:
- return false;
- }
-}
-#endif
-
-bool IsAllowedAddressSpaceAccess(int sysno) {
- switch (sysno) {
- case __NR_brk:
- case __NR_mlock:
- case __NR_munlock:
- case __NR_munmap:
- return true;
- case __NR_madvise:
- case __NR_mincore:
- case __NR_mlockall:
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_mmap:
-#endif
-#if defined(__i386__) || defined(__arm__)
- case __NR_mmap2:
-#endif
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_modify_ldt:
-#endif
- case __NR_mprotect:
- case __NR_mremap:
- case __NR_msync:
- case __NR_munlockall:
- case __NR_readahead:
- case __NR_remap_file_pages:
-#if defined(__i386__)
- case __NR_vm86:
- case __NR_vm86old:
-#endif
- default:
- return false;
- }
-}
-
-bool IsAllowedGeneralIo(int sysno) {
- switch (sysno) {
- case __NR_lseek:
-#if defined(__i386__) || defined(__arm__)
- case __NR__llseek:
-#endif
- case __NR_poll:
- case __NR_ppoll:
- case __NR_pselect6:
- case __NR_read:
- case __NR_readv:
-#if defined(__arm__)
- case __NR_recv:
-#endif
-#if defined(__x86_64__) || defined(__arm__)
- case __NR_recvfrom: // Could specify source.
- case __NR_recvmsg: // Could specify source.
-#endif
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_select:
-#endif
-#if defined(__i386__) || defined(__arm__)
- case __NR__newselect:
-#endif
-#if defined(__arm__)
- case __NR_send:
-#endif
-#if defined(__x86_64__) || defined(__arm__)
- case __NR_sendmsg: // Could specify destination.
- case __NR_sendto: // Could specify destination.
-#endif
- case __NR_write:
- case __NR_writev:
- return true;
- case __NR_ioctl: // Can be very powerful.
- case __NR_pread64:
- case __NR_preadv:
- case __NR_pwrite64:
- case __NR_pwritev:
- case __NR_recvmmsg: // Could specify source.
- case __NR_sendfile:
-#if defined(__i386__) || defined(__arm__)
- case __NR_sendfile64:
-#endif
- case __NR_sendmmsg: // Could specify destination.
- case __NR_splice:
- case __NR_tee:
- case __NR_vmsplice:
- default:
- return false;
- }
-}
-
-bool IsAllowedPrctl(int sysno) {
- switch (sysno) {
- case __NR_prctl:
- return true;
- default:
-#if defined(__x86_64__)
- case __NR_arch_prctl:
-#endif
- return false;
- }
-}
-
-bool IsAllowedBasicScheduler(int sysno) {
- switch (sysno) {
- case __NR_sched_yield:
- case __NR_pause:
- case __NR_nanosleep:
- return true;
- case __NR_getpriority:
-#if defined(__i386__) || defined(__arm__)
- case __NR_nice:
-#endif
- case __NR_setpriority:
- default:
- return false;
- }
-}
-
-bool IsAdminOperation(int sysno) {
- switch (sysno) {
-#if defined(__i386__) || defined(__arm__)
- case __NR_bdflush:
-#endif
- case __NR_kexec_load:
- case __NR_reboot:
- case __NR_setdomainname:
- case __NR_sethostname:
- case __NR_syslog:
- return true;
- default:
- return false;
- }
-}
-
-bool IsKernelModule(int sysno) {
- switch (sysno) {
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_create_module:
- case __NR_get_kernel_syms: // Should ENOSYS.
- case __NR_query_module:
-#endif
- case __NR_delete_module:
- case __NR_init_module:
- return true;
- default:
- return false;
- }
-}
-
-bool IsGlobalFSViewChange(int sysno) {
- switch (sysno) {
- case __NR_pivot_root:
- case __NR_chroot:
- case __NR_sync:
- return true;
- default:
- return false;
- }
-}
-
-bool IsFsControl(int sysno) {
- switch (sysno) {
- case __NR_mount:
- case __NR_nfsservctl:
- case __NR_quotactl:
- case __NR_swapoff:
- case __NR_swapon:
-#if defined(__i386__)
- case __NR_umount:
-#endif
- case __NR_umount2:
- return true;
- default:
- return false;
- }
-}
-
-bool IsNuma(int sysno) {
- switch (sysno) {
- case __NR_get_mempolicy:
- case __NR_getcpu:
- case __NR_mbind:
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_migrate_pages:
-#endif
- case __NR_move_pages:
- case __NR_set_mempolicy:
- return true;
- default:
- return false;
- }
-}
-
-bool IsMessageQueue(int sysno) {
- switch (sysno) {
- case __NR_mq_getsetattr:
- case __NR_mq_notify:
- case __NR_mq_open:
- case __NR_mq_timedreceive:
- case __NR_mq_timedsend:
- case __NR_mq_unlink:
- return true;
- default:
- return false;
- }
-}
-
-bool IsGlobalProcessEnvironment(int sysno) {
- switch (sysno) {
- case __NR_acct: // Privileged.
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_getrlimit:
-#endif
-#if defined(__i386__) || defined(__arm__)
- case __NR_ugetrlimit:
-#endif
-#if defined(__i386__)
- case __NR_ulimit:
-#endif
- case __NR_getrusage:
- case __NR_personality: // Can change its personality as well.
- case __NR_prlimit64: // Like setrlimit / getrlimit.
- case __NR_setrlimit:
- case __NR_times:
- return true;
- default:
- return false;
- }
-}
-
-bool IsDebug(int sysno) {
- switch (sysno) {
- case __NR_ptrace:
- case __NR_process_vm_readv:
- case __NR_process_vm_writev:
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_kcmp:
-#endif
- return true;
- default:
- return false;
- }
-}
-
-bool IsGlobalSystemStatus(int sysno) {
- switch (sysno) {
- case __NR__sysctl:
- case __NR_sysfs:
- case __NR_sysinfo:
- case __NR_uname:
-#if defined(__i386__)
- case __NR_olduname:
- case __NR_oldolduname:
-#endif
- return true;
- default:
- return false;
- }
-}
-
-bool IsEventFd(int sysno) {
- switch (sysno) {
- case __NR_eventfd:
- case __NR_eventfd2:
- return true;
- default:
- return false;
- }
-}
-
-// Asynchronous I/O API.
-bool IsAsyncIo(int sysno) {
- switch (sysno) {
- case __NR_io_cancel:
- case __NR_io_destroy:
- case __NR_io_getevents:
- case __NR_io_setup:
- case __NR_io_submit:
- return true;
- default:
- return false;
- }
-}
-
-bool IsKeyManagement(int sysno) {
- switch (sysno) {
- case __NR_add_key:
- case __NR_keyctl:
- case __NR_request_key:
- return true;
- default:
- return false;
- }
-}
-
-#if defined(__x86_64__) || defined(__arm__)
-bool IsSystemVSemaphores(int sysno) {
- switch (sysno) {
- case __NR_semctl:
- case __NR_semget:
- case __NR_semop:
- case __NR_semtimedop:
- return true;
- default:
- return false;
- }
-}
-#endif
-
-#if defined(__x86_64__) || defined(__arm__)
-// These give a lot of ambient authority and bypass the setuid sandbox.
-bool IsSystemVSharedMemory(int sysno) {
- switch (sysno) {
- case __NR_shmat:
- case __NR_shmctl:
- case __NR_shmdt:
- case __NR_shmget:
- return true;
- default:
- return false;
- }
-}
-#endif
-
-#if defined(__x86_64__) || defined(__arm__)
-bool IsSystemVMessageQueue(int sysno) {
- switch (sysno) {
- case __NR_msgctl:
- case __NR_msgget:
- case __NR_msgrcv:
- case __NR_msgsnd:
- return true;
- default:
- return false;
- }
-}
-#endif
-
-#if defined(__i386__)
-// Big system V multiplexing system call.
-bool IsSystemVIpc(int sysno) {
- switch (sysno) {
- case __NR_ipc:
- return true;
- default:
- return false;
- }
-}
-#endif
-
-bool IsAnySystemV(int sysno) {
-#if defined(__x86_64__) || defined(__arm__)
- return IsSystemVMessageQueue(sysno) ||
- IsSystemVSemaphores(sysno) ||
- IsSystemVSharedMemory(sysno);
-#elif defined(__i386__)
- return IsSystemVIpc(sysno);
-#endif
-}
-
-bool IsAdvancedScheduler(int sysno) {
- switch (sysno) {
- case __NR_ioprio_get: // IO scheduler.
- case __NR_ioprio_set:
- case __NR_sched_get_priority_max:
- case __NR_sched_get_priority_min:
- case __NR_sched_getaffinity:
- case __NR_sched_getparam:
- case __NR_sched_getscheduler:
- case __NR_sched_rr_get_interval:
- case __NR_sched_setaffinity:
- case __NR_sched_setparam:
- case __NR_sched_setscheduler:
- return true;
- default:
- return false;
- }
-}
-
-bool IsInotify(int sysno) {
- switch (sysno) {
- case __NR_inotify_add_watch:
- case __NR_inotify_init:
- case __NR_inotify_init1:
- case __NR_inotify_rm_watch:
- return true;
- default:
- return false;
- }
-}
-
-bool IsFaNotify(int sysno) {
- switch (sysno) {
- case __NR_fanotify_init:
- case __NR_fanotify_mark:
- return true;
- default:
- return false;
- }
-}
-
-bool IsTimer(int sysno) {
- switch (sysno) {
- case __NR_getitimer:
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_alarm:
-#endif
- case __NR_setitimer:
- return true;
- default:
- return false;
- }
-}
-
-bool IsAdvancedTimer(int sysno) {
- switch (sysno) {
- case __NR_timer_create:
- case __NR_timer_delete:
- case __NR_timer_getoverrun:
- case __NR_timer_gettime:
- case __NR_timer_settime:
- case __NR_timerfd_create:
- case __NR_timerfd_gettime:
- case __NR_timerfd_settime:
- return true;
- default:
- return false;
- }
-}
-
-bool IsExtendedAttributes(int sysno) {
- switch (sysno) {
- case __NR_fgetxattr:
- case __NR_flistxattr:
- case __NR_fremovexattr:
- case __NR_fsetxattr:
- case __NR_getxattr:
- case __NR_lgetxattr:
- case __NR_listxattr:
- case __NR_llistxattr:
- case __NR_lremovexattr:
- case __NR_lsetxattr:
- case __NR_removexattr:
- case __NR_setxattr:
- return true;
- default:
- return false;
- }
-}
-
-// Various system calls that need to be researched.
-// TODO(jln): classify this better.
-bool IsMisc(int sysno) {
- switch (sysno) {
- case __NR_name_to_handle_at:
- case __NR_open_by_handle_at:
- case __NR_perf_event_open:
- case __NR_syncfs:
- case __NR_vhangup:
- // The system calls below are not implemented.
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_afs_syscall:
-#endif
-#if defined(__i386__)
- case __NR_break:
-#endif
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_getpmsg:
-#endif
-#if defined(__i386__)
- case __NR_gtty:
- case __NR_idle:
- case __NR_lock:
- case __NR_mpx:
- case __NR_prof:
- case __NR_profil:
-#endif
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_putpmsg:
-#endif
-#if defined(__x86_64__)
- case __NR_security:
-#endif
-#if defined(__i386__)
- case __NR_stty:
-#endif
-#if defined(__x86_64__)
- case __NR_tuxcall:
-#endif
- case __NR_vserver:
- return true;
- default:
- return false;
- }
-}
-
-#if defined(__arm__)
-bool IsArmPciConfig(int sysno) {
- switch (sysno) {
- case __NR_pciconfig_iobase:
- case __NR_pciconfig_read:
- case __NR_pciconfig_write:
- return true;
- default:
- return false;
- }
-}
-
-bool IsArmPrivate(int sysno) {
- switch (sysno) {
- case __ARM_NR_breakpoint:
- case __ARM_NR_cacheflush:
- case __ARM_NR_set_tls:
- case __ARM_NR_usr26:
- case __ARM_NR_usr32:
- return true;
- default:
- return false;
- }
-}
-#endif // defined(__arm__)
-
-// End of the system call sets section.
-
-bool IsBaselinePolicyAllowed(int sysno) {
- if (IsAllowedAddressSpaceAccess(sysno) ||
- IsAllowedBasicScheduler(sysno) ||
- IsAllowedEpoll(sysno) ||
- IsAllowedFileSystemAccessViaFd(sysno) ||
- IsAllowedGeneralIo(sysno) ||
- IsAllowedGetOrModifySocket(sysno) ||
- IsAllowedGettime(sysno) ||
- IsAllowedPrctl(sysno) ||
- IsAllowedProcessStartOrDeath(sysno) ||
- IsAllowedSignalHandling(sysno) ||
- IsFutex(sysno) ||
- IsGetSimpleId(sysno) ||
- IsKernelInternalApi(sysno) ||
-#if defined(__arm__)
- IsArmPrivate(sysno) ||
-#endif
- IsKill(sysno) ||
- IsAllowedOperationOnFd(sysno)) {
- return true;
- } else {
- return false;
- }
-}
-
-// System calls that will trigger the crashing SIGSYS handler.
-bool IsBaselinePolicyWatched(int sysno) {
- if (IsAdminOperation(sysno) ||
- IsAdvancedScheduler(sysno) ||
- IsAdvancedTimer(sysno) ||
- IsAsyncIo(sysno) ||
- IsDebug(sysno) ||
- IsEventFd(sysno) ||
- IsExtendedAttributes(sysno) ||
- IsFaNotify(sysno) ||
- IsFsControl(sysno) ||
- IsGlobalFSViewChange(sysno) ||
- IsGlobalProcessEnvironment(sysno) ||
- IsGlobalSystemStatus(sysno) ||
- IsInotify(sysno) ||
- IsKernelModule(sysno) ||
- IsKeyManagement(sysno) ||
- IsMessageQueue(sysno) ||
- IsMisc(sysno) ||
-#if defined(__x86_64__)
- IsNetworkSocketInformation(sysno) ||
-#endif
- IsNuma(sysno) ||
- IsProcessGroupOrSession(sysno) ||
- IsProcessPrivilegeChange(sysno) ||
-#if defined(__i386__)
- IsSocketCall(sysno) || // We'll need to handle this properly to build
- // a x86_32 policy.
-#endif
-#if defined(__arm__)
- IsArmPciConfig(sysno) ||
-#endif
- IsTimer(sysno)) {
- return true;
- } else {
- return false;
- }
-}
-
-ErrorCode RestrictMmapFlags(Sandbox* sandbox) {
- // The flags you see are actually the allowed ones, and the variable is a
- // "denied" mask because of the negation operator.
- // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as
- // MAP_POPULATE.
- // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries.
- uint32_t denied_mask = ~(MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS |
- MAP_STACK | MAP_NORESERVE | MAP_FIXED |
- MAP_DENYWRITE);
- return sandbox->Cond(3, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
- denied_mask,
- sandbox->Trap(CrashSIGSYS_Handler, NULL),
- ErrorCode(ErrorCode::ERR_ALLOWED));
-}
-
-ErrorCode RestrictMprotectFlags(Sandbox* sandbox) {
- // The flags you see are actually the allowed ones, and the variable is a
- // "denied" mask because of the negation operator.
- // Significantly, we don't permit weird undocumented flags such as
- // PROT_GROWSDOWN.
- uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC);
- return sandbox->Cond(2, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
- denied_mask,
- sandbox->Trap(CrashSIGSYS_Handler, NULL),
- ErrorCode(ErrorCode::ERR_ALLOWED));
-}
-
-ErrorCode RestrictFcntlCommands(Sandbox* sandbox) {
- // We allow F_GETFL, F_SETFL, F_GETFD, F_SETFD, F_DUPFD, F_DUPFD_CLOEXEC,
- // F_SETLK, F_SETLKW and F_GETLK.
- // We also restrict the flags in F_SETFL. We don't want to permit flags with
- // a history of trouble such as O_DIRECT. The flags you see are actually the
- // allowed ones, and the variable is a "denied" mask because of the negation
- // operator.
- // Glibc overrides the kernel's O_LARGEFILE value. Account for this.
- int kOLargeFileFlag = O_LARGEFILE;
- if (IsArchitectureX86_64() || IsArchitectureI386())
- kOLargeFileFlag = 0100000;
-
- // TODO(jln): add TP_LONG/TP_SIZET types.
- ErrorCode::ArgType mask_long_type;
- if (sizeof(long) == 8)
- mask_long_type = ErrorCode::TP_64BIT;
- else if (sizeof(long) == 4)
- mask_long_type = ErrorCode::TP_32BIT;
- else
- NOTREACHED();
-
- unsigned long denied_mask = ~(O_ACCMODE | O_APPEND | O_NONBLOCK | O_SYNC |
- kOLargeFileFlag | O_CLOEXEC | O_NOATIME);
- return sandbox->Cond(1, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, F_GETFL,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(1, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, F_SETFL,
- sandbox->Cond(2, mask_long_type,
- ErrorCode::OP_HAS_ANY_BITS, denied_mask,
- sandbox->Trap(CrashSIGSYS_Handler, NULL),
- ErrorCode(ErrorCode::ERR_ALLOWED)),
- sandbox->Cond(1, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, F_GETFD,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(1, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, F_SETFD,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(1, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, F_DUPFD,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(1, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, F_SETLK,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(1, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, F_SETLKW,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(1, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, F_GETLK,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(1, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, F_DUPFD_CLOEXEC,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Trap(CrashSIGSYS_Handler, NULL))))))))));
-}
-
-#if defined(__i386__)
-ErrorCode RestrictSocketcallCommand(Sandbox* sandbox) {
- // Allow the same individual syscalls as we do on ARM or x86_64.
- // The main difference is that we're unable to restrict the first parameter
- // to socketpair(2). Whilst initially sounding bad, it's noteworthy that very
- // few protocols actually support socketpair(2). The scary call that we're
- // worried about, socket(2), remains blocked.
- return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- SYS_SOCKETPAIR, ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- SYS_SEND, ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- SYS_RECV, ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- SYS_SENDTO, ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- SYS_RECVFROM, ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- SYS_SHUTDOWN, ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- SYS_SENDMSG, ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- SYS_RECVMSG, ErrorCode(ErrorCode::ERR_ALLOWED),
- ErrorCode(EPERM)))))))));
-}
-#endif
-
-ErrorCode BaselinePolicy(Sandbox* sandbox, int sysno) {
- if (IsBaselinePolicyAllowed(sysno)) {
- return ErrorCode(ErrorCode::ERR_ALLOWED);
- }
-
-#if defined(__x86_64__) || defined(__arm__)
- if (sysno == __NR_socketpair) {
- // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
- COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different);
- return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, AF_UNIX,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Trap(CrashSIGSYS_Handler, NULL));
- }
-#endif
-
- if (sysno == __NR_madvise) {
- // Only allow MADV_DONTNEED (aka MADV_FREE).
- return sandbox->Cond(2, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, MADV_DONTNEED,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- ErrorCode(EPERM));
- }
-
-#if defined(__i386__) || defined(__x86_64__)
- if (sysno == __NR_mmap)
- return RestrictMmapFlags(sandbox);
-#endif
-
-#if defined(__i386__) || defined(__arm__)
- if (sysno == __NR_mmap2)
- return RestrictMmapFlags(sandbox);
-#endif
-
- if (sysno == __NR_mprotect)
- return RestrictMprotectFlags(sandbox);
-
- if (sysno == __NR_fcntl)
- return RestrictFcntlCommands(sandbox);
-
-#if defined(__i386__) || defined(__arm__)
- if (sysno == __NR_fcntl64)
- return RestrictFcntlCommands(sandbox);
-#endif
-
- if (IsFileSystem(sysno) || IsCurrentDirectory(sysno)) {
- return ErrorCode(EPERM);
- }
-
- if (IsAnySystemV(sysno)) {
- return ErrorCode(EPERM);
- }
-
- if (IsUmask(sysno) || IsDeniedFileSystemAccessViaFd(sysno) ||
- IsDeniedGetOrModifySocket(sysno)) {
- return ErrorCode(EPERM);
- }
-
-#if defined(__i386__)
- if (IsSocketCall(sysno))
- return RestrictSocketcallCommand(sandbox);
-#endif
-
- if (IsBaselinePolicyWatched(sysno)) {
- // Previously unseen syscalls. TODO(jln): some of these should
- // be denied gracefully right away.
- return sandbox->Trap(CrashSIGSYS_Handler, NULL);
- }
- // In any other case crash the program with our SIGSYS handler.
- return sandbox->Trap(CrashSIGSYS_Handler, NULL);
-}
-
-// The BaselinePolicy only takes two arguments. BaselinePolicyWithAux
-// allows us to conform to the BPF compiler's policy type.
-ErrorCode BaselinePolicyWithAux(Sandbox* sandbox, int sysno, void* aux) {
- CHECK(!aux);
- return BaselinePolicy(sandbox, sysno);
-}
-
-// Main policy for x86_64/i386. Extended by ArmGpuProcessPolicy.
-ErrorCode GpuProcessPolicy(Sandbox* sandbox, int sysno,
- void* broker_process) {
- switch (sysno) {
- case __NR_ioctl:
-#if defined(__i386__) || defined(__x86_64__)
- // The Nvidia driver uses flags not in the baseline policy
- // (MAP_LOCKED | MAP_EXECUTABLE | MAP_32BIT)
- case __NR_mmap:
-#endif
- // We also hit this on the linux_chromeos bot but don't yet know what
- // weird flags were involved.
- case __NR_mprotect:
- case __NR_sched_getaffinity:
- case __NR_sched_setaffinity:
- case __NR_setpriority:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
- case __NR_access:
- case __NR_open:
- case __NR_openat:
- return sandbox->Trap(GpuSIGSYS_Handler, broker_process);
- default:
- if (IsEventFd(sysno))
- return ErrorCode(ErrorCode::ERR_ALLOWED);
-
- // Default on the baseline policy.
- return BaselinePolicy(sandbox, sysno);
- }
-}
-
-// x86_64/i386.
-// A GPU broker policy is the same as a GPU policy with open and
-// openat allowed.
-ErrorCode GpuBrokerProcessPolicy(Sandbox* sandbox, int sysno, void* aux) {
- // "aux" would typically be NULL, when called from
- // "EnableGpuBrokerPolicyCallBack"
- switch (sysno) {
- case __NR_access:
- case __NR_open:
- case __NR_openat:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
- default:
- return GpuProcessPolicy(sandbox, sysno, aux);
- }
-}
-
-// Generic ARM GPU process sandbox, inheriting from GpuProcessPolicy.
-ErrorCode ArmGpuProcessPolicy(Sandbox* sandbox, int sysno,
- void* broker_process) {
- switch (sysno) {
-#if defined(__arm__)
- // ARM GPU sandbox is started earlier so we need to allow networking
- // in the sandbox.
- case __NR_connect:
- case __NR_getpeername:
- case __NR_getsockname:
- case __NR_sysinfo:
- case __NR_uname:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
- // Allow only AF_UNIX for |domain|.
- case __NR_socket:
- case __NR_socketpair:
- return sandbox->Cond(0, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, AF_UNIX,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- ErrorCode(EPERM));
-#endif // defined(__arm__)
- default:
- if (IsAdvancedScheduler(sysno))
- return ErrorCode(ErrorCode::ERR_ALLOWED);
-
- // Default to the generic GPU policy.
- return GpuProcessPolicy(sandbox, sysno, broker_process);
- }
-}
-
-// Same as above but with shmat allowed, inheriting from GpuProcessPolicy.
-ErrorCode ArmGpuProcessPolicyWithShmat(Sandbox* sandbox, int sysno,
- void* broker_process) {
-#if defined(__arm__)
- if (sysno == __NR_shmat)
- return ErrorCode(ErrorCode::ERR_ALLOWED);
-#endif // defined(__arm__)
-
- return ArmGpuProcessPolicy(sandbox, sysno, broker_process);
-}
-
-// A GPU broker policy is the same as a GPU policy with open and
-// openat allowed.
-ErrorCode ArmGpuBrokerProcessPolicy(Sandbox* sandbox,
- int sysno, void* aux) {
- // "aux" would typically be NULL, when called from
- // "EnableGpuBrokerPolicyCallBack"
- switch (sysno) {
- case __NR_access:
- case __NR_open:
- case __NR_openat:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
- default:
- return ArmGpuProcessPolicy(sandbox, sysno, aux);
- }
-}
-
-// Allow clone(2) for threads.
-// Reject fork(2) attempts with EPERM.
-// Crash if anything else is attempted.
-// Don't restrict on ASAN.
-ErrorCode RestrictCloneToThreadsAndEPERMFork(Sandbox* sandbox) {
- // Glibc's pthread.
- if (!RunningOnASAN()) {
- return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
- CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS |
- CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- CLONE_PARENT_SETTID | SIGCHLD,
- ErrorCode(EPERM),
- // ARM
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,
- ErrorCode(EPERM),
- sandbox->Trap(SIGSYSCloneFailure, NULL))));
- } else {
- return ErrorCode(ErrorCode::ERR_ALLOWED);
- }
-}
-
-ErrorCode RestrictPrctl(Sandbox* sandbox) {
- // Allow PR_SET_NAME, PR_SET_DUMPABLE, PR_GET_DUMPABLE. Will need to add
- // seccomp compositing in the future.
- // PR_SET_PTRACER is used by breakpad but not needed anymore.
- return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- PR_SET_NAME, ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- PR_SET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- PR_GET_DUMPABLE, ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Trap(SIGSYSPrctlFailure, NULL))));
-}
-
-ErrorCode RestrictIoctl(Sandbox* sandbox) {
- // Allow TCGETS and FIONREAD, trap to SIGSYSIoctlFailure otherwise.
- return sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, TCGETS,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, FIONREAD,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- sandbox->Trap(SIGSYSIoctlFailure, NULL)));
-}
-
-ErrorCode RendererOrWorkerProcessPolicy(Sandbox* sandbox, int sysno, void*) {
- switch (sysno) {
- case __NR_clone:
- return RestrictCloneToThreadsAndEPERMFork(sandbox);
- case __NR_ioctl:
- return RestrictIoctl(sandbox);
- case __NR_prctl:
- return RestrictPrctl(sandbox);
- // Allow the system calls below.
- case __NR_fdatasync:
- case __NR_fsync:
- case __NR_getpriority:
-#if defined(__i386__) || defined(__x86_64__)
- case __NR_getrlimit:
-#endif
-#if defined(__i386__) || defined(__arm__)
- case __NR_ugetrlimit:
-#endif
- case __NR_mremap: // See crbug.com/149834.
- case __NR_pread64:
- case __NR_pwrite64:
- case __NR_sched_getaffinity:
- case __NR_sched_get_priority_max:
- case __NR_sched_get_priority_min:
- case __NR_sched_getparam:
- case __NR_sched_getscheduler:
- case __NR_sched_setscheduler:
- case __NR_setpriority:
- case __NR_sysinfo:
- case __NR_times:
- case __NR_uname:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
- case __NR_prlimit64:
- return ErrorCode(EPERM); // See crbug.com/160157.
- default:
- if (IsUsingToolKitGtk()) {
-#if defined(__x86_64__) || defined(__arm__)
- if (IsSystemVSharedMemory(sysno))
- return ErrorCode(ErrorCode::ERR_ALLOWED);
-#endif
-#if defined(__i386__)
- if (IsSystemVIpc(sysno))
- return ErrorCode(ErrorCode::ERR_ALLOWED);
-#endif
- }
-
- // Default on the baseline policy.
- return BaselinePolicy(sandbox, sysno);
- }
-}
-
-ErrorCode FlashProcessPolicy(Sandbox* sandbox, int sysno, void*) {
- switch (sysno) {
- case __NR_clone:
- return RestrictCloneToThreadsAndEPERMFork(sandbox);
- case __NR_pread64:
- case __NR_pwrite64:
- case __NR_sched_get_priority_max:
- case __NR_sched_get_priority_min:
- case __NR_sched_getaffinity:
- case __NR_sched_getparam:
- case __NR_sched_getscheduler:
- case __NR_sched_setscheduler:
- case __NR_times:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
- case __NR_ioctl:
- return ErrorCode(ENOTTY); // Flash Access.
- default:
- if (IsUsingToolKitGtk()) {
-#if defined(__x86_64__) || defined(__arm__)
- if (IsSystemVSharedMemory(sysno))
- return ErrorCode(ErrorCode::ERR_ALLOWED);
-#endif
-#if defined(__i386__)
- if (IsSystemVIpc(sysno))
- return ErrorCode(ErrorCode::ERR_ALLOWED);
-#endif
- }
-
- // Default on the baseline policy.
- return BaselinePolicy(sandbox, sysno);
- }
-}
-
-ErrorCode BlacklistDebugAndNumaPolicy(Sandbox* sandbox, int sysno, void*) {
- if (!Sandbox::IsValidSyscallNumber(sysno)) {
- // TODO(jln) we should not have to do that in a trivial policy.
- return ErrorCode(ENOSYS);
- }
-
- if (IsDebug(sysno) || IsNuma(sysno))
- return sandbox->Trap(CrashSIGSYS_Handler, NULL);
-
- return ErrorCode(ErrorCode::ERR_ALLOWED);
-}
-
-// Allow all syscalls.
-// This will still deny x32 or IA32 calls in 64 bits mode or
-// 64 bits system calls in compatibility mode.
-ErrorCode AllowAllPolicy(Sandbox*, int sysno, void*) {
- if (!Sandbox::IsValidSyscallNumber(sysno)) {
- // TODO(jln) we should not have to do that in a trivial policy.
- return ErrorCode(ENOSYS);
- } else {
- return ErrorCode(ErrorCode::ERR_ALLOWED);
- }
-}
-
-// If a BPF policy is engaged for |process_type|, run a few sanity checks.
-void RunSandboxSanityChecks(const std::string& process_type) {
- if (process_type == switches::kRendererProcess ||
- process_type == switches::kWorkerProcess ||
- process_type == switches::kGpuProcess ||
- process_type == switches::kPpapiPluginProcess) {
- int syscall_ret;
- errno = 0;
-
- // Without the sandbox, this would EBADF.
- syscall_ret = fchmod(-1, 07777);
- CHECK_EQ(-1, syscall_ret);
- CHECK_EQ(EPERM, errno);
-
- // Run most of the sanity checks only in DEBUG mode to avoid a perf.
- // impact.
-#if !defined(NDEBUG)
- // open() must be restricted.
- syscall_ret = open("/etc/passwd", O_RDONLY);
- CHECK_EQ(-1, syscall_ret);
- CHECK_EQ(EPERM, errno);
-
- // We should never allow the creation of netlink sockets.
- syscall_ret = socket(AF_NETLINK, SOCK_DGRAM, 0);
- CHECK_EQ(-1, syscall_ret);
- CHECK_EQ(EPERM, errno);
-#endif // !defined(NDEBUG)
- }
-}
-
-bool EnableGpuBrokerPolicyCallback() {
- StartSandboxWithPolicy(GpuBrokerProcessPolicy, NULL);
- return true;
-}
-
-bool EnableArmGpuBrokerPolicyCallback() {
- StartSandboxWithPolicy(ArmGpuBrokerProcessPolicy, NULL);
- return true;
-}
-
-// Files needed by the ARM GPU userspace.
-static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2";
-static const char kLibEglPath[] = "/usr/lib/libEGL.so.1";
-
-void AddArmMaliGpuWhitelist(std::vector<std::string>* read_whitelist,
- std::vector<std::string>* write_whitelist) {
- // Device file needed by the ARM GPU userspace.
- static const char kMali0Path[] = "/dev/mali0";
-
- // Devices needed for video decode acceleration on ARM.
- static const char kDevMfcDecPath[] = "/dev/mfc-dec";
- static const char kDevGsc1Path[] = "/dev/gsc1";
-
- // Devices needed for video encode acceleration on ARM.
- static const char kDevMfcEncPath[] = "/dev/mfc-enc";
-
- read_whitelist->push_back(kMali0Path);
- read_whitelist->push_back(kDevMfcDecPath);
- read_whitelist->push_back(kDevGsc1Path);
- read_whitelist->push_back(kDevMfcEncPath);
-
- write_whitelist->push_back(kMali0Path);
- write_whitelist->push_back(kDevMfcDecPath);
- write_whitelist->push_back(kDevGsc1Path);
- write_whitelist->push_back(kDevMfcEncPath);
-}
-
-void AddArmTegraGpuWhitelist(std::vector<std::string>* read_whitelist,
- std::vector<std::string>* write_whitelist) {
- // Device files needed by the Tegra GPU userspace.
- static const char kDevNvhostCtrlPath[] = "/dev/nvhost-ctrl";
- static const char kDevNvhostGr2dPath[] = "/dev/nvhost-gr2d";
- static const char kDevNvhostGr3dPath[] = "/dev/nvhost-gr3d";
- static const char kDevNvhostIspPath[] = "/dev/nvhost-isp";
- static const char kDevNvhostViPath[] = "/dev/nvhost-vi";
- static const char kDevNvmapPath[] = "/dev/nvmap";
- static const char kDevTegraSemaPath[] = "/dev/tegra_sema";
-
- read_whitelist->push_back(kDevNvhostCtrlPath);
- read_whitelist->push_back(kDevNvhostGr2dPath);
- read_whitelist->push_back(kDevNvhostGr3dPath);
- read_whitelist->push_back(kDevNvhostIspPath);
- read_whitelist->push_back(kDevNvhostViPath);
- read_whitelist->push_back(kDevNvmapPath);
- read_whitelist->push_back(kDevTegraSemaPath);
-
- write_whitelist->push_back(kDevNvhostCtrlPath);
- write_whitelist->push_back(kDevNvhostGr2dPath);
- write_whitelist->push_back(kDevNvhostGr3dPath);
- write_whitelist->push_back(kDevNvhostIspPath);
- write_whitelist->push_back(kDevNvhostViPath);
- write_whitelist->push_back(kDevNvmapPath);
- write_whitelist->push_back(kDevTegraSemaPath);
-}
-
-void AddArmGpuWhitelist(std::vector<std::string>* read_whitelist,
- std::vector<std::string>* write_whitelist) {
- // On ARM we're enabling the sandbox before the X connection is made,
- // so we need to allow access to |.Xauthority|.
- static const char kXAuthorityPath[] = "/home/chronos/.Xauthority";
- static const char kLdSoCache[] = "/etc/ld.so.cache";
-
- read_whitelist->push_back(kXAuthorityPath);
- read_whitelist->push_back(kLdSoCache);
- read_whitelist->push_back(kLibGlesPath);
- read_whitelist->push_back(kLibEglPath);
-
- AddArmMaliGpuWhitelist(read_whitelist, write_whitelist);
- AddArmTegraGpuWhitelist(read_whitelist, write_whitelist);
-}
-
-// Start a broker process to handle open() inside the sandbox.
-void InitGpuBrokerProcess(Sandbox::EvaluateSyscall gpu_policy,
- BrokerProcess** broker_process) {
- static const char kDriRcPath[] = "/etc/drirc";
- static const char kDriCard0Path[] = "/dev/dri/card0";
-
- CHECK(broker_process);
- CHECK(*broker_process == NULL);
-
- bool (*sandbox_callback)(void) = NULL;
-
- // All GPU process policies need these files brokered out.
- std::vector<std::string> read_whitelist;
- read_whitelist.push_back(kDriCard0Path);
- read_whitelist.push_back(kDriRcPath);
-
- std::vector<std::string> write_whitelist;
- write_whitelist.push_back(kDriCard0Path);
-
- if (gpu_policy == ArmGpuProcessPolicy ||
- gpu_policy == ArmGpuProcessPolicyWithShmat) {
- // We shouldn't be using this policy on non-ARM architectures.
- CHECK(IsArchitectureArm());
- AddArmGpuWhitelist(&read_whitelist, &write_whitelist);
- sandbox_callback = EnableArmGpuBrokerPolicyCallback;
- } else if (gpu_policy == GpuProcessPolicy) {
- sandbox_callback = EnableGpuBrokerPolicyCallback;
- } else {
- // We shouldn't be initializing a GPU broker process without a GPU process
- // policy.
- NOTREACHED();
- }
-
- *broker_process = new BrokerProcess(read_whitelist, write_whitelist);
- // Initialize the broker process and give it a sandbox callback.
- CHECK((*broker_process)->Init(sandbox_callback));
-}
-
-// Warms up/preloads resources needed by the policies.
-// Eventually start a broker process and return it in broker_process.
-void WarmupPolicy(Sandbox::EvaluateSyscall policy,
- BrokerProcess** broker_process) {
- if (policy == GpuProcessPolicy) {
- // Create a new broker process.
- InitGpuBrokerProcess(policy, broker_process);
-
- if (IsArchitectureX86_64() || IsArchitectureI386()) {
- // Accelerated video decode dlopen()'s a shared object
- // inside the sandbox, so preload it now.
- if (IsAcceleratedVideoDecodeEnabled()) {
- const char* I965DrvVideoPath = NULL;
-
- if (IsArchitectureX86_64()) {
- I965DrvVideoPath = "/usr/lib64/va/drivers/i965_drv_video.so";
- } else if (IsArchitectureI386()) {
- I965DrvVideoPath = "/usr/lib/va/drivers/i965_drv_video.so";
- }
-
- dlopen(I965DrvVideoPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
- }
- }
- } else if (policy == ArmGpuProcessPolicy ||
- policy == ArmGpuProcessPolicyWithShmat) {
- // Create a new broker process.
- InitGpuBrokerProcess(policy, broker_process);
-
- // Preload the GL libraries. These are in the read whitelist but we have to
- // preload them anyways to work around ld.so bugs. See crbug.com/268439.
- dlopen(kLibGlesPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
- dlopen(kLibEglPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
-
- // Preload the Tegra libraries.
- dlopen("/usr/lib/libnvrm.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
- dlopen("/usr/lib/libnvrm_graphics.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
- dlopen("/usr/lib/libnvos.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
- dlopen("/usr/lib/libnvddk_2d.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
- dlopen("/usr/lib/libardrv_dynamic.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
- dlopen("/usr/lib/libnvwsi.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
- dlopen("/usr/lib/libnvglsi.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
- dlopen("/usr/lib/libcgdrv.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
- }
-}
-
-Sandbox::EvaluateSyscall GetProcessSyscallPolicy(
- const CommandLine& command_line,
- const std::string& process_type) {
- if (process_type == switches::kGpuProcess) {
- // On Chrome OS ARM, we need a specific GPU process policy.
- if (IsChromeOS() && IsArchitectureArm()) {
- if (command_line.HasSwitch(switches::kGpuSandboxAllowSysVShm))
- return ArmGpuProcessPolicyWithShmat;
- else
- return ArmGpuProcessPolicy;
- }
- else
- return GpuProcessPolicy;
- }
-
- if (process_type == switches::kPpapiPluginProcess) {
- // TODO(jln): figure out what to do with non-Flash PPAPI
- // out-of-process plug-ins.
- return FlashProcessPolicy;
- }
-
- if (process_type == switches::kRendererProcess ||
- process_type == switches::kWorkerProcess) {
- return RendererOrWorkerProcessPolicy;
- }
-
- if (process_type == switches::kUtilityProcess) {
- return BlacklistDebugAndNumaPolicy;
- }
-
- NOTREACHED();
- // This will be our default if we need one.
- return AllowAllPolicy;
-}
-
-// broker_process can be NULL if there is no need for one.
-void StartSandboxWithPolicy(Sandbox::EvaluateSyscall syscall_policy,
- BrokerProcess* broker_process) {
- // Starting the sandbox is a one-way operation. The kernel doesn't allow
- // us to unload a sandbox policy after it has been started. Nonetheless,
- // in order to make the use of the "Sandbox" object easier, we allow for
- // the object to be destroyed after the sandbox has been started. Note that
- // doing so does not stop the sandbox.
- Sandbox sandbox;
- sandbox.SetSandboxPolicy(syscall_policy, broker_process);
- sandbox.StartSandbox();
-}
-
-// Initialize the seccomp-bpf sandbox.
-bool StartBpfSandbox(const CommandLine& command_line,
- const std::string& process_type) {
- Sandbox::EvaluateSyscall syscall_policy =
- GetProcessSyscallPolicy(command_line, process_type);
-
- BrokerProcess* broker_process = NULL;
- // Warm up resources needed by the policy we're about to enable and
- // eventually start a broker process.
- WarmupPolicy(syscall_policy, &broker_process);
-
- StartSandboxWithPolicy(syscall_policy, broker_process);
-
- RunSandboxSanityChecks(process_type);
-
- return true;
-}
-
-} // namespace
-
-#endif // SECCOMP_BPF_SANDBOX
-
-namespace content {
-
-// Is seccomp BPF globally enabled?
-bool SandboxSeccompBpf::IsSeccompBpfDesired() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (!command_line.HasSwitch(switches::kNoSandbox) &&
- !command_line.HasSwitch(switches::kDisableSeccompFilterSandbox)) {
- return true;
- } else {
- return false;
- }
-}
-
-bool SandboxSeccompBpf::ShouldEnableSeccompBpf(
- const std::string& process_type) {
-#if defined(SECCOMP_BPF_SANDBOX)
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (process_type == switches::kGpuProcess)
- return !command_line.HasSwitch(switches::kDisableGpuSandbox);
-
- return true;
-#endif // SECCOMP_BPF_SANDBOX
- return false;
-}
-
-bool SandboxSeccompBpf::SupportsSandbox() {
-#if defined(SECCOMP_BPF_SANDBOX)
- // TODO(jln): pass the saved proc_fd_ from the LinuxSandbox singleton
- // here.
- Sandbox::SandboxStatus bpf_sandbox_status =
- Sandbox::SupportsSeccompSandbox(-1);
- // Kernel support is what we are interested in here. Other status
- // such as STATUS_UNAVAILABLE (has threads) still indicate kernel support.
- // We make this a negative check, since if there is a bug, we would rather
- // "fail closed" (expect a sandbox to be available and try to start it).
- if (bpf_sandbox_status != Sandbox::STATUS_UNSUPPORTED) {
- return true;
- }
-#endif
- return false;
-}
-
-bool SandboxSeccompBpf::StartSandbox(const std::string& process_type) {
-#if defined(SECCOMP_BPF_SANDBOX)
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-
- if (IsSeccompBpfDesired() && // Global switches policy.
- ShouldEnableSeccompBpf(process_type) && // Process-specific policy.
- SupportsSandbox()) {
- // If the kernel supports the sandbox, and if the command line says we
- // should enable it, enable it or die.
- bool started_sandbox = StartBpfSandbox(command_line, process_type);
- CHECK(started_sandbox);
- return true;
- }
-#endif
- return false;
-}
-
-bool SandboxSeccompBpf::StartSandboxWithExternalPolicy(
- playground2::BpfSandboxPolicy policy) {
-#if defined(SECCOMP_BPF_SANDBOX)
- if (IsSeccompBpfDesired() && SupportsSandbox()) {
- CHECK(policy);
- StartSandboxWithPolicy(policy, NULL);
- return true;
- }
-#endif // defined(SECCOMP_BPF_SANDBOX)
- return false;
-}
-
-#if defined(SECCOMP_BPF_SANDBOX)
-playground2::BpfSandboxPolicyCallback SandboxSeccompBpf::GetBaselinePolicy() {
- return base::Bind(&BaselinePolicyWithAux);
-}
-#endif // defined(SECCOMP_BPF_SANDBOX)
-
-} // namespace content
diff --git a/chromium/content/common/sandbox_win.cc b/chromium/content/common/sandbox_win.cc
index e71cdafdc05..7d916acdf8f 100644
--- a/chromium/content/common/sandbox_win.cc
+++ b/chromium/content/common/sandbox_win.cc
@@ -40,9 +40,13 @@ namespace {
// The DLLs listed here are known (or under strong suspicion) of causing crashes
// when they are loaded in the renderer. Note: at runtime we generate short
// versions of the dll name only if the dll has an extension.
+// For more information about how this list is generated, and how to get off
+// of it, see:
+// https://sites.google.com/a/chromium.org/dev/Home/third-party-developers
const wchar_t* const kTroublesomeDlls[] = {
L"adialhk.dll", // Kaspersky Internet Security.
L"acpiz.dll", // Unknown.
+ L"akinsofthook32.dll", // Akinsoft Software Engineering.
L"avgrsstx.dll", // AVG 8.
L"babylonchromepi.dll", // Babylon translator.
L"btkeyind.dll", // Widcomm Bluetooth.
@@ -216,7 +220,7 @@ void AddGenericDllEvictionPolicy(sandbox::TargetPolicy* policy) {
}
// Returns the object path prepended with the current logon session.
-string16 PrependWindowsSessionPath(const char16* object) {
+base::string16 PrependWindowsSessionPath(const char16* object) {
// Cache this because it can't change after process creation.
static uintptr_t s_session_id = 0;
if (s_session_id == 0) {
@@ -432,6 +436,9 @@ void CheckDuplicateHandle(HANDLE handle) {
&size);
CHECK(NT_SUCCESS(error));
+ CHECK(!(basic_info.GrantedAccess & WRITE_DAC)) <<
+ kDuplicateHandleWarning;
+
if (0 == _wcsicmp(type_info->Name.Buffer, L"Process")) {
const ACCESS_MASK kDangerousMask = ~(PROCESS_QUERY_LIMITED_INFORMATION |
SYNCHRONIZE);
@@ -463,13 +470,14 @@ BOOL WINAPI DuplicateHandlePatch(HANDLE source_process_handle,
if (!::IsProcessInJob(target_process_handle, NULL, &is_in_job)) {
// We need a handle with permission to check the job object.
if (ERROR_ACCESS_DENIED == ::GetLastError()) {
- base::win::ScopedHandle process;
+ HANDLE temp_handle;
CHECK(g_iat_orig_duplicate_handle(::GetCurrentProcess(),
target_process_handle,
::GetCurrentProcess(),
- process.Receive(),
+ &temp_handle,
PROCESS_QUERY_INFORMATION,
FALSE, 0));
+ base::win::ScopedHandle process(temp_handle);
CHECK(::IsProcessInJob(process, NULL, &is_in_job));
}
}
@@ -479,10 +487,11 @@ BOOL WINAPI DuplicateHandlePatch(HANDLE source_process_handle,
CHECK(!inherit_handle) << kDuplicateHandleWarning;
// Duplicate the handle again, to get the final permissions.
- base::win::ScopedHandle handle;
+ HANDLE temp_handle;
CHECK(g_iat_orig_duplicate_handle(target_process_handle, *target_handle,
- ::GetCurrentProcess(), handle.Receive(),
+ ::GetCurrentProcess(), &temp_handle,
0, FALSE, DUPLICATE_SAME_ACCESS));
+ base::win::ScopedHandle handle(temp_handle);
// Callers use CHECK macro to make sure we get the right stack.
CheckDuplicateHandle(handle);
@@ -508,7 +517,7 @@ void SetJobLevel(const CommandLine& cmd_line,
// Just have to figure out what needs to be warmed up first.
void AddBaseHandleClosePolicy(sandbox::TargetPolicy* policy) {
// TODO(cpu): Add back the BaseNamedObjects policy.
- string16 object_path = PrependWindowsSessionPath(
+ base::string16 object_path = PrependWindowsSessionPath(
L"\\BaseNamedObjects\\windows_shell_global_counters");
policy->AddKernelObjectToClose(L"Section", object_path.data());
}
@@ -596,7 +605,6 @@ base::ProcessHandle StartSandboxedProcess(
return process;
}
- base::win::ScopedProcessInformation target;
sandbox::TargetPolicy* policy = g_broker_services->CreatePolicy();
sandbox::MitigationFlags mitigations = sandbox::MITIGATION_HEAP_TERMINATE |
@@ -668,11 +676,13 @@ base::ProcessHandle StartSandboxedProcess(
TRACE_EVENT_BEGIN_ETW("StartProcessWithAccess::LAUNCHPROCESS", 0, 0);
+ PROCESS_INFORMATION temp_process_info = {};
result = g_broker_services->SpawnTarget(
- cmd_line->GetProgram().value().c_str(),
- cmd_line->GetCommandLineString().c_str(),
- policy, target.Receive());
+ cmd_line->GetProgram().value().c_str(),
+ cmd_line->GetCommandLineString().c_str(),
+ policy, &temp_process_info);
policy->Release();
+ base::win::ScopedProcessInformation target(temp_process_info);
TRACE_EVENT_END_ETW("StartProcessWithAccess::LAUNCHPROCESS", 0, 0);
diff --git a/chromium/content/common/savable_url_schemes.cc b/chromium/content/common/savable_url_schemes.cc
index 697f2ebae54..47b843f945b 100644
--- a/chromium/content/common/savable_url_schemes.cc
+++ b/chromium/content/common/savable_url_schemes.cc
@@ -17,7 +17,7 @@ const char* const kDefaultSavableSchemes[] = {
kHttpsScheme,
chrome::kFileScheme,
chrome::kFileSystemScheme,
- chrome::kFtpScheme,
+ kFtpScheme,
chrome::kChromeDevToolsScheme,
chrome::kChromeUIScheme,
chrome::kDataScheme,
diff --git a/chromium/content/common/service_worker_messages.h b/chromium/content/common/service_worker_messages.h
index 0f1dd4bdb1d..d2a5eb27602 100644
--- a/chromium/content/common/service_worker_messages.h
+++ b/chromium/content/common/service_worker_messages.h
@@ -7,27 +7,67 @@
#include "base/strings/string16.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_param_traits.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
#include "url/gurl.h"
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+
#define IPC_MESSAGE_START ServiceWorkerMsgStart
+IPC_ENUM_TRAITS(blink::WebServiceWorkerError::ErrorType)
+
// Messages sent from the child process to the browser.
-IPC_MESSAGE_CONTROL3(ServiceWorkerHostMsg_RegisterServiceWorker,
- int32 /* callback_id */,
- string16 /* scope */,
+IPC_MESSAGE_CONTROL4(ServiceWorkerHostMsg_RegisterServiceWorker,
+ int32 /* thread_id */,
+ int32 /* request_id */,
+ GURL /* scope */,
GURL /* script_url */)
-IPC_MESSAGE_CONTROL2(ServiceWorkerHostMsg_UnregisterServiceWorker,
- int32 /* callback_id */,
- string16 /* scope (url pattern) */)
+IPC_MESSAGE_CONTROL3(ServiceWorkerHostMsg_UnregisterServiceWorker,
+ int32 /* thread_id */,
+ int32 /* request_id */,
+ GURL /* scope (url pattern) */)
// Messages sent from the browser to the child process.
// Response to ServiceWorkerMsg_RegisterServiceWorker
-IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_ServiceWorkerRegistered,
- int32 /* callback_id */)
+IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_ServiceWorkerRegistered,
+ int32 /* thread_id */,
+ int32 /* request_id */,
+ int64 /* service_worker_id */)
// Response to ServiceWorkerMsg_UnregisterServiceWorker
-IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_ServiceWorkerUnregistered,
- int32 /* callback_id */)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_ServiceWorkerUnregistered,
+ int32 /* thread_id */,
+ int32 /* request_id */)
+
+// Sent when any kind of registration error occurs during a
+// RegisterServiceWorker / UnregisterServiceWorker handler above.
+IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_ServiceWorkerRegistrationError,
+ int32 /* thread_id */,
+ int32 /* request_id */,
+ blink::WebServiceWorkerError::ErrorType /* code */,
+ base::string16 /* message */)
+
+// Informs the browser of a new ServiceWorkerProvider in the child process,
+// |provider_id| is unique within its child process.
+IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_ProviderCreated,
+ int /* provider_id */)
+
+// Informs the browser of a ServiceWorkerProvider being destroyed.
+IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_ProviderDestroyed,
+ int /* provider_id */)
+
+// For EmbeddedWorker related messages -------------------------------------
+
+// Browser -> Renderer message to create a new embedded worker context.
+IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_StartWorker,
+ int /* embedded_worker_id */,
+ int64 /* service_worker_version_id */,
+ GURL /* script_url */)
+
+// Browser -> Renderer message to terminate the embedded worker.
+IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_TerminateWorker,
+ int /* embedded_worker_id */)
diff --git a/chromium/content/common/set_process_title.cc b/chromium/content/common/set_process_title.cc
index 6fde51bd6cb..5113ee03d97 100644
--- a/chromium/content/common/set_process_title.cc
+++ b/chromium/content/common/set_process_title.cc
@@ -50,7 +50,7 @@ void SetProcessTitleFromCommandLine(const char** main_argv) {
// display purposes and has no TOCTTOU security implications.
base::FilePath target;
base::FilePath self_exe(base::kProcSelfExe);
- if (file_util::ReadSymbolicLink(self_exe, &target)) {
+ if (base::ReadSymbolicLink(self_exe, &target)) {
have_argv0 = true;
title = target.value();
// If the binary has since been deleted, Linux appends " (deleted)" to the
diff --git a/chromium/content/common/socket_stream_handle_data.cc b/chromium/content/common/socket_stream_handle_data.cc
index be419d7216e..dbf75a48c1a 100644
--- a/chromium/content/common/socket_stream_handle_data.cc
+++ b/chromium/content/common/socket_stream_handle_data.cc
@@ -7,7 +7,7 @@
#include "webkit/child/websocketstreamhandle_impl.h"
using webkit_glue::WebSocketStreamHandleImpl;
-using WebKit::WebSocketStreamHandle;
+using blink::WebSocketStreamHandle;
namespace content {
diff --git a/chromium/content/common/socket_stream_handle_data.h b/chromium/content/common/socket_stream_handle_data.h
index c339ec04cce..470e9baa3ed 100644
--- a/chromium/content/common/socket_stream_handle_data.h
+++ b/chromium/content/common/socket_stream_handle_data.h
@@ -8,7 +8,7 @@
#include "base/supports_user_data.h"
#include "content_export.h"
-namespace WebKit {
+namespace blink {
class WebSocketStreamHandle;
}
@@ -24,12 +24,12 @@ class SocketStreamHandleData : public base::SupportsUserData::Data {
// Creates SocketStreamHandleData object with |render_view_id| and store it
// to |handle|.
static void AddToHandle(
- WebKit::WebSocketStreamHandle* handle, int render_view_id);
+ blink::WebSocketStreamHandle* handle, int render_view_id);
- // Retrieves the stored user data from WebKit::WebSocketStreamHandle object.
+ // Retrieves the stored user data from blink::WebSocketStreamHandle object.
// |handle| must actually be a WebSocketStreamHandleImpl object.
CONTENT_EXPORT static const SocketStreamHandleData* ForHandle(
- WebKit::WebSocketStreamHandle* handle);
+ blink::WebSocketStreamHandle* handle);
private:
explicit SocketStreamHandleData(int render_view_id)
diff --git a/chromium/content/common/ssl_status_serialization.cc b/chromium/content/common/ssl_status_serialization.cc
index 87593a595a2..5543c35d4e3 100644
--- a/chromium/content/common/ssl_status_serialization.cc
+++ b/chromium/content/common/ssl_status_serialization.cc
@@ -9,24 +9,37 @@
namespace content {
-std::string SerializeSecurityInfo(int cert_id,
- net::CertStatus cert_status,
- int security_bits,
- int ssl_connection_status) {
+std::string SerializeSecurityInfo(
+ int cert_id,
+ net::CertStatus cert_status,
+ int security_bits,
+ int ssl_connection_status,
+ const SignedCertificateTimestampIDStatusList&
+ signed_certificate_timestamp_ids) {
Pickle pickle;
pickle.WriteInt(cert_id);
pickle.WriteUInt32(cert_status);
pickle.WriteInt(security_bits);
pickle.WriteInt(ssl_connection_status);
+ pickle.WriteInt(signed_certificate_timestamp_ids.size());
+ for (SignedCertificateTimestampIDStatusList::const_iterator iter =
+ signed_certificate_timestamp_ids.begin();
+ iter != signed_certificate_timestamp_ids.end(); ++iter) {
+ pickle.WriteInt(iter->id);
+ pickle.WriteUInt16(iter->status);
+ }
return std::string(static_cast<const char*>(pickle.data()), pickle.size());
}
-bool DeserializeSecurityInfo(const std::string& state,
- int* cert_id,
- net::CertStatus* cert_status,
- int* security_bits,
- int* ssl_connection_status) {
- DCHECK(cert_id && cert_status && security_bits && ssl_connection_status);
+bool DeserializeSecurityInfo(
+ const std::string& state,
+ int* cert_id,
+ net::CertStatus* cert_status,
+ int* security_bits,
+ int* ssl_connection_status,
+ SignedCertificateTimestampIDStatusList* signed_certificate_timestamp_ids) {
+ DCHECK(cert_id && cert_status && security_bits && ssl_connection_status &&
+ signed_certificate_timestamp_ids);
if (state.empty()) {
// No SSL used.
*cert_id = 0;
@@ -34,15 +47,35 @@ bool DeserializeSecurityInfo(const std::string& state,
*cert_status = 0;
*security_bits = -1;
*ssl_connection_status = 0;
+ signed_certificate_timestamp_ids->clear();
return false;
}
Pickle pickle(state.data(), static_cast<int>(state.size()));
PickleIterator iter(pickle);
- return pickle.ReadInt(&iter, cert_id) &&
- pickle.ReadUInt32(&iter, cert_status) &&
- pickle.ReadInt(&iter, security_bits) &&
- pickle.ReadInt(&iter, ssl_connection_status);
+ bool pickle_read_ok = pickle.ReadInt(&iter, cert_id) &&
+ pickle.ReadUInt32(&iter, cert_status) &&
+ pickle.ReadInt(&iter, security_bits) &&
+ pickle.ReadInt(&iter, ssl_connection_status);
+ if (!pickle_read_ok)
+ return pickle_read_ok;
+
+ int num_scts_to_read;
+ pickle_read_ok = pickle.ReadInt(&iter, &num_scts_to_read);
+ int id;
+ uint16 status;
+ for (; pickle_read_ok && num_scts_to_read > 0; --num_scts_to_read) {
+ pickle_read_ok = pickle.ReadInt(&iter, &id) &&
+ pickle.ReadUInt16(&iter, &status);
+ if (pickle_read_ok) {
+ signed_certificate_timestamp_ids->push_back(
+ SignedCertificateTimestampIDAndStatus(
+ id,
+ static_cast<net::ct::SCTVerifyStatus>(status)));
+ }
+ }
+
+ return pickle_read_ok;
}
} // namespace content
diff --git a/chromium/content/common/ssl_status_serialization.h b/chromium/content/common/ssl_status_serialization.h
index fa1230bb9f8..03675c16986 100644
--- a/chromium/content/common/ssl_status_serialization.h
+++ b/chromium/content/common/ssl_status_serialization.h
@@ -8,21 +8,27 @@
#include <string>
#include "content/common/content_export.h"
+#include "content/public/common/signed_certificate_timestamp_id_and_status.h"
#include "net/cert/cert_status_flags.h"
namespace content {
// Convenience methods for serializing/deserializing the security info.
-CONTENT_EXPORT std::string SerializeSecurityInfo(int cert_id,
- net::CertStatus cert_status,
- int security_bits,
- int connection_status);
-
-bool DeserializeSecurityInfo(const std::string& state,
- int* cert_id,
- net::CertStatus* cert_status,
- int* security_bits,
- int* connection_status);
+CONTENT_EXPORT std::string SerializeSecurityInfo(
+ int cert_id,
+ net::CertStatus cert_status,
+ int security_bits,
+ int connection_status,
+ const SignedCertificateTimestampIDStatusList&
+ signed_certificate_timestamp_ids);
+
+bool DeserializeSecurityInfo(
+ const std::string& state,
+ int* cert_id,
+ net::CertStatus* cert_status,
+ int* security_bits,
+ int* connection_status,
+ SignedCertificateTimestampIDStatusList* signed_certificate_timestamp_ids);
} // namespace content
diff --git a/chromium/content/common/swapped_out_messages.cc b/chromium/content/common/swapped_out_messages.cc
index 05b5781b915..47acc358e02 100644
--- a/chromium/content/common/swapped_out_messages.cc
+++ b/chromium/content/common/swapped_out_messages.cc
@@ -5,6 +5,7 @@
#include "content/common/swapped_out_messages.h"
#include "content/common/accessibility_messages.h"
+#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_client.h"
@@ -35,6 +36,8 @@ bool SwappedOutMessages::CanSendWhileSwappedOut(const IPC::Message* msg) {
// Allow cross-process JavaScript calls.
case ViewHostMsg_RouteCloseEvent::ID:
case ViewHostMsg_RouteMessageEvent::ID:
+ // Frame detach must occur after the RenderView has swapped out.
+ case FrameHostMsg_Detach::ID:
return true;
default:
break;
diff --git a/chromium/content/common/url_schemes.cc b/chromium/content/common/url_schemes.cc
index ac8dbf40aa5..2b4be7d852e 100644
--- a/chromium/content/common/url_schemes.cc
+++ b/chromium/content/common/url_schemes.cc
@@ -30,15 +30,12 @@ namespace content {
void RegisterContentSchemes(bool lock_standard_schemes) {
std::vector<std::string> additional_standard_schemes;
std::vector<std::string> additional_savable_schemes;
- GetContentClient()->AddAdditionalSchemes(
- &additional_standard_schemes,
- &additional_savable_schemes);
+ GetContentClient()->AddAdditionalSchemes(&additional_standard_schemes,
+ &additional_savable_schemes);
- // Don't need "chrome-internal" which was used in old versions of Chrome for
- // the new tab page.
url_util::AddStandardScheme(chrome::kChromeDevToolsScheme);
url_util::AddStandardScheme(chrome::kChromeUIScheme);
- url_util::AddStandardScheme(chrome::kGuestScheme);
+ url_util::AddStandardScheme(kGuestScheme);
url_util::AddStandardScheme(kMetadataScheme);
std::for_each(additional_standard_schemes.begin(),
additional_standard_schemes.end(),
diff --git a/chromium/content/common/view_messages.h b/chromium/content/common/view_messages.h
index ed0cf62b884..554c8a1af8e 100644
--- a/chromium/content/common/view_messages.h
+++ b/chromium/content/common/view_messages.h
@@ -20,6 +20,7 @@
#include "content/common/view_message_enums.h"
#include "content/common/webplugin_geometry.h"
#include "content/port/common/input_event_ack_state.h"
+#include "content/public/common/color_suggestion.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/common/favicon_url.h"
@@ -34,6 +35,7 @@
#include "content/public/common/stop_find_action.h"
#include "content/public/common/three_d_api_types.h"
#include "content/public/common/window_container_type.h"
+#include "content/common/date_time_suggestion.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"
@@ -42,12 +44,12 @@
#include "media/base/media_log_event.h"
#include "third_party/WebKit/public/platform/WebFloatPoint.h"
#include "third_party/WebKit/public/platform/WebFloatRect.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "third_party/WebKit/public/web/WebMediaPlayerAction.h"
#include "third_party/WebKit/public/web/WebPluginAction.h"
#include "third_party/WebKit/public/web/WebPopupType.h"
-#include "third_party/WebKit/public/web/WebScreenInfo.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"
@@ -72,11 +74,11 @@
IPC_ENUM_TRAITS(AccessibilityMode)
IPC_ENUM_TRAITS(ViewMsg_Navigate_Type::Value)
-IPC_ENUM_TRAITS(WebKit::WebContextMenuData::MediaType)
-IPC_ENUM_TRAITS(WebKit::WebMediaPlayerAction::Type)
-IPC_ENUM_TRAITS(WebKit::WebPluginAction::Type)
-IPC_ENUM_TRAITS(WebKit::WebPopupType)
-IPC_ENUM_TRAITS(WebKit::WebTextDirection)
+IPC_ENUM_TRAITS(blink::WebContextMenuData::MediaType)
+IPC_ENUM_TRAITS(blink::WebMediaPlayerAction::Type)
+IPC_ENUM_TRAITS(blink::WebPluginAction::Type)
+IPC_ENUM_TRAITS(blink::WebPopupType)
+IPC_ENUM_TRAITS(blink::WebTextDirection)
IPC_ENUM_TRAITS(WindowContainerType)
IPC_ENUM_TRAITS(content::FaviconURL::IconType)
IPC_ENUM_TRAITS(content::FileChooserParams::Mode)
@@ -103,42 +105,42 @@ IPC_STRUCT_TRAITS_BEGIN(FontDescriptor)
IPC_STRUCT_TRAITS_END()
#endif
-IPC_STRUCT_TRAITS_BEGIN(WebKit::WebCompositionUnderline)
+IPC_STRUCT_TRAITS_BEGIN(blink::WebCompositionUnderline)
IPC_STRUCT_TRAITS_MEMBER(startOffset)
IPC_STRUCT_TRAITS_MEMBER(endOffset)
IPC_STRUCT_TRAITS_MEMBER(color)
IPC_STRUCT_TRAITS_MEMBER(thick)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(WebKit::WebFindOptions)
+IPC_STRUCT_TRAITS_BEGIN(blink::WebFindOptions)
IPC_STRUCT_TRAITS_MEMBER(forward)
IPC_STRUCT_TRAITS_MEMBER(matchCase)
IPC_STRUCT_TRAITS_MEMBER(findNext)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(WebKit::WebMediaPlayerAction)
+IPC_STRUCT_TRAITS_BEGIN(blink::WebMediaPlayerAction)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(enable)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(WebKit::WebPluginAction)
+IPC_STRUCT_TRAITS_BEGIN(blink::WebPluginAction)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(enable)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(WebKit::WebFloatPoint)
+IPC_STRUCT_TRAITS_BEGIN(blink::WebFloatPoint)
IPC_STRUCT_TRAITS_MEMBER(x)
IPC_STRUCT_TRAITS_MEMBER(y)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(WebKit::WebFloatRect)
+IPC_STRUCT_TRAITS_BEGIN(blink::WebFloatRect)
IPC_STRUCT_TRAITS_MEMBER(x)
IPC_STRUCT_TRAITS_MEMBER(y)
IPC_STRUCT_TRAITS_MEMBER(width)
IPC_STRUCT_TRAITS_MEMBER(height)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(WebKit::WebScreenInfo)
+IPC_STRUCT_TRAITS_BEGIN(blink::WebScreenInfo)
IPC_STRUCT_TRAITS_MEMBER(deviceScaleFactor)
IPC_STRUCT_TRAITS_MEMBER(depth)
IPC_STRUCT_TRAITS_MEMBER(depthPerComponent)
@@ -159,6 +161,17 @@ IPC_STRUCT_TRAITS_BEGIN(content::MenuItem)
IPC_STRUCT_TRAITS_MEMBER(submenu)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(content::ColorSuggestion)
+ IPC_STRUCT_TRAITS_MEMBER(color)
+ IPC_STRUCT_TRAITS_MEMBER(label)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::DateTimeSuggestion)
+ IPC_STRUCT_TRAITS_MEMBER(value)
+ IPC_STRUCT_TRAITS_MEMBER(localized_value)
+ IPC_STRUCT_TRAITS_MEMBER(label)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::ContextMenuParams)
IPC_STRUCT_TRAITS_MEMBER(media_type)
IPC_STRUCT_TRAITS_MEMBER(x)
@@ -180,11 +193,9 @@ IPC_STRUCT_TRAITS_BEGIN(content::ContextMenuParams)
IPC_STRUCT_TRAITS_MEMBER(speech_input_enabled)
IPC_STRUCT_TRAITS_MEMBER(spellcheck_enabled)
IPC_STRUCT_TRAITS_MEMBER(is_editable)
-#if defined(OS_MACOSX)
IPC_STRUCT_TRAITS_MEMBER(writing_direction_default)
IPC_STRUCT_TRAITS_MEMBER(writing_direction_left_to_right)
IPC_STRUCT_TRAITS_MEMBER(writing_direction_right_to_left)
-#endif // OS_MACOSX
IPC_STRUCT_TRAITS_MEMBER(edit_flags)
IPC_STRUCT_TRAITS_MEMBER(security_info)
IPC_STRUCT_TRAITS_MEMBER(frame_charset)
@@ -258,6 +269,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::RendererPreferences)
IPC_STRUCT_TRAITS_MEMBER(inactive_selection_fg_color)
IPC_STRUCT_TRAITS_MEMBER(browser_handles_non_local_top_level_requests)
IPC_STRUCT_TRAITS_MEMBER(browser_handles_all_top_level_requests)
+ IPC_STRUCT_TRAITS_MEMBER(browser_handles_all_top_level_link_clicks)
IPC_STRUCT_TRAITS_MEMBER(caret_blink_interval)
IPC_STRUCT_TRAITS_MEMBER(use_custom_colors)
IPC_STRUCT_TRAITS_MEMBER(enable_referrers)
@@ -332,7 +344,7 @@ IPC_STRUCT_BEGIN(ViewHostMsg_CreateWindow_Params)
// The name of the resulting frame that should be created (empty if none
// has been specified).
- IPC_STRUCT_MEMBER(string16, frame_name)
+ IPC_STRUCT_MEMBER(base::string16, frame_name)
// The frame identifier of the frame initiating the open.
IPC_STRUCT_MEMBER(int64, opener_frame_id)
@@ -362,7 +374,12 @@ IPC_STRUCT_BEGIN(ViewHostMsg_CreateWindow_Params)
IPC_STRUCT_MEMBER(content::Referrer, referrer)
// The window features to use for the new view.
- IPC_STRUCT_MEMBER(WebKit::WebWindowFeatures, features)
+ IPC_STRUCT_MEMBER(blink::WebWindowFeatures, features)
+
+ // The additional window features to use for the new view. We pass these
+ // separately from |features| above because we cannot serialize WebStrings
+ // over IPC.
+ IPC_STRUCT_MEMBER(std::vector<base::string16>, additional_features)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(ViewHostMsg_CreateWorker_Params)
@@ -370,7 +387,7 @@ IPC_STRUCT_BEGIN(ViewHostMsg_CreateWorker_Params)
IPC_STRUCT_MEMBER(GURL, url)
// Name for a SharedWorker, otherwise empty string.
- IPC_STRUCT_MEMBER(string16, name)
+ IPC_STRUCT_MEMBER(base::string16, name)
// The ID of the parent document (unique within parent renderer).
IPC_STRUCT_MEMBER(unsigned long long, document_id)
@@ -388,30 +405,26 @@ IPC_STRUCT_BEGIN(ViewHostMsg_CreateWorker_Params)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(ViewHostMsg_DateTimeDialogValue_Params)
- IPC_STRUCT_MEMBER(int, dialog_type)
- IPC_STRUCT_MEMBER(int, year)
- IPC_STRUCT_MEMBER(int, month)
- IPC_STRUCT_MEMBER(int, day)
- IPC_STRUCT_MEMBER(int, hour)
- IPC_STRUCT_MEMBER(int, minute)
- IPC_STRUCT_MEMBER(int, second)
- IPC_STRUCT_MEMBER(int, milli)
- IPC_STRUCT_MEMBER(int, week)
+ IPC_STRUCT_MEMBER(ui::TextInputType, dialog_type)
+ IPC_STRUCT_MEMBER(double, dialog_value)
IPC_STRUCT_MEMBER(double, minimum)
IPC_STRUCT_MEMBER(double, maximum)
IPC_STRUCT_MEMBER(double, step)
+ IPC_STRUCT_MEMBER(std::vector<content::DateTimeSuggestion>, suggestions)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(ViewHostMsg_DidFailProvisionalLoadWithError_Params)
// The frame ID for the failure report.
IPC_STRUCT_MEMBER(int64, frame_id)
+ // The WebFrame's uniqueName().
+ IPC_STRUCT_MEMBER(base::string16, frame_unique_name)
// True if this is the top-most frame.
IPC_STRUCT_MEMBER(bool, is_main_frame)
// Error code as reported in the DidFailProvisionalLoad callback.
IPC_STRUCT_MEMBER(int, error_code)
// An error message generated from the error_code. This can be an empty
// string if we were unable to find a meaningful description.
- IPC_STRUCT_MEMBER(string16, error_description)
+ IPC_STRUCT_MEMBER(base::string16, error_description)
// The URL that the error is reported for.
IPC_STRUCT_MEMBER(GURL, url)
// True if the failure is the result of navigating to a POST again
@@ -428,6 +441,9 @@ IPC_STRUCT_BEGIN_WITH_PARENT(ViewHostMsg_FrameNavigate_Params,
// frame the navigation happened in for a given renderer.
IPC_STRUCT_MEMBER(int64, frame_id)
+ // The WebFrame's uniqueName().
+ IPC_STRUCT_MEMBER(base::string16, frame_unique_name)
+
// Information regarding the security of the connection (empty if the
// connection was not secure).
IPC_STRUCT_MEMBER(std::string, security_info)
@@ -478,9 +494,9 @@ IPC_STRUCT_END()
IPC_STRUCT_BEGIN(ViewHostMsg_SelectionBounds_Params)
IPC_STRUCT_MEMBER(gfx::Rect, anchor_rect)
- IPC_STRUCT_MEMBER(WebKit::WebTextDirection, anchor_dir)
+ IPC_STRUCT_MEMBER(blink::WebTextDirection, anchor_dir)
IPC_STRUCT_MEMBER(gfx::Rect, focus_rect)
- IPC_STRUCT_MEMBER(WebKit::WebTextDirection, focus_dir)
+ IPC_STRUCT_MEMBER(blink::WebTextDirection, focus_dir)
IPC_STRUCT_MEMBER(bool, is_anchor_first)
IPC_STRUCT_END()
@@ -644,9 +660,18 @@ IPC_STRUCT_BEGIN(ViewMsg_Navigate_Params)
// no referrer.
IPC_STRUCT_MEMBER(content::Referrer, referrer)
+ // Any redirect URLs that occurred before |url|. Useful for cross-process
+ // navigations; defaults to empty.
+ IPC_STRUCT_MEMBER(std::vector<GURL>, redirects)
+
// The type of transition.
IPC_STRUCT_MEMBER(content::PageTransition, transition)
+ // Informs the RenderView the pending navigation should replace the current
+ // history entry when it commits. This is used for cross-process redirects so
+ // the transferred navigation can recover the navigation state.
+ IPC_STRUCT_MEMBER(bool, should_replace_current_entry)
+
// Opaque history state (received by ViewHostMsg_UpdateState).
IPC_STRUCT_MEMBER(content::PageState, page_state)
@@ -710,7 +735,7 @@ IPC_STRUCT_BEGIN(ViewMsg_New_Params)
IPC_STRUCT_MEMBER(int64, session_storage_namespace_id)
// The name of the frame associated with this view (or empty if none).
- IPC_STRUCT_MEMBER(string16, frame_name)
+ IPC_STRUCT_MEMBER(base::string16, frame_name)
// The route ID of the opener RenderView if we need to set one
// (MSG_ROUTING_NONE otherwise).
@@ -728,7 +753,7 @@ IPC_STRUCT_BEGIN(ViewMsg_New_Params)
IPC_STRUCT_MEMBER(int32, next_page_id)
// The properties of the screen associated with the view.
- IPC_STRUCT_MEMBER(WebKit::WebScreenInfo, screen_info)
+ IPC_STRUCT_MEMBER(blink::WebScreenInfo, screen_info)
// The accessibility mode of the renderer.
IPC_STRUCT_MEMBER(AccessibilityMode, accessibility_mode)
@@ -741,7 +766,7 @@ IPC_STRUCT_END()
IPC_STRUCT_BEGIN(ViewMsg_PostMessage_Params)
// The serialized script value.
- IPC_STRUCT_MEMBER(string16, data)
+ IPC_STRUCT_MEMBER(base::string16, data)
// When sent to the browser, this is the routing ID of the source frame in
// the source process. The browser replaces it with the routing ID of the
@@ -749,10 +774,14 @@ IPC_STRUCT_BEGIN(ViewMsg_PostMessage_Params)
IPC_STRUCT_MEMBER(int, source_routing_id)
// The origin of the source frame.
- IPC_STRUCT_MEMBER(string16, source_origin)
+ IPC_STRUCT_MEMBER(base::string16, source_origin)
// The origin for the message's target.
- IPC_STRUCT_MEMBER(string16, target_origin)
+ IPC_STRUCT_MEMBER(base::string16, target_origin)
+
+ // Information about the MessagePorts this message contains.
+ IPC_STRUCT_MEMBER(std::vector<int>, message_port_ids)
+ IPC_STRUCT_MEMBER(std::vector<int>, new_routing_ids)
IPC_STRUCT_END()
// Messages sent from the browser to the renderer.
@@ -806,6 +835,11 @@ IPC_MESSAGE_ROUTED2(ViewMsg_SetHistoryLengthAndPrune,
int, /* merge_history_length */
int32 /* minimum_page_id */)
+// Tells the renderer the browser's notion of its process ID.
+// Some subsystems, like LatencyInfo, require this to be known to the renderer.
+IPC_MESSAGE_CONTROL1(ViewMsg_SetRendererProcessID,
+ base::ProcessId /* process_id */)
+
// Tells the renderer to create a new view.
// This message is slightly different, the view it takes (via
// ViewMsg_New_Params) is the view to create, the message itself is sent as a
@@ -833,7 +867,7 @@ IPC_MESSAGE_ROUTED0(ViewMsg_TimezoneChange)
IPC_MESSAGE_ROUTED0(ViewMsg_Close)
IPC_STRUCT_BEGIN(ViewMsg_Resize_Params)
- IPC_STRUCT_MEMBER(WebKit::WebScreenInfo, screen_info)
+ IPC_STRUCT_MEMBER(blink::WebScreenInfo, screen_info)
IPC_STRUCT_MEMBER(gfx::Size, new_size)
IPC_STRUCT_MEMBER(gfx::Size, physical_backing_size)
IPC_STRUCT_MEMBER(float, overdraw_bottom_height)
@@ -895,9 +929,6 @@ IPC_MESSAGE_ROUTED0(ViewMsg_UpdateRect_ACK)
// compositor path.
IPC_MESSAGE_ROUTED0(ViewMsg_SwapBuffers_ACK)
-// Tells the render widget that a smooth scroll completed.
-IPC_MESSAGE_ROUTED0(ViewMsg_SyntheticGestureCompleted)
-
// Tells the renderer to focus the first (last if reverse is true) focusable
// node.
IPC_MESSAGE_ROUTED1(ViewMsg_SetInitialFocus,
@@ -930,8 +961,8 @@ IPC_MESSAGE_ROUTED0(ViewMsg_ReloadFrame)
// Sent when the user wants to search for a word on the page (find in page).
IPC_MESSAGE_ROUTED3(ViewMsg_Find,
int /* request_id */,
- string16 /* search_text */,
- WebKit::WebFindOptions)
+ base::string16 /* search_text */,
+ blink::WebFindOptions)
// This message notifies the renderer that the user has closed the FindInPage
// window (and what action to take regarding the selection).
@@ -945,7 +976,7 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SetBrowserRenderingStats,
// Replaces a date time input field.
IPC_MESSAGE_ROUTED1(ViewMsg_ReplaceDateTime,
- ViewHostMsg_DateTimeDialogValue_Params /* value */)
+ double /* dialog_value */)
// Copies the image at location x, y to the clipboard (if there indeed is an
// image at that location).
@@ -957,13 +988,13 @@ IPC_MESSAGE_ROUTED2(ViewMsg_CopyImageAt,
// located at the given point.
IPC_MESSAGE_ROUTED2(ViewMsg_MediaPlayerActionAt,
gfx::Point, /* location */
- WebKit::WebMediaPlayerAction)
+ blink::WebMediaPlayerAction)
// Tells the renderer to perform the given action on the plugin located at
// the given point.
IPC_MESSAGE_ROUTED2(ViewMsg_PluginActionAt,
gfx::Point, /* location */
- WebKit::WebPluginAction)
+ blink::WebPluginAction)
// Request for the renderer to evaluate an xpath to a frame and execute a
// javascript: url in that frame's context. The message is completely
@@ -989,8 +1020,8 @@ IPC_MESSAGE_ROUTED2(ViewMsg_PluginActionAt,
// ViewHostMsg_ScriptEvalResponse is passed the ID parameter so that the
// client can uniquely identify the request.
IPC_MESSAGE_ROUTED4(ViewMsg_ScriptEvalRequest,
- string16, /* frame_xpath */
- string16, /* jscript_url */
+ base::string16, /* frame_xpath */
+ base::string16, /* jscript_url */
int, /* ID */
bool /* If true, result is sent back. */)
@@ -1005,7 +1036,7 @@ IPC_MESSAGE_ROUTED0(ViewMsg_DisownOpener)
// into that frame's document. See ViewMsg_ScriptEvalRequest for details on
// allowed xpath expressions.
IPC_MESSAGE_ROUTED2(ViewMsg_CSSInsertRequest,
- string16, /* frame_xpath */
+ base::string16, /* frame_xpath */
std::string /* css string */)
// Change the zoom level for the current main frame. If the level actually
@@ -1074,17 +1105,22 @@ IPC_MESSAGE_ROUTED2(ViewMsg_SetWebUIProperty,
IPC_MESSAGE_ROUTED1(ViewMsg_SetInputMethodActive,
bool /* is_active */)
+// IME API oncandidatewindow* events for InputMethodContext.
+IPC_MESSAGE_ROUTED0(ViewMsg_CandidateWindowShown)
+IPC_MESSAGE_ROUTED0(ViewMsg_CandidateWindowUpdated)
+IPC_MESSAGE_ROUTED0(ViewMsg_CandidateWindowHidden)
+
// This message sends a string being composed with an input method.
IPC_MESSAGE_ROUTED4(
ViewMsg_ImeSetComposition,
- string16, /* text */
- std::vector<WebKit::WebCompositionUnderline>, /* underlines */
+ base::string16, /* text */
+ std::vector<blink::WebCompositionUnderline>, /* underlines */
int, /* selectiont_start */
int /* selection_end */)
// This message confirms an ongoing composition.
IPC_MESSAGE_ROUTED3(ViewMsg_ImeConfirmComposition,
- string16 /* text */,
+ base::string16 /* text */,
gfx::Range /* replacement_range */,
bool /* keep_selection */)
@@ -1093,7 +1129,7 @@ IPC_MESSAGE_ROUTED3(ViewMsg_ImeConfirmComposition,
IPC_MESSAGE_ROUTED3(ViewMsg_SetCompositionFromExistingText,
int /* start */,
int /* end */,
- std::vector<WebKit::WebCompositionUnderline> /* underlines */)
+ std::vector<blink::WebCompositionUnderline> /* underlines */)
// Selects between the given start and end offsets in the currently focused
// editable field.
@@ -1140,6 +1176,11 @@ IPC_MESSAGE_ROUTED0(ViewMsg_CantFocus)
// via ViewHostMsg_ShouldClose.
IPC_MESSAGE_ROUTED0(ViewMsg_ShouldClose)
+// Tells the renderer to suppress any further modal dialogs until it receives a
+// corresponding ViewMsg_SwapOut message. This ensures that no
+// PageGroupLoadDeferrer is on the stack for SwapOut.
+IPC_MESSAGE_ROUTED0(ViewMsg_SuppressDialogsUntilSwapOut)
+
// Instructs the renderer to swap out for a cross-site transition, including
// running the unload event handler. Expects a SwapOut_ACK message when
// finished.
@@ -1189,7 +1230,7 @@ IPC_MESSAGE_ROUTED1(ViewMsg_DisableAutoResize,
// Changes the text direction of the currently selected input field (if any).
IPC_MESSAGE_ROUTED1(ViewMsg_SetTextDirection,
- WebKit::WebTextDirection /* direction */)
+ blink::WebTextDirection /* direction */)
// Tells the renderer to clear the focused node (if any).
IPC_MESSAGE_ROUTED0(ViewMsg_ClearFocusedNode)
@@ -1213,12 +1254,6 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SetActive,
// Sent when the worker has started.
IPC_MESSAGE_ROUTED0(ViewMsg_WorkerCreated)
-// The response to ViewHostMsg_AsyncOpenPepperFile.
-IPC_MESSAGE_ROUTED3(ViewMsg_AsyncOpenPepperFile_ACK,
- base::PlatformFileError /* error_code */,
- IPC::PlatformFileForTransit /* file descriptor */,
- int /* message_id */)
-
// Tells the renderer that the network state has changed and that
// window.navigator.onLine should be updated for all WebViews.
IPC_MESSAGE_CONTROL1(ViewMsg_NetworkStateChanged,
@@ -1268,11 +1303,20 @@ IPC_MESSAGE_ROUTED3(ViewMsg_WindowSnapshotCompleted,
gfx::Size /* size */,
std::vector<unsigned char> /* png */)
+#if defined(OS_MACOSX)
+// Notification of a change in scrollbar appearance and/or behavior.
+IPC_MESSAGE_CONTROL4(ViewMsg_UpdateScrollbarTheme,
+ float /* initial_button_delay */,
+ float /* autoscroll_button_delay */,
+ bool /* jump_on_track_click */,
+ bool /* redraw */)
+#endif
+
+#if defined(OS_ANDROID)
// Tells the renderer to suspend/resume the webkit timers.
IPC_MESSAGE_CONTROL1(ViewMsg_SetWebKitSharedTimersSuspended,
bool /* suspend */)
-#if defined(OS_ANDROID)
// 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|
@@ -1295,10 +1339,6 @@ IPC_MESSAGE_ROUTED2(ViewMsg_SelectPopupMenuItems,
// ViewMsg_ScrollFocusedEditableNodeIntoView was called.
IPC_MESSAGE_ROUTED0(ViewMsg_UndoScrollFocusedEditableNodeIntoView)
-// This message relays the beginning or end of a batch event in the IME.
-IPC_MESSAGE_ROUTED1(ViewMsg_ImeBatchStateChanged,
- bool /* is_begin */)
-
// Notifies the renderer whether hiding/showing the top controls is enabled
// and whether or not to animate to the proper state.
IPC_MESSAGE_ROUTED3(ViewMsg_UpdateTopControlsState,
@@ -1319,6 +1359,11 @@ IPC_MESSAGE_ROUTED0(ViewMsg_ImeEventAck)
// Sent by the browser when we should pause video playback.
IPC_MESSAGE_ROUTED0(ViewMsg_PauseVideo);
+// Extracts the data at the given rect, returning it through the
+// ViewHostMsg_SmartClipDataExtracted IPC.
+IPC_MESSAGE_ROUTED1(ViewMsg_ExtractSmartClipData,
+ gfx::Rect /* rect */)
+
#elif defined(OS_MACOSX)
// Let the RenderView know its window has changed visibility.
IPC_MESSAGE_ROUTED1(ViewMsg_SetWindowVisibility,
@@ -1336,7 +1381,7 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SetInLiveResize,
// Tell the renderer that plugin IME has completed.
IPC_MESSAGE_ROUTED2(ViewMsg_PluginImeCompositionCompleted,
- string16 /* text */,
+ base::string16 /* text */,
int /* plugin_id */)
// External popup menus.
@@ -1377,7 +1422,7 @@ IPC_SYNC_MESSAGE_CONTROL1_4(ViewHostMsg_CreateWindow,
// contains the widget being created.
IPC_SYNC_MESSAGE_CONTROL2_2(ViewHostMsg_CreateWidget,
int /* opener_id */,
- WebKit::WebPopupType /* popup type */,
+ blink::WebPopupType /* popup type */,
int /* route_id */,
int32 /* surface_id */)
@@ -1401,10 +1446,6 @@ IPC_SYNC_MESSAGE_CONTROL0_2(ViewHostMsg_GetAudioHardwareConfig,
IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetCPUUsage,
int /* CPU usage in percents */)
-// Asks the browser for the user's monitor profile.
-IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetMonitorColorProfile,
- std::vector<char> /* profile */)
-
// Asks the browser for the renderer process memory size stats.
IPC_SYNC_MESSAGE_CONTROL0_2(ViewHostMsg_GetProcessMemorySizes,
size_t /* private_bytes */,
@@ -1463,11 +1504,6 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_UpdateScreenRects_ACK)
IPC_MESSAGE_ROUTED1(ViewHostMsg_RequestMove,
gfx::Rect /* position */)
-// Sent by the renderer process to notify the browser that the web page has
-// programmatically scrolled.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_DidProgrammaticallyScroll,
- gfx::Vector2d /* scroll_point */)
-
// Notifies the browser that a frame in the view has changed. This message
// has a lot of parameters and is packed/unpacked by functions defined in
// render_messages.h.
@@ -1549,8 +1585,8 @@ IPC_MESSAGE_ROUTED3(ViewHostMsg_DidFinishLoad,
// title changes.
IPC_MESSAGE_ROUTED3(ViewHostMsg_UpdateTitle,
int32 /* page_id */,
- string16 /* title */,
- WebKit::WebTextDirection /* title direction */)
+ base::string16 /* title */,
+ blink::WebTextDirection /* title direction */)
// Change the encoding name of the page in UI when the page has detected
// proper encoding name.
@@ -1609,19 +1645,12 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_DidRunInsecureContent,
std::string /* security_origin */,
GURL /* target URL */)
-// Sent when the renderer starts a provisional load for a frame.
-IPC_MESSAGE_ROUTED4(ViewHostMsg_DidStartProvisionalLoadForFrame,
- int64 /* frame_id */,
- int64 /* parent_frame_id */,
- bool /* true if it is the main frame */,
- GURL /* url */)
-
IPC_MESSAGE_ROUTED5(ViewHostMsg_DidFailLoadWithError,
int64 /* frame_id */,
GURL /* validated_url */,
bool /* is_main_frame */,
int /* error_code */,
- string16 /* error_description */)
+ base::string16 /* error_description */)
// Sent when the renderer fails a provisional load with an error.
IPC_MESSAGE_ROUTED1(ViewHostMsg_DidFailProvisionalLoadWithError,
@@ -1648,26 +1677,6 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_UpdateIsDelayed)
IPC_MESSAGE_ROUTED1(ViewHostMsg_DidActivateAcceleratedCompositing,
bool /* true if the accelerated compositor is actve */)
-IPC_STRUCT_BEGIN(ViewHostMsg_BeginSmoothScroll_Params)
- IPC_STRUCT_MEMBER(bool, scroll_down)
- IPC_STRUCT_MEMBER(int32, pixels_to_scroll)
- IPC_STRUCT_MEMBER(int32, mouse_event_x)
- IPC_STRUCT_MEMBER(int32, mouse_event_y)
-IPC_STRUCT_END()
-
-IPC_MESSAGE_ROUTED1(ViewHostMsg_BeginSmoothScroll,
- ViewHostMsg_BeginSmoothScroll_Params /* params */)
-
-IPC_STRUCT_BEGIN(ViewHostMsg_BeginPinch_Params)
- IPC_STRUCT_MEMBER(bool, zoom_in)
- IPC_STRUCT_MEMBER(int32, pixels_to_move)
- IPC_STRUCT_MEMBER(int32, anchor_x)
- IPC_STRUCT_MEMBER(int32, anchor_y)
-IPC_STRUCT_END()
-
-IPC_MESSAGE_ROUTED1(ViewHostMsg_BeginPinch,
- ViewHostMsg_BeginPinch_Params /* params */)
-
IPC_MESSAGE_ROUTED0(ViewHostMsg_Focus)
IPC_MESSAGE_ROUTED0(ViewHostMsg_Blur)
@@ -1719,37 +1728,16 @@ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_GetPlugins,
bool /* refresh*/,
std::vector<content::WebPluginInfo> /* plugins */)
-// Return information about a plugin for the given URL and MIME
-// type. If there is no matching plugin, |found| is false.
-// |actual_mime_type| is the actual mime type supported by the
-// found plugin.
-IPC_SYNC_MESSAGE_CONTROL4_3(ViewHostMsg_GetPluginInfo,
- int /* routing_id */,
- GURL /* url */,
- GURL /* page_url */,
- std::string /* mime_type */,
- bool /* found */,
- content::WebPluginInfo /* plugin info */,
- std::string /* actual_mime_type */)
-
-// A renderer sends this to the browser process when it wants to
-// create a plugin. The browser will create the plugin process if
-// necessary, and will return a handle to the channel on success.
-// On error an empty string is returned.
-IPC_SYNC_MESSAGE_CONTROL4_2(ViewHostMsg_OpenChannelToPlugin,
- int /* routing_id */,
- GURL /* url */,
- GURL /* page_url */,
- std::string /* mime_type */,
- IPC::ChannelHandle /* channel_handle */,
- content::WebPluginInfo /* info */)
-
#if defined(OS_WIN)
IPC_MESSAGE_ROUTED1(ViewHostMsg_WindowlessPluginDummyWindowCreated,
gfx::NativeViewId /* dummy_activation_window */)
IPC_MESSAGE_ROUTED1(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
gfx::NativeViewId /* dummy_activation_window */)
+
+// Asks the browser for the user's monitor profile.
+IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetMonitorColorProfile,
+ std::vector<char> /* profile */)
#endif
// Get the list of proxies to use for |url|, as a semicolon delimited list
@@ -1803,7 +1791,7 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_AppCacheAccessed,
IPC_MESSAGE_ROUTED3(ViewHostMsg_DownloadUrl,
GURL /* url */,
content::Referrer /* referrer */,
- string16 /* suggested_name */)
+ base::string16 /* suggested_name */)
// Used to go to the session history entry at the given offset (ie, -1 will
// return the "back" item).
@@ -1820,12 +1808,12 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_RouteMessageEvent,
ViewMsg_PostMessage_Params)
IPC_SYNC_MESSAGE_ROUTED4_2(ViewHostMsg_RunJavaScriptMessage,
- string16 /* in - alert message */,
- string16 /* in - default prompt */,
+ base::string16 /* in - alert message */,
+ base::string16 /* in - default prompt */,
GURL /* in - originating page URL */,
content::JavaScriptMessageType /* in - type */,
bool /* out - success */,
- string16 /* out - user_input field */)
+ base::string16 /* out - user_input field */)
// Requests that the given URL be opened in the specified manner.
IPC_MESSAGE_ROUTED1(ViewHostMsg_OpenURL, ViewHostMsg_OpenURL_Params)
@@ -1865,10 +1853,6 @@ IPC_MESSAGE_ROUTED3(ViewHostMsg_WebUISend,
std::string /* message */,
base::ListValue /* args */)
-// Requests a snapshot of the given window.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_GetWindowSnapshot,
- int /* snapshot_id */)
-
// A renderer sends this to the browser process when it wants to create a ppapi
// plugin. The browser will create the plugin process if necessary, and will
// return a handle to the channel on success.
@@ -1933,14 +1917,6 @@ IPC_MESSAGE_CONTROL2(ViewHostMsg_OpenChannelToPpapiBroker,
int /* routing_id */,
base::FilePath /* path */)
-// Opens a Pepper file asynchronously. The response returns a file descriptor
-// and an error code from base/platform_file.h.
-IPC_MESSAGE_CONTROL4(ViewHostMsg_AsyncOpenPepperFile,
- int /* routing_id */,
- base::FilePath /* file path */,
- int /* pp_open_flags */,
- int /* message_id */)
-
// A renderer sends this to the browser process when it wants to access a PPAPI
// broker. In contrast to ViewHostMsg_OpenChannelToPpapiBroker, this is called
// for every connection.
@@ -1966,8 +1942,8 @@ IPC_SYNC_MESSAGE_ROUTED1_0(ViewHostMsg_DestroyPluginContainer,
// Send the tooltip text for the current mouse position to the browser.
IPC_MESSAGE_ROUTED2(ViewHostMsg_SetTooltipText,
- string16 /* tooltip text string */,
- WebKit::WebTextDirection /* text direction hint */)
+ base::string16 /* tooltip text string */,
+ blink::WebTextDirection /* text direction hint */)
IPC_MESSAGE_ROUTED0(ViewHostMsg_SelectRange_ACK)
IPC_MESSAGE_ROUTED0(ViewHostMsg_MoveCaret_ACK)
@@ -1976,7 +1952,7 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_MoveCaret_ACK)
// Note: The secound parameter is the character based offset of the string16
// text in the document.
IPC_MESSAGE_ROUTED3(ViewHostMsg_SelectionChanged,
- string16 /* text covers the selection range */,
+ base::string16 /* text covers the selection range */,
size_t /* the offset of the text in the document */,
gfx::Range /* selection range in the document */)
@@ -1985,9 +1961,10 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_SelectionBoundsChanged,
ViewHostMsg_SelectionBounds_Params)
// Asks the browser to open the color chooser.
-IPC_MESSAGE_ROUTED2(ViewHostMsg_OpenColorChooser,
+IPC_MESSAGE_ROUTED3(ViewHostMsg_OpenColorChooser,
int /* id */,
- SkColor /* color */)
+ SkColor /* color */,
+ std::vector<content::ColorSuggestion> /* suggestions */)
// Asks the browser to end the color chooser.
IPC_MESSAGE_ROUTED1(ViewHostMsg_EndColorChooser, int /* id */)
@@ -2035,28 +2012,19 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_ImeCancelComposition)
// or debugger UI.
IPC_MESSAGE_ROUTED4(ViewHostMsg_AddMessageToConsole,
int32, /* log level */
- string16, /* msg */
+ base::string16, /* msg */
int32, /* line number */
- string16 /* source id */ )
-
-// Sent by the renderer process to indicate that a plugin instance has crashed.
-// Note: |plugin_pid| should not be trusted. The corresponding process has
-// probably died. Moreover, the ID may have been reused by a new process. Any
-// usage other than displaying it in a prompt to the user is very likely to be
-// wrong.
-IPC_MESSAGE_ROUTED2(ViewHostMsg_CrashedPlugin,
- base::FilePath /* plugin_path */,
- base::ProcessId /* plugin_pid */)
+ base::string16 /* source id */ )
// Displays a box to confirm that the user wants to navigate away from the
// page. Replies true if yes, false otherwise, the reply string is ignored,
// but is included so that we can use OnJavaScriptMessageBoxClosed.
IPC_SYNC_MESSAGE_ROUTED3_2(ViewHostMsg_RunBeforeUnloadConfirm,
- GURL, /* in - originating frame URL */
- string16 /* in - alert message */,
- bool /* in - is a reload */,
- bool /* out - success */,
- string16 /* out - This is ignored.*/)
+ GURL, /* in - originating frame URL */
+ base::string16 /* in - alert message */,
+ bool /* in - is a reload */,
+ bool /* out - success */,
+ base::string16 /* out - This is ignored.*/)
// Sent when a provisional load on the main frame redirects.
IPC_MESSAGE_ROUTED3(ViewHostMsg_DidRedirectProvisionalLoad,
@@ -2155,7 +2123,7 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_JSOutOfMemory)
IPC_MESSAGE_ROUTED4(ViewHostMsg_RegisterProtocolHandler,
std::string /* scheme */,
GURL /* url */,
- string16 /* title */,
+ base::string16 /* title */,
bool /* user_gesture */)
// Stores new inspector setting in the profile.
@@ -2221,15 +2189,6 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_DomOperationResponse,
std::string /* json_string */,
int /* automation_id */)
-// Sent to the browser when the renderer detects it is blocked on a pepper
-// plugin message for too long. This is also sent when it becomes unhung
-// (according to the value of is_hung). The browser can give the user the
-// option of killing the plugin.
-IPC_MESSAGE_ROUTED3(ViewHostMsg_PepperPluginHung,
- int /* plugin_child_id */,
- base::FilePath /* path */,
- bool /* is_hung */)
-
// Notifies that multiple touch targets may have been pressed, and to show
// the disambiguation popup.
IPC_MESSAGE_ROUTED3(ViewHostMsg_ShowDisambiguationPopup,
@@ -2253,19 +2212,6 @@ IPC_MESSAGE_CONTROL3(ViewHostMsg_DidLose3DContext,
content::ThreeDAPIType /* context_type */,
int /* arb_robustness_status_code */)
-// This message is sent when a frame is added to the DOM.
-IPC_MESSAGE_ROUTED3(ViewHostMsg_FrameAttached,
- int64 /* parent_frame_id*/,
- int64 /* frame_id */,
- std::string /* frame_name */)
-
-// Notifies the browser that the frame with the given id was detached. The
-// |parent_frame_id| is -1 for the top level frame, otherwise the id of the
-// immediate parent of the detached frame.
-IPC_MESSAGE_ROUTED2(ViewHostMsg_FrameDetached,
- int64 /* parent_frame_id */,
- int64 /* frame_id */)
-
// Notifies the browser that document has parsed the body. This is used by the
// ResourceScheduler as an indication that bandwidth contention won't block
// first paint.
@@ -2281,6 +2227,37 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateFaviconURL,
IPC_MESSAGE_ROUTED1(ViewHostMsg_DidFirstVisuallyNonEmptyPaint,
int /* page_id */)
+// Sent by the renderer to the browser to start a vibration with the given
+// duration.
+IPC_MESSAGE_CONTROL1(ViewHostMsg_Vibrate,
+ int64 /* milliseconds */)
+
+// Sent by the renderer to the browser to cancel the currently running
+// vibration, if there is one.
+IPC_MESSAGE_CONTROL0(ViewHostMsg_CancelVibration)
+
+// Message sent from renderer to the browser when the element that is focused
+// has been touched. A bool is passed in this message which indicates if the
+// node is editable.
+IPC_MESSAGE_ROUTED1(ViewHostMsg_FocusedNodeTouched,
+ bool /* editable */)
+
+// Message sent from the renderer to the browser when an HTML form has failed
+// validation constraints.
+IPC_MESSAGE_ROUTED3(ViewHostMsg_ShowValidationMessage,
+ gfx::Rect /* anchor rectangle in root view coordinate */,
+ base::string16 /* validation message */,
+ base::string16 /* supplemental text */)
+
+// Message sent from the renderer to the browser when a HTML form validation
+// message should be hidden from view.
+IPC_MESSAGE_ROUTED0(ViewHostMsg_HideValidationMessage)
+
+// Message sent from the renderer to the browser when the suggested co-ordinates
+// of the anchor for a HTML form validation message have changed.
+IPC_MESSAGE_ROUTED1(ViewHostMsg_MoveValidationMessage,
+ gfx::Rect /* anchor rectangle in root view coordinate */)
+
#if defined(OS_ANDROID)
// Response to ViewMsg_FindMatchRects.
//
@@ -2310,11 +2287,6 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_StartContentIntent,
IPC_MESSAGE_ROUTED1(ViewHostMsg_DidChangeBodyBackgroundColor,
uint32 /* bg_color */)
-// This message is an ACK that the batch state change has been received by
-// the renderer and all IME related messages should be processed accordingly.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_ImeBatchStateChanged_ACK,
- bool /* is_begin */)
-
// This message runs the MediaCodec for decoding audio for webaudio.
IPC_MESSAGE_CONTROL3(ViewHostMsg_RunWebAudioMediaCodec,
base::SharedMemoryHandle /* encoded_data_handle */,
@@ -2327,14 +2299,13 @@ IPC_MESSAGE_CONTROL3(ViewHostMsg_RunWebAudioMediaCodec,
IPC_MESSAGE_ROUTED1(ViewHostMsg_SetNeedsBeginFrame,
bool /* enabled */)
-// Sent by the renderer to the browser to start a vibration with the given
-// duration.
-IPC_MESSAGE_CONTROL1(ViewHostMsg_Vibrate,
- int64 /* milliseconds */)
-
-// Sent by the renderer to the browser to cancel the currently running
-// vibration, if there is one.
-IPC_MESSAGE_CONTROL0(ViewHostMsg_CancelVibration)
+// Reply to the ViewMsg_ExtractSmartClipData message.
+// TODO(juhui24.lee@samsung.com): this should be changed to a vector of structs
+// instead of encoding the data as a string which is not allowed normally. Since
+// ths is only used in Android WebView, it's allowed temporarily.
+// http://crbug.com/330872
+IPC_MESSAGE_ROUTED1(ViewHostMsg_SmartClipDataExtracted,
+ string16)
#elif defined(OS_MACOSX)
// Request that the browser load a font into shared memory for us.
@@ -2358,7 +2329,7 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_StartPluginIme)
// for details.
IPC_SYNC_MESSAGE_CONTROL2_0(ViewHostMsg_PreCacheFontCharacters,
LOGFONT /* font_data */,
- string16 /* characters */)
+ base::string16 /* characters */)
#endif
#if defined(OS_POSIX)
diff --git a/chromium/content/common/websocket.cc b/chromium/content/common/websocket.cc
new file mode 100644
index 00000000000..b1d57611f68
--- /dev/null
+++ b/chromium/content/common/websocket.cc
@@ -0,0 +1,18 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/websocket.h"
+
+namespace content {
+
+WebSocketHandshakeRequest::WebSocketHandshakeRequest() {}
+
+WebSocketHandshakeRequest::~WebSocketHandshakeRequest() {}
+
+WebSocketHandshakeResponse::WebSocketHandshakeResponse()
+ : status_code(0) {}
+
+WebSocketHandshakeResponse::~WebSocketHandshakeResponse() {}
+
+} // namespace content
diff --git a/chromium/content/common/websocket.h b/chromium/content/common/websocket.h
index 3bc8a99532c..98d75faf08e 100644
--- a/chromium/content/common/websocket.h
+++ b/chromium/content/common/websocket.h
@@ -5,6 +5,13 @@
#ifndef CONTENT_COMMON_WEBSOCKET_H_
#define CONTENT_COMMON_WEBSOCKET_H_
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/time/time.h"
+#include "url/gurl.h"
+
namespace content {
// WebSocket data message types sent between the browser and renderer processes.
@@ -14,6 +21,38 @@ enum WebSocketMessageType {
WEB_SOCKET_MESSAGE_TYPE_BINARY = 0x2
};
+// Opening handshake request information which will be shown in the inspector.
+// All string data should be encoded to ASCII in the browser process.
+struct WebSocketHandshakeRequest {
+ WebSocketHandshakeRequest();
+ ~WebSocketHandshakeRequest();
+
+ // The request URL
+ GURL url;
+ // Additional HTTP request headers
+ std::vector<std::pair<std::string, std::string> > headers;
+ // The time that this request is sent
+ base::Time request_time;
+};
+
+// Opening handshake response information which will be shown in the inspector.
+// All string data should be encoded to ASCII in the browser process.
+struct WebSocketHandshakeResponse {
+ WebSocketHandshakeResponse();
+ ~WebSocketHandshakeResponse();
+
+ // The request URL
+ GURL url;
+ // HTTP status code
+ int status_code;
+ // HTTP status text
+ std::string status_text;
+ // Additional HTTP response headers
+ std::vector<std::pair<std::string, std::string> > headers;
+ // The time that this response arrives
+ base::Time response_time;
+};
+
} // namespace content
#endif // CONTENT_COMMON_WEBSOCKET_H_
diff --git a/chromium/content/common/websocket_messages.h b/chromium/content/common/websocket_messages.h
index a3dd68cb671..dadece4706d 100644
--- a/chromium/content/common/websocket_messages.h
+++ b/chromium/content/common/websocket_messages.h
@@ -26,6 +26,20 @@
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START WebSocketMsgStart
+IPC_STRUCT_TRAITS_BEGIN(content::WebSocketHandshakeRequest)
+ IPC_STRUCT_TRAITS_MEMBER(url)
+ IPC_STRUCT_TRAITS_MEMBER(headers)
+ IPC_STRUCT_TRAITS_MEMBER(request_time)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::WebSocketHandshakeResponse)
+ IPC_STRUCT_TRAITS_MEMBER(url)
+ IPC_STRUCT_TRAITS_MEMBER(status_code)
+ IPC_STRUCT_TRAITS_MEMBER(status_text)
+ IPC_STRUCT_TRAITS_MEMBER(headers)
+ IPC_STRUCT_TRAITS_MEMBER(response_time)
+IPC_STRUCT_TRAITS_END()
+
// WebSocket messages sent from the renderer to the browser.
// Open new virtual WebSocket connection to |socket_url|. |channel_id| is an
@@ -38,13 +52,12 @@
// The browser process will not send |channel_id| as-is to the remote server; it
// will try to use a short id on the wire. This saves the renderer from
// having to try to choose the ids cleverly.
-IPC_MESSAGE_CONTROL4(WebSocketHostMsg_AddChannelRequest,
- int /* channel_id */,
- GURL /* socket_url */,
- std::vector<std::string> /* requested_protocols */,
- GURL /* origin */)
+IPC_MESSAGE_ROUTED3(WebSocketHostMsg_AddChannelRequest,
+ GURL /* socket_url */,
+ std::vector<std::string> /* requested_protocols */,
+ GURL /* origin */)
-// Web Socket messages sent from the browser to the renderer.
+// WebSocket messages sent from the browser to the renderer.
// Respond to an AddChannelRequest for channel |channel_id|. |channel_id| is
// scoped to the renderer process; while it is unique per-renderer, the browser
@@ -55,11 +68,36 @@ IPC_MESSAGE_CONTROL4(WebSocketHostMsg_AddChannelRequest,
// re-use. |selected_protocol| is the sub-protocol the server selected,
// or empty if no sub-protocol was selected. |extensions| is the list of
// extensions negotiated for the connection.
-IPC_MESSAGE_CONTROL4(WebSocketMsg_AddChannelResponse,
- int /* channel_id */,
- bool /* fail */,
- std::string /* selected_protocol */,
- std::string /* extensions */)
+IPC_MESSAGE_ROUTED3(WebSocketMsg_AddChannelResponse,
+ bool /* fail */,
+ std::string /* selected_protocol */,
+ std::string /* extensions */)
+
+// Notify the renderer that the browser has started an opening handshake.
+// This message is for showing the request in the inspector and
+// can be omitted if the inspector is not active.
+IPC_MESSAGE_ROUTED1(WebSocketMsg_NotifyStartOpeningHandshake,
+ content::WebSocketHandshakeRequest /* request */)
+
+// Notify the renderer that the browser has finished an opening handshake.
+// This message precedes AddChannelResponse.
+// This message is for showing the response in the inspector and
+// can be omitted if the inspector is not active.
+IPC_MESSAGE_ROUTED1(WebSocketMsg_NotifyFinishOpeningHandshake,
+ content::WebSocketHandshakeResponse /* response */)
+
+// Notify the renderer that the browser is required to fail the connection
+// (see RFC6455 7.1.7 for details).
+// When the renderer process receives this messages it does the following:
+// 1. Fire an error event.
+// 2. Show |message| to the inspector.
+// 3. Close the channel immediately uncleanly, as if it received
+// DropChannel(was_clean = false, code = 1006, reason = "").
+// |message| will be shown in the inspector and won't be passed to the script.
+// TODO(yhirano): Find the way to pass |message| directly to the inspector
+// process.
+IPC_MESSAGE_ROUTED1(WebSocketMsg_NotifyFailure,
+ std::string /* message */)
// WebSocket messages that can be sent in either direction.
@@ -75,11 +113,10 @@ IPC_ENUM_TRAITS(content::WebSocketMessageType)
// first message. If |type| is WEB_SOCKET_MESSAGE_TYPE_TEXT, then the
// concatenation of the |data| from every frame in the message must be valid
// UTF-8. If |fin| is not set, |data| must be non-empty.
-IPC_MESSAGE_CONTROL4(WebSocketMsg_SendFrame,
- int /* channel_id */,
- bool /* fin */,
- content::WebSocketMessageType /* type */,
- std::vector<char> /* data */)
+IPC_MESSAGE_ROUTED3(WebSocketMsg_SendFrame,
+ bool /* fin */,
+ content::WebSocketMessageType /* type */,
+ std::vector<char> /* data */)
// Add |quota| tokens of send quota for channel |channel_id|. |quota| must be a
// positive integer. Both the browser and the renderer set send quota for the
@@ -87,9 +124,8 @@ IPC_MESSAGE_CONTROL4(WebSocketMsg_SendFrame,
// messages. Both sides start a new channel with a quota of 0, and must wait for
// a FlowControl message before calling SendFrame. The total available quota on
// one side must never exceed 0x7FFFFFFFFFFFFFFF tokens.
-IPC_MESSAGE_CONTROL2(WebSocketMsg_FlowControl,
- int /* channel_id */,
- int64 /* quota */)
+IPC_MESSAGE_ROUTED1(WebSocketMsg_FlowControl,
+ int64 /* quota */)
// Drop the channel.
// When sent by the renderer, this will cause a DropChannel message to be sent
@@ -104,7 +140,12 @@ IPC_MESSAGE_CONTROL2(WebSocketMsg_FlowControl,
// UTF-8 encoded string which may be useful for debugging but is not necessarily
// human-readable, as supplied by the server in the Close or DropChannel
// message.
-IPC_MESSAGE_CONTROL3(WebSocketMsg_DropChannel,
- int /* channel_id */,
- unsigned short /* code */,
- std::string /* reason */)
+// If |was_clean| is false on a message from the browser, then the WebSocket
+// connection was not closed cleanly. If |was_clean| is false on a message from
+// the renderer, then the connection should be closed immediately without a
+// closing handshake and the renderer cannot accept any new messages on this
+// connection.
+IPC_MESSAGE_ROUTED3(WebSocketMsg_DropChannel,
+ bool /* was_clean */,
+ unsigned short /* code */,
+ std::string /* reason */)
diff --git a/chromium/content/common/worker_messages.h b/chromium/content/common/worker_messages.h
index 6f20461ec3e..6145f802b4e 100644
--- a/chromium/content/common/worker_messages.h
+++ b/chromium/content/common/worker_messages.h
@@ -19,14 +19,6 @@
#include "third_party/WebKit/public/web/WebContentSecurityPolicy.h"
#include "url/gurl.h"
-// Singly-included section, not converted.
-#ifndef CONTENT_COMMON_WORKER_MESSAGES_H_
-#define CONTENT_COMMON_WORKER_MESSAGES_H_
-
-typedef std::pair<string16, std::vector<int> > QueuedMessage;
-
-#endif // CONTENT_COMMON_WORKER_MESSAGES_H_
-
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START WorkerMsgStart
@@ -39,21 +31,21 @@ IPC_STRUCT_BEGIN(WorkerHostMsg_PostConsoleMessageToWorkerObject_Params)
IPC_STRUCT_MEMBER(int, source_identifier)
IPC_STRUCT_MEMBER(int, message_type)
IPC_STRUCT_MEMBER(int, message_level)
- IPC_STRUCT_MEMBER(string16, message)
+ IPC_STRUCT_MEMBER(base::string16, message)
IPC_STRUCT_MEMBER(int, line_number)
- IPC_STRUCT_MEMBER(string16, source_url)
+ IPC_STRUCT_MEMBER(base::string16, source_url)
IPC_STRUCT_END()
// Parameter structure for WorkerProcessMsg_CreateWorker.
IPC_STRUCT_BEGIN(WorkerProcessMsg_CreateWorker_Params)
IPC_STRUCT_MEMBER(GURL, url)
- IPC_STRUCT_MEMBER(string16, name)
+ IPC_STRUCT_MEMBER(base::string16, name)
IPC_STRUCT_MEMBER(int, route_id)
IPC_STRUCT_MEMBER(int, creator_process_id)
IPC_STRUCT_MEMBER(int64, shared_worker_appcache_id)
IPC_STRUCT_END()
-IPC_ENUM_TRAITS(WebKit::WebContentSecurityPolicyType)
+IPC_ENUM_TRAITS(blink::WebContentSecurityPolicyType)
//-----------------------------------------------------------------------------
// WorkerProcess messages
@@ -61,71 +53,17 @@ IPC_ENUM_TRAITS(WebKit::WebContentSecurityPolicyType)
IPC_MESSAGE_CONTROL1(WorkerProcessMsg_CreateWorker,
WorkerProcessMsg_CreateWorker_Params)
-// Note: these Message Port related messages can also be sent to the
-// renderer process. Putting them here since we don't have a shared place
-// like common_messages_internal.h
-IPC_MESSAGE_ROUTED3(WorkerProcessMsg_Message,
- string16 /* message */,
- std::vector<int> /* sent_message_port_ids */,
- std::vector<int> /* new_routing_ids */)
-
-// Tells the Message Port Channel object that there are no more in-flight
-// messages arriving.
-IPC_MESSAGE_ROUTED0(WorkerProcessMsg_MessagesQueued)
-
-
//-----------------------------------------------------------------------------
// WorkerProcessHost messages
// These are messages sent from the worker process to the browser process.
-// Note: these Message Port related messages can also be sent out from the
-// renderer process. Putting them here since we don't have a shared place
-// like common_messages_internal.h
-
-// Creates a new Message Port Channel object. The first paramaeter is the
-// message port channel's routing id in this process. The second parameter
-// is the process-wide-unique identifier for that port.
-IPC_SYNC_MESSAGE_CONTROL0_2(WorkerProcessHostMsg_CreateMessagePort,
- int /* route_id */,
- int /* message_port_id */)
-
-// Sent when a Message Port Channel object is destroyed.
-IPC_MESSAGE_CONTROL1(WorkerProcessHostMsg_DestroyMessagePort,
- int /* message_port_id */)
-
-// Sends a message to a message port. Optionally sends a message port as
-// as well if sent_message_port_id != MSG_ROUTING_NONE.
-IPC_MESSAGE_CONTROL3(WorkerProcessHostMsg_PostMessage,
- int /* sender_message_port_id */,
- string16 /* message */,
- std::vector<int> /* sent_message_port_ids */)
-
-// Causes messages sent to the remote port to be delivered to this local port.
-IPC_MESSAGE_CONTROL2(WorkerProcessHostMsg_Entangle,
- int /* local_message_port_id */,
- int /* remote_message_port_id */)
-
-// Causes the browser to queue messages sent to this port until the the port
-// has made sure that all in-flight messages were routed to the new
-// destination.
-IPC_MESSAGE_CONTROL1(WorkerProcessHostMsg_QueueMessages,
- int /* message_port_id */)
-
-// Sends the browser all the queued messages that arrived at this message port
-// after it was sent in a postMessage call.
-// NOTE: MSVS can't compile the macro if std::vector<std::pair<string16, int> >
-// is used, so we typedef it in worker_messages.h.
-IPC_MESSAGE_CONTROL2(WorkerProcessHostMsg_SendQueuedMessages,
- int /* message_port_id */,
- std::vector<QueuedMessage> /* queued_messages */)
-
// Sent by the worker process to check whether access to web databases is
// allowed.
IPC_SYNC_MESSAGE_CONTROL5_1(WorkerProcessHostMsg_AllowDatabase,
int /* worker_route_id */,
GURL /* origin url */,
- string16 /* database name */,
- string16 /* database display name */,
+ base::string16 /* database name */,
+ base::string16 /* database display name */,
unsigned long /* estimated size */,
bool /* result */)
@@ -139,26 +77,25 @@ IPC_SYNC_MESSAGE_CONTROL2_1(WorkerProcessHostMsg_AllowFileSystem,
IPC_SYNC_MESSAGE_CONTROL3_1(WorkerProcessHostMsg_AllowIndexedDB,
int /* worker_route_id */,
GURL /* origin url */,
- string16 /* database name */,
+ base::string16 /* database name */,
bool /* result */)
+// Sent by the worker process to request being killed.
+IPC_SYNC_MESSAGE_CONTROL0_0(WorkerProcessHostMsg_ForceKillWorker)
+
+
//-----------------------------------------------------------------------------
// Worker messages
// These are messages sent from the renderer process to the worker process.
IPC_MESSAGE_ROUTED5(WorkerMsg_StartWorkerContext,
GURL /* url */,
- string16 /* user_agent */,
- string16 /* source_code */,
- string16 /* content_security_policy */,
- WebKit::WebContentSecurityPolicyType)
+ base::string16 /* user_agent */,
+ base::string16 /* source_code */,
+ base::string16 /* content_security_policy */,
+ blink::WebContentSecurityPolicyType)
IPC_MESSAGE_ROUTED0(WorkerMsg_TerminateWorkerContext)
-IPC_MESSAGE_ROUTED3(WorkerMsg_PostMessage,
- string16 /* message */,
- std::vector<int> /* sent_message_port_ids */,
- std::vector<int> /* new_routing_ids */)
-
IPC_MESSAGE_ROUTED2(WorkerMsg_Connect,
int /* sent_message_port_id */,
int /* routing_id */)
@@ -170,20 +107,6 @@ IPC_MESSAGE_ROUTED0(WorkerMsg_WorkerObjectDestroyed)
// WorkerHost messages
// These are messages sent from the worker process to the renderer process.
// WorkerMsg_PostMessage is also sent here.
-IPC_MESSAGE_ROUTED3(WorkerHostMsg_PostExceptionToWorkerObject,
- string16 /* error_message */,
- int /* line_number */,
- string16 /* source_url*/)
-
-IPC_MESSAGE_ROUTED1(WorkerHostMsg_PostConsoleMessageToWorkerObject,
- WorkerHostMsg_PostConsoleMessageToWorkerObject_Params)
-
-IPC_MESSAGE_ROUTED1(WorkerHostMsg_ConfirmMessageFromWorkerObject,
- bool /* bool has_pending_activity */)
-
-IPC_MESSAGE_ROUTED1(WorkerHostMsg_ReportPendingActivity,
- bool /* bool has_pending_activity */)
-
IPC_MESSAGE_CONTROL1(WorkerHostMsg_WorkerContextClosed,
int /* worker_route_id */)
IPC_MESSAGE_ROUTED0(WorkerHostMsg_WorkerContextDestroyed)
diff --git a/chromium/content/content.gyp b/chromium/content/content.gyp
index 221a1a53928..14504ee8e57 100644
--- a/chromium/content/content.gyp
+++ b/chromium/content/content.gyp
@@ -21,14 +21,10 @@
}],
],
},
- 'includes': [
- 'content_tests.gypi',
- ],
'conditions': [
['OS != "ios"', {
'includes': [
'../build/win_precompile.gypi',
- 'content_shell.gypi',
],
}],
# In component mode, we build all of content as a single DLL.
@@ -396,10 +392,11 @@
'../base/base.gyp:base',
'../media/media.gyp:media_java',
'../net/net.gyp:net',
- '../ui/ui.gyp:ui_java',
+ '../ui/android/ui_android.gyp:ui_java',
'common_aidl',
'content_common',
'page_transition_types_java',
+ 'popup_item_type_java',
'result_codes_java',
'speech_recognition_error_java',
'top_controls_state_java',
@@ -436,6 +433,18 @@
'includes': [ '../build/android/java_cpp_template.gypi' ],
},
{
+ 'target_name': 'popup_item_type_java',
+ 'type': 'none',
+ 'sources': [
+ 'public/android/java/src/org/chromium/content/browser/input/PopupItemType.template',
+ ],
+ 'variables': {
+ 'package_name': 'org/chromium/content/browser/input',
+ 'template_deps': ['browser/android/popup_item_type_list.h'],
+ },
+ 'includes': [ '../build/android/java_cpp_template.gypi' ],
+ },
+ {
'target_name': 'result_codes_java',
'type': 'none',
'sources': [
@@ -480,12 +489,11 @@
},
'includes': [ '../build/jar_file_jni_generator.gypi' ],
},
-
{
'target_name': 'content_jni_headers',
'type': 'none',
'dependencies': [
- 'java_set_jni_headers',
+ 'java_set_jni_headers'
],
'direct_dependent_settings': {
'include_dirs': [
@@ -494,6 +502,24 @@
},
'includes': [ 'content_jni.gypi' ],
},
+ {
+ 'target_name': 'content_android_linker',
+ 'type': 'shared_library',
+ 'conditions': [
+ ['android_webview_build == 0', {
+ # Avoid breaking the webview build because it doesn't have
+ # <(android_ndk_root)/crazy_linker.gyp. Note that it never uses
+ # the linker anyway.
+ 'sources': [
+ 'common/android/linker/linker_jni.cc',
+ ],
+ 'dependencies': [
+ '<(android_ndk_root)/crazy_linker.gyp:crazy_linker',
+ ],
+ }],
+ ],
+ },
+
],
}], # OS == "android"
],
diff --git a/chromium/content/content_app.gypi b/chromium/content/content_app.gypi
index 2055f21e4ce..127b5934bff 100644
--- a/chromium/content/content_app.gypi
+++ b/chromium/content/content_app.gypi
@@ -10,6 +10,7 @@
'../base/base.gyp:base',
'../base/base.gyp:base_i18n',
'../crypto/crypto.gyp:crypto',
+ '../ui/gfx/gfx.gyp:gfx',
'../ui/ui.gyp:ui',
],
'sources': [
diff --git a/chromium/content/content_browser.gypi b/chromium/content/content_browser.gypi
index f820ad028a8..28878f77e47 100644
--- a/chromium/content/content_browser.gypi
+++ b/chromium/content/content_browser.gypi
@@ -4,7 +4,6 @@
{
'dependencies': [
- 'browser/speech/proto/speech_proto.gyp:speech_proto',
'../base/base.gyp:base_static',
'../crypto/crypto.gyp:crypto',
'../google_apis/google_apis.gyp:google_apis',
@@ -14,9 +13,12 @@
'../third_party/re2/re2.gyp:re2',
'../third_party/zlib/google/zip.gyp:zip',
'../third_party/zlib/zlib.gyp:zlib',
+ '../ui/events/events.gyp:events_base',
+ '../ui/gfx/gfx.gyp:gfx',
+ '../ui/resources/ui_resources.gyp:ui_resources',
'../ui/snapshot/snapshot.gyp:snapshot',
'../ui/ui.gyp:ui',
- '../ui/ui.gyp:ui_resources',
+ 'browser/speech/proto/speech_proto.gyp:speech_proto',
],
'include_dirs': [
'..',
@@ -27,7 +29,7 @@
'port/browser/location_provider.h',
'port/browser/render_view_host_delegate_view.h',
'port/browser/render_widget_host_view_port.h',
- 'port/browser/synthetic_gesture.h',
+ 'port/browser/vibration_provider.h',
'port/browser/web_contents_view_port.h',
'public/browser/access_token_store.h',
'public/browser/android/compositor.h',
@@ -69,6 +71,8 @@
'public/browser/content_browser_client.cc',
'public/browser/content_browser_client.h',
'public/browser/cookie_store_factory.h',
+ 'public/browser/desktop_media_id.cc',
+ 'public/browser/desktop_media_id.h',
'public/browser/devtools_agent_host.h',
'public/browser/devtools_client_host.h',
'public/browser/devtools_external_agent_proxy.h',
@@ -78,6 +82,7 @@
'public/browser/devtools_http_handler.h',
'public/browser/devtools_http_handler_delegate.h',
'public/browser/devtools_manager.h',
+ 'public/browser/devtools_target.h',
'public/browser/dom_operation_notification_details.h',
'public/browser/dom_storage_context.h',
'public/browser/download_destination_observer.h',
@@ -114,6 +119,8 @@
'public/browser/load_notification_details.h',
'public/browser/local_storage_usage_info.cc',
'public/browser/local_storage_usage_info.h',
+ 'public/browser/media_device_id.cc',
+ 'public/browser/media_device_id.h',
'public/browser/media_devices_monitor.h',
'public/browser/native_web_keyboard_event.h',
'public/browser/navigation_controller.cc',
@@ -143,9 +150,8 @@
'public/browser/render_frame_host.h',
'public/browser/render_process_host.h',
'public/browser/render_process_host_factory.h',
+ 'public/browser/render_process_host_observer.h',
'public/browser/render_view_host.h',
- 'public/browser/render_view_host_observer.cc',
- 'public/browser/render_view_host_observer.h',
'public/browser/render_widget_host.h',
'public/browser/render_widget_host_view.h',
'public/browser/render_widget_host_view_mac_delegate.h',
@@ -162,6 +168,7 @@
'public/browser/save_page_type.h',
'public/browser/session_storage_namespace.h',
'public/browser/session_storage_usage_info.h',
+ 'public/browser/signed_certificate_timestamp_store.h',
'public/browser/site_instance.h',
'public/browser/speech_recognition_event_listener.h',
'public/browser/speech_recognition_manager.h',
@@ -172,8 +179,6 @@
'public/browser/speech_recognition_session_context.h',
'public/browser/storage_partition.h',
'public/browser/stream_handle.h',
- 'public/browser/trace_controller.h',
- 'public/browser/trace_subscriber.h',
'public/browser/tracing_controller.h',
'public/browser/user_metrics.h',
'public/browser/utility_process_host.h',
@@ -271,14 +276,13 @@
'browser/android/load_url_params.h',
'browser/android/overscroll_glow.h',
'browser/android/overscroll_glow.cc',
+ 'browser/android/popup_item_type_list.h',
'browser/android/surface_texture_peer_browser_impl.cc',
'browser/android/surface_texture_peer_browser_impl.h',
'browser/android/touch_point.cc',
'browser/android/touch_point.h',
- 'browser/android/tracing_intent_handler.cc',
- 'browser/android/tracing_intent_handler.h',
- 'browser/android/vibration_message_filter.cc',
- 'browser/android/vibration_message_filter.h',
+ 'browser/android/tracing_controller_android.cc',
+ 'browser/android/tracing_controller_android.h',
'browser/android/web_contents_observer_android.cc',
'browser/android/web_contents_observer_android.h',
'browser/appcache/appcache_dispatcher_host.cc',
@@ -299,12 +303,18 @@
'browser/aura/image_transport_factory.h',
'browser/aura/no_transport_image_transport_factory.cc',
'browser/aura/no_transport_image_transport_factory.h',
+ 'browser/aura/owned_mailbox.h',
+ 'browser/aura/owned_mailbox.cc',
'browser/aura/reflector_impl.cc',
'browser/aura/reflector_impl.h',
'browser/aura/resize_lock.cc',
'browser/aura/resize_lock.h',
+ 'browser/aura/gpu_browser_compositor_output_surface.cc',
+ 'browser/aura/gpu_browser_compositor_output_surface.h',
'browser/aura/software_browser_compositor_output_surface.cc',
'browser/aura/software_browser_compositor_output_surface.h',
+ 'browser/aura/software_output_device_ozone.cc',
+ 'browser/aura/software_output_device_ozone.h',
'browser/aura/software_output_device_win.cc',
'browser/aura/software_output_device_win.h',
'browser/aura/software_output_device_x11.cc',
@@ -324,8 +334,6 @@
'browser/browser_plugin/browser_plugin_geolocation_permission_context.h',
'browser/browser_plugin/browser_plugin_guest.cc',
'browser/browser_plugin/browser_plugin_guest.h',
- 'browser/browser_plugin/browser_plugin_guest_helper.cc',
- 'browser/browser_plugin/browser_plugin_guest_helper.h',
'browser/browser_plugin/browser_plugin_guest_manager.cc',
'browser/browser_plugin/browser_plugin_guest_manager.h',
'browser/browser_plugin/browser_plugin_host_factory.h',
@@ -387,19 +395,12 @@
'browser/devtools/worker_devtools_manager.h',
'browser/devtools/worker_devtools_message_filter.cc',
'browser/devtools/worker_devtools_message_filter.h',
- 'browser/device_monitor_linux.cc',
- 'browser/device_monitor_linux.h',
'browser/device_monitor_mac.h',
'browser/device_monitor_mac.mm',
- 'browser/device_orientation/accelerometer_mac.cc',
- 'browser/device_orientation/accelerometer_mac.h',
- 'browser/device_orientation/data_fetcher.h',
+ 'browser/device_monitor_udev.cc',
+ 'browser/device_monitor_udev.h',
'browser/device_orientation/data_fetcher_impl_android.cc',
'browser/device_orientation/data_fetcher_impl_android.h',
- 'browser/device_orientation/data_fetcher_impl_win.cc',
- 'browser/device_orientation/data_fetcher_impl_win.h',
- 'browser/device_orientation/data_fetcher_orientation_android.cc',
- 'browser/device_orientation/data_fetcher_orientation_android.h',
'browser/device_orientation/data_fetcher_shared_memory.h',
'browser/device_orientation/data_fetcher_shared_memory_android.cc',
'browser/device_orientation/data_fetcher_shared_memory_base.cc',
@@ -415,18 +416,6 @@
'browser/device_orientation/device_orientation_message_filter.cc',
'browser/device_orientation/device_orientation_message_filter.h',
'browser/device_orientation/inertial_sensor_consts.h',
- 'browser/device_orientation/message_filter.cc',
- 'browser/device_orientation/message_filter.h',
- 'browser/device_orientation/observer_delegate.cc',
- 'browser/device_orientation/observer_delegate.h',
- 'browser/device_orientation/orientation.cc',
- 'browser/device_orientation/orientation.h',
- 'browser/device_orientation/orientation_message_filter.cc',
- 'browser/device_orientation/orientation_message_filter.h',
- 'browser/device_orientation/provider.cc',
- 'browser/device_orientation/provider.h',
- 'browser/device_orientation/provider_impl.cc',
- 'browser/device_orientation/provider_impl.h',
'browser/dom_storage/dom_storage_area.cc',
'browser/dom_storage/dom_storage_area.h',
'browser/dom_storage/dom_storage_context_impl.cc',
@@ -515,6 +504,39 @@
'browser/fileapi/fileapi_message_filter.cc',
'browser/fileapi/fileapi_message_filter.h',
'browser/font_list_async.cc',
+ 'browser/frame_host/debug_urls.cc',
+ 'browser/frame_host/debug_urls.h',
+ 'browser/frame_host/frame_tree.cc',
+ 'browser/frame_host/frame_tree.h',
+ 'browser/frame_host/frame_tree_node.cc',
+ 'browser/frame_host/frame_tree_node.h',
+ 'browser/frame_host/interstitial_page_impl.cc',
+ 'browser/frame_host/interstitial_page_impl.h',
+ 'browser/frame_host/interstitial_page_navigator_impl.cc',
+ 'browser/frame_host/interstitial_page_navigator_impl.h',
+ 'browser/frame_host/navigation_controller_android.cc',
+ 'browser/frame_host/navigation_controller_android.h',
+ 'browser/frame_host/navigation_controller_delegate.h',
+ 'browser/frame_host/navigation_controller_impl.cc',
+ 'browser/frame_host/navigation_controller_impl.h',
+ 'browser/frame_host/navigation_entry_impl.cc',
+ 'browser/frame_host/navigation_entry_impl.h',
+ 'browser/frame_host/navigation_entry_screenshot_manager.cc',
+ 'browser/frame_host/navigation_entry_screenshot_manager.h',
+ 'browser/frame_host/navigator.h',
+ 'browser/frame_host/navigator_impl.cc',
+ 'browser/frame_host/navigator_impl.h',
+ 'browser/frame_host/navigator_delegate.h',
+ 'browser/frame_host/render_frame_host_delegate.cc',
+ 'browser/frame_host/render_frame_host_delegate.h',
+ 'browser/frame_host/render_frame_host_factory.cc',
+ 'browser/frame_host/render_frame_host_factory.h',
+ 'browser/frame_host/render_frame_host_impl.cc',
+ 'browser/frame_host/render_frame_host_impl.h',
+ 'browser/frame_host/render_frame_host_manager.cc',
+ 'browser/frame_host/render_frame_host_manager.h',
+ 'browser/frame_host/render_frame_message_filter.cc',
+ 'browser/frame_host/render_frame_message_filter.h',
'browser/gamepad/gamepad_data_fetcher.h',
'browser/gamepad/gamepad_platform_data_fetcher.h',
'browser/gamepad/gamepad_platform_data_fetcher_linux.cc',
@@ -539,8 +561,6 @@
'browser/geolocation/geolocation_dispatcher_host.h',
'browser/geolocation/geolocation_provider_impl.cc',
'browser/geolocation/geolocation_provider_impl.h',
- 'browser/geolocation/gps_location_provider_linux.cc',
- 'browser/geolocation/gps_location_provider_linux.h',
'browser/geolocation/location_api_adapter_android.cc',
'browser/geolocation/location_api_adapter_android.h',
'browser/geolocation/location_arbitrator.h',
@@ -652,8 +672,8 @@
'browser/loader/certificate_resource_handler.h',
'browser/loader/cross_site_resource_handler.cc',
'browser/loader/cross_site_resource_handler.h',
- 'browser/loader/doomed_resource_handler.cc',
- 'browser/loader/doomed_resource_handler.h',
+ 'browser/loader/detachable_resource_handler.cc',
+ 'browser/loader/detachable_resource_handler.h',
'browser/loader/global_routing_id.h',
'browser/loader/layered_resource_handler.cc',
'browser/loader/layered_resource_handler.h',
@@ -663,8 +683,6 @@
'browser/loader/power_save_block_resource_throttle.h',
'browser/loader/redirect_to_file_resource_handler.cc',
'browser/loader/redirect_to_file_resource_handler.h',
- 'browser/loader/render_view_host_tracker.cc',
- 'browser/loader/render_view_host_tracker.h',
'browser/loader/resource_buffer.cc',
'browser/loader/resource_buffer.h',
'browser/loader/resource_dispatcher_host_impl.cc',
@@ -690,8 +708,6 @@
'browser/loader/sync_resource_handler.h',
'browser/loader/throttling_resource_handler.cc',
'browser/loader/throttling_resource_handler.h',
- 'browser/loader/transfer_navigation_resource_throttle.cc',
- 'browser/loader/transfer_navigation_resource_throttle.h',
'browser/loader/upload_data_stream_builder.cc',
'browser/loader/upload_data_stream_builder.h',
'browser/mach_broker_mac.h',
@@ -704,6 +720,7 @@
'browser/media/android/media_drm_credential_manager.h',
'browser/media/android/media_resource_getter_impl.cc',
'browser/media/android/media_resource_getter_impl.h',
+ 'browser/media/media_devices_monitor.cc',
'browser/media/media_internals.cc',
'browser/media/media_internals.h',
'browser/media/media_internals_handler.cc',
@@ -723,13 +740,12 @@
'browser/media/webrtc_internals_ui.cc',
'browser/media/webrtc_internals_ui.h',
'browser/media/webrtc_internals_ui_observer.h',
- 'browser/media_devices_monitor.cc',
+ 'browser/message_port_message_filter.cc',
+ 'browser/message_port_message_filter.h',
+ 'browser/message_port_service.cc',
+ 'browser/message_port_service.h',
'browser/mime_registry_message_filter.cc',
'browser/mime_registry_message_filter.h',
- 'browser/service_worker/service_worker_dispatcher_host.h',
- 'browser/service_worker/service_worker_dispatcher_host.cc',
- 'browser/service_worker/service_worker_context.h',
- 'browser/service_worker/service_worker_context.cc',
'browser/net/browser_online_state_observer.cc',
'browser/net/browser_online_state_observer.h',
'browser/net/sqlite_persistent_cookie_store.cc',
@@ -770,6 +786,7 @@
'browser/profiler_message_filter.h',
'browser/quota_dispatcher_host.cc',
'browser/quota_dispatcher_host.h',
+ 'browser/renderer_data_memoizing_store.h',
'browser/renderer_host/backing_store.cc',
'browser/renderer_host/backing_store.h',
'browser/renderer_host/backing_store_aura.cc',
@@ -782,8 +799,6 @@
'browser/renderer_host/backing_store_manager.h',
'browser/renderer_host/backing_store_win.cc',
'browser/renderer_host/backing_store_win.h',
- 'browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc',
- 'browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.h',
'browser/renderer_host/clipboard_message_filter.cc',
'browser/renderer_host/clipboard_message_filter.h',
'browser/renderer_host/clipboard_message_filter_mac.mm',
@@ -801,12 +816,12 @@
'browser/renderer_host/compositor_impl_android.h',
'browser/renderer_host/database_message_filter.cc',
'browser/renderer_host/database_message_filter.h',
+ 'browser/renderer_host/delegated_frame_evictor.cc',
+ 'browser/renderer_host/delegated_frame_evictor.h',
'browser/renderer_host/dip_util.cc',
'browser/renderer_host/dip_util.h',
'browser/renderer_host/file_utilities_message_filter.cc',
'browser/renderer_host/file_utilities_message_filter.h',
- 'browser/renderer_host/frame_memory_manager.cc',
- 'browser/renderer_host/frame_memory_manager.h',
'browser/renderer_host/gamepad_browser_message_filter.cc',
'browser/renderer_host/gamepad_browser_message_filter.h',
'browser/renderer_host/gpu_message_filter.cc',
@@ -825,25 +840,39 @@
'browser/renderer_host/image_transport_factory_android.h',
'browser/renderer_host/ime_adapter_android.cc',
'browser/renderer_host/ime_adapter_android.h',
- 'browser/renderer_host/input/browser_input_event.cc',
- 'browser/renderer_host/input/browser_input_event.h',
- 'browser/renderer_host/input/buffered_input_router.cc',
- 'browser/renderer_host/input/buffered_input_router.h',
'browser/renderer_host/input/gesture_event_filter.cc',
'browser/renderer_host/input/gesture_event_filter.h',
- 'browser/renderer_host/input/immediate_input_router.cc',
- 'browser/renderer_host/input/immediate_input_router.h',
'browser/renderer_host/input/input_ack_handler.h',
- 'browser/renderer_host/input/input_queue.cc',
- 'browser/renderer_host/input/input_queue.h',
- 'browser/renderer_host/input/input_queue_client.h',
'browser/renderer_host/input/input_router.h',
'browser/renderer_host/input/input_router_client.h',
+ 'browser/renderer_host/input/input_router_impl.cc',
+ 'browser/renderer_host/input/input_router_impl.h',
+ 'browser/renderer_host/input/synthetic_gesture.cc',
+ 'browser/renderer_host/input/synthetic_gesture.h',
+ 'browser/renderer_host/input/synthetic_gesture_controller.cc',
+ 'browser/renderer_host/input/synthetic_gesture_controller.h',
+ 'browser/renderer_host/input/synthetic_gesture_target.h',
+ 'browser/renderer_host/input/synthetic_gesture_target_android.cc',
+ 'browser/renderer_host/input/synthetic_gesture_target_android.h',
+ 'browser/renderer_host/input/synthetic_gesture_target_aura.cc',
+ 'browser/renderer_host/input/synthetic_gesture_target_aura.h',
+ 'browser/renderer_host/input/synthetic_gesture_target_base.cc',
+ 'browser/renderer_host/input/synthetic_gesture_target_base.h',
+ 'browser/renderer_host/input/synthetic_pinch_gesture.cc',
+ 'browser/renderer_host/input/synthetic_pinch_gesture.h',
+ 'browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc',
+ 'browser/renderer_host/input/synthetic_smooth_scroll_gesture.h',
+ 'browser/renderer_host/input/synthetic_tap_gesture.cc',
+ 'browser/renderer_host/input/synthetic_tap_gesture.h',
'browser/renderer_host/input/tap_suppression_controller.cc',
'browser/renderer_host/input/tap_suppression_controller.h',
'browser/renderer_host/input/tap_suppression_controller_client.h',
+ 'browser/renderer_host/input/timeout_monitor.cc',
+ 'browser/renderer_host/input/timeout_monitor.h',
'browser/renderer_host/input/touch_event_queue.cc',
'browser/renderer_host/input/touch_event_queue.h',
+ 'browser/renderer_host/input/touch_action_filter.cc',
+ 'browser/renderer_host/input/touch_action_filter.h',
'browser/renderer_host/input/touchpad_tap_suppression_controller_aura.cc',
'browser/renderer_host/input/touchpad_tap_suppression_controller.cc',
'browser/renderer_host/input/touchpad_tap_suppression_controller.h',
@@ -872,6 +901,8 @@
'browser/renderer_host/java/java_method.h',
'browser/renderer_host/java/java_type.cc',
'browser/renderer_host/java/java_type.h',
+ 'browser/renderer_host/java/jni_helper.cc',
+ 'browser/renderer_host/java/jni_helper.h',
'browser/renderer_host/media/audio_input_device_manager.cc',
'browser/renderer_host/media/audio_input_device_manager.h',
'browser/renderer_host/media/audio_input_renderer_host.cc',
@@ -904,6 +935,8 @@
'browser/renderer_host/media/video_capture_controller.h',
'browser/renderer_host/media/video_capture_controller_event_handler.cc',
'browser/renderer_host/media/video_capture_controller_event_handler.h',
+ 'browser/renderer_host/media/video_capture_device_impl.cc',
+ 'browser/renderer_host/media/video_capture_device_impl.h',
'browser/renderer_host/media/video_capture_host.cc',
'browser/renderer_host/media/video_capture_host.h',
'browser/renderer_host/media/video_capture_manager.cc',
@@ -938,6 +971,8 @@
'browser/renderer_host/pepper/pepper_browser_font_singleton_host.h',
'browser/renderer_host/pepper/pepper_external_file_ref_backend.cc',
'browser/renderer_host/pepper/pepper_external_file_ref_backend.h',
+ 'browser/renderer_host/pepper/pepper_file_io_host.cc',
+ 'browser/renderer_host/pepper/pepper_file_io_host.h',
'browser/renderer_host/pepper/pepper_file_ref_host.cc',
'browser/renderer_host/pepper/pepper_file_ref_host.h',
'browser/renderer_host/pepper/pepper_file_system_browser_host.cc',
@@ -975,17 +1010,18 @@
'browser/renderer_host/pepper/pepper_truetype_font_list_android.cc',
'browser/renderer_host/pepper/pepper_truetype_font_list_host.cc',
'browser/renderer_host/pepper/pepper_truetype_font_list_host.h',
- 'browser/renderer_host/pepper/pepper_truetype_font_list_linux.cc',
+ 'browser/renderer_host/pepper/pepper_truetype_font_list_ozone.cc',
+ 'browser/renderer_host/pepper/pepper_truetype_font_list_pango.cc',
'browser/renderer_host/pepper/pepper_truetype_font_list_mac.mm',
'browser/renderer_host/pepper/pepper_truetype_font_list_win.cc',
'browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc',
'browser/renderer_host/pepper/pepper_udp_socket_message_filter.h',
+ 'browser/renderer_host/pepper/quota_reservation.cc',
+ 'browser/renderer_host/pepper/quota_reservation.h',
'browser/renderer_host/pepper/ssl_context_helper.cc',
'browser/renderer_host/pepper/ssl_context_helper.h',
'browser/renderer_host/popup_menu_helper_mac.h',
'browser/renderer_host/popup_menu_helper_mac.mm',
- 'browser/renderer_host/render_frame_host_impl.cc',
- 'browser/renderer_host/render_frame_host_impl.h',
'browser/renderer_host/render_message_filter.cc',
'browser/renderer_host/render_message_filter.h',
'browser/renderer_host/render_process_host_impl.cc',
@@ -1022,24 +1058,18 @@
'browser/renderer_host/render_widget_host_view_mac.mm',
'browser/renderer_host/render_widget_host_view_win.cc',
'browser/renderer_host/render_widget_host_view_win.h',
- 'browser/renderer_host/synthetic_gesture_calculator.cc',
- 'browser/renderer_host/synthetic_gesture_calculator.h',
- 'browser/renderer_host/synthetic_gesture_controller.cc',
- 'browser/renderer_host/synthetic_gesture_controller.h',
+ 'browser/renderer_host/renderer_frame_manager.cc',
+ 'browser/renderer_host/renderer_frame_manager.h',
+ 'browser/renderer_host/software_frame_manager.cc',
+ 'browser/renderer_host/software_frame_manager.h',
'browser/renderer_host/socket_stream_dispatcher_host.cc',
'browser/renderer_host/socket_stream_dispatcher_host.h',
'browser/renderer_host/socket_stream_host.cc',
'browser/renderer_host/socket_stream_host.h',
- 'browser/renderer_host/surface_texture_transport_client_android.cc',
- 'browser/renderer_host/surface_texture_transport_client_android.h',
'browser/renderer_host/text_input_client_mac.h',
'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/generic_touch_gesture_android.cc',
- 'browser/renderer_host/generic_touch_gesture_android.h',
- 'browser/renderer_host/touch_smooth_scroll_gesture_aura.cc',
- 'browser/renderer_host/touch_smooth_scroll_gesture_aura.h',
'browser/renderer_host/ui_events_helper.cc',
'browser/renderer_host/ui_events_helper.h',
'browser/renderer_host/web_input_event_aura.cc',
@@ -1048,12 +1078,41 @@
'browser/renderer_host/web_input_event_aurax11.cc',
'browser/renderer_host/webmenurunner_mac.h',
'browser/renderer_host/webmenurunner_mac.mm',
+ 'browser/renderer_host/websocket_dispatcher_host.cc',
+ 'browser/renderer_host/websocket_dispatcher_host.h',
+ 'browser/renderer_host/websocket_host.cc',
+ 'browser/renderer_host/websocket_host.h',
'browser/resolve_proxy_msg_helper.cc',
'browser/resolve_proxy_msg_helper.h',
'browser/resource_context_impl.cc',
'browser/resource_context_impl.h',
'browser/safe_util_win.cc',
'browser/safe_util_win.h',
+ 'browser/service_worker/embedded_worker_instance.cc',
+ 'browser/service_worker/embedded_worker_instance.h',
+ 'browser/service_worker/embedded_worker_registry.cc',
+ 'browser/service_worker/embedded_worker_registry.h',
+ 'browser/service_worker/service_worker_context.h',
+ 'browser/service_worker/service_worker_context_core.cc',
+ 'browser/service_worker/service_worker_context_core.h',
+ 'browser/service_worker/service_worker_context_wrapper.cc',
+ 'browser/service_worker/service_worker_context_wrapper.h',
+ 'browser/service_worker/service_worker_dispatcher_host.cc',
+ 'browser/service_worker/service_worker_dispatcher_host.h',
+ 'browser/service_worker/service_worker_provider_host.cc',
+ 'browser/service_worker/service_worker_provider_host.h',
+ 'browser/service_worker/service_worker_register_job.cc',
+ 'browser/service_worker/service_worker_register_job.h',
+ 'browser/service_worker/service_worker_registration.cc',
+ 'browser/service_worker/service_worker_registration.h',
+ 'browser/service_worker/service_worker_registration_status.cc',
+ 'browser/service_worker/service_worker_registration_status.h',
+ 'browser/service_worker/service_worker_storage.cc',
+ 'browser/service_worker/service_worker_storage.h',
+ 'browser/service_worker/service_worker_version.cc',
+ 'browser/service_worker/service_worker_version.h',
+ 'browser/signed_certificate_timestamp_store_impl.cc',
+ 'browser/signed_certificate_timestamp_store_impl.h',
'browser/site_instance_impl.cc',
'browser/site_instance_impl.h',
'browser/speech/audio_buffer.cc',
@@ -1123,12 +1182,10 @@
'browser/system_message_window_win.h',
'browser/tcmalloc_internals_request_job.cc',
'browser/tcmalloc_internals_request_job.h',
- 'browser/tracing/trace_controller_impl.cc',
- 'browser/tracing/trace_controller_impl.h',
+ 'browser/theme_helper_mac.mm',
+ 'browser/theme_helper_mac.h',
'browser/tracing/trace_message_filter.cc',
'browser/tracing/trace_message_filter.h',
- 'browser/tracing/trace_subscriber_stdio.cc',
- 'browser/tracing/trace_subscriber_stdio.h',
'browser/tracing/tracing_controller_impl.cc',
'browser/tracing/tracing_controller_impl.h',
'browser/tracing/tracing_ui.cc',
@@ -1138,34 +1195,26 @@
'browser/user_metrics.cc',
'browser/utility_process_host_impl.cc',
'browser/utility_process_host_impl.h',
+ 'browser/vibration/vibration_message_filter.cc',
+ 'browser/vibration/vibration_message_filter.h',
+ 'browser/vibration/vibration_provider_android.cc',
+ 'browser/vibration/vibration_provider_android.h',
'browser/web_contents/aura/image_window_delegate.cc',
'browser/web_contents/aura/image_window_delegate.h',
'browser/web_contents/aura/shadow_layer_delegate.cc',
'browser/web_contents/aura/shadow_layer_delegate.h',
'browser/web_contents/aura/window_slider.cc',
'browser/web_contents/aura/window_slider.h',
- 'browser/web_contents/debug_urls.cc',
- 'browser/web_contents/debug_urls.h',
'browser/web_contents/drag_utils_gtk.cc',
'browser/web_contents/drag_utils_gtk.h',
- 'browser/web_contents/frame_tree_node.cc',
- 'browser/web_contents/frame_tree_node.h',
- 'browser/web_contents/interstitial_page_impl.cc',
- 'browser/web_contents/interstitial_page_impl.h',
- 'browser/web_contents/navigation_controller_impl.cc',
- 'browser/web_contents/navigation_controller_impl.h',
- 'browser/web_contents/navigation_entry_impl.cc',
- 'browser/web_contents/navigation_entry_impl.h',
- 'browser/web_contents/render_view_host_manager.cc',
- 'browser/web_contents/render_view_host_manager.h',
'browser/web_contents/touch_editable_impl_aura.cc',
'browser/web_contents/touch_editable_impl_aura.h',
+ 'browser/web_contents/web_contents_android.cc',
+ 'browser/web_contents/web_contents_android.h',
'browser/web_contents/web_contents_drag_win.cc',
'browser/web_contents/web_contents_drag_win.h',
'browser/web_contents/web_contents_impl.cc',
'browser/web_contents/web_contents_impl.h',
- 'browser/web_contents/web_contents_screenshot_manager.cc',
- 'browser/web_contents/web_contents_screenshot_manager.h',
'browser/web_contents/web_contents_view_android.cc',
'browser/web_contents/web_contents_view_android.h',
'browser/web_contents/web_contents_view_aura.cc',
@@ -1211,8 +1260,6 @@
'browser/webui/web_ui_impl.cc',
'browser/webui/web_ui_impl.h',
'browser/webui/web_ui_message_handler.cc',
- 'browser/worker_host/message_port_service.cc',
- 'browser/worker_host/message_port_service.h',
'browser/worker_host/worker_document_set.cc',
'browser/worker_host/worker_document_set.h',
'browser/worker_host/worker_message_filter.cc',
@@ -1236,7 +1283,12 @@
'<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/grit/webui_resources_map.cc',
],
'conditions': [
- ['OS!="win" and OS!="mac" and OS!="linux"', {
+ ['toolkit_views==1', {
+ 'dependencies': [
+ '../ui/events/events.gyp:events',
+ ],
+ }],
+ ['OS!="win" and OS!="mac" and (OS!="linux" or use_udev==0)', {
'sources': [
'browser/gamepad/gamepad_platform_data_fetcher.cc',
]
@@ -1263,6 +1315,7 @@
['include', '^browser/cert_store_impl\\.cc$'],
['include', '^browser/download/download_create_info\\.cc$'],
['include', '^browser/notification_service_impl\\.cc$'],
+ ['include', '^browser/signed_certificate_timestamp_store_impl\\.cc$'],
['include', '^browser/user_metrics\\.cc$'],
['include', '^browser/web_contents/navigation_entry_impl\\.cc$'],
],
@@ -1272,7 +1325,6 @@
'../cc/cc.gyp:cc',
'../gpu/gpu.gyp:gpu_ipc',
'../net/net.gyp:http_server',
- '../printing/printing.gyp:printing',
'../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
'../ui/surface/surface.gyp:surface',
'../webkit/common/webkit_common.gyp:webkit_common',
@@ -1282,6 +1334,11 @@
'../webkit/webkit_resources.gyp:webkit_strings',
],
}],
+ ['enable_printing!=0', {
+ 'dependencies': [
+ '../printing/printing.gyp:printing',
+ ],
+ }],
['OS!="ios" and chrome_multiple_dll!=1', {
'dependencies': [
'../third_party/WebKit/public/blink.gyp:blink',
@@ -1295,9 +1352,16 @@
['OS!="android" and OS!="ios"', {
'dependencies': [
'browser/tracing/tracing_resources.gyp:tracing_resources',
+ ],
+ }],
+ ['android_webview_build==0 and OS!="ios"', {
+ 'dependencies': [
'../third_party/libyuv/libyuv.gyp:libyuv',
],
}],
+ ['android_webview_build==1', {
+ 'defines': ['AVOID_LIBYUV_FOR_ANDROID_WEBVIEW'],
+ }],
['enable_webrtc==1', {
'dependencies': [
'../jingle/jingle.gyp:jingle_glue',
@@ -1325,6 +1389,8 @@
'sources': [
'browser/renderer_host/media/desktop_capture_device.cc',
'browser/renderer_host/media/desktop_capture_device.h',
+ 'browser/renderer_host/media/desktop_capture_device_aura.cc',
+ 'browser/renderer_host/media/desktop_capture_device_aura.h',
],
'dependencies': [
'../third_party/webrtc/modules/modules.gyp:desktop_capture',
@@ -1370,26 +1436,34 @@
}],
['toolkit_uses_gtk == 1', {
'dependencies': [
- '../build/linux/system.gyp:dbus',
# For FcLangSetAdd call in render_sandbox_host_linux.cc
'../build/linux/system.gyp:fontconfig',
'../build/linux/system.gyp:gtk',
# For XShm* in backing_store_x.cc
'../build/linux/system.gyp:x11',
- '../dbus/dbus.gyp:dbus',
],
}],
['OS=="linux"', {
'dependencies': [
- '../build/linux/system.gyp:udev',
'../sandbox/sandbox.gyp:libc_urandom_override',
],
}],
+ ['use_udev == 1', {
+ 'dependencies': [
+ '../build/linux/system.gyp:udev',
+ ],
+ }, {
+ 'sources!': [
+ 'browser/device_monitor_udev.cc',
+ 'browser/device_monitor_udev.h',
+ 'browser/gamepad/gamepad_platform_data_fetcher_linux.cc',
+ 'browser/udev_linux.cc',
+ 'browser/udev_linux.h',
+ ],
+ }],
['OS=="linux" and use_aura==1', {
'dependencies': [
- '../build/linux/system.gyp:dbus',
'../build/linux/system.gyp:fontconfig',
- '../dbus/dbus.gyp:dbus',
],
}],
['use_x11==1', {
@@ -1401,6 +1475,9 @@
'dependencies': [
'../build/linux/system.gyp:pangocairo',
],
+ 'sources!': [
+ 'browser/renderer_host/pepper/pepper_truetype_font_list_ozone.cc',
+ ],
}],
['OS=="android"', {
'dependencies': [
@@ -1429,7 +1506,6 @@
'browser/geolocation/device_data_provider.cc',
'browser/geolocation/empty_device_data_provider.cc',
'browser/geolocation/wifi_data_provider_common.cc',
- 'browser/renderer_host/input/tap_suppression_controller.cc',
'browser/renderer_host/native_web_keyboard_event.cc',
]
}, { # OS!="android"
@@ -1439,21 +1515,14 @@
],
}],
['OS=="mac"', {
- 'sources': [
- # Build necessary Mozilla sources
- '../third_party/mozilla/ComplexTextInputPanel.h',
- '../third_party/mozilla/ComplexTextInputPanel.mm',
- '../third_party/mozilla/NSPasteboard+Utils.h',
- '../third_party/mozilla/NSPasteboard+Utils.mm',
- '../third_party/mozilla/NSString+Utils.h',
- '../third_party/mozilla/NSString+Utils.mm',
- '../third_party/mozilla/NSURL+Utils.h',
- '../third_party/mozilla/NSURL+Utils.m',
- ],
'sources/': [
['exclude', '^browser/device_orientation/data_fetcher_shared_memory_default.cc$'],
],
+ 'sources!': [
+ 'browser/geolocation/empty_wifi_data_provider.cc',
+ ],
'dependencies': [
+ '../third_party/mozilla/mozilla.gyp:mozilla',
'../third_party/sudden_motion_sensor/sudden_motion_sensor.gyp:sudden_motion_sensor',
],
'link_settings': {
@@ -1477,14 +1546,17 @@
['os_bsd==1', {
'sources/': [
['exclude', '^browser/gamepad/gamepad_platform_data_fetcher_linux\\.cc$'],
- ['exclude', '^browser/geolocation/wifi_data_provider_linux\\.cc$'],
],
}],
['use_aura!=1 and use_qt!=1 and OS!="win"', {
'sources!': [
- 'browser/renderer_host/input/touchscreen_tap_suppression_controller.cc',
'browser/renderer_host/ui_events_helper.cc',
'browser/renderer_host/ui_events_helper.h',
+ ],
+ }],
+ ['use_aura!=1 and OS!="win" and OS!="android"', {
+ 'sources!': [
+ 'browser/renderer_host/input/touchscreen_tap_suppression_controller.cc',
'browser/renderer_host/tap_suppression_controller.cc',
],
}, {
@@ -1559,9 +1631,22 @@
'../third_party/speex/speex.gyp:libspeex',
],
}],
- ['linux_use_libgps==1', {
+ ['OS == "win"', {
+ 'sources!': [
+ 'browser/geolocation/empty_wifi_data_provider.cc',
+ ],
+ }],
+ ['OS == "linux" and use_dbus==1', {
+ 'sources!': [
+ 'browser/geolocation/empty_wifi_data_provider.cc',
+ ],
'dependencies': [
- '../build/linux/system.gyp:libgps',
+ '../build/linux/system.gyp:dbus',
+ '../dbus/dbus.gyp:dbus',
+ ],
+ }, { # OS != "linux" or use_dbus==0
+ 'sources!': [
+ 'browser/geolocation/wifi_data_provider_linux.cc',
],
}],
],
diff --git a/chromium/content/content_browsertests.isolate b/chromium/content/content_browsertests.isolate
index 73127503e3d..b9387effc4c 100644
--- a/chromium/content/content_browsertests.isolate
+++ b/chromium/content/content_browsertests.isolate
@@ -8,9 +8,6 @@
'isolate_dependency_tracked': [
'<(PRODUCT_DIR)/content_shell/assets/content_shell.pak',
],
- 'isolate_dependency_untracked': [
- '../third_party/webgl_conformance/',
- ],
},
}],
['OS=="android" or OS=="linux" or OS=="mac" or OS=="win"', {
@@ -26,8 +23,8 @@
'command': [
'../testing/xvfb.py',
'<(PRODUCT_DIR)',
- '../tools/swarm_client/googletest/run_test_cases.py',
'<(PRODUCT_DIR)/content_browsertests<(EXECUTABLE_SUFFIX)',
+ '--test-launcher-bot-mode',
],
'isolate_dependency_tracked': [
'../testing/xvfb.py',
@@ -54,7 +51,7 @@
'../third_party/pyftpdlib/',
'../third_party/pywebsocket/',
'../third_party/tlslite/',
- '../tools/swarm_client/',
+ '../tools/swarming_client/',
],
},
}],
@@ -76,8 +73,8 @@
'variables': {
'command': [
'../testing/test_env.py',
- '../tools/swarm_client/googletest/run_test_cases.py',
'<(PRODUCT_DIR)/content_browsertests<(EXECUTABLE_SUFFIX)',
+ '--test-launcher-bot-mode',
],
},
}],
@@ -97,7 +94,6 @@
# WorkerXHRHttpLayoutTest.Tests which are currently disabled.
#'../third_party/cygwin/',
#'../third_party/perl/perl/',
- '../third_party/python_26/',
],
},
}],
diff --git a/chromium/content/content_child.gypi b/chromium/content/content_child.gypi
index 3e3d5a2ecac..6e862379372 100644
--- a/chromium/content/content_child.gypi
+++ b/chromium/content/content_child.gypi
@@ -7,6 +7,7 @@
'../base/base.gyp:base',
'../components/tracing.gyp:tracing',
'../skia/skia.gyp:skia',
+ '../ui/gfx/gfx.gyp:gfx',
'../ui/ui.gyp:ui',
'../url/url.gyp:url_lib',
],
@@ -31,6 +32,8 @@
'child/browser_font_resource_trusted.h',
'child/child_histogram_message_filter.cc',
'child/child_histogram_message_filter.h',
+ 'child/child_message_filter.cc',
+ 'child/child_message_filter.h',
'child/child_process.cc',
'child/child_process.h',
'child/child_resource_message_filter.cc',
@@ -57,12 +60,12 @@
'child/indexed_db/indexed_db_key_builders.h',
'child/indexed_db/indexed_db_message_filter.cc',
'child/indexed_db/indexed_db_message_filter.h',
- 'child/indexed_db/proxy_webidbcursor_impl.cc',
- 'child/indexed_db/proxy_webidbcursor_impl.h',
- 'child/indexed_db/proxy_webidbdatabase_impl.cc',
- 'child/indexed_db/proxy_webidbdatabase_impl.h',
- 'child/indexed_db/proxy_webidbfactory_impl.cc',
- 'child/indexed_db/proxy_webidbfactory_impl.h',
+ 'child/indexed_db/webidbcursor_impl.cc',
+ 'child/indexed_db/webidbcursor_impl.h',
+ 'child/indexed_db/webidbdatabase_impl.cc',
+ 'child/indexed_db/webidbdatabase_impl.h',
+ 'child/indexed_db/webidbfactory_impl.cc',
+ 'child/indexed_db/webidbfactory_impl.h',
'child/npapi/np_channel_base.cc',
'child/npapi/np_channel_base.h',
'child/npapi/npobject_base.h',
@@ -123,6 +126,16 @@
'child/resource_dispatcher.h',
'child/runtime_features.cc',
'child/runtime_features.h',
+ 'child/scoped_child_process_reference.cc',
+ 'child/scoped_child_process_reference.h',
+ 'child/service_worker/service_worker_dispatcher.cc',
+ 'child/service_worker/service_worker_dispatcher.h',
+ 'child/service_worker/service_worker_message_filter.cc',
+ 'child/service_worker/service_worker_message_filter.h',
+ 'child/service_worker/web_service_worker_impl.cc',
+ 'child/service_worker/web_service_worker_impl.h',
+ 'child/service_worker/web_service_worker_provider_impl.cc',
+ 'child/service_worker/web_service_worker_provider_impl.h',
'child/site_isolation_policy.cc',
'child/site_isolation_policy.h',
'child/socket_stream_dispatcher.cc',
@@ -137,6 +150,12 @@
'child/webkitplatformsupport_impl.h',
'child/webmessageportchannel_impl.cc',
'child/webmessageportchannel_impl.h',
+ 'child/websocket_bridge.cc',
+ 'child/websocket_bridge.h',
+ 'child/websocket_dispatcher.cc',
+ 'child/websocket_dispatcher.h',
+ 'child/worker_thread_task_runner.cc',
+ 'child/worker_thread_task_runner.h',
'public/child/image_decoder_utils.h',
'public/child/resource_dispatcher_delegate.h',
],
@@ -165,8 +184,8 @@
'dependencies': [
'../third_party/WebKit/public/blink.gyp:blink',
'../third_party/npapi/npapi.gyp:npapi',
+ '../webkit/child/webkit_child.gyp:webkit_child',
'../webkit/common/webkit_common.gyp:webkit_common',
- '../webkit/support/webkit_support.gyp:glue_child',
],
}],
['use_aura==1', {
diff --git a/chromium/content/content_common.gypi b/chromium/content/content_common.gypi
index 8c455744e26..621748a3313 100644
--- a/chromium/content/content_common.gypi
+++ b/chromium/content/content_common.gypi
@@ -9,7 +9,8 @@
'../net/net.gyp:net',
'../skia/skia.gyp:skia',
'../third_party/icu/icu.gyp:icuuc',
- '../ui/ui.gyp:shell_dialogs',
+ '../ui/gfx/gfx.gyp:gfx',
+ '../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
'../ui/ui.gyp:ui',
'../url/url.gyp:url_lib',
'../webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
@@ -26,6 +27,8 @@
'public/common/child_process_host_delegate.cc',
'public/common/child_process_host_delegate.h',
'public/common/child_process_sandbox_support_linux.h',
+ 'public/common/color_suggestion.cc',
+ 'public/common/color_suggestion.h',
'public/common/content_constants.cc',
'public/common/content_constants.h',
'public/common/content_descriptors.h',
@@ -36,8 +39,6 @@
'public/common/context_menu_params.cc',
'public/common/context_menu_params.h',
'public/common/console_message_level.h',
- 'public/common/desktop_media_id.cc',
- 'public/common/desktop_media_id.h',
'public/common/drop_data.cc',
'public/common/drop_data.h',
'public/common/favicon_url.cc',
@@ -81,6 +82,8 @@
'public/common/security_style.h',
'public/common/show_desktop_notification_params.cc',
'public/common/show_desktop_notification_params.h',
+ 'public/common/signed_certificate_timestamp_id_and_status.cc',
+ 'public/common/signed_certificate_timestamp_id_and_status.h',
'public/common/speech_recognition_error.h',
'public/common/speech_recognition_grammar.h',
'public/common/speech_recognition_result.h',
@@ -96,6 +99,7 @@
'public/common/url_fetcher.h',
'public/common/url_utils.cc',
'public/common/url_utils.h',
+ 'public/common/user_metrics_action.h',
'public/common/webplugininfo.cc',
'public/common/webplugininfo.h',
'public/common/zygote_fork_delegate_linux.h',
@@ -107,8 +111,6 @@
'common/android/address_parser.h',
'common/android/address_parser_internal.cc',
'common/android/address_parser_internal.h',
- 'common/android/command_line.cc',
- 'common/android/command_line.h',
'common/android/common_jni_registrar.cc',
'common/android/common_jni_registrar.h',
'common/android/device_telephony_info.cc',
@@ -148,8 +150,9 @@
'common/cookie_data.cc',
'common/cookie_data.h',
'common/database_messages.h',
+ 'common/date_time_suggestion.h',
'common/desktop_notification_messages.h',
- 'common/device_motion_hardware_buffer.h',
+ 'common/device_orientation/device_motion_hardware_buffer.h',
'common/device_orientation/device_motion_messages.h',
'common/device_orientation/device_orientation_hardware_buffer.h',
'common/device_orientation/device_orientation_messages.h',
@@ -172,6 +175,7 @@
'common/font_list.h',
'common/font_list_android.cc',
'common/font_list_mac.mm',
+ 'common/font_list_ozone.cc',
'common/font_list_pango.cc',
'common/font_list_win.cc',
'common/gamepad_hardware_buffer.h',
@@ -187,16 +191,26 @@
'common/gpu/client/gl_helper.h',
'common/gpu/client/gl_helper_scaling.cc',
'common/gpu/client/gl_helper_scaling.h',
- 'common/gpu/client/gl_surface_capturer_host.cc',
- 'common/gpu/client/gl_surface_capturer_host.h',
'common/gpu/client/gpu_channel_host.cc',
'common/gpu/client/gpu_channel_host.h',
+ 'common/gpu/client/gpu_memory_buffer_impl.cc',
+ 'common/gpu/client/gpu_memory_buffer_impl.h',
+ 'common/gpu/client/gpu_memory_buffer_impl_android.cc',
+ 'common/gpu/client/gpu_memory_buffer_impl_linux.cc',
+ 'common/gpu/client/gpu_memory_buffer_impl_mac.cc',
+ 'common/gpu/client/gpu_memory_buffer_impl_shm.cc',
+ 'common/gpu/client/gpu_memory_buffer_impl_shm.h',
+ 'common/gpu/client/gpu_memory_buffer_impl_win.cc',
'common/gpu/client/gpu_video_decode_accelerator_host.cc',
'common/gpu/client/gpu_video_decode_accelerator_host.h',
'common/gpu/client/gpu_video_encode_accelerator_host.cc',
'common/gpu/client/gpu_video_encode_accelerator_host.h',
'common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc',
'common/gpu/client/webgraphicscontext3d_command_buffer_impl.h',
+ 'common/gpu/devtools_gpu_agent.cc',
+ 'common/gpu/devtools_gpu_agent.h',
+ 'common/gpu/devtools_gpu_instrumentation.cc',
+ 'common/gpu/devtools_gpu_instrumentation.h',
'common/gpu/gpu_channel.cc',
'common/gpu/gpu_channel.h',
'common/gpu/gpu_channel_manager.cc',
@@ -204,7 +218,6 @@
'common/gpu/gpu_command_buffer_stub.cc',
'common/gpu/gpu_command_buffer_stub.h',
'common/gpu/gpu_config.h',
- 'common/gpu/gpu_memory_allocation.h',
'common/gpu/gpu_memory_manager.cc',
'common/gpu/gpu_memory_manager.h',
'common/gpu/gpu_memory_manager_client.cc',
@@ -225,22 +238,18 @@
'common/gpu/image_transport_surface_linux.cc',
'common/gpu/image_transport_surface_mac.cc',
'common/gpu/image_transport_surface_win.cc',
- 'common/gpu/media/gl_surface_capturer.cc',
- 'common/gpu/media/gl_surface_capturer.h',
'common/gpu/media/gpu_video_decode_accelerator.cc',
'common/gpu/media/gpu_video_decode_accelerator.h',
'common/gpu/media/gpu_video_encode_accelerator.cc',
'common/gpu/media/gpu_video_encode_accelerator.h',
- 'common/gpu/media/video_decode_accelerator_impl.cc',
- 'common/gpu/media/video_decode_accelerator_impl.h',
'common/gpu/media/h264_bit_reader.cc',
'common/gpu/media/h264_bit_reader.h',
'common/gpu/media/h264_parser.cc',
'common/gpu/media/h264_parser.h',
+ 'common/gpu/media/video_decode_accelerator_impl.cc',
+ 'common/gpu/media/video_decode_accelerator_impl.h',
'common/gpu/stream_texture_manager_android.cc',
'common/gpu/stream_texture_manager_android.h',
- 'common/gpu/surface_capturer.cc',
- 'common/gpu/surface_capturer.h',
'common/gpu/sync_point_manager.cc',
'common/gpu/sync_point_manager.h',
'common/gpu/texture_image_transport_surface.cc',
@@ -248,6 +257,7 @@
'common/handle_enumerator_win.cc',
'common/handle_enumerator_win.h',
'common/image_messages.h',
+ 'common/indexed_db/indexed_db_constants.h',
'common/indexed_db/indexed_db_key.cc',
'common/indexed_db/indexed_db_key.h',
'common/indexed_db/indexed_db_key_path.cc',
@@ -257,18 +267,26 @@
'common/indexed_db/indexed_db_messages.h',
'common/indexed_db/indexed_db_param_traits.cc',
'common/indexed_db/indexed_db_param_traits.h',
- 'common/input/event_packet.cc',
- 'common/input/event_packet.h',
- 'common/input/ipc_input_event_payload.cc',
- 'common/input/ipc_input_event_payload.h',
'common/input/input_event.cc',
'common/input/input_event.h',
- 'common/input/input_event_disposition.cc',
- 'common/input/input_event_disposition.h',
'common/input/input_param_traits.cc',
'common/input/input_param_traits.h',
- 'common/input/web_input_event_payload.cc',
- 'common/input/web_input_event_payload.h',
+ 'common/input/scoped_web_input_event.cc',
+ 'common/input/scoped_web_input_event.h',
+ 'common/input/synthetic_gesture_packet.cc',
+ 'common/input/synthetic_gesture_packet.h',
+ 'common/input/synthetic_gesture_params.cc',
+ 'common/input/synthetic_gesture_params.h',
+ 'common/input/synthetic_pinch_gesture_params.cc',
+ 'common/input/synthetic_pinch_gesture_params.h',
+ 'common/input/synthetic_smooth_scroll_gesture_params.cc',
+ 'common/input/synthetic_smooth_scroll_gesture_params.h',
+ 'common/input/synthetic_tap_gesture_params.cc',
+ 'common/input/synthetic_tap_gesture_params.h',
+ 'common/input/synthetic_web_input_event_builders.cc',
+ 'common/input/synthetic_web_input_event_builders.h',
+ 'common/input/web_input_event_traits.cc',
+ 'common/input/web_input_event_traits.h',
'common/input_messages.h',
'common/inter_process_time_ticks_converter.cc',
'common/inter_process_time_ticks_converter.h',
@@ -292,6 +310,7 @@
'common/media/video_capture_messages.h',
'common/media/webrtc_identity_messages.h',
'common/memory_benchmark_messages.h',
+ 'common/message_port_messages.h',
'common/message_router.cc',
'common/message_router.h',
'common/mime_registry_messages.h',
@@ -303,7 +322,6 @@
'common/one_writer_seqlock.cc',
'common/one_writer_seqlock.h',
'common/p2p_messages.h',
- 'common/p2p_sockets.h',
'common/page_state_serialization.cc',
'common/page_state_serialization.h',
'common/page_zoom.cc',
@@ -327,16 +345,26 @@
'common/quota_messages.h',
'common/resource_messages.cc',
'common/resource_messages.h',
- 'common/sandbox_init_linux.cc',
'common/sandbox_init_mac.cc',
'common/sandbox_init_mac.h',
'common/sandbox_init_win.cc',
+ 'common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc',
+ 'common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h',
+ 'common/sandbox_linux/bpf_gpu_policy_linux.cc',
+ 'common/sandbox_linux/bpf_gpu_policy_linux.h',
+ 'common/sandbox_linux/bpf_ppapi_policy_linux.cc',
+ 'common/sandbox_linux/bpf_ppapi_policy_linux.h',
+ 'common/sandbox_linux/bpf_renderer_policy_linux.cc',
+ 'common/sandbox_linux/bpf_renderer_policy_linux.h',
+ 'common/sandbox_linux/sandbox_bpf_base_policy_linux.cc',
+ 'common/sandbox_linux/sandbox_bpf_base_policy_linux.h',
+ 'common/sandbox_linux/sandbox_init_linux.cc',
+ 'common/sandbox_linux/sandbox_linux.cc',
+ 'common/sandbox_linux/sandbox_linux.h',
+ 'common/sandbox_linux/sandbox_seccomp_bpf_linux.cc',
+ 'common/sandbox_linux/sandbox_seccomp_bpf_linux.h',
'common/sandbox_mac.h',
'common/sandbox_mac.mm',
- 'common/sandbox_linux.h',
- 'common/sandbox_linux.cc',
- 'common/sandbox_seccomp_bpf_linux.cc',
- 'common/sandbox_seccomp_bpf_linux.h',
'common/sandbox_util.cc',
'common/sandbox_util.h',
'common/sandbox_win.cc',
@@ -364,6 +392,7 @@
'common/view_message_enums.h',
'common/webplugin_geometry.cc',
'common/webplugin_geometry.h',
+ 'common/websocket.cc',
'common/websocket.h',
'common/websocket_messages.h',
'common/worker_messages.h',
@@ -393,6 +422,7 @@
['include', '^public/common/page_state\\.cc$'],
['include', '^public/common/page_transition_types\\.cc$'],
['include', '^public/common/password_form\\.cc$'],
+ ['include', '^public/common/signed_certificate_timestamp_id_and_status\\.cc$'],
['include', '^public/common/speech_recognition_result\\.cc$'],
['include', '^public/common/ssl_status\\.cc$'],
['include', '^public/common/url_constants\\.cc$'],
@@ -407,12 +437,15 @@
}, { # OS!="ios"
'dependencies': [
'../cc/cc.gyp:cc',
+ '../gpu/gpu.gyp:command_buffer_service',
'../gpu/gpu.gyp:gles2_c_lib',
'../gpu/gpu.gyp:gles2_implementation',
'../gpu/gpu.gyp:gpu_ipc',
+ '../gpu/skia_bindings/skia_bindings.gyp:gpu_skia_bindings',
'../ipc/ipc.gyp:ipc',
'../media/media.gyp:media',
'../media/media.gyp:shared_memory_support',
+ '../third_party/WebKit/public/blink.gyp:blink',
'../ui/gl/gl.gyp:gl',
'../webkit/common/webkit_common.gyp:webkit_common',
'../webkit/storage_browser.gyp:webkit_storage_browser',
@@ -421,10 +454,14 @@
}],
['OS!="ios" and chrome_multiple_dll!=1', {
'dependencies': [
- '../webkit/support/webkit_support.gyp:glue',
+ '../webkit/glue/webkit_glue.gyp:glue',
],
}],
['OS=="mac"', {
+ 'sources': [
+ 'common/gpu/client/gpu_memory_buffer_impl_io_surface.cc',
+ 'common/gpu/client/gpu_memory_buffer_impl_io_surface.h',
+ ],
'sources!': [
'common/plugin_list_posix.cc',
],
@@ -454,9 +491,8 @@
'dependencies': [
'../build/linux/system.gyp:pangocairo',
],
- }, { # use_pango == 0
'sources!': [
- 'common/font_list_pango.cc',
+ 'common/font_list_ozone.cc',
],
}],
['use_x11 == 1', {
@@ -481,17 +517,11 @@
],
}, { # enable_plugins == 0
'sources!': [
- 'common/font_list.cc',
'common/pepper_plugin_list.cc',
'common/pepper_plugin_list.h',
'common/sandbox_util.cc',
],
}],
- ['enable_gpu==1', {
- 'dependencies': [
- '../gpu/gpu.gyp:command_buffer_service',
- ],
- }],
['OS=="android"', {
'dependencies': [
'../media/media.gyp:media',
@@ -501,6 +531,16 @@
'common/gpu/media/android_video_decode_accelerator.h',
],
}],
+ ['OS=="android" and android_webview_build==0', {
+ 'dependencies': [
+ '../media/media.gyp:media',
+ '../third_party/libyuv/libyuv.gyp:libyuv',
+ ],
+ 'sources': [
+ 'common/gpu/media/android_video_encode_accelerator.cc',
+ 'common/gpu/media/android_video_encode_accelerator.h',
+ ],
+ }],
['target_arch=="arm" and chromeos == 1 and use_x11 == 1', {
'dependencies': [
'../media/media.gyp:media',
diff --git a/chromium/content/content_gpu.gypi b/chromium/content/content_gpu.gypi
index 9068549e272..453fbecce80 100644
--- a/chromium/content/content_gpu.gypi
+++ b/chromium/content/content_gpu.gypi
@@ -26,26 +26,18 @@
['OS=="win"', {
'include_dirs': [
'<(DEPTH)/third_party/khronos',
- '<(DEPTH)/third_party/angle_dx11/src',
+ '<(angle_path)/src',
'<(DEPTH)/third_party/wtl/include',
],
'dependencies': [
- '../third_party/angle_dx11/src/build_angle.gyp:libEGL',
- '../third_party/angle_dx11/src/build_angle.gyp:libGLESv2',
+ '<(angle_path)/src/build_angle.gyp:libEGL',
+ '<(angle_path)/src/build_angle.gyp:libGLESv2',
],
'link_settings': {
'libraries': [
'-lsetupapi.lib',
],
},
- 'copies': [
- {
- 'destination': '<(PRODUCT_DIR)',
- 'files': [
- '<(windows_sdk_path)/Redist/D3D/<(winsdk_arch)/d3dcompiler_46.dll',
- ],
- },
- ],
}],
['OS=="win" and target_arch=="ia32" and directxsdk_exists=="True"', {
# We don't support x64 prior to Win7 and D3DCompiler_43.dll is
diff --git a/chromium/content/content_jni.gypi b/chromium/content/content_jni.gypi
index 0699777bd7f..dee7d1cf3bc 100644
--- a/chromium/content/content_jni.gypi
+++ b/chromium/content/content_jni.gypi
@@ -25,22 +25,24 @@
'public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java',
'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java',
'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java',
- 'public/android/java/src/org/chromium/content/browser/LocationProvider.java',
+ 'public/android/java/src/org/chromium/content/browser/LocationProviderAdapter.java',
'public/android/java/src/org/chromium/content/browser/MediaDrmCredentialManager.java',
'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java',
'public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java',
- 'public/android/java/src/org/chromium/content/browser/GenericTouchGesture.java',
'public/android/java/src/org/chromium/content/browser/SpeechRecognition.java',
+ 'public/android/java/src/org/chromium/content/browser/TouchEventSynthesizer.java',
'public/android/java/src/org/chromium/content/browser/TouchPoint.java',
- 'public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java',
- 'public/android/java/src/org/chromium/content/browser/VibrationMessageFilter.java',
+ 'public/android/java/src/org/chromium/content/browser/TracingControllerAndroid.java',
+ 'public/android/java/src/org/chromium/content/browser/VibrationProvider.java',
'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java',
- 'public/android/java/src/org/chromium/content/common/CommandLine.java',
+ 'public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java',
+ 'public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java',
'public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java',
'public/android/java/src/org/chromium/content/common/TraceEvent.java',
],
'variables': {
- 'jni_gen_package': 'content'
+ 'jni_gen_package': 'content',
+ 'jni_generator_ptr_type': 'long',
},
'includes': [ '../build/jni_generator.gypi' ],
}
diff --git a/chromium/content/content_plugin.gypi b/chromium/content/content_plugin.gypi
index 7ff4221d15d..5ad3b808f3f 100644
--- a/chromium/content/content_plugin.gypi
+++ b/chromium/content/content_plugin.gypi
@@ -7,9 +7,9 @@
['enable_plugins==1', {
'dependencies': [
'../skia/skia.gyp:skia',
- '../third_party/npapi/npapi.gyp:npapi',
'../third_party/WebKit/public/blink.gyp:blink',
- '../webkit/support/webkit_support.gyp:glue',
+ '../third_party/npapi/npapi.gyp:npapi',
+ '../webkit/glue/webkit_glue.gyp:glue',
],
'include_dirs': [
'<(INTERMEDIATE_DIR)',
diff --git a/chromium/content/content_ppapi_plugin.gypi b/chromium/content/content_ppapi_plugin.gypi
index 4b8025d99aa..782c1f0cec5 100644
--- a/chromium/content/content_ppapi_plugin.gypi
+++ b/chromium/content/content_ppapi_plugin.gypi
@@ -8,6 +8,7 @@
'dependencies': [
'../base/base.gyp:base',
'../ppapi/ppapi_internal.gyp:ppapi_ipc',
+ '../ui/gfx/gfx.gyp:gfx',
'../ui/ui.gyp:ui',
],
'sources': [
diff --git a/chromium/content/content_renderer.gypi b/chromium/content/content_renderer.gypi
index 46b7468d34f..d8870ccdf8e 100644
--- a/chromium/content/content_renderer.gypi
+++ b/chromium/content/content_renderer.gypi
@@ -4,6 +4,7 @@
{
'dependencies': [
+ '../gin/gin.gyp:gin',
'../jingle/jingle.gyp:jingle_glue',
'../media/media.gyp:media',
'../net/net.gyp:net',
@@ -14,22 +15,22 @@
'../third_party/libjingle/libjingle.gyp:libjingle',
'../third_party/npapi/npapi.gyp:npapi',
'../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
+ '../ui/events/events.gyp:dom4_keycode_converter',
'../ui/native_theme/native_theme.gyp:native_theme',
'../ui/surface/surface.gyp:surface',
- '../ui/ui.gyp:keycode_converter',
'../v8/tools/gyp/v8.gyp:v8',
+ '../webkit/child/webkit_child.gyp:webkit_child',
'../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
'../webkit/common/webkit_common.gyp:webkit_common',
+ '../webkit/glue/webkit_glue.gyp:glue',
'../webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_bindings',
'../webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_support',
'../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
'../webkit/storage_common.gyp:webkit_storage_common',
- '../webkit/support/webkit_support.gyp:glue',
- '../webkit/support/webkit_support.gyp:glue_child',
],
'include_dirs': [
'..',
- '<(SHARED_INTERMEDIATE_DIR)', # Needed by key_systems_info.cc.
+ '<(SHARED_INTERMEDIATE_DIR)', # Needed by key_systems.cc.
],
'sources': [
'public/renderer/android_content_detection_prefixes.cc',
@@ -48,6 +49,9 @@
'public/renderer/pepper_plugin_instance.h',
'public/renderer/renderer_ppapi_host.h',
'public/renderer/render_frame.h',
+ 'public/renderer/render_frame_observer.cc',
+ 'public/renderer/render_frame_observer.h',
+ 'public/renderer/render_frame_observer_tracker.h',
'public/renderer/render_process_observer.cc',
'public/renderer/render_process_observer.h',
'public/renderer/render_thread.cc',
@@ -57,6 +61,7 @@
'public/renderer/render_view_observer.h',
'public/renderer/render_view_observer_tracker.h',
'public/renderer/render_view_visitor.h',
+ 'public/renderer/resource_fetcher.h',
'public/renderer/v8_value_converter.h',
'public/renderer/web_preferences.h',
'renderer/accessibility/accessibility_node_serializer.cc',
@@ -79,10 +84,27 @@
'renderer/android/phone_number_detector.h',
'renderer/android/synchronous_compositor_factory.cc',
'renderer/android/synchronous_compositor_factory.h',
+ 'renderer/browser_plugin/browser_plugin.cc',
+ 'renderer/browser_plugin/browser_plugin.h',
+ 'renderer/browser_plugin/browser_plugin_backing_store.cc',
+ 'renderer/browser_plugin/browser_plugin_backing_store.h',
+ 'renderer/browser_plugin/browser_plugin_bindings.cc',
+ 'renderer/browser_plugin/browser_plugin_bindings.h',
+ 'renderer/browser_plugin/browser_plugin_compositing_helper.cc',
+ 'renderer/browser_plugin/browser_plugin_compositing_helper.h',
+ 'renderer/browser_plugin/browser_plugin_manager_factory.h',
+ 'renderer/browser_plugin/browser_plugin_manager_impl.cc',
+ 'renderer/browser_plugin/browser_plugin_manager_impl.h',
+ 'renderer/browser_plugin/browser_plugin_manager.cc',
+ 'renderer/browser_plugin/browser_plugin_manager.h',
+ 'renderer/clipboard_utils.cc',
+ 'renderer/clipboard_utils.h',
+ 'renderer/context_menu_params_builder.cc',
+ 'renderer/context_menu_params_builder.h',
'renderer/cursor_utils.cc',
'renderer/cursor_utils.h',
- 'renderer/device_orientation_dispatcher.cc',
- 'renderer/device_orientation_dispatcher.h',
+ 'renderer/date_time_suggestion_builder.cc',
+ 'renderer/date_time_suggestion_builder.h',
'renderer/device_orientation/device_motion_event_pump.cc',
'renderer/device_orientation/device_motion_event_pump.h',
'renderer/device_orientation/device_orientation_event_pump.cc',
@@ -112,6 +134,14 @@
'renderer/drop_data_builder.h',
'renderer/external_popup_menu.cc',
'renderer/external_popup_menu.h',
+ 'renderer/fetchers/alt_error_page_resource_fetcher.cc',
+ 'renderer/fetchers/alt_error_page_resource_fetcher.h',
+ 'renderer/fetchers/image_resource_fetcher.cc',
+ 'renderer/fetchers/image_resource_fetcher.h',
+ 'renderer/fetchers/multi_resolution_image_resource_fetcher.cc',
+ 'renderer/fetchers/multi_resolution_image_resource_fetcher.h',
+ 'renderer/fetchers/resource_fetcher_impl.cc',
+ 'renderer/fetchers/resource_fetcher_impl.h',
'renderer/gamepad_shared_memory_reader.cc',
'renderer/gamepad_shared_memory_reader.h',
'renderer/geolocation_dispatcher.cc',
@@ -122,29 +152,31 @@
'renderer/gpu/compositor_software_output_device.h',
'renderer/gpu/delegated_compositor_output_surface.cc',
'renderer/gpu/delegated_compositor_output_surface.h',
- 'renderer/gpu/input_event_filter.cc',
- 'renderer/gpu/input_event_filter.h',
- 'renderer/gpu/input_handler_proxy.cc',
- 'renderer/gpu/input_handler_proxy.h',
- 'renderer/gpu/input_handler_manager.cc',
- 'renderer/gpu/input_handler_manager.h',
- 'renderer/gpu/input_handler_manager_client.h',
- 'renderer/gpu/input_handler_wrapper.cc',
- 'renderer/gpu/input_handler_wrapper.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/stream_texture_host_android.cc',
- 'renderer/gpu/stream_texture_host_android.h',
'renderer/gpu/render_widget_compositor.cc',
'renderer/gpu/render_widget_compositor.h',
+ 'renderer/gpu/stream_texture_host_android.cc',
+ 'renderer/gpu/stream_texture_host_android.h',
'renderer/idle_user_detector.cc',
'renderer/idle_user_detector.h',
'renderer/image_loading_helper.cc',
'renderer/image_loading_helper.h',
+ 'renderer/ime_event_guard.cc',
+ 'renderer/ime_event_guard.h',
'renderer/in_process_renderer_thread.cc',
'renderer/in_process_renderer_thread.h',
+ 'renderer/input/input_event_filter.cc',
+ 'renderer/input/input_event_filter.h',
+ 'renderer/input/input_handler_manager.cc',
+ 'renderer/input/input_handler_manager.h',
+ 'renderer/input/input_handler_manager_client.h',
+ 'renderer/input/input_handler_proxy.cc',
+ 'renderer/input/input_handler_proxy.h',
+ 'renderer/input/input_handler_wrapper.cc',
+ 'renderer/input/input_handler_wrapper.h',
'renderer/input_tag_speech_dispatcher.cc',
'renderer/input_tag_speech_dispatcher.h',
'renderer/internal_document_state_data.cc',
@@ -176,8 +208,6 @@
'renderer/media/android/stream_texture_factory_android_synchronous_impl.h',
'renderer/media/android/webmediaplayer_android.cc',
'renderer/media/android/webmediaplayer_android.h',
- 'renderer/media/android/webmediaplayer_proxy_android.cc',
- 'renderer/media/android/webmediaplayer_proxy_android.h',
'renderer/media/audio_decoder.cc',
'renderer/media/audio_decoder.h',
'renderer/media/audio_device_factory.cc',
@@ -198,8 +228,8 @@
'renderer/media/crypto/content_decryption_module_factory.h',
'renderer/media/crypto/key_systems.cc',
'renderer/media/crypto/key_systems.h',
- 'renderer/media/crypto/key_systems_info.cc',
- 'renderer/media/crypto/key_systems_info.h',
+ 'renderer/media/crypto/key_systems_support_uma.cc',
+ 'renderer/media/crypto/key_systems_support_uma.h',
'renderer/media/crypto/ppapi_decryptor.cc',
'renderer/media/crypto/ppapi_decryptor.h',
'renderer/media/crypto/proxy_decryptor.cc',
@@ -212,6 +242,8 @@
'renderer/media/media_stream_dispatcher.h',
'renderer/media/media_stream_dispatcher_eventhandler.h',
'renderer/media/media_stream_impl.h',
+ 'renderer/media/media_stream_track_extra_data.cc',
+ 'renderer/media/media_stream_track_extra_data.h',
'renderer/media/midi_dispatcher.cc',
'renderer/media/midi_dispatcher.h',
'renderer/media/midi_message_filter.cc',
@@ -268,6 +300,12 @@
'renderer/mouse_lock_dispatcher.h',
'renderer/notification_provider.cc',
'renderer/notification_provider.h',
+ 'renderer/npapi/plugin_channel_host.cc',
+ 'renderer/npapi/plugin_channel_host.h',
+ 'renderer/npapi/webplugin_delegate_proxy.cc',
+ 'renderer/npapi/webplugin_delegate_proxy.h',
+ 'renderer/npapi/webplugin_impl.cc',
+ 'renderer/npapi/webplugin_impl.h',
'renderer/paint_aggregator.cc',
'renderer/paint_aggregator.h',
'renderer/pepper/audio_helper.cc',
@@ -307,8 +345,6 @@
'renderer/pepper/pepper_device_enumeration_host_helper.h',
'renderer/pepper/pepper_file_chooser_host.cc',
'renderer/pepper/pepper_file_chooser_host.h',
- 'renderer/pepper/pepper_file_io_host.cc',
- 'renderer/pepper/pepper_file_io_host.h',
'renderer/pepper/pepper_file_ref_renderer_host.cc',
'renderer/pepper/pepper_file_ref_renderer_host.h',
'renderer/pepper/pepper_file_system_host.cc',
@@ -380,8 +416,6 @@
'renderer/pepper/ppb_video_decoder_impl.h',
'renderer/pepper/ppb_widget_impl.cc',
'renderer/pepper/ppb_widget_impl.h',
- 'renderer/pepper/quota_file_io.cc',
- 'renderer/pepper/quota_file_io.h',
'renderer/pepper/renderer_ppapi_host_impl.cc',
'renderer/pepper/renderer_ppapi_host_impl.h',
'renderer/pepper/renderer_restrict_dispatch_group.h',
@@ -400,39 +434,6 @@
'renderer/pepper/usb_key_code_conversion_win.cc',
'renderer/pepper/v8_var_converter.cc',
'renderer/pepper/v8_var_converter.h',
- 'renderer/browser_plugin/browser_plugin.cc',
- 'renderer/browser_plugin/browser_plugin.h',
- 'renderer/browser_plugin/browser_plugin_backing_store.h',
- 'renderer/browser_plugin/browser_plugin_backing_store.cc',
- 'renderer/browser_plugin/browser_plugin_bindings.h',
- 'renderer/browser_plugin/browser_plugin_bindings.cc',
- 'renderer/browser_plugin/browser_plugin_manager.h',
- 'renderer/browser_plugin/browser_plugin_manager.cc',
- 'renderer/browser_plugin/browser_plugin_manager_factory.h',
- 'renderer/browser_plugin/browser_plugin_manager_impl.h',
- 'renderer/browser_plugin/browser_plugin_manager_impl.cc',
- 'renderer/browser_plugin/browser_plugin_compositing_helper.h',
- 'renderer/browser_plugin/browser_plugin_compositing_helper.cc',
- 'renderer/context_menu_params_builder.cc',
- 'renderer/context_menu_params_builder.h',
- 'renderer/date_time_formatter.cc',
- 'renderer/date_time_formatter.h',
- 'renderer/fetchers/alt_error_page_resource_fetcher.cc',
- 'renderer/fetchers/alt_error_page_resource_fetcher.h',
- 'renderer/fetchers/image_resource_fetcher.cc',
- 'renderer/fetchers/image_resource_fetcher.h',
- 'renderer/fetchers/multi_resolution_image_resource_fetcher.cc',
- 'renderer/fetchers/multi_resolution_image_resource_fetcher.h',
- 'renderer/fetchers/resource_fetcher.cc',
- 'renderer/fetchers/resource_fetcher.h',
- 'renderer/ime_event_guard.cc',
- 'renderer/ime_event_guard.h',
- 'renderer/npapi/plugin_channel_host.cc',
- 'renderer/npapi/plugin_channel_host.h',
- 'renderer/npapi/webplugin_delegate_proxy.cc',
- 'renderer/npapi/webplugin_delegate_proxy.h',
- 'renderer/npapi/webplugin_impl.cc',
- 'renderer/npapi/webplugin_impl.h',
'renderer/render_frame_impl.cc',
'renderer/render_frame_impl.h',
'renderer/render_process.h',
@@ -466,20 +467,28 @@
'renderer/renderer_main_platform_delegate_win.cc',
'renderer/renderer_webapplicationcachehost_impl.cc',
'renderer/renderer_webapplicationcachehost_impl.h',
- 'renderer/renderer_webcookiejar_impl.cc',
- 'renderer/renderer_webcookiejar_impl.h',
'renderer/renderer_webcolorchooser_impl.cc',
'renderer/renderer_webcolorchooser_impl.h',
+ 'renderer/renderer_webcookiejar_impl.cc',
+ 'renderer/renderer_webcookiejar_impl.h',
'renderer/renderer_webkitplatformsupport_impl.cc',
'renderer/renderer_webkitplatformsupport_impl.h',
+ 'renderer/resizing_mode_selector.cc',
+ 'renderer/resizing_mode_selector.h',
'renderer/sad_plugin.cc',
'renderer/sad_plugin.h',
'renderer/savable_resources.cc',
'renderer/savable_resources.h',
'renderer/scoped_clipboard_writer_glue.cc',
'renderer/scoped_clipboard_writer_glue.h',
+ 'renderer/service_worker/embedded_worker_dispatcher.cc',
+ 'renderer/service_worker/embedded_worker_dispatcher.h',
+ 'renderer/service_worker/service_worker_context_client.cc',
+ 'renderer/service_worker/service_worker_context_client.h',
'renderer/shared_memory_seqlock_reader.cc',
'renderer/shared_memory_seqlock_reader.h',
+ 'renderer/shared_worker_repository.cc',
+ 'renderer/shared_worker_repository.h',
'renderer/skia_benchmarking_extension.cc',
'renderer/skia_benchmarking_extension.h',
'renderer/speech_recognition_dispatcher.cc',
@@ -492,21 +501,23 @@
'renderer/text_input_client_observer.h',
'renderer/v8_value_converter_impl.cc',
'renderer/v8_value_converter_impl.h',
- 'renderer/webclipboard_impl.cc',
- 'renderer/webclipboard_impl.h',
'renderer/web_preferences.cc',
'renderer/web_ui_extension.cc',
'renderer/web_ui_extension.h',
'renderer/web_ui_extension_data.cc',
'renderer/web_ui_extension_data.h',
- 'renderer/webcrypto_impl.cc',
- 'renderer/webcrypto_impl.h',
- 'renderer/webcrypto_impl_nss.cc',
- 'renderer/webcrypto_impl_openssl.cc',
+ 'renderer/webclipboard_impl.cc',
+ 'renderer/webclipboard_impl.h',
+ 'renderer/webcrypto/webcrypto_impl.cc',
+ 'renderer/webcrypto/webcrypto_impl.h',
+ 'renderer/webcrypto/webcrypto_impl_nss.cc',
+ 'renderer/webcrypto/webcrypto_impl_openssl.cc',
+ 'renderer/webcrypto/webcrypto_util.cc',
+ 'renderer/webcrypto/webcrypto_util.h',
+ 'renderer/webpublicsuffixlist_impl.cc',
+ 'renderer/webpublicsuffixlist_impl.h',
'renderer/websharedworker_proxy.cc',
'renderer/websharedworker_proxy.h',
- 'renderer/websharedworkerrepository_impl.cc',
- 'renderer/websharedworkerrepository_impl.h',
],
'conditions': [
['notifications==0', {
@@ -557,11 +568,6 @@
'renderer/java/java_bridge_dispatcher.h',
],
}],
- ['google_tv == 1', {
- 'sources!': [
- 'renderer/media/crypto/key_systems_info.cc',
- ],
- }],
# TODO(jrg): remove the OS=="android" section?
# http://crbug.com/113172
# Understand better how media_stream_ is tied into Chromium.
@@ -575,10 +581,25 @@
'../third_party/libjingle/libjingle.gyp:libjingle_webrtc',
'../third_party/libjingle/libjingle.gyp:libpeerconnection',
'../third_party/webrtc/modules/modules.gyp:audio_device',
+ '../third_party/webrtc/modules/modules.gyp:audio_processing',
'<(DEPTH)/crypto/crypto.gyp:crypto',
],
'sources': [
+ 'public/renderer/media_stream_audio_sink.h',
+ 'public/renderer/media_stream_audio_sink.cc',
+ 'public/renderer/media_stream_sink.h',
+ 'public/renderer/media_stream_video_sink.cc',
+ 'public/renderer/media_stream_video_sink.h',
'public/renderer/webrtc_log_message_delegate.h',
+ 'renderer/media/media_stream_audio_processor.cc',
+ 'renderer/media/media_stream_audio_processor.h',
+ 'renderer/media/media_stream_audio_processor_options.cc',
+ 'renderer/media/media_stream_audio_processor_options.h',
+ 'renderer/media/media_stream_audio_sink_owner.cc',
+ 'renderer/media/media_stream_audio_sink_owner.h',
+ 'renderer/media/media_stream_audio_track_sink.h',
+ 'renderer/media/media_stream_video_track.cc',
+ 'renderer/media/media_stream_video_track.h',
'renderer/media/media_stream_center.cc',
'renderer/media/media_stream_dependency_factory.cc',
'renderer/media/media_stream_dispatcher.cc',
@@ -588,6 +609,8 @@
'renderer/media/media_stream_source_observer.h',
'renderer/media/native_handle_impl.cc',
'renderer/media/native_handle_impl.h',
+ 'renderer/media/peer_connection_audio_sink_owner.cc',
+ 'renderer/media/peer_connection_audio_sink_owner.h',
'renderer/media/peer_connection_handler_base.cc',
'renderer/media/peer_connection_handler_base.h',
'renderer/media/peer_connection_identity_service.cc',
@@ -626,8 +649,6 @@
'renderer/media/webaudio_capturer_source.h',
'renderer/media/webrtc_audio_capturer.cc',
'renderer/media/webrtc_audio_capturer.h',
- 'renderer/media/webrtc_audio_capturer_sink_owner.cc',
- 'renderer/media/webrtc_audio_capturer_sink_owner.h',
'renderer/media/webrtc_audio_device_impl.cc',
'renderer/media/webrtc_audio_device_impl.h',
'renderer/media/webrtc_audio_device_not_impl.cc',
@@ -642,8 +663,10 @@
'renderer/media/webrtc_local_audio_source_provider.h',
'renderer/media/webrtc_local_audio_track.cc',
'renderer/media/webrtc_local_audio_track.h',
- 'renderer/media/webrtc_logging_initializer.cc',
- 'renderer/media/webrtc_logging_initializer.h',
+ 'renderer/media/webrtc_logging.cc',
+ 'renderer/media/webrtc_logging.h',
+ 'renderer/media/webrtc/webrtc_video_sink_adapter.cc',
+ 'renderer/media/webrtc/webrtc_video_sink_adapter.h',
'renderer/p2p/host_address_request.cc',
'renderer/p2p/host_address_request.h',
'renderer/p2p/ipc_network_manager.cc',
@@ -653,8 +676,8 @@
'renderer/p2p/network_list_observer.h',
'renderer/p2p/port_allocator.cc',
'renderer/p2p/port_allocator.h',
- 'renderer/p2p/socket_client.cc',
- 'renderer/p2p/socket_client.h',
+ 'renderer/p2p/socket_client_impl.cc',
+ 'renderer/p2p/socket_client_impl.h',
'renderer/p2p/socket_dispatcher.cc',
'renderer/p2p/socket_dispatcher.h',
'renderer/pepper/pepper_video_destination_host.cc',
@@ -662,6 +685,11 @@
'renderer/pepper/pepper_video_source_host.cc',
'renderer/pepper/pepper_video_source_host.h',
],
+ },{ # enable_webrtc==0
+ 'sources': [
+ 'renderer/media/webrtc_logging_noop.cc',
+ 'renderer/media/webrtc_logging.h',
+ ],
}],
['enable_webrtc==1 and google_tv==1', {
'sources': [
@@ -696,23 +724,16 @@
'renderer/media/crypto/ppapi_decryptor.h',
],
}],
- ['enable_gpu!=1', {
- 'sources!': [
- 'renderer/pepper/ppb_graphics_3d_impl.cc',
- 'renderer/pepper/ppb_graphics_3d_impl.h',
- 'renderer/pepper/ppb_open_gl_es_impl.cc',
- ],
- }],
['use_openssl==1', {
'sources!': [
- 'renderer/webcrypto_impl_nss.cc',
+ 'renderer/webcrypto/webcrypto_impl_nss.cc',
],
'dependencies': [
'../third_party/openssl/openssl.gyp:openssl',
],
}, {
'sources!': [
- 'renderer/webcrypto_impl_openssl.cc',
+ 'renderer/webcrypto/webcrypto_impl_openssl.cc',
],
'conditions': [
['os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', {
diff --git a/chromium/content/content_resources.grd b/chromium/content/content_resources.grd
index b8178ed426d..f293ca38a26 100644
--- a/chromium/content/content_resources.grd
+++ b/chromium/content/content_resources.grd
@@ -31,6 +31,9 @@
<include name="IDR_RENDERER_SANDBOX_PROFILE" file="renderer/renderer.sb" type="BINDATA" />
<include name="IDR_UTILITY_SANDBOX_PROFILE" file="utility/utility.sb" type="BINDATA" />
</if>
+ <if expr="is_android">
+ <include name="IDR_MEDIAPLAYER_REMOTE_PLAYBACK_ICON" file="renderer/resources/media/mediaplayer_remote_playback.png" type="BINDATA" />
+ </if>
</includes>
</release>
</grit>
diff --git a/chromium/content/content_shell.gypi b/chromium/content/content_shell.gypi
index 6541d4f9f17..c4ef4427f29 100644
--- a/chromium/content/content_shell.gypi
+++ b/chromium/content/content_shell.gypi
@@ -21,40 +21,42 @@
{
'target_name': 'content_shell_lib',
'type': 'static_library',
- 'defines!': ['CONTENT_IMPLEMENTATION'],
'defines': ['CONTENT_SHELL_VERSION="<(content_shell_version)"'],
'variables': {
'chromium_code': 1,
},
'dependencies': [
- 'content_app_both',
- 'content_browser',
- 'content_common',
- 'content_gpu',
- 'content_plugin',
- 'content_ppapi_plugin',
- 'content_renderer',
+ 'content.gyp:content_app_both',
+ 'content.gyp:content_browser',
+ 'content.gyp:content_common',
+ 'content.gyp:content_gpu',
+ 'content.gyp:content_plugin',
+ 'content.gyp:content_ppapi_plugin',
+ 'content.gyp:content_renderer',
+ 'content.gyp:content_utility',
+ 'content.gyp:content_worker',
'content_shell_resources',
- 'content_utility',
- 'content_worker',
'test_support_content',
'content_resources.gyp:content_resources',
'../base/base.gyp:base',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../components/components.gyp:breakpad_component',
'../ipc/ipc.gyp:ipc',
'../media/media.gyp:media',
'../net/net.gyp:net',
'../net/net.gyp:net_resources',
'../skia/skia.gyp:skia',
'../third_party/WebKit/public/blink_test_runner.gyp:blink_test_runner',
+ '../ui/events/events.gyp:events_base',
+ '../ui/gfx/gfx.gyp:gfx',
'../ui/gl/gl.gyp:gl',
'../ui/ui.gyp:ui',
'../url/url.gyp:url_lib',
'../v8/tools/gyp/v8.gyp:v8',
+ '../webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
'../webkit/common/webkit_common.gyp:webkit_common',
+ '../webkit/glue/webkit_glue.gyp:glue',
'../webkit/webkit_resources.gyp:webkit_resources',
- '../webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
- '../webkit/support/webkit_support.gyp:glue',
],
'include_dirs': [
'..',
@@ -66,6 +68,8 @@
'shell/android/shell_manager.h',
'shell/app/paths_mac.h',
'shell/app/paths_mac.mm',
+ 'shell/app/shell_breakpad_client.cc',
+ 'shell/app/shell_breakpad_client.h',
'shell/app/shell_main_delegate.cc',
'shell/app/shell_main_delegate.h',
'shell/app/shell_main_delegate_mac.h',
@@ -75,8 +79,6 @@
'shell/app/webkit_test_platform_support_linux.cc',
'shell/app/webkit_test_platform_support_mac.mm',
'shell/app/webkit_test_platform_support_win.cc',
- 'shell/browser/minimal_shell.cc',
- 'shell/browser/minimal_shell.h',
'shell/browser/notify_done_forwarder.cc',
'shell/browser/notify_done_forwarder.h',
'shell/browser/shell_android.cc',
@@ -130,6 +132,7 @@
'shell/browser/shell_speech_recognition_manager_delegate.h',
'shell/browser/shell_url_request_context_getter.cc',
'shell/browser/shell_url_request_context_getter.h',
+ 'shell/browser/shell_views.cc',
'shell/browser/shell_web_contents_view_delegate_android.cc',
'shell/browser/shell_web_contents_view_delegate_creator.h',
'shell/browser/shell_web_contents_view_delegate_gtk.cc',
@@ -208,6 +211,11 @@
'test_support_content',
],
}], # OS=="android"
+ ['os_posix == 1 and OS != "mac" and android_webview_build != 1', {
+ 'dependencies': [
+ '../components/components.gyp:breakpad_host',
+ ],
+ }],
['(os_posix==1 and use_aura==1 and linux_use_tcmalloc==1) or (android_use_tcmalloc==1)', {
'dependencies': [
# This is needed by content/app/content_main_runner.cc
@@ -218,26 +226,40 @@
'dependencies': [
'../ui/aura/aura.gyp:aura',
'../ui/base/strings/ui_strings.gyp:ui_strings',
- '../ui/views/controls/webview/webview.gyp:webview',
- '../ui/views/views.gyp:views',
- '../ui/views/views.gyp:views_test_support',
- '../ui/ui.gyp:ui_resources',
],
'sources/': [
['exclude', 'shell/browser/shell_gtk.cc'],
['exclude', 'shell/browser/shell_win.cc'],
],
+ 'conditions': [
+ ['toolkit_views==1', {
+ 'dependencies': [
+ '../ui/resources/ui_resources.gyp:ui_resources',
+ '../ui/views/controls/webview/webview.gyp:webview',
+ '../ui/views/views.gyp:views',
+ '../ui/views/views.gyp:views_test_support',
+ ],
+ 'sources/': [
+ ['exclude', 'shell/browser/shell_aura.cc'],
+ ],
+ }, {
+ 'sources/': [
+ ['exclude', 'shell/browser/shell_views.cc'],
+ ],
+ }],
+ ],
+ }, {
+ 'sources/': [
+ ['exclude', 'shell/browser/shell_aura.cc'],
+ ['exclude', 'shell/browser/shell_views.cc'],
+ ],
}], # use_aura==1
['chromeos==1', {
'dependencies': [
'../chromeos/chromeos.gyp:chromeos',
+ '../ui/wm/wm.gyp:wm_test_support',
],
}], # chromeos==1
- ['use_ash==1', {
- 'dependencies': [
- '../ash/ash.gyp:ash',
- ],
- }],
['use_custom_freetype==1', {
'dependencies': [
'../third_party/freetype2/freetype2.gyp:freetype2',
@@ -292,12 +314,11 @@
'target_name': 'content_shell_pak',
'type': 'none',
'dependencies': [
- 'browser/devtools/devtools_resources.gyp:devtools_resources',
'content_resources.gyp:content_resources',
'content_shell_resources',
'<(DEPTH)/net/net.gyp:net_resources',
'<(DEPTH)/ui/base/strings/ui_strings.gyp:ui_strings',
- '<(DEPTH)/ui/ui.gyp:ui_resources',
+ '<(DEPTH)/ui/resources/ui_resources.gyp:ui_resources',
'<(DEPTH)/webkit/webkit_resources.gyp:webkit_resources',
'<(DEPTH)/webkit/webkit_resources.gyp:webkit_strings',
],
@@ -307,6 +328,11 @@
'browser/tracing/tracing_resources.gyp:tracing_resources',
],
}],
+ ['OS!="android"', {
+ 'dependencies': [
+ 'browser/devtools/devtools_resources.gyp:devtools_resources',
+ ],
+ }],
],
'variables': {
'repack_path': '<(DEPTH)/tools/grit/grit/format/repack.py',
@@ -324,7 +350,6 @@
'<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/ui_resources_100_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/webui_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/ui/ui_strings/ui_strings_en-US.pak',
- '<(SHARED_INTERMEDIATE_DIR)/webkit/devtools_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/webkit/blink_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_resources_100_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_strings_en-US.pak',
@@ -338,6 +363,11 @@
'<@(pak_inputs)'],
'conditions': [
['OS!="android"', {
+ 'variables': {
+ 'pak_inputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/webkit/devtools_resources.pak',
+ ],
+ },
'outputs': [
'<(PRODUCT_DIR)/content_shell.pak',
],
@@ -354,7 +384,6 @@
'target_name': 'content_shell',
'type': 'executable',
'mac_bundle': 1,
- 'defines!': ['CONTENT_IMPLEMENTATION'],
'variables': {
'chromium_code': 1,
},
@@ -451,16 +480,6 @@
],
},
{
- 'postbuild_name': 'Fix Framework Link',
- 'action': [
- 'install_name_tool',
- '-change',
- '/Library/Frameworks/<(content_shell_product_name) Framework.framework/Versions/A/<(content_shell_product_name) Framework',
- '@executable_path/../Frameworks/<(content_shell_product_name) Framework.framework/<(content_shell_product_name) Framework',
- '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}'
- ],
- },
- {
# Modify the Info.plist as needed.
'postbuild_name': 'Tweak Info.plist',
'action': ['../build/mac/tweak_info_plist.py',
@@ -524,8 +543,25 @@
'mac_bundle_resources': [
'shell/app/English.lproj/HttpAuth.xib',
'shell/app/English.lproj/MainMenu.xib',
- '<(PRODUCT_DIR)/content_shell.pak'
+ '<(PRODUCT_DIR)/content_shell.pak',
+ 'shell/app/framework-Info.plist',
+ ],
+ 'mac_bundle_resources!': [
+ 'shell/app/framework-Info.plist',
],
+ 'xcode_settings': {
+ # The framework is placed within the .app's Framework
+ # directory. DYLIB_INSTALL_NAME_BASE and
+ # LD_DYLIB_INSTALL_NAME affect -install_name.
+ 'DYLIB_INSTALL_NAME_BASE':
+ '@executable_path/../Frameworks',
+ # See /build/mac/copy_framework_unversioned.sh for
+ # information on LD_DYLIB_INSTALL_NAME.
+ 'LD_DYLIB_INSTALL_NAME':
+ '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(WRAPPER_NAME)/$(PRODUCT_NAME)',
+
+ 'INFOPLIST_FILE': 'shell/app/framework-Info.plist',
+ },
'dependencies': [
'content_shell_lib',
],
@@ -536,6 +572,24 @@
'shell/app/shell_content_main.cc',
'shell/app/shell_content_main.h',
],
+ 'postbuilds': [
+ {
+ # Modify the Info.plist as needed. The script explains why
+ # this is needed. This is also done in the chrome target.
+ # The framework needs the Breakpad keys if this feature is
+ # enabled. It does not need the Keystone keys; these always
+ # come from the outer application bundle. The framework
+ # doesn't currently use the SCM keys for anything,
+ # but this seems like a really good place to store them.
+ 'postbuild_name': 'Tweak Info.plist',
+ 'action': ['../build/mac/tweak_info_plist.py',
+ '--breakpad=1',
+ '--keystone=0',
+ '--scm=1',
+ '--version=<(content_shell_version)',
+ '--branding=<(content_shell_product_name)'],
+ },
+ ],
'copies': [
{
# Copy FFmpeg binaries for audio/video support.
@@ -544,6 +598,13 @@
'<(PRODUCT_DIR)/ffmpegsumo.so',
],
},
+ {
+ 'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Resources',
+ 'files': [
+ '<(PRODUCT_DIR)/crash_inspector',
+ '<(PRODUCT_DIR)/crash_report_sender.app'
+ ],
+ },
],
'conditions': [
['enable_webrtc==1', {
@@ -601,8 +662,8 @@
'action': [
'install_name_tool',
'-change',
- '/Library/Frameworks/<(content_shell_product_name) Framework.framework/Versions/A/<(content_shell_product_name) Framework',
- '@executable_path/../../../../Frameworks/<(content_shell_product_name) Framework.framework/<(content_shell_product_name) Framework',
+ '@executable_path/../Frameworks/<(content_shell_product_name) Framework.framework/<(content_shell_product_name) Framework',
+ '@executable_path/../../../<(content_shell_product_name) Framework.framework/<(content_shell_product_name) Framework',
'${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}'
],
},
@@ -693,7 +754,7 @@
'target_name': 'content_shell_java',
'type': 'none',
'dependencies': [
- 'content_java',
+ 'content.gyp:content_java',
],
'variables': {
'java_in_dir': '../content/shell/android/java',
@@ -720,7 +781,7 @@
'target_name': 'content_shell_apk',
'type': 'none',
'dependencies': [
- 'content_java',
+ 'content.gyp:content_java',
'content_java_test_support',
'content_shell_java',
'libcontent_shell_content_view',
@@ -728,7 +789,7 @@
'../media/media.gyp:media_java',
'../net/net.gyp:net_java',
'../tools/android/forwarder/forwarder.gyp:forwarder',
- '../ui/ui.gyp:ui_java',
+ '../ui/android/ui_android.gyp:ui_java',
],
'variables': {
'apk_name': 'ContentShell',
@@ -737,7 +798,7 @@
'resource_dir': 'shell/android/shell_apk/res',
'native_lib_target': 'libcontent_shell_content_view',
'additional_input_paths': ['<(PRODUCT_DIR)/content_shell/assets/content_shell.pak'],
- 'asset_location': '<(ant_build_out)/content_shell/assets',
+ 'asset_location': '<(PRODUCT_DIR)/content_shell/assets',
},
'conditions': [
['android_webview_build==0', {
@@ -750,5 +811,62 @@
},
],
}], # OS=="android"
+ ['OS=="win"', {
+ 'targets': [
+ {
+ 'target_name': 'content_shell_crash_service',
+ 'type': 'executable',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../components/components.gyp:breakpad_crash_service',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'shell/tools/content_shell_crash_service.cc',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS
+ },
+ },
+ },
+ ],
+ }], # OS=="win"
+ ['OS=="win" and fastbuild==0 and target_arch=="ia32"', {
+ 'variables': {
+ 'dest_dir': '<(PRODUCT_DIR)/syzygy',
+ },
+ 'targets': [
+ {
+ 'target_name': 'content_shell_syzyasan',
+ 'type': 'none',
+ 'sources' : [],
+ # Instrument content_shell with SyzyAsan.
+ 'actions': [
+ {
+ 'action_name': 'Instrument content_shell with SyzyAsan',
+ 'msvs_cygwin_shell': 0,
+ 'inputs': [
+ '<(PRODUCT_DIR)/content_shell.exe',
+ ],
+ 'outputs': [
+ '<(dest_dir)/content_shell.exe',
+ '<(dest_dir)/content_shell.exe.pdb',
+ ],
+ 'action': [
+ 'python',
+ '<(DEPTH)/chrome/tools/build/win/syzygy_instrument.py',
+ '--mode', 'asan',
+ '--input_executable', '<(PRODUCT_DIR)/content_shell.exe',
+ '--input_symbol', '<(PRODUCT_DIR)/content_shell.exe.pdb',
+ '--destination_dir', '<(dest_dir)',
+ ],
+ },
+ ],
+ },
+ ],
+ }], # OS=="win" and fastbuild==0 and target_arch=="ia32"
]
}
diff --git a/chromium/content/content_shell_and_tests.gyp b/chromium/content/content_shell_and_tests.gyp
new file mode 100644
index 00000000000..b3c3c4c20bf
--- /dev/null
+++ b/chromium/content/content_shell_and_tests.gyp
@@ -0,0 +1,32 @@
+# 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.
+
+{
+ 'variables': {
+ 'chromium_code': 1, # Use higher warning level.
+ },
+ 'target_defaults': {
+ 'conditions': [
+ # TODO(jschuh): Remove this after crbug.com/173851 gets fixed.
+ ['OS=="win" and target_arch=="x64"', {
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'AdditionalOptions': ['/bigobj'],
+ },
+ },
+ }],
+ ],
+ },
+ 'includes': [
+ 'content_tests.gypi',
+ ],
+ 'conditions': [
+ ['OS != "ios"', {
+ 'includes': [
+ '../build/win_precompile.gypi',
+ 'content_shell.gypi',
+ ],
+ }],
+ ],
+}
diff --git a/chromium/content/content_tests.gypi b/chromium/content/content_tests.gypi
index 6b609fe8ee6..6ac19670386 100644
--- a/chromium/content/content_tests.gypi
+++ b/chromium/content/content_tests.gypi
@@ -7,20 +7,22 @@
{
'target_name': 'test_support_content',
'type': 'static_library',
- 'defines!': ['CONTENT_IMPLEMENTATION'],
'dependencies': [
'../net/net.gyp:net_test_support',
'../skia/skia.gyp:skia',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
- '../ui/ui.gyp:keycode_converter',
+ '../ui/events/events.gyp:dom4_keycode_converter',
+ '../ui/events/events.gyp:events_base',
+ '../ui/gfx/gfx.gyp:gfx',
+ '../ui/resources/ui_resources.gyp:ui_resources',
'../ui/ui.gyp:ui',
- '../ui/ui.gyp:ui_resources',
- '../ui/ui.gyp:ui_test_support',
+ '../ui/ui_unittests.gyp:ui_test_support',
'../url/url.gyp:url_lib',
- 'content_app_both',
- 'content_browser',
- 'content_common',
+ 'browser/speech/proto/speech_proto.gyp:speech_proto',
+ 'content.gyp:content_app_both',
+ 'content.gyp:content_browser',
+ 'content.gyp:content_common',
],
'include_dirs': [
'..',
@@ -37,7 +39,6 @@
'public/test/download_test_observer.h',
'public/test/fake_speech_recognition_manager.cc',
'public/test/fake_speech_recognition_manager.h',
- 'public/test/js_injection_ready_observer.h',
'public/test/layouttest_support.h',
'public/test/mock_download_item.cc',
'public/test/mock_download_item.h',
@@ -53,22 +54,28 @@
'public/test/mock_resource_context.h',
'public/test/nested_message_pump_android.cc',
'public/test/nested_message_pump_android.h',
- 'public/test/render_view_fake_resources_test.cc',
- 'public/test/render_view_fake_resources_test.h',
'public/test/render_view_test.cc',
'public/test/render_view_test.h',
'public/test/render_widget_test.cc',
'public/test/render_widget_test.h',
+ 'public/test/sandbox_file_system_test_helper.cc',
+ 'public/test/sandbox_file_system_test_helper.h',
'public/test/test_browser_context.cc',
'public/test/test_browser_context.h',
- 'public/test/test_browser_thread_bundle.cc',
- 'public/test/test_browser_thread_bundle.h',
'public/test/test_browser_thread.cc',
'public/test/test_browser_thread.h',
+ 'public/test/test_browser_thread_bundle.cc',
+ 'public/test/test_browser_thread_bundle.h',
'public/test/test_content_client_initializer.cc',
'public/test/test_content_client_initializer.h',
'public/test/test_file_error_injector.cc',
'public/test/test_file_error_injector.h',
+ 'public/test/test_file_system_backend.cc',
+ 'public/test/test_file_system_backend.h',
+ 'public/test/test_file_system_context.cc',
+ 'public/test/test_file_system_context.h',
+ 'public/test/test_file_system_options.cc',
+ 'public/test/test_file_system_options.h',
'public/test/test_launcher.cc',
'public/test/test_launcher.h',
'public/test/test_navigation_observer.cc',
@@ -101,15 +108,13 @@
'browser/renderer_host/compositing_iosurface_transformer_mac.h',
'browser/renderer_host/media/mock_media_observer.cc',
'browser/renderer_host/media/mock_media_observer.h',
- 'browser/renderer_host/test_backing_store.cc',
- 'browser/renderer_host/test_backing_store.h',
- 'browser/renderer_host/test_render_view_host.cc',
- 'browser/renderer_host/test_render_view_host.h',
'gpu/gpu_idirect3d9_mock_win.cc',
'gpu/gpu_idirect3d9_mock_win.h',
'test/content_test_suite.cc',
'test/content_test_suite.h',
'test/layouttest_support.cc',
+ 'test/mock_google_streaming_server.cc',
+ 'test/mock_google_streaming_server.h',
'test/mock_keyboard.cc',
'test/mock_keyboard.h',
'test/mock_keyboard_driver_win.cc',
@@ -118,6 +123,9 @@
'test/mock_render_process.h',
'test/mock_webclipboard_impl.cc',
'test/mock_webclipboard_impl.h',
+ 'test/mock_webframeclient.h',
+ 'test/mock_weburlloader.cc',
+ 'test/mock_weburlloader.h',
'test/net/url_request_abort_on_end_job.cc',
'test/net/url_request_abort_on_end_job.h',
'test/net/url_request_failed_job.cc',
@@ -130,12 +138,20 @@
'test/net/url_request_slow_download_job.h',
'test/ppapi_unittest.cc',
'test/ppapi_unittest.h',
+ 'test/test_backing_store.cc',
+ 'test/test_backing_store.h',
'test/test_content_browser_client.cc',
'test/test_content_browser_client.h',
'test/test_content_client.cc',
'test/test_content_client.h',
'test/test_media_stream_client.cc',
'test/test_media_stream_client.h',
+ 'test/test_render_frame_host.cc',
+ 'test/test_render_frame_host.h',
+ 'test/test_render_frame_host_factory.cc',
+ 'test/test_render_frame_host_factory.h',
+ 'test/test_render_view_host.cc',
+ 'test/test_render_view_host.h',
'test/test_render_view_host_factory.cc',
'test/test_render_view_host_factory.h',
'test/test_video_frame_provider.cc',
@@ -158,10 +174,11 @@
'test/weburl_loader_mock_factory.cc',
'test/weburl_loader_mock_factory.h',
- # TODO(phajdan.jr): Those files should be moved to webkit
- # test support target.
+ # TODO(kinuko): Those files should be moved to content/public/test.
'../webkit/browser/appcache/appcache_test_helper.cc',
'../webkit/browser/appcache/appcache_test_helper.h',
+ '../webkit/browser/fileapi/async_file_test_helper.cc',
+ '../webkit/browser/fileapi/async_file_test_helper.h',
],
'conditions': [
['OS == "ios"', {
@@ -188,27 +205,20 @@
'copies': [{
'destination': '<(SHARED_INTERMEDIATE_DIR)/webkit',
'files': [
- '../webkit/tools/test_shell/resources/missingImage.png',
- '../webkit/tools/test_shell/resources/textAreaResizeCorner.png',
- ],
- }],
- }, { # OS!="mac"
- 'copies': [{
- 'destination': '<(PRODUCT_DIR)/DumpRenderTree_resources',
- 'files': [
- '../webkit/tools/test_shell/resources/missingImage.gif',
- '../webkit/tools/test_shell/resources/textAreaResizeCorner.png',
+ 'shell/resources/missingImage.png',
+ 'shell/resources/textAreaResizeCorner.png',
],
}],
}],
],
'dependencies': [
- 'content_child',
- 'content_gpu',
- 'content_ppapi_plugin',
- 'content_renderer',
- 'content_utility',
- 'content_worker',
+ 'content.gyp:content_child',
+ 'content.gyp:content_gpu',
+ 'content.gyp:content_ppapi_plugin',
+ 'content.gyp:content_renderer',
+ 'content.gyp:content_utility',
+ 'content.gyp:content_worker',
+ '../cc/cc_tests.gyp:cc_test_support',
'../media/media.gyp:media',
'../ppapi/ppapi_internal.gyp:ppapi_host',
'../ppapi/ppapi_internal.gyp:ppapi_proxy',
@@ -217,14 +227,14 @@
'../third_party/WebKit/public/blink.gyp:blink',
'../third_party/WebKit/public/blink_test_runner.gyp:blink_test_runner',
'../ui/surface/surface.gyp:surface',
+ '../webkit/child/webkit_child.gyp:webkit_child',
'../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
'../webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
+ '../webkit/glue/webkit_glue.gyp:glue',
'../webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_support',
'../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
'../webkit/storage_browser.gyp:webkit_storage_browser',
'../webkit/storage_common.gyp:webkit_storage_common',
- '../webkit/support/webkit_support.gyp:glue',
- '../webkit/support/webkit_support.gyp:glue_child',
],
}],
['OS == "win" or toolkit_uses_gtk == 1', {
@@ -268,6 +278,7 @@
'dependencies': [
'../ui/aura/aura.gyp:aura_test_support',
'../ui/compositor/compositor.gyp:compositor',
+ '../ui/resources/ui_resources.gyp:ui_test_pak',
],
}],
['OS=="win"', {
@@ -282,7 +293,7 @@
}],
['OS=="android"', {
'dependencies': [
- '../ui/ui.gyp:shell_dialogs',
+ '../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
'test_support_content_jni_headers',
],
}],
@@ -291,10 +302,9 @@
{
'target_name': 'content_unittests',
'type': '<(gtest_target_type)',
- 'defines!': ['CONTENT_IMPLEMENTATION'],
'dependencies': [
- 'content_browser',
- 'content_common',
+ 'content.gyp:content_browser',
+ 'content.gyp:content_common',
'test_support_content',
'browser/speech/proto/speech_proto.gyp:speech_proto',
'../base/base.gyp:test_support_base',
@@ -305,6 +315,7 @@
'../sql/sql.gyp:test_support_sql',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
+ '../ui/gfx/gfx.gyp:gfx',
'../ui/ui.gyp:ui',
'../webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
],
@@ -317,13 +328,14 @@
'browser/accessibility/browser_accessibility_manager_unittest.cc',
'browser/accessibility/browser_accessibility_win_unittest.cc',
'browser/appcache/chrome_appcache_service_unittest.cc',
+ 'browser/aura/software_browser_compositor_output_surface_unittest.cc',
+ 'browser/aura/software_output_device_ozone_unittest.cc',
'browser/browser_thread_unittest.cc',
'browser/browser_url_handler_impl_unittest.cc',
'browser/byte_stream_unittest.cc',
'browser/child_process_security_policy_unittest.cc',
'browser/device_orientation/data_fetcher_impl_android_unittest.cc',
'browser/device_orientation/data_fetcher_shared_memory_base_unittest.cc',
- 'browser/device_orientation/provider_unittest.cc',
'browser/devtools/devtools_http_handler_unittest.cc',
'browser/devtools/devtools_manager_unittest.cc',
'browser/dom_storage/dom_storage_area_unittest.cc',
@@ -337,12 +349,36 @@
'browser/download/file_metadata_unittest_linux.cc',
'browser/download/rate_estimator_unittest.cc',
'browser/download/save_package_unittest.cc',
+ 'browser/fileapi/blob_url_request_job_unittest.cc',
+ 'browser/fileapi/copy_or_move_file_validator_unittest.cc',
+ 'browser/fileapi/copy_or_move_operation_delegate_unittest.cc',
+ 'browser/fileapi/dragged_file_util_unittest.cc',
+ 'browser/fileapi/file_system_context_unittest.cc',
+ 'browser/fileapi/file_system_dir_url_request_job_unittest.cc',
+ 'browser/fileapi/file_system_file_stream_reader_unittest.cc',
+ 'browser/fileapi/file_system_operation_impl_unittest.cc',
+ 'browser/fileapi/file_system_operation_impl_write_unittest.cc',
+ 'browser/fileapi/file_system_operation_runner_unittest.cc',
+ 'browser/fileapi/file_system_quota_client_unittest.cc',
+ 'browser/fileapi/file_system_url_request_job_unittest.cc',
+ 'browser/fileapi/file_writer_delegate_unittest.cc',
'browser/fileapi/fileapi_message_filter_unittest.cc',
+ 'browser/fileapi/local_file_util_unittest.cc',
+ 'browser/fileapi/obfuscated_file_util_unittest.cc',
+ 'browser/fileapi/plugin_private_file_system_backend_unittest.cc',
+ 'browser/fileapi/recursive_operation_delegate_unittest.cc',
+ 'browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc',
+ 'browser/fileapi/sandbox_file_system_backend_unittest.cc',
+ 'browser/fileapi/transient_file_util_unittest.cc',
+ 'browser/fileapi/upload_file_system_file_element_reader_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',
+ 'browser/frame_host/render_frame_host_manager_unittest.cc',
'browser/gamepad/gamepad_provider_unittest.cc',
'browser/gamepad/gamepad_test_helpers.cc',
'browser/gamepad/gamepad_test_helpers.h',
'browser/geolocation/geolocation_provider_unittest.cc',
- 'browser/geolocation/gps_location_provider_unittest_linux.cc',
'browser/geolocation/location_arbitrator_impl_unittest.cc',
'browser/geolocation/network_location_provider_unittest.cc',
'browser/geolocation/wifi_data_provider_chromeos_unittest.cc',
@@ -354,11 +390,17 @@
'browser/indexed_db/indexed_db_backing_store_unittest.cc',
'browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc',
'browser/indexed_db/indexed_db_database_unittest.cc',
+ 'browser/indexed_db/indexed_db_factory_unittest.cc',
'browser/indexed_db/indexed_db_fake_backing_store.cc',
'browser/indexed_db/indexed_db_fake_backing_store.h',
'browser/indexed_db/indexed_db_leveldb_coding_unittest.cc',
'browser/indexed_db/indexed_db_quota_client_unittest.cc',
+ 'browser/indexed_db/indexed_db_transaction_unittest.cc',
'browser/indexed_db/indexed_db_unittest.cc',
+ 'browser/indexed_db/mock_indexed_db_callbacks.cc',
+ 'browser/indexed_db/mock_indexed_db_callbacks.h',
+ 'browser/indexed_db/mock_indexed_db_database_callbacks.cc',
+ 'browser/indexed_db/mock_indexed_db_database_callbacks.h',
'browser/indexed_db/leveldb/leveldb_unittest.cc',
'browser/indexed_db/list_set_unittest.cc',
'browser/loader/offline_policy_unittest.cc',
@@ -376,15 +418,16 @@
'browser/power_monitor_message_broadcaster_unittest.cc',
'browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc',
'browser/renderer_host/gtk_key_bindings_handler_unittest.cc',
- 'browser/renderer_host/input/buffered_input_router_unittest.cc',
- 'browser/renderer_host/input/immediate_input_router_unittest.cc',
- 'browser/renderer_host/input/input_router_unittest.h',
- 'browser/renderer_host/input/input_router_unittest.cc',
- 'browser/renderer_host/input/input_queue_unittest.cc',
+ 'browser/renderer_host/input/gesture_event_filter_unittest.cc',
+ 'browser/renderer_host/input/input_router_impl_unittest.cc',
'browser/renderer_host/input/mock_input_ack_handler.cc',
'browser/renderer_host/input/mock_input_ack_handler.h',
'browser/renderer_host/input/mock_input_router_client.cc',
'browser/renderer_host/input/mock_input_router_client.h',
+ 'browser/renderer_host/input/synthetic_gesture_controller_unittest.cc',
+ 'browser/renderer_host/input/tap_suppression_controller_unittest.cc',
+ 'browser/renderer_host/input/touch_event_queue_unittest.cc',
+ 'browser/renderer_host/input/touch_action_filter_unittest.cc',
'browser/renderer_host/media/audio_input_device_manager_unittest.cc',
'browser/renderer_host/media/audio_mirroring_manager_unittest.cc',
'browser/renderer_host/media/audio_renderer_host_unittest.cc',
@@ -392,6 +435,7 @@
'browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc',
'browser/renderer_host/media/media_stream_manager_unittest.cc',
'browser/renderer_host/media/media_stream_ui_proxy_unittest.cc',
+ 'browser/renderer_host/media/midi_host_unittest.cc',
'browser/renderer_host/media/video_capture_buffer_pool_unittest.cc',
'browser/renderer_host/media/video_capture_controller_unittest.cc',
'browser/renderer_host/media/video_capture_host_unittest.cc',
@@ -401,19 +445,28 @@
'browser/renderer_host/media/web_contents_video_capture_device_unittest.cc',
'browser/renderer_host/pepper/browser_ppapi_host_test.cc',
'browser/renderer_host/pepper/browser_ppapi_host_test.h',
+ 'browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc',
'browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc',
'browser/renderer_host/pepper/pepper_printing_host_unittest.cc',
+ 'browser/renderer_host/pepper/quota_reservation_unittest.cc',
+ 'browser/renderer_host/render_process_host_unittest.cc',
'browser/renderer_host/render_view_host_unittest.cc',
'browser/renderer_host/render_widget_host_unittest.cc',
'browser/renderer_host/render_widget_host_view_aura_unittest.cc',
'browser/renderer_host/render_widget_host_view_guest_unittest.cc',
'browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm',
'browser/renderer_host/render_widget_host_view_mac_unittest.mm',
- 'browser/renderer_host/synthetic_gesture_controller_unittest.cc',
+ 'browser/renderer_host/software_frame_manager_unittest.cc',
'browser/renderer_host/text_input_client_mac_unittest.mm',
'browser/renderer_host/web_input_event_aura_unittest.cc',
'browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc',
+ 'browser/renderer_host/websocket_dispatcher_host_unittest.cc',
'browser/resolve_proxy_msg_helper_unittest.cc',
+ 'browser/service_worker/embedded_worker_instance_unittest.cc',
+ 'browser/service_worker/service_worker_context_unittest.cc',
+ 'browser/service_worker/service_worker_dispatcher_host_unittest.cc',
+ 'browser/service_worker/service_worker_registration_unittest.cc',
+ 'browser/service_worker/service_worker_storage_unittest.cc',
'browser/site_instance_impl_unittest.cc',
'browser/speech/chunked_byte_buffer_unittest.cc',
'browser/speech/endpointer/endpointer_unittest.cc',
@@ -422,16 +475,12 @@
'browser/speech/speech_recognizer_impl_unittest.cc',
'browser/ssl/ssl_host_state_unittest.cc',
'browser/startup_task_runner_unittest.cc',
- 'browser/storage_partition_impl_unittest.cc',
'browser/storage_partition_impl_map_unittest.cc',
+ 'browser/storage_partition_impl_unittest.cc',
'browser/streams/stream_unittest.cc',
'browser/streams/stream_url_request_job_unittest.cc',
'browser/system_message_window_win_unittest.cc',
- 'browser/tracing/trace_subscriber_stdio_unittest.cc',
'browser/web_contents/aura/window_slider_unittest.cc',
- 'browser/web_contents/navigation_controller_impl_unittest.cc',
- 'browser/web_contents/navigation_entry_impl_unittest.cc',
- 'browser/web_contents/render_view_host_manager_unittest.cc',
'browser/web_contents/web_contents_delegate_unittest.cc',
'browser/web_contents/web_contents_impl_unittest.cc',
'browser/web_contents/web_contents_user_data_unittest.cc',
@@ -442,7 +491,7 @@
'browser/webui/web_ui_message_handler_unittest.cc',
'child/fileapi/webfilewriter_base_unittest.cc',
'child/indexed_db/indexed_db_dispatcher_unittest.cc',
- 'child/indexed_db/proxy_webidbcursor_impl_unittest.cc',
+ 'child/indexed_db/webidbcursor_impl_unittest.cc',
'child/npapi/plugin_lib_unittest.cc',
'child/power_monitor_broadcast_source_unittest.cc',
'child/resource_dispatcher_unittest.cc',
@@ -470,14 +519,13 @@
'renderer/android/email_detector_unittest.cc',
'renderer/android/phone_number_detector_unittest.cc',
'renderer/bmp_image_decoder_unittest.cc',
- 'renderer/date_time_formatter_unittest.cc',
'renderer/device_orientation/device_motion_event_pump_unittest.cc',
'renderer/device_orientation/device_orientation_event_pump_unittest.cc',
'renderer/disambiguation_popup_helper_unittest.cc',
'renderer/dom_storage/dom_storage_cached_area_unittest.cc',
- 'renderer/gpu/input_event_filter_unittest.cc',
- 'renderer/gpu/input_handler_proxy_unittest.cc',
'renderer/ico_image_decoder_unittest.cc',
+ 'renderer/input/input_event_filter_unittest.cc',
+ 'renderer/input/input_handler_proxy_unittest.cc',
'renderer/media/android/media_info_loader_unittest.cc',
'renderer/media/audio_message_filter_unittest.cc',
'renderer/media/audio_renderer_mixer_manager_unittest.cc',
@@ -496,13 +544,13 @@
'renderer/pepper/host_var_tracker_unittest.cc',
'renderer/pepper/mock_resource.h',
'renderer/pepper/pepper_broker_unittest.cc',
- 'renderer/pepper/quota_file_io_unittest.cc',
'renderer/pepper/v8_var_converter_unittest.cc',
'renderer/render_thread_impl_unittest.cc',
'renderer/render_view_impl_unittest.cc',
+ 'renderer/render_widget_unittest.cc',
'renderer/skia_benchmarking_extension_unittest.cc',
'renderer/v8_value_converter_impl_unittest.cc',
- 'renderer/webcrypto_impl_unittest.cc',
+ 'renderer/webcrypto/webcrypto_impl_unittest.cc',
'test/image_decoder_test.cc',
'test/image_decoder_test.h',
'test/run_all_unittests.cc',
@@ -527,7 +575,6 @@
'../webkit/browser/appcache/mock_appcache_storage.h',
'../webkit/browser/appcache/mock_appcache_storage_unittest.cc',
'../webkit/browser/blob/blob_storage_context_unittest.cc',
- '../webkit/browser/blob/blob_url_request_job_unittest.cc',
'../webkit/browser/blob/local_file_stream_reader_unittest.cc',
'../webkit/browser/blob/mock_blob_url_request_context.cc',
'../webkit/browser/blob/mock_blob_url_request_context.h',
@@ -535,49 +582,25 @@
'../webkit/browser/database/database_tracker_unittest.cc',
'../webkit/browser/database/database_util_unittest.cc',
'../webkit/browser/database/databases_table_unittest.cc',
- '../webkit/browser/fileapi/async_file_test_helper.cc',
- '../webkit/browser/fileapi/async_file_test_helper.h',
- '../webkit/browser/fileapi/copy_or_move_file_validator_unittest.cc',
- '../webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc',
- '../webkit/browser/fileapi/dragged_file_util_unittest.cc',
'../webkit/browser/fileapi/external_mount_points_unittest.cc',
- '../webkit/browser/fileapi/file_system_context_unittest.cc',
- '../webkit/browser/fileapi/file_system_dir_url_request_job_unittest.cc',
- '../webkit/browser/fileapi/file_system_file_stream_reader_unittest.cc',
- '../webkit/browser/fileapi/file_system_operation_impl_unittest.cc',
- '../webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc',
- '../webkit/browser/fileapi/file_system_operation_runner_unittest.cc',
- '../webkit/browser/fileapi/file_system_quota_client_unittest.cc',
- '../webkit/browser/fileapi/file_system_url_request_job_unittest.cc',
'../webkit/browser/fileapi/file_system_url_unittest.cc',
'../webkit/browser/fileapi/file_system_usage_cache_unittest.cc',
- '../webkit/browser/fileapi/file_writer_delegate_unittest.cc',
'../webkit/browser/fileapi/isolated_context_unittest.cc',
'../webkit/browser/fileapi/local_file_stream_writer_unittest.cc',
- '../webkit/browser/fileapi/local_file_util_unittest.cc',
'../webkit/browser/fileapi/mock_file_change_observer.cc',
'../webkit/browser/fileapi/mock_file_change_observer.h',
- '../webkit/browser/fileapi/mock_file_system_context.cc',
- '../webkit/browser/fileapi/mock_file_system_context.h',
- '../webkit/browser/fileapi/mock_file_system_options.cc',
- '../webkit/browser/fileapi/mock_file_system_options.h',
'../webkit/browser/fileapi/native_file_util_unittest.cc',
- '../webkit/browser/fileapi/obfuscated_file_util_unittest.cc',
- '../webkit/browser/fileapi/recursive_operation_delegate_unittest.cc',
+ '../webkit/browser/fileapi/quota/quota_backend_impl_unittest.cc',
+ '../webkit/browser/fileapi/quota/quota_reservation_manager_unittest.cc',
'../webkit/browser/fileapi/sandbox_database_test_helper.cc',
'../webkit/browser/fileapi/sandbox_database_test_helper.h',
'../webkit/browser/fileapi/sandbox_directory_database_unittest.cc',
- '../webkit/browser/fileapi/sandbox_file_system_backend_unittest.cc',
- '../webkit/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc',
- '../webkit/browser/fileapi/sandbox_file_system_test_helper.cc',
- '../webkit/browser/fileapi/sandbox_file_system_test_helper.h',
'../webkit/browser/fileapi/sandbox_isolated_origin_database_unittest.cc',
'../webkit/browser/fileapi/sandbox_origin_database_unittest.cc',
+ '../webkit/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc',
'../webkit/browser/fileapi/test_file_set.cc',
'../webkit/browser/fileapi/test_file_set.h',
'../webkit/browser/fileapi/timed_task_helper_unittest.cc',
- '../webkit/browser/fileapi/transient_file_util_unittest.cc',
- '../webkit/browser/fileapi/upload_file_system_file_element_reader_unittest.cc',
'../webkit/child/multipart_response_delegate_unittest.cc',
'../webkit/child/touch_fling_gesture_curve_unittest.cc',
'../webkit/child/worker_task_runner_unittest.cc',
@@ -587,8 +610,6 @@
'../webkit/common/database/database_identifier_unittest.cc',
'../webkit/common/fileapi/file_system_util_unittest.cc',
'../webkit/glue/webkit_glue_unittest.cc',
- '../webkit/mocks/mock_weburlloader.cc',
- '../webkit/mocks/mock_weburlloader.h',
'../webkit/common/user_agent/user_agent_unittest.cc',
'../webkit/browser/quota/mock_quota_manager.cc',
'../webkit/browser/quota/mock_quota_manager.h',
@@ -616,11 +637,11 @@
],
}, { # OS != "ios"
'dependencies': [
- 'content_browser',
- 'content_child',
- 'content_gpu',
- 'content_plugin',
- 'content_renderer',
+ 'content.gyp:content_browser',
+ 'content.gyp:content_child',
+ 'content.gyp:content_gpu',
+ 'content.gyp:content_plugin',
+ 'content.gyp:content_renderer',
'content_resources.gyp:content_resources',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../gpu/gpu.gyp:gpu',
@@ -634,14 +655,15 @@
'../third_party/icu/icu.gyp:icuuc',
'../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
'../third_party/libjingle/libjingle.gyp:libjingle',
+ '../ui/compositor/compositor.gyp:compositor_test_support',
'../ui/gl/gl.gyp:gl',
'../v8/tools/gyp/v8.gyp:v8',
'../webkit/common/webkit_common.gyp:webkit_common',
+ '../webkit/glue/webkit_glue.gyp:glue',
+ '../webkit/child/webkit_child.gyp:webkit_child',
'../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
'../webkit/storage_browser.gyp:webkit_storage_browser',
'../webkit/storage_common.gyp:webkit_storage_common',
- '../webkit/support/webkit_support.gyp:glue',
- '../webkit/support/webkit_support.gyp:glue_child',
],
}],
['enable_plugins==0', {
@@ -660,16 +682,19 @@
'sources': [
'browser/media/webrtc_internals_unittest.cc',
'browser/renderer_host/media/webrtc_identity_service_host_unittest.cc',
+ 'browser/renderer_host/p2p/socket_host_test_utils.cc',
'browser/renderer_host/p2p/socket_host_test_utils.h',
'browser/renderer_host/p2p/socket_host_tcp_unittest.cc',
'browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc',
'browser/renderer_host/p2p/socket_host_udp_unittest.cc',
+ 'renderer/media/media_stream_audio_processor_unittest.cc',
'renderer/media/media_stream_dependency_factory_unittest.cc',
'renderer/media/media_stream_dispatcher_unittest.cc',
'renderer/media/media_stream_impl_unittest.cc',
'renderer/media/rtc_peer_connection_handler_unittest.cc',
'renderer/media/rtc_video_decoder_unittest.cc',
'renderer/media/video_source_handler_unittest.cc',
+ 'renderer/media/webrtc_audio_capturer_unittest.cc',
'renderer/media/webrtc_audio_device_unittest.cc',
'renderer/media/webrtc_identity_service_unittest.cc',
'renderer/media/webrtc_local_audio_source_provider_unittest.cc',
@@ -694,6 +719,11 @@
'../third_party/webrtc/modules/modules.gyp:desktop_capture',
],
}],
+ ['enable_webrtc==1 and chromeos==1', {
+ 'sources': [
+ 'browser/renderer_host/media/desktop_capture_device_aura_unittest.cc',
+ ],
+ }],
# TODO(jrg): remove the OS=="android" section?
# http://crbug.com/113172
# Understand better how media_stream_ is tied into Chromium.
@@ -742,24 +772,18 @@
['use_aura==1', {
'dependencies': [
'../ui/aura/aura.gyp:aura',
- ],
- 'sources!': [
- 'browser/accessibility/browser_accessibility_win_unittest.cc',
- 'browser/renderer_host/input/tap_suppression_controller_unittest.cc',
- ],
+ ]
}],
- ['branding=="Chrome"', {
- 'sources!': [
- # These tests depend on single process mode, which is disabled in
- # official builds.
- 'renderer/dom_serializer_browsertest.cc',
- 'renderer/resource_fetcher_browsertest.cc',
- 'renderer/savable_resources_browsertest.cc',
+ ['use_aura==1 or toolkit_views==1', {
+ 'dependencies': [
+ '../ui/events/events.gyp:events_test_support',
],
}],
['OS == "android"', {
+ 'sources': [
+ 'browser/renderer_host/java/jni_helper_unittest.cc',
+ ],
'sources!': [
- 'browser/geolocation/gps_location_provider_unittest_linux.cc',
'browser/geolocation/network_location_provider_unittest.cc',
'browser/geolocation/wifi_data_provider_chromeos_unittest.cc',
'browser/geolocation/wifi_data_provider_common_unittest.cc',
@@ -776,59 +800,125 @@
'../testing/android/native_test.gyp:native_test_native_code',
],
}],
+ ['use_aura!=1 and OS!="win" and OS!="android"', {
+ 'sources!': [
+ 'browser/renderer_host/input/tap_suppression_controller_unittest.cc',
+ ],
+ }],
['enable_webrtc==1 and google_tv==1', {
'sources': [
'renderer/media/rtc_video_decoder_factory_tv_unittest.cc',
],
}],
- # TODO(bryaneyler): Also enable these for OpenSSL once that
- # implementation is ready. Issue 267888.
- ['use_nss!=1', {
+ ['use_dbus==0', {
'sources!': [
- 'renderer/webcrypto_impl_unittest.cc',
+ 'browser/geolocation/wifi_data_provider_linux_unittest.cc',
],
- }],
+ }],
],
},
],
'conditions': [
+ ['test_isolation_mode != "noop"', {
+ 'targets': [
+ {
+ 'target_name': 'content_unittests_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'content_unittests',
+ ],
+ 'includes': [
+ '../build/isolate.gypi',
+ 'content_unittests.isolate',
+ ],
+ 'sources': [
+ 'content_unittests.isolate',
+ ],
+ },
+ ],
+ }],
['OS!="ios"', {
'targets': [
{
- 'target_name': 'content_browsertests',
+ 'target_name': 'content_perftests',
'type': '<(gtest_target_type)',
'defines!': ['CONTENT_IMPLEMENTATION'],
'dependencies': [
- 'content_common',
- 'content_gpu',
- 'content_plugin',
- 'content_renderer',
+ 'content.gyp:content_common',
+ 'test_support_content',
+ '../base/base.gyp:test_support_base',
+ '../cc/cc.gyp:cc',
+ '../skia/skia.gyp:skia',
+ '../testing/gtest.gyp:gtest',
+ '../testing/perf/perf_test.gyp:*',
+ '../ui/gfx/gfx.gyp:gfx',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'common/cc_messages_perftest.cc',
+ 'test/run_all_perftests.cc',
+ ],
+ },
+ {
+ 'target_name': 'content_browser_test_support',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'content_shell_lib',
+ '../skia/skia.gyp:skia',
+ '../testing/gtest.gyp:gtest',
+ ],
+ 'sources': [
+ 'test/accessibility_browser_test_utils.cc',
+ 'test/accessibility_browser_test_utils.h',
+ 'test/content_browser_test.cc',
+ 'test/content_browser_test.h',
+ 'test/content_browser_test_utils.cc',
+ 'test/content_browser_test_utils.h',
+ 'test/content_browser_test_utils_mac.mm',
+ 'test/cpp_binding_example.cc',
+ 'test/cpp_binding_example.h',
+ ],
+ },
+ {
+ 'target_name': 'content_browsertests',
+ 'type': '<(gtest_target_type)',
+ 'dependencies': [
+ 'content.gyp:content_common',
+ 'content.gyp:content_gpu',
+ 'content.gyp:content_plugin',
+ 'content.gyp:content_renderer',
+ 'content_browser_test_support',
'content_resources.gyp:content_resources',
'content_shell_lib',
'content_shell_pak',
- 'test_support_content',
'../base/base.gyp:test_support_base',
+ '../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',
'../net/net.gyp:net_test_support',
'../ppapi/ppapi_internal.gyp:ppapi_host',
'../ppapi/ppapi_internal.gyp:ppapi_ipc',
'../ppapi/ppapi_internal.gyp:ppapi_proxy',
'../ppapi/ppapi_internal.gyp:ppapi_shared',
'../ppapi/ppapi_internal.gyp:ppapi_unittest_shared',
- '../skia/skia.gyp:skia',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
+ '../third_party/WebKit/public/blink.gyp:blink',
'../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
'../third_party/mesa/mesa.gyp:osmesa',
+ '../ui/gfx/gfx.gyp:gfx',
'../ui/gl/gl.gyp:gl',
+ '../ui/resources/ui_resources.gyp:ui_resources',
+ '../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
'../ui/snapshot/snapshot.gyp:snapshot',
- '../ui/ui.gyp:shell_dialogs',
'../ui/ui.gyp:ui',
- '../ui/ui.gyp:ui_resources',
+ '../webkit/child/webkit_child.gyp:webkit_child',
+ '../webkit/glue/webkit_glue.gyp:glue',
'../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
- '../webkit/support/webkit_support.gyp:glue',
- '../webkit/support/webkit_support.gyp:glue_child',
],
'include_dirs': [
'..',
@@ -844,6 +934,7 @@
'browser/accessibility/accessibility_win_browsertest.cc',
'browser/accessibility/cross_platform_accessibility_browsertest.cc',
'browser/accessibility/dump_accessibility_tree_browsertest.cc',
+ 'browser/aura/image_transport_factory_browsertest.cc',
'browser/bookmarklet_browsertest.cc',
'browser/browser_plugin/browser_plugin_host_browsertest.cc',
'browser/browser_plugin/test_browser_plugin_embedder.cc',
@@ -856,22 +947,17 @@
'browser/browser_plugin/test_browser_plugin_guest_manager.h',
'browser/child_process_security_policy_browsertest.cc',
'browser/database_browsertest.cc',
- 'browser/device_orientation/device_orientation_browsertest.cc',
+ 'browser/device_orientation/device_inertial_sensor_browsertest.cc',
+ 'browser/devtools/renderer_overrides_handler_browsertest.cc',
'browser/dom_storage/dom_storage_browsertest.cc',
'browser/download/download_browsertest.cc',
'browser/download/drag_download_file_browsertest.cc',
'browser/download/mhtml_generation_browsertest.cc',
'browser/download/save_package_browsertest.cc',
'browser/fileapi/file_system_browsertest.cc',
+ 'browser/frame_host/render_frame_host_manager_browsertest.cc',
'browser/gpu/compositor_util_browsertest.cc',
- 'browser/gpu/gpu_crash_browsertest.cc',
- 'browser/gpu/gpu_functional_browsertest.cc',
- 'browser/gpu/gpu_info_browsertest.cc',
'browser/gpu/gpu_ipc_browsertests.cc',
- 'browser/gpu/gpu_memory_test.cc',
- 'browser/gpu/gpu_pixel_browsertest.cc',
- 'browser/gpu/webgl_conformance_test.cc',
- 'browser/gpu/webgl_conformance_test_list_autogen.h',
'browser/indexed_db/indexed_db_browsertest.cc',
'browser/loader/resource_dispatcher_host_browsertest.cc',
'browser/media/encrypted_media_browsertest.cc',
@@ -882,16 +968,16 @@
'browser/plugin_data_remover_impl_browsertest.cc',
'browser/plugin_browsertest.cc',
'browser/plugin_service_impl_browsertest.cc',
+ 'browser/renderer_host/input/touch_input_browsertest.cc',
'browser/renderer_host/render_process_host_browsertest.cc',
'browser/renderer_host/render_view_host_browsertest.cc',
- 'browser/renderer_host/render_view_host_manager_browsertest.cc',
'browser/renderer_host/render_widget_host_browsertest.cc',
'browser/renderer_host/render_widget_host_view_browsertest.cc',
- 'browser/renderer_host/render_widget_host_view_win_browsertest.cc',
'browser/security_exploit_browsertest.cc',
'browser/session_history_browsertest.cc',
'browser/site_per_process_browsertest.cc',
'browser/speech/input_tag_speech_browsertest.cc',
+ 'browser/speech/speech_recognition_browsertest.cc',
'browser/tracing/tracing_controller_browsertest.cc',
'browser/web_contents/touch_editable_impl_aura_browsertest.cc',
'browser/web_contents/web_contents_impl_browsertest.cc',
@@ -909,7 +995,9 @@
'renderer/browser_plugin/mock_browser_plugin_manager.h',
'renderer/cpp_bound_class_unittest.cc',
'renderer/dom_serializer_browsertest.cc',
+ 'renderer/gin_browsertest.cc',
'renderer/mouse_lock_dispatcher_browsertest.cc',
+ 'renderer/pepper/fake_pepper_plugin_instance.cc',
'renderer/pepper/mock_renderer_ppapi_host.cc',
'renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc',
'renderer/pepper/pepper_file_chooser_host_unittest.cc',
@@ -921,17 +1009,8 @@
'renderer/render_widget_browsertest.cc',
'renderer/resource_fetcher_browsertest.cc',
'renderer/savable_resources_browsertest.cc',
- 'test/accessibility_browser_test_utils.cc',
- 'test/accessibility_browser_test_utils.h',
- 'test/content_browser_test.h',
- 'test/content_browser_test.cc',
- 'test/content_browser_test_utils.cc',
- 'test/content_browser_test_utils.h',
- 'test/content_browser_test_utils_mac.mm',
'test/content_browser_test_test.cc',
'test/content_test_launcher.cc',
- 'test/cpp_binding_example.cc',
- 'test/cpp_binding_example.h',
'test/webui_resource_browsertest.cc',
],
'conditions': [
@@ -977,7 +1056,6 @@
}, { # OS!="win"
'sources!': [
'browser/accessibility/accessibility_win_browsertest.cc',
- 'browser/renderer_host/render_widget_host_view_win_browsertest.cc',
],
}],
['OS=="win" and win_use_allocator_shim==1', {
@@ -1011,9 +1089,20 @@
['use_aura==1', {
'sources!': [
'browser/accessibility/accessibility_win_browsertest.cc',
- 'browser/accessibility/dump_accessibility_tree_browsertest.cc',
+ ],
+ }, {
+ 'sources/': [
+ ['exclude', '^browser/aura/'],
+ ],
+ }],
+ ['use_aura==1 and OS!="win"', {
+ 'sources!': [
'browser/plugin_browsertest.cc',
- 'browser/renderer_host/render_widget_host_view_win_browsertest.cc',
+ ],
+ }],
+ ['use_aura==1 or toolkit_views==1', {
+ 'dependencies': [
+ '../ui/events/events.gyp:events_test_support',
],
}],
['OS!="android" and OS!="ios"', {
@@ -1027,6 +1116,9 @@
'sources': [
'browser/media/webrtc_browsertest.cc',
],
+ 'dependencies': [
+ '../testing/perf/perf_test.gyp:perf_test',
+ ],
}],
['enable_plugins==0', {
'sources/': [
@@ -1042,25 +1134,34 @@
['exclude', '^browser/speech/'],
]
}],
+ ['branding=="Chrome"', {
+ 'sources!': [
+ # These tests depend on single process mode, which is disabled
+ # in official builds.
+ 'renderer/dom_serializer_browsertest.cc',
+ 'renderer/resource_fetcher_browsertest.cc',
+ 'renderer/savable_resources_browsertest.cc',
+ ],
+ }],
],
},
{
'target_name': 'content_gl_tests',
'type': '<(gtest_target_type)',
- 'defines!': ['CONTENT_IMPLEMENTATION'],
'dependencies': [
- 'content_common',
+ 'content.gyp:content_common',
'test_support_content',
'../base/base.gyp:test_support_base',
'../gpu/gpu.gyp:command_buffer_common',
'../testing/gtest.gyp:gtest',
- '../ui/ui.gyp:ui',
+ '../ui/gfx/gfx.gyp:gfx',
'../ui/gl/gl.gyp:gl',
+ '../ui/ui.gyp:ui',
'../third_party/WebKit/public/blink.gyp:blink',
# The following two dependencies provide the missing
# symbol HeapProfilerStart in Linux component builds.
- '../webkit/support/webkit_support.gyp:glue',
- '../webkit/support/webkit_support.gyp:glue_child',
+ '../webkit/child/webkit_child.gyp:webkit_child',
+ '../webkit/glue/webkit_glue.gyp:glue',
],
'include_dirs': [
'..',
@@ -1080,19 +1181,19 @@
{
'target_name': 'content_gl_benchmark',
'type': '<(gtest_target_type)',
- 'defines!': ['CONTENT_IMPLEMENTATION'],
'dependencies': [
- 'content_common',
+ 'content.gyp:content_common',
'test_support_content',
'../base/base.gyp:test_support_base',
'../testing/gtest.gyp:gtest',
- '../ui/ui.gyp:ui',
+ '../ui/gfx/gfx.gyp:gfx',
'../ui/gl/gl.gyp:gl',
+ '../ui/ui.gyp:ui',
'../third_party/WebKit/public/blink.gyp:blink',
# The following two dependencies provide the missing
# symbol HeapProfilerStart in Linux component builds.
- '../webkit/support/webkit_support.gyp:glue',
- '../webkit/support/webkit_support.gyp:glue_child',
+ '../webkit/glue/webkit_glue.gyp:glue',
+ '../webkit/child/webkit_child.gyp:webkit_child',
],
'include_dirs': [
'..',
@@ -1123,11 +1224,12 @@
'target_name': 'video_decode_accelerator_unittest',
'type': '<(gtest_target_type)',
'dependencies': [
- 'content',
+ 'content.gyp:content',
'../base/base.gyp:base',
'../testing/gtest.gyp:gtest',
'../media/media.gyp:media',
'../ui/gl/gl.gyp:gl',
+ '../ui/gfx/gfx.gyp:gfx',
'../ui/ui.gyp:ui',
],
'include_dirs': [
@@ -1136,7 +1238,7 @@
'sources': [
'common/gpu/media/android_video_decode_accelerator_unittest.cc',
'common/gpu/media/rendering_helper.h',
- 'common/gpu/media/rendering_helper_gl.cc',
+ 'common/gpu/media/rendering_helper.cc',
'common/gpu/media/video_accelerator_unittest_helpers.h',
'common/gpu/media/video_decode_accelerator_unittest.cc',
],
@@ -1144,7 +1246,7 @@
['OS=="android"', {
'sources/': [
['exclude', '^common/gpu/media/rendering_helper.h'],
- ['exclude', '^common/gpu/media/rendering_helper_gl.cc'],
+ ['exclude', '^common/gpu/media/rendering_helper.cc'],
['exclude', '^common/gpu/media/video_decode_accelerator_unittest.cc'],
],
'dependencies': [
@@ -1160,8 +1262,8 @@
}],
['OS=="win"', {
'dependencies': [
- '../third_party/angle_dx11/src/build_angle.gyp:libEGL',
- '../third_party/angle_dx11/src/build_angle.gyp:libGLESv2',
+ '<(angle_path)/src/build_angle.gyp:libEGL',
+ '<(angle_path)/src/build_angle.gyp:libGLESv2',
],
}],
['(OS=="win" and win_use_allocator_shim==1) or '
@@ -1188,11 +1290,12 @@
'target_name': 'video_encode_accelerator_unittest',
'type': 'executable',
'dependencies': [
- 'content',
+ 'content.gyp:content',
'../base/base.gyp:base',
'../testing/gtest.gyp:gtest',
'../media/media.gyp:media',
'../ui/gl/gl.gyp:gl',
+ '../ui/gfx/gfx.gyp:gfx',
'../ui/ui.gyp:ui',
],
'sources': [
@@ -1208,7 +1311,7 @@
'target_name': 'h264_parser_unittest',
'type': 'executable',
'dependencies': [
- 'content_common',
+ 'content.gyp:content_common',
'../base/base.gyp:base',
'../testing/gtest.gyp:gtest',
],
@@ -1250,7 +1353,7 @@
'target_name': 'content_unittests_apk',
'type': 'none',
'dependencies': [
- 'content_java',
+ 'content.gyp:content_java',
'content_unittests',
],
'variables': {
@@ -1263,8 +1366,8 @@
'target_name': 'content_browsertests_apk',
'type': 'none',
'dependencies': [
+ 'content.gyp:content_java',
'content_browsertests',
- 'content_java',
'content_java_test_support',
'content_shell_java',
],
@@ -1274,11 +1377,63 @@
'resource_dir': 'shell/android/browsertests_apk/res',
'native_lib_target': 'libcontent_browsertests',
'additional_input_paths': ['<(PRODUCT_DIR)/content_shell/assets/content_shell.pak'],
- 'asset_location': '<(ant_build_out)/content_shell/assets',
+ 'asset_location': '<(PRODUCT_DIR)/content_shell/assets',
},
'includes': [ '../build/java_apk.gypi' ],
},
{
+ 'target_name': 'content_linker_test_apk',
+ 'type': 'none',
+ 'dependencies': [
+ 'content_android_linker_test',
+ 'content.gyp:content_java',
+ 'content_shell_java',
+ ],
+ 'variables': {
+ 'apk_name': 'ContentLinkerTest',
+ 'java_in_dir': 'shell/android/linker_test_apk',
+ 'resource_dir': 'shell/android/linker_test_apk/res',
+ 'native_lib_target': 'libcontent_android_linker_test',
+ 'additional_input_paths': ['<(PRODUCT_DIR)/content_shell/assets/content_shell.pak'],
+ 'asset_location': '<(PRODUCT_DIR)/content_shell/assets',
+ 'use_content_linker': '1',
+ 'enable_content_linker_tests': '1',
+ },
+ 'includes': [ '../build/java_apk.gypi' ],
+ },
+ {
+ 'target_name': 'content_android_linker_test',
+ 'type': 'shared_library',
+ 'defines!': ['CONTENT_IMPLEMENTATION'],
+ 'dependencies': [
+ 'content_android_linker_test_jni_headers',
+ 'content_shell_lib',
+ # Required to include "content/public/browser/android/compositor.h"
+ # in content_linker_test_android.cc :-(
+ '../skia/skia.gyp:skia',
+ ],
+ 'sources': [
+ 'shell/android/linker_test_apk/content_linker_test_android.cc',
+ 'shell/android/linker_test_apk/content_linker_test_linker_tests.cc',
+ ],
+ },
+ {
+ 'target_name': 'content_android_linker_test_jni_headers',
+ 'type': 'none',
+ 'sources': [
+ 'shell/android/linker_test_apk/src/org/chromium/content_linker_test_apk/LinkerTests.java',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)/content/shell',
+ ],
+ },
+ 'variables': {
+ 'jni_gen_package': 'content/shell',
+ },
+ 'includes': [ '../build/jni_generator.gypi' ],
+ },
+ {
'target_name': 'video_decode_accelerator_unittest_apk',
'type': 'none',
'dependencies': [
@@ -1316,8 +1471,8 @@
'dependencies': [
'../base/base.gyp:base',
'../base/base.gyp:base_java_test_support',
- 'content_common',
- 'content_java',
+ 'content.gyp:content_common',
+ 'content.gyp:content_java',
],
'variables': {
'java_in_dir': '../content/public/test/android/javatests',
@@ -1328,9 +1483,9 @@
'target_name': 'content_shell_test_apk',
'type': 'none',
'dependencies': [
- 'content_java',
'content_java_test_support',
'content_shell_apk_java',
+ 'content.gyp:content_java',
'../base/base.gyp:base_java',
'../base/base.gyp:base_javatests',
'../base/base.gyp:base_java_test_support',
diff --git a/chromium/content/content_unittests.isolate b/chromium/content/content_unittests.isolate
index b39101c737f..3a2e6f348fc 100644
--- a/chromium/content/content_unittests.isolate
+++ b/chromium/content/content_unittests.isolate
@@ -12,60 +12,65 @@
],
},
}],
- ['OS=="android" or OS=="mac"', {
+ ['OS=="android" or OS=="mac" or OS=="win"', {
'variables': {
'isolate_dependency_tracked': [
'<(PRODUCT_DIR)/content_resources.pak',
],
},
}],
- ['OS=="linux"', {
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
'variables': {
- 'command': [
- '../testing/xvfb.py',
- '<(PRODUCT_DIR)',
- '../tools/swarm_client/googletest/run_test_cases.py',
- '<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
- ],
'isolate_dependency_tracked': [
- '<(PRODUCT_DIR)/libffmpegsumo.so',
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
],
'isolate_dependency_untracked': [
- '<(PRODUCT_DIR)/test_data/',
+ '../tools/swarming_client/',
],
},
}],
- ['OS=="linux" or OS=="mac" or OS=="win"', {
+ ['OS=="linux"', {
'variables': {
- 'isolate_dependency_tracked': [
+ 'command': [
+ '../testing/xvfb.py',
+ '<(PRODUCT_DIR)',
'<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
+ '--brave-new-test-launcher',
+ '--test-launcher-bot-mode',
],
- 'isolate_dependency_untracked': [
- '../tools/swarm_client/',
+ 'isolate_dependency_tracked': [
+ '../testing/xvfb.py',
+ '<(PRODUCT_DIR)/libffmpegsumo.so',
+ '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)',
],
},
}],
['OS=="mac"', {
'variables': {
+ 'command': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
+ '--brave-new-test-launcher',
+ '--test-launcher-bot-mode',
+ ],
'isolate_dependency_tracked': [
'<(PRODUCT_DIR)/ffmpegsumo.so',
],
},
}],
- ['OS=="mac" or OS=="win"', {
+ ['OS=="win"', {
'variables': {
'command': [
'../testing/test_env.py',
- '../tools/swarm_client/googletest/run_test_cases.py',
'<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
+ '--brave-new-test-launcher',
+ '--test-launcher-bot-mode',
],
- },
- }],
- ['OS=="win"', {
- 'variables': {
'isolate_dependency_tracked': [
'<(PRODUCT_DIR)/ffmpegsumo.dll',
'<(PRODUCT_DIR)/icudt.dll',
+ '<(PRODUCT_DIR)/ui_test.pak',
],
},
}],
diff --git a/chromium/content/content_worker.gypi b/chromium/content/content_worker.gypi
index 827ca531438..4ee159969a4 100644
--- a/chromium/content/content_worker.gypi
+++ b/chromium/content/content_worker.gypi
@@ -16,6 +16,8 @@
'worker/websharedworkerclient_proxy.cc',
'worker/websharedworkerclient_proxy.h',
'worker/worker_main.cc',
+ 'worker/shared_worker_permission_client_proxy.cc',
+ 'worker/shared_worker_permission_client_proxy.h',
'worker/worker_thread.cc',
'worker/worker_thread.h',
'worker/worker_webapplicationcachehost_impl.cc',
diff --git a/chromium/content/gpu/OWNERS b/chromium/content/gpu/OWNERS
index cc057367ceb..e8d07a9e149 100644
--- a/chromium/content/gpu/OWNERS
+++ b/chromium/content/gpu/OWNERS
@@ -1,3 +1,2 @@
-apatrick@chromium.org
kbr@chromium.org
piman@chromium.org
diff --git a/chromium/content/gpu/gpu_main.cc b/chromium/content/gpu/gpu_main.cc
index 9e29e03e2c1..80715ec39de 100644
--- a/chromium/content/gpu/gpu_main.cc
+++ b/chromium/content/gpu/gpu_main.cc
@@ -12,6 +12,7 @@
#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
@@ -21,7 +22,7 @@
#include "content/common/content_constants_internal.h"
#include "content/common/gpu/gpu_config.h"
#include "content/common/gpu/gpu_messages.h"
-#include "content/common/sandbox_linux.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/gpu/gpu_child_thread.h"
#include "content/gpu/gpu_process.h"
#include "content/gpu/gpu_watchdog_thread.h"
@@ -29,7 +30,9 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
#include "crypto/hmac.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/gpu_info_collector.h"
+#include "gpu/config/gpu_util.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_switches.h"
@@ -38,12 +41,7 @@
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#include "base/win/scoped_com_initializer.h"
-#include "content/common/gpu/media/dxva_video_decode_accelerator.h"
#include "sandbox/win/src/sandbox.h"
-#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
-#include "content/common/gpu/media/exynos_video_decode_accelerator.h"
-#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
-#include "content/common/gpu/media/vaapi_wrapper.h"
#endif
#if defined(USE_X11)
@@ -97,31 +95,27 @@ int GpuMain(const MainFunctionParams& parameters) {
base::Time start_time = base::Time::Now();
- bool in_browser_process = command_line.HasSwitch(switches::kSingleProcess) ||
- command_line.HasSwitch(switches::kInProcessGPU);
-
- if (!in_browser_process) {
#if defined(OS_WIN)
- // Prevent Windows from displaying a modal dialog on failures like not being
- // able to load a DLL.
- SetErrorMode(
- SEM_FAILCRITICALERRORS |
- SEM_NOGPFAULTERRORBOX |
- SEM_NOOPENFILEERRORBOX);
+ // Prevent Windows from displaying a modal dialog on failures like not being
+ // able to load a DLL.
+ SetErrorMode(
+ SEM_FAILCRITICALERRORS |
+ SEM_NOGPFAULTERRORBOX |
+ SEM_NOOPENFILEERRORBOX);
#elif defined(USE_X11)
- ui::SetDefaultX11ErrorHandlers();
+ ui::SetDefaultX11ErrorHandlers();
#endif
- logging::SetLogMessageHandler(GpuProcessLogMessageHandler);
- }
+ logging::SetLogMessageHandler(GpuProcessLogMessageHandler);
- if (command_line.HasSwitch(switches::kSupportsDualGpus) &&
- command_line.HasSwitch(switches::kGpuSwitching)) {
- std::string option = command_line.GetSwitchValueASCII(
- switches::kGpuSwitching);
- if (option == switches::kGpuSwitchingOptionNameForceDiscrete)
+ if (command_line.HasSwitch(switches::kSupportsDualGpus)) {
+ std::string types = command_line.GetSwitchValueASCII(
+ switches::kGpuDriverBugWorkarounds);
+ std::set<int> workarounds;
+ gpu::StringToFeatureSet(types, &workarounds);
+ if (workarounds.count(gpu::FORCE_DISCRETE_GPU) == 1)
ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu();
- else if (option == switches::kGpuSwitchingOptionNameForceIntegrated)
+ else if (workarounds.count(gpu::FORCE_INTEGRATED_GPU) == 1)
ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
}
@@ -191,13 +185,13 @@ int GpuMain(const MainFunctionParams& parameters) {
DCHECK(command_line.HasSwitch(switches::kGpuVendorID) &&
command_line.HasSwitch(switches::kGpuDeviceID) &&
command_line.HasSwitch(switches::kGpuDriverVersion));
- bool success = base::HexStringToInt(
+ bool success = base::HexStringToUInt(
command_line.GetSwitchValueASCII(switches::kGpuVendorID),
- reinterpret_cast<int*>(&(gpu_info.gpu.vendor_id)));
+ &gpu_info.gpu.vendor_id);
DCHECK(success);
- success = base::HexStringToInt(
+ success = base::HexStringToUInt(
command_line.GetSwitchValueASCII(switches::kGpuDeviceID),
- reinterpret_cast<int*>(&(gpu_info.gpu.device_id)));
+ &gpu_info.gpu.device_id);
DCHECK(success);
gpu_info.driver_vendor =
command_line.GetSwitchValueASCII(switches::kGpuDriverVendor);
@@ -205,6 +199,9 @@ int GpuMain(const MainFunctionParams& parameters) {
command_line.GetSwitchValueASCII(switches::kGpuDriverVersion);
GetContentClient()->SetGpuInfo(gpu_info);
+ base::TimeDelta collect_context_time;
+ base::TimeDelta initialize_one_off_time;
+
// Warm up resources that don't need access to GPUInfo.
if (WarmUpSandbox(command_line)) {
#if defined(OS_LINUX)
@@ -220,6 +217,8 @@ int GpuMain(const MainFunctionParams& parameters) {
#endif
#endif // defined(OS_LINUX)
+ base::TimeTicks before_initialize_one_off = base::TimeTicks::Now();
+
// Load and initialize the GL implementation and locate the GL entry points.
if (gfx::GLSurface::InitializeOneOff()) {
// We need to collect GL strings (VENDOR, RENDERER) for blacklisting
@@ -230,11 +229,22 @@ int GpuMain(const MainFunctionParams& parameters) {
// By skipping the following code on Mac, we don't really lose anything,
// because the basic GPU information is passed down from browser process
// and we already registered them through SetGpuInfo() above.
+ base::TimeTicks before_collect_context_graphics_info =
+ base::TimeTicks::Now();
#if !defined(OS_MACOSX)
if (!gpu::CollectContextGraphicsInfo(&gpu_info))
VLOG(1) << "gpu::CollectGraphicsInfo failed";
GetContentClient()->SetGpuInfo(gpu_info);
+#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+ // Recompute gpu driver bug workarounds - this is specifically useful
+ // on systems where vendor_id/device_id aren't available.
+ if (!command_line.HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
+ gpu::ApplyGpuDriverBugWorkarounds(
+ gpu_info, const_cast<CommandLine*>(&command_line));
+ }
+#endif
+
#if defined(OS_LINUX)
initialized_gl_context = true;
#if !defined(OS_CHROMEOS)
@@ -249,11 +259,16 @@ int GpuMain(const MainFunctionParams& parameters) {
#endif // !defined(OS_CHROMEOS)
#endif // defined(OS_LINUX)
#endif // !defined(OS_MACOSX)
+ collect_context_time =
+ base::TimeTicks::Now() - before_collect_context_graphics_info;
} else {
VLOG(1) << "gfx::GLSurface::InitializeOneOff failed";
dead_on_arrival = true;
}
+ initialize_one_off_time =
+ base::TimeTicks::Now() - before_initialize_one_off;
+
if (enable_watchdog && delayed_watchdog_enable) {
watchdog_thread = new GpuWatchdogThread(kGpuTimeout);
watchdog_thread->Start();
@@ -286,6 +301,11 @@ int GpuMain(const MainFunctionParams& parameters) {
GpuProcess gpu_process;
+ // These UMA must be stored after GpuProcess is constructed as it
+ // initializes StatisticsRecorder which tracks the histograms.
+ UMA_HISTOGRAM_TIMES("GPU.CollectContextGraphicsInfo", collect_context_time);
+ UMA_HISTOGRAM_TIMES("GPU.InitializeOneOffTime", initialize_one_off_time);
+
GpuChildThread* child_thread = new GpuChildThread(watchdog_thread.get(),
dead_on_arrival,
gpu_info,
@@ -358,47 +378,6 @@ bool WarmUpSandbox(const CommandLine& command_line) {
}
}
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
- ExynosVideoDecodeAccelerator::PreSandboxInitialization();
-#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
- VaapiWrapper::PreSandboxInitialization();
-#endif
-
-#if defined(OS_WIN)
- {
- TRACE_EVENT0("gpu", "Preload setupapi.dll");
- // Preload this DLL because the sandbox prevents it from loading.
- if (LoadLibrary(L"setupapi.dll") == NULL) {
- LOG(ERROR) << "WarmUpSandbox() failed with loading setupapi.dll";
- return false;
- }
- }
-
- if (!command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
- TRACE_EVENT0("gpu", "Initialize DXVA");
- // Initialize H/W video decoding stuff which fails in the sandbox.
- DXVAVideoDecodeAccelerator::PreSandboxInitialization();
- }
-
- {
- TRACE_EVENT0("gpu", "Warm up DWM");
-
- // DWM was introduced with Windows Vista. DwmFlush seems to be sufficient
- // to warm it up before lowering the token. DWM is required to present to
- // a window with Vista and later and this allows us to do so with the
- // GPU process sandbox enabled.
- if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
- HMODULE module = LoadLibrary(L"dwmapi.dll");
- if (module) {
- typedef HRESULT (WINAPI *DwmFlushFunc)();
- DwmFlushFunc dwm_flush = reinterpret_cast<DwmFlushFunc>(
- GetProcAddress(module, "DwmFlush"));
- if (dwm_flush)
- dwm_flush();
- }
- }
- }
-#endif
return true;
}
@@ -424,13 +403,17 @@ bool StartSandboxLinux(const gpu::GPUInfo& gpu_info,
WarmUpSandboxNvidia(gpu_info, should_initialize_gl_context);
- if (watchdog_thread)
- watchdog_thread->Stop();
+ if (watchdog_thread) {
+ // LinuxSandbox needs to be able to ensure that the thread
+ // has really been stopped.
+ LinuxSandbox::StopThread(watchdog_thread);
+ }
// LinuxSandbox::InitializeSandbox() must always be called
// with only one thread.
res = LinuxSandbox::InitializeSandbox();
- if (watchdog_thread)
+ if (watchdog_thread) {
watchdog_thread->Start();
+ }
return res;
}
diff --git a/chromium/content/gpu/gpu_watchdog_thread.cc b/chromium/content/gpu/gpu_watchdog_thread.cc
index 17889b7bd2f..940d07e72ac 100644
--- a/chromium/content/gpu/gpu_watchdog_thread.cc
+++ b/chromium/content/gpu/gpu_watchdog_thread.cc
@@ -12,6 +12,7 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
+#include "base/file_util.h"
#include "base/power_monitor/power_monitor.h"
#include "base/process/process.h"
#include "build/build_config.h"
@@ -21,6 +22,10 @@
namespace content {
namespace {
const int64 kCheckPeriodMs = 2000;
+#if defined(OS_CHROMEOS)
+const base::FilePath::CharType
+ kTtyFilePath[] = FILE_PATH_LITERAL("/sys/class/tty/tty0/active");
+#endif
} // namespace
GpuWatchdogThread::GpuWatchdogThread(int timeout)
@@ -51,6 +56,9 @@ GpuWatchdogThread::GpuWatchdogThread(int timeout)
DCHECK(result);
#endif
+#if defined(OS_CHROMEOS)
+ tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r");
+#endif
watched_message_loop_->AddTaskObserver(&task_observer_);
}
@@ -110,6 +118,11 @@ GpuWatchdogThread::~GpuWatchdogThread() {
if (power_monitor)
power_monitor->RemoveObserver(this);
+#if defined(OS_CHROMEOS)
+ if (tty_file_)
+ fclose(tty_file_);
+#endif
+
watched_message_loop_->RemoveTaskObserver(&task_observer_);
}
@@ -223,6 +236,20 @@ 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;
+ }
+#endif
+
LOG(ERROR) << "The GPU process hung. Terminating after "
<< timeout_.InMilliseconds() << " ms.";
diff --git a/chromium/content/gpu/gpu_watchdog_thread.h b/chromium/content/gpu/gpu_watchdog_thread.h
index 8731e41b436..db7978baa57 100644
--- a/chromium/content/gpu/gpu_watchdog_thread.h
+++ b/chromium/content/gpu/gpu_watchdog_thread.h
@@ -92,6 +92,10 @@ class GpuWatchdogThread : public base::Thread,
bool suspended_;
+#if defined(OS_CHROMEOS)
+ FILE* tty_file_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(GpuWatchdogThread);
};
diff --git a/chromium/content/plugin/plugin_channel.cc b/chromium/content/plugin/plugin_channel.cc
index 3340ea8df13..1ba88781856 100644
--- a/chromium/content/plugin/plugin_channel.cc
+++ b/chromium/content/plugin/plugin_channel.cc
@@ -13,6 +13,7 @@
#include "build/build_config.h"
#include "content/child/child_process.h"
#include "content/child/npapi/plugin_instance.h"
+#include "content/child/npapi/webplugin_delegate_impl.h"
#include "content/child/plugin_messages.h"
#include "content/common/plugin_process_messages.h"
#include "content/plugin/plugin_thread.h"
@@ -22,20 +23,15 @@
#include "third_party/WebKit/public/web/WebBindings.h"
#if defined(OS_POSIX)
-#include "base/posix/eintr_wrapper.h"
#include "ipc/ipc_channel_posix.h"
#endif
-using WebKit::WebBindings;
+using blink::WebBindings;
namespace content {
namespace {
-void PluginReleaseCallback() {
- ChildProcess::current()->ReleaseProcess();
-}
-
// How long we wait before releasing the plugin process.
const int kPluginReleaseTimeMinutes = 5;
@@ -206,9 +202,7 @@ base::WaitableEvent* PluginChannel::GetModalDialogEvent(int render_view_id) {
PluginChannel::~PluginChannel() {
PluginThread::current()->Send(new PluginProcessHostMsg_ChannelDestroyed(
renderer_id_));
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&PluginReleaseCallback),
+ process_ref_.ReleaseWithDelay(
base::TimeDelta::FromMinutes(kPluginReleaseTimeMinutes));
}
@@ -225,7 +219,12 @@ void PluginChannel::CleanUp() {
// called twice.
scoped_refptr<PluginChannel> me(this);
- plugin_stubs_.clear();
+ while (!plugin_stubs_.empty()) {
+ // Separate vector::erase and ~WebPluginDelegateStub.
+ // See https://code.google.com/p/chromium/issues/detail?id=314088
+ scoped_refptr<WebPluginDelegateStub> stub = plugin_stubs_[0];
+ plugin_stubs_.erase(plugin_stubs_.begin());
+ }
}
bool PluginChannel::Init(base::MessageLoopProxy* ipc_message_loop,
@@ -245,7 +244,6 @@ PluginChannel::PluginChannel()
filter_(new MessageFilter()),
npp_(new struct _NPP) {
set_send_unblocking_only_during_unblock_dispatch();
- ChildProcess::current()->AddRefProcess();
const CommandLine* command_line = CommandLine::ForCurrentProcess();
log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
@@ -263,6 +261,7 @@ bool PluginChannel::OnControlMessageReceived(const IPC::Message& msg) {
OnDestroyInstance)
IPC_MESSAGE_HANDLER(PluginMsg_GenerateRouteID, OnGenerateRouteID)
IPC_MESSAGE_HANDLER(PluginProcessMsg_ClearSiteData, OnClearSiteData)
+ IPC_MESSAGE_HANDLER(PluginHostMsg_DidAbortLoading, OnDidAbortLoading)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
DCHECK(handled);
@@ -285,7 +284,12 @@ void PluginChannel::OnDestroyInstance(int instance_id,
scoped_refptr<MessageFilter> filter(filter_);
int render_view_id =
plugin_stubs_[i]->webplugin()->host_render_view_routing_id();
+ // Separate vector::erase and ~WebPluginDelegateStub.
+ // See https://code.google.com/p/chromium/issues/detail?id=314088
+ scoped_refptr<WebPluginDelegateStub> stub = plugin_stubs_[i];
plugin_stubs_.erase(plugin_stubs_.begin() + i);
+ stub = NULL;
+
Send(reply_msg);
RemoveRoute(instance_id);
// NOTE: *this* might be deleted as a result of calling RemoveRoute.
@@ -331,4 +335,13 @@ void PluginChannel::OnClearSiteData(const std::string& site,
Send(new PluginProcessHostMsg_ClearSiteDataResult(success));
}
+void PluginChannel::OnDidAbortLoading(int render_view_id) {
+ for (size_t i = 0; i < plugin_stubs_.size(); ++i) {
+ if (plugin_stubs_[i]->webplugin()->host_render_view_routing_id() ==
+ render_view_id) {
+ plugin_stubs_[i]->delegate()->instance()->CloseStreams();
+ }
+ }
+}
+
} // namespace content
diff --git a/chromium/content/plugin/plugin_channel.h b/chromium/content/plugin/plugin_channel.h
index 8af63b9e029..75359449ff1 100644
--- a/chromium/content/plugin/plugin_channel.h
+++ b/chromium/content/plugin/plugin_channel.h
@@ -11,6 +11,7 @@
#include "base/process/process.h"
#include "build/build_config.h"
#include "content/child/npapi/np_channel_base.h"
+#include "content/child/scoped_child_process_reference.h"
#include "content/plugin/webplugin_delegate_stub.h"
namespace base {
@@ -81,9 +82,12 @@ class PluginChannel : public NPChannelBase {
void OnClearSiteData(const std::string& site,
uint64 flags,
uint64 max_age);
+ void OnDidAbortLoading(int render_view_id);
std::vector<scoped_refptr<WebPluginDelegateStub> > plugin_stubs_;
+ ScopedChildProcessReference process_ref_;
+
// The id of the renderer who is on the other side of the channel.
int renderer_id_;
diff --git a/chromium/content/plugin/plugin_main_mac.mm b/chromium/content/plugin/plugin_main_mac.mm
index df4d701f4ea..91deed83dab 100644
--- a/chromium/content/plugin/plugin_main_mac.mm
+++ b/chromium/content/plugin/plugin_main_mac.mm
@@ -19,7 +19,7 @@ void TrimInterposeEnvironment() {
std::string interpose_list;
if (!env->GetVar(kDYLDInsertLibrariesKey, &interpose_list)) {
- LOG(INFO) << "No Carbon Interpose library found.";
+ VLOG(0) << "No Carbon Interpose library found.";
return;
}
diff --git a/chromium/content/plugin/plugin_thread.cc b/chromium/content/plugin/plugin_thread.cc
index e6b477fd64b..72fd3cb9134 100644
--- a/chromium/content/plugin/plugin_thread.cc
+++ b/chromium/content/plugin/plugin_thread.cc
@@ -28,7 +28,6 @@
#include "content/public/common/content_switches.h"
#include "content/public/plugin/content_plugin_client.h"
#include "ipc/ipc_channel_handle.h"
-#include "webkit/glue/webkit_glue.h"
#if defined(TOOLKIT_GTK)
#include "ui/gfx/gtk_util.h"
@@ -124,7 +123,7 @@ PluginThread::PluginThread()
}
GetContentClient()->plugin()->PluginProcessStarted(
- plugin.get() ? plugin->plugin_info().name : string16());
+ plugin.get() ? plugin->plugin_info().name : base::string16());
// Certain plugins, such as flash, steal the unhandled exception filter
// thus we never get crash reports when they fault. This call fixes it.
diff --git a/chromium/content/plugin/webplugin_delegate_stub.cc b/chromium/content/plugin/webplugin_delegate_stub.cc
index ff0342a51c0..fd4827d320b 100644
--- a/chromium/content/plugin/webplugin_delegate_stub.cc
+++ b/chromium/content/plugin/webplugin_delegate_stub.cc
@@ -20,14 +20,14 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "skia/ext/platform_device.h"
+#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/WebKit/public/web/WebCursorInfo.h"
#include "third_party/npapi/bindings/npapi.h"
#include "third_party/npapi/bindings/npruntime.h"
#include "webkit/common/cursors/webcursor.h"
-using WebKit::WebBindings;
-using WebKit::WebCursorInfo;
+using blink::WebBindings;
+using blink::WebCursorInfo;
namespace content {
@@ -87,7 +87,8 @@ WebPluginDelegateStub::~WebPluginDelegateStub() {
}
// Remove the NPObject owner mapping for this instance.
- channel_->RemoveMappingForNPObjectOwner(instance_id_);
+ if (delegate_)
+ channel_->RemoveMappingForNPObjectOwner(instance_id_);
}
bool WebPluginDelegateStub::OnMessageReceived(const IPC::Message& msg) {
@@ -272,7 +273,7 @@ void WebPluginDelegateStub::OnSetFocus(bool focused) {
}
void WebPluginDelegateStub::OnHandleInputEvent(
- const WebKit::WebInputEvent *event,
+ const blink::WebInputEvent *event,
bool* handled,
WebCursor* cursor) {
WebCursor::CursorInfo cursor_info;
@@ -316,7 +317,8 @@ void WebPluginDelegateStub::OnGetPluginScriptableObject(int* route_id) {
WebBindings::releaseObject(object);
}
-void WebPluginDelegateStub::OnGetFormValue(string16* value, bool* success) {
+void WebPluginDelegateStub::OnGetFormValue(base::string16* value,
+ bool* success) {
*success = false;
if (!delegate_)
return;
@@ -337,7 +339,7 @@ void WebPluginDelegateStub::OnSetContentAreaFocus(bool has_focus) {
#if defined(OS_WIN) && !defined(USE_AURA)
void WebPluginDelegateStub::OnImeCompositionUpdated(
- const string16& text,
+ const base::string16& text,
const std::vector<int>& clauses,
const std::vector<int>& target,
int cursor_position) {
@@ -348,7 +350,8 @@ void WebPluginDelegateStub::OnImeCompositionUpdated(
#endif
}
-void WebPluginDelegateStub::OnImeCompositionCompleted(const string16& text) {
+void WebPluginDelegateStub::OnImeCompositionCompleted(
+ const base::string16& text) {
if (delegate_)
delegate_->ImeCompositionCompleted(text);
}
@@ -381,7 +384,8 @@ void WebPluginDelegateStub::OnWindowFrameChanged(const gfx::Rect& window_frame,
delegate_->WindowFrameChanged(window_frame, view_frame);
}
-void WebPluginDelegateStub::OnImeCompositionCompleted(const string16& text) {
+void WebPluginDelegateStub::OnImeCompositionCompleted(
+ const base::string16& text) {
if (delegate_)
delegate_->ImeCompositionCompleted(text);
}
diff --git a/chromium/content/plugin/webplugin_delegate_stub.h b/chromium/content/plugin/webplugin_delegate_stub.h
index 375fee4bd75..8787f2524b1 100644
--- a/chromium/content/plugin/webplugin_delegate_stub.h
+++ b/chromium/content/plugin/webplugin_delegate_stub.h
@@ -23,7 +23,7 @@ struct PluginMsg_FetchURL_Params;
struct PluginMsg_UpdateGeometry_Param;
class WebCursor;
-namespace WebKit {
+namespace blink {
class WebInputEvent;
}
@@ -48,6 +48,7 @@ class WebPluginDelegateStub : public IPC::Listener,
virtual bool Send(IPC::Message* msg) OVERRIDE;
int instance_id() { return instance_id_; }
+ WebPluginDelegateImpl* delegate() { return delegate_; }
WebPluginProxy* webplugin() { return webplugin_; }
private:
@@ -68,7 +69,7 @@ class WebPluginDelegateStub : public IPC::Listener,
void OnDidFail(int id);
void OnDidFinishLoadWithReason(const GURL& url, int reason, int notify_id);
void OnSetFocus(bool focused);
- void OnHandleInputEvent(const WebKit::WebInputEvent* event,
+ void OnHandleInputEvent(const blink::WebInputEvent* event,
bool* handled, WebCursor* cursor);
void OnPaint(const gfx::Rect& damaged_rect);
void OnDidPaint();
@@ -78,15 +79,15 @@ class WebPluginDelegateStub : public IPC::Listener,
const std::string& result,
bool success,
int notify_id);
- void OnGetFormValue(string16* value, bool* success);
+ void OnGetFormValue(base::string16* value, bool* success);
void OnSetContentAreaFocus(bool has_focus);
#if defined(OS_WIN) && !defined(USE_AURA)
- void OnImeCompositionUpdated(const string16& text,
+ void OnImeCompositionUpdated(const base::string16& text,
const std::vector<int>& clauses,
const std::vector<int>& target,
int cursor_position);
- void OnImeCompositionCompleted(const string16& text);
+ void OnImeCompositionCompleted(const base::string16& text);
#endif
#if defined(OS_MACOSX)
void OnSetWindowFocus(bool has_focus);
@@ -95,7 +96,7 @@ class WebPluginDelegateStub : public IPC::Listener,
bool has_focus);
void OnWindowFrameChanged(const gfx::Rect& window_frame,
const gfx::Rect& view_frame);
- void OnImeCompositionCompleted(const string16& text);
+ void OnImeCompositionCompleted(const base::string16& text);
#endif
void OnDidReceiveManualResponse(
diff --git a/chromium/content/plugin/webplugin_proxy.cc b/chromium/content/plugin/webplugin_proxy.cc
index ecdab988d97..c87aac263f9 100644
--- a/chromium/content/plugin/webplugin_proxy.cc
+++ b/chromium/content/plugin/webplugin_proxy.cc
@@ -41,7 +41,7 @@
#include "content/public/common/sandbox_init.h"
#endif
-using WebKit::WebBindings;
+using blink::WebBindings;
namespace content {
@@ -77,7 +77,7 @@ WebPluginProxy::WebPluginProxy(
// then consider using SHM pixmaps for windowless plugin painting.
XDisplay* display = gfx::GetXDisplay();
if (ui::QuerySharedMemorySupport(display) == ui::SHARED_MEMORY_PIXMAP &&
- ui::BitsPerPixelForPixmapDepth(
+ gfx::BitsPerPixelForPixmapDepth(
display, DefaultDepth(display, DefaultScreen(display))) == 32) {
Visual* vis = DefaultVisual(display, DefaultScreen(display));
@@ -323,7 +323,7 @@ void WebPluginProxy::HandleURLRequest(const char* url,
GURL request_url(url);
if (!request_url.SchemeIs(kHttpScheme) &&
!request_url.SchemeIs(kHttpsScheme) &&
- !request_url.SchemeIs(chrome::kFtpScheme)) {
+ !request_url.SchemeIs(kFtpScheme)) {
return;
}
}
diff --git a/chromium/content/port/browser/event_with_latency_info.h b/chromium/content/port/browser/event_with_latency_info.h
index a39ae52076d..c0da18651be 100644
--- a/chromium/content/port/browser/event_with_latency_info.h
+++ b/chromium/content/port/browser/event_with_latency_info.h
@@ -7,7 +7,9 @@
#include "ui/events/latency_info.h"
-namespace WebKit {
+#include "content/common/input/web_input_event_traits.h"
+
+namespace blink {
class WebGestureEvent;
class WebMouseEvent;
class WebMouseWheelEvent;
@@ -26,15 +28,30 @@ class EventWithLatencyInfo {
: event(e), latency(l) {}
EventWithLatencyInfo() {}
+
+ bool CanCoalesceWith(const EventWithLatencyInfo& other)
+ const WARN_UNUSED_RESULT {
+ return WebInputEventTraits::CanCoalesce(other.event, event);
+ }
+
+ void CoalesceWith(const EventWithLatencyInfo& other) {
+ WebInputEventTraits::Coalesce(other.event, &event);
+ // When coalescing two input events, we keep the oldest LatencyInfo
+ // for Telemetry latency test since it will represent the longest
+ // latency.
+ if (other.latency.trace_id >= 0 &&
+ (latency.trace_id < 0 || other.latency.trace_id < latency.trace_id))
+ latency = other.latency;
+ }
};
-typedef EventWithLatencyInfo<WebKit::WebGestureEvent>
+typedef EventWithLatencyInfo<blink::WebGestureEvent>
GestureEventWithLatencyInfo;
-typedef EventWithLatencyInfo<WebKit::WebMouseWheelEvent>
+typedef EventWithLatencyInfo<blink::WebMouseWheelEvent>
MouseWheelEventWithLatencyInfo;
-typedef EventWithLatencyInfo<WebKit::WebMouseEvent>
+typedef EventWithLatencyInfo<blink::WebMouseEvent>
MouseEventWithLatencyInfo;
-typedef EventWithLatencyInfo<WebKit::WebTouchEvent>
+typedef EventWithLatencyInfo<blink::WebTouchEvent>
TouchEventWithLatencyInfo;
} // namespace content
diff --git a/chromium/content/port/browser/render_view_host_delegate_view.h b/chromium/content/port/browser/render_view_host_delegate_view.h
index 5e5d9b4d11e..c6fb2e77774 100644
--- a/chromium/content/port/browser/render_view_host_delegate_view.h
+++ b/chromium/content/port/browser/render_view_host_delegate_view.h
@@ -51,14 +51,14 @@ class CONTENT_EXPORT RenderViewHostDelegateView {
// reason, it must inform the renderer that the drag has ended; otherwise,
// this results in bugs like http://crbug.com/157134.
virtual void StartDragging(const DropData& drop_data,
- WebKit::WebDragOperationsMask allowed_ops,
+ blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) {}
// The page wants to update the mouse cursor during a drag & drop operation.
// |operation| describes the current operation (none, move, copy, link.)
- virtual void UpdateDragCursor(WebKit::WebDragOperation operation) {}
+ virtual void UpdateDragCursor(blink::WebDragOperation operation) {}
// Notification that view for this delegate got the focus.
virtual void GotFocus() {}
diff --git a/chromium/content/port/browser/render_widget_host_view_port.h b/chromium/content/port/browser/render_widget_host_view_port.h
index d13a125049b..a668af67745 100644
--- a/chromium/content/port/browser/render_widget_host_view_port.h
+++ b/chromium/content/port/browser/render_widget_host_view_port.h
@@ -5,7 +5,9 @@
#ifndef CONTENT_PORT_BROWSER_RENDER_WIDGET_HOST_VIEW_PORT_H_
#define CONTENT_PORT_BROWSER_RENDER_WIDGET_HOST_VIEW_PORT_H_
+#include "base/basictypes.h"
#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
#include "base/process/kill.h"
#include "base/strings/string16.h"
#include "cc/output/compositor_frame.h"
@@ -34,7 +36,7 @@ namespace media {
class VideoFrame;
}
-namespace WebKit {
+namespace blink {
struct WebScreenInfo;
}
@@ -42,6 +44,7 @@ namespace content {
class BackingStore;
class RenderWidgetHostViewFrameSubscriber;
class SyntheticGesture;
+class SyntheticGestureTarget;
struct WebPluginGeometry;
struct NativeWebKeyboardEvent;
@@ -60,7 +63,7 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView,
static RenderWidgetHostViewPort* CreateViewForWidget(
RenderWidgetHost* widget);
- static void GetDefaultScreenInfo(WebKit::WebScreenInfo* results);
+ static void GetDefaultScreenInfo(blink::WebScreenInfo* results);
// Perform all the initialization steps necessary for this object to represent
// a popup (such as a <select> dropdown), then shows the popup at |pos|.
@@ -143,10 +146,10 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView,
// Tells the View that the tooltip text for the current mouse position over
// the page has changed.
- virtual void SetTooltipText(const string16& tooltip_text) = 0;
+ virtual void SetTooltipText(const base::string16& tooltip_text) = 0;
// Notifies the View that the renderer text selection has changed.
- virtual void SelectionChanged(const string16& text,
+ virtual void SelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) = 0;
@@ -212,6 +215,8 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView,
// Called when accelerated compositing state changes.
virtual void OnAcceleratedCompositingStateChange() = 0;
+ // Called when an accelerated compositing surface is initialized.
+ virtual void AcceleratedSurfaceInitialized(int host_id, int route_id) = 0;
// |params.window| and |params.surface_id| indicate which accelerated
// surface's buffers swapped. |params.renderer_id| and |params.route_id|
// are used to formulate a reply to the GPU process to prevent it from getting
@@ -241,7 +246,7 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView,
uint32 output_surface_id,
scoped_ptr<cc::CompositorFrame> frame) = 0;
- virtual void GetScreenInfo(WebKit::WebScreenInfo* results) = 0;
+ virtual void GetScreenInfo(blink::WebScreenInfo* results) = 0;
// The size of the view's backing surface in non-DPI-adjusted pixels.
virtual gfx::Size GetPhysicalBackingSize() const = 0;
@@ -255,6 +260,9 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView,
virtual gfx::GLSurfaceHandle GetCompositingSurface() = 0;
+ // Resize compositing surface.
+ virtual void ResizeCompositingSurface(const gfx::Size&) = 0;
+
// Because the associated remote WebKit instance can asynchronously
// prevent-default on a dispatched touch event, the touch events are queued in
// the GestureRecognizer until invocation of ProcessAckedTouchEvent releases
@@ -263,30 +271,30 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView,
virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) = 0;
- // Asks the view to create a synthetic gesture that will be used to
- // simulate a user-initiated scroll.
- virtual SyntheticGesture* CreateSmoothScrollGesture(
- bool scroll_down, int pixels_to_scroll, int mouse_event_x,
- int mouse_event_y) = 0;
-
- // Asks the view to create a synthetic gesture that will be used to
- // simulate a user-initiated pinch-to-zoom.
- virtual SyntheticGesture* CreatePinchGesture(
- bool zoom_in, int pixels_to_move, int anchor_x, int anchor_y) = 0;
-
virtual void SetHasHorizontalScrollbar(bool has_horizontal_scrollbar) = 0;
virtual void SetScrollOffsetPinning(
bool is_pinned_to_left, bool is_pinned_to_right) = 0;
// Called when a mousewheel event was not processed by the renderer.
- virtual void UnhandledWheelEvent(const WebKit::WebMouseWheelEvent& event) = 0;
+ virtual void UnhandledWheelEvent(const blink::WebMouseWheelEvent& event) = 0;
// Called prior to forwarding input event messages to the renderer, giving
// the view a chance to perform in-process event filtering or processing.
// Return values of |NOT_CONSUMED| or |UNKNOWN| will result in |input_event|
// being forwarded.
virtual InputEventAckState FilterInputEvent(
- const WebKit::WebInputEvent& input_event) = 0;
+ const blink::WebInputEvent& input_event) = 0;
+
+ // Called by the host when it requires an input flush; the flush call should
+ // by synchronized with BeginFrame.
+ virtual void OnSetNeedsFlushInput() = 0;
+
+ // Called by the host when the input flush has completed.
+ virtual void OnDidFlushInput() = 0;
+
+ // Create a platform specific SyntheticGestureTarget implementation that will
+ // be used to inject synthetic input events.
+ virtual scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget() = 0;
virtual void GestureEventAck(int gesture_event_type,
InputEventAckState ack_result) = 0;
@@ -294,8 +302,8 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView,
virtual void OnOverscrolled(gfx::Vector2dF accumulated_overscroll,
gfx::Vector2dF current_fling_velocity) = 0;
- virtual void SetPopupType(WebKit::WebPopupType popup_type) = 0;
- virtual WebKit::WebPopupType GetPopupType() = 0;
+ virtual void SetPopupType(blink::WebPopupType popup_type) = 0;
+ virtual blink::WebPopupType GetPopupType() = 0;
virtual BrowserAccessibilityManager*
GetBrowserAccessibilityManager() const = 0;
@@ -334,6 +342,10 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView,
#if defined(OS_WIN) && defined(USE_AURA)
virtual void SetParentNativeViewAccessible(
gfx::NativeViewAccessible accessible_parent) = 0;
+
+ // Returns an HWND that's given as the parent window for windowless Flash to
+ // workaround crbug.com/301548.
+ virtual gfx::NativeViewId GetParentForWindowlessPlugin() const = 0;
#endif
};
diff --git a/chromium/content/port/browser/synthetic_gesture.h b/chromium/content/port/browser/synthetic_gesture.h
deleted file mode 100644
index 4330d76c216..00000000000
--- a/chromium/content/port/browser/synthetic_gesture.h
+++ /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.
-
-#ifndef CONTENT_PORT_BROWSER_SYNTHETIC_GESTURE_H_
-#define CONTENT_PORT_BROWSER_SYNTHETIC_GESTURE_H_
-
-#include "base/memory/ref_counted.h"
-#include "base/time/time.h"
-
-namespace content {
-
-class RenderWidgetHost;
-
-// This is a base class representing a single scroll gesture. These gestures are
-// paired with the rendering benchmarking system to (automatically) measure how
-// smoothnly chrome is responding to user input.
-class SyntheticGesture : public base::RefCounted<SyntheticGesture> {
- public:
-
- // When called, the gesture should compute its state at the provided timestamp
- // and send the right input events to the provided RenderWidgetHost to
- // simulate the gesture having run up to that point in time.
- //
- // This function should return true until the gesture is over. A false return
- // value will stop ticking the gesture and clean it up.
- virtual bool ForwardInputEvents(base::TimeTicks now,
- RenderWidgetHost* host) = 0;
- protected:
- friend class base::RefCounted<SyntheticGesture>;
- virtual ~SyntheticGesture() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_PORT_BROWSER_SYNTHETIC_GESTURE_H_
diff --git a/chromium/content/port/browser/vibration_provider.h b/chromium/content/port/browser/vibration_provider.h
new file mode 100644
index 00000000000..df2587f288d
--- /dev/null
+++ b/chromium/content/port/browser/vibration_provider.h
@@ -0,0 +1,23 @@
+// 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_PORT_BROWSER_VIBRATION_PROVIDER_H_
+#define CONTENT_PORT_BROWSER_VIBRATION_PROVIDER_H_
+
+namespace content {
+
+class VibrationProvider {
+ public:
+ // Device should start vibrating for N milliseconds.
+ virtual void Vibrate(int64 milliseconds) = 0;
+
+ // Cancels vibration of the device.
+ virtual void CancelVibration() = 0;
+
+ virtual ~VibrationProvider() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PORT_BROWSER_VIBRATION_PROVIDER_H_
diff --git a/chromium/content/port/browser/web_contents_view_port.h b/chromium/content/port/browser/web_contents_view_port.h
index 12c3083ba88..fef0b3c909a 100644
--- a/chromium/content/port/browser/web_contents_view_port.h
+++ b/chromium/content/port/browser/web_contents_view_port.h
@@ -35,7 +35,7 @@ class CONTENT_EXPORT WebContentsViewPort : public WebContentsView {
// is not strictly necessary and isn't expected to be displayed anywhere, but
// can aid certain debugging tools such as Spy++ on Windows where you are
// trying to find a specific window.
- virtual void SetPageTitle(const string16& title) = 0;
+ virtual void SetPageTitle(const base::string16& title) = 0;
// Invoked when the WebContents is notified that the RenderView has been
// fully created.
diff --git a/chromium/content/port/common/input_event_ack_state.h b/chromium/content/port/common/input_event_ack_state.h
index 4458b620050..5a95772f00a 100644
--- a/chromium/content/port/common/input_event_ack_state.h
+++ b/chromium/content/port/common/input_event_ack_state.h
@@ -13,6 +13,7 @@ enum InputEventAckState {
INPUT_EVENT_ACK_STATE_CONSUMED,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
+ INPUT_EVENT_ACK_STATE_IGNORED,
INPUT_EVENT_ACK_STATE_MAX = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
};
diff --git a/chromium/content/ppapi_plugin/broker_process_dispatcher.cc b/chromium/content/ppapi_plugin/broker_process_dispatcher.cc
index 727506c9f83..5f1ff63a0c5 100644
--- a/chromium/content/ppapi_plugin/broker_process_dispatcher.cc
+++ b/chromium/content/ppapi_plugin/broker_process_dispatcher.cc
@@ -81,8 +81,6 @@ BrokerProcessDispatcher::BrokerProcessDispatcher(
flash_browser_operations_1_3_(NULL),
flash_browser_operations_1_2_(NULL),
flash_browser_operations_1_0_(NULL) {
- ChildProcess::current()->AddRefProcess();
-
if (get_plugin_interface) {
flash_browser_operations_1_0_ =
static_cast<const PPP_Flash_BrowserOperations_1_0*>(
@@ -105,10 +103,7 @@ BrokerProcessDispatcher::~BrokerProcessDispatcher() {
// plugin. This is the case for common plugins where they may be used on a
// source and destination page of a navigation. We don't want to tear down
// and re-start processes each time in these cases.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&ChildProcess::ReleaseProcess,
- base::Unretained(ChildProcess::current())),
+ process_ref_.ReleaseWithDelay(
base::TimeDelta::FromSeconds(kBrokerReleaseTimeSeconds));
}
diff --git a/chromium/content/ppapi_plugin/broker_process_dispatcher.h b/chromium/content/ppapi_plugin/broker_process_dispatcher.h
index dd8c6a6294b..7b6471765f1 100644
--- a/chromium/content/ppapi_plugin/broker_process_dispatcher.h
+++ b/chromium/content/ppapi_plugin/broker_process_dispatcher.h
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "base/memory/weak_ptr.h"
+#include "content/child/scoped_child_process_reference.h"
#include "ppapi/c/ppp.h"
#include "ppapi/proxy/broker_dispatcher.h"
#include "ppapi/shared_impl/ppp_flash_browser_operations_shared.h"
@@ -78,6 +79,8 @@ class BrokerProcessDispatcher
PP_Flash_BrowserOperations_SettingType setting_type,
const ppapi::FlashSiteSettings& sites);
+ ScopedChildProcessReference process_ref_;
+
PP_GetInterface_Func get_plugin_interface_;
const PPP_Flash_BrowserOperations_1_3* flash_browser_operations_1_3_;
diff --git a/chromium/content/ppapi_plugin/plugin_process_dispatcher.cc b/chromium/content/ppapi_plugin/plugin_process_dispatcher.cc
index b0574d4853c..3bfc46a3b8b 100644
--- a/chromium/content/ppapi_plugin/plugin_process_dispatcher.cc
+++ b/chromium/content/ppapi_plugin/plugin_process_dispatcher.cc
@@ -23,7 +23,6 @@ PluginProcessDispatcher::PluginProcessDispatcher(
: ppapi::proxy::PluginDispatcher(get_interface,
permissions,
incognito) {
- ChildProcess::current()->AddRefProcess();
}
PluginProcessDispatcher::~PluginProcessDispatcher() {
@@ -32,10 +31,7 @@ PluginProcessDispatcher::~PluginProcessDispatcher() {
// plugin. This is the case for common plugins where they may be used on a
// source and destination page of a navigation. We don't want to tear down
// and re-start processes each time in these cases.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&ChildProcess::ReleaseProcess,
- base::Unretained(ChildProcess::current())),
+ process_ref_.ReleaseWithDelay(
base::TimeDelta::FromSeconds(kPluginReleaseTimeSeconds));
}
diff --git a/chromium/content/ppapi_plugin/plugin_process_dispatcher.h b/chromium/content/ppapi_plugin/plugin_process_dispatcher.h
index 1398a067a2c..2d80e0f02ec 100644
--- a/chromium/content/ppapi_plugin/plugin_process_dispatcher.h
+++ b/chromium/content/ppapi_plugin/plugin_process_dispatcher.h
@@ -6,6 +6,7 @@
#define CONTENT_PPAPI_PLUGIN_PLUGIN_PROCESS_DISPATCHER_H_
#include "base/basictypes.h"
+#include "content/child/scoped_child_process_reference.h"
#include "ppapi/proxy/plugin_dispatcher.h"
namespace content {
@@ -21,6 +22,8 @@ class PluginProcessDispatcher : public ppapi::proxy::PluginDispatcher {
virtual ~PluginProcessDispatcher();
private:
+ ScopedChildProcessReference process_ref_;
+
DISALLOW_COPY_AND_ASSIGN(PluginProcessDispatcher);
};
diff --git a/chromium/content/ppapi_plugin/ppapi_plugin_main.cc b/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
index dc7cf4a5694..9be65c11e66 100644
--- a/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
+++ b/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
@@ -10,18 +10,20 @@
#include "build/build_config.h"
#include "content/child/child_process.h"
#include "content/common/content_constants_internal.h"
-#include "content/common/sandbox_linux.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/ppapi_plugin/ppapi_thread.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/plugin/content_plugin_client.h"
#include "crypto/nss_util.h"
+#include "ppapi/proxy/plugin_globals.h"
#include "ppapi/proxy/proxy_module.h"
#include "ui/base/ui_base_switches.h"
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox.h"
+#include "third_party/skia/include/ports/SkTypeface_win.h"
#endif
#if defined(OS_LINUX)
@@ -40,6 +42,18 @@ void* g_target_services = 0;
namespace content {
+namespace {
+
+#if defined(OS_WIN)
+// Windows-only skia sandbox support
+void SkiaPreCacheFont(const LOGFONT& logfont) {
+ ppapi::proxy::PluginGlobals::Get()->PreCacheFontForFlash(
+ reinterpret_cast<const void*>(&logfont));
+}
+#endif
+
+} // namespace
+
// Main function for starting the PPAPI plugin process.
int PpapiPluginMain(const MainFunctionParams& parameters) {
const CommandLine& command_line = parameters.command_line;
@@ -105,6 +119,10 @@ int PpapiPluginMain(const MainFunctionParams& parameters) {
ppapi_process.set_main_thread(
new PpapiThread(parameters.command_line, false)); // Not a broker.
+#if defined(OS_WIN)
+ SkTypeface_SetEnsureLOGFONTAccessibleProc(SkiaPreCacheFont);
+#endif
+
main_message_loop.Run();
return 0;
}
diff --git a/chromium/content/ppapi_plugin/ppapi_thread.cc b/chromium/content/ppapi_plugin/ppapi_thread.cc
index 2d46807a371..c79ad230ec1 100644
--- a/chromium/content/ppapi_plugin/ppapi_thread.cc
+++ b/chromium/content/ppapi_plugin/ppapi_thread.cc
@@ -36,8 +36,9 @@
#include "ppapi/c/ppp.h"
#include "ppapi/proxy/interface_list.h"
#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_message_filter.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/shared_impl/api_id.h"
+#include "ppapi/proxy/resource_reply_thread_registrar.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "ui/base/ui_base_switches.h"
@@ -60,49 +61,25 @@ namespace content {
typedef int32_t (*InitializeBrokerFunc)
(PP_ConnectInstance_Func* connect_instance_func);
-PpapiThread::DispatcherMessageListener::DispatcherMessageListener(
- PpapiThread* owner) : owner_(owner) {
-}
-
-PpapiThread::DispatcherMessageListener::~DispatcherMessageListener() {
-}
-
-bool PpapiThread::DispatcherMessageListener::OnMessageReceived(
- const IPC::Message& msg) {
- // The first parameter should be a plugin dispatcher ID.
- PickleIterator iter(msg);
- uint32 id = 0;
- if (!msg.ReadUInt32(&iter, &id)) {
- NOTREACHED();
- return false;
- }
- std::map<uint32, ppapi::proxy::PluginDispatcher*>::iterator dispatcher =
- owner_->plugin_dispatchers_.find(id);
- if (dispatcher != owner_->plugin_dispatchers_.end())
- return dispatcher->second->OnMessageReceived(msg);
-
- return false;
-}
-
PpapiThread::PpapiThread(const CommandLine& command_line, bool is_broker)
: is_broker_(is_broker),
connect_instance_func_(NULL),
local_pp_module_(
base::RandInt(0, std::numeric_limits<PP_Module>::max())),
- next_plugin_dispatcher_id_(1),
- dispatcher_message_listener_(this) {
+ next_plugin_dispatcher_id_(1) {
ppapi::proxy::PluginGlobals* globals = ppapi::proxy::PluginGlobals::Get();
globals->set_plugin_proxy_delegate(this);
globals->set_command_line(
command_line.GetSwitchValueASCII(switches::kPpapiFlashArgs));
webkit_platform_support_.reset(new PpapiWebKitPlatformSupportImpl);
- WebKit::initialize(webkit_platform_support_.get());
+ blink::initialize(webkit_platform_support_.get());
- // Register interfaces that expect messages from the browser process. Please
- // note that only those InterfaceProxy-based ones require registration.
- AddRoute(ppapi::API_ID_PPB_HOSTRESOLVER_PRIVATE,
- &dispatcher_message_listener_);
+ if (!is_broker_) {
+ channel()->AddFilter(
+ new ppapi::proxy::PluginMessageFilter(
+ NULL, globals->resource_reply_thread_registrar()));
+ }
}
PpapiThread::~PpapiThread() {
@@ -112,7 +89,8 @@ void PpapiThread::Shutdown() {
ppapi::proxy::PluginGlobals::Get()->set_plugin_proxy_delegate(NULL);
if (plugin_entry_points_.shutdown_module)
plugin_entry_points_.shutdown_module();
- WebKit::shutdown();
+ webkit_platform_support_->Shutdown();
+ blink::shutdown();
}
bool PpapiThread::Send(IPC::Message* msg) {
@@ -134,7 +112,6 @@ bool PpapiThread::OnControlMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(PpapiMsg_SetNetworkState, OnSetNetworkState)
IPC_MESSAGE_HANDLER(PpapiMsg_Crash, OnCrash)
IPC_MESSAGE_HANDLER(PpapiMsg_Hang, OnHang)
- IPC_MESSAGE_HANDLER(PpapiPluginMsg_ResourceReply, OnResourceReply)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -229,7 +206,8 @@ void PpapiThread::Unregister(uint32 plugin_dispatcher_id) {
}
void PpapiThread::OnLoadPlugin(const base::FilePath& path,
- const ppapi::PpapiPermissions& permissions) {
+ const ppapi::PpapiPermissions& permissions,
+ bool supports_dev_channel) {
// In case of crashes, the crash dump doesn't indicate which plugin
// it came from.
base::debug::SetCrashKeyValue("ppapi_path", path.MaybeAsASCII());
@@ -239,6 +217,7 @@ void PpapiThread::OnLoadPlugin(const base::FilePath& path,
// This must be set before calling into the plugin so it can get the
// interfaces it has permission for.
ppapi::proxy::InterfaceList::SetProcessGlobalPermissions(permissions);
+ ppapi::proxy::InterfaceList::SetSupportsDevChannel(supports_dev_channel);
permissions_ = permissions;
// Trusted Pepper plugins may be "internal", i.e. built-in to the browser
@@ -385,13 +364,6 @@ void PpapiThread::OnCreateChannel(base::ProcessId renderer_pid,
Send(new PpapiHostMsg_ChannelCreated(channel_handle));
}
-void PpapiThread::OnResourceReply(
- const ppapi::proxy::ResourceMessageReplyParams& reply_params,
- const IPC::Message& nested_msg) {
- ppapi::proxy::PluginDispatcher::DispatchResourceReply(reply_params,
- nested_msg);
-}
-
void PpapiThread::OnSetNetworkState(bool online) {
// Note the browser-process side shouldn't send us these messages in the
// first unless the plugin has dev permissions, so we don't need to check
diff --git a/chromium/content/ppapi_plugin/ppapi_thread.h b/chromium/content/ppapi_plugin/ppapi_thread.h
index d1ca5501dfb..20c68ceb198 100644
--- a/chromium/content/ppapi_plugin/ppapi_thread.h
+++ b/chromium/content/ppapi_plugin/ppapi_thread.h
@@ -16,7 +16,6 @@
#include "build/build_config.h"
#include "content/child/child_thread.h"
#include "content/public/common/pepper_plugin_info.h"
-#include "ipc/ipc_listener.h"
#include "ppapi/c/pp_module.h"
#include "ppapi/c/trusted/ppp_broker.h"
#include "ppapi/proxy/connection.h"
@@ -62,22 +61,6 @@ class PpapiThread : public ChildThread,
LOAD_RESULT_MAX // Boundary value for UMA_HISTOGRAM_ENUMERATION.
};
- // This class finds the target PluginDispatcher for each message it receives
- // and forwards the message.
- class DispatcherMessageListener : public IPC::Listener {
- public:
- explicit DispatcherMessageListener(PpapiThread* owner);
- virtual ~DispatcherMessageListener();
-
- // IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
-
- private:
- PpapiThread* owner_;
-
- DISALLOW_COPY_AND_ASSIGN(DispatcherMessageListener);
- };
-
// ChildThread overrides.
virtual bool Send(IPC::Message* msg) OVERRIDE;
virtual bool OnControlMessageReceived(const IPC::Message& msg) OVERRIDE;
@@ -110,13 +93,11 @@ class PpapiThread : public ChildThread,
// Message handlers.
void OnLoadPlugin(const base::FilePath& path,
- const ppapi::PpapiPermissions& permissions);
+ const ppapi::PpapiPermissions& permissions,
+ bool supports_dev_channel);
void OnCreateChannel(base::ProcessId renderer_pid,
int renderer_child_id,
bool incognito);
- void OnResourceReply(
- const ppapi::proxy::ResourceMessageReplyParams& reply_params,
- const IPC::Message& nested_msg);
void OnSetNetworkState(bool online);
void OnCrash();
void OnHang();
@@ -173,8 +154,6 @@ class PpapiThread : public ChildThread,
base::win::ScopedHandle peer_handle_;
#endif
- DispatcherMessageListener dispatcher_message_listener_;
-
DISALLOW_IMPLICIT_CONSTRUCTORS(PpapiThread);
};
diff --git a/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.cc b/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.cc
index 049fe20d102..948b02581ec 100644
--- a/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.cc
+++ b/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.cc
@@ -8,11 +8,12 @@
#include "base/logging.h"
#include "base/strings/string16.h"
-#include "base/synchronization/lock.h"
+#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "content/child/child_thread.h"
#include "content/common/child_process_messages.h"
#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
#include "third_party/WebKit/public/platform/WebString.h"
#if defined(OS_WIN)
@@ -28,10 +29,10 @@
#include "third_party/icu/source/common/unicode/utf16.h"
#endif
-using WebKit::WebSandboxSupport;
-using WebKit::WebString;
-using WebKit::WebUChar;
-using WebKit::WebUChar32;
+using blink::WebSandboxSupport;
+using blink::WebString;
+using blink::WebUChar;
+using blink::WebUChar32;
typedef struct CGFont* CGFontRef;
@@ -50,19 +51,21 @@ class PpapiWebKitPlatformSupportImpl::SandboxSupport
#elif defined(OS_ANDROID)
// Empty class.
#elif defined(OS_POSIX)
+ SandboxSupport();
virtual void getFontFamilyForCharacter(
WebUChar32 character,
const char* preferred_locale,
- WebKit::WebFontFamily* family);
+ blink::WebFontFamily* family);
virtual void getRenderStyleForStrike(
- const char* family, int sizeAndStyle, WebKit::WebFontRenderStyle* out);
+ const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out);
private:
// WebKit likes to ask us for the correct font family to use for a set of
// unicode code points. It needs this information frequently so we cache it
// here.
- base::Lock unicode_font_families_mutex_;
- std::map<int32_t, WebKit::WebFontFamily> unicode_font_families_;
+ std::map<int32_t, blink::WebFontFamily> unicode_font_families_;
+ // For debugging crbug.com/312965
+ base::PlatformThreadId creation_thread_;
#endif
};
@@ -98,13 +101,19 @@ bool PpapiWebKitPlatformSupportImpl::SandboxSupport::loadFont(
#elif defined(OS_POSIX)
+PpapiWebKitPlatformSupportImpl::SandboxSupport::SandboxSupport()
+ : creation_thread_(base::PlatformThread::CurrentId()) {
+}
+
void
PpapiWebKitPlatformSupportImpl::SandboxSupport::getFontFamilyForCharacter(
WebUChar32 character,
const char* preferred_locale,
- WebKit::WebFontFamily* family) {
- base::AutoLock lock(unicode_font_families_mutex_);
- const std::map<int32_t, WebKit::WebFontFamily>::const_iterator iter =
+ blink::WebFontFamily* family) {
+ ppapi::ProxyLock::AssertAcquired();
+ // For debugging crbug.com/312965
+ CHECK_EQ(creation_thread_, base::PlatformThread::CurrentId());
+ const std::map<int32_t, blink::WebFontFamily>::const_iterator iter =
unicode_font_families_.find(character);
if (iter != unicode_font_families_.end()) {
family->name = iter->second.name;
@@ -118,7 +127,7 @@ PpapiWebKitPlatformSupportImpl::SandboxSupport::getFontFamilyForCharacter(
}
void PpapiWebKitPlatformSupportImpl::SandboxSupport::getRenderStyleForStrike(
- const char* family, int sizeAndStyle, WebKit::WebFontRenderStyle* out) {
+ const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out) {
GetRenderStyleForStrike(family, sizeAndStyle, out);
}
@@ -131,22 +140,29 @@ PpapiWebKitPlatformSupportImpl::PpapiWebKitPlatformSupportImpl()
PpapiWebKitPlatformSupportImpl::~PpapiWebKitPlatformSupportImpl() {
}
-WebKit::WebClipboard* PpapiWebKitPlatformSupportImpl::clipboard() {
+void PpapiWebKitPlatformSupportImpl::Shutdown() {
+ // SandboxSupport contains a map of WebFontFamily objects, which hold
+ // WebCStrings, which become invalidated when blink is shut down. Hence, we
+ // need to clear that map now, just before blink::shutdown() is called.
+ sandbox_support_.reset();
+}
+
+blink::WebClipboard* PpapiWebKitPlatformSupportImpl::clipboard() {
NOTREACHED();
return NULL;
}
-WebKit::WebMimeRegistry* PpapiWebKitPlatformSupportImpl::mimeRegistry() {
+blink::WebMimeRegistry* PpapiWebKitPlatformSupportImpl::mimeRegistry() {
NOTREACHED();
return NULL;
}
-WebKit::WebFileUtilities* PpapiWebKitPlatformSupportImpl::fileUtilities() {
+blink::WebFileUtilities* PpapiWebKitPlatformSupportImpl::fileUtilities() {
NOTREACHED();
return NULL;
}
-WebKit::WebSandboxSupport* PpapiWebKitPlatformSupportImpl::sandboxSupport() {
+blink::WebSandboxSupport* PpapiWebKitPlatformSupportImpl::sandboxSupport() {
return sandbox_support_.get();
}
@@ -167,72 +183,72 @@ bool PpapiWebKitPlatformSupportImpl::isLinkVisited(
return false;
}
-WebKit::WebMessagePortChannel*
+blink::WebMessagePortChannel*
PpapiWebKitPlatformSupportImpl::createMessagePortChannel() {
NOTREACHED();
return NULL;
}
void PpapiWebKitPlatformSupportImpl::setCookies(
- const WebKit::WebURL& url,
- const WebKit::WebURL& first_party_for_cookies,
- const WebKit::WebString& value) {
+ const blink::WebURL& url,
+ const blink::WebURL& first_party_for_cookies,
+ const blink::WebString& value) {
NOTREACHED();
}
-WebKit::WebString PpapiWebKitPlatformSupportImpl::cookies(
- const WebKit::WebURL& url,
- const WebKit::WebURL& first_party_for_cookies) {
+blink::WebString PpapiWebKitPlatformSupportImpl::cookies(
+ const blink::WebURL& url,
+ const blink::WebURL& first_party_for_cookies) {
NOTREACHED();
- return WebKit::WebString();
+ return blink::WebString();
}
-WebKit::WebString PpapiWebKitPlatformSupportImpl::defaultLocale() {
+blink::WebString PpapiWebKitPlatformSupportImpl::defaultLocale() {
NOTREACHED();
- return WebKit::WebString();
+ return blink::WebString();
}
-WebKit::WebThemeEngine* PpapiWebKitPlatformSupportImpl::themeEngine() {
+blink::WebThemeEngine* PpapiWebKitPlatformSupportImpl::themeEngine() {
NOTREACHED();
return NULL;
}
-WebKit::WebURLLoader* PpapiWebKitPlatformSupportImpl::createURLLoader() {
+blink::WebURLLoader* PpapiWebKitPlatformSupportImpl::createURLLoader() {
NOTREACHED();
return NULL;
}
-WebKit::WebSocketStreamHandle*
+blink::WebSocketStreamHandle*
PpapiWebKitPlatformSupportImpl::createSocketStreamHandle() {
NOTREACHED();
return NULL;
}
void PpapiWebKitPlatformSupportImpl::getPluginList(bool refresh,
- WebKit::WebPluginListBuilder* builder) {
+ blink::WebPluginListBuilder* builder) {
NOTREACHED();
}
-WebKit::WebData PpapiWebKitPlatformSupportImpl::loadResource(const char* name) {
+blink::WebData PpapiWebKitPlatformSupportImpl::loadResource(const char* name) {
NOTREACHED();
- return WebKit::WebData();
+ return blink::WebData();
}
-WebKit::WebStorageNamespace*
+blink::WebStorageNamespace*
PpapiWebKitPlatformSupportImpl::createLocalStorageNamespace() {
NOTREACHED();
return 0;
}
void PpapiWebKitPlatformSupportImpl::dispatchStorageEvent(
- const WebKit::WebString& key, const WebKit::WebString& old_value,
- const WebKit::WebString& new_value, const WebKit::WebString& origin,
- const WebKit::WebURL& url, bool is_local_storage) {
+ const blink::WebString& key, const blink::WebString& old_value,
+ const blink::WebString& new_value, const blink::WebString& origin,
+ const blink::WebURL& url, bool is_local_storage) {
NOTREACHED();
}
int PpapiWebKitPlatformSupportImpl::databaseDeleteFile(
- const WebKit::WebString& vfs_file_name, bool sync_dir) {
+ const blink::WebString& vfs_file_name, bool sync_dir) {
NOTREACHED();
return 0;
}
diff --git a/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h b/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h
index d2a35417f04..c8e6ab9c6a3 100644
--- a/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h
+++ b/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h
@@ -16,34 +16,37 @@ class PpapiWebKitPlatformSupportImpl : public WebKitPlatformSupportImpl {
PpapiWebKitPlatformSupportImpl();
virtual ~PpapiWebKitPlatformSupportImpl();
+ // Shutdown must be called just prior to shutting down blink.
+ void Shutdown();
+
// WebKitPlatformSupport methods:
- virtual WebKit::WebClipboard* clipboard();
- virtual WebKit::WebMimeRegistry* mimeRegistry();
- virtual WebKit::WebFileUtilities* fileUtilities();
- virtual WebKit::WebSandboxSupport* sandboxSupport();
+ virtual blink::WebClipboard* clipboard();
+ virtual blink::WebMimeRegistry* mimeRegistry();
+ virtual blink::WebFileUtilities* fileUtilities();
+ virtual blink::WebSandboxSupport* sandboxSupport();
virtual bool sandboxEnabled();
virtual unsigned long long visitedLinkHash(const char* canonicalURL,
size_t length);
virtual bool isLinkVisited(unsigned long long linkHash);
- virtual WebKit::WebMessagePortChannel* createMessagePortChannel();
- virtual void setCookies(const WebKit::WebURL& url,
- const WebKit::WebURL& first_party_for_cookies,
- const WebKit::WebString& value);
- virtual WebKit::WebString cookies(
- const WebKit::WebURL& url,
- const WebKit::WebURL& first_party_for_cookies);
- virtual WebKit::WebString defaultLocale();
- virtual WebKit::WebThemeEngine* themeEngine();
- virtual WebKit::WebURLLoader* createURLLoader();
- virtual WebKit::WebSocketStreamHandle* createSocketStreamHandle();
- virtual void getPluginList(bool refresh, WebKit::WebPluginListBuilder*);
- virtual WebKit::WebData loadResource(const char* name);
- virtual WebKit::WebStorageNamespace* createLocalStorageNamespace();
- virtual void dispatchStorageEvent(const WebKit::WebString& key,
- const WebKit::WebString& oldValue, const WebKit::WebString& newValue,
- const WebKit::WebString& origin, const WebKit::WebURL& url,
+ virtual blink::WebMessagePortChannel* createMessagePortChannel();
+ virtual void setCookies(const blink::WebURL& url,
+ const blink::WebURL& first_party_for_cookies,
+ const blink::WebString& value);
+ virtual blink::WebString cookies(
+ const blink::WebURL& url,
+ const blink::WebURL& first_party_for_cookies);
+ virtual blink::WebString defaultLocale();
+ virtual blink::WebThemeEngine* themeEngine();
+ virtual blink::WebURLLoader* createURLLoader();
+ virtual blink::WebSocketStreamHandle* createSocketStreamHandle();
+ virtual void getPluginList(bool refresh, blink::WebPluginListBuilder*);
+ virtual blink::WebData loadResource(const char* name);
+ virtual blink::WebStorageNamespace* createLocalStorageNamespace();
+ virtual void dispatchStorageEvent(const blink::WebString& key,
+ const blink::WebString& oldValue, const blink::WebString& newValue,
+ const blink::WebString& origin, const blink::WebURL& url,
bool isLocalStorage);
- virtual int databaseDeleteFile(const WebKit::WebString& vfs_file_name,
+ virtual int databaseDeleteFile(const blink::WebString& vfs_file_name,
bool sync_dir);
private:
diff --git a/chromium/content/public/android/OWNERS b/chromium/content/public/android/OWNERS
index 7b7df6dc836..29d0acf8c4e 100644
--- a/chromium/content/public/android/OWNERS
+++ b/chromium/content/public/android/OWNERS
@@ -1,4 +1,3 @@
bulach@chromium.org
-joth@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
diff --git a/chromium/content/public/app/android_library_loader_hooks.h b/chromium/content/public/app/android_library_loader_hooks.h
index c4bec7e3939..2ec5a194cfd 100644
--- a/chromium/content/public/app/android_library_loader_hooks.h
+++ b/chromium/content/public/app/android_library_loader_hooks.h
@@ -18,6 +18,16 @@ namespace content {
// once the native library has fully loaded.
CONTENT_EXPORT bool RegisterLibraryLoaderEntryHook(JNIEnv* env);
+// Register all content JNI functions now, rather than waiting for the process
+// of fully loading the native library to complete. This must only be called
+// during JNI_OnLoad.
+CONTENT_EXPORT bool EnsureJniRegistered(JNIEnv* env);
+
+// Pass the version name to Content. This used to check that the library version
+// matches the version expected by Java before completing JNI registration.
+// Note: argument must remain valid at least until library loading is complete.
+CONTENT_EXPORT void SetVersionNumber(const char* version_number);
+
// Call on exit to delete the AtExitManager which OnLibraryLoadedOnUIThread
// created.
CONTENT_EXPORT void LibraryLoaderExitHook();
diff --git a/chromium/content/public/browser/access_token_store.h b/chromium/content/public/browser/access_token_store.h
index 0af3fe78882..bd130144c6c 100644
--- a/chromium/content/public/browser/access_token_store.h
+++ b/chromium/content/public/browser/access_token_store.h
@@ -33,7 +33,7 @@ namespace content {
class AccessTokenStore : public base::RefCountedThreadSafe<AccessTokenStore> {
public:
// Map of server URLs to associated access token.
- typedef std::map<GURL, string16> AccessTokenSet;
+ typedef std::map<GURL, base::string16> AccessTokenSet;
typedef base::Callback<void(AccessTokenSet, net::URLRequestContextGetter*)>
LoadAccessTokensCallbackType;
@@ -47,7 +47,7 @@ class AccessTokenStore : public base::RefCountedThreadSafe<AccessTokenStore> {
const LoadAccessTokensCallbackType& callback) = 0;
virtual void SaveAccessToken(
- const GURL& server_url, const string16& access_token) = 0;
+ const GURL& server_url, const base::string16& access_token) = 0;
protected:
friend class base::RefCountedThreadSafe<AccessTokenStore>;
diff --git a/chromium/content/public/browser/android/compositor.h b/chromium/content/public/browser/android/compositor.h
index a7072c4fb5e..eb0c96e6413 100644
--- a/chromium/content/public/browser/android/compositor.h
+++ b/chromium/content/public/browser/android/compositor.h
@@ -35,21 +35,10 @@ class CONTENT_EXPORT Compositor {
// instance can be used. This should be called only once.
static void Initialize();
- enum CompositorFlags {
- // Creates a direct GL context on the thread that draws
- // (i.e. main or impl thread).
- DIRECT_CONTEXT_ON_DRAW_THREAD = 1,
-
- // Runs the compositor in threaded mode.
- ENABLE_COMPOSITOR_THREAD = 1 << 1,
- };
-
- // Initialize with flags. This should only be called once instead
- // of Initialize().
- static void InitializeWithFlags(uint32 flags);
-
- // Creates and returns a compositor instance.
- static Compositor* Create(CompositorClient* client);
+ // Creates and returns a compositor instance. |root_window| needs to outlive
+ // the compositor as it manages callbacks on the compositor.
+ static Compositor* Create(CompositorClient* client,
+ gfx::NativeWindow root_window);
// Attaches the layer tree.
virtual void SetRootLayer(scoped_refptr<cc::Layer> root) = 0;
@@ -72,17 +61,11 @@ class CONTENT_EXPORT Compositor {
// Set the output surface which the compositor renders into.
virtual void SetSurface(jobject surface) = 0;
- // Tells the view tree to assume a transparent background when rendering.
- virtual void SetHasTransparentBackground(bool flag) = 0;
-
// Attempts to composite and read back the result into the provided buffer.
// The buffer must be at least window width * height * 4 (RGBA) bytes large.
// The buffer is not modified if false is returned.
virtual bool CompositeAndReadback(void *pixels, const gfx::Rect& rect) = 0;
- // Invalidate the whole viewport.
- virtual void SetNeedsRedraw() = 0;
-
// Composite immediately. Used in single-threaded mode.
virtual void Composite() = 0;
@@ -95,27 +78,27 @@ class CONTENT_EXPORT Compositor {
// Generates an OpenGL texture and returns a texture handle. May return 0
// if the current context is lost.
- virtual WebKit::WebGLId GenerateTexture(gfx::JavaBitmap& bitmap) = 0;
+ virtual blink::WebGLId GenerateTexture(gfx::JavaBitmap& bitmap) = 0;
// Generates an OpenGL compressed texture and returns a texture handle. May
// return 0 if the current context is lost.
- virtual WebKit::WebGLId GenerateCompressedTexture(gfx::Size& size,
+ virtual blink::WebGLId GenerateCompressedTexture(gfx::Size& size,
int data_size,
void* data) = 0;
// Deletes an OpenGL texture.
- virtual void DeleteTexture(WebKit::WebGLId texture_id) = 0;
+ virtual void DeleteTexture(blink::WebGLId texture_id) = 0;
// Grabs a copy of |texture_id| and saves it into |bitmap|. No scaling is
// done. It is assumed that the texture size matches that of the bitmap.
- virtual bool CopyTextureToBitmap(WebKit::WebGLId texture_id,
+ virtual bool CopyTextureToBitmap(blink::WebGLId texture_id,
gfx::JavaBitmap& bitmap) = 0;
// Grabs a copy of |texture_id| and saves it into |bitmap|. No scaling is
// done. |src_rect| allows the caller to specify which rect of |texture_id|
// to copy to |bitmap|. It needs to match the size of |bitmap|. Returns
// true if the |texture_id| was copied into |bitmap|, false if not.
- virtual bool CopyTextureToBitmap(WebKit::WebGLId texture_id,
+ virtual bool CopyTextureToBitmap(blink::WebGLId texture_id,
const gfx::Rect& src_rect,
gfx::JavaBitmap& bitmap) = 0;
protected:
diff --git a/chromium/content/public/browser/android/content_view_core.h b/chromium/content/public/browser/android/content_view_core.h
index 79be4c4c120..9adaf4c39ce 100644
--- a/chromium/content/public/browser/android/content_view_core.h
+++ b/chromium/content/public/browser/android/content_view_core.h
@@ -55,6 +55,7 @@ class CONTENT_EXPORT ContentViewCore {
virtual void RequestContentClipping(const gfx::Rect& clipping,
const gfx::Size& content_size) = 0;
virtual void PauseVideo() = 0;
+ virtual void PauseOrResumeGeolocation(bool should_pause) = 0;
// Observer callback for frame metadata updates.
typedef base::Callback<void(
diff --git a/chromium/content/public/browser/android/content_view_layer_renderer.h b/chromium/content/public/browser/android/content_view_layer_renderer.h
index abc39cce121..a7d563ab104 100644
--- a/chromium/content/public/browser/android/content_view_layer_renderer.h
+++ b/chromium/content/public/browser/android/content_view_layer_renderer.h
@@ -8,7 +8,7 @@
// This interface is used by consumers of the ContentViewRenderView to
// attach/detach layers.
-namespace WebKit {
+namespace blink {
class WebLayer;
}
@@ -16,8 +16,8 @@ namespace content {
class ContentViewLayerRenderer {
public:
- virtual void AttachLayer(WebKit::WebLayer* layer) = 0;
- virtual void DetachLayer(WebKit::WebLayer* layer) = 0;
+ virtual void AttachLayer(blink::WebLayer* layer) = 0;
+ virtual void DetachLayer(blink::WebLayer* layer) = 0;
protected:
virtual ~ContentViewLayerRenderer() {}
diff --git a/chromium/content/public/browser/android/synchronous_compositor.cc b/chromium/content/public/browser/android/synchronous_compositor.cc
index 051aa5b34ff..25c4dc4cf3c 100644
--- a/chromium/content/public/browser/android/synchronous_compositor.cc
+++ b/chromium/content/public/browser/android/synchronous_compositor.cc
@@ -9,4 +9,15 @@ namespace content {
SynchronousCompositorMemoryPolicy::SynchronousCompositorMemoryPolicy()
: bytes_limit(0), num_resources_limit(0) {}
+bool SynchronousCompositorMemoryPolicy::operator==(
+ const SynchronousCompositorMemoryPolicy& other) const {
+ return bytes_limit == other.bytes_limit &&
+ num_resources_limit == other.num_resources_limit;
+}
+
+bool SynchronousCompositorMemoryPolicy::operator!=(
+ const SynchronousCompositorMemoryPolicy& other) const {
+ return !(*this == other);
+}
+
} // namespace content
diff --git a/chromium/content/public/browser/android/synchronous_compositor.h b/chromium/content/public/browser/android/synchronous_compositor.h
index 45b01eb6e83..c77d2a87100 100644
--- a/chromium/content/public/browser/android/synchronous_compositor.h
+++ b/chromium/content/public/browser/android/synchronous_compositor.h
@@ -31,6 +31,9 @@ struct CONTENT_EXPORT SynchronousCompositorMemoryPolicy {
size_t num_resources_limit;
SynchronousCompositorMemoryPolicy();
+
+ bool operator==(const SynchronousCompositorMemoryPolicy& other) const;
+ bool operator!=(const SynchronousCompositorMemoryPolicy& other) const;
};
// Interface for embedders that wish to direct compositing operations
diff --git a/chromium/content/public/browser/android/synchronous_compositor_client.h b/chromium/content/public/browser/android/synchronous_compositor_client.h
index bfd647b931d..fd57c6d49a7 100644
--- a/chromium/content/public/browser/android/synchronous_compositor_client.h
+++ b/chromium/content/public/browser/android/synchronous_compositor_client.h
@@ -25,8 +25,14 @@ class SynchronousCompositorClient {
virtual void DidDestroyCompositor(SynchronousCompositor* compositor) = 0;
// See LayerScrollOffsetDelegate for details.
+ virtual void SetMaxRootLayerScrollOffset(
+ gfx::Vector2dF max_scroll_offset) = 0;
virtual void SetTotalRootLayerScrollOffset(gfx::Vector2dF new_value) = 0;
virtual gfx::Vector2dF GetTotalRootLayerScrollOffset() = 0;
+ virtual bool IsExternalFlingActive() const = 0;
+ virtual void SetRootLayerPageScaleFactor(float page_scale_factor) = 0;
+ virtual void SetRootLayerScrollableSize(gfx::SizeF scrollable_size) = 0;
+
virtual void DidOverscroll(gfx::Vector2dF accumulated_overscroll,
gfx::Vector2dF latest_overscroll_delta,
gfx::Vector2dF current_fling_velocity) = 0;
diff --git a/chromium/content/public/browser/browser_child_process_host.h b/chromium/content/public/browser/browser_child_process_host.h
index e618ad7daf0..7776a0d3df5 100644
--- a/chromium/content/public/browser/browser_child_process_host.h
+++ b/chromium/content/public/browser/browser_child_process_host.h
@@ -68,7 +68,7 @@ class CONTENT_EXPORT BrowserChildProcessHost : public IPC::Sender {
bool known_dead, int* exit_code) = 0;
// Sets the user-visible name of the process.
- virtual void SetName(const string16& name) = 0;
+ virtual void SetName(const base::string16& name) = 0;
// Set the handle of the process. BrowserChildProcessHost will do this when
// the Launch method is used to start the process. However if the owner
diff --git a/chromium/content/public/browser/browser_child_process_host_iterator.cc b/chromium/content/public/browser/browser_child_process_host_iterator.cc
index 19eaec39333..a2aa0473b6f 100644
--- a/chromium/content/public/browser/browser_child_process_host_iterator.cc
+++ b/chromium/content/public/browser/browser_child_process_host_iterator.cc
@@ -13,19 +13,25 @@ namespace content {
BrowserChildProcessHostIterator::BrowserChildProcessHostIterator()
: all_(true), process_type_(PROCESS_TYPE_UNKNOWN) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) <<
- "BrowserChildProcessHostIterator must be used on the IO thread.";
+ "BrowserChildProcessHostIterator must be used on the IO thread.";
iterator_ = BrowserChildProcessHostImpl::GetIterator()->begin();
}
BrowserChildProcessHostIterator::BrowserChildProcessHostIterator(int type)
: all_(false), process_type_(type) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) <<
- "BrowserChildProcessHostIterator must be used on the IO thread.";
+ "BrowserChildProcessHostIterator must be used on the IO thread.";
+ DCHECK_NE(PROCESS_TYPE_RENDERER, type) <<
+ "BrowserChildProcessHostIterator doesn't work for renderer processes; "
+ "try RenderProcessHost::AllHostsIterator() instead.";
iterator_ = BrowserChildProcessHostImpl::GetIterator()->begin();
if (!Done() && (*iterator_)->GetData().process_type != process_type_)
++(*this);
}
+BrowserChildProcessHostIterator::~BrowserChildProcessHostIterator() {
+}
+
bool BrowserChildProcessHostIterator::operator++() {
CHECK(!Done());
do {
diff --git a/chromium/content/public/browser/browser_child_process_host_iterator.h b/chromium/content/public/browser/browser_child_process_host_iterator.h
index c9e0d715f5f..59075c3b853 100644
--- a/chromium/content/public/browser/browser_child_process_host_iterator.h
+++ b/chromium/content/public/browser/browser_child_process_host_iterator.h
@@ -26,6 +26,7 @@ class CONTENT_EXPORT BrowserChildProcessHostIterator {
public:
BrowserChildProcessHostIterator();
explicit BrowserChildProcessHostIterator(int type);
+ ~BrowserChildProcessHostIterator();
// These methods work on the current iterator object. Only call them if
// Done() returns false.
diff --git a/chromium/content/public/browser/browser_context.h b/chromium/content/public/browser/browser_context.h
index cbac82f4df8..d6d89501039 100644
--- a/chromium/content/public/browser/browser_context.h
+++ b/chromium/content/public/browser/browser_context.h
@@ -132,9 +132,17 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
virtual void RequestMIDISysExPermission(
int render_process_id,
int render_view_id,
+ int bridge_id,
const GURL& requesting_frame,
const MIDISysExPermissionCallback& callback) = 0;
+ // Cancels a pending MIDI permission request.
+ virtual void CancelMIDISysExPermissionRequest(
+ int render_process_id,
+ int render_view_id,
+ int bridge_id,
+ const GURL& requesting_frame) = 0;
+
// Returns the resource context.
virtual ResourceContext* GetResourceContext() = 0;
diff --git a/chromium/content/public/browser/browser_message_filter.cc b/chromium/content/public/browser/browser_message_filter.cc
index 53c0f872b2a..cca9d309f01 100644
--- a/chromium/content/public/browser/browser_message_filter.cc
+++ b/chromium/content/public/browser/browser_message_filter.cc
@@ -6,11 +6,13 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/command_line.h"
#include "base/logging.h"
#include "base/process/kill.h"
#include "base/process/process_handle.h"
#include "base/task_runner.h"
#include "content/public/browser/user_metrics.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "ipc/ipc_sync_message.h"
@@ -18,52 +20,87 @@ using content::BrowserMessageFilter;
namespace content {
-BrowserMessageFilter::BrowserMessageFilter()
- : channel_(NULL),
-#if defined(OS_WIN)
- peer_handle_(base::kNullProcessHandle),
-#endif
- peer_pid_(base::kNullProcessId) {
-}
+class BrowserMessageFilter::Internal : public IPC::ChannelProxy::MessageFilter {
+ public:
+ explicit Internal(BrowserMessageFilter* filter) : filter_(filter) {}
-void BrowserMessageFilter::OnFilterAdded(IPC::Channel* channel) {
- channel_ = channel;
-}
+ private:
+ virtual ~Internal() {}
-void BrowserMessageFilter::OnChannelClosing() {
- channel_ = NULL;
-}
+ // IPC::ChannelProxy::MessageFilter implementation:
+ virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE {
+ filter_->channel_ = channel;
+ filter_->OnFilterAdded(channel);
+ }
-void BrowserMessageFilter::OnChannelConnected(int32 peer_pid) {
- peer_pid_ = peer_pid;
-}
+ virtual void OnFilterRemoved() OVERRIDE {
+ filter_->OnFilterRemoved();
+ }
-bool BrowserMessageFilter::OnMessageReceived(const IPC::Message& message) {
- BrowserThread::ID thread = BrowserThread::IO;
- OverrideThreadForMessage(message, &thread);
-
- if (thread == BrowserThread::IO) {
- scoped_refptr<base::TaskRunner> runner =
- OverrideTaskRunnerForMessage(message);
- if (runner.get()) {
- runner->PostTask(
- FROM_HERE,
- base::Bind(base::IgnoreResult(&BrowserMessageFilter::DispatchMessage),
- this,
- message));
+ virtual void OnChannelClosing() OVERRIDE {
+ filter_->channel_ = NULL;
+ filter_->OnChannelClosing();
+ }
+
+ virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
+ filter_->peer_pid_ = peer_pid;
+ filter_->OnChannelConnected(peer_pid);
+ }
+
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ BrowserThread::ID thread = BrowserThread::IO;
+ filter_->OverrideThreadForMessage(message, &thread);
+
+ if (thread == BrowserThread::IO) {
+ scoped_refptr<base::TaskRunner> runner =
+ filter_->OverrideTaskRunnerForMessage(message);
+ if (runner.get()) {
+ runner->PostTask(
+ FROM_HERE,
+ base::Bind(
+ base::IgnoreResult(&Internal::DispatchMessage), this, message));
+ return true;
+ }
+ return DispatchMessage(message);
+ }
+
+ if (thread == BrowserThread::UI &&
+ !BrowserMessageFilter::CheckCanDispatchOnUI(message, filter_)) {
return true;
}
- return DispatchMessage(message);
- }
- if (thread == BrowserThread::UI && !CheckCanDispatchOnUI(message, this))
+ BrowserThread::PostTask(
+ thread, FROM_HERE,
+ base::Bind(
+ base::IgnoreResult(&Internal::DispatchMessage), this, message));
return true;
+ }
- BrowserThread::PostTask(
- thread, FROM_HERE,
- base::Bind(base::IgnoreResult(&BrowserMessageFilter::DispatchMessage),
- this, message));
- return true;
+ // Dispatches a message to the derived class.
+ bool DispatchMessage(const IPC::Message& message) {
+ bool message_was_ok = true;
+ bool rv = filter_->OnMessageReceived(message, &message_was_ok);
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) || rv) <<
+ "Must handle messages that were dispatched to another thread!";
+ if (!message_was_ok) {
+ content::RecordAction(UserMetricsAction("BadMessageTerminate_BMF"));
+ filter_->BadMessageReceived();
+ }
+
+ return rv;
+ }
+
+ scoped_refptr<BrowserMessageFilter> filter_;
+
+ DISALLOW_COPY_AND_ASSIGN(Internal);
+};
+
+BrowserMessageFilter::BrowserMessageFilter()
+ : internal_(NULL), channel_(NULL),
+#if defined(OS_WIN)
+ peer_handle_(base::kNullProcessHandle),
+#endif
+ peer_pid_(base::kNullProcessId) {
}
base::ProcessHandle BrowserMessageFilter::PeerHandle() {
@@ -80,6 +117,11 @@ base::ProcessHandle BrowserMessageFilter::PeerHandle() {
#endif
}
+
+void BrowserMessageFilter::OnDestruct() const {
+ delete this;
+}
+
bool BrowserMessageFilter::Send(IPC::Message* message) {
if (message->is_sync()) {
// We don't support sending synchronous messages from the browser. If we
@@ -106,10 +148,6 @@ bool BrowserMessageFilter::Send(IPC::Message* message) {
return false;
}
-void BrowserMessageFilter::OverrideThreadForMessage(const IPC::Message& message,
- BrowserThread::ID* thread) {
-}
-
base::TaskRunner* BrowserMessageFilter::OverrideTaskRunnerForMessage(
const IPC::Message& message) {
return NULL;
@@ -141,8 +179,12 @@ bool BrowserMessageFilter::CheckCanDispatchOnUI(const IPC::Message& message,
}
void BrowserMessageFilter::BadMessageReceived() {
- base::KillProcess(PeerHandle(), content::RESULT_CODE_KILLED_BAD_MESSAGE,
- false);
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+
+ if (!command_line->HasSwitch(switches::kDisableKillAfterBadIPC)) {
+ base::KillProcess(PeerHandle(), content::RESULT_CODE_KILLED_BAD_MESSAGE,
+ false);
+ }
}
BrowserMessageFilter::~BrowserMessageFilter() {
@@ -152,17 +194,12 @@ BrowserMessageFilter::~BrowserMessageFilter() {
#endif
}
-bool BrowserMessageFilter::DispatchMessage(const IPC::Message& message) {
- bool message_was_ok = true;
- bool rv = OnMessageReceived(message, &message_was_ok);
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) || rv) <<
- "Must handle messages that were dispatched to another thread!";
- if (!message_was_ok) {
- content::RecordAction(UserMetricsAction("BadMessageTerminate_BMF"));
- BadMessageReceived();
- }
-
- return rv;
+IPC::ChannelProxy::MessageFilter* BrowserMessageFilter::GetFilter() {
+ // We create this on demand so that if a filter is used in a unit test but
+ // never attached to a channel, we don't leak Internal and this;
+ DCHECK(!internal_) << "Should only be called once.";
+ internal_ = new Internal(this);
+ return internal_;
}
} // namespace content
diff --git a/chromium/content/public/browser/browser_message_filter.h b/chromium/content/public/browser/browser_message_filter.h
index c997cc6e05e..ad1f0693790 100644
--- a/chromium/content/public/browser/browser_message_filter.h
+++ b/chromium/content/public/browser/browser_message_filter.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_PUBLIC_BROWSER_BROWSER_MESSAGE_FILTER_H_
#define CONTENT_PUBLIC_BROWSER_BROWSER_MESSAGE_FILTER_H_
+#include "base/memory/ref_counted.h"
#include "base/process/process.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
@@ -19,22 +20,28 @@ class TaskRunner;
}
namespace content {
+struct BrowserMessageFilterTraits;
// Base class for message filters in the browser process. You can receive and
// send messages on any thread.
class CONTENT_EXPORT BrowserMessageFilter
- : public IPC::ChannelProxy::MessageFilter,
+ : public base::RefCountedThreadSafe<
+ BrowserMessageFilter, BrowserMessageFilterTraits>,
public IPC::Sender {
public:
BrowserMessageFilter();
- // IPC::ChannelProxy::MessageFilter methods. If you override them, make sure
- // to call them as well. These are always called on the IO thread.
- virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- // DON'T OVERRIDE THIS! Override the other version below.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ // These match the corresponding IPC::ChannelProxy::MessageFilter methods and
+ // are always called on the IO thread.
+ virtual void OnFilterAdded(IPC::Channel* channel) {}
+ virtual void OnFilterRemoved() {}
+ virtual void OnChannelClosing() {}
+ virtual void OnChannelConnected(int32 peer_pid) {}
+
+ // Called when the message filter is about to be deleted. This gives
+ // derived classes the option of controlling which thread they're deleted
+ // on etc.
+ virtual void OnDestruct() const;
// IPC::Sender implementation. Can be called on any thread. Can't send sync
// messages (since we don't want to block the browser on any other process).
@@ -49,7 +56,7 @@ class CONTENT_EXPORT BrowserMessageFilter
// browser thread, change |thread| to the id of the target thread
virtual void OverrideThreadForMessage(
const IPC::Message& message,
- BrowserThread::ID* thread);
+ BrowserThread::ID* thread) {}
// If you want the message to be dispatched via the SequencedWorkerPool,
// return a non-null task runner which will target tasks accordingly.
@@ -71,6 +78,10 @@ class CONTENT_EXPORT BrowserMessageFilter
// Can be called on any thread, after OnChannelConnected is called.
base::ProcessId peer_pid() const { return peer_pid_; }
+ void set_peer_pid_for_testing(base::ProcessId peer_pid) {
+ peer_pid_ = peer_pid;
+ }
+
// Checks that the given message can be dispatched on the UI thread, depending
// on the platform. If not, returns false and an error ot the sender.
static bool CheckCanDispatchOnUI(const IPC::Message& message,
@@ -84,8 +95,24 @@ class CONTENT_EXPORT BrowserMessageFilter
virtual ~BrowserMessageFilter();
private:
- // Dispatches a message to the derived class.
- bool DispatchMessage(const IPC::Message& message);
+ friend class base::RefCountedThreadSafe<BrowserMessageFilter,
+ BrowserMessageFilterTraits>;
+
+ class Internal;
+ friend class BrowserChildProcessHostImpl;
+ friend class BrowserPpapiHost;
+ friend class RenderProcessHostImpl;
+
+ // This is private because the only classes that need access to it are made
+ // friends above. This is only guaranteed to be valid on creation, after that
+ // this class could outlive the filter.
+ IPC::ChannelProxy::MessageFilter* GetFilter();
+
+ // This implements IPC::ChannelProxy::MessageFilter so that we can hide that
+ // from child classes. Internal keeps a reference to this class, which is why
+ // there's a weak pointer back. This class could outlive Internal based on
+ // what the child class does in its OnDestruct method.
+ Internal* internal_;
IPC::Channel* channel_;
base::ProcessId peer_pid_;
@@ -96,6 +123,12 @@ class CONTENT_EXPORT BrowserMessageFilter
#endif
};
+struct BrowserMessageFilterTraits {
+ static void Destruct(const BrowserMessageFilter* filter) {
+ filter->OnDestruct();
+ }
+};
+
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_BROWSER_MESSAGE_FILTER_H_
diff --git a/chromium/content/public/browser/browser_plugin_guest_delegate.cc b/chromium/content/public/browser/browser_plugin_guest_delegate.cc
index b3dbb15a12d..52577612aa1 100644
--- a/chromium/content/public/browser/browser_plugin_guest_delegate.cc
+++ b/chromium/content/public/browser/browser_plugin_guest_delegate.cc
@@ -15,11 +15,20 @@ bool BrowserPluginGuestDelegate::IsDragAndDropEnabled() {
return false;
}
+bool BrowserPluginGuestDelegate::IsOverridingUserAgent() const {
+ return false;
+}
+
bool BrowserPluginGuestDelegate::RequestPermission(
BrowserPluginPermissionType permission_type,
const base::DictionaryValue& request_info,
- const PermissionResponseCallback& callback) {
+ const PermissionResponseCallback& callback,
+ bool allowed_by_default) {
return false;
}
+GURL BrowserPluginGuestDelegate::ResolveURL(const std::string& src) {
+ return GURL(src);
+}
+
} // namespace content
diff --git a/chromium/content/public/browser/browser_plugin_guest_delegate.h b/chromium/content/public/browser/browser_plugin_guest_delegate.h
index 60838c16496..c0d2ded0290 100644
--- a/chromium/content/public/browser/browser_plugin_guest_delegate.h
+++ b/chromium/content/public/browser/browser_plugin_guest_delegate.h
@@ -26,14 +26,17 @@ class CONTENT_EXPORT BrowserPluginGuestDelegate {
// Add a message to the console.
virtual void AddMessageToConsole(int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id) {}
+ const base::string16& source_id) {}
// Request the delegate to close this guest, and do whatever cleanup it needs
// to do.
virtual void Close() {}
+ // Notification that the embedder has completed attachment.
+ virtual void DidAttach() {}
+
// Informs the delegate that the guest render process is gone. |status|
// indicates whether the guest was killed, crashed, or was terminated
// gracefully.
@@ -46,6 +49,9 @@ class CONTENT_EXPORT BrowserPluginGuestDelegate {
virtual bool IsDragAndDropEnabled();
+ // Returns whether the user agent for the guest is being overridden.
+ virtual bool IsOverridingUserAgent() const;
+
// Notification that a load in the guest resulted in abort. Note that |url|
// may be invalid.
virtual void LoadAbort(bool is_top_level,
@@ -73,7 +79,11 @@ class CONTENT_EXPORT BrowserPluginGuestDelegate {
virtual bool RequestPermission(
BrowserPluginPermissionType permission_type,
const base::DictionaryValue& request_info,
- const PermissionResponseCallback& callback);
+ const PermissionResponseCallback& callback,
+ bool allowed_by_default);
+
+ // Requests resolution of a potentially relative URL.
+ virtual GURL ResolveURL(const std::string& src);
// Notifies that the content size of the guest has changed in autosize mode.
virtual void SizeChanged(const gfx::Size& old_size,
diff --git a/chromium/content/public/browser/browser_thread.h b/chromium/content/public/browser/browser_thread.h
index ab44edab498..55cb62b2235 100644
--- a/chromium/content/public/browser/browser_thread.h
+++ b/chromium/content/public/browser/browser_thread.h
@@ -163,6 +163,10 @@ class CONTENT_EXPORT BrowserThread {
// lookup and is guaranteed unique without you having to come up with a
// unique string), you can access the sequenced worker pool directly via
// GetBlockingPool().
+ //
+ // If you need to PostTaskAndReplyWithResult, use
+ // base::PostTaskAndReplyWithResult() with GetBlockingPool() as the task
+ // runner.
static bool PostBlockingPoolTask(const tracked_objects::Location& from_here,
const base::Closure& task);
static bool PostBlockingPoolTaskAndReply(
diff --git a/chromium/content/public/browser/child_process_data.h b/chromium/content/public/browser/child_process_data.h
index b6693050aba..3683be9c330 100644
--- a/chromium/content/public/browser/child_process_data.h
+++ b/chromium/content/public/browser/child_process_data.h
@@ -18,7 +18,7 @@ struct ChildProcessData {
// The name of the process. i.e. for plugins it might be Flash, while for
// for workers it might be the domain that it's from.
- string16 name;
+ base::string16 name;
// The unique identifier for this child process. This identifier is NOT a
// process ID, and will be unique for all types of child process for
diff --git a/chromium/content/public/browser/child_process_security_policy.h b/chromium/content/public/browser/child_process_security_policy.h
index 2ab2d1add2b..2f462b28a18 100644
--- a/chromium/content/public/browser/child_process_security_policy.h
+++ b/chromium/content/public/browser/child_process_security_policy.h
@@ -51,10 +51,6 @@ class ChildProcessSecurityPolicy {
virtual void GrantCreateReadWriteFile(int child_id,
const base::FilePath& file) = 0;
- // This permission grants creation and write access to a file.
- virtual void GrantCreateWriteFile(int child_id,
- const base::FilePath& file) = 0;
-
// These methods verify whether or not the child process has been granted
// permissions perform these functions on |file|.
@@ -62,21 +58,16 @@ class ChildProcessSecurityPolicy {
// browser should call this method to determine whether the process has the
// capability to upload the requested file.
virtual bool CanReadFile(int child_id, const base::FilePath& file) = 0;
- virtual bool CanWriteFile(int child_id, const base::FilePath& file) = 0;
- virtual bool CanCreateFile(int child_id, const base::FilePath& file) = 0;
- virtual bool CanCreateWriteFile(int child_id, const base::FilePath& file) = 0;
+ virtual bool CanCreateReadWriteFile(int child_id,
+ const base::FilePath& file) = 0;
// Grants read access permission to the given isolated file system
// identified by |filesystem_id|. An isolated file system can be
// created for a set of native files/directories (like dropped files)
// using fileapi::IsolatedContext. A child process needs to be granted
// permission to the file system to access the files in it using
- // file system URL.
- //
- // Note: to grant read access to the content of files you also need
- // to give permission directly to the file paths using GrantReadFile.
- // TODO(kinuko): We should unify this file-level and file-system-level
- // permission when a file is accessed via a file system.
+ // file system URL. You do NOT need to give direct permission to
+ // individual file paths.
//
// Note: files/directories in the same file system share the same
// permission as far as they are accessed via the file system, i.e.
@@ -87,18 +78,18 @@ class ChildProcessSecurityPolicy {
// Grants write access permission to the given isolated file system
// identified by |filesystem_id|. See comments for GrantReadFileSystem
- // for more details. For writing you do NOT need to give direct permission
- // to individual file paths.
+ // for more details. You do NOT need to give direct permission to
+ // individual file paths.
//
// This must be called with a great care as this gives write permission
// to all files/directories included in the file system.
virtual void GrantWriteFileSystem(int child_id,
const std::string& filesystem_id) = 0;
- // Grant create file permission to the given isolated file system identified
- // by |filesystem_id|.
- // See comments for GrantReadFileSystem for more details. For creating you
- // do NOT need to give direct permission to individual file paths.
+ // Grants create file permission to the given isolated file system
+ // identified by |filesystem_id|. See comments for GrantReadFileSystem
+ // for more details. You do NOT need to give direct permission to
+ // individual file paths.
//
// This must be called with a great care as this gives create permission
// within all directories included in the file system.
@@ -106,12 +97,29 @@ class ChildProcessSecurityPolicy {
int child_id,
const std::string& filesystem_id) = 0;
+ // Grants create, read and write access permissions to the given isolated
+ // file system identified by |filesystem_id|. See comments for
+ // GrantReadFileSystem for more details. You do NOT need to give direct
+ // permission to individual file paths.
+ //
+ // This must be called with a great care as this gives create, read and write
+ // permissions to all files/directories included in the file system.
+ virtual void GrantCreateReadWriteFileSystem(
+ int child_id,
+ const std::string& filesystem_id) = 0;
+
// Grants permission to copy-into filesystem |filesystem_id|. 'copy-into'
// is used to allow copying files into the destination filesystem without
// granting more general create and write permissions.
virtual void GrantCopyIntoFileSystem(int child_id,
const std::string& filesystem_id) = 0;
+ // Grants permission to delete from filesystem |filesystem_id|. 'delete-from'
+ // is used to allow deleting files into the destination filesystem without
+ // granting more general create and write permissions.
+ virtual void GrantDeleteFromFileSystem(int child_id,
+ const std::string& filesystem_id) = 0;
+
// Grants the child process the capability to access URLs of the provided
// scheme.
virtual void GrantScheme(int child_id, const std::string& scheme) = 0;
@@ -127,8 +135,12 @@ class ChildProcessSecurityPolicy {
// Returns true if copy-into access has been granted to |filesystem_id|.
virtual bool CanCopyIntoFileSystem(int child_id,
const std::string& filesystem_id) = 0;
+
+ // Returns true if delete-from access has been granted to |filesystem_id|.
+ virtual bool CanDeleteFromFileSystem(int child_id,
+ const std::string& filesystem_id) = 0;
};
-}; // namespace content
+} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_CHILD_PROCESS_SECURITY_POLICY_H_
diff --git a/chromium/content/public/browser/content_browser_client.cc b/chromium/content/public/browser/content_browser_client.cc
index 79364169257..acb9fe849ff 100644
--- a/chromium/content/public/browser/content_browser_client.cc
+++ b/chromium/content/public/browser/content_browser_client.cc
@@ -75,7 +75,7 @@ bool ContentBrowserClient::ShouldTryToUseExistingProcessHost(
return false;
}
-bool ContentBrowserClient::ShouldSwapProcessesForNavigation(
+bool ContentBrowserClient::ShouldSwapBrowsingInstancesForNavigation(
SiteInstance* site_instance,
const GURL& current_url,
const GURL& new_url) {
@@ -141,8 +141,8 @@ bool ContentBrowserClient::AllowSaveLocalState(ResourceContext* context) {
bool ContentBrowserClient::AllowWorkerDatabase(
const GURL& url,
- const string16& name,
- const string16& display_name,
+ const base::string16& name,
+ const base::string16& display_name,
unsigned long estimated_size,
ResourceContext* context,
const std::vector<std::pair<int, int> >& render_views) {
@@ -158,7 +158,7 @@ bool ContentBrowserClient::AllowWorkerFileSystem(
bool ContentBrowserClient::AllowWorkerIndexedDB(
const GURL& url,
- const string16& name,
+ const base::string16& name,
ResourceContext* context,
const std::vector<std::pair<int, int> >& render_views) {
return true;
@@ -203,12 +203,12 @@ MediaObserver* ContentBrowserClient::GetMediaObserver() {
return NULL;
}
-WebKit::WebNotificationPresenter::Permission
+blink::WebNotificationPresenter::Permission
ContentBrowserClient::CheckDesktopNotificationPermission(
const GURL& source_origin,
ResourceContext* context,
int render_process_id) {
- return WebKit::WebNotificationPresenter::PermissionAllowed;
+ return blink::WebNotificationPresenter::PermissionAllowed;
}
bool ContentBrowserClient::CanCreateWindow(
@@ -219,7 +219,7 @@ bool ContentBrowserClient::CanCreateWindow(
const GURL& target_url,
const content::Referrer& referrer,
WindowOpenDisposition disposition,
- const WebKit::WebWindowFeatures& features,
+ const blink::WebWindowFeatures& features,
bool user_gesture,
bool opener_suppressed,
content::ResourceContext* context,
@@ -288,17 +288,24 @@ LocationProvider* ContentBrowserClient::OverrideSystemLocationProvider() {
return NULL;
}
+VibrationProvider* ContentBrowserClient::OverrideVibrationProvider() {
+ return NULL;
+}
+
#if defined(OS_WIN)
const wchar_t* ContentBrowserClient::GetResourceDllName() {
return NULL;
}
#endif
-#if defined(USE_NSS)
-crypto::CryptoModuleBlockingPasswordDelegate*
- ContentBrowserClient::GetCryptoPasswordDelegate(const GURL& url) {
- return NULL;
+bool ContentBrowserClient::IsPluginAllowedToCallRequestOSFileHandle(
+ content::BrowserContext* browser_context,
+ const GURL& url) {
+ return false;
+}
+
+bool ContentBrowserClient::IsPluginAllowedToUseDevChannelAPIs() {
+ return false;
}
-#endif
} // namespace content
diff --git a/chromium/content/public/browser/content_browser_client.h b/chromium/content/public/browser/content_browser_client.h
index f817cb2ae69..639998fa5d9 100644
--- a/chromium/content/public/browser/content_browser_client.h
+++ b/chromium/content/public/browser/content_browser_client.h
@@ -35,7 +35,7 @@ class CommandLine;
class GURL;
struct WebPreferences;
-namespace WebKit {
+namespace blink {
struct WebWindowFeatures;
}
@@ -43,9 +43,6 @@ namespace base {
class DictionaryValue;
class FilePath;
}
-namespace crypto {
-class CryptoModuleBlockingPasswordDelegate;
-}
namespace gfx {
class GLShareGroup;
@@ -95,6 +92,7 @@ class RenderViewHostDelegateView;
class ResourceContext;
class SiteInstance;
class SpeechRecognitionManagerDelegate;
+class VibrationProvider;
class WebContents;
class WebContentsViewDelegate;
class WebContentsViewPort;
@@ -151,6 +149,7 @@ class CONTENT_EXPORT ContentBrowserClient {
// the delegate in the content embedder that will service the guest in the
// content layer. The content layer takes ownership of the |guest_delegate|.
virtual void GuestWebContentsCreated(
+ SiteInstance* guest_site_instance,
WebContents* guest_web_contents,
WebContents* opener_web_contents,
BrowserPluginGuestDelegate** guest_delegate,
@@ -239,11 +238,14 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual void SiteInstanceDeleting(SiteInstance* site_instance) {}
// Returns true if for the navigation from |current_url| to |new_url|
- // in |site_instance|, the process should be swapped (even if we are in a
- // process model that doesn't usually swap).
- virtual bool ShouldSwapProcessesForNavigation(SiteInstance* site_instance,
- const GURL& current_url,
- const GURL& new_url);
+ // in |site_instance|, a new SiteInstance and BrowsingInstance should be
+ // created (even if we are in a process model that doesn't usually swap.)
+ // This forces a process swap and severs script connections with existing
+ // tabs.
+ virtual bool ShouldSwapBrowsingInstancesForNavigation(
+ SiteInstance* site_instance,
+ const GURL& current_url,
+ const GURL& new_url);
// Returns true if the given navigation redirect should cause a renderer
// process swap.
@@ -310,8 +312,8 @@ class CONTENT_EXPORT ContentBrowserClient {
// This is called on the IO thread.
virtual bool AllowWorkerDatabase(
const GURL& url,
- const string16& name,
- const string16& display_name,
+ const base::string16& name,
+ const base::string16& display_name,
unsigned long estimated_size,
ResourceContext* context,
const std::vector<std::pair<int, int> >& render_views);
@@ -329,7 +331,7 @@ class CONTENT_EXPORT ContentBrowserClient {
// This is called on the IO thread.
virtual bool AllowWorkerIndexedDB(
const GURL& url,
- const string16& name,
+ const base::string16& name,
ResourceContext* context,
const std::vector<std::pair<int, int> >& render_views);
@@ -430,7 +432,7 @@ class CONTENT_EXPORT ContentBrowserClient {
// Checks if the given page has permission to show desktop notifications.
// This is called on the IO thread.
- virtual WebKit::WebNotificationPresenter::Permission
+ virtual blink::WebNotificationPresenter::Permission
CheckDesktopNotificationPermission(
const GURL& source_url,
ResourceContext* context,
@@ -461,7 +463,7 @@ class CONTENT_EXPORT ContentBrowserClient {
const GURL& target_url,
const content::Referrer& referrer,
WindowOpenDisposition disposition,
- const WebKit::WebWindowFeatures& features,
+ const blink::WebWindowFeatures& features,
bool user_gesture,
bool opener_suppressed,
content::ResourceContext* context,
@@ -569,8 +571,18 @@ class CONTENT_EXPORT ContentBrowserClient {
// Allows an embedder to return its own LocationProvider implementation.
// Return NULL 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();
+ // Allows an embedder to return its own VibrationProvider implementation.
+ // Return NULL 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 VibrationProvider* OverrideVibrationProvider();
+
// Allow an embedder to provide a share group reimplementation to connect renderer
// GL contexts with the root compositor.
virtual gfx::GLShareGroup* GetInProcessGpuShareGroup() { return 0; }
@@ -595,13 +607,14 @@ class CONTENT_EXPORT ContentBrowserClient {
bool* success) {}
#endif
-#if defined(USE_NSS)
- // Return a delegate to authenticate and unlock |module|.
- // This is called on a worker thread.
- virtual
- crypto::CryptoModuleBlockingPasswordDelegate* GetCryptoPasswordDelegate(
- const GURL& url);
-#endif
+ // Returns true if plugin referred to by the url can use
+ // pp::FileIO::RequestOSFileHandle.
+ virtual bool IsPluginAllowedToCallRequestOSFileHandle(
+ content::BrowserContext* browser_context,
+ const GURL& url);
+
+ // Returns true if dev channel APIs are available for plugins.
+ virtual bool IsPluginAllowedToUseDevChannelAPIs();
};
} // namespace content
diff --git a/chromium/content/public/browser/cookie_crypto_delegate.h b/chromium/content/public/browser/cookie_crypto_delegate.h
new file mode 100644
index 00000000000..92a9a6a35cf
--- /dev/null
+++ b/chromium/content/public/browser/cookie_crypto_delegate.h
@@ -0,0 +1,22 @@
+// 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_PUBLIC_BROWSER_COOKIE_CRYPTO_DELEGATE_H_
+#define CONTENT_PUBLIC_BROWSER_COOKIE_CRYPTO_DELEGATE_H_
+
+namespace content {
+
+// Implements encryption and decryption for the persistent cookie store.
+class CookieCryptoDelegate {
+ public:
+ virtual ~CookieCryptoDelegate() {}
+ virtual bool EncryptString(const std::string& plaintext,
+ std::string* ciphertext) = 0;
+ virtual bool DecryptString(const std::string& ciphertext,
+ std::string* plaintext) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_COOKIE_CRYPTO_DELEGATE_H_
diff --git a/chromium/content/public/browser/cookie_store_factory.h b/chromium/content/public/browser/cookie_store_factory.h
index 22de97d5911..300178ed85c 100644
--- a/chromium/content/public/browser/cookie_store_factory.h
+++ b/chromium/content/public/browser/cookie_store_factory.h
@@ -17,16 +17,26 @@ class SpecialStoragePolicy;
}
namespace content {
+class CookieCryptoDelegate;
// All blocking database accesses will be performed on |background_task_runner|.
-// If background_task_runner is NULL, then a background task runner will be
-// created internally.
+// Callbacks for data load events will be performed on |client_task_runner|.
CONTENT_EXPORT net::CookieStore* CreatePersistentCookieStore(
const base::FilePath& path,
bool restore_old_session_cookies,
quota::SpecialStoragePolicy* storage_policy,
net::CookieMonster::Delegate* cookie_monster_delegate,
- const scoped_refptr<base::SequencedTaskRunner>& background_task_runner);
+ const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
+ const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+ scoped_ptr<CookieCryptoDelegate> crypto_delegate);
+
+// Uses the default client_task_runner and background_task_runner.
+CONTENT_EXPORT net::CookieStore* CreatePersistentCookieStore(
+ const base::FilePath& path,
+ bool restore_old_session_cookies,
+ quota::SpecialStoragePolicy* storage_policy,
+ net::CookieMonster::Delegate* cookie_monster_delegate,
+ scoped_ptr<CookieCryptoDelegate> crypto_delegate);
} // namespace content
diff --git a/chromium/content/public/browser/desktop_media_id.cc b/chromium/content/public/browser/desktop_media_id.cc
new file mode 100644
index 00000000000..a2adfdab5e6
--- /dev/null
+++ b/chromium/content/public/browser/desktop_media_id.cc
@@ -0,0 +1,147 @@
+// 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/public/browser/desktop_media_id.h"
+
+#include <vector>
+
+#include "base/memory/singleton.h"
+#include "base/strings/string_split.h"
+
+#if defined(USE_AURA)
+#include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
+#endif // defined(USE_AURA)
+
+namespace {
+
+#if defined(USE_AURA)
+
+class AuraWindowRegistry : public aura::WindowObserver {
+ public:
+ static AuraWindowRegistry* GetInstance() {
+ return Singleton<AuraWindowRegistry>::get();
+ }
+
+ int RegisterWindow(aura::Window* window) {
+ // First check if an Id is already assigned to the |window|.
+ std::map<aura::Window*, int>::iterator it = window_to_id_map_.find(window);
+ if (it != window_to_id_map_.end()) {
+ return it->second;
+ }
+
+ // If the windows doesn't have an Id yet assign it.
+ int id = next_id_++;
+ window_to_id_map_[window] = id;
+ id_to_window_map_[id] = window;
+ window->AddObserver(this);
+ return id;
+ }
+
+ aura::Window* GetWindowById(int id) {
+ std::map<int, aura::Window*>::iterator it = id_to_window_map_.find(id);
+ return (it != id_to_window_map_.end()) ? it->second : NULL;
+ }
+
+ private:
+ friend struct DefaultSingletonTraits<AuraWindowRegistry>;
+
+ AuraWindowRegistry()
+ : next_id_(0) {
+ }
+ virtual ~AuraWindowRegistry() {}
+
+ // WindowObserver overrides.
+ virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
+ std::map<aura::Window*, int>::iterator it = window_to_id_map_.find(window);
+ DCHECK(it != window_to_id_map_.end());
+ id_to_window_map_.erase(it->second);
+ window_to_id_map_.erase(it);
+ }
+
+ int next_id_;
+ std::map<aura::Window*, int> window_to_id_map_;
+ std::map<int, aura::Window*> id_to_window_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(AuraWindowRegistry);
+};
+
+#endif // defined(USE_AURA)
+
+} // namespace
+
+namespace content {
+
+const char kScreenPrefix[] = "screen";
+const char kWindowPrefix[] = "window";
+const char kAuraWindowPrefix[] = "aura_window";
+
+#if defined(USE_AURA)
+
+// static
+DesktopMediaID DesktopMediaID::RegisterAuraWindow(aura::Window* window) {
+ return DesktopMediaID(
+ TYPE_AURA_WINDOW,
+ AuraWindowRegistry::GetInstance()->RegisterWindow(window));
+}
+
+// static
+aura::Window* DesktopMediaID::GetAuraWindowById(const DesktopMediaID& id) {
+ DCHECK_EQ(id.type, TYPE_AURA_WINDOW);
+ return AuraWindowRegistry::GetInstance()->GetWindowById(id.id);
+}
+
+#endif // defined(USE_AURA)
+
+// static
+DesktopMediaID DesktopMediaID::Parse(const std::string& str) {
+ std::vector<std::string> parts;
+ base::SplitString(str, ':', &parts);
+
+ if (parts.size() != 2)
+ return DesktopMediaID(TYPE_NONE, 0);
+
+ Type type = TYPE_NONE;
+ if (parts[0] == kScreenPrefix) {
+ type = TYPE_SCREEN;
+ } else if (parts[0] == kWindowPrefix) {
+ type = TYPE_WINDOW;
+ } else if (parts[0] == kAuraWindowPrefix) {
+ type = TYPE_AURA_WINDOW;
+ } else {
+ return DesktopMediaID(TYPE_NONE, 0);
+ }
+
+ int64 id;
+ if (!base::StringToInt64(parts[1], &id))
+ return DesktopMediaID(TYPE_NONE, 0);
+
+ return DesktopMediaID(type, id);
+}
+
+std::string DesktopMediaID::ToString() {
+ std::string prefix;
+ switch (type) {
+ case TYPE_NONE:
+ NOTREACHED();
+ return std::string();
+ case TYPE_SCREEN:
+ prefix = kScreenPrefix;
+ break;
+ case TYPE_WINDOW:
+ prefix = kWindowPrefix;
+ break;
+ case TYPE_AURA_WINDOW:
+ prefix = kAuraWindowPrefix;
+ break;
+ }
+ DCHECK(!prefix.empty());
+
+ prefix.append(":");
+ prefix.append(base::Int64ToString(id));
+
+ return prefix;
+}
+
+} // namespace content
diff --git a/chromium/content/public/common/desktop_media_id.h b/chromium/content/public/browser/desktop_media_id.h
index a863872eb12..639a3c8d430 100644
--- a/chromium/content/public/common/desktop_media_id.h
+++ b/chromium/content/public/browser/desktop_media_id.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_COMMON_DESKTOP_MEDIA_ID_H_
-#define CONTENT_PUBLIC_COMMON_DESKTOP_MEDIA_ID_H_
+#ifndef CONTENT_PUBLIC_BROWSER_DESKTOP_MEDIA_ID_H_
+#define CONTENT_PUBLIC_BROWSER_DESKTOP_MEDIA_ID_H_
#include <string>
@@ -12,6 +12,10 @@
#include "base/strings/string_util.h"
#include "content/common/content_export.h"
+namespace aura {
+class Window;
+} // namespace aura
+
namespace content {
// Type used to identify desktop media sources. It's converted to string and
@@ -22,9 +26,20 @@ struct CONTENT_EXPORT DesktopMediaID {
TYPE_NONE,
TYPE_SCREEN,
TYPE_WINDOW,
+ TYPE_AURA_WINDOW,
};
typedef intptr_t Id;
+#if defined(USE_AURA)
+ // Assigns integer identifier to the |window| and returns DesktopMediaID of
+ // type TYPE_AURA_WINDOW that corresponds to that |window|.
+ static DesktopMediaID RegisterAuraWindow(aura::Window* window);
+
+ // For DesktopMediaID of type TYPE_AURA_WINDOW returns the |window| that was
+ // previously registered using RegisterAuraWindow().
+ static aura::Window* GetAuraWindowById(const DesktopMediaID& id);
+#endif // defined(USE_AURA)
+
static DesktopMediaID Parse(const std::string& str);
DesktopMediaID()
@@ -54,4 +69,4 @@ struct CONTENT_EXPORT DesktopMediaID {
} // namespace content
-#endif // CONTENT_PUBLIC_COMMON_DESKTOP_MEDIA_ID_H_
+#endif // CONTENT_PUBLIC_BROWSER_DESKTOP_MEDIA_ID_H_
diff --git a/chromium/content/public/browser/devtools_http_handler.h b/chromium/content/public/browser/devtools_http_handler.h
index 95cf4077eba..4af55059da9 100644
--- a/chromium/content/public/browser/devtools_http_handler.h
+++ b/chromium/content/public/browser/devtools_http_handler.h
@@ -18,7 +18,6 @@ class URLRequestContextGetter;
namespace content {
-class DevToolsAgentHost;
class DevToolsHttpHandlerDelegate;
// This class is used for managing DevTools remote debugging server.
@@ -26,19 +25,6 @@ class DevToolsHttpHandlerDelegate;
// this browser.
class DevToolsHttpHandler {
public:
- // Interface responsible for mapping DevToolsAgentHost instances to/from
- // string identifiers.
- class DevToolsAgentHostBinding {
- public:
- virtual ~DevToolsAgentHostBinding() {}
-
- // Returns the mapping of DevToolsAgentHost to identifier.
- virtual std::string GetIdentifier(DevToolsAgentHost* agent_host) = 0;
-
- // Returns the mapping of identifier to DevToolsAgentHost.
- virtual DevToolsAgentHost* ForIdentifier(const std::string& identifier) = 0;
- };
-
// Returns true if the given protocol version is supported.
CONTENT_EXPORT static bool IsSupportedProtocolVersion(
const std::string& version);
@@ -57,13 +43,8 @@ class DevToolsHttpHandler {
// Automatically destroys the handler instance.
virtual void Stop() = 0;
- // Set the DevToolsAgentHostBinding instance. If no instance is provided the
- // default implementation will be used.
- virtual void SetDevToolsAgentHostBinding(
- DevToolsAgentHostBinding* binding) = 0;
-
- // Returns the URL for the address to debug |render_view_host|.
- virtual GURL GetFrontendURL(DevToolsAgentHost* agent_host) = 0;
+ // Returns the URL for the address to debug |agent_host|.
+ virtual GURL GetFrontendURL() = 0;
protected:
virtual ~DevToolsHttpHandler() {}
diff --git a/chromium/content/public/browser/devtools_http_handler_delegate.h b/chromium/content/public/browser/devtools_http_handler_delegate.h
index 3e1d6412820..2b64a7dd40a 100644
--- a/chromium/content/public/browser/devtools_http_handler_delegate.h
+++ b/chromium/content/public/browser/devtools_http_handler_delegate.h
@@ -16,15 +16,10 @@ class GURL;
namespace content {
-class RenderViewHost;
+class DevToolsTarget;
class DevToolsHttpHandlerDelegate {
public:
- enum TargetType {
- kTargetTypeTab = 0,
- kTargetTypeOther,
- };
-
virtual ~DevToolsHttpHandlerDelegate() {}
// Should return discovery page HTML that should list available tabs
@@ -41,14 +36,15 @@ class DevToolsHttpHandlerDelegate {
// thumbnail.
virtual std::string GetPageThumbnailData(const GURL& url) = 0;
- // Creates new inspectable target and returns its render view host.
- virtual RenderViewHost* CreateNewTarget() = 0;
+ // Creates new inspectable target.
+ virtual scoped_ptr<DevToolsTarget> CreateNewTarget(const GURL& url) = 0;
- // Returns the type of the target.
- virtual TargetType GetTargetType(RenderViewHost*) = 0;
+ typedef std::vector<DevToolsTarget*> TargetList;
+ typedef base::Callback<void(const TargetList&)> TargetCallback;
- // Provides the delegate with an ability to supply a description for views.
- virtual std::string GetViewDescription(content::RenderViewHost*) = 0;
+ // Requests the list of all inspectable targets.
+ // The caller gets the ownership of the returned targets.
+ virtual void EnumerateTargets(TargetCallback callback) = 0;
// Creates named socket for reversed tethering implementation (used with
// remote debugging, primarily for mobile).
diff --git a/chromium/content/public/browser/devtools_target.h b/chromium/content/public/browser/devtools_target.h
new file mode 100644
index 00000000000..3fcac0572f3
--- /dev/null
+++ b/chromium/content/public/browser/devtools_target.h
@@ -0,0 +1,64 @@
+// 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_PUBLIC_BROWSER_DEVTOOLS_TARGET_H_
+#define CONTENT_PUBLIC_BROWSER_DEVTOOLS_TARGET_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class DevToolsAgentHost;
+
+// DevToolsTarget represents an inspectable target and can be used to
+// manipulate the target and query its details.
+// Instantiation and discovery of DevToolsTarget instances is the responsibility
+// of DevToolsHttpHandlerDelegate.
+class DevToolsTarget {
+ public:
+ virtual ~DevToolsTarget() {}
+
+ // Returns the unique target id.
+ virtual std::string GetId() const = 0;
+
+ // Returns the target type.
+ virtual std::string GetType() const = 0;
+
+ // Returns the target title.
+ virtual std::string GetTitle() const = 0;
+
+ // Returns the target description.
+ virtual std::string GetDescription() const = 0;
+
+ // Returns the url associated with this target.
+ virtual GURL GetUrl() const = 0;
+
+ // Returns the favicon url for this target.
+ virtual GURL GetFaviconUrl() const = 0;
+
+ // Returns the time when the target was last active.
+ virtual base::TimeTicks GetLastActivityTime() const = 0;
+
+ // Returns true if the debugger is attached to the target.
+ virtual bool IsAttached() const = 0;
+
+ // Returns the agent host for this target.
+ virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const = 0;
+
+ // Activates the target. Returns false if the operation failed.
+ virtual bool Activate() const = 0;
+
+ // Closes the target. Returns false if the operation failed.
+ virtual bool Close() const = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_DEVTOOLS_TARGET_H_
diff --git a/chromium/content/public/browser/download_manager.h b/chromium/content/public/browser/download_manager.h
index 37c6d09da90..6bb1f35156d 100644
--- a/chromium/content/public/browser/download_manager.h
+++ b/chromium/content/public/browser/download_manager.h
@@ -158,6 +158,12 @@ class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data {
// is too slow, use an AllDownloadItemNotifier to count in-progress items.
virtual int InProgressCount() const = 0;
+ // The number of in progress (including paused) downloads.
+ // Performance note: this loops over all items. If profiling finds that this
+ // is too slow, use an AllDownloadItemNotifier to count in-progress items.
+ // This excludes downloads that are marked as malicious.
+ virtual int NonMaliciousInProgressCount() const = 0;
+
virtual BrowserContext* GetBrowserContext() const = 0;
// Checks whether downloaded files still exist. Updates state of downloads
diff --git a/chromium/content/public/browser/download_save_info.h b/chromium/content/public/browser/download_save_info.h
index 6b7a14a3d40..1f449111f09 100644
--- a/chromium/content/public/browser/download_save_info.h
+++ b/chromium/content/public/browser/download_save_info.h
@@ -27,7 +27,7 @@ struct CONTENT_EXPORT DownloadSaveInfo {
// If non-empty, contains an untrusted filename suggestion. This can't contain
// a path (only a filename), and is only effective if |file_path| is empty.
- string16 suggested_name;
+ base::string16 suggested_name;
// If non-NULL, contains the source data stream for the file contents.
scoped_ptr<net::FileStream> file_stream;
diff --git a/chromium/content/public/browser/download_url_parameters.h b/chromium/content/public/browser/download_url_parameters.h
index a907f092f63..b48bc2a2e15 100644
--- a/chromium/content/public/browser/download_url_parameters.h
+++ b/chromium/content/public/browser/download_url_parameters.h
@@ -89,7 +89,7 @@ class CONTENT_EXPORT DownloadUrlParameters {
void set_file_path(const base::FilePath& file_path) {
save_info_.file_path = file_path;
}
- void set_suggested_name(const string16& suggested_name) {
+ void set_suggested_name(const base::string16& suggested_name) {
save_info_.suggested_name = suggested_name;
}
void set_offset(int64 offset) { save_info_.offset = offset; }
@@ -126,7 +126,9 @@ class CONTENT_EXPORT DownloadUrlParameters {
return resource_context_;
}
const base::FilePath& file_path() const { return save_info_.file_path; }
- const string16& suggested_name() const { return save_info_.suggested_name; }
+ const base::string16& suggested_name() const {
+ return save_info_.suggested_name;
+ }
int64 offset() const { return save_info_.offset; }
const std::string& hash_state() const { return save_info_.hash_state; }
bool prompt() const { return save_info_.prompt_for_save_location; }
diff --git a/chromium/content/public/browser/host_zoom_map.h b/chromium/content/public/browser/host_zoom_map.h
index 0554c1d4f1e..72c9a1fb62f 100644
--- a/chromium/content/public/browser/host_zoom_map.h
+++ b/chromium/content/public/browser/host_zoom_map.h
@@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "base/callback.h"
+#include "base/callback_list.h"
#include "content/common/content_export.h"
namespace content {
@@ -91,11 +92,10 @@ class HostZoomMap {
virtual void SetDefaultZoomLevel(double level) = 0;;
typedef base::Callback<void(const ZoomLevelChange&)> ZoomLevelChangedCallback;
-
+ typedef base::CallbackList<void(const ZoomLevelChange&)>::Subscription
+ Subscription;
// Add and remove zoom level changed callbacks.
- virtual void AddZoomLevelChangedCallback(
- const ZoomLevelChangedCallback& callback) = 0;
- virtual void RemoveZoomLevelChangedCallback(
+ virtual scoped_ptr<Subscription> AddZoomLevelChangedCallback(
const ZoomLevelChangedCallback& callback) = 0;
protected:
diff --git a/chromium/content/public/browser/indexed_db_context.h b/chromium/content/public/browser/indexed_db_context.h
index 1d11a9a6cb1..27c254caf7a 100644
--- a/chromium/content/public/browser/indexed_db_context.h
+++ b/chromium/content/public/browser/indexed_db_context.h
@@ -28,10 +28,8 @@ class IndexedDBContext : public base::RefCountedThreadSafe<IndexedDBContext> {
virtual base::TaskRunner* TaskRunner() const = 0;
// Methods used in response to QuotaManager requests.
- virtual std::vector<GURL> GetAllOrigins() = 0;
virtual std::vector<IndexedDBInfo> GetAllOriginsInfo() = 0;
virtual int64 GetOriginDiskUsage(const GURL& origin_url) = 0;
- virtual base::Time GetOriginLastModified(const GURL& origin_url) = 0;
// Deletes all indexed db files for the given origin.
virtual void DeleteForOrigin(const GURL& origin_url) = 0;
diff --git a/chromium/content/public/browser/javascript_dialog_manager.cc b/chromium/content/public/browser/javascript_dialog_manager.cc
index 0a58d9ffb38..ccc1f1670f4 100644
--- a/chromium/content/public/browser/javascript_dialog_manager.cc
+++ b/chromium/content/public/browser/javascript_dialog_manager.cc
@@ -9,7 +9,7 @@ namespace content {
bool JavaScriptDialogManager::HandleJavaScriptDialog(
WebContents* web_contents,
bool accept,
- const string16* prompt_override) {
+ const base::string16* prompt_override) {
return false;
}
diff --git a/chromium/content/public/browser/javascript_dialog_manager.h b/chromium/content/public/browser/javascript_dialog_manager.h
index 778893d926b..cdc628b5bc5 100644
--- a/chromium/content/public/browser/javascript_dialog_manager.h
+++ b/chromium/content/public/browser/javascript_dialog_manager.h
@@ -23,7 +23,7 @@ class WebContents;
class CONTENT_EXPORT JavaScriptDialogManager {
public:
typedef base::Callback<void(bool /* success */,
- const string16& /* user_input */)>
+ const base::string16& /* user_input */)>
DialogClosedCallback;
// Displays a JavaScript dialog. |did_suppress_message| will not be nil; if
@@ -33,14 +33,14 @@ class CONTENT_EXPORT JavaScriptDialogManager {
const GURL& origin_url,
const std::string& accept_lang,
JavaScriptMessageType javascript_message_type,
- const string16& message_text,
- const string16& default_prompt_text,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
const DialogClosedCallback& callback,
bool* did_suppress_message) = 0;
// Displays a dialog asking the user if they want to leave a page.
virtual void RunBeforeUnloadDialog(WebContents* web_contents,
- const string16& message_text,
+ const base::string16& message_text,
bool is_reload,
const DialogClosedCallback& callback) = 0;
@@ -50,7 +50,7 @@ class CONTENT_EXPORT JavaScriptDialogManager {
// dialog was handled.
virtual bool HandleJavaScriptDialog(WebContents* web_contents,
bool accept,
- const string16* prompt_override);
+ const base::string16* prompt_override);
// Cancels all active and pending dialogs for the given WebContents.
virtual void CancelActiveAndPendingDialogs(WebContents* web_contents) = 0;
diff --git a/chromium/content/public/browser/media_device_id.cc b/chromium/content/public/browser/media_device_id.cc
new file mode 100644
index 00000000000..65ac7e2dc44
--- /dev/null
+++ b/chromium/content/public/browser/media_device_id.cc
@@ -0,0 +1,39 @@
+// 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/public/browser/media_device_id.h"
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "crypto/hmac.h"
+
+namespace content {
+
+std::string GetHMACForMediaDeviceID(const ResourceContext::SaltCallback& sc,
+ const GURL& security_origin,
+ const std::string& raw_unique_id) {
+ DCHECK(security_origin.is_valid());
+ DCHECK(!raw_unique_id.empty());
+ crypto::HMAC hmac(crypto::HMAC::SHA256);
+ const size_t digest_length = hmac.DigestLength();
+ std::vector<uint8> digest(digest_length);
+ std::string salt = sc.Run();
+ bool result = hmac.Init(security_origin.spec()) &&
+ hmac.Sign(raw_unique_id + salt, &digest[0], digest.size());
+ DCHECK(result);
+ return StringToLowerASCII(base::HexEncode(&digest[0], digest.size()));
+}
+
+bool DoesMediaDeviceIDMatchHMAC(const ResourceContext::SaltCallback& sc,
+ const GURL& security_origin,
+ const std::string& device_guid,
+ const std::string& raw_unique_id) {
+ DCHECK(security_origin.is_valid());
+ DCHECK(!raw_unique_id.empty());
+ std::string guid_from_raw_device_id =
+ GetHMACForMediaDeviceID(sc, security_origin, raw_unique_id);
+ return guid_from_raw_device_id == device_guid;
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/media_device_id.h b/chromium/content/public/browser/media_device_id.h
new file mode 100644
index 00000000000..e14809cedd1
--- /dev/null
+++ b/chromium/content/public/browser/media_device_id.h
@@ -0,0 +1,38 @@
+// 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.
+//
+// Media device IDs come in two flavors: The machine-wide unique ID of
+// the device, which is what we use on the browser side, and one-way
+// hashes over the unique ID and a security origin, which we provide
+// to code on the renderer side as per-security-origin IDs.
+
+#ifndef CONTENT_PUBLIC_BROWSER_MEDIA_DEVICE_ID_H_
+#define CONTENT_PUBLIC_BROWSER_MEDIA_DEVICE_ID_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+#include "content/public/browser/resource_context.h"
+#include "url/gurl.h"
+
+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 GURL& 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 GURL& security_origin,
+ const std::string& device_guid,
+ const std::string& raw_unique_id);
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_MEDIA_DEVICE_ID_H_
diff --git a/chromium/content/public/browser/native_web_keyboard_event.h b/chromium/content/public/browser/native_web_keyboard_event.h
index 694222241bf..1585fbd6762 100644
--- a/chromium/content/public/browser/native_web_keyboard_event.h
+++ b/chromium/content/public/browser/native_web_keyboard_event.h
@@ -18,7 +18,7 @@ namespace content {
// Owns a platform specific event; used to pass own and pass event through
// platform independent code.
struct CONTENT_EXPORT NativeWebKeyboardEvent :
- NON_EXPORTED_BASE(public WebKit::WebKeyboardEvent) {
+ NON_EXPORTED_BASE(public blink::WebKeyboardEvent) {
NativeWebKeyboardEvent();
explicit NativeWebKeyboardEvent(gfx::NativeEvent native_event);
@@ -37,7 +37,7 @@ struct CONTENT_EXPORT NativeWebKeyboardEvent :
int state,
double time_stamp_seconds);
#elif defined(OS_ANDROID)
- NativeWebKeyboardEvent(WebKit::WebInputEvent::Type type,
+ NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
int modifiers,
double time_secs,
int keycode,
@@ -45,7 +45,7 @@ struct CONTENT_EXPORT NativeWebKeyboardEvent :
bool is_system_key);
// Takes ownership of android_key_event.
NativeWebKeyboardEvent(jobject android_key_event,
- WebKit::WebInputEvent::Type type,
+ blink::WebInputEvent::Type type,
int modifiers,
double time_secs,
int keycode,
diff --git a/chromium/content/public/browser/navigation_controller.cc b/chromium/content/public/browser/navigation_controller.cc
index f6502a3c524..f0b3f46cc50 100644
--- a/chromium/content/public/browser/navigation_controller.cc
+++ b/chromium/content/public/browser/navigation_controller.cc
@@ -12,6 +12,7 @@ NavigationController::LoadURLParams::LoadURLParams(const GURL& url)
: url(url),
load_type(LOAD_TYPE_DEFAULT),
transition_type(PAGE_TRANSITION_LINK),
+ frame_tree_node_id(-1),
is_renderer_initiated(false),
override_user_agent(UA_OVERRIDE_INHERIT),
browser_initiated_post_data(NULL),
@@ -28,6 +29,7 @@ NavigationController::LoadURLParams::LoadURLParams(
: url(other.url),
load_type(other.load_type),
transition_type(other.transition_type),
+ frame_tree_node_id(other.frame_tree_node_id),
referrer(other.referrer),
extra_headers(other.extra_headers),
is_renderer_initiated(other.is_renderer_initiated),
@@ -46,7 +48,9 @@ NavigationController::LoadURLParams::operator=(
url = other.url;
load_type = other.load_type;
transition_type = other.transition_type;
+ frame_tree_node_id = other.frame_tree_node_id;
referrer = other.referrer;
+ redirect_chain = other.redirect_chain;
extra_headers = other.extra_headers;
is_renderer_initiated = other.is_renderer_initiated;
override_user_agent = other.override_user_agent;
diff --git a/chromium/content/public/browser/navigation_controller.h b/chromium/content/public/browser/navigation_controller.h
index 47f3123afa1..8c0596e7e2b 100644
--- a/chromium/content/public/browser/navigation_controller.h
+++ b/chromium/content/public/browser/navigation_controller.h
@@ -116,9 +116,16 @@ class NavigationController {
// Note the default value in constructor below.
PageTransition transition_type;
+ // The FrameTreeNode ID for the frame to navigate, or -1 for the main frame.
+ int64 frame_tree_node_id;
+
// Referrer for this load. Empty if none.
Referrer referrer;
+ // Any redirect URLs that occurred for this navigation before |url|.
+ // Defaults to an empty vector.
+ std::vector<GURL> redirect_chain;
+
// Extra headers for this load, separated by \n.
std::string extra_headers;
@@ -212,6 +219,8 @@ class NavigationController {
// Active entry --------------------------------------------------------------
+ // THIS IS DEPRECATED. DO NOT USE. Use GetVisibleEntry instead.
+ //
// Returns the active entry, which is the transient entry if any, the pending
// entry if a navigation is in progress or the last committed entry otherwise.
// NOTE: This can be NULL!!
@@ -343,7 +352,7 @@ class NavigationController {
// Random --------------------------------------------------------------------
- // Session storage depends on dom_storage that depends on WebKit::WebString,
+ // Session storage depends on dom_storage that depends on blink::WebString,
// which cannot be used on iOS.
#if !defined(OS_IOS)
// Returns all the SessionStorageNamespace objects that this
@@ -399,12 +408,15 @@ class NavigationController {
// this: E F *G*
// result: A B C *G*
// If there is a pending entry after *G* in |this|, it is also preserved.
+ // If |replace_entry| is true, the current entry in |source| is replaced. So
+ // the result above would be A B *G*.
// This ignores any pending or transient entries in |source|. Callers must
- // ensure that |CanPruneAllButVisible| returns true before calling this, or it
- // will crash.
- virtual void CopyStateFromAndPrune(NavigationController* source) = 0;
+ // ensure that |CanPruneAllButLastCommitted| returns true before calling this,
+ // or it will crash.
+ virtual void CopyStateFromAndPrune(NavigationController* source,
+ bool replace_entry) = 0;
- // Returns whether it is safe to call PruneAllButVisible or
+ // Returns whether it is safe to call PruneAllButLastCommitted or
// CopyStateFromAndPrune. There must be a last committed entry, no transient
// entry, and if there is a pending entry, it must be new and not an existing
// entry.
@@ -420,12 +432,13 @@ class NavigationController {
// sensible place to put the pending entry when it did commit, after all other
// entries are pruned. For example, it could be going back several entries.
// (New pending entries are safe, because they can always commit to the end.)
- virtual bool CanPruneAllButVisible() = 0;
+ virtual bool CanPruneAllButLastCommitted() = 0;
// Removes all the entries except the last committed entry. If there is a new
// pending navigation it is preserved. Callers must ensure
- // |CanPruneAllButVisible| returns true before calling this, or it will crash.
- virtual void PruneAllButVisible() = 0;
+ // |CanPruneAllButLastCommitted| returns true before calling this, or it will
+ // crash.
+ virtual void PruneAllButLastCommitted() = 0;
// Clears all screenshots associated with navigation entries in this
// controller. Useful to reduce memory consumption in low-memory situations.
diff --git a/chromium/content/public/browser/navigation_entry.h b/chromium/content/public/browser/navigation_entry.h
index faeecc7c640..e23773f1a2c 100644
--- a/chromium/content/public/browser/navigation_entry.h
+++ b/chromium/content/public/browser/navigation_entry.h
@@ -25,7 +25,7 @@ struct SSLStatus;
// A NavigationEntry is a data structure that captures all the information
// required to recreate a browsing state. This includes some opaque binary
-// state as provided by the WebContentsImpl as well as some clear text title and
+// state as provided by the WebContents as well as some clear text title and
// URL which is used for our user interface.
class NavigationEntry {
public:
@@ -73,18 +73,17 @@ class NavigationEntry {
// The caller is responsible for detecting when there is no title and
// displaying the appropriate "Untitled" label if this is being displayed to
// the user.
- virtual void SetTitle(const string16& title) = 0;
- virtual const string16& GetTitle() const = 0;
-
- // XXX
- // Content state is an opaque blob created by WebKit that represents the
- // state of the page. This includes form entries and scroll position for each
- // frame. We store it so that we can supply it back to WebKit to restore form
- // state properly when the user goes back and forward.
+ virtual void SetTitle(const base::string16& title) = 0;
+ virtual const base::string16& GetTitle() const = 0;
+
+ // Page state is an opaque blob created by Blink that represents the state of
+ // the page. This includes form entries and scroll position for each frame.
+ // We store it so that we can supply it back to Blink to restore form state
+ // properly when the user goes back and forward.
//
- // WARNING: This state is saved to the file and used to restore previous
- // states. If the format is modified in the future, we should still be able to
- // deal with older versions.
+ // NOTE: This state is saved to disk and used to restore previous states. If
+ // the format is modified in the future, we should still be able to deal with
+ // older versions.
virtual void SetPageState(const PageState& state) = 0;
virtual const PageState& GetPageState() const = 0;
@@ -100,7 +99,7 @@ class NavigationEntry {
// the page if it is available or the URL. |languages| is the list of
// accpeted languages (e.g., prefs::kAcceptLanguages) or empty if proper
// URL formatting isn't needed (e.g., unit tests).
- virtual const string16& GetTitleForDisplay(
+ virtual const base::string16& GetTitleForDisplay(
const std::string& languages) const = 0;
// Returns true if the current tab is in view source mode. This will be false
@@ -193,9 +192,11 @@ class NavigationEntry {
// Set extra data on this NavigationEntry according to the specified |key|.
// This data is not persisted by default.
- virtual void SetExtraData(const std::string& key, const string16& data) = 0;
+ virtual void SetExtraData(const std::string& key,
+ const base::string16& data) = 0;
// If present, fills the |data| present at the specified |key|.
- virtual bool GetExtraData(const std::string& key, string16* data) const = 0;
+ virtual bool GetExtraData(const std::string& key,
+ base::string16* data) const = 0;
// Removes the data at the specified |key|.
virtual void ClearExtraData(const std::string& key) = 0;
diff --git a/chromium/content/public/browser/notification_types.h b/chromium/content/public/browser/notification_types.h
index 69eae612df2..3366f169cb4 100644
--- a/chromium/content/public/browser/notification_types.h
+++ b/chromium/content/public/browser/notification_types.h
@@ -42,6 +42,7 @@ enum NotificationType {
//
// The source will be the navigation controller doing the commit. The
// details will be NavigationController::LoadCommittedDetails.
+ // DEPRECATED: Use WebContentsObserver::NavigationEntryCommitted()
NOTIFICATION_NAV_ENTRY_COMMITTED,
// Indicates that the NavigationController given in the Source has
@@ -72,26 +73,22 @@ enum NotificationType {
// Corresponds to ViewHostMsg_DocumentOnLoadCompletedInMainFrame. The source
// is the WebContents and the details the page_id.
+ // DEPRECATED: Use WebContentsObserver::DocumentOnLoadCompletedInMainFrame()
NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
// A content load is starting. The source will be a
// Source<NavigationController> corresponding to the tab in which the load
// is occurring. No details are expected for this notification.
+ // DEPRECATED: Use WebContentsObserver::DidStartLoading()
NOTIFICATION_LOAD_START,
// A content load has stopped. The source will be a
// Source<NavigationController> corresponding to the tab in which the load
// is occurring. Details in the form of a LoadNotificationDetails object
// are optional.
+ // DEPRECATED: Use WebContentsObserver::DidStopLoading()
NOTIFICATION_LOAD_STOP,
- // Content was loaded from an in-memory cache. The source will be a
- // Source<NavigationController> corresponding to the tab in which the load
- // occurred. Details in the form of a LoadFromMemoryCacheDetails object
- // are provided.
- // DEPRECATED: Use WebContentsObserver::DidLoadResourceFromMemoryCache()
- NOTIFICATION_LOAD_FROM_MEMORY_CACHE,
-
// A response has been received for a resource request. The source will be
// a Source<WebContents> corresponding to the tab in which the request was
// issued. Details in the form of a ResourceRequestDetails object are
@@ -117,12 +114,10 @@ enum NotificationType {
// This notification is sent when a WebContents swaps its render view host
// with another one, possibly changing processes. The source is a
- // Source<WebContents> with a pointer to the WebContents. A
- // NOTIFICATION_WEB_CONTENTS_DISCONNECTED notification is guaranteed before
- // the source pointer becomes junk. Details are the RenderViewHost that
- // has been replaced, or NULL if the old RVH was shut down.
- // DEPRECATED: Use WebContentsObserver::RenderViewHostSwapped()
- NOTIFICATION_WEB_CONTENTS_SWAPPED,
+ // Source<WebContents> with a pointer to the WebContents, details is a
+ // std::pair::<old RenderViewHost, new RenderViewHost>.
+ // DEPRECATED: Use WebContentsObserver::RenderViewHostChanged()
+ NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
// This message is sent after a WebContents is disconnected from the
// renderer process. The source is a Source<WebContents> with a pointer to
@@ -136,13 +131,9 @@ enum NotificationType {
// This notification is sent after WebContents' title is updated. The source
// is a Source<WebContents> with a pointer to the WebContents. The details
// is a std::pair<NavigationEntry*, bool> that contains more information.
+ // DEPRECATED: Use WebContentsObserver::TitleWasSet()
NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
- // Indicates a WebContents has been hidden or restored. The source is
- // a Source<WebContents>. The details is a bool set to true if the new
- // state is visible.
- NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED,
-
// This notification is sent when a WebContents is being destroyed. Any
// object holding a reference to a WebContents can listen to that
// notification to properly reset the reference. The source is a
@@ -175,16 +166,10 @@ enum NotificationType {
// This may get sent along with RENDERER_PROCESS_TERMINATED.
NOTIFICATION_RENDERER_PROCESS_CLOSED,
- // Indicates that a render process has become unresponsive for a period of
+ // Indicates that a RenderWidgetHost has become unresponsive for a period of
// time. The source will be the RenderWidgetHost that corresponds to the
// hung view, and no details are expected.
- NOTIFICATION_RENDERER_PROCESS_HANG,
-
- // This is sent to notify that the RenderViewHost displayed in a WebContents
- // has changed. Source is the NavigationController for which the change
- // happened, details is a
- // std::pair::<old RenderViewHost, new RenderViewHost>).
- NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
+ NOTIFICATION_RENDER_WIDGET_HOST_HANG,
// This is sent when a RenderWidgetHost is being destroyed. The source is
// the RenderWidgetHost, the details are not used.
diff --git a/chromium/content/public/browser/page_navigator.cc b/chromium/content/public/browser/page_navigator.cc
index d6eb79f9090..164bc4e0bc1 100644
--- a/chromium/content/public/browser/page_navigator.cc
+++ b/chromium/content/public/browser/page_navigator.cc
@@ -16,6 +16,7 @@ OpenURLParams::OpenURLParams(
referrer(referrer),
uses_post(false),
source_frame_id(-1),
+ frame_tree_node_id(-1),
disposition(disposition),
transition(transition),
is_renderer_initiated(is_renderer_initiated),
@@ -27,6 +28,7 @@ OpenURLParams::OpenURLParams(
const GURL& url,
const Referrer& referrer,
int64 source_frame_id,
+ int64 frame_tree_node_id,
WindowOpenDisposition disposition,
PageTransition transition,
bool is_renderer_initiated)
@@ -34,6 +36,7 @@ OpenURLParams::OpenURLParams(
referrer(referrer),
uses_post(false),
source_frame_id(source_frame_id),
+ frame_tree_node_id(frame_tree_node_id),
disposition(disposition),
transition(transition),
is_renderer_initiated(is_renderer_initiated),
@@ -44,6 +47,7 @@ OpenURLParams::OpenURLParams(
OpenURLParams::OpenURLParams()
: uses_post(false),
source_frame_id(-1),
+ frame_tree_node_id(-1),
disposition(UNKNOWN),
transition(PageTransitionFromInt(0)),
is_renderer_initiated(false),
diff --git a/chromium/content/public/browser/page_navigator.h b/chromium/content/public/browser/page_navigator.h
index 7a6e788385c..7cd9afbadbf 100644
--- a/chromium/content/public/browser/page_navigator.h
+++ b/chromium/content/public/browser/page_navigator.h
@@ -33,6 +33,7 @@ struct CONTENT_EXPORT OpenURLParams {
OpenURLParams(const GURL& url,
const Referrer& referrer,
int64 source_frame_id,
+ int64 frame_tree_node_id,
WindowOpenDisposition disposition,
PageTransition transition,
bool is_renderer_initiated);
@@ -42,6 +43,9 @@ struct CONTENT_EXPORT OpenURLParams {
GURL url;
Referrer referrer;
+ // Any redirect URLs that occurred for this navigation before |url|.
+ 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.
@@ -56,9 +60,13 @@ struct CONTENT_EXPORT OpenURLParams {
// is terminated by \r\n. May be empty if no extra headers are needed.
std::string extra_headers;
- // The source frame id or -1 to indicate the main frame.
+ // The renderer-specific source frame id or -1 to indicate the main frame.
+ // TODO(creis): This appears to be dead code and should be removed.
int64 source_frame_id;
+ // The browser-global FrameTreeNode ID or -1 to indicate the main frame.
+ int64 frame_tree_node_id;
+
// The disposition requested by the navigation source.
WindowOpenDisposition disposition;
@@ -68,9 +76,6 @@ struct CONTENT_EXPORT OpenURLParams {
// Whether this navigation is initiated by the renderer process.
bool is_renderer_initiated;
- // The override encoding of the URL contents to be opened.
- std::string override_encoding;
-
// Reference to the old request id in case this is a navigation that is being
// transferred to a new renderer.
GlobalRequestID transferred_global_request_id;
diff --git a/chromium/content/public/browser/plugin_service.h b/chromium/content/public/browser/plugin_service.h
index 8c28948d21a..4cf5f988ac0 100644
--- a/chromium/content/public/browser/plugin_service.h
+++ b/chromium/content/public/browser/plugin_service.h
@@ -70,7 +70,7 @@ class PluginService {
// the |context| and renderer IDs. This will report whether the data is stale
// via |is_stale| and returns whether or not the plugin can be found.
virtual bool GetPluginInfo(int render_process_id,
- int render_view_id,
+ int render_frame_id,
ResourceContext* context,
const GURL& url,
const GURL& page_url,
@@ -89,7 +89,7 @@ class PluginService {
// Returns the display name for the plugin identified by the given path. If
// the path doesn't identify a plugin, or the plugin has no display name,
// this will attempt to generate a display name from the path.
- virtual string16 GetPluginDisplayNameByPath(
+ virtual base::string16 GetPluginDisplayNameByPath(
const base::FilePath& plugin_path) = 0;
// Asynchronously loads plugins if necessary and then calls back to the
@@ -159,6 +159,9 @@ class PluginService {
base::string16* plugin_name,
base::string16* plugin_version) = 0;
#endif
+
+ // Returns true iff PPAPI "dev channel" methods are supported.
+ virtual bool PpapiDevChannelSupported() = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/plugin_service_filter.h b/chromium/content/public/browser/plugin_service_filter.h
index 8ff55039a0b..fda9d33c1ec 100644
--- a/chromium/content/public/browser/plugin_service_filter.h
+++ b/chromium/content/public/browser/plugin_service_filter.h
@@ -24,7 +24,7 @@ class PluginServiceFilter {
// Whether |plugin| is available. The client can return false to hide the
// plugin, or return true and optionally change the passed in plugin.
virtual bool IsPluginAvailable(int render_process_id,
- int render_view_id,
+ int render_frame_id,
const void* context,
const GURL& url,
const GURL& policy_url,
diff --git a/chromium/content/public/browser/render_frame_host.h b/chromium/content/public/browser/render_frame_host.h
index 9b6344f3bae..1455f856f24 100644
--- a/chromium/content/public/browser/render_frame_host.h
+++ b/chromium/content/public/browser/render_frame_host.h
@@ -17,6 +17,9 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
public:
virtual ~RenderFrameHost() {}
+ // Returns the route id for this frame.
+ virtual int GetRoutingID() = 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 35627c78b63..76558254871 100644
--- a/chromium/content/public/browser/render_process_host.h
+++ b/chromium/content/public/browser/render_process_host.h
@@ -9,6 +9,7 @@
#include "base/id_map.h"
#include "base/process/kill.h"
#include "base/process/process_handle.h"
+#include "base/supports_user_data.h"
#include "content/common/content_export.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_sender.h"
@@ -18,17 +19,16 @@
class GURL;
struct ViewMsg_SwapOut_Params;
-namespace content {
-class BrowserContext;
-class RenderWidgetHost;
-class StoragePartition;
-}
-
namespace base {
class TimeDelta;
}
namespace content {
+class BrowserContext;
+class BrowserMessageFilter;
+class RenderProcessHostObserver;
+class RenderWidgetHost;
+class StoragePartition;
typedef base::Thread* (*RendererMainThreadFactoryFunction)(
const std::string& id);
@@ -37,7 +37,8 @@ typedef base::Thread* (*RendererMainThreadFactoryFunction)(
// communication channel. There will generally be one RenderProcessHost per
// renderer process.
class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
- public IPC::Listener {
+ public IPC::Listener,
+ public base::SupportsUserData {
public:
typedef IDMap<RenderProcessHost>::iterator iterator;
@@ -55,6 +56,8 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
int exit_code;
};
+ // General functions ---------------------------------------------------------
+
virtual ~RenderProcessHost() {}
// Initialize the new renderer process, returning true on success. This must
@@ -73,6 +76,12 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
virtual void AddRoute(int32 routing_id, IPC::Listener* listener) = 0;
virtual void RemoveRoute(int32 routing_id) = 0;
+ // Add and remove observers for lifecycle events. The order in which
+ // notifications are sent to observers is undefined. Observers must be sure to
+ // remove the observer before they go away.
+ virtual void AddObserver(RenderProcessHostObserver* observer) = 0;
+ virtual void RemoveObserver(RenderProcessHostObserver* observer) = 0;
+
// Called to wait for the next UpdateRect message for the specified render
// widget. Returns true if successful, and the msg out-param will contain a
// copy of the received UpdateRect message.
@@ -160,6 +169,9 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// Returns the renderer channel.
virtual IPC::ChannelProxy* GetChannel() = 0;
+ // Adds a message filter to the IPC channel.
+ virtual void AddFilter(BrowserMessageFilter* filter) = 0;
+
// Try to shutdown the associated render process as fast as possible
virtual bool FastShutdownForPageCount(size_t count) = 0;
diff --git a/chromium/content/public/browser/render_process_host_observer.h b/chromium/content/public/browser/render_process_host_observer.h
new file mode 100644
index 00000000000..221673734fb
--- /dev/null
+++ b/chromium/content/public/browser/render_process_host_observer.h
@@ -0,0 +1,27 @@
+// 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_PUBLIC_BROWSER_RENDER_PROCESS_HOST_OBSERVER_H_
+#define CONTENT_PUBLIC_BROWSER_RENDER_PROCESS_HOST_OBSERVER_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+class RenderProcessHost;
+
+// An observer API implemented by classes which are interested
+// in RenderProcessHost lifecycle events.
+class CONTENT_EXPORT RenderProcessHostObserver {
+ public:
+ // Called when the observed RenderProcessHost itself is destroyed.
+ virtual void RenderProcessHostDestroyed(RenderProcessHost* host) {}
+
+ protected:
+ virtual ~RenderProcessHostObserver() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_RENDER_PROCESS_HOST_OBSERVER_H_
diff --git a/chromium/content/public/browser/render_view_host.h b/chromium/content/public/browser/render_view_host.h
index 8cef3374b01..f2efd36c8ba 100644
--- a/chromium/content/public/browser/render_view_host.h
+++ b/chromium/content/public/browser/render_view_host.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_PUBLIC_BROWSER_RENDER_VIEW_HOST_H_
#define CONTENT_PUBLIC_BROWSER_RENDER_VIEW_HOST_H_
+#include <list>
+
#include "base/callback_forward.h"
#include "content/common/content_export.h"
#include "content/public/browser/render_widget_host.h"
@@ -25,11 +27,15 @@ class FilePath;
class Value;
}
+namespace media {
+class AudioOutputController;
+}
+
namespace ui {
struct SelectedFileInfo;
}
-namespace WebKit {
+namespace blink {
struct WebFindOptions;
struct WebMediaPlayerAction;
struct WebPluginAction;
@@ -73,11 +79,6 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
bool empty_allowed,
GURL* url);
- // Adds/removes a callback called on creation of each new RenderViewHost.
- typedef base::Callback<void(RenderViewHost*)> CreatedCallback;
- static void AddCreatedCallback(const CreatedCallback& callback);
- static void RemoveCreatedCallback(const CreatedCallback& callback);
-
virtual ~RenderViewHost() {}
// Tell the render view to enable a set of javascript bindings. The argument
@@ -101,7 +102,7 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
int callback_context) = 0;
virtual void DesktopNotificationPostDisplay(int callback_context) = 0;
virtual void DesktopNotificationPostError(int notification_id,
- const string16& message) = 0;
+ const base::string16& message) = 0;
virtual void DesktopNotificationPostClose(int notification_id,
bool by_user) = 0;
virtual void DesktopNotificationPostClick(int notification_id) = 0;
@@ -119,7 +120,7 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
// either in a drop or by being cancelled.
virtual void DragSourceEndedAt(
int client_x, int client_y, int screen_x, int screen_y,
- WebKit::WebDragOperation operation) = 0;
+ blink::WebDragOperation operation) = 0;
// Notifies the renderer that a drag and drop operation is in progress, with
// droppable items positioned over the renderer's view.
@@ -135,12 +136,12 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
const DropData& drop_data,
const gfx::Point& client_pt,
const gfx::Point& screen_pt,
- WebKit::WebDragOperationsMask operations_allowed,
+ blink::WebDragOperationsMask operations_allowed,
int key_modifiers) = 0;
virtual void DragTargetDragOver(
const gfx::Point& client_pt,
const gfx::Point& screen_pt,
- WebKit::WebDragOperationsMask operations_allowed,
+ blink::WebDragOperationsMask operations_allowed,
int key_modifiers) = 0;
virtual void DragTargetDragLeave() = 0;
virtual void DragTargetDrop(const gfx::Point& client_pt,
@@ -166,31 +167,31 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
// located at the given point.
virtual void ExecuteMediaPlayerActionAtLocation(
const gfx::Point& location,
- const WebKit::WebMediaPlayerAction& action) = 0;
+ const blink::WebMediaPlayerAction& action) = 0;
// Runs some javascript within the context of a frame in the page.
- virtual void ExecuteJavascriptInWebFrame(const string16& frame_xpath,
- const string16& jscript) = 0;
+ virtual void ExecuteJavascriptInWebFrame(const base::string16& frame_xpath,
+ const base::string16& jscript) = 0;
// Runs some javascript within the context of a frame in the page. The result
// is sent back via the provided callback.
typedef base::Callback<void(const base::Value*)> JavascriptResultCallback;
virtual void ExecuteJavascriptInWebFrameCallbackResult(
- const string16& frame_xpath,
- const string16& jscript,
+ const base::string16& frame_xpath,
+ const base::string16& jscript,
const JavascriptResultCallback& callback) = 0;
// Tells the renderer to perform the given action on the plugin located at
// the given point.
virtual void ExecutePluginActionAtLocation(
- const gfx::Point& location, const WebKit::WebPluginAction& action) = 0;
+ const gfx::Point& location, const blink::WebPluginAction& action) = 0;
// Asks the renderer to exit fullscreen
virtual void ExitFullscreen() = 0;
// Finds text on a page.
- virtual void Find(int request_id, const string16& search_text,
- const WebKit::WebFindOptions& options) = 0;
+ virtual void Find(int request_id, const base::string16& search_text,
+ const blink::WebFindOptions& options) = 0;
// Notifies the renderer that the user has closed the FindInPage window
// (and what action to take regarding the selection).
@@ -222,7 +223,7 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
// Requests the renderer to evaluate an xpath to a frame and insert css
// into that frame's document.
- virtual void InsertCSS(const string16& frame_xpath,
+ virtual void InsertCSS(const base::string16& frame_xpath,
const std::string& css) = 0;
// Returns true if the RenderView is active and has not crashed. Virtual
@@ -252,9 +253,6 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
virtual void SetWebUIProperty(const std::string& name,
const std::string& value) = 0;
- // Set the zoom level for the current main frame
- virtual void SetZoomLevel(double level) = 0;
-
// Changes the zoom level for the current main frame.
virtual void Zoom(PageZoom zoom) = 0;
@@ -273,6 +271,16 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
// Informs the renderer process of a change in timezone.
virtual void NotifyTimezoneChange() = 0;
+ // Retrieves the list of AudioOutputController objects associated
+ // with this object and passes it to the callback you specify, on
+ // the same thread on which you called the method.
+ typedef std::list<scoped_refptr<media::AudioOutputController> >
+ AudioOutputControllerList;
+ typedef base::Callback<void(const AudioOutputControllerList&)>
+ GetAudioOutputControllersCallback;
+ virtual void GetAudioOutputControllers(
+ const GetAudioOutputControllersCallback& callback) const = 0;
+
#if defined(OS_ANDROID)
// Selects and zooms to the find result nearest to the point (x,y)
// defined in find-in-page coordinates.
@@ -280,6 +288,9 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
// Asks the renderer to send the rects of the current find matches.
virtual void RequestFindMatchRects(int current_version) = 0;
+
+ // Disables fullscreen media playback for encrypted video.
+ virtual void DisableFullscreenEncryptedMediaPlayback() = 0;
#endif
private:
diff --git a/chromium/content/public/browser/render_view_host_observer.cc b/chromium/content/public/browser/render_view_host_observer.cc
deleted file mode 100644
index f421bc3a3c7..00000000000
--- a/chromium/content/public/browser/render_view_host_observer.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/browser/render_view_host_observer.h"
-
-#include "content/browser/renderer_host/render_view_host_impl.h"
-
-namespace content {
-
-RenderViewHostObserver::RenderViewHostObserver(RenderViewHost* render_view_host)
- : render_view_host_(static_cast<RenderViewHostImpl*>(render_view_host)),
- routing_id_(render_view_host_->GetRoutingID()) {
- render_view_host_->AddObserver(this);
-}
-
-RenderViewHostObserver::~RenderViewHostObserver() {
- if (render_view_host_)
- render_view_host_->RemoveObserver(this);
-}
-
-void RenderViewHostObserver::RenderViewHostInitialized() {
-}
-
-void RenderViewHostObserver::RenderViewHostDestroyed(RenderViewHost* rvh) {
- delete this;
-}
-
-void RenderViewHostObserver::Navigate(const GURL& url) {
-}
-
-bool RenderViewHostObserver::OnMessageReceived(const IPC::Message& message) {
- return false;
-}
-
-bool RenderViewHostObserver::Send(IPC::Message* message) {
- if (!render_view_host_) {
- delete message;
- return false;
- }
-
- return render_view_host_->Send(message);
-}
-
-RenderViewHost* RenderViewHostObserver::render_view_host() const {
- return render_view_host_;
-}
-
-void RenderViewHostObserver::RenderViewHostDestruction() {
- render_view_host_->RemoveObserver(this);
- RenderViewHost* rvh = render_view_host_;
- render_view_host_ = NULL;
- RenderViewHostDestroyed(rvh);
-}
-
-} // namespace content
diff --git a/chromium/content/public/browser/render_view_host_observer.h b/chromium/content/public/browser/render_view_host_observer.h
deleted file mode 100644
index 932e7153623..00000000000
--- a/chromium/content/public/browser/render_view_host_observer.h
+++ /dev/null
@@ -1,70 +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_RENDER_VIEW_HOST_OBSERVER_H_
-#define CONTENT_PUBLIC_BROWSER_RENDER_VIEW_HOST_OBSERVER_H_
-
-#include "base/compiler_specific.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
-#include "content/common/content_export.h"
-
-class GURL;
-
-namespace content {
-
-class RenderViewHost;
-class RenderViewHostImpl;
-
-// An observer API implemented by classes which want to filter IPC messages from
-// RenderViewHost.
-class CONTENT_EXPORT RenderViewHostObserver : public IPC::Listener,
- public IPC::Sender {
- public:
-
- protected:
- explicit RenderViewHostObserver(RenderViewHost* render_view_host);
-
- virtual ~RenderViewHostObserver();
-
- // Invoked after the RenderViewHost is created in the renderer process. After
- // this point, messages can be sent to it (or to observers in the renderer).
- virtual void RenderViewHostInitialized();
-
- // Invoked when the RenderViewHost is being destroyed. Gives subclasses a
- // chance to cleanup. The base implementation will delete the object.
- // |render_view_host| is passed as an argument since render_view_host() will
- // return NULL once this method enters.
- virtual void RenderViewHostDestroyed(RenderViewHost* render_view_host);
-
- // Notifies that a navigation is starting.
- virtual void Navigate(const GURL& url);
-
- // IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- // IPC::Sender implementation.
- virtual bool Send(IPC::Message* message) OVERRIDE;
-
- RenderViewHost* render_view_host() const;
- int routing_id() { return routing_id_; }
-
- private:
- friend class RenderViewHostImpl;
-
- // Invoked from RenderViewHost. Invokes RenderViewHostDestroyed and NULL out
- // |render_view_host_|.
- void RenderViewHostDestruction();
-
- RenderViewHostImpl* render_view_host_;
-
- // The routing ID of the associated RenderViewHost.
- int routing_id_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderViewHostObserver);
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_RENDER_VIEW_HOST_OBSERVER_H_
diff --git a/chromium/content/public/browser/render_widget_host.h b/chromium/content/public/browser/render_widget_host.h
index e54403c6011..944ecbbcc75 100644
--- a/chromium/content/public/browser/render_widget_host.h
+++ b/chromium/content/public/browser/render_widget_host.h
@@ -27,7 +27,7 @@ namespace gfx {
class Rect;
}
-namespace WebKit {
+namespace blink {
class WebMouseEvent;
struct WebScreenInfo;
}
@@ -113,11 +113,6 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
// Returns the size of all the backing stores used for rendering
static size_t BackingStoreMemorySize();
- // Adds/removes a callback called on creation of each new RenderWidgetHost.
- typedef base::Callback<void(RenderWidgetHost*)> CreatedCallback;
- static void AddCreatedCallback(const CreatedCallback& callback);
- static void RemoveCreatedCallback(const CreatedCallback& callback);
-
// Returns the RenderWidgetHost given its ID and the ID of its render process.
// Returns NULL if the IDs do not correspond to a live RenderWidgetHost.
static RenderWidgetHost* FromID(int32 process_id, int32 routing_id);
@@ -175,7 +170,7 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
// NotifyTextDirection(). (We may receive keydown events even after we
// canceled updating the text direction because of auto-repeat.)
// Note: we cannot undo this change for compatibility with Firefox and IE.
- virtual void UpdateTextDirection(WebKit::WebTextDirection direction) = 0;
+ virtual void UpdateTextDirection(blink::WebTextDirection direction) = 0;
virtual void NotifyTextDirection() = 0;
virtual void Focus() = 0;
@@ -221,9 +216,9 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
// Forwards the given message to the renderer. These are called by
// the view when it has received a message.
virtual void ForwardMouseEvent(
- const WebKit::WebMouseEvent& mouse_event) = 0;
+ const blink::WebMouseEvent& mouse_event) = 0;
virtual void ForwardWheelEvent(
- const WebKit::WebMouseWheelEvent& wheel_event) = 0;
+ const blink::WebMouseWheelEvent& wheel_event) = 0;
virtual void ForwardKeyboardEvent(
const NativeWebKeyboardEvent& key_event) = 0;
@@ -261,11 +256,11 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
// Makes an IPC call to tell webkit to replace the currently selected word
// or a word around the cursor.
- virtual void Replace(const string16& word) = 0;
+ virtual void Replace(const base::string16& word) = 0;
// Makes an IPC call to tell webkit to replace the misspelling in the current
// selection.
- virtual void ReplaceMisspelling(const string16& word) = 0;
+ virtual void ReplaceMisspelling(const base::string16& word) = 0;
// Called to notify the RenderWidget that the resize rect has changed without
// the size of the RenderWidget itself changing.
@@ -298,12 +293,12 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
const KeyPressEventCallback& callback) = 0;
// Add/remove a callback that can handle all kinds of mouse events.
- typedef base::Callback<bool(const WebKit::WebMouseEvent&)> MouseEventCallback;
+ typedef base::Callback<bool(const blink::WebMouseEvent&)> MouseEventCallback;
virtual void AddMouseEventCallback(const MouseEventCallback& callback) = 0;
virtual void RemoveMouseEventCallback(const MouseEventCallback& callback) = 0;
// Get the screen info corresponding to this render widget.
- virtual void GetWebScreenInfo(WebKit::WebScreenInfo* result) = 0;
+ virtual void GetWebScreenInfo(blink::WebScreenInfo* result) = 0;
// Grabs snapshot from renderer side and returns the bitmap to a callback.
// If |src_rect| is empty, the whole contents is copied. This is an expensive
diff --git a/chromium/content/public/browser/render_widget_host_view.h b/chromium/content/public/browser/render_widget_host_view.h
index 6caba6d5798..d815cdfd2b1 100644
--- a/chromium/content/public/browser/render_widget_host_view.h
+++ b/chromium/content/public/browser/render_widget_host_view.h
@@ -105,7 +105,7 @@ class CONTENT_EXPORT RenderWidgetHostView {
virtual void SetShowingContextMenu(bool showing) = 0;
// Returns the currently selected text.
- virtual string16 GetSelectedText() const = 0;
+ virtual base::string16 GetSelectedText() const = 0;
// Subclasses should override this method to do what is appropriate to set
// the custom background for their platform.
diff --git a/chromium/content/public/browser/render_widget_host_view_mac_delegate.h b/chromium/content/public/browser/render_widget_host_view_mac_delegate.h
index 4e79fcbe2fa..6bcf744631d 100644
--- a/chromium/content/public/browser/render_widget_host_view_mac_delegate.h
+++ b/chromium/content/public/browser/render_widget_host_view_mac_delegate.h
@@ -16,6 +16,7 @@
// Like any Objective-C delegate, it is not retained by the delegator object.
// The delegator object will call the -viewGone: method when it is going away.
+@class NSEvent;
@protocol RenderWidgetHostViewMacDelegate
@optional
// Notification that the view is gone.
@@ -41,6 +42,19 @@
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item
isValidItem:(BOOL*)valid;
+@required
+// Notification of when a gesture begins/ends.
+- (void)beginGestureWithEvent:(NSEvent*)event;
+- (void)endGestureWithEvent:(NSEvent*)event;
+
+// This is a low level API which provides touches associated with an event.
+// It is used in conjunction with gestures to determine finger placement
+// on the trackpad.
+- (void)touchesMovedWithEvent:(NSEvent*)event;
+- (void)touchesBeganWithEvent:(NSEvent*)event;
+- (void)touchesCancelledWithEvent:(NSEvent*)event;
+- (void)touchesEndedWithEvent:(NSEvent*)event;
+
@end
#endif // CONTENT_PUBLIC_BROWSER_RENDER_WIDGET_HOST_VIEW_MAC_DELEGATE_H_
diff --git a/chromium/content/public/browser/resource_context.h b/chromium/content/public/browser/resource_context.h
index 191f30ac13b..58eb298987b 100644
--- a/chromium/content/public/browser/resource_context.h
+++ b/chromium/content/public/browser/resource_context.h
@@ -5,7 +5,11 @@
#ifndef CONTENT_PUBLIC_BROWSER_RESOURCE_CONTEXT_H_
#define CONTENT_PUBLIC_BROWSER_RESOURCE_CONTEXT_H_
+#include <string>
+
#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
#include "base/supports_user_data.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
@@ -17,7 +21,9 @@ class AppCacheService;
}
namespace net {
+class ClientCertStore;
class HostResolver;
+class KeygenHandler;
class URLRequestContext;
}
@@ -41,6 +47,17 @@ class CONTENT_EXPORT ResourceContext : public base::SupportsUserData {
// with a BrowsingContext.
virtual net::URLRequestContext* GetRequestContext() = 0;
+ // Get platform ClientCertStore. May return NULL.
+ virtual scoped_ptr<net::ClientCertStore> CreateClientCertStore();
+
+ // Create a platform KeygenHandler and pass it to |callback|. The |callback|
+ // may be run synchronously.
+ virtual void CreateKeygenHandler(
+ uint32 key_size_in_bits,
+ const std::string& challenge_string,
+ const GURL& url,
+ const base::Callback<void(scoped_ptr<net::KeygenHandler>)>& callback);
+
// Returns true if microphone access is allowed for |origin|. Used to
// determine what level of authorization is given to |origin| to access
// resource metadata.
@@ -50,6 +67,30 @@ class CONTENT_EXPORT ResourceContext : public base::SupportsUserData {
// determine what level of authorization is given to |origin| to access
// resource metadata.
virtual bool AllowCameraAccess(const GURL& origin) = 0;
+
+ // 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();
};
} // 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 cc19e9e7b0d..4457de11bef 100644
--- a/chromium/content/public/browser/resource_dispatcher_host_delegate.cc
+++ b/chromium/content/public/browser/resource_dispatcher_host_delegate.cc
@@ -25,10 +25,18 @@ void ResourceDispatcherHostDelegate::RequestBeginning(
ResourceType::Type resource_type,
int child_id,
int route_id,
- bool is_continuation_of_transferred_request,
ScopedVector<ResourceThrottle>* throttles) {
}
+void ResourceDispatcherHostDelegate::WillTransferRequestToNewProcess(
+ int old_child_id,
+ int old_route_id,
+ int old_request_id,
+ int new_child_id,
+ int new_route_id,
+ int new_request_id) {
+}
+
void ResourceDispatcherHostDelegate::DownloadStarting(
net::URLRequest* request,
ResourceContext* resource_context,
diff --git a/chromium/content/public/browser/resource_dispatcher_host_delegate.h b/chromium/content/public/browser/resource_dispatcher_host_delegate.h
index 95e336bb9bc..3bc9b85a927 100644
--- a/chromium/content/public/browser/resource_dispatcher_host_delegate.h
+++ b/chromium/content/public/browser/resource_dispatcher_host_delegate.h
@@ -63,9 +63,17 @@ class CONTENT_EXPORT ResourceDispatcherHostDelegate {
ResourceType::Type resource_type,
int child_id,
int route_id,
- bool is_continuation_of_transferred_request,
ScopedVector<ResourceThrottle>* throttles);
+ // Called if a navigation request is transferred from one process to another.
+ virtual void WillTransferRequestToNewProcess(
+ int old_child_id,
+ int old_route_id,
+ int old_request_id,
+ int new_child_id,
+ int new_route_id,
+ int new_request_id);
+
// Allows an embedder to add additional resource handlers for a download.
// |must_download| is set if the request must be handled as a download.
virtual void DownloadStarting(
diff --git a/chromium/content/public/browser/resource_request_info.h b/chromium/content/public/browser/resource_request_info.h
index 69529750e9b..1c191ab607d 100644
--- a/chromium/content/public/browser/resource_request_info.h
+++ b/chromium/content/public/browser/resource_request_info.h
@@ -34,7 +34,8 @@ class ResourceRequestInfo {
ResourceType::Type resource_type,
ResourceContext* context,
int render_process_id,
- int render_view_id);
+ int render_view_id,
+ bool is_async);
// Returns the associated RenderView for a given process. Returns false, if
// there is no associated RenderView. This method does not rely on the
@@ -62,6 +63,12 @@ class ResourceRequestInfo {
// Unique identifier (within the scope of the child process) for this request.
virtual int GetRequestID() const = 0;
+ // The IPC route identifier of the RenderFrame.
+ // TODO(jam): once all navigation and resource requests are sent between
+ // frames and RenderView/RenderViewHost aren't involved we can remove this and
+ // just use GetRouteID above.
+ virtual int GetRenderFrameID() const = 0;
+
// True if GetFrameID() represents a main frame in the RenderView.
virtual bool IsMainFrame() const = 0;
@@ -79,7 +86,7 @@ class ResourceRequestInfo {
virtual ResourceType::Type GetResourceType() const = 0;
// Returns the associated referrer policy.
- virtual WebKit::WebReferrerPolicy GetReferrerPolicy() const = 0;
+ virtual blink::WebReferrerPolicy GetReferrerPolicy() const = 0;
// Returns the associated page transition type.
virtual PageTransition GetPageTransition() const = 0;
@@ -99,6 +106,9 @@ class ResourceRequestInfo {
// Returns true if this is associated with an asynchronous request.
virtual bool IsAsync() const = 0;
+ // Whether this is a download.
+ virtual bool IsDownload() const = 0;
+
protected:
virtual ~ResourceRequestInfo() {}
};
diff --git a/chromium/content/public/browser/resource_throttle.h b/chromium/content/public/browser/resource_throttle.h
index 4eb3bd7b81b..7bcab8813c1 100644
--- a/chromium/content/public/browser/resource_throttle.h
+++ b/chromium/content/public/browser/resource_throttle.h
@@ -26,6 +26,11 @@ class ResourceThrottle {
virtual void WillRedirectRequest(const GURL& new_url, bool* defer) {}
virtual void WillProcessResponse(bool* defer) {}
+ // Returns the name of the throttle, as a UTF-8 C-string, for logging
+ // purposes. NULL is not allowed. Caller does *not* take ownership of the
+ // returned string.
+ virtual const char* GetNameForLogging() const = 0;
+
void set_controller_for_testing(ResourceController* c) {
controller_ = c;
}
diff --git a/chromium/content/public/browser/session_storage_namespace.h b/chromium/content/public/browser/session_storage_namespace.h
index 6c28a408acb..ec49419ffb3 100644
--- a/chromium/content/public/browser/session_storage_namespace.h
+++ b/chromium/content/public/browser/session_storage_namespace.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/memory/ref_counted.h"
namespace content {
@@ -31,6 +32,48 @@ class SessionStorageNamespace
virtual bool should_persist() const = 0;
+ // SessionStorageNamespaces can be merged. These merges happen based on
+ // a transaction log of operations on the session storage namespace since
+ // this function has been called. Transaction logging will be restricted
+ // to the processes indicated.
+ virtual void AddTransactionLogProcessId(int process_id) = 0;
+
+ // When transaction logging for a process is no longer required, the log
+ // can be removed to save space.
+ virtual void RemoveTransactionLogProcessId(int process_id) = 0;
+
+ // Creates a new session storage namespace which is an alias of the current
+ // instance.
+ virtual SessionStorageNamespace* CreateAlias() = 0;
+
+ enum MergeResult {
+ MERGE_RESULT_NAMESPACE_NOT_FOUND,
+ MERGE_RESULT_NAMESPACE_NOT_ALIAS,
+ MERGE_RESULT_NOT_LOGGING,
+ MERGE_RESULT_NO_TRANSACTIONS,
+ MERGE_RESULT_TOO_MANY_TRANSACTIONS,
+ MERGE_RESULT_NOT_MERGEABLE,
+ MERGE_RESULT_MERGEABLE,
+ MERGE_RESULT_MAX_VALUE
+ };
+
+ typedef base::Callback<void(MergeResult)> MergeResultCallback;
+
+ // Determines whether the transaction log for the process specified can
+ // be merged into the other session storage namespace supplied.
+ // If actually_merge is set to true, the merge will actually be performed,
+ // if possible, and the result of the merge will be returned.
+ // If actually_merge is set to false, the result of whether a merge would be
+ // possible is returned.
+ virtual void Merge(bool actually_merge,
+ int process_id,
+ SessionStorageNamespace* other,
+ const MergeResultCallback& callback) = 0;
+
+ // Indicates whether this SessionStorageNamespace is an alias of |other|,
+ // i.e. whether they point to the same underlying data.
+ virtual bool IsAliasOf(SessionStorageNamespace* other) = 0;
+
protected:
friend class base::RefCountedThreadSafe<SessionStorageNamespace>;
virtual ~SessionStorageNamespace() {}
diff --git a/chromium/content/public/browser/signed_certificate_timestamp_store.h b/chromium/content/public/browser/signed_certificate_timestamp_store.h
new file mode 100644
index 00000000000..753c1ada81d
--- /dev/null
+++ b/chromium/content/public/browser/signed_certificate_timestamp_store.h
@@ -0,0 +1,53 @@
+// 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_PUBLIC_BROWSER_SIGNED_CERTIFICATE_TIMESTAMP_STORE_H_
+#define CONTENT_PUBLIC_BROWSER_SIGNED_CERTIFICATE_TIMESTAMP_STORE_H_
+
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+
+namespace net {
+namespace ct {
+struct SignedCertificateTimestamp;
+} // namespace ct
+} // namespace net
+
+namespace content {
+
+// The purpose of the SignedCertificateTimestampStore is to provide an easy way
+// to store/retrieve SignedCertificateTimestamp objects. When stored,
+// SignedCertificateTimestamp objects are associated with a RenderProcessHost.
+// If all the RenderProcessHosts associated with the SCT have exited, the SCT
+// is removed from the store. This class is used by the SSLManager to keep
+// track of the SCTs associated with loaded resources. It can be accessed from
+// the UI and IO threads (it is thread-safe). Note that the SCT ids will
+// overflow if we register more than 2^32 - 1 SCTs in 1 browsing session (which
+// is highly unlikely to happen).
+class SignedCertificateTimestampStore {
+ public:
+ // Returns the singleton instance of the SignedCertificateTimestampStore.
+ CONTENT_EXPORT static SignedCertificateTimestampStore* GetInstance();
+
+ // Stores the specified SCT and returns the id associated with it. The SCT
+ // is associated with the specified RenderProcessHost.
+ // When all the RenderProcessHosts associated with a SCT have exited, the
+ // SCT is removed from the store.
+ // Note: ids start at 1.
+ virtual int Store(net::ct::SignedCertificateTimestamp* sct,
+ int render_process_host_id) = 0;
+
+ // Tries to retrieve the previously stored SCT associated with the specified
+ // |sct_id|. Returns whether the SCT could be found, and, if |sct| is
+ // non-NULL, copies it in.
+ virtual bool Retrieve(
+ int sct_id, scoped_refptr<net::ct::SignedCertificateTimestamp>* sct) = 0;
+
+ protected:
+ virtual ~SignedCertificateTimestampStore() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_SIGNED_CERTIFICATE_TIMESTAMP_STORE_H_
diff --git a/chromium/content/public/browser/site_instance.h b/chromium/content/public/browser/site_instance.h
index 3755e8fa0de..2cede0abf41 100644
--- a/chromium/content/public/browser/site_instance.h
+++ b/chromium/content/public/browser/site_instance.h
@@ -71,11 +71,12 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
// we use process-per-site and there is an existing process available.
virtual bool HasProcess() const = 0;
- // Returns the current process being used to render pages in this
- // SiteInstance. If the process has not yet been created or has cleanly
- // exited (e.g., when it is not actively being used), then this method will
- // create a new process with a new ID. Note that renderer process crashes
- // leave the current RenderProcessHost (and ID) in place.
+ // 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
+ // 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
diff --git a/chromium/content/public/browser/speech_recognition_manager.h b/chromium/content/public/browser/speech_recognition_manager.h
index 45f21d6ddbe..f72e75fd9b8 100644
--- a/chromium/content/public/browser/speech_recognition_manager.h
+++ b/chromium/content/public/browser/speech_recognition_manager.h
@@ -35,7 +35,7 @@ class SpeechRecognitionManager {
static CONTENT_EXPORT SpeechRecognitionManager* GetInstance();
// Singleton manager setter useful for tests.
- static void CONTENT_EXPORT SetManagerForTests(
+ static void CONTENT_EXPORT SetManagerForTesting(
SpeechRecognitionManager* manager);
// Creates a new recognition session.
@@ -48,9 +48,9 @@ class SpeechRecognitionManager {
// Aborts recognition for an existing session, without providing any result.
virtual void AbortSession(int session_id) = 0;
- // Aborts all sessions for a given listener, without providing any result.
- virtual void AbortAllSessionsForListener(
- SpeechRecognitionEventListener* listener) = 0;
+ // Aborts all sessions for a given render process,
+ // without providing any result.
+ virtual void AbortAllSessionsForRenderProcess(int render_process_id) = 0;
// Aborts all sessions for a given RenderView, without providing any result.
virtual void AbortAllSessionsForRenderView(int render_process_id,
@@ -80,7 +80,7 @@ class SpeechRecognitionManager {
// Returns a human readable string for the model/make of the active audio
// input device for this computer.
- virtual string16 GetAudioInputDeviceModel() = 0;
+ virtual base::string16 GetAudioInputDeviceModel() = 0;
// Invokes the platform provided microphone settings UI in a non-blocking way,
// via the BrowserThread::FILE thread.
diff --git a/chromium/content/public/browser/speech_recognition_session_config.cc b/chromium/content/public/browser/speech_recognition_session_config.cc
index a9e247d0a40..4022fccd80f 100644
--- a/chromium/content/public/browser/speech_recognition_session_config.cc
+++ b/chromium/content/public/browser/speech_recognition_session_config.cc
@@ -15,8 +15,7 @@ SpeechRecognitionSessionConfig::SpeechRecognitionSessionConfig()
filter_profanities(false),
continuous(false),
interim_results(false),
- max_hypotheses(kDefaultMaxHypotheses),
- event_listener(NULL) {
+ max_hypotheses(kDefaultMaxHypotheses) {
}
SpeechRecognitionSessionConfig::~SpeechRecognitionSessionConfig() {
diff --git a/chromium/content/public/browser/speech_recognition_session_config.h b/chromium/content/public/browser/speech_recognition_session_config.h
index dd63582888b..813fbd1056a 100644
--- a/chromium/content/public/browser/speech_recognition_session_config.h
+++ b/chromium/content/public/browser/speech_recognition_session_config.h
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/speech_recognition_session_context.h"
#include "content/public/common/speech_recognition_grammar.h"
@@ -31,7 +32,7 @@ struct CONTENT_EXPORT SpeechRecognitionSessionConfig {
uint32 max_hypotheses;
SpeechRecognitionSessionContext initial_context;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter;
- SpeechRecognitionEventListener* event_listener;
+ base::WeakPtr<SpeechRecognitionEventListener> event_listener;
};
} // namespace content
diff --git a/chromium/content/public/browser/speech_recognition_session_context.cc b/chromium/content/public/browser/speech_recognition_session_context.cc
index f8652888fe8..f362ef34f18 100644
--- a/chromium/content/public/browser/speech_recognition_session_context.cc
+++ b/chromium/content/public/browser/speech_recognition_session_context.cc
@@ -4,12 +4,16 @@
#include "content/public/browser/speech_recognition_session_context.h"
+#include "ipc/ipc_message.h"
+
namespace content {
SpeechRecognitionSessionContext::SpeechRecognitionSessionContext()
: render_process_id(0),
render_view_id(0),
- guest_render_view_id(0),
+ guest_render_view_id(MSG_ROUTING_NONE),
+ embedder_render_process_id(0),
+ embedder_render_view_id(MSG_ROUTING_NONE),
request_id(0),
requested_by_page_element(true) {
}
diff --git a/chromium/content/public/browser/speech_recognition_session_context.h b/chromium/content/public/browser/speech_recognition_session_context.h
index 143773c778c..5606b78f352 100644
--- a/chromium/content/public/browser/speech_recognition_session_context.h
+++ b/chromium/content/public/browser/speech_recognition_session_context.h
@@ -26,9 +26,24 @@ struct CONTENT_EXPORT SpeechRecognitionSessionContext {
int render_process_id;
int render_view_id;
+
// Browser plugin guest's render view id, if this context represents a speech
- // recognition request from an embedder on behalf of the guest.
+ // recognition request from an embedder on behalf of the guest. This is used
+ // for input tag where speech bubble is to be shown.
+ //
+ // TODO(lazyboy): Right now showing bubble from guest does not work, we fall
+ // back to embedder instead, fix this and use
+ // embedder_render_process_id/embedder_render_view_id similar to Web Speech
+ // API below.
int guest_render_view_id;
+
+ // The pair (|embedder_render_process_id|, |embedder_render_view_id|)
+ // represents a Browser plugin guest's embedder. This is filled in if the
+ // session is from a guest Web Speech API. We use these to check if the
+ // embedder (app) is permitted to use audio.
+ int embedder_render_process_id;
+ int embedder_render_view_id;
+
int request_id;
// Determines whether recognition was requested by a page element (in which
diff --git a/chromium/content/public/browser/storage_partition.h b/chromium/content/public/browser/storage_partition.h
index b30ca426f83..579ccbcbb44 100644
--- a/chromium/content/public/browser/storage_partition.h
+++ b/chromium/content/public/browser/storage_partition.h
@@ -26,6 +26,7 @@ class URLRequestContextGetter;
namespace quota {
class QuotaManager;
+class SpecialStoragePolicy;
}
namespace webkit_database {
@@ -97,19 +98,26 @@ class StoragePartition {
const GURL& storage_origin,
net::URLRequestContextGetter* rq_context) = 0;
- // Similar to ClearDataForOrigin(), but deletes all data out of the
- // StoragePartition rather than just the data related to this origin.
- virtual void ClearDataForUnboundedRange(uint32 remove_mask,
- uint32 quota_storage_remove_mask) = 0;
-
- // Similar to ClearDataForOrigin(), but deletes all the data out of the
- // StoragePartion from between the given |begin| and |end| dates rather
- // then just the data related to this origin.
- virtual void ClearDataForRange(uint32 remove_mask,
- uint32 quota_storage_remove_mask,
- const base::Time& begin,
- const base::Time& end,
- const base::Closure& callback) = 0;
+ // A callback type to check if a given origin matches a storage policy.
+ // Can be passed empty/null where used, which means the origin will always
+ // match.
+ typedef base::Callback<bool(const GURL&,
+ quota::SpecialStoragePolicy*)>
+ OriginMatcherFunction;
+
+ // Similar to ClearDataForOrigin().
+ // Deletes all data out fo the StoragePartition if |storage_origin| is NULL.
+ // |origin_matcher| is present if special storage policy is to be handled,
+ // otherwise the callback can be null (base::Callback::is_null() == true).
+ // |callback| is called when data deletion is done or at least the deletion is
+ // scheduled.
+ virtual void ClearData(uint32 remove_mask,
+ uint32 quota_storage_remove_mask,
+ const GURL* storage_origin,
+ const OriginMatcherFunction& origin_matcher,
+ const base::Time begin,
+ const base::Time end,
+ const base::Closure& callback) = 0;
protected:
virtual ~StoragePartition() {}
diff --git a/chromium/content/public/browser/trace_controller.h b/chromium/content/public/browser/trace_controller.h
deleted file mode 100644
index ebcff7faf41..00000000000
--- a/chromium/content/public/browser/trace_controller.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_BROWSER_TRACE_CONTROLLER_H_
-#define CONTENT_PUBLIC_BROWSER_TRACE_CONTROLLER_H_
-
-#include "base/debug/trace_event.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class TraceSubscriber;
-
-// Note: TraceController is going to be deprecated and replaced with
-// TracingController.
-//
-// TraceController is used on the browser processes to enable/disable
-// trace status and collect trace data. Only the browser UI thread is allowed
-// to interact with the TraceController object. All calls on the TraceSubscriber
-// happen on the UI thread.
-class TraceController {
- public:
- CONTENT_EXPORT static TraceController* GetInstance();
-
- // Called by browser process to start tracing events on all processes.
- //
- // Currently only one subscriber is allowed at a time.
- // Tracing begins immediately locally, and asynchronously on child processes
- // as soon as they receive the BeginTracing request.
- //
- // If BeginTracing was already called previously,
- // or if an EndTracingAsync is pending,
- // or if another subscriber is tracing,
- // BeginTracing will return false meaning it failed.
- //
- // |category_patterns| is a comma-delimited list of category wildcards.
- // A category pattern can have an optional '-' prefix to exclude category
- // groups that contain a matching category.
- // All the same rules apply above, so for example, having both included and
- // excluded category patterns in the same list would not be supported.
- //
- // |mode| is the tracing mode being used.
- //
- // Example: BeginTracing("test_MyTest*");
- // Example: BeginTracing("test_MyTest*,test_OtherStuff");
- // Example: BeginTracing("-excluded_category1,-excluded_category2");
- virtual bool BeginTracing(TraceSubscriber* subscriber,
- const std::string& category_patterns,
- base::debug::TraceLog::Options options) = 0;
-
- // Called by browser process to stop tracing events on all processes.
- //
- // Child processes typically are caching trace data and only rarely flush
- // and send trace data back to the browser process. That is because it may be
- // an expensive operation to send the trace data over IPC, and we would like
- // to avoid much runtime overhead of tracing. So, to end tracing, we must
- // asynchronously ask all child processes to flush any pending trace data.
- //
- // Once all child processes have acked the EndTracing request,
- // TraceSubscriber will be called with OnEndTracingComplete.
- //
- // If a previous call to EndTracingAsync is already pending,
- // or if another subscriber is tracing,
- // EndTracingAsync will return false meaning it failed.
- virtual bool EndTracingAsync(TraceSubscriber* subscriber) = 0;
-
- // Get the maximum across processes of trace buffer percent full state.
- // When the TraceBufferPercentFull value is determined,
- // subscriber->OnTraceBufferPercentFullReply is called.
- // When any child process reaches 100% full, the TraceController will end
- // tracing, and call TraceSubscriber::OnEndTracingComplete.
- // GetTraceBufferPercentFullAsync fails in the following conditions:
- // trace is ending or disabled;
- // a previous call to GetTraceBufferPercentFullAsync is pending; or
- // the caller is not the current subscriber.
- virtual bool GetTraceBufferPercentFullAsync(TraceSubscriber* subscriber) = 0;
-
- // |subscriber->OnEventWatchNotification()| will be called every time the
- // given event occurs on any process.
- virtual bool SetWatchEvent(TraceSubscriber* subscriber,
- const std::string& category_name,
- const std::string& event_name) = 0;
-
- // Cancel the watch event. If tracing is enabled, this may race with the
- // watch event notification firing.
- virtual bool CancelWatchEvent(TraceSubscriber* subscriber) = 0;
-
- // Cancel the subscriber so that it will not be called when EndTracingAsync is
- // acked by all child processes. This will also call EndTracingAsync
- // internally if necessary.
- // Safe to call even if caller is not the current subscriber.
- virtual void CancelSubscriber(TraceSubscriber* subscriber) = 0;
-
- // Get set of known category groups. This can change as new code paths are
- // reached. If true is returned, subscriber->OnKnownCategoriesCollected will
- // be called once the categories are retrieved from child processes.
- virtual bool GetKnownCategoryGroupsAsync(TraceSubscriber* subscriber) = 0;
-
- protected:
- virtual ~TraceController() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_TRACE_CONTROLLER_H_
-
diff --git a/chromium/content/public/browser/trace_subscriber.h b/chromium/content/public/browser/trace_subscriber.h
deleted file mode 100644
index 02e9f1cf35d..00000000000
--- a/chromium/content/public/browser/trace_subscriber.h
+++ /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.
-
-#ifndef CONTENT_PUBLIC_BROWSER_TRACE_SUBSCRIBER_H_
-#define CONTENT_PUBLIC_BROWSER_TRACE_SUBSCRIBER_H_
-
-#include <set>
-
-#include "base/memory/ref_counted_memory.h"
-
-namespace content {
-
-// Objects interested in receiving trace data derive from TraceSubscriber. All
-// callbacks occur on the UI thread.
-// See also: trace_message_filter.h
-// See also: child_trace_message_filter.h
-class TraceSubscriber {
- public:
- // Called once after TraceController::EndTracingAsync.
- virtual void OnEndTracingComplete() = 0;
-
- // Called 0 or more times between TraceController::BeginTracing and
- // OnEndTracingComplete. Use base::debug::TraceResultBuffer to convert one or
- // more trace fragments to JSON.
- virtual void OnTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& trace_fragment) = 0;
-
- // Called once after TraceController::GetKnownCategoryGroupsAsync.
- virtual void OnKnownCategoriesCollected(
- const std::set<std::string>& known_categories) {}
-
- virtual void OnTraceBufferPercentFullReply(float percent_full) {}
-
- virtual void OnEventWatchNotification() {}
-
- protected:
- virtual ~TraceSubscriber() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_TRACE_SUBSCRIBER_H_
diff --git a/chromium/content/public/browser/tracing_controller.h b/chromium/content/public/browser/tracing_controller.h
index 18d4355da78..68184a5a844 100644
--- a/chromium/content/public/browser/tracing_controller.h
+++ b/chromium/content/public/browser/tracing_controller.h
@@ -5,7 +5,10 @@
#ifndef CONTENT_PUBLIC_BROWSER_TRACING_CONTROLLER_H_
#define CONTENT_PUBLIC_BROWSER_TRACING_CONTROLLER_H_
-#include "base/debug/trace_event.h"
+#include <set>
+#include <string>
+
+#include "base/callback.h"
#include "content/common/content_export.h"
namespace base {
@@ -23,8 +26,10 @@ class TracingController;
class TracingController {
public:
enum Options {
+ DEFAULT_OPTIONS = 0,
ENABLE_SYSTRACE = 1 << 0,
ENABLE_SAMPLING = 1 << 1,
+ RECORD_CONTINUOUSLY = 1 << 2, // For EnableRecording() only.
};
CONTENT_EXPORT static TracingController* GetInstance();
@@ -37,7 +42,7 @@ class TracingController {
// groups.
typedef base::Callback<void(const std::set<std::string>&)>
GetCategoriesDoneCallback;
- virtual void GetCategories(
+ virtual bool GetCategories(
const GetCategoriesDoneCallback& callback) = 0;
// Start recording on all processes.
@@ -48,8 +53,8 @@ class TracingController {
// Once all child processes have acked to the EnableRecording request,
// EnableRecordingDoneCallback will be called back.
//
- // |filter| is a filter to control what category groups should be traced.
- // A filter can have an optional '-' prefix to exclude category groups
+ // |category_filter| is a filter to control what category groups should be
+ // traced. A filter can have an optional '-' prefix to exclude category groups
// that contain a matching category. Having both included and excluded
// category patterns in the same list would not be supported.
//
@@ -59,8 +64,8 @@ class TracingController {
//
// |options| controls what kind of tracing is enabled.
typedef base::Callback<void()> EnableRecordingDoneCallback;
- virtual void EnableRecording(
- const base::debug::CategoryFilter& filter,
+ virtual bool EnableRecording(
+ const std::string& category_filter,
TracingController::Options options,
const EnableRecordingDoneCallback& callback) = 0;
@@ -75,9 +80,16 @@ class TracingController {
// Once all child processes have acked to the DisableRecording request,
// TracingFileResultCallback will be called back with a file that contains
// the traced data.
- typedef base::Callback<void(scoped_ptr<base::FilePath>)>
- TracingFileResultCallback;
- virtual void DisableRecording(const TracingFileResultCallback& callback) = 0;
+ //
+ // Trace data will be written into |result_file_path| if it is not empty, or
+ // into a temporary file. The actual file path will be passed to |callback| if
+ // it's not null.
+ //
+ // If |result_file_path| is empty and |callback| is null, trace data won't be
+ // written to any file.
+ typedef base::Callback<void(const base::FilePath&)> TracingFileResultCallback;
+ virtual bool DisableRecording(const base::FilePath& result_file_path,
+ const TracingFileResultCallback& callback) = 0;
// Start monitoring on all processes.
//
@@ -87,11 +99,13 @@ class TracingController {
// Once all child processes have acked to the EnableMonitoring request,
// EnableMonitoringDoneCallback will be called back.
//
- // |filter| is a filter to control what category groups should be traced.
+ // |category_filter| is a filter to control what category groups should be
+ // traced.
//
// |options| controls what kind of tracing is enabled.
typedef base::Callback<void()> EnableMonitoringDoneCallback;
- virtual void EnableMonitoring(const base::debug::CategoryFilter& filter,
+ virtual bool EnableMonitoring(
+ const std::string& category_filter,
TracingController::Options options,
const EnableMonitoringDoneCallback& callback) = 0;
@@ -100,13 +114,13 @@ class TracingController {
// Once all child processes have acked to the DisableMonitoring request,
// DisableMonitoringDoneCallback is called back.
typedef base::Callback<void()> DisableMonitoringDoneCallback;
- virtual void DisableMonitoring(
+ virtual bool DisableMonitoring(
const DisableMonitoringDoneCallback& callback) = 0;
// Get the current monitoring configuration.
virtual void GetMonitoringStatus(bool* out_enabled,
- base::debug::CategoryFilter* out_filter,
- TracingController::Options* out_options) = 0;
+ std::string* out_category_filter,
+ TracingController::Options* out_options) = 0;
// Get the current monitoring traced data.
//
@@ -116,12 +130,37 @@ class TracingController {
// to avoid much runtime overhead of tracing. So, to end tracing, we must
// asynchronously ask all child processes to flush any pending trace data.
//
- // Once all child processes have acked to the CaptureCurrentMonitoringSnapshot
+ // Once all child processes have acked to the CaptureMonitoringSnapshot
// request, TracingFileResultCallback will be called back with a file that
// contains the traced data.
- virtual void CaptureCurrentMonitoringSnapshot(
+ //
+ // Trace data will be written into |result_file_path| if it is not empty, or
+ // into a temporary file. The actual file path will be passed to |callback|.
+ //
+ // If |result_file_path| is empty and |callback| is null, trace data won't be
+ // written to any file.
+ virtual bool CaptureMonitoringSnapshot(
+ const base::FilePath& result_file_path,
const TracingFileResultCallback& callback) = 0;
+ // Get the maximum across processes of trace buffer percent full state.
+ // When the TraceBufferPercentFull value is determined, the callback is
+ // called.
+ typedef base::Callback<void(float)> GetTraceBufferPercentFullCallback;
+ virtual bool GetTraceBufferPercentFull(
+ const GetTraceBufferPercentFullCallback& callback) = 0;
+
+ // |callback| will will be called every time the given event occurs on any
+ // process.
+ typedef base::Callback<void()> WatchEventCallback;
+ virtual bool SetWatchEvent(const std::string& category_name,
+ const std::string& event_name,
+ const WatchEventCallback& callback) = 0;
+
+ // Cancel the watch event. If tracing is enabled, this may race with the
+ // watch event callback.
+ virtual bool CancelWatchEvent() = 0;
+
protected:
virtual ~TracingController() {}
};
diff --git a/chromium/content/public/browser/url_data_source.cc b/chromium/content/public/browser/url_data_source.cc
index 669f5c87262..d9506f50cf3 100644
--- a/chromium/content/public/browser/url_data_source.cc
+++ b/chromium/content/public/browser/url_data_source.cc
@@ -52,4 +52,8 @@ bool URLDataSource::ShouldServiceRequest(const net::URLRequest* request) const {
return false;
}
+bool URLDataSource::ShouldServeMimeTypeAsContentTypeHeader() const {
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/public/browser/url_data_source.h b/chromium/content/public/browser/url_data_source.h
index d6ff1e06a68..d93e51e4d87 100644
--- a/chromium/content/public/browser/url_data_source.h
+++ b/chromium/content/public/browser/url_data_source.h
@@ -108,6 +108,13 @@ class CONTENT_EXPORT URLDataSource {
// WebUI scheme support for an embedder.
virtual bool ShouldServiceRequest(const net::URLRequest* request) const;
+ // By default, Content-Type: header is not sent along with the response.
+ // To start sending mime type returned by GetMimeType in HTTP headers,
+ // return true. It is useful when tunneling response served from this data
+ // source programmatically. Or when AppCache is enabled for this source as it
+ // is for chrome-devtools.
+ virtual bool ShouldServeMimeTypeAsContentTypeHeader() const;
+
// Called to inform the source that StartDataRequest() will be called soon.
// Gives the source an opportunity to rewrite |path| to incorporate extra
// information from the URLRequest prior to serving.
diff --git a/chromium/content/public/browser/user_metrics.h b/chromium/content/public/browser/user_metrics.h
index 8b4615a476a..e9480acaea3 100644
--- a/chromium/content/public/browser/user_metrics.h
+++ b/chromium/content/public/browser/user_metrics.h
@@ -9,21 +9,13 @@
#include "base/callback.h"
#include "content/common/content_export.h"
+#include "content/public/common/user_metrics_action.h"
namespace content {
// This module provides some helper functions for logging actions tracked by
// the user metrics system.
-
-// UserMetricsAction exist purely to standardize on the paramters passed to
-// UserMetrics. That way, our toolset can scan the sourcecode reliable for
-// constructors and extract the associated string constants
-struct UserMetricsAction {
- const char* str_;
- explicit UserMetricsAction(const char* str) : str_(str) {}
-};
-
// Record that the user performed an action.
// "Action" here means a user-generated event:
// good: "Reload", "CloseTab", and "IMEInvoked"
@@ -34,7 +26,9 @@ struct UserMetricsAction {
// string literal parameter must be on the same line, e.g.
// content::RecordAction(
// content::UserMetricsAction("my extremely long action name"));
-// because otherwise our processing scripts won't pick up on new actions.
+// This ensures that our processing scripts can associate this action's hash
+// with its metric name. Therefore, it will be possible to retrieve the metric
+// name from the hash later on.
//
// Once a new recorded action is added, run
// tools/metrics/actions/extract_actions.py --hash
@@ -49,7 +43,7 @@ CONTENT_EXPORT void RecordAction(const UserMetricsAction& action);
// not automatically found by the action-processing scripts. It can be used
// when it's a pain to enumerate all possible actions, but if you use this
// you need to also update the rules for extracting known actions in
-// chrome/tools/extract_actions.py.
+// tools/metrics/actions/extract_actions.py.
CONTENT_EXPORT void RecordComputedAction(const std::string& action);
// Called with the action string.
diff --git a/chromium/content/public/browser/utility_process_host.h b/chromium/content/public/browser/utility_process_host.h
index 2cff030e1f7..1f027a8610b 100644
--- a/chromium/content/public/browser/utility_process_host.h
+++ b/chromium/content/public/browser/utility_process_host.h
@@ -55,16 +55,12 @@ class UtilityProcessHost : public IPC::Sender,
// the operation.
virtual void SetExposedDir(const base::FilePath& dir) = 0;
- // Allows a mdns to use network in sandbox.
+ // Perform presandbox initialization for mDNS.
virtual void EnableMDns() = 0;
// Make the process run without a sandbox.
virtual void DisableSandbox() = 0;
- // If the sandbox is being used and we are on Linux, launch the process from
- // the zygote. Can only be used for tasks that do not require FS access.
- virtual void EnableZygote() = 0;
-
// Returns information about the utility child process.
virtual const ChildProcessData& GetData() = 0;
diff --git a/chromium/content/public/browser/web_contents.h b/chromium/content/public/browser/web_contents.h
index 2035404b81b..0f59c773096 100644
--- a/chromium/content/public/browser/web_contents.h
+++ b/chromium/content/public/browser/web_contents.h
@@ -24,6 +24,10 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
+#if defined(OS_ANDROID)
+#include "base/android/scoped_java_ref.h"
+#endif
+
namespace base {
class TimeTicks;
}
@@ -42,6 +46,7 @@ namespace content {
class BrowserContext;
class InterstitialPage;
class PageState;
+class RenderFrameHost;
class RenderProcessHost;
class RenderViewHost;
class RenderWidgetHostView;
@@ -117,13 +122,6 @@ class WebContents : public PageNavigator,
const CreateParams& params,
const SessionStorageNamespaceMap& session_storage_namespace_map);
- // Adds/removes a callback called on creation of each new WebContents.
- typedef base::Callback<void(WebContents*)> CreatedCallback;
- CONTENT_EXPORT static void AddCreatedCallback(
- const CreatedCallback& callback);
- CONTENT_EXPORT static void RemoveCreatedCallback(
- const CreatedCallback& callback);
-
// Returns a WebContents that wraps the RenderViewHost, or NULL if the
// render view host's delegate isn't a WebContents.
CONTENT_EXPORT static WebContents* FromRenderViewHost(
@@ -166,6 +164,9 @@ class WebContents : public PageNavigator,
// these may change over time.
virtual RenderProcessHost* GetRenderProcessHost() const = 0;
+ // Returns the main frame for the currently active view.
+ virtual RenderFrameHost* GetMainFrame() = 0;
+
// Gets the current RenderViewHost for this tab.
virtual RenderViewHost* GetRenderViewHost() const = 0;
@@ -229,7 +230,7 @@ class WebContents : public PageNavigator,
// Returns the current navigation properties, which if a navigation is
// pending may be provisional (e.g., the navigation could result in a
// download, in which case the URL would revert to what it was previously).
- virtual const string16& GetTitle() const = 0;
+ virtual const base::string16& GetTitle() const = 0;
// The max page ID for any page that the current SiteInstance has loaded in
// this WebContents. Page IDs are specific to a given SiteInstance and
@@ -257,7 +258,7 @@ class WebContents : public PageNavigator,
// Return the current load state and the URL associated with it.
virtual const net::LoadStateWithParam& GetLoadState() const = 0;
- virtual const string16& GetLoadStateHost() const = 0;
+ virtual const base::string16& GetLoadStateHost() const = 0;
// Return the upload progress.
virtual uint64 GetUploadSize() const = 0;
@@ -465,6 +466,16 @@ class WebContents : public PageNavigator,
uint32_t max_bitmap_size,
const ImageDownloadCallback& callback) = 0;
+ // Sets the zoom level for the current page and all BrowserPluginGuests
+ // within the page.
+ virtual void SetZoomLevel(double level) = 0;
+
+#if defined(OS_ANDROID)
+ CONTENT_EXPORT static WebContents* FromJavaWebContents(
+ jobject jweb_contents_android);
+ virtual base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() = 0;
+#endif // OS_ANDROID
+
private:
// This interface should only be implemented inside content.
friend class WebContentsImpl;
diff --git a/chromium/content/public/browser/web_contents_delegate.cc b/chromium/content/public/browser/web_contents_delegate.cc
index 924cabb7e2d..63ad65baeab 100644
--- a/chromium/content/public/browser/web_contents_delegate.cc
+++ b/chromium/content/public/browser/web_contents_delegate.cc
@@ -41,9 +41,9 @@ bool WebContentsDelegate::ShouldSuppressDialogs() {
bool WebContentsDelegate::AddMessageToConsole(WebContents* source,
int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id) {
+ const base::string16& source_id) {
return false;
}
@@ -113,7 +113,7 @@ bool WebContentsDelegate::PreHandleKeyboardEvent(
bool WebContentsDelegate::CanDragEnter(
WebContents* source,
const DropData& data,
- WebKit::WebDragOperationsMask operations_allowed) {
+ blink::WebDragOperationsMask operations_allowed) {
return true;
}
@@ -125,7 +125,7 @@ bool WebContentsDelegate::ShouldCreateWebContents(
WebContents* web_contents,
int route_id,
WindowContainerType window_container_type,
- const string16& frame_name,
+ const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
SessionStorageNamespace* session_storage_namespace) {
@@ -146,7 +146,9 @@ bool WebContentsDelegate::IsFullscreenForTabOrPending(
}
content::ColorChooser* WebContentsDelegate::OpenColorChooser(
- WebContents* web_contents, SkColor color) {
+ WebContents* web_contents,
+ SkColor color,
+ const std::vector<ColorSuggestion>& suggestions) {
return NULL;
}
diff --git a/chromium/content/public/browser/web_contents_delegate.h b/chromium/content/public/browser/web_contents_delegate.h
index c660b2a4820..e1319c0a433 100644
--- a/chromium/content/public/browser/web_contents_delegate.h
+++ b/chromium/content/public/browser/web_contents_delegate.h
@@ -21,7 +21,6 @@
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect_f.h"
-#include "ui/gfx/vector2d.h"
class GURL;
@@ -40,6 +39,7 @@ class RenderViewHost;
class SessionStorageNamespace;
class WebContents;
class WebContentsImpl;
+struct ColorSuggestion;
struct ContextMenuParams;
struct DropData;
struct FileChooserParams;
@@ -54,7 +54,7 @@ class Rect;
class Size;
}
-namespace WebKit {
+namespace blink {
class WebLayer;
struct WebWindowFeatures;
}
@@ -182,9 +182,9 @@ class CONTENT_EXPORT WebContentsDelegate {
// will be used for the message.
virtual bool AddMessageToConsole(WebContents* source,
int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id);
+ const base::string16& source_id);
// Tells us that we've finished firing this tab's beforeunload event.
// The proceed bool tells us whether the user chose to proceed closing the
@@ -279,7 +279,7 @@ class CONTENT_EXPORT WebContentsDelegate {
// cancel the operation. This method is used by Chromium Embedded Framework.
virtual bool CanDragEnter(WebContents* source,
const DropData& data,
- WebKit::WebDragOperationsMask operations_allowed);
+ blink::WebDragOperationsMask operations_allowed);
// Render view drag n drop ended.
virtual void DragEnded() {}
@@ -298,7 +298,7 @@ class CONTENT_EXPORT WebContentsDelegate {
WebContents* web_contents,
int route_id,
WindowContainerType window_container_type,
- const string16& frame_name,
+ const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
SessionStorageNamespace* session_storage_namespace);
@@ -307,7 +307,7 @@ class CONTENT_EXPORT WebContentsDelegate {
// typically happens when popups are created.
virtual void WebContentsCreated(WebContents* source_contents,
int64 source_frame_id,
- const string16& frame_name,
+ const base::string16& frame_name,
const GURL& target_url,
WebContents* new_contents) {}
@@ -333,9 +333,13 @@ class CONTENT_EXPORT WebContentsDelegate {
virtual JavaScriptDialogManager* GetJavaScriptDialogManager();
// Called when color chooser should open. Returns the opened color chooser.
- // Ownership of the returned pointer is transferred to the caller.
- virtual ColorChooser* OpenColorChooser(WebContents* web_contents,
- SkColor color);
+ // Returns NULL if we failed to open the color chooser (e.g. when there is a
+ // ColorChooserDialog already open on Windows). Ownership of the returned
+ // pointer is transferred to the caller.
+ virtual ColorChooser* OpenColorChooser(
+ WebContents* web_contents,
+ SkColor color,
+ const std::vector<ColorSuggestion>& suggestions);
// Called when a file selection is to be done.
virtual void RunFileChooser(WebContents* web_contents,
@@ -360,10 +364,6 @@ class CONTENT_EXPORT WebContentsDelegate {
virtual bool IsFullscreenForTabOrPending(
const WebContents* web_contents) const;
- // Called when the renderer has scrolled programmatically.
- virtual void DidProgrammaticallyScroll(WebContents* web_contents,
- const gfx::Vector2d& scroll_point) {}
-
// Called when a Javascript out of memory notification is received.
virtual void JSOutOfMemory(WebContents* web_contents) {}
@@ -373,7 +373,7 @@ class CONTENT_EXPORT WebContentsDelegate {
virtual void RegisterProtocolHandler(WebContents* web_contents,
const std::string& protocol,
const GURL& url,
- const string16& title,
+ const base::string16& title,
bool user_gesture) {}
// Result of string search in the page. This includes the number of matches
@@ -453,6 +453,22 @@ class CONTENT_EXPORT WebContentsDelegate {
virtual gfx::Size GetSizeForNewRenderView(
const WebContents* web_contents) const;
+ // Notification that validation of a form displayed by the |web_contents|
+ // has failed. There can only be one message per |web_contents| at a time.
+ virtual void ShowValidationMessage(WebContents* web_contents,
+ const gfx::Rect& anchor_in_root_view,
+ const string16& main_text,
+ const string16& sub_text) {}
+
+ // Notification that the delegate should hide any showing form validation
+ // message.
+ virtual void HideValidationMessage(WebContents* web_contents) {}
+
+ // Notification that the form element that triggered the validation failure
+ // has moved.
+ virtual void MoveValidationMessage(WebContents* web_contents,
+ const gfx::Rect& anchor_in_root_view) {}
+
protected:
virtual ~WebContentsDelegate();
diff --git a/chromium/content/public/browser/web_contents_observer.cc b/chromium/content/public/browser/web_contents_observer.cc
index 14790293040..fc0fcf253ac 100644
--- a/chromium/content/public/browser/web_contents_observer.cc
+++ b/chromium/content/public/browser/web_contents_observer.cc
@@ -29,6 +29,10 @@ WebContents* WebContentsObserver::web_contents() const {
}
void WebContentsObserver::Observe(WebContents* web_contents) {
+ if (web_contents == web_contents_) {
+ // Early exit to avoid infinite loops if we're in the middle of a callback.
+ return;
+ }
if (web_contents_)
web_contents_->RemoveObserver(this);
web_contents_ = static_cast<WebContentsImpl*>(web_contents);
diff --git a/chromium/content/public/browser/web_contents_observer.h b/chromium/content/public/browser/web_contents_observer.h
index 81dcf381f74..ce6c2da8ccc 100644
--- a/chromium/content/public/browser/web_contents_observer.h
+++ b/chromium/content/public/browser/web_contents_observer.h
@@ -16,6 +16,8 @@
namespace content {
+class NavigationEntry;
+class RenderFrameHost;
class RenderViewHost;
class WebContents;
class WebContentsImpl;
@@ -43,6 +45,13 @@ struct ResourceRequestDetails;
class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
public IPC::Sender {
public:
+ // Called when a RenderFrameHost associated with this WebContents is created.
+ virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) {}
+
+ // Called whenever a RenderFrameHost associated with this WebContents is
+ // deleted.
+ virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) {}
+
// Only one of the two methods below will be called when a RVH is created for
// a WebContents, depending on whether it's for an interstitial or not.
virtual void RenderViewCreated(RenderViewHost* render_view_host) {}
@@ -70,15 +79,20 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// another one, possibly changing processes. The RenderViewHost that has
// been replaced is in |old_render_view_host|, which is NULL if the old RVH
// was shut down.
- virtual void RenderViewHostSwapped(RenderViewHost* old_render_view_host) {}
+ virtual void RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) {}
// This method is invoked after the WebContents decided which RenderViewHost
// to use for the next navigation, but before the navigation starts.
virtual void AboutToNavigateRenderView(
RenderViewHost* render_view_host) {}
- // This method is invoked right after the navigation was initiated.
- virtual void NavigateToPendingEntry(
+ // 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.
+ virtual void DidStartNavigationToPendingEntry(
const GURL& url,
NavigationController::ReloadType reload_type) {}
@@ -120,6 +134,7 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// this signal without a prior DidStartProvisionalLoadForFrame signal.
virtual void DidCommitProvisionalLoadForFrame(
int64 frame_id,
+ const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& url,
PageTransition transition_type,
@@ -127,10 +142,11 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// This method is invoked when the provisional load failed.
virtual void DidFailProvisionalLoad(int64 frame_id,
+ const base::string16& frame_unique_name,
bool is_main_frame,
const GURL& validated_url,
int error_code,
- const string16& error_description,
+ const base::string16& error_description,
RenderViewHost* render_view_host) {}
// If the provisional load corresponded to the main frame, this method is
@@ -145,9 +161,14 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
const LoadCommittedDetails& details,
const FrameNavigateParams& params) {}
- // This method is invoked once the window.document object was created.
+ // 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(int32 page_id) {}
+
// 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.
@@ -171,7 +192,7 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
const GURL& validated_url,
bool is_main_frame,
int error_code,
- const string16& error_description,
+ const base::string16& error_description,
RenderViewHost* render_view_host) {}
// This method is invoked when content was loaded from an in-memory cache.
@@ -209,6 +230,10 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
virtual void FrameDetached(RenderViewHost* render_view_host,
int64 frame_id) {}
+ // This method is invoked when the renderer has completed its first paint
+ // after a non-empty layout.
+ virtual void DidFirstVisuallyNonEmptyPaint(int32 page_id) {}
+
// These two methods correspond to the points in time when the spinner of the
// tab starts and stops spinning.
virtual void DidStartLoading(RenderViewHost* render_view_host) {}
@@ -226,8 +251,14 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// configured to ignore UI events, and an UI event took place.
virtual void DidGetIgnoredUIEvent() {}
- // This method is invoked every time the WebContents becomes visible.
+ // These methods are invoked every time the WebContents changes visibility.
virtual void WasShown() {}
+ virtual void WasHidden() {}
+
+ // This methods is invoked when the title of the WebContents is set. If the
+ // title was explicitly set, |explicit_set| is true, otherwise the title was
+ // synthesized and |explicit_set| is false.
+ virtual void TitleWasSet(NavigationEntry* entry, bool explicit_set) {}
virtual void AppCacheAccessed(const GURL& manifest_url,
bool blocked_by_policy) {}
diff --git a/chromium/content/public/browser/web_contents_view.h b/chromium/content/public/browser/web_contents_view.h
index d0594b7526b..8405945e68e 100644
--- a/chromium/content/public/browser/web_contents_view.h
+++ b/chromium/content/public/browser/web_contents_view.h
@@ -90,6 +90,15 @@ class CONTENT_EXPORT WebContentsView {
// Returns true if overlapping views are allowed, false otherwise.
virtual bool GetAllowOverlappingViews() const = 0;
+
+ // To draw two overlapping web contents view, the underlaying one should
+ // know about the overlaying one. Caller must ensure that |overlay| exists
+ // until |RemoveOverlayView| is called.
+ virtual void SetOverlayView(WebContentsView* overlay,
+ const gfx::Point& offset) = 0;
+
+ // Removes the previously set overlay view.
+ virtual void RemoveOverlayView() = 0;
#endif
};
diff --git a/chromium/content/public/browser/web_drag_dest_delegate.h b/chromium/content/public/browser/web_drag_dest_delegate.h
index cca3d2eadf7..a556b88af0b 100644
--- a/chromium/content/public/browser/web_drag_dest_delegate.h
+++ b/chromium/content/public/browser/web_drag_dest_delegate.h
@@ -55,7 +55,7 @@ class WebDragDestDelegate {
// drag. Not every drag will trigger these.
virtual void OnReceiveDataFromGtk(GtkSelectionData* data) = 0;
virtual void OnReceiveProcessedData(const GURL& url,
- const string16& title) = 0;
+ const base::string16& title) = 0;
#elif defined(USE_AURA)
// Called at the start of every drag to supply the data associated with the
// drag.
diff --git a/chromium/content/public/browser/web_ui.h b/chromium/content/public/browser/web_ui.h
index 3dad85c2a0d..5427673ad43 100644
--- a/chromium/content/public/browser/web_ui.h
+++ b/chromium/content/public/browser/web_ui.h
@@ -41,7 +41,7 @@ class CONTENT_EXPORT WebUI {
// Returns JavaScript code that, when executed, calls the function specified
// by |function_name| with the arguments specified in |arg_list|.
- static string16 GetJavascriptCall(
+ static base::string16 GetJavascriptCall(
const std::string& function_name,
const std::vector<const base::Value*>& arg_list);
@@ -60,8 +60,8 @@ class CONTENT_EXPORT WebUI {
// Gets a custom tab title provided by the Web UI. If there is no title
// override, the string will be empty which should trigger the default title
// behavior for the tab.
- virtual const string16& GetOverriddenTitle() const = 0;
- virtual void OverrideTitle(const string16& title) = 0;
+ virtual const base::string16& GetOverriddenTitle() const = 0;
+ virtual void OverrideTitle(const base::string16& title) = 0;
// Returns the transition type that should be used for link clicks on this
// Web UI. This will default to LINK but may be overridden.
diff --git a/chromium/content/public/browser/web_ui_data_source.h b/chromium/content/public/browser/web_ui_data_source.h
index 8348de36a8f..b5cc6d577ba 100644
--- a/chromium/content/public/browser/web_ui_data_source.h
+++ b/chromium/content/public/browser/web_ui_data_source.h
@@ -30,7 +30,8 @@ class WebUIDataSource {
WebUIDataSource* source);
// Adds a string keyed to its name to our dictionary.
- virtual void AddString(const std::string& name, const string16& value) = 0;
+ virtual void AddString(const std::string& name,
+ const base::string16& value) = 0;
// Adds a string keyed to its name to our dictionary.
virtual void AddString(const std::string& name, const std::string& value) = 0;
diff --git a/chromium/content/public/browser/web_ui_message_handler.h b/chromium/content/public/browser/web_ui_message_handler.h
index 18fdd94b19c..20a60726033 100644
--- a/chromium/content/public/browser/web_ui_message_handler.h
+++ b/chromium/content/public/browser/web_ui_message_handler.h
@@ -46,7 +46,7 @@ class CONTENT_EXPORT WebUIMessageHandler {
double* out_value);
// Extract a string value from a list Value.
- static string16 ExtractStringValue(const base::ListValue* value);
+ static base::string16 ExtractStringValue(const base::ListValue* value);
// This is where subclasses specify which messages they'd like to handle and
// perform any additional initialization.. At this point web_ui() will return
diff --git a/chromium/content/public/browser/worker_service.h b/chromium/content/public/browser/worker_service.h
index 10740faf9b4..7ce2bf4ec1f 100644
--- a/chromium/content/public/browser/worker_service.h
+++ b/chromium/content/public/browser/worker_service.h
@@ -31,7 +31,7 @@ class WorkerService {
struct WorkerInfo {
GURL url;
- string16 name;
+ base::string16 name;
int process_id;
int route_id;
base::ProcessHandle handle;
diff --git a/chromium/content/public/browser/worker_service_observer.h b/chromium/content/public/browser/worker_service_observer.h
index ff6c8ef3ba7..9c1e055c5b8 100644
--- a/chromium/content/public/browser/worker_service_observer.h
+++ b/chromium/content/public/browser/worker_service_observer.h
@@ -15,7 +15,7 @@ namespace content {
class WorkerServiceObserver {
public:
virtual void WorkerCreated(const GURL& url,
- const string16& name,
+ const base::string16& name,
int process_id,
int route_id) {}
virtual void WorkerDestroyed(int process_id, int route_id) {}
diff --git a/chromium/content/public/browser/zygote_host_linux.h b/chromium/content/public/browser/zygote_host_linux.h
index a9798de10dc..77cc00b2fb1 100644
--- a/chromium/content/public/browser/zygote_host_linux.h
+++ b/chromium/content/public/browser/zygote_host_linux.h
@@ -38,12 +38,6 @@ class ZygoteHost {
// likely to be killed by the OOM killer.
virtual void AdjustRendererOOMScore(base::ProcessHandle process_handle,
int score) = 0;
-
- // Adjust the point at which the low memory notifier in the kernel tells
- // us that we're low on memory. When there is less than |margin_mb| left,
- // then the notifier will notify us. Set |margin_mb| to -1 to turn off
- // low memory notification altogether.
- virtual void AdjustLowMemoryMargin(int64 margin_mb) = 0;
};
} // namespace content
diff --git a/chromium/content/public/common/browser_plugin_permission_type.h b/chromium/content/public/common/browser_plugin_permission_type.h
index 8df6c3fe419..257b3913d01 100644
--- a/chromium/content/public/common/browser_plugin_permission_type.h
+++ b/chromium/content/public/common/browser_plugin_permission_type.h
@@ -28,7 +28,9 @@ enum BrowserPluginPermissionType {
// Note: Even through dialogs do not use the permission API, the dialog API
// is sufficiently similiar that it's convenient to consider it a permission
// type for code reuse.
- BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG
+ BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG,
+
+ BROWSER_PLUGIN_PERMISSION_TYPE_CONTENT_END,
};
#endif // CONTENT_COMMON_BROWSER_PLUGIN_PERMISSION_TYPE_H_
diff --git a/chromium/content/public/common/color_suggestion.cc b/chromium/content/public/common/color_suggestion.cc
new file mode 100644
index 00000000000..0d3653808da
--- /dev/null
+++ b/chromium/content/public/common/color_suggestion.cc
@@ -0,0 +1,16 @@
+// 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/public/common/color_suggestion.h"
+
+#include "third_party/WebKit/public/web/WebColorSuggestion.h"
+
+namespace content {
+
+ColorSuggestion::ColorSuggestion(const blink::WebColorSuggestion& suggestion)
+ : color(suggestion.color),
+ label(suggestion.label) {
+}
+
+} // namespace content
diff --git a/chromium/content/public/common/color_suggestion.h b/chromium/content/public/common/color_suggestion.h
new file mode 100644
index 00000000000..dcb1a4efe18
--- /dev/null
+++ b/chromium/content/public/common/color_suggestion.h
@@ -0,0 +1,30 @@
+// 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_PUBLIC_COMMON_COLOR_SUGGESTION_H_
+#define CONTENT_PUBLIC_COMMON_COLOR_SUGGESTION_H_
+
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace blink {
+struct WebColorSuggestion;
+}
+
+namespace content {
+
+// Container for information about datalist suggestion for the color input
+// control.
+struct CONTENT_EXPORT ColorSuggestion {
+ ColorSuggestion() {}
+ explicit ColorSuggestion(const blink::WebColorSuggestion& suggestion);
+
+ SkColor color;
+ base::string16 label;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_COLOR_SUGGESTION_H_
diff --git a/chromium/content/public/common/common_param_traits.cc b/chromium/content/public/common/common_param_traits.cc
index f2a5c8a0e9d..4e5d92b8522 100644
--- a/chromium/content/public/common/common_param_traits.cc
+++ b/chromium/content/public/common/common_param_traits.cc
@@ -7,6 +7,7 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/page_state.h"
#include "content/public/common/referrer.h"
+#include "content/public/common/url_utils.h"
#include "net/base/host_port_pair.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/rect.h"
@@ -50,7 +51,7 @@ struct SkBitmap_Data {
namespace IPC {
void ParamTraits<GURL>::Write(Message* m, const GURL& p) {
- DCHECK(p.possibly_invalid_spec().length() <= content::kMaxURLChars);
+ DCHECK(p.possibly_invalid_spec().length() <= content::GetMaxURLChars());
// Beware of print-parse inconsistency which would change an invalid
// URL into a valid one. Ideally, the message would contain this flag
@@ -69,7 +70,7 @@ void ParamTraits<GURL>::Write(Message* m, const GURL& p) {
bool ParamTraits<GURL>::Read(const Message* m, PickleIterator* iter, GURL* p) {
std::string s;
- if (!m->ReadString(iter, &s) || s.length() > content::kMaxURLChars) {
+ if (!m->ReadString(iter, &s) || s.length() > content::GetMaxURLChars()) {
*p = GURL();
return false;
}
@@ -192,19 +193,21 @@ void ParamTraits<gfx::PointF>::Log(const gfx::PointF& v, std::string* l) {
void ParamTraits<gfx::Size>::Write(Message* m, const gfx::Size& p) {
DCHECK_GE(p.width(), 0);
DCHECK_GE(p.height(), 0);
- m->WriteInt(p.width());
- m->WriteInt(p.height());
+ int values[2] = { p.width(), p.height() };
+ m->WriteBytes(&values, sizeof(int) * 2);
}
bool ParamTraits<gfx::Size>::Read(const Message* m,
PickleIterator* iter,
gfx::Size* r) {
- int w, h;
- if (!m->ReadInt(iter, &w) || w < 0 ||
- !m->ReadInt(iter, &h) || h < 0)
+ const char* char_values;
+ if (!m->ReadBytes(iter, &char_values, sizeof(int) * 2))
return false;
- r->set_width(w);
- r->set_height(h);
+ const int* values = reinterpret_cast<const int*>(char_values);
+ if (values[0] < 0 || values[1] < 0)
+ return false;
+ r->set_width(values[0]);
+ r->set_height(values[1]);
return true;
}
@@ -213,19 +216,19 @@ void ParamTraits<gfx::Size>::Log(const gfx::Size& p, std::string* l) {
}
void ParamTraits<gfx::SizeF>::Write(Message* m, const gfx::SizeF& p) {
- ParamTraits<float>::Write(m, p.width());
- ParamTraits<float>::Write(m, p.height());
+ float values[2] = { p.width(), p.height() };
+ m->WriteBytes(&values, sizeof(float) * 2);
}
bool ParamTraits<gfx::SizeF>::Read(const Message* m,
PickleIterator* iter,
- gfx::SizeF* p) {
- float w, h;
- if (!ParamTraits<float>::Read(m, iter, &w) ||
- !ParamTraits<float>::Read(m, iter, &h))
+ gfx::SizeF* r) {
+ const char* char_values;
+ if (!m->ReadBytes(iter, &char_values, sizeof(float) * 2))
return false;
- p->set_width(w);
- p->set_height(h);
+ const float* values = reinterpret_cast<const float*>(char_values);
+ r->set_width(values[0]);
+ r->set_height(values[1]);
return true;
}
@@ -233,20 +236,20 @@ void ParamTraits<gfx::SizeF>::Log(const gfx::SizeF& p, std::string* l) {
l->append(base::StringPrintf("(%f, %f)", p.width(), p.height()));
}
-void ParamTraits<gfx::Vector2d>::Write(Message* m, const gfx::Vector2d& v) {
- m->WriteInt(v.x());
- m->WriteInt(v.y());
+void ParamTraits<gfx::Vector2d>::Write(Message* m, const gfx::Vector2d& p) {
+ int values[2] = { p.x(), p.y() };
+ m->WriteBytes(&values, sizeof(int) * 2);
}
bool ParamTraits<gfx::Vector2d>::Read(const Message* m,
PickleIterator* iter,
gfx::Vector2d* r) {
- int x, y;
- if (!m->ReadInt(iter, &x) ||
- !m->ReadInt(iter, &y))
+ const char* char_values;
+ if (!m->ReadBytes(iter, &char_values, sizeof(int) * 2))
return false;
- r->set_x(x);
- r->set_y(y);
+ const int* values = reinterpret_cast<const int*>(char_values);
+ r->set_x(values[0]);
+ r->set_y(values[1]);
return true;
}
@@ -254,20 +257,20 @@ void ParamTraits<gfx::Vector2d>::Log(const gfx::Vector2d& v, std::string* l) {
l->append(base::StringPrintf("(%d, %d)", v.x(), v.y()));
}
-void ParamTraits<gfx::Vector2dF>::Write(Message* m, const gfx::Vector2dF& v) {
- ParamTraits<float>::Write(m, v.x());
- ParamTraits<float>::Write(m, v.y());
+void ParamTraits<gfx::Vector2dF>::Write(Message* m, const gfx::Vector2dF& p) {
+ float values[2] = { p.x(), p.y() };
+ m->WriteBytes(&values, sizeof(float) * 2);
}
bool ParamTraits<gfx::Vector2dF>::Read(const Message* m,
PickleIterator* iter,
gfx::Vector2dF* r) {
- float x, y;
- if (!ParamTraits<float>::Read(m, iter, &x) ||
- !ParamTraits<float>::Read(m, iter, &y))
+ const char* char_values;
+ if (!m->ReadBytes(iter, &char_values, sizeof(float) * 2))
return false;
- r->set_x(x);
- r->set_y(y);
+ const float* values = reinterpret_cast<const float*>(char_values);
+ r->set_x(values[0]);
+ r->set_y(values[1]);
return true;
}
@@ -276,20 +279,20 @@ void ParamTraits<gfx::Vector2dF>::Log(const gfx::Vector2dF& v, std::string* l) {
}
void ParamTraits<gfx::Rect>::Write(Message* m, const gfx::Rect& p) {
- WriteParam(m, p.origin());
- WriteParam(m, p.size());
+ int values[4] = { p.x(), p.y(), p.width(), p.height() };
+ m->WriteBytes(&values, sizeof(int) * 4);
}
bool ParamTraits<gfx::Rect>::Read(const Message* m,
PickleIterator* iter,
gfx::Rect* r) {
- gfx::Point origin;
- gfx::Size size;
- if (!ReadParam(m, iter, &origin) ||
- !ReadParam(m, iter, &size))
+ const char* char_values;
+ if (!m->ReadBytes(iter, &char_values, sizeof(int) * 4))
return false;
- r->set_origin(origin);
- r->set_size(size);
+ const int* values = reinterpret_cast<const int*>(char_values);
+ if (values[2] < 0 || values[3] < 0)
+ return false;
+ r->SetRect(values[0], values[1], values[2], values[3]);
return true;
}
@@ -299,25 +302,18 @@ void ParamTraits<gfx::Rect>::Log(const gfx::Rect& p, std::string* l) {
}
void ParamTraits<gfx::RectF>::Write(Message* m, const gfx::RectF& p) {
- ParamTraits<float>::Write(m, p.x());
- ParamTraits<float>::Write(m, p.y());
- ParamTraits<float>::Write(m, p.width());
- ParamTraits<float>::Write(m, p.height());
+ float values[4] = { p.x(), p.y(), p.width(), p.height() };
+ m->WriteBytes(&values, sizeof(float) * 4);
}
bool ParamTraits<gfx::RectF>::Read(const Message* m,
PickleIterator* iter,
gfx::RectF* r) {
- float x, y, w, h;
- if (!ParamTraits<float>::Read(m, iter, &x) ||
- !ParamTraits<float>::Read(m, iter, &y) ||
- !ParamTraits<float>::Read(m, iter, &w) ||
- !ParamTraits<float>::Read(m, iter, &h))
+ const char* char_values;
+ if (!m->ReadBytes(iter, &char_values, sizeof(float) * 4))
return false;
- r->set_x(x);
- r->set_y(y);
- r->set_width(w);
- r->set_height(h);
+ const float* values = reinterpret_cast<const float*>(char_values);
+ r->SetRect(values[0], values[1], values[2], values[3]);
return true;
}
diff --git a/chromium/content/public/common/common_param_traits_macros.h b/chromium/content/public/common/common_param_traits_macros.h
index 134f05ed5f7..4c871a6f29c 100644
--- a/chromium/content/public/common/common_param_traits_macros.h
+++ b/chromium/content/public/common/common_param_traits_macros.h
@@ -29,17 +29,17 @@
IPC_ENUM_TRAITS(content::ConsoleMessageLevel)
IPC_ENUM_TRAITS(content::PageTransition)
IPC_ENUM_TRAITS(content::SecurityStyle)
-IPC_ENUM_TRAITS(WebKit::WebReferrerPolicy)
+IPC_ENUM_TRAITS(blink::WebReferrerPolicy)
IPC_ENUM_TRAITS(WindowOpenDisposition)
IPC_ENUM_TRAITS(webkit_glue::EditingBehavior)
-IPC_ENUM_TRAITS(net::RequestPriority)
+IPC_ENUM_TRAITS_MAX_VALUE(net::RequestPriority, net::MAXIMUM_PRIORITY)
-IPC_STRUCT_TRAITS_BEGIN(WebKit::WebPoint)
+IPC_STRUCT_TRAITS_BEGIN(blink::WebPoint)
IPC_STRUCT_TRAITS_MEMBER(x)
IPC_STRUCT_TRAITS_MEMBER(y)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(WebKit::WebRect)
+IPC_STRUCT_TRAITS_BEGIN(blink::WebRect)
IPC_STRUCT_TRAITS_MEMBER(x)
IPC_STRUCT_TRAITS_MEMBER(y)
IPC_STRUCT_TRAITS_MEMBER(width)
@@ -101,6 +101,7 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(allow_scripts_to_close_windows)
IPC_STRUCT_TRAITS_MEMBER(remote_fonts_enabled)
IPC_STRUCT_TRAITS_MEMBER(javascript_can_access_clipboard)
+ IPC_STRUCT_TRAITS_MEMBER(xslt_enabled)
IPC_STRUCT_TRAITS_MEMBER(xss_auditor_enabled)
IPC_STRUCT_TRAITS_MEMBER(dns_prefetching_enabled)
IPC_STRUCT_TRAITS_MEMBER(local_storage_enabled)
@@ -109,9 +110,6 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(tabs_to_links)
IPC_STRUCT_TRAITS_MEMBER(hyperlink_auditing_enabled)
IPC_STRUCT_TRAITS_MEMBER(is_online)
- IPC_STRUCT_TRAITS_MEMBER(user_style_sheet_enabled)
- IPC_STRUCT_TRAITS_MEMBER(user_style_sheet_location)
- IPC_STRUCT_TRAITS_MEMBER(author_and_user_styles_enabled)
IPC_STRUCT_TRAITS_MEMBER(allow_universal_access_from_file_urls)
IPC_STRUCT_TRAITS_MEMBER(allow_file_access_from_file_urls)
IPC_STRUCT_TRAITS_MEMBER(webaudio_enabled)
@@ -130,6 +128,7 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
accelerated_compositing_for_scrollable_frames_enabled)
IPC_STRUCT_TRAITS_MEMBER(composited_scrolling_for_frames_enabled)
IPC_STRUCT_TRAITS_MEMBER(mock_scrollbars_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(layer_squashing_enabled)
IPC_STRUCT_TRAITS_MEMBER(threaded_html_parser)
IPC_STRUCT_TRAITS_MEMBER(show_paint_rects)
IPC_STRUCT_TRAITS_MEMBER(asynchronous_spell_checking_enabled)
@@ -139,6 +138,7 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(accelerated_2d_canvas_enabled)
IPC_STRUCT_TRAITS_MEMBER(minimum_accelerated_2d_canvas_size)
IPC_STRUCT_TRAITS_MEMBER(antialiased_2d_canvas_disabled)
+ IPC_STRUCT_TRAITS_MEMBER(accelerated_2d_canvas_msaa_sample_count)
IPC_STRUCT_TRAITS_MEMBER(accelerated_filters_enabled)
IPC_STRUCT_TRAITS_MEMBER(gesture_tap_highlight_enabled)
IPC_STRUCT_TRAITS_MEMBER(accelerated_compositing_for_plugins_enabled)
@@ -152,14 +152,14 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(enable_scroll_animator)
IPC_STRUCT_TRAITS_MEMBER(visual_word_movement_enabled)
IPC_STRUCT_TRAITS_MEMBER(password_echo_enabled)
- IPC_STRUCT_TRAITS_MEMBER(css_sticky_position_enabled)
- IPC_STRUCT_TRAITS_MEMBER(css_shaders_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(should_clear_document_background)
IPC_STRUCT_TRAITS_MEMBER(lazy_layout_enabled)
IPC_STRUCT_TRAITS_MEMBER(region_based_columns_enabled)
IPC_STRUCT_TRAITS_MEMBER(touch_enabled)
IPC_STRUCT_TRAITS_MEMBER(device_supports_touch)
IPC_STRUCT_TRAITS_MEMBER(device_supports_mouse)
IPC_STRUCT_TRAITS_MEMBER(touch_adjustment_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(pointer_events_max_touch_points)
IPC_STRUCT_TRAITS_MEMBER(fixed_position_creates_stacking_context)
IPC_STRUCT_TRAITS_MEMBER(sync_xhr_in_documents_enabled)
IPC_STRUCT_TRAITS_MEMBER(deferred_image_decoding_enabled)
@@ -168,13 +168,17 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(editing_behavior)
IPC_STRUCT_TRAITS_MEMBER(supports_multiple_windows)
IPC_STRUCT_TRAITS_MEMBER(viewport_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(viewport_meta_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(main_frame_resizes_are_orientation_changes)
IPC_STRUCT_TRAITS_MEMBER(initialize_at_minimum_page_scale)
IPC_STRUCT_TRAITS_MEMBER(smart_insert_delete_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(compositor_touch_hit_testing)
IPC_STRUCT_TRAITS_MEMBER(cookie_enabled)
IPC_STRUCT_TRAITS_MEMBER(spatial_navigation_enabled)
#if defined(OS_ANDROID)
IPC_STRUCT_TRAITS_MEMBER(text_autosizing_enabled)
IPC_STRUCT_TRAITS_MEMBER(font_scale_factor)
+ IPC_STRUCT_TRAITS_MEMBER(device_scale_adjustment)
IPC_STRUCT_TRAITS_MEMBER(force_enable_zoom)
IPC_STRUCT_TRAITS_MEMBER(double_tap_to_zoom_enabled)
IPC_STRUCT_TRAITS_MEMBER(user_gesture_required_for_media_playback)
@@ -185,11 +189,16 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(wide_viewport_quirk)
IPC_STRUCT_TRAITS_MEMBER(use_wide_viewport)
IPC_STRUCT_TRAITS_MEMBER(viewport_meta_layout_size_quirk)
+ IPC_STRUCT_TRAITS_MEMBER(viewport_meta_merge_content_quirk)
+ IPC_STRUCT_TRAITS_MEMBER(viewport_meta_non_user_scalable_quirk)
IPC_STRUCT_TRAITS_MEMBER(viewport_meta_zero_values_quirk)
+ IPC_STRUCT_TRAITS_MEMBER(clobber_user_agent_initial_scale_quirk)
+ IPC_STRUCT_TRAITS_MEMBER(ignore_main_frame_overflow_hidden_quirk)
+ IPC_STRUCT_TRAITS_MEMBER(report_screen_size_in_physical_pixels_quirk)
#endif
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(WebKit::WebWindowFeatures)
+IPC_STRUCT_TRAITS_BEGIN(blink::WebWindowFeatures)
IPC_STRUCT_TRAITS_MEMBER(x)
IPC_STRUCT_TRAITS_MEMBER(xSet)
IPC_STRUCT_TRAITS_MEMBER(y)
diff --git a/chromium/content/public/common/content_client.cc b/chromium/content/public/common/content_client.cc
index d4d00c0d05a..54db51778a4 100644
--- a/chromium/content/public/common/content_client.cc
+++ b/chromium/content/public/common/content_client.cc
@@ -89,8 +89,8 @@ std::string ContentClient::GetUserAgent() const {
return std::string();
}
-string16 ContentClient::GetLocalizedString(int message_id) const {
- return string16();
+base::string16 ContentClient::GetLocalizedString(int message_id) const {
+ return base::string16();
}
base::StringPiece ContentClient::GetDataResource(
diff --git a/chromium/content/public/common/content_client.h b/chromium/content/public/common/content_client.h
index e2e0c73a08f..1695656e891 100644
--- a/chromium/content/public/common/content_client.h
+++ b/chromium/content/public/common/content_client.h
@@ -118,7 +118,7 @@ class CONTENT_EXPORT ContentClient {
virtual std::string GetUserAgent() const;
// Returns a string resource given its id.
- virtual string16 GetLocalizedString(int message_id) const;
+ virtual base::string16 GetLocalizedString(int message_id) const;
// Return the contents of a resource in a StringPiece given the resource id.
virtual base::StringPiece GetDataResource(
diff --git a/chromium/content/public/common/content_constants.cc b/chromium/content/public/common/content_constants.cc
index 75e92731089..251db885e1c 100644
--- a/chromium/content/public/common/content_constants.cc
+++ b/chromium/content/public/common/content_constants.cc
@@ -25,7 +25,6 @@ const char kFlashPluginSplDescription[] = "FutureSplash Player";
const size_t kMaxRendererProcessCount = 82;
const int kMaxSessionHistoryEntries = 50;
const size_t kMaxTitleChars = 4 * 1024;
-const size_t kMaxURLChars = 2 * 1024 * 1024;
const size_t kMaxURLDisplayChars = 32 * 1024;
#if defined(GOOGLE_CHROME_BUILD)
@@ -39,11 +38,7 @@ const int kStatsMaxCounters = 3000;
const int kHistogramSynchronizerReservedSequenceNumber = 0;
-const char kGpuCompositingFieldTrialName[] = "ForceCompositingMode";
-const char kGpuCompositingFieldTrialForceCompositingEnabledName[] = "enabled";
-const char kGpuCompositingFieldTrialThreadEnabledName[] = "thread";
-
-const char kLowLatencyFlashAudioFieldTrialName[] = "LowLatencyFlashAudio";
-const char kLowLatencyFlashAudioFieldTrialEnabledName[] = "LowLatency";
+const char kFlashHwVideoDecodeFieldTrialName[] = "FlashHardwareVideoDecode";
+const char kFlashHwVideoDecodeFieldTrialEnabledName[] = "HwVideo";
} // namespace content
diff --git a/chromium/content/public/common/content_constants.h b/chromium/content/public/common/content_constants.h
index 012b00fd35c..9b3b0e38671 100644
--- a/chromium/content/public/common/content_constants.h
+++ b/chromium/content/public/common/content_constants.h
@@ -41,13 +41,6 @@ extern const int kMaxSessionHistoryEntries;
// to accept in the browser process.
extern const size_t kMaxTitleChars;
-// The maximum number of characters in the URL that we're willing to accept
-// in the browser process. It is set low enough to avoid damage to the browser
-// but high enough that a web site can abuse location.hash for a little storage.
-// We have different values for "max accepted" and "max displayed" because
-// a data: URI may be legitimately massive, but the full URI would kill all
-// known operating systems if you dropped it into a UI control.
-CONTENT_EXPORT extern const size_t kMaxURLChars;
CONTENT_EXPORT extern const size_t kMaxURLDisplayChars;
extern const char kStatsFilename[];
@@ -61,14 +54,9 @@ extern const int kStatsMaxCounters;
// a browser-supplied sequence number.
CONTENT_EXPORT extern const int kHistogramSynchronizerReservedSequenceNumber;
-CONTENT_EXPORT extern const char kGpuCompositingFieldTrialName[];
-CONTENT_EXPORT extern const char
- kGpuCompositingFieldTrialForceCompositingEnabledName[];
-CONTENT_EXPORT extern const char kGpuCompositingFieldTrialThreadEnabledName[];
-
-// Shared constants for the low latency flash audio field trial.
-CONTENT_EXPORT extern const char kLowLatencyFlashAudioFieldTrialName[];
-CONTENT_EXPORT extern const char kLowLatencyFlashAudioFieldTrialEnabledName[];
+// Shared constants for the flash hardware video decode field trial.
+CONTENT_EXPORT extern const char kFlashHwVideoDecodeFieldTrialName[];
+CONTENT_EXPORT extern const char kFlashHwVideoDecodeFieldTrialEnabledName[];
} // namespace content
diff --git a/chromium/content/public/common/content_descriptors.h b/chromium/content/public/common/content_descriptors.h
index 3640ea5cdc7..ce7ab0e8d8a 100644
--- a/chromium/content/public/common/content_descriptors.h
+++ b/chromium/content/public/common/content_descriptors.h
@@ -10,7 +10,7 @@
// This is a list of global descriptor keys to be used with the
// base::GlobalDescriptors object (see base/posix/global_descriptors.h)
enum {
- kCrashDumpSignal = kPrimaryIPCChannel + 1,
+ kCrashDumpSignal = kIPCDescriptorMax,
kSandboxIPCChannel, // http://code.google.com/p/chromium/LinuxSandboxIPC
#if defined(OS_ANDROID)
diff --git a/chromium/content/public/common/content_switches.cc b/chromium/content/public/common/content_switches.cc
index 264f0c15204..1fc5ef5f2d1 100644
--- a/chromium/content/public/common/content_switches.cc
+++ b/chromium/content/public/common/content_switches.cc
@@ -6,13 +6,14 @@
namespace switches {
+// The number of MSAA samples for canvas2D. Requires MSAA support by GPU to
+// have an effect. 0 disables MSAA.
+const char kAcceleratedCanvas2dMSAASampleCount[] = "canvas-msaa-sample-count";
+
// By default, file:// URIs cannot read other file:// URIs. This is an
// override for developers who need the old behavior for testing.
const char kAllowFileAccessFromFiles[] = "allow-file-access-from-files";
-// Allows filters (SkImageFilter objects) to be sent between processes over IPC
-const char kAllowFiltersOverIPC[] = "allow-filters-over-ipc";
-
// Enables the sandboxed processes to run without a job object assigned to them.
// This flag is required to allow Chrome to run in RemoteApps or Citrix. This
// flag can reduce the security of the sandboxed processes and allow them to do
@@ -63,11 +64,6 @@ const char kDebugPluginLoading[] = "debug-plugin-loading";
const char kDefaultTileWidth[] = "default-tile-width";
const char kDefaultTileHeight[] = "default-tile-height";
-// Handles URL requests by NPAPI plugins directly through the browser, instead
-// of going through the renderer. This will be the new default, but it's not
-// turned on initially until we do more testing.
-const char kDirectNPAPIRequests[] = "direct-npapi-requests";
-
// Disable antialiasing on 2d canvas.
const char kDisable2dCanvasAntialiasing[] = "disable-canvas-aa";
@@ -95,6 +91,14 @@ const char kDisableAcceleratedLayers[] = "disable-accelerated-layers";
const char kDisableAcceleratedOverflowScroll[] =
"disable-accelerated-overflow-scroll";
+// Disables layer squashing.
+const char kDisableLayerSquashing[] =
+ "disable-layer-squashing";
+
+// Disable accelerated compositing for scrollable frames.
+const char kDisableAcceleratedScrollableFrames[] =
+ "disable-accelerated-scrollable-frames";
+
// Disables the hardware acceleration of plugins.
const char kDisableAcceleratedPlugins[] = "disable-accelerated-plugins";
@@ -119,10 +123,14 @@ const char kDisableAudio[] = "disable-audio";
// users with many windows/tabs and lots of memory.
const char kDisableBackingStoreLimit[] = "disable-backing-store-limit";
-// Enables browser plugin compositing experiment.
+// Disable browser plugin compositing experiment.
const char kDisableBrowserPluginCompositing[] =
"disable-browser-plugin-compositing";
+// Disable accelerated scrolling by the compositor for frames.
+const char kDisableCompositedScrollingForFrames[] =
+ "disable-composited-scrolling-for-frames";
+
// See comment for kEnableCompositingForFixedPosition.
const char kDisableCompositingForFixedPosition[] =
"disable-fixed-position-compositing";
@@ -143,18 +151,33 @@ const char kDisableDelegatedRenderer[] = "disable-delegated-renderer";
// Disables desktop notifications (default enabled on windows).
const char kDisableDesktopNotifications[] = "disable-desktop-notifications";
+// Disables experimental navigator content utils implementation.
+const char kDisableNavigatorContentUtils[] =
+ "disable-navigator-content-utils";
+
// Disable device motion events.
const char kDisableDeviceMotion[] = "disable-device-motion";
// Disable device orientation events.
const char kDisableDeviceOrientation[] = "disable-device-orientation";
+// Handles URL requests by NPAPI plugins through the renderer.
+const char kDisableDirectNPAPIRequests[] = "disable-direct-npapi-requests";
+
+// Disable the per-domain blocking for 3D APIs after GPU reset.
+// This switch is intended only for tests.
+extern const char kDisableDomainBlockingFor3DAPIs[] =
+ "disable-domain-blocking-for-3d-apis";
+
// Disable experimental WebGL support.
const char kDisableExperimentalWebGL[] = "disable-webgl";
// Disable FileSystem API.
const char kDisableFileSystem[] = "disable-file-system";
+// Disables sending filters (SkImageFilter objects) between processes over IPC
+const char kDisableFiltersOverIPC[] = "disable-filters-over-ipc";
+
const char kDisableFixedPositionCreatesStackingContext[]
= "disable-fixed-position-creates-stacking-context";
@@ -174,6 +197,9 @@ const char kDisableFullScreen[] = "disable-fullscreen";
// Suppresses support for the Geolocation javascript API.
const char kDisableGeolocation[] = "disable-geolocation";
+// Disable deferral of scroll-ending gesture events when a scroll is active.
+const char kDisableGestureDebounce[] = "disable-gesture-debounce";
+
const char kDisableGestureTapHighlight[] = "disable-gesture-tap-highlight";
// Disable GL multisampling.
@@ -186,6 +212,11 @@ const char kDisableGpu[] = "disable-gpu";
// Prevent the compositor from using its GPU implementation.
const char kDisableGpuCompositing[] = "disable-gpu-compositing";
+// Disable the limit on the number of times the GPU process may be restarted
+// This switch is intended only for tests.
+extern const char kDisableGpuProcessCrashLimit[] =
+ "disable-gpu-process-crash-limit";
+
// Do not launch the GPU process shortly after browser process launch. Instead
// launch it when it is first needed.
const char kDisableGpuProcessPrelaunch[] = "disable-gpu-process-prelaunch";
@@ -205,9 +236,6 @@ const char kDisableHangMonitor[] = "disable-hang-monitor";
// Disable the RenderThread's HistogramCustomizer.
const char kDisableHistogramCustomizer[] = "disable-histogram-customizer";
-// Disables HTML-based desktop notifications.
-const char kDisableHTMLNotifications[] = "disable-html-notifications";
-
// Disable the use of an ImageTransportSurface. This means the GPU process
// will present the rendered page rather than the browser process.
const char kDisableImageTransportSurface[] = "disable-image-transport-surface";
@@ -218,8 +246,14 @@ const char kDisableJava[] = "disable-java";
// Don't execute JavaScript (browser JS like the new tab page still runs).
const char kDisableJavaScript[] = "disable-javascript";
+// Don't kill a child process when it sends a bad IPC message. Apart
+// from testing, it is a bad idea from a security perspective to enable
+// this switch.
+const char kDisableKillAfterBadIPC[] = "disable-kill-after-bad-ipc";
+
// Disables prefixed Encrypted Media API (e.g. webkitGenerateKeyRequest()).
-const char kDisableLegacyEncryptedMedia[] = "disable-legacy-encrypted-media";
+const char kDisablePrefixedEncryptedMedia[] =
+ "disable-prefixed-encrypted-media";
// Disable LocalStorage.
const char kDisableLocalStorage[] = "disable-local-storage";
@@ -228,6 +262,11 @@ const char kDisableLocalStorage[] = "disable-local-storage";
// builds.
const char kDisableLogging[] = "disable-logging";
+// Allows P2P sockets to talk UDP to other servers without using STUN first.
+// For development only, use with caution.
+// TODO(hubbe): Remove this flag.
+const char kDisableP2PSocketSTUNFilter[] = "disable-p2psocket-stun-filter";
+
// Disable Pepper3D.
const char kDisablePepper3d[] = "disable-pepper-3d";
@@ -279,22 +318,30 @@ const char kDisableSSLFalseStart[] = "disable-ssl-false-start";
// Disable multithreaded GPU compositing of web content.
const char kDisableThreadedCompositing[] = "disable-threaded-compositing";
-// Disables the threaded HTML parser in WebKit
+// Disables the threaded HTML parser in Blink
const char kDisableThreadedHTMLParser[] = "disable-threaded-html-parser";
-// Disable web audio API.
-const char kDisableWebAudio[] = "disable-webaudio";
-
-// Disables prefixed Media Source API (i.e., the WebKitMediaSource object).
-const char kDisableWebKitMediaSource[] = "disable-webkit-media-source";
+// Disable accelerated overflow scrolling in corner cases (that would not be
+// handled by enable-accelerated-overflow-scroll).
+const char kDisableUniversalAcceleratedOverflowScroll[] =
+ "disable-universal-accelerated-overflow-scroll";
// Disables unprefixed Media Source API (i.e., the MediaSource object).
const char kDisableUnprefixedMediaSource[] = "disable-unprefixed-media-source";
+// Disable CSS Transitions / Animations on the Web Animations model.
+const char kDisableWebAnimationsCSS[] = "disable-web-animations-css";
+
+// Disables prefixed Media Source API (i.e., the WebKitMediaSource object).
+const char kDisableWebKitMediaSource[] = "disable-webkit-media-source";
+
// Don't enforce the same-origin policy. (Used by people testing their sites.)
const char kDisableWebSecurity[] = "disable-web-security";
-// Disables WebKit's XSSAuditor. The XSSAuditor mitigates reflective XSS.
+// Disables support for XSLT.
+const char kDisableXSLT[] = "disable-xslt";
+
+// Disables Blink's XSSAuditor. The XSSAuditor mitigates reflective XSS.
const char kDisableXSSAuditor[] = "disable-xss-auditor";
// Specifies if the |DOMAutomationController| needs to be bound in the
@@ -316,6 +363,11 @@ const char kEnableAcceleratedFixedRootBackground[] =
const char kEnableAcceleratedOverflowScroll[] =
"enable-accelerated-overflow-scroll";
+// Enables experimental feature that maps multiple RenderLayers to
+// one composited layer to avoid pathological layer counts.
+const char kEnableLayerSquashing[] =
+ "enable-layer-squashing";
+
// Enables accelerated compositing for scrollable frames for accelerated
// scrolling for them. Requires kForceCompositingMode.
const char kEnableAcceleratedScrollableFrames[] =
@@ -324,18 +376,9 @@ const char kEnableAcceleratedScrollableFrames[] =
// Turns on extremely verbose logging of accessibility events.
const char kEnableAccessibilityLogging[] = "enable-accessibility-logging";
-// Enable notifications of audible/silent audio output from a render view.
-//
-// TODO(miu): Remove --enable-audible-notifications once the feature goes
-// live. http://crbug.com/178934
-const char kEnableAudibleNotifications[] = "enable-audible-notifications";
-
-// Use a begin frame signal from browser to renderer to schedule rendering.
+// Use a BeginImplFrame signal from browser to renderer to schedule rendering.
const char kEnableBeginFrameScheduling[] = "enable-begin-frame-scheduling";
-// Synchronize delivery and response of input events to and from the renderer.
-const char kEnableBrowserInputController[] = "enable-browser-input-controller";
-
// Enables browser plugin for all types of pages.
const char kEnableBrowserPluginForAllViewTypes[] =
"enable-browser-plugin-for-all-view-types";
@@ -372,9 +415,6 @@ const char kEnableCompositingForFixedPosition[] =
const char kEnableCompositingForTransition[] =
"enable-transition-compositing";
-// Enables CSS3 custom filters
-const char kEnableCssShaders[] = "enable-css-shaders";
-
// Defer image decoding in WebKit until painting.
const char kEnableDeferredImageDecoding[] = "enable-deferred-image-decoding";
@@ -401,10 +441,8 @@ const char kEnableExperimentalWebPlatformFeatures[] =
// Enable an experimental WebSocket implementation.
const char kEnableExperimentalWebSocket[] = "enable-experimental-websocket";
-// By default, a page is laid out to fill the entire width of the window.
-// This flag fixes the layout of the page to a default of 980 CSS pixels,
-// or to a specified width and height using --enable-fixed-layout=w,h
-const char kEnableFixedLayout[] = "enable-fixed-layout";
+// Enable the fast text autosizing implementation.
+const char kEnableFastTextAutosizing[] = "enable-fast-text-autosizing";
const char kEnableFixedPositionCreatesStackingContext[]
= "enable-fixed-position-creates-stacking-context";
@@ -423,6 +461,9 @@ const char kEnableHighDpiCompositingForFixedPosition[] =
"enable-high-dpi-fixed-position-compositing";
#if defined(OS_WIN)
+// Enables the DirectWrite font rendering system on windows.
+const char kEnableDirectWrite[] = "enable-direct-write";
+
// Use high resolution timers for TimeTicks.
const char kEnableHighResolutionTime[] = "enable-high-resolution-time";
#endif
@@ -479,6 +520,10 @@ const char kEnablePruneGpuCommandBuffers[] =
const char kEnableRegionBasedColumns[] =
"enable-region-based-columns";
+// Enables the new layout/paint system which paints after layout is complete.
+const char kEnableRepaintAfterLayout[] =
+ "enable-repaint-after-layout";
+
// Cause the OS X sandbox write to syslog every time an access to a resource
// is denied by the sandbox.
const char kEnableSandboxLogging[] = "enable-sandbox-logging";
@@ -516,6 +561,10 @@ const char kEnableStatsTable[] = "enable-stats-table";
// cookies on cross-site requests.
const char kEnableStrictSiteIsolation[] = "enable-strict-site-isolation";
+// Enable support for ServiceWorker. See
+// https://github.com/slightlyoff/ServiceWorker for more information.
+const char kEnableServiceWorker[] = "enable-service-worker";
+
// Enable use of experimental TCP sockets API for sending data in the
// SYN packet.
const char kEnableTcpFastOpen[] = "enable-tcp-fastopen";
@@ -527,15 +576,28 @@ const char kEnableTextServicesFramework[] = "enable-text-services-framework";
// Enable multithreaded GPU compositing of web content.
const char kEnableThreadedCompositing[] = "enable-threaded-compositing";
+// Enable accelerated overflow scrolling in all cases.
+const char kEnableUniversalAcceleratedOverflowScroll[] =
+ "enable-universal-accelerated-overflow-scroll";
+
// Enable screen capturing support for MediaStream API.
const char kEnableUserMediaScreenCapturing[] =
"enable-usermedia-screen-capturing";
-// Enables the use of the viewport meta tag, which allows
+// Enables the use of the @viewport CSS rule, which allows
// pages to control aspects of their own layout. This also turns on touch-screen
// pinch gestures.
const char kEnableViewport[] = "enable-viewport";
+// Enables the use of the legacy viewport meta tag. Turning this on also
+// turns on the @viewport CSS rule
+const char kEnableViewportMeta[] = "enable-viewport-meta";
+
+// Resizes of the main frame are the caused by changing between landscape
+// and portrait mode (i.e. Android) so the page should be rescaled to fit
+const char kMainFrameResizesAreOrientationChanges[] =
+ "main-frame-resizes-are-orientation-changes";
+
// Enables moving cursor by word in visual order.
const char kEnableVisualWordMovement[] = "enable-visual-word-movement";
@@ -622,6 +684,9 @@ const char kJavaScriptFlags[] = "js-flags";
// Load an NPAPI plugin from the specified path.
const char kLoadPlugin[] = "load-plugin";
+// Logs GPU control list decisions when enforcing blacklist rules.
+const char kLogGpuControlListDecisions[] = "log-gpu-control-list-decisions";
+
// Sets the minimum log level. Valid values are from 0 to 3:
// INFO = 0, WARNING = 1, LOG_ERROR = 2, LOG_FATAL = 3.
const char kLoggingLevel[] = "log-level";
@@ -651,10 +716,6 @@ const char kNoReferrers[] = "no-referrers";
// Disables the sandbox for all process types that are normally sandboxed.
const char kNoSandbox[] = "no-sandbox";
-// Enables not sending touch events to renderer while scrolling.
-const char kNoTouchToRendererWhileScrolling[] =
- "no-touch-to-renderer-while-scrolling";
-
// Enables or disables history navigation in response to horizontal overscroll.
// Set the value to '1' to enable the feature, and set to '0' to disable.
// Defaults to enabled.
@@ -713,9 +774,12 @@ const char kProcessType[] = "type";
// Reduces the GPU process sandbox to be less strict.
const char kReduceGpuSandbox[] = "reduce-gpu-sandbox";
-// Register Pepper plugins (see pepper_plugin_registry.cc for its format).
-const char kRegisterPepperPlugins[] = "register-pepper-plugins";
+// Enables more web features over insecure connections. Designed to be used
+// for testing purposes only.
+const char kReduceSecurityForTesting[] = "reduce-security-for-testing";
+// Register Pepper plugins (see pepper_plugin_list.cc for its format).
+const char kRegisterPepperPlugins[] = "register-pepper-plugins";
// Enables remote debug over HTTP on the specified port.
const char kRemoteDebuggingPort[] = "remote-debugging-port";
@@ -764,18 +828,16 @@ const char kSingleProcess[] = "single-process";
// http://www.chromium.org/developers/design-documents/site-isolation
//
// Unlike --enable-strict-site-isolation (which allows cross-site iframes),
-// this flag blocks cross-site documents even in iframes, until out-of-process
-// iframe support is available. Cross-site network requests do attach the
-// normal set of cookies, but a renderer process is only allowed to view or
-// modify cookies for its own site (via JavaScript).
-// TODO(irobert): Implement the cross-site document blocking in
-// http://crbug.com/159215.
+// this flag does not affect which cookies are attached to cross-site requests.
+// Support is being added to render cross-site iframes in a different process
+// than their parent pages.
const char kSitePerProcess[] = "site-per-process";
// Skip gpu info collection, blacklist loading, and blacklist auto-update
// scheduling at browser startup time.
// Therefore, all GPU features are available, and about:gpu page shows empty
-// content. The switch is intended only for tests.
+// content. The switch is intended only for layout tests.
+// TODO(gab): Get rid of this switch entirely.
const char kSkipGpuDataLoading[] = "skip-gpu-data-loading";
// Specifies the request key for the continuous speech recognition webservice.
@@ -796,10 +858,6 @@ const char kTabCaptureDownscaleQuality[] = "tab-capture-downscale-quality";
// Upscale defaults to "best".
const char kTabCaptureUpscaleQuality[] = "tab-capture-upscale-quality";
-// GestureTapDown events are deferred by this many miillseconds before
-// sending them to the renderer.
-const char kTapDownDeferralTimeMs[] = "tap-down-deferral-time";
-
// 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";
@@ -807,6 +865,10 @@ const char kTestingFixedHttpsPort[] = "testing-fixed-https-port";
// Runs the security test for the renderer sandbox.
const char kTestSandbox[] = "test-sandbox";
+// Enable timeout-based touch event cancellation if a touch ack is delayed.
+// If unspecified, touch timeout behavior will be disabled.
+const char kTouchAckTimeoutDelayMs[] = "touch-ack-timeout-delay-ms";
+
// Causes TRACE_EVENT flags to be recorded beginning with shutdown. Optionally,
// can specify the specific trace categories to include (e.g.
// --trace-shutdown=base,net) otherwise, all events are recorded.
@@ -889,6 +951,9 @@ const char kWaitForDebuggerChildren[] = "wait-for-debugger-children";
// Logging.cpp in WebKit's WebCore for a list of available channels.
const char kWebCoreLogChannels[] = "webcore-log-channels";
+// Overrides the amount of shared memory the webgl command buffer allocates
+const char kWebGLCommandBufferSizeKb[] = "webgl-command-buffer-size-kb";
+
// Causes the process to run as a worker subprocess.
const char kWorkerProcess[] = "worker";
@@ -899,23 +964,34 @@ const char kZygoteCmdPrefix[] = "zygote-cmd-prefix";
const char kZygoteProcess[] = "zygote";
#if defined(ENABLE_WEBRTC)
-// Disable WebRTC device enumeration.
+// Enables audio processing in a MediaStreamTrack. When this flag is on, AEC,
+// NS and AGC will be done per MediaStreamTrack instead of in PeerConnection.
+const char kEnableAudioTrackProcessing[] = "enable-audio-track-processing";
+
+// Disables WebRTC device enumeration.
const char kDisableDeviceEnumeration[] = "disable-device-enumeration";
-// Disable WebRTC DataChannels SCTP wire protocol support.
+// Disables WebRTC DataChannels SCTP wire protocol support.
const char kDisableSCTPDataChannels[] = "disable-sctp-data-channels";
// Disables HW decode acceleration for WebRTC.
const char kDisableWebRtcHWDecoding[] = "disable-webrtc-hw-decoding";
+// Disables encryption of RTP Media for WebRTC. When Chrome embeds Content, it
+// ignores this switch on its stable and beta channels.
+const char kDisableWebRtcEncryption[] = "disable-webrtc-encryption";
+
// Disables HW encode acceleration for WebRTC.
const char kDisableWebRtcHWEncoding[] = "disable-webrtc-hw-encoding";
// Enables WebRTC AEC recordings.
const char kEnableWebRtcAecRecordings[] = "enable-webrtc-aec-recordings";
-// Enable WebRTC to open TCP server sockets.
+// Enables WebRTC to open TCP server sockets.
const char kEnableWebRtcTcpServerSocket[] = "enable-webrtc-tcp-server-socket";
+
+// Enables VP8 HW encode acceleration for WebRTC.
+const char kEnableWebRtcHWVp8Encoding[] = "enable-webrtc-hw-vp8-encoding";
#endif
#if defined(OS_ANDROID)
@@ -950,6 +1026,13 @@ const char kNetworkCountryIso[] = "network-country-iso";
const char kRemoteDebuggingSocketName[] = "remote-debugging-socket-name";
#endif
+#if defined(OS_ANDROID) && defined(ARCH_CPU_X86)
+const char kEnableWebAudio[] = "enable-webaudio";
+#else
+// Disable web audio API.
+const char kDisableWebAudio[] = "disable-webaudio";
+#endif
+
#if defined(OS_CHROMEOS)
// Disables panel fitting (used for mirror mode).
const char kDisablePanelFitting[] = "disable-panel-fitting";
@@ -972,11 +1055,6 @@ const char kUseCoreAnimation[] = "use-core-animation";
const char kChildCleanExit[] = "child-clean-exit";
#endif
-#if defined(USE_AURA)
-// Forces usage of the test compositor. Needed to run ui tests on bots.
-extern const char kTestCompositor[] = "test-compositor";
-#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 133bb5d6c3d..11842883b8e 100644
--- a/chromium/content/public/common/content_switches.h
+++ b/chromium/content/public/common/content_switches.h
@@ -14,11 +14,11 @@ namespace switches {
// All switches in alphabetical order. The switches should be documented
// alongside the definition of their values in the .cc file.
+CONTENT_EXPORT extern const char kAcceleratedCanvas2dMSAASampleCount[];
CONTENT_EXPORT extern const char kAllowFileAccessFromFiles[];
-CONTENT_EXPORT extern const char kAllowFiltersOverIPC[];
CONTENT_EXPORT extern const char kAllowNoSandboxJob[];
extern const char kAllowSandboxDebugging[];
-extern const char kAllowWebUICompositing[];
+CONTENT_EXPORT extern const char kAllowWebUICompositing[];
extern const char kAuditAllHandles[];
extern const char kAuditHandles[];
CONTENT_EXPORT extern const char kBlacklistAcceleratedCompositing[];
@@ -30,15 +30,16 @@ CONTENT_EXPORT extern const char kBrowserSubprocessPath[];
extern const char kDebugPluginLoading[];
CONTENT_EXPORT extern const char kDefaultTileWidth[];
CONTENT_EXPORT extern const char kDefaultTileHeight[];
-extern const char kDirectNPAPIRequests[];
CONTENT_EXPORT extern const char kDisable2dCanvasAntialiasing[];
CONTENT_EXPORT extern const char kDisable3DAPIs[];
CONTENT_EXPORT extern const char kDisableAccelerated2dCanvas[];
CONTENT_EXPORT extern const char kDisableAcceleratedCompositing[];
CONTENT_EXPORT extern const char kDisableAcceleratedFixedRootBackground[];
CONTENT_EXPORT extern const char kDisableAcceleratedLayers[];
-extern const char kDisableAcceleratedOverflowScroll[];
+CONTENT_EXPORT extern const char kDisableAcceleratedOverflowScroll[];
+CONTENT_EXPORT extern const char kDisableLayerSquashing[];
CONTENT_EXPORT extern const char kDisableAcceleratedPlugins[];
+CONTENT_EXPORT extern const char kDisableAcceleratedScrollableFrames[];
CONTENT_EXPORT extern const char kDisableAcceleratedVideo[];
CONTENT_EXPORT extern const char kDisableAcceleratedVideoDecode[];
CONTENT_EXPORT extern const char kDisableAltWinstation[];
@@ -46,6 +47,7 @@ CONTENT_EXPORT extern const char kDisableApplicationCache[];
CONTENT_EXPORT extern const char kDisableAudio[];
extern const char kDisableBackingStoreLimit[];
CONTENT_EXPORT extern const char kDisableBrowserPluginCompositing[];
+CONTENT_EXPORT extern const char kDisableCompositedScrollingForFrames[];
CONTENT_EXPORT extern const char kDisableCompositingForFixedPosition[];
CONTENT_EXPORT extern const char kDisableCompositingForTransition[];
CONTENT_EXPORT extern const char kDisableDatabases[];
@@ -54,85 +56,93 @@ CONTENT_EXPORT extern const char kDisableDelegatedRenderer[];
extern const char kDisableDesktopNotifications[];
CONTENT_EXPORT extern const char kDisableDeviceMotion[];
CONTENT_EXPORT extern const char kDisableDeviceOrientation[];
+extern const char kDisableDirectNPAPIRequests[];
+extern const char kDisableDomainBlockingFor3DAPIs[];
CONTENT_EXPORT extern const char kDisableExperimentalWebGL[];
CONTENT_EXPORT extern const char kDisableFileSystem[];
+CONTENT_EXPORT extern const char kDisableFiltersOverIPC[];
CONTENT_EXPORT extern const char kDisableFixedPositionCreatesStackingContext[];
CONTENT_EXPORT extern const char kDisableFlash3d[];
CONTENT_EXPORT extern const char kDisableFlashStage3d[];
CONTENT_EXPORT extern const char kDisableForceCompositingMode[];
CONTENT_EXPORT extern const char kDisableFullScreen[];
extern const char kDisableGeolocation[];
+extern const char kDisableGestureDebounce[];
CONTENT_EXPORT extern const char kDisableGestureTapHighlight[];
CONTENT_EXPORT extern const char kDisableGLMultisampling[];
-extern const char kDisableGpu[];
+CONTENT_EXPORT extern const char kDisableGpu[];
CONTENT_EXPORT extern const char kDisableGpuCompositing[];
+extern const char kDisableGpuProcessCrashLimit[];
CONTENT_EXPORT extern const char kDisableGpuProcessPrelaunch[];
-extern const char kDisableGpuSandbox[];
-extern const char kDisableGpuWatchdog[];
+CONTENT_EXPORT extern const char kDisableGpuSandbox[];
+CONTENT_EXPORT extern const char kDisableGpuWatchdog[];
CONTENT_EXPORT extern const char kDisableHangMonitor[];
extern const char kDisableHistogramCustomizer[];
-CONTENT_EXPORT extern const char kDisableHTMLNotifications[];
extern const char kDisableImageTransportSurface[];
CONTENT_EXPORT extern const char kDisableJava[];
CONTENT_EXPORT extern const char kDisableJavaScript[];
-extern const char kDisableLegacyEncryptedMedia[];
+CONTENT_EXPORT extern const char kDisablePrefixedEncryptedMedia[];
+extern const char kDisableKillAfterBadIPC[];
CONTENT_EXPORT extern const char kDisableLocalStorage[];
CONTENT_EXPORT extern const char kDisableLogging[];
+extern const char kDisableNavigatorContentUtils[];
+extern const char kDisableP2PSocketSTUNFilter[];
extern const char kDisablePepper3d[];
-extern const char kDisablePinch[];
+CONTENT_EXPORT extern const char kDisablePinch[];
CONTENT_EXPORT extern const char kDisablePlugins[];
CONTENT_EXPORT extern const char kDisablePluginsDiscovery[];
extern const char kDisableRemoteFonts[];
extern const char kDisableRendererAccessibility[];
-extern const char kDisableSeccompFilterSandbox[];
+CONTENT_EXPORT extern const char kDisableSeccompFilterSandbox[];
extern const char kDisableSessionStorage[];
-extern const char kDisableSetuidSandbox[];
+CONTENT_EXPORT extern const char kDisableSetuidSandbox[];
CONTENT_EXPORT extern const char kDisableSharedWorkers[];
extern const char kDisableSiteSpecificQuirks[];
CONTENT_EXPORT extern const char kDisableSmoothScrolling[];
CONTENT_EXPORT extern const char kDisableSoftwareRasterizer[];
CONTENT_EXPORT extern const char kDisableSpeechInput[];
-extern const char kDisableSSLFalseStart[];
+CONTENT_EXPORT extern const char kDisableSSLFalseStart[];
CONTENT_EXPORT extern const char kDisableThreadedCompositing[];
CONTENT_EXPORT extern const char kDisableThreadedHTMLParser[];
-CONTENT_EXPORT extern const char kDisableWebAudio[];
-extern const char kDisableWebKitMediaSource[];
-extern const char kDisableUnprefixedMediaSource[];
+CONTENT_EXPORT extern const char kDisableUniversalAcceleratedOverflowScroll[];
+CONTENT_EXPORT extern const char kDisableUnprefixedMediaSource[];
+extern const char kDisableWebAnimationsCSS[];
+CONTENT_EXPORT extern const char kDisableWebKitMediaSource[];
CONTENT_EXPORT extern const char kDisableWebSecurity[];
+extern const char kDisableXSLT[];
extern const char kDisableXSSAuditor[];
CONTENT_EXPORT extern const char kDomAutomationController[];
CONTENT_EXPORT extern const char kEnableAcceleratedFilters[];
CONTENT_EXPORT extern const char kEnableAcceleratedFixedRootBackground[];
-extern const char kEnableAcceleratedOverflowScroll[];
-extern const char kEnableAcceleratedScrollableFrames[];
+CONTENT_EXPORT extern const char kEnableAcceleratedOverflowScroll[];
+CONTENT_EXPORT extern const char kEnableLayerSquashing[];
+CONTENT_EXPORT extern const char kEnableAcceleratedScrollableFrames[];
extern const char kEnableAccessibilityLogging[];
-extern const char kEnableAudibleNotifications[];
CONTENT_EXPORT extern const char kEnableBeginFrameScheduling[];
-CONTENT_EXPORT extern const char kEnableBrowserInputController[];
CONTENT_EXPORT extern const char kEnableBrowserPluginForAllViewTypes[];
CONTENT_EXPORT extern const char kEnableBrowserPluginDragDrop[];
-extern const char kEnableCompositedScrollingForFrames[];
+CONTENT_EXPORT extern const char kEnableCompositedScrollingForFrames[];
CONTENT_EXPORT extern const char kEnableCompositingForFixedPosition[];
CONTENT_EXPORT extern const char kEnableCompositingForTransition[];
-CONTENT_EXPORT extern const char kEnableCssShaders[];
CONTENT_EXPORT extern const char kEnableDeferredImageDecoding[];
CONTENT_EXPORT extern const char kEnableDeadlineScheduling[];
CONTENT_EXPORT extern const char kEnableDelegatedRenderer[];
CONTENT_EXPORT extern const char kEnableDownloadResumption[];
-extern const char kEnableEncryptedMedia[];
+CONTENT_EXPORT extern const char kEnableEncryptedMedia[];
CONTENT_EXPORT extern const char kEnableExperimentalCanvasFeatures[];
CONTENT_EXPORT extern const char kEnableExperimentalWebPlatformFeatures[];
-extern const char kEnableExperimentalWebSocket[];
-CONTENT_EXPORT extern const char kEnableFixedLayout[];
+CONTENT_EXPORT extern const char kEnableExperimentalWebSocket[];
+extern const char kEnableFastTextAutosizing[];
CONTENT_EXPORT extern const char kEnableFixedPositionCreatesStackingContext[];
CONTENT_EXPORT extern const char kEnableGestureTapHighlight[];
extern const char kEnableGpuBenchmarking[];
extern const char kEnableGpuClientTracing[];
CONTENT_EXPORT extern const char kEnableHighDpiCompositingForFixedPosition[];
- #if defined(OS_WIN)
-extern const char kEnableHighResolutionTime[];
+#if defined(OS_WIN)
+CONTENT_EXPORT extern const char kEnableDirectWrite[];
+CONTENT_EXPORT extern const char kEnableHighResolutionTime[];
#endif
-extern const char kEnableHTMLImports[];
+CONTENT_EXPORT extern const char kEnableHTMLImports[];
CONTENT_EXPORT extern const char kEnableInbandTextTracks[];
extern const char kEnableInputModeAttribute[];
CONTENT_EXPORT extern const char kEnableLogging[];
@@ -140,14 +150,15 @@ extern const char kEnableMemoryBenchmarking[];
extern const char kEnableMonitorProfile[];
CONTENT_EXPORT extern const char kEnableOfflineCacheAccess[];
CONTENT_EXPORT extern const char kEnableOverlayFullscreenVideo[];
-extern const char kEnableOverlayScrollbars[];
+CONTENT_EXPORT extern const char kEnableOverlayScrollbars[];
CONTENT_EXPORT extern const char kEnableOverscrollNotifications[];
-extern const char kEnablePinch[];
+CONTENT_EXPORT extern const char kEnablePinch[];
extern const char kEnablePreparsedJsCaching[];
CONTENT_EXPORT extern const char kEnablePrivilegedWebGLExtensions[];
extern const char kEnablePruneGpuCommandBuffers[];
CONTENT_EXPORT extern const char kEnableRegionBasedColumns[];
-extern const char kEnableSandboxLogging[];
+CONTENT_EXPORT extern const char kEnableRepaintAfterLayout[];
+CONTENT_EXPORT extern const char kEnableSandboxLogging[];
extern const char kEnableSkiaBenchmarking[];
CONTENT_EXPORT extern const char kEnableSmoothScrolling[];
CONTENT_EXPORT extern const char kEnableSoftwareCompositing[];
@@ -156,28 +167,33 @@ CONTENT_EXPORT extern const char kEnableSpeechSynthesis[];
extern const char kEnableSSLCachedInfo[];
CONTENT_EXPORT extern const char kEnableStatsTable[];
extern const char kEnableStrictSiteIsolation[];
+CONTENT_EXPORT extern const char kEnableServiceWorker[];
CONTENT_EXPORT extern const char kEnableTcpFastOpen[];
CONTENT_EXPORT extern const char kEnableTextServicesFramework[];
CONTENT_EXPORT extern const char kEnableThreadedCompositing[];
-extern const char kEnableUserMediaScreenCapturing[];
-extern const char kEnableViewport[];
+CONTENT_EXPORT extern const char kEnableUniversalAcceleratedOverflowScroll[];
+CONTENT_EXPORT extern const char kEnableUserMediaScreenCapturing[];
+CONTENT_EXPORT extern const char kEnableViewport[];
+CONTENT_EXPORT extern const char kEnableViewportMeta[];
+CONTENT_EXPORT extern const char kMainFrameResizesAreOrientationChanges[];
extern const char kEnableVisualWordMovement[];
CONTENT_EXPORT extern const char kEnableVtune[];
+// FIXME: Remove this once Web Animations CSS is enabled by default in Blink.
extern const char kEnableWebAnimationsCSS[];
extern const char kEnableWebAnimationsSVG[];
CONTENT_EXPORT extern const char kEnableWebGLDraftExtensions[];
-extern const char kEnableWebMIDI[];
+CONTENT_EXPORT extern const char kEnableWebMIDI[];
CONTENT_EXPORT extern const char kExtraPluginDir[];
CONTENT_EXPORT extern const char kForceCompositingMode[];
-extern const char kForceFieldTrials[];
+CONTENT_EXPORT extern const char kForceFieldTrials[];
CONTENT_EXPORT extern const char kForceRendererAccessibility[];
extern const char kGpuDeviceID[];
extern const char kGpuDriverVendor[];
extern const char kGpuDriverVersion[];
extern const char kGpuLauncher[];
CONTENT_EXPORT extern const char kGpuProcess[];
-extern const char kGpuSandboxAllowSysVShm[];
-extern const char kGpuStartupDialog[];
+CONTENT_EXPORT extern const char kGpuSandboxAllowSysVShm[];
+CONTENT_EXPORT extern const char kGpuStartupDialog[];
extern const char kGpuVendorID[];
CONTENT_EXPORT extern const char kHostResolverRules[];
CONTENT_EXPORT extern const char kIgnoreCertificateErrors[];
@@ -186,6 +202,7 @@ extern const char kInProcessGPU[];
extern const char kInProcessPlugins[];
CONTENT_EXPORT extern const char kJavaScriptFlags[];
extern const char kLoadPlugin[];
+CONTENT_EXPORT extern const char kLogGpuControlListDecisions[];
CONTENT_EXPORT extern const char kLoggingLevel[];
CONTENT_EXPORT extern const char kLogNetLog[];
extern const char kLogPluginMessages[];
@@ -195,14 +212,13 @@ extern const char kMemoryMetrics[];
CONTENT_EXPORT extern const char kMuteAudio[];
CONTENT_EXPORT extern const char kNoReferrers[];
CONTENT_EXPORT extern const char kNoSandbox[];
-CONTENT_EXPORT extern const char kNoTouchToRendererWhileScrolling[];
CONTENT_EXPORT extern const char kOverscrollHistoryNavigation[];
extern const char kPluginLauncher[];
CONTENT_EXPORT extern const char kPluginPath[];
CONTENT_EXPORT extern const char kPluginProcess[];
extern const char kPluginStartupDialog[];
CONTENT_EXPORT extern const char kPpapiBrokerProcess[];
-extern const char kPpapiFlashArgs[];
+CONTENT_EXPORT extern const char kPpapiFlashArgs[];
CONTENT_EXPORT extern const char kPpapiInProcess[];
extern const char kPpapiPluginLauncher[];
CONTENT_EXPORT extern const char kPpapiPluginProcess[];
@@ -211,13 +227,14 @@ CONTENT_EXPORT extern const char kProcessPerSite[];
CONTENT_EXPORT extern const char kProcessPerTab[];
CONTENT_EXPORT extern const char kProcessType[];
extern const char kReduceGpuSandbox[];
+CONTENT_EXPORT extern const char kReduceSecurityForTesting[];
CONTENT_EXPORT extern const char kRegisterPepperPlugins[];
CONTENT_EXPORT extern const char kRemoteDebuggingPort[];
CONTENT_EXPORT extern const char kRendererAssertTest[];
extern const char kRendererCmdPrefix[];
CONTENT_EXPORT extern const char kRendererProcess[];
-extern const char kRendererProcessLimit[];
-extern const char kRendererStartupDialog[];
+CONTENT_EXPORT extern const char kRendererProcessLimit[];
+CONTENT_EXPORT extern const char kRendererStartupDialog[];
extern const char kSandboxIPCProcess[];
CONTENT_EXPORT extern const char kScrollEndEffect[];
extern const char kShowPaintRects[];
@@ -227,12 +244,12 @@ CONTENT_EXPORT extern const char kSitePerProcess[];
CONTENT_EXPORT extern const char kSkipGpuDataLoading[];
extern const char kSpeechRecognitionWebserviceKey[];
CONTENT_EXPORT extern const char kStatsCollectionController[];
-extern const char kTabCaptureDownscaleQuality[];
-extern const char kTabCaptureUpscaleQuality[];
-extern const char kTapDownDeferralTimeMs[];
+CONTENT_EXPORT extern const char kTabCaptureDownscaleQuality[];
+CONTENT_EXPORT extern const char kTabCaptureUpscaleQuality[];
CONTENT_EXPORT extern const char kTestingFixedHttpPort[];
CONTENT_EXPORT extern const char kTestingFixedHttpsPort[];
CONTENT_EXPORT extern const char kTestSandbox[];
+CONTENT_EXPORT extern const char kTouchAckTimeoutDelayMs[];
CONTENT_EXPORT extern const char kTraceShutdown[];
extern const char kTraceShutdownFile[];
extern const char kTraceStartup[];
@@ -250,17 +267,21 @@ extern const char kUtilityProcessAllowedDir[];
CONTENT_EXPORT extern const char kUtilityProcessEnableMDns[];
CONTENT_EXPORT extern const char kWaitForDebuggerChildren[];
extern const char kWebCoreLogChannels[];
+CONTENT_EXPORT extern const char kWebGLCommandBufferSizeKb[];
CONTENT_EXPORT extern const char kWorkerProcess[];
CONTENT_EXPORT extern const char kZygoteCmdPrefix[];
CONTENT_EXPORT extern const char kZygoteProcess[];
#if defined(ENABLE_WEBRTC)
+CONTENT_EXPORT extern const char kEnableAudioTrackProcessing[];
CONTENT_EXPORT extern const char kDisableDeviceEnumeration[];
CONTENT_EXPORT extern const char kDisableSCTPDataChannels[];
CONTENT_EXPORT extern const char kDisableWebRtcHWDecoding[];
-extern const char kDisableWebRtcHWEncoding[];
+CONTENT_EXPORT extern const char kDisableWebRtcEncryption[];
+CONTENT_EXPORT extern const char kDisableWebRtcHWEncoding[];
extern const char kEnableWebRtcAecRecordings[];
extern const char kEnableWebRtcTcpServerSocket[];
+CONTENT_EXPORT extern const char kEnableWebRtcHWVp8Encoding[];
#endif
#if defined(OS_ANDROID)
@@ -275,6 +296,12 @@ extern const char kNetworkCountryIso[];
CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
#endif
+#if defined(OS_ANDROID) && defined(ARCH_CPU_X86)
+CONTENT_EXPORT extern const char kEnableWebAudio[];
+#else
+CONTENT_EXPORT extern const char kDisableWebAudio[];
+#endif
+
#if defined(OS_CHROMEOS)
CONTENT_EXPORT extern const char kDisablePanelFitting[];
#endif
@@ -282,17 +309,13 @@ CONTENT_EXPORT extern const char kDisablePanelFitting[];
#if defined(OS_MACOSX) && !defined(OS_IOS)
extern const char kDisableCarbonInterposing[];
extern const char kDisableCoreAnimationPlugins[];
-extern const char kUseCoreAnimation[];
+CONTENT_EXPORT extern const char kUseCoreAnimation[];
#endif
#if defined(OS_POSIX)
extern const char kChildCleanExit[];
#endif
-#if defined(USE_AURA)
-CONTENT_EXPORT extern const char kTestCompositor[];
-#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/context_menu_params.cc b/chromium/content/public/common/context_menu_params.cc
index 5ec5a1f7a4e..9d5438aa99f 100644
--- a/chromium/content/public/common/context_menu_params.cc
+++ b/chromium/content/public/common/context_menu_params.cc
@@ -15,7 +15,7 @@ CustomContextMenuContext::CustomContextMenuContext()
}
ContextMenuParams::ContextMenuParams()
- : media_type(WebKit::WebContextMenuData::MediaTypeNone),
+ : media_type(blink::WebContextMenuData::MediaTypeNone),
x(0),
y(0),
has_image_contents(true),
@@ -25,16 +25,14 @@ ContextMenuParams::ContextMenuParams()
speech_input_enabled(false),
spellcheck_enabled(false),
is_editable(false),
-#if defined(OS_MACOSX)
writing_direction_default(
- WebKit::WebContextMenuData::CheckableMenuItemDisabled),
+ blink::WebContextMenuData::CheckableMenuItemDisabled),
writing_direction_left_to_right(
- WebKit::WebContextMenuData::CheckableMenuItemEnabled),
+ blink::WebContextMenuData::CheckableMenuItemEnabled),
writing_direction_right_to_left(
- WebKit::WebContextMenuData::CheckableMenuItemEnabled),
-#endif // OS_MACOSX
+ blink::WebContextMenuData::CheckableMenuItemEnabled),
edit_flags(0),
- referrer_policy(WebKit::WebReferrerPolicyDefault) {
+ referrer_policy(blink::WebReferrerPolicyDefault) {
}
ContextMenuParams::~ContextMenuParams() {
diff --git a/chromium/content/public/common/context_menu_params.h b/chromium/content/public/common/context_menu_params.h
index 053d5ad77ce..aca84e25351 100644
--- a/chromium/content/public/common/context_menu_params.h
+++ b/chromium/content/public/common/context_menu_params.h
@@ -48,7 +48,7 @@ struct CONTENT_EXPORT ContextMenuParams {
~ContextMenuParams();
// This is the type of Context Node that the context menu was invoked on.
- WebKit::WebContextMenuData::MediaType media_type;
+ blink::WebContextMenuData::MediaType media_type;
// These values represent the coordinates of the mouse when the context menu
// was invoked. Coords are relative to the associated RenderView's origin.
@@ -62,7 +62,7 @@ struct CONTENT_EXPORT ContextMenuParams {
// The text associated with the link. May be an empty string if the contents
// of the link are an image.
// Will be empty if link_url is empty.
- string16 link_text;
+ base::string16 link_text;
// The link URL to be used ONLY for "copy link address". We don't validate
// this field in the frontend process.
@@ -99,11 +99,11 @@ struct CONTENT_EXPORT ContextMenuParams {
int media_flags;
// This is the text of the selection that the context menu was invoked on.
- string16 selection_text;
+ base::string16 selection_text;
// The misspelled word under the cursor, if any. Used to generate the
// |dictionary_suggestions| list.
- string16 misspelled_word;
+ base::string16 misspelled_word;
// The identifier of the misspelling under the cursor, if any.
uint32 misspelling_hash;
@@ -113,7 +113,7 @@ struct CONTENT_EXPORT ContextMenuParams {
// by intercepting ViewHostMsg_ContextMenu in ResourceMessageFilter
// and populating dictionary_suggestions if the type is EDITABLE
// and the misspelled_word is not empty.
- std::vector<string16> dictionary_suggestions;
+ std::vector<base::string16> dictionary_suggestions;
// If editable, flag for whether node is speech-input enabled.
bool speech_input_enabled;
@@ -124,13 +124,10 @@ struct CONTENT_EXPORT ContextMenuParams {
// Whether context is editable.
bool is_editable;
-#if defined(OS_MACOSX)
// Writing direction menu items.
- // Currently only used on OS X.
int writing_direction_default;
int writing_direction_left_to_right;
int writing_direction_right_to_left;
-#endif // OS_MACOSX
// These flags indicate to the browser whether the renderer believes it is
// able to perform the corresponding action.
@@ -143,7 +140,7 @@ struct CONTENT_EXPORT ContextMenuParams {
std::string frame_charset;
// The referrer policy of the frame on which the menu is invoked.
- WebKit::WebReferrerPolicy referrer_policy;
+ blink::WebReferrerPolicy referrer_policy;
CustomContextMenuContext custom_context;
std::vector<MenuItem> custom_items;
diff --git a/chromium/content/public/common/desktop_media_id.cc b/chromium/content/public/common/desktop_media_id.cc
deleted file mode 100644
index 82ebe9ca4d2..00000000000
--- a/chromium/content/public/common/desktop_media_id.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/common/desktop_media_id.h"
-
-namespace content {
-
-// static
-DesktopMediaID DesktopMediaID::Parse(const std::string& str) {
- if (str == "screen")
- return DesktopMediaID(TYPE_SCREEN, 0);
-
- std::string window_prefix("window:");
- if (StartsWithASCII(str, window_prefix, true)) {
- int64 id;
- if (!base::StringToInt64(str.substr(window_prefix.size()), &id))
- return DesktopMediaID(TYPE_NONE, 0);
- return DesktopMediaID(TYPE_WINDOW, id);
- }
-
- return DesktopMediaID(TYPE_NONE, 0);
-}
-
-std::string DesktopMediaID::ToString() {
- switch (type) {
- case TYPE_NONE:
- NOTREACHED();
- return std::string();
-
- case TYPE_SCREEN:
- return "screen";
-
- case TYPE_WINDOW:
- return "window:" + base::Int64ToString(id);
- }
- NOTREACHED();
- return std::string();
-}
-
-} // namespace content
diff --git a/chromium/content/public/common/drop_data.cc b/chromium/content/public/common/drop_data.cc
index 9e42ddac2f0..3536efb21cf 100644
--- a/chromium/content/public/common/drop_data.cc
+++ b/chromium/content/public/common/drop_data.cc
@@ -16,7 +16,7 @@ DropData::FileInfo::FileInfo(const base::string16& path,
}
DropData::DropData()
- : referrer_policy(WebKit::WebReferrerPolicyDefault) {
+ : referrer_policy(blink::WebReferrerPolicyDefault) {
}
DropData::~DropData() {
diff --git a/chromium/content/public/common/drop_data.h b/chromium/content/public/common/drop_data.h
index 008b3f9ae34..74ad79ddd71 100644
--- a/chromium/content/public/common/drop_data.h
+++ b/chromium/content/public/common/drop_data.h
@@ -44,7 +44,7 @@ struct CONTENT_EXPORT DropData {
// Referrer policy to use when dragging a link out of the webview results in
// a download.
- WebKit::WebReferrerPolicy referrer_policy;
+ blink::WebReferrerPolicy referrer_policy;
// User is dropping one or more files on the webview.
std::vector<FileInfo> filenames;
diff --git a/chromium/content/public/common/file_chooser_params.h b/chromium/content/public/common/file_chooser_params.h
index 0c7f1e41ce7..46043269a57 100644
--- a/chromium/content/public/common/file_chooser_params.h
+++ b/chromium/content/public/common/file_chooser_params.h
@@ -37,14 +37,14 @@ struct CONTENT_EXPORT FileChooserParams {
// Title to be used for the dialog. This may be empty for the default title,
// which will be either "Open" or "Save" depending on the mode.
- string16 title;
+ base::string16 title;
// Default file name to select in the dialog.
base::FilePath default_file_name;
// A list of valid lower-cased MIME types or file extensions specified in an
// input element. It is used to restrict selectable files to such types.
- std::vector<string16> accept_types;
+ std::vector<base::string16> accept_types;
#if defined(OS_ANDROID)
// See http://www.w3.org/TR/html-media-capture for more information.
diff --git a/chromium/content/public/common/media_stream_request.cc b/chromium/content/public/common/media_stream_request.cc
index d343e76342e..b15a0b04879 100644
--- a/chromium/content/public/common/media_stream_request.cc
+++ b/chromium/content/public/common/media_stream_request.cc
@@ -11,7 +11,7 @@ namespace content {
bool IsAudioMediaType(MediaStreamType type) {
return (type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
type == content::MEDIA_TAB_AUDIO_CAPTURE ||
- type == content::MEDIA_SYSTEM_AUDIO_CAPTURE);
+ type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE);
}
bool IsVideoMediaType(MediaStreamType type) {
@@ -58,11 +58,19 @@ MediaStreamDevice::MediaStreamDevice(
MediaStreamDevice::~MediaStreamDevice() {}
+bool MediaStreamDevice::IsEqual(const MediaStreamDevice& second) const {
+ const AudioDeviceParameters& input_second = second.input;
+ return type == second.type &&
+ name == second.name &&
+ id == second.id &&
+ input.sample_rate == input_second.sample_rate &&
+ input.channel_layout == input_second.channel_layout;
+}
+
MediaStreamRequest::MediaStreamRequest(
int render_process_id,
int render_view_id,
int page_request_id,
- const std::string& tab_capture_device_id,
const GURL& security_origin,
MediaStreamRequestType request_type,
const std::string& requested_audio_device_id,
@@ -72,7 +80,6 @@ MediaStreamRequest::MediaStreamRequest(
: render_process_id(render_process_id),
render_view_id(render_view_id),
page_request_id(page_request_id),
- tab_capture_device_id(tab_capture_device_id),
security_origin(security_origin),
request_type(request_type),
requested_audio_device_id(requested_audio_device_id),
diff --git a/chromium/content/public/common/media_stream_request.h b/chromium/content/public/common/media_stream_request.h
index 1c844cc7e19..c4c838fb6e3 100644
--- a/chromium/content/public/common/media_stream_request.h
+++ b/chromium/content/public/common/media_stream_request.h
@@ -26,9 +26,6 @@ enum MediaStreamType {
MEDIA_DEVICE_VIDEO_CAPTURE,
// Mirroring of a browser tab.
- //
- // TODO(serygeu): Remove these values and use MEDIA_DESKTOP_VIDEO_CAPTURE and
- // MEDIA_DESKTOP_AUDIO_CAPTURE.
MEDIA_TAB_AUDIO_CAPTURE,
MEDIA_TAB_VIDEO_CAPTURE,
@@ -38,7 +35,7 @@ enum MediaStreamType {
// Capture system audio (post-mix loopback stream).
//
// TODO(sergeyu): Replace with MEDIA_DESKTOP_AUDIO_CAPTURE.
- MEDIA_SYSTEM_AUDIO_CAPTURE,
+ MEDIA_LOOPBACK_AUDIO_CAPTURE,
NUM_MEDIA_TYPES
};
@@ -87,6 +84,8 @@ struct CONTENT_EXPORT MediaStreamDevice {
~MediaStreamDevice();
+ bool IsEqual(const MediaStreamDevice& second) const;
+
// The device's type.
MediaStreamType type;
@@ -107,14 +106,15 @@ struct CONTENT_EXPORT MediaStreamDevice {
// in media::AudioParameters.
struct AudioDeviceParameters {
AudioDeviceParameters()
- : sample_rate(), channel_layout(), frames_per_buffer() {
+ : sample_rate(), channel_layout(), frames_per_buffer(), effects() {
}
AudioDeviceParameters(int sample_rate, int channel_layout,
- int frames_per_buffer)
+ int frames_per_buffer)
: sample_rate(sample_rate),
channel_layout(channel_layout),
- frames_per_buffer(frames_per_buffer) {
+ frames_per_buffer(frames_per_buffer),
+ effects() {
}
// Preferred sample rate in samples per second for the device.
@@ -130,6 +130,9 @@ struct CONTENT_EXPORT MediaStreamDevice {
// expected browser side settings and avoid unnecessary buffering.
// See media::AudioParameters for more.
int frames_per_buffer;
+
+ // See media::AudioParameters::PlatformEffectsMask.
+ int effects;
};
// These below two member variables are valid only when the type of device is
@@ -150,9 +153,6 @@ typedef std::vector<MediaStreamDevice> MediaStreamDevices;
typedef std::map<MediaStreamType, MediaStreamDevices> MediaStreamDeviceMap;
// Represents a request for media streams (audio/video).
-// It looks like the last 4 parameters should use StreamOptions instead, but
-// StreamOption depends on media_stream_request.h because it needs
-// MediaStreamDevice.
// TODO(vrk): Decouple MediaStreamDevice from this header file so that
// media_stream_options.h no longer depends on this file.
// TODO(vrk,justinlin,wjia): Figure out a way to share this code cleanly between
@@ -164,7 +164,6 @@ struct CONTENT_EXPORT MediaStreamRequest {
int render_process_id,
int render_view_id,
int page_request_id,
- const std::string& tab_capture_device_id,
const GURL& security_origin,
MediaStreamRequestType request_type,
const std::string& requested_audio_device_id,
@@ -174,10 +173,14 @@ struct CONTENT_EXPORT MediaStreamRequest {
~MediaStreamRequest();
- // The render process id generating this request.
+ // This is the render process id for the renderer associated with generating
+ // frames for a MediaStream. Any indicators associated with a capture will be
+ // displayed for this renderer.
int render_process_id;
- // The render view id generating this request.
+ // This is the render view id for the renderer associated with generating
+ // frames for a MediaStream. Any indicators associated with a capture will be
+ // displayed for this renderer.
int render_view_id;
// The unique id combined with render_process_id and render_view_id for
diff --git a/chromium/content/public/common/menu_item.h b/chromium/content/public/common/menu_item.h
index c6c20bc99e7..982832c7334 100644
--- a/chromium/content/public/common/menu_item.h
+++ b/chromium/content/public/common/menu_item.h
@@ -17,10 +17,10 @@ namespace content {
// custom entries of the context menu.
struct CONTENT_EXPORT MenuItem {
enum Type {
- OPTION = WebKit::WebMenuItemInfo::Option,
- CHECKABLE_OPTION = WebKit::WebMenuItemInfo::CheckableOption,
- GROUP = WebKit::WebMenuItemInfo::Group,
- SEPARATOR = WebKit::WebMenuItemInfo::Separator,
+ OPTION = blink::WebMenuItemInfo::Option,
+ CHECKABLE_OPTION = blink::WebMenuItemInfo::CheckableOption,
+ GROUP = blink::WebMenuItemInfo::Group,
+ SEPARATOR = blink::WebMenuItemInfo::Separator,
SUBMENU // This is currently only used by Pepper, not by WebKit.
};
diff --git a/chromium/content/common/p2p_sockets.h b/chromium/content/public/common/p2p_socket_type.h
index 6f09366c9b8..a272f8c075c 100644
--- a/chromium/content/common/p2p_sockets.h
+++ b/chromium/content/public/common/p2p_socket_type.h
@@ -1,12 +1,12 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
// This file defines some basic types used by the P2P-related IPC
// messages.
-#ifndef CONTENT_COMMON_P2P_SOCKETS_H_
-#define CONTENT_COMMON_P2P_SOCKETS_H_
+#ifndef CONTENT_PUBLIC_COMMON_P2P_SOCKET_TYPE_H_
+#define CONTENT_PUBLIC_COMMON_P2P_SOCKET_TYPE_H_
namespace content {
@@ -25,4 +25,4 @@ enum P2PSocketType {
} // namespace content
-#endif // CONTENT_COMMON_P2P_SOCKETS_H_
+#endif // CONTENT_PUBLIC_COMMON_P2P_SOCKET_TYPE_H_
diff --git a/chromium/content/public/common/page_state.cc b/chromium/content/public/common/page_state.cc
index 54c00e3dc01..1e429b80df6 100644
--- a/chromium/content/public/common/page_state.cc
+++ b/chromium/content/public/common/page_state.cc
@@ -76,13 +76,13 @@ PageState PageState::CreateForTesting(
state.top.http_body.is_null = false;
if (optional_body_data) {
ExplodedHttpBodyElement element;
- element.type = WebKit::WebHTTPBody::Element::TypeData;
+ element.type = blink::WebHTTPBody::Element::TypeData;
element.data = optional_body_data;
state.top.http_body.elements.push_back(element);
}
if (optional_body_file_path) {
ExplodedHttpBodyElement element;
- element.type = WebKit::WebHTTPBody::Element::TypeFile;
+ element.type = blink::WebHTTPBody::Element::TypeFile;
element.file_path =
ToNullableString16(optional_body_file_path->AsUTF8Unsafe());
state.top.http_body.elements.push_back(element);
diff --git a/chromium/content/public/common/referrer.h b/chromium/content/public/common/referrer.h
index c30f4b8bb7e..b10bfd6c28e 100644
--- a/chromium/content/public/common/referrer.h
+++ b/chromium/content/public/common/referrer.h
@@ -15,14 +15,14 @@ namespace content {
// applied to this URL. When passing around referrers that will eventually end
// up being used for URL requests, always use this struct.
struct CONTENT_EXPORT Referrer {
- Referrer(const GURL& url, WebKit::WebReferrerPolicy policy) : url(url),
+ Referrer(const GURL& url, blink::WebReferrerPolicy policy) : url(url),
policy(policy) {
}
- Referrer() : policy(WebKit::WebReferrerPolicyDefault) {
+ Referrer() : policy(blink::WebReferrerPolicyDefault) {
}
GURL url;
- WebKit::WebReferrerPolicy policy;
+ blink::WebReferrerPolicy policy;
};
} // namespace content
diff --git a/chromium/content/public/common/renderer_preferences.cc b/chromium/content/public/common/renderer_preferences.cc
index 9d3d12f25f0..8213c95dd94 100644
--- a/chromium/content/public/common/renderer_preferences.cc
+++ b/chromium/content/public/common/renderer_preferences.cc
@@ -37,6 +37,7 @@ RendererPreferences::RendererPreferences()
inactive_selection_fg_color(SkColorSetRGB(50, 50, 50)),
browser_handles_non_local_top_level_requests(false),
browser_handles_all_top_level_requests(false),
+ browser_handles_all_top_level_link_clicks(false),
caret_blink_interval(0.5),
use_custom_colors(true),
enable_referrers(true),
diff --git a/chromium/content/public/common/renderer_preferences.h b/chromium/content/public/common/renderer_preferences.h
index acbc197f3f0..61d334995e7 100644
--- a/chromium/content/public/common/renderer_preferences.h
+++ b/chromium/content/public/common/renderer_preferences.h
@@ -97,6 +97,9 @@ struct CONTENT_EXPORT RendererPreferences {
// Browser wants a look at all top-level navigation requests.
bool browser_handles_all_top_level_requests;
+ // Browser wants a look at all top-level link clicks.
+ bool browser_handles_all_top_level_link_clicks;
+
// Cursor blink rate in seconds.
// Currently only changed from default on Linux. Uses |gtk-cursor-blink|
// from GtkSettings.
diff --git a/chromium/content/public/common/result_codes_list.h b/chromium/content/public/common/result_codes_list.h
index 9f6453b1c0e..5a79f754dba 100644
--- a/chromium/content/public/common/result_codes_list.h
+++ b/chromium/content/public/common/result_codes_list.h
@@ -35,4 +35,10 @@ RESULT_CODE(FAILED_TO_REGISTER_JNI, 4)
// Failed to find and load the native library.
RESULT_CODE(NATIVE_LIBRARY_LOAD_FAILED, 5)
+
+// Wrong version of library loaded
+RESULT_CODE(NATIVE_LIBRARY_WRONG_VERSION, 6)
+
+// Native library startup failed
+RESULT_CODE(NATIVE_STARTUP_FAILED, 7)
#endif
diff --git a/chromium/content/public/common/sandbox_init.h b/chromium/content/public/common/sandbox_init.h
index 86043226f17..f709d23ea2a 100644
--- a/chromium/content/public/common/sandbox_init.h
+++ b/chromium/content/public/common/sandbox_init.h
@@ -5,15 +5,11 @@
#ifndef CONTENT_PUBLIC_COMMON_SANDBOX_INIT_H_
#define CONTENT_PUBLIC_COMMON_SANDBOX_INIT_H_
-#include "base/callback_forward.h"
+#include "base/memory/scoped_ptr.h"
#include "base/process/process.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
-#if defined(OS_LINUX)
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy_forward.h"
-#endif // defined(OS_LINUX)
-
class CommandLine;
namespace base {
@@ -21,6 +17,7 @@ class FilePath;
}
namespace sandbox {
+class SandboxBPFPolicy;
struct SandboxInterfaceInfo;
}
@@ -89,14 +86,13 @@ class SandboxInitializerDelegate;
// Initialize a seccomp-bpf sandbox. |policy| may not be NULL.
// Returns true if the sandbox has been properly engaged.
-CONTENT_EXPORT bool InitializeSandbox(playground2::BpfSandboxPolicy policy);
-
-// Return a Callback implementing the "baseline" policy. This is used by a
-// SandboxInitializerDelegate to implement a policy that is derived from
-// the baseline.
-CONTENT_EXPORT playground2::BpfSandboxPolicyCallback
- GetBpfSandboxBaselinePolicy();
+CONTENT_EXPORT bool InitializeSandbox(
+ scoped_ptr<sandbox::SandboxBPFPolicy> policy);
+// Return a "baseline" policy. This is used by a SandboxInitializerDelegate to
+// implement a policy that is derived from the baseline.
+CONTENT_EXPORT scoped_ptr<sandbox::SandboxBPFPolicy>
+GetBPFSandboxBaselinePolicy();
#endif // defined(OS_LINUX)
} // namespace content
diff --git a/chromium/content/public/common/sandbox_linux.h b/chromium/content/public/common/sandbox_linux.h
index 6824d55c1ea..4d2db390759 100644
--- a/chromium/content/public/common/sandbox_linux.h
+++ b/chromium/content/public/common/sandbox_linux.h
@@ -21,7 +21,10 @@ enum LinuxSandboxStatus {
kSandboxLinuxNetNS = 1 << 2,
// seccomp-bpf sandbox active.
- kSandboxLinuxSeccompBpf = 1 << 3,
+ kSandboxLinuxSeccompBPF = 1 << 3,
+
+ // A flag that denotes an invalid sandbox status.
+ kSandboxLinuxInvalid = 1 << 31,
};
} // namespace content
diff --git a/chromium/content/public/common/show_desktop_notification_params.cc b/chromium/content/public/common/show_desktop_notification_params.cc
index b7e35a6624d..4914cb0574f 100644
--- a/chromium/content/public/common/show_desktop_notification_params.cc
+++ b/chromium/content/public/common/show_desktop_notification_params.cc
@@ -7,7 +7,7 @@
namespace content {
ShowDesktopNotificationHostMsgParams::ShowDesktopNotificationHostMsgParams()
- : is_html(false), direction(WebKit::WebTextDirectionDefault),
+ : direction(blink::WebTextDirectionDefault),
notification_id(0) {
}
diff --git a/chromium/content/public/common/show_desktop_notification_params.h b/chromium/content/public/common/show_desktop_notification_params.h
index ef129cca08c..5ff4511a472 100644
--- a/chromium/content/public/common/show_desktop_notification_params.h
+++ b/chromium/content/public/common/show_desktop_notification_params.h
@@ -19,23 +19,17 @@ struct CONTENT_EXPORT ShowDesktopNotificationHostMsgParams {
// URL which is the origin that created this notification.
GURL origin;
- // True if this is HTML
- bool is_html;
-
- // URL which contains the HTML contents (if is_html is true), otherwise empty.
- GURL contents_url;
-
// Contents of the notification if is_html is false.
GURL icon_url;
- string16 title;
- string16 body;
+ base::string16 title;
+ base::string16 body;
// Directionality of the notification.
- WebKit::WebTextDirection direction;
+ blink::WebTextDirection direction;
// ReplaceID if this notification should replace an existing one; may be
// empty if no replacement is called for.
- string16 replace_id;
+ base::string16 replace_id;
// Notification ID for sending events back for this notification.
int notification_id;
diff --git a/chromium/content/public/common/signed_certificate_timestamp_id_and_status.cc b/chromium/content/public/common/signed_certificate_timestamp_id_and_status.cc
new file mode 100644
index 00000000000..e61ca58a238
--- /dev/null
+++ b/chromium/content/public/common/signed_certificate_timestamp_id_and_status.cc
@@ -0,0 +1,18 @@
+// 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/public/common/signed_certificate_timestamp_id_and_status.h"
+
+namespace content {
+
+SignedCertificateTimestampIDAndStatus::SignedCertificateTimestampIDAndStatus(
+ int id, net::ct::SCTVerifyStatus status)
+ : id(id), status(status) {}
+
+bool SignedCertificateTimestampIDAndStatus::operator==(
+ const SignedCertificateTimestampIDAndStatus& other) const {
+ return id == other.id && status == other.status;
+}
+
+} // namespace content
diff --git a/chromium/content/public/common/signed_certificate_timestamp_id_and_status.h b/chromium/content/public/common/signed_certificate_timestamp_id_and_status.h
new file mode 100644
index 00000000000..66da00832ff
--- /dev/null
+++ b/chromium/content/public/common/signed_certificate_timestamp_id_and_status.h
@@ -0,0 +1,32 @@
+// 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_PUBLIC_COMMON_SIGNED_CERTIFICATE_TIMESTAMP_ID_AND_STATUS_H_
+#define CONTENT_PUBLIC_COMMON_SIGNED_CERTIFICATE_TIMESTAMP_ID_AND_STATUS_H_
+
+#include <vector>
+
+#include "content/common/content_export.h"
+#include "net/cert/sct_status_flags.h"
+
+namespace content {
+
+// Holds the ID of a SignedCertificateTimestamp (as assigned by
+// SignedCertificateTimestampStore), and its verification status.
+struct CONTENT_EXPORT SignedCertificateTimestampIDAndStatus {
+ SignedCertificateTimestampIDAndStatus(
+ int id, net::ct::SCTVerifyStatus status);
+
+ bool operator==(const SignedCertificateTimestampIDAndStatus& other) const;
+
+ int id;
+ net::ct::SCTVerifyStatus status;
+};
+
+typedef std::vector<SignedCertificateTimestampIDAndStatus>
+ SignedCertificateTimestampIDStatusList;
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_SIGNED_CERTIFICATE_TIMESTAMP_ID_AND_STATUS_H_
diff --git a/chromium/content/public/common/speech_recognition_result.h b/chromium/content/public/common/speech_recognition_result.h
index 78044e5b5e5..aa1a02c31e1 100644
--- a/chromium/content/public/common/speech_recognition_result.h
+++ b/chromium/content/public/common/speech_recognition_result.h
@@ -14,12 +14,12 @@
namespace content {
struct SpeechRecognitionHypothesis {
- string16 utterance;
+ base::string16 utterance;
double confidence;
SpeechRecognitionHypothesis() : confidence(0.0) {}
- SpeechRecognitionHypothesis(const string16& utterance_value,
+ SpeechRecognitionHypothesis(const base::string16& utterance_value,
double confidence_value)
: utterance(utterance_value),
confidence(confidence_value) {
diff --git a/chromium/content/public/common/ssl_status.cc b/chromium/content/public/common/ssl_status.cc
index 7f6aeeca685..4b114aca453 100644
--- a/chromium/content/public/common/ssl_status.cc
+++ b/chromium/content/public/common/ssl_status.cc
@@ -15,4 +15,6 @@ SSLStatus::SSLStatus()
content_status(NORMAL_CONTENT) {
}
+SSLStatus::~SSLStatus() {}
+
} // namespace content
diff --git a/chromium/content/public/common/ssl_status.h b/chromium/content/public/common/ssl_status.h
index 049a5afeef1..6e23eb7dd75 100644
--- a/chromium/content/public/common/ssl_status.h
+++ b/chromium/content/public/common/ssl_status.h
@@ -7,6 +7,7 @@
#include "content/common/content_export.h"
#include "content/public/common/security_style.h"
+#include "content/public/common/signed_certificate_timestamp_id_and_status.h"
#include "net/cert/cert_status_flags.h"
namespace content {
@@ -29,13 +30,16 @@ struct CONTENT_EXPORT SSLStatus {
};
SSLStatus();
+ ~SSLStatus();
bool Equals(const SSLStatus& status) const {
return security_style == status.security_style &&
cert_id == status.cert_id &&
cert_status == status.cert_status &&
security_bits == status.security_bits &&
- content_status == status.content_status;
+ content_status == status.content_status &&
+ signed_certificate_timestamp_ids ==
+ status.signed_certificate_timestamp_ids;
}
content::SecurityStyle security_style;
@@ -45,6 +49,7 @@ struct CONTENT_EXPORT SSLStatus {
int connection_status;
// A combination of the ContentStatusFlags above.
int content_status;
+ SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
};
} // namespace content
diff --git a/chromium/content/public/common/url_constants.cc b/chromium/content/public/common/url_constants.cc
index cee29767dda..261dbc9c47f 100644
--- a/chromium/content/public/common/url_constants.cc
+++ b/chromium/content/public/common/url_constants.cc
@@ -12,17 +12,16 @@ const char kBlobScheme[] = "blob";
// Before adding new chrome schemes please check with security@chromium.org.
// There are security implications associated with introducing new schemes.
const char kChromeDevToolsScheme[] = "chrome-devtools";
-const char kChromeInternalScheme[] = "chrome-internal";
const char kChromeUIScheme[] = "chrome";
const char kDataScheme[] = "data";
const char kFileScheme[] = "file";
const char kFileSystemScheme[] = "filesystem";
-const char kFtpScheme[] = "ftp";
-const char kGuestScheme[] = "chrome-guest";
} // namespace chrome
namespace content {
+const char kFtpScheme[] = "ftp";
+const char kGuestScheme[] = "chrome-guest";
const char kHttpScheme[] = "http";
const char kHttpsScheme[] = "https";
const char kJavaScriptScheme[] = "javascript";
diff --git a/chromium/content/public/common/url_constants.h b/chromium/content/public/common/url_constants.h
index cb8fe227b23..b2194f9d13f 100644
--- a/chromium/content/public/common/url_constants.h
+++ b/chromium/content/public/common/url_constants.h
@@ -18,17 +18,16 @@ namespace chrome {
CONTENT_EXPORT extern const char kAboutScheme[];
CONTENT_EXPORT extern const char kBlobScheme[];
CONTENT_EXPORT extern const char kChromeDevToolsScheme[];
-CONTENT_EXPORT extern const char kChromeInternalScheme[];
CONTENT_EXPORT extern const char kChromeUIScheme[]; // Used for WebUIs.
CONTENT_EXPORT extern const char kDataScheme[];
CONTENT_EXPORT extern const char kFileScheme[];
CONTENT_EXPORT extern const char kFileSystemScheme[];
-CONTENT_EXPORT extern const char kFtpScheme[];
-CONTENT_EXPORT extern const char kGuestScheme[];
} // namespace chrome
namespace content {
+CONTENT_EXPORT extern const char kFtpScheme[];
+CONTENT_EXPORT extern const char kGuestScheme[];
CONTENT_EXPORT extern const char kHttpScheme[];
CONTENT_EXPORT extern const char kHttpsScheme[];
CONTENT_EXPORT extern const char kJavaScriptScheme[];
@@ -76,7 +75,7 @@ CONTENT_EXPORT extern const char kChromeUINetworkViewCacheURL[];
CONTENT_EXPORT extern const char kChromeUIShorthangURL[];
// Special URL used to swap out a view being rendered by another process.
-extern const char kSwappedOutURL[];
+CONTENT_EXPORT extern const char kSwappedOutURL[];
} // namespace content
diff --git a/chromium/content/public/common/url_utils.cc b/chromium/content/public/common/url_utils.cc
index 2f08b9650b6..1aa1a97051e 100644
--- a/chromium/content/public/common/url_utils.cc
+++ b/chromium/content/public/common/url_utils.cc
@@ -4,13 +4,19 @@
#include "content/public/common/url_utils.h"
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/logging.h"
#include "build/build_config.h"
#include "content/common/savable_url_schemes.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "url/gurl.h"
namespace content {
+static size_t g_max_url_size = 2 * 1024 * 1024;
+
const char* const* GetSavableSchemes() {
return GetSavableSchemesInternal();
}
@@ -19,7 +25,6 @@ bool HasWebUIScheme(const GURL& url) {
return
#if !defined(OS_IOS)
url.SchemeIs(chrome::kChromeDevToolsScheme) ||
- url.SchemeIs(chrome::kChromeInternalScheme) ||
#endif
url.SchemeIs(chrome::kChromeUIScheme);
}
@@ -32,4 +37,17 @@ bool IsSavableURL(const GURL& url) {
return false;
}
+#if defined(OS_ANDROID)
+void SetMaxURLChars(size_t max_chars) {
+ // Check that it is not used by a multiprocesses embedder
+ CommandLine* cmd = CommandLine::ForCurrentProcess();
+ CHECK(cmd->HasSwitch(switches::kSingleProcess));
+ g_max_url_size = max_chars;
+}
+#endif
+
+size_t GetMaxURLChars() {
+ return g_max_url_size;
+}
+
} // namespace content
diff --git a/chromium/content/public/common/url_utils.h b/chromium/content/public/common/url_utils.h
index 0b67ab80972..1d1f68d245b 100644
--- a/chromium/content/public/common/url_utils.h
+++ b/chromium/content/public/common/url_utils.h
@@ -5,6 +5,9 @@
#ifndef CONTENT_PUBLIC_COMMON_URL_UTILS_H_
#define CONTENT_PUBLIC_COMMON_URL_UTILS_H_
+#include <stddef.h> // For size_t
+
+#include "build/build_config.h"
#include "content/common/content_export.h"
class GURL;
@@ -22,6 +25,28 @@ CONTENT_EXPORT bool HasWebUIScheme(const GURL& url);
// Check whether we can do the saving page operation for the specified URL.
CONTENT_EXPORT bool IsSavableURL(const GURL& url);
+#if defined(OS_ANDROID)
+// Set a new max size for URL's that we are willing to accept in the browser
+// process.
+// Should not be used except by Android WebView for backwards compatibility.
+// Should be called early in start up before forking child processes.
+//
+// This is for supporting legacy android apps, android webview needs to
+// support loading long data urls. In chrome, the url length is limited to 2M to
+// prevent renderer process DOS-ing the browser process. So only for android
+// webview, increase the limit to 20M, which is a large enough value to satisfy
+// legacy app compatibility requirements.
+CONTENT_EXPORT void SetMaxURLChars(size_t max_chars);
+#endif
+
+// The maximum number of characters in the URL that we're willing to accept
+// in the browser process. It is set low enough to avoid damage to the browser
+// but high enough that a web site can abuse location.hash for a little storage.
+// We have different values for "max accepted" and "max displayed" because
+// a data: URI may be legitimately massive, but the full URI would kill all
+// known operating systems if you dropped it into a UI control.
+CONTENT_EXPORT size_t GetMaxURLChars();
+
} // namespace content
#endif // CONTENT_PUBLIC_COMMON_URL_UTILS_H_
diff --git a/chromium/content/public/common/user_metrics_action.h b/chromium/content/public/common/user_metrics_action.h
new file mode 100644
index 00000000000..3b604ef3b8f
--- /dev/null
+++ b/chromium/content/public/common/user_metrics_action.h
@@ -0,0 +1,29 @@
+// 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_PUBLIC_COMMON_USER_METRICS_ACTION_H_
+#define CONTENT_PUBLIC_COMMON_USER_METRICS_ACTION_H_
+
+namespace content {
+
+// UserMetricsAction exists purely to standardize on the parameters passed to
+// UserMetrics. That way, our toolset can scan the source code reliable for
+// constructors and extract the associated string constants.
+// WARNING: When using UserMetricsAction, UserMetricsAction and a string literal
+// parameter must be on the same line, e.g.
+// RecordAction(
+// UserMetricsAction("my extremely long action name"));
+// or
+// RenderThread::Get()->RecordAction(
+// UserMetricsAction("my extremely long action name"));
+// because otherwise our processing scripts won't pick up on new actions.
+// Please see tools/metrics/actions/extract_actions.py for details.
+struct UserMetricsAction {
+ const char* str_;
+ explicit UserMetricsAction(const char* str) : str_(str) {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_USER_METRICS_ACTION_H_
diff --git a/chromium/content/public/common/webplugininfo.cc b/chromium/content/public/common/webplugininfo.cc
index fe2a02e8fe1..9f0c42f9ced 100644
--- a/chromium/content/public/common/webplugininfo.cc
+++ b/chromium/content/public/common/webplugininfo.cc
@@ -74,7 +74,7 @@ void WebPluginInfo::CreateVersionFromString(
// Remove spaces and ')' from the version string,
// Replace any instances of 'r', ',' or '(' with a dot.
std::string version = UTF16ToASCII(version_string);
- RemoveChars(version, ") ", &version);
+ base::RemoveChars(version, ") ", &version);
std::replace(version.begin(), version.end(), 'd', '.');
std::replace(version.begin(), version.end(), 'r', '.');
std::replace(version.begin(), version.end(), ',', '.');
diff --git a/chromium/content/public/common/window_container_type.cc b/chromium/content/public/common/window_container_type.cc
index a1099e6cfe0..ec3b12c6364 100644
--- a/chromium/content/public/common/window_container_type.cc
+++ b/chromium/content/public/common/window_container_type.cc
@@ -17,7 +17,7 @@ const char kPersistent[] = "persistent";
} // namespace
WindowContainerType WindowFeaturesToContainerType(
- const WebKit::WebWindowFeatures& window_features) {
+ const blink::WebWindowFeatures& window_features) {
bool background = false;
bool persistent = false;
diff --git a/chromium/content/public/common/window_container_type.h b/chromium/content/public/common/window_container_type.h
index 5aec6edceae..1d3b46fe6b1 100644
--- a/chromium/content/public/common/window_container_type.h
+++ b/chromium/content/public/common/window_container_type.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_PUBLIC_COMMON_WINDOW_CONTAINER_TYPE_H_
#define CONTENT_PUBLIC_COMMON_WINDOW_CONTAINER_TYPE_H_
-namespace WebKit {
+namespace blink {
struct WebWindowFeatures;
@@ -30,6 +30,6 @@ enum WindowContainerType {
// Conversion function:
WindowContainerType WindowFeaturesToContainerType(
- const WebKit::WebWindowFeatures& window_features);
+ const blink::WebWindowFeatures& window_features);
#endif // CONTENT_PUBLIC_COMMON_WINDOW_CONTAINER_TYPE_H_
diff --git a/chromium/content/public/common/zygote_fork_delegate_linux.h b/chromium/content/public/common/zygote_fork_delegate_linux.h
index a5ea9f2952f..87b4859c7cf 100644
--- a/chromium/content/public/common/zygote_fork_delegate_linux.h
+++ b/chromium/content/public/common/zygote_fork_delegate_linux.h
@@ -43,6 +43,18 @@ class ZygoteForkDelegate {
virtual bool CanHelp(const std::string& process_type, std::string* uma_name,
int* uma_sample, int* uma_boundary_value) = 0;
+ // Indexes of FDs in the vector passed to Fork().
+ enum {
+ // Used to pass in the descriptor for talking to the Browser
+ kBrowserFDIndex,
+ // The next two are used in the protocol for discovering the
+ // child processes real PID from within the SUID sandbox. See
+ // http://code.google.com/p/chromium/wiki/LinuxZygote
+ kDummyFDIndex,
+ kParentFDIndex,
+ kNumPassedFDs // Number of FDs in the vector passed to Fork().
+ };
+
// Delegate forks, returning a -1 on failure. Outside the
// suid sandbox, Fork() returns the Linux process ID.
// This method is not aware of any potential pid namespaces, so it'll
diff --git a/chromium/content/public/plugin/content_plugin_client.h b/chromium/content/public/plugin/content_plugin_client.h
index cff2ad516cc..f68c3ad56f6 100644
--- a/chromium/content/public/plugin/content_plugin_client.h
+++ b/chromium/content/public/plugin/content_plugin_client.h
@@ -20,7 +20,7 @@ class CONTENT_EXPORT ContentPluginClient {
virtual void PreSandboxInitialization() {}
// Notifies that a plugin process has started.
- virtual void PluginProcessStarted(const string16& plugin_name) {}
+ virtual void PluginProcessStarted(const base::string16& plugin_name) {}
};
} // namespace content
diff --git a/chromium/content/public/renderer/android/OWNERS b/chromium/content/public/renderer/android/OWNERS
index cff1ac91ba0..f1159d64574 100644
--- a/chromium/content/public/renderer/android/OWNERS
+++ b/chromium/content/public/renderer/android/OWNERS
@@ -1,6 +1,3 @@
-# While the SynchronousCompositor API is in active development include
-# all the following owners in any changes under this path.
-
+boliu@chromium.org
jamesr@chromium.org
-joth@chromium.org
mkosiba@chromium.org
diff --git a/chromium/content/public/renderer/content_renderer_client.cc b/chromium/content/public/renderer/content_renderer_client.cc
index 76c80b42f87..e33e34f8fec 100644
--- a/chromium/content/public/renderer/content_renderer_client.cc
+++ b/chromium/content/public/renderer/content_renderer_client.cc
@@ -19,15 +19,15 @@ std::string ContentRendererClient::GetDefaultEncoding() {
}
bool ContentRendererClient::OverrideCreatePlugin(
- RenderView* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params,
- WebKit::WebPlugin** plugin) {
+ RenderFrame* render_frame,
+ blink::WebFrame* frame,
+ const blink::WebPluginParams& params,
+ blink::WebPlugin** plugin) {
return false;
}
-WebKit::WebPlugin* ContentRendererClient::CreatePluginReplacement(
- RenderView* render_view,
+blink::WebPlugin* ContentRendererClient::CreatePluginReplacement(
+ RenderFrame* render_frame,
const base::FilePath& plugin_path) {
return NULL;
}
@@ -41,49 +41,45 @@ bool ContentRendererClient::ShouldSuppressErrorPage(const GURL& url) {
return false;
}
-void ContentRendererClient::DeferMediaLoad(RenderView* render_view,
+void ContentRendererClient::DeferMediaLoad(RenderFrame* render_frame,
const base::Closure& closure) {
closure.Run();
}
-WebKit::WebMediaStreamCenter*
+blink::WebMediaStreamCenter*
ContentRendererClient::OverrideCreateWebMediaStreamCenter(
- WebKit::WebMediaStreamCenterClient* client) {
+ blink::WebMediaStreamCenterClient* client) {
return NULL;
}
-WebKit::WebRTCPeerConnectionHandler*
+blink::WebRTCPeerConnectionHandler*
ContentRendererClient::OverrideCreateWebRTCPeerConnectionHandler(
- WebKit::WebRTCPeerConnectionHandlerClient* client) {
+ blink::WebRTCPeerConnectionHandlerClient* client) {
return NULL;
}
-WebKit::WebMIDIAccessor*
+blink::WebMIDIAccessor*
ContentRendererClient::OverrideCreateMIDIAccessor(
- WebKit::WebMIDIAccessorClient* client) {
+ blink::WebMIDIAccessorClient* client) {
return NULL;
}
-WebKit::WebAudioDevice*
+blink::WebAudioDevice*
ContentRendererClient::OverrideCreateAudioDevice(
double sample_rate) {
return NULL;
}
-WebKit::WebClipboard* ContentRendererClient::OverrideWebClipboard() {
+blink::WebClipboard* ContentRendererClient::OverrideWebClipboard() {
return NULL;
}
-WebKit::WebThemeEngine* ContentRendererClient::OverrideThemeEngine() {
+blink::WebThemeEngine* ContentRendererClient::OverrideThemeEngine() {
return NULL;
}
-WebKit::WebSpeechSynthesizer* ContentRendererClient::OverrideSpeechSynthesizer(
- WebKit::WebSpeechSynthesizerClient* client) {
- return NULL;
-}
-
-WebKit::WebCrypto* ContentRendererClient::OverrideWebCrypto() {
+blink::WebSpeechSynthesizer* ContentRendererClient::OverrideSpeechSynthesizer(
+ blink::WebSpeechSynthesizerClient* client) {
return NULL;
}
@@ -95,16 +91,21 @@ bool ContentRendererClient::AllowPopup() {
return false;
}
+#ifdef OS_ANDROID
bool ContentRendererClient::HandleNavigation(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationType type,
- WebKit::WebNavigationPolicy default_policy,
+ RenderView* view,
+ DocumentState* document_state,
+ int opener_id,
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationType type,
+ blink::WebNavigationPolicy default_policy,
bool is_redirect) {
return false;
}
+#endif
-bool ContentRendererClient::ShouldFork(WebKit::WebFrame* frame,
+bool ContentRendererClient::ShouldFork(blink::WebFrame* frame,
const GURL& url,
const std::string& http_method,
bool is_initial_navigation,
@@ -114,7 +115,7 @@ bool ContentRendererClient::ShouldFork(WebKit::WebFrame* frame,
}
bool ContentRendererClient::WillSendRequest(
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
PageTransition transition_type,
const GURL& url,
const GURL& first_party_for_cookies,
@@ -122,10 +123,6 @@ bool ContentRendererClient::WillSendRequest(
return false;
}
-bool ContentRendererClient::ShouldPumpEventsDuringCookieMessage() {
- return false;
-}
-
unsigned long long ContentRendererClient::VisitedLinkHash(
const char* canonical_url, size_t length) {
return 0LL;
@@ -135,30 +132,14 @@ bool ContentRendererClient::IsLinkVisited(unsigned long long link_hash) {
return false;
}
-WebKit::WebPrescientNetworking*
+blink::WebPrescientNetworking*
ContentRendererClient::GetPrescientNetworking() {
return NULL;
}
bool ContentRendererClient::ShouldOverridePageVisibilityState(
- const RenderView* render_view,
- WebKit::WebPageVisibilityState* override_state) {
- return false;
-}
-
-bool ContentRendererClient::HandleGetCookieRequest(
- RenderView* sender,
- const GURL& url,
- const GURL& first_party_for_cookies,
- std::string* cookies) {
- return false;
-}
-
-bool ContentRendererClient::HandleSetCookieRequest(
- RenderView* sender,
- const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& value) {
+ const RenderFrame* render_frame,
+ blink::WebPageVisibilityState* override_state) {
return false;
}
@@ -172,13 +153,8 @@ bool ContentRendererClient::IsExternalPepperPlugin(
return false;
}
-bool ContentRendererClient::IsPluginAllowedToCallRequestOSFileHandle(
- WebKit::WebPluginContainer* container) {
- return false;
-}
-
bool ContentRendererClient::AllowBrowserPlugin(
- WebKit::WebPluginContainer* container) {
+ blink::WebPluginContainer* container) {
return false;
}
@@ -199,4 +175,10 @@ bool ContentRendererClient::ShouldEnableSiteIsolationPolicy() const {
return true;
}
+blink::WebWorkerPermissionClientProxy*
+ContentRendererClient::CreateWorkerPermissionClientProxy(
+ RenderView* render_view, blink::WebFrame* frame) {
+ return NULL;
+}
+
} // namespace content
diff --git a/chromium/content/public/renderer/content_renderer_client.h b/chromium/content/public/renderer/content_renderer_client.h
index 4434a0f083f..1e834fe89c2 100644
--- a/chromium/content/public/renderer/content_renderer_client.h
+++ b/chromium/content/public/renderer/content_renderer_client.h
@@ -26,10 +26,9 @@ class FilePath;
class MessageLoop;
}
-namespace WebKit {
+namespace blink {
class WebAudioDevice;
class WebClipboard;
-class WebCrypto;
class WebFrame;
class WebMIDIAccessor;
class WebMIDIAccessorClient;
@@ -44,12 +43,14 @@ class WebSpeechSynthesizer;
class WebSpeechSynthesizerClient;
class WebThemeEngine;
class WebURLRequest;
+class WebWorkerPermissionClientProxy;
struct WebPluginParams;
struct WebURLError;
}
namespace content {
-
+class DocumentState;
+class RenderFrame;
class RenderView;
class SynchronousCompositor;
struct KeySystemInfo;
@@ -63,6 +64,9 @@ class CONTENT_EXPORT ContentRendererClient {
// Notifies us that the RenderThread has been created.
virtual void RenderThreadStarted() {}
+ // Notifies that a new RenderFrame has been created.
+ virtual void RenderFrameCreated(RenderFrame* render_frame) {}
+
// Notifies that a new RenderView has been created.
virtual void RenderViewCreated(RenderView* render_view) {}
@@ -83,15 +87,15 @@ class CONTENT_EXPORT ContentRendererClient {
// |plugin| will contain the created plugin, although it could be NULL. If it
// returns false, the content layer will create the plugin.
virtual bool OverrideCreatePlugin(
- RenderView* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params,
- WebKit::WebPlugin** plugin);
+ RenderFrame* render_frame,
+ blink::WebFrame* frame,
+ const blink::WebPluginParams& params,
+ blink::WebPlugin** plugin);
// Creates a replacement plug-in that is shown when the plug-in at |file_path|
// couldn't be loaded. This allows the embedder to show a custom placeholder.
- virtual WebKit::WebPlugin* CreatePluginReplacement(
- RenderView* render_view,
+ virtual blink::WebPlugin* CreatePluginReplacement(
+ RenderFrame* render_frame,
const base::FilePath& plugin_path);
// Returns true if the embedder has an error page to show for the given http
@@ -114,55 +118,52 @@ class CONTENT_EXPORT ContentRendererClient {
// (lack of information on the error code) so the caller should take care to
// initialize the string values with safe defaults before the call.
virtual void GetNavigationErrorStrings(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& failed_request,
- const WebKit::WebURLError& error,
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& failed_request,
+ const blink::WebURLError& error,
+ const std::string& accept_languages,
std::string* error_html,
- string16* error_description) {}
+ base::string16* error_description) {}
// Allows the embedder to control when media resources are loaded. Embedders
// can run |closure| immediately if they don't wish to defer media resource
// loading.
- virtual void DeferMediaLoad(RenderView* render_view,
+ virtual void DeferMediaLoad(RenderFrame* render_frame,
const base::Closure& closure);
// Allows the embedder to override creating a WebMediaStreamCenter. If it
// returns NULL the content layer will create the stream center.
- virtual WebKit::WebMediaStreamCenter* OverrideCreateWebMediaStreamCenter(
- WebKit::WebMediaStreamCenterClient* client);
+ virtual blink::WebMediaStreamCenter* OverrideCreateWebMediaStreamCenter(
+ blink::WebMediaStreamCenterClient* client);
// Allows the embedder to override creating a WebRTCPeerConnectionHandler. If
// it returns NULL the content layer will create the connection handler.
- virtual WebKit::WebRTCPeerConnectionHandler*
+ virtual blink::WebRTCPeerConnectionHandler*
OverrideCreateWebRTCPeerConnectionHandler(
- WebKit::WebRTCPeerConnectionHandlerClient* client);
+ blink::WebRTCPeerConnectionHandlerClient* client);
// Allows the embedder to override creating a WebMIDIAccessor. If it
// returns NULL the content layer will create the MIDI accessor.
- virtual WebKit::WebMIDIAccessor* OverrideCreateMIDIAccessor(
- WebKit::WebMIDIAccessorClient* client);
+ virtual blink::WebMIDIAccessor* OverrideCreateMIDIAccessor(
+ blink::WebMIDIAccessorClient* client);
// Allows the embedder to override creating a WebAudioDevice. If it
// returns NULL the content layer will create the audio device.
- virtual WebKit::WebAudioDevice* OverrideCreateAudioDevice(
+ virtual blink::WebAudioDevice* OverrideCreateAudioDevice(
double sample_rate);
- // Allows the embedder to override the WebKit::WebClipboard used. If it
+ // Allows the embedder to override the blink::WebClipboard used. If it
// returns NULL the content layer will handle clipboard interactions.
- virtual WebKit::WebClipboard* OverrideWebClipboard();
+ virtual blink::WebClipboard* OverrideWebClipboard();
// Allows the embedder to override the WebThemeEngine used. If it returns NULL
// the content layer will provide an engine.
- virtual WebKit::WebThemeEngine* OverrideThemeEngine();
+ virtual blink::WebThemeEngine* OverrideThemeEngine();
// Allows the embedder to override the WebSpeechSynthesizer used.
// If it returns NULL the content layer will provide an engine.
- virtual WebKit::WebSpeechSynthesizer* OverrideSpeechSynthesizer(
- WebKit::WebSpeechSynthesizerClient* client);
-
- // Allows the embedder to override the WebCrypto used.
- // If it returns NULL the content layer will handle crypto.
- virtual WebKit::WebCrypto* OverrideWebCrypto();
+ virtual blink::WebSpeechSynthesizer* OverrideSpeechSynthesizer(
+ blink::WebSpeechSynthesizerClient* client);
// Returns true if the renderer process should schedule the idle handler when
// all widgets are hidden.
@@ -171,16 +172,28 @@ class CONTENT_EXPORT ContentRendererClient {
// Returns true if a popup window should be allowed.
virtual bool AllowPopup();
+#ifdef OS_ANDROID
+ // TODO(sgurun) This callback is deprecated and will be removed as soon
+ // as android webview completes implementation of a resource throttle based
+ // shouldoverrideurl implementation. See crbug.com/325351
+ //
// Returns true if the navigation was handled by the embedder and should be
- // ignored by WebKit. This method is used by CEF.
- virtual bool HandleNavigation(WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationType type,
- WebKit::WebNavigationPolicy default_policy,
+ // ignored by WebKit. This method is used by CEF and android_webview.
+ virtual bool HandleNavigation(RenderView* view,
+ DocumentState* document_state,
+ int opener_id,
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationType type,
+ blink::WebNavigationPolicy default_policy,
bool is_redirect);
+#endif
// Returns true if we should fork a new process for the given navigation.
- virtual bool ShouldFork(WebKit::WebFrame* frame,
+ // If |send_referrer| is set to false (which is the default), no referrer
+ // header will be send for the navigation. Otherwise, the referrer header is
+ // set according to the frame's referrer policy.
+ virtual bool ShouldFork(blink::WebFrame* frame,
const GURL& url,
const std::string& http_method,
bool is_initial_navigation,
@@ -189,47 +202,29 @@ class CONTENT_EXPORT ContentRendererClient {
// Notifies the embedder that the given frame is requesting the resource at
// |url|. If the function returns true, the url is changed to |new_url|.
- virtual bool WillSendRequest(WebKit::WebFrame* frame,
+ virtual bool WillSendRequest(blink::WebFrame* frame,
PageTransition transition_type,
const GURL& url,
const GURL& first_party_for_cookies,
GURL* new_url);
- // Whether to pump events when sending sync cookie messages. Needed if the
- // embedder can potentiall put up a modal dialog on the UI thread as a result.
- virtual bool ShouldPumpEventsDuringCookieMessage();
-
- // See the corresponding functions in WebKit::WebFrameClient.
- virtual void DidCreateScriptContext(WebKit::WebFrame* frame,
+ // See the corresponding functions in blink::WebFrameClient.
+ virtual void DidCreateScriptContext(blink::WebFrame* frame,
v8::Handle<v8::Context> context,
int extension_group,
int world_id) {}
- virtual void WillReleaseScriptContext(WebKit::WebFrame* frame,
+ virtual void WillReleaseScriptContext(blink::WebFrame* frame,
v8::Handle<v8::Context>,
int world_id) {}
- // See WebKit::Platform.
+ // See blink::Platform.
virtual unsigned long long VisitedLinkHash(const char* canonical_url,
size_t length);
virtual bool IsLinkVisited(unsigned long long link_hash);
- virtual WebKit::WebPrescientNetworking* GetPrescientNetworking();
+ virtual blink::WebPrescientNetworking* GetPrescientNetworking();
virtual bool ShouldOverridePageVisibilityState(
- const RenderView* render_view,
- WebKit::WebPageVisibilityState* override_state);
-
- // Return true if the GetCookie request will be handled by the embedder.
- // Cookies are returned in the cookie parameter.
- virtual bool HandleGetCookieRequest(RenderView* sender,
- const GURL& url,
- const GURL& first_party_for_cookies,
- std::string* cookies);
-
- // Return true if the SetCookie request will be handled by the embedder.
- // Cookies to be set are passed in the value parameter.
- virtual bool HandleSetCookieRequest(RenderView* sender,
- const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& value);
+ const RenderFrame* render_frame,
+ blink::WebPageVisibilityState* override_state);
// Allows an embedder to return custom PPAPI interfaces.
virtual const void* CreatePPAPIInterface(
@@ -239,13 +234,8 @@ class CONTENT_EXPORT ContentRendererClient {
// startup steps).
virtual bool IsExternalPepperPlugin(const std::string& module_name);
- // Returns true if plugin living in the container can use
- // pp::FileIO::RequestOSFileHandle.
- virtual bool IsPluginAllowedToCallRequestOSFileHandle(
- WebKit::WebPluginContainer* container);
-
// Returns whether BrowserPlugin should be allowed within the |container|.
- virtual bool AllowBrowserPlugin(WebKit::WebPluginContainer* container);
+ virtual bool AllowBrowserPlugin(blink::WebPluginContainer* container);
// Returns true if the page at |url| can use Pepper MediaStream APIs.
virtual bool AllowPepperMediaStreamAPI(const GURL& url);
@@ -265,6 +255,11 @@ class CONTENT_EXPORT ContentRendererClient {
// this renderer process. Currently, we apply the policy only to a renderer
// process running on a normal page from the web.
virtual bool ShouldEnableSiteIsolationPolicy() const;
+
+ // Creates a permission client proxy for in-renderer worker.
+ virtual blink::WebWorkerPermissionClientProxy*
+ CreateWorkerPermissionClientProxy(RenderView* render_view,
+ blink::WebFrame* frame);
};
} // namespace content
diff --git a/chromium/content/public/renderer/document_state.h b/chromium/content/public/renderer/document_state.h
index cd9fd585206..11b7d5e10bf 100644
--- a/chromium/content/public/renderer/document_state.h
+++ b/chromium/content/public/renderer/document_state.h
@@ -22,7 +22,7 @@ class NavigationState;
// The RenderView stores an instance of this class in the "extra data" of each
// WebDataSource (see RenderView::DidCreateDataSource).
class CONTENT_EXPORT DocumentState
- : NON_EXPORTED_BASE(public WebKit::WebDataSource::ExtraData),
+ : NON_EXPORTED_BASE(public blink::WebDataSource::ExtraData),
public base::SupportsUserData {
public:
// The exact values of this enum are used in histograms, so new values must be
@@ -43,7 +43,7 @@ class CONTENT_EXPORT DocumentState
DocumentState();
virtual ~DocumentState();
- static DocumentState* FromDataSource(WebKit::WebDataSource* ds) {
+ static DocumentState* FromDataSource(blink::WebDataSource* ds) {
return static_cast<DocumentState*>(ds->extraData());
}
diff --git a/chromium/content/public/renderer/history_item_serialization.cc b/chromium/content/public/renderer/history_item_serialization.cc
index 14519d5f118..96309c954d2 100644
--- a/chromium/content/public/renderer/history_item_serialization.cc
+++ b/chromium/content/public/renderer/history_item_serialization.cc
@@ -13,11 +13,11 @@
#include "third_party/WebKit/public/web/WebHistoryItem.h"
#include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
-using WebKit::WebHTTPBody;
-using WebKit::WebHistoryItem;
-using WebKit::WebSerializedScriptValue;
-using WebKit::WebString;
-using WebKit::WebVector;
+using blink::WebHTTPBody;
+using blink::WebHistoryItem;
+using blink::WebSerializedScriptValue;
+using blink::WebString;
+using blink::WebVector;
namespace content {
namespace {
@@ -42,13 +42,13 @@ void ToExplodedHttpBodyElement(const WebHTTPBody::Element& input,
output->file_modification_time = input.modificationTime;
break;
case WebHTTPBody::Element::TypeFileSystemURL:
- output->filesystem_url = input.url;
+ 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->deprecated_blob_url = input.blobURL;
+ output->blob_uuid = input.blobUUID.utf8();
break;
}
}
@@ -67,14 +67,14 @@ void AppendHTTPBodyElement(const ExplodedHttpBodyElement& element,
element.file_modification_time);
break;
case WebHTTPBody::Element::TypeFileSystemURL:
- http_body->appendURLRange(
+ http_body->appendFileSystemURLRange(
element.filesystem_url,
element.file_start,
element.file_length,
element.file_modification_time);
break;
case WebHTTPBody::Element::TypeBlob:
- http_body->appendBlob(element.deprecated_blob_url);
+ http_body->appendBlob(WebString::fromUTF8(element.blob_uuid));
break;
}
}
@@ -85,19 +85,14 @@ bool RecursivelyGenerateFrameState(const WebHistoryItem& item,
state->original_url_string = item.originalURLString();
state->referrer = item.referrer();
state->target = item.target();
- state->parent = item.parent();
- state->title = item.title();
- state->alternate_title = item.alternateTitle();
if (!item.stateObject().isNull())
state->state_object = item.stateObject().toString();
state->scroll_offset = item.scrollOffset();
state->item_sequence_number = item.itemSequenceNumber();
state->document_sequence_number =
item.documentSequenceNumber();
- state->visit_count = item.visitCount();
- state->visited_time = item.lastVisitedTime();
+ state->target_frame_id = item.targetFrameID();
state->page_scale_factor = item.pageScaleFactor();
- state->is_target_item = item.isTargetItem();
ToNullableString16Vector(item.documentState(), &state->document_state);
state->http_body.http_content_type = item.httpContentType();
@@ -129,19 +124,13 @@ bool RecursivelyGenerateHistoryItem(const ExplodedFrameState& state,
item->setOriginalURLString(state.original_url_string);
item->setReferrer(state.referrer);
item->setTarget(state.target);
- item->setParent(state.parent);
- item->setTitle(state.title);
- item->setAlternateTitle(state.alternate_title);
if (!state.state_object.is_null()) {
item->setStateObject(
WebSerializedScriptValue::fromString(state.state_object));
}
item->setDocumentState(state.document_state);
item->setScrollOffset(state.scroll_offset);
- item->setVisitCount(state.visit_count);
- item->setLastVisitedTime(state.visited_time);
item->setPageScaleFactor(state.page_scale_factor);
- item->setIsTargetItem(state.is_target_item);
// These values are generated at WebHistoryItem construction time, and we
// only want to override those new values with old values if the old values
@@ -151,6 +140,8 @@ bool RecursivelyGenerateHistoryItem(const ExplodedFrameState& state,
if (state.document_sequence_number)
item->setDocumentSequenceNumber(state.document_sequence_number);
+ item->setTargetFrameID(state.target_frame_id);
+
item->setHTTPContentType(state.http_body.http_content_type);
if (!state.http_body.is_null) {
WebHTTPBody http_body;
diff --git a/chromium/content/public/renderer/history_item_serialization.h b/chromium/content/public/renderer/history_item_serialization.h
index 44eb1e1c094..dda1cf406fa 100644
--- a/chromium/content/public/renderer/history_item_serialization.h
+++ b/chromium/content/public/renderer/history_item_serialization.h
@@ -9,7 +9,7 @@
#include "content/common/content_export.h"
-namespace WebKit {
+namespace blink {
class WebHistoryItem;
}
@@ -17,8 +17,8 @@ namespace content {
class PageState;
CONTENT_EXPORT PageState HistoryItemToPageState(
- const WebKit::WebHistoryItem& item);
-CONTENT_EXPORT WebKit::WebHistoryItem PageStateToHistoryItem(
+ const blink::WebHistoryItem& item);
+CONTENT_EXPORT blink::WebHistoryItem PageStateToHistoryItem(
const PageState& state);
} // namespace content
diff --git a/chromium/content/public/renderer/media_stream_audio_sink.cc b/chromium/content/public/renderer/media_stream_audio_sink.cc
new file mode 100644
index 00000000000..f96c92b336f
--- /dev/null
+++ b/chromium/content/public/renderer/media_stream_audio_sink.cc
@@ -0,0 +1,40 @@
+// 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/public/renderer/media_stream_audio_sink.h"
+
+#include "base/logging.h"
+#include "content/renderer/media/media_stream_track_extra_data.h"
+#include "content/renderer/media/webrtc_local_audio_track.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+
+namespace content {
+
+void MediaStreamAudioSink::AddToAudioTrack(
+ MediaStreamAudioSink* sink,
+ const blink::WebMediaStreamTrack& track) {
+ DCHECK(track.source().type() == blink::WebMediaStreamSource::TypeAudio);
+ MediaStreamTrackExtraData* extra_data =
+ static_cast<MediaStreamTrackExtraData*>(track.extraData());
+ // TODO(xians): Support remote audio track.
+ DCHECK(extra_data->is_local_track());
+ WebRtcLocalAudioTrack* audio_track =
+ static_cast<WebRtcLocalAudioTrack*>(extra_data->track().get());
+ audio_track->AddSink(sink);
+}
+
+void MediaStreamAudioSink::RemoveFromAudioTrack(
+ MediaStreamAudioSink* sink,
+ const blink::WebMediaStreamTrack& track) {
+ MediaStreamTrackExtraData* extra_data =
+ static_cast<MediaStreamTrackExtraData*>(track.extraData());
+ // TODO(xians): Support remote audio track.
+ DCHECK(extra_data->is_local_track());
+ WebRtcLocalAudioTrack* audio_track =
+ static_cast<WebRtcLocalAudioTrack*>(extra_data->track().get());
+ audio_track->RemoveSink(sink);
+}
+
+} // namespace content
diff --git a/chromium/content/public/renderer/media_stream_audio_sink.h b/chromium/content/public/renderer/media_stream_audio_sink.h
new file mode 100644
index 00000000000..312d61dc42f
--- /dev/null
+++ b/chromium/content/public/renderer/media_stream_audio_sink.h
@@ -0,0 +1,59 @@
+// 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_PUBLIC_RENDERER_MEDIA_STREAM_AUDIO_SINK_H_
+#define CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_AUDIO_SINK_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "content/common/content_export.h"
+#include "content/public/renderer/media_stream_sink.h"
+
+namespace blink {
+class WebMediaStreamTrack;
+}
+
+namespace media {
+class AudioParameters;
+}
+
+namespace content {
+
+class CONTENT_EXPORT MediaStreamAudioSink : public MediaStreamSink {
+ public:
+ // Adds a MediaStreamAudioSink to the audio track to receive audio data from
+ // the track.
+ // Called on the main render thread.
+ static void AddToAudioTrack(MediaStreamAudioSink* sink,
+ const blink::WebMediaStreamTrack& track);
+
+ // Removes a MediaStreamAudioSink from the audio track to stop receiving
+ // audio data from the track.
+ // Called on the main render thread.
+ static void RemoveFromAudioTrack(MediaStreamAudioSink* sink,
+ const blink::WebMediaStreamTrack& track);
+
+ // Callback on delivering the interleaved audio data.
+ // |audio_data| is the pointer to the audio data.
+ // |sample_rate| is the sample frequency of |audio_data|.
+ // |number_of_channels| is the number of audio channels of |audio_data|.
+ // |number_of_frames| is the number of audio frames in the |audio_data|.
+ // Called on real-time audio thread.
+ virtual void OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames) = 0;
+
+ // Callback called when the format of the audio stream has changed.
+ // This is called on the same thread as OnData().
+ virtual void OnSetFormat(const media::AudioParameters& params) = 0;
+
+ protected:
+ virtual ~MediaStreamAudioSink() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_AUDIO_SINK_H_
diff --git a/chromium/content/public/renderer/media_stream_sink.h b/chromium/content/public/renderer/media_stream_sink.h
new file mode 100644
index 00000000000..e142ba1d81e
--- /dev/null
+++ b/chromium/content/public/renderer/media_stream_sink.h
@@ -0,0 +1,30 @@
+// 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_PUBLIC_RENDERER_MEDIA_STREAM_SINK_H_
+#define CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_SINK_H_
+
+#include "base/compiler_specific.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
+
+namespace content {
+
+// MediaStreamSink is the base interface for MediaStreamAudioSink and
+// MediaStreamVideoSink. It allows an implementation to receive notifications
+// about state changes on a blink::WebMediaStreamSource object or such an
+// object underlying a blink::WebMediaStreamTrack.
+class CONTENT_EXPORT MediaStreamSink {
+ public:
+ virtual void OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) {}
+ virtual void OnEnabledChanged(bool enabled) {}
+
+ protected:
+ virtual ~MediaStreamSink() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_SINK_H_
diff --git a/chromium/content/public/renderer/media_stream_video_sink.cc b/chromium/content/public/renderer/media_stream_video_sink.cc
new file mode 100644
index 00000000000..c6580362203
--- /dev/null
+++ b/chromium/content/public/renderer/media_stream_video_sink.cc
@@ -0,0 +1,31 @@
+// 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/public/renderer/media_stream_video_sink.h"
+
+#include "base/logging.h"
+#include "content/renderer/media/media_stream_video_track.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+
+namespace content {
+
+void MediaStreamVideoSink::AddToVideoTrack(
+ MediaStreamVideoSink* sink,
+ const blink::WebMediaStreamTrack& track) {
+ DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track.source().type());
+ MediaStreamVideoTrack* video_track =
+ static_cast<MediaStreamVideoTrack*>(track.extraData());
+ video_track->AddSink(sink);
+}
+
+void MediaStreamVideoSink::RemoveFromVideoTrack(
+ MediaStreamVideoSink* sink,
+ const blink::WebMediaStreamTrack& track) {
+ DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track.source().type());
+ MediaStreamVideoTrack* video_track =
+ static_cast<MediaStreamVideoTrack*>(track.extraData());
+ video_track->RemoveSink(sink);
+}
+
+} // namespace content
diff --git a/chromium/content/public/renderer/media_stream_video_sink.h b/chromium/content/public/renderer/media_stream_video_sink.h
new file mode 100644
index 00000000000..48a37199b55
--- /dev/null
+++ b/chromium/content/public/renderer/media_stream_video_sink.h
@@ -0,0 +1,47 @@
+// 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_PUBLIC_RENDERER_MEDIA_STREAM_VIDEO_SINK_H_
+#define CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_VIDEO_SINK_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "content/public/renderer/media_stream_sink.h"
+
+namespace media {
+class VideoFrame;
+}
+
+namespace blink {
+class WebMediaStreamTrack;
+}
+
+namespace content {
+
+// MediaStreamVideoSink is an interface used for receiving video frames from a
+// Video Stream Track or a Video Source.
+// http://dev.w3.org/2011/webrtc/editor/getusermedia.html
+// All methods calls will be done from the main render thread.
+class CONTENT_EXPORT MediaStreamVideoSink : public MediaStreamSink {
+ public:
+ // An implementation of MediaStreamVideoSink should call AddToVideoTrack when
+ // it is ready to receive data from a video track. Before the implementation
+ // is destroyed, RemoveFromVideoTrack must be called.
+ // Calls to these methods must be done on the main render thread.
+ static void AddToVideoTrack(MediaStreamVideoSink* sink,
+ const blink::WebMediaStreamTrack& track);
+ static void RemoveFromVideoTrack(MediaStreamVideoSink* sink,
+ const blink::WebMediaStreamTrack& track);
+
+ virtual void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame) = 0;
+
+ protected:
+ virtual ~MediaStreamVideoSink() {}
+};
+
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_VIDEO_SINK_H_
diff --git a/chromium/content/public/renderer/navigation_state.cc b/chromium/content/public/renderer/navigation_state.cc
index 5745a2b4654..a1fc18349bd 100644
--- a/chromium/content/public/renderer/navigation_state.cc
+++ b/chromium/content/public/renderer/navigation_state.cc
@@ -17,6 +17,7 @@ NavigationState::NavigationState(content::PageTransition transition_type,
pending_page_id_(pending_page_id),
pending_history_list_offset_(pending_history_list_offset),
history_list_was_cleared_(history_list_was_cleared),
+ should_replace_current_entry_(false),
was_within_same_page_(false),
transferred_request_child_id_(-1),
transferred_request_request_id_(-1),
diff --git a/chromium/content/public/renderer/navigation_state.h b/chromium/content/public/renderer/navigation_state.h
index 01f92a05cd5..64b85113f72 100644
--- a/chromium/content/public/renderer/navigation_state.h
+++ b/chromium/content/public/renderer/navigation_state.h
@@ -51,6 +51,23 @@ class CONTENT_EXPORT NavigationState {
return history_list_was_cleared_;
}
+ // If is_content_initiated() is false, whether this navigation should replace
+ // the current entry in the back/forward history list. Otherwise, use
+ // replacesCurrentHistoryItem() on the WebDataSource.
+ //
+ // TODO(davidben): It would be good to unify these and have only one source
+ // for the two cases. We can plumb this through WebFrame::loadRequest to set
+ // lockBackForwardList on the FrameLoadRequest. However, this breaks process
+ // swaps because FrameLoader::loadWithNavigationAction treats loads before a
+ // FrameLoader has committedFirstRealDocumentLoad as a replacement. (Added for
+ // http://crbug.com/178380).
+ bool should_replace_current_entry() const {
+ return should_replace_current_entry_;
+ }
+ void set_should_replace_current_entry(bool value) {
+ should_replace_current_entry_ = value;
+ }
+
// Contains the transition type that the browser specified when it
// initiated the load.
content::PageTransition transition_type() const { return transition_type_; }
@@ -111,6 +128,7 @@ class CONTENT_EXPORT NavigationState {
int32 pending_page_id_;
int pending_history_list_offset_;
bool history_list_was_cleared_;
+ bool should_replace_current_entry_;
bool was_within_same_page_;
int transferred_request_child_id_;
diff --git a/chromium/content/public/renderer/p2p_socket_client.h b/chromium/content/public/renderer/p2p_socket_client.h
new file mode 100644
index 00000000000..6df92851243
--- /dev/null
+++ b/chromium/content/public/renderer/p2p_socket_client.h
@@ -0,0 +1,62 @@
+// 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_PUBLIC_RENDERER_P2P_SOCKET_CLIENT_H_
+#define CONTENT_PUBLIC_RENDERER_P2P_SOCKET_CLIENT_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "content/public/common/p2p_socket_type.h"
+#include "net/base/ip_endpoint.h"
+
+namespace content {
+
+class P2PSocketClientDelegate;
+
+// P2P socket that routes all calls over IPC.
+// Note that while ref-counting is thread-safe, all methods must be
+// called on the same thread.
+class CONTENT_EXPORT P2PSocketClient :
+ public base::RefCountedThreadSafe<P2PSocketClient> {
+ public:
+ // Create a new P2PSocketClient() of the specified |type| and connected to
+ // the specified |address|. |address| matters only when |type| is set to
+ // P2P_SOCKET_TCP_CLIENT. The methods on the returned socket may only be
+ // called on the same thread that created it.
+ static scoped_refptr<P2PSocketClient> Create(
+ P2PSocketType type,
+ const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address,
+ P2PSocketClientDelegate* delegate);
+
+ P2PSocketClient() {}
+
+ // Send the |data| to the |address|.
+ virtual void Send(const net::IPEndPoint& address,
+ const std::vector<char>& data) = 0;
+
+ // Send the |data| to the |address| using Differentiated Services Code Point
+ // |dscp|.
+ virtual void SendWithDscp(const net::IPEndPoint& address,
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp) = 0;
+
+ // Must be called before the socket is destroyed.
+ virtual void Close() = 0;
+
+ virtual int GetSocketID() const = 0;
+ virtual void SetDelegate(P2PSocketClientDelegate* delegate) = 0;
+
+ protected:
+ virtual ~P2PSocketClient() {}
+
+ private:
+ // Calls destructor.
+ friend class base::RefCountedThreadSafe<P2PSocketClient>;
+};
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_P2P_SOCKET_CLIENT_H_
diff --git a/chromium/content/public/renderer/p2p_socket_client_delegate.h b/chromium/content/public/renderer/p2p_socket_client_delegate.h
new file mode 100644
index 00000000000..6b2a7312756
--- /dev/null
+++ b/chromium/content/public/renderer/p2p_socket_client_delegate.h
@@ -0,0 +1,46 @@
+// 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_PUBLIC_RENDERER_P2P_SOCKET_CLIENT_DELEGATE_H_
+#define CONTENT_PUBLIC_RENDERER_P2P_SOCKET_CLIENT_DELEGATE_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "content/public/common/p2p_socket_type.h"
+#include "net/base/ip_endpoint.h"
+
+namespace content {
+
+class P2PSocketClient;
+
+class P2PSocketClientDelegate {
+ public:
+ virtual ~P2PSocketClientDelegate() { }
+
+ // Called after the socket has been opened with the local endpoint address
+ // as argument. Please note that in the precence of multiple interfaces,
+ // you should not rely on the local endpoint address if possible.
+ virtual void OnOpen(const net::IPEndPoint& address) = 0;
+
+ // For a socket that is listening on incoming TCP connectsion, this
+ // function is called when a new client connects.
+ virtual void OnIncomingTcpConnection(const net::IPEndPoint& address,
+ P2PSocketClient* client) = 0;
+
+ // Called once for each Send() call after the send is complete.
+ virtual void OnSendComplete() = 0;
+
+ // Called if an non-retryable error occurs.
+ virtual void OnError() = 0;
+
+ // Called when data is received on the socket.
+ virtual void OnDataReceived(const net::IPEndPoint& address,
+ const std::vector<char>& data,
+ const base::TimeTicks& timestamp) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_P2P_SOCKET_CLIENT_DELEGATE_H_
diff --git a/chromium/content/public/renderer/pepper_plugin_instance.h b/chromium/content/public/renderer/pepper_plugin_instance.h
index b52b943869f..4811217b18d 100644
--- a/chromium/content/public/renderer/pepper_plugin_instance.h
+++ b/chromium/content/public/renderer/pepper_plugin_instance.h
@@ -9,6 +9,7 @@
#include "base/process/process_handle.h"
#include "content/common/content_export.h"
#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
#include "ppapi/c/private/ppb_instance_private.h"
class GURL;
@@ -32,10 +33,14 @@ namespace IPC {
struct ChannelHandle;
}
-namespace WebKit {
+namespace blink {
class WebPluginContainer;
}
+namespace v8 {
+class Isolate;
+}
+
namespace content {
class RenderView;
@@ -47,7 +52,9 @@ class PepperPluginInstance {
virtual content::RenderView* GetRenderView() = 0;
- virtual WebKit::WebPluginContainer* GetContainer() = 0;
+ virtual blink::WebPluginContainer* GetContainer() = 0;
+
+ virtual v8::Isolate* GetIsolate() const = 0;
virtual ppapi::VarTracker* GetVarTracker() = 0;
@@ -93,6 +100,9 @@ class PepperPluginInstance {
// Creates a pending PepperFileRefRendererHost. Returns 0 on failure.
virtual int MakePendingFileRefRendererHost(const base::FilePath& path) = 0;
+
+ // Sets a read-only property on the <embed> tag for this plugin instance.
+ virtual void SetEmbedProperty(PP_Var key, PP_Var value) = 0;
};
} // namespace content
diff --git a/chromium/content/public/renderer/render_frame.h b/chromium/content/public/renderer/render_frame.h
index 47ace3e2d8a..eef36c686ff 100644
--- a/chromium/content/public/renderer/render_frame.h
+++ b/chromium/content/public/renderer/render_frame.h
@@ -8,14 +8,69 @@
#include "content/common/content_export.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
+#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
+
+struct WebPreferences;
+
+namespace blink {
+class WebFrame;
+class WebPlugin;
+class WebURLRequest;
+struct WebPluginParams;
+}
namespace content {
+class ContextMenuClient;
+class RenderView;
+struct ContextMenuParams;
+struct WebPluginInfo;
// This interface wraps functionality, which is specific to frames, such as
// navigation. It provides communication with a corresponding RenderFrameHost
// in the browser process.
class CONTENT_EXPORT RenderFrame : public IPC::Listener,
public IPC::Sender {
+ public:
+ // Returns the RenderView associated with this frame.
+ virtual RenderView* GetRenderView() = 0;
+
+ // Get the routing ID of the frame.
+ virtual int GetRoutingID() = 0;
+
+ // Gets WebKit related preferences associated with this frame.
+ virtual WebPreferences& GetWebkitPreferences() = 0;
+
+ // Shows a context menu with the given information. The given client will
+ // be called with the result.
+ //
+ // The request ID will be returned by this function. This is passed to the
+ // client functions for identification.
+ //
+ // If the client is destroyed, CancelContextMenu() should be called with the
+ // request ID returned by this function.
+ //
+ // Note: if you end up having clients outliving the RenderFrame, we should add
+ // a CancelContextMenuCallback function that takes a request id.
+ virtual int ShowContextMenu(ContextMenuClient* client,
+ const ContextMenuParams& params) = 0;
+
+ // Cancels a context menu in the event that the client is destroyed before the
+ // menu is closed.
+ virtual void CancelContextMenu(int request_id) = 0;
+
+ // Create a new NPAPI/Pepper plugin depending on |info|. Returns NULL if no
+ // plugin was found.
+ virtual blink::WebPlugin* CreatePlugin(
+ blink::WebFrame* frame,
+ const WebPluginInfo& info,
+ const blink::WebPluginParams& params) = 0;
+
+ // The client should handle the navigation externally.
+ virtual void LoadURLExternally(
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationPolicy policy) = 0;
+
protected:
virtual ~RenderFrame() {}
diff --git a/chromium/content/public/renderer/render_frame_observer.cc b/chromium/content/public/renderer/render_frame_observer.cc
new file mode 100644
index 00000000000..5891e111f5c
--- /dev/null
+++ b/chromium/content/public/renderer/render_frame_observer.cc
@@ -0,0 +1,55 @@
+// 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/public/renderer/render_frame_observer.h"
+
+#include "content/renderer/render_frame_impl.h"
+
+using blink::WebFrame;
+
+namespace content {
+
+RenderFrameObserver::RenderFrameObserver(RenderFrame* render_frame)
+ : render_frame_(render_frame),
+ routing_id_(MSG_ROUTING_NONE) {
+ // |render_frame| can be NULL on unit testing.
+ if (render_frame) {
+ RenderFrameImpl* impl = static_cast<RenderFrameImpl*>(render_frame);
+ routing_id_ = impl->GetRoutingID();
+ impl->AddObserver(this);
+ }
+}
+
+RenderFrameObserver::~RenderFrameObserver() {
+ if (render_frame_) {
+ RenderFrameImpl* impl = static_cast<RenderFrameImpl*>(render_frame_);
+ impl->RemoveObserver(this);
+ }
+}
+
+void RenderFrameObserver::OnDestruct() {
+ delete this;
+}
+
+bool RenderFrameObserver::OnMessageReceived(const IPC::Message& message) {
+ return false;
+}
+
+bool RenderFrameObserver::Send(IPC::Message* message) {
+ if (render_frame_)
+ return render_frame_->Send(message);
+
+ delete message;
+ return false;
+}
+
+RenderFrame* RenderFrameObserver::render_frame() const {
+ return render_frame_;
+}
+
+void RenderFrameObserver::RenderFrameGone() {
+ render_frame_ = NULL;
+}
+
+} // namespace content
diff --git a/chromium/content/public/renderer/render_frame_observer.h b/chromium/content/public/renderer/render_frame_observer.h
new file mode 100644
index 00000000000..6d4aa6401bf
--- /dev/null
+++ b/chromium/content/public/renderer/render_frame_observer.h
@@ -0,0 +1,61 @@
+// 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_PUBLIC_RENDERER_RENDER_FRAME_OBSERVER_H_
+#define CONTENT_PUBLIC_RENDERER_RENDER_FRAME_OBSERVER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "content/common/content_export.h"
+#include "ipc/ipc_listener.h"
+#include "ipc/ipc_sender.h"
+
+namespace content {
+
+class RendererPpapiHost;
+class RenderFrame;
+class RenderFrameImpl;
+
+// Base class for objects that want to filter incoming IPCs, and also get
+// notified of changes to the frame.
+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();
+
+ // Called when a Pepper plugin is created.
+ virtual void DidCreatePepperPlugin(RendererPpapiHost* host) {}
+
+ // IPC::Listener implementation.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ // IPC::Sender implementation.
+ virtual bool Send(IPC::Message* message) OVERRIDE;
+
+ RenderFrame* render_frame() const;
+ int routing_id() const { return routing_id_; }
+
+ protected:
+ explicit RenderFrameObserver(RenderFrame* render_frame);
+ virtual ~RenderFrameObserver();
+
+ private:
+ friend class RenderFrameImpl;
+
+ // This is called by the RenderFrame when it's going away so that this object
+ // can null out its pointer.
+ void RenderFrameGone();
+
+ RenderFrame* render_frame_;
+ // The routing ID of the associated RenderFrame.
+ int routing_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameObserver);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_RENDER_FRAME_OBSERVER_H_
diff --git a/chromium/content/public/renderer/render_frame_observer_tracker.h b/chromium/content/public/renderer/render_frame_observer_tracker.h
new file mode 100644
index 00000000000..7c5b332ef32
--- /dev/null
+++ b/chromium/content/public/renderer/render_frame_observer_tracker.h
@@ -0,0 +1,68 @@
+// 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.
+
+// Helper class used to find the RenderFrameObservers for a given RenderFrame.
+//
+// Example usage:
+//
+// class MyRFO : public RenderFrameObserver,
+// public RenderFrameObserverTracker<MyRFO> {
+// ...
+// };
+//
+// MyRFO::MyRFO(RenderFrame* render_frame)
+// : RenderFrameObserver(render_frame),
+// RenderFrameObserverTracker<MyRFO>(render_frame) {
+// ...
+// }
+//
+// void SomeFunction(RenderFrame* rf) {
+// MyRFO* my_rfo = new MyRFO(rf);
+// MyRFO* my_rfo_tracked = MyRFO::Get(rf);
+// // my_rfo == my_rfo_tracked
+// }
+
+#ifndef CONTENT_PUBLIC_RENDERER_RENDER_FRAME_OBSERVER_TRACKER_H_
+#define CONTENT_PUBLIC_RENDERER_RENDER_FRAME_OBSERVER_TRACKER_H_
+
+#include <map>
+
+#include "base/lazy_instance.h"
+
+namespace content {
+
+class RenderFrame;
+
+template <class T>
+class RenderFrameObserverTracker {
+ public:
+ static T* Get(const RenderFrame* render_frame) {
+ return render_frame_map_.Get()[render_frame];
+ }
+
+ explicit RenderFrameObserverTracker(const RenderFrame* render_frame)
+ : render_frame_(render_frame) {
+ render_frame_map_.Get()[render_frame] = static_cast<T*>(this);
+ }
+ ~RenderFrameObserverTracker() {
+ render_frame_map_.Get().erase(render_frame_);
+ }
+
+ private:
+ const RenderFrame* render_frame_;
+
+ static base::LazyInstance<std::map<const RenderFrame*, T*> >
+ render_frame_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameObserverTracker<T>);
+};
+
+template <class T>
+base::LazyInstance<std::map<const RenderFrame*, T*> >
+ RenderFrameObserverTracker<T>::render_frame_map_ =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_RENDER_FRAME_OBSERVER_TRACKER_H_
diff --git a/chromium/content/public/renderer/render_thread.h b/chromium/content/public/renderer/render_thread.h
index 87e064839cf..4693da3aa72 100644
--- a/chromium/content/public/renderer/render_thread.h
+++ b/chromium/content/public/renderer/render_thread.h
@@ -9,6 +9,7 @@
#include "base/callback.h"
#include "base/memory/shared_memory.h"
#include "content/common/content_export.h"
+#include "content/public/common/user_metrics_action.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_sender.h"
@@ -61,8 +62,6 @@ class CONTENT_EXPORT RenderThread : public IPC::Sender {
// These map to IPC::ChannelProxy methods.
virtual void AddFilter(IPC::ChannelProxy::MessageFilter* filter) = 0;
virtual void RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) = 0;
- virtual void SetOutgoingMessageFilter(
- IPC::ChannelProxy::OutgoingMessageFilter* filter) = 0;
// Add/remove observers for the process.
virtual void AddObserver(RenderProcessObserver* observer) = 0;
@@ -80,8 +79,22 @@ class CONTENT_EXPORT RenderThread : public IPC::Sender {
// initialization.
virtual void EnsureWebKitInitialized() = 0;
- // Helper function to send over a string to be recorded by user metrics
- virtual void RecordUserMetrics(const std::string& action) = 0;
+ // Sends over a UserMetricsAction to be recorded by user metrics as an action.
+ // Once a new user metric is added, run
+ // tools/metrics/actions/extract_actions.py --hash
+ // to generate a new mapping of [action hashes -> metric names] and send it
+ // out for review to be updated.
+ // WARNING: When using UserMetricsAction, UserMetricsAction and a string
+ // literal parameter must be on the same line, e.g.
+ // RenderThread::Get()->RecordAction(
+ // UserMetricsAction("my extremely long action name"));
+ // because otherwise our processing scripts won't pick up on new actions.
+ virtual void RecordAction(const UserMetricsAction& action) = 0;
+
+ // Sends over a string to be recorded by user metrics as a computed action.
+ // 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;
// Asks the host to create a block of shared memory for the renderer.
// The shared memory allocated by the host is returned back.
diff --git a/chromium/content/public/renderer/render_view.h b/chromium/content/public/renderer/render_view.h
index 94bdce5ebfe..c7ab4af9755 100644
--- a/chromium/content/public/renderer/render_view.h
+++ b/chromium/content/public/renderer/render_view.h
@@ -5,26 +5,25 @@
#ifndef CONTENT_PUBLIC_RENDERER_RENDER_VIEW_H_
#define CONTENT_PUBLIC_RENDERER_RENDER_VIEW_H_
+#include <string>
+
#include "base/basictypes.h"
#include "base/strings/string16.h"
#include "content/common/content_export.h"
#include "content/public/common/top_controls_state.h"
#include "ipc/ipc_sender.h"
-#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
#include "third_party/WebKit/public/web/WebPageVisibilityState.h"
#include "ui/gfx/native_widget_types.h"
struct WebPreferences;
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebNode;
-class WebPlugin;
class WebString;
class WebURLRequest;
class WebView;
struct WebContextMenuData;
-struct WebPluginParams;
}
namespace gfx {
@@ -33,16 +32,14 @@ class Size;
namespace content {
-class ContextMenuClient;
+class RenderFrame;
class RenderViewVisitor;
-struct ContextMenuParams;
struct SSLStatus;
-struct WebPluginInfo;
class CONTENT_EXPORT RenderView : public IPC::Sender {
public:
// Returns the RenderView containing the given WebView.
- static RenderView* FromWebView(WebKit::WebView* webview);
+ static RenderView* FromWebView(blink::WebView* webview);
// Returns the RenderView for the given routing ID.
static RenderView* FromRoutingID(int routing_id);
@@ -51,6 +48,9 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
// been closed but not yet destroyed are excluded).
static void ForEach(RenderViewVisitor* visitor);
+ // Returns the main RenderFrame.
+ virtual RenderFrame* GetMainRenderFrame() = 0;
+
// Get the routing ID of the view.
virtual int GetRoutingID() const = 0;
@@ -73,28 +73,21 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
virtual void SetWebkitPreferences(const WebPreferences& preferences) = 0;
// Returns the associated WebView. May return NULL when the view is closing.
- virtual WebKit::WebView* GetWebView() = 0;
+ virtual blink::WebView* GetWebView() = 0;
// Gets the focused node. If no such node exists then the node will be isNull.
- virtual WebKit::WebNode GetFocusedNode() const = 0;
+ virtual blink::WebNode GetFocusedNode() const = 0;
// Gets the node that the context menu was pressed over.
- virtual WebKit::WebNode GetContextMenuNode() const = 0;
+ virtual blink::WebNode GetContextMenuNode() const = 0;
// Returns true if the parameter node is a textfield, text area, a content
// editable div, or has an ARIA role of textbox.
- virtual bool IsEditableNode(const WebKit::WebNode& node) const = 0;
-
- // Create a new NPAPI/Pepper plugin depending on |info|. Returns NULL if no
- // plugin was found.
- virtual WebKit::WebPlugin* CreatePlugin(
- WebKit::WebFrame* frame,
- const WebPluginInfo& info,
- const WebKit::WebPluginParams& params) = 0;
+ virtual bool IsEditableNode(const blink::WebNode& node) const = 0;
// Evaluates a string of JavaScript in a particular frame.
- virtual void EvaluateScript(const string16& frame_xpath,
- const string16& jscript,
+ virtual void EvaluateScript(const base::string16& frame_xpath,
+ const base::string16& jscript,
int id,
bool notify_result) = 0;
@@ -114,37 +107,13 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
// Filtered time per frame based on UpdateRect messages.
virtual float GetFilteredTimePerFrame() const = 0;
- // Shows a context menu with the given information. The given client will
- // be called with the result.
- //
- // The request ID will be returned by this function. This is passed to the
- // client functions for identification.
- //
- // If the client is destroyed, CancelContextMenu() should be called with the
- // request ID returned by this function.
- //
- // Note: if you end up having clients outliving the RenderView, we should add
- // a CancelContextMenuCallback function that takes a request id.
- virtual int ShowContextMenu(ContextMenuClient* client,
- const ContextMenuParams& params) = 0;
-
- // Cancels a context menu in the event that the client is destroyed before the
- // menu is closed.
- virtual void CancelContextMenu(int request_id) = 0;
-
// Returns the current visibility of the WebView.
- virtual WebKit::WebPageVisibilityState GetVisibilityState() const = 0;
+ virtual blink::WebPageVisibilityState GetVisibilityState() const = 0;
// Displays a modal alert dialog containing the given message. Returns
// once the user dismisses the dialog.
- virtual void RunModalAlertDialog(WebKit::WebFrame* frame,
- const WebKit::WebString& message) = 0;
-
- // The client should handle the navigation externally.
- virtual void LoadURLExternally(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationPolicy policy) = 0;
+ virtual void RunModalAlertDialog(blink::WebFrame* frame,
+ const blink::WebString& message) = 0;
// Used by plugins that load data in this RenderView to update the loading
// notifications.
@@ -161,7 +130,10 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
virtual void ClearEditCommands() = 0;
// Returns a collection of security info about |frame|.
- virtual SSLStatus GetSSLStatusOfFrame(WebKit::WebFrame* frame) const = 0;
+ virtual SSLStatus GetSSLStatusOfFrame(blink::WebFrame* frame) const = 0;
+
+ // Returns |renderer_preferences_.accept_languages| value.
+ virtual const std::string& GetAcceptLanguages() const = 0;
#if defined(OS_ANDROID)
virtual void UpdateTopControlsState(TopControlsState constraints,
diff --git a/chromium/content/public/renderer/render_view_observer.cc b/chromium/content/public/renderer/render_view_observer.cc
index c0271c11fb4..dd439cf1b2f 100644
--- a/chromium/content/public/renderer/render_view_observer.cc
+++ b/chromium/content/public/renderer/render_view_observer.cc
@@ -6,7 +6,7 @@
#include "content/renderer/render_view_impl.h"
-using WebKit::WebFrame;
+using blink::WebFrame;
namespace content {
diff --git a/chromium/content/public/renderer/render_view_observer.h b/chromium/content/public/renderer/render_view_observer.h
index 87158b4c7d4..9578867cbff 100644
--- a/chromium/content/public/renderer/render_view_observer.h
+++ b/chromium/content/public/renderer/render_view_observer.h
@@ -10,6 +10,7 @@
#include "content/common/content_export.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebIconURL.h"
class GURL;
@@ -20,7 +21,7 @@ class PpapiHost;
}
}
-namespace WebKit {
+namespace blink {
class WebDataSource;
class WebFrame;
class WebFormElement;
@@ -52,45 +53,47 @@ class CONTENT_EXPORT RenderViewObserver : public IPC::Listener,
// These match the WebKit API notifications
virtual void DidStartLoading() {}
virtual void DidStopLoading() {}
- virtual void DidFinishDocumentLoad(WebKit::WebFrame* frame) {}
- virtual void DidFailLoad(WebKit::WebFrame* frame,
- const WebKit::WebURLError& error) {}
- virtual void DidFinishLoad(WebKit::WebFrame* frame) {}
- virtual void DidStartProvisionalLoad(WebKit::WebFrame* frame) {}
- virtual void DidFailProvisionalLoad(WebKit::WebFrame* frame,
- const WebKit::WebURLError& error) {}
- virtual void DidCommitProvisionalLoad(WebKit::WebFrame* frame,
+ virtual void DidFinishDocumentLoad(blink::WebFrame* frame) {}
+ virtual void DidFailLoad(blink::WebFrame* frame,
+ const blink::WebURLError& error) {}
+ virtual void DidFinishLoad(blink::WebFrame* frame) {}
+ virtual void DidStartProvisionalLoad(blink::WebFrame* frame) {}
+ virtual void DidFailProvisionalLoad(blink::WebFrame* frame,
+ const blink::WebURLError& error) {}
+ virtual void DidCommitProvisionalLoad(blink::WebFrame* frame,
bool is_new_navigation) {}
- virtual void DidClearWindowObject(WebKit::WebFrame* frame) {}
- virtual void DidCreateDocumentElement(WebKit::WebFrame* frame) {}
- virtual void FrameCreated(WebKit::WebFrame* parent,
- WebKit::WebFrame* frame) {}
- virtual void FrameDetached(WebKit::WebFrame* frame) {}
- virtual void FrameWillClose(WebKit::WebFrame* frame) {}
- virtual void WillSendSubmitEvent(WebKit::WebFrame* frame,
- const WebKit::WebFormElement& form) {}
- virtual void WillSubmitForm(WebKit::WebFrame* frame,
- const WebKit::WebFormElement& form) {}
- virtual void DidCreateDataSource(WebKit::WebFrame* frame,
- WebKit::WebDataSource* ds) {}
- virtual void PrintPage(WebKit::WebFrame* frame, bool user_initiated) {}
- virtual void FocusedNodeChanged(const WebKit::WebNode& node) {}
- virtual void WillCreateMediaPlayer(WebKit::WebFrame* frame,
- WebKit::WebMediaPlayerClient* client) {}
+ virtual void DidClearWindowObject(blink::WebFrame* frame) {}
+ virtual void DidCreateDocumentElement(blink::WebFrame* frame) {}
+ virtual void FrameCreated(blink::WebFrame* parent,
+ blink::WebFrame* frame) {}
+ virtual void FrameDetached(blink::WebFrame* frame) {}
+ virtual void FrameWillClose(blink::WebFrame* frame) {}
+ virtual void DidMatchCSS(
+ blink::WebFrame* frame,
+ const blink::WebVector<blink::WebString>& newly_matching_selectors,
+ const blink::WebVector<blink::WebString>& stopped_matching_selectors) {}
+ virtual void WillSendSubmitEvent(blink::WebFrame* frame,
+ const blink::WebFormElement& form) {}
+ virtual void WillSubmitForm(blink::WebFrame* frame,
+ const blink::WebFormElement& form) {}
+ virtual void DidCreateDataSource(blink::WebFrame* frame,
+ blink::WebDataSource* ds) {}
+ virtual void PrintPage(blink::WebFrame* frame, bool user_initiated) {}
+ virtual void FocusedNodeChanged(const blink::WebNode& node) {}
+ virtual void WillCreateMediaPlayer(blink::WebFrame* frame,
+ blink::WebMediaPlayerClient* client) {}
virtual void ZoomLevelChanged() {};
- virtual void DidChangeScrollOffset(WebKit::WebFrame* frame) {}
- virtual void DraggableRegionsChanged(WebKit::WebFrame* frame) {}
+ virtual void DidChangeScrollOffset(blink::WebFrame* frame) {}
+ virtual void DraggableRegionsChanged(blink::WebFrame* frame) {}
virtual void DidRequestShowContextMenu(
- WebKit::WebFrame* frame,
- const WebKit::WebContextMenuData& data) {}
+ blink::WebFrame* frame,
+ const blink::WebContextMenuData& data) {}
virtual void DidCommitCompositorFrame() {}
virtual void DidUpdateLayout() {}
// These match the RenderView methods.
- virtual void DidHandleMouseEvent(const WebKit::WebMouseEvent& event) {}
- virtual void DidHandleTouchEvent(const WebKit::WebTouchEvent& event) {}
- virtual void DidHandleGestureEvent(const WebKit::WebGestureEvent& event) {}
- virtual void DidCreatePepperPlugin(RendererPpapiHost* host) {}
+ virtual void DidHandleMouseEvent(const blink::WebMouseEvent& event) {}
+ virtual void DidHandleTouchEvent(const blink::WebTouchEvent& event) {}
// Called when we receive a console message from WebKit for which we requested
// extra details (like the stack trace). |message| is the error message,
diff --git a/chromium/content/public/renderer/renderer_ppapi_host.h b/chromium/content/public/renderer/renderer_ppapi_host.h
index 88a863fd2d7..4e253e2e2cf 100644
--- a/chromium/content/public/renderer/renderer_ppapi_host.h
+++ b/chromium/content/public/renderer/renderer_ppapi_host.h
@@ -14,6 +14,7 @@
#include "content/common/content_export.h"
#include "ipc/ipc_platform_file.h"
#include "ppapi/c/pp_instance.h"
+#include "url/gurl.h"
namespace base {
class FilePath;
@@ -33,12 +34,13 @@ class PpapiHost;
}
}
-namespace WebKit {
+namespace blink {
class WebPluginContainer;
}
namespace content {
class PepperPluginInstance;
+class RenderFrame;
class RenderView;
// Interface that allows components in the embedder app to talk to the
@@ -70,13 +72,18 @@ class RendererPpapiHost {
virtual PepperPluginInstance* GetPluginInstance(
PP_Instance instance) const = 0;
+ // Returns the RenderFrame for the given plugin instance, or NULL if the
+ // instance is invalid.
+ virtual RenderFrame* GetRenderFrameForInstance(
+ PP_Instance instance) const = 0;
+
// Returns the RenderView for the given plugin instance, or NULL if the
// instance is invalid.
virtual RenderView* GetRenderViewForInstance(PP_Instance instance) const = 0;
// Returns the WebPluginContainer for the given plugin instance, or NULL if
// the instance is invalid.
- virtual WebKit::WebPluginContainer* GetContainerForInstance(
+ virtual blink::WebPluginContainer* GetContainerForInstance(
PP_Instance instance) const = 0;
// Returns the PID of the child process containing the plugin. If running
@@ -96,10 +103,10 @@ class RendererPpapiHost {
// routing ID of the fullscreen widget. Returns 0 on failure.
virtual int GetRoutingIDForWidget(PP_Instance instance) const = 0;
- // Converts the given plugin coordinate to the containing RenderView. This
+ // Converts the given plugin coordinate to the containing RenderFrame. This
// will take into account the current Flash fullscreen state so will use
// the fullscreen widget if it's displayed.
- virtual gfx::Point PluginPointToRenderView(
+ virtual gfx::Point PluginPointToRenderFrame(
PP_Instance instance,
const gfx::Point& pt) const = 0;
@@ -128,6 +135,13 @@ class RendererPpapiHost {
const std::vector<IPC::Message>& nested_msgs,
const base::Callback<void(const std::vector<int>&)>& callback) const = 0;
+ // Gets the URL of the document containing the given PP_Instance.
+ // Returns an empty URL if the instance is invalid.
+ // TODO(yzshen): Some methods such as this one don't need to be pure virtual.
+ // Instead, they could be directly implemented using other methods in this
+ // interface. Consider changing them to static helpers.
+ virtual GURL GetDocumentURL(PP_Instance instance) const = 0;
+
protected:
virtual ~RendererPpapiHost() {}
};
diff --git a/chromium/content/public/renderer/resource_fetcher.h b/chromium/content/public/renderer/resource_fetcher.h
new file mode 100644
index 00000000000..5f57cb6b09a
--- /dev/null
+++ b/chromium/content/public/renderer/resource_fetcher.h
@@ -0,0 +1,55 @@
+// 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_PUBLIC_RENDERER_RESOURCE_FETCHER_H_
+#define CONTENT_PUBLIC_RENDERER_RESOURCE_FETCHER_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
+
+class GURL;
+
+namespace base {
+class TimeDelta;
+}
+
+namespace blink {
+class WebFrame;
+class WebURLResponse;
+}
+
+namespace content {
+
+// Interface to download resources asynchronously.
+class CONTENT_EXPORT ResourceFetcher {
+ public:
+ virtual ~ResourceFetcher() {}
+
+ // This will be called asynchronously after the URL has been fetched,
+ // successfully or not. If there is a failure, response and data will both be
+ // empty. |response| and |data| are both valid until the URLFetcher instance
+ // is destroyed.
+ typedef base::Callback<void(const blink::WebURLResponse& response,
+ const std::string& data)> Callback;
+
+ // Creates a ResourceFetcher and starts fetching the specified resource.
+ // Caller takes ownership of the returned object. Deleting the
+ // ResourceFetcher will cancel the request, and the callback will never be
+ // run.
+ static ResourceFetcher* Create(const GURL& url,
+ blink::WebFrame* frame,
+ blink::WebURLRequest::TargetType target_type,
+ const Callback& callback);
+
+ // Sets how long to wait for the server to reply. By default, there is no
+ // timeout.
+ virtual void SetTimeout(const base::TimeDelta& timeout) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_RESOURCE_FETCHER_H_
diff --git a/chromium/content/public/renderer/v8_value_converter.h b/chromium/content/public/renderer/v8_value_converter.h
index 11514f71789..2b1011310a1 100644
--- a/chromium/content/public/renderer/v8_value_converter.h
+++ b/chromium/content/public/renderer/v8_value_converter.h
@@ -31,11 +31,13 @@ class CONTENT_EXPORT V8ValueConverter {
// If false is returned, V8ValueConverter proceeds with the default
// behavior.
virtual bool FromV8Object(v8::Handle<v8::Object> value,
- base::Value** out) const = 0;
+ base::Value** out,
+ v8::Isolate* isolate) const = 0;
// If false is returned, V8ValueConverter proceeds with the default
// behavior.
virtual bool FromV8Array(v8::Handle<v8::Array> value,
- base::Value** out) const = 0;
+ base::Value** out,
+ v8::Isolate* isolate) const = 0;
};
static V8ValueConverter* create();
diff --git a/chromium/content/public/renderer/web_preferences.h b/chromium/content/public/renderer/web_preferences.h
index f3838437974..a61047338ad 100644
--- a/chromium/content/public/renderer/web_preferences.h
+++ b/chromium/content/public/renderer/web_preferences.h
@@ -9,14 +9,14 @@
struct WebPreferences;
-namespace WebKit {
+namespace blink {
class WebView;
}
namespace content {
CONTENT_EXPORT void ApplyWebPreferences(const WebPreferences& prefs,
- WebKit::WebView* web_view);
+ blink::WebView* web_view);
} // namespace content
diff --git a/chromium/content/public/renderer/webrtc_log_message_delegate.h b/chromium/content/public/renderer/webrtc_log_message_delegate.h
index 44695670db6..cb324df8cb2 100644
--- a/chromium/content/public/renderer/webrtc_log_message_delegate.h
+++ b/chromium/content/public/renderer/webrtc_log_message_delegate.h
@@ -17,11 +17,6 @@ namespace content {
// the ordinary logging stream) that will be used for diagnostic purposes.
class WebRtcLogMessageDelegate {
public:
- // Tells the handler to initialize WebRTC logging. |app_session_id| is set
- // by the Javascript application. |app_url| is the Javascript application URL.
- virtual void InitLogging(const std::string& app_session_id,
- const std::string& app_url) = 0;
-
// Pass a diagnostic WebRTC log message.
virtual void LogMessage(const std::string& message) = 0;
@@ -33,6 +28,9 @@ class WebRtcLogMessageDelegate {
CONTENT_EXPORT void InitWebRtcLoggingDelegate(
WebRtcLogMessageDelegate* delegate);
+// Must be called on IO thread.
+CONTENT_EXPORT void InitWebRtcLogging();
+
} // namespace content
#endif // CONTENT_PUBLIC_RENDERER_MEDIA_WEBRTC_LOG_MESSAGE_DELEGATE_H_
diff --git a/chromium/content/renderer/DEPS b/chromium/content/renderer/DEPS
index 2da21ae9152..10db7729647 100644
--- a/chromium/content/renderer/DEPS
+++ b/chromium/content/renderer/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+content/public/renderer",
"+content/child",
+ "+gin",
"+jingle/glue",
"+media", # For audio input/output and audio/video decoding.
"+third_party/hyphen/hyphen.h",
diff --git a/chromium/content/renderer/OWNERS b/chromium/content/renderer/OWNERS
index 5c44d85d058..b3105d08b3c 100644
--- a/chromium/content/renderer/OWNERS
+++ b/chromium/content/renderer/OWNERS
@@ -1,5 +1,4 @@
jamesr@chromium.org
-jochen@chromium.org
# Mac Sandbox profiles.
per-file *.sb=set noparent
diff --git a/chromium/content/renderer/accessibility/accessibility_node_serializer.cc b/chromium/content/renderer/accessibility/accessibility_node_serializer.cc
index 87fd1494010..39fa24520f5 100644
--- a/chromium/content/renderer/accessibility/accessibility_node_serializer.cc
+++ b/chromium/content/renderer/accessibility/accessibility_node_serializer.cc
@@ -23,12 +23,12 @@
#include "third_party/WebKit/public/web/WebInputElement.h"
#include "third_party/WebKit/public/web/WebNode.h"
-using WebKit::WebAXObject;
-using WebKit::WebDocument;
-using WebKit::WebDocumentType;
-using WebKit::WebElement;
-using WebKit::WebNode;
-using WebKit::WebVector;
+using blink::WebAXObject;
+using blink::WebDocument;
+using blink::WebDocumentType;
+using blink::WebElement;
+using blink::WebNode;
+using blink::WebVector;
namespace content {
namespace {
@@ -55,71 +55,71 @@ bool IsParentUnignoredOf(const WebAXObject& ancestor,
uint32 ConvertState(const WebAXObject& o) {
uint32 state = 0;
if (o.isChecked())
- state |= (1 << WebKit::WebAXStateChecked);
+ state |= (1 << blink::WebAXStateChecked);
if (o.isCollapsed())
- state |= (1 << WebKit::WebAXStateCollapsed);
+ state |= (1 << blink::WebAXStateCollapsed);
if (o.canSetFocusAttribute())
- state |= (1 << WebKit::WebAXStateFocusable);
+ state |= (1 << blink::WebAXStateFocusable);
if (o.isFocused())
- state |= (1 << WebKit::WebAXStateFocused);
+ state |= (1 << blink::WebAXStateFocused);
- if (o.role() == WebKit::WebAXRolePopUpButton ||
+ if (o.role() == blink::WebAXRolePopUpButton ||
o.ariaHasPopup()) {
- state |= (1 << WebKit::WebAXStateHaspopup);
+ state |= (1 << blink::WebAXStateHaspopup);
if (!o.isCollapsed())
- state |= (1 << WebKit::WebAXStateExpanded);
+ state |= (1 << blink::WebAXStateExpanded);
}
if (o.isHovered())
- state |= (1 << WebKit::WebAXStateHovered);
+ state |= (1 << blink::WebAXStateHovered);
if (o.isIndeterminate())
- state |= (1 << WebKit::WebAXStateIndeterminate);
+ state |= (1 << blink::WebAXStateIndeterminate);
if (!o.isVisible())
- state |= (1 << WebKit::WebAXStateInvisible);
+ state |= (1 << blink::WebAXStateInvisible);
if (o.isLinked())
- state |= (1 << WebKit::WebAXStateLinked);
+ state |= (1 << blink::WebAXStateLinked);
if (o.isMultiSelectable())
- state |= (1 << WebKit::WebAXStateMultiselectable);
+ state |= (1 << blink::WebAXStateMultiselectable);
if (o.isOffScreen())
- state |= (1 << WebKit::WebAXStateOffscreen);
+ state |= (1 << blink::WebAXStateOffscreen);
if (o.isPressed())
- state |= (1 << WebKit::WebAXStatePressed);
+ state |= (1 << blink::WebAXStatePressed);
if (o.isPasswordField())
- state |= (1 << WebKit::WebAXStateProtected);
+ state |= (1 << blink::WebAXStateProtected);
if (o.isReadOnly())
- state |= (1 << WebKit::WebAXStateReadonly);
+ state |= (1 << blink::WebAXStateReadonly);
if (o.isRequired())
- state |= (1 << WebKit::WebAXStateRequired);
+ state |= (1 << blink::WebAXStateRequired);
if (o.canSetSelectedAttribute())
- state |= (1 << WebKit::WebAXStateSelectable);
+ state |= (1 << blink::WebAXStateSelectable);
if (o.isSelected())
- state |= (1 << WebKit::WebAXStateSelected);
+ state |= (1 << blink::WebAXStateSelected);
if (o.isVisited())
- state |= (1 << WebKit::WebAXStateVisited);
+ state |= (1 << blink::WebAXStateVisited);
if (o.isEnabled())
- state |= (1 << WebKit::WebAXStateEnabled);
+ state |= (1 << blink::WebAXStateEnabled);
if (o.isVertical())
- state |= (1 << WebKit::WebAXStateVertical);
+ state |= (1 << blink::WebAXStateVertical);
if (o.isVisited())
- state |= (1 << WebKit::WebAXStateVisited);
+ state |= (1 << blink::WebAXStateVisited);
return state;
}
@@ -143,7 +143,7 @@ void SerializeAccessibilityNode(
dst->AddStringAttribute(dst->ATTR_VALUE, UTF16ToUTF8(src.stringValue()));
}
- if (dst->role == WebKit::WebAXRoleColorWell) {
+ if (dst->role == blink::WebAXRoleColorWell) {
int r, g, b;
src.colorValue(r, g, b);
dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_RED, r);
@@ -151,6 +151,32 @@ void SerializeAccessibilityNode(
dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_BLUE, b);
}
+ if (dst->role == blink::WebAXRoleInlineTextBox) {
+ dst->AddIntAttribute(dst->ATTR_TEXT_DIRECTION, src.textDirection());
+
+ WebVector<int> src_character_offsets;
+ src.characterOffsets(src_character_offsets);
+ std::vector<int32> character_offsets;
+ character_offsets.reserve(src_character_offsets.size());
+ for (size_t i = 0; i < src_character_offsets.size(); ++i)
+ character_offsets.push_back(src_character_offsets[i]);
+ dst->AddIntListAttribute(dst->ATTR_CHARACTER_OFFSETS, character_offsets);
+
+ WebVector<int> src_word_starts;
+ WebVector<int> src_word_ends;
+ src.wordBoundaries(src_word_starts, src_word_ends);
+ std::vector<int32> word_starts;
+ std::vector<int32> word_ends;
+ word_starts.reserve(src_word_starts.size());
+ word_ends.reserve(src_word_starts.size());
+ for (size_t i = 0; i < src_word_starts.size(); ++i) {
+ word_starts.push_back(src_word_starts[i]);
+ word_ends.push_back(src_word_ends[i]);
+ }
+ dst->AddIntListAttribute(dst->ATTR_WORD_STARTS, word_starts);
+ dst->AddIntListAttribute(dst->ATTR_WORD_ENDS, word_ends);
+ }
+
if (src.accessKey().length())
dst->AddStringAttribute(dst->ATTR_ACCESS_KEY, UTF16ToUTF8(src.accessKey()));
if (src.actionVerb().length())
@@ -182,18 +208,18 @@ void SerializeAccessibilityNode(
if (!src.url().isEmpty())
dst->AddStringAttribute(dst->ATTR_URL, src.url().spec());
- if (dst->role == WebKit::WebAXRoleHeading)
+ if (dst->role == blink::WebAXRoleHeading)
dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.headingLevel());
- else if ((dst->role == WebKit::WebAXRoleTreeItem ||
- dst->role == WebKit::WebAXRoleRow) &&
+ else if ((dst->role == blink::WebAXRoleTreeItem ||
+ dst->role == blink::WebAXRoleRow) &&
src.hierarchicalLevel() > 0) {
dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.hierarchicalLevel());
}
// Treat the active list box item as focused.
- if (dst->role == WebKit::WebAXRoleListBoxOption &&
+ if (dst->role == blink::WebAXRoleListBoxOption &&
src.isSelectedOptionActive()) {
- dst->state |= (1 << WebKit::WebAXStateFocused);
+ dst->state |= (1 << blink::WebAXStateFocused);
}
if (src.canvasHasFallbackContent())
@@ -211,7 +237,7 @@ void SerializeAccessibilityNode(
is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME"));
if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true"))
- dst->state |= (1 << WebKit::WebAXStateExpanded);
+ dst->state |= (1 << blink::WebAXStateExpanded);
// TODO(ctguil): The tagName in WebKit is lower cased but
// HTMLElement::nodeName calls localNameUpper. Consider adding
@@ -226,9 +252,9 @@ void SerializeAccessibilityNode(
dst->html_attributes.push_back(std::make_pair(name, value));
}
- if (dst->role == WebKit::WebAXRoleEditableText ||
- dst->role == WebKit::WebAXRoleTextArea ||
- dst->role == WebKit::WebAXRoleTextField) {
+ if (dst->role == blink::WebAXRoleEditableText ||
+ dst->role == blink::WebAXRoleTextArea ||
+ dst->role == blink::WebAXRoleTextField) {
dst->AddIntAttribute(dst->ATTR_TEXT_SEL_START, src.selectionStart());
dst->AddIntAttribute(dst->ATTR_TEXT_SEL_END, src.selectionEnd());
@@ -316,10 +342,10 @@ void SerializeAccessibilityNode(
container_live_relevant);
}
- if (dst->role == WebKit::WebAXRoleProgressIndicator ||
- dst->role == WebKit::WebAXRoleScrollBar ||
- dst->role == WebKit::WebAXRoleSlider ||
- dst->role == WebKit::WebAXRoleSpinButton) {
+ if (dst->role == blink::WebAXRoleProgressIndicator ||
+ dst->role == blink::WebAXRoleScrollBar ||
+ dst->role == blink::WebAXRoleSlider ||
+ dst->role == blink::WebAXRoleSpinButton) {
dst->AddFloatAttribute(dst->ATTR_VALUE_FOR_RANGE, src.valueForRange());
dst->AddFloatAttribute(dst->ATTR_MAX_VALUE_FOR_RANGE,
src.maxValueForRange());
@@ -327,8 +353,8 @@ void SerializeAccessibilityNode(
src.minValueForRange());
}
- if (dst->role == WebKit::WebAXRoleDocument ||
- dst->role == WebKit::WebAXRoleWebArea) {
+ if (dst->role == blink::WebAXRoleDocument ||
+ dst->role == blink::WebAXRoleWebArea) {
dst->AddStringAttribute(dst->ATTR_HTML_TAG, "#document");
const WebDocument& document = src.document();
if (name.empty())
@@ -361,7 +387,7 @@ void SerializeAccessibilityNode(
dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MAX, max_offset.height());
}
- if (dst->role == WebKit::WebAXRoleTable) {
+ if (dst->role == blink::WebAXRoleTable) {
int column_count = src.columnCount();
int row_count = src.rowCount();
if (column_count > 0 && row_count > 0) {
@@ -391,23 +417,23 @@ void SerializeAccessibilityNode(
}
}
- if (dst->role == WebKit::WebAXRoleRow) {
+ if (dst->role == blink::WebAXRoleRow) {
dst->AddIntAttribute(dst->ATTR_TABLE_ROW_INDEX, src.rowIndex());
WebAXObject header = src.rowHeader();
if (!header.isDetached())
dst->AddIntAttribute(dst->ATTR_TABLE_ROW_HEADER_ID, header.axID());
}
- if (dst->role == WebKit::WebAXRoleColumn) {
+ if (dst->role == blink::WebAXRoleColumn) {
dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_INDEX, src.columnIndex());
WebAXObject header = src.columnHeader();
if (!header.isDetached())
dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_HEADER_ID, header.axID());
}
- if (dst->role == WebKit::WebAXRoleCell ||
- dst->role == WebKit::WebAXRoleRowHeader ||
- dst->role == WebKit::WebAXRoleColumnHeader) {
+ if (dst->role == blink::WebAXRoleCell ||
+ dst->role == blink::WebAXRoleRowHeader ||
+ dst->role == blink::WebAXRoleColumnHeader) {
dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_INDEX,
src.cellColumnIndex());
dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_SPAN,
@@ -440,10 +466,10 @@ bool ShouldIncludeChildNode(
const WebAXObject& parent,
const WebAXObject& child) {
switch(parent.role()) {
- case WebKit::WebAXRoleSlider:
- case WebKit::WebAXRoleEditableText:
- case WebKit::WebAXRoleTextArea:
- case WebKit::WebAXRoleTextField:
+ case blink::WebAXRoleSlider:
+ case blink::WebAXRoleEditableText:
+ case blink::WebAXRoleTextArea:
+ case blink::WebAXRoleTextField:
return false;
default:
break;
diff --git a/chromium/content/renderer/accessibility/accessibility_node_serializer.h b/chromium/content/renderer/accessibility/accessibility_node_serializer.h
index 24e7e9e9ab1..374a79df334 100644
--- a/chromium/content/renderer/accessibility/accessibility_node_serializer.h
+++ b/chromium/content/renderer/accessibility/accessibility_node_serializer.h
@@ -11,12 +11,12 @@
namespace content {
void SerializeAccessibilityNode(
- const WebKit::WebAXObject& src,
+ const blink::WebAXObject& src,
AccessibilityNodeData* dst);
bool ShouldIncludeChildNode(
- const WebKit::WebAXObject& parent,
- const WebKit::WebAXObject& child);
+ const blink::WebAXObject& parent,
+ const blink::WebAXObject& child);
} // namespace content
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility.cc b/chromium/content/renderer/accessibility/renderer_accessibility.cc
index cf2ecd68327..18eb78fc6a6 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility.cc
+++ b/chromium/content/renderer/accessibility/renderer_accessibility.cc
@@ -12,10 +12,10 @@
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
-using WebKit::WebAXObject;
-using WebKit::WebDocument;
-using WebKit::WebFrame;
-using WebKit::WebView;
+using blink::WebAXObject;
+using blink::WebDocument;
+using blink::WebFrame;
+using blink::WebView;
namespace content {
@@ -44,59 +44,59 @@ WebDocument RendererAccessibility::GetMainDocument() {
#ifndef NDEBUG
const std::string RendererAccessibility::AccessibilityEventToString(
- WebKit::WebAXEvent event) {
+ blink::WebAXEvent event) {
switch (event) {
- case WebKit::WebAXEventActiveDescendantChanged:
+ case blink::WebAXEventActiveDescendantChanged:
return "active descendant changed";
- case WebKit::WebAXEventAriaAttributeChanged:
+ case blink::WebAXEventAriaAttributeChanged:
return "aria attribute changed";
- case WebKit::WebAXEventAutocorrectionOccured:
+ case blink::WebAXEventAutocorrectionOccured:
return "autocorrection occurred";
- case WebKit::WebAXEventBlur:
+ case blink::WebAXEventBlur:
return "blur";
- case WebKit::WebAXEventAlert:
+ case blink::WebAXEventAlert:
return "alert";
- case WebKit::WebAXEventCheckedStateChanged:
+ case blink::WebAXEventCheckedStateChanged:
return "check state changed";
- case WebKit::WebAXEventChildrenChanged:
+ case blink::WebAXEventChildrenChanged:
return "children changed";
- case WebKit::WebAXEventFocus:
+ case blink::WebAXEventFocus:
return "focus changed";
- case WebKit::WebAXEventInvalidStatusChanged:
+ case blink::WebAXEventInvalidStatusChanged:
return "invalid status changed";
- case WebKit::WebAXEventLayoutComplete:
+ case blink::WebAXEventLayoutComplete:
return "layout complete";
- case WebKit::WebAXEventLiveRegionChanged:
+ case blink::WebAXEventLiveRegionChanged:
return "live region changed";
- case WebKit::WebAXEventLoadComplete:
+ case blink::WebAXEventLoadComplete:
return "load complete";
- case WebKit::WebAXEventMenuListItemSelected:
+ case blink::WebAXEventMenuListItemSelected:
return "menu list item selected";
- case WebKit::WebAXEventMenuListValueChanged:
+ case blink::WebAXEventMenuListValueChanged:
return "menu list changed";
- case WebKit::WebAXEventShow:
+ case blink::WebAXEventShow:
return "object show";
- case WebKit::WebAXEventHide:
+ case blink::WebAXEventHide:
return "object hide";
- case WebKit::WebAXEventRowCountChanged:
+ case blink::WebAXEventRowCountChanged:
return "row count changed";
- case WebKit::WebAXEventRowCollapsed:
+ case blink::WebAXEventRowCollapsed:
return "row collapsed";
- case WebKit::WebAXEventRowExpanded:
+ case blink::WebAXEventRowExpanded:
return "row expanded";
- case WebKit::WebAXEventScrolledToAnchor:
+ case blink::WebAXEventScrolledToAnchor:
return "scrolled to anchor";
- case WebKit::WebAXEventSelectedChildrenChanged:
+ case blink::WebAXEventSelectedChildrenChanged:
return "selected children changed";
- case WebKit::WebAXEventSelectedTextChanged:
+ case blink::WebAXEventSelectedTextChanged:
return "selected text changed";
- case WebKit::WebAXEventTextChanged:
+ case blink::WebAXEventTextChanged:
return "text changed";
- case WebKit::WebAXEventTextInserted:
+ case blink::WebAXEventTextInserted:
return "text inserted";
- case WebKit::WebAXEventTextRemoved:
+ case blink::WebAXEventTextRemoved:
return "text removed";
- case WebKit::WebAXEventValueChanged:
+ case blink::WebAXEventValueChanged:
return "value changed";
default:
NOTREACHED();
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility.h b/chromium/content/renderer/accessibility/renderer_accessibility.h
index 93799eaf60c..cc157ff0671 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility.h
+++ b/chromium/content/renderer/accessibility/renderer_accessibility.h
@@ -9,7 +9,7 @@
#include "content/public/renderer/render_view_observer.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
-namespace WebKit {
+namespace blink {
class WebDocument;
};
@@ -55,15 +55,15 @@ class CONTENT_EXPORT RendererAccessibility : public RenderViewObserver {
// Called when an accessibility notification occurs in WebKit.
virtual void HandleWebAccessibilityEvent(
- const WebKit::WebAXObject& obj, WebKit::WebAXEvent event) = 0;
+ const blink::WebAXObject& obj, blink::WebAXEvent event) = 0;
protected:
// Returns the main top-level document for this page, or NULL if there's
// no view or frame.
- WebKit::WebDocument GetMainDocument();
+ blink::WebDocument GetMainDocument();
#ifndef NDEBUG
- const std::string AccessibilityEventToString(WebKit::WebAXEvent event);
+ const std::string AccessibilityEventToString(blink::WebAXEvent event);
#endif
// The RenderViewImpl that owns us.
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc b/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc
index 7f91243a47a..6cc5550c7e7 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc
+++ b/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc
@@ -14,8 +14,8 @@
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebView.h"
-using WebKit::WebAXObject;
-using WebKit::WebDocument;
+using blink::WebAXObject;
+using blink::WebDocument;
namespace content {
@@ -102,7 +102,7 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) {
SetMode(AccessibilityModeEditableTextOnly);
// Set a minimum size and give focus so simulated events work.
- view()->webwidget()->resize(WebKit::WebSize(500, 500));
+ view()->webwidget()->resize(blink::WebSize(500, 500));
view()->webwidget()->setFocus(true);
std::string html =
@@ -125,16 +125,16 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) {
AccessibilityHostMsg_EventParams event;
GetLastAccEvent(&event);
EXPECT_EQ(event.event_type,
- WebKit::WebAXEventLayoutComplete);
+ blink::WebAXEventLayoutComplete);
EXPECT_EQ(event.id, 1);
EXPECT_EQ(event.nodes.size(), 2U);
EXPECT_EQ(event.nodes[0].id, 1);
EXPECT_EQ(event.nodes[0].role,
- WebKit::WebAXRoleRootWebArea);
+ blink::WebAXRoleRootWebArea);
EXPECT_EQ(event.nodes[0].state,
- (1U << WebKit::WebAXStateReadonly) |
- (1U << WebKit::WebAXStateFocusable) |
- (1U << WebKit::WebAXStateFocused));
+ (1U << blink::WebAXStateReadonly) |
+ (1U << blink::WebAXStateFocusable) |
+ (1U << blink::WebAXStateFocused));
EXPECT_EQ(event.nodes[0].child_ids.size(), 1U);
}
@@ -146,21 +146,21 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) {
AccessibilityHostMsg_EventParams event;
GetLastAccEvent(&event);
EXPECT_EQ(event.event_type,
- WebKit::WebAXEventFocus);
+ blink::WebAXEventFocus);
EXPECT_EQ(event.id, 3);
EXPECT_EQ(event.nodes[0].id, 1);
EXPECT_EQ(event.nodes[0].role,
- WebKit::WebAXRoleRootWebArea);
+ blink::WebAXRoleRootWebArea);
EXPECT_EQ(event.nodes[0].state,
- (1U << WebKit::WebAXStateReadonly) |
- (1U << WebKit::WebAXStateFocusable));
+ (1U << blink::WebAXStateReadonly) |
+ (1U << blink::WebAXStateFocusable));
EXPECT_EQ(event.nodes[0].child_ids.size(), 1U);
EXPECT_EQ(event.nodes[1].id, 3);
EXPECT_EQ(event.nodes[1].role,
- WebKit::WebAXRoleGroup);
+ blink::WebAXRoleGroup);
EXPECT_EQ(event.nodes[1].state,
- (1U << WebKit::WebAXStateFocusable) |
- (1U << WebKit::WebAXStateFocused));
+ (1U << blink::WebAXStateFocusable) |
+ (1U << blink::WebAXStateFocused));
}
// Check other editable text nodes.
@@ -172,8 +172,8 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) {
GetLastAccEvent(&event);
EXPECT_EQ(event.id, 4);
EXPECT_EQ(event.nodes[1].state,
- (1U << WebKit::WebAXStateFocusable) |
- (1U << WebKit::WebAXStateFocused));
+ (1U << blink::WebAXStateFocusable) |
+ (1U << blink::WebAXStateFocused));
}
{
@@ -184,8 +184,8 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) {
GetLastAccEvent(&event);
EXPECT_EQ(event.id, 5);
EXPECT_EQ(event.nodes[1].state,
- (1U << WebKit::WebAXStateFocusable) |
- (1U << WebKit::WebAXStateFocused));
+ (1U << blink::WebAXStateFocusable) |
+ (1U << blink::WebAXStateFocused));
}
{
@@ -196,8 +196,8 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) {
GetLastAccEvent(&event);
EXPECT_EQ(event.id, 6);
EXPECT_EQ(event.nodes[1].state,
- (1U << WebKit::WebAXStateFocusable) |
- (1U << WebKit::WebAXStateFocused));
+ (1U << blink::WebAXStateFocusable) |
+ (1U << blink::WebAXStateFocused));
}
// Try focusing things that aren't editable text.
@@ -209,9 +209,9 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) {
GetLastAccEvent(&event);
EXPECT_EQ(event.id, 7);
EXPECT_EQ(event.nodes[1].state,
- (1U << WebKit::WebAXStateFocusable) |
- (1U << WebKit::WebAXStateFocused) |
- (1U << WebKit::WebAXStateReadonly));
+ (1U << blink::WebAXStateFocusable) |
+ (1U << blink::WebAXStateFocused) |
+ (1U << blink::WebAXStateReadonly));
}
{
@@ -222,9 +222,9 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) {
GetLastAccEvent(&event);
EXPECT_EQ(event.id, 8);
EXPECT_EQ(event.nodes[1].state,
- (1U << WebKit::WebAXStateFocusable) |
- (1U << WebKit::WebAXStateFocused) |
- (1U << WebKit::WebAXStateReadonly));
+ (1U << blink::WebAXStateFocusable) |
+ (1U << blink::WebAXStateFocused) |
+ (1U << blink::WebAXStateReadonly));
}
// Clear focus.
@@ -269,7 +269,7 @@ TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) {
WebAXObject root_obj = document.accessibilityObject();
accessibility->HandleWebAccessibilityEvent(
root_obj,
- WebKit::WebAXEventLayoutComplete);
+ blink::WebAXEventLayoutComplete);
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(4, accessibility->browser_tree_node_count());
EXPECT_EQ(1, CountAccessibilityNodesSentToBrowser());
@@ -289,7 +289,7 @@ TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) {
sink_->ClearMessages();
accessibility->HandleWebAccessibilityEvent(
root_obj,
- WebKit::WebAXEventLayoutComplete);
+ blink::WebAXEventLayoutComplete);
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(4, accessibility->browser_tree_node_count());
EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
@@ -304,7 +304,7 @@ TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) {
const WebAXObject& first_child = root_obj.childAt(0);
accessibility->HandleWebAccessibilityEvent(
first_child,
- WebKit::WebAXEventLiveRegionChanged);
+ blink::WebAXEventLiveRegionChanged);
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(4, accessibility->browser_tree_node_count());
EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
@@ -332,8 +332,8 @@ TEST_F(RendererAccessibilityTest,
scoped_ptr<TestRendererAccessibilityComplete> accessibility(
new TestRendererAccessibilityComplete(view()));
accessibility->SendPendingAccessibilityEvents();
- EXPECT_EQ(3, accessibility->browser_tree_node_count());
- EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser());
+ EXPECT_EQ(5, accessibility->browser_tree_node_count());
+ EXPECT_EQ(5, CountAccessibilityNodesSentToBrowser());
// Post a "value changed" event, but then swap out
// before sending it. It shouldn't send the event while
@@ -343,7 +343,7 @@ TEST_F(RendererAccessibilityTest,
WebAXObject root_obj = document.accessibilityObject();
accessibility->HandleWebAccessibilityEvent(
root_obj,
- WebKit::WebAXEventValueChanged);
+ blink::WebAXEventValueChanged);
view()->OnSwapOut();
accessibility->SendPendingAccessibilityEvents();
EXPECT_FALSE(sink_->GetUniqueMessageMatching(
@@ -405,7 +405,7 @@ TEST_F(RendererAccessibilityTest, HideAccessibilityObject) {
sink_->ClearMessages();
accessibility->HandleWebAccessibilityEvent(
node_a,
- WebKit::WebAXEventChildrenChanged);
+ blink::WebAXEventChildrenChanged);
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(3, accessibility->browser_tree_node_count());
@@ -455,7 +455,7 @@ TEST_F(RendererAccessibilityTest, ShowAccessibilityObject) {
WebAXObject node_a = root_obj.childAt(0);
accessibility->HandleWebAccessibilityEvent(
node_a,
- WebKit::WebAXEventChildrenChanged);
+ blink::WebAXEventChildrenChanged);
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(4, accessibility->browser_tree_node_count());
@@ -479,8 +479,8 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) {
scoped_ptr<TestRendererAccessibilityComplete> accessibility(
new TestRendererAccessibilityComplete(view()));
accessibility->SendPendingAccessibilityEvents();
- EXPECT_EQ(5, accessibility->browser_tree_node_count());
- EXPECT_EQ(5, CountAccessibilityNodesSentToBrowser());
+ EXPECT_EQ(7, accessibility->browser_tree_node_count());
+ EXPECT_EQ(7, CountAccessibilityNodesSentToBrowser());
// Initially, the accessibility tree looks like this:
//
@@ -488,7 +488,9 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) {
// +--Body
// +--Anonymous Block
// +--Static Text "1"
+ // +--Inline Text Box "1"
// +--Static Text "2"
+ // +--Inline Text Box "2"
WebDocument document = view()->GetWebView()->mainFrame()->document();
WebAXObject root_obj = document.accessibilityObject();
WebAXObject body = root_obj.childAt(0);
@@ -507,7 +509,7 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) {
sink_->ClearMessages();
accessibility->HandleWebAccessibilityEvent(
body,
- WebKit::WebAXEventChildrenChanged);
+ blink::WebAXEventChildrenChanged);
accessibility->SendPendingAccessibilityEvents();
@@ -516,17 +518,19 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) {
// Document
// +--Body
// +--Static Text "1"
+ // +--Inline Text Box "1"
// +--Static Text "2"
+ // +--Inline Text Box "2"
//
// We just assert that there are now four nodes in the
// accessibility tree and that only three nodes needed
// to be updated (the body, the static text 1, and
// the static text 2).
- EXPECT_EQ(4, accessibility->browser_tree_node_count());
+ EXPECT_EQ(6, accessibility->browser_tree_node_count());
AccessibilityHostMsg_EventParams event;
GetLastAccEvent(&event);
- ASSERT_EQ(3U, event.nodes.size());
+ ASSERT_EQ(5U, event.nodes.size());
EXPECT_EQ(body.axID(), event.nodes[0].id);
EXPECT_EQ(text_1.axID(), event.nodes[1].id);
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_complete.cc b/chromium/content/renderer/accessibility/renderer_accessibility_complete.cc
index d70a00a4820..bf8466dd871 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility_complete.cc
+++ b/chromium/content/renderer/accessibility/renderer_accessibility_complete.cc
@@ -17,14 +17,14 @@
#include "third_party/WebKit/public/web/WebNode.h"
#include "third_party/WebKit/public/web/WebView.h"
-using WebKit::WebAXObject;
-using WebKit::WebDocument;
-using WebKit::WebFrame;
-using WebKit::WebNode;
-using WebKit::WebPoint;
-using WebKit::WebRect;
-using WebKit::WebSize;
-using WebKit::WebView;
+using blink::WebAXObject;
+using blink::WebDocument;
+using blink::WebFrame;
+using blink::WebNode;
+using blink::WebPoint;
+using blink::WebRect;
+using blink::WebSize;
+using blink::WebView;
namespace content {
@@ -37,17 +37,30 @@ RendererAccessibilityComplete::RendererAccessibilityComplete(
ack_pending_(false) {
WebAXObject::enableAccessibility();
+#if !defined(OS_ANDROID)
+ // Skip inline text boxes on Android - since there are no native Android
+ // APIs that compute the bounds of a range of text, it's a waste to
+ // include these in the AX tree.
+ WebAXObject::enableInlineTextBoxAccessibility();
+#endif
+
const WebDocument& document = GetMainDocument();
if (!document.isNull()) {
// It's possible that the webview has already loaded a webpage without
// accessibility being enabled. Initialize the browser's cached
// accessibility tree by sending it a notification.
HandleWebAccessibilityEvent(document.accessibilityObject(),
- WebKit::WebAXEventLayoutComplete);
+ blink::WebAXEventLayoutComplete);
}
}
RendererAccessibilityComplete::~RendererAccessibilityComplete() {
+ if (browser_root_) {
+ ClearBrowserTreeNode(browser_root_);
+ browser_id_map_.erase(browser_root_->id);
+ delete browser_root_;
+ }
+ DCHECK(browser_id_map_.empty());
}
bool RendererAccessibilityComplete::OnMessageReceived(
@@ -80,11 +93,11 @@ void RendererAccessibilityComplete::FocusedNodeChanged(const WebNode& node) {
// When focus is cleared, implicitly focus the document.
// TODO(dmazzoni): Make WebKit send this notification instead.
HandleWebAccessibilityEvent(document.accessibilityObject(),
- WebKit::WebAXEventBlur);
+ blink::WebAXEventBlur);
}
}
-void RendererAccessibilityComplete::DidFinishLoad(WebKit::WebFrame* frame) {
+void RendererAccessibilityComplete::DidFinishLoad(blink::WebFrame* frame) {
const WebDocument& document = GetMainDocument();
if (document.isNull())
return;
@@ -95,12 +108,12 @@ void RendererAccessibilityComplete::DidFinishLoad(WebKit::WebFrame* frame) {
// TODO(dmazzoni): remove this once rdar://5794454 is fixed.
WebAXObject new_root = document.accessibilityObject();
if (!browser_root_ || new_root.axID() != browser_root_->id)
- HandleWebAccessibilityEvent(new_root, WebKit::WebAXEventLayoutComplete);
+ HandleWebAccessibilityEvent(new_root, blink::WebAXEventLayoutComplete);
}
void RendererAccessibilityComplete::HandleWebAccessibilityEvent(
- const WebKit::WebAXObject& obj,
- WebKit::WebAXEvent event) {
+ const blink::WebAXObject& obj,
+ blink::WebAXEvent event) {
const WebDocument& document = GetMainDocument();
if (document.isNull())
return;
@@ -116,7 +129,7 @@ void RendererAccessibilityComplete::HandleWebAccessibilityEvent(
if (!obj.equals(document.accessibilityObject())) {
HandleWebAccessibilityEvent(
document.accessibilityObject(),
- WebKit::WebAXEventLayoutComplete);
+ blink::WebAXEventLayoutComplete);
}
}
@@ -188,7 +201,7 @@ void RendererAccessibilityComplete::SendPendingAccessibilityEvents() {
// doesn't also send us events for each child that changed
// selection state, so make sure we re-send that whole subtree.
if (event.event_type ==
- WebKit::WebAXEventSelectedChildrenChanged) {
+ blink::WebAXEventSelectedChildrenChanged) {
base::hash_map<int32, BrowserTreeNode*>::iterator iter =
browser_id_map_.find(obj.axID());
if (iter != browser_id_map_.end())
@@ -207,7 +220,7 @@ void RendererAccessibilityComplete::SendPendingAccessibilityEvents() {
obj.axID() != root_id) {
obj = obj.parentObject();
if (event.event_type ==
- WebKit::WebAXEventChildrenChanged) {
+ blink::WebAXEventChildrenChanged) {
event.id = obj.axID();
}
}
@@ -266,7 +279,7 @@ void RendererAccessibilityComplete::SendPendingAccessibilityEvents() {
if (logging_) {
AccessibilityNodeDataTreeNode tree;
MakeAccessibilityNodeDataTree(event_msg.nodes, &tree);
- LOG(INFO) << "Accessibility update: \n"
+ VLOG(0) << "Accessibility update: \n"
<< "routing id=" << routing_id()
<< " event="
<< AccessibilityEventToString(event.event_type)
@@ -308,7 +321,7 @@ void RendererAccessibilityComplete::AppendLocationChangeEvents(
return;
AccessibilityHostMsg_EventParams event_msg;
- event_msg.event_type = static_cast<WebKit::WebAXEvent>(-1);
+ event_msg.event_type = static_cast<blink::WebAXEvent>(-1);
event_msg.id = root_object.axID();
event_msg.nodes.resize(location_changes.size());
for (size_t i = 0; i < location_changes.size(); i++) {
@@ -328,7 +341,7 @@ RendererAccessibilityComplete::CreateBrowserTreeNode() {
}
void RendererAccessibilityComplete::SerializeChangedNodes(
- const WebKit::WebAXObject& obj,
+ const blink::WebAXObject& obj,
std::vector<AccessibilityNodeData>* dst,
std::set<int>* ids_serialized) {
if (ids_serialized->find(obj.axID()) != ids_serialized->end())
@@ -431,7 +444,7 @@ void RendererAccessibilityComplete::SerializeChangedNodes(
AccessibilityNodeData* serialized_node = &dst->back();
SerializeAccessibilityNode(obj, serialized_node);
if (serialized_node->id == browser_root_->id)
- serialized_node->role = WebKit::WebAXRoleRootWebArea;
+ serialized_node->role = blink::WebAXRoleRootWebArea;
// Iterate over the children, make note of the ones that are new
// and need to be serialized, and update the BrowserTreeNode
@@ -457,7 +470,6 @@ void RendererAccessibilityComplete::SerializeChangedNodes(
serialized_node->child_ids.push_back(child_id);
if (browser_child_id_map.find(child_id) != browser_child_id_map.end()) {
BrowserTreeNode* reused_child = browser_child_id_map[child_id];
- reused_child->location = obj.boundingBoxRect();
browser_node->children.push_back(reused_child);
} else {
BrowserTreeNode* new_child = CreateBrowserTreeNode();
@@ -527,7 +539,7 @@ void RendererAccessibilityComplete::OnScrollToMakeVisible(
// https://bugs.webkit.org/show_bug.cgi?id=73460
HandleWebAccessibilityEvent(
document.accessibilityObject(),
- WebKit::WebAXEventLayoutComplete);
+ blink::WebAXEventLayoutComplete);
}
void RendererAccessibilityComplete::OnScrollToPoint(
@@ -553,7 +565,7 @@ void RendererAccessibilityComplete::OnScrollToPoint(
// https://bugs.webkit.org/show_bug.cgi?id=73460
HandleWebAccessibilityEvent(
document.accessibilityObject(),
- WebKit::WebAXEventLayoutComplete);
+ blink::WebAXEventLayoutComplete);
}
void RendererAccessibilityComplete::OnSetTextSelection(
@@ -572,11 +584,11 @@ void RendererAccessibilityComplete::OnSetTextSelection(
}
// TODO(dmazzoni): support elements other than <input>.
- WebKit::WebNode node = obj.node();
+ blink::WebNode node = obj.node();
if (!node.isNull() && node.isElementNode()) {
- WebKit::WebElement element = node.to<WebKit::WebElement>();
- WebKit::WebInputElement* input_element =
- WebKit::toWebInputElement(&element);
+ blink::WebElement element = node.to<blink::WebElement>();
+ blink::WebInputElement* input_element =
+ blink::toWebInputElement(&element);
if (input_element && input_element->isTextField())
input_element->setSelectionRange(start_offset, end_offset);
}
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_complete.h b/chromium/content/renderer/accessibility/renderer_accessibility_complete.h
index 174062a4cac..d23c7ba4e5e 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility_complete.h
+++ b/chromium/content/renderer/accessibility/renderer_accessibility_complete.h
@@ -16,7 +16,7 @@
#include "third_party/WebKit/public/web/WebAXEnums.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
-namespace WebKit {
+namespace blink {
class WebDocument;
class WebNode;
};
@@ -40,12 +40,12 @@ class CONTENT_EXPORT RendererAccessibilityComplete
// RenderView::Observer implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void FocusedNodeChanged(const WebKit::WebNode& node) OVERRIDE;
- virtual void DidFinishLoad(WebKit::WebFrame* frame) OVERRIDE;
+ virtual void FocusedNodeChanged(const blink::WebNode& node) OVERRIDE;
+ virtual void DidFinishLoad(blink::WebFrame* frame) OVERRIDE;
// RendererAccessibility.
virtual void HandleWebAccessibilityEvent(
- const WebKit::WebAXObject& obj, WebKit::WebAXEvent event) OVERRIDE;
+ const blink::WebAXObject& obj, blink::WebAXEvent event) OVERRIDE;
// In order to keep track of what nodes the browser knows about, we keep a
// representation of the browser tree - just IDs and parent/child
@@ -78,7 +78,7 @@ class CONTENT_EXPORT RendererAccessibilityComplete
// |obj|, based on what object ids we know the browser already has.
// The set of ids serialized is added to |ids_serialized|, and any
// ids previously in that set are not serialized again.
- void SerializeChangedNodes(const WebKit::WebAXObject& obj,
+ void SerializeChangedNodes(const blink::WebAXObject& obj,
std::vector<AccessibilityNodeData>* dst,
std::set<int>* ids_serialized);
@@ -97,19 +97,19 @@ class CONTENT_EXPORT RendererAccessibilityComplete
void OnFatalError();
// Checks if a WebKit accessibility object is an editable text node.
- bool IsEditableText(const WebKit::WebAXObject& node);
+ bool IsEditableText(const blink::WebAXObject& node);
// Recursively explore the tree of WebKit accessibility objects rooted
// at |src|, and for each editable text node encountered, add a
// corresponding WebAccessibility node as a child of |dst|.
void RecursiveAddEditableTextNodesToTree(
- const WebKit::WebAXObject& src,
+ const blink::WebAXObject& src,
AccessibilityNodeData* dst);
// Build a tree of serializable AccessibilityNodeData nodes to send to the
// browser process, given a WebAXObject node from WebKit.
// Modifies |dst| in-place, it's assumed to be empty.
- void BuildAccessibilityTree(const WebKit::WebAXObject& src,
+ void BuildAccessibilityTree(const blink::WebAXObject& src,
bool include_children,
AccessibilityNodeData* dst);
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc b/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc
index cea316e6710..b8d1f688b96 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc
+++ b/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc
@@ -12,11 +12,11 @@
#include "third_party/WebKit/public/web/WebNode.h"
#include "third_party/WebKit/public/web/WebView.h"
-using WebKit::WebDocument;
-using WebKit::WebElement;
-using WebKit::WebFrame;
-using WebKit::WebNode;
-using WebKit::WebView;
+using blink::WebDocument;
+using blink::WebElement;
+using blink::WebFrame;
+using blink::WebNode;
+using blink::WebView;
namespace {
// The root node will always have id 1. Let each child node have a new
@@ -36,7 +36,7 @@ RendererAccessibilityFocusOnly::~RendererAccessibilityFocusOnly() {
}
void RendererAccessibilityFocusOnly::HandleWebAccessibilityEvent(
- const WebKit::WebAXObject& obj, WebKit::WebAXEvent event) {
+ const blink::WebAXObject& obj, blink::WebAXEvent event) {
// Do nothing.
}
@@ -45,7 +45,7 @@ void RendererAccessibilityFocusOnly::FocusedNodeChanged(const WebNode& node) {
HandleFocusedNodeChanged(node, true);
}
-void RendererAccessibilityFocusOnly::DidFinishLoad(WebKit::WebFrame* frame) {
+void RendererAccessibilityFocusOnly::DidFinishLoad(blink::WebFrame* frame) {
WebView* view = render_view()->GetWebView();
if (view->focusedFrame() != frame)
return;
@@ -88,8 +88,8 @@ void RendererAccessibilityFocusOnly::HandleFocusedNodeChanged(
// event, which doesn't post a native event on Windows.
event.event_type =
send_focus_event ?
- WebKit::WebAXEventFocus :
- WebKit::WebAXEventLayoutComplete;
+ blink::WebAXEventFocus :
+ blink::WebAXEventLayoutComplete;
// Set the id that the event applies to: the root node if nothing
// has focus, otherwise the focused node.
@@ -101,17 +101,17 @@ void RendererAccessibilityFocusOnly::HandleFocusedNodeChanged(
// Always include the root of the tree, the document. It always has id 1.
root.id = 1;
- root.role = WebKit::WebAXRoleRootWebArea;
+ root.role = blink::WebAXRoleRootWebArea;
root.state =
- (1 << WebKit::WebAXStateReadonly) |
- (1 << WebKit::WebAXStateFocusable);
+ (1 << blink::WebAXStateReadonly) |
+ (1 << blink::WebAXStateFocusable);
if (!node_has_focus)
- root.state |= (1 << WebKit::WebAXStateFocused);
+ root.state |= (1 << blink::WebAXStateFocused);
root.location = gfx::Rect(render_view_->size());
root.child_ids.push_back(next_id_);
child.id = next_id_;
- child.role = WebKit::WebAXRoleGroup;
+ child.role = blink::WebAXRoleGroup;
if (!node.isNull() && node.isElementNode()) {
child.location = gfx::Rect(
@@ -124,15 +124,15 @@ void RendererAccessibilityFocusOnly::HandleFocusedNodeChanged(
if (node_has_focus) {
child.state =
- (1 << WebKit::WebAXStateFocusable) |
- (1 << WebKit::WebAXStateFocused);
+ (1 << blink::WebAXStateFocusable) |
+ (1 << blink::WebAXStateFocused);
if (!node_is_editable_text)
- child.state |= (1 << WebKit::WebAXStateReadonly);
+ child.state |= (1 << blink::WebAXStateReadonly);
}
#ifndef NDEBUG
if (logging_) {
- LOG(INFO) << "Accessibility update: \n"
+ VLOG(0) << "Accessibility update: \n"
<< "routing id=" << routing_id()
<< " event="
<< AccessibilityEventToString(event.event_type)
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h b/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h
index 1d01e1df7ca..c8e09c58b91 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h
+++ b/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h
@@ -54,14 +54,14 @@ class RendererAccessibilityFocusOnly : public RendererAccessibility {
// RendererAccessibility implementation.
virtual void HandleWebAccessibilityEvent(
- const WebKit::WebAXObject& obj, WebKit::WebAXEvent event) OVERRIDE;
+ const blink::WebAXObject& obj, blink::WebAXEvent event) OVERRIDE;
// RenderView::Observer implementation.
- virtual void FocusedNodeChanged(const WebKit::WebNode& node) OVERRIDE;
- virtual void DidFinishLoad(WebKit::WebFrame* frame) OVERRIDE;
+ virtual void FocusedNodeChanged(const blink::WebNode& node) OVERRIDE;
+ virtual void DidFinishLoad(blink::WebFrame* frame) OVERRIDE;
private:
- void HandleFocusedNodeChanged(const WebKit::WebNode& node,
+ void HandleFocusedNodeChanged(const blink::WebNode& node,
bool send_focus_event);
int next_id_;
diff --git a/chromium/content/renderer/active_notification_tracker.cc b/chromium/content/renderer/active_notification_tracker.cc
index 9f0b6e0b872..ff2d9cf6561 100644
--- a/chromium/content/renderer/active_notification_tracker.cc
+++ b/chromium/content/renderer/active_notification_tracker.cc
@@ -9,8 +9,8 @@
#include "third_party/WebKit/public/web/WebNotification.h"
#include "third_party/WebKit/public/web/WebNotificationPermissionCallback.h"
-using WebKit::WebNotification;
-using WebKit::WebNotificationPermissionCallback;
+using blink::WebNotification;
+using blink::WebNotificationPermissionCallback;
namespace content {
@@ -38,7 +38,7 @@ bool ActiveNotificationTracker::GetNotification(
}
int ActiveNotificationTracker::RegisterNotification(
- const WebKit::WebNotification& proxy) {
+ const blink::WebNotification& proxy) {
if (reverse_notification_table_.find(proxy)
!= reverse_notification_table_.end()) {
return reverse_notification_table_[proxy];
@@ -66,16 +66,6 @@ void ActiveNotificationTracker::Clear() {
}
}
-void ActiveNotificationTracker::DetachAll() {
- ReverseTable::iterator iter;
- for (iter = reverse_notification_table_.begin();
- iter != reverse_notification_table_.end();
- ++iter) {
- WebNotification notification(iter->first);
- notification.detachPresenter();
- }
-}
-
WebNotificationPermissionCallback* ActiveNotificationTracker::GetCallback(
int id) {
return callback_table_.Lookup(id);
diff --git a/chromium/content/renderer/active_notification_tracker.h b/chromium/content/renderer/active_notification_tracker.h
index 6591eae334f..b6305a56754 100644
--- a/chromium/content/renderer/active_notification_tracker.h
+++ b/chromium/content/renderer/active_notification_tracker.h
@@ -13,7 +13,7 @@
#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebNotification.h"
-namespace WebKit {
+namespace blink {
class WebNotificationPermissionCallback;
}
@@ -28,31 +28,27 @@ class CONTENT_EXPORT ActiveNotificationTracker {
~ActiveNotificationTracker();
// Methods for tracking active notification objects.
- int RegisterNotification(const WebKit::WebNotification& notification);
+ int RegisterNotification(const blink::WebNotification& notification);
void UnregisterNotification(int id);
- bool GetId(const WebKit::WebNotification& notification, int& id);
- bool GetNotification(int id, WebKit::WebNotification* notification);
+ bool GetId(const blink::WebNotification& notification, int& id);
+ bool GetNotification(int id, blink::WebNotification* notification);
// Methods for tracking active permission requests.
int RegisterPermissionRequest(
- WebKit::WebNotificationPermissionCallback* callback);
+ blink::WebNotificationPermissionCallback* callback);
void OnPermissionRequestComplete(int id);
- WebKit::WebNotificationPermissionCallback* GetCallback(int id);
+ blink::WebNotificationPermissionCallback* GetCallback(int id);
// Clears out all active notifications. Useful on page navigation.
void Clear();
- // Detaches all active notifications from their presenter. Necessary
- // when the Presenter is destroyed.
- void DetachAll();
-
private:
- typedef std::map<WebKit::WebNotification, int> ReverseTable;
+ typedef std::map<blink::WebNotification, int> ReverseTable;
// Tracking maps for active notifications and permission requests.
- IDMap<WebKit::WebNotification> notification_table_;
+ IDMap<blink::WebNotification> notification_table_;
ReverseTable reverse_notification_table_;
- IDMap<WebKit::WebNotificationPermissionCallback> callback_table_;
+ IDMap<blink::WebNotificationPermissionCallback> callback_table_;
DISALLOW_COPY_AND_ASSIGN(ActiveNotificationTracker);
};
diff --git a/chromium/content/renderer/active_notification_tracker_unittest.cc b/chromium/content/renderer/active_notification_tracker_unittest.cc
index 714a0d110e4..88e8dcd054a 100644
--- a/chromium/content/renderer/active_notification_tracker_unittest.cc
+++ b/chromium/content/renderer/active_notification_tracker_unittest.cc
@@ -10,13 +10,13 @@ namespace content {
TEST(ActiveNotificationTrackerTest, TestLookupAndClear) {
ActiveNotificationTracker tracker;
- WebKit::WebNotification notification1;
+ blink::WebNotification notification1;
int id1 = tracker.RegisterNotification(notification1);
- WebKit::WebNotification notification2;
+ blink::WebNotification notification2;
int id2 = tracker.RegisterNotification(notification2);
- WebKit::WebNotification result;
+ blink::WebNotification result;
tracker.GetNotification(id1, &result);
EXPECT_TRUE(result == notification1);
diff --git a/chromium/content/renderer/android/OWNERS b/chromium/content/renderer/android/OWNERS
index 7b7df6dc836..29d0acf8c4e 100644
--- a/chromium/content/renderer/android/OWNERS
+++ b/chromium/content/renderer/android/OWNERS
@@ -1,4 +1,3 @@
bulach@chromium.org
-joth@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
diff --git a/chromium/content/renderer/android/address_detector.cc b/chromium/content/renderer/android/address_detector.cc
index afc7ab6c301..fdc70b136ae 100644
--- a/chromium/content/renderer/android/address_detector.cc
+++ b/chromium/content/renderer/android/address_detector.cc
@@ -36,20 +36,23 @@ size_t AddressDetector::GetMaximumContentLength() {
return kMaxAddressLength;
}
-std::string AddressDetector::GetContentText(const string16& text) {
+std::string AddressDetector::GetContentText(const base::string16& text) {
// Get the address and replace unicode bullets with commas.
- string16 address_16 = CollapseWhitespace(text, false);
+ base::string16 address_16 = CollapseWhitespace(text, false);
std::replace(address_16.begin(), address_16.end(),
static_cast<char16>(0x2022), static_cast<char16>(','));
return UTF16ToUTF8(address_16);
}
-bool AddressDetector::FindContent(const string16::const_iterator& begin,
- const string16::const_iterator& end, size_t* start_pos, size_t* end_pos,
+bool AddressDetector::FindContent(
+ const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end,
+ size_t* start_pos,
+ size_t* end_pos,
std::string* content_text) {
if (address_parser::FindAddress(begin, end, start_pos, end_pos)) {
content_text->assign(
- GetContentText(string16(begin + *start_pos, begin + *end_pos)));
+ GetContentText(base::string16(begin + *start_pos, begin + *end_pos)));
return true;
}
return false;
diff --git a/chromium/content/renderer/android/address_detector.h b/chromium/content/renderer/android/address_detector.h
index 2619503af91..eea777f1329 100644
--- a/chromium/content/renderer/android/address_detector.h
+++ b/chromium/content/renderer/android/address_detector.h
@@ -19,15 +19,15 @@ class AddressDetector : public ContentDetector {
private:
// Implementation of ContentDetector.
- virtual bool FindContent(const string16::const_iterator& begin,
- const string16::const_iterator& end,
+ virtual bool FindContent(const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end,
size_t* start_pos,
size_t* end_pos,
std::string* content_text) OVERRIDE;
virtual GURL GetIntentURL(const std::string& content_text) OVERRIDE;
virtual size_t GetMaximumContentLength() OVERRIDE;
- std::string GetContentText(const string16& text);
+ std::string GetContentText(const base::string16& text);
DISALLOW_COPY_AND_ASSIGN(AddressDetector);
};
diff --git a/chromium/content/renderer/android/content_detector.cc b/chromium/content/renderer/android/content_detector.cc
index 95caba55a94..e5d2f05df71 100644
--- a/chromium/content/renderer/android/content_detector.cc
+++ b/chromium/content/renderer/android/content_detector.cc
@@ -9,14 +9,14 @@
#include "third_party/WebKit/public/web/WebHitTestResult.h"
#include "third_party/WebKit/public/web/WebSurroundingText.h"
-using WebKit::WebRange;
-using WebKit::WebSurroundingText;
+using blink::WebRange;
+using blink::WebSurroundingText;
namespace content {
ContentDetector::Result::Result() : valid(false) {}
-ContentDetector::Result::Result(const WebKit::WebRange& content_boundaries,
+ContentDetector::Result::Result(const blink::WebRange& content_boundaries,
const std::string& text,
const GURL& intent_url)
: valid(true),
@@ -28,12 +28,12 @@ ContentDetector::Result::Result(const WebKit::WebRange& content_boundaries,
ContentDetector::Result::~Result() {}
ContentDetector::Result ContentDetector::FindTappedContent(
- const WebKit::WebHitTestResult& hit_test) {
+ const blink::WebHitTestResult& hit_test) {
if (hit_test.isNull())
return Result();
std::string content_text;
- WebKit::WebRange range = FindContentRange(hit_test, &content_text);
+ blink::WebRange range = FindContentRange(hit_test, &content_text);
if (range.isNull())
return Result();
@@ -42,7 +42,7 @@ ContentDetector::Result ContentDetector::FindTappedContent(
}
WebRange ContentDetector::FindContentRange(
- const WebKit::WebHitTestResult& hit_test,
+ const blink::WebHitTestResult& hit_test,
std::string* content_text) {
// As the surrounding text extractor looks at maxLength/2 characters on
// either side of the hit point, we need to double max content length here.
@@ -52,7 +52,7 @@ WebRange ContentDetector::FindContentRange(
if (surrounding_text.isNull())
return WebRange();
- string16 content = surrounding_text.textContent();
+ base::string16 content = surrounding_text.textContent();
if (content.empty())
return WebRange();
diff --git a/chromium/content/renderer/android/content_detector.h b/chromium/content/renderer/android/content_detector.h
index d17a5855b23..28a153af8a0 100644
--- a/chromium/content/renderer/android/content_detector.h
+++ b/chromium/content/renderer/android/content_detector.h
@@ -8,7 +8,7 @@
#include "third_party/WebKit/public/web/WebRange.h"
#include "url/gurl.h"
-namespace WebKit {
+namespace blink {
class WebHitTestResult;
}
@@ -20,13 +20,13 @@ class ContentDetector {
// Holds the content detection results.
struct Result {
Result();
- Result(const WebKit::WebRange& content_boundaries,
+ Result(const blink::WebRange& content_boundaries,
const std::string& text,
const GURL& intent_url);
~Result();
bool valid;
- WebKit::WebRange content_boundaries;
+ blink::WebRange content_boundaries;
std::string text; // Processed text of the content.
GURL intent_url; // URL of the intent that should process this content.
};
@@ -35,7 +35,7 @@ class ContentDetector {
// Returns a WebKit range delimiting the contents found around the tapped
// position. If no content is found a null range will be returned.
- Result FindTappedContent(const WebKit::WebHitTestResult& hit_test);
+ Result FindTappedContent(const blink::WebHitTestResult& hit_test);
protected:
ContentDetector() {}
@@ -44,8 +44,8 @@ class ContentDetector {
// if the desired content is found. The start and end positions relative to
// the input iterators are returned in start_pos and end_pos.
// The end position is assumed to be non-inclusive.
- virtual bool FindContent(const string16::const_iterator& begin,
- const string16::const_iterator& end,
+ virtual bool FindContent(const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end,
size_t* start_pos,
size_t* end_pos,
std::string* content_text) = 0;
@@ -57,7 +57,7 @@ class ContentDetector {
// position in order to search for content.
virtual size_t GetMaximumContentLength() = 0;
- WebKit::WebRange FindContentRange(const WebKit::WebHitTestResult& hit_test,
+ blink::WebRange FindContentRange(const blink::WebHitTestResult& hit_test,
std::string* content_text);
DISALLOW_COPY_AND_ASSIGN(ContentDetector);
diff --git a/chromium/content/renderer/android/email_detector.cc b/chromium/content/renderer/android/email_detector.cc
index 28b8af4d901..dba1f4245c7 100644
--- a/chromium/content/renderer/android/email_detector.cc
+++ b/chromium/content/renderer/android/email_detector.cc
@@ -42,12 +42,12 @@ GURL EmailDetector::GetIntentURL(const std::string& content_text) {
net::EscapeQueryParamValue(content_text, true));
}
-bool EmailDetector::FindContent(const string16::const_iterator& begin,
- const string16::const_iterator& end,
+bool EmailDetector::FindContent(const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end,
size_t* start_pos,
size_t* end_pos,
std::string* content_text) {
- string16 utf16_input = string16(begin, end);
+ base::string16 utf16_input = base::string16(begin, end);
icu::UnicodeString pattern(kEmailRegex);
icu::UnicodeString input(utf16_input.data(), utf16_input.length());
UErrorCode status = U_ZERO_ERROR;
diff --git a/chromium/content/renderer/android/email_detector.h b/chromium/content/renderer/android/email_detector.h
index dbd6de3fb71..ff469e865cd 100644
--- a/chromium/content/renderer/android/email_detector.h
+++ b/chromium/content/renderer/android/email_detector.h
@@ -23,8 +23,8 @@ class CONTENT_EXPORT EmailDetector : public ContentDetector {
friend class EmailDetectorTest;
// Implementation of ContentDetector.
- virtual bool FindContent(const string16::const_iterator& begin,
- const string16::const_iterator& end,
+ virtual bool FindContent(const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end,
size_t* start_pos,
size_t* end_pos,
std::string* content_text) OVERRIDE;
diff --git a/chromium/content/renderer/android/email_detector_unittest.cc b/chromium/content/renderer/android/email_detector_unittest.cc
index f3ed10ff56b..45bcc9bf483 100644
--- a/chromium/content/renderer/android/email_detector_unittest.cc
+++ b/chromium/content/renderer/android/email_detector_unittest.cc
@@ -13,8 +13,8 @@ class EmailDetectorTest : public testing::Test {
public:
static void FindAndCheckEmail(const std::string& content,
const std::string& expected) {
- string16 content_16 = UTF8ToUTF16(content);
- string16 result_16;
+ base::string16 content_16 = UTF8ToUTF16(content);
+ base::string16 result_16;
size_t start, end;
EmailDetector detector;
std::string content_text;
diff --git a/chromium/content/renderer/android/phone_number_detector.cc b/chromium/content/renderer/android/phone_number_detector.cc
index 19c526f9bd0..843adfaad1d 100644
--- a/chromium/content/renderer/android/phone_number_detector.cc
+++ b/chromium/content/renderer/android/phone_number_detector.cc
@@ -54,12 +54,13 @@ GURL PhoneNumberDetector::GetIntentURL(const std::string& content_text) {
net::EscapeQueryParamValue(content_text, true));
}
-bool PhoneNumberDetector::FindContent(const string16::const_iterator& begin,
- const string16::const_iterator& end,
- size_t* start_pos,
- size_t* end_pos,
- std::string* content_text) {
- string16 utf16_input = string16(begin, end);
+bool PhoneNumberDetector::FindContent(
+ const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end,
+ size_t* start_pos,
+ size_t* end_pos,
+ std::string* content_text) {
+ base::string16 utf16_input = base::string16(begin, end);
std::string utf8_input = UTF16ToUTF8(utf16_input);
PhoneNumberMatcher matcher(utf8_input, region_code_);
diff --git a/chromium/content/renderer/android/phone_number_detector.h b/chromium/content/renderer/android/phone_number_detector.h
index 1ccf47d6158..081a427628e 100644
--- a/chromium/content/renderer/android/phone_number_detector.h
+++ b/chromium/content/renderer/android/phone_number_detector.h
@@ -24,8 +24,8 @@ class CONTENT_EXPORT PhoneNumberDetector : public ContentDetector {
friend class PhoneNumberDetectorTest;
// Implementation of ContentDetector.
- virtual bool FindContent(const string16::const_iterator& begin,
- const string16::const_iterator& end,
+ virtual bool FindContent(const base::string16::const_iterator& begin,
+ const base::string16::const_iterator& end,
size_t* start_pos,
size_t* end_pos,
std::string* content_text) OVERRIDE;
diff --git a/chromium/content/renderer/android/phone_number_detector_unittest.cc b/chromium/content/renderer/android/phone_number_detector_unittest.cc
index 387cedec1b4..e248f0e451f 100644
--- a/chromium/content/renderer/android/phone_number_detector_unittest.cc
+++ b/chromium/content/renderer/android/phone_number_detector_unittest.cc
@@ -13,8 +13,8 @@ class PhoneNumberDetectorTest : public testing::Test {
public:
static std::string FindNumber(const std::string& content,
const std::string& region) {
- string16 content_16 = UTF8ToUTF16(content);
- string16 result_16;
+ base::string16 content_16 = UTF8ToUTF16(content);
+ base::string16 result_16;
size_t start, end;
PhoneNumberDetector detector(region);
std::string content_text;
@@ -26,8 +26,8 @@ class PhoneNumberDetectorTest : public testing::Test {
static std::string FindAndFormatNumber(const std::string& content,
const std::string& region) {
- string16 content_16 = UTF8ToUTF16(content);
- string16 result_16;
+ base::string16 content_16 = UTF8ToUTF16(content);
+ base::string16 result_16;
size_t start, end;
PhoneNumberDetector detector(region);
std::string content_text;
diff --git a/chromium/content/renderer/bmp_image_decoder_unittest.cc b/chromium/content/renderer/bmp_image_decoder_unittest.cc
index 019eeb53c97..666196ad84b 100644
--- a/chromium/content/renderer/bmp_image_decoder_unittest.cc
+++ b/chromium/content/renderer/bmp_image_decoder_unittest.cc
@@ -10,8 +10,8 @@ class BMPImageDecoderTest : public ImageDecoderTest {
BMPImageDecoderTest() : ImageDecoderTest("bmp") { }
protected:
- virtual WebKit::WebImageDecoder* CreateWebKitImageDecoder() const OVERRIDE {
- return new WebKit::WebImageDecoder(WebKit::WebImageDecoder::TypeBMP);
+ virtual blink::WebImageDecoder* CreateWebKitImageDecoder() const OVERRIDE {
+ return new blink::WebImageDecoder(blink::WebImageDecoder::TypeBMP);
}
// The BMPImageDecoderTest tests are really slow under Valgrind.
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.cc b/chromium/content/renderer/browser_plugin/browser_plugin.cc
index 71aac853dbb..5f88fe142f9 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.cc
@@ -43,13 +43,13 @@
#include "base/sys_info.h"
#endif
-using WebKit::WebCanvas;
-using WebKit::WebPluginContainer;
-using WebKit::WebPluginParams;
-using WebKit::WebPoint;
-using WebKit::WebRect;
-using WebKit::WebURL;
-using WebKit::WebVector;
+using blink::WebCanvas;
+using blink::WebPluginContainer;
+using blink::WebPluginParams;
+using blink::WebPoint;
+using blink::WebRect;
+using blink::WebURL;
+using blink::WebVector;
namespace content {
@@ -59,17 +59,15 @@ static std::string GetInternalEventName(const char* event_name) {
return base::StringPrintf("-internal-%s", event_name);
}
-typedef std::map<WebKit::WebPluginContainer*,
+typedef std::map<blink::WebPluginContainer*,
BrowserPlugin*> PluginContainerMap;
static base::LazyInstance<PluginContainerMap> g_plugin_container_map =
LAZY_INSTANCE_INITIALIZER;
} // namespace
-BrowserPlugin::BrowserPlugin(
- RenderViewImpl* render_view,
- WebKit::WebFrame* frame,
- const WebPluginParams& params)
+BrowserPlugin::BrowserPlugin(RenderViewImpl* render_view,
+ blink::WebFrame* frame)
: guest_instance_id_(browser_plugin::kInstanceIDNone),
attached_(false),
render_view_(render_view->AsWeakPtr()),
@@ -90,6 +88,7 @@ BrowserPlugin::BrowserPlugin(
mouse_locked_(false),
browser_plugin_manager_(render_view->GetBrowserPluginManager()),
compositing_enabled_(false),
+ embedder_frame_url_(frame->document().url()),
weak_ptr_factory_(this) {
}
@@ -107,7 +106,7 @@ BrowserPlugin::~BrowserPlugin() {
/*static*/
BrowserPlugin* BrowserPlugin::FromContainer(
- WebKit::WebPluginContainer* container) {
+ blink::WebPluginContainer* container) {
PluginContainerMap* browser_plugins = g_plugin_container_map.Pointer();
PluginContainerMap::iterator it = browser_plugins->find(container);
return it == browser_plugins->end() ? NULL : it->second;
@@ -121,6 +120,8 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(BrowserPluginMsg_BuffersSwapped, OnBuffersSwapped)
IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginMsg_CompositorFrameSwapped,
OnCompositorFrameSwapped(message))
+ IPC_MESSAGE_HANDLER(BrowserPluginMsg_CopyFromCompositingSurface,
+ OnCopyFromCompositingSurface)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestContentWindowReady,
OnGuestContentWindowReady)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone)
@@ -140,14 +141,14 @@ void BrowserPlugin::UpdateDOMAttribute(const std::string& attribute_name,
if (!container())
return;
- WebKit::WebElement element = container()->element();
- WebKit::WebString web_attribute_name =
- WebKit::WebString::fromUTF8(attribute_name);
+ blink::WebElement element = container()->element();
+ blink::WebString web_attribute_name =
+ blink::WebString::fromUTF8(attribute_name);
if (!HasDOMAttribute(attribute_name) ||
(std::string(element.getAttribute(web_attribute_name).utf8()) !=
attribute_value)) {
element.setAttribute(web_attribute_name,
- WebKit::WebString::fromUTF8(attribute_value));
+ blink::WebString::fromUTF8(attribute_value));
}
}
@@ -156,7 +157,7 @@ void BrowserPlugin::RemoveDOMAttribute(const std::string& attribute_name) {
return;
container()->element().removeAttribute(
- WebKit::WebString::fromUTF8(attribute_name));
+ blink::WebString::fromUTF8(attribute_name));
}
std::string BrowserPlugin::GetDOMAttributeValue(
@@ -165,7 +166,7 @@ std::string BrowserPlugin::GetDOMAttributeValue(
return std::string();
return container()->element().getAttribute(
- WebKit::WebString::fromUTF8(attribute_name)).utf8();
+ blink::WebString::fromUTF8(attribute_name)).utf8();
}
bool BrowserPlugin::HasDOMAttribute(const std::string& attribute_name) const {
@@ -173,13 +174,17 @@ bool BrowserPlugin::HasDOMAttribute(const std::string& attribute_name) const {
return false;
return container()->element().hasAttribute(
- WebKit::WebString::fromUTF8(attribute_name));
+ blink::WebString::fromUTF8(attribute_name));
}
std::string BrowserPlugin::GetNameAttribute() const {
return GetDOMAttributeValue(browser_plugin::kAttributeName);
}
+bool BrowserPlugin::GetAllowTransparencyAttribute() const {
+ return HasDOMAttribute(browser_plugin::kAttributeAllowTransparency);
+}
+
std::string BrowserPlugin::GetSrcAttribute() const {
return GetDOMAttributeValue(browser_plugin::kAttributeSrc);
}
@@ -257,6 +262,21 @@ void BrowserPlugin::ParseNameAttribute() {
GetNameAttribute()));
}
+void BrowserPlugin::ParseAllowTransparencyAttribute() {
+ if (!HasGuestInstanceID())
+ return;
+
+ bool opaque = !GetAllowTransparencyAttribute();
+
+ if (compositing_helper_)
+ compositing_helper_->SetContentsOpaque(opaque);
+
+ browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetContentsOpaque(
+ render_view_routing_id_,
+ guest_instance_id_,
+ opaque));
+}
+
bool BrowserPlugin::ParseSrcAttribute(std::string* error_message) {
if (!valid_partition_id_) {
*error_message = browser_plugin::kErrorInvalidPartition;
@@ -370,10 +390,12 @@ void BrowserPlugin::Attach(scoped_ptr<base::DictionaryValue> extra_params) {
BrowserPluginHostMsg_Attach_Params attach_params;
attach_params.focused = ShouldGuestBeFocused();
attach_params.visible = visible_;
+ attach_params.opaque = !GetAllowTransparencyAttribute();
attach_params.name = GetNameAttribute();
attach_params.storage_partition_id = storage_partition_id_;
attach_params.persist_storage = persist_storage_;
attach_params.src = GetSrcAttribute();
+ attach_params.embedder_frame_url = embedder_frame_url_;
GetDamageBufferWithSizeParams(&attach_params.auto_size_params,
&attach_params.resize_guest_params,
false);
@@ -436,6 +458,23 @@ void BrowserPlugin::OnCompositorFrameSwapped(const IPC::Message& message) {
param.e /* host_id */);
}
+void BrowserPlugin::OnCopyFromCompositingSurface(int guest_instance_id,
+ int request_id,
+ gfx::Rect source_rect,
+ gfx::Size dest_size) {
+ if (!compositing_enabled_) {
+ browser_plugin_manager()->Send(
+ new BrowserPluginHostMsg_CopyFromCompositingSurfaceAck(
+ render_view_routing_id_,
+ guest_instance_id_,
+ request_id,
+ SkBitmap()));
+ return;
+ }
+ compositing_helper_->CopyFromCompositingSurface(request_id, source_rect,
+ dest_size);
+}
+
void BrowserPlugin::OnGuestContentWindowReady(int guest_instance_id,
int content_window_routing_id) {
DCHECK(content_window_routing_id != MSG_ROUTING_NONE);
@@ -445,6 +484,14 @@ void BrowserPlugin::OnGuestContentWindowReady(int guest_instance_id,
void BrowserPlugin::OnGuestGone(int guest_instance_id) {
guest_crashed_ = true;
+ // Turn off compositing so we can display the sad graphic. Changes to
+ // compositing state will show up at a later time after a layout and commit.
+ EnableCompositing(false);
+ if (compositing_helper_) {
+ compositing_helper_->OnContainerDestroy();
+ compositing_helper_ = NULL;
+ }
+
// Queue up showing the sad graphic to give content embedders an opportunity
// to fire their listeners and potentially overlay the webview with custom
// behavior. If the BrowserPlugin is destroyed in the meantime, then the
@@ -479,8 +526,8 @@ void BrowserPlugin::OnShouldAcceptTouchEvents(int guest_instance_id,
bool accept) {
if (container()) {
container()->requestTouchEventType(accept ?
- WebKit::WebPluginContainer::TouchEventRequestTypeRaw :
- WebKit::WebPluginContainer::TouchEventRequestTypeNone);
+ blink::WebPluginContainer::TouchEventRequestTypeRaw :
+ blink::WebPluginContainer::TouchEventRequestTypeNone);
}
}
@@ -634,29 +681,29 @@ NPObject* BrowserPlugin::GetContentWindow() const {
content_window_routing_id_);
if (!guest_render_view)
return NULL;
- WebKit::WebFrame* guest_frame = guest_render_view->GetWebView()->mainFrame();
+ blink::WebFrame* guest_frame = guest_render_view->GetWebView()->mainFrame();
return guest_frame->windowObject();
}
// static
-bool BrowserPlugin::AttachWindowTo(const WebKit::WebNode& node, int window_id) {
+bool BrowserPlugin::AttachWindowTo(const blink::WebNode& node, int window_id) {
if (node.isNull())
return false;
if (!node.isElementNode())
return false;
- WebKit::WebElement shim_element = node.toConst<WebKit::WebElement>();
+ blink::WebElement shim_element = node.toConst<blink::WebElement>();
// The shim containing the BrowserPlugin must be attached to a document.
if (shim_element.document().isNull())
return false;
- WebKit::WebNode shadow_root = shim_element.shadowRoot();
+ blink::WebNode shadow_root = shim_element.shadowRoot();
if (shadow_root.isNull() || !shadow_root.hasChildNodes())
return false;
- WebKit::WebNode plugin_element = shadow_root.firstChild();
- WebKit::WebPluginContainer* plugin_container =
+ blink::WebNode plugin_element = shadow_root.firstChild();
+ blink::WebPluginContainer* plugin_container =
plugin_element.pluginContainer();
if (!plugin_container)
return false;
@@ -743,8 +790,6 @@ void BrowserPlugin::ShowSadGraphic() {
// NULL so we shouldn't attempt to access it.
if (container_)
container_->invalidate();
- // Turn off compositing so we can display the sad graphic.
- EnableCompositing(false);
}
void BrowserPlugin::ParseAttributes() {
@@ -780,7 +825,7 @@ void BrowserPlugin::TriggerEvent(const std::string& event_name,
if (!container())
return;
- WebKit::WebFrame* frame = container()->element().document().frame();
+ blink::WebFrame* frame = container()->element().document().frame();
if (!frame)
return;
@@ -801,18 +846,22 @@ void BrowserPlugin::TriggerEvent(const std::string& event_name,
return;
}
- WebKit::WebDOMEvent dom_event = frame->document().createEvent("CustomEvent");
- WebKit::WebDOMCustomEvent event = dom_event.to<WebKit::WebDOMCustomEvent>();
+ blink::WebDOMEvent dom_event = frame->document().createEvent("CustomEvent");
+ blink::WebDOMCustomEvent event = dom_event.to<blink::WebDOMCustomEvent>();
// The events triggered directly from the plugin <object> are internal events
// whose implementation details can (and likely will) change over time. The
// wrapper/shim (e.g. <webview> tag) should receive these events, and expose a
// more appropriate (and stable) event to the consumers as part of the API.
event.initCustomEvent(
- WebKit::WebString::fromUTF8(GetInternalEventName(event_name.c_str())),
- false, false,
- WebKit::WebSerializedScriptValue::serialize(
- v8::String::New(json_string.c_str(), json_string.size())));
+ blink::WebString::fromUTF8(GetInternalEventName(event_name.c_str())),
+ false,
+ false,
+ blink::WebSerializedScriptValue::serialize(
+ v8::String::NewFromUtf8(context->GetIsolate(),
+ json_string.c_str(),
+ v8::String::kNormalString,
+ json_string.size())));
container()->element().dispatchEvent(event);
}
@@ -833,7 +882,7 @@ bool BrowserPlugin::ShouldGuestBeFocused() const {
return plugin_focused_ && embedder_focused;
}
-WebKit::WebPluginContainer* BrowserPlugin::container() const {
+blink::WebPluginContainer* BrowserPlugin::container() const {
return container_;
}
@@ -874,21 +923,24 @@ void BrowserPlugin::EnableCompositing(bool enable) {
render_view_routing_id_);
}
} else {
- // We're switching back to the software path. We create a new damage
- // buffer that can accommodate the current size of the container.
- BrowserPluginHostMsg_ResizeGuest_Params params;
- // Request a full repaint from the guest even if its size is not actually
- // changing.
- PopulateResizeGuestParameters(&params,
- plugin_rect(),
- true /* needs_repaint */);
- paint_ack_received_ = false;
- browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
- render_view_routing_id_,
- guest_instance_id_,
- params));
+ if (paint_ack_received_) {
+ // We're switching back to the software path. We create a new damage
+ // buffer that can accommodate the current size of the container.
+ BrowserPluginHostMsg_ResizeGuest_Params params;
+ // Request a full repaint from the guest even if its size is not actually
+ // changing.
+ PopulateResizeGuestParameters(&params,
+ plugin_rect(),
+ true /* needs_repaint */);
+ paint_ack_received_ = false;
+ browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
+ render_view_routing_id_,
+ guest_instance_id_,
+ params));
+ }
}
compositing_helper_->EnableCompositing(enable);
+ compositing_helper_->SetContentsOpaque(!GetAllowTransparencyAttribute());
}
void BrowserPlugin::destroy() {
@@ -916,7 +968,7 @@ NPObject* BrowserPlugin::scriptableObject() {
NPObject* browser_plugin_np_object(bindings_->np_object());
// The object is expected to be retained before it is returned.
- WebKit::WebBindings::retainObject(browser_plugin_np_object);
+ blink::WebBindings::retainObject(browser_plugin_np_object);
return browser_plugin_np_object;
}
@@ -932,6 +984,10 @@ bool BrowserPlugin::supportsEditCommands() const {
return true;
}
+bool BrowserPlugin::supportsInputMethod() const {
+ return true;
+}
+
bool BrowserPlugin::canProcessDrag() const {
return true;
}
@@ -988,7 +1044,7 @@ bool BrowserPlugin::InBounds(const gfx::Point& position) const {
gfx::Point BrowserPlugin::ToLocalCoordinates(const gfx::Point& point) const {
if (container_)
- return container_->windowToLocalPoint(WebKit::WebPoint(point));
+ return container_->windowToLocalPoint(blink::WebPoint(point));
return gfx::Point(point.x() - plugin_rect_.x(), point.y() - plugin_rect_.y());
}
@@ -1000,6 +1056,7 @@ bool BrowserPlugin::ShouldForwardToBrowserPlugin(
case BrowserPluginMsg_Attach_ACK::ID:
case BrowserPluginMsg_BuffersSwapped::ID:
case BrowserPluginMsg_CompositorFrameSwapped::ID:
+ case BrowserPluginMsg_CopyFromCompositingSurface::ID:
case BrowserPluginMsg_GuestContentWindowReady::ID:
case BrowserPluginMsg_GuestGone::ID:
case BrowserPluginMsg_SetCursor::ID:
@@ -1180,34 +1237,34 @@ bool BrowserPlugin::acceptsInputEvents() {
return true;
}
-bool BrowserPlugin::handleInputEvent(const WebKit::WebInputEvent& event,
- WebKit::WebCursorInfo& cursor_info) {
+bool BrowserPlugin::handleInputEvent(const blink::WebInputEvent& event,
+ blink::WebCursorInfo& cursor_info) {
if (guest_crashed_ || !HasGuestInstanceID())
return false;
- if (event.type == WebKit::WebInputEvent::ContextMenu)
+ if (event.type == blink::WebInputEvent::ContextMenu)
return true;
- const WebKit::WebInputEvent* modified_event = &event;
- scoped_ptr<WebKit::WebTouchEvent> touch_event;
+ const blink::WebInputEvent* modified_event = &event;
+ scoped_ptr<blink::WebTouchEvent> touch_event;
// WebKit gives BrowserPlugin a list of touches that are down, but the browser
// process expects a list of all touches. We modify the TouchEnd event here to
// match these expectations.
- if (event.type == WebKit::WebInputEvent::TouchEnd) {
- const WebKit::WebTouchEvent* orig_touch_event =
- static_cast<const WebKit::WebTouchEvent*>(&event);
- touch_event.reset(new WebKit::WebTouchEvent());
- memcpy(touch_event.get(), orig_touch_event, sizeof(WebKit::WebTouchEvent));
+ if (event.type == blink::WebInputEvent::TouchEnd) {
+ const blink::WebTouchEvent* orig_touch_event =
+ static_cast<const blink::WebTouchEvent*>(&event);
+ touch_event.reset(new blink::WebTouchEvent());
+ memcpy(touch_event.get(), orig_touch_event, sizeof(blink::WebTouchEvent));
if (touch_event->changedTouchesLength > 0) {
memcpy(&touch_event->touches[touch_event->touchesLength],
&touch_event->changedTouches,
- touch_event->changedTouchesLength * sizeof(WebKit::WebTouchPoint));
+ touch_event->changedTouchesLength * sizeof(blink::WebTouchPoint));
}
touch_event->touchesLength += touch_event->changedTouchesLength;
modified_event = touch_event.get();
}
- if (WebKit::WebInputEvent::isKeyboardEventType(event.type) &&
+ if (blink::WebInputEvent::isKeyboardEventType(event.type) &&
!edit_commands_.empty()) {
browser_plugin_manager()->Send(
new BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent(
@@ -1226,11 +1283,11 @@ bool BrowserPlugin::handleInputEvent(const WebKit::WebInputEvent& event,
return true;
}
-bool BrowserPlugin::handleDragStatusUpdate(WebKit::WebDragStatus drag_status,
- const WebKit::WebDragData& drag_data,
- WebKit::WebDragOperationsMask mask,
- const WebKit::WebPoint& position,
- const WebKit::WebPoint& screen) {
+bool BrowserPlugin::handleDragStatusUpdate(blink::WebDragStatus drag_status,
+ const blink::WebDragData& drag_data,
+ blink::WebDragOperationsMask mask,
+ const blink::WebPoint& position,
+ const blink::WebPoint& screen) {
if (guest_crashed_ || !HasGuestInstanceID())
return false;
browser_plugin_manager()->Send(
@@ -1245,7 +1302,7 @@ bool BrowserPlugin::handleDragStatusUpdate(WebKit::WebDragStatus drag_status,
}
void BrowserPlugin::didReceiveResponse(
- const WebKit::WebURLResponse& response) {
+ const blink::WebURLResponse& response) {
}
void BrowserPlugin::didReceiveData(const char* data, int data_length) {
@@ -1254,20 +1311,20 @@ void BrowserPlugin::didReceiveData(const char* data, int data_length) {
void BrowserPlugin::didFinishLoading() {
}
-void BrowserPlugin::didFailLoading(const WebKit::WebURLError& error) {
+void BrowserPlugin::didFailLoading(const blink::WebURLError& error) {
}
-void BrowserPlugin::didFinishLoadingFrameRequest(const WebKit::WebURL& url,
+void BrowserPlugin::didFinishLoadingFrameRequest(const blink::WebURL& url,
void* notify_data) {
}
void BrowserPlugin::didFailLoadingFrameRequest(
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
void* notify_data,
- const WebKit::WebURLError& error) {
+ const blink::WebURLError& error) {
}
-bool BrowserPlugin::executeEditCommand(const WebKit::WebString& name) {
+bool BrowserPlugin::executeEditCommand(const blink::WebString& name) {
browser_plugin_manager()->Send(new BrowserPluginHostMsg_ExecuteEditCommand(
render_view_routing_id_,
guest_instance_id_,
@@ -1277,13 +1334,61 @@ bool BrowserPlugin::executeEditCommand(const WebKit::WebString& name) {
return true;
}
-bool BrowserPlugin::executeEditCommand(const WebKit::WebString& name,
- const WebKit::WebString& value) {
+bool BrowserPlugin::executeEditCommand(const blink::WebString& name,
+ const blink::WebString& value) {
edit_commands_.push_back(EditCommand(name.utf8(), value.utf8()));
// BrowserPlugin swallows edit commands.
return true;
}
+bool BrowserPlugin::setComposition(
+ const blink::WebString& text,
+ const blink::WebVector<blink::WebCompositionUnderline>& underlines,
+ int selectionStart,
+ int selectionEnd) {
+ if (!HasGuestInstanceID())
+ return false;
+ std::vector<blink::WebCompositionUnderline> std_underlines;
+ for (size_t i = 0; i < underlines.size(); ++i) {
+ std_underlines.push_back(underlines[i]);
+ }
+ browser_plugin_manager()->Send(new BrowserPluginHostMsg_ImeSetComposition(
+ render_view_routing_id_,
+ guest_instance_id_,
+ text.utf8(),
+ std_underlines,
+ selectionStart,
+ selectionEnd));
+ // TODO(kochi): This assumes the IPC handling always succeeds.
+ return true;
+}
+
+bool BrowserPlugin::confirmComposition(
+ const blink::WebString& text,
+ blink::WebWidget::ConfirmCompositionBehavior selectionBehavior) {
+ if (!HasGuestInstanceID())
+ return false;
+ bool keep_selection = (selectionBehavior == blink::WebWidget::KeepSelection);
+ browser_plugin_manager()->Send(new BrowserPluginHostMsg_ImeConfirmComposition(
+ render_view_routing_id_,
+ guest_instance_id_,
+ text.utf8(),
+ keep_selection));
+ // TODO(kochi): This assumes the IPC handling always succeeds.
+ return true;
+}
+
+void BrowserPlugin::extendSelectionAndDelete(int before, int after) {
+ if (!HasGuestInstanceID())
+ return;
+ browser_plugin_manager()->Send(
+ new BrowserPluginHostMsg_ExtendSelectionAndDelete(
+ render_view_routing_id_,
+ guest_instance_id_,
+ before,
+ after));
+}
+
void BrowserPlugin::OnLockMouseACK(bool succeeded) {
mouse_locked_ = succeeded;
browser_plugin_manager()->Send(new BrowserPluginHostMsg_LockMouse_ACK(
@@ -1300,7 +1405,7 @@ void BrowserPlugin::OnMouseLockLost() {
}
bool BrowserPlugin::HandleMouseLockedInputEvent(
- const WebKit::WebMouseEvent& event) {
+ const blink::WebMouseEvent& event) {
browser_plugin_manager()->Send(
new BrowserPluginHostMsg_HandleInputEvent(render_view_routing_id_,
guest_instance_id_,
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.h b/chromium/content/renderer/browser_plugin/browser_plugin.h
index ba30ac909d8..d2b21aa7742 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.h
@@ -14,12 +14,13 @@
#include "base/memory/shared_memory.h"
#endif
#include "base/values.h"
-#include "content/public/common/browser_plugin_permission_type.h"
#include "content/renderer/browser_plugin/browser_plugin_backing_store.h"
#include "content/renderer/browser_plugin/browser_plugin_bindings.h"
#include "content/renderer/mouse_lock_dispatcher.h"
#include "content/renderer/render_view_impl.h"
+#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebDragStatus.h"
+#include "third_party/WebKit/public/web/WebWidget.h"
struct BrowserPluginHostMsg_AutoSize_Params;
struct BrowserPluginHostMsg_ResizeGuest_Params;
@@ -34,7 +35,7 @@ class BrowserPluginManager;
class MockBrowserPlugin;
class CONTENT_EXPORT BrowserPlugin :
- NON_EXPORTED_BASE(public WebKit::WebPlugin),
+ NON_EXPORTED_BASE(public blink::WebPlugin),
public MouseLockDispatcher::LockTarget {
public:
RenderViewImpl* render_view() const { return render_view_.get(); }
@@ -42,7 +43,7 @@ class CONTENT_EXPORT BrowserPlugin :
int guest_instance_id() const { return guest_instance_id_; }
bool attached() const { return attached_; }
- static BrowserPlugin* FromContainer(WebKit::WebPluginContainer* container);
+ static BrowserPlugin* FromContainer(blink::WebPluginContainer* container);
bool OnMessageReceived(const IPC::Message& msg);
@@ -61,6 +62,11 @@ class CONTENT_EXPORT BrowserPlugin :
std::string GetNameAttribute() const;
// Parse the name attribute value.
void ParseNameAttribute();
+ // Get the allowtransparency attribute value.
+ bool GetAllowTransparencyAttribute() const;
+ // Parse the allowtransparency attribute and adjust transparency of
+ // BrowserPlugin accordingly.
+ void ParseAllowTransparencyAttribute();
// Get the src attribute value of the BrowserPlugin instance.
std::string GetSrcAttribute() const;
// Parse the src attribute value of the BrowserPlugin instance.
@@ -102,7 +108,7 @@ class CONTENT_EXPORT BrowserPlugin :
// Attaches the window identified by |window_id| to the the given node
// encapsulating a BrowserPlugin.
- static bool AttachWindowTo(const WebKit::WebNode& node,
+ static bool AttachWindowTo(const blink::WebNode& node,
int window_id);
// Informs the guest of an updated focus state.
@@ -139,55 +145,65 @@ class CONTENT_EXPORT BrowserPlugin :
// Returns whether a message should be forwarded to BrowserPlugin.
static bool ShouldForwardToBrowserPlugin(const IPC::Message& message);
- // WebKit::WebPlugin implementation.
- virtual WebKit::WebPluginContainer* container() const OVERRIDE;
- virtual bool initialize(WebKit::WebPluginContainer* container) OVERRIDE;
+ // blink::WebPlugin implementation.
+ virtual blink::WebPluginContainer* container() const OVERRIDE;
+ virtual bool initialize(blink::WebPluginContainer* container) OVERRIDE;
virtual void destroy() OVERRIDE;
virtual NPObject* scriptableObject() OVERRIDE;
virtual struct _NPP* pluginNPP() OVERRIDE;
virtual bool supportsKeyboardFocus() const OVERRIDE;
virtual bool supportsEditCommands() const OVERRIDE;
+ virtual bool supportsInputMethod() const OVERRIDE;
virtual bool canProcessDrag() const OVERRIDE;
virtual void paint(
- WebKit::WebCanvas* canvas,
- const WebKit::WebRect& rect) OVERRIDE;
+ blink::WebCanvas* canvas,
+ const blink::WebRect& rect) OVERRIDE;
virtual void updateGeometry(
- const WebKit::WebRect& frame_rect,
- const WebKit::WebRect& clip_rect,
- const WebKit::WebVector<WebKit::WebRect>& cut_outs_rects,
+ const blink::WebRect& frame_rect,
+ const blink::WebRect& clip_rect,
+ const blink::WebVector<blink::WebRect>& cut_outs_rects,
bool is_visible) OVERRIDE;
virtual void updateFocus(bool focused) OVERRIDE;
virtual void updateVisibility(bool visible) OVERRIDE;
virtual bool acceptsInputEvents() OVERRIDE;
virtual bool handleInputEvent(
- const WebKit::WebInputEvent& event,
- WebKit::WebCursorInfo& cursor_info) OVERRIDE;
- virtual bool handleDragStatusUpdate(WebKit::WebDragStatus drag_status,
- const WebKit::WebDragData& drag_data,
- WebKit::WebDragOperationsMask mask,
- const WebKit::WebPoint& position,
- const WebKit::WebPoint& screen) OVERRIDE;
+ const blink::WebInputEvent& event,
+ blink::WebCursorInfo& cursor_info) OVERRIDE;
+ virtual bool handleDragStatusUpdate(blink::WebDragStatus drag_status,
+ const blink::WebDragData& drag_data,
+ blink::WebDragOperationsMask mask,
+ const blink::WebPoint& position,
+ const blink::WebPoint& screen) OVERRIDE;
virtual void didReceiveResponse(
- const WebKit::WebURLResponse& response) OVERRIDE;
+ const blink::WebURLResponse& response) OVERRIDE;
virtual void didReceiveData(const char* data, int data_length) OVERRIDE;
virtual void didFinishLoading() OVERRIDE;
- virtual void didFailLoading(const WebKit::WebURLError& error) OVERRIDE;
+ virtual void didFailLoading(const blink::WebURLError& error) OVERRIDE;
virtual void didFinishLoadingFrameRequest(
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
void* notify_data) OVERRIDE;
virtual void didFailLoadingFrameRequest(
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
void* notify_data,
- const WebKit::WebURLError& error) OVERRIDE;
- virtual bool executeEditCommand(const WebKit::WebString& name) OVERRIDE;
- virtual bool executeEditCommand(const WebKit::WebString& name,
- const WebKit::WebString& value) OVERRIDE;
+ const blink::WebURLError& error) OVERRIDE;
+ virtual bool executeEditCommand(const blink::WebString& name) OVERRIDE;
+ virtual bool executeEditCommand(const blink::WebString& name,
+ const blink::WebString& value) OVERRIDE;
+ virtual bool setComposition(
+ const blink::WebString& text,
+ const blink::WebVector<blink::WebCompositionUnderline>& underlines,
+ int selectionStart,
+ int selectionEnd) OVERRIDE;
+ virtual bool confirmComposition(
+ const blink::WebString& text,
+ blink::WebWidget::ConfirmCompositionBehavior selectionBehavior) OVERRIDE;
+ virtual void extendSelectionAndDelete(int before, int after) OVERRIDE;
// MouseLockDispatcher::LockTarget implementation.
virtual void OnLockMouseACK(bool succeeded) OVERRIDE;
virtual void OnMouseLockLost() OVERRIDE;
virtual bool HandleMouseLockedInputEvent(
- const WebKit::WebMouseEvent& event) OVERRIDE;
+ const blink::WebMouseEvent& event) OVERRIDE;
private:
friend class base::DeleteHelper<BrowserPlugin>;
@@ -199,16 +215,11 @@ class CONTENT_EXPORT BrowserPlugin :
friend class MockBrowserPlugin;
// A BrowserPlugin object is a controller that represents an instance of a
- // browser plugin within the embedder renderer process. Each BrowserPlugin
- // within a RenderView has a unique instance_id that is used to track per-
- // BrowserPlugin state in the browser process. Once a BrowserPlugin does
- // an initial navigation or is attached to a newly created guest, it acquires
- // a guest_instance_id as well. The guest instance ID uniquely identifies a
- // guest WebContents that's hosted by this BrowserPlugin.
- BrowserPlugin(
- RenderViewImpl* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params);
+ // browser plugin within the embedder renderer process. Once a BrowserPlugin
+ // does an initial navigation or is attached to a newly created guest, it
+ // acquires a guest_instance_id as well. The guest instance ID uniquely
+ // identifies a guest WebContents that's hosted by this BrowserPlugin.
+ BrowserPlugin(RenderViewImpl* render_view, blink::WebFrame* frame);
virtual ~BrowserPlugin();
@@ -287,6 +298,10 @@ class CONTENT_EXPORT BrowserPlugin :
void OnBuffersSwapped(int instance_id,
const BrowserPluginMsg_BuffersSwapped_Params& params);
void OnCompositorFrameSwapped(const IPC::Message& message);
+ void OnCopyFromCompositingSurface(int instance_id,
+ int request_id,
+ gfx::Rect source_rect,
+ gfx::Size dest_size);
void OnGuestContentWindowReady(int instance_id,
int content_window_routing_id);
void OnGuestGone(int instance_id);
@@ -308,7 +323,7 @@ class CONTENT_EXPORT BrowserPlugin :
// If the |render_view_| is destroyed before the BrowserPlugin is destroyed
// then we will attempt to access a NULL pointer.
int render_view_routing_id_;
- WebKit::WebPluginContainer* container_;
+ blink::WebPluginContainer* container_;
scoped_ptr<BrowserPluginBindings> bindings_;
scoped_ptr<BrowserPluginBackingStore> backing_store_;
scoped_ptr<base::SharedMemory> current_damage_buffer_;
@@ -339,9 +354,6 @@ class CONTENT_EXPORT BrowserPlugin :
bool before_first_navigation_;
bool mouse_locked_;
- typedef std::pair<int, base::WeakPtr<BrowserPlugin> > TrackedV8ObjectID;
- std::map<int, TrackedV8ObjectID*> tracked_v8_objects_;
-
// BrowserPlugin outlives RenderViewImpl in Chrome Apps and so we need to
// store the BrowserPlugin's BrowserPluginManager in a member variable to
// avoid accessing the RenderViewImpl.
@@ -354,6 +366,9 @@ class CONTENT_EXPORT BrowserPlugin :
// Used to identify the plugin to WebBindings.
scoped_ptr<struct _NPP> npp_;
+ // URL for the embedder frame.
+ GURL embedder_frame_url_;
+
// Weak factory used in v8 |MakeWeak| callback, since the v8 callback might
// get called after BrowserPlugin has been destroyed.
base::WeakPtrFactory<BrowserPlugin> weak_ptr_factory_;
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc b/chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc
index 5dd5231703c..2e0ab773315 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc
@@ -28,12 +28,12 @@
#include "third_party/npapi/bindings/npapi.h"
#include "v8/include/v8.h"
-using WebKit::WebBindings;
-using WebKit::WebElement;
-using WebKit::WebDOMEvent;
-using WebKit::WebDOMMessageEvent;
-using WebKit::WebPluginContainer;
-using WebKit::WebString;
+using blink::WebBindings;
+using blink::WebElement;
+using blink::WebDOMEvent;
+using blink::WebDOMMessageEvent;
+using blink::WebPluginContainer;
+using blink::WebString;
namespace content {
@@ -242,7 +242,7 @@ class BrowserPluginBindingAttach: public BrowserPluginMethodBinding {
return false;
scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
- v8::Handle<v8::Value> obj(WebKit::WebBindings::toV8Value(&args[0]));
+ v8::Handle<v8::Value> obj(blink::WebBindings::toV8Value(&args[0]));
scoped_ptr<base::Value> value(
converter->FromV8Value(obj, bindings->instance()->render_view()->
GetWebView()->mainFrame()->mainWorldScriptContext()));
@@ -272,7 +272,7 @@ class BrowserPluginBindingAttachWindowTo : public BrowserPluginMethodBinding {
virtual bool Invoke(BrowserPluginBindings* bindings,
const NPVariant* args,
NPVariant* result) OVERRIDE {
- WebKit::WebNode node;
+ blink::WebNode node;
WebBindings::getNode(NPVARIANT_TO_OBJECT(args[0]), &node);
int window_id = IntFromNPVariant(args[1]);
BOOLEAN_TO_NPVARIANT(BrowserPlugin::AttachWindowTo(node, window_id),
@@ -312,6 +312,41 @@ class BrowserPluginPropertyBinding {
DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBinding);
};
+class BrowserPluginPropertyBindingAllowTransparency
+ : public BrowserPluginPropertyBinding {
+ public:
+ BrowserPluginPropertyBindingAllowTransparency()
+ : BrowserPluginPropertyBinding(
+ browser_plugin::kAttributeAllowTransparency) {
+ }
+ virtual bool GetProperty(BrowserPluginBindings* bindings,
+ NPVariant* result) OVERRIDE {
+ bool allow_transparency =
+ bindings->instance()->GetAllowTransparencyAttribute();
+ BOOLEAN_TO_NPVARIANT(allow_transparency, *result);
+ return true;
+ }
+ virtual bool SetProperty(BrowserPluginBindings* bindings,
+ NPObject* np_obj,
+ const NPVariant* variant) OVERRIDE {
+ std::string value = StringFromNPVariant(*variant);
+ if (!bindings->instance()->HasDOMAttribute(name())) {
+ UpdateDOMAttribute(bindings, value);
+ bindings->instance()->ParseAllowTransparencyAttribute();
+ } else {
+ UpdateDOMAttribute(bindings, value);
+ }
+ return true;
+ }
+ virtual void RemoveProperty(BrowserPluginBindings* bindings,
+ NPObject* np_obj) OVERRIDE {
+ bindings->instance()->RemoveDOMAttribute(name());
+ bindings->instance()->ParseAllowTransparencyAttribute();
+ }
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAllowTransparency);
+};
+
class BrowserPluginPropertyBindingAutoSize
: public BrowserPluginPropertyBinding {
public:
@@ -638,6 +673,8 @@ BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance)
method_bindings_.push_back(new BrowserPluginBindingAttach);
method_bindings_.push_back(new BrowserPluginBindingAttachWindowTo);
+ property_bindings_.push_back(
+ new BrowserPluginPropertyBindingAllowTransparency);
property_bindings_.push_back(new BrowserPluginPropertyBindingAutoSize);
property_bindings_.push_back(new BrowserPluginPropertyBindingContentWindow);
property_bindings_.push_back(new BrowserPluginPropertyBindingMaxHeight);
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc b/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc
index d12b45bdfc2..36ee92cf0fa 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc
@@ -16,14 +16,15 @@
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_webkitplatformsupport_impl.h"
#include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/public/web/WebCursorInfo.h"
+#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
namespace {
const char kHTMLForBrowserPluginObject[] =
"<object id='browserplugin' width='640px' height='480px'"
- " src='foo' type='%s'>";
+ " src='foo' type='%s'></object>"
+ "<script>document.querySelector('object').nonExistentAttribute;</script>";
const char kHTMLForBrowserPluginWithAllAttributes[] =
"<object id='browserplugin' width='640' height='480' type='%s'"
@@ -61,7 +62,7 @@ class TestContentRendererClient : public ContentRendererClient {
virtual ~TestContentRendererClient() {
}
virtual bool AllowBrowserPlugin(
- WebKit::WebPluginContainer* container) OVERRIDE {
+ blink::WebPluginContainer* container) OVERRIDE {
// Allow BrowserPlugin for tests.
return true;
}
@@ -114,7 +115,7 @@ std::string BrowserPluginTest::ExecuteScriptAndReturnString(
const std::string& script) {
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue(
- WebKit::WebScriptSource(WebKit::WebString::fromUTF8(script.c_str())));
+ blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str())));
if (value.IsEmpty() || !value->IsString())
return std::string();
@@ -129,7 +130,7 @@ int BrowserPluginTest::ExecuteScriptAndReturnInt(
const std::string& script) {
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue(
- WebKit::WebScriptSource(WebKit::WebString::fromUTF8(script.c_str())));
+ blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str())));
if (value.IsEmpty() || !value->IsInt32())
return 0;
@@ -142,7 +143,7 @@ bool BrowserPluginTest::ExecuteScriptAndReturnBool(
const std::string& script, bool* result) {
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue(
- WebKit::WebScriptSource(WebKit::WebString::fromUTF8(script.c_str())));
+ blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str())));
if (value.IsEmpty() || !value->IsBoolean())
return false;
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc b/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc
index c7e1ae88432..a3ce8444df1 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc
@@ -4,19 +4,25 @@
#include "content/renderer/browser_plugin/browser_plugin_compositing_helper.h"
+#include "cc/layers/delegated_frame_provider.h"
+#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/layers/delegated_renderer_layer.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/layers/texture_layer.h"
#include "cc/output/context_provider.h"
+#include "cc/output/copy_output_request.h"
+#include "cc/output/copy_output_result.h"
#include "cc/resources/single_release_callback.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
#include "content/renderer/render_thread_impl.h"
+#include "skia/ext/image_operations.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/skia_util.h"
#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
namespace content {
@@ -30,7 +36,7 @@ BrowserPluginCompositingHelper::SwapBuffersInfo::SwapBuffersInfo()
}
BrowserPluginCompositingHelper::BrowserPluginCompositingHelper(
- WebKit::WebPluginContainer* container,
+ blink::WebPluginContainer* container,
BrowserPluginManager* manager,
int instance_id,
int host_routing_id)
@@ -41,6 +47,8 @@ BrowserPluginCompositingHelper::BrowserPluginCompositingHelper(
last_host_id_(0),
last_mailbox_valid_(false),
ack_pending_(true),
+ software_ack_pending_(false),
+ opaque_(true),
container_(container),
browser_plugin_manager_(manager) {
}
@@ -48,12 +56,45 @@ BrowserPluginCompositingHelper::BrowserPluginCompositingHelper(
BrowserPluginCompositingHelper::~BrowserPluginCompositingHelper() {
}
+void BrowserPluginCompositingHelper::CopyFromCompositingSurface(
+ int request_id,
+ gfx::Rect source_rect,
+ gfx::Size dest_size) {
+ CHECK(background_layer_);
+ scoped_ptr<cc::CopyOutputRequest> request =
+ cc::CopyOutputRequest::CreateBitmapRequest(base::Bind(
+ &BrowserPluginCompositingHelper::CopyFromCompositingSurfaceHasResult,
+ this,
+ request_id,
+ dest_size));
+ request->set_area(source_rect);
+ background_layer_->RequestCopyOfOutput(request.Pass());
+}
+
void BrowserPluginCompositingHelper::DidCommitCompositorFrame() {
- if (!delegated_layer_.get() || !ack_pending_)
+ if (software_ack_pending_) {
+ cc::CompositorFrameAck ack;
+ if (!unacked_software_frames_.empty()) {
+ ack.last_software_frame_id = unacked_software_frames_.back();
+ unacked_software_frames_.pop_back();
+ }
+
+ browser_plugin_manager_->Send(
+ new BrowserPluginHostMsg_CompositorFrameACK(
+ host_routing_id_,
+ instance_id_,
+ last_route_id_,
+ last_output_surface_id_,
+ last_host_id_,
+ ack));
+
+ software_ack_pending_ = false;
+ }
+ if (!resource_collection_.get() || !ack_pending_)
return;
cc::CompositorFrameAck ack;
- delegated_layer_->TakeUnusedResourcesForChildCompositor(&ack.resources);
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
browser_plugin_manager_->Send(
new BrowserPluginHostMsg_CompositorFrameACK(
@@ -79,7 +120,7 @@ void BrowserPluginCompositingHelper::EnableCompositing(bool enable) {
container_->setWebLayer(enable ? web_layer_.get() : NULL);
}
-void BrowserPluginCompositingHelper::CheckSizeAndAdjustLayerBounds(
+void BrowserPluginCompositingHelper::CheckSizeAndAdjustLayerProperties(
const gfx::Size& new_size,
float device_scale_factor,
cc::Layer* layer) {
@@ -92,6 +133,10 @@ void BrowserPluginCompositingHelper::CheckSizeAndAdjustLayerBounds(
gfx::ScaleSize(buffer_size_, 1.0f / device_scale_factor));
layer->SetBounds(device_scale_adjusted_size);
}
+
+ // Manually manage background layer for transparent webview.
+ if (!opaque_)
+ background_layer_->SetIsDrawable(false);
}
void BrowserPluginCompositingHelper::MailboxReleased(
@@ -112,6 +157,9 @@ void BrowserPluginCompositingHelper::MailboxReleased(
last_route_id_ != mailbox.route_id)
return;
+ if (mailbox.type == SOFTWARE_COMPOSITOR_FRAME)
+ unacked_software_frames_.push_back(mailbox.software_frame_id);
+
// We need to send an ACK to for every buffer sent to us.
// However, if a buffer is freed up from
// the compositor in cases like switching back to SW mode without a new
@@ -152,20 +200,8 @@ void BrowserPluginCompositingHelper::MailboxReleased(
ack));
break;
}
- case SOFTWARE_COMPOSITOR_FRAME: {
- cc::CompositorFrameAck ack;
- ack.last_software_frame_id = mailbox.software_frame_id;
-
- browser_plugin_manager_->Send(
- new BrowserPluginHostMsg_CompositorFrameACK(
- host_routing_id_,
- instance_id_,
- mailbox.route_id,
- mailbox.output_surface_id,
- mailbox.host_id,
- ack));
+ case SOFTWARE_COMPOSITOR_FRAME:
break;
- }
}
}
@@ -174,6 +210,13 @@ void BrowserPluginCompositingHelper::OnContainerDestroy() {
container_->setWebLayer(NULL);
container_ = NULL;
+ if (resource_collection_)
+ resource_collection_->SetClient(NULL);
+
+ ack_pending_ = false;
+ software_ack_pending_ = false;
+ resource_collection_ = NULL;
+ frame_provider_ = NULL;
texture_layer_ = NULL;
delegated_layer_ = NULL;
background_layer_ = NULL;
@@ -208,7 +251,7 @@ void BrowserPluginCompositingHelper::OnBuffersSwappedPrivate(
if (!texture_layer_.get()) {
texture_layer_ = cc::TextureLayer::CreateForMailbox(NULL);
texture_layer_->SetIsDrawable(true);
- texture_layer_->SetContentsOpaque(true);
+ SetContentsOpaque(opaque_);
background_layer_->AddChild(texture_layer_);
}
@@ -223,9 +266,9 @@ void BrowserPluginCompositingHelper::OnBuffersSwappedPrivate(
// when a new buffer arrives.
// Visually, this will either display a smaller part of the buffer
// or introduce a gutter around it.
- CheckSizeAndAdjustLayerBounds(mailbox.size,
- device_scale_factor,
- texture_layer_.get());
+ CheckSizeAndAdjustLayerProperties(mailbox.size,
+ device_scale_factor,
+ texture_layer_.get());
bool is_software_frame = mailbox.type == SOFTWARE_COMPOSITOR_FRAME;
bool current_mailbox_valid = is_software_frame ?
@@ -310,39 +353,80 @@ void BrowserPluginCompositingHelper::OnCompositorFrameSwapped(
LOG(ERROR) << "Failed to map shared memory of size "
<< size_in_bytes;
// Send ACK right away.
- ack_pending_ = true;
+ software_ack_pending_ = true;
MailboxReleased(swap_info, 0, false);
+ DidCommitCompositorFrame();
return;
}
swap_info.shared_memory = shared_memory.release();
OnBuffersSwappedPrivate(swap_info, 0,
frame->metadata.device_scale_factor);
+ software_ack_pending_ = true;
+ last_route_id_ = route_id;
+ last_output_surface_id_ = output_surface_id;
+ last_host_id_ = host_id;
return;
}
DCHECK(!texture_layer_.get());
- if (!delegated_layer_.get()) {
- delegated_layer_ = cc::DelegatedRendererLayer::Create(NULL);
- delegated_layer_->SetIsDrawable(true);
- delegated_layer_->SetContentsOpaque(true);
+ cc::DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
+ // Do nothing if we are getting destroyed or have no frame data.
+ if (!frame_data || !background_layer_)
+ return;
+
+ DCHECK(!frame_data->render_pass_list.empty());
+ cc::RenderPass* root_pass = frame_data->render_pass_list.back();
+ gfx::Size frame_size = root_pass->output_rect.size();
+
+ if (last_route_id_ != route_id ||
+ last_output_surface_id_ != output_surface_id ||
+ last_host_id_ != host_id) {
+ // Resource ids are scoped by the output surface.
+ // If the originating output surface doesn't match the last one, it
+ // indicates the guest's output surface may have been recreated, in which
+ // case we should recreate the DelegatedRendererLayer, to avoid matching
+ // resources from the old one with resources from the new one which would
+ // have the same id.
+ frame_provider_ = NULL;
+
+ // Drop the cc::DelegatedFrameResourceCollection so that we will not return
+ // any resources from the old output surface with the new output surface id.
+ if (resource_collection_) {
+ resource_collection_->SetClient(NULL);
+
+ if (resource_collection_->LoseAllResources())
+ SendReturnedDelegatedResources();
+ resource_collection_ = NULL;
+ }
+ last_output_surface_id_ = output_surface_id;
+ last_route_id_ = route_id;
+ last_host_id_ = host_id;
+ }
+ if (!resource_collection_) {
+ resource_collection_ = new cc::DelegatedFrameResourceCollection;
+ resource_collection_->SetClient(this);
+ }
+ if (!frame_provider_.get() || frame_provider_->frame_size() != frame_size) {
+ frame_provider_ = new cc::DelegatedFrameProvider(
+ resource_collection_.get(), frame->delegated_frame_data.Pass());
+ if (delegated_layer_.get())
+ delegated_layer_->RemoveFromParent();
+ delegated_layer_ =
+ cc::DelegatedRendererLayer::Create(frame_provider_.get());
+ delegated_layer_->SetIsDrawable(true);
+ SetContentsOpaque(opaque_);
background_layer_->AddChild(delegated_layer_);
+ } else {
+ frame_provider_->SetFrameData(frame->delegated_frame_data.Pass());
}
- cc::DelegatedFrameData *frame_data = frame->delegated_frame_data.get();
- if (!frame_data)
- return;
-
- CheckSizeAndAdjustLayerBounds(
+ CheckSizeAndAdjustLayerProperties(
frame_data->render_pass_list.back()->output_rect.size(),
frame->metadata.device_scale_factor,
delegated_layer_.get());
- delegated_layer_->SetFrameData(frame->delegated_frame_data.Pass());
- last_route_id_ = route_id;
- last_output_surface_id_ = output_surface_id;
- last_host_id_ = host_id;
ack_pending_ = true;
}
@@ -353,4 +437,57 @@ void BrowserPluginCompositingHelper::UpdateVisibility(bool visible) {
delegated_layer_->SetIsDrawable(visible);
}
+void BrowserPluginCompositingHelper::UnusedResourcesAreAvailable() {
+ if (ack_pending_)
+ return;
+
+ SendReturnedDelegatedResources();
+}
+
+void BrowserPluginCompositingHelper::SendReturnedDelegatedResources() {
+ cc::CompositorFrameAck ack;
+ if (resource_collection_)
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
+ DCHECK(!ack.resources.empty());
+
+ browser_plugin_manager_->Send(
+ new BrowserPluginHostMsg_ReclaimCompositorResources(
+ host_routing_id_,
+ instance_id_,
+ last_route_id_,
+ last_output_surface_id_,
+ last_host_id_,
+ ack));
+}
+
+void BrowserPluginCompositingHelper::SetContentsOpaque(bool opaque) {
+ opaque_ = opaque;
+
+ if (texture_layer_.get())
+ texture_layer_->SetContentsOpaque(opaque_);
+ if (delegated_layer_.get())
+ delegated_layer_->SetContentsOpaque(opaque_);
+}
+
+void BrowserPluginCompositingHelper::CopyFromCompositingSurfaceHasResult(
+ int request_id,
+ gfx::Size dest_size,
+ scoped_ptr<cc::CopyOutputResult> result) {
+ scoped_ptr<SkBitmap> bitmap;
+ if (result && result->HasBitmap() && !result->size().IsEmpty())
+ bitmap = result->TakeBitmap();
+
+ SkBitmap resized_bitmap;
+ if (bitmap) {
+ resized_bitmap = skia::ImageOperations::Resize(*bitmap,
+ skia::ImageOperations::RESIZE_BEST,
+ dest_size.width(),
+ dest_size.height());
+ }
+ browser_plugin_manager_->Send(
+ new BrowserPluginHostMsg_CopyFromCompositingSurfaceAck(
+ host_routing_id_, instance_id_, request_id,
+ resized_bitmap));
+}
+
} // namespace content
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.h b/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.h
index 268a9b46259..7f9a473a619 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.h
@@ -6,9 +6,11 @@
#define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_COMPOSITING_HELPER_H_
#include <string>
+#include <vector>
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "cc/layers/delegated_frame_resource_collection.h"
#include "content/common/content_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "ui/gfx/size.h"
@@ -19,28 +21,40 @@ class SharedMemory;
namespace cc {
class CompositorFrame;
+class CopyOutputResult;
class Layer;
class SolidColorLayer;
class TextureLayer;
+class DelegatedFrameProvider;
+class DelegatedFrameResourceCollection;
class DelegatedRendererLayer;
}
-namespace WebKit {
+namespace blink {
class WebPluginContainer;
class WebLayer;
}
+namespace gfx {
+class Rect;
+class Size;
+}
+
namespace content {
class BrowserPluginManager;
class CONTENT_EXPORT BrowserPluginCompositingHelper :
- public base::RefCounted<BrowserPluginCompositingHelper> {
+ public base::RefCounted<BrowserPluginCompositingHelper>,
+ public cc::DelegatedFrameResourceCollectionClient {
public:
- BrowserPluginCompositingHelper(WebKit::WebPluginContainer* container,
+ BrowserPluginCompositingHelper(blink::WebPluginContainer* container,
BrowserPluginManager* manager,
int instance_id,
int host_routing_id);
+ void CopyFromCompositingSurface(int request_id,
+ gfx::Rect source_rect,
+ gfx::Size dest_size);
void DidCommitCompositorFrame();
void EnableCompositing(bool);
void OnContainerDestroy();
@@ -54,6 +68,11 @@ class CONTENT_EXPORT BrowserPluginCompositingHelper :
uint32 output_surface_id,
int host_id);
void UpdateVisibility(bool);
+
+ // cc::DelegatedFrameProviderClient implementation.
+ virtual void UnusedResourcesAreAvailable() OVERRIDE;
+ void SetContentsOpaque(bool);
+
protected:
// Friend RefCounted so that the dtor can be non-public.
friend class base::RefCounted<BrowserPluginCompositingHelper>;
@@ -75,16 +94,22 @@ class CONTENT_EXPORT BrowserPluginCompositingHelper :
unsigned software_frame_id;
base::SharedMemory* shared_memory;
};
- ~BrowserPluginCompositingHelper();
- void CheckSizeAndAdjustLayerBounds(const gfx::Size& new_size,
- float device_scale_factor,
- cc::Layer* layer);
+ virtual ~BrowserPluginCompositingHelper();
+ void CheckSizeAndAdjustLayerProperties(const gfx::Size& new_size,
+ float device_scale_factor,
+ cc::Layer* layer);
void OnBuffersSwappedPrivate(const SwapBuffersInfo& mailbox,
unsigned sync_point,
float device_scale_factor);
void MailboxReleased(SwapBuffersInfo mailbox,
unsigned sync_point,
bool lost_resource);
+ void SendReturnedDelegatedResources();
+ void CopyFromCompositingSurfaceHasResult(
+ int request_id,
+ gfx::Size dest_size,
+ scoped_ptr<cc::CopyOutputResult> result);
+
int instance_id_;
int host_routing_id_;
int last_route_id_;
@@ -92,14 +117,20 @@ class CONTENT_EXPORT BrowserPluginCompositingHelper :
int last_host_id_;
bool last_mailbox_valid_;
bool ack_pending_;
+ bool software_ack_pending_;
+ bool opaque_;
+ std::vector<unsigned> unacked_software_frames_;
gfx::Size buffer_size_;
+ scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection_;
+ scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
+
scoped_refptr<cc::SolidColorLayer> background_layer_;
scoped_refptr<cc::TextureLayer> texture_layer_;
scoped_refptr<cc::DelegatedRendererLayer> delegated_layer_;
- scoped_ptr<WebKit::WebLayer> web_layer_;
- WebKit::WebPluginContainer* container_;
+ scoped_ptr<blink::WebLayer> web_layer_;
+ blink::WebPluginContainer* container_;
scoped_refptr<BrowserPluginManager> browser_plugin_manager_;
};
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager.h b/chromium/content/renderer/browser_plugin/browser_plugin_manager.h
index 7e08a1ef4a9..8a57c3d5407 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin_manager.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin_manager.h
@@ -12,7 +12,7 @@
#include "content/public/renderer/render_view_observer.h"
#include "ipc/ipc_sender.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
struct WebPluginParams;
}
@@ -45,9 +45,7 @@ class CONTENT_EXPORT BrowserPluginManager
// BrowserPluginManager via AddBrowserPlugin. When it is destroyed, it is
// responsible for removing its association via RemoveBrowserPlugin.
virtual BrowserPlugin* CreateBrowserPlugin(
- RenderViewImpl* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params) = 0;
+ RenderViewImpl* render_view, blink::WebFrame* frame) = 0;
// Asynchronously requests a new browser-process-allocated instance ID.
// After the browser process allocates an ID, it calls back into the
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc b/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc
index e7732f8afe9..542af453d35 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc
@@ -24,9 +24,8 @@ BrowserPluginManagerImpl::~BrowserPluginManagerImpl() {
BrowserPlugin* BrowserPluginManagerImpl::CreateBrowserPlugin(
RenderViewImpl* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params) {
- return new BrowserPlugin(render_view, frame, params);
+ blink::WebFrame* frame) {
+ return new BrowserPlugin(render_view, frame);
}
void BrowserPluginManagerImpl::AllocateInstanceID(
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h b/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h
index 30ee72cfc98..a046995af63 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h
@@ -23,8 +23,7 @@ class BrowserPluginManagerImpl : public BrowserPluginManager {
// BrowserPluginManager implementation.
virtual BrowserPlugin* CreateBrowserPlugin(
RenderViewImpl* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params) OVERRIDE;
+ blink::WebFrame* frame) OVERRIDE;
virtual void AllocateInstanceID(
const base::WeakPtr<BrowserPlugin>& browser_plugin) OVERRIDE;
diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin.cc b/chromium/content/renderer/browser_plugin/mock_browser_plugin.cc
index 39b2d2dc047..a19d0aa516e 100644
--- a/chromium/content/renderer/browser_plugin/mock_browser_plugin.cc
+++ b/chromium/content/renderer/browser_plugin/mock_browser_plugin.cc
@@ -8,9 +8,8 @@
namespace content {
MockBrowserPlugin::MockBrowserPlugin(RenderViewImpl* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params)
- : BrowserPlugin(render_view, frame, params) {
+ blink::WebFrame* frame)
+ : BrowserPlugin(render_view, frame) {
}
MockBrowserPlugin::~MockBrowserPlugin() {}
diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin.h b/chromium/content/renderer/browser_plugin/mock_browser_plugin.h
index acd001b64ca..ee0f5542f9e 100644
--- a/chromium/content/renderer/browser_plugin/mock_browser_plugin.h
+++ b/chromium/content/renderer/browser_plugin/mock_browser_plugin.h
@@ -12,8 +12,7 @@ namespace content {
class MockBrowserPlugin : public BrowserPlugin {
public:
MockBrowserPlugin(RenderViewImpl* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params);
+ blink::WebFrame* frame);
virtual ~MockBrowserPlugin();
diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc b/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc
index 9007f6e00e1..4a606862ef1 100644
--- a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc
+++ b/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc
@@ -21,10 +21,8 @@ MockBrowserPluginManager::~MockBrowserPluginManager() {
}
BrowserPlugin* MockBrowserPluginManager::CreateBrowserPlugin(
- RenderViewImpl* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params) {
- return new MockBrowserPlugin(render_view, frame, params);
+ RenderViewImpl* render_view, blink::WebFrame* frame) {
+ return new MockBrowserPlugin(render_view, frame);
}
void MockBrowserPluginManager::AllocateInstanceID(
diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h b/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h
index 78ae0bef9b2..83d55a5d352 100644
--- a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h
+++ b/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h
@@ -19,9 +19,7 @@ class MockBrowserPluginManager : public BrowserPluginManager {
// BrowserPluginManager implementation.
virtual BrowserPlugin* CreateBrowserPlugin(
- RenderViewImpl* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params) OVERRIDE;
+ RenderViewImpl* render_view, blink::WebFrame* frame) OVERRIDE;
virtual void AllocateInstanceID(
const base::WeakPtr<BrowserPlugin>& browser_plugin) OVERRIDE;
diff --git a/chromium/content/renderer/clipboard_client.h b/chromium/content/renderer/clipboard_client.h
index 1e00af61449..14a00076092 100644
--- a/chromium/content/renderer/clipboard_client.h
+++ b/chromium/content/renderer/clipboard_client.h
@@ -33,41 +33,43 @@ class ClipboardClient {
virtual ui::Clipboard* GetClipboard() = 0;
// Get a sequence number which uniquely identifies clipboard state.
- virtual uint64 GetSequenceNumber(ui::Clipboard::Buffer buffer) = 0;
+ virtual uint64 GetSequenceNumber(ui::ClipboardType type) = 0;
// Tests whether the clipboard contains a certain format
virtual bool IsFormatAvailable(const ui::Clipboard::FormatType& format,
- ui::Clipboard::Buffer buffer) = 0;
+ ui::ClipboardType type) = 0;
// Clear the contents of the clipboard.
- virtual void Clear(ui::Clipboard::Buffer buffer) = 0;
+ virtual void Clear(ui::ClipboardType type) = 0;
// Reads the available types from the clipboard, if available.
- virtual void ReadAvailableTypes(ui::Clipboard::Buffer buffer,
+ virtual void ReadAvailableTypes(ui::ClipboardType type,
std::vector<base::string16>* types,
bool* contains_filenames) = 0;
// Reads UNICODE text from the clipboard, if available.
- virtual void ReadText(ui::Clipboard::Buffer buffer,
+ virtual void ReadText(ui::ClipboardType type,
base::string16* result) = 0;
// Reads ASCII text from the clipboard, if available.
- virtual void ReadAsciiText(ui::Clipboard::Buffer buffer,
+ virtual void ReadAsciiText(ui::ClipboardType type,
std::string* result) = 0;
// Reads HTML from the clipboard, if available.
- virtual void ReadHTML(ui::Clipboard::Buffer buffer, base::string16* markup,
- GURL* url, uint32* fragment_start,
+ virtual void ReadHTML(ui::ClipboardType type,
+ base::string16* markup,
+ GURL* url,
+ uint32* fragment_start,
uint32* fragment_end) = 0;
// Reads RTF from the clipboard, if available.
- virtual void ReadRTF(ui::Clipboard::Buffer buffer, std::string* result) = 0;
+ virtual void ReadRTF(ui::ClipboardType type, std::string* result) = 0;
// Reads and image from the clipboard, if available.
- virtual void ReadImage(ui::Clipboard::Buffer buffer, std::string* data) = 0;
+ virtual void ReadImage(ui::ClipboardType type, std::string* data) = 0;
// Reads a custom data type from the clipboard, if available.
- virtual void ReadCustomData(ui::Clipboard::Buffer buffer,
+ virtual void ReadCustomData(ui::ClipboardType clipboard_type,
const base::string16& type,
base::string16* data) = 0;
diff --git a/chromium/content/renderer/clipboard_utils.cc b/chromium/content/renderer/clipboard_utils.cc
new file mode 100644
index 00000000000..28c04c99a7e
--- /dev/null
+++ b/chromium/content/renderer/clipboard_utils.cc
@@ -0,0 +1,39 @@
+// 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/clipboard_utils.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "net/base/escape.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+
+namespace content {
+
+std::string URLToMarkup(const blink::WebURL& url,
+ const blink::WebString& title) {
+ std::string markup("<a href=\"");
+ markup.append(url.spec());
+ markup.append("\">");
+ // TODO(darin): HTML escape this
+ markup.append(net::EscapeForHTML(UTF16ToUTF8(title)));
+ markup.append("</a>");
+ return markup;
+}
+
+std::string URLToImageMarkup(const blink::WebURL& url,
+ const blink::WebString& title) {
+ std::string markup("<img src=\"");
+ markup.append(net::EscapeForHTML(url.spec()));
+ markup.append("\"");
+ if (!title.isEmpty()) {
+ markup.append(" alt=\"");
+ markup.append(net::EscapeForHTML(UTF16ToUTF8(title)));
+ markup.append("\"");
+ }
+ markup.append("/>");
+ return markup;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/clipboard_utils.h b/chromium/content/renderer/clipboard_utils.h
new file mode 100644
index 00000000000..3acf7b43ebb
--- /dev/null
+++ b/chromium/content/renderer/clipboard_utils.h
@@ -0,0 +1,27 @@
+// 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_CLIPBOARD_UTILS_H_
+#define CONTENT_RENDERER_CLIPBOARD_UTILS_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+
+namespace blink {
+class WebString;
+class WebURL;
+}
+
+namespace content {
+
+CONTENT_EXPORT std::string URLToMarkup(const blink::WebURL& url,
+ const blink::WebString& title);
+
+CONTENT_EXPORT std::string URLToImageMarkup(const blink::WebURL& url,
+ const blink::WebString& title);
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_CLIPBOARD_UTILS_H_
diff --git a/chromium/content/renderer/context_menu_params_builder.cc b/chromium/content/renderer/context_menu_params_builder.cc
index e8cd0789cc1..2f22745475d 100644
--- a/chromium/content/renderer/context_menu_params_builder.cc
+++ b/chromium/content/renderer/context_menu_params_builder.cc
@@ -16,7 +16,7 @@ namespace content {
// static
ContextMenuParams ContextMenuParamsBuilder::Build(
- const WebKit::WebContextMenuData& data) {
+ const blink::WebContextMenuData& data) {
ContextMenuParams params;
params.media_type = data.mediaType;
params.x = data.mousePosition.x;
@@ -35,11 +35,9 @@ ContextMenuParams ContextMenuParamsBuilder::Build(
params.speech_input_enabled = data.isSpeechInputEnabled;
params.spellcheck_enabled = data.isSpellCheckingEnabled;
params.is_editable = data.isEditable;
-#if defined(OS_MACOSX)
params.writing_direction_default = data.writingDirectionDefault;
params.writing_direction_left_to_right = data.writingDirectionLeftToRight;
params.writing_direction_right_to_left = data.writingDirectionRightToLeft;
-#endif // OS_MACOSX
params.edit_flags = data.editFlags;
params.frame_charset = data.frameEncoding.utf8();
params.referrer_policy = data.referrerPolicy;
@@ -55,7 +53,7 @@ ContextMenuParams ContextMenuParamsBuilder::Build(
params.frame_page_state = HistoryItemToPageState(data.frameHistoryItem);
if (!params.link_url.is_empty()) {
- WebKit::WebNode selectedNode = data.node;
+ blink::WebNode selectedNode = data.node;
// If there are other embedded tags (like <a ..>Some <b>text</b></a>)
// we need to extract the parent <a/> node.
@@ -63,7 +61,7 @@ ContextMenuParams ContextMenuParamsBuilder::Build(
selectedNode = selectedNode.parentNode();
}
- WebKit::WebElement selectedElement = selectedNode.to<WebKit::WebElement>();
+ blink::WebElement selectedElement = selectedNode.to<blink::WebElement>();
if (selectedNode.isLink() && !selectedElement.isNull()) {
params.link_text = selectedElement.innerText();
} else {
@@ -76,10 +74,10 @@ ContextMenuParams ContextMenuParamsBuilder::Build(
// Deserialize the SSL info.
if (!data.securityInfo.isEmpty()) {
DeserializeSecurityInfo(data.securityInfo,
- &params.security_info.cert_id,
- &params.security_info.cert_status,
- &params.security_info.security_bits,
- &params.security_info.connection_status);
+ &params.security_info.cert_id, &params.security_info.cert_status,
+ &params.security_info.security_bits,
+ &params.security_info.connection_status,
+ &params.security_info.signed_certificate_timestamp_ids);
}
return params;
diff --git a/chromium/content/renderer/context_menu_params_builder.h b/chromium/content/renderer/context_menu_params_builder.h
index 414d61bcd76..624f85505c8 100644
--- a/chromium/content/renderer/context_menu_params_builder.h
+++ b/chromium/content/renderer/context_menu_params_builder.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_RENDERER_CONTEXT_MENU_PARAMS_BUILDER_H_
#define CONTENT_RENDERER_CONTEXT_MENU_PARAMS_BUILDER_H_
-namespace WebKit {
+namespace blink {
struct WebContextMenuData;
}
@@ -14,7 +14,7 @@ struct ContextMenuParams;
class ContextMenuParamsBuilder {
public:
- static ContextMenuParams Build(const WebKit::WebContextMenuData& data);
+ static ContextMenuParams Build(const blink::WebContextMenuData& data);
};
} // namespace content
diff --git a/chromium/content/renderer/cpp_bound_class_unittest.cc b/chromium/content/renderer/cpp_bound_class_unittest.cc
index 2c0f75f881c..8b05fea12bf 100644
--- a/chromium/content/renderer/cpp_bound_class_unittest.cc
+++ b/chromium/content/renderer/cpp_bound_class_unittest.cc
@@ -59,7 +59,7 @@ class TestObserver : public RenderViewObserver {
public:
explicit TestObserver(RenderView* render_view)
: RenderViewObserver(render_view) {}
- virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE {
+ virtual void DidClearWindowObject(blink::WebFrame* frame) OVERRIDE {
example_bound_class_.BindToJavascript(frame, "example");
}
void set_fallback_method_enabled(bool use_fallback) {
@@ -80,7 +80,7 @@ class CppBoundClassTest : public RenderViewTest {
observer_.reset(new TestObserver(view_));
observer_->set_fallback_method_enabled(useFallback());
- WebKit::WebURLRequest url_request;
+ blink::WebURLRequest url_request;
url_request.initialize();
url_request.setURL(GURL(kAboutBlankURL));
@@ -104,7 +104,7 @@ class CppBoundClassTest : public RenderViewTest {
void CheckTrue(const std::string& expression) {
int was_page_a = -1;
- string16 check_page_a =
+ base::string16 check_page_a =
ASCIIToUTF16(std::string("Number(") + expression + ")");
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
EXPECT_EQ(1, was_page_a);
diff --git a/chromium/content/renderer/cursor_utils.cc b/chromium/content/renderer/cursor_utils.cc
index 80351c94a3b..27bda233bfd 100644
--- a/chromium/content/renderer/cursor_utils.cc
+++ b/chromium/content/renderer/cursor_utils.cc
@@ -5,10 +5,10 @@
#include "content/renderer/cursor_utils.h"
#include "build/build_config.h"
-#include "third_party/WebKit/public/web/WebCursorInfo.h"
+#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "webkit/common/cursors/webcursor.h"
-using WebKit::WebCursorInfo;
+using blink::WebCursorInfo;
namespace content {
diff --git a/chromium/content/renderer/cursor_utils.h b/chromium/content/renderer/cursor_utils.h
index 2e594afc0c5..e19f7586fa1 100644
--- a/chromium/content/renderer/cursor_utils.h
+++ b/chromium/content/renderer/cursor_utils.h
@@ -7,20 +7,20 @@
class WebCursor;
-namespace WebKit {
+namespace blink {
struct WebCursorInfo;
}
namespace content {
-// Adapts our cursor info to WebKit::WebCursorInfo.
+// Adapts our cursor info to blink::WebCursorInfo.
bool GetWebKitCursorInfo(const WebCursor& cursor,
- WebKit::WebCursorInfo* webkit_cursor_info);
+ blink::WebCursorInfo* webkit_cursor_info);
-// Adapts WebKit::CursorInfo to our cursor.
+// Adapts blink::CursorInfo to our cursor.
void InitializeCursorFromWebKitCursorInfo(
WebCursor* cursor,
- const WebKit::WebCursorInfo& webkit_cursor_info);
+ const blink::WebCursorInfo& webkit_cursor_info);
} // namespace content
diff --git a/chromium/content/renderer/date_time_formatter.cc b/chromium/content/renderer/date_time_formatter.cc
deleted file mode 100644
index a0ce77b91cf..00000000000
--- a/chromium/content/renderer/date_time_formatter.cc
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/date_time_formatter.h"
-
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
-#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h"
-#include "third_party/icu/source/i18n/unicode/smpdtfmt.h"
-
-
-namespace content {
-
-void DateTimeFormatter::CreatePatternMap() {
- // Initialize all the UI elements with empty patterns,
- // then fill in the ones that are actually date/time inputs and
- // are implemented.
- for (int i = 0 ; i <= ui::TEXT_INPUT_TYPE_MAX; ++i) {
- patterns_[i] = "";
- }
- patterns_[ui::TEXT_INPUT_TYPE_DATE] = "yyyy-MM-dd";
- patterns_[ui::TEXT_INPUT_TYPE_DATE_TIME] = "yyyy-MM-dd'T'HH:mm'Z'";
- patterns_[ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL] = "yyyy-MM-dd'T'HH:mm";
- patterns_[ui::TEXT_INPUT_TYPE_MONTH] = "yyyy-MM";
- patterns_[ui::TEXT_INPUT_TYPE_TIME] = "HH:mm";
- patterns_[ui::TEXT_INPUT_TYPE_WEEK] = "Y-'W'ww";
-}
-
-// Returns true if icu_value parses as a valid for the specified date/time
-// pattern. The date/time pattern given is for icu::SimpleDateFormat.
-static bool TryPattern(const char* pattern,
- const icu::UnicodeString& icu_value) {
- icu::UnicodeString time_pattern = pattern;
- UErrorCode success = U_ZERO_ERROR;
- icu::SimpleDateFormat formatter(time_pattern, success);
- formatter.parse(icu_value, success);
- return success == U_ZERO_ERROR;
-}
-
-// For a time value represented as a string find the longest time
-// pattern which matches it. A valid time can have hours and minutes
-// or hours, minutes and seconds or hour, minutes, seconds and upto 3
-// digits of fractional seconds. Specify step in milliseconds, it is 1000
-// times the value specified as "step" in the "<input type=time step=...>
-// HTML fragment. A value of 60000 or more indicates that seconds
-// are not expected and a value of 1000 or more indicates that fractional
-// seconds are not expected.
-static const char* FindLongestTimePatternWhichMatches(const std::string& value,
- double step) {
- const char* pattern = "HH:mm";
- if (step >= 60000)
- return pattern;
-
- icu::UnicodeString icu_value = icu::UnicodeString::fromUTF8(
- icu::StringPiece(value.data(), value.size()));
- const char* last_pattern = pattern;
- pattern = "HH:mm:ss";
- if (!TryPattern(pattern, icu_value))
- return last_pattern;
- if (step >= 1000)
- return pattern;
- last_pattern = pattern;
- pattern = "HH:mm:ss.S";
- if (!TryPattern(pattern, icu_value))
- return last_pattern;
- last_pattern = pattern;
- pattern = "HH:mm:ss.SS";
- if (!TryPattern(pattern, icu_value))
- return last_pattern;
- last_pattern = pattern;
- pattern = "HH:mm:ss.SSS";
- if (!TryPattern(pattern, icu_value))
- return last_pattern;
- return pattern;
-}
-
-DateTimeFormatter::DateTimeFormatter(
- const WebKit::WebDateTimeChooserParams& source)
- : formatted_string_(source.currentValue.utf8()) {
- CreatePatternMap();
- if (source.type == WebKit::WebDateTimeInputTypeTime)
- time_pattern_ =
- FindLongestTimePatternWhichMatches(formatted_string_, source.step);
- ExtractType(source);
- if (!ParseValues()) {
- type_ = ui::TEXT_INPUT_TYPE_NONE;
- ClearAll();
- LOG(WARNING) << "Problems parsing input <" << formatted_string_ << ">";
- }
-}
-
-DateTimeFormatter::DateTimeFormatter(ui::TextInputType type,
- int year,
- int month,
- int day,
- int hour,
- int minute,
- int second,
- int milli,
- int week_year,
- int week)
- : type_(type),
- year_(year),
- month_(month),
- day_(day),
- hour_(hour),
- minute_(minute),
- second_(second),
- milli_(milli),
- week_year_(week_year),
- week_(week) {
- CreatePatternMap();
- if (type_ == ui::TEXT_INPUT_TYPE_TIME && (second != 0 || milli != 0)) {
- if (milli == 0)
- time_pattern_ = "HH:mm:ss";
- else if (milli % 100 == 0)
- time_pattern_ = "HH:mm:ss.S";
- else if (milli % 10 == 0)
- time_pattern_ = "HH:mm:ss.SS";
- else
- time_pattern_ = "HH:mm:ss.SSS";
- pattern_ = &time_pattern_;
- } else {
- pattern_ = type_ > 0 && type_ <= ui::TEXT_INPUT_TYPE_MAX ?
- &patterns_[type_] : &patterns_[ui::TEXT_INPUT_TYPE_NONE];
- }
-
- formatted_string_ = FormatString();
-}
-
-DateTimeFormatter::~DateTimeFormatter() {
-}
-
-int DateTimeFormatter::GetYear() const {
- return year_;
-}
-
-int DateTimeFormatter::GetMonth() const {
- return month_;
-}
-
-int DateTimeFormatter::GetDay() const {
- return day_;
-}
-
-int DateTimeFormatter::GetHour() const {
- return hour_;
-}
-
-int DateTimeFormatter::GetMinute() const {
- return minute_;
-}
-
-int DateTimeFormatter::GetSecond() const {
- return second_;
-}
-
-int DateTimeFormatter::GetMilli() const { return milli_; }
-
-int DateTimeFormatter::GetWeekYear() const { return week_year_; }
-
-int DateTimeFormatter::GetWeek() const {
- return week_;
-}
-
-ui::TextInputType DateTimeFormatter::GetType() const {
- return type_;
-}
-
-const std::string& DateTimeFormatter::GetFormattedValue() const {
- return formatted_string_;
-}
-
-const std::string DateTimeFormatter::FormatString() const {
- UErrorCode success = U_ZERO_ERROR;
- if (year_ == 0 && month_ == 0 && day_ == 0 && hour_ == 0 && minute_ == 0 &&
- second_ == 0 && milli_ == 0 && week_year_ == 0 && week_ == 0) {
- return std::string();
- }
-
- std::string result;
- icu::GregorianCalendar calendar(success);
- if (success <= U_ZERO_ERROR) {
- if (type_ == ui::TEXT_INPUT_TYPE_WEEK) {
- // An ISO week starts with Monday.
- calendar.setFirstDayOfWeek(UCAL_MONDAY);
- // ISO 8601 defines that the week with the year's first Thursday is the
- // first week.
- calendar.setMinimalDaysInFirstWeek(4);
- calendar.set(UCAL_YEAR_WOY, week_year_);
- calendar.set(UCAL_WEEK_OF_YEAR, week_);
- } else {
- calendar.set(UCAL_YEAR, year_);
- calendar.set(UCAL_MONTH, month_);
- calendar.set(UCAL_DATE, day_);
- calendar.set(UCAL_HOUR_OF_DAY, hour_);
- calendar.set(UCAL_MINUTE, minute_);
- calendar.set(UCAL_SECOND, second_);
- calendar.set(UCAL_MILLISECOND, milli_);
- }
- icu::SimpleDateFormat formatter(*pattern_, success);
- icu::UnicodeString formatted_time;
- formatter.format(calendar, formatted_time, NULL, success);
- UTF16ToUTF8(formatted_time.getBuffer(),
- static_cast<size_t>(formatted_time.length()),
- &result);
- if (success <= U_ZERO_ERROR)
- return result;
- }
- LOG(WARNING) << "Calendar not created: error " << success;
- return std::string();
-}
-
-void DateTimeFormatter::ExtractType(
- const WebKit::WebDateTimeChooserParams& source) {
- switch (source.type) {
- case WebKit::WebDateTimeInputTypeDate:
- type_ = ui::TEXT_INPUT_TYPE_DATE;
- break;
- case WebKit::WebDateTimeInputTypeDateTime:
- type_ = ui::TEXT_INPUT_TYPE_DATE_TIME;
- break;
- case WebKit::WebDateTimeInputTypeDateTimeLocal:
- type_ = ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL;
- break;
- case WebKit::WebDateTimeInputTypeMonth:
- type_ = ui::TEXT_INPUT_TYPE_MONTH;
- break;
- case WebKit::WebDateTimeInputTypeTime:
- type_ = ui::TEXT_INPUT_TYPE_TIME;
- break;
- case WebKit::WebDateTimeInputTypeWeek:
- type_ = ui::TEXT_INPUT_TYPE_WEEK;
- break;
- case WebKit::WebDateTimeInputTypeNone:
- default:
- type_ = ui::TEXT_INPUT_TYPE_NONE;
- }
-}
-
-// Not all fields are defined in all configurations and ICU might store
-// garbage if success <= U_ZERO_ERROR so the output is sanitized here.
-int DateTimeFormatter::ExtractValue(
- const icu::Calendar* calendar, UCalendarDateFields value) const {
- UErrorCode success = U_ZERO_ERROR;
- int result = calendar->get(value, success);
- return (success <= U_ZERO_ERROR) ? result : 0;
-}
-
-bool DateTimeFormatter::ParseValues() {
- if (type_ == ui::TEXT_INPUT_TYPE_NONE) {
- ClearAll();
- return false;
- }
-
- if (formatted_string_.empty()) {
- ClearAll();
- return true;
- }
-
- UErrorCode success = U_ZERO_ERROR;
- icu::UnicodeString icu_value = icu::UnicodeString::fromUTF8(
- icu::StringPiece(formatted_string_.data(), formatted_string_.size()));
- if (type_ > 0 && type_ <= ui::TEXT_INPUT_TYPE_MAX) {
- const icu::UnicodeString pattern =
- type_ == ui::TEXT_INPUT_TYPE_TIME ? time_pattern_ : patterns_[type_];
- icu::SimpleDateFormat formatter(pattern, success);
- formatter.parse(icu_value, success);
- if (success <= U_ZERO_ERROR) {
- const icu::Calendar* cal = formatter.getCalendar();
- year_ = ExtractValue(cal, UCAL_YEAR);
- month_ = ExtractValue(cal, UCAL_MONTH);
- day_ = ExtractValue(cal, UCAL_DATE);
- hour_ = ExtractValue(cal, UCAL_HOUR_OF_DAY); // 24h format
- minute_ = ExtractValue(cal, UCAL_MINUTE);
- second_ = ExtractValue(cal, UCAL_SECOND);
- milli_ = ExtractValue(cal, UCAL_MILLISECOND);
- week_year_ = ExtractValue(cal, UCAL_YEAR_WOY);
- week_ = ExtractValue(cal, UCAL_WEEK_OF_YEAR);
- }
- }
-
- return (success <= U_ZERO_ERROR);
-}
-
-void DateTimeFormatter::ClearAll() {
- year_ = 0;
- month_ = 0;
- day_ = 0;
- hour_ = 0;
- minute_ = 0;
- second_ = 0;
- milli_ = 0;
- week_year_ = 0;
- week_ = 0;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/date_time_formatter.h b/chromium/content/renderer/date_time_formatter.h
deleted file mode 100644
index b2b73410216..00000000000
--- a/chromium/content/renderer/date_time_formatter.h
+++ /dev/null
@@ -1,81 +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_RENDERER_DATE_TIME_FORMATTER_H_
-#define CONTENT_RENDERER_DATE_TIME_FORMATTER_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "content/common/content_export.h"
-#include "third_party/icu/source/common/unicode/unistr.h"
-#include "third_party/icu/source/i18n/unicode/gregocal.h"
-#include "ui/base/ime/text_input_type.h"
-
-namespace WebKit {
-struct WebDateTimeChooserParams;
-} // namespace WebKit
-
-namespace content {
-
-// Converts between a text string representing a date/time and
-// a set of year/month/day/hour/minute/second/milli and vice versa.
-// It is timezone agnostic.
-class CONTENT_EXPORT DateTimeFormatter {
- public:
- explicit DateTimeFormatter(const WebKit::WebDateTimeChooserParams& source);
- DateTimeFormatter(ui::TextInputType type,
- int year,
- int month,
- int day,
- int hour,
- int minute,
- int second,
- int milli,
- int week_year,
- int week);
- ~DateTimeFormatter();
-
- int GetYear() const;
- int GetMonth() const;
- int GetDay() const;
- int GetHour() const;
- int GetMinute() const;
- int GetSecond() const;
- int GetMilli() const;
- int GetWeekYear() const;
- int GetWeek() const;
- ui::TextInputType GetType() const;
- const std::string& GetFormattedValue() const;
-
- private:
- void CreatePatternMap();
- bool ParseValues();
- const std::string FormatString() const;
- int ExtractValue(
- const icu::Calendar* calendar, UCalendarDateFields value) const;
- void ExtractType(const WebKit::WebDateTimeChooserParams& source);
- void ClearAll();
-
- ui::TextInputType type_;
- icu::UnicodeString patterns_[ui::TEXT_INPUT_TYPE_MAX + 1];
- icu::UnicodeString time_pattern_;
- int year_;
- int month_;
- int day_;
- int hour_;
- int minute_;
- int second_;
- int milli_;
- int week_year_;
- int week_;
- const icu::UnicodeString* pattern_;
- std::string formatted_string_;
-
- DISALLOW_COPY_AND_ASSIGN(DateTimeFormatter);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_DATE_TIME_FORMATTER_H_
diff --git a/chromium/content/renderer/date_time_formatter_unittest.cc b/chromium/content/renderer/date_time_formatter_unittest.cc
deleted file mode 100644
index 0d8b07f2420..00000000000
--- a/chromium/content/renderer/date_time_formatter_unittest.cc
+++ /dev/null
@@ -1,225 +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 <map>
-
-#include "content/renderer/date_time_formatter.h"
-#include "content/renderer/renderer_date_time_picker.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h"
-#include "third_party/icu/source/common/unicode/unistr.h"
-#include "ui/base/ime/text_input_type.h"
-
-namespace content {
-
-class RendererDateTimePickerTest {
-};
-
-TEST(RendererDateTimePickerTest, TestParserValidStringInputs) {
- WebKit::WebDateTimeChooserParams params;
- params.currentValue = "2010-07";
- params.type = WebKit::WebDateTimeInputTypeMonth;
- DateTimeFormatter sut(params);
- EXPECT_EQ(2010, sut.GetYear());
-
- // Month field is 0 based
- EXPECT_EQ(6, sut.GetMonth());
-
- // Month input defaults to the first day of the month (1 based)
- EXPECT_EQ(1, sut.GetDay());
- EXPECT_EQ(0, sut.GetHour());
- EXPECT_EQ(0, sut.GetMinute());
- EXPECT_EQ(0, sut.GetSecond());
- EXPECT_EQ(2010, sut.GetWeekYear());
- EXPECT_EQ(26, sut.GetWeek());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_MONTH, sut.GetType());
-
- params.currentValue = "2012-05-25";
- params.type = WebKit::WebDateTimeInputTypeDate;
- DateTimeFormatter sut2(params);
- EXPECT_EQ(2012, sut2.GetYear());
- EXPECT_EQ(4, sut2.GetMonth());
- EXPECT_EQ(25, sut2.GetDay());
- EXPECT_EQ(0, sut2.GetHour());
- EXPECT_EQ(0, sut2.GetMinute());
- EXPECT_EQ(0, sut2.GetSecond());
- EXPECT_EQ(2012, sut2.GetWeekYear());
- EXPECT_EQ(21, sut2.GetWeek());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_DATE, sut2.GetType());
-
- params.currentValue = "2013-05-21T12:15";
- params.type = WebKit::WebDateTimeInputTypeDateTimeLocal;
- DateTimeFormatter sut3(params);
- EXPECT_EQ(2013, sut3.GetYear());
- EXPECT_EQ(4, sut3.GetMonth());
- EXPECT_EQ(21, sut3.GetDay());
- EXPECT_EQ(12, sut3.GetHour());
- EXPECT_EQ(15, sut3.GetMinute());
- EXPECT_EQ(0, sut3.GetSecond());
- EXPECT_EQ(2013, sut3.GetWeekYear());
- EXPECT_EQ(21, sut3.GetWeek());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL, sut3.GetType());
-
- params.currentValue = "2013-W15";
- params.type = WebKit::WebDateTimeInputTypeWeek;
- DateTimeFormatter sut4(params);
- EXPECT_EQ(2013, sut4.GetYear());
- EXPECT_EQ(3, sut4.GetMonth());
- EXPECT_EQ(7, sut4.GetDay());
- EXPECT_EQ(0, sut4.GetHour());
- EXPECT_EQ(0, sut4.GetMinute());
- EXPECT_EQ(0, sut4.GetSecond());
- EXPECT_EQ(2013, sut4.GetWeekYear());
- EXPECT_EQ(15, sut4.GetWeek());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_WEEK, sut4.GetType());
-
- params.currentValue = "12:15";
- params.type = WebKit::WebDateTimeInputTypeTime;
- DateTimeFormatter sut5(params);
- EXPECT_EQ(12, sut5.GetHour());
- EXPECT_EQ(15, sut5.GetMinute());
- EXPECT_EQ(0, sut5.GetSecond());
- EXPECT_EQ(0, sut5.GetMilli());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut5.GetType());
-
- params.currentValue = "12:15:02";
- params.type = WebKit::WebDateTimeInputTypeTime;
- DateTimeFormatter sut6(params);
- EXPECT_EQ(12, sut6.GetHour());
- EXPECT_EQ(15, sut6.GetMinute());
- EXPECT_EQ(02, sut6.GetSecond());
- EXPECT_EQ(0, sut6.GetMilli());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut6.GetType());
-
- params.currentValue = "12:15:02.1";
- params.type = WebKit::WebDateTimeInputTypeTime;
- DateTimeFormatter sut7(params);
- EXPECT_EQ(12, sut7.GetHour());
- EXPECT_EQ(15, sut7.GetMinute());
- EXPECT_EQ(02, sut7.GetSecond());
- EXPECT_EQ(100, sut7.GetMilli());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut7.GetType());
-
- params.currentValue = "12:15:02.123";
- params.type = WebKit::WebDateTimeInputTypeTime;
- DateTimeFormatter sut8(params);
- EXPECT_EQ(12, sut8.GetHour());
- EXPECT_EQ(15, sut8.GetMinute());
- EXPECT_EQ(02, sut8.GetSecond());
- EXPECT_EQ(123, sut8.GetMilli());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut8.GetType());
-}
-
-
-TEST(RendererDateTimePickerTest, TestParserInvalidStringInputs) {
-
- // Random non parsable text
- WebKit::WebDateTimeChooserParams params;
- params.currentValue = "<script injection";
- params.type = WebKit::WebDateTimeInputTypeMonth;
- DateTimeFormatter sut(params);
- EXPECT_EQ(0, sut.GetYear());
- EXPECT_EQ(0, sut.GetMonth());
- EXPECT_EQ(0, sut.GetDay());
- EXPECT_EQ(0, sut.GetHour());
- EXPECT_EQ(0, sut.GetMinute());
- EXPECT_EQ(0, sut.GetSecond());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, sut.GetType());
-
- // unimplemented type
- params.currentValue = "week 23";
- params.type = WebKit::WebDateTimeInputTypeWeek; // Not implemented
- DateTimeFormatter sut2(params);
- EXPECT_EQ(0, sut2.GetYear());
- EXPECT_EQ(0, sut2.GetMonth());
- EXPECT_EQ(0, sut2.GetDay());
- EXPECT_EQ(0, sut2.GetHour());
- EXPECT_EQ(0, sut2.GetMinute());
- EXPECT_EQ(0, sut2.GetSecond());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, sut2.GetType());
-
- // type is a subset of pattern
- params.currentValue = "2012-05-25";
- params.type = WebKit::WebDateTimeInputTypeDateTimeLocal;
- DateTimeFormatter sut3(params);
- EXPECT_EQ(0, sut3.GetYear());
- EXPECT_EQ(0, sut3.GetMonth());
- EXPECT_EQ(0, sut3.GetDay());
- EXPECT_EQ(0, sut3.GetHour());
- EXPECT_EQ(0, sut3.GetMinute());
- EXPECT_EQ(0, sut3.GetSecond());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, sut3.GetType());
-
- // type is a superset of pattern
- params.currentValue = "2013-05-21T12:15";
- params.type = WebKit::WebDateTimeInputTypeMonth;
- DateTimeFormatter sut4(params);
- EXPECT_EQ(2013, sut4.GetYear());
- EXPECT_EQ(4, sut4.GetMonth());
- EXPECT_EQ(1, sut4.GetDay());
- EXPECT_EQ(0, sut4.GetHour());
- EXPECT_EQ(0, sut4.GetMinute());
- EXPECT_EQ(0, sut4.GetSecond());
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_MONTH, sut4.GetType());
-}
-
-
-TEST(RendererDateTimePickerTest, TestParserValidDateInputs) {
- DateTimeFormatter sut(
- ui::TEXT_INPUT_TYPE_MONTH, 2012, 11, 1, 0, 0, 0, 0, 0, 0);
- EXPECT_EQ("2012-12", sut.GetFormattedValue());
-
- DateTimeFormatter sut2(
- ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL, 2013, 3, 23, 15, 47, 0, 0, 0, 0);
- EXPECT_EQ("2013-04-23T15:47", sut2.GetFormattedValue());
-
- DateTimeFormatter sut3(
- ui::TEXT_INPUT_TYPE_WEEK, 0, 0, 0, 0, 0, 0, 0, 2012, 2);
- EXPECT_EQ("2012-W02", sut3.GetFormattedValue());
-}
-
-TEST(RendererDateTimePickerTest, TestParserValidTimeInputs) {
- DateTimeFormatter sut(
- ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 12, 15, 0, 0, 0, 0);
- EXPECT_EQ("12:15", sut.GetFormattedValue());
-
- DateTimeFormatter sut2(
- ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 12, 15, 02, 0, 0, 0);
- EXPECT_EQ("12:15:02", sut2.GetFormattedValue());
-
- DateTimeFormatter sut3(
- ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 12, 15, 02, 123, 0, 0);
- EXPECT_EQ("12:15:02.123", sut3.GetFormattedValue());
-}
-
-TEST(RendererDateTimePickerTest, TestParserInvalidDateInputs) {
- DateTimeFormatter sut(ui::TEXT_INPUT_TYPE_WEEK, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- EXPECT_EQ("", sut.GetFormattedValue());
-
- DateTimeFormatter sut2(
- ui::TEXT_INPUT_TYPE_NONE, 2013, 3, 23, 0, 0, 0, 0, 0, 0);
- EXPECT_EQ("", sut2.GetFormattedValue());
-
- DateTimeFormatter sut3(
- ui::TEXT_INPUT_TYPE_NONE, 2013, 14, 32, 0, 0, 0, 0, 0, 0);
- EXPECT_EQ("", sut3.GetFormattedValue());
-
- DateTimeFormatter sut4(ui::TEXT_INPUT_TYPE_DATE, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- EXPECT_EQ("", sut4.GetFormattedValue());
-
- DateTimeFormatter sut5(ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- EXPECT_EQ("", sut5.GetFormattedValue());
-
- DateTimeFormatter sut6(
- ui::TEXT_INPUT_TYPE_PASSWORD, 23, 0, 0, 0, 5, 0, 0, 0, 0);
- EXPECT_EQ("", sut6.GetFormattedValue());
-
- DateTimeFormatter sut7(ui::TEXT_INPUT_TYPE_MAX, 23, 0, 0, 0, 5, 0, 0, 0, 0);
- EXPECT_EQ("", sut7.GetFormattedValue());
-
- DateTimeFormatter sut8(
- static_cast<ui::TextInputType>(10000), 23, 0, 0, 0, 5, 0, 0, 0, 0);
- EXPECT_EQ("", sut8.GetFormattedValue());
-}
-} // namespace content
diff --git a/chromium/content/renderer/date_time_suggestion_builder.cc b/chromium/content/renderer/date_time_suggestion_builder.cc
new file mode 100644
index 00000000000..7dff00d7824
--- /dev/null
+++ b/chromium/content/renderer/date_time_suggestion_builder.cc
@@ -0,0 +1,22 @@
+// 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/date_time_suggestion_builder.h"
+
+#include "content/common/date_time_suggestion.h"
+#include "third_party/WebKit/public/web/WebDateTimeSuggestion.h"
+
+namespace content {
+
+// static
+DateTimeSuggestion DateTimeSuggestionBuilder::Build(
+ const blink::WebDateTimeSuggestion& suggestion) {
+ DateTimeSuggestion result;
+ result.value = suggestion.value;
+ result.localized_value = suggestion.localizedValue;
+ result.label = suggestion.label;
+ return result;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/date_time_suggestion_builder.h b/chromium/content/renderer/date_time_suggestion_builder.h
new file mode 100644
index 00000000000..5087051fb04
--- /dev/null
+++ b/chromium/content/renderer/date_time_suggestion_builder.h
@@ -0,0 +1,23 @@
+// 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_DATE_TIME_SUGGESTION_BUILDER_H_
+#define CONTENT_RENDERER_DATE_TIME_SUGGESTION_BUILDER_H_
+
+namespace blink {
+struct WebDateTimeSuggestion;
+} // namespace blink
+
+namespace content {
+struct DateTimeSuggestion;
+
+class DateTimeSuggestionBuilder {
+ public:
+ static DateTimeSuggestion Build(
+ const blink::WebDateTimeSuggestion& suggestion);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_DATE_TIME_SUGGESTION_BUILDER_H_
diff --git a/chromium/content/renderer/device_orientation/device_motion_event_pump.cc b/chromium/content/renderer/device_orientation/device_motion_event_pump.cc
index e7ad8cacb7b..c60bd7a1265 100644
--- a/chromium/content/renderer/device_orientation/device_motion_event_pump.cc
+++ b/chromium/content/renderer/device_orientation/device_motion_event_pump.cc
@@ -22,7 +22,7 @@ DeviceMotionEventPump::~DeviceMotionEventPump() {
}
bool DeviceMotionEventPump::SetListener(
- WebKit::WebDeviceMotionListener* listener) {
+ blink::WebDeviceMotionListener* listener) {
listener_ = listener;
return listener_ ? RequestStart() : Stop();
}
@@ -39,7 +39,7 @@ bool DeviceMotionEventPump::OnControlMessageReceived(
void DeviceMotionEventPump::FireEvent() {
DCHECK(listener_);
- WebKit::WebDeviceMotionData data;
+ blink::WebDeviceMotionData data;
if (reader_->GetLatestData(&data) && data.allAvailableSensorsAreActive)
listener_->didChangeDeviceMotion(data);
}
diff --git a/chromium/content/renderer/device_orientation/device_motion_event_pump.h b/chromium/content/renderer/device_orientation/device_motion_event_pump.h
index 4fa453de819..f262ad42685 100644
--- a/chromium/content/renderer/device_orientation/device_motion_event_pump.h
+++ b/chromium/content/renderer/device_orientation/device_motion_event_pump.h
@@ -10,13 +10,13 @@
#include "content/renderer/shared_memory_seqlock_reader.h"
#include "third_party/WebKit/public/platform/WebDeviceMotionData.h"
-namespace WebKit {
+namespace blink {
class WebDeviceMotionListener;
}
namespace content {
-typedef SharedMemorySeqLockReader<WebKit::WebDeviceMotionData>
+typedef SharedMemorySeqLockReader<blink::WebDeviceMotionData>
DeviceMotionSharedMemoryReader;
class CONTENT_EXPORT DeviceMotionEventPump : public DeviceSensorEventPump {
@@ -27,7 +27,7 @@ class CONTENT_EXPORT DeviceMotionEventPump : public DeviceSensorEventPump {
// Sets the listener to receive updates for device motion data at
// regular intervals. Returns true if the registration was successful.
- bool SetListener(WebKit::WebDeviceMotionListener* listener);
+ bool SetListener(blink::WebDeviceMotionListener* listener);
// RenderProcessObserver implementation.
virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -38,7 +38,7 @@ class CONTENT_EXPORT DeviceMotionEventPump : public DeviceSensorEventPump {
virtual bool SendStartMessage() OVERRIDE;
virtual bool SendStopMessage() OVERRIDE;
- WebKit::WebDeviceMotionListener* listener_;
+ blink::WebDeviceMotionListener* listener_;
scoped_ptr<DeviceMotionSharedMemoryReader> reader_;
};
diff --git a/chromium/content/renderer/device_orientation/device_motion_event_pump_unittest.cc b/chromium/content/renderer/device_orientation/device_motion_event_pump_unittest.cc
index 066294b0aeb..6cb78b61a90 100644
--- a/chromium/content/renderer/device_orientation/device_motion_event_pump_unittest.cc
+++ b/chromium/content/renderer/device_orientation/device_motion_event_pump_unittest.cc
@@ -7,7 +7,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
-#include "content/common/device_motion_hardware_buffer.h"
+#include "content/common/device_orientation/device_motion_hardware_buffer.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebDeviceMotionListener.h"
@@ -17,14 +17,14 @@ namespace content {
class DeviceMotionEventPumpTest : public testing::Test {
};
-class MockDeviceMotionListener : public WebKit::WebDeviceMotionListener {
+class MockDeviceMotionListener : public blink::WebDeviceMotionListener {
public:
MockDeviceMotionListener();
virtual ~MockDeviceMotionListener() { }
virtual void didChangeDeviceMotion(
- const WebKit::WebDeviceMotionData&) OVERRIDE;
+ const blink::WebDeviceMotionData&) OVERRIDE;
bool did_change_device_motion_;
- WebKit::WebDeviceMotionData data_;
+ blink::WebDeviceMotionData data_;
};
MockDeviceMotionListener::MockDeviceMotionListener()
@@ -33,7 +33,7 @@ MockDeviceMotionListener::MockDeviceMotionListener()
}
void MockDeviceMotionListener::didChangeDeviceMotion(
- const WebKit::WebDeviceMotionData& data) {
+ const blink::WebDeviceMotionData& data) {
memcpy(&data_, &data, sizeof(data));
did_change_device_motion_ = true;
}
@@ -71,7 +71,7 @@ TEST_F(DeviceMotionEventPumpTest, MAYBE_DidStartPolling) {
memset(buffer, 0, sizeof(DeviceMotionHardwareBuffer));
shared_memory.ShareToProcess(base::kNullProcessHandle, &handle);
- WebKit::WebDeviceMotionData& data = buffer->data;
+ blink::WebDeviceMotionData& data = buffer->data;
data.accelerationX = 1;
data.hasAccelerationX = true;
data.accelerationY = 2;
@@ -87,7 +87,7 @@ TEST_F(DeviceMotionEventPumpTest, MAYBE_DidStartPolling) {
RunAllPendingInMessageLoop();
motion_pump->SetListener(0);
- WebKit::WebDeviceMotionData& received_data = listener->data_;
+ blink::WebDeviceMotionData& received_data = listener->data_;
EXPECT_TRUE(listener->did_change_device_motion_);
EXPECT_TRUE(received_data.hasAccelerationX);
EXPECT_EQ(1, (double)received_data.accelerationX);
@@ -128,7 +128,7 @@ TEST_F(DeviceMotionEventPumpTest, MAYBE_DidStartPollingNotAllSensorsActive) {
memset(buffer, 0, sizeof(DeviceMotionHardwareBuffer));
shared_memory.ShareToProcess(base::kNullProcessHandle, &handle);
- WebKit::WebDeviceMotionData& data = buffer->data;
+ blink::WebDeviceMotionData& data = buffer->data;
data.accelerationX = 1;
data.hasAccelerationX = true;
data.accelerationY = 2;
@@ -144,7 +144,7 @@ TEST_F(DeviceMotionEventPumpTest, MAYBE_DidStartPollingNotAllSensorsActive) {
RunAllPendingInMessageLoop();
motion_pump->SetListener(0);
- WebKit::WebDeviceMotionData& received_data = listener->data_;
+ blink::WebDeviceMotionData& received_data = listener->data_;
// No change in device motion because allAvailableSensorsAreActive is false.
EXPECT_FALSE(listener->did_change_device_motion_);
EXPECT_FALSE(received_data.hasAccelerationX);
diff --git a/chromium/content/renderer/device_orientation/device_orientation_event_pump.cc b/chromium/content/renderer/device_orientation/device_orientation_event_pump.cc
index ca45537dfc2..14930433439 100644
--- a/chromium/content/renderer/device_orientation/device_orientation_event_pump.cc
+++ b/chromium/content/renderer/device_orientation/device_orientation_event_pump.cc
@@ -26,7 +26,7 @@ DeviceOrientationEventPump::~DeviceOrientationEventPump() {
}
bool DeviceOrientationEventPump::SetListener(
- WebKit::WebDeviceOrientationListener* listener) {
+ blink::WebDeviceOrientationListener* listener) {
listener_ = listener;
return listener_ ? RequestStart() : Stop();
}
@@ -43,7 +43,7 @@ bool DeviceOrientationEventPump::OnControlMessageReceived(
void DeviceOrientationEventPump::FireEvent() {
DCHECK(listener_);
- WebKit::WebDeviceOrientationData data;
+ blink::WebDeviceOrientationData data;
if (reader_->GetLatestData(&data) && ShouldFireEvent(data)) {
memcpy(&data_, &data, sizeof(data));
listener_->didChangeDeviceOrientation(data);
@@ -59,7 +59,7 @@ static bool IsSignificantlyDifferent(bool hasAngle1, double angle1,
}
bool DeviceOrientationEventPump::ShouldFireEvent(
- const WebKit::WebDeviceOrientationData& data) const {
+ const blink::WebDeviceOrientationData& data) const {
return data.allAvailableSensorsAreActive &&
(IsSignificantlyDifferent(
data_.hasAlpha, data_.alpha, data.hasAlpha, data.alpha) ||
diff --git a/chromium/content/renderer/device_orientation/device_orientation_event_pump.h b/chromium/content/renderer/device_orientation/device_orientation_event_pump.h
index 26658ff5d4d..ac7f31cd3b0 100644
--- a/chromium/content/renderer/device_orientation/device_orientation_event_pump.h
+++ b/chromium/content/renderer/device_orientation/device_orientation_event_pump.h
@@ -10,13 +10,13 @@
#include "content/renderer/shared_memory_seqlock_reader.h"
#include "third_party/WebKit/public/platform/WebDeviceOrientationData.h"
-namespace WebKit {
+namespace blink {
class WebDeviceOrientationListener;
}
namespace content {
-typedef SharedMemorySeqLockReader<WebKit::WebDeviceOrientationData>
+typedef SharedMemorySeqLockReader<blink::WebDeviceOrientationData>
DeviceOrientationSharedMemoryReader;
class CONTENT_EXPORT DeviceOrientationEventPump : public DeviceSensorEventPump {
@@ -31,7 +31,7 @@ class CONTENT_EXPORT DeviceOrientationEventPump : public DeviceSensorEventPump {
// Sets the listener to receive updates for device orientation data at
// regular intervals. Returns true if the registration was successful.
- bool SetListener(WebKit::WebDeviceOrientationListener* listener);
+ bool SetListener(blink::WebDeviceOrientationListener* listener);
// RenderProcessObserver implementation.
virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -42,10 +42,10 @@ class CONTENT_EXPORT DeviceOrientationEventPump : public DeviceSensorEventPump {
virtual bool SendStartMessage() OVERRIDE;
virtual bool SendStopMessage() OVERRIDE;
- bool ShouldFireEvent(const WebKit::WebDeviceOrientationData& data) const;
+ bool ShouldFireEvent(const blink::WebDeviceOrientationData& data) const;
- WebKit::WebDeviceOrientationListener* listener_;
- WebKit::WebDeviceOrientationData data_;
+ blink::WebDeviceOrientationListener* listener_;
+ blink::WebDeviceOrientationData data_;
scoped_ptr<DeviceOrientationSharedMemoryReader> reader_;
};
diff --git a/chromium/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc b/chromium/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc
index 2d137ad3a14..402cd077568 100644
--- a/chromium/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc
+++ b/chromium/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc
@@ -14,15 +14,15 @@
namespace content {
class MockDeviceOrientationListener
- : public WebKit::WebDeviceOrientationListener {
+ : public blink::WebDeviceOrientationListener {
public:
MockDeviceOrientationListener();
virtual ~MockDeviceOrientationListener() { }
virtual void didChangeDeviceOrientation(
- const WebKit::WebDeviceOrientationData&) OVERRIDE;
+ const blink::WebDeviceOrientationData&) OVERRIDE;
void ResetDidChangeOrientation();
bool did_change_device_orientation_;
- WebKit::WebDeviceOrientationData data_;
+ blink::WebDeviceOrientationData data_;
};
MockDeviceOrientationListener::MockDeviceOrientationListener()
@@ -31,7 +31,7 @@ MockDeviceOrientationListener::MockDeviceOrientationListener()
}
void MockDeviceOrientationListener::didChangeDeviceOrientation(
- const WebKit::WebDeviceOrientationData& data) {
+ const blink::WebDeviceOrientationData& data) {
memcpy(&data_, &data, sizeof(data));
did_change_device_orientation_ = true;
}
@@ -50,6 +50,11 @@ class DeviceOrientationEventPumpForTesting : public DeviceOrientationEventPump {
}
virtual bool SendStartMessage() OVERRIDE { return true; }
virtual bool SendStopMessage() OVERRIDE { return true; }
+ virtual void FireEvent() OVERRIDE {
+ DeviceOrientationEventPump::FireEvent();
+ Stop();
+ base::MessageLoop::current()->QuitWhenIdle();
+ }
};
class DeviceOrientationEventPumpTest : public testing::Test {
@@ -70,7 +75,7 @@ class DeviceOrientationEventPumpTest : public testing::Test {
}
void InitBuffer() {
- WebKit::WebDeviceOrientationData& data = buffer_->data;
+ blink::WebDeviceOrientationData& data = buffer_->data;
data.alpha = 1;
data.hasAlpha = true;
data.beta = 2;
@@ -94,17 +99,15 @@ class DeviceOrientationEventPumpTest : public testing::Test {
#define MAYBE_DidStartPolling DidStartPolling
#endif
TEST_F(DeviceOrientationEventPumpTest, MAYBE_DidStartPolling) {
- base::MessageLoop loop(base::MessageLoop::TYPE_UI);
- InitBuffer();
+ base::MessageLoop loop;
+ InitBuffer();
orientation_pump_->SetListener(listener_.get());
orientation_pump_->OnDidStart(handle_);
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
- orientation_pump_->GetDelayMillis() * 2));
- RunAllPendingInMessageLoop();
- orientation_pump_->SetListener(0);
- WebKit::WebDeviceOrientationData& received_data = listener_->data_;
+ base::MessageLoop::current()->Run();
+
+ blink::WebDeviceOrientationData& received_data = listener_->data_;
EXPECT_TRUE(listener_->did_change_device_orientation_);
EXPECT_TRUE(received_data.allAvailableSensorsAreActive);
EXPECT_EQ(1, (double)received_data.alpha);
@@ -125,16 +128,15 @@ TEST_F(DeviceOrientationEventPumpTest, MAYBE_DidStartPolling) {
#endif
TEST_F(DeviceOrientationEventPumpTest,
MAYBE_UpdateRespectsOrientationThreshold) {
- base::MessageLoop loop(base::MessageLoop::TYPE_UI);
- InitBuffer();
+ base::MessageLoop loop;
+ InitBuffer();
orientation_pump_->SetListener(listener_.get());
orientation_pump_->OnDidStart(handle_);
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
- orientation_pump_->GetDelayMillis() * 2));
- RunAllPendingInMessageLoop();
- WebKit::WebDeviceOrientationData& received_data = listener_->data_;
+ base::MessageLoop::current()->Run();
+
+ blink::WebDeviceOrientationData& received_data = listener_->data_;
EXPECT_TRUE(listener_->did_change_device_orientation_);
EXPECT_TRUE(received_data.allAvailableSensorsAreActive);
EXPECT_EQ(1, (double)received_data.alpha);
@@ -148,9 +150,10 @@ TEST_F(DeviceOrientationEventPumpTest,
1 + DeviceOrientationEventPump::kOrientationThreshold / 2.0;
listener_->ResetDidChangeOrientation();
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
- orientation_pump_->GetDelayMillis() * 2));
- RunAllPendingInMessageLoop();
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&DeviceOrientationEventPumpForTesting::FireEvent,
+ base::Unretained(orientation_pump_.get())));
+ base::MessageLoop::current()->Run();
EXPECT_FALSE(listener_->did_change_device_orientation_);
EXPECT_TRUE(received_data.allAvailableSensorsAreActive);
@@ -165,10 +168,10 @@ TEST_F(DeviceOrientationEventPumpTest,
1 + DeviceOrientationEventPump::kOrientationThreshold;
listener_->ResetDidChangeOrientation();
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
- orientation_pump_->GetDelayMillis() * 2));
- RunAllPendingInMessageLoop();
- orientation_pump_->SetListener(0);
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&DeviceOrientationEventPumpForTesting::FireEvent,
+ base::Unretained(orientation_pump_.get())));
+ base::MessageLoop::current()->Run();
EXPECT_TRUE(listener_->did_change_device_orientation_);
EXPECT_EQ(1 + DeviceOrientationEventPump::kOrientationThreshold,
diff --git a/chromium/content/renderer/device_orientation/device_sensor_event_pump.cc b/chromium/content/renderer/device_orientation/device_sensor_event_pump.cc
index e4c0eb0599d..8e82d8f5825 100644
--- a/chromium/content/renderer/device_orientation/device_sensor_event_pump.cc
+++ b/chromium/content/renderer/device_orientation/device_sensor_event_pump.cc
@@ -9,7 +9,10 @@
namespace content {
-const int DeviceSensorEventPump::kDefaultPumpDelayMillis = 40;
+// Default interval between successive polls, should take into account the
+// value of |kInertialSensorIntervalMillis| in
+// content/browser/device_orientation/inertial_sensor_consts.h.
+const int DeviceSensorEventPump::kDefaultPumpDelayMillis = 50;
int DeviceSensorEventPump::GetDelayMillis() const {
return pump_delay_millis_;
diff --git a/chromium/content/renderer/device_orientation_dispatcher.cc b/chromium/content/renderer/device_orientation_dispatcher.cc
deleted file mode 100644
index 72d86882544..00000000000
--- a/chromium/content/renderer/device_orientation_dispatcher.cc
+++ /dev/null
@@ -1,94 +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/device_orientation_dispatcher.h"
-
-#include "content/common/device_orientation/device_orientation_messages.h"
-#include "content/renderer/render_view_impl.h"
-#include "third_party/WebKit/public/web/WebDeviceOrientation.h"
-#include "third_party/WebKit/public/web/WebDeviceOrientationController.h"
-
-namespace content {
-
-DeviceOrientationDispatcher::DeviceOrientationDispatcher(
- RenderViewImpl* render_view)
- : RenderViewObserver(render_view), started_(false) {}
-
-DeviceOrientationDispatcher::~DeviceOrientationDispatcher() {
- if (started_)
- stopUpdating();
-}
-
-bool DeviceOrientationDispatcher::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(DeviceOrientationDispatcher, msg)
- IPC_MESSAGE_HANDLER(DeviceOrientationMsg_Updated,
- OnDeviceOrientationUpdated)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void DeviceOrientationDispatcher::setController(
- WebKit::WebDeviceOrientationController* controller) {
- controller_.reset(controller);
-}
-
-void DeviceOrientationDispatcher::startUpdating() {
- Send(new DeviceOrientationHostMsg_StartUpdating(routing_id()));
- started_ = true;
-}
-
-void DeviceOrientationDispatcher::stopUpdating() {
- Send(new DeviceOrientationHostMsg_StopUpdating(routing_id()));
- started_ = false;
-}
-
-WebKit::WebDeviceOrientation DeviceOrientationDispatcher::lastOrientation()
- const {
- return last_orientation_;
-}
-
-namespace {
-bool OrientationsEqual(const DeviceOrientationMsg_Updated_Params& a,
- WebKit::WebDeviceOrientation* b) {
- if (a.can_provide_alpha != b->canProvideAlpha())
- return false;
- if (a.can_provide_alpha && a.alpha != b->alpha())
- return false;
- if (a.can_provide_beta != b->canProvideBeta())
- return false;
- if (a.can_provide_beta && a.beta != b->beta())
- return false;
- if (a.can_provide_gamma != b->canProvideGamma())
- return false;
- if (a.can_provide_gamma && a.gamma != b->gamma())
- return false;
- if (a.can_provide_absolute != b->canProvideAbsolute())
- return false;
- if (a.can_provide_absolute && a.absolute != b->absolute())
- return false;
-
- return true;
-}
-} // namespace
-
-void DeviceOrientationDispatcher::OnDeviceOrientationUpdated(
- const DeviceOrientationMsg_Updated_Params& p) {
- if (!last_orientation_.isNull() && OrientationsEqual(p, &last_orientation_))
- return;
-
- last_orientation_.setNull(false);
- if (p.can_provide_alpha)
- last_orientation_.setAlpha(p.alpha);
- if (p.can_provide_beta)
- last_orientation_.setBeta(p.beta);
- if (p.can_provide_gamma)
- last_orientation_.setGamma(p.gamma);
- if (p.can_provide_absolute)
- last_orientation_.setAbsolute(p.absolute);
- controller_->didChangeDeviceOrientation(last_orientation_);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/device_orientation_dispatcher.h b/chromium/content/renderer/device_orientation_dispatcher.h
deleted file mode 100644
index 5ee3342ebf3..00000000000
--- a/chromium/content/renderer/device_orientation_dispatcher.h
+++ /dev/null
@@ -1,46 +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_DEVICE_ORIENTATION_DISPATCHER_H_
-#define CONTENT_RENDERER_DEVICE_ORIENTATION_DISPATCHER_H_
-
-#include "third_party/WebKit/public/web/WebDeviceOrientationClient.h"
-#include "third_party/WebKit/public/web/WebDeviceOrientation.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "content/public/renderer/render_view_observer.h"
-
-struct DeviceOrientationMsg_Updated_Params;
-
-namespace content {
-class RenderViewImpl;
-
-class DeviceOrientationDispatcher : public RenderViewObserver,
- public WebKit::WebDeviceOrientationClient {
- public:
- explicit DeviceOrientationDispatcher(RenderViewImpl* render_view);
- virtual ~DeviceOrientationDispatcher();
-
- private:
- // RenderView::Observer implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- // From WebKit::WebDeviceOrientationClient.
- virtual void setController(
- WebKit::WebDeviceOrientationController* controller);
- virtual void startUpdating();
- virtual void stopUpdating();
- virtual WebKit::WebDeviceOrientation lastOrientation() const;
-
- void OnDeviceOrientationUpdated(
- const DeviceOrientationMsg_Updated_Params& p);
-
- scoped_ptr<WebKit::WebDeviceOrientationController> controller_;
- WebKit::WebDeviceOrientation last_orientation_;
- bool started_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_DEVICE_ORIENTATION_DISPATCHER_H_
diff --git a/chromium/content/renderer/devtools/devtools_agent.cc b/chromium/content/renderer/devtools/devtools_agent.cc
index 635acc18641..a2415441e25 100644
--- a/chromium/content/renderer/devtools/devtools_agent.cc
+++ b/chromium/content/renderer/devtools/devtools_agent.cc
@@ -12,9 +12,11 @@
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "content/common/devtools_messages.h"
+#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
#include "content/renderer/devtools/devtools_agent_filter.h"
#include "content/renderer/devtools/devtools_client.h"
+#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
#include "third_party/WebKit/public/platform/WebPoint.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -22,26 +24,29 @@
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
#include "third_party/WebKit/public/web/WebDevToolsAgent.h"
#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebSettings.h"
#include "third_party/WebKit/public/web/WebView.h"
#if defined(USE_TCMALLOC)
#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
#endif
-using WebKit::WebConsoleMessage;
-using WebKit::WebDevToolsAgent;
-using WebKit::WebDevToolsAgentClient;
-using WebKit::WebFrame;
-using WebKit::WebPoint;
-using WebKit::WebString;
-using WebKit::WebCString;
-using WebKit::WebVector;
-using WebKit::WebView;
+using blink::WebConsoleMessage;
+using blink::WebDevToolsAgent;
+using blink::WebDevToolsAgentClient;
+using blink::WebFrame;
+using blink::WebPoint;
+using blink::WebString;
+using blink::WebCString;
+using blink::WebVector;
+using blink::WebView;
using base::debug::TraceLog;
namespace content {
+base::subtle::AtomicWord DevToolsAgent::event_callback_;
+
namespace {
class WebKitClientMessageLoopImpl
@@ -69,7 +74,8 @@ base::LazyInstance<IdToAgentMap>::Leaky
DevToolsAgent::DevToolsAgent(RenderViewImpl* render_view)
: RenderViewObserver(render_view),
is_attached_(false),
- is_devtools_client_(false) {
+ is_devtools_client_(false),
+ gpu_route_id_(MSG_ROUTING_NONE) {
g_agent_for_routing_id.Get()[routing_id()] = this;
render_view->webview()->setDevToolsAgentClient(this);
@@ -79,6 +85,7 @@ DevToolsAgent::DevToolsAgent(RenderViewImpl* render_view)
DevToolsAgent::~DevToolsAgent() {
g_agent_for_routing_id.Get().erase(routing_id());
+ setTraceEventCallback(NULL);
}
// Called on the Renderer thread.
@@ -93,6 +100,7 @@ bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_InspectElement, OnInspectElement)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_AddMessageToConsole,
OnAddMessageToConsole)
+ IPC_MESSAGE_HANDLER(DevToolsAgentMsg_GpuTasksChunk, OnGpuTasksChunk)
IPC_MESSAGE_HANDLER(DevToolsMsg_SetupDevToolsClient, OnSetupDevToolsClient)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -105,7 +113,7 @@ bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) {
}
void DevToolsAgent::sendMessageToInspectorFrontend(
- const WebKit::WebString& message) {
+ const blink::WebString& message) {
Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(routing_id(),
message.utf8()));
}
@@ -115,11 +123,11 @@ int DevToolsAgent::hostIdentifier() {
}
void DevToolsAgent::saveAgentRuntimeState(
- const WebKit::WebString& state) {
+ const blink::WebString& state) {
Send(new DevToolsHostMsg_SaveAgentRuntimeState(routing_id(), state.utf8()));
}
-WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop*
+blink::WebDevToolsAgentClient::WebKitClientMessageLoop*
DevToolsAgent::createClientMessageLoop() {
return new WebKitClientMessageLoopImpl();
}
@@ -134,19 +142,94 @@ void DevToolsAgent::clearBrowserCookies() {
void DevToolsAgent::setTraceEventCallback(TraceEventCallback cb) {
TraceLog* trace_log = TraceLog::GetInstance();
- trace_log->SetEventCallback(cb);
+ base::subtle::NoBarrier_Store(&event_callback_,
+ reinterpret_cast<base::subtle::AtomicWord>(cb));
if (!!cb) {
- trace_log->SetEnabled(base::debug::CategoryFilter(
+ trace_log->SetEventCallbackEnabled(base::debug::CategoryFilter(
base::debug::CategoryFilter::kDefaultCategoryFilterString),
- TraceLog::RECORD_UNTIL_FULL);
+ TraceEventCallbackWrapper);
} else {
- trace_log->SetDisabled();
+ trace_log->SetEventCallbackDisabled();
+ }
+}
+
+// static
+void DevToolsAgent::TraceEventCallbackWrapper(
+ base::TimeTicks timestamp,
+ char phase,
+ const unsigned char* category_group_enabled,
+ const char* name,
+ unsigned long long id,
+ int num_args,
+ const char* const arg_names[],
+ const unsigned char arg_types[],
+ const unsigned long long arg_values[],
+ unsigned char flags) {
+ TraceEventCallback callback =
+ reinterpret_cast<TraceEventCallback>(
+ base::subtle::NoBarrier_Load(&event_callback_));
+ if (callback) {
+ double timestamp_seconds = (timestamp - base::TimeTicks()).InSecondsF();
+ callback(phase, category_group_enabled, name, id, num_args,
+ arg_names, arg_types, arg_values, flags, timestamp_seconds);
}
}
+void DevToolsAgent::startGPUEventsRecording() {
+ GpuChannelHost* gpu_channel_host =
+ RenderThreadImpl::current()->GetGpuChannel();
+ if (!gpu_channel_host)
+ return;
+ DCHECK(gpu_route_id_ == MSG_ROUTING_NONE);
+ gpu_channel_host->Send(
+ new GpuChannelMsg_DevToolsStartEventsRecording(&gpu_route_id_));
+ DCHECK(gpu_route_id_ != MSG_ROUTING_NONE);
+ if (gpu_route_id_ != MSG_ROUTING_NONE) {
+ gpu_channel_host->AddRoute(gpu_route_id_, AsWeakPtr());
+ }
+}
+
+void DevToolsAgent::stopGPUEventsRecording() {
+ GpuChannelHost* gpu_channel_host =
+ RenderThreadImpl::current()->GetGpuChannel();
+ if (!gpu_channel_host || gpu_route_id_ == MSG_ROUTING_NONE)
+ return;
+ gpu_channel_host->Send(new GpuChannelMsg_DevToolsStopEventsRecording());
+ gpu_channel_host->RemoveRoute(gpu_route_id_);
+ gpu_route_id_ = MSG_ROUTING_NONE;
+}
+
+void DevToolsAgent::OnGpuTasksChunk(const std::vector<GpuTaskInfo>& tasks) {
+ WebDevToolsAgent* web_agent = GetWebAgent();
+ if (!web_agent)
+ return;
+ for (size_t i = 0; i < tasks.size(); i++) {
+ const GpuTaskInfo& task = tasks[i];
+ WebDevToolsAgent::GPUEvent event(task.timestamp, task.phase, task.foreign,
+ static_cast<size_t>(task.used_gpu_memory_bytes));
+ web_agent->processGPUEvent(event);
+ }
+}
+
+void DevToolsAgent::enableDeviceEmulation(
+ const blink::WebRect& device_rect,
+ const blink::WebRect& view_rect,
+ float device_scale_factor,
+ bool fit_to_view) {
+ RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view());
+ impl->webview()->settings()->setForceCompositingMode(true);
+ impl->EnableScreenMetricsEmulation(gfx::Rect(device_rect),
+ gfx::Rect(view_rect), device_scale_factor, fit_to_view);
+}
+
+void DevToolsAgent::disableDeviceEmulation() {
+ RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view());
+ impl->DisableScreenMetricsEmulation();
+}
+
#if defined(USE_TCMALLOC) && !defined(OS_WIN)
static void AllocationVisitor(void* data, const void* ptr) {
- typedef WebKit::WebDevToolsAgentClient::AllocatedObjectVisitor Visitor;
+ typedef blink::WebDevToolsAgentClient::AllocatedObjectVisitor Visitor;
Visitor* visitor = reinterpret_cast<Visitor*>(data);
visitor->visitObject(ptr);
}
@@ -192,6 +275,7 @@ void DevToolsAgent::OnDetach() {
}
void DevToolsAgent::OnDispatchOnInspectorBackend(const std::string& message) {
+ TRACE_EVENT0("devtools", "DevToolsAgent::OnDispatchOnInspectorBackend");
WebDevToolsAgent* web_agent = GetWebAgent();
if (web_agent)
web_agent->dispatchOnInspectorBackend(WebString::fromUTF8(message));
diff --git a/chromium/content/renderer/devtools/devtools_agent.h b/chromium/content/renderer/devtools/devtools_agent.h
index 4ac22db97f9..68f3bc4fc2c 100644
--- a/chromium/content/renderer/devtools/devtools_agent.h
+++ b/chromium/content/renderer/devtools/devtools_agent.h
@@ -6,16 +6,22 @@
#define CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_AGENT_H_
#include <string>
+#include <vector>
+#include "base/atomicops.h"
#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
#include "content/public/common/console_message_level.h"
#include "content/public/renderer/render_view_observer.h"
#include "third_party/WebKit/public/web/WebDevToolsAgentClient.h"
-namespace WebKit {
+namespace blink {
class WebDevToolsAgent;
}
+struct GpuTaskInfo;
+
namespace content {
class RenderViewImpl;
@@ -24,7 +30,8 @@ class RenderViewImpl;
// agents infrastructure are flowing through this communication agent.
// There is a corresponding DevToolsClient object on the client side.
class DevToolsAgent : public RenderViewObserver,
- public WebKit::WebDevToolsAgentClient {
+ public base::SupportsWeakPtr<DevToolsAgent>,
+ public blink::WebDevToolsAgentClient {
public:
explicit DevToolsAgent(RenderViewImpl* render_view);
virtual ~DevToolsAgent();
@@ -32,27 +39,39 @@ class DevToolsAgent : public RenderViewObserver,
// Returns agent instance for its host id.
static DevToolsAgent* FromHostId(int host_id);
- WebKit::WebDevToolsAgent* GetWebAgent();
+ blink::WebDevToolsAgent* GetWebAgent();
bool IsAttached();
private:
- friend class DevToolsAgentFilter;
-
// RenderView::Observer implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
// WebDevToolsAgentClient implementation
- virtual void sendMessageToInspectorFrontend(const WebKit::WebString& data);
+ virtual void sendMessageToInspectorFrontend(const blink::WebString& data);
virtual int hostIdentifier();
- virtual void saveAgentRuntimeState(const WebKit::WebString& state);
- virtual WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop*
+ virtual void saveAgentRuntimeState(const blink::WebString& state);
+ virtual blink::WebDevToolsAgentClient::WebKitClientMessageLoop*
createClientMessageLoop();
virtual void clearBrowserCache();
virtual void clearBrowserCookies();
virtual void visitAllocatedObjects(AllocatedObjectVisitor* visitor);
- virtual void setTraceEventCallback(TraceEventCallback cb);
+
+ typedef void (*TraceEventCallback)(
+ char phase, const unsigned char*, const char* name, unsigned long long id,
+ int numArgs, const char* const* argNames, const unsigned char* argTypes,
+ const unsigned long long* argValues,
+ unsigned char flags, double timestamp);
+ virtual void setTraceEventCallback(TraceEventCallback cb) OVERRIDE;
+ virtual void startGPUEventsRecording() OVERRIDE;
+ virtual void stopGPUEventsRecording() OVERRIDE;
+
+ virtual void enableDeviceEmulation(
+ const blink::WebRect& device_rect,
+ const blink::WebRect& view_rect, float device_scale_factor,
+ bool fit_to_view);
+ virtual void disableDeviceEmulation();
void OnAttach();
void OnReattach(const std::string& agent_state);
@@ -61,11 +80,27 @@ class DevToolsAgent : public RenderViewObserver,
void OnInspectElement(int x, int y);
void OnAddMessageToConsole(ConsoleMessageLevel level,
const std::string& message);
+ void OnGpuTasksChunk(const std::vector<GpuTaskInfo>& tasks);
void ContinueProgram();
void OnSetupDevToolsClient();
+ static void TraceEventCallbackWrapper(
+ base::TimeTicks timestamp,
+ char phase,
+ const unsigned char* category_group_enabled,
+ const char* name,
+ unsigned long long id,
+ int num_args,
+ const char* const arg_names[],
+ const unsigned char arg_types[],
+ const unsigned long long arg_values[],
+ unsigned char flags);
+
bool is_attached_;
bool is_devtools_client_;
+ int32 gpu_route_id_;
+
+ static base::subtle::AtomicWord /* TraceEventCallback */ event_callback_;
DISALLOW_COPY_AND_ASSIGN(DevToolsAgent);
};
diff --git a/chromium/content/renderer/devtools/devtools_agent_filter.cc b/chromium/content/renderer/devtools/devtools_agent_filter.cc
index 1613ad8c477..fc9e34f8a8a 100644
--- a/chromium/content/renderer/devtools/devtools_agent_filter.cc
+++ b/chromium/content/renderer/devtools/devtools_agent_filter.cc
@@ -11,8 +11,8 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebDevToolsAgent.h"
-using WebKit::WebDevToolsAgent;
-using WebKit::WebString;
+using blink::WebDevToolsAgent;
+using blink::WebString;
namespace content {
diff --git a/chromium/content/renderer/devtools/devtools_client.cc b/chromium/content/renderer/devtools/devtools_client.cc
index 5793d2c7ebf..3d51312b8d0 100644
--- a/chromium/content/renderer/devtools/devtools_client.cc
+++ b/chromium/content/renderer/devtools/devtools_client.cc
@@ -16,10 +16,9 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebDevToolsFrontend.h"
#include "ui/base/ui_base_switches.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
-using WebKit::WebDevToolsFrontend;
-using WebKit::WebString;
+using blink::WebDevToolsFrontend;
+using blink::WebString;
namespace content {
@@ -31,7 +30,6 @@ DevToolsClient::DevToolsClient(RenderViewImpl* render_view)
render_view->webview(),
this,
ASCIIToUTF16(command_line.GetSwitchValueASCII(switches::kLang))));
- appcache::AddSupportedScheme(chrome::kChromeDevToolsScheme);
}
DevToolsClient::~DevToolsClient() {
diff --git a/chromium/content/renderer/devtools/devtools_client.h b/chromium/content/renderer/devtools/devtools_client.h
index 1c9d3f8fc20..be1e902cdff 100644
--- a/chromium/content/renderer/devtools/devtools_client.h
+++ b/chromium/content/renderer/devtools/devtools_client.h
@@ -12,7 +12,7 @@
#include "content/public/renderer/render_view_observer.h"
#include "third_party/WebKit/public/web/WebDevToolsFrontendClient.h"
-namespace WebKit {
+namespace blink {
class WebDevToolsFrontend;
class WebString;
}
@@ -29,7 +29,7 @@ class RenderViewImpl;
// code in glue
class CONTENT_EXPORT DevToolsClient
: public RenderViewObserver,
- NON_EXPORTED_BASE(public WebKit::WebDevToolsFrontendClient) {
+ NON_EXPORTED_BASE(public blink::WebDevToolsFrontendClient) {
public:
explicit DevToolsClient(RenderViewImpl* render_view);
virtual ~DevToolsClient();
@@ -39,14 +39,14 @@ class CONTENT_EXPORT DevToolsClient
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
// WebDevToolsFrontendClient implementation.
- virtual void sendMessageToBackend(const WebKit::WebString&) OVERRIDE;
- virtual void sendMessageToEmbedder(const WebKit::WebString&) OVERRIDE;
+ virtual void sendMessageToBackend(const blink::WebString&) OVERRIDE;
+ virtual void sendMessageToEmbedder(const blink::WebString&) OVERRIDE;
virtual bool isUnderTest() OVERRIDE;
void OnDispatchOnInspectorFrontend(const std::string& message);
- scoped_ptr<WebKit::WebDevToolsFrontend> web_tools_frontend_;
+ scoped_ptr<blink::WebDevToolsFrontend> web_tools_frontend_;
DISALLOW_COPY_AND_ASSIGN(DevToolsClient);
};
diff --git a/chromium/content/renderer/disambiguation_popup_helper.cc b/chromium/content/renderer/disambiguation_popup_helper.cc
index 88f2e51d11c..9fff7b9b99c 100644
--- a/chromium/content/renderer/disambiguation_popup_helper.cc
+++ b/chromium/content/renderer/disambiguation_popup_helper.cc
@@ -7,8 +7,8 @@
#include "third_party/WebKit/public/platform/WebRect.h"
#include "ui/gfx/size_conversions.h"
-using WebKit::WebRect;
-using WebKit::WebVector;
+using blink::WebRect;
+using blink::WebVector;
namespace {
diff --git a/chromium/content/renderer/disambiguation_popup_helper.h b/chromium/content/renderer/disambiguation_popup_helper.h
index 535683d691a..0238f8a562c 100644
--- a/chromium/content/renderer/disambiguation_popup_helper.h
+++ b/chromium/content/renderer/disambiguation_popup_helper.h
@@ -13,7 +13,7 @@ class Rect;
class Size;
}
-namespace WebKit {
+namespace blink {
struct WebRect;
}
@@ -24,7 +24,7 @@ class DisambiguationPopupHelper {
public:
CONTENT_EXPORT static float ComputeZoomAreaAndScaleFactor(
const gfx::Rect& tap_rect,
- const WebKit::WebVector<WebKit::WebRect>& target_rects,
+ const blink::WebVector<blink::WebRect>& target_rects,
const gfx::Size& screen_size,
const gfx::Size& visible_content_size,
float total_scale,
diff --git a/chromium/content/renderer/disambiguation_popup_helper_unittest.cc b/chromium/content/renderer/disambiguation_popup_helper_unittest.cc
index 0b6d0020ae3..8cbbe4b5ab3 100644
--- a/chromium/content/renderer/disambiguation_popup_helper_unittest.cc
+++ b/chromium/content/renderer/disambiguation_popup_helper_unittest.cc
@@ -33,7 +33,7 @@ class DisambiguationPopupHelperUnittest : public testing::Test {
TEST_F(DisambiguationPopupHelperUnittest, ClipByViewport) {
gfx::Rect tap_rect(1000, 1000, 10, 10);
- WebKit::WebVector<WebKit::WebRect> target_rects(static_cast<size_t>(1));
+ blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(1));
target_rects[0] = gfx::Rect(-20, -20, 10, 10);
gfx::Rect zoom_rect;
@@ -50,7 +50,7 @@ TEST_F(DisambiguationPopupHelperUnittest, ClipByViewport) {
TEST_F(DisambiguationPopupHelperUnittest, MiniTarget) {
gfx::Rect tap_rect(-5, -5, 20, 20);
- WebKit::WebVector<WebKit::WebRect> target_rects(static_cast<size_t>(1));
+ blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(1));
target_rects[0] = gfx::Rect(10, 10, 1, 1);
gfx::Rect zoom_rect;
@@ -68,7 +68,7 @@ TEST_F(DisambiguationPopupHelperUnittest, MiniTarget) {
TEST_F(DisambiguationPopupHelperUnittest, LongLinks) {
gfx::Rect tap_rect(10, 10, 20, 20);
- WebKit::WebVector<WebKit::WebRect> target_rects(static_cast<size_t>(2));
+ blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(2));
target_rects[0] = gfx::Rect(15, 15, 1000, 5);
target_rects[1] = gfx::Rect(15, 25, 1000, 5);
diff --git a/chromium/content/renderer/dom_serializer_browsertest.cc b/chromium/content/renderer/dom_serializer_browsertest.cc
index 69dfc6533be..16bd30fb77f 100644
--- a/chromium/content/renderer/dom_serializer_browsertest.cc
+++ b/chromium/content/renderer/dom_serializer_browsertest.cc
@@ -35,21 +35,21 @@
#include "third_party/WebKit/public/web/WebPageSerializerClient.h"
#include "third_party/WebKit/public/web/WebView.h"
-using WebKit::WebCString;
-using WebKit::WebData;
-using WebKit::WebDocument;
-using WebKit::WebElement;
-using WebKit::WebFrame;
-using WebKit::WebNode;
-using WebKit::WebNodeCollection;
-using WebKit::WebNodeList;
-using WebKit::WebPageSerializer;
-using WebKit::WebPageSerializerClient;
-using WebKit::WebNode;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebView;
-using WebKit::WebVector;
+using blink::WebCString;
+using blink::WebData;
+using blink::WebDocument;
+using blink::WebElement;
+using blink::WebFrame;
+using blink::WebNode;
+using blink::WebNodeCollection;
+using blink::WebNodeList;
+using blink::WebPageSerializer;
+using blink::WebPageSerializerClient;
+using blink::WebNode;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebView;
+using blink::WebVector;
namespace content {
@@ -150,7 +150,7 @@ class LoadObserver : public RenderViewObserver {
: RenderViewObserver(render_view),
quit_closure_(quit_closure) {}
- virtual void DidFinishLoad(WebKit::WebFrame* frame) OVERRIDE {
+ virtual void DidFinishLoad(blink::WebFrame* frame) OVERRIDE {
if (frame == render_view()->GetWebView()->mainFrame())
quit_closure_.Run();
}
@@ -269,18 +269,18 @@ class DomSerializerTests : public ContentBrowserTest,
// Find corresponding WebFrame according to page_url.
WebFrame* web_frame = FindSubFrameByURL(GetWebView(), page_url);
ASSERT_TRUE(web_frame != NULL);
- // Add input file URl to links_.
- links_.assign(&page_url,1);
- // Add dummy file path to local_path_.
+ WebVector<WebURL> links;
+ links.assign(&page_url, 1);
WebString file_path =
base::FilePath(FILE_PATH_LITERAL("c:\\dummy.htm")).AsUTF16Unsafe();
- local_paths_.assign(&file_path, 1);
+ WebVector<WebString> local_paths;
+ local_paths.assign(&file_path, 1);
// Start serializing DOM.
bool result = WebPageSerializer::serialize(web_frame,
recursive_serialization,
static_cast<WebPageSerializerClient*>(this),
- links_,
- local_paths_,
+ links,
+ local_paths,
local_directory_name_.AsUTF16Unsafe());
ASSERT_TRUE(result);
ASSERT_TRUE(serialized_);
@@ -770,11 +770,6 @@ class DomSerializerTests : public ContentBrowserTest,
SerializationFinishStatusMap serialization_finish_status_;
// Flag indicates whether the process of serializing DOM is finished or not.
bool serialized_;
- // The links_ contain dummy original URLs of all saved links.
- WebVector<WebURL> links_;
- // The local_paths_ contain dummy corresponding local file paths of all saved
- // links, which matched links_ one by one.
- WebVector<WebString> local_paths_;
// The local_directory_name_ is dummy relative path of directory which
// contain all saved auxiliary files included all sub frames and resources.
const base::FilePath local_directory_name_;
@@ -912,8 +907,12 @@ IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeHTMLDOMWithEntitiesInText) {
// Test situation of html entities in attribute value when serializing
// HTML DOM.
// This test started to fail at WebKit r65388. See http://crbug.com/52279.
+//
+// TODO(tiger@opera.com): Disabled in preparation of page serializer merge --
+// Some attributes are handled differently in the merged serializer.
+// Bug: http://crbug.com/328354
IN_PROC_BROWSER_TEST_F(DomSerializerTests,
- SerializeHTMLDOMWithEntitiesInAttributeValue) {
+ DISABLE_SerializeHTMLDOMWithEntitiesInAttributeValue) {
// Need to spin up the renderer and also navigate to a file url so that the
// renderer code doesn't attempt a fork when it sees a load to file scheme
// from non-file scheme.
@@ -947,7 +946,12 @@ IN_PROC_BROWSER_TEST_F(DomSerializerTests,
// When serializing, we should comment the BASE tag, append a new BASE tag.
// rewrite all the savable URLs to relative local path, and change other URLs
// to absolute URLs.
-IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeHTMLDOMWithBaseTag) {
+//
+// TODO(tiger@opera.com): Disabled in preparation of page serializer merge --
+// Base tags are handled a bit different in merged version.
+// Bug: http://crbug.com/328354
+IN_PROC_BROWSER_TEST_F(DomSerializerTests,
+ DISABLE_SerializeHTMLDOMWithBaseTag) {
base::FilePath page_file_path = GetTestFilePath(
"dom_serializer", "html_doc_has_base_tag.htm");
diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc b/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc
index a01d3c6f7fb..2923fcb1def 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc
+++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc
@@ -12,6 +12,12 @@
namespace content {
+namespace {
+
+static const int kMaxLogGetMessagesToSend = 16 * 1024;
+
+} // namespace
+
DOMStorageCachedArea::DOMStorageCachedArea(int64 namespace_id,
const GURL& origin,
DOMStorageProxy* proxy)
@@ -19,6 +25,7 @@ DOMStorageCachedArea::DOMStorageCachedArea(int64 namespace_id,
namespace_id_(namespace_id),
origin_(origin),
proxy_(proxy),
+ remaining_log_get_messages_(0),
weak_factory_(this) {}
DOMStorageCachedArea::~DOMStorageCachedArea() {}
@@ -38,7 +45,12 @@ base::NullableString16 DOMStorageCachedArea::GetItem(
int connection_id,
const base::string16& key) {
PrimeIfNeeded(connection_id);
- return map_->GetItem(key);
+ base::NullableString16 result = map_->GetItem(key);
+ if (remaining_log_get_messages_ > 0) {
+ remaining_log_get_messages_--;
+ proxy_->LogGetItem(connection_id, key, result);
+ }
+ return result;
}
bool DOMStorageCachedArea::SetItem(int connection_id,
@@ -155,9 +167,11 @@ void DOMStorageCachedArea::Prime(int connection_id) {
// Ignore all mutations until OnLoadComplete time.
ignore_all_mutations_ = true;
DOMStorageValuesMap values;
+ bool send_log_get_messages = false;
base::TimeTicks before = base::TimeTicks::Now();
proxy_->LoadArea(connection_id,
&values,
+ &send_log_get_messages,
base::Bind(&DOMStorageCachedArea::OnLoadComplete,
weak_factory_.GetWeakPtr()));
base::TimeDelta time_to_prime = base::TimeTicks::Now() - before;
@@ -167,6 +181,8 @@ void DOMStorageCachedArea::Prime(int connection_id) {
time_to_prime);
map_ = new DOMStorageMap(kPerStorageAreaQuota);
map_->SwapValues(&values);
+ if (send_log_get_messages)
+ remaining_log_get_messages_ = kMaxLogGetMessagesToSend;
size_t local_storage_size_kb = map_->bytes_used() / 1024;
// Track localStorage size, from 0-6MB. Note that the maximum size should be
diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area.h b/chromium/content/renderer/dom_storage/dom_storage_cached_area.h
index b9910388553..6942534cf87 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_cached_area.h
+++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area.h
@@ -51,6 +51,9 @@ class CONTENT_EXPORT DOMStorageCachedArea
size_t MemoryBytesUsedByCache() const;
+ // Resets the object back to its newly constructed state.
+ void Reset();
+
private:
friend class DOMStorageCachedAreaTest;
friend class base::RefCounted<DOMStorageCachedArea>;
@@ -63,9 +66,6 @@ class CONTENT_EXPORT DOMStorageCachedArea
Prime(connection_id);
}
- // Resets the object back to its newly constructed state.
- void Reset();
-
// Async completion callbacks for proxied operations.
// These are used to maintain cache consistency by preventing
// mutation events from other processes from overwriting local
@@ -86,6 +86,11 @@ class CONTENT_EXPORT DOMStorageCachedArea
GURL origin_;
scoped_refptr<DOMStorageMap> map_;
scoped_refptr<DOMStorageProxy> proxy_;
+ // Sometimes, we need to send messages to the browser for each get access,
+ // for logging purposes. However, we only do this for a fixed maximum number
+ // of gets. Here, we keep track of how many remaining get log messages we
+ // need to send.
+ int remaining_log_get_messages_;
base::WeakPtrFactory<DOMStorageCachedArea> weak_factory_;
};
diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc b/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc
index ada36d72b20..04b5a286edc 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc
+++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc
@@ -25,11 +25,13 @@ class MockProxy : public DOMStorageProxy {
virtual void LoadArea(int connection_id,
DOMStorageValuesMap* values,
+ bool* send_log_get_messages,
const CompletionCallback& callback) OVERRIDE {
pending_callbacks_.push_back(callback);
observed_load_area_ = true;
observed_connection_id_ = connection_id;
*values = load_area_return_values_;
+ *send_log_get_messages = false;
}
virtual void SetItem(int connection_id,
@@ -45,6 +47,11 @@ class MockProxy : public DOMStorageProxy {
observed_page_url_ = page_url;
}
+ virtual void LogGetItem(int connection_id,
+ const base::string16& key,
+ const base::NullableString16& value) OVERRIDE {
+ }
+
virtual void RemoveItem(int connection_id,
const base::string16& key,
const GURL& page_url,
diff --git a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc
index a8a37c989a4..477251c33a9 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc
+++ b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc
@@ -103,16 +103,20 @@ class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy {
void CloseCachedArea(DOMStorageCachedArea* area);
DOMStorageCachedArea* LookupCachedArea(
int64 namespace_id, const GURL& origin);
+ void ResetAllCachedAreas(int64 namespace_id);
void CompleteOnePendingCallback(bool success);
void Shutdown();
// DOMStorageProxy interface for use by DOMStorageCachedArea.
virtual void LoadArea(int connection_id, DOMStorageValuesMap* values,
+ bool* send_log_get_messages,
const CompletionCallback& callback) OVERRIDE;
- virtual void SetItem(int connection_id, const string16& key,
- const string16& value, const GURL& page_url,
+ virtual void SetItem(int connection_id, const base::string16& key,
+ const base::string16& value, const GURL& page_url,
const CompletionCallback& callback) OVERRIDE;
- virtual void RemoveItem(int connection_id, const string16& key,
+ virtual void LogGetItem(int connection_id, const base::string16& key,
+ const base::NullableString16& value) OVERRIDE;
+ virtual void RemoveItem(int connection_id, const base::string16& key,
const GURL& page_url,
const CompletionCallback& callback) OVERRIDE;
virtual void ClearArea(int connection_id,
@@ -125,9 +129,11 @@ class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy {
struct CachedAreaHolder {
scoped_refptr<DOMStorageCachedArea> area_;
int open_count_;
+ int64 namespace_id_;
CachedAreaHolder() : open_count_(0) {}
- CachedAreaHolder(DOMStorageCachedArea* area, int count)
- : area_(area), open_count_(count) {}
+ CachedAreaHolder(DOMStorageCachedArea* area, int count,
+ int64 namespace_id)
+ : area_(area), open_count_(count), namespace_id_(namespace_id) {}
};
typedef std::map<std::string, CachedAreaHolder> CachedAreaMap;
typedef std::list<CompletionCallback> CallbackList;
@@ -139,7 +145,7 @@ class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy {
// to more reliably commit changes during shutdown.
void PushPendingCallback(const CompletionCallback& callback) {
if (pending_callbacks_.empty())
- WebKit::Platform::current()->suddenTerminationChanged(false);
+ blink::Platform::current()->suddenTerminationChanged(false);
pending_callbacks_.push_back(callback);
}
@@ -147,7 +153,7 @@ class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy {
CompletionCallback callback = pending_callbacks_.front();
pending_callbacks_.pop_front();
if (pending_callbacks_.empty())
- WebKit::Platform::current()->suddenTerminationChanged(true);
+ blink::Platform::current()->suddenTerminationChanged(true);
return callback;
}
@@ -183,7 +189,7 @@ DOMStorageCachedArea* DomStorageDispatcher::ProxyImpl::OpenCachedArea(
}
scoped_refptr<DOMStorageCachedArea> area =
new DOMStorageCachedArea(namespace_id, origin, this);
- cached_areas_[key] = CachedAreaHolder(area.get(), 1);
+ cached_areas_[key] = CachedAreaHolder(area.get(), 1, namespace_id);
return area.get();
}
@@ -208,6 +214,15 @@ DOMStorageCachedArea* DomStorageDispatcher::ProxyImpl::LookupCachedArea(
return holder->area_.get();
}
+void DomStorageDispatcher::ProxyImpl::ResetAllCachedAreas(int64 namespace_id) {
+ for (CachedAreaMap::iterator it = cached_areas_.begin();
+ it != cached_areas_.end();
+ ++it) {
+ if (it->second.namespace_id_ == namespace_id)
+ it->second.area_->Reset();
+ }
+}
+
void DomStorageDispatcher::ProxyImpl::CompleteOnePendingCallback(bool success) {
PopPendingCallback().Run(success);
}
@@ -221,24 +236,30 @@ void DomStorageDispatcher::ProxyImpl::Shutdown() {
}
void DomStorageDispatcher::ProxyImpl::LoadArea(
- int connection_id, DOMStorageValuesMap* values,
+ int connection_id, DOMStorageValuesMap* values, bool* send_log_get_messages,
const CompletionCallback& callback) {
PushPendingCallback(callback);
throttling_filter_->SendThrottled(new DOMStorageHostMsg_LoadStorageArea(
- connection_id, values));
+ connection_id, values, send_log_get_messages));
}
void DomStorageDispatcher::ProxyImpl::SetItem(
- int connection_id, const string16& key,
- const string16& value, const GURL& page_url,
+ int connection_id, const base::string16& key,
+ const base::string16& value, const GURL& page_url,
const CompletionCallback& callback) {
PushPendingCallback(callback);
throttling_filter_->SendThrottled(new DOMStorageHostMsg_SetItem(
connection_id, key, value, page_url));
}
+void DomStorageDispatcher::ProxyImpl::LogGetItem(
+ int connection_id, const base::string16& key,
+ const base::NullableString16& value) {
+ sender_->Send(new DOMStorageHostMsg_LogGetItem(connection_id, key, value));
+}
+
void DomStorageDispatcher::ProxyImpl::RemoveItem(
- int connection_id, const string16& key, const GURL& page_url,
+ int connection_id, const base::string16& key, const GURL& page_url,
const CompletionCallback& callback) {
PushPendingCallback(callback);
throttling_filter_->SendThrottled(new DOMStorageHostMsg_RemoveItem(
@@ -284,6 +305,8 @@ bool DomStorageDispatcher::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(DOMStorageMsg_Event, OnStorageEvent)
IPC_MESSAGE_HANDLER(DOMStorageMsg_AsyncOperationComplete,
OnAsyncOperationComplete)
+ IPC_MESSAGE_HANDLER(DOMStorageMsg_ResetCachedValues,
+ OnResetCachedValues)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -306,7 +329,7 @@ void DomStorageDispatcher::OnStorageEvent(
}
if (params.namespace_id == kLocalStorageNamespaceId) {
- WebKit::WebStorageEventDispatcher::dispatchLocalStorageEvent(
+ blink::WebStorageEventDispatcher::dispatchLocalStorageEvent(
params.key,
params.old_value,
params.new_value,
@@ -317,7 +340,7 @@ void DomStorageDispatcher::OnStorageEvent(
} else {
WebStorageNamespaceImpl
session_namespace_for_event_dispatch(params.namespace_id);
- WebKit::WebStorageEventDispatcher::dispatchSessionStorageEvent(
+ blink::WebStorageEventDispatcher::dispatchSessionStorageEvent(
params.key,
params.old_value,
params.new_value,
@@ -333,4 +356,8 @@ void DomStorageDispatcher::OnAsyncOperationComplete(bool success) {
proxy_->CompleteOnePendingCallback(success);
}
+void DomStorageDispatcher::OnResetCachedValues(int64 namespace_id) {
+ proxy_->ResetAllCachedAreas(namespace_id);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.h b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.h
index f395d575f5c..70595ca12fd 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.h
+++ b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.h
@@ -42,6 +42,7 @@ class DomStorageDispatcher {
// IPC message handlers
void OnStorageEvent(const DOMStorageMsg_Event_Params& params);
void OnAsyncOperationComplete(bool success);
+ void OnResetCachedValues(int64 namespace_id);
scoped_refptr<ProxyImpl> proxy_;
};
diff --git a/chromium/content/renderer/dom_storage/dom_storage_proxy.h b/chromium/content/renderer/dom_storage/dom_storage_proxy.h
index 80cd87cdcc4..118aab34da3 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_proxy.h
+++ b/chromium/content/renderer/dom_storage/dom_storage_proxy.h
@@ -21,6 +21,7 @@ class DOMStorageProxy : public base::RefCounted<DOMStorageProxy> {
virtual void LoadArea(int connection_id,
DOMStorageValuesMap* values,
+ bool* send_log_get_messages,
const CompletionCallback& callback) = 0;
virtual void SetItem(int connection_id,
@@ -29,6 +30,10 @@ class DOMStorageProxy : public base::RefCounted<DOMStorageProxy> {
const GURL& page_url,
const CompletionCallback& callback) = 0;
+ virtual void LogGetItem(int connection_id,
+ const base::string16& key,
+ const base::NullableString16& value) = 0;
+
virtual void RemoveItem(int connection_id,
const base::string16& key,
const GURL& page_url,
diff --git a/chromium/content/renderer/dom_storage/webstoragearea_impl.cc b/chromium/content/renderer/dom_storage/webstoragearea_impl.cc
index d5bf07dbaf9..c3075352dd5 100644
--- a/chromium/content/renderer/dom_storage/webstoragearea_impl.cc
+++ b/chromium/content/renderer/dom_storage/webstoragearea_impl.cc
@@ -14,8 +14,8 @@
#include "content/renderer/render_thread_impl.h"
#include "third_party/WebKit/public/platform/WebURL.h"
-using WebKit::WebString;
-using WebKit::WebURL;
+using blink::WebString;
+using blink::WebURL;
namespace content {
diff --git a/chromium/content/renderer/dom_storage/webstoragearea_impl.h b/chromium/content/renderer/dom_storage/webstoragearea_impl.h
index 7854562603e..24056ce26e5 100644
--- a/chromium/content/renderer/dom_storage/webstoragearea_impl.h
+++ b/chromium/content/renderer/dom_storage/webstoragearea_impl.h
@@ -16,7 +16,7 @@ namespace content {
class DOMStorageCachedArea;
-class WebStorageAreaImpl : public WebKit::WebStorageArea {
+class WebStorageAreaImpl : public blink::WebStorageArea {
public:
static WebStorageAreaImpl* FromConnectionId(int id);
@@ -25,14 +25,14 @@ class WebStorageAreaImpl : public WebKit::WebStorageArea {
// See WebStorageArea.h for documentation on these functions.
virtual unsigned length();
- virtual WebKit::WebString key(unsigned index);
- virtual WebKit::WebString getItem(const WebKit::WebString& key);
+ virtual blink::WebString key(unsigned index);
+ virtual blink::WebString getItem(const blink::WebString& key);
virtual void setItem(
- const WebKit::WebString& key, const WebKit::WebString& value,
- const WebKit::WebURL& page_url, WebStorageArea::Result& result);
+ const blink::WebString& key, const blink::WebString& value,
+ const blink::WebURL& page_url, WebStorageArea::Result& result);
virtual void removeItem(
- const WebKit::WebString& key, const WebKit::WebURL& page_url);
- virtual void clear(const WebKit::WebURL& url);
+ const blink::WebString& key, const blink::WebURL& page_url);
+ virtual void clear(const blink::WebURL& url);
virtual size_t memoryBytesUsedByCache() const;
private:
diff --git a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc
index d5f1dc5bc8e..531263d6f84 100644
--- a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc
+++ b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc
@@ -10,9 +10,9 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "url/gurl.h"
-using WebKit::WebStorageArea;
-using WebKit::WebStorageNamespace;
-using WebKit::WebString;
+using blink::WebStorageArea;
+using blink::WebStorageNamespace;
+using blink::WebString;
namespace content {
diff --git a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h
index 52c1b355f9b..364e6480352 100644
--- a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h
+++ b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h
@@ -10,7 +10,7 @@
namespace content {
-class WebStorageNamespaceImpl : public WebKit::WebStorageNamespace {
+class WebStorageNamespaceImpl : public blink::WebStorageNamespace {
public:
// The default constructor creates a local storage namespace, the second
// constructor should be used for session storage namepaces.
@@ -19,9 +19,9 @@ class WebStorageNamespaceImpl : public WebKit::WebStorageNamespace {
virtual ~WebStorageNamespaceImpl();
// See WebStorageNamespace.h for documentation on these functions.
- virtual WebKit::WebStorageArea* createStorageArea(
- const WebKit::WebString& origin);
- virtual WebKit::WebStorageNamespace* copy();
+ virtual blink::WebStorageArea* createStorageArea(
+ const blink::WebString& origin);
+ virtual blink::WebStorageNamespace* copy();
virtual bool isSameNamespace(const WebStorageNamespace&) const;
private:
diff --git a/chromium/content/renderer/drop_data_builder.cc b/chromium/content/renderer/drop_data_builder.cc
index 56bc81a9964..f9e5c420d3c 100644
--- a/chromium/content/renderer/drop_data_builder.cc
+++ b/chromium/content/renderer/drop_data_builder.cc
@@ -11,15 +11,15 @@
#include "third_party/WebKit/public/platform/WebVector.h"
#include "ui/base/clipboard/clipboard.h"
-using WebKit::WebDragData;
-using WebKit::WebVector;
+using blink::WebDragData;
+using blink::WebVector;
namespace content {
//static
DropData DropDataBuilder::Build(const WebDragData& drag_data) {
DropData result;
- result.referrer_policy = WebKit::WebReferrerPolicyDefault;
+ result.referrer_policy = blink::WebReferrerPolicyDefault;
const WebVector<WebDragData::Item>& item_list = drag_data.items();
for (size_t i = 0; i < item_list.size(); ++i) {
diff --git a/chromium/content/renderer/drop_data_builder.h b/chromium/content/renderer/drop_data_builder.h
index 4870d47f927..2dfb7b92375 100644
--- a/chromium/content/renderer/drop_data_builder.h
+++ b/chromium/content/renderer/drop_data_builder.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_RENDERER_DROP_DATA_BUILDER_H_
#define CONTENT_RENDERER_DROP_DATA_BUILDER_H_
-namespace WebKit {
+namespace blink {
class WebDragData;
}
@@ -14,7 +14,7 @@ struct DropData;
class DropDataBuilder {
public:
- static DropData Build(const WebKit::WebDragData& data);
+ static DropData Build(const blink::WebDragData& data);
};
} // namespace content
diff --git a/chromium/content/renderer/external_popup_menu.cc b/chromium/content/renderer/external_popup_menu.cc
index 08d71e98261..01909131341 100644
--- a/chromium/content/renderer/external_popup_menu.cc
+++ b/chromium/content/renderer/external_popup_menu.cc
@@ -14,16 +14,31 @@ namespace content {
ExternalPopupMenu::ExternalPopupMenu(
RenderViewImpl* render_view,
- const WebKit::WebPopupMenuInfo& popup_menu_info,
- WebKit::WebExternalPopupMenuClient* popup_menu_client)
+ const blink::WebPopupMenuInfo& popup_menu_info,
+ blink::WebExternalPopupMenuClient* popup_menu_client)
: render_view_(render_view),
popup_menu_info_(popup_menu_info),
- popup_menu_client_(popup_menu_client) {
+ popup_menu_client_(popup_menu_client),
+ origin_scale_for_emulation_(0) {
}
-void ExternalPopupMenu::show(const WebKit::WebRect& bounds) {
+void ExternalPopupMenu::SetOriginScaleAndOffsetForEmulation(
+ float scale, const gfx::Point& offset) {
+ origin_scale_for_emulation_ = scale;
+ origin_offset_for_emulation_ = offset;
+}
+
+void ExternalPopupMenu::show(const blink::WebRect& bounds) {
+ blink::WebRect rect = bounds;
+ if (origin_scale_for_emulation_) {
+ rect.x *= origin_scale_for_emulation_;
+ rect.y *= origin_scale_for_emulation_;
+ }
+ rect.x += origin_offset_for_emulation_.x();
+ rect.y += origin_offset_for_emulation_.y();
+
ViewHostMsg_ShowPopup_Params popup_params;
- popup_params.bounds = bounds;
+ popup_params.bounds = rect;
popup_params.item_height = popup_menu_info_.itemHeight;
popup_params.item_font_size = popup_menu_info_.itemFontSize;
popup_params.selected_item = popup_menu_info_.selectedIndex;
diff --git a/chromium/content/renderer/external_popup_menu.h b/chromium/content/renderer/external_popup_menu.h
index 729205fba9f..32137008416 100644
--- a/chromium/content/renderer/external_popup_menu.h
+++ b/chromium/content/renderer/external_popup_menu.h
@@ -10,22 +10,26 @@
#include "base/basictypes.h"
#include "third_party/WebKit/public/web/WebExternalPopupMenu.h"
#include "third_party/WebKit/public/web/WebPopupMenuInfo.h"
+#include "ui/gfx/point.h"
-namespace WebKit {
+namespace blink {
class WebExternalPopupMenuClient;
}
namespace content {
class RenderViewImpl;
-class ExternalPopupMenu : public WebKit::WebExternalPopupMenu {
+class ExternalPopupMenu : public blink::WebExternalPopupMenu {
public:
ExternalPopupMenu(RenderViewImpl* render_view,
- const WebKit::WebPopupMenuInfo& popup_menu_info,
- WebKit::WebExternalPopupMenuClient* popup_menu_client);
+ const blink::WebPopupMenuInfo& popup_menu_info,
+ blink::WebExternalPopupMenuClient* popup_menu_client);
virtual ~ExternalPopupMenu() {}
+ void SetOriginScaleAndOffsetForEmulation(
+ float scale, const gfx::Point& offset);
+
#if defined(OS_MACOSX)
// Called when the user has selected an item. |selected_item| is -1 if the
// user canceled the popup.
@@ -37,14 +41,19 @@ class ExternalPopupMenu : public WebKit::WebExternalPopupMenu {
void DidSelectItems(bool canceled, const std::vector<int>& selected_indices);
#endif
- // WebKit::WebExternalPopupMenu implementation:
- virtual void show(const WebKit::WebRect& bounds);
+ // blink::WebExternalPopupMenu implementation:
+ virtual void show(const blink::WebRect& bounds);
virtual void close();
private:
RenderViewImpl* render_view_;
- WebKit::WebPopupMenuInfo popup_menu_info_;
- WebKit::WebExternalPopupMenuClient* popup_menu_client_;
+ blink::WebPopupMenuInfo popup_menu_info_;
+ blink::WebExternalPopupMenuClient* popup_menu_client_;
+
+ // Popups may be displaced when screen metrics emulation is enabled.
+ // These scale and offset are used to properly adjust popup position.
+ float origin_scale_for_emulation_;
+ gfx::Point origin_offset_for_emulation_;
DISALLOW_COPY_AND_ASSIGN(ExternalPopupMenu);
};
diff --git a/chromium/content/renderer/external_popup_menu_browsertest.cc b/chromium/content/renderer/external_popup_menu_browsertest.cc
index 30e539732d9..2e3e66456d2 100644
--- a/chromium/content/renderer/external_popup_menu_browsertest.cc
+++ b/chromium/content/renderer/external_popup_menu_browsertest.cc
@@ -31,7 +31,7 @@ class ExternalPopupMenuTest : public RenderViewTest {
virtual void SetUp() {
RenderViewTest::SetUp();
// We need to set this explictly as RenderMain is not run.
- WebKit::WebView::setUseExternalPopupMenus(true);
+ blink::WebView::setUseExternalPopupMenus(true);
std::string html = "<select id='mySelect' onchange='selectChanged(this)'>"
" <option>zero</option>"
@@ -52,12 +52,12 @@ class ExternalPopupMenuTest : public RenderViewTest {
LoadHTML(html.c_str());
// Set a minimum size and give focus so simulated events work.
- view()->webwidget()->resize(WebKit::WebSize(500, 500));
+ view()->webwidget()->resize(blink::WebSize(500, 500));
view()->webwidget()->setFocus(true);
}
int GetSelectedIndex() {
- string16 script(ASCIIToUTF16(kSelectID));
+ base::string16 script(ASCIIToUTF16(kSelectID));
script.append(ASCIIToUTF16(".selectedIndex"));
int selected_index = -1;
ExecuteJavaScriptAndReturnIntValue(script, &selected_index);
diff --git a/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.cc b/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.cc
index cbcab0900bd..0fef535e752 100644
--- a/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.cc
+++ b/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.cc
@@ -6,12 +6,14 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "content/renderer/fetchers/resource_fetcher.h"
+#include "base/time/time.h"
+#include "content/public/renderer/resource_fetcher.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
-using WebKit::WebFrame;
-using WebKit::WebURLError;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
+using blink::WebFrame;
+using blink::WebURLError;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
namespace content {
@@ -29,19 +31,16 @@ AltErrorPageResourceFetcher::AltErrorPageResourceFetcher(
callback_(callback),
original_request_(original_request),
original_error_(original_error) {
- fetcher_.reset(new ResourceFetcherWithTimeout(
- url, frame, WebURLRequest::TargetIsMainFrame, kDownloadTimeoutSec,
+ fetcher_.reset(ResourceFetcher::Create(
+ url, frame, WebURLRequest::TargetIsMainFrame,
base::Bind(&AltErrorPageResourceFetcher::OnURLFetchComplete,
base::Unretained(this))));
+ fetcher_->SetTimeout(base::TimeDelta::FromSeconds(kDownloadTimeoutSec));
}
AltErrorPageResourceFetcher::~AltErrorPageResourceFetcher() {
}
-void AltErrorPageResourceFetcher::Cancel() {
- fetcher_->Cancel();
-}
-
void AltErrorPageResourceFetcher::OnURLFetchComplete(
const WebURLResponse& response,
const std::string& data) {
diff --git a/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.h b/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.h
index 6d828572eec..5f23f288028 100644
--- a/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.h
+++ b/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.h
@@ -11,13 +11,13 @@
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "url/gurl.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebURLResponse;
}
namespace content {
-class ResourceFetcherWithTimeout;
+class ResourceFetcher;
// Used for downloading alternate dns error pages. Once downloading is done
// (or fails), the webview delegate is notified.
@@ -26,39 +26,36 @@ class AltErrorPageResourceFetcher {
// This will be called when the alternative error page has been fetched,
// successfully or not. If there is a failure, the third parameter (the
// data) will be empty.
- typedef base::Callback<void(WebKit::WebFrame*,
- const WebKit::WebURLRequest&,
- const WebKit::WebURLError&,
+ typedef base::Callback<void(blink::WebFrame*,
+ const blink::WebURLRequest&,
+ const blink::WebURLError&,
const std::string&)> Callback;
AltErrorPageResourceFetcher(
const GURL& url,
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& original_request,
- const WebKit::WebURLError& original_error,
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& original_request,
+ const blink::WebURLError& original_error,
const Callback& callback);
~AltErrorPageResourceFetcher();
- // Stop any pending loads.
- void Cancel();
-
private:
- void OnURLFetchComplete(const WebKit::WebURLResponse& response,
+ void OnURLFetchComplete(const blink::WebURLResponse& response,
const std::string& data);
// Does the actual fetching.
- scoped_ptr<ResourceFetcherWithTimeout> fetcher_;
+ scoped_ptr<ResourceFetcher> fetcher_;
- WebKit::WebFrame* frame_;
+ blink::WebFrame* frame_;
Callback callback_;
// The original request. If loading the alternate error page fails, it's
// needed to generate the error page.
- WebKit::WebURLRequest original_request_;
+ blink::WebURLRequest original_request_;
// The error associated with this load. If there's an error talking with the
// alt error page server, we need this to complete the original load.
- WebKit::WebURLError original_error_;
+ blink::WebURLError original_error_;
DISALLOW_COPY_AND_ASSIGN(AltErrorPageResourceFetcher);
};
diff --git a/chromium/content/renderer/fetchers/image_resource_fetcher.cc b/chromium/content/renderer/fetchers/image_resource_fetcher.cc
index 0ce0d4e4242..f43b3d84e84 100644
--- a/chromium/content/renderer/fetchers/image_resource_fetcher.cc
+++ b/chromium/content/renderer/fetchers/image_resource_fetcher.cc
@@ -8,13 +8,15 @@
#include "base/bind_helpers.h"
#include "base/debug/crash_logging.h"
#include "content/child/image_decoder.h"
+#include "content/public/renderer/resource_fetcher.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/size.h"
-using WebKit::WebFrame;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
+using blink::WebFrame;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
namespace content {
@@ -29,7 +31,7 @@ ImageResourceFetcher::ImageResourceFetcher(
id_(id),
image_url_(image_url),
image_size_(image_size) {
- fetcher_.reset(new ResourceFetcher(
+ fetcher_.reset(ResourceFetcher::Create(
image_url, frame, target_type,
base::Bind(&ImageResourceFetcher::OnURLFetchComplete,
base::Unretained(this))));
@@ -39,8 +41,6 @@ ImageResourceFetcher::ImageResourceFetcher(
}
ImageResourceFetcher::~ImageResourceFetcher() {
- if (!fetcher_->completed())
- fetcher_->Cancel();
}
void ImageResourceFetcher::OnURLFetchComplete(
diff --git a/chromium/content/renderer/fetchers/image_resource_fetcher.h b/chromium/content/renderer/fetchers/image_resource_fetcher.h
index 2ddb20da540..2edcf3296fc 100644
--- a/chromium/content/renderer/fetchers/image_resource_fetcher.h
+++ b/chromium/content/renderer/fetchers/image_resource_fetcher.h
@@ -7,12 +7,21 @@
#include "base/basictypes.h"
#include "base/callback.h"
-#include "content/renderer/fetchers/resource_fetcher.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "url/gurl.h"
class SkBitmap;
+namespace blink {
+class WebFrame;
+class WebURLResponse;
+}
+
namespace content {
+class ResourceFetcher;
+
// ImageResourceFetcher handles downloading an image for a webview. Once
// downloading is done the supplied callback is notified. ImageResourceFetcher
// is used to download the favicon and images for web apps.
@@ -22,10 +31,10 @@ class ImageResourceFetcher {
ImageResourceFetcher(
const GURL& image_url,
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
int id,
int image_size,
- WebKit::WebURLRequest::TargetType target_type,
+ blink::WebURLRequest::TargetType target_type,
const Callback& callback);
virtual ~ImageResourceFetcher();
@@ -38,7 +47,7 @@ class ImageResourceFetcher {
private:
// ResourceFetcher::Callback. Decodes the image and invokes callback_.
- void OnURLFetchComplete(const WebKit::WebURLResponse& response,
+ void OnURLFetchComplete(const blink::WebURLResponse& response,
const std::string& data);
Callback callback_;
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 304abe890d7..ea0e6d03052 100644
--- a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
+++ b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
@@ -7,13 +7,15 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "content/child/image_decoder.h"
+#include "content/public/renderer/resource_fetcher.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/size.h"
-using WebKit::WebFrame;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
+using blink::WebFrame;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
namespace content {
@@ -27,15 +29,13 @@ MultiResolutionImageResourceFetcher::MultiResolutionImageResourceFetcher(
id_(id),
http_status_code_(0),
image_url_(image_url) {
- fetcher_.reset(new ResourceFetcher(
+ fetcher_.reset(ResourceFetcher::Create(
image_url, frame, target_type,
base::Bind(&MultiResolutionImageResourceFetcher::OnURLFetchComplete,
base::Unretained(this))));
}
MultiResolutionImageResourceFetcher::~MultiResolutionImageResourceFetcher() {
- if (!fetcher_->completed())
- fetcher_->Cancel();
}
void MultiResolutionImageResourceFetcher::OnURLFetchComplete(
diff --git a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h
index 3e7c326b496..1b329500342 100644
--- a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h
+++ b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h
@@ -5,28 +5,38 @@
#ifndef CONTENT_RENDERER_FETCHERS_MULTI_RESOLUTION_IMAGE_RESOURCE_FETCHER_H_
#define CONTENT_RENDERER_FETCHERS_MULTI_RESOLUTION_IMAGE_RESOURCE_FETCHER_H_
+#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/callback.h"
-#include "content/renderer/fetchers/resource_fetcher.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "url/gurl.h"
class SkBitmap;
+namespace blink {
+class WebFrame;
+class WebURLResponse;
+}
+
namespace content {
+class ResourceFetcher;
+
// A resource fetcher that returns all (differently-sized) frames in
// an image. Useful for favicons.
-class MultiResolutionImageResourceFetcher{
+class MultiResolutionImageResourceFetcher {
public:
typedef base::Callback<void(MultiResolutionImageResourceFetcher*,
const std::vector<SkBitmap>&)> Callback;
MultiResolutionImageResourceFetcher(
const GURL& image_url,
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
int id,
- WebKit::WebURLRequest::TargetType target_type,
+ blink::WebURLRequest::TargetType target_type,
const Callback& callback);
virtual ~MultiResolutionImageResourceFetcher();
@@ -42,7 +52,7 @@ class MultiResolutionImageResourceFetcher{
private:
// ResourceFetcher::Callback. Decodes the image and invokes callback_.
- void OnURLFetchComplete(const WebKit::WebURLResponse& response,
+ void OnURLFetchComplete(const blink::WebURLResponse& response,
const std::string& data);
Callback callback_;
diff --git a/chromium/content/renderer/fetchers/resource_fetcher.h b/chromium/content/renderer/fetchers/resource_fetcher.h
deleted file mode 100644
index 5900973adda..00000000000
--- a/chromium/content/renderer/fetchers/resource_fetcher.h
+++ /dev/null
@@ -1,135 +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.
-//
-// A wrapper around ResourceHandle and ResourceHandleClient that simplifies
-// the download of an HTTP object. The interface is modeled after URLFetcher
-// in the /chrome/browser.
-//
-// ResourceFetcher::Delegate::OnURLFetchComplete will be called async after
-// the ResourceFetcher object is created.
-
-#ifndef CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_H_
-#define CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/timer/timer.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "url/gurl.h"
-
-class GURL;
-
-namespace WebKit {
-class WebFrame;
-class WebURLLoader;
-struct WebURLError;
-}
-
-namespace content {
-
-class CONTENT_EXPORT ResourceFetcher
- : NON_EXPORTED_BASE(public WebKit::WebURLLoaderClient) {
- public:
- // This will be called when the URL has been fetched, successfully or not.
- // If there is a failure, response and data will both be empty. |response|
- // and |data| are both valid until the URLFetcher instance is destroyed.
- typedef base::Callback<void(const WebKit::WebURLResponse&,
- const std::string&)> Callback;
-
- // We need a frame to make requests.
- ResourceFetcher(
- const GURL& url, WebKit::WebFrame* frame,
- WebKit::WebURLRequest::TargetType target_type,
- const Callback& callback);
- virtual ~ResourceFetcher();
-
- // Stop the request and don't call the callback.
- void Cancel();
-
- bool completed() const { return completed_; }
-
- protected:
- // WebURLLoaderClient methods:
- virtual void willSendRequest(
- WebKit::WebURLLoader* loader, WebKit::WebURLRequest& new_request,
- const WebKit::WebURLResponse& redirect_response);
- virtual void didSendData(
- WebKit::WebURLLoader* loader, unsigned long long bytes_sent,
- unsigned long long total_bytes_to_be_sent);
- virtual void didReceiveResponse(
- WebKit::WebURLLoader* loader, const WebKit::WebURLResponse& response);
- virtual void didReceiveCachedMetadata(
- WebKit::WebURLLoader* loader, const char* data, int data_length);
-
- virtual void didReceiveData(
- WebKit::WebURLLoader* loader, const char* data, int data_length,
- int encoded_data_length);
- virtual void didFinishLoading(
- WebKit::WebURLLoader* loader, double finishTime);
- virtual void didFail(
- WebKit::WebURLLoader* loader, const WebKit::WebURLError& error);
-
- scoped_ptr<WebKit::WebURLLoader> loader_;
-
- // URL we're fetching
- GURL url_;
-
- // Target type
- WebKit::WebURLRequest::TargetType target_type_;
-
- // A copy of the original resource response
- WebKit::WebURLResponse response_;
-
- // Set to true once the request is compelte.
- bool completed_;
-
- private:
- // Start the actual download.
- void Start(WebKit::WebFrame* frame);
-
- void RunCallback(const WebKit::WebURLResponse& response,
- const std::string& data);
-
- // Callback when we're done
- Callback callback_;
-
- // Buffer to hold the content from the server.
- std::string data_;
-
- // Buffer to hold metadata from the cache.
- std::string metadata_;
-};
-
-/////////////////////////////////////////////////////////////////////////////
-// A resource fetcher with a timeout
-class CONTENT_EXPORT ResourceFetcherWithTimeout
- : NON_EXPORTED_BASE(public ResourceFetcher) {
- public:
- ResourceFetcherWithTimeout(const GURL& url,
- WebKit::WebFrame* frame,
- WebKit::WebURLRequest::TargetType target_type,
- int timeout_secs,
- const Callback& callback);
- virtual ~ResourceFetcherWithTimeout();
-
- private:
- // Callback for timer that limits how long we wait for the alternate error
- // page server. If this timer fires and the request hasn't completed, we
- // kill the request.
- void TimeoutFired();
-
- // Limit how long we wait for the alternate error page server.
- base::OneShotTimer<ResourceFetcherWithTimeout> timeout_timer_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_H_
diff --git a/chromium/content/renderer/fetchers/resource_fetcher.cc b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
index 455f59eb272..5c59de3739d 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher.cc
+++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/renderer/fetchers/resource_fetcher.h"
+#include "content/renderer/fetchers/resource_fetcher_impl.h"
#include "base/logging.h"
+#include "base/time/time.h"
#include "third_party/WebKit/public/platform/Platform.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
@@ -15,51 +16,59 @@
#include "third_party/WebKit/public/web/WebKit.h"
using base::TimeDelta;
-using WebKit::WebFrame;
-using WebKit::WebURLError;
-using WebKit::WebURLLoader;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
+using blink::WebFrame;
+using blink::WebURLError;
+using blink::WebURLLoader;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
namespace content {
-ResourceFetcher::ResourceFetcher(const GURL& url, WebFrame* frame,
- WebURLRequest::TargetType target_type,
- const Callback& callback)
- : url_(url),
- target_type_(target_type),
- completed_(false),
+// static
+ResourceFetcher* ResourceFetcher::Create(
+ const GURL& url, WebFrame* frame, WebURLRequest::TargetType target_type,
+ const Callback& callback) {
+ return new ResourceFetcherImpl(url, frame, target_type, callback);
+}
+
+ResourceFetcherImpl::ResourceFetcherImpl(const GURL& url, WebFrame* frame,
+ WebURLRequest::TargetType target_type,
+ const Callback& callback)
+ : completed_(false),
callback_(callback) {
// Can't do anything without a frame. However, delegate can be NULL (so we
// can do a http request and ignore the results).
DCHECK(frame);
- Start(frame);
+ Start(url, frame, target_type);
}
-ResourceFetcher::~ResourceFetcher() {
+ResourceFetcherImpl::~ResourceFetcherImpl() {
if (!completed_ && loader_)
loader_->cancel();
}
-void ResourceFetcher::Cancel() {
- if (!completed_) {
- loader_->cancel();
- completed_ = true;
- }
+void ResourceFetcherImpl::SetTimeout(const base::TimeDelta& timeout) {
+ DCHECK(loader_);
+ DCHECK(!completed_);
+ timeout_timer_.Start(FROM_HERE, timeout, this,
+ &ResourceFetcherImpl::TimeoutFired);
}
-void ResourceFetcher::Start(WebFrame* frame) {
- WebURLRequest request(url_);
- request.setTargetType(target_type_);
+void ResourceFetcherImpl::Start(const GURL& url, WebFrame* frame,
+ WebURLRequest::TargetType target_type) {
+ WebURLRequest request(url);
+ request.setTargetType(target_type);
request.setFirstPartyForCookies(frame->document().firstPartyForCookies());
frame->dispatchWillSendRequest(request);
- loader_.reset(WebKit::Platform::current()->createURLLoader());
+ loader_.reset(blink::Platform::current()->createURLLoader());
loader_->loadAsynchronously(request, this);
}
-void ResourceFetcher::RunCallback(const WebURLResponse& response,
- const std::string& data) {
+void ResourceFetcherImpl::RunCallback(const WebURLResponse& response,
+ const std::string& data) {
+ completed_ = true;
+ timeout_timer_.Stop();
if (callback_.is_null())
return;
@@ -69,26 +78,32 @@ void ResourceFetcher::RunCallback(const WebURLResponse& response,
callback.Run(response, data);
}
+void ResourceFetcherImpl::TimeoutFired() {
+ DCHECK(!completed_);
+ loader_->cancel();
+ RunCallback(WebURLResponse(), std::string());
+}
+
/////////////////////////////////////////////////////////////////////////////
// WebURLLoaderClient methods
-void ResourceFetcher::willSendRequest(
+void ResourceFetcherImpl::willSendRequest(
WebURLLoader* loader, WebURLRequest& new_request,
const WebURLResponse& redirect_response) {
}
-void ResourceFetcher::didSendData(
+void ResourceFetcherImpl::didSendData(
WebURLLoader* loader, unsigned long long bytes_sent,
unsigned long long total_bytes_to_be_sent) {
}
-void ResourceFetcher::didReceiveResponse(
+void ResourceFetcherImpl::didReceiveResponse(
WebURLLoader* loader, const WebURLResponse& response) {
DCHECK(!completed_);
response_ = response;
}
-void ResourceFetcher::didReceiveData(
+void ResourceFetcherImpl::didReceiveData(
WebURLLoader* loader, const char* data, int data_length,
int encoded_data_length) {
DCHECK(!completed_);
@@ -97,7 +112,7 @@ void ResourceFetcher::didReceiveData(
data_.append(data, data_length);
}
-void ResourceFetcher::didReceiveCachedMetadata(
+void ResourceFetcherImpl::didReceiveCachedMetadata(
WebURLLoader* loader, const char* data, int data_length) {
DCHECK(!completed_);
DCHECK(data_length > 0);
@@ -105,41 +120,19 @@ void ResourceFetcher::didReceiveCachedMetadata(
metadata_.assign(data, data_length);
}
-void ResourceFetcher::didFinishLoading(
+void ResourceFetcherImpl::didFinishLoading(
WebURLLoader* loader, double finishTime) {
DCHECK(!completed_);
- completed_ = true;
RunCallback(response_, data_);
}
-void ResourceFetcher::didFail(WebURLLoader* loader, const WebURLError& error) {
+void ResourceFetcherImpl::didFail(WebURLLoader* loader,
+ const WebURLError& error) {
DCHECK(!completed_);
- completed_ = true;
// Go ahead and tell our delegate that we're done.
RunCallback(WebURLResponse(), std::string());
}
-/////////////////////////////////////////////////////////////////////////////
-// A resource fetcher with a timeout
-
-ResourceFetcherWithTimeout::ResourceFetcherWithTimeout(
- const GURL& url, WebFrame* frame, WebURLRequest::TargetType target_type,
- int timeout_secs, const Callback& callback)
- : ResourceFetcher(url, frame, target_type, callback) {
- timeout_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(timeout_secs), this,
- &ResourceFetcherWithTimeout::TimeoutFired);
-}
-
-ResourceFetcherWithTimeout::~ResourceFetcherWithTimeout() {
-}
-
-void ResourceFetcherWithTimeout::TimeoutFired() {
- if (!completed_) {
- loader_->cancel();
- didFail(NULL, WebURLError());
- }
-}
-
} // namespace content
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.h b/chromium/content/renderer/fetchers/resource_fetcher_impl.h
new file mode 100644
index 00000000000..2aa5d23a723
--- /dev/null
+++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.h
@@ -0,0 +1,102 @@
+// 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_RENDERER_FETCHERS_RESOURCE_FETCHER_H_
+#define CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/timer/timer.h"
+#include "content/public/renderer/resource_fetcher.h"
+#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
+
+class GURL;
+
+namespace blink {
+class WebFrame;
+class WebURLLoader;
+struct WebURLError;
+}
+
+namespace content {
+
+class ResourceFetcherImpl : public ResourceFetcher,
+ public blink::WebURLLoaderClient {
+ public:
+ // ResourceFetcher implementation:
+ virtual void SetTimeout(const base::TimeDelta& timeout) OVERRIDE;
+
+ private:
+ friend class ResourceFetcher;
+
+ ResourceFetcherImpl(
+ const GURL& url, blink::WebFrame* frame,
+ blink::WebURLRequest::TargetType target_type,
+ const Callback& callback);
+
+ virtual ~ResourceFetcherImpl();
+
+ // Start the actual download.
+ void Start(const GURL& url, blink::WebFrame* frame,
+ blink::WebURLRequest::TargetType target_type);
+
+ void RunCallback(const blink::WebURLResponse& response,
+ const std::string& data);
+
+ // Callback for timer that limits how long we wait for the server. If this
+ // timer fires and the request hasn't completed, we kill the request.
+ void TimeoutFired();
+
+ // WebURLLoaderClient methods:
+ virtual void willSendRequest(
+ blink::WebURLLoader* loader, blink::WebURLRequest& new_request,
+ const blink::WebURLResponse& redirect_response);
+ virtual void didSendData(
+ blink::WebURLLoader* loader, unsigned long long bytes_sent,
+ unsigned long long total_bytes_to_be_sent);
+ virtual void didReceiveResponse(
+ blink::WebURLLoader* loader, const blink::WebURLResponse& response);
+ virtual void didReceiveCachedMetadata(
+ blink::WebURLLoader* loader, const char* data, int data_length);
+
+ virtual void didReceiveData(
+ blink::WebURLLoader* loader, const char* data, int data_length,
+ int encoded_data_length);
+ virtual void didFinishLoading(
+ blink::WebURLLoader* loader, double finishTime);
+ virtual void didFail(
+ blink::WebURLLoader* loader, const blink::WebURLError& error);
+
+ scoped_ptr<blink::WebURLLoader> loader_;
+
+ // Set to true once the request is complete.
+ bool completed_;
+
+ // Buffer to hold the content from the server.
+ std::string data_;
+
+ // A copy of the original resource response.
+ blink::WebURLResponse response_;
+
+ // Callback when we're done.
+ Callback callback_;
+
+ // Buffer to hold metadata from the cache.
+ std::string metadata_;
+
+ // Limit how long to wait for the server.
+ base::OneShotTimer<ResourceFetcherImpl> timeout_timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceFetcherImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_H_
diff --git a/chromium/content/renderer/gamepad_shared_memory_reader.cc b/chromium/content/renderer/gamepad_shared_memory_reader.cc
index f4e81941ae5..23edeb3a223 100644
--- a/chromium/content/renderer/gamepad_shared_memory_reader.cc
+++ b/chromium/content/renderer/gamepad_shared_memory_reader.cc
@@ -35,14 +35,14 @@ GamepadSharedMemoryReader::GamepadSharedMemoryReader()
static_cast<GamepadHardwareBuffer*>(memory);
}
-void GamepadSharedMemoryReader::SampleGamepads(WebKit::WebGamepads& gamepads) {
+void GamepadSharedMemoryReader::SampleGamepads(blink::WebGamepads& gamepads) {
// ==========
// DANGER
// ==========
//
// This logic is duplicated in Pepper as well. If you change it, that also
// needs to be in sync. See ppapi/proxy/gamepad_resource.cc.
- WebKit::WebGamepads read_into;
+ blink::WebGamepads read_into;
TRACE_EVENT0("GAMEPAD", "SampleGamepads");
if (!base::SharedMemory::IsHandleValid(renderer_shared_memory_handle_))
@@ -82,7 +82,7 @@ void GamepadSharedMemoryReader::SampleGamepads(WebKit::WebGamepads& gamepads) {
// gamepads to prevent fingerprinting. The actual data is not cleared.
// WebKit will only copy out data into the JS buffers for connected
// gamepads so this is sufficient.
- for (unsigned i = 0; i < WebKit::WebGamepads::itemsLengthCap; i++)
+ for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; i++)
gamepads.items[i].connected = false;
}
}
diff --git a/chromium/content/renderer/gamepad_shared_memory_reader.h b/chromium/content/renderer/gamepad_shared_memory_reader.h
index 8c10b90797d..08dc41a8c91 100644
--- a/chromium/content/renderer/gamepad_shared_memory_reader.h
+++ b/chromium/content/renderer/gamepad_shared_memory_reader.h
@@ -17,7 +17,7 @@ class GamepadSharedMemoryReader {
public:
GamepadSharedMemoryReader();
virtual ~GamepadSharedMemoryReader();
- void SampleGamepads(WebKit::WebGamepads&);
+ void SampleGamepads(blink::WebGamepads&);
private:
base::SharedMemoryHandle renderer_shared_memory_handle_;
diff --git a/chromium/content/renderer/geolocation_dispatcher.cc b/chromium/content/renderer/geolocation_dispatcher.cc
index 57eeeb6b724..a764b6107e2 100644
--- a/chromium/content/renderer/geolocation_dispatcher.cc
+++ b/chromium/content/renderer/geolocation_dispatcher.cc
@@ -13,11 +13,11 @@
#include "third_party/WebKit/public/web/WebGeolocationPosition.h"
#include "third_party/WebKit/public/web/WebGeolocationError.h"
-using WebKit::WebGeolocationController;
-using WebKit::WebGeolocationError;
-using WebKit::WebGeolocationPermissionRequest;
-using WebKit::WebGeolocationPermissionRequestManager;
-using WebKit::WebGeolocationPosition;
+using blink::WebGeolocationController;
+using blink::WebGeolocationError;
+using blink::WebGeolocationPermissionRequest;
+using blink::WebGeolocationPermissionRequestManager;
+using blink::WebGeolocationPosition;
namespace content {
@@ -87,7 +87,7 @@ bool GeolocationDispatcher::lastPosition(WebGeolocationPosition&) {
void GeolocationDispatcher::requestPermission(
const WebGeolocationPermissionRequest& permissionRequest) {
int bridge_id = pending_permissions_->add(permissionRequest);
- string16 origin = permissionRequest.securityOrigin().toString();
+ base::string16 origin = permissionRequest.securityOrigin().toString();
Send(new GeolocationHostMsg_RequestPermission(
routing_id(), bridge_id, GURL(origin)));
}
@@ -99,7 +99,7 @@ void GeolocationDispatcher::cancelPermissionRequest(
int bridge_id;
if (!pending_permissions_->remove(permissionRequest, bridge_id))
return;
- string16 origin = permissionRequest.securityOrigin().toString();
+ base::string16 origin = permissionRequest.securityOrigin().toString();
Send(new GeolocationHostMsg_CancelPermissionRequest(
routing_id(), bridge_id, GURL(origin)));
}
@@ -150,7 +150,7 @@ void GeolocationDispatcher::OnPositionUpdated(
}
controller_->errorOccurred(
WebGeolocationError(
- code, WebKit::WebString::fromUTF8(geoposition.error_message)));
+ code, blink::WebString::fromUTF8(geoposition.error_message)));
}
}
diff --git a/chromium/content/renderer/geolocation_dispatcher.h b/chromium/content/renderer/geolocation_dispatcher.h
index bda1ff73e66..5a96070373a 100644
--- a/chromium/content/renderer/geolocation_dispatcher.h
+++ b/chromium/content/renderer/geolocation_dispatcher.h
@@ -10,7 +10,7 @@
#include "third_party/WebKit/public/web/WebGeolocationClient.h"
#include "third_party/WebKit/public/web/WebGeolocationController.h"
-namespace WebKit {
+namespace blink {
class WebGeolocationController;
class WebGeolocationPermissionRequest;
class WebGeolocationPermissionRequestManager;
@@ -25,7 +25,7 @@ struct Geoposition;
// WebKit.
// It's the complement of GeolocationDispatcherHost (owned by RenderViewHost).
class GeolocationDispatcher : public RenderViewObserver,
- public WebKit::WebGeolocationClient {
+ public blink::WebGeolocationClient {
public:
explicit GeolocationDispatcher(RenderViewImpl* render_view);
virtual ~GeolocationDispatcher();
@@ -39,12 +39,12 @@ class GeolocationDispatcher : public RenderViewObserver,
virtual void startUpdating();
virtual void stopUpdating();
virtual void setEnableHighAccuracy(bool enable_high_accuracy);
- virtual void setController(WebKit::WebGeolocationController* controller);
- virtual bool lastPosition(WebKit::WebGeolocationPosition& position);
+ virtual void setController(blink::WebGeolocationController* controller);
+ virtual bool lastPosition(blink::WebGeolocationPosition& position);
virtual void requestPermission(
- const WebKit::WebGeolocationPermissionRequest& permissionRequest);
+ const blink::WebGeolocationPermissionRequest& permissionRequest);
virtual void cancelPermissionRequest(
- const WebKit::WebGeolocationPermissionRequest& permissionRequest);
+ const blink::WebGeolocationPermissionRequest& permissionRequest);
// Permission for using geolocation has been set.
void OnPermissionSet(int bridge_id, bool is_allowed);
@@ -55,9 +55,9 @@ class GeolocationDispatcher : public RenderViewObserver,
// The controller_ is valid for the lifetime of the underlying
// WebCore::GeolocationController. geolocationDestroyed() is
// invoked when the underlying object is destroyed.
- scoped_ptr< WebKit::WebGeolocationController> controller_;
+ scoped_ptr< blink::WebGeolocationController> controller_;
- scoped_ptr<WebKit::WebGeolocationPermissionRequestManager>
+ scoped_ptr<blink::WebGeolocationPermissionRequestManager>
pending_permissions_;
bool enable_high_accuracy_;
bool updating_;
diff --git a/chromium/content/renderer/gin_browsertest.cc b/chromium/content/renderer/gin_browsertest.cc
new file mode 100644
index 00000000000..3f69fbb8ab8
--- /dev/null
+++ b/chromium/content/renderer/gin_browsertest.cc
@@ -0,0 +1,95 @@
+// 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 "base/command_line.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/render_view_test.h"
+#include "content/renderer/render_view_impl.h"
+#include "gin/handle.h"
+#include "gin/per_isolate_data.h"
+#include "gin/wrappable.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebKit.h"
+#include "third_party/WebKit/public/web/WebView.h"
+
+namespace content {
+
+namespace {
+
+class TestGinObject : public gin::Wrappable<TestGinObject> {
+ public:
+ static gin::WrapperInfo kWrapperInfo;
+
+ static gin::Handle<TestGinObject> Create(v8::Isolate* isolate, bool* alive) {
+ return gin::CreateHandle(isolate, new TestGinObject(alive));
+ }
+
+ private:
+ TestGinObject(bool* alive) : alive_(alive) { *alive_ = true; }
+ virtual ~TestGinObject() { *alive_ = false; }
+
+ bool* alive_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestGinObject);
+};
+
+gin::WrapperInfo TestGinObject::kWrapperInfo = { gin::kEmbedderNativeGin };
+
+void RegisterTemplates(v8::Isolate* isolate) {
+ gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
+
+ v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
+ templ->SetInternalFieldCount(gin::kNumberOfInternalFields);
+ data->SetObjectTemplate(&TestGinObject::kWrapperInfo, templ);
+}
+
+class GinBrowserTest : public RenderViewTest {
+ public:
+ GinBrowserTest() {}
+ virtual ~GinBrowserTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kJavaScriptFlags, "--expose_gc");
+
+ RenderViewTest::SetUp();
+ }
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(GinBrowserTest);
+};
+
+// Test that garbage collection doesn't crash if a gin-wrapped object is
+// present.
+TEST_F(GinBrowserTest, GinAndGarbageCollection) {
+ LoadHTML("<!doctype html>");
+
+ bool alive = false;
+
+ {
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Context::Scope context_scope(
+ view_->GetWebView()->mainFrame()->mainWorldScriptContext());
+
+ RegisterTemplates(isolate);
+
+ // We create the object inside a scope so it's not kept alive by a handle
+ // on the stack.
+ TestGinObject::Create(isolate, &alive);
+ }
+
+ CHECK(alive);
+
+ // Should not crash.
+ v8::V8::LowMemoryNotification();
+
+ CHECK(!alive);
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/renderer/gpu/OWNERS b/chromium/content/renderer/gpu/OWNERS
index d73ca877b50..6f39d70c6bf 100644
--- a/chromium/content/renderer/gpu/OWNERS
+++ b/chromium/content/renderer/gpu/OWNERS
@@ -1,2 +1,2 @@
-apatrick@chromium.org
-kbr@chromium.org
+kbr@chromium.org
+piman@chromium.org
diff --git a/chromium/content/renderer/gpu/compositor_output_surface.cc b/chromium/content/renderer/gpu/compositor_output_surface.cc
index a31bc92757f..3889f467f85 100644
--- a/chromium/content/renderer/gpu/compositor_output_surface.cc
+++ b/chromium/content/renderer/gpu/compositor_output_surface.cc
@@ -8,6 +8,7 @@
#include "base/message_loop/message_loop_proxy.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_ack.h"
+#include "cc/output/managed_memory_policy.h"
#include "cc/output/output_surface_client.h"
#include "content/common/gpu/client/command_buffer_proxy_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
@@ -76,7 +77,7 @@ CompositorOutputSurface::CompositorOutputSurface(
CompositorOutputSurface::~CompositorOutputSurface() {
DCHECK(CalledOnValidThread());
- SetNeedsBeginFrame(false);
+ SetNeedsBeginImplFrame(false);
if (!HasClient())
return;
UpdateSmoothnessTakesPriority(false);
@@ -98,6 +99,14 @@ bool CompositorOutputSurface::BindToClient(
base::Bind(&CompositorOutputSurfaceProxy::OnMessageReceived,
output_surface_proxy_));
+ if (!context_provider()) {
+ // Without a GPU context, the memory policy otherwise wouldn't be set.
+ client->SetMemoryPolicy(cc::ManagedMemoryPolicy(
+ 64 * 1024 * 1024,
+ gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE,
+ cc::ManagedMemoryPolicy::kDefaultNumResourcesLimit));
+ }
+
return true;
}
@@ -133,7 +142,7 @@ void CompositorOutputSurface::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_SwapCompositorFrameAck, OnSwapAck);
IPC_MESSAGE_HANDLER(ViewMsg_ReclaimCompositorResources, OnReclaimResources);
#if defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(ViewMsg_BeginFrame, OnBeginFrame);
+ IPC_MESSAGE_HANDLER(ViewMsg_BeginFrame, OnBeginImplFrame);
#endif
IPC_END_MESSAGE_MAP()
}
@@ -145,16 +154,16 @@ void CompositorOutputSurface::OnUpdateVSyncParameters(
}
#if defined(OS_ANDROID)
-void CompositorOutputSurface::SetNeedsBeginFrame(bool enable) {
+void CompositorOutputSurface::SetNeedsBeginImplFrame(bool enable) {
DCHECK(CalledOnValidThread());
- if (needs_begin_frame_ != enable)
+ if (needs_begin_impl_frame_ != enable)
Send(new ViewHostMsg_SetNeedsBeginFrame(routing_id_, enable));
- OutputSurface::SetNeedsBeginFrame(enable);
+ OutputSurface::SetNeedsBeginImplFrame(enable);
}
-void CompositorOutputSurface::OnBeginFrame(const cc::BeginFrameArgs& args) {
+void CompositorOutputSurface::OnBeginImplFrame(const cc::BeginFrameArgs& args) {
DCHECK(CalledOnValidThread());
- BeginFrame(args);
+ BeginImplFrame(args);
}
#endif // defined(OS_ANDROID)
diff --git a/chromium/content/renderer/gpu/compositor_output_surface.h b/chromium/content/renderer/gpu/compositor_output_surface.h
index f8c79558501..7afaa519bb8 100644
--- a/chromium/content/renderer/gpu/compositor_output_surface.h
+++ b/chromium/content/renderer/gpu/compositor_output_surface.h
@@ -54,7 +54,7 @@ class CompositorOutputSurface
virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE;
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
#if defined(OS_ANDROID)
- virtual void SetNeedsBeginFrame(bool enable) OVERRIDE;
+ virtual void SetNeedsBeginImplFrame(bool enable) OVERRIDE;
#endif
// TODO(epenner): This seems out of place here and would be a better fit
@@ -93,7 +93,7 @@ class CompositorOutputSurface
void OnUpdateVSyncParameters(
base::TimeTicks timebase, base::TimeDelta interval);
#if defined(OS_ANDROID)
- void OnBeginFrame(const cc::BeginFrameArgs& args);
+ void OnBeginImplFrame(const cc::BeginFrameArgs& args);
#endif
bool Send(IPC::Message* message);
diff --git a/chromium/content/renderer/gpu/compositor_software_output_device.cc b/chromium/content/renderer/gpu/compositor_software_output_device.cc
index 6132590ecee..c37b958ad9e 100644
--- a/chromium/content/renderer/gpu/compositor_software_output_device.cc
+++ b/chromium/content/renderer/gpu/compositor_software_output_device.cc
@@ -201,6 +201,9 @@ void CompositorSoftwareOutputDevice::EndPaint(
frame_data->size = viewport_size_;
frame_data->damage_rect = damage_rect_;
frame_data->handle = buffer->handle();
+
+ CHECK_LE(static_cast<size_t>(frame_data->size.GetArea()) * 4,
+ buffer->shared_memory()->mapped_size());
}
void CompositorSoftwareOutputDevice::ReclaimSoftwareFrame(unsigned id) {
diff --git a/chromium/content/renderer/gpu/compositor_software_output_device.h b/chromium/content/renderer/gpu/compositor_software_output_device.h
index e658dfb386f..ce21b2b8d5b 100644
--- a/chromium/content/renderer/gpu/compositor_software_output_device.h
+++ b/chromium/content/renderer/gpu/compositor_software_output_device.h
@@ -49,6 +49,7 @@ private:
void* memory() const { return mem_->memory(); }
base::SharedMemoryHandle handle() const { return mem_->handle(); }
+ base::SharedMemory* shared_memory() const { return mem_.get(); }
bool free() const { return free_; }
void SetFree(bool free) { free_ = free; }
diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
index 9d745f9b018..602b6ec6cbf 100644
--- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -14,8 +14,14 @@
#include "cc/layers/layer.h"
#include "content/common/browser_rendering_stats.h"
#include "content/common/gpu/gpu_rendering_stats.h"
+#include "content/common/input/synthetic_gesture_params.h"
+#include "content/common/input/synthetic_pinch_gesture_params.h"
+#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
+#include "content/common/input/synthetic_tap_gesture_params.h"
#include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/v8_value_converter.h"
#include "content/renderer/gpu/render_widget_compositor.h"
+#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/skia_benchmarking_extension.h"
#include "third_party/WebKit/public/web/WebFrame.h"
@@ -30,13 +36,13 @@
#include "v8/include/v8.h"
#include "webkit/renderer/compositor_bindings/web_rendering_stats_impl.h"
-using WebKit::WebCanvas;
-using WebKit::WebFrame;
-using WebKit::WebImageCache;
-using WebKit::WebPrivatePtr;
-using WebKit::WebRenderingStatsImpl;
-using WebKit::WebSize;
-using WebKit::WebView;
+using blink::WebCanvas;
+using blink::WebFrame;
+using blink::WebImageCache;
+using blink::WebPrivatePtr;
+using blink::WebRenderingStatsImpl;
+using blink::WebSize;
+using blink::WebView;
const char kGpuBenchmarkingExtensionName[] = "v8/GpuBenchmarking";
@@ -100,28 +106,33 @@ class SkPictureSerializer {
class RenderingStatsEnumerator : public cc::RenderingStats::Enumerator {
public:
- RenderingStatsEnumerator(v8::Handle<v8::Object> stats_object)
- : stats_object(stats_object) { }
+ RenderingStatsEnumerator(v8::Isolate* isolate,
+ v8::Handle<v8::Object> stats_object)
+ : isolate(isolate), stats_object(stats_object) {}
virtual void AddInt64(const char* name, int64 value) OVERRIDE {
- stats_object->Set(v8::String::New(name), v8::Number::New(value));
+ stats_object->Set(v8::String::NewFromUtf8(isolate, name),
+ v8::Number::New(isolate, value));
}
virtual void AddDouble(const char* name, double value) OVERRIDE {
- stats_object->Set(v8::String::New(name), v8::Number::New(value));
+ stats_object->Set(v8::String::NewFromUtf8(isolate, name),
+ v8::Number::New(isolate, value));
}
virtual void AddInt(const char* name, int value) OVERRIDE {
- stats_object->Set(v8::String::New(name), v8::Integer::New(value));
+ stats_object->Set(v8::String::NewFromUtf8(isolate, name),
+ v8::Integer::New(value));
}
virtual void AddTimeDeltaInSecondsF(const char* name,
const base::TimeDelta& value) OVERRIDE {
- stats_object->Set(v8::String::New(name),
- v8::Number::New(value.InSecondsF()));
+ stats_object->Set(v8::String::NewFromUtf8(isolate, name),
+ v8::Number::New(isolate, value.InSecondsF()));
}
private:
+ v8::Isolate* isolate;
v8::Handle<v8::Object> stats_object;
};
@@ -157,8 +168,8 @@ class CallbackAndContext : public base::RefCounted<CallbackAndContext> {
friend class base::RefCounted<CallbackAndContext>;
virtual ~CallbackAndContext() {
- callback_.Dispose();
- context_.Dispose();
+ callback_.Reset();
+ context_.Reset();
}
v8::Isolate* isolate_;
@@ -167,6 +178,72 @@ class CallbackAndContext : public base::RefCounted<CallbackAndContext> {
DISALLOW_COPY_AND_ASSIGN(CallbackAndContext);
};
+class GpuBenchmarkingContext {
+ public:
+ GpuBenchmarkingContext()
+ : web_frame_(NULL),
+ web_view_(NULL),
+ render_view_impl_(NULL),
+ compositor_(NULL) {}
+
+ bool Init(bool init_compositor) {
+ web_frame_ = WebFrame::frameForCurrentContext();
+ if (!web_frame_)
+ return false;
+
+ web_view_ = web_frame_->view();
+ if (!web_view_) {
+ web_frame_ = NULL;
+ return false;
+ }
+
+ render_view_impl_ = RenderViewImpl::FromWebView(web_view_);
+ if (!render_view_impl_) {
+ web_frame_ = NULL;
+ web_view_ = NULL;
+ return false;
+ }
+
+ if (!init_compositor)
+ return true;
+
+ compositor_ = render_view_impl_->compositor();
+ if (!compositor_) {
+ web_frame_ = NULL;
+ web_view_ = NULL;
+ render_view_impl_ = NULL;
+ return false;
+ }
+
+ return true;
+ }
+
+ WebFrame* web_frame() const {
+ DCHECK(web_frame_ != NULL);
+ return web_frame_;
+ }
+ WebView* web_view() const {
+ DCHECK(web_view_ != NULL);
+ return web_view_;
+ }
+ RenderViewImpl* render_view_impl() const {
+ DCHECK(render_view_impl_ != NULL);
+ return render_view_impl_;
+ }
+ RenderWidgetCompositor* compositor() const {
+ DCHECK(compositor_ != NULL);
+ return compositor_;
+ }
+
+ private:
+ WebFrame* web_frame_;
+ WebView* web_view_;
+ RenderViewImpl* render_view_impl_;
+ RenderWidgetCompositor* compositor_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext);
+};
+
} // namespace
class GpuBenchmarkingWrapper : public v8::Extension {
@@ -191,37 +268,72 @@ class GpuBenchmarkingWrapper : public v8::Extension {
" native function GetRenderingStats();"
" return GetRenderingStats();"
"};"
+ "chrome.gpuBenchmarking.gpuRenderingStats = function() {"
+ " native function GetGpuRenderingStats();"
+ " return GetGpuRenderingStats();"
+ "};"
"chrome.gpuBenchmarking.printToSkPicture = function(dirname) {"
" native function PrintToSkPicture();"
" return PrintToSkPicture(dirname);"
"};"
+ "chrome.gpuBenchmarking.DEFAULT_INPUT = 0;"
+ "chrome.gpuBenchmarking.TOUCH_INPUT = 1;"
+ "chrome.gpuBenchmarking.MOUSE_INPUT = 2;"
"chrome.gpuBenchmarking.smoothScrollBy = "
- " function(pixels_to_scroll, opt_callback, opt_mouse_event_x,"
- " opt_mouse_event_y) {"
+ " function(pixels_to_scroll, opt_callback, opt_start_x,"
+ " opt_start_y, opt_gesture_source_type,"
+ " opt_direction, opt_speed_in_pixels_s) {"
" pixels_to_scroll = pixels_to_scroll || 0;"
" callback = opt_callback || function() { };"
+ " gesture_source_type = opt_gesture_source_type ||"
+ " chrome.gpuBenchmarking.DEFAULT_INPUT;"
+ " direction = opt_direction || 'down';"
+ " speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
" native function BeginSmoothScroll();"
- " if (typeof opt_mouse_event_x !== 'undefined' &&"
- " typeof opt_mouse_event_y !== 'undefined') {"
- " return BeginSmoothScroll(pixels_to_scroll >= 0, callback,"
- " Math.abs(pixels_to_scroll),"
- " opt_mouse_event_x, opt_mouse_event_y);"
- " } else {"
- " return BeginSmoothScroll(pixels_to_scroll >= 0, callback,"
- " Math.abs(pixels_to_scroll));"
- " }"
+ " return BeginSmoothScroll(pixels_to_scroll, callback,"
+ " gesture_source_type, direction,"
+ " speed_in_pixels_s, true,"
+ " opt_start_x, opt_start_y);"
"};"
"chrome.gpuBenchmarking.smoothScrollBySendsTouch = function() {"
" native function SmoothScrollSendsTouch();"
" return SmoothScrollSendsTouch();"
"};"
+ "chrome.gpuBenchmarking.swipe = "
+ " function(direction, distance, opt_callback,"
+ " opt_start_x, opt_start_y,"
+ " opt_speed_in_pixels_s) {"
+ " direction = direction || 'up';"
+ " distance = distance || 0;"
+ " callback = opt_callback || function() { };"
+ " speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
+ " native function BeginSmoothScroll();"
+ " return BeginSmoothScroll(-distance, callback,"
+ " chrome.gpuBenchmarking.TOUCH_INPUT,"
+ " direction, speed_in_pixels_s, false,"
+ " opt_start_x, opt_start_y);"
+ "};"
"chrome.gpuBenchmarking.pinchBy = "
- " function(zoom_in, pixels_to_move, anchor_x, anchor_y,"
- " opt_callback) {"
+ " function(zoom_in, pixels_to_cover, anchor_x, anchor_y,"
+ " opt_callback, opt_relative_pointer_speed_in_pixels_s) {"
" callback = opt_callback || function() { };"
+ " relative_pointer_speed_in_pixels_s ="
+ " opt_relative_pointer_speed_in_pixels_s || 800;"
" native function BeginPinch();"
- " return BeginPinch(zoom_in, pixels_to_move,"
- " anchor_x, anchor_y, callback);"
+ " return BeginPinch(zoom_in, pixels_to_cover,"
+ " anchor_x, anchor_y, callback,"
+ " relative_pointer_speed_in_pixels_s);"
+ "};"
+ "chrome.gpuBenchmarking.tap = "
+ " function(position_x, position_y, opt_callback, opt_duration_ms,"
+ " opt_gesture_source_type) {"
+ " callback = opt_callback || function() { };"
+ " duration_ms = opt_duration_ms || 0;"
+ " gesture_source_type = opt_gesture_source_type ||"
+ " chrome.gpuBenchmarking.DEFAULT_INPUT;"
+ " native function BeginTap();"
+ " return BeginTap(position_x, position_y, callback, duration_ms,"
+ " gesture_source_type);"
"};"
"chrome.gpuBenchmarking.beginWindowSnapshotPNG = function(callback) {"
" native function BeginWindowSnapshotPNG();"
@@ -230,99 +342,90 @@ class GpuBenchmarkingWrapper : public v8::Extension {
"chrome.gpuBenchmarking.clearImageCache = function() {"
" native function ClearImageCache();"
" ClearImageCache();"
+ "};"
+ "chrome.gpuBenchmarking.runMicroBenchmark ="
+ " function(name, callback, opt_arguments) {"
+ " arguments = opt_arguments || {};"
+ " native function RunMicroBenchmark();"
+ " return RunMicroBenchmark(name, callback, arguments);"
+ "};"
+ "chrome.gpuBenchmarking.hasGpuProcess = function() {"
+ " native function HasGpuProcess();"
+ " return HasGpuProcess();"
"};") {}
- virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
+ v8::Isolate* isolate,
v8::Handle<v8::String> name) OVERRIDE {
- if (name->Equals(v8::String::New("SetNeedsDisplayOnAllLayers")))
- return v8::FunctionTemplate::New(SetNeedsDisplayOnAllLayers);
- if (name->Equals(v8::String::New("SetRasterizeOnlyVisibleContent")))
- return v8::FunctionTemplate::New(SetRasterizeOnlyVisibleContent);
- if (name->Equals(v8::String::New("GetRenderingStats")))
- return v8::FunctionTemplate::New(GetRenderingStats);
- if (name->Equals(v8::String::New("PrintToSkPicture")))
- return v8::FunctionTemplate::New(PrintToSkPicture);
- if (name->Equals(v8::String::New("BeginSmoothScroll")))
- return v8::FunctionTemplate::New(BeginSmoothScroll);
- if (name->Equals(v8::String::New("SmoothScrollSendsTouch")))
- return v8::FunctionTemplate::New(SmoothScrollSendsTouch);
- if (name->Equals(v8::String::New("BeginPinch")))
- return v8::FunctionTemplate::New(BeginPinch);
- if (name->Equals(v8::String::New("BeginWindowSnapshotPNG")))
- return v8::FunctionTemplate::New(BeginWindowSnapshotPNG);
- if (name->Equals(v8::String::New("ClearImageCache")))
- return v8::FunctionTemplate::New(ClearImageCache);
+ if (name->Equals(
+ v8::String::NewFromUtf8(isolate, "SetNeedsDisplayOnAllLayers")))
+ return v8::FunctionTemplate::New(isolate, SetNeedsDisplayOnAllLayers);
+ if (name->Equals(
+ v8::String::NewFromUtf8(isolate, "SetRasterizeOnlyVisibleContent")))
+ return v8::FunctionTemplate::New(isolate, SetRasterizeOnlyVisibleContent);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "GetRenderingStats")))
+ return v8::FunctionTemplate::New(isolate, GetRenderingStats);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "GetGpuRenderingStats")))
+ return v8::FunctionTemplate::New(isolate, GetGpuRenderingStats);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "PrintToSkPicture")))
+ return v8::FunctionTemplate::New(isolate, PrintToSkPicture);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginSmoothScroll")))
+ return v8::FunctionTemplate::New(isolate, BeginSmoothScroll);
+ if (name->Equals(
+ v8::String::NewFromUtf8(isolate, "SmoothScrollSendsTouch")))
+ return v8::FunctionTemplate::New(isolate, SmoothScrollSendsTouch);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginPinch")))
+ return v8::FunctionTemplate::New(isolate, BeginPinch);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginTap")))
+ return v8::FunctionTemplate::New(isolate, BeginTap);
+ if (name->Equals(
+ v8::String::NewFromUtf8(isolate, "BeginWindowSnapshotPNG")))
+ return v8::FunctionTemplate::New(isolate, BeginWindowSnapshotPNG);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "ClearImageCache")))
+ return v8::FunctionTemplate::New(isolate, ClearImageCache);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "RunMicroBenchmark")))
+ return v8::FunctionTemplate::New(isolate, RunMicroBenchmark);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "HasGpuProcess")))
+ return v8::FunctionTemplate::New(isolate, HasGpuProcess);
return v8::Handle<v8::FunctionTemplate>();
}
static void SetNeedsDisplayOnAllLayers(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- WebFrame* web_frame = WebFrame::frameForCurrentContext();
- if (!web_frame)
- return;
-
- WebView* web_view = web_frame->view();
- if (!web_view)
- return;
-
- RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view);
- if (!render_view_impl)
- return;
-
- RenderWidgetCompositor* compositor = render_view_impl->compositor();
- if (!compositor)
+ GpuBenchmarkingContext context;
+ if (!context.Init(true))
return;
- compositor->SetNeedsDisplayOnAllLayers();
+ context.compositor()->SetNeedsDisplayOnAllLayers();
}
static void SetRasterizeOnlyVisibleContent(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- WebFrame* web_frame = WebFrame::frameForCurrentContext();
- if (!web_frame)
- return;
-
- WebView* web_view = web_frame->view();
- if (!web_view)
- return;
-
- RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view);
- if (!render_view_impl)
+ GpuBenchmarkingContext context;
+ if (!context.Init(true))
return;
- RenderWidgetCompositor* compositor = render_view_impl->compositor();
- if (!compositor)
- return;
-
- compositor->SetRasterizeOnlyVisibleContent();
+ context.compositor()->SetRasterizeOnlyVisibleContent();
}
static void GetRenderingStats(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- WebFrame* web_frame = WebFrame::frameForCurrentContext();
- if (!web_frame)
- return;
-
- WebView* web_view = web_frame->view();
- if (!web_view)
- return;
-
- RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view);
- if (!render_view_impl)
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
return;
WebRenderingStatsImpl stats;
- render_view_impl->GetRenderingStats(stats);
+ context.render_view_impl()->GetRenderingStats(stats);
content::GpuRenderingStats gpu_stats;
- render_view_impl->GetGpuRenderingStats(&gpu_stats);
+ context.render_view_impl()->GetGpuRenderingStats(&gpu_stats);
BrowserRenderingStats browser_stats;
- render_view_impl->GetBrowserRenderingStats(&browser_stats);
+ context.render_view_impl()->GetBrowserRenderingStats(&browser_stats);
v8::Handle<v8::Object> stats_object = v8::Object::New();
- RenderingStatsEnumerator enumerator(stats_object);
+ RenderingStatsEnumerator enumerator(args.GetIsolate(), stats_object);
stats.rendering_stats.EnumerateFields(&enumerator);
gpu_stats.EnumerateFields(&enumerator);
browser_stats.EnumerateFields(&enumerator);
@@ -330,43 +433,50 @@ class GpuBenchmarkingWrapper : public v8::Extension {
args.GetReturnValue().Set(stats_object);
}
- static void PrintToSkPicture(
+ static void GetGpuRenderingStats(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- if (args.Length() != 1)
- return;
- v8::String::AsciiValue dirname(args[0]);
- if (dirname.length() == 0)
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
return;
- WebFrame* web_frame = WebFrame::frameForCurrentContext();
- if (!web_frame)
- return;
+ content::GpuRenderingStats gpu_stats;
+ context.render_view_impl()->GetGpuRenderingStats(&gpu_stats);
- WebView* web_view = web_frame->view();
- if (!web_view)
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Handle<v8::Object> stats_object = v8::Object::New(isolate);
+ RenderingStatsEnumerator enumerator(isolate, stats_object);
+ gpu_stats.EnumerateFields(&enumerator);
+
+ args.GetReturnValue().Set(stats_object);
+ }
+
+ static void PrintToSkPicture(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 1)
return;
- RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view);
- if (!render_view_impl)
+ v8::String::Utf8Value dirname(args[0]);
+ if (dirname.length() == 0)
return;
- RenderWidgetCompositor* compositor = render_view_impl->compositor();
- if (!compositor)
+ GpuBenchmarkingContext context;
+ if (!context.Init(true))
return;
- const cc::Layer* root_layer = compositor->GetRootLayer();
+ const cc::Layer* root_layer = context.compositor()->GetRootLayer();
if (!root_layer)
return;
base::FilePath dirpath(
base::FilePath::StringType(*dirname, *dirname + dirname.length()));
- if (!file_util::CreateDirectory(dirpath) ||
+ if (!base::CreateDirectory(dirpath) ||
!base::PathIsWritable(dirpath)) {
std::string msg("Path is not writable: ");
msg.append(dirpath.MaybeAsASCII());
- v8::ThrowException(v8::Exception::Error(
- v8::String::New(msg.c_str(), msg.length())));
+ v8::Isolate* isolate = args.GetIsolate();
+ isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
+ isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
return;
}
@@ -374,7 +484,7 @@ class GpuBenchmarkingWrapper : public v8::Extension {
serializer.Serialize(root_layer);
}
- static void OnSmoothScrollCompleted(
+ static void OnSyntheticGestureCompleted(
CallbackAndContext* callback_and_context) {
v8::HandleScope scope(callback_and_context->isolate());
v8::Handle<v8::Context> context = callback_and_context->GetContext();
@@ -398,120 +508,197 @@ class GpuBenchmarkingWrapper : public v8::Extension {
static void BeginSmoothScroll(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- WebFrame* web_frame = WebFrame::frameForCurrentContext();
- if (!web_frame)
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
return;
- WebView* web_view = web_frame->view();
- if (!web_view)
- return;
-
- RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view);
- if (!render_view_impl)
- return;
-
- // Account for the 2 optional arguments, mouse_event_x and mouse_event_y.
+ // The last two arguments can be undefined. We check their validity later.
int arglen = args.Length();
- if (arglen < 3 ||
- !args[0]->IsBoolean() ||
+ if (arglen < 8 ||
+ !args[0]->IsNumber() ||
!args[1]->IsFunction() ||
- !args[2]->IsNumber()) {
+ !args[2]->IsNumber() ||
+ !args[3]->IsString() ||
+ !args[4]->IsNumber() ||
+ !args[5]->IsBoolean()) {
args.GetReturnValue().Set(false);
return;
}
- bool scroll_down = args[0]->BooleanValue();
v8::Local<v8::Function> callback_local =
v8::Local<v8::Function>::Cast(args[1]);
scoped_refptr<CallbackAndContext> callback_and_context =
new CallbackAndContext(args.GetIsolate(),
callback_local,
- web_frame->mainWorldScriptContext());
+ context.web_frame()->mainWorldScriptContext());
- int pixels_to_scroll = args[2]->IntegerValue();
+ scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
+ new SyntheticSmoothScrollGestureParams);
- int mouse_event_x = 0;
- int mouse_event_y = 0;
+ // Convert coordinates from CSS pixels to density independent pixels (DIPs).
+ float page_scale_factor = context.web_view()->pageScaleFactor();
- if (arglen == 3) {
- WebKit::WebRect rect = render_view_impl->windowRect();
- mouse_event_x = rect.x + rect.width / 2;
- mouse_event_y = rect.y + rect.height / 2;
- } else {
- if (arglen != 5 ||
- !args[3]->IsNumber() ||
- !args[4]->IsNumber()) {
- args.GetReturnValue().Set(false);
- return;
- }
+ int gesture_source_type = args[2]->IntegerValue();
+ if (gesture_source_type < 0 ||
+ gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
+ args.GetReturnValue().Set(false);
+ return;
+ }
+ gesture_params->gesture_source_type =
+ static_cast<SyntheticGestureParams::GestureSourceType>(
+ gesture_source_type);
+
+ int distance = args[0]->IntegerValue() * page_scale_factor;
+ v8::String::Utf8Value direction(args[3]);
+ DCHECK(*direction);
+ std::string direction_str(*direction);
+ if (direction_str == "down")
+ gesture_params->distance.set_y(distance);
+ else if (direction_str == "up")
+ gesture_params->distance.set_y(-distance);
+ else if (direction_str == "right")
+ gesture_params->distance.set_x(distance);
+ else if (direction_str == "left")
+ gesture_params->distance.set_x(-distance);
+ else {
+ args.GetReturnValue().Set(false);
+ return;
+ }
- mouse_event_x = args[3]->IntegerValue() * web_view->pageScaleFactor();
- mouse_event_y = args[4]->IntegerValue() * web_view->pageScaleFactor();
+ gesture_params->speed_in_pixels_s = args[4]->IntegerValue();
+ gesture_params->prevent_fling = args[5]->BooleanValue();
+
+ // Account for the 2 optional arguments, start_x and start_y.
+ if (args[6]->IsUndefined() || args[7]->IsUndefined()) {
+ blink::WebRect rect = context.render_view_impl()->windowRect();
+ gesture_params->anchor.SetPoint(rect.width / 2, rect.height / 2);
+ } else if (args[6]->IsNumber() && args[7]->IsNumber()) {
+ gesture_params->anchor.SetPoint(
+ args[6]->IntegerValue() * page_scale_factor,
+ args[7]->IntegerValue() * page_scale_factor);
+ } else {
+ args.GetReturnValue().Set(false);
+ return;
}
// TODO(nduca): If the render_view_impl is destroyed while the gesture is in
// progress, we will leak the callback and context. This needs to be fixed,
// somehow.
- render_view_impl->BeginSmoothScroll(
- scroll_down,
- base::Bind(&OnSmoothScrollCompleted,
- callback_and_context),
- pixels_to_scroll,
- mouse_event_x,
- mouse_event_y);
+ context.render_view_impl()->QueueSyntheticGesture(
+ gesture_params.PassAs<SyntheticGestureParams>(),
+ base::Bind(&OnSyntheticGestureCompleted,
+ callback_and_context));
args.GetReturnValue().Set(true);
}
static void BeginPinch(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- WebFrame* web_frame = WebFrame::frameForCurrentContext();
- if (!web_frame)
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
return;
- WebView* web_view = web_frame->view();
- if (!web_view)
+ int arglen = args.Length();
+ if (arglen < 6 ||
+ !args[0]->IsBoolean() ||
+ !args[1]->IsNumber() ||
+ !args[2]->IsNumber() ||
+ !args[3]->IsNumber() ||
+ !args[4]->IsFunction() ||
+ !args[5]->IsNumber()) {
+ args.GetReturnValue().Set(false);
return;
+ }
+
+ scoped_ptr<SyntheticPinchGestureParams> gesture_params(
+ new SyntheticPinchGestureParams);
+
+ // Convert coordinates from CSS pixels to density independent pixels (DIPs).
+ float page_scale_factor = context.web_view()->pageScaleFactor();
+
+ gesture_params->zoom_in = args[0]->BooleanValue();
+ gesture_params->total_num_pixels_covered =
+ args[1]->IntegerValue() * page_scale_factor;
+ gesture_params->anchor.SetPoint(
+ args[2]->IntegerValue() * page_scale_factor,
+ args[3]->IntegerValue() * page_scale_factor);
+ gesture_params->relative_pointer_speed_in_pixels_s =
+ args[5]->IntegerValue();
+
+ v8::Local<v8::Function> callback_local =
+ v8::Local<v8::Function>::Cast(args[4]);
+
+ scoped_refptr<CallbackAndContext> callback_and_context =
+ new CallbackAndContext(args.GetIsolate(),
+ callback_local,
+ context.web_frame()->mainWorldScriptContext());
- RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view);
- if (!render_view_impl)
+
+ // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
+ // progress, we will leak the callback and context. This needs to be fixed,
+ // somehow.
+ context.render_view_impl()->QueueSyntheticGesture(
+ gesture_params.PassAs<SyntheticGestureParams>(),
+ base::Bind(&OnSyntheticGestureCompleted,
+ callback_and_context));
+
+ args.GetReturnValue().Set(true);
+ }
+
+ static void BeginTap(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
return;
int arglen = args.Length();
if (arglen < 5 ||
- !args[0]->IsBoolean() ||
+ !args[0]->IsNumber() ||
!args[1]->IsNumber() ||
- !args[2]->IsNumber() ||
+ !args[2]->IsFunction() ||
!args[3]->IsNumber() ||
- !args[4]->IsFunction()) {
+ !args[4]->IsNumber()) {
args.GetReturnValue().Set(false);
return;
}
- bool zoom_in = args[0]->BooleanValue();
- int pixels_to_move = args[1]->IntegerValue();
- int anchor_x = args[2]->IntegerValue();
- int anchor_y = args[3]->IntegerValue();
+ scoped_ptr<SyntheticTapGestureParams> gesture_params(
+ new SyntheticTapGestureParams);
+
+ // Convert coordinates from CSS pixels to density independent pixels (DIPs).
+ float page_scale_factor = context.web_view()->pageScaleFactor();
+
+ gesture_params->position.SetPoint(
+ args[0]->IntegerValue() * page_scale_factor,
+ args[1]->IntegerValue() * page_scale_factor);
+ gesture_params->duration_ms = args[3]->IntegerValue();
+
+ int gesture_source_type = args[4]->IntegerValue();
+ if (gesture_source_type < 0 ||
+ gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
+ args.GetReturnValue().Set(false);
+ return;
+ }
+ gesture_params->gesture_source_type =
+ static_cast<SyntheticGestureParams::GestureSourceType>(
+ gesture_source_type);
v8::Local<v8::Function> callback_local =
- v8::Local<v8::Function>::Cast(args[4]);
+ v8::Local<v8::Function>::Cast(args[2]);
scoped_refptr<CallbackAndContext> callback_and_context =
new CallbackAndContext(args.GetIsolate(),
callback_local,
- web_frame->mainWorldScriptContext());
+ context.web_frame()->mainWorldScriptContext());
// TODO(nduca): If the render_view_impl is destroyed while the gesture is in
// progress, we will leak the callback and context. This needs to be fixed,
// somehow.
- render_view_impl->BeginPinch(
- zoom_in,
- pixels_to_move,
- anchor_x,
- anchor_y,
- base::Bind(&OnSmoothScrollCompleted,
+ context.render_view_impl()->QueueSyntheticGesture(
+ gesture_params.PassAs<SyntheticGestureParams>(),
+ base::Bind(&OnSyntheticGestureCompleted,
callback_and_context));
args.GetReturnValue().Set(true);
@@ -520,7 +707,8 @@ class GpuBenchmarkingWrapper : public v8::Extension {
static void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
const gfx::Size& size,
const std::vector<unsigned char>& png) {
- v8::HandleScope scope(callback_and_context->isolate());
+ v8::Isolate* isolate = callback_and_context->isolate();
+ v8::HandleScope scope(isolate);
v8::Handle<v8::Context> context = callback_and_context->GetContext();
v8::Context::Scope context_scope(context);
WebFrame* frame = WebFrame::frameForContext(context);
@@ -530,24 +718,27 @@ class GpuBenchmarkingWrapper : public v8::Extension {
if(!size.IsEmpty()) {
v8::Handle<v8::Object> result_object;
- result_object = v8::Object::New();
+ result_object = v8::Object::New(isolate);
- result_object->Set(v8::String::New("width"),
- v8::Number::New(size.width()));
- result_object->Set(v8::String::New("height"),
- v8::Number::New(size.height()));
+ result_object->Set(v8::String::NewFromUtf8(isolate, "width"),
+ v8::Number::New(isolate, size.width()));
+ result_object->Set(v8::String::NewFromUtf8(isolate, "height"),
+ v8::Number::New(isolate, size.height()));
std::string base64_png;
base::Base64Encode(base::StringPiece(
reinterpret_cast<const char*>(&*png.begin()), png.size()),
&base64_png);
- result_object->Set(v8::String::New("data"),
- v8::String::New(base64_png.c_str(), base64_png.size()));
+ result_object->Set(v8::String::NewFromUtf8(isolate, "data"),
+ v8::String::NewFromUtf8(isolate,
+ base64_png.c_str(),
+ v8::String::kNormalString,
+ base64_png.size()));
result = result_object;
} else {
- result = v8::Null();
+ result = v8::Null(isolate);
}
v8::Handle<v8::Value> argv[] = { result };
@@ -559,16 +750,8 @@ class GpuBenchmarkingWrapper : public v8::Extension {
static void BeginWindowSnapshotPNG(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- WebFrame* web_frame = WebFrame::frameForCurrentContext();
- if (!web_frame)
- return;
-
- WebView* web_view = web_frame->view();
- if (!web_view)
- return;
-
- RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view);
- if (!render_view_impl)
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
return;
if (!args[0]->IsFunction())
@@ -580,9 +763,9 @@ class GpuBenchmarkingWrapper : public v8::Extension {
scoped_refptr<CallbackAndContext> callback_and_context =
new CallbackAndContext(args.GetIsolate(),
callback_local,
- web_frame->mainWorldScriptContext());
+ context.web_frame()->mainWorldScriptContext());
- render_view_impl->GetWindowSnapshot(
+ context.render_view_impl()->GetWindowSnapshot(
base::Bind(&OnSnapshotCompleted, callback_and_context));
}
@@ -590,6 +773,67 @@ class GpuBenchmarkingWrapper : public v8::Extension {
const v8::FunctionCallbackInfo<v8::Value>& args) {
WebImageCache::clear();
}
+
+ static void OnMicroBenchmarkCompleted(
+ CallbackAndContext* callback_and_context,
+ scoped_ptr<base::Value> result) {
+ v8::HandleScope scope(callback_and_context->isolate());
+ v8::Handle<v8::Context> context = callback_and_context->GetContext();
+ v8::Context::Scope context_scope(context);
+ WebFrame* frame = WebFrame::frameForContext(context);
+ if (frame) {
+ scoped_ptr<V8ValueConverter> converter =
+ make_scoped_ptr(V8ValueConverter::create());
+ v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context);
+ v8::Handle<v8::Value> argv[] = { value };
+
+ frame->callFunctionEvenIfScriptDisabled(
+ callback_and_context->GetCallback(), v8::Object::New(), 1, argv);
+ }
+ }
+
+ static void RunMicroBenchmark(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(true)) {
+ args.GetReturnValue().Set(false);
+ return;
+ }
+
+ if (args.Length() != 3 ||
+ !args[0]->IsString() ||
+ !args[1]->IsFunction() ||
+ !args[2]->IsObject()) {
+ args.GetReturnValue().Set(false);
+ return;
+ }
+
+ v8::Local<v8::Function> callback_local =
+ v8::Local<v8::Function>::Cast(args[1]);
+
+ scoped_refptr<CallbackAndContext> callback_and_context =
+ new CallbackAndContext(args.GetIsolate(),
+ callback_local,
+ context.web_frame()->mainWorldScriptContext());
+
+ scoped_ptr<V8ValueConverter> converter =
+ make_scoped_ptr(V8ValueConverter::create());
+ v8::Handle<v8::Context> v8_context = callback_and_context->GetContext();
+ scoped_ptr<base::Value> value =
+ make_scoped_ptr(converter->FromV8Value(args[2], v8_context));
+
+ v8::String::Utf8Value benchmark(args[0]);
+ DCHECK(*benchmark);
+ args.GetReturnValue().Set(context.compositor()->ScheduleMicroBenchmark(
+ std::string(*benchmark),
+ value.Pass(),
+ base::Bind(&OnMicroBenchmarkCompleted, callback_and_context)));
+ }
+
+ static void HasGpuProcess(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
+ args.GetReturnValue().Set(!!gpu_channel);
+ }
};
v8::Extension* GpuBenchmarkingExtension::Get() {
diff --git a/chromium/content/renderer/gpu/mailbox_output_surface.cc b/chromium/content/renderer/gpu/mailbox_output_surface.cc
index ce635d3bce0..b23575da9ac 100644
--- a/chromium/content/renderer/gpu/mailbox_output_surface.cc
+++ b/chromium/content/renderer/gpu/mailbox_output_surface.cc
@@ -5,6 +5,7 @@
#include "content/renderer/gpu/mailbox_output_surface.h"
#include "base/logging.h"
+#include "cc/base/util.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_ack.h"
#include "cc/output/gl_frame_data.h"
@@ -53,7 +54,7 @@ MailboxOutputSurface::~MailboxOutputSurface() {
void MailboxOutputSurface::EnsureBackbuffer() {
is_backbuffer_discarded_ = false;
- WebKit::WebGraphicsContext3D* context3d = context_provider_->Context3d();
+ blink::WebGraphicsContext3D* context3d = context_provider_->Context3d();
if (!current_backing_.texture_id) {
// Find a texture of matching size to recycle.
@@ -86,12 +87,12 @@ void MailboxOutputSurface::EnsureBackbuffer() {
context3d->texImage2D(
GL_TEXTURE_2D,
0,
- ResourceProvider::GetGLInternalFormat(format_),
+ GLInternalFormat(format_),
surface_size_.width(),
surface_size_.height(),
0,
- ResourceProvider::GetGLDataFormat(format_),
- ResourceProvider::GetGLDataType(format_),
+ GLDataFormat(format_),
+ GLDataType(format_),
NULL);
context3d->genMailboxCHROMIUM(current_backing_.mailbox.name);
context3d->produceTextureCHROMIUM(
@@ -103,7 +104,7 @@ void MailboxOutputSurface::EnsureBackbuffer() {
void MailboxOutputSurface::DiscardBackbuffer() {
is_backbuffer_discarded_ = true;
- WebKit::WebGraphicsContext3D* context3d = context_provider_->Context3d();
+ blink::WebGraphicsContext3D* context3d = context_provider_->Context3d();
if (current_backing_.texture_id) {
context3d->deleteTexture(current_backing_.texture_id);
@@ -137,7 +138,7 @@ void MailboxOutputSurface::BindFramebuffer() {
EnsureBackbuffer();
DCHECK(current_backing_.texture_id);
- WebKit::WebGraphicsContext3D* context3d = context_provider_->Context3d();
+ blink::WebGraphicsContext3D* context3d = context_provider_->Context3d();
if (!fbo_)
fbo_ = context3d->createFramebuffer();
diff --git a/chromium/content/renderer/gpu/render_widget_compositor.cc b/chromium/content/renderer/gpu/render_widget_compositor.cc
index 2d5401e70b7..90ae2feaad7 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor.cc
+++ b/chromium/content/renderer/gpu/render_widget_compositor.cc
@@ -16,26 +16,34 @@
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
+#include "base/values.h"
+#include "cc/base/latency_info_swap_promise.h"
+#include "cc/base/latency_info_swap_promise_monitor.h"
#include "cc/base/switches.h"
#include "cc/debug/layer_tree_debug_state.h"
+#include "cc/debug/micro_benchmark.h"
#include "cc/layers/layer.h"
#include "cc/trees/layer_tree_host.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/public/common/content_switches.h"
-#include "content/renderer/gpu/input_handler_manager.h"
+#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/render_thread_impl.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/web/WebWidget.h"
#include "ui/gl/gl_switches.h"
#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
+namespace base {
+class Value;
+}
+
namespace cc {
class Layer;
}
-using WebKit::WebFloatPoint;
-using WebKit::WebSize;
-using WebKit::WebRect;
+using blink::WebFloatPoint;
+using blink::WebSize;
+using blink::WebRect;
namespace content {
namespace {
@@ -59,26 +67,6 @@ bool GetSwitchValueAsInt(
}
}
-bool GetSwitchValueAsFloat(
- const CommandLine& command_line,
- const std::string& switch_string,
- float min_value,
- float max_value,
- float* result) {
- std::string string_value = command_line.GetSwitchValueASCII(switch_string);
- double double_value;
- if (base::StringToDouble(string_value, &double_value) &&
- double_value >= min_value && double_value <= max_value) {
- *result = static_cast<float>(double_value);
- return true;
- } else {
- LOG(WARNING) << "Failed to parse switch " << switch_string << ": " <<
- string_value;
- return false;
- }
-}
-
-
} // namespace
// static
@@ -98,7 +86,7 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
settings.throttle_frame_production =
!cmd->HasSwitch(switches::kDisableGpuVsync);
- settings.begin_frame_scheduling_enabled =
+ settings.begin_impl_frame_scheduling_enabled =
cmd->HasSwitch(switches::kEnableBeginFrameScheduling);
settings.deadline_scheduling_enabled =
cmd->HasSwitch(switches::kEnableDeadlineScheduling) &&
@@ -109,8 +97,8 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
cmd->HasSwitch(cc::switches::kEnablePerTilePainting);
settings.accelerated_animation_enabled =
!cmd->HasSwitch(cc::switches::kDisableThreadedAnimation);
- settings.force_direct_layer_drawing =
- cmd->HasSwitch(cc::switches::kForceDirectLayerDrawing);
+ settings.touch_hit_testing =
+ !cmd->HasSwitch(cc::switches::kDisableCompositorTouchHitTesting);
int default_tile_width = settings.default_tile_size.width();
if (cmd->HasSwitch(switches::kDefaultTileWidth)) {
@@ -142,6 +130,7 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
max_untiled_layer_height);
settings.impl_side_painting = cc::switches::IsImplSidePaintingEnabled();
+ settings.gpu_rasterization = cc::switches::IsGPURasterizationEnabled();
settings.calculate_top_controls_position =
cmd->HasSwitch(cc::switches::kEnableTopControlsPositionCalculation);
@@ -196,6 +185,8 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
cmd->HasSwitch(cc::switches::kShowCompositedLayerBorders);
settings.initial_debug_state.show_fps_counter =
cmd->HasSwitch(cc::switches::kShowFPSCounter);
+ settings.initial_debug_state.show_layer_animation_bounds_rects =
+ cmd->HasSwitch(cc::switches::kShowLayerAnimationBounds);
settings.initial_debug_state.show_paint_rects =
cmd->HasSwitch(switches::kShowPaintRects);
settings.initial_debug_state.show_property_changed_rects =
@@ -235,15 +226,6 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
settings.num_raster_threads = num_raster_threads;
}
- if (cmd->HasSwitch(cc::switches::kLowResolutionContentsScaleFactor)) {
- const int kMinScaleFactor = settings.minimum_contents_scale;
- const int kMaxScaleFactor = 1;
- GetSwitchValueAsFloat(*cmd,
- cc::switches::kLowResolutionContentsScaleFactor,
- kMinScaleFactor, kMaxScaleFactor,
- &settings.low_res_contents_scale_factor);
- }
-
if (cmd->HasSwitch(cc::switches::kMaxTilesForInterestArea)) {
int max_tiles_for_interest_area;
if (GetSwitchValueAsInt(*cmd,
@@ -274,7 +256,6 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
// TODO(danakj): Move these to the android code.
settings.max_partial_texture_updates = 0;
settings.scrollbar_animator = cc::LayerTreeSettings::LinearFade;
- settings.solid_color_scrollbars = true;
settings.solid_color_scrollbar_color =
cmd->HasSwitch(switches::kHideScrollbars)
? SK_ColorTRANSPARENT
@@ -283,6 +264,7 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
// Android WebView handles root layer flings itself.
settings.ignore_root_layer_flings =
widget->UsingSynchronousRendererCompositor();
+ settings.always_overscroll = widget->UsingSynchronousRendererCompositor();
// RGBA_4444 textures are only enabled for low end devices
// and are disabled for Android WebView as it doesn't support the format.
settings.use_rgba_4444_textures =
@@ -292,7 +274,6 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
#elif !defined(OS_MACOSX)
if (cmd->HasSwitch(switches::kEnableOverlayScrollbars)) {
settings.scrollbar_animator = cc::LayerTreeSettings::Thinning;
- settings.solid_color_scrollbars = true;
}
if (cmd->HasSwitch(cc::switches::kEnablePinchVirtualViewport) ||
cmd->HasSwitch(switches::kEnableOverlayScrollbars)) {
@@ -300,7 +281,7 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
}
#endif
- if (!compositor->initialize(settings))
+ if (!compositor->Initialize(settings))
return scoped_ptr<RenderWidgetCompositor>();
return compositor.Pass();
@@ -333,6 +314,10 @@ void RenderWidgetCompositor::SetSuppressScheduleComposite(bool suppress) {
suppress_schedule_composite_ = suppress;
}
+bool RenderWidgetCompositor::BeginMainFrameRequested() const {
+ return layer_tree_host_->BeginMainFrameRequested();
+}
+
void RenderWidgetCompositor::Animate(base::TimeTicks time) {
layer_tree_host_->UpdateClientAnimations(time);
}
@@ -373,9 +358,17 @@ void RenderWidgetCompositor::SetNeedsRedrawRect(gfx::Rect damage_rect) {
layer_tree_host_->SetNeedsRedrawRect(damage_rect);
}
-void RenderWidgetCompositor::SetLatencyInfo(
- const ui::LatencyInfo& latency_info) {
- layer_tree_host_->SetLatencyInfo(latency_info);
+void RenderWidgetCompositor::SetNeedsForcedRedraw() {
+ layer_tree_host_->SetNextCommitForcesRedraw();
+ setNeedsAnimate();
+}
+
+scoped_ptr<cc::SwapPromiseMonitor>
+RenderWidgetCompositor::CreateLatencyInfoSwapPromiseMonitor(
+ ui::LatencyInfo* latency) {
+ return scoped_ptr<cc::SwapPromiseMonitor>(
+ new cc::LatencyInfoSwapPromiseMonitor(
+ latency, layer_tree_host_.get(), NULL));
}
int RenderWidgetCompositor::GetLayerTreeId() const {
@@ -390,12 +383,23 @@ const cc::Layer* RenderWidgetCompositor::GetRootLayer() const {
return layer_tree_host_->root_layer();
}
-bool RenderWidgetCompositor::initialize(cc::LayerTreeSettings settings) {
+bool RenderWidgetCompositor::ScheduleMicroBenchmark(
+ const std::string& name,
+ scoped_ptr<base::Value> value,
+ const base::Callback<void(scoped_ptr<base::Value>)>& callback) {
+ return layer_tree_host_->ScheduleMicroBenchmark(name, value.Pass(), callback);
+}
+
+bool RenderWidgetCompositor::Initialize(cc::LayerTreeSettings settings) {
scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy =
RenderThreadImpl::current()->compositor_message_loop_proxy();
- layer_tree_host_ = cc::LayerTreeHost::Create(this,
- settings,
- compositor_message_loop_proxy);
+ if (compositor_message_loop_proxy.get()) {
+ layer_tree_host_ = cc::LayerTreeHost::CreateThreaded(
+ this, NULL, settings, compositor_message_loop_proxy);
+ } else {
+ layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(
+ this, this, NULL, settings);
+ }
return layer_tree_host_;
}
@@ -403,7 +407,7 @@ void RenderWidgetCompositor::setSurfaceReady() {
layer_tree_host_->SetLayerTreeHostClientReady();
}
-void RenderWidgetCompositor::setRootLayer(const WebKit::WebLayer& layer) {
+void RenderWidgetCompositor::setRootLayer(const blink::WebLayer& layer) {
layer_tree_host_->SetRootLayer(
static_cast<const webkit::WebLayerImpl*>(&layer)->layer());
}
@@ -439,7 +443,7 @@ float RenderWidgetCompositor::deviceScaleFactor() const {
return layer_tree_host_->device_scale_factor();
}
-void RenderWidgetCompositor::setBackgroundColor(WebKit::WebColor color) {
+void RenderWidgetCompositor::setBackgroundColor(blink::WebColor color) {
layer_tree_host_->set_background_color(color);
}
@@ -462,7 +466,7 @@ void RenderWidgetCompositor::setPageScaleFactorAndLimits(
}
void RenderWidgetCompositor::startPageScaleAnimation(
- const WebKit::WebPoint& destination,
+ const blink::WebPoint& destination,
bool use_anchor,
float new_page_scale,
double duration_sec) {
@@ -479,13 +483,6 @@ void RenderWidgetCompositor::setNeedsAnimate() {
layer_tree_host_->SetNeedsAnimate();
}
-void RenderWidgetCompositor::setNeedsRedraw() {
- if (threaded_)
- layer_tree_host_->SetNeedsAnimate();
- else
- widget_->scheduleAnimation();
-}
-
bool RenderWidgetCompositor::commitRequested() const {
return layer_tree_host_->CommitRequested();
}
@@ -494,16 +491,16 @@ void RenderWidgetCompositor::didStopFlinging() {
layer_tree_host_->DidStopFlinging();
}
-void RenderWidgetCompositor::registerForAnimations(WebKit::WebLayer* layer) {
+void RenderWidgetCompositor::registerForAnimations(blink::WebLayer* layer) {
cc::Layer* cc_layer = static_cast<webkit::WebLayerImpl*>(layer)->layer();
cc_layer->layer_animation_controller()->SetAnimationRegistrar(
layer_tree_host_->animation_registrar());
}
void RenderWidgetCompositor::registerViewportLayers(
- const WebKit::WebLayer* pageScaleLayer,
- const WebKit::WebLayer* innerViewportScrollLayer,
- const WebKit::WebLayer* outerViewportScrollLayer) {
+ const blink::WebLayer* pageScaleLayer,
+ const blink::WebLayer* innerViewportScrollLayer,
+ const blink::WebLayer* outerViewportScrollLayer) {
layer_tree_host_->RegisterViewportLayers(
static_cast<const webkit::WebLayerImpl*>(pageScaleLayer)->layer(),
static_cast<const webkit::WebLayerImpl*>(innerViewportScrollLayer)
@@ -567,12 +564,12 @@ void RenderWidgetCompositor::setShowScrollBottleneckRects(bool show) {
layer_tree_host_->SetDebugState(debug_state);
}
-void RenderWidgetCompositor::WillBeginFrame() {
- widget_->InstrumentWillBeginFrame();
+void RenderWidgetCompositor::WillBeginMainFrame(int frame_id) {
+ widget_->InstrumentWillBeginFrame(frame_id);
widget_->willBeginCompositorFrame();
}
-void RenderWidgetCompositor::DidBeginFrame() {
+void RenderWidgetCompositor::DidBeginMainFrame() {
widget_->InstrumentDidBeginFrame();
}
@@ -614,6 +611,13 @@ void RenderWidgetCompositor::DidCommitAndDrawFrame() {
void RenderWidgetCompositor::DidCompleteSwapBuffers() {
widget_->didCompleteSwapBuffers();
+ if (!threaded_)
+ widget_->OnSwapBuffersComplete();
+}
+
+scoped_refptr<cc::ContextProvider>
+RenderWidgetCompositor::OffscreenContextProvider() {
+ return RenderThreadImpl::current()->OffscreenCompositorContextProvider();
}
void RenderWidgetCompositor::ScheduleComposite() {
@@ -621,15 +625,22 @@ void RenderWidgetCompositor::ScheduleComposite() {
widget_->scheduleComposite();
}
-scoped_refptr<cc::ContextProvider>
-RenderWidgetCompositor::OffscreenContextProviderForMainThread() {
- return RenderThreadImpl::current()->OffscreenContextProviderForMainThread();
+void RenderWidgetCompositor::ScheduleAnimation() {
+ widget_->scheduleAnimation();
}
-scoped_refptr<cc::ContextProvider>
-RenderWidgetCompositor::OffscreenContextProviderForCompositorThread() {
- return RenderThreadImpl::current()->
- OffscreenContextProviderForCompositorThread();
+void RenderWidgetCompositor::DidPostSwapBuffers() {
+ widget_->OnSwapBuffersPosted();
+}
+
+void RenderWidgetCompositor::DidAbortSwapBuffers() {
+ widget_->OnSwapBuffersAborted();
+}
+
+void RenderWidgetCompositor::RateLimitSharedMainThreadContext() {
+ cc::ContextProvider* provider =
+ RenderThreadImpl::current()->SharedMainThreadContextProvider().get();
+ provider->Context3d()->rateLimitOffscreenContextCHROMIUM();
}
} // namespace content
diff --git a/chromium/content/renderer/gpu/render_widget_compositor.h b/chromium/content/renderer/gpu/render_widget_compositor.h
index 060d0b85e9e..941fe3173b8 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor.h
+++ b/chromium/content/renderer/gpu/render_widget_compositor.h
@@ -5,11 +5,15 @@
#ifndef CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_H_
#define CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_H_
+#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
+#include "base/values.h"
+#include "cc/base/swap_promise_monitor.h"
#include "cc/debug/rendering_stats.h"
#include "cc/input/top_controls_state.h"
#include "cc/trees/layer_tree_host_client.h"
+#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "cc/trees/layer_tree_settings.h"
#include "third_party/WebKit/public/platform/WebLayerTreeView.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -28,8 +32,9 @@ class LayerTreeHost;
namespace content {
class RenderWidget;
-class RenderWidgetCompositor : public WebKit::WebLayerTreeView,
- public cc::LayerTreeHostClient {
+class RenderWidgetCompositor : public blink::WebLayerTreeView,
+ public cc::LayerTreeHostClient,
+ public cc::LayerTreeHostSingleThreadClient {
public:
// Attempt to construct and initialize a compositor instance for the widget
// with the given settings. Returns NULL if initialization fails.
@@ -40,6 +45,7 @@ class RenderWidgetCompositor : public WebKit::WebLayerTreeView,
const base::WeakPtr<cc::InputHandler>& GetInputHandler();
void SetSuppressScheduleComposite(bool suppress);
+ bool BeginMainFrameRequested() const;
void Animate(base::TimeTicks time);
void Composite(base::TimeTicks frame_begin_time);
void SetNeedsDisplayOnAllLayers();
@@ -50,49 +56,61 @@ class RenderWidgetCompositor : public WebKit::WebLayerTreeView,
bool animate);
void SetOverdrawBottomHeight(float overdraw_bottom_height);
void SetNeedsRedrawRect(gfx::Rect damage_rect);
- void SetLatencyInfo(const ui::LatencyInfo& latency_info);
+ // Like setNeedsRedraw but forces the frame to be drawn, without early-outs.
+ // Redraw will be forced after the next commit
+ void SetNeedsForcedRedraw();
+ // Calling CreateLatencyInfoSwapPromiseMonitor() to get a scoped
+ // LatencyInfoSwapPromiseMonitor. During the life time of the
+ // LatencyInfoSwapPromiseMonitor, if SetNeedsCommit() or SetNeedsUpdateLayer()
+ // is called on LayerTreeHost, the original latency info will be turned
+ // into a LatencyInfoSwapPromise.
+ scoped_ptr<cc::SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor(
+ ui::LatencyInfo* latency);
int GetLayerTreeId() const;
void NotifyInputThrottledUntilCommit();
const cc::Layer* GetRootLayer() const;
+ bool ScheduleMicroBenchmark(
+ const std::string& name,
+ scoped_ptr<base::Value> value,
+ const base::Callback<void(scoped_ptr<base::Value>)>& callback);
// WebLayerTreeView implementation.
virtual void setSurfaceReady();
- virtual void setRootLayer(const WebKit::WebLayer& layer);
+ virtual void setRootLayer(const blink::WebLayer& layer);
virtual void clearRootLayer();
virtual void setViewportSize(
- const WebKit::WebSize& unused_deprecated,
- const WebKit::WebSize& device_viewport_size);
- virtual WebKit::WebSize layoutViewportSize() const;
- virtual WebKit::WebSize deviceViewportSize() const;
- virtual WebKit::WebFloatPoint adjustEventPointForPinchZoom(
- const WebKit::WebFloatPoint& point) const;
+ const blink::WebSize& unused_deprecated,
+ const blink::WebSize& device_viewport_size);
+ virtual blink::WebSize layoutViewportSize() const;
+ virtual blink::WebSize deviceViewportSize() const;
+ virtual blink::WebFloatPoint adjustEventPointForPinchZoom(
+ const blink::WebFloatPoint& point) const;
virtual void setDeviceScaleFactor(float device_scale);
virtual float deviceScaleFactor() const;
- virtual void setBackgroundColor(WebKit::WebColor color);
+ virtual void setBackgroundColor(blink::WebColor color);
virtual void setHasTransparentBackground(bool transparent);
virtual void setOverhangBitmap(const SkBitmap& bitmap);
virtual void setVisible(bool visible);
virtual void setPageScaleFactorAndLimits(float page_scale_factor,
float minimum,
float maximum);
- virtual void startPageScaleAnimation(const WebKit::WebPoint& destination,
+ virtual void startPageScaleAnimation(const blink::WebPoint& destination,
bool use_anchor,
float new_page_scale,
double duration_sec);
virtual void setNeedsAnimate();
- virtual void setNeedsRedraw();
virtual bool commitRequested() const;
virtual void didStopFlinging();
- virtual bool compositeAndReadback(void *pixels, const WebKit::WebRect& rect);
+ virtual bool compositeAndReadback(void *pixels, const blink::WebRect& rect);
virtual void finishAllRendering();
virtual void setDeferCommits(bool defer_commits);
- virtual void registerForAnimations(WebKit::WebLayer* layer);
+ virtual void registerForAnimations(blink::WebLayer* layer);
virtual void registerViewportLayers(
- const WebKit::WebLayer* pageScaleLayer,
- const WebKit::WebLayer* innerViewportScrollLayer,
- const WebKit::WebLayer* outerViewportScrollLayer) OVERRIDE;
+ const blink::WebLayer* pageScaleLayer,
+ const blink::WebLayer* innerViewportScrollLayer,
+ const blink::WebLayer* outerViewportScrollLayer) OVERRIDE;
virtual void clearViewportLayers() OVERRIDE;
- virtual void renderingStats(WebKit::WebRenderingStats& stats) const {}
+ virtual void renderingStats(blink::WebRenderingStats& stats) const {}
virtual void setShowFPSCounter(bool show);
virtual void setShowPaintRects(bool show);
virtual void setShowDebugBorders(bool show);
@@ -100,8 +118,8 @@ class RenderWidgetCompositor : public WebKit::WebLayerTreeView,
virtual void setShowScrollBottleneckRects(bool show);
// cc::LayerTreeHostClient implementation.
- virtual void WillBeginFrame() OVERRIDE;
- virtual void DidBeginFrame() OVERRIDE;
+ virtual void WillBeginMainFrame(int frame_id) OVERRIDE;
+ virtual void DidBeginMainFrame() OVERRIDE;
virtual void Animate(double frame_begin_time) OVERRIDE;
virtual void Layout() OVERRIDE;
virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
@@ -113,16 +131,20 @@ class RenderWidgetCompositor : public WebKit::WebLayerTreeView,
virtual void DidCommit() OVERRIDE;
virtual void DidCommitAndDrawFrame() OVERRIDE;
virtual void DidCompleteSwapBuffers() OVERRIDE;
- virtual void ScheduleComposite() OVERRIDE;
- virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForMainThread() OVERRIDE;
virtual scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForCompositorThread() OVERRIDE;
+ OffscreenContextProvider() OVERRIDE;
+ virtual void RateLimitSharedMainThreadContext() OVERRIDE;
+
+ // cc::LayerTreeHostSingleThreadClient implementation.
+ virtual void ScheduleComposite() OVERRIDE;
+ virtual void ScheduleAnimation() OVERRIDE;
+ virtual void DidPostSwapBuffers() OVERRIDE;
+ virtual void DidAbortSwapBuffers() OVERRIDE;
private:
RenderWidgetCompositor(RenderWidget* widget, bool threaded);
- bool initialize(cc::LayerTreeSettings settings);
+ bool Initialize(cc::LayerTreeSettings settings);
bool threaded_;
bool suppress_schedule_composite_;
diff --git a/chromium/content/renderer/ico_image_decoder_unittest.cc b/chromium/content/renderer/ico_image_decoder_unittest.cc
index 83f5a3f161f..4beca93b05d 100644
--- a/chromium/content/renderer/ico_image_decoder_unittest.cc
+++ b/chromium/content/renderer/ico_image_decoder_unittest.cc
@@ -6,15 +6,15 @@
#include "content/test/image_decoder_test.h"
#include "third_party/WebKit/public/web/WebImageDecoder.h"
-using WebKit::WebImageDecoder;
+using blink::WebImageDecoder;
class ICOImageDecoderTest : public ImageDecoderTest {
public:
ICOImageDecoderTest() : ImageDecoderTest("ico") { }
protected:
- virtual WebKit::WebImageDecoder* CreateWebKitImageDecoder() const OVERRIDE {
- return new WebKit::WebImageDecoder(WebKit::WebImageDecoder::TypeICO);
+ virtual blink::WebImageDecoder* CreateWebKitImageDecoder() const OVERRIDE {
+ return new blink::WebImageDecoder(blink::WebImageDecoder::TypeICO);
}
};
diff --git a/chromium/content/renderer/idle_user_detector.cc b/chromium/content/renderer/idle_user_detector.cc
index 0f138a8d46f..dff78d1ab07 100644
--- a/chromium/content/renderer/idle_user_detector.cc
+++ b/chromium/content/renderer/idle_user_detector.cc
@@ -25,7 +25,7 @@ bool IdleUserDetector::OnMessageReceived(const IPC::Message& message) {
return false;
}
-void IdleUserDetector::OnHandleInputEvent(const WebKit::WebInputEvent* event,
+void IdleUserDetector::OnHandleInputEvent(const blink::WebInputEvent* event,
const ui::LatencyInfo& latency_info,
bool is_keyboard_shortcut) {
if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) {
diff --git a/chromium/content/renderer/idle_user_detector.h b/chromium/content/renderer/idle_user_detector.h
index 500d8f752a0..a5ee80bdd29 100644
--- a/chromium/content/renderer/idle_user_detector.h
+++ b/chromium/content/renderer/idle_user_detector.h
@@ -8,7 +8,7 @@
#include "base/basictypes.h"
#include "content/public/renderer/render_view_observer.h"
-namespace WebKit {
+namespace blink {
class WebInputEvent;
}
@@ -29,7 +29,7 @@ class IdleUserDetector : public RenderViewObserver {
// RenderViewObserver implementation:
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- void OnHandleInputEvent(const WebKit::WebInputEvent* event,
+ void OnHandleInputEvent(const blink::WebInputEvent* event,
const ui::LatencyInfo& latency_info,
bool is_keyboard_shortcut);
diff --git a/chromium/content/renderer/image_loading_helper.cc b/chromium/content/renderer/image_loading_helper.cc
index 22a36c8a48b..8f403bb9143 100644
--- a/chromium/content/renderer/image_loading_helper.cc
+++ b/chromium/content/renderer/image_loading_helper.cc
@@ -20,12 +20,11 @@
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/size.h"
#include "ui/gfx/skbitmap_operations.h"
-#include "webkit/glue/webkit_glue.h"
-using WebKit::WebFrame;
-using WebKit::WebVector;
-using WebKit::WebURL;
-using WebKit::WebURLRequest;
+using blink::WebFrame;
+using blink::WebVector;
+using blink::WebURL;
+using blink::WebURLRequest;
namespace {
diff --git a/chromium/content/renderer/input/OWNERS b/chromium/content/renderer/input/OWNERS
new file mode 100644
index 00000000000..d012c830472
--- /dev/null
+++ b/chromium/content/renderer/input/OWNERS
@@ -0,0 +1,2 @@
+aelias@chromium.org
+jdduke@chromium.org
diff --git a/chromium/content/renderer/gpu/input_event_filter.cc b/chromium/content/renderer/input/input_event_filter.cc
index 208c47180f9..a0399783988 100644
--- a/chromium/content/renderer/gpu/input_event_filter.cc
+++ b/chromium/content/renderer/input/input_event_filter.cc
@@ -1,20 +1,22 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/renderer/input/input_event_filter.h"
+
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
#include "cc/input/input_handler.h"
+#include "content/common/input/web_input_event_traits.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_switches.h"
-#include "content/renderer/gpu/input_event_filter.h"
#include "ui/gfx/vector2d_f.h"
-using WebKit::WebInputEvent;
+using blink::WebInputEvent;
namespace content {
@@ -131,8 +133,7 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
return;
DCHECK(event);
- InputEventAckState ack =
- handler_.Run(routing_id, event, latency_info);
+ InputEventAckState ack = handler_.Run(routing_id, event, &latency_info);
if (ack == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) {
TRACE_EVENT0("input", "InputEventFilter::ForwardToHandler");
@@ -145,10 +146,11 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
return;
}
- SendACK(event->type, ack, latency_info, routing_id);
+ if (!WebInputEventTraits::IgnoresAckDisposition(event->type))
+ SendACK(event->type, ack, latency_info, routing_id);
}
-void InputEventFilter::SendACK(WebKit::WebInputEvent::Type type,
+void InputEventFilter::SendACK(blink::WebInputEvent::Type type,
InputEventAckState ack_result,
const ui::LatencyInfo& latency_info,
int routing_id) {
diff --git a/chromium/content/renderer/gpu/input_event_filter.h b/chromium/content/renderer/input/input_event_filter.h
index b4526200c2f..240f939f721 100644
--- a/chromium/content/renderer/gpu/input_event_filter.h
+++ b/chromium/content/renderer/input/input_event_filter.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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_INPUT_EVENT_FILTER_H_
-#define CONTENT_RENDERER_GPU_INPUT_EVENT_FILTER_H_
+#ifndef CONTENT_RENDERER_INPUT_INPUT_EVENT_FILTER_H_
+#define CONTENT_RENDERER_INPUT_INPUT_EVENT_FILTER_H_
#include <queue>
#include <set>
@@ -12,7 +12,7 @@
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "content/port/common/input_event_ack_state.h"
-#include "content/renderer/gpu/input_handler_manager_client.h"
+#include "content/renderer/input/input_handler_manager_client.h"
#include "ipc/ipc_channel_proxy.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
@@ -62,7 +62,7 @@ class CONTENT_EXPORT InputEventFilter
void ForwardToMainListener(const IPC::Message& message);
void ForwardToHandler(const IPC::Message& message);
- void SendACK(WebKit::WebInputEvent::Type type,
+ void SendACK(blink::WebInputEvent::Type type,
InputEventAckState ack_result,
const ui::LatencyInfo& latency_info,
int routing_id);
@@ -91,4 +91,4 @@ class CONTENT_EXPORT InputEventFilter
} // namespace content
-#endif // CONTENT_RENDERER_GPU_INPUT_EVENT_FILTER_H_
+#endif // CONTENT_RENDERER_INPUT_INPUT_EVENT_FILTER_H_
diff --git a/chromium/content/renderer/gpu/input_event_filter_unittest.cc b/chromium/content/renderer/input/input_event_filter_unittest.cc
index d8e605268b0..a131ceb47dc 100644
--- a/chromium/content/renderer/gpu/input_event_filter_unittest.cc
+++ b/chromium/content/renderer/input/input_event_filter_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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.
@@ -10,12 +10,12 @@
#include "base/message_loop/message_loop.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
-#include "content/renderer/gpu/input_event_filter.h"
+#include "content/renderer/input/input_event_filter.h"
#include "ipc/ipc_test_sink.h"
#include "testing/gtest/include/gtest/gtest.h"
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
namespace content {
namespace {
@@ -47,7 +47,7 @@ class InputEventRecorder {
InputEventAckState HandleInputEvent(int routing_id,
const WebInputEvent* event,
- const ui::LatencyInfo& latency_info) {
+ ui::LatencyInfo* latency_info) {
DCHECK_EQ(kTestRoutingID, routing_id);
records_.push_back(Record(event));
@@ -285,9 +285,9 @@ TEST_F(InputEventFilterTest, PreserveRelativeOrder) {
messages.push_back(InputMsg_Paste(kTestRoutingID));
messages.push_back(InputMsg_PasteAndMatchStyle(kTestRoutingID));
messages.push_back(InputMsg_Delete(kTestRoutingID));
- messages.push_back(InputMsg_Replace(kTestRoutingID, string16()));
+ messages.push_back(InputMsg_Replace(kTestRoutingID, base::string16()));
messages.push_back(InputMsg_ReplaceMisspelling(kTestRoutingID,
- string16()));
+ base::string16()));
messages.push_back(InputMsg_Delete(kTestRoutingID));
messages.push_back(InputMsg_SelectAll(kTestRoutingID));
messages.push_back(InputMsg_Unselect(kTestRoutingID));
diff --git a/chromium/content/renderer/gpu/input_handler_manager.cc b/chromium/content/renderer/input/input_handler_manager.cc
index 1db011baebb..6195f5195df 100644
--- a/chromium/content/renderer/gpu/input_handler_manager.cc
+++ b/chromium/content/renderer/input/input_handler_manager.cc
@@ -1,18 +1,18 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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/input_handler_manager.h"
+#include "content/renderer/input/input_handler_manager.h"
#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
#include "cc/input/input_handler.h"
-#include "content/renderer/gpu/input_event_filter.h"
-#include "content/renderer/gpu/input_handler_manager_client.h"
-#include "content/renderer/gpu/input_handler_wrapper.h"
+#include "content/renderer/input/input_event_filter.h"
+#include "content/renderer/input/input_handler_manager_client.h"
+#include "content/renderer/input/input_handler_wrapper.h"
-using WebKit::WebInputEvent;
+using blink::WebInputEvent;
namespace content {
@@ -88,13 +88,14 @@ void InputHandlerManager::AddInputHandlerOnCompositorThread(
"InputHandlerManager::AddInputHandlerOnCompositorThread",
"result", "AddingRoute");
client_->DidAddInputHandler(routing_id, input_handler.get());
- input_handlers_[routing_id] =
- make_scoped_refptr(new InputHandlerWrapper(this,
- routing_id, main_loop, input_handler, render_view_impl));
+ input_handlers_.add(routing_id,
+ make_scoped_ptr(new InputHandlerWrapper(this,
+ routing_id, main_loop, input_handler, render_view_impl)));
}
void InputHandlerManager::RemoveInputHandler(int routing_id) {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ DCHECK(input_handlers_.contains(routing_id));
TRACE_EVENT0("input", "InputHandlerManager::RemoveInputHandler");
@@ -105,13 +106,13 @@ void InputHandlerManager::RemoveInputHandler(int routing_id) {
InputEventAckState InputHandlerManager::HandleInputEvent(
int routing_id,
const WebInputEvent* input_event,
- const ui::LatencyInfo& latency_info) {
+ ui::LatencyInfo* latency_info) {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
InputHandlerMap::iterator it = input_handlers_.find(routing_id);
if (it == input_handlers_.end()) {
TRACE_EVENT1("input", "InputHandlerManager::HandleInputEvent",
- "result", "NoInputHandlerFound");
+ "result", "NoInputHandlerFound");
// Oops, we no longer have an interested input handler..
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
diff --git a/chromium/content/renderer/gpu/input_handler_manager.h b/chromium/content/renderer/input/input_handler_manager.h
index 3811d63a8df..f2df0415f29 100644
--- a/chromium/content/renderer/gpu/input_handler_manager.h
+++ b/chromium/content/renderer/input/input_handler_manager.h
@@ -1,12 +1,11 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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_INPUT_HANDLER_MANAGER_H_
-#define CONTENT_RENDERER_GPU_INPUT_HANDLER_MANAGER_H_
-
-#include <map>
+#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_H_
+#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_H_
+#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "content/port/common/input_event_ack_state.h"
@@ -21,7 +20,7 @@ class InputHandler;
struct DidOverscrollParams;
}
-namespace WebKit {
+namespace blink {
class WebInputEvent;
}
@@ -52,8 +51,8 @@ class InputHandlerManager {
// Called from the compositor's thread.
InputEventAckState HandleInputEvent(int routing_id,
- const WebKit::WebInputEvent* input_event,
- const ui::LatencyInfo& latency_info);
+ const blink::WebInputEvent* input_event,
+ ui::LatencyInfo* latency_info);
// Called from the compositor's thread.
void DidOverscroll(int routing_id, const cc::DidOverscrollParams& params);
@@ -66,8 +65,8 @@ class InputHandlerManager {
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl);
- typedef std::map<int, // routing_id
- scoped_refptr<InputHandlerWrapper> > InputHandlerMap;
+ typedef base::ScopedPtrHashMap<int, // routing_id
+ InputHandlerWrapper> InputHandlerMap;
InputHandlerMap input_handlers_;
scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
@@ -76,4 +75,4 @@ class InputHandlerManager {
} // namespace content
-#endif // CONTENT_RENDERER_GPU_INPUT_HANDLER_MANAGER_H_
+#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_H_
diff --git a/chromium/content/renderer/gpu/input_handler_manager_client.h b/chromium/content/renderer/input/input_handler_manager_client.h
index c147a8a6be0..0a36e50ba5d 100644
--- a/chromium/content/renderer/gpu/input_handler_manager_client.h
+++ b/chromium/content/renderer/input/input_handler_manager_client.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_GPU_INPUT_HANDLER_MANAGER_CLIENT_H_
-#define CONTENT_RENDERER_GPU_INPUT_HANDLER_MANAGER_CLIENT_H_
+#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_CLIENT_H_
+#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_CLIENT_H_
#include "base/basictypes.h"
#include "base/callback.h"
@@ -20,7 +20,7 @@ class InputHandler;
struct DidOverscrollParams;
}
-namespace WebKit {
+namespace blink {
class WebInputEvent;
}
@@ -35,8 +35,8 @@ class CONTENT_EXPORT InputHandlerManagerClient {
// The client should only makes calls to |handler| on the compositor thread.
typedef base::Callback<
InputEventAckState(int /*routing_id*/,
- const WebKit::WebInputEvent*,
- const ui::LatencyInfo& latency_info)> Handler;
+ const blink::WebInputEvent*,
+ ui::LatencyInfo* latency_info)> Handler;
// Called from the main thread.
virtual void SetBoundHandler(const Handler& handler) = 0;
diff --git a/chromium/content/renderer/gpu/input_handler_proxy.cc b/chromium/content/renderer/input/input_handler_proxy.cc
index f1ca2a54711..ce9ce22a02d 100644
--- a/chromium/content/renderer/gpu/input_handler_proxy.cc
+++ b/chromium/content/renderer/input/input_handler_proxy.cc
@@ -1,27 +1,37 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// 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/input_handler_proxy.h"
+#include "content/renderer/input/input_handler_proxy.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
-#include "content/renderer/gpu/input_handler_proxy_client.h"
+#include "content/renderer/input/input_handler_proxy_client.h"
#include "third_party/WebKit/public/platform/Platform.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/latency_info.h"
-
-using WebKit::WebFloatPoint;
-using WebKit::WebFloatSize;
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebPoint;
-using WebKit::WebTouchEvent;
+#include "ui/gfx/frame_time.h"
+
+using blink::WebFloatPoint;
+using blink::WebFloatSize;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebPoint;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
namespace {
+// Validate provided event timestamps that interact with animation timestamps.
+const double kBadTimestampDeltaFromNowInS = 60. * 60. * 24. * 7.;
+
+double InSecondsF(const base::TimeTicks& time) {
+ return (time - base::TimeTicks()).InSecondsF();
+}
+
void SendScrollLatencyUma(const WebInputEvent& event,
const ui::LatencyInfo& latency_info) {
if (!(event.type == WebInputEvent::GestureScrollBegin ||
@@ -39,10 +49,10 @@ void SendScrollLatencyUma(const WebInputEvent& event,
base::TimeDelta delta = base::TimeTicks::HighResNow() - it->second.event_time;
for (size_t i = 0; i < it->second.event_count; ++i) {
UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.RendererImpl.GestureScroll",
+ "Event.Latency.RendererImpl.GestureScroll2",
delta.InMicroseconds(),
0,
- 200000,
+ 1000000,
100);
}
} // namespace
@@ -82,14 +92,14 @@ void InputHandlerProxy::SetClient(InputHandlerProxyClient* client) {
InputHandlerProxy::EventDisposition
InputHandlerProxy::HandleInputEventWithLatencyInfo(
const WebInputEvent& event,
- const ui::LatencyInfo& latency_info) {
+ ui::LatencyInfo* latency_info) {
DCHECK(input_handler_);
- SendScrollLatencyUma(event, latency_info);
+ SendScrollLatencyUma(event, *latency_info);
+ scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor =
+ input_handler_->CreateLatencyInfoSwapPromiseMonitor(latency_info);
InputHandlerProxy::EventDisposition disposition = HandleInputEvent(event);
- if (disposition != DID_NOT_HANDLE)
- input_handler_->SetLatencyInfoForInputEvent(latency_info);
return disposition;
}
@@ -218,9 +228,14 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
} else if (event.type == WebInputEvent::TouchStart) {
const WebTouchEvent& touch_event =
*static_cast<const WebTouchEvent*>(&event);
- if (!input_handler_->HaveTouchEventHandlersAt(touch_event.touches[0]
- .position))
- return DROP_EVENT;
+ for (size_t i = 0; i < touch_event.touchesLength; ++i) {
+ if (touch_event.touches[i].state != WebTouchPoint::StatePressed)
+ continue;
+ if (input_handler_->HaveTouchEventHandlersAt(touch_event.touches[i]
+ .position))
+ return DID_NOT_HANDLE;
+ }
+ return DROP_EVENT;
} else if (WebInputEvent::isKeyboardEventType(event.type)) {
CancelCurrentFling();
}
@@ -257,13 +272,19 @@ InputHandlerProxy::HandleGestureFling(
gesture_event.sourceDevice,
WebFloatPoint(gesture_event.data.flingStart.velocityX,
gesture_event.data.flingStart.velocityY),
- WebKit::WebSize()));
+ blink::WebSize()));
fling_overscrolled_horizontally_ = false;
fling_overscrolled_vertically_ = false;
TRACE_EVENT_ASYNC_BEGIN0(
"renderer",
"InputHandlerProxy::HandleGestureFling::started",
this);
+ if (gesture_event.timeStampSeconds) {
+ fling_parameters_.startTime = gesture_event.timeStampSeconds;
+ DCHECK_LT(fling_parameters_.startTime -
+ InSecondsF(gfx::FrameTime::Now()),
+ kBadTimestampDeltaFromNowInS);
+ }
fling_parameters_.delta =
WebFloatPoint(gesture_event.data.flingStart.velocityX,
gesture_event.data.flingStart.velocityY);
@@ -304,7 +325,7 @@ void InputHandlerProxy::Animate(base::TimeTicks time) {
if (!fling_curve_)
return;
- double monotonic_time_sec = (time - base::TimeTicks()).InSecondsF();
+ double monotonic_time_sec = InSecondsF(time);
if (!fling_parameters_.startTime) {
fling_parameters_.startTime = monotonic_time_sec;
input_handler_->ScheduleAnimation();
@@ -359,7 +380,7 @@ bool InputHandlerProxy::CancelCurrentFling() {
had_fling_animation);
fling_curve_.reset();
gesture_scroll_on_impl_thread_ = false;
- fling_parameters_ = WebKit::WebActiveWheelFlingParameters();
+ fling_parameters_ = blink::WebActiveWheelFlingParameters();
return had_fling_animation;
}
diff --git a/chromium/content/renderer/gpu/input_handler_proxy.h b/chromium/content/renderer/input/input_handler_proxy.h
index e307827bc00..46f88ab5ea4 100644
--- a/chromium/content/renderer/gpu/input_handler_proxy.h
+++ b/chromium/content/renderer/input/input_handler_proxy.h
@@ -1,19 +1,19 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// 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_INPUT_HANDLER_PROXY_H_
-#define CONTENT_RENDERER_GPU_INPUT_HANDLER_PROXY_H_
+#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_H_
+#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_H_
#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "cc/input/input_handler.h"
#include "content/common/content_export.h"
-#include "third_party/WebKit/public/web/WebActiveWheelFlingParameters.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/platform/WebGestureCurve.h"
#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
+#include "third_party/WebKit/public/web/WebActiveWheelFlingParameters.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace content {
@@ -25,7 +25,7 @@ class InputHandlerProxyClient;
// intended for a specific WebWidget.
class CONTENT_EXPORT InputHandlerProxy
: public cc::InputHandlerClient,
- public NON_EXPORTED_BASE(WebKit::WebGestureCurveTarget) {
+ public NON_EXPORTED_BASE(blink::WebGestureCurveTarget) {
public:
explicit InputHandlerProxy(cc::InputHandler* input_handler);
virtual ~InputHandlerProxy();
@@ -38,9 +38,9 @@ class CONTENT_EXPORT InputHandlerProxy
DROP_EVENT
};
EventDisposition HandleInputEventWithLatencyInfo(
- const WebKit::WebInputEvent& event,
- const ui::LatencyInfo& latency_info);
- EventDisposition HandleInputEvent(const WebKit::WebInputEvent& event);
+ const blink::WebInputEvent& event,
+ ui::LatencyInfo* latency_info);
+ EventDisposition HandleInputEvent(const blink::WebInputEvent& event);
// cc::InputHandlerClient implementation.
virtual void WillShutdown() OVERRIDE;
@@ -48,27 +48,27 @@ class CONTENT_EXPORT InputHandlerProxy
virtual void MainThreadHasStoppedFlinging() OVERRIDE;
virtual void DidOverscroll(const cc::DidOverscrollParams& params) OVERRIDE;
- // WebKit::WebGestureCurveTarget implementation.
- virtual void scrollBy(const WebKit::WebFloatSize& offset);
- virtual void notifyCurrentFlingVelocity(const WebKit::WebFloatSize& velocity);
+ // blink::WebGestureCurveTarget implementation.
+ virtual void scrollBy(const blink::WebFloatSize& offset);
+ virtual void notifyCurrentFlingVelocity(const blink::WebFloatSize& velocity);
bool gesture_scroll_on_impl_thread_for_testing() const {
return gesture_scroll_on_impl_thread_;
}
private:
- EventDisposition HandleGestureFling(const WebKit::WebGestureEvent& event);
+ EventDisposition HandleGestureFling(const blink::WebGestureEvent& event);
// Returns true if we scrolled by the increment.
- bool TouchpadFlingScroll(const WebKit::WebFloatSize& increment);
+ bool TouchpadFlingScroll(const blink::WebFloatSize& increment);
// Returns true if we actually had an active fling to cancel.
bool CancelCurrentFling();
- scoped_ptr<WebKit::WebGestureCurve> fling_curve_;
+ scoped_ptr<blink::WebGestureCurve> fling_curve_;
// Parameters for the active fling animation, stored in case we need to
// transfer it out later.
- WebKit::WebActiveWheelFlingParameters fling_parameters_;
+ blink::WebActiveWheelFlingParameters fling_parameters_;
InputHandlerProxyClient* client_;
cc::InputHandler* input_handler_;
@@ -92,4 +92,4 @@ class CONTENT_EXPORT InputHandlerProxy
} // namespace content
-#endif // CONTENT_RENDERER_GPU_INPUT_HANDLER_PROXY_H_
+#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_H_
diff --git a/chromium/content/renderer/gpu/input_handler_proxy_client.h b/chromium/content/renderer/input/input_handler_proxy_client.h
index 6ef000c098f..7ef1121bf7c 100644
--- a/chromium/content/renderer/gpu/input_handler_proxy_client.h
+++ b/chromium/content/renderer/input/input_handler_proxy_client.h
@@ -1,11 +1,11 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// 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_INPUT_HANDLER_PROXY_CLIENT_H_
-#define CONTENT_RENDERER_GPU_INPUT_HANDLER_PROXY_CLIENT_H_
+#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_CLIENT_H_
+#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_CLIENT_H_
-namespace WebKit {
+namespace blink {
class WebGestureCurve;
struct WebActiveWheelFlingParameters;
struct WebFloatPoint;
@@ -23,14 +23,14 @@ class InputHandlerProxyClient {
// Transfers an active wheel fling animation initiated by a previously
// handled input event out to the client.
virtual void TransferActiveWheelFlingAnimation(
- const WebKit::WebActiveWheelFlingParameters& params) = 0;
+ const blink::WebActiveWheelFlingParameters& params) = 0;
// Creates a new fling animation curve instance for device |device_source|
// with |velocity| and already scrolled |cumulative_scroll| pixels.
- virtual WebKit::WebGestureCurve* CreateFlingAnimationCurve(
+ virtual blink::WebGestureCurve* CreateFlingAnimationCurve(
int device_source,
- const WebKit::WebFloatPoint& velocity,
- const WebKit::WebSize& cumulative_scroll) = 0;
+ const blink::WebFloatPoint& velocity,
+ const blink::WebSize& cumulative_scroll) = 0;
virtual void DidOverscroll(const cc::DidOverscrollParams& params) = 0;
@@ -40,4 +40,4 @@ class InputHandlerProxyClient {
} // namespace content
-#endif // CONTENT_RENDERER_GPU_INPUT_HANDLER_PROXY_CLIENT_H_
+#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_CLIENT_H_
diff --git a/chromium/content/renderer/gpu/input_handler_proxy_unittest.cc b/chromium/content/renderer/input/input_handler_proxy_unittest.cc
index 5a3472cca47..c7cc9168c18 100644
--- a/chromium/content/renderer/gpu/input_handler_proxy_unittest.cc
+++ b/chromium/content/renderer/input/input_handler_proxy_unittest.cc
@@ -1,12 +1,13 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// 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/input_handler_proxy.h"
+#include "content/renderer/input/input_handler_proxy.h"
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-#include "content/renderer/gpu/input_handler_proxy_client.h"
+#include "cc/base/swap_promise_monitor.h"
+#include "content/renderer/input/input_handler_proxy_client.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebFloatPoint.h"
@@ -16,14 +17,16 @@
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/latency_info.h"
-using WebKit::WebActiveWheelFlingParameters;
-using WebKit::WebFloatPoint;
-using WebKit::WebFloatSize;
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebPoint;
-using WebKit::WebSize;
+using blink::WebActiveWheelFlingParameters;
+using blink::WebFloatPoint;
+using blink::WebFloatSize;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebPoint;
+using blink::WebSize;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
namespace content {
namespace {
@@ -51,8 +54,10 @@ class MockInputHandler : public cc::InputHandler {
MOCK_METHOD0(ScrollEnd, void());
MOCK_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus());
- MOCK_METHOD1(SetLatencyInfoForInputEvent,
- void(const ui::LatencyInfo& latency_info));
+ virtual scoped_ptr<cc::SwapPromiseMonitor>
+ CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) OVERRIDE {
+ return scoped_ptr<cc::SwapPromiseMonitor>();
+ }
virtual void BindToClient(cc::InputHandlerClient* client) OVERRIDE {}
@@ -62,10 +67,10 @@ class MockInputHandler : public cc::InputHandler {
base::TimeDelta duration) OVERRIDE {}
virtual void NotifyCurrentFlingVelocity(gfx::Vector2dF velocity) OVERRIDE {}
+ virtual void MouseMoveAt(gfx::Point mouse_position) OVERRIDE {}
- virtual bool HaveTouchEventHandlersAt(gfx::Point point) OVERRIDE {
- return false;
- }
+ MOCK_METHOD1(HaveTouchEventHandlersAt,
+ bool(gfx::Point point));
virtual void SetRootLayerScrollOffsetDelegate(
cc::LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate)
@@ -78,18 +83,18 @@ class MockInputHandler : public cc::InputHandler {
// A simple WebGestureCurve implementation that flings at a constant velocity
// indefinitely.
-class FakeWebGestureCurve : public WebKit::WebGestureCurve {
+class FakeWebGestureCurve : public blink::WebGestureCurve {
public:
- FakeWebGestureCurve(const WebKit::WebFloatPoint& velocity,
- const WebKit::WebSize& cumulative_scroll)
+ FakeWebGestureCurve(const blink::WebFloatPoint& velocity,
+ const blink::WebSize& cumulative_scroll)
: velocity_(velocity), cumulative_scroll_(cumulative_scroll) {}
virtual ~FakeWebGestureCurve() {}
// Returns false if curve has finished and can no longer be applied.
- virtual bool apply(double time, WebKit::WebGestureCurveTarget* target) {
- WebKit::WebSize displacement(velocity_.x * time, velocity_.y * time);
- WebKit::WebFloatSize increment(
+ virtual bool apply(double time, blink::WebGestureCurveTarget* target) {
+ blink::WebSize displacement(velocity_.x * time, velocity_.y * time);
+ blink::WebFloatSize increment(
displacement.width - cumulative_scroll_.width,
displacement.height - cumulative_scroll_.height);
cumulative_scroll_ = displacement;
@@ -100,8 +105,8 @@ class FakeWebGestureCurve : public WebKit::WebGestureCurve {
}
private:
- WebKit::WebFloatPoint velocity_;
- WebKit::WebSize cumulative_scroll_;
+ blink::WebFloatPoint velocity_;
+ blink::WebSize cumulative_scroll_;
DISALLOW_COPY_AND_ASSIGN(FakeWebGestureCurve);
};
@@ -117,7 +122,7 @@ class MockInputHandlerProxyClient
MOCK_METHOD1(TransferActiveWheelFlingAnimation,
void(const WebActiveWheelFlingParameters&));
- virtual WebKit::WebGestureCurve* CreateFlingAnimationCurve(
+ virtual blink::WebGestureCurve* CreateFlingAnimationCurve(
int deviceSource,
const WebFloatPoint& velocity,
const WebSize& cumulative_scroll) OVERRIDE {
@@ -884,6 +889,63 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) {
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
}
+TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) {
+ // We shouldn't send any events to the widget for this gesture.
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // On the fling start, we should schedule an animation but not actually start
+ // scrolling.
+ base::TimeDelta startTimeOffset = base::TimeDelta::FromMilliseconds(10);
+ gesture_.type = WebInputEvent::GestureFlingStart;
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ WebPoint fling_global_point = WebPoint(17, 23);
+ int modifiers = 7;
+ gesture_.timeStampSeconds = startTimeOffset.InSecondsF();
+ gesture_.data.flingStart.velocityX = fling_delta.x;
+ gesture_.data.flingStart.velocityY = fling_delta.y;
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ gesture_.x = fling_point.x;
+ gesture_.y = fling_point.y;
+ gesture_.globalX = fling_global_point.x;
+ gesture_.globalY = fling_global_point.y;
+ gesture_.modifiers = modifiers;
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
+ EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+ // With a valid time stamp, the first animate call should skip start time
+ // initialization and immediately begin scroll update production. This reduces
+ // the likelihood of a hitch between the scroll preceding the fling and
+ // the first scroll generated by the fling.
+ // Scrolling should start in the -X direction.
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
+ .WillOnce(testing::Return(true));
+ base::TimeTicks time = base::TimeTicks() + 2 * startTimeOffset;
+ input_handler_->Animate(time);
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ gesture_.type = WebInputEvent::GestureFlingCancel;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+}
+
TEST_F(InputHandlerProxyTest,
GestureScrollOnImplThreadFlagClearedAfterFling) {
// We shouldn't send any events to the widget for this gesture.
@@ -1016,5 +1078,75 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) {
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
}
+TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestNegative) {
+ // None of the three touch points fall in the touch region. So the event
+ // should be dropped.
+ expected_disposition_ = InputHandlerProxy::DROP_EVENT;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(mock_input_handler_,
+ HaveTouchEventHandlersAt(
+ testing::Property(&gfx::Point::x, testing::Gt(0))))
+ .WillOnce(testing::Return(false));
+ EXPECT_CALL(mock_input_handler_,
+ HaveTouchEventHandlersAt(
+ testing::Property(&gfx::Point::x, testing::Lt(0))))
+ .WillOnce(testing::Return(false));
+
+ WebTouchEvent touch;
+ touch.type = WebInputEvent::TouchStart;
+
+ touch.touchesLength = 3;
+ touch.touches[0].state = WebTouchPoint::StateStationary;
+ touch.touches[0].screenPosition = WebPoint();
+ touch.touches[0].position = WebPoint();
+
+ touch.touches[1].state = WebTouchPoint::StatePressed;
+ touch.touches[1].screenPosition = WebPoint(10, 10);
+ touch.touches[1].position = WebPoint(10, 10);
+
+ touch.touches[2].state = WebTouchPoint::StatePressed;
+ touch.touches[2].screenPosition = WebPoint(-10, 10);
+ touch.touches[2].position = WebPoint(-10, 10);
+
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
+}
+
+TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestPositive) {
+ // One of the touch points is on a touch-region. So the event should be sent
+ // to the main thread.
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(mock_input_handler_,
+ HaveTouchEventHandlersAt(
+ testing::Property(&gfx::Point::x, testing::Eq(0))))
+ .WillOnce(testing::Return(false));
+ EXPECT_CALL(mock_input_handler_,
+ HaveTouchEventHandlersAt(
+ testing::Property(&gfx::Point::x, testing::Gt(0))))
+ .WillOnce(testing::Return(true));
+ // Since the second touch point hits a touch-region, there should be no
+ // hit-testing for the third touch point.
+
+ WebTouchEvent touch;
+ touch.type = WebInputEvent::TouchStart;
+
+ touch.touchesLength = 3;
+ touch.touches[0].state = WebTouchPoint::StatePressed;
+ touch.touches[0].screenPosition = WebPoint();
+ touch.touches[0].position = WebPoint();
+
+ touch.touches[1].state = WebTouchPoint::StatePressed;
+ touch.touches[1].screenPosition = WebPoint(10, 10);
+ touch.touches[1].position = WebPoint(10, 10);
+
+ touch.touches[2].state = WebTouchPoint::StatePressed;
+ touch.touches[2].screenPosition = WebPoint(-10, 10);
+ touch.touches[2].position = WebPoint(-10, 10);
+
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/renderer/gpu/input_handler_wrapper.cc b/chromium/content/renderer/input/input_handler_wrapper.cc
index 348ff6dc586..14e23ebf3ad 100644
--- a/chromium/content/renderer/gpu/input_handler_wrapper.cc
+++ b/chromium/content/renderer/input/input_handler_wrapper.cc
@@ -1,12 +1,12 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// 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/input_handler_wrapper.h"
+#include "content/renderer/input/input_handler_wrapper.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "content/renderer/gpu/input_event_filter.h"
-#include "content/renderer/gpu/input_handler_manager.h"
+#include "content/renderer/input/input_event_filter.h"
+#include "content/renderer/input/input_handler_manager.h"
#include "third_party/WebKit/public/platform/Platform.h"
namespace content {
@@ -22,6 +22,7 @@ InputHandlerWrapper::InputHandlerWrapper(
input_handler_proxy_(input_handler.get()),
main_loop_(main_loop),
render_view_impl_(render_view_impl) {
+ DCHECK(input_handler);
input_handler_proxy_.SetClient(this);
}
@@ -30,7 +31,7 @@ InputHandlerWrapper::~InputHandlerWrapper() {
}
void InputHandlerWrapper::TransferActiveWheelFlingAnimation(
- const WebKit::WebActiveWheelFlingParameters& params) {
+ const blink::WebActiveWheelFlingParameters& params) {
main_loop_->PostTask(
FROM_HERE,
base::Bind(&RenderViewImpl::TransferActiveWheelFlingAnimation,
@@ -42,11 +43,11 @@ void InputHandlerWrapper::WillShutdown() {
input_handler_manager_->RemoveInputHandler(routing_id_);
}
-WebKit::WebGestureCurve* InputHandlerWrapper::CreateFlingAnimationCurve(
+blink::WebGestureCurve* InputHandlerWrapper::CreateFlingAnimationCurve(
int deviceSource,
- const WebKit::WebFloatPoint& velocity,
- const WebKit::WebSize& cumulative_scroll) {
- return WebKit::Platform::current()->createFlingAnimationCurve(
+ const blink::WebFloatPoint& velocity,
+ const blink::WebSize& cumulative_scroll) {
+ return blink::Platform::current()->createFlingAnimationCurve(
deviceSource, velocity, cumulative_scroll);
}
diff --git a/chromium/content/renderer/gpu/input_handler_wrapper.h b/chromium/content/renderer/input/input_handler_wrapper.h
index f72bae5b12d..562012ace1d 100644
--- a/chromium/content/renderer/gpu/input_handler_wrapper.h
+++ b/chromium/content/renderer/input/input_handler_wrapper.h
@@ -1,28 +1,26 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// 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_INPUT_HANDLER_WRAPPER_H_
-#define CONTENT_RENDERER_GPU_INPUT_HANDLER_WRAPPER_H_
+#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_WRAPPER_H_
+#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_WRAPPER_H_
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "content/renderer/gpu/input_handler_manager.h"
-#include "content/renderer/gpu/input_handler_proxy.h"
-#include "content/renderer/gpu/input_handler_proxy_client.h"
+#include "content/renderer/input/input_handler_manager.h"
+#include "content/renderer/input/input_handler_proxy.h"
+#include "content/renderer/input/input_handler_proxy_client.h"
namespace content {
// This class lives on the compositor thread.
-class InputHandlerWrapper
- : public InputHandlerProxyClient,
- public base::RefCountedThreadSafe<InputHandlerWrapper> {
+class InputHandlerWrapper : public InputHandlerProxyClient {
public:
InputHandlerWrapper(InputHandlerManager* input_handler_manager,
int routing_id,
const scoped_refptr<base::MessageLoopProxy>& main_loop,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl);
+ virtual ~InputHandlerWrapper();
int routing_id() const { return routing_id_; }
InputHandlerProxy* input_handler_proxy() { return &input_handler_proxy_; }
@@ -30,18 +28,14 @@ class InputHandlerWrapper
// InputHandlerProxyClient implementation.
virtual void WillShutdown() OVERRIDE;
virtual void TransferActiveWheelFlingAnimation(
- const WebKit::WebActiveWheelFlingParameters& params) OVERRIDE;
- virtual WebKit::WebGestureCurve* CreateFlingAnimationCurve(
+ const blink::WebActiveWheelFlingParameters& params) OVERRIDE;
+ virtual blink::WebGestureCurve* CreateFlingAnimationCurve(
int deviceSource,
- const WebKit::WebFloatPoint& velocity,
- const WebKit::WebSize& cumulativeScroll) OVERRIDE;
+ const blink::WebFloatPoint& velocity,
+ const blink::WebSize& cumulativeScroll) OVERRIDE;
virtual void DidOverscroll(const cc::DidOverscrollParams& params) OVERRIDE;
private:
- friend class base::RefCountedThreadSafe<InputHandlerWrapper>;
-
- virtual ~InputHandlerWrapper();
-
InputHandlerManager* input_handler_manager_;
int routing_id_;
InputHandlerProxy input_handler_proxy_;
@@ -55,4 +49,4 @@ class InputHandlerWrapper
} // namespace content
-#endif // CONTENT_RENDERER_GPU_INPUT_HANDLER_WRAPPER_H_
+#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_WRAPPER_H_
diff --git a/chromium/content/renderer/input_tag_speech_dispatcher.cc b/chromium/content/renderer/input_tag_speech_dispatcher.cc
index afce8c27cd8..b9490ce7639 100644
--- a/chromium/content/renderer/input_tag_speech_dispatcher.cc
+++ b/chromium/content/renderer/input_tag_speech_dispatcher.cc
@@ -18,18 +18,18 @@
#include "third_party/WebKit/public/web/WebSpeechInputListener.h"
#include "third_party/WebKit/public/web/WebView.h"
-using WebKit::WebDocument;
-using WebKit::WebElement;
-using WebKit::WebFrame;
-using WebKit::WebInputElement;
-using WebKit::WebNode;
-using WebKit::WebView;
+using blink::WebDocument;
+using blink::WebElement;
+using blink::WebFrame;
+using blink::WebInputElement;
+using blink::WebNode;
+using blink::WebView;
namespace content {
InputTagSpeechDispatcher::InputTagSpeechDispatcher(
RenderViewImpl* render_view,
- WebKit::WebSpeechInputListener* listener)
+ blink::WebSpeechInputListener* listener)
: RenderViewObserver(render_view),
listener_(listener) {
}
@@ -53,10 +53,10 @@ bool InputTagSpeechDispatcher::OnMessageReceived(
bool InputTagSpeechDispatcher::startRecognition(
int request_id,
- const WebKit::WebRect& element_rect,
- const WebKit::WebString& language,
- const WebKit::WebString& grammar,
- const WebKit::WebSecurityOrigin& origin) {
+ const blink::WebRect& element_rect,
+ const blink::WebString& language,
+ const blink::WebString& grammar,
+ const blink::WebSecurityOrigin& origin) {
DVLOG(1) << "InputTagSpeechDispatcher::startRecognition enter";
InputTagSpeechHostMsg_StartRecognition_Params params;
@@ -92,7 +92,7 @@ void InputTagSpeechDispatcher::OnSpeechRecognitionResults(
DCHECK_EQ(results.size(), 1U);
const SpeechRecognitionResult& result = results[0];
- WebKit::WebSpeechInputResultArray webkit_result(result.hypotheses.size());
+ blink::WebSpeechInputResultArray webkit_result(result.hypotheses.size());
for (size_t i = 0; i < result.hypotheses.size(); ++i) {
webkit_result[i].assign(result.hypotheses[i].utterance,
result.hypotheses[i].confidence);
@@ -131,8 +131,8 @@ void InputTagSpeechDispatcher::OnSpeechRecognitionToggleSpeechInput() {
if (focused_node.isNull() || !focused_node.isElementNode())
return;
- WebKit::WebElement element = focused_node.to<WebKit::WebElement>();
- WebKit::WebInputElement* input_element = WebKit::toWebInputElement(&element);
+ blink::WebElement element = focused_node.to<blink::WebElement>();
+ blink::WebInputElement* input_element = blink::toWebInputElement(&element);
if (!input_element)
return;
if (!input_element->isSpeechInputEnabled())
diff --git a/chromium/content/renderer/input_tag_speech_dispatcher.h b/chromium/content/renderer/input_tag_speech_dispatcher.h
index b51d7230347..ee9dda99e0e 100644
--- a/chromium/content/renderer/input_tag_speech_dispatcher.h
+++ b/chromium/content/renderer/input_tag_speech_dispatcher.h
@@ -10,7 +10,7 @@
#include "content/public/renderer/render_view_observer.h"
#include "third_party/WebKit/public/web/WebSpeechInputController.h"
-namespace WebKit {
+namespace blink {
class WebSpeechInputListener;
}
@@ -21,21 +21,21 @@ struct SpeechRecognitionResult;
// InputTagSpeechDispatcher is a delegate for messages used by WebKit. It's
// the complement of InputTagSpeechDispatcherHost (owned by RenderViewHost).
class InputTagSpeechDispatcher : public RenderViewObserver,
- public WebKit::WebSpeechInputController {
+ public blink::WebSpeechInputController {
public:
InputTagSpeechDispatcher(RenderViewImpl* render_view,
- WebKit::WebSpeechInputListener* listener);
+ blink::WebSpeechInputListener* listener);
private:
// RenderView::Observer implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- // WebKit::WebSpeechInputController.
+ // blink::WebSpeechInputController.
virtual bool startRecognition(int request_id,
- const WebKit::WebRect& element_rect,
- const WebKit::WebString& language,
- const WebKit::WebString& grammar,
- const WebKit::WebSecurityOrigin& origin);
+ const blink::WebRect& element_rect,
+ const blink::WebString& language,
+ const blink::WebString& grammar,
+ const blink::WebSecurityOrigin& origin);
virtual void cancelRecognition(int request_id);
virtual void stopRecording(int request_id);
@@ -46,7 +46,7 @@ class InputTagSpeechDispatcher : public RenderViewObserver,
void OnSpeechRecognitionComplete(int request_id);
void OnSpeechRecognitionToggleSpeechInput();
- WebKit::WebSpeechInputListener* listener_;
+ blink::WebSpeechInputListener* listener_;
DISALLOW_COPY_AND_ASSIGN(InputTagSpeechDispatcher);
};
diff --git a/chromium/content/renderer/internal_document_state_data.cc b/chromium/content/renderer/internal_document_state_data.cc
index cd400f371eb..e3370dc5e56 100644
--- a/chromium/content/renderer/internal_document_state_data.cc
+++ b/chromium/content/renderer/internal_document_state_data.cc
@@ -25,14 +25,14 @@ InternalDocumentStateData::InternalDocumentStateData()
is_overriding_user_agent_(false),
must_reset_scroll_and_scale_state_(false),
cache_policy_override_set_(false),
- cache_policy_override_(WebKit::WebURLRequest::UseProtocolCachePolicy),
+ cache_policy_override_(blink::WebURLRequest::UseProtocolCachePolicy),
referrer_policy_set_(false),
- referrer_policy_(WebKit::WebReferrerPolicyDefault) {
+ referrer_policy_(blink::WebReferrerPolicyDefault) {
}
// static
InternalDocumentStateData* InternalDocumentStateData::FromDataSource(
- WebKit::WebDataSource* ds) {
+ blink::WebDataSource* ds) {
return FromDocumentState(static_cast<DocumentState*>(ds->extraData()));
}
diff --git a/chromium/content/renderer/internal_document_state_data.h b/chromium/content/renderer/internal_document_state_data.h
index 9fba893461d..6d2f2bc868d 100644
--- a/chromium/content/renderer/internal_document_state_data.h
+++ b/chromium/content/renderer/internal_document_state_data.h
@@ -13,7 +13,7 @@
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "url/gurl.h"
-namespace WebKit {
+namespace blink {
class WebDataSource;
}
@@ -27,7 +27,7 @@ class InternalDocumentStateData : public base::SupportsUserData::Data {
public:
InternalDocumentStateData();
- static InternalDocumentStateData* FromDataSource(WebKit::WebDataSource* ds);
+ static InternalDocumentStateData* FromDataSource(blink::WebDataSource* ds);
static InternalDocumentStateData* FromDocumentState(DocumentState* ds);
// Set to true once RenderViewImpl::didFirstVisuallyNonEmptyLayout() is
@@ -89,16 +89,16 @@ class InternalDocumentStateData : public base::SupportsUserData::Data {
// by default is not set. You can mark a NavigationState as not having a cache
// state by way of clear_cache_policy_override.
void set_cache_policy_override(
- WebKit::WebURLRequest::CachePolicy cache_policy) {
+ blink::WebURLRequest::CachePolicy cache_policy) {
cache_policy_override_ = cache_policy;
cache_policy_override_set_ = true;
}
- WebKit::WebURLRequest::CachePolicy cache_policy_override() const {
+ blink::WebURLRequest::CachePolicy cache_policy_override() const {
return cache_policy_override_;
}
void clear_cache_policy_override() {
cache_policy_override_set_ = false;
- cache_policy_override_ = WebKit::WebURLRequest::UseProtocolCachePolicy;
+ cache_policy_override_ = blink::WebURLRequest::UseProtocolCachePolicy;
}
bool is_cache_policy_override_set() const {
return cache_policy_override_set_;
@@ -107,15 +107,15 @@ class InternalDocumentStateData : public base::SupportsUserData::Data {
// Sets the referrer policy to use. This is only used for browser initiated
// navigations, otherwise, the referrer policy is defined by the frame's
// document.
- WebKit::WebReferrerPolicy referrer_policy() const {
+ blink::WebReferrerPolicy referrer_policy() const {
return referrer_policy_;
}
- void set_referrer_policy(WebKit::WebReferrerPolicy referrer_policy) {
+ void set_referrer_policy(blink::WebReferrerPolicy referrer_policy) {
referrer_policy_ = referrer_policy;
referrer_policy_set_ = true;
}
void clear_referrer_policy() {
- referrer_policy_ = WebKit::WebReferrerPolicyDefault;
+ referrer_policy_ = blink::WebReferrerPolicyDefault;
referrer_policy_set_ = false;
}
bool is_referrer_policy_set() const { return referrer_policy_set_; }
@@ -138,9 +138,9 @@ class InternalDocumentStateData : public base::SupportsUserData::Data {
bool is_overriding_user_agent_;
bool must_reset_scroll_and_scale_state_;
bool cache_policy_override_set_;
- WebKit::WebURLRequest::CachePolicy cache_policy_override_;
+ blink::WebURLRequest::CachePolicy cache_policy_override_;
bool referrer_policy_set_;
- WebKit::WebReferrerPolicy referrer_policy_;
+ blink::WebReferrerPolicy referrer_policy_;
scoped_ptr<AltErrorPageResourceFetcher> alt_error_page_fetcher_;
DISALLOW_COPY_AND_ASSIGN(InternalDocumentStateData);
diff --git a/chromium/content/renderer/java/OWNERS b/chromium/content/renderer/java/OWNERS
index 4b297c43ee6..d378671071d 100644
--- a/chromium/content/renderer/java/OWNERS
+++ b/chromium/content/renderer/java/OWNERS
@@ -1,2 +1,2 @@
-joth@chromium.org
steveblock@chromium.org
+torne@chromium.org
diff --git a/chromium/content/renderer/java/java_bridge_channel.cc b/chromium/content/renderer/java/java_bridge_channel.cc
index 235425ab4ff..0d6d3f6c35f 100644
--- a/chromium/content/renderer/java/java_bridge_channel.cc
+++ b/chromium/content/renderer/java/java_bridge_channel.cc
@@ -27,12 +27,12 @@ JavaBridgeChannel::JavaBridgeChannel()
: peer_owner_id_(new struct _NPP) {
// Register the dummy owner Id for our peer (the Browser process) as an object
// owner, and have all objects received from the peer owned by it.
- WebKit::WebBindings::registerObjectOwner(peer_owner_id_.get());
+ blink::WebBindings::registerObjectOwner(peer_owner_id_.get());
SetDefaultNPObjectOwner(peer_owner_id_.get());
}
JavaBridgeChannel::~JavaBridgeChannel() {
- WebKit::WebBindings::unregisterObjectOwner(peer_owner_id_.get());
+ blink::WebBindings::unregisterObjectOwner(peer_owner_id_.get());
}
int JavaBridgeChannel::GenerateRouteID() {
diff --git a/chromium/content/renderer/java/java_bridge_dispatcher.cc b/chromium/content/renderer/java/java_bridge_dispatcher.cc
index 376ecb1e481..f7e435cf2b1 100644
--- a/chromium/content/renderer/java/java_bridge_dispatcher.cc
+++ b/chromium/content/renderer/java/java_bridge_dispatcher.cc
@@ -36,7 +36,7 @@ void JavaBridgeDispatcher::EnsureChannelIsSetUp() {
JavaBridgeDispatcher::~JavaBridgeDispatcher() {
for (ObjectMap::const_iterator iter = objects_.begin();
iter != objects_.end(); ++iter) {
- WebKit::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second));
+ blink::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second));
}
}
@@ -51,7 +51,7 @@ bool JavaBridgeDispatcher::OnMessageReceived(const IPC::Message& msg) {
return handled;
}
-void JavaBridgeDispatcher::DidClearWindowObject(WebKit::WebFrame* web_frame) {
+void JavaBridgeDispatcher::DidClearWindowObject(blink::WebFrame* web_frame) {
// Note that we have to (re)bind all objects, as they will have been unbound
// when the window object was cleared.
for (ObjectMap::const_iterator iter = objects_.begin();
@@ -65,7 +65,7 @@ void JavaBridgeDispatcher::DidClearWindowObject(WebKit::WebFrame* web_frame) {
}
void JavaBridgeDispatcher::OnAddNamedObject(
- const string16& name,
+ const base::string16& name,
const NPVariant_Param& variant_param) {
DCHECK_EQ(variant_param.type, NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID);
@@ -90,12 +90,12 @@ void JavaBridgeDispatcher::OnAddNamedObject(
// OnRemoveNamedObject() is called for that object.
ObjectMap::iterator iter = objects_.find(name);
if (iter != objects_.end()) {
- WebKit::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second));
+ blink::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second));
}
objects_[name] = variant;
}
-void JavaBridgeDispatcher::OnRemoveNamedObject(const string16& name) {
+void JavaBridgeDispatcher::OnRemoveNamedObject(const base::string16& name) {
if (!channel_.get()) {
DCHECK(objects_.empty());
return;
@@ -106,7 +106,7 @@ void JavaBridgeDispatcher::OnRemoveNamedObject(const string16& name) {
// is present.
ObjectMap::iterator iter = objects_.find(name);
DCHECK(iter != objects_.end());
- WebKit::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second));
+ blink::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second));
objects_.erase(iter);
}
diff --git a/chromium/content/renderer/java/java_bridge_dispatcher.h b/chromium/content/renderer/java/java_bridge_dispatcher.h
index 29a10374590..325d5291851 100644
--- a/chromium/content/renderer/java/java_bridge_dispatcher.h
+++ b/chromium/content/renderer/java/java_bridge_dispatcher.h
@@ -30,18 +30,18 @@ class JavaBridgeDispatcher : public RenderViewObserver {
private:
// RenderViewObserver override:
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE;
+ virtual void DidClearWindowObject(blink::WebFrame* frame) OVERRIDE;
// Message handlers
- void OnAddNamedObject(const string16& name,
+ void OnAddNamedObject(const base::string16& name,
const NPVariant_Param& variant_param);
- void OnRemoveNamedObject(const string16& name);
+ void OnRemoveNamedObject(const base::string16& name);
void EnsureChannelIsSetUp();
// Objects that will be bound to the window when the window object is next
// cleared. We hold a ref to these.
- typedef std::map<string16, NPVariant> ObjectMap;
+ typedef std::map<base::string16, NPVariant> ObjectMap;
ObjectMap objects_;
scoped_refptr<JavaBridgeChannel> channel_;
};
diff --git a/chromium/content/renderer/load_progress_tracker.cc b/chromium/content/renderer/load_progress_tracker.cc
index 3a04b7232d1..0cc26fdcccf 100644
--- a/chromium/content/renderer/load_progress_tracker.cc
+++ b/chromium/content/renderer/load_progress_tracker.cc
@@ -38,7 +38,7 @@ void LoadProgressTracker::DidStopLoading() {
ResetStates();
}
-void LoadProgressTracker::DidChangeLoadProgress(WebKit::WebFrame* frame,
+void LoadProgressTracker::DidChangeLoadProgress(blink::WebFrame* frame,
double progress) {
if (tracked_frame_ && frame != tracked_frame_)
return;
diff --git a/chromium/content/renderer/load_progress_tracker.h b/chromium/content/renderer/load_progress_tracker.h
index a23935027d1..c4ed37eca9d 100644
--- a/chromium/content/renderer/load_progress_tracker.h
+++ b/chromium/content/renderer/load_progress_tracker.h
@@ -9,7 +9,7 @@
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
}
@@ -23,7 +23,7 @@ class LoadProgressTracker {
void DidStopLoading();
- void DidChangeLoadProgress(WebKit::WebFrame* frame, double progress);
+ void DidChangeLoadProgress(blink::WebFrame* frame, double progress);
private:
void ResetStates();
@@ -32,7 +32,7 @@ class LoadProgressTracker {
RenderViewImpl* render_view_;
- WebKit::WebFrame* tracked_frame_;
+ blink::WebFrame* tracked_frame_;
double progress_;
diff --git a/chromium/content/renderer/media/active_loader.cc b/chromium/content/renderer/media/active_loader.cc
index e7601ea6bca..6951514e5b1 100644
--- a/chromium/content/renderer/media/active_loader.cc
+++ b/chromium/content/renderer/media/active_loader.cc
@@ -9,7 +9,7 @@
namespace content {
-ActiveLoader::ActiveLoader(scoped_ptr<WebKit::WebURLLoader> loader)
+ActiveLoader::ActiveLoader(scoped_ptr<blink::WebURLLoader> loader)
: loader_(loader.Pass()),
deferred_(false) {
}
diff --git a/chromium/content/renderer/media/active_loader.h b/chromium/content/renderer/media/active_loader.h
index 751e6a96c46..1c30214b92c 100644
--- a/chromium/content/renderer/media/active_loader.h
+++ b/chromium/content/renderer/media/active_loader.h
@@ -8,7 +8,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-namespace WebKit {
+namespace blink {
class WebURLLoader;
}
@@ -21,7 +21,7 @@ class ActiveLoader {
public:
// Creates an ActiveLoader with the given loader. It is assumed that the
// initial state of |loader| is loading and not deferred.
- explicit ActiveLoader(scoped_ptr<WebKit::WebURLLoader> loader);
+ explicit ActiveLoader(scoped_ptr<blink::WebURLLoader> loader);
~ActiveLoader();
// Starts or stops deferring the resource load.
@@ -31,7 +31,7 @@ class ActiveLoader {
private:
friend class BufferedDataSourceTest;
- scoped_ptr<WebKit::WebURLLoader> loader_;
+ scoped_ptr<blink::WebURLLoader> loader_;
bool deferred_;
DISALLOW_IMPLICIT_CONSTRUCTORS(ActiveLoader);
diff --git a/chromium/content/renderer/media/android/audio_decoder_android.cc b/chromium/content/renderer/media/android/audio_decoder_android.cc
index afc6dec62e3..b589d67412c 100644
--- a/chromium/content/renderer/media/android/audio_decoder_android.cc
+++ b/chromium/content/renderer/media/android/audio_decoder_android.cc
@@ -113,7 +113,7 @@ class WAVEDecoder {
// WAVE file, |destination_bus| is filled with the decoded data and
// DecodeWAVEFile returns true. Otherwise, DecodeWAVEFile returns
// false.
- bool DecodeWAVEFile(WebKit::WebAudioBus* destination_bus);
+ bool DecodeWAVEFile(blink::WebAudioBus* destination_bus);
private:
// Minimum number of bytes in a WAVE file to hold all of the data we
@@ -157,7 +157,7 @@ class WAVEDecoder {
// Read data chunk and save it to |destination_bus|. Returns false
// if the data chunk could not be read correctly.
- bool CopyDataChunkToBus(WebKit::WebAudioBus* destination_bus);
+ bool CopyDataChunkToBus(blink::WebAudioBus* destination_bus);
// The WAVE chunk ID that identifies the chunk.
uint8_t chunk_id_[kChunkIDLength];
@@ -293,7 +293,7 @@ bool WAVEDecoder::ReadFMTChunk() {
return false;
}
-bool WAVEDecoder::CopyDataChunkToBus(WebKit::WebAudioBus* destination_bus) {
+bool WAVEDecoder::CopyDataChunkToBus(blink::WebAudioBus* destination_bus) {
// The data chunk contains the audio data itself.
if (!bytes_per_sample_ || bytes_per_sample_ > kMaximumBytesPerSample) {
DVLOG(1) << "WARNING: data chunk without preceeding fmt chunk,"
@@ -326,7 +326,7 @@ bool WAVEDecoder::CopyDataChunkToBus(WebKit::WebAudioBus* destination_bus) {
return true;
}
-bool WAVEDecoder::DecodeWAVEFile(WebKit::WebAudioBus* destination_bus) {
+bool WAVEDecoder::DecodeWAVEFile(blink::WebAudioBus* destination_bus) {
// Parse and decode WAVE file. If we can't parse it, return false.
if (buffer_ + kMinimumWAVLength > buffer_end_) {
@@ -395,7 +395,7 @@ bool WAVEDecoder::DecodeWAVEFile(WebKit::WebAudioBus* destination_bus) {
// bus and copy the pcm data to the destination bus as it's being
// received.
static void CopyPcmDataToBus(int input_fd,
- WebKit::WebAudioBus* destination_bus,
+ blink::WebAudioBus* destination_bus,
size_t number_of_frames,
unsigned number_of_channels,
double file_sample_rate) {
@@ -433,7 +433,7 @@ static void CopyPcmDataToBus(int input_fd,
// until there's no more data and then copy the data to the
// destination bus.
static void BufferAndCopyPcmDataToBus(int input_fd,
- WebKit::WebAudioBus* destination_bus,
+ blink::WebAudioBus* destination_bus,
unsigned number_of_channels,
double file_sample_rate) {
int16_t pipe_data[PIPE_BUF / sizeof(int16_t)];
@@ -478,7 +478,7 @@ static void BufferAndCopyPcmDataToBus(int input_fd,
destination_bus->resizeSmaller(decoded_frames);
}
-static bool TryWAVEFileDecoder(WebKit::WebAudioBus* destination_bus,
+static bool TryWAVEFileDecoder(blink::WebAudioBus* destination_bus,
const uint8_t* encoded_data,
size_t data_size) {
WAVEDecoder decoder(encoded_data, data_size);
@@ -493,7 +493,7 @@ static bool TryWAVEFileDecoder(WebKit::WebAudioBus* destination_bus,
// to the browser to start the decoder using this buffer and one end
// of a pipe. The MediaCodec class will decode the data from the
// shared memory and write the PCM samples back to us over a pipe.
-bool DecodeAudioFileData(WebKit::WebAudioBus* destination_bus, const char* data,
+bool DecodeAudioFileData(blink::WebAudioBus* destination_bus, const char* data,
size_t data_size, double sample_rate,
scoped_refptr<ThreadSafeSender> sender) {
// Try to decode the data as a WAVE file first. If it can't be
diff --git a/chromium/content/renderer/media/android/audio_decoder_android.h b/chromium/content/renderer/media/android/audio_decoder_android.h
index c6c3b403b6a..d2cac1575df 100644
--- a/chromium/content/renderer/media/android/audio_decoder_android.h
+++ b/chromium/content/renderer/media/android/audio_decoder_android.h
@@ -7,13 +7,13 @@
#include "content/child/thread_safe_sender.h"
-namespace WebKit {
+namespace blink {
class WebAudioBus;
}
namespace content {
-bool DecodeAudioFileData(WebKit::WebAudioBus* destination_bus,
+bool DecodeAudioFileData(blink::WebAudioBus* destination_bus,
const char* data,
size_t data_size,
double sample_rate,
diff --git a/chromium/content/renderer/media/android/media_info_loader.cc b/chromium/content/renderer/media/android/media_info_loader.cc
index 1025550580b..875265c41c5 100644
--- a/chromium/content/renderer/media/android/media_info_loader.cc
+++ b/chromium/content/renderer/media/android/media_info_loader.cc
@@ -12,12 +12,12 @@
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebFrame.h"
-using WebKit::WebFrame;
-using WebKit::WebURLError;
-using WebKit::WebURLLoader;
-using WebKit::WebURLLoaderOptions;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
+using blink::WebFrame;
+using blink::WebURLError;
+using blink::WebURLLoader;
+using blink::WebURLLoaderOptions;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
namespace content {
@@ -25,7 +25,7 @@ static const int kHttpOK = 200;
MediaInfoLoader::MediaInfoLoader(
const GURL& url,
- WebKit::WebMediaPlayer::CORSMode cors_mode,
+ blink::WebMediaPlayer::CORSMode cors_mode,
const ReadyCB& ready_cb)
: loader_failed_(false),
url_(url),
@@ -35,7 +35,7 @@ MediaInfoLoader::MediaInfoLoader(
MediaInfoLoader::~MediaInfoLoader() {}
-void MediaInfoLoader::Start(WebKit::WebFrame* frame) {
+void MediaInfoLoader::Start(blink::WebFrame* frame) {
// Make sure we have not started.
DCHECK(!ready_cb_.is_null());
CHECK(frame);
@@ -45,22 +45,24 @@ void MediaInfoLoader::Start(WebKit::WebFrame* frame) {
// Prepare the request.
WebURLRequest request(url_);
request.setTargetType(WebURLRequest::TargetIsMedia);
- frame->setReferrerForRequest(request, WebKit::WebURL());
+ frame->setReferrerForRequest(request, blink::WebURL());
scoped_ptr<WebURLLoader> loader;
if (test_loader_) {
loader = test_loader_.Pass();
} else {
WebURLLoaderOptions options;
- if (cors_mode_ == WebKit::WebMediaPlayer::CORSModeUnspecified) {
+ if (cors_mode_ == blink::WebMediaPlayer::CORSModeUnspecified) {
options.allowCredentials = true;
options.crossOriginRequestPolicy =
WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
} else {
options.exposeAllResponseHeaders = true;
+ // The author header set is empty, no preflight should go ahead.
+ options.preflightPolicy = WebURLLoaderOptions::PreventPreflight;
options.crossOriginRequestPolicy =
WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
- if (cors_mode_ == WebKit::WebMediaPlayer::CORSModeUseCredentials)
+ if (cors_mode_ == blink::WebMediaPlayer::CORSModeUseCredentials)
options.allowCredentials = true;
}
loader.reset(frame->createAssociatedURLLoader(options));
@@ -72,7 +74,7 @@ void MediaInfoLoader::Start(WebKit::WebFrame* frame) {
}
/////////////////////////////////////////////////////////////////////////////
-// WebKit::WebURLLoaderClient implementation.
+// blink::WebURLLoaderClient implementation.
void MediaInfoLoader::willSendRequest(
WebURLLoader* loader,
WebURLRequest& newRequest,
@@ -81,7 +83,7 @@ void MediaInfoLoader::willSendRequest(
// In this case we shouldn't do anything.
if (ready_cb_.is_null()) {
// Set the url in the request to an invalid value (empty url).
- newRequest.setURL(WebKit::WebURL());
+ newRequest.setURL(blink::WebURL());
return;
}
@@ -109,7 +111,11 @@ void MediaInfoLoader::didReceiveResponse(
"Unknown")
<< " " << response.httpStatusCode();
DCHECK(active_loader_.get());
- if (response.httpStatusCode() == kHttpOK || url_.SchemeIsFile()) {
+ if (!url_.SchemeIs("http") && !url_.SchemeIs("https")) {
+ DidBecomeReady(kOk);
+ return;
+ }
+ if (response.httpStatusCode() == kHttpOK) {
DidBecomeReady(kOk);
return;
}
@@ -126,7 +132,7 @@ void MediaInfoLoader::didReceiveData(
}
void MediaInfoLoader::didDownloadData(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
int dataLength,
int encodedDataLength) {
NOTIMPLEMENTED();
@@ -169,7 +175,7 @@ bool MediaInfoLoader::DidPassCORSAccessCheck() const {
DCHECK(ready_cb_.is_null())
<< "Must become ready before calling DidPassCORSAccessCheck()";
return !loader_failed_ &&
- cors_mode_ != WebKit::WebMediaPlayer::CORSModeUnspecified;
+ cors_mode_ != blink::WebMediaPlayer::CORSModeUnspecified;
}
/////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/content/renderer/media/android/media_info_loader.h b/chromium/content/renderer/media/android/media_info_loader.h
index 5a6fc054b22..8e67c80c0c9 100644
--- a/chromium/content/renderer/media/android/media_info_loader.h
+++ b/chromium/content/renderer/media/android/media_info_loader.h
@@ -12,11 +12,11 @@
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/renderer/media/active_loader.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
-#include "third_party/WebKit/public/web/WebMediaPlayer.h"
#include "url/gurl.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebURLLoader;
class WebURLRequest;
@@ -27,7 +27,7 @@ namespace content {
// This class provides additional information about a media URL. Currently it
// can be used to determine if a media URL has a single security origin and
// whether the URL passes a CORS access check.
-class CONTENT_EXPORT MediaInfoLoader : private WebKit::WebURLLoaderClient {
+class CONTENT_EXPORT MediaInfoLoader : private blink::WebURLLoaderClient {
public:
// Status codes for start operations on MediaInfoLoader.
enum Status {
@@ -51,12 +51,12 @@ class CONTENT_EXPORT MediaInfoLoader : private WebKit::WebURLLoaderClient {
typedef base::Callback<void(Status)> ReadyCB;
MediaInfoLoader(
const GURL& url,
- WebKit::WebMediaPlayer::CORSMode cors_mode,
+ blink::WebMediaPlayer::CORSMode cors_mode,
const ReadyCB& ready_cb);
virtual ~MediaInfoLoader();
// Start loading media info.
- void Start(WebKit::WebFrame* frame);
+ void Start(blink::WebFrame* frame);
// Returns true if the media resource has a single origin, false otherwise.
// Only valid to call after the loader becomes ready.
@@ -69,48 +69,48 @@ class CONTENT_EXPORT MediaInfoLoader : private WebKit::WebURLLoaderClient {
private:
friend class MediaInfoLoaderTest;
- // WebKit::WebURLLoaderClient implementation.
+ // blink::WebURLLoaderClient implementation.
virtual void willSendRequest(
- WebKit::WebURLLoader* loader,
- WebKit::WebURLRequest& newRequest,
- const WebKit::WebURLResponse& redirectResponse);
+ blink::WebURLLoader* loader,
+ blink::WebURLRequest& newRequest,
+ const blink::WebURLResponse& redirectResponse);
virtual void didSendData(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
unsigned long long bytesSent,
unsigned long long totalBytesToBeSent);
virtual void didReceiveResponse(
- WebKit::WebURLLoader* loader,
- const WebKit::WebURLResponse& response);
+ blink::WebURLLoader* loader,
+ const blink::WebURLResponse& response);
virtual void didDownloadData(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
int data_length,
int encodedDataLength);
virtual void didReceiveData(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
const char* data,
int data_length,
int encoded_data_length);
virtual void didReceiveCachedMetadata(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
const char* data, int dataLength);
virtual void didFinishLoading(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
double finishTime);
virtual void didFail(
- WebKit::WebURLLoader* loader,
- const WebKit::WebURLError&);
+ blink::WebURLLoader* loader,
+ const blink::WebURLError&);
void DidBecomeReady(Status status);
// Injected WebURLLoader instance for testing purposes.
- scoped_ptr<WebKit::WebURLLoader> test_loader_;
+ scoped_ptr<blink::WebURLLoader> test_loader_;
// Keeps track of an active WebURLLoader and associated state.
scoped_ptr<ActiveLoader> active_loader_;
bool loader_failed_;
GURL url_;
- WebKit::WebMediaPlayer::CORSMode cors_mode_;
+ blink::WebMediaPlayer::CORSMode cors_mode_;
bool single_origin_;
ReadyCB ready_cb_;
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 37e41b18a04..65bfba8e77c 100644
--- a/chromium/content/renderer/media/android/media_info_loader_unittest.cc
+++ b/chromium/content/renderer/media/android/media_info_loader_unittest.cc
@@ -5,25 +5,22 @@
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "content/renderer/media/android/media_info_loader.h"
+#include "content/test/mock_webframeclient.h"
+#include "content/test/mock_weburlloader.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "third_party/WebKit/public/web/WebMediaPlayer.h"
#include "third_party/WebKit/public/web/WebView.h"
-#include "webkit/mocks/mock_webframeclient.h"
-#include "webkit/mocks/mock_weburlloader.h"
using ::testing::_;
using ::testing::InSequence;
using ::testing::NiceMock;
-using WebKit::WebString;
-using WebKit::WebURLError;
-using WebKit::WebURLResponse;
-using WebKit::WebView;
-
-using webkit_glue::MockWebFrameClient;
-using webkit_glue::MockWebURLLoader;
+using blink::WebString;
+using blink::WebURLError;
+using blink::WebURLResponse;
+using blink::WebView;
namespace content {
@@ -48,7 +45,7 @@ class MediaInfoLoaderTest : public testing::Test {
void Initialize(
const char* url,
- WebKit::WebMediaPlayer::CORSMode cors_mode) {
+ blink::WebMediaPlayer::CORSMode cors_mode) {
gurl_ = GURL(url);
loader_.reset(new MediaInfoLoader(
@@ -58,7 +55,7 @@ class MediaInfoLoaderTest : public testing::Test {
// |test_loader_| will be used when Start() is called.
url_loader_ = new NiceMock<MockWebURLLoader>();
- loader_->test_loader_ = scoped_ptr<WebKit::WebURLLoader>(url_loader_);
+ loader_->test_loader_ = scoped_ptr<blink::WebURLLoader>(url_loader_);
}
void Start() {
@@ -75,8 +72,8 @@ class MediaInfoLoaderTest : public testing::Test {
void Redirect(const char* url) {
GURL redirect_url(url);
- WebKit::WebURLRequest new_request(redirect_url);
- WebKit::WebURLResponse redirect_response(gurl_);
+ blink::WebURLRequest new_request(redirect_url);
+ blink::WebURLResponse redirect_response(gurl_);
loader_->willSendRequest(url_loader_, new_request, redirect_response);
@@ -119,20 +116,20 @@ class MediaInfoLoaderTest : public testing::Test {
};
TEST_F(MediaInfoLoaderTest, StartStop) {
- Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified);
+ Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified);
Start();
Stop();
}
TEST_F(MediaInfoLoaderTest, LoadFailure) {
- Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified);
+ Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified);
Start();
FailLoad();
}
TEST_F(MediaInfoLoaderTest, HasSingleOriginNoRedirect) {
// Make sure no redirect case works as expected.
- Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified);
+ Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified);
Start();
SendResponse(kHttpOK, MediaInfoLoader::kOk);
EXPECT_TRUE(loader_->HasSingleOrigin());
@@ -140,7 +137,7 @@ TEST_F(MediaInfoLoaderTest, HasSingleOriginNoRedirect) {
TEST_F(MediaInfoLoaderTest, HasSingleOriginSingleRedirect) {
// Test redirect to the same domain.
- Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified);
+ Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified);
Start();
Redirect(kHttpRedirectToSameDomainUrl1);
SendResponse(kHttpOK, MediaInfoLoader::kOk);
@@ -149,7 +146,7 @@ TEST_F(MediaInfoLoaderTest, HasSingleOriginSingleRedirect) {
TEST_F(MediaInfoLoaderTest, HasSingleOriginDoubleRedirect) {
// Test redirect twice to the same domain.
- Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified);
+ Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified);
Start();
Redirect(kHttpRedirectToSameDomainUrl1);
Redirect(kHttpRedirectToSameDomainUrl2);
@@ -159,7 +156,7 @@ TEST_F(MediaInfoLoaderTest, HasSingleOriginDoubleRedirect) {
TEST_F(MediaInfoLoaderTest, HasSingleOriginDifferentDomain) {
// Test redirect to a different domain.
- Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified);
+ Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified);
Start();
Redirect(kHttpRedirectToDifferentDomainUrl1);
SendResponse(kHttpOK, MediaInfoLoader::kOk);
@@ -168,7 +165,7 @@ TEST_F(MediaInfoLoaderTest, HasSingleOriginDifferentDomain) {
TEST_F(MediaInfoLoaderTest, HasSingleOriginMultipleDomains) {
// Test redirect to the same domain and then to a different domain.
- Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified);
+ Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified);
Start();
Redirect(kHttpRedirectToSameDomainUrl1);
Redirect(kHttpRedirectToDifferentDomainUrl1);
@@ -177,14 +174,14 @@ TEST_F(MediaInfoLoaderTest, HasSingleOriginMultipleDomains) {
}
TEST_F(MediaInfoLoaderTest, CORSAccessCheckPassed) {
- Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUseCredentials);
+ Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUseCredentials);
Start();
SendResponse(kHttpOK, MediaInfoLoader::kOk);
EXPECT_TRUE(loader_->DidPassCORSAccessCheck());
}
TEST_F(MediaInfoLoaderTest, CORSAccessCheckFailed) {
- Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUseCredentials);
+ Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUseCredentials);
Start();
SendResponse(kHttpNotFound, MediaInfoLoader::kFailed);
EXPECT_FALSE(loader_->DidPassCORSAccessCheck());
diff --git a/chromium/content/renderer/media/android/media_source_delegate.cc b/chromium/content/renderer/media/android/media_source_delegate.cc
index eae0fe11301..57fc0157ca4 100644
--- a/chromium/content/renderer/media/android/media_source_delegate.cc
+++ b/chromium/content/renderer/media/android/media_source_delegate.cc
@@ -25,8 +25,8 @@
using media::DemuxerStream;
using media::DemuxerConfigs;
using media::DemuxerData;
-using WebKit::WebMediaPlayer;
-using WebKit::WebString;
+using blink::WebMediaPlayer;
+using blink::WebString;
namespace {
@@ -40,13 +40,6 @@ const uint8 kVorbisPadding[] = { 0xff, 0xff, 0xff, 0xff };
namespace content {
-static scoped_ptr<media::TextTrack> ReturnNullTextTrack(
- media::TextKind kind,
- const std::string& label,
- const std::string& language) {
- return scoped_ptr<media::TextTrack>();
-}
-
static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log,
const std::string& error) {
media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error));
@@ -70,7 +63,9 @@ MediaSourceDelegate::MediaSourceDelegate(
audio_stream_(NULL),
video_stream_(NULL),
seeking_(false),
- last_seek_request_id_(0),
+ doing_browser_seek_(false),
+ browser_seek_time_(media::kNoTimestamp()),
+ expecting_regular_seek_(false),
#if defined(GOOGLE_TV)
key_added_(false),
#endif
@@ -101,7 +96,6 @@ void MediaSourceDelegate::Destroy() {
}
duration_change_cb_.Reset();
- time_update_seek_hack_cb_.Reset();
update_network_state_cb_.Reset();
media_source_opened_cb_.Reset();
@@ -145,11 +139,10 @@ void MediaSourceDelegate::StopDemuxer() {
void MediaSourceDelegate::InitializeMediaSource(
const MediaSourceOpenedCB& media_source_opened_cb,
- const media::NeedKeyCB& need_key_cb,
+ const media::Demuxer::NeedKeyCB& need_key_cb,
const media::SetDecryptorReadyCB& set_decryptor_ready_cb,
const UpdateNetworkStateCB& update_network_state_cb,
- const DurationChangeCB& duration_change_cb,
- const TimeUpdateSeekHackCB& time_update_seek_hack_cb) {
+ const DurationChangeCB& duration_change_cb) {
DCHECK(main_loop_->BelongsToCurrentThread());
DCHECK(!media_source_opened_cb.is_null());
media_source_opened_cb_ = media_source_opened_cb;
@@ -157,7 +150,6 @@ void MediaSourceDelegate::InitializeMediaSource(
set_decryptor_ready_cb_ = set_decryptor_ready_cb;
update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb);
duration_change_cb_ = duration_change_cb;
- time_update_seek_hack_cb_ = time_update_seek_hack_cb;
access_unit_size_ = kAccessUnitSizeForMediaSource;
chunk_demuxer_.reset(new media::ChunkDemuxer(
@@ -165,7 +157,6 @@ void MediaSourceDelegate::InitializeMediaSource(
&MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)),
media::BindToCurrentLoop(base::Bind(
&MediaSourceDelegate::OnNeedKey, main_weak_this_)),
- base::Bind(&ReturnNullTextTrack),
base::Bind(&LogMediaSourceError, media_log_)));
demuxer_ = chunk_demuxer_.get();
@@ -180,7 +171,8 @@ void MediaSourceDelegate::InitializeDemuxer() {
DCHECK(media_loop_->BelongsToCurrentThread());
demuxer_client_->AddDelegate(demuxer_client_id_, this);
demuxer_->Initialize(this, base::Bind(&MediaSourceDelegate::OnDemuxerInitDone,
- media_weak_factory_.GetWeakPtr()));
+ media_weak_factory_.GetWeakPtr()),
+ false);
}
#if defined(GOOGLE_TV)
@@ -203,7 +195,7 @@ void MediaSourceDelegate::InitializeMediaStream(
}
#endif
-const WebKit::WebTimeRanges& MediaSourceDelegate::Buffered() {
+const blink::WebTimeRanges& MediaSourceDelegate::Buffered() {
buffered_web_time_ranges_ =
ConvertToWebTimeRanges(buffered_time_ranges_);
return buffered_web_time_ranges_;
@@ -225,46 +217,106 @@ size_t MediaSourceDelegate::VideoDecodedByteCount() const {
return statistics_.video_bytes_decoded;
}
-void MediaSourceDelegate::Seek(const base::TimeDelta& time,
- unsigned seek_request_id) {
- DCHECK(media_loop_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << "(" << time.InSecondsF() << ") : "
+void MediaSourceDelegate::CancelPendingSeek(const base::TimeDelta& seek_time) {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+ DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : "
<< demuxer_client_id_;
- last_seek_time_ = time;
- last_seek_request_id_ = seek_request_id;
+ if (!chunk_demuxer_)
+ return;
+
+ {
+ // Remember to trivially finish any newly arriving browser seek requests
+ // that may arrive prior to the next regular seek request.
+ base::AutoLock auto_lock(seeking_lock_);
+ expecting_regular_seek_ = true;
+ }
+
+ // Cancel any previously expected or in-progress regular or browser seek.
+ // It is possible that we have just finished the seek, but caller does
+ // not know this yet. It is still safe to cancel in this case because the
+ // caller will always call StartWaitingForSeek() when it is notified of
+ // the finished seek.
+ chunk_demuxer_->CancelPendingSeek(seek_time);
+}
+
+void MediaSourceDelegate::StartWaitingForSeek(
+ const base::TimeDelta& seek_time) {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+ DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : "
+ << demuxer_client_id_;
- if (chunk_demuxer_) {
- if (IsSeeking()) {
- chunk_demuxer_->CancelPendingSeek(time);
+ if (!chunk_demuxer_)
+ return;
+
+ bool cancel_browser_seek = false;
+ {
+ // Remember to trivially finish any newly arriving browser seek requests
+ // that may arrive prior to the next regular seek request.
+ base::AutoLock auto_lock(seeking_lock_);
+ expecting_regular_seek_ = true;
+
+ // Remember to cancel any in-progress browser seek.
+ if (seeking_) {
+ DCHECK(doing_browser_seek_);
+ cancel_browser_seek = true;
+ }
+ }
+
+ if (cancel_browser_seek)
+ chunk_demuxer_->CancelPendingSeek(seek_time);
+ chunk_demuxer_->StartWaitingForSeek(seek_time);
+}
+
+void MediaSourceDelegate::Seek(
+ const base::TimeDelta& seek_time, bool is_browser_seek) {
+ DCHECK(media_loop_->BelongsToCurrentThread());
+ DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ", "
+ << (is_browser_seek ? "browser seek" : "regular seek") << ") : "
+ << demuxer_client_id_;
+
+ base::TimeDelta internal_seek_time = seek_time;
+ {
+ base::AutoLock auto_lock(seeking_lock_);
+ DCHECK(!seeking_);
+ seeking_ = true;
+ doing_browser_seek_ = is_browser_seek;
+
+ if (doing_browser_seek_ && (!chunk_demuxer_ || expecting_regular_seek_)) {
+ // Trivially finish the browser seek without actually doing it. Reads will
+ // continue to be |kAborted| until the next regular seek is done. Browser
+ // seeking is not supported unless using a ChunkDemuxer; browser seeks are
+ // trivially finished if |chunk_demuxer_| is NULL.
+ seeking_ = false;
+ doing_browser_seek_ = false;
+ demuxer_client_->DemuxerSeekDone(demuxer_client_id_, seek_time);
return;
}
- chunk_demuxer_->StartWaitingForSeek(time);
+ if (doing_browser_seek_) {
+ internal_seek_time = FindBufferedBrowserSeekTime_Locked(seek_time);
+ browser_seek_time_ = internal_seek_time;
+ } else {
+ expecting_regular_seek_ = false;
+ browser_seek_time_ = media::kNoTimestamp();
+ }
}
- SetSeeking(true);
- SeekInternal(time, seek_request_id);
-
- // During fullscreen media source playback Seek() can be called without
- // WebMediaPlayerAndroid's knowledge. We need to inform it that a seek is
- // in progress so the correct time can be returned to web applications while
- // seeking.
- //
- // TODO(wolenetz): Remove after landing a uniform seeking codepath.
- if (!time_update_seek_hack_cb_.is_null()) {
- main_loop_->PostTask(FROM_HERE,
- base::Bind(time_update_seek_hack_cb_, time));
+ // Prepare |chunk_demuxer_| for browser seek.
+ if (is_browser_seek) {
+ chunk_demuxer_->CancelPendingSeek(internal_seek_time);
+ chunk_demuxer_->StartWaitingForSeek(internal_seek_time);
}
+
+ SeekInternal(internal_seek_time);
}
-void MediaSourceDelegate::SeekInternal(const base::TimeDelta& time,
- unsigned request_id) {
+void MediaSourceDelegate::SeekInternal(const base::TimeDelta& seek_time) {
DCHECK(media_loop_->BelongsToCurrentThread());
DCHECK(IsSeeking());
- demuxer_->Seek(time, base::Bind(
- &MediaSourceDelegate::OnDemuxerSeekDone, media_weak_factory_.GetWeakPtr(),
- request_id));
+ demuxer_->Seek(seek_time, base::Bind(
+ &MediaSourceDelegate::OnDemuxerSeekDone,
+ media_weak_factory_.GetWeakPtr()));
}
void MediaSourceDelegate::SetTotalBytes(int64 total_bytes) {
@@ -447,6 +499,19 @@ void MediaSourceDelegate::OnDemuxerError(media::PipelineStatus status) {
update_network_state_cb_.Run(PipelineErrorToNetworkState(status));
}
+void MediaSourceDelegate::AddTextStream(
+ media::DemuxerStream* /* text_stream */ ,
+ const media::TextTrackConfig& /* config */ ) {
+ // TODO(matthewjheaney): add text stream (http://crbug/322115).
+ NOTIMPLEMENTED();
+}
+
+void MediaSourceDelegate::RemoveTextStream(
+ media::DemuxerStream* /* text_stream */ ) {
+ // TODO(matthewjheaney): remove text stream (http://crbug/322115).
+ NOTIMPLEMENTED();
+}
+
void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) {
DCHECK(media_loop_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
@@ -546,8 +611,7 @@ void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone(
NotifyDemuxerReady();
}
-void MediaSourceDelegate::OnDemuxerSeekDone(unsigned seek_request_id,
- media::PipelineStatus status) {
+void MediaSourceDelegate::OnDemuxerSeekDone(media::PipelineStatus status) {
DCHECK(media_loop_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
DCHECK(IsSeeking());
@@ -557,14 +621,6 @@ void MediaSourceDelegate::OnDemuxerSeekDone(unsigned seek_request_id,
return;
}
- // Newer seek has been issued. Resume the last seek request.
- if (seek_request_id != last_seek_request_id_) {
- if (chunk_demuxer_)
- chunk_demuxer_->StartWaitingForSeek(last_seek_time_);
- SeekInternal(last_seek_time_, last_seek_request_id_);
- return;
- }
-
ResetAudioDecryptingDemuxerStream();
}
@@ -597,9 +653,12 @@ void MediaSourceDelegate::ResetVideoDecryptingDemuxerStream() {
void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() {
DCHECK(media_loop_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
- SetSeeking(false);
- demuxer_client_->SeekRequestAck(demuxer_client_id_, last_seek_request_id_);
- last_seek_request_id_ = 0;
+
+ base::AutoLock auto_lock(seeking_lock_);
+ DCHECK(seeking_);
+ seeking_ = false;
+ doing_browser_seek_ = false;
+ demuxer_client_->DemuxerSeekDone(demuxer_client_id_, browser_seek_time_);
}
void MediaSourceDelegate::OnDemuxerStopDone() {
@@ -718,8 +777,7 @@ void MediaSourceDelegate::OnNeedKey(const std::string& type,
if (need_key_cb_.is_null())
return;
- // TODO(xhwang): Remove |session_id| from media::NeedKeyCB.
- need_key_cb_.Run("", type, init_data);
+ need_key_cb_.Run(type, init_data);
}
bool MediaSourceDelegate::HasEncryptedStream() {
@@ -730,14 +788,50 @@ bool MediaSourceDelegate::HasEncryptedStream() {
video_stream_->video_decoder_config().is_encrypted());
}
-void MediaSourceDelegate::SetSeeking(bool seeking) {
- base::AutoLock auto_lock(seeking_lock_);
- seeking_ = seeking;
-}
-
bool MediaSourceDelegate::IsSeeking() const {
base::AutoLock auto_lock(seeking_lock_);
return seeking_;
}
+base::TimeDelta MediaSourceDelegate::FindBufferedBrowserSeekTime_Locked(
+ const base::TimeDelta& seek_time) const {
+ seeking_lock_.AssertAcquired();
+ DCHECK(seeking_);
+ DCHECK(doing_browser_seek_);
+ DCHECK(chunk_demuxer_) << "Browser seek requested, but no chunk demuxer";
+
+ media::Ranges<base::TimeDelta> buffered =
+ chunk_demuxer_->GetBufferedRanges();
+
+ for (size_t i = 0; i < buffered.size(); ++i) {
+ base::TimeDelta range_start = buffered.start(i);
+ base::TimeDelta range_end = buffered.end(i);
+ if (range_start <= seek_time) {
+ if (range_end >= seek_time)
+ return seek_time;
+ continue;
+ }
+
+ // If the start of the next buffered range after |seek_time| is too far
+ // into the future, do not jump forward.
+ if ((range_start - seek_time) > base::TimeDelta::FromMilliseconds(100))
+ break;
+
+ // TODO(wolenetz): Remove possibility that this browser seek jumps
+ // into future when the requested range is unbuffered but there is some
+ // other buffered range after it. See http://crbug.com/304234.
+ return range_start;
+ }
+
+ // We found no range containing |seek_time| or beginning shortly after
+ // |seek_time|. While possible that such data at and beyond the player's
+ // current time have been garbage collected or removed by the web app, this is
+ // unlikely. This may cause unexpected playback stall due to seek pending an
+ // append for a GOP prior to the last GOP demuxed.
+ // TODO(wolenetz): Remove the possibility for this seek to cause unexpected
+ // player stall by replaying cached data since last keyframe in browser player
+ // rather than issuing browser seek. See http://crbug.com/304234.
+ return seek_time;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/android/media_source_delegate.h b/chromium/content/renderer/media/android/media_source_delegate.h
index d519c093836..317ef6544df 100644
--- a/chromium/content/renderer/media/android/media_source_delegate.h
+++ b/chromium/content/renderer/media/android/media_source_delegate.h
@@ -20,7 +20,7 @@
#include "media/base/pipeline_status.h"
#include "media/base/ranges.h"
#include "media/base/text_track.h"
-#include "third_party/WebKit/public/web/WebMediaPlayer.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
namespace media {
class ChunkDemuxer;
@@ -38,12 +38,11 @@ class RendererDemuxerAndroid;
class MediaSourceDelegate : public media::DemuxerHost {
public:
- typedef base::Callback<void(WebKit::WebMediaSource*)>
+ typedef base::Callback<void(blink::WebMediaSource*)>
MediaSourceOpenedCB;
- typedef base::Callback<void(WebKit::WebMediaPlayer::NetworkState)>
+ typedef base::Callback<void(blink::WebMediaPlayer::NetworkState)>
UpdateNetworkStateCB;
typedef base::Callback<void(const base::TimeDelta&)> DurationChangeCB;
- typedef base::Callback<void(const base::TimeDelta&)> TimeUpdateSeekHackCB;
// Helper class used by scoped_ptr to destroy an instance of
// MediaSourceDelegate.
@@ -63,11 +62,10 @@ class MediaSourceDelegate : public media::DemuxerHost {
// this object after this call.
void InitializeMediaSource(
const MediaSourceOpenedCB& media_source_opened_cb,
- const media::NeedKeyCB& need_key_cb,
+ const media::Demuxer::NeedKeyCB& need_key_cb,
const media::SetDecryptorReadyCB& set_decryptor_ready_cb,
const UpdateNetworkStateCB& update_network_state_cb,
- const DurationChangeCB& duration_change_cb,
- const TimeUpdateSeekHackCB& time_update_seek_hack_cb);
+ const DurationChangeCB& duration_change_cb);
#if defined(GOOGLE_TV)
void InitializeMediaStream(
@@ -75,16 +73,32 @@ class MediaSourceDelegate : public media::DemuxerHost {
const UpdateNetworkStateCB& update_network_state_cb);
#endif
- const WebKit::WebTimeRanges& Buffered();
+ const blink::WebTimeRanges& Buffered();
size_t DecodedFrameCount() const;
size_t DroppedFrameCount() const;
size_t AudioDecodedByteCount() const;
size_t VideoDecodedByteCount() const;
- // Seeks the demuxer and acknowledges the seek request with |seek_request_id|
- // after the seek has been completed. This method can be called during pending
- // seeks, in which case only the last seek request will be acknowledged.
- void Seek(const base::TimeDelta& time, unsigned seek_request_id);
+ // In MSE case, calls ChunkDemuxer::CancelPendingSeek(). Also sets the
+ // expectation that a regular seek will be arriving and to trivially finish
+ // any browser seeks that may be requested prior to the regular seek.
+ void CancelPendingSeek(const base::TimeDelta& seek_time);
+
+ // In MSE case, calls ChunkDemuxer::StartWaitingForSeek(), first calling
+ // ChunkDemuxer::CancelPendingSeek() if a browser seek is in progress.
+ // Also sets the expectation that a regular seek will be arriving and to
+ // trivially finish any browser seeks that may be requested prior to the
+ // regular seek.
+ void StartWaitingForSeek(const base::TimeDelta& seek_time);
+
+ // Seeks the demuxer and later calls OnDemuxerSeekDone() after the seek has
+ // been completed. There must be no other seek of the demuxer currently in
+ // process when this method is called.
+ // If |is_browser_seek| is true, then this is a short-term hack browser
+ // seek.
+ // TODO(wolenetz): Instead of doing browser seek, browser player should replay
+ // cached data since last keyframe. See http://crbug.com/304234.
+ void Seek(const base::TimeDelta& seek_time, bool is_browser_seek);
void NotifyKeyAdded(const std::string& key_system);
@@ -113,6 +127,9 @@ class MediaSourceDelegate : public media::DemuxerHost {
base::TimeDelta end) OVERRIDE;
virtual void SetDuration(base::TimeDelta duration) OVERRIDE;
virtual void OnDemuxerError(media::PipelineStatus status) OVERRIDE;
+ virtual void AddTextStream(media::DemuxerStream* text_stream,
+ const media::TextTrackConfig& config) OVERRIDE;
+ virtual void RemoveTextStream(media::DemuxerStream* text_stream) OVERRIDE;
// Notifies |demuxer_client_| and fires |duration_changed_cb_|.
void OnDurationChanged(const base::TimeDelta& duration);
@@ -132,8 +149,7 @@ class MediaSourceDelegate : public media::DemuxerHost {
// decrypted audio/video streams if present.
//
// Runs on the media thread.
- void OnDemuxerSeekDone(unsigned seek_request_id,
- media::PipelineStatus status);
+ void OnDemuxerSeekDone(media::PipelineStatus status);
void ResetAudioDecryptingDemuxerStream();
void ResetVideoDecryptingDemuxerStream();
void FinishResettingDecryptingDemuxerStreams();
@@ -147,7 +163,7 @@ class MediaSourceDelegate : public media::DemuxerHost {
void StopDemuxer();
void InitializeDemuxer();
- void SeekInternal(const base::TimeDelta& time, unsigned seek_request_id);
+ void SeekInternal(const base::TimeDelta& seek_time);
// Reads an access unit from the demuxer stream |stream| and stores it in
// the |index|th access unit in |params|.
void ReadFromDemuxerStream(media::DemuxerStream::Type type,
@@ -164,9 +180,16 @@ class MediaSourceDelegate : public media::DemuxerHost {
bool HasEncryptedStream();
- void SetSeeking(bool seeking);
bool IsSeeking() const;
+ // Returns |seek_time| if it is still buffered or if there is no currently
+ // buffered range including or soon after |seek_time|. If |seek_time| is not
+ // buffered, but there is a later range buffered near to |seek_time|, returns
+ // next buffered range's start time instead. Only call this for browser seeks.
+ // |seeking_lock_| must be held by caller.
+ base::TimeDelta FindBufferedBrowserSeekTime_Locked(
+ const base::TimeDelta& seek_time) const;
+
// Message loop for main renderer thread and corresponding weak pointer.
const scoped_refptr<base::MessageLoopProxy> main_loop_;
base::WeakPtrFactory<MediaSourceDelegate> main_weak_factory_;
@@ -182,7 +205,6 @@ class MediaSourceDelegate : public media::DemuxerHost {
scoped_refptr<media::MediaLog> media_log_;
UpdateNetworkStateCB update_network_state_cb_;
DurationChangeCB duration_change_cb_;
- TimeUpdateSeekHackCB time_update_seek_hack_cb_;
scoped_ptr<media::ChunkDemuxer> chunk_demuxer_;
media::Demuxer* demuxer_;
@@ -199,14 +221,14 @@ class MediaSourceDelegate : public media::DemuxerHost {
media::PipelineStatistics statistics_;
media::Ranges<base::TimeDelta> buffered_time_ranges_;
// Keep a list of buffered time ranges.
- WebKit::WebTimeRanges buffered_web_time_ranges_;
+ blink::WebTimeRanges buffered_web_time_ranges_;
MediaSourceOpenedCB media_source_opened_cb_;
- media::NeedKeyCB need_key_cb_;
+ media::Demuxer::NeedKeyCB need_key_cb_;
// The currently selected key system. Empty string means that no key system
// has been selected.
- WebKit::WebString current_key_system_;
+ blink::WebString current_key_system_;
// Temporary for EME v0.1. In the future the init data type should be passed
// through GenerateKeyRequest() directly from WebKit.
@@ -216,8 +238,14 @@ class MediaSourceDelegate : public media::DemuxerHost {
mutable base::Lock seeking_lock_;
bool seeking_;
- base::TimeDelta last_seek_time_;
- unsigned last_seek_request_id_;
+ // Track if we are currently performing a browser seek, and track whether or
+ // not a regular seek is expected soon. If a regular seek is expected soon,
+ // then any in-progress browser seek will be canceled pending the
+ // regular seek, if using |chunk_demuxer_|, and any requested browser seek
+ // will be trivially finished. Access is serialized by |seeking_lock_|.
+ bool doing_browser_seek_;
+ base::TimeDelta browser_seek_time_;
+ bool expecting_regular_seek_;
#if defined(GOOGLE_TV)
bool key_added_;
diff --git a/chromium/content/renderer/media/android/proxy_media_keys.cc b/chromium/content/renderer/media/android/proxy_media_keys.cc
index 2beb66a478d..ef93a2552fb 100644
--- a/chromium/content/renderer/media/android/proxy_media_keys.cc
+++ b/chromium/content/renderer/media/android/proxy_media_keys.cc
@@ -8,15 +8,30 @@
#include "base/basictypes.h"
#include "base/logging.h"
-#include "content/renderer/media/android/webmediaplayer_proxy_android.h"
+#include "content/renderer/media/android/renderer_media_player_manager.h"
#include "content/renderer/media/crypto/key_systems.h"
namespace content {
-ProxyMediaKeys::ProxyMediaKeys(WebMediaPlayerProxyAndroid* proxy,
- int media_keys_id)
- : proxy_(proxy), media_keys_id_(media_keys_id) {
- DCHECK(proxy_);
+ProxyMediaKeys::ProxyMediaKeys(
+ RendererMediaPlayerManager* manager,
+ int media_keys_id,
+ const media::SessionCreatedCB& session_created_cb,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb)
+ : manager_(manager),
+ media_keys_id_(media_keys_id),
+ session_created_cb_(session_created_cb),
+ session_message_cb_(session_message_cb),
+ session_ready_cb_(session_ready_cb),
+ session_closed_cb_(session_closed_cb),
+ session_error_cb_(session_error_cb) {
+ DCHECK(manager_);
+}
+
+ProxyMediaKeys::~ProxyMediaKeys() {
}
void ProxyMediaKeys::InitializeCDM(const std::string& key_system,
@@ -26,31 +41,58 @@ void ProxyMediaKeys::InitializeCDM(const std::string& key_system,
#elif defined(OS_ANDROID)
std::vector<uint8> uuid = GetUUID(key_system);
DCHECK(!uuid.empty());
- proxy_->InitializeCDM(media_keys_id_, uuid, frame_url);
+ manager_->InitializeCDM(media_keys_id_, this, uuid, frame_url);
#endif
}
-bool ProxyMediaKeys::GenerateKeyRequest(const std::string& type,
- const uint8* init_data,
- int init_data_length) {
- proxy_->GenerateKeyRequest(
+bool ProxyMediaKeys::CreateSession(uint32 session_id,
+ const std::string& type,
+ const uint8* init_data,
+ int init_data_length) {
+ manager_->CreateSession(
media_keys_id_,
+ session_id,
type,
std::vector<uint8>(init_data, init_data + init_data_length));
return true;
}
-void ProxyMediaKeys::AddKey(const uint8* key, int key_length,
- const uint8* init_data, int init_data_length,
- const std::string& session_id) {
- proxy_->AddKey(media_keys_id_,
- std::vector<uint8>(key, key + key_length),
- std::vector<uint8>(init_data, init_data + init_data_length),
- session_id);
+void ProxyMediaKeys::UpdateSession(uint32 session_id,
+ const uint8* response,
+ int response_length) {
+ manager_->UpdateSession(
+ media_keys_id_,
+ session_id,
+ std::vector<uint8>(response, response + response_length));
+}
+
+void ProxyMediaKeys::ReleaseSession(uint32 session_id) {
+ manager_->ReleaseSession(media_keys_id_, session_id);
+}
+
+void ProxyMediaKeys::OnSessionCreated(uint32 session_id,
+ const std::string& web_session_id) {
+ session_created_cb_.Run(session_id, web_session_id);
+}
+
+void ProxyMediaKeys::OnSessionMessage(uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url) {
+ session_message_cb_.Run(session_id, message, destination_url);
+}
+
+void ProxyMediaKeys::OnSessionReady(uint32 session_id) {
+ session_ready_cb_.Run(session_id);
+}
+
+void ProxyMediaKeys::OnSessionClosed(uint32 session_id) {
+ session_closed_cb_.Run(session_id);
}
-void ProxyMediaKeys::CancelKeyRequest(const std::string& session_id) {
- proxy_->CancelKeyRequest(media_keys_id_, session_id);
+void ProxyMediaKeys::OnSessionError(uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code) {
+ session_error_cb_.Run(session_id, error_code, system_code);
}
} // namespace content
diff --git a/chromium/content/renderer/media/android/proxy_media_keys.h b/chromium/content/renderer/media/android/proxy_media_keys.h
index 847a78285f6..ca5c932d883 100644
--- a/chromium/content/renderer/media/android/proxy_media_keys.h
+++ b/chromium/content/renderer/media/android/proxy_media_keys.h
@@ -12,32 +12,56 @@ class GURL;
namespace content {
-class WebMediaPlayerProxyAndroid;
+class RendererMediaPlayerManager;
-// MediaKeys wrapper of the WebMediaPlayerProxyAndroid.
-// TODO(xhwang): Remove |player_id| from WebMediaPlayerProxyAndroid, make
-// WebMediaPlayerProxyAndroid a subclass of media::MediaKeys, then remove this
-// class!
+// A MediaKeys proxy that wraps the EME part of RendererMediaPlayerManager.
+// TODO(xhwang): Instead of accessing RendererMediaPlayerManager directly, let
+// RendererMediaPlayerManager return a MediaKeys object that can be used by
+// ProxyDecryptor directly. Then we can remove this class!
class ProxyMediaKeys : public media::MediaKeys {
public:
- ProxyMediaKeys(WebMediaPlayerProxyAndroid* proxy, int media_keys_id);
+ ProxyMediaKeys(RendererMediaPlayerManager* proxy,
+ int media_keys_id,
+ const media::SessionCreatedCB& session_created_cb,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb);
+ virtual ~ProxyMediaKeys();
void InitializeCDM(const std::string& key_system, const GURL& frame_url);
// MediaKeys implementation.
- virtual bool GenerateKeyRequest(const std::string& type,
- const uint8* init_data,
- int init_data_length) OVERRIDE;
- virtual void AddKey(const uint8* key, int key_length,
- const uint8* init_data, int init_data_length,
- const std::string& session_id) OVERRIDE;
- virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE;
+ virtual bool CreateSession(uint32 session_id,
+ const std::string& type,
+ const uint8* init_data,
+ int init_data_length) OVERRIDE;
+ virtual void UpdateSession(uint32 session_id,
+ const uint8* response,
+ int response_length) OVERRIDE;
+ virtual void ReleaseSession(uint32 session_id) OVERRIDE;
+
+ // Callbacks.
+ void OnSessionCreated(uint32 session_id, const std::string& web_session_id);
+ void OnSessionMessage(uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url);
+ void OnSessionReady(uint32 session_id);
+ void OnSessionClosed(uint32 session_id);
+ void OnSessionError(uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code);
private:
- WebMediaPlayerProxyAndroid* proxy_;
+ RendererMediaPlayerManager* manager_;
int media_keys_id_;
+ media::SessionCreatedCB session_created_cb_;
+ media::SessionMessageCB session_message_cb_;
+ media::SessionReadyCB session_ready_cb_;
+ media::SessionClosedCB session_closed_cb_;
+ media::SessionErrorCB session_error_cb_;
- DISALLOW_COPY_AND_ASSIGN (ProxyMediaKeys);
+ DISALLOW_COPY_AND_ASSIGN(ProxyMediaKeys);
};
} // namespace content
diff --git a/chromium/content/renderer/media/android/renderer_demuxer_android.cc b/chromium/content/renderer/media/android/renderer_demuxer_android.cc
index 20d09570e29..ab139b5403e 100644
--- a/chromium/content/renderer/media/android/renderer_demuxer_android.cc
+++ b/chromium/content/renderer/media/android/renderer_demuxer_android.cc
@@ -40,7 +40,7 @@ void RendererDemuxerAndroid::RemoveDelegate(int demuxer_client_id) {
bool RendererDemuxerAndroid::OnMessageReceived(const IPC::Message& message) {
switch (message.type()) {
- case MediaPlayerMsg_MediaSeekRequest::ID:
+ case MediaPlayerMsg_DemuxerSeekRequest::ID:
case MediaPlayerMsg_ReadFromDemuxer::ID:
case MediaPlayerMsg_MediaConfigRequest::ID:
media_message_loop_->PostTask(FROM_HERE, base::Bind(
@@ -64,10 +64,11 @@ void RendererDemuxerAndroid::ReadFromDemuxerAck(
demuxer_client_id, data));
}
-void RendererDemuxerAndroid::SeekRequestAck(int demuxer_client_id,
- unsigned seek_request_id) {
- thread_safe_sender_->Send(new MediaPlayerHostMsg_MediaSeekRequestAck(
- demuxer_client_id, seek_request_id));
+void RendererDemuxerAndroid::DemuxerSeekDone(
+ int demuxer_client_id,
+ const base::TimeDelta& actual_browser_seek_time) {
+ thread_safe_sender_->Send(new MediaPlayerHostMsg_DemuxerSeekDone(
+ demuxer_client_id, actual_browser_seek_time));
}
void RendererDemuxerAndroid::DurationChanged(int demuxer_client_id,
@@ -78,7 +79,7 @@ void RendererDemuxerAndroid::DurationChanged(int demuxer_client_id,
void RendererDemuxerAndroid::DispatchMessage(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(RendererDemuxerAndroid, message)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaSeekRequest, OnMediaSeekRequest)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_DemuxerSeekRequest, OnDemuxerSeekRequest)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_ReadFromDemuxer, OnReadFromDemuxer)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaConfigRequest, OnMediaConfigRequest)
IPC_END_MESSAGE_MAP()
@@ -92,13 +93,13 @@ void RendererDemuxerAndroid::OnReadFromDemuxer(
delegate->OnReadFromDemuxer(type);
}
-void RendererDemuxerAndroid::OnMediaSeekRequest(
+void RendererDemuxerAndroid::OnDemuxerSeekRequest(
int demuxer_client_id,
const base::TimeDelta& time_to_seek,
- unsigned seek_request_id) {
+ bool is_browser_seek) {
MediaSourceDelegate* delegate = delegates_.Lookup(demuxer_client_id);
if (delegate)
- delegate->Seek(time_to_seek, seek_request_id);
+ delegate->Seek(time_to_seek, is_browser_seek);
}
void RendererDemuxerAndroid::OnMediaConfigRequest(int demuxer_client_id) {
diff --git a/chromium/content/renderer/media/android/renderer_demuxer_android.h b/chromium/content/renderer/media/android/renderer_demuxer_android.h
index 6888d6af8d4..c6538a1b2cb 100644
--- a/chromium/content/renderer/media/android/renderer_demuxer_android.h
+++ b/chromium/content/renderer/media/android/renderer_demuxer_android.h
@@ -51,7 +51,8 @@ class RendererDemuxerAndroid : public IPC::ChannelProxy::MessageFilter {
const media::DemuxerConfigs& configs);
void ReadFromDemuxerAck(int demuxer_client_id,
const media::DemuxerData& data);
- void SeekRequestAck(int demuxer_client_id, unsigned seek_request_id);
+ void DemuxerSeekDone(int demuxer_client_id,
+ const base::TimeDelta& actual_browser_seek_time);
void DurationChanged(int demuxer_client_id, const base::TimeDelta& duration);
protected:
@@ -62,9 +63,9 @@ class RendererDemuxerAndroid : public IPC::ChannelProxy::MessageFilter {
void DispatchMessage(const IPC::Message& message);
void OnReadFromDemuxer(int demuxer_client_id,
media::DemuxerStream::Type type);
- void OnMediaSeekRequest(int demuxer_client_id,
- const base::TimeDelta& time_to_seek,
- unsigned seek_request_id);
+ void OnDemuxerSeekRequest(int demuxer_client_id,
+ const base::TimeDelta& time_to_seek,
+ bool is_browser_seek);
void OnMediaConfigRequest(int demuxer_client_id);
base::AtomicSequenceNumber next_demuxer_client_id_;
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 62a99c0fa60..64e6fc5b112 100644
--- a/chromium/content/renderer/media/android/renderer_media_player_manager.cc
+++ b/chromium/content/renderer/media/android/renderer_media_player_manager.cc
@@ -4,15 +4,28 @@
#include "content/renderer/media/android/renderer_media_player_manager.h"
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "content/common/media/media_player_messages_android.h"
+#include "content/renderer/media/android/proxy_media_keys.h"
+#include "content/renderer/media/android/renderer_media_player_manager.h"
#include "content/renderer/media/android/webmediaplayer_android.h"
#include "ui/gfx/rect_f.h"
+// Maximum sizes for various EME message parameters. These are checks to
+// prevent unnecessarily large messages from being passed around, and the sizes
+// are somewhat arbitrary as the EME specification doesn't specify any limits.
+static const size_t kEmeWebSessionIdMaximum = 512;
+static const size_t kEmeMessageMaximum = 10240; // 10 KB
+static const size_t kEmeDestinationUrlMaximum = 2048; // 2 KB
+
namespace content {
-RendererMediaPlayerManager::RendererMediaPlayerManager()
- : next_media_player_id_(0),
- fullscreen_frame_(NULL) {
-}
+RendererMediaPlayerManager::RendererMediaPlayerManager(RenderView* render_view)
+ : RenderViewObserver(render_view),
+ next_media_player_id_(0),
+ fullscreen_frame_(NULL),
+ pending_fullscreen_frame_(NULL) {}
RendererMediaPlayerManager::~RendererMediaPlayerManager() {
std::map<int, WebMediaPlayerAndroid*>::iterator player_it;
@@ -21,6 +34,297 @@ RendererMediaPlayerManager::~RendererMediaPlayerManager() {
WebMediaPlayerAndroid* player = player_it->second;
player->Detach();
}
+
+ Send(new MediaPlayerHostMsg_DestroyAllMediaPlayers(routing_id()));
+}
+
+bool RendererMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(RendererMediaPlayerManager, msg)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaMetadataChanged,
+ OnMediaMetadataChanged)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPlaybackCompleted,
+ OnMediaPlaybackCompleted)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaBufferingUpdate,
+ OnMediaBufferingUpdate)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_SeekRequest, OnSeekRequest)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_SeekCompleted, OnSeekCompleted)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaError, OnMediaError)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaVideoSizeChanged,
+ OnVideoSizeChanged)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaTimeUpdate, OnTimeUpdate)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPlayerReleased,
+ OnMediaPlayerReleased)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_ConnectedToRemoteDevice,
+ OnConnectedToRemoteDevice)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_DisconnectedFromRemoteDevice,
+ OnDisconnectedFromRemoteDevice)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_RequestFullscreen,
+ OnRequestFullscreen)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidEnterFullscreen, OnDidEnterFullscreen)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidExitFullscreen, OnDidExitFullscreen)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPlay, OnPlayerPlay)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPause, OnPlayerPause)
+ IPC_MESSAGE_HANDLER(MediaKeysMsg_SessionCreated, OnSessionCreated)
+ IPC_MESSAGE_HANDLER(MediaKeysMsg_SessionMessage, OnSessionMessage)
+ IPC_MESSAGE_HANDLER(MediaKeysMsg_SessionReady, OnSessionReady)
+ IPC_MESSAGE_HANDLER(MediaKeysMsg_SessionClosed, OnSessionClosed)
+ IPC_MESSAGE_HANDLER(MediaKeysMsg_SessionError, OnSessionError)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void RendererMediaPlayerManager::Initialize(
+ MediaPlayerHostMsg_Initialize_Type type,
+ int player_id,
+ const GURL& url,
+ const GURL& first_party_for_cookies,
+ int demuxer_client_id) {
+ Send(new MediaPlayerHostMsg_Initialize(
+ routing_id(), type, player_id, url, first_party_for_cookies,
+ demuxer_client_id));
+}
+
+void RendererMediaPlayerManager::Start(int player_id) {
+ Send(new MediaPlayerHostMsg_Start(routing_id(), player_id));
+}
+
+void RendererMediaPlayerManager::Pause(
+ int player_id,
+ bool is_media_related_action) {
+ Send(new MediaPlayerHostMsg_Pause(
+ routing_id(), player_id, is_media_related_action));
+}
+
+void RendererMediaPlayerManager::Seek(
+ int player_id,
+ const base::TimeDelta& time) {
+ Send(new MediaPlayerHostMsg_Seek(routing_id(), player_id, time));
+}
+
+void RendererMediaPlayerManager::SetVolume(int player_id, double volume) {
+ Send(new MediaPlayerHostMsg_SetVolume(routing_id(), player_id, volume));
+}
+
+void RendererMediaPlayerManager::ReleaseResources(int player_id) {
+ Send(new MediaPlayerHostMsg_Release(routing_id(), player_id));
+}
+
+void RendererMediaPlayerManager::DestroyPlayer(int player_id) {
+ Send(new MediaPlayerHostMsg_DestroyMediaPlayer(routing_id(), player_id));
+}
+
+void RendererMediaPlayerManager::OnMediaMetadataChanged(
+ int player_id,
+ base::TimeDelta duration,
+ int width,
+ int height,
+ bool success) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnMediaMetadataChanged(duration, width, height, success);
+}
+
+void RendererMediaPlayerManager::OnMediaPlaybackCompleted(int player_id) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnPlaybackComplete();
+}
+
+void RendererMediaPlayerManager::OnMediaBufferingUpdate(int player_id,
+ int percent) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnBufferingUpdate(percent);
+}
+
+void RendererMediaPlayerManager::OnSeekRequest(
+ int player_id,
+ const base::TimeDelta& time_to_seek) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnSeekRequest(time_to_seek);
+}
+
+void RendererMediaPlayerManager::OnSeekCompleted(
+ int player_id,
+ const base::TimeDelta& current_time) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnSeekComplete(current_time);
+}
+
+void RendererMediaPlayerManager::OnMediaError(int player_id, int error) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnMediaError(error);
+}
+
+void RendererMediaPlayerManager::OnVideoSizeChanged(int player_id,
+ int width,
+ int height) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnVideoSizeChanged(width, height);
+}
+
+void RendererMediaPlayerManager::OnTimeUpdate(int player_id,
+ base::TimeDelta current_time) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnTimeUpdate(current_time);
+}
+
+void RendererMediaPlayerManager::OnMediaPlayerReleased(int player_id) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnPlayerReleased();
+}
+
+void RendererMediaPlayerManager::OnConnectedToRemoteDevice(int player_id) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnConnectedToRemoteDevice();
+}
+
+void RendererMediaPlayerManager::OnDisconnectedFromRemoteDevice(int player_id) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnDisconnectedFromRemoteDevice();
+}
+
+void RendererMediaPlayerManager::OnDidEnterFullscreen(int player_id) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnDidEnterFullscreen();
+}
+
+void RendererMediaPlayerManager::OnDidExitFullscreen(int player_id) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnDidExitFullscreen();
+}
+
+void RendererMediaPlayerManager::OnPlayerPlay(int player_id) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnMediaPlayerPlay();
+}
+
+void RendererMediaPlayerManager::OnPlayerPause(int player_id) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnMediaPlayerPause();
+}
+
+void RendererMediaPlayerManager::OnRequestFullscreen(int player_id) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnRequestFullscreen();
+}
+
+void RendererMediaPlayerManager::EnterFullscreen(int player_id,
+ blink::WebFrame* frame) {
+ pending_fullscreen_frame_ = frame;
+ Send(new MediaPlayerHostMsg_EnterFullscreen(routing_id(), player_id));
+}
+
+void RendererMediaPlayerManager::ExitFullscreen(int player_id) {
+ pending_fullscreen_frame_ = NULL;
+ Send(new MediaPlayerHostMsg_ExitFullscreen(routing_id(), player_id));
+}
+
+void RendererMediaPlayerManager::InitializeCDM(int media_keys_id,
+ ProxyMediaKeys* media_keys,
+ const std::vector<uint8>& uuid,
+ const GURL& frame_url) {
+ RegisterMediaKeys(media_keys_id, media_keys);
+ Send(new MediaKeysHostMsg_InitializeCDM(
+ routing_id(), media_keys_id, uuid, frame_url));
+}
+
+void RendererMediaPlayerManager::CreateSession(
+ int media_keys_id,
+ uint32 session_id,
+ const std::string& type,
+ const std::vector<uint8>& init_data) {
+ Send(new MediaKeysHostMsg_CreateSession(
+ routing_id(), media_keys_id, session_id, type, init_data));
+}
+
+void RendererMediaPlayerManager::UpdateSession(
+ int media_keys_id,
+ uint32 session_id,
+ const std::vector<uint8>& response) {
+ Send(new MediaKeysHostMsg_UpdateSession(
+ routing_id(), media_keys_id, session_id, response));
+}
+
+void RendererMediaPlayerManager::ReleaseSession(int media_keys_id,
+ uint32 session_id) {
+ Send(new MediaKeysHostMsg_ReleaseSession(
+ routing_id(), media_keys_id, session_id));
+}
+
+void RendererMediaPlayerManager::OnSessionCreated(
+ int media_keys_id,
+ uint32 session_id,
+ const std::string& web_session_id) {
+ if (web_session_id.length() > kEmeWebSessionIdMaximum) {
+ OnSessionError(
+ media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
+ return;
+ }
+
+ ProxyMediaKeys* media_keys = GetMediaKeys(media_keys_id);
+ if (media_keys)
+ media_keys->OnSessionCreated(session_id, web_session_id);
+}
+
+void RendererMediaPlayerManager::OnSessionMessage(
+ int media_keys_id,
+ uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url) {
+ if (message.size() > kEmeMessageMaximum) {
+ OnSessionError(
+ media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
+ return;
+ }
+ if (destination_url.length() > kEmeDestinationUrlMaximum) {
+ OnSessionError(
+ media_keys_id, session_id, media::MediaKeys::kUnknownError, 0);
+ return;
+ }
+
+ ProxyMediaKeys* media_keys = GetMediaKeys(media_keys_id);
+ if (media_keys)
+ media_keys->OnSessionMessage(session_id, message, destination_url);
+}
+
+void RendererMediaPlayerManager::OnSessionReady(int media_keys_id,
+ uint32 session_id) {
+ ProxyMediaKeys* media_keys = GetMediaKeys(media_keys_id);
+ if (media_keys)
+ media_keys->OnSessionReady(session_id);
+}
+
+void RendererMediaPlayerManager::OnSessionClosed(int media_keys_id,
+ uint32 session_id) {
+ ProxyMediaKeys* media_keys = GetMediaKeys(media_keys_id);
+ if (media_keys)
+ media_keys->OnSessionClosed(session_id);
+}
+
+void RendererMediaPlayerManager::OnSessionError(
+ int media_keys_id,
+ uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code) {
+ ProxyMediaKeys* media_keys = GetMediaKeys(media_keys_id);
+ if (media_keys)
+ media_keys->OnSessionError(session_id, error_code, system_code);
}
int RendererMediaPlayerManager::RegisterMediaPlayer(
@@ -31,6 +335,20 @@ int RendererMediaPlayerManager::RegisterMediaPlayer(
void RendererMediaPlayerManager::UnregisterMediaPlayer(int player_id) {
media_players_.erase(player_id);
+ media_keys_.erase(player_id);
+}
+
+void RendererMediaPlayerManager::RegisterMediaKeys(int media_keys_id,
+ ProxyMediaKeys* media_keys) {
+ // WebMediaPlayerAndroid must have already been registered for
+ // |media_keys_id|. For now |media_keys_id| is the same as player_id
+ // used in other methods.
+ DCHECK(media_players_.find(media_keys_id) != media_players_.end());
+
+ // Only allowed to register once.
+ DCHECK(media_keys_.find(media_keys_id) == media_keys_.end());
+
+ media_keys_[media_keys_id] = media_keys;
}
void RendererMediaPlayerManager::ReleaseVideoResources() {
@@ -54,11 +372,19 @@ WebMediaPlayerAndroid* RendererMediaPlayerManager::GetMediaPlayer(
return NULL;
}
-bool RendererMediaPlayerManager::CanEnterFullscreen(WebKit::WebFrame* frame) {
- return !fullscreen_frame_ || IsInFullscreen(frame);
+ProxyMediaKeys* RendererMediaPlayerManager::GetMediaKeys(int media_keys_id) {
+ std::map<int, ProxyMediaKeys*>::iterator iter =
+ media_keys_.find(media_keys_id);
+ return (iter != media_keys_.end()) ? iter->second : NULL;
+}
+
+bool RendererMediaPlayerManager::CanEnterFullscreen(blink::WebFrame* frame) {
+ return (!fullscreen_frame_ && !pending_fullscreen_frame_)
+ || ShouldEnterFullscreen(frame);
}
-void RendererMediaPlayerManager::DidEnterFullscreen(WebKit::WebFrame* frame) {
+void RendererMediaPlayerManager::DidEnterFullscreen(blink::WebFrame* frame) {
+ pending_fullscreen_frame_ = NULL;
fullscreen_frame_ = frame;
}
@@ -66,11 +392,33 @@ void RendererMediaPlayerManager::DidExitFullscreen() {
fullscreen_frame_ = NULL;
}
-bool RendererMediaPlayerManager::IsInFullscreen(WebKit::WebFrame* frame) {
+bool RendererMediaPlayerManager::IsInFullscreen(blink::WebFrame* frame) {
return fullscreen_frame_ == frame;
}
-#if defined(GOOGLE_TV)
+bool RendererMediaPlayerManager::ShouldEnterFullscreen(blink::WebFrame* frame) {
+ return fullscreen_frame_ == frame || pending_fullscreen_frame_ == frame;
+}
+
+#if defined(VIDEO_HOLE)
+void RendererMediaPlayerManager::RequestExternalSurface(
+ int player_id,
+ const gfx::RectF& geometry) {
+ Send(new MediaPlayerHostMsg_NotifyExternalSurface(
+ routing_id(), player_id, true, geometry));
+}
+
+void RendererMediaPlayerManager::DidCommitCompositorFrame() {
+ std::map<int, gfx::RectF> geometry_change;
+ RetrieveGeometryChanges(&geometry_change);
+ for (std::map<int, gfx::RectF>::iterator it = geometry_change.begin();
+ it != geometry_change.end();
+ ++it) {
+ Send(new MediaPlayerHostMsg_NotifyExternalSurface(
+ routing_id(), it->first, false, it->second));
+ }
+}
+
void RendererMediaPlayerManager::RetrieveGeometryChanges(
std::map<int, gfx::RectF>* changes) {
DCHECK(changes->empty());
@@ -88,6 +436,6 @@ void RendererMediaPlayerManager::RetrieveGeometryChanges(
}
}
}
-#endif
+#endif // defined(VIDEO_HOLE)
} // namespace content
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 e565602a279..188d5425132 100644
--- a/chromium/content/renderer/media/android/renderer_media_player_manager.h
+++ b/chromium/content/renderer/media/android/renderer_media_player_manager.h
@@ -6,10 +6,22 @@
#define CONTENT_RENDERER_MEDIA_ANDROID_RENDERER_MEDIA_PLAYER_MANAGER_H_
#include <map>
+#include <string>
+#include <vector>
#include "base/basictypes.h"
+#include "base/time/time.h"
+#include "content/common/media/media_player_messages_enums_android.h"
+#include "content/public/renderer/render_view_observer.h"
+#include "media/base/android/media_player_android.h"
+#include "media/base/media_keys.h"
+#include "url/gurl.h"
-namespace WebKit {
+#if defined(GOOGLE_TV)
+#include "ui/gfx/rect_f.h"
+#endif
+
+namespace blink {
class WebFrame;
}
@@ -19,50 +31,166 @@ class RectF;
namespace content {
+class ProxyMediaKeys;
class WebMediaPlayerAndroid;
// Class for managing all the WebMediaPlayerAndroid objects in the same
// RenderView.
-class RendererMediaPlayerManager {
+class RendererMediaPlayerManager : public RenderViewObserver {
public:
- RendererMediaPlayerManager();
+ // Constructs a RendererMediaPlayerManager object for the |render_view|.
+ RendererMediaPlayerManager(RenderView* render_view);
virtual ~RendererMediaPlayerManager();
- // Register and unregister a WebMediaPlayerAndroid object.
+ // RenderViewObserver overrides.
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+
+ // Initializes a MediaPlayerAndroid object in browser process.
+ void Initialize(MediaPlayerHostMsg_Initialize_Type type,
+ int player_id,
+ const GURL& url,
+ const GURL& first_party_for_cookies,
+ int demuxer_client_id);
+
+ // Starts the player.
+ void Start(int player_id);
+
+ // Pauses the player.
+ // is_media_related_action should be true if this pause is coming from an
+ // an action that explicitly pauses the video (user pressing pause, JS, etc.)
+ // Otherwise it should be false if Pause is being called due to other reasons
+ // (cleanup, freeing resources, etc.)
+ void Pause(int player_id, bool is_media_related_action);
+
+ // Performs seek on the player.
+ void Seek(int player_id, const base::TimeDelta& time);
+
+ // Sets the player volume.
+ void SetVolume(int player_id, double volume);
+
+ // Releases resources for the player.
+ void ReleaseResources(int player_id);
+
+ // Destroys the player in the browser process
+ void DestroyPlayer(int player_id);
+
+ // Requests the player to enter fullscreen.
+ void EnterFullscreen(int player_id, blink::WebFrame* frame);
+
+ // Requests the player to exit fullscreen.
+ void ExitFullscreen(int player_id);
+
+#if defined(VIDEO_HOLE)
+ // Requests an external surface for out-of-band compositing.
+ void RequestExternalSurface(int player_id, const gfx::RectF& geometry);
+
+ // RenderViewObserver overrides.
+ virtual void DidCommitCompositorFrame() OVERRIDE;
+#endif // defined(VIDEO_HOLE)
+
+ // Encrypted media related methods.
+ void InitializeCDM(int media_keys_id,
+ ProxyMediaKeys* media_keys,
+ const std::vector<uint8>& uuid,
+ const GURL& frame_url);
+ void CreateSession(int media_keys_id,
+ uint32 session_id,
+ const std::string& type,
+ const std::vector<uint8>& init_data);
+ void UpdateSession(int media_keys_id,
+ uint32 session_id,
+ const std::vector<uint8>& response);
+ void ReleaseSession(int media_keys_id, uint32 session_id);
+
+ // Registers and unregisters a WebMediaPlayerAndroid object.
int RegisterMediaPlayer(WebMediaPlayerAndroid* player);
void UnregisterMediaPlayer(int player_id);
- // Release the media resources managed by this object when a video
+ // Registers a ProxyMediaKeys object. There must be a WebMediaPlayerAndroid
+ // object already registered for this id, and it is unregistered when the
+ // player is unregistered. For now |media_keys_id| is the same as player_id
+ // used in other methods.
+ void RegisterMediaKeys(int media_keys_id, ProxyMediaKeys* media_keys);
+
+ // Releases the media resources managed by this object when a video
// is playing.
void ReleaseVideoResources();
- // Check whether a player can enter fullscreen.
- bool CanEnterFullscreen(WebKit::WebFrame* frame);
+ // Checks whether a player can enter fullscreen.
+ bool CanEnterFullscreen(blink::WebFrame* frame);
// Called when a player entered or exited fullscreen.
- void DidEnterFullscreen(WebKit::WebFrame* frame);
+ void DidEnterFullscreen(blink::WebFrame* frame);
void DidExitFullscreen();
- // Check whether the Webframe is in fullscreen.
- bool IsInFullscreen(WebKit::WebFrame* frame);
+ // Checks whether the Webframe is in fullscreen.
+ bool IsInFullscreen(blink::WebFrame* frame);
+
+ // True if a newly created media player should enter fullscreen.
+ bool ShouldEnterFullscreen(blink::WebFrame* frame);
- // Get the pointer to WebMediaPlayerAndroid given the |player_id|.
+ // Gets the pointer to WebMediaPlayerAndroid given the |player_id|.
WebMediaPlayerAndroid* GetMediaPlayer(int player_id);
-#if defined(GOOGLE_TV)
- // Get the list of media players with video geometry changes.
+ // Gets the pointer to ProxyMediaKeys given the |media_keys_id|.
+ ProxyMediaKeys* GetMediaKeys(int media_keys_id);
+
+#if defined(VIDEO_HOLE)
+ // Gets the list of media players with video geometry changes.
void RetrieveGeometryChanges(std::map<int, gfx::RectF>* changes);
-#endif
+#endif // defined(VIDEO_HOLE)
private:
+ // Message handlers.
+ void OnMediaMetadataChanged(int player_id,
+ base::TimeDelta duration,
+ int width,
+ int height,
+ bool success);
+ void OnMediaPlaybackCompleted(int player_id);
+ void OnMediaBufferingUpdate(int player_id, int percent);
+ void OnSeekRequest(int player_id, const base::TimeDelta& time_to_seek);
+ void OnSeekCompleted(int player_id, const base::TimeDelta& current_time);
+ void OnMediaError(int player_id, int error);
+ void OnVideoSizeChanged(int player_id, int width, int height);
+ void OnTimeUpdate(int player_id, base::TimeDelta current_time);
+ void OnMediaPlayerReleased(int player_id);
+ void OnConnectedToRemoteDevice(int player_id);
+ void OnDisconnectedFromRemoteDevice(int player_id);
+ void OnDidExitFullscreen(int player_id);
+ void OnDidEnterFullscreen(int player_id);
+ void OnPlayerPlay(int player_id);
+ void OnPlayerPause(int player_id);
+ void OnRequestFullscreen(int player_id);
+ void OnSessionCreated(int media_keys_id,
+ uint32 session_id,
+ const std::string& web_session_id);
+ void OnSessionMessage(int media_keys_id,
+ uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url);
+ void OnSessionReady(int media_keys_id, uint32 session_id);
+ void OnSessionClosed(int media_keys_id, uint32 session_id);
+ void OnSessionError(int media_keys_id,
+ uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code);
+
// Info for all available WebMediaPlayerAndroid on a page; kept so that
- // we can enumerate them to send updates about tab focus and visibily.
+ // we can enumerate them to send updates about tab focus and visibility.
std::map<int, WebMediaPlayerAndroid*> media_players_;
+ // Info for all available ProxyMediaKeys. There must be at most one
+ // ProxyMediaKeys for each available WebMediaPlayerAndroid.
+ std::map<int, ProxyMediaKeys*> media_keys_;
+
int next_media_player_id_;
// WebFrame of the fullscreen video.
- WebKit::WebFrame* fullscreen_frame_;
+ blink::WebFrame* fullscreen_frame_;
+
+ // WebFrame of pending fullscreen request.
+ blink::WebFrame* pending_fullscreen_frame_;
DISALLOW_COPY_AND_ASSIGN(RendererMediaPlayerManager);
};
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_android.h b/chromium/content/renderer/media/android/stream_texture_factory_android.h
index d41d857cf62..849cc06eefa 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_android.h
+++ b/chromium/content/renderer/media/android/stream_texture_factory_android.h
@@ -10,6 +10,10 @@
#include "gpu/command_buffer/common/mailbox.h"
#include "ui/gfx/size.h"
+namespace blink {
+class WebGraphicsContext3D;
+}
+
namespace content {
// The proxy class for the gpu thread to notify the compositor thread
@@ -70,6 +74,8 @@ class StreamTextureFactory {
// Set the streamTexture size for the given stream Id.
virtual void SetStreamTextureSize(int32 texture_id,
const gfx::Size& size) = 0;
+
+ virtual blink::WebGraphicsContext3D* Context3d() = 0;
};
} // namespace content
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_android_impl.cc b/chromium/content/renderer/media/android/stream_texture_factory_android_impl.cc
index 721b680fb14..3b421ca04ef 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_android_impl.cc
+++ b/chromium/content/renderer/media/android/stream_texture_factory_android_impl.cc
@@ -80,7 +80,7 @@ void StreamTextureProxyImpl::OnMatrixChanged(const float matrix[16]) {
} // namespace
StreamTextureFactoryImpl::StreamTextureFactoryImpl(
- WebKit::WebGraphicsContext3D* context,
+ blink::WebGraphicsContext3D* context,
GpuChannelHost* channel,
int view_id)
: context_(context), channel_(channel), view_id_(view_id) {
@@ -137,4 +137,8 @@ void StreamTextureFactoryImpl::SetStreamTextureSize(
channel_->Send(new GpuChannelMsg_SetStreamTextureSize(stream_id, size));
}
+blink::WebGraphicsContext3D* StreamTextureFactoryImpl::Context3d() {
+ return context_;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_android_impl.h b/chromium/content/renderer/media/android/stream_texture_factory_android_impl.h
index 20aacdd9f98..0cd3d5866c9 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_android_impl.h
+++ b/chromium/content/renderer/media/android/stream_texture_factory_android_impl.h
@@ -7,7 +7,7 @@
#include "content/renderer/media/android/stream_texture_factory_android.h"
-namespace WebKit {
+namespace blink {
class WebGraphicsContext3D;
}
@@ -17,7 +17,7 @@ class GpuChannelHost;
class StreamTextureFactoryImpl : public StreamTextureFactory {
public:
- StreamTextureFactoryImpl(WebKit::WebGraphicsContext3D* context,
+ StreamTextureFactoryImpl(blink::WebGraphicsContext3D* context,
GpuChannelHost* channel,
int view_id);
virtual ~StreamTextureFactoryImpl();
@@ -33,9 +33,10 @@ class StreamTextureFactoryImpl : public StreamTextureFactory {
virtual void DestroyStreamTexture(unsigned texture_id) OVERRIDE;
virtual void SetStreamTextureSize(int32 texture_id,
const gfx::Size& size) OVERRIDE;
+ virtual blink::WebGraphicsContext3D* Context3d() OVERRIDE;
private:
- WebKit::WebGraphicsContext3D* context_;
+ blink::WebGraphicsContext3D* context_;
scoped_refptr<GpuChannelHost> channel_;
int view_id_;
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc b/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc
index 575bfa6557d..c284328a4b2 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc
+++ b/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc
@@ -117,14 +117,19 @@ void StreamTextureProxyImpl::OnFrameAvailable() {
} // namespace
StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl(
- ContextProvider* context_provider,
+ const CreateContextProviderCallback& try_create_callback,
int view_id)
- : context_provider_(context_provider), view_id_(view_id) {}
+ : create_context_provider_callback_(try_create_callback),
+ context_provider_(create_context_provider_callback_.Run()),
+ view_id_(view_id) {}
StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {}
StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() {
if (!context_provider_)
+ context_provider_ = create_context_provider_callback_.Run();
+
+ if (!context_provider_)
return NULL;
return new StreamTextureProxyImpl(context_provider_);
}
@@ -149,7 +154,7 @@ unsigned StreamTextureFactorySynchronousImpl::CreateStreamTexture(
gpu::Mailbox* texture_mailbox,
unsigned* texture_mailbox_sync_point) {
DCHECK(context_provider_);
- WebKit::WebGraphicsContext3D* context = context_provider_->Context3d();
+ blink::WebGraphicsContext3D* context = context_provider_->Context3d();
unsigned stream_id = 0;
if (context->makeContextCurrent()) {
*texture_id = context->createTexture();
@@ -168,7 +173,7 @@ unsigned StreamTextureFactorySynchronousImpl::CreateStreamTexture(
void StreamTextureFactorySynchronousImpl::DestroyStreamTexture(
unsigned texture_id) {
DCHECK(context_provider_);
- WebKit::WebGraphicsContext3D* context = context_provider_->Context3d();
+ blink::WebGraphicsContext3D* context = context_provider_->Context3d();
if (context->makeContextCurrent()) {
context->destroyStreamTextureCHROMIUM(texture_id);
context->deleteTexture(texture_id);
@@ -180,4 +185,10 @@ void StreamTextureFactorySynchronousImpl::SetStreamTextureSize(
int32 stream_id,
const gfx::Size& size) {}
+blink::WebGraphicsContext3D*
+StreamTextureFactorySynchronousImpl::Context3d() {
+ DCHECK(context_provider_);
+ return context_provider_->Context3d();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h b/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h
index 8b6ab6f106d..51c77e5666e 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h
+++ b/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_
#define CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_
+#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "content/renderer/media/android/stream_texture_factory_android.h"
@@ -12,7 +13,7 @@ namespace gfx {
class SurfaceTexture;
}
-namespace WebKit {
+namespace blink {
class WebGraphicsContext3D;
}
@@ -26,15 +27,19 @@ class StreamTextureFactorySynchronousImpl : public StreamTextureFactory {
virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
uint32 stream_id) = 0;
- virtual WebKit::WebGraphicsContext3D* Context3d() = 0;
+ virtual blink::WebGraphicsContext3D* Context3d() = 0;
protected:
friend class base::RefCountedThreadSafe<ContextProvider>;
virtual ~ContextProvider() {}
};
- StreamTextureFactorySynchronousImpl(ContextProvider* context_provider,
- int view_id);
+ typedef base::Callback<scoped_refptr<ContextProvider>(void)>
+ CreateContextProviderCallback;
+
+ StreamTextureFactorySynchronousImpl(
+ const CreateContextProviderCallback& try_create_callback,
+ int view_id);
virtual ~StreamTextureFactorySynchronousImpl();
virtual StreamTextureProxy* CreateProxy() OVERRIDE;
@@ -47,8 +52,10 @@ class StreamTextureFactorySynchronousImpl : public StreamTextureFactory {
virtual void DestroyStreamTexture(unsigned texture_id) OVERRIDE;
virtual void SetStreamTextureSize(int32 stream_id,
const gfx::Size& size) OVERRIDE;
+ virtual blink::WebGraphicsContext3D* Context3d() OVERRIDE;
private:
+ CreateContextProviderCallback create_context_provider_callback_;
scoped_refptr<ContextProvider> context_provider_;
int view_id_;
diff --git a/chromium/content/renderer/media/android/webmediaplayer_android.cc b/chromium/content/renderer/media/android/webmediaplayer_android.cc
index b2c0b37661d..a39ae56fead 100644
--- a/chromium/content/renderer/media/android/webmediaplayer_android.cc
+++ b/chromium/content/renderer/media/android/webmediaplayer_android.cc
@@ -13,26 +13,31 @@
#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "cc/layers/video_layer.h"
+#include "content/public/common/content_client.h"
#include "content/renderer/media/android/proxy_media_keys.h"
#include "content/renderer/media/android/renderer_demuxer_android.h"
#include "content/renderer/media/android/renderer_media_player_manager.h"
-#include "content/renderer/media/android/webmediaplayer_proxy_android.h"
#include "content/renderer/media/crypto/key_systems.h"
#include "content/renderer/media/webmediaplayer_delegate.h"
#include "content/renderer/media/webmediaplayer_util.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "grit/content_resources.h"
#include "media/base/android/media_player_android.h"
#include "media/base/bind_to_loop.h"
#include "media/base/media_switches.h"
#include "media/base/video_frame.h"
#include "net/base/mime_util.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebMediaPlayerClient.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebView.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "ui/gfx/image/image.h"
#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
#if defined(GOOGLE_TV)
@@ -42,11 +47,11 @@
static const uint32 kGLTextureExternalOES = 0x8D65;
-using WebKit::WebMediaPlayer;
-using WebKit::WebSize;
-using WebKit::WebString;
-using WebKit::WebTimeRanges;
-using WebKit::WebURL;
+using blink::WebMediaPlayer;
+using blink::WebSize;
+using blink::WebString;
+using blink::WebTimeRanges;
+using blink::WebURL;
using media::MediaPlayerAndroid;
using media::VideoFrame;
@@ -57,12 +62,23 @@ const char* kMediaEme = "Media.EME.";
namespace content {
+// static
+void WebMediaPlayerAndroid::OnReleaseRemotePlaybackTexture(
+ const scoped_refptr<base::MessageLoopProxy>& main_loop,
+ const base::WeakPtr<WebMediaPlayerAndroid>& player,
+ uint32 sync_point) {
+ main_loop->PostTask(
+ FROM_HERE,
+ base::Bind(&WebMediaPlayerAndroid::DoReleaseRemotePlaybackTexture,
+ player,
+ sync_point));
+}
+
WebMediaPlayerAndroid::WebMediaPlayerAndroid(
- WebKit::WebFrame* frame,
- WebKit::WebMediaPlayerClient* client,
+ blink::WebFrame* frame,
+ blink::WebMediaPlayerClient* client,
base::WeakPtr<WebMediaPlayerDelegate> delegate,
RendererMediaPlayerManager* manager,
- WebMediaPlayerProxyAndroid* proxy,
StreamTextureFactory* factory,
const scoped_refptr<base::MessageLoopProxy>& media_loop,
media::MediaLog* media_log)
@@ -73,12 +89,13 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
main_loop_(base::MessageLoopProxy::current()),
media_loop_(media_loop),
ignore_metadata_duration_change_(false),
- pending_seek_(0),
+ pending_seek_(false),
seeking_(false),
did_loading_progress_(false),
manager_(manager),
network_state_(WebMediaPlayer::NetworkStateEmpty),
ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
+ remote_playback_texture_id_(0),
texture_id_(0),
texture_mailbox_sync_point_(0),
stream_id_(0),
@@ -99,13 +116,14 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
#endif // defined(GOOGLE_TV)
pending_playback_(false),
player_type_(MEDIA_PLAYER_TYPE_URL),
- proxy_(proxy),
current_time_(0),
+ is_remote_(false),
media_log_(media_log),
weak_factory_(this) {
- DCHECK(proxy_);
DCHECK(manager_);
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+
// We want to be notified of |main_loop_| destruction.
base::MessageLoop::current()->AddDestructionObserver(this);
@@ -121,25 +139,16 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
external_surface_threshold_ = -1;
}
}
+#endif // defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
// Defer stream texture creation until we are sure it's necessary.
- stream_id_ = 0;
needs_establish_peer_ = false;
current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1));
-#endif
- if (stream_texture_factory_) {
- stream_texture_proxy_.reset(stream_texture_factory_->CreateProxy());
- if (needs_establish_peer_ && stream_texture_proxy_) {
- stream_id_ = stream_texture_factory_->CreateStreamTexture(
- kGLTextureExternalOES,
- &texture_id_,
- &texture_mailbox_,
- &texture_mailbox_sync_point_);
- ReallocateVideoFrame();
- }
- }
+#endif // defined(VIDEO_HOLE)
+ TryCreateStreamTextureProxyIfNeeded();
- if (WebKit::WebRuntimeFeatures::isLegacyEncryptedMediaEnabled()) {
+ if (blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled()) {
// TODO(xhwang): Report an error when there is encrypted stream but EME is
// not enabled. Currently the player just doesn't start and waits for ever.
decryptor_.reset(new ProxyDecryptor(
@@ -147,7 +156,7 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
client,
frame,
#else
- proxy_,
+ manager_,
player_id_, // TODO(xhwang): Use media_keys_id when MediaKeys are
// separated from WebMediaPlayer.
#endif // defined(ENABLE_PEPPER_CDMS)
@@ -163,14 +172,20 @@ WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
SetVideoFrameProviderClient(NULL);
client_->setWebLayer(NULL);
- if (proxy_)
- proxy_->DestroyPlayer(player_id_);
+ if (manager_) {
+ manager_->DestroyPlayer(player_id_);
+ manager_->UnregisterMediaPlayer(player_id_);
+ }
if (stream_id_)
stream_texture_factory_->DestroyStreamTexture(texture_id_);
- if (manager_)
- manager_->UnregisterMediaPlayer(player_id_);
+ if (remote_playback_texture_id_) {
+ blink::WebGraphicsContext3D* context =
+ stream_texture_factory_->Context3d();
+ if (context->makeContextCurrent())
+ context->deleteTexture(remote_playback_texture_id_);
+ }
if (base::MessageLoop::current())
base::MessageLoop::current()->RemoveDestructionObserver(this);
@@ -198,7 +213,7 @@ WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
}
void WebMediaPlayerAndroid::load(LoadType load_type,
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
CORSMode cors_mode) {
switch (load_type) {
case LoadTypeURL:
@@ -250,8 +265,6 @@ void WebMediaPlayerAndroid::load(LoadType load_type,
base::Bind(&WebMediaPlayerAndroid::UpdateNetworkState,
weak_factory_.GetWeakPtr()),
base::Bind(&WebMediaPlayerAndroid::OnDurationChanged,
- weak_factory_.GetWeakPtr()),
- base::Bind(&WebMediaPlayerAndroid::OnTimeUpdate,
weak_factory_.GetWeakPtr()));
}
#if defined(GOOGLE_TV)
@@ -279,11 +292,11 @@ void WebMediaPlayerAndroid::load(LoadType load_type,
url_ = url;
GURL first_party_url = frame_->document().firstPartyForCookies();
- proxy_->Initialize(
+ manager_->Initialize(
player_type_, player_id_, url, first_party_url, demuxer_client_id);
- if (manager_->IsInFullscreen(frame_))
- proxy_->EnterFullscreen(player_id_);
+ if (manager_->ShouldEnterFullscreen(frame_))
+ manager_->EnterFullscreen(player_id_, frame_);
UpdateNetworkState(WebMediaPlayer::NetworkStateLoading);
UpdateReadyState(WebMediaPlayer::ReadyStateHaveNothing);
@@ -312,20 +325,24 @@ void WebMediaPlayerAndroid::DidLoadMediaInfo(
}
void WebMediaPlayerAndroid::play() {
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
if (hasVideo() && needs_external_surface_ &&
!manager_->IsInFullscreen(frame_)) {
DCHECK(!needs_establish_peer_);
- proxy_->RequestExternalSurface(player_id_, last_computed_rect_);
+ manager_->RequestExternalSurface(player_id_, last_computed_rect_);
}
+#endif // defined(VIDEO_HOLE)
+#if defined(GOOGLE_TV)
if (audio_renderer_ && paused())
audio_renderer_->Play();
-#endif
+#endif // defined(GOOGLE_TV)
+
+ TryCreateStreamTextureProxyIfNeeded();
if (hasVideo() && needs_establish_peer_)
EstablishSurfaceTexturePeer();
if (paused())
- proxy_->Start(player_id_);
+ manager_->Start(player_id_);
UpdatePlayingState(true);
UpdateNetworkState(WebMediaPlayer::NetworkStateLoading);
playing_started_ = true;
@@ -340,16 +357,52 @@ void WebMediaPlayerAndroid::pause(bool is_media_related_action) {
if (audio_renderer_ && !paused())
audio_renderer_->Pause();
#endif
- proxy_->Pause(player_id_, is_media_related_action);
+ manager_->Pause(player_id_, is_media_related_action);
UpdatePlayingState(false);
}
void WebMediaPlayerAndroid::seek(double seconds) {
- pending_seek_ = seconds;
+ DCHECK(main_loop_->BelongsToCurrentThread());
+ DVLOG(1) << __FUNCTION__ << "(" << seconds << ")";
+
+ base::TimeDelta new_seek_time = ConvertSecondsToTimestamp(seconds);
+
+ if (seeking_) {
+ if (new_seek_time == seek_time_) {
+ if (media_source_delegate_) {
+ if (!pending_seek_) {
+ // If using media source demuxer, only suppress redundant seeks if
+ // there is no pending seek. This enforces that any pending seek that
+ // results in a demuxer seek is preceded by matching
+ // CancelPendingSeek() and StartWaitingForSeek() calls.
+ return;
+ }
+ } else {
+ // Suppress all redundant seeks if unrestricted by media source
+ // demuxer API.
+ pending_seek_ = false;
+ return;
+ }
+ }
+
+ pending_seek_ = true;
+ pending_seek_time_ = new_seek_time;
+
+ if (media_source_delegate_)
+ media_source_delegate_->CancelPendingSeek(pending_seek_time_);
+
+ // Later, OnSeekComplete will trigger the pending seek.
+ return;
+ }
+
seeking_ = true;
+ seek_time_ = new_seek_time;
+
+ if (media_source_delegate_)
+ media_source_delegate_->StartWaitingForSeek(seek_time_);
- base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
- proxy_->Seek(player_id_, seek_time);
+ // Kick off the asynchronous seek!
+ manager_->Seek(player_id_, seek_time_);
}
bool WebMediaPlayerAndroid::supportsFullscreen() const {
@@ -365,7 +418,7 @@ void WebMediaPlayerAndroid::setRate(double rate) {
}
void WebMediaPlayerAndroid::setVolume(double volume) {
- proxy_->SetVolume(player_id_, volume);
+ manager_->SetVolume(player_id_, volume);
}
bool WebMediaPlayerAndroid::hasVideo() const {
@@ -414,9 +467,13 @@ double WebMediaPlayerAndroid::duration() const {
}
double WebMediaPlayerAndroid::currentTime() const {
- // If the player is pending for a seek, return the seek time.
- if (seeking())
- return pending_seek_;
+ // If the player is processing a seek, return the seek time.
+ // Blink may still query us if updatePlaybackState() occurs while seeking.
+ if (seeking()) {
+ return pending_seek_ ?
+ pending_seek_time_.InSecondsF() : seek_time_.InSecondsF();
+ }
+
return current_time_;
}
@@ -454,21 +511,21 @@ bool WebMediaPlayerAndroid::didLoadingProgress() const {
return ret;
}
-void WebMediaPlayerAndroid::paint(WebKit::WebCanvas* canvas,
- const WebKit::WebRect& rect,
+void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas,
+ const blink::WebRect& rect,
unsigned char alpha) {
NOTIMPLEMENTED();
}
bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
- WebKit::WebGraphicsContext3D* web_graphics_context,
+ blink::WebGraphicsContext3D* web_graphics_context,
unsigned int texture,
unsigned int level,
unsigned int internal_format,
unsigned int type,
bool premultiply_alpha,
bool flip_y) {
- if (!texture_id_)
+ if (is_remote_ || !texture_id_)
return false;
// For hidden video element (with style "display:none"), ensure the texture
@@ -610,11 +667,11 @@ void WebMediaPlayerAndroid::OnPlaybackComplete() {
// if the loop attribute is set, timeChanged() will update the current time
// to 0. It will perform a seek to 0. As the requests to the renderer
- // process are sequential, the OnSeekCompelete() will only occur
+ // process are sequential, the OnSeekComplete() will only occur
// once OnPlaybackComplete() is done. As the playback can only be executed
// upon completion of OnSeekComplete(), the request needs to be saved.
is_playing_ = false;
- if (seeking_ && pending_seek_ == 0)
+ if (seeking_ && seek_time_ == base::TimeDelta())
pending_playback_ = true;
}
@@ -623,9 +680,20 @@ void WebMediaPlayerAndroid::OnBufferingUpdate(int percentage) {
did_loading_progress_ = true;
}
+void WebMediaPlayerAndroid::OnSeekRequest(const base::TimeDelta& time_to_seek) {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+ client_->requestSeek(time_to_seek.InSecondsF());
+}
+
void WebMediaPlayerAndroid::OnSeekComplete(
const base::TimeDelta& current_time) {
+ DCHECK(main_loop_->BelongsToCurrentThread());
seeking_ = false;
+ if (pending_seek_) {
+ pending_seek_ = false;
+ seek(pending_seek_time_.InSecondsF());
+ return;
+ }
OnTimeUpdate(current_time);
@@ -661,28 +729,36 @@ void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
if (natural_size_.width == width && natural_size_.height == height)
return;
+#if defined(VIDEO_HOLE)
+ bool has_surface_size_restriction = false;
#if defined(GOOGLE_TV)
- if ((external_surface_threshold_ >= 0 &&
- external_surface_threshold_ <= width * height) ||
- // Use H/W surface for MSE as the content is protected.
- media_source_delegate_) {
+ has_surface_size_restriction = external_surface_threshold_ >= 0 &&
+ external_surface_threshold_ <= width * height;
+#endif // defined(GOOGLE_TV)
+ // Use H/W surface for MSE as the content might be protected.
+ // TODO(qinmin): Change this so that only EME needs the H/W surface
+ if (media_source_delegate_ || has_surface_size_restriction) {
needs_external_surface_ = true;
if (!paused() && !manager_->IsInFullscreen(frame_))
- proxy_->RequestExternalSurface(player_id_, last_computed_rect_);
+ manager_->RequestExternalSurface(player_id_, last_computed_rect_);
} else if (stream_texture_factory_ && !stream_id_) {
// Do deferred stream texture creation finally.
- stream_id_ = stream_texture_factory_->CreateStreamTexture(
- kGLTextureExternalOES,
- &texture_id_,
- &texture_mailbox_,
- &texture_mailbox_sync_point_);
+ DoCreateStreamTexture();
if (paused()) {
SetNeedsEstablishPeer(true);
} else {
EstablishSurfaceTexturePeer();
}
}
-#endif
+#else
+ // When play() gets called, |natural_size_| may still be empty and
+ // EstablishSurfaceTexturePeer() will not get called. As a result, the video
+ // may play without a surface texture. When we finally get the valid video
+ // size here, we should call EstablishSurfaceTexturePeer() if it has not been
+ // previously called.
+ if (!paused() && needs_establish_peer_)
+ EstablishSurfaceTexturePeer();
+#endif // defined(VIDEO_HOLE)
natural_size_.width = width;
natural_size_.height = height;
@@ -694,6 +770,24 @@ void WebMediaPlayerAndroid::OnTimeUpdate(const base::TimeDelta& current_time) {
current_time_ = current_time.InSecondsF();
}
+void WebMediaPlayerAndroid::OnConnectedToRemoteDevice() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ DCHECK(!media_source_delegate_);
+ DrawRemotePlaybackIcon();
+ is_remote_ = true;
+ SetNeedsEstablishPeer(false);
+}
+
+void WebMediaPlayerAndroid::OnDisconnectedFromRemoteDevice() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ DCHECK(!media_source_delegate_);
+ SetNeedsEstablishPeer(true);
+ if (!paused())
+ EstablishSurfaceTexturePeer();
+ is_remote_ = false;
+ ReallocateVideoFrame();
+}
+
void WebMediaPlayerAndroid::OnDidEnterFullscreen() {
if (!manager_->IsInFullscreen(frame_)) {
frame_->view()->willEnterFullScreen();
@@ -711,10 +805,10 @@ void WebMediaPlayerAndroid::OnDidExitFullscreen() {
if (!paused() && needs_establish_peer_)
EstablishSurfaceTexturePeer();
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
if (!paused() && needs_external_surface_)
- proxy_->RequestExternalSurface(player_id_, last_computed_rect_);
-#endif
+ manager_->RequestExternalSurface(player_id_, last_computed_rect_);
+#endif // defined(VIDEO_HOLE)
frame_->view()->willExitFullScreen();
frame_->view()->didExitFullScreen();
@@ -732,6 +826,10 @@ void WebMediaPlayerAndroid::OnMediaPlayerPause() {
client_->playbackStateChanged();
}
+void WebMediaPlayerAndroid::OnRequestFullscreen() {
+ client_->requestFullscreen();
+}
+
void WebMediaPlayerAndroid::OnDurationChanged(const base::TimeDelta& duration) {
DCHECK(main_loop_->BelongsToCurrentThread());
// Only MSE |player_type_| registers this callback.
@@ -776,9 +874,9 @@ void WebMediaPlayerAndroid::OnPlayerReleased() {
if (!needs_external_surface_)
needs_establish_peer_ = true;
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
last_computed_rect_ = gfx::RectF();
-#endif
+#endif // defined(VIDEO_HOLE)
}
void WebMediaPlayerAndroid::ReleaseMediaResources() {
@@ -800,7 +898,7 @@ void WebMediaPlayerAndroid::ReleaseMediaResources() {
case WebMediaPlayer::NetworkStateDecodeError:
break;
}
- proxy_->ReleaseResources(player_id_);
+ manager_->ReleaseResources(player_id_);
OnPlayerReleased();
}
@@ -817,33 +915,140 @@ void WebMediaPlayerAndroid::Detach() {
}
media_source_delegate_.reset();
- current_frame_ = NULL;
+ {
+ base::AutoLock auto_lock(current_frame_lock_);
+ current_frame_ = NULL;
+ }
+ is_remote_ = false;
manager_ = NULL;
- proxy_ = NULL;
+}
+
+void WebMediaPlayerAndroid::DrawRemotePlaybackIcon() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ if (!video_weblayer_)
+ return;
+ blink::WebGraphicsContext3D* context = stream_texture_factory_->Context3d();
+ if (!context->makeContextCurrent())
+ return;
+
+ // TODO(johnme): Should redraw this frame if the layer bounds change; but
+ // there seems no easy way to listen for the layer resizing (as opposed to
+ // OnVideoSizeChanged, which is when the frame sizes of the video file
+ // change). Perhaps have to poll (on main thread of course)?
+ gfx::Size video_size_css_px = video_weblayer_->bounds();
+ float device_scale_factor = frame_->view()->deviceScaleFactor();
+ // canvas_size will be the size in device pixels when pageScaleFactor == 1
+ gfx::Size canvas_size(
+ static_cast<int>(video_size_css_px.width() * device_scale_factor),
+ static_cast<int>(video_size_css_px.height() * device_scale_factor));
+
+ SkBitmap bitmap;
+ bitmap.setConfig(
+ SkBitmap::kARGB_8888_Config, canvas_size.width(), canvas_size.height());
+ bitmap.allocPixels();
+
+ SkCanvas canvas(bitmap);
+ canvas.drawColor(SK_ColorBLACK);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setFilterLevel(SkPaint::kHigh_FilterLevel);
+ const SkBitmap* icon_bitmap =
+ content::GetContentClient()
+ ->GetNativeImageNamed(IDR_MEDIAPLAYER_REMOTE_PLAYBACK_ICON)
+ .ToSkBitmap();
+ // In order to get a reasonable margin around the icon:
+ // - the icon should be under half the frame width
+ // - the icon should be at most 3/5 of the frame height
+ // Additionally, on very large screens, the icon size should be capped. A max
+ // width of 320 was arbitrarily chosen; since this is half the resource's
+ // pixel width, it should look crisp even on 2x deviceScaleFactor displays.
+ int icon_width = 320;
+ icon_width = std::min(icon_width, canvas_size.width() / 2);
+ icon_width = std::min(icon_width,
+ canvas_size.height() * icon_bitmap->width() /
+ icon_bitmap->height() * 3 / 5);
+ int icon_height = icon_width * icon_bitmap->height() / icon_bitmap->width();
+ // Center the icon within the frame
+ SkRect icon_rect = SkRect::MakeXYWH((canvas_size.width() - icon_width) / 2,
+ (canvas_size.height() - icon_height) / 2,
+ icon_width,
+ icon_height);
+ canvas.drawBitmapRectToRect(
+ *icon_bitmap, NULL /* src */, icon_rect /* dest */, &paint);
+
+ if (!remote_playback_texture_id_)
+ remote_playback_texture_id_ = context->createTexture();
+ unsigned texture_target = GL_TEXTURE_2D;
+ context->bindTexture(texture_target, remote_playback_texture_id_);
+ context->texParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ context->texParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ context->texParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ context->texParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ {
+ SkAutoLockPixels lock(bitmap);
+ context->texImage2D(texture_target,
+ 0 /* level */,
+ GL_RGBA /* internalformat */,
+ bitmap.width(),
+ bitmap.height(),
+ 0 /* border */,
+ GL_RGBA /* format */,
+ GL_UNSIGNED_BYTE /* type */,
+ bitmap.getPixels());
+ }
+
+ gpu::Mailbox texture_mailbox;
+ context->genMailboxCHROMIUM(texture_mailbox.name);
+ context->produceTextureCHROMIUM(texture_target, texture_mailbox.name);
+ context->flush();
+ unsigned texture_mailbox_sync_point = context->insertSyncPoint();
+
+ scoped_refptr<VideoFrame> new_frame = VideoFrame::WrapNativeTexture(
+ make_scoped_ptr(new VideoFrame::MailboxHolder(
+ texture_mailbox,
+ texture_mailbox_sync_point,
+ base::Bind(&WebMediaPlayerAndroid::OnReleaseRemotePlaybackTexture,
+ main_loop_,
+ weak_factory_.GetWeakPtr()))),
+ texture_target,
+ canvas_size /* coded_size */,
+ gfx::Rect(canvas_size) /* visible_rect */,
+ canvas_size /* natural_size */,
+ base::TimeDelta() /* timestamp */,
+ VideoFrame::ReadPixelsCB(),
+ base::Closure() /* no_longer_needed_cb */);
+ SetCurrentFrameInternal(new_frame);
}
void WebMediaPlayerAndroid::ReallocateVideoFrame() {
if (needs_external_surface_) {
- // VideoFrame::CreateHoleFrame is only defined under GOOGLE_TV.
-#if defined(GOOGLE_TV)
+ // VideoFrame::CreateHoleFrame is only defined under VIDEO_HOLE.
+#if defined(VIDEO_HOLE)
if (!natural_size_.isEmpty()) {
- current_frame_ = VideoFrame::CreateHoleFrame(natural_size_);
+ scoped_refptr<VideoFrame> new_frame =
+ VideoFrame::CreateHoleFrame(natural_size_);
+ SetCurrentFrameInternal(new_frame);
// Force the client to grab the hole frame.
client_->repaint();
}
#else
- NOTIMPLEMENTED() << "Hole punching not supported outside of Google TV";
-#endif
- } else if (texture_id_) {
- current_frame_ = VideoFrame::WrapNativeTexture(
- new VideoFrame::MailboxHolder(
+ NOTIMPLEMENTED() << "Hole punching not supported without VIDEO_HOLE flag";
+#endif // defined(VIDEO_HOLE)
+ } else if (!is_remote_ && texture_id_) {
+ scoped_refptr<VideoFrame> new_frame = VideoFrame::WrapNativeTexture(
+ make_scoped_ptr(new VideoFrame::MailboxHolder(
texture_mailbox_,
texture_mailbox_sync_point_,
- VideoFrame::MailboxHolder::TextureNoLongerNeededCallback()),
- kGLTextureExternalOES, natural_size_,
- gfx::Rect(natural_size_), natural_size_, base::TimeDelta(),
+ VideoFrame::MailboxHolder::TextureNoLongerNeededCallback())),
+ kGLTextureExternalOES,
+ natural_size_,
+ gfx::Rect(natural_size_),
+ natural_size_,
+ base::TimeDelta(),
VideoFrame::ReadPixelsCB(),
base::Closure());
+ SetCurrentFrameInternal(new_frame);
}
}
@@ -860,22 +1065,55 @@ void WebMediaPlayerAndroid::SetVideoFrameProviderClient(
stream_texture_proxy_->SetClient(client);
}
+void WebMediaPlayerAndroid::SetCurrentFrameInternal(
+ scoped_refptr<media::VideoFrame>& video_frame) {
+ base::AutoLock auto_lock(current_frame_lock_);
+ current_frame_ = video_frame;
+}
+
scoped_refptr<media::VideoFrame> WebMediaPlayerAndroid::GetCurrentFrame() {
+ scoped_refptr<VideoFrame> video_frame;
+ {
+ base::AutoLock auto_lock(current_frame_lock_);
+ video_frame = current_frame_;
+ }
+
if (!stream_texture_proxy_initialized_ && stream_texture_proxy_ &&
- stream_id_ && !needs_external_surface_) {
- gfx::Size natural_size = current_frame_->natural_size();
+ stream_id_ && !needs_external_surface_ && !is_remote_) {
+ gfx::Size natural_size = video_frame->natural_size();
+ // TODO(sievers): These variables are accessed on the wrong thread here.
stream_texture_proxy_->BindToCurrentThread(stream_id_);
stream_texture_factory_->SetStreamTextureSize(stream_id_, natural_size);
stream_texture_proxy_initialized_ = true;
cached_stream_texture_size_ = natural_size;
}
- return current_frame_;
+
+ return video_frame;
}
void WebMediaPlayerAndroid::PutCurrentFrame(
const scoped_refptr<media::VideoFrame>& frame) {
}
+void WebMediaPlayerAndroid::TryCreateStreamTextureProxyIfNeeded() {
+ // Already created.
+ if (stream_texture_proxy_)
+ return;
+
+ // No factory to create proxy.
+ if (!stream_texture_factory_)
+ return;
+
+ stream_texture_proxy_.reset(stream_texture_factory_->CreateProxy());
+ if (needs_establish_peer_ && stream_texture_proxy_) {
+ DoCreateStreamTexture();
+ ReallocateVideoFrame();
+ }
+
+ if (stream_texture_proxy_ && video_frame_provider_client_)
+ stream_texture_proxy_->SetClient(video_frame_provider_client_);
+}
+
void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() {
if (!stream_texture_proxy_)
return;
@@ -888,11 +1126,7 @@ void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() {
texture_id_ = 0;
texture_mailbox_ = gpu::Mailbox();
texture_mailbox_sync_point_ = 0;
- stream_id_ = stream_texture_factory_->CreateStreamTexture(
- kGLTextureExternalOES,
- &texture_id_,
- &texture_mailbox_,
- &texture_mailbox_sync_point_);
+ DoCreateStreamTexture();
ReallocateVideoFrame();
stream_texture_proxy_initialized_ = false;
}
@@ -901,6 +1135,17 @@ void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() {
needs_establish_peer_ = false;
}
+void WebMediaPlayerAndroid::DoCreateStreamTexture() {
+ DCHECK(!stream_id_);
+ DCHECK(!texture_id_);
+ DCHECK(!texture_mailbox_sync_point_);
+ stream_id_ = stream_texture_factory_->CreateStreamTexture(
+ kGLTextureExternalOES,
+ &texture_id_,
+ &texture_mailbox_,
+ &texture_mailbox_sync_point_);
+}
+
void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) {
needs_establish_peer_ = needs_establish_peer;
}
@@ -915,7 +1160,7 @@ void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) {
delegate_->DidPause(this);
}
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
bool WebMediaPlayerAndroid::RetrieveGeometryChange(gfx::RectF* rect) {
if (!video_weblayer_)
return false;
@@ -948,7 +1193,7 @@ bool WebMediaPlayerAndroid::RetrieveGeometryChange(gfx::RectF* rect) {
// UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is
// that UMA_* macros require the names to be constant throughout the process'
// lifetime.
-static void EmeUMAHistogramEnumeration(const WebKit::WebString& key_system,
+static void EmeUMAHistogramEnumeration(const blink::WebString& key_system,
const std::string& method,
int sample,
int boundary_value) {
@@ -958,7 +1203,7 @@ static void EmeUMAHistogramEnumeration(const WebKit::WebString& key_system,
base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
}
-static void EmeUMAHistogramCounts(const WebKit::WebString& key_system,
+static void EmeUMAHistogramCounts(const blink::WebString& key_system,
const std::string& method,
int sample) {
// Use the same parameters as UMA_HISTOGRAM_COUNTS.
@@ -1012,6 +1257,12 @@ WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::generateKeyRequest(
return e;
}
+bool WebMediaPlayerAndroid::IsKeySystemSupported(const WebString& key_system) {
+ // On Android, EME only works with MSE.
+ return player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE &&
+ IsConcreteSupportedKeySystem(key_system);
+}
+
WebMediaPlayer::MediaKeyException
WebMediaPlayerAndroid::GenerateKeyRequestInternal(
const WebString& key_system,
@@ -1021,7 +1272,7 @@ WebMediaPlayerAndroid::GenerateKeyRequestInternal(
<< std::string(reinterpret_cast<const char*>(init_data),
static_cast<size_t>(init_data_length));
- if (!IsConcreteSupportedKeySystem(key_system))
+ if (!IsKeySystemSupported(key_system))
return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
// We do not support run-time switching between key systems for now.
@@ -1074,7 +1325,7 @@ WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::AddKeyInternal(
static_cast<size_t>(init_data_length))
<< " [" << session_id.utf8().data() << "]";
- if (!IsConcreteSupportedKeySystem(key_system))
+ if (!IsKeySystemSupported(key_system))
return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
if (current_key_system_.isEmpty() || key_system != current_key_system_)
@@ -1098,7 +1349,7 @@ WebMediaPlayer::MediaKeyException
WebMediaPlayerAndroid::CancelKeyRequestInternal(
const WebString& key_system,
const WebString& session_id) {
- if (!IsConcreteSupportedKeySystem(key_system))
+ if (!IsKeySystemSupported(key_system))
return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
if (current_key_system_.isEmpty() || key_system != current_key_system_)
@@ -1128,7 +1379,7 @@ void WebMediaPlayerAndroid::OnKeyError(const std::string& session_id,
client_->keyError(
current_key_system_,
WebString::fromUTF8(session_id),
- static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
+ static_cast<blink::WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
system_code);
}
@@ -1147,17 +1398,16 @@ void WebMediaPlayerAndroid::OnKeyMessage(const std::string& session_id,
}
void WebMediaPlayerAndroid::OnMediaSourceOpened(
- WebKit::WebMediaSource* web_media_source) {
+ blink::WebMediaSource* web_media_source) {
client_->mediaSourceOpened(web_media_source);
}
-void WebMediaPlayerAndroid::OnNeedKey(const std::string& session_id,
- const std::string& type,
+void WebMediaPlayerAndroid::OnNeedKey(const std::string& type,
const std::vector<uint8>& init_data) {
DCHECK(main_loop_->BelongsToCurrentThread());
// Do not fire NeedKey event if encrypted media is not enabled.
- if (!WebKit::WebRuntimeFeatures::isEncryptedMediaEnabled() &&
- !WebKit::WebRuntimeFeatures::isLegacyEncryptedMediaEnabled()) {
+ if (!blink::WebRuntimeFeatures::isEncryptedMediaEnabled() &&
+ !blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled()) {
return;
}
@@ -1168,8 +1418,9 @@ void WebMediaPlayerAndroid::OnNeedKey(const std::string& session_id,
init_data_type_ = type;
const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
+ // TODO(xhwang): Drop |keySystem| and |sessionId| in keyNeeded() call.
client_->keyNeeded(WebString(),
- WebString::fromUTF8(session_id),
+ WebString(),
init_data_ptr,
init_data.size());
}
@@ -1187,15 +1438,28 @@ bool WebMediaPlayerAndroid::InjectMediaStream(
}
#endif
+void WebMediaPlayerAndroid::DoReleaseRemotePlaybackTexture(uint32 sync_point) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ DCHECK(remote_playback_texture_id_);
+
+ blink::WebGraphicsContext3D* context =
+ stream_texture_factory_->Context3d();
+
+ if (sync_point)
+ context->waitSyncPoint(sync_point);
+ context->deleteTexture(remote_playback_texture_id_);
+ remote_playback_texture_id_ = 0;
+}
+
void WebMediaPlayerAndroid::enterFullscreen() {
if (manager_->CanEnterFullscreen(frame_)) {
- proxy_->EnterFullscreen(player_id_);
+ manager_->EnterFullscreen(player_id_, frame_);
SetNeedsEstablishPeer(false);
}
}
void WebMediaPlayerAndroid::exitFullscreen() {
- proxy_->ExitFullscreen(player_id_);
+ manager_->ExitFullscreen(player_id_);
}
bool WebMediaPlayerAndroid::canEnterFullscreen() const {
diff --git a/chromium/content/renderer/media/android/webmediaplayer_android.h b/chromium/content/renderer/media/android/webmediaplayer_android.h
index c25b0bd3975..40582ca1c8a 100644
--- a/chromium/content/renderer/media/android/webmediaplayer_android.h
+++ b/chromium/content/renderer/media/android/webmediaplayer_android.h
@@ -26,9 +26,9 @@
#include "media/base/demuxer_stream.h"
#include "media/base/media_keys.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/web/WebMediaPlayer.h"
#include "ui/gfx/rect_f.h"
namespace media {
@@ -36,7 +36,7 @@ class Demuxer;
class MediaLog;
}
-namespace WebKit {
+namespace blink {
class WebFrame;
}
@@ -47,19 +47,18 @@ class WebLayerImpl;
namespace content {
class WebMediaPlayerDelegate;
class RendererMediaPlayerManager;
-class WebMediaPlayerProxyAndroid;
#if defined(GOOGLE_TV)
class MediaStreamAudioRenderer;
class MediaStreamClient;
#endif
-// This class implements WebKit::WebMediaPlayer by keeping the android
+// This class implements blink::WebMediaPlayer by keeping the android
// media player in the browser process. It listens to all the status changes
// sent from the browser process and sends playback controls to the media
// player.
class WebMediaPlayerAndroid
- : public WebKit::WebMediaPlayer,
+ : public blink::WebMediaPlayer,
public cc::VideoFrameProvider,
public base::MessageLoop::DestructionObserver,
public base::SupportsWeakPtr<WebMediaPlayerAndroid> {
@@ -72,24 +71,23 @@ class WebMediaPlayerAndroid
// blink, so that enterFullscreen() will not be called if another video is
// already in fullscreen.
WebMediaPlayerAndroid(
- WebKit::WebFrame* frame,
- WebKit::WebMediaPlayerClient* client,
+ blink::WebFrame* frame,
+ blink::WebMediaPlayerClient* client,
base::WeakPtr<WebMediaPlayerDelegate> delegate,
RendererMediaPlayerManager* manager,
- WebMediaPlayerProxyAndroid* proxy,
StreamTextureFactory* factory,
const scoped_refptr<base::MessageLoopProxy>& media_loop,
media::MediaLog* media_log);
virtual ~WebMediaPlayerAndroid();
- // WebKit::WebMediaPlayer implementation.
+ // blink::WebMediaPlayer implementation.
virtual void enterFullscreen();
virtual void exitFullscreen();
virtual bool canEnterFullscreen() const;
// Resource loading.
virtual void load(LoadType load_type,
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
CORSMode cors_mode) OVERRIDE;
// Playback controls.
@@ -101,16 +99,16 @@ class WebMediaPlayerAndroid
virtual bool supportsSave() const;
virtual void setRate(double rate);
virtual void setVolume(double volume);
- virtual const WebKit::WebTimeRanges& buffered();
+ virtual const blink::WebTimeRanges& buffered();
virtual double maxTimeSeekable() const;
// Methods for painting.
- virtual void paint(WebKit::WebCanvas* canvas,
- const WebKit::WebRect& rect,
+ virtual void paint(blink::WebCanvas* canvas,
+ const blink::WebRect& rect,
unsigned char alpha);
virtual bool copyVideoTextureToPlatformTexture(
- WebKit::WebGraphicsContext3D* web_graphics_context,
+ blink::WebGraphicsContext3D* web_graphics_context,
unsigned int texture,
unsigned int level,
unsigned int internal_format,
@@ -123,7 +121,7 @@ class WebMediaPlayerAndroid
virtual bool hasAudio() const;
// Dimensions of the video.
- virtual WebKit::WebSize naturalSize() const;
+ virtual blink::WebSize naturalSize() const;
// Getters of playback state.
virtual bool paused() const;
@@ -134,8 +132,8 @@ class WebMediaPlayerAndroid
virtual bool didLoadingProgress() const;
// Internal states of loading and network.
- virtual WebKit::WebMediaPlayer::NetworkState networkState() const;
- virtual WebKit::WebMediaPlayer::ReadyState readyState() const;
+ virtual blink::WebMediaPlayer::NetworkState networkState() const;
+ virtual blink::WebMediaPlayer::ReadyState readyState() const;
virtual bool hasSingleSecurityOrigin() const;
virtual bool didPassCORSAccessCheck() const;
@@ -161,6 +159,7 @@ class WebMediaPlayerAndroid
int height, bool success);
void OnPlaybackComplete();
void OnBufferingUpdate(int percentage);
+ void OnSeekRequest(const base::TimeDelta& time_to_seek);
void OnSeekComplete(const base::TimeDelta& current_time);
void OnMediaError(int error_type);
void OnVideoSizeChanged(int width, int height);
@@ -170,10 +169,13 @@ class WebMediaPlayerAndroid
void OnTimeUpdate(const base::TimeDelta& current_time);
// Functions called when media player status changes.
- void OnMediaPlayerPlay();
- void OnMediaPlayerPause();
+ void OnConnectedToRemoteDevice();
+ void OnDisconnectedFromRemoteDevice();
void OnDidEnterFullscreen();
void OnDidExitFullscreen();
+ void OnMediaPlayerPlay();
+ void OnMediaPlayerPause();
+ void OnRequestFullscreen();
// Called when the player is released.
virtual void OnPlayerReleased();
@@ -189,27 +191,27 @@ class WebMediaPlayerAndroid
// Detach the player from its manager.
void Detach();
-#if defined(GOOGLE_TV)
+#if defined(VIDEO_HOLE)
// Retrieve geometry of the media player (i.e. location and size of the video
// frame) if changed. Returns true only if the geometry has been changed since
// the last call.
bool RetrieveGeometryChange(gfx::RectF* rect);
-#endif
+#endif // defined(VIDEO_HOLE)
virtual MediaKeyException generateKeyRequest(
- const WebKit::WebString& key_system,
+ const blink::WebString& key_system,
const unsigned char* init_data,
unsigned init_data_length) OVERRIDE;
virtual MediaKeyException addKey(
- const WebKit::WebString& key_system,
+ const blink::WebString& key_system,
const unsigned char* key,
unsigned key_length,
const unsigned char* init_data,
unsigned init_data_length,
- const WebKit::WebString& session_id) OVERRIDE;
+ const blink::WebString& session_id) OVERRIDE;
virtual MediaKeyException cancelKeyRequest(
- const WebKit::WebString& key_system,
- const WebKit::WebString& session_id) OVERRIDE;
+ const blink::WebString& key_system,
+ const blink::WebString& session_id) OVERRIDE;
void OnKeyAdded(const std::string& session_id);
void OnKeyError(const std::string& session_id,
@@ -219,10 +221,9 @@ class WebMediaPlayerAndroid
const std::vector<uint8>& message,
const std::string& destination_url);
- void OnMediaSourceOpened(WebKit::WebMediaSource* web_media_source);
+ void OnMediaSourceOpened(blink::WebMediaSource* web_media_source);
void OnNeedKey(const std::string& type,
- const std::string& session_id,
const std::vector<uint8>& init_data);
#if defined(GOOGLE_TV)
@@ -231,13 +232,22 @@ class WebMediaPlayerAndroid
const base::Closure& destroy_demuxer_cb);
#endif
+ // Can be called on any thread.
+ static void OnReleaseRemotePlaybackTexture(
+ const scoped_refptr<base::MessageLoopProxy>& main_loop,
+ const base::WeakPtr<WebMediaPlayerAndroid>& player,
+ uint32 sync_point);
+
protected:
// Helper method to update the playing state.
void UpdatePlayingState(bool is_playing_);
// Helper methods for posting task for setting states and update WebKit.
- void UpdateNetworkState(WebKit::WebMediaPlayer::NetworkState state);
- void UpdateReadyState(WebKit::WebMediaPlayer::ReadyState state);
+ void UpdateNetworkState(blink::WebMediaPlayer::NetworkState state);
+ void UpdateReadyState(blink::WebMediaPlayer::ReadyState state);
+ void TryCreateStreamTextureProxyIfNeeded();
+ void DoCreateStreamTexture();
+
// Helper method to reestablish the surface texture peer for android
// media player.
@@ -246,34 +256,34 @@ class WebMediaPlayerAndroid
// Requesting whether the surface texture peer needs to be reestablished.
void SetNeedsEstablishPeer(bool needs_establish_peer);
-#if defined(GOOGLE_TV)
- // Request external surface for out-of-band composition.
- void RequestExternalSurface();
-#endif
-
private:
+ void DrawRemotePlaybackIcon();
void ReallocateVideoFrame();
+ void SetCurrentFrameInternal(scoped_refptr<media::VideoFrame>& frame);
void DidLoadMediaInfo(MediaInfoLoader::Status status);
+ void DoReleaseRemotePlaybackTexture(uint32 sync_point);
+
+ bool IsKeySystemSupported(const blink::WebString& key_system);
// Actually do the work for generateKeyRequest/addKey so they can easily
// report results to UMA.
MediaKeyException GenerateKeyRequestInternal(
- const WebKit::WebString& key_system,
+ const blink::WebString& key_system,
const unsigned char* init_data,
unsigned init_data_length);
- MediaKeyException AddKeyInternal(const WebKit::WebString& key_system,
+ MediaKeyException AddKeyInternal(const blink::WebString& key_system,
const unsigned char* key,
unsigned key_length,
const unsigned char* init_data,
unsigned init_data_length,
- const WebKit::WebString& session_id);
+ const blink::WebString& session_id);
MediaKeyException CancelKeyRequestInternal(
- const WebKit::WebString& key_system,
- const WebKit::WebString& session_id);
+ const blink::WebString& key_system,
+ const blink::WebString& session_id);
- WebKit::WebFrame* const frame_;
+ blink::WebFrame* const frame_;
- WebKit::WebMediaPlayerClient* const client_;
+ blink::WebMediaPlayerClient* const client_;
// |delegate_| is used to notify the browser process of the player status, so
// that the browser process can control screen locks.
@@ -283,16 +293,19 @@ class WebMediaPlayerAndroid
base::WeakPtr<WebMediaPlayerDelegate> delegate_;
// Save the list of buffered time ranges.
- WebKit::WebTimeRanges buffered_;
+ blink::WebTimeRanges buffered_;
// Size of the video.
- WebKit::WebSize natural_size_;
+ blink::WebSize natural_size_;
// Size that has been sent to StreamTexture.
- WebKit::WebSize cached_stream_texture_size_;
+ blink::WebSize cached_stream_texture_size_;
// The video frame object used for rendering by the compositor.
scoped_refptr<media::VideoFrame> current_frame_;
+ base::Lock current_frame_lock_;
+
+ base::ThreadChecker main_thread_checker_;
// Message loop for main renderer thread.
const scoped_refptr<base::MessageLoopProxy> main_loop_;
@@ -311,24 +324,31 @@ class WebMediaPlayerAndroid
// any subsequent duration value passed to OnMediaMetadataChange().
bool ignore_metadata_duration_change_;
- // The time android media player is trying to seek.
- double pending_seek_;
+ // Seek gets pending if another seek is in progress. Only last pending seek
+ // will have effect.
+ bool pending_seek_;
+ base::TimeDelta pending_seek_time_;
// Internal seek state.
bool seeking_;
+ base::TimeDelta seek_time_;
// Whether loading has progressed since the last call to didLoadingProgress.
mutable bool did_loading_progress_;
- // Manager for managing this object.
+ // Manager for managing this object and for delegating method calls on
+ // Render Thread.
RendererMediaPlayerManager* manager_;
// Player ID assigned by the |manager_|.
int player_id_;
// Current player states.
- WebKit::WebMediaPlayer::NetworkState network_state_;
- WebKit::WebMediaPlayer::ReadyState ready_state_;
+ blink::WebMediaPlayer::NetworkState network_state_;
+ blink::WebMediaPlayer::ReadyState ready_state_;
+
+ // GL texture ID used to show the remote playback icon.
+ unsigned int remote_playback_texture_id_;
// GL texture ID allocated to the video.
unsigned int texture_id_;
@@ -344,7 +364,7 @@ class WebMediaPlayerAndroid
// Whether the mediaplayer is playing.
bool is_playing_;
- // Wether the mediaplayer has already started playing.
+ // Whether the mediaplayer has already started playing.
bool playing_started_;
// Whether media player needs to re-establish the surface texture peer.
@@ -376,15 +396,17 @@ class WebMediaPlayerAndroid
scoped_ptr<webkit::WebLayerImpl> video_weblayer_;
+#if defined(VIDEO_HOLE)
+ // A rectangle represents the geometry of video frame, when computed last
+ // time.
+ gfx::RectF last_computed_rect_;
+#endif // defined(VIDEO_HOLE)
+
#if defined(GOOGLE_TV)
// Pixel threshold for external surface usage. Negative value means that the
// threshold is not defined, so that external surface is never used.
int external_surface_threshold_;
- // A rectangle represents the geometry of video frame, when computed last
- // time.
- gfx::RectF last_computed_rect_;
-
// Media Stream related fields.
media::Demuxer* demuxer_;
base::Closure destroy_demuxer_cb_;
@@ -401,23 +423,21 @@ class WebMediaPlayerAndroid
MediaPlayerHostMsg_Initialize_Type player_type_;
- // Proxy object that delegates method calls on Render Thread.
- // This object is created on the Render Thread and is only called in the
- // destructor.
- WebMediaPlayerProxyAndroid* proxy_;
-
// The current playing time. Because the media player is in the browser
// process, it will regularly update the |current_time_| by calling
// OnTimeUpdate().
double current_time_;
+ // Whether the browser is currently connected to a remote media player.
+ bool is_remote_;
+
media::MediaLog* media_log_;
scoped_ptr<MediaInfoLoader> info_loader_;
// The currently selected key system. Empty string means that no key system
// has been selected.
- WebKit::WebString current_key_system_;
+ blink::WebString current_key_system_;
// Temporary for EME v0.1. In the future the init data type should be passed
// through GenerateKeyRequest() directly from WebKit.
diff --git a/chromium/content/renderer/media/android/webmediaplayer_proxy_android.cc b/chromium/content/renderer/media/android/webmediaplayer_proxy_android.cc
deleted file mode 100644
index 39e87a07dd7..00000000000
--- a/chromium/content/renderer/media/android/webmediaplayer_proxy_android.cc
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/android/webmediaplayer_proxy_android.h"
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "content/common/media/media_player_messages_android.h"
-#include "content/renderer/media/android/renderer_media_player_manager.h"
-#include "content/renderer/media/android/webmediaplayer_android.h"
-
-namespace content {
-
-WebMediaPlayerProxyAndroid::WebMediaPlayerProxyAndroid(
- RenderView* render_view,
- RendererMediaPlayerManager* manager)
- : RenderViewObserver(render_view),
- manager_(manager) {}
-
-WebMediaPlayerProxyAndroid::~WebMediaPlayerProxyAndroid() {
- Send(new MediaPlayerHostMsg_DestroyAllMediaPlayers(routing_id()));
-}
-
-bool WebMediaPlayerProxyAndroid::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(WebMediaPlayerProxyAndroid, msg)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaMetadataChanged,
- OnMediaMetadataChanged)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPlaybackCompleted,
- OnMediaPlaybackCompleted)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaBufferingUpdate,
- OnMediaBufferingUpdate)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaSeekCompleted, OnMediaSeekCompleted)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaError, OnMediaError)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaVideoSizeChanged,
- OnVideoSizeChanged)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaTimeUpdate, OnTimeUpdate)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPlayerReleased,
- OnMediaPlayerReleased)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidEnterFullscreen, OnDidEnterFullscreen)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidExitFullscreen, OnDidExitFullscreen)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPlay, OnPlayerPlay)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPause, OnPlayerPause)
- IPC_MESSAGE_HANDLER(MediaKeysMsg_KeyAdded, OnKeyAdded)
- IPC_MESSAGE_HANDLER(MediaKeysMsg_KeyError, OnKeyError)
- IPC_MESSAGE_HANDLER(MediaKeysMsg_KeyMessage, OnKeyMessage)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void WebMediaPlayerProxyAndroid::Initialize(
- MediaPlayerHostMsg_Initialize_Type type,
- int player_id,
- const GURL& url,
- const GURL& first_party_for_cookies,
- int demuxer_client_id) {
- Send(new MediaPlayerHostMsg_Initialize(
- routing_id(), type, player_id, url, first_party_for_cookies,
- demuxer_client_id));
-}
-
-void WebMediaPlayerProxyAndroid::Start(int player_id) {
- Send(new MediaPlayerHostMsg_Start(routing_id(), player_id));
-}
-
-void WebMediaPlayerProxyAndroid::Pause(
- int player_id,
- bool is_media_related_action) {
- Send(new MediaPlayerHostMsg_Pause(
- routing_id(), player_id, is_media_related_action));
-}
-
-void WebMediaPlayerProxyAndroid::Seek(int player_id, base::TimeDelta time) {
- Send(new MediaPlayerHostMsg_Seek(routing_id(), player_id, time));
-}
-
-void WebMediaPlayerProxyAndroid::SetVolume(int player_id, double volume) {
- Send(new MediaPlayerHostMsg_SetVolume(routing_id(), player_id, volume));
-}
-
-void WebMediaPlayerProxyAndroid::ReleaseResources(int player_id) {
- Send(new MediaPlayerHostMsg_Release(routing_id(), player_id));
-}
-
-void WebMediaPlayerProxyAndroid::DestroyPlayer(int player_id) {
- Send(new MediaPlayerHostMsg_DestroyMediaPlayer(routing_id(), player_id));
-}
-
-void WebMediaPlayerProxyAndroid::OnMediaMetadataChanged(
- int player_id,
- base::TimeDelta duration,
- int width,
- int height,
- bool success) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnMediaMetadataChanged(duration, width, height, success);
-}
-
-void WebMediaPlayerProxyAndroid::OnMediaPlaybackCompleted(int player_id) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnPlaybackComplete();
-}
-
-void WebMediaPlayerProxyAndroid::OnMediaBufferingUpdate(int player_id,
- int percent) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnBufferingUpdate(percent);
-}
-
-void WebMediaPlayerProxyAndroid::OnMediaSeekCompleted(
- int player_id,
- base::TimeDelta current_time) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnSeekComplete(current_time);
-}
-
-void WebMediaPlayerProxyAndroid::OnMediaError(int player_id, int error) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnMediaError(error);
-}
-
-void WebMediaPlayerProxyAndroid::OnVideoSizeChanged(int player_id,
- int width,
- int height) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnVideoSizeChanged(width, height);
-}
-
-void WebMediaPlayerProxyAndroid::OnTimeUpdate(int player_id,
- base::TimeDelta current_time) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnTimeUpdate(current_time);
-}
-
-void WebMediaPlayerProxyAndroid::OnMediaPlayerReleased(int player_id) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnPlayerReleased();
-}
-
-void WebMediaPlayerProxyAndroid::OnDidEnterFullscreen(int player_id) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnDidEnterFullscreen();
-}
-
-void WebMediaPlayerProxyAndroid::OnDidExitFullscreen(int player_id) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnDidExitFullscreen();
-}
-
-void WebMediaPlayerProxyAndroid::OnPlayerPlay(int player_id) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnMediaPlayerPlay();
-}
-
-void WebMediaPlayerProxyAndroid::OnPlayerPause(int player_id) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
- if (player)
- player->OnMediaPlayerPause();
-}
-
-void WebMediaPlayerProxyAndroid::EnterFullscreen(int player_id) {
- Send(new MediaPlayerHostMsg_EnterFullscreen(routing_id(), player_id));
-}
-
-void WebMediaPlayerProxyAndroid::ExitFullscreen(int player_id) {
- Send(new MediaPlayerHostMsg_ExitFullscreen(routing_id(), player_id));
-}
-
-#if defined(GOOGLE_TV)
-void WebMediaPlayerProxyAndroid::RequestExternalSurface(
- int player_id,
- const gfx::RectF& geometry) {
- Send(new MediaPlayerHostMsg_NotifyExternalSurface(
- routing_id(), player_id, true, geometry));
-}
-
-void WebMediaPlayerProxyAndroid::DidCommitCompositorFrame() {
- std::map<int, gfx::RectF> geometry_change;
- manager_->RetrieveGeometryChanges(&geometry_change);
- for (std::map<int, gfx::RectF>::iterator it = geometry_change.begin();
- it != geometry_change.end();
- ++it) {
- Send(new MediaPlayerHostMsg_NotifyExternalSurface(
- routing_id(), it->first, false, it->second));
- }
-}
-#endif
-
-void WebMediaPlayerProxyAndroid::InitializeCDM(int media_keys_id,
- const std::vector<uint8>& uuid,
- const GURL& frame_url) {
- Send(new MediaKeysHostMsg_InitializeCDM(
- routing_id(), media_keys_id, uuid, frame_url));
-}
-
-void WebMediaPlayerProxyAndroid::GenerateKeyRequest(
- int media_keys_id,
- const std::string& type,
- const std::vector<uint8>& init_data) {
- Send(new MediaKeysHostMsg_GenerateKeyRequest(
- routing_id(), media_keys_id, type, init_data));
-}
-
-void WebMediaPlayerProxyAndroid::AddKey(int media_keys_id,
- const std::vector<uint8>& key,
- const std::vector<uint8>& init_data,
- const std::string& session_id) {
- Send(new MediaKeysHostMsg_AddKey(
- routing_id(), media_keys_id, key, init_data, session_id));
-}
-
-void WebMediaPlayerProxyAndroid::CancelKeyRequest(
- int media_keys_id,
- const std::string& session_id) {
- Send(new MediaKeysHostMsg_CancelKeyRequest(
- routing_id(), media_keys_id, session_id));
-}
-
-WebMediaPlayerAndroid* WebMediaPlayerProxyAndroid::GetWebMediaPlayer(
- int player_id) {
- return static_cast<WebMediaPlayerAndroid*>(
- manager_->GetMediaPlayer(player_id));
-}
-
-void WebMediaPlayerProxyAndroid::OnKeyAdded(int media_keys_id,
- const std::string& session_id) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(media_keys_id);
- if (player)
- player->OnKeyAdded(session_id);
-}
-
-void WebMediaPlayerProxyAndroid::OnKeyError(
- int media_keys_id,
- const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- int system_code) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(media_keys_id);
- if (player)
- player->OnKeyError(session_id, error_code, system_code);
-}
-
-void WebMediaPlayerProxyAndroid::OnKeyMessage(
- int media_keys_id,
- const std::string& session_id,
- const std::vector<uint8>& message,
- const std::string& destination_url) {
- WebMediaPlayerAndroid* player = GetWebMediaPlayer(media_keys_id);
- if (player)
- player->OnKeyMessage(session_id, message, destination_url);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/android/webmediaplayer_proxy_android.h b/chromium/content/renderer/media/android/webmediaplayer_proxy_android.h
deleted file mode 100644
index 76d2d43b1d5..00000000000
--- a/chromium/content/renderer/media/android/webmediaplayer_proxy_android.h
+++ /dev/null
@@ -1,136 +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_MEDIA_ANDROID_WEBMEDIAPLAYER_PROXY_ANDROID_H_
-#define CONTENT_RENDERER_MEDIA_ANDROID_WEBMEDIAPLAYER_PROXY_ANDROID_H_
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/time/time.h"
-#include "content/common/media/media_player_messages_enums_android.h"
-#include "content/public/renderer/render_view_observer.h"
-#include "media/base/android/media_player_android.h"
-#include "media/base/media_keys.h"
-#include "url/gurl.h"
-
-#if defined(GOOGLE_TV)
-#include "ui/gfx/rect_f.h"
-#endif
-
-namespace content {
-
-class RendererMediaPlayerManager;
-class WebMediaPlayerAndroid;
-
-// This class manages IPC communication between WebMediaPlayerAndroid and the
-// MediaPlayerManagerAndroid in the browser process.
-class WebMediaPlayerProxyAndroid : public RenderViewObserver {
- public:
- // Construct a WebMediaPlayerProxyAndroid object for the |render_view|.
- // |manager| is passed to this class so that it can find the right
- // WebMediaPlayerAndroid using player IDs.
- WebMediaPlayerProxyAndroid(
- RenderView* render_view,
- RendererMediaPlayerManager* manager);
- virtual ~WebMediaPlayerProxyAndroid();
-
- // RenderViewObserver overrides.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
-
- // Initializes a MediaPlayerAndroid object in browser process.
- void Initialize(MediaPlayerHostMsg_Initialize_Type type,
- int player_id,
- const GURL& url,
- const GURL& first_party_for_cookies,
- int demuxer_client_id);
-
- // Starts the player.
- void Start(int player_id);
-
- // Pauses the player.
- // is_media_related_action should be true if this pause is coming from an
- // an action that explicitly pauses the video (user pressing pause, JS, etc.)
- // Otherwise it should be false if Pause is being called due to other reasons
- // (cleanup, freeing resources, etc.)
- void Pause(int player_id, bool is_media_related_action);
-
- // Performs seek on the player.
- void Seek(int player_id, base::TimeDelta time);
-
- // Set the player volume.
- void SetVolume(int player_id, double volume);
-
- // Release resources for the player.
- void ReleaseResources(int player_id);
-
- // Destroy the player in the browser process
- void DestroyPlayer(int player_id);
-
- // Request the player to enter fullscreen.
- void EnterFullscreen(int player_id);
-
- // Request the player to exit fullscreen.
- void ExitFullscreen(int player_id);
-
-#if defined(GOOGLE_TV)
- // Request an external surface for out-of-band compositing.
- void RequestExternalSurface(int player_id, const gfx::RectF& geometry);
-
- // RenderViewObserver overrides.
- virtual void DidCommitCompositorFrame() OVERRIDE;
-#endif
-
- // Encrypted media related methods.
- void InitializeCDM(int media_keys_id,
- const std::vector<uint8>& uuid,
- const GURL& frame_url);
- void GenerateKeyRequest(int media_keys_id,
- const std::string& type,
- const std::vector<uint8>& init_data);
- void AddKey(int media_keys_id,
- const std::vector<uint8>& key,
- const std::vector<uint8>& init_data,
- const std::string& session_id);
- void CancelKeyRequest(int media_keys_id, const std::string& session_id);
-
- private:
- WebMediaPlayerAndroid* GetWebMediaPlayer(int player_id);
-
- // Message handlers.
- void OnMediaMetadataChanged(int player_id,
- base::TimeDelta duration,
- int width,
- int height,
- bool success);
- void OnMediaPlaybackCompleted(int player_id);
- void OnMediaBufferingUpdate(int player_id, int percent);
- void OnMediaSeekCompleted(int player_id, base::TimeDelta current_time);
- void OnMediaError(int player_id, int error);
- void OnVideoSizeChanged(int player_id, int width, int height);
- void OnTimeUpdate(int player_id, base::TimeDelta current_time);
- void OnMediaPlayerReleased(int player_id);
- void OnDidExitFullscreen(int player_id);
- void OnDidEnterFullscreen(int player_id);
- void OnPlayerPlay(int player_id);
- void OnPlayerPause(int player_id);
- void OnKeyAdded(int media_keys_id, const std::string& session_id);
- void OnKeyError(int media_keys_id,
- const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- int system_code);
- void OnKeyMessage(int media_keys_id,
- const std::string& session_id,
- const std::vector<uint8>& message,
- const std::string& destination_url);
-
- RendererMediaPlayerManager* manager_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(WebMediaPlayerProxyAndroid);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_ANDROID_WEBMEDIAPLAYER_PROXY_ANDROID_H_
diff --git a/chromium/content/renderer/media/audio_decoder.cc b/chromium/content/renderer/media/audio_decoder.cc
index 64cf6ddde73..dd9f1fafa0d 100644
--- a/chromium/content/renderer/media/audio_decoder.cc
+++ b/chromium/content/renderer/media/audio_decoder.cc
@@ -19,13 +19,13 @@ using media::AudioBus;
using media::AudioFileReader;
using media::InMemoryUrlProtocol;
using std::vector;
-using WebKit::WebAudioBus;
+using blink::WebAudioBus;
namespace content {
// Decode in-memory audio file data.
bool DecodeAudioFileData(
- WebKit::WebAudioBus* destination_bus,
+ blink::WebAudioBus* destination_bus,
const char* data, size_t data_size, double sample_rate) {
DCHECK(destination_bus);
if (!destination_bus)
diff --git a/chromium/content/renderer/media/audio_decoder.h b/chromium/content/renderer/media/audio_decoder.h
index bef404b44bc..9c14ed9f5d5 100644
--- a/chromium/content/renderer/media/audio_decoder.h
+++ b/chromium/content/renderer/media/audio_decoder.h
@@ -7,12 +7,12 @@
#include "base/basictypes.h"
-namespace WebKit { class WebAudioBus; }
+namespace blink { class WebAudioBus; }
namespace content {
// Decode in-memory audio file data.
-bool DecodeAudioFileData(WebKit::WebAudioBus* destination_bus, const char* data,
+bool DecodeAudioFileData(blink::WebAudioBus* destination_bus, const char* data,
size_t data_size, double sample_rate);
} // namespace content
diff --git a/chromium/content/renderer/media/audio_input_message_filter.cc b/chromium/content/renderer/media/audio_input_message_filter.cc
index 84a86de2577..a2696f085e6 100644
--- a/chromium/content/renderer/media/audio_input_message_filter.cc
+++ b/chromium/content/renderer/media/audio_input_message_filter.cc
@@ -6,7 +6,9 @@
#include "base/bind.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/strings/stringprintf.h"
#include "content/common/media/audio_messages.h"
+#include "content/renderer/media/webrtc_logging.h"
#include "ipc/ipc_logging.h"
namespace content {
@@ -123,6 +125,10 @@ void AudioInputMessageFilter::OnStreamCreated(
uint32 total_segments) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
+ WebRtcLogMessage(base::StringPrintf(
+ "AIMF::OnStreamCreated. stream_id=%d",
+ stream_id));
+
#if !defined(OS_WIN)
base::SyncSocket::Handle socket_handle = socket_descriptor.fd;
#endif
diff --git a/chromium/content/renderer/media/audio_message_filter.cc b/chromium/content/renderer/media/audio_message_filter.cc
index e56d612d579..27d0821342f 100644
--- a/chromium/content/renderer/media/audio_message_filter.cc
+++ b/chromium/content/renderer/media/audio_message_filter.cc
@@ -6,7 +6,9 @@
#include "base/bind.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/strings/stringprintf.h"
#include "content/common/media/audio_messages.h"
+#include "content/renderer/media/webrtc_logging.h"
#include "content/renderer/render_thread_impl.h"
#include "ipc/ipc_logging.h"
@@ -169,6 +171,10 @@ void AudioMessageFilter::OnStreamCreated(
uint32 length) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
+ WebRtcLogMessage(base::StringPrintf(
+ "AMF::OnStreamCreated. stream_id=%d",
+ stream_id));
+
#if !defined(OS_WIN)
base::SyncSocket::Handle socket_handle = socket_descriptor.fd;
#endif
@@ -202,6 +208,13 @@ void AudioMessageFilter::OnOutputDeviceChanged(int stream_id,
DCHECK(io_message_loop_->BelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
+ WebRtcLogMessage(base::StringPrintf(
+ "AMF::OnOutputDeviceChanged. stream_id=%d"
+ ", new_buffer_size=%d, new_sample_rate=%d",
+ stream_id,
+ new_buffer_size,
+ new_sample_rate));
+
// Ignore the message if an audio hardware config hasn't been created; this
// can occur if the renderer is using the high latency audio path.
// TODO(dalecurtis): After http://crbug.com/173435 is fixed, convert to CHECK.
diff --git a/chromium/content/renderer/media/buffered_data_source.cc b/chromium/content/renderer/media/buffered_data_source.cc
index 65a2d49d8fe..1992b706ad4 100644
--- a/chromium/content/renderer/media/buffered_data_source.cc
+++ b/chromium/content/renderer/media/buffered_data_source.cc
@@ -10,7 +10,7 @@
#include "media/base/media_log.h"
#include "net/base/net_errors.h"
-using WebKit::WebFrame;
+using blink::WebFrame;
namespace {
@@ -82,9 +82,7 @@ BufferedDataSource::BufferedDataSource(
WebFrame* frame,
media::MediaLog* media_log,
const DownloadingCB& downloading_cb)
- : weak_factory_(this),
- weak_this_(weak_factory_.GetWeakPtr()),
- cors_mode_(BufferedResourceLoader::kUnspecified),
+ : cors_mode_(BufferedResourceLoader::kUnspecified),
total_bytes_(kPositionNotSpecified),
assume_fully_buffered_(false),
streaming_(false),
@@ -98,8 +96,10 @@ BufferedDataSource::BufferedDataSource(
bitrate_(0),
playback_rate_(0.0),
media_log_(media_log),
- downloading_cb_(downloading_cb) {
+ downloading_cb_(downloading_cb),
+ weak_factory_(this) {
DCHECK(!downloading_cb_.is_null());
+ weak_this_ = weak_factory_.GetWeakPtr();
}
BufferedDataSource::~BufferedDataSource() {}
@@ -192,6 +192,28 @@ void BufferedDataSource::Abort() {
frame_ = NULL;
}
+void BufferedDataSource::MediaPlaybackRateChanged(float playback_rate) {
+ DCHECK(render_loop_->BelongsToCurrentThread());
+ DCHECK(loader_.get());
+
+ if (playback_rate < 0.0f)
+ return;
+
+ playback_rate_ = playback_rate;
+ loader_->SetPlaybackRate(playback_rate);
+}
+
+void BufferedDataSource::MediaIsPlaying() {
+ DCHECK(render_loop_->BelongsToCurrentThread());
+ media_has_played_ = true;
+ UpdateDeferStrategy(false);
+}
+
+void BufferedDataSource::MediaIsPaused() {
+ DCHECK(render_loop_->BelongsToCurrentThread());
+ UpdateDeferStrategy(true);
+}
+
/////////////////////////////////////////////////////////////////////////////
// media::DataSource implementation.
void BufferedDataSource::Stop(const base::Closure& closure) {
@@ -205,11 +227,6 @@ void BufferedDataSource::Stop(const base::Closure& closure) {
base::Bind(&BufferedDataSource::StopLoader, weak_this_));
}
-void BufferedDataSource::SetPlaybackRate(float playback_rate) {
- render_loop_->PostTask(FROM_HERE, base::Bind(
- &BufferedDataSource::SetPlaybackRateTask, weak_this_, playback_rate));
-}
-
void BufferedDataSource::SetBitrate(int bitrate) {
render_loop_->PostTask(FROM_HERE, base::Bind(
&BufferedDataSource::SetBitrateTask, weak_this_, bitrate));
@@ -279,35 +296,6 @@ void BufferedDataSource::StopLoader() {
loader_->Stop();
}
-void BufferedDataSource::SetPlaybackRateTask(float playback_rate) {
- DCHECK(render_loop_->BelongsToCurrentThread());
- DCHECK(loader_.get());
-
- if (playback_rate != 0)
- media_has_played_ = true;
-
- playback_rate_ = playback_rate;
- loader_->SetPlaybackRate(playback_rate);
-
- if (!loader_->range_supported()) {
- // 200 responses end up not being reused to satisfy future range requests,
- // and we don't want to get too far ahead of the read-head (and thus require
- // a restart), so keep to the thresholds.
- loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
- } else if (media_has_played_ && playback_rate == 0) {
- // If the playback has started (at which point the preload value is ignored)
- // and we're paused, then try to load as much as possible (the loader will
- // fall back to kCapacityDefer if it knows the current response won't be
- // useful from the cache in the future).
- loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer);
- } else {
- // If media is currently playing or the page indicated preload=auto,
- // use threshold strategy to enable/disable deferring when the buffer
- // is full/depleted.
- loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
- }
-}
-
void BufferedDataSource::SetBitrateTask(int bitrate) {
DCHECK(render_loop_->BelongsToCurrentThread());
DCHECK(loader_.get());
@@ -545,4 +533,28 @@ void BufferedDataSource::UpdateHostState_Locked() {
host()->AddBufferedByteRange(0, total_bytes_);
}
+void BufferedDataSource::UpdateDeferStrategy(bool paused) {
+ // 200 responses end up not being reused to satisfy future range requests,
+ // and we don't want to get too far ahead of the read-head (and thus require
+ // a restart), so keep to the thresholds.
+ if (!loader_->range_supported()) {
+ loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
+ return;
+ }
+
+ // If the playback has started (at which point the preload value is ignored)
+ // and we're paused, then try to load as much as possible (the loader will
+ // fall back to kCapacityDefer if it knows the current response won't be
+ // useful from the cache in the future).
+ if (media_has_played_ && paused) {
+ loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer);
+ return;
+ }
+
+ // If media is currently playing or the page indicated preload=auto,
+ // use threshold strategy to enable/disable deferring when the buffer
+ // is full/depleted.
+ loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/buffered_data_source.h b/chromium/content/renderer/media/buffered_data_source.h
index da451ba9a73..30991dd2796 100644
--- a/chromium/content/renderer/media/buffered_data_source.h
+++ b/chromium/content/renderer/media/buffered_data_source.h
@@ -39,7 +39,7 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource {
// |downloading_cb| will be called whenever the downloading/paused state of
// the source changes.
BufferedDataSource(const scoped_refptr<base::MessageLoopProxy>& render_loop,
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
media::MediaLog* media_log,
const DownloadingCB& downloading_cb);
virtual ~BufferedDataSource();
@@ -73,11 +73,16 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource {
// Method called on the render thread.
void Abort();
+ // Notifies changes in playback state for controlling media buffering
+ // behavior.
+ void MediaPlaybackRateChanged(float playback_rate);
+ void MediaIsPlaying();
+ void MediaIsPaused();
+
// media::DataSource implementation.
// Called from demuxer thread.
virtual void set_host(media::DataSourceHost* host) OVERRIDE;
virtual void Stop(const base::Closure& closure) OVERRIDE;
- virtual void SetPlaybackRate(float playback_rate) OVERRIDE;
virtual void Read(int64 position, int size, uint8* data,
const media::DataSource::ReadCB& read_cb) OVERRIDE;
@@ -105,11 +110,6 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource {
// Stops |loader_| if present. Used by Abort() and Stop().
void StopLoader();
- // This task uses the current playback rate with the previous playback rate
- // to determine whether we are going from pause to play and play to pause,
- // and signals the buffered resource loader accordingly.
- void SetPlaybackRateTask(float playback_rate);
-
// Tells |loader_| the bitrate of the media.
void SetBitrateTask(int bitrate);
@@ -135,7 +135,10 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource {
void UpdateHostState_Locked();
- base::WeakPtrFactory<BufferedDataSource> weak_factory_;
+ // Update |loader_|'s deferring strategy in response to a play/pause, or
+ // change in playback rate.
+ void UpdateDeferStrategy(bool paused);
+
base::WeakPtr<BufferedDataSource> weak_this_;
// URL of the resource requested.
@@ -157,7 +160,7 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource {
bool streaming_;
// A webframe for loading.
- WebKit::WebFrame* frame_;
+ blink::WebFrame* frame_;
// A resource loader for the media resource.
scoped_ptr<BufferedResourceLoader> loader_;
@@ -213,6 +216,8 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource {
DownloadingCB downloading_cb_;
+ base::WeakPtrFactory<BufferedDataSource> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(BufferedDataSource);
};
diff --git a/chromium/content/renderer/media/buffered_data_source_unittest.cc b/chromium/content/renderer/media/buffered_data_source_unittest.cc
index 11af9eb8349..b7808a88d53 100644
--- a/chromium/content/renderer/media/buffered_data_source_unittest.cc
+++ b/chromium/content/renderer/media/buffered_data_source_unittest.cc
@@ -6,14 +6,14 @@
#include "base/message_loop/message_loop.h"
#include "content/renderer/media/buffered_data_source.h"
#include "content/renderer/media/test_response_generator.h"
+#include "content/test/mock_webframeclient.h"
+#include "content/test/mock_weburlloader.h"
#include "media/base/media_log.h"
#include "media/base/mock_data_source_host.h"
#include "media/base/mock_filters.h"
#include "media/base/test_helpers.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebView.h"
-#include "webkit/mocks/mock_webframeclient.h"
-#include "webkit/mocks/mock_weburlloader.h"
using ::testing::_;
using ::testing::Assign;
@@ -22,14 +22,11 @@ using ::testing::InSequence;
using ::testing::NiceMock;
using ::testing::StrictMock;
-using WebKit::WebFrame;
-using WebKit::WebString;
-using WebKit::WebURLLoader;
-using WebKit::WebURLResponse;
-using WebKit::WebView;
-
-using webkit_glue::MockWebFrameClient;
-using webkit_glue::MockWebURLLoader;
+using blink::WebFrame;
+using blink::WebString;
+using blink::WebURLLoader;
+using blink::WebURLResponse;
+using blink::WebView;
namespace content {
@@ -554,10 +551,10 @@ TEST_F(BufferedDataSourceTest, SetBitrate) {
Stop();
}
-TEST_F(BufferedDataSourceTest, SetPlaybackRate) {
+TEST_F(BufferedDataSourceTest, MediaPlaybackRateChanged) {
InitializeWith206Response();
- data_source_->SetPlaybackRate(2.0f);
+ data_source_->MediaPlaybackRateChanged(2.0f);
message_loop_.RunUntilIdle();
EXPECT_EQ(2.0f, data_source_playback_rate());
EXPECT_EQ(2.0f, loader_playback_rate());
diff --git a/chromium/content/renderer/media/buffered_resource_loader.cc b/chromium/content/renderer/media/buffered_resource_loader.cc
index a99f7ec77d0..b050febc25d 100644
--- a/chromium/content/renderer/media/buffered_resource_loader.cc
+++ b/chromium/content/renderer/media/buffered_resource_loader.cc
@@ -6,13 +6,12 @@
#include "base/bits.h"
#include "base/callback_helpers.h"
-#include "base/format_macros.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "content/renderer/media/cache_util.h"
#include "media/base/media_log.h"
+#include "net/http/http_byte_range.h"
#include "net/http/http_request_headers.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
@@ -20,13 +19,13 @@
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebURLLoaderOptions.h"
-using WebKit::WebFrame;
-using WebKit::WebString;
-using WebKit::WebURLError;
-using WebKit::WebURLLoader;
-using WebKit::WebURLLoaderOptions;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
+using blink::WebFrame;
+using blink::WebString;
+using blink::WebURLError;
+using blink::WebURLLoader;
+using blink::WebURLLoaderOptions;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
namespace content {
@@ -165,11 +164,11 @@ void BufferedResourceLoader::Start(
if (IsRangeRequest()) {
request.setHTTPHeaderField(
WebString::fromUTF8(net::HttpRequestHeaders::kRange),
- WebString::fromUTF8(GenerateHeaders(first_byte_position_,
- last_byte_position_)));
+ WebString::fromUTF8(net::HttpByteRange::Bounded(
+ first_byte_position_, last_byte_position_).GetHeaderValue()));
}
- frame->setReferrerForRequest(request, WebKit::WebURL());
+ frame->setReferrerForRequest(request, blink::WebURL());
// Disable compression, compression for audio/video doesn't make sense...
request.setHTTPHeaderField(
@@ -188,6 +187,8 @@ void BufferedResourceLoader::Start(
WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
} else {
options.exposeAllResponseHeaders = true;
+ // The author header set is empty, no preflight should go ahead.
+ options.preflightPolicy = WebURLLoaderOptions::PreventPreflight;
options.crossOriginRequestPolicy =
WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
if (cors_mode_ == kUseCredentials)
@@ -322,7 +323,7 @@ bool BufferedResourceLoader::range_supported() {
}
/////////////////////////////////////////////////////////////////////////////
-// WebKit::WebURLLoaderClient implementation.
+// blink::WebURLLoaderClient implementation.
void BufferedResourceLoader::willSendRequest(
WebURLLoader* loader,
WebURLRequest& newRequest,
@@ -332,7 +333,7 @@ void BufferedResourceLoader::willSendRequest(
// In this case we shouldn't do anything.
if (start_cb_.is_null()) {
// Set the url in the request to an invalid value (empty url).
- newRequest.setURL(WebKit::WebURL());
+ newRequest.setURL(blink::WebURL());
return;
}
@@ -467,7 +468,7 @@ void BufferedResourceLoader::didReceiveData(
}
void BufferedResourceLoader::didDownloadData(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
int dataLength,
int encoded_data_length) {
NOTIMPLEMENTED();
@@ -748,27 +749,6 @@ bool BufferedResourceLoader::VerifyPartialResponse(
return true;
}
-std::string BufferedResourceLoader::GenerateHeaders(
- int64 first_byte_position,
- int64 last_byte_position) {
- // Construct the value for the range header.
- std::string header;
- if (first_byte_position > kPositionNotSpecified &&
- last_byte_position > kPositionNotSpecified) {
- if (first_byte_position <= last_byte_position) {
- header = base::StringPrintf("bytes=%" PRId64 "-%" PRId64,
- first_byte_position,
- last_byte_position);
- }
- } else if (first_byte_position > kPositionNotSpecified) {
- header = base::StringPrintf("bytes=%" PRId64 "-",
- first_byte_position);
- } else if (last_byte_position > kPositionNotSpecified) {
- NOTIMPLEMENTED() << "Suffix range not implemented";
- }
- return header;
-}
-
void BufferedResourceLoader::DoneRead(Status status, int bytes_read) {
if (saved_forward_capacity_) {
buffer_.set_forward_capacity(saved_forward_capacity_);
diff --git a/chromium/content/renderer/media/buffered_resource_loader.h b/chromium/content/renderer/media/buffered_resource_loader.h
index 24b5ad8f96b..3331979d2c9 100644
--- a/chromium/content/renderer/media/buffered_resource_loader.h
+++ b/chromium/content/renderer/media/buffered_resource_loader.h
@@ -36,7 +36,7 @@ const char kHttpsScheme[] = "https";
// pausing resource loading when the in-memory buffer is full and resuming
// resource loading when there is available capacity.
class CONTENT_EXPORT BufferedResourceLoader
- : NON_EXPORTED_BASE(public WebKit::WebURLLoaderClient) {
+ : NON_EXPORTED_BASE(public blink::WebURLLoaderClient) {
public:
// kNeverDefer - Aggresively buffer; never defer loading while paused.
// kReadThenDefer - Request only enough data to fulfill read requests.
@@ -106,7 +106,7 @@ class CONTENT_EXPORT BufferedResourceLoader
void Start(const StartCB& start_cb,
const LoadingStateChangedCB& loading_cb,
const ProgressCB& progress_cb,
- WebKit::WebFrame* frame);
+ blink::WebFrame* frame);
// Stops everything associated with this loader, including active URL loads
// and pending callbacks.
@@ -138,36 +138,36 @@ class CONTENT_EXPORT BufferedResourceLoader
// Returns true if the server supports byte range requests.
bool range_supported();
- // WebKit::WebURLLoaderClient implementation.
+ // blink::WebURLLoaderClient implementation.
virtual void willSendRequest(
- WebKit::WebURLLoader* loader,
- WebKit::WebURLRequest& newRequest,
- const WebKit::WebURLResponse& redirectResponse);
+ blink::WebURLLoader* loader,
+ blink::WebURLRequest& newRequest,
+ const blink::WebURLResponse& redirectResponse);
virtual void didSendData(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
unsigned long long bytesSent,
unsigned long long totalBytesToBeSent);
virtual void didReceiveResponse(
- WebKit::WebURLLoader* loader,
- const WebKit::WebURLResponse& response);
+ blink::WebURLLoader* loader,
+ const blink::WebURLResponse& response);
virtual void didDownloadData(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
int data_length,
int encoded_data_length);
virtual void didReceiveData(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
const char* data,
int data_length,
int encoded_data_length);
virtual void didReceiveCachedMetadata(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
const char* data, int dataLength);
virtual void didFinishLoading(
- WebKit::WebURLLoader* loader,
+ blink::WebURLLoader* loader,
double finishTime);
virtual void didFail(
- WebKit::WebURLLoader* loader,
- const WebKit::WebURLError&);
+ blink::WebURLLoader* loader,
+ const blink::WebURLError&);
// Returns true if the media resource has a single origin, false otherwise.
// Only valid to call after Start() has completed.
@@ -235,16 +235,7 @@ class CONTENT_EXPORT BufferedResourceLoader
void ReadInternal();
// If we have made a range request, verify the response from the server.
- bool VerifyPartialResponse(const WebKit::WebURLResponse& response);
-
- // Returns the value for a range request header using parameters
- // |first_byte_position| and |last_byte_position|. Negative numbers other
- // than |kPositionNotSpecified| are not allowed for |first_byte_position| and
- // |last_byte_position|. |first_byte_position| should always be less than or
- // equal to |last_byte_position| if they are both not |kPositionNotSpecified|.
- // Empty string is returned on invalid parameters.
- std::string GenerateHeaders(int64 first_byte_position,
- int64 last_byte_position);
+ bool VerifyPartialResponse(const blink::WebURLResponse& response);
// Done with read. Invokes the read callback and reset parameters for the
// read request.
@@ -316,7 +307,7 @@ class CONTENT_EXPORT BufferedResourceLoader
int last_offset_;
// Injected WebURLLoader instance for testing purposes.
- scoped_ptr<WebKit::WebURLLoader> test_loader_;
+ scoped_ptr<blink::WebURLLoader> test_loader_;
// Bitrate of the media. Set to 0 if unknown.
int bitrate_;
diff --git a/chromium/content/renderer/media/buffered_resource_loader_unittest.cc b/chromium/content/renderer/media/buffered_resource_loader_unittest.cc
index a0a63cf2aea..656f1e846e7 100644
--- a/chromium/content/renderer/media/buffered_resource_loader_unittest.cc
+++ b/chromium/content/renderer/media/buffered_resource_loader_unittest.cc
@@ -10,6 +10,8 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "content/renderer/media/buffered_resource_loader.h"
+#include "content/test/mock_webframeclient.h"
+#include "content/test/mock_weburlloader.h"
#include "media/base/media_log.h"
#include "media/base/seekable_buffer.h"
#include "net/base/net_errors.h"
@@ -21,8 +23,6 @@
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
-#include "webkit/mocks/mock_webframeclient.h"
-#include "webkit/mocks/mock_weburlloader.h"
using ::testing::_;
using ::testing::InSequence;
@@ -30,13 +30,10 @@ using ::testing::Return;
using ::testing::Truly;
using ::testing::NiceMock;
-using WebKit::WebString;
-using WebKit::WebURLError;
-using WebKit::WebURLResponse;
-using WebKit::WebView;
-
-using webkit_glue::MockWebFrameClient;
-using webkit_glue::MockWebURLLoader;
+using blink::WebString;
+using blink::WebURLError;
+using blink::WebURLResponse;
+using blink::WebView;
namespace content {
@@ -56,7 +53,7 @@ enum NetworkState {
};
// Predicate that tests that request disallows compressed data.
-static bool CorrectAcceptEncoding(const WebKit::WebURLRequest &request) {
+static bool CorrectAcceptEncoding(const blink::WebURLRequest &request) {
std::string value = request.httpHeaderField(
WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding)).utf8();
return (value.find("identity;q=1") != std::string::npos) &&
@@ -91,7 +88,7 @@ class BufferedResourceLoaderTest : public testing::Test {
// |test_loader_| will be used when Start() is called.
url_loader_ = new NiceMock<MockWebURLLoader>();
- loader_->test_loader_ = scoped_ptr<WebKit::WebURLLoader>(url_loader_);
+ loader_->test_loader_ = scoped_ptr<blink::WebURLLoader>(url_loader_);
}
void SetLoaderBuffer(int forward_capacity, int backward_capacity) {
@@ -190,8 +187,8 @@ class BufferedResourceLoaderTest : public testing::Test {
void Redirect(const char* url) {
GURL redirectUrl(url);
- WebKit::WebURLRequest newRequest(redirectUrl);
- WebKit::WebURLResponse redirectResponse(gurl_);
+ blink::WebURLRequest newRequest(redirectUrl);
+ blink::WebURLResponse redirectResponse(gurl_);
loader_->willSendRequest(url_loader_, newRequest, redirectResponse);
diff --git a/chromium/content/renderer/media/cache_util.cc b/chromium/content/renderer/media/cache_util.cc
index f7326c12e09..2114ddd5189 100644
--- a/chromium/content/renderer/media/cache_util.cc
+++ b/chromium/content/renderer/media/cache_util.cc
@@ -18,7 +18,7 @@
using base::Time;
using base::TimeDelta;
using net::HttpVersion;
-using WebKit::WebURLResponse;
+using blink::WebURLResponse;
namespace content {
diff --git a/chromium/content/renderer/media/cache_util.h b/chromium/content/renderer/media/cache_util.h
index 061e87a4e73..aca8d8a9081 100644
--- a/chromium/content/renderer/media/cache_util.h
+++ b/chromium/content/renderer/media/cache_util.h
@@ -10,7 +10,7 @@
#include "base/basictypes.h"
#include "content/common/content_export.h"
-namespace WebKit {
+namespace blink {
class WebURLResponse;
}
@@ -34,7 +34,7 @@ enum UncacheableReason {
// Return the logical OR of the reasons "response" cannot be used for a future
// request (using the disk cache), or 0 if it might be useful.
uint32 CONTENT_EXPORT GetReasonsForUncacheability(
- const WebKit::WebURLResponse& response);
+ const blink::WebURLResponse& response);
} // namespace content
diff --git a/chromium/content/renderer/media/cache_util_unittest.cc b/chromium/content/renderer/media/cache_util_unittest.cc
index 806b201e1ef..2db66b94baa 100644
--- a/chromium/content/renderer/media/cache_util_unittest.cc
+++ b/chromium/content/renderer/media/cache_util_unittest.cc
@@ -14,8 +14,8 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
-using WebKit::WebString;
-using WebKit::WebURLResponse;
+using blink::WebString;
+using blink::WebURLResponse;
namespace content {
diff --git a/chromium/content/renderer/media/crypto/content_decryption_module_factory.cc b/chromium/content/renderer/media/crypto/content_decryption_module_factory.cc
index e53fa17debc..feafca7c4bc 100644
--- a/chromium/content/renderer/media/crypto/content_decryption_module_factory.cc
+++ b/chromium/content/renderer/media/crypto/content_decryption_module_factory.cc
@@ -12,12 +12,12 @@
#include "content/renderer/media/crypto/ppapi_decryptor.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/pepper_webplugin_impl.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebMediaPlayerClient.h"
#elif defined(OS_ANDROID)
#include "content/renderer/media/android/proxy_media_keys.h"
-#include "content/renderer/media/android/webmediaplayer_proxy_android.h"
+#include "content/renderer/media/android/renderer_media_player_manager.h"
#endif // defined(ENABLE_PEPPER_CDMS)
namespace content {
@@ -28,13 +28,13 @@ namespace content {
// closeHelperPluginSoon() when the Helper Plugin is no longer needed.
static scoped_refptr<PepperPluginInstanceImpl> CreateHelperPlugin(
const std::string& plugin_type,
- WebKit::WebMediaPlayerClient* web_media_player_client,
- WebKit::WebFrame* web_frame) {
+ blink::WebMediaPlayerClient* web_media_player_client,
+ blink::WebFrame* web_frame) {
DCHECK(web_media_player_client);
DCHECK(web_frame);
- WebKit::WebPlugin* web_plugin = web_media_player_client->createHelperPlugin(
- WebKit::WebString::fromUTF8(plugin_type), web_frame);
+ blink::WebPlugin* web_plugin = web_media_player_client->createHelperPlugin(
+ blink::WebString::fromUTF8(plugin_type), web_frame);
if (!web_plugin)
return NULL;
@@ -47,12 +47,14 @@ static scoped_refptr<PepperPluginInstanceImpl> CreateHelperPlugin(
static scoped_ptr<media::MediaKeys> CreatePpapiDecryptor(
const std::string& key_system,
- const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb,
+ const media::SessionCreatedCB& session_created_cb,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb,
const base::Closure& destroy_plugin_cb,
- WebKit::WebMediaPlayerClient* web_media_player_client,
- WebKit::WebFrame* web_frame) {
+ blink::WebMediaPlayerClient* web_media_player_client,
+ blink::WebFrame* web_frame) {
DCHECK(web_media_player_client);
DCHECK(web_frame);
@@ -61,16 +63,18 @@ static scoped_ptr<media::MediaKeys> CreatePpapiDecryptor(
const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance =
CreateHelperPlugin(plugin_type, web_media_player_client, web_frame);
if (!plugin_instance.get()) {
- DLOG(ERROR) << "ProxyDecryptor: plugin instance creation failed.";
+ DLOG(ERROR) << "Plugin instance creation failed.";
return scoped_ptr<media::MediaKeys>();
}
scoped_ptr<PpapiDecryptor> decryptor =
PpapiDecryptor::Create(key_system,
plugin_instance,
- key_added_cb,
- key_error_cb,
- key_message_cb,
+ session_created_cb,
+ session_message_cb,
+ session_ready_cb,
+ session_closed_cb,
+ session_error_cb,
destroy_plugin_cb);
if (!decryptor)
@@ -81,8 +85,8 @@ static scoped_ptr<media::MediaKeys> CreatePpapiDecryptor(
}
void ContentDecryptionModuleFactory::DestroyHelperPlugin(
- WebKit::WebMediaPlayerClient* web_media_player_client,
- WebKit::WebFrame* web_frame) {
+ blink::WebMediaPlayerClient* web_media_player_client,
+ blink::WebFrame* web_frame) {
web_media_player_client->closeHelperPluginSoon(web_frame);
}
#endif // defined(ENABLE_PEPPER_CDMS)
@@ -90,20 +94,26 @@ void ContentDecryptionModuleFactory::DestroyHelperPlugin(
scoped_ptr<media::MediaKeys> ContentDecryptionModuleFactory::Create(
const std::string& key_system,
#if defined(ENABLE_PEPPER_CDMS)
- WebKit::WebMediaPlayerClient* web_media_player_client,
- WebKit::WebFrame* web_frame,
+ blink::WebMediaPlayerClient* web_media_player_client,
+ blink::WebFrame* web_frame,
const base::Closure& destroy_plugin_cb,
#elif defined(OS_ANDROID)
- WebMediaPlayerProxyAndroid* proxy,
+ RendererMediaPlayerManager* manager,
int media_keys_id,
const GURL& frame_url,
#endif // defined(ENABLE_PEPPER_CDMS)
- const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb) {
+ const media::SessionCreatedCB& session_created_cb,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb) {
if (CanUseAesDecryptor(key_system)) {
return scoped_ptr<media::MediaKeys>(
- new media::AesDecryptor(key_added_cb, key_error_cb, key_message_cb));
+ new media::AesDecryptor(session_created_cb,
+ session_message_cb,
+ session_ready_cb,
+ session_closed_cb,
+ session_error_cb));
}
#if defined(ENABLE_PEPPER_CDMS)
@@ -112,12 +122,24 @@ scoped_ptr<media::MediaKeys> ContentDecryptionModuleFactory::Create(
if (!web_media_player_client)
return scoped_ptr<media::MediaKeys>();
- return CreatePpapiDecryptor(
- key_system, key_added_cb, key_error_cb, key_message_cb,
- destroy_plugin_cb, web_media_player_client, web_frame);
+ return CreatePpapiDecryptor(key_system,
+ session_created_cb,
+ session_message_cb,
+ session_ready_cb,
+ session_closed_cb,
+ session_error_cb,
+ destroy_plugin_cb,
+ web_media_player_client,
+ web_frame);
#elif defined(OS_ANDROID)
scoped_ptr<ProxyMediaKeys> proxy_media_keys(
- new ProxyMediaKeys(proxy, media_keys_id));
+ new ProxyMediaKeys(manager,
+ media_keys_id,
+ session_created_cb,
+ session_message_cb,
+ session_ready_cb,
+ session_closed_cb,
+ session_error_cb));
proxy_media_keys->InitializeCDM(key_system, frame_url);
return proxy_media_keys.PassAs<media::MediaKeys>();
#else
diff --git a/chromium/content/renderer/media/crypto/content_decryption_module_factory.h b/chromium/content/renderer/media/crypto/content_decryption_module_factory.h
index 01ab731e064..87623ca0785 100644
--- a/chromium/content/renderer/media/crypto/content_decryption_module_factory.h
+++ b/chromium/content/renderer/media/crypto/content_decryption_module_factory.h
@@ -13,7 +13,7 @@
class GURL;
#if defined(ENABLE_PEPPER_CDMS)
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebMediaPlayerClient;
}
@@ -21,7 +21,7 @@ class WebMediaPlayerClient;
namespace content {
-class WebMediaPlayerProxyAndroid;
+class RendererMediaPlayerManager;
class ContentDecryptionModuleFactory {
public:
@@ -29,22 +29,24 @@ class ContentDecryptionModuleFactory {
const std::string& key_system,
#if defined(ENABLE_PEPPER_CDMS)
// TODO(ddorwin): We need different pointers for the WD API.
- WebKit::WebMediaPlayerClient* web_media_player_client,
- WebKit::WebFrame* web_frame,
+ blink::WebMediaPlayerClient* web_media_player_client,
+ blink::WebFrame* web_frame,
const base::Closure& destroy_plugin_cb,
#elif defined(OS_ANDROID)
- WebMediaPlayerProxyAndroid* proxy,
+ RendererMediaPlayerManager* manager,
int media_keys_id,
const GURL& frame_url,
#endif // defined(ENABLE_PEPPER_CDMS)
- const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb);
+ const media::SessionCreatedCB& session_created_cb,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb);
#if defined(ENABLE_PEPPER_CDMS)
static void DestroyHelperPlugin(
- WebKit::WebMediaPlayerClient* web_media_player_client,
- WebKit::WebFrame* web_frame);
+ blink::WebMediaPlayerClient* web_media_player_client,
+ blink::WebFrame* web_frame);
#endif // defined(ENABLE_PEPPER_CDMS)
};
diff --git a/chromium/content/renderer/media/crypto/key_systems.cc b/chromium/content/renderer/media/crypto/key_systems.cc
index 4ce61227050..41025337a03 100644
--- a/chromium/content/renderer/media/crypto/key_systems.cc
+++ b/chromium/content/renderer/media/crypto/key_systems.cc
@@ -5,6 +5,7 @@
#include "content/renderer/media/crypto/key_systems.h"
#include <map>
+#include <string>
#include "base/lazy_instance.h"
#include "base/logging.h"
@@ -12,32 +13,51 @@
#include "content/public/common/content_client.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/key_system_info.h"
-#include "content/renderer/media/crypto/key_systems_info.h"
+#include "content/renderer/media/crypto/key_systems_support_uma.h"
#include "net/base/mime_util.h"
#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
+
namespace content {
+const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey";
+
+const char kAudioWebM[] = "audio/webm";
+const char kVideoWebM[] = "video/webm";
+const char kVorbis[] = "vorbis";
+const char kVorbisVP8[] = "vorbis,vp8,vp8.0";
+
+#if defined(USE_PROPRIETARY_CODECS)
+const char kAudioMp4[] = "audio/mp4";
+const char kVideoMp4[] = "video/mp4";
+const char kMp4a[] = "mp4a";
+const char kMp4aAvc1Avc3[] = "mp4a,avc1,avc3";
+#endif // defined(USE_PROPRIETARY_CODECS)
+
+#if !defined(GOOGLE_TV)
+inline std::string KeySystemNameForUMAInternal(
+ const blink::WebString& key_system) {
+ if (key_system == kClearKeyKeySystem)
+ return "ClearKey";
+#if defined(WIDEVINE_CDM_AVAILABLE)
+ if (key_system == kWidevineKeySystem)
+ return "Widevine";
+#endif // WIDEVINE_CDM_AVAILABLE
+ return "Unknown";
+}
+#else
+// Declares the function, which is defined in another file.
+std::string KeySystemNameForUMAInternal(const blink::WebString& key_system);
+#endif // !defined(GOOGLE_TV)
+
// Convert a WebString to ASCII, falling back on an empty string in the case
// of a non-ASCII string.
-static std::string ToASCIIOrEmpty(const WebKit::WebString& string) {
+static std::string ToASCIIOrEmpty(const blink::WebString& string) {
return IsStringASCII(string) ? UTF16ToASCII(string) : std::string();
}
-static const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey";
-
-static const char kAudioWebM[] = "audio/webm";
-static const char kVideoWebM[] = "video/webm";
-static const char kVorbis[] = "vorbis";
-static const char kVorbisVP8[] = "vorbis,vp8,vp8.0";
-
-static const char kAudioMp4[] = "audio/mp4";
-static const char kVideoMp4[] = "video/mp4";
-static const char kMp4a[] = "mp4a";
-static const char kAvc1[] = "avc1";
-static const char kMp4aAvc1[] = "mp4a,avc1";
-
static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) {
KeySystemInfo info(kClearKeyKeySystem);
@@ -45,7 +65,7 @@ static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) {
info.supported_types.push_back(std::make_pair(kVideoWebM, kVorbisVP8));
#if defined(USE_PROPRIETARY_CODECS)
info.supported_types.push_back(std::make_pair(kAudioMp4, kMp4a));
- info.supported_types.push_back(std::make_pair(kVideoMp4, kMp4aAvc1));
+ info.supported_types.push_back(std::make_pair(kVideoMp4, kMp4aAvc1Avc3));
#endif // defined(USE_PROPRIETARY_CODECS)
info.use_aes_decryptor = true;
@@ -116,10 +136,9 @@ class KeySystems {
const std::string& codecs_list,
KeySystemProperties* properties);
- bool IsSupportedKeySystemWithContainerAndCodec(
- const std::string& mime_type,
- const std::string& codec,
- const std::string& key_system);
+ bool IsSupportedKeySystemWithContainerAndCodec(const std::string& mime_type,
+ const std::string& codec,
+ const std::string& key_system);
// Map from key system string to capabilities.
KeySystemPropertiesMap concrete_key_system_map_;
@@ -128,6 +147,8 @@ class KeySystems {
// to represent its capabilities.
ParentKeySystemMap parent_key_system_map_;
+ KeySystemsSupportUMA key_systems_support_uma_;
+
DISALLOW_COPY_AND_ASSIGN(KeySystems);
};
@@ -145,6 +166,9 @@ KeySystems::KeySystems() {
// Clear Key is always supported.
AddClearKey(&key_systems_info);
AddConcreteSupportedKeySystems(key_systems_info);
+#if defined(WIDEVINE_CDM_AVAILABLE)
+ key_systems_support_uma_.AddKeySystemToReport(kWidevineKeySystem);
+#endif // defined(WIDEVINE_CDM_AVAILABLE)
}
void KeySystems::AddConcreteSupportedKeySystems(
@@ -216,8 +240,6 @@ void KeySystems::AddSupportedType(const std::string& mime_type,
net::ParseCodecString(codecs_list, &mime_type_codecs, false);
CodecSet codecs(mime_type_codecs.begin(), mime_type_codecs.end());
- // Support the MIME type string alone, without codec(s) specified.
- codecs.insert(std::string());
MimeTypeMap& mime_types_map = properties->types;
// mime_types_map must not be repeated for a given key system.
@@ -234,18 +256,37 @@ bool KeySystems::IsSupportedKeySystemWithContainerAndCodec(
const std::string& mime_type,
const std::string& codec,
const std::string& key_system) {
+ bool has_type = !mime_type.empty();
+ DCHECK(has_type || codec.empty());
+
+ key_systems_support_uma_.ReportKeySystemQuery(key_system, has_type);
+
KeySystemPropertiesMap::const_iterator key_system_iter =
concrete_key_system_map_.find(key_system);
if (key_system_iter == concrete_key_system_map_.end())
return false;
+ key_systems_support_uma_.ReportKeySystemSupport(key_system, false);
+
+ if (mime_type.empty())
+ return true;
+
const MimeTypeMap& mime_types_map = key_system_iter->second.types;
MimeTypeMap::const_iterator mime_iter = mime_types_map.find(mime_type);
if (mime_iter == mime_types_map.end())
return false;
+ if (codec.empty()) {
+ key_systems_support_uma_.ReportKeySystemSupport(key_system, true);
+ return true;
+ }
+
const CodecSet& codecs = mime_iter->second;
- return (codecs.find(codec) != codecs.end());
+ if (codecs.find(codec) == codecs.end())
+ return false;
+
+ key_systems_support_uma_.ReportKeySystemSupport(key_system, true);
+ return true;
}
bool KeySystems::IsSupportedKeySystemWithMediaMimeType(
@@ -262,11 +303,6 @@ bool KeySystems::IsSupportedKeySystemWithMediaMimeType(
else
concrete_key_system = key_system;
- // This method is only used by the canPlaytType() path (not the EME methods),
- // so we check for suppressed key_systems here.
- if(IsCanPlayTypeSuppressed(concrete_key_system))
- return false;
-
if (codecs.empty()) {
return IsSupportedKeySystemWithContainerAndCodec(
mime_type, std::string(), concrete_key_system);
@@ -274,7 +310,7 @@ bool KeySystems::IsSupportedKeySystemWithMediaMimeType(
for (size_t i = 0; i < codecs.size(); ++i) {
if (!IsSupportedKeySystemWithContainerAndCodec(
- mime_type, codecs[i], concrete_key_system)) {
+ mime_type, codecs[i], concrete_key_system)) {
return false;
}
}
@@ -321,7 +357,7 @@ std::vector<uint8> KeySystems::GetUUID(const std::string& concrete_key_system) {
//------------------------------------------------------------------------------
-bool IsConcreteSupportedKeySystem(const WebKit::WebString& key_system) {
+bool IsConcreteSupportedKeySystem(const blink::WebString& key_system) {
return KeySystems::GetInstance().IsConcreteSupportedKeySystem(
ToASCIIOrEmpty(key_system));
}
@@ -334,10 +370,14 @@ bool IsSupportedKeySystemWithMediaMimeType(
mime_type, codecs, key_system);
}
-std::string KeySystemNameForUMA(const WebKit::WebString& key_system) {
+std::string KeySystemNameForUMA(const blink::WebString& key_system) {
return KeySystemNameForUMAInternal(key_system);
}
+std::string KeySystemNameForUMA(const std::string& key_system) {
+ return KeySystemNameForUMAInternal(blink::WebString::fromUTF8(key_system));
+}
+
bool CanUseAesDecryptor(const std::string& concrete_key_system) {
return KeySystems::GetInstance().UseAesDecryptor(concrete_key_system);
}
diff --git a/chromium/content/renderer/media/crypto/key_systems.h b/chromium/content/renderer/media/crypto/key_systems.h
index 47dc06a93db..2f4cb101b09 100644
--- a/chromium/content/renderer/media/crypto/key_systems.h
+++ b/chromium/content/renderer/media/crypto/key_systems.h
@@ -11,7 +11,7 @@
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
-namespace WebKit {
+namespace blink {
class WebString;
}
@@ -24,7 +24,7 @@ namespace content {
// |key_system| supports a specific type of media or to check parent key
// systems.
CONTENT_EXPORT bool IsConcreteSupportedKeySystem(
- const WebKit::WebString& key_system);
+ const blink::WebString& key_system);
// Returns whether |key_sytem| supports the specified media type and codec(s).
CONTENT_EXPORT bool IsSupportedKeySystemWithMediaMimeType(
@@ -34,7 +34,8 @@ CONTENT_EXPORT bool IsSupportedKeySystemWithMediaMimeType(
// Returns a name for |key_system| suitable to UMA logging.
CONTENT_EXPORT std::string KeySystemNameForUMA(
- const WebKit::WebString& key_system);
+ const blink::WebString& key_system);
+CONTENT_EXPORT std::string KeySystemNameForUMA(const std::string& key_system);
// Returns whether AesDecryptor can be used for the given |concrete_key_system|.
CONTENT_EXPORT bool CanUseAesDecryptor(const std::string& concrete_key_system);
diff --git a/chromium/content/renderer/media/crypto/key_systems_info.cc b/chromium/content/renderer/media/crypto/key_systems_info.cc
deleted file mode 100644
index 22bc7181b24..00000000000
--- a/chromium/content/renderer/media/crypto/key_systems_info.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/crypto/key_systems_info.h"
-
-#include "third_party/WebKit/public/platform/WebString.h"
-
-#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
-
-// The following must be after widevine_cdm_version.h.
-
-#if defined(DISABLE_WIDEVINE_CDM_CANPLAYTYPE)
-#include "base/command_line.h"
-#include "media/base/media_switches.h"
-#endif
-
-namespace content {
-
-static const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey";
-
-bool IsCanPlayTypeSuppressed(const std::string& key_system) {
-#if defined(DISABLE_WIDEVINE_CDM_CANPLAYTYPE)
- // See http://crbug.com/237627.
- if (key_system == kWidevineKeySystem &&
- !CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kOverrideEncryptedMediaCanPlayType))
- return true;
-#endif
- return false;
-}
-
-std::string KeySystemNameForUMAInternal(const WebKit::WebString& key_system) {
- if (key_system == kClearKeyKeySystem)
- return "ClearKey";
-#if defined(WIDEVINE_CDM_AVAILABLE)
- if (key_system == kWidevineKeySystem)
- return "Widevine";
-#endif // WIDEVINE_CDM_AVAILABLE
- return "Unknown";
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/crypto/key_systems_info.h b/chromium/content/renderer/media/crypto/key_systems_info.h
deleted file mode 100644
index e2fe128872c..00000000000
--- a/chromium/content/renderer/media/crypto/key_systems_info.h
+++ /dev/null
@@ -1,27 +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_MEDIA_CRYPTO_KEY_SYSTEMS_INFO_H_
-#define CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_INFO_H_
-
-#include <string>
-
-namespace WebKit {
-class WebString;
-}
-
-namespace content {
-
-// Returns true if canPlayType should return an empty string for |key_system|.
-bool IsCanPlayTypeSuppressed(const std::string& key_system);
-
-// Returns the name that UMA will use for the given |key_system|.
-// This function can be called frequently. Hence this function should be
-// implemented not to impact performance and does not rely on the main
-// key system map.
-std::string KeySystemNameForUMAInternal(const WebKit::WebString& key_system);
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_INFO_H_
diff --git a/chromium/content/renderer/media/crypto/key_systems_support_uma.cc b/chromium/content/renderer/media/crypto/key_systems_support_uma.cc
new file mode 100644
index 00000000000..f1d77bd677b
--- /dev/null
+++ b/chromium/content/renderer/media/crypto/key_systems_support_uma.cc
@@ -0,0 +1,125 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/crypto/key_systems_support_uma.h"
+
+#include <string>
+
+#include "content/public/renderer/render_thread.h"
+#include "content/renderer/media/crypto/key_systems.h"
+
+namespace content {
+
+namespace {
+
+const char kKeySystemSupportActionPrefix[] = "KeySystemSupport.";
+
+// Reports an event only once.
+class OneTimeReporter {
+ public:
+ OneTimeReporter(const std::string& key_system,
+ bool has_type,
+ const std::string& event);
+ ~OneTimeReporter();
+
+ void Report();
+
+ private:
+ bool is_reported_;
+ std::string action_;
+};
+
+OneTimeReporter::OneTimeReporter(const std::string& key_system,
+ bool has_type,
+ const std::string& event)
+ : is_reported_(false) {
+ action_ = kKeySystemSupportActionPrefix + KeySystemNameForUMA(key_system);
+ if (has_type)
+ action_ += "WithType";
+ action_ += '.' + event;
+}
+
+OneTimeReporter::~OneTimeReporter() {}
+
+void OneTimeReporter::Report() {
+ if (is_reported_)
+ return;
+ RenderThread::Get()->RecordComputedAction(action_);
+ is_reported_ = true;
+}
+
+} // namespace
+
+class KeySystemsSupportUMA::Reporter {
+ public:
+ explicit Reporter(const std::string& key_system);
+ ~Reporter();
+
+ void Report(bool has_type, bool is_supported);
+
+ private:
+ const std::string key_system_;
+
+ OneTimeReporter call_reporter_;
+ OneTimeReporter call_with_type_reporter_;
+ OneTimeReporter support_reporter_;
+ OneTimeReporter support_with_type_reporter_;
+};
+
+KeySystemsSupportUMA::Reporter::Reporter(const std::string& key_system)
+ : key_system_(key_system),
+ call_reporter_(key_system, false, "Queried"),
+ call_with_type_reporter_(key_system, true, "Queried"),
+ support_reporter_(key_system, false, "Supported"),
+ support_with_type_reporter_(key_system, true, "Supported") {}
+
+KeySystemsSupportUMA::Reporter::~Reporter() {}
+
+void KeySystemsSupportUMA::Reporter::Report(bool has_type, bool is_supported) {
+ call_reporter_.Report();
+ if (has_type)
+ call_with_type_reporter_.Report();
+
+ if (!is_supported)
+ return;
+
+ support_reporter_.Report();
+ if (has_type)
+ support_with_type_reporter_.Report();
+}
+
+KeySystemsSupportUMA::KeySystemsSupportUMA() {}
+
+KeySystemsSupportUMA::~KeySystemsSupportUMA() {}
+
+void KeySystemsSupportUMA::AddKeySystemToReport(const std::string& key_system) {
+ DCHECK(!GetReporter(key_system));
+ reporters_.set(key_system, scoped_ptr<Reporter>(new Reporter(key_system)));
+}
+
+void KeySystemsSupportUMA::ReportKeySystemQuery(const std::string& key_system,
+ bool has_type) {
+ Reporter* reporter = GetReporter(key_system);
+ if (!reporter)
+ return;
+ reporter->Report(has_type, false);
+}
+
+void KeySystemsSupportUMA::ReportKeySystemSupport(const std::string& key_system,
+ bool has_type) {
+ Reporter* reporter = GetReporter(key_system);
+ if (!reporter)
+ return;
+ reporter->Report(has_type, true);
+}
+
+KeySystemsSupportUMA::Reporter* KeySystemsSupportUMA::GetReporter(
+ const std::string& key_system) {
+ Reporters::iterator reporter = reporters_.find(key_system);
+ if (reporter == reporters_.end())
+ return NULL;
+ return reporter->second;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/crypto/key_systems_support_uma.h b/chromium/content/renderer/media/crypto/key_systems_support_uma.h
new file mode 100644
index 00000000000..95e1b02bcd4
--- /dev/null
+++ b/chromium/content/renderer/media/crypto/key_systems_support_uma.h
@@ -0,0 +1,57 @@
+// 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_MEDIA_CRYPTO_KEY_SYSTEMS_SUPPORT_UMA_H_
+#define CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_SUPPORT_UMA_H_
+
+#include <string>
+
+#include "base/containers/scoped_ptr_hash_map.h"
+
+namespace content {
+
+// Key system support UMA statistics for queried key systems.
+// 1. The key system is queried (with or without a MIME type).
+// 2. The key system is queried with a MIME type.
+// 3. The queried key system is supported (with or without a MIME type). This is
+// reported when the key system is supported when queried, regardless of
+// whether a MIME type is specified.
+// 4. The queried key system is supported with a MIME type. This is reported
+// when the key system is supported when queried without a MIME type
+// specified.
+// Note: All 4 stats are only reported once per renderer process per key system.
+class KeySystemsSupportUMA {
+ public:
+ KeySystemsSupportUMA();
+ ~KeySystemsSupportUMA();
+
+ // Adds a |key_system| for which query/support statistics are reported.
+ // If you use this function to add key system to report, make sure to update
+ // AddKeySystemSupportActions() in tools/metrics/actions/extract_actions.py.
+ void AddKeySystemToReport(const std::string& key_system);
+
+ // Reports that the |key_system| is queried. When |has_type|, also reports
+ // that the |key_system| with a MIME type is queried.
+ void ReportKeySystemQuery(const std::string& key_system, bool has_type);
+
+ // Reports that the queried |key_system| is supported. When |has_type| (a
+ // a MIME type is specified in the query), also reports that the queried
+ // |key_system| is supported with that MIME type.
+ void ReportKeySystemSupport(const std::string& key_system, bool has_type);
+
+ private:
+ class Reporter;
+
+ // Returns the Reporter for |key_system|. Returns NULL if |key_system| was not
+ // added for UMA reporting.
+ Reporter* GetReporter(const std::string& key_system);
+
+ // Key system <-> Reporter map.
+ typedef base::ScopedPtrHashMap<std::string, Reporter> Reporters;
+ Reporters reporters_;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_SUPPORT_UMA_H_
diff --git a/chromium/content/renderer/media/crypto/key_systems_unittest.cc b/chromium/content/renderer/media/crypto/key_systems_unittest.cc
index 624b811519e..89fa51ab19a 100644
--- a/chromium/content/renderer/media/crypto/key_systems_unittest.cc
+++ b/chromium/content/renderer/media/crypto/key_systems_unittest.cc
@@ -33,7 +33,7 @@
#endif // defined(NDEBUG)
#endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
-using WebKit::WebString;
+using blink::WebString;
// These are the (fake) key systems that are registered for these tests.
// kUsesAes uses the AesDecryptor like Clear Key.
@@ -355,8 +355,7 @@ TEST_F(KeySystemsTest, IsSupportedKeySystem_InvalidVariants) {
}
TEST_F(KeySystemsTest, IsSupportedKeySystemWithMediaMimeType_NoType) {
- // These two should be true. See http://crbug.com/164303.
- EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType(
+ EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType(
std::string(), no_codecs(), kUsesAes));
EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType(
std::string(), no_codecs(), kUsesAesParent));
diff --git a/chromium/content/renderer/media/crypto/ppapi_decryptor.cc b/chromium/content/renderer/media/crypto/ppapi_decryptor.cc
index 80f8149e315..aff94a240e5 100644
--- a/chromium/content/renderer/media/crypto/ppapi_decryptor.cc
+++ b/chromium/content/renderer/media/crypto/ppapi_decryptor.cc
@@ -25,9 +25,11 @@ namespace content {
scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create(
const std::string& key_system,
const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance,
- const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb,
+ const media::SessionCreatedCB& session_created_cb,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb,
const base::Closure& destroy_plugin_cb) {
ContentDecryptorDelegate* plugin_cdm_delegate =
plugin_instance->GetContentDecryptorDelegate();
@@ -36,41 +38,53 @@ scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create(
return scoped_ptr<PpapiDecryptor>();
}
- // TODO(jrummell): How do we get the can_challenge_platform value from
- // the browser?
- const bool can_challenge_platform = false;
- plugin_cdm_delegate->Initialize(key_system, can_challenge_platform);
+ plugin_cdm_delegate->Initialize(key_system);
return scoped_ptr<PpapiDecryptor>(new PpapiDecryptor(plugin_instance,
plugin_cdm_delegate,
- key_added_cb,
- key_error_cb,
- key_message_cb,
+ session_created_cb,
+ session_message_cb,
+ session_ready_cb,
+ session_closed_cb,
+ session_error_cb,
destroy_plugin_cb));
}
PpapiDecryptor::PpapiDecryptor(
const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance,
ContentDecryptorDelegate* plugin_cdm_delegate,
- const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb,
+ const media::SessionCreatedCB& session_created_cb,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb,
const base::Closure& destroy_plugin_cb)
: plugin_instance_(plugin_instance),
plugin_cdm_delegate_(plugin_cdm_delegate),
- key_added_cb_(key_added_cb),
- key_error_cb_(key_error_cb),
- key_message_cb_(key_message_cb),
+ session_created_cb_(session_created_cb),
+ session_message_cb_(session_message_cb),
+ session_ready_cb_(session_ready_cb),
+ session_closed_cb_(session_closed_cb),
+ session_error_cb_(session_error_cb),
destroy_plugin_cb_(destroy_plugin_cb),
render_loop_proxy_(base::MessageLoopProxy::current()),
- weak_ptr_factory_(this),
- weak_this_(weak_ptr_factory_.GetWeakPtr()) {
+ weak_ptr_factory_(this) {
DCHECK(plugin_instance_.get());
-
- plugin_cdm_delegate_->SetKeyEventCallbacks(
- base::Bind(&PpapiDecryptor::KeyAdded, weak_this_),
- base::Bind(&PpapiDecryptor::KeyError, weak_this_),
- base::Bind(&PpapiDecryptor::KeyMessage, weak_this_));
+ DCHECK(!session_created_cb_.is_null());
+ DCHECK(!session_message_cb_.is_null());
+ DCHECK(!session_ready_cb_.is_null());
+ DCHECK(!session_closed_cb_.is_null());
+ DCHECK(!session_error_cb_.is_null());
+ DCHECK(!destroy_plugin_cb_.is_null());
+
+ weak_this_ = weak_ptr_factory_.GetWeakPtr();
+
+ plugin_cdm_delegate_->SetSessionEventCallbacks(
+ base::Bind(&PpapiDecryptor::OnSessionCreated, weak_this_),
+ base::Bind(&PpapiDecryptor::OnSessionMessage, weak_this_),
+ base::Bind(&PpapiDecryptor::OnSessionReady, weak_this_),
+ base::Bind(&PpapiDecryptor::OnSessionClosed, weak_this_),
+ base::Bind(&PpapiDecryptor::OnSessionError, weak_this_));
}
PpapiDecryptor::~PpapiDecryptor() {
@@ -79,34 +93,32 @@ PpapiDecryptor::~PpapiDecryptor() {
destroy_plugin_cb_.Run();
}
-bool PpapiDecryptor::GenerateKeyRequest(const std::string& type,
- const uint8* init_data,
- int init_data_length) {
- DVLOG(2) << "GenerateKeyRequest()";
+bool PpapiDecryptor::CreateSession(uint32 session_id,
+ const std::string& type,
+ const uint8* init_data,
+ int init_data_length) {
+ DVLOG(2) << __FUNCTION__;
DCHECK(render_loop_proxy_->BelongsToCurrentThread());
DCHECK(plugin_cdm_delegate_);
- if (!plugin_cdm_delegate_->GenerateKeyRequest(
- type, init_data, init_data_length)) {
- ReportFailureToCallPlugin(std::string());
+ if (!plugin_cdm_delegate_->CreateSession(
+ session_id, type, init_data, init_data_length)) {
+ ReportFailureToCallPlugin(session_id);
return false;
}
return true;
}
-void PpapiDecryptor::AddKey(const uint8* key,
- int key_length,
- const uint8* init_data,
- int init_data_length,
- const std::string& session_id) {
- DVLOG(2) << "AddKey()";
+void PpapiDecryptor::UpdateSession(uint32 session_id,
+ const uint8* response,
+ int response_length) {
+ DVLOG(2) << __FUNCTION__;
DCHECK(render_loop_proxy_->BelongsToCurrentThread());
- if (!plugin_cdm_delegate_->AddKey(
- session_id, key, key_length, init_data, init_data_length)) {
+ if (!plugin_cdm_delegate_->UpdateSession(
+ session_id, response, response_length))
ReportFailureToCallPlugin(session_id);
- }
if (!new_audio_key_cb_.is_null())
new_audio_key_cb_.Run();
@@ -115,11 +127,11 @@ void PpapiDecryptor::AddKey(const uint8* key,
new_video_key_cb_.Run();
}
-void PpapiDecryptor::CancelKeyRequest(const std::string& session_id) {
- DVLOG(2) << "CancelKeyRequest()";
+void PpapiDecryptor::ReleaseSession(uint32 session_id) {
+ DVLOG(2) << __FUNCTION__;
DCHECK(render_loop_proxy_->BelongsToCurrentThread());
- if (!plugin_cdm_delegate_->CancelKeyRequest(session_id))
+ if (!plugin_cdm_delegate_->ReleaseSession(session_id))
ReportFailureToCallPlugin(session_id);
}
@@ -140,6 +152,14 @@ media::Decryptor* PpapiDecryptor::GetDecryptor() {
void PpapiDecryptor::RegisterNewKeyCB(StreamType stream_type,
const NewKeyCB& new_key_cb) {
+ if (!render_loop_proxy_->BelongsToCurrentThread()) {
+ render_loop_proxy_->PostTask(FROM_HERE, base::Bind(
+ &PpapiDecryptor::RegisterNewKeyCB, weak_this_, stream_type,
+ new_key_cb));
+ return;
+ }
+
+ DVLOG(3) << __FUNCTION__ << " - stream_type: " << stream_type;
switch (stream_type) {
case kAudio:
new_audio_key_cb_ = new_key_cb;
@@ -163,13 +183,19 @@ void PpapiDecryptor::Decrypt(
return;
}
- DVLOG(3) << "Decrypt() - stream_type: " << stream_type;
+ DVLOG(3) << __FUNCTION__ << " - stream_type: " << stream_type;
if (!plugin_cdm_delegate_->Decrypt(stream_type, encrypted, decrypt_cb))
decrypt_cb.Run(kError, NULL);
}
void PpapiDecryptor::CancelDecrypt(StreamType stream_type) {
- DVLOG(1) << "CancelDecrypt() - stream_type: " << stream_type;
+ if (!render_loop_proxy_->BelongsToCurrentThread()) {
+ render_loop_proxy_->PostTask(FROM_HERE, base::Bind(
+ &PpapiDecryptor::CancelDecrypt, weak_this_, stream_type));
+ return;
+ }
+
+ DVLOG(1) << __FUNCTION__ << " - stream_type: " << stream_type;
plugin_cdm_delegate_->CancelDecrypt(stream_type);
}
@@ -182,7 +208,7 @@ void PpapiDecryptor::InitializeAudioDecoder(
return;
}
- DVLOG(2) << "InitializeAudioDecoder()";
+ DVLOG(2) << __FUNCTION__;
DCHECK(config.is_encrypted());
DCHECK(config.IsValidConfig());
@@ -203,7 +229,7 @@ void PpapiDecryptor::InitializeVideoDecoder(
return;
}
- DVLOG(2) << "InitializeVideoDecoder()";
+ DVLOG(2) << __FUNCTION__;
DCHECK(config.is_encrypted());
DCHECK(config.IsValidConfig());
@@ -225,7 +251,7 @@ void PpapiDecryptor::DecryptAndDecodeAudio(
return;
}
- DVLOG(3) << "DecryptAndDecodeAudio()";
+ DVLOG(3) << __FUNCTION__;
if (!plugin_cdm_delegate_->DecryptAndDecodeAudio(encrypted, audio_decode_cb))
audio_decode_cb.Run(kError, AudioBuffers());
}
@@ -240,7 +266,7 @@ void PpapiDecryptor::DecryptAndDecodeVideo(
return;
}
- DVLOG(3) << "DecryptAndDecodeVideo()";
+ DVLOG(3) << __FUNCTION__;
if (!plugin_cdm_delegate_->DecryptAndDecodeVideo(encrypted, video_decode_cb))
video_decode_cb.Run(kError, NULL);
}
@@ -252,7 +278,7 @@ void PpapiDecryptor::ResetDecoder(StreamType stream_type) {
return;
}
- DVLOG(2) << "ResetDecoder() - stream_type: " << stream_type;
+ DVLOG(2) << __FUNCTION__ << " - stream_type: " << stream_type;
plugin_cdm_delegate_->ResetDecoder(stream_type);
}
@@ -263,17 +289,19 @@ void PpapiDecryptor::DeinitializeDecoder(StreamType stream_type) {
return;
}
- DVLOG(2) << "DeinitializeDecoder() - stream_type: " << stream_type;
+ DVLOG(2) << __FUNCTION__ << " - stream_type: " << stream_type;
plugin_cdm_delegate_->DeinitializeDecoder(stream_type);
}
-void PpapiDecryptor::ReportFailureToCallPlugin(const std::string& session_id) {
+void PpapiDecryptor::ReportFailureToCallPlugin(uint32 session_id) {
+ DCHECK(render_loop_proxy_->BelongsToCurrentThread());
DVLOG(1) << "Failed to call plugin.";
- key_error_cb_.Run(session_id, kUnknownError, 0);
+ session_error_cb_.Run(session_id, kUnknownError, 0);
}
void PpapiDecryptor::OnDecoderInitialized(StreamType stream_type,
bool success) {
+ DCHECK(render_loop_proxy_->BelongsToCurrentThread());
switch (stream_type) {
case kAudio:
DCHECK(!audio_decoder_init_cb_.is_null());
@@ -288,23 +316,34 @@ void PpapiDecryptor::OnDecoderInitialized(StreamType stream_type,
}
}
-void PpapiDecryptor::KeyAdded(const std::string& session_id) {
+void PpapiDecryptor::OnSessionCreated(uint32 session_id,
+ const std::string& web_session_id) {
+ DCHECK(render_loop_proxy_->BelongsToCurrentThread());
+ session_created_cb_.Run(session_id, web_session_id);
+}
+
+void PpapiDecryptor::OnSessionMessage(uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url) {
+ DCHECK(render_loop_proxy_->BelongsToCurrentThread());
+ session_message_cb_.Run(session_id, message, destination_url);
+}
+
+void PpapiDecryptor::OnSessionReady(uint32 session_id) {
DCHECK(render_loop_proxy_->BelongsToCurrentThread());
- key_added_cb_.Run(session_id);
+ session_ready_cb_.Run(session_id);
}
-void PpapiDecryptor::KeyError(const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- int system_code) {
+void PpapiDecryptor::OnSessionClosed(uint32 session_id) {
DCHECK(render_loop_proxy_->BelongsToCurrentThread());
- key_error_cb_.Run(session_id, error_code, system_code);
+ session_closed_cb_.Run(session_id);
}
-void PpapiDecryptor::KeyMessage(const std::string& session_id,
- const std::vector<uint8>& message,
- const std::string& default_url) {
+void PpapiDecryptor::OnSessionError(uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code) {
DCHECK(render_loop_proxy_->BelongsToCurrentThread());
- key_message_cb_.Run(session_id, message, default_url);
+ session_error_cb_.Run(session_id, error_code, system_code);
}
} // namespace content
diff --git a/chromium/content/renderer/media/crypto/ppapi_decryptor.h b/chromium/content/renderer/media/crypto/ppapi_decryptor.h
index 327ecc6bc47..95c5f74a4c3 100644
--- a/chromium/content/renderer/media/crypto/ppapi_decryptor.h
+++ b/chromium/content/renderer/media/crypto/ppapi_decryptor.h
@@ -23,8 +23,8 @@ namespace content {
class ContentDecryptorDelegate;
class PepperPluginInstanceImpl;
-// PpapiDecryptor implements media::Decryptor and forwards all calls to the
-// PluginInstance.
+// PpapiDecryptor implements media::MediaKeys and media::Decryptor and forwards
+// all calls to the PluginInstance.
// This class should always be created & destroyed on the main renderer thread.
class PpapiDecryptor : public media::MediaKeys, public media::Decryptor {
public:
@@ -32,21 +32,24 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor {
// TODO(ddorwin): Remove after updating the delegate.
const std::string& key_system,
const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance,
- const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb,
+ const media::SessionCreatedCB& session_created_cb,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb,
const base::Closure& destroy_plugin_cb);
virtual ~PpapiDecryptor();
// media::MediaKeys implementation.
- virtual bool GenerateKeyRequest(const std::string& type,
- const uint8* init_data,
- int init_data_length) OVERRIDE;
- virtual void AddKey(const uint8* key, int key_length,
- const uint8* init_data, int init_data_length,
- const std::string& session_id) OVERRIDE;
- virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE;
+ virtual bool CreateSession(uint32 session_id,
+ const std::string& type,
+ const uint8* init_data,
+ int init_data_length) OVERRIDE;
+ virtual void UpdateSession(uint32 session_id,
+ const uint8* response,
+ int response_length) OVERRIDE;
+ virtual void ReleaseSession(uint32 session_id) OVERRIDE;
virtual Decryptor* GetDecryptor() OVERRIDE;
// media::Decryptor implementation.
@@ -70,26 +73,31 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor {
virtual void DeinitializeDecoder(StreamType stream_type) OVERRIDE;
private:
- PpapiDecryptor(
- const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance,
- ContentDecryptorDelegate* plugin_cdm_delegate,
- const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb,
- const base::Closure& destroy_plugin_cb);
+ PpapiDecryptor(const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance,
+ ContentDecryptorDelegate* plugin_cdm_delegate,
+ const media::SessionCreatedCB& session_created_cb,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb,
+ const base::Closure& destroy_plugin_cb);
- void ReportFailureToCallPlugin(const std::string& session_id);
+ void ReportFailureToCallPlugin(uint32 session_id);
void OnDecoderInitialized(StreamType stream_type, bool success);
- // Callbacks for |plugin_cdm_delegate_| to fire key events.
- void KeyAdded(const std::string& session_id);
- void KeyError(const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- int system_code);
- void KeyMessage(const std::string& session_id,
- const std::vector<uint8>& message,
- const std::string& default_url);
+ // Callbacks for |plugin_cdm_delegate_| to fire session events.
+ void OnSessionCreated(uint32 session_id, const std::string& web_session_id);
+ void OnSessionMessage(uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url);
+ void OnSessionReady(uint32 session_id);
+ void OnSessionClosed(uint32 session_id);
+ void OnSessionError(uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code);
+
+ base::WeakPtr<PpapiDecryptor> weak_this_;
// Hold a reference of the plugin instance to make sure the plugin outlives
// the |plugin_cdm_delegate_|. This is needed because |plugin_cdm_delegate_|
@@ -98,10 +106,12 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor {
ContentDecryptorDelegate* plugin_cdm_delegate_;
- // Callbacks for firing key events.
- media::KeyAddedCB key_added_cb_;
- media::KeyErrorCB key_error_cb_;
- media::KeyMessageCB key_message_cb_;
+ // Callbacks for firing session events.
+ media::SessionCreatedCB session_created_cb_;
+ media::SessionMessageCB session_message_cb_;
+ media::SessionReadyCB session_ready_cb_;
+ media::SessionClosedCB session_closed_cb_;
+ media::SessionErrorCB session_error_cb_;
// Called to destroy the helper plugin when this class no longer needs it.
base::Closure destroy_plugin_cb_;
@@ -114,7 +124,6 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor {
NewKeyCB new_video_key_cb_;
base::WeakPtrFactory<PpapiDecryptor> weak_ptr_factory_;
- base::WeakPtr<PpapiDecryptor> weak_this_;
DISALLOW_COPY_AND_ASSIGN(PpapiDecryptor);
};
diff --git a/chromium/content/renderer/media/crypto/proxy_decryptor.cc b/chromium/content/renderer/media/crypto/proxy_decryptor.cc
index c50080f1c98..0016d19a7e8 100644
--- a/chromium/content/renderer/media/crypto/proxy_decryptor.cc
+++ b/chromium/content/renderer/media/crypto/proxy_decryptor.cc
@@ -7,10 +7,24 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
+#include "base/strings/string_util.h"
#include "content/renderer/media/crypto/content_decryption_module_factory.h"
+#if defined(OS_ANDROID)
+#include "content/renderer/media/android/renderer_media_player_manager.h"
+#endif // defined(OS_ANDROID)
+#include "media/cdm/json_web_key.h"
+#include "media/cdm/key_system_names.h"
namespace content {
+// Since these reference IDs may conflict with the ones generated in
+// WebContentDecryptionModuleSessionImpl for the short time both paths are
+// active, start with 100000 and generate the IDs from there.
+// TODO(jrummell): Only allow one path http://crbug.com/306680.
+uint32 ProxyDecryptor::next_session_id_ = 100000;
+
+const uint32 kInvalidSessionId = 0;
+
#if defined(ENABLE_PEPPER_CDMS)
void ProxyDecryptor::DestroyHelperPlugin() {
ContentDecryptionModuleFactory::DestroyHelperPlugin(
@@ -20,26 +34,30 @@ void ProxyDecryptor::DestroyHelperPlugin() {
ProxyDecryptor::ProxyDecryptor(
#if defined(ENABLE_PEPPER_CDMS)
- WebKit::WebMediaPlayerClient* web_media_player_client,
- WebKit::WebFrame* web_frame,
+ blink::WebMediaPlayerClient* web_media_player_client,
+ blink::WebFrame* web_frame,
#elif defined(OS_ANDROID)
- WebMediaPlayerProxyAndroid* proxy,
+ RendererMediaPlayerManager* manager,
int media_keys_id,
#endif // defined(ENABLE_PEPPER_CDMS)
- const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb)
+ const KeyAddedCB& key_added_cb,
+ const KeyErrorCB& key_error_cb,
+ const KeyMessageCB& key_message_cb)
: weak_ptr_factory_(this),
#if defined(ENABLE_PEPPER_CDMS)
web_media_player_client_(web_media_player_client),
web_frame_(web_frame),
#elif defined(OS_ANDROID)
- proxy_(proxy),
+ manager_(manager),
media_keys_id_(media_keys_id),
#endif // defined(ENABLE_PEPPER_CDMS)
key_added_cb_(key_added_cb),
key_error_cb_(key_error_cb),
- key_message_cb_(key_message_cb) {
+ key_message_cb_(key_message_cb),
+ is_clear_key_(false) {
+ DCHECK(!key_added_cb_.is_null());
+ DCHECK(!key_error_cb_.is_null());
+ DCHECK(!key_message_cb_.is_null());
}
ProxyDecryptor::~ProxyDecryptor() {
@@ -83,21 +101,28 @@ bool ProxyDecryptor::InitializeCDM(const std::string& key_system,
DCHECK(!media_keys_);
media_keys_ = CreateMediaKeys(key_system, frame_url);
+ if (!media_keys_)
+ return false;
- return media_keys_ != NULL;
+ if (!decryptor_ready_cb_.is_null())
+ base::ResetAndReturn(&decryptor_ready_cb_).Run(media_keys_->GetDecryptor());
+
+ is_clear_key_ =
+ media::IsClearKey(key_system) || media::IsExternalClearKey(key_system);
+ return true;
}
bool ProxyDecryptor::GenerateKeyRequest(const std::string& type,
const uint8* init_data,
int init_data_length) {
- if (!media_keys_->GenerateKeyRequest(type, init_data, init_data_length)) {
+ // Use a unique reference id for this request.
+ uint32 session_id = next_session_id_++;
+ if (!media_keys_->CreateSession(
+ session_id, type, init_data, init_data_length)) {
media_keys_.reset();
return false;
}
- if (!decryptor_ready_cb_.is_null())
- base::ResetAndReturn(&decryptor_ready_cb_).Run(media_keys_->GetDecryptor());
-
return true;
}
@@ -105,18 +130,58 @@ void ProxyDecryptor::AddKey(const uint8* key,
int key_length,
const uint8* init_data,
int init_data_length,
- const std::string& session_id) {
+ const std::string& web_session_id) {
DVLOG(1) << "AddKey()";
// WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
- media_keys_->AddKey(key, key_length, init_data, init_data_length, session_id);
+ uint32 session_id = LookupSessionId(web_session_id);
+ if (session_id == kInvalidSessionId) {
+ // Session hasn't been referenced before, so it is an error.
+ // Note that the specification says "If sessionId is not null and is
+ // unrecognized, throw an INVALID_ACCESS_ERR." However, for backwards
+ // compatibility the error is not thrown, but rather reported as a
+ // KeyError.
+ key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0);
+ return;
+ }
+
+ // EME WD spec only supports a single array passed to the CDM. For
+ // Clear Key using v0.1b, both arrays are used (|init_data| is key_id).
+ // Since the EME WD spec supports the key as a JSON Web Key,
+ // convert the 2 arrays to a JWK and pass it as the single array.
+ if (is_clear_key_) {
+ // Decryptor doesn't support empty key ID (see http://crbug.com/123265).
+ // So ensure a non-empty value is passed.
+ if (!init_data) {
+ static const uint8 kDummyInitData[1] = {0};
+ init_data = kDummyInitData;
+ init_data_length = arraysize(kDummyInitData);
+ }
+
+ std::string jwk =
+ media::GenerateJWKSet(key, key_length, init_data, init_data_length);
+ DCHECK(!jwk.empty());
+ media_keys_->UpdateSession(
+ session_id, reinterpret_cast<const uint8*>(jwk.data()), jwk.size());
+ return;
+ }
+
+ media_keys_->UpdateSession(session_id, key, key_length);
}
void ProxyDecryptor::CancelKeyRequest(const std::string& session_id) {
DVLOG(1) << "CancelKeyRequest()";
// WebMediaPlayerImpl ensures GenerateKeyRequest() has been called.
- media_keys_->CancelKeyRequest(session_id);
+ uint32 session_reference_id = LookupSessionId(session_id);
+ if (session_reference_id == kInvalidSessionId) {
+ // Session hasn't been created, so it is an error.
+ key_error_cb_.Run(
+ std::string(), media::MediaKeys::kUnknownError, 0);
+ }
+ else {
+ media_keys_->ReleaseSession(session_reference_id);
+ }
}
scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys(
@@ -130,29 +195,76 @@ scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys(
base::Bind(&ProxyDecryptor::DestroyHelperPlugin,
weak_ptr_factory_.GetWeakPtr()),
#elif defined(OS_ANDROID)
- proxy_,
+ manager_,
media_keys_id_,
frame_url,
#endif // defined(ENABLE_PEPPER_CDMS)
- base::Bind(&ProxyDecryptor::KeyAdded, weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&ProxyDecryptor::KeyError, weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&ProxyDecryptor::KeyMessage, weak_ptr_factory_.GetWeakPtr()));
+ base::Bind(&ProxyDecryptor::OnSessionCreated,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&ProxyDecryptor::OnSessionMessage,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&ProxyDecryptor::OnSessionReady,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&ProxyDecryptor::OnSessionClosed,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&ProxyDecryptor::OnSessionError,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ProxyDecryptor::OnSessionCreated(uint32 session_id,
+ const std::string& web_session_id) {
+ // Due to heartbeat messages, OnSessionCreated() can get called multiple
+ // times.
+ SessionIdMap::iterator it = sessions_.find(session_id);
+ DCHECK(it == sessions_.end() || it->second == web_session_id);
+ if (it == sessions_.end())
+ sessions_[session_id] = web_session_id;
+}
+
+void ProxyDecryptor::OnSessionMessage(uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url) {
+ // Assumes that OnSessionCreated() has been called before this.
+ key_message_cb_.Run(LookupWebSessionId(session_id), message, destination_url);
}
-void ProxyDecryptor::KeyAdded(const std::string& session_id) {
- key_added_cb_.Run(session_id);
+void ProxyDecryptor::OnSessionReady(uint32 session_id) {
+ // Assumes that OnSessionCreated() has been called before this.
+ key_added_cb_.Run(LookupWebSessionId(session_id));
}
-void ProxyDecryptor::KeyError(const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- int system_code) {
- key_error_cb_.Run(session_id, error_code, system_code);
+void ProxyDecryptor::OnSessionClosed(uint32 session_id) {
+ // No closed event in EME v0.1b.
}
-void ProxyDecryptor::KeyMessage(const std::string& session_id,
- const std::vector<uint8>& message,
- const std::string& default_url) {
- key_message_cb_.Run(session_id, message, default_url);
+void ProxyDecryptor::OnSessionError(uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code) {
+ // Assumes that OnSessionCreated() has been called before this.
+ key_error_cb_.Run(LookupWebSessionId(session_id), error_code, system_code);
+}
+
+uint32 ProxyDecryptor::LookupSessionId(const std::string& session_id) {
+ for (SessionIdMap::iterator it = sessions_.begin();
+ it != sessions_.end();
+ ++it) {
+ if (it->second == session_id)
+ return it->first;
+ }
+
+ // If |session_id| is null, then use the single reference id.
+ if (session_id.empty() && sessions_.size() == 1)
+ return sessions_.begin()->first;
+
+ return kInvalidSessionId;
+}
+
+const std::string& ProxyDecryptor::LookupWebSessionId(uint32 session_id) {
+ DCHECK_NE(session_id, kInvalidSessionId);
+
+ // Session may not exist if error happens during GenerateKeyRequest().
+ SessionIdMap::iterator it = sessions_.find(session_id);
+ return (it != sessions_.end()) ? it->second : base::EmptyString();
}
} // namespace content
diff --git a/chromium/content/renderer/media/crypto/proxy_decryptor.h b/chromium/content/renderer/media/crypto/proxy_decryptor.h
index 02027219794..026b56a2802 100644
--- a/chromium/content/renderer/media/crypto/proxy_decryptor.h
+++ b/chromium/content/renderer/media/crypto/proxy_decryptor.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_MEDIA_CRYPTO_PROXY_DECRYPTOR_H_
#define CONTENT_RENDERER_MEDIA_CRYPTO_PROXY_DECRYPTOR_H_
+#include <map>
#include <string>
#include <vector>
@@ -17,7 +18,7 @@
class GURL;
-namespace WebKit {
+namespace blink {
#if defined(ENABLE_PEPPER_CDMS)
class WebFrame;
class WebMediaPlayerClient;
@@ -26,27 +27,46 @@ class WebMediaPlayerClient;
namespace content {
-class WebMediaPlayerProxyAndroid;
+#if defined(OS_ANDROID)
+class RendererMediaPlayerManager;
+#endif // defined(OS_ANDROID)
// ProxyDecryptor is for EME v0.1b only. It should not be used for the WD API.
// A decryptor proxy that creates a real decryptor object on demand and
// forwards decryptor calls to it.
+//
+// Now that the Pepper API calls use session ID to match responses with
+// requests, this class maintains a mapping between session ID and web session
+// ID. Callers of this class expect web session IDs in the responses.
+// Session IDs are internal unique references to the session. Web session IDs
+// are the CDM generated ID for the session, and are what are visible to users.
+//
// TODO(xhwang): Currently we don't support run-time switching among decryptor
// objects. Fix this when needed.
// TODO(xhwang): The ProxyDecryptor is not a Decryptor. Find a better name!
-class ProxyDecryptor : public media::MediaKeys {
+class ProxyDecryptor {
public:
+ // These are similar to the callbacks in media_keys.h, but pass back the
+ // web session ID rather than the internal session ID.
+ typedef base::Callback<void(const std::string& session_id)> KeyAddedCB;
+ typedef base::Callback<void(const std::string& session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code)> KeyErrorCB;
+ typedef base::Callback<void(const std::string& session_id,
+ const std::vector<uint8>& message,
+ const std::string& default_url)> KeyMessageCB;
+
ProxyDecryptor(
#if defined(ENABLE_PEPPER_CDMS)
- WebKit::WebMediaPlayerClient* web_media_player_client,
- WebKit::WebFrame* web_frame,
+ blink::WebMediaPlayerClient* web_media_player_client,
+ blink::WebFrame* web_frame,
#elif defined(OS_ANDROID)
- WebMediaPlayerProxyAndroid* proxy,
+ RendererMediaPlayerManager* manager,
int media_keys_id,
#endif // defined(ENABLE_PEPPER_CDMS)
- const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb);
+ const KeyAddedCB& key_added_cb,
+ const KeyErrorCB& key_error_cb,
+ const KeyMessageCB& key_message_cb);
virtual ~ProxyDecryptor();
// Only call this once.
@@ -58,29 +78,41 @@ class ProxyDecryptor : public media::MediaKeys {
// NULL immediately and reset.
void SetDecryptorReadyCB(const media::DecryptorReadyCB& decryptor_ready_cb);
- // MediaKeys implementation.
// May only be called after InitializeCDM() succeeds.
- virtual bool GenerateKeyRequest(const std::string& type,
- const uint8* init_data,
- int init_data_length) OVERRIDE;
- virtual void AddKey(const uint8* key, int key_length,
- const uint8* init_data, int init_data_length,
- const std::string& session_id) OVERRIDE;
- virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE;
+ bool GenerateKeyRequest(const std::string& type,
+ const uint8* init_data,
+ int init_data_length);
+ void AddKey(const uint8* key, int key_length,
+ const uint8* init_data, int init_data_length,
+ const std::string& session_id);
+ void CancelKeyRequest(const std::string& session_id);
private:
+ // Session_id <-> web_session_id map.
+ typedef std::map<uint32, std::string> SessionIdMap;
+
// Helper function to create MediaKeys to handle the given |key_system|.
scoped_ptr<media::MediaKeys> CreateMediaKeys(const std::string& key_system,
const GURL& frame_url);
- // Callbacks for firing key events.
- void KeyAdded(const std::string& session_id);
- void KeyError(const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- int system_code);
- void KeyMessage(const std::string& session_id,
- const std::vector<uint8>& message,
- const std::string& default_url);
+ // Callbacks for firing session events.
+ void OnSessionCreated(uint32 session_id, const std::string& web_session_id);
+ void OnSessionMessage(uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& default_url);
+ void OnSessionReady(uint32 session_id);
+ void OnSessionClosed(uint32 session_id);
+ void OnSessionError(uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code);
+
+ // Helper function to determine session_id for the provided |web_session_id|.
+ uint32 LookupSessionId(const std::string& web_session_id);
+
+ // Helper function to determine web_session_id for the provided |session_id|.
+ // The returned web_session_id is only valid on the main thread, and should be
+ // stored by copy.
+ const std::string& LookupWebSessionId(uint32 session_id);
base::WeakPtrFactory<ProxyDecryptor> weak_ptr_factory_;
@@ -89,10 +121,10 @@ class ProxyDecryptor : public media::MediaKeys {
void DestroyHelperPlugin();
// Needed to create the PpapiDecryptor.
- WebKit::WebMediaPlayerClient* web_media_player_client_;
- WebKit::WebFrame* web_frame_;
+ blink::WebMediaPlayerClient* web_media_player_client_;
+ blink::WebFrame* web_frame_;
#elif defined(OS_ANDROID)
- WebMediaPlayerProxyAndroid* proxy_;
+ RendererMediaPlayerManager* manager_;
int media_keys_id_;
#endif // defined(ENABLE_PEPPER_CDMS)
@@ -101,9 +133,9 @@ class ProxyDecryptor : public media::MediaKeys {
scoped_ptr<media::MediaKeys> media_keys_;
// Callbacks for firing key events.
- media::KeyAddedCB key_added_cb_;
- media::KeyErrorCB key_error_cb_;
- media::KeyMessageCB key_message_cb_;
+ KeyAddedCB key_added_cb_;
+ KeyErrorCB key_error_cb_;
+ KeyMessageCB key_message_cb_;
// Protects the |decryptor_|. Note that |decryptor_| itself should be thread
// safe as per the Decryptor interface.
@@ -111,6 +143,15 @@ class ProxyDecryptor : public media::MediaKeys {
media::DecryptorReadyCB decryptor_ready_cb_;
+ // Session IDs are used to uniquely track sessions so that CDM callbacks
+ // can get mapped to the correct session ID. Session ID should be unique
+ // per renderer process for debugging purposes.
+ static uint32 next_session_id_;
+
+ SessionIdMap sessions_;
+
+ bool is_clear_key_;
+
DISALLOW_COPY_AND_ASSIGN(ProxyDecryptor);
};
diff --git a/chromium/content/renderer/media/media_stream_audio_processor.cc b/chromium/content/renderer/media/media_stream_audio_processor.cc
new file mode 100644
index 00000000000..98439c78aef
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_audio_processor.cc
@@ -0,0 +1,354 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/media_stream_audio_processor.h"
+
+#include "base/command_line.h"
+#include "base/debug/trace_event.h"
+#include "content/public/common/content_switches.h"
+#include "content/renderer/media/media_stream_audio_processor_options.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_converter.h"
+#include "media/base/audio_fifo.h"
+#include "media/base/channel_layout.h"
+
+namespace content {
+
+namespace {
+
+using webrtc::AudioProcessing;
+using webrtc::MediaConstraintsInterface;
+
+#if defined(ANDROID)
+const int kAudioProcessingSampleRate = 16000;
+#else
+const int kAudioProcessingSampleRate = 32000;
+#endif
+const int kAudioProcessingNumberOfChannel = 1;
+
+const int kMaxNumberOfBuffersInFifo = 2;
+
+} // namespace
+
+class MediaStreamAudioProcessor::MediaStreamAudioConverter
+ : public media::AudioConverter::InputCallback {
+ public:
+ MediaStreamAudioConverter(const media::AudioParameters& source_params,
+ const media::AudioParameters& sink_params)
+ : source_params_(source_params),
+ sink_params_(sink_params),
+ audio_converter_(source_params, sink_params_, false) {
+ audio_converter_.AddInput(this);
+ // Create and initialize audio fifo and audio bus wrapper.
+ // The size of the FIFO should be at least twice of the source buffer size
+ // or twice of the sink buffer size.
+ int buffer_size = std::max(
+ kMaxNumberOfBuffersInFifo * source_params_.frames_per_buffer(),
+ kMaxNumberOfBuffersInFifo * sink_params_.frames_per_buffer());
+ fifo_.reset(new media::AudioFifo(source_params_.channels(), buffer_size));
+ // TODO(xians): Use CreateWrapper to save one memcpy.
+ audio_wrapper_ = media::AudioBus::Create(sink_params_.channels(),
+ sink_params_.frames_per_buffer());
+ }
+
+ virtual ~MediaStreamAudioConverter() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ audio_converter_.RemoveInput(this);
+ }
+
+ void Push(media::AudioBus* audio_source) {
+ // Called on the audio thread, which is the capture audio thread for
+ // |MediaStreamAudioProcessor::capture_converter_|, and render audio thread
+ // for |MediaStreamAudioProcessor::render_converter_|.
+ // And it must be the same thread as calling Convert().
+ DCHECK(thread_checker_.CalledOnValidThread());
+ fifo_->Push(audio_source);
+ }
+
+ bool Convert(webrtc::AudioFrame* out) {
+ // Called on the audio thread, which is the capture audio thread for
+ // |MediaStreamAudioProcessor::capture_converter_|, and render audio thread
+ // for |MediaStreamAudioProcessor::render_converter_|.
+ // Return false if there is no 10ms data in the FIFO.
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (fifo_->frames() < (source_params_.sample_rate() / 100))
+ return false;
+
+ // Convert 10ms data to the output format, this will trigger ProvideInput().
+ audio_converter_.Convert(audio_wrapper_.get());
+
+ // TODO(xians): Figure out a better way to handle the interleaved and
+ // deinterleaved format switching.
+ audio_wrapper_->ToInterleaved(audio_wrapper_->frames(),
+ sink_params_.bits_per_sample() / 8,
+ out->data_);
+
+ out->samples_per_channel_ = sink_params_.frames_per_buffer();
+ out->sample_rate_hz_ = sink_params_.sample_rate();
+ out->speech_type_ = webrtc::AudioFrame::kNormalSpeech;
+ out->vad_activity_ = webrtc::AudioFrame::kVadUnknown;
+ out->num_channels_ = sink_params_.channels();
+
+ return true;
+ }
+
+ const media::AudioParameters& source_parameters() const {
+ return source_params_;
+ }
+ const media::AudioParameters& sink_parameters() const {
+ return sink_params_;
+ }
+
+ private:
+ // AudioConverter::InputCallback implementation.
+ virtual double ProvideInput(media::AudioBus* audio_bus,
+ base::TimeDelta buffer_delay) OVERRIDE {
+ // Called on realtime audio thread.
+ // TODO(xians): Figure out why the first Convert() triggers ProvideInput
+ // two times.
+ if (fifo_->frames() < audio_bus->frames())
+ return 0;
+
+ fifo_->Consume(audio_bus, 0, audio_bus->frames());
+
+ // Return 1.0 to indicate no volume scaling on the data.
+ return 1.0;
+ }
+
+ base::ThreadChecker thread_checker_;
+ const media::AudioParameters source_params_;
+ const media::AudioParameters sink_params_;
+
+ // TODO(xians): consider using SincResampler to save some memcpy.
+ // Handles mixing and resampling between input and output parameters.
+ media::AudioConverter audio_converter_;
+ scoped_ptr<media::AudioBus> audio_wrapper_;
+ scoped_ptr<media::AudioFifo> fifo_;
+};
+
+MediaStreamAudioProcessor::MediaStreamAudioProcessor(
+ const webrtc::MediaConstraintsInterface* constraints)
+ : render_delay_ms_(0) {
+ capture_thread_checker_.DetachFromThread();
+ render_thread_checker_.DetachFromThread();
+ InitializeAudioProcessingModule(constraints);
+}
+
+MediaStreamAudioProcessor::~MediaStreamAudioProcessor() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ StopAudioProcessing();
+}
+
+void MediaStreamAudioProcessor::PushCaptureData(media::AudioBus* audio_source) {
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
+ capture_converter_->Push(audio_source);
+}
+
+void MediaStreamAudioProcessor::PushRenderData(
+ const int16* render_audio, int sample_rate, int number_of_channels,
+ int number_of_frames, base::TimeDelta render_delay) {
+ DCHECK(render_thread_checker_.CalledOnValidThread());
+
+ // Return immediately if the echo cancellation is off.
+ if (!audio_processing_ ||
+ !audio_processing_->echo_cancellation()->is_enabled()) {
+ return;
+ }
+
+ TRACE_EVENT0("audio",
+ "MediaStreamAudioProcessor::FeedRenderDataToAudioProcessing");
+ int64 new_render_delay_ms = render_delay.InMilliseconds();
+ DCHECK_LT(new_render_delay_ms,
+ std::numeric_limits<base::subtle::Atomic32>::max());
+ base::subtle::Release_Store(&render_delay_ms_, new_render_delay_ms);
+
+ InitializeRenderConverterIfNeeded(sample_rate, number_of_channels,
+ number_of_frames);
+
+ // TODO(xians): Avoid this extra interleave/deinterleave.
+ render_data_bus_->FromInterleaved(render_audio,
+ render_data_bus_->frames(),
+ sizeof(render_audio[0]));
+ render_converter_->Push(render_data_bus_.get());
+ while (render_converter_->Convert(&render_frame_))
+ audio_processing_->AnalyzeReverseStream(&render_frame_);
+}
+
+bool MediaStreamAudioProcessor::ProcessAndConsumeData(
+ base::TimeDelta capture_delay, int volume, bool key_pressed,
+ int16** out) {
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("audio",
+ "MediaStreamAudioProcessor::ProcessAndConsumeData");
+
+ if (!capture_converter_->Convert(&capture_frame_))
+ return false;
+
+ ProcessData(&capture_frame_, capture_delay, volume, key_pressed);
+ *out = capture_frame_.data_;
+
+ return true;
+}
+
+void MediaStreamAudioProcessor::SetCaptureFormat(
+ const media::AudioParameters& source_params) {
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
+ DCHECK(source_params.IsValid());
+
+ // Create and initialize audio converter for the source data.
+ // When the webrtc AudioProcessing is enabled, the sink format of the
+ // converter will be the same as the post-processed data format, which is
+ // 32k mono for desktops and 16k mono for Android. When the AudioProcessing
+ // is disabled, the sink format will be the same as the source format.
+ const int sink_sample_rate = audio_processing_ ?
+ kAudioProcessingSampleRate : source_params.sample_rate();
+ const media::ChannelLayout sink_channel_layout = audio_processing_ ?
+ media::CHANNEL_LAYOUT_MONO : source_params.channel_layout();
+
+ // WebRtc is using 10ms data as its native packet size.
+ media::AudioParameters sink_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY, sink_channel_layout,
+ sink_sample_rate, 16, sink_sample_rate / 100);
+ capture_converter_.reset(
+ new MediaStreamAudioConverter(source_params, sink_params));
+}
+
+const media::AudioParameters& MediaStreamAudioProcessor::OutputFormat() const {
+ return capture_converter_->sink_parameters();
+}
+
+void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
+ const webrtc::MediaConstraintsInterface* constraints) {
+ DCHECK(!audio_processing_);
+ DCHECK(constraints);
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableAudioTrackProcessing)) {
+ return;
+ }
+
+ const bool enable_aec = GetPropertyFromConstraints(
+ constraints, MediaConstraintsInterface::kEchoCancellation);
+ const bool enable_ns = GetPropertyFromConstraints(
+ constraints, MediaConstraintsInterface::kNoiseSuppression);
+ const bool enable_high_pass_filter = GetPropertyFromConstraints(
+ constraints, MediaConstraintsInterface::kHighpassFilter);
+#if defined(IOS) || defined(ANDROID)
+ const bool enable_experimental_aec = false;
+ const bool enable_typing_detection = false;
+#else
+ const bool enable_experimental_aec = GetPropertyFromConstraints(
+ constraints, MediaConstraintsInterface::kExperimentalEchoCancellation);
+ const bool enable_typing_detection = GetPropertyFromConstraints(
+ constraints, MediaConstraintsInterface::kTypingNoiseDetection);
+#endif
+
+ // Return immediately if no audio processing component is enabled.
+ if (!enable_aec && !enable_experimental_aec && !enable_ns &&
+ !enable_high_pass_filter && !enable_typing_detection) {
+ return;
+ }
+
+ // Create and configure the webrtc::AudioProcessing.
+ audio_processing_.reset(webrtc::AudioProcessing::Create(0));
+
+ // Enable the audio processing components.
+ if (enable_aec) {
+ EnableEchoCancellation(audio_processing_.get());
+ if (enable_experimental_aec)
+ EnableExperimentalEchoCancellation(audio_processing_.get());
+ }
+
+ if (enable_ns)
+ EnableNoiseSuppression(audio_processing_.get());
+
+ if (enable_high_pass_filter)
+ EnableHighPassFilter(audio_processing_.get());
+
+ if (enable_typing_detection)
+ EnableTypingDetection(audio_processing_.get());
+
+
+ // Configure the audio format the audio processing is running on. This
+ // has to be done after all the needed components are enabled.
+ CHECK_EQ(audio_processing_->set_sample_rate_hz(kAudioProcessingSampleRate),
+ 0);
+ CHECK_EQ(audio_processing_->set_num_channels(kAudioProcessingNumberOfChannel,
+ kAudioProcessingNumberOfChannel),
+ 0);
+}
+
+void MediaStreamAudioProcessor::InitializeRenderConverterIfNeeded(
+ int sample_rate, int number_of_channels, int frames_per_buffer) {
+ DCHECK(render_thread_checker_.CalledOnValidThread());
+ // TODO(xians): Figure out if we need to handle the buffer size change.
+ if (render_converter_.get() &&
+ render_converter_->source_parameters().sample_rate() == sample_rate &&
+ render_converter_->source_parameters().channels() == number_of_channels) {
+ // Do nothing if the |render_converter_| has been setup properly.
+ return;
+ }
+
+ // Create and initialize audio converter for the render data.
+ // webrtc::AudioProcessing accepts the same format as what it uses to process
+ // capture data, which is 32k mono for desktops and 16k mono for Android.
+ media::AudioParameters source_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::GuessChannelLayout(number_of_channels), sample_rate, 16,
+ frames_per_buffer);
+ media::AudioParameters sink_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_MONO, kAudioProcessingSampleRate, 16,
+ kAudioProcessingSampleRate / 100);
+ render_converter_.reset(
+ new MediaStreamAudioConverter(source_params, sink_params));
+ render_data_bus_ = media::AudioBus::Create(number_of_channels,
+ frames_per_buffer);
+}
+
+void MediaStreamAudioProcessor::ProcessData(webrtc::AudioFrame* audio_frame,
+ base::TimeDelta capture_delay,
+ int volume,
+ bool key_pressed) {
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
+ if (!audio_processing_)
+ return;
+
+ TRACE_EVENT0("audio", "MediaStreamAudioProcessor::Process10MsData");
+ DCHECK_EQ(audio_processing_->sample_rate_hz(),
+ capture_converter_->sink_parameters().sample_rate());
+ DCHECK_EQ(audio_processing_->num_input_channels(),
+ capture_converter_->sink_parameters().channels());
+ DCHECK_EQ(audio_processing_->num_output_channels(),
+ capture_converter_->sink_parameters().channels());
+
+ base::subtle::Atomic32 render_delay_ms =
+ base::subtle::Acquire_Load(&render_delay_ms_);
+ int64 capture_delay_ms = capture_delay.InMilliseconds();
+ DCHECK_LT(capture_delay_ms,
+ std::numeric_limits<base::subtle::Atomic32>::max());
+ int total_delay_ms = capture_delay_ms + render_delay_ms;
+ if (total_delay_ms > 1000) {
+ LOG(WARNING) << "Large audio delay, capture delay: " << capture_delay_ms
+ << "ms; render delay: " << render_delay_ms << "ms";
+ }
+
+ audio_processing_->set_stream_delay_ms(total_delay_ms);
+ webrtc::GainControl* agc = audio_processing_->gain_control();
+ int err = agc->set_stream_analog_level(volume);
+ DCHECK_EQ(err, 0) << "set_stream_analog_level() error: " << err;
+ err = audio_processing_->ProcessStream(audio_frame);
+ DCHECK_EQ(err, 0) << "ProcessStream() error: " << err;
+
+ // TODO(xians): Add support for AGC, typing detection, audio level
+ // calculation, stereo swapping.
+}
+
+void MediaStreamAudioProcessor::StopAudioProcessing() {
+ if (!audio_processing_.get())
+ return;
+
+ audio_processing_.reset();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_processor.h b/chromium/content/renderer/media/media_stream_audio_processor.h
new file mode 100644
index 00000000000..9c6db685db4
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_audio_processor.h
@@ -0,0 +1,138 @@
+// 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_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_H_
+
+#include "base/atomicops.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "media/base/audio_converter.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
+#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
+#include "third_party/webrtc/modules/interface/module_common_types.h"
+
+namespace media {
+class AudioBus;
+class AudioFifo;
+class AudioParameters;
+} // namespace media
+
+namespace webrtc {
+class AudioFrame;
+}
+
+namespace content {
+
+// This class owns an object of webrtc::AudioProcessing which contains signal
+// processing components like AGC, AEC and NS. It enables the components based
+// on the getUserMedia constraints, processes the data and outputs it in a unit
+// of 10 ms data chunk.
+class CONTENT_EXPORT MediaStreamAudioProcessor {
+ public:
+ explicit MediaStreamAudioProcessor(
+ const webrtc::MediaConstraintsInterface* constraints);
+ ~MediaStreamAudioProcessor();
+
+ // Pushes capture data in |audio_source| to the internal FIFO.
+ // Called on the capture audio thread.
+ void PushCaptureData(media::AudioBus* audio_source);
+
+ // Push the render audio to webrtc::AudioProcessing for analysis. This is
+ // needed iff echo processing is enabled.
+ // |render_audio| is the pointer to the render audio data, its format
+ // is specified by |sample_rate|, |number_of_channels| and |number_of_frames|.
+ // Called on the render audio thread.
+ void PushRenderData(const int16* render_audio,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ base::TimeDelta render_delay);
+
+ // Processes a block of 10 ms data from the internal FIFO and outputs it via
+ // |out|. |out| is the address of the pointer that will be pointed to
+ // the post-processed data if the method is returning a true. The lifetime
+ // of the data represeted by |out| is guaranteed to outlive the method call.
+ // That also says *|out| won't change until this method is called again.
+ // Returns true if the internal FIFO has at least 10 ms data for processing,
+ // otherwise false.
+ // |capture_delay|, |volume| and |key_pressed| will be passed to
+ // webrtc::AudioProcessing to help processing the data.
+ // Called on the capture audio thread.
+ bool ProcessAndConsumeData(base::TimeDelta capture_delay,
+ int volume,
+ bool key_pressed,
+ int16** out);
+
+ // Called when the format of the capture data has changed.
+ // This has to be called before PushCaptureData() and ProcessAndConsumeData().
+ // Called on the main render thread.
+ void SetCaptureFormat(const media::AudioParameters& source_params);
+
+ // The audio format of the output from the processor.
+ const media::AudioParameters& OutputFormat() const;
+
+ // Accessor to check if the audio processing is enabled or not.
+ bool has_audio_processing() const { return audio_processing_.get() != NULL; }
+
+ private:
+ class MediaStreamAudioConverter;
+
+ // Helper to initialize the WebRtc AudioProcessing.
+ void InitializeAudioProcessingModule(
+ const webrtc::MediaConstraintsInterface* constraints);
+
+ // Helper to initialize the render converter.
+ void InitializeRenderConverterIfNeeded(int sample_rate,
+ int number_of_channels,
+ int frames_per_buffer);
+
+ // Called by ProcessAndConsumeData().
+ void ProcessData(webrtc::AudioFrame* audio_frame,
+ base::TimeDelta capture_delay,
+ int volume,
+ bool key_pressed);
+
+ // Called when the processor is going away.
+ void StopAudioProcessing();
+
+ // 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_;
+
+ // webrtc::AudioProcessing module which does AEC, AGC, NS, HighPass filter,
+ // ..etc.
+ scoped_ptr<webrtc::AudioProcessing> audio_processing_;
+
+ // Converter used for the down-mixing and resampling of the capture data.
+ scoped_ptr<MediaStreamAudioConverter> capture_converter_;
+
+ // AudioFrame used to hold the output of |capture_converter_|.
+ webrtc::AudioFrame capture_frame_;
+
+ // Converter used for the down-mixing and resampling of the render data when
+ // the AEC is enabled.
+ scoped_ptr<MediaStreamAudioConverter> render_converter_;
+
+ // AudioFrame used to hold the output of |render_converter_|.
+ webrtc::AudioFrame render_frame_;
+
+ // Data bus to help converting interleaved data to an AudioBus.
+ scoped_ptr<media::AudioBus> render_data_bus_;
+
+ // Used to DCHECK that some methods are called on the main render thread.
+ base::ThreadChecker main_thread_checker_;
+
+ // Used to DCHECK that some methods are called on the capture audio thread.
+ base::ThreadChecker capture_thread_checker_;
+
+ // Used to DCHECK that PushRenderData() is called on the render audio thread.
+ base::ThreadChecker render_thread_checker_;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_H_
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_options.cc b/chromium/content/renderer/media/media_stream_audio_processor_options.cc
new file mode 100644
index 00000000000..add7f957c86
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_audio_processor_options.cc
@@ -0,0 +1,96 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/media_stream_audio_processor_options.h"
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
+#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
+
+namespace content {
+
+bool GetPropertyFromConstraints(const MediaConstraintsInterface* constraints,
+ const std::string& key) {
+ bool value = false;
+ return webrtc::FindConstraint(constraints, key, &value, NULL) && value;
+}
+
+void EnableEchoCancellation(AudioProcessing* audio_processing) {
+#if defined(OS_IOS)
+ // On iOS, VPIO provides built-in EC and AGC.
+ return;
+#elif defined(OS_ANDROID)
+ // Mobile devices are using AECM.
+ int err = audio_processing->echo_control_mobile()->Enable(true);
+ err |= audio_processing->echo_control_mobile()->set_routing_mode(
+ webrtc::EchoControlMobile::kSpeakerphone);
+ CHECK_EQ(err, 0);
+#else
+ int err = audio_processing->echo_cancellation()->Enable(true);
+ err |= audio_processing->echo_cancellation()->set_suppression_level(
+ webrtc::EchoCancellation::kHighSuppression);
+
+ // Enable the metrics for AEC.
+ err |= audio_processing->echo_cancellation()->enable_metrics(true);
+ err |= audio_processing->echo_cancellation()->enable_delay_logging(true);
+ CHECK_EQ(err, 0);
+#endif
+}
+
+void EnableNoiseSuppression(AudioProcessing* audio_processing) {
+ int err = audio_processing->noise_suppression()->set_level(
+ webrtc::NoiseSuppression::kHigh);
+ err |= audio_processing->noise_suppression()->Enable(true);
+ CHECK_EQ(err, 0);
+}
+
+void EnableHighPassFilter(AudioProcessing* audio_processing) {
+ CHECK_EQ(audio_processing->high_pass_filter()->Enable(true), 0);
+}
+
+// TODO(xians): stereo swapping
+void EnableTypingDetection(AudioProcessing* audio_processing) {
+ int err = audio_processing->voice_detection()->Enable(true);
+ err |= audio_processing->voice_detection()->set_likelihood(
+ webrtc::VoiceDetection::kVeryLowLikelihood);
+ CHECK_EQ(err, 0);
+}
+
+void EnableExperimentalEchoCancellation(AudioProcessing* audio_processing) {
+ webrtc::Config config;
+ config.Set<webrtc::DelayCorrection>(new webrtc::DelayCorrection(true));
+ audio_processing->SetExtraOptions(config);
+}
+
+void StartAecDump(AudioProcessing* audio_processing) {
+ // TODO(grunell): Figure out a more suitable directory for the audio dump
+ // data.
+ base::FilePath path;
+#if defined(CHROMEOS)
+ PathService::Get(base::DIR_TEMP, &path);
+#elif defined(ANDROID)
+ path = base::FilePath(FILE_PATH_LITERAL("sdcard"));
+#else
+ PathService::Get(base::DIR_EXE, &path);
+#endif
+ base::FilePath file = path.Append(FILE_PATH_LITERAL("audio.aecdump"));
+
+#if defined(OS_WIN)
+ const std::string file_name = WideToUTF8(file.value());
+#else
+ const std::string file_name = file.value();
+#endif
+ if (audio_processing->StartDebugRecording(file_name.c_str()))
+ DLOG(ERROR) << "Fail to start AEC debug recording";
+}
+
+void StopAecDump(AudioProcessing* audio_processing) {
+ if (audio_processing->StopDebugRecording())
+ DLOG(ERROR) << "Fail to stop AEC debug recording";
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_options.h b/chromium/content/renderer/media/media_stream_audio_processor_options.h
new file mode 100644
index 00000000000..dcdec4e61f4
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_audio_processor_options.h
@@ -0,0 +1,53 @@
+// 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_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_OPTIONS_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_OPTIONS_H_
+
+#include <string>
+
+namespace webrtc {
+
+class AudioFrame;
+class AudioProcessing;
+class MediaConstraintsInterface;
+
+}
+
+namespace content {
+
+using webrtc::AudioProcessing;
+using webrtc::MediaConstraintsInterface;
+
+// Gets the property named by |key| from the |constraints|.
+// Returns true if the key is found and has a valid boolean value; Otherwise
+// false.
+bool GetPropertyFromConstraints(
+ const MediaConstraintsInterface* constraints,
+ const std::string& key);
+
+// Enables the echo cancellation in |audio_processing|.
+void EnableEchoCancellation(AudioProcessing* audio_processing);
+
+// Enables the noise suppression in |audio_processing|.
+void EnableNoiseSuppression(AudioProcessing* audio_processing);
+
+// Enables the high pass filter in |audio_processing|.
+void EnableHighPassFilter(AudioProcessing* audio_processing);
+
+// Enables the typing detection in |audio_processing|.
+void EnableTypingDetection(AudioProcessing* audio_processing);
+
+// Enables the experimental echo cancellation in |audio_processing|.
+void EnableExperimentalEchoCancellation(AudioProcessing* audio_processing);
+
+// Starts the echo cancellation dump in |audio_processing|.
+void StartAecDump(AudioProcessing* audio_processing);
+
+// Stops the echo cancellation dump in |audio_processing|.
+void StopAecDump(AudioProcessing* audio_processing);
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_OPTIONS_H_
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc b/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc
new file mode 100644
index 00000000000..1a6409c2c1a
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc
@@ -0,0 +1,166 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/time/time.h"
+#include "content/public/common/content_switches.h"
+#include "content/renderer/media/media_stream_audio_processor.h"
+#include "content/renderer/media/rtc_media_constraints.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_bus.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::AtLeast;
+using ::testing::Return;
+
+namespace content {
+
+namespace {
+
+#if defined(ANDROID)
+const int kAudioProcessingSampleRate = 16000;
+#else
+const int kAudioProcessingSampleRate = 32000;
+#endif
+const int kAudioProcessingNumberOfChannel = 1;
+
+// The number of packers used for testing.
+const int kNumberOfPacketsForTest = 100;
+
+void ReadDataFromSpeechFile(char* data, int length) {
+ base::FilePath file;
+ CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &file));
+ file = file.Append(FILE_PATH_LITERAL("media"))
+ .Append(FILE_PATH_LITERAL("test"))
+ .Append(FILE_PATH_LITERAL("data"))
+ .Append(FILE_PATH_LITERAL("speech_16b_stereo_48kHz.raw"));
+ DCHECK(base::PathExists(file));
+ int64 data_file_size64 = 0;
+ DCHECK(base::GetFileSize(file, &data_file_size64));
+ EXPECT_EQ(length, base::ReadFile(file, data, length));
+ DCHECK(data_file_size64 > length);
+}
+
+void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints) {
+ // Constant constraint keys which enables default audio constraints on
+ // mediastreams with audio.
+ struct {
+ const char* key;
+ const char* value;
+ } static const kDefaultAudioConstraints[] = {
+ { webrtc::MediaConstraintsInterface::kEchoCancellation,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ #if defined(OS_CHROMEOS) || defined(OS_MACOSX)
+ // Enable the extended filter mode AEC on platforms with known echo issues.
+ { webrtc::MediaConstraintsInterface::kExperimentalEchoCancellation,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ #endif
+ { webrtc::MediaConstraintsInterface::kAutoGainControl,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ { webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ { webrtc::MediaConstraintsInterface::kNoiseSuppression,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ { webrtc::MediaConstraintsInterface::kHighpassFilter,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) {
+ constraints->AddMandatory(kDefaultAudioConstraints[i].key,
+ kDefaultAudioConstraints[i].value, false);
+ }
+}
+
+} // namespace
+
+class MediaStreamAudioProcessorTest : public ::testing::Test {
+ public:
+ MediaStreamAudioProcessorTest()
+ : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO, 48000, 16, 512) {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableAudioTrackProcessing);
+ }
+
+ protected:
+ // Helper method to save duplicated code.
+ void ProcessDataAndVerifyFormat(MediaStreamAudioProcessor* audio_processor,
+ int expected_output_sample_rate,
+ int expected_output_channels,
+ int expected_output_buffer_size) {
+ // Read the audio data from a file.
+ const int packet_size =
+ params_.frames_per_buffer() * 2 * params_.channels();
+ const size_t length = packet_size * kNumberOfPacketsForTest;
+ scoped_ptr<char[]> capture_data(new char[length]);
+ ReadDataFromSpeechFile(capture_data.get(), length);
+ const int16* data_ptr = reinterpret_cast<const int16*>(capture_data.get());
+ scoped_ptr<media::AudioBus> data_bus = media::AudioBus::Create(
+ params_.channels(), params_.frames_per_buffer());
+ for (int i = 0; i < kNumberOfPacketsForTest; ++i) {
+ data_bus->FromInterleaved(data_ptr, data_bus->frames(), 2);
+ audio_processor->PushCaptureData(data_bus.get());
+
+ // |audio_processor| does nothing when the audio processing is off in
+ // the processor.
+ audio_processor->PushRenderData(
+ data_ptr,
+ params_.sample_rate(), params_.channels(),
+ params_.frames_per_buffer(), base::TimeDelta::FromMilliseconds(10));
+
+ int16* output = NULL;
+ while(audio_processor->ProcessAndConsumeData(
+ base::TimeDelta::FromMilliseconds(10), 255, false, &output)) {
+ EXPECT_TRUE(output != NULL);
+ EXPECT_EQ(audio_processor->OutputFormat().sample_rate(),
+ expected_output_sample_rate);
+ EXPECT_EQ(audio_processor->OutputFormat().channels(),
+ expected_output_channels);
+ EXPECT_EQ(audio_processor->OutputFormat().frames_per_buffer(),
+ expected_output_buffer_size);
+ }
+
+ data_ptr += params_.frames_per_buffer() * params_.channels();
+ }
+ }
+
+ media::AudioParameters params_;
+};
+
+TEST_F(MediaStreamAudioProcessorTest, WithoutAudioProcessing) {
+ // Setup the audio processor with empty constraint.
+ RTCMediaConstraints constraints;
+ MediaStreamAudioProcessor audio_processor(&constraints);
+ audio_processor.SetCaptureFormat(params_);
+ EXPECT_FALSE(audio_processor.has_audio_processing());
+
+ ProcessDataAndVerifyFormat(&audio_processor,
+ params_.sample_rate(),
+ params_.channels(),
+ params_.sample_rate() / 100);
+}
+
+TEST_F(MediaStreamAudioProcessorTest, WithAudioProcessing) {
+ // Setup the audio processor with default constraint.
+ RTCMediaConstraints constraints;
+ ApplyFixedAudioConstraints(&constraints);
+ MediaStreamAudioProcessor audio_processor(&constraints);
+ audio_processor.SetCaptureFormat(params_);
+ EXPECT_TRUE(audio_processor.has_audio_processing());
+
+ ProcessDataAndVerifyFormat(&audio_processor,
+ kAudioProcessingSampleRate,
+ kAudioProcessingNumberOfChannel,
+ kAudioProcessingSampleRate / 100);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_sink_owner.cc b/chromium/content/renderer/media/media_stream_audio_sink_owner.cc
new file mode 100644
index 00000000000..664988d8213
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_audio_sink_owner.cc
@@ -0,0 +1,70 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/media_stream_audio_sink_owner.h"
+
+#include "content/public/renderer/media_stream_audio_sink.h"
+#include "media/audio/audio_parameters.h"
+
+namespace content {
+
+MediaStreamAudioSinkOwner::MediaStreamAudioSinkOwner(MediaStreamAudioSink* sink)
+ : delegate_(sink) {
+}
+
+int MediaStreamAudioSinkOwner::OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) {
+ base::AutoLock lock(lock_);
+ // TODO(xians): Investigate on the possibility of not calling out with the
+ // lock.
+ if (delegate_) {
+ delegate_->OnData(audio_data,
+ sample_rate,
+ number_of_channels,
+ number_of_frames);
+ }
+
+ return 0;
+}
+
+void MediaStreamAudioSinkOwner::OnSetFormat(
+ const media::AudioParameters& params) {
+ base::AutoLock lock(lock_);
+ if (delegate_)
+ delegate_->OnSetFormat(params);
+}
+
+void MediaStreamAudioSinkOwner::OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) {
+ base::AutoLock lock(lock_);
+ if (delegate_)
+ delegate_->OnReadyStateChanged(state);
+}
+
+void MediaStreamAudioSinkOwner::Reset() {
+ base::AutoLock lock(lock_);
+ delegate_ = NULL;
+}
+
+bool MediaStreamAudioSinkOwner::IsEqual(
+ const MediaStreamAudioSink* other) const {
+ DCHECK(other);
+ base::AutoLock lock(lock_);
+ return (other == delegate_);
+}
+
+bool MediaStreamAudioSinkOwner::IsEqual(
+ const PeerConnectionAudioSink* other) const {
+ DCHECK(other);
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_sink_owner.h b/chromium/content/renderer/media/media_stream_audio_sink_owner.h
new file mode 100644
index 00000000000..6fcabbd3580
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_audio_sink_owner.h
@@ -0,0 +1,54 @@
+// 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_MEDIA_MEDIA_STREAM_AUDIO_SINK_OWNER_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_SINK_OWNER_H_
+
+#include <vector>
+
+#include "base/synchronization/lock.h"
+#include "content/renderer/media/media_stream_audio_track_sink.h"
+
+namespace content {
+
+class MediaStreamAudioSink;
+
+// Reference counted holder of MediaStreamAudioSink sinks.
+class MediaStreamAudioSinkOwner : public MediaStreamAudioTrackSink {
+ public:
+ explicit MediaStreamAudioSinkOwner(MediaStreamAudioSink* sink);
+
+ // MediaStreamAudioTrackSink implementation.
+ virtual int OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) OVERRIDE;
+ virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
+ virtual void OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
+ virtual void Reset() OVERRIDE;
+ virtual bool IsEqual(const MediaStreamAudioSink* other) const OVERRIDE;
+ virtual bool IsEqual(const PeerConnectionAudioSink* other) const OVERRIDE;
+
+ protected:
+ virtual ~MediaStreamAudioSinkOwner() {}
+
+ private:
+ mutable base::Lock lock_;
+
+ // Raw pointer to the delegate, the client need to call Reset() to set the
+ // pointer to NULL before the delegate goes away.
+ MediaStreamAudioSink* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioSinkOwner);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_SINK_OWNER_H_
diff --git a/chromium/content/renderer/media/media_stream_audio_track_sink.h b/chromium/content/renderer/media/media_stream_audio_track_sink.h
new file mode 100644
index 00000000000..6e511bd6534
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_audio_track_sink.h
@@ -0,0 +1,72 @@
+// 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_MEDIA_MEDIA_STREAM_AUDIO_TRACK_SINK_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_TRACK_SINK_H_
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "media/audio/audio_parameters.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
+
+namespace content {
+
+class MediaStreamAudioSink;
+class PeerConnectionAudioSink;
+
+// Interface for reference counted holder of audio stream audio track sink.
+class MediaStreamAudioTrackSink
+ : public base::RefCountedThreadSafe<MediaStreamAudioTrackSink> {
+ public:
+ virtual int OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) = 0;
+
+ virtual void OnSetFormat(const media::AudioParameters& params) = 0;
+
+ virtual void OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) = 0;
+
+ virtual void Reset() = 0;
+
+ virtual bool IsEqual(const MediaStreamAudioSink* other) const = 0;
+ virtual bool IsEqual(const PeerConnectionAudioSink* other) const = 0;
+
+ // Wrapper which allows to use std::find_if() when adding and removing
+ // sinks to/from the list.
+ struct WrapsMediaStreamSink {
+ WrapsMediaStreamSink(MediaStreamAudioSink* sink) : sink_(sink) {}
+ bool operator()(
+ const scoped_refptr<MediaStreamAudioTrackSink>& owner) const {
+ return owner->IsEqual(sink_);
+ }
+ MediaStreamAudioSink* sink_;
+ };
+ struct WrapsPeerConnectionSink {
+ WrapsPeerConnectionSink(PeerConnectionAudioSink* sink) : sink_(sink) {}
+ bool operator()(
+ const scoped_refptr<MediaStreamAudioTrackSink>& owner) const {
+ return owner->IsEqual(sink_);
+ }
+ PeerConnectionAudioSink* sink_;
+ };
+
+ protected:
+ virtual ~MediaStreamAudioTrackSink() {}
+
+ private:
+ friend class base::RefCountedThreadSafe<MediaStreamAudioTrackSink>;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_TRACK_SINK_H_
diff --git a/chromium/content/renderer/media/media_stream_center.cc b/chromium/content/renderer/media/media_stream_center.cc
index 26f2303d04a..daf1a499507 100644
--- a/chromium/content/renderer/media/media_stream_center.cc
+++ b/chromium/content/renderer/media/media_stream_center.cc
@@ -16,7 +16,8 @@
#include "content/public/renderer/render_thread.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
#include "content/renderer/media/media_stream_extra_data.h"
-#include "content/renderer/media/media_stream_impl.h"
+#include "content/renderer/media/media_stream_source_extra_data.h"
+#include "content/renderer/media/media_stream_track_extra_data.h"
#include "content/renderer/render_view_impl.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
#include "third_party/WebKit/public/platform/WebMediaStreamCenterClient.h"
@@ -28,43 +29,19 @@
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/libjingle/source/talk/app/webrtc/jsep.h"
-using WebKit::WebFrame;
-using WebKit::WebView;
+using blink::WebFrame;
+using blink::WebView;
namespace content {
-static webrtc::MediaStreamInterface* GetNativeMediaStream(
- const WebKit::WebMediaStream& stream) {
- MediaStreamExtraData* extra_data =
- static_cast<MediaStreamExtraData*>(stream.extraData());
- return extra_data->stream().get();
-}
-
-static webrtc::MediaStreamTrackInterface* GetNativeMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& component) {
- std::string track_id = UTF16ToUTF8(component.id());
- webrtc::MediaStreamInterface* native_stream = GetNativeMediaStream(stream);
- if (native_stream) {
- if (component.source().type() == WebKit::WebMediaStreamSource::TypeAudio) {
- return native_stream->FindAudioTrack(track_id);
- }
- if (component.source().type() == WebKit::WebMediaStreamSource::TypeVideo) {
- return native_stream->FindVideoTrack(track_id);
- }
- }
- NOTREACHED();
- return NULL;
-}
-
-MediaStreamCenter::MediaStreamCenter(WebKit::WebMediaStreamCenterClient* client,
+MediaStreamCenter::MediaStreamCenter(blink::WebMediaStreamCenterClient* client,
MediaStreamDependencyFactory* factory)
: rtc_factory_(factory), next_request_id_(0) {}
MediaStreamCenter::~MediaStreamCenter() {}
bool MediaStreamCenter::getMediaStreamTrackSources(
- const WebKit::WebMediaStreamTrackSourcesRequest& request) {
+ const blink::WebMediaStreamTrackSourcesRequest& request) {
if (!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableDeviceEnumeration)) {
int request_id = next_request_id_++;
@@ -76,47 +53,83 @@ bool MediaStreamCenter::getMediaStreamTrackSources(
return false;
}
+void MediaStreamCenter::didCreateMediaStreamTrack(
+ const blink::WebMediaStreamTrack& track) {
+ if (!rtc_factory_)
+ return;
+ rtc_factory_->CreateNativeMediaStreamTrack(track);
+}
+
void MediaStreamCenter::didEnableMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& component) {
- webrtc::MediaStreamTrackInterface* track =
- GetNativeMediaStreamTrack(stream, component);
- if (track)
- track->set_enabled(true);
+ const blink::WebMediaStreamTrack& track) {
+ webrtc::MediaStreamTrackInterface* native_track =
+ MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track);
+ if (native_track)
+ native_track->set_enabled(true);
}
void MediaStreamCenter::didDisableMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& component) {
- webrtc::MediaStreamTrackInterface* track =
- GetNativeMediaStreamTrack(stream, component);
- if (track)
- track->set_enabled(false);
+ const blink::WebMediaStreamTrack& track) {
+ webrtc::MediaStreamTrackInterface* native_track =
+ MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track);
+ if (native_track)
+ native_track->set_enabled(false);
+}
+
+bool MediaStreamCenter::didStopMediaStreamTrack(
+ const blink::WebMediaStreamTrack& track) {
+ DVLOG(1) << "MediaStreamCenter::didStopMediaStreamTrack";
+ blink::WebMediaStreamSource source = track.source();
+ MediaStreamSourceExtraData* extra_data =
+ static_cast<MediaStreamSourceExtraData*>(source.extraData());
+ if (!extra_data) {
+ DVLOG(1) << "didStopMediaStreamTrack called on a remote track.";
+ return false;
+ }
+
+ extra_data->OnLocalSourceStop();
+ return true;
}
void MediaStreamCenter::didStopLocalMediaStream(
- const WebKit::WebMediaStream& stream) {
+ const blink::WebMediaStream& stream) {
DVLOG(1) << "MediaStreamCenter::didStopLocalMediaStream";
MediaStreamExtraData* extra_data =
- static_cast<MediaStreamExtraData*>(stream.extraData());
+ static_cast<MediaStreamExtraData*>(stream.extraData());
if (!extra_data) {
NOTREACHED();
return;
}
+ // TODO(perkj): MediaStream::Stop is being deprecated. But for the moment we
+ // need to support the old behavior and the new. Since we only create one
+ // source object per actual device- we need to fake stopping a
+ // MediaStreamTrack by disabling it if the same device is used as source by
+ // multiple tracks. Note that disabling a track here, don't affect the
+ // enabled property in JS.
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
+ stream.audioTracks(audio_tracks);
+ for (size_t i = 0; i < audio_tracks.size(); ++i)
+ didDisableMediaStreamTrack(audio_tracks[i]);
+
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
+ stream.videoTracks(video_tracks);
+ for (size_t i = 0; i < video_tracks.size(); ++i)
+ didDisableMediaStreamTrack(video_tracks[i]);
+
extra_data->OnLocalStreamStop();
}
void MediaStreamCenter::didCreateMediaStream(
- WebKit::WebMediaStream& stream) {
+ blink::WebMediaStream& stream) {
if (!rtc_factory_)
return;
rtc_factory_->CreateNativeLocalMediaStream(&stream);
}
bool MediaStreamCenter::didAddMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& track) {
+ const blink::WebMediaStream& stream,
+ const blink::WebMediaStreamTrack& track) {
if (!rtc_factory_)
return false;
@@ -124,8 +137,8 @@ bool MediaStreamCenter::didAddMediaStreamTrack(
}
bool MediaStreamCenter::didRemoveMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& track) {
+ const blink::WebMediaStream& stream,
+ const blink::WebMediaStreamTrack& track) {
if (!rtc_factory_)
return false;
@@ -148,29 +161,29 @@ void MediaStreamCenter::OnGetSourcesComplete(
RequestMap::iterator request_it = requests_.find(request_id);
DCHECK(request_it != requests_.end());
- WebKit::WebVector<WebKit::WebSourceInfo> sourceInfos(devices.size());
+ blink::WebVector<blink::WebSourceInfo> sourceInfos(devices.size());
for (size_t i = 0; i < devices.size(); ++i) {
const MediaStreamDevice& device = devices[i].device;
DCHECK(device.type == MEDIA_DEVICE_AUDIO_CAPTURE ||
device.type == MEDIA_DEVICE_VIDEO_CAPTURE);
- WebKit::WebSourceInfo::VideoFacingMode video_facing;
+ blink::WebSourceInfo::VideoFacingMode video_facing;
switch (device.video_facing) {
case MEDIA_VIDEO_FACING_USER:
- video_facing = WebKit::WebSourceInfo::VideoFacingModeUser;
+ video_facing = blink::WebSourceInfo::VideoFacingModeUser;
break;
case MEDIA_VIDEO_FACING_ENVIRONMENT:
- video_facing = WebKit::WebSourceInfo::VideoFacingModeEnvironment;
+ video_facing = blink::WebSourceInfo::VideoFacingModeEnvironment;
break;
default:
- video_facing = WebKit::WebSourceInfo::VideoFacingModeNone;
+ video_facing = blink::WebSourceInfo::VideoFacingModeNone;
}
sourceInfos[i]
- .initialize(WebKit::WebString::fromUTF8(device.id),
+ .initialize(blink::WebString::fromUTF8(device.id),
device.type == MEDIA_DEVICE_AUDIO_CAPTURE
- ? WebKit::WebSourceInfo::SourceKindAudio
- : WebKit::WebSourceInfo::SourceKindVideo,
- WebKit::WebString::fromUTF8(device.name),
+ ? blink::WebSourceInfo::SourceKindAudio
+ : blink::WebSourceInfo::SourceKindVideo,
+ blink::WebString::fromUTF8(device.name),
video_facing);
}
request_it->second.requestSucceeded(sourceInfos);
diff --git a/chromium/content/renderer/media/media_stream_center.h b/chromium/content/renderer/media/media_stream_center.h
index 83a55f621a2..fbf1be73b55 100644
--- a/chromium/content/renderer/media/media_stream_center.h
+++ b/chromium/content/renderer/media/media_stream_center.h
@@ -17,7 +17,7 @@
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrackSourcesRequest.h"
-namespace WebKit {
+namespace blink {
class WebMediaStreamCenterClient;
}
@@ -25,39 +25,43 @@ namespace content {
class MediaStreamDependencyFactory;
class CONTENT_EXPORT MediaStreamCenter
- : NON_EXPORTED_BASE(public WebKit::WebMediaStreamCenter),
+ : NON_EXPORTED_BASE(public blink::WebMediaStreamCenter),
public RenderProcessObserver {
public:
- MediaStreamCenter(WebKit::WebMediaStreamCenterClient* client,
+ MediaStreamCenter(blink::WebMediaStreamCenterClient* client,
MediaStreamDependencyFactory* factory);
virtual ~MediaStreamCenter();
+ private:
virtual bool getMediaStreamTrackSources(
- const WebKit::WebMediaStreamTrackSourcesRequest& request);
+ const blink::WebMediaStreamTrackSourcesRequest& request) OVERRIDE;
+
+ virtual void didCreateMediaStreamTrack(
+ const blink::WebMediaStreamTrack& track) OVERRIDE;
virtual void didEnableMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& component);
+ const blink::WebMediaStreamTrack& track) OVERRIDE;
virtual void didDisableMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& component);
+ const blink::WebMediaStreamTrack& track) OVERRIDE;
virtual void didStopLocalMediaStream(
- const WebKit::WebMediaStream& stream);
+ const blink::WebMediaStream& stream) OVERRIDE;
+
+ virtual bool didStopMediaStreamTrack(
+ const blink::WebMediaStreamTrack& track) OVERRIDE;
virtual void didCreateMediaStream(
- WebKit::WebMediaStream& stream);
+ blink::WebMediaStream& stream) OVERRIDE;
virtual bool didAddMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& track);
+ const blink::WebMediaStream& stream,
+ const blink::WebMediaStreamTrack& track) OVERRIDE;
virtual bool didRemoveMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& track);
+ const blink::WebMediaStream& stream,
+ const blink::WebMediaStreamTrack& track) OVERRIDE;
- private:
// RenderProcessObserver implementation.
virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -72,7 +76,7 @@ class CONTENT_EXPORT MediaStreamCenter
// requests.
int next_request_id_;
- typedef std::map<int, WebKit::WebMediaStreamTrackSourcesRequest> RequestMap;
+ typedef std::map<int, blink::WebMediaStreamTrackSourcesRequest> RequestMap;
// Maps request ids to request objects.
RequestMap requests_;
diff --git a/chromium/content/renderer/media/media_stream_dependency_factory.cc b/chromium/content/renderer/media/media_stream_dependency_factory.cc
index 23f68e9fa5e..8da7b14cb71 100644
--- a/chromium/content/renderer/media/media_stream_dependency_factory.cc
+++ b/chromium/content/renderer/media/media_stream_dependency_factory.cc
@@ -11,6 +11,8 @@
#include "base/synchronization/waitable_event.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/media/media_stream_source_extra_data.h"
+#include "content/renderer/media/media_stream_track_extra_data.h"
+#include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/peer_connection_identity_service.h"
#include "content/renderer/media/rtc_media_constraints.h"
#include "content/renderer/media/rtc_peer_connection_handler.h"
@@ -21,7 +23,6 @@
#include "content/renderer/media/webaudio_capturer_source.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
-#include "content/renderer/media/webrtc_logging_initializer.h"
#include "content/renderer/media/webrtc_uma_histograms.h"
#include "content/renderer/p2p/ipc_network_manager.h"
#include "content/renderer/p2p/ipc_socket_factory.h"
@@ -48,11 +49,11 @@
#include "content/renderer/media/rtc_video_decoder_factory_tv.h"
#endif
-namespace content {
+#if defined(OS_ANDROID)
+#include "media/base/android/media_codec_bridge.h"
+#endif
-// The constraint key for the PeerConnection constructor for enabling diagnostic
-// WebRTC logging. It's a Google specific key, hence the "goog" prefix.
-const char kWebRtcLoggingConstraint[] = "googLog";
+namespace content {
// Constant constraint keys which enables default audio constraints on
// mediastreams with audio.
@@ -62,6 +63,11 @@ struct {
} const kDefaultAudioConstraints[] = {
{ webrtc::MediaConstraintsInterface::kEchoCancellation,
webrtc::MediaConstraintsInterface::kValueTrue },
+#if defined(OS_CHROMEOS) || defined(OS_MACOSX)
+ // Enable the extended filter mode AEC on platforms with known echo issues.
+ { webrtc::MediaConstraintsInterface::kExperimentalEchoCancellation,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+#endif
{ webrtc::MediaConstraintsInterface::kAutoGainControl,
webrtc::MediaConstraintsInterface::kValueTrue },
{ webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl,
@@ -72,6 +78,15 @@ struct {
webrtc::MediaConstraintsInterface::kValueTrue },
};
+// Map of corresponding media constraints and platform effects.
+struct {
+ const char* constraint;
+ const media::AudioParameters::PlatformEffectsMask effect;
+} const kConstraintEffectMap[] = {
+ { webrtc::MediaConstraintsInterface::kEchoCancellation,
+ media::AudioParameters::ECHO_CANCELLER},
+};
+
// Merge |constraints| with |kDefaultAudioConstraints|. For any key which exists
// in both, the value from |constraints| is maintained, including its
// mandatory/optional status. New values from |kDefaultAudioConstraints| will
@@ -96,7 +111,7 @@ class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
P2PSocketDispatcher* socket_dispatcher,
talk_base::NetworkManager* network_manager,
talk_base::PacketSocketFactory* socket_factory,
- WebKit::WebFrame* web_frame)
+ blink::WebFrame* web_frame)
: socket_dispatcher_(socket_dispatcher),
network_manager_(network_manager),
socket_factory_(socket_factory),
@@ -145,14 +160,14 @@ class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
talk_base::NetworkManager* network_manager_;
talk_base::PacketSocketFactory* socket_factory_;
// Raw ptr to the WebFrame that created the P2PPortAllocatorFactory.
- WebKit::WebFrame* web_frame_;
+ blink::WebFrame* web_frame_;
};
// SourceStateObserver is a help class used for observing the startup state
// transition of webrtc media sources such as a camera or microphone.
// An instance of the object deletes itself after use.
// Usage:
-// 1. Create an instance of the object with the WebKit::WebMediaStream
+// 1. Create an instance of the object with the blink::WebMediaStream
// the observed sources belongs to a callback.
// 2. Add the sources to the observer using AddSource.
// 3. Call StartObserving()
@@ -162,7 +177,7 @@ class SourceStateObserver : public webrtc::ObserverInterface,
public base::NonThreadSafe {
public:
SourceStateObserver(
- WebKit::WebMediaStream* web_stream,
+ blink::WebMediaStream* web_stream,
const MediaStreamDependencyFactory::MediaSourcesCreatedCallback& callback)
: web_stream_(web_stream),
ready_callback_(callback),
@@ -216,7 +231,7 @@ class SourceStateObserver : public webrtc::ObserverInterface,
}
}
- WebKit::WebMediaStream* web_stream_;
+ blink::WebMediaStream* web_stream_;
MediaStreamDependencyFactory::MediaSourcesCreatedCallback ready_callback_;
bool live_;
typedef std::vector<scoped_refptr<webrtc::MediaSourceInterface> >
@@ -242,9 +257,9 @@ MediaStreamDependencyFactory::~MediaStreamDependencyFactory() {
CleanupPeerConnectionFactory();
}
-WebKit::WebRTCPeerConnectionHandler*
+blink::WebRTCPeerConnectionHandler*
MediaStreamDependencyFactory::CreateRTCPeerConnectionHandler(
- WebKit::WebRTCPeerConnectionHandlerClient* client) {
+ blink::WebRTCPeerConnectionHandlerClient* client) {
// Save histogram data so we can see how much PeerConnetion is used.
// The histogram counts the number of calls to the JS API
// webKitRTCPeerConnection.
@@ -258,9 +273,9 @@ MediaStreamDependencyFactory::CreateRTCPeerConnectionHandler(
void MediaStreamDependencyFactory::CreateNativeMediaSources(
int render_view_id,
- const WebKit::WebMediaConstraints& audio_constraints,
- const WebKit::WebMediaConstraints& video_constraints,
- WebKit::WebMediaStream* web_stream,
+ const blink::WebMediaConstraints& audio_constraints,
+ const blink::WebMediaConstraints& video_constraints,
+ blink::WebMediaStream* web_stream,
const MediaSourcesCreatedCallback& sources_created) {
DVLOG(1) << "MediaStreamDependencyFactory::CreateNativeMediaSources()";
if (!EnsurePeerConnectionFactory()) {
@@ -275,17 +290,19 @@ void MediaStreamDependencyFactory::CreateNativeMediaSources(
// Create local video sources.
RTCMediaConstraints native_video_constraints(video_constraints);
- WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
web_stream->videoTracks(video_tracks);
for (size_t i = 0; i < video_tracks.size(); ++i) {
- const WebKit::WebMediaStreamSource& source = video_tracks[i].source();
+ const blink::WebMediaStreamSource& source = video_tracks[i].source();
MediaStreamSourceExtraData* source_data =
static_cast<MediaStreamSourceExtraData*>(source.extraData());
- if (!source_data) {
- // TODO(perkj): Implement support for sources from remote MediaStreams.
- NOTIMPLEMENTED();
+
+ // Check if the source has already been created. This happens when the same
+ // source is used in multiple MediaStreams as a result of calling
+ // getUserMedia.
+ if (source_data->video_source())
continue;
- }
+
const bool is_screencast =
source_data->device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE ||
source_data->device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE;
@@ -300,26 +317,51 @@ void MediaStreamDependencyFactory::CreateNativeMediaSources(
// microphone or tab audio.
RTCMediaConstraints native_audio_constraints(audio_constraints);
ApplyFixedAudioConstraints(&native_audio_constraints);
- WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
web_stream->audioTracks(audio_tracks);
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kEnableWebRtcAecRecordings)) {
- native_audio_constraints.AddOptional(
- RTCMediaConstraints::kInternalAecDump, "true");
- }
for (size_t i = 0; i < audio_tracks.size(); ++i) {
- const WebKit::WebMediaStreamSource& source = audio_tracks[i].source();
+ const blink::WebMediaStreamSource& source = audio_tracks[i].source();
MediaStreamSourceExtraData* source_data =
static_cast<MediaStreamSourceExtraData*>(source.extraData());
- if (!source_data) {
- // TODO(henrika): Implement support for sources from remote MediaStreams.
- NOTIMPLEMENTED();
+
+ // Check if the source has already been created. This happens when the same
+ // source is used in multiple MediaStreams as a result of calling
+ // getUserMedia.
+ if (source_data->local_audio_source())
continue;
- }
// TODO(xians): Create a new capturer for difference microphones when we
// support multiple microphones. See issue crbug/262117 .
- const StreamDeviceInfo device_info = source_data->device_info();
+ StreamDeviceInfo device_info = source_data->device_info();
+ RTCMediaConstraints constraints = native_audio_constraints;
+
+ // If any platform effects are available, check them against the
+ // constraints. Disable effects to match false constraints, but if a
+ // constraint is true, set the constraint to false to later disable the
+ // software effect.
+ int effects = device_info.device.input.effects;
+ if (effects != media::AudioParameters::NO_EFFECTS) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kConstraintEffectMap); ++i) {
+ bool value;
+ if (!webrtc::FindConstraint(&constraints,
+ kConstraintEffectMap[i].constraint, &value, NULL) || !value) {
+ // If the constraint is false, or does not exist, disable the platform
+ // effect.
+ effects &= ~kConstraintEffectMap[i].effect;
+ DVLOG(1) << "Disabling constraint: "
+ << kConstraintEffectMap[i].constraint;
+ } else if (effects & kConstraintEffectMap[i].effect) {
+ // If the constraint is true, leave the platform effect enabled, and
+ // set the constraint to false to later disable the software effect.
+ constraints.AddMandatory(kConstraintEffectMap[i].constraint,
+ webrtc::MediaConstraintsInterface::kValueFalse, true);
+ DVLOG(1) << "Disabling platform effect: "
+ << kConstraintEffectMap[i].constraint;
+ }
+ }
+ device_info.device.input.effects = effects;
+ }
+
scoped_refptr<WebRtcAudioCapturer> capturer(
MaybeCreateAudioCapturer(render_view_id, device_info));
if (!capturer.get()) {
@@ -332,11 +374,12 @@ void MediaStreamDependencyFactory::CreateNativeMediaSources(
// be called multiple times which is likely also a bug.
return;
}
+ source_data->SetAudioCapturer(capturer);
// Creates a LocalAudioSource object which holds audio options.
// TODO(xians): The option should apply to the track instead of the source.
source_data->SetLocalAudioSource(
- CreateLocalAudioSource(&native_audio_constraints).get());
+ CreateLocalAudioSource(&constraints).get());
source_observer->AddSource(source_data->local_audio_source());
}
@@ -344,7 +387,7 @@ void MediaStreamDependencyFactory::CreateNativeMediaSources(
}
void MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
- WebKit::WebMediaStream* web_stream) {
+ blink::WebMediaStream* web_stream) {
DVLOG(1) << "MediaStreamDependencyFactory::CreateNativeLocalMediaStream()";
if (!EnsurePeerConnectionFactory()) {
DVLOG(1) << "EnsurePeerConnectionFactory() failed!";
@@ -359,14 +402,14 @@ void MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
web_stream->setExtraData(extra_data);
// Add audio tracks.
- WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
web_stream->audioTracks(audio_tracks);
for (size_t i = 0; i < audio_tracks.size(); ++i) {
AddNativeMediaStreamTrack(*web_stream, audio_tracks[i]);
}
// Add video tracks.
- WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
web_stream->videoTracks(video_tracks);
for (size_t i = 0; i < video_tracks.size(); ++i) {
AddNativeMediaStreamTrack(*web_stream, video_tracks[i]);
@@ -374,7 +417,7 @@ void MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
}
void MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
- WebKit::WebMediaStream* web_stream,
+ blink::WebMediaStream* web_stream,
const MediaStreamExtraData::StreamStopCallback& stream_stop) {
CreateNativeLocalMediaStream(web_stream);
@@ -383,15 +426,11 @@ void MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
extra_data->SetLocalStreamStopCallback(stream_stop);
}
-bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& track) {
- MediaStreamExtraData* extra_data =
- static_cast<MediaStreamExtraData*>(stream.extraData());
- webrtc::MediaStreamInterface* native_stream = extra_data->stream().get();
- DCHECK(native_stream);
-
- WebKit::WebMediaStreamSource source = track.source();
+scoped_refptr<webrtc::AudioTrackInterface>
+MediaStreamDependencyFactory::CreateNativeAudioMediaStreamTrack(
+ const blink::WebMediaStreamTrack& track) {
+ blink::WebMediaStreamSource source = track.source();
+ DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio);
MediaStreamSourceExtraData* source_data =
static_cast<MediaStreamSourceExtraData*>(source.extraData());
@@ -399,15 +438,9 @@ bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack(
// right now they're on the source, so we fetch them from there.
RTCMediaConstraints track_constraints(source.constraints());
- WebKit::WebMediaStreamSource::Type type = track.source().type();
- DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio ||
- type == WebKit::WebMediaStreamSource::TypeVideo);
-
- if (type == WebKit::WebMediaStreamSource::TypeAudio) {
- // Apply default audio constraints that enable echo cancellation,
- // automatic gain control, noise suppression and high-pass filter.
- ApplyFixedAudioConstraints(&track_constraints);
- }
+ // Apply default audio constraints that enable echo cancellation,
+ // automatic gain control, noise suppression and high-pass filter.
+ ApplyFixedAudioConstraints(&track_constraints);
scoped_refptr<WebAudioCapturerSource> webaudio_source;
if (!source_data) {
@@ -421,40 +454,111 @@ bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack(
// TODO(perkj): Implement support for sources from
// remote MediaStreams.
NOTIMPLEMENTED();
- return false;
+ return NULL;
}
}
std::string track_id = UTF16ToUTF8(track.id());
- if (source.type() == WebKit::WebMediaStreamSource::TypeAudio) {
- scoped_refptr<WebRtcAudioCapturer> capturer;
- if (GetWebRtcAudioDevice())
- capturer = GetWebRtcAudioDevice()->GetDefaultCapturer();
-
- scoped_refptr<webrtc::AudioTrackInterface> audio_track(
- CreateLocalAudioTrack(track_id,
- capturer,
- webaudio_source.get(),
- source_data->local_audio_source(),
- &track_constraints));
- audio_track->set_enabled(track.isEnabled());
- if (capturer.get()) {
- WebKit::WebMediaStreamTrack writable_track = track;
- writable_track.setSourceProvider(capturer->audio_source_provider());
+ scoped_refptr<WebRtcAudioCapturer> capturer;
+ if (GetWebRtcAudioDevice())
+ capturer = GetWebRtcAudioDevice()->GetDefaultCapturer();
+
+ scoped_refptr<webrtc::AudioTrackInterface> audio_track(
+ CreateLocalAudioTrack(track_id,
+ capturer,
+ webaudio_source.get(),
+ source_data->local_audio_source(),
+ &track_constraints));
+ AddNativeTrackToBlinkTrack(audio_track.get(), track, true);
+
+ audio_track->set_enabled(track.isEnabled());
+
+ // Pass the pointer of the source provider to the blink audio track.
+ blink::WebMediaStreamTrack writable_track = track;
+ writable_track.setSourceProvider(static_cast<WebRtcLocalAudioTrack*>(
+ audio_track.get())->audio_source_provider());
+
+ return audio_track;
+}
+
+scoped_refptr<webrtc::VideoTrackInterface>
+MediaStreamDependencyFactory::CreateNativeVideoMediaStreamTrack(
+ const blink::WebMediaStreamTrack& track) {
+ blink::WebMediaStreamSource source = track.source();
+ DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeVideo);
+ MediaStreamSourceExtraData* source_data =
+ static_cast<MediaStreamSourceExtraData*>(source.extraData());
+
+ if (!source_data) {
+ // TODO(perkj): Implement support for sources from
+ // remote MediaStreams.
+ NOTIMPLEMENTED();
+ return NULL;
+ }
+
+ std::string track_id = UTF16ToUTF8(track.id());
+ scoped_refptr<webrtc::VideoTrackInterface> video_track(
+ CreateLocalVideoTrack(track_id, source_data->video_source()));
+ AddNativeTrackToBlinkTrack(video_track.get(), track, true);
+
+ video_track->set_enabled(track.isEnabled());
+
+ return video_track;
+}
+
+void MediaStreamDependencyFactory::CreateNativeMediaStreamTrack(
+ const blink::WebMediaStreamTrack& track) {
+ DCHECK(!track.isNull() && !track.extraData());
+ DCHECK(!track.source().isNull());
+
+ switch (track.source().type()) {
+ case blink::WebMediaStreamSource::TypeAudio:
+ CreateNativeAudioMediaStreamTrack(track);
+ break;
+ case blink::WebMediaStreamSource::TypeVideo:
+ CreateNativeVideoMediaStreamTrack(track);
+ break;
+ }
+}
+
+bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack(
+ const blink::WebMediaStream& stream,
+ const blink::WebMediaStreamTrack& track) {
+ webrtc::MediaStreamInterface* native_stream = GetNativeMediaStream(stream);
+ DCHECK(native_stream);
+
+ switch (track.source().type()) {
+ case blink::WebMediaStreamSource::TypeAudio: {
+ scoped_refptr<webrtc::AudioTrackInterface> native_audio_track;
+ if (!track.extraData()) {
+ native_audio_track = CreateNativeAudioMediaStreamTrack(track);
+ } else {
+ native_audio_track = static_cast<webrtc::AudioTrackInterface*>(
+ GetNativeMediaStreamTrack(track));
+ }
+
+ return native_audio_track.get() &&
+ native_stream->AddTrack(native_audio_track);
+ }
+ case blink::WebMediaStreamSource::TypeVideo: {
+ scoped_refptr<webrtc::VideoTrackInterface> native_video_track;
+ if (!track.extraData()) {
+ native_video_track = CreateNativeVideoMediaStreamTrack(track);
+ } else {
+ native_video_track = static_cast<webrtc::VideoTrackInterface*>(
+ GetNativeMediaStreamTrack(track));
+ }
+
+ return native_video_track.get() &&
+ native_stream->AddTrack(native_video_track);
}
- return native_stream->AddTrack(audio_track.get());
- } else {
- DCHECK(source.type() == WebKit::WebMediaStreamSource::TypeVideo);
- scoped_refptr<webrtc::VideoTrackInterface> video_track(
- CreateLocalVideoTrack(track_id, source_data->video_source()));
- video_track->set_enabled(track.isEnabled());
- return native_stream->AddTrack(video_track.get());
}
+ return false;
}
bool MediaStreamDependencyFactory::AddNativeVideoMediaTrack(
const std::string& track_id,
- WebKit::WebMediaStream* stream,
+ blink::WebMediaStream* stream,
cricket::VideoCapturer* capturer) {
if (!stream) {
LOG(ERROR) << "AddNativeVideoMediaTrack called with null WebMediaStream.";
@@ -466,20 +570,21 @@ bool MediaStreamDependencyFactory::AddNativeVideoMediaTrack(
CreateLocalVideoTrack(track_id, capturer);
// Add the native track to native stream
- MediaStreamExtraData* extra_data =
- static_cast<MediaStreamExtraData*>(stream->extraData());
- DCHECK(extra_data);
- webrtc::MediaStreamInterface* native_stream = extra_data->stream().get();
+ webrtc::MediaStreamInterface* native_stream =
+ GetNativeMediaStream(*stream);
+ DCHECK(native_stream);
native_stream->AddTrack(native_track.get());
// Create a new webkit video track.
- WebKit::WebMediaStreamTrack webkit_track;
- WebKit::WebMediaStreamSource webkit_source;
- WebKit::WebString webkit_track_id(UTF8ToUTF16(track_id));
- WebKit::WebMediaStreamSource::Type type =
- WebKit::WebMediaStreamSource::TypeVideo;
+ blink::WebMediaStreamTrack webkit_track;
+ blink::WebMediaStreamSource webkit_source;
+ blink::WebString webkit_track_id(UTF8ToUTF16(track_id));
+ blink::WebMediaStreamSource::Type type =
+ blink::WebMediaStreamSource::TypeVideo;
webkit_source.initialize(webkit_track_id, type, webkit_track_id);
+
webkit_track.initialize(webkit_track_id, webkit_source);
+ AddNativeTrackToBlinkTrack(native_track.get(), webkit_track, true);
// Add the track to WebMediaStream.
stream->addTrack(webkit_track);
@@ -487,71 +592,82 @@ bool MediaStreamDependencyFactory::AddNativeVideoMediaTrack(
}
bool MediaStreamDependencyFactory::RemoveNativeMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& track) {
+ const blink::WebMediaStream& stream,
+ const blink::WebMediaStreamTrack& track) {
MediaStreamExtraData* extra_data =
static_cast<MediaStreamExtraData*>(stream.extraData());
webrtc::MediaStreamInterface* native_stream = extra_data->stream().get();
DCHECK(native_stream);
-
- WebKit::WebMediaStreamSource::Type type = track.source().type();
- DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio ||
- type == WebKit::WebMediaStreamSource::TypeVideo);
-
std::string track_id = UTF16ToUTF8(track.id());
- if (type == WebKit::WebMediaStreamSource::TypeAudio) {
- // Remove the source provider as the track is going away.
- WebKit::WebMediaStreamTrack writable_track = track;
- writable_track.setSourceProvider(NULL);
- return native_stream->RemoveTrack(native_stream->FindAudioTrack(track_id));
- }
-
- CHECK_EQ(type, WebKit::WebMediaStreamSource::TypeVideo);
- return native_stream->RemoveTrack(native_stream->FindVideoTrack(track_id));
+ switch (track.source().type()) {
+ case blink::WebMediaStreamSource::TypeAudio:
+ return native_stream->RemoveTrack(
+ native_stream->FindAudioTrack(track_id));
+ case blink::WebMediaStreamSource::TypeVideo:
+ return native_stream->RemoveTrack(
+ native_stream->FindVideoTrack(track_id));
+ }
+ return false;
}
bool MediaStreamDependencyFactory::CreatePeerConnectionFactory() {
+ DCHECK(!pc_factory_.get());
+ DCHECK(!audio_device_.get());
DVLOG(1) << "MediaStreamDependencyFactory::CreatePeerConnectionFactory()";
- if (!pc_factory_.get()) {
- DCHECK(!audio_device_.get());
- audio_device_ = new WebRtcAudioDeviceImpl();
-
- scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
- scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
-
- const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
- scoped_refptr<base::MessageLoopProxy> media_loop_proxy =
- RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy();
- scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories =
- RenderThreadImpl::current()->GetGpuFactories(media_loop_proxy);
+
+ scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
+ scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
+
+ const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories =
+ RenderThreadImpl::current()->GetGpuFactories();
#if !defined(GOOGLE_TV)
- if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWDecoding)) {
- if (gpu_factories)
- decoder_factory.reset(new RTCVideoDecoderFactory(gpu_factories));
- }
+ if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWDecoding)) {
+ if (gpu_factories)
+ decoder_factory.reset(new RTCVideoDecoderFactory(gpu_factories));
+ }
#else
- // PeerConnectionFactory will hold the ownership of this
- // VideoDecoderFactory.
- decoder_factory.reset(decoder_factory_tv_ = new RTCVideoDecoderFactoryTv());
+ // PeerConnectionFactory will hold the ownership of this
+ // VideoDecoderFactory.
+ decoder_factory.reset(decoder_factory_tv_ = new RTCVideoDecoderFactoryTv());
#endif
- if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) {
- if (gpu_factories)
- encoder_factory.reset(new RTCVideoEncoderFactory(gpu_factories));
- }
+ if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) {
+ if (gpu_factories)
+ encoder_factory.reset(new RTCVideoEncoderFactory(gpu_factories));
+ }
- scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory(
- webrtc::CreatePeerConnectionFactory(worker_thread_,
- signaling_thread_,
- audio_device_.get(),
- encoder_factory.release(),
- decoder_factory.release()));
- if (factory.get())
- pc_factory_ = factory;
- else
- audio_device_ = NULL;
+#if defined(OS_ANDROID)
+ if (!media::MediaCodecBridge::IsAvailable() ||
+ !media::MediaCodecBridge::SupportsSetParameters()) {
+ encoder_factory.reset();
}
- return pc_factory_.get() != NULL;
+#endif
+
+ scoped_refptr<WebRtcAudioDeviceImpl> audio_device(
+ new WebRtcAudioDeviceImpl());
+
+ scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory(
+ webrtc::CreatePeerConnectionFactory(worker_thread_,
+ signaling_thread_,
+ audio_device.get(),
+ encoder_factory.release(),
+ decoder_factory.release()));
+ if (!factory.get()) {
+ return false;
+ }
+
+ audio_device_ = audio_device;
+ pc_factory_ = factory;
+ webrtc::PeerConnectionFactoryInterface::Options factory_options;
+ factory_options.enable_aec_dump =
+ cmd_line->HasSwitch(switches::kEnableWebRtcAecRecordings);
+ factory_options.disable_sctp_data_channels =
+ cmd_line->HasSwitch(switches::kDisableSCTPDataChannels);
+ factory_options.disable_encryption =
+ cmd_line->HasSwitch(switches::kDisableWebRtcEncryption);
+ pc_factory_->SetOptions(factory_options);
+ return true;
}
bool MediaStreamDependencyFactory::PeerConnectionFactoryCreated() {
@@ -562,24 +678,11 @@ scoped_refptr<webrtc::PeerConnectionInterface>
MediaStreamDependencyFactory::CreatePeerConnection(
const webrtc::PeerConnectionInterface::IceServers& ice_servers,
const webrtc::MediaConstraintsInterface* constraints,
- WebKit::WebFrame* web_frame,
+ blink::WebFrame* web_frame,
webrtc::PeerConnectionObserver* observer) {
CHECK(web_frame);
CHECK(observer);
- webrtc::MediaConstraintsInterface::Constraints optional_constraints =
- constraints->GetOptional();
- std::string constraint_value;
- if (optional_constraints.FindFirst(kWebRtcLoggingConstraint,
- &constraint_value)) {
- std::string url = web_frame->document().url().spec();
- RenderThreadImpl::current()->GetIOMessageLoopProxy()->PostTask(
- FROM_HERE, base::Bind(
- &InitWebRtcLogging,
- constraint_value,
- url));
- }
-
scoped_refptr<P2PPortAllocatorFactory> pa_factory =
new talk_base::RefCountedObject<P2PPortAllocatorFactory>(
p2p_socket_dispatcher_.get(),
@@ -588,7 +691,7 @@ MediaStreamDependencyFactory::CreatePeerConnection(
web_frame);
PeerConnectionIdentityService* identity_service =
- PeerConnectionIdentityService::Create(
+ new PeerConnectionIdentityService(
GURL(web_frame->document().url().spec()).GetOrigin());
return pc_factory_->CreatePeerConnection(ice_servers,
@@ -628,7 +731,7 @@ MediaStreamDependencyFactory::CreateLocalVideoSource(
scoped_refptr<WebAudioCapturerSource>
MediaStreamDependencyFactory::CreateWebAudioSource(
- WebKit::WebMediaStreamSource* source,
+ blink::WebMediaStreamSource* source,
RTCMediaConstraints* constraints) {
DVLOG(1) << "MediaStreamDependencyFactory::CreateWebAudioSource()";
DCHECK(GetWebRtcAudioDevice());
@@ -843,7 +946,10 @@ MediaStreamDependencyFactory::MaybeCreateAudioCapturer(
device_info.device.input.sample_rate,
device_info.device.input.frames_per_buffer,
device_info.session_id,
- device_info.device.id)) {
+ device_info.device.id,
+ device_info.device.matched_output.sample_rate,
+ device_info.device.matched_output.frames_per_buffer,
+ device_info.device.input.effects)) {
return NULL;
}
@@ -854,4 +960,41 @@ MediaStreamDependencyFactory::MaybeCreateAudioCapturer(
return capturer;
}
+void MediaStreamDependencyFactory::AddNativeTrackToBlinkTrack(
+ webrtc::MediaStreamTrackInterface* native_track,
+ const blink::WebMediaStreamTrack& webkit_track,
+ bool is_local_track) {
+ DCHECK(!webkit_track.isNull() && !webkit_track.extraData());
+ blink::WebMediaStreamTrack track = webkit_track;
+
+ if (track.source().type() == blink::WebMediaStreamSource::TypeVideo) {
+ track.setExtraData(new MediaStreamVideoTrack(
+ static_cast<webrtc::VideoTrackInterface*>(native_track),
+ is_local_track));
+ } else {
+ track.setExtraData(new MediaStreamTrackExtraData(native_track,
+ is_local_track));
+ }
+}
+
+webrtc::MediaStreamInterface*
+MediaStreamDependencyFactory::GetNativeMediaStream(
+ const blink::WebMediaStream& stream) {
+ if (stream.isNull())
+ return NULL;
+ MediaStreamExtraData* extra_data =
+ static_cast<MediaStreamExtraData*>(stream.extraData());
+ return extra_data ? extra_data->stream().get() : NULL;
+}
+
+webrtc::MediaStreamTrackInterface*
+MediaStreamDependencyFactory::GetNativeMediaStreamTrack(
+ const blink::WebMediaStreamTrack& track) {
+ if (track.isNull())
+ return NULL;
+ MediaStreamTrackExtraData* extra_data =
+ static_cast<MediaStreamTrackExtraData*>(track.extraData());
+ return extra_data ? extra_data->track().get() : NULL;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_dependency_factory.h b/chromium/content/renderer/media/media_stream_dependency_factory.h
index a728d885041..d0759708b8f 100644
--- a/chromium/content/renderer/media/media_stream_dependency_factory.h
+++ b/chromium/content/renderer/media/media_stream_dependency_factory.h
@@ -30,7 +30,7 @@ namespace webrtc {
class PeerConnection;
}
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebMediaConstraints;
class WebMediaStream;
@@ -60,7 +60,7 @@ class CONTENT_EXPORT MediaStreamDependencyFactory
: NON_EXPORTED_BASE(public base::NonThreadSafe) {
public:
// MediaSourcesCreatedCallback is used in CreateNativeMediaSources.
- typedef base::Callback<void(WebKit::WebMediaStream* web_stream,
+ typedef base::Callback<void(blink::WebMediaStream* web_stream,
bool live)> MediaSourcesCreatedCallback;
MediaStreamDependencyFactory(
VideoCaptureImplManager* vc_manager,
@@ -69,8 +69,8 @@ class CONTENT_EXPORT MediaStreamDependencyFactory
// Create a RTCPeerConnectionHandler object that implements the
// WebKit WebRTCPeerConnectionHandler interface.
- WebKit::WebRTCPeerConnectionHandler* CreateRTCPeerConnectionHandler(
- WebKit::WebRTCPeerConnectionHandlerClient* client);
+ blink::WebRTCPeerConnectionHandler* CreateRTCPeerConnectionHandler(
+ blink::WebRTCPeerConnectionHandlerClient* client);
// CreateNativeMediaSources creates libjingle representations of
// the underlying sources to the tracks in |web_stream|.
@@ -81,37 +81,41 @@ class CONTENT_EXPORT MediaStreamDependencyFactory
// |audio_constraints| and |video_constraints| set parameters for the sources.
void CreateNativeMediaSources(
int render_view_id,
- const WebKit::WebMediaConstraints& audio_constraints,
- const WebKit::WebMediaConstraints& video_constraints,
- WebKit::WebMediaStream* web_stream,
+ const blink::WebMediaConstraints& audio_constraints,
+ const blink::WebMediaConstraints& video_constraints,
+ blink::WebMediaStream* web_stream,
const MediaSourcesCreatedCallback& sources_created);
// Creates a libjingle representation of a MediaStream and stores
// it in the extra data field of |web_stream|.
void CreateNativeLocalMediaStream(
- WebKit::WebMediaStream* web_stream);
+ blink::WebMediaStream* web_stream);
// Creates a libjingle representation of a MediaStream and stores
// it in the extra data field of |web_stream|.
// |stream_stopped| is a callback that is run when a MediaStream have been
// stopped.
void CreateNativeLocalMediaStream(
- WebKit::WebMediaStream* web_stream,
+ blink::WebMediaStream* web_stream,
const MediaStreamExtraData::StreamStopCallback& stream_stop);
+ // Creates a libjingle representation of a MediaStreamTrack and stores
+ // it in the extra data field of |track|.
+ void CreateNativeMediaStreamTrack(const blink::WebMediaStreamTrack& track);
+
// Adds a libjingle representation of a MediaStreamTrack to |stream| based
// on the source of |track|.
- bool AddNativeMediaStreamTrack(const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& track);
+ bool AddNativeMediaStreamTrack(const blink::WebMediaStream& stream,
+ const blink::WebMediaStreamTrack& track);
// Creates and adds libjingle representation of a MediaStreamTrack to |stream|
// based on the desired |track_id| and |capturer|.
bool AddNativeVideoMediaTrack(const std::string& track_id,
- WebKit::WebMediaStream* stream,
+ blink::WebMediaStream* stream,
cricket::VideoCapturer* capturer);
- bool RemoveNativeMediaStreamTrack(const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& track);
+ bool RemoveNativeMediaStreamTrack(const blink::WebMediaStream& stream,
+ const blink::WebMediaStreamTrack& track);
// Asks the libjingle PeerConnection factory to create a libjingle
// PeerConnection object.
@@ -120,7 +124,7 @@ class CONTENT_EXPORT MediaStreamDependencyFactory
CreatePeerConnection(
const webrtc::PeerConnectionInterface::IceServers& ice_servers,
const webrtc::MediaConstraintsInterface* constraints,
- WebKit::WebFrame* web_frame,
+ blink::WebFrame* web_frame,
webrtc::PeerConnectionObserver* observer);
// Creates a libjingle representation of a Session description. Used by a
@@ -142,6 +146,17 @@ class CONTENT_EXPORT MediaStreamDependencyFactory
RTCVideoDecoderFactoryTv* decoder_factory_tv() { return decoder_factory_tv_; }
#endif
+ static void AddNativeTrackToBlinkTrack(
+ webrtc::MediaStreamTrackInterface* native_track,
+ const blink::WebMediaStreamTrack& webkit_track,
+ bool is_local_track);
+
+ static webrtc::MediaStreamInterface* GetNativeMediaStream(
+ const blink::WebMediaStream& stream);
+
+ static webrtc::MediaStreamTrackInterface* GetNativeMediaStreamTrack(
+ const blink::WebMediaStreamTrack& track);
+
protected:
// Asks the PeerConnection factory to create a Local MediaStream object.
virtual scoped_refptr<webrtc::MediaStreamInterface>
@@ -166,7 +181,7 @@ class CONTENT_EXPORT MediaStreamDependencyFactory
// The |constraints| will be modified to include the default, mandatory
// WebAudio constraints.
virtual scoped_refptr<WebAudioCapturerSource> CreateWebAudioSource(
- WebKit::WebMediaStreamSource* source, RTCMediaConstraints* constraints);
+ blink::WebMediaStreamSource* source, RTCMediaConstraints* constraints);
// Asks the PeerConnection factory to create a Local AudioTrack object.
virtual scoped_refptr<webrtc::AudioTrackInterface>
@@ -209,9 +224,11 @@ class CONTENT_EXPORT MediaStreamDependencyFactory
void DeleteIpcNetworkManager();
void CleanupPeerConnectionFactory();
- void CreateWebRtcLoggingHandler(WebRtcLoggingMessageFilter* filter,
- const std::string& app_session_id,
- const std::string& app_url);
+ scoped_refptr<webrtc::AudioTrackInterface>
+ CreateNativeAudioMediaStreamTrack(const blink::WebMediaStreamTrack& track);
+
+ scoped_refptr<webrtc::VideoTrackInterface>
+ CreateNativeVideoMediaStreamTrack(const blink::WebMediaStreamTrack& track);
// We own network_manager_, must be deleted on the worker thread.
// The network manager uses |p2p_socket_dispatcher_|.
diff --git a/chromium/content/renderer/media/media_stream_dependency_factory_unittest.cc b/chromium/content/renderer/media/media_stream_dependency_factory_unittest.cc
index 8cc562c07e0..352fa6ea0ee 100644
--- a/chromium/content/renderer/media/media_stream_dependency_factory_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_dependency_factory_unittest.cc
@@ -27,20 +27,20 @@ class MediaSourceCreatedObserver {
}
void OnCreateNativeSourcesComplete(
- WebKit::WebMediaStream* description,
+ blink::WebMediaStream* description,
bool request_succeeded) {
result_ = request_succeeded;
description_ = description;
}
- WebKit::WebMediaStream* description() const {
+ blink::WebMediaStream* description() const {
return description_;
}
bool result() const { return result_; }
private:
bool result_;
- WebKit::WebMediaStream* description_;
+ blink::WebMediaStream* description_;
};
class MediaStreamDependencyFactoryTest : public ::testing::Test {
@@ -49,21 +49,12 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test {
dependency_factory_.reset(new MockMediaStreamDependencyFactory());
}
- virtual void TearDown() OVERRIDE {
- // TODO(tommyw): Remove this once WebKit::MediaStreamSource::Owner has been
- // implemented to fully avoid a circular dependency.
- for (size_t i = 0; i < audio_sources_.size(); ++i)
- audio_sources_[i].setExtraData(NULL);
-
- for (size_t i = 0; i < video_sources_.size(); ++i)
- video_sources_[i].setExtraData(NULL);
- }
-
- WebKit::WebMediaStream CreateWebKitMediaStream(bool audio, bool video) {
- WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources(
+ blink::WebMediaStream CreateWebKitMediaStream(bool audio, bool video) {
+ blink::WebVector<blink::WebMediaStreamSource> audio_sources(
audio ? static_cast<size_t>(1) : 0);
- WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources(
+ blink::WebVector<blink::WebMediaStreamSource> video_sources(
video ? static_cast<size_t>(1) : 0);
+ MediaStreamSourceExtraData::SourceStopCallback dummy_callback;
if (audio) {
StreamDeviceInfo info;
@@ -71,10 +62,10 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test {
info.device.name = "audio";
info.session_id = 99;
audio_sources[0].initialize("audio",
- WebKit::WebMediaStreamSource::TypeAudio,
+ blink::WebMediaStreamSource::TypeAudio,
"audio");
audio_sources[0].setExtraData(
- new MediaStreamSourceExtraData(info, audio_sources[0]));
+ new MediaStreamSourceExtraData(info, dummy_callback));
audio_sources_.assign(audio_sources);
}
if (video) {
@@ -83,21 +74,21 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test {
info.device.name = "video";
info.session_id = 98;
video_sources[0].initialize("video",
- WebKit::WebMediaStreamSource::TypeVideo,
+ blink::WebMediaStreamSource::TypeVideo,
"video");
video_sources[0].setExtraData(
- new MediaStreamSourceExtraData(info, video_sources[0]));
+ new MediaStreamSourceExtraData(info, dummy_callback));
video_sources_.assign(video_sources);
}
- WebKit::WebMediaStream stream_desc;
- WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_track_vector(
+ blink::WebMediaStream stream_desc;
+ blink::WebVector<blink::WebMediaStreamTrack> audio_track_vector(
audio_sources.size());
for (size_t i = 0; i < audio_track_vector.size(); ++i) {
audio_track_vector[i].initialize(audio_sources[i].id(),
audio_sources[i]);
}
- WebKit::WebVector<WebKit::WebMediaStreamTrack> video_track_vector(
+ blink::WebVector<blink::WebMediaStreamTrack> video_track_vector(
video_sources.size());
for (size_t i = 0; i < video_track_vector.size(); ++i) {
video_track_vector[i].initialize(video_sources[i].id(),
@@ -109,15 +100,15 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test {
return stream_desc;
}
- void CreateNativeSources(WebKit::WebMediaStream* descriptor) {
+ void CreateNativeSources(blink::WebMediaStream* descriptor) {
static const int kRenderViewId = 1;
MediaSourceCreatedObserver observer;
- WebKit::WebMediaConstraints audio_constraints;
+ blink::WebMediaConstraints audio_constraints;
dependency_factory_->CreateNativeMediaSources(
kRenderViewId,
- WebKit::WebMediaConstraints(),
- WebKit::WebMediaConstraints(),
+ blink::WebMediaConstraints(),
+ blink::WebMediaConstraints(),
descriptor,
base::Bind(
&MediaSourceCreatedObserver::OnCreateNativeSourcesComplete,
@@ -134,7 +125,7 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test {
EXPECT_TRUE(observer.description() == descriptor);
}
- void VerifyMediaStream(const WebKit::WebMediaStream& stream_desc,
+ void VerifyMediaStream(const blink::WebMediaStream& stream_desc,
size_t num_audio_tracks,
size_t num_video_tracks) {
content::MediaStreamExtraData* extra_data =
@@ -147,19 +138,19 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test {
protected:
scoped_ptr<MockMediaStreamDependencyFactory> dependency_factory_;
- WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources_;
- WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources_;
+ blink::WebVector<blink::WebMediaStreamSource> audio_sources_;
+ blink::WebVector<blink::WebMediaStreamSource> video_sources_;
};
TEST_F(MediaStreamDependencyFactoryTest, CreateRTCPeerConnectionHandler) {
MockWebRTCPeerConnectionHandlerClient client_jsep;
- scoped_ptr<WebKit::WebRTCPeerConnectionHandler> pc_handler(
+ scoped_ptr<blink::WebRTCPeerConnectionHandler> pc_handler(
dependency_factory_->CreateRTCPeerConnectionHandler(&client_jsep));
EXPECT_TRUE(pc_handler.get() != NULL);
}
TEST_F(MediaStreamDependencyFactoryTest, CreateNativeMediaStream) {
- WebKit::WebMediaStream stream_desc = CreateWebKitMediaStream(true, true);
+ blink::WebMediaStream stream_desc = CreateWebKitMediaStream(true, true);
CreateNativeSources(&stream_desc);
dependency_factory_->CreateNativeLocalMediaStream(&stream_desc);
@@ -171,23 +162,23 @@ TEST_F(MediaStreamDependencyFactoryTest, CreateNativeMediaStream) {
// remote tracks.
TEST_F(MediaStreamDependencyFactoryTest, CreateNativeMediaStreamWithoutSource) {
// Create a WebKit MediaStream description.
- WebKit::WebMediaStreamSource audio_source;
+ blink::WebMediaStreamSource audio_source;
audio_source.initialize("audio source",
- WebKit::WebMediaStreamSource::TypeAudio,
+ blink::WebMediaStreamSource::TypeAudio,
"something");
- WebKit::WebMediaStreamSource video_source;
+ blink::WebMediaStreamSource video_source;
video_source.initialize("video source",
- WebKit::WebMediaStreamSource::TypeVideo,
+ blink::WebMediaStreamSource::TypeVideo,
"something");
- WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks(
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks(
static_cast<size_t>(1));
audio_tracks[0].initialize(audio_source.id(), audio_source);
- WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks(
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks(
static_cast<size_t>(1));
video_tracks[0].initialize(video_source.id(), video_source);
- WebKit::WebMediaStream stream_desc;
+ blink::WebMediaStream stream_desc;
stream_desc.initialize("new stream", audio_tracks, video_tracks);
EXPECT_TRUE(dependency_factory_->EnsurePeerConnectionFactory());
@@ -196,13 +187,13 @@ TEST_F(MediaStreamDependencyFactoryTest, CreateNativeMediaStreamWithoutSource) {
}
TEST_F(MediaStreamDependencyFactoryTest, AddAndRemoveNativeTrack) {
- WebKit::WebMediaStream stream_desc = CreateWebKitMediaStream(true, true);
+ blink::WebMediaStream stream_desc = CreateWebKitMediaStream(true, true);
CreateNativeSources(&stream_desc);
dependency_factory_->CreateNativeLocalMediaStream(&stream_desc);
VerifyMediaStream(stream_desc, 1, 1);
- WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
stream_desc.audioTracks(audio_tracks);
EXPECT_TRUE(dependency_factory_->RemoveNativeMediaStreamTrack(
stream_desc, audio_tracks[0]));
@@ -212,7 +203,7 @@ TEST_F(MediaStreamDependencyFactoryTest, AddAndRemoveNativeTrack) {
stream_desc, audio_tracks[0]));
VerifyMediaStream(stream_desc, 1, 1);
- WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
stream_desc.videoTracks(video_tracks);
EXPECT_TRUE(dependency_factory_->RemoveNativeMediaStreamTrack(
stream_desc, video_tracks[0]));
diff --git a/chromium/content/renderer/media/media_stream_dispatcher.cc b/chromium/content/renderer/media/media_stream_dispatcher.cc
index 57d65b6b8ef..96f92fbfa9c 100644
--- a/chromium/content/renderer/media/media_stream_dispatcher.cc
+++ b/chromium/content/renderer/media/media_stream_dispatcher.cc
@@ -14,38 +14,21 @@
namespace content {
-MediaStreamDispatcher::EnumerationRequest::EnumerationRequest(
- const base::WeakPtr<MediaStreamDispatcherEventHandler>& handler,
- int request_id)
- : handler(handler),
- request_id(request_id) {
-}
-
-MediaStreamDispatcher::EnumerationRequest::~EnumerationRequest() {}
-
-bool MediaStreamDispatcher::EnumerationRequest::IsThisRequest(
- int request_id1,
- const base::WeakPtr<MediaStreamDispatcherEventHandler>& handler1) {
- return (request_id1 == request_id && handler1.get() == handler.get());
-}
-
-MediaStreamDispatcher::EnumerationState::EnumerationState()
- : ipc_id(-1) {
-}
-
-MediaStreamDispatcher::EnumerationState::~EnumerationState() {}
-
-struct MediaStreamDispatcher::EnumerationState::CachedDevices {
- CachedDevices(const std::string& label,
- const StreamDeviceInfoArray& device_array)
- : label(label),
- devices(device_array) {
+namespace {
+
+bool RemoveStreamDeviceFromArray(const StreamDeviceInfo device_info,
+ StreamDeviceInfoArray* array) {
+ for (StreamDeviceInfoArray::iterator device_it = array->begin();
+ device_it != array->end(); ++device_it) {
+ if (StreamDeviceInfo::IsEqual(*device_it, device_info)) {
+ array->erase(device_it);
+ return true;
+ }
}
- ~CachedDevices() {}
+ return false;
+}
- std::string label;
- StreamDeviceInfoArray devices;
-};
+} // namespace
MediaStreamDispatcher::MediaStreamDispatcher(RenderViewImpl* render_view)
: RenderViewObserver(render_view),
@@ -89,17 +72,31 @@ void MediaStreamDispatcher::CancelGenerateStream(
}
}
-void MediaStreamDispatcher::StopStream(const std::string& label) {
- DCHECK(main_loop_->BelongsToCurrentThread());
- DVLOG(1) << "MediaStreamDispatcher::StopStream"
- << ", {label = " << label << "}";
-
- LabelStreamMap::iterator it = label_stream_map_.find(label);
- if (it == label_stream_map_.end())
- return;
+void MediaStreamDispatcher::StopStreamDevice(
+ const StreamDeviceInfo& device_info) {
+ DVLOG(1) << "MediaStreamDispatcher::StopStreamDevice"
+ << ", {device_id = " << device_info.device.id << "}";
+ // Remove |device_info| from all streams in |label_stream_map_|.
+ bool device_found = false;
+ LabelStreamMap::iterator stream_it = label_stream_map_.begin();
+ while (stream_it != label_stream_map_.end()) {
+ StreamDeviceInfoArray& audio_array = stream_it->second.audio_array;
+ StreamDeviceInfoArray& video_array = stream_it->second.video_array;
+
+ if (RemoveStreamDeviceFromArray(device_info, &audio_array) ||
+ RemoveStreamDeviceFromArray(device_info, &video_array)) {
+ device_found = true;
+ if (audio_array.empty() && video_array.empty()) {
+ label_stream_map_.erase(stream_it++);
+ continue;
+ }
+ }
+ ++stream_it;
+ }
+ DCHECK(device_found);
- Send(new MediaStreamHostMsg_StopGeneratedStream(routing_id(), label));
- label_stream_map_.erase(it);
+ Send(new MediaStreamHostMsg_StopStreamDevice(routing_id(),
+ device_info.device.id));
}
void MediaStreamDispatcher::EnumerateDevices(
@@ -113,21 +110,16 @@ void MediaStreamDispatcher::EnumerateDevices(
DVLOG(1) << "MediaStreamDispatcher::EnumerateDevices("
<< request_id << ")";
- EnumerationState* state =
- (type == MEDIA_DEVICE_AUDIO_CAPTURE ?
- &audio_enumeration_state_ : &video_enumeration_state_);
- state->requests.push_back(EnumerationRequest(event_handler, request_id));
-
- if (state->cached_devices) {
- event_handler->OnDevicesEnumerated(
- request_id, state->cached_devices->devices);
- } else if (state->ipc_id < 0) {
- Send(new MediaStreamHostMsg_EnumerateDevices(routing_id(),
- next_ipc_id_,
- type,
- security_origin));
- state->ipc_id = next_ipc_id_++;
+ for (RequestList::iterator it = requests_.begin(); it != requests_.end();
+ ++it) {
+ DCHECK(!it->IsThisRequest(request_id, event_handler));
}
+
+ requests_.push_back(Request(event_handler, request_id, next_ipc_id_));
+ Send(new MediaStreamHostMsg_EnumerateDevices(routing_id(),
+ next_ipc_id_++,
+ type,
+ security_origin));
}
void MediaStreamDispatcher::StopEnumerateDevices(
@@ -136,32 +128,13 @@ void MediaStreamDispatcher::StopEnumerateDevices(
DCHECK(main_loop_->BelongsToCurrentThread());
DVLOG(1) << "MediaStreamDispatcher::StopEnumerateDevices("
<< request_id << ")";
-
- // Remove the request.
- RemoveEnumerationRequest(
- request_id, event_handler, &audio_enumeration_state_);
- RemoveEnumerationRequest(
- request_id, event_handler, &video_enumeration_state_);
-}
-
-void MediaStreamDispatcher::RemoveEnumerationRequest(
- int request_id,
- const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
- EnumerationState* state) {
- EnumerationRequestList* requests = &state->requests;
- for (EnumerationRequestList::iterator it = requests->begin();
- it != requests->end(); ++it) {
+ for (RequestList::iterator it = requests_.begin(); it != requests_.end();
+ ++it) {
if (it->IsThisRequest(request_id, event_handler)) {
- requests->erase(it);
- if (requests->empty() && state->cached_devices) {
- // No more request and has a label, try to stop the label
- // and invalidate the state.
- Send(new MediaStreamHostMsg_StopGeneratedStream(
- routing_id(), state->cached_devices->label));
- state->ipc_id = -1;
- state->cached_devices.reset();
- }
- return;
+ Send(new MediaStreamHostMsg_CancelEnumerateDevices(routing_id(),
+ it->ipc_request));
+ requests_.erase(it);
+ break;
}
}
}
@@ -191,10 +164,16 @@ void MediaStreamDispatcher::CancelOpenDevice(
void MediaStreamDispatcher::CloseDevice(const std::string& label) {
DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(!label.empty());
DVLOG(1) << "MediaStreamDispatcher::CloseDevice"
<< ", {label = " << label << "}";
- StopStream(label);
+ LabelStreamMap::iterator it = label_stream_map_.find(label);
+ if (it == label_stream_map_.end())
+ return;
+ label_stream_map_.erase(it);
+
+ Send(new MediaStreamHostMsg_CloseDevice(routing_id(), label));
}
bool MediaStreamDispatcher::Send(IPC::Message* message) {
@@ -213,12 +192,10 @@ bool MediaStreamDispatcher::OnMessageReceived(const IPC::Message& message) {
OnStreamGenerated)
IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
OnStreamGenerationFailed)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_StopGeneratedStream,
- OnStopGeneratedStream)
+ IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped,
+ OnDeviceStopped)
IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated,
OnDevicesEnumerated)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerationFailed,
- OnDevicesEnumerationFailed)
IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened,
OnDeviceOpened)
IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpenFailed,
@@ -273,67 +250,43 @@ void MediaStreamDispatcher::OnStreamGenerationFailed(int request_id) {
}
}
-void MediaStreamDispatcher::OnStopGeneratedStream(const std::string& label) {
+void MediaStreamDispatcher::OnDeviceStopped(
+ const std::string& label,
+ const StreamDeviceInfo& device_info) {
DCHECK(main_loop_->BelongsToCurrentThread());
+ DVLOG(1) << "MediaStreamDispatcher::OnDeviceStopped("
+ << "{label = " << label << "})"
+ << ", {device_id = " << device_info.device.id << "})";
+
LabelStreamMap::iterator it = label_stream_map_.find(label);
- if (it == label_stream_map_.end())
+ if (it == label_stream_map_.end()) {
+ // This can happen if a user happen stop a the device from JS at the same
+ // time as the underlying media device is unplugged from the system.
return;
-
- if (it->second.handler.get()) {
- it->second.handler->OnStopGeneratedStream(label);
- DVLOG(1) << "MediaStreamDispatcher::OnStopGeneratedStream("
- << label << ")\n";
}
- label_stream_map_.erase(it);
+ Stream* stream = &it->second;
+ if (IsAudioMediaType(device_info.device.type))
+ RemoveStreamDeviceFromArray(device_info, &stream->audio_array);
+ else
+ RemoveStreamDeviceFromArray(device_info, &stream->video_array);
+
+ if (stream->handler.get())
+ stream->handler->OnDeviceStopped(label, device_info);
+
+ if (stream->audio_array.empty() && stream->video_array.empty())
+ label_stream_map_.erase(it);
}
void MediaStreamDispatcher::OnDevicesEnumerated(
int request_id,
- const std::string& label,
const StreamDeviceInfoArray& device_array) {
DCHECK(main_loop_->BelongsToCurrentThread());
DCHECK_GE(request_id, 0);
- EnumerationState* state;
- if (request_id == audio_enumeration_state_.ipc_id) {
- state = &audio_enumeration_state_;
- } else if (request_id == video_enumeration_state_.ipc_id) {
- state = &video_enumeration_state_;
- } else {
- // This could happen when requester has stopped enumeration while some
- // enumerated response is on the way. Have to stop the |label| because
- // this might be the first enumerated device list is received. This also
- // lead to same label being stopped multiple times.
- Send(new MediaStreamHostMsg_StopGeneratedStream(routing_id(), label));
- return;
- }
-
- DCHECK(!label.empty());
- state->cached_devices.reset(new EnumerationState::CachedDevices(
- label, device_array));
-
- for (EnumerationRequestList::iterator it = state->requests.begin();
- it != state->requests.end(); ++it) {
- if (it->handler.get()) {
+ for (RequestList::iterator it = requests_.begin(); it != requests_.end();
+ ++it) {
+ if (it->ipc_request == request_id && it->handler.get()) {
it->handler->OnDevicesEnumerated(it->request_id, device_array);
- DVLOG(1) << "MediaStreamDispatcher::OnDevicesEnumerated("
- << it->request_id << ")";
- }
- }
-}
-
-void MediaStreamDispatcher::OnDevicesEnumerationFailed(int request_id) {
- DCHECK(main_loop_->BelongsToCurrentThread());
- for (RequestList::iterator it = requests_.begin();
- it != requests_.end(); ++it) {
- Request& request = *it;
- if (request.ipc_request == request_id) {
- if (request.handler.get()) {
- request.handler->OnDevicesEnumerationFailed(request.request_id);
- DVLOG(1) << "MediaStreamDispatcher::OnDevicesEnumerationFailed("
- << request.request_id << ")\n";
- }
- requests_.erase(it);
break;
}
}
@@ -389,10 +342,10 @@ void MediaStreamDispatcher::OnDeviceOpenFailed(int request_id) {
int MediaStreamDispatcher::audio_session_id(const std::string& label,
int index) {
LabelStreamMap::iterator it = label_stream_map_.find(label);
- if (it == label_stream_map_.end())
+ if (it == label_stream_map_.end() ||
+ it->second.audio_array.size() <= static_cast<size_t>(index)) {
return StreamDeviceInfo::kNoId;
-
- DCHECK_GT(it->second.audio_array.size(), static_cast<size_t>(index));
+ }
return it->second.audio_array[index].session_id;
}
@@ -403,10 +356,10 @@ bool MediaStreamDispatcher::IsStream(const std::string& label) {
int MediaStreamDispatcher::video_session_id(const std::string& label,
int index) {
LabelStreamMap::iterator it = label_stream_map_.find(label);
- if (it == label_stream_map_.end())
+ if (it == label_stream_map_.end() ||
+ it->second.video_array.size() <= static_cast<size_t>(index)) {
return StreamDeviceInfo::kNoId;
-
- DCHECK_GT(it->second.video_array.size(), static_cast<size_t>(index));
+ }
return it->second.video_array[index].session_id;
}
diff --git a/chromium/content/renderer/media/media_stream_dispatcher.h b/chromium/content/renderer/media/media_stream_dispatcher.h
index af25963940e..4c08958488a 100644
--- a/chromium/content/renderer/media/media_stream_dispatcher.h
+++ b/chromium/content/renderer/media/media_stream_dispatcher.h
@@ -52,8 +52,8 @@ class CONTENT_EXPORT MediaStreamDispatcher
int request_id,
const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler);
- // Stop a started stream. Label is the label provided in OnStreamGenerated.
- virtual void StopStream(const std::string& label);
+ // Stop a started device that has been requested by calling GenerateStream.
+ virtual void StopStreamDevice(const StreamDeviceInfo& device_info);
// Request to enumerate devices.
void EnumerateDevices(
@@ -91,9 +91,10 @@ class CONTENT_EXPORT MediaStreamDispatcher
// Returns an audio session_id given a label and an index.
virtual int audio_session_id(const std::string& label, int index);
+ protected:
+ int GetNextIpcIdForTest() { return next_ipc_id_; }
+
private:
- FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, BasicStream);
- FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, BasicStreamForDevice);
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, BasicVideoDevice);
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, TestFailure);
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, CancelGenerateStream);
@@ -131,37 +132,6 @@ class CONTENT_EXPORT MediaStreamDispatcher
StreamDeviceInfoArray video_array;
};
- // An enumeration request is identified by pair (request_id, handler).
- // It allows multiple clients to make requests and each client could have
- // its own request_id sequence.
- struct EnumerationRequest {
- EnumerationRequest(
- const base::WeakPtr<MediaStreamDispatcherEventHandler>& handler,
- int request_id);
- ~EnumerationRequest();
- bool IsThisRequest(
- int request_id,
- const base::WeakPtr<MediaStreamDispatcherEventHandler>& handler);
-
- base::WeakPtr<MediaStreamDispatcherEventHandler> handler;
- int request_id;
- };
-
- // List of requests made to EnumerateDevices.
- typedef std::list<EnumerationRequest> EnumerationRequestList;
-
- struct EnumerationState {
- EnumerationState();
- ~EnumerationState();
-
- struct CachedDevices;
-
- // If |ipc_id| >= 0, then we've started.
- int ipc_id;
- scoped_ptr<CachedDevices> cached_devices;
- EnumerationRequestList requests;
- };
-
// RenderViewObserver OVERRIDE.
virtual bool Send(IPC::Message* message) OVERRIDE;
@@ -173,10 +143,10 @@ class CONTENT_EXPORT MediaStreamDispatcher
const StreamDeviceInfoArray& audio_array,
const StreamDeviceInfoArray& video_array);
void OnStreamGenerationFailed(int request_id);
- void OnStopGeneratedStream(const std::string& label);
+ void OnDeviceStopped(const std::string& label,
+ const StreamDeviceInfo& device_info);
void OnDevicesEnumerated(
int request_id,
- const std::string& label,
const StreamDeviceInfoArray& device_array);
void OnDevicesEnumerationFailed(int request_id);
void OnDeviceOpened(
@@ -185,11 +155,6 @@ class CONTENT_EXPORT MediaStreamDispatcher
const StreamDeviceInfo& device_info);
void OnDeviceOpenFailed(int request_id);
- void RemoveEnumerationRequest(
- int request_id,
- const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
- EnumerationState* state);
-
// Used for DCHECKs so methods calls won't execute in the wrong thread.
scoped_refptr<base::MessageLoopProxy> main_loop_;
@@ -197,10 +162,8 @@ class CONTENT_EXPORT MediaStreamDispatcher
typedef std::map<std::string, Stream> LabelStreamMap;
LabelStreamMap label_stream_map_;
- EnumerationState audio_enumeration_state_;
- EnumerationState video_enumeration_state_;
-
- // List of calls made to GenerateStream that have not yet completed.
+ // List of calls made to the browser process that have not yet completed or
+ // been canceled.
typedef std::list<Request> RequestList;
RequestList requests_;
diff --git a/chromium/content/renderer/media/media_stream_dispatcher_eventhandler.h b/chromium/content/renderer/media/media_stream_dispatcher_eventhandler.h
index 7a0803a096c..e83f2952560 100644
--- a/chromium/content/renderer/media/media_stream_dispatcher_eventhandler.h
+++ b/chromium/content/renderer/media/media_stream_dispatcher_eventhandler.h
@@ -25,17 +25,16 @@ class CONTENT_EXPORT MediaStreamDispatcherEventHandler {
// to the requested devices or no device is available.
virtual void OnStreamGenerationFailed(int request_id) = 0;
- // The user has requested to stop a media stream.
- virtual void OnStopGeneratedStream(const std::string& label) = 0;
+ // A device has been stopped in the browser processes.
+ virtual void OnDeviceStopped(
+ const std::string& label,
+ const StreamDeviceInfo& device_info) = 0;
// A new list of devices have been enumerated.
virtual void OnDevicesEnumerated(
int request_id,
const StreamDeviceInfoArray& device_array) = 0;
- // Failed to enumerate devices.
- virtual void OnDevicesEnumerationFailed(int request_id) = 0;
-
// A device has been opened.
virtual void OnDeviceOpened(
int request_id,
diff --git a/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc b/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc
index 300bfe39690..635d22fa04c 100644
--- a/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc
@@ -7,6 +7,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "content/common/media/media_stream_messages.h"
#include "content/public/common/media_stream_request.h"
#include "content/renderer/media/media_stream_dispatcher.h"
@@ -24,11 +25,9 @@ const int kRequestId1 = 10;
const int kRequestId2 = 20;
const int kRequestId3 = 30;
const int kRequestId4 = 40;
-static const char kLabel[] = "test";
const MediaStreamType kAudioType = MEDIA_DEVICE_AUDIO_CAPTURE;
const MediaStreamType kVideoType = MEDIA_DEVICE_VIDEO_CAPTURE;
-const MediaStreamType kNoAudioType = MEDIA_NO_SERVICE;
class MockMediaStreamDispatcherEventHandler
: public MediaStreamDispatcherEventHandler,
@@ -44,14 +43,29 @@ class MockMediaStreamDispatcherEventHandler
const StreamDeviceInfoArray& video_device_array) OVERRIDE {
request_id_ = request_id;
label_ = label;
+ if (audio_device_array.size()) {
+ DCHECK(audio_device_array.size() == 1);
+ audio_device_ = audio_device_array[0];
+ }
+ if (video_device_array.size()) {
+ DCHECK(video_device_array.size() == 1);
+ video_device_ = video_device_array[0];
+ }
}
virtual void OnStreamGenerationFailed(int request_id) OVERRIDE {
request_id_ = request_id;
}
- virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE {
- label_ = label;
+ virtual void OnDeviceStopped(const std::string& label,
+ const StreamDeviceInfo& device_info) OVERRIDE {
+ device_stopped_label_ = label;
+ if (IsVideoMediaType(device_info.device.type)) {
+ EXPECT_TRUE(StreamDeviceInfo::IsEqual(video_device_, device_info));
+ }
+ if (IsAudioMediaType(device_info.device.type)) {
+ EXPECT_TRUE(StreamDeviceInfo::IsEqual(audio_device_, device_info));
+ }
}
virtual void OnDevicesEnumerated(
@@ -60,10 +74,6 @@ class MockMediaStreamDispatcherEventHandler
request_id_ = request_id;
}
- virtual void OnDevicesEnumerationFailed(int request_id) OVERRIDE {
- request_id_ = request_id;
- }
-
virtual void OnDeviceOpened(
int request_id,
const std::string& label,
@@ -76,163 +86,133 @@ class MockMediaStreamDispatcherEventHandler
request_id_ = request_id;
}
+ void ResetStoredParameters() {
+ request_id_ = -1;
+ label_ = "";
+ device_stopped_label_ = "";
+ audio_device_ = StreamDeviceInfo();
+ video_device_ = StreamDeviceInfo();
+ }
+
int request_id_;
std::string label_;
-
- DISALLOW_COPY_AND_ASSIGN(MockMediaStreamDispatcherEventHandler);
+ std::string device_stopped_label_;
+ StreamDeviceInfo audio_device_;
+ StreamDeviceInfo video_device_;
};
-} // namespace
-
-TEST(MediaStreamDispatcherTest, BasicStream) {
- scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
- scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
- scoped_ptr<MockMediaStreamDispatcherEventHandler>
- handler(new MockMediaStreamDispatcherEventHandler);
- StreamOptions components(kAudioType, kVideoType);
- GURL security_origin;
-
- int ipc_request_id1 = dispatcher->next_ipc_id_;
- dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
- components, security_origin);
- int ipc_request_id2 = dispatcher->next_ipc_id_;
- EXPECT_NE(ipc_request_id1, ipc_request_id2);
- dispatcher->GenerateStream(kRequestId2, handler.get()->AsWeakPtr(),
- components, security_origin);
- EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
+class MediaStreamDispatcherUnderTest : public MediaStreamDispatcher {
+ public:
+ MediaStreamDispatcherUnderTest() : MediaStreamDispatcher(NULL) {}
- StreamDeviceInfoArray audio_device_array(1);
- StreamDeviceInfo audio_device_info;
- audio_device_info.device.name = "Microphone";
- audio_device_info.device.type = kAudioType;
- audio_device_info.session_id = kAudioSessionId;
- audio_device_array[0] = audio_device_info;
+ using MediaStreamDispatcher::GetNextIpcIdForTest;
+ using RenderViewObserver::OnMessageReceived;
+};
- StreamDeviceInfoArray video_device_array(1);
- StreamDeviceInfo video_device_info;
- video_device_info.device.name = "Camera";
- video_device_info.device.type = kVideoType;
- video_device_info.session_id = kVideoSessionId;
- video_device_array[0] = video_device_info;
+class MediaStreamDispatcherTest : public ::testing::Test {
+ public:
+ MediaStreamDispatcherTest()
+ : dispatcher_(new MediaStreamDispatcherUnderTest()),
+ handler_(new MockMediaStreamDispatcherEventHandler),
+ security_origin_("http://test.com"),
+ request_id_(10) {
+ }
- // Complete the creation of stream1.
- std::string stream_label1 = std::string("stream1");
- dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
- kRouteId, ipc_request_id1, stream_label1,
- audio_device_array, video_device_array));
- EXPECT_EQ(handler->request_id_, kRequestId1);
- EXPECT_EQ(handler->label_, stream_label1);
+ // Generates a request for a MediaStream and returns the request id that is
+ // used in IPC. Use this returned id in CompleteGenerateStream to identify
+ // the request.
+ int GenerateStream(const StreamOptions& options, int request_id) {
+ int next_ipc_id = dispatcher_->GetNextIpcIdForTest();
+ dispatcher_->GenerateStream(request_id, handler_.get()->AsWeakPtr(),
+ options, security_origin_);
+ return next_ipc_id;
+ }
- // Complete the creation of stream2.
- std::string stream_label2 = std::string("stream2");
- dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
- kRouteId, ipc_request_id2, stream_label2,
+ // CompleteGenerateStream create a MediaStreamMsg_StreamGenerated instance
+ // and call the MediaStreamDispathcer::OnMessageReceived. |ipc_id| must be the
+ // the id returned by GenerateStream.
+ std::string CompleteGenerateStream(int ipc_id, const StreamOptions& options,
+ int request_id) {
+ StreamDeviceInfoArray audio_device_array(options.audio_requested ? 1 : 0);
+ if (options.audio_requested) {
+ StreamDeviceInfo audio_device_info;
+ audio_device_info.device.name = "Microphone";
+ audio_device_info.device.type = kAudioType;
+ audio_device_info.session_id = kAudioSessionId;
+ audio_device_array[0] = audio_device_info;
+ }
+
+ StreamDeviceInfoArray video_device_array(options.video_requested ? 1 : 0);
+ if (options.video_requested) {
+ StreamDeviceInfo video_device_info;
+ video_device_info.device.name = "Camera";
+ video_device_info.device.type = kVideoType;
+ video_device_info.session_id = kVideoSessionId;
+ video_device_array[0] = video_device_info;
+ }
+
+ std::string label = "stream" + base::IntToString(ipc_id);
+
+ handler_->ResetStoredParameters();
+ dispatcher_->OnMessageReceived(MediaStreamMsg_StreamGenerated(
+ kRouteId, ipc_id, label,
audio_device_array, video_device_array));
- EXPECT_EQ(handler->request_id_, kRequestId2);
- EXPECT_EQ(handler->label_, stream_label2);
- EXPECT_EQ(dispatcher->requests_.size(), size_t(0));
- EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(2));
+ EXPECT_EQ(handler_->request_id_, request_id);
+ EXPECT_EQ(handler_->label_, label);
- // Check the session_id of stream2.
- EXPECT_EQ(dispatcher->audio_session_id(stream_label2, 0), kAudioSessionId);
- EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), kVideoSessionId);
+ if (options.audio_requested)
+ EXPECT_EQ(dispatcher_->audio_session_id(label, 0), kAudioSessionId);
- // Stop stream2.
- dispatcher->StopStream(stream_label2);
- EXPECT_EQ(dispatcher->audio_session_id(stream_label2, 0),
- StreamDeviceInfo::kNoId);
- EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0),
- StreamDeviceInfo::kNoId);
+ if (options.video_requested)
+ EXPECT_EQ(dispatcher_->video_session_id(label, 0), kVideoSessionId);
- // Stop stream1.
- dispatcher->StopStream(stream_label1);
- EXPECT_EQ(dispatcher->audio_session_id(stream_label1, 0),
- StreamDeviceInfo::kNoId);
- EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0),
- StreamDeviceInfo::kNoId);
- EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
+ return label;
+ }
- // Verify that the request has been completed.
- EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
- EXPECT_EQ(dispatcher->requests_.size(), size_t(0));
-}
+ protected:
+ base::MessageLoop message_loop_;
+ scoped_ptr<MediaStreamDispatcherUnderTest> dispatcher_;
+ scoped_ptr<MockMediaStreamDispatcherEventHandler> handler_;
+ GURL security_origin_;
+ int request_id_;
+};
-TEST(MediaStreamDispatcherTest, BasicStreamForDevice) {
- static const char kDeviceId[] = "/dev/video0";
+} // namespace
- scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
- scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
- scoped_ptr<MockMediaStreamDispatcherEventHandler>
- handler(new MockMediaStreamDispatcherEventHandler);
- StreamOptions components(kNoAudioType, kVideoType);
- components.audio_device_id = kDeviceId;
- components.video_device_id = kDeviceId;
- GURL security_origin;
+TEST_F(MediaStreamDispatcherTest, GenerateStreamAndStopDevices) {
+ StreamOptions options(true, true);
- int ipc_request_id1 = dispatcher->next_ipc_id_;
- dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
- components, security_origin);
- int ipc_request_id2 = dispatcher->next_ipc_id_;
+ int ipc_request_id1 = GenerateStream(options, kRequestId1);
+ int ipc_request_id2 = GenerateStream(options, kRequestId2);
EXPECT_NE(ipc_request_id1, ipc_request_id2);
- dispatcher->GenerateStream(kRequestId2, handler.get()->AsWeakPtr(),
- components, security_origin);
- EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
-
- // No audio requested.
- StreamDeviceInfoArray audio_device_array;
-
- StreamDeviceInfoArray video_device_array(1);
- StreamDeviceInfo video_device_info;
- video_device_info.device.name = "Fake Video Capture Device";
- video_device_info.device.type = kVideoType;
- video_device_info.session_id = kVideoSessionId;
- video_device_array[0] = video_device_info;
// Complete the creation of stream1.
- std::string stream_label1 = std::string("stream1");
- dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
- kRouteId, ipc_request_id1, stream_label1,
- audio_device_array, video_device_array));
- EXPECT_EQ(handler->request_id_, kRequestId1);
- EXPECT_EQ(handler->label_, stream_label1);
+ const std::string& label1 = CompleteGenerateStream(ipc_request_id1, options,
+ kRequestId1);
// Complete the creation of stream2.
- std::string stream_label2 = std::string("stream2");
- dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
- kRouteId, ipc_request_id2, stream_label2,
- audio_device_array, video_device_array));
- EXPECT_EQ(handler->request_id_, kRequestId2);
- EXPECT_EQ(handler->label_, stream_label2);
+ const std::string& label2 = CompleteGenerateStream(ipc_request_id2, options,
+ kRequestId2);
- EXPECT_EQ(dispatcher->requests_.size(), size_t(0));
- EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(2));
-
- // Check the session_id of stream2.
- EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), kVideoSessionId);
-
- // Stop stream2.
- dispatcher->StopStream(stream_label2);
- EXPECT_EQ(dispatcher->audio_session_id(stream_label2, 0),
+ // Stop the actual audio device and verify that there is no valid
+ // |session_id|.
+ dispatcher_->StopStreamDevice(handler_->audio_device_);
+ EXPECT_EQ(dispatcher_->audio_session_id(label1, 0),
StreamDeviceInfo::kNoId);
- EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0),
+ EXPECT_EQ(dispatcher_->audio_session_id(label2, 0),
StreamDeviceInfo::kNoId);
- // Stop stream1.
- dispatcher->StopStream(stream_label1);
- EXPECT_EQ(dispatcher->audio_session_id(stream_label1, 0),
+ // Stop the actual video device and verify that there is no valid
+ // |session_id|.
+ dispatcher_->StopStreamDevice(handler_->video_device_);
+ EXPECT_EQ(dispatcher_->video_session_id(label1, 0),
StreamDeviceInfo::kNoId);
- EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0),
+ EXPECT_EQ(dispatcher_->video_session_id(label2, 0),
StreamDeviceInfo::kNoId);
- EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
-
- // Verify that the request has been completed.
- EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
- EXPECT_EQ(dispatcher->requests_.size(), size_t(0));
}
-TEST(MediaStreamDispatcherTest, BasicVideoDevice) {
- scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
+TEST_F(MediaStreamDispatcherTest, BasicVideoDevice) {
scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
scoped_ptr<MockMediaStreamDispatcherEventHandler>
handler1(new MockMediaStreamDispatcherEventHandler);
@@ -251,7 +231,7 @@ TEST(MediaStreamDispatcherTest, BasicVideoDevice) {
kRequestId2, handler2.get()->AsWeakPtr(),
kVideoType,
security_origin);
- EXPECT_EQ(dispatcher->video_enumeration_state_.requests.size(), size_t(2));
+ EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
StreamDeviceInfoArray video_device_array(1);
StreamDeviceInfo video_device_info;
@@ -261,13 +241,16 @@ TEST(MediaStreamDispatcherTest, BasicVideoDevice) {
video_device_info.session_id = kVideoSessionId;
video_device_array[0] = video_device_info;
- // Complete the enumeration request and all requesters should receive reply.
+ // Complete the first enumeration request.
dispatcher->OnMessageReceived(MediaStreamMsg_DevicesEnumerated(
- kRouteId, ipc_request_id1, kLabel, video_device_array));
+ kRouteId, ipc_request_id1, video_device_array));
EXPECT_EQ(handler1->request_id_, kRequestId1);
+
+ dispatcher->OnMessageReceived(MediaStreamMsg_DevicesEnumerated(
+ kRouteId, ipc_request_id2, video_device_array));
EXPECT_EQ(handler2->request_id_, kRequestId2);
- EXPECT_EQ(dispatcher->video_enumeration_state_.requests.size(), size_t(2));
+ EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
int ipc_request_id3 = dispatcher->next_ipc_id_;
@@ -281,7 +264,7 @@ TEST(MediaStreamDispatcherTest, BasicVideoDevice) {
video_device_info.device.id,
kVideoType,
security_origin);
- EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
+ EXPECT_EQ(dispatcher->requests_.size(), size_t(4));
// Complete the OpenDevice of request 1.
std::string stream_label1 = std::string("stream1");
@@ -295,35 +278,34 @@ TEST(MediaStreamDispatcherTest, BasicVideoDevice) {
kRouteId, ipc_request_id4, stream_label2, video_device_info));
EXPECT_EQ(handler1->request_id_, kRequestId4);
- EXPECT_EQ(dispatcher->requests_.size(), size_t(0));
+ EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(2));
// Check the video_session_id.
EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), kVideoSessionId);
EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), kVideoSessionId);
- // Stop stream2.
- dispatcher->StopStream(stream_label2);
+ // Close the device from request 2.
+ dispatcher->CloseDevice(stream_label2);
EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0),
StreamDeviceInfo::kNoId);
- // Stop stream1.
- dispatcher->StopStream(stream_label1);
+ // Close the device from request 1.
+ dispatcher->CloseDevice(stream_label1);
EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0),
StreamDeviceInfo::kNoId);
EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
// Verify that the request have been completed.
EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
- EXPECT_EQ(dispatcher->requests_.size(), size_t(0));
+ EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
}
-TEST(MediaStreamDispatcherTest, TestFailure) {
- scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
+TEST_F(MediaStreamDispatcherTest, TestFailure) {
scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
scoped_ptr<MockMediaStreamDispatcherEventHandler>
handler(new MockMediaStreamDispatcherEventHandler);
- StreamOptions components(kAudioType, kVideoType);
+ StreamOptions components(true, true);
GURL security_origin;
// Test failure when creating a stream.
@@ -364,18 +346,13 @@ TEST(MediaStreamDispatcherTest, TestFailure) {
EXPECT_EQ(handler->request_id_, kRequestId1);
EXPECT_EQ(handler->label_, stream_label1);
EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), kVideoSessionId);
-
- // Stop stream1.
- dispatcher->StopStream(stream_label1);
- EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
}
-TEST(MediaStreamDispatcherTest, CancelGenerateStream) {
- scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
+TEST_F(MediaStreamDispatcherTest, CancelGenerateStream) {
scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
scoped_ptr<MockMediaStreamDispatcherEventHandler>
handler(new MockMediaStreamDispatcherEventHandler);
- StreamOptions components(kAudioType, kVideoType);
+ StreamOptions components(true, true);
int ipc_request_id1 = dispatcher->next_ipc_id_;
dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
@@ -411,4 +388,22 @@ TEST(MediaStreamDispatcherTest, CancelGenerateStream) {
EXPECT_EQ(0u, dispatcher->requests_.size());
}
+// Test that the MediaStreamDispatcherEventHandler is notified when the message
+// MediaStreamMsg_DeviceStopped is received.
+TEST_F(MediaStreamDispatcherTest, DeviceClosed) {
+ StreamOptions options(true, true);
+
+ int ipc_request_id = GenerateStream(options, kRequestId1);
+ const std::string& label = CompleteGenerateStream(ipc_request_id, options,
+ kRequestId1);
+
+ dispatcher_->OnMessageReceived(
+ MediaStreamMsg_DeviceStopped(kRouteId, label, handler_->video_device_));
+ // Verify that MediaStreamDispatcherEventHandler::OnDeviceStopped has been
+ // called.
+ EXPECT_EQ(label, handler_->device_stopped_label_);
+ EXPECT_EQ(dispatcher_->video_session_id(label, 0),
+ StreamDeviceInfo::kNoId);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_extra_data.h b/chromium/content/renderer/media/media_stream_extra_data.h
index afac9c350a2..63bfca4a139 100644
--- a/chromium/content/renderer/media/media_stream_extra_data.h
+++ b/chromium/content/renderer/media/media_stream_extra_data.h
@@ -18,7 +18,7 @@ class MediaStreamInterface;
namespace content {
class CONTENT_EXPORT MediaStreamExtraData
- : NON_EXPORTED_BASE(public WebKit::WebMediaStream::ExtraData) {
+ : NON_EXPORTED_BASE(public blink::WebMediaStream::ExtraData) {
public:
typedef base::Callback<void(const std::string& label)> StreamStopCallback;
diff --git a/chromium/content/renderer/media/media_stream_impl.cc b/chromium/content/renderer/media/media_stream_impl.cc
index 96dffde9fcd..bc720205d8e 100644
--- a/chromium/content/renderer/media/media_stream_impl.cc
+++ b/chromium/content/renderer/media/media_stream_impl.cc
@@ -7,11 +7,9 @@
#include <utility>
#include "base/logging.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 "content/public/common/desktop_media_id.h"
#include "content/renderer/media/media_stream_audio_renderer.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
#include "content/renderer/media/media_stream_dispatcher.h"
@@ -21,13 +19,12 @@
#include "content/renderer/media/webrtc_audio_capturer.h"
#include "content/renderer/media/webrtc_audio_renderer.h"
#include "content/renderer/media/webrtc_local_audio_renderer.h"
+#include "content/renderer/media/webrtc_logging.h"
#include "content/renderer/media/webrtc_uma_histograms.h"
#include "content/renderer/render_thread_impl.h"
#include "media/base/audio_hardware_config.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
-#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
@@ -35,87 +32,30 @@
namespace content {
namespace {
-std::string GetStreamConstraint(
- const WebKit::WebMediaConstraints& constraints, const std::string& key,
- bool is_mandatory) {
- if (constraints.isNull())
- return std::string();
-
- WebKit::WebString value;
- if (is_mandatory) {
- constraints.getMandatoryConstraintValue(UTF8ToUTF16(key), value);
- } else {
- constraints.getOptionalConstraintValue(UTF8ToUTF16(key), value);
- }
- return UTF16ToUTF8(value);
-}
-
-void UpdateRequestOptions(
- const WebKit::WebUserMediaRequest& user_media_request,
- StreamOptions* options) {
- if (options->audio_type != content::MEDIA_NO_SERVICE) {
- std::string audio_stream_source = GetStreamConstraint(
- user_media_request.audioConstraints(), kMediaStreamSource, true);
- if (audio_stream_source == kMediaStreamSourceTab) {
- options->audio_type = content::MEDIA_TAB_AUDIO_CAPTURE;
- options->audio_device_id = GetStreamConstraint(
- user_media_request.audioConstraints(),
- kMediaStreamSourceId, true);
- } else if (audio_stream_source == kMediaStreamSourceSystem) {
- options->audio_type = content::MEDIA_SYSTEM_AUDIO_CAPTURE;
- }
+void CopyStreamConstraints(const blink::WebMediaConstraints& constraints,
+ StreamOptions::Constraints* mandatory,
+ StreamOptions::Constraints* optional) {
+ blink::WebVector<blink::WebMediaConstraint> mandatory_constraints;
+ constraints.getMandatoryConstraints(mandatory_constraints);
+ for (size_t i = 0; i < mandatory_constraints.size(); i++) {
+ mandatory->push_back(StreamOptions::Constraint(
+ mandatory_constraints[i].m_name.utf8(),
+ mandatory_constraints[i].m_value.utf8()));
}
- if (options->video_type != content::MEDIA_NO_SERVICE) {
- std::string video_stream_source = GetStreamConstraint(
- user_media_request.videoConstraints(), kMediaStreamSource, true);
- if (video_stream_source == kMediaStreamSourceTab) {
- options->video_type = content::MEDIA_TAB_VIDEO_CAPTURE;
- options->video_device_id = GetStreamConstraint(
- user_media_request.videoConstraints(),
- kMediaStreamSourceId, true);
- } else if (video_stream_source == kMediaStreamSourceScreen) {
- options->video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
- options->video_device_id =
- DesktopMediaID(DesktopMediaID::TYPE_SCREEN, 0).ToString();
- } else if (video_stream_source == kMediaStreamSourceDesktop) {
- options->video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
- options->video_device_id = GetStreamConstraint(
- user_media_request.videoConstraints(),
- kMediaStreamSourceId, true);
- }
+ blink::WebVector<blink::WebMediaConstraint> optional_constraints;
+ constraints.getOptionalConstraints(optional_constraints);
+ for (size_t i = 0; i < optional_constraints.size(); i++) {
+ optional->push_back(StreamOptions::Constraint(
+ optional_constraints[i].m_name.utf8(),
+ optional_constraints[i].m_value.utf8()));
}
}
static int g_next_request_id = 0;
-// Creates a WebKit representation of a stream sources based on
-// |devices| from the MediaStreamDispatcher.
-void CreateWebKitSourceVector(
- const std::string& label,
- const StreamDeviceInfoArray& devices,
- WebKit::WebMediaStreamSource::Type type,
- WebKit::WebVector<WebKit::WebMediaStreamSource>& webkit_sources) {
- CHECK_EQ(devices.size(), webkit_sources.size());
- for (size_t i = 0; i < devices.size(); ++i) {
- const char* track_type =
- (type == WebKit::WebMediaStreamSource::TypeAudio) ? "a" : "v";
- std::string source_id = base::StringPrintf("%s%s%u", label.c_str(),
- track_type,
- static_cast<unsigned int>(i));
- webkit_sources[i].initialize(
- UTF8ToUTF16(source_id),
- type,
- UTF8ToUTF16(devices[i].device.name));
- webkit_sources[i].setExtraData(
- new content::MediaStreamSourceExtraData(devices[i], webkit_sources[i]));
- webkit_sources[i].setDeviceId(UTF8ToUTF16(
- base::IntToString(devices[i].session_id)));
- }
-}
-
webrtc::MediaStreamInterface* GetNativeMediaStream(
- const WebKit::WebMediaStream& web_stream) {
+ const blink::WebMediaStream& web_stream) {
content::MediaStreamExtraData* extra_data =
static_cast<content::MediaStreamExtraData*>(web_stream.extraData());
if (!extra_data)
@@ -132,6 +72,18 @@ void GetDefaultOutputDeviceParams(
*output_buffer_size = hardware_config->GetOutputBufferSize();
}
+void RemoveSource(const blink::WebMediaStreamSource& source,
+ std::vector<blink::WebMediaStreamSource>* sources) {
+ for (std::vector<blink::WebMediaStreamSource>::iterator it =
+ sources->begin();
+ it != sources->end(); ++it) {
+ if (source.id() == it->id()) {
+ sources->erase(it);
+ return;
+ }
+ }
+}
+
} // namespace
MediaStreamImpl::MediaStreamImpl(
@@ -146,31 +98,16 @@ MediaStreamImpl::MediaStreamImpl(
MediaStreamImpl::~MediaStreamImpl() {
}
-void MediaStreamImpl::OnLocalMediaStreamStop(
- const std::string& label) {
- DVLOG(1) << "MediaStreamImpl::OnLocalMediaStreamStop(" << label << ")";
-
- UserMediaRequestInfo* user_media_request = FindUserMediaRequestInfo(label);
- if (user_media_request) {
- StopLocalAudioTrack(user_media_request->web_stream);
- media_stream_dispatcher_->StopStream(label);
- DeleteUserMediaRequestInfo(user_media_request);
- } else {
- DVLOG(1) << "MediaStreamImpl::OnLocalMediaStreamStop: the stream has "
- << "already been stopped.";
- }
-}
-
void MediaStreamImpl::requestUserMedia(
- const WebKit::WebUserMediaRequest& user_media_request) {
+ const blink::WebUserMediaRequest& user_media_request) {
// Save histogram data so we can see how much GetUserMedia is used.
// The histogram counts the number of calls to the JS API
// webGetUserMedia.
UpdateWebRTCMethodCount(WEBKIT_GET_USER_MEDIA);
DCHECK(CalledOnValidThread());
int request_id = g_next_request_id++;
- StreamOptions options(MEDIA_NO_SERVICE, MEDIA_NO_SERVICE);
- WebKit::WebFrame* frame = NULL;
+ StreamOptions options;
+ blink::WebFrame* frame = NULL;
GURL security_origin;
bool enable_automatic_output_device_selection = false;
@@ -178,27 +115,29 @@ void MediaStreamImpl::requestUserMedia(
// if it isNull.
if (user_media_request.isNull()) {
// We are in a test.
- options.audio_type = MEDIA_DEVICE_AUDIO_CAPTURE;
- options.video_type = MEDIA_DEVICE_VIDEO_CAPTURE;
+ options.audio_requested = true;
+ options.video_requested = true;
} else {
if (user_media_request.audio()) {
- options.audio_type = MEDIA_DEVICE_AUDIO_CAPTURE;
- options.audio_device_id = GetStreamConstraint(
- user_media_request.audioConstraints(),
- kMediaStreamSourceInfoId, false);
+ options.audio_requested = true;
+ CopyStreamConstraints(user_media_request.audioConstraints(),
+ &options.mandatory_audio,
+ &options.optional_audio);
+
// Check if this input device should be used to select a matching output
// device for audio rendering.
- std::string enable = GetStreamConstraint(
- user_media_request.audioConstraints(),
- kMediaStreamRenderToAssociatedSink, false);
- if (LowerCaseEqualsASCII(enable, "true"))
+ std::string enable;
+ if (options.GetFirstAudioConstraintByName(
+ kMediaStreamRenderToAssociatedSink, &enable, NULL) &&
+ LowerCaseEqualsASCII(enable, "true")) {
enable_automatic_output_device_selection = true;
+ }
}
if (user_media_request.video()) {
- options.video_type = MEDIA_DEVICE_VIDEO_CAPTURE;
- options.video_device_id = GetStreamConstraint(
- user_media_request.videoConstraints(),
- kMediaStreamSourceInfoId, false);
+ options.video_requested = true;
+ CopyStreamConstraints(user_media_request.videoConstraints(),
+ &options.mandatory_video,
+ &options.optional_video);
}
security_origin = GURL(user_media_request.securityOrigin().toString());
@@ -207,17 +146,34 @@ void MediaStreamImpl::requestUserMedia(
// out of scope.
frame = user_media_request.ownerDocument().frame();
DCHECK(frame);
-
- UpdateRequestOptions(user_media_request, &options);
}
DVLOG(1) << "MediaStreamImpl::requestUserMedia(" << request_id << ", [ "
- << "audio=" << (options.audio_type)
+ << "audio=" << (options.audio_requested)
<< " select associated sink: "
<< enable_automatic_output_device_selection
- << ", video=" << (options.video_type) << " ], "
+ << ", video=" << (options.video_requested) << " ], "
<< security_origin.spec() << ")";
+ std::string audio_device_id;
+ bool mandatory_audio;
+ options.GetFirstAudioConstraintByName(kMediaStreamSourceInfoId,
+ &audio_device_id, &mandatory_audio);
+ std::string video_device_id;
+ bool mandatory_video;
+ options.GetFirstVideoConstraintByName(kMediaStreamSourceInfoId,
+ &video_device_id, &mandatory_video);
+
+ WebRtcLogMessage(base::StringPrintf(
+ "MSI::requestUserMedia. request_id=%d"
+ ", audio source id=%s mandatory= %s "
+ ", video source id=%s mandatory= %s",
+ request_id,
+ audio_device_id.c_str(),
+ mandatory_audio ? "true":"false",
+ video_device_id.c_str(),
+ mandatory_video ? "true":"false"));
+
user_media_requests_.push_back(
new UserMediaRequestInfo(request_id, frame, user_media_request,
enable_automatic_output_device_selection));
@@ -230,7 +186,7 @@ void MediaStreamImpl::requestUserMedia(
}
void MediaStreamImpl::cancelUserMediaRequest(
- const WebKit::WebUserMediaRequest& user_media_request) {
+ const blink::WebUserMediaRequest& user_media_request) {
DCHECK(CalledOnValidThread());
UserMediaRequestInfo* request = FindUserMediaRequestInfo(user_media_request);
if (request) {
@@ -241,14 +197,14 @@ void MediaStreamImpl::cancelUserMediaRequest(
}
}
-WebKit::WebMediaStream MediaStreamImpl::GetMediaStream(
+blink::WebMediaStream MediaStreamImpl::GetMediaStream(
const GURL& url) {
- return WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url);
+ return blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url);
}
bool MediaStreamImpl::IsMediaStream(const GURL& url) {
- WebKit::WebMediaStream web_stream(
- WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url));
+ blink::WebMediaStream web_stream(
+ blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url));
if (web_stream.isNull() || !web_stream.extraData())
return false; // This is not a valid stream.
@@ -264,7 +220,7 @@ MediaStreamImpl::GetVideoFrameProvider(
const base::Closure& error_cb,
const VideoFrameProvider::RepaintCB& repaint_cb) {
DCHECK(CalledOnValidThread());
- WebKit::WebMediaStream web_stream(GetMediaStream(url));
+ blink::WebMediaStream web_stream(GetMediaStream(url));
if (web_stream.isNull() || !web_stream.extraData())
return NULL; // This is not a valid stream.
@@ -272,17 +228,18 @@ MediaStreamImpl::GetVideoFrameProvider(
DVLOG(1) << "MediaStreamImpl::GetVideoFrameProvider stream:"
<< UTF16ToUTF8(web_stream.id());
- webrtc::MediaStreamInterface* stream = GetNativeMediaStream(web_stream);
- if (stream)
- return CreateVideoFrameProvider(stream, error_cb, repaint_cb);
- NOTREACHED();
- return NULL;
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
+ web_stream.videoTracks(video_tracks);
+ if (video_tracks.isEmpty())
+ return NULL;
+
+ return new RTCVideoRenderer(video_tracks[0], error_cb, repaint_cb);
}
scoped_refptr<MediaStreamAudioRenderer>
MediaStreamImpl::GetAudioRenderer(const GURL& url) {
DCHECK(CalledOnValidThread());
- WebKit::WebMediaStream web_stream(GetMediaStream(url));
+ blink::WebMediaStream web_stream(GetMediaStream(url));
if (web_stream.isNull() || !web_stream.extraData())
return NULL; // This is not a valid stream.
@@ -295,7 +252,14 @@ MediaStreamImpl::GetAudioRenderer(const GURL& url) {
if (extra_data->is_local()) {
// Create the local audio renderer if the stream contains audio tracks.
- return CreateLocalAudioRenderer(extra_data->stream().get());
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
+ web_stream.audioTracks(audio_tracks);
+ if (audio_tracks.isEmpty())
+ return NULL;
+
+ // TODO(xians): Add support for the case that the media stream contains
+ // multiple audio tracks.
+ return CreateLocalAudioRenderer(audio_tracks[0]);
}
webrtc::MediaStreamInterface* stream = extra_data->stream().get();
@@ -332,42 +296,75 @@ void MediaStreamImpl::OnStreamGenerated(
if (!request_info) {
// This can happen if the request is canceled or the frame reloads while
// MediaStreamDispatcher is processing the request.
- // We need to tell the dispatcher to stop the stream.
- media_stream_dispatcher_->StopStream(label);
+ // Only stop the device if the device is not used in another MediaStream.
+ for (StreamDeviceInfoArray::const_iterator device_it = audio_array.begin();
+ device_it != audio_array.end(); ++device_it) {
+ if (!FindLocalSource(*device_it))
+ media_stream_dispatcher_->StopStreamDevice(*device_it);
+ }
+
+ for (StreamDeviceInfoArray::const_iterator device_it = video_array.begin();
+ device_it != video_array.end(); ++device_it) {
+ if (!FindLocalSource(*device_it))
+ media_stream_dispatcher_->StopStreamDevice(*device_it);
+ }
+
DVLOG(1) << "Request ID not found";
return;
}
request_info->generated = true;
- WebKit::WebVector<WebKit::WebMediaStreamSource> audio_source_vector(
- audio_array.size());
- CreateWebKitSourceVector(label, audio_array,
- WebKit::WebMediaStreamSource::TypeAudio,
+ blink::WebVector<blink::WebMediaStreamSource> audio_source_vector(
+ audio_array.size());
+
+ // Log the device names for this request.
+ for (StreamDeviceInfoArray::const_iterator it = audio_array.begin();
+ it != audio_array.end(); ++it) {
+ WebRtcLogMessage(base::StringPrintf(
+ "Generated media stream for request id %d contains audio device name"
+ " \"%s\"",
+ request_id,
+ it->device.name.c_str()));
+ }
+
+ StreamDeviceInfoArray overridden_audio_array = audio_array;
+ if (!request_info->enable_automatic_output_device_selection) {
+ // If the GetUserMedia request did not explicitly set the constraint
+ // kMediaStreamRenderToAssociatedSink, the output device parameters must
+ // be removed.
+ for (StreamDeviceInfoArray::iterator it = overridden_audio_array.begin();
+ it != overridden_audio_array.end(); ++it) {
+ it->device.matched_output_device_id = "";
+ it->device.matched_output = MediaStreamDevice::AudioDeviceParameters();
+ }
+ }
+ CreateWebKitSourceVector(label, overridden_audio_array,
+ blink::WebMediaStreamSource::TypeAudio,
+ request_info->frame,
audio_source_vector);
- request_info->audio_sources.assign(audio_source_vector);
- WebKit::WebVector<WebKit::WebMediaStreamSource> video_source_vector(
+
+ blink::WebVector<blink::WebMediaStreamSource> video_source_vector(
video_array.size());
CreateWebKitSourceVector(label, video_array,
- WebKit::WebMediaStreamSource::TypeVideo,
+ blink::WebMediaStreamSource::TypeVideo,
+ request_info->frame,
video_source_vector);
- request_info->video_sources.assign(video_source_vector);
+ blink::WebUserMediaRequest* request = &(request_info->request);
+ blink::WebString webkit_id = UTF8ToUTF16(label);
+ blink::WebMediaStream* web_stream = &(request_info->web_stream);
- WebKit::WebUserMediaRequest* request = &(request_info->request);
- WebKit::WebString webkit_id = UTF8ToUTF16(label);
- WebKit::WebMediaStream* web_stream = &(request_info->web_stream);
-
- WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_track_vector(
+ blink::WebVector<blink::WebMediaStreamTrack> audio_track_vector(
audio_array.size());
for (size_t i = 0; i < audio_track_vector.size(); ++i) {
- audio_track_vector[i].initialize(audio_source_vector[i].id(),
- audio_source_vector[i]);
+ audio_track_vector[i].initialize(audio_source_vector[i]);
+ request_info->sources.push_back(audio_source_vector[i]);
}
- WebKit::WebVector<WebKit::WebMediaStreamTrack> video_track_vector(
+ blink::WebVector<blink::WebMediaStreamTrack> video_track_vector(
video_array.size());
for (size_t i = 0; i < video_track_vector.size(); ++i) {
- video_track_vector[i].initialize(video_source_vector[i].id(),
- video_source_vector[i]);
+ video_track_vector[i].initialize(video_source_vector[i]);
+ request_info->sources.push_back(video_source_vector[i]);
}
web_stream->initialize(webkit_id, audio_track_vector,
@@ -375,10 +372,10 @@ void MediaStreamImpl::OnStreamGenerated(
// WebUserMediaRequest don't have an implementation in unit tests.
// Therefore we need to check for isNull here.
- WebKit::WebMediaConstraints audio_constraints = request->isNull() ?
- WebKit::WebMediaConstraints() : request->audioConstraints();
- WebKit::WebMediaConstraints video_constraints = request->isNull() ?
- WebKit::WebMediaConstraints() : request->videoConstraints();
+ blink::WebMediaConstraints audio_constraints = request->isNull() ?
+ blink::WebMediaConstraints() : request->audioConstraints();
+ blink::WebMediaConstraints video_constraints = request->isNull() ?
+ blink::WebMediaConstraints() : request->videoConstraints();
dependency_factory_->CreateNativeMediaSources(
RenderViewObserver::routing_id(),
@@ -406,27 +403,82 @@ void MediaStreamImpl::OnStreamGenerationFailed(int request_id) {
}
// Callback from MediaStreamDispatcher.
-// The user has requested to stop the media stream.
-void MediaStreamImpl::OnStopGeneratedStream(const std::string& label) {
+// The browser process has stopped a device used by a MediaStream.
+void MediaStreamImpl::OnDeviceStopped(
+ const std::string& label,
+ const StreamDeviceInfo& device_info) {
DCHECK(CalledOnValidThread());
- DVLOG(1) << "MediaStreamImpl::OnStopGeneratedStream(" << label << ")";
+ DVLOG(1) << "MediaStreamImpl::OnDeviceStopped("
+ << "{device_id = " << device_info.device.id << "})";
+
+ const blink::WebMediaStreamSource* source_ptr = FindLocalSource(device_info);
+ if (!source_ptr) {
+ // This happens if the same device is used in several guM requests or
+ // if a user happen stop a track from JS at the same time
+ // as the underlying media device is unplugged from the system.
+ return;
+ }
+ // By creating |source| it is guaranteed that the blink::WebMediaStreamSource
+ // object is valid during the cleanup.
+ blink::WebMediaStreamSource source(*source_ptr);
+ StopLocalSource(source, false);
+
+ for (LocalStreamSources::iterator device_it = local_sources_.begin();
+ device_it != local_sources_.end(); ++device_it) {
+ if (device_it->source.id() == source.id()) {
+ local_sources_.erase(device_it);
+ break;
+ }
+ }
- UserMediaRequestInfo* user_media_request = FindUserMediaRequestInfo(label);
- if (user_media_request) {
- // No need to call media_stream_dispatcher_->StopStream() because the
- // request has come from the browser process.
- StopLocalAudioTrack(user_media_request->web_stream);
- DeleteUserMediaRequestInfo(user_media_request);
- } else {
- DVLOG(1) << "MediaStreamImpl::OnStopGeneratedStream: the stream has "
- << "already been stopped.";
+ // Remove the reference to this source from all |user_media_requests_|.
+ // TODO(perkj): The below is not necessary once we don't need to support
+ // MediaStream::Stop().
+ UserMediaRequests::iterator it = user_media_requests_.begin();
+ while (it != user_media_requests_.end()) {
+ RemoveSource(source, &(*it)->sources);
+ if ((*it)->sources.empty()) {
+ it = user_media_requests_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+void MediaStreamImpl::CreateWebKitSourceVector(
+ const std::string& label,
+ const StreamDeviceInfoArray& devices,
+ blink::WebMediaStreamSource::Type type,
+ blink::WebFrame* frame,
+ blink::WebVector<blink::WebMediaStreamSource>& webkit_sources) {
+ CHECK_EQ(devices.size(), webkit_sources.size());
+ for (size_t i = 0; i < devices.size(); ++i) {
+ const blink::WebMediaStreamSource* existing_source =
+ FindLocalSource(devices[i]);
+ if (existing_source) {
+ webkit_sources[i] = *existing_source;
+ DVLOG(1) << "Source already exist. Reusing source with id "
+ << webkit_sources[i]. id().utf8();
+ continue;
+ }
+ webkit_sources[i].initialize(
+ UTF8ToUTF16(devices[i].device.id),
+ type,
+ UTF8ToUTF16(devices[i].device.name));
+ MediaStreamSourceExtraData* source_extra_data(
+ new content::MediaStreamSourceExtraData(
+ devices[i],
+ base::Bind(&MediaStreamImpl::OnLocalSourceStop, AsWeakPtr())));
+ // |source_extra_data| is owned by webkit_sources[i].
+ webkit_sources[i].setExtraData(source_extra_data);
+ local_sources_.push_back(LocalStreamSource(frame, webkit_sources[i]));
}
}
// Callback from MediaStreamDependencyFactory when the sources in |web_stream|
// have been generated.
void MediaStreamImpl::OnCreateNativeSourcesComplete(
- WebKit::WebMediaStream* web_stream,
+ blink::WebMediaStream* web_stream,
bool request_succeeded) {
UserMediaRequestInfo* request_info = FindUserMediaRequestInfo(web_stream);
if (!request_info) {
@@ -442,10 +494,16 @@ void MediaStreamImpl::OnCreateNativeSourcesComplete(
web_stream,
base::Bind(&MediaStreamImpl::OnLocalMediaStreamStop, AsWeakPtr()));
}
+ DVLOG(1) << "MediaStreamImpl::OnCreateNativeSourcesComplete("
+ << "{request_id = " << request_info->request_id << "} "
+ << "{request_succeeded = " << request_succeeded << "})";
CompleteGetUserMediaRequest(request_info->web_stream, &request_info->request,
request_succeeded);
if (!request_succeeded) {
- OnLocalMediaStreamStop(UTF16ToUTF8(web_stream->id()));
+ // TODO(perkj): Once we don't support MediaStream::Stop the |request_info|
+ // can be deleted even if the request succeeds.
+ DeleteUserMediaRequestInfo(request_info);
+ StopUnreferencedSources(true);
}
}
@@ -457,12 +515,6 @@ void MediaStreamImpl::OnDevicesEnumerated(
NOTIMPLEMENTED();
}
-void MediaStreamImpl::OnDevicesEnumerationFailed(int request_id) {
- DVLOG(1) << "MediaStreamImpl::OnDevicesEnumerationFailed("
- << request_id << ")";
- NOTIMPLEMENTED();
-}
-
void MediaStreamImpl::OnDeviceOpened(
int request_id,
const std::string& label,
@@ -479,8 +531,8 @@ void MediaStreamImpl::OnDeviceOpenFailed(int request_id) {
}
void MediaStreamImpl::CompleteGetUserMediaRequest(
- const WebKit::WebMediaStream& stream,
- WebKit::WebUserMediaRequest* request_info,
+ const blink::WebMediaStream& stream,
+ blink::WebUserMediaRequest* request_info,
bool request_succeeded) {
if (request_succeeded) {
request_info->requestSucceeded(stream);
@@ -489,6 +541,40 @@ void MediaStreamImpl::CompleteGetUserMediaRequest(
}
}
+const blink::WebMediaStreamSource* MediaStreamImpl::FindLocalSource(
+ const StreamDeviceInfo& device) const {
+ for (LocalStreamSources::const_iterator it = local_sources_.begin();
+ it != local_sources_.end(); ++it) {
+ MediaStreamSourceExtraData* extra_data =
+ static_cast<MediaStreamSourceExtraData*>(
+ it->source.extraData());
+ const StreamDeviceInfo& active_device = extra_data->device_info();
+ if (active_device.device.id == device.device.id &&
+ active_device.device.type == device.device.type &&
+ active_device.session_id == device.session_id) {
+ return &it->source;
+ }
+ }
+ return NULL;
+}
+
+bool MediaStreamImpl::FindSourceInRequests(
+ const blink::WebMediaStreamSource& source) const {
+ for (UserMediaRequests::const_iterator req_it = user_media_requests_.begin();
+ req_it != user_media_requests_.end(); ++req_it) {
+ const std::vector<blink::WebMediaStreamSource>& sources =
+ (*req_it)->sources;
+ for (std::vector<blink::WebMediaStreamSource>::const_iterator source_it =
+ sources.begin();
+ source_it != sources.end(); ++source_it) {
+ if (source_it->id() == source.id()) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
MediaStreamImpl::UserMediaRequestInfo*
MediaStreamImpl::FindUserMediaRequestInfo(int request_id) {
UserMediaRequests::iterator it = user_media_requests_.begin();
@@ -501,7 +587,7 @@ MediaStreamImpl::FindUserMediaRequestInfo(int request_id) {
MediaStreamImpl::UserMediaRequestInfo*
MediaStreamImpl::FindUserMediaRequestInfo(
- const WebKit::WebUserMediaRequest& request) {
+ const blink::WebUserMediaRequest& request) {
UserMediaRequests::iterator it = user_media_requests_.begin();
for (; it != user_media_requests_.end(); ++it) {
if ((*it)->request == request)
@@ -522,7 +608,7 @@ MediaStreamImpl::FindUserMediaRequestInfo(const std::string& label) {
MediaStreamImpl::UserMediaRequestInfo*
MediaStreamImpl::FindUserMediaRequestInfo(
- WebKit::WebMediaStream* web_stream) {
+ blink::WebMediaStream* web_stream) {
UserMediaRequests::iterator it = user_media_requests_.begin();
for (; it != user_media_requests_.end(); ++it) {
if (&((*it)->web_stream) == web_stream)
@@ -543,31 +629,24 @@ void MediaStreamImpl::DeleteUserMediaRequestInfo(
NOTREACHED();
}
-void MediaStreamImpl::FrameDetached(WebKit::WebFrame* frame) {
+void MediaStreamImpl::FrameDetached(blink::WebFrame* frame) {
// Do same thing as FrameWillClose.
FrameWillClose(frame);
}
-void MediaStreamImpl::FrameWillClose(WebKit::WebFrame* frame) {
+void MediaStreamImpl::FrameWillClose(blink::WebFrame* frame) {
// Loop through all UserMediaRequests and find the requests that belong to the
// frame that is being closed.
UserMediaRequests::iterator request_it = user_media_requests_.begin();
-
while (request_it != user_media_requests_.end()) {
if ((*request_it)->frame == frame) {
DVLOG(1) << "MediaStreamImpl::FrameWillClose: "
<< "Cancel user media request " << (*request_it)->request_id;
- // If the request is generated, it means that the MediaStreamDispatcher
- // has generated a stream for us and we need to let the
- // MediaStreamDispatcher know that the stream is no longer wanted.
- // If not, we cancel the request and delete the request object.
- if ((*request_it)->generated) {
- // Stop the local audio track before closing the device in the browser.
- StopLocalAudioTrack((*request_it)->web_stream);
-
- media_stream_dispatcher_->StopStream(
- UTF16ToUTF8((*request_it)->web_stream.id()));
- } else {
+ // If the request is not generated, it means that a request
+ // has been sent to the MediaStreamDispatcher to generate a stream
+ // but MediaStreamDispatcher has not yet responded and we need to cancel
+ // the request.
+ if (!(*request_it)->generated) {
media_stream_dispatcher_->CancelGenerateStream(
(*request_it)->request_id, AsWeakPtr());
}
@@ -576,23 +655,96 @@ void MediaStreamImpl::FrameWillClose(WebKit::WebFrame* frame) {
++request_it;
}
}
+
+ // Loop through all current local sources and stop the sources that were
+ // created by the frame that will be closed.
+ LocalStreamSources::iterator sources_it = local_sources_.begin();
+ while (sources_it != local_sources_.end()) {
+ if (sources_it->frame == frame) {
+ StopLocalSource(sources_it->source, true);
+ sources_it = local_sources_.erase(sources_it);
+ } else {
+ ++sources_it;
+ }
+ }
}
-scoped_refptr<VideoFrameProvider>
-MediaStreamImpl::CreateVideoFrameProvider(
- webrtc::MediaStreamInterface* stream,
- const base::Closure& error_cb,
- const VideoFrameProvider::RepaintCB& repaint_cb) {
- if (stream->GetVideoTracks().empty())
- return NULL;
+void MediaStreamImpl::OnLocalMediaStreamStop(
+ const std::string& label) {
+ DVLOG(1) << "MediaStreamImpl::OnLocalMediaStreamStop(" << label << ")";
- DVLOG(1) << "MediaStreamImpl::CreateRemoteVideoFrameProvider label:"
- << stream->label();
+ UserMediaRequestInfo* user_media_request = FindUserMediaRequestInfo(label);
+ if (user_media_request) {
+ DeleteUserMediaRequestInfo(user_media_request);
+ }
+ StopUnreferencedSources(true);
+}
+
+void MediaStreamImpl::OnLocalSourceStop(
+ const blink::WebMediaStreamSource& source) {
+ DCHECK(CalledOnValidThread());
+
+ StopLocalSource(source, true);
+
+ bool device_found = false;
+ for (LocalStreamSources::iterator device_it = local_sources_.begin();
+ device_it != local_sources_.end(); ++device_it) {
+ if (device_it->source.id() == source.id()) {
+ device_found = true;
+ local_sources_.erase(device_it);
+ break;
+ }
+ }
+ CHECK(device_found);
+
+ // Remove the reference to this source from all |user_media_requests_|.
+ // TODO(perkj): The below is not necessary once we don't need to support
+ // MediaStream::Stop().
+ UserMediaRequests::iterator it = user_media_requests_.begin();
+ while (it != user_media_requests_.end()) {
+ RemoveSource(source, &(*it)->sources);
+ if ((*it)->sources.empty()) {
+ it = user_media_requests_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+void MediaStreamImpl::StopLocalSource(
+ const blink::WebMediaStreamSource& source,
+ bool notify_dispatcher) {
+ MediaStreamSourceExtraData* extra_data =
+ static_cast<MediaStreamSourceExtraData*> (source.extraData());
+ CHECK(extra_data);
+ DVLOG(1) << "MediaStreamImpl::StopLocalSource("
+ << "{device_id = " << extra_data->device_info().device.id << "})";
+
+ if (source.type() == blink::WebMediaStreamSource::TypeAudio) {
+ if (extra_data->GetAudioCapturer()) {
+ extra_data->GetAudioCapturer()->Stop();
+ }
+ }
+
+ if (notify_dispatcher)
+ media_stream_dispatcher_->StopStreamDevice(extra_data->device_info());
- return new RTCVideoRenderer(
- stream->GetVideoTracks()[0],
- error_cb,
- repaint_cb);
+ blink::WebMediaStreamSource writable_source(source);
+ writable_source.setReadyState(
+ blink::WebMediaStreamSource::ReadyStateEnded);
+ writable_source.setExtraData(NULL);
+}
+
+void MediaStreamImpl::StopUnreferencedSources(bool notify_dispatcher) {
+ LocalStreamSources::iterator source_it = local_sources_.begin();
+ while (source_it != local_sources_.end()) {
+ if (!FindSourceInRequests(source_it->source)) {
+ StopLocalSource(source_it->source, notify_dispatcher);
+ source_it = local_sources_.erase(source_it);
+ } else {
+ ++source_it;
+ }
+ }
}
scoped_refptr<WebRtcAudioRenderer> MediaStreamImpl::CreateRemoteAudioRenderer(
@@ -618,19 +770,8 @@ scoped_refptr<WebRtcAudioRenderer> MediaStreamImpl::CreateRemoteAudioRenderer(
scoped_refptr<WebRtcLocalAudioRenderer>
MediaStreamImpl::CreateLocalAudioRenderer(
- webrtc::MediaStreamInterface* stream) {
- if (stream->GetAudioTracks().empty())
- return NULL;
-
- DVLOG(1) << "MediaStreamImpl::CreateLocalAudioRenderer label:"
- << stream->label();
-
- webrtc::AudioTrackVector audio_tracks = stream->GetAudioTracks();
- DCHECK_EQ(audio_tracks.size(), 1u);
- webrtc::AudioTrackInterface* audio_track = audio_tracks[0];
- DVLOG(1) << "audio_track.kind : " << audio_track->kind()
- << "audio_track.id : " << audio_track->id()
- << "audio_track.enabled: " << audio_track->enabled();
+ const blink::WebMediaStreamTrack& audio_track) {
+ DVLOG(1) << "MediaStreamImpl::CreateLocalAudioRenderer";
int session_id = 0, sample_rate = 0, buffer_size = 0;
if (!GetAuthorizedDeviceInfoForAudioRenderer(&session_id,
@@ -642,89 +783,37 @@ MediaStreamImpl::CreateLocalAudioRenderer(
// Create a new WebRtcLocalAudioRenderer instance and connect it to the
// existing WebRtcAudioCapturer so that the renderer can use it as source.
return new WebRtcLocalAudioRenderer(
- static_cast<WebRtcLocalAudioTrack*>(audio_track),
+ audio_track,
RenderViewObserver::routing_id(),
session_id,
- sample_rate,
buffer_size);
}
-void MediaStreamImpl::StopLocalAudioTrack(
- const WebKit::WebMediaStream& web_stream) {
- MediaStreamExtraData* extra_data = static_cast<MediaStreamExtraData*>(
- web_stream.extraData());
- if (extra_data && extra_data->is_local() && extra_data->stream().get() &&
- !extra_data->stream()->GetAudioTracks().empty()) {
- webrtc::AudioTrackVector audio_tracks =
- extra_data->stream()->GetAudioTracks();
- for (size_t i = 0; i < audio_tracks.size(); ++i) {
- WebRtcLocalAudioTrack* audio_track = static_cast<WebRtcLocalAudioTrack*>(
- audio_tracks[i].get());
- // Remove the WebRtcAudioDevice as the sink to the local audio track.
- audio_track->RemoveSink(dependency_factory_->GetWebRtcAudioDevice());
- // Stop the audio track. This will unhook the audio track from the
- // capturer and will shutdown the source of the capturer if it is the
- // last audio track connecting to the capturer.
- audio_track->Stop();
- }
- }
-}
-
bool MediaStreamImpl::GetAuthorizedDeviceInfoForAudioRenderer(
int* session_id,
int* output_sample_rate,
int* output_frames_per_buffer) {
DCHECK(CalledOnValidThread());
- const StreamDeviceInfo* device_info = NULL;
- WebKit::WebString session_id_str;
- UserMediaRequests::iterator it = user_media_requests_.begin();
- for (; it != user_media_requests_.end(); ++it) {
- UserMediaRequestInfo* request = (*it);
- for (size_t i = 0; i < request->audio_sources.size(); ++i) {
- const WebKit::WebMediaStreamSource& source = request->audio_sources[i];
- if (source.readyState() == WebKit::WebMediaStreamSource::ReadyStateEnded)
- continue;
-
- // Check if this request explicitly turned on the automatic output
- // device selection constraint.
- if (!request->enable_automatic_output_device_selection)
- continue;
-
- if (!session_id_str.isEmpty() &&
- !session_id_str.equals(source.deviceId())) {
- DVLOG(1) << "Multiple capture devices are open so we can't pick a "
- "session for a matching output device.";
- return false;
- }
-
- // TODO(tommi): Storing the session id in the deviceId field doesn't
- // feel right. Move it over to MediaStreamSourceExtraData?
- session_id_str = source.deviceId();
- content::MediaStreamSourceExtraData* extra_data =
- static_cast<content::MediaStreamSourceExtraData*>(source.extraData());
- device_info = &extra_data->device_info();
- }
- }
-
- if (session_id_str.isEmpty() || !device_info ||
- !device_info->device.matched_output.sample_rate) {
+ WebRtcAudioDeviceImpl* audio_device =
+ dependency_factory_->GetWebRtcAudioDevice();
+ if (!audio_device)
return false;
- }
- base::StringToInt(UTF16ToUTF8(session_id_str), session_id);
- *output_sample_rate = device_info->device.matched_output.sample_rate;
- *output_frames_per_buffer =
- device_info->device.matched_output.frames_per_buffer;
+ if (!audio_device->GetDefaultCapturer())
+ return false;
- return true;
+ return audio_device->GetDefaultCapturer()->GetPairedOutputParameters(
+ session_id,
+ output_sample_rate,
+ output_frames_per_buffer);
}
MediaStreamSourceExtraData::MediaStreamSourceExtraData(
const StreamDeviceInfo& device_info,
- const WebKit::WebMediaStreamSource& webkit_source)
+ const SourceStopCallback& stop_callback)
: device_info_(device_info),
- webkit_source_(webkit_source) {
+ stop_callback_(stop_callback) {
}
MediaStreamSourceExtraData::MediaStreamSourceExtraData() {
@@ -732,6 +821,11 @@ MediaStreamSourceExtraData::MediaStreamSourceExtraData() {
MediaStreamSourceExtraData::~MediaStreamSourceExtraData() {}
+void MediaStreamSourceExtraData::OnLocalSourceStop() {
+ if (!stop_callback_.is_null())
+ stop_callback_.Run(owner());
+}
+
MediaStreamExtraData::MediaStreamExtraData(
webrtc::MediaStreamInterface* stream, bool is_local)
: stream_(stream),
@@ -753,8 +847,8 @@ void MediaStreamExtraData::OnLocalStreamStop() {
MediaStreamImpl::UserMediaRequestInfo::UserMediaRequestInfo(
int request_id,
- WebKit::WebFrame* frame,
- const WebKit::WebUserMediaRequest& request,
+ blink::WebFrame* frame,
+ const blink::WebUserMediaRequest& request,
bool enable_automatic_output_device_selection)
: request_id(request_id),
generated(false),
@@ -765,22 +859,6 @@ MediaStreamImpl::UserMediaRequestInfo::UserMediaRequestInfo(
}
MediaStreamImpl::UserMediaRequestInfo::~UserMediaRequestInfo() {
- // Release the extra data field of all sources created by
- // MediaStreamImpl for this request. This breaks the circular reference to
- // WebKit::MediaStreamSource.
- // TODO(tommyw): Remove this once WebKit::MediaStreamSource::Owner has been
- // implemented to fully avoid a circular dependency.
- for (size_t i = 0; i < audio_sources.size(); ++i) {
- audio_sources[i].setReadyState(
- WebKit::WebMediaStreamSource::ReadyStateEnded);
- audio_sources[i].setExtraData(NULL);
- }
-
- for (size_t i = 0; i < video_sources.size(); ++i) {
- video_sources[i].setReadyState(
- WebKit::WebMediaStreamSource::ReadyStateEnded);
- video_sources[i].setExtraData(NULL);
- }
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_impl.h b/chromium/content/renderer/media/media_stream_impl.h
index 8329d5f0b8d..8f72d2ba287 100644
--- a/chromium/content/renderer/media/media_stream_impl.h
+++ b/chromium/content/renderer/media/media_stream_impl.h
@@ -20,6 +20,8 @@
#include "content/renderer/media/media_stream_client.h"
#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebUserMediaClient.h"
#include "third_party/WebKit/public/web/WebUserMediaRequest.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
@@ -28,6 +30,7 @@ namespace content {
class MediaStreamAudioRenderer;
class MediaStreamDependencyFactory;
class MediaStreamDispatcher;
+class MediaStreamSourceExtraData;
class WebRtcAudioRenderer;
class WebRtcLocalAudioRenderer;
@@ -39,7 +42,7 @@ class WebRtcLocalAudioRenderer;
// MediaStreamImpl have weak pointers to a MediaStreamDispatcher.
class CONTENT_EXPORT MediaStreamImpl
: public RenderViewObserver,
- NON_EXPORTED_BASE(public WebKit::WebUserMediaClient),
+ NON_EXPORTED_BASE(public blink::WebUserMediaClient),
NON_EXPORTED_BASE(public MediaStreamClient),
public MediaStreamDispatcherEventHandler,
public base::SupportsWeakPtr<MediaStreamImpl>,
@@ -51,11 +54,11 @@ class CONTENT_EXPORT MediaStreamImpl
MediaStreamDependencyFactory* dependency_factory);
virtual ~MediaStreamImpl();
- // WebKit::WebUserMediaClient implementation
+ // blink::WebUserMediaClient implementation
virtual void requestUserMedia(
- const WebKit::WebUserMediaRequest& user_media_request) OVERRIDE;
+ const blink::WebUserMediaRequest& user_media_request) OVERRIDE;
virtual void cancelUserMediaRequest(
- const WebKit::WebUserMediaRequest& user_media_request) OVERRIDE;
+ const blink::WebUserMediaRequest& user_media_request) OVERRIDE;
// MediaStreamClient implementation.
virtual bool IsMediaStream(const GURL& url) OVERRIDE;
@@ -73,11 +76,11 @@ class CONTENT_EXPORT MediaStreamImpl
const StreamDeviceInfoArray& audio_array,
const StreamDeviceInfoArray& video_array) OVERRIDE;
virtual void OnStreamGenerationFailed(int request_id) OVERRIDE;
- virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE;
+ virtual void OnDeviceStopped(const std::string& label,
+ const StreamDeviceInfo& device_info) OVERRIDE;
virtual void OnDevicesEnumerated(
int request_id,
const StreamDeviceInfoArray& device_array) OVERRIDE;
- virtual void OnDevicesEnumerationFailed(int request_id) OVERRIDE;
virtual void OnDeviceOpened(
int request_id,
const std::string& label,
@@ -85,12 +88,12 @@ class CONTENT_EXPORT MediaStreamImpl
virtual void OnDeviceOpenFailed(int request_id) OVERRIDE;
// RenderViewObserver OVERRIDE
- virtual void FrameDetached(WebKit::WebFrame* frame) OVERRIDE;
- virtual void FrameWillClose(WebKit::WebFrame* frame) OVERRIDE;
+ virtual void FrameDetached(blink::WebFrame* frame) OVERRIDE;
+ virtual void FrameWillClose(blink::WebFrame* frame) OVERRIDE;
protected:
- // Stops a local MediaStream by notifying the MediaStreamDispatcher that the
- // stream no longer may be used.
+ void OnLocalSourceStop(const blink::WebMediaStreamSource& source);
+
void OnLocalMediaStreamStop(const std::string& label);
// Callback function triggered when all native (libjingle) versions of the
@@ -99,28 +102,28 @@ class CONTENT_EXPORT MediaStreamImpl
// UserMediaRequests::web_stream for which the underlying sources have been
// created.
void OnCreateNativeSourcesComplete(
- WebKit::WebMediaStream* web_stream,
+ blink::WebMediaStream* web_stream,
bool request_succeeded);
// This function is virtual for test purposes. A test can override this to
// test requesting local media streams. The function notifies WebKit that the
// |request| have completed and generated the MediaStream |stream|.
virtual void CompleteGetUserMediaRequest(
- const WebKit::WebMediaStream& stream,
- WebKit::WebUserMediaRequest* request_info,
+ const blink::WebMediaStream& stream,
+ blink::WebUserMediaRequest* request_info,
bool request_succeeded);
// Returns the WebKit representation of a MediaStream given an URL.
// This is virtual for test purposes.
- virtual WebKit::WebMediaStream GetMediaStream(const GURL& url);
+ virtual blink::WebMediaStream GetMediaStream(const GURL& url);
private:
// Structure for storing information about a WebKit request to create a
// MediaStream.
struct UserMediaRequestInfo {
UserMediaRequestInfo(int request_id,
- WebKit::WebFrame* frame,
- const WebKit::WebUserMediaRequest& request,
+ blink::WebFrame* frame,
+ const blink::WebUserMediaRequest& request,
bool enable_automatic_output_device_selection);
~UserMediaRequestInfo();
int request_id;
@@ -128,33 +131,60 @@ class CONTENT_EXPORT MediaStreamImpl
// OnStreamGenerated.
bool generated;
const bool enable_automatic_output_device_selection;
- WebKit::WebFrame* frame; // WebFrame that requested the MediaStream.
- WebKit::WebMediaStream web_stream;
- WebKit::WebUserMediaRequest request;
- WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources;
- WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources;
+ blink::WebFrame* frame; // WebFrame that requested the MediaStream.
+ blink::WebMediaStream web_stream;
+ blink::WebUserMediaRequest request;
+ std::vector<blink::WebMediaStreamSource> sources;
};
typedef ScopedVector<UserMediaRequestInfo> UserMediaRequests;
+ struct LocalStreamSource {
+ LocalStreamSource(blink::WebFrame* frame,
+ const blink::WebMediaStreamSource& source)
+ : frame(frame), source(source) {
+ }
+ // |frame| is the WebFrame that requested |source|. NULL in unit tests.
+ // TODO(perkj): Change so that |frame| is not NULL in unit tests.
+ blink::WebFrame* frame;
+ blink::WebMediaStreamSource source;
+ };
+ typedef std::vector<LocalStreamSource> LocalStreamSources;
+
+ // Creates a WebKit representation of stream sources based on
+ // |devices| from the MediaStreamDispatcher.
+ void CreateWebKitSourceVector(
+ const std::string& label,
+ const StreamDeviceInfoArray& devices,
+ blink::WebMediaStreamSource::Type type,
+ blink::WebFrame* frame,
+ blink::WebVector<blink::WebMediaStreamSource>& webkit_sources);
+
UserMediaRequestInfo* FindUserMediaRequestInfo(int request_id);
UserMediaRequestInfo* FindUserMediaRequestInfo(
- WebKit::WebMediaStream* web_stream);
+ blink::WebMediaStream* web_stream);
UserMediaRequestInfo* FindUserMediaRequestInfo(
- const WebKit::WebUserMediaRequest& request);
+ const blink::WebUserMediaRequest& request);
UserMediaRequestInfo* FindUserMediaRequestInfo(const std::string& label);
void DeleteUserMediaRequestInfo(UserMediaRequestInfo* request);
- scoped_refptr<VideoFrameProvider>
- CreateVideoFrameProvider(
- webrtc::MediaStreamInterface* stream,
- const base::Closure& error_cb,
- const VideoFrameProvider::RepaintCB& repaint_cb);
+ // Returns the source that use a device with |device.session_id|
+ // and |device.device.id|. NULL if such source doesn't exist.
+ const blink::WebMediaStreamSource* FindLocalSource(
+ const StreamDeviceInfo& device) const;
+
+ // Returns true if |source| exists in |user_media_requests_|
+ bool FindSourceInRequests(const blink::WebMediaStreamSource& source) const;
+
+ void StopLocalSource(const blink::WebMediaStreamSource& source,
+ bool notify_dispatcher);
+ // Stops all local sources that don't exist in exist in
+ // |user_media_requests_|.
+ void StopUnreferencedSources(bool notify_dispatcher);
+
scoped_refptr<WebRtcAudioRenderer> CreateRemoteAudioRenderer(
webrtc::MediaStreamInterface* stream);
scoped_refptr<WebRtcLocalAudioRenderer> CreateLocalAudioRenderer(
- webrtc::MediaStreamInterface* stream);
-
- void StopLocalAudioTrack(const WebKit::WebMediaStream& web_stream);
+ const blink::WebMediaStreamTrack& audio_track);
// Returns a valid session id if a single capture device is currently open
// (and then the matching session_id), otherwise -1.
@@ -176,6 +206,8 @@ class CONTENT_EXPORT MediaStreamImpl
UserMediaRequests user_media_requests_;
+ LocalStreamSources local_sources_;
+
DISALLOW_COPY_AND_ASSIGN(MediaStreamImpl);
};
diff --git a/chromium/content/renderer/media/media_stream_impl_unittest.cc b/chromium/content/renderer/media/media_stream_impl_unittest.cc
index ea0b834039e..644f2cd483d 100644
--- a/chromium/content/renderer/media/media_stream_impl_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_impl_unittest.cc
@@ -34,34 +34,35 @@ class MediaStreamImplUnderTest : public MediaStreamImpl {
}
void RequestUserMedia() {
- WebKit::WebUserMediaRequest user_media_request;
+ blink::WebUserMediaRequest user_media_request;
state_ = REQUEST_NOT_COMPLETE;
requestUserMedia(user_media_request);
}
virtual void CompleteGetUserMediaRequest(
- const WebKit::WebMediaStream& stream,
- WebKit::WebUserMediaRequest* request_info,
+ const blink::WebMediaStream& stream,
+ blink::WebUserMediaRequest* request_info,
bool request_succeeded) OVERRIDE {
last_generated_stream_ = stream;
state_ = request_succeeded ? REQUEST_SUCCEEDED : REQUEST_FAILED;
}
- virtual WebKit::WebMediaStream GetMediaStream(
+ virtual blink::WebMediaStream GetMediaStream(
const GURL& url) OVERRIDE {
return last_generated_stream_;
}
using MediaStreamImpl::OnLocalMediaStreamStop;
+ using MediaStreamImpl::OnLocalSourceStop;
- const WebKit::WebMediaStream& last_generated_stream() {
+ const blink::WebMediaStream& last_generated_stream() {
return last_generated_stream_;
}
RequestState request_state() const { return state_; }
private:
- WebKit::WebMediaStream last_generated_stream_;
+ blink::WebMediaStream last_generated_stream_;
RequestState state_;
};
@@ -75,7 +76,7 @@ class MediaStreamImplTest : public ::testing::Test {
dependency_factory_.get()));
}
- WebKit::WebMediaStream RequestLocalMediaStream() {
+ blink::WebMediaStream RequestLocalMediaStream() {
ms_impl_->RequestUserMedia();
FakeMediaStreamDispatcherComplete();
ChangeVideoSourceStateToLive();
@@ -84,7 +85,7 @@ class MediaStreamImplTest : public ::testing::Test {
EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED,
ms_impl_->request_state());
- WebKit::WebMediaStream desc = ms_impl_->last_generated_stream();
+ blink::WebMediaStream desc = ms_impl_->last_generated_stream();
content::MediaStreamExtraData* extra_data =
static_cast<content::MediaStreamExtraData*>(desc.extraData());
if (!extra_data || !extra_data->stream().get()) {
@@ -136,26 +137,128 @@ class MediaStreamImplTest : public ::testing::Test {
scoped_ptr<MockMediaStreamDependencyFactory> dependency_factory_;
};
-TEST_F(MediaStreamImplTest, LocalMediaStream) {
- // Test a stream with both audio and video.
- WebKit::WebMediaStream mixed_desc = RequestLocalMediaStream();
+TEST_F(MediaStreamImplTest, GenerateMediaStream) {
+ // Generate a stream with both audio and video.
+ blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
+}
+
+// Test that the same source object is used if two MediaStreams are generated
+// using the same source.
+TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithSameSource) {
+ blink::WebMediaStream desc1 = RequestLocalMediaStream();
+ blink::WebMediaStream desc2 = RequestLocalMediaStream();
+
+ blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
+ desc1.videoTracks(desc1_video_tracks);
+ blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
+ desc2.videoTracks(desc2_video_tracks);
+ EXPECT_EQ(desc1_video_tracks[0].source().id(),
+ desc2_video_tracks[0].source().id());
+
+ EXPECT_EQ(desc1_video_tracks[0].source().extraData(),
+ desc2_video_tracks[0].source().extraData());
+
+ blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
+ desc1.audioTracks(desc1_audio_tracks);
+ blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
+ desc2.audioTracks(desc2_audio_tracks);
+ EXPECT_EQ(desc1_audio_tracks[0].source().id(),
+ desc2_audio_tracks[0].source().id());
+
+ EXPECT_EQ(desc1_audio_tracks[0].source().extraData(),
+ desc2_audio_tracks[0].source().extraData());
+}
- // Test a stream with audio only.
- WebKit::WebMediaStream audio_desc = RequestLocalMediaStream();
+// Test that the same source object is not used if two MediaStreams are
+// generated using different sources.
+TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithDifferentSources) {
+ blink::WebMediaStream desc1 = RequestLocalMediaStream();
+ // Make sure another device is selected (another |session_id|) in the next
+ // gUM request.
+ ms_dispatcher_->IncrementSessionId();
+ blink::WebMediaStream desc2 = RequestLocalMediaStream();
+
+ blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
+ desc1.videoTracks(desc1_video_tracks);
+ blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
+ desc2.videoTracks(desc2_video_tracks);
+ EXPECT_NE(desc1_video_tracks[0].source().id(),
+ desc2_video_tracks[0].source().id());
+
+ EXPECT_NE(desc1_video_tracks[0].source().extraData(),
+ desc2_video_tracks[0].source().extraData());
+
+ blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
+ desc1.audioTracks(desc1_audio_tracks);
+ blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
+ desc2.audioTracks(desc2_audio_tracks);
+ EXPECT_NE(desc1_audio_tracks[0].source().id(),
+ desc2_audio_tracks[0].source().id());
+
+ EXPECT_NE(desc1_audio_tracks[0].source().extraData(),
+ desc2_audio_tracks[0].source().extraData());
+}
- // Test a stream with video only.
- WebKit::WebMediaStream video_desc = RequestLocalMediaStream();
+TEST_F(MediaStreamImplTest, StopLocalMediaStream) {
+ // Generate a stream with both audio and video.
+ blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
// Stop generated local streams.
ms_impl_->OnLocalMediaStreamStop(mixed_desc.id().utf8());
- EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter());
- ms_impl_->OnLocalMediaStreamStop(audio_desc.id().utf8());
- EXPECT_EQ(2, ms_dispatcher_->stop_stream_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+}
+
+// This test that a source is not stopped even if the MediaStream is stopped if
+// there are two MediaStreams using the same device. The source is stopped
+// if there are no more MediaStreams using the device.
+TEST_F(MediaStreamImplTest, StopLocalMediaStreamWhenTwoStreamUseSameDevices) {
+ // Generate a stream with both audio and video.
+ blink::WebMediaStream desc1 = RequestLocalMediaStream();
+ blink::WebMediaStream desc2 = RequestLocalMediaStream();
+
+ ms_impl_->OnLocalMediaStreamStop(desc2.id().utf8());
+ EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
+
+ ms_impl_->OnLocalMediaStreamStop(desc1.id().utf8());
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+}
+
+// Test that the source is stopped even if there are two MediaStreams using
+// the same source.
+TEST_F(MediaStreamImplTest, StopSource) {
+ // Generate a stream with both audio and video.
+ blink::WebMediaStream desc1 = RequestLocalMediaStream();
+ blink::WebMediaStream desc2 = RequestLocalMediaStream();
+
+ // Stop the video source.
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
+ desc1.videoTracks(video_tracks);
+ ms_impl_->OnLocalSourceStop(video_tracks[0].source());
+ EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+
+ // Stop the audio source.
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
+ desc1.audioTracks(audio_tracks);
+ ms_impl_->OnLocalSourceStop(audio_tracks[0].source());
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+}
+
+// Test that the MediaStreams are deleted if the owning WebFrame is deleted.
+// In the unit test the owning frame is NULL.
+TEST_F(MediaStreamImplTest, FrameWillClose) {
+ // Test a stream with both audio and video.
+ blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
// Test that the MediaStreams are deleted if the owning WebFrame is deleted.
// In the unit test the owning frame is NULL.
ms_impl_->FrameWillClose(NULL);
- EXPECT_EQ(3, ms_dispatcher_->stop_stream_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
}
// This test what happens if a source to a MediaSteam fails to start.
@@ -167,7 +270,8 @@ TEST_F(MediaStreamImplTest, MediaSourceFailToStart) {
EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED,
ms_impl_->request_state());
EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
- EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
}
// This test what happens if MediaStreamImpl is deleted while the sources of a
@@ -189,7 +293,8 @@ TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingStream) {
ms_impl_->RequestUserMedia();
ms_impl_->FrameWillClose(NULL);
EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
- EXPECT_EQ(0, ms_dispatcher_->stop_stream_counter());
+ EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
ChangeAudioSourceStateToLive();
ChangeVideoSourceStateToLive();
EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
@@ -201,10 +306,10 @@ TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingStream) {
TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingSources) {
ms_impl_->RequestUserMedia();
FakeMediaStreamDispatcherComplete();
- EXPECT_EQ(0, ms_dispatcher_->stop_stream_counter());
EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
ms_impl_->FrameWillClose(NULL);
- EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
ChangeAudioSourceStateToLive();
ChangeVideoSourceStateToLive();
EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
@@ -214,13 +319,14 @@ TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingSources) {
// This test what happens if stop is called on a stream after the frame has
// been reloaded.
TEST_F(MediaStreamImplTest, StopStreamAfterReload) {
- WebKit::WebMediaStream mixed_desc = RequestLocalMediaStream();
- EXPECT_EQ(0, ms_dispatcher_->stop_stream_counter());
+ blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
ms_impl_->FrameWillClose(NULL);
- EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
ms_impl_->OnLocalMediaStreamStop(mixed_desc.id().utf8());
- EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_registry_interface.h b/chromium/content/renderer/media/media_stream_registry_interface.h
index af4c26a4e78..ace11c5e396 100644
--- a/chromium/content/renderer/media/media_stream_registry_interface.h
+++ b/chromium/content/renderer/media/media_stream_registry_interface.h
@@ -14,7 +14,7 @@ namespace content {
// Interface to get WebMediaStream from its url.
class MediaStreamRegistryInterface {
public:
- virtual WebKit::WebMediaStream GetMediaStream(const std::string& url) = 0;
+ virtual blink::WebMediaStream GetMediaStream(const std::string& url) = 0;
protected:
virtual ~MediaStreamRegistryInterface() {}
diff --git a/chromium/content/renderer/media/media_stream_source_extra_data.h b/chromium/content/renderer/media/media_stream_source_extra_data.h
index bb06435c158..4b88c147f8b 100644
--- a/chromium/content/renderer/media/media_stream_source_extra_data.h
+++ b/chromium/content/renderer/media/media_stream_source_extra_data.h
@@ -5,29 +5,28 @@
#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_SOURCE_EXTRA_DATA_H_
#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_SOURCE_EXTRA_DATA_H_
+#include "base/callback.h"
#include "base/compiler_specific.h"
#include "content/common/content_export.h"
#include "content/common/media/media_stream_options.h"
#include "content/renderer/media/media_stream_source_observer.h"
+#include "content/renderer/media/webrtc_audio_capturer.h"
#include "third_party/libjingle/source/talk/app/webrtc/videosourceinterface.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
namespace content {
class CONTENT_EXPORT MediaStreamSourceExtraData
- : NON_EXPORTED_BASE(public WebKit::WebMediaStreamSource::ExtraData) {
+ : NON_EXPORTED_BASE(public blink::WebMediaStreamSource::ExtraData) {
public:
- MediaStreamSourceExtraData(
- const StreamDeviceInfo& device_info,
- const WebKit::WebMediaStreamSource& webkit_source);
+ typedef base::Callback<void(const blink::WebMediaStreamSource& source)>
+ SourceStopCallback;
+
+ MediaStreamSourceExtraData(const StreamDeviceInfo& device_info,
+ const SourceStopCallback& stop_callback);
MediaStreamSourceExtraData();
virtual ~MediaStreamSourceExtraData();
- // Returns the WebMediaStreamSource object that owns this object.
- const WebKit::WebMediaStreamSource& webkit_source() const {
- return webkit_source_;
- }
-
// Return device information about the camera or microphone.
const StreamDeviceInfo& device_info() const {
return device_info_;
@@ -44,23 +43,34 @@ class CONTENT_EXPORT MediaStreamSourceExtraData
// See |source_observer_|.
}
+ void SetAudioCapturer(WebRtcAudioCapturer* capturer) {
+ DCHECK(!audio_capturer_);
+ audio_capturer_ = capturer;
+ }
+
+ WebRtcAudioCapturer* GetAudioCapturer() const {
+ // TODO(perkj): |audio_capturer_| can currently be reconfigured to use
+ // another microphone even after it has been created since only one
+ // capturer is supported. See issue crbug/262117.
+ // It would make more sense if a WebRtcAudioCapturer represent one and only
+ // one audio source.
+ if (audio_capturer_ &&
+ device_info_.session_id == audio_capturer_->session_id()) {
+ return audio_capturer_;
+ }
+ return NULL;
+ }
+
webrtc::VideoSourceInterface* video_source() { return video_source_.get(); }
webrtc::AudioSourceInterface* local_audio_source() {
return local_audio_source_.get();
}
+ void OnLocalSourceStop();
+
private:
StreamDeviceInfo device_info_;
- // TODO(tommyw): Remove |webkit_source_| after WebMediaStreamSource::Owner()
- // is implemented, which let us fetch the
- // WebMediaStreamSource without increasing the reference count.
- // |webkit_source_| will create a circular reference to WebMediaStreamSource.
- // WebMediaStreamSource -> MediaStreamSourceExtraData -> WebMediaStreamSource
- // Currently, we rely on manually releasing the MediaStreamSourceExtraData
- // from WebMediaStreamSource like what
- // MediaStreamImpl::~UserMediaRequestInfo() does.
- WebKit::WebMediaStreamSource webkit_source_;
scoped_refptr<webrtc::VideoSourceInterface> video_source_;
// This member holds an instance of webrtc::LocalAudioSource. This is used
@@ -70,6 +80,10 @@ class CONTENT_EXPORT MediaStreamSourceExtraData
scoped_refptr<webrtc::AudioSourceInterface> local_audio_source_;
scoped_ptr<MediaStreamSourceObserver> source_observer_;
+ scoped_refptr<WebRtcAudioCapturer> audio_capturer_;
+
+ SourceStopCallback stop_callback_;
+
DISALLOW_COPY_AND_ASSIGN(MediaStreamSourceExtraData);
};
diff --git a/chromium/content/renderer/media/media_stream_source_observer.cc b/chromium/content/renderer/media/media_stream_source_observer.cc
index 1f165bbfa37..319327fa72d 100644
--- a/chromium/content/renderer/media/media_stream_source_observer.cc
+++ b/chromium/content/renderer/media/media_stream_source_observer.cc
@@ -33,7 +33,7 @@ void MediaStreamSourceObserver::OnChanged() {
if (state == state_)
return;
state_ = state;
- WebKit::WebMediaStreamSource webkit_source(extra_data_->webkit_source());
+ blink::WebMediaStreamSource webkit_source(extra_data_->owner());
switch (state) {
case webrtc::MediaSourceInterface::kInitializing:
@@ -42,15 +42,15 @@ void MediaStreamSourceObserver::OnChanged() {
break;
case webrtc::MediaSourceInterface::kLive:
webkit_source.setReadyState(
- WebKit::WebMediaStreamSource::ReadyStateLive);
+ blink::WebMediaStreamSource::ReadyStateLive);
break;
case webrtc::MediaSourceInterface::kMuted:
webkit_source.setReadyState(
- WebKit::WebMediaStreamSource::ReadyStateMuted);
+ blink::WebMediaStreamSource::ReadyStateMuted);
break;
case webrtc::MediaSourceInterface::kEnded:
webkit_source.setReadyState(
- WebKit::WebMediaStreamSource::ReadyStateEnded);
+ blink::WebMediaStreamSource::ReadyStateEnded);
webrtc_source_->UnregisterObserver(this);
webrtc_source_ = NULL;
break;
diff --git a/chromium/content/renderer/media/media_stream_track_extra_data.cc b/chromium/content/renderer/media/media_stream_track_extra_data.cc
new file mode 100644
index 00000000000..0fbb29496b3
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_track_extra_data.cc
@@ -0,0 +1,20 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/media_stream_track_extra_data.h"
+
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+
+namespace content {
+
+MediaStreamTrackExtraData::MediaStreamTrackExtraData(
+ webrtc::MediaStreamTrackInterface* track, bool is_local_track)
+ : track_(track),
+ is_local_track_(is_local_track) {
+}
+
+MediaStreamTrackExtraData::~MediaStreamTrackExtraData() {
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_track_extra_data.h b/chromium/content/renderer/media/media_stream_track_extra_data.h
new file mode 100644
index 00000000000..dbc25b46dec
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_track_extra_data.h
@@ -0,0 +1,41 @@
+// 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_MEDIA_MEDIA_STREAM_TRACK_EXTRA_DATA_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_TRACK_EXTRA_DATA_H_
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+
+namespace webrtc {
+class MediaStreamTrackInterface;
+} // namespace webrtc
+
+namespace content {
+
+class CONTENT_EXPORT MediaStreamTrackExtraData
+ : NON_EXPORTED_BASE(public blink::WebMediaStreamTrack::ExtraData) {
+ public:
+ MediaStreamTrackExtraData(webrtc::MediaStreamTrackInterface* track,
+ bool is_local_track);
+ virtual ~MediaStreamTrackExtraData();
+
+ const scoped_refptr<webrtc::MediaStreamTrackInterface>& track() const {
+ return track_;
+ }
+ bool is_local_track () const { return is_local_track_; }
+
+ private:
+ scoped_refptr<webrtc::MediaStreamTrackInterface> track_;
+ const bool is_local_track_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamTrackExtraData);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_TRACK_EXTRA_DATA_H_
diff --git a/chromium/content/renderer/media/media_stream_video_track.cc b/chromium/content/renderer/media/media_stream_video_track.cc
new file mode 100644
index 00000000000..44962445161
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_video_track.cc
@@ -0,0 +1,47 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/media_stream_video_track.h"
+
+#include "content/renderer/media/webrtc/webrtc_video_sink_adapter.h"
+
+namespace content {
+
+// Wrapper which allows to use std::find_if() when adding and removing
+// sinks to/from |sinks_|.
+struct SinkWrapper {
+ explicit SinkWrapper(MediaStreamVideoSink* sink) : sink_(sink) {}
+ bool operator()(
+ const WebRtcVideoSinkAdapter* owner) {
+ return owner->sink() == sink_;
+ }
+ MediaStreamVideoSink* sink_;
+};
+
+MediaStreamVideoTrack::MediaStreamVideoTrack(webrtc::VideoTrackInterface* track,
+ bool is_local_track)
+ : MediaStreamTrackExtraData(track, is_local_track),
+ video_track_(track) {
+}
+
+MediaStreamVideoTrack::~MediaStreamVideoTrack() {
+ DCHECK(sinks_.empty());
+}
+
+void MediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(std::find_if(sinks_.begin(), sinks_.end(),
+ SinkWrapper(sink)) == sinks_.end());
+ sinks_.push_back(new WebRtcVideoSinkAdapter(video_track_, sink));
+}
+
+void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ ScopedVector<WebRtcVideoSinkAdapter>::iterator it =
+ std::find_if(sinks_.begin(), sinks_.end(), SinkWrapper(sink));
+ DCHECK(it != sinks_.end());
+ sinks_.erase(it);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_video_track.h b/chromium/content/renderer/media/media_stream_video_track.h
new file mode 100644
index 00000000000..410a8f9a40b
--- /dev/null
+++ b/chromium/content/renderer/media/media_stream_video_track.h
@@ -0,0 +1,49 @@
+// 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_MEDIA_MEDIA_STREAM_VIDEO_TRACK_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_VIDEO_TRACK_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_vector.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+#include "content/public/renderer/media_stream_video_sink.h"
+#include "content/renderer/media/media_stream_track_extra_data.h"
+
+namespace webrtc {
+class VideoTrackInterface;
+}
+
+namespace content {
+
+class WebRtcVideoSinkAdapter;
+
+// MediaStreamVideoTrack is a video specific representation of a
+// blink::WebMediaStreamTrack in content. It is owned by the blink object
+// and can be retrieved from a blink object using
+// WebMediaStreamTrack::extraData()
+class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrackExtraData {
+ public:
+ MediaStreamVideoTrack(webrtc::VideoTrackInterface* track,
+ bool is_local_track);
+ virtual ~MediaStreamVideoTrack();
+ void AddSink(MediaStreamVideoSink* sink);
+ void RemoveSink(MediaStreamVideoSink* sink);
+
+ private:
+ // Used to DCHECK that we are called on the correct thread.
+ base::ThreadChecker thread_checker_;
+ // The webrtc video track.
+ // TODO(perkj): Make this class independent of webrtc as part of project
+ // Piranha Plant.
+ webrtc::VideoTrackInterface* video_track_;
+ ScopedVector<WebRtcVideoSinkAdapter> sinks_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoTrack);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_VIDEO_TRACK_H_
diff --git a/chromium/content/renderer/media/midi_dispatcher.cc b/chromium/content/renderer/media/midi_dispatcher.cc
index edd57c23ee1..1f04e3e22f8 100644
--- a/chromium/content/renderer/media/midi_dispatcher.cc
+++ b/chromium/content/renderer/media/midi_dispatcher.cc
@@ -11,8 +11,8 @@
#include "third_party/WebKit/public/web/WebMIDIPermissionRequest.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
-using WebKit::WebMIDIPermissionRequest;
-using WebKit::WebSecurityOrigin;
+using blink::WebMIDIPermissionRequest;
+using blink::WebSecurityOrigin;
namespace content {
@@ -34,11 +34,11 @@ bool MIDIDispatcher::OnMessageReceived(const IPC::Message& message) {
void MIDIDispatcher::requestSysExPermission(
const WebMIDIPermissionRequest& request) {
- int client_id = requests_.Add(new WebMIDIPermissionRequest(request));
+ int bridge_id = requests_.Add(new WebMIDIPermissionRequest(request));
WebSecurityOrigin security_origin = request.securityOrigin();
std::string origin = security_origin.toString().utf8();
GURL url(origin);
- Send(new MIDIHostMsg_RequestSysExPermission(routing_id(), client_id, url));
+ Send(new MIDIHostMsg_RequestSysExPermission(routing_id(), bridge_id, url));
}
void MIDIDispatcher::cancelSysExPermissionRequest(
@@ -47,19 +47,23 @@ void MIDIDispatcher::cancelSysExPermissionRequest(
!it.IsAtEnd();
it.Advance()) {
WebMIDIPermissionRequest* value = it.GetCurrentValue();
- if (!value->equals(request))
- continue;
- requests_.Remove(it.GetCurrentKey());
+ if (value->equals(request)) {
+ base::string16 origin = request.securityOrigin().toString();
+ Send(new MIDIHostMsg_CancelSysExPermissionRequest(
+ routing_id(), it.GetCurrentKey(), GURL(origin)));
+ requests_.Remove(it.GetCurrentKey());
+ break;
+ }
}
}
-void MIDIDispatcher::OnSysExPermissionApproved(int client_id, bool is_allowed) {
+void MIDIDispatcher::OnSysExPermissionApproved(int bridge_id, bool is_allowed) {
// |request| can be NULL when the request is canceled.
- WebMIDIPermissionRequest* request = requests_.Lookup(client_id);
+ WebMIDIPermissionRequest* request = requests_.Lookup(bridge_id);
if (!request)
return;
request->setIsAllowed(is_allowed);
- requests_.Remove(client_id);
+ requests_.Remove(bridge_id);
}
} // namespace content
diff --git a/chromium/content/renderer/media/midi_dispatcher.h b/chromium/content/renderer/media/midi_dispatcher.h
index 143d706987e..70f8125bdd2 100644
--- a/chromium/content/renderer/media/midi_dispatcher.h
+++ b/chromium/content/renderer/media/midi_dispatcher.h
@@ -9,7 +9,7 @@
#include "content/public/renderer/render_view_observer.h"
#include "third_party/WebKit/public/web/WebMIDIClient.h"
-namespace WebKit {
+namespace blink {
class WebMIDIPermissionRequest;
}
@@ -23,7 +23,7 @@ class RenderViewImpl;
// MIDIDispatcherHost owned by RenderViewHost since permissions are managed in
// the browser process.
class MIDIDispatcher : public RenderViewObserver,
- public WebKit::WebMIDIClient {
+ public blink::WebMIDIClient {
public:
explicit MIDIDispatcher(RenderViewImpl* render_view);
virtual ~MIDIDispatcher();
@@ -32,11 +32,11 @@ class MIDIDispatcher : public RenderViewObserver,
// RenderView::Observer implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- // WebKit::WebMIDIClient implementation.
+ // blink::WebMIDIClient implementation.
virtual void requestSysExPermission(
- const WebKit::WebMIDIPermissionRequest& request) OVERRIDE;
+ const blink::WebMIDIPermissionRequest& request) OVERRIDE;
virtual void cancelSysExPermissionRequest(
- const WebKit::WebMIDIPermissionRequest& request) OVERRIDE;
+ const blink::WebMIDIPermissionRequest& request) OVERRIDE;
// Permission for using system exclusive messages has been set.
void OnSysExPermissionApproved(int client_id, bool is_allowed);
@@ -44,7 +44,7 @@ class MIDIDispatcher : public RenderViewObserver,
// Each WebMIDIPermissionRequest object is valid until
// cancelSysExPermissionRequest() is called with the object, or used to call
// WebMIDIPermissionRequest::setIsAllowed().
- IDMap<WebKit::WebMIDIPermissionRequest> requests_;
+ IDMap<blink::WebMIDIPermissionRequest> requests_;
DISALLOW_COPY_AND_ASSIGN(MIDIDispatcher);
};
diff --git a/chromium/content/renderer/media/midi_message_filter.cc b/chromium/content/renderer/media/midi_message_filter.cc
index 32e8bdd2477..d114618ec60 100644
--- a/chromium/content/renderer/media/midi_message_filter.cc
+++ b/chromium/content/renderer/media/midi_message_filter.cc
@@ -72,7 +72,7 @@ void MIDIMessageFilter::OnChannelClosing() {
channel_ = NULL;
}
-void MIDIMessageFilter::StartSession(WebKit::WebMIDIAccessorClient* client) {
+void MIDIMessageFilter::StartSession(blink::WebMIDIAccessorClient* client) {
// Generate and keep track of a "client id" which is sent to the browser
// to ask permission to talk to MIDI hardware.
// This id is handed back when we receive the answer in OnAccessApproved().
@@ -90,7 +90,7 @@ void MIDIMessageFilter::StartSessionOnIOThread(int client_id) {
Send(new MIDIHostMsg_StartSession(client_id));
}
-void MIDIMessageFilter::RemoveClient(WebKit::WebMIDIAccessorClient* client) {
+void MIDIMessageFilter::RemoveClient(blink::WebMIDIAccessorClient* client) {
ClientsMap::iterator i = clients_.find(client);
if (i != clients_.end())
clients_.erase(i);
@@ -115,7 +115,7 @@ void MIDIMessageFilter::HandleSessionStarted(
bool success,
MIDIPortInfoList inputs,
MIDIPortInfoList outputs) {
- WebKit::WebMIDIAccessorClient* client = GetClientFromId(client_id);
+ blink::WebMIDIAccessorClient* client = GetClientFromId(client_id);
if (!client)
return;
@@ -140,7 +140,7 @@ void MIDIMessageFilter::HandleSessionStarted(
client->didStartSession(success);
}
-WebKit::WebMIDIAccessorClient*
+blink::WebMIDIAccessorClient*
MIDIMessageFilter::GetClientFromId(int client_id) {
// Iterating like this seems inefficient, but in practice there generally
// will be very few clients (usually one). Additionally, this lookup
diff --git a/chromium/content/renderer/media/midi_message_filter.h b/chromium/content/renderer/media/midi_message_filter.h
index 4b8481fbc57..c2e66ae4d0c 100644
--- a/chromium/content/renderer/media/midi_message_filter.h
+++ b/chromium/content/renderer/media/midi_message_filter.h
@@ -31,8 +31,8 @@ class CONTENT_EXPORT MIDIMessageFilter
// If permission is granted, then the client's
// addInputPort() and addOutputPort() methods will be called,
// giving the client access to receive and send data.
- void StartSession(WebKit::WebMIDIAccessorClient* client);
- void RemoveClient(WebKit::WebMIDIAccessorClient* client);
+ void StartSession(blink::WebMIDIAccessorClient* client);
+ void RemoveClient(blink::WebMIDIAccessorClient* client);
// A client will only be able to call this method if it has a suitable
// output port (from addOutputPort()).
@@ -92,7 +92,7 @@ class CONTENT_EXPORT MIDIMessageFilter
const std::vector<uint8>& data,
double timestamp);
- WebKit::WebMIDIAccessorClient* GetClientFromId(int client_id);
+ blink::WebMIDIAccessorClient* GetClientFromId(int client_id);
// IPC channel for Send(); must only be accessed on |io_message_loop_|.
IPC::Channel* channel_;
@@ -107,7 +107,7 @@ class CONTENT_EXPORT MIDIMessageFilter
// We map client to "client id" used to track permission.
// When access has been approved, we add the input and output ports to
// the client, allowing it to actually receive and send MIDI data.
- typedef std::map<WebKit::WebMIDIAccessorClient*, int> ClientsMap;
+ typedef std::map<blink::WebMIDIAccessorClient*, int> ClientsMap;
ClientsMap clients_;
// Dishes out client ids.
diff --git a/chromium/content/renderer/media/mock_media_stream_dependency_factory.cc b/chromium/content/renderer/media/mock_media_stream_dependency_factory.cc
index 6067c1117bb..8de0e2b43dd 100644
--- a/chromium/content/renderer/media/mock_media_stream_dependency_factory.cc
+++ b/chromium/content/renderer/media/mock_media_stream_dependency_factory.cc
@@ -135,7 +135,8 @@ void MockAudioSource::UnregisterObserver(webrtc::ObserverInterface* observer) {
}
void MockAudioSource::SetLive() {
- DCHECK_EQ(MediaSourceInterface::kInitializing, state_);
+ DCHECK(state_ == MediaSourceInterface::kInitializing ||
+ state_ == MediaSourceInterface::kLive);
state_ = MediaSourceInterface::kLive;
if (observer_)
observer_->OnChanged();
@@ -202,7 +203,8 @@ void MockVideoSource::FireOnChanged() {
}
void MockVideoSource::SetLive() {
- DCHECK_EQ(MediaSourceInterface::kInitializing, state_);
+ DCHECK(state_ == MediaSourceInterface::kInitializing ||
+ state_ == MediaSourceInterface::kLive);
state_ = MediaSourceInterface::kLive;
FireOnChanged();
}
@@ -384,7 +386,7 @@ scoped_refptr<webrtc::PeerConnectionInterface>
MockMediaStreamDependencyFactory::CreatePeerConnection(
const webrtc::PeerConnectionInterface::IceServers& ice_servers,
const webrtc::MediaConstraintsInterface* constraints,
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
webrtc::PeerConnectionObserver* observer) {
DCHECK(mock_pc_factory_created_);
return new talk_base::RefCountedObject<MockPeerConnectionImpl>(this);
@@ -409,7 +411,7 @@ MockMediaStreamDependencyFactory::CreateLocalVideoSource(
scoped_refptr<WebAudioCapturerSource>
MockMediaStreamDependencyFactory::CreateWebAudioSource(
- WebKit::WebMediaStreamSource* source,
+ blink::WebMediaStreamSource* source,
RTCMediaConstraints* constraints) {
return NULL;
}
diff --git a/chromium/content/renderer/media/mock_media_stream_dependency_factory.h b/chromium/content/renderer/media/mock_media_stream_dependency_factory.h
index 7152d119608..bd73ec7bd9b 100644
--- a/chromium/content/renderer/media/mock_media_stream_dependency_factory.h
+++ b/chromium/content/renderer/media/mock_media_stream_dependency_factory.h
@@ -118,7 +118,7 @@ class MockMediaStreamDependencyFactory : public MediaStreamDependencyFactory {
virtual scoped_refptr<webrtc::PeerConnectionInterface> CreatePeerConnection(
const webrtc::PeerConnectionInterface::IceServers& ice_servers,
const webrtc::MediaConstraintsInterface* constraints,
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
webrtc::PeerConnectionObserver* observer) OVERRIDE;
virtual scoped_refptr<webrtc::AudioSourceInterface>
CreateLocalAudioSource(
@@ -129,7 +129,7 @@ class MockMediaStreamDependencyFactory : public MediaStreamDependencyFactory {
bool is_screencast,
const webrtc::MediaConstraintsInterface* constraints) OVERRIDE;
virtual scoped_refptr<WebAudioCapturerSource> CreateWebAudioSource(
- WebKit::WebMediaStreamSource* source,
+ blink::WebMediaStreamSource* source,
RTCMediaConstraints* constraints) OVERRIDE;
virtual scoped_refptr<webrtc::MediaStreamInterface>
CreateLocalMediaStream(const std::string& label) OVERRIDE;
diff --git a/chromium/content/renderer/media/mock_media_stream_dispatcher.cc b/chromium/content/renderer/media/mock_media_stream_dispatcher.cc
index b6a163a9c5f..ed5c91c91ee 100644
--- a/chromium/content/renderer/media/mock_media_stream_dispatcher.cc
+++ b/chromium/content/renderer/media/mock_media_stream_dispatcher.cc
@@ -4,7 +4,7 @@
#include "content/renderer/media/mock_media_stream_dispatcher.h"
-#include "base/strings/stringprintf.h"
+#include "base/strings/string_number_conversions.h"
#include "content/public/common/media_stream_request.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -14,7 +14,9 @@ MockMediaStreamDispatcher::MockMediaStreamDispatcher()
: MediaStreamDispatcher(NULL),
request_id_(-1),
request_stream_counter_(0),
- stop_stream_counter_(0) {
+ stop_audio_device_counter_(0),
+ stop_video_device_counter_(0),
+ session_id_(0) {
}
MockMediaStreamDispatcher::~MockMediaStreamDispatcher() {}
@@ -26,24 +28,24 @@ void MockMediaStreamDispatcher::GenerateStream(
const GURL& url) {
request_id_ = request_id;
- stream_label_ = base::StringPrintf("%s%d","local_stream",request_id);
+ stream_label_ = "local_stream" + base::IntToString(request_id);
audio_array_.clear();
video_array_.clear();
- if (IsAudioMediaType(components.audio_type)) {
+ if (components.audio_requested) {
StreamDeviceInfo audio;
- audio.device.id = "audio_device_id";
+ audio.device.id = "audio_device_id" + base::IntToString(session_id_);
audio.device.name = "microphone";
- audio.device.type = components.audio_type;
- audio.session_id = request_id;
+ audio.device.type = MEDIA_DEVICE_AUDIO_CAPTURE;
+ audio.session_id = session_id_;
audio_array_.push_back(audio);
}
- if (IsVideoMediaType(components.video_type)) {
+ if (components.video_requested) {
StreamDeviceInfo video;
- video.device.id = "video_device_id";
+ video.device.id = "video_device_id" + base::IntToString(session_id_);
video.device.name = "usb video camera";
- video.device.type = components.video_type;
- video.session_id = request_id;
+ video.device.type = MEDIA_DEVICE_VIDEO_CAPTURE;
+ video.session_id = session_id_;
video_array_.push_back(video);
}
++request_stream_counter_;
@@ -55,8 +57,17 @@ void MockMediaStreamDispatcher::CancelGenerateStream(
EXPECT_EQ(request_id, request_id_);
}
-void MockMediaStreamDispatcher::StopStream(const std::string& label) {
- ++stop_stream_counter_;
+void MockMediaStreamDispatcher::StopStreamDevice(
+ const StreamDeviceInfo& device_info) {
+ if (IsAudioMediaType(device_info.device.type)) {
+ ++stop_audio_device_counter_;
+ return;
+ }
+ if (IsVideoMediaType(device_info.device.type)) {
+ ++stop_video_device_counter_;
+ return;
+ }
+ NOTREACHED();
}
bool MockMediaStreamDispatcher::IsStream(const std::string& label) {
diff --git a/chromium/content/renderer/media/mock_media_stream_dispatcher.h b/chromium/content/renderer/media/mock_media_stream_dispatcher.h
index 23ecec0bfe5..d16f32d6f3f 100644
--- a/chromium/content/renderer/media/mock_media_stream_dispatcher.h
+++ b/chromium/content/renderer/media/mock_media_stream_dispatcher.h
@@ -27,14 +27,18 @@ class MockMediaStreamDispatcher : public MediaStreamDispatcher {
int request_id,
const base::WeakPtr<MediaStreamDispatcherEventHandler>&
event_handler) OVERRIDE;
- virtual void StopStream(const std::string& label) OVERRIDE;
+ virtual void StopStreamDevice(const StreamDeviceInfo& device_info) OVERRIDE;
virtual bool IsStream(const std::string& label) OVERRIDE;
virtual int video_session_id(const std::string& label, int index) OVERRIDE;
virtual int audio_session_id(const std::string& label, int index) OVERRIDE;
int request_id() const { return request_id_; }
int request_stream_counter() const { return request_stream_counter_; }
- int stop_stream_counter() const { return stop_stream_counter_; }
+ void IncrementSessionId() { ++session_id_; }
+
+ int stop_audio_device_counter() const { return stop_audio_device_counter_; }
+ int stop_video_device_counter() const { return stop_video_device_counter_; }
+
const std::string& stream_label() const { return stream_label_;}
StreamDeviceInfoArray audio_array() const { return audio_array_; }
StreamDeviceInfoArray video_array() const { return video_array_; }
@@ -43,9 +47,11 @@ class MockMediaStreamDispatcher : public MediaStreamDispatcher {
int request_id_;
base::WeakPtr<MediaStreamDispatcherEventHandler> event_handler_;
int request_stream_counter_;
- int stop_stream_counter_;
+ int stop_audio_device_counter_;
+ int stop_video_device_counter_;
std::string stream_label_;
+ int session_id_;
StreamDeviceInfoArray audio_array_;
StreamDeviceInfoArray video_array_;
diff --git a/chromium/content/renderer/media/mock_media_stream_registry.cc b/chromium/content/renderer/media/mock_media_stream_registry.cc
index 04621238f50..cc29c058e66 100644
--- a/chromium/content/renderer/media/mock_media_stream_registry.cc
+++ b/chromium/content/renderer/media/mock_media_stream_registry.cc
@@ -26,9 +26,9 @@ void MockMediaStreamRegistry::Init(const std::string& stream_url) {
stream_url_ = stream_url;
scoped_refptr<webrtc::MediaStreamInterface> stream(
factory_->CreateLocalMediaStream(kTestStreamLabel));
- WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_audio_tracks;
- WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_video_tracks;
- WebKit::WebString webkit_stream_label(UTF8ToUTF16(stream->label()));
+ blink::WebVector<blink::WebMediaStreamTrack> webkit_audio_tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> webkit_video_tracks;
+ blink::WebString webkit_stream_label(UTF8ToUTF16(stream->label()));
test_stream_.initialize(webkit_stream_label,
webkit_audio_tracks, webkit_video_tracks);
test_stream_.setExtraData(new MediaStreamExtraData(stream.get(), false));
@@ -39,15 +39,15 @@ bool MockMediaStreamRegistry::AddVideoTrack(const std::string& track_id) {
return factory_->AddNativeVideoMediaTrack(track_id, &test_stream_, capturer);
}
-WebKit::WebMediaStream MockMediaStreamRegistry::GetMediaStream(
+blink::WebMediaStream MockMediaStreamRegistry::GetMediaStream(
const std::string& url) {
if (url != stream_url_) {
- return WebKit::WebMediaStream();
+ return blink::WebMediaStream();
}
return test_stream_;
}
-const WebKit::WebMediaStream MockMediaStreamRegistry::test_stream() const {
+const blink::WebMediaStream MockMediaStreamRegistry::test_stream() const {
return test_stream_;
}
diff --git a/chromium/content/renderer/media/mock_media_stream_registry.h b/chromium/content/renderer/media/mock_media_stream_registry.h
index 4d77395cced..c0dba849fb4 100644
--- a/chromium/content/renderer/media/mock_media_stream_registry.h
+++ b/chromium/content/renderer/media/mock_media_stream_registry.h
@@ -18,13 +18,13 @@ class MockMediaStreamRegistry : public MediaStreamRegistryInterface {
void Init(const std::string& stream_label);
bool AddVideoTrack(const std::string& track_id);
- virtual WebKit::WebMediaStream GetMediaStream(const std::string& url)
+ virtual blink::WebMediaStream GetMediaStream(const std::string& url)
OVERRIDE;
- const WebKit::WebMediaStream test_stream() const;
+ const blink::WebMediaStream test_stream() const;
private:
MockMediaStreamDependencyFactory* factory_;
- WebKit::WebMediaStream test_stream_;
+ blink::WebMediaStream test_stream_;
std::string stream_url_;
};
diff --git a/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.cc b/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.cc
index 2eb8b08e328..a50525e1c39 100644
--- a/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.cc
+++ b/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.cc
@@ -30,7 +30,7 @@ MockWebRTCPeerConnectionHandlerClient::
~MockWebRTCPeerConnectionHandlerClient() {}
void MockWebRTCPeerConnectionHandlerClient::didGenerateICECandidateWorker(
- const WebKit::WebRTCICECandidate& candidate) {
+ const blink::WebRTCICECandidate& candidate) {
if (!candidate.isNull()) {
candidate_sdp_ = UTF16ToUTF8(candidate.candidate());
candidate_mline_index_ = candidate.sdpMLineIndex();
@@ -43,12 +43,12 @@ void MockWebRTCPeerConnectionHandlerClient::didGenerateICECandidateWorker(
}
void MockWebRTCPeerConnectionHandlerClient::didAddRemoteStreamWorker(
- const WebKit::WebMediaStream& stream_descriptor) {
+ const blink::WebMediaStream& stream_descriptor) {
remote_steam_ = stream_descriptor;
}
void MockWebRTCPeerConnectionHandlerClient::didRemoveRemoteStreamWorker(
- const WebKit::WebMediaStream& stream_descriptor) {
+ const blink::WebMediaStream& stream_descriptor) {
remote_steam_.reset();
}
diff --git a/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.h b/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.h
index 1bc5b2ac15a..720a7cb65ea 100644
--- a/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.h
+++ b/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.h
@@ -17,7 +17,7 @@
namespace content {
class MockWebRTCPeerConnectionHandlerClient
- : public WebKit::WebRTCPeerConnectionHandlerClient {
+ : public blink::WebRTCPeerConnectionHandlerClient {
public:
MockWebRTCPeerConnectionHandlerClient();
virtual ~MockWebRTCPeerConnectionHandlerClient();
@@ -25,33 +25,33 @@ class MockWebRTCPeerConnectionHandlerClient
// WebRTCPeerConnectionHandlerClient implementation.
MOCK_METHOD0(negotiationNeeded, void());
MOCK_METHOD1(didGenerateICECandidate,
- void(const WebKit::WebRTCICECandidate& candidate));
+ void(const blink::WebRTCICECandidate& candidate));
MOCK_METHOD1(didChangeSignalingState, void(SignalingState state));
MOCK_METHOD1(didChangeICEGatheringState, void(ICEGatheringState state));
MOCK_METHOD1(didChangeICEConnectionState, void(ICEConnectionState state));
MOCK_METHOD1(didAddRemoteStream,
- void(const WebKit::WebMediaStream& stream_descriptor));
+ void(const blink::WebMediaStream& stream_descriptor));
MOCK_METHOD1(didRemoveRemoteStream,
- void(const WebKit::WebMediaStream& stream_descriptor));
+ void(const blink::WebMediaStream& stream_descriptor));
MOCK_METHOD1(didAddRemoteDataChannel,
- void(WebKit::WebRTCDataChannelHandler*));
+ void(blink::WebRTCDataChannelHandler*));
void didGenerateICECandidateWorker(
- const WebKit::WebRTCICECandidate& candidate);
+ const blink::WebRTCICECandidate& candidate);
void didAddRemoteStreamWorker(
- const WebKit::WebMediaStream& stream_descriptor);
+ const blink::WebMediaStream& stream_descriptor);
void didRemoveRemoteStreamWorker(
- const WebKit::WebMediaStream& stream_descriptor);
+ const blink::WebMediaStream& stream_descriptor);
const std::string& candidate_sdp() const { return candidate_sdp_; }
int candidate_mlineindex() const {
return candidate_mline_index_;
}
const std::string& candidate_mid() const { return candidate_mid_ ; }
- const WebKit::WebMediaStream& remote_stream() const { return remote_steam_;}
+ const blink::WebMediaStream& remote_stream() const { return remote_steam_;}
private:
- WebKit::WebMediaStream remote_steam_;
+ blink::WebMediaStream remote_steam_;
std::string candidate_sdp_;
int candidate_mline_index_;
std::string candidate_mid_;
diff --git a/chromium/content/renderer/media/peer_connection_audio_sink_owner.cc b/chromium/content/renderer/media/peer_connection_audio_sink_owner.cc
new file mode 100644
index 00000000000..4073ac61425
--- /dev/null
+++ b/chromium/content/renderer/media/peer_connection_audio_sink_owner.cc
@@ -0,0 +1,71 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/peer_connection_audio_sink_owner.h"
+
+#include "content/renderer/media/webrtc_audio_device_impl.h"
+
+namespace content {
+
+PeerConnectionAudioSinkOwner::PeerConnectionAudioSinkOwner(
+ PeerConnectionAudioSink* sink)
+ : delegate_(sink) {
+}
+
+int PeerConnectionAudioSinkOwner::OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) {
+ base::AutoLock lock(lock_);
+ if (delegate_) {
+ return delegate_->OnData(audio_data,
+ sample_rate,
+ number_of_channels,
+ number_of_frames,
+ channels,
+ audio_delay_milliseconds,
+ current_volume,
+ need_audio_processing,
+ key_pressed);
+ }
+
+ return 0;
+}
+
+void PeerConnectionAudioSinkOwner::OnSetFormat(
+ const media::AudioParameters& params) {
+ base::AutoLock lock(lock_);
+ if (delegate_)
+ delegate_->OnSetFormat(params);
+}
+
+void PeerConnectionAudioSinkOwner::OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) {
+ // Not forwarded at the moment.
+}
+
+void PeerConnectionAudioSinkOwner::Reset() {
+ base::AutoLock lock(lock_);
+ delegate_ = NULL;
+}
+
+bool PeerConnectionAudioSinkOwner::IsEqual(
+ const MediaStreamAudioSink* other) const {
+ DCHECK(other);
+ return false;
+}
+
+bool PeerConnectionAudioSinkOwner::IsEqual(
+ const PeerConnectionAudioSink* other) const {
+ DCHECK(other);
+ base::AutoLock lock(lock_);
+ return (other == delegate_);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/peer_connection_audio_sink_owner.h b/chromium/content/renderer/media/peer_connection_audio_sink_owner.h
new file mode 100644
index 00000000000..289a3f477a7
--- /dev/null
+++ b/chromium/content/renderer/media/peer_connection_audio_sink_owner.h
@@ -0,0 +1,54 @@
+// 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_MEDIA_PEER_CONNECTION_AUDIO_SINK_OWNER_H_
+#define CONTENT_RENDERER_MEDIA_PEER_CONNECTION_AUDIO_SINK_OWNER_H_
+
+#include <vector>
+
+#include "base/synchronization/lock.h"
+#include "content/renderer/media/media_stream_audio_track_sink.h"
+
+namespace content {
+
+class PeerConnectionAudioSink;
+
+// Reference counted holder of PeerConnectionAudioSink.
+class PeerConnectionAudioSinkOwner : public MediaStreamAudioTrackSink {
+ public:
+ explicit PeerConnectionAudioSinkOwner(PeerConnectionAudioSink* sink);
+
+ // MediaStreamAudioTrackSink implementation.
+ virtual int OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) OVERRIDE;
+ virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
+ virtual void OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
+ virtual void Reset() OVERRIDE;
+ virtual bool IsEqual(const MediaStreamAudioSink* other) const OVERRIDE;
+ virtual bool IsEqual(const PeerConnectionAudioSink* other) const OVERRIDE;
+
+ protected:
+ virtual ~PeerConnectionAudioSinkOwner() {}
+
+ private:
+ mutable base::Lock lock_;
+
+ // Raw pointer to the delegate, the client need to call Reset() to set the
+ // pointer to NULL before the delegate goes away.
+ PeerConnectionAudioSink* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(PeerConnectionAudioSinkOwner);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_PEER_CONNECTION_AUDIO_SINK_OWNER_H_
diff --git a/chromium/content/renderer/media/peer_connection_handler_base.cc b/chromium/content/renderer/media/peer_connection_handler_base.cc
index 792e61b0968..05e71a6226a 100644
--- a/chromium/content/renderer/media/peer_connection_handler_base.cc
+++ b/chromium/content/renderer/media/peer_connection_handler_base.cc
@@ -15,16 +15,6 @@
namespace content {
-// TODO(hta): Unify implementations of these functions from MediaStreamCenter
-static webrtc::MediaStreamInterface* GetNativeMediaStream(
- const WebKit::WebMediaStream& stream) {
- MediaStreamExtraData* extra_data =
- static_cast<MediaStreamExtraData*>(stream.extraData());
- if (extra_data)
- return extra_data->stream().get();
- return NULL;
-}
-
PeerConnectionHandlerBase::PeerConnectionHandlerBase(
MediaStreamDependencyFactory* dependency_factory)
: dependency_factory_(dependency_factory),
@@ -35,39 +25,22 @@ PeerConnectionHandlerBase::~PeerConnectionHandlerBase() {
}
bool PeerConnectionHandlerBase::AddStream(
- const WebKit::WebMediaStream& stream,
+ const blink::WebMediaStream& stream,
const webrtc::MediaConstraintsInterface* constraints) {
- webrtc::MediaStreamInterface* native_stream = GetNativeMediaStream(stream);
+ webrtc::MediaStreamInterface* native_stream =
+ MediaStreamDependencyFactory::GetNativeMediaStream(stream);
if (!native_stream)
return false;
return native_peer_connection_->AddStream(native_stream, constraints);
}
void PeerConnectionHandlerBase::RemoveStream(
- const WebKit::WebMediaStream& stream) {
- webrtc::MediaStreamInterface* native_stream = GetNativeMediaStream(stream);
+ const blink::WebMediaStream& stream) {
+ webrtc::MediaStreamInterface* native_stream =
+ MediaStreamDependencyFactory::GetNativeMediaStream(stream);
if (native_stream)
native_peer_connection_->RemoveStream(native_stream);
DCHECK(native_stream);
}
-webrtc::MediaStreamTrackInterface*
-PeerConnectionHandlerBase::GetNativeMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& track) {
- std::string track_id = UTF16ToUTF8(track.id());
- webrtc::MediaStreamInterface* native_stream = GetNativeMediaStream(stream);
- if (!native_stream) {
- return NULL;
- }
- if (track.source().type() == WebKit::WebMediaStreamSource::TypeAudio) {
- return native_stream->FindAudioTrack(track_id);
- }
- if (track.source().type() == WebKit::WebMediaStreamSource::TypeVideo) {
- return native_stream->FindVideoTrack(track_id);
- }
- NOTIMPLEMENTED(); // We have an unknown type of media stream track.
- return NULL;
-}
-
} // namespace content
diff --git a/chromium/content/renderer/media/peer_connection_handler_base.h b/chromium/content/renderer/media/peer_connection_handler_base.h
index 54f16734f5c..db6c0407e31 100644
--- a/chromium/content/renderer/media/peer_connection_handler_base.h
+++ b/chromium/content/renderer/media/peer_connection_handler_base.h
@@ -32,13 +32,10 @@ class CONTENT_EXPORT PeerConnectionHandlerBase
protected:
virtual ~PeerConnectionHandlerBase();
- void AddStream(const WebKit::WebMediaStream& stream);
- bool AddStream(const WebKit::WebMediaStream& stream,
+ void AddStream(const blink::WebMediaStream& stream);
+ bool AddStream(const blink::WebMediaStream& stream,
const webrtc::MediaConstraintsInterface* constraints);
- void RemoveStream(const WebKit::WebMediaStream& stream);
- webrtc::MediaStreamTrackInterface* GetNativeMediaStreamTrack(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& component);
+ void RemoveStream(const blink::WebMediaStream& stream);
// dependency_factory_ is a raw pointer, and is valid for the lifetime of
// MediaStreamImpl.
diff --git a/chromium/content/renderer/media/peer_connection_identity_service.cc b/chromium/content/renderer/media/peer_connection_identity_service.cc
index 904eb4128c3..f7bc8568102 100644
--- a/chromium/content/renderer/media/peer_connection_identity_service.cc
+++ b/chromium/content/renderer/media/peer_connection_identity_service.cc
@@ -9,17 +9,8 @@
namespace content {
-PeerConnectionIdentityService* PeerConnectionIdentityService::Create(
- const GURL& origin) {
-// The crypto APIs needed for generating identities are not implenented for
-// OPENSSL yet (crbug/91512). So returning NULL in that case.
-// TODO(jiayl): remove the #if once the crypto APIs are implemented for OPENSSL.
-#if defined(USE_OPENSSL)
- return NULL;
-#else
- return new PeerConnectionIdentityService(origin);
-#endif // defined(USE_OPENSSL)
-}
+PeerConnectionIdentityService::PeerConnectionIdentityService(const GURL& origin)
+ : origin_(origin), pending_observer_(NULL), pending_request_id_(0) {}
PeerConnectionIdentityService::~PeerConnectionIdentityService() {
if (pending_observer_)
@@ -48,9 +39,6 @@ bool PeerConnectionIdentityService::RequestIdentity(
return true;
}
-PeerConnectionIdentityService::PeerConnectionIdentityService(const GURL& origin)
- : origin_(origin), pending_observer_(NULL), pending_request_id_(0) {}
-
void PeerConnectionIdentityService::OnIdentityReady(
const std::string& certificate,
const std::string& private_key) {
diff --git a/chromium/content/renderer/media/peer_connection_identity_service.h b/chromium/content/renderer/media/peer_connection_identity_service.h
index fa0b16a096c..b68cafa135d 100644
--- a/chromium/content/renderer/media/peer_connection_identity_service.h
+++ b/chromium/content/renderer/media/peer_connection_identity_service.h
@@ -19,7 +19,7 @@ namespace content {
class PeerConnectionIdentityService
: public webrtc::DTLSIdentityServiceInterface {
public:
- static PeerConnectionIdentityService* Create(const GURL& origin);
+ explicit PeerConnectionIdentityService(const GURL& origin);
virtual ~PeerConnectionIdentityService();
@@ -30,8 +30,6 @@ class PeerConnectionIdentityService
webrtc::DTLSIdentityRequestObserver* observer) OVERRIDE;
private:
- explicit PeerConnectionIdentityService(const GURL& origin);
-
void OnIdentityReady(const std::string& certificate,
const std::string& private_key);
void OnRequestFailed(int error);
diff --git a/chromium/content/renderer/media/peer_connection_tracker.cc b/chromium/content/renderer/media/peer_connection_tracker.cc
index 597c6455704..b594ff8f0b3 100644
--- a/chromium/content/renderer/media/peer_connection_tracker.cc
+++ b/chromium/content/renderer/media/peer_connection_tracker.cc
@@ -18,7 +18,7 @@
using std::string;
using webrtc::MediaConstraintsInterface;
-using WebKit::WebRTCPeerConnectionHandlerClient;
+using blink::WebRTCPeerConnectionHandlerClient;
namespace content {
@@ -63,16 +63,16 @@ static string SerializeMediaConstraints(
}
static string SerializeMediaStreamComponent(
- const WebKit::WebMediaStreamTrack component) {
+ const blink::WebMediaStreamTrack component) {
string id = UTF16ToUTF8(component.source().id());
return id;
}
static string SerializeMediaDescriptor(
- const WebKit::WebMediaStream& stream) {
+ const blink::WebMediaStream& stream) {
string label = UTF16ToUTF8(stream.id());
string result = "label: " + label;
- WebKit::WebVector<WebKit::WebMediaStreamTrack> tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> tracks;
stream.audioTracks(tracks);
if (!tracks.isEmpty()) {
result += ", audio: [";
@@ -251,7 +251,7 @@ void PeerConnectionTracker::RegisterPeerConnection(
RTCPeerConnectionHandler* pc_handler,
const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers,
const RTCMediaConstraints& constraints,
- const WebKit::WebFrame* frame) {
+ const blink::WebFrame* frame) {
DVLOG(1) << "PeerConnectionTracker::RegisterPeerConnection()";
PeerConnectionInfo info;
@@ -304,7 +304,7 @@ void PeerConnectionTracker::TrackCreateAnswer(
void PeerConnectionTracker::TrackSetSessionDescription(
RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebRTCSessionDescription& desc,
+ const blink::WebRTCSessionDescription& desc,
Source source) {
string sdp = UTF16ToUTF8(desc.sdp());
string type = UTF16ToUTF8(desc.type());
@@ -330,7 +330,7 @@ void PeerConnectionTracker::TrackUpdateIce(
void PeerConnectionTracker::TrackAddIceCandidate(
RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebRTCICECandidate& candidate,
+ const blink::WebRTCICECandidate& candidate,
Source source) {
string value = "mid: " + UTF16ToUTF8(candidate.sdpMid()) + ", " +
"candidate: " + UTF16ToUTF8(candidate.candidate());
@@ -341,7 +341,7 @@ void PeerConnectionTracker::TrackAddIceCandidate(
void PeerConnectionTracker::TrackAddStream(
RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebMediaStream& stream,
+ const blink::WebMediaStream& stream,
Source source){
SendPeerConnectionUpdate(
pc_handler, source == SOURCE_LOCAL ? "addStream" : "onAddStream",
@@ -350,7 +350,7 @@ void PeerConnectionTracker::TrackAddStream(
void PeerConnectionTracker::TrackRemoveStream(
RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebMediaStream& stream,
+ const blink::WebMediaStream& stream,
Source source){
SendPeerConnectionUpdate(
pc_handler, source == SOURCE_LOCAL ? "removeStream" : "onRemoveStream",
@@ -429,7 +429,7 @@ void PeerConnectionTracker::TrackOnRenegotiationNeeded(
void PeerConnectionTracker::TrackCreateDTMFSender(
RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebMediaStreamTrack& track) {
+ const blink::WebMediaStreamTrack& track) {
SendPeerConnectionUpdate(pc_handler, "createDTMFSender",
UTF16ToUTF8(track.id()));
}
diff --git a/chromium/content/renderer/media/peer_connection_tracker.h b/chromium/content/renderer/media/peer_connection_tracker.h
index 41c78d87852..3bcda3996f7 100644
--- a/chromium/content/renderer/media/peer_connection_tracker.h
+++ b/chromium/content/renderer/media/peer_connection_tracker.h
@@ -14,12 +14,12 @@
#include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebRTCICECandidate;
class WebString;
class WebRTCSessionDescription;
-} // namespace WebKit
+} // namespace blink
namespace webrtc {
class DataChannelInterface;
@@ -70,7 +70,7 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver {
RTCPeerConnectionHandler* pc_handler,
const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers,
const RTCMediaConstraints& constraints,
- const WebKit::WebFrame* frame);
+ const blink::WebFrame* frame);
// Sends an update when a PeerConnection has been destroyed.
virtual void UnregisterPeerConnection(RTCPeerConnectionHandler* pc_handler);
@@ -86,7 +86,7 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver {
// Sends an update when setLocalDescription or setRemoteDescription is called.
virtual void TrackSetSessionDescription(
RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebRTCSessionDescription& desc, Source source);
+ const blink::WebRTCSessionDescription& desc, Source source);
// Sends an update when Ice candidates are updated.
virtual void TrackUpdateIce(
@@ -97,17 +97,17 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver {
// Sends an update when an Ice candidate is added.
virtual void TrackAddIceCandidate(
RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebRTCICECandidate& candidate, Source source);
+ const blink::WebRTCICECandidate& candidate, Source source);
// Sends an update when a media stream is added.
virtual void TrackAddStream(
RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebMediaStream& stream, Source source);
+ const blink::WebMediaStream& stream, Source source);
// Sends an update when a media stream is removed.
virtual void TrackRemoveStream(
RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebMediaStream& stream, Source source);
+ const blink::WebMediaStream& stream, Source source);
// Sends an update when a DataChannel is created.
virtual void TrackCreateDataChannel(
@@ -120,19 +120,19 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver {
// Sends an update when the signaling state of a PeerConnection has changed.
virtual void TrackSignalingStateChange(
RTCPeerConnectionHandler* pc_handler,
- WebKit::WebRTCPeerConnectionHandlerClient::SignalingState state);
+ blink::WebRTCPeerConnectionHandlerClient::SignalingState state);
// Sends an update when the Ice connection state
// of a PeerConnection has changed.
virtual void TrackIceConnectionStateChange(
RTCPeerConnectionHandler* pc_handler,
- WebKit::WebRTCPeerConnectionHandlerClient::ICEConnectionState state);
+ blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state);
// Sends an update when the Ice gathering state
// of a PeerConnection has changed.
virtual void TrackIceGatheringStateChange(
RTCPeerConnectionHandler* pc_handler,
- WebKit::WebRTCPeerConnectionHandlerClient::ICEGatheringState state);
+ blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state);
// Sends an update when the SetSessionDescription or CreateOffer or
// CreateAnswer callbacks are called.
@@ -146,7 +146,7 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver {
// Sends an update when a DTMFSender is created.
virtual void TrackCreateDTMFSender(
RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebMediaStreamTrack& track);
+ const blink::WebMediaStreamTrack& track);
private:
// Assign a local ID to a peer connection so that the browser process can
diff --git a/chromium/content/renderer/media/remote_media_stream_impl.cc b/chromium/content/renderer/media/remote_media_stream_impl.cc
index 7e481a6d042..af430e242f7 100644
--- a/chromium/content/renderer/media/remote_media_stream_impl.cc
+++ b/chromium/content/renderer/media/remote_media_stream_impl.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/renderer/media/media_stream_dependency_factory.h"
#include "content/renderer/media/media_stream_extra_data.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -21,13 +22,13 @@ class RemoteMediaStreamTrackObserver
public:
RemoteMediaStreamTrackObserver(
webrtc::MediaStreamTrackInterface* webrtc_track,
- const WebKit::WebMediaStreamTrack& webkit_track);
+ const blink::WebMediaStreamTrack& webkit_track);
virtual ~RemoteMediaStreamTrackObserver();
webrtc::MediaStreamTrackInterface* observered_track() {
return webrtc_track_.get();
}
- const WebKit::WebMediaStreamTrack& webkit_track() { return webkit_track_; }
+ const blink::WebMediaStreamTrack& webkit_track() { return webkit_track_; }
private:
// webrtc::ObserverInterface implementation.
@@ -35,7 +36,7 @@ class RemoteMediaStreamTrackObserver
webrtc::MediaStreamTrackInterface::TrackState state_;
scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_;
- WebKit::WebMediaStreamTrack webkit_track_;
+ blink::WebMediaStreamTrack webkit_track_;
DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackObserver);
};
@@ -45,13 +46,15 @@ class RemoteMediaStreamTrackObserver
namespace {
void InitializeWebkitTrack(webrtc::MediaStreamTrackInterface* track,
- WebKit::WebMediaStreamTrack* webkit_track,
- WebKit::WebMediaStreamSource::Type type) {
- WebKit::WebMediaStreamSource webkit_source;
- WebKit::WebString webkit_track_id(UTF8ToUTF16(track->id()));
+ blink::WebMediaStreamTrack* webkit_track,
+ blink::WebMediaStreamSource::Type type) {
+ blink::WebMediaStreamSource webkit_source;
+ blink::WebString webkit_track_id(UTF8ToUTF16(track->id()));
webkit_source.initialize(webkit_track_id, type, webkit_track_id);
webkit_track->initialize(webkit_track_id, webkit_source);
+ content::MediaStreamDependencyFactory::AddNativeTrackToBlinkTrack(
+ track, *webkit_track, false);
}
content::RemoteMediaStreamTrackObserver* FindTrackObserver(
@@ -72,7 +75,7 @@ namespace content {
RemoteMediaStreamTrackObserver::RemoteMediaStreamTrackObserver(
webrtc::MediaStreamTrackInterface* webrtc_track,
- const WebKit::WebMediaStreamTrack& webkit_track)
+ const blink::WebMediaStreamTrack& webkit_track)
: state_(webrtc_track->state()),
webrtc_track_(webrtc_track),
webkit_track_(webkit_track) {
@@ -98,11 +101,11 @@ void RemoteMediaStreamTrackObserver::OnChanged() {
break;
case webrtc::MediaStreamTrackInterface::kLive:
webkit_track_.source().setReadyState(
- WebKit::WebMediaStreamSource::ReadyStateLive);
+ blink::WebMediaStreamSource::ReadyStateLive);
break;
case webrtc::MediaStreamTrackInterface::kEnded:
webkit_track_.source().setReadyState(
- WebKit::WebMediaStreamSource::ReadyStateEnded);
+ blink::WebMediaStreamSource::ReadyStateEnded);
break;
default:
NOTREACHED();
@@ -117,7 +120,7 @@ RemoteMediaStreamImpl::RemoteMediaStreamImpl(
webrtc::AudioTrackVector webrtc_audio_tracks =
webrtc_stream_->GetAudioTracks();
- WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_audio_tracks(
+ blink::WebVector<blink::WebMediaStreamTrack> webkit_audio_tracks(
webrtc_audio_tracks.size());
// Initialize WebKit audio tracks.
@@ -126,7 +129,7 @@ RemoteMediaStreamImpl::RemoteMediaStreamImpl(
webrtc::AudioTrackInterface* audio_track = webrtc_audio_tracks[i];
DCHECK(audio_track);
InitializeWebkitTrack(audio_track, &webkit_audio_tracks[i],
- WebKit::WebMediaStreamSource::TypeAudio);
+ blink::WebMediaStreamSource::TypeAudio);
audio_track_observers_.push_back(
new RemoteMediaStreamTrackObserver(audio_track,
webkit_audio_tracks[i]));
@@ -135,13 +138,13 @@ RemoteMediaStreamImpl::RemoteMediaStreamImpl(
// Initialize WebKit video tracks.
webrtc::VideoTrackVector webrtc_video_tracks =
webrtc_stream_->GetVideoTracks();
- WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_video_tracks(
+ blink::WebVector<blink::WebMediaStreamTrack> webkit_video_tracks(
webrtc_video_tracks.size());
for (i = 0; i < webrtc_video_tracks.size(); ++i) {
webrtc::VideoTrackInterface* video_track = webrtc_video_tracks[i];
DCHECK(video_track);
InitializeWebkitTrack(video_track, &webkit_video_tracks[i],
- WebKit::WebMediaStreamSource::TypeVideo);
+ blink::WebMediaStreamSource::TypeVideo);
video_track_observers_.push_back(
new RemoteMediaStreamTrackObserver(video_track,
webkit_video_tracks[i]));
@@ -189,9 +192,9 @@ void RemoteMediaStreamImpl::OnChanged() {
for (webrtc::AudioTrackVector::iterator it = webrtc_audio_tracks.begin();
it != webrtc_audio_tracks.end(); ++it) {
if (!FindTrackObserver(*it, audio_track_observers_)) {
- WebKit::WebMediaStreamTrack new_track;
+ blink::WebMediaStreamTrack new_track;
InitializeWebkitTrack(*it, &new_track,
- WebKit::WebMediaStreamSource::TypeAudio);
+ blink::WebMediaStreamSource::TypeAudio);
audio_track_observers_.push_back(
new RemoteMediaStreamTrackObserver(*it, new_track));
webkit_stream_.addTrack(new_track);
@@ -204,9 +207,9 @@ void RemoteMediaStreamImpl::OnChanged() {
for (webrtc::VideoTrackVector::iterator it = webrtc_video_tracks.begin();
it != webrtc_video_tracks.end(); ++it) {
if (!FindTrackObserver(*it, video_track_observers_)) {
- WebKit::WebMediaStreamTrack new_track;
+ blink::WebMediaStreamTrack new_track;
InitializeWebkitTrack(*it, &new_track,
- WebKit::WebMediaStreamSource::TypeVideo);
+ blink::WebMediaStreamSource::TypeVideo);
video_track_observers_.push_back(
new RemoteMediaStreamTrackObserver(*it, new_track));
webkit_stream_.addTrack(new_track);
diff --git a/chromium/content/renderer/media/remote_media_stream_impl.h b/chromium/content/renderer/media/remote_media_stream_impl.h
index cc711e41358..3263ed458e9 100644
--- a/chromium/content/renderer/media/remote_media_stream_impl.h
+++ b/chromium/content/renderer/media/remote_media_stream_impl.h
@@ -32,7 +32,7 @@ class CONTENT_EXPORT RemoteMediaStreamImpl
webrtc::MediaStreamInterface* webrtc_stream);
virtual ~RemoteMediaStreamImpl();
- const WebKit::WebMediaStream& webkit_stream() { return webkit_stream_; }
+ const blink::WebMediaStream& webkit_stream() { return webkit_stream_; }
private:
// webrtc::ObserverInterface implementation.
@@ -41,7 +41,7 @@ class CONTENT_EXPORT RemoteMediaStreamImpl
scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream_;
ScopedVector<RemoteMediaStreamTrackObserver> audio_track_observers_;
ScopedVector<RemoteMediaStreamTrackObserver> video_track_observers_;
- WebKit::WebMediaStream webkit_stream_;
+ blink::WebMediaStream webkit_stream_;
DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamImpl);
};
diff --git a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
index 7fcb79cb25c..7d4db85513f 100644
--- a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
+++ b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
@@ -12,8 +12,8 @@
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
-#include "gpu/ipc/command_buffer_proxy.h"
#include "third_party/skia/include/core/SkPixelRef.h"
namespace content {
@@ -21,9 +21,9 @@ namespace content {
RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {}
RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
GpuChannelHost* gpu_channel_host,
- const scoped_refptr<base::MessageLoopProxy>& message_loop,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider)
- : message_loop_(message_loop),
+ : message_loop_(
+ RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy()),
gpu_channel_host_(gpu_channel_host),
context_provider_(context_provider),
thread_safe_sender_(ChildThread::current()->thread_safe_sender()),
@@ -111,32 +111,9 @@ RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator(
scoped_ptr<media::VideoEncodeAccelerator>
RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator(
media::VideoEncodeAccelerator::Client* client) {
- if (message_loop_->BelongsToCurrentThread()) {
- AsyncCreateVideoEncodeAccelerator(client);
- message_loop_async_waiter_.Reset();
- return vea_.Pass();
- }
- // The VEA is returned in the vea_ member variable by the
- // AsyncCreateVideoEncodeAccelerator() function.
- message_loop_->PostTask(FROM_HERE,
- base::Bind(&RendererGpuVideoAcceleratorFactories::
- AsyncCreateVideoEncodeAccelerator,
- this,
- client));
+ DCHECK(message_loop_->BelongsToCurrentThread());
- base::WaitableEvent* objects[] = {&aborted_waiter_,
- &message_loop_async_waiter_};
- if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) {
- // If we are aborting and the VDA is created by the
- // AsyncCreateVideoEncodeAccelerator() function later we need to ensure
- // that it is destroyed on the same thread.
- message_loop_->PostTask(FROM_HERE,
- base::Bind(&RendererGpuVideoAcceleratorFactories::
- AsyncDestroyVideoEncodeAccelerator,
- this));
- return scoped_ptr<media::VideoEncodeAccelerator>();
- }
- return vea_.Pass();
+ return gpu_channel_host_->CreateVideoEncoder(client);
}
void RendererGpuVideoAcceleratorFactories::AsyncCreateVideoDecodeAccelerator(
@@ -152,67 +129,26 @@ void RendererGpuVideoAcceleratorFactories::AsyncCreateVideoDecodeAccelerator(
message_loop_async_waiter_.Signal();
}
-void RendererGpuVideoAcceleratorFactories::AsyncCreateVideoEncodeAccelerator(
- media::VideoEncodeAccelerator::Client* client) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- vea_ = gpu_channel_host_->CreateVideoEncoder(client).Pass();
- message_loop_async_waiter_.Signal();
-}
-
uint32 RendererGpuVideoAcceleratorFactories::CreateTextures(
int32 count,
const gfx::Size& size,
std::vector<uint32>* texture_ids,
std::vector<gpu::Mailbox>* texture_mailboxes,
uint32 texture_target) {
- uint32 sync_point = 0;
-
- if (message_loop_->BelongsToCurrentThread()) {
- AsyncCreateTextures(count, size, texture_target, &sync_point);
- texture_ids->swap(created_textures_);
- texture_mailboxes->swap(created_texture_mailboxes_);
- message_loop_async_waiter_.Reset();
- return sync_point;
- }
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncCreateTextures,
- this,
- count,
- size,
- texture_target,
- &sync_point));
-
- base::WaitableEvent* objects[] = {&aborted_waiter_,
- &message_loop_async_waiter_};
- if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0)
- return 0;
- texture_ids->swap(created_textures_);
- texture_mailboxes->swap(created_texture_mailboxes_);
- return sync_point;
-}
-
-void RendererGpuVideoAcceleratorFactories::AsyncCreateTextures(
- int32 count,
- const gfx::Size& size,
- uint32 texture_target,
- uint32* sync_point) {
DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK(texture_target);
WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
- if (!context) {
- message_loop_async_waiter_.Signal();
- return;
- }
+ if (!context)
+ return 0;
+
gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
- created_textures_.resize(count);
- created_texture_mailboxes_.resize(count);
- gles2->GenTextures(count, &created_textures_[0]);
+ texture_ids->resize(count);
+ texture_mailboxes->resize(count);
+ gles2->GenTextures(count, &texture_ids->at(0));
for (int i = 0; i < count; ++i) {
gles2->ActiveTexture(GL_TEXTURE0);
- uint32 texture_id = created_textures_[i];
+ uint32 texture_id = texture_ids->at(i);
gles2->BindTexture(texture_target, texture_id);
gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -229,11 +165,9 @@ void RendererGpuVideoAcceleratorFactories::AsyncCreateTextures(
GL_UNSIGNED_BYTE,
NULL);
}
- // GLES2Implementation doesn't currently have the fast path of mailbox
- // generation, but WebGraphicsContext3DCommandBufferImpl does.
- context->genMailboxCHROMIUM(created_texture_mailboxes_[i].name);
+ gles2->GenMailboxCHROMIUM(texture_mailboxes->at(i).name);
gles2->ProduceTextureCHROMIUM(texture_target,
- created_texture_mailboxes_[i].name);
+ texture_mailboxes->at(i).name);
}
// We need a glFlush here to guarantee the decoder (in the GPU process) can
@@ -242,25 +176,12 @@ void RendererGpuVideoAcceleratorFactories::AsyncCreateTextures(
gles2->Flush();
DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
- *sync_point = gles2->InsertSyncPointCHROMIUM();
- message_loop_async_waiter_.Signal();
+ return gles2->InsertSyncPointCHROMIUM();
}
void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id) {
- if (message_loop_->BelongsToCurrentThread()) {
- AsyncDeleteTexture(texture_id);
- return;
- }
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncDeleteTexture,
- this,
- texture_id));
-}
-
-void RendererGpuVideoAcceleratorFactories::AsyncDeleteTexture(
- uint32 texture_id) {
DCHECK(message_loop_->BelongsToCurrentThread());
+
WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
if (!context)
return;
@@ -271,38 +192,21 @@ void RendererGpuVideoAcceleratorFactories::AsyncDeleteTexture(
}
void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point) {
- if (message_loop_->BelongsToCurrentThread()) {
- AsyncWaitSyncPoint(sync_point);
- message_loop_async_waiter_.Reset();
- return;
- }
-
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncWaitSyncPoint,
- this,
- sync_point));
- base::WaitableEvent* objects[] = {&aborted_waiter_,
- &message_loop_async_waiter_};
- base::WaitableEvent::WaitMany(objects, arraysize(objects));
-}
-
-void RendererGpuVideoAcceleratorFactories::AsyncWaitSyncPoint(
- uint32 sync_point) {
DCHECK(message_loop_->BelongsToCurrentThread());
+
WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
- if (!context) {
- message_loop_async_waiter_.Signal();
+ if (!context)
return;
- }
gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
gles2->WaitSyncPointCHROMIUM(sync_point);
- message_loop_async_waiter_.Signal();
+
+ // Callers expect the WaitSyncPoint to affect the next IPCs. Make sure to
+ // flush the command buffers to ensure that.
+ gles2->ShallowFlushCHROMIUM();
}
void RendererGpuVideoAcceleratorFactories::ReadPixels(uint32 texture_id,
- uint32 texture_target,
const gfx::Size& size,
const SkBitmap& pixels) {
// SkBitmaps use the SkPixelRef object to refcount the underlying pixels.
@@ -317,14 +221,13 @@ void RendererGpuVideoAcceleratorFactories::ReadPixels(uint32 texture_id,
base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncReadPixels,
this,
texture_id,
- texture_target,
size));
base::WaitableEvent* objects[] = {&aborted_waiter_,
&message_loop_async_waiter_};
if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0)
return;
} else {
- AsyncReadPixels(texture_id, texture_target, size);
+ AsyncReadPixels(texture_id, size);
message_loop_async_waiter_.Reset();
}
read_pixels_bitmap_.setPixelRef(NULL);
@@ -332,7 +235,6 @@ void RendererGpuVideoAcceleratorFactories::ReadPixels(uint32 texture_id,
void RendererGpuVideoAcceleratorFactories::AsyncReadPixels(
uint32 texture_id,
- uint32 texture_target,
const gfx::Size& size) {
DCHECK(message_loop_->BelongsToCurrentThread());
WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
@@ -345,25 +247,34 @@ void RendererGpuVideoAcceleratorFactories::AsyncReadPixels(
GLuint tmp_texture;
gles2->GenTextures(1, &tmp_texture);
- gles2->BindTexture(texture_target, tmp_texture);
- gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ gles2->BindTexture(GL_TEXTURE_2D, tmp_texture);
+ gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
context->copyTextureCHROMIUM(
- texture_target, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE);
+ GL_TEXTURE_2D, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE);
GLuint fb;
gles2->GenFramebuffers(1, &fb);
gles2->BindFramebuffer(GL_FRAMEBUFFER, fb);
gles2->FramebufferTexture2D(
- GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, tmp_texture, 0);
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_texture, 0);
gles2->PixelStorei(GL_PACK_ALIGNMENT, 4);
+#if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \
+ SK_A32_SHIFT == 24
+ GLenum skia_format = GL_BGRA_EXT;
+#elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
+ SK_A32_SHIFT == 24
+ GLenum skia_format = GL_RGBA;
+#else
+#error Unexpected Skia ARGB_8888 layout!
+#endif
gles2->ReadPixels(0,
0,
size.width(),
size.height(),
- GL_BGRA_EXT,
+ skia_format,
GL_UNSIGNED_BYTE,
read_pixels_bitmap_.pixelRef()->pixels());
gles2->DeleteFramebuffers(1, &fb);
@@ -374,6 +285,7 @@ void RendererGpuVideoAcceleratorFactories::AsyncReadPixels(
base::SharedMemory* RendererGpuVideoAcceleratorFactories::CreateSharedMemory(
size_t size) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
return ChildThread::AllocateSharedMemory(size, thread_safe_sender_.get());
}
@@ -406,11 +318,4 @@ RendererGpuVideoAcceleratorFactories::AsyncDestroyVideoDecodeAccelerator() {
vda_.release()->Destroy();
}
-void
-RendererGpuVideoAcceleratorFactories::AsyncDestroyVideoEncodeAccelerator() {
- // OK to release because Destroy() will delete the VDA instance.
- if (vea_)
- vea_.release()->Destroy();
-}
-
} // namespace content
diff --git a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h
index e1736d12a3b..eb9d650b5d0 100644
--- a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h
+++ b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h
@@ -32,20 +32,23 @@ class WebGraphicsContext3DCommandBufferImpl;
// RenderViewImpl and only has its own header to allow extraction of its
// implementation from render_view_impl.cc which is already far too large.
//
-// The public methods of the class can be called from any thread, and are
-// internally trampolined to the appropriate thread. GPU/GL-related calls go to
-// the constructor-argument loop (the media thread).
+// The RendererGpuVideoAcceleratorFactories can be constructed on any thread.
+// Most public methods of the class must be called from the media thread. The
+// exceptions (which can be called from any thread, as they are internally
+// trampolined) are:
+// * CreateVideoDecodeAccelerator()
+// * ReadPixels()
class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories
: public media::GpuVideoAcceleratorFactories {
public:
// Takes a ref on |gpu_channel_host| and tests |context| for loss before each
- // use.
+ // use. Safe to call from any thread.
RendererGpuVideoAcceleratorFactories(
GpuChannelHost* gpu_channel_host,
- const scoped_refptr<base::MessageLoopProxy>& message_loop,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider);
// media::GpuVideoAcceleratorFactories implementation.
+ // CreateVideoDecodeAccelerator() is safe to call from any thread.
virtual scoped_ptr<media::VideoDecodeAccelerator>
CreateVideoDecodeAccelerator(
media::VideoCodecProfile profile,
@@ -62,8 +65,8 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories
uint32 texture_target) OVERRIDE;
virtual void DeleteTexture(uint32 texture_id) OVERRIDE;
virtual void WaitSyncPoint(uint32 sync_point) OVERRIDE;
+ // ReadPixels() is safe to call from any thread.
virtual void ReadPixels(uint32 texture_id,
- uint32 texture_target,
const gfx::Size& size,
const SkBitmap& pixels) OVERRIDE;
virtual base::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
@@ -92,23 +95,11 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories
// a WaitableEvent* param to signal completion (except for DeleteTexture,
// which is fire-and-forget).
// AsyncCreateVideoDecodeAccelerator returns its output in the |vda_| member.
- // AsyncCreateVideoEncodeAccelerator returns its output in the |vea_| member.
void AsyncCreateVideoDecodeAccelerator(
media::VideoCodecProfile profile,
media::VideoDecodeAccelerator::Client* client);
- void AsyncCreateVideoEncodeAccelerator(
- media::VideoEncodeAccelerator::Client* client);
- void AsyncCreateTextures(int32 count,
- const gfx::Size& size,
- uint32 texture_target,
- uint32* sync_point);
- void AsyncDeleteTexture(uint32 texture_id);
- void AsyncWaitSyncPoint(uint32 sync_point);
- void AsyncReadPixels(uint32 texture_id,
- uint32 texture_target,
- const gfx::Size& size);
+ void AsyncReadPixels(uint32 texture_id, const gfx::Size& size);
void AsyncDestroyVideoDecodeAccelerator();
- void AsyncDestroyVideoEncodeAccelerator();
scoped_refptr<base::MessageLoopProxy> message_loop_;
scoped_refptr<GpuChannelHost> gpu_channel_host_;
@@ -128,16 +119,9 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories
// The vda returned by the CreateVideoDecodeAccelerator function.
scoped_ptr<media::VideoDecodeAccelerator> vda_;
- // The vea returned by the CreateVideoEncodeAccelerator function.
- scoped_ptr<media::VideoEncodeAccelerator> vea_;
-
// Bitmap returned by ReadPixels().
SkBitmap read_pixels_bitmap_;
- // Textures returned by the CreateTexture() function.
- std::vector<uint32> created_textures_;
- std::vector<gpu::Mailbox> created_texture_mailboxes_;
-
DISALLOW_COPY_AND_ASSIGN(RendererGpuVideoAcceleratorFactories);
};
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
index 3d23a9ce3c4..ec38769573f 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -13,10 +13,10 @@
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
-using WebKit::WebAudioDevice;
-using WebKit::WebFrame;
-using WebKit::WebVector;
-using WebKit::WebView;
+using blink::WebAudioDevice;
+using blink::WebFrame;
+using blink::WebVector;
+using blink::WebView;
namespace content {
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
index 5a8161fde83..962ec0851c3 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
@@ -19,15 +19,15 @@ class AudioOutputDevice;
namespace content {
class RendererWebAudioDeviceImpl
- : public WebKit::WebAudioDevice,
+ : public blink::WebAudioDevice,
public media::AudioRendererSink::RenderCallback {
public:
RendererWebAudioDeviceImpl(const media::AudioParameters& params,
- WebKit::WebAudioDevice::RenderCallback* callback,
+ blink::WebAudioDevice::RenderCallback* callback,
int session_id);
virtual ~RendererWebAudioDeviceImpl();
- // WebKit::WebAudioDevice implementation.
+ // blink::WebAudioDevice implementation.
virtual void start();
virtual void stop();
virtual double sampleRate();
@@ -46,10 +46,10 @@ class RendererWebAudioDeviceImpl
const media::AudioParameters params_;
// Weak reference to the callback into WebKit code.
- WebKit::WebAudioDevice::RenderCallback* const client_callback_;
+ blink::WebAudioDevice::RenderCallback* const client_callback_;
// To avoid the need for locking, ensure the control methods of the
- // WebKit::WebAudioDevice implementation are called on the same thread.
+ // blink::WebAudioDevice implementation are called on the same thread.
base::ThreadChecker thread_checker_;
// When non-NULL, we are started. When NULL, we are stopped.
diff --git a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc
index de9db931c13..b12174636e8 100644
--- a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc
+++ b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc
@@ -11,7 +11,7 @@
namespace content {
RendererWebMIDIAccessorImpl::RendererWebMIDIAccessorImpl(
- WebKit::WebMIDIAccessorClient* client)
+ blink::WebMIDIAccessorClient* client)
: client_(client) {
DCHECK(client_);
}
diff --git a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h
index 7032943c441..4ebaffd408b 100644
--- a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h
+++ b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h
@@ -15,13 +15,13 @@ namespace content {
class MIDIMessageFilter;
class RendererWebMIDIAccessorImpl
- : public WebKit::WebMIDIAccessor {
+ : public blink::WebMIDIAccessor {
public:
explicit RendererWebMIDIAccessorImpl(
- WebKit::WebMIDIAccessorClient* client);
+ blink::WebMIDIAccessorClient* client);
virtual ~RendererWebMIDIAccessorImpl();
- // WebKit::WebMIDIAccessor implementation.
+ // blink::WebMIDIAccessor implementation.
virtual void startSession();
virtual void sendMIDIData(unsigned port_index,
const unsigned char* data,
@@ -29,7 +29,7 @@ class RendererWebMIDIAccessorImpl
double timestamp);
private:
- WebKit::WebMIDIAccessorClient* client_;
+ blink::WebMIDIAccessorClient* client_;
MIDIMessageFilter* midi_message_filter();
diff --git a/chromium/content/renderer/media/rtc_data_channel_handler.cc b/chromium/content/renderer/media/rtc_data_channel_handler.cc
index 713dc4cf8b8..065048a5556 100644
--- a/chromium/content/renderer/media/rtc_data_channel_handler.cc
+++ b/chromium/content/renderer/media/rtc_data_channel_handler.cc
@@ -25,11 +25,11 @@ RtcDataChannelHandler::~RtcDataChannelHandler() {
}
void RtcDataChannelHandler::setClient(
- WebKit::WebRTCDataChannelHandlerClient* client) {
+ blink::WebRTCDataChannelHandlerClient* client) {
webkit_client_ = client;
}
-WebKit::WebString RtcDataChannelHandler::label() {
+blink::WebString RtcDataChannelHandler::label() {
return UTF8ToUTF16(channel_->label());
}
@@ -49,7 +49,7 @@ unsigned short RtcDataChannelHandler::maxRetransmits() const {
return channel_->maxRetransmits();
}
-WebKit::WebString RtcDataChannelHandler::protocol() const {
+blink::WebString RtcDataChannelHandler::protocol() const {
return UTF8ToUTF16(channel_->protocol());
}
@@ -65,7 +65,7 @@ unsigned long RtcDataChannelHandler::bufferedAmount() {
return channel_->buffered_amount();
}
-bool RtcDataChannelHandler::sendStringData(const WebKit::WebString& data) {
+bool RtcDataChannelHandler::sendStringData(const blink::WebString& data) {
std::string utf8_buffer = UTF16ToUTF8(data);
talk_base::Buffer buffer(utf8_buffer.c_str(), utf8_buffer.length());
webrtc::DataBuffer data_buffer(buffer, false);
@@ -91,19 +91,19 @@ void RtcDataChannelHandler::OnStateChange() {
switch (channel_->state()) {
case webrtc::DataChannelInterface::kConnecting:
webkit_client_->didChangeReadyState(
- WebKit::WebRTCDataChannelHandlerClient::ReadyStateConnecting);
+ blink::WebRTCDataChannelHandlerClient::ReadyStateConnecting);
break;
case webrtc::DataChannelInterface::kOpen:
webkit_client_->didChangeReadyState(
- WebKit::WebRTCDataChannelHandlerClient::ReadyStateOpen);
+ blink::WebRTCDataChannelHandlerClient::ReadyStateOpen);
break;
case webrtc::DataChannelInterface::kClosing:
webkit_client_->didChangeReadyState(
- WebKit::WebRTCDataChannelHandlerClient::ReadyStateClosing);
+ blink::WebRTCDataChannelHandlerClient::ReadyStateClosing);
break;
case webrtc::DataChannelInterface::kClosed:
webkit_client_->didChangeReadyState(
- WebKit::WebRTCDataChannelHandlerClient::ReadyStateClosed);
+ blink::WebRTCDataChannelHandlerClient::ReadyStateClosed);
break;
default:
NOTREACHED();
@@ -120,7 +120,7 @@ void RtcDataChannelHandler::OnMessage(const webrtc::DataBuffer& buffer) {
if (buffer.binary) {
webkit_client_->didReceiveRawData(buffer.data.data(), buffer.data.length());
} else {
- string16 utf16;
+ base::string16 utf16;
if (!UTF8ToUTF16(buffer.data.data(), buffer.data.length(), &utf16)) {
LOG(ERROR) << "Failed convert received data to UTF16";
return;
diff --git a/chromium/content/renderer/media/rtc_data_channel_handler.h b/chromium/content/renderer/media/rtc_data_channel_handler.h
index 8ec07e03691..a5521344f08 100644
--- a/chromium/content/renderer/media/rtc_data_channel_handler.h
+++ b/chromium/content/renderer/media/rtc_data_channel_handler.h
@@ -21,26 +21,26 @@ namespace content {
// Callbacks to the webrtc::DataChannelObserver implementation also occur on
// the main render thread.
class CONTENT_EXPORT RtcDataChannelHandler
- : NON_EXPORTED_BASE(public WebKit::WebRTCDataChannelHandler),
+ : NON_EXPORTED_BASE(public blink::WebRTCDataChannelHandler),
NON_EXPORTED_BASE(public webrtc::DataChannelObserver),
NON_EXPORTED_BASE(public base::NonThreadSafe) {
public:
explicit RtcDataChannelHandler(webrtc::DataChannelInterface* channel);
virtual ~RtcDataChannelHandler();
- // WebKit::WebRTCDataChannelHandler implementation.
+ // blink::WebRTCDataChannelHandler implementation.
virtual void setClient(
- WebKit::WebRTCDataChannelHandlerClient* client) OVERRIDE;
- virtual WebKit::WebString label() OVERRIDE;
+ blink::WebRTCDataChannelHandlerClient* client) OVERRIDE;
+ virtual blink::WebString label() OVERRIDE;
virtual bool isReliable() OVERRIDE;
virtual bool ordered() const OVERRIDE;
virtual unsigned short maxRetransmitTime() const OVERRIDE;
virtual unsigned short maxRetransmits() const OVERRIDE;
- virtual WebKit::WebString protocol() const OVERRIDE;
+ virtual blink::WebString protocol() const OVERRIDE;
virtual bool negotiated() const OVERRIDE;
virtual unsigned short id() const OVERRIDE;
virtual unsigned long bufferedAmount() OVERRIDE;
- virtual bool sendStringData(const WebKit::WebString& data) OVERRIDE;
+ virtual bool sendStringData(const blink::WebString& data) OVERRIDE;
virtual bool sendRawData(const char* data, size_t length) OVERRIDE;
virtual void close() OVERRIDE;
@@ -50,7 +50,7 @@ class CONTENT_EXPORT RtcDataChannelHandler
private:
scoped_refptr<webrtc::DataChannelInterface> channel_;
- WebKit::WebRTCDataChannelHandlerClient* webkit_client_;
+ blink::WebRTCDataChannelHandlerClient* webkit_client_;
};
} // namespace content
diff --git a/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc b/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc
index 72e75aa4c62..3df592c8a6b 100644
--- a/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc
+++ b/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc
@@ -26,11 +26,11 @@ RtcDtmfSenderHandler::~RtcDtmfSenderHandler() {
}
void RtcDtmfSenderHandler::setClient(
- WebKit::WebRTCDTMFSenderHandlerClient* client) {
+ blink::WebRTCDTMFSenderHandlerClient* client) {
webkit_client_ = client;
}
-WebKit::WebString RtcDtmfSenderHandler::currentToneBuffer() {
+blink::WebString RtcDtmfSenderHandler::currentToneBuffer() {
return UTF8ToUTF16(dtmf_sender_->tones());
}
@@ -38,7 +38,7 @@ bool RtcDtmfSenderHandler::canInsertDTMF() {
return dtmf_sender_->CanInsertDtmf();
}
-bool RtcDtmfSenderHandler::insertDTMF(const WebKit::WebString& tones,
+bool RtcDtmfSenderHandler::insertDTMF(const blink::WebString& tones,
long duration,
long interToneGap) {
std::string utf8_tones = UTF16ToUTF8(tones);
diff --git a/chromium/content/renderer/media/rtc_dtmf_sender_handler.h b/chromium/content/renderer/media/rtc_dtmf_sender_handler.h
index eeff5eb4860..3f77525fb5e 100644
--- a/chromium/content/renderer/media/rtc_dtmf_sender_handler.h
+++ b/chromium/content/renderer/media/rtc_dtmf_sender_handler.h
@@ -23,19 +23,19 @@ namespace content {
// Callbacks to the webrtc::DtmfSenderObserverInterface implementation also
// occur on the main render thread.
class CONTENT_EXPORT RtcDtmfSenderHandler
- : NON_EXPORTED_BASE(public WebKit::WebRTCDTMFSenderHandler),
+ : NON_EXPORTED_BASE(public blink::WebRTCDTMFSenderHandler),
NON_EXPORTED_BASE(public webrtc::DtmfSenderObserverInterface),
NON_EXPORTED_BASE(public base::NonThreadSafe) {
public:
explicit RtcDtmfSenderHandler(webrtc::DtmfSenderInterface* dtmf_sender);
virtual ~RtcDtmfSenderHandler();
- // WebKit::WebRTCDTMFSenderHandler implementation.
+ // blink::WebRTCDTMFSenderHandler implementation.
virtual void setClient(
- WebKit::WebRTCDTMFSenderHandlerClient* client) OVERRIDE;
- virtual WebKit::WebString currentToneBuffer() OVERRIDE;
+ blink::WebRTCDTMFSenderHandlerClient* client) OVERRIDE;
+ virtual blink::WebString currentToneBuffer() OVERRIDE;
virtual bool canInsertDTMF() OVERRIDE;
- virtual bool insertDTMF(const WebKit::WebString& tones, long duration,
+ virtual bool insertDTMF(const blink::WebString& tones, long duration,
long interToneGap) OVERRIDE;
// webrtc::DtmfSenderObserverInterface implementation.
@@ -43,7 +43,7 @@ class CONTENT_EXPORT RtcDtmfSenderHandler
private:
scoped_refptr<webrtc::DtmfSenderInterface> dtmf_sender_;
- WebKit::WebRTCDTMFSenderHandlerClient* webkit_client_;
+ blink::WebRTCDTMFSenderHandlerClient* webkit_client_;
};
} // namespace content
diff --git a/chromium/content/renderer/media/rtc_media_constraints.cc b/chromium/content/renderer/media/rtc_media_constraints.cc
index 7fa9791f2eb..4bdfd9079b3 100644
--- a/chromium/content/renderer/media/rtc_media_constraints.cc
+++ b/chromium/content/renderer/media/rtc_media_constraints.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "content/renderer/media/rtc_media_constraints.h"
+#include <string>
+
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "content/common/media/media_stream_options.h"
@@ -14,7 +16,7 @@ namespace content {
namespace {
void GetNativeMediaConstraints(
- const WebKit::WebVector<WebKit::WebMediaConstraint>& constraints,
+ const blink::WebVector<blink::WebMediaConstraint>& constraints,
webrtc::MediaConstraintsInterface::Constraints* native_constraints) {
DCHECK(native_constraints);
for (size_t i = 0; i < constraints.size(); ++i) {
@@ -27,12 +29,17 @@ void GetNativeMediaConstraints(
new_constraint.key == kMediaStreamSourceId)
continue;
+ // Ignore sourceId constraint since that has nothing to do with webrtc.
+ if (new_constraint.key == kMediaStreamSourceInfoId)
+ continue;
+
// Ignore internal constraints set by JS.
- // TODO(jiayl): replace the hard coded string with
- // webrtc::MediaConstraintsInterface::kInternalConstraintPrefix when
- // the Libjingle change is rolled.
- if (StartsWithASCII(new_constraint.key, "internal", true))
+ if (StartsWithASCII(
+ new_constraint.key,
+ webrtc::MediaConstraintsInterface::kInternalConstraintPrefix,
+ true)) {
continue;
+ }
DVLOG(3) << "MediaStreamConstraints:" << new_constraint.key
<< " : " << new_constraint.value;
@@ -45,13 +52,13 @@ void GetNativeMediaConstraints(
RTCMediaConstraints::RTCMediaConstraints() {}
RTCMediaConstraints::RTCMediaConstraints(
- const WebKit::WebMediaConstraints& constraints) {
+ const blink::WebMediaConstraints& constraints) {
if (constraints.isNull())
return; // Will happen in unit tests.
- WebKit::WebVector<WebKit::WebMediaConstraint> mandatory;
+ blink::WebVector<blink::WebMediaConstraint> mandatory;
constraints.getMandatoryConstraints(mandatory);
GetNativeMediaConstraints(mandatory, &mandatory_);
- WebKit::WebVector<WebKit::WebMediaConstraint> optional;
+ blink::WebVector<blink::WebMediaConstraint> optional;
constraints.getOptionalConstraints(optional);
GetNativeMediaConstraints(optional, &optional_);
}
diff --git a/chromium/content/renderer/media/rtc_media_constraints.h b/chromium/content/renderer/media/rtc_media_constraints.h
index 58f84864f22..fd55e346b06 100644
--- a/chromium/content/renderer/media/rtc_media_constraints.h
+++ b/chromium/content/renderer/media/rtc_media_constraints.h
@@ -9,7 +9,7 @@
#include "content/common/content_export.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
-namespace WebKit {
+namespace blink {
class WebMediaConstraints;
}
@@ -23,7 +23,7 @@ class CONTENT_EXPORT RTCMediaConstraints
public:
RTCMediaConstraints();
explicit RTCMediaConstraints(
- const WebKit::WebMediaConstraints& constraints);
+ const blink::WebMediaConstraints& constraints);
virtual ~RTCMediaConstraints();
virtual const Constraints& GetMandatory() const OVERRIDE;
virtual const Constraints& GetOptional() const OVERRIDE;
diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler.cc b/chromium/content/renderer/media/rtc_peer_connection_handler.cc
index 127a7e23fcd..1536ec30188 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler.cc
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler.cc
@@ -41,10 +41,10 @@
namespace content {
// Converter functions from libjingle types to WebKit types.
-WebKit::WebRTCPeerConnectionHandlerClient::ICEGatheringState
+blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
GetWebKitIceGatheringState(
webrtc::PeerConnectionInterface::IceGatheringState state) {
- using WebKit::WebRTCPeerConnectionHandlerClient;
+ using blink::WebRTCPeerConnectionHandlerClient;
switch (state) {
case webrtc::PeerConnectionInterface::kIceGatheringNew:
return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew;
@@ -58,10 +58,10 @@ GetWebKitIceGatheringState(
}
}
-static WebKit::WebRTCPeerConnectionHandlerClient::ICEConnectionState
+static blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
GetWebKitIceConnectionState(
webrtc::PeerConnectionInterface::IceConnectionState ice_state) {
- using WebKit::WebRTCPeerConnectionHandlerClient;
+ using blink::WebRTCPeerConnectionHandlerClient;
switch (ice_state) {
case webrtc::PeerConnectionInterface::kIceConnectionNew:
return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting;
@@ -83,9 +83,9 @@ GetWebKitIceConnectionState(
}
}
-static WebKit::WebRTCPeerConnectionHandlerClient::SignalingState
+static blink::WebRTCPeerConnectionHandlerClient::SignalingState
GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) {
- using WebKit::WebRTCPeerConnectionHandlerClient;
+ using blink::WebRTCPeerConnectionHandlerClient;
switch (state) {
case webrtc::PeerConnectionInterface::kStable:
return WebRTCPeerConnectionHandlerClient::SignalingStateStable;
@@ -106,10 +106,10 @@ GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) {
}
}
-static WebKit::WebRTCSessionDescription
+static blink::WebRTCSessionDescription
CreateWebKitSessionDescription(
const webrtc::SessionDescriptionInterface* native_desc) {
- WebKit::WebRTCSessionDescription description;
+ blink::WebRTCSessionDescription description;
if (!native_desc) {
LOG(ERROR) << "Native session description is null.";
return description;
@@ -128,13 +128,13 @@ CreateWebKitSessionDescription(
// Converter functions from WebKit types to libjingle types.
static void GetNativeIceServers(
- const WebKit::WebRTCConfiguration& server_configuration,
+ const blink::WebRTCConfiguration& server_configuration,
webrtc::PeerConnectionInterface::IceServers* servers) {
if (server_configuration.isNull() || !servers)
return;
for (size_t i = 0; i < server_configuration.numberOfServers(); ++i) {
webrtc::PeerConnectionInterface::IceServer server;
- const WebKit::WebRTCICEServer& webkit_server =
+ const blink::WebRTCICEServer& webkit_server =
server_configuration.server(i);
server.username = UTF16ToUTF8(webkit_server.username());
server.password = UTF16ToUTF8(webkit_server.credential());
@@ -172,12 +172,12 @@ class SessionDescriptionRequestTracker {
};
// Class mapping responses from calls to libjingle CreateOffer/Answer and
-// the WebKit::WebRTCSessionDescriptionRequest.
+// the blink::WebRTCSessionDescriptionRequest.
class CreateSessionDescriptionRequest
: public webrtc::CreateSessionDescriptionObserver {
public:
explicit CreateSessionDescriptionRequest(
- const WebKit::WebRTCSessionDescriptionRequest& request,
+ const blink::WebRTCSessionDescriptionRequest& request,
RTCPeerConnectionHandler* handler,
PeerConnectionTracker::Action action)
: webkit_request_(request), tracker_(handler, action) {}
@@ -195,17 +195,17 @@ class CreateSessionDescriptionRequest
virtual ~CreateSessionDescriptionRequest() {}
private:
- WebKit::WebRTCSessionDescriptionRequest webkit_request_;
+ blink::WebRTCSessionDescriptionRequest webkit_request_;
SessionDescriptionRequestTracker tracker_;
};
// Class mapping responses from calls to libjingle
-// SetLocalDescription/SetRemoteDescription and a WebKit::WebRTCVoidRequest.
+// SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
class SetSessionDescriptionRequest
: public webrtc::SetSessionDescriptionObserver {
public:
explicit SetSessionDescriptionRequest(
- const WebKit::WebRTCVoidRequest& request,
+ const blink::WebRTCVoidRequest& request,
RTCPeerConnectionHandler* handler,
PeerConnectionTracker::Action action)
: webkit_request_(request), tracker_(handler, action) {}
@@ -223,12 +223,12 @@ class SetSessionDescriptionRequest
virtual ~SetSessionDescriptionRequest() {}
private:
- WebKit::WebRTCVoidRequest webkit_request_;
+ blink::WebRTCVoidRequest webkit_request_;
SessionDescriptionRequestTracker tracker_;
};
// Class mapping responses from calls to libjingle
-// GetStats into a WebKit::WebRTCStatsCallback.
+// GetStats into a blink::WebRTCStatsCallback.
class StatsResponse : public webrtc::StatsObserver {
public:
explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request)
@@ -247,8 +247,8 @@ class StatsResponse : public webrtc::StatsObserver {
private:
void AddReport(const webrtc::StatsReport& report) {
- int idx = response_->addReport(WebKit::WebString::fromUTF8(report.id),
- WebKit::WebString::fromUTF8(report.type),
+ int idx = response_->addReport(blink::WebString::fromUTF8(report.id),
+ blink::WebString::fromUTF8(report.type),
report.timestamp);
for (webrtc::StatsReport::Values::const_iterator value_it =
report.values.begin();
@@ -260,8 +260,8 @@ class StatsResponse : public webrtc::StatsObserver {
void AddStatistic(int idx, const std::string& name,
const std::string& value) {
response_->addStatistic(idx,
- WebKit::WebString::fromUTF8(name),
- WebKit::WebString::fromUTF8(value));
+ blink::WebString::fromUTF8(name),
+ blink::WebString::fromUTF8(value));
}
talk_base::scoped_refptr<LocalRTCStatsRequest> request_;
@@ -269,7 +269,7 @@ class StatsResponse : public webrtc::StatsObserver {
};
// Implementation of LocalRTCStatsRequest.
-LocalRTCStatsRequest::LocalRTCStatsRequest(WebKit::WebRTCStatsRequest impl)
+LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
: impl_(impl),
response_(NULL) {
}
@@ -281,11 +281,7 @@ bool LocalRTCStatsRequest::hasSelector() const {
return impl_.hasSelector();
}
-WebKit::WebMediaStream LocalRTCStatsRequest::stream() const {
- return impl_.stream();
-}
-
-WebKit::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
+blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
return impl_.component();
}
@@ -302,24 +298,24 @@ void LocalRTCStatsRequest::requestSucceeded(
}
// Implementation of LocalRTCStatsResponse.
-WebKit::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
+blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const {
return impl_;
}
-size_t LocalRTCStatsResponse::addReport(WebKit::WebString type,
- WebKit::WebString id,
+size_t LocalRTCStatsResponse::addReport(blink::WebString type,
+ blink::WebString id,
double timestamp) {
return impl_.addReport(type, id, timestamp);
}
void LocalRTCStatsResponse::addStatistic(size_t report,
- WebKit::WebString name,
- WebKit::WebString value) {
+ blink::WebString name,
+ blink::WebString value) {
impl_.addStatistic(report, name, value);
}
RTCPeerConnectionHandler::RTCPeerConnectionHandler(
- WebKit::WebRTCPeerConnectionHandlerClient* client,
+ blink::WebRTCPeerConnectionHandlerClient* client,
MediaStreamDependencyFactory* dependency_factory)
: PeerConnectionHandlerBase(dependency_factory),
client_(client),
@@ -333,14 +329,14 @@ RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
STLDeleteValues(&remote_streams_);
}
-void RTCPeerConnectionHandler::associateWithFrame(WebKit::WebFrame* frame) {
+void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
DCHECK(frame);
frame_ = frame;
}
bool RTCPeerConnectionHandler::initialize(
- const WebKit::WebRTCConfiguration& server_configuration,
- const WebKit::WebMediaConstraints& options) {
+ const blink::WebRTCConfiguration& server_configuration,
+ const blink::WebMediaConstraints& options) {
DCHECK(frame_);
peer_connection_tracker_ =
@@ -351,12 +347,6 @@ bool RTCPeerConnectionHandler::initialize(
RTCMediaConstraints constraints(options);
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableSCTPDataChannels)) {
- constraints.AddOptional(
- webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, "true");
- }
-
native_peer_connection_ =
dependency_factory_->CreatePeerConnection(
servers, &constraints, frame_, this);
@@ -372,8 +362,8 @@ bool RTCPeerConnectionHandler::initialize(
}
bool RTCPeerConnectionHandler::InitializeForTest(
- const WebKit::WebRTCConfiguration& server_configuration,
- const WebKit::WebMediaConstraints& options,
+ const blink::WebRTCConfiguration& server_configuration,
+ const blink::WebMediaConstraints& options,
PeerConnectionTracker* peer_connection_tracker) {
webrtc::PeerConnectionInterface::IceServers servers;
GetNativeIceServers(server_configuration, &servers);
@@ -391,8 +381,8 @@ bool RTCPeerConnectionHandler::InitializeForTest(
}
void RTCPeerConnectionHandler::createOffer(
- const WebKit::WebRTCSessionDescriptionRequest& request,
- const WebKit::WebMediaConstraints& options) {
+ const blink::WebRTCSessionDescriptionRequest& request,
+ const blink::WebMediaConstraints& options) {
scoped_refptr<CreateSessionDescriptionRequest> description_request(
new talk_base::RefCountedObject<CreateSessionDescriptionRequest>(
request, this, PeerConnectionTracker::ACTION_CREATE_OFFER));
@@ -404,8 +394,8 @@ void RTCPeerConnectionHandler::createOffer(
}
void RTCPeerConnectionHandler::createAnswer(
- const WebKit::WebRTCSessionDescriptionRequest& request,
- const WebKit::WebMediaConstraints& options) {
+ const blink::WebRTCSessionDescriptionRequest& request,
+ const blink::WebMediaConstraints& options) {
scoped_refptr<CreateSessionDescriptionRequest> description_request(
new talk_base::RefCountedObject<CreateSessionDescriptionRequest>(
request, this, PeerConnectionTracker::ACTION_CREATE_ANSWER));
@@ -418,8 +408,8 @@ void RTCPeerConnectionHandler::createAnswer(
}
void RTCPeerConnectionHandler::setLocalDescription(
- const WebKit::WebRTCVoidRequest& request,
- const WebKit::WebRTCSessionDescription& description) {
+ const blink::WebRTCVoidRequest& request,
+ const blink::WebRTCSessionDescription& description) {
webrtc::SdpParseError error;
webrtc::SessionDescriptionInterface* native_desc =
CreateNativeSessionDescription(description, &error);
@@ -429,7 +419,7 @@ void RTCPeerConnectionHandler::setLocalDescription(
reason_str.append(" ");
reason_str.append(error.description);
LOG(ERROR) << reason_str;
- request.requestFailed(WebKit::WebString::fromUTF8(reason_str));
+ request.requestFailed(blink::WebString::fromUTF8(reason_str));
return;
}
if (peer_connection_tracker_)
@@ -443,8 +433,8 @@ void RTCPeerConnectionHandler::setLocalDescription(
}
void RTCPeerConnectionHandler::setRemoteDescription(
- const WebKit::WebRTCVoidRequest& request,
- const WebKit::WebRTCSessionDescription& description) {
+ const blink::WebRTCVoidRequest& request,
+ const blink::WebRTCSessionDescription& description) {
webrtc::SdpParseError error;
webrtc::SessionDescriptionInterface* native_desc =
CreateNativeSessionDescription(description, &error);
@@ -454,7 +444,7 @@ void RTCPeerConnectionHandler::setRemoteDescription(
reason_str.append(" ");
reason_str.append(error.description);
LOG(ERROR) << reason_str;
- request.requestFailed(WebKit::WebString::fromUTF8(reason_str));
+ request.requestFailed(blink::WebString::fromUTF8(reason_str));
return;
}
if (peer_connection_tracker_)
@@ -467,27 +457,27 @@ void RTCPeerConnectionHandler::setRemoteDescription(
native_peer_connection_->SetRemoteDescription(set_request.get(), native_desc);
}
-WebKit::WebRTCSessionDescription
+blink::WebRTCSessionDescription
RTCPeerConnectionHandler::localDescription() {
const webrtc::SessionDescriptionInterface* native_desc =
native_peer_connection_->local_description();
- WebKit::WebRTCSessionDescription description =
+ blink::WebRTCSessionDescription description =
CreateWebKitSessionDescription(native_desc);
return description;
}
-WebKit::WebRTCSessionDescription
+blink::WebRTCSessionDescription
RTCPeerConnectionHandler::remoteDescription() {
const webrtc::SessionDescriptionInterface* native_desc =
native_peer_connection_->remote_description();
- WebKit::WebRTCSessionDescription description =
+ blink::WebRTCSessionDescription description =
CreateWebKitSessionDescription(native_desc);
return description;
}
bool RTCPeerConnectionHandler::updateICE(
- const WebKit::WebRTCConfiguration& server_configuration,
- const WebKit::WebMediaConstraints& options) {
+ const blink::WebRTCConfiguration& server_configuration,
+ const blink::WebMediaConstraints& options) {
webrtc::PeerConnectionInterface::IceServers servers;
GetNativeIceServers(server_configuration, &servers);
RTCMediaConstraints constraints(options);
@@ -500,7 +490,21 @@ bool RTCPeerConnectionHandler::updateICE(
}
bool RTCPeerConnectionHandler::addICECandidate(
- const WebKit::WebRTCICECandidate& candidate) {
+ const blink::WebRTCVoidRequest& request,
+ const blink::WebRTCICECandidate& candidate) {
+ // Libjingle currently does not accept callbacks for addICECandidate.
+ // For that reason we are going to call callbacks from here.
+ bool result = addICECandidate(candidate);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult,
+ base::Unretained(this), request, result));
+ // On failure callback will be triggered.
+ return true;
+}
+
+bool RTCPeerConnectionHandler::addICECandidate(
+ const blink::WebRTCICECandidate& candidate) {
scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
dependency_factory_->CreateIceCandidate(
UTF16ToUTF8(candidate.sdpMid()),
@@ -522,9 +526,21 @@ bool RTCPeerConnectionHandler::addICECandidate(
return return_value;
}
+void RTCPeerConnectionHandler::OnaddICECandidateResult(
+ const blink::WebRTCVoidRequest& webkit_request, bool result) {
+ if (!result) {
+ // We don't have the actual error code from the libjingle, so for now
+ // using a generic error string.
+ return webkit_request.requestFailed(
+ UTF8ToUTF16("Error processing ICE candidate"));
+ }
+
+ return webkit_request.requestSucceeded();
+}
+
bool RTCPeerConnectionHandler::addStream(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaConstraints& options) {
+ const blink::WebMediaStream& stream,
+ const blink::WebMediaConstraints& options) {
RTCMediaConstraints constraints(options);
if (peer_connection_tracker_)
@@ -545,7 +561,7 @@ bool RTCPeerConnectionHandler::addStream(
}
void RTCPeerConnectionHandler::removeStream(
- const WebKit::WebMediaStream& stream) {
+ const blink::WebMediaStream& stream) {
RemoveStream(stream);
if (peer_connection_tracker_)
peer_connection_tracker_->TrackRemoveStream(
@@ -553,7 +569,7 @@ void RTCPeerConnectionHandler::removeStream(
}
void RTCPeerConnectionHandler::getStats(
- const WebKit::WebRTCStatsRequest& request) {
+ const blink::WebRTCStatsRequest& request) {
scoped_refptr<LocalRTCStatsRequest> inner_request(
new talk_base::RefCountedObject<LocalRTCStatsRequest>(request));
getStats(inner_request.get());
@@ -564,8 +580,8 @@ void RTCPeerConnectionHandler::getStats(LocalRTCStatsRequest* request) {
new talk_base::RefCountedObject<StatsResponse>(request));
webrtc::MediaStreamTrackInterface* track = NULL;
if (request->hasSelector()) {
- track = GetNativeMediaStreamTrack(request->stream(),
- request->component());
+ track = MediaStreamDependencyFactory::GetNativeMediaStreamTrack(
+ request->component());
if (!track) {
DVLOG(1) << "GetStats: Track not found.";
// TODO(hta): Consider how to get an error back.
@@ -589,8 +605,8 @@ void RTCPeerConnectionHandler::GetStats(
}
}
-WebKit::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
- const WebKit::WebString& label, const WebKit::WebRTCDataChannelInit& init) {
+blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
+ const blink::WebString& label, const blink::WebRTCDataChannelInit& init) {
DVLOG(1) << "createDataChannel label " << UTF16ToUTF8(label);
webrtc::DataChannelInit config;
@@ -617,18 +633,18 @@ WebKit::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
return new RtcDataChannelHandler(webrtc_channel);
}
-WebKit::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
- const WebKit::WebMediaStreamTrack& track) {
+blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
+ const blink::WebMediaStreamTrack& track) {
DVLOG(1) << "createDTMFSender.";
- if (track.source().type() != WebKit::WebMediaStreamSource::TypeAudio) {
+ if (track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
DLOG(ERROR) << "Could not create DTMF sender from a non-audio track.";
return NULL;
}
webrtc::AudioTrackInterface* audio_track =
static_cast<webrtc::AudioTrackInterface*>(
- GetNativeMediaStreamTrack(track.stream(), track));
+ MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track));
talk_base::scoped_refptr<webrtc::DtmfSenderInterface> sender(
native_peer_connection_->CreateDtmfSender(audio_track));
@@ -657,7 +673,7 @@ void RTCPeerConnectionHandler::OnError() {
void RTCPeerConnectionHandler::OnSignalingChange(
webrtc::PeerConnectionInterface::SignalingState new_state) {
- WebKit::WebRTCPeerConnectionHandlerClient::SignalingState state =
+ blink::WebRTCPeerConnectionHandlerClient::SignalingState state =
GetWebKitSignalingState(new_state);
if (peer_connection_tracker_)
peer_connection_tracker_->TrackSignalingStateChange(this, state);
@@ -667,7 +683,7 @@ void RTCPeerConnectionHandler::OnSignalingChange(
// Called any time the IceConnectionState changes
void RTCPeerConnectionHandler::OnIceConnectionChange(
webrtc::PeerConnectionInterface::IceConnectionState new_state) {
- WebKit::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
+ blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
GetWebKitIceConnectionState(new_state);
if (peer_connection_tracker_)
peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
@@ -680,11 +696,11 @@ void RTCPeerConnectionHandler::OnIceGatheringChange(
if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
// If ICE gathering is completed, generate a NULL ICE candidate,
// to signal end of candidates.
- WebKit::WebRTCICECandidate null_candidate;
+ blink::WebRTCICECandidate null_candidate;
client_->didGenerateICECandidate(null_candidate);
}
- WebKit::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
+ blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
GetWebKitIceGatheringState(new_state);
if (peer_connection_tracker_)
peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
@@ -720,7 +736,7 @@ void RTCPeerConnectionHandler::OnRemoveStream(
}
scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
- const WebKit::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
+ const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
DCHECK(!webkit_stream.isNull());
remote_streams_.erase(it);
@@ -739,7 +755,7 @@ void RTCPeerConnectionHandler::OnIceCandidate(
NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
return;
}
- WebKit::WebRTCICECandidate web_candidate;
+ blink::WebRTCICECandidate web_candidate;
web_candidate.initialize(UTF8ToUTF16(sdp),
UTF8ToUTF16(candidate->sdp_mid()),
candidate->sdp_mline_index());
@@ -773,7 +789,7 @@ PeerConnectionTracker* RTCPeerConnectionHandler::peer_connection_tracker() {
webrtc::SessionDescriptionInterface*
RTCPeerConnectionHandler::CreateNativeSessionDescription(
- const WebKit::WebRTCSessionDescription& description,
+ const blink::WebRTCSessionDescription& description,
webrtc::SdpParseError* error) {
std::string sdp = UTF16ToUTF8(description.sdp());
std::string type = UTF16ToUTF8(description.type());
diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler.h b/chromium/content/renderer/media/rtc_peer_connection_handler.h
index bb650102143..f3de4b9e8f7 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler.h
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler.h
@@ -13,7 +13,7 @@
#include "third_party/WebKit/public/platform/WebRTCStatsRequest.h"
#include "third_party/WebKit/public/platform/WebRTCStatsResponse.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebRTCDataChannelHandler;
}
@@ -22,19 +22,19 @@ namespace content {
class PeerConnectionTracker;
-// Mockable wrapper for WebKit::WebRTCStatsResponse
+// Mockable wrapper for blink::WebRTCStatsResponse
class CONTENT_EXPORT LocalRTCStatsResponse
: public NON_EXPORTED_BASE(talk_base::RefCountInterface) {
public:
- explicit LocalRTCStatsResponse(const WebKit::WebRTCStatsResponse& impl)
+ explicit LocalRTCStatsResponse(const blink::WebRTCStatsResponse& impl)
: impl_(impl) {
}
- virtual WebKit::WebRTCStatsResponse webKitStatsResponse() const;
- virtual size_t addReport(WebKit::WebString type, WebKit::WebString id,
+ virtual blink::WebRTCStatsResponse webKitStatsResponse() const;
+ virtual size_t addReport(blink::WebString type, blink::WebString id,
double timestamp);
virtual void addStatistic(size_t report,
- WebKit::WebString name, WebKit::WebString value);
+ blink::WebString name, blink::WebString value);
protected:
virtual ~LocalRTCStatsResponse() {}
@@ -42,20 +42,19 @@ class CONTENT_EXPORT LocalRTCStatsResponse
LocalRTCStatsResponse() {}
private:
- WebKit::WebRTCStatsResponse impl_;
+ blink::WebRTCStatsResponse impl_;
};
-// Mockable wrapper for WebKit::WebRTCStatsRequest
+// Mockable wrapper for blink::WebRTCStatsRequest
class CONTENT_EXPORT LocalRTCStatsRequest
: public NON_EXPORTED_BASE(talk_base::RefCountInterface) {
public:
- explicit LocalRTCStatsRequest(WebKit::WebRTCStatsRequest impl);
+ explicit LocalRTCStatsRequest(blink::WebRTCStatsRequest impl);
// Constructor for testing.
LocalRTCStatsRequest();
virtual bool hasSelector() const;
- virtual WebKit::WebMediaStream stream() const;
- virtual WebKit::WebMediaStreamTrack component() const;
+ virtual blink::WebMediaStreamTrack component() const;
virtual void requestSucceeded(const LocalRTCStatsResponse* response);
virtual scoped_refptr<LocalRTCStatsResponse> createResponse();
@@ -63,7 +62,7 @@ class CONTENT_EXPORT LocalRTCStatsRequest
virtual ~LocalRTCStatsRequest();
private:
- WebKit::WebRTCStatsRequest impl_;
+ blink::WebRTCStatsRequest impl_;
talk_base::scoped_refptr<LocalRTCStatsResponse> response_;
};
@@ -75,62 +74,68 @@ class CONTENT_EXPORT LocalRTCStatsRequest
// the main render thread.
class CONTENT_EXPORT RTCPeerConnectionHandler
: public PeerConnectionHandlerBase,
- NON_EXPORTED_BASE(public WebKit::WebRTCPeerConnectionHandler) {
+ NON_EXPORTED_BASE(public blink::WebRTCPeerConnectionHandler) {
public:
RTCPeerConnectionHandler(
- WebKit::WebRTCPeerConnectionHandlerClient* client,
+ blink::WebRTCPeerConnectionHandlerClient* client,
MediaStreamDependencyFactory* dependency_factory);
virtual ~RTCPeerConnectionHandler();
- void associateWithFrame(WebKit::WebFrame* frame);
+ void associateWithFrame(blink::WebFrame* frame);
// Initialize method only used for unit test.
bool InitializeForTest(
- const WebKit::WebRTCConfiguration& server_configuration,
- const WebKit::WebMediaConstraints& options,
+ const blink::WebRTCConfiguration& server_configuration,
+ const blink::WebMediaConstraints& options,
PeerConnectionTracker* peer_connection_tracker);
- // WebKit::WebRTCPeerConnectionHandler implementation
+ // blink::WebRTCPeerConnectionHandler implementation
virtual bool initialize(
- const WebKit::WebRTCConfiguration& server_configuration,
- const WebKit::WebMediaConstraints& options) OVERRIDE;
+ const blink::WebRTCConfiguration& server_configuration,
+ const blink::WebMediaConstraints& options) OVERRIDE;
virtual void createOffer(
- const WebKit::WebRTCSessionDescriptionRequest& request,
- const WebKit::WebMediaConstraints& options) OVERRIDE;
+ const blink::WebRTCSessionDescriptionRequest& request,
+ const blink::WebMediaConstraints& options) OVERRIDE;
virtual void createAnswer(
- const WebKit::WebRTCSessionDescriptionRequest& request,
- const WebKit::WebMediaConstraints& options) OVERRIDE;
+ const blink::WebRTCSessionDescriptionRequest& request,
+ const blink::WebMediaConstraints& options) OVERRIDE;
virtual void setLocalDescription(
- const WebKit::WebRTCVoidRequest& request,
- const WebKit::WebRTCSessionDescription& description) OVERRIDE;
+ const blink::WebRTCVoidRequest& request,
+ const blink::WebRTCSessionDescription& description) OVERRIDE;
virtual void setRemoteDescription(
- const WebKit::WebRTCVoidRequest& request,
- const WebKit::WebRTCSessionDescription& description) OVERRIDE;
+ const blink::WebRTCVoidRequest& request,
+ const blink::WebRTCSessionDescription& description) OVERRIDE;
- virtual WebKit::WebRTCSessionDescription localDescription()
+ virtual blink::WebRTCSessionDescription localDescription()
OVERRIDE;
- virtual WebKit::WebRTCSessionDescription remoteDescription()
+ virtual blink::WebRTCSessionDescription remoteDescription()
OVERRIDE;
+
virtual bool updateICE(
- const WebKit::WebRTCConfiguration& server_configuration,
- const WebKit::WebMediaConstraints& options) OVERRIDE;
+ const blink::WebRTCConfiguration& server_configuration,
+ const blink::WebMediaConstraints& options) OVERRIDE;
+ virtual bool addICECandidate(
+ const blink::WebRTCICECandidate& candidate) OVERRIDE;
virtual bool addICECandidate(
- const WebKit::WebRTCICECandidate& candidate) OVERRIDE;
+ const blink::WebRTCVoidRequest& request,
+ const blink::WebRTCICECandidate& candidate) OVERRIDE;
+ virtual void OnaddICECandidateResult(const blink::WebRTCVoidRequest& request,
+ bool result);
virtual bool addStream(
- const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaConstraints& options) OVERRIDE;
+ const blink::WebMediaStream& stream,
+ const blink::WebMediaConstraints& options) OVERRIDE;
virtual void removeStream(
- const WebKit::WebMediaStream& stream) OVERRIDE;
+ const blink::WebMediaStream& stream) OVERRIDE;
virtual void getStats(
- const WebKit::WebRTCStatsRequest& request) OVERRIDE;
- virtual WebKit::WebRTCDataChannelHandler* createDataChannel(
- const WebKit::WebString& label,
- const WebKit::WebRTCDataChannelInit& init) OVERRIDE;
- virtual WebKit::WebRTCDTMFSenderHandler* createDTMFSender(
- const WebKit::WebMediaStreamTrack& track) OVERRIDE;
+ const blink::WebRTCStatsRequest& request) OVERRIDE;
+ virtual blink::WebRTCDataChannelHandler* createDataChannel(
+ const blink::WebString& label,
+ const blink::WebRTCDataChannelInit& init) OVERRIDE;
+ virtual blink::WebRTCDTMFSenderHandler* createDTMFSender(
+ const blink::WebMediaStreamTrack& track) OVERRIDE;
virtual void stop() OVERRIDE;
// webrtc::PeerConnectionObserver implementation
@@ -163,13 +168,13 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
private:
webrtc::SessionDescriptionInterface* CreateNativeSessionDescription(
- const WebKit::WebRTCSessionDescription& description,
+ const blink::WebRTCSessionDescription& description,
webrtc::SdpParseError* error);
// |client_| is a weak pointer, and is valid until stop() has returned.
- WebKit::WebRTCPeerConnectionHandlerClient* client_;
+ blink::WebRTCPeerConnectionHandlerClient* client_;
- WebKit::WebFrame* frame_;
+ blink::WebFrame* frame_;
PeerConnectionTracker* peer_connection_tracker_;
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 9528cbe6714..18901ea7a7e 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc
@@ -38,7 +38,7 @@
static const char kDummySdp[] = "dummy sdp";
static const char kDummySdpType[] = "dummy type";
-using WebKit::WebRTCPeerConnectionHandlerClient;
+using blink::WebRTCPeerConnectionHandlerClient;
using testing::NiceMock;
using testing::_;
using testing::Ref;
@@ -52,15 +52,15 @@ class MockRTCStatsResponse : public LocalRTCStatsResponse {
statistic_count_(0) {
}
- virtual size_t addReport(WebKit::WebString type,
- WebKit::WebString id,
+ virtual size_t addReport(blink::WebString type,
+ blink::WebString id,
double timestamp) OVERRIDE {
++report_count_;
return report_count_;
}
virtual void addStatistic(size_t report,
- WebKit::WebString name, WebKit::WebString value)
+ blink::WebString name, blink::WebString value)
OVERRIDE {
++statistic_count_;
}
@@ -71,21 +71,17 @@ class MockRTCStatsResponse : public LocalRTCStatsResponse {
int statistic_count_;
};
-// Mocked wrapper for WebKit::WebRTCStatsRequest
+// Mocked wrapper for blink::WebRTCStatsRequest
class MockRTCStatsRequest : public LocalRTCStatsRequest {
public:
MockRTCStatsRequest()
: has_selector_(false),
- stream_(),
request_succeeded_called_(false) {}
virtual bool hasSelector() const OVERRIDE {
return has_selector_;
}
- virtual WebKit::WebMediaStream stream() const OVERRIDE {
- return stream_;
- }
- virtual WebKit::WebMediaStreamTrack component() const OVERRIDE {
+ virtual blink::WebMediaStreamTrack component() const OVERRIDE {
return component_;
}
virtual scoped_refptr<LocalRTCStatsResponse> createResponse() OVERRIDE {
@@ -101,10 +97,8 @@ class MockRTCStatsRequest : public LocalRTCStatsRequest {
}
// Function for setting whether or not a selector is available.
- void setSelector(const WebKit::WebMediaStream& stream,
- const WebKit::WebMediaStreamTrack& component) {
+ void setSelector(const blink::WebMediaStreamTrack& component) {
has_selector_ = true;
- stream_ = stream;
component_ = component;
}
@@ -119,8 +113,7 @@ class MockRTCStatsRequest : public LocalRTCStatsRequest {
private:
bool has_selector_;
- WebKit::WebMediaStream stream_;
- WebKit::WebMediaStreamTrack component_;
+ blink::WebMediaStreamTrack component_;
scoped_refptr<MockRTCStatsResponse> response_;
bool request_succeeded_called_;
};
@@ -138,7 +131,7 @@ class MockPeerConnectionTracker : public PeerConnectionTracker {
const RTCMediaConstraints& constraints));
MOCK_METHOD3(TrackSetSessionDescription,
void(RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebRTCSessionDescription& desc,
+ const blink::WebRTCSessionDescription& desc,
Source source));
MOCK_METHOD3(
TrackUpdateIce,
@@ -148,15 +141,15 @@ class MockPeerConnectionTracker : public PeerConnectionTracker {
const RTCMediaConstraints& options));
MOCK_METHOD3(TrackAddIceCandidate,
void(RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebRTCICECandidate& candidate,
+ const blink::WebRTCICECandidate& candidate,
Source source));
MOCK_METHOD3(TrackAddStream,
void(RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebMediaStream& stream,
+ const blink::WebMediaStream& stream,
Source source));
MOCK_METHOD3(TrackRemoveStream,
void(RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebMediaStream& stream,
+ const blink::WebMediaStream& stream,
Source source));
MOCK_METHOD1(TrackOnIceComplete,
void(RTCPeerConnectionHandler* pc_handler));
@@ -180,7 +173,7 @@ class MockPeerConnectionTracker : public PeerConnectionTracker {
void(RTCPeerConnectionHandler* pc_handler));
MOCK_METHOD2(TrackCreateDTMFSender,
void(RTCPeerConnectionHandler* pc_handler,
- const WebKit::WebMediaStreamTrack& track));
+ const blink::WebMediaStreamTrack& track));
};
class RTCPeerConnectionHandlerUnderTest : public RTCPeerConnectionHandler {
@@ -209,8 +202,8 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
new RTCPeerConnectionHandlerUnderTest(mock_client_.get(),
mock_dependency_factory_.get()));
mock_tracker_.reset(new NiceMock<MockPeerConnectionTracker>());
- WebKit::WebRTCConfiguration config;
- WebKit::WebMediaConstraints constraints;
+ blink::WebRTCConfiguration config;
+ blink::WebMediaConstraints constraints;
EXPECT_TRUE(pc_handler_->InitializeForTest(config, constraints,
mock_tracker_.get()));
@@ -219,28 +212,28 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
}
// Creates a WebKit local MediaStream.
- WebKit::WebMediaStream CreateLocalMediaStream(
+ blink::WebMediaStream CreateLocalMediaStream(
const std::string& stream_label) {
std::string video_track_label("video-label");
std::string audio_track_label("audio-label");
- WebKit::WebMediaStreamSource audio_source;
- audio_source.initialize(WebKit::WebString::fromUTF8(audio_track_label),
- WebKit::WebMediaStreamSource::TypeAudio,
- WebKit::WebString::fromUTF8("audio_track"));
- WebKit::WebMediaStreamSource video_source;
- video_source.initialize(WebKit::WebString::fromUTF8(video_track_label),
- WebKit::WebMediaStreamSource::TypeVideo,
- WebKit::WebString::fromUTF8("video_track"));
+ blink::WebMediaStreamSource audio_source;
+ audio_source.initialize(blink::WebString::fromUTF8(audio_track_label),
+ blink::WebMediaStreamSource::TypeAudio,
+ blink::WebString::fromUTF8("audio_track"));
+ blink::WebMediaStreamSource video_source;
+ video_source.initialize(blink::WebString::fromUTF8(video_track_label),
+ blink::WebMediaStreamSource::TypeVideo,
+ blink::WebString::fromUTF8("video_track"));
- WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks(
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks(
static_cast<size_t>(1));
audio_tracks[0].initialize(audio_source.id(), audio_source);
- WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks(
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks(
static_cast<size_t>(1));
video_tracks[0].initialize(video_source.id(), video_source);
- WebKit::WebMediaStream local_stream;
+ blink::WebMediaStream local_stream;
local_stream.initialize(UTF8ToUTF16(stream_label), audio_tracks,
video_tracks);
@@ -255,6 +248,8 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
mock_dependency_factory_->CreateLocalAudioTrack(
audio_track_id, capturer, NULL, NULL,
&audio_constraints));
+ MediaStreamDependencyFactory::AddNativeTrackToBlinkTrack(
+ audio_track.get(), audio_tracks[0], true);
native_stream->AddTrack(audio_track.get());
local_stream.videoTracks(video_tracks);
@@ -263,6 +258,8 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
scoped_refptr<webrtc::VideoTrackInterface> video_track(
mock_dependency_factory_->CreateLocalVideoTrack(
video_track_id, source));
+ MediaStreamDependencyFactory::AddNativeTrackToBlinkTrack(
+ video_track.get(), video_tracks[0], true);
native_stream->AddTrack(video_track.get());
local_stream.setExtraData(
@@ -315,11 +312,11 @@ TEST_F(RTCPeerConnectionHandlerTest, Destruct) {
}
TEST_F(RTCPeerConnectionHandlerTest, CreateOffer) {
- WebKit::WebRTCSessionDescriptionRequest request;
- WebKit::WebMediaConstraints options;
+ blink::WebRTCSessionDescriptionRequest request;
+ blink::WebMediaConstraints options;
EXPECT_CALL(*mock_tracker_.get(), TrackCreateOffer(pc_handler_.get(), _));
- // TODO(perkj): Can WebKit::WebRTCSessionDescriptionRequest be changed so
+ // TODO(perkj): Can blink::WebRTCSessionDescriptionRequest be changed so
// the |reqest| requestSucceeded can be tested? Currently the |request| object
// can not be initialized from a unit test.
EXPECT_FALSE(mock_peer_connection_->created_session_description() != NULL);
@@ -328,10 +325,10 @@ TEST_F(RTCPeerConnectionHandlerTest, CreateOffer) {
}
TEST_F(RTCPeerConnectionHandlerTest, CreateAnswer) {
- WebKit::WebRTCSessionDescriptionRequest request;
- WebKit::WebMediaConstraints options;
+ blink::WebRTCSessionDescriptionRequest request;
+ blink::WebMediaConstraints options;
EXPECT_CALL(*mock_tracker_.get(), TrackCreateAnswer(pc_handler_.get(), _));
- // TODO(perkj): Can WebKit::WebRTCSessionDescriptionRequest be changed so
+ // TODO(perkj): Can blink::WebRTCSessionDescriptionRequest be changed so
// the |reqest| requestSucceeded can be tested? Currently the |request| object
// can not be initialized from a unit test.
EXPECT_FALSE(mock_peer_connection_->created_session_description() != NULL);
@@ -340,8 +337,8 @@ TEST_F(RTCPeerConnectionHandlerTest, CreateAnswer) {
}
TEST_F(RTCPeerConnectionHandlerTest, setLocalDescription) {
- WebKit::WebRTCVoidRequest request;
- WebKit::WebRTCSessionDescription description;
+ blink::WebRTCVoidRequest request;
+ blink::WebRTCSessionDescription description;
description.initialize(kDummySdpType, kDummySdp);
// PeerConnectionTracker::TrackSetSessionDescription is expected to be called
// before |mock_peer_connection| is called.
@@ -363,8 +360,8 @@ TEST_F(RTCPeerConnectionHandlerTest, setLocalDescription) {
}
TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescription) {
- WebKit::WebRTCVoidRequest request;
- WebKit::WebRTCSessionDescription description;
+ blink::WebRTCVoidRequest request;
+ blink::WebRTCSessionDescription description;
description.initialize(kDummySdpType, kDummySdp);
// PeerConnectionTracker::TrackSetSessionDescription is expected to be called
@@ -387,8 +384,8 @@ TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescription) {
}
TEST_F(RTCPeerConnectionHandlerTest, updateICE) {
- WebKit::WebRTCConfiguration config;
- WebKit::WebMediaConstraints constraints;
+ blink::WebRTCConfiguration config;
+ blink::WebMediaConstraints constraints;
EXPECT_CALL(*mock_tracker_.get(), TrackUpdateIce(pc_handler_.get(), _, _));
// TODO(perkj): Test that the parameters in |config| can be translated when a
@@ -398,7 +395,7 @@ TEST_F(RTCPeerConnectionHandlerTest, updateICE) {
}
TEST_F(RTCPeerConnectionHandlerTest, addICECandidate) {
- WebKit::WebRTCICECandidate candidate;
+ blink::WebRTCICECandidate candidate;
candidate.initialize(kDummySdp, "mid", 1);
EXPECT_CALL(*mock_tracker_.get(),
@@ -413,9 +410,9 @@ TEST_F(RTCPeerConnectionHandlerTest, addICECandidate) {
TEST_F(RTCPeerConnectionHandlerTest, addAndRemoveStream) {
std::string stream_label = "local_stream";
- WebKit::WebMediaStream local_stream(
+ blink::WebMediaStream local_stream(
CreateLocalMediaStream(stream_label));
- WebKit::WebMediaConstraints constraints;
+ blink::WebMediaConstraints constraints;
EXPECT_CALL(*mock_tracker_.get(),
TrackAddStream(pc_handler_.get(),
@@ -456,17 +453,17 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsAfterClose) {
}
TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithLocalSelector) {
- WebKit::WebMediaStream local_stream(
+ blink::WebMediaStream local_stream(
CreateLocalMediaStream("local_stream"));
- WebKit::WebMediaConstraints constraints;
+ blink::WebMediaConstraints constraints;
pc_handler_->addStream(local_stream, constraints);
- WebKit::WebVector<WebKit::WebMediaStreamTrack> tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> tracks;
local_stream.audioTracks(tracks);
ASSERT_LE(1ul, tracks.size());
scoped_refptr<MockRTCStatsRequest> request(
new talk_base::RefCountedObject<MockRTCStatsRequest>());
- request->setSelector(local_stream, tracks[0]);
+ request->setSelector(tracks[0]);
pc_handler_->getStats(request.get());
EXPECT_EQ(1, request->result()->report_count());
}
@@ -475,15 +472,15 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithRemoteSelector) {
scoped_refptr<webrtc::MediaStreamInterface> stream(
AddRemoteMockMediaStream("remote_stream", "video", "audio"));
pc_handler_->OnAddStream(stream.get());
- const WebKit::WebMediaStream& remote_stream = mock_client_->remote_stream();
+ const blink::WebMediaStream& remote_stream = mock_client_->remote_stream();
- WebKit::WebVector<WebKit::WebMediaStreamTrack> tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> tracks;
remote_stream.audioTracks(tracks);
ASSERT_LE(1ul, tracks.size());
scoped_refptr<MockRTCStatsRequest> request(
new talk_base::RefCountedObject<MockRTCStatsRequest>());
- request->setSelector(remote_stream, tracks[0]);
+ request->setSelector(tracks[0]);
pc_handler_->getStats(request.get());
EXPECT_EQ(1, request->result()->report_count());
}
@@ -491,18 +488,18 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithRemoteSelector) {
TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithBadSelector) {
// The setup is the same as GetStatsWithLocalSelector, but the stream is not
// added to the PeerConnection.
- WebKit::WebMediaStream local_stream(
+ blink::WebMediaStream local_stream(
CreateLocalMediaStream("local_stream_2"));
- WebKit::WebMediaConstraints constraints;
- WebKit::WebVector<WebKit::WebMediaStreamTrack> tracks;
+ blink::WebMediaConstraints constraints;
+ blink::WebVector<blink::WebMediaStreamTrack> tracks;
local_stream.audioTracks(tracks);
- WebKit::WebMediaStreamTrack component = tracks[0];
+ blink::WebMediaStreamTrack component = tracks[0];
mock_peer_connection_->SetGetStatsResult(false);
scoped_refptr<MockRTCStatsRequest> request(
new talk_base::RefCountedObject<MockRTCStatsRequest>());
- request->setSelector(local_stream, component);
+ request->setSelector(component);
pc_handler_->getStats(request.get());
EXPECT_EQ(0, request->result()->report_count());
}
@@ -655,20 +652,20 @@ TEST_F(RTCPeerConnectionHandlerTest, OnAddAndOnRemoveStream) {
testing::InSequence sequence;
EXPECT_CALL(*mock_tracker_.get(), TrackAddStream(
pc_handler_.get(),
- testing::Property(&WebKit::WebMediaStream::id,
+ testing::Property(&blink::WebMediaStream::id,
UTF8ToUTF16(remote_stream_label)),
PeerConnectionTracker::SOURCE_REMOTE));
EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
- testing::Property(&WebKit::WebMediaStream::id,
+ testing::Property(&blink::WebMediaStream::id,
UTF8ToUTF16(remote_stream_label))));
EXPECT_CALL(*mock_tracker_.get(), TrackRemoveStream(
pc_handler_.get(),
- testing::Property(&WebKit::WebMediaStream::id,
+ testing::Property(&blink::WebMediaStream::id,
UTF8ToUTF16(remote_stream_label)),
PeerConnectionTracker::SOURCE_REMOTE));
EXPECT_CALL(*mock_client_.get(), didRemoveRemoteStream(
- testing::Property(&WebKit::WebMediaStream::id,
+ testing::Property(&blink::WebMediaStream::id,
UTF8ToUTF16(remote_stream_label))));
pc_handler_->OnAddStream(remote_stream.get());
@@ -683,29 +680,29 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoteTrackState) {
testing::InSequence sequence;
EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
- testing::Property(&WebKit::WebMediaStream::id,
+ testing::Property(&blink::WebMediaStream::id,
UTF8ToUTF16(remote_stream_label))));
pc_handler_->OnAddStream(remote_stream.get());
- const WebKit::WebMediaStream& webkit_stream = mock_client_->remote_stream();
+ const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
- WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
webkit_stream.audioTracks(audio_tracks);
- EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateLive,
+ EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
audio_tracks[0].source().readyState());
- WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
webkit_stream.videoTracks(video_tracks);
- EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateLive,
+ EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
video_tracks[0].source().readyState());
remote_stream->GetAudioTracks()[0]->set_state(
webrtc::MediaStreamTrackInterface::kEnded);
- EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateEnded,
+ EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
audio_tracks[0].source().readyState());
remote_stream->GetVideoTracks()[0]->set_state(
webrtc::MediaStreamTrackInterface::kEnded);
- EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateEnded,
+ EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
video_tracks[0].source().readyState());
}
@@ -715,12 +712,12 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) {
AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
- testing::Property(&WebKit::WebMediaStream::id,
+ testing::Property(&blink::WebMediaStream::id,
UTF8ToUTF16(remote_stream_label))));
pc_handler_->OnAddStream(remote_stream.get());
- const WebKit::WebMediaStream& webkit_stream = mock_client_->remote_stream();
+ const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
- WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
webkit_stream.audioTracks(audio_tracks);
EXPECT_EQ(1u, audio_tracks.size());
@@ -728,13 +725,13 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) {
scoped_refptr<webrtc::AudioTrackInterface> webrtc_track =
remote_stream->GetAudioTracks()[0].get();
remote_stream->RemoveTrack(webrtc_track.get());
- WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_audio_tracks1;
+ blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks1;
webkit_stream.audioTracks(modified_audio_tracks1);
EXPECT_EQ(0u, modified_audio_tracks1.size());
// Add the WebRtc audio track again.
remote_stream->AddTrack(webrtc_track.get());
- WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_audio_tracks2;
+ blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks2;
webkit_stream.audioTracks(modified_audio_tracks2);
EXPECT_EQ(1u, modified_audio_tracks2.size());
}
@@ -745,12 +742,12 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddVideoTrackFromRemoteStream) {
AddRemoteMockMediaStream(remote_stream_label, "video", "video"));
EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
- testing::Property(&WebKit::WebMediaStream::id,
+ testing::Property(&blink::WebMediaStream::id,
UTF8ToUTF16(remote_stream_label))));
pc_handler_->OnAddStream(remote_stream.get());
- const WebKit::WebMediaStream& webkit_stream = mock_client_->remote_stream();
+ const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
- WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
webkit_stream.videoTracks(video_tracks);
EXPECT_EQ(1u, video_tracks.size());
@@ -758,13 +755,13 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddVideoTrackFromRemoteStream) {
scoped_refptr<webrtc::VideoTrackInterface> webrtc_track =
remote_stream->GetVideoTracks()[0].get();
remote_stream->RemoveTrack(webrtc_track.get());
- WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_video_tracks1;
+ blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks1;
webkit_stream.videoTracks(modified_video_tracks1);
EXPECT_EQ(0u, modified_video_tracks1.size());
// Add the WebRtc video track again.
remote_stream->AddTrack(webrtc_track.get());
- WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_video_tracks2;
+ blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks2;
webkit_stream.videoTracks(modified_video_tracks2);
EXPECT_EQ(1u, modified_video_tracks2.size());
}
@@ -793,24 +790,24 @@ TEST_F(RTCPeerConnectionHandlerTest, OnRenegotiationNeeded) {
}
TEST_F(RTCPeerConnectionHandlerTest, CreateDataChannel) {
- WebKit::WebString label = "d1";
+ blink::WebString label = "d1";
EXPECT_CALL(*mock_tracker_.get(),
TrackCreateDataChannel(pc_handler_.get(),
testing::NotNull(),
PeerConnectionTracker::SOURCE_LOCAL));
- scoped_ptr<WebKit::WebRTCDataChannelHandler> channel(
- pc_handler_->createDataChannel("d1", WebKit::WebRTCDataChannelInit()));
+ scoped_ptr<blink::WebRTCDataChannelHandler> channel(
+ pc_handler_->createDataChannel("d1", blink::WebRTCDataChannelInit()));
EXPECT_TRUE(channel.get() != NULL);
EXPECT_EQ(label, channel->label());
}
TEST_F(RTCPeerConnectionHandlerTest, CreateDtmfSender) {
std::string stream_label = "local_stream";
- WebKit::WebMediaStream local_stream(CreateLocalMediaStream(stream_label));
- WebKit::WebMediaConstraints constraints;
+ blink::WebMediaStream local_stream(CreateLocalMediaStream(stream_label));
+ blink::WebMediaConstraints constraints;
pc_handler_->addStream(local_stream, constraints);
- WebKit::WebVector<WebKit::WebMediaStreamTrack> tracks;
+ blink::WebVector<blink::WebMediaStreamTrack> tracks;
local_stream.videoTracks(tracks);
ASSERT_LE(1ul, tracks.size());
@@ -823,7 +820,7 @@ TEST_F(RTCPeerConnectionHandlerTest, CreateDtmfSender) {
TrackCreateDTMFSender(pc_handler_.get(),
testing::Ref(tracks[0])));
- scoped_ptr<WebKit::WebRTCDTMFSenderHandler> sender(
+ scoped_ptr<blink::WebRTCDTMFSenderHandler> sender(
pc_handler_->createDTMFSender(tracks[0]));
EXPECT_TRUE(sender.get());
}
diff --git a/chromium/content/renderer/media/rtc_video_capture_delegate.cc b/chromium/content/renderer/media/rtc_video_capture_delegate.cc
index 8b038d5c75c..4cc2b59193a 100644
--- a/chromium/content/renderer/media/rtc_video_capture_delegate.cc
+++ b/chromium/content/renderer/media/rtc_video_capture_delegate.cc
@@ -5,6 +5,7 @@
#include "content/renderer/media/rtc_video_capture_delegate.h"
#include "base/bind.h"
+#include "media/base/video_frame.h"
namespace content {
@@ -26,7 +27,7 @@ RtcVideoCaptureDelegate::~RtcVideoCaptureDelegate() {
}
void RtcVideoCaptureDelegate::StartCapture(
- const media::VideoCaptureCapability& capability,
+ const media::VideoCaptureParams& params,
const FrameCapturedCallback& captured_callback,
const StateChangeCallback& state_callback) {
DVLOG(3) << " RtcVideoCaptureDelegate::StartCapture ";
@@ -39,7 +40,7 @@ void RtcVideoCaptureDelegate::StartCapture(
// Increase the reference count to ensure we are not deleted until
// The we are unregistered in RtcVideoCaptureDelegate::OnRemoved.
AddRef();
- capture_engine_->StartCapture(this, capability);
+ capture_engine_->StartCapture(this, params);
}
void RtcVideoCaptureDelegate::StopCapture() {
@@ -92,16 +93,6 @@ void RtcVideoCaptureDelegate::OnFrameReady(
frame));
}
-void RtcVideoCaptureDelegate::OnDeviceInfoReceived(
- media::VideoCapture* capture,
- const media::VideoCaptureParams& device_info) {
-}
-
-void RtcVideoCaptureDelegate::OnDeviceInfoChanged(
- media::VideoCapture* capture,
- const media::VideoCaptureParams& device_info) {
-}
-
void RtcVideoCaptureDelegate::OnFrameReadyOnCaptureThread(
media::VideoCapture* capture,
const scoped_refptr<media::VideoFrame>& frame) {
diff --git a/chromium/content/renderer/media/rtc_video_capture_delegate.h b/chromium/content/renderer/media/rtc_video_capture_delegate.h
index 415b346c838..f081c3731b0 100644
--- a/chromium/content/renderer/media/rtc_video_capture_delegate.h
+++ b/chromium/content/renderer/media/rtc_video_capture_delegate.h
@@ -36,7 +36,7 @@ class RtcVideoCaptureDelegate
RtcVideoCaptureDelegate(const media::VideoCaptureSessionId id,
VideoCaptureImplManager* vc_manager);
- void StartCapture(const media::VideoCaptureCapability& capability,
+ void StartCapture(const media::VideoCaptureParams& params,
const FrameCapturedCallback& captured_callback,
const StateChangeCallback& state_callback);
void StopCapture();
@@ -51,12 +51,6 @@ class RtcVideoCaptureDelegate
virtual void OnFrameReady(
media::VideoCapture* capture,
const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
- virtual void OnDeviceInfoReceived(
- media::VideoCapture* capture,
- const media::VideoCaptureParams& device_info) OVERRIDE;
- virtual void OnDeviceInfoChanged(
- media::VideoCapture* capture,
- const media::VideoCaptureParams& device_info) OVERRIDE;
private:
friend class base::RefCountedThreadSafe<RtcVideoCaptureDelegate>;
diff --git a/chromium/content/renderer/media/rtc_video_capturer.cc b/chromium/content/renderer/media/rtc_video_capturer.cc
index fec4d091e87..0a7a82cf588 100644
--- a/chromium/content/renderer/media/rtc_video_capturer.cc
+++ b/chromium/content/renderer/media/rtc_video_capturer.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/debug/trace_event.h"
+#include "media/base/video_frame.h"
namespace content {
@@ -29,24 +30,24 @@ cricket::CaptureState RtcVideoCapturer::Start(
return cricket::CS_FAILED;
}
- media::VideoCaptureCapability cap;
- cap.width = capture_format.width;
- cap.height = capture_format.height;
- cap.frame_rate = capture_format.framerate();
- cap.color = media::PIXEL_FORMAT_I420;
+ media::VideoCaptureParams request;
+ request.requested_format = media::VideoCaptureFormat(
+ gfx::Size(capture_format.width, capture_format.height),
+ capture_format.framerate(),
+ media::PIXEL_FORMAT_I420);
SetCaptureFormat(&capture_format);
state_ = VIDEO_CAPTURE_STATE_STARTED;
first_frame_timestamp_ = media::kNoTimestamp();
delegate_->StartCapture(
- cap,
+ request,
base::Bind(&RtcVideoCapturer::OnFrameCaptured, base::Unretained(this)),
base::Bind(&RtcVideoCapturer::OnStateChange, base::Unretained(this)));
// Update the desired aspect ratio so that later the video frame can be
// cropped to meet the requirement if the camera returns a different
- // resolution than the |cap|.
- UpdateAspectRatio(cap.width, cap.height);
+ // resolution than the |request|.
+ UpdateAspectRatio(capture_format.width, capture_format.height);
return cricket::CS_STARTING;
}
diff --git a/chromium/content/renderer/media/rtc_video_decoder.cc b/chromium/content/renderer/media/rtc_video_decoder.cc
index 70f8add2d00..1c8d6008bca 100644
--- a/chromium/content/renderer/media/rtc_video_decoder.cc
+++ b/chromium/content/renderer/media/rtc_video_decoder.cc
@@ -73,9 +73,7 @@ RTCVideoDecoder::BufferData::~BufferData() {}
RTCVideoDecoder::RTCVideoDecoder(
const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories)
- : weak_factory_(this),
- weak_this_(weak_factory_.GetWeakPtr()),
- factories_(factories),
+ : factories_(factories),
vda_loop_proxy_(factories->GetMessageLoop()),
decoder_texture_target_(0),
next_picture_buffer_id_(0),
@@ -83,8 +81,12 @@ RTCVideoDecoder::RTCVideoDecoder(
decode_complete_callback_(NULL),
num_shm_buffers_(0),
next_bitstream_buffer_id_(0),
- reset_bitstream_buffer_id_(ID_INVALID) {
+ reset_bitstream_buffer_id_(ID_INVALID),
+ weak_factory_(this) {
DCHECK(!vda_loop_proxy_->BelongsToCurrentThread());
+
+ weak_this_ = weak_factory_.GetWeakPtr();
+
base::WaitableEvent message_loop_async_waiter(false, false);
// Waiting here is safe. The media thread is stopped in the child thread and
// the child thread is blocked when VideoDecoderFactory::CreateVideoDecoder
@@ -184,24 +186,44 @@ int32_t RTCVideoDecoder::Decode(
DVLOG(3) << "Decode";
base::AutoLock auto_lock(lock_);
+
if (state_ == UNINITIALIZED || decode_complete_callback_ == NULL) {
LOG(ERROR) << "The decoder has not initialized.";
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
}
+
if (state_ == DECODE_ERROR) {
LOG(ERROR) << "Decoding error occurred.";
return WEBRTC_VIDEO_CODEC_ERROR;
}
+
if (missingFrames || !inputImage._completeFrame) {
DLOG(ERROR) << "Missing or incomplete frames.";
// Unlike the SW decoder in libvpx, hw decoder cannot handle broken frames.
// Return an error to request a key frame.
return WEBRTC_VIDEO_CODEC_ERROR;
}
+
+ // Most platforms' VDA implementations support mid-stream resolution change
+ // internally. Platforms whose VDAs fail to support mid-stream resolution
+ // change gracefully need to have their clients cover for them, and we do that
+ // here.
+#ifdef ANDROID
+ const bool kVDACanHandleMidstreamResize = false;
+#else
+ const bool kVDACanHandleMidstreamResize = true;
+#endif
+
+ bool need_to_reset_for_midstream_resize = false;
if (inputImage._frameType == webrtc::kKeyFrame) {
DVLOG(2) << "Got key frame. size=" << inputImage._encodedWidth << "x"
<< inputImage._encodedHeight;
+ gfx::Size prev_frame_size = frame_size_;
frame_size_.SetSize(inputImage._encodedWidth, inputImage._encodedHeight);
+ if (!kVDACanHandleMidstreamResize && !prev_frame_size.IsEmpty() &&
+ prev_frame_size != frame_size_) {
+ need_to_reset_for_midstream_resize = true;
+ }
} else if (IsFirstBufferAfterReset(next_bitstream_buffer_id_,
reset_bitstream_buffer_id_)) {
// TODO(wuchengli): VDA should handle it. Remove this when
@@ -219,15 +241,20 @@ int32_t RTCVideoDecoder::Decode(
// Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & ID_LAST;
- // If the shared memory is available and there are no pending buffers, send
- // the buffer for decode. If not, save the buffer in the queue for decode
- // later.
+ // If a shared memory segment is available, there are no pending buffers, and
+ // this isn't a mid-stream resolution change, then send the buffer for decode
+ // immediately. Otherwise, save the buffer in the queue for later decode.
scoped_ptr<SHMBuffer> shm_buffer;
- if (pending_buffers_.size() == 0)
+ if (!need_to_reset_for_midstream_resize && pending_buffers_.size() == 0)
shm_buffer = GetSHM_Locked(inputImage._length);
if (!shm_buffer) {
- int32_t result = SaveToPendingBuffers_Locked(inputImage, buffer_data);
- return result ? WEBRTC_VIDEO_CODEC_OK : WEBRTC_VIDEO_CODEC_ERROR;
+ if (!SaveToPendingBuffers_Locked(inputImage, buffer_data))
+ return WEBRTC_VIDEO_CODEC_ERROR;
+ if (need_to_reset_for_midstream_resize) {
+ base::AutoUnlock auto_unlock(lock_);
+ Reset();
+ }
+ return WEBRTC_VIDEO_CODEC_OK;
}
SaveToDecodeBuffers_Locked(inputImage, shm_buffer.Pass(), buffer_data);
@@ -394,13 +421,13 @@ scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame(
base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue(
base::checked_numeric_cast<uint64_t>(timestamp) * 1000 / 90);
return media::VideoFrame::WrapNativeTexture(
- new media::VideoFrame::MailboxHolder(
+ make_scoped_ptr(new media::VideoFrame::MailboxHolder(
pb.texture_mailbox(),
0, // sync_point
media::BindToCurrentLoop(
base::Bind(&RTCVideoDecoder::ReusePictureBuffer,
weak_this_,
- picture.picture_buffer_id()))),
+ picture.picture_buffer_id())))),
decoder_texture_target_,
pb.size(),
visible_rect,
@@ -409,7 +436,6 @@ scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame(
base::Bind(&media::GpuVideoAcceleratorFactories::ReadPixels,
factories_,
pb.texture_id(),
- decoder_texture_target_,
natural_size),
base::Closure());
}
@@ -755,7 +781,7 @@ int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) {
// Logging boolean is enough to know if HW decoding has been used. Also,
// InitDecode is less likely to return an error so enum is not used here.
bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false;
- UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeStatus", sample);
+ UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample);
return status;
}
diff --git a/chromium/content/renderer/media/rtc_video_decoder.h b/chromium/content/renderer/media/rtc_video_decoder.h
index d73fc143d1b..b0f967ab546 100644
--- a/chromium/content/renderer/media/rtc_video_decoder.h
+++ b/chromium/content/renderer/media/rtc_video_decoder.h
@@ -201,8 +201,7 @@ class CONTENT_EXPORT RTCVideoDecoder
// The size of the incoming video frames.
gfx::Size frame_size_;
- // The weak pointer should live and die on the |vda_loop_proxy_|;
- base::WeakPtrFactory<RTCVideoDecoder> weak_factory_;
+ // Weak pointer to this, which can be dereferenced only on |vda_loop_proxy_|.
base::WeakPtr<RTCVideoDecoder> weak_this_;
scoped_refptr<media::GpuVideoAcceleratorFactories> factories_;
@@ -269,6 +268,10 @@ class CONTENT_EXPORT RTCVideoDecoder
// Release has been called. Guarded by |lock_|.
int32 reset_bitstream_buffer_id_;
+ // Factory used to populate |weak_this_|. Must be destroyed, or invalidated,
+ // on |vda_loop_proxy_|.
+ base::WeakPtrFactory<RTCVideoDecoder> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoder);
};
diff --git a/chromium/content/renderer/media/rtc_video_decoder_factory_tv.cc b/chromium/content/renderer/media/rtc_video_decoder_factory_tv.cc
index 58db5c383fe..64c14adf313 100644
--- a/chromium/content/renderer/media/rtc_video_decoder_factory_tv.cc
+++ b/chromium/content/renderer/media/rtc_video_decoder_factory_tv.cc
@@ -193,14 +193,29 @@ void RTCVideoDecoderFactoryTv::ReleaseDemuxer() {
}
}
-void RTCVideoDecoderFactoryTv::Initialize(media::DemuxerHost*,
- const media::PipelineStatusCB& cb) {
+void RTCVideoDecoderFactoryTv::Initialize(media::DemuxerHost* /*host*/,
+ const media::PipelineStatusCB& cb,
+ bool /*enable_text_tracks*/) {
base::AutoLock lock(lock_);
init_cb_ = media::BindToLoop(base::MessageLoopProxy::current(), cb);
if (stream_)
base::ResetAndReturn(&init_cb_).Run(media::PIPELINE_OK);
}
+void RTCVideoDecoderFactoryTv::Seek(base::TimeDelta time,
+ const media::PipelineStatusCB& status_cb) {
+ DCHECK(!status_cb.is_null());
+ status_cb.Run(media::PIPELINE_OK);
+}
+
+void RTCVideoDecoderFactoryTv::Stop(const base::Closure& callback) {
+ DCHECK(!callback.is_null());
+ callback.Run();
+}
+
+void RTCVideoDecoderFactoryTv::OnAudioRendererDisabled() {
+}
+
DemuxerStream* RTCVideoDecoderFactoryTv::GetStream(DemuxerStream::Type type) {
base::AutoLock lock(lock_);
if (type == DemuxerStream::VIDEO)
diff --git a/chromium/content/renderer/media/rtc_video_decoder_factory_tv.h b/chromium/content/renderer/media/rtc_video_decoder_factory_tv.h
index 0d5380bc65a..cd51cdcf862 100644
--- a/chromium/content/renderer/media/rtc_video_decoder_factory_tv.h
+++ b/chromium/content/renderer/media/rtc_video_decoder_factory_tv.h
@@ -47,7 +47,12 @@ class CONTENT_EXPORT RTCVideoDecoderFactoryTv
// media::Demuxer implementation.
virtual void Initialize(media::DemuxerHost* host,
- const media::PipelineStatusCB& cb) OVERRIDE;
+ const media::PipelineStatusCB& cb,
+ bool enable_text_tracks) OVERRIDE;
+ virtual void Seek(base::TimeDelta time,
+ const media::PipelineStatusCB& status_cb) OVERRIDE;
+ virtual void Stop(const base::Closure& callback) OVERRIDE;
+ virtual void OnAudioRendererDisabled() OVERRIDE;
virtual media::DemuxerStream* GetStream(
media::DemuxerStream::Type type) OVERRIDE;
virtual base::TimeDelta GetStartTime() const OVERRIDE;
diff --git a/chromium/content/renderer/media/rtc_video_encoder.cc b/chromium/content/renderer/media/rtc_video_encoder.cc
index 1ab56c930be..4b54db2342d 100644
--- a/chromium/content/renderer/media/rtc_video_encoder.cc
+++ b/chromium/content/renderer/media/rtc_video_encoder.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/metrics/histogram.h"
#include "base/synchronization/waitable_event.h"
#include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
#include "media/base/bitstream_buffer.h"
@@ -395,7 +396,7 @@ void RTCVideoEncoder::Impl::EncodeOneFrame() {
const int index = input_buffers_free_.back();
base::SharedMemory* input_buffer = input_buffers_[index];
scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapExternalSharedMemory(
+ media::VideoFrame::WrapExternalPackedMemory(
media::VideoFrame::I420,
input_frame_coded_size_,
gfx::Rect(input_visible_size_),
@@ -474,9 +475,9 @@ RTCVideoEncoder::RTCVideoEncoder(
: video_codec_type_(type),
video_codec_profile_(profile),
gpu_factories_(gpu_factories),
- weak_this_factory_(this),
encoded_image_callback_(NULL),
- impl_status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED) {
+ impl_status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED),
+ weak_this_factory_(this) {
DVLOG(1) << "RTCVideoEncoder(): profile=" << profile;
}
@@ -512,6 +513,7 @@ int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
// webrtc::VideoEncoder expects this call to be synchronous.
initialization_waiter.Wait();
+ RecordInitEncodeUMA(initialization_retval);
return initialization_retval;
}
@@ -612,6 +614,11 @@ void RTCVideoEncoder::ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image,
webrtc::CodecSpecificInfo info;
memset(&info, 0, sizeof(info));
info.codecType = video_codec_type_;
+ if (video_codec_type_ == webrtc::kVideoCodecVP8) {
+ info.codecSpecific.VP8.pictureId = -1;
+ info.codecSpecific.VP8.tl0PicIdx = -1;
+ info.codecSpecific.VP8.keyIdx = -1;
+ }
// Generate a header describing a single fragment.
webrtc::RTPFragmentationHeader header;
@@ -647,4 +654,14 @@ void RTCVideoEncoder::NotifyError(int32_t error) {
impl_ = NULL;
}
+void RTCVideoEncoder::RecordInitEncodeUMA(int32_t init_retval) {
+ UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess",
+ init_retval == WEBRTC_VIDEO_CODEC_OK);
+ if (init_retval == WEBRTC_VIDEO_CODEC_OK) {
+ UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile",
+ video_codec_profile_,
+ media::VIDEO_CODEC_PROFILE_MAX);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/rtc_video_encoder.h b/chromium/content/renderer/media/rtc_video_encoder.h
index 3c15a55ce73..4e36ece1c1d 100644
--- a/chromium/content/renderer/media/rtc_video_encoder.h
+++ b/chromium/content/renderer/media/rtc_video_encoder.h
@@ -69,6 +69,8 @@ class CONTENT_EXPORT RTCVideoEncoder
void NotifyError(int32_t error);
+ void RecordInitEncodeUMA(int32_t init_retval);
+
base::ThreadChecker thread_checker_;
// The video codec type, as reported to WebRTC.
@@ -80,10 +82,6 @@ class CONTENT_EXPORT RTCVideoEncoder
// Factory for creating VEAs, shared memory buffers, etc.
scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories_;
- // Weak pointer factory for posting back VEA::Client notifications to
- // RTCVideoEncoder.
- base::WeakPtrFactory<RTCVideoEncoder> weak_this_factory_;
-
// webrtc::VideoEncoder encode complete callback.
webrtc::EncodedImageCallback* encoded_image_callback_;
@@ -96,6 +94,10 @@ class CONTENT_EXPORT RTCVideoEncoder
// interface entry point is called.
int32_t impl_status_;
+ // Weak pointer factory for posting back VEA::Client notifications to
+ // RTCVideoEncoder.
+ base::WeakPtrFactory<RTCVideoEncoder> weak_this_factory_;
+
DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoder);
};
diff --git a/chromium/content/renderer/media/rtc_video_renderer.cc b/chromium/content/renderer/media/rtc_video_renderer.cc
index f64ed02fed2..013fcad8dfb 100644
--- a/chromium/content/renderer/media/rtc_video_renderer.cc
+++ b/chromium/content/renderer/media/rtc_video_renderer.cc
@@ -4,30 +4,22 @@
#include "content/renderer/media/rtc_video_renderer.h"
-#include "base/bind.h"
#include "base/debug/trace_event.h"
-#include "base/location.h"
-#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "content/renderer/media/native_handle_impl.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
-#include "third_party/libjingle/source/talk/media/base/videoframe.h"
-
-using media::CopyYPlane;
-using media::CopyUPlane;
-using media::CopyVPlane;
namespace content {
RTCVideoRenderer::RTCVideoRenderer(
- webrtc::VideoTrackInterface* video_track,
+ const blink::WebMediaStreamTrack& video_track,
const base::Closure& error_cb,
const RepaintCB& repaint_cb)
: error_cb_(error_cb),
repaint_cb_(repaint_cb),
message_loop_proxy_(base::MessageLoopProxy::current()),
- state_(kStopped),
+ state_(STOPPED),
+ first_frame_rendered_(false),
video_track_(video_track) {
}
@@ -36,113 +28,82 @@ RTCVideoRenderer::~RTCVideoRenderer() {
void RTCVideoRenderer::Start() {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
- DCHECK_EQ(state_, kStopped);
+ DCHECK_EQ(state_, STOPPED);
+ DCHECK(!first_frame_rendered_);
+
+ AddToVideoTrack(this, video_track_);
+ state_ = STARTED;
- if (video_track_.get()) {
- video_track_->AddRenderer(this);
- video_track_->RegisterObserver(this);
+ if (video_track_.source().readyState() ==
+ blink::WebMediaStreamSource::ReadyStateEnded ||
+ !video_track_.isEnabled()) {
+ MaybeRenderSignalingFrame();
}
- state_ = kStarted;
- MaybeRenderSignalingFrame();
}
void RTCVideoRenderer::Stop() {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
- if (video_track_.get()) {
- state_ = kStopped;
- video_track_->RemoveRenderer(this);
- video_track_->UnregisterObserver(this);
- video_track_ = NULL;
- }
+ DCHECK(state_ == STARTED || state_ == PAUSED);
+ RemoveFromVideoTrack(this, video_track_);
+ state_ = STOPPED;
+ first_frame_rendered_ = false;
}
void RTCVideoRenderer::Play() {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
- if (video_track_.get() && state_ == kPaused) {
- state_ = kStarted;
+ if (state_ == PAUSED) {
+ state_ = STARTED;
}
}
void RTCVideoRenderer::Pause() {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
- if (video_track_.get() && state_ == kStarted) {
- state_ = kPaused;
+ if (state_ == STARTED) {
+ state_ = PAUSED;
}
}
-void RTCVideoRenderer::SetSize(int width, int height) {
+void RTCVideoRenderer::OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ if (state == blink::WebMediaStreamSource::ReadyStateEnded)
+ MaybeRenderSignalingFrame();
}
-void RTCVideoRenderer::RenderFrame(const cricket::VideoFrame* frame) {
- base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds(
- frame->GetTimeStamp() / talk_base::kNumNanosecsPerMillisec);
-
- TRACE_EVENT_INSTANT2("rtc_video_renderer",
- "RenderFrame",
- TRACE_EVENT_SCOPE_THREAD,
- "elapsed time",
- frame->GetElapsedTime(),
- "timestamp_ms",
- timestamp.InMilliseconds());
-
- scoped_refptr<media::VideoFrame> video_frame;
- if (frame->GetNativeHandle() != NULL) {
- NativeHandleImpl* handle =
- static_cast<NativeHandleImpl*>(frame->GetNativeHandle());
- video_frame = static_cast<media::VideoFrame*>(handle->GetHandle());
- video_frame->SetTimestamp(timestamp);
- } else {
- gfx::Size size(frame->GetWidth(), frame->GetHeight());
- video_frame = media::VideoFrame::CreateFrame(
- media::VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
-
- // Aspect ratio unsupported; DCHECK when there are non-square pixels.
- DCHECK_EQ(frame->GetPixelWidth(), 1u);
- DCHECK_EQ(frame->GetPixelHeight(), 1u);
-
- int y_rows = frame->GetHeight();
- int uv_rows = frame->GetHeight() / 2; // YV12 format.
- CopyYPlane(
- frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame.get());
- CopyUPlane(
- frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame.get());
- CopyVPlane(
- frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame.get());
- }
-
- message_loop_proxy_->PostTask(
- FROM_HERE, base::Bind(&RTCVideoRenderer::DoRenderFrameOnMainThread,
- this, video_frame));
+void RTCVideoRenderer::OnEnabledChanged(bool enabled) {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ if (!enabled)
+ MaybeRenderSignalingFrame();
}
-void RTCVideoRenderer::OnChanged() {
+void RTCVideoRenderer::OnVideoFrame(
+ const scoped_refptr<media::VideoFrame>& frame) {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
- MaybeRenderSignalingFrame();
+ if (state_ != STARTED) {
+ return;
+ }
+
+ TRACE_EVENT_INSTANT1("rtc_video_renderer",
+ "OnVideoFrame",
+ TRACE_EVENT_SCOPE_THREAD,
+ "timestamp",
+ frame->GetTimestamp().InMilliseconds());
+ repaint_cb_.Run(frame);
+ first_frame_rendered_ = true;
}
void RTCVideoRenderer::MaybeRenderSignalingFrame() {
- // Render a small black frame if the track transition to ended.
+ // Render a small black frame if no frame has been rendered.
// This is necessary to make sure audio can play if the video tag src is
- // a MediaStream video track that has been rejected or ended.
- if (video_track_->state() == webrtc::MediaStreamTrackInterface::kEnded) {
- const int kMinFrameSize = 2;
- const gfx::Size size(kMinFrameSize, kMinFrameSize);
- scoped_refptr<media::VideoFrame> video_frame =
- media::VideoFrame::CreateBlackFrame(size);
- DoRenderFrameOnMainThread(video_frame);
- }
-}
-
-void RTCVideoRenderer::DoRenderFrameOnMainThread(
- scoped_refptr<media::VideoFrame> video_frame) {
- DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-
- if (state_ != kStarted) {
+ // a MediaStream video track that has been rejected, ended or disabled.
+ if (first_frame_rendered_)
return;
- }
- TRACE_EVENT0("video", "DoRenderFrameOnMainThread");
- repaint_cb_.Run(video_frame);
+ const int kMinFrameSize = 2;
+ const gfx::Size size(kMinFrameSize, kMinFrameSize);
+ scoped_refptr<media::VideoFrame> video_frame =
+ media::VideoFrame::CreateBlackFrame(size);
+ OnVideoFrame(video_frame);
}
} // namespace content
diff --git a/chromium/content/renderer/media/rtc_video_renderer.h b/chromium/content/renderer/media/rtc_video_renderer.h
index d7bb9869dab..b72a5860ee8 100644
--- a/chromium/content/renderer/media/rtc_video_renderer.h
+++ b/chromium/content/renderer/media/rtc_video_renderer.h
@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_RENDERER_MEDIA_LOCAL_VIDEO_RENDERER_H_
-#define CONTENT_RENDERER_MEDIA_LOCAL_VIDEO_RENDERER_H_
+#ifndef CONTENT_RENDERER_MEDIA_RTC_VIDEO_RENDERER_H_
+#define CONTENT_RENDERER_MEDIA_RTC_VIDEO_RENDERER_H_
#include "base/callback.h"
#include "content/common/content_export.h"
+#include "content/public/renderer/media_stream_video_sink.h"
#include "content/renderer/media/video_frame_provider.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "ui/gfx/size.h"
namespace base {
@@ -20,23 +21,20 @@ namespace content {
// RTCVideoRenderer is a VideoFrameProvider designed for rendering
// Video MediaStreamTracks,
// http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediastreamtrack
-// RTCVideoRenderer implements webrtc::VideoRendererInterface in order to render
-// video frames provided from a webrtc::VideoTrackInteface.
-// RTCVideoRenderer register itself to the Video Track when the
+// RTCVideoRenderer implements VideoTrackSink in order to render
+// video frames provided from a VideoTrack.
+// RTCVideoRenderer register itself as a sink to the VideoTrack when the
// VideoFrameProvider is started and deregisters itself when it is stopped.
-// Calls to webrtc::VideoTrackInterface must occur on the main thread.
// TODO(wuchengli): Add unit test. See the link below for reference.
// http://src.chromium.org/viewvc/chrome/trunk/src/content/renderer/media/rtc_vi
// deo_decoder_unittest.cc?revision=180591&view=markup
class CONTENT_EXPORT RTCVideoRenderer
: NON_EXPORTED_BASE(public VideoFrameProvider),
- NON_EXPORTED_BASE(public webrtc::VideoRendererInterface),
- NON_EXPORTED_BASE(public webrtc::ObserverInterface) {
+ NON_EXPORTED_BASE(public MediaStreamVideoSink) {
public:
- RTCVideoRenderer(
- webrtc::VideoTrackInterface* video_track,
- const base::Closure& error_cb,
- const RepaintCB& repaint_cb);
+ RTCVideoRenderer(const blink::WebMediaStreamTrack& video_track,
+ const base::Closure& error_cb,
+ const RepaintCB& repaint_cb);
// VideoFrameProvider implementation. Called on the main thread.
virtual void Start() OVERRIDE;
@@ -44,38 +42,35 @@ class CONTENT_EXPORT RTCVideoRenderer
virtual void Play() OVERRIDE;
virtual void Pause() OVERRIDE;
- // webrtc::VideoRendererInterface implementation. May be called on
- // a different thread.
- virtual void SetSize(int width, int height) OVERRIDE;
- virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE;
-
- // webrtc::ObserverInterface implementation.
- virtual void OnChanged() OVERRIDE;
-
protected:
virtual ~RTCVideoRenderer();
private:
enum State {
- kStarted,
- kPaused,
- kStopped,
+ STARTED,
+ PAUSED,
+ STOPPED,
};
+ // VideoTrackSink implementation. Called on the main thread.
+ virtual void OnVideoFrame(
+ const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
+ virtual void OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
+ virtual void OnEnabledChanged(bool enabled) OVERRIDE;
+
void MaybeRenderSignalingFrame();
- void DoRenderFrameOnMainThread(scoped_refptr<media::VideoFrame> video_frame);
base::Closure error_cb_;
RepaintCB repaint_cb_;
scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
State state_;
-
- // The video track the renderer is connected to.
- scoped_refptr<webrtc::VideoTrackInterface> video_track_;
+ bool first_frame_rendered_;
+ blink::WebMediaStreamTrack video_track_;
DISALLOW_COPY_AND_ASSIGN(RTCVideoRenderer);
};
} // namespace content
-#endif // CONTENT_RENDERER_MEDIA_LOCAL_VIDEO_RENDERER_H_
+#endif // CONTENT_RENDERER_MEDIA_RTC_VIDEO_RENDERER_H_
diff --git a/chromium/content/renderer/media/tagged_list.h b/chromium/content/renderer/media/tagged_list.h
new file mode 100644
index 00000000000..450f9f69e98
--- /dev/null
+++ b/chromium/content/renderer/media/tagged_list.h
@@ -0,0 +1,94 @@
+// 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_MEDIA_TAGGED_LIST_H_
+#define CONTENT_RENDERER_MEDIA_TAGGED_LIST_H_
+
+#include <algorithm>
+#include <list>
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+
+namespace content {
+
+// Implements the pattern of a list of items, where added items are
+// tagged, you can tag all items, and you can retrieve the list of
+// items that are tagged, which removes the tag.
+//
+// For thread safety, operations on this object should be under an
+// external lock. An internally-locked version could be created, but
+// is not needed at the moment as users already lock.
+template <class ItemType>
+class TaggedList {
+ public:
+ typedef std::list<scoped_refptr<ItemType> > ItemList;
+
+ TaggedList() {}
+
+ void AddAndTag(ItemType* item) {
+ items_.push_back(item);
+ tagged_items_.push_back(item);
+ }
+
+ void TagAll() {
+ tagged_items_ = items_;
+ }
+
+ const ItemList& Items() const {
+ return items_;
+ }
+
+ // Retrieves the list of items with tags, and removes their tags.
+ //
+ // |dest| should be empty.
+ void RetrieveAndClearTags(ItemList* dest) {
+ DCHECK(dest->empty());
+ dest->swap(tagged_items_);
+ }
+
+ // Remove an item that matches a predicate. Will return a reference
+ // to it if it is found.
+ template <class UnaryPredicate>
+ scoped_refptr<ItemType> Remove(UnaryPredicate predicate) {
+ tagged_items_.remove_if(predicate);
+
+ typename ItemList::iterator it = std::find_if(
+ items_.begin(), items_.end(), predicate);
+ if (it != items_.end()) {
+ scoped_refptr<ItemType> removed_item = *it;
+ items_.erase(it);
+ return removed_item;
+ }
+
+ return NULL;
+ }
+
+ template <class UnaryPredicate>
+ bool Contains(UnaryPredicate predicate) const {
+ return std::find_if(items_.begin(), items_.end(), predicate) !=
+ items_.end();
+ }
+
+ void Clear() {
+ items_.clear();
+ tagged_items_.clear();
+ }
+
+ bool IsEmpty() const {
+ bool is_empty = items_.empty();
+ DCHECK(!is_empty || tagged_items_.empty());
+ return is_empty;
+ }
+
+ private:
+ ItemList items_;
+ ItemList tagged_items_;
+
+ DISALLOW_COPY_AND_ASSIGN(TaggedList);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_TAGGED_LIST_H_
diff --git a/chromium/content/renderer/media/test_response_generator.cc b/chromium/content/renderer/media/test_response_generator.cc
index 1ced1313db6..64f82e78f50 100644
--- a/chromium/content/renderer/media/test_response_generator.cc
+++ b/chromium/content/renderer/media/test_response_generator.cc
@@ -11,9 +11,9 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
-using WebKit::WebString;
-using WebKit::WebURLError;
-using WebKit::WebURLResponse;
+using blink::WebString;
+using blink::WebURLError;
+using blink::WebURLResponse;
namespace content {
diff --git a/chromium/content/renderer/media/test_response_generator.h b/chromium/content/renderer/media/test_response_generator.h
index d8f1d5e1322..dcbcc0544e4 100644
--- a/chromium/content/renderer/media/test_response_generator.h
+++ b/chromium/content/renderer/media/test_response_generator.h
@@ -28,29 +28,29 @@ class TestResponseGenerator {
TestResponseGenerator(const GURL& gurl, int64 content_length);
// Generates a WebURLError object.
- WebKit::WebURLError GenerateError();
+ blink::WebURLError GenerateError();
// Generates a regular HTTP 200 response.
- WebKit::WebURLResponse Generate200();
+ blink::WebURLResponse Generate200();
// Generates a regular HTTP 206 response starting from |first_byte_offset|
// until the end of the resource.
- WebKit::WebURLResponse Generate206(int64 first_byte_offset);
+ blink::WebURLResponse Generate206(int64 first_byte_offset);
// Generates a custom HTTP 206 response starting from |first_byte_offset|
// until the end of the resource. You can tweak what gets included in the
// headers via |flags|.
- WebKit::WebURLResponse Generate206(int64 first_byte_offset, Flags flags);
+ blink::WebURLResponse Generate206(int64 first_byte_offset, Flags flags);
// Generates a regular HTTP 404 response.
- WebKit::WebURLResponse Generate404();
+ blink::WebURLResponse Generate404();
// Generates a file:// response starting from |first_byte_offset| until the
// end of the resource.
//
// If |first_byte_offset| is negative a response containing no content length
// will be returned.
- WebKit::WebURLResponse GenerateFileResponse(int64 first_byte_offset);
+ blink::WebURLResponse GenerateFileResponse(int64 first_byte_offset);
int64 content_length() { return content_length_; }
diff --git a/chromium/content/renderer/media/texttrack_impl.cc b/chromium/content/renderer/media/texttrack_impl.cc
index 7acf39a1a48..3df473b593a 100644
--- a/chromium/content/renderer/media/texttrack_impl.cc
+++ b/chromium/content/renderer/media/texttrack_impl.cc
@@ -4,21 +4,32 @@
#include "content/renderer/media/texttrack_impl.h"
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop_proxy.h"
#include "content/renderer/media/webinbandtexttrack_impl.h"
-#include "third_party/WebKit/public/web/WebInbandTextTrackClient.h"
-#include "third_party/WebKit/public/web/WebMediaPlayerClient.h"
+#include "media/base/bind_to_loop.h"
+#include "third_party/WebKit/public/platform/WebInbandTextTrackClient.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
namespace content {
-TextTrackImpl::TextTrackImpl(WebKit::WebMediaPlayerClient* client,
- WebInbandTextTrackImpl* text_track)
- : client_(client), text_track_(text_track) {
+TextTrackImpl::TextTrackImpl(
+ const scoped_refptr<base::MessageLoopProxy>& message_loop,
+ blink::WebMediaPlayerClient* client,
+ scoped_ptr<WebInbandTextTrackImpl> text_track)
+ : message_loop_(message_loop),
+ client_(client),
+ text_track_(text_track.Pass()) {
client_->addTextTrack(text_track_.get());
}
TextTrackImpl::~TextTrackImpl() {
- if (text_track_->client())
- client_->removeTextTrack(text_track_.get());
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&TextTrackImpl::OnRemoveTrack,
+ client_,
+ base::Passed(&text_track_)));
}
void TextTrackImpl::addWebVTTCue(const base::TimeDelta& start,
@@ -26,12 +37,34 @@ void TextTrackImpl::addWebVTTCue(const base::TimeDelta& start,
const std::string& id,
const std::string& content,
const std::string& settings) {
- if (WebKit::WebInbandTextTrackClient* client = text_track_->client())
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&TextTrackImpl::OnAddCue,
+ text_track_.get(),
+ start, end,
+ id, content, settings));
+}
+
+void TextTrackImpl::OnAddCue(WebInbandTextTrackImpl* text_track,
+ const base::TimeDelta& start,
+ const base::TimeDelta& end,
+ const std::string& id,
+ const std::string& content,
+ const std::string& settings) {
+ if (blink::WebInbandTextTrackClient* client = text_track->client()) {
client->addWebVTTCue(start.InSecondsF(),
end.InSecondsF(),
- WebKit::WebString::fromUTF8(id),
- WebKit::WebString::fromUTF8(content),
- WebKit::WebString::fromUTF8(settings));
+ blink::WebString::fromUTF8(id),
+ blink::WebString::fromUTF8(content),
+ blink::WebString::fromUTF8(settings));
+ }
+}
+
+void TextTrackImpl::OnRemoveTrack(
+ blink::WebMediaPlayerClient* client,
+ scoped_ptr<WebInbandTextTrackImpl> text_track) {
+ if (text_track->client())
+ client->removeTextTrack(text_track.get());
}
} // namespace content
diff --git a/chromium/content/renderer/media/texttrack_impl.h b/chromium/content/renderer/media/texttrack_impl.h
index 09007c6b17a..3285b60ed10 100644
--- a/chromium/content/renderer/media/texttrack_impl.h
+++ b/chromium/content/renderer/media/texttrack_impl.h
@@ -11,7 +11,12 @@
#include "base/memory/scoped_ptr.h"
#include "media/base/text_track.h"
-namespace WebKit {
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace blink {
+class WebInbandTextTrackClient;
class WebMediaPlayerClient;
}
@@ -22,8 +27,9 @@ class WebInbandTextTrackImpl;
class TextTrackImpl : public media::TextTrack {
public:
// Constructor assumes ownership of the |text_track| object.
- TextTrackImpl(WebKit::WebMediaPlayerClient* client,
- WebInbandTextTrackImpl* text_track);
+ TextTrackImpl(const scoped_refptr<base::MessageLoopProxy>& message_loop,
+ blink::WebMediaPlayerClient* client,
+ scoped_ptr<WebInbandTextTrackImpl> text_track);
virtual ~TextTrackImpl();
@@ -34,7 +40,18 @@ class TextTrackImpl : public media::TextTrack {
const std::string& settings) OVERRIDE;
private:
- WebKit::WebMediaPlayerClient* client_;
+ static void OnAddCue(WebInbandTextTrackImpl* text_track,
+ const base::TimeDelta& start,
+ const base::TimeDelta& end,
+ const std::string& id,
+ const std::string& content,
+ const std::string& settings);
+
+ static void OnRemoveTrack(blink::WebMediaPlayerClient* client,
+ scoped_ptr<WebInbandTextTrackImpl> text_track);
+
+ scoped_refptr<base::MessageLoopProxy> message_loop_;
+ blink::WebMediaPlayerClient* client_;
scoped_ptr<WebInbandTextTrackImpl> text_track_;
DISALLOW_COPY_AND_ASSIGN(TextTrackImpl);
};
diff --git a/chromium/content/renderer/media/video_capture_impl.cc b/chromium/content/renderer/media/video_capture_impl.cc
index 0fe2789b17f..30b43ddfcf4 100644
--- a/chromium/content/renderer/media/video_capture_impl.cc
+++ b/chromium/content/renderer/media/video_capture_impl.cc
@@ -10,6 +10,7 @@
#include "content/common/media/video_capture_messages.h"
#include "media/base/bind_to_loop.h"
#include "media/base/limits.h"
+#include "media/base/video_frame.h"
namespace content {
@@ -17,20 +18,11 @@ class VideoCaptureImpl::ClientBuffer
: public base::RefCountedThreadSafe<ClientBuffer> {
public:
ClientBuffer(scoped_ptr<base::SharedMemory> buffer,
- size_t buffer_size,
- int frame_width,
- int frame_height,
- int frame_stride)
+ size_t buffer_size)
: buffer(buffer.Pass()),
- buffer_size(buffer_size),
- frame_width(frame_width),
- frame_height(frame_height),
- frame_stride(frame_stride) {}
+ buffer_size(buffer_size) {}
const scoped_ptr<base::SharedMemory> buffer;
const size_t buffer_size;
- const int frame_width; // In pixels.
- const int frame_height; // In pixels.
- const int frame_stride; // In pixels.
private:
friend class base::RefCountedThreadSafe<ClientBuffer>;
@@ -44,20 +36,12 @@ bool VideoCaptureImpl::CaptureStarted() {
return state_ == VIDEO_CAPTURE_STATE_STARTED;
}
-int VideoCaptureImpl::CaptureWidth() {
- return capture_format_.width;
-}
-
-int VideoCaptureImpl::CaptureHeight() {
- return capture_format_.height;
-}
-
int VideoCaptureImpl::CaptureFrameRate() {
- return capture_format_.frame_rate;
+ return last_frame_format_.frame_rate;
}
VideoCaptureImpl::VideoCaptureImpl(
- const media::VideoCaptureSessionId id,
+ const media::VideoCaptureSessionId session_id,
base::MessageLoopProxy* capture_message_loop_proxy,
VideoCaptureMessageFilter* filter)
: VideoCapture(),
@@ -65,13 +49,11 @@ VideoCaptureImpl::VideoCaptureImpl(
capture_message_loop_proxy_(capture_message_loop_proxy),
io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()),
device_id_(0),
- client_buffer_weak_this_factory_(this),
- video_type_(media::PIXEL_FORMAT_I420),
- device_info_available_(false),
+ session_id_(session_id),
suspended_(false),
- state_(VIDEO_CAPTURE_STATE_STOPPED) {
+ state_(VIDEO_CAPTURE_STATE_STOPPED),
+ weak_this_factory_(this) {
DCHECK(filter);
- capture_format_.session_id = id;
}
VideoCaptureImpl::~VideoCaptureImpl() {}
@@ -94,12 +76,10 @@ void VideoCaptureImpl::DeInit(base::Closure task) {
void VideoCaptureImpl::StartCapture(
media::VideoCapture::EventHandler* handler,
- const media::VideoCaptureCapability& capability) {
- DCHECK_EQ(capability.color, media::PIXEL_FORMAT_I420);
-
+ const media::VideoCaptureParams& params) {
capture_message_loop_proxy_->PostTask(FROM_HERE,
base::Bind(&VideoCaptureImpl::DoStartCaptureOnCaptureThread,
- base::Unretained(this), handler, capability));
+ base::Unretained(this), handler, params));
}
void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) {
@@ -116,10 +96,19 @@ void VideoCaptureImpl::OnBufferCreated(
base::Unretained(this), handle, length, buffer_id));
}
-void VideoCaptureImpl::OnBufferReceived(int buffer_id, base::Time timestamp) {
+void VideoCaptureImpl::OnBufferDestroyed(int buffer_id) {
+ capture_message_loop_proxy_->PostTask(FROM_HERE,
+ base::Bind(&VideoCaptureImpl::DoBufferDestroyedOnCaptureThread,
+ base::Unretained(this), buffer_id));
+}
+
+void VideoCaptureImpl::OnBufferReceived(
+ int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format) {
capture_message_loop_proxy_->PostTask(FROM_HERE,
base::Bind(&VideoCaptureImpl::DoBufferReceivedOnCaptureThread,
- base::Unretained(this), buffer_id, timestamp));
+ base::Unretained(this), buffer_id, timestamp, format));
}
void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) {
@@ -128,20 +117,6 @@ void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) {
base::Unretained(this), state));
}
-void VideoCaptureImpl::OnDeviceInfoReceived(
- const media::VideoCaptureParams& device_info) {
- capture_message_loop_proxy_->PostTask(FROM_HERE,
- base::Bind(&VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread,
- base::Unretained(this), device_info));
-}
-
-void VideoCaptureImpl::OnDeviceInfoChanged(
- const media::VideoCaptureParams& device_info) {
- capture_message_loop_proxy_->PostTask(FROM_HERE,
- base::Bind(&VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread,
- base::Unretained(this), device_info));
-}
-
void VideoCaptureImpl::OnDelegateAdded(int32 device_id) {
capture_message_loop_proxy_->PostTask(FROM_HERE,
base::Bind(&VideoCaptureImpl::DoDelegateAddedOnCaptureThread,
@@ -165,7 +140,7 @@ void VideoCaptureImpl::DoDeInitOnCaptureThread(base::Closure task) {
void VideoCaptureImpl::DoStartCaptureOnCaptureThread(
media::VideoCapture::EventHandler* handler,
- const media::VideoCaptureCapability& capability) {
+ const media::VideoCaptureParams& params) {
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
if (state_ == VIDEO_CAPTURE_STATE_ERROR) {
@@ -178,46 +153,30 @@ void VideoCaptureImpl::DoStartCaptureOnCaptureThread(
clients_.find(handler) != clients_.end() ) {
// This client has started.
} else if (!device_id_) {
- clients_pending_on_filter_[handler] = capability;
+ clients_pending_on_filter_[handler] = params;
} else {
handler->OnStarted(this);
if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
- // TODO(wjia): Temporarily disable restarting till client supports
- // resampling.
-#if 0
- if (capability.width > capture_format_.width ||
- capability.height > capture_format_.height) {
- StopDevice();
- DVLOG(1) << "StartCapture: Got client with higher resolution ("
- << capability.width << ", " << capability.height << ") "
- << "after started, try to restart.";
- clients_pending_on_restart_[handler] = capability;
- } else {
-#endif
- {
- if (device_info_available_) {
- handler->OnDeviceInfoReceived(this, device_info_);
- }
-
- clients_[handler] = capability;
- }
+ clients_[handler] = params;
} else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) {
- clients_pending_on_restart_[handler] = capability;
- DVLOG(1) << "StartCapture: Got new resolution ("
- << capability.width << ", " << capability.height << ") "
- << ", during stopping.";
+ clients_pending_on_restart_[handler] = params;
+ DVLOG(1) << "StartCapture: Got new resolution "
+ << params.requested_format.frame_size.ToString()
+ << " during stopping.";
} else {
- clients_[handler] = capability;
+ // TODO(sheu): Allowing resolution change will require that all
+ // outstanding clients of a capture session support resolution change.
+ DCHECK(!params.allow_resolution_change);
+ clients_[handler] = params;
DCHECK_EQ(1ul, clients_.size());
- video_type_ = capability.color;
- int session_id = capture_format_.session_id;
- DCHECK_EQ(capability.session_id, 0);
- capture_format_ = capability;
- capture_format_.session_id = session_id;
- if (capture_format_.frame_rate > media::limits::kMaxFramesPerSecond)
- capture_format_.frame_rate = media::limits::kMaxFramesPerSecond;
- DVLOG(1) << "StartCapture: starting with first resolution ("
- << capture_format_.width << "," << capture_format_.height << ")";
+ params_ = params;
+ if (params_.requested_format.frame_rate >
+ media::limits::kMaxFramesPerSecond) {
+ params_.requested_format.frame_rate =
+ media::limits::kMaxFramesPerSecond;
+ }
+ DVLOG(1) << "StartCapture: starting with first resolution "
+ << params_.requested_format.frame_size.ToString();
StartCaptureInternal();
}
@@ -239,7 +198,7 @@ void VideoCaptureImpl::DoStopCaptureOnCaptureThread(
DVLOG(1) << "StopCapture: No more client, stopping ...";
StopDevice();
client_buffers_.clear();
- client_buffer_weak_this_factory_.InvalidateWeakPtrs();
+ weak_this_factory_.InvalidateWeakPtrs();
}
}
@@ -255,8 +214,6 @@ void VideoCaptureImpl::DoBufferCreatedOnCaptureThread(
return;
}
- DCHECK(device_info_available_);
-
scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(handle, false));
if (!shm->Map(length)) {
DLOG(ERROR) << "DoBufferCreatedOnCaptureThread: Map() failed.";
@@ -267,15 +224,26 @@ void VideoCaptureImpl::DoBufferCreatedOnCaptureThread(
client_buffers_.insert(std::make_pair(
buffer_id,
new ClientBuffer(shm.Pass(),
- length,
- device_info_.width,
- device_info_.height,
- device_info_.width))).second;
+ length))).second;
DCHECK(inserted);
}
+void VideoCaptureImpl::DoBufferDestroyedOnCaptureThread(int buffer_id) {
+ DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
+
+ ClientBufferMap::iterator iter = client_buffers_.find(buffer_id);
+ if (iter == client_buffers_.end())
+ return;
+
+ DCHECK(!iter->second || iter->second->HasOneRef())
+ << "Instructed to delete buffer we are still using.";
+ client_buffers_.erase(iter);
+}
+
void VideoCaptureImpl::DoBufferReceivedOnCaptureThread(
- int buffer_id, base::Time timestamp) {
+ int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format) {
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) {
@@ -283,15 +251,17 @@ void VideoCaptureImpl::DoBufferReceivedOnCaptureThread(
return;
}
+ last_frame_format_ = format;
+
ClientBufferMap::iterator iter = client_buffers_.find(buffer_id);
DCHECK(iter != client_buffers_.end());
scoped_refptr<ClientBuffer> buffer = iter->second;
scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapExternalSharedMemory(
+ media::VideoFrame::WrapExternalPackedMemory(
media::VideoFrame::I420,
- gfx::Size(buffer->frame_stride, buffer->frame_height),
- gfx::Rect(0, 0, buffer->frame_width, buffer->frame_height),
- gfx::Size(buffer->frame_width, buffer->frame_height),
+ last_frame_format_.frame_size,
+ gfx::Rect(last_frame_format_.frame_size),
+ last_frame_format_.frame_size,
reinterpret_cast<uint8*>(buffer->buffer->memory()),
buffer->buffer_size,
buffer->buffer->handle(),
@@ -302,7 +272,7 @@ void VideoCaptureImpl::DoBufferReceivedOnCaptureThread(
capture_message_loop_proxy_,
base::Bind(
&VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread,
- client_buffer_weak_this_factory_.GetWeakPtr(),
+ weak_this_factory_.GetWeakPtr(),
buffer_id,
buffer)));
@@ -327,7 +297,7 @@ void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) {
state_ = VIDEO_CAPTURE_STATE_STOPPED;
DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_;
client_buffers_.clear();
- client_buffer_weak_this_factory_.InvalidateWeakPtrs();
+ weak_this_factory_.InvalidateWeakPtrs();
if (!clients_.empty() || !clients_pending_on_restart_.empty())
RestartCapture();
break;
@@ -362,27 +332,6 @@ void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) {
}
}
-void VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread(
- const media::VideoCaptureParams& device_info) {
- DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
- DCHECK(client_buffers_.empty());
-
- device_info_ = device_info;
- device_info_available_ = true;
- for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) {
- it->first->OnDeviceInfoReceived(this, device_info);
- }
-}
-
-void VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread(
- const media::VideoCaptureParams& device_info) {
- DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
-
- for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) {
- it->first->OnDeviceInfoChanged(this, device_info);
- }
-}
-
void VideoCaptureImpl::DoDelegateAddedOnCaptureThread(int32 device_id) {
DVLOG(1) << "DoDelegateAdded: device_id " << device_id;
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
@@ -391,9 +340,9 @@ void VideoCaptureImpl::DoDelegateAddedOnCaptureThread(int32 device_id) {
for (ClientInfo::iterator it = clients_pending_on_filter_.begin();
it != clients_pending_on_filter_.end(); ) {
media::VideoCapture::EventHandler* handler = it->first;
- const media::VideoCaptureCapability capability = it->second;
+ const media::VideoCaptureParams params = it->second;
clients_pending_on_filter_.erase(it++);
- StartCapture(handler, capability);
+ StartCapture(handler, params);
}
}
@@ -407,11 +356,10 @@ void VideoCaptureImpl::DoSuspendCaptureOnCaptureThread(bool suspend) {
void VideoCaptureImpl::StopDevice() {
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
- device_info_available_ = false;
if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
state_ = VIDEO_CAPTURE_STATE_STOPPING;
Send(new VideoCaptureHostMsg_Stop(device_id_));
- capture_format_.width = capture_format_.height = 0;
+ params_.requested_format.frame_size.SetSize(0, 0);
}
}
@@ -423,20 +371,19 @@ void VideoCaptureImpl::RestartCapture() {
int height = 0;
for (ClientInfo::iterator it = clients_.begin();
it != clients_.end(); ++it) {
- width = std::max(width, it->second.width);
- height = std::max(height, it->second.height);
+ width = std::max(width, it->second.requested_format.frame_size.width());
+ height = std::max(height, it->second.requested_format.frame_size.height());
}
for (ClientInfo::iterator it = clients_pending_on_restart_.begin();
it != clients_pending_on_restart_.end(); ) {
- width = std::max(width, it->second.width);
- height = std::max(height, it->second.height);
+ width = std::max(width, it->second.requested_format.frame_size.width());
+ height = std::max(height, it->second.requested_format.frame_size.height());
clients_[it->first] = it->second;
clients_pending_on_restart_.erase(it++);
}
- capture_format_.width = width;
- capture_format_.height = height;
- DVLOG(1) << "RestartCapture, " << capture_format_.width << ", "
- << capture_format_.height;
+ params_.requested_format.frame_size.SetSize(width, height);
+ DVLOG(1) << "RestartCapture, "
+ << params_.requested_format.frame_size.ToString();
StartCaptureInternal();
}
@@ -444,13 +391,7 @@ void VideoCaptureImpl::StartCaptureInternal() {
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
DCHECK(device_id_);
- media::VideoCaptureParams capability_as_params_copy;
- capability_as_params_copy.width = capture_format_.width;
- capability_as_params_copy.height = capture_format_.height;
- capability_as_params_copy.frame_rate = capture_format_.frame_rate;
- capability_as_params_copy.session_id = capture_format_.session_id;
- capability_as_params_copy.frame_size_type = capture_format_.frame_size_type;
- Send(new VideoCaptureHostMsg_Start(device_id_, capability_as_params_copy));
+ Send(new VideoCaptureHostMsg_Start(device_id_, session_id_, params_));
state_ = VIDEO_CAPTURE_STATE_STARTED;
}
diff --git a/chromium/content/renderer/media/video_capture_impl.h b/chromium/content/renderer/media/video_capture_impl.h
index 03696a7c9ec..2215cef4336 100644
--- a/chromium/content/renderer/media/video_capture_impl.h
+++ b/chromium/content/renderer/media/video_capture_impl.h
@@ -6,8 +6,8 @@
// interfaces for clients to Start/Stop capture. It also communicates to clients
// when buffer is ready, state of capture device is changed.
-// VideoCaptureImpl is also a delegate of VideoCaptureMessageFilter which
-// relays operation of capture device to browser process and receives response
+// VideoCaptureImpl is also a delegate of VideoCaptureMessageFilter which relays
+// operation of a capture device to the browser process and receives responses
// from browser process.
// The media::VideoCapture and VideoCaptureMessageFilter::Delegate are
@@ -52,22 +52,21 @@ class CONTENT_EXPORT VideoCaptureImpl
// media::VideoCapture interface.
virtual void StartCapture(
media::VideoCapture::EventHandler* handler,
- const media::VideoCaptureCapability& capability) OVERRIDE;
+ const media::VideoCaptureParams& params) OVERRIDE;
virtual void StopCapture(media::VideoCapture::EventHandler* handler) OVERRIDE;
virtual bool CaptureStarted() OVERRIDE;
- virtual int CaptureWidth() OVERRIDE;
- virtual int CaptureHeight() OVERRIDE;
virtual int CaptureFrameRate() OVERRIDE;
// VideoCaptureMessageFilter::Delegate interface.
virtual void OnBufferCreated(base::SharedMemoryHandle handle,
- int length, int buffer_id) OVERRIDE;
- virtual void OnBufferReceived(int buffer_id, base::Time timestamp) OVERRIDE;
+ int length,
+ int buffer_id) OVERRIDE;
+ virtual void OnBufferDestroyed(int buffer_id) OVERRIDE;
+ virtual void OnBufferReceived(
+ int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format) OVERRIDE;
virtual void OnStateChanged(VideoCaptureState state) OVERRIDE;
- virtual void OnDeviceInfoReceived(
- const media::VideoCaptureParams& device_info) OVERRIDE;
- virtual void OnDeviceInfoChanged(
- const media::VideoCaptureParams& device_info) OVERRIDE;
virtual void OnDelegateAdded(int32 device_id) OVERRIDE;
// Stop/resume delivering video frames to clients, based on flag |suspend|.
@@ -80,28 +79,29 @@ class CONTENT_EXPORT VideoCaptureImpl
class ClientBuffer;
typedef std::map<media::VideoCapture::EventHandler*,
- media::VideoCaptureCapability> ClientInfo;
+ media::VideoCaptureParams> ClientInfo;
- VideoCaptureImpl(media::VideoCaptureSessionId id,
+ VideoCaptureImpl(media::VideoCaptureSessionId session_id,
base::MessageLoopProxy* capture_message_loop_proxy,
VideoCaptureMessageFilter* filter);
virtual ~VideoCaptureImpl();
void DoStartCaptureOnCaptureThread(
media::VideoCapture::EventHandler* handler,
- const media::VideoCaptureCapability& capability);
+ const media::VideoCaptureParams& params);
void DoStopCaptureOnCaptureThread(media::VideoCapture::EventHandler* handler);
void DoBufferCreatedOnCaptureThread(base::SharedMemoryHandle handle,
- int length, int buffer_id);
- void DoBufferReceivedOnCaptureThread(int buffer_id, base::Time timestamp);
+ int length,
+ int buffer_id);
+ void DoBufferDestroyedOnCaptureThread(int buffer_id);
+ void DoBufferReceivedOnCaptureThread(
+ int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format);
void DoClientBufferFinishedOnCaptureThread(
int buffer_id,
const scoped_refptr<ClientBuffer>& buffer);
void DoStateChangedOnCaptureThread(VideoCaptureState state);
- void DoDeviceInfoReceivedOnCaptureThread(
- const media::VideoCaptureParams& device_info);
- void DoDeviceInfoChangedOnCaptureThread(
- const media::VideoCaptureParams& device_info);
void DoDelegateAddedOnCaptureThread(int32 device_id);
void DoSuspendCaptureOnCaptureThread(bool suspend);
@@ -124,33 +124,31 @@ class CONTENT_EXPORT VideoCaptureImpl
const scoped_refptr<base::MessageLoopProxy> capture_message_loop_proxy_;
const scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
int device_id_;
+ const int session_id_;
// Buffers available for sending to the client.
typedef std::map<int32, scoped_refptr<ClientBuffer> > ClientBufferMap;
ClientBufferMap client_buffers_;
- // WeakPtrFactory pointing back to |this| object, for use with
- // media::VideoFrames constructed in OnBufferReceived() from buffers cached
- // in |client_buffers_|.
- base::WeakPtrFactory<VideoCaptureImpl> client_buffer_weak_this_factory_;
ClientInfo clients_;
-
ClientInfo clients_pending_on_filter_;
ClientInfo clients_pending_on_restart_;
- media::VideoPixelFormat video_type_;
-
- // Member capture_format_ represents the video format requested by the client
- // to this class via DoStartCaptureOnCaptureThread.
- media::VideoCaptureCapability capture_format_;
+ // Member params_ represents the video format requested by the
+ // client to this class via DoStartCaptureOnCaptureThread.
+ media::VideoCaptureParams params_;
// The device's video capture format sent from browser process side.
- media::VideoCaptureParams device_info_;
- bool device_info_available_;
+ media::VideoCaptureFormat last_frame_format_;
bool suspended_;
VideoCaptureState state_;
+ // WeakPtrFactory pointing back to |this| object, for use with
+ // media::VideoFrames constructed in OnBufferReceived() from buffers cached
+ // in |client_buffers_|.
+ base::WeakPtrFactory<VideoCaptureImpl> weak_this_factory_;
+
DISALLOW_COPY_AND_ASSIGN(VideoCaptureImpl);
};
diff --git a/chromium/content/renderer/media/video_capture_impl_unittest.cc b/chromium/content/renderer/media/video_capture_impl_unittest.cc
index 986106bf1bd..713b3a06d4f 100644
--- a/chromium/content/renderer/media/video_capture_impl_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_impl_unittest.cc
@@ -45,7 +45,7 @@ class MockVideoCaptureClient : public media::VideoCapture::EventHandler {
const scoped_refptr<media::VideoFrame>& frame));
MOCK_METHOD2(OnDeviceInfoReceived,
void(media::VideoCapture* capture,
- const media::VideoCaptureParams& device_info));
+ const media::VideoCaptureFormat& device_info));
private:
DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureClient);
@@ -81,9 +81,8 @@ class VideoCaptureImplTest : public ::testing::Test {
}
void DeviceStartCapture(int device_id,
+ media::VideoCaptureSessionId session_id,
const media::VideoCaptureParams& params) {
- media::VideoCaptureParams device_info = params;
- OnDeviceInfoReceived(device_info);
OnStateChanged(VIDEO_CAPTURE_STATE_STARTED);
}
@@ -96,21 +95,13 @@ class VideoCaptureImplTest : public ::testing::Test {
void DeviceReceiveEmptyBuffer(int device_id, int buffer_id) {}
};
- VideoCaptureImplTest()
- : capability_small_(176,
- 144,
- 30,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice),
- capability_large_(320,
- 240,
- 30,
- media::PIXEL_FORMAT_I420,
- 0,
- false,
- media::ConstantResolutionVideoCaptureDevice) {
+ VideoCaptureImplTest() {
+ params_small_.requested_format = media::VideoCaptureFormat(
+ gfx::Size(176, 144), 30, media::PIXEL_FORMAT_I420);
+
+ params_large_.requested_format = media::VideoCaptureFormat(
+ gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
+
message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
message_loop_proxy_ = base::MessageLoopProxy::current().get();
child_process_.reset(new ChildProcess());
@@ -135,8 +126,8 @@ class VideoCaptureImplTest : public ::testing::Test {
scoped_refptr<MockVideoCaptureMessageFilter> message_filter_;
media::VideoCaptureSessionId session_id_;
MockVideoCaptureImpl* video_capture_impl_;
- const media::VideoCaptureCapability capability_small_;
- const media::VideoCaptureCapability capability_large_;
+ media::VideoCaptureParams params_small_;
+ media::VideoCaptureParams params_large_;
private:
DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplTest);
@@ -148,10 +139,8 @@ TEST_F(VideoCaptureImplTest, Simple) {
EXPECT_CALL(*client, OnStarted(_))
.WillOnce(Return());
- EXPECT_CALL(*client, OnDeviceInfoReceived(_,_))
- .WillOnce(Return());
- video_capture_impl_->StartCapture(client.get(), capability_small_);
+ video_capture_impl_->StartCapture(client.get(), params_small_);
message_loop_->RunUntilIdle();
EXPECT_CALL(*client, OnStopped(_))
@@ -169,10 +158,8 @@ TEST_F(VideoCaptureImplTest, TwoClientsInSequence) {
EXPECT_CALL(*client, OnStarted(_))
.WillOnce(Return());
- EXPECT_CALL(*client, OnDeviceInfoReceived(_,_))
- .WillOnce(Return());
- video_capture_impl_->StartCapture(client.get(), capability_small_);
+ video_capture_impl_->StartCapture(client.get(), params_small_);
message_loop_->RunUntilIdle();
EXPECT_CALL(*client, OnStopped(_))
@@ -185,10 +172,8 @@ TEST_F(VideoCaptureImplTest, TwoClientsInSequence) {
EXPECT_CALL(*client, OnStarted(_))
.WillOnce(Return());
- EXPECT_CALL(*client, OnDeviceInfoReceived(_,_))
- .WillOnce(Return());
- video_capture_impl_->StartCapture(client.get(), capability_small_);
+ video_capture_impl_->StartCapture(client.get(), params_small_);
message_loop_->RunUntilIdle();
EXPECT_CALL(*client, OnStopped(_))
@@ -208,15 +193,11 @@ TEST_F(VideoCaptureImplTest, LargeAndSmall) {
EXPECT_CALL(*client_large, OnStarted(_))
.WillOnce(Return());
- EXPECT_CALL(*client_large, OnDeviceInfoReceived(_,_))
- .WillOnce(Return());
EXPECT_CALL(*client_small, OnStarted(_))
.WillOnce(Return());
- EXPECT_CALL(*client_small, OnDeviceInfoReceived(_,_))
- .WillOnce(Return());
- video_capture_impl_->StartCapture(client_large.get(), capability_large_);
- video_capture_impl_->StartCapture(client_small.get(), capability_small_);
+ video_capture_impl_->StartCapture(client_large.get(), params_large_);
+ video_capture_impl_->StartCapture(client_small.get(), params_small_);
message_loop_->RunUntilIdle();
EXPECT_CALL(*client_large, OnStopped(_))
@@ -241,16 +222,11 @@ TEST_F(VideoCaptureImplTest, SmallAndLarge) {
EXPECT_CALL(*client_large, OnStarted(_))
.WillOnce(Return());
- EXPECT_CALL(*client_large, OnDeviceInfoReceived(_,_))
- .WillOnce(Return());
EXPECT_CALL(*client_small, OnStarted(_))
.WillOnce(Return());
- EXPECT_CALL(*client_small, OnDeviceInfoReceived(_,_))
- .Times(AtLeast(1))
- .WillRepeatedly(Return());
- video_capture_impl_->StartCapture(client_small.get(), capability_small_);
- video_capture_impl_->StartCapture(client_large.get(), capability_large_);
+ video_capture_impl_->StartCapture(client_small.get(), params_small_);
+ video_capture_impl_->StartCapture(client_large.get(), params_large_);
message_loop_->RunUntilIdle();
EXPECT_CALL(*client_large, OnStopped(_))
@@ -275,15 +251,11 @@ TEST_F(VideoCaptureImplTest, TwoClientsWithSameSize) {
EXPECT_CALL(*client1, OnStarted(_))
.WillOnce(Return());
- EXPECT_CALL(*client1, OnDeviceInfoReceived(_,_))
- .WillOnce(Return());
EXPECT_CALL(*client2, OnStarted(_))
.WillOnce(Return());
- EXPECT_CALL(*client2, OnDeviceInfoReceived(_,_))
- .WillOnce(Return());
- video_capture_impl_->StartCapture(client1.get(), capability_small_);
- video_capture_impl_->StartCapture(client2.get(), capability_small_);
+ video_capture_impl_->StartCapture(client1.get(), params_small_);
+ video_capture_impl_->StartCapture(client2.get(), params_small_);
message_loop_->RunUntilIdle();
EXPECT_CALL(*client1, OnStopped(_))
diff --git a/chromium/content/renderer/media/video_capture_message_filter.cc b/chromium/content/renderer/media/video_capture_message_filter.cc
index 0ef77fa1888..52847d91744 100644
--- a/chromium/content/renderer/media/video_capture_message_filter.cc
+++ b/chromium/content/renderer/media/video_capture_message_filter.cc
@@ -60,7 +60,7 @@ bool VideoCaptureMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(VideoCaptureMsg_BufferReady, OnBufferReceived)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_StateChanged, OnDeviceStateChanged)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnBufferCreated)
- IPC_MESSAGE_HANDLER(VideoCaptureMsg_DeviceInfo, OnDeviceInfoReceived)
+ IPC_MESSAGE_HANDLER(VideoCaptureMsg_FreeBuffer, OnBufferDestroyed)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -68,8 +68,6 @@ bool VideoCaptureMessageFilter::OnMessageReceived(const IPC::Message& message) {
void VideoCaptureMessageFilter::OnFilterAdded(IPC::Channel* channel) {
DVLOG(1) << "VideoCaptureMessageFilter::OnFilterAdded()";
- // Captures the message loop proxy for IPC.
- message_loop_proxy_ = base::MessageLoopProxy::current();
channel_ = channel;
for (Delegates::iterator it = pending_delegates_.begin();
@@ -119,7 +117,8 @@ void VideoCaptureMessageFilter::OnBufferCreated(
void VideoCaptureMessageFilter::OnBufferReceived(
int device_id,
int buffer_id,
- base::Time timestamp) {
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format) {
Delegate* delegate = find_delegate(device_id);
if (!delegate) {
DLOG(WARNING) << "OnBufferReceived: Got video frame buffer for a "
@@ -131,31 +130,32 @@ void VideoCaptureMessageFilter::OnBufferReceived(
return;
}
- delegate->OnBufferReceived(buffer_id, timestamp);
+ delegate->OnBufferReceived(buffer_id, timestamp, format);
}
-void VideoCaptureMessageFilter::OnDeviceStateChanged(
+void VideoCaptureMessageFilter::OnBufferDestroyed(
int device_id,
- VideoCaptureState state) {
+ int buffer_id) {
Delegate* delegate = find_delegate(device_id);
if (!delegate) {
- DLOG(WARNING) << "OnDeviceStateChanged: Got video capture event for a "
+ DLOG(WARNING) << "OnBufferDestroyed: Instructed to free buffer for a "
"non-existent or removed video capture.";
return;
}
- delegate->OnStateChanged(state);
+
+ delegate->OnBufferDestroyed(buffer_id);
}
-void VideoCaptureMessageFilter::OnDeviceInfoReceived(
+void VideoCaptureMessageFilter::OnDeviceStateChanged(
int device_id,
- const media::VideoCaptureParams& params) {
+ VideoCaptureState state) {
Delegate* delegate = find_delegate(device_id);
if (!delegate) {
- DLOG(WARNING) << "OnDeviceInfoReceived: Got video capture event for a "
+ DLOG(WARNING) << "OnDeviceStateChanged: Got video capture event for a "
"non-existent or removed video capture.";
return;
}
- delegate->OnDeviceInfoReceived(params);
+ delegate->OnStateChanged(state);
}
} // namespace content
diff --git a/chromium/content/renderer/media/video_capture_message_filter.h b/chromium/content/renderer/media/video_capture_message_filter.h
index abbe23edb0c..024c1bd91b3 100644
--- a/chromium/content/renderer/media/video_capture_message_filter.h
+++ b/chromium/content/renderer/media/video_capture_message_filter.h
@@ -13,7 +13,6 @@
#include <map>
#include "base/memory/shared_memory.h"
-#include "base/message_loop/message_loop_proxy.h"
#include "content/common/content_export.h"
#include "content/common/media/video_capture.h"
#include "ipc/ipc_channel_proxy.h"
@@ -28,25 +27,20 @@ class CONTENT_EXPORT VideoCaptureMessageFilter
public:
// Called when a video frame buffer is created in the browser process.
virtual void OnBufferCreated(base::SharedMemoryHandle handle,
- int length, int buffer_id) = 0;
+ int length,
+ int buffer_id) = 0;
+
+ virtual void OnBufferDestroyed(int buffer_id) = 0;
// Called when a video frame buffer is received from the browser process.
- virtual void OnBufferReceived(int buffer_id, base::Time timestamp) = 0;
+ virtual void OnBufferReceived(int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format) = 0;
// Called when state of a video capture device has changed in the browser
// process.
virtual void OnStateChanged(VideoCaptureState state) = 0;
- // Called when device info is received from video capture device in the
- // browser process.
- virtual void OnDeviceInfoReceived(
- const media::VideoCaptureParams& device_info) = 0;
-
- // Called when newly changed device info is received from video capture
- // device in the browser process.
- virtual void OnDeviceInfoChanged(
- const media::VideoCaptureParams& device_info) {};
-
// Called when the delegate has been added to filter's delegate list.
// |device_id| is the device id for the delegate.
virtual void OnDelegateAdded(int32 device_id) = 0;
@@ -76,26 +70,27 @@ class CONTENT_EXPORT VideoCaptureMessageFilter
virtual ~VideoCaptureMessageFilter();
private:
- FRIEND_TEST_ALL_PREFIXES(VideoCaptureMessageFilterTest, Basic);
- FRIEND_TEST_ALL_PREFIXES(VideoCaptureMessageFilterTest, Delegates);
-
typedef std::map<int32, Delegate*> Delegates;
// Receive a newly created buffer from browser process.
void OnBufferCreated(int device_id,
base::SharedMemoryHandle handle,
- int length, int buffer_id);
+ int length,
+ int buffer_id);
- // Receive a buffer from browser process.
- void OnBufferReceived(int device_id, int buffer_id, base::Time timestamp);
+ // Release a buffer received by OnBufferCreated.
+ void OnBufferDestroyed(int device_id,
+ int buffer_id);
+
+ // Receive a filled buffer from browser process.
+ void OnBufferReceived(int device_id,
+ int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format);
// State of browser process' video capture device has changed.
void OnDeviceStateChanged(int device_id, VideoCaptureState state);
- // Receive device info from browser process.
- void OnDeviceInfoReceived(int device_id,
- const media::VideoCaptureParams& params);
-
// Finds the delegate associated with |device_id|, NULL if not found.
Delegate* find_delegate(int device_id) const;
@@ -106,8 +101,6 @@ class CONTENT_EXPORT VideoCaptureMessageFilter
IPC::Channel* channel_;
- scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
-
DISALLOW_COPY_AND_ASSIGN(VideoCaptureMessageFilter);
};
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 3dec39d5de3..366bcb03041 100644
--- a/chromium/content/renderer/media/video_capture_message_filter_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_message_filter_unittest.cc
@@ -3,125 +3,67 @@
// found in the LICENSE file.
#include "base/memory/shared_memory.h"
-#include "base/message_loop/message_loop.h"
#include "content/common/media/video_capture_messages.h"
#include "content/renderer/media/video_capture_message_filter.h"
+#include "ipc/ipc_test_sink.h"
+#include "media/video/capture/video_capture_types.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::Mock;
+using ::testing::Return;
+using ::testing::SaveArg;
+using ::testing::StrictMock;
+
namespace content {
namespace {
class MockVideoCaptureDelegate : public VideoCaptureMessageFilter::Delegate {
public:
- MockVideoCaptureDelegate() {
- Reset();
- device_id_received_ = false;
- device_id_ = 0;
- }
-
- virtual void OnBufferCreated(base::SharedMemoryHandle handle,
- int length, int buffer_id) OVERRIDE {
- buffer_created_ = true;
- handle_ = handle;
- }
-
- // Called when a video frame buffer is received from the browser process.
- virtual void OnBufferReceived(int buffer_id, base::Time timestamp) OVERRIDE {
- buffer_received_ = true;
- buffer_id_ = buffer_id;
- timestamp_ = timestamp;
- }
-
- virtual void OnStateChanged(VideoCaptureState state) OVERRIDE {
- state_changed_received_ = true;
- state_ = state;
- }
-
- virtual void OnDeviceInfoReceived(
- const media::VideoCaptureParams& params) OVERRIDE {
- device_info_received_ = true;
- params_.width = params.width;
- params_.height = params.height;
- params_.frame_rate = params.frame_rate;
- }
+ MockVideoCaptureDelegate() : device_id_(0) {}
+
+ // VideoCaptureMessageFilter::Delegate implementation.
+ MOCK_METHOD3(OnBufferCreated, void(base::SharedMemoryHandle handle,
+ int length,
+ int buffer_id));
+ MOCK_METHOD1(OnBufferDestroyed, void(int buffer_id));
+ MOCK_METHOD3(OnBufferReceived, void(int buffer_id,
+ base::Time timestamp,
+ const media::VideoCaptureFormat& format));
+ MOCK_METHOD1(OnStateChanged, void(VideoCaptureState state));
virtual void OnDelegateAdded(int32 device_id) OVERRIDE {
- device_id_received_ = true;
+ ASSERT_TRUE(device_id != 0);
+ ASSERT_TRUE(device_id_ == 0);
device_id_ = device_id;
}
- void Reset() {
- buffer_created_ = false;
- handle_ = base::SharedMemory::NULLHandle();
-
- buffer_received_ = false;
- buffer_id_ = -1;
- timestamp_ = base::Time();
-
- state_changed_received_ = false;
- state_ = VIDEO_CAPTURE_STATE_ERROR;
-
- device_info_received_ = false;
- params_.width = 0;
- params_.height = 0;
- params_.frame_rate = 0;
- }
-
- bool buffer_created() { return buffer_created_; }
- base::SharedMemoryHandle received_buffer_handle() { return handle_; }
-
- bool buffer_received() { return buffer_received_; }
- int received_buffer_id() { return buffer_id_; }
- base::Time received_buffer_ts() { return timestamp_; }
-
- bool state_changed_received() { return state_changed_received_; }
- VideoCaptureState state() { return state_; }
-
- bool device_info_receive() { return device_info_received_; }
- const media::VideoCaptureParams& received_device_info() { return params_; }
-
- int32 device_id() { return device_id_; }
+ int device_id() { return device_id_; }
private:
- bool buffer_created_;
- base::SharedMemoryHandle handle_;
-
- bool buffer_received_;
- int buffer_id_;
- base::Time timestamp_;
-
- bool state_changed_received_;
- VideoCaptureState state_;
-
- bool device_info_received_;
- media::VideoCaptureParams params_;
-
- bool device_id_received_;
- int32 device_id_;
-
- DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureDelegate);
+ int device_id_;
};
} // namespace
TEST(VideoCaptureMessageFilterTest, Basic) {
- base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
-
scoped_refptr<VideoCaptureMessageFilter> filter(
new VideoCaptureMessageFilter());
- filter->channel_ = reinterpret_cast<IPC::Channel*>(1);
+ IPC::TestSink channel;
+ filter->OnFilterAdded(&channel);
MockVideoCaptureDelegate delegate;
filter->AddDelegate(&delegate);
+ ASSERT_EQ(1, delegate.device_id());
// VideoCaptureMsg_StateChanged
- EXPECT_FALSE(delegate.state_changed_received());
+ EXPECT_CALL(delegate, OnStateChanged(VIDEO_CAPTURE_STATE_STARTED));
filter->OnMessageReceived(
VideoCaptureMsg_StateChanged(delegate.device_id(),
VIDEO_CAPTURE_STATE_STARTED));
- EXPECT_TRUE(delegate.state_changed_received());
- EXPECT_TRUE(VIDEO_CAPTURE_STATE_STARTED == delegate.state());
- delegate.Reset();
+ Mock::VerifyAndClearExpectations(&delegate);
// VideoCaptureMsg_NewBuffer
const base::SharedMemoryHandle handle =
@@ -130,92 +72,72 @@ TEST(VideoCaptureMessageFilterTest, Basic) {
#else
base::SharedMemoryHandle(10, true);
#endif
- EXPECT_FALSE(delegate.buffer_created());
+ EXPECT_CALL(delegate, OnBufferCreated(handle, 100, 1));
filter->OnMessageReceived(VideoCaptureMsg_NewBuffer(
- delegate.device_id(), handle, 1, 1));
- EXPECT_TRUE(delegate.buffer_created());
- EXPECT_EQ(handle, delegate.received_buffer_handle());
- delegate.Reset();
+ delegate.device_id(), handle, 100, 1));
+ Mock::VerifyAndClearExpectations(&delegate);
// VideoCaptureMsg_BufferReady
- int buffer_id = 1;
+ int buffer_id = 22;
base::Time timestamp = base::Time::FromInternalValue(1);
- EXPECT_FALSE(delegate.buffer_received());
+ media::VideoCaptureFormat format(
+ gfx::Size(234, 512), 30, media::PIXEL_FORMAT_I420);
+ media::VideoCaptureFormat saved_format;
+ EXPECT_CALL(delegate, OnBufferReceived(buffer_id, timestamp, _))
+ .WillRepeatedly(SaveArg<2>(&saved_format));
filter->OnMessageReceived(VideoCaptureMsg_BufferReady(
- delegate.device_id(), buffer_id, timestamp));
- EXPECT_TRUE(delegate.buffer_received());
- EXPECT_EQ(buffer_id, delegate.received_buffer_id());
- EXPECT_TRUE(timestamp == delegate.received_buffer_ts());
- delegate.Reset();
-
- // VideoCaptureMsg_DeviceInfo
- media::VideoCaptureParams params;
- params.width = 320;
- params.height = 240;
- params.frame_rate = 30;
-
- EXPECT_FALSE(delegate.device_info_receive());
- filter->OnMessageReceived(VideoCaptureMsg_DeviceInfo(
- delegate.device_id(), params));
- EXPECT_TRUE(delegate.device_info_receive());
- EXPECT_EQ(params.width, delegate.received_device_info().width);
- EXPECT_EQ(params.height, delegate.received_device_info().height);
- EXPECT_EQ(params.frame_rate,
- delegate.received_device_info().frame_rate);
- delegate.Reset();
-
- message_loop.RunUntilIdle();
+ delegate.device_id(), buffer_id, timestamp, format));
+ Mock::VerifyAndClearExpectations(&delegate);
+ EXPECT_EQ(234, saved_format.frame_size.width());
+ EXPECT_EQ(512, saved_format.frame_size.height());
+ EXPECT_EQ(30, saved_format.frame_rate);
+
+ // VideoCaptureMsg_FreeBuffer
+ EXPECT_CALL(delegate, OnBufferDestroyed(buffer_id));
+ filter->OnMessageReceived(VideoCaptureMsg_FreeBuffer(
+ delegate.device_id(), buffer_id));
+ Mock::VerifyAndClearExpectations(&delegate);
}
TEST(VideoCaptureMessageFilterTest, Delegates) {
- base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
-
scoped_refptr<VideoCaptureMessageFilter> filter(
new VideoCaptureMessageFilter());
- filter->channel_ = reinterpret_cast<IPC::Channel*>(1);
- MockVideoCaptureDelegate delegate1;
- MockVideoCaptureDelegate delegate2;
+ IPC::TestSink channel;
+ filter->OnFilterAdded(&channel);
+
+ StrictMock<MockVideoCaptureDelegate> delegate1;
+ StrictMock<MockVideoCaptureDelegate> delegate2;
filter->AddDelegate(&delegate1);
filter->AddDelegate(&delegate2);
+ ASSERT_EQ(1, delegate1.device_id());
+ ASSERT_EQ(2, delegate2.device_id());
// Send an IPC message. Make sure the correct delegate gets called.
- EXPECT_FALSE(delegate1.state_changed_received());
- EXPECT_FALSE(delegate2.state_changed_received());
+ EXPECT_CALL(delegate1, OnStateChanged(VIDEO_CAPTURE_STATE_STARTED));
filter->OnMessageReceived(
VideoCaptureMsg_StateChanged(delegate1.device_id(),
VIDEO_CAPTURE_STATE_STARTED));
- EXPECT_TRUE(delegate1.state_changed_received());
- EXPECT_FALSE(delegate2.state_changed_received());
- delegate1.Reset();
+ Mock::VerifyAndClearExpectations(&delegate1);
- EXPECT_FALSE(delegate1.state_changed_received());
- EXPECT_FALSE(delegate2.state_changed_received());
+ EXPECT_CALL(delegate2, OnStateChanged(VIDEO_CAPTURE_STATE_STARTED));
filter->OnMessageReceived(
VideoCaptureMsg_StateChanged(delegate2.device_id(),
VIDEO_CAPTURE_STATE_STARTED));
- EXPECT_FALSE(delegate1.state_changed_received());
- EXPECT_TRUE(delegate2.state_changed_received());
- delegate2.Reset();
+ Mock::VerifyAndClearExpectations(&delegate2);
// Remove the delegates. Make sure they won't get called.
filter->RemoveDelegate(&delegate1);
- EXPECT_FALSE(delegate1.state_changed_received());
filter->OnMessageReceived(
VideoCaptureMsg_StateChanged(delegate1.device_id(),
- VIDEO_CAPTURE_STATE_STARTED));
- EXPECT_FALSE(delegate1.state_changed_received());
+ VIDEO_CAPTURE_STATE_ENDED));
filter->RemoveDelegate(&delegate2);
- EXPECT_FALSE(delegate2.state_changed_received());
filter->OnMessageReceived(
VideoCaptureMsg_StateChanged(delegate2.device_id(),
- VIDEO_CAPTURE_STATE_STARTED));
- EXPECT_FALSE(delegate2.state_changed_received());
-
- message_loop.RunUntilIdle();
+ VIDEO_CAPTURE_STATE_ENDED));
}
} // namespace content
diff --git a/chromium/content/renderer/media/video_destination_handler.cc b/chromium/content/renderer/media/video_destination_handler.cc
index 7438c495f3a..692efeff86f 100644
--- a/chromium/content/renderer/media/video_destination_handler.cc
+++ b/chromium/content/renderer/media/video_destination_handler.cc
@@ -168,12 +168,12 @@ bool VideoDestinationHandler::Open(
factory = RenderThreadImpl::current()->GetMediaStreamDependencyFactory();
DCHECK(factory != NULL);
}
- WebKit::WebMediaStream stream;
+ blink::WebMediaStream stream;
if (registry) {
stream = registry->GetMediaStream(url);
} else {
stream =
- WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
+ blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
}
if (stream.isNull() || !stream.extraData()) {
LOG(ERROR) << "VideoDestinationHandler::Open - invalid url: " << url;
diff --git a/chromium/content/renderer/media/video_destination_handler.h b/chromium/content/renderer/media/video_destination_handler.h
index 087d3ac6437..578fe223202 100644
--- a/chromium/content/renderer/media/video_destination_handler.h
+++ b/chromium/content/renderer/media/video_destination_handler.h
@@ -75,7 +75,7 @@ class CONTENT_EXPORT VideoDestinationHandler {
// |frame_writer|.
// If |factory| is NULL the MediaStreamDependencyFactory owned by
// RenderThreadImpl::current() will be used.
- // If |registry| is NULL the global WebKit::WebMediaStreamRegistry will be
+ // If |registry| is NULL the global blink::WebMediaStreamRegistry will be
// used to look up the media stream.
// The caller of the function takes the ownership of |frame_writer|.
// Returns true on success and false on failure.
diff --git a/chromium/content/renderer/media/video_destination_handler_unittest.cc b/chromium/content/renderer/media/video_destination_handler_unittest.cc
index 110e115b84b..a89ad614386 100644
--- a/chromium/content/renderer/media/video_destination_handler_unittest.cc
+++ b/chromium/content/renderer/media/video_destination_handler_unittest.cc
@@ -106,8 +106,8 @@ TEST_F(VideoDestinationHandlerTest, Open) {
EXPECT_TRUE(frame_writer);
// Verify the video track has been added.
- const WebKit::WebMediaStream test_stream = registry_.test_stream();
- WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
+ const blink::WebMediaStream test_stream = registry_.test_stream();
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
test_stream.videoTracks(video_tracks);
EXPECT_EQ(1u, video_tracks.size());
diff --git a/chromium/content/renderer/media/video_source_handler.cc b/chromium/content/renderer/media/video_source_handler.cc
index c0577fc3a32..69b83557939 100644
--- a/chromium/content/renderer/media/video_source_handler.cc
+++ b/chromium/content/renderer/media/video_source_handler.cc
@@ -103,12 +103,12 @@ bool VideoSourceHandler::Close(const std::string& url,
scoped_refptr<VideoSourceInterface> VideoSourceHandler::GetFirstVideoSource(
const std::string& url) {
scoped_refptr<webrtc::VideoSourceInterface> source;
- WebKit::WebMediaStream stream;
+ blink::WebMediaStream stream;
if (registry_) {
stream = registry_->GetMediaStream(url);
} else {
stream =
- WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
+ blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
}
if (stream.isNull() || !stream.extraData()) {
LOG(ERROR) << "GetFirstVideoSource - invalid url: " << url;
diff --git a/chromium/content/renderer/media/video_source_handler.h b/chromium/content/renderer/media/video_source_handler.h
index 3d3b4df560b..7025d922ccc 100644
--- a/chromium/content/renderer/media/video_source_handler.h
+++ b/chromium/content/renderer/media/video_source_handler.h
@@ -40,7 +40,7 @@ class CONTENT_EXPORT FrameReaderInterface {
class CONTENT_EXPORT VideoSourceHandler {
public:
// |registry| is used to look up the media stream by url. If a NULL |registry|
- // is given, the global WebKit::WebMediaStreamRegistry will be used.
+ // is given, the global blink::WebMediaStreamRegistry will be used.
explicit VideoSourceHandler(MediaStreamRegistryInterface* registry);
virtual ~VideoSourceHandler();
// Connects to the first video track in the MediaStream specified by |url| and
diff --git a/chromium/content/renderer/media/webaudio_capturer_source.cc b/chromium/content/renderer/media/webaudio_capturer_source.cc
index f9bf084cccd..1f1192a9791 100644
--- a/chromium/content/renderer/media/webaudio_capturer_source.cc
+++ b/chromium/content/renderer/media/webaudio_capturer_source.cc
@@ -5,7 +5,8 @@
#include "content/renderer/media/webaudio_capturer_source.h"
#include "base/logging.h"
-#include "content/renderer/media/webrtc_local_audio_source_provider.h"
+#include "base/time/time.h"
+#include "content/renderer/media/webrtc_audio_capturer.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
using media::AudioBus;
@@ -21,7 +22,8 @@ namespace content {
WebAudioCapturerSource::WebAudioCapturerSource()
: track_(NULL),
- source_provider_(NULL) {
+ capturer_(NULL),
+ audio_format_changed_(false) {
}
WebAudioCapturerSource::~WebAudioCapturerSource() {
@@ -48,11 +50,7 @@ void WebAudioCapturerSource::setFormat(
params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
channel_layout, number_of_channels, 0, sample_rate, 16,
sample_rate / 100);
-
- // Update the downstream client to use the same format as what WebKit
- // is using.
- if (track_)
- track_->SetCaptureFormat(params_);
+ audio_format_changed_ = true;
wrapper_bus_ = AudioBus::CreateWrapper(params_.channels());
capture_bus_ = AudioBus::Create(params_);
@@ -62,35 +60,34 @@ void WebAudioCapturerSource::setFormat(
}
void WebAudioCapturerSource::Start(
- WebRtcLocalAudioTrack* track,
- WebRtcLocalAudioSourceProvider* source_provider) {
+ WebRtcLocalAudioTrack* track, WebRtcAudioCapturer* capturer) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(track);
- // |source_provider| may be NULL if no getUserMedia has been called before
- // calling CreateMediaStreamDestination.
- // The downstream client should be configured the same as what WebKit
- // is feeding it.
- track->SetCaptureFormat(params_);
-
base::AutoLock auto_lock(lock_);
track_ = track;
- source_provider_ = source_provider;
+ capturer_ = capturer;
}
void WebAudioCapturerSource::Stop() {
DCHECK(thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
track_ = NULL;
- source_provider_ = NULL;
+ capturer_ = NULL;
}
void WebAudioCapturerSource::consumeAudio(
- const WebKit::WebVector<const float*>& audio_data,
+ const blink::WebVector<const float*>& audio_data,
size_t number_of_frames) {
base::AutoLock auto_lock(lock_);
if (!track_)
return;
+ // Update the downstream client if the audio format has been changed.
+ if (audio_format_changed_) {
+ track_->OnSetFormat(params_);
+ audio_format_changed_ = false;
+ }
+
wrapper_bus_->set_frames(number_of_frames);
// Make sure WebKit is honoring what it told us up front
@@ -109,16 +106,16 @@ void WebAudioCapturerSource::consumeAudio(
fifo_->Push(wrapper_bus_.get());
int capture_frames = params_.frames_per_buffer();
- int delay_ms = 0;
+ base::TimeDelta delay;
int volume = 0;
bool key_pressed = false;
+ if (capturer_) {
+ capturer_->GetAudioProcessingParams(&delay, &volume, &key_pressed);
+ }
while (fifo_->frames() >= capture_frames) {
- if (source_provider_) {
- source_provider_->GetAudioProcessingParams(
- &delay_ms, &volume, &key_pressed);
- }
fifo_->Consume(capture_bus_.get(), 0, capture_frames);
- track_->Capture(capture_bus_.get(), delay_ms, volume, key_pressed);
+ track_->Capture(capture_bus_.get(), delay.InMilliseconds(),
+ volume, key_pressed);
}
}
diff --git a/chromium/content/renderer/media/webaudio_capturer_source.h b/chromium/content/renderer/media/webaudio_capturer_source.h
index b438a4083ee..2993531db18 100644
--- a/chromium/content/renderer/media/webaudio_capturer_source.h
+++ b/chromium/content/renderer/media/webaudio_capturer_source.h
@@ -16,8 +16,8 @@
namespace content {
+class WebRtcAudioCapturer;
class WebRtcLocalAudioTrack;
-class WebRtcLocalAudioSourceProvider;
// WebAudioCapturerSource is the missing link between
// WebAudio's MediaStreamAudioDestinationNode and WebRtcLocalAudioTrack.
@@ -28,7 +28,7 @@ class WebRtcLocalAudioSourceProvider;
// audio stream to the WebRtcLocalAudioTrack::Capture() method.
class WebAudioCapturerSource
: public base::RefCountedThreadSafe<WebAudioCapturerSource>,
- public WebKit::WebAudioDestinationConsumer {
+ public blink::WebAudioDestinationConsumer {
public:
WebAudioCapturerSource();
@@ -37,15 +37,14 @@ class WebAudioCapturerSource
virtual void setFormat(size_t number_of_channels, float sample_rate) OVERRIDE;
// MediaStreamAudioDestinationNode periodically calls consumeAudio().
// Called on the WebAudio audio thread.
- virtual void consumeAudio(const WebKit::WebVector<const float*>& audio_data,
+ virtual void consumeAudio(const blink::WebVector<const float*>& audio_data,
size_t number_of_frames) OVERRIDE;
// Called when the WebAudioCapturerSource is hooking to a media audio track.
// |track| is the sink of the data flow. |source_provider| is the source of
// the data flow where stream information like delay, volume, key_pressed,
// is stored.
- void Start(WebRtcLocalAudioTrack* track,
- WebRtcLocalAudioSourceProvider* source_provider);
+ void Start(WebRtcLocalAudioTrack* track, WebRtcAudioCapturer* capturer);
// Called when the media audio track is stopping.
void Stop();
@@ -63,13 +62,16 @@ class WebAudioCapturerSource
// To avoid circular reference, a raw pointer is kept here.
WebRtcLocalAudioTrack* track_;
- // A raw pointer to the source provider to get audio processing params like
+ // A raw pointer to the capturer to get audio processing params like
// delay, volume, key_pressed information.
- // This |source_provider_| is guaranteed to outlive this object.
- WebRtcLocalAudioSourceProvider* source_provider_;
+ // This |capturer_| is guaranteed to outlive this object.
+ WebRtcAudioCapturer* capturer_;
media::AudioParameters params_;
+ // Flag to help notify the |track_| when the audio format has changed.
+ bool audio_format_changed_;
+
// Wraps data coming from HandleCapture().
scoped_ptr<media::AudioBus> wrapper_bus_;
diff --git a/chromium/content/renderer/media/webaudiosourceprovider_impl.cc b/chromium/content/renderer/media/webaudiosourceprovider_impl.cc
index b722a33af4c..ec1683daae4 100644
--- a/chromium/content/renderer/media/webaudiosourceprovider_impl.cc
+++ b/chromium/content/renderer/media/webaudiosourceprovider_impl.cc
@@ -6,10 +6,13 @@
#include <vector>
+#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/logging.h"
-#include "third_party/WebKit/public/web/WebAudioSourceProviderClient.h"
+#include "media/base/bind_to_loop.h"
+#include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h"
-using WebKit::WebVector;
+using blink::WebVector;
namespace content {
@@ -45,7 +48,8 @@ class AutoTryLock {
WebAudioSourceProviderImpl::WebAudioSourceProviderImpl(
const scoped_refptr<media::AudioRendererSink>& sink)
- : channels_(0),
+ : weak_this_(this),
+ channels_(0),
sample_rate_(0),
volume_(1.0),
state_(kStopped),
@@ -54,10 +58,11 @@ WebAudioSourceProviderImpl::WebAudioSourceProviderImpl(
sink_(sink) {
}
-WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() {}
+WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() {
+}
void WebAudioSourceProviderImpl::setClient(
- WebKit::WebAudioSourceProviderClient* client) {
+ blink::WebAudioSourceProviderClient* client) {
base::AutoLock auto_lock(sink_lock_);
if (client && client != client_) {
// Detach the audio renderer from normal playback.
@@ -66,14 +71,17 @@ void WebAudioSourceProviderImpl::setClient(
// The client will now take control by calling provideInput() periodically.
client_ = client;
- if (renderer_) {
- // The client needs to be notified of the audio format, if available.
- // If the format is not yet available, we'll be notified later
- // when Initialize() is called.
-
- // Inform WebKit about the audio stream format.
- client->setFormat(channels_, sample_rate_);
- }
+ set_format_cb_ = media::BindToCurrentLoop(
+ base::Bind(&WebAudioSourceProviderImpl::OnSetFormat,
+ weak_this_.GetWeakPtr()));
+
+ // If |renderer_| is set, then run |set_format_cb_| to send |client_|
+ // the current format info. If |renderer_| is not set, then |set_format_cb_|
+ // will get called when Initialize() is called.
+ // Note: Always using |set_format_cb_| ensures we have the same
+ // locking order when calling into |client_|.
+ if (renderer_)
+ base::ResetAndReturn(&set_format_cb_).Run();
} else if (!client && client_) {
// Restore normal playback.
client_ = NULL;
@@ -165,10 +173,17 @@ void WebAudioSourceProviderImpl::Initialize(
channels_ = params.channels();
sample_rate_ = params.sample_rate();
- if (client_) {
- // Inform WebKit about the audio stream format.
- client_->setFormat(channels_, sample_rate_);
- }
+ if (!set_format_cb_.is_null())
+ base::ResetAndReturn(&set_format_cb_).Run();
+}
+
+void WebAudioSourceProviderImpl::OnSetFormat() {
+ base::AutoLock auto_lock(sink_lock_);
+ if (!client_)
+ return;
+
+ // Inform Blink about the audio stream format.
+ client_->setFormat(channels_, sample_rate_);
}
} // namespace content
diff --git a/chromium/content/renderer/media/webaudiosourceprovider_impl.h b/chromium/content/renderer/media/webaudiosourceprovider_impl.h
index fd27697f49b..d1a6fe72322 100644
--- a/chromium/content/renderer/media/webaudiosourceprovider_impl.h
+++ b/chromium/content/renderer/media/webaudiosourceprovider_impl.h
@@ -5,20 +5,22 @@
#ifndef CONTENT_RENDERER_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_
#define CONTENT_RENDERER_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "media/base/audio_renderer_sink.h"
+#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h"
#include "third_party/WebKit/public/platform/WebVector.h"
-#include "third_party/WebKit/public/web/WebAudioSourceProvider.h"
-namespace WebKit {
+namespace blink {
class WebAudioSourceProviderClient;
}
namespace content {
// WebAudioSourceProviderImpl provides a bridge between classes:
-// WebKit::WebAudioSourceProvider <---> media::AudioRendererSink
+// blink::WebAudioSourceProvider <---> media::AudioRendererSink
//
// WebAudioSourceProviderImpl wraps an existing audio sink that is used unless
// WebKit has set a client via setClient(). While a client is set WebKit will
@@ -27,15 +29,15 @@ namespace content {
//
// All calls are protected by a lock.
class CONTENT_EXPORT WebAudioSourceProviderImpl
- : NON_EXPORTED_BASE(public WebKit::WebAudioSourceProvider),
+ : NON_EXPORTED_BASE(public blink::WebAudioSourceProvider),
NON_EXPORTED_BASE(public media::AudioRendererSink) {
public:
explicit WebAudioSourceProviderImpl(
const scoped_refptr<media::AudioRendererSink>& sink);
- // WebKit::WebAudioSourceProvider implementation.
- virtual void setClient(WebKit::WebAudioSourceProviderClient* client);
- virtual void provideInput(const WebKit::WebVector<float*>& audio_data,
+ // blink::WebAudioSourceProvider implementation.
+ virtual void setClient(blink::WebAudioSourceProviderClient* client);
+ virtual void provideInput(const blink::WebVector<float*>& audio_data,
size_t number_of_frames);
// media::AudioRendererSink implementation.
@@ -51,6 +53,14 @@ class CONTENT_EXPORT WebAudioSourceProviderImpl
virtual ~WebAudioSourceProviderImpl();
private:
+ // Calls setFormat() on |client_| from the Blink renderer thread.
+ void OnSetFormat();
+
+ base::WeakPtrFactory<WebAudioSourceProviderImpl> weak_this_;
+
+ // Closure that posts a task to call OnSetFormat() on the renderer thread.
+ base::Closure set_format_cb_;
+
// Set to true when Initialize() is called.
int channels_;
int sample_rate_;
@@ -64,7 +74,7 @@ class CONTENT_EXPORT WebAudioSourceProviderImpl
media::AudioRendererSink::RenderCallback* renderer_;
// When set via setClient() it overrides |sink_| for consuming audio.
- WebKit::WebAudioSourceProviderClient* client_;
+ blink::WebAudioSourceProviderClient* client_;
// Where audio ends up unless overridden by |client_|.
base::Lock sink_lock_;
diff --git a/chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc b/chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc
index 9b893c74b25..e4786a5a07a 100644
--- a/chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc
+++ b/chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "content/renderer/media/webaudiosourceprovider_impl.h"
#include "media/audio/audio_parameters.h"
#include "media/base/fake_audio_render_callback.h"
#include "media/base/mock_audio_renderer_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebAudioSourceProviderClient.h"
+#include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h"
namespace content {
@@ -18,7 +20,7 @@ const float kTestVolume = 0.25;
class WebAudioSourceProviderImplTest
: public testing::Test,
- public WebKit::WebAudioSourceProviderClient {
+ public blink::WebAudioSourceProviderClient {
public:
WebAudioSourceProviderImplTest()
: params_(media::AudioParameters::AUDIO_PCM_LINEAR,
@@ -51,7 +53,7 @@ class WebAudioSourceProviderImplTest
testing::Mock::VerifyAndClear(mock_sink_.get());
}
- void SetClient(WebKit::WebAudioSourceProviderClient* client) {
+ void SetClient(blink::WebAudioSourceProviderClient* client) {
testing::InSequence s;
if (client) {
@@ -59,6 +61,7 @@ class WebAudioSourceProviderImplTest
EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate()));
}
wasp_impl_->setClient(client);
+ base::RunLoop().RunUntilIdle();
testing::Mock::VerifyAndClear(mock_sink_.get());
testing::Mock::VerifyAndClear(this);
@@ -76,7 +79,7 @@ class WebAudioSourceProviderImplTest
return true;
}
- // WebKit::WebAudioSourceProviderClient implementation.
+ // blink::WebAudioSourceProviderClient implementation.
MOCK_METHOD2(setFormat, void(size_t numberOfChannels, float sampleRate));
protected:
@@ -84,6 +87,7 @@ class WebAudioSourceProviderImplTest
media::FakeAudioRenderCallback fake_callback_;
scoped_refptr<media::MockAudioRendererSink> mock_sink_;
scoped_refptr<WebAudioSourceProviderImpl> wasp_impl_;
+ base::MessageLoop message_loop_;
DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest);
};
@@ -94,14 +98,17 @@ TEST_F(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) {
EXPECT_CALL(*mock_sink_.get(), Stop());
wasp_impl_->setClient(this);
+ base::RunLoop().RunUntilIdle();
// When Initialize() is called after setClient(), the params should propagate
// to the client via setFormat() during the call.
EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate()));
wasp_impl_->Initialize(params_, &fake_callback_);
+ base::RunLoop().RunUntilIdle();
// setClient() with the same client should do nothing.
wasp_impl_->setClient(this);
+ base::RunLoop().RunUntilIdle();
}
// Verify AudioRendererSink functionality w/ and w/o a client.
@@ -153,7 +160,7 @@ TEST_F(WebAudioSourceProviderImplTest, ProvideInput) {
scoped_ptr<media::AudioBus> bus2 = media::AudioBus::Create(params_);
// Point the WebVector into memory owned by |bus1|.
- WebKit::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels()));
+ blink::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels()));
for (size_t i = 0; i < audio_data.size(); ++i)
audio_data[i] = bus1->channel(i);
diff --git a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc
index a70ad2adbb8..14bbc8d5fe9 100644
--- a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc
+++ b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc
@@ -31,37 +31,48 @@ class SessionIdAdapter {
bool Initialize(const std::string& key_system,
scoped_ptr<media::MediaKeys>* media_keys);
+ // Generates a unique internal session id.
+ uint32 GenerateSessionId();
+
// Adds a session to the internal map. Does not take ownership of the session.
- void AddSession(const std::string& session_id,
+ void AddSession(uint32 session_id,
WebContentDecryptionModuleSessionImpl* session);
// Removes a session from the internal map.
- void RemoveSession(const std::string& session_id);
+ void RemoveSession(uint32 session_id);
private:
- typedef std::map<std::string, WebContentDecryptionModuleSessionImpl*>
- SessionMap;
-
- // Callbacks for firing key events.
- void KeyAdded(const std::string& session_id);
- void KeyError(const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- int system_code);
- void KeyMessage(const std::string& session_id,
- const std::vector<uint8>& message,
- const std::string& destination_url);
+ typedef std::map<uint32, WebContentDecryptionModuleSessionImpl*> SessionMap;
+
+ // Callbacks for firing session events.
+ void OnSessionCreated(uint32 session_id, const std::string& web_session_id);
+ void OnSessionMessage(uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url);
+ void OnSessionReady(uint32 session_id);
+ void OnSessionClosed(uint32 session_id);
+ void OnSessionError(uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code);
// Helper function of the callbacks.
- WebContentDecryptionModuleSessionImpl* GetSession(
- const std::string& session_id);
+ WebContentDecryptionModuleSessionImpl* GetSession(uint32 session_id);
base::WeakPtrFactory<SessionIdAdapter> weak_ptr_factory_;
SessionMap sessions_;
+ // Session ID should be unique per renderer process for debugging purposes.
+ static uint32 next_session_id_;
+
DISALLOW_COPY_AND_ASSIGN(SessionIdAdapter);
};
+const uint32 kStartingSessionId = 1;
+uint32 SessionIdAdapter::next_session_id_ = kStartingSessionId;
+COMPILE_ASSERT(kStartingSessionId > media::MediaKeys::kInvalidSessionId,
+ invalid_starting_value);
+
SessionIdAdapter::SessionIdAdapter()
: weak_ptr_factory_(this) {
}
@@ -91,9 +102,11 @@ bool SessionIdAdapter::Initialize(const std::string& key_system,
// TODO(ddorwin): Get the URL for the frame containing the MediaKeys.
GURL(),
#endif // defined(ENABLE_PEPPER_CDMS)
- base::Bind(&SessionIdAdapter::KeyAdded, weak_this),
- base::Bind(&SessionIdAdapter::KeyError, weak_this),
- base::Bind(&SessionIdAdapter::KeyMessage, weak_this));
+ base::Bind(&SessionIdAdapter::OnSessionCreated, weak_this),
+ base::Bind(&SessionIdAdapter::OnSessionMessage, weak_this),
+ base::Bind(&SessionIdAdapter::OnSessionReady, weak_this),
+ base::Bind(&SessionIdAdapter::OnSessionClosed, weak_this),
+ base::Bind(&SessionIdAdapter::OnSessionError, weak_this));
if (!created_media_keys)
return false;
@@ -101,47 +114,57 @@ bool SessionIdAdapter::Initialize(const std::string& key_system,
return true;
}
+uint32 SessionIdAdapter::GenerateSessionId() {
+ return next_session_id_++;
+}
+
void SessionIdAdapter::AddSession(
- const std::string& session_id,
+ uint32 session_id,
WebContentDecryptionModuleSessionImpl* session) {
DCHECK(sessions_.find(session_id) == sessions_.end());
sessions_[session_id] = session;
}
-void SessionIdAdapter::RemoveSession(const std::string& session_id) {
+void SessionIdAdapter::RemoveSession(uint32 session_id) {
DCHECK(sessions_.find(session_id) != sessions_.end());
sessions_.erase(session_id);
}
-void SessionIdAdapter::KeyAdded(const std::string& session_id) {
- GetSession(session_id)->KeyAdded();
+void SessionIdAdapter::OnSessionCreated(uint32 session_id,
+ const std::string& web_session_id) {
+ GetSession(session_id)->OnSessionCreated(web_session_id);
}
-void SessionIdAdapter::KeyError(const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- int system_code) {
- GetSession(session_id)->KeyError(error_code, system_code);
+void SessionIdAdapter::OnSessionMessage(uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& destination_url) {
+ GetSession(session_id)->OnSessionMessage(message, destination_url);
}
-void SessionIdAdapter::KeyMessage(const std::string& session_id,
- const std::vector<uint8>& message,
- const std::string& destination_url) {
- GetSession(session_id)->KeyMessage(message, destination_url);
+void SessionIdAdapter::OnSessionReady(uint32 session_id) {
+ GetSession(session_id)->OnSessionReady();
+}
+
+void SessionIdAdapter::OnSessionClosed(uint32 session_id) {
+ GetSession(session_id)->OnSessionClosed();
+}
+
+void SessionIdAdapter::OnSessionError(uint32 session_id,
+ media::MediaKeys::KeyError error_code,
+ int system_code) {
+ GetSession(session_id)->OnSessionError(error_code, system_code);
}
WebContentDecryptionModuleSessionImpl* SessionIdAdapter::GetSession(
- const std::string& session_id) {
- // TODO(ddorwin): Map session IDs correctly. For now, we only support one.
- std::string session_object_id = "";
- WebContentDecryptionModuleSessionImpl* session = sessions_[session_object_id];
- DCHECK(session); // It must have been present.
- return session;
+ uint32 session_id) {
+ DCHECK(sessions_.find(session_id) != sessions_.end());
+ return sessions_[session_id];
}
//------------------------------------------------------------------------------
WebContentDecryptionModuleImpl*
-WebContentDecryptionModuleImpl::Create(const string16& key_system) {
+WebContentDecryptionModuleImpl::Create(const base::string16& key_system) {
// TODO(ddorwin): Guard against this in supported types check and remove this.
// Chromium only supports ASCII key systems.
if (!IsStringASCII(key_system)) {
@@ -170,24 +193,24 @@ WebContentDecryptionModuleImpl::~WebContentDecryptionModuleImpl() {
}
// The caller owns the created session.
-WebKit::WebContentDecryptionModuleSession*
+blink::WebContentDecryptionModuleSession*
WebContentDecryptionModuleImpl::createSession(
- WebKit::WebContentDecryptionModuleSession::Client* client) {
+ blink::WebContentDecryptionModuleSession::Client* client) {
DCHECK(media_keys_);
+ uint32 session_id = adapter_->GenerateSessionId();
WebContentDecryptionModuleSessionImpl* session =
new WebContentDecryptionModuleSessionImpl(
+ session_id,
media_keys_.get(),
client,
base::Bind(&WebContentDecryptionModuleImpl::OnSessionClosed,
base::Unretained(this)));
- // TODO(ddorwin): session_id is not populated yet!
- adapter_->AddSession(session->session_id(), session);
+ adapter_->AddSession(session_id, session);
return session;
}
-void WebContentDecryptionModuleImpl::OnSessionClosed(
- const std::string& session_id) {
+void WebContentDecryptionModuleImpl::OnSessionClosed(uint32 session_id) {
adapter_->RemoveSession(session_id);
}
diff --git a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h
index d2aa01fa1bf..ecd5198efda 100644
--- a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h
+++ b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h
@@ -21,15 +21,16 @@ class WebContentDecryptionModuleSessionImpl;
class SessionIdAdapter;
class WebContentDecryptionModuleImpl
- : public WebKit::WebContentDecryptionModule {
+ : public blink::WebContentDecryptionModule {
public:
- static WebContentDecryptionModuleImpl* Create(const string16& key_system);
+ static WebContentDecryptionModuleImpl* Create(
+ const base::string16& key_system);
virtual ~WebContentDecryptionModuleImpl();
- // WebKit::WebContentDecryptionModule implementation.
- virtual WebKit::WebContentDecryptionModuleSession* createSession(
- WebKit::WebContentDecryptionModuleSession::Client* client);
+ // blink::WebContentDecryptionModule implementation.
+ virtual blink::WebContentDecryptionModuleSession* createSession(
+ blink::WebContentDecryptionModuleSession::Client* client);
private:
// Takes ownership of |media_keys| and |adapter|.
@@ -37,7 +38,7 @@ class WebContentDecryptionModuleImpl
scoped_ptr<SessionIdAdapter> adapter);
// Called when a WebContentDecryptionModuleSessionImpl is closed.
- void OnSessionClosed(const std::string& session_id);
+ void OnSessionClosed(uint32 session_id);
scoped_ptr<media::MediaKeys> media_keys_;
scoped_ptr<SessionIdAdapter> adapter_;
diff --git a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc
index b1dea741d5a..bc74d35dc6a 100644
--- a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc
+++ b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc
@@ -12,70 +12,87 @@
namespace content {
WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
+ uint32 session_id,
media::MediaKeys* media_keys,
Client* client,
const SessionClosedCB& session_closed_cb)
: media_keys_(media_keys),
client_(client),
- session_closed_cb_(session_closed_cb) {
+ session_closed_cb_(session_closed_cb),
+ session_id_(session_id) {
DCHECK(media_keys_);
- // TODO(ddorwin): Populate session_id_ from the real implementation.
}
WebContentDecryptionModuleSessionImpl::
~WebContentDecryptionModuleSessionImpl() {
}
-WebKit::WebString WebContentDecryptionModuleSessionImpl::sessionId() const {
- return WebKit::WebString::fromUTF8(session_id_);
+blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const {
+ return web_session_id_;
}
void WebContentDecryptionModuleSessionImpl::generateKeyRequest(
- const WebKit::WebString& mime_type,
+ const blink::WebString& mime_type,
const uint8* init_data, size_t init_data_length) {
// TODO(ddorwin): Guard against this in supported types check and remove this.
// Chromium only supports ASCII MIME types.
if (!IsStringASCII(mime_type)) {
NOTREACHED();
- KeyError(media::MediaKeys::kUnknownError, 0);
+ OnSessionError(media::MediaKeys::kUnknownError, 0);
return;
}
- media_keys_->GenerateKeyRequest(UTF16ToASCII(mime_type),
- init_data, init_data_length);
+ media_keys_->CreateSession(
+ session_id_, UTF16ToASCII(mime_type), init_data, init_data_length);
}
-void WebContentDecryptionModuleSessionImpl::update(const uint8* key,
- size_t key_length) {
- DCHECK(key);
- media_keys_->AddKey(key, key_length, NULL, 0, session_id_);
+void WebContentDecryptionModuleSessionImpl::update(const uint8* response,
+ size_t response_length) {
+ DCHECK(response);
+ media_keys_->UpdateSession(session_id_, response, response_length);
}
void WebContentDecryptionModuleSessionImpl::close() {
- media_keys_->CancelKeyRequest(session_id_);
+ media_keys_->ReleaseSession(session_id_);
+}
- // Detach from the CDM.
- if (!session_closed_cb_.is_null())
- base::ResetAndReturn(&session_closed_cb_).Run(session_id_);
+void WebContentDecryptionModuleSessionImpl::OnSessionCreated(
+ const std::string& web_session_id) {
+ // Due to heartbeat messages, OnSessionCreated() can get called multiple
+ // times.
+ // TODO(jrummell): Once all CDMs are updated to support reference ids,
+ // OnSessionCreated() should only be called once, and the second check can be
+ // removed.
+ blink::WebString id = blink::WebString::fromUTF8(web_session_id);
+ DCHECK(web_session_id_.isEmpty() || web_session_id_ == id)
+ << "Session ID may not be changed once set.";
+ web_session_id_ = id;
}
-void WebContentDecryptionModuleSessionImpl::KeyAdded() {
+void WebContentDecryptionModuleSessionImpl::OnSessionMessage(
+ const std::vector<uint8>& message,
+ const std::string& destination_url) {
+ client_->keyMessage(message.empty() ? NULL : &message[0],
+ message.size(),
+ GURL(destination_url));
+}
+
+void WebContentDecryptionModuleSessionImpl::OnSessionReady() {
+ // TODO(jrummell): Blink APIs need to be updated to the new EME API. For now,
+ // convert the response to the old v0.1b API.
client_->keyAdded();
}
-void WebContentDecryptionModuleSessionImpl::KeyError(
+void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
+ if (!session_closed_cb_.is_null())
+ base::ResetAndReturn(&session_closed_cb_).Run(session_id_);
+}
+
+void WebContentDecryptionModuleSessionImpl::OnSessionError(
media::MediaKeys::KeyError error_code,
int system_code) {
client_->keyError(static_cast<Client::MediaKeyErrorCode>(error_code),
system_code);
}
-void WebContentDecryptionModuleSessionImpl::KeyMessage(
- const std::vector<uint8>& message,
- const std::string& destination_url) {
- client_->keyMessage(message.empty() ? NULL : &message[0],
- message.size(),
- GURL(destination_url));
-}
-
} // namespace content
diff --git a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h
index df76f08de5f..6ff091c876a 100644
--- a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h
+++ b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h
@@ -21,31 +21,32 @@ class MediaKeys;
namespace content {
class WebContentDecryptionModuleSessionImpl
- : public WebKit::WebContentDecryptionModuleSession {
+ : public blink::WebContentDecryptionModuleSession {
public:
- typedef base::Callback<void(const std::string& session_id)> SessionClosedCB;
+ typedef base::Callback<void(uint32 session_id)> SessionClosedCB;
WebContentDecryptionModuleSessionImpl(
+ uint32 session_id,
media::MediaKeys* media_keys,
Client* client,
const SessionClosedCB& session_closed_cb);
virtual ~WebContentDecryptionModuleSessionImpl();
- // WebKit::WebContentDecryptionModuleSession implementation.
- virtual WebKit::WebString sessionId() const OVERRIDE;
- virtual void generateKeyRequest(const WebKit::WebString& mime_type,
+ // blink::WebContentDecryptionModuleSession implementation.
+ virtual blink::WebString sessionId() const OVERRIDE;
+ virtual void generateKeyRequest(const blink::WebString& mime_type,
const uint8* init_data,
size_t init_data_length) OVERRIDE;
- virtual void update(const uint8* key, size_t key_length) OVERRIDE;
+ virtual void update(const uint8* response, size_t response_length) OVERRIDE;
virtual void close() OVERRIDE;
- const std::string& session_id() const { return session_id_; }
-
// Callbacks.
- void KeyAdded();
- void KeyError(media::MediaKeys::KeyError error_code, int system_code);
- void KeyMessage(const std::vector<uint8>& message,
- const std::string& destination_url);
+ void OnSessionCreated(const std::string& web_session_id);
+ void OnSessionMessage(const std::vector<uint8>& message,
+ const std::string& destination_url);
+ void OnSessionReady();
+ void OnSessionClosed();
+ void OnSessionError(media::MediaKeys::KeyError error_code, int system_code);
private:
// Non-owned pointers.
@@ -54,7 +55,13 @@ class WebContentDecryptionModuleSessionImpl
SessionClosedCB session_closed_cb_;
- std::string session_id_;
+ // Web session ID is the app visible ID for this session generated by the CDM.
+ // This value is not set until the CDM calls OnSessionCreated().
+ blink::WebString web_session_id_;
+
+ // Session ID is used to uniquely track this object so that CDM callbacks
+ // can get routed to the correct object.
+ const uint32 session_id_;
DISALLOW_COPY_AND_ASSIGN(WebContentDecryptionModuleSessionImpl);
};
diff --git a/chromium/content/renderer/media/webinbandtexttrack_impl.cc b/chromium/content/renderer/media/webinbandtexttrack_impl.cc
index 6d1de2610c8..e83af8f3451 100644
--- a/chromium/content/renderer/media/webinbandtexttrack_impl.cc
+++ b/chromium/content/renderer/media/webinbandtexttrack_impl.cc
@@ -10,14 +10,15 @@ namespace content {
WebInbandTextTrackImpl::WebInbandTextTrackImpl(
Kind kind,
- const WebKit::WebString& label,
- const WebKit::WebString& language,
+ const blink::WebString& label,
+ const blink::WebString& language,
+ const blink::WebString& id,
int index)
: client_(NULL),
- mode_(ModeDisabled),
kind_(kind),
label_(label),
language_(language),
+ id_(id),
index_(index) {
}
@@ -26,47 +27,28 @@ WebInbandTextTrackImpl::~WebInbandTextTrackImpl() {
}
void WebInbandTextTrackImpl::setClient(
- WebKit::WebInbandTextTrackClient* client) {
+ blink::WebInbandTextTrackClient* client) {
client_ = client;
}
-WebKit::WebInbandTextTrackClient* WebInbandTextTrackImpl::client() {
+blink::WebInbandTextTrackClient* WebInbandTextTrackImpl::client() {
return client_;
}
-void WebInbandTextTrackImpl::setMode(Mode mode) {
- mode_ = mode;
-}
-
-WebInbandTextTrackImpl::Mode WebInbandTextTrackImpl::mode() const {
- return mode_;
-}
-
WebInbandTextTrackImpl::Kind WebInbandTextTrackImpl::kind() const {
return kind_;
}
-bool WebInbandTextTrackImpl::isClosedCaptions() const {
- switch (kind_) {
- case KindCaptions:
- case KindSubtitles:
- return true;
-
- default:
- return false;
- }
-}
-
-WebKit::WebString WebInbandTextTrackImpl::label() const {
+blink::WebString WebInbandTextTrackImpl::label() const {
return label_;
}
-WebKit::WebString WebInbandTextTrackImpl::language() const {
+blink::WebString WebInbandTextTrackImpl::language() const {
return language_;
}
-bool WebInbandTextTrackImpl::isDefault() const {
- return false;
+blink::WebString WebInbandTextTrackImpl::id() const {
+ return id_;
}
int WebInbandTextTrackImpl::textTrackIndex() const {
diff --git a/chromium/content/renderer/media/webinbandtexttrack_impl.h b/chromium/content/renderer/media/webinbandtexttrack_impl.h
index 82b94adbdbc..293fbd3fac9 100644
--- a/chromium/content/renderer/media/webinbandtexttrack_impl.h
+++ b/chromium/content/renderer/media/webinbandtexttrack_impl.h
@@ -5,40 +5,37 @@
#ifndef CONTENT_RENDERER_MEDIA_WEBINBANDTEXTTRACK_IMPL_H_
#define CONTENT_RENDERER_MEDIA_WEBINBANDTEXTTRACK_IMPL_H_
+#include "third_party/WebKit/public/platform/WebInbandTextTrack.h"
#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/web/WebInbandTextTrack.h"
namespace content {
-class WebInbandTextTrackImpl : public WebKit::WebInbandTextTrack {
+class WebInbandTextTrackImpl : public blink::WebInbandTextTrack {
public:
WebInbandTextTrackImpl(Kind kind,
- const WebKit::WebString& label,
- const WebKit::WebString& language,
+ const blink::WebString& label,
+ const blink::WebString& language,
+ const blink::WebString& id,
int index);
virtual ~WebInbandTextTrackImpl();
- virtual void setClient(WebKit::WebInbandTextTrackClient* client);
- virtual WebKit::WebInbandTextTrackClient* client();
-
- virtual void setMode(Mode mode);
- virtual Mode mode() const;
+ virtual void setClient(blink::WebInbandTextTrackClient* client);
+ virtual blink::WebInbandTextTrackClient* client();
virtual Kind kind() const;
- virtual bool isClosedCaptions() const;
- virtual WebKit::WebString label() const;
- virtual WebKit::WebString language() const;
- virtual bool isDefault() const;
+ virtual blink::WebString label() const;
+ virtual blink::WebString language() const;
+ virtual blink::WebString id() const;
virtual int textTrackIndex() const;
private:
- WebKit::WebInbandTextTrackClient* client_;
- Mode mode_;
+ blink::WebInbandTextTrackClient* client_;
Kind kind_;
- WebKit::WebString label_;
- WebKit::WebString language_;
+ blink::WebString label_;
+ blink::WebString language_;
+ blink::WebString id_;
int index_;
DISALLOW_COPY_AND_ASSIGN(WebInbandTextTrackImpl);
};
diff --git a/chromium/content/renderer/media/webmediaplayer_delegate.h b/chromium/content/renderer/media/webmediaplayer_delegate.h
index 63492f8c5f3..868abce6407 100644
--- a/chromium/content/renderer/media/webmediaplayer_delegate.h
+++ b/chromium/content/renderer/media/webmediaplayer_delegate.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_DELEGATE_H_
#define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_DELEGATE_H_
-namespace WebKit {
+namespace blink {
class WebMediaPlayer;
}
namespace content {
@@ -17,13 +17,13 @@ class WebMediaPlayerDelegate {
WebMediaPlayerDelegate() {}
// The specified player started playing media.
- virtual void DidPlay(WebKit::WebMediaPlayer* player) = 0;
+ virtual void DidPlay(blink::WebMediaPlayer* player) = 0;
// The specified player stopped playing media.
- virtual void DidPause(WebKit::WebMediaPlayer* player) = 0;
+ virtual void DidPause(blink::WebMediaPlayer* player) = 0;
// The specified player was destroyed. Do not call any methods on it.
- virtual void PlayerGone(WebKit::WebMediaPlayer* player) = 0;
+ virtual void PlayerGone(blink::WebMediaPlayer* player) = 0;
protected:
virtual ~WebMediaPlayerDelegate() {}
diff --git a/chromium/content/renderer/media/webmediaplayer_impl.cc b/chromium/content/renderer/media/webmediaplayer_impl.cc
index 7bb1937af4e..ee637a6879a 100644
--- a/chromium/content/renderer/media/webmediaplayer_impl.cc
+++ b/chromium/content/renderer/media/webmediaplayer_impl.cc
@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/debug/crash_logging.h"
+#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
@@ -37,6 +38,7 @@
#include "media/base/media_log.h"
#include "media/base/media_switches.h"
#include "media/base/pipeline.h"
+#include "media/base/text_renderer.h"
#include "media/base/video_frame.h"
#include "media/filters/audio_renderer_impl.h"
#include "media/filters/chunk_demuxer.h"
@@ -46,7 +48,7 @@
#include "media/filters/gpu_video_accelerator_factories.h"
#include "media/filters/gpu_video_decoder.h"
#include "media/filters/opus_audio_decoder.h"
-#include "media/filters/video_renderer_base.h"
+#include "media/filters/video_renderer_impl.h"
#include "media/filters/vpx_video_decoder.h"
#include "third_party/WebKit/public/platform/WebMediaSource.h"
#include "third_party/WebKit/public/platform/WebRect.h"
@@ -59,11 +61,11 @@
#include "v8/include/v8.h"
#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
-using WebKit::WebCanvas;
-using WebKit::WebMediaPlayer;
-using WebKit::WebRect;
-using WebKit::WebSize;
-using WebKit::WebString;
+using blink::WebCanvas;
+using blink::WebMediaPlayer;
+using blink::WebRect;
+using blink::WebSize;
+using blink::WebString;
using media::PipelineStatus;
namespace {
@@ -128,11 +130,13 @@ static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log,
}
WebMediaPlayerImpl::WebMediaPlayerImpl(
- WebKit::WebFrame* frame,
- WebKit::WebMediaPlayerClient* client,
+ content::RenderView* render_view,
+ blink::WebFrame* frame,
+ blink::WebMediaPlayerClient* client,
base::WeakPtr<WebMediaPlayerDelegate> delegate,
const WebMediaPlayerParams& params)
- : frame_(frame),
+ : content::RenderViewObserver(render_view),
+ frame_(frame),
network_state_(WebMediaPlayer::NetworkStateEmpty),
ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
main_loop_(base::MessageLoopProxy::current()),
@@ -153,6 +157,8 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
supports_save_(true),
starting_(false),
chunk_demuxer_(NULL),
+ current_frame_painted_(false),
+ frames_dropped_before_paint_(0),
pending_repaint_(false),
pending_size_change_(false),
video_frame_provider_client_(NULL),
@@ -162,6 +168,11 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
pipeline_.reset(new media::Pipeline(media_loop_, media_log_.get()));
+ // |gpu_factories_| requires that its entry points be called on its
+ // |GetMessageLoop()|. Since |pipeline_| will own decoders created from the
+ // factories, require that their message loops are identical.
+ DCHECK(!gpu_factories_ || (gpu_factories_->GetMessageLoop() == media_loop_));
+
// Let V8 know we started new thread if we did not do it yet.
// Made separate task to avoid deletion of player currently being created.
// Also, delaying GC until after player starts gets rid of starting lag --
@@ -173,10 +184,7 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
base::Bind(&WebMediaPlayerImpl::IncrementExternallyAllocatedMemory,
AsWeakPtr()));
- // Also we want to be notified of |main_loop_| destruction.
- base::MessageLoop::current()->AddDestructionObserver(this);
-
- if (WebKit::WebRuntimeFeatures::isLegacyEncryptedMediaEnabled()) {
+ if (blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled()) {
decryptor_.reset(new ProxyDecryptor(
#if defined(ENABLE_PEPPER_CDMS)
client,
@@ -206,11 +214,6 @@ WebMediaPlayerImpl::~WebMediaPlayerImpl() {
delegate_->PlayerGone(this);
Destroy();
-
- // Remove destruction observer if we're being destroyed but the main thread is
- // still running.
- if (base::MessageLoop::current())
- base::MessageLoop::current()->RemoveDestructionObserver(this);
}
namespace {
@@ -247,7 +250,7 @@ URLSchemeForHistogram URLScheme(const GURL& url) {
} // anonymous namespace
-void WebMediaPlayerImpl::load(LoadType load_type, const WebKit::WebURL& url,
+void WebMediaPlayerImpl::load(LoadType load_type, const blink::WebURL& url,
CORSMode cors_mode) {
if (!defer_load_cb_.is_null()) {
defer_load_cb_.Run(base::Bind(
@@ -258,7 +261,7 @@ void WebMediaPlayerImpl::load(LoadType load_type, const WebKit::WebURL& url,
}
void WebMediaPlayerImpl::DoLoad(LoadType load_type,
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
CORSMode cors_mode) {
DCHECK(main_loop_->BelongsToCurrentThread());
@@ -305,6 +308,8 @@ void WebMediaPlayerImpl::play() {
paused_ = false;
pipeline_->SetPlaybackRate(playback_rate_);
+ if (data_source_)
+ data_source_->MediaIsPlaying();
media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY));
@@ -317,6 +322,8 @@ void WebMediaPlayerImpl::pause() {
paused_ = true;
pipeline_->SetPlaybackRate(0.0f);
+ if (data_source_)
+ data_source_->MediaIsPaused();
paused_time_ = pipeline_->GetMediaTime();
media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
@@ -338,6 +345,9 @@ bool WebMediaPlayerImpl::supportsSave() const {
void WebMediaPlayerImpl::seek(double seconds) {
DCHECK(main_loop_->BelongsToCurrentThread());
+ if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
+ SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
+
base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
if (starting_ || seeking_) {
@@ -384,6 +394,8 @@ void WebMediaPlayerImpl::setRate(double rate) {
playback_rate_ = rate;
if (!paused_) {
pipeline_->SetPlaybackRate(rate);
+ if (data_source_)
+ data_source_->MediaPlaybackRateChanged(rate);
}
}
@@ -421,12 +433,12 @@ bool WebMediaPlayerImpl::hasAudio() const {
return pipeline_->HasAudio();
}
-WebKit::WebSize WebMediaPlayerImpl::naturalSize() const {
+blink::WebSize WebMediaPlayerImpl::naturalSize() const {
DCHECK(main_loop_->BelongsToCurrentThread());
gfx::Size size;
pipeline_->GetNaturalVideoSize(&size);
- return WebKit::WebSize(size);
+ return blink::WebSize(size);
}
bool WebMediaPlayerImpl::paused() const {
@@ -468,9 +480,9 @@ WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
return ready_state_;
}
-const WebKit::WebTimeRanges& WebMediaPlayerImpl::buffered() {
+const blink::WebTimeRanges& WebMediaPlayerImpl::buffered() {
DCHECK(main_loop_->BelongsToCurrentThread());
- WebKit::WebTimeRanges web_ranges(
+ blink::WebTimeRanges web_ranges(
ConvertToWebTimeRanges(pipeline_->GetBufferedTimeRanges()));
buffered_.swap(web_ranges);
return buffered_;
@@ -515,8 +527,10 @@ void WebMediaPlayerImpl::paint(WebCanvas* canvas,
scoped_refptr<media::VideoFrame> video_frame;
{
base::AutoLock auto_lock(lock_);
+ DoneWaitingForPaint(true);
video_frame = current_frame_;
}
+ TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
gfx::Rect gfx_rect(rect);
skcanvas_video_renderer_.Paint(video_frame.get(), canvas, gfx_rect, alpha);
}
@@ -548,7 +562,12 @@ unsigned WebMediaPlayerImpl::droppedFrameCount() const {
DCHECK(main_loop_->BelongsToCurrentThread());
media::PipelineStatistics stats = pipeline_->GetStatistics();
- return stats.video_frames_dropped;
+
+ base::AutoLock auto_lock(lock_);
+ unsigned frames_dropped =
+ stats.video_frames_dropped + frames_dropped_before_paint_;
+ DCHECK_LE(frames_dropped, stats.video_frames_decoded);
+ return frames_dropped;
}
unsigned WebMediaPlayerImpl::audioDecodedByteCount() const {
@@ -576,6 +595,9 @@ void WebMediaPlayerImpl::SetVideoFrameProviderClient(
scoped_refptr<media::VideoFrame> WebMediaPlayerImpl::GetCurrentFrame() {
base::AutoLock auto_lock(lock_);
+ DoneWaitingForPaint(true);
+ TRACE_EVENT_ASYNC_BEGIN0(
+ "media", "WebMediaPlayerImpl:compositing", this);
return current_frame_;
}
@@ -586,10 +608,11 @@ void WebMediaPlayerImpl::PutCurrentFrame(
DCHECK(frame_->view()->isAcceleratedCompositingActive());
UMA_HISTOGRAM_BOOLEAN("Media.AcceleratedCompositingActive", true);
}
+ TRACE_EVENT_ASYNC_END0("media", "WebMediaPlayerImpl:compositing", this);
}
bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
- WebKit::WebGraphicsContext3D* web_graphics_context,
+ blink::WebGraphicsContext3D* web_graphics_context,
unsigned int texture,
unsigned int level,
unsigned int internal_format,
@@ -602,7 +625,9 @@ bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
video_frame = current_frame_;
}
- if (!video_frame.get())
+ TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
+
+ if (!video_frame)
return false;
if (video_frame->format() != media::VideoFrame::NATIVE_TEXTURE)
return false;
@@ -621,7 +646,7 @@ bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
DCHECK_EQ(static_cast<GLuint>(bound_texture), texture);
}
- scoped_refptr<media::VideoFrame::MailboxHolder> mailbox_holder =
+ media::VideoFrame::MailboxHolder* mailbox_holder =
video_frame->texture_mailbox();
uint32 source_texture = web_graphics_context->createTexture();
@@ -666,7 +691,7 @@ bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
// UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is
// that UMA_* macros require the names to be constant throughout the process'
// lifetime.
-static void EmeUMAHistogramEnumeration(const WebKit::WebString& key_system,
+static void EmeUMAHistogramEnumeration(const blink::WebString& key_system,
const std::string& method,
int sample,
int boundary_value) {
@@ -676,7 +701,7 @@ static void EmeUMAHistogramEnumeration(const WebKit::WebString& key_system,
base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
}
-static void EmeUMAHistogramCounts(const WebKit::WebString& key_system,
+static void EmeUMAHistogramCounts(const blink::WebString& key_system,
const std::string& method,
int sample) {
// Use the same parameters as UMA_HISTOGRAM_COUNTS.
@@ -828,23 +853,31 @@ WebMediaPlayerImpl::CancelKeyRequestInternal(
return WebMediaPlayer::MediaKeyExceptionNoError;
}
-void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() {
+void WebMediaPlayerImpl::OnDestruct() {
Destroy();
}
void WebMediaPlayerImpl::Repaint() {
DCHECK(main_loop_->BelongsToCurrentThread());
+ TRACE_EVENT0("media", "WebMediaPlayerImpl:repaint");
bool size_changed = false;
{
base::AutoLock auto_lock(lock_);
std::swap(pending_size_change_, size_changed);
- pending_repaint_ = false;
+ if (pending_repaint_) {
+ TRACE_EVENT_ASYNC_END0(
+ "media", "WebMediaPlayerImpl:repaintPending", this);
+ pending_repaint_ = false;
+ }
}
- if (size_changed)
+ if (size_changed) {
+ TRACE_EVENT0("media", "WebMediaPlayerImpl:clientSizeChanged");
GetClient()->sizeChanged();
+ }
+ TRACE_EVENT0("media", "WebMediaPlayerImpl:clientRepaint");
GetClient()->repaint();
}
@@ -937,8 +970,7 @@ void WebMediaPlayerImpl::OnKeyAdded(const std::string& session_id) {
WebString::fromUTF8(session_id));
}
-void WebMediaPlayerImpl::OnNeedKey(const std::string& session_id,
- const std::string& type,
+void WebMediaPlayerImpl::OnNeedKey(const std::string& type,
const std::vector<uint8>& init_data) {
DCHECK(main_loop_->BelongsToCurrentThread());
@@ -954,26 +986,33 @@ void WebMediaPlayerImpl::OnNeedKey(const std::string& session_id,
const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
GetClient()->keyNeeded(WebString(),
- WebString::fromUTF8(session_id),
+ WebString(),
init_data_ptr,
init_data.size());
}
-scoped_ptr<media::TextTrack>
-WebMediaPlayerImpl::OnTextTrack(media::TextKind kind,
- const std::string& label,
- const std::string& language) {
- typedef WebInbandTextTrackImpl::Kind webkind_t;
- const webkind_t webkind = static_cast<webkind_t>(kind);
- const WebKit::WebString weblabel = WebKit::WebString::fromUTF8(label);
- const WebKit::WebString weblanguage = WebKit::WebString::fromUTF8(language);
+void WebMediaPlayerImpl::OnAddTextTrack(
+ const media::TextTrackConfig& config,
+ const media::AddTextTrackDoneCB& done_cb) {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+
+ const WebInbandTextTrackImpl::Kind web_kind =
+ static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
+ const blink::WebString web_label =
+ blink::WebString::fromUTF8(config.label());
+ const blink::WebString web_language =
+ blink::WebString::fromUTF8(config.language());
+ const blink::WebString web_id =
+ blink::WebString::fromUTF8(config.id());
+
+ scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track(
+ new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id,
+ text_track_index_++));
- WebInbandTextTrackImpl* const text_track =
- new WebInbandTextTrackImpl(webkind, weblabel, weblanguage,
- text_track_index_++);
+ scoped_ptr<media::TextTrack> text_track(
+ new TextTrackImpl(main_loop_, GetClient(), web_inband_text_track.Pass()));
- return scoped_ptr<media::TextTrack>(new TextTrackImpl(GetClient(),
- text_track));
+ done_cb.Run(text_track.Pass());
}
void WebMediaPlayerImpl::OnKeyError(const std::string& session_id,
@@ -987,7 +1026,7 @@ void WebMediaPlayerImpl::OnKeyError(const std::string& session_id,
GetClient()->keyError(
current_key_system_,
WebString::fromUTF8(session_id),
- static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
+ static_cast<blink::WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
system_code);
}
@@ -1038,7 +1077,6 @@ void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
void WebMediaPlayerImpl::StartPipeline() {
const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
- bool increase_preroll_on_underflow = true;
// Keep track if this is a MSE or non-MSE playback.
UMA_HISTOGRAM_BOOLEAN("Media.MSE.Playback",
@@ -1051,38 +1089,17 @@ void WebMediaPlayerImpl::StartPipeline() {
demuxer_.reset(new media::FFmpegDemuxer(
media_loop_, data_source_.get(),
- BIND_TO_RENDER_LOOP_1(&WebMediaPlayerImpl::OnNeedKey, ""),
+ BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNeedKey),
media_log_));
} else {
DCHECK(!chunk_demuxer_);
DCHECK(!data_source_);
- media::AddTextTrackCB add_text_track_cb;
-
- if (cmd_line->HasSwitch(switches::kEnableInbandTextTracks)) {
- add_text_track_cb =
- base::Bind(&WebMediaPlayerImpl::OnTextTrack, base::Unretained(this));
- }
-
chunk_demuxer_ = new media::ChunkDemuxer(
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
- BIND_TO_RENDER_LOOP_1(&WebMediaPlayerImpl::OnNeedKey, ""),
- add_text_track_cb,
+ BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNeedKey),
base::Bind(&LogMediaSourceError, media_log_));
demuxer_.reset(chunk_demuxer_);
-
-#if !defined(OS_CHROMEOS)
- // Disable GpuVideoDecoder creation on platforms other than CrOS until
- // they support codec config changes.
- // TODO(acolwell): Remove this once http://crbug.com/151045 is fixed.
- gpu_factories_ = NULL;
-#endif
-
- // Disable preroll increases on underflow since the web application has no
- // way to detect that this is happening and runs the risk of triggering
- // unwanted garbage collection if it is to aggressive about appending data.
- // TODO(acolwell): Remove this once http://crbug.com/144683 is fixed.
- increase_preroll_on_underflow = false;
}
scoped_ptr<media::FilterCollection> filter_collection(
@@ -1099,7 +1116,7 @@ void WebMediaPlayerImpl::StartPipeline() {
// Create our audio decoders and renderer.
ScopedVector<media::AudioDecoder> audio_decoders;
audio_decoders.push_back(new media::FFmpegAudioDecoder(media_loop_));
- if (cmd_line->HasSwitch(switches::kEnableOpusPlayback)) {
+ if (!cmd_line->HasSwitch(switches::kDisableOpusPlayback)) {
audio_decoders.push_back(new media::OpusAudioDecoder(media_loop_));
}
@@ -1107,8 +1124,7 @@ void WebMediaPlayerImpl::StartPipeline() {
new media::AudioRendererImpl(media_loop_,
audio_source_provider_.get(),
audio_decoders.Pass(),
- set_decryptor_ready_cb,
- increase_preroll_on_underflow));
+ set_decryptor_ready_cb));
filter_collection->SetAudioRenderer(audio_renderer.Pass());
// Create our video decoders and renderer.
@@ -1119,8 +1135,6 @@ void WebMediaPlayerImpl::StartPipeline() {
new media::GpuVideoDecoder(gpu_factories_, media_log_));
}
- // TODO(phajdan.jr): Remove ifdefs when libvpx with vp9 support is released
- // (http://crbug.com/174287) .
#if !defined(MEDIA_DISABLE_LIBVPX)
video_decoders.push_back(new media::VpxVideoDecoder(media_loop_));
#endif // !defined(MEDIA_DISABLE_LIBVPX)
@@ -1128,7 +1142,7 @@ void WebMediaPlayerImpl::StartPipeline() {
video_decoders.push_back(new media::FFmpegVideoDecoder(media_loop_));
scoped_ptr<media::VideoRenderer> video_renderer(
- new media::VideoRendererBase(
+ new media::VideoRendererImpl(
media_loop_,
video_decoders.Pass(),
set_decryptor_ready_cb,
@@ -1137,6 +1151,15 @@ void WebMediaPlayerImpl::StartPipeline() {
true));
filter_collection->SetVideoRenderer(video_renderer.Pass());
+ if (cmd_line->HasSwitch(switches::kEnableInbandTextTracks)) {
+ scoped_ptr<media::TextRenderer> text_renderer(
+ new media::TextRenderer(
+ media_loop_,
+ BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack)));
+
+ filter_collection->SetTextRenderer(text_renderer.Pass());
+ }
+
// ... and we're ready to go!
starting_ = true;
pipeline_->Start(
@@ -1195,7 +1218,8 @@ void WebMediaPlayerImpl::Destroy() {
// Let V8 know we are not using extra resources anymore.
if (incremented_externally_allocated_memory_) {
- v8::V8::AdjustAmountOfExternalAllocatedMemory(-kPlayerExtraMemory);
+ v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+ -kPlayerExtraMemory);
incremented_externally_allocated_memory_ = false;
}
@@ -1205,20 +1229,21 @@ void WebMediaPlayerImpl::Destroy() {
data_source_.reset();
}
-WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() {
+blink::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() {
DCHECK(main_loop_->BelongsToCurrentThread());
DCHECK(client_);
return client_;
}
-WebKit::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() {
+blink::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() {
return audio_source_provider_.get();
}
void WebMediaPlayerImpl::IncrementExternallyAllocatedMemory() {
DCHECK(main_loop_->BelongsToCurrentThread());
incremented_externally_allocated_memory_ = true;
- v8::V8::AdjustAmountOfExternalAllocatedMemory(kPlayerExtraMemory);
+ v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+ kPlayerExtraMemory);
}
double WebMediaPlayerImpl::GetPipelineDuration() const {
@@ -1243,20 +1268,51 @@ void WebMediaPlayerImpl::FrameReady(
const scoped_refptr<media::VideoFrame>& frame) {
base::AutoLock auto_lock(lock_);
- if (current_frame_.get() &&
+ if (current_frame_ &&
current_frame_->natural_size() != frame->natural_size() &&
!pending_size_change_) {
pending_size_change_ = true;
}
+ DoneWaitingForPaint(false);
+
current_frame_ = frame;
+ current_frame_painted_ = false;
+ TRACE_EVENT_FLOW_BEGIN0("media", "WebMediaPlayerImpl:waitingForPaint", this);
if (pending_repaint_)
return;
+ TRACE_EVENT_ASYNC_BEGIN0("media", "WebMediaPlayerImpl:repaintPending", this);
pending_repaint_ = true;
main_loop_->PostTask(FROM_HERE, base::Bind(
&WebMediaPlayerImpl::Repaint, AsWeakPtr()));
}
+void WebMediaPlayerImpl::DoneWaitingForPaint(bool painting_frame) {
+ lock_.AssertAcquired();
+ if (!current_frame_ || current_frame_painted_)
+ return;
+
+ TRACE_EVENT_FLOW_END0("media", "WebMediaPlayerImpl:waitingForPaint", this);
+
+ if (painting_frame) {
+ current_frame_painted_ = true;
+ return;
+ }
+
+ // The frame wasn't painted, but we aren't waiting for a Repaint() call so
+ // assume that the frame wasn't painted because the video wasn't visible.
+ if (!pending_repaint_)
+ return;
+
+ // The |current_frame_| wasn't painted, it is being replaced, and we haven't
+ // even gotten the chance to request a repaint for it yet. Mark it as dropped.
+ TRACE_EVENT0("media", "WebMediaPlayerImpl:frameDropped");
+ DVLOG(1) << "Frame dropped before being painted: "
+ << current_frame_->GetTimestamp().InSecondsF();
+ if (frames_dropped_before_paint_ < kuint32max)
+ frames_dropped_before_paint_++;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webmediaplayer_impl.h b/chromium/content/renderer/media/webmediaplayer_impl.h
index 270186bbbe5..50ee39b1429 100644
--- a/chromium/content/renderer/media/webmediaplayer_impl.h
+++ b/chromium/content/renderer/media/webmediaplayer_impl.h
@@ -29,6 +29,7 @@
#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
#include "cc/layers/video_frame_provider.h"
+#include "content/public/renderer/render_view_observer.h"
#include "content/renderer/media/crypto/proxy_decryptor.h"
#include "media/base/audio_renderer_sink.h"
#include "media/base/decryptor.h"
@@ -37,15 +38,15 @@
#include "media/base/text_track.h"
#include "media/filters/skcanvas_video_renderer.h"
#include "skia/ext/platform_canvas.h"
+#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-#include "third_party/WebKit/public/web/WebAudioSourceProvider.h"
-#include "third_party/WebKit/public/web/WebMediaPlayer.h"
-#include "third_party/WebKit/public/web/WebMediaPlayerClient.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
#include "url/gurl.h"
class RenderAudioSourceProvider;
-namespace WebKit {
+namespace blink {
class WebFrame;
}
@@ -55,7 +56,6 @@ class MessageLoopProxy;
namespace media {
class ChunkDemuxer;
-class FFmpegDemuxer;
class GpuVideoAcceleratorFactories;
class MediaLog;
}
@@ -72,23 +72,25 @@ class WebMediaPlayerParams;
class WebTextTrackImpl;
class WebMediaPlayerImpl
- : public WebKit::WebMediaPlayer,
+ : public blink::WebMediaPlayer,
public cc::VideoFrameProvider,
- public base::MessageLoop::DestructionObserver,
+ public content::RenderViewObserver,
public base::SupportsWeakPtr<WebMediaPlayerImpl> {
public:
// Constructs a WebMediaPlayer implementation using Chromium's media stack.
- //
+ // |render_view| is passed only for the purpose of registering |this| as an
+ // observer of it.
// |delegate| may be null.
WebMediaPlayerImpl(
- WebKit::WebFrame* frame,
- WebKit::WebMediaPlayerClient* client,
+ content::RenderView* render_view,
+ blink::WebFrame* frame,
+ blink::WebMediaPlayerClient* client,
base::WeakPtr<WebMediaPlayerDelegate> delegate,
const WebMediaPlayerParams& params);
virtual ~WebMediaPlayerImpl();
virtual void load(LoadType load_type,
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
CORSMode cors_mode) OVERRIDE;
// Playback controls.
@@ -99,13 +101,13 @@ class WebMediaPlayerImpl
virtual void seek(double seconds);
virtual void setRate(double rate);
virtual void setVolume(double volume);
- virtual void setPreload(WebKit::WebMediaPlayer::Preload preload);
- virtual const WebKit::WebTimeRanges& buffered();
+ virtual void setPreload(blink::WebMediaPlayer::Preload preload);
+ virtual const blink::WebTimeRanges& buffered();
virtual double maxTimeSeekable() const;
// Methods for painting.
- virtual void paint(WebKit::WebCanvas* canvas,
- const WebKit::WebRect& rect,
+ virtual void paint(blink::WebCanvas* canvas,
+ const blink::WebRect& rect,
unsigned char alpha);
// True if the loaded media has a playable video/audio track.
@@ -113,7 +115,7 @@ class WebMediaPlayerImpl
virtual bool hasAudio() const;
// Dimensions of the video.
- virtual WebKit::WebSize naturalSize() const;
+ virtual blink::WebSize naturalSize() const;
// Getters of playback state.
virtual bool paused() const;
@@ -124,8 +126,8 @@ class WebMediaPlayerImpl
// Internal states of loading and network.
// TODO(hclam): Ask the pipeline about the state rather than having reading
// them from members which would cause race conditions.
- virtual WebKit::WebMediaPlayer::NetworkState networkState() const;
- virtual WebKit::WebMediaPlayer::ReadyState readyState() const;
+ virtual blink::WebMediaPlayer::NetworkState networkState() const;
+ virtual blink::WebMediaPlayer::ReadyState readyState() const;
virtual bool didLoadingProgress() const;
@@ -147,7 +149,7 @@ class WebMediaPlayerImpl
OVERRIDE;
virtual bool copyVideoTextureToPlatformTexture(
- WebKit::WebGraphicsContext3D* web_graphics_context,
+ blink::WebGraphicsContext3D* web_graphics_context,
unsigned int texture,
unsigned int level,
unsigned int internal_format,
@@ -155,29 +157,26 @@ class WebMediaPlayerImpl
bool premultiply_alpha,
bool flip_y);
- virtual WebKit::WebAudioSourceProvider* audioSourceProvider();
+ virtual blink::WebAudioSourceProvider* audioSourceProvider();
virtual MediaKeyException generateKeyRequest(
- const WebKit::WebString& key_system,
+ const blink::WebString& key_system,
const unsigned char* init_data,
unsigned init_data_length);
- virtual MediaKeyException addKey(const WebKit::WebString& key_system,
+ virtual MediaKeyException addKey(const blink::WebString& key_system,
const unsigned char* key,
unsigned key_length,
const unsigned char* init_data,
unsigned init_data_length,
- const WebKit::WebString& session_id);
+ const blink::WebString& session_id);
virtual MediaKeyException cancelKeyRequest(
- const WebKit::WebString& key_system,
- const WebKit::WebString& session_id);
+ const blink::WebString& key_system,
+ const blink::WebString& session_id);
- // As we are closing the tab or even the browser, |main_loop_| is destroyed
- // even before this object gets destructed, so we need to know when
- // |main_loop_| is being destroyed and we can stop posting repaint task
- // to it.
- virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
+ // content::RenderViewObserver implementation.
+ virtual void OnDestruct() OVERRIDE;
void Repaint();
@@ -195,18 +194,16 @@ class WebMediaPlayerImpl
const std::vector<uint8>& message,
const std::string& default_url);
void OnNeedKey(const std::string& type,
- const std::string& session_id,
const std::vector<uint8>& init_data);
- scoped_ptr<media::TextTrack> OnTextTrack(media::TextKind kind,
- const std::string& label,
- const std::string& language);
+ void OnAddTextTrack(const media::TextTrackConfig& config,
+ const media::AddTextTrackDoneCB& done_cb);
void SetOpaque(bool);
private:
// Called after |defer_load_cb_| has decided to allow the load. If
// |defer_load_cb_| is null this is called immediately.
void DoLoad(LoadType load_type,
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
CORSMode cors_mode);
// Called after asynchronous initialization of a data source completed.
@@ -220,14 +217,14 @@ class WebMediaPlayerImpl
// Helpers that set the network/ready state and notifies the client if
// they've changed.
- void SetNetworkState(WebKit::WebMediaPlayer::NetworkState state);
- void SetReadyState(WebKit::WebMediaPlayer::ReadyState state);
+ void SetNetworkState(blink::WebMediaPlayer::NetworkState state);
+ void SetReadyState(blink::WebMediaPlayer::ReadyState state);
// Destroy resources held.
void Destroy();
// Getter method to |client_|.
- WebKit::WebMediaPlayerClient* GetClient();
+ blink::WebMediaPlayerClient* GetClient();
// Lets V8 know that player uses extra resources not managed by V8.
void IncrementExternallyAllocatedMemory();
@@ -235,18 +232,18 @@ class WebMediaPlayerImpl
// Actually do the work for generateKeyRequest/addKey so they can easily
// report results to UMA.
MediaKeyException GenerateKeyRequestInternal(
- const WebKit::WebString& key_system,
+ const blink::WebString& key_system,
const unsigned char* init_data,
unsigned init_data_length);
- MediaKeyException AddKeyInternal(const WebKit::WebString& key_system,
+ MediaKeyException AddKeyInternal(const blink::WebString& key_system,
const unsigned char* key,
unsigned key_length,
const unsigned char* init_data,
unsigned init_data_length,
- const WebKit::WebString& session_id);
+ const blink::WebString& session_id);
MediaKeyException CancelKeyRequestInternal(
- const WebKit::WebString& key_system,
- const WebKit::WebString& session_id);
+ const blink::WebString& key_system,
+ const blink::WebString& session_id);
// Gets the duration value reported by the pipeline.
double GetPipelineDuration() const;
@@ -254,18 +251,24 @@ class WebMediaPlayerImpl
// Notifies WebKit of the duration change.
void OnDurationChange();
- // Called by VideoRendererBase on its internal thread with the new frame to be
+ // Called by VideoRendererImpl on its internal thread with the new frame to be
// painted.
void FrameReady(const scoped_refptr<media::VideoFrame>& frame);
- WebKit::WebFrame* frame_;
+ // Called when a paint or a new frame arrives to indicate that we are
+ // no longer waiting for |current_frame_| to be painted.
+ // |painting_frame| is set to true if |current_frame_| is being painted.
+ // False indicates |current_frame_| is being replaced with a new frame.
+ void DoneWaitingForPaint(bool painting_frame);
+
+ blink::WebFrame* frame_;
// TODO(hclam): get rid of these members and read from the pipeline directly.
- WebKit::WebMediaPlayer::NetworkState network_state_;
- WebKit::WebMediaPlayer::ReadyState ready_state_;
+ blink::WebMediaPlayer::NetworkState network_state_;
+ blink::WebMediaPlayer::ReadyState ready_state_;
// Keep a list of buffered time ranges.
- WebKit::WebTimeRanges buffered_;
+ blink::WebTimeRanges buffered_;
// Message loops for posting tasks on Chrome's main thread. Also used
// for DCHECKs so methods calls won't execute in the wrong thread.
@@ -276,7 +279,7 @@ class WebMediaPlayerImpl
// The currently selected key system. Empty string means that no key system
// has been selected.
- WebKit::WebString current_key_system_;
+ blink::WebString current_key_system_;
// The LoadType passed in the |load_type| parameter of the load() call.
LoadType load_type_;
@@ -303,7 +306,7 @@ class WebMediaPlayerImpl
bool pending_seek_;
double pending_seek_seconds_;
- WebKit::WebMediaPlayerClient* client_;
+ blink::WebMediaPlayerClient* client_;
base::WeakPtr<WebMediaPlayerDelegate> delegate_;
@@ -347,12 +350,15 @@ class WebMediaPlayerImpl
// Video frame rendering members.
//
- // |lock_| protects |current_frame_| since new frames arrive on the video
+ // |lock_| protects |current_frame_|, |current_frame_painted_|, and
+ // |frames_dropped_before_paint_| since new frames arrive on the video
// rendering thread, yet are accessed for rendering on either the main thread
// or compositing thread depending on whether accelerated compositing is used.
- base::Lock lock_;
+ mutable base::Lock lock_;
media::SkCanvasVideoRenderer skcanvas_video_renderer_;
scoped_refptr<media::VideoFrame> current_frame_;
+ bool current_frame_painted_;
+ uint32 frames_dropped_before_paint_;
bool pending_repaint_;
bool pending_size_change_;
diff --git a/chromium/content/renderer/media/webmediaplayer_ms.cc b/chromium/content/renderer/media/webmediaplayer_ms.cc
index eb28f7bc99c..3f64ff150ef 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms.cc
+++ b/chromium/content/renderer/media/webmediaplayer_ms.cc
@@ -18,24 +18,24 @@
#include "content/renderer/media/webmediaplayer_util.h"
#include "media/base/media_log.h"
#include "media/base/video_frame.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebMediaPlayerClient.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
-using WebKit::WebCanvas;
-using WebKit::WebMediaPlayer;
-using WebKit::WebRect;
-using WebKit::WebSize;
+using blink::WebCanvas;
+using blink::WebMediaPlayer;
+using blink::WebRect;
+using blink::WebSize;
namespace content {
WebMediaPlayerMS::WebMediaPlayerMS(
- WebKit::WebFrame* frame,
- WebKit::WebMediaPlayerClient* client,
+ blink::WebFrame* frame,
+ blink::WebMediaPlayerClient* client,
base::WeakPtr<WebMediaPlayerDelegate> delegate,
MediaStreamClient* media_stream_client,
media::MediaLog* media_log)
@@ -82,7 +82,7 @@ WebMediaPlayerMS::~WebMediaPlayerMS() {
}
void WebMediaPlayerMS::load(LoadType load_type,
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
CORSMode cors_mode) {
DVLOG(1) << "WebMediaPlayerMS::load";
DCHECK(thread_checker_.CalledOnValidThread());
@@ -204,14 +204,14 @@ bool WebMediaPlayerMS::hasAudio() const {
return (audio_renderer_.get() != NULL);
}
-WebKit::WebSize WebMediaPlayerMS::naturalSize() const {
+blink::WebSize WebMediaPlayerMS::naturalSize() const {
DCHECK(thread_checker_.CalledOnValidThread());
gfx::Size size;
if (current_frame_.get())
size = current_frame_->natural_size();
DVLOG(3) << "WebMediaPlayerMS::naturalSize, " << size.ToString();
- return WebKit::WebSize(size);
+ return blink::WebSize(size);
}
bool WebMediaPlayerMS::paused() const {
@@ -251,7 +251,7 @@ WebMediaPlayer::ReadyState WebMediaPlayerMS::readyState() const {
return ready_state_;
}
-const WebKit::WebTimeRanges& WebMediaPlayerMS::buffered() {
+const blink::WebTimeRanges& WebMediaPlayerMS::buffered() {
DCHECK(thread_checker_.CalledOnValidThread());
return buffered_;
}
@@ -423,7 +423,7 @@ void WebMediaPlayerMS::SetReadyState(WebMediaPlayer::ReadyState state) {
GetClient()->readyStateChanged();
}
-WebKit::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() {
+blink::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(client_);
return client_;
diff --git a/chromium/content/renderer/media/webmediaplayer_ms.h b/chromium/content/renderer/media/webmediaplayer_ms.h
index 1ed75a392d6..8fa5ef5e1e2 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms.h
+++ b/chromium/content/renderer/media/webmediaplayer_ms.h
@@ -13,10 +13,10 @@
#include "cc/layers/video_frame_provider.h"
#include "media/filters/skcanvas_video_renderer.h"
#include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/public/web/WebMediaPlayer.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "url/gurl.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebMediaPlayerClient;
}
@@ -47,24 +47,24 @@ class WebMediaPlayerDelegate;
// AudioPlayer
// plays audio streams.
//
-// WebKit::WebMediaPlayerClient
+// blink::WebMediaPlayerClient
// WebKit client of this media player object.
class WebMediaPlayerMS
- : public WebKit::WebMediaPlayer,
+ : public blink::WebMediaPlayer,
public cc::VideoFrameProvider,
public base::SupportsWeakPtr<WebMediaPlayerMS> {
public:
// Construct a WebMediaPlayerMS with reference to the client, and
// a MediaStreamClient which provides VideoFrameProvider.
- WebMediaPlayerMS(WebKit::WebFrame* frame,
- WebKit::WebMediaPlayerClient* client,
+ WebMediaPlayerMS(blink::WebFrame* frame,
+ blink::WebMediaPlayerClient* client,
base::WeakPtr<WebMediaPlayerDelegate> delegate,
MediaStreamClient* media_stream_client,
media::MediaLog* media_log);
virtual ~WebMediaPlayerMS();
virtual void load(LoadType load_type,
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
CORSMode cors_mode) OVERRIDE;
// Playback controls.
@@ -75,13 +75,13 @@ class WebMediaPlayerMS
virtual void seek(double seconds);
virtual void setRate(double rate);
virtual void setVolume(double volume);
- virtual void setPreload(WebKit::WebMediaPlayer::Preload preload) OVERRIDE;
- virtual const WebKit::WebTimeRanges& buffered() OVERRIDE;
+ virtual void setPreload(blink::WebMediaPlayer::Preload preload) OVERRIDE;
+ virtual const blink::WebTimeRanges& buffered() OVERRIDE;
virtual double maxTimeSeekable() const;
// Methods for painting.
- virtual void paint(WebKit::WebCanvas* canvas,
- const WebKit::WebRect& rect,
+ virtual void paint(blink::WebCanvas* canvas,
+ const blink::WebRect& rect,
unsigned char alpha) OVERRIDE;
// True if the loaded media has a playable video/audio track.
@@ -89,7 +89,7 @@ class WebMediaPlayerMS
virtual bool hasAudio() const OVERRIDE;
// Dimensions of the video.
- virtual WebKit::WebSize naturalSize() const OVERRIDE;
+ virtual blink::WebSize naturalSize() const OVERRIDE;
// Getters of playback state.
virtual bool paused() const OVERRIDE;
@@ -98,8 +98,8 @@ class WebMediaPlayerMS
virtual double currentTime() const;
// Internal states of loading and network.
- virtual WebKit::WebMediaPlayer::NetworkState networkState() const OVERRIDE;
- virtual WebKit::WebMediaPlayer::ReadyState readyState() const OVERRIDE;
+ virtual blink::WebMediaPlayer::NetworkState networkState() const OVERRIDE;
+ virtual blink::WebMediaPlayer::ReadyState readyState() const OVERRIDE;
virtual bool didLoadingProgress() const OVERRIDE;
@@ -131,23 +131,23 @@ class WebMediaPlayerMS
// Helpers that set the network/ready state and notifies the client if
// they've changed.
- void SetNetworkState(WebKit::WebMediaPlayer::NetworkState state);
- void SetReadyState(WebKit::WebMediaPlayer::ReadyState state);
+ void SetNetworkState(blink::WebMediaPlayer::NetworkState state);
+ void SetReadyState(blink::WebMediaPlayer::ReadyState state);
// Getter method to |client_|.
- WebKit::WebMediaPlayerClient* GetClient();
+ blink::WebMediaPlayerClient* GetClient();
- WebKit::WebFrame* frame_;
+ blink::WebFrame* frame_;
- WebKit::WebMediaPlayer::NetworkState network_state_;
- WebKit::WebMediaPlayer::ReadyState ready_state_;
+ blink::WebMediaPlayer::NetworkState network_state_;
+ blink::WebMediaPlayer::ReadyState ready_state_;
- WebKit::WebTimeRanges buffered_;
+ blink::WebTimeRanges buffered_;
// Used for DCHECKs to ensure methods calls executed in the correct thread.
base::ThreadChecker thread_checker_;
- WebKit::WebMediaPlayerClient* client_;
+ blink::WebMediaPlayerClient* client_;
base::WeakPtr<WebMediaPlayerDelegate> delegate_;
diff --git a/chromium/content/renderer/media/webmediaplayer_util.cc b/chromium/content/renderer/media/webmediaplayer_util.cc
index 741239addcc..a245f038b0a 100644
--- a/chromium/content/renderer/media/webmediaplayer_util.cc
+++ b/chromium/content/renderer/media/webmediaplayer_util.cc
@@ -7,7 +7,7 @@
#include <math.h>
#include "media/base/media_keys.h"
-#include "third_party/WebKit/public/web/WebMediaPlayerClient.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
namespace content {
@@ -15,7 +15,7 @@ namespace content {
#define COMPILE_ASSERT_MATCHING_ENUM(name) \
COMPILE_ASSERT( \
- static_cast<int>(WebKit::WebMediaPlayerClient::MediaKeyErrorCode ## name) == \
+ static_cast<int>(blink::WebMediaPlayerClient::MediaKeyErrorCode ## name) == \
static_cast<int>(media::MediaKeys::k ## name ## Error), \
mismatching_enums)
COMPILE_ASSERT_MATCHING_ENUM(Unknown);
@@ -28,9 +28,9 @@ base::TimeDelta ConvertSecondsToTimestamp(double seconds) {
microseconds > 0 ? microseconds + 0.5 : ceil(microseconds - 0.5));
}
-WebKit::WebTimeRanges ConvertToWebTimeRanges(
+blink::WebTimeRanges ConvertToWebTimeRanges(
const media::Ranges<base::TimeDelta>& ranges) {
- WebKit::WebTimeRanges result(ranges.size());
+ blink::WebTimeRanges result(ranges.size());
for (size_t i = 0; i < ranges.size(); i++) {
result[i].start = ranges.start(i).InSecondsF();
result[i].end = ranges.end(i).InSecondsF();
@@ -38,14 +38,14 @@ WebKit::WebTimeRanges ConvertToWebTimeRanges(
return result;
}
-WebKit::WebMediaPlayer::NetworkState PipelineErrorToNetworkState(
+blink::WebMediaPlayer::NetworkState PipelineErrorToNetworkState(
media::PipelineStatus error) {
DCHECK_NE(error, media::PIPELINE_OK);
switch (error) {
case media::PIPELINE_ERROR_NETWORK:
case media::PIPELINE_ERROR_READ:
- return WebKit::WebMediaPlayer::NetworkStateNetworkError;
+ return blink::WebMediaPlayer::NetworkStateNetworkError;
// TODO(vrk): Because OnPipelineInitialize() directly reports the
// NetworkStateFormatError instead of calling OnPipelineError(), I believe
@@ -57,24 +57,24 @@ WebKit::WebMediaPlayer::NetworkState PipelineErrorToNetworkState(
case media::DEMUXER_ERROR_COULD_NOT_PARSE:
case media::DEMUXER_ERROR_NO_SUPPORTED_STREAMS:
case media::DECODER_ERROR_NOT_SUPPORTED:
- return WebKit::WebMediaPlayer::NetworkStateFormatError;
+ return blink::WebMediaPlayer::NetworkStateFormatError;
case media::PIPELINE_ERROR_DECODE:
case media::PIPELINE_ERROR_ABORT:
case media::PIPELINE_ERROR_OPERATION_PENDING:
case media::PIPELINE_ERROR_INVALID_STATE:
- return WebKit::WebMediaPlayer::NetworkStateDecodeError;
+ return blink::WebMediaPlayer::NetworkStateDecodeError;
case media::PIPELINE_ERROR_DECRYPT:
// TODO(xhwang): Change to use NetworkStateDecryptError once it's added in
// Webkit (see http://crbug.com/124486).
- return WebKit::WebMediaPlayer::NetworkStateDecodeError;
+ return blink::WebMediaPlayer::NetworkStateDecodeError;
case media::PIPELINE_OK:
case media::PIPELINE_STATUS_MAX:
NOTREACHED() << "Unexpected status! " << error;
}
- return WebKit::WebMediaPlayer::NetworkStateFormatError;
+ return blink::WebMediaPlayer::NetworkStateFormatError;
}
} // namespace content
diff --git a/chromium/content/renderer/media/webmediaplayer_util.h b/chromium/content/renderer/media/webmediaplayer_util.h
index 007980c7d09..3c2dacc6eab 100644
--- a/chromium/content/renderer/media/webmediaplayer_util.h
+++ b/chromium/content/renderer/media/webmediaplayer_util.h
@@ -8,8 +8,8 @@
#include "base/time/time.h"
#include "media/base/pipeline_status.h"
#include "media/base/ranges.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/WebTimeRange.h"
-#include "third_party/WebKit/public/web/WebMediaPlayer.h"
namespace content {
@@ -19,10 +19,10 @@ namespace content {
// Refer to https://bugs.webkit.org/show_bug.cgi?id=52697 for details.
base::TimeDelta ConvertSecondsToTimestamp(double seconds);
-WebKit::WebTimeRanges ConvertToWebTimeRanges(
+blink::WebTimeRanges ConvertToWebTimeRanges(
const media::Ranges<base::TimeDelta>& ranges);
-WebKit::WebMediaPlayer::NetworkState PipelineErrorToNetworkState(
+blink::WebMediaPlayer::NetworkState PipelineErrorToNetworkState(
media::PipelineStatus error);
} // namespace content
diff --git a/chromium/content/renderer/media/webmediasource_impl.cc b/chromium/content/renderer/media/webmediasource_impl.cc
index a420f9d1b63..d1a2dfbc9ed 100644
--- a/chromium/content/renderer/media/webmediasource_impl.cc
+++ b/chromium/content/renderer/media/webmediasource_impl.cc
@@ -10,8 +10,8 @@
#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebString.h"
-using ::WebKit::WebString;
-using ::WebKit::WebMediaSource;
+using ::blink::WebString;
+using ::blink::WebMediaSource;
namespace content {
@@ -34,9 +34,9 @@ WebMediaSourceImpl::WebMediaSourceImpl(
WebMediaSourceImpl::~WebMediaSourceImpl() {}
WebMediaSource::AddStatus WebMediaSourceImpl::addSourceBuffer(
- const WebKit::WebString& type,
- const WebKit::WebVector<WebKit::WebString>& codecs,
- WebKit::WebSourceBuffer** source_buffer) {
+ const blink::WebString& type,
+ const blink::WebVector<blink::WebString>& codecs,
+ blink::WebSourceBuffer** source_buffer) {
std::string id = base::GenerateGUID();
std::vector<std::string> new_codecs(codecs.size());
for (size_t i = 0; i < codecs.size(); ++i)
diff --git a/chromium/content/renderer/media/webmediasource_impl.h b/chromium/content/renderer/media/webmediasource_impl.h
index 8d679943190..42d5eef9405 100644
--- a/chromium/content/renderer/media/webmediasource_impl.h
+++ b/chromium/content/renderer/media/webmediasource_impl.h
@@ -17,16 +17,16 @@ class ChunkDemuxer;
namespace content {
-class WebMediaSourceImpl : public WebKit::WebMediaSource {
+class WebMediaSourceImpl : public blink::WebMediaSource {
public:
WebMediaSourceImpl(media::ChunkDemuxer* demuxer, media::LogCB log_cb);
virtual ~WebMediaSourceImpl();
- // WebKit::WebMediaSource implementation.
+ // blink::WebMediaSource implementation.
virtual AddStatus addSourceBuffer(
- const WebKit::WebString& type,
- const WebKit::WebVector<WebKit::WebString>& codecs,
- WebKit::WebSourceBuffer** source_buffer) OVERRIDE;
+ const blink::WebString& type,
+ const blink::WebVector<blink::WebString>& codecs,
+ blink::WebSourceBuffer** source_buffer) OVERRIDE;
virtual double duration() OVERRIDE;
virtual void setDuration(double duration) OVERRIDE;
virtual void markEndOfStream(EndOfStreamStatus status) OVERRIDE;
diff --git a/chromium/content/renderer/media/webrtc/OWNERS b/chromium/content/renderer/media/webrtc/OWNERS
new file mode 100644
index 00000000000..dbd443f2610
--- /dev/null
+++ b/chromium/content/renderer/media/webrtc/OWNERS
@@ -0,0 +1,10 @@
+# Piranha Plant members.
+xians@chromium.org
+perkj@chromium.org
+hclam@chromium.org
+joi@chromium.org
+
+# To be able to roll new libjingle releases.
+ronghuawu@chromium.org
+mallinath@chromium.org
+sergeyu@chromium.org \ No newline at end of file
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.cc
new file mode 100644
index 00000000000..652dec0c846
--- /dev/null
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.cc
@@ -0,0 +1,119 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/webrtc/webrtc_video_sink_adapter.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "content/renderer/media/native_handle_impl.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_util.h"
+#include "third_party/libjingle/source/talk/media/base/videoframe.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
+#include "ui/gfx/size.h"
+
+using media::CopyYPlane;
+using media::CopyUPlane;
+using media::CopyVPlane;
+
+namespace content {
+
+WebRtcVideoSinkAdapter::WebRtcVideoSinkAdapter(
+ webrtc::VideoTrackInterface* video_track,
+ MediaStreamVideoSink* sink)
+ : message_loop_proxy_(base::MessageLoopProxy::current()),
+ sink_(sink),
+ video_track_(video_track),
+ state_(video_track->state()),
+ track_enabled_(video_track->enabled()) {
+ DCHECK(sink);
+ video_track_->AddRenderer(this);
+ video_track_->RegisterObserver(this);
+ DVLOG(1) << "WebRtcVideoSinkAdapter";
+}
+
+WebRtcVideoSinkAdapter::~WebRtcVideoSinkAdapter() {
+ video_track_->RemoveRenderer(this);
+ video_track_->UnregisterObserver(this);
+ DVLOG(1) << "~WebRtcVideoSinkAdapter";
+}
+
+void WebRtcVideoSinkAdapter::SetSize(int width, int height) {
+ NOTIMPLEMENTED();
+}
+
+void WebRtcVideoSinkAdapter::RenderFrame(const cricket::VideoFrame* frame) {
+ base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds(
+ frame->GetTimeStamp() / talk_base::kNumNanosecsPerMillisec);
+
+ scoped_refptr<media::VideoFrame> video_frame;
+ if (frame->GetNativeHandle() != NULL) {
+ NativeHandleImpl* handle =
+ static_cast<NativeHandleImpl*>(frame->GetNativeHandle());
+ video_frame = static_cast<media::VideoFrame*>(handle->GetHandle());
+ video_frame->SetTimestamp(timestamp);
+ } else {
+ gfx::Size size(frame->GetWidth(), frame->GetHeight());
+ video_frame = media::VideoFrame::CreateFrame(
+ media::VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
+
+ // Aspect ratio unsupported; DCHECK when there are non-square pixels.
+ DCHECK_EQ(frame->GetPixelWidth(), 1u);
+ DCHECK_EQ(frame->GetPixelHeight(), 1u);
+
+ int y_rows = frame->GetHeight();
+ int uv_rows = frame->GetHeight() / 2; // YV12 format.
+ CopyYPlane(
+ frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame.get());
+ CopyUPlane(
+ frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame.get());
+ CopyVPlane(
+ frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame.get());
+ }
+
+ message_loop_proxy_->PostTask(
+ FROM_HERE, base::Bind(&WebRtcVideoSinkAdapter::DoRenderFrameOnMainThread,
+ AsWeakPtr(), video_frame));
+}
+
+void WebRtcVideoSinkAdapter::OnChanged() {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+
+ // TODO(perkj): OnChanged belongs to the base class of WebRtcVideoSinkAdapter
+ // common for both webrtc audio and video.
+ webrtc::MediaStreamTrackInterface::TrackState state = video_track_->state();
+ if (state != state_) {
+ state_ = state;
+ switch (state) {
+ case webrtc::MediaStreamTrackInterface::kInitializing:
+ // Ignore the kInitializing state since there is no match in
+ // WebMediaStreamSource::ReadyState.
+ break;
+ case webrtc::MediaStreamTrackInterface::kLive:
+ sink_->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateLive);
+ break;
+ case webrtc::MediaStreamTrackInterface::kEnded:
+ sink_->OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyStateEnded);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+ if (track_enabled_ != video_track_->enabled()) {
+ track_enabled_ = video_track_->enabled();
+ sink_->OnEnabledChanged(track_enabled_);
+ }
+}
+
+void WebRtcVideoSinkAdapter::DoRenderFrameOnMainThread(
+ scoped_refptr<media::VideoFrame> video_frame) {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ sink_->OnVideoFrame(video_frame);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.h
new file mode 100644
index 00000000000..2f75a95ef35
--- /dev/null
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.h
@@ -0,0 +1,60 @@
+// 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_MEDIA_WEBRTC_WEBRTC_VIDEO_SINK_ADAPTER_H_
+#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_SINK_ADAPTER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "content/public/renderer/media_stream_video_sink.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace content {
+
+// WebRtcVideoSinkAdapter acts as the middle man between a
+// webrtc:::VideoTrackInterface and a content::MediaStreamVideoSink.
+// It is responsible for translating video data from a libjingle video type
+// to a chrome video type.
+class CONTENT_EXPORT WebRtcVideoSinkAdapter
+ : NON_EXPORTED_BASE(public webrtc::VideoRendererInterface),
+ NON_EXPORTED_BASE(public webrtc::ObserverInterface),
+ public base::SupportsWeakPtr<WebRtcVideoSinkAdapter> {
+ public:
+ WebRtcVideoSinkAdapter(webrtc::VideoTrackInterface* video_track,
+ MediaStreamVideoSink* sink);
+ virtual ~WebRtcVideoSinkAdapter();
+
+ MediaStreamVideoSink* sink() const { return sink_; }
+
+ protected:
+ // webrtc::VideoRendererInterface implementation. May be called on
+ // a different thread.
+ virtual void SetSize(int width, int height) OVERRIDE;
+ virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE;
+
+ // webrtc::ObserverInterface implementation.
+ // TODO(perkj): OnChanged should be implemented on a common base class used
+ // for both WebRtc Audio and Video tracks.
+ virtual void OnChanged() OVERRIDE;
+
+ private:
+ void DoRenderFrameOnMainThread(scoped_refptr<media::VideoFrame> video_frame);
+
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+ MediaStreamVideoSink* sink_;
+ // The video track the renderer is connected to.
+ scoped_refptr<webrtc::VideoTrackInterface> video_track_;
+ webrtc::MediaStreamTrackInterface::TrackState state_;
+ bool track_enabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebRtcVideoSinkAdapter);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_SINK_ADAPTER_H_
diff --git a/chromium/content/renderer/media/webrtc_audio_capturer.cc b/chromium/content/renderer/media/webrtc_audio_capturer.cc
index c5127c191ad..391e7d77f59 100644
--- a/chromium/content/renderer/media/webrtc_audio_capturer.cc
+++ b/chromium/content/renderer/media/webrtc_audio_capturer.cc
@@ -8,11 +8,12 @@
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "content/child/child_process.h"
#include "content/renderer/media/audio_device_factory.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
-#include "media/audio/audio_util.h"
+#include "content/renderer/media/webrtc_logging.h"
#include "media/audio/sample_rates.h"
namespace content {
@@ -56,10 +57,10 @@ class WebRtcAudioCapturer::TrackOwner
}
}
- void SetCaptureFormat(const media::AudioParameters& params) {
+ void OnSetFormat(const media::AudioParameters& params) {
base::AutoLock lock(lock_);
if (delegate_)
- delegate_->SetCaptureFormat(params);
+ delegate_->OnSetFormat(params);
}
void Reset() {
@@ -67,12 +68,22 @@ class WebRtcAudioCapturer::TrackOwner
delegate_ = NULL;
}
+ void Stop() {
+ base::AutoLock lock(lock_);
+ DCHECK(delegate_);
+
+ // This can be reentrant so reset |delegate_| before calling out.
+ WebRtcLocalAudioTrack* temp = delegate_;
+ delegate_ = NULL;
+ temp->Stop();
+ }
+
// Wrapper which allows to use std::find_if() when adding and removing
// sinks to/from the list.
struct TrackWrapper {
TrackWrapper(WebRtcLocalAudioTrack* track) : track_(track) {}
bool operator()(
- const scoped_refptr<WebRtcAudioCapturer::TrackOwner>& owner) {
+ const scoped_refptr<WebRtcAudioCapturer::TrackOwner>& owner) const {
return owner->IsEqual(track_);
}
WebRtcLocalAudioTrack* track_;
@@ -103,7 +114,8 @@ scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() {
}
void WebRtcAudioCapturer::Reconfigure(int sample_rate,
- media::ChannelLayout channel_layout) {
+ media::ChannelLayout channel_layout,
+ int effects) {
DCHECK(thread_checker_.CalledOnValidThread());
int buffer_size = GetBufferSize(sample_rate);
DVLOG(1) << "Using WebRTC input buffer size: " << buffer_size;
@@ -113,40 +125,52 @@ void WebRtcAudioCapturer::Reconfigure(int sample_rate,
// bits_per_sample is always 16 for now.
int bits_per_sample = 16;
- media::AudioParameters params(format, channel_layout, sample_rate,
- bits_per_sample, buffer_size);
-
- TrackList tracks;
+ media::AudioParameters params(format, channel_layout, 0, sample_rate,
+ bits_per_sample, buffer_size, effects);
{
base::AutoLock auto_lock(lock_);
- tracks = tracks_;
params_ = params;
- }
- // Tell all audio_tracks which format we use.
- for (TrackList::const_iterator it = tracks.begin();
- it != tracks.end(); ++it)
- (*it)->SetCaptureFormat(params);
+ // Notify all tracks about the new format.
+ tracks_.TagAll();
+ }
}
bool WebRtcAudioCapturer::Initialize(int render_view_id,
- media::ChannelLayout channel_layout,
- int sample_rate,
- int buffer_size,
- int session_id,
- const std::string& device_id) {
+ media::ChannelLayout channel_layout,
+ int sample_rate,
+ int buffer_size,
+ int session_id,
+ const std::string& device_id,
+ int paired_output_sample_rate,
+ int paired_output_frames_per_buffer,
+ int effects) {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK_GE(render_view_id, 0);
DVLOG(1) << "WebRtcAudioCapturer::Initialize()";
DVLOG(1) << "Audio input hardware channel layout: " << channel_layout;
UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout",
channel_layout, media::CHANNEL_LAYOUT_MAX);
+ WebRtcLogMessage(base::StringPrintf(
+ "WAC::Initialize. render_view_id=%d"
+ ", channel_layout=%d, sample_rate=%d, buffer_size=%d"
+ ", session_id=%d, paired_output_sample_rate=%d"
+ ", paired_output_frames_per_buffer=%d",
+ render_view_id,
+ channel_layout,
+ sample_rate,
+ buffer_size,
+ session_id,
+ paired_output_sample_rate,
+ paired_output_frames_per_buffer));
+
render_view_id_ = render_view_id;
session_id_ = session_id;
device_id_ = device_id;
hardware_buffer_size_ = buffer_size;
+ output_sample_rate_ = paired_output_sample_rate;
+ output_frames_per_buffer_= paired_output_frames_per_buffer;
if (render_view_id == -1) {
// Return true here to allow injecting a new source via SetCapturerSource()
@@ -181,35 +205,33 @@ bool WebRtcAudioCapturer::Initialize(int render_view_id,
return false;
}
- Reconfigure(sample_rate, channel_layout);
-
// Create and configure the default audio capturing source. The |source_|
// will be overwritten if an external client later calls SetCapturerSource()
// providing an alternative media::AudioCapturerSource.
SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id),
channel_layout,
- static_cast<float>(sample_rate));
+ static_cast<float>(sample_rate),
+ effects);
return true;
}
WebRtcAudioCapturer::WebRtcAudioCapturer()
- : source_(NULL),
- running_(false),
- agc_is_enabled_(false),
+ : running_(false),
render_view_id_(-1),
hardware_buffer_size_(0),
session_id_(0),
volume_(0),
- source_provider_(new WebRtcLocalAudioSourceProvider()),
- peer_connection_mode_(false) {
- DCHECK(source_provider_.get());
+ peer_connection_mode_(false),
+ output_sample_rate_(0),
+ output_frames_per_buffer_(0),
+ key_pressed_(false) {
DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()";
}
WebRtcAudioCapturer::~WebRtcAudioCapturer() {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(tracks_.empty());
+ DCHECK(tracks_.IsEmpty());
DCHECK(!running_);
DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()";
}
@@ -218,17 +240,21 @@ void WebRtcAudioCapturer::AddTrack(WebRtcLocalAudioTrack* track) {
DCHECK(track);
DVLOG(1) << "WebRtcAudioCapturer::AddTrack()";
+ {
+ base::AutoLock auto_lock(lock_);
+ // Verify that |track| is not already added to the list.
+ DCHECK(!tracks_.Contains(TrackOwner::TrackWrapper(track)));
+
+ // Add with a tag, so we remember to call OnSetFormat() on the new
+ // track.
+ scoped_refptr<TrackOwner> track_owner(new TrackOwner(track));
+ tracks_.AddAndTag(track_owner);
+ }
+
// Start the source if the first audio track is connected to the capturer.
// Start() will do nothing if the capturer has already been started.
Start();
- base::AutoLock auto_lock(lock_);
- // Verify that |track| is not already added to the list.
- DCHECK(std::find_if(tracks_.begin(), tracks_.end(),
- TrackOwner::TrackWrapper(track)) == tracks_.end());
-
- track->SetCaptureFormat(params_);
- tracks_.push_back(new WebRtcAudioCapturer::TrackOwner(track));
}
void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) {
@@ -237,20 +263,18 @@ void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) {
bool stop_source = false;
{
base::AutoLock auto_lock(lock_);
- // Get iterator to the first element for which WrapsSink(track) returns
- // true.
- TrackList::iterator it = std::find_if(
- tracks_.begin(), tracks_.end(), TrackOwner::TrackWrapper(track));
- if (it != tracks_.end()) {
- // Clear the delegate to ensure that no more capture callbacks will
- // be sent to this sink. Also avoids a possible crash which can happen
- // if this method is called while capturing is active.
- (*it)->Reset();
- tracks_.erase(it);
- }
+
+ scoped_refptr<TrackOwner> removed_item =
+ tracks_.Remove(TrackOwner::TrackWrapper(track));
+
+ // Clear the delegate to ensure that no more capture callbacks will
+ // be sent to this sink. Also avoids a possible crash which can happen
+ // if this method is called while capturing is active.
+ if (removed_item.get())
+ removed_item->Reset();
// Stop the source if the last audio track is going away.
- stop_source = tracks_.empty();
+ stop_source = tracks_.IsEmpty();
}
if (stop_source)
@@ -260,7 +284,8 @@ void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) {
void WebRtcAudioCapturer::SetCapturerSource(
const scoped_refptr<media::AudioCapturerSource>& source,
media::ChannelLayout channel_layout,
- float sample_rate) {
+ float sample_rate,
+ int effects) {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << ","
<< "sample_rate=" << sample_rate << ")";
@@ -286,11 +311,10 @@ void WebRtcAudioCapturer::SetCapturerSource(
// Dispatch the new parameters both to the sink(s) and to the new source.
// The idea is to get rid of any dependency of the microphone parameters
// which would normally be used by default.
- Reconfigure(sample_rate, channel_layout);
+ Reconfigure(sample_rate, channel_layout, effects);
// Make sure to grab the new parameters in case they were reconfigured.
media::AudioParameters params = audio_parameters();
- source_provider_->Initialize(params);
if (source.get())
source->Initialize(params, this, session_id_);
@@ -317,43 +341,53 @@ void WebRtcAudioCapturer::EnablePeerConnectionMode() {
render_view_id = render_view_id_;
}
+ // Do nothing if the current buffer size is the WebRtc native buffer size.
+ media::AudioParameters params = audio_parameters();
+ if (GetBufferSize(params.sample_rate()) == params.frames_per_buffer())
+ return;
+
// Create a new audio stream as source which will open the hardware using
// WebRtc native buffer size.
- media::AudioParameters params = audio_parameters();
SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id),
params.channel_layout(),
- static_cast<float>(params.sample_rate()));
+ static_cast<float>(params.sample_rate()),
+ params.effects());
}
void WebRtcAudioCapturer::Start() {
DVLOG(1) << "WebRtcAudioCapturer::Start()";
base::AutoLock auto_lock(lock_);
- if (running_)
+ if (running_ || !source_)
return;
// Start the data source, i.e., start capturing data from the current source.
- // Note that, the source does not have to be a microphone.
- if (source_.get()) {
- // We need to set the AGC control before starting the stream.
- source_->SetAutomaticGainControl(agc_is_enabled_);
- source_->Start();
- }
-
+ // We need to set the AGC control before starting the stream.
+ source_->SetAutomaticGainControl(true);
+ source_->Start();
running_ = true;
}
void WebRtcAudioCapturer::Stop() {
DVLOG(1) << "WebRtcAudioCapturer::Stop()";
scoped_refptr<media::AudioCapturerSource> source;
+ TrackList::ItemList tracks;
{
base::AutoLock auto_lock(lock_);
if (!running_)
return;
source = source_;
+ tracks = tracks_.Items();
+ tracks_.Clear();
running_ = false;
}
+ for (TrackList::ItemList::const_iterator it = tracks.begin();
+ it != tracks.end();
+ ++it) {
+ (*it)->Stop();
+ }
+
if (source.get())
source->Stop();
}
@@ -376,16 +410,6 @@ int WebRtcAudioCapturer::MaxVolume() const {
return WebRtcAudioDeviceImpl::kMaxVolumeLevel;
}
-void WebRtcAudioCapturer::SetAutomaticGainControl(bool enable) {
- base::AutoLock auto_lock(lock_);
- // Store the setting since SetAutomaticGainControl() can be called before
- // Initialize(), in this case stored setting will be applied in Start().
- agc_is_enabled_ = enable;
-
- if (source_.get())
- source_->SetAutomaticGainControl(enable);
-}
-
void WebRtcAudioCapturer::Capture(media::AudioBus* audio_source,
int audio_delay_milliseconds,
double volume,
@@ -404,8 +428,10 @@ void WebRtcAudioCapturer::Capture(media::AudioBus* audio_source,
DCHECK_LE(volume, 1.6);
#endif
- TrackList tracks;
+ TrackList::ItemList tracks;
+ TrackList::ItemList tracks_to_notify_format;
int current_volume = 0;
+ media::AudioParameters params;
{
base::AutoLock auto_lock(lock_);
if (!running_)
@@ -416,16 +442,26 @@ void WebRtcAudioCapturer::Capture(media::AudioBus* audio_source,
// volume is higher than 255.
volume_ = static_cast<int>((volume * MaxVolume()) + 0.5);
current_volume = volume_;
- tracks = tracks_;
+ audio_delay_ = base::TimeDelta::FromMilliseconds(audio_delay_milliseconds);
+ key_pressed_ = key_pressed;
+ tracks = tracks_.Items();
+ tracks_.RetrieveAndClearTags(&tracks_to_notify_format);
+
+ CHECK(params_.IsValid());
+ CHECK_EQ(audio_source->channels(), params_.channels());
+ CHECK_EQ(audio_source->frames(), params_.frames_per_buffer());
+ params = params_;
}
- // Deliver captured data to source provider, which stores the data into FIFO
- // for WebAudio to fetch.
- source_provider_->DeliverData(audio_source, audio_delay_milliseconds,
- current_volume, key_pressed);
+ // Notify the tracks on when the format changes. This will do nothing if
+ // |tracks_to_notify_format| is empty.
+ for (TrackList::ItemList::const_iterator it = tracks_to_notify_format.begin();
+ it != tracks_to_notify_format.end(); ++it) {
+ (*it)->OnSetFormat(params);
+ }
// Feed the data to the tracks.
- for (TrackList::const_iterator it = tracks.begin();
+ for (TrackList::ItemList::const_iterator it = tracks.begin();
it != tracks.end();
++it) {
(*it)->Capture(audio_source, audio_delay_milliseconds,
@@ -442,6 +478,21 @@ media::AudioParameters WebRtcAudioCapturer::audio_parameters() const {
return params_;
}
+bool WebRtcAudioCapturer::GetPairedOutputParameters(
+ int* session_id,
+ int* output_sample_rate,
+ int* output_frames_per_buffer) const {
+ // Don't set output parameters unless all of them are valid.
+ if (session_id_ <= 0 || !output_sample_rate_ || !output_frames_per_buffer_)
+ return false;
+
+ *session_id = session_id_;
+ *output_sample_rate = output_sample_rate_;
+ *output_frames_per_buffer = output_frames_per_buffer_;
+
+ return true;
+}
+
int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const {
DCHECK(thread_checker_.CalledOnValidThread());
#if defined(OS_ANDROID)
@@ -449,13 +500,27 @@ int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const {
return (2 * sample_rate / 100);
#endif
- // Use the native hardware buffer size in non peer connection mode.
- if (!peer_connection_mode_ && hardware_buffer_size_)
+ // PeerConnection is running at a buffer size of 10ms data. A multiple of
+ // 10ms as the buffer size can give the best performance to PeerConnection.
+ int peer_connection_buffer_size = sample_rate / 100;
+
+ // Use the native hardware buffer size in non peer connection mode when the
+ // platform is using a native buffer size smaller than the PeerConnection
+ // buffer size.
+ if (!peer_connection_mode_ && hardware_buffer_size_ &&
+ hardware_buffer_size_ <= peer_connection_buffer_size) {
return hardware_buffer_size_;
+ }
- // WebRtc is running at a buffer size of 10ms data. Use a multiple of 10ms
- // as the buffer size to achieve the best performance for WebRtc.
return (sample_rate / 100);
}
+void WebRtcAudioCapturer::GetAudioProcessingParams(
+ base::TimeDelta* delay, int* volume, bool* key_pressed) {
+ base::AutoLock auto_lock(lock_);
+ *delay = audio_delay_;
+ *volume = volume_;
+ *key_pressed = key_pressed_;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_audio_capturer.h b/chromium/content/renderer/media/webrtc_audio_capturer.h
index 21246798cc4..23391140411 100644
--- a/chromium/content/renderer/media/webrtc_audio_capturer.h
+++ b/chromium/content/renderer/media/webrtc_audio_capturer.h
@@ -12,8 +12,9 @@
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
+#include "content/renderer/media/tagged_list.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
-#include "content/renderer/media/webrtc_local_audio_source_provider.h"
#include "media/audio/audio_input_device.h"
#include "media/base/audio_capturer_source.h"
@@ -53,16 +54,22 @@ class CONTENT_EXPORT WebRtcAudioCapturer
int sample_rate,
int buffer_size,
int session_id,
- const std::string& device_id);
+ const std::string& device_id,
+ int paired_output_sample_rate,
+ int paired_output_frames_per_buffer,
+ int effects);
// Add a audio track to the sinks of the capturer.
// WebRtcAudioDeviceImpl calls this method on the main render thread but
// other clients may call it from other threads. The current implementation
// does not support multi-thread calling.
+ // The first AddTrack will implicitly trigger the Start() of this object.
// Called on the main render thread or libjingle working thread.
void AddTrack(WebRtcLocalAudioTrack* track);
// Remove a audio track from the sinks of the capturer.
+ // If the track has been added to the capturer, it must call RemoveTrack()
+ // before it goes away.
// Called on the main render thread or libjingle working thread.
void RemoveTrack(WebRtcLocalAudioTrack* track);
@@ -73,7 +80,8 @@ class CONTENT_EXPORT WebRtcAudioCapturer
void SetCapturerSource(
const scoped_refptr<media::AudioCapturerSource>& source,
media::ChannelLayout channel_layout,
- float sample_rate);
+ float sample_rate,
+ int effects);
// Called when a stream is connecting to a peer connection. This will set
// up the native buffer size for the stream in order to optimize the
@@ -86,10 +94,6 @@ class CONTENT_EXPORT WebRtcAudioCapturer
int Volume() const;
int MaxVolume() const;
- // Enables or disables the WebRtc AGC control.
- // Called from a Libjingle working thread.
- void SetAutomaticGainControl(bool enable);
-
bool is_recording() const { return running_; }
// Audio parameters utilized by the audio capturer. Can be utilized by
@@ -100,11 +104,26 @@ class CONTENT_EXPORT WebRtcAudioCapturer
// of this accessor and if we can remove it.
media::AudioParameters audio_parameters() const;
+ // Gets information about the paired output device. Returns true if such a
+ // device exists.
+ bool GetPairedOutputParameters(int* session_id,
+ int* output_sample_rate,
+ int* output_frames_per_buffer) const;
+
const std::string& device_id() const { return device_id_; }
+ int session_id() const { return session_id_; }
+
+ // Stops recording audio. This method will empty its track lists since
+ // stopping the capturer will implicitly invalidate all its tracks.
+ // This method is exposed to the public because the media stream track can
+ // call Stop() on its source.
+ void Stop();
- WebKit::WebAudioSourceProvider* audio_source_provider() const {
- return source_provider_.get();
- }
+ // Called by the WebAudioCapturerSource to get the audio processing params.
+ // This function is triggered by provideInput() on the WebAudio audio thread,
+ // TODO(xians): Remove after moving APM from WebRtc to Chrome.
+ void GetAudioProcessingParams(base::TimeDelta* delay, int* volume,
+ bool* key_pressed);
protected:
friend class base::RefCountedThreadSafe<WebRtcAudioCapturer>;
@@ -113,7 +132,7 @@ class CONTENT_EXPORT WebRtcAudioCapturer
private:
class TrackOwner;
- typedef std::list<scoped_refptr<TrackOwner> > TrackList;
+ typedef TaggedList<TrackOwner> TrackList;
// AudioCapturerSource::CaptureCallback implementation.
// Called on the AudioInputDevice audio thread.
@@ -125,18 +144,14 @@ class CONTENT_EXPORT WebRtcAudioCapturer
// Reconfigures the capturer with a new capture parameters.
// Must be called without holding the lock.
- void Reconfigure(int sample_rate, media::ChannelLayout channel_layout);
+ void Reconfigure(int sample_rate, media::ChannelLayout channel_layout,
+ int effects);
// Starts recording audio.
// Triggered by AddSink() on the main render thread or a Libjingle working
// thread. It should NOT be called under |lock_|.
void Start();
- // Stops recording audio.
- // Triggered by RemoveSink() on the main render thread or a Libjingle working
- // thread. It should NOT be called under |lock_|.
- void Stop();
-
// Helper function to get the buffer size based on |peer_connection_mode_|
// and sample rate;
int GetBufferSize(int sample_rate) const;
@@ -145,10 +160,12 @@ class CONTENT_EXPORT WebRtcAudioCapturer
base::ThreadChecker thread_checker_;
// Protects |source_|, |audio_tracks_|, |running_|, |loopback_fifo_|,
- // |params_|, |buffering_| and |agc_is_enabled_|.
+ // |params_| and |buffering_|.
mutable base::Lock lock_;
- // A list of audio tracks that the audio data is fed to.
+ // A tagged list of audio tracks that the audio data is fed
+ // to. Tagged items need to be notified that the audio format has
+ // changed.
TrackList tracks_;
// The audio data source from the browser process.
@@ -159,9 +176,6 @@ class CONTENT_EXPORT WebRtcAudioCapturer
bool running_;
- // True when automatic gain control is enabled, false otherwise.
- bool agc_is_enabled_;
-
int render_view_id_;
// Cached value for the hardware native buffer size, used when
@@ -179,15 +193,16 @@ class CONTENT_EXPORT WebRtcAudioCapturer
// Range is [0, 255].
int volume_;
- // The source provider to feed the capture data to other clients like
- // WebAudio.
- // TODO(xians): Move the source provider to track once we don't need to feed
- // delay, volume, key_pressed information to WebAudioCapturerSource.
- const scoped_ptr<WebRtcLocalAudioSourceProvider> source_provider_;
-
// Flag which affects the buffer size used by the capturer.
bool peer_connection_mode_;
+ int output_sample_rate_;
+ int output_frames_per_buffer_;
+
+ // Cache value for the audio processing params.
+ base::TimeDelta audio_delay_;
+ bool key_pressed_;
+
DISALLOW_COPY_AND_ASSIGN(WebRtcAudioCapturer);
};
diff --git a/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.cc b/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.cc
deleted file mode 100644
index 59de5107c0f..00000000000
--- a/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/webrtc_audio_capturer_sink_owner.h"
-
-namespace content {
-
-WebRtcAudioCapturerSinkOwner::WebRtcAudioCapturerSinkOwner(
- WebRtcAudioCapturerSink* sink)
- : delegate_(sink) {
-}
-
-int WebRtcAudioCapturerSinkOwner::CaptureData(const std::vector<int>& channels,
- const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) {
- base::AutoLock lock(lock_);
- if (delegate_) {
- delegate_->CaptureData(channels,
- audio_data,
- sample_rate,
- number_of_channels,
- number_of_frames,
- audio_delay_milliseconds,
- current_volume,
- need_audio_processing,
- key_pressed);
- }
-
- return 0;
-}
-
-void WebRtcAudioCapturerSinkOwner::SetCaptureFormat(
- const media::AudioParameters& params) {
- base::AutoLock lock(lock_);
- if (delegate_)
- delegate_->SetCaptureFormat(params);
-}
-
-bool WebRtcAudioCapturerSinkOwner::IsEqual(
- const WebRtcAudioCapturerSink* other) const {
- base::AutoLock lock(lock_);
- return (other == delegate_);
-}
-
-void WebRtcAudioCapturerSinkOwner::Reset() {
- base::AutoLock lock(lock_);
- delegate_ = NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.h b/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.h
deleted file mode 100644
index f338209224d..00000000000
--- a/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.h
+++ /dev/null
@@ -1,66 +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_MEDIA_WEBRTC_AUDIO_CAPTURER_SINK_OWNER_H_
-#define CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_CAPTURER_SINK_OWNER_H_
-
-#include <vector>
-
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "content/renderer/media/webrtc_audio_device_impl.h"
-#include "media/audio/audio_parameters.h"
-
-namespace content {
-
-class WebRtcAudioCapturerSink;
-
-// Reference counted container of WebRtcAudioCapturerSink delegates.
-class WebRtcAudioCapturerSinkOwner
- : public base::RefCountedThreadSafe<WebRtcAudioCapturerSinkOwner>,
- public WebRtcAudioCapturerSink {
- public:
- explicit WebRtcAudioCapturerSinkOwner(WebRtcAudioCapturerSink* sink);
-
- // WebRtcAudioCapturerSink implementation.
- virtual int CaptureData(const std::vector<int>& channels,
- const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) OVERRIDE;
-
- virtual void SetCaptureFormat(const media::AudioParameters& params) OVERRIDE;
-
- bool IsEqual(const WebRtcAudioCapturerSink* other) const;
- void Reset();
-
- // Wrapper which allows to use std::find_if() when adding and removing
- // sinks to/from the list.
- struct WrapsSink {
- WrapsSink(WebRtcAudioCapturerSink* sink) : sink_(sink) {}
- bool operator()(
- const scoped_refptr<WebRtcAudioCapturerSinkOwner>& owner) {
- return owner->IsEqual(sink_);
- }
- WebRtcAudioCapturerSink* sink_;
- };
-
- protected:
- virtual ~WebRtcAudioCapturerSinkOwner() {}
-
- private:
- friend class base::RefCountedThreadSafe<WebRtcAudioCapturerSinkOwner>;
- WebRtcAudioCapturerSink* delegate_;
- mutable base::Lock lock_;
-
- DISALLOW_COPY_AND_ASSIGN(WebRtcAudioCapturerSinkOwner);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_CAPTURER_SINK_OWNER_H_
diff --git a/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc b/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc
new file mode 100644
index 00000000000..184ba0155ab
--- /dev/null
+++ b/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc
@@ -0,0 +1,174 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "content/renderer/media/rtc_media_constraints.h"
+#include "content/renderer/media/webrtc_audio_capturer.h"
+#include "content/renderer/media/webrtc_local_audio_track.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_bus.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::AtLeast;
+
+namespace content {
+
+namespace {
+
+// TODO(xians): Consolidate the similar methods in different unittests into
+// one.
+void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints) {
+ // Constant constraint keys which enables default audio constraints on
+ // mediastreams with audio.
+ struct {
+ const char* key;
+ const char* value;
+ } static const kDefaultAudioConstraints[] = {
+ { webrtc::MediaConstraintsInterface::kEchoCancellation,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ #if defined(OS_CHROMEOS) || defined(OS_MACOSX)
+ // Enable the extended filter mode AEC on platforms with known echo issues.
+ { webrtc::MediaConstraintsInterface::kExperimentalEchoCancellation,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ #endif
+ { webrtc::MediaConstraintsInterface::kAutoGainControl,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ { webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ { webrtc::MediaConstraintsInterface::kNoiseSuppression,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ { webrtc::MediaConstraintsInterface::kHighpassFilter,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) {
+ constraints->AddMandatory(kDefaultAudioConstraints[i].key,
+ kDefaultAudioConstraints[i].value, false);
+ }
+}
+
+class MockCapturerSource : public media::AudioCapturerSource {
+ public:
+ MockCapturerSource() {}
+ MOCK_METHOD3(Initialize, void(const media::AudioParameters& params,
+ CaptureCallback* callback,
+ int session_id));
+ MOCK_METHOD0(Start, void());
+ MOCK_METHOD0(Stop, void());
+ MOCK_METHOD1(SetVolume, void(double volume));
+ MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
+
+ protected:
+ virtual ~MockCapturerSource() {}
+};
+
+class MockPeerConnectionAudioSink : public PeerConnectionAudioSink {
+ public:
+ MockPeerConnectionAudioSink() {}
+ ~MockPeerConnectionAudioSink() {}
+ MOCK_METHOD9(OnData, int(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed));
+ MOCK_METHOD1(OnSetFormat, void(const media::AudioParameters& params));
+};
+
+} // namespace
+
+class WebRtcAudioCapturerTest : public testing::Test {
+ protected:
+ WebRtcAudioCapturerTest()
+#if defined(OS_ANDROID)
+ : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO, 48000, 16, 960) {
+ // Android works with a buffer size bigger than 20ms.
+#else
+ : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128) {
+#endif
+ capturer_ = WebRtcAudioCapturer::CreateCapturer();
+ capturer_->Initialize(-1, params_.channel_layout(), params_.sample_rate(),
+ params_.frames_per_buffer(), 0, std::string(), 0, 0,
+ params_.effects());
+ capturer_source_ = new MockCapturerSource();
+ EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0));
+ capturer_->SetCapturerSource(capturer_source_,
+ params_.channel_layout(),
+ params_.sample_rate(),
+ params_.effects());
+
+ EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*capturer_source_.get(), Start());
+ RTCMediaConstraints constraints;
+ ApplyFixedAudioConstraints(&constraints);
+ track_ = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL,
+ NULL, &constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track_->audio_source_provider())->SetSinkParamsForTesting(params_);
+ track_->Start();
+ EXPECT_TRUE(track_->enabled());
+ }
+
+ media::AudioParameters params_;
+ scoped_refptr<MockCapturerSource> capturer_source_;
+ scoped_refptr<WebRtcAudioCapturer> capturer_;
+ scoped_refptr<WebRtcLocalAudioTrack> track_;
+};
+
+// Pass the delay value, vollume and key_pressed info via capture callback, and
+// those values should be correctly stored and passed to the track.
+TEST_F(WebRtcAudioCapturerTest, VerifyAudioParams) {
+ // Connect a mock sink to the track.
+ scoped_ptr<MockPeerConnectionAudioSink> sink(
+ new MockPeerConnectionAudioSink());
+ track_->AddSink(sink.get());
+
+ int delay_ms = 65;
+ bool key_pressed = true;
+ double volume = 0.9;
+ // MaxVolume() in WebRtcAudioCapturer is hard-coded to return 255, we add 0.5
+ // to do the correct truncation as how the production code does.
+ int expected_volume_value = volume * capturer_->MaxVolume() + 0.5;
+ scoped_ptr<media::AudioBus> audio_bus = media::AudioBus::Create(params_);
+ audio_bus->Zero();
+#if defined(OS_ANDROID)
+ const int expected_buffer_size = params_.sample_rate() / 100;
+#else
+ const int expected_buffer_size = params_.frames_per_buffer();
+#endif
+ bool expected_need_audio_processing = true;
+ media::AudioCapturerSource::CaptureCallback* callback =
+ static_cast<media::AudioCapturerSource::CaptureCallback*>(capturer_);
+ // Verify the sink is getting the correct values.
+ EXPECT_CALL(*sink, OnSetFormat(_));
+ EXPECT_CALL(*sink,
+ OnData(_, params_.sample_rate(), params_.channels(),
+ expected_buffer_size, _, delay_ms,
+ expected_volume_value, expected_need_audio_processing,
+ key_pressed)).Times(AtLeast(1));
+ callback->Capture(audio_bus.get(), delay_ms, volume, key_pressed);
+
+ // Verify the cached values in the capturer fits what we expect.
+ base::TimeDelta cached_delay;
+ int cached_volume = !expected_volume_value;
+ bool cached_key_pressed = !key_pressed;
+ capturer_->GetAudioProcessingParams(&cached_delay, &cached_volume,
+ &cached_key_pressed);
+ EXPECT_EQ(cached_delay.InMilliseconds(), delay_ms);
+ EXPECT_EQ(cached_volume, expected_volume_value);
+ EXPECT_EQ(cached_key_pressed, key_pressed);
+
+ track_->RemoveSink(sink.get());
+ EXPECT_CALL(*capturer_source_.get(), Stop());
+ capturer_->Stop();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_audio_device_impl.cc b/chromium/content/renderer/media/webrtc_audio_device_impl.cc
index 0692ddc55ba..1daf048fe86 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_impl.cc
+++ b/chromium/content/renderer/media/webrtc_audio_device_impl.cc
@@ -12,7 +12,6 @@
#include "content/renderer/media/webrtc_audio_renderer.h"
#include "content/renderer/render_thread_impl.h"
#include "media/audio/audio_parameters.h"
-#include "media/audio/audio_util.h"
#include "media/audio/sample_rates.h"
using media::AudioParameters;
@@ -28,7 +27,6 @@ WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()
initialized_(false),
playing_(false),
recording_(false),
- agc_is_enabled_(false),
microphone_volume_(0) {
DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()";
}
@@ -52,15 +50,15 @@ int32_t WebRtcAudioDeviceImpl::Release() {
}
return ret;
}
-int WebRtcAudioDeviceImpl::CaptureData(const std::vector<int>& channels,
- const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) {
+int WebRtcAudioDeviceImpl::OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) {
int total_delay_ms = 0;
{
base::AutoLock auto_lock(lock_);
@@ -80,6 +78,7 @@ int WebRtcAudioDeviceImpl::CaptureData(const std::vector<int>& channels,
// buffer is empty.
const int16* audio_buffer = audio_data;
const int samples_per_10_msec = (sample_rate / 100);
+ CHECK_EQ(number_of_frames % samples_per_10_msec, 0);
int accumulated_audio_samples = 0;
uint32_t new_volume = 0;
while (accumulated_audio_samples < number_of_frames) {
@@ -107,10 +106,9 @@ int WebRtcAudioDeviceImpl::CaptureData(const std::vector<int>& channels,
return new_volume;
}
-void WebRtcAudioDeviceImpl::SetCaptureFormat(
+void WebRtcAudioDeviceImpl::OnSetFormat(
const media::AudioParameters& params) {
- DVLOG(1) << "WebRtcAudioDeviceImpl::SetCaptureFormat()";
- DCHECK(thread_checker_.CalledOnValidThread());
+ DVLOG(1) << "WebRtcAudioDeviceImpl::OnSetFormat()";
}
void WebRtcAudioDeviceImpl::RenderData(uint8* audio_data,
@@ -319,37 +317,6 @@ bool WebRtcAudioDeviceImpl::Recording() const {
return recording_;
}
-int32_t WebRtcAudioDeviceImpl::SetAGC(bool enable) {
- DVLOG(1) << "WebRtcAudioDeviceImpl::SetAGC(enable=" << enable << ")";
- DCHECK(initialized_);
-
- // Return early if we are not changing the AGC state.
- if (enable == agc_is_enabled_)
- return 0;
-
- // Set the AGC on all the capturers. It depends on the source of the
- // capturer whether AGC is supported or not.
- // The current implementation does not support changing the AGC state while
- // recording. Using this approach simplifies the design and it is also
- // inline with the latest WebRTC standard.
- for (CapturerList::const_iterator iter = capturers_.begin();
- iter != capturers_.end(); ++iter) {
- if (!(*iter)->is_recording())
- (*iter)->SetAutomaticGainControl(enable);
- }
-
- agc_is_enabled_ = enable;
- return 0;
-}
-
-bool WebRtcAudioDeviceImpl::AGC() const {
- DVLOG(1) << "WebRtcAudioDeviceImpl::AGC()";
- DCHECK(thread_checker_.CalledOnValidThread());
- // To reduce the usage of IPC messages, an internal AGC state is used.
- // TODO(henrika): investigate if there is a need for a "deeper" getter.
- return agc_is_enabled_;
-}
-
int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) {
DVLOG(1) << "WebRtcAudioDeviceImpl::SetMicrophoneVolume(" << volume << ")";
DCHECK(initialized_);
@@ -375,6 +342,7 @@ int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const {
return -1;
*volume = static_cast<uint32_t>(capturer->Volume());
+
return 0;
}
@@ -459,10 +427,6 @@ void WebRtcAudioDeviceImpl::AddAudioCapturer(
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(capturer.get());
- // Enable/disable the AGC on the new capture.
- DCHECK(!capturer->is_recording());
- capturer->SetAutomaticGainControl(agc_is_enabled_);
-
// We only support one microphone today, which means the list can contain
// only one capturer with a valid device id.
DCHECK(capturer->device_id().empty() || !GetDefaultCapturer());
diff --git a/chromium/content/renderer/media/webrtc_audio_device_impl.h b/chromium/content/renderer/media/webrtc_audio_device_impl.h
index b644178030b..f515c6e24cb 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_impl.h
+++ b/chromium/content/renderer/media/webrtc_audio_device_impl.h
@@ -202,7 +202,7 @@ class WebRtcAudioRendererSource {
virtual ~WebRtcAudioRendererSource() {}
};
-class WebRtcAudioCapturerSink {
+class PeerConnectionAudioSink {
public:
// Callback to deliver the captured interleaved data.
// |channels| contains a vector of WebRtc VoE channels.
@@ -216,29 +216,31 @@ class WebRtcAudioCapturerSink {
// audio processing.
// The return value is the new microphone volume, in the range of |0, 255].
// When the volume does not need to be updated, it returns 0.
- virtual int CaptureData(const std::vector<int>& channels,
- const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) = 0;
+ virtual int OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) = 0;
// Set the format for the capture audio parameters.
- virtual void SetCaptureFormat(const media::AudioParameters& params) = 0;
+ // This is called when the capture format has changed, and it must be called
+ // on the same thread as calling CaptureData().
+ virtual void OnSetFormat(const media::AudioParameters& params) = 0;
protected:
- virtual ~WebRtcAudioCapturerSink() {}
+ virtual ~PeerConnectionAudioSink() {}
};
// Note that this class inherits from webrtc::AudioDeviceModule but due to
// the high number of non-implemented methods, we move the cruft over to the
// WebRtcAudioDeviceNotImpl.
class CONTENT_EXPORT WebRtcAudioDeviceImpl
- : NON_EXPORTED_BASE(public WebRtcAudioDeviceNotImpl),
- NON_EXPORTED_BASE(public WebRtcAudioCapturerSink),
+ : NON_EXPORTED_BASE(public PeerConnectionAudioSink),
+ NON_EXPORTED_BASE(public WebRtcAudioDeviceNotImpl),
NON_EXPORTED_BASE(public WebRtcAudioRendererSource) {
public:
// The maximum volume value WebRtc uses.
@@ -278,11 +280,6 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl
virtual int32_t StopRecording() OVERRIDE;
virtual bool Recording() const OVERRIDE;
- // Called on the main render thread and libJingle worker thread.
- virtual int32_t SetAGC(bool enable) OVERRIDE;
-
- virtual bool AGC() const OVERRIDE;
-
// Called on the AudioInputDevice worker thread.
virtual int32_t SetMicrophoneVolume(uint32_t volume) OVERRIDE;
@@ -330,21 +327,21 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl
// Make destructor private to ensure that we can only be deleted by Release().
virtual ~WebRtcAudioDeviceImpl();
- // WebRtcAudioCapturerSink implementation.
+ // PeerConnectionAudioSink implementation.
// Called on the AudioInputDevice worker thread.
- virtual int CaptureData(const std::vector<int>& channels,
- const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) OVERRIDE;
+ virtual int OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) OVERRIDE;
- // Called on the main render thread.
- virtual void SetCaptureFormat(const media::AudioParameters& params) OVERRIDE;
+ // Called on the AudioInputDevice worker thread.
+ virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
// WebRtcAudioRendererSource implementation.
@@ -392,9 +389,6 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl
bool playing_;
bool recording_;
- // Local copy of the current Automatic Gain Control state.
- bool agc_is_enabled_;
-
// Used for histograms of total recording and playout times.
base::Time start_capture_time_;
base::Time start_render_time_;
diff --git a/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc b/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc
index fd21fcb2ea6..a126acdaaf7 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc
+++ b/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc
@@ -274,4 +274,12 @@ int32_t WebRtcAudioDeviceNotImpl::GetLoudspeakerStatus(bool* enabled) const {
return 0;
}
+int32_t WebRtcAudioDeviceNotImpl::SetAGC(bool enable) {
+ return 0;
+}
+
+bool WebRtcAudioDeviceNotImpl::AGC() const {
+ return true;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_audio_device_not_impl.h b/chromium/content/renderer/media/webrtc_audio_device_not_impl.h
index af48ad4b81f..041c7d43a8c 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_not_impl.h
+++ b/chromium/content/renderer/media/webrtc_audio_device_not_impl.h
@@ -106,6 +106,8 @@ class CONTENT_EXPORT WebRtcAudioDeviceNotImpl
virtual int32_t ResetAudioDevice() OVERRIDE;
virtual int32_t SetLoudspeakerStatus(bool enable) OVERRIDE;
virtual int32_t GetLoudspeakerStatus(bool* enabled) const OVERRIDE;
+ virtual int32_t SetAGC(bool enable) OVERRIDE;
+ virtual bool AGC() const OVERRIDE;
protected:
virtual ~WebRtcAudioDeviceNotImpl() {};
diff --git a/chromium/content/renderer/media/webrtc_audio_device_unittest.cc b/chromium/content/renderer/media/webrtc_audio_device_unittest.cc
index 7a194e6b451..d6821f6fba0 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_audio_device_unittest.cc
@@ -120,7 +120,8 @@ bool CreateAndInitializeCapturer(WebRtcAudioDeviceImpl* webrtc_audio_device) {
media::ChannelLayout channel_layout =
hardware_config->GetInputChannelLayout();
if (!capturer->Initialize(kRenderViewId, channel_layout, sample_rate, 0, 1,
- media::AudioManagerBase::kDefaultDeviceId)) {
+ media::AudioManagerBase::kDefaultDeviceId, 0, 0,
+ media::AudioParameters::NO_EFFECTS)) {
return false;
}
@@ -135,7 +136,7 @@ bool CreateAndInitializeCapturer(WebRtcAudioDeviceImpl* webrtc_audio_device) {
// Also, connect the sink to the audio track.
scoped_refptr<WebRtcLocalAudioTrack>
CreateAndStartLocalAudioTrack(WebRtcAudioCapturer* capturer,
- WebRtcAudioCapturerSink* sink) {
+ PeerConnectionAudioSink* sink) {
scoped_refptr<WebRtcLocalAudioTrack> local_audio_track(
WebRtcLocalAudioTrack::Create(std::string(), capturer, NULL, NULL, NULL));
local_audio_track->AddSink(sink);
@@ -205,37 +206,38 @@ class WebRTCMediaProcessImpl : public webrtc::VoEMediaProcess {
DISALLOW_COPY_AND_ASSIGN(WebRTCMediaProcessImpl);
};
-class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink {
+// TODO(xians): Use MediaStreamAudioSink.
+class MockMediaStreamAudioSink : public PeerConnectionAudioSink {
public:
- explicit MockWebRtcAudioCapturerSink(base::WaitableEvent* event)
+ explicit MockMediaStreamAudioSink(base::WaitableEvent* event)
: event_(event) {
DCHECK(event_);
}
- virtual ~MockWebRtcAudioCapturerSink() {}
-
- // WebRtcAudioCapturerSink implementation.
- virtual int CaptureData(const std::vector<int>& channels,
- const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) OVERRIDE {
+ virtual ~MockMediaStreamAudioSink() {}
+
+ // PeerConnectionAudioSink implementation.
+ virtual int OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) OVERRIDE {
// Signal that a callback has been received.
event_->Signal();
return 0;
}
// Set the format for the capture audio parameters.
- virtual void SetCaptureFormat(
+ virtual void OnSetFormat(
const media::AudioParameters& params) OVERRIDE {}
private:
base::WaitableEvent* event_;
- DISALLOW_COPY_AND_ASSIGN(MockWebRtcAudioCapturerSink);
+ DISALLOW_COPY_AND_ASSIGN(MockMediaStreamAudioSink);
};
class MockWebRtcAudioRendererSource : public WebRtcAudioRendererSource {
@@ -294,8 +296,8 @@ void ReadDataFromSpeechFile(char* data, int length) {
.Append(FILE_PATH_LITERAL("speech_16b_stereo_48kHz.raw"));
DCHECK(base::PathExists(data_file));
int64 data_file_size64 = 0;
- DCHECK(file_util::GetFileSize(data_file, &data_file_size64));
- EXPECT_EQ(length, file_util::ReadFile(data_file, data, length));
+ DCHECK(base::GetFileSize(data_file, &data_file_size64));
+ EXPECT_EQ(length, base::ReadFile(data_file, data, length));
DCHECK(data_file_size64 > length);
}
@@ -329,13 +331,13 @@ int RunWebRtcLoopbackTimeTest(media::AudioManager* manager,
int err = base->Init(webrtc_audio_device.get());
EXPECT_EQ(0, err);
- // We use SetCaptureFormat() and SetRenderFormat() to configure the audio
+ // We use OnSetFormat() and SetRenderFormat() to configure the audio
// parameters so that this test can run on machine without hardware device.
const media::AudioParameters params = media::AudioParameters(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
48000, 2, 480);
- WebRtcAudioCapturerSink* capturer_sink =
- static_cast<WebRtcAudioCapturerSink*>(webrtc_audio_device.get());
+ PeerConnectionAudioSink* capturer_sink =
+ static_cast<PeerConnectionAudioSink*>(webrtc_audio_device.get());
WebRtcAudioRendererSource* renderer_source =
static_cast<WebRtcAudioRendererSource*>(webrtc_audio_device.get());
renderer_source->SetRenderFormat(params);
@@ -379,12 +381,12 @@ int RunWebRtcLoopbackTimeTest(media::AudioManager* manager,
voe_channels.push_back(channel);
for (int j = 0; j < kNumberOfPacketsForLoopbackTest; ++j) {
// Sending fake capture data to WebRtc.
- capturer_sink->CaptureData(
- voe_channels,
+ capturer_sink->OnData(
reinterpret_cast<int16*>(capture_data.get() + input_packet_size * j),
params.sample_rate(),
params.channels(),
params.frames_per_buffer(),
+ voe_channels,
kHardwareLatencyInMs,
1.0,
enable_apm,
@@ -512,20 +514,10 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_StartPlayout) {
scoped_ptr<media::AudioHardwareConfig> config =
CreateRealHardwareConfig(audio_manager_.get());
SetAudioHardwareConfig(config.get());
- media::AudioParameters params(config->GetOutputConfig());
if (!HardwareSampleRatesAreValid())
return;
- EXPECT_CALL(media_observer(),
- OnAudioStreamCreated(_, 1, params, StrEq(""))).Times(1);
- EXPECT_CALL(media_observer(),
- OnSetAudioStreamPlaying(_, 1, true)).Times(1);
- EXPECT_CALL(media_observer(),
- OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1);
- EXPECT_CALL(media_observer(),
- OnDeleteAudioStream(_, 1)).Times(AnyNumber());
-
WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
ASSERT_TRUE(engine.valid());
ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
@@ -673,7 +665,7 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_StartRecording) {
ch, webrtc::kRecordingPerChannel));
EXPECT_EQ(0, base->StopSend(ch));
- local_audio_track->Stop();
+ webrtc_audio_device->GetDefaultCapturer()->Stop();
EXPECT_EQ(0, base->DeleteChannel(ch));
EXPECT_EQ(0, base->Terminate());
}
@@ -698,20 +690,10 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_PlayLocalFile) {
scoped_ptr<media::AudioHardwareConfig> config =
CreateRealHardwareConfig(audio_manager_.get());
SetAudioHardwareConfig(config.get());
- media::AudioParameters params(config->GetOutputConfig());
if (!HardwareSampleRatesAreValid())
return;
- EXPECT_CALL(media_observer(),
- OnAudioStreamCreated(_, 1, params, StrEq(""))).Times(1);
- EXPECT_CALL(media_observer(),
- OnSetAudioStreamPlaying(_, 1, true)).Times(1);
- EXPECT_CALL(media_observer(),
- OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1);
- EXPECT_CALL(media_observer(),
- OnDeleteAudioStream(_, 1)).Times(AnyNumber());
-
WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
ASSERT_TRUE(engine.valid());
ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
@@ -779,20 +761,10 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_FullDuplexAudioWithAGC) {
scoped_ptr<media::AudioHardwareConfig> config =
CreateRealHardwareConfig(audio_manager_.get());
SetAudioHardwareConfig(config.get());
- media::AudioParameters params(config->GetOutputConfig());
if (!HardwareSampleRatesAreValid())
return;
- EXPECT_CALL(media_observer(),
- OnAudioStreamCreated(_, 1, params, StrEq(""))).Times(1);
- EXPECT_CALL(media_observer(),
- OnSetAudioStreamPlaying(_, 1, true));
- EXPECT_CALL(media_observer(),
- OnSetAudioStreamStatus(_, 1, StrEq("closed")));
- EXPECT_CALL(media_observer(),
- OnDeleteAudioStream(_, 1)).Times(AnyNumber());
-
WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
ASSERT_TRUE(engine.valid());
ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
@@ -845,13 +817,13 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_FullDuplexAudioWithAGC) {
proxy->Start();
proxy->Play();
- LOG(INFO) << ">> You should now be able to hear yourself in loopback...";
+ VLOG(0) << ">> You should now be able to hear yourself in loopback...";
message_loop_.PostDelayedTask(FROM_HERE,
base::MessageLoop::QuitClosure(),
base::TimeDelta::FromSeconds(2));
message_loop_.Run();
- local_audio_track->Stop();
+ webrtc_audio_device->GetDefaultCapturer()->Stop();
proxy->Stop();
EXPECT_EQ(0, base->StopSend(ch));
EXPECT_EQ(0, base->StopPlayout(ch));
@@ -890,8 +862,8 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, DISABLED_WebRtcRecordingSetupTime) {
EXPECT_TRUE(CreateAndInitializeCapturer(webrtc_audio_device.get()));
base::WaitableEvent event(false, false);
- scoped_ptr<MockWebRtcAudioCapturerSink> sink(
- new MockWebRtcAudioCapturerSink(&event));
+ scoped_ptr<MockMediaStreamAudioSink> sink(
+ new MockMediaStreamAudioSink(&event));
// Create and start a local audio track. Starting the audio track will connect
// the audio track to the capturer and also start the source of the capturer.
@@ -910,8 +882,7 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, DISABLED_WebRtcRecordingSetupTime) {
int delay = (base::Time::Now() - start_time).InMilliseconds();
PrintPerfResultMs("webrtc_recording_setup_c", "t", delay);
- local_audio_track->RemoveSink(sink.get());
- local_audio_track->Stop();
+ webrtc_audio_device->GetDefaultCapturer()->Stop();
EXPECT_EQ(0, base->StopSend(ch));
EXPECT_EQ(0, base->DeleteChannel(ch));
EXPECT_EQ(0, base->Terminate());
@@ -934,20 +905,10 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_WebRtcPlayoutSetupTime) {
scoped_ptr<media::AudioHardwareConfig> config =
CreateRealHardwareConfig(audio_manager_.get());
SetAudioHardwareConfig(config.get());
- media::AudioParameters params(config->GetOutputConfig());
if (!HardwareSampleRatesAreValid())
return;
- EXPECT_CALL(media_observer(),
- OnAudioStreamCreated(_, 1, params, StrEq(""))).Times(1);
- EXPECT_CALL(media_observer(),
- OnSetAudioStreamStatus(_, 1, _)).Times(AnyNumber());
- EXPECT_CALL(media_observer(),
- OnSetAudioStreamPlaying(_, 1, true));
- EXPECT_CALL(media_observer(),
- OnDeleteAudioStream(_, 1)).Times(AnyNumber());
-
base::WaitableEvent event(false, false);
scoped_ptr<MockWebRtcAudioRendererSource> renderer_source(
new MockWebRtcAudioRendererSource(&event));
@@ -980,6 +941,13 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_WebRtcPlayoutSetupTime) {
TEST_F(MAYBE_WebRTCAudioDeviceTest,
MAYBE_WebRtcLoopbackTimeWithoutSignalProcessing) {
+#if defined(OS_WIN)
+ // This test hangs on WinXP: see http://crbug.com/318189.
+ if (base::win::GetVersion() <= base::win::VERSION_XP) {
+ LOG(WARNING) << "Test disabled due to the test hangs on WinXP.";
+ return;
+ }
+#endif
int latency = RunWebRtcLoopbackTimeTest(audio_manager_.get(), false);
PrintPerfResultMs("webrtc_loopback_without_sigal_processing (100 packets)",
"t", latency);
@@ -996,6 +964,13 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest,
TEST_F(MAYBE_WebRTCAudioDeviceTest,
MAYBE_WebRtcLoopbackTimeWithSignalProcessing) {
+#if defined(OS_WIN)
+ // This test hangs on WinXP: see http://crbug.com/318189.
+ if (base::win::GetVersion() <= base::win::VERSION_XP) {
+ LOG(WARNING) << "Test disabled due to the test hangs on WinXP.";
+ return;
+ }
+#endif
int latency = RunWebRtcLoopbackTimeTest(audio_manager_.get(), true);
PrintPerfResultMs("webrtc_loopback_with_signal_processing (100 packets)",
"t", latency);
diff --git a/chromium/content/renderer/media/webrtc_audio_renderer.cc b/chromium/content/renderer/media/webrtc_audio_renderer.cc
index 9955b6e3169..dae29a506aa 100644
--- a/chromium/content/renderer/media/webrtc_audio_renderer.cc
+++ b/chromium/content/renderer/media/webrtc_audio_renderer.cc
@@ -7,8 +7,10 @@
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "content/renderer/media/audio_device_factory.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
+#include "content/renderer/media/webrtc_logging.h"
#include "media/audio/audio_output_device.h"
#include "media/audio/audio_parameters.h"
#include "media/audio/sample_rates.h"
@@ -36,7 +38,6 @@ const int kValidOutputRates[] = {48000, 44100};
// low latency, currently 16000 is used to work around audio problem on some
// Android devices.
const int kValidOutputRates[] = {48000, 44100, 16000};
-const int kDefaultOutputBufferSize = 2048;
#else
const int kValidOutputRates[] = {44100};
#endif
@@ -177,6 +178,13 @@ WebRtcAudioRenderer::WebRtcAudioRenderer(int source_render_view_id,
fifo_delay_milliseconds_(0),
sample_rate_(sample_rate),
frames_per_buffer_(frames_per_buffer) {
+ WebRtcLogMessage(base::StringPrintf(
+ "WAR::WAR. source_render_view_id=%d"
+ ", session_id=%d, sample_rate=%d, frames_per_buffer=%d",
+ source_render_view_id,
+ session_id,
+ sample_rate,
+ frames_per_buffer));
}
WebRtcAudioRenderer::~WebRtcAudioRenderer() {
@@ -194,12 +202,8 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
DCHECK(!sink_.get());
DCHECK(!source_);
- // Use stereo output on all platforms exept Android.
+ // Use stereo output on all platforms.
media::ChannelLayout channel_layout = media::CHANNEL_LAYOUT_STEREO;
-#if defined(OS_ANDROID)
- DVLOG(1) << "Using mono audio output for Android";
- channel_layout = media::CHANNEL_LAYOUT_MONO;
-#endif
// TODO(tommi,henrika): Maybe we should just change |sample_rate_| to be
// immutable and change its value instead of using a temporary?
@@ -255,11 +259,23 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
media::AudioParameters sink_params;
-#if defined(OS_ANDROID)
- buffer_size = kDefaultOutputBufferSize;
-#else
+ // Use native output siz as default.
buffer_size = frames_per_buffer_;
+#if 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.
+ const int frames_per_10ms = (sample_rate / 100);
+ if (buffer_size < 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
+ buffer_size = 2 * frames_per_10ms;
+ DVLOG(1) << "Low-latency output detected on Android";
+ }
#endif
+ DVLOG(1) << "Using sink output buffer size: " << buffer_size;
sink_params.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
channel_layout, channels, 0, sample_rate, 16, buffer_size);
diff --git a/chromium/content/renderer/media/webrtc_local_audio_renderer.cc b/chromium/content/renderer/media/webrtc_local_audio_renderer.cc
index 3b94e2416b3..6a92d906d32 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_renderer.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_renderer.cc
@@ -7,6 +7,7 @@
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/metrics/histogram.h"
#include "base/synchronization/lock.h"
#include "content/renderer/media/audio_device_factory.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
@@ -16,20 +17,27 @@
namespace content {
+namespace {
+
+enum LocalRendererSinkStates {
+ kSinkStarted = 0,
+ kSinkNeverStarted,
+ kSinkStatesMax // Must always be last!
+};
+
+} // namespace
+
// media::AudioRendererSink::RenderCallback implementation
int WebRtcLocalAudioRenderer::Render(
media::AudioBus* audio_bus, int audio_delay_milliseconds) {
+ TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::Render");
base::AutoLock auto_lock(thread_lock_);
- if (!playing_) {
+ if (!playing_ || !volume_ || !loopback_fifo_) {
audio_bus->Zero();
return 0;
}
- TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::Render");
-
- DCHECK(loopback_fifo_.get() != NULL);
-
// Provide data by reading from the FIFO if the FIFO contains enough
// to fulfill the request.
if (loopback_fifo_->frames() >= audio_bus->frames()) {
@@ -48,178 +56,182 @@ void WebRtcLocalAudioRenderer::OnRenderError() {
NOTIMPLEMENTED();
}
-// content::WebRtcAudioCapturerSink implementation
-int WebRtcLocalAudioRenderer::CaptureData(const std::vector<int>& channels,
- const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) {
+// content::MediaStreamAudioSink implementation
+void WebRtcLocalAudioRenderer::OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames) {
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::CaptureData");
base::AutoLock auto_lock(thread_lock_);
-
- if (!playing_)
- return 0;
+ if (!playing_ || !volume_ || !loopback_fifo_)
+ return;
// Push captured audio to FIFO so it can be read by a local sink.
- if (loopback_fifo_) {
- if (loopback_fifo_->frames() + number_of_frames <=
- loopback_fifo_->max_frames()) {
- scoped_ptr<media::AudioBus> audio_source = media::AudioBus::Create(
- number_of_channels, number_of_frames);
- audio_source->FromInterleaved(audio_data,
- audio_source->frames(),
- sizeof(audio_data[0]));
- loopback_fifo_->Push(audio_source.get());
-
- base::Time now = base::Time::Now();
- total_render_time_ += now - last_render_time_;
- last_render_time_ = now;
- } else {
- DVLOG(1) << "FIFO is full";
- }
+ if (loopback_fifo_->frames() + number_of_frames <=
+ loopback_fifo_->max_frames()) {
+ scoped_ptr<media::AudioBus> audio_source = media::AudioBus::Create(
+ number_of_channels, number_of_frames);
+ audio_source->FromInterleaved(audio_data,
+ audio_source->frames(),
+ sizeof(audio_data[0]));
+ loopback_fifo_->Push(audio_source.get());
+
+ const base::TimeTicks now = base::TimeTicks::Now();
+ total_render_time_ += now - last_render_time_;
+ last_render_time_ = now;
+ } else {
+ DVLOG(1) << "FIFO is full";
}
-
- return 0;
}
-void WebRtcLocalAudioRenderer::SetCaptureFormat(
+void WebRtcLocalAudioRenderer::OnSetFormat(
const media::AudioParameters& params) {
- audio_params_ = params;
+ DVLOG(1) << "WebRtcLocalAudioRenderer::OnSetFormat()";
+ // If the source is restarted, we might have changed to another capture
+ // thread.
+ capture_thread_checker_.DetachFromThread();
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
+
+ // Reset the |source_params_|, |sink_params_| and |loopback_fifo_| to match
+ // the new format.
+ {
+ base::AutoLock auto_lock(thread_lock_);
+ if (source_params_ == params)
+ return;
+
+ source_params_ = params;
+
+ sink_params_.Reset(source_params_.format(),
+ source_params_.channel_layout(),
+ source_params_.channels(),
+ source_params_.input_channels(),
+ source_params_.sample_rate(),
+ source_params_.bits_per_sample(),
+#if defined(OS_ANDROID)
+ // On Android, input and output are using same sampling rate. In order to
+ // achieve low latency mode, we need use buffer size suggested by
+ // AudioManager for the sink paramters which will be used to decide
+ // buffer size for shared memory buffer.
+ frames_per_buffer_
+#else
+ 2 * source_params_.frames_per_buffer()
+#endif
+ );
+
+ // TODO(henrika): we could add a more dynamic solution here but I prefer
+ // a fixed size combined with bad audio at overflow. The alternative is
+ // that we start to build up latency and that can be more difficult to
+ // detect. Tests have shown that the FIFO never contains more than 2 or 3
+ // audio frames but I have selected a max size of ten buffers just
+ // in case since these tests were performed on a 16 core, 64GB Win 7
+ // machine. We could also add some sort of error notifier in this area if
+ // the FIFO overflows.
+ loopback_fifo_.reset(new media::AudioFifo(
+ params.channels(), 10 * params.frames_per_buffer()));
+ }
+
+ // Post a task on the main render thread to reconfigure the |sink_| with the
+ // new format.
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&WebRtcLocalAudioRenderer::ReconfigureSink, this,
+ params));
}
// WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer implementation.
WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer(
- WebRtcLocalAudioTrack* audio_track,
+ const blink::WebMediaStreamTrack& audio_track,
int source_render_view_id,
int session_id,
- int sample_rate,
int frames_per_buffer)
: audio_track_(audio_track),
source_render_view_id_(source_render_view_id),
session_id_(session_id),
+ message_loop_(base::MessageLoopProxy::current()),
playing_(false),
- sample_rate_(sample_rate),
- frames_per_buffer_(frames_per_buffer) {
- DCHECK(audio_track);
+ frames_per_buffer_(frames_per_buffer),
+ volume_(0.0),
+ sink_started_(false) {
DVLOG(1) << "WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer()";
}
WebRtcLocalAudioRenderer::~WebRtcLocalAudioRenderer() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK(!sink_.get());
DVLOG(1) << "WebRtcLocalAudioRenderer::~WebRtcLocalAudioRenderer()";
}
void WebRtcLocalAudioRenderer::Start() {
DVLOG(1) << "WebRtcLocalAudioRenderer::Start()";
- DCHECK(thread_checker_.CalledOnValidThread());
- // Add this class as sink to the audio track to ensure that we receive
- // WebRtcAudioCapturerSink::CaptureData() callbacks for captured audio.
- // |audio_params_| will be updated right after the AddCapturerAudioTrack().
- audio_track_->AddSink(this);
+ DCHECK(message_loop_->BelongsToCurrentThread());
- base::AutoLock auto_lock(thread_lock_);
+ // We get audio data from |audio_track_|...
+ MediaStreamAudioSink::AddToAudioTrack(this, audio_track_);
+ // ...and |sink_| will get audio data from us.
DCHECK(!sink_.get());
-
- // TODO(henrika): we could add a more dynamic solution here but I prefer
- // a fixed size combined with bad audio at overflow. The alternative is
- // that we start to build up latency and that can be more difficult to
- // detect. Tests have shown that the FIFO never contains more than 2 or 3
- // audio frames but I have selected a max size of ten buffers just
- // in case since these tests were performed on a 16 core, 64GB Win 7
- // machine. We could also add some sort of error notifier in this area if
- // the FIFO overflows.
- DCHECK(!loopback_fifo_);
- loopback_fifo_.reset(new media::AudioFifo(
- audio_params_.channels(), 10 * audio_params_.frames_per_buffer()));
-
- media::AudioParameters sink_params(audio_params_.format(),
- audio_params_.channel_layout(),
- audio_params_.sample_rate(),
- audio_params_.bits_per_sample(),
-#if defined(OS_ANDROID)
- // On Android, input and output are using same sampling rate. In order to
- // achieve low latency mode, we need use buffer size suggested by
- // AudioManager for the sink paramters which will be used to decide
- // buffer size for shared memory buffer.
- frames_per_buffer_
-#else
- 2 * audio_params_.frames_per_buffer()
-#endif
- );
-
sink_ = AudioDeviceFactory::NewOutputDevice(source_render_view_id_);
- // TODO(henrika): we could utilize the unified audio here instead and do
- // sink_->InitializeIO(sink_params, 2, callback_.get());
- // It would then be possible to avoid using the WebRtcAudioCapturer.
- sink_->InitializeUnifiedStream(sink_params, this, session_id_);
-
- // Start the capturer and local rendering. Note that, the capturer is owned
- // by the WebRTC ADM and might already bee running.
- sink_->Start();
-
- last_render_time_ = base::Time::Now();
+ base::AutoLock auto_lock(thread_lock_);
+ last_render_time_ = base::TimeTicks::Now();
playing_ = false;
}
void WebRtcLocalAudioRenderer::Stop() {
DVLOG(1) << "WebRtcLocalAudioRenderer::Stop()";
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (!sink_.get())
- return;
+ DCHECK(message_loop_->BelongsToCurrentThread());
{
base::AutoLock auto_lock(thread_lock_);
playing_ = false;
-
- if (loopback_fifo_.get() != NULL) {
- loopback_fifo_->Clear();
- loopback_fifo_.reset();
- }
+ loopback_fifo_.reset();
}
// Stop the output audio stream, i.e, stop asking for data to render.
- sink_->Stop();
- sink_ = NULL;
+ // It is safer to call Stop() on the |sink_| to clean up the resources even
+ // when the |sink_| is never started.
+ if (sink_) {
+ sink_->Stop();
+ sink_ = NULL;
+ }
+
+ if (!sink_started_) {
+ UMA_HISTOGRAM_ENUMERATION("Media.LocalRendererSinkStates",
+ kSinkNeverStarted, kSinkStatesMax);
+ }
+ sink_started_ = false;
// Ensure that the capturer stops feeding us with captured audio.
- // Note that, we do not stop the capturer here since it may still be used by
- // the WebRTC ADM.
- audio_track_->RemoveSink(this);
- audio_track_ = NULL;
+ MediaStreamAudioSink::RemoveFromAudioTrack(this, audio_track_);
}
void WebRtcLocalAudioRenderer::Play() {
DVLOG(1) << "WebRtcLocalAudioRenderer::Play()";
- DCHECK(thread_checker_.CalledOnValidThread());
- base::AutoLock auto_lock(thread_lock_);
+ DCHECK(message_loop_->BelongsToCurrentThread());
if (!sink_.get())
return;
- // Resumes rendering by ensuring that WebRtcLocalAudioRenderer::Render()
- // now reads data from the local FIFO.
- playing_ = true;
- last_render_time_ = base::Time::Now();
+ {
+ base::AutoLock auto_lock(thread_lock_);
+ // Resumes rendering by ensuring that WebRtcLocalAudioRenderer::Render()
+ // now reads data from the local FIFO.
+ playing_ = true;
+ last_render_time_ = base::TimeTicks::Now();
+ }
- if (loopback_fifo_)
- loopback_fifo_->Clear();
+ // Note: If volume_ is currently muted, the |sink_| will not be started yet.
+ MaybeStartSink();
}
void WebRtcLocalAudioRenderer::Pause() {
DVLOG(1) << "WebRtcLocalAudioRenderer::Pause()";
- DCHECK(thread_checker_.CalledOnValidThread());
- base::AutoLock auto_lock(thread_lock_);
+ DCHECK(message_loop_->BelongsToCurrentThread());
if (!sink_.get())
return;
+ base::AutoLock auto_lock(thread_lock_);
// Temporarily suspends rendering audio.
// WebRtcLocalAudioRenderer::Render() will return early during this state
// and only zeros will be provided to the active sink.
@@ -228,14 +240,24 @@ void WebRtcLocalAudioRenderer::Pause() {
void WebRtcLocalAudioRenderer::SetVolume(float volume) {
DVLOG(1) << "WebRtcLocalAudioRenderer::SetVolume(" << volume << ")";
- DCHECK(thread_checker_.CalledOnValidThread());
- base::AutoLock auto_lock(thread_lock_);
+ DCHECK(message_loop_->BelongsToCurrentThread());
+
+ {
+ base::AutoLock auto_lock(thread_lock_);
+ // Cache the volume.
+ volume_ = volume;
+ }
+
+ // Lazily start the |sink_| when the local renderer is unmuted during
+ // playing.
+ MaybeStartSink();
+
if (sink_.get())
sink_->SetVolume(volume);
}
base::TimeDelta WebRtcLocalAudioRenderer::GetCurrentRenderTime() const {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(message_loop_->BelongsToCurrentThread());
base::AutoLock auto_lock(thread_lock_);
if (!sink_.get())
return base::TimeDelta();
@@ -246,4 +268,46 @@ bool WebRtcLocalAudioRenderer::IsLocalRenderer() const {
return true;
}
+void WebRtcLocalAudioRenderer::MaybeStartSink() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DVLOG(1) << "WebRtcLocalAudioRenderer::MaybeStartSink()";
+
+ if (!sink_.get() || !source_params_.IsValid())
+ return;
+
+ base::AutoLock auto_lock(thread_lock_);
+
+ // Clear up the old data in the FIFO.
+ loopback_fifo_->Clear();
+
+ if (!sink_params_.IsValid() || !playing_ || !volume_ || sink_started_)
+ return;
+
+ DVLOG(1) << "WebRtcLocalAudioRenderer::MaybeStartSink() -- Starting sink_.";
+ sink_->InitializeUnifiedStream(sink_params_, this, session_id_);
+ sink_->Start();
+ sink_started_ = true;
+ UMA_HISTOGRAM_ENUMERATION("Media.LocalRendererSinkStates",
+ kSinkStarted, kSinkStatesMax);
+}
+
+void WebRtcLocalAudioRenderer::ReconfigureSink(
+ const media::AudioParameters& params) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+
+ DVLOG(1) << "WebRtcLocalAudioRenderer::ReconfigureSink()";
+
+ if (!sink_)
+ return; // WebRtcLocalAudioRenderer has not yet been started.
+
+ // Stop |sink_| and re-create a new one to be initialized with different audio
+ // parameters. Then, invoke MaybeStartSink() to restart everything again.
+ if (sink_started_) {
+ sink_->Stop();
+ sink_started_ = false;
+ }
+ sink_ = AudioDeviceFactory::NewOutputDevice(source_render_view_id_);
+ MaybeStartSink();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_local_audio_renderer.h b/chromium/content/renderer/media/webrtc_local_audio_renderer.h
index f77d523f4a6..e9871ece81b 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_renderer.h
+++ b/chromium/content/renderer/media/webrtc_local_audio_renderer.h
@@ -9,12 +9,15 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop_proxy.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
+#include "content/public/renderer/media_stream_audio_sink.h"
#include "content/renderer/media/media_stream_audio_renderer.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
namespace media {
class AudioBus;
@@ -33,7 +36,7 @@ class WebRtcAudioCapturer;
// It also implements media::AudioRendererSink::RenderCallback to render audio
// data provided from a WebRtcLocalAudioTrack source.
// When the audio layer in the browser process asks for data to render, this
-// class provides the data by implementing the WebRtcAudioCapturerSink
+// class provides the data by implementing the MediaStreamAudioSink
// interface, i.e., we are a sink seen from the WebRtcAudioCapturer perspective.
// TODO(henrika): improve by using similar principles as in RTCVideoRenderer
// which register itself to the video track when the provider is started and
@@ -41,16 +44,15 @@ class WebRtcAudioCapturer;
// Tracking this at http://crbug.com/164813.
class CONTENT_EXPORT WebRtcLocalAudioRenderer
: NON_EXPORTED_BASE(public MediaStreamAudioRenderer),
- NON_EXPORTED_BASE(public media::AudioRendererSink::RenderCallback),
- NON_EXPORTED_BASE(public WebRtcAudioCapturerSink) {
+ NON_EXPORTED_BASE(public MediaStreamAudioSink),
+ NON_EXPORTED_BASE(public media::AudioRendererSink::RenderCallback) {
public:
// Creates a local renderer and registers a capturing |source| object.
// The |source| is owned by the WebRtcAudioDeviceImpl.
// Called on the main thread.
- WebRtcLocalAudioRenderer(WebRtcLocalAudioTrack* audio_track,
+ WebRtcLocalAudioRenderer(const blink::WebMediaStreamTrack& audio_track,
int source_render_view_id,
int session_id,
- int sample_rate,
int frames_per_buffer);
// MediaStreamAudioRenderer implementation.
@@ -71,21 +73,16 @@ class CONTENT_EXPORT WebRtcLocalAudioRenderer
virtual ~WebRtcLocalAudioRenderer();
private:
- // WebRtcAudioCapturerSink implementation.
+ // MediaStreamAudioSink implementation.
// Called on the AudioInputDevice worker thread.
- virtual int CaptureData(const std::vector<int>& channels,
- const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) OVERRIDE;
-
- // Can be called on different user thread.
- virtual void SetCaptureFormat(const media::AudioParameters& params) OVERRIDE;
+ virtual void OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames) OVERRIDE;
+
+ // Called on the AudioInputDevice worker thread.
+ virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
// media::AudioRendererSink::RenderCallback implementation.
// Render() is called on the AudioOutputDevice thread and OnRenderError()
@@ -94,37 +91,52 @@ class CONTENT_EXPORT WebRtcLocalAudioRenderer
int audio_delay_milliseconds) OVERRIDE;
virtual void OnRenderError() OVERRIDE;
+ // Initializes and starts the |sink_| if
+ // we have received valid |source_params_| &&
+ // |playing_| has been set to true &&
+ // |volume_| is not zero.
+ void MaybeStartSink();
+
+ // Sets new |source_params_| and then re-initializes and restarts |sink_|.
+ void ReconfigureSink(const media::AudioParameters& params);
+
// The audio track which provides data to render. Given that this class
// implements local loopback, the audio track is getting data from a capture
// instance like a selected microphone and forwards the recorded data to its
// sinks. The recorded data is stored in a FIFO and consumed
// by this class when the sink asks for new data.
- // The WebRtcAudioCapturer is today created by WebRtcAudioDeviceImpl.
- scoped_refptr<WebRtcLocalAudioTrack> audio_track_;
+ // This class is calling MediaStreamAudioSink::AddToAudioTrack() and
+ // MediaStreamAudioSink::RemoveFromAudioTrack() to connect and disconnect
+ // with the audio track.
+ blink::WebMediaStreamTrack audio_track_;
// The render view in which the audio is rendered into |sink_|.
const int source_render_view_id_;
const int session_id_;
+ // MessageLoop associated with the single thread that performs all control
+ // tasks. Set to the MessageLoop that invoked the ctor.
+ const scoped_refptr<base::MessageLoopProxy> message_loop_;
+
// The sink (destination) for rendered audio.
scoped_refptr<media::AudioOutputDevice> sink_;
- // Used to DCHECK that we are called on the correct thread.
- base::ThreadChecker thread_checker_;
-
// Contains copies of captured audio frames.
scoped_ptr<media::AudioFifo> loopback_fifo_;
// Stores last time a render callback was received. The time difference
// between a new time stamp and this value can be used to derive the
// total render time.
- base::Time last_render_time_;
+ base::TimeTicks last_render_time_;
// Keeps track of total time audio has been rendered.
base::TimeDelta total_render_time_;
- // The audio parameters used by the renderer.
- media::AudioParameters audio_params_;
+ // The audio parameters of the capture source.
+ media::AudioParameters source_params_;
+
+ // The audio parameters used by the sink.
+ media::AudioParameters sink_params_;
// Set when playing, cleared when paused.
bool playing_;
@@ -132,14 +144,22 @@ class CONTENT_EXPORT WebRtcLocalAudioRenderer
// Protects |loopback_fifo_|, |playing_| and |sink_|.
mutable base::Lock thread_lock_;
- // The preferred sample rate and buffer sizes provided via the ctor.
- const int sample_rate_;
+ // The preferred buffer size provided via the ctor.
const int frames_per_buffer_;
// The preferred device id of the output device or empty for the default
// output device.
const std::string output_device_id_;
+ // Cache value for the volume.
+ float volume_;
+
+ // Flag to indicate whether |sink_| has been started yet.
+ bool sink_started_;
+
+ // Used to DCHECK that some methods are called on the capture audio thread.
+ base::ThreadChecker capture_thread_checker_;
+
DISALLOW_COPY_AND_ASSIGN(WebRtcLocalAudioRenderer);
};
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 cc70c785a97..bc5f80dfe37 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
@@ -9,9 +9,9 @@
#include "media/audio/audio_parameters.h"
#include "media/base/audio_fifo.h"
#include "media/base/audio_hardware_config.h"
-#include "third_party/WebKit/public/web/WebAudioSourceProviderClient.h"
+#include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h"
-using WebKit::WebVector;
+using blink::WebVector;
namespace content {
@@ -23,111 +23,101 @@ static const size_t kMaxNumberOfBuffers = 10;
const size_t WebRtcLocalAudioSourceProvider::kWebAudioRenderBufferSize = 128;
WebRtcLocalAudioSourceProvider::WebRtcLocalAudioSourceProvider()
- : audio_delay_ms_(0),
- volume_(1),
- key_pressed_(false),
- is_enabled_(false) {
-}
-
-WebRtcLocalAudioSourceProvider::~WebRtcLocalAudioSourceProvider() {
- if (audio_converter_.get())
- audio_converter_->RemoveInput(this);
-}
-
-void WebRtcLocalAudioSourceProvider::Initialize(
- const media::AudioParameters& source_params) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Use the native audio output hardware sample-rate for the sink.
+ : is_enabled_(false) {
+ // Get the native audio output hardware sample-rate for the sink.
+ // We need to check if RenderThreadImpl is valid here since the unittests
+ // do not have one and they will inject their own |sink_params_| for testing.
if (RenderThreadImpl::current()) {
media::AudioHardwareConfig* hardware_config =
RenderThreadImpl::current()->GetAudioHardwareConfig();
int sample_rate = hardware_config->GetOutputSampleRate();
sink_params_.Reset(
- source_params.format(), media::CHANNEL_LAYOUT_STEREO, 2, 0,
- sample_rate, source_params.bits_per_sample(),
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO, 2, 0, sample_rate, 16,
kWebAudioRenderBufferSize);
- } else {
- // This happens on unittests which does not have a valid RenderThreadImpl,
- // the unittests should have injected their own |sink_params_| for testing.
- DCHECK(sink_params_.IsValid());
}
+}
+
+WebRtcLocalAudioSourceProvider::~WebRtcLocalAudioSourceProvider() {
+ if (audio_converter_.get())
+ audio_converter_->RemoveInput(this);
+}
+
+void WebRtcLocalAudioSourceProvider::OnSetFormat(
+ const media::AudioParameters& params) {
+ // We need detach the thread here because it will be a new capture thread
+ // calling OnSetFormat() and OnData() if the source is restarted.
+ capture_thread_checker_.DetachFromThread();
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
+ DCHECK(params.IsValid());
+ DCHECK(sink_params_.IsValid());
base::AutoLock auto_lock(lock_);
- source_params_ = source_params;
+ source_params_ = params;
// Create the audio converter with |disable_fifo| as false so that the
// converter will request source_params.frames_per_buffer() each time.
// This will not increase the complexity as there is only one client to
// the converter.
audio_converter_.reset(
- new media::AudioConverter(source_params, sink_params_, false));
+ new media::AudioConverter(params, sink_params_, false));
audio_converter_->AddInput(this);
fifo_.reset(new media::AudioFifo(
- source_params.channels(),
- kMaxNumberOfBuffers * source_params.frames_per_buffer()));
+ params.channels(),
+ kMaxNumberOfBuffers * params.frames_per_buffer()));
+ input_bus_ = media::AudioBus::Create(params.channels(),
+ params.frames_per_buffer());
}
-void WebRtcLocalAudioSourceProvider::DeliverData(
- media::AudioBus* audio_source,
- int audio_delay_milliseconds,
- int volume,
- bool key_pressed) {
+void WebRtcLocalAudioSourceProvider::OnData(
+ const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames) {
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
if (!is_enabled_)
return;
DCHECK(fifo_.get());
- if (fifo_->frames() + audio_source->frames() <= fifo_->max_frames()) {
- fifo_->Push(audio_source);
+ // TODO(xians): A better way to handle the interleaved and deinterleaved
+ // format switching, see issue/317710.
+ DCHECK(input_bus_->frames() == number_of_frames);
+ DCHECK(input_bus_->channels() == number_of_channels);
+ input_bus_->FromInterleaved(audio_data, number_of_frames, 2);
+
+ if (fifo_->frames() + number_of_frames <= fifo_->max_frames()) {
+ fifo_->Push(input_bus_.get());
} else {
// This can happen if the data in FIFO is too slowed to be consumed or
// WebAudio stops consuming data.
DLOG(WARNING) << "Local source provicer FIFO is full" << fifo_->frames();
}
-
- // Cache the values for GetAudioProcessingParams().
- last_fill_ = base::TimeTicks::Now();
- audio_delay_ms_ = audio_delay_milliseconds;
- volume_ = volume;
- key_pressed_ = key_pressed;
-}
-
-void WebRtcLocalAudioSourceProvider::GetAudioProcessingParams(
- int* delay_ms, int* volume, bool* key_pressed) {
- int elapsed_ms = 0;
- if (!last_fill_.is_null()) {
- elapsed_ms = static_cast<int>(
- (base::TimeTicks::Now() - last_fill_).InMilliseconds());
- }
- *delay_ms = audio_delay_ms_ + elapsed_ms + static_cast<int>(
- 1000 * fifo_->frames() / source_params_.sample_rate() + 0.5);
- *volume = volume_;
- *key_pressed = key_pressed_;
}
void WebRtcLocalAudioSourceProvider::setClient(
- WebKit::WebAudioSourceProviderClient* client) {
+ blink::WebAudioSourceProviderClient* client) {
NOTREACHED();
}
void WebRtcLocalAudioSourceProvider::provideInput(
const WebVector<float*>& audio_data, size_t number_of_frames) {
DCHECK_EQ(number_of_frames, kWebAudioRenderBufferSize);
- if (!bus_wrapper_ ||
- static_cast<size_t>(bus_wrapper_->channels()) != audio_data.size()) {
- bus_wrapper_ = media::AudioBus::CreateWrapper(audio_data.size());
+ if (!output_wrapper_ ||
+ static_cast<size_t>(output_wrapper_->channels()) != audio_data.size()) {
+ output_wrapper_ = media::AudioBus::CreateWrapper(audio_data.size());
}
- bus_wrapper_->set_frames(number_of_frames);
+ output_wrapper_->set_frames(number_of_frames);
for (size_t i = 0; i < audio_data.size(); ++i)
- bus_wrapper_->SetChannelData(i, audio_data[i]);
+ output_wrapper_->SetChannelData(i, audio_data[i]);
base::AutoLock auto_lock(lock_);
- DCHECK(audio_converter_.get());
- DCHECK(fifo_.get());
+ if (!audio_converter_)
+ return;
+
is_enabled_ = true;
- audio_converter_->Convert(bus_wrapper_.get());
+ audio_converter_->Convert(output_wrapper_.get());
}
double WebRtcLocalAudioSourceProvider::ProvideInput(
@@ -136,11 +126,9 @@ double WebRtcLocalAudioSourceProvider::ProvideInput(
fifo_->Consume(audio_bus, 0, audio_bus->frames());
} else {
audio_bus->Zero();
- if (!last_fill_.is_null()) {
- DLOG(WARNING) << "Underrun, FIFO has data " << fifo_->frames()
- << " samples but " << audio_bus->frames()
- << " samples are needed";
- }
+ DVLOG(1) << "WARNING: Underrun, FIFO has data " << fifo_->frames()
+ << " samples but " << audio_bus->frames()
+ << " samples are needed";
}
return 1.0;
@@ -148,7 +136,6 @@ double WebRtcLocalAudioSourceProvider::ProvideInput(
void WebRtcLocalAudioSourceProvider::SetSinkParamsForTesting(
const media::AudioParameters& sink_params) {
- DCHECK(thread_checker_.CalledOnValidThread());
sink_params_ = sink_params;
}
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 23ba215db81..eb437fabe59 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.h
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.h
@@ -5,14 +5,17 @@
#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_LOCAL_AUDIO_SOURCE_PROVIDER_H_
#define CONTENT_RENDERER_MEDIA_WEBRTC_LOCAL_AUDIO_SOURCE_PROVIDER_H_
+#include <vector>
+
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
+#include "content/public/renderer/media_stream_audio_sink.h"
#include "media/base/audio_converter.h"
+#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h"
#include "third_party/WebKit/public/platform/WebVector.h"
-#include "third_party/WebKit/public/web/WebAudioSourceProvider.h"
namespace media {
class AudioBus;
@@ -21,14 +24,14 @@ class AudioFifo;
class AudioParameters;
}
-namespace WebKit {
+namespace blink {
class WebAudioSourceProviderClient;
}
namespace content {
// WebRtcLocalAudioSourceProvider provides a bridge between classes:
-// WebRtcAudioCapturer ---> WebKit::WebAudioSourceProvider
+// WebRtcAudioCapturer ---> blink::WebAudioSourceProvider
//
// WebRtcLocalAudioSourceProvider works as a sink to the WebRtcAudiocapturer
// and store the capture data to a FIFO. When the media stream is connected to
@@ -37,33 +40,25 @@ namespace content {
//
// All calls are protected by a lock.
class CONTENT_EXPORT WebRtcLocalAudioSourceProvider
- : NON_EXPORTED_BASE(public media::AudioConverter::InputCallback),
- NON_EXPORTED_BASE(public WebKit::WebAudioSourceProvider) {
+ : NON_EXPORTED_BASE(public blink::WebAudioSourceProvider),
+ NON_EXPORTED_BASE(public media::AudioConverter::InputCallback),
+ NON_EXPORTED_BASE(public MediaStreamAudioSink) {
public:
static const size_t kWebAudioRenderBufferSize;
WebRtcLocalAudioSourceProvider();
virtual ~WebRtcLocalAudioSourceProvider();
- // Initialize function for the souce provider. This can be called multiple
- // times if the source format has changed.
- void Initialize(const media::AudioParameters& source_params);
-
- // Called by the WebRtcAudioCapturer to deliever captured data into fifo on
- // the capture audio thread.
- void DeliverData(media::AudioBus* audio_source,
- int audio_delay_milliseconds,
- int volume,
- bool key_pressed);
-
- // Called by the WebAudioCapturerSource to get the audio processing params.
- // This function is triggered by provideInput() on the WebAudio audio thread,
- // so it has been under the protection of |lock_|.
- void GetAudioProcessingParams(int* delay_ms, int* volume, bool* key_pressed);
+ // MediaStreamAudioSink implementation.
+ virtual void OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames) OVERRIDE;
+ virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
- // WebKit::WebAudioSourceProvider implementation.
- virtual void setClient(WebKit::WebAudioSourceProviderClient* client) OVERRIDE;
- virtual void provideInput(const WebKit::WebVector<float*>& audio_data,
+ // blink::WebAudioSourceProvider implementation.
+ virtual void setClient(blink::WebAudioSourceProviderClient* client) OVERRIDE;
+ virtual void provideInput(const blink::WebVector<float*>& audio_data,
size_t number_of_frames) OVERRIDE;
// media::AudioConverter::Inputcallback implementation.
@@ -82,15 +77,13 @@ class CONTENT_EXPORT WebRtcLocalAudioSourceProvider
void SetSinkParamsForTesting(const media::AudioParameters& sink_params);
private:
- // Used to DCHECK that we are called on the correct thread.
- base::ThreadChecker thread_checker_;
+ // Used to DCHECK that some methods are called on the capture audio thread.
+ base::ThreadChecker capture_thread_checker_;
scoped_ptr<media::AudioConverter> audio_converter_;
scoped_ptr<media::AudioFifo> fifo_;
- scoped_ptr<media::AudioBus> bus_wrapper_;
- int audio_delay_ms_;
- int volume_;
- bool key_pressed_;
+ scoped_ptr<media::AudioBus> input_bus_;
+ scoped_ptr<media::AudioBus> output_wrapper_;
bool is_enabled_;
media::AudioParameters source_params_;
media::AudioParameters sink_params_;
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 c23ce0ee634..5b7e8526898 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
@@ -19,23 +19,25 @@ class WebRtcLocalAudioSourceProviderTest : public testing::Test {
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO, 2, 0, 44100, 16,
WebRtcLocalAudioSourceProvider::kWebAudioRenderBufferSize);
- source_bus_ = media::AudioBus::Create(source_params_);
+ const int length =
+ source_params_.frames_per_buffer() * source_params_.channels();
+ source_data_.reset(new int16[length]);
sink_bus_ = media::AudioBus::Create(sink_params_);
source_provider_.reset(new WebRtcLocalAudioSourceProvider());
source_provider_->SetSinkParamsForTesting(sink_params_);
- source_provider_->Initialize(source_params_);
+ source_provider_->OnSetFormat(source_params_);
}
media::AudioParameters source_params_;
+ scoped_ptr<int16[]> source_data_;
media::AudioParameters sink_params_;
- scoped_ptr<media::AudioBus> source_bus_;
scoped_ptr<media::AudioBus> sink_bus_;
scoped_ptr<WebRtcLocalAudioSourceProvider> source_provider_;
};
TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyDataFlow) {
// Point the WebVector into memory owned by |sink_bus_|.
- WebKit::WebVector<float*> audio_data(
+ blink::WebVector<float*> audio_data(
static_cast<size_t>(sink_bus_->channels()));
for (size_t i = 0; i < audio_data.size(); ++i)
audio_data[i] = sink_bus_->channel(i);
@@ -47,12 +49,15 @@ TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyDataFlow) {
EXPECT_TRUE(sink_bus_->channel(0)[0] == 0);
// Set the value of source data to be 1.
- for (int i = 0; i < source_params_.frames_per_buffer(); ++i) {
- source_bus_->channel(0)[i] = 1;
- }
+ const int length =
+ source_params_.frames_per_buffer() * source_params_.channels();
+ std::fill(source_data_.get(), source_data_.get() + length, 1);
// Deliver data to |source_provider_|.
- source_provider_->DeliverData(source_bus_.get(), 0, 0, false);
+ source_provider_->OnData(source_data_.get(),
+ source_params_.sample_rate(),
+ source_params_.channels(),
+ source_params_.frames_per_buffer());
// Consume the first packet in the resampler, which contains only zero.
// And the consumption of the data will trigger pulling the real packet from
@@ -69,7 +74,10 @@ TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyDataFlow) {
}
// Prepare the second packet for featching.
- source_provider_->DeliverData(source_bus_.get(), 0, 0, false);
+ source_provider_->OnData(source_data_.get(),
+ source_params_.sample_rate(),
+ source_params_.channels(),
+ source_params_.frames_per_buffer());
// Verify the packets.
for (int i = 0; i < source_params_.frames_per_buffer();
@@ -83,39 +91,4 @@ TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyDataFlow) {
}
}
-TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyAudioProcessingParams) {
- // Point the WebVector into memory owned by |sink_bus_|.
- WebKit::WebVector<float*> audio_data(
- static_cast<size_t>(sink_bus_->channels()));
- for (size_t i = 0; i < audio_data.size(); ++i)
- audio_data[i] = sink_bus_->channel(i);
-
- // Enable the source provider.
- source_provider_->provideInput(audio_data, sink_params_.frames_per_buffer());
-
- // Deliver data to |source_provider_| with audio processing params.
- int source_delay = 5;
- int source_volume = 255;
- bool source_key_pressed = true;
- source_provider_->DeliverData(source_bus_.get(), source_delay,
- source_volume, source_key_pressed);
-
- int delay = 0, volume = 0;
- bool key_pressed = false;
- source_provider_->GetAudioProcessingParams(&delay, &volume, &key_pressed);
- EXPECT_EQ(volume, source_volume);
- EXPECT_EQ(key_pressed, source_key_pressed);
- int expected_delay = source_delay + static_cast<int>(
- source_bus_->frames() / source_params_.sample_rate() + 0.5);
- EXPECT_GE(delay, expected_delay);
-
- // Sleep a few ms to simulate processing time. This should increase the delay
- // value as time passes.
- int cached_delay = delay;
- const int kSleepMs = 10;
- base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(kSleepMs));
- source_provider_->GetAudioProcessingParams(&delay, &volume, &key_pressed);
- EXPECT_GT(delay, cached_delay);
-}
-
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_local_audio_track.cc b/chromium/content/renderer/media/webrtc_local_audio_track.cc
index c79757613fe..8afa06feab2 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_track.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_track.cc
@@ -4,9 +4,12 @@
#include "content/renderer/media/webrtc_local_audio_track.h"
+#include "content/public/renderer/media_stream_audio_sink.h"
+#include "content/renderer/media/media_stream_audio_sink_owner.h"
+#include "content/renderer/media/media_stream_audio_track_sink.h"
+#include "content/renderer/media/peer_connection_audio_sink_owner.h"
#include "content/renderer/media/webaudio_capturer_source.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
-#include "content/renderer/media/webrtc_audio_capturer_sink_owner.h"
#include "content/renderer/media/webrtc_local_audio_source_provider.h"
#include "media/base/audio_fifo.h"
#include "third_party/libjingle/source/talk/media/base/audiorenderer.h"
@@ -54,28 +57,39 @@ bool NeedsAudioProcessing(
// This is a temporary audio buffer with parameters used to send data to
// callbacks.
-class WebRtcLocalAudioTrack::ConfiguredBuffer :
- public base::RefCounted<WebRtcLocalAudioTrack::ConfiguredBuffer> {
+class WebRtcLocalAudioTrack::ConfiguredBuffer {
public:
- ConfiguredBuffer() : sink_buffer_size_(0) {}
+ ConfiguredBuffer() {}
+ virtual ~ConfiguredBuffer() {}
- void Initialize(const media::AudioParameters& params) {
+ void Configure(const media::AudioParameters& params) {
DCHECK(params.IsValid());
- params_ = params;
- // Use 10ms as the sink buffer size since that is the native packet size
- // WebRtc is running on.
- sink_buffer_size_ = params.sample_rate() / 100;
- audio_wrapper_ =
- media::AudioBus::Create(params.channels(), sink_buffer_size_);
- buffer_.reset(new int16[sink_buffer_size_ * params.channels()]);
+ // PeerConnection uses 10ms as the sink buffer size as its native packet
+ // size. We use the native PeerConnection buffer size to achieve the best
+ // performance when a PeerConnection is connected with a track.
+ int sink_buffer_size = params.sample_rate() / 100;
+ if (params.frames_per_buffer() < sink_buffer_size) {
+ // When the source is running with a buffer size smaller than the peer
+ // connection buffer size, that means no PeerConnection is connected
+ // to the track, use the same buffer size as the incoming format to
+ // avoid extra FIFO for WebAudio.
+ sink_buffer_size = params.frames_per_buffer();
+ }
+ params_.Reset(params.format(), params.channel_layout(), params.channels(),
+ params.input_channels(), params.sample_rate(),
+ params.bits_per_sample(), sink_buffer_size);
+
+ audio_wrapper_ = media::AudioBus::Create(params_.channels(),
+ params_.frames_per_buffer());
+ buffer_.reset(new int16[params_.frames_per_buffer() * params_.channels()]);
// The size of the FIFO should be at least twice of the source buffer size
// or twice of the sink buffer size.
int buffer_size = std::max(
kMaxNumberOfBuffersInFifo * params.frames_per_buffer(),
- kMaxNumberOfBuffersInFifo * sink_buffer_size_);
- fifo_.reset(new media::AudioFifo(params.channels(), buffer_size));
+ kMaxNumberOfBuffersInFifo * params_.frames_per_buffer());
+ fifo_.reset(new media::AudioFifo(params_.channels(), buffer_size));
}
void Push(media::AudioBus* audio_source) {
@@ -95,18 +109,15 @@ class WebRtcLocalAudioTrack::ConfiguredBuffer :
}
int16* buffer() const { return buffer_.get(); }
+
+ // Format of the output audio buffer.
const media::AudioParameters& params() const { return params_; }
- int sink_buffer_size() const { return sink_buffer_size_; }
private:
- ~ConfiguredBuffer() {}
- friend class base::RefCounted<WebRtcLocalAudioTrack::ConfiguredBuffer>;
-
media::AudioParameters params_;
scoped_ptr<media::AudioBus> audio_wrapper_;
scoped_ptr<media::AudioFifo> fifo_;
scoped_ptr<int16[]> buffer_;
- int sink_buffer_size_;
};
scoped_refptr<WebRtcLocalAudioTrack> WebRtcLocalAudioTrack::Create(
@@ -131,13 +142,18 @@ WebRtcLocalAudioTrack::WebRtcLocalAudioTrack(
capturer_(capturer),
webaudio_source_(webaudio_source),
track_source_(track_source),
- need_audio_processing_(NeedsAudioProcessing(constraints)) {
+ need_audio_processing_(NeedsAudioProcessing(constraints)),
+ buffer_(new ConfiguredBuffer()) {
DCHECK(capturer.get() || webaudio_source);
+ if (!webaudio_source_) {
+ source_provider_.reset(new WebRtcLocalAudioSourceProvider());
+ AddSink(source_provider_.get());
+ }
DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
}
WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()";
// Users might not call Stop() on the track.
Stop();
@@ -147,47 +163,59 @@ void WebRtcLocalAudioTrack::Capture(media::AudioBus* audio_source,
int audio_delay_milliseconds,
int volume,
bool key_pressed) {
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
scoped_refptr<WebRtcAudioCapturer> capturer;
std::vector<int> voe_channels;
- int sample_rate = 0;
- int number_of_channels = 0;
- int number_of_frames = 0;
- SinkList sinks;
- scoped_refptr<ConfiguredBuffer> current_buffer;
+ SinkList::ItemList sinks;
+ SinkList::ItemList sinks_to_notify_format;
+ bool is_webaudio_source = false;
{
base::AutoLock auto_lock(lock_);
capturer = capturer_;
voe_channels = voe_channels_;
- current_buffer = buffer_;
- sample_rate = current_buffer->params().sample_rate();
- number_of_channels = current_buffer->params().channels();
- number_of_frames = current_buffer->sink_buffer_size();
- sinks = sinks_;
+ sinks = sinks_.Items();
+ sinks_.RetrieveAndClearTags(&sinks_to_notify_format);
+ is_webaudio_source = (webaudio_source_.get() != NULL);
+ }
+
+ // Notify the tracks on when the format changes. This will do nothing if
+ // |sinks_to_notify_format| is empty.
+ for (SinkList::ItemList::const_iterator it = sinks_to_notify_format.begin();
+ it != sinks_to_notify_format.end(); ++it) {
+ (*it)->OnSetFormat(buffer_->params());
}
// Push the data to the fifo.
- current_buffer->Push(audio_source);
- // Only turn off the audio processing when the constraint is set to false as
- // well as there is no correct delay value.
- bool need_audio_processing = need_audio_processing_ ?
- need_audio_processing_ : (audio_delay_milliseconds != 0);
+ buffer_->Push(audio_source);
+
+ // When the source is WebAudio, turn off the audio processing if the delay
+ // value is 0 even though the constraint is set to true. In such case, it
+ // indicates the data is not from microphone.
+ // TODO(xians): remove the flag when supporting one APM per audio track.
+ // See crbug/264611 for details.
+ bool need_audio_processing = need_audio_processing_;
+ if (is_webaudio_source && need_audio_processing)
+ need_audio_processing = (audio_delay_milliseconds != 0);
+
int current_volume = volume;
- while (current_buffer->Consume()) {
+ while (buffer_->Consume()) {
// Feed the data to the sinks.
// TODO (jiayl): we should not pass the real audio data down if the track is
// disabled. This is currently done so to feed input to WebRTC typing
// detection and should be changed when audio processing is moved from
// WebRTC to the track.
- for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) {
- int new_volume = (*it)->CaptureData(voe_channels,
- current_buffer->buffer(),
- sample_rate,
- number_of_channels,
- number_of_frames,
- audio_delay_milliseconds,
- current_volume,
- need_audio_processing,
- key_pressed);
+ for (SinkList::ItemList::const_iterator it = sinks.begin();
+ it != sinks.end();
+ ++it) {
+ int new_volume = (*it)->OnData(buffer_->buffer(),
+ buffer_->params().sample_rate(),
+ buffer_->params().channels(),
+ buffer_->params().frames_per_buffer(),
+ voe_channels,
+ audio_delay_milliseconds,
+ current_volume,
+ need_audio_processing,
+ key_pressed);
if (new_volume != 0 && capturer.get()) {
// Feed the new volume to WebRtc while changing the volume on the
// browser.
@@ -198,26 +226,20 @@ void WebRtcLocalAudioTrack::Capture(media::AudioBus* audio_source,
}
}
-void WebRtcLocalAudioTrack::SetCaptureFormat(
+void WebRtcLocalAudioTrack::OnSetFormat(
const media::AudioParameters& params) {
- if (!params.IsValid())
- return;
+ DVLOG(1) << "WebRtcLocalAudioTrack::OnSetFormat()";
+ // If the source is restarted, we might have changed to another capture
+ // thread.
+ capture_thread_checker_.DetachFromThread();
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
- scoped_refptr<ConfiguredBuffer> new_buffer(new ConfiguredBuffer());
- new_buffer->Initialize(params);
+ DCHECK(params.IsValid());
+ buffer_->Configure(params);
- SinkList sinks;
- {
- base::AutoLock auto_lock(lock_);
- buffer_ = new_buffer;
- sinks = sinks_;
- }
-
- // Update all the existing sinks with the new format.
- for (SinkList::const_iterator it = sinks.begin();
- it != sinks.end(); ++it) {
- (*it)->SetCaptureFormat(params);
- }
+ base::AutoLock auto_lock(lock_);
+ // Remember to notify all sinks of the new format.
+ sinks_.TagAll();
}
void WebRtcLocalAudioTrack::AddChannel(int channel_id) {
@@ -257,65 +279,101 @@ std::string WebRtcLocalAudioTrack::kind() const {
return kAudioTrackKind;
}
-void WebRtcLocalAudioTrack::AddSink(WebRtcAudioCapturerSink* sink) {
- DCHECK(thread_checker_.CalledOnValidThread());
+void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()";
base::AutoLock auto_lock(lock_);
- if (buffer_.get())
- sink->SetCaptureFormat(buffer_->params());
// Verify that |sink| is not already added to the list.
- DCHECK(std::find_if(
- sinks_.begin(), sinks_.end(),
- WebRtcAudioCapturerSinkOwner::WrapsSink(sink)) == sinks_.end());
-
- // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns
- // the |sink| and delagates all calls to the WebRtcAudioCapturerSink
- // interface.
- sinks_.push_back(new WebRtcAudioCapturerSinkOwner(sink));
+ DCHECK(!sinks_.Contains(
+ MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink)));
+
+ // Create (and add to the list) a new MediaStreamAudioTrackSink
+ // which owns the |sink| and delagates all calls to the
+ // MediaStreamAudioSink interface. It will be tagged in the list, so
+ // we remember to call OnSetFormat() on the new sink.
+ scoped_refptr<MediaStreamAudioTrackSink> sink_owner(
+ new MediaStreamAudioSinkOwner(sink));
+ sinks_.AddAndTag(sink_owner);
}
-void WebRtcLocalAudioTrack::RemoveSink(
- WebRtcAudioCapturerSink* sink) {
- DCHECK(thread_checker_.CalledOnValidThread());
+void WebRtcLocalAudioTrack::RemoveSink(MediaStreamAudioSink* sink) {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()";
base::AutoLock auto_lock(lock_);
- // Get iterator to the first element for which WrapsSink(sink) returns true.
- SinkList::iterator it = std::find_if(
- sinks_.begin(), sinks_.end(),
- WebRtcAudioCapturerSinkOwner::WrapsSink(sink));
- if (it != sinks_.end()) {
- // Clear the delegate to ensure that no more capture callbacks will
- // be sent to this sink. Also avoids a possible crash which can happen
- // if this method is called while capturing is active.
- (*it)->Reset();
- sinks_.erase(it);
- }
+
+ scoped_refptr<MediaStreamAudioTrackSink> removed_item = sinks_.Remove(
+ MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink));
+
+ // Clear the delegate to ensure that no more capture callbacks will
+ // be sent to this sink. Also avoids a possible crash which can happen
+ // if this method is called while capturing is active.
+ if (removed_item.get())
+ removed_item->Reset();
+}
+
+void WebRtcLocalAudioTrack::AddSink(PeerConnectionAudioSink* sink) {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()";
+ base::AutoLock auto_lock(lock_);
+
+ // Verify that |sink| is not already added to the list.
+ DCHECK(!sinks_.Contains(
+ MediaStreamAudioTrackSink::WrapsPeerConnectionSink(sink)));
+
+ // Create (and add to the list) a new MediaStreamAudioTrackSink
+ // which owns the |sink| and delagates all calls to the
+ // MediaStreamAudioSink interface. It will be tagged in the list, so
+ // we remember to call OnSetFormat() on the new sink.
+ scoped_refptr<MediaStreamAudioTrackSink> sink_owner(
+ new PeerConnectionAudioSinkOwner(sink));
+ sinks_.AddAndTag(sink_owner);
+}
+
+void WebRtcLocalAudioTrack::RemoveSink(PeerConnectionAudioSink* sink) {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()";
+
+ base::AutoLock auto_lock(lock_);
+
+ scoped_refptr<MediaStreamAudioTrackSink> removed_item = sinks_.Remove(
+ MediaStreamAudioTrackSink::WrapsPeerConnectionSink(sink));
+ // Clear the delegate to ensure that no more capture callbacks will
+ // be sent to this sink. Also avoids a possible crash which can happen
+ // if this method is called while capturing is active.
+ if (removed_item.get())
+ removed_item->Reset();
}
void WebRtcLocalAudioTrack::Start() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcLocalAudioTrack::Start()";
if (webaudio_source_.get()) {
// If the track is hooking up with WebAudio, do NOT add the track to the
// capturer as its sink otherwise two streams in different clock will be
// pushed through the same track.
- WebRtcLocalAudioSourceProvider* source_provider = NULL;
- if (capturer_.get()) {
- source_provider = static_cast<WebRtcLocalAudioSourceProvider*>(
- capturer_->audio_source_provider());
- }
- webaudio_source_->Start(this, source_provider);
+ webaudio_source_->Start(this, capturer_.get());
return;
}
if (capturer_.get())
capturer_->AddTrack(this);
+
+ SinkList::ItemList sinks;
+ {
+ base::AutoLock auto_lock(lock_);
+ sinks = sinks_.Items();
+ }
+ for (SinkList::ItemList::const_iterator it = sinks.begin();
+ it != sinks.end();
+ ++it) {
+ (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateLive);
+ }
}
void WebRtcLocalAudioTrack::Stop() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcLocalAudioTrack::Stop()";
if (!capturer_.get() && !webaudio_source_.get())
return;
@@ -327,21 +385,28 @@ void WebRtcLocalAudioTrack::Stop() {
// in such case and no need to call RemoveTrack().
webaudio_source_->Stop();
} else {
+ // It is necessary to call RemoveTrack on the |capturer_| to avoid getting
+ // audio callback after Stop().
capturer_->RemoveTrack(this);
}
// Protect the pointers using the lock when accessing |sinks_| and
// setting the |capturer_| to NULL.
- SinkList sinks;
+ SinkList::ItemList sinks;
{
base::AutoLock auto_lock(lock_);
- sinks = sinks_;
+ sinks = sinks_.Items();
+ sinks_.Clear();
webaudio_source_ = NULL;
capturer_ = NULL;
}
- for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it)
+ for (SinkList::ItemList::const_iterator it = sinks.begin();
+ it != sinks.end();
+ ++it){
+ (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded);
(*it)->Reset();
+ }
}
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_local_audio_track.h b/chromium/content/renderer/media/webrtc_local_audio_track.h
index 01b11208021..0ad463b2cdf 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_track.h
+++ b/chromium/content/renderer/media/webrtc_local_audio_track.h
@@ -10,7 +10,10 @@
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
+#include "content/renderer/media/media_stream_audio_track_sink.h"
+#include "content/renderer/media/tagged_list.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
+#include "content/renderer/media/webrtc_local_audio_source_provider.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreamtrack.h"
@@ -26,12 +29,14 @@ class AudioBus;
namespace content {
+class MediaStreamAudioSink;
+class MediaStreamAudioSinkOwner;
+class PeerConnectionAudioSink;
class WebAudioCapturerSource;
class WebRtcAudioCapturer;
-class WebRtcAudioCapturerSinkOwner;
// A WebRtcLocalAudioTrack instance contains the implementations of
-// MediaStreamTrack and WebRtcAudioCapturerSink.
+// MediaStreamTrack and MediaStreamAudioSink.
// When an instance is created, it will register itself as a track to the
// WebRtcAudioCapturer to get the captured data, and forward the data to
// its |sinks_|. The data flow can be stopped by disabling the audio track.
@@ -47,14 +52,20 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
webrtc::AudioSourceInterface* track_source,
const webrtc::MediaConstraintsInterface* constraints);
- // Add a sink to the track. This function will trigger a SetCaptureFormat()
+ // Add a sink to the track. This function will trigger a OnSetFormat()
// call on the |sink|.
// Called on the main render thread.
- void AddSink(WebRtcAudioCapturerSink* sink);
+ void AddSink(MediaStreamAudioSink* sink);
// Remove a sink from the track.
// Called on the main render thread.
- void RemoveSink(WebRtcAudioCapturerSink* sink);
+ void RemoveSink(MediaStreamAudioSink* sink);
+
+ // Add/remove PeerConnection sink to/from the track.
+ // TODO(xians): Remove these two methods after PeerConnection can use the
+ // same sink interface as MediaStreamAudioSink.
+ void AddSink(PeerConnectionAudioSink* sink);
+ void RemoveSink(PeerConnectionAudioSink* sink);
// Starts the local audio track. Called on the main render thread and
// should be called only once when audio track is created.
@@ -65,6 +76,7 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
void Stop();
// Method called by the capturer to deliver the capture data.
+ // Call on the capture audio thread.
void Capture(media::AudioBus* audio_source,
int audio_delay_milliseconds,
int volume,
@@ -72,8 +84,12 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
// Method called by the capturer to set the audio parameters used by source
// of the capture data..
- // Can be called on different user threads.
- void SetCaptureFormat(const media::AudioParameters& params);
+ // Call on the capture audio thread.
+ void OnSetFormat(const media::AudioParameters& params);
+
+ blink::WebAudioSourceProvider* audio_source_provider() const {
+ return source_provider_.get();
+ }
protected:
WebRtcLocalAudioTrack(
@@ -86,7 +102,7 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
virtual ~WebRtcLocalAudioTrack();
private:
- typedef std::list<scoped_refptr<WebRtcAudioCapturerSinkOwner> > SinkList;
+ typedef TaggedList<MediaStreamAudioTrackSink> SinkList;
// cricket::AudioCapturer implementation.
virtual void AddChannel(int channel_id) OVERRIDE;
@@ -111,24 +127,33 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
// TODO(xians): merge |track_source_| to |capturer_|.
talk_base::scoped_refptr<webrtc::AudioSourceInterface> track_source_;
- // A list of sinks that the audio data is fed to.
+ // A tagged list of sinks that the audio data is fed to. Tags
+ // indicate tracks that need to be notified that the audio format
+ // has changed.
SinkList sinks_;
- // Used to DCHECK that we are called on the correct thread.
- base::ThreadChecker thread_checker_;
+ // Used to DCHECK that some methods are called on the main render thread.
+ base::ThreadChecker main_render_thread_checker_;
+
+ // Used to DCHECK that some methods are called on the capture audio thread.
+ base::ThreadChecker capture_thread_checker_;
// Protects |params_| and |sinks_|.
mutable base::Lock lock_;
- // A vector of WebRtc VoE channels that the capturer sends datat to.
+ // A vector of WebRtc VoE channels that the capturer sends data to.
std::vector<int> voe_channels_;
bool need_audio_processing_;
// Buffers used for temporary storage during capture callbacks.
- // Allocated during initialization.
+ // Allocated and accessed only on the capture audio thread.
class ConfiguredBuffer;
- scoped_refptr<ConfiguredBuffer> buffer_;
+ scoped_ptr<ConfiguredBuffer> buffer_;
+
+ // The source provider to feed the track data to other clients like
+ // WebAudio.
+ scoped_ptr<WebRtcLocalAudioSourceProvider> source_provider_;
DISALLOW_COPY_AND_ASSIGN(WebRtcLocalAudioTrack);
};
diff --git a/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc b/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc
index 1014ebe3332..a43577669d6 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc
@@ -6,6 +6,7 @@
#include "base/test/test_timeouts.h"
#include "content/renderer/media/rtc_media_constraints.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
+#include "content/renderer/media/webrtc_audio_device_impl.h"
#include "content/renderer/media/webrtc_local_audio_source_provider.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
#include "media/audio/audio_parameters.h"
@@ -32,12 +33,13 @@ ACTION_P(SignalEvent, event) {
// the |WebRtcAudioCapturer|.
class FakeAudioThread : public base::PlatformThread::Delegate {
public:
- explicit FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer)
+ FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer,
+ const media::AudioParameters& params)
: capturer_(capturer),
thread_(),
closure_(false, false) {
DCHECK(capturer.get());
- audio_bus_ = media::AudioBus::Create(capturer_->audio_parameters());
+ audio_bus_ = media::AudioBus::Create(params);
}
virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); }
@@ -81,32 +83,56 @@ class FakeAudioThread : public base::PlatformThread::Delegate {
class MockCapturerSource : public media::AudioCapturerSource {
public:
- MockCapturerSource() {}
- MOCK_METHOD3(Initialize, void(const media::AudioParameters& params,
- CaptureCallback* callback,
- int session_id));
- MOCK_METHOD0(Start, void());
- MOCK_METHOD0(Stop, void());
+ explicit MockCapturerSource(WebRtcAudioCapturer* capturer)
+ : capturer_(capturer) {}
+ MOCK_METHOD3(OnInitialize, void(const media::AudioParameters& params,
+ CaptureCallback* callback,
+ int session_id));
+ MOCK_METHOD0(OnStart, void());
+ MOCK_METHOD0(OnStop, void());
MOCK_METHOD1(SetVolume, void(double volume));
MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
+ virtual void Initialize(const media::AudioParameters& params,
+ CaptureCallback* callback,
+ int session_id) OVERRIDE {
+ DCHECK(params.IsValid());
+ params_ = params;
+ OnInitialize(params, callback, session_id);
+ }
+ virtual void Start() OVERRIDE {
+ audio_thread_.reset(new FakeAudioThread(capturer_, params_));
+ audio_thread_->Start();
+ OnStart();
+ }
+ virtual void Stop() OVERRIDE {
+ audio_thread_->Stop();
+ audio_thread_.reset();
+ OnStop();
+ }
protected:
virtual ~MockCapturerSource() {}
+
+ private:
+ scoped_ptr<FakeAudioThread> audio_thread_;
+ WebRtcAudioCapturer* capturer_;
+ media::AudioParameters params_;
};
-class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink {
+// TODO(xians): Use MediaStreamAudioSink.
+class MockMediaStreamAudioSink : public PeerConnectionAudioSink {
public:
- MockWebRtcAudioCapturerSink() {}
- ~MockWebRtcAudioCapturerSink() {}
- int CaptureData(const std::vector<int>& channels,
- const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) OVERRIDE {
+ MockMediaStreamAudioSink() {}
+ ~MockMediaStreamAudioSink() {}
+ int OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) OVERRIDE {
CaptureData(channels.size(),
sample_rate,
number_of_channels,
@@ -126,7 +152,7 @@ class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink {
int current_volume,
bool need_audio_processing,
bool key_pressed));
- MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params));
+ MOCK_METHOD1(OnSetFormat, void(const media::AudioParameters& params));
};
} // namespace
@@ -137,34 +163,18 @@ class WebRtcLocalAudioTrackTest : public ::testing::Test {
params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO, 2, 0, 48000, 16, 480);
capturer_ = WebRtcAudioCapturer::CreateCapturer();
- WebRtcLocalAudioSourceProvider* source_provider =
- static_cast<WebRtcLocalAudioSourceProvider*>(
- capturer_->audio_source_provider());
- source_provider->SetSinkParamsForTesting(params_);
- capturer_source_ = new MockCapturerSource();
- EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0))
+ capturer_source_ = new MockCapturerSource(capturer_.get());
+ EXPECT_CALL(*capturer_source_.get(), OnInitialize(_, capturer_.get(), 0))
.WillOnce(Return());
capturer_->SetCapturerSource(capturer_source_,
params_.channel_layout(),
- params_.sample_rate());
-
- EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(false))
- .WillOnce(Return());
-
- // Start the audio thread used by the |capturer_source_|.
- audio_thread_.reset(new FakeAudioThread(capturer_));
- audio_thread_->Start();
- }
-
- virtual void TearDown() {
- audio_thread_->Stop();
- audio_thread_.reset();
+ params_.sample_rate(),
+ params_.effects());
}
media::AudioParameters params_;
scoped_refptr<MockCapturerSource> capturer_source_;
scoped_refptr<WebRtcAudioCapturer> capturer_;
- scoped_ptr<FakeAudioThread> audio_thread_;
};
// Creates a capturer and audio track, fakes its audio thread, and
@@ -172,11 +182,14 @@ class WebRtcLocalAudioTrackTest : public ::testing::Test {
// get data callback when the track is connected to the capturer but not when
// the track is disconnected from the capturer.
TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
- EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return());
+ EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*capturer_source_.get(), OnStart());
RTCMediaConstraints constraints;
scoped_refptr<WebRtcLocalAudioTrack> track =
WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
&constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track->audio_source_provider())->SetSinkParamsForTesting(params_);
track->Start();
EXPECT_TRUE(track->enabled());
@@ -186,11 +199,10 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
static_cast<webrtc::AudioTrackInterface*>(track.get())->
GetRenderer()->AddChannel(i);
}
- scoped_ptr<MockWebRtcAudioCapturerSink> sink(
- new MockWebRtcAudioCapturerSink());
+ scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
const media::AudioParameters params = capturer_->audio_parameters();
base::WaitableEvent event(false, false);
- EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return());
+ EXPECT_CALL(*sink, OnSetFormat(_)).WillOnce(Return());
EXPECT_CALL(*sink,
CaptureData(kNumberOfNetworkChannels,
params.sample_rate(),
@@ -206,9 +218,8 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
track->RemoveSink(sink.get());
- EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return());
- track->Stop();
- track = NULL;
+ EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return());
+ capturer_->Stop();
}
// The same setup as ConnectAndDisconnectOneSink, but enable and disable the
@@ -217,22 +228,24 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
// callback.
// TODO(xians): Enable this test after resolving the racing issue that TSAN
// reports on MediaStreamTrack::enabled();
-TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) {
- EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return());
+TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) {
+ EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*capturer_source_.get(), OnStart());
RTCMediaConstraints constraints;
scoped_refptr<WebRtcLocalAudioTrack> track =
WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
&constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track->audio_source_provider())->SetSinkParamsForTesting(params_);
track->Start();
static_cast<webrtc::AudioTrackInterface*>(track.get())->
GetRenderer()->AddChannel(0);
EXPECT_TRUE(track->enabled());
EXPECT_TRUE(track->set_enabled(false));
- scoped_ptr<MockWebRtcAudioCapturerSink> sink(
- new MockWebRtcAudioCapturerSink());
+ scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
const media::AudioParameters params = capturer_->audio_parameters();
base::WaitableEvent event(false, false);
- EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return());
+ EXPECT_CALL(*sink, OnSetFormat(_)).Times(1);
EXPECT_CALL(*sink,
CaptureData(1,
params.sample_rate(),
@@ -260,28 +273,31 @@ TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) {
EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
track->RemoveSink(sink.get());
- EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return());
- track->Stop();
+ EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return());
+ capturer_->Stop();
track = NULL;
}
// Create multiple audio tracks and enable/disable them, verify that the audio
// callbacks appear/disappear.
-TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) {
- EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return());
+// Flaky due to a data race, see http://crbug.com/295418
+TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) {
+ EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*capturer_source_.get(), OnStart());
RTCMediaConstraints constraints;
scoped_refptr<WebRtcLocalAudioTrack> track_1 =
WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
&constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track_1->audio_source_provider())->SetSinkParamsForTesting(params_);
track_1->Start();
static_cast<webrtc::AudioTrackInterface*>(track_1.get())->
GetRenderer()->AddChannel(0);
EXPECT_TRUE(track_1->enabled());
- scoped_ptr<MockWebRtcAudioCapturerSink> sink_1(
- new MockWebRtcAudioCapturerSink());
+ scoped_ptr<MockMediaStreamAudioSink> sink_1(new MockMediaStreamAudioSink());
const media::AudioParameters params = capturer_->audio_parameters();
base::WaitableEvent event_1(false, false);
- EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return());
+ EXPECT_CALL(*sink_1, OnSetFormat(_)).WillOnce(Return());
EXPECT_CALL(*sink_1,
CaptureData(1,
params.sample_rate(),
@@ -298,6 +314,8 @@ TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) {
scoped_refptr<WebRtcLocalAudioTrack> track_2 =
WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
&constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track_2->audio_source_provider())->SetSinkParamsForTesting(params_);
track_2->Start();
static_cast<webrtc::AudioTrackInterface*>(track_2.get())->
GetRenderer()->AddChannel(1);
@@ -307,9 +325,8 @@ TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) {
event_1.Reset();
base::WaitableEvent event_2(false, false);
- scoped_ptr<MockWebRtcAudioCapturerSink> sink_2(
- new MockWebRtcAudioCapturerSink());
- EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return());
+ scoped_ptr<MockMediaStreamAudioSink> sink_2(new MockMediaStreamAudioSink());
+ EXPECT_CALL(*sink_2, OnSetFormat(_)).WillOnce(Return());
EXPECT_CALL(*sink_1,
CaptureData(1,
params.sample_rate(),
@@ -338,27 +355,32 @@ TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) {
track_1->Stop();
track_1 = NULL;
- EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return());
+ EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return());
track_2->RemoveSink(sink_2.get());
track_2->Stop();
track_2 = NULL;
+
+ capturer_->Stop();
}
// Start one track and verify the capturer is correctly starting its source.
// And it should be fine to not to call Stop() explicitly.
TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) {
- EXPECT_CALL(*capturer_source_.get(), Start()).Times(1);
+ EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*capturer_source_.get(), OnStart());
RTCMediaConstraints constraints;
scoped_refptr<WebRtcLocalAudioTrack> track =
WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
&constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track->audio_source_provider())->SetSinkParamsForTesting(params_);
track->Start();
// When the track goes away, it will automatically stop the
// |capturer_source_|.
- EXPECT_CALL(*capturer_source_.get(), Stop());
- track->Stop();
+ EXPECT_CALL(*capturer_source_.get(), OnStop());
+ capturer_->Stop();
track = NULL;
}
@@ -367,91 +389,97 @@ TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) {
TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) {
// Starting the first audio track will start the |capturer_source_|.
base::WaitableEvent event(false, false);
- EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(SignalEvent(&event));
+ EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*capturer_source_.get(), OnStart()).WillOnce(SignalEvent(&event));
RTCMediaConstraints constraints;
scoped_refptr<WebRtcLocalAudioTrack> track_1 =
WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
&constraints);
static_cast<webrtc::AudioTrackInterface*>(track_1.get())->
GetRenderer()->AddChannel(0);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track_1->audio_source_provider())->SetSinkParamsForTesting(params_);
track_1->Start();
EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
// Verify the data flow by connecting the sink to |track_1|.
- scoped_ptr<MockWebRtcAudioCapturerSink> sink(
- new MockWebRtcAudioCapturerSink());
+ scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
event.Reset();
+ EXPECT_CALL(*sink, OnSetFormat(_)).WillOnce(SignalEvent(&event));
EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false))
.Times(AnyNumber()).WillRepeatedly(Return());
- EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1);
track_1->AddSink(sink.get());
+ EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
// Start the second audio track will not start the |capturer_source_|
// since it has been started.
- EXPECT_CALL(*capturer_source_.get(), Start()).Times(0);
+ EXPECT_CALL(*capturer_source_.get(), OnStart()).Times(0);
scoped_refptr<WebRtcLocalAudioTrack> track_2 =
WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
&constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track_2->audio_source_provider())->SetSinkParamsForTesting(params_);
track_2->Start();
static_cast<webrtc::AudioTrackInterface*>(track_2.get())->
GetRenderer()->AddChannel(1);
- // Stop the first audio track will not stop the |capturer_source_|.
- EXPECT_CALL(*capturer_source_.get(), Stop()).Times(0);
- track_1->RemoveSink(sink.get());
- track_1->Stop();
- track_1 = NULL;
+ // Stop the capturer will clear up the track lists in the capturer.
+ EXPECT_CALL(*capturer_source_.get(), OnStop());
+ capturer_->Stop();
- EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false))
- .Times(AnyNumber()).WillRepeatedly(Return());
- EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1);
+ // Adding a new track to the capturer.
track_2->AddSink(sink.get());
+ EXPECT_CALL(*sink, OnSetFormat(_)).Times(0);
- // Stop the last audio track will stop the |capturer_source_|.
+ // Stop the capturer again will not trigger stopping the source of the
+ // capturer again..
event.Reset();
- EXPECT_CALL(*capturer_source_.get(), Stop())
- .Times(1).WillOnce(SignalEvent(&event));
- track_2->Stop();
- track_2->RemoveSink(sink.get());
- track_2 = NULL;
- EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
+ EXPECT_CALL(*capturer_source_.get(), OnStop()).Times(0);
+ capturer_->Stop();
}
// Set new source to the existing capturer.
TEST_F(WebRtcLocalAudioTrackTest, SetNewSourceForCapturerAfterStartTrack) {
// Setup the audio track and start the track.
- EXPECT_CALL(*capturer_source_.get(), Start()).Times(1);
+ EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*capturer_source_.get(), OnStart());
RTCMediaConstraints constraints;
scoped_refptr<WebRtcLocalAudioTrack> track =
WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
&constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track->audio_source_provider())->SetSinkParamsForTesting(params_);
track->Start();
// Setting new source to the capturer and the track should still get packets.
- scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource());
- EXPECT_CALL(*capturer_source_.get(), Stop());
- EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false));
- EXPECT_CALL(*new_source.get(), Initialize(_, capturer_.get(), 0))
+ scoped_refptr<MockCapturerSource> new_source(
+ new MockCapturerSource(capturer_.get()));
+ EXPECT_CALL(*capturer_source_.get(), OnStop());
+ EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*new_source.get(), OnInitialize(_, capturer_.get(), 0))
.WillOnce(Return());
- EXPECT_CALL(*new_source.get(), Start()).WillOnce(Return());
+ EXPECT_CALL(*new_source.get(), OnStart());
capturer_->SetCapturerSource(new_source,
params_.channel_layout(),
- params_.sample_rate());
+ params_.sample_rate(),
+ params_.effects());
// Stop the track.
- EXPECT_CALL(*new_source.get(), Stop());
- track->Stop();
- track = NULL;
+ EXPECT_CALL(*new_source.get(), OnStop());
+ capturer_->Stop();
}
// Create a new capturer with new source, connect it to a new audio track.
TEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) {
// Setup the first audio track and start it.
- EXPECT_CALL(*capturer_source_.get(), Start()).Times(1);
+ EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*capturer_source_.get(), OnStart());
RTCMediaConstraints constraints;
scoped_refptr<WebRtcLocalAudioTrack> track_1 =
WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
&constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track_1->audio_source_provider())->SetSinkParamsForTesting(params_);
track_1->Start();
// Connect a number of network channels to the |track_1|.
@@ -461,41 +489,34 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) {
GetRenderer()->AddChannel(i);
}
// Verify the data flow by connecting the |sink_1| to |track_1|.
- scoped_ptr<MockWebRtcAudioCapturerSink> sink_1(
- new MockWebRtcAudioCapturerSink());
+ scoped_ptr<MockMediaStreamAudioSink> sink_1(new MockMediaStreamAudioSink());
EXPECT_CALL(
*sink_1.get(),
CaptureData(
kNumberOfNetworkChannelsForTrack1, 48000, 2, _, 0, 0, false, false))
.Times(AnyNumber()).WillRepeatedly(Return());
- EXPECT_CALL(*sink_1.get(), SetCaptureFormat(_)).Times(1);
+ EXPECT_CALL(*sink_1.get(), OnSetFormat(_)).Times(AnyNumber());
track_1->AddSink(sink_1.get());
// Create a new capturer with new source with different audio format.
scoped_refptr<WebRtcAudioCapturer> new_capturer(
WebRtcAudioCapturer::CreateCapturer());
- WebRtcLocalAudioSourceProvider* source_provider =
- static_cast<WebRtcLocalAudioSourceProvider*>(
- new_capturer->audio_source_provider());
- source_provider->SetSinkParamsForTesting(params_);
- scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource());
- EXPECT_CALL(*new_source.get(), Initialize(_, new_capturer.get(), 0))
- .WillOnce(Return());
- EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false))
- .WillOnce(Return());
+ scoped_refptr<MockCapturerSource> new_source(
+ new MockCapturerSource(new_capturer.get()));
+ EXPECT_CALL(*new_source.get(), OnInitialize(_, new_capturer.get(), 0));
new_capturer->SetCapturerSource(new_source,
media::CHANNEL_LAYOUT_MONO,
- 44100);
-
- // Start the audio thread used by the new source.
- scoped_ptr<FakeAudioThread> audio_thread(new FakeAudioThread(new_capturer));
- audio_thread->Start();
+ 44100,
+ media::AudioParameters::NO_EFFECTS);
// Setup the second audio track, connect it to the new capturer and start it.
- EXPECT_CALL(*new_source.get(), Start()).Times(1);
+ EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*new_source.get(), OnStart());
scoped_refptr<WebRtcLocalAudioTrack> track_2 =
WebRtcLocalAudioTrack::Create(std::string(), new_capturer, NULL, NULL,
&constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track_2->audio_source_provider())->SetSinkParamsForTesting(params_);
track_2->Start();
// Connect a number of network channels to the |track_2|.
@@ -505,30 +526,81 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) {
GetRenderer()->AddChannel(i);
}
// Verify the data flow by connecting the |sink_2| to |track_2|.
- scoped_ptr<MockWebRtcAudioCapturerSink> sink_2(
- new MockWebRtcAudioCapturerSink());
+ scoped_ptr<MockMediaStreamAudioSink> sink_2(new MockMediaStreamAudioSink());
+ base::WaitableEvent event(false, false);
EXPECT_CALL(
*sink_2,
CaptureData(
kNumberOfNetworkChannelsForTrack2, 44100, 1, _, 0, 0, false, false))
.Times(AnyNumber()).WillRepeatedly(Return());
- EXPECT_CALL(*sink_2, SetCaptureFormat(_)).Times(1);
+ EXPECT_CALL(*sink_2, OnSetFormat(_)).WillOnce(SignalEvent(&event));
track_2->AddSink(sink_2.get());
+ EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
+
+ // Stopping the new source will stop the second track.
+ event.Reset();
+ EXPECT_CALL(*new_source.get(), OnStop())
+ .Times(1).WillOnce(SignalEvent(&event));
+ new_capturer->Stop();
+ EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
+
+ // Stop the capturer of the first audio track.
+ EXPECT_CALL(*capturer_source_.get(), OnStop());
+ capturer_->Stop();
+}
- // Stop the second audio track will stop the new source.
+
+// Make sure a audio track can deliver packets with a buffer size smaller than
+// 10ms when it is not connected with a peer connection.
+TEST_F(WebRtcLocalAudioTrackTest, TrackWorkWithSmallBufferSize) {
+ // Setup a capturer which works with a buffer size smaller than 10ms.
+ media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128);
+
+ // Create a capturer with new source which works with the format above.
+ scoped_refptr<WebRtcAudioCapturer> capturer(
+ WebRtcAudioCapturer::CreateCapturer());
+ scoped_refptr<MockCapturerSource> source(
+ new MockCapturerSource(capturer.get()));
+ capturer->Initialize(-1, params.channel_layout(), params.sample_rate(),
+ params.frames_per_buffer(), 0, std::string(), 0, 0,
+ params.effects());
+
+ EXPECT_CALL(*source.get(), OnInitialize(_, capturer.get(), 0));
+ capturer->SetCapturerSource(source, params.channel_layout(),
+ params.sample_rate(), params.effects());
+
+ // Setup a audio track, connect it to the capturer and start it.
+ EXPECT_CALL(*source.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*source.get(), OnStart());
+ RTCMediaConstraints constraints;
+ scoped_refptr<WebRtcLocalAudioTrack> track =
+ WebRtcLocalAudioTrack::Create(std::string(), capturer, NULL, NULL,
+ &constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track->audio_source_provider())->SetSinkParamsForTesting(params);
+ track->Start();
+
+ // Verify the data flow by connecting the |sink| to |track|.
+ scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
base::WaitableEvent event(false, false);
- EXPECT_CALL(*new_source.get(), Stop()).Times(1).WillOnce(SignalEvent(&event));
- track_2->Stop();
- track_2->RemoveSink(sink_2.get());
- track_2 = NULL;
+ EXPECT_CALL(*sink, OnSetFormat(_)).Times(1);
+ // Verify the sinks are getting the packets with an expecting buffer size.
+#if defined(OS_ANDROID)
+ const int expected_buffer_size = params.sample_rate() / 100;
+#else
+ const int expected_buffer_size = params.frames_per_buffer();
+#endif
+ EXPECT_CALL(*sink, CaptureData(
+ 0, params.sample_rate(), params.channels(), expected_buffer_size,
+ 0, 0, false, false))
+ .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event));
+ track->AddSink(sink.get());
EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
- audio_thread->Stop();
- audio_thread.reset();
- // Stop the first audio track.
- EXPECT_CALL(*capturer_source_.get(), Stop());
- track_1->Stop();
- track_1 = NULL;
+ // Stopping the new source will stop the second track.
+ EXPECT_CALL(*source, OnStop()).Times(1);
+ capturer->Stop();
}
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_logging_initializer.cc b/chromium/content/renderer/media/webrtc_logging.cc
index d0d95b46ba6..2bdc7a33e5a 100644
--- a/chromium/content/renderer/media/webrtc_logging_initializer.cc
+++ b/chromium/content/renderer/media/webrtc_logging.cc
@@ -2,11 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/renderer/media/webrtc_logging_initializer.h"
+#include "content/renderer/media/webrtc_logging.h"
-#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/webrtc_log_message_delegate.h"
-#include "content/renderer/render_thread_impl.h"
#include "third_party/libjingle/overrides/talk/base/logging.h"
namespace content {
@@ -21,12 +19,8 @@ void InitWebRtcLoggingDelegate(WebRtcLogMessageDelegate* delegate) {
g_webrtc_logging_delegate = delegate;
}
-void InitWebRtcLogging(const std::string& app_session_id,
- const std::string& app_url) {
- if (g_webrtc_logging_delegate) {
- g_webrtc_logging_delegate->InitLogging(app_session_id, app_url);
- talk_base::InitDiagnosticLoggingDelegateFunction(WebRtcLogMessage);
- }
+void InitWebRtcLogging() {
+ talk_base::InitDiagnosticLoggingDelegateFunction(WebRtcLogMessage);
}
void WebRtcLogMessage(const std::string& message) {
diff --git a/chromium/content/renderer/media/webrtc_logging.h b/chromium/content/renderer/media/webrtc_logging.h
new file mode 100644
index 00000000000..0aafa9cc7d5
--- /dev/null
+++ b/chromium/content/renderer/media/webrtc_logging.h
@@ -0,0 +1,22 @@
+// 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_WEBRTC_LOGGING_H_
+#define CONTENT_RENDERER_WEBRTC_LOGGING_H_
+
+#include <string>
+
+namespace content {
+
+// This function will add |message| to the diagnostic WebRTC log, if started.
+// Otherwise it will be ignored. Note that this log may be uploaded to a
+// server by the embedder - no sensitive information should be logged. May be
+// called on any thread.
+// TODO(grunell): Create a macro for adding log messages. Messages should
+// probably also go to the ordinary logging stream.
+void WebRtcLogMessage(const std::string& message);
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_WEBRTC_LOGGING_H_
diff --git a/chromium/content/renderer/media/webrtc_logging_initializer.h b/chromium/content/renderer/media/webrtc_logging_initializer.h
deleted file mode 100644
index 08abc66a7fd..00000000000
--- a/chromium/content/renderer/media/webrtc_logging_initializer.h
+++ /dev/null
@@ -1,23 +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_WEBRTC_LOGGING_INITIALIZER_H_
-#define CONTENT_RENDERER_WEBRTC_LOGGING_INITIALIZER_H_
-
-#include <string>
-
-namespace content {
-
-class WebRtcLogMessageDelegate;
-
-// Must be called on IO thread.
-void InitWebRtcLogging(const std::string& app_session_id,
- const std::string& app_url);
-
-// May be called on any thread.
-void WebRtcLogMessage(const std::string& message);
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_WEBRTC_LOGGING_INITIALIZER_H_
diff --git a/chromium/content/common/gpu/surface_capturer.cc b/chromium/content/renderer/media/webrtc_logging_noop.cc
index ce02b4d8319..00bfdefbe3b 100644
--- a/chromium/content/common/gpu/surface_capturer.cc
+++ b/chromium/content/renderer/media/webrtc_logging_noop.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/common/gpu/surface_capturer.h"
+#include "content/renderer/media/webrtc_logging.h"
namespace content {
-SurfaceCapturer::~SurfaceCapturer() {}
+void WebRtcLogMessage(const std::string& message) {}
} // namespace content
diff --git a/chromium/content/renderer/media/websourcebuffer_impl.cc b/chromium/content/renderer/media/websourcebuffer_impl.cc
index dc568572663..c9429779d82 100644
--- a/chromium/content/renderer/media/websourcebuffer_impl.cc
+++ b/chromium/content/renderer/media/websourcebuffer_impl.cc
@@ -36,9 +36,9 @@ WebSourceBufferImpl::~WebSourceBufferImpl() {
DCHECK(!demuxer_) << "Object destroyed w/o removedFromMediaSource() call";
}
-WebKit::WebTimeRanges WebSourceBufferImpl::buffered() {
+blink::WebTimeRanges WebSourceBufferImpl::buffered() {
media::Ranges<base::TimeDelta> ranges = demuxer_->GetBufferedRanges(id_);
- WebKit::WebTimeRanges result(ranges.size());
+ blink::WebTimeRanges result(ranges.size());
for (size_t i = 0; i < ranges.size(); i++) {
result[i].start = ranges.start(i).InSecondsF();
result[i].end = ranges.end(i).InSecondsF();
diff --git a/chromium/content/renderer/media/websourcebuffer_impl.h b/chromium/content/renderer/media/websourcebuffer_impl.h
index 1f05f3b32f9..abfec405ad2 100644
--- a/chromium/content/renderer/media/websourcebuffer_impl.h
+++ b/chromium/content/renderer/media/websourcebuffer_impl.h
@@ -9,7 +9,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "third_party/WebKit/public/web/WebSourceBuffer.h"
+#include "third_party/WebKit/public/platform/WebSourceBuffer.h"
namespace media {
class ChunkDemuxer;
@@ -17,13 +17,13 @@ class ChunkDemuxer;
namespace content {
-class WebSourceBufferImpl : public WebKit::WebSourceBuffer {
+class WebSourceBufferImpl : public blink::WebSourceBuffer {
public:
WebSourceBufferImpl(const std::string& id, media::ChunkDemuxer* demuxer);
virtual ~WebSourceBufferImpl();
- // WebKit::WebSourceBuffer implementation.
- virtual WebKit::WebTimeRanges buffered() OVERRIDE;
+ // blink::WebSourceBuffer implementation.
+ virtual blink::WebTimeRanges buffered() OVERRIDE;
virtual void append(const unsigned char* data, unsigned length) OVERRIDE;
virtual void abort() OVERRIDE;
// TODO(acolwell): Add OVERRIDE when Blink-side changes land.
diff --git a/chromium/content/renderer/memory_benchmarking_extension.cc b/chromium/content/renderer/memory_benchmarking_extension.cc
index e463fcfff09..50d5dcc436e 100644
--- a/chromium/content/renderer/memory_benchmarking_extension.cc
+++ b/chromium/content/renderer/memory_benchmarking_extension.cc
@@ -41,12 +41,13 @@ class MemoryBenchmarkingWrapper : public v8::Extension {
"};"
) {}
- virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
+ v8::Isolate* isolate,
v8::Handle<v8::String> name) OVERRIDE {
- if (name->Equals(v8::String::New("IsHeapProfilerRunning")))
- return v8::FunctionTemplate::New(IsHeapProfilerRunning);
- else if (name->Equals(v8::String::New("HeapProfilerDump")))
- return v8::FunctionTemplate::New(HeapProfilerDump);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "IsHeapProfilerRunning")))
+ return v8::FunctionTemplate::New(isolate, IsHeapProfilerRunning);
+ else if (name->Equals(v8::String::NewFromUtf8(isolate, "HeapProfilerDump")))
+ return v8::FunctionTemplate::New(isolate, HeapProfilerDump);
return v8::Handle<v8::FunctionTemplate>();
}
@@ -60,10 +61,10 @@ class MemoryBenchmarkingWrapper : public v8::Extension {
const v8::FunctionCallbackInfo<v8::Value>& args) {
std::string process_type;
if (args.Length() && args[0]->IsString())
- process_type = *v8::String::AsciiValue(args[0]);
+ process_type = *v8::String::Utf8Value(args[0]);
std::string reason("benchmarking_extension");
if (args.Length() > 1 && args[1]->IsString())
- reason = *v8::String::AsciiValue(args[1]);
+ reason = *v8::String::Utf8Value(args[1]);
if (process_type == "browser") {
content::RenderThreadImpl::current()->Send(
new MemoryBenchmarkHostMsg_HeapProfilerDump(reason));
diff --git a/chromium/content/renderer/menu_item_builder.cc b/chromium/content/renderer/menu_item_builder.cc
index 5946c41bb71..0bbd5d89190 100644
--- a/chromium/content/renderer/menu_item_builder.cc
+++ b/chromium/content/renderer/menu_item_builder.cc
@@ -8,14 +8,14 @@
namespace content {
-MenuItem MenuItemBuilder::Build(const WebKit::WebMenuItemInfo& item) {
+MenuItem MenuItemBuilder::Build(const blink::WebMenuItemInfo& item) {
MenuItem result;
result.label = item.label;
result.tool_tip = item.toolTip;
result.type = static_cast<MenuItem::Type>(item.type);
result.action = item.action;
- result.rtl = (item.textDirection == WebKit::WebTextDirectionRightToLeft);
+ result.rtl = (item.textDirection == blink::WebTextDirectionRightToLeft);
result.has_directional_override = item.hasTextDirectionOverride;
result.enabled = item.enabled;
result.checked = item.checked;
diff --git a/chromium/content/renderer/menu_item_builder.h b/chromium/content/renderer/menu_item_builder.h
index 8f007bdd9db..f82a4587a1b 100644
--- a/chromium/content/renderer/menu_item_builder.h
+++ b/chromium/content/renderer/menu_item_builder.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_RENDERER_MENU_ITEM_BUILDER_H_
#define CONTENT_RENDERER_MENU_ITEM_BUILDER_H_
-namespace WebKit {
+namespace blink {
struct WebMenuItemInfo;
}
@@ -14,7 +14,7 @@ struct MenuItem;
class MenuItemBuilder {
public:
- static MenuItem Build(const WebKit::WebMenuItemInfo& item);
+ static MenuItem Build(const blink::WebMenuItemInfo& item);
};
} // namespace content
diff --git a/chromium/content/renderer/mhtml_generator.cc b/chromium/content/renderer/mhtml_generator.cc
index 0a1c78578e8..95300441c2e 100644
--- a/chromium/content/renderer/mhtml_generator.cc
+++ b/chromium/content/renderer/mhtml_generator.cc
@@ -48,8 +48,8 @@ void MHTMLGenerator::NotifyBrowser(int job_id, int64 data_size) {
// TODO(jcivelli): write the chunks in deferred tasks to give a chance to the
// message loop to process other events.
int64 MHTMLGenerator::GenerateMHTML() {
- WebKit::WebCString mhtml =
- WebKit::WebPageSerializer::serializeToMHTML(render_view()->GetWebView());
+ blink::WebCString mhtml =
+ blink::WebPageSerializer::serializeToMHTML(render_view()->GetWebView());
const size_t chunk_size = 1024;
const char* data = mhtml.data();
size_t total_bytes_written = 0;
diff --git a/chromium/content/renderer/mouse_lock_dispatcher.cc b/chromium/content/renderer/mouse_lock_dispatcher.cc
index 56ec66d5552..f72e1e05889 100644
--- a/chromium/content/renderer/mouse_lock_dispatcher.cc
+++ b/chromium/content/renderer/mouse_lock_dispatcher.cc
@@ -58,7 +58,7 @@ bool MouseLockDispatcher::IsMouseLockedTo(LockTarget* target) {
}
bool MouseLockDispatcher::WillHandleMouseEvent(
- const WebKit::WebMouseEvent& event) {
+ const blink::WebMouseEvent& event) {
if (mouse_locked_ && target_)
return target_->HandleMouseLockedInputEvent(event);
return false;
diff --git a/chromium/content/renderer/mouse_lock_dispatcher.h b/chromium/content/renderer/mouse_lock_dispatcher.h
index 6423b7d8f07..29b8e4f1261 100644
--- a/chromium/content/renderer/mouse_lock_dispatcher.h
+++ b/chromium/content/renderer/mouse_lock_dispatcher.h
@@ -8,9 +8,9 @@
#include "base/basictypes.h"
#include "content/common/content_export.h"
-namespace WebKit {
+namespace blink {
class WebMouseEvent;
-} // namespace WebKit
+} // namespace blink
namespace content {
@@ -28,7 +28,7 @@ class CONTENT_EXPORT MouseLockDispatcher {
virtual void OnMouseLockLost() = 0;
// A mouse lock is enabled and mouse events are being delievered.
virtual bool HandleMouseLockedInputEvent(
- const WebKit::WebMouseEvent& event) = 0;
+ const blink::WebMouseEvent& event) = 0;
};
// Locks the mouse to the |target|. If true is returned, an asynchronous
@@ -43,7 +43,7 @@ class CONTENT_EXPORT MouseLockDispatcher {
bool IsMouseLockedTo(LockTarget* target);
// Allow lock target to consumed a mouse event, if it does return true.
- bool WillHandleMouseEvent(const WebKit::WebMouseEvent& event);
+ bool WillHandleMouseEvent(const blink::WebMouseEvent& event);
// Subclasses or users have to call these methods to report mouse lock events
// from the browser.
diff --git a/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc b/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc
index f9c44c22353..ef18331d530 100644
--- a/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc
+++ b/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc
@@ -21,7 +21,7 @@ class MockLockTarget : public MouseLockDispatcher::LockTarget {
MOCK_METHOD1(OnLockMouseACK, void(bool));
MOCK_METHOD0(OnMouseLockLost, void());
MOCK_METHOD1(HandleMouseLockedInputEvent,
- bool(const WebKit::WebMouseEvent&));
+ bool(const blink::WebMouseEvent&));
};
// MouseLockDispatcher is a RenderViewObserver, and we test it by creating a
@@ -90,7 +90,7 @@ TEST_F(MouseLockDispatcherTest, BasicMockLockTarget) {
EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_));
// Receive mouse event.
- dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent());
+ dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
// Unlock.
dispatcher()->UnlockMouse(target_);
@@ -120,7 +120,7 @@ TEST_F(MouseLockDispatcherTest, DeleteAndUnlock) {
dispatcher()->OnLockTargetDestroyed(target_);
delete target_;
target_ = NULL;
- dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent());
+ dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
}
@@ -171,7 +171,7 @@ TEST_F(MouseLockDispatcherTest, MouseEventsNotReceived) {
EXPECT_CALL(*target_, HandleMouseLockedInputEvent(_)).Times(0);
// (Don't) receive mouse event.
- dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent());
+ dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
// Lock.
EXPECT_TRUE(dispatcher()->LockMouse(target_));
@@ -179,7 +179,7 @@ TEST_F(MouseLockDispatcherTest, MouseEventsNotReceived) {
EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_));
// Receive mouse event.
- dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent());
+ dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
// Unlock.
dispatcher()->UnlockMouse(target_);
@@ -187,7 +187,7 @@ TEST_F(MouseLockDispatcherTest, MouseEventsNotReceived) {
EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
// (Don't) receive mouse event.
- dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent());
+ dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
}
// Test multiple targets
@@ -216,7 +216,7 @@ TEST_F(MouseLockDispatcherTest, MultipleTargets) {
EXPECT_FALSE(dispatcher()->LockMouse(alternate_target_));
// Receive mouse event to only one target.
- dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent());
+ dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
// Unlock alternate target has no effect.
dispatcher()->UnlockMouse(alternate_target_);
diff --git a/chromium/content/renderer/notification_provider.cc b/chromium/content/renderer/notification_provider.cc
index fc7504226b6..07b5241aec6 100644
--- a/chromium/content/renderer/notification_provider.cc
+++ b/chromium/content/renderer/notification_provider.cc
@@ -15,14 +15,14 @@
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebView.h"
-using WebKit::WebDocument;
-using WebKit::WebNotification;
-using WebKit::WebNotificationPresenter;
-using WebKit::WebNotificationPermissionCallback;
-using WebKit::WebSecurityOrigin;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebUserGestureIndicator;
+using blink::WebDocument;
+using blink::WebNotification;
+using blink::WebNotificationPresenter;
+using blink::WebNotificationPermissionCallback;
+using blink::WebSecurityOrigin;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebUserGestureIndicator;
namespace content {
@@ -32,15 +32,21 @@ NotificationProvider::NotificationProvider(RenderViewImpl* render_view)
}
NotificationProvider::~NotificationProvider() {
- manager_.DetachAll();
}
bool NotificationProvider::show(const WebNotification& notification) {
+ WebDocument document = render_view()->GetWebView()->mainFrame()->document();
int notification_id = manager_.RegisterNotification(notification);
- if (notification.isHTML())
- return ShowHTML(notification, notification_id);
- else
- return ShowText(notification, notification_id);
+
+ ShowDesktopNotificationHostMsgParams params;
+ params.origin = GURL(document.securityOrigin().toString());
+ params.icon_url = notification.iconURL();
+ params.title = notification.title();
+ params.body = notification.body();
+ params.direction = notification.direction();
+ params.notification_id = notification_id;
+ params.replace_id = notification.replaceId();
+ return Send(new DesktopNotificationHostMsg_Show(routing_id(), params));
}
void NotificationProvider::cancel(const WebNotification& notification) {
@@ -101,35 +107,6 @@ bool NotificationProvider::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-bool NotificationProvider::ShowHTML(const WebNotification& notification,
- int id) {
- DCHECK(notification.isHTML());
- ShowDesktopNotificationHostMsgParams params;
- WebDocument document = render_view()->GetWebView()->mainFrame()->document();
- params.origin = GURL(document.securityOrigin().toString());
- params.is_html = true;
- params.contents_url = notification.url();
- params.notification_id = id;
- params.replace_id = notification.replaceId();
- return Send(new DesktopNotificationHostMsg_Show(routing_id(), params));
-}
-
-bool NotificationProvider::ShowText(const WebNotification& notification,
- int id) {
- DCHECK(!notification.isHTML());
- ShowDesktopNotificationHostMsgParams params;
- params.is_html = false;
- WebDocument document = render_view()->GetWebView()->mainFrame()->document();
- params.origin = GURL(document.securityOrigin().toString());
- params.icon_url = notification.iconURL();
- params.title = notification.title();
- params.body = notification.body();
- params.direction = notification.direction();
- params.notification_id = id;
- params.replace_id = notification.replaceId();
- return Send(new DesktopNotificationHostMsg_Show(routing_id(), params));
-}
-
void NotificationProvider::OnDisplay(int id) {
WebNotification notification;
bool found = manager_.GetNotification(id, &notification);
diff --git a/chromium/content/renderer/notification_provider.h b/chromium/content/renderer/notification_provider.h
index ababece3271..8abafb1caf7 100644
--- a/chromium/content/renderer/notification_provider.h
+++ b/chromium/content/renderer/notification_provider.h
@@ -10,7 +10,7 @@
#include "third_party/WebKit/public/web/WebNotification.h"
#include "third_party/WebKit/public/web/WebNotificationPresenter.h"
-namespace WebKit {
+namespace blink {
class WebNotificationPermissionCallback;
}
@@ -20,7 +20,7 @@ class RenderViewImpl;
// NotificationProvider class is owned by the RenderView. Only
// to be used on the main thread.
class NotificationProvider : public RenderViewObserver,
- public WebKit::WebNotificationPresenter {
+ public blink::WebNotificationPresenter {
public:
explicit NotificationProvider(RenderViewImpl* render_view);
virtual ~NotificationProvider();
@@ -29,22 +29,18 @@ class NotificationProvider : public RenderViewObserver,
// RenderView::Observer implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- // WebKit::WebNotificationPresenter interface.
- virtual bool show(const WebKit::WebNotification& proxy);
- virtual void cancel(const WebKit::WebNotification& proxy);
- virtual void objectDestroyed(const WebKit::WebNotification& proxy);
- virtual WebKit::WebNotificationPresenter::Permission checkPermission(
- const WebKit::WebSecurityOrigin& origin);
- virtual void requestPermission(const WebKit::WebSecurityOrigin& origin,
- WebKit::WebNotificationPermissionCallback* callback);
-
- // Internal methods used to show notifications.
- bool ShowHTML(const WebKit::WebNotification& notification, int id);
- bool ShowText(const WebKit::WebNotification& notification, int id);
+ // blink::WebNotificationPresenter interface.
+ virtual bool show(const blink::WebNotification& proxy);
+ virtual void cancel(const blink::WebNotification& proxy);
+ virtual void objectDestroyed(const blink::WebNotification& proxy);
+ virtual blink::WebNotificationPresenter::Permission checkPermission(
+ const blink::WebSecurityOrigin& origin);
+ virtual void requestPermission(const blink::WebSecurityOrigin& origin,
+ blink::WebNotificationPermissionCallback* callback);
// IPC handlers.
void OnDisplay(int id);
- void OnError(int id, const WebKit::WebString& message);
+ void OnError(int id, const blink::WebString& message);
void OnClose(int id, bool by_user);
void OnClick(int id);
void OnPermissionRequestComplete(int id);
diff --git a/chromium/content/renderer/npapi/plugin_channel_host.cc b/chromium/content/renderer/npapi/plugin_channel_host.cc
index c276d33384b..679288f5133 100644
--- a/chromium/content/renderer/npapi/plugin_channel_host.cc
+++ b/chromium/content/renderer/npapi/plugin_channel_host.cc
@@ -127,7 +127,7 @@ bool PluginChannelHost::OnControlMessageReceived(const IPC::Message& message) {
}
void PluginChannelHost::OnSetException(const std::string& message) {
- WebKit::WebBindings::setException(NULL, message.c_str());
+ blink::WebBindings::setException(NULL, message.c_str());
}
void PluginChannelHost::OnPluginShuttingDown() {
diff --git a/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc b/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc
index 80cb2ea2879..d7f847240b0 100644
--- a/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc
+++ b/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc
@@ -31,6 +31,7 @@
#include "content/child/npapi/webplugin_resource_client.h"
#include "content/child/plugin_messages.h"
#include "content/common/content_constants_internal.h"
+#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/npapi/plugin_channel_host.h"
@@ -53,7 +54,6 @@
#include "ui/gfx/size.h"
#include "ui/gfx/skia_util.h"
#include "webkit/common/cursors/webcursor.h"
-#include "webkit/glue/webkit_glue.h"
#if defined(OS_POSIX)
#include "ipc/ipc_channel_posix.h"
@@ -67,12 +67,12 @@
#include "content/public/common/sandbox_init.h"
#endif
-using WebKit::WebBindings;
-using WebKit::WebCursorInfo;
-using WebKit::WebDragData;
-using WebKit::WebInputEvent;
-using WebKit::WebString;
-using WebKit::WebView;
+using blink::WebBindings;
+using blink::WebCursorInfo;
+using blink::WebDragData;
+using blink::WebInputEvent;
+using blink::WebString;
+using blink::WebView;
namespace content {
@@ -203,8 +203,10 @@ class ResourceClientProxy : public WebPluginResourceClient {
WebPluginDelegateProxy::WebPluginDelegateProxy(
WebPluginImpl* plugin,
const std::string& mime_type,
- const base::WeakPtr<RenderViewImpl>& render_view)
+ const base::WeakPtr<RenderViewImpl>& render_view,
+ RenderFrameImpl* render_frame)
: render_view_(render_view),
+ render_frame_(render_frame),
plugin_(plugin),
uses_shared_bitmaps_(false),
#if defined(OS_MACOSX)
@@ -306,8 +308,8 @@ bool WebPluginDelegateProxy::Initialize(
#endif
IPC::ChannelHandle channel_handle;
- if (!RenderThreadImpl::current()->Send(new ViewHostMsg_OpenChannelToPlugin(
- render_view_->routing_id(), url, page_url_, mime_type_,
+ if (!RenderThreadImpl::current()->Send(new FrameHostMsg_OpenChannelToPlugin(
+ render_frame_->GetRoutingID(), url, page_url_, mime_type_,
&channel_handle, &info_))) {
continue;
}
@@ -317,7 +319,8 @@ bool WebPluginDelegateProxy::Initialize(
// shouldn't happen, since if we got here the plugin should exist) or the
// plugin crashed on initialization.
if (!info_.path.empty()) {
- render_view_->PluginCrashed(info_.path, base::kNullProcessId);
+ render_view_->main_render_frame()->PluginCrashed(
+ info_.path, base::kNullProcessId);
LOG(ERROR) << "Plug-in crashed on start";
// Return true so that the plugin widget is created and we can paint the
@@ -489,8 +492,10 @@ void WebPluginDelegateProxy::OnChannelError() {
}
plugin_->Invalidate();
}
- if (!channel_host_->expecting_shutdown())
- render_view_->PluginCrashed(info_.path, channel_host_->peer_pid());
+ if (!channel_host_->expecting_shutdown()) {
+ render_view_->main_render_frame()->PluginCrashed(
+ info_.path, channel_host_->peer_pid());
+ }
#if defined(OS_MACOSX) || defined(OS_WIN)
// Ensure that the renderer doesn't think the plugin still has focus.
@@ -666,14 +671,6 @@ bool WebPluginDelegateProxy::CreateSharedBitmap(
return !!canvas->get();
}
-#if defined(OS_MACOSX)
-// Flips |rect| vertically within an enclosing rect with height |height|.
-// Intended for converting rects between flipped and non-flipped contexts.
-static void FlipRectVerticallyWithHeight(gfx::Rect* rect, int height) {
- rect->set_y(height - rect->bottom());
-}
-#endif
-
void WebPluginDelegateProxy::Paint(SkCanvas* canvas,
const gfx::Rect& damaged_rect) {
// Limit the damaged rectangle to whatever is contained inside the plugin
@@ -755,7 +752,7 @@ NPP WebPluginDelegateProxy::GetPluginNPP() {
return npp_.get();
}
-bool WebPluginDelegateProxy::GetFormValue(string16* value) {
+bool WebPluginDelegateProxy::GetFormValue(base::string16* value) {
bool success = false;
Send(new PluginMsg_GetFormValue(instance_id_, value, &success));
return success;
@@ -806,7 +803,7 @@ void WebPluginDelegateProxy::SetContentAreaFocus(bool has_focus) {
#if defined(OS_WIN)
void WebPluginDelegateProxy::ImeCompositionUpdated(
- const string16& text,
+ const base::string16& text,
const std::vector<int>& clauses,
const std::vector<int>& target,
int cursor_position,
@@ -821,7 +818,7 @@ void WebPluginDelegateProxy::ImeCompositionUpdated(
Send(msg);
}
-void WebPluginDelegateProxy::ImeCompositionCompleted(const string16& text,
+void WebPluginDelegateProxy::ImeCompositionCompleted(const base::string16& text,
int plugin_id) {
// Dispatch the IME text if this plug-in is the focused one.
if (instance_id_ != plugin_id)
@@ -848,7 +845,7 @@ void WebPluginDelegateProxy::SetContainerVisibility(bool is_visible) {
if (is_visible) {
gfx::Rect window_frame = render_view_->rootWindowRect();
gfx::Rect view_frame = render_view_->windowRect();
- WebKit::WebView* webview = render_view_->webview();
+ blink::WebView* webview = render_view_->webview();
msg = new PluginMsg_ContainerShown(instance_id_, window_frame, view_frame,
webview && webview->isActive());
} else {
@@ -870,7 +867,7 @@ void WebPluginDelegateProxy::WindowFrameChanged(gfx::Rect window_frame,
msg->set_unblock(true);
Send(msg);
}
-void WebPluginDelegateProxy::ImeCompositionCompleted(const string16& text,
+void WebPluginDelegateProxy::ImeCompositionCompleted(const base::string16& text,
int plugin_id) {
// If the message isn't intended for this plugin, there's nothing to do.
if (instance_id_ != plugin_id)
@@ -935,7 +932,7 @@ void WebPluginDelegateProxy::OnNotifyIMEStatus(int input_type,
ViewHostMsg_SelectionBounds_Params bounds_params;
bounds_params.anchor_rect = bounds_params.focus_rect = caret_rect;
bounds_params.anchor_dir = bounds_params.focus_dir =
- WebKit::WebTextDirectionLeftToRight;
+ blink::WebTextDirectionLeftToRight;
bounds_params.is_anchor_first = true;
render_view_->Send(new ViewHostMsg_SelectionBoundsChanged(
render_view_->routing_id(),
@@ -1215,7 +1212,8 @@ bool WebPluginDelegateProxy::UseSynchronousGeometryUpdates() {
// Need to update geometry synchronously with WMP, otherwise if a site
// scripts the plugin to start playing while it's in the middle of handling
// an update geometry message, videos don't play. See urls in bug 20260.
- if (info_.name.find(ASCIIToUTF16("Windows Media Player")) != string16::npos)
+ if (info_.name.find(ASCIIToUTF16("Windows Media Player")) !=
+ base::string16::npos)
return true;
// The move networks plugin needs to be informed of geometry updates
diff --git a/chromium/content/renderer/npapi/webplugin_delegate_proxy.h b/chromium/content/renderer/npapi/webplugin_delegate_proxy.h
index 542986fa26d..dfa4842a694 100644
--- a/chromium/content/renderer/npapi/webplugin_delegate_proxy.h
+++ b/chromium/content/renderer/npapi/webplugin_delegate_proxy.h
@@ -38,6 +38,7 @@ class WaitableEvent;
namespace content {
class NPObjectStub;
class PluginChannelHost;
+class RenderFrameImpl;
class RenderViewImpl;
class WebPluginImpl;
@@ -51,7 +52,8 @@ class WebPluginDelegateProxy
public:
WebPluginDelegateProxy(WebPluginImpl* plugin,
const std::string& mime_type,
- const base::WeakPtr<RenderViewImpl>& render_view);
+ const base::WeakPtr<RenderViewImpl>& render_view,
+ RenderFrameImpl* render_frame);
// WebPluginDelegate implementation:
virtual void PluginDestroyed() OVERRIDE;
@@ -64,11 +66,11 @@ class WebPluginDelegateProxy
virtual void Paint(SkCanvas* canvas, const gfx::Rect& rect) OVERRIDE;
virtual NPObject* GetPluginScriptableObject() OVERRIDE;
virtual struct _NPP* GetPluginNPP() OVERRIDE;
- virtual bool GetFormValue(string16* value) OVERRIDE;
+ virtual bool GetFormValue(base::string16* value) OVERRIDE;
virtual void DidFinishLoadWithReason(const GURL& url, NPReason reason,
int notify_id) OVERRIDE;
virtual void SetFocus(bool focused) OVERRIDE;
- virtual bool HandleInputEvent(const WebKit::WebInputEvent& event,
+ virtual bool HandleInputEvent(const blink::WebInputEvent& event,
WebCursor::CursorInfo* cursor) OVERRIDE;
virtual int GetProcessId() OVERRIDE;
@@ -78,14 +80,15 @@ class WebPluginDelegateProxy
#if defined(OS_WIN)
// Informs the plugin that plugin IME has updated its status.
virtual void ImeCompositionUpdated(
- const string16& text,
+ const base::string16& text,
const std::vector<int>& clauses,
const std::vector<int>& target,
int cursor_position,
int plugin_id);
// Informs the plugin that plugin IME has completed.
// If |text| is empty, composition was cancelled.
- virtual void ImeCompositionCompleted(const string16& text, int plugin_id);
+ virtual void ImeCompositionCompleted(const base::string16& text,
+ int plugin_id);
#endif
#if defined(OS_MACOSX)
// Informs the plugin that its enclosing window has gained or lost focus.
@@ -96,7 +99,8 @@ class WebPluginDelegateProxy
virtual void WindowFrameChanged(gfx::Rect window_frame, gfx::Rect view_frame);
// Informs the plugin that plugin IME has completed.
// If |text| is empty, composition was cancelled.
- virtual void ImeCompositionCompleted(const string16& text, int plugin_id);
+ virtual void ImeCompositionCompleted(const base::string16& text,
+ int plugin_id);
#endif
// IPC::Listener implementation:
@@ -251,6 +255,7 @@ class WebPluginDelegateProxy
#endif
base::WeakPtr<RenderViewImpl> render_view_;
+ RenderFrameImpl* render_frame_;
WebPluginImpl* plugin_;
bool uses_shared_bitmaps_;
#if defined(OS_MACOSX)
diff --git a/chromium/content/renderer/npapi/webplugin_impl.cc b/chromium/content/renderer/npapi/webplugin_impl.cc
index 13874f3fbb1..ed6436f5bb5 100644
--- a/chromium/content/renderer/npapi/webplugin_impl.cc
+++ b/chromium/content/renderer/npapi/webplugin_impl.cc
@@ -24,6 +24,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/npapi/webplugin_delegate_proxy.h"
+#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
@@ -33,6 +34,7 @@
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebCookieJar.h"
+#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebHTTPBody.h"
#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
@@ -42,7 +44,6 @@
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
-#include "third_party/WebKit/public/web/WebCursorInfo.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
@@ -57,32 +58,32 @@
#include "webkit/child/multipart_response_delegate.h"
#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
-using WebKit::WebCanvas;
-using WebKit::WebConsoleMessage;
-using WebKit::WebCookieJar;
-using WebKit::WebCString;
-using WebKit::WebCursorInfo;
-using WebKit::WebData;
-using WebKit::WebDataSource;
-using WebKit::WebFrame;
-using WebKit::WebHTTPBody;
-using WebKit::WebHTTPHeaderVisitor;
-using WebKit::WebInputEvent;
-using WebKit::WebKeyboardEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebPluginContainer;
-using WebKit::WebPluginParams;
-using WebKit::WebRect;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebURLError;
-using WebKit::WebURLLoader;
-using WebKit::WebURLLoaderClient;
-using WebKit::WebURLLoaderOptions;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
-using WebKit::WebVector;
-using WebKit::WebView;
+using blink::WebCanvas;
+using blink::WebConsoleMessage;
+using blink::WebCookieJar;
+using blink::WebCString;
+using blink::WebCursorInfo;
+using blink::WebData;
+using blink::WebDataSource;
+using blink::WebFrame;
+using blink::WebHTTPBody;
+using blink::WebHTTPHeaderVisitor;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebPluginContainer;
+using blink::WebPluginParams;
+using blink::WebRect;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebURLError;
+using blink::WebURLLoader;
+using blink::WebURLLoaderClient;
+using blink::WebURLLoaderOptions;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
+using blink::WebVector;
+using blink::WebView;
using webkit_glue::MultipartResponseDelegate;
namespace content {
@@ -212,14 +213,14 @@ void GetResponseInfo(const WebURLResponse& response,
} // namespace
-// WebKit::WebPlugin ----------------------------------------------------------
+// blink::WebPlugin ----------------------------------------------------------
struct WebPluginImpl::ClientInfo {
unsigned long id;
WebPluginResourceClient* client;
- WebKit::WebURLRequest request;
+ blink::WebURLRequest request;
bool pending_failure_notification;
- linked_ptr<WebKit::WebURLLoader> loader;
+ linked_ptr<blink::WebURLLoader> loader;
bool notify_redirects;
bool is_plugin_src_load;
int64 data_offset;
@@ -249,9 +250,9 @@ bool WebPluginImpl::initialize(WebPluginContainer* container) {
if (!ok) {
plugin_delegate->PluginDestroyed();
- WebKit::WebPlugin* replacement_plugin =
+ blink::WebPlugin* replacement_plugin =
GetContentClient()->renderer()->CreatePluginReplacement(
- render_view_.get(), file_path_);
+ render_frame_, file_path_);
if (!replacement_plugin)
return false;
@@ -286,7 +287,7 @@ NPP WebPluginImpl::pluginNPP() {
return npp_;
}
-bool WebPluginImpl::getFormValue(WebKit::WebString& value) {
+bool WebPluginImpl::getFormValue(blink::WebString& value) {
if (!delegate_)
return false;
base::string16 form_value;
@@ -481,10 +482,12 @@ WebPluginImpl::WebPluginImpl(
WebFrame* webframe,
const WebPluginParams& params,
const base::FilePath& file_path,
- const base::WeakPtr<RenderViewImpl>& render_view)
+ const base::WeakPtr<RenderViewImpl>& render_view,
+ RenderFrameImpl* render_frame)
: windowless_(false),
window_(gfx::kNullPluginWindow),
accepts_input_events_(false),
+ render_frame_(render_frame),
render_view_(render_view),
webframe_(webframe),
delegate_(NULL),
@@ -648,7 +651,8 @@ WebPluginDelegate* WebPluginImpl::CreatePluginDelegate() {
#endif
}
- return new WebPluginDelegateProxy(this, mime_type_, render_view_);
+ return new WebPluginDelegateProxy(
+ this, mime_type_, render_view_, render_frame_);
}
WebPluginImpl::RoutingStatus WebPluginImpl::RouteToFrame(
@@ -968,7 +972,8 @@ void WebPluginImpl::didReceiveResponse(WebURLLoader* loader,
&upper_bound,
&instance_size);
} else if (response.httpStatusCode() == kHttpResponseSuccessStatusCode) {
- RenderThreadImpl::current()->RecordUserMetrics("Plugin_200ForByteRange");
+ RenderThreadImpl::current()->RecordAction(
+ UserMetricsAction("Plugin_200ForByteRange"));
// If the client issued a byte range request and the server responds with
// HTTP 200 OK, it indicates that the server does not support byte range
// requests.
@@ -1194,8 +1199,8 @@ void WebPluginImpl::HandleURLRequestInternal(const char* url,
if (!delegate_)
return;
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDirectNPAPIRequests)) {
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableDirectNPAPIRequests)) {
// We got here either because the plugin called GetURL/PostURL, or because
// we're fetching the data for an embed tag. If we're in multi-process mode,
// we want to fetch the data in the plugin process as the renderer won't be
@@ -1487,7 +1492,7 @@ void WebPluginImpl::TearDownPluginInstance(
weak_factory_.InvalidateWeakPtrs();
}
-void WebPluginImpl::SetReferrer(WebKit::WebURLRequest* request,
+void WebPluginImpl::SetReferrer(blink::WebURLRequest* request,
Referrer referrer_flag) {
switch (referrer_flag) {
case DOCUMENT_URL:
diff --git a/chromium/content/renderer/npapi/webplugin_impl.h b/chromium/content/renderer/npapi/webplugin_impl.h
index 9c7bf011875..1b7049c8654 100644
--- a/chromium/content/renderer/npapi/webplugin_impl.h
+++ b/chromium/content/renderer/npapi/webplugin_impl.h
@@ -29,7 +29,7 @@ namespace cc {
class IOSurfaceLayer;
}
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebLayer;
class WebPluginContainer;
@@ -43,7 +43,7 @@ class MultipartResponseDelegate;
} // namespace webkit_glue
namespace content {
-
+class RenderFrameImpl;
class RenderViewImpl;
class WebPluginDelegate;
@@ -51,50 +51,51 @@ class WebPluginDelegate;
// after changing out of WebCore types, to a delegate. The delegate may
// be in a different process.
class WebPluginImpl : public WebPlugin,
- public WebKit::WebPlugin,
- public WebKit::WebURLLoaderClient {
+ public blink::WebPlugin,
+ public blink::WebURLLoaderClient {
public:
WebPluginImpl(
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params,
+ blink::WebFrame* frame,
+ const blink::WebPluginParams& params,
const base::FilePath& file_path,
- const base::WeakPtr<RenderViewImpl>& render_view);
+ const base::WeakPtr<RenderViewImpl>& render_view,
+ RenderFrameImpl* render_frame);
virtual ~WebPluginImpl();
// Helper function for sorting post data.
- CONTENT_EXPORT static bool SetPostData(WebKit::WebURLRequest* request,
+ CONTENT_EXPORT static bool SetPostData(blink::WebURLRequest* request,
const char* buf,
uint32 length);
- WebKit::WebFrame* webframe() { return webframe_; }
+ blink::WebFrame* webframe() { return webframe_; }
WebPluginDelegate* delegate() { return delegate_; }
- // WebKit::WebPlugin methods:
+ // blink::WebPlugin methods:
virtual bool initialize(
- WebKit::WebPluginContainer* container);
+ blink::WebPluginContainer* container);
virtual void destroy();
virtual NPObject* scriptableObject();
virtual struct _NPP* pluginNPP();
- virtual bool getFormValue(WebKit::WebString& value);
+ virtual bool getFormValue(blink::WebString& value);
virtual void paint(
- WebKit::WebCanvas* canvas, const WebKit::WebRect& paint_rect);
+ blink::WebCanvas* canvas, const blink::WebRect& paint_rect);
virtual void updateGeometry(
- const WebKit::WebRect& frame_rect, const WebKit::WebRect& clip_rect,
- const WebKit::WebVector<WebKit::WebRect>& cut_outs, bool is_visible);
+ const blink::WebRect& frame_rect, const blink::WebRect& clip_rect,
+ const blink::WebVector<blink::WebRect>& cut_outs, bool is_visible);
virtual void updateFocus(bool focused);
virtual void updateVisibility(bool visible);
virtual bool acceptsInputEvents();
virtual bool handleInputEvent(
- const WebKit::WebInputEvent& event, WebKit::WebCursorInfo& cursor_info);
- virtual void didReceiveResponse(const WebKit::WebURLResponse& response);
+ const blink::WebInputEvent& event, blink::WebCursorInfo& cursor_info);
+ virtual void didReceiveResponse(const blink::WebURLResponse& response);
virtual void didReceiveData(const char* data, int data_length);
virtual void didFinishLoading();
- virtual void didFailLoading(const WebKit::WebURLError& error);
+ virtual void didFailLoading(const blink::WebURLError& error);
virtual void didFinishLoadingFrameRequest(
- const WebKit::WebURL& url, void* notify_data);
+ const blink::WebURL& url, void* notify_data);
virtual void didFailLoadingFrameRequest(
- const WebKit::WebURL& url, void* notify_data,
- const WebKit::WebURLError& error);
+ const blink::WebURL& url, void* notify_data,
+ const blink::WebURLError& error);
virtual bool isPlaceholder() OVERRIDE;
// WebPlugin implementation:
@@ -200,31 +201,31 @@ class WebPluginImpl : public WebPlugin,
gfx::Rect GetWindowClipRect(const gfx::Rect& rect);
// Sets the actual Widget for the plugin.
- void SetContainer(WebKit::WebPluginContainer* container);
+ void SetContainer(blink::WebPluginContainer* container);
// Destroys the plugin instance.
// The response_handle_to_ignore parameter if not NULL indicates the
// resource handle to be left valid during plugin shutdown.
- void TearDownPluginInstance(WebKit::WebURLLoader* loader_to_ignore);
+ void TearDownPluginInstance(blink::WebURLLoader* loader_to_ignore);
// WebURLLoaderClient implementation. We implement this interface in the
// renderer process, and then use the simple WebPluginResourceClient interface
// to relay the callbacks to the plugin.
- virtual void willSendRequest(WebKit::WebURLLoader* loader,
- WebKit::WebURLRequest& request,
- const WebKit::WebURLResponse& response);
- virtual void didSendData(WebKit::WebURLLoader* loader,
+ virtual void willSendRequest(blink::WebURLLoader* loader,
+ blink::WebURLRequest& request,
+ const blink::WebURLResponse& response);
+ virtual void didSendData(blink::WebURLLoader* loader,
unsigned long long bytes_sent,
unsigned long long total_bytes_to_be_sent);
- virtual void didReceiveResponse(WebKit::WebURLLoader* loader,
- const WebKit::WebURLResponse& response);
+ virtual void didReceiveResponse(blink::WebURLLoader* loader,
+ const blink::WebURLResponse& response);
- virtual void didReceiveData(WebKit::WebURLLoader* loader, const char *buffer,
+ virtual void didReceiveData(blink::WebURLLoader* loader, const char *buffer,
int data_length, int encoded_data_length);
- virtual void didFinishLoading(WebKit::WebURLLoader* loader,
+ virtual void didFinishLoading(blink::WebURLLoader* loader,
double finishTime);
- virtual void didFail(WebKit::WebURLLoader* loader,
- const WebKit::WebURLError& error);
+ virtual void didFail(blink::WebURLLoader* loader,
+ const blink::WebURLError& error);
// Helper function to remove the stored information about a resource
// request given its index in m_clients.
@@ -232,13 +233,13 @@ class WebPluginImpl : public WebPlugin,
// Helper function to remove the stored information about a resource
// request given a handle.
- void RemoveClient(WebKit::WebURLLoader* loader);
+ void RemoveClient(blink::WebURLLoader* loader);
// Handles HTTP multipart responses, i.e. responses received with a HTTP
// status code of 206.
// Returns false if response is not multipart (may be if we requested
// single range).
- bool HandleHttpMultipartResponse(const WebKit::WebURLResponse& response,
+ bool HandleHttpMultipartResponse(const blink::WebURLResponse& response,
WebPluginResourceClient* client);
void HandleURLRequestInternal(const char* url,
@@ -254,7 +255,7 @@ class WebPluginImpl : public WebPlugin,
// Tears down the existing plugin instance and creates a new plugin instance
// to handle the response identified by the loader parameter.
- bool ReinitializePluginForResponse(WebKit::WebURLLoader* loader);
+ bool ReinitializePluginForResponse(blink::WebURLLoader* loader);
// Delayed task for downloading the plugin source URL.
void OnDownloadPluginSrcUrl();
@@ -262,11 +263,11 @@ class WebPluginImpl : public WebPlugin,
struct ClientInfo;
// Helper functions
- WebPluginResourceClient* GetClientFromLoader(WebKit::WebURLLoader* loader);
- ClientInfo* GetClientInfoFromLoader(WebKit::WebURLLoader* loader);
+ WebPluginResourceClient* GetClientFromLoader(blink::WebURLLoader* loader);
+ ClientInfo* GetClientInfoFromLoader(blink::WebURLLoader* loader);
// Helper function to set the referrer on the request passed in.
- void SetReferrer(WebKit::WebURLRequest* request, Referrer referrer_flag);
+ void SetReferrer(blink::WebURLRequest* request, Referrer referrer_flag);
// Check for invalid chars like @, ;, \ before the first / (in path).
bool IsValidUrl(const GURL& url, Referrer referrer_flag);
@@ -283,16 +284,17 @@ class WebPluginImpl : public WebPlugin,
int32 next_io_surface_height_;
uint32 next_io_surface_id_;
scoped_refptr<cc::IOSurfaceLayer> io_surface_layer_;
- scoped_ptr<WebKit::WebLayer> web_layer_;
+ scoped_ptr<blink::WebLayer> web_layer_;
#endif
bool accepts_input_events_;
+ RenderFrameImpl* render_frame_;
base::WeakPtr<RenderViewImpl> render_view_;
- WebKit::WebFrame* webframe_;
+ blink::WebFrame* webframe_;
WebPluginDelegate* delegate_;
// This is just a weak reference.
- WebKit::WebPluginContainer* container_;
+ blink::WebPluginContainer* container_;
// Unique identifier for this plugin, used to track script objects.
struct _NPP* npp_;
diff --git a/chromium/content/renderer/npapi/webplugin_impl_unittest.cc b/chromium/content/renderer/npapi/webplugin_impl_unittest.cc
index df1371cf620..dd3b83eda5e 100644
--- a/chromium/content/renderer/npapi/webplugin_impl_unittest.cc
+++ b/chromium/content/renderer/npapi/webplugin_impl_unittest.cc
@@ -9,9 +9,9 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
-using WebKit::WebHTTPBody;
-using WebKit::WebString;
-using WebKit::WebURLRequest;
+using blink::WebHTTPBody;
+using blink::WebString;
+using blink::WebURLRequest;
namespace content {
diff --git a/chromium/content/renderer/p2p/ipc_network_manager.cc b/chromium/content/renderer/p2p/ipc_network_manager.cc
index 34a65c53b35..bd7923d9aa1 100644
--- a/chromium/content/renderer/p2p/ipc_network_manager.cc
+++ b/chromium/content/renderer/p2p/ipc_network_manager.cc
@@ -46,18 +46,32 @@ void IpcNetworkManager::OnNetworkListChanged(
if (!network_list_received_)
network_list_received_ = true;
+ // Note: 32 and 64 are the arbitrary(kind of) prefix length used to
+ // differentiate IPv4 and IPv6 addresses.
+ // talk_base::Network uses these prefix_length to compare network
+ // interfaces discovered.
std::vector<talk_base::Network*> networks;
for (net::NetworkInterfaceList::const_iterator it = list.begin();
it != list.end(); it++) {
- uint32 address;
- if (it->address.size() != net::kIPv4AddressSize)
- continue;
- memcpy(&address, &it->address[0], sizeof(uint32));
- address = talk_base::NetworkToHost32(address);
- talk_base::Network* network = new talk_base::Network(
- it->name, it->name, talk_base::IPAddress(address), 32);
- network->AddIP(talk_base::IPAddress(address));
- networks.push_back(network);
+ if (it->address.size() == net::kIPv4AddressSize) {
+ uint32 address;
+ memcpy(&address, &it->address[0], sizeof(uint32));
+ address = talk_base::NetworkToHost32(address);
+ talk_base::Network* network = new talk_base::Network(
+ it->name, it->name, talk_base::IPAddress(address), 32);
+ network->AddIP(talk_base::IPAddress(address));
+ networks.push_back(network);
+ } else if (it->address.size() == net::kIPv6AddressSize) {
+ in6_addr address;
+ memcpy(&address, &it->address[0], sizeof(in6_addr));
+ talk_base::IPAddress ip6_addr(address);
+ if (!talk_base::IPIsPrivate(ip6_addr)) {
+ talk_base::Network* network = new talk_base::Network(
+ it->name, it->name, ip6_addr, 64);
+ network->AddIP(ip6_addr);
+ networks.push_back(network);
+ }
+ }
}
bool changed = false;
diff --git a/chromium/content/renderer/p2p/ipc_socket_factory.cc b/chromium/content/renderer/p2p/ipc_socket_factory.cc
index ced8822dc9b..04825c35f75 100644
--- a/chromium/content/renderer/p2p/ipc_socket_factory.cc
+++ b/chromium/content/renderer/p2p/ipc_socket_factory.cc
@@ -10,7 +10,9 @@
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "content/renderer/p2p/socket_client.h"
+#include "content/public/renderer/p2p_socket_client_delegate.h"
+#include "content/renderer/p2p/host_address_request.h"
+#include "content/renderer/p2p/socket_client_impl.h"
#include "content/renderer/p2p/socket_dispatcher.h"
#include "jingle/glue/utils.h"
#include "third_party/libjingle/source/talk/base/asyncpacketsocket.h"
@@ -35,13 +37,13 @@ const size_t kMaximumInFlightBytes = 64 * 1024; // 64 KB
// using P2PSocketClient that works over IPC-channel. It must be used
// on the thread it was created.
class IpcPacketSocket : public talk_base::AsyncPacketSocket,
- public P2PSocketClient::Delegate {
+ public P2PSocketClientDelegate {
public:
IpcPacketSocket();
virtual ~IpcPacketSocket();
// Always takes ownership of client even if initialization fails.
- bool Init(P2PSocketType type, P2PSocketClient* client,
+ bool Init(P2PSocketType type, P2PSocketClientImpl* client,
const talk_base::SocketAddress& local_address,
const talk_base::SocketAddress& remote_address);
@@ -60,14 +62,16 @@ class IpcPacketSocket : public talk_base::AsyncPacketSocket,
virtual int GetError() const OVERRIDE;
virtual void SetError(int error) OVERRIDE;
- // P2PSocketClient::Delegate implementation.
+ // P2PSocketClientDelegate implementation.
virtual void OnOpen(const net::IPEndPoint& address) OVERRIDE;
- virtual void OnIncomingTcpConnection(const net::IPEndPoint& address,
- P2PSocketClient* client) OVERRIDE;
+ virtual void OnIncomingTcpConnection(
+ const net::IPEndPoint& address,
+ P2PSocketClient* client) OVERRIDE;
virtual void OnSendComplete() OVERRIDE;
virtual void OnError() OVERRIDE;
virtual void OnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data) OVERRIDE;
+ const std::vector<char>& data,
+ const base::TimeTicks& timestamp) OVERRIDE;
private:
enum InternalState {
@@ -148,7 +152,8 @@ void IpcPacketSocket::TraceSendThrottlingState() const {
in_flight_packet_sizes_.size());
}
-bool IpcPacketSocket::Init(P2PSocketType type, P2PSocketClient* client,
+bool IpcPacketSocket::Init(P2PSocketType type,
+ P2PSocketClientImpl* client,
const talk_base::SocketAddress& local_address,
const talk_base::SocketAddress& remote_address) {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
@@ -173,7 +178,7 @@ bool IpcPacketSocket::Init(P2PSocketType type, P2PSocketClient* client,
return false;
}
- client_->Init(type, local_endpoint, remote_endpoint, this);
+ client->Init(type, local_endpoint, remote_endpoint, this);
return true;
}
@@ -190,7 +195,7 @@ void IpcPacketSocket::InitAcceptedTcp(
remote_address_ = remote_address;
state_ = IS_OPEN;
TraceSendThrottlingState();
- client_->set_delegate(this);
+ client_->SetDelegate(this);
}
// talk_base::AsyncPacketSocket interface.
@@ -237,7 +242,9 @@ int IpcPacketSocket::SendTo(const void *data, size_t data_size,
if (data_size > send_bytes_available_) {
TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
- TRACE_EVENT_SCOPE_THREAD, "id", client_->socket_id());
+ TRACE_EVENT_SCOPE_THREAD,
+ "id",
+ client_->GetSocketID());
writable_signal_expected_ = true;
error_ = EWOULDBLOCK;
return -1;
@@ -256,7 +263,8 @@ int IpcPacketSocket::SendTo(const void *data, size_t data_size,
const char* data_char = reinterpret_cast<const char*>(data);
std::vector<char> data_vector(data_char, data_char + data_size);
- client_->Send(address_chrome, data_vector);
+ client_->SendWithDscp(address_chrome, data_vector,
+ static_cast<net::DiffServCodePoint>(dscp));
// Fake successful send. The caller ignores result anyway.
return data_size;
@@ -374,7 +382,8 @@ void IpcPacketSocket::OnError() {
}
void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data) {
+ const std::vector<char>& data,
+ const base::TimeTicks& timestamp) {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
talk_base::SocketAddress address_lj;
@@ -385,7 +394,9 @@ void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address,
return;
}
- SignalReadPacket(this, &data[0], data.size(), address_lj);
+ talk_base::PacketTime packet_time(timestamp.ToInternalValue(), 0);
+ SignalReadPacket(this, &data[0], data.size(), address_lj,
+ packet_time);
}
} // namespace
@@ -401,7 +412,8 @@ IpcPacketSocketFactory::~IpcPacketSocketFactory() {
talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket(
const talk_base::SocketAddress& local_address, int min_port, int max_port) {
talk_base::SocketAddress crome_address;
- P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_);
+ P2PSocketClientImpl* socket_client =
+ new P2PSocketClientImpl(socket_dispatcher_);
scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
// TODO(sergeyu): Respect local_address and port limits here (need
// to pass them over IPC channel to the browser).
@@ -421,7 +433,8 @@ talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket(
P2PSocketType type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ?
P2P_SOCKET_STUN_TCP_SERVER : P2P_SOCKET_TCP_SERVER;
- P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_);
+ P2PSocketClientImpl* socket_client =
+ new P2PSocketClientImpl(socket_dispatcher_);
scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
if (!socket->Init(type, socket_client, local_address,
talk_base::SocketAddress())) {
@@ -446,12 +459,18 @@ talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket(
type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ?
P2P_SOCKET_STUN_TCP_CLIENT : P2P_SOCKET_TCP_CLIENT;
}
- P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_);
+ P2PSocketClientImpl* socket_client =
+ new P2PSocketClientImpl(socket_dispatcher_);
scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
- if (!socket->Init(type, socket_client, local_address,
- remote_address))
+ if (!socket->Init(type, socket_client, local_address, remote_address))
return NULL;
return socket.release();
}
+talk_base::AsyncResolverInterface*
+IpcPacketSocketFactory::CreateAsyncResolver() {
+ NOTREACHED();
+ return NULL;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/p2p/ipc_socket_factory.h b/chromium/content/renderer/p2p/ipc_socket_factory.h
index cb418838958..cba98b3c0d0 100644
--- a/chromium/content/renderer/p2p/ipc_socket_factory.h
+++ b/chromium/content/renderer/p2p/ipc_socket_factory.h
@@ -40,6 +40,7 @@ class IpcPacketSocketFactory : public talk_base::PacketSocketFactory {
const talk_base::ProxyInfo& proxy_info,
const std::string& user_agent,
int opts) OVERRIDE;
+ virtual talk_base::AsyncResolverInterface* CreateAsyncResolver() OVERRIDE;
private:
P2PSocketDispatcher* socket_dispatcher_;
diff --git a/chromium/content/renderer/p2p/port_allocator.cc b/chromium/content/renderer/p2p/port_allocator.cc
index 2c5b8e44d88..280e04d7bc8 100644
--- a/chromium/content/renderer/p2p/port_allocator.cc
+++ b/chromium/content/renderer/p2p/port_allocator.cc
@@ -21,12 +21,12 @@
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebURLLoaderOptions.h"
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebURLLoader;
-using WebKit::WebURLLoaderOptions;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebURLLoader;
+using blink::WebURLLoaderOptions;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
namespace content {
@@ -69,7 +69,7 @@ P2PPortAllocator::Config::RelayServerConfig::~RelayServerConfig() {
}
P2PPortAllocator::P2PPortAllocator(
- WebKit::WebFrame* web_frame,
+ blink::WebFrame* web_frame,
P2PSocketDispatcher* socket_dispatcher,
talk_base::NetworkManager* network_manager,
talk_base::PacketSocketFactory* socket_factory,
@@ -153,8 +153,8 @@ void P2PPortAllocatorSession::didFinishLoading(WebURLLoader* loader,
ParseRelayResponse();
}
-void P2PPortAllocatorSession::didFail(WebKit::WebURLLoader* loader,
- const WebKit::WebURLError& error) {
+void P2PPortAllocatorSession::didFail(blink::WebURLLoader* loader,
+ const blink::WebURLError& error) {
DCHECK_EQ(loader, relay_session_request_.get());
DCHECK_NE(error.reason, 0);
diff --git a/chromium/content/renderer/p2p/port_allocator.h b/chromium/content/renderer/p2p/port_allocator.h
index 5c0a4fc332e..eb50aeff4cb 100644
--- a/chromium/content/renderer/p2p/port_allocator.h
+++ b/chromium/content/renderer/p2p/port_allocator.h
@@ -11,10 +11,10 @@
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
#include "third_party/libjingle/source/talk/p2p/client/basicportallocator.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebURLLoader;
-} // namespace WebKit
+} // namespace blink
namespace content {
@@ -54,7 +54,7 @@ class P2PPortAllocator : public cricket::BasicPortAllocator {
bool disable_tcp_transport;
};
- P2PPortAllocator(WebKit::WebFrame* web_frame,
+ P2PPortAllocator(blink::WebFrame* web_frame,
P2PSocketDispatcher* socket_dispatcher,
talk_base::NetworkManager* network_manager,
talk_base::PacketSocketFactory* socket_factory,
@@ -70,7 +70,7 @@ class P2PPortAllocator : public cricket::BasicPortAllocator {
private:
friend class P2PPortAllocatorSession;
- WebKit::WebFrame* web_frame_;
+ blink::WebFrame* web_frame_;
P2PSocketDispatcher* socket_dispatcher_;
Config config_;
@@ -78,7 +78,7 @@ class P2PPortAllocator : public cricket::BasicPortAllocator {
};
class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession,
- public WebKit::WebURLLoaderClient {
+ public blink::WebURLLoaderClient {
public:
P2PPortAllocatorSession(
P2PPortAllocator* allocator,
@@ -88,15 +88,15 @@ class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession,
const std::string& ice_password);
virtual ~P2PPortAllocatorSession();
- // WebKit::WebURLLoaderClient overrides.
- virtual void didReceiveData(WebKit::WebURLLoader* loader,
+ // blink::WebURLLoaderClient overrides.
+ virtual void didReceiveData(blink::WebURLLoader* loader,
const char* data,
int data_length,
int encoded_data_length) OVERRIDE;
- virtual void didFinishLoading(WebKit::WebURLLoader* loader,
+ virtual void didFinishLoading(blink::WebURLLoader* loader,
double finish_time) OVERRIDE;
- virtual void didFail(WebKit::WebURLLoader* loader,
- const WebKit::WebURLError& error) OVERRIDE;
+ virtual void didFail(blink::WebURLLoader* loader,
+ const blink::WebURLError& error) OVERRIDE;
protected:
// Overrides for cricket::BasicPortAllocatorSession.
@@ -134,7 +134,7 @@ class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession,
std::vector<RelayServer> relay_info_;
- scoped_ptr<WebKit::WebURLLoader> relay_session_request_;
+ scoped_ptr<blink::WebURLLoader> relay_session_request_;
int relay_session_attempts_;
std::string relay_session_response_;
talk_base::SocketAddress relay_ip_;
diff --git a/chromium/content/renderer/p2p/socket_client.cc b/chromium/content/renderer/p2p/socket_client.cc
deleted file mode 100644
index 68797db66cc..00000000000
--- a/chromium/content/renderer/p2p/socket_client.cc
+++ /dev/null
@@ -1,186 +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/renderer/p2p/socket_client.h"
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "content/common/p2p_messages.h"
-#include "content/renderer/p2p/socket_dispatcher.h"
-
-namespace content {
-
-P2PSocketClient::P2PSocketClient(P2PSocketDispatcher* dispatcher)
- : dispatcher_(dispatcher),
- ipc_message_loop_(dispatcher->message_loop()),
- delegate_message_loop_(base::MessageLoopProxy::current()),
- socket_id_(0), delegate_(NULL),
- state_(STATE_UNINITIALIZED) {
-}
-
-P2PSocketClient::~P2PSocketClient() {
- CHECK(state_ == STATE_CLOSED || state_ == STATE_UNINITIALIZED);
-}
-
-void P2PSocketClient::Init(
- P2PSocketType type,
- const net::IPEndPoint& local_address,
- const net::IPEndPoint& remote_address,
- P2PSocketClient::Delegate* delegate) {
- DCHECK(delegate_message_loop_->BelongsToCurrentThread());
- // |delegate_| is only accessesed on |delegate_message_loop_|.
- delegate_ = delegate;
-
- ipc_message_loop_->PostTask(
- FROM_HERE, base::Bind(&P2PSocketClient::DoInit, this, type, local_address,
- remote_address));
-}
-
-void P2PSocketClient::DoInit(P2PSocketType type,
- const net::IPEndPoint& local_address,
- const net::IPEndPoint& remote_address) {
- DCHECK_EQ(state_, STATE_UNINITIALIZED);
- DCHECK(delegate_);
- state_ = STATE_OPENING;
- socket_id_ = dispatcher_->RegisterClient(this);
- dispatcher_->SendP2PMessage(new P2PHostMsg_CreateSocket(
- type, socket_id_, local_address, remote_address));
-}
-
-void P2PSocketClient::Send(const net::IPEndPoint& address,
- const std::vector<char>& data) {
- if (!ipc_message_loop_->BelongsToCurrentThread()) {
- ipc_message_loop_->PostTask(
- FROM_HERE, base::Bind(&P2PSocketClient::Send, this, address, data));
- return;
- }
-
- // Can send data only when the socket is open.
- DCHECK(state_ == STATE_OPEN || state_ == STATE_ERROR);
- if (state_ == STATE_OPEN) {
- dispatcher_->SendP2PMessage(new P2PHostMsg_Send(socket_id_, address, data));
- }
-}
-
-void P2PSocketClient::Close() {
- DCHECK(delegate_message_loop_->BelongsToCurrentThread());
-
- delegate_ = NULL;
-
- ipc_message_loop_->PostTask(
- FROM_HERE, base::Bind(&P2PSocketClient::DoClose, this));
-}
-
-void P2PSocketClient::DoClose() {
- DCHECK(ipc_message_loop_->BelongsToCurrentThread());
- if (dispatcher_) {
- if (state_ == STATE_OPEN || state_ == STATE_OPENING ||
- state_ == STATE_ERROR) {
- dispatcher_->SendP2PMessage(new P2PHostMsg_DestroySocket(socket_id_));
- }
- dispatcher_->UnregisterClient(socket_id_);
- }
-
- state_ = STATE_CLOSED;
-}
-
-void P2PSocketClient::set_delegate(Delegate* delegate) {
- DCHECK(delegate_message_loop_->BelongsToCurrentThread());
- delegate_ = delegate;
-}
-
-void P2PSocketClient::OnSocketCreated(const net::IPEndPoint& address) {
- DCHECK(ipc_message_loop_->BelongsToCurrentThread());
- DCHECK_EQ(state_, STATE_OPENING);
- state_ = STATE_OPEN;
-
- delegate_message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&P2PSocketClient::DeliverOnSocketCreated, this, address));
-}
-
-void P2PSocketClient::DeliverOnSocketCreated(const net::IPEndPoint& address) {
- DCHECK(delegate_message_loop_->BelongsToCurrentThread());
- if (delegate_)
- delegate_->OnOpen(address);
-}
-
-void P2PSocketClient::OnIncomingTcpConnection(const net::IPEndPoint& address) {
- DCHECK(ipc_message_loop_->BelongsToCurrentThread());
- DCHECK_EQ(state_, STATE_OPEN);
-
- scoped_refptr<P2PSocketClient> new_client = new P2PSocketClient(dispatcher_);
- new_client->socket_id_ = dispatcher_->RegisterClient(new_client.get());
- new_client->state_ = STATE_OPEN;
- new_client->delegate_message_loop_ = delegate_message_loop_;
-
- dispatcher_->SendP2PMessage(new P2PHostMsg_AcceptIncomingTcpConnection(
- socket_id_, address, new_client->socket_id_));
-
- delegate_message_loop_->PostTask(
- FROM_HERE, base::Bind(&P2PSocketClient::DeliverOnIncomingTcpConnection,
- this, address, new_client));
-}
-
-void P2PSocketClient::DeliverOnIncomingTcpConnection(
- const net::IPEndPoint& address, scoped_refptr<P2PSocketClient> new_client) {
- DCHECK(delegate_message_loop_->BelongsToCurrentThread());
- if (delegate_) {
- delegate_->OnIncomingTcpConnection(address, new_client.get());
- } else {
- // Just close the socket if there is no delegate to accept it.
- new_client->Close();
- }
-}
-
-void P2PSocketClient::OnSendComplete() {
- DCHECK(ipc_message_loop_->BelongsToCurrentThread());
-
- delegate_message_loop_->PostTask(
- FROM_HERE, base::Bind(&P2PSocketClient::DeliverOnSendComplete, this));
-}
-
-void P2PSocketClient::DeliverOnSendComplete() {
- DCHECK(delegate_message_loop_->BelongsToCurrentThread());
- if (delegate_)
- delegate_->OnSendComplete();
-}
-
-void P2PSocketClient::OnError() {
- DCHECK(ipc_message_loop_->BelongsToCurrentThread());
- state_ = STATE_ERROR;
-
- delegate_message_loop_->PostTask(
- FROM_HERE, base::Bind(&P2PSocketClient::DeliverOnError, this));
-}
-
-void P2PSocketClient::DeliverOnError() {
- DCHECK(delegate_message_loop_->BelongsToCurrentThread());
- if (delegate_)
- delegate_->OnError();
-}
-
-void P2PSocketClient::OnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data) {
- DCHECK(ipc_message_loop_->BelongsToCurrentThread());
- DCHECK_EQ(STATE_OPEN, state_);
- delegate_message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&P2PSocketClient::DeliverOnDataReceived, this, address, data));
-}
-
-void P2PSocketClient::DeliverOnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data) {
- DCHECK(delegate_message_loop_->BelongsToCurrentThread());
- if (delegate_)
- delegate_->OnDataReceived(address, data);
-}
-
-void P2PSocketClient::Detach() {
- DCHECK(ipc_message_loop_->BelongsToCurrentThread());
- dispatcher_ = NULL;
- OnError();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/p2p/socket_client_impl.cc b/chromium/content/renderer/p2p/socket_client_impl.cc
new file mode 100644
index 00000000000..b0d58498090
--- /dev/null
+++ b/chromium/content/renderer/p2p/socket_client_impl.cc
@@ -0,0 +1,243 @@
+// 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/p2p/socket_client_impl.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "content/common/p2p_messages.h"
+#include "content/public/renderer/p2p_socket_client_delegate.h"
+#include "content/renderer/p2p/socket_dispatcher.h"
+#include "content/renderer/render_thread_impl.h"
+#include "crypto/random.h"
+
+namespace {
+
+uint64 GetUniqueId(uint32 random_socket_id, uint32 packet_id) {
+ uint64 uid = random_socket_id;
+ uid <<= 32;
+ uid |= packet_id;
+ return uid;
+}
+
+} // namespace
+
+namespace content {
+
+scoped_refptr<P2PSocketClient> P2PSocketClient::Create(
+ P2PSocketType type,
+ const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address,
+ P2PSocketClientDelegate* delegate) {
+ P2PSocketClientImpl *impl = new P2PSocketClientImpl(
+ RenderThreadImpl::current()->p2p_socket_dispatcher());
+ impl->Init(type, local_address, remote_address, delegate);
+ return impl;
+}
+
+P2PSocketClientImpl::P2PSocketClientImpl(P2PSocketDispatcher* dispatcher)
+ : dispatcher_(dispatcher),
+ ipc_message_loop_(dispatcher->message_loop()),
+ delegate_message_loop_(base::MessageLoopProxy::current()),
+ socket_id_(0), delegate_(NULL),
+ state_(STATE_UNINITIALIZED),
+ random_socket_id_(0),
+ next_packet_id_(0) {
+ crypto::RandBytes(&random_socket_id_, sizeof(random_socket_id_));
+}
+
+P2PSocketClientImpl::~P2PSocketClientImpl() {
+ CHECK(state_ == STATE_CLOSED || state_ == STATE_UNINITIALIZED);
+}
+
+void P2PSocketClientImpl::Init(
+ P2PSocketType type,
+ const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address,
+ P2PSocketClientDelegate* delegate) {
+ DCHECK(delegate_message_loop_->BelongsToCurrentThread());
+ // |delegate_| is only accessesed on |delegate_message_loop_|.
+ delegate_ = delegate;
+
+ ipc_message_loop_->PostTask(
+ FROM_HERE, base::Bind(&P2PSocketClientImpl::DoInit,
+ this,
+ type,
+ local_address,
+ remote_address));
+}
+
+void P2PSocketClientImpl::DoInit(P2PSocketType type,
+ const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) {
+ DCHECK_EQ(state_, STATE_UNINITIALIZED);
+ DCHECK(delegate_);
+ state_ = STATE_OPENING;
+ socket_id_ = dispatcher_->RegisterClient(this);
+ dispatcher_->SendP2PMessage(new P2PHostMsg_CreateSocket(
+ type, socket_id_, local_address, remote_address));
+}
+
+void P2PSocketClientImpl::SendWithDscp(
+ const net::IPEndPoint& address,
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp) {
+ if (!ipc_message_loop_->BelongsToCurrentThread()) {
+ ipc_message_loop_->PostTask(
+ FROM_HERE, base::Bind(
+ &P2PSocketClientImpl::SendWithDscp, this, address, data, dscp));
+ return;
+ }
+
+ // Can send data only when the socket is open.
+ DCHECK(state_ == STATE_OPEN || state_ == STATE_ERROR);
+ if (state_ == STATE_OPEN) {
+ uint64 unique_id = GetUniqueId(random_socket_id_, ++next_packet_id_);
+ TRACE_EVENT_ASYNC_BEGIN0("p2p", "Send", unique_id);
+ dispatcher_->SendP2PMessage(new P2PHostMsg_Send(socket_id_, address, data,
+ dscp, unique_id));
+ }
+}
+
+void P2PSocketClientImpl::Send(const net::IPEndPoint& address,
+ const std::vector<char>& data) {
+ SendWithDscp(address, data, net::DSCP_DEFAULT);
+}
+
+void P2PSocketClientImpl::Close() {
+ DCHECK(delegate_message_loop_->BelongsToCurrentThread());
+
+ delegate_ = NULL;
+
+ ipc_message_loop_->PostTask(
+ FROM_HERE, base::Bind(&P2PSocketClientImpl::DoClose, this));
+}
+
+void P2PSocketClientImpl::DoClose() {
+ DCHECK(ipc_message_loop_->BelongsToCurrentThread());
+ if (dispatcher_) {
+ if (state_ == STATE_OPEN || state_ == STATE_OPENING ||
+ state_ == STATE_ERROR) {
+ dispatcher_->SendP2PMessage(new P2PHostMsg_DestroySocket(socket_id_));
+ }
+ dispatcher_->UnregisterClient(socket_id_);
+ }
+
+ state_ = STATE_CLOSED;
+}
+
+int P2PSocketClientImpl::GetSocketID() const {
+ return socket_id_;
+}
+
+void P2PSocketClientImpl::SetDelegate(P2PSocketClientDelegate* delegate) {
+ DCHECK(delegate_message_loop_->BelongsToCurrentThread());
+ delegate_ = delegate;
+}
+
+void P2PSocketClientImpl::OnSocketCreated(const net::IPEndPoint& address) {
+ DCHECK(ipc_message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, STATE_OPENING);
+ state_ = STATE_OPEN;
+
+ delegate_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&P2PSocketClientImpl::DeliverOnSocketCreated, this, address));
+}
+
+void P2PSocketClientImpl::DeliverOnSocketCreated(
+ const net::IPEndPoint& address) {
+ DCHECK(delegate_message_loop_->BelongsToCurrentThread());
+ if (delegate_)
+ delegate_->OnOpen(address);
+}
+
+void P2PSocketClientImpl::OnIncomingTcpConnection(
+ const net::IPEndPoint& address) {
+ DCHECK(ipc_message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, STATE_OPEN);
+
+ scoped_refptr<P2PSocketClientImpl> new_client =
+ new P2PSocketClientImpl(dispatcher_);
+ new_client->socket_id_ = dispatcher_->RegisterClient(new_client.get());
+ new_client->state_ = STATE_OPEN;
+ new_client->delegate_message_loop_ = delegate_message_loop_;
+
+ dispatcher_->SendP2PMessage(new P2PHostMsg_AcceptIncomingTcpConnection(
+ socket_id_, address, new_client->socket_id_));
+
+ delegate_message_loop_->PostTask(
+ FROM_HERE, base::Bind(
+ &P2PSocketClientImpl::DeliverOnIncomingTcpConnection,
+ this, address, new_client));
+}
+
+void P2PSocketClientImpl::DeliverOnIncomingTcpConnection(
+ const net::IPEndPoint& address,
+ scoped_refptr<P2PSocketClient> new_client) {
+ DCHECK(delegate_message_loop_->BelongsToCurrentThread());
+ if (delegate_) {
+ delegate_->OnIncomingTcpConnection(address, new_client.get());
+ } else {
+ // Just close the socket if there is no delegate to accept it.
+ new_client->Close();
+ }
+}
+
+void P2PSocketClientImpl::OnSendComplete() {
+ DCHECK(ipc_message_loop_->BelongsToCurrentThread());
+
+ delegate_message_loop_->PostTask(
+ FROM_HERE, base::Bind(&P2PSocketClientImpl::DeliverOnSendComplete, this));
+}
+
+void P2PSocketClientImpl::DeliverOnSendComplete() {
+ DCHECK(delegate_message_loop_->BelongsToCurrentThread());
+ if (delegate_)
+ delegate_->OnSendComplete();
+}
+
+void P2PSocketClientImpl::OnError() {
+ DCHECK(ipc_message_loop_->BelongsToCurrentThread());
+ state_ = STATE_ERROR;
+
+ delegate_message_loop_->PostTask(
+ FROM_HERE, base::Bind(&P2PSocketClientImpl::DeliverOnError, this));
+}
+
+void P2PSocketClientImpl::DeliverOnError() {
+ DCHECK(delegate_message_loop_->BelongsToCurrentThread());
+ if (delegate_)
+ delegate_->OnError();
+}
+
+void P2PSocketClientImpl::OnDataReceived(const net::IPEndPoint& address,
+ const std::vector<char>& data,
+ const base::TimeTicks& timestamp) {
+ DCHECK(ipc_message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(STATE_OPEN, state_);
+ delegate_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&P2PSocketClientImpl::DeliverOnDataReceived,
+ this,
+ address,
+ data,
+ timestamp));
+}
+
+void P2PSocketClientImpl::DeliverOnDataReceived(
+ const net::IPEndPoint& address, const std::vector<char>& data,
+ const base::TimeTicks& timestamp) {
+ DCHECK(delegate_message_loop_->BelongsToCurrentThread());
+ if (delegate_)
+ delegate_->OnDataReceived(address, data, timestamp);
+}
+
+void P2PSocketClientImpl::Detach() {
+ DCHECK(ipc_message_loop_->BelongsToCurrentThread());
+ dispatcher_ = NULL;
+ OnError();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/p2p/socket_client.h b/chromium/content/renderer/p2p/socket_client_impl.h
index fd8537e7242..305a993a752 100644
--- a/chromium/content/renderer/p2p/socket_client.h
+++ b/chromium/content/renderer/p2p/socket_client_impl.h
@@ -1,14 +1,15 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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_P2P_SOCKET_CLIENT_H_
-#define CONTENT_RENDERER_P2P_SOCKET_CLIENT_H_
+#ifndef CONTENT_RENDERER_P2P_SOCKET_CLIENT_IMPL_H_
+#define CONTENT_RENDERER_P2P_SOCKET_CLIENT_IMPL_H_
#include <vector>
#include "base/memory/ref_counted.h"
-#include "content/common/p2p_sockets.h"
+#include "content/public/common/p2p_socket_type.h"
+#include "content/public/renderer/p2p_socket_client.h"
#include "net/base/ip_endpoint.h"
namespace base {
@@ -19,49 +20,41 @@ namespace content {
class P2PSocketDispatcher;
-// P2P socket that rountes all calls over IPC.
+// P2P socket that routes all calls over IPC.
//
// The object runs on two threads: IPC thread and delegate thread. The
// IPC thread is used to interact with P2PSocketDispatcher. All
// callbacks to the user of this class are called on the delegate
// thread which is specified in Init().
-class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> {
+class P2PSocketClientImpl : public P2PSocketClient {
public:
- // Delegate is called on the the same thread on which P2PSocketCLient is
- // created.
- class Delegate {
- public:
- virtual ~Delegate() { }
-
- virtual void OnOpen(const net::IPEndPoint& address) = 0;
- virtual void OnIncomingTcpConnection(const net::IPEndPoint& address,
- P2PSocketClient* client) = 0;
- virtual void OnSendComplete() = 0;
- virtual void OnError() = 0;
- virtual void OnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data) = 0;
- };
-
- explicit P2PSocketClient(P2PSocketDispatcher* dispatcher);
+ explicit P2PSocketClientImpl(P2PSocketDispatcher* dispatcher);
// Initialize socket of the specified |type| and connected to the
// specified |address|. |address| matters only when |type| is set to
// P2P_SOCKET_TCP_CLIENT.
- void Init(P2PSocketType type,
- const net::IPEndPoint& local_address,
- const net::IPEndPoint& remote_address,
- Delegate* delegate);
+ virtual void Init(P2PSocketType type,
+ const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address,
+ P2PSocketClientDelegate* delegate);
// Send the |data| to the |address|.
- void Send(const net::IPEndPoint& address, const std::vector<char>& data);
+ virtual void Send(const net::IPEndPoint& address,
+ const std::vector<char>& data) OVERRIDE;
+
+ // Send the |data| to the |address| using Differentiated Services Code Point
+ // |dscp|.
+ virtual void SendWithDscp(const net::IPEndPoint& address,
+ const std::vector<char>& data,
+ net::DiffServCodePoint dscp) OVERRIDE;
// Must be called before the socket is destroyed. The delegate may
// not be called after |closed_task| is executed.
- void Close();
+ virtual void Close() OVERRIDE;
- int socket_id() const { return socket_id_; }
+ virtual int GetSocketID() const OVERRIDE;
- void set_delegate(Delegate* delegate);
+ virtual void SetDelegate(P2PSocketClientDelegate* delegate) OVERRIDE;
private:
enum State {
@@ -74,10 +67,7 @@ class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> {
friend class P2PSocketDispatcher;
- // Calls destructor.
- friend class base::RefCountedThreadSafe<P2PSocketClient>;
-
- virtual ~P2PSocketClient();
+ virtual ~P2PSocketClientImpl();
// Message handlers that run on IPC thread.
void OnSocketCreated(const net::IPEndPoint& address);
@@ -86,7 +76,8 @@ class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> {
void OnSendComplete();
void OnError();
void OnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data);
+ const std::vector<char>& data,
+ const base::TimeTicks& timestamp);
// Proxy methods that deliver messages to the delegate thread.
void DeliverOnSocketCreated(const net::IPEndPoint& address);
@@ -96,7 +87,8 @@ class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> {
void DeliverOnSendComplete();
void DeliverOnError();
void DeliverOnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data);
+ const std::vector<char>& data,
+ const base::TimeTicks& timestamp);
// Scheduled on the IPC thread to finish initialization.
void DoInit(P2PSocketType type,
@@ -113,12 +105,16 @@ class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> {
scoped_refptr<base::MessageLoopProxy> ipc_message_loop_;
scoped_refptr<base::MessageLoopProxy> delegate_message_loop_;
int socket_id_;
- Delegate* delegate_;
+ P2PSocketClientDelegate* delegate_;
State state_;
- DISALLOW_COPY_AND_ASSIGN(P2PSocketClient);
+ // These two fields are used to identify packets for tracing.
+ uint32 random_socket_id_;
+ uint32 next_packet_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(P2PSocketClientImpl);
};
} // namespace content
-#endif // CONTENT_RENDERER_P2P_SOCKET_CLIENT_H_
+#endif // CONTENT_RENDERER_P2P_SOCKET_CLIENT_IMPL_H_
diff --git a/chromium/content/renderer/p2p/socket_dispatcher.cc b/chromium/content/renderer/p2p/socket_dispatcher.cc
index e3a47a17e82..1b2a6fce0af 100644
--- a/chromium/content/renderer/p2p/socket_dispatcher.cc
+++ b/chromium/content/renderer/p2p/socket_dispatcher.cc
@@ -11,7 +11,7 @@
#include "content/common/p2p_messages.h"
#include "content/renderer/p2p/host_address_request.h"
#include "content/renderer/p2p/network_list_observer.h"
-#include "content/renderer/p2p/socket_client.h"
+#include "content/renderer/p2p/socket_client_impl.h"
#include "content/renderer/render_view_impl.h"
namespace content {
@@ -27,7 +27,7 @@ P2PSocketDispatcher::P2PSocketDispatcher(
P2PSocketDispatcher::~P2PSocketDispatcher() {
network_list_observers_->AssertEmpty();
- for (IDMap<P2PSocketClient>::iterator i(&clients_); !i.IsAtEnd();
+ for (IDMap<P2PSocketClientImpl>::iterator i(&clients_); !i.IsAtEnd();
i.Advance()) {
i.GetCurrentValue()->Detach();
}
@@ -88,7 +88,7 @@ base::MessageLoopProxy* P2PSocketDispatcher::message_loop() {
return message_loop_.get();
}
-int P2PSocketDispatcher::RegisterClient(P2PSocketClient* client) {
+int P2PSocketDispatcher::RegisterClient(P2PSocketClientImpl* client) {
DCHECK(message_loop_->BelongsToCurrentThread());
return clients_.Add(client);
}
@@ -139,7 +139,7 @@ void P2PSocketDispatcher::OnGetHostAddressResult(
void P2PSocketDispatcher::OnSocketCreated(
int socket_id, const net::IPEndPoint& address) {
- P2PSocketClient* client = GetClient(socket_id);
+ P2PSocketClientImpl* client = GetClient(socket_id);
if (client) {
client->OnSocketCreated(address);
}
@@ -147,21 +147,21 @@ void P2PSocketDispatcher::OnSocketCreated(
void P2PSocketDispatcher::OnIncomingTcpConnection(
int socket_id, const net::IPEndPoint& address) {
- P2PSocketClient* client = GetClient(socket_id);
+ P2PSocketClientImpl* client = GetClient(socket_id);
if (client) {
client->OnIncomingTcpConnection(address);
}
}
void P2PSocketDispatcher::OnSendComplete(int socket_id) {
- P2PSocketClient* client = GetClient(socket_id);
+ P2PSocketClientImpl* client = GetClient(socket_id);
if (client) {
client->OnSendComplete();
}
}
void P2PSocketDispatcher::OnError(int socket_id) {
- P2PSocketClient* client = GetClient(socket_id);
+ P2PSocketClientImpl* client = GetClient(socket_id);
if (client) {
client->OnError();
}
@@ -169,15 +169,16 @@ void P2PSocketDispatcher::OnError(int socket_id) {
void P2PSocketDispatcher::OnDataReceived(
int socket_id, const net::IPEndPoint& address,
- const std::vector<char>& data) {
- P2PSocketClient* client = GetClient(socket_id);
+ const std::vector<char>& data,
+ const base::TimeTicks& timestamp) {
+ P2PSocketClientImpl* client = GetClient(socket_id);
if (client) {
- client->OnDataReceived(address, data);
+ client->OnDataReceived(address, data, timestamp);
}
}
-P2PSocketClient* P2PSocketDispatcher::GetClient(int socket_id) {
- P2PSocketClient* client = clients_.Lookup(socket_id);
+P2PSocketClientImpl* P2PSocketDispatcher::GetClient(int socket_id) {
+ P2PSocketClientImpl* client = clients_.Lookup(socket_id);
if (client == NULL) {
// This may happen if the socket was closed, but the browser side
// hasn't processed the close message by the time it sends the
diff --git a/chromium/content/renderer/p2p/socket_dispatcher.h b/chromium/content/renderer/p2p/socket_dispatcher.h
index 34c78a15e87..b1bea29ef11 100644
--- a/chromium/content/renderer/p2p/socket_dispatcher.h
+++ b/chromium/content/renderer/p2p/socket_dispatcher.h
@@ -29,7 +29,7 @@
#include "base/observer_list_threadsafe.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
-#include "content/common/p2p_sockets.h"
+#include "content/public/common/p2p_socket_type.h"
#include "ipc/ipc_channel_proxy.h"
#include "net/base/net_util.h"
@@ -46,7 +46,7 @@ namespace content {
class NetworkListObserver;
class RenderViewImpl;
class P2PHostAddressRequest;
-class P2PSocketClient;
+class P2PSocketClientImpl;
class CONTENT_EXPORT P2PSocketDispatcher
: public IPC::ChannelProxy::MessageFilter {
@@ -68,7 +68,7 @@ class CONTENT_EXPORT P2PSocketDispatcher
private:
friend class P2PHostAddressRequest;
- friend class P2PSocketClient;
+ friend class P2PSocketClientImpl;
// Send a message asynchronously.
virtual void Send(IPC::Message* message);
@@ -83,7 +83,7 @@ class CONTENT_EXPORT P2PSocketDispatcher
base::MessageLoopProxy* message_loop();
// Called by P2PSocketClient.
- int RegisterClient(P2PSocketClient* client);
+ int RegisterClient(P2PSocketClientImpl* client);
void UnregisterClient(int id);
void SendP2PMessage(IPC::Message* msg);
@@ -100,12 +100,13 @@ class CONTENT_EXPORT P2PSocketDispatcher
void OnSendComplete(int socket_id);
void OnError(int socket_id);
void OnDataReceived(int socket_id, const net::IPEndPoint& address,
- const std::vector<char>& data);
+ const std::vector<char>& data,
+ const base::TimeTicks& timestamp);
- P2PSocketClient* GetClient(int socket_id);
+ P2PSocketClientImpl* GetClient(int socket_id);
scoped_refptr<base::MessageLoopProxy> message_loop_;
- IDMap<P2PSocketClient> clients_;
+ IDMap<P2PSocketClientImpl> clients_;
IDMap<P2PHostAddressRequest> host_address_requests_;
diff --git a/chromium/content/renderer/pepper/OWNERS b/chromium/content/renderer/pepper/OWNERS
index cb5435cc3d1..ddbd3b66d38 100644
--- a/chromium/content/renderer/pepper/OWNERS
+++ b/chromium/content/renderer/pepper/OWNERS
@@ -1,6 +1,7 @@
bbudge@chromium.org
dmichael@chromium.org
raymes@chromium.org
+teravest@chromium.org
yzshen@chromium.org
per-file usb_key_code_*=garykac@chromium.org
diff --git a/chromium/content/renderer/pepper/content_decryptor_delegate.cc b/chromium/content/renderer/pepper/content_decryptor_delegate.cc
index ce910379015..49790db2b7b 100644
--- a/chromium/content/renderer/pepper/content_decryptor_delegate.cc
+++ b/chromium/content/renderer/pepper/content_decryptor_delegate.cc
@@ -44,7 +44,7 @@ namespace {
bool MakeBufferResource(PP_Instance instance,
const uint8* data, uint32_t size,
scoped_refptr<PPB_Buffer_Impl>* resource) {
- TRACE_EVENT0("eme", "ContentDecryptorDelegate - MakeBufferResource");
+ TRACE_EVENT0("media", "ContentDecryptorDelegate - MakeBufferResource");
DCHECK(resource);
if (!data || !size) {
@@ -218,6 +218,27 @@ PP_DecryptorStreamType MediaDecryptorStreamTypeToPpStreamType(
}
}
+media::SampleFormat PpDecryptedSampleFormatToMediaSampleFormat(
+ PP_DecryptedSampleFormat result) {
+ switch (result) {
+ case PP_DECRYPTEDSAMPLEFORMAT_U8:
+ return media::kSampleFormatU8;
+ case PP_DECRYPTEDSAMPLEFORMAT_S16:
+ return media::kSampleFormatS16;
+ case PP_DECRYPTEDSAMPLEFORMAT_S32:
+ return media::kSampleFormatS32;
+ case PP_DECRYPTEDSAMPLEFORMAT_F32:
+ return media::kSampleFormatF32;
+ case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_S16:
+ return media::kSampleFormatPlanarS16;
+ case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_F32:
+ return media::kSampleFormatPlanarF32;
+ default:
+ NOTREACHED();
+ return media::kUnknownSampleFormat;
+ }
+}
+
} // namespace
ContentDecryptorDelegate::ContentDecryptorDelegate(
@@ -232,76 +253,66 @@ ContentDecryptorDelegate::ContentDecryptorDelegate(
pending_video_decoder_init_request_id_(0),
pending_audio_decode_request_id_(0),
pending_video_decode_request_id_(0),
- weak_ptr_factory_(this),
- weak_this_(weak_ptr_factory_.GetWeakPtr()),
- audio_sample_format_(media::kUnknownSampleFormat),
audio_samples_per_second_(0),
audio_channel_count_(0),
- audio_bytes_per_frame_(0) {
+ weak_ptr_factory_(this) {
+ weak_this_ = weak_ptr_factory_.GetWeakPtr();
}
ContentDecryptorDelegate::~ContentDecryptorDelegate() {
}
-void ContentDecryptorDelegate::Initialize(const std::string& key_system,
- bool can_challenge_platform) {
+void ContentDecryptorDelegate::Initialize(const std::string& key_system) {
DCHECK(!key_system.empty());
DCHECK(key_system_.empty());
key_system_ = key_system;
plugin_decryption_interface_->Initialize(
pp_instance_,
- StringVar::StringToPPVar(key_system_),
- PP_FromBool(can_challenge_platform));
+ StringVar::StringToPPVar(key_system_));
}
-void ContentDecryptorDelegate::SetKeyEventCallbacks(
- const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb) {
- key_added_cb_ = key_added_cb;
- key_error_cb_ = key_error_cb;
- key_message_cb_ = key_message_cb;
+void ContentDecryptorDelegate::SetSessionEventCallbacks(
+ const media::SessionCreatedCB& session_created_cb,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb) {
+ session_created_cb_ = session_created_cb;
+ session_message_cb_ = session_message_cb;
+ session_ready_cb_ = session_ready_cb;
+ session_closed_cb_ = session_closed_cb;
+ session_error_cb_ = session_error_cb;
}
-bool ContentDecryptorDelegate::GenerateKeyRequest(const std::string& type,
- const uint8* init_data,
- int init_data_length) {
+bool ContentDecryptorDelegate::CreateSession(uint32 session_id,
+ const std::string& type,
+ const uint8* init_data,
+ int init_data_length) {
PP_Var init_data_array =
PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
init_data_length, init_data);
- plugin_decryption_interface_->GenerateKeyRequest(
- pp_instance_,
- StringVar::StringToPPVar(type),
- init_data_array);
+ plugin_decryption_interface_->CreateSession(pp_instance_,
+ session_id,
+ StringVar::StringToPPVar(type),
+ init_data_array);
return true;
}
-bool ContentDecryptorDelegate::AddKey(const std::string& session_id,
- const uint8* key,
- int key_length,
- const uint8* init_data,
- int init_data_length) {
- PP_Var key_array =
- PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(key_length,
- key);
- PP_Var init_data_array =
+bool ContentDecryptorDelegate::UpdateSession(uint32 session_id,
+ const uint8* response,
+ int response_length) {
+ PP_Var response_array =
PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
- init_data_length, init_data);
-
- plugin_decryption_interface_->AddKey(
- pp_instance_,
- StringVar::StringToPPVar(session_id),
- key_array,
- init_data_array);
+ response_length, response);
+ plugin_decryption_interface_->UpdateSession(
+ pp_instance_, session_id, response_array);
return true;
}
-bool ContentDecryptorDelegate::CancelKeyRequest(const std::string& session_id) {
- plugin_decryption_interface_->CancelKeyRequest(
- pp_instance_,
- StringVar::StringToPPVar(session_id));
+bool ContentDecryptorDelegate::ReleaseSession(uint32 session_id) {
+ plugin_decryption_interface_->ReleaseSession(pp_instance_, session_id);
return true;
}
@@ -405,10 +416,8 @@ bool ContentDecryptorDelegate::InitializeAudioDecoder(
pp_decoder_config.samples_per_second = decoder_config.samples_per_second();
pp_decoder_config.request_id = next_decryption_request_id_++;
- audio_sample_format_ = decoder_config.sample_format();
audio_samples_per_second_ = pp_decoder_config.samples_per_second;
audio_channel_count_ = pp_decoder_config.channel_count;
- audio_bytes_per_frame_ = decoder_config.bytes_per_frame();
scoped_refptr<PPB_Buffer_Impl> extra_data_resource;
if (!MakeBufferResource(pp_instance_,
@@ -553,7 +562,7 @@ bool ContentDecryptorDelegate::DecryptAndDecodeVideo(
const uint32_t request_id = next_decryption_request_id_++;
DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id;
TRACE_EVENT_ASYNC_BEGIN0(
- "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
+ "media", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
PP_EncryptedBlockInfo block_info = {};
if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
@@ -580,38 +589,28 @@ bool ContentDecryptorDelegate::DecryptAndDecodeVideo(
return true;
}
-void ContentDecryptorDelegate::NeedKey(PP_Var key_system_var,
- PP_Var session_id_var,
- PP_Var init_data_var) {
- // TODO(ddorwin): Remove from PPB_ContentDecryptor_Private.
- NOTREACHED();
-}
-
-void ContentDecryptorDelegate::KeyAdded(PP_Var key_system_var,
- PP_Var session_id_var) {
- if (key_added_cb_.is_null())
+void ContentDecryptorDelegate::OnSessionCreated(uint32 session_id,
+ PP_Var web_session_id_var) {
+ if (session_created_cb_.is_null())
return;
- StringVar* session_id_string = StringVar::FromPPVar(session_id_var);
+ StringVar* session_id_string = StringVar::FromPPVar(web_session_id_var);
+
if (!session_id_string) {
- key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0);
+ OnSessionError(session_id, media::MediaKeys::kUnknownError, 0);
return;
}
- key_added_cb_.Run(session_id_string->value());
+ session_created_cb_.Run(session_id, session_id_string->value());
}
-void ContentDecryptorDelegate::KeyMessage(PP_Var key_system_var,
- PP_Var session_id_var,
- PP_Var message_var,
- PP_Var default_url_var) {
- if (key_message_cb_.is_null())
+void ContentDecryptorDelegate::OnSessionMessage(uint32 session_id,
+ PP_Var message_var,
+ PP_Var default_url_var) {
+ if (session_message_cb_.is_null())
return;
- StringVar* session_id_string = StringVar::FromPPVar(session_id_var);
-
- ArrayBufferVar* message_array_buffer =
- ArrayBufferVar::FromPPVar(message_var);
+ ArrayBufferVar* message_array_buffer = ArrayBufferVar::FromPPVar(message_var);
std::vector<uint8> message;
if (message_array_buffer) {
@@ -621,32 +620,37 @@ void ContentDecryptorDelegate::KeyMessage(PP_Var key_system_var,
StringVar* default_url_string = StringVar::FromPPVar(default_url_var);
- if (!session_id_string || !default_url_string) {
- key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0);
+ if (!default_url_string) {
+ OnSessionError(session_id, media::MediaKeys::kUnknownError, 0);
return;
}
- key_message_cb_.Run(session_id_string->value(),
- message,
- default_url_string->value());
+ session_message_cb_.Run(session_id, message, default_url_string->value());
}
-void ContentDecryptorDelegate::KeyError(PP_Var key_system_var,
- PP_Var session_id_var,
- int32_t media_error,
- int32_t system_code) {
- if (key_error_cb_.is_null())
+void ContentDecryptorDelegate::OnSessionReady(uint32 session_id) {
+ if (session_ready_cb_.is_null())
return;
- StringVar* session_id_string = StringVar::FromPPVar(session_id_var);
- if (!session_id_string) {
- key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0);
+ session_ready_cb_.Run(session_id);
+}
+
+void ContentDecryptorDelegate::OnSessionClosed(uint32 session_id) {
+ if (session_closed_cb_.is_null())
+ return;
+
+ session_closed_cb_.Run(session_id);
+}
+
+void ContentDecryptorDelegate::OnSessionError(uint32 session_id,
+ int32_t media_error,
+ int32_t system_code) {
+ if (session_error_cb_.is_null())
return;
- }
- key_error_cb_.Run(session_id_string->value(),
- static_cast<media::MediaKeys::KeyError>(media_error),
- system_code);
+ session_error_cb_.Run(session_id,
+ static_cast<media::MediaKeys::KeyError>(media_error),
+ system_code);
}
void ContentDecryptorDelegate::DecoderInitializeDone(
@@ -799,7 +803,7 @@ void ContentDecryptorDelegate::DeliverFrame(
}
TRACE_EVENT_ASYNC_END0(
- "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
+ "media", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
DCHECK(!pending_video_decode_cb_.is_null());
pending_video_decode_request_id_ = 0;
@@ -852,12 +856,12 @@ void ContentDecryptorDelegate::DeliverFrame(
void ContentDecryptorDelegate::DeliverSamples(
PP_Resource audio_frames,
- const PP_DecryptedBlockInfo* block_info) {
- DCHECK(block_info);
+ const PP_DecryptedSampleInfo* sample_info) {
+ DCHECK(sample_info);
- FreeBuffer(block_info->tracking_info.buffer_id);
+ FreeBuffer(sample_info->tracking_info.buffer_id);
- const uint32_t request_id = block_info->tracking_info.request_id;
+ const uint32_t request_id = sample_info->tracking_info.request_id;
DVLOG(2) << "DeliverSamples() - request_id: " << request_id;
// If the request ID is not valid or does not match what's saved, do nothing.
@@ -874,15 +878,19 @@ void ContentDecryptorDelegate::DeliverSamples(
const media::Decryptor::AudioBuffers empty_frames;
media::Decryptor::Status status =
- PpDecryptResultToMediaDecryptorStatus(block_info->result);
+ PpDecryptResultToMediaDecryptorStatus(sample_info->result);
if (status != media::Decryptor::kSuccess) {
audio_decode_cb.Run(status, empty_frames);
return;
}
+ media::SampleFormat sample_format =
+ PpDecryptedSampleFormatToMediaSampleFormat(sample_info->format);
+
media::Decryptor::AudioBuffers audio_frame_list;
if (!DeserializeAudioFrames(audio_frames,
- block_info->data_size,
+ sample_info->data_size,
+ sample_format,
&audio_frame_list)) {
NOTREACHED() << "CDM did not serialize the buffer correctly.";
audio_decode_cb.Run(media::Decryptor::kError, empty_frames);
@@ -925,7 +933,7 @@ bool ContentDecryptorDelegate::MakeMediaBufferResource(
media::Decryptor::StreamType stream_type,
const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
scoped_refptr<PPB_Buffer_Impl>* resource) {
- TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource");
+ TRACE_EVENT0("media", "ContentDecryptorDelegate::MakeMediaBufferResource");
// End of stream buffers are represented as null resources.
if (encrypted_buffer->end_of_stream()) {
@@ -995,6 +1003,7 @@ void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo(
bool ContentDecryptorDelegate::DeserializeAudioFrames(
PP_Resource audio_frames,
size_t data_size,
+ media::SampleFormat sample_format,
media::Decryptor::AudioBuffers* frames) {
DCHECK(frames);
EnterResourceNoLock<PPB_Buffer_API> enter(audio_frames, true);
@@ -1012,6 +1021,13 @@ bool ContentDecryptorDelegate::DeserializeAudioFrames(
const uint8* cur = static_cast<uint8*>(mapper.data());
size_t bytes_left = data_size;
+ const int audio_bytes_per_frame =
+ media::SampleFormatToBytesPerChannel(sample_format) *
+ audio_channel_count_;
+
+ // Allocate space for the channel pointers given to AudioBuffer.
+ std::vector<const uint8*> channel_ptrs(
+ audio_channel_count_, static_cast<const uint8*>(NULL));
do {
int64 timestamp = 0;
int64 frame_size = -1;
@@ -1034,13 +1050,18 @@ bool ContentDecryptorDelegate::DeserializeAudioFrames(
return false;
}
- const uint8* data[] = {cur};
- int frame_count = frame_size / audio_bytes_per_frame_;
+ // Setup channel pointers. AudioBuffer::CopyFrom() will only use the first
+ // one in the case of interleaved data.
+ const int size_per_channel = frame_size / audio_channel_count_;
+ for (int i = 0; i < audio_channel_count_; ++i)
+ channel_ptrs[i] = cur + i * size_per_channel;
+
+ const int frame_count = frame_size / audio_bytes_per_frame;
scoped_refptr<media::AudioBuffer> frame = media::AudioBuffer::CopyFrom(
- audio_sample_format_,
+ sample_format,
audio_channel_count_,
frame_count,
- data,
+ &channel_ptrs[0],
base::TimeDelta::FromMicroseconds(timestamp),
base::TimeDelta::FromMicroseconds(audio_samples_per_second_ /
frame_count));
diff --git a/chromium/content/renderer/pepper/content_decryptor_delegate.h b/chromium/content/renderer/pepper/content_decryptor_delegate.h
index f58ef9f6073..352817dd011 100644
--- a/chromium/content/renderer/pepper/content_decryptor_delegate.h
+++ b/chromium/content/renderer/pepper/content_decryptor_delegate.h
@@ -39,23 +39,24 @@ class ContentDecryptorDelegate {
const PPP_ContentDecryptor_Private* plugin_decryption_interface);
~ContentDecryptorDelegate();
- void Initialize(const std::string& key_system,
- const bool can_challenge_platform);
+ void Initialize(const std::string& key_system);
- void SetKeyEventCallbacks(const media::KeyAddedCB& key_added_cb,
- const media::KeyErrorCB& key_error_cb,
- const media::KeyMessageCB& key_message_cb);
+ void SetSessionEventCallbacks(
+ const media::SessionCreatedCB& session_created_cb,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb);
// Provides access to PPP_ContentDecryptor_Private.
- bool GenerateKeyRequest(const std::string& type,
- const uint8* init_data,
- int init_data_length);
- bool AddKey(const std::string& session_id,
- const uint8* key,
- int key_length,
- const uint8* init_data,
- int init_data_length);
- bool CancelKeyRequest(const std::string& session_id);
+ bool CreateSession(uint32 session_id,
+ const std::string& type,
+ const uint8* init_data,
+ int init_data_length);
+ bool UpdateSession(uint32 session_id,
+ const uint8* response,
+ int response_length);
+ bool ReleaseSession(uint32 session_id);
bool Decrypt(media::Decryptor::StreamType stream_type,
const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
const media::Decryptor::DecryptCB& decrypt_cb);
@@ -79,18 +80,15 @@ class ContentDecryptorDelegate {
const media::Decryptor::VideoDecodeCB& video_decode_cb);
// PPB_ContentDecryptor_Private dispatching methods.
- // TODO(ddorwin): Remove this method.
- void NeedKey(PP_Var key_system, PP_Var session_id, PP_Var init_data);
- // TODO(ddorwin): Remove key_system_var parameter from these methods.
- void KeyAdded(PP_Var key_system, PP_Var session_id);
- void KeyMessage(PP_Var key_system,
- PP_Var session_id,
- PP_Var message,
- PP_Var default_url);
- void KeyError(PP_Var key_system,
- PP_Var session_id,
- int32_t media_error,
- int32_t system_code);
+ void OnSessionCreated(uint32 session_id, PP_Var web_session_id_var);
+ void OnSessionMessage(uint32 session_id,
+ PP_Var message,
+ PP_Var destination_url);
+ void OnSessionReady(uint32 session_id);
+ void OnSessionClosed(uint32 session_id);
+ void OnSessionError(uint32 session_id,
+ int32_t media_error,
+ int32_t system_code);
void DeliverBlock(PP_Resource decrypted_block,
const PP_DecryptedBlockInfo* block_info);
void DecoderInitializeDone(PP_DecryptorStreamType decoder_type,
@@ -103,7 +101,7 @@ class ContentDecryptorDelegate {
void DeliverFrame(PP_Resource decrypted_frame,
const PP_DecryptedFrameInfo* frame_info);
void DeliverSamples(PP_Resource audio_frames,
- const PP_DecryptedBlockInfo* block_info);
+ const PP_DecryptedSampleInfo* sample_info);
private:
// Cancels the pending decrypt-and-decode callback for |stream_type|.
@@ -132,6 +130,7 @@ class ContentDecryptorDelegate {
// buffers in |frames|. Returns true upon success.
bool DeserializeAudioFrames(PP_Resource audio_frames,
size_t data_size,
+ media::SampleFormat sample_format,
media::Decryptor::AudioBuffers* frames);
const PP_Instance pp_instance_;
@@ -140,10 +139,12 @@ class ContentDecryptorDelegate {
// TODO(ddorwin): Remove after updating the Pepper API to not use key system.
std::string key_system_;
- // Callbacks for firing key events.
- media::KeyAddedCB key_added_cb_;
- media::KeyErrorCB key_error_cb_;
- media::KeyMessageCB key_message_cb_;
+ // Callbacks for firing session events.
+ media::SessionCreatedCB session_created_cb_;
+ media::SessionMessageCB session_message_cb_;
+ media::SessionReadyCB session_ready_cb_;
+ media::SessionClosedCB session_closed_cb_;
+ media::SessionErrorCB session_error_cb_;
gfx::Size natural_size_;
@@ -177,14 +178,12 @@ class ContentDecryptorDelegate {
std::queue<uint32_t> free_buffers_;
- base::WeakPtrFactory<ContentDecryptorDelegate> weak_ptr_factory_;
- base::WeakPtr<ContentDecryptorDelegate> weak_this_;
-
// Keep track of audio parameters.
- media::SampleFormat audio_sample_format_;
int audio_samples_per_second_;
int audio_channel_count_;
- int audio_bytes_per_frame_;
+
+ base::WeakPtr<ContentDecryptorDelegate> weak_this_;
+ base::WeakPtrFactory<ContentDecryptorDelegate> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ContentDecryptorDelegate);
};
diff --git a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
index 0b59503a37c..0bd3fdf8729 100644
--- a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
+++ b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
@@ -10,7 +10,6 @@
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/pepper/pepper_audio_input_host.h"
#include "content/renderer/pepper/pepper_file_chooser_host.h"
-#include "content/renderer/pepper/pepper_file_io_host.h"
#include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
#include "content/renderer/pepper/pepper_file_system_host.h"
#include "content/renderer/pepper/pepper_graphics_2d_host.h"
@@ -20,11 +19,13 @@
#include "content/renderer/pepper/pepper_video_destination_host.h"
#include "content/renderer/pepper/pepper_video_source_host.h"
#include "content/renderer/pepper/pepper_websocket_host.h"
+#include "content/renderer/pepper/ppb_image_data_impl.h"
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/ppapi_message_utils.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/shared_impl/ppb_image_data_shared.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
@@ -35,11 +36,14 @@ using ppapi::proxy::SerializedTrueTypeFontDesc;
using ppapi::UnpackMessage;
namespace content {
+
+#if defined(ENABLE_WEBRTC)
namespace {
+#if defined(ENABLE_WEBRTC)
bool CanUseMediaStreamAPI(const RendererPpapiHost* host,
PP_Instance instance) {
- WebKit::WebPluginContainer* container =
+ blink::WebPluginContainer* container =
host->GetContainerForInstance(instance);
if (!container)
return false;
@@ -49,8 +53,10 @@ bool CanUseMediaStreamAPI(const RendererPpapiHost* host,
GetContentClient()->renderer();
return content_renderer_client->AllowPepperMediaStreamAPI(document_url);
}
+#endif // defined(ENABLE_WEBRTC)
-}
+} // namespace
+#endif // defined(ENABLE_WEBRTC)
ContentRendererPepperHostFactory::ContentRendererPepperHostFactory(
RendererPpapiHostImpl* host)
@@ -73,9 +79,6 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
// Public interfaces.
switch (message.type()) {
- case PpapiHostMsg_FileIO_Create::ID:
- return scoped_ptr<ResourceHost>(new PepperFileIOHost(
- host_, instance, params.pp_resource()));
case PpapiHostMsg_FileRef_CreateInternal::ID: {
PP_Resource file_system;
std::string internal_path;
@@ -106,9 +109,11 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
NOTREACHED();
return scoped_ptr<ResourceHost>();
}
+ scoped_refptr<PPB_ImageData_Impl> image_data(new PPB_ImageData_Impl(
+ instance, ppapi::PPB_ImageData_Shared::PLATFORM));
return scoped_ptr<ResourceHost>(
PepperGraphics2DHost::Create(host_, instance, params.pp_resource(),
- size, is_always_opaque));
+ size, is_always_opaque, image_data));
}
case PpapiHostMsg_URLLoader_Create::ID:
return scoped_ptr<ResourceHost>(new PepperURLLoaderHost(
diff --git a/chromium/content/renderer/pepper/event_conversion.cc b/chromium/content/renderer/pepper/event_conversion.cc
index 0df48952943..b7c06016f77 100644
--- a/chromium/content/renderer/pepper/event_conversion.cc
+++ b/chromium/content/renderer/pepper/event_conversion.cc
@@ -26,14 +26,14 @@
using ppapi::EventTimeToPPTimeTicks;
using ppapi::InputEventData;
using ppapi::PPTimeTicksToEventTime;
-using WebKit::WebInputEvent;
-using WebKit::WebKeyboardEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebString;
-using WebKit::WebTouchEvent;
-using WebKit::WebTouchPoint;
-using WebKit::WebUChar;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebString;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+using blink::WebUChar;
namespace content {
diff --git a/chromium/content/renderer/pepper/event_conversion.h b/chromium/content/renderer/pepper/event_conversion.h
index edaa7309912..81aa6b3acf7 100644
--- a/chromium/content/renderer/pepper/event_conversion.h
+++ b/chromium/content/renderer/pepper/event_conversion.h
@@ -17,7 +17,7 @@ namespace ppapi {
struct InputEventData;
}
-namespace WebKit {
+namespace blink {
class WebGamepads;
class WebInputEvent;
}
@@ -27,24 +27,24 @@ namespace content {
// Converts the given WebKit event to one or possibly multiple PP_InputEvents.
// The generated events will be filled into the given vector. On failure, no
// events will ge generated and the vector will be empty.
-void CreateInputEventData(const WebKit::WebInputEvent& event,
+void CreateInputEventData(const blink::WebInputEvent& event,
std::vector<ppapi::InputEventData >* pp_events);
// Creates a WebInputEvent from the given PP_InputEvent. If it fails, returns
// NULL. The caller owns the created object on success.
-WebKit::WebInputEvent* CreateWebInputEvent(const ppapi::InputEventData& event);
+blink::WebInputEvent* CreateWebInputEvent(const ppapi::InputEventData& event);
// Creates an array of WebInputEvents to make the given event look like a user
// input event on all platforms. |plugin_x| and |plugin_y| should be the
// coordinates of a point within the plugin's area on the page.
-std::vector<linked_ptr<WebKit::WebInputEvent> > CreateSimulatedWebInputEvents(
+std::vector<linked_ptr<blink::WebInputEvent> > CreateSimulatedWebInputEvents(
const ppapi::InputEventData& event,
int plugin_x,
int plugin_y);
// Returns the PPAPI event class for the given WebKit event type. The given
// type should not be "Undefined" since there's no corresponding PPAPI class.
-PP_InputEvent_Class ClassifyInputEvent(WebKit::WebInputEvent::Type type);
+PP_InputEvent_Class ClassifyInputEvent(blink::WebInputEvent::Type type);
} // namespace content
diff --git a/chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc
new file mode 100644
index 00000000000..af0ba49c0ee
--- /dev/null
+++ b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/pepper/fake_pepper_plugin_instance.h"
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
+
+namespace content {
+
+FakePepperPluginInstance::~FakePepperPluginInstance() {}
+
+content::RenderView* FakePepperPluginInstance::GetRenderView() {
+ return NULL;
+}
+
+blink::WebPluginContainer* FakePepperPluginInstance::GetContainer() {
+ return NULL;
+}
+
+v8::Isolate* FakePepperPluginInstance::GetIsolate() const {
+ return NULL;
+}
+
+ppapi::VarTracker* FakePepperPluginInstance::GetVarTracker() {
+ return NULL;
+}
+
+const GURL& FakePepperPluginInstance::GetPluginURL() {
+ return gurl_;
+}
+
+base::FilePath FakePepperPluginInstance::GetModulePath() {
+ return base::FilePath();
+}
+
+PP_Resource FakePepperPluginInstance::CreateImage(gfx::ImageSkia* source_image,
+ float scale) {
+ return 0;
+}
+
+PP_ExternalPluginResult FakePepperPluginInstance::SwitchToOutOfProcessProxy(
+ const base::FilePath& file_path,
+ ppapi::PpapiPermissions permissions,
+ const IPC::ChannelHandle& channel_handle,
+ base::ProcessId plugin_pid,
+ int plugin_child_id) {
+ return PP_EXTERNAL_PLUGIN_FAILED;
+}
+
+void FakePepperPluginInstance::SetAlwaysOnTop(bool on_top) {}
+
+bool FakePepperPluginInstance::IsFullPagePlugin() {
+ return false;
+}
+
+bool FakePepperPluginInstance::FlashSetFullscreen(bool fullscreen,
+ bool delay_report) {
+ return false;
+}
+
+bool FakePepperPluginInstance::IsRectTopmost(const gfx::Rect& rect) {
+ return false;
+}
+
+int32_t FakePepperPluginInstance::Navigate(
+ const ppapi::URLRequestInfoData& request,
+ const char* target,
+ bool from_user_action) {
+ return PP_ERROR_FAILED;
+}
+
+int FakePepperPluginInstance::MakePendingFileRefRendererHost(
+ const base::FilePath& path) {
+ return 0;
+}
+
+void FakePepperPluginInstance::SetEmbedProperty(PP_Var key, PP_Var value) {}
+
+} // namespace content
diff --git a/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h
new file mode 100644
index 00000000000..f492b33facb
--- /dev/null
+++ b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h
@@ -0,0 +1,49 @@
+// 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_RENDERER_PEPPER_FAKE_PEPPER_PLUGIN_INSTANCE_H_
+#define CONTENT_RENDERER_PEPPER_FAKE_PEPPER_PLUGIN_INSTANCE_H_
+
+#include "content/public/renderer/pepper_plugin_instance.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class FakePepperPluginInstance : public PepperPluginInstance {
+ public:
+ virtual ~FakePepperPluginInstance();
+
+ // PepperPluginInstance overrides.
+ virtual content::RenderView* GetRenderView() OVERRIDE;
+ virtual blink::WebPluginContainer* GetContainer() OVERRIDE;
+ virtual v8::Isolate* GetIsolate() const OVERRIDE;
+ virtual ppapi::VarTracker* GetVarTracker() OVERRIDE;
+ virtual const GURL& GetPluginURL() OVERRIDE;
+ virtual base::FilePath GetModulePath() OVERRIDE;
+ virtual PP_Resource CreateImage(gfx::ImageSkia* source_image,
+ float scale) OVERRIDE;
+ virtual PP_ExternalPluginResult SwitchToOutOfProcessProxy(
+ const base::FilePath& file_path,
+ ppapi::PpapiPermissions permissions,
+ const IPC::ChannelHandle& channel_handle,
+ base::ProcessId plugin_pid,
+ int plugin_child_id) OVERRIDE;
+ virtual void SetAlwaysOnTop(bool on_top) OVERRIDE;
+ virtual bool IsFullPagePlugin() OVERRIDE;
+ virtual bool FlashSetFullscreen(bool fullscreen, bool delay_report) OVERRIDE;
+ virtual bool IsRectTopmost(const gfx::Rect& rect) OVERRIDE;
+ virtual int32_t Navigate(const ppapi::URLRequestInfoData& request,
+ const char* target,
+ bool from_user_action) OVERRIDE;
+ virtual int MakePendingFileRefRendererHost(
+ const base::FilePath& path) OVERRIDE;
+ virtual void SetEmbedProperty(PP_Var key, PP_Var value) OVERRIDE;
+
+ private:
+ GURL gurl_;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_PEPPER_FAKE_PEPPER_PLUGIN_INSTANCE_H_
diff --git a/chromium/content/renderer/pepper/fullscreen_container.h b/chromium/content/renderer/pepper/fullscreen_container.h
index 81ee53d8554..d91cc668f49 100644
--- a/chromium/content/renderer/pepper/fullscreen_container.h
+++ b/chromium/content/renderer/pepper/fullscreen_container.h
@@ -5,11 +5,11 @@
#ifndef CONTENT_RENDERER_PEPPER_PPB_FULLSCREEN_CONTAINER_IMPL_H_
#define CONTENT_RENDERER_PEPPER_PPB_FULLSCREEN_CONTAINER_IMPL_H_
-namespace WebKit {
+namespace blink {
class WebLayer;
struct WebCursorInfo;
struct WebRect;
-} // namespace WebKit
+} // namespace blink
namespace content {
@@ -21,19 +21,19 @@ class FullscreenContainer {
virtual void Invalidate() = 0;
// Invalidates a partial region of the plugin.
- virtual void InvalidateRect(const WebKit::WebRect&) = 0;
+ virtual void InvalidateRect(const blink::WebRect&) = 0;
// Scrolls a partial region of the plugin in the given direction.
- virtual void ScrollRect(int dx, int dy, const WebKit::WebRect&) = 0;
+ virtual void ScrollRect(int dx, int dy, const blink::WebRect&) = 0;
// Destroys the fullscreen window. This also destroys the FullscreenContainer
// instance.
virtual void Destroy() = 0;
// Notifies the container that the mouse cursor has changed.
- virtual void DidChangeCursor(const WebKit::WebCursorInfo& cursor) = 0;
+ virtual void DidChangeCursor(const blink::WebCursorInfo& cursor) = 0;
- virtual void SetLayer(WebKit::WebLayer* layer) = 0;
+ virtual void SetLayer(blink::WebLayer* layer) = 0;
protected:
virtual ~FullscreenContainer() {}
diff --git a/chromium/content/renderer/pepper/host_array_buffer_var.cc b/chromium/content/renderer/pepper/host_array_buffer_var.cc
index b6b719dab56..d8d4cec8bf9 100644
--- a/chromium/content/renderer/pepper/host_array_buffer_var.cc
+++ b/chromium/content/renderer/pepper/host_array_buffer_var.cc
@@ -18,7 +18,7 @@
#include "ppapi/c/pp_instance.h"
using ppapi::ArrayBufferVar;
-using WebKit::WebArrayBuffer;
+using blink::WebArrayBuffer;
namespace content {
diff --git a/chromium/content/renderer/pepper/host_array_buffer_var.h b/chromium/content/renderer/pepper/host_array_buffer_var.h
index 9ba1d7c6c56..13bd80630de 100644
--- a/chromium/content/renderer/pepper/host_array_buffer_var.h
+++ b/chromium/content/renderer/pepper/host_array_buffer_var.h
@@ -17,7 +17,7 @@ namespace content {
class HostArrayBufferVar : public ppapi::ArrayBufferVar {
public:
explicit HostArrayBufferVar(uint32 size_in_bytes);
- explicit HostArrayBufferVar(const WebKit::WebArrayBuffer& buffer);
+ explicit HostArrayBufferVar(const blink::WebArrayBuffer& buffer);
explicit HostArrayBufferVar(uint32 size_in_bytes,
base::SharedMemoryHandle handle);
@@ -30,12 +30,12 @@ class HostArrayBufferVar : public ppapi::ArrayBufferVar {
int* host_shm_handle_id,
base::SharedMemoryHandle* plugin_shm_handle) OVERRIDE;
- WebKit::WebArrayBuffer& webkit_buffer() { return buffer_; }
+ blink::WebArrayBuffer& webkit_buffer() { return buffer_; }
private:
virtual ~HostArrayBufferVar();
- WebKit::WebArrayBuffer buffer_;
+ blink::WebArrayBuffer buffer_;
// Tracks whether the data in the buffer is valid.
bool valid_;
diff --git a/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc b/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc
index 68ae4ebc090..8707d94b1a8 100644
--- a/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc
+++ b/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc
@@ -12,9 +12,6 @@
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
#include "content/renderer/pepper/renderer_restrict_dispatch_group.h"
#include "content/renderer/render_view_impl.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebElement.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
namespace content {
@@ -87,7 +84,7 @@ void HostDispatcherWrapper::AddInstance(PP_Instance instance) {
PepperRendererInstanceData(
0, // The render process id will be supplied in the browser.
render_view->GetRoutingID(),
- plugin_instance->GetContainer()->element().document().url(),
+ host->GetDocumentURL(instance),
plugin_instance->GetPluginURL()),
is_external_));
}
diff --git a/chromium/content/renderer/pepper/host_globals.cc b/chromium/content/renderer/pepper/host_globals.cc
index e35ea320791..31c5f0bd410 100644
--- a/chromium/content/renderer/pepper/host_globals.cc
+++ b/chromium/content/renderer/pepper/host_globals.cc
@@ -29,14 +29,14 @@ using ppapi::CheckIdType;
using ppapi::MakeTypedId;
using ppapi::PPIdType;
using ppapi::ResourceTracker;
-using WebKit::WebConsoleMessage;
-using WebKit::WebString;
+using blink::WebConsoleMessage;
+using blink::WebString;
namespace content {
namespace {
-typedef std::set<WebKit::WebPluginContainer*> ContainerSet;
+typedef std::set<blink::WebPluginContainer*> ContainerSet;
// Adds all WebPluginContainers associated with the given module to the set.
void GetAllContainersForModule(PluginModule* module,
@@ -177,7 +177,7 @@ void HostGlobals::BroadcastLogWithSource(PP_Module pp_module,
(*i)->element().document().frame()->addMessageToConsole(message);
}
-base::TaskRunner* HostGlobals::GetFileTaskRunner(PP_Instance instance) {
+base::TaskRunner* HostGlobals::GetFileTaskRunner() {
return RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get();
}
diff --git a/chromium/content/renderer/pepper/host_globals.h b/chromium/content/renderer/pepper/host_globals.h
index 761fa915743..9d1b289d506 100644
--- a/chromium/content/renderer/pepper/host_globals.h
+++ b/chromium/content/renderer/pepper/host_globals.h
@@ -51,7 +51,7 @@ class HostGlobals : public ppapi::PpapiGlobals {
const std::string& source,
const std::string& value) OVERRIDE;
virtual ppapi::MessageLoopShared* GetCurrentMessageLoop() OVERRIDE;
- virtual base::TaskRunner* GetFileTaskRunner(PP_Instance instance) OVERRIDE;
+ virtual base::TaskRunner* GetFileTaskRunner() OVERRIDE;
HostVarTracker* host_var_tracker() {
return &host_var_tracker_;
diff --git a/chromium/content/renderer/pepper/host_resource_var.cc b/chromium/content/renderer/pepper/host_resource_var.cc
index a59bed37f6f..810a949965e 100644
--- a/chromium/content/renderer/pepper/host_resource_var.cc
+++ b/chromium/content/renderer/pepper/host_resource_var.cc
@@ -9,16 +9,29 @@ namespace content {
HostResourceVar::HostResourceVar() : pp_resource_(0) {}
HostResourceVar::HostResourceVar(PP_Resource pp_resource)
- : pp_resource_(pp_resource) {}
+ : pp_resource_(pp_resource),
+ pending_renderer_host_id_(0),
+ pending_browser_host_id_(0) {}
-HostResourceVar::HostResourceVar(const IPC::Message& creation_message)
+HostResourceVar::HostResourceVar(int pending_renderer_host_id,
+ const IPC::Message& creation_message)
: pp_resource_(0),
+ pending_renderer_host_id_(pending_renderer_host_id),
+ pending_browser_host_id_(0),
creation_message_(new IPC::Message(creation_message)) {}
PP_Resource HostResourceVar::GetPPResource() const {
return pp_resource_;
}
+int HostResourceVar::GetPendingRendererHostId() const {
+ return pending_renderer_host_id_;
+}
+
+int HostResourceVar::GetPendingBrowserHostId() const {
+ return pending_browser_host_id_;
+}
+
const IPC::Message* HostResourceVar::GetCreationMessage() const {
return creation_message_.get();
}
diff --git a/chromium/content/renderer/pepper/host_resource_var.h b/chromium/content/renderer/pepper/host_resource_var.h
index 79fe487041d..cc6b0577f4d 100644
--- a/chromium/content/renderer/pepper/host_resource_var.h
+++ b/chromium/content/renderer/pepper/host_resource_var.h
@@ -24,23 +24,38 @@ class HostResourceVar : public ppapi::ResourceVar {
explicit HostResourceVar(PP_Resource pp_resource);
// Makes a resource var with a pending resource host.
- // The |creation_message| contains data needed to create the plugin-side
- // resource. Its type depends on the type of resource.
- explicit HostResourceVar(const IPC::Message& creation_message);
+ // The |pending_renderer_host_id| is a pending resource host ID in the
+ // renderer to attach from the plugin. Depending on the type of resource, this
+ // may be 0. The |creation_message| contains additional data needed to create
+ // the plugin-side resource. Its type depends on the type of resource.
+ HostResourceVar(int pending_renderer_host_id,
+ const IPC::Message& creation_message);
// ResourceVar override.
virtual PP_Resource GetPPResource() const OVERRIDE;
+ virtual int GetPendingRendererHostId() const OVERRIDE;
+ virtual int GetPendingBrowserHostId() const OVERRIDE;
virtual const IPC::Message* GetCreationMessage() const OVERRIDE;
virtual bool IsPending() const OVERRIDE;
+ void set_pending_browser_host_id(int id) {
+ pending_browser_host_id_ = id;
+ }
+
protected:
virtual ~HostResourceVar();
private:
// Real resource ID in the plugin. 0 if one has not yet been created
- // (indicating that there is a pending host resource).
+ // (indicating that there is a pending resource host).
PP_Resource pp_resource_;
+ // Pending resource host ID in the renderer.
+ int pending_renderer_host_id_;
+
+ // Pending resource host ID in the browser.
+ int pending_browser_host_id_;
+
// If the plugin-side resource has not yet been created, carries a message to
// create a resource of the specific type on the plugin side. Otherwise, NULL.
scoped_ptr<IPC::Message> creation_message_;
diff --git a/chromium/content/renderer/pepper/host_var_tracker.cc b/chromium/content/renderer/pepper/host_var_tracker.cc
index ed67dbaa616..27f2977b08e 100644
--- a/chromium/content/renderer/pepper/host_var_tracker.cc
+++ b/chromium/content/renderer/pepper/host_var_tracker.cc
@@ -103,6 +103,17 @@ int HostVarTracker::GetLiveNPObjectVarsForInstance(PP_Instance instance) const {
return static_cast<int>(found->second->size());
}
+PP_Var HostVarTracker::MakeResourcePPVarFromMessage(
+ PP_Instance instance,
+ const IPC::Message& creation_message,
+ int pending_renderer_id,
+ int pending_browser_id) {
+ // On the host side, the creation message is ignored when creating a resource.
+ // Therefore, a call to this function indicates a null resource. Return the
+ // resource 0.
+ return MakeResourcePPVar(0);
+}
+
ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) {
return new HostResourceVar(pp_resource);
}
diff --git a/chromium/content/renderer/pepper/host_var_tracker.h b/chromium/content/renderer/pepper/host_var_tracker.h
index 858c3015e3d..5ab4df458ba 100644
--- a/chromium/content/renderer/pepper/host_var_tracker.h
+++ b/chromium/content/renderer/pepper/host_var_tracker.h
@@ -55,6 +55,11 @@ class HostVarTracker : public ppapi::VarTracker {
PP_Instance instance) const;
// VarTracker public implementation.
+ virtual PP_Var MakeResourcePPVarFromMessage(
+ PP_Instance instance,
+ const IPC::Message& creation_message,
+ int pending_renderer_id,
+ int pending_browser_id) OVERRIDE;
virtual ppapi::ResourceVar* MakeResourceVar(PP_Resource pp_resource) OVERRIDE;
virtual void DidDeleteInstance(PP_Instance instance) OVERRIDE;
diff --git a/chromium/content/renderer/pepper/host_var_tracker_unittest.cc b/chromium/content/renderer/pepper/host_var_tracker_unittest.cc
index 24932dbb8df..048680558d7 100644
--- a/chromium/content/renderer/pepper/host_var_tracker_unittest.cc
+++ b/chromium/content/renderer/pepper/host_var_tracker_unittest.cc
@@ -59,7 +59,7 @@ NPObject* NewTrackedNPObject() {
class ReleaseNPObject {
public:
void operator()(NPObject* o) const {
- WebKit::WebBindings::releaseObject(o);
+ blink::WebBindings::releaseObject(o);
}
};
diff --git a/chromium/content/renderer/pepper/message_channel.cc b/chromium/content/renderer/pepper/message_channel.cc
index c41be2f451a..7c5961cfbe2 100644
--- a/chromium/content/renderer/pepper/message_channel.cc
+++ b/chromium/content/renderer/pepper/message_channel.cc
@@ -32,12 +32,12 @@
using ppapi::ArrayBufferVar;
using ppapi::PpapiGlobals;
using ppapi::StringVar;
-using WebKit::WebBindings;
-using WebKit::WebElement;
-using WebKit::WebDOMEvent;
-using WebKit::WebDOMMessageEvent;
-using WebKit::WebPluginContainer;
-using WebKit::WebSerializedScriptValue;
+using blink::WebBindings;
+using blink::WebElement;
+using blink::WebDOMEvent;
+using blink::WebDOMMessageEvent;
+using blink::WebPluginContainer;
+using blink::WebSerializedScriptValue;
namespace content {
@@ -105,8 +105,9 @@ PP_Var CopyPPVar(const PP_Var& var) {
case PP_VARTYPE_ARRAY:
case PP_VARTYPE_DICTIONARY:
case PP_VARTYPE_RESOURCE:
- // These types are not supported by PostMessage in-process.
- NOTREACHED();
+ // These types are not supported by PostMessage in-process. In some rare
+ // cases with the NaCl plugin, they may be sent but they will be dropped
+ // anyway (see crbug.com/318837 for details).
return PP_MakeUndefined();
}
NOTREACHED();
@@ -189,6 +190,12 @@ bool MessageChannelHasProperty(NPObject* np_obj, NPIdentifier name) {
if (!np_obj)
return false;
+ MessageChannel* message_channel = ToMessageChannel(np_obj);
+ if (message_channel) {
+ if (message_channel->GetReadOnlyProperty(name, NULL))
+ return true;
+ }
+
// Invoke on the passthrough object, if we have one.
NPObject* passthrough = ToPassThroughObject(np_obj);
if (passthrough)
@@ -205,6 +212,12 @@ bool MessageChannelGetProperty(NPObject* np_obj, NPIdentifier name,
if (IdentifierIsPostMessage(name))
return false;
+ MessageChannel* message_channel = ToMessageChannel(np_obj);
+ if (message_channel) {
+ if (message_channel->GetReadOnlyProperty(name, result))
+ return true;
+ }
+
// Invoke on the passthrough object, if we have one.
NPObject* passthrough = ToPassThroughObject(np_obj);
if (passthrough)
@@ -289,8 +302,8 @@ MessageChannel::MessageChannel(PepperPluginInstanceImpl* instance)
: instance_(instance),
passthrough_object_(NULL),
np_object_(NULL),
- weak_ptr_factory_(this),
- early_message_queue_state_(QUEUE_MESSAGES) {
+ early_message_queue_state_(QUEUE_MESSAGES),
+ weak_ptr_factory_(this) {
// Now create an NPObject for receiving calls to postMessage. This sets the
// reference count to 1. We release it in the destructor.
NPObject* obj = WebBindings::createObject(instance_->instanceNPP(),
@@ -344,7 +357,7 @@ void MessageChannel::NPVariantToPPVar(const NPVariant* variant) {
// shouldn't result in a deep copy.
v8::Handle<v8::Value> v8_value = WebBindings::toV8Value(variant);
V8VarConverter(instance_->pp_instance()).FromV8Value(
- v8_value, v8::Context::GetCurrent(),
+ v8_value, v8::Isolate::GetCurrent()->GetCurrentContext(),
base::Bind(&MessageChannel::NPVariantToPPVarComplete,
weak_ptr_factory_.GetWeakPtr(), result_iterator));
return;
@@ -546,4 +559,20 @@ void MessageChannel::SetPassthroughObject(NPObject* passthrough) {
passthrough_object_ = passthrough;
}
+bool MessageChannel::GetReadOnlyProperty(NPIdentifier key,
+ NPVariant *value) const {
+ std::map<NPIdentifier, ppapi::ScopedPPVar>::const_iterator it =
+ internal_properties_.find(key);
+ if (it != internal_properties_.end()) {
+ if (value)
+ return PPVarToNPVariant(it->second.get(), value);
+ return true;
+ }
+ return false;
+}
+
+void MessageChannel::SetReadOnlyProperty(PP_Var key, PP_Var value) {
+ internal_properties_[PPVarToNPIdentifier(key)] = ppapi::ScopedPPVar(value);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/pepper/message_channel.h b/chromium/content/renderer/pepper/message_channel.h
index e4e14233593..43aa0f95a62 100644
--- a/chromium/content/renderer/pepper/message_channel.h
+++ b/chromium/content/renderer/pepper/message_channel.h
@@ -7,6 +7,7 @@
#include <deque>
#include <list>
+#include <map>
#include "base/memory/weak_ptr.h"
#include "ppapi/shared_impl/resource.h"
@@ -81,6 +82,9 @@ class MessageChannel {
void QueueJavaScriptMessages();
void StopQueueingJavaScriptMessages();
+ bool GetReadOnlyProperty(NPIdentifier key, NPVariant* value) const;
+ void SetReadOnlyProperty(PP_Var key, PP_Var value);
+
private:
// Struct for storing the result of a NPVariant being converted to a PP_Var.
struct VarConversionResult {
@@ -119,20 +123,16 @@ class MessageChannel {
// Post a message to the onmessage handler for this channel's instance
// synchronously. This is used by PostMessageToJavaScript.
void PostMessageToJavaScriptImpl(
- const WebKit::WebSerializedScriptValue& message_data);
+ const blink::WebSerializedScriptValue& message_data);
// Post a message to the PPP_Instance HandleMessage function for this
// channel's instance. This is used by PostMessageToNative.
void PostMessageToNativeImpl(PP_Var message_data);
void DrainEarlyMessageQueue();
- // This is used to ensure pending tasks will not fire after this object is
- // destroyed.
- base::WeakPtrFactory<MessageChannel> weak_ptr_factory_;
-
// TODO(teravest): Remove all the tricky DRAIN_CANCELLED logic once
// PluginInstance::ResetAsProxied() is gone.
- std::deque<WebKit::WebSerializedScriptValue> early_message_queue_;
+ std::deque<blink::WebSerializedScriptValue> early_message_queue_;
enum EarlyMessageQueueState {
QUEUE_MESSAGES, // Queue JS messages.
SEND_DIRECTLY, // Post JS messages directly.
@@ -147,6 +147,12 @@ class MessageChannel {
// the order in which messages are processed is preserved.
std::list<VarConversionResult> converted_var_queue_;
+ std::map<NPIdentifier, ppapi::ScopedPPVar> internal_properties_;
+
+ // This is used to ensure pending tasks will not fire after this object is
+ // destroyed.
+ base::WeakPtrFactory<MessageChannel> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(MessageChannel);
};
diff --git a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc
index b0ee2a7aa66..2354f0bd385 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/renderer/pepper/fake_pepper_plugin_instance.h"
#include "ui/gfx/point.h"
namespace content {
@@ -14,7 +15,8 @@ MockRendererPpapiHost::MockRendererPpapiHost(RenderView* render_view,
ppapi_host_(&sink_, ppapi::PpapiPermissions()),
render_view_(render_view),
pp_instance_(instance),
- has_user_gesture_(false) {
+ has_user_gesture_(false),
+ plugin_instance_(new FakePepperPluginInstance) {
}
MockRendererPpapiHost::~MockRendererPpapiHost() {
@@ -30,7 +32,11 @@ bool MockRendererPpapiHost::IsValidInstance(PP_Instance instance) const {
PepperPluginInstance* MockRendererPpapiHost::GetPluginInstance(
PP_Instance instance) const {
- NOTIMPLEMENTED();
+ return plugin_instance_.get();
+}
+
+RenderFrame* MockRendererPpapiHost::GetRenderFrameForInstance(
+ PP_Instance instance) const {
return NULL;
}
@@ -41,7 +47,7 @@ RenderView* MockRendererPpapiHost::GetRenderViewForInstance(
return NULL;
}
-WebKit::WebPluginContainer* MockRendererPpapiHost::GetContainerForInstance(
+blink::WebPluginContainer* MockRendererPpapiHost::GetContainerForInstance(
PP_Instance instance) const {
NOTIMPLEMENTED();
return NULL;
@@ -60,7 +66,7 @@ int MockRendererPpapiHost::GetRoutingIDForWidget(PP_Instance instance) const {
return 0;
}
-gfx::Point MockRendererPpapiHost::PluginPointToRenderView(
+gfx::Point MockRendererPpapiHost::PluginPointToRenderFrame(
PP_Instance instance,
const gfx::Point& pt) const {
return gfx::Point();
@@ -74,7 +80,6 @@ IPC::PlatformFileForTransit MockRendererPpapiHost::ShareHandleWithRemote(
}
bool MockRendererPpapiHost::IsRunningInProcess() const {
- NOTIMPLEMENTED();
return false;
}
@@ -86,4 +91,9 @@ void MockRendererPpapiHost::CreateBrowserResourceHosts(
return;
}
+GURL MockRendererPpapiHost::GetDocumentURL(PP_Instance instance) const {
+ NOTIMPLEMENTED();
+ return GURL();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h
index 8f22d239ea3..c9d282ac99e 100644
--- a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h
+++ b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h
@@ -6,12 +6,14 @@
#define CONTENT_RENDERER_PEPPER_MOCK_RENDERER_PPAPI_HOST_H_
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "content/renderer/pepper/content_renderer_pepper_host_factory.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/resource_message_test_sink.h"
namespace content {
+class FakePepperPluginInstance;
class PluginModule;
// A mock RendererPpapiHost for testing resource hosts. Messages sent by
@@ -35,14 +37,16 @@ class MockRendererPpapiHost : public RendererPpapiHost {
virtual bool IsValidInstance(PP_Instance instance) const OVERRIDE;
virtual PepperPluginInstance* GetPluginInstance(
PP_Instance instance) const OVERRIDE;
+ virtual RenderFrame* GetRenderFrameForInstance(
+ PP_Instance instance) const OVERRIDE;
virtual RenderView* GetRenderViewForInstance(
PP_Instance instance) const OVERRIDE;
- virtual WebKit::WebPluginContainer* GetContainerForInstance(
+ virtual blink::WebPluginContainer* GetContainerForInstance(
PP_Instance instance) const OVERRIDE;
virtual base::ProcessId GetPluginPID() const OVERRIDE;
virtual bool HasUserGesture(PP_Instance instance) const OVERRIDE;
virtual int GetRoutingIDForWidget(PP_Instance instance) const OVERRIDE;
- virtual gfx::Point PluginPointToRenderView(
+ virtual gfx::Point PluginPointToRenderFrame(
PP_Instance instance,
const gfx::Point& pt) const OVERRIDE;
virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
@@ -54,6 +58,7 @@ class MockRendererPpapiHost : public RendererPpapiHost {
const std::vector<IPC::Message>& nested_msgs,
const base::Callback<void(
const std::vector<int>&)>& callback) const OVERRIDE;
+ virtual GURL GetDocumentURL(PP_Instance instance) const OVERRIDE;
private:
ppapi::proxy::ResourceMessageTestSink sink_;
@@ -64,6 +69,8 @@ class MockRendererPpapiHost : public RendererPpapiHost {
bool has_user_gesture_;
+ scoped_ptr<FakePepperPluginInstance> plugin_instance_;
+
DISALLOW_COPY_AND_ASSIGN(MockRendererPpapiHost);
};
diff --git a/chromium/content/renderer/pepper/npapi_glue.cc b/chromium/content/renderer/pepper/npapi_glue.cc
index 678a410019c..8489c4d3fbd 100644
--- a/chromium/content/renderer/pepper/npapi_glue.cc
+++ b/chromium/content/renderer/pepper/npapi_glue.cc
@@ -28,10 +28,10 @@ using ppapi::NPObjectVar;
using ppapi::PpapiGlobals;
using ppapi::StringVar;
using ppapi::Var;
-using WebKit::WebArrayBuffer;
-using WebKit::WebBindings;
-using WebKit::WebFrame;
-using WebKit::WebPluginContainer;
+using blink::WebArrayBuffer;
+using blink::WebBindings;
+using blink::WebFrame;
+using blink::WebPluginContainer;
namespace content {
diff --git a/chromium/content/renderer/pepper/npobject_var.cc b/chromium/content/renderer/pepper/npobject_var.cc
index 690dd229eeb..c45d0d2822a 100644
--- a/chromium/content/renderer/pepper/npobject_var.cc
+++ b/chromium/content/renderer/pepper/npobject_var.cc
@@ -10,7 +10,7 @@
#include "ppapi/c/pp_var.h"
#include "third_party/WebKit/public/web/WebBindings.h"
-using WebKit::WebBindings;
+using blink::WebBindings;
namespace ppapi {
diff --git a/chromium/content/renderer/pepper/pepper_audio_input_host.cc b/chromium/content/renderer/pepper/pepper_audio_input_host.cc
index 331bb49065f..19aa2b1b285 100644
--- a/chromium/content/renderer/pepper/pepper_audio_input_host.cc
+++ b/chromium/content/renderer/pepper/pepper_audio_input_host.cc
@@ -12,15 +12,11 @@
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
#include "content/renderer/render_view_impl.h"
#include "ipc/ipc_message.h"
-#include "media/audio/shared_memory_util.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/serialized_structs.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebElement.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
namespace content {
@@ -54,7 +50,8 @@ PepperAudioInputHost::PepperAudioInputHost(
this,
PepperMediaDeviceManager::GetForRenderView(
host->GetRenderViewForInstance(pp_instance())),
- PP_DEVICETYPE_DEV_AUDIOCAPTURE) {
+ PP_DEVICETYPE_DEV_AUDIOCAPTURE,
+ host->GetDocumentURL(instance)) {
}
PepperAudioInputHost::~PepperAudioInputHost() {
@@ -100,9 +97,8 @@ int32_t PepperAudioInputHost::OnOpen(
if (audio_input_)
return PP_ERROR_FAILED;
- PepperPluginInstanceImpl* instance =
- renderer_ppapi_host_->GetPluginInstanceImpl(pp_instance());
- if (!instance)
+ GURL document_url = renderer_ppapi_host_->GetDocumentURL(pp_instance());
+ if (!document_url.is_valid())
return PP_ERROR_FAILED;
// When it is done, we'll get called back on StreamCreated() or
@@ -112,7 +108,7 @@ int32_t PepperAudioInputHost::OnOpen(
audio_input_ = PepperPlatformAudioInput::Create(
render_view->AsWeakPtr(), device_id,
- instance->container()->element().document().url(),
+ document_url,
static_cast<int>(sample_rate),
static_cast<int>(sample_frame_count), this);
if (audio_input_) {
@@ -169,13 +165,7 @@ void PepperAudioInputHost::OnOpenComplete(
scoped_socket, scoped_shared_memory, &temp_socket, &temp_shmem);
serialized_socket_handle.set_socket(temp_socket);
- // Note that we must call TotalSharedMemorySizeInBytes() because extra space
- // in shared memory is allocated for book-keeping, so the actual size of the
- // shared memory buffer is larger than |shared_memory_size|. When sending to
- // NaCl, NaClIPCAdapter expects this size to match the size of the full
- // shared memory buffer.
- serialized_shared_memory_handle.set_shmem(
- temp_shmem, media::TotalSharedMemorySizeInBytes(shared_memory_size));
+ serialized_shared_memory_handle.set_shmem(temp_shmem, shared_memory_size);
}
// Send all the values, even on error. This simplifies some of our cleanup
diff --git a/chromium/content/renderer/pepper/pepper_browser_connection.cc b/chromium/content/renderer/pepper/pepper_browser_connection.cc
index 803f3df96c9..dfb24298131 100644
--- a/chromium/content/renderer/pepper/pepper_browser_connection.cc
+++ b/chromium/content/renderer/pepper/pepper_browser_connection.cc
@@ -9,16 +9,16 @@
#include "base/logging.h"
#include "content/common/view_messages.h"
#include "content/renderer/pepper/pepper_in_process_router.h"
-#include "content/renderer/render_view_impl.h"
+#include "content/renderer/render_frame_impl.h"
#include "ipc/ipc_message_macros.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/resource_message_params.h"
namespace content {
-PepperBrowserConnection::PepperBrowserConnection(RenderView* render_view)
- : RenderViewObserver(render_view),
- RenderViewObserverTracker<PepperBrowserConnection>(render_view),
+PepperBrowserConnection::PepperBrowserConnection(RenderFrame* render_frame)
+ : RenderFrameObserver(render_frame),
+ RenderFrameObserverTracker<PepperBrowserConnection>(render_frame),
next_sequence_number_(1) {
}
diff --git a/chromium/content/renderer/pepper/pepper_browser_connection.h b/chromium/content/renderer/pepper/pepper_browser_connection.h
index bef0ba2db1c..cfc5603cff9 100644
--- a/chromium/content/renderer/pepper/pepper_browser_connection.h
+++ b/chromium/content/renderer/pepper/pepper_browser_connection.h
@@ -11,12 +11,14 @@
#include "base/callback.h"
#include "base/files/file_path.h"
-#include "content/public/renderer/render_view_observer.h"
-#include "content/public/renderer/render_view_observer_tracker.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "content/public/renderer/render_frame_observer_tracker.h"
#include "ppapi/c/pp_file_info.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_resource.h"
+class GURL;
+
namespace content {
// This class represents a connection from the renderer to the browser for
@@ -24,12 +26,12 @@ namespace content {
// and renderer communicate about ResourceHosts, they should pass the plugin
// process ID to identify which plugin they are talking about.
class PepperBrowserConnection
- : public RenderViewObserver,
- public RenderViewObserverTracker<PepperBrowserConnection> {
+ : public RenderFrameObserver,
+ public RenderFrameObserverTracker<PepperBrowserConnection> {
public:
typedef base::Callback<void(const std::vector<int>&)>
PendingResourceIDCallback;
- explicit PepperBrowserConnection(RenderView* render_view);
+ explicit PepperBrowserConnection(RenderFrame* render_frame);
virtual ~PepperBrowserConnection();
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
index 9ec6373a096..28beb20936e 100644
--- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
+++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
@@ -34,6 +34,9 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest
requested_(false),
request_id_(0),
sync_call_(false) {
+ if (!owner_->document_url_.is_valid())
+ return;
+
requested_ = true;
// Note that the callback passed into
@@ -46,6 +49,7 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest
sync_call_ = true;
request_id_ = owner_->delegate_->EnumerateDevices(
owner_->device_type_,
+ owner_->document_url_,
base::Bind(&ScopedRequest::EnumerateDevicesCallbackBody, AsWeakPtr()));
sync_call_ = false;
}
@@ -61,7 +65,6 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest
private:
void EnumerateDevicesCallbackBody(
int request_id,
- bool succeeded,
const std::vector<ppapi::DeviceRefData>& devices) {
if (sync_call_) {
base::MessageLoop::current()->PostTask(
@@ -69,11 +72,10 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest
base::Bind(&ScopedRequest::EnumerateDevicesCallbackBody,
AsWeakPtr(),
request_id,
- succeeded,
devices));
} else {
DCHECK_EQ(request_id_, request_id);
- callback_.Run(request_id, succeeded, devices);
+ callback_.Run(request_id, devices);
// This object may have been destroyed at this point.
}
}
@@ -91,10 +93,12 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest
PepperDeviceEnumerationHostHelper::PepperDeviceEnumerationHostHelper(
ppapi::host::ResourceHost* resource_host,
Delegate* delegate,
- PP_DeviceType_Dev device_type)
+ PP_DeviceType_Dev device_type,
+ const GURL& document_url)
: resource_host_(resource_host),
delegate_(delegate),
- device_type_(device_type) {
+ device_type_(device_type),
+ document_url_(document_url) {
}
PepperDeviceEnumerationHostHelper::~PepperDeviceEnumerationHostHelper() {
@@ -165,31 +169,27 @@ int32_t PepperDeviceEnumerationHostHelper::OnStopMonitoringDeviceChange(
void PepperDeviceEnumerationHostHelper::OnEnumerateDevicesComplete(
int /* request_id */,
- bool succeeded,
const std::vector<ppapi::DeviceRefData>& devices) {
DCHECK(enumerate_devices_context_.get());
enumerate_.reset(NULL);
- enumerate_devices_context_->params.set_result(
- succeeded ? PP_OK : PP_ERROR_FAILED);
+ enumerate_devices_context_->params.set_result(PP_OK);
resource_host_->host()->SendReply(
*enumerate_devices_context_,
- PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply(
- succeeded ? devices : std::vector<ppapi::DeviceRefData>()));
+ PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply(devices));
enumerate_devices_context_.reset();
}
void PepperDeviceEnumerationHostHelper::OnNotifyDeviceChange(
uint32_t callback_id,
int /* request_id */,
- bool succeeded,
const std::vector<ppapi::DeviceRefData>& devices) {
resource_host_->host()->SendUnsolicitedReply(
resource_host_->pp_resource(),
PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange(
callback_id,
- succeeded ? devices : std::vector<ppapi::DeviceRefData>()));
+ devices));
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h
index 5773845561b..4142dec758e 100644
--- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h
+++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h
@@ -12,6 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "ppapi/c/dev/ppb_device_ref_dev.h"
+#include "url/gurl.h"
namespace ppapi {
struct DeviceRefData;
@@ -42,13 +43,13 @@ class CONTENT_EXPORT PepperDeviceEnumerationHostHelper {
typedef base::Callback<
void (int /* request_id */,
- bool /* succeeded */,
const std::vector<ppapi::DeviceRefData>& /* devices */)>
EnumerateDevicesCallback;
// Enumerates devices of the specified type. The request ID passed into the
// callback will be the same as the return value.
virtual int EnumerateDevices(PP_DeviceType_Dev type,
+ const GURL& document_url,
const EnumerateDevicesCallback& callback) = 0;
// Stop enumerating devices of the specified |request_id|. The |request_id|
// is the return value of EnumerateDevicesCallback.
@@ -58,7 +59,8 @@ class CONTENT_EXPORT PepperDeviceEnumerationHostHelper {
// |resource_host| and |delegate| must outlive this object.
PepperDeviceEnumerationHostHelper(ppapi::host::ResourceHost* resource_host,
Delegate* delegate,
- PP_DeviceType_Dev device_type);
+ PP_DeviceType_Dev device_type,
+ const GURL& document_url);
~PepperDeviceEnumerationHostHelper();
// Returns true if the message has been handled.
@@ -84,12 +86,10 @@ class CONTENT_EXPORT PepperDeviceEnumerationHostHelper {
void OnEnumerateDevicesComplete(
int request_id,
- bool succeeded,
const std::vector<ppapi::DeviceRefData>& devices);
void OnNotifyDeviceChange(
uint32_t callback_id,
int request_id,
- bool succeeded,
const std::vector<ppapi::DeviceRefData>& devices);
// Non-owning pointers.
@@ -97,6 +97,7 @@ class CONTENT_EXPORT PepperDeviceEnumerationHostHelper {
Delegate* delegate_;
PP_DeviceType_Dev device_type_;
+ GURL document_url_;
scoped_ptr<ScopedRequest> enumerate_;
scoped_ptr<ScopedRequest> monitor_;
diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
index 895bdd8e273..298e953bf64 100644
--- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
@@ -18,6 +18,7 @@
#include "ppapi/proxy/resource_message_test_sink.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
namespace content {
@@ -34,6 +35,7 @@ class TestDelegate : public PepperDeviceEnumerationHostHelper::Delegate {
virtual int EnumerateDevices(
PP_DeviceType_Dev /* type */,
+ const GURL& /* document_url */,
const EnumerateDevicesCallback& callback) OVERRIDE {
last_used_id_++;
callbacks_[last_used_id_] = callback;
@@ -50,14 +52,13 @@ class TestDelegate : public PepperDeviceEnumerationHostHelper::Delegate {
// Returns false if |request_id| is not found.
bool SimulateEnumerateResult(
int request_id,
- bool succeeded,
const std::vector<ppapi::DeviceRefData>& devices) {
std::map<int, EnumerateDevicesCallback>::iterator iter =
callbacks_.find(request_id);
if (iter == callbacks_.end())
return false;
- iter->second.Run(request_id, succeeded, devices);
+ iter->second.Run(request_id, devices);
return true;
}
@@ -78,7 +79,8 @@ class PepperDeviceEnumerationHostHelperTest : public testing::Test {
: ppapi_host_(&sink_, ppapi::PpapiPermissions()),
resource_host_(&ppapi_host_, 12345, 67890),
device_enumeration_(&resource_host_, &delegate_,
- PP_DEVICETYPE_DEV_AUDIOCAPTURE) {
+ PP_DEVICETYPE_DEV_AUDIOCAPTURE,
+ GURL("http://example.com")) {
}
virtual ~PepperDeviceEnumerationHostHelperTest() {}
@@ -150,7 +152,7 @@ TEST_F(PepperDeviceEnumerationHostHelperTest, EnumerateDevices) {
data_item.name = "name_2";
data_item.id = "id_2";
data.push_back(data_item);
- ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, true, data));
+ ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, data));
// StopEnumerateDevices() should have been called since the EnumerateDevices
// message is not a persistent request.
@@ -181,7 +183,7 @@ TEST_F(PepperDeviceEnumerationHostHelperTest, MonitorDeviceChange) {
int request_id = delegate_.last_used_id();
std::vector<ppapi::DeviceRefData> data;
- ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, true, data));
+ ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, data));
// StopEnumerateDevices() shouldn't be called because the MonitorDeviceChange
// message is a persistent request.
@@ -198,7 +200,7 @@ TEST_F(PepperDeviceEnumerationHostHelperTest, MonitorDeviceChange) {
data_item.name = "name_2";
data_item.id = "id_2";
data.push_back(data_item);
- ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, true, data));
+ ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, data));
EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount());
CheckNotifyDeviceChangeMessage(callback_id, data);
@@ -214,7 +216,7 @@ TEST_F(PepperDeviceEnumerationHostHelperTest, MonitorDeviceChange) {
data_item.name = "name_3";
data_item.id = "id_3";
data.push_back(data_item);
- ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id2, true, data));
+ ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id2, data));
CheckNotifyDeviceChangeMessage(callback_id2, data);
diff --git a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
index e73694ac336..ca13f5a7949 100644
--- a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
+++ b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
@@ -22,7 +22,7 @@
namespace content {
class PepperFileChooserHost::CompletionHandler
- : public WebKit::WebFileChooserCompletion {
+ : public blink::WebFileChooserCompletion {
public:
CompletionHandler(const base::WeakPtr<PepperFileChooserHost>& host)
: host_(host) {
@@ -31,7 +31,7 @@ class PepperFileChooserHost::CompletionHandler
virtual ~CompletionHandler() {}
virtual void didChooseFile(
- const WebKit::WebVector<WebKit::WebString>& file_names) {
+ const blink::WebVector<blink::WebString>& file_names) {
if (host_.get()) {
std::vector<PepperFileChooserHost::ChosenFileInfo> files;
for (size_t i = 0; i < file_names.size(); i++) {
@@ -45,7 +45,7 @@ class PepperFileChooserHost::CompletionHandler
delete this;
}
virtual void didChooseFile(
- const WebKit::WebVector<SelectedFileInfo>& file_names) {
+ const blink::WebVector<SelectedFileInfo>& file_names) {
if (host_.get()) {
std::vector<PepperFileChooserHost::ChosenFileInfo> files;
for (size_t i = 0; i < file_names.size(); i++) {
@@ -145,17 +145,17 @@ int32_t PepperFileChooserHost::OnShow(
return PP_ERROR_NO_USER_GESTURE;
}
- WebKit::WebFileChooserParams params;
+ blink::WebFileChooserParams params;
if (save_as) {
params.saveAs = true;
- params.initialValue = WebKit::WebString::fromUTF8(
+ params.initialValue = blink::WebString::fromUTF8(
suggested_file_name.data(), suggested_file_name.size());
} else {
params.multiSelect = open_multiple;
}
- std::vector<WebKit::WebString> mine_types(accept_mime_types.size());
+ std::vector<blink::WebString> mine_types(accept_mime_types.size());
for (size_t i = 0; i < accept_mime_types.size(); i++) {
- mine_types[i] = WebKit::WebString::fromUTF8(
+ mine_types[i] = blink::WebString::fromUTF8(
accept_mime_types[i].data(), accept_mime_types[i].size());
}
params.acceptTypes = mine_types;
diff --git a/chromium/content/renderer/pepper/pepper_file_io_host.cc b/chromium/content/renderer/pepper/pepper_file_io_host.cc
deleted file mode 100644
index 6add31ae0d6..00000000000
--- a/chromium/content/renderer/pepper/pepper_file_io_host.cc
+++ /dev/null
@@ -1,563 +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/pepper/pepper_file_io_host.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/command_line.h"
-#include "base/files/file_util_proxy.h"
-#include "content/child/child_thread.h"
-#include "content/child/fileapi/file_system_dispatcher.h"
-#include "content/child/quota_dispatcher.h"
-#include "content/common/fileapi/file_system_messages.h"
-#include "content/common/view_messages.h"
-#include "content/public/common/content_client.h"
-#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
-#include "content/renderer/pepper/quota_file_io.h"
-#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
-#include "content/renderer/render_thread_impl.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/ppb_file_io.h"
-#include "ppapi/host/dispatch_host_message.h"
-#include "ppapi/host/ppapi_host.h"
-#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/shared_impl/file_type_conversion.h"
-#include "ppapi/shared_impl/time_conversion.h"
-#include "ppapi/thunk/enter.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
-
-namespace content {
-
-using ppapi::FileIOStateManager;
-using ppapi::PPTimeToTime;
-using ppapi::host::ReplyMessageContext;
-using ppapi::thunk::EnterResourceNoLock;
-
-namespace {
-
-typedef base::Callback<void (base::PlatformFileError)> PlatformGeneralCallback;
-
-int32_t ErrorOrByteNumber(int32_t pp_error, int32_t byte_number) {
- // On the plugin side, some callbacks expect a parameter that means different
- // things depending on whether is negative or not. We translate for those
- // callbacks here.
- return pp_error == PP_OK ? byte_number : pp_error;
-}
-
-class QuotaCallbackTranslator : public QuotaDispatcher::Callback {
- public:
- typedef QuotaFileIO::Delegate::AvailableSpaceCallback PluginCallback;
- explicit QuotaCallbackTranslator(const PluginCallback& cb) : callback_(cb) {}
- virtual void DidQueryStorageUsageAndQuota(int64 usage, int64 quota) OVERRIDE {
- callback_.Run(std::max(static_cast<int64>(0), quota - usage));
- }
- virtual void DidGrantStorageQuota(int64 granted_quota) OVERRIDE {
- NOTREACHED();
- }
- virtual void DidFail(quota::QuotaStatusCode error) OVERRIDE {
- callback_.Run(0);
- }
- private:
- PluginCallback callback_;
-};
-
-class QuotaFileIODelegate : public QuotaFileIO::Delegate {
- public:
- QuotaFileIODelegate() {}
- virtual ~QuotaFileIODelegate() {}
-
- virtual void QueryAvailableSpace(
- const GURL& origin,
- quota::StorageType type,
- const AvailableSpaceCallback& callback) OVERRIDE {
- ChildThread::current()->quota_dispatcher()->QueryStorageUsageAndQuota(
- origin, type, new QuotaCallbackTranslator(callback));
- }
- virtual void WillUpdateFile(const GURL& file_path) OVERRIDE {
- ChildThread::current()->Send(new FileSystemHostMsg_WillUpdate(file_path));
- }
- virtual void DidUpdateFile(const GURL& file_path, int64_t delta) OVERRIDE {
- ChildThread::current()->Send(new FileSystemHostMsg_DidUpdate(
- file_path, delta));
- }
- virtual scoped_refptr<base::MessageLoopProxy>
- GetFileThreadMessageLoopProxy() OVERRIDE {
- return RenderThreadImpl::current()->GetFileThreadMessageLoopProxy();
- }
-};
-
-typedef base::Callback<
- void (base::PlatformFileError error,
- base::PassPlatformFile file,
- quota::QuotaLimitType quota_policy,
- const PepperFileIOHost::NotifyCloseFileCallback& close_file_callback)>
- AsyncOpenFileSystemURLCallback;
-
-void DoNotifyCloseFile(int file_open_id, base::PlatformFileError error) {
- ChildThread::current()->file_system_dispatcher()->NotifyCloseFile(
- file_open_id);
-}
-
-void DidOpenFileSystemURL(const AsyncOpenFileSystemURLCallback& callback,
- base::PlatformFile file,
- int file_open_id,
- quota::QuotaLimitType quota_policy) {
- callback.Run(base::PLATFORM_FILE_OK,
- base::PassPlatformFile(&file),
- quota_policy,
- base::Bind(&DoNotifyCloseFile, file_open_id));
- // Make sure we won't leak file handle if the requester has died.
- if (file != base::kInvalidPlatformFileValue) {
- base::FileUtilProxy::Close(
- RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
- file,
- base::Bind(&DoNotifyCloseFile, file_open_id));
- }
-}
-
-void DidFailOpenFileSystemURL(const AsyncOpenFileSystemURLCallback& callback,
- base::PlatformFileError error_code) {
- base::PlatformFile invalid_file = base::kInvalidPlatformFileValue;
- callback.Run(error_code,
- base::PassPlatformFile(&invalid_file),
- quota::kQuotaLimitTypeUnknown,
- PepperFileIOHost::NotifyCloseFileCallback());
-}
-
-} // namespace
-
-PepperFileIOHost::PepperFileIOHost(RendererPpapiHost* host,
- PP_Instance instance,
- PP_Resource resource)
- : ResourceHost(host->GetPpapiHost(), instance, resource),
- renderer_ppapi_host_(host),
- file_(base::kInvalidPlatformFileValue),
- file_system_type_(PP_FILESYSTEMTYPE_INVALID),
- quota_policy_(quota::kQuotaLimitTypeUnknown),
- is_running_in_process_(host->IsRunningInProcess()),
- open_flags_(0),
- routing_id_(RenderThreadImpl::current()->GenerateRoutingID()),
- weak_factory_(this) {
- ChildThread::current()->AddRoute(routing_id_, this);
-}
-
-PepperFileIOHost::~PepperFileIOHost() {
- OnHostMsgClose(NULL);
- ChildThread::current()->RemoveRoute(routing_id_);
-}
-
-int32_t PepperFileIOHost::OnResourceMessageReceived(
- const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) {
- IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open,
- OnHostMsgOpen)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch,
- OnHostMsgTouch)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Write,
- OnHostMsgWrite)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength,
- OnHostMsgSetLength)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Flush,
- OnHostMsgFlush)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Close,
- OnHostMsgClose)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_WillWrite,
- OnHostMsgWillWrite)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_WillSetLength,
- OnHostMsgWillSetLength)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_GetOSFileDescriptor,
- OnHostMsgGetOSFileDescriptor)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_RequestOSFileHandle,
- OnHostMsgRequestOSFileHandle)
- IPC_END_MESSAGE_MAP()
- return PP_ERROR_FAILED;
-}
-
-bool PepperFileIOHost::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg)
- IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenPepperFile_ACK, OnAsyncFileOpened)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void PepperFileIOHost::OnAsyncFileOpened(
- base::PlatformFileError error_code,
- IPC::PlatformFileForTransit file_for_transit,
- int message_id) {
- AsyncOpenFileCallback* callback =
- pending_async_open_files_.Lookup(message_id);
- DCHECK(callback);
- pending_async_open_files_.Remove(message_id);
-
- base::PlatformFile file =
- IPC::PlatformFileForTransitToPlatformFile(file_for_transit);
- callback->Run(error_code, base::PassPlatformFile(&file));
- // Make sure we won't leak file handle if the requester has died.
- if (file != base::kInvalidPlatformFileValue) {
- base::FileUtilProxy::Close(
- RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
- file,
- base::FileUtilProxy::StatusCallback());
- }
- delete callback;
-}
-
-int32_t PepperFileIOHost::OnHostMsgOpen(
- ppapi::host::HostMessageContext* context,
- PP_Resource file_ref_resource,
- int32_t open_flags) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_EXCLUSIVE, false);
- if (rv != PP_OK)
- return rv;
-
- open_flags_ = open_flags;
- if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags, NULL))
- return PP_ERROR_BADARGUMENT;
-
- ppapi::host::ResourceHost* resource_host =
- renderer_ppapi_host_->GetPpapiHost()->GetResourceHost(file_ref_resource);
- if (!resource_host || !resource_host->IsFileRefHost())
- return PP_ERROR_BADRESOURCE;
- PepperFileRefRendererHost* file_ref_host =
- static_cast<PepperFileRefRendererHost*>(resource_host);
-
- file_system_type_ = file_ref_host->GetFileSystemType();
- if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
- file_system_url_ = file_ref_host->GetFileSystemURL();
- FileSystemDispatcher* file_system_dispatcher =
- ChildThread::current()->file_system_dispatcher();
-
- AsyncOpenFileSystemURLCallback callback = base::Bind(
- &PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext());
- file_system_dispatcher->OpenPepperFile(
- file_system_url_, open_flags,
- base::Bind(&DidOpenFileSystemURL, callback),
- base::Bind(&DidFailOpenFileSystemURL, callback));
- } else {
- int message_id = pending_async_open_files_.Add(new AsyncOpenFileCallback(
- base::Bind(&PepperFileIOHost::ExecutePlatformOpenFileCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())));
- RenderThreadImpl::current()->Send(new ViewHostMsg_AsyncOpenPepperFile(
- routing_id_,
- file_ref_host->GetExternalFilePath(),
- open_flags_,
- message_id));
- }
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgTouch(
- ppapi::host::HostMessageContext* context,
- PP_Time last_access_time,
- PP_Time last_modified_time) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_EXCLUSIVE, true);
- if (rv != PP_OK)
- return rv;
-
- if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
- FileSystemDispatcher* file_system_dispatcher =
- ChildThread::current()->file_system_dispatcher();
- file_system_dispatcher->TouchFile(
- file_system_url_,
- PPTimeToTime(last_access_time),
- PPTimeToTime(last_modified_time),
- base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext()));
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
- }
-
- // TODO(nhiroki): fix a failure of FileIO.Touch for an external filesystem on
- // Mac and Linux due to sandbox restrictions (http://crbug.com/101128).
- if (!base::FileUtilProxy::Touch(
- RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
- file_,
- PPTimeToTime(last_access_time),
- PPTimeToTime(last_modified_time),
- base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())))
- return PP_ERROR_FAILED;
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgWrite(
- ppapi::host::HostMessageContext* context,
- int64_t offset,
- const std::string& buffer) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_WRITE, true);
- if (rv != PP_OK)
- return rv;
-
- if (quota_file_io_) {
- if (!quota_file_io_->Write(
- offset, buffer.c_str(), buffer.size(),
- base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())))
- return PP_ERROR_FAILED;
- } else {
- if (!base::FileUtilProxy::Write(
- RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
- file_,
- offset,
- buffer.c_str(),
- buffer.size(),
- base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())))
- return PP_ERROR_FAILED;
- }
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgSetLength(
- ppapi::host::HostMessageContext* context,
- int64_t length) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_EXCLUSIVE, true);
- if (rv != PP_OK)
- return rv;
-
- if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
- FileSystemDispatcher* file_system_dispatcher =
- ChildThread::current()->file_system_dispatcher();
- file_system_dispatcher->Truncate(
- file_system_url_, length, NULL,
- base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext()));
- } else {
- // TODO(nhiroki): fix a failure of FileIO.SetLength for an external
- // filesystem on Mac due to sandbox restrictions (http://crbug.com/156077).
- if (!base::FileUtilProxy::Truncate(
- RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
- file_,
- length,
- base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())))
- return PP_ERROR_FAILED;
- }
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgFlush(
- ppapi::host::HostMessageContext* context) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_EXCLUSIVE, true);
- if (rv != PP_OK)
- return rv;
-
- if (!base::FileUtilProxy::Flush(
- RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
- file_,
- base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())))
- return PP_ERROR_FAILED;
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgClose(
- ppapi::host::HostMessageContext* context) {
- if (file_ != base::kInvalidPlatformFileValue) {
- base::FileUtilProxy::Close(
- RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
- file_,
- base::ResetAndReturn(&notify_close_file_callback_));
- file_ = base::kInvalidPlatformFileValue;
- quota_file_io_.reset();
- }
- return PP_OK;
-}
-
-int32_t PepperFileIOHost::OnHostMsgWillWrite(
- ppapi::host::HostMessageContext* context,
- int64_t offset,
- int32_t bytes_to_write) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_EXCLUSIVE, true);
- if (rv != PP_OK)
- return rv;
-
- if (!quota_file_io_)
- return PP_OK;
-
- if (!quota_file_io_->WillWrite(
- offset, bytes_to_write,
- base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())))
- return PP_ERROR_FAILED;
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgWillSetLength(
- ppapi::host::HostMessageContext* context,
- int64_t length) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_EXCLUSIVE, true);
- if (rv != PP_OK)
- return rv;
-
- if (!quota_file_io_)
- return PP_OK;
-
- if (!quota_file_io_->WillSetLength(
- length,
- base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())))
- return PP_ERROR_FAILED;
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgRequestOSFileHandle(
- ppapi::host::HostMessageContext* context) {
- if (!is_running_in_process_ &&
- quota_policy_ != quota::kQuotaLimitTypeUnlimited)
- return PP_ERROR_FAILED;
-
- // Whitelist to make it privately accessible.
- if (!GetContentClient()->renderer()->IsPluginAllowedToCallRequestOSFileHandle(
- renderer_ppapi_host_->GetContainerForInstance(pp_instance())))
- return PP_ERROR_NOACCESS;
-
- IPC::PlatformFileForTransit file =
- renderer_ppapi_host_->ShareHandleWithRemote(file_, false);
- if (file == IPC::InvalidPlatformFileForTransit())
- return PP_ERROR_FAILED;
- ppapi::host::ReplyMessageContext reply_context =
- context->MakeReplyMessageContext();
- ppapi::proxy::SerializedHandle file_handle;
- file_handle.set_file_handle(file, open_flags_);
- reply_context.params.AppendHandle(file_handle);
- host()->SendReply(reply_context,
- PpapiPluginMsg_FileIO_RequestOSFileHandleReply());
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgGetOSFileDescriptor(
- ppapi::host::HostMessageContext* context) {
- if (!is_running_in_process_)
- return PP_ERROR_FAILED;
-
- int32_t fd =
-#if defined(OS_POSIX)
- file_;
-#elif defined(OS_WIN)
- reinterpret_cast<uintptr_t>(file_);
-#else
- -1;
-#endif
-
- host()->SendReply(context->MakeReplyMessageContext(),
- PpapiPluginMsg_FileIO_GetOSFileDescriptorReply(fd));
- return PP_OK_COMPLETIONPENDING;
-}
-
-void PepperFileIOHost::ExecutePlatformGeneralCallback(
- ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError error_code) {
- reply_context.params.set_result(
- ppapi::PlatformFileErrorToPepperError(error_code));
- host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
- state_manager_.SetOperationFinished();
-}
-
-void PepperFileIOHost::ExecutePlatformOpenFileCallback(
- ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- base::PassPlatformFile file) {
- int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
- if (pp_error == PP_OK)
- state_manager_.SetOpenSucceed();
-
- DCHECK(file_ == base::kInvalidPlatformFileValue);
- file_ = file.ReleaseValue();
-
- DCHECK(!quota_file_io_.get());
- if (file_ != base::kInvalidPlatformFileValue) {
- if (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
- file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT) {
- quota_file_io_.reset(new QuotaFileIO(
- new QuotaFileIODelegate, file_, file_system_url_, file_system_type_));
- }
-
- IPC::PlatformFileForTransit file_for_transit =
- renderer_ppapi_host_->ShareHandleWithRemote(file_, false);
- if (!(file_for_transit == IPC::InvalidPlatformFileForTransit())) {
- // Send the file descriptor to the plugin process. This is used in the
- // plugin for any file operations that can be done there.
- int32_t flags_to_send = open_flags_;
- if (!host()->permissions().HasPermission(ppapi::PERMISSION_DEV)) {
- // IMPORTANT: Clear PP_FILEOPENFLAG_WRITE and PP_FILEOPENFLAG_APPEND so
- // the plugin can't write and so bypass our quota checks.
- flags_to_send =
- open_flags_ & ~(PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_APPEND);
- }
- ppapi::proxy::SerializedHandle file_handle;
- file_handle.set_file_handle(file_for_transit, flags_to_send);
- reply_context.params.AppendHandle(file_handle);
- }
- }
-
- reply_context.params.set_result(pp_error);
- host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply());
- state_manager_.SetOperationFinished();
-}
-
-void PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback(
- ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- base::PassPlatformFile file,
- quota::QuotaLimitType quota_policy,
- const PepperFileIOHost::NotifyCloseFileCallback& callback) {
- if (error_code == base::PLATFORM_FILE_OK)
- notify_close_file_callback_ = callback;
- quota_policy_ = quota_policy;
- ExecutePlatformOpenFileCallback(reply_context, error_code, file);
-}
-
-void PepperFileIOHost::ExecutePlatformWriteCallback(
- ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- int bytes_written) {
- // On the plugin side, the callback expects a parameter with different meaning
- // depends on whether is negative or not. It is the result here. We translate
- // for the callback.
- int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
- reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written));
- host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
- state_manager_.SetOperationFinished();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_file_io_host.h b/chromium/content/renderer/pepper/pepper_file_io_host.h
deleted file mode 100644
index 0525a6c605b..00000000000
--- a/chromium/content/renderer/pepper/pepper_file_io_host.h
+++ /dev/null
@@ -1,148 +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_PEPPER_PEPPER_FILE_IO_HOST_H_
-#define CONTENT_RENDERER_PEPPER_PEPPER_FILE_IO_HOST_H_
-
-#include <set>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/callback_forward.h"
-#include "base/id_map.h"
-#include "base/memory/weak_ptr.h"
-#include "base/platform_file.h"
-#include "content/public/renderer/renderer_ppapi_host.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_platform_file.h"
-#include "ppapi/host/host_message_context.h"
-#include "ppapi/host/resource_host.h"
-#include "ppapi/shared_impl/file_io_state_manager.h"
-#include "ppapi/thunk/ppb_file_ref_api.h"
-#include "url/gurl.h"
-#include "webkit/common/quota/quota_types.h"
-
-using ppapi::host::ReplyMessageContext;
-
-namespace content {
-class QuotaFileIO;
-
-class PepperFileIOHost : public ppapi::host::ResourceHost,
- public base::SupportsWeakPtr<PepperFileIOHost>,
- public IPC::Listener {
- public:
- typedef base::Callback<void (base::PlatformFileError)>
- NotifyCloseFileCallback;
-
- PepperFileIOHost(RendererPpapiHost* host,
- PP_Instance instance,
- PP_Resource resource);
- virtual ~PepperFileIOHost();
-
- // ppapi::host::ResourceHost override.
- virtual int32_t OnResourceMessageReceived(
- const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
-
- private:
- // IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- void OnAsyncFileOpened(
- base::PlatformFileError error_code,
- IPC::PlatformFileForTransit file_for_transit,
- int message_id);
-
- int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
- PP_Resource file_ref_resource,
- int32_t open_flags);
- int32_t OnHostMsgTouch(ppapi::host::HostMessageContext* context,
- PP_Time last_access_time,
- PP_Time last_modified_time);
- int32_t OnHostMsgWrite(ppapi::host::HostMessageContext* context,
- int64_t offset,
- const std::string& buffer);
- int32_t OnHostMsgSetLength(ppapi::host::HostMessageContext* context,
- int64_t length);
- int32_t OnHostMsgClose(ppapi::host::HostMessageContext* context);
- int32_t OnHostMsgFlush(ppapi::host::HostMessageContext* context);
- // Private API.
- int32_t OnHostMsgRequestOSFileHandle(
- ppapi::host::HostMessageContext* context);
- // Trusted API.
- int32_t OnHostMsgGetOSFileDescriptor(
- ppapi::host::HostMessageContext* context);
- int32_t OnHostMsgWillWrite(ppapi::host::HostMessageContext* context,
- int64_t offset,
- int32_t bytes_to_write);
- int32_t OnHostMsgWillSetLength(ppapi::host::HostMessageContext* context,
- int64_t length);
-
- // Callback handlers. These mostly convert the PlatformFileError to the
- // PP_Error code and send back the reply. Note that the argument
- // ReplyMessageContext is copied so that we have a closure containing all
- // necessary information to reply.
- void ExecutePlatformGeneralCallback(ReplyMessageContext reply_context,
- base::PlatformFileError error_code);
- void ExecutePlatformOpenFileCallback(ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- base::PassPlatformFile file);
- void ExecutePlatformOpenFileSystemURLCallback(
- ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- base::PassPlatformFile file,
- quota::QuotaLimitType quota_policy,
- const NotifyCloseFileCallback& callback);
- void ExecutePlatformQueryCallback(ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- const base::PlatformFileInfo& file_info);
- void ExecutePlatformReadCallback(ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- const char* data, int bytes_read);
- void ExecutePlatformWriteCallback(ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- int bytes_written);
-
- RendererPpapiHost* renderer_ppapi_host_;
- base::PlatformFile file_;
-
- // The file system type specified in the Open() call. This will be
- // PP_FILESYSTEMTYPE_INVALID before open was called. This value does not
- // indicate that the open command actually succeeded.
- PP_FileSystemType file_system_type_;
-
- // Valid only for PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY}.
- GURL file_system_url_;
-
- // Used to check if we can pass file handle to plugins.
- quota::QuotaLimitType quota_policy_;
-
- // Callback function for notifying when the file handle is closed.
- NotifyCloseFileCallback notify_close_file_callback_;
-
- // Pointer to a QuotaFileIO instance, which is valid only while a file
- // of type PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY} is opened.
- scoped_ptr<QuotaFileIO> quota_file_io_;
-
- bool is_running_in_process_;
-
- int32_t open_flags_;
-
- ppapi::FileIOStateManager state_manager_;
-
- int routing_id_;
-
- typedef base::Callback<void (base::PlatformFileError, base::PassPlatformFile)>
- AsyncOpenFileCallback;
-
- IDMap<AsyncOpenFileCallback> pending_async_open_files_;
-
- base::WeakPtrFactory<PepperFileIOHost> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(PepperFileIOHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_PEPPER_PEPPER_FILE_IO_HOST_H_
diff --git a/chromium/content/renderer/pepper/pepper_file_system_host.cc b/chromium/content/renderer/pepper/pepper_file_system_host.cc
index 00c580b6d31..be5cead8240 100644
--- a/chromium/content/renderer/pepper/pepper_file_system_host.cc
+++ b/chromium/content/renderer/pepper/pepper_file_system_host.cc
@@ -15,33 +15,15 @@
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/file_system_util.h"
#include "ppapi/shared_impl/file_type_conversion.h"
#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "webkit/common/fileapi/file_system_util.h"
namespace content {
-namespace {
-
-bool LooksLikeAGuid(const std::string& fsid) {
- const size_t kExpectedFsIdSize = 32;
- if (fsid.size() != kExpectedFsIdSize)
- return false;
- for (std::string::const_iterator it = fsid.begin(); it != fsid.end(); ++it) {
- if (('A' <= *it && *it <= 'F') ||
- ('0' <= *it && *it <= '9'))
- continue;
- return false;
- }
- return true;
-}
-
-} // namespace
-
PepperFileSystemHost::PepperFileSystemHost(RendererPpapiHost* host,
PP_Instance instance,
PP_Resource resource,
@@ -54,6 +36,20 @@ PepperFileSystemHost::PepperFileSystemHost(RendererPpapiHost* host,
weak_factory_(this) {
}
+PepperFileSystemHost::PepperFileSystemHost(RendererPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource,
+ const GURL& root_url,
+ PP_FileSystemType type)
+ : ResourceHost(host->GetPpapiHost(), instance, resource),
+ renderer_ppapi_host_(host),
+ type_(type),
+ opened_(true),
+ root_url_(root_url),
+ called_open_(true),
+ weak_factory_(this) {
+}
+
PepperFileSystemHost::~PepperFileSystemHost() {
}
@@ -102,33 +98,21 @@ int32_t PepperFileSystemHost::OnHostMsgOpen(
return PP_ERROR_INPROGRESS;
called_open_ = true;
- fileapi::FileSystemType file_system_type;
- switch (type_) {
- case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
- file_system_type = fileapi::kFileSystemTypeTemporary;
- break;
- case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
- file_system_type = fileapi::kFileSystemTypePersistent;
- break;
- case PP_FILESYSTEMTYPE_EXTERNAL:
- file_system_type = fileapi::kFileSystemTypeExternal;
- break;
- default:
- return PP_ERROR_FAILED;
- }
-
- PepperPluginInstance* plugin_instance =
- renderer_ppapi_host_->GetPluginInstance(pp_instance());
- if (!plugin_instance)
+ fileapi::FileSystemType file_system_type =
+ ppapi::PepperFileSystemTypeToFileSystemType(type_);
+ if (file_system_type == fileapi::kFileSystemTypeUnknown)
+ return PP_ERROR_FAILED;
+
+ GURL document_url = renderer_ppapi_host_->GetDocumentURL(pp_instance());
+ if (!document_url.is_valid())
return PP_ERROR_FAILED;
FileSystemDispatcher* file_system_dispatcher =
ChildThread::current()->file_system_dispatcher();
reply_context_ = context->MakeReplyMessageContext();
file_system_dispatcher->OpenFileSystem(
- GURL(plugin_instance->GetContainer()->element().document().url()).
- GetOrigin(),
- file_system_type, expected_size, true /* create */,
+ document_url.GetOrigin(),
+ file_system_type,
base::Bind(&PepperFileSystemHost::DidOpenFileSystem,
weak_factory_.GetWeakPtr()),
base::Bind(&PepperFileSystemHost::DidFailOpenFileSystem,
@@ -138,18 +122,28 @@ int32_t PepperFileSystemHost::OnHostMsgOpen(
int32_t PepperFileSystemHost::OnHostMsgInitIsolatedFileSystem(
ppapi::host::HostMessageContext* context,
- const std::string& fsid) {
+ const std::string& fsid,
+ PP_IsolatedFileSystemType_Private type) {
+ // Do not allow multiple opens.
+ if (called_open_)
+ return PP_ERROR_INPROGRESS;
called_open_ = true;
+
// Do a sanity check.
- if (!LooksLikeAGuid(fsid))
+ if (!fileapi::ValidateIsolatedFileSystemId(fsid))
return PP_ERROR_BADARGUMENT;
+
RenderView* view =
renderer_ppapi_host_->GetRenderViewForInstance(pp_instance());
if (!view)
return PP_ERROR_FAILED;
+
const GURL& url = view->GetWebView()->mainFrame()->document().url();
+ const std::string root_name = ppapi::IsolatedFileSystemTypeToRootName(type);
+ if (root_name.empty())
+ return PP_ERROR_BADARGUMENT;
root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
- url.GetOrigin(), fsid, "crxfs"));
+ url.GetOrigin(), fsid, root_name));
opened_ = true;
return PP_OK;
}
diff --git a/chromium/content/renderer/pepper/pepper_file_system_host.h b/chromium/content/renderer/pepper/pepper_file_system_host.h
index 3ff8d4d6e21..0e0be311c1c 100644
--- a/chromium/content/renderer/pepper/pepper_file_system_host.h
+++ b/chromium/content/renderer/pepper/pepper_file_system_host.h
@@ -5,9 +5,12 @@
#ifndef CONTENT_RENDERER_PEPPER_PEPPER_FILE_SYSTEM_HOST_H_
#define CONTENT_RENDERER_PEPPER_PEPPER_FILE_SYSTEM_HOST_H_
+#include <string>
+
#include "base/basictypes.h"
#include "base/memory/weak_ptr.h"
#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/private/ppb_isolated_file_system_private.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
#include "url/gurl.h"
@@ -16,13 +19,24 @@ namespace content {
class RendererPpapiHost;
-class PepperFileSystemHost :
- public ppapi::host::ResourceHost,
- public base::SupportsWeakPtr<PepperFileSystemHost> {
+class PepperFileSystemHost
+ : public ppapi::host::ResourceHost,
+ public base::SupportsWeakPtr<PepperFileSystemHost> {
public:
+ // Creates a new PepperFileSystemHost for a file system of a given |type|. The
+ // host will not be connected to any specific file system, and will need to
+ // subsequently be opened before use.
+ PepperFileSystemHost(RendererPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource,
+ PP_FileSystemType type);
+ // Creates a new PepperFileSystemHost with an existing file system at the
+ // given |root_url| and of the given |type|. The file system must already be
+ // opened. Once created, the PepperFileSystemHost is already opened for use.
PepperFileSystemHost(RendererPpapiHost* host,
PP_Instance instance,
PP_Resource resource,
+ const GURL& root_url,
PP_FileSystemType type);
virtual ~PepperFileSystemHost();
@@ -46,7 +60,8 @@ class PepperFileSystemHost :
int64_t expected_size);
int32_t OnHostMsgInitIsolatedFileSystem(
ppapi::host::HostMessageContext* context,
- const std::string& fsid);
+ const std::string& fsid,
+ PP_IsolatedFileSystemType_Private type);
RendererPpapiHost* renderer_ppapi_host_;
ppapi::host::ReplyMessageContext reply_context_;
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
index 8fb9841d645..51034591b8b 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -23,11 +23,11 @@
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppb_view_shared.h"
#include "ppapi/thunk/enter.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/blit.h"
-#include "ui/gfx/point.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_conversions.h"
@@ -136,7 +136,8 @@ struct PepperGraphics2DHost::QueuedOperation {
enum Type {
PAINT,
SCROLL,
- REPLACE
+ REPLACE,
+ SET_OFFSET
};
QueuedOperation(Type t)
@@ -160,18 +161,24 @@ struct PepperGraphics2DHost::QueuedOperation {
// Valid when type == REPLACE.
scoped_refptr<PPB_ImageData_Impl> replace_image;
+
+ // Valid when type == SET_OFFSET.
+ gfx::Point offset;
};
// static
-PepperGraphics2DHost* PepperGraphics2DHost::Create(RendererPpapiHost* host,
- PP_Instance instance,
- PP_Resource resource,
- const PP_Size& size,
- PP_Bool is_always_opaque) {
+PepperGraphics2DHost* PepperGraphics2DHost::Create(
+ RendererPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource,
+ const PP_Size& size,
+ PP_Bool is_always_opaque,
+ scoped_refptr<PPB_ImageData_Impl> backing_store) {
PepperGraphics2DHost* resource_host =
new PepperGraphics2DHost(host, instance, resource);
if (!resource_host->Init(size.width, size.height,
- PP_ToBool(is_always_opaque))) {
+ PP_ToBool(is_always_opaque),
+ backing_store)) {
delete resource_host;
return NULL;
}
@@ -188,9 +195,9 @@ PepperGraphics2DHost::PepperGraphics2DHost(RendererPpapiHost* host,
offscreen_flush_pending_(false),
is_always_opaque_(false),
scale_(1.0f),
- weak_ptr_factory_(this),
is_running_in_process_(host->IsRunningInProcess()),
- texture_mailbox_modified_(true) {}
+ texture_mailbox_modified_(true),
+ resize_mode_(PP_GRAPHICS2D_DEV_RESIZEMODE_DEFAULT) {}
PepperGraphics2DHost::~PepperGraphics2DHost() {
// Unbind from the instance when destroyed if we're still bound.
@@ -198,10 +205,13 @@ PepperGraphics2DHost::~PepperGraphics2DHost() {
bound_instance_->BindGraphics(bound_instance_->pp_instance(), 0);
}
-bool PepperGraphics2DHost::Init(int width, int height, bool is_always_opaque) {
+bool PepperGraphics2DHost::Init(
+ int width,
+ int height,
+ bool is_always_opaque,
+ scoped_refptr<PPB_ImageData_Impl> backing_store) {
// The underlying PPB_ImageData_Impl will validate the dimensions.
- image_data_ = new PPB_ImageData_Impl(pp_instance(),
- PPB_ImageData_Impl::PLATFORM);
+ image_data_ = backing_store;
if (!image_data_->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(),
width, height, true) ||
!image_data_->Map()) {
@@ -226,13 +236,19 @@ int32_t PepperGraphics2DHost::OnResourceMessageReceived(
PPAPI_DISPATCH_HOST_RESOURCE_CALL(
PpapiHostMsg_Graphics2D_ReplaceContents,
OnHostMsgReplaceContents)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
PpapiHostMsg_Graphics2D_Flush,
OnHostMsgFlush)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(
PpapiHostMsg_Graphics2D_Dev_SetScale,
OnHostMsgSetScale)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_Graphics2D_SetOffset,
+ OnHostMsgSetOffset)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_Graphics2D_SetResizeMode,
+ OnHostMsgSetResizeMode)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
PpapiHostMsg_Graphics2D_ReadImageData,
OnHostMsgReadImageData)
IPC_END_MESSAGE_MAP()
@@ -323,7 +339,7 @@ bool PepperGraphics2DHost::BindToInstance(
// The |backing_bitmap| must be clipped to the |plugin_rect| to avoid painting
// outside the plugin area. This can happen if the plugin has been resized since
// PaintImageData verified the image is within the plugin size.
-void PepperGraphics2DHost::Paint(WebKit::WebCanvas* canvas,
+void PepperGraphics2DHost::Paint(blink::WebCanvas* canvas,
const gfx::Rect& plugin_rect,
const gfx::Rect& paint_rect) {
TRACE_EVENT0("pepper", "PepperGraphics2DHost::Paint");
@@ -380,17 +396,20 @@ void PepperGraphics2DHost::Paint(WebKit::WebCanvas* canvas,
origin.set(SkIntToScalar(plugin_rect.x()), SkIntToScalar(plugin_rect.y()));
SkPoint pixel_origin = origin;
- if (scale_ != 1.0f && scale_ > 0.0f) {
- float inverse_scale = 1.0f / scale_;
- pixel_origin.scale(inverse_scale);
- canvas->scale(scale_, scale_);
+
+ gfx::PointF resize_scale(GetResizeScale());
+ gfx::PointF scale(ScalePoint(resize_scale, scale_));
+ if ((scale.x() != 1.0f || scale.y() != 1.0f) &&
+ scale.x() > 0.0f && scale.y() > 0.0f) {
+ canvas->scale(scale.x(), scale.y());
+ pixel_origin.set(pixel_origin.x() * (1.0f / scale.x()),
+ pixel_origin.y() * (1.0f / scale.y()));
}
+ pixel_origin.offset(SkIntToScalar(plugin_offset_.x()),
+ SkIntToScalar(plugin_offset_.y()));
canvas->drawBitmap(image, pixel_origin.x(), pixel_origin.y(), &paint);
}
-void PepperGraphics2DHost::ViewWillInitiatePaint() {
-}
-
void PepperGraphics2DHost::ViewInitiatedPaint() {
}
@@ -402,6 +421,11 @@ void PepperGraphics2DHost::ViewFlushedPaint() {
}
}
+void PepperGraphics2DHost::DidChangeView(const ppapi::ViewData& view_data) {
+ gfx::Size old_plugin_size = current_plugin_size_;
+ current_plugin_size_ = PP_ToGfxSize(view_data.rect.size);
+}
+
void PepperGraphics2DHost::SetScale(float scale) {
scale_ = scale;
}
@@ -418,6 +442,27 @@ PPB_ImageData_Impl* PepperGraphics2DHost::ImageData() {
return image_data_.get();
}
+gfx::Size PepperGraphics2DHost::Size() const {
+ if (!image_data_)
+ return gfx::Size();
+ return gfx::Size(image_data_->width(), image_data_->height());
+}
+
+gfx::PointF PepperGraphics2DHost::GetResizeScale() const {
+ switch (resize_mode_) {
+ case PP_GRAPHICS2D_DEV_RESIZEMODE_DEFAULT:
+ return gfx::PointF(1.0f, 1.0f);
+ case PP_GRAPHICS2D_DEV_RESIZEMODE_STRETCH:
+ if (flushed_plugin_size_.IsEmpty())
+ return gfx::PointF(1.0f, 1.0f);
+ return gfx::PointF(
+ 1.0f * current_plugin_size_.width() / flushed_plugin_size_.width(),
+ 1.0f * current_plugin_size_.height() / flushed_plugin_size_.height());
+ }
+ NOTREACHED();
+ return gfx::PointF(1.0f, 1.0f);
+}
+
int32_t PepperGraphics2DHost::OnHostMsgPaintImageData(
ppapi::host::HostMessageContext* context,
const ppapi::HostResource& image_data,
@@ -510,7 +555,8 @@ int32_t PepperGraphics2DHost::OnHostMsgReplaceContents(
}
int32_t PepperGraphics2DHost::OnHostMsgFlush(
- ppapi::host::HostMessageContext* context) {
+ ppapi::host::HostMessageContext* context,
+ const ppapi::ViewData& view_data) {
// Don't allow more than one pending flush at a time.
if (HasPendingFlush())
return PP_ERROR_INPROGRESS;
@@ -518,10 +564,10 @@ int32_t PepperGraphics2DHost::OnHostMsgFlush(
PP_Resource old_image_data = 0;
flush_reply_context_ = context->MakeReplyMessageContext();
if (is_running_in_process_)
- return Flush(NULL);
+ return Flush(NULL, PP_ToGfxSize(view_data.rect.size));
// Reuse image data when running out of process.
- int32_t result = Flush(&old_image_data);
+ int32_t result = Flush(&old_image_data, PP_ToGfxSize(view_data.rect.size));
if (old_image_data) {
// If the Graphics2D has an old image data it's not using any more, send
@@ -547,6 +593,22 @@ int32_t PepperGraphics2DHost::OnHostMsgSetScale(
return PP_ERROR_BADARGUMENT;
}
+int32_t PepperGraphics2DHost::OnHostMsgSetOffset(
+ ppapi::host::HostMessageContext* context,
+ const PP_Point& offset) {
+ QueuedOperation operation(QueuedOperation::SET_OFFSET);
+ operation.offset = PP_ToGfxPoint(offset);
+ queued_operations_.push_back(operation);
+ return PP_OK;
+}
+
+int32_t PepperGraphics2DHost::OnHostMsgSetResizeMode(
+ ppapi::host::HostMessageContext* context,
+ PP_Graphics2D_Dev_ResizeMode resize_mode) {
+ resize_mode_ = resize_mode;
+ return PP_OK;
+}
+
int32_t PepperGraphics2DHost::OnHostMsgReadImageData(
ppapi::host::HostMessageContext* context,
PP_Resource image,
@@ -586,13 +648,15 @@ void PepperGraphics2DHost::AttachedToNewLayer() {
texture_mailbox_modified_ = true;
}
-int32_t PepperGraphics2DHost::Flush(PP_Resource* old_image_data) {
+int32_t PepperGraphics2DHost::Flush(PP_Resource* old_image_data,
+ const gfx::Size& flushed_plugin_size) {
bool done_replace_contents = false;
bool no_update_visible = true;
bool is_plugin_visible = true;
for (size_t i = 0; i < queued_operations_.size(); i++) {
QueuedOperation& operation = queued_operations_[i];
gfx::Rect op_rect;
+ gfx::Rect old_op_rect;
switch (operation.type) {
case QueuedOperation::PAINT:
ExecutePaintImageData(operation.paint_image.get(),
@@ -616,16 +680,28 @@ int32_t PepperGraphics2DHost::Flush(PP_Resource* old_image_data) {
done_replace_contents ? NULL : old_image_data);
done_replace_contents = true;
break;
+ case QueuedOperation::SET_OFFSET:
+ old_op_rect = gfx::Rect(plugin_offset_.x(), plugin_offset_.y(),
+ image_data_->width(), image_data_->height());
+ plugin_offset_ = operation.offset;
+ // The offset is applied below for |op_rect|.
+ op_rect = gfx::Rect(image_data_->width(), image_data_->height());
+ break;
}
+ op_rect.Offset(plugin_offset_.x(), plugin_offset_.y());
+
// For correctness with accelerated compositing, we must issue an invalidate
// on the full op_rect even if it is partially or completely off-screen.
// However, if we issue an invalidate for a clipped-out region, WebKit will
- // do nothing and we won't get any ViewWillInitiatePaint/ViewFlushedPaint
- // calls, leaving our callback stranded. So we still need to check whether
- // the repainted area is visible to determine how to deal with the callback.
- if (bound_instance_ && !op_rect.IsEmpty()) {
+ // do nothing and we won't get any ViewFlushedPaint calls, leaving our
+ // callback stranded. So we still need to check whether the repainted area
+ // is visible to determine how to deal with the callback.
+ if (bound_instance_ && (!op_rect.IsEmpty() || !old_op_rect.IsEmpty())) {
gfx::Point scroll_delta(operation.scroll_dx, operation.scroll_dy);
+ if (!ConvertToLogicalPixels(scale_, &old_op_rect, NULL)) {
+ NOTREACHED();
+ }
if (!ConvertToLogicalPixels(scale_,
&op_rect,
operation.type == QueuedOperation::SCROLL ?
@@ -639,23 +715,29 @@ int32_t PepperGraphics2DHost::Flush(PP_Resource* old_image_data) {
// Set |no_update_visible| to false if the change overlaps the visible
// area.
- gfx::Rect visible_changed_rect = gfx::IntersectRects(clip, op_rect);
- if (!visible_changed_rect.IsEmpty())
+ if (!gfx::IntersectRects(clip, op_rect).IsEmpty() ||
+ !gfx::IntersectRects(clip, old_op_rect).IsEmpty()) {
no_update_visible = false;
+ }
// Notify the plugin of the entire change (op_rect), even if it is
// partially or completely off-screen.
if (operation.type == QueuedOperation::SCROLL) {
bound_instance_->ScrollRect(scroll_delta.x(), scroll_delta.y(),
op_rect);
+ DCHECK(old_op_rect.IsEmpty());
} else {
- bound_instance_->InvalidateRect(op_rect);
+ if (!op_rect.IsEmpty())
+ bound_instance_->InvalidateRect(op_rect);
+ if (!old_op_rect.IsEmpty())
+ bound_instance_->InvalidateRect(old_op_rect);
}
texture_mailbox_modified_ = true;
}
}
queued_operations_.clear();
+ flushed_plugin_size_ = flushed_plugin_size;
if (!bound_instance_) {
// As promised in the API, we always schedule callback when unbound.
ScheduleOffscreenFlushAck();
@@ -762,7 +844,7 @@ void PepperGraphics2DHost::ScheduleOffscreenFlushAck() {
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&PepperGraphics2DHost::SendOffscreenFlushAck,
- weak_ptr_factory_.GetWeakPtr()),
+ AsWeakPtr()),
base::TimeDelta::FromMilliseconds(kOffscreenCallbackDelayMs));
}
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.h b/chromium/content/renderer/pepper/pepper_graphics_2d_host.h
index 7179398d11b..cda286a2df8 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.h
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.h
@@ -11,10 +11,13 @@
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
+#include "ppapi/c/dev/ppb_graphics_2d_dev.h"
#include "ppapi/c/ppb_graphics_2d.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
#include "third_party/WebKit/public/platform/WebCanvas.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/size.h"
namespace cc {
class SingleReleaseCallback;
@@ -22,10 +25,13 @@ class TextureMailbox;
}
namespace gfx {
-class Point;
class Rect;
}
+namespace ppapi {
+struct ViewData;
+}
+
namespace content {
class PepperPluginInstanceImpl;
@@ -36,11 +42,13 @@ class CONTENT_EXPORT PepperGraphics2DHost
: public ppapi::host::ResourceHost,
public base::SupportsWeakPtr<PepperGraphics2DHost> {
public:
- static PepperGraphics2DHost* Create(RendererPpapiHost* host,
- PP_Instance instance,
- PP_Resource resource,
- const PP_Size& size,
- PP_Bool is_always_opaque);
+ static PepperGraphics2DHost* Create(
+ RendererPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource,
+ const PP_Size& size,
+ PP_Bool is_always_opaque,
+ scoped_refptr<PPB_ImageData_Impl> backing_store);
virtual ~PepperGraphics2DHost();
@@ -58,7 +66,7 @@ class CONTENT_EXPORT PepperGraphics2DHost
// is already bound to a different instance, and nothing will happen.
bool BindToInstance(PepperPluginInstanceImpl* new_instance);
// Paints the current backing store to the web page.
- void Paint(WebKit::WebCanvas* canvas,
+ void Paint(blink::WebCanvas* canvas,
const gfx::Rect& plugin_rect,
const gfx::Rect& paint_rect);
@@ -69,21 +77,32 @@ class CONTENT_EXPORT PepperGraphics2DHost
// Notifications about the view's progress painting. See PluginInstance.
// These messages are used to send Flush callbacks to the plugin.
- void ViewWillInitiatePaint();
void ViewInitiatedPaint();
void ViewFlushedPaint();
+ void DidChangeView(const ppapi::ViewData& view_data);
+
void SetScale(float scale);
float GetScale() const;
bool IsAlwaysOpaque() const;
PPB_ImageData_Impl* ImageData();
+ gfx::Size Size() const;
+
+ // The amount to resize the backing store by when painting to the canvas.
+ // This is used to stretch the backing store when resizing the plugin element.
+ gfx::PointF GetResizeScale() const;
+ // The offset of the backing store into the plugin element.
+ gfx::Point plugin_offset() const { return plugin_offset_; }
private:
PepperGraphics2DHost(RendererPpapiHost* host,
PP_Instance instance,
PP_Resource resource);
- bool Init(int width, int height, bool is_always_opaque);
+ bool Init(int width,
+ int height,
+ bool is_always_opaque,
+ scoped_refptr<PPB_ImageData_Impl> backing_store);
int32_t OnHostMsgPaintImageData(ppapi::host::HostMessageContext* context,
const ppapi::HostResource& image_data,
@@ -96,16 +115,22 @@ class CONTENT_EXPORT PepperGraphics2DHost
const PP_Point& amount);
int32_t OnHostMsgReplaceContents(ppapi::host::HostMessageContext* context,
const ppapi::HostResource& image_data);
- int32_t OnHostMsgFlush(ppapi::host::HostMessageContext* context);
+ int32_t OnHostMsgFlush(ppapi::host::HostMessageContext* context,
+ const ppapi::ViewData& view_data);
int32_t OnHostMsgSetScale(ppapi::host::HostMessageContext* context,
float scale);
+ int32_t OnHostMsgSetOffset(ppapi::host::HostMessageContext* context,
+ const PP_Point& offset);
+ int32_t OnHostMsgSetResizeMode(ppapi::host::HostMessageContext* context,
+ PP_Graphics2D_Dev_ResizeMode resize_mode);
int32_t OnHostMsgReadImageData(ppapi::host::HostMessageContext* context,
PP_Resource image,
const PP_Point& top_left);
// If |old_image_data| is not NULL, a previous used ImageData object will be
// reused. This is used by ReplaceContents.
- int32_t Flush(PP_Resource* old_image_data);
+ int32_t Flush(PP_Resource* old_image_data,
+ const gfx::Size& flushed_plugin_size);
// Called internally to execute the different queued commands. The
// parameters to these functions will have already been validated. The last
@@ -143,7 +168,6 @@ class CONTENT_EXPORT PepperGraphics2DHost
gfx::Rect* op_rect,
gfx::Point* delta);
-
RendererPpapiHost* renderer_ppapi_host_;
scoped_refptr<PPB_ImageData_Impl> image_data_;
@@ -173,13 +197,27 @@ class CONTENT_EXPORT PepperGraphics2DHost
// DIP
float scale_;
- base::WeakPtrFactory<PepperGraphics2DHost> weak_ptr_factory_;
-
ppapi::host::ReplyMessageContext flush_reply_context_;
bool is_running_in_process_;
bool texture_mailbox_modified_;
+ bool is_using_texture_layer_;
+
+ // The offset into the plugin area at which to draw the contents of the
+ // graphics context.
+ gfx::Point plugin_offset_;
+
+ // The size of the plugin element from the plugin's perspective at the last
+ // time Flush() was called. Because the plugin runs in a separate process and
+ // the size of the plugin element in the renderer is updated asynchronously,
+ // it may believe that the plugin element is a different size to what it
+ // actually is.
+ gfx::Size flushed_plugin_size_;
+ // The current size of the plugin element.
+ gfx::Size current_plugin_size_;
+
+ PP_Graphics2D_Dev_ResizeMode resize_mode_;
friend class PepperGraphics2DHostTest;
DISALLOW_COPY_AND_ASSIGN(PepperGraphics2DHost);
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc
index 78a8fe01ae1..b17dfa71886 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc
@@ -5,10 +5,21 @@
#include "content/renderer/pepper/pepper_graphics_2d_host.h"
#include "base/basictypes.h"
+#include "base/message_loop/message_loop.h"
+#include "content/renderer/pepper/gfx_conversion.h"
+#include "content/renderer/pepper/mock_renderer_ppapi_host.h"
+#include "content/renderer/pepper/ppb_image_data_impl.h"
+#include "ppapi/shared_impl/ppb_view_shared.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/test_globals.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebCanvas.h"
+#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
+using blink::WebCanvas;
+
namespace content {
class PepperGraphics2DHostTest : public testing::Test {
@@ -18,6 +29,89 @@ class PepperGraphics2DHostTest : public testing::Test {
gfx::Point* delta) {
return PepperGraphics2DHost::ConvertToLogicalPixels(scale, op_rect, delta);
}
+
+ PepperGraphics2DHostTest()
+ : message_loop_(base::MessageLoop::TYPE_DEFAULT),
+ renderer_ppapi_host_(NULL, 12345) {}
+
+ virtual ~PepperGraphics2DHostTest() {
+ ppapi::ProxyAutoLock proxy_lock;
+ host_.reset();
+ }
+
+ void Init(PP_Instance instance,
+ const PP_Size& backing_store_size,
+ const PP_Rect& plugin_rect) {
+ renderer_view_data_.rect = plugin_rect;
+ PluginViewUpdated();
+ test_globals_.GetResourceTracker()->DidCreateInstance(instance);
+ scoped_refptr<PPB_ImageData_Impl> backing_store(
+ new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest()));
+ host_.reset(PepperGraphics2DHost::Create(
+ &renderer_ppapi_host_, instance, 12345, backing_store_size, PP_FALSE,
+ backing_store));
+ DCHECK(host_.get());
+ }
+
+ void PaintImageData(PPB_ImageData_Impl* image_data) {
+ ppapi::HostResource image_data_resource;
+ image_data_resource.SetHostResource(image_data->pp_instance(),
+ image_data->pp_resource());
+ host_->OnHostMsgPaintImageData(NULL, image_data_resource,
+ PP_Point(), false, PP_Rect());
+ }
+
+ void SetOffset(const PP_Point& point) {
+ host_->OnHostMsgSetOffset(NULL, point);
+ }
+
+ void Flush() {
+ ppapi::host::HostMessageContext context(
+ ppapi::proxy::ResourceMessageCallParams(host_->pp_resource(), 0));
+ host_->OnHostMsgFlush(&context, plugin_view_data_);
+ host_->ViewFlushedPaint();
+ host_->SendOffscreenFlushAck();
+ }
+
+ void PaintToWebCanvas(SkBitmap* bitmap) {
+ scoped_ptr<WebCanvas> canvas(new WebCanvas(*bitmap));
+ gfx::Rect plugin_rect(PP_ToGfxRect(renderer_view_data_.rect));
+ host_->Paint(canvas.get(), plugin_rect,
+ gfx::Rect(0, 0, plugin_rect.width(), plugin_rect.height()));
+ }
+
+ void DidChangeView(const PP_Rect& plugin_rect) {
+ renderer_view_data_.rect = plugin_rect;
+ host_->DidChangeView(renderer_view_data_);
+ }
+
+ void PluginViewUpdated() {
+ plugin_view_data_ = renderer_view_data_;
+ }
+
+ void SetResizeMode(PP_Graphics2D_Dev_ResizeMode resize_mode) {
+ host_->OnHostMsgSetResizeMode(NULL, resize_mode);
+ }
+
+ void ResetPageBitmap(SkBitmap* bitmap) {
+ PP_Rect plugin_rect = renderer_view_data_.rect;
+ int width = plugin_rect.point.x + plugin_rect.size.width;
+ int height = plugin_rect.point.y + plugin_rect.size.height;
+ if (bitmap->isNull() || bitmap->width() != width ||
+ bitmap->height() != height) {
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ bitmap->allocPixels();
+ }
+ bitmap->eraseColor(0);
+ }
+
+ private:
+ ppapi::ViewData renderer_view_data_;
+ ppapi::ViewData plugin_view_data_;
+ scoped_ptr<PepperGraphics2DHost> host_;
+ base::MessageLoop message_loop_;
+ MockRendererPpapiHost renderer_ppapi_host_;
+ ppapi::TestGlobals test_globals_;
};
TEST_F(PepperGraphics2DHostTest, ConvertToLogicalPixels) {
@@ -89,4 +183,212 @@ TEST_F(PepperGraphics2DHostTest, ConvertToLogicalPixels) {
}
}
+TEST_F(PepperGraphics2DHostTest, SetOffset) {
+ ppapi::ProxyAutoLock proxy_lock;
+
+ // Initialize the backing store.
+ PP_Instance instance = 12345;
+ PP_Size backing_store_size = { 300, 300 };
+ PP_Rect plugin_rect = PP_MakeRectFromXYWH(0, 0, 500, 500);
+ Init(instance, backing_store_size, plugin_rect);
+
+ // Paint the entire backing store red.
+ scoped_refptr<PPB_ImageData_Impl> image_data(
+ new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest()));
+ image_data->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(),
+ backing_store_size.width,
+ backing_store_size.height,
+ true);
+ {
+ ImageDataAutoMapper auto_mapper(image_data.get());
+ image_data->GetMappedBitmap()->eraseColor(
+ SkColorSetARGBMacro(255, 255, 0, 0));
+ }
+ PaintImageData(image_data.get());
+ Flush();
+
+ // Set up the actual and expected bitmaps/canvas.
+ SkBitmap actual_bitmap;
+ ResetPageBitmap(&actual_bitmap);
+ SkBitmap expected_bitmap;
+ ResetPageBitmap(&expected_bitmap);
+
+ // Paint the backing store to the canvas.
+ PaintToWebCanvas(&actual_bitmap);
+ expected_bitmap.eraseArea(
+ SkIRect::MakeWH(backing_store_size.width, backing_store_size.height),
+ SkColorSetARGBMacro(255, 255, 0, 0));
+ EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
+ actual_bitmap.getAddr(0, 0),
+ expected_bitmap.getSize()), 0);
+
+ // Set the offset.
+ PP_Point offset = { 20, 20 };
+ SetOffset(offset);
+ ResetPageBitmap(&actual_bitmap);
+ PaintToWebCanvas(&actual_bitmap);
+ // No flush has occurred so the result should be the same.
+ EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
+ actual_bitmap.getAddr(0, 0),
+ expected_bitmap.getSize()), 0);
+
+ // Flush the offset and the location of the rectangle should have shifted.
+ Flush();
+ ResetPageBitmap(&actual_bitmap);
+ PaintToWebCanvas(&actual_bitmap);
+ ResetPageBitmap(&expected_bitmap);
+ expected_bitmap.eraseArea(
+ SkIRect::MakeXYWH(offset.x, offset.y,
+ backing_store_size.width, backing_store_size.height),
+ SkColorSetARGBMacro(255, 255, 0, 0));
+ EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
+ actual_bitmap.getAddr(0, 0),
+ expected_bitmap.getSize()), 0);
+}
+
+TEST_F(PepperGraphics2DHostTest, ResizeModeDefault) {
+ ppapi::ProxyAutoLock proxy_lock;
+
+ // Initialize the backing store.
+ PP_Instance instance = 12345;
+ PP_Size backing_store_size = { 300, 300 };
+ PP_Rect plugin_rect = PP_MakeRectFromXYWH(0, 0, 300, 300);
+ Init(instance, backing_store_size, plugin_rect);
+
+ // Paint the entire backing store red.
+ scoped_refptr<PPB_ImageData_Impl> image_data(
+ new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest()));
+ image_data->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(),
+ backing_store_size.width,
+ backing_store_size.height,
+ true);
+ {
+ ImageDataAutoMapper auto_mapper(image_data.get());
+ image_data->GetMappedBitmap()->eraseColor(
+ SkColorSetARGBMacro(255, 255, 0, 0));
+ }
+ PaintImageData(image_data.get());
+ Flush();
+
+ // Set up the actual and expected bitmaps/canvas.
+ SkBitmap actual_bitmap;
+ ResetPageBitmap(&actual_bitmap);
+ SkBitmap expected_bitmap;
+ ResetPageBitmap(&expected_bitmap);
+
+ // Paint the backing store to the canvas.
+ PaintToWebCanvas(&actual_bitmap);
+ expected_bitmap.eraseArea(
+ SkIRect::MakeWH(backing_store_size.width, backing_store_size.height),
+ SkColorSetARGBMacro(255, 255, 0, 0));
+ EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
+ actual_bitmap.getAddr(0, 0),
+ expected_bitmap.getSize()), 0);
+
+ // Resize the plugin.
+ DidChangeView(PP_MakeRectFromXYWH(0, 0, 500, 500));
+ // Paint the backing store again, it shouldn't have changed.
+ ResetPageBitmap(&actual_bitmap);
+ PaintToWebCanvas(&actual_bitmap);
+ ResetPageBitmap(&expected_bitmap);
+ expected_bitmap.eraseArea(
+ SkIRect::MakeWH(backing_store_size.width, backing_store_size.height),
+ SkColorSetARGBMacro(255, 255, 0, 0));
+ EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
+ actual_bitmap.getAddr(0, 0),
+ expected_bitmap.getSize()), 0);
+
+ // Let the plugin know about the updated view and reflush the original image.
+ PluginViewUpdated();
+ PaintImageData(image_data.get());
+ Flush();
+ // Paint the backing store again, it shouldn't have changed.
+ ResetPageBitmap(&actual_bitmap);
+ PaintToWebCanvas(&actual_bitmap);
+ EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
+ actual_bitmap.getAddr(0, 0),
+ expected_bitmap.getSize()), 0);
+}
+
+TEST_F(PepperGraphics2DHostTest, ResizeModeStretch) {
+ ppapi::ProxyAutoLock proxy_lock;
+
+ // Initialize the backing store.
+ PP_Instance instance = 12345;
+ PP_Size backing_store_size = { 300, 300 };
+ PP_Rect plugin_rect = PP_MakeRectFromXYWH(0, 0, 300, 300);
+ Init(instance, backing_store_size, plugin_rect);
+ SetResizeMode(PP_GRAPHICS2D_DEV_RESIZEMODE_STRETCH);
+
+ // Paint the entire backing store red.
+ scoped_refptr<PPB_ImageData_Impl> image_data(
+ new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest()));
+ image_data->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(),
+ backing_store_size.width,
+ backing_store_size.height,
+ true);
+ {
+ ImageDataAutoMapper auto_mapper(image_data.get());
+ image_data->GetMappedBitmap()->eraseColor(
+ SkColorSetARGBMacro(255, 255, 0, 0));
+ }
+ PaintImageData(image_data.get());
+ Flush();
+
+ // Set up the actual and expected bitmaps/canvas.
+ SkBitmap actual_bitmap;
+ ResetPageBitmap(&actual_bitmap);
+ SkBitmap expected_bitmap;
+ ResetPageBitmap(&expected_bitmap);
+
+ // Paint the backing store to the canvas.
+ PaintToWebCanvas(&actual_bitmap);
+ expected_bitmap.eraseArea(
+ SkIRect::MakeWH(backing_store_size.width, backing_store_size.height),
+ SkColorSetARGBMacro(255, 255, 0, 0));
+ EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
+ actual_bitmap.getAddr(0, 0),
+ expected_bitmap.getSize()), 0);
+
+ // Resize the plugin.
+ plugin_rect = PP_MakeRectFromXYWH(0, 0, 500, 500);
+ DidChangeView(plugin_rect);
+ ResetPageBitmap(&actual_bitmap);
+ ResetPageBitmap(&expected_bitmap);
+
+ // Paint the backing store again, it should be stretched even though no new
+ // image has been flushed.
+ PaintToWebCanvas(&actual_bitmap);
+ expected_bitmap.eraseColor(SkColorSetARGBMacro(255, 255, 0, 0));
+ EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
+ actual_bitmap.getAddr(0, 0),
+ expected_bitmap.getSize()), 0);
+
+ // Re-flush the original image data and paint it, it should be stretched as
+ // well.
+ PaintImageData(image_data.get());
+ Flush();
+ ResetPageBitmap(&actual_bitmap);
+ PaintToWebCanvas(&actual_bitmap);
+ EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
+ actual_bitmap.getAddr(0, 0),
+ expected_bitmap.getSize()), 0);
+
+ // Let the plugin know about the updated view.
+ PluginViewUpdated();
+
+ // Now flush the image data again, it should be at the original size.
+ PaintImageData(image_data.get());
+ Flush();
+ ResetPageBitmap(&actual_bitmap);
+ PaintToWebCanvas(&actual_bitmap);
+ ResetPageBitmap(&expected_bitmap);
+ expected_bitmap.eraseArea(
+ SkIRect::MakeWH(backing_store_size.width, backing_store_size.height),
+ SkColorSetARGBMacro(255, 255, 0, 0));
+ EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0),
+ actual_bitmap.getAddr(0, 0),
+ expected_bitmap.getSize()), 0);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_hung_plugin_filter.cc b/chromium/content/renderer/pepper/pepper_hung_plugin_filter.cc
index 10282125e0c..ba4af0e22bb 100644
--- a/chromium/content/renderer/pepper/pepper_hung_plugin_filter.cc
+++ b/chromium/content/renderer/pepper/pepper_hung_plugin_filter.cc
@@ -6,7 +6,7 @@
#include "base/bind.h"
#include "content/child/child_process.h"
-#include "content/common/view_messages.h"
+#include "content/common/frame_messages.h"
#include "content/renderer/render_thread_impl.h"
namespace content {
@@ -26,10 +26,10 @@ const int kBlockedHardThresholdSec = kHungThresholdSec * 1.5;
PepperHungPluginFilter::PepperHungPluginFilter(
const base::FilePath& plugin_path,
- int view_routing_id,
+ int frame_routing_id,
int plugin_child_id)
: plugin_path_(plugin_path),
- view_routing_id_(view_routing_id),
+ frame_routing_id_(frame_routing_id),
plugin_child_id_(plugin_child_id),
filter_(RenderThread::Get()->GetSyncMessageFilter()),
io_loop_(ChildProcess::current()->io_message_loop_proxy()),
@@ -151,8 +151,8 @@ void PepperHungPluginFilter::OnHangTimer() {
}
void PepperHungPluginFilter::SendHungMessage(bool is_hung) {
- filter_->Send(new ViewHostMsg_PepperPluginHung(
- view_routing_id_, plugin_child_id_, plugin_path_, is_hung));
+ filter_->Send(new FrameHostMsg_PepperPluginHung(
+ frame_routing_id_, plugin_child_id_, plugin_path_, is_hung));
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h b/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h
index 9f8bad3e51f..ee83674800f 100644
--- a/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h
+++ b/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h
@@ -30,12 +30,12 @@ namespace content {
class PepperHungPluginFilter
: public ppapi::proxy::HostDispatcher::SyncMessageStatusReceiver {
public:
- // The |view_routing_id| is the ID of the render_view so that this class can
- // send messages to the browser via that view's route. The |plugin_child_id|
+ // The |frame_routing_id| is the ID of the render_frame so that this class can
+ // send messages to the browser via that frame's route. The |plugin_child_id|
// is the ID in the browser process of the pepper plugin process host. We use
// this to identify the proper plugin process to terminate.
PepperHungPluginFilter(const base::FilePath& plugin_path,
- int view_routing_id,
+ int frame_routing_id,
int plugin_child_id);
// SyncMessageStatusReceiver implementation.
@@ -75,7 +75,7 @@ class PepperHungPluginFilter
base::Lock lock_;
base::FilePath plugin_path_;
- int view_routing_id_;
+ int frame_routing_id_;
int plugin_child_id_;
// Used to post messages to the renderer <-> browser message channel from
diff --git a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
index cb10ff269c8..23ed785ac5f 100644
--- a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
+++ b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
@@ -16,7 +16,6 @@
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
#include "ppapi/host/ppapi_host.h"
-#include "ppapi/proxy/ext_crx_file_system_private_resource.h"
#include "ppapi/proxy/file_chooser_resource.h"
#include "ppapi/proxy/file_io_resource.h"
#include "ppapi/proxy/file_ref_resource.h"
diff --git a/chromium/content/renderer/pepper/pepper_in_process_router.cc b/chromium/content/renderer/pepper/pepper_in_process_router.cc
index 1446426dd77..45755e1d4d8 100644
--- a/chromium/content/renderer/pepper/pepper_in_process_router.cc
+++ b/chromium/content/renderer/pepper/pepper_in_process_router.cc
@@ -7,8 +7,8 @@
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "content/public/renderer/render_thread.h"
-#include "content/public/renderer/render_view.h"
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
+#include "content/renderer/render_frame_impl.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
#include "ppapi/proxy/ppapi_messages.h"
@@ -65,9 +65,9 @@ IPC::Sender* PepperInProcessRouter::GetRendererToPluginSender() {
ppapi::proxy::Connection PepperInProcessRouter::GetPluginConnection(
PP_Instance instance) {
int routing_id = 0;
- RenderView* view = host_impl_->GetRenderViewForInstance(instance);
- if (view)
- routing_id = view->GetRoutingID();
+ RenderFrame* frame = host_impl_->GetRenderFrameForInstance(instance);
+ if (frame)
+ routing_id = frame->GetRoutingID();
return ppapi::proxy::Connection(browser_channel_.get(),
plugin_to_host_router_.get(),
routing_id);
diff --git a/chromium/content/renderer/pepper/pepper_media_device_manager.cc b/chromium/content/renderer/pepper/pepper_media_device_manager.cc
index 35318163012..9704980e3a1 100644
--- a/chromium/content/renderer/pepper/pepper_media_device_manager.cc
+++ b/chromium/content/renderer/pepper/pepper_media_device_manager.cc
@@ -45,6 +45,7 @@ PepperMediaDeviceManager::~PepperMediaDeviceManager() {
int PepperMediaDeviceManager::EnumerateDevices(
PP_DeviceType_Dev type,
+ const GURL& document_url,
const EnumerateDevicesCallback& callback) {
enumerate_callbacks_[next_id_] = callback;
int request_id = next_id_++;
@@ -53,14 +54,15 @@ int PepperMediaDeviceManager::EnumerateDevices(
GetRenderViewImpl()->media_stream_dispatcher()->EnumerateDevices(
request_id, AsWeakPtr(),
PepperMediaDeviceManager::FromPepperDeviceType(type),
- GURL());
+ document_url.GetOrigin());
#else
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(
- &PepperMediaDeviceManager::OnDevicesEnumerationFailed,
+ &PepperMediaDeviceManager::OnDevicesEnumerated,
AsWeakPtr(),
- request_id));
+ request_id,
+ StreamDeviceInfoArray()));
#endif
return request_id;
@@ -152,18 +154,30 @@ void PepperMediaDeviceManager::OnStreamGenerated(
void PepperMediaDeviceManager::OnStreamGenerationFailed(int request_id) {
}
-void PepperMediaDeviceManager::OnStopGeneratedStream(const std::string& label) {
+void PepperMediaDeviceManager::OnDeviceStopped(
+ const std::string& label,
+ const StreamDeviceInfo& device_info) {
}
void PepperMediaDeviceManager::OnDevicesEnumerated(
int request_id,
const StreamDeviceInfoArray& device_array) {
- NotifyDevicesEnumerated(request_id, true, device_array);
-}
+ EnumerateCallbackMap::iterator iter = enumerate_callbacks_.find(request_id);
+ if (iter == enumerate_callbacks_.end()) {
+ // This might be enumerated result sent before StopEnumerateDevices is
+ // called since EnumerateDevices is persistent request.
+ return;
+ }
+
+ EnumerateDevicesCallback callback = iter->second;
-void PepperMediaDeviceManager::OnDevicesEnumerationFailed(
- int request_id) {
- NotifyDevicesEnumerated(request_id, false, StreamDeviceInfoArray());
+ std::vector<ppapi::DeviceRefData> devices;
+ devices.reserve(device_array.size());
+ for (StreamDeviceInfoArray::const_iterator info =
+ device_array.begin(); info != device_array.end(); ++info) {
+ devices.push_back(FromStreamDeviceInfo(*info));
+ }
+ callback.Run(request_id, devices);
}
void PepperMediaDeviceManager::OnDeviceOpened(
@@ -209,30 +223,6 @@ PP_DeviceType_Dev PepperMediaDeviceManager::FromMediaStreamType(
}
}
-void PepperMediaDeviceManager::NotifyDevicesEnumerated(
- int request_id,
- bool succeeded,
- const StreamDeviceInfoArray& device_array) {
- EnumerateCallbackMap::iterator iter = enumerate_callbacks_.find(request_id);
- if (iter == enumerate_callbacks_.end()) {
- // This might be enumerated result sent before StopEnumerateDevices is
- // called since EnumerateDevices is persistent request.
- return;
- }
-
- EnumerateDevicesCallback callback = iter->second;
-
- std::vector<ppapi::DeviceRefData> devices;
- if (succeeded) {
- devices.reserve(device_array.size());
- for (StreamDeviceInfoArray::const_iterator info =
- device_array.begin(); info != device_array.end(); ++info) {
- devices.push_back(FromStreamDeviceInfo(*info));
- }
- }
- callback.Run(request_id, succeeded, devices);
-}
-
void PepperMediaDeviceManager::NotifyDeviceOpened(
int request_id,
bool succeeded,
diff --git a/chromium/content/renderer/pepper/pepper_media_device_manager.h b/chromium/content/renderer/pepper/pepper_media_device_manager.h
index 67d8976e0d4..ff67101d4a9 100644
--- a/chromium/content/renderer/pepper/pepper_media_device_manager.h
+++ b/chromium/content/renderer/pepper/pepper_media_device_manager.h
@@ -29,6 +29,7 @@ class PepperMediaDeviceManager
// PepperDeviceEnumerationHostHelper::Delegate implementation:
virtual int EnumerateDevices(
PP_DeviceType_Dev type,
+ const GURL& document_url,
const EnumerateDevicesCallback& callback) OVERRIDE;
virtual void StopEnumerateDevices(int request_id) OVERRIDE;
@@ -60,11 +61,11 @@ class PepperMediaDeviceManager
const StreamDeviceInfoArray& audio_device_array,
const StreamDeviceInfoArray& video_device_array) OVERRIDE;
virtual void OnStreamGenerationFailed(int request_id) OVERRIDE;
- virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE;
+ virtual void OnDeviceStopped(const std::string& label,
+ const StreamDeviceInfo& device_info) OVERRIDE;
virtual void OnDevicesEnumerated(
int request_id,
const StreamDeviceInfoArray& device_array) OVERRIDE;
- virtual void OnDevicesEnumerationFailed(int request_id) OVERRIDE;
virtual void OnDeviceOpened(
int request_id,
const std::string& label,
@@ -78,11 +79,6 @@ class PepperMediaDeviceManager
private:
PepperMediaDeviceManager(RenderView* render_view);
- void NotifyDevicesEnumerated(
- int request_id,
- bool succeeded,
- const StreamDeviceInfoArray& device_array);
-
void NotifyDeviceOpened(int request_id,
bool succeeded,
const std::string& label);
diff --git a/chromium/content/renderer/pepper/pepper_platform_context_3d.cc b/chromium/content/renderer/pepper/pepper_platform_context_3d.cc
index e080e16bd2d..b9fd07b67d5 100644
--- a/chromium/content/renderer/pepper/pepper_platform_context_3d.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_context_3d.cc
@@ -11,13 +11,10 @@
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/gles2_cmd_helper.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
-#include "gpu/ipc/command_buffer_proxy.h"
#include "ppapi/c/pp_graphics_3d.h"
#include "ui/gl/gpu_preference.h"
#include "url/gurl.h"
-#ifdef ENABLE_GPU
-
namespace content {
PlatformContext3D::PlatformContext3D()
@@ -134,6 +131,10 @@ gpu::CommandBuffer* PlatformContext3D::GetCommandBuffer() {
return command_buffer_;
}
+gpu::GpuControl* PlatformContext3D::GetGpuControl() {
+ return command_buffer_;
+}
+
int PlatformContext3D::GetCommandBufferRouteId() {
DCHECK(command_buffer_);
return command_buffer_->GetRouteID();
@@ -148,8 +149,8 @@ void PlatformContext3D::SetOnConsoleMessageCallback(
console_message_callback_ = task;
}
-bool PlatformContext3D::Echo(const base::Closure& task) {
- return command_buffer_->Echo(task);
+void PlatformContext3D::Echo(const base::Closure& task) {
+ command_buffer_->Echo(task);
}
void PlatformContext3D::OnContextLost() {
@@ -167,5 +168,3 @@ void PlatformContext3D::OnConsoleMessage(const std::string& msg, int id) {
}
} // namespace content
-
-#endif // ENABLE_GPU
diff --git a/chromium/content/renderer/pepper/pepper_platform_context_3d.h b/chromium/content/renderer/pepper/pepper_platform_context_3d.h
index 842871a45fd..2520bbd65da 100644
--- a/chromium/content/renderer/pepper/pepper_platform_context_3d.h
+++ b/chromium/content/renderer/pepper/pepper_platform_context_3d.h
@@ -12,8 +12,6 @@
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "gpu/command_buffer/common/mailbox.h"
-#ifdef ENABLE_GPU
-
class CommandBufferProxy;
namespace gpu {
class CommandBuffer;
@@ -43,6 +41,9 @@ class PlatformContext3D {
// destroyed.
gpu::CommandBuffer* GetCommandBuffer();
+ // Returns the GpuControl class that services out-of-band messages.
+ gpu::GpuControl* GetGpuControl();
+
// If the command buffer is routed in the GPU channel, return the route id.
// Otherwise return 0.
int GetCommandBufferRouteId();
@@ -58,7 +59,7 @@ class PlatformContext3D {
void SetOnConsoleMessageCallback(const ConsoleMessageCallback& callback);
// Run the callback once the channel has been flushed.
- bool Echo(const base::Closure& task);
+ void Echo(const base::Closure& task);
private:
bool InitRaw();
@@ -76,6 +77,4 @@ class PlatformContext3D {
} // namespace content
-#endif // ENABLE_GPU
-
#endif // CONTENT_RENDERER_PEPPER_PEPPER_PLATFORM_CONTEXT_3D_H_
diff --git a/chromium/content/renderer/pepper/pepper_platform_video_capture.cc b/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
index 86ce45d8453..dc58ad44e68 100644
--- a/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
@@ -46,7 +46,7 @@ PepperPlatformVideoCapture::PepperPlatformVideoCapture(
void PepperPlatformVideoCapture::StartCapture(
media::VideoCapture::EventHandler* handler,
- const media::VideoCaptureCapability& capability) {
+ const media::VideoCaptureParams& params) {
DCHECK(handler == handler_);
if (unbalanced_start_)
@@ -55,7 +55,7 @@ void PepperPlatformVideoCapture::StartCapture(
if (video_capture_) {
unbalanced_start_ = true;
AddRef(); // Will be balanced in OnRemoved().
- video_capture_->StartCapture(handler_proxy_.get(), capability);
+ video_capture_->StartCapture(handler_proxy_.get(), params);
}
}
@@ -75,14 +75,6 @@ bool PepperPlatformVideoCapture::CaptureStarted() {
return handler_proxy_->state().started;
}
-int PepperPlatformVideoCapture::CaptureWidth() {
- return handler_proxy_->state().width;
-}
-
-int PepperPlatformVideoCapture::CaptureHeight() {
- return handler_proxy_->state().height;
-}
-
int PepperPlatformVideoCapture::CaptureFrameRate() {
return handler_proxy_->state().frame_rate;
}
@@ -146,13 +138,6 @@ void PepperPlatformVideoCapture::OnFrameReady(
handler_->OnFrameReady(capture, frame);
}
-void PepperPlatformVideoCapture::OnDeviceInfoReceived(
- VideoCapture* capture,
- const media::VideoCaptureParams& device_info) {
- if (handler_)
- handler_->OnDeviceInfoReceived(capture, device_info);
-}
-
PepperPlatformVideoCapture::~PepperPlatformVideoCapture() {
DCHECK(!video_capture_);
DCHECK(label_.empty());
diff --git a/chromium/content/renderer/pepper/pepper_platform_video_capture.h b/chromium/content/renderer/pepper/pepper_platform_video_capture.h
index 5ecde2e73de..609eaa34e11 100644
--- a/chromium/content/renderer/pepper/pepper_platform_video_capture.h
+++ b/chromium/content/renderer/pepper/pepper_platform_video_capture.h
@@ -42,11 +42,9 @@ class PepperPlatformVideoCapture
// media::VideoCapture implementation.
virtual void StartCapture(
media::VideoCapture::EventHandler* handler,
- const media::VideoCaptureCapability& capability) OVERRIDE;
+ const media::VideoCaptureParams& params) OVERRIDE;
virtual void StopCapture(media::VideoCapture::EventHandler* handler) OVERRIDE;
virtual bool CaptureStarted() OVERRIDE;
- virtual int CaptureWidth() OVERRIDE;
- virtual int CaptureHeight() OVERRIDE;
virtual int CaptureFrameRate() OVERRIDE;
// media::VideoCapture::EventHandler implementation
@@ -58,9 +56,6 @@ class PepperPlatformVideoCapture
virtual void OnFrameReady(
VideoCapture* capture,
const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
- virtual void OnDeviceInfoReceived(
- VideoCapture* capture,
- const media::VideoCaptureParams& device_info) OVERRIDE;
protected:
friend class base::RefCounted<PepperPlatformVideoCapture>;
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
index f8b2cfface3..c6d6582132c 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -45,8 +45,10 @@
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
#include "content/renderer/pepper/url_request_info_util.h"
#include "content/renderer/pepper/url_response_info_util.h"
+#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
+#include "content/renderer/render_widget.h"
#include "content/renderer/render_widget_fullscreen_pepper.h"
#include "content/renderer/sad_plugin.h"
#include "media/base/audio_hardware_config.h"
@@ -87,6 +89,7 @@
#include "printing/units.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/platform_device.h"
+#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "third_party/WebKit/public/platform/WebGamepads.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
@@ -94,7 +97,6 @@
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/web/WebBindings.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
-#include "third_party/WebKit/public/web/WebCursorInfo.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
@@ -117,6 +119,10 @@
#include "v8/include/v8.h"
#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
+#if defined(OS_CHROMEOS)
+#include "ui/events/keycodes/keyboard_codes_posix.h"
+#endif
+
#if defined(OS_MACOSX)
#include "printing/metafile_impl.h"
#endif // defined(OS_MACOSX)
@@ -148,27 +154,27 @@ using ppapi::thunk::PPB_ImageData_API;
using ppapi::Var;
using ppapi::ArrayBufferVar;
using ppapi::ViewData;
-using WebKit::WebBindings;
-using WebKit::WebCanvas;
-using WebKit::WebCursorInfo;
-using WebKit::WebDocument;
-using WebKit::WebElement;
-using WebKit::WebFrame;
-using WebKit::WebInputEvent;
-using WebKit::WebPlugin;
-using WebKit::WebPluginContainer;
-using WebKit::WebPrintParams;
-using WebKit::WebPrintScalingOption;
-using WebKit::WebScopedUserGesture;
-using WebKit::WebString;
-using WebKit::WebURLError;
-using WebKit::WebURLLoader;
-using WebKit::WebURLLoaderClient;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
-using WebKit::WebUserGestureIndicator;
-using WebKit::WebUserGestureToken;
-using WebKit::WebView;
+using blink::WebBindings;
+using blink::WebCanvas;
+using blink::WebCursorInfo;
+using blink::WebDocument;
+using blink::WebElement;
+using blink::WebFrame;
+using blink::WebInputEvent;
+using blink::WebPlugin;
+using blink::WebPluginContainer;
+using blink::WebPrintParams;
+using blink::WebPrintScalingOption;
+using blink::WebScopedUserGesture;
+using blink::WebString;
+using blink::WebURLError;
+using blink::WebURLLoader;
+using blink::WebURLLoaderClient;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
+using blink::WebUserGestureIndicator;
+using blink::WebUserGestureToken;
+using blink::WebView;
namespace content {
@@ -298,20 +304,20 @@ COMPILE_ASSERT_MATCHING_ENUM(TypeGrabbing, PP_MOUSECURSOR_TYPE_GRABBING);
// Do not assert WebCursorInfo::TypeCustom == PP_CURSORTYPE_CUSTOM;
// PP_CURSORTYPE_CUSTOM is pinned to allow new cursor types.
-COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM(WebKit::WebPrintScalingOptionNone,
+COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM(blink::WebPrintScalingOptionNone,
PP_PRINTSCALINGOPTION_NONE);
COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM(
- WebKit::WebPrintScalingOptionFitToPrintableArea,
+ blink::WebPrintScalingOptionFitToPrintableArea,
PP_PRINTSCALINGOPTION_FIT_TO_PRINTABLE_AREA);
COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM(
- WebKit::WebPrintScalingOptionSourceSize, PP_PRINTSCALINGOPTION_SOURCE_SIZE);
+ blink::WebPrintScalingOptionSourceSize, PP_PRINTSCALINGOPTION_SOURCE_SIZE);
// Sets |*security_origin| to be the WebKit security origin associated with the
// document containing the given plugin instance. On success, returns true. If
// the instance is invalid, returns false and |*security_origin| will be
// unchanged.
bool SecurityOriginForInstance(PP_Instance instance_id,
- WebKit::WebSecurityOrigin* security_origin) {
+ blink::WebSecurityOrigin* security_origin) {
PepperPluginInstanceImpl* instance =
HostGlobals::Get()->GetInstance(instance_id);
if (!instance)
@@ -333,6 +339,33 @@ scoped_ptr<const char*[]> StringVectorToArgArray(
return array.Pass();
}
+// Returns true if this is a "system reserved" key which should not be sent to
+// a plugin. Some poorly behaving plugins (like Flash) incorrectly report that
+// they handle all keys sent to them. This can prevent keystrokes from working
+// for things like screen brightness and volume control.
+bool IsReservedSystemInputEvent(const blink::WebInputEvent& event) {
+#if defined(OS_CHROMEOS)
+ if (event.type != WebInputEvent::KeyDown &&
+ event.type != WebInputEvent::KeyUp)
+ return false;
+ const blink::WebKeyboardEvent& key_event =
+ static_cast<const blink::WebKeyboardEvent&>(event);
+ switch (key_event.windowsKeyCode) {
+ case ui::VKEY_BRIGHTNESS_DOWN:
+ case ui::VKEY_BRIGHTNESS_UP:
+ case ui::VKEY_KBD_BRIGHTNESS_DOWN:
+ case ui::VKEY_KBD_BRIGHTNESS_UP:
+ case ui::VKEY_VOLUME_MUTE:
+ case ui::VKEY_VOLUME_DOWN:
+ case ui::VKEY_VOLUME_UP:
+ return true;
+ default:
+ return false;
+ }
+#endif // defined(OS_CHROMEOS)
+ return false;
+}
+
class PluginInstanceLockTarget : public MouseLockDispatcher::LockTarget {
public:
PluginInstanceLockTarget(PepperPluginInstanceImpl* plugin)
@@ -347,7 +380,7 @@ class PluginInstanceLockTarget : public MouseLockDispatcher::LockTarget {
}
virtual bool HandleMouseLockedInputEvent(
- const WebKit::WebMouseEvent &event) OVERRIDE {
+ const blink::WebMouseEvent &event) OVERRIDE {
plugin_->HandleMouseLockedInputEvent(event);
return true;
}
@@ -361,7 +394,7 @@ class PluginInstanceLockTarget : public MouseLockDispatcher::LockTarget {
// static
PepperPluginInstanceImpl* PepperPluginInstanceImpl::Create(
- RenderViewImpl* render_view,
+ RenderFrameImpl* render_frame,
PluginModule* module,
WebPluginContainer* container,
const GURL& plugin_url) {
@@ -371,7 +404,7 @@ PepperPluginInstanceImpl* PepperPluginInstanceImpl::Create(
PPP_Instance_Combined::Create(get_plugin_interface_func);
if (!ppp_instance_combined)
return NULL;
- return new PepperPluginInstanceImpl(render_view, module,
+ return new PepperPluginInstanceImpl(render_frame, module,
ppp_instance_combined, container,
plugin_url);
}
@@ -435,19 +468,19 @@ PPB_Gamepad_API* PepperPluginInstanceImpl::GamepadImpl::AsPPB_Gamepad_API() {
void PepperPluginInstanceImpl::GamepadImpl::Sample(
PP_Instance instance,
PP_GamepadsSampleData* data) {
- WebKit::WebGamepads webkit_data;
+ blink::WebGamepads webkit_data;
RenderThreadImpl::current()->SampleGamepads(&webkit_data);
ConvertWebKitGamepadData(
- *reinterpret_cast<const ppapi::WebKitGamepads*>(&webkit_data), data);
+ bit_cast<ppapi::WebKitGamepads>(webkit_data), data);
}
PepperPluginInstanceImpl::PepperPluginInstanceImpl(
- RenderViewImpl* render_view,
+ RenderFrameImpl* render_frame,
PluginModule* module,
ppapi::PPP_Instance_Combined* instance_interface,
WebPluginContainer* container,
const GURL& plugin_url)
- : render_view_(render_view),
+ : render_frame_(render_frame),
module_(module),
instance_interface_(instance_interface),
pp_instance_(0),
@@ -456,7 +489,6 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
plugin_url_(plugin_url),
full_frame_(false),
sent_initial_did_change_view_(false),
- view_change_weak_ptr_factory_(this),
bound_graphics_2d_platform_(NULL),
has_webkit_focus_(false),
has_content_area_focus_(false),
@@ -493,25 +525,28 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
document_loader_(NULL),
external_document_load_(false),
npp_(new NPP_t),
- isolate_(v8::Isolate::GetCurrent()) {
+ isolate_(v8::Isolate::GetCurrent()),
+ is_deleted_(false),
+ view_change_weak_ptr_factory_(this),
+ weak_factory_(this) {
pp_instance_ = HostGlobals::Get()->AddInstance(this);
memset(&current_print_settings_, 0, sizeof(current_print_settings_));
module_->InstanceCreated(this);
- if (render_view) { // NULL in tests
- render_view->PepperInstanceCreated(this);
- view_data_.is_page_visible = !render_view->is_hidden();
+ if (render_frame) { // NULL in tests
+ render_frame->PepperInstanceCreated(this);
+ view_data_.is_page_visible = !render_frame_->GetRenderWidget()->is_hidden();
// Set the initial focus.
- SetContentAreaFocus(render_view_->has_focus());
+ SetContentAreaFocus(render_frame_->GetRenderWidget()->has_focus());
if (!module_->IsProxied()) {
PepperBrowserConnection* browser_connection =
- PepperBrowserConnection::Get(render_view_);
+ PepperBrowserConnection::Get(render_frame_);
browser_connection->DidCreateInProcessInstance(
pp_instance(),
- render_view_->GetRoutingID(),
+ render_frame_->render_view()->GetRoutingID(),
container_->element().document().url(),
GetPluginURL());
}
@@ -542,12 +577,12 @@ PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
if (TrackedCallback::IsPending(lock_mouse_callback_))
lock_mouse_callback_->Abort();
- if (render_view_)
- render_view_->PepperInstanceDeleted(this);
+ if (render_frame_)
+ render_frame_->PepperInstanceDeleted(this);
- if (!module_->IsProxied() && render_view_) {
+ if (!module_->IsProxied() && render_frame_) {
PepperBrowserConnection* browser_connection =
- PepperBrowserConnection::Get(render_view_);
+ PepperBrowserConnection::Get(render_frame_);
browser_connection->DidDeleteInProcessInstance(pp_instance());
}
@@ -569,6 +604,8 @@ PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
// returned, then it needs to keep its own reference on the stack.
void PepperPluginInstanceImpl::Delete() {
+ is_deleted_ = true;
+
// Keep a reference on the stack. See NOTE above.
scoped_refptr<PepperPluginInstanceImpl> ref(this);
// Force the MessageChannel to release its "passthrough object" which should
@@ -599,6 +636,10 @@ void PepperPluginInstanceImpl::Delete() {
container_ = NULL;
}
+bool PepperPluginInstanceImpl::is_deleted() const {
+ return is_deleted_;
+}
+
void PepperPluginInstanceImpl::Paint(WebCanvas* canvas,
const gfx::Rect& plugin_rect,
const gfx::Rect& paint_rect) {
@@ -675,7 +716,7 @@ void PepperPluginInstanceImpl::InstanceCrashed() {
BindGraphics(pp_instance(), 0);
InvalidateRect(gfx::Rect());
- render_view_->PluginCrashed(module_->path(), module_->GetPeerProcessId());
+ render_frame_->PluginCrashed(module_->path(), module_->GetPeerProcessId());
UnSetAndDeleteLockTargetAdapter();
}
@@ -721,8 +762,9 @@ bool PepperPluginInstanceImpl::Initialize(
UpdateTouchEventRequest();
container_->setWantsWheelEvents(IsAcceptingWheelEvents());
- SetGPUHistogram(ppapi::Preferences(render_view_->webkit_preferences()),
- arg_names, arg_values);
+ SetGPUHistogram(ppapi::Preferences(
+ render_frame_->render_view()->webkit_preferences()),
+ arg_names, arg_values);
argn_ = arg_names;
argv_ = arg_values;
@@ -738,7 +780,7 @@ bool PepperPluginInstanceImpl::Initialize(
}
bool PepperPluginInstanceImpl::HandleDocumentLoad(
- const WebKit::WebURLResponse& response) {
+ const blink::WebURLResponse& response) {
DCHECK(!document_loader_);
if (external_document_load_) {
// The external proxy isn't available, so save the response and record
@@ -782,7 +824,7 @@ bool PepperPluginInstanceImpl::HandleDocumentLoad(
pp_instance(),
response,
base::Bind(&PepperPluginInstanceImpl::DidDataFromWebURLResponse,
- AsWeakPtr(),
+ weak_factory_.GetWeakPtr(),
response,
pending_host_id));
@@ -794,7 +836,7 @@ bool PepperPluginInstanceImpl::HandleDocumentLoad(
bool PepperPluginInstanceImpl::SendCompositionEventToPlugin(
PP_InputEvent_Type type, const base::string16& text) {
- std::vector<WebKit::WebCompositionUnderline> empty;
+ std::vector<blink::WebCompositionUnderline> empty;
return SendCompositionEventWithUnderlineInformationToPlugin(
type, text, empty, static_cast<int>(text.size()),
static_cast<int>(text.size()));
@@ -804,7 +846,7 @@ bool PepperPluginInstanceImpl::
SendCompositionEventWithUnderlineInformationToPlugin(
PP_InputEvent_Type type,
const base::string16& text,
- const std::vector<WebKit::WebCompositionUnderline>& underlines,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
int selection_end) {
// Keep a reference on the stack. See NOTE above.
@@ -893,7 +935,7 @@ bool PepperPluginInstanceImpl::HandleCompositionStart(
bool PepperPluginInstanceImpl::HandleCompositionUpdate(
const base::string16& text,
- const std::vector<WebKit::WebCompositionUnderline>& underlines,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
int selection_end) {
return SendCompositionEventWithUnderlineInformationToPlugin(
@@ -948,18 +990,22 @@ gfx::Rect PepperPluginInstanceImpl::GetCaretBounds() const {
}
bool PepperPluginInstanceImpl::HandleInputEvent(
- const WebKit::WebInputEvent& event,
+ const blink::WebInputEvent& event,
WebCursorInfo* cursor_info) {
TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::HandleInputEvent");
if (WebInputEvent::isMouseEventType(event.type)) {
- render_view_->PepperDidReceiveMouseEvent(this);
+ render_frame_->PepperDidReceiveMouseEvent(this);
}
// Don't dispatch input events to crashed plugins.
if (module()->is_crashed())
return false;
+ // Don't send reserved system key events to plugins.
+ if (IsReservedSystemInputEvent(event))
+ return false;
+
// Keep a reference on the stack. See NOTE above.
scoped_refptr<PepperPluginInstanceImpl> ref(this);
@@ -1052,7 +1098,8 @@ void PepperPluginInstanceImpl::ViewChanged(
WebDocument document = element.document();
bool is_fullscreen_element = (element == document.fullScreenElement());
if (!view_data_.is_fullscreen && desired_fullscreen_state_ &&
- render_view_->is_fullscreen() && is_fullscreen_element) {
+ render_frame()->GetRenderWidget()->is_fullscreen() &&
+ is_fullscreen_element) {
// Entered fullscreen. Only possible via SetFullscreen().
view_data_.is_fullscreen = true;
} else if (view_data_.is_fullscreen && !is_fullscreen_element) {
@@ -1114,13 +1161,6 @@ void PepperPluginInstanceImpl::PageVisibilityChanged(bool is_visible) {
SendDidChangeView();
}
-void PepperPluginInstanceImpl::ViewWillInitiatePaint() {
- if (bound_graphics_2d_platform_)
- bound_graphics_2d_platform_->ViewWillInitiatePaint();
- else if (bound_graphics_3d_.get())
- bound_graphics_3d_->ViewWillInitiatePaint();
-}
-
void PepperPluginInstanceImpl::ViewInitiatedPaint() {
if (bound_graphics_2d_platform_)
bound_graphics_2d_platform_->ViewInitiatedPaint();
@@ -1346,12 +1386,22 @@ bool PepperPluginInstanceImpl::LoadPrintInterface() {
}
bool PepperPluginInstanceImpl::LoadPrivateInterface() {
+ // If this is a NaCl app, we want to talk to the trusted NaCl plugin to
+ // call GetInstanceObject. This is necessary to ensure that the properties
+ // the trusted plugin exposes (readyState and lastError) work properly. Note
+ // that untrusted NaCl apps are not allowed to provide PPP_InstancePrivate,
+ // so it's correct to never look up PPP_InstancePrivate for them.
+ //
+ // If this is *not* a NaCl plugin, original_module_ will never be set; we talk
+ // to the "real" module.
+ scoped_refptr<PluginModule> module = original_module_ ? original_module_ :
+ module_;
// Only check for the interface if the plugin has private permission.
- if (!module_->permissions().HasPermission(ppapi::PERMISSION_PRIVATE))
+ if (!module->permissions().HasPermission(ppapi::PERMISSION_PRIVATE))
return false;
if (!plugin_private_interface_) {
plugin_private_interface_ = static_cast<const PPP_Instance_Private*>(
- module_->GetPluginInterface(PPP_INSTANCE_PRIVATE_INTERFACE));
+ module->GetPluginInterface(PPP_INSTANCE_PRIVATE_INTERFACE));
}
return !!plugin_private_interface_;
@@ -1398,7 +1448,7 @@ void PepperPluginInstanceImpl::SendFocusChangeNotification() {
scoped_refptr<PepperPluginInstanceImpl> ref(this);
bool has_focus = PluginHasFocus();
- render_view_->PepperFocusChanged(this, has_focus);
+ render_frame_->PepperFocusChanged(this, has_focus);
// instance_interface_ may have been cleared in Delete() if the
// PepperWebPluginImpl is destroyed.
@@ -1410,8 +1460,8 @@ void PepperPluginInstanceImpl::UpdateTouchEventRequest() {
bool raw_touch = (filtered_input_event_mask_ & PP_INPUTEVENT_CLASS_TOUCH) ||
(input_event_mask_ & PP_INPUTEVENT_CLASS_TOUCH);
container_->requestTouchEventType(raw_touch ?
- WebKit::WebPluginContainer::TouchEventRequestTypeRaw :
- WebKit::WebPluginContainer::TouchEventRequestTypeSynthesizedMouse);
+ blink::WebPluginContainer::TouchEventRequestTypeRaw :
+ blink::WebPluginContainer::TouchEventRequestTypeSynthesizedMouse);
}
bool PepperPluginInstanceImpl::IsAcceptingWheelEvents() const {
@@ -1448,16 +1498,6 @@ void PepperPluginInstanceImpl::SendDidChangeView() {
last_sent_view_data_.Equals(view_data_)))
return; // Nothing to update.
- const PP_Size& size = view_data_.rect.size;
- // Avoid sending a notification with a huge rectangle.
- if (size.width < 0 || size.width > kMaxPluginSideLength ||
- size.height < 0 || size.height > kMaxPluginSideLength ||
- // We know this won't overflow due to above checks.
- static_cast<uint32>(size.width) * static_cast<uint32>(size.height) >
- kMaxPluginSize) {
- return;
- }
-
sent_initial_did_change_view_ = true;
last_sent_view_data_ = view_data_;
ScopedPPResource resource(
@@ -1465,9 +1505,16 @@ void PepperPluginInstanceImpl::SendDidChangeView() {
(new PPB_View_Shared(ppapi::OBJECT_IS_IMPL,
pp_instance(), view_data_))->GetReference());
- instance_interface_->DidChangeView(pp_instance(), resource,
- &view_data_.rect,
- &view_data_.clip_rect);
+ if (bound_graphics_2d_platform_)
+ bound_graphics_2d_platform_->DidChangeView(view_data_);
+
+ // It's possible that Delete() has been called but the renderer hasn't
+ // released its reference to this object yet.
+ if (instance_interface_) {
+ instance_interface_->DidChangeView(pp_instance(), resource,
+ &view_data_.rect,
+ &view_data_.clip_rect);
+ }
}
void PepperPluginInstanceImpl::ReportGeometry() {
@@ -1537,7 +1584,7 @@ int PepperPluginInstanceImpl::PrintBegin(const WebPrintParams& print_params) {
}
bool PepperPluginInstanceImpl::PrintPage(int page_number,
- WebKit::WebCanvas* canvas) {
+ blink::WebCanvas* canvas) {
#if defined(ENABLE_FULL_PRINTING)
DCHECK(plugin_print_interface_);
PP_PrintPageNumberRange_Dev page_range;
@@ -1563,7 +1610,7 @@ bool PepperPluginInstanceImpl::PrintPage(int page_number,
bool PepperPluginInstanceImpl::PrintPageHelper(
PP_PrintPageNumberRange_Dev* page_ranges,
int num_ranges,
- WebKit::WebCanvas* canvas) {
+ blink::WebCanvas* canvas) {
// Keep a reference on the stack. See NOTE above.
scoped_refptr<PepperPluginInstanceImpl> ref(this);
DCHECK(plugin_print_interface_);
@@ -1639,7 +1686,9 @@ bool PepperPluginInstanceImpl::SetFullscreen(bool fullscreen) {
if (fullscreen == IsFullscreenOrPending())
return false;
- if (fullscreen && !render_view_->IsPluginFullscreenAllowed())
+ if (fullscreen &&
+ !render_frame_->render_view()->renderer_preferences().
+ plugin_fullscreen_allowed)
return false;
// Check whether we are trying to switch while the state is in transition.
@@ -1717,7 +1766,7 @@ bool PepperPluginInstanceImpl::IsViewAccelerated() {
}
bool PepperPluginInstanceImpl::PrintPDFOutput(PP_Resource print_output,
- WebKit::WebCanvas* canvas) {
+ blink::WebCanvas* canvas) {
#if defined(ENABLE_FULL_PRINTING)
ppapi::thunk::EnterResourceNoLock<PPB_Buffer_API> enter(print_output, true);
if (enter.failed())
@@ -1827,8 +1876,9 @@ void PepperPluginInstanceImpl::UpdateLayer() {
if ((want_layer == !!texture_layer_.get()) &&
(want_3d_layer == layer_is_hardware_) &&
- layer_bound_to_fullscreen_ == !!fullscreen_container_)
+ layer_bound_to_fullscreen_ == !!fullscreen_container_) {
return;
+ }
if (texture_layer_) {
if (!layer_bound_to_fullscreen_)
@@ -1874,10 +1924,6 @@ unsigned PepperPluginInstanceImpl::PrepareTexture() {
return 0;
}
-WebKit::WebGraphicsContext3D* PepperPluginInstanceImpl::Context3d() {
- return NULL;
-}
-
bool PepperPluginInstanceImpl::PrepareTextureMailbox(
cc::TextureMailbox* mailbox,
scoped_ptr<cc::SingleReleaseCallback>* release_callback,
@@ -1925,9 +1971,9 @@ void PepperPluginInstanceImpl::OnMouseLockLost() {
}
void PepperPluginInstanceImpl::HandleMouseLockedInputEvent(
- const WebKit::WebMouseEvent& event) {
+ const blink::WebMouseEvent& event) {
// |cursor_info| is ignored since it is hidden when the mouse is locked.
- WebKit::WebCursorInfo cursor_info;
+ blink::WebCursorInfo cursor_info;
HandleInputEvent(event, &cursor_info);
}
@@ -1966,7 +2012,7 @@ bool PepperPluginInstanceImpl::SimulateIMEEvent(
SimulateImeSetCompositionEvent(input_event);
break;
case PP_INPUTEVENT_TYPE_IME_TEXT:
- render_view_->SimulateImeConfirmComposition(
+ render_frame_->SimulateImeConfirmComposition(
UTF8ToUTF16(input_event.character_text), gfx::Range());
break;
default:
@@ -1987,9 +2033,9 @@ void PepperPluginInstanceImpl::SimulateImeSetCompositionEvent(
base::string16 utf16_text =
base::UTF8ToUTF16AndAdjustOffsets(input_event.character_text, &offsets);
- std::vector<WebKit::WebCompositionUnderline> underlines;
+ std::vector<blink::WebCompositionUnderline> underlines;
for (size_t i = 2; i + 1 < offsets.size(); ++i) {
- WebKit::WebCompositionUnderline underline;
+ blink::WebCompositionUnderline underline;
underline.startOffset = offsets[i];
underline.endOffset = offsets[i + 1];
if (input_event.composition_target_segment == static_cast<int32_t>(i - 2))
@@ -1997,7 +2043,7 @@ void PepperPluginInstanceImpl::SimulateImeSetCompositionEvent(
underlines.push_back(underline);
}
- render_view_->SimulateImeSetComposition(
+ render_frame_->SimulateImeSetComposition(
utf16_text, underlines, offsets[0], offsets[1]);
}
@@ -2141,7 +2187,7 @@ PP_Var PepperPluginInstanceImpl::ExecuteScript(PP_Instance instance,
NPVariant result;
bool ok = false;
if (IsProcessingUserGesture()) {
- WebKit::WebScopedUserGesture user_gesture(CurrentUserGestureToken());
+ blink::WebScopedUserGesture user_gesture(CurrentUserGestureToken());
ok = WebBindings::evaluate(NULL, frame->windowObject(), &np_script,
&result);
} else {
@@ -2175,35 +2221,43 @@ uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputBufferSize(
PP_Var PepperPluginInstanceImpl::GetDefaultCharSet(PP_Instance instance) {
return StringVar::StringToPPVar(
- render_view_->webkit_preferences().default_encoding);
+ render_frame_->render_view()->webkit_preferences().default_encoding);
}
// These PPB_ContentDecryptor_Private calls are responses to
// PPP_ContentDecryptor_Private calls made on |content_decryptor_delegate_|.
// Therefore, |content_decryptor_delegate_| must have been initialized when
// the following methods are called.
-void PepperPluginInstanceImpl::KeyAdded(PP_Instance instance,
- PP_Var key_system_var,
- PP_Var session_id_var) {
- content_decryptor_delegate_->KeyAdded(key_system_var, session_id_var);
+void PepperPluginInstanceImpl::SessionCreated(PP_Instance instance,
+ uint32_t session_id,
+ PP_Var web_session_id_var) {
+ content_decryptor_delegate_->OnSessionCreated(session_id, web_session_id_var);
+}
+
+void PepperPluginInstanceImpl::SessionMessage(PP_Instance instance,
+ uint32_t session_id,
+ PP_Var message_var,
+ PP_Var destination_url) {
+ content_decryptor_delegate_->OnSessionMessage(
+ session_id, message_var, destination_url);
+}
+
+void PepperPluginInstanceImpl::SessionReady(PP_Instance instance,
+ uint32_t session_id) {
+ content_decryptor_delegate_->OnSessionReady(session_id);
}
-void PepperPluginInstanceImpl::KeyMessage(PP_Instance instance,
- PP_Var key_system_var,
- PP_Var session_id_var,
- PP_Var message_var,
- PP_Var default_url_var) {
- content_decryptor_delegate_->KeyMessage(
- key_system_var, session_id_var, message_var, default_url_var);
+void PepperPluginInstanceImpl::SessionClosed(PP_Instance instance,
+ uint32_t session_id) {
+ content_decryptor_delegate_->OnSessionClosed(session_id);
}
-void PepperPluginInstanceImpl::KeyError(PP_Instance instance,
- PP_Var key_system_var,
- PP_Var session_id_var,
- int32_t media_error,
- int32_t system_code) {
- content_decryptor_delegate_->KeyError(
- key_system_var, session_id_var, media_error, system_code);
+void PepperPluginInstanceImpl::SessionError(PP_Instance instance,
+ uint32_t session_id,
+ int32_t media_error,
+ int32_t system_code) {
+ content_decryptor_delegate_->OnSessionError(
+ session_id, media_error, system_code);
}
void PepperPluginInstanceImpl::DeliverBlock(
@@ -2248,8 +2302,8 @@ void PepperPluginInstanceImpl::DeliverFrame(
void PepperPluginInstanceImpl::DeliverSamples(
PP_Instance instance,
PP_Resource audio_frames,
- const PP_DecryptedBlockInfo* block_info) {
- content_decryptor_delegate_->DeliverSamples(audio_frames, block_info);
+ const PP_DecryptedSampleInfo* sample_info) {
+ content_decryptor_delegate_->DeliverSamples(audio_frames, sample_info);
}
void PepperPluginInstanceImpl::NumberOfFindResultsChanged(
@@ -2257,15 +2311,15 @@ void PepperPluginInstanceImpl::NumberOfFindResultsChanged(
int32_t total,
PP_Bool final_result) {
DCHECK_NE(find_identifier_, -1);
- render_view_->reportFindInPageMatchCount(
+ render_frame_->reportFindInPageMatchCount(
find_identifier_, total, PP_ToBool(final_result));
}
void PepperPluginInstanceImpl::SelectedFindResultChanged(PP_Instance instance,
int32_t index) {
DCHECK_NE(find_identifier_, -1);
- render_view_->reportFindInPageSelection(
- find_identifier_, index + 1, WebKit::WebRect());
+ render_frame_->reportFindInPageSelection(
+ find_identifier_, index + 1, blink::WebRect());
}
PP_Bool PepperPluginInstanceImpl::IsFullscreen(PP_Instance instance) {
@@ -2279,7 +2333,7 @@ PP_Bool PepperPluginInstanceImpl::SetFullscreen(PP_Instance instance,
PP_Bool PepperPluginInstanceImpl::GetScreenSize(PP_Instance instance,
PP_Size* size) {
- WebKit::WebScreenInfo info = render_view_->screenInfo();
+ blink::WebScreenInfo info = render_frame()->GetRenderWidget()->screenInfo();
*size = PP_MakeSize(info.rect.width, info.rect.height);
return PP_TRUE;
}
@@ -2291,12 +2345,12 @@ ppapi::Resource* PepperPluginInstanceImpl::GetSingletonResource(
switch (id) {
case ppapi::BROKER_SINGLETON_ID:
case ppapi::BROWSER_FONT_SINGLETON_ID:
- case ppapi::CRX_FILESYSTEM_SINGLETON_ID:
case ppapi::EXTENSIONS_COMMON_SINGLETON_ID:
case ppapi::FLASH_CLIPBOARD_SINGLETON_ID:
case ppapi::FLASH_FILE_SINGLETON_ID:
case ppapi::FLASH_FULLSCREEN_SINGLETON_ID:
case ppapi::FLASH_SINGLETON_ID:
+ case ppapi::ISOLATED_FILESYSTEM_SINGLETON_ID:
case ppapi::NETWORK_PROXY_SINGLETON_ID:
case ppapi::PDF_SINGLETON_ID:
case ppapi::TRUETYPE_FONT_SINGLETON_ID:
@@ -2352,7 +2406,8 @@ void PepperPluginInstanceImpl::ZoomLimitsChanged(PP_Instance instance,
}
double minimum_level = ZoomFactorToZoomLevel(minimum_factor);
double maximum_level = ZoomFactorToZoomLevel(maximum_factor);
- render_view_->webview()->zoomLimitsChanged(minimum_level, maximum_level);
+ render_frame_->render_view()->webview()->zoomLimitsChanged(
+ minimum_level, maximum_level);
}
void PepperPluginInstanceImpl::PostMessage(PP_Instance instance,
@@ -2439,7 +2494,7 @@ void PepperPluginInstanceImpl::SetTextInputType(PP_Instance instance,
if (itype < 0 || itype > ui::TEXT_INPUT_TYPE_URL)
itype = ui::TEXT_INPUT_TYPE_NONE;
text_input_type_ = static_cast<ui::TextInputType>(itype);
- render_view_->PepperTextInputTypeChanged(this);
+ render_frame_->PepperTextInputTypeChanged(this);
}
void PepperPluginInstanceImpl::UpdateCaretPosition(
@@ -2449,11 +2504,11 @@ void PepperPluginInstanceImpl::UpdateCaretPosition(
text_input_caret_ = PP_ToGfxRect(caret);
text_input_caret_bounds_ = PP_ToGfxRect(bounding_box);
text_input_caret_set_ = true;
- render_view_->PepperCaretPositionChanged(this);
+ render_frame_->PepperCaretPositionChanged(this);
}
void PepperPluginInstanceImpl::CancelCompositionText(PP_Instance instance) {
- render_view_->PepperCancelComposition(this);
+ render_frame_->PepperCancelComposition(this);
}
void PepperPluginInstanceImpl::SelectionChanged(PP_Instance instance) {
@@ -2468,7 +2523,7 @@ void PepperPluginInstanceImpl::SelectionChanged(PP_Instance instance) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&PepperPluginInstanceImpl::RequestSurroundingText,
- AsWeakPtr(),
+ weak_factory_.GetWeakPtr(),
static_cast<size_t>(kExtraCharsForTextInput)));
}
@@ -2479,7 +2534,7 @@ void PepperPluginInstanceImpl::UpdateSurroundingText(PP_Instance instance,
surrounding_text_ = text;
selection_caret_ = caret;
selection_anchor_ = anchor;
- render_view_->PepperSelectionChanged(this);
+ render_frame_->PepperSelectionChanged(this);
}
PP_Var PepperPluginInstanceImpl::ResolveRelativeToDocument(
@@ -2503,7 +2558,7 @@ PP_Bool PepperPluginInstanceImpl::DocumentCanRequest(PP_Instance instance,
if (!url_string)
return PP_FALSE;
- WebKit::WebSecurityOrigin security_origin;
+ blink::WebSecurityOrigin security_origin;
if (!SecurityOriginForInstance(instance, &security_origin))
return PP_FALSE;
@@ -2517,11 +2572,11 @@ PP_Bool PepperPluginInstanceImpl::DocumentCanRequest(PP_Instance instance,
PP_Bool PepperPluginInstanceImpl::DocumentCanAccessDocument(
PP_Instance instance,
PP_Instance target) {
- WebKit::WebSecurityOrigin our_origin;
+ blink::WebSecurityOrigin our_origin;
if (!SecurityOriginForInstance(instance, &our_origin))
return PP_FALSE;
- WebKit::WebSecurityOrigin target_origin;
+ blink::WebSecurityOrigin target_origin;
if (!SecurityOriginForInstance(instance, &target_origin))
return PP_FALSE;
@@ -2531,7 +2586,7 @@ PP_Bool PepperPluginInstanceImpl::DocumentCanAccessDocument(
PP_Var PepperPluginInstanceImpl::GetDocumentURL(
PP_Instance instance,
PP_URLComponents_Dev* components) {
- WebKit::WebDocument document = container()->element().document();
+ blink::WebDocument document = container()->element().document();
return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(document.url(),
components);
}
@@ -2546,7 +2601,7 @@ PP_Var PepperPluginInstanceImpl::GetPluginInstanceURL(
PP_Var PepperPluginInstanceImpl::GetPluginReferrerURL(
PP_Instance instance,
PP_URLComponents_Dev* components) {
- WebKit::WebDocument document = container()->element().document();
+ blink::WebDocument document = container()->element().document();
if (!full_frame_)
return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(document.url(),
components);
@@ -2623,7 +2678,7 @@ PP_ExternalPluginResult PepperPluginInstanceImpl::ResetAsProxied(
document_loader_ = NULL;
// Pass the response to the new proxy.
HandleDocumentLoad(external_document_response_);
- external_document_response_ = WebKit::WebURLResponse();
+ external_document_response_ = blink::WebURLResponse();
// Replay any document load events we've received to the real loader.
external_document_loader_->ReplayReceivedData(document_loader_);
external_document_loader_.reset(NULL);
@@ -2642,22 +2697,22 @@ NPP PepperPluginInstanceImpl::instanceNPP() {
return npp_.get();
}
-v8::Isolate* PepperPluginInstanceImpl::GetIsolate() const {
- return isolate_;
-}
-
PepperPluginInstance* PepperPluginInstance::Get(PP_Instance instance_id) {
return HostGlobals::Get()->GetInstance(instance_id);
}
RenderView* PepperPluginInstanceImpl::GetRenderView() {
- return render_view_;
+ return render_frame_->render_view();
}
-WebKit::WebPluginContainer* PepperPluginInstanceImpl::GetContainer() {
+blink::WebPluginContainer* PepperPluginInstanceImpl::GetContainer() {
return container_;
}
+v8::Isolate* PepperPluginInstanceImpl::GetIsolate() const {
+ return isolate_;
+}
+
ppapi::VarTracker* PepperPluginInstanceImpl::GetVarTracker() {
return HostGlobals::Get()->GetVarTracker();
}
@@ -2672,11 +2727,9 @@ base::FilePath PepperPluginInstanceImpl::GetModulePath() {
PP_Resource PepperPluginInstanceImpl::CreateImage(gfx::ImageSkia* source_image,
float scale) {
- ui::ScaleFactor scale_factor = ui::GetScaleFactorFromScale(scale);
- gfx::ImageSkiaRep image_skia_rep = source_image->GetRepresentation(
- scale_factor);
+ gfx::ImageSkiaRep image_skia_rep = source_image->GetRepresentation(scale);
- if (image_skia_rep.is_null() || image_skia_rep.scale_factor() != scale_factor)
+ if (image_skia_rep.is_null() || image_skia_rep.scale() != scale)
return 0;
scoped_refptr<PPB_ImageData_Impl> image_data(new PPB_ImageData_Impl(
@@ -2717,7 +2770,7 @@ PP_ExternalPluginResult PepperPluginInstanceImpl::SwitchToOutOfProcessProxy(
RendererPpapiHostImpl* renderer_ppapi_host =
external_plugin_module->CreateOutOfProcessModule(
- render_view_,
+ render_frame_,
file_path,
permissions,
channel_handle,
@@ -2742,7 +2795,7 @@ void PepperPluginInstanceImpl::DoSetCursor(WebCursorInfo* cursor) {
if (fullscreen_container_) {
fullscreen_container_->DidChangeCursor(*cursor);
} else {
- render_view_->PepperDidChangeCursor(this, *cursor);
+ render_frame_->PepperDidChangeCursor(this, *cursor);
}
}
@@ -2763,14 +2816,17 @@ bool PepperPluginInstanceImpl::FlashSetFullscreen(bool fullscreen,
if (fullscreen == FlashIsFullscreenOrPending())
return true;
- if (fullscreen && !render_view_->IsPluginFullscreenAllowed())
+ if (fullscreen &&
+ !render_frame_->render_view()->renderer_preferences().
+ plugin_fullscreen_allowed)
return false;
// Unbind current 2D or 3D graphics context.
VLOG(1) << "Setting fullscreen to " << (fullscreen ? "on" : "off");
if (fullscreen) {
DCHECK(!fullscreen_container_);
- fullscreen_container_ = render_view_->CreatePepperFullscreenContainer(this);
+ fullscreen_container_ =
+ render_frame_->CreatePepperFullscreenContainer(this);
UpdateLayer();
} else {
DCHECK(fullscreen_container_);
@@ -2854,17 +2910,22 @@ int PepperPluginInstanceImpl::MakePendingFileRefRendererHost(
scoped_ptr<ppapi::host::ResourceHost>(file_ref_host));
}
+void PepperPluginInstanceImpl::SetEmbedProperty(PP_Var key,
+ PP_Var value) {
+ message_channel_->SetReadOnlyProperty(key, value);
+}
+
bool PepperPluginInstanceImpl::CanAccessMainFrame() const {
if (!container_)
return false;
- WebKit::WebDocument containing_document = container_->element().document();
+ blink::WebDocument containing_document = container_->element().document();
if (!containing_document.frame() ||
!containing_document.frame()->view() ||
!containing_document.frame()->view()->mainFrame()) {
return false;
}
- WebKit::WebDocument main_document =
+ blink::WebDocument main_document =
containing_document.frame()->view()->mainFrame()->document();
return containing_document.securityOrigin().canAccess(
@@ -2882,7 +2943,7 @@ void PepperPluginInstanceImpl::KeepSizeAttributesBeforeFullscreen() {
}
void PepperPluginInstanceImpl::SetSizeAttributesForFullscreen() {
- WebKit::WebScreenInfo info = render_view_->screenInfo();
+ blink::WebScreenInfo info = render_frame_->GetRenderWidget()->screenInfo();
screen_size_for_fullscreen_ = gfx::Size(info.rect.width, info.rect.height);
std::string width = StringPrintf("%d", screen_size_for_fullscreen_.width());
std::string height = StringPrintf("%d", screen_size_for_fullscreen_.height());
@@ -2937,7 +2998,7 @@ MouseLockDispatcher* PepperPluginInstanceImpl::GetMouseLockDispatcher() {
static_cast<RenderWidgetFullscreenPepper*>(fullscreen_container_);
return container->mouse_lock_dispatcher();
} else {
- return render_view_->mouse_lock_dispatcher();
+ return render_frame_->render_view()->mouse_lock_dispatcher();
}
}
@@ -2949,7 +3010,7 @@ void PepperPluginInstanceImpl::UnSetAndDeleteLockTargetAdapter() {
}
void PepperPluginInstanceImpl::DidDataFromWebURLResponse(
- const WebKit::WebURLResponse& response,
+ const blink::WebURLResponse& response,
int pending_host_id,
const ppapi::URLResponseInfoData& data) {
RendererPpapiHostImpl* host_impl = module_->renderer_ppapi_host();
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
index 42d7d7139e2..0ed093f9d52 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -63,7 +63,7 @@ struct _NPP;
class SkBitmap;
class TransportDIB;
-namespace WebKit {
+namespace blink {
class WebInputEvent;
class WebLayer;
class WebMouseEvent;
@@ -105,6 +105,7 @@ class PluginObject;
class PPB_Graphics3D_Impl;
class PPB_ImageData_Impl;
class PPB_URLLoader_Impl;
+class RenderFrameImpl;
class RenderViewImpl;
// Represents one time a plugin appears on one web page.
@@ -113,7 +114,6 @@ class RenderViewImpl;
// ResourceTracker.
class CONTENT_EXPORT PepperPluginInstanceImpl
: public base::RefCounted<PepperPluginInstanceImpl>,
- public base::SupportsWeakPtr<PepperPluginInstanceImpl>,
public NON_EXPORTED_BASE(PepperPluginInstance),
public ppapi::PPB_Instance_Shared,
public NON_EXPORTED_BASE(cc::TextureLayerClient) {
@@ -123,15 +123,15 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// get_plugin_interface function. If the plugin does not support any valid
// PPP_Instance interface, returns NULL.
static PepperPluginInstanceImpl* Create(
- RenderViewImpl* render_view,
+ RenderFrameImpl* render_frame,
PluginModule* module,
- WebKit::WebPluginContainer* container,
+ blink::WebPluginContainer* container,
const GURL& plugin_url);
- RenderViewImpl* render_view() const { return render_view_; }
+ RenderFrameImpl* render_frame() const { return render_frame_; }
PluginModule* module() const { return module_.get(); }
MessageChannel& message_channel() { return *message_channel_; }
- WebKit::WebPluginContainer* container() const { return container_; }
+ blink::WebPluginContainer* container() const { return container_; }
// Returns the PP_Instance uniquely identifying this instance. Guaranteed
// nonzero.
@@ -147,8 +147,11 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// the WebPlugin implementation when WebKit is about to remove the plugin.
void Delete();
+ // Returns true if Delete() has been called on this object.
+ bool is_deleted() const;
+
// Paints the current backing store to the web page.
- void Paint(WebKit::WebCanvas* canvas,
+ void Paint(blink::WebCanvas* canvas,
const gfx::Rect& plugin_rect,
const gfx::Rect& paint_rect);
@@ -178,9 +181,9 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
bool Initialize(const std::vector<std::string>& arg_names,
const std::vector<std::string>& arg_values,
bool full_frame);
- bool HandleDocumentLoad(const WebKit::WebURLResponse& response);
- bool HandleInputEvent(const WebKit::WebInputEvent& event,
- WebKit::WebCursorInfo* cursor_info);
+ bool HandleDocumentLoad(const blink::WebURLResponse& response);
+ bool HandleInputEvent(const blink::WebInputEvent& event,
+ blink::WebCursorInfo* cursor_info);
PP_Var GetInstanceObject();
void ViewChanged(const gfx::Rect& position, const gfx::Rect& clip,
const std::vector<gfx::Rect>& cut_outs_rects);
@@ -189,7 +192,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
bool HandleCompositionStart(const base::string16& text);
bool HandleCompositionUpdate(
const base::string16& text,
- const std::vector<WebKit::WebCompositionUnderline>& underlines,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
int selection_end);
bool HandleCompositionEnd(const base::string16& text);
@@ -208,10 +211,9 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// Notification about page visibility. The default is "visible".
void PageVisibilityChanged(bool is_visible);
- // Notifications that the view is about to paint, has started painting, and
- // has flushed the painted content to the screen. These messages are used to
- // send Flush callbacks to the plugin for DeviceContext2D/3D.
- void ViewWillInitiatePaint();
+ // Notifications that the view has started painting, and has flushed the
+ // painted content to the screen. These messages are used to send Flush
+ // callbacks to the plugin for DeviceContext2D/3D.
void ViewInitiatedPaint();
void ViewFlushedPaint();
@@ -242,12 +244,12 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
bool SupportsPrintInterface();
bool IsPrintScalingDisabled();
- int PrintBegin(const WebKit::WebPrintParams& print_params);
- bool PrintPage(int page_number, WebKit::WebCanvas* canvas);
+ int PrintBegin(const blink::WebPrintParams& print_params);
+ bool PrintPage(int page_number, blink::WebCanvas* canvas);
void PrintEnd();
bool CanRotateView();
- void RotateView(WebKit::WebPlugin::RotationType type);
+ void RotateView(blink::WebPlugin::RotationType type);
// There are 2 implementations of the fullscreen interface
// PPB_FlashFullscreen is used by Pepper Flash.
@@ -311,14 +313,14 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// Returns the user gesture token to use for creating a WebScopedUserGesture,
// if IsProcessingUserGesture returned true.
- WebKit::WebUserGestureToken CurrentUserGestureToken();
+ blink::WebUserGestureToken CurrentUserGestureToken();
// A mouse lock request was pending and this reports success or failure.
void OnLockMouseACK(bool succeeded);
// A mouse lock was in place, but has been lost.
void OnMouseLockLost();
// A mouse lock is enabled and mouse events are being delivered.
- void HandleMouseLockedInputEvent(const WebKit::WebMouseEvent& event);
+ void HandleMouseLockedInputEvent(const blink::WebMouseEvent& event);
// Simulates an input event to the plugin by passing it down to WebKit,
// which sends it back up to the plugin as if it came from the user.
@@ -334,10 +336,10 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// case is non-NULL as long as the corresponding loader resource is alive.
// This pointer is non-owning, so the loader must use set_document_loader to
// clear itself when it is destroyed.
- WebKit::WebURLLoaderClient* document_loader() const {
+ blink::WebURLLoaderClient* document_loader() const {
return document_loader_;
}
- void set_document_loader(WebKit::WebURLLoaderClient* loader) {
+ void set_document_loader(blink::WebURLLoaderClient* loader) {
document_loader_ = loader;
}
@@ -345,7 +347,8 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// PluginInstance implementation
virtual RenderView* GetRenderView() OVERRIDE;
- virtual WebKit::WebPluginContainer* GetContainer() OVERRIDE;
+ virtual blink::WebPluginContainer* GetContainer() OVERRIDE;
+ virtual v8::Isolate* GetIsolate() const OVERRIDE;
virtual ppapi::VarTracker* GetVarTracker() OVERRIDE;
virtual const GURL& GetPluginURL() OVERRIDE;
virtual base::FilePath GetModulePath() OVERRIDE;
@@ -366,6 +369,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
bool from_user_action) OVERRIDE;
virtual int MakePendingFileRefRendererHost(
const base::FilePath& path) OVERRIDE;
+ virtual void SetEmbedProperty(PP_Var key, PP_Var value) OVERRIDE;
// PPB_Instance_API implementation.
virtual PP_Bool BindGraphics(PP_Instance instance,
@@ -442,19 +446,20 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
PP_URLComponents_Dev* components) OVERRIDE;
// PPB_ContentDecryptor_Private implementation.
- virtual void KeyAdded(PP_Instance instance,
- PP_Var key_system,
- PP_Var session_id) OVERRIDE;
- virtual void KeyMessage(PP_Instance instance,
- PP_Var key_system,
- PP_Var session_id,
- PP_Var message,
- PP_Var default_url) OVERRIDE;
- virtual void KeyError(PP_Instance instance,
- PP_Var key_system,
- PP_Var session_id,
- int32_t media_error,
- int32_t system_code) OVERRIDE;
+ virtual void SessionCreated(PP_Instance instance,
+ uint32_t session_id,
+ PP_Var web_session_id_var) OVERRIDE;
+ virtual void SessionMessage(PP_Instance instance,
+ uint32_t session_id,
+ PP_Var message,
+ PP_Var destination_url) OVERRIDE;
+ virtual void SessionReady(PP_Instance instance, uint32_t session_id) OVERRIDE;
+ virtual void SessionClosed(PP_Instance instance,
+ uint32_t session_id) OVERRIDE;
+ virtual void SessionError(PP_Instance instance,
+ uint32_t session_id,
+ int32_t media_error,
+ int32_t system_code) OVERRIDE;
virtual void DeliverBlock(PP_Instance instance,
PP_Resource decrypted_block,
const PP_DecryptedBlockInfo* block_info) OVERRIDE;
@@ -471,9 +476,10 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
virtual void DeliverFrame(PP_Instance instance,
PP_Resource decrypted_frame,
const PP_DecryptedFrameInfo* frame_info) OVERRIDE;
- virtual void DeliverSamples(PP_Instance instance,
- PP_Resource audio_frames,
- const PP_DecryptedBlockInfo* block_info) OVERRIDE;
+ virtual void DeliverSamples(
+ PP_Instance instance,
+ PP_Resource audio_frames,
+ const PP_DecryptedSampleInfo* sample_info) OVERRIDE;
// Reset this instance as proxied. Assigns the instance a new module, resets
// cached interfaces to point to the out-of-process proxy and re-sends
@@ -493,13 +499,8 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// itself when making NPObject scripting calls to WebBindings.
struct _NPP* instanceNPP();
- // Returns the v8::Isolate that was current when this Instance was created.
- // This is not inlined so as to avoid an unnecessary header include of v8.h.
- v8::Isolate* GetIsolate() const;
-
// cc::TextureLayerClient implementation.
virtual unsigned PrepareTexture() OVERRIDE;
- virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE;
virtual bool PrepareTextureMailbox(
cc::TextureMailbox* mailbox,
scoped_ptr<cc::SingleReleaseCallback>* release_callback,
@@ -514,27 +515,27 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// Class to record document load notifications and play them back once the
// real document loader becomes available. Used only by external instances.
- class ExternalDocumentLoader : public WebKit::WebURLLoaderClient {
+ class ExternalDocumentLoader : public blink::WebURLLoaderClient {
public:
ExternalDocumentLoader();
virtual ~ExternalDocumentLoader();
void ReplayReceivedData(WebURLLoaderClient* document_loader);
- // WebKit::WebURLLoaderClient implementation.
- virtual void didReceiveData(WebKit::WebURLLoader* loader,
+ // blink::WebURLLoaderClient implementation.
+ virtual void didReceiveData(blink::WebURLLoader* loader,
const char* data,
int data_length,
int encoded_data_length);
- virtual void didFinishLoading(WebKit::WebURLLoader* loader,
+ virtual void didFinishLoading(blink::WebURLLoader* loader,
double finish_time);
- virtual void didFail(WebKit::WebURLLoader* loader,
- const WebKit::WebURLError& error);
+ virtual void didFail(blink::WebURLLoader* loader,
+ const blink::WebURLError& error);
private:
std::list<std::string> data_;
bool finished_loading_;
- scoped_ptr<WebKit::WebURLError> error_;
+ scoped_ptr<blink::WebURLError> error_;
};
// Implements PPB_Gamepad_API. This is just to avoid having an excessive
@@ -555,10 +556,10 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// objects. This constructor is private so that we can hide the
// PPP_Instance_Combined details while still having 1 constructor to maintain
// for member initialization.
- PepperPluginInstanceImpl(RenderViewImpl* render_view,
+ PepperPluginInstanceImpl(RenderFrameImpl* render_frame,
PluginModule* module,
ppapi::PPP_Instance_Combined* instance_interface,
- WebKit::WebPluginContainer* container,
+ blink::WebPluginContainer* container,
const GURL& plugin_url);
bool LoadFindInterface();
@@ -594,12 +595,12 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// best format to use. Returns false if the plugin does not support any
// print format that we can handle (we can handle only PDF).
bool GetPreferredPrintOutputFormat(PP_PrintOutputFormat_Dev* format);
- bool PrintPDFOutput(PP_Resource print_output, WebKit::WebCanvas* canvas);
+ bool PrintPDFOutput(PP_Resource print_output, blink::WebCanvas* canvas);
// Updates the layer for compositing. This creates a layer and attaches to the
// container if:
- // - we have a bound Graphics3D
- // - the Graphics3D has a texture
+ // - we have a bound Graphics3D and the Graphics3D has a texture, OR
+ // we have a bound Graphics2D and are using software compositing
// - we are not in Flash full-screen mode (or transitioning to it)
// Otherwise it destroys the layer.
// It does either operation lazily.
@@ -608,9 +609,9 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// Internal helper function for PrintPage().
bool PrintPageHelper(PP_PrintPageNumberRange_Dev* page_ranges,
int num_ranges,
- WebKit::WebCanvas* canvas);
+ blink::WebCanvas* canvas);
- void DoSetCursor(WebKit::WebCursorInfo* cursor);
+ void DoSetCursor(blink::WebCursorInfo* cursor);
// Internal helper functions for HandleCompositionXXX().
bool SendCompositionEventToPlugin(
@@ -619,7 +620,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
bool SendCompositionEventWithUnderlineInformationToPlugin(
PP_InputEvent_Type type,
const base::string16& text,
- const std::vector<WebKit::WebCompositionUnderline>& underlines,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
int selection_end);
@@ -647,11 +648,11 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
void UnSetAndDeleteLockTargetAdapter();
void DidDataFromWebURLResponse(
- const WebKit::WebURLResponse& response,
+ const blink::WebURLResponse& response,
int pending_host_id,
const ppapi::URLResponseInfoData& data);
- RenderViewImpl* render_view_;
+ RenderFrameImpl* render_frame_;
scoped_refptr<PluginModule> module_;
scoped_ptr<ppapi::PPP_Instance_Combined> instance_interface_;
// If this is the NaCl plugin, we create a new module when we switch to the
@@ -663,9 +664,9 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
PP_Instance pp_instance_;
// NULL until we have been initialized.
- WebKit::WebPluginContainer* container_;
+ blink::WebPluginContainer* container_;
scoped_refptr<cc::TextureLayer> texture_layer_;
- scoped_ptr<WebKit::WebLayer> web_layer_;
+ scoped_ptr<blink::WebLayer> web_layer_;
bool layer_bound_to_fullscreen_;
bool layer_is_hardware_;
@@ -687,13 +688,6 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// same as the default values.
bool sent_initial_did_change_view_;
- // 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
- // view_data_ but not send updates. This also allows us to cancel scheduled
- // view change events.
- base::WeakPtrFactory<PepperPluginInstanceImpl> view_change_weak_ptr_factory_;
-
// The current device context for painting in 2D and 3D.
scoped_refptr<PPB_Graphics3D_Impl> bound_graphics_3d_;
PepperGraphics2DHost* bound_graphics_2d_platform_;
@@ -748,7 +742,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// to generate the entire PDF given the variables below:
//
// The most recently used WebCanvas, guaranteed to be valid.
- skia::RefPtr<WebKit::WebCanvas> canvas_;
+ skia::RefPtr<blink::WebCanvas> canvas_;
// An array of page ranges.
std::vector<PP_PrintPageNumberRange_Dev> ranges_;
@@ -761,7 +755,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
const PPP_Graphics3D* plugin_graphics_3d_interface_;
// Contains the cursor if it's set by the plugin.
- scoped_ptr<WebKit::WebCursorInfo> cursor_;
+ scoped_ptr<blink::WebCursorInfo> cursor_;
// 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.
@@ -794,10 +788,10 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// WebKit does not resize the plugin when going into fullscreen mode, so we do
// this here by modifying the various plugin attributes and then restoring
// them on exit.
- WebKit::WebString width_before_fullscreen_;
- WebKit::WebString height_before_fullscreen_;
- WebKit::WebString border_before_fullscreen_;
- WebKit::WebString style_before_fullscreen_;
+ blink::WebString width_before_fullscreen_;
+ blink::WebString height_before_fullscreen_;
+ blink::WebString border_before_fullscreen_;
+ blink::WebString style_before_fullscreen_;
gfx::Size screen_size_for_fullscreen_;
// The MessageChannel used to implement bidirectional postMessage for the
@@ -831,7 +825,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// Track pending user gestures so out-of-process plugins can respond to
// a user gesture after it has been processed.
PP_TimeTicks pending_user_gesture_;
- WebKit::WebUserGestureToken pending_user_gesture_token_;
+ blink::WebUserGestureToken pending_user_gesture_token_;
// We store the arguments so we can re-send them if we are reset to talk to
// NaCl via the IPC NaCl proxy.
@@ -839,9 +833,9 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
std::vector<std::string> argv_;
// Non-owning pointer to the document loader, if any.
- WebKit::WebURLLoaderClient* document_loader_;
+ blink::WebURLLoaderClient* document_loader_;
// State for deferring document loads. Used only by external instances.
- WebKit::WebURLResponse external_document_response_;
+ blink::WebURLResponse external_document_response_;
scoped_ptr<ExternalDocumentLoader> external_document_loader_;
bool external_document_load_;
@@ -859,6 +853,16 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
scoped_ptr<MouseLockDispatcher::LockTarget> lock_target_;
+ bool is_deleted_;
+
+ // 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
+ // view_data_ but not send updates. This also allows us to cancel scheduled
+ // view change events.
+ base::WeakPtrFactory<PepperPluginInstanceImpl> view_change_weak_ptr_factory_;
+ base::WeakPtrFactory<PepperPluginInstanceImpl> weak_factory_;
+
friend class PpapiPluginInstanceTest;
DISALLOW_COPY_AND_ASSIGN(PepperPluginInstanceImpl);
};
diff --git a/chromium/content/renderer/pepper/pepper_plugin_registry.cc b/chromium/content/renderer/pepper/pepper_plugin_registry.cc
index a5ae34643c4..5939ce16d23 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_registry.cc
+++ b/chromium/content/renderer/pepper/pepper_plugin_registry.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "content/common/pepper_plugin_list.h"
+#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_module.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
@@ -16,8 +17,10 @@ PepperPluginRegistry* PepperPluginRegistry::GetInstance() {
static PepperPluginRegistry* registry = NULL;
// This object leaks. It is a temporary hack to work around a crash.
// http://code.google.com/p/chromium/issues/detail?id=63234
- if (!registry)
+ if (!registry) {
registry = new PepperPluginRegistry;
+ registry->Initialize();
+ }
return registry;
}
@@ -41,10 +44,29 @@ const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin(
}
PluginModule* PepperPluginRegistry::GetLiveModule(const base::FilePath& path) {
- NonOwningModuleMap::iterator it = live_modules_.find(path);
- if (it == live_modules_.end())
+ NonOwningModuleMap::iterator module_iter = live_modules_.find(path);
+ if (module_iter == live_modules_.end())
return NULL;
- return it->second;
+
+ // Check the instances for the module to see if they've all been Delete()d.
+ // We don't want to return a PluginModule in that case, since the plugin may
+ // have exited already.
+ const PluginModule::PluginInstanceSet& instance_set =
+ module_iter->second->GetAllInstances();
+
+ // If instance_set is empty, InstanceCreated() hasn't been called yet, so
+ // it's safe to return the PluginModule.
+ if (instance_set.empty())
+ return module_iter->second;
+
+ PluginModule::PluginInstanceSet::const_iterator instance_iter =
+ instance_set.begin();
+ while (instance_iter != instance_set.end()) {
+ if (!(*instance_iter)->is_deleted())
+ return module_iter->second;
+ ++instance_iter;
+ }
+ return NULL;
}
void PepperPluginRegistry::AddLiveModule(const base::FilePath& path,
@@ -79,6 +101,9 @@ PepperPluginRegistry::~PepperPluginRegistry() {
}
PepperPluginRegistry::PepperPluginRegistry() {
+}
+
+void PepperPluginRegistry::Initialize() {
ComputePepperPluginList(&plugin_list_);
// Note that in each case, AddLiveModule must be called before completing
diff --git a/chromium/content/renderer/pepper/pepper_plugin_registry.h b/chromium/content/renderer/pepper/pepper_plugin_registry.h
index 7bd6ff9f62c..83319a9be68 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_registry.h
+++ b/chromium/content/renderer/pepper/pepper_plugin_registry.h
@@ -47,6 +47,7 @@ class PepperPluginRegistry {
private:
PepperPluginRegistry();
+ void Initialize();
// All known pepper plugins.
std::vector<PepperPluginInfo> plugin_list_;
diff --git a/chromium/content/renderer/pepper/pepper_truetype_font_win.cc b/chromium/content/renderer/pepper/pepper_truetype_font_win.cc
index e515bd18671..6d040445dd8 100644
--- a/chromium/content/renderer/pepper/pepper_truetype_font_win.cc
+++ b/chromium/content/renderer/pepper/pepper_truetype_font_win.cc
@@ -223,11 +223,15 @@ int32_t PepperTrueTypeFontWin::GetTable(uint32_t table_tag,
DWORD safe_length = std::min(table_size - safe_offset,
static_cast<DWORD>(max_data_length));
data->resize(safe_length);
- table_size = GetFontData(hdc, table_tag, safe_offset,
- reinterpret_cast<uint8_t*>(&(*data)[0]),
- safe_length);
- if (table_size == GDI_ERROR)
- return PP_ERROR_FAILED;
+ if (safe_length == 0) {
+ table_size = 0;
+ } else {
+ table_size = GetFontData(hdc, table_tag, safe_offset,
+ reinterpret_cast<uint8_t*>(&(*data)[0]),
+ safe_length);
+ if (table_size == GDI_ERROR)
+ return PP_ERROR_FAILED;
+ }
return static_cast<int32_t>(table_size);
}
diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.cc b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
index 3f0dbc963e0..178548ee718 100644
--- a/chromium/content/renderer/pepper/pepper_url_loader_host.cc
+++ b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
@@ -27,14 +27,14 @@
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebURLLoaderOptions.h"
-using WebKit::WebFrame;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebURLError;
-using WebKit::WebURLLoader;
-using WebKit::WebURLLoaderOptions;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
+using blink::WebFrame;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebURLError;
+using blink::WebURLLoader;
+using blink::WebURLLoaderOptions;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
#ifdef _MSC_VER
// Do not warn about use of std::copy with raw pointers.
@@ -98,7 +98,7 @@ PepperURLLoaderHost::~PepperURLLoaderHost() {
// re-entering the scoped_ptr destructor with the same scoped_ptr object
// via loader_.reset(). Be sure that loader_ is first NULL then destroy
// the scoped_ptr. See http://crbug.com/159429.
- scoped_ptr<WebKit::WebURLLoader> for_destruction_only(loader_.release());
+ scoped_ptr<blink::WebURLLoader> for_destruction_only(loader_.release());
}
int32_t PepperURLLoaderHost::OnResourceMessageReceived(
@@ -367,7 +367,7 @@ void PepperURLLoaderHost::Close() {
GetFrame()->stopLoading();
}
-WebKit::WebFrame* PepperURLLoaderHost::GetFrame() {
+blink::WebFrame* PepperURLLoaderHost::GetFrame() {
PepperPluginInstance* instance_object =
renderer_ppapi_host_->GetPluginInstance(pp_instance());
if (!instance_object)
diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.h b/chromium/content/renderer/pepper/pepper_url_loader_host.h
index e515174eb40..2790c785c74 100644
--- a/chromium/content/renderer/pepper/pepper_url_loader_host.h
+++ b/chromium/content/renderer/pepper/pepper_url_loader_host.h
@@ -16,7 +16,7 @@
#include "ppapi/shared_impl/url_response_info_data.h"
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebURLLoader;
}
@@ -27,7 +27,7 @@ class RendererPpapiHostImpl;
class PepperURLLoaderHost
: public ppapi::host::ResourceHost,
- public WebKit::WebURLLoaderClient {
+ public blink::WebURLLoaderClient {
public:
// If main_document_loader is true, PP_Resource must be 0 since it will be
// pending until the plugin resource attaches to it.
@@ -42,26 +42,26 @@ class PepperURLLoaderHost
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) OVERRIDE;
- // WebKit::WebURLLoaderClient implementation.
- virtual void willSendRequest(WebKit::WebURLLoader* loader,
- WebKit::WebURLRequest& new_request,
- const WebKit::WebURLResponse& redir_response);
- virtual void didSendData(WebKit::WebURLLoader* loader,
+ // blink::WebURLLoaderClient implementation.
+ virtual void willSendRequest(blink::WebURLLoader* loader,
+ blink::WebURLRequest& new_request,
+ const blink::WebURLResponse& redir_response);
+ virtual void didSendData(blink::WebURLLoader* loader,
unsigned long long bytes_sent,
unsigned long long total_bytes_to_be_sent);
- virtual void didReceiveResponse(WebKit::WebURLLoader* loader,
- const WebKit::WebURLResponse& response);
- virtual void didDownloadData(WebKit::WebURLLoader* loader,
+ virtual void didReceiveResponse(blink::WebURLLoader* loader,
+ const blink::WebURLResponse& response);
+ virtual void didDownloadData(blink::WebURLLoader* loader,
int data_length,
int encoded_data_length);
- virtual void didReceiveData(WebKit::WebURLLoader* loader,
+ virtual void didReceiveData(blink::WebURLLoader* loader,
const char* data,
int data_length,
int encoded_data_length);
- virtual void didFinishLoading(WebKit::WebURLLoader* loader,
+ virtual void didFinishLoading(blink::WebURLLoader* loader,
double finish_time);
- virtual void didFail(WebKit::WebURLLoader* loader,
- const WebKit::WebURLError& error);
+ virtual void didFail(blink::WebURLLoader* loader,
+ const blink::WebURLError& error);
private:
// ResourceHost protected overrides.
@@ -96,14 +96,14 @@ class PepperURLLoaderHost
void Close();
// Returns the frame for the current request.
- WebKit::WebFrame* GetFrame();
+ blink::WebFrame* GetFrame();
// Calls SetDefersLoading on the current load. This encapsulates the logic
// differences between document loads and regular ones.
void SetDefersLoading(bool defers_loading);
// Converts a WebURLResponse to a URLResponseInfo and saves it.
- void SaveResponse(const WebKit::WebURLResponse& response);
+ void SaveResponse(const blink::WebURLResponse& response);
void DidDataFromWebURLResponse(const ppapi::URLResponseInfoData& data);
// Sends the UpdateProgress message (if necessary) to the plugin.
@@ -129,7 +129,7 @@ class PepperURLLoaderHost
// always NULL check this value before using it. In the case of a main
// document load, you would call the functions on the document to cancel the
// load, etc. since there is no loader.
- scoped_ptr<WebKit::WebURLLoader> loader_;
+ scoped_ptr<blink::WebURLLoader> loader_;
int64_t bytes_sent_;
int64_t total_bytes_to_be_sent_;
diff --git a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
index 00a2c6bc349..4f171ff0a7a 100644
--- a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
@@ -24,13 +24,13 @@
// test it by making sure the conversion routines actually work at the same
// time.
-using WebKit::WebCString;
-using WebKit::WebFrame;
-using WebKit::WebFrameClient;
-using WebKit::WebString;
-using WebKit::WebView;
-using WebKit::WebURL;
-using WebKit::WebURLRequest;
+using blink::WebCString;
+using blink::WebFrame;
+using blink::WebFrameClient;
+using blink::WebString;
+using blink::WebView;
+using blink::WebURL;
+using blink::WebURLRequest;
namespace {
diff --git a/chromium/content/renderer/pepper/pepper_video_capture_host.cc b/chromium/content/renderer/pepper/pepper_video_capture_host.cc
index cf06bcaf1d0..732842402d6 100644
--- a/chromium/content/renderer/pepper/pepper_video_capture_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_capture_host.cc
@@ -17,9 +17,6 @@
#include "ppapi/shared_impl/host_resource.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_buffer_api.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebElement.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
using ppapi::HostResource;
using ppapi::TrackedCallback;
@@ -46,7 +43,8 @@ PepperVideoCaptureHost::PepperVideoCaptureHost(RendererPpapiHostImpl* host,
this,
PepperMediaDeviceManager::GetForRenderView(
host->GetRenderViewForInstance(pp_instance())),
- PP_DEVICETYPE_DEV_VIDEOCAPTURE) {
+ PP_DEVICETYPE_DEV_VIDEOCAPTURE,
+ host->GetDocumentURL(instance)) {
}
PepperVideoCaptureHost::~PepperVideoCaptureHost() {
@@ -118,6 +116,10 @@ void PepperVideoCaptureHost::OnError(media::VideoCapture* capture,
int error_code) {
// Today, the media layer only sends "1" as an error.
DCHECK(error_code == 1);
+ PostErrorReply();
+}
+
+void PepperVideoCaptureHost::PostErrorReply() {
// It either comes because some error was detected while starting (e.g. 2
// conflicting "master" resolution), or because the browser failed to start
// the capture.
@@ -133,6 +135,12 @@ void PepperVideoCaptureHost::OnFrameReady(
media::VideoCapture* capture,
const scoped_refptr<media::VideoFrame>& frame) {
DCHECK(frame.get());
+
+ if (alloc_size_ != frame->coded_size()) {
+ AllocBuffers(frame->coded_size(), capture->CaptureFrameRate());
+ alloc_size_ = frame->coded_size();
+ }
+
for (uint32_t i = 0; i < buffers_.size(); ++i) {
if (!buffers_[i].in_use) {
DCHECK_EQ(frame->format(), media::VideoFrame::I420);
@@ -165,13 +173,13 @@ void PepperVideoCaptureHost::OnFrameReady(
}
}
-void PepperVideoCaptureHost::OnDeviceInfoReceived(
- media::VideoCapture* capture,
- const media::VideoCaptureParams& device_info) {
+void PepperVideoCaptureHost::AllocBuffers(
+ const gfx::Size& resolution,
+ int frame_rate) {
PP_VideoCaptureDeviceInfo_Dev info = {
- static_cast<uint32_t>(device_info.width),
- static_cast<uint32_t>(device_info.height),
- static_cast<uint32_t>(device_info.frame_rate)
+ static_cast<uint32_t>(resolution.width()),
+ static_cast<uint32_t>(resolution.height()),
+ static_cast<uint32_t>(frame_rate)
};
ReleaseBuffers();
@@ -246,7 +254,7 @@ void PepperVideoCaptureHost::OnDeviceInfoReceived(
// capture.
SetStatus(PP_VIDEO_CAPTURE_STATUS_STOPPING, true);
platform_video_capture_->StopCapture(this);
- OnError(capture, PP_ERROR_NOMEMORY);
+ PostErrorReply();
return;
}
@@ -265,9 +273,8 @@ int32_t PepperVideoCaptureHost::OnOpen(
SetRequestedInfo(requested_info, buffer_count);
- PepperPluginInstance* instance =
- renderer_ppapi_host_->GetPluginInstance(pp_instance());
- if (!instance)
+ GURL document_url = renderer_ppapi_host_->GetDocumentURL(pp_instance());
+ if (!document_url.is_valid())
return PP_ERROR_FAILED;
RenderViewImpl* render_view = static_cast<RenderViewImpl*>(
@@ -275,7 +282,7 @@ int32_t PepperVideoCaptureHost::OnOpen(
platform_video_capture_ = new PepperPlatformVideoCapture(
render_view->AsWeakPtr(), device_id,
- instance->GetContainer()->element().document().url(), this);
+ document_url, this);
open_reply_context_ = context->MakeReplyMessageContext();
@@ -292,7 +299,7 @@ int32_t PepperVideoCaptureHost::OnStartCapture(
// It's safe to call this regardless it's capturing or not, because
// PepperPlatformVideoCapture maintains the state.
- platform_video_capture_->StartCapture(this, capability_);
+ platform_video_capture_->StartCapture(this, video_capture_params_);
return PP_OK;
}
@@ -358,12 +365,11 @@ void PepperVideoCaptureHost::SetRequestedInfo(
// Clamp the buffer count to between 1 and |kMaxBuffers|.
buffer_count_hint_ = std::min(std::max(buffer_count, 1U), kMaxBuffers);
- capability_.width = device_info.width;
- capability_.height = device_info.height;
- capability_.frame_rate = device_info.frames_per_second;
- capability_.expected_capture_delay = 0; // Ignored.
- capability_.color = media::PIXEL_FORMAT_I420;
- capability_.interlaced = false; // Ignored.
+ video_capture_params_.requested_format = media::VideoCaptureFormat(
+ gfx::Size(device_info.width, device_info.height),
+ device_info.frames_per_second,
+ media::PIXEL_FORMAT_I420);
+ video_capture_params_.allow_resolution_change = false;
}
void PepperVideoCaptureHost::DetachPlatformVideoCapture() {
diff --git a/chromium/content/renderer/pepper/pepper_video_capture_host.h b/chromium/content/renderer/pepper/pepper_video_capture_host.h
index ab6a3046a2d..a8312a2f5a8 100644
--- a/chromium/content/renderer/pepper/pepper_video_capture_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_capture_host.h
@@ -47,9 +47,6 @@ class PepperVideoCaptureHost
virtual void OnFrameReady(
media::VideoCapture* capture,
const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
- virtual void OnDeviceInfoReceived(
- media::VideoCapture* capture,
- const media::VideoCaptureParams& device_info) OVERRIDE;
private:
int32_t OnOpen(ppapi::host::HostMessageContext* context,
@@ -64,6 +61,9 @@ class PepperVideoCaptureHost
int32_t StopCapture();
int32_t Close();
+ void PostErrorReply();
+ void AllocBuffers(const gfx::Size& resolution,
+ int frame_rate);
void ReleaseBuffers();
void SendStatus();
@@ -88,10 +88,11 @@ class PepperVideoCaptureHost
RendererPpapiHostImpl* renderer_ppapi_host_;
+ gfx::Size alloc_size_;
std::vector<BufferInfo> buffers_;
size_t buffer_count_hint_;
- media::VideoCaptureCapability capability_;
+ media::VideoCaptureParams video_capture_params_;
PP_VideoCaptureStatus_Dev status_;
diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
index acbe8388353..129ee455222 100644
--- a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -32,23 +32,24 @@
#include "url/gurl.h"
using ppapi::NPObjectVar;
-using WebKit::WebCanvas;
-using WebKit::WebPlugin;
-using WebKit::WebPluginContainer;
-using WebKit::WebPluginParams;
-using WebKit::WebPoint;
-using WebKit::WebPrintParams;
-using WebKit::WebRect;
-using WebKit::WebSize;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebVector;
+using blink::WebCanvas;
+using blink::WebPlugin;
+using blink::WebPluginContainer;
+using blink::WebPluginParams;
+using blink::WebPoint;
+using blink::WebPrintParams;
+using blink::WebRect;
+using blink::WebSize;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebVector;
namespace content {
struct PepperWebPluginImpl::InitData {
scoped_refptr<PluginModule> module;
base::WeakPtr<RenderViewImpl> render_view;
+ RenderFrame* render_frame;
std::vector<std::string> arg_names;
std::vector<std::string> arg_values;
GURL url;
@@ -57,7 +58,8 @@ struct PepperWebPluginImpl::InitData {
PepperWebPluginImpl::PepperWebPluginImpl(
PluginModule* plugin_module,
const WebPluginParams& params,
- const base::WeakPtr<RenderViewImpl>& render_view)
+ const base::WeakPtr<RenderViewImpl>& render_view,
+ RenderFrame* render_frame)
: init_data_(new InitData()),
full_frame_(params.loadManually),
instance_object_(PP_MakeUndefined()),
@@ -65,6 +67,7 @@ PepperWebPluginImpl::PepperWebPluginImpl(
DCHECK(plugin_module);
init_data_->module = plugin_module;
init_data_->render_view = render_view;
+ init_data_->render_frame = render_frame;
for (size_t i = 0; i < params.attributeNames.size(); ++i) {
init_data_->arg_names.push_back(params.attributeNames[i].utf8());
init_data_->arg_values.push_back(params.attributeValues[i].utf8());
@@ -78,14 +81,14 @@ PepperWebPluginImpl::PepperWebPluginImpl(
PepperWebPluginImpl::~PepperWebPluginImpl() {
}
-WebKit::WebPluginContainer* PepperWebPluginImpl::container() const {
+blink::WebPluginContainer* PepperWebPluginImpl::container() const {
return container_;
}
bool PepperWebPluginImpl::initialize(WebPluginContainer* container) {
// The plugin delegate may have gone away.
instance_ = init_data_->module->CreateInstance(
- init_data_->render_view.get(), container, init_data_->url);
+ init_data_->render_view->main_render_frame(), container, init_data_->url);
if (!instance_.get())
return false;
@@ -99,9 +102,9 @@ bool PepperWebPluginImpl::initialize(WebPluginContainer* container) {
instance_->Delete();
instance_ = NULL;
- WebKit::WebPlugin* replacement_plugin =
+ blink::WebPlugin* replacement_plugin =
GetContentClient()->renderer()->CreatePluginReplacement(
- init_data_->render_view.get(), init_data_->module->path());
+ init_data_->render_frame, init_data_->module->path());
if (!replacement_plugin || !replacement_plugin->initialize(container))
return false;
@@ -147,7 +150,7 @@ NPObject* PepperWebPluginImpl::scriptableObject() {
}
NPObject* message_channel_np_object(instance_->message_channel().np_object());
// The object is expected to be retained before it is returned.
- WebKit::WebBindings::retainObject(message_channel_np_object);
+ blink::WebBindings::retainObject(message_channel_np_object);
return message_channel_np_object;
}
@@ -189,46 +192,46 @@ bool PepperWebPluginImpl::acceptsInputEvents() {
return true;
}
-bool PepperWebPluginImpl::handleInputEvent(const WebKit::WebInputEvent& event,
- WebKit::WebCursorInfo& cursor_info) {
+bool PepperWebPluginImpl::handleInputEvent(const blink::WebInputEvent& event,
+ blink::WebCursorInfo& cursor_info) {
if (instance_->FlashIsFullscreenOrPending())
return false;
return instance_->HandleInputEvent(event, &cursor_info);
}
void PepperWebPluginImpl::didReceiveResponse(
- const WebKit::WebURLResponse& response) {
+ const blink::WebURLResponse& response) {
DCHECK(!instance_->document_loader());
instance_->HandleDocumentLoad(response);
}
void PepperWebPluginImpl::didReceiveData(const char* data, int data_length) {
- WebKit::WebURLLoaderClient* document_loader = instance_->document_loader();
+ blink::WebURLLoaderClient* document_loader = instance_->document_loader();
if (document_loader)
document_loader->didReceiveData(NULL, data, data_length, 0);
}
void PepperWebPluginImpl::didFinishLoading() {
- WebKit::WebURLLoaderClient* document_loader = instance_->document_loader();
+ blink::WebURLLoaderClient* document_loader = instance_->document_loader();
if (document_loader)
document_loader->didFinishLoading(NULL, 0.0);
}
-void PepperWebPluginImpl::didFailLoading(const WebKit::WebURLError& error) {
- WebKit::WebURLLoaderClient* document_loader = instance_->document_loader();
+void PepperWebPluginImpl::didFailLoading(const blink::WebURLError& error) {
+ blink::WebURLLoaderClient* document_loader = instance_->document_loader();
if (document_loader)
document_loader->didFail(NULL, error);
}
void PepperWebPluginImpl::didFinishLoadingFrameRequest(
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
void* notify_data) {
}
void PepperWebPluginImpl::didFailLoadingFrameRequest(
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
void* notify_data,
- const WebKit::WebURLError& error) {
+ const blink::WebURLError& error) {
}
bool PepperWebPluginImpl::hasSelection() const {
@@ -251,7 +254,7 @@ void PepperWebPluginImpl::setZoomLevel(double level, bool text_only) {
instance_->Zoom(content::ZoomLevelToZoomFactor(level), text_only);
}
-bool PepperWebPluginImpl::startFind(const WebKit::WebString& search_text,
+bool PepperWebPluginImpl::startFind(const blink::WebString& search_text,
bool case_sensitive,
int identifier) {
return instance_->StartFind(search_text, case_sensitive, identifier);
@@ -278,7 +281,7 @@ int PepperWebPluginImpl::printBegin(const WebPrintParams& print_params) {
}
bool PepperWebPluginImpl::printPage(int page_number,
- WebKit::WebCanvas* canvas) {
+ blink::WebCanvas* canvas) {
return instance_->PrintPage(page_number, canvas);
}
diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.h b/chromium/content/renderer/pepper/pepper_webplugin_impl.h
index c96b44e33cb..600dd578d5b 100644
--- a/chromium/content/renderer/pepper/pepper_webplugin_impl.h
+++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.h
@@ -17,7 +17,7 @@
struct _NPP;
-namespace WebKit {
+namespace blink {
struct WebPluginParams;
struct WebPrintParams;
}
@@ -27,49 +27,51 @@ namespace content {
class PepperPluginInstanceImpl;
class PluginModule;
class PPB_URLLoader_Impl;
+class RenderFrame;
class RenderViewImpl;
-class PepperWebPluginImpl : public WebKit::WebPlugin {
+class PepperWebPluginImpl : public blink::WebPlugin {
public:
PepperWebPluginImpl(PluginModule* module,
- const WebKit::WebPluginParams& params,
- const base::WeakPtr<RenderViewImpl>& render_view);
+ const blink::WebPluginParams& params,
+ const base::WeakPtr<RenderViewImpl>& render_view,
+ RenderFrame* render_frame);
PepperPluginInstanceImpl* instance() { return instance_.get(); }
- // WebKit::WebPlugin implementation.
- virtual WebKit::WebPluginContainer* container() const;
- virtual bool initialize(WebKit::WebPluginContainer* container);
+ // blink::WebPlugin implementation.
+ virtual blink::WebPluginContainer* container() const;
+ virtual bool initialize(blink::WebPluginContainer* container);
virtual void destroy();
virtual NPObject* scriptableObject();
virtual struct _NPP* pluginNPP();
- virtual bool getFormValue(WebKit::WebString& value);
- virtual void paint(WebKit::WebCanvas* canvas, const WebKit::WebRect& rect);
+ virtual bool getFormValue(blink::WebString& value);
+ virtual void paint(blink::WebCanvas* canvas, const blink::WebRect& rect);
virtual void updateGeometry(
- const WebKit::WebRect& frame_rect,
- const WebKit::WebRect& clip_rect,
- const WebKit::WebVector<WebKit::WebRect>& cut_outs_rects,
+ const blink::WebRect& frame_rect,
+ const blink::WebRect& clip_rect,
+ const blink::WebVector<blink::WebRect>& cut_outs_rects,
bool is_visible);
virtual void updateFocus(bool focused);
virtual void updateVisibility(bool visible);
virtual bool acceptsInputEvents();
- virtual bool handleInputEvent(const WebKit::WebInputEvent& event,
- WebKit::WebCursorInfo& cursor_info);
- virtual void didReceiveResponse(const WebKit::WebURLResponse& response);
+ virtual bool handleInputEvent(const blink::WebInputEvent& event,
+ blink::WebCursorInfo& cursor_info);
+ virtual void didReceiveResponse(const blink::WebURLResponse& response);
virtual void didReceiveData(const char* data, int data_length);
virtual void didFinishLoading();
- virtual void didFailLoading(const WebKit::WebURLError&);
- virtual void didFinishLoadingFrameRequest(const WebKit::WebURL& url,
+ virtual void didFailLoading(const blink::WebURLError&);
+ virtual void didFinishLoadingFrameRequest(const blink::WebURL& url,
void* notify_data);
- virtual void didFailLoadingFrameRequest(const WebKit::WebURL& url,
+ virtual void didFailLoadingFrameRequest(const blink::WebURL& url,
void* notify_data,
- const WebKit::WebURLError& error);
+ const blink::WebURLError& error);
virtual bool hasSelection() const;
- virtual WebKit::WebString selectionAsText() const;
- virtual WebKit::WebString selectionAsMarkup() const;
- virtual WebKit::WebURL linkAtPosition(const WebKit::WebPoint& position) const;
+ virtual blink::WebString selectionAsText() const;
+ virtual blink::WebString selectionAsMarkup() const;
+ virtual blink::WebURL linkAtPosition(const blink::WebPoint& position) const;
virtual void setZoomLevel(double level, bool text_only);
- virtual bool startFind(const WebKit::WebString& search_text,
+ virtual bool startFind(const blink::WebString& search_text,
bool case_sensitive,
int identifier);
virtual void selectFindResult(bool forward);
@@ -77,8 +79,8 @@ class PepperWebPluginImpl : public WebKit::WebPlugin {
virtual bool supportsPaginatedPrint() OVERRIDE;
virtual bool isPrintScalingDisabled() OVERRIDE;
- virtual int printBegin(const WebKit::WebPrintParams& print_params) OVERRIDE;
- virtual bool printPage(int page_number, WebKit::WebCanvas* canvas) OVERRIDE;
+ virtual int printBegin(const blink::WebPrintParams& print_params) OVERRIDE;
+ virtual bool printPage(int page_number, blink::WebCanvas* canvas) OVERRIDE;
virtual void printEnd() OVERRIDE;
virtual bool canRotateView() OVERRIDE;
@@ -98,7 +100,7 @@ class PepperWebPluginImpl : public WebKit::WebPlugin {
scoped_refptr<PepperPluginInstanceImpl> instance_;
gfx::Rect plugin_rect_;
PP_Var instance_object_;
- WebKit::WebPluginContainer* container_;
+ blink::WebPluginContainer* container_;
DISALLOW_COPY_AND_ASSIGN(PepperWebPluginImpl);
};
diff --git a/chromium/content/renderer/pepper/pepper_websocket_host.cc b/chromium/content/renderer/pepper/pepper_websocket_host.cc
index 78870ef21b0..a88fdb54e47 100644
--- a/chromium/content/renderer/pepper/pepper_websocket_host.cc
+++ b/chromium/content/renderer/pepper/pepper_websocket_host.cc
@@ -22,11 +22,11 @@
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/WebKit/public/web/WebSocket.h"
-using WebKit::WebArrayBuffer;
-using WebKit::WebDocument;
-using WebKit::WebString;
-using WebKit::WebSocket;
-using WebKit::WebURL;
+using blink::WebArrayBuffer;
+using blink::WebDocument;
+using blink::WebString;
+using blink::WebSocket;
+using blink::WebURL;
namespace content {
@@ -77,7 +77,7 @@ void PepperWebSocketHost::didConnect() {
protocol));
}
-void PepperWebSocketHost::didReceiveMessage(const WebKit::WebString& message) {
+void PepperWebSocketHost::didReceiveMessage(const blink::WebString& message) {
// Dispose packets after receiving an error.
if (error_was_received_)
return;
@@ -90,7 +90,7 @@ void PepperWebSocketHost::didReceiveMessage(const WebKit::WebString& message) {
}
void PepperWebSocketHost::didReceiveArrayBuffer(
- const WebKit::WebArrayBuffer& binaryData) {
+ const blink::WebArrayBuffer& binaryData) {
// Dispose packets after receiving an error.
if (error_was_received_)
return;
@@ -135,7 +135,7 @@ void PepperWebSocketHost::didStartClosingHandshake() {
void PepperWebSocketHost::didClose(unsigned long unhandled_buffered_amount,
ClosingHandshakeCompletionStatus status,
unsigned short code,
- const WebKit::WebString& reason) {
+ const blink::WebString& reason) {
if (connecting_) {
connecting_ = false;
connect_reply_.params.set_result(PP_ERROR_FAILED);
@@ -224,8 +224,8 @@ int32_t PepperWebSocketHost::OnHostMsgConnect(
// Convert protocols to WebString.
WebString web_protocols = WebString::fromUTF8(protocol_string);
- // Create WebKit::WebSocket object and connect.
- WebKit::WebPluginContainer* container =
+ // Create blink::WebSocket object and connect.
+ blink::WebPluginContainer* container =
renderer_ppapi_host_->GetContainerForInstance(pp_instance());
if (!container)
return PP_ERROR_BADARGUMENT;
diff --git a/chromium/content/renderer/pepper/pepper_websocket_host.h b/chromium/content/renderer/pepper/pepper_websocket_host.h
index 7c8d5b2a614..3447fcf91a7 100644
--- a/chromium/content/renderer/pepper/pepper_websocket_host.h
+++ b/chromium/content/renderer/pepper/pepper_websocket_host.h
@@ -27,7 +27,7 @@ class RendererPpapiHost;
class CONTENT_EXPORT PepperWebSocketHost
: public ppapi::host::ResourceHost,
- public NON_EXPORTED_BASE(::WebKit::WebSocketClient) {
+ public NON_EXPORTED_BASE(::blink::WebSocketClient) {
public:
explicit PepperWebSocketHost(RendererPpapiHost* host,
PP_Instance instance,
@@ -40,15 +40,15 @@ class CONTENT_EXPORT PepperWebSocketHost
// WebSocketClient implementation.
virtual void didConnect();
- virtual void didReceiveMessage(const WebKit::WebString& message);
- virtual void didReceiveArrayBuffer(const WebKit::WebArrayBuffer& binaryData);
+ virtual void didReceiveMessage(const blink::WebString& message);
+ virtual void didReceiveArrayBuffer(const blink::WebArrayBuffer& binaryData);
virtual void didReceiveMessageError();
virtual void didUpdateBufferedAmount(unsigned long buffered_amount);
virtual void didStartClosingHandshake();
virtual void didClose(unsigned long unhandled_buffered_amount,
ClosingHandshakeCompletionStatus status,
unsigned short code,
- const WebKit::WebString& reason);
+ const blink::WebString& reason);
private:
// IPC message handlers.
int32_t OnHostMsgConnect(ppapi::host::HostMessageContext* context,
@@ -89,7 +89,7 @@ class CONTENT_EXPORT PepperWebSocketHost
// Keeps the WebKit side WebSocket object. This is used for calling WebKit
// side functions via WebKit API.
- scoped_ptr<WebKit::WebSocket> websocket_;
+ scoped_ptr<blink::WebSocket> websocket_;
DISALLOW_COPY_AND_ASSIGN(PepperWebSocketHost);
};
diff --git a/chromium/content/renderer/pepper/plugin_module.cc b/chromium/content/renderer/pepper/plugin_module.cc
index d8c193cbb9b..8ffc89e7adc 100644
--- a/chromium/content/renderer/pepper/plugin_module.cc
+++ b/chromium/content/renderer/pepper/plugin_module.cc
@@ -30,6 +30,7 @@
#include "content/renderer/pepper/ppb_video_decoder_impl.h"
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
#include "content/renderer/render_view_impl.h"
+#include "ppapi/c/dev/ppb_alarms_dev.h"
#include "ppapi/c/dev/ppb_audio_input_dev.h"
#include "ppapi/c/dev/ppb_buffer_dev.h"
#include "ppapi/c/dev/ppb_char_set_dev.h"
@@ -46,18 +47,17 @@
#include "ppapi/c/dev/ppb_printing_dev.h"
#include "ppapi/c/dev/ppb_resource_array_dev.h"
#include "ppapi/c/dev/ppb_scrollbar_dev.h"
-#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/c/dev/ppb_text_input_dev.h"
#include "ppapi/c/dev/ppb_trace_event_dev.h"
#include "ppapi/c/dev/ppb_truetype_font_dev.h"
#include "ppapi/c/dev/ppb_url_util_dev.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/dev/ppb_var_resource_dev.h"
#include "ppapi/c/dev/ppb_video_capture_dev.h"
#include "ppapi/c/dev/ppb_video_decoder_dev.h"
#include "ppapi/c/dev/ppb_view_dev.h"
#include "ppapi/c/dev/ppb_widget_dev.h"
#include "ppapi/c/dev/ppb_zoom_dev.h"
-#include "ppapi/c/extensions/dev/ppb_ext_alarms_dev.h"
#include "ppapi/c/extensions/dev/ppb_ext_socket_dev.h"
#include "ppapi/c/pp_module.h"
#include "ppapi/c/pp_resource.h"
@@ -111,11 +111,14 @@
#include "ppapi/c/private/ppb_flash_print.h"
#include "ppapi/c/private/ppb_host_resolver_private.h"
#include "ppapi/c/private/ppb_instance_private.h"
+#include "ppapi/c/private/ppb_isolated_file_system_private.h"
+#include "ppapi/c/private/ppb_output_protection_private.h"
#include "ppapi/c/private/ppb_pdf.h"
#include "ppapi/c/private/ppb_proxy_private.h"
#include "ppapi/c/private/ppb_talk_private.h"
#include "ppapi/c/private/ppb_tcp_server_socket_private.h"
#include "ppapi/c/private/ppb_tcp_socket_private.h"
+#include "ppapi/c/private/ppb_testing_private.h"
#include "ppapi/c/private/ppb_udp_socket_private.h"
#include "ppapi/c/private/ppb_uma_private.h"
#include "ppapi/c/private/ppb_video_destination_private.h"
@@ -125,7 +128,6 @@
#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
#include "ppapi/c/trusted/ppb_char_set_trusted.h"
#include "ppapi/c/trusted/ppb_file_chooser_trusted.h"
-#include "ppapi/c/trusted/ppb_file_io_trusted.h"
#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
#include "ppapi/shared_impl/callback_tracker.h"
#include "ppapi/shared_impl/ppapi_preferences.h"
@@ -284,7 +286,7 @@ void SetMinimumArrayBufferSizeForShmem(PP_Instance /*instance*/,
// Does nothing. Not needed in-process.
}
-const PPB_Testing_Dev testing_interface = {
+const PPB_Testing_Private testing_interface = {
&ReadImageData,
&RunMessageLoop,
&QuitMessageLoop,
@@ -334,10 +336,8 @@ const void* InternalGetInterface(const char* name) {
// in production code.
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnablePepperTesting)) {
- if (strcmp(name, PPB_TESTING_DEV_INTERFACE) == 0 ||
- strcmp(name, PPB_TESTING_DEV_INTERFACE_0_9) == 0) {
+ if (strcmp(name, PPB_TESTING_PRIVATE_INTERFACE) == 0)
return &testing_interface;
- }
}
return NULL;
}
@@ -382,7 +382,7 @@ bool LoadEntryPointsFromLibrary(
return true;
}
-void CreateHostForInProcessModule(RenderViewImpl* render_view,
+void CreateHostForInProcessModule(RenderFrameImpl* render_frame,
PluginModule* module,
const WebPluginInfo& webplugin_info) {
// First time an in-process plugin was used, make a host for it.
@@ -394,9 +394,8 @@ void CreateHostForInProcessModule(RenderViewImpl* render_view,
PepperPluginRegistry::GetInstance()->GetInfoForPlugin(
webplugin_info)->permissions);
RendererPpapiHostImpl* host_impl =
- RendererPpapiHostImpl::CreateOnModuleForInProcess(
- module, perms);
- render_view->PepperPluginCreated(host_impl);
+ RendererPpapiHostImpl::CreateOnModuleForInProcess(module, perms);
+ render_frame->PepperPluginCreated(host_impl);
}
} // namespace
@@ -551,11 +550,11 @@ bool PluginModule::SupportsInterface(const char* name) {
}
PepperPluginInstanceImpl* PluginModule::CreateInstance(
- RenderViewImpl* render_view,
- WebKit::WebPluginContainer* container,
+ RenderFrameImpl* render_frame,
+ blink::WebPluginContainer* container,
const GURL& plugin_url) {
PepperPluginInstanceImpl* instance = PepperPluginInstanceImpl::Create(
- render_view, this, container, plugin_url);
+ render_frame, this, container, plugin_url);
if (!instance) {
LOG(WARNING) << "Plugin doesn't support instance interface, failing.";
return NULL;
@@ -630,7 +629,7 @@ PepperBroker* PluginModule::GetBroker() {
}
RendererPpapiHostImpl* PluginModule::CreateOutOfProcessModule(
- RenderViewImpl* render_view,
+ RenderFrameImpl* render_frame,
const base::FilePath& path,
ppapi::PpapiPermissions permissions,
const IPC::ChannelHandle& channel_handle,
@@ -638,7 +637,7 @@ RendererPpapiHostImpl* PluginModule::CreateOutOfProcessModule(
int plugin_child_id,
bool is_external) {
scoped_refptr<PepperHungPluginFilter> hung_filter(new PepperHungPluginFilter(
- path, render_view->GetRoutingID(), plugin_child_id));
+ path, render_frame->GetRoutingID(), plugin_child_id));
scoped_ptr<HostDispatcherWrapper> dispatcher(
new HostDispatcherWrapper(this,
peer_pid,
@@ -648,14 +647,14 @@ RendererPpapiHostImpl* PluginModule::CreateOutOfProcessModule(
if (!dispatcher->Init(
channel_handle,
&GetInterface,
- ppapi::Preferences(render_view->webkit_preferences()),
+ ppapi::Preferences(render_frame->render_view()->webkit_preferences()),
hung_filter.get()))
return NULL;
RendererPpapiHostImpl* host_impl =
RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
this, dispatcher->dispatcher(), permissions);
- render_view->PepperPluginCreated(host_impl);
+ render_frame->PepperPluginCreated(host_impl);
InitAsProxied(dispatcher.release());
return host_impl;
@@ -680,7 +679,7 @@ bool PluginModule::InitializeModule(
}
scoped_refptr<PluginModule> PluginModule::Create(
- RenderViewImpl* render_view,
+ RenderFrameImpl* render_frame,
const WebPluginInfo& webplugin_info,
bool* pepper_plugin_was_registered) {
*pepper_plugin_was_registered = true;
@@ -694,7 +693,7 @@ scoped_refptr<PluginModule> PluginModule::Create(
// If the module exists and no embedder state was associated with it,
// then the module was one of the ones preloaded and is an in-process
// plugin. We need to associate our host state with it.
- CreateHostForInProcessModule(render_view, module.get(), webplugin_info);
+ CreateHostForInProcessModule(render_frame, module.get(), webplugin_info);
}
return module;
}
@@ -719,7 +718,7 @@ scoped_refptr<PluginModule> PluginModule::Create(
IPC::ChannelHandle channel_handle;
base::ProcessId peer_pid;
int plugin_child_id = 0;
- render_view->Send(new ViewHostMsg_OpenChannelToPepperPlugin(
+ render_frame->Send(new ViewHostMsg_OpenChannelToPepperPlugin(
path, &channel_handle, &peer_pid, &plugin_child_id));
if (channel_handle.name.empty()) {
// Couldn't be initialized.
@@ -731,7 +730,7 @@ scoped_refptr<PluginModule> PluginModule::Create(
module = new PluginModule(info->name, path, permissions);
PepperPluginRegistry::GetInstance()->AddLiveModule(path, module.get());
- if (!module->CreateOutOfProcessModule(render_view,
+ if (!module->CreateOutOfProcessModule(render_frame,
path,
permissions,
channel_handle,
diff --git a/chromium/content/renderer/pepper/plugin_module.h b/chromium/content/renderer/pepper/plugin_module.h
index daadf3cdec9..ad9463c45ad 100644
--- a/chromium/content/renderer/pepper/plugin_module.h
+++ b/chromium/content/renderer/pepper/plugin_module.h
@@ -41,16 +41,16 @@ namespace IPC {
struct ChannelHandle;
}
-namespace WebKit {
+namespace blink {
class WebPluginContainer;
-} // namespace WebKit
+} // namespace blink
namespace content {
class HostDispatcherWrapper;
class PepperPluginInstanceImpl;
class PepperBroker;
class RendererPpapiHostImpl;
-class RenderViewImpl;
+class RenderFrameImpl;
struct WebPluginInfo;
// Represents one plugin library loaded into one renderer. This library may
@@ -139,8 +139,8 @@ class CONTENT_EXPORT PluginModule :
const ppapi::PpapiPermissions& permissions() const { return permissions_; }
PepperPluginInstanceImpl* CreateInstance(
- RenderViewImpl* render_view,
- WebKit::WebPluginContainer* container,
+ RenderFrameImpl* render_frame,
+ blink::WebPluginContainer* container,
const GURL& plugin_url);
// Returns "some" plugin instance associated with this module. This is not
@@ -189,7 +189,7 @@ class CONTENT_EXPORT PluginModule :
// Create a new HostDispatcher for proxying, hook it to the PluginModule,
// and perform other common initialization.
RendererPpapiHostImpl* CreateOutOfProcessModule(
- RenderViewImpl* render_view,
+ RenderFrameImpl* render_frame,
const base::FilePath& path,
ppapi::PpapiPermissions permissions,
const IPC::ChannelHandle& channel_handle,
@@ -212,7 +212,7 @@ class CONTENT_EXPORT PluginModule :
// the second is that the plugin failed to initialize. In this case,
// |*pepper_plugin_was_registered| will be set to true and the caller should
// not fall back on any other plugin types.
- static scoped_refptr<PluginModule> Create(RenderViewImpl* render_view,
+ static scoped_refptr<PluginModule> Create(RenderFrameImpl* render_frame,
const WebPluginInfo& webplugin_info,
bool* pepper_plugin_was_registered);
diff --git a/chromium/content/renderer/pepper/plugin_object.cc b/chromium/content/renderer/pepper/plugin_object.cc
index 7746846a288..55e4c6c08ec 100644
--- a/chromium/content/renderer/pepper/plugin_object.cc
+++ b/chromium/content/renderer/pepper/plugin_object.cc
@@ -27,7 +27,7 @@
using ppapi::PpapiGlobals;
using ppapi::StringVar;
using ppapi::Var;
-using WebKit::WebBindings;
+using blink::WebBindings;
namespace content {
diff --git a/chromium/content/renderer/pepper/ppb_broker_impl.cc b/chromium/content/renderer/pepper/ppb_broker_impl.cc
index f68d257e145..882c5db74aa 100644
--- a/chromium/content/renderer/pepper/ppb_broker_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_broker_impl.cc
@@ -84,7 +84,7 @@ int32_t PPB_Broker_Impl::Connect(
RenderThreadImpl::current()->Send(
new ViewHostMsg_RequestPpapiBrokerPermission(
- plugin_instance->render_view()->GetRoutingID(),
+ plugin_instance->render_frame()->render_view()->GetRoutingID(),
routing_id_,
GetDocumentUrl(),
broker_path));
diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
index b48d68ab030..1564279f7b4 100644
--- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -27,10 +27,10 @@
using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_Graphics3D_API;
-using WebKit::WebConsoleMessage;
-using WebKit::WebFrame;
-using WebKit::WebPluginContainer;
-using WebKit::WebString;
+using blink::WebConsoleMessage;
+using blink::WebFrame;
+using blink::WebPluginContainer;
+using blink::WebString;
namespace content {
@@ -160,7 +160,7 @@ gpu::CommandBuffer::State PPB_Graphics3D_Impl::FlushSyncFast(
}
uint32_t PPB_Graphics3D_Impl::InsertSyncPoint() {
- return GetCommandBuffer()->InsertSyncPoint();
+ return platform_context_->GetGpuControl()->InsertSyncPoint();
}
bool PPB_Graphics3D_Impl::BindToInstance(bool bind) {
@@ -172,9 +172,6 @@ bool PPB_Graphics3D_Impl::IsOpaque() {
return platform_context_->IsOpaque();
}
-void PPB_Graphics3D_Impl::ViewWillInitiatePaint() {
-}
-
void PPB_Graphics3D_Impl::ViewInitiatedPaint() {
commit_pending_ = false;
@@ -189,6 +186,10 @@ gpu::CommandBuffer* PPB_Graphics3D_Impl::GetCommandBuffer() {
return platform_context_->GetCommandBuffer();
}
+gpu::GpuControl* PPB_Graphics3D_Impl::GetGpuControl() {
+ return platform_context_->GetGpuControl();
+}
+
int32 PPB_Graphics3D_Impl::DoSwapBuffers() {
// We do not have a GLES2 implementation when using an OOP proxy.
// The plugin-side proxy is responsible for adding the SwapBuffers command
@@ -333,7 +334,11 @@ void PPB_Graphics3D_Impl::SendContextLost() {
static_cast<const PPP_Graphics3D*>(
instance->module()->GetPluginInterface(
PPP_GRAPHICS_3D_INTERFACE));
- if (ppp_graphics_3d)
+ // We have to check *again* that the instance exists, because it could have
+ // been deleted during GetPluginInterface(). Even the PluginModule could be
+ // deleted, but in that case, the instance should also be gone, so the
+ // GetInstance check covers both cases.
+ if (ppp_graphics_3d && HostGlobals::Get()->GetInstance(this_pp_instance))
ppp_graphics_3d->Graphics3DContextLost(this_pp_instance);
}
diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
index 3e1c797526b..d4d4c2bad28 100644
--- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
+++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
@@ -45,7 +45,6 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
// Notifications about the view's progress painting. See PluginInstance.
// These messages are used to send Flush callbacks to the plugin.
- void ViewWillInitiatePaint();
void ViewInitiatedPaint();
void ViewFlushedPaint();
@@ -55,6 +54,7 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
virtual ~PPB_Graphics3D_Impl();
// ppapi::PPB_Graphics3D_Shared overrides.
virtual gpu::CommandBuffer* GetCommandBuffer() OVERRIDE;
+ virtual gpu::GpuControl* GetGpuControl() OVERRIDE;
virtual int32 DoSwapBuffers() OVERRIDE;
private:
diff --git a/chromium/content/renderer/pepper/ppb_image_data_impl.cc b/chromium/content/renderer/pepper/ppb_image_data_impl.cc
index 9ea83d5e2f4..80cc38dcd3d 100644
--- a/chromium/content/renderer/pepper/ppb_image_data_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_image_data_impl.cc
@@ -25,6 +25,19 @@ using ppapi::thunk::PPB_ImageData_API;
namespace content {
+namespace {
+// Returns true if the ImageData shared memory should be allocated in the
+// browser process for the current platform.
+bool IsBrowserAllocated() {
+#if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID)
+ // On the Mac, shared memory has to be created in the browser in order to
+ // work in the sandbox.
+ return true;
+#endif
+ return false;
+}
+} // namespace
+
PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance,
PPB_ImageData_Shared::ImageDataType type)
: Resource(ppapi::OBJECT_IS_IMPL, instance),
@@ -33,7 +46,7 @@ PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance,
height_(0) {
switch (type) {
case PPB_ImageData_Shared::PLATFORM:
- backend_.reset(new ImageDataPlatformBackend);
+ backend_.reset(new ImageDataPlatformBackend(IsBrowserAllocated()));
return;
case PPB_ImageData_Shared::SIMPLE:
backend_.reset(new ImageDataSimpleBackend);
@@ -43,6 +56,15 @@ PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance,
NOTREACHED();
}
+PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance,
+ ForTest)
+ : Resource(ppapi::OBJECT_IS_IMPL, instance),
+ format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL),
+ width_(0),
+ height_(0) {
+ backend_.reset(new ImageDataPlatformBackend(false));
+}
+
PPB_ImageData_Impl::~PPB_ImageData_Impl() {
}
@@ -127,19 +149,22 @@ const SkBitmap* PPB_ImageData_Impl::GetMappedBitmap() const {
// ImageDataPlatformBackend ----------------------------------------------------
-ImageDataPlatformBackend::ImageDataPlatformBackend()
+ImageDataPlatformBackend::ImageDataPlatformBackend(bool is_browser_allocated)
: width_(0),
- height_(0) {
+ height_(0),
+ is_browser_allocated_(is_browser_allocated) {
}
// On POSIX, we have to tell the browser to free the transport DIB.
ImageDataPlatformBackend::~ImageDataPlatformBackend() {
-#if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID)
- if (dib_) {
- RenderThreadImpl::current()->Send(
- new ViewHostMsg_FreeTransportDIB(dib_->id()));
- }
+ if (is_browser_allocated_) {
+#if defined(OS_POSIX)
+ if (dib_) {
+ RenderThreadImpl::current()->Send(
+ new ViewHostMsg_FreeTransportDIB(dib_->id()));
+ }
#endif
+ }
}
bool ImageDataPlatformBackend::Init(PPB_ImageData_Impl* impl,
@@ -152,30 +177,32 @@ bool ImageDataPlatformBackend::Init(PPB_ImageData_Impl* impl,
uint32 buffer_size = width_ * height_ * 4;
// Allocate the transport DIB and the PlatformCanvas pointing to it.
-#if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID)
- // On the Mac, shared memory has to be created in the browser in order to
- // work in the sandbox. Do this by sending a message to the browser
- // requesting a TransportDIB (see also
- // chrome/renderer/webplugin_delegate_proxy.cc, method
- // WebPluginDelegateProxy::CreateBitmap() for similar code). The TransportDIB
- // is cached in the browser, and is freed (in typical cases) by the
- // TransportDIB's destructor.
- TransportDIB::Handle dib_handle;
- IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(buffer_size,
- true,
- &dib_handle);
- if (!RenderThreadImpl::current()->Send(msg))
- return false;
- if (!TransportDIB::is_valid_handle(dib_handle))
- return false;
-
- TransportDIB* dib = TransportDIB::CreateWithHandle(dib_handle);
-#else
- static int next_dib_id = 0;
- TransportDIB* dib = TransportDIB::Create(buffer_size, next_dib_id++);
- if (!dib)
- return false;
+ TransportDIB* dib = NULL;
+ if (is_browser_allocated_) {
+#if defined(OS_POSIX)
+ // Allocate the image data by sending a message to the browser requesting a
+ // TransportDIB (see also chrome/renderer/webplugin_delegate_proxy.cc,
+ // method WebPluginDelegateProxy::CreateBitmap() for similar code). The
+ // TransportDIB is cached in the browser, and is freed (in typical cases) by
+ // the TransportDIB's destructor.
+ TransportDIB::Handle dib_handle;
+ IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(buffer_size,
+ true,
+ &dib_handle);
+ if (!RenderThreadImpl::current()->Send(msg))
+ return false;
+ if (!TransportDIB::is_valid_handle(dib_handle))
+ return false;
+
+ dib = TransportDIB::CreateWithHandle(dib_handle);
#endif
+ } else {
+ static int next_dib_id = 0;
+ dib = TransportDIB::Create(buffer_size, next_dib_id++);
+ if (!dib)
+ return false;
+ }
+ DCHECK(dib);
dib_.reset(dib);
return true;
}
@@ -198,7 +225,7 @@ void* ImageDataPlatformBackend::Map() {
skia::GetTopDevice(*mapped_canvas_)->accessBitmap(true);
// Our platform bitmaps are set to opaque by default, which we don't want.
- const_cast<SkBitmap&>(bitmap).setIsOpaque(false);
+ const_cast<SkBitmap&>(bitmap).setAlphaType(kPremul_SkAlphaType);
bitmap.lockPixels();
return bitmap.getAddr32(0, 0);
@@ -273,7 +300,7 @@ void* ImageDataSimpleBackend::Map() {
shared_memory_->Map(skia_bitmap_.getSize());
skia_bitmap_.setPixels(shared_memory_->memory());
// Our platform bitmaps are set to opaque by default, which we don't want.
- skia_bitmap_.setIsOpaque(false);
+ skia_bitmap_.setAlphaType(kPremul_SkAlphaType);
skia_canvas_.reset(new SkCanvas(skia_bitmap_));
return skia_bitmap_.getAddr32(0, 0);
}
diff --git a/chromium/content/renderer/pepper/ppb_image_data_impl.h b/chromium/content/renderer/pepper/ppb_image_data_impl.h
index a16bbfa104b..49c399b1d39 100644
--- a/chromium/content/renderer/pepper/ppb_image_data_impl.h
+++ b/chromium/content/renderer/pepper/ppb_image_data_impl.h
@@ -54,6 +54,11 @@ class CONTENT_EXPORT PPB_ImageData_Impl
PPB_ImageData_Impl(PP_Instance instance,
PPB_ImageData_Shared::ImageDataType type);
+ // Constructor used for unittests. The ImageData is always allocated locally.
+ struct ForTest {};
+ PPB_ImageData_Impl(PP_Instance instance,
+ ForTest);
+
bool Init(PP_ImageDataFormat format,
int width, int height,
bool init_to_zero);
@@ -102,7 +107,9 @@ class CONTENT_EXPORT PPB_ImageData_Impl
class ImageDataPlatformBackend : public PPB_ImageData_Impl::Backend {
public:
- ImageDataPlatformBackend();
+ // |is_browser_allocated| indicates whether the backing shared memory should
+ // be allocated by the browser process.
+ ImageDataPlatformBackend(bool is_browser_allocated);
virtual ~ImageDataPlatformBackend();
// PPB_ImageData_Impl::Backend implementation.
@@ -124,6 +131,8 @@ class ImageDataPlatformBackend : public PPB_ImageData_Impl::Backend {
int height_;
scoped_ptr<TransportDIB> dib_;
+ bool is_browser_allocated_;
+
// When the device is mapped, this is the image. Null when umapped.
scoped_ptr<SkCanvas> mapped_canvas_;
diff --git a/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc b/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc
index fb01c597569..326c7003183 100644
--- a/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc
@@ -27,10 +27,10 @@
#endif
using ppapi::thunk::PPB_Scrollbar_API;
-using WebKit::WebInputEvent;
-using WebKit::WebRect;
-using WebKit::WebScrollbar;
-using WebKit::WebPluginScrollbar;
+using blink::WebInputEvent;
+using blink::WebRect;
+using blink::WebScrollbar;
+using blink::WebPluginScrollbar;
namespace content {
@@ -59,7 +59,7 @@ void PPB_Scrollbar_Impl::Init(bool vertical) {
scrollbar_.reset(WebPluginScrollbar::createForPlugin(
vertical ? WebScrollbar::Vertical : WebScrollbar::Horizontal,
plugin_instance->container(),
- static_cast<WebKit::WebPluginScrollbarClient*>(this)));
+ static_cast<blink::WebPluginScrollbarClient*>(this)));
}
PPB_Scrollbar_API* PPB_Scrollbar_Impl::AsPPB_Scrollbar_API() {
@@ -168,7 +168,7 @@ void PPB_Scrollbar_Impl::SetLocationInternal(const PP_Rect* location) {
location->size.height));
}
-void PPB_Scrollbar_Impl::valueChanged(WebKit::WebPluginScrollbar* scrollbar) {
+void PPB_Scrollbar_Impl::valueChanged(blink::WebPluginScrollbar* scrollbar) {
PluginModule* plugin_module =
HostGlobals::Get()->GetInstance(pp_instance())->module();
if (!plugin_module)
@@ -206,8 +206,8 @@ void PPB_Scrollbar_Impl::overlayChanged(WebPluginScrollbar* scrollbar) {
}
void PPB_Scrollbar_Impl::invalidateScrollbarRect(
- WebKit::WebPluginScrollbar* scrollbar,
- const WebKit::WebRect& rect) {
+ blink::WebPluginScrollbar* scrollbar,
+ const blink::WebRect& rect) {
gfx::Rect gfx_rect(rect.x,
rect.y,
rect.width,
@@ -217,8 +217,8 @@ void PPB_Scrollbar_Impl::invalidateScrollbarRect(
// since the PPB_Scrollbar_Impl code is still in the middle of updating its
// internal state.
// Note: we use a WeakPtrFactory here so that a lingering callback can not
- // modify the lifetime of this object. Otherwise, WebKit::WebPluginScrollbar
- // could outlive WebKit::WebPluginContainer, which is against its contract.
+ // modify the lifetime of this object. Otherwise, blink::WebPluginScrollbar
+ // could outlive blink::WebPluginContainer, which is against its contract.
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&PPB_Scrollbar_Impl::NotifyInvalidate,
@@ -226,8 +226,8 @@ void PPB_Scrollbar_Impl::invalidateScrollbarRect(
}
void PPB_Scrollbar_Impl::getTickmarks(
- WebKit::WebPluginScrollbar* scrollbar,
- WebKit::WebVector<WebKit::WebRect>* tick_marks) const {
+ blink::WebPluginScrollbar* scrollbar,
+ blink::WebVector<blink::WebRect>* tick_marks) const {
if (tickmarks_.empty()) {
WebRect* rects = NULL;
tick_marks->assign(rects, 0);
diff --git a/chromium/content/renderer/pepper/ppb_scrollbar_impl.h b/chromium/content/renderer/pepper/ppb_scrollbar_impl.h
index eb7906b26b0..f649c816d8c 100644
--- a/chromium/content/renderer/pepper/ppb_scrollbar_impl.h
+++ b/chromium/content/renderer/pepper/ppb_scrollbar_impl.h
@@ -20,7 +20,7 @@ namespace content {
class PPB_Scrollbar_Impl : public PPB_Widget_Impl,
public ppapi::thunk::PPB_Scrollbar_API,
- public WebKit::WebPluginScrollbarClient {
+ public blink::WebPluginScrollbarClient {
public:
static PP_Resource Create(PP_Instance instance, bool vertical);
@@ -50,20 +50,20 @@ class PPB_Scrollbar_Impl : public PPB_Widget_Impl,
const ppapi::InputEventData& data) OVERRIDE;
virtual void SetLocationInternal(const PP_Rect* location) OVERRIDE;
- // WebKit::WebPluginScrollbarClient implementation.
- virtual void valueChanged(WebKit::WebPluginScrollbar* scrollbar) OVERRIDE;
- virtual void overlayChanged(WebKit::WebPluginScrollbar* scrollbar) OVERRIDE;
- virtual void invalidateScrollbarRect(WebKit::WebPluginScrollbar* scrollbar,
- const WebKit::WebRect& rect) OVERRIDE;
+ // blink::WebPluginScrollbarClient implementation.
+ virtual void valueChanged(blink::WebPluginScrollbar* scrollbar) OVERRIDE;
+ virtual void overlayChanged(blink::WebPluginScrollbar* scrollbar) OVERRIDE;
+ virtual void invalidateScrollbarRect(blink::WebPluginScrollbar* scrollbar,
+ const blink::WebRect& rect) OVERRIDE;
virtual void getTickmarks(
- WebKit::WebPluginScrollbar* scrollbar,
- WebKit::WebVector<WebKit::WebRect>* tick_marks) const OVERRIDE;
+ blink::WebPluginScrollbar* scrollbar,
+ blink::WebVector<blink::WebRect>* tick_marks) const OVERRIDE;
void NotifyInvalidate();
gfx::Rect dirty_;
- std::vector<WebKit::WebRect> tickmarks_;
- scoped_ptr<WebKit::WebPluginScrollbar> scrollbar_;
+ std::vector<blink::WebRect> tickmarks_;
+ scoped_ptr<blink::WebPluginScrollbar> scrollbar_;
// Used so that the post task for Invalidate doesn't keep an extra reference.
base::WeakPtrFactory<PPB_Scrollbar_Impl> weak_ptr_factory_;
diff --git a/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc b/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc
index 23472fac26c..6f12733c1a4 100644
--- a/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc
@@ -24,7 +24,7 @@ using ppapi::NPObjectVar;
using ppapi::PpapiGlobals;
using ppapi::StringVar;
using ppapi::Var;
-using WebKit::WebBindings;
+using blink::WebBindings;
namespace content {
@@ -333,7 +333,7 @@ PP_Var CallDeprecated(PP_Var var,
return PP_MakeUndefined();
PepperPluginInstanceImpl* plugin = accessor.GetPluginInstance();
if (plugin && plugin->IsProcessingUserGesture()) {
- WebKit::WebScopedUserGesture user_gesture(
+ blink::WebScopedUserGesture user_gesture(
plugin->CurrentUserGestureToken());
return InternalCallDeprecated(&accessor, method_name, argc, argv,
exception);
diff --git a/chromium/content/renderer/pepper/quota_file_io.cc b/chromium/content/renderer/pepper/quota_file_io.cc
deleted file mode 100644
index a5e4f6b3dd1..00000000000
--- a/chromium/content/renderer/pepper/quota_file_io.cc
+++ /dev/null
@@ -1,390 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/pepper/quota_file_io.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/stl_util.h"
-#include "base/task_runner_util.h"
-#include "content/renderer/pepper/host_globals.h"
-
-using base::PlatformFile;
-using base::PlatformFileError;
-using quota::StorageType;
-
-namespace content {
-
-namespace {
-StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) {
- switch (type) {
- case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
- return quota::kStorageTypePersistent;
- case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
- return quota::kStorageTypeTemporary;
- default:
- return quota::kStorageTypeUnknown;
- }
- NOTREACHED();
- return quota::kStorageTypeUnknown;
-}
-
-int WriteAdapter(PlatformFile file, int64 offset,
- scoped_ptr<char[]> data, int size) {
- return base::WritePlatformFile(file, offset, data.get(), size);
-}
-
-} // namespace
-
-class QuotaFileIO::PendingOperationBase {
- public:
- virtual ~PendingOperationBase() {}
-
- // Either one of Run() or DidFail() is called (the latter is called when
- // there was more than one error during quota queries).
- virtual void Run() = 0;
- virtual void DidFail(PlatformFileError error) = 0;
-
- protected:
- PendingOperationBase(QuotaFileIO* quota_io, bool is_will_operation)
- : quota_io_(quota_io), is_will_operation_(is_will_operation) {
- DCHECK(quota_io_);
- quota_io_->WillUpdate();
- }
-
- QuotaFileIO* quota_io_;
- const bool is_will_operation_;
-};
-
-class QuotaFileIO::WriteOperation : public PendingOperationBase {
- public:
- WriteOperation(QuotaFileIO* quota_io,
- bool is_will_operation,
- int64_t offset,
- const char* buffer,
- int32_t bytes_to_write,
- const WriteCallback& callback)
- : PendingOperationBase(quota_io, is_will_operation),
- offset_(offset),
- bytes_to_write_(bytes_to_write),
- callback_(callback),
- finished_(false),
- status_(base::PLATFORM_FILE_OK),
- bytes_written_(0),
- weak_factory_(this) {
- if (!is_will_operation) {
- // TODO(kinuko): Check the API convention if we really need to keep a copy
- // of the buffer during the async write operations.
- buffer_.reset(new char[bytes_to_write]);
- memcpy(buffer_.get(), buffer, bytes_to_write);
- }
- }
- virtual ~WriteOperation() {}
- virtual void Run() OVERRIDE {
- DCHECK(quota_io_);
- if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) {
- DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE);
- return;
- }
- if (is_will_operation_) {
- // Assuming the write will succeed.
- DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_);
- return;
- }
- DCHECK(buffer_.get());
-
- if (!base::PostTaskAndReplyWithResult(
- quota_io_->delegate()->GetFileThreadMessageLoopProxy().get(),
- FROM_HERE,
- base::Bind(&WriteAdapter,
- quota_io_->file_,
- offset_,
- base::Passed(&buffer_),
- bytes_to_write_),
- base::Bind(&WriteOperation::DidWrite,
- weak_factory_.GetWeakPtr()))) {
- DidFail(base::PLATFORM_FILE_ERROR_FAILED);
- return;
- }
- }
-
- virtual void DidFail(PlatformFileError error) OVERRIDE {
- DidFinish(error, 0);
- }
-
- bool finished() const { return finished_; }
-
- virtual void WillRunCallback() {
- base::MessageLoopProxy::current()->PostTask(
- FROM_HERE,
- base::Bind(&WriteOperation::RunCallback, weak_factory_.GetWeakPtr()));
- }
-
- private:
- void DidWrite(int bytes_written) {
- base::PlatformFileError error = bytes_written > 0 ?
- base::PLATFORM_FILE_OK : base::PLATFORM_FILE_ERROR_FAILED;
- DidFinish(error, bytes_written);
- }
-
- void DidFinish(PlatformFileError status, int bytes_written) {
- finished_ = true;
- status_ = status;
- bytes_written_ = bytes_written;
- int64_t max_offset =
- (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written;
- // This may delete itself by calling RunCallback.
- quota_io_->DidWrite(this, max_offset);
- }
-
- virtual void RunCallback() {
- DCHECK_EQ(false, callback_.is_null());
- callback_.Run(status_, bytes_written_);
- delete this;
- }
-
- const int64_t offset_;
- scoped_ptr<char[]> buffer_;
- const int32_t bytes_to_write_;
- WriteCallback callback_;
- bool finished_;
- PlatformFileError status_;
- int64_t bytes_written_;
- base::WeakPtrFactory<WriteOperation> weak_factory_;
-};
-
-class QuotaFileIO::SetLengthOperation : public PendingOperationBase {
- public:
- SetLengthOperation(QuotaFileIO* quota_io,
- bool is_will_operation,
- int64_t length,
- const StatusCallback& callback)
- : PendingOperationBase(quota_io, is_will_operation),
- length_(length),
- callback_(callback),
- weak_factory_(this) {}
-
- virtual ~SetLengthOperation() {}
-
- virtual void Run() OVERRIDE {
- DCHECK(quota_io_);
- if (quota_io_->CheckIfExceedsQuota(length_)) {
- DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE);
- return;
- }
- if (is_will_operation_) {
- DidFinish(base::PLATFORM_FILE_OK);
- return;
- }
-
- if (!base::FileUtilProxy::Truncate(
- quota_io_->delegate()->GetFileThreadMessageLoopProxy().get(),
- quota_io_->file_,
- length_,
- base::Bind(&SetLengthOperation::DidFinish,
- weak_factory_.GetWeakPtr()))) {
- DidFail(base::PLATFORM_FILE_ERROR_FAILED);
- return;
- }
- }
-
- virtual void DidFail(PlatformFileError error) OVERRIDE {
- DidFinish(error);
- }
-
- private:
- void DidFinish(PlatformFileError status) {
- quota_io_->DidSetLength(status, length_);
- DCHECK_EQ(false, callback_.is_null());
- callback_.Run(status);
- delete this;
- }
-
- int64_t length_;
- StatusCallback callback_;
- base::WeakPtrFactory<SetLengthOperation> weak_factory_;
-};
-
-// QuotaFileIO --------------------------------------------------------------
-
-QuotaFileIO::QuotaFileIO(
- Delegate* delegate,
- PlatformFile file,
- const GURL& file_url,
- PP_FileSystemType type)
- : delegate_(delegate),
- file_(file),
- file_url_(file_url),
- storage_type_(PPFileSystemTypeToQuotaStorageType(type)),
- cached_file_size_(0),
- cached_available_space_(0),
- outstanding_quota_queries_(0),
- outstanding_errors_(0),
- max_written_offset_(0),
- inflight_operations_(0),
- weak_factory_(this) {
- DCHECK_NE(base::kInvalidPlatformFileValue, file_);
- DCHECK_NE(quota::kStorageTypeUnknown, storage_type_);
-}
-
-QuotaFileIO::~QuotaFileIO() {
- // Note that this doesn't dispatch pending callbacks.
- STLDeleteContainerPointers(pending_operations_.begin(),
- pending_operations_.end());
- STLDeleteContainerPointers(pending_callbacks_.begin(),
- pending_callbacks_.end());
-}
-
-bool QuotaFileIO::Write(
- int64_t offset, const char* buffer, int32_t bytes_to_write,
- const WriteCallback& callback) {
- if (bytes_to_write <= 0)
- return false;
-
- WriteOperation* op = new WriteOperation(
- this, false, offset, buffer, bytes_to_write, callback);
- return RegisterOperationForQuotaChecks(op);
-}
-
-bool QuotaFileIO::SetLength(int64_t length, const StatusCallback& callback) {
- DCHECK(pending_operations_.empty());
- SetLengthOperation* op = new SetLengthOperation(
- this, false, length, callback);
- return RegisterOperationForQuotaChecks(op);
-}
-
-bool QuotaFileIO::WillWrite(
- int64_t offset, int32_t bytes_to_write, const WriteCallback& callback) {
- WriteOperation* op = new WriteOperation(
- this, true, offset, NULL, bytes_to_write, callback);
- return RegisterOperationForQuotaChecks(op);
-}
-
-bool QuotaFileIO::WillSetLength(int64_t length,
- const StatusCallback& callback) {
- DCHECK(pending_operations_.empty());
- SetLengthOperation* op = new SetLengthOperation(this, true, length, callback);
- return RegisterOperationForQuotaChecks(op);
-}
-
-bool QuotaFileIO::RegisterOperationForQuotaChecks(
- PendingOperationBase* op_ptr) {
- scoped_ptr<PendingOperationBase> op(op_ptr);
- if (pending_operations_.empty()) {
- // This is the first pending quota check. Run querying the file size
- // and available space.
- outstanding_quota_queries_ = 0;
- outstanding_errors_ = 0;
-
- // Query the file size.
- ++outstanding_quota_queries_;
- if (!base::FileUtilProxy::GetFileInfoFromPlatformFile(
- delegate_->GetFileThreadMessageLoopProxy().get(),
- file_,
- base::Bind(&QuotaFileIO::DidQueryInfoForQuota,
- weak_factory_.GetWeakPtr()))) {
- // This makes the call fail synchronously; we do not fire the callback
- // here but just delete the operation and return false.
- return false;
- }
-
- // Query the current available space.
- ++outstanding_quota_queries_;
- delegate_->QueryAvailableSpace(
- file_url_.GetOrigin(), storage_type_,
- base::Bind(&QuotaFileIO::DidQueryAvailableSpace,
- weak_factory_.GetWeakPtr()));
- }
- pending_operations_.push_back(op.release());
- return true;
-}
-
-void QuotaFileIO::DidQueryInfoForQuota(
- base::PlatformFileError error_code,
- const base::PlatformFileInfo& file_info) {
- if (error_code != base::PLATFORM_FILE_OK)
- ++outstanding_errors_;
- cached_file_size_ = file_info.size;
- DCHECK_GT(outstanding_quota_queries_, 0);
- if (--outstanding_quota_queries_ == 0)
- DidQueryForQuotaCheck();
-}
-
-void QuotaFileIO::DidQueryAvailableSpace(int64_t avail_space) {
- cached_available_space_ = avail_space;
- DCHECK_GT(outstanding_quota_queries_, 0);
- if (--outstanding_quota_queries_ == 0)
- DidQueryForQuotaCheck();
-}
-
-void QuotaFileIO::DidQueryForQuotaCheck() {
- DCHECK(!pending_operations_.empty());
- DCHECK_GT(inflight_operations_, 0);
- while (!pending_operations_.empty()) {
- PendingOperationBase* op = pending_operations_.front();
- pending_operations_.pop_front();
- pending_callbacks_.push_back(op);
- if (outstanding_errors_ > 0) {
- op->DidFail(base::PLATFORM_FILE_ERROR_FAILED);
- continue;
- }
- op->Run();
- }
-}
-
-bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const {
- DCHECK_GE(cached_file_size_, 0);
- DCHECK_GE(cached_available_space_, 0);
- return new_file_size - cached_file_size_ > cached_available_space_;
-}
-
-void QuotaFileIO::WillUpdate() {
- if (inflight_operations_++ == 0) {
- delegate_->WillUpdateFile(file_url_);
- DCHECK_EQ(0, max_written_offset_);
- }
-}
-
-void QuotaFileIO::DidWrite(WriteOperation* op,
- int64_t written_offset_end) {
- max_written_offset_ = std::max(max_written_offset_, written_offset_end);
- DCHECK_GT(inflight_operations_, 0);
- DCHECK(!pending_callbacks_.empty());
- // Fire callbacks for finished operations.
- while (!pending_callbacks_.empty()) {
- WriteOperation* op = static_cast<WriteOperation*>(
- pending_callbacks_.front());
- if (!op->finished())
- break;
- pending_callbacks_.pop_front();
- op->WillRunCallback();
- }
- // If we have no more pending writes, notify the browser that we did
- // update the file.
- if (--inflight_operations_ == 0) {
- DCHECK(pending_operations_.empty());
- int64_t growth = max_written_offset_ - cached_file_size_;
- growth = growth < 0 ? 0 : growth;
-
- delegate_->DidUpdateFile(file_url_, growth);
- max_written_offset_ = 0;
- }
-}
-
-void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) {
- DCHECK_EQ(1, inflight_operations_);
- pending_callbacks_.pop_front();
- DCHECK(pending_callbacks_.empty());
- int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 :
- new_file_size - cached_file_size_;
-
- delegate_->DidUpdateFile(file_url_, delta);
- inflight_operations_ = 0;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/pepper/quota_file_io.h b/chromium/content/renderer/pepper/quota_file_io.h
deleted file mode 100644
index 8dbcd2a115f..00000000000
--- a/chromium/content/renderer/pepper/quota_file_io.h
+++ /dev/null
@@ -1,133 +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_RENDERER_PEPPER_QUOTA_FILE_IO_H_
-#define CONTENT_RENDERER_PEPPER_QUOTA_FILE_IO_H_
-
-#include <deque>
-
-#include "base/callback_forward.h"
-#include "base/files/file_util_proxy.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/platform_file.h"
-#include "content/common/content_export.h"
-#include "ppapi/c/pp_file_info.h"
-#include "url/gurl.h"
-#include "webkit/common/quota/quota_types.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace content {
-
-// This class is created per PPB_FileIO_Impl instance and provides
-// write operations for quota-managed files (i.e. files of
-// PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY}).
-class QuotaFileIO {
- public:
- // For quota handlings for FileIO API. This will be owned by QuotaFileIO.
- class Delegate {
- public:
- virtual ~Delegate() {}
- typedef base::Callback<void (int64)> AvailableSpaceCallback;
- virtual void QueryAvailableSpace(
- const GURL& origin,
- quota::StorageType type,
- const AvailableSpaceCallback& callback) = 0;
- virtual void WillUpdateFile(const GURL& file_path) = 0;
- virtual void DidUpdateFile(const GURL& file_path, int64_t delta) = 0;
- // Returns a MessageLoopProxy instance associated with the message loop of
- // the file thread in this renderer.
- virtual scoped_refptr<base::MessageLoopProxy>
- GetFileThreadMessageLoopProxy() = 0;
- };
-
- typedef base::FileUtilProxy::WriteCallback WriteCallback;
- typedef base::FileUtilProxy::StatusCallback StatusCallback;
-
- CONTENT_EXPORT QuotaFileIO(Delegate* delegate,
- base::PlatformFile file,
- const GURL& path_url,
- PP_FileSystemType type);
- CONTENT_EXPORT ~QuotaFileIO();
-
- // Performs write or setlength operation with quota checks.
- // Returns true when the operation is successfully dispatched.
- // |bytes_to_write| must be geater than zero.
- // |callback| will be dispatched when the operation completes.
- // Otherwise it returns false and |callback| will not be dispatched.
- // |callback| will not be dispatched either when this instance is
- // destroyed before the operation completes.
- // SetLength/WillSetLength cannot be called while there're any in-flight
- // operations. For Write/WillWrite it is guaranteed that |callback| are
- // always dispatched in the same order as Write being called.
- CONTENT_EXPORT bool Write(int64_t offset,
- const char* buffer,
- int32_t bytes_to_write,
- const WriteCallback& callback);
- CONTENT_EXPORT bool WillWrite(int64_t offset,
- int32_t bytes_to_write,
- const WriteCallback& callback);
-
- CONTENT_EXPORT bool SetLength(int64_t length,
- const StatusCallback& callback);
- CONTENT_EXPORT bool WillSetLength(int64_t length,
- const StatusCallback& callback);
-
- Delegate* delegate() const { return delegate_.get(); }
-
- private:
- class PendingOperationBase;
- class WriteOperation;
- class SetLengthOperation;
-
- bool CheckIfExceedsQuota(int64_t new_file_size) const;
- void WillUpdate();
- void DidWrite(WriteOperation* op, int64_t written_offset_end);
- void DidSetLength(base::PlatformFileError error, int64_t new_file_size);
-
- bool RegisterOperationForQuotaChecks(PendingOperationBase* op);
- void DidQueryInfoForQuota(base::PlatformFileError error_code,
- const base::PlatformFileInfo& file_info);
- void DidQueryAvailableSpace(int64_t avail_space);
- void DidQueryForQuotaCheck();
-
- scoped_ptr<Delegate> delegate_;
-
- // The file information associated to this instance.
- base::PlatformFile file_;
- GURL file_url_;
- quota::StorageType storage_type_;
-
- // Pending operations that are waiting quota checks and pending
- // callbacks that are to be fired after the operation;
- // we use two separate queues for them so that we can safely dequeue the
- // pending callbacks while enqueueing new operations. (This could
- // happen when callbacks are dispatched synchronously due to error etc.)
- std::deque<PendingOperationBase*> pending_operations_;
- std::deque<PendingOperationBase*> pending_callbacks_;
-
- // Valid only while there're pending quota checks.
- int64_t cached_file_size_;
- int64_t cached_available_space_;
-
- // Quota-related queries and errors occurred during in-flight quota checks.
- int outstanding_quota_queries_;
- int outstanding_errors_;
-
- // For parallel writes bookkeeping.
- int64_t max_written_offset_;
- int inflight_operations_;
-
- base::WeakPtrFactory<QuotaFileIO> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(QuotaFileIO);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_PEPPER_QUOTA_FILE_IO_H_
diff --git a/chromium/content/renderer/pepper/quota_file_io_unittest.cc b/chromium/content/renderer/pepper/quota_file_io_unittest.cc
deleted file mode 100644
index 2321c9f369e..00000000000
--- a/chromium/content/renderer/pepper/quota_file_io_unittest.cc
+++ /dev/null
@@ -1,496 +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 <deque>
-#include <limits>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/platform_file.h"
-#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
-#include "content/renderer/pepper/quota_file_io.h"
-#include "content/test/ppapi_unittest.h"
-
-using base::MessageLoopProxy;
-using base::PlatformFile;
-using base::PlatformFileError;
-
-namespace content {
-
-namespace {
-class QuotaMockDelegate : public QuotaFileIO::Delegate {
- public:
- typedef QuotaFileIO::Delegate::AvailableSpaceCallback Callback;
-
- QuotaMockDelegate()
- : available_space_(0),
- will_update_count_(0),
- file_thread_(MessageLoopProxy::current()),
- weak_factory_(this) {
- }
- virtual ~QuotaMockDelegate() {}
-
- virtual void QueryAvailableSpace(
- const GURL& origin,
- quota::StorageType type,
- const Callback& callback) OVERRIDE {
- DCHECK_EQ(false, callback.is_null());
- MessageLoopProxy::current()->PostTask(
- FROM_HERE, base::Bind(
- &QuotaMockDelegate::RunAvailableSpaceCallback,
- weak_factory_.GetWeakPtr(), callback));
- }
-
- virtual void WillUpdateFile(const GURL& file_path) OVERRIDE {
- file_path_ = file_path;
- ++will_update_count_;
- }
-
- virtual void DidUpdateFile(const GURL& file_path, int64_t delta) OVERRIDE {
- ASSERT_EQ(file_path_, file_path);
- ASSERT_GT(will_update_count_, 0);
- --will_update_count_;
- available_space_ -= delta;
- }
-
- virtual scoped_refptr<base::MessageLoopProxy>
- GetFileThreadMessageLoopProxy() OVERRIDE {
- return file_thread_;
- }
-
- void set_available_space(int64 available) { available_space_ = available; }
- int64_t available_space() const { return available_space_; }
-
- private:
- void RunAvailableSpaceCallback(const Callback& callback) {
- callback.Run(available_space_);
- }
-
- int64_t available_space_;
- int will_update_count_;
- GURL file_path_;
- scoped_refptr<MessageLoopProxy> file_thread_;
- base::WeakPtrFactory<QuotaMockDelegate> weak_factory_;
-};
-} // namespace
-
-class QuotaFileIOTest : public PpapiUnittest {
- public:
- QuotaFileIOTest()
- : delegate_(NULL),
- weak_factory_(this) {}
-
- virtual void SetUp() OVERRIDE {
- PpapiUnittest::SetUp();
- ASSERT_TRUE(dir_.CreateUniqueTempDir());
- base::FilePath path;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(dir_.path(), &path));
- int file_flags = base::PLATFORM_FILE_OPEN |
- base::PLATFORM_FILE_READ |
- base::PLATFORM_FILE_WRITE |
- base::PLATFORM_FILE_WRITE_ATTRIBUTES;
- bool created = false;
- file_ = base::kInvalidPlatformFileValue;
- PlatformFileError error = base::PLATFORM_FILE_OK;
- file_ = base::CreatePlatformFile(path, file_flags, &created, &error);
- ASSERT_EQ(base::PLATFORM_FILE_OK, error);
- ASSERT_NE(base::kInvalidPlatformFileValue, file_);
- ASSERT_FALSE(created);
- delegate_ = new QuotaMockDelegate; // Owned by QuotaFileIO.
- quota_file_io_.reset(new QuotaFileIO(
- delegate_, file_, GURL(), PP_FILESYSTEMTYPE_LOCALTEMPORARY));
- }
-
- virtual void TearDown() OVERRIDE {
- quota_file_io_.reset();
- if (file_ != base::kInvalidPlatformFileValue)
- base::ClosePlatformFile(file_);
- PpapiUnittest::TearDown();
- }
-
- protected:
- void WriteTestBody(bool will_operation) {
- // Attempt to write zero bytes.
- EXPECT_FALSE(quota_file_io_->Write(
- 0, "data", 0,
- base::Bind(&QuotaFileIOTest::DidWrite, weak_factory_.GetWeakPtr())));
- // Attempt to write negative number of bytes.
- EXPECT_FALSE(quota_file_io_->Write(
- 0, "data", std::numeric_limits<int32_t>::min(),
- base::Bind(&QuotaFileIOTest::DidWrite, weak_factory_.GetWeakPtr())));
-
- delegate()->set_available_space(100);
- std::string read_buffer;
-
- // Write 8 bytes at offset 0 (-> length=8).
- std::string data("12345678");
- Write(0, data, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(100 - 8, delegate()->available_space());
- reset_results();
-
- if (will_operation) {
- // WillWrite doesn't actually write.
- EXPECT_EQ(0, GetPlatformFileSize());
- // Adjust the actual file size to 'fake' write to proceed testing.
- SetPlatformFileSize(8);
- } else {
- EXPECT_EQ(8, GetPlatformFileSize());
- ReadPlatformFile(&read_buffer);
- EXPECT_EQ(data, read_buffer);
- }
-
- // Write 5 bytes at offset 5 (-> length=10).
- data = "55555";
- Write(5, data, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(100 - 10, delegate()->available_space());
- reset_results();
-
- if (will_operation) {
- EXPECT_EQ(8, GetPlatformFileSize());
- SetPlatformFileSize(10);
- } else {
- EXPECT_EQ(10, GetPlatformFileSize());
- ReadPlatformFile(&read_buffer);
- EXPECT_EQ("1234555555", read_buffer);
- }
-
- // Write 7 bytes at offset 8 (-> length=15).
- data = "9012345";
- Write(8, data, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(100 - 15, delegate()->available_space());
- reset_results();
-
- if (will_operation) {
- EXPECT_EQ(10, GetPlatformFileSize());
- SetPlatformFileSize(15);
- } else {
- EXPECT_EQ(15, GetPlatformFileSize());
- ReadPlatformFile(&read_buffer);
- EXPECT_EQ("123455559012345", read_buffer);
- }
-
- // Write 2 bytes at offset 2 (-> length=15).
- data = "33";
- Write(2, data, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(100 - 15, delegate()->available_space());
- reset_results();
-
- if (will_operation) {
- EXPECT_EQ(15, GetPlatformFileSize());
- } else {
- EXPECT_EQ(15, GetPlatformFileSize());
- ReadPlatformFile(&read_buffer);
- EXPECT_EQ("123355559012345", read_buffer);
- }
-
- // Write 4 bytes at offset 20 (-> length=24).
- data = "XXXX";
- Write(20, data, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(100 - 24, delegate()->available_space());
- reset_results();
-
- if (will_operation) {
- EXPECT_EQ(15, GetPlatformFileSize());
- SetPlatformFileSize(24);
- } else {
- EXPECT_EQ(24, GetPlatformFileSize());
- ReadPlatformFile(&read_buffer);
- EXPECT_EQ(std::string("123355559012345\0\0\0\0\0XXXX", 24), read_buffer);
- }
-
- delegate()->set_available_space(5);
-
- // Quota error case. Write 7 bytes at offset 23 (-> length is unchanged)
- data = "ABCDEFG";
- Write(23, data, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status().front());
- EXPECT_EQ(5, delegate()->available_space());
- reset_results();
-
- // Overlapping write. Write 6 bytes at offset 2 (-> length is unchanged)
- data = "ABCDEF";
- Write(2, data, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(5, delegate()->available_space());
- reset_results();
-
- // Overlapping + extending the file size, but within the quota.
- // Write 6 bytes at offset 23 (-> length=29).
- Write(23, data, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(0, delegate()->available_space());
- reset_results();
-
- if (!will_operation) {
- EXPECT_EQ(29, GetPlatformFileSize());
- ReadPlatformFile(&read_buffer);
- EXPECT_EQ(std::string("12ABCDEF9012345\0\0\0\0\0XXXABCDEF", 29),
- read_buffer);
- }
- }
-
- void SetLengthTestBody(bool will_operation) {
- delegate()->set_available_space(100);
-
- SetLength(0, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(0, GetPlatformFileSize());
- EXPECT_EQ(100, delegate()->available_space());
- reset_results();
-
- SetLength(8, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(100 - 8, delegate()->available_space());
- reset_results();
-
- if (will_operation) {
- EXPECT_EQ(0, GetPlatformFileSize());
- SetPlatformFileSize(8);
- } else {
- EXPECT_EQ(8, GetPlatformFileSize());
- }
-
- SetLength(16, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(100 - 16, delegate()->available_space());
- reset_results();
-
- if (will_operation) {
- EXPECT_EQ(8, GetPlatformFileSize());
- SetPlatformFileSize(16);
- } else {
- EXPECT_EQ(16, GetPlatformFileSize());
- }
-
- SetLength(4, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(100 - 4, delegate()->available_space());
- reset_results();
-
- if (will_operation) {
- EXPECT_EQ(16, GetPlatformFileSize());
- SetPlatformFileSize(4);
- } else {
- EXPECT_EQ(4, GetPlatformFileSize());
- }
-
- SetLength(0, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- EXPECT_EQ(100, delegate()->available_space());
- reset_results();
-
- if (will_operation) {
- EXPECT_EQ(4, GetPlatformFileSize());
- SetPlatformFileSize(0);
- } else {
- EXPECT_EQ(0, GetPlatformFileSize());
- }
-
- delegate()->set_available_space(5);
-
- // Quota error case.
- SetLength(7, will_operation);
- base::MessageLoop::current()->RunUntilIdle();
- ASSERT_EQ(1U, num_results());
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status().front());
- EXPECT_EQ(5, delegate()->available_space());
- reset_results();
- }
-
- QuotaMockDelegate* delegate() {
- return delegate_;
- }
-
- void Write(int64_t offset, const std::string& data, bool will_operation) {
- if (will_operation) {
- ASSERT_TRUE(quota_file_io_->WillWrite(
- offset, data.size(),
- base::Bind(&QuotaFileIOTest::DidWrite, weak_factory_.GetWeakPtr())));
- } else {
- ASSERT_TRUE(quota_file_io_->Write(
- offset, data.c_str(), data.size(),
- base::Bind(&QuotaFileIOTest::DidWrite, weak_factory_.GetWeakPtr())));
- }
- }
-
- void SetLength(int64_t length, bool will_operation) {
- if (will_operation) {
- ASSERT_TRUE(quota_file_io_->WillSetLength(
- length,
- base::Bind(&QuotaFileIOTest::DidSetLength,
- weak_factory_.GetWeakPtr())));
- } else {
- ASSERT_TRUE(quota_file_io_->SetLength(
- length,
- base::Bind(&QuotaFileIOTest::DidSetLength,
- weak_factory_.GetWeakPtr())));
- }
- }
-
- void DidWrite(PlatformFileError status, int bytes_written) {
- status_.push_back(status);
- bytes_written_.push_back(bytes_written);
- }
-
- void DidSetLength(PlatformFileError status) {
- status_.push_back(status);
- }
-
- size_t num_results() const { return status_.size(); }
- const std::deque<int>& bytes_written() const { return bytes_written_; }
- const std::deque<PlatformFileError>& status() const { return status_; }
-
- void reset_results() {
- bytes_written_.clear();
- status_.clear();
- }
-
- void pop_result() {
- bytes_written_.pop_front();
- status_.pop_front();
- }
-
- void ReadPlatformFile(std::string* data) {
- data->clear();
- char buf[256];
- int32_t read_offset = 0;
- for (;;) {
- int rv = base::ReadPlatformFile(file_, read_offset, buf, sizeof(buf));
- ASSERT_GE(rv, 0);
- if (rv == 0)
- break;
- read_offset += rv;
- data->append(buf, rv);
- }
- }
-
- int64_t GetPlatformFileSize() {
- base::PlatformFileInfo info;
- EXPECT_TRUE(base::GetPlatformFileInfo(file_, &info));
- return info.size;
- }
-
- void SetPlatformFileSize(int64_t length) {
- EXPECT_TRUE(base::TruncatePlatformFile(file_, length));
- }
-
- private:
- base::ScopedTempDir dir_;
- PlatformFile file_;
- scoped_ptr<QuotaFileIO> quota_file_io_;
- std::deque<int> bytes_written_;
- std::deque<PlatformFileError> status_;
- QuotaMockDelegate* delegate_;
- base::WeakPtrFactory<QuotaFileIOTest> weak_factory_;
-};
-
-TEST_F(QuotaFileIOTest, Write) {
- WriteTestBody(false);
-}
-
-TEST_F(QuotaFileIOTest, WillWrite) {
- WriteTestBody(true);
-}
-
-TEST_F(QuotaFileIOTest, SetLength) {
- SetLengthTestBody(false);
-}
-
-TEST_F(QuotaFileIOTest, WillSetLength) {
- SetLengthTestBody(true);
-}
-
-TEST_F(QuotaFileIOTest, ParallelWrites) {
- delegate()->set_available_space(22);
- std::string read_buffer;
-
- const std::string data1[] = {
- std::string("12345678"),
- std::string("55555"),
- std::string("9012345"),
- };
- Write(0, data1[0], false);
- Write(5, data1[1], false);
- Write(8, data1[2], false);
- base::MessageLoop::current()->RunUntilIdle();
-
- ASSERT_EQ(ARRAYSIZE_UNSAFE(data1), num_results());
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data1); ++i) {
- EXPECT_EQ(static_cast<int>(data1[i].size()), bytes_written().front());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- pop_result();
- }
-
- EXPECT_EQ(22 - 15, delegate()->available_space());
- EXPECT_EQ(15, GetPlatformFileSize());
- ReadPlatformFile(&read_buffer);
- EXPECT_EQ("123455559012345", read_buffer);
-
- // The second write will fail for quota error.
- const std::string data2[] = {
- std::string("33"),
- std::string("XXXX"),
- };
- Write(2, data2[0], false);
- Write(20, data2[1], false);
- base::MessageLoop::current()->RunUntilIdle();
-
- ASSERT_EQ(ARRAYSIZE_UNSAFE(data2), num_results());
- EXPECT_EQ(static_cast<int>(data2[0].size()), bytes_written().front());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status().front());
- pop_result();
- EXPECT_EQ(0, bytes_written().front());
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status().front());
- pop_result();
-
- EXPECT_EQ(22 - 15, delegate()->available_space());
- EXPECT_EQ(15, GetPlatformFileSize());
- ReadPlatformFile(&read_buffer);
- EXPECT_EQ("123355559012345", read_buffer);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc
index 5c41003d71f..5014c9898ef 100644
--- a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc
+++ b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc
@@ -132,6 +132,17 @@ ppapi::host::PpapiHost* RendererPpapiHostImpl::GetPpapiHost() {
return ppapi_host_.get();
}
+RenderFrame* RendererPpapiHostImpl::GetRenderFrameForInstance(
+ PP_Instance instance) const {
+ PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
+ if (!instance_object)
+ return NULL;
+
+ // Since we're the embedder, we can make assumptions about the helper on
+ // the instance and get back to our RenderFrame.
+ return instance_object->render_frame();
+}
+
RenderView* RendererPpapiHostImpl::GetRenderViewForInstance(
PP_Instance instance) const {
PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
@@ -140,7 +151,7 @@ RenderView* RendererPpapiHostImpl::GetRenderViewForInstance(
// Since we're the embedder, we can make assumptions about the helper on
// the instance and get back to our RenderView.
- return instance_object->render_view();
+ return instance_object->render_frame()->render_view();
}
bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
@@ -152,7 +163,7 @@ PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance(
return GetAndValidateInstance(instance);
}
-WebKit::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance(
+blink::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance(
PP_Instance instance) const {
PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
if (!instance_object)
@@ -188,19 +199,20 @@ int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance) const {
return GetRenderViewForInstance(instance)->GetRoutingID();
}
-gfx::Point RendererPpapiHostImpl::PluginPointToRenderView(
+gfx::Point RendererPpapiHostImpl::PluginPointToRenderFrame(
PP_Instance instance,
const gfx::Point& pt) const {
PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
if (!plugin_instance)
return pt;
- RenderViewImpl* render_view = static_cast<RenderViewImpl*>(
- GetRenderViewForInstance(instance));
+ RenderFrameImpl* render_frame = static_cast<RenderFrameImpl*>(
+ GetRenderFrameForInstance(instance));
if (plugin_instance->view_data().is_fullscreen ||
plugin_instance->flash_fullscreen()) {
- WebKit::WebRect window_rect = render_view->windowRect();
- WebKit::WebRect screen_rect = render_view->screenInfo().rect;
+ blink::WebRect window_rect = render_frame->GetRenderWidget()->windowRect();
+ blink::WebRect screen_rect =
+ render_frame->GetRenderWidget()->screenInfo().rect;
return gfx::Point(pt.x() - window_rect.x + screen_rect.x,
pt.y() - window_rect.y + screen_rect.y);
}
@@ -231,9 +243,9 @@ void RendererPpapiHostImpl::CreateBrowserResourceHosts(
PP_Instance instance,
const std::vector<IPC::Message>& nested_msgs,
const base::Callback<void(const std::vector<int>&)>& callback) const {
- RenderView* render_view = GetRenderViewForInstance(instance);
+ RenderFrame* render_frame = GetRenderFrameForInstance(instance);
PepperBrowserConnection* browser_connection =
- PepperBrowserConnection::Get(render_view);
+ PepperBrowserConnection::Get(render_frame);
if (!browser_connection) {
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, std::vector<int>(nested_msgs.size(), 0)));
@@ -245,6 +257,14 @@ void RendererPpapiHostImpl::CreateBrowserResourceHosts(
}
}
+GURL RendererPpapiHostImpl::GetDocumentURL(PP_Instance instance) const {
+ PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
+ if (!instance_object)
+ return GURL();
+
+ return instance_object->container()->element().document().url();
+}
+
PepperPluginInstanceImpl* RendererPpapiHostImpl::GetAndValidateInstance(
PP_Instance pp_instance) const {
PepperPluginInstanceImpl* instance =
diff --git a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h
index b7a0a53a505..c2ad0d1cb0d 100644
--- a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h
+++ b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h
@@ -78,14 +78,16 @@ class RendererPpapiHostImpl : public RendererPpapiHost {
virtual bool IsValidInstance(PP_Instance instance) const OVERRIDE;
virtual PepperPluginInstance* GetPluginInstance(
PP_Instance instance) const OVERRIDE;
+ virtual RenderFrame* GetRenderFrameForInstance(
+ PP_Instance instance) const OVERRIDE;
virtual RenderView* GetRenderViewForInstance(
PP_Instance instance) const OVERRIDE;
- virtual WebKit::WebPluginContainer* GetContainerForInstance(
+ virtual blink::WebPluginContainer* GetContainerForInstance(
PP_Instance instance) const OVERRIDE;
virtual base::ProcessId GetPluginPID() const OVERRIDE;
virtual bool HasUserGesture(PP_Instance instance) const OVERRIDE;
virtual int GetRoutingIDForWidget(PP_Instance instance) const OVERRIDE;
- virtual gfx::Point PluginPointToRenderView(
+ virtual gfx::Point PluginPointToRenderFrame(
PP_Instance instance,
const gfx::Point& pt) const OVERRIDE;
virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
@@ -97,6 +99,7 @@ class RendererPpapiHostImpl : public RendererPpapiHost {
const std::vector<IPC::Message>& nested_msgs,
const base::Callback<void(
const std::vector<int>&)>& callback) const OVERRIDE;
+ virtual GURL GetDocumentURL(PP_Instance instance) const OVERRIDE;
private:
RendererPpapiHostImpl(PluginModule* module,
diff --git a/chromium/content/renderer/pepper/resource_converter.cc b/chromium/content/renderer/pepper/resource_converter.cc
index 4f9f5d99cd2..5054c2dc3a4 100644
--- a/chromium/content/renderer/pepper/resource_converter.cc
+++ b/chromium/content/renderer/pepper/resource_converter.cc
@@ -7,22 +7,84 @@
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "content/public/renderer/renderer_ppapi_host.h"
+#include "content/renderer/pepper/pepper_file_system_host.h"
#include "ipc/ipc_message.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/host/resource_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/resource_var.h"
#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "third_party/WebKit/public/platform/WebFileSystem.h"
+#include "third_party/WebKit/public/web/WebDOMFileSystem.h"
namespace {
void FlushComplete(
const base::Callback<void(bool)>& callback,
- const std::vector<PP_Var>& browser_host_resource_vars,
+ const std::vector<scoped_refptr<content::HostResourceVar> >& browser_vars,
const std::vector<int>& pending_host_ids) {
- CHECK(browser_host_resource_vars.size() == pending_host_ids.size());
- for (size_t i = 0; i < browser_host_resource_vars.size(); ++i) {
- // TODO(raymes): Set the pending browser host ID in the resource var.
+ CHECK(browser_vars.size() == pending_host_ids.size());
+ for (size_t i = 0; i < browser_vars.size(); ++i) {
+ browser_vars[i]->set_pending_browser_host_id(pending_host_ids[i]);
}
callback.Run(true);
}
+// Converts a blink::WebFileSystem::Type to a PP_FileSystemType.
+PP_FileSystemType WebFileSystemTypeToPPAPI(blink::WebFileSystem::Type type) {
+ switch (type) {
+ case blink::WebFileSystem::TypeTemporary:
+ return PP_FILESYSTEMTYPE_LOCALTEMPORARY;
+ case blink::WebFileSystem::TypePersistent:
+ return PP_FILESYSTEMTYPE_LOCALPERSISTENT;
+ case blink::WebFileSystem::TypeIsolated:
+ return PP_FILESYSTEMTYPE_ISOLATED;
+ case blink::WebFileSystem::TypeExternal:
+ return PP_FILESYSTEMTYPE_EXTERNAL;
+ default:
+ NOTREACHED();
+ return PP_FILESYSTEMTYPE_LOCALTEMPORARY;
+ }
+}
+
+// Given a V8 value containing a DOMFileSystem, creates a resource host and
+// returns the resource information for serialization.
+// On error, false.
+bool DOMFileSystemToResource(
+ PP_Instance instance,
+ content::RendererPpapiHost* host,
+ const blink::WebDOMFileSystem& dom_file_system,
+ int* pending_renderer_id,
+ scoped_ptr<IPC::Message>* create_message,
+ scoped_ptr<IPC::Message>* browser_host_create_message) {
+ DCHECK(!dom_file_system.isNull());
+
+ PP_FileSystemType file_system_type =
+ WebFileSystemTypeToPPAPI(dom_file_system.type());
+ GURL root_url = dom_file_system.rootURL();
+
+ // External file systems are not currently supported. (Without this check,
+ // there would be a CHECK-fail in FileRefResource.)
+ // TODO(mgiuca): Support external file systems.
+ if (file_system_type == PP_FILESYSTEMTYPE_EXTERNAL)
+ return false;
+
+ *pending_renderer_id = host->GetPpapiHost()->AddPendingResourceHost(
+ scoped_ptr<ppapi::host::ResourceHost>(
+ new content::PepperFileSystemHost(host, instance, 0, root_url,
+ file_system_type)));
+ if (*pending_renderer_id == 0)
+ return false;
+
+ create_message->reset(
+ new PpapiPluginMsg_FileSystem_CreateFromPendingHost(file_system_type));
+
+ browser_host_create_message->reset(
+ new PpapiHostMsg_FileSystem_CreateFromRenderer(root_url.spec(),
+ file_system_type));
+ return true;
+}
+
} // namespace
namespace content {
@@ -38,37 +100,69 @@ ResourceConverterImpl::ResourceConverterImpl(PP_Instance instance,
ResourceConverterImpl::~ResourceConverterImpl() {
// Verify Flush() was called.
DCHECK(browser_host_create_messages_.empty());
- DCHECK(browser_host_resource_vars.empty());
+ DCHECK(browser_vars.empty());
}
-bool ResourceConverterImpl::FromV8Value(v8::Handle<v8::Value> val,
+bool ResourceConverterImpl::FromV8Value(v8::Handle<v8::Object> val,
v8::Handle<v8::Context> context,
- PP_Var* result) {
+ PP_Var* result,
+ bool* was_resource) {
+ v8::Context::Scope context_scope(context);
+ v8::HandleScope handle_scope(context->GetIsolate());
+
+ *was_resource = false;
+
+ blink::WebDOMFileSystem dom_file_system =
+ blink::WebDOMFileSystem::fromV8Value(val);
+ if (!dom_file_system.isNull()) {
+ int pending_renderer_id;
+ scoped_ptr<IPC::Message> create_message;
+ scoped_ptr<IPC::Message> browser_host_create_message;
+ if (!DOMFileSystemToResource(instance_, host_, dom_file_system,
+ &pending_renderer_id, &create_message,
+ &browser_host_create_message)) {
+ return false;
+ }
+ DCHECK(create_message);
+ DCHECK(browser_host_create_message);
+ scoped_refptr<HostResourceVar> result_var =
+ CreateResourceVarWithBrowserHost(
+ pending_renderer_id, *create_message, *browser_host_create_message);
+ *result = result_var->GetPPVar();
+ *was_resource = true;
+ return true;
+ }
- return false;
+ // The value was not convertible to a resource. Return true with
+ // |was_resource| set to false. As per the interface of FromV8Value, |result|
+ // may be left unmodified in this case.
+ return true;
}
void ResourceConverterImpl::Flush(const base::Callback<void(bool)>& callback) {
host_->CreateBrowserResourceHosts(
instance_,
browser_host_create_messages_,
- base::Bind(&FlushComplete, callback, browser_host_resource_vars));
+ base::Bind(&FlushComplete, callback, browser_vars));
browser_host_create_messages_.clear();
- browser_host_resource_vars.clear();
+ browser_vars.clear();
}
-PP_Var ResourceConverterImpl::CreateResourceVar(
+scoped_refptr<HostResourceVar> ResourceConverterImpl::CreateResourceVar(
+ int pending_renderer_id,
const IPC::Message& create_message) {
- // TODO(raymes): Create a ResourceVar here.
- return PP_MakeUndefined();
+ return new HostResourceVar(pending_renderer_id, create_message);
}
-PP_Var ResourceConverterImpl::CreateResourceVarWithBrowserHost(
+scoped_refptr<HostResourceVar>
+ResourceConverterImpl::CreateResourceVarWithBrowserHost(
+ int pending_renderer_id,
const IPC::Message& create_message,
const IPC::Message& browser_host_create_message) {
- PP_Var result = CreateResourceVar(create_message);
+ scoped_refptr<HostResourceVar> result =
+ CreateResourceVar(pending_renderer_id, create_message);
browser_host_create_messages_.push_back(browser_host_create_message);
- browser_host_resource_vars.push_back(result);
+ browser_vars.push_back(result);
return result;
}
diff --git a/chromium/content/renderer/pepper/resource_converter.h b/chromium/content/renderer/pepper/resource_converter.h
index 7d9fd1ec7d9..a52f7ad83ce 100644
--- a/chromium/content/renderer/pepper/resource_converter.h
+++ b/chromium/content/renderer/pepper/resource_converter.h
@@ -10,7 +10,9 @@
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+#include "content/renderer/pepper/host_resource_var.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_var.h"
#include "v8/include/v8.h"
@@ -35,24 +37,41 @@ class CONTENT_EXPORT ResourceConverter {
// Flush() must be called before any vars created by the ResourceConverter
// are valid. It handles creating any resource hosts that need to be created.
virtual void Flush(const base::Callback<void(bool)>& callback) = 0;
+
+ // Attempts to convert a V8 object to a PP_Var with type PP_VARTYPE_RESOURCE.
+ // On success, writes the resulting var to |result|, sets |was_resource| to
+ // true and returns true. If |val| is not a resource, sets |was_resource| to
+ // false and returns true. If an error occurs, returns false.
+ virtual bool FromV8Value(v8::Handle<v8::Object> val,
+ v8::Handle<v8::Context> context,
+ PP_Var* result,
+ bool* was_resource) = 0;
};
class ResourceConverterImpl : public ResourceConverter {
public:
ResourceConverterImpl(PP_Instance instance, RendererPpapiHost* host);
virtual ~ResourceConverterImpl();
- virtual void Flush(const base::Callback<void(bool)>& callback) OVERRIDE;
- bool FromV8Value(v8::Handle<v8::Value> val,
- v8::Handle<v8::Context> context,
- PP_Var* result);
+ // ResourceConverter overrides.
+ virtual void Flush(const base::Callback<void(bool)>& callback) OVERRIDE;
+ virtual bool FromV8Value(v8::Handle<v8::Object> val,
+ v8::Handle<v8::Context> context,
+ PP_Var* result,
+ bool* was_resource) OVERRIDE;
private:
- // Creates a resource var with the given message to be sent to the plugin.
- PP_Var CreateResourceVar(const IPC::Message& create_message);
- // Creates a resource var with the given message to send to the plugin and a
- // message to create the browser host.
- PP_Var CreateResourceVarWithBrowserHost(
+ // Creates a resource var with the given |pending_renderer_id| and
+ // |create_message| to be sent to the plugin.
+ scoped_refptr<HostResourceVar> CreateResourceVar(
+ int pending_renderer_id,
+ const IPC::Message& create_message);
+ // Creates a resource var with the given |pending_renderer_id| and
+ // |create_message| to be sent to the plugin. Also sends
+ // |browser_host_create_message| to the browser, and asynchronously stores the
+ // resulting browser host ID in the newly created var.
+ scoped_refptr<HostResourceVar> CreateResourceVarWithBrowserHost(
+ int pending_renderer_id,
const IPC::Message& create_message,
const IPC::Message& browser_host_create_message);
@@ -62,11 +81,11 @@ class ResourceConverterImpl : public ResourceConverter {
RendererPpapiHost* host_;
// A list of the messages to create the browser hosts. This is a parallel
- // array to |browser_host_resource_vars|. It is kept as a parallel array so
- // that it can be conveniently passed to |CreateBrowserResourceHosts|.
+ // array to |browser_vars|. It is kept as a parallel array so that it can be
+ // conveniently passed to |CreateBrowserResourceHosts|.
std::vector<IPC::Message> browser_host_create_messages_;
// A list of the resource vars associated with browser hosts.
- std::vector<PP_Var> browser_host_resource_vars;
+ std::vector<scoped_refptr<HostResourceVar> > browser_vars;
DISALLOW_COPY_AND_ASSIGN(ResourceConverterImpl);
};
diff --git a/chromium/content/renderer/pepper/resource_creation_impl.cc b/chromium/content/renderer/pepper/resource_creation_impl.cc
index 178236edf68..d9ed442aecd 100644
--- a/chromium/content/renderer/pepper/resource_creation_impl.cc
+++ b/chromium/content/renderer/pepper/resource_creation_impl.cc
@@ -216,6 +216,11 @@ PP_Resource ResourceCreationImpl::CreateNetworkMonitor(PP_Instance instance) {
return 0; // Not supported in-process.
}
+PP_Resource ResourceCreationImpl::CreateOutputProtectionPrivate(
+ PP_Instance instance) {
+ return 0; // Not supported in-process.
+}
+
PP_Resource ResourceCreationImpl::CreatePlatformVerificationPrivate(
PP_Instance instance) {
return 0; // Not supported in-process.
diff --git a/chromium/content/renderer/pepper/resource_creation_impl.h b/chromium/content/renderer/pepper/resource_creation_impl.h
index d5b61b8fd54..ac54b6b442a 100644
--- a/chromium/content/renderer/pepper/resource_creation_impl.h
+++ b/chromium/content/renderer/pepper/resource_creation_impl.h
@@ -110,6 +110,8 @@ class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI {
uint32_t size) OVERRIDE;
virtual PP_Resource CreateScrollbar(PP_Instance instance,
PP_Bool vertical) OVERRIDE;
+ virtual PP_Resource CreateOutputProtectionPrivate(
+ PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateTalk(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateTCPServerSocketPrivate(
PP_Instance instance) OVERRIDE;
diff --git a/chromium/content/renderer/pepper/url_request_info_util.cc b/chromium/content/renderer/pepper/url_request_info_util.cc
index 92ecdfbfde0..500b7bd2e75 100644
--- a/chromium/content/renderer/pepper/url_request_info_util.cc
+++ b/chromium/content/renderer/pepper/url_request_info_util.cc
@@ -32,12 +32,12 @@
using ppapi::Resource;
using ppapi::URLRequestInfoData;
using ppapi::thunk::EnterResourceNoLock;
-using WebKit::WebData;
-using WebKit::WebHTTPBody;
-using WebKit::WebString;
-using WebKit::WebFrame;
-using WebKit::WebURL;
-using WebKit::WebURLRequest;
+using blink::WebData;
+using blink::WebHTTPBody;
+using blink::WebString;
+using blink::WebFrame;
+using blink::WebURL;
+using blink::WebURLRequest;
namespace content {
@@ -177,7 +177,7 @@ bool CreateWebURLRequest(PP_Instance instance,
if (data->has_custom_user_agent) {
bool was_after_preconnect_request = false;
dest->setExtraData(new webkit_glue::WebURLRequestExtraDataImpl(
- WebKit::WebReferrerPolicyDefault, // Ignored.
+ blink::WebReferrerPolicyDefault, // Ignored.
WebString::fromUTF8(data->custom_user_agent),
was_after_preconnect_request));
}
diff --git a/chromium/content/renderer/pepper/url_request_info_util.h b/chromium/content/renderer/pepper/url_request_info_util.h
index 2fb40e676a2..aaafb234703 100644
--- a/chromium/content/renderer/pepper/url_request_info_util.h
+++ b/chromium/content/renderer/pepper/url_request_info_util.h
@@ -13,7 +13,7 @@ namespace ppapi {
struct URLRequestInfoData;
}
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebURLRequest;
}
@@ -26,8 +26,8 @@ namespace content {
// pointers) will be populated by this function on success.
CONTENT_EXPORT bool CreateWebURLRequest(PP_Instance instance,
ppapi::URLRequestInfoData* data,
- WebKit::WebFrame* frame,
- WebKit::WebURLRequest* dest);
+ blink::WebFrame* frame,
+ blink::WebURLRequest* dest);
// Returns true if universal access is required to use the given request.
CONTENT_EXPORT bool URLRequestRequiresUniversalAccess(
diff --git a/chromium/content/renderer/pepper/url_response_info_util.cc b/chromium/content/renderer/pepper/url_response_info_util.cc
index eda54d4ba5b..6349226a1db 100644
--- a/chromium/content/renderer/pepper/url_response_info_util.cc
+++ b/chromium/content/renderer/pepper/url_response_info_util.cc
@@ -19,9 +19,9 @@
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
-using WebKit::WebHTTPHeaderVisitor;
-using WebKit::WebString;
-using WebKit::WebURLResponse;
+using blink::WebHTTPHeaderVisitor;
+using blink::WebString;
+using blink::WebURLResponse;
namespace content {
diff --git a/chromium/content/renderer/pepper/url_response_info_util.h b/chromium/content/renderer/pepper/url_response_info_util.h
index ee0c23839f7..d7570627ed0 100644
--- a/chromium/content/renderer/pepper/url_response_info_util.h
+++ b/chromium/content/renderer/pepper/url_response_info_util.h
@@ -9,7 +9,7 @@
#include "ppapi/c/pp_instance.h"
#include "ppapi/shared_impl/url_response_info_data.h"
-namespace WebKit {
+namespace blink {
class WebURLResponse;
}
@@ -24,7 +24,7 @@ typedef base::Callback<void(const ppapi::URLResponseInfoData&)>
// passed to the plugin.
void DataFromWebURLResponse(RendererPpapiHostImpl* host_impl,
PP_Instance pp_instance,
- const WebKit::WebURLResponse& response,
+ const blink::WebURLResponse& response,
const DataFromWebURLResponseCallback& callback);
} // namespace content
diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion.cc b/chromium/content/renderer/pepper/usb_key_code_conversion.cc
index a166593c5bf..129e663a5ed 100644
--- a/chromium/content/renderer/pepper/usb_key_code_conversion.cc
+++ b/chromium/content/renderer/pepper/usb_key_code_conversion.cc
@@ -6,7 +6,7 @@
#include "build/build_config.h"
-using WebKit::WebKeyboardEvent;
+using blink::WebKeyboardEvent;
namespace content {
diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion.h b/chromium/content/renderer/pepper/usb_key_code_conversion.h
index 1fcd04a9a18..9554c57222a 100644
--- a/chromium/content/renderer/pepper/usb_key_code_conversion.h
+++ b/chromium/content/renderer/pepper/usb_key_code_conversion.h
@@ -7,9 +7,9 @@
#include "ppapi/c/pp_stdint.h"
-namespace WebKit {
+namespace blink {
class WebKeyboardEvent;
-} // namespace WebKit
+} // namespace blink
namespace content {
@@ -18,11 +18,11 @@ namespace content {
// The code consists of the USB Page (in the high-order 16-bit word) and
// USB Usage Id of the key. If no translation can be performed then zero
// is returned.
-uint32_t UsbKeyCodeForKeyboardEvent(const WebKit::WebKeyboardEvent& key_event);
+uint32_t UsbKeyCodeForKeyboardEvent(const blink::WebKeyboardEvent& key_event);
// Returns a string that represents the UI Event |code| parameter as specified
// in http://www.w3.org/TR/uievents/
-const char* CodeForKeyboardEvent(const WebKit::WebKeyboardEvent& key_event);
+const char* CodeForKeyboardEvent(const blink::WebKeyboardEvent& key_event);
} // namespace content
diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc b/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc
index c50fe4ebb38..8b9a4a52181 100644
--- a/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc
+++ b/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc
@@ -6,9 +6,9 @@
#include "base/basictypes.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/base/keycodes/keycode_converter.h"
+#include "ui/events/keycodes/dom4/keycode_converter.h"
-using WebKit::WebKeyboardEvent;
+using blink::WebKeyboardEvent;
namespace content {
diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc b/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc
index bcead0e7895..c701b48453c 100644
--- a/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc
+++ b/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc
@@ -6,9 +6,9 @@
#include "base/basictypes.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/base/keycodes/keycode_converter.h"
+#include "ui/events/keycodes/dom4/keycode_converter.h"
-using WebKit::WebKeyboardEvent;
+using blink::WebKeyboardEvent;
namespace content {
diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc b/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc
index b04cd7366b3..c9e0592b843 100644
--- a/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc
+++ b/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc
@@ -6,9 +6,9 @@
#include "base/basictypes.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/base/keycodes/keycode_converter.h"
+#include "ui/events/keycodes/dom4/keycode_converter.h"
-using WebKit::WebKeyboardEvent;
+using blink::WebKeyboardEvent;
namespace content {
@@ -23,8 +23,13 @@ uint32_t UsbKeyCodeForKeyboardEvent(const WebKeyboardEvent& key_event) {
}
const char* CodeForKeyboardEvent(const WebKeyboardEvent& key_event) {
+ // Extract the scancode and extended bit from the native key event's lParam.
+ int scancode = (key_event.nativeKeyCode >> 16) & 0x000000FF;
+ if ((key_event.nativeKeyCode & (1 << 24)) != 0)
+ scancode |= 0xe000;
+
ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance();
- return key_converter->NativeKeycodeToCode(key_event.nativeKeyCode);
+ return key_converter->NativeKeycodeToCode(scancode);
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/v8_var_converter.cc b/chromium/content/renderer/pepper/v8_var_converter.cc
index 062922aed12..3f8b37e2878 100644
--- a/chromium/content/renderer/pepper/v8_var_converter.cc
+++ b/chromium/content/renderer/pepper/v8_var_converter.cc
@@ -81,7 +81,8 @@ typedef base::hash_set<HashedHandle> ParentHandleSet;
// associated with it in the map will be returned, otherwise a new V8 value will
// be created and added to the map. |did_create| indicates whether a new v8
// value was created as a result of calling the function.
-bool GetOrCreateV8Value(const PP_Var& var,
+bool GetOrCreateV8Value(v8::Isolate* isolate,
+ const PP_Var& var,
v8::Handle<v8::Value>* result,
bool* did_create,
VarHandleMap* visited_ids,
@@ -100,13 +101,15 @@ bool GetOrCreateV8Value(const PP_Var& var,
switch (var.type) {
case PP_VARTYPE_UNDEFINED:
- *result = v8::Undefined();
+ *result = v8::Undefined(isolate);
break;
case PP_VARTYPE_NULL:
- *result = v8::Null();
+ *result = v8::Null(isolate);
break;
case PP_VARTYPE_BOOL:
- *result = (var.value.as_bool == PP_TRUE) ? v8::True() : v8::False();
+ *result = (var.value.as_bool == PP_TRUE)
+ ? v8::True(isolate)
+ : v8::False(isolate);
break;
case PP_VARTYPE_INT32:
*result = v8::Integer::New(var.value.as_int);
@@ -125,7 +128,10 @@ bool GetOrCreateV8Value(const PP_Var& var,
// Create a string object rather than a string primitive. This allows us
// to have multiple references to the same string in javascript, which
// matches the reference behavior of PP_Vars.
- *result = v8::String::New(value.c_str(), value.size())->ToObject();
+ *result = v8::String::NewFromUtf8(isolate,
+ value.c_str(),
+ v8::String::kNormalString,
+ value.size())->ToObject();
break;
}
case PP_VARTYPE_ARRAY_BUFFER: {
@@ -137,12 +143,11 @@ bool GetOrCreateV8Value(const PP_Var& var,
}
HostArrayBufferVar* host_buffer =
static_cast<HostArrayBufferVar*>(buffer);
- *result =
- v8::Local<v8::Value>::New(host_buffer->webkit_buffer().toV8Value());
+ *result = host_buffer->webkit_buffer().toV8Value();
break;
}
case PP_VARTYPE_ARRAY:
- *result = v8::Array::New();
+ *result = v8::Array::New(isolate);
break;
case PP_VARTYPE_DICTIONARY:
*result = v8::Object::New();
@@ -151,7 +156,6 @@ bool GetOrCreateV8Value(const PP_Var& var,
case PP_VARTYPE_RESOURCE:
// TODO(mgiuca): Convert PP_VARTYPE_RESOURCE vars into the correct V8
// type. (http://crbug.com/177017)
- NOTREACHED();
result->Clear();
return false;
}
@@ -168,6 +172,7 @@ bool GetOrCreateV8Value(const PP_Var& var,
// the map. |did_create| indicates if a new PP_Var was created as a result of
// calling the function.
bool GetOrCreateVar(v8::Handle<v8::Value> val,
+ v8::Handle<v8::Context> context,
PP_Var* result,
bool* did_create,
HandleVarMap* visited_handles,
@@ -207,14 +212,20 @@ bool GetOrCreateVar(v8::Handle<v8::Value> val,
} else if (val->IsArray()) {
*result = (new ArrayVar())->GetPPVar();
} else if (val->IsObject()) {
- scoped_ptr<WebKit::WebArrayBuffer> web_array_buffer(
- WebKit::WebArrayBuffer::createFromV8Value(val));
+ scoped_ptr<blink::WebArrayBuffer> web_array_buffer(
+ blink::WebArrayBuffer::createFromV8Value(val));
if (web_array_buffer.get()) {
scoped_refptr<HostArrayBufferVar> buffer_var(new HostArrayBufferVar(
*web_array_buffer));
*result = buffer_var->GetPPVar();
} else {
- *result = (new DictionaryVar())->GetPPVar();
+ bool was_resource;
+ if (!resource_converter->FromV8Value(val->ToObject(), context, result,
+ &was_resource))
+ return false;
+ if (!was_resource) {
+ *result = (new DictionaryVar())->GetPPVar();
+ }
}
} else {
// Silently ignore the case where we can't convert to a Var as we may
@@ -268,14 +279,15 @@ bool V8VarConverter::ToV8Value(const PP_Var& var,
v8::Handle<v8::Context> context,
v8::Handle<v8::Value>* result) {
v8::Context::Scope context_scope(context);
- v8::HandleScope handle_scope(context->GetIsolate());
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::EscapableHandleScope handle_scope(isolate);
VarHandleMap visited_ids;
ParentVarSet parent_ids;
std::stack<StackEntry<PP_Var> > stack;
stack.push(StackEntry<PP_Var>(var));
- v8::Handle<v8::Value> root;
+ v8::Local<v8::Value> root;
bool is_root = true;
while (!stack.empty()) {
@@ -292,7 +304,7 @@ bool V8VarConverter::ToV8Value(const PP_Var& var,
}
bool did_create = false;
- if (!GetOrCreateV8Value(current_var, &current_v8, &did_create,
+ if (!GetOrCreateV8Value(isolate, current_var, &current_v8, &did_create,
&visited_ids, &parent_ids)) {
return false;
}
@@ -316,7 +328,7 @@ bool V8VarConverter::ToV8Value(const PP_Var& var,
for (size_t i = 0; i < array_var->elements().size(); ++i) {
const PP_Var& child_var = array_var->elements()[i].get();
v8::Handle<v8::Value> child_v8;
- if (!GetOrCreateV8Value(child_var, &child_v8, &did_create,
+ if (!GetOrCreateV8Value(isolate, child_var, &child_v8, &did_create,
&visited_ids, &parent_ids)) {
return false;
}
@@ -346,14 +358,18 @@ bool V8VarConverter::ToV8Value(const PP_Var& var,
const std::string& key = iter->first;
const PP_Var& child_var = iter->second.get();
v8::Handle<v8::Value> child_v8;
- if (!GetOrCreateV8Value(child_var, &child_v8, &did_create,
+ if (!GetOrCreateV8Value(isolate, child_var, &child_v8, &did_create,
&visited_ids, &parent_ids)) {
return false;
}
if (did_create && CanHaveChildren(child_var))
stack.push(child_var);
v8::TryCatch try_catch;
- v8_object->Set(v8::String::New(key.c_str(), key.length()), child_v8);
+ v8_object->Set(v8::String::NewFromUtf8(isolate,
+ key.c_str(),
+ v8::String::kNormalString,
+ key.length()),
+ child_v8);
if (try_catch.HasCaught()) {
LOG(ERROR) << "Setter for property " << key.c_str() << " threw an "
<< "exception.";
@@ -363,7 +379,7 @@ bool V8VarConverter::ToV8Value(const PP_Var& var,
}
}
- *result = handle_scope.Close(root);
+ *result = handle_scope.Escape(root);
return true;
}
@@ -396,7 +412,7 @@ void V8VarConverter::FromV8Value(
}
bool did_create = false;
- if (!GetOrCreateVar(current_v8, &current_var, &did_create,
+ if (!GetOrCreateVar(current_v8, context, &current_var, &did_create,
&visited_handles, &parent_handles,
resource_converter_.get())) {
message_loop_proxy_->PostTask(FROM_HERE,
@@ -436,7 +452,7 @@ void V8VarConverter::FromV8Value(
continue;
PP_Var child_var;
- if (!GetOrCreateVar(child_v8, &child_var, &did_create,
+ if (!GetOrCreateVar(child_v8, context, &child_var, &did_create,
&visited_handles, &parent_handles,
resource_converter_.get())) {
message_loop_proxy_->PostTask(FROM_HERE,
@@ -467,7 +483,7 @@ void V8VarConverter::FromV8Value(
// Extend this test to cover more types as necessary and if sensible.
if (!key->IsString() && !key->IsNumber()) {
- NOTREACHED() << "Key \"" << *v8::String::AsciiValue(key) << "\" "
+ NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) << "\" "
"is neither a string nor a number";
message_loop_proxy_->PostTask(FROM_HERE,
base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false));
@@ -489,7 +505,7 @@ void V8VarConverter::FromV8Value(
}
PP_Var child_var;
- if (!GetOrCreateVar(child_v8, &child_var, &did_create,
+ if (!GetOrCreateVar(child_v8, context, &child_var, &did_create,
&visited_handles, &parent_handles,
resource_converter_.get())) {
message_loop_proxy_->PostTask(FROM_HERE,
diff --git a/chromium/content/renderer/pepper/v8_var_converter_unittest.cc b/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
index 878c39bc623..afe85fddf3c 100644
--- a/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
+++ b/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
@@ -49,6 +49,13 @@ class MockResourceConverter : public content::ResourceConverter {
virtual void Flush(const base::Callback<void(bool)>& callback) OVERRIDE {
callback.Run(true);
}
+ virtual bool FromV8Value(v8::Handle<v8::Object> val,
+ v8::Handle<v8::Context> context,
+ PP_Var* result,
+ bool* was_resource) OVERRIDE {
+ *was_resource = false;
+ return true;
+ }
};
// Maps PP_Var IDs to the V8 value handle they correspond to.
@@ -162,7 +169,7 @@ class V8VarConverterTest : public testing::Test {
context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global));
}
virtual void TearDown() {
- context_.Dispose();
+ context_.Reset();
ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty());
ProxyLock::Release();
}
@@ -194,9 +201,9 @@ class V8VarConverterTest : public testing::Test {
bool RoundTrip(const PP_Var& var, PP_Var* result) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
v8::Handle<v8::Value> v8_result;
if (!converter_->ToV8Value(var, context, &v8_result))
return false;
@@ -322,9 +329,9 @@ TEST_F(V8VarConverterTest, DictionaryArrayRoundTripTest) {
TEST_F(V8VarConverterTest, Cycles) {
// Check that cycles aren't converted.
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
// Var->V8 conversion.
{
@@ -358,14 +365,17 @@ TEST_F(V8VarConverterTest, Cycles) {
// V8->Var conversion.
{
- v8::Handle<v8::Object> object = v8::Object::New();
- v8::Handle<v8::Array> array = v8::Array::New();
+ v8::Handle<v8::Object> object = v8::Object::New(isolate_);
+ v8::Handle<v8::Array> array = v8::Array::New(isolate_);
PP_Var var_result;
// Array <-> dictionary cycle.
std::string key = "1";
- object->Set(v8::String::New(key.c_str(), key.length()), array);
+ object->Set(
+ v8::String::NewFromUtf8(
+ isolate_, key.c_str(), v8::String::kNormalString, key.length()),
+ array);
array->Set(0, object);
ASSERT_FALSE(FromV8ValueSync(object, context, &var_result));
@@ -388,7 +398,9 @@ TEST_F(V8VarConverterTest, StrangeDictionaryKeyTest) {
{
// Test non-string key types. They should be cast to strings.
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
+ v8::Local<v8::Context> context =
+ v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
const char* source = "(function() {"
"return {"
@@ -401,7 +413,8 @@ TEST_F(V8VarConverterTest, StrangeDictionaryKeyTest) {
"};"
"})();";
- v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
+ v8::Handle<v8::Script> script(
+ v8::Script::New(v8::String::NewFromUtf8(isolate_, source)));
v8::Handle<v8::Object> object = script->Run().As<v8::Object>();
ASSERT_FALSE(object.IsEmpty());
diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc
index 2cec72d37c3..2d9628e41b9 100644
--- a/chromium/content/renderer/render_frame_impl.cc
+++ b/chromium/content/renderer/render_frame_impl.cc
@@ -4,12 +4,19 @@
#include "content/renderer/render_frame_impl.h"
+#include <map>
+#include <string>
+
#include "base/command_line.h"
+#include "base/i18n/char_iterator.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "content/child/appcache/appcache_dispatcher.h"
+#include "content/child/plugin_messages.h"
#include "content/child/quota_dispatcher.h"
#include "content/child/request_extra_data.h"
+#include "content/child/service_worker/web_service_worker_provider_impl.h"
+#include "content/common/frame_messages.h"
#include "content/common/socket_stream_handle_data.h"
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
@@ -19,15 +26,20 @@
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/navigation_state.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "content/renderer/accessibility/renderer_accessibility.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
#include "content/renderer/internal_document_state_data.h"
+#include "content/renderer/npapi/plugin_channel_host.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
+#include "content/renderer/render_widget_fullscreen_pepper.h"
#include "content/renderer/renderer_webapplicationcachehost_impl.h"
#include "content/renderer/websharedworker_proxy.h"
#include "net/base/net_errors.h"
#include "net/http/http_util.h"
+#include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
@@ -40,38 +52,53 @@
#include "third_party/WebKit/public/web/WebPluginParams.h"
#include "third_party/WebKit/public/web/WebSearchableFormData.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
-#include "third_party/WebKit/public/web/WebStorageQuotaCallbacks.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "webkit/child/weburlresponse_extradata_impl.h"
+#if defined(ENABLE_PLUGINS)
+#include "content/renderer/npapi/webplugin_impl.h"
+#include "content/renderer/pepper/pepper_browser_connection.h"
+#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "content/renderer/pepper/pepper_webplugin_impl.h"
+#include "content/renderer/pepper/plugin_module.h"
+#endif
+
#if defined(ENABLE_WEBRTC)
#include "content/renderer/media/rtc_peer_connection_handler.h"
#endif
-using WebKit::WebDataSource;
-using WebKit::WebDocument;
-using WebKit::WebFrame;
-using WebKit::WebNavigationPolicy;
-using WebKit::WebPluginParams;
-using WebKit::WebReferrerPolicy;
-using WebKit::WebSearchableFormData;
-using WebKit::WebSecurityOrigin;
-using WebKit::WebStorageQuotaCallbacks;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebURLError;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
-using WebKit::WebUserGestureIndicator;
-using WebKit::WebVector;
-using WebKit::WebView;
+using blink::WebDataSource;
+using blink::WebDocument;
+using blink::WebFrame;
+using blink::WebNavigationPolicy;
+using blink::WebPluginParams;
+using blink::WebReferrerPolicy;
+using blink::WebSearchableFormData;
+using blink::WebSecurityOrigin;
+using blink::WebServiceWorkerProvider;
+using blink::WebStorageQuotaCallbacks;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebURLError;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
+using blink::WebUserGestureIndicator;
+using blink::WebVector;
+using blink::WebView;
using base::Time;
using base::TimeDelta;
using webkit_glue::WebURLResponseExtraDataImpl;
namespace content {
+namespace {
+
+typedef std::map<blink::WebFrame*, RenderFrameImpl*> FrameMap;
+base::LazyInstance<FrameMap> g_child_frame_map = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
static RenderFrameImpl* (*g_create_render_frame_impl)(RenderViewImpl*, int32) =
NULL;
@@ -80,13 +107,10 @@ RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view,
int32 routing_id) {
DCHECK(routing_id != MSG_ROUTING_NONE);
- RenderFrameImpl* render_frame = NULL;
if (g_create_render_frame_impl)
- render_frame = g_create_render_frame_impl(render_view, routing_id);
+ return g_create_render_frame_impl(render_view, routing_id);
else
- render_frame = new RenderFrameImpl(render_view, routing_id);
-
- return render_frame;
+ return new RenderFrameImpl(render_view, routing_id);
}
// static
@@ -102,18 +126,318 @@ RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id)
routing_id_(routing_id),
is_swapped_out_(false),
is_detaching_(false) {
+ RenderThread::Get()->AddRoute(routing_id_, this);
+#if defined(ENABLE_PLUGINS)
+ new PepperBrowserConnection(this);
+#endif
+
+ GetContentClient()->renderer()->RenderFrameCreated(this);
}
RenderFrameImpl::~RenderFrameImpl() {
+ FOR_EACH_OBSERVER(RenderFrameObserver, observers_, RenderFrameGone());
+ FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnDestruct());
+ RenderThread::Get()->RemoveRoute(routing_id_);
}
-int RenderFrameImpl::GetRoutingID() const {
- return routing_id_;
+RenderWidget* RenderFrameImpl::GetRenderWidget() {
+ return render_view_;
+}
+
+#if defined(ENABLE_PLUGINS)
+void RenderFrameImpl::PepperPluginCreated(RendererPpapiHost* host) {
+ FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
+ DidCreatePepperPlugin(host));
+}
+
+void RenderFrameImpl::PepperInstanceCreated(
+ PepperPluginInstanceImpl* instance) {
+ active_pepper_instances_.insert(instance);
+}
+
+void RenderFrameImpl::PepperInstanceDeleted(
+ PepperPluginInstanceImpl* instance) {
+ active_pepper_instances_.erase(instance);
+
+ if (render_view_->pepper_last_mouse_event_target() == instance)
+ render_view_->set_pepper_last_mouse_event_target(NULL);
+ if (render_view_->focused_pepper_plugin() == instance)
+ PepperFocusChanged(instance, false);
+}
+
+void RenderFrameImpl::PepperDidChangeCursor(
+ PepperPluginInstanceImpl* instance,
+ const blink::WebCursorInfo& cursor) {
+ // Update the cursor appearance immediately if the requesting plugin is the
+ // one which receives the last mouse event. Otherwise, the new cursor won't be
+ // picked up until the plugin gets the next input event. That is bad if, e.g.,
+ // the plugin would like to set an invisible cursor when there isn't any user
+ // input for a while.
+ if (instance == render_view_->pepper_last_mouse_event_target())
+ GetRenderWidget()->didChangeCursor(cursor);
+}
+
+void RenderFrameImpl::PepperDidReceiveMouseEvent(
+ PepperPluginInstanceImpl* instance) {
+ render_view_->set_pepper_last_mouse_event_target(instance);
+}
+
+void RenderFrameImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance,
+ bool focused) {
+ if (focused)
+ render_view_->set_focused_pepper_plugin(instance);
+ else if (render_view_->focused_pepper_plugin() == instance)
+ render_view_->set_focused_pepper_plugin(NULL);
+
+ GetRenderWidget()->UpdateTextInputType();
+ GetRenderWidget()->UpdateSelectionBounds();
+}
+
+void RenderFrameImpl::PepperTextInputTypeChanged(
+ PepperPluginInstanceImpl* instance) {
+ if (instance != render_view_->focused_pepper_plugin())
+ return;
+
+ GetRenderWidget()->UpdateTextInputType();
+ if (render_view_->renderer_accessibility()) {
+ render_view_->renderer_accessibility()->FocusedNodeChanged(
+ blink::WebNode());
+ }
+}
+
+void RenderFrameImpl::PepperCaretPositionChanged(
+ PepperPluginInstanceImpl* instance) {
+ if (instance != render_view_->focused_pepper_plugin())
+ return;
+ GetRenderWidget()->UpdateSelectionBounds();
+}
+
+void RenderFrameImpl::PepperCancelComposition(
+ PepperPluginInstanceImpl* instance) {
+ if (instance != render_view_->focused_pepper_plugin())
+ return;
+ Send(new ViewHostMsg_ImeCancelComposition(render_view_->GetRoutingID()));;
+#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
+ GetRenderWidget()->UpdateCompositionInfo(true);
+#endif
+}
+
+void RenderFrameImpl::PepperSelectionChanged(
+ PepperPluginInstanceImpl* instance) {
+ if (instance != render_view_->focused_pepper_plugin())
+ return;
+ render_view_->SyncSelectionIfRequired();
+}
+
+RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer(
+ PepperPluginInstanceImpl* plugin) {
+ GURL active_url;
+ if (render_view_->webview() && render_view_->webview()->mainFrame())
+ active_url = GURL(render_view_->webview()->mainFrame()->document().url());
+ RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create(
+ GetRenderWidget()->routing_id(), plugin, active_url,
+ GetRenderWidget()->screenInfo());
+ widget->show(blink::WebNavigationPolicyIgnore);
+ return widget;
+}
+
+bool RenderFrameImpl::IsPepperAcceptingCompositionEvents() const {
+ if (!render_view_->focused_pepper_plugin())
+ return false;
+ return render_view_->focused_pepper_plugin()->
+ IsPluginAcceptingCompositionEvents();
+}
+
+void RenderFrameImpl::PluginCrashed(const base::FilePath& plugin_path,
+ base::ProcessId plugin_pid) {
+ // TODO(jam): dispatch this IPC in RenderFrameHost and switch to use
+ // routing_id_ as a result.
+ Send(new FrameHostMsg_PluginCrashed(routing_id_, plugin_path, plugin_pid));
+}
+
+void RenderFrameImpl::DidInitiatePaint() {
+ // Notify all instances that we painted. The same caveats apply as for
+ // ViewFlushedPaint regarding instances closing themselves, so we take
+ // similar precautions.
+ PepperPluginSet plugins = active_pepper_instances_;
+ for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) {
+ if (active_pepper_instances_.find(*i) != active_pepper_instances_.end())
+ (*i)->ViewInitiatedPaint();
+ }
+}
+
+void RenderFrameImpl::DidFlushPaint() {
+ // Notify all instances that we flushed. This will call into the plugin, and
+ // we it may ask to close itself as a result. This will, in turn, modify our
+ // set, possibly invalidating the iterator. So we iterate on a copy that
+ // won't change out from under us.
+ PepperPluginSet plugins = active_pepper_instances_;
+ for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) {
+ // The copy above makes sure our iterator is never invalid if some plugins
+ // are destroyed. But some plugin may decide to close all of its views in
+ // response to a paint in one of them, so we need to make sure each one is
+ // still "current" before using it.
+ //
+ // It's possible that a plugin was destroyed, but another one was created
+ // with the same address. In this case, we'll call ViewFlushedPaint on that
+ // new plugin. But that's OK for this particular case since we're just
+ // notifying all of our instances that the view flushed, and the new one is
+ // one of our instances.
+ //
+ // What about the case where a new one is created in a callback at a new
+ // address and we don't issue the callback? We're still OK since this
+ // callback is used for flush callbacks and we could not have possibly
+ // started a new paint for the new plugin while processing a previous paint
+ // for an existing one.
+ if (active_pepper_instances_.find(*i) != active_pepper_instances_.end())
+ (*i)->ViewFlushedPaint();
+ }
+}
+
+PepperPluginInstanceImpl* RenderFrameImpl::GetBitmapForOptimizedPluginPaint(
+ const gfx::Rect& paint_bounds,
+ TransportDIB** dib,
+ gfx::Rect* location,
+ gfx::Rect* clip,
+ float* scale_factor) {
+ for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
+ i != active_pepper_instances_.end(); ++i) {
+ PepperPluginInstanceImpl* instance = *i;
+ // In Flash fullscreen , the plugin contents should be painted onto the
+ // fullscreen widget instead of the web page.
+ if (!instance->FlashIsFullscreenOrPending() &&
+ instance->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, location,
+ clip, scale_factor))
+ return *i;
+ }
+ return NULL;
+}
+
+void RenderFrameImpl::PageVisibilityChanged(bool shown) {
+ // Inform PPAPI plugins that their page is no longer visible.
+ for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
+ i != active_pepper_instances_.end(); ++i)
+ (*i)->PageVisibilityChanged(shown);
+}
+
+void RenderFrameImpl::OnSetFocus(bool enable) {
+ // Notify all Pepper plugins.
+ for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
+ i != active_pepper_instances_.end(); ++i)
+ (*i)->SetContentAreaFocus(enable);
+}
+
+void RenderFrameImpl::WillHandleMouseEvent(const blink::WebMouseEvent& event) {
+ // This method is called for every mouse event that the render view receives.
+ // And then the mouse event is forwarded to WebKit, which dispatches it to the
+ // event target. Potentially a Pepper plugin will receive the event.
+ // In order to tell whether a plugin gets the last mouse event and which it
+ // is, we set |pepper_last_mouse_event_target_| to NULL here. If a plugin gets
+ // the event, it will notify us via DidReceiveMouseEvent() and set itself as
+ // |pepper_last_mouse_event_target_|.
+ render_view_->set_pepper_last_mouse_event_target(NULL);
}
+void RenderFrameImpl::SimulateImeSetComposition(
+ const base::string16& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
+ int selection_start,
+ int selection_end) {
+ render_view_->OnImeSetComposition(
+ text, underlines, selection_start, selection_end);
+}
+
+void RenderFrameImpl::SimulateImeConfirmComposition(
+ const base::string16& text,
+ const gfx::Range& replacement_range) {
+ render_view_->OnImeConfirmComposition(text, replacement_range, false);
+}
+
+
+void RenderFrameImpl::OnImeSetComposition(
+ const base::string16& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
+ int selection_start,
+ int selection_end) {
+ // When a PPAPI plugin has focus, we bypass WebKit.
+ if (!IsPepperAcceptingCompositionEvents()) {
+ pepper_composition_text_ = text;
+ } else {
+ // TODO(kinaba) currently all composition events are sent directly to
+ // plugins. Use DOM event mechanism after WebKit is made aware about
+ // plugins that support composition.
+ // The code below mimics the behavior of WebCore::Editor::setComposition.
+
+ // Empty -> nonempty: composition started.
+ if (pepper_composition_text_.empty() && !text.empty()) {
+ render_view_->focused_pepper_plugin()->HandleCompositionStart(
+ base::string16());
+ }
+ // Nonempty -> empty: composition canceled.
+ if (!pepper_composition_text_.empty() && text.empty()) {
+ render_view_->focused_pepper_plugin()->HandleCompositionEnd(
+ base::string16());
+ }
+ pepper_composition_text_ = text;
+ // Nonempty: composition is ongoing.
+ if (!pepper_composition_text_.empty()) {
+ render_view_->focused_pepper_plugin()->HandleCompositionUpdate(
+ pepper_composition_text_, underlines, selection_start,
+ selection_end);
+ }
+ }
+}
+
+void RenderFrameImpl::OnImeConfirmComposition(
+ const base::string16& text,
+ const gfx::Range& replacement_range,
+ bool keep_selection) {
+ // When a PPAPI plugin has focus, we bypass WebKit.
+ // Here, text.empty() has a special meaning. It means to commit the last
+ // update of composition text (see
+ // RenderWidgetHost::ImeConfirmComposition()).
+ const base::string16& last_text = text.empty() ? pepper_composition_text_
+ : text;
+
+ // last_text is empty only when both text and pepper_composition_text_ is.
+ // Ignore it.
+ if (last_text.empty())
+ return;
+
+ if (!IsPepperAcceptingCompositionEvents()) {
+ base::i18n::UTF16CharIterator iterator(&last_text);
+ int32 i = 0;
+ while (iterator.Advance()) {
+ blink::WebKeyboardEvent char_event;
+ char_event.type = blink::WebInputEvent::Char;
+ char_event.timeStampSeconds = base::Time::Now().ToDoubleT();
+ char_event.modifiers = 0;
+ char_event.windowsKeyCode = last_text[i];
+ char_event.nativeKeyCode = last_text[i];
+
+ const int32 char_start = i;
+ for (; i < iterator.array_pos(); ++i) {
+ char_event.text[i - char_start] = last_text[i];
+ char_event.unmodifiedText[i - char_start] = last_text[i];
+ }
+
+ if (GetRenderWidget()->webwidget())
+ GetRenderWidget()->webwidget()->handleInputEvent(char_event);
+ }
+ } else {
+ // Mimics the order of events sent by WebKit.
+ // See WebCore::Editor::setComposition() for the corresponding code.
+ render_view_->focused_pepper_plugin()->HandleCompositionEnd(last_text);
+ render_view_->focused_pepper_plugin()->HandleTextInput(last_text);
+ }
+ pepper_composition_text_.clear();
+}
+
+#endif // ENABLE_PLUGINS
+
bool RenderFrameImpl::Send(IPC::Message* message) {
if (is_detaching_ ||
- (is_swapped_out_ &&
+ ((is_swapped_out_ || render_view_->is_swapped_out()) &&
!SwappedOutMessages::CanSendWhileSwappedOut(message))) {
delete message;
return false;
@@ -123,85 +447,121 @@ bool RenderFrameImpl::Send(IPC::Message* message) {
}
bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
+ ObserverListBase<RenderFrameObserver>::Iterator it(observers_);
+ RenderFrameObserver* observer;
+ while ((observer = it.GetNext()) != NULL) {
+ if (observer->OnMessageReceived(msg))
+ return true;
+ }
+
// TODO(ajwong): Fill in with message handlers as various components
// are migrated over to understand frames.
return false;
}
-// WebKit::WebFrameClient implementation -------------------------------------
+RenderView* RenderFrameImpl::GetRenderView() {
+ return render_view_;
+}
+
+int RenderFrameImpl::GetRoutingID() {
+ return routing_id_;
+}
+
+WebPreferences& RenderFrameImpl::GetWebkitPreferences() {
+ return render_view_->GetWebkitPreferences();
+}
+
+int RenderFrameImpl::ShowContextMenu(ContextMenuClient* client,
+ const ContextMenuParams& params) {
+ return render_view_->ShowContextMenu(client, params);
+}
+
+void RenderFrameImpl::CancelContextMenu(int request_id) {
+ return render_view_->CancelContextMenu(request_id);
+}
+
+blink::WebPlugin* RenderFrameImpl::CreatePlugin(
+ blink::WebFrame* frame,
+ const WebPluginInfo& info,
+ const blink::WebPluginParams& params) {
+#if defined(ENABLE_PLUGINS)
+ bool pepper_plugin_was_registered = false;
+ scoped_refptr<PluginModule> pepper_module(PluginModule::Create(
+ this, info, &pepper_plugin_was_registered));
+ if (pepper_plugin_was_registered) {
+ if (pepper_module.get()) {
+ // TODO(jam): change to take RenderFrame.
+ return new PepperWebPluginImpl(
+ pepper_module.get(), params, render_view_->AsWeakPtr(), this);
+ }
+ }
+#if defined(OS_CHROMEOS)
+ LOG(WARNING) << "Pepper module/plugin creation failed.";
+ return NULL;
+#else
+ // TODO(jam): change to take RenderFrame.
+ return new WebPluginImpl(frame, params, info.path, render_view_->AsWeakPtr(),
+ this);
+#endif
+#else
+ return NULL;
+#endif
+}
-WebKit::WebPlugin* RenderFrameImpl::createPlugin(
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params) {
- WebKit::WebPlugin* plugin = NULL;
+void RenderFrameImpl::LoadURLExternally(
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationPolicy policy) {
+ loadURLExternally(frame, request, policy);
+}
+
+// blink::WebFrameClient implementation ----------------------------------------
+
+blink::WebPlugin* RenderFrameImpl::createPlugin(
+ blink::WebFrame* frame,
+ const blink::WebPluginParams& params) {
+ blink::WebPlugin* plugin = NULL;
if (GetContentClient()->renderer()->OverrideCreatePlugin(
- render_view_, frame, params, &plugin)) {
+ this, frame, params, &plugin)) {
return plugin;
}
-#if defined(ENABLE_PLUGINS)
if (UTF16ToASCII(params.mimeType) == kBrowserPluginMimeType) {
return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin(
- render_view_, frame, params);
+ render_view_, frame);
}
+#if defined(ENABLE_PLUGINS)
WebPluginInfo info;
std::string mime_type;
- bool found = render_view_->GetPluginInfo(
- params.url, frame->top()->document().url(), params.mimeType.utf8(),
- &info, &mime_type);
+ bool found = false;
+ Send(new FrameHostMsg_GetPluginInfo(
+ routing_id_, params.url, frame->top()->document().url(),
+ params.mimeType.utf8(), &found, &info, &mime_type));
if (!found)
return NULL;
WebPluginParams params_to_use = params;
params_to_use.mimeType = WebString::fromUTF8(mime_type);
- return render_view_->CreatePlugin(frame, info, params_to_use);
+ return CreatePlugin(frame, info, params_to_use);
#else
return NULL;
#endif // defined(ENABLE_PLUGINS)
}
-WebKit::WebSharedWorker* RenderFrameImpl::createSharedWorker(
- WebKit::WebFrame* frame,
- const WebKit::WebURL& url,
- const WebKit::WebString& name,
- unsigned long long document_id) {
- int route_id = MSG_ROUTING_NONE;
- bool exists = false;
- bool url_mismatch = false;
- ViewHostMsg_CreateWorker_Params params;
- params.url = url;
- params.name = name;
- params.document_id = document_id;
- params.render_view_route_id = render_view_->GetRoutingID();
- params.route_id = MSG_ROUTING_NONE;
- params.script_resource_appcache_id = 0;
- render_view_->Send(new ViewHostMsg_LookupSharedWorker(
- params, &exists, &route_id, &url_mismatch));
- if (url_mismatch) {
- return NULL;
- } else {
- return new WebSharedWorkerProxy(RenderThreadImpl::current(),
- document_id,
- exists,
- route_id,
- render_view_->GetRoutingID());
- }
-}
-
-WebKit::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
- WebKit::WebFrame* frame,
- const WebKit::WebURL& url,
- WebKit::WebMediaPlayerClient* client) {
+blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
+ blink::WebFrame* frame,
+ const blink::WebURL& url,
+ blink::WebMediaPlayerClient* client) {
// TODO(nasko): Moving the implementation here involves moving a few media
// related client objects here or referencing them in the RenderView. Needs
// more work to understand where the proper place for those objects is.
- return render_view_->createMediaPlayer(frame, url, client);
+ return render_view_->CreateMediaPlayer(this, frame, url, client);
}
-WebKit::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost(
- WebKit::WebFrame* frame,
- WebKit::WebApplicationCacheHostClient* client) {
+blink::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost(
+ blink::WebFrame* frame,
+ blink::WebApplicationCacheHostClient* client) {
if (!frame || !frame->view())
return NULL;
return new RendererWebApplicationCacheHostImpl(
@@ -209,26 +569,75 @@ WebKit::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost(
RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy());
}
-WebKit::WebCookieJar* RenderFrameImpl::cookieJar(WebKit::WebFrame* frame) {
+blink::WebWorkerPermissionClientProxy*
+RenderFrameImpl::createWorkerPermissionClientProxy(WebFrame* frame) {
+ if (!frame || !frame->view())
+ return NULL;
+ return GetContentClient()->renderer()->CreateWorkerPermissionClientProxy(
+ RenderViewImpl::FromWebView(frame->view()), frame);
+}
+
+blink::WebCookieJar* RenderFrameImpl::cookieJar(blink::WebFrame* frame) {
return render_view_->cookieJar(frame);
}
-void RenderFrameImpl::didAccessInitialDocument(WebKit::WebFrame* frame) {
+blink::WebServiceWorkerProvider* RenderFrameImpl::createServiceWorkerProvider(
+ blink::WebFrame* frame,
+ blink::WebServiceWorkerProviderClient* client) {
+ return new WebServiceWorkerProviderImpl(
+ ChildThread::current()->thread_safe_sender(),
+ make_scoped_ptr(client));
+}
+
+void RenderFrameImpl::didAccessInitialDocument(blink::WebFrame* frame) {
render_view_->didAccessInitialDocument(frame);
}
-void RenderFrameImpl::didCreateFrame(WebKit::WebFrame* parent,
- WebKit::WebFrame* child) {
- render_view_->Send(new ViewHostMsg_FrameAttached(
- render_view_->GetRoutingID(), parent->identifier(), child->identifier(),
- UTF16ToUTF8(child->assignedName())));
+blink::WebFrame* RenderFrameImpl::createChildFrame(
+ blink::WebFrame* parent,
+ const blink::WebString& name) {
+ RenderFrameImpl* child_render_frame = this;
+ long long child_frame_identifier = WebFrame::generateEmbedderIdentifier();
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
+ // Synchronously notify the browser of a child frame creation to get the
+ // routing_id for the RenderFrame.
+ int routing_id;
+ Send(new FrameHostMsg_CreateChildFrame(routing_id_,
+ parent->identifier(),
+ child_frame_identifier,
+ UTF16ToUTF8(name),
+ &routing_id));
+ child_render_frame = RenderFrameImpl::Create(render_view_, routing_id);
+ }
+
+ blink::WebFrame* web_frame = WebFrame::create(child_render_frame,
+ child_frame_identifier);
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
+ g_child_frame_map.Get().insert(
+ std::make_pair(web_frame, child_render_frame));
+ }
+
+ return web_frame;
}
-void RenderFrameImpl::didDisownOpener(WebKit::WebFrame* frame) {
+void RenderFrameImpl::didDisownOpener(blink::WebFrame* frame) {
render_view_->didDisownOpener(frame);
}
-void RenderFrameImpl::frameDetached(WebKit::WebFrame* frame) {
+void RenderFrameImpl::frameDetached(blink::WebFrame* frame) {
+ // 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_);
+
+ int64 parent_frame_id = -1;
+ if (frame->parent())
+ parent_frame_id = frame->parent()->identifier();
+
+ Send(new FrameHostMsg_Detach(routing_id_, parent_frame_id,
+ frame->identifier()));
+
// Currently multiple WebCore::Frames can send frameDetached to a single
// RenderFrameImpl. This is legacy behavior from when RenderViewImpl served
// as a shared WebFrameClient for multiple Webcore::Frame objects. It also
@@ -236,32 +645,42 @@ void RenderFrameImpl::frameDetached(WebKit::WebFrame* frame) {
// even though one WebCore::Frame may have detached itself, others will
// still need to use this object.
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
- // TODO(ajwong): Add CHECK(!is_detaching_) once we guarantee each
- // RenderFrameImpl is only used by one WebCore::Frame.
+ // The |is_detaching_| flag disables Send(). FrameHostMsg_Detach must be
+ // sent before setting |is_detaching_| to true. In contrast, Observers
+ // should only be notified afterwards so they cannot call back into and
+ // have IPCs fired off.
is_detaching_ = true;
}
- int64 parent_frame_id = -1;
- if (frame->parent())
- parent_frame_id = frame->parent()->identifier();
-
- render_view_->Send(new ViewHostMsg_FrameDetached(render_view_->GetRoutingID(),
- parent_frame_id,
- frame->identifier()));
-
// Call back to RenderViewImpl for observers to be notified.
// TODO(nasko): Remove once we have RenderFrameObserver.
render_view_->frameDetached(frame);
+
+ frame->close();
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
+ // If the frame does not have a parent, it is the main frame. The main
+ // frame is owned by the containing RenderViewHost so it does not require
+ // any cleanup here.
+ if (frame->parent()) {
+ FrameMap::iterator it = g_child_frame_map.Get().find(frame);
+ DCHECK(it != g_child_frame_map.Get().end());
+ DCHECK_EQ(it->second, this);
+ g_child_frame_map.Get().erase(it);
+ delete this;
+ // Object is invalid after this point.
+ }
+ }
}
-void RenderFrameImpl::willClose(WebKit::WebFrame* frame) {
+void RenderFrameImpl::willClose(blink::WebFrame* frame) {
// Call back to RenderViewImpl for observers to be notified.
// TODO(nasko): Remove once we have RenderFrameObserver.
render_view_->willClose(frame);
}
-void RenderFrameImpl::didChangeName(WebKit::WebFrame* frame,
- const WebKit::WebString& name) {
+void RenderFrameImpl::didChangeName(blink::WebFrame* frame,
+ const blink::WebString& name) {
if (!render_view_->renderer_preferences_.report_frame_name_changes)
return;
@@ -272,19 +691,27 @@ void RenderFrameImpl::didChangeName(WebKit::WebFrame* frame,
UTF16ToUTF8(name)));
}
-void RenderFrameImpl::loadURLExternally(WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationPolicy policy) {
+void RenderFrameImpl::didMatchCSS(
+ blink::WebFrame* frame,
+ const blink::WebVector<blink::WebString>& newly_matching_selectors,
+ const blink::WebVector<blink::WebString>& stopped_matching_selectors) {
+ render_view_->didMatchCSS(
+ frame, newly_matching_selectors, stopped_matching_selectors);
+}
+
+void RenderFrameImpl::loadURLExternally(blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationPolicy policy) {
loadURLExternally(frame, request, policy, WebString());
}
void RenderFrameImpl::loadURLExternally(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationPolicy policy,
- const WebKit::WebString& suggested_name) {
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationPolicy policy,
+ const blink::WebString& suggested_name) {
Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame, request));
- if (policy == WebKit::WebNavigationPolicyDownload) {
+ if (policy == blink::WebNavigationPolicyDownload) {
render_view_->Send(new ViewHostMsg_DownloadUrl(render_view_->GetRoutingID(),
request.url(), referrer,
suggested_name));
@@ -293,36 +720,36 @@ void RenderFrameImpl::loadURLExternally(
}
}
-WebKit::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
- WebKit::WebFrame* frame,
- WebKit::WebDataSource::ExtraData* extra_data,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationType type,
- WebKit::WebNavigationPolicy default_policy,
+blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
+ blink::WebFrame* frame,
+ blink::WebDataSource::ExtraData* extra_data,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationType type,
+ blink::WebNavigationPolicy default_policy,
bool is_redirect) {
return render_view_->decidePolicyForNavigation(
frame, extra_data, request, type, default_policy, is_redirect);
}
-WebKit::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationType type,
- WebKit::WebNavigationPolicy default_policy,
+blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationType type,
+ blink::WebNavigationPolicy default_policy,
bool is_redirect) {
return render_view_->decidePolicyForNavigation(
frame, request, type, default_policy, is_redirect);
}
-void RenderFrameImpl::willSendSubmitEvent(WebKit::WebFrame* frame,
- const WebKit::WebFormElement& form) {
+void RenderFrameImpl::willSendSubmitEvent(blink::WebFrame* frame,
+ const blink::WebFormElement& form) {
// Call back to RenderViewImpl for observers to be notified.
// TODO(nasko): Remove once we have RenderFrameObserver.
render_view_->willSendSubmitEvent(frame, form);
}
-void RenderFrameImpl::willSubmitForm(WebKit::WebFrame* frame,
- const WebKit::WebFormElement& form) {
+void RenderFrameImpl::willSubmitForm(blink::WebFrame* frame,
+ const blink::WebFormElement& form) {
DocumentState* document_state =
DocumentState::FromDataSource(frame->provisionalDataSource());
NavigationState* navigation_state = document_state->navigation_state();
@@ -345,8 +772,8 @@ void RenderFrameImpl::willSubmitForm(WebKit::WebFrame* frame,
render_view_->willSubmitForm(frame, form);
}
-void RenderFrameImpl::didCreateDataSource(WebKit::WebFrame* frame,
- WebKit::WebDataSource* datasource) {
+void RenderFrameImpl::didCreateDataSource(blink::WebFrame* frame,
+ blink::WebDataSource* datasource) {
// TODO(nasko): Move implementation here. Needed state:
// * pending_navigation_params_
// * webview
@@ -356,24 +783,64 @@ void RenderFrameImpl::didCreateDataSource(WebKit::WebFrame* frame,
render_view_->didCreateDataSource(frame, datasource);
}
-void RenderFrameImpl::didStartProvisionalLoad(WebKit::WebFrame* frame) {
- // TODO(nasko): Move implementation here. Needed state:
- // * is_swapped_out_
- // * navigation_gesture_
- // * completed_client_redirect_src_
- render_view_->didStartProvisionalLoad(frame);
+void RenderFrameImpl::didStartProvisionalLoad(blink::WebFrame* frame) {
+ WebDataSource* ds = frame->provisionalDataSource();
+
+ // In fast/loader/stop-provisional-loads.html, we abort the load before this
+ // callback is invoked.
+ if (!ds)
+ return;
+
+ DocumentState* document_state = DocumentState::FromDataSource(ds);
+
+ // We should only navigate to swappedout:// when is_swapped_out_ is true.
+ CHECK((ds->request().url() != GURL(kSwappedOutURL)) ||
+ render_view_->is_swapped_out()) <<
+ "Heard swappedout:// when not swapped out.";
+
+ // Update the request time if WebKit has better knowledge of it.
+ if (document_state->request_time().is_null()) {
+ double event_time = ds->triggeringEventTime();
+ if (event_time != 0.0)
+ document_state->set_request_time(Time::FromDoubleT(event_time));
+ }
+
+ // Start time is only set after request time.
+ document_state->set_start_load_time(Time::Now());
+
+ bool is_top_most = !frame->parent();
+ if (is_top_most) {
+ render_view_->set_navigation_gesture(
+ WebUserGestureIndicator::isProcessingUserGesture() ?
+ NavigationGestureUser : NavigationGestureAuto);
+ } else if (ds->replacesCurrentHistoryItem()) {
+ // Subframe navigations that don't add session history items must be
+ // marked with AUTO_SUBFRAME. See also didFailProvisionalLoad for how we
+ // handle loading of error pages.
+ document_state->navigation_state()->set_transition_type(
+ PAGE_TRANSITION_AUTO_SUBFRAME);
+ }
+
+ FOR_EACH_OBSERVER(
+ RenderViewObserver, render_view_->observers(),
+ DidStartProvisionalLoad(frame));
+
+ Send(new FrameHostMsg_DidStartProvisionalLoadForFrame(
+ routing_id_, frame->identifier(),
+ frame->parent() ? frame->parent()->identifier() : -1,
+ is_top_most, ds->request().url()));
}
void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad(
- WebKit::WebFrame* frame) {
+ blink::WebFrame* frame) {
// TODO(nasko): Move implementation here. Needed state:
// * page_id_
render_view_->didReceiveServerRedirectForProvisionalLoad(frame);
}
void RenderFrameImpl::didFailProvisionalLoad(
- WebKit::WebFrame* frame,
- const WebKit::WebURLError& error) {
+ blink::WebFrame* frame,
+ const blink::WebURLError& error) {
// TODO(nasko): Move implementation here. Needed state:
// * page_id_
// * pending_navigation_params_
@@ -383,7 +850,7 @@ void RenderFrameImpl::didFailProvisionalLoad(
render_view_->didFailProvisionalLoad(frame, error);
}
-void RenderFrameImpl::didCommitProvisionalLoad(WebKit::WebFrame* frame,
+void RenderFrameImpl::didCommitProvisionalLoad(blink::WebFrame* frame,
bool is_new_navigation) {
// TODO(nasko): Move implementation here. Needed state:
// * page_id_
@@ -398,7 +865,7 @@ void RenderFrameImpl::didCommitProvisionalLoad(WebKit::WebFrame* frame,
render_view_->didCommitProvisionalLoad(frame, is_new_navigation);
}
-void RenderFrameImpl::didClearWindowObject(WebKit::WebFrame* frame) {
+void RenderFrameImpl::didClearWindowObject(blink::WebFrame* frame) {
// TODO(nasko): Move implementation here. Needed state:
// * enabled_bindings_
// * dom_automation_controller_
@@ -406,7 +873,7 @@ void RenderFrameImpl::didClearWindowObject(WebKit::WebFrame* frame) {
render_view_->didClearWindowObject(frame);
}
-void RenderFrameImpl::didCreateDocumentElement(WebKit::WebFrame* frame) {
+void RenderFrameImpl::didCreateDocumentElement(blink::WebFrame* frame) {
// Notify the browser about non-blank documents loading in the top frame.
GURL url = frame->document().url();
if (url.is_valid() && url.spec() != kAboutBlankURL) {
@@ -423,60 +890,60 @@ void RenderFrameImpl::didCreateDocumentElement(WebKit::WebFrame* frame) {
render_view_->didCreateDocumentElement(frame);
}
-void RenderFrameImpl::didReceiveTitle(WebKit::WebFrame* frame,
- const WebKit::WebString& title,
- WebKit::WebTextDirection direction) {
+void RenderFrameImpl::didReceiveTitle(blink::WebFrame* frame,
+ const blink::WebString& title,
+ blink::WebTextDirection direction) {
// TODO(nasko): Investigate wheather implementation should move here.
render_view_->didReceiveTitle(frame, title, direction);
}
-void RenderFrameImpl::didChangeIcon(WebKit::WebFrame* frame,
- WebKit::WebIconURL::Type icon_type) {
+void RenderFrameImpl::didChangeIcon(blink::WebFrame* frame,
+ blink::WebIconURL::Type icon_type) {
// TODO(nasko): Investigate wheather implementation should move here.
render_view_->didChangeIcon(frame, icon_type);
}
-void RenderFrameImpl::didFinishDocumentLoad(WebKit::WebFrame* frame) {
+void RenderFrameImpl::didFinishDocumentLoad(blink::WebFrame* frame) {
// TODO(nasko): Move implementation here. No state needed, just observers
// notification in before updating encoding.
render_view_->didFinishDocumentLoad(frame);
}
-void RenderFrameImpl::didHandleOnloadEvents(WebKit::WebFrame* frame) {
+void RenderFrameImpl::didHandleOnloadEvents(blink::WebFrame* frame) {
// TODO(nasko): Move implementation here. Needed state:
// * page_id_
render_view_->didHandleOnloadEvents(frame);
}
-void RenderFrameImpl::didFailLoad(WebKit::WebFrame* frame,
- const WebKit::WebURLError& error) {
+void RenderFrameImpl::didFailLoad(blink::WebFrame* frame,
+ const blink::WebURLError& error) {
// TODO(nasko): Move implementation here. No state needed.
render_view_->didFailLoad(frame, error);
}
-void RenderFrameImpl::didFinishLoad(WebKit::WebFrame* frame) {
+void RenderFrameImpl::didFinishLoad(blink::WebFrame* frame) {
// TODO(nasko): Move implementation here. No state needed, just observers
// notification before sending message to the browser process.
render_view_->didFinishLoad(frame);
}
-void RenderFrameImpl::didNavigateWithinPage(WebKit::WebFrame* frame,
+void RenderFrameImpl::didNavigateWithinPage(blink::WebFrame* frame,
bool is_new_navigation) {
// TODO(nasko): Move implementation here. No state needed, just observers
// notification before sending message to the browser process.
render_view_->didNavigateWithinPage(frame, is_new_navigation);
}
-void RenderFrameImpl::didUpdateCurrentHistoryItem(WebKit::WebFrame* frame) {
+void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebFrame* frame) {
// TODO(nasko): Move implementation here. Needed methods:
// * StartNavStateSyncTimerIfNecessary
render_view_->didUpdateCurrentHistoryItem(frame);
}
void RenderFrameImpl::willRequestAfterPreconnect(
- WebKit::WebFrame* frame,
- WebKit::WebURLRequest& request) {
- WebKit::WebReferrerPolicy referrer_policy = WebKit::WebReferrerPolicyDefault;
+ blink::WebFrame* frame,
+ blink::WebURLRequest& request) {
+ blink::WebReferrerPolicy referrer_policy = blink::WebReferrerPolicyDefault;
WebString custom_user_agent;
if (request.extraData()) {
@@ -498,10 +965,10 @@ void RenderFrameImpl::willRequestAfterPreconnect(
}
void RenderFrameImpl::willSendRequest(
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
unsigned identifier,
- WebKit::WebURLRequest& request,
- const WebKit::WebURLResponse& redirect_response) {
+ blink::WebURLRequest& request,
+ const blink::WebURLResponse& redirect_response) {
// The request my be empty during tests.
if (request.url().isEmpty())
return;
@@ -536,7 +1003,7 @@ void RenderFrameImpl::willSendRequest(
if (internal_data->is_cache_policy_override_set())
request.setCachePolicy(internal_data->cache_policy_override());
- WebKit::WebReferrerPolicy referrer_policy;
+ blink::WebReferrerPolicy referrer_policy;
if (internal_data->is_referrer_policy_set()) {
referrer_policy = internal_data->referrer_policy();
internal_data->clear_referrer_policy();
@@ -565,10 +1032,26 @@ void RenderFrameImpl::willSendRequest(
}
}
+ // Attach |should_replace_current_entry| state to requests so that, should
+ // this navigation later require a request transfer, all state is preserved
+ // when it is re-created in the new process.
+ bool should_replace_current_entry = false;
+ if (navigation_state->is_content_initiated()) {
+ should_replace_current_entry = data_source->replacesCurrentHistoryItem();
+ } else {
+ // If the navigation is browser-initiated, the NavigationState contains the
+ // correct value instead of the WebDataSource.
+ //
+ // TODO(davidben): Avoid this awkward duplication of state. See comment on
+ // NavigationState::should_replace_current_entry().
+ should_replace_current_entry =
+ navigation_state->should_replace_current_entry();
+ }
request.setExtraData(
new RequestExtraData(referrer_policy,
custom_user_agent,
was_after_preconnect_request,
+ routing_id_,
(frame == top_frame),
frame->identifier(),
GURL(frame->document().securityOrigin().toString()),
@@ -576,6 +1059,7 @@ void RenderFrameImpl::willSendRequest(
frame->parent() ? frame->parent()->identifier() : -1,
navigation_state->allow_download(),
transition_type,
+ should_replace_current_entry,
navigation_state->transferred_request_child_id(),
navigation_state->transferred_request_request_id()));
@@ -613,9 +1097,9 @@ void RenderFrameImpl::willSendRequest(
}
void RenderFrameImpl::didReceiveResponse(
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
unsigned identifier,
- const WebKit::WebURLResponse& response) {
+ const blink::WebURLResponse& response) {
// Only do this for responses that correspond to a provisional data source
// of the top-most frame. If we have a provisional data source, then we
// can't have any sub-resources yet, so we know that this response must
@@ -658,7 +1142,7 @@ void RenderFrameImpl::didReceiveResponse(
internal_data->set_use_error_page(true);
}
-void RenderFrameImpl::didFinishResourceLoad(WebKit::WebFrame* frame,
+void RenderFrameImpl::didFinishResourceLoad(blink::WebFrame* frame,
unsigned identifier) {
// TODO(nasko): Move implementation here. Needed state:
// * devtools_agent_
@@ -668,9 +1152,9 @@ void RenderFrameImpl::didFinishResourceLoad(WebKit::WebFrame* frame,
}
void RenderFrameImpl::didLoadResourceFromMemoryCache(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- const WebKit::WebURLResponse& response) {
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ const blink::WebURLResponse& response) {
// The recipients of this message have no use for data: URLs: they don't
// affect the page's insecure content list and are not in the disk cache. To
// prevent large (1M+) data: URLs from crashing in the IPC system, we simply
@@ -690,28 +1174,37 @@ void RenderFrameImpl::didLoadResourceFromMemoryCache(
ResourceType::FromTargetType(request.targetType())));
}
-void RenderFrameImpl::didDisplayInsecureContent(WebKit::WebFrame* frame) {
+void RenderFrameImpl::didDisplayInsecureContent(blink::WebFrame* frame) {
render_view_->Send(new ViewHostMsg_DidDisplayInsecureContent(
render_view_->GetRoutingID()));
}
void RenderFrameImpl::didRunInsecureContent(
- WebKit::WebFrame* frame,
- const WebKit::WebSecurityOrigin& origin,
- const WebKit::WebURL& target) {
+ blink::WebFrame* frame,
+ const blink::WebSecurityOrigin& origin,
+ const blink::WebURL& target) {
render_view_->Send(new ViewHostMsg_DidRunInsecureContent(
render_view_->GetRoutingID(),
origin.toString().utf8(),
target));
}
+void RenderFrameImpl::didAbortLoading(blink::WebFrame* frame) {
+#if defined(ENABLE_PLUGINS)
+ if (frame != render_view_->webview()->mainFrame())
+ return;
+ PluginChannelHost::Broadcast(
+ new PluginHostMsg_DidAbortLoading(render_view_->GetRoutingID()));
+#endif
+}
+
void RenderFrameImpl::didExhaustMemoryAvailableForScript(
- WebKit::WebFrame* frame) {
+ blink::WebFrame* frame) {
render_view_->Send(new ViewHostMsg_JSOutOfMemory(
render_view_->GetRoutingID()));
}
-void RenderFrameImpl::didCreateScriptContext(WebKit::WebFrame* frame,
+void RenderFrameImpl::didCreateScriptContext(blink::WebFrame* frame,
v8::Handle<v8::Context> context,
int extension_group,
int world_id) {
@@ -719,32 +1212,32 @@ void RenderFrameImpl::didCreateScriptContext(WebKit::WebFrame* frame,
frame, context, extension_group, world_id);
}
-void RenderFrameImpl::willReleaseScriptContext(WebKit::WebFrame* frame,
+void RenderFrameImpl::willReleaseScriptContext(blink::WebFrame* frame,
v8::Handle<v8::Context> context,
int world_id) {
GetContentClient()->renderer()->WillReleaseScriptContext(
frame, context, world_id);
}
-void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(WebKit::WebFrame* frame) {
+void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(blink::WebFrame* frame) {
render_view_->didFirstVisuallyNonEmptyLayout(frame);
}
-void RenderFrameImpl::didChangeContentsSize(WebKit::WebFrame* frame,
- const WebKit::WebSize& size) {
+void RenderFrameImpl::didChangeContentsSize(blink::WebFrame* frame,
+ const blink::WebSize& size) {
// TODO(nasko): Move implementation here. Needed state:
// * cached_has_main_frame_horizontal_scrollbar_
// * cached_has_main_frame_vertical_scrollbar_
render_view_->didChangeContentsSize(frame, size);
}
-void RenderFrameImpl::didChangeScrollOffset(WebKit::WebFrame* frame) {
+void RenderFrameImpl::didChangeScrollOffset(blink::WebFrame* frame) {
// TODO(nasko): Move implementation here. Needed methods:
// * StartNavStateSyncTimerIfNecessary
render_view_->didChangeScrollOffset(frame);
}
-void RenderFrameImpl::willInsertBody(WebKit::WebFrame* frame) {
+void RenderFrameImpl::willInsertBody(blink::WebFrame* frame) {
if (!frame->parent()) {
render_view_->Send(new ViewHostMsg_WillInsertBody(
render_view_->GetRoutingID()));
@@ -766,22 +1259,22 @@ void RenderFrameImpl::reportFindInPageMatchCount(int request_id,
void RenderFrameImpl::reportFindInPageSelection(
int request_id,
int active_match_ordinal,
- const WebKit::WebRect& selection_rect) {
+ const blink::WebRect& selection_rect) {
render_view_->Send(new ViewHostMsg_Find_Reply(
render_view_->GetRoutingID(), request_id, -1, selection_rect,
active_match_ordinal, false));
}
void RenderFrameImpl::requestStorageQuota(
- WebKit::WebFrame* frame,
- WebKit::WebStorageQuotaType type,
+ blink::WebFrame* frame,
+ blink::WebStorageQuotaType type,
unsigned long long requested_size,
- WebKit::WebStorageQuotaCallbacks* callbacks) {
+ blink::WebStorageQuotaCallbacks* callbacks) {
DCHECK(frame);
WebSecurityOrigin origin = frame->document().securityOrigin();
if (origin.isUnique()) {
// Unique origins cannot store persistent state.
- callbacks->didFail(WebKit::WebStorageQuotaErrorAbort);
+ callbacks->didFail(blink::WebStorageQuotaErrorAbort);
return;
}
ChildThread::current()->quota_dispatcher()->RequestStorageQuota(
@@ -791,35 +1284,35 @@ void RenderFrameImpl::requestStorageQuota(
}
void RenderFrameImpl::willOpenSocketStream(
- WebKit::WebSocketStreamHandle* handle) {
+ blink::WebSocketStreamHandle* handle) {
SocketStreamHandleData::AddToHandle(handle, render_view_->GetRoutingID());
}
void RenderFrameImpl::willStartUsingPeerConnectionHandler(
- WebKit::WebFrame* frame,
- WebKit::WebRTCPeerConnectionHandler* handler) {
+ blink::WebFrame* frame,
+ blink::WebRTCPeerConnectionHandler* handler) {
#if defined(ENABLE_WEBRTC)
static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame);
#endif
}
bool RenderFrameImpl::willCheckAndDispatchMessageEvent(
- WebKit::WebFrame* sourceFrame,
- WebKit::WebFrame* targetFrame,
- WebKit::WebSecurityOrigin targetOrigin,
- WebKit::WebDOMMessageEvent event) {
+ blink::WebFrame* sourceFrame,
+ blink::WebFrame* targetFrame,
+ blink::WebSecurityOrigin targetOrigin,
+ blink::WebDOMMessageEvent event) {
// TODO(nasko): Move implementation here. Needed state:
// * is_swapped_out_
return render_view_->willCheckAndDispatchMessageEvent(
sourceFrame, targetFrame, targetOrigin, event);
}
-WebKit::WebString RenderFrameImpl::userAgentOverride(
- WebKit::WebFrame* frame,
- const WebKit::WebURL& url) {
+blink::WebString RenderFrameImpl::userAgentOverride(
+ blink::WebFrame* frame,
+ const blink::WebURL& url) {
if (!render_view_->webview() || !render_view_->webview()->mainFrame() ||
render_view_->renderer_preferences_.user_agent_override.empty()) {
- return WebKit::WebString();
+ return blink::WebString();
}
// If we're in the middle of committing a load, the data source we need
@@ -836,16 +1329,16 @@ WebKit::WebString RenderFrameImpl::userAgentOverride(
if (internal_data && internal_data->is_overriding_user_agent())
return WebString::fromUTF8(
render_view_->renderer_preferences_.user_agent_override);
- return WebKit::WebString();
+ return blink::WebString();
}
-WebKit::WebString RenderFrameImpl::doNotTrackValue(WebKit::WebFrame* frame) {
+blink::WebString RenderFrameImpl::doNotTrackValue(blink::WebFrame* frame) {
if (render_view_->renderer_preferences_.enable_do_not_track)
return WebString::fromUTF8("1");
return WebString();
}
-bool RenderFrameImpl::allowWebGL(WebKit::WebFrame* frame, bool default_value) {
+bool RenderFrameImpl::allowWebGL(blink::WebFrame* frame, bool default_value) {
if (!default_value)
return false;
@@ -858,7 +1351,7 @@ bool RenderFrameImpl::allowWebGL(WebKit::WebFrame* frame, bool default_value) {
return !blocked;
}
-void RenderFrameImpl::didLoseWebGLContext(WebKit::WebFrame* frame,
+void RenderFrameImpl::didLoseWebGLContext(blink::WebFrame* frame,
int arb_robustness_status_code) {
render_view_->Send(new ViewHostMsg_DidLose3DContext(
GURL(frame->top()->document().securityOrigin().toString()),
@@ -866,4 +1359,13 @@ void RenderFrameImpl::didLoseWebGLContext(WebKit::WebFrame* frame,
arb_robustness_status_code));
}
+void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void RenderFrameImpl::RemoveObserver(RenderFrameObserver* observer) {
+ observer->RenderFrameGone();
+ observers_.RemoveObserver(observer);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h
index b6940f96e91..2d26bd28ee6 100644
--- a/chromium/content/renderer/render_frame_impl.h
+++ b/chromium/content/renderer/render_frame_impl.h
@@ -5,19 +5,44 @@
#ifndef CONTENT_RENDERER_RENDER_FRAME_IMPL_H_
#define CONTENT_RENDERER_RENDER_FRAME_IMPL_H_
+#include <set>
+#include <vector>
+
#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/observer_list.h"
+#include "base/process/process_handle.h"
+#include "base/strings/string16.h"
#include "content/public/renderer/render_frame.h"
#include "ipc/ipc_message.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebFrameClient.h"
+class TransportDIB;
+
+namespace blink {
+class WebMouseEvent;
+struct WebCompositionUnderline;
+struct WebCursorInfo;
+}
+
+namespace gfx {
+class Range;
+class Rect;
+}
+
namespace content {
+class PepperPluginInstanceImpl;
+class RendererPpapiHost;
+class RenderFrameObserver;
class RenderViewImpl;
+class RenderWidget;
+class RenderWidgetFullscreenPepper;
class CONTENT_EXPORT RenderFrameImpl
: public RenderFrame,
- NON_EXPORTED_BASE(public WebKit::WebFrameClient) {
+ NON_EXPORTED_BASE(public blink::WebFrameClient) {
public:
// Creates a new RenderFrame. |render_view| is the RenderView object that this
// frame belongs to.
@@ -30,163 +55,289 @@ class CONTENT_EXPORT RenderFrameImpl
virtual ~RenderFrameImpl();
+ // TODO(jam): this is a temporary getter until all the code is transitioned
+ // to using RenderFrame instead of RenderView.
+ RenderViewImpl* render_view() { return render_view_; }
+
+ // Returns the RenderWidget associated with this frame.
+ RenderWidget* GetRenderWidget();
+
+#if defined(ENABLE_PLUGINS)
+ // Notification that a PPAPI plugin has been created.
+ void PepperPluginCreated(RendererPpapiHost* host);
+
+ // Indicates that the given instance has been created.
+ void PepperInstanceCreated(PepperPluginInstanceImpl* instance);
+
+ // Indicates that the given instance is being destroyed. This is called from
+ // the destructor, so it's important that the instance is not dereferenced
+ // from this call.
+ void PepperInstanceDeleted(PepperPluginInstanceImpl* instance);
+
+ // Notifies that |instance| has changed the cursor.
+ // This will update the cursor appearance if it is currently over the plugin
+ // instance.
+ void PepperDidChangeCursor(PepperPluginInstanceImpl* instance,
+ const blink::WebCursorInfo& cursor);
+
+ // Notifies that |instance| has received a mouse event.
+ void PepperDidReceiveMouseEvent(PepperPluginInstanceImpl* instance);
+
+ // Notification that the given plugin is focused or unfocused.
+ void PepperFocusChanged(PepperPluginInstanceImpl* instance, bool focused);
+
+ // Informs the render view that a PPAPI plugin has changed text input status.
+ void PepperTextInputTypeChanged(PepperPluginInstanceImpl* instance);
+ void PepperCaretPositionChanged(PepperPluginInstanceImpl* instance);
+
+ // Cancels current composition.
+ void PepperCancelComposition(PepperPluginInstanceImpl* instance);
+
+ // Informs the render view that a PPAPI plugin has changed selection.
+ void PepperSelectionChanged(PepperPluginInstanceImpl* instance);
+
+ // Creates a fullscreen container for a pepper plugin instance.
+ RenderWidgetFullscreenPepper* CreatePepperFullscreenContainer(
+ PepperPluginInstanceImpl* plugin);
+
+ bool IsPepperAcceptingCompositionEvents() const;
+
+ // Notification that the given plugin has crashed.
+ void PluginCrashed(const base::FilePath& plugin_path,
+ base::ProcessId plugin_pid);
+
+ // These map to virtual methods on RenderWidget that are used to call out to
+ // RenderView.
+ // TODO(jam): once we get rid of RenderView, RenderFrame will own RenderWidget
+ // and methods would be on a delegate interface.
+ void DidInitiatePaint();
+ void DidFlushPaint();
+ PepperPluginInstanceImpl* GetBitmapForOptimizedPluginPaint(
+ const gfx::Rect& paint_bounds,
+ TransportDIB** dib,
+ gfx::Rect* location,
+ gfx::Rect* clip,
+ float* scale_factor);
+ void PageVisibilityChanged(bool shown);
+ void OnSetFocus(bool enable);
+ void WillHandleMouseEvent(const blink::WebMouseEvent& event);
+
+ // Simulates IME events for testing purpose.
+ void SimulateImeSetComposition(
+ const base::string16& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
+ int selection_start,
+ int selection_end);
+ void SimulateImeConfirmComposition(const base::string16& text,
+ const gfx::Range& replacement_range);
+
+ // TODO(jam): remove these once the IPC handler moves from RenderView to
+ // RenderFrame.
+ void OnImeSetComposition(
+ const base::string16& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
+ int selection_start,
+ int selection_end);
+ void OnImeConfirmComposition(
+ const base::string16& text,
+ const gfx::Range& replacement_range,
+ bool keep_selection);
+#endif // ENABLE_PLUGINS
+
// IPC::Sender
virtual bool Send(IPC::Message* msg) OVERRIDE;
// IPC::Listener
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- // WebKit::WebFrameClient implementation -------------------------------------
- virtual WebKit::WebPlugin* createPlugin(
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params);
- virtual WebKit::WebSharedWorker* createSharedWorker(
- WebKit::WebFrame* frame,
- const WebKit::WebURL& url,
- const WebKit::WebString& name,
- unsigned long long document_id);
- virtual WebKit::WebMediaPlayer* createMediaPlayer(
- WebKit::WebFrame* frame,
- const WebKit::WebURL& url,
- WebKit::WebMediaPlayerClient* client);
- virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost(
- WebKit::WebFrame* frame,
- WebKit::WebApplicationCacheHostClient* client);
- virtual WebKit::WebCookieJar* cookieJar(WebKit::WebFrame* frame);
- virtual void didAccessInitialDocument(WebKit::WebFrame* frame);
- virtual void didCreateFrame(WebKit::WebFrame* parent,
- WebKit::WebFrame* child);
- virtual void didDisownOpener(WebKit::WebFrame* frame);
- virtual void frameDetached(WebKit::WebFrame* frame);
- virtual void willClose(WebKit::WebFrame* frame);
- virtual void didChangeName(WebKit::WebFrame* frame,
- const WebKit::WebString& name);
- virtual void loadURLExternally(WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationPolicy policy);
+ // RenderFrame implementation:
+ virtual RenderView* GetRenderView() OVERRIDE;
+ virtual int GetRoutingID() OVERRIDE;
+ virtual WebPreferences& GetWebkitPreferences() OVERRIDE;
+ virtual int ShowContextMenu(ContextMenuClient* client,
+ const ContextMenuParams& params) OVERRIDE;
+ virtual void CancelContextMenu(int request_id) OVERRIDE;
+ virtual blink::WebPlugin* CreatePlugin(
+ blink::WebFrame* frame,
+ const WebPluginInfo& info,
+ const blink::WebPluginParams& params) OVERRIDE;
+ virtual void LoadURLExternally(
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationPolicy policy) OVERRIDE;
+
+ // blink::WebFrameClient implementation -------------------------------------
+ virtual blink::WebPlugin* createPlugin(
+ blink::WebFrame* frame,
+ const blink::WebPluginParams& params);
+ virtual blink::WebMediaPlayer* createMediaPlayer(
+ blink::WebFrame* frame,
+ const blink::WebURL& url,
+ blink::WebMediaPlayerClient* client);
+ virtual blink::WebApplicationCacheHost* createApplicationCacheHost(
+ blink::WebFrame* frame,
+ blink::WebApplicationCacheHostClient* client);
+ virtual blink::WebWorkerPermissionClientProxy*
+ createWorkerPermissionClientProxy(blink::WebFrame* frame);
+ virtual blink::WebCookieJar* cookieJar(blink::WebFrame* frame);
+ virtual blink::WebServiceWorkerProvider* createServiceWorkerProvider(
+ blink::WebFrame* frame,
+ blink::WebServiceWorkerProviderClient*);
+ virtual void didAccessInitialDocument(blink::WebFrame* frame);
+ virtual blink::WebFrame* createChildFrame(blink::WebFrame* parent,
+ const blink::WebString& name);
+ virtual void didDisownOpener(blink::WebFrame* frame);
+ virtual void frameDetached(blink::WebFrame* frame);
+ virtual void willClose(blink::WebFrame* frame);
+ virtual void didChangeName(blink::WebFrame* frame,
+ const blink::WebString& name);
+ virtual void didMatchCSS(
+ blink::WebFrame* frame,
+ const blink::WebVector<blink::WebString>& newly_matching_selectors,
+ const blink::WebVector<blink::WebString>& stopped_matching_selectors);
+ virtual void loadURLExternally(blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationPolicy policy);
virtual void loadURLExternally(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationPolicy policy,
- const WebKit::WebString& suggested_name);
- virtual WebKit::WebNavigationPolicy decidePolicyForNavigation(
- WebKit::WebFrame* frame,
- WebKit::WebDataSource::ExtraData* extra_data,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationType type,
- WebKit::WebNavigationPolicy default_policy,
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationPolicy policy,
+ const blink::WebString& suggested_name);
+ virtual blink::WebNavigationPolicy decidePolicyForNavigation(
+ blink::WebFrame* frame,
+ blink::WebDataSource::ExtraData* extra_data,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationType type,
+ blink::WebNavigationPolicy default_policy,
bool is_redirect);
// DEPRECATED
- virtual WebKit::WebNavigationPolicy decidePolicyForNavigation(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationType type,
- WebKit::WebNavigationPolicy default_policy,
+ virtual blink::WebNavigationPolicy decidePolicyForNavigation(
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationType type,
+ blink::WebNavigationPolicy default_policy,
bool is_redirect);
- virtual void willSendSubmitEvent(WebKit::WebFrame* frame,
- const WebKit::WebFormElement& form);
- virtual void willSubmitForm(WebKit::WebFrame* frame,
- const WebKit::WebFormElement& form);
- virtual void didCreateDataSource(WebKit::WebFrame* frame,
- WebKit::WebDataSource* datasource);
- virtual void didStartProvisionalLoad(WebKit::WebFrame* frame);
+ virtual void willSendSubmitEvent(blink::WebFrame* frame,
+ const blink::WebFormElement& form);
+ virtual void willSubmitForm(blink::WebFrame* frame,
+ const blink::WebFormElement& form);
+ virtual void didCreateDataSource(blink::WebFrame* frame,
+ blink::WebDataSource* datasource);
+ virtual void didStartProvisionalLoad(blink::WebFrame* frame);
virtual void didReceiveServerRedirectForProvisionalLoad(
- WebKit::WebFrame* frame);
+ blink::WebFrame* frame);
virtual void didFailProvisionalLoad(
- WebKit::WebFrame* frame,
- const WebKit::WebURLError& error);
- virtual void didCommitProvisionalLoad(WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
+ const blink::WebURLError& error);
+ virtual void didCommitProvisionalLoad(blink::WebFrame* frame,
bool is_new_navigation);
- virtual void didClearWindowObject(WebKit::WebFrame* frame);
- virtual void didCreateDocumentElement(WebKit::WebFrame* frame);
- virtual void didReceiveTitle(WebKit::WebFrame* frame,
- const WebKit::WebString& title,
- WebKit::WebTextDirection direction);
- virtual void didChangeIcon(WebKit::WebFrame* frame,
- WebKit::WebIconURL::Type icon_type);
- virtual void didFinishDocumentLoad(WebKit::WebFrame* frame);
- virtual void didHandleOnloadEvents(WebKit::WebFrame* frame);
- virtual void didFailLoad(WebKit::WebFrame* frame,
- const WebKit::WebURLError& error);
- virtual void didFinishLoad(WebKit::WebFrame* frame);
- virtual void didNavigateWithinPage(WebKit::WebFrame* frame,
+ virtual void didClearWindowObject(blink::WebFrame* frame);
+ virtual void didCreateDocumentElement(blink::WebFrame* frame);
+ virtual void didReceiveTitle(blink::WebFrame* frame,
+ const blink::WebString& title,
+ blink::WebTextDirection direction);
+ virtual void didChangeIcon(blink::WebFrame* frame,
+ blink::WebIconURL::Type icon_type);
+ virtual void didFinishDocumentLoad(blink::WebFrame* frame);
+ virtual void didHandleOnloadEvents(blink::WebFrame* frame);
+ virtual void didFailLoad(blink::WebFrame* frame,
+ const blink::WebURLError& error);
+ virtual void didFinishLoad(blink::WebFrame* frame);
+ virtual void didNavigateWithinPage(blink::WebFrame* frame,
bool is_new_navigation);
- virtual void didUpdateCurrentHistoryItem(WebKit::WebFrame* frame);
- virtual void willRequestAfterPreconnect(WebKit::WebFrame* frame,
- WebKit::WebURLRequest& request);
+ virtual void didUpdateCurrentHistoryItem(blink::WebFrame* frame);
+ virtual void willRequestAfterPreconnect(blink::WebFrame* frame,
+ blink::WebURLRequest& request);
virtual void willSendRequest(
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
unsigned identifier,
- WebKit::WebURLRequest& request,
- const WebKit::WebURLResponse& redirect_response);
+ blink::WebURLRequest& request,
+ const blink::WebURLResponse& redirect_response);
virtual void didReceiveResponse(
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
unsigned identifier,
- const WebKit::WebURLResponse& response);
- virtual void didFinishResourceLoad(WebKit::WebFrame* frame,
+ const blink::WebURLResponse& response);
+ virtual void didFinishResourceLoad(blink::WebFrame* frame,
unsigned identifier);
virtual void didLoadResourceFromMemoryCache(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- const WebKit::WebURLResponse& response);
- virtual void didDisplayInsecureContent(WebKit::WebFrame* frame);
- virtual void didRunInsecureContent(WebKit::WebFrame* frame,
- const WebKit::WebSecurityOrigin& origin,
- const WebKit::WebURL& target);
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ const blink::WebURLResponse& response);
+ virtual void didDisplayInsecureContent(blink::WebFrame* frame);
+ virtual void didRunInsecureContent(blink::WebFrame* frame,
+ const blink::WebSecurityOrigin& origin,
+ const blink::WebURL& target);
+ virtual void didAbortLoading(blink::WebFrame* frame);
virtual void didExhaustMemoryAvailableForScript(
- WebKit::WebFrame* frame);
- virtual void didCreateScriptContext(WebKit::WebFrame* frame,
+ blink::WebFrame* frame);
+ virtual void didCreateScriptContext(blink::WebFrame* frame,
v8::Handle<v8::Context> context,
int extension_group,
int world_id);
- virtual void willReleaseScriptContext(WebKit::WebFrame* frame,
+ virtual void willReleaseScriptContext(blink::WebFrame* frame,
v8::Handle<v8::Context> context,
int world_id);
- virtual void didFirstVisuallyNonEmptyLayout(WebKit::WebFrame* frame);
- virtual void didChangeContentsSize(WebKit::WebFrame* frame,
- const WebKit::WebSize& size);
- virtual void didChangeScrollOffset(WebKit::WebFrame* frame);
- virtual void willInsertBody(WebKit::WebFrame* frame);
+ virtual void didFirstVisuallyNonEmptyLayout(blink::WebFrame* frame);
+ virtual void didChangeContentsSize(blink::WebFrame* frame,
+ const blink::WebSize& size);
+ virtual void didChangeScrollOffset(blink::WebFrame* frame);
+ virtual void willInsertBody(blink::WebFrame* frame);
virtual void reportFindInPageMatchCount(int request_id,
int count,
bool final_update);
virtual void reportFindInPageSelection(int request_id,
int active_match_ordinal,
- const WebKit::WebRect& sel);
+ const blink::WebRect& sel);
virtual void requestStorageQuota(
- WebKit::WebFrame* frame,
- WebKit::WebStorageQuotaType type,
+ blink::WebFrame* frame,
+ blink::WebStorageQuotaType type,
unsigned long long requested_size,
- WebKit::WebStorageQuotaCallbacks* callbacks);
+ blink::WebStorageQuotaCallbacks* callbacks);
virtual void willOpenSocketStream(
- WebKit::WebSocketStreamHandle* handle);
+ blink::WebSocketStreamHandle* handle);
virtual void willStartUsingPeerConnectionHandler(
- WebKit::WebFrame* frame,
- WebKit::WebRTCPeerConnectionHandler* handler);
+ blink::WebFrame* frame,
+ blink::WebRTCPeerConnectionHandler* handler);
virtual bool willCheckAndDispatchMessageEvent(
- WebKit::WebFrame* sourceFrame,
- WebKit::WebFrame* targetFrame,
- WebKit::WebSecurityOrigin targetOrigin,
- WebKit::WebDOMMessageEvent event);
- virtual WebKit::WebString userAgentOverride(
- WebKit::WebFrame* frame,
- const WebKit::WebURL& url);
- virtual WebKit::WebString doNotTrackValue(WebKit::WebFrame* frame);
- virtual bool allowWebGL(WebKit::WebFrame* frame, bool default_value);
- virtual void didLoseWebGLContext(WebKit::WebFrame* frame,
+ blink::WebFrame* sourceFrame,
+ blink::WebFrame* targetFrame,
+ blink::WebSecurityOrigin targetOrigin,
+ blink::WebDOMMessageEvent event);
+ virtual blink::WebString userAgentOverride(
+ blink::WebFrame* frame,
+ const blink::WebURL& url);
+ virtual blink::WebString doNotTrackValue(blink::WebFrame* frame);
+ virtual bool allowWebGL(blink::WebFrame* frame, bool default_value);
+ virtual void didLoseWebGLContext(blink::WebFrame* frame,
int arb_robustness_status_code);
protected:
RenderFrameImpl(RenderViewImpl* render_view, int32 routing_id);
private:
- int GetRoutingID() const;
+ friend class RenderFrameObserver;
+
+ // Functions to add and remove observers for this object.
+ void AddObserver(RenderFrameObserver* observer);
+ void RemoveObserver(RenderFrameObserver* observer);
RenderViewImpl* render_view_;
int routing_id_;
bool is_swapped_out_;
bool is_detaching_;
+#if defined(ENABLE_PLUGINS)
+ typedef std::set<PepperPluginInstanceImpl*> PepperPluginSet;
+ PepperPluginSet active_pepper_instances_;
+
+ // Current text input composition text. Empty if no composition is in
+ // progress.
+ base::string16 pepper_composition_text_;
+#endif
+
+ // All the registered observers.
+ ObserverList<RenderFrameObserver> observers_;
+
DISALLOW_COPY_AND_ASSIGN(RenderFrameImpl);
};
diff --git a/chromium/content/renderer/render_process_impl.cc b/chromium/content/renderer/render_process_impl.cc
index 20d181b2682..4bce329a065 100644
--- a/chromium/content/renderer/render_process_impl.cc
+++ b/chromium/content/renderer/render_process_impl.cc
@@ -36,6 +36,10 @@
#include "base/mac/mac_util.h"
#endif
+#if defined(OS_ANDROID)
+#include "base/android/sys_utils.h"
+#endif
+
namespace content {
RenderProcessImpl::RenderProcessImpl()
@@ -68,6 +72,11 @@ RenderProcessImpl::RenderProcessImpl()
// Out of process dev tools rely upon auto break behavior.
webkit_glue::SetJavaScriptFlags("--debugger-auto-break");
+#if defined(OS_ANDROID)
+ if (base::android::SysUtils::IsLowEndDevice())
+ webkit_glue::SetJavaScriptFlags("--optimize-for-size");
+#endif
+
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
webkit_glue::SetJavaScriptFlags(
@@ -81,7 +90,7 @@ RenderProcessImpl::RenderProcessImpl()
RenderProcessImpl::~RenderProcessImpl() {
#ifndef NDEBUG
- int count = WebKit::WebFrame::instanceCount();
+ int count = blink::WebFrame::instanceCount();
if (count)
DLOG(ERROR) << "WebFrame LEAKED " << count << " TIMES";
#endif
diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc
index 857c87e4407..e910b8bf80d 100644
--- a/chromium/content/renderer/render_thread_impl.cc
+++ b/chromium/content/renderer/render_thread_impl.cc
@@ -44,7 +44,9 @@
#include "content/common/dom_storage/dom_storage_messages.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/gpu_channel_host.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/gpu_process_launch_causes.h"
#include "content/common/resource_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_constants.h"
@@ -62,8 +64,8 @@
#include "content/renderer/gamepad_shared_memory_reader.h"
#include "content/renderer/gpu/compositor_output_surface.h"
#include "content/renderer/gpu/gpu_benchmarking_extension.h"
-#include "content/renderer/gpu/input_event_filter.h"
-#include "content/renderer/gpu/input_handler_manager.h"
+#include "content/renderer/input/input_event_filter.h"
+#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/media/audio_input_message_filter.h"
#include "content/renderer/media/audio_message_filter.h"
#include "content/renderer/media/audio_renderer_mixer_manager.h"
@@ -79,6 +81,7 @@
#include "content/renderer/render_process_impl.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/renderer_webkitplatformsupport_impl.h"
+#include "content/renderer/service_worker/embedded_worker_dispatcher.h"
#include "content/renderer/skia_benchmarking_extension.h"
#include "grit/content_resources.h"
#include "ipc/ipc_channel_handle.h"
@@ -102,13 +105,11 @@
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebScriptController.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
-#include "third_party/WebKit/public/web/WebSharedWorkerRepository.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/base/layout.h"
#include "ui/base/ui_base_switches.h"
#include "v8/include/v8.h"
#include "webkit/child/worker_task_runner.h"
-#include "webkit/glue/webkit_glue.h"
#include "webkit/renderer/compositor_bindings/web_external_bitmap_impl.h"
#if defined(OS_WIN)
@@ -121,6 +122,10 @@
#include "content/child/npapi/np_channel_base.h"
#endif
+#if defined(OS_MACOSX)
+#include "third_party/WebKit/public/web/mac/WebScrollbarTheme.h"
+#endif
+
#if defined(OS_POSIX)
#include "ipc/ipc_channel_posix.h"
#endif
@@ -136,14 +141,14 @@
#endif
using base::ThreadRestrictions;
-using WebKit::WebDocument;
-using WebKit::WebFrame;
-using WebKit::WebNetworkStateNotifier;
-using WebKit::WebRuntimeFeatures;
-using WebKit::WebScriptController;
-using WebKit::WebSecurityPolicy;
-using WebKit::WebString;
-using WebKit::WebView;
+using blink::WebDocument;
+using blink::WebFrame;
+using blink::WebNetworkStateNotifier;
+using blink::WebRuntimeFeatures;
+using blink::WebScriptController;
+using blink::WebSecurityPolicy;
+using blink::WebString;
+using blink::WebView;
namespace content {
@@ -235,7 +240,7 @@ void EnableWebCoreLogChannels(const std::string& channels) {
return;
base::StringTokenizer t(channels, ", ");
while (t.GetNext())
- WebKit::enableLogChannel(t.token().c_str());
+ blink::enableLogChannel(t.token().c_str());
}
} // namespace
@@ -311,7 +316,7 @@ void RenderThreadImpl::Init() {
#if defined(OS_MACOSX) || defined(OS_ANDROID)
// On Mac and Android, the select popups are rendered by the browser.
- WebKit::WebView::setUseExternalPopupMenus(true);
+ blink::WebView::setUseExternalPopupMenus(true);
#endif
lazy_tls.Pointer()->Set(this);
@@ -341,6 +346,7 @@ void RenderThreadImpl::Init() {
dom_storage_dispatcher_.reset(new DomStorageDispatcher());
main_thread_indexed_db_dispatcher_.reset(new IndexedDBDispatcher(
thread_safe_sender()));
+ embedded_worker_dispatcher_.reset(new EmbeddedWorkerDispatcher());
media_stream_center_ = NULL;
@@ -370,7 +376,7 @@ void RenderThreadImpl::Init() {
midi_message_filter_ = new MIDIMessageFilter(GetIOMessageLoopProxy());
AddFilter(midi_message_filter_.get());
- AddFilter(new IndexedDBMessageFilter(thread_safe_sender()));
+ AddFilter((new IndexedDBMessageFilter(thread_safe_sender()))->GetFilter());
GetContentClient()->renderer()->RenderThreadStarted();
@@ -398,6 +404,12 @@ void RenderThreadImpl::Init() {
memory_pressure_listener_.reset(new base::MemoryPressureListener(
base::Bind(&RenderThreadImpl::OnMemoryPressure, base::Unretained(this))));
+ renderer_process_id_ = base::kNullProcessId;
+
+ // AllocateGpuMemoryBuffer must be used exclusively on one thread but
+ // it doesn't have to be the same thread RenderThreadImpl is created on.
+ allocate_gpu_memory_buffer_thread_checker_.DetachFromThread();
+
TRACE_EVENT_END_ETW("RenderThreadImpl::Init", 0, "");
}
@@ -411,8 +423,10 @@ void RenderThreadImpl::Shutdown() {
ChildThread::Shutdown();
// Wait for all databases to be closed.
- if (web_database_observer_impl_)
- web_database_observer_impl_->WaitForAllDatabasesToClose();
+ if (webkit_platform_support_) {
+ webkit_platform_support_->web_database_observer_impl()->
+ WaitForAllDatabasesToClose();
+ }
// Shutdown in reverse of the initialization order.
if (devtools_agent_message_filter_.get()) {
@@ -452,7 +466,7 @@ void RenderThreadImpl::Shutdown() {
main_thread_indexed_db_dispatcher_.reset();
if (webkit_platform_support_)
- WebKit::shutdown();
+ blink::shutdown();
lazy_tls.Pointer()->Set(NULL);
@@ -464,33 +478,24 @@ void RenderThreadImpl::Shutdown() {
// Leak shared contexts on other threads, as we can not get to the correct
// thread to destroy them.
- if (shared_contexts_compositor_thread_.get())
- shared_contexts_compositor_thread_->set_leak_on_destroy();
+ if (offscreen_compositor_contexts_.get())
+ offscreen_compositor_contexts_->set_leak_on_destroy();
}
bool RenderThreadImpl::Send(IPC::Message* msg) {
// Certain synchronous messages cannot always be processed synchronously by
- // the browser, e.g., Chrome frame communicating with the embedding browser.
- // This could cause a complete hang of Chrome if a windowed plug-in is trying
- // to communicate with the renderer thread since the browser's UI thread
- // could be stuck (within a Windows API call) trying to synchronously
- // communicate with the plug-in. The remedy is to pump messages on this
- // thread while the browser is processing this request. This creates an
- // opportunity for re-entrancy into WebKit, so we need to take care to disable
- // callbacks, timers, and pending network loads that could trigger such
- // callbacks.
+ // the browser, e.g., putting up UI and waiting for the user. This could cause
+ // a complete hang of Chrome if a windowed plug-in is trying to communicate
+ // with the renderer thread since the browser's UI thread could be stuck
+ // (within a Windows API call) trying to synchronously communicate with the
+ // plug-in. The remedy is to pump messages on this thread while the browser
+ // is processing this request. This creates an opportunity for re-entrancy
+ // into WebKit, so we need to take care to disable callbacks, timers, and
+ // pending network loads that could trigger such callbacks.
bool pumping_events = false;
if (msg->is_sync()) {
if (msg->is_caller_pumping_messages()) {
pumping_events = true;
- } else {
- if ((msg->type() == ViewHostMsg_GetCookies::ID ||
- msg->type() == ViewHostMsg_GetRawCookies::ID ||
- msg->type() == ViewHostMsg_CookiesEnabled::ID) &&
- GetContentClient()->renderer()->
- ShouldPumpEventsDuringCookieMessage()) {
- pumping_events = true;
- }
}
}
@@ -592,10 +597,6 @@ void RenderThreadImpl::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) {
channel()->RemoveFilter(filter);
}
-void RenderThreadImpl::SetOutgoingMessageFilter(
- IPC::ChannelProxy::OutgoingMessageFilter* filter) {
-}
-
void RenderThreadImpl::AddObserver(RenderProcessObserver* observer) {
observers_.AddObserver(observer);
}
@@ -641,9 +642,7 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
return;
webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl);
- WebKit::initialize(webkit_platform_support_.get());
- WebKit::setSharedWorkerRepository(
- webkit_platform_support_.get()->sharedWorkerRepository());
+ blink::initialize(webkit_platform_support_.get());
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
@@ -657,18 +656,7 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
#endif
if (!compositor_message_loop_proxy_.get()) {
compositor_thread_.reset(new base::Thread("Compositor"));
-#if defined(OS_POSIX)
- // Workaround for crbug.com/293736
- // On Posix, MessagePumpDefault uses system time, so delayed tasks (for
- // compositor scheduling) work incorrectly across system time changes
- // (e.g. tlsdate). So instead, use an IO loop, which uses libevent, that
- // uses monotonic time (immune to these problems).
- base::Thread::Options options;
- options.message_loop_type = base::MessageLoop::TYPE_IO;
- compositor_thread_->StartWithOptions(options);
-#else
compositor_thread_->Start();
-#endif
#if defined(OS_ANDROID)
compositor_thread_->SetPriority(base::kThreadPriority_Display);
#endif
@@ -715,10 +703,6 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
EnableWebCoreLogChannels(
command_line.GetSwitchValueASCII(switches::kWebCoreLogChannels));
- web_database_observer_impl_.reset(
- new WebDatabaseObserverImpl(sync_message_filter()));
- WebKit::WebDatabase::setObserver(web_database_observer_impl_.get());
-
SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line);
if (!media::IsMediaLibraryInitialized()) {
@@ -745,7 +729,11 @@ void RenderThreadImpl::RegisterSchemes() {
WebSecurityPolicy::registerURLSchemeAsEmptyDocument(swappedout_scheme);
}
-void RenderThreadImpl::RecordUserMetrics(const std::string& action) {
+void RenderThreadImpl::RecordAction(const UserMetricsAction& action) {
+ Send(new ViewHostMsg_UserMetricsRecordAction(action.str_));
+}
+
+void RenderThreadImpl::RecordComputedAction(const std::string& action) {
Send(new ViewHostMsg_UserMetricsRecordAction(action));
}
@@ -883,88 +871,106 @@ void RenderThreadImpl::PostponeIdleNotification() {
}
scoped_refptr<RendererGpuVideoAcceleratorFactories>
-RenderThreadImpl::GetGpuFactories(
- const scoped_refptr<base::MessageLoopProxy>& factories_loop) {
+RenderThreadImpl::GetGpuFactories() {
DCHECK(IsMainThread());
+ scoped_refptr<GpuChannelHost> gpu_channel_host = GetGpuChannel();
const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories;
if (!cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
if (!gpu_va_context_provider_ ||
gpu_va_context_provider_->DestroyedOnMainThread()) {
+ if (!gpu_channel_host) {
+ gpu_channel_host = EstablishGpuChannelSync(
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE);
+ }
gpu_va_context_provider_ = ContextProviderCommandBuffer::Create(
make_scoped_ptr(
WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- this,
- WebKit::WebGraphicsContext3D::Attributes(),
- GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"))),
+ gpu_channel_host.get(),
+ blink::WebGraphicsContext3D::Attributes(),
+ GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"),
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits())),
"GPU-VideoAccelerator-Offscreen");
}
}
- GpuChannelHost* gpu_channel_host = GetGpuChannel();
if (gpu_channel_host) {
gpu_factories = new RendererGpuVideoAcceleratorFactories(
- gpu_channel_host, factories_loop, gpu_va_context_provider_);
+ gpu_channel_host.get(), gpu_va_context_provider_);
}
return gpu_factories;
}
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
RenderThreadImpl::CreateOffscreenContext3d() {
- WebKit::WebGraphicsContext3D::Attributes attributes;
+ blink::WebGraphicsContext3D::Attributes attributes;
attributes.shareResources = true;
attributes.depth = false;
attributes.stencil = false;
attributes.antialias = false;
attributes.noAutomaticFlushes = true;
+ scoped_refptr<GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync(
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
return make_scoped_ptr(
WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- this,
+ gpu_channel_host.get(),
attributes,
- GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d")));
+ GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d"),
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits()));
}
scoped_refptr<cc::ContextProvider>
-RenderThreadImpl::OffscreenContextProviderForMainThread() {
+RenderThreadImpl::OffscreenCompositorContextProvider() {
DCHECK(IsMainThread());
#if defined(OS_ANDROID)
if (SynchronousCompositorFactory* factory =
SynchronousCompositorFactory::GetInstance()) {
+ if (compositor_message_loop_proxy_)
+ return factory->GetOffscreenContextProviderForCompositorThread();
return factory->GetOffscreenContextProviderForMainThread();
}
#endif
- if (!shared_contexts_main_thread_.get() ||
- shared_contexts_main_thread_->DestroyedOnMainThread()) {
- shared_contexts_main_thread_ = ContextProviderCommandBuffer::Create(
+ if (!offscreen_compositor_contexts_.get() ||
+ offscreen_compositor_contexts_->DestroyedOnMainThread()) {
+ offscreen_compositor_contexts_ = ContextProviderCommandBuffer::Create(
CreateOffscreenContext3d(),
- "Compositor-Offscreen-MainThread");
- if (shared_contexts_main_thread_.get() &&
- !shared_contexts_main_thread_->BindToCurrentThread())
- shared_contexts_main_thread_ = NULL;
+ "Compositor-Offscreen");
}
- return shared_contexts_main_thread_;
+ return offscreen_compositor_contexts_;
}
scoped_refptr<cc::ContextProvider>
-RenderThreadImpl::OffscreenContextProviderForCompositorThread() {
+RenderThreadImpl::SharedMainThreadContextProvider() {
DCHECK(IsMainThread());
-
#if defined(OS_ANDROID)
if (SynchronousCompositorFactory* factory =
- SynchronousCompositorFactory::GetInstance()) {
- return factory->GetOffscreenContextProviderForCompositorThread();
- }
+ SynchronousCompositorFactory::GetInstance())
+ return factory->GetOffscreenContextProviderForMainThread();
#endif
- if (!shared_contexts_compositor_thread_.get() ||
- shared_contexts_compositor_thread_->DestroyedOnMainThread()) {
- shared_contexts_compositor_thread_ = ContextProviderCommandBuffer::Create(
- CreateOffscreenContext3d(), "Compositor-Offscreen");
+ if (!shared_main_thread_contexts_ ||
+ shared_main_thread_contexts_->DestroyedOnMainThread()) {
+ if (compositor_message_loop_proxy_) {
+ // In threaded compositing mode, we have to create a new ContextProvider
+ // to bind to the main thread since the compositor's is bound to the
+ // compositor thread.
+ shared_main_thread_contexts_ =
+ ContextProviderCommandBuffer::Create(CreateOffscreenContext3d(),
+ "Offscreen-MainThread");
+ } else {
+ // In single threaded mode, we can use the same context provider.
+ shared_main_thread_contexts_ =
+ static_cast<ContextProviderCommandBuffer*>(
+ OffscreenCompositorContextProvider().get());
+ }
}
- return shared_contexts_compositor_thread_;
+ if (shared_main_thread_contexts_ &&
+ !shared_main_thread_contexts_->BindToCurrentThread())
+ shared_main_thread_contexts_ = NULL;
+ return shared_main_thread_contexts_;
}
AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() {
@@ -993,7 +999,7 @@ media::AudioHardwareConfig* RenderThreadImpl::GetAudioHardwareConfig() {
#if defined(OS_WIN)
void RenderThreadImpl::PreCacheFontCharacters(const LOGFONT& log_font,
- const string16& str) {
+ const base::string16& str) {
Send(new ViewHostMsg_PreCacheFontCharacters(log_font, str));
}
@@ -1059,6 +1065,38 @@ void RenderThreadImpl::DeleteImage(int32 image_id, int32 sync_point) {
NOTREACHED();
}
+scoped_ptr<gfx::GpuMemoryBuffer> RenderThreadImpl::AllocateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat) {
+ DCHECK(allocate_gpu_memory_buffer_thread_checker_.CalledOnValidThread());
+
+ if (!GpuMemoryBufferImpl::IsFormatValid(internalformat))
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ gfx::GpuMemoryBufferHandle handle;
+ bool success;
+ IPC::Message* message =
+ new ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer(width,
+ height,
+ internalformat,
+ &handle);
+
+ // Allow calling this from the compositor thread.
+ if (base::MessageLoop::current() == message_loop())
+ success = ChildThread::Send(message);
+ else
+ success = sync_message_filter()->Send(message);
+
+ if (!success)
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ return GpuMemoryBufferImpl::Create(
+ handle,
+ gfx::Size(width, height),
+ internalformat).PassAs<gfx::GpuMemoryBuffer>();
+}
+
void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() {
suspend_webkit_shared_timer_ = false;
}
@@ -1084,7 +1122,8 @@ bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
// Some messages are handled by delegates.
if (appcache_dispatcher_->OnMessageReceived(msg) ||
- dom_storage_dispatcher_->OnMessageReceived(msg)) {
+ dom_storage_dispatcher_->OnMessageReceived(msg) ||
+ embedded_worker_dispatcher_->OnMessageReceived(msg)) {
return true;
}
@@ -1098,8 +1137,14 @@ bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache)
IPC_MESSAGE_HANDLER(ViewMsg_NetworkStateChanged, OnNetworkStateChanged)
IPC_MESSAGE_HANDLER(ViewMsg_TempCrashWithData, OnTempCrashWithData)
+ IPC_MESSAGE_HANDLER(ViewMsg_SetRendererProcessID, OnSetRendererProcessID)
+#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(ViewMsg_SetWebKitSharedTimersSuspended,
OnSetWebKitSharedTimersSuspended)
+#endif
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(ViewMsg_UpdateScrollbarTheme, OnUpdateScrollbarTheme)
+#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -1164,12 +1209,12 @@ GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync(
shutdown_event_ = ChildProcess::current()->GetShutDownEvent();
gpu_channel_ = GpuChannelHost::Create(
- this, 0, client_id, gpu_info, channel_handle);
+ this, 0, gpu_info, channel_handle);
return gpu_channel_.get();
}
-WebKit::WebMediaStreamCenter* RenderThreadImpl::CreateMediaStreamCenter(
- WebKit::WebMediaStreamCenterClient* client) {
+blink::WebMediaStreamCenter* RenderThreadImpl::CreateMediaStreamCenter(
+ blink::WebMediaStreamCenterClient* client) {
#if defined(OS_ANDROID)
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableWebRTC))
@@ -1219,7 +1264,7 @@ void RenderThreadImpl::OnPurgePluginListCache(bool reload_pages) {
// refresh temporarily to prevent each renderer process causing the list to be
// regenerated.
webkit_platform_support_->set_plugin_refresh_allowed(false);
- WebKit::resetPluginCache(reload_pages);
+ blink::resetPluginCache(reload_pages);
webkit_platform_support_->set_plugin_refresh_allowed(true);
FOR_EACH_OBSERVER(RenderProcessObserver, observers_, PluginListChanged());
@@ -1235,9 +1280,27 @@ void RenderThreadImpl::OnTempCrashWithData(const GURL& data) {
CHECK(false);
}
+void RenderThreadImpl::OnSetRendererProcessID(base::ProcessId process_id) {
+ renderer_process_id_ = process_id;
+}
+
+#if defined(OS_ANDROID)
void RenderThreadImpl::OnSetWebKitSharedTimersSuspended(bool suspend) {
ToggleWebKitSharedTimer(suspend);
}
+#endif
+
+#if defined(OS_MACOSX)
+void RenderThreadImpl::OnUpdateScrollbarTheme(float initial_button_delay,
+ float autoscroll_button_delay,
+ bool jump_on_track_click,
+ bool redraw) {
+ blink::WebScrollbarTheme::updateScrollbars(initial_button_delay,
+ autoscroll_button_delay,
+ jump_on_track_click,
+ redraw);
+}
+#endif
void RenderThreadImpl::OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
@@ -1248,7 +1311,7 @@ void RenderThreadImpl::OnMemoryPressure(
// Trigger full v8 garbage collection on critical memory notification.
v8::V8::LowMemoryNotification();
// Clear the image cache.
- WebKit::WebImageCache::clear();
+ blink::WebImageCache::clear();
// Purge Skia font cache, by setting it to 0 and then again to the previous
// limit.
size_t font_cache_limit = SkGraphics::SetFontCacheLimit(0);
@@ -1275,18 +1338,7 @@ RenderThreadImpl::GetMediaThreadMessageLoopProxy() {
DCHECK(message_loop() == base::MessageLoop::current());
if (!media_thread_) {
media_thread_.reset(new base::Thread("Media"));
-#if defined(OS_POSIX)
- // Workaround for crbug.com/293736
- // On Posix, MessagePumpDefault uses system time, so delayed tasks (for
- // compositor scheduling) work incorrectly across system time changes
- // (e.g. tlsdate). So instead, use an IO loop, which uses libevent, that
- // uses monotonic time (immune to these problems).
- base::Thread::Options options;
- options.message_loop_type = base::MessageLoop::TYPE_IO;
- media_thread_->StartWithOptions(options);
-#else
media_thread_->Start();
-#endif
#if defined(OS_ANDROID)
renderer_demuxer_ = new RendererDemuxerAndroid();
@@ -1304,10 +1356,14 @@ void RenderThreadImpl::SetFlingCurveParameters(
}
-void RenderThreadImpl::SampleGamepads(WebKit::WebGamepads* data) {
+void RenderThreadImpl::SampleGamepads(blink::WebGamepads* data) {
if (!gamepad_shared_memory_reader_)
gamepad_shared_memory_reader_.reset(new GamepadSharedMemoryReader);
gamepad_shared_memory_reader_->SampleGamepads(*data);
}
+base::ProcessId RenderThreadImpl::renderer_process_id() const {
+ return renderer_process_id_;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_thread_impl.h b/chromium/content/renderer/render_thread_impl.h
index ad4f888422c..5dffc8d8b5c 100644
--- a/chromium/content/renderer/render_thread_impl.h
+++ b/chromium/content/renderer/render_thread_impl.h
@@ -11,13 +11,14 @@
#include "base/memory/memory_pressure_listener.h"
#include "base/observer_list.h"
+#include "base/process/process_handle.h"
#include "base/strings/string16.h"
+#include "base/threading/thread_checker.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "content/child/child_thread.h"
#include "content/common/content_export.h"
#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
#include "ipc/ipc_channel_proxy.h"
@@ -27,7 +28,7 @@ class GrContext;
class SkBitmap;
struct ViewMsg_New_Params;
-namespace WebKit {
+namespace blink {
class WebGamepads;
class WebGraphicsContext3D;
class WebMediaStreamCenter;
@@ -77,6 +78,7 @@ class ContextProviderCommandBuffer;
class DBMessageFilter;
class DevToolsAgentFilter;
class DomStorageDispatcher;
+class EmbeddedWorkerDispatcher;
class GamepadSharedMemoryReader;
class GpuChannelHost;
class IndexedDBDispatcher;
@@ -91,7 +93,6 @@ class RendererDemuxerAndroid;
class RendererWebKitPlatformSupportImpl;
class RenderProcessObserver;
class VideoCaptureImplManager;
-class WebDatabaseObserverImpl;
class WebGraphicsContext3DCommandBufferImpl;
class WebRTCIdentityService;
@@ -133,8 +134,6 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
virtual int GenerateRoutingID() OVERRIDE;
virtual void AddFilter(IPC::ChannelProxy::MessageFilter* filter) OVERRIDE;
virtual void RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) OVERRIDE;
- virtual void SetOutgoingMessageFilter(
- IPC::ChannelProxy::OutgoingMessageFilter* filter) OVERRIDE;
virtual void AddObserver(RenderProcessObserver* observer) OVERRIDE;
virtual void RemoveObserver(RenderProcessObserver* observer) OVERRIDE;
virtual void SetResourceDispatcherDelegate(
@@ -142,7 +141,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
virtual void WidgetHidden() OVERRIDE;
virtual void WidgetRestored() OVERRIDE;
virtual void EnsureWebKitInitialized() OVERRIDE;
- virtual void RecordUserMetrics(const std::string& action) OVERRIDE;
+ virtual void RecordAction(const UserMetricsAction& action) OVERRIDE;
+ virtual void RecordComputedAction(const std::string& action) OVERRIDE;
virtual scoped_ptr<base::SharedMemory> HostAllocateSharedMemoryBuffer(
size_t buffer_size) OVERRIDE;
virtual void RegisterExtension(v8::Extension* extension) OVERRIDE;
@@ -164,7 +164,7 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
// 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.
- virtual GpuChannelHost* EstablishGpuChannelSync(CauseForGpuLaunch) OVERRIDE;
+ GpuChannelHost* EstablishGpuChannelSync(CauseForGpuLaunch);
// These methods modify how the next message is sent. Normally, when sending
@@ -206,6 +206,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
return dom_storage_dispatcher_.get();
}
+ EmbeddedWorkerDispatcher* embedded_worker_dispatcher() const {
+ return embedded_worker_dispatcher_.get();
+ }
+
AudioInputMessageFilter* audio_input_message_filter() {
return audio_input_message_filter_.get();
}
@@ -226,8 +230,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
// Creates the embedder implementation of WebMediaStreamCenter.
// The resulting object is owned by WebKit and deleted by WebKit at tear-down.
- WebKit::WebMediaStreamCenter* CreateMediaStreamCenter(
- WebKit::WebMediaStreamCenterClient* client);
+ blink::WebMediaStreamCenter* CreateMediaStreamCenter(
+ blink::WebMediaStreamCenterClient* client);
// Returns a factory used for creating RTC PeerConnection objects.
MediaStreamDependencyFactory* GetMediaStreamDependencyFactory();
@@ -264,14 +268,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
// not sent for at least one notification delay.
void PostponeIdleNotification();
- // Gets gpu factories, which will run on |factories_loop|.
- scoped_refptr<RendererGpuVideoAcceleratorFactories> GetGpuFactories(
- const scoped_refptr<base::MessageLoopProxy>& factories_loop);
+ scoped_refptr<RendererGpuVideoAcceleratorFactories> GetGpuFactories();
- scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForMainThread();
- scoped_refptr<cc::ContextProvider>
- OffscreenContextProviderForCompositorThread();
+ scoped_refptr<cc::ContextProvider> OffscreenCompositorContextProvider();
+ scoped_refptr<cc::ContextProvider> SharedMainThreadContextProvider();
// AudioRendererMixerManager instance which manages renderer side mixer
// instances shared based on configured audio parameters. Lazily created on
@@ -284,7 +284,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
media::AudioHardwareConfig* GetAudioHardwareConfig();
#if defined(OS_WIN)
- void PreCacheFontCharacters(const LOGFONT& log_font, const string16& str);
+ void PreCacheFontCharacters(const LOGFONT& log_font,
+ const base::string16& str);
#endif
#if defined(ENABLE_WEBRTC)
@@ -343,7 +344,12 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
const std::vector<float>& new_touchscreen);
// Retrieve current gamepad data.
- void SampleGamepads(WebKit::WebGamepads* data);
+ void SampleGamepads(blink::WebGamepads* data);
+
+ // Get the browser process's notion of the renderer process's ID.
+ // This is the first argument to RenderWidgetHost::FromID. Ideally
+ // this would be available on all platforms via base::Process.
+ base::ProcessId renderer_process_id() const;
private:
// ChildThread
@@ -364,6 +370,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
int32 image_id,
const CreateImageCallback& callback) OVERRIDE;
virtual void DeleteImage(int32 image_id, int32 sync_point) OVERRIDE;
+ virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
+ size_t width,
+ size_t height,
+ unsigned internalformat) OVERRIDE;
void Init();
@@ -376,9 +386,18 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
void OnNetworkStateChanged(bool online);
void OnGetAccessibilityTree();
void OnTempCrashWithData(const GURL& data);
- void OnSetWebKitSharedTimersSuspended(bool suspend);
+ void OnSetRendererProcessID(base::ProcessId process_id);
void OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
+#if defined(OS_ANDROID)
+ void OnSetWebKitSharedTimersSuspended(bool suspend);
+#endif
+#if defined(OS_MACOSX)
+ void OnUpdateScrollbarTheme(float initial_button_delay,
+ float autoscroll_button_delay,
+ bool jump_on_track_click,
+ bool redraw);
+#endif
void IdleHandlerInForegroundTab();
@@ -389,9 +408,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
scoped_ptr<DomStorageDispatcher> dom_storage_dispatcher_;
scoped_ptr<IndexedDBDispatcher> main_thread_indexed_db_dispatcher_;
scoped_ptr<RendererWebKitPlatformSupportImpl> webkit_platform_support_;
+ scoped_ptr<EmbeddedWorkerDispatcher> embedded_worker_dispatcher_;
// Used on the render thread and deleted by WebKit at shutdown.
- WebKit::WebMediaStreamCenter* media_stream_center_;
+ blink::WebMediaStreamCenter* media_stream_center_;
// Used on the renderer and IPC threads.
scoped_refptr<DBMessageFilter> db_message_filter_;
@@ -415,9 +435,6 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
// Used on multiple threads.
scoped_refptr<VideoCaptureImplManager> vc_manager_;
- // Used on multiple script execution context threads.
- scoped_ptr<WebDatabaseObserverImpl> web_database_observer_impl_;
-
#if defined(OS_WIN)
// Initialize COM when using plugins outside the sandbox.
scoped_ptr<base::win::ScopedCOMInitializer> initialize_com_;
@@ -470,9 +487,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
scoped_ptr<InputHandlerManager> input_handler_manager_;
scoped_refptr<IPC::ForwardingMessageFilter> compositor_output_surface_filter_;
- scoped_refptr<ContextProviderCommandBuffer> shared_contexts_main_thread_;
- scoped_refptr<ContextProviderCommandBuffer>
- shared_contexts_compositor_thread_;
+ scoped_refptr<ContextProviderCommandBuffer> offscreen_compositor_contexts_;
+ scoped_refptr<ContextProviderCommandBuffer> shared_main_thread_contexts_;
ObserverList<RenderProcessObserver> observers_;
@@ -489,6 +505,13 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
scoped_ptr<GamepadSharedMemoryReader> gamepad_shared_memory_reader_;
+ base::ProcessId renderer_process_id_;
+
+ // TODO(reveman): Allow AllocateGpuMemoryBuffer to be called from
+ // multiple threads. Current allocation mechanism for IOSurface
+ // backed GpuMemoryBuffers prevent this. crbug.com/325045
+ base::ThreadChecker allocate_gpu_memory_buffer_thread_checker_;
+
DISALLOW_COPY_AND_ASSIGN(RenderThreadImpl);
};
diff --git a/chromium/content/renderer/render_view_browsertest.cc b/chromium/content/renderer/render_view_browsertest.cc
index a66e041ce9d..d378ab6a24a 100644
--- a/chromium/content/renderer/render_view_browsertest.cc
+++ b/chromium/content/renderer/render_view_browsertest.cc
@@ -7,6 +7,7 @@
#include "base/memory/shared_memory.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/win/windows_version.h"
#include "content/common/ssl_status_serialization.h"
#include "content/common/view_messages.h"
#include "content/public/browser/native_web_keyboard_event.h"
@@ -51,24 +52,28 @@
#if defined(USE_AURA) && defined(USE_X11)
#include <X11/Xlib.h>
-#include "ui/base/x/x11_util.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/test/events_test_utils_x11.h"
#endif
-using WebKit::WebFrame;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebRuntimeFeatures;
-using WebKit::WebString;
-using WebKit::WebTextDirection;
-using WebKit::WebURLError;
+#if defined(USE_OZONE)
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#endif
+
+using blink::WebFrame;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebRuntimeFeatures;
+using blink::WebString;
+using blink::WebTextDirection;
+using blink::WebURLError;
namespace content {
namespace {
-#if defined(USE_AURA) && defined(USE_X11)
+#if (defined(USE_AURA) && defined(USE_X11)) || defined(USE_OZONE)
// Converts MockKeyboard::Modifiers to ui::EventFlags.
int ConvertMockKeyboardModifier(MockKeyboard::Modifiers modifiers) {
static struct ModifierMap {
@@ -125,11 +130,10 @@ class RenderViewImplTest : public RenderViewTest {
virtual void SetUp() OVERRIDE {
RenderViewTest::SetUp();
- // This test depends on Blink flag InputModeAttribute, which is enabled
- // under only test. Content browser test doesn't enable the feature so we
- // need enable it manually.
- // TODO(yoichio): Remove this if InputMode feature is enabled by default.
- WebRuntimeFeatures::enableInputModeAttribute(true);
+ // Enable Blink's experimental and test only features so that test code
+ // does not have to bother enabling each feature.
+ WebRuntimeFeatures::enableExperimentalFeatures(true);
+ WebRuntimeFeatures::enableTestOnlyFeatures(true);
}
RenderViewImpl* view() {
@@ -140,7 +144,7 @@ class RenderViewImplTest : public RenderViewTest {
int SendKeyEvent(MockKeyboard::Layout layout,
int key_code,
MockKeyboard::Modifiers modifiers,
- string16* output) {
+ base::string16* output) {
#if defined(OS_WIN)
// Retrieve the Unicode character for the given tuple (keyboard-layout,
// key-code, and modifiers).
@@ -194,30 +198,25 @@ class RenderViewImplTest : public RenderViewTest {
CHECK(output);
const int flags = ConvertMockKeyboardModifier(modifiers);
- XEvent xevent1;
- InitXKeyEventForTesting(ui::ET_KEY_PRESSED,
- static_cast<ui::KeyboardCode>(key_code),
- flags,
- &xevent1);
- ui::KeyEvent event1(&xevent1, false);
+ ui::ScopedXI2Event xevent;
+ xevent.InitKeyEvent(ui::ET_KEY_PRESSED,
+ static_cast<ui::KeyboardCode>(key_code),
+ flags);
+ ui::KeyEvent event1(xevent, false);
NativeWebKeyboardEvent keydown_event(&event1);
SendNativeKeyEvent(keydown_event);
- XEvent xevent2;
- InitXKeyEventForTesting(ui::ET_KEY_PRESSED,
- static_cast<ui::KeyboardCode>(key_code),
- flags,
- &xevent2);
- ui::KeyEvent event2(&xevent2, true);
+ xevent.InitKeyEvent(ui::ET_KEY_PRESSED,
+ static_cast<ui::KeyboardCode>(key_code),
+ flags);
+ ui::KeyEvent event2(xevent, true);
NativeWebKeyboardEvent char_event(&event2);
SendNativeKeyEvent(char_event);
- XEvent xevent3;
- InitXKeyEventForTesting(ui::ET_KEY_RELEASED,
- static_cast<ui::KeyboardCode>(key_code),
- flags,
- &xevent3);
- ui::KeyEvent event3(&xevent3, false);
+ xevent.InitKeyEvent(ui::ET_KEY_RELEASED,
+ static_cast<ui::KeyboardCode>(key_code),
+ flags);
+ ui::KeyEvent event3(xevent, false);
NativeWebKeyboardEvent keyup_event(&event3);
SendNativeKeyEvent(keyup_event);
@@ -225,6 +224,39 @@ class RenderViewImplTest : public RenderViewTest {
flags);
output->assign(1, static_cast<char16>(c));
return 1;
+#elif defined(USE_OZONE)
+ const int flags = ConvertMockKeyboardModifier(modifiers);
+
+ // Ozone's native events are ui::Events. So first create the "native" event,
+ // then create the actual ui::KeyEvent with the native event.
+ ui::KeyEvent keydown_native_event(ui::ET_KEY_PRESSED,
+ static_cast<ui::KeyboardCode>(key_code),
+ flags,
+ true);
+ ui::KeyEvent keydown_event(&keydown_native_event, false);
+ NativeWebKeyboardEvent keydown_web_event(&keydown_event);
+ SendNativeKeyEvent(keydown_web_event);
+
+ ui::KeyEvent char_native_event(ui::ET_KEY_PRESSED,
+ static_cast<ui::KeyboardCode>(key_code),
+ flags,
+ true);
+ ui::KeyEvent char_event(&char_native_event, true);
+ NativeWebKeyboardEvent char_web_event(&char_event);
+ SendNativeKeyEvent(char_web_event);
+
+ ui::KeyEvent keyup_native_event(ui::ET_KEY_RELEASED,
+ static_cast<ui::KeyboardCode>(key_code),
+ flags,
+ true);
+ ui::KeyEvent keyup_event(&keyup_native_event, false);
+ NativeWebKeyboardEvent keyup_web_event(&keyup_event);
+ SendNativeKeyEvent(keyup_web_event);
+
+ long c = GetCharacterFromKeyCode(static_cast<ui::KeyboardCode>(key_code),
+ flags);
+ output->assign(1, static_cast<char16>(c));
+ return 1;
#elif defined(TOOLKIT_GTK)
// We ignore |layout|, which means we are only testing the layout of the
// current locale. TODO(estade): fix this to respect |layout|.
@@ -246,9 +278,9 @@ class RenderViewImplTest : public RenderViewTest {
SendNativeKeyEvent(webkit_event);
// Need to add a char event after the key down.
- if (webkit_event.type == WebKit::WebInputEvent::RawKeyDown) {
+ if (webkit_event.type == blink::WebInputEvent::RawKeyDown) {
NativeWebKeyboardEvent char_event = webkit_event;
- char_event.type = WebKit::WebInputEvent::Char;
+ char_event.type = blink::WebInputEvent::Char;
char_event.skip_in_browser = true;
SendNativeKeyEvent(char_event);
}
@@ -321,13 +353,13 @@ TEST_F(RenderViewImplTest, OnNavigationHttpPost) {
// Check post data sent to browser matches
EXPECT_TRUE(host_nav_params.a.page_state.IsValid());
- const WebKit::WebHistoryItem item = PageStateToHistoryItem(
+ const blink::WebHistoryItem item = PageStateToHistoryItem(
host_nav_params.a.page_state);
- WebKit::WebHTTPBody body = item.httpBody();
- WebKit::WebHTTPBody::Element element;
+ blink::WebHTTPBody body = item.httpBody();
+ blink::WebHTTPBody::Element element;
bool successful = body.elementAt(0, element);
EXPECT_TRUE(successful);
- EXPECT_EQ(WebKit::WebHTTPBody::Element::TypeData, element.type);
+ EXPECT_EQ(blink::WebHTTPBody::Element::TypeData, element.type);
EXPECT_EQ(length, element.data.size());
EXPECT_EQ(0, memcmp(raw_data, element.data.data(), length));
}
@@ -340,38 +372,68 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicy) {
state.set_navigation_state(NavigationState::CreateContentInitiated());
// Navigations to normal HTTP URLs can be handled locally.
- WebKit::WebURLRequest request(GURL("http://foo.com"));
- WebKit::WebNavigationPolicy policy = view()->decidePolicyForNavigation(
+ blink::WebURLRequest request(GURL("http://foo.com"));
+ blink::WebNavigationPolicy policy = view()->decidePolicyForNavigation(
GetMainFrame(),
&state,
request,
- WebKit::WebNavigationTypeLinkClicked,
- WebKit::WebNavigationPolicyCurrentTab,
+ blink::WebNavigationTypeLinkClicked,
+ blink::WebNavigationPolicyCurrentTab,
false);
- EXPECT_EQ(WebKit::WebNavigationPolicyCurrentTab, policy);
+ EXPECT_EQ(blink::WebNavigationPolicyCurrentTab, policy);
// Verify that form posts to WebUI URLs will be sent to the browser process.
- WebKit::WebURLRequest form_request(GURL("chrome://foo"));
+ blink::WebURLRequest form_request(GURL("chrome://foo"));
form_request.setHTTPMethod("POST");
policy = view()->decidePolicyForNavigation(
GetMainFrame(),
&state,
form_request,
- WebKit::WebNavigationTypeFormSubmitted,
- WebKit::WebNavigationPolicyCurrentTab,
+ blink::WebNavigationTypeFormSubmitted,
+ blink::WebNavigationPolicyCurrentTab,
false);
- EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
+ EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
// Verify that popup links to WebUI URLs also are sent to browser.
- WebKit::WebURLRequest popup_request(GURL("chrome://foo"));
+ blink::WebURLRequest popup_request(GURL("chrome://foo"));
policy = view()->decidePolicyForNavigation(
GetMainFrame(),
&state,
popup_request,
- WebKit::WebNavigationTypeLinkClicked,
- WebKit::WebNavigationPolicyNewForegroundTab,
+ blink::WebNavigationTypeLinkClicked,
+ blink::WebNavigationPolicyNewForegroundTab,
false);
- EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
+ EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
+}
+
+TEST_F(RenderViewImplTest, DecideNavigationPolicyHandlesAllTopLevel) {
+ DocumentState state;
+ state.set_navigation_state(NavigationState::CreateContentInitiated());
+
+ RendererPreferences prefs = view()->renderer_preferences();
+ prefs.browser_handles_all_top_level_requests = true;
+ view()->OnSetRendererPrefs(prefs);
+
+ const blink::WebNavigationType kNavTypes[] = {
+ blink::WebNavigationTypeLinkClicked,
+ blink::WebNavigationTypeFormSubmitted,
+ blink::WebNavigationTypeBackForward,
+ blink::WebNavigationTypeReload,
+ blink::WebNavigationTypeFormResubmitted,
+ blink::WebNavigationTypeOther,
+ };
+
+ blink::WebURLRequest request(GURL("http://foo.com"));
+ for (size_t i = 0; i < arraysize(kNavTypes); ++i) {
+ blink::WebNavigationPolicy policy = view()->decidePolicyForNavigation(
+ GetMainFrame(),
+ &state,
+ request,
+ kNavTypes[i],
+ blink::WebNavigationPolicyCurrentTab,
+ false);
+ EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
+ }
}
TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) {
@@ -382,55 +444,55 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) {
state.set_navigation_state(NavigationState::CreateContentInitiated());
// Navigations to normal HTTP URLs will be sent to browser process.
- WebKit::WebURLRequest request(GURL("http://foo.com"));
- WebKit::WebNavigationPolicy policy = view()->decidePolicyForNavigation(
+ blink::WebURLRequest request(GURL("http://foo.com"));
+ blink::WebNavigationPolicy policy = view()->decidePolicyForNavigation(
GetMainFrame(),
&state,
request,
- WebKit::WebNavigationTypeLinkClicked,
- WebKit::WebNavigationPolicyCurrentTab,
+ blink::WebNavigationTypeLinkClicked,
+ blink::WebNavigationPolicyCurrentTab,
false);
- EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
+ EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
// Navigations to WebUI URLs will also be sent to browser process.
- WebKit::WebURLRequest webui_request(GURL("chrome://foo"));
+ blink::WebURLRequest webui_request(GURL("chrome://foo"));
policy = view()->decidePolicyForNavigation(
GetMainFrame(),
&state,
webui_request,
- WebKit::WebNavigationTypeLinkClicked,
- WebKit::WebNavigationPolicyCurrentTab,
+ blink::WebNavigationTypeLinkClicked,
+ blink::WebNavigationPolicyCurrentTab,
false);
- EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
+ EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
// Verify that form posts to data URLs will be sent to the browser process.
- WebKit::WebURLRequest data_request(GURL("data:text/html,foo"));
+ blink::WebURLRequest data_request(GURL("data:text/html,foo"));
data_request.setHTTPMethod("POST");
policy = view()->decidePolicyForNavigation(
GetMainFrame(),
&state,
data_request,
- WebKit::WebNavigationTypeFormSubmitted,
- WebKit::WebNavigationPolicyCurrentTab,
+ blink::WebNavigationTypeFormSubmitted,
+ blink::WebNavigationPolicyCurrentTab,
false);
- EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
+ EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
// Verify that a popup that creates a view first and then navigates to a
// normal HTTP URL will be sent to the browser process, even though the
// new view does not have any enabled_bindings_.
- WebKit::WebURLRequest popup_request(GURL("http://foo.com"));
- WebKit::WebView* new_web_view = view()->createView(
- GetMainFrame(), popup_request, WebKit::WebWindowFeatures(), "foo",
- WebKit::WebNavigationPolicyNewForegroundTab);
+ blink::WebURLRequest popup_request(GURL("http://foo.com"));
+ blink::WebView* new_web_view = view()->createView(
+ GetMainFrame(), popup_request, blink::WebWindowFeatures(), "foo",
+ blink::WebNavigationPolicyNewForegroundTab, false);
RenderViewImpl* new_view = RenderViewImpl::FromWebView(new_web_view);
policy = new_view->decidePolicyForNavigation(
new_web_view->mainFrame(),
&state,
popup_request,
- WebKit::WebNavigationTypeLinkClicked,
- WebKit::WebNavigationPolicyNewForegroundTab,
+ blink::WebNavigationTypeLinkClicked,
+ blink::WebNavigationPolicyNewForegroundTab,
false);
- EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
+ EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
// Clean up after the new view so we don't leak it.
new_view->Close();
@@ -1006,7 +1068,7 @@ TEST_F(RenderViewImplTest, ImeComposition) {
case IME_SETCOMPOSITION:
view()->OnImeSetComposition(
WideToUTF16Hack(ime_message->ime_string),
- std::vector<WebKit::WebCompositionUnderline>(),
+ std::vector<blink::WebCompositionUnderline>(),
ime_message->selection_start,
ime_message->selection_end);
break;
@@ -1020,8 +1082,8 @@ TEST_F(RenderViewImplTest, ImeComposition) {
case IME_CANCELCOMPOSITION:
view()->OnImeSetComposition(
- string16(),
- std::vector<WebKit::WebCompositionUnderline>(),
+ base::string16(),
+ std::vector<blink::WebCompositionUnderline>(),
0, 0);
break;
}
@@ -1065,8 +1127,8 @@ TEST_F(RenderViewImplTest, OnSetTextDirection) {
WebTextDirection direction;
const wchar_t* expected_result;
} kTextDirection[] = {
- { WebKit::WebTextDirectionRightToLeft, L"\x000A" L"rtl,rtl" },
- { WebKit::WebTextDirectionLeftToRight, L"\x000A" L"ltr,ltr" },
+ { blink::WebTextDirectionRightToLeft, L"\x000A" L"rtl,rtl" },
+ { blink::WebTextDirectionLeftToRight, L"\x000A" L"ltr,ltr" },
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTextDirection); ++i) {
// Set the text direction of the <textarea> element.
@@ -1208,7 +1270,7 @@ TEST_F(RenderViewImplTest, MAYBE_OnHandleKeyboardEvent) {
// driver is installed in a PC and the driver can assign a Unicode
// charcter for the given tuple (key-code and modifiers).
int key_code = kKeyCodes[k];
- string16 char_code;
+ base::string16 char_code;
if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0)
continue;
@@ -1455,7 +1517,7 @@ TEST_F(RenderViewImplTest, MAYBE_InsertCharacters) {
// driver is installed in a PC and the driver can assign a Unicode
// charcter for the given tuple (layout, key-code, and modifiers).
int key_code = kKeyCodes[k];
- string16 char_code;
+ base::string16 char_code;
if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0)
continue;
}
@@ -1522,7 +1584,7 @@ TEST_F(RenderViewImplTest, DidFailProvisionalLoadWithErrorForCancellation) {
// Regression test for http://crbug.com/41562
TEST_F(RenderViewImplTest, UpdateTargetURLWithInvalidURL) {
const GURL invalid_gurl("http://");
- view()->setMouseOverURL(WebKit::WebURL(invalid_gurl));
+ view()->setMouseOverURL(blink::WebURL(invalid_gurl));
EXPECT_EQ(invalid_gurl, view()->target_url_);
}
@@ -1711,9 +1773,9 @@ TEST_F(RenderViewImplTest, ContextMenu) {
TEST_F(RenderViewImplTest, TestBackForward) {
LoadHTML("<div id=pagename>Page A</div>");
- WebKit::WebHistoryItem page_a_item = GetMainFrame()->currentHistoryItem();
+ blink::WebHistoryItem page_a_item = GetMainFrame()->currentHistoryItem();
int was_page_a = -1;
- string16 check_page_a =
+ base::string16 check_page_a =
ASCIIToUTF16(
"Number(document.getElementById('pagename').innerHTML == 'Page A')");
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
@@ -1721,7 +1783,7 @@ TEST_F(RenderViewImplTest, TestBackForward) {
LoadHTML("<div id=pagename>Page B</div>");
int was_page_b = -1;
- string16 check_page_b =
+ base::string16 check_page_b =
ASCIIToUTF16(
"Number(document.getElementById('pagename').innerHTML == 'Page B')");
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
@@ -1729,13 +1791,13 @@ TEST_F(RenderViewImplTest, TestBackForward) {
LoadHTML("<div id=pagename>Page C</div>");
int was_page_c = -1;
- string16 check_page_c =
+ base::string16 check_page_c =
ASCIIToUTF16(
"Number(document.getElementById('pagename').innerHTML == 'Page C')");
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c));
EXPECT_EQ(1, was_page_b);
- WebKit::WebHistoryItem forward_item = GetMainFrame()->currentHistoryItem();
+ blink::WebHistoryItem forward_item = GetMainFrame()->currentHistoryItem();
GoBack(GetMainFrame()->previousHistoryItem());
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
EXPECT_EQ(1, was_page_b);
@@ -1760,17 +1822,24 @@ TEST_F(RenderViewImplTest, TestBackForward) {
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) {
+
+#if defined(OS_WIN)
+ // http://crbug.com/304193
+ if (base::win::GetVersion() < base::win::VERSION_VISTA)
+ return;
+#endif
+
LoadHTML("<textarea id=\"test\"></textarea>");
ExecuteJavaScript("document.getElementById('test').focus();");
- const string16 empty_string = UTF8ToUTF16("");
- const std::vector<WebKit::WebCompositionUnderline> empty_underline;
+ const base::string16 empty_string = UTF8ToUTF16("");
+ const std::vector<blink::WebCompositionUnderline> empty_underline;
std::vector<gfx::Rect> bounds;
view()->OnSetFocus(true);
view()->OnSetInputMethodActive(true);
// ASCII composition
- const string16 ascii_composition = UTF8ToUTF16("aiueo");
+ const base::string16 ascii_composition = UTF8ToUTF16("aiueo");
view()->OnImeSetComposition(ascii_composition, empty_underline, 0, 0);
view()->GetCompositionCharacterBounds(&bounds);
ASSERT_EQ(ascii_composition.size(), bounds.size());
@@ -1780,7 +1849,7 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) {
empty_string, gfx::Range::InvalidRange(), false);
// Non surrogate pair unicode character.
- const string16 unicode_composition = UTF8ToUTF16(
+ const base::string16 unicode_composition = UTF8ToUTF16(
"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A");
view()->OnImeSetComposition(unicode_composition, empty_underline, 0, 0);
view()->GetCompositionCharacterBounds(&bounds);
@@ -1791,7 +1860,7 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) {
empty_string, gfx::Range::InvalidRange(), false);
// Surrogate pair character.
- const string16 surrogate_pair_char = UTF8ToUTF16("\xF0\xA0\xAE\x9F");
+ const base::string16 surrogate_pair_char = UTF8ToUTF16("\xF0\xA0\xAE\x9F");
view()->OnImeSetComposition(surrogate_pair_char,
empty_underline,
0,
@@ -1804,7 +1873,7 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) {
empty_string, gfx::Range::InvalidRange(), false);
// Mixed string.
- const string16 surrogate_pair_mixed_composition =
+ const base::string16 surrogate_pair_mixed_composition =
surrogate_pair_char + UTF8ToUTF16("\xE3\x81\x82") + surrogate_pair_char +
UTF8ToUTF16("b") + surrogate_pair_char;
const size_t utf16_length = 8UL;
@@ -1866,9 +1935,9 @@ TEST_F(RenderViewImplTest, SetEditableSelectionAndComposition) {
"</html>");
ExecuteJavaScript("document.getElementById('test1').focus();");
view()->OnSetEditableSelectionOffsets(4, 8);
- const std::vector<WebKit::WebCompositionUnderline> empty_underline;
+ const std::vector<blink::WebCompositionUnderline> empty_underline;
view()->OnSetCompositionFromExistingText(7, 10, empty_underline);
- WebKit::WebTextInputInfo info = view()->webview()->textInputInfo();
+ blink::WebTextInputInfo info = view()->webview()->textInputInfo();
EXPECT_EQ(4, info.selectionStart);
EXPECT_EQ(8, info.selectionEnd);
EXPECT_EQ(7, info.compositionStart);
@@ -1892,7 +1961,7 @@ TEST_F(RenderViewImplTest, OnExtendSelectionAndDelete) {
ExecuteJavaScript("document.getElementById('test1').focus();");
view()->OnSetEditableSelectionOffsets(10, 10);
view()->OnExtendSelectionAndDelete(3, 4);
- WebKit::WebTextInputInfo info = view()->webview()->textInputInfo();
+ blink::WebTextInputInfo info = view()->webview()->textInputInfo();
EXPECT_EQ("abcdefgopqrstuvwxyz", info.value);
EXPECT_EQ(7, info.selectionStart);
EXPECT_EQ(7, info.selectionEnd);
@@ -1943,13 +2012,45 @@ TEST_F(RenderViewImplTest, GetSSLStatusOfFrame) {
SSLStatus ssl_status = view()->GetSSLStatusOfFrame(frame);
EXPECT_FALSE(net::IsCertStatusError(ssl_status.cert_status));
- const_cast<WebKit::WebURLResponse&>(frame->dataSource()->response()).
+ const_cast<blink::WebURLResponse&>(frame->dataSource()->response()).
setSecurityInfo(
- SerializeSecurityInfo(0, net::CERT_STATUS_ALL_ERRORS, 0, 0));
+ SerializeSecurityInfo(0, net::CERT_STATUS_ALL_ERRORS, 0, 0,
+ SignedCertificateTimestampIDStatusList()));
ssl_status = view()->GetSSLStatusOfFrame(frame);
EXPECT_TRUE(net::IsCertStatusError(ssl_status.cert_status));
}
+TEST_F(RenderViewImplTest, MessageOrderInDidChangeSelection) {
+ view()->OnSetInputMethodActive(true);
+ view()->set_send_content_state_immediately(true);
+ LoadHTML("<textarea id=\"test\"></textarea>");
+
+ view()->handling_input_event_ = true;
+ ExecuteJavaScript("document.getElementById('test').focus();");
+
+ bool is_input_type_called = false;
+ bool is_selection_called = false;
+ size_t last_input_type = 0;
+ size_t last_selection = 0;
+
+ for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
+ const uint32 type = render_thread_->sink().GetMessageAt(i)->type();
+ if (type == ViewHostMsg_TextInputTypeChanged::ID) {
+ is_input_type_called = true;
+ last_input_type = i;
+ } else if (type == ViewHostMsg_SelectionChanged::ID) {
+ is_selection_called = true;
+ last_selection = i;
+ }
+ }
+
+ EXPECT_TRUE(is_input_type_called);
+ EXPECT_TRUE(is_selection_called);
+
+ // InputTypeChange shold be called earlier than SelectionChanged.
+ EXPECT_LT(last_input_type, last_selection);
+}
+
class SuppressErrorPageTest : public RenderViewTest {
public:
virtual void SetUp() OVERRIDE {
@@ -1969,11 +2070,12 @@ class SuppressErrorPageTest : public RenderViewTest {
}
virtual void GetNavigationErrorStrings(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& failed_request,
- const WebKit::WebURLError& error,
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& failed_request,
+ const blink::WebURLError& error,
+ const std::string& accept_languages,
std::string* error_html,
- string16* error_description) OVERRIDE {
+ base::string16* error_description) OVERRIDE {
if (error_html)
*error_html = "A suffusion of yellow.";
}
@@ -1982,7 +2084,14 @@ class SuppressErrorPageTest : public RenderViewTest {
TestContentRendererClient client_;
};
-TEST_F(SuppressErrorPageTest, Suppresses) {
+#if defined(OS_ANDROID)
+// Crashing on Android: http://crbug.com/311341
+#define MAYBE_Suppresses DISABLED_Suppresses
+#else
+#define MAYBE_Suppresses Suppresses
+#endif
+
+TEST_F(SuppressErrorPageTest, MAYBE_Suppresses) {
WebURLError error;
error.domain = WebString::fromUTF8(net::kErrorDomain);
error.reason = net::ERR_FILE_NOT_FOUND;
@@ -2003,7 +2112,14 @@ TEST_F(SuppressErrorPageTest, Suppresses) {
EXPECT_EQ("", UTF16ToASCII(web_frame->contentAsText(kMaxOutputCharacters)));
}
-TEST_F(SuppressErrorPageTest, DoesNotSuppress) {
+#if defined(OS_ANDROID)
+// Crashing on Android: http://crbug.com/311341
+#define MAYBE_DoesNotSuppress DISABLED_DoesNotSuppress
+#else
+#define MAYBE_DoesNotSuppress DoesNotSuppress
+#endif
+
+TEST_F(SuppressErrorPageTest, MAYBE_DoesNotSuppress) {
WebURLError error;
error.domain = WebString::fromUTF8(net::kErrorDomain);
error.reason = net::ERR_FILE_NOT_FOUND;
@@ -2026,4 +2142,42 @@ TEST_F(SuppressErrorPageTest, DoesNotSuppress) {
UTF16ToASCII(web_frame->contentAsText(kMaxOutputCharacters)));
}
+// Tests if IME API's candidatewindow* events sent from browser are handled
+// in renderer.
+TEST_F(RenderViewImplTest, SendCandidateWindowEvents) {
+ // Sends an HTML with an <input> element and scripts to the renderer.
+ // The script handles all 3 of candidatewindow* events for an
+ // InputMethodContext object and once it received 'show', 'update', 'hide'
+ // should appear in the result div.
+ LoadHTML("<input id='test'>"
+ "<div id='result'>Result: </div>"
+ "<script>"
+ "window.onload = function() {"
+ " var result = document.getElementById('result');"
+ " var test = document.getElementById('test');"
+ " test.focus();"
+ " var context = test.inputMethodContext;"
+ " if (context) {"
+ " context.oncandidatewindowshow = function() {"
+ " result.innerText += 'show'; };"
+ " context.oncandidatewindowupdate = function(){"
+ " result.innerText += 'update'; };"
+ " context.oncandidatewindowhide = function(){"
+ " result.innerText += 'hide'; };"
+ " }"
+ "};"
+ "</script>");
+
+ // Fire candidatewindow events.
+ view()->OnCandidateWindowShown();
+ view()->OnCandidateWindowUpdated();
+ view()->OnCandidateWindowHidden();
+
+ // Retrieve the content and check if it is expected.
+ const int kMaxOutputCharacters = 50;
+ std::string output = UTF16ToUTF8(
+ GetMainFrame()->contentAsText(kMaxOutputCharacters));
+ EXPECT_EQ(output, "\nResult:showupdatehide");
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_view_browsertest_mac.mm b/chromium/content/renderer/render_view_browsertest_mac.mm
index d025ca8647f..f0959e06e1b 100644
--- a/chromium/content/renderer/render_view_browsertest_mac.mm
+++ b/chromium/content/renderer/render_view_browsertest_mac.mm
@@ -50,37 +50,32 @@ TEST_F(RenderViewTest, MacTestCmdUp) {
// a single long line).
#define HTML(s) #s
const char* kRawHtml = HTML(
- <html>
- <head><title></title>
- <script type='text/javascript' language='javascript'>
- function OnKeyEvent(ev) {
- var result = document.getElementById(ev.type);
- result.innerText = (ev.which || ev.keyCode) + ',' +
- ev.shiftKey + ',' +
- ev.ctrlKey + ',' +
- ev.metaKey + ',' +
- ev.altKey;
- return %s; /* Replace with "return true;" when testing in an html file. */
- }
- function OnScroll(ev) {
- var result = document.getElementById("scroll");
- result.innerText = window.pageYOffset;
- return true;
- }
- </script>
- <style type="text/css">
- p { border-bottom:5000px solid black; } /* enforce vertical scroll bar */
+ <!DOCTYPE html>
+ <style>
+ /* Add a vertical scrollbar */
+ body { height: 10128px; }
</style>
- </head>
- <body
- onscroll='return OnScroll(event);'
- onkeydown='return OnKeyEvent(event);'>
- <div id='keydown' contenteditable='true'> </div>
- <div id='scroll' contenteditable='true'> </div>
+ <div id='keydown'></div>
+ <div id='scroll'></div>
+ <script>
+ var allowKeyEvents = true;
+ var scroll = document.getElementById('scroll');
+ var result = document.getElementById('keydown');
+ onkeydown = function(event) {
+ result.textContent =
+ event.keyCode + ',' +
+ event.shiftKey + ',' +
+ event.ctrlKey + ',' +
+ event.metaKey + ',' +
+ event.altKey;
+ return allowKeyEvents;
+ }
+ </script>
+ <!--
+ TODO(esprehn): For some strange reason we need a non-empty document for
+ scrolling to work. This is not the case in a real browser only in the test.
+ -->
<p>p1
- <p>p2
- </body>
- </html>
);
#undef HTML
@@ -91,58 +86,54 @@ TEST_F(RenderViewTest, MacTestCmdUp) {
view->OnUpdateWebPreferences(prefs);
const int kMaxOutputCharacters = 1024;
- string16 output;
- char htmlBuffer[2048];
+ base::string16 output;
NSEvent* arrowDownKeyDown = CmdDeadKeyEvent(NSKeyDown, kVK_DownArrow);
NSEvent* arrowUpKeyDown = CmdDeadKeyEvent(NSKeyDown, kVK_UpArrow);
// First test when javascript does not eat keypresses -- should scroll.
- sprintf(htmlBuffer, kRawHtml, "true");
view->set_send_content_state_immediately(true);
- LoadHTML(htmlBuffer);
+ LoadHTML(kRawHtml);
render_thread_->sink().ClearMessages();
- const char* kArrowDownScrollDown =
- "40,false,false,true,false\n10128\np1\n\np2";
+ const char* kArrowDownScrollDown = "40,false,false,true,false\n10144\np1";
view->OnSetEditCommandsForNextKeyEvent(
EditCommands(1, EditCommand("moveToEndOfDocument", "")));
SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown));
ProcessPendingMessages();
+ ExecuteJavaScript("scroll.textContent = window.pageYOffset");
output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
EXPECT_EQ(kArrowDownScrollDown, UTF16ToASCII(output));
- const char* kArrowUpScrollUp =
- "38,false,false,true,false\n0\np1\n\np2";
+ const char* kArrowUpScrollUp = "38,false,false,true,false\n0\np1";
view->OnSetEditCommandsForNextKeyEvent(
EditCommands(1, EditCommand("moveToBeginningOfDocument", "")));
SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown));
ProcessPendingMessages();
+ ExecuteJavaScript("scroll.textContent = window.pageYOffset");
output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
EXPECT_EQ(kArrowUpScrollUp, UTF16ToASCII(output));
+ // Now let javascript eat the key events -- no scrolling should happen.
+ // Set a scroll position slightly down the page to ensure that it does not
+ // move.
+ ExecuteJavaScript("allowKeyEvents = false; window.scrollTo(0, 100)");
- // Now let javascript eat the key events -- no scrolling should happen
- sprintf(htmlBuffer, kRawHtml, "false");
- view->set_send_content_state_immediately(true);
- LoadHTML(htmlBuffer);
- render_thread_->sink().ClearMessages();
-
- const char* kArrowDownNoScroll =
- "40,false,false,true,false\np1\n\np2";
+ const char* kArrowDownNoScroll = "40,false,false,true,false\n100\np1";
view->OnSetEditCommandsForNextKeyEvent(
EditCommands(1, EditCommand("moveToEndOfDocument", "")));
SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown));
ProcessPendingMessages();
+ ExecuteJavaScript("scroll.textContent = window.pageYOffset");
output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
EXPECT_EQ(kArrowDownNoScroll, UTF16ToASCII(output));
- const char* kArrowUpNoScroll =
- "38,false,false,true,false\np1\n\np2";
+ const char* kArrowUpNoScroll = "38,false,false,true,false\n100\np1";
view->OnSetEditCommandsForNextKeyEvent(
EditCommands(1, EditCommand("moveToBeginningOfDocument", "")));
SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown));
ProcessPendingMessages();
+ ExecuteJavaScript("scroll.textContent = window.pageYOffset");
output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
EXPECT_EQ(kArrowUpNoScroll, UTF16ToASCII(output));
}
diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc
index 6efebffe5f9..134281769ca 100644
--- a/chromium/content/renderer/render_view_impl.cc
+++ b/chromium/content/renderer/render_view_impl.cc
@@ -15,7 +15,7 @@
#include "base/debug/alias.h"
#include "base/debug/trace_event.h"
#include "base/files/file_path.h"
-#include "base/i18n/char_iterator.h"
+#include "base/i18n/rtl.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
@@ -23,6 +23,7 @@
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/process/kill.h"
+#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
@@ -30,6 +31,7 @@
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
+#include "cc/base/switches.h"
#include "content/child/appcache/appcache_dispatcher.h"
#include "content/child/appcache/web_application_cache_host_impl.h"
#include "content/child/child_thread.h"
@@ -75,7 +77,6 @@
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
#include "content/renderer/browser_plugin/browser_plugin_manager_impl.h"
#include "content/renderer/context_menu_params_builder.h"
-#include "content/renderer/device_orientation_dispatcher.h"
#include "content/renderer/devtools/devtools_agent.h"
#include "content/renderer/disambiguation_popup_helper.h"
#include "content/renderer/dom_automation_controller.h"
@@ -84,11 +85,11 @@
#include "content/renderer/external_popup_menu.h"
#include "content/renderer/fetchers/alt_error_page_resource_fetcher.h"
#include "content/renderer/geolocation_dispatcher.h"
-#include "content/renderer/gpu/input_handler_manager.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/idle_user_detector.h"
#include "content/renderer/image_loading_helper.h"
#include "content/renderer/ime_event_guard.h"
+#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/input_tag_speech_dispatcher.h"
#include "content/renderer/internal_document_state_data.h"
#include "content/renderer/java/java_bridge_dispatcher.h"
@@ -112,10 +113,11 @@
#include "content/renderer/render_view_impl_params.h"
#include "content/renderer/render_view_mouse_lock_dispatcher.h"
#include "content/renderer/render_widget_fullscreen_pepper.h"
-#include "content/renderer/renderer_date_time_picker.h"
#include "content/renderer/renderer_webapplicationcachehost_impl.h"
#include "content/renderer/renderer_webcolorchooser_impl.h"
+#include "content/renderer/resizing_mode_selector.h"
#include "content/renderer/savable_resources.h"
+#include "content/renderer/shared_worker_repository.h"
#include "content/renderer/speech_recognition_dispatcher.h"
#include "content/renderer/stats_collection_controller.h"
#include "content/renderer/stats_collection_observer.h"
@@ -144,6 +146,7 @@
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/platform/WebSocketStreamHandle.h"
+#include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
@@ -152,6 +155,7 @@
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "third_party/WebKit/public/web/WebColorName.h"
+#include "third_party/WebKit/public/web/WebColorSuggestion.h"
#include "third_party/WebKit/public/web/WebDOMEvent.h"
#include "third_party/WebKit/public/web/WebDOMMessageEvent.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
@@ -178,7 +182,6 @@
#include "third_party/WebKit/public/web/WebPluginAction.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/WebKit/public/web/WebPluginDocument.h"
-#include "third_party/WebKit/public/web/WebPluginParams.h"
#include "third_party/WebKit/public/web/WebRange.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
@@ -187,13 +190,13 @@
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
#include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
#include "third_party/WebKit/public/web/WebSettings.h"
-#include "third_party/WebKit/public/web/WebStorageQuotaCallbacks.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebUserMediaClient.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/WebKit/public/web/WebWindowFeatures.h"
#include "third_party/WebKit/public/web/default/WebRenderTheme.h"
#include "ui/base/ui_base_switches_util.h"
+#include "ui/events/latency_info.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
@@ -216,7 +219,6 @@
#include "content/renderer/media/android/renderer_media_player_manager.h"
#include "content/renderer/media/android/stream_texture_factory_android_impl.h"
#include "content/renderer/media/android/webmediaplayer_android.h"
-#include "content/renderer/media/android/webmediaplayer_proxy_android.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebFloatPoint.h"
#include "third_party/WebKit/public/platform/WebFloatRect.h"
@@ -240,116 +242,109 @@
#if defined(ENABLE_PLUGINS)
#include "content/renderer/npapi/webplugin_delegate_proxy.h"
-#include "content/renderer/npapi/webplugin_impl.h"
-#include "content/renderer/pepper/pepper_browser_connection.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/pepper_plugin_registry.h"
-#include "content/renderer/pepper/pepper_webplugin_impl.h"
-#include "content/renderer/pepper/plugin_module.h"
#endif
#if defined(ENABLE_WEBRTC)
#include "content/renderer/media/rtc_peer_connection_handler.h"
#endif
-using WebKit::WebAXObject;
-using WebKit::WebApplicationCacheHost;
-using WebKit::WebApplicationCacheHostClient;
-using WebKit::WebCString;
-using WebKit::WebColor;
-using WebKit::WebColorName;
-using WebKit::WebConsoleMessage;
-using WebKit::WebContextMenuData;
-using WebKit::WebCookieJar;
-using WebKit::WebData;
-using WebKit::WebDataSource;
-using WebKit::WebDocument;
-using WebKit::WebDOMEvent;
-using WebKit::WebDOMMessageEvent;
-using WebKit::WebDragData;
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationsMask;
-using WebKit::WebEditingAction;
-using WebKit::WebElement;
-using WebKit::WebExternalPopupMenu;
-using WebKit::WebExternalPopupMenuClient;
-using WebKit::WebFileChooserCompletion;
-using WebKit::WebFindOptions;
-using WebKit::WebFormControlElement;
-using WebKit::WebFormElement;
-using WebKit::WebFrame;
-using WebKit::WebGestureEvent;
-using WebKit::WebHistoryItem;
-using WebKit::WebHTTPBody;
-using WebKit::WebIconURL;
-using WebKit::WebImage;
-using WebKit::WebInputElement;
-using WebKit::WebInputEvent;
-using WebKit::WebMediaPlayer;
-using WebKit::WebMediaPlayerAction;
-using WebKit::WebMediaPlayerClient;
-using WebKit::WebMouseEvent;
-using WebKit::WebNavigationPolicy;
-using WebKit::WebNavigationType;
-using WebKit::WebNode;
-using WebKit::WebPageSerializer;
-using WebKit::WebPageSerializerClient;
-using WebKit::WebPeerConnection00Handler;
-using WebKit::WebPeerConnection00HandlerClient;
-using WebKit::WebPeerConnectionHandler;
-using WebKit::WebPeerConnectionHandlerClient;
-using WebKit::WebPluginAction;
-using WebKit::WebPluginContainer;
-using WebKit::WebPluginDocument;
-using WebKit::WebPluginParams;
-using WebKit::WebPoint;
-using WebKit::WebPopupMenuInfo;
-using WebKit::WebRange;
-using WebKit::WebRect;
-using WebKit::WebReferrerPolicy;
-using WebKit::WebRuntimeFeatures;
-using WebKit::WebScriptSource;
-using WebKit::WebSearchableFormData;
-using WebKit::WebSecurityOrigin;
-using WebKit::WebSecurityPolicy;
-using WebKit::WebSerializedScriptValue;
-using WebKit::WebSettings;
-using WebKit::WebSharedWorker;
-using WebKit::WebSize;
-using WebKit::WebSocketStreamHandle;
-using WebKit::WebStorageNamespace;
-using WebKit::WebStorageQuotaCallbacks;
-using WebKit::WebStorageQuotaError;
-using WebKit::WebStorageQuotaType;
-using WebKit::WebString;
-using WebKit::WebTextAffinity;
-using WebKit::WebTextDirection;
-using WebKit::WebTouchEvent;
-using WebKit::WebURL;
-using WebKit::WebURLError;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
-using WebKit::WebUserGestureIndicator;
-using WebKit::WebVector;
-using WebKit::WebView;
-using WebKit::WebWidget;
-using WebKit::WebWindowFeatures;
+using blink::WebAXObject;
+using blink::WebApplicationCacheHost;
+using blink::WebApplicationCacheHostClient;
+using blink::WebCString;
+using blink::WebColor;
+using blink::WebColorName;
+using blink::WebConsoleMessage;
+using blink::WebContextMenuData;
+using blink::WebCookieJar;
+using blink::WebData;
+using blink::WebDataSource;
+using blink::WebDocument;
+using blink::WebDOMEvent;
+using blink::WebDOMMessageEvent;
+using blink::WebDragData;
+using blink::WebDragOperation;
+using blink::WebDragOperationsMask;
+using blink::WebElement;
+using blink::WebExternalPopupMenu;
+using blink::WebExternalPopupMenuClient;
+using blink::WebFileChooserCompletion;
+using blink::WebFindOptions;
+using blink::WebFormControlElement;
+using blink::WebFormElement;
+using blink::WebFrame;
+using blink::WebGestureEvent;
+using blink::WebHistoryItem;
+using blink::WebHTTPBody;
+using blink::WebIconURL;
+using blink::WebImage;
+using blink::WebInputElement;
+using blink::WebInputEvent;
+using blink::WebMediaPlayer;
+using blink::WebMediaPlayerAction;
+using blink::WebMediaPlayerClient;
+using blink::WebMouseEvent;
+using blink::WebNavigationPolicy;
+using blink::WebNavigationType;
+using blink::WebNode;
+using blink::WebPageSerializer;
+using blink::WebPageSerializerClient;
+using blink::WebPeerConnection00Handler;
+using blink::WebPeerConnection00HandlerClient;
+using blink::WebPeerConnectionHandler;
+using blink::WebPeerConnectionHandlerClient;
+using blink::WebPluginAction;
+using blink::WebPluginContainer;
+using blink::WebPluginDocument;
+using blink::WebPoint;
+using blink::WebPopupMenuInfo;
+using blink::WebRange;
+using blink::WebRect;
+using blink::WebReferrerPolicy;
+using blink::WebRuntimeFeatures;
+using blink::WebScriptSource;
+using blink::WebSearchableFormData;
+using blink::WebSecurityOrigin;
+using blink::WebSecurityPolicy;
+using blink::WebSerializedScriptValue;
+using blink::WebSettings;
+using blink::WebSize;
+using blink::WebSocketStreamHandle;
+using blink::WebStorageNamespace;
+using blink::WebStorageQuotaCallbacks;
+using blink::WebStorageQuotaError;
+using blink::WebStorageQuotaType;
+using blink::WebString;
+using blink::WebTextAffinity;
+using blink::WebTextDirection;
+using blink::WebTouchEvent;
+using blink::WebURL;
+using blink::WebURLError;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
+using blink::WebUserGestureIndicator;
+using blink::WebVector;
+using blink::WebView;
+using blink::WebWidget;
+using blink::WebWindowFeatures;
using base::Time;
using base::TimeDelta;
using webkit_glue::WebURLResponseExtraDataImpl;
#if defined(OS_ANDROID)
-using WebKit::WebContentDetectionResult;
-using WebKit::WebFloatPoint;
-using WebKit::WebFloatRect;
-using WebKit::WebHitTestResult;
+using blink::WebContentDetectionResult;
+using blink::WebFloatPoint;
+using blink::WebFloatRect;
+using blink::WebHitTestResult;
#endif
namespace content {
//-----------------------------------------------------------------------------
-typedef std::map<WebKit::WebView*, RenderViewImpl*> ViewMap;
+typedef std::map<blink::WebView*, RenderViewImpl*> ViewMap;
static base::LazyInstance<ViewMap> g_view_map = LAZY_INSTANCE_INITIALIZER;
typedef std::map<int32, RenderViewImpl*> RoutingIDViewMap;
static base::LazyInstance<RoutingIDViewMap> g_routing_id_view_map =
@@ -363,19 +358,17 @@ static base::LazyInstance<RoutingIDViewMap> g_routing_id_view_map =
// foreground renderer. This means there is a small window of time from which
// content state is modified and not sent to session restore, but this is
// better than having to wake up all renderers during shutdown.
-static const int kDelaySecondsForContentStateSyncHidden = 5;
-static const int kDelaySecondsForContentStateSync = 1;
+const int kDelaySecondsForContentStateSyncHidden = 5;
+const int kDelaySecondsForContentStateSync = 1;
-static const size_t kExtraCharsBeforeAndAfterSelection = 100;
+const size_t kExtraCharsBeforeAndAfterSelection = 100;
-static const float kScalingIncrement = 0.1f;
-
-static const float kScalingIncrementForGesture = 0.01f;
+const float kScalingIncrementForGesture = 0.01f;
#if defined(OS_ANDROID)
// Delay between tapping in content and launching the associated android intent.
// Used to allow users see what has been recognized as content.
-static const size_t kContentIntentDelayMilliseconds = 700;
+const size_t kContentIntentDelayMilliseconds = 700;
#endif
static RenderViewImpl* (*g_create_render_view_impl)(RenderViewImplParams*) =
@@ -521,13 +514,13 @@ static bool IsNonLocalTopLevelNavigation(const GURL& url,
if (!url.SchemeIs(kHttpScheme) && !url.SchemeIs(kHttpsScheme))
return false;
- if (type != WebKit::WebNavigationTypeReload &&
- type != WebKit::WebNavigationTypeBackForward && !is_form_post) {
+ if (type != blink::WebNavigationTypeReload &&
+ type != blink::WebNavigationTypeBackForward && !is_form_post) {
// The opener relationship between the new window and the parent allows the
// new window to script the parent and vice versa. This is not allowed if
// the origins of the two domains are different. This can be treated as a
// top level navigation and routed back to the host.
- WebKit::WebFrame* opener = frame->opener();
+ blink::WebFrame* opener = frame->opener();
if (!opener)
return true;
@@ -537,11 +530,11 @@ static bool IsNonLocalTopLevelNavigation(const GURL& url,
return false;
}
-static void NotifyTimezoneChange(WebKit::WebFrame* frame) {
+static void NotifyTimezoneChange(blink::WebFrame* frame) {
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
v8::Context::Scope context_scope(frame->mainWorldScriptContext());
- v8::Date::DateTimeConfigurationChangeNotification();
- WebKit::WebFrame* child = frame->firstChild();
+ v8::Date::DateTimeConfigurationChangeNotification(v8::Isolate::GetCurrent());
+ blink::WebFrame* child = frame->firstChild();
for (; child; child = child->nextSibling())
NotifyTimezoneChange(child);
}
@@ -549,19 +542,19 @@ static void NotifyTimezoneChange(WebKit::WebFrame* frame) {
static WindowOpenDisposition NavigationPolicyToDisposition(
WebNavigationPolicy policy) {
switch (policy) {
- case WebKit::WebNavigationPolicyIgnore:
+ case blink::WebNavigationPolicyIgnore:
return IGNORE_ACTION;
- case WebKit::WebNavigationPolicyDownload:
+ case blink::WebNavigationPolicyDownload:
return SAVE_TO_DISK;
- case WebKit::WebNavigationPolicyCurrentTab:
+ case blink::WebNavigationPolicyCurrentTab:
return CURRENT_TAB;
- case WebKit::WebNavigationPolicyNewBackgroundTab:
+ case blink::WebNavigationPolicyNewBackgroundTab:
return NEW_BACKGROUND_TAB;
- case WebKit::WebNavigationPolicyNewForegroundTab:
+ case blink::WebNavigationPolicyNewForegroundTab:
return NEW_FOREGROUND_TAB;
- case WebKit::WebNavigationPolicyNewWindow:
+ case blink::WebNavigationPolicyNewWindow:
return NEW_WINDOW;
- case WebKit::WebNavigationPolicyNewPopup:
+ case blink::WebNavigationPolicyNewPopup:
return NEW_POPUP;
default:
NOTREACHED() << "Unexpected WebNavigationPolicy";
@@ -599,12 +592,61 @@ static bool ShouldUseAcceleratedCompositingForOverflowScroll(
float device_scale_factor) {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kDisableAcceleratedOverflowScroll))
+ return false;
+
if (command_line.HasSwitch(switches::kEnableAcceleratedOverflowScroll))
return true;
return DeviceScaleEnsuresTextQuality(device_scale_factor);
}
+static bool ShouldUseAcceleratedCompositingForScrollableFrames(
+ float device_scale_factor) {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+
+ if (command_line.HasSwitch(switches::kDisableAcceleratedScrollableFrames))
+ return false;
+
+ if (command_line.HasSwitch(switches::kEnableAcceleratedScrollableFrames))
+ return true;
+
+ if (!cc::switches::IsLCDTextEnabled())
+ return true;
+
+ return DeviceScaleEnsuresTextQuality(device_scale_factor);
+}
+
+static bool ShouldUseCompositedScrollingForFrames(
+ float device_scale_factor) {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+
+ if (command_line.HasSwitch(switches::kDisableCompositedScrollingForFrames))
+ return false;
+
+ if (command_line.HasSwitch(switches::kEnableCompositedScrollingForFrames))
+ return true;
+
+ if (!cc::switches::IsLCDTextEnabled())
+ return true;
+
+ return DeviceScaleEnsuresTextQuality(device_scale_factor);
+}
+
+static bool ShouldUseUniversalAcceleratedCompositingForOverflowScroll() {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+
+ if (command_line.HasSwitch(
+ switches::kDisableUniversalAcceleratedOverflowScroll))
+ return false;
+
+ if (command_line.HasSwitch(
+ switches::kEnableUniversalAcceleratedOverflowScroll))
+ return true;
+
+ return false;
+}
+
static bool ShouldUseTransitionCompositing(float device_scale_factor) {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
@@ -632,15 +674,15 @@ static bool ShouldUseAcceleratedFixedRootBackground(float device_scale_factor) {
return DeviceScaleEnsuresTextQuality(device_scale_factor);
}
-static FaviconURL::IconType ToFaviconType(WebKit::WebIconURL::Type type) {
+static FaviconURL::IconType ToFaviconType(blink::WebIconURL::Type type) {
switch (type) {
- case WebKit::WebIconURL::TypeFavicon:
+ case blink::WebIconURL::TypeFavicon:
return FaviconURL::FAVICON;
- case WebKit::WebIconURL::TypeTouch:
+ case blink::WebIconURL::TypeTouch:
return FaviconURL::TOUCH_ICON;
- case WebKit::WebIconURL::TypeTouchPrecomposed:
+ case blink::WebIconURL::TypeTouchPrecomposed:
return FaviconURL::TOUCH_PRECOMPOSED_ICON;
- case WebKit::WebIconURL::TypeInvalid:
+ case blink::WebIconURL::TypeInvalid:
return FaviconURL::INVALID_ICON;
}
return FaviconURL::INVALID_ICON;
@@ -661,7 +703,7 @@ namespace {
class WebWidgetLockTarget : public MouseLockDispatcher::LockTarget {
public:
- explicit WebWidgetLockTarget(WebKit::WebWidget* webwidget)
+ explicit WebWidgetLockTarget(blink::WebWidget* webwidget)
: webwidget_(webwidget) {}
virtual void OnLockMouseACK(bool succeeded) OVERRIDE {
@@ -676,13 +718,13 @@ class WebWidgetLockTarget : public MouseLockDispatcher::LockTarget {
}
virtual bool HandleMouseLockedInputEvent(
- const WebKit::WebMouseEvent &event) OVERRIDE {
+ const blink::WebMouseEvent &event) OVERRIDE {
// The WebWidget handles mouse lock in WebKit's handleInputEvent().
return false;
}
private:
- WebKit::WebWidget* webwidget_;
+ blink::WebWidget* webwidget_;
};
int64 ExtractPostId(const WebHistoryItem& item) {
@@ -772,7 +814,7 @@ WebDragData DropDataToWebDragData(const DropData& drop_data) {
} // namespace
RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
- : RenderWidget(WebKit::WebPopupTypeNone,
+ : RenderWidget(blink::WebPopupTypeNone,
params->screen_info,
params->swapped_out,
params->hidden),
@@ -784,6 +826,7 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
navigation_gesture_(NavigationGestureUnknown),
opened_by_user_gesture_(true),
opener_suppressed_(false),
+ suppress_dialogs_until_swap_out_(false),
page_id_(-1),
last_page_id_sent_to_browser_(-1),
next_page_id_(params->next_page_id),
@@ -804,7 +847,6 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
geolocation_dispatcher_(NULL),
input_tag_speech_dispatcher_(NULL),
speech_recognition_dispatcher_(NULL),
- device_orientation_dispatcher_(NULL),
media_stream_dispatcher_(NULL),
browser_plugin_manager_(NULL),
media_stream_client_(NULL),
@@ -813,12 +855,11 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
devtools_agent_(NULL),
accessibility_mode_(AccessibilityModeOff),
renderer_accessibility_(NULL),
- java_bridge_dispatcher_(NULL),
mouse_lock_dispatcher_(NULL),
#if defined(OS_ANDROID)
body_background_color_(SK_ColorWHITE),
expected_content_intent_id_(0),
- media_player_proxy_(NULL),
+ media_player_manager_(NULL),
#endif
#if defined(OS_WIN)
focused_plugin_id_(-1),
@@ -837,9 +878,6 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
}
void RenderViewImpl::Initialize(RenderViewImplParams* params) {
- RenderFrameImpl* main_frame = RenderFrameImpl::Create(
- this, params->main_frame_routing_id);
- main_render_frame_.reset(main_frame);
routing_id_ = params->routing_id;
surface_id_ = params->surface_id;
if (params->opener_id != MSG_ROUTING_NONE && params->is_renderer_created)
@@ -898,13 +936,24 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
ShouldUseFixedPositionCompositing(device_scale_factor_));
webview()->settings()->setAcceleratedCompositingForOverflowScrollEnabled(
ShouldUseAcceleratedCompositingForOverflowScroll(device_scale_factor_));
+ webview()->settings()->setCompositorDrivenAcceleratedScrollingEnabled(
+ ShouldUseUniversalAcceleratedCompositingForOverflowScroll());
webview()->settings()->setAcceleratedCompositingForTransitionEnabled(
ShouldUseTransitionCompositing(device_scale_factor_));
webview()->settings()->setAcceleratedCompositingForFixedRootBackgroundEnabled(
ShouldUseAcceleratedFixedRootBackground(device_scale_factor_));
+ webview()->settings()->setAcceleratedCompositingForScrollableFramesEnabled(
+ ShouldUseAcceleratedCompositingForScrollableFrames(device_scale_factor_));
+ webview()->settings()->setCompositedScrollingForFramesEnabled(
+ ShouldUseCompositedScrollingForFrames(device_scale_factor_));
ApplyWebPreferences(webkit_preferences_, webview());
- webview()->initializeMainFrame(main_render_frame_.get());
+
+ main_render_frame_.reset(
+ RenderFrameImpl::Create(this, params->main_frame_routing_id));
+ // The main frame WebFrame object is closed by
+ // RenderViewImpl::frameDetached().
+ webview()->setMainFrame(WebFrame::create(main_render_frame_.get()));
if (switches::IsTouchDragDropEnabled())
webview()->settings()->setTouchDragDropEnabled(true);
@@ -927,8 +976,11 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
new TextInputClientObserver(this);
#endif // defined(OS_MACOSX)
+ new SharedWorkerRepository(this);
+
#if defined(OS_ANDROID)
- media_player_manager_.reset(new RendererMediaPlayerManager());
+ media_player_manager_ = new RendererMediaPlayerManager(this);
+ new JavaBridgeDispatcher(this);
#endif
// The next group of objects all implement RenderViewObserver, so are deleted
@@ -952,10 +1004,6 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
ProcessViewLayoutFlags(command_line);
-#if defined(ENABLE_PLUGINS)
- new PepperBrowserConnection(this);
-#endif
-
GetContentClient()->renderer()->RenderViewCreated(this);
// If we have an opener_id but we weren't created by a renderer, then
@@ -1015,7 +1063,7 @@ RenderViewImpl* RenderViewImpl::FromWebView(WebView* webview) {
}
/*static*/
-RenderView* RenderView::FromWebView(WebKit::WebView* webview) {
+RenderView* RenderView::FromWebView(blink::WebView* webview) {
return RenderViewImpl::FromWebView(webview);
}
@@ -1049,12 +1097,12 @@ RenderViewImpl* RenderViewImpl::Create(
int32 main_frame_routing_id,
int32 surface_id,
int64 session_storage_namespace_id,
- const string16& frame_name,
+ const base::string16& frame_name,
bool is_renderer_created,
bool swapped_out,
bool hidden,
int32 next_page_id,
- const WebKit::WebScreenInfo& screen_info,
+ const blink::WebScreenInfo& screen_info,
AccessibilityMode accessibility_mode,
bool allow_partial_swap) {
DCHECK(routing_id != MSG_ROUTING_NONE);
@@ -1099,120 +1147,11 @@ void RenderViewImpl::RemoveObserver(RenderViewObserver* observer) {
observers_.RemoveObserver(observer);
}
-WebKit::WebView* RenderViewImpl::webview() const {
- return static_cast<WebKit::WebView*>(webwidget());
+blink::WebView* RenderViewImpl::webview() const {
+ return static_cast<blink::WebView*>(webwidget());
}
#if defined(ENABLE_PLUGINS)
-void RenderViewImpl::PepperInstanceCreated(PepperPluginInstanceImpl* instance) {
- active_pepper_instances_.insert(instance);
-}
-
-void RenderViewImpl::PepperInstanceDeleted(PepperPluginInstanceImpl* instance) {
- active_pepper_instances_.erase(instance);
-
- if (pepper_last_mouse_event_target_ == instance)
- pepper_last_mouse_event_target_ = NULL;
- if (focused_pepper_plugin_ == instance)
- PepperFocusChanged(instance, false);
-}
-
-void RenderViewImpl::PepperDidChangeCursor(
- PepperPluginInstanceImpl* instance,
- const WebKit::WebCursorInfo& cursor) {
- // Update the cursor appearance immediately if the requesting plugin is the
- // one which receives the last mouse event. Otherwise, the new cursor won't be
- // picked up until the plugin gets the next input event. That is bad if, e.g.,
- // the plugin would like to set an invisible cursor when there isn't any user
- // input for a while.
- if (instance == pepper_last_mouse_event_target_)
- didChangeCursor(cursor);
-}
-
-void RenderViewImpl::PepperDidReceiveMouseEvent(
- PepperPluginInstanceImpl* instance) {
- pepper_last_mouse_event_target_ = instance;
-}
-
-void RenderViewImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance,
- bool focused) {
- if (focused)
- focused_pepper_plugin_ = instance;
- else if (focused_pepper_plugin_ == instance)
- focused_pepper_plugin_ = NULL;
-
- UpdateTextInputType();
- UpdateSelectionBounds();
-}
-
-void RenderViewImpl::PepperTextInputTypeChanged(
- PepperPluginInstanceImpl* instance) {
- if (instance != focused_pepper_plugin_)
- return;
-
- UpdateTextInputType();
- if (renderer_accessibility_)
- renderer_accessibility_->FocusedNodeChanged(WebNode());
-}
-
-void RenderViewImpl::PepperCaretPositionChanged(
- PepperPluginInstanceImpl* instance) {
- if (instance != focused_pepper_plugin_)
- return;
- UpdateSelectionBounds();
-}
-
-void RenderViewImpl::PepperCancelComposition(
- PepperPluginInstanceImpl* instance) {
- if (instance != focused_pepper_plugin_)
- return;
- Send(new ViewHostMsg_ImeCancelComposition(routing_id()));;
-#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
- UpdateCompositionInfo(true);
-#endif
-}
-
-void RenderViewImpl::PepperSelectionChanged(
- PepperPluginInstanceImpl* instance) {
- if (instance != focused_pepper_plugin_)
- return;
- SyncSelectionIfRequired();
-}
-
-RenderWidgetFullscreenPepper* RenderViewImpl::CreatePepperFullscreenContainer(
- PepperPluginInstanceImpl* plugin) {
- GURL active_url;
- if (webview() && webview()->mainFrame())
- active_url = GURL(webview()->mainFrame()->document().url());
- RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create(
- routing_id_, plugin, active_url, screen_info_);
- widget->show(WebKit::WebNavigationPolicyIgnore);
- return widget;
-}
-
-void RenderViewImpl::PepperPluginCreated(RendererPpapiHost* host) {
- FOR_EACH_OBSERVER(RenderViewObserver, observers_,
- DidCreatePepperPlugin(host));
-}
-
-bool RenderViewImpl::GetPepperCaretBounds(gfx::Rect* rect) {
- if (!focused_pepper_plugin_)
- return false;
- *rect = focused_pepper_plugin_->GetCaretBounds();
- return true;
-}
-
-bool RenderViewImpl::IsPepperAcceptingCompositionEvents() const {
- if (!focused_pepper_plugin_)
- return false;
- return focused_pepper_plugin_->IsPluginAcceptingCompositionEvents();
-}
-
-void RenderViewImpl::PluginCrashed(const base::FilePath& plugin_path,
- base::ProcessId plugin_pid) {
- Send(new ViewHostMsg_CrashedPlugin(routing_id_, plugin_path, plugin_pid));
-}
-
void RenderViewImpl::RegisterPluginDelegate(WebPluginDelegateProxy* delegate) {
plugin_delegates_.insert(delegate);
// If the renderer is visible, set initial visibility and focus state.
@@ -1234,32 +1173,6 @@ void RenderViewImpl::UnregisterPluginDelegate(
plugin_delegates_.erase(delegate);
}
-bool RenderViewImpl::GetPluginInfo(const GURL& url,
- const GURL& page_url,
- const std::string& mime_type,
- WebPluginInfo* plugin_info,
- std::string* actual_mime_type) {
- bool found = false;
- Send(new ViewHostMsg_GetPluginInfo(
- routing_id_, url, page_url, mime_type, &found, plugin_info,
- actual_mime_type));
- return found;
-}
-
-void RenderViewImpl::SimulateImeSetComposition(
- const string16& text,
- const std::vector<WebKit::WebCompositionUnderline>& underlines,
- int selection_start,
- int selection_end) {
- OnImeSetComposition(text, underlines, selection_start, selection_end);
-}
-
-void RenderViewImpl::SimulateImeConfirmComposition(
- const string16& text,
- const gfx::Range& replacement_range) {
- OnImeConfirmComposition(text, replacement_range, false);
-}
-
#if defined(OS_WIN)
void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) {
if (focused)
@@ -1286,7 +1199,7 @@ void RenderViewImpl::StartPluginIme() {
#endif // ENABLE_PLUGINS
void RenderViewImpl::TransferActiveWheelFlingAnimation(
- const WebKit::WebActiveWheelFlingParameters& params) {
+ const blink::WebActiveWheelFlingParameters& params) {
if (webview())
webview()->transferActiveWheelFlingAnimation(params);
}
@@ -1368,6 +1281,8 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
OnEnumerateDirectoryResponse)
IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnShouldClose)
+ IPC_MESSAGE_HANDLER(ViewMsg_SuppressDialogsUntilSwapOut,
+ OnSuppressDialogsUntilSwapOut)
IPC_MESSAGE_HANDLER(ViewMsg_SwapOut, OnSwapOut)
IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
@@ -1399,11 +1314,12 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryLengthAndPrune,
OnSetHistoryLengthAndPrune)
IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
-#if defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(JavaBridgeMsg_Init, OnJavaBridgeInit)
-#endif
IPC_MESSAGE_HANDLER(ViewMsg_SetAccessibilityMode, OnSetAccessibilityMode)
IPC_MESSAGE_HANDLER(ViewMsg_DisownOpener, OnDisownOpener)
+ IPC_MESSAGE_HANDLER(ViewMsg_ReleaseDisambiguationPopupDIB,
+ OnReleaseDisambiguationPopupDIB)
+ IPC_MESSAGE_HANDLER(ViewMsg_WindowSnapshotCompleted,
+ OnWindowSnapshotCompleted)
#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(InputMsg_ActivateNearestFindResult,
OnActivateNearestFindResult)
@@ -1414,6 +1330,7 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_UpdateTopControlsState,
OnUpdateTopControlsState)
IPC_MESSAGE_HANDLER(ViewMsg_PauseVideo, OnPauseVideo)
+ IPC_MESSAGE_HANDLER(ViewMsg_ExtractSmartClipData, OnExtractSmartClipData)
#elif defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard)
IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted,
@@ -1423,10 +1340,8 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_SetWindowVisibility, OnSetWindowVisibility)
IPC_MESSAGE_HANDLER(ViewMsg_WindowFrameChanged, OnWindowFrameChanged)
#endif
- IPC_MESSAGE_HANDLER(ViewMsg_ReleaseDisambiguationPopupDIB,
- OnReleaseDisambiguationPopupDIB)
- IPC_MESSAGE_HANDLER(ViewMsg_WindowSnapshotCompleted,
- OnWindowSnapshotCompleted)
+ // Adding a new message? Add platform independent ones first, then put the
+ // platform specific ones at the end.
// Have the super handle all other messages.
IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message))
@@ -1581,10 +1496,13 @@ void RenderViewImpl::OnNavigate(const ViewMsg_Navigate_Params& params) {
// Set post data.
WebHTTPBody http_body;
http_body.initialize();
- http_body.appendData(WebData(
- reinterpret_cast<const char*>(
- &params.browser_initiated_post_data.front()),
- params.browser_initiated_post_data.size()));
+ const char* data = NULL;
+ if (params.browser_initiated_post_data.size()) {
+ data = reinterpret_cast<const char*>(
+ &params.browser_initiated_post_data.front());
+ }
+ http_body.appendData(
+ WebData(data, params.browser_initiated_post_data.size()));
request.setHTTPBody(http_body);
}
@@ -1652,7 +1570,7 @@ void RenderViewImpl::OnStop() {
if (webview()) {
WebFrame* main_frame = webview()->mainFrame();
// Stop the alt error page fetcher. If we let it continue it may complete
- // and cause RenderViewHostManager to swap to this RenderView, even though
+ // and cause RenderFrameHostManager to swap to this RenderView, even though
// it may no longer be active.
StopAltErrorPageFetcher(main_frame->provisionalDataSource());
StopAltErrorPageFetcher(main_frame->dataSource());
@@ -1728,7 +1646,7 @@ void RenderViewImpl::OnMoveCaret(const gfx::Point& point) {
Send(new ViewHostMsg_MoveCaret_ACK(routing_id_));
- webview()->focusedFrame()->moveCaretSelectionTowardsWindowPoint(point);
+ webview()->focusedFrame()->moveCaretSelection(point);
}
void RenderViewImpl::OnPaste() {
@@ -1757,7 +1675,7 @@ void RenderViewImpl::OnRedo() {
GetFocusedNode());
}
-void RenderViewImpl::OnReplace(const string16& text) {
+void RenderViewImpl::OnReplace(const base::string16& text) {
if (!webview())
return;
@@ -1768,7 +1686,7 @@ void RenderViewImpl::OnReplace(const string16& text) {
frame->replaceSelection(text);
}
-void RenderViewImpl::OnReplaceMisspelling(const string16& text) {
+void RenderViewImpl::OnReplaceMisspelling(const base::string16& text) {
if (!webview())
return;
@@ -1781,7 +1699,7 @@ void RenderViewImpl::OnReplaceMisspelling(const string16& text) {
void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect(
const gfx::Rect& rect) {
- WebKit::WebNode node = GetFocusedNode();
+ blink::WebNode node = GetFocusedNode();
if (!node.isNull()) {
if (IsEditableNode(node)) {
webview()->saveScrollAndScaleState();
@@ -1841,7 +1759,7 @@ void RenderViewImpl::OnCopyToFindPboard() {
// than the |OnCopy()| case.
WebFrame* frame = webview()->focusedFrame();
if (frame->hasSelection()) {
- string16 selection = frame->selectionAsText();
+ base::string16 selection = frame->selectionAsText();
RenderThread::Get()->Send(
new ClipboardHostMsg_FindPboardWriteStringAsync(selection));
}
@@ -1865,7 +1783,7 @@ void RenderViewImpl::OnSetEditableSelectionOffsets(int start, int end) {
void RenderViewImpl::OnSetCompositionFromExistingText(
int start, int end,
- const std::vector<WebKit::WebCompositionUnderline>& underlines) {
+ const std::vector<blink::WebCompositionUnderline>& underlines) {
if (!ShouldHandleImeEvent())
return;
ImeEventGuard guard(this);
@@ -1955,6 +1873,7 @@ void RenderViewImpl::UpdateURL(WebFrame* frame) {
params.post_id = -1;
params.page_id = page_id_;
params.frame_id = frame->identifier();
+ params.frame_unique_name = frame->uniqueName();
params.socket_address.set_host(response.remoteIPAddress().utf8());
params.socket_address.set_port(response.remotePort());
WebURLResponseExtraDataImpl* extra_data = GetExtraDataFromResponse(response);
@@ -2050,7 +1969,7 @@ void RenderViewImpl::UpdateURL(WebFrame* frame) {
params.referrer = GetReferrerFromRequest(frame, original_request);
}
- string16 method = request.httpMethod();
+ base::string16 method = request.httpMethod();
if (EqualsASCII(method, "POST")) {
params.is_post = true;
params.post_id = ExtractPostId(item);
@@ -2059,8 +1978,13 @@ void RenderViewImpl::UpdateURL(WebFrame* frame) {
// Send the user agent override back.
params.is_overriding_user_agent = internal_data->is_overriding_user_agent();
- // Track the URL of the original request.
- params.original_request_url = original_request.url();
+ // Track the URL of the original request. We use the first entry of the
+ // redirect chain if it exists because the chain may have started in another
+ // process.
+ if (params.redirects.size() > 0)
+ params.original_request_url = params.redirects.at(0);
+ else
+ params.original_request_url = original_request.url();
params.history_list_was_cleared =
navigation_state->history_list_was_cleared();
@@ -2068,7 +1992,7 @@ void RenderViewImpl::UpdateURL(WebFrame* frame) {
// Save some histogram data so we can compute the average memory used per
// page load of the glyphs.
UMA_HISTOGRAM_COUNTS_10000("Memory.GlyphPagesPerLoad",
- WebKit::WebGlyphCache::pageCount());
+ blink::WebGlyphCache::pageCount());
// This message needs to be sent before any of allowScripts(),
// allowImages(), allowPlugins() is called for the new page, so that when
@@ -2102,7 +2026,7 @@ void RenderViewImpl::UpdateURL(WebFrame* frame) {
// Tell the embedding application that the title of the active page has changed
void RenderViewImpl::UpdateTitle(WebFrame* frame,
- const string16& title,
+ const base::string16& title,
WebTextDirection title_direction) {
// Ignore all but top level navigations.
if (frame->parent())
@@ -2111,7 +2035,7 @@ void RenderViewImpl::UpdateTitle(WebFrame* frame,
base::debug::TraceLog::GetInstance()->UpdateProcessLabel(
routing_id_, UTF16ToUTF8(title));
- string16 shortened_title = title.substr(0, kMaxTitleChars);
+ base::string16 shortened_title = title.substr(0, kMaxTitleChars);
Send(new ViewHostMsg_UpdateTitle(routing_id_, page_id_, shortened_title,
title_direction));
}
@@ -2166,7 +2090,19 @@ void RenderViewImpl::OpenURL(WebFrame* frame,
params.frame_id = frame->identifier();
WebDataSource* ds = frame->provisionalDataSource();
if (ds) {
- params.should_replace_current_entry = ds->replacesCurrentHistoryItem();
+ DocumentState* document_state = DocumentState::FromDataSource(ds);
+ NavigationState* navigation_state = document_state->navigation_state();
+ if (navigation_state->is_content_initiated()) {
+ params.should_replace_current_entry = ds->replacesCurrentHistoryItem();
+ } else {
+ // This is necessary to preserve the should_replace_current_entry value on
+ // cross-process redirects, in the event it was set by a previous process.
+ //
+ // TODO(davidben): Avoid this awkward duplication of state. See comment on
+ // NavigationState::should_replace_current_entry().
+ params.should_replace_current_entry =
+ navigation_state->should_replace_current_entry();
+ }
} else {
params.should_replace_current_entry = false;
}
@@ -2174,10 +2110,10 @@ void RenderViewImpl::OpenURL(WebFrame* frame,
if (GetContentClient()->renderer()->AllowPopup())
params.user_gesture = true;
- if (policy == WebKit::WebNavigationPolicyNewBackgroundTab ||
- policy == WebKit::WebNavigationPolicyNewForegroundTab ||
- policy == WebKit::WebNavigationPolicyNewWindow ||
- policy == WebKit::WebNavigationPolicyNewPopup) {
+ if (policy == blink::WebNavigationPolicyNewBackgroundTab ||
+ policy == blink::WebNavigationPolicyNewForegroundTab ||
+ policy == blink::WebNavigationPolicyNewWindow ||
+ policy == blink::WebNavigationPolicyNewPopup) {
WebUserGestureIndicator::consumeUserGesture();
}
@@ -2199,7 +2135,8 @@ void RenderViewImpl::LoadNavigationErrorPage(
error_html = &html;
} else {
GetContentClient()->renderer()->GetNavigationErrorStrings(
- frame, failed_request, error, &alt_html, NULL);
+ frame, failed_request, error, renderer_preferences_.accept_languages,
+ &alt_html, NULL);
error_html = &alt_html;
}
@@ -2210,12 +2147,17 @@ void RenderViewImpl::LoadNavigationErrorPage(
}
bool RenderViewImpl::RunJavaScriptMessage(JavaScriptMessageType type,
- const string16& message,
- const string16& default_value,
+ const base::string16& message,
+ const base::string16& default_value,
const GURL& frame_url,
- string16* result) {
+ base::string16* result) {
+ // Don't allow further dialogs if we are waiting to swap out, since the
+ // PageGroupLoadDeferrer in our stack prevents it.
+ if (suppress_dialogs_until_swap_out_)
+ return false;
+
bool success = false;
- string16 result_temp;
+ base::string16 result_temp;
if (!result)
result = &result_temp;
@@ -2239,25 +2181,45 @@ bool RenderViewImpl::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) {
void RenderViewImpl::GetWindowSnapshot(const WindowSnapshotCallback& callback) {
int id = next_snapshot_id_++;
pending_snapshots_.insert(std::make_pair(id, callback));
- Send(new ViewHostMsg_GetWindowSnapshot(routing_id_, id));
+ ui::LatencyInfo latency_info;
+ latency_info.AddLatencyNumber(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT,
+ GetLatencyComponentId(),
+ id);
+ scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor;
+ if (RenderWidgetCompositor* rwc = compositor()) {
+ latency_info_swap_promise_monitor =
+ rwc->CreateLatencyInfoSwapPromiseMonitor(&latency_info).Pass();
+ } else {
+ latency_info_.MergeWith(latency_info);
+ }
+ ScheduleCompositeWithForcedRedraw();
}
void RenderViewImpl::OnWindowSnapshotCompleted(const int snapshot_id,
const gfx::Size& size, const std::vector<unsigned char>& png) {
- PendingSnapshotMap::iterator it = pending_snapshots_.find(snapshot_id);
- DCHECK(it != pending_snapshots_.end());
- it->second.Run(size, png);
- pending_snapshots_.erase(it);
+
+ // Any pending snapshots with a lower ID than the one received are considered
+ // to be implicitly complete, and returned the same snapshot data.
+ PendingSnapshotMap::iterator it = pending_snapshots_.begin();
+ while(it != pending_snapshots_.end()) {
+ if (it->first <= snapshot_id) {
+ it->second.Run(size, png);
+ pending_snapshots_.erase(it++);
+ } else {
+ ++it;
+ }
+ }
}
-// WebKit::WebViewClient ------------------------------------------------------
+// blink::WebViewClient ------------------------------------------------------
WebView* RenderViewImpl::createView(
WebFrame* creator,
const WebURLRequest& request,
const WebWindowFeatures& features,
const WebString& frame_name,
- WebNavigationPolicy policy) {
+ WebNavigationPolicy policy,
+ bool suppress_opener) {
ViewHostMsg_CreateWindow_Params params;
params.opener_id = routing_id_;
params.user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
@@ -2274,7 +2236,7 @@ WebView* RenderViewImpl::createView(
if (!security_url.is_valid())
security_url = GURL();
params.opener_security_origin = security_url;
- params.opener_suppressed = creator->willSuppressOpenerInNewFrame();
+ params.opener_suppressed = suppress_opener;
params.disposition = NavigationPolicyToDisposition(policy);
if (!request.isNull()) {
params.target_url = request.url();
@@ -2282,6 +2244,9 @@ WebView* RenderViewImpl::createView(
}
params.features = features;
+ for (size_t i = 0; i < features.additionalFeatures.size(); ++i)
+ params.additional_features.push_back(features.additionalFeatures[i]);
+
int32 routing_id = MSG_ROUTING_NONE;
int32 main_frame_routing_id = MSG_ROUTING_NONE;
int32 surface_id = 0;
@@ -2325,7 +2290,7 @@ WebView* RenderViewImpl::createView(
main_frame_routing_id,
surface_id,
cloned_session_storage_namespace_id,
- string16(), // WebCore will take care of setting the correct name.
+ base::string16(), // WebCore will take care of setting the correct name.
true, // is_renderer_created
false, // swapped_out
params.disposition == NEW_BACKGROUND_TAB, // hidden
@@ -2345,9 +2310,13 @@ WebView* RenderViewImpl::createView(
return view->webview();
}
-WebWidget* RenderViewImpl::createPopupMenu(WebKit::WebPopupType popup_type) {
+WebWidget* RenderViewImpl::createPopupMenu(blink::WebPopupType popup_type) {
RenderWidget* widget =
RenderWidget::Create(routing_id_, popup_type, screen_info_);
+ if (screen_metrics_emulator_) {
+ widget->SetPopupOriginAdjustmentsForEmulation(
+ screen_metrics_emulator_.get());
+ }
return widget->webwidget();
}
@@ -2364,6 +2333,10 @@ WebExternalPopupMenu* RenderViewImpl::createExternalPopupMenu(
return NULL;
external_popup_menu_.reset(
new ExternalPopupMenu(this, popup_menu_info, popup_menu_client));
+ if (screen_metrics_emulator_) {
+ SetExternalPopupOriginAdjustmentsForEmulation(
+ external_popup_menu_.get(), screen_metrics_emulator_.get());
+ }
return external_popup_menu_.get();
}
@@ -2387,6 +2360,7 @@ void RenderViewImpl::didAddMessageToConsole(
log_severity = logging::LOG_VERBOSE;
break;
case WebConsoleMessage::LevelLog:
+ case WebConsoleMessage::LevelInfo:
log_severity = logging::LOG_INFO;
break;
case WebConsoleMessage::LevelWarning:
@@ -2422,7 +2396,7 @@ void RenderViewImpl::printPage(WebFrame* frame) {
PrintPage(frame, handling_input_event_));
}
-WebKit::WebNotificationPresenter* RenderViewImpl::notificationPresenter() {
+blink::WebNotificationPresenter* RenderViewImpl::notificationPresenter() {
return notification_provider_;
}
@@ -2438,7 +2412,7 @@ bool RenderViewImpl::enumerateChosenDirectory(
}
void RenderViewImpl::initializeHelperPluginWebFrame(
- WebKit::WebHelperPlugin* plugin) {
+ blink::WebHelperPlugin* plugin) {
plugin->initializeFrame(main_render_frame_.get());
}
@@ -2495,8 +2469,13 @@ void RenderViewImpl::didChangeSelection(bool is_empty_selection) {
if (is_empty_selection)
selection_text_.clear();
- SyncSelectionIfRequired();
+ // UpdateTextInputType should be called before SyncSelectionIfRequired.
+ // UpdateTextInputType may send TextInputTypeChanged to notify the focus
+ // was changed, and SyncSelectionIfRequired may send SelectionChanged
+ // to notify the selection was changed. Focus change should be notified
+ // before selection change.
UpdateTextInputType();
+ SyncSelectionIfRequired();
#if defined(OS_ANDROID)
UpdateTextInputState(false, true);
#endif
@@ -2508,7 +2487,7 @@ void RenderViewImpl::didExecuteCommand(const WebString& command_name) {
StartsWithASCII(name, "Insert", true) ||
StartsWithASCII(name, "Delete", true))
return;
- RenderThreadImpl::current()->RecordUserMetrics(name);
+ RenderThreadImpl::current()->RecordComputedAction(name);
}
bool RenderViewImpl::handleCurrentKeyboardEvent() {
@@ -2537,17 +2516,22 @@ bool RenderViewImpl::handleCurrentKeyboardEvent() {
return did_execute_command;
}
-WebKit::WebColorChooser* RenderViewImpl::createColorChooser(
- WebKit::WebColorChooserClient* client,
- const WebKit::WebColor& initial_color) {
+blink::WebColorChooser* RenderViewImpl::createColorChooser(
+ blink::WebColorChooserClient* client,
+ const blink::WebColor& initial_color,
+ const blink::WebVector<blink::WebColorSuggestion>& suggestions) {
RendererWebColorChooserImpl* color_chooser =
new RendererWebColorChooserImpl(this, client);
- color_chooser->Open(static_cast<SkColor>(initial_color));
+ std::vector<content::ColorSuggestion> color_suggestions;
+ for (size_t i = 0; i < suggestions.size(); i++) {
+ color_suggestions.push_back(content::ColorSuggestion(suggestions[i]));
+ }
+ color_chooser->Open(static_cast<SkColor>(initial_color), color_suggestions);
return color_chooser;
}
bool RenderViewImpl::runFileChooser(
- const WebKit::WebFileChooserParams& params,
+ const blink::WebFileChooserParams& params,
WebFileChooserCompletion* chooser_completion) {
// Do not open the file dialog in a hidden RenderView.
if (is_hidden())
@@ -2578,7 +2562,7 @@ void RenderViewImpl::runModalAlertDialog(WebFrame* frame,
const WebString& message) {
RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_ALERT,
message,
- string16(),
+ base::string16(),
frame->document().url(),
NULL);
}
@@ -2587,7 +2571,7 @@ bool RenderViewImpl::runModalConfirmDialog(WebFrame* frame,
const WebString& message) {
return RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_CONFIRM,
message,
- string16(),
+ base::string16(),
frame->document().url(),
NULL);
}
@@ -2596,7 +2580,7 @@ bool RenderViewImpl::runModalPromptDialog(WebFrame* frame,
const WebString& message,
const WebString& default_value,
WebString* actual_value) {
- string16 result;
+ base::string16 result;
bool ok = RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_PROMPT,
message,
default_value,
@@ -2612,7 +2596,7 @@ bool RenderViewImpl::runModalBeforeUnloadDialog(
bool is_reload = false;
WebDataSource* ds = frame->provisionalDataSource();
if (ds)
- is_reload = (ds->navigationType() == WebKit::WebNavigationTypeReload);
+ is_reload = (ds->navigationType() == blink::WebNavigationTypeReload);
return runModalBeforeUnloadDialog(frame, is_reload, message);
}
@@ -2624,16 +2608,56 @@ bool RenderViewImpl::runModalBeforeUnloadDialog(
if (is_swapped_out_)
return true;
+ // Don't allow further dialogs if we are waiting to swap out, since the
+ // PageGroupLoadDeferrer in our stack prevents it.
+ if (suppress_dialogs_until_swap_out_)
+ return false;
+
bool success = false;
// This is an ignored return value, but is included so we can accept the same
// response as RunJavaScriptMessage.
- string16 ignored_result;
+ base::string16 ignored_result;
SendAndRunNestedMessageLoop(new ViewHostMsg_RunBeforeUnloadConfirm(
routing_id_, frame->document().url(), message, is_reload,
&success, &ignored_result));
return success;
}
+void RenderViewImpl::showValidationMessage(
+ const blink::WebRect& anchor_in_root_view,
+ const blink::WebString& main_text,
+ const blink::WebString& sub_text,
+ blink::WebTextDirection hint) {
+ base::string16 wrapped_main_text = main_text;
+ base::string16 wrapped_sub_text = sub_text;
+ if (hint == blink::WebTextDirectionLeftToRight) {
+ wrapped_main_text =
+ base::i18n::GetDisplayStringInLTRDirectionality(wrapped_main_text);
+ if (!wrapped_sub_text.empty()) {
+ wrapped_sub_text =
+ base::i18n::GetDisplayStringInLTRDirectionality(wrapped_sub_text);
+ }
+ } else if (hint == blink::WebTextDirectionRightToLeft
+ && !base::i18n::IsRTL()) {
+ base::i18n::WrapStringWithRTLFormatting(&wrapped_main_text);
+ if (!wrapped_sub_text.empty()) {
+ base::i18n::WrapStringWithRTLFormatting(&wrapped_sub_text);
+ }
+ }
+ Send(new ViewHostMsg_ShowValidationMessage(
+ routing_id(), anchor_in_root_view, wrapped_main_text, wrapped_sub_text));
+}
+
+void RenderViewImpl::hideValidationMessage() {
+ Send(new ViewHostMsg_HideValidationMessage(routing_id()));
+}
+
+void RenderViewImpl::moveValidationMessage(
+ const blink::WebRect& anchor_in_root_view) {
+ Send(new ViewHostMsg_MoveValidationMessage(routing_id(),
+ anchor_in_root_view));
+}
+
void RenderViewImpl::showContextMenu(
WebFrame* frame, const WebContextMenuData& data) {
ContextMenuParams params = ContextMenuParamsBuilder::Build(data);
@@ -2642,6 +2666,7 @@ void RenderViewImpl::showContextMenu(
params.x = touch_editing_context_menu_location_.x();
params.y = touch_editing_context_menu_location_.y();
}
+ OnShowHostContextMenu(&params);
// Plugins, e.g. PDF, don't currently update the render view when their
// selected text changes, but the context menu params do contain the updated
@@ -2671,7 +2696,7 @@ void RenderViewImpl::showContextMenu(
// in the context menu.
// TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large
// data encoded images. We should have a way to save them.
- if (params.src_url.spec().size() > kMaxURLChars)
+ if (params.src_url.spec().size() > GetMaxURLChars())
params.src_url = GURL();
context_menu_node_ = data.node;
@@ -2711,9 +2736,9 @@ void RenderViewImpl::UpdateTargetURL(const GURL& url,
pending_target_url_ = latest_url;
target_url_status_ = TARGET_PENDING;
} else {
- // URLs larger than |kMaxURLChars| cannot be sent through IPC -
+ // URLs larger than |MaxURLChars()| cannot be sent through IPC -
// see |ParamTraits<GURL>|.
- if (latest_url.possibly_invalid_spec().size() > kMaxURLChars)
+ if (latest_url.possibly_invalid_spec().size() > GetMaxURLChars())
latest_url = GURL();
Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, latest_url));
target_url_ = latest_url;
@@ -2728,6 +2753,12 @@ gfx::RectF RenderViewImpl::ClientRectToPhysicalWindowRect(
return window_rect;
}
+int64 RenderViewImpl::GetLatencyComponentId() {
+ // Note: this must match the logic in RenderWidgetHostImpl.
+ return GetRoutingID() | (static_cast<int64>(
+ RenderThreadImpl::current()->renderer_process_id()) << 32);
+}
+
void RenderViewImpl::StartNavStateSyncTimerIfNecessary() {
// No need to update state if no page has committed yet.
if (page_id_ == -1)
@@ -2831,7 +2862,7 @@ int RenderViewImpl::historyForwardListCount() {
}
void RenderViewImpl::postAccessibilityEvent(
- const WebAXObject& obj, WebKit::WebAXEvent event) {
+ const WebAXObject& obj, blink::WebAXEvent event) {
if (renderer_accessibility_) {
renderer_accessibility_->HandleWebAccessibilityEvent(obj, event);
}
@@ -2844,7 +2875,7 @@ void RenderViewImpl::didUpdateInspectorSetting(const WebString& key,
value.utf8()));
}
-// WebKit::WebWidgetClient ----------------------------------------------------
+// blink::WebWidgetClient ----------------------------------------------------
void RenderViewImpl::didFocus() {
// TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed
@@ -2888,8 +2919,8 @@ void RenderViewImpl::show(WebNavigationPolicy policy) {
// We exempt background tabs for compat with older versions of Chrome.
// TODO(darin): This seems bogus. These should have a user gesture, so
// we probably don't need this check.
- if (policy != WebKit::WebNavigationPolicyNewBackgroundTab)
- policy = WebKit::WebNavigationPolicyNewPopup;
+ if (policy != blink::WebNavigationPolicyNewBackgroundTab)
+ policy = blink::WebNavigationPolicyNewPopup;
}
// NOTE: initial_pos_ may still have its default values at this point, but
@@ -2904,6 +2935,11 @@ void RenderViewImpl::show(WebNavigationPolicy policy) {
void RenderViewImpl::runModal() {
DCHECK(did_show_) << "should already have shown the view";
+ // Don't allow further dialogs if we are waiting to swap out, since the
+ // PageGroupLoadDeferrer in our stack prevents it.
+ if (suppress_dialogs_until_swap_out_)
+ return;
+
// We must keep WebKit's shared timer running in this case in order to allow
// showModalDialog to function properly.
//
@@ -2959,8 +2995,15 @@ void RenderViewImpl::didHandleGestureEvent(
const WebGestureEvent& event,
bool event_cancelled) {
RenderWidget::didHandleGestureEvent(event, event_cancelled);
- FOR_EACH_OBSERVER(RenderViewObserver, observers_,
- DidHandleGestureEvent(event));
+
+ if (event.type != blink::WebGestureEvent::GestureTap)
+ return;
+
+ blink::WebTextInputType text_input_type =
+ GetWebView()->textInputInfo().type;
+
+ Send(new ViewHostMsg_FocusedNodeTouched(
+ routing_id(), text_input_type != blink::WebTextInputTypeNone));
}
void RenderViewImpl::initializeLayerTreeView() {
@@ -2971,112 +3014,47 @@ void RenderViewImpl::initializeLayerTreeView() {
webview()->devToolsAgent()->setLayerTreeId(rwc->GetLayerTreeId());
}
-// WebKit::WebFrameClient -----------------------------------------------------
+// blink::WebFrameClient -----------------------------------------------------
WebMediaPlayer* RenderViewImpl::createMediaPlayer(
- WebFrame* frame, const WebKit::WebURL& url, WebMediaPlayerClient* client) {
+ WebFrame* frame, const blink::WebURL& url, WebMediaPlayerClient* client) {
+ NOTREACHED();
+ return NULL;
+}
+
+blink::WebMediaPlayer* RenderViewImpl::CreateMediaPlayer(
+ RenderFrame* render_frame,
+ blink::WebFrame* frame,
+ const blink::WebURL& url,
+ blink::WebMediaPlayerClient* client) {
FOR_EACH_OBSERVER(
RenderViewObserver, observers_, WillCreateMediaPlayer(frame, client));
- const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
-#if defined(ENABLE_WEBRTC)
- if (!InitializeMediaStreamClient())
- return NULL;
-
-#if !defined(GOOGLE_TV)
- if (media_stream_client_->IsMediaStream(url)) {
-#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
- bool found_neon =
- (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
- UMA_HISTOGRAM_BOOLEAN("Platform.WebRtcNEONFound", found_neon);
-#endif // defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
- return new WebMediaPlayerMS(
- frame, client, AsWeakPtr(), media_stream_client_, new RenderMediaLog());
- }
-#endif // !defined(GOOGLE_TV)
-#endif // defined(ENABLE_WEBRTC)
+ WebMediaPlayer* player = CreateWebMediaPlayerForMediaStream(frame, url,
+ client);
+ if (player)
+ return player;
#if defined(OS_ANDROID)
- GpuChannelHost* gpu_channel_host =
- RenderThreadImpl::current()->EstablishGpuChannelSync(
- CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE);
- if (!gpu_channel_host) {
- LOG(ERROR) << "Failed to establish GPU channel for media player";
- return NULL;
- }
-
- scoped_refptr<cc::ContextProvider> context_provider =
- RenderThreadImpl::current()->OffscreenContextProviderForMainThread();
- scoped_ptr<StreamTextureFactory> stream_texture_factory;
- if (UsingSynchronousRendererCompositor()) {
- SynchronousCompositorFactory* factory =
- SynchronousCompositorFactory::GetInstance();
- stream_texture_factory = factory->CreateStreamTextureFactory(routing_id_);
- } else {
- if (!context_provider.get()) {
- LOG(ERROR) << "Failed to get context3d for media player";
- return NULL;
- }
-
- stream_texture_factory.reset(new StreamTextureFactoryImpl(
- context_provider->Context3d(), gpu_channel_host, routing_id_));
- }
-
- if (!media_player_proxy_) {
- media_player_proxy_ = new WebMediaPlayerProxyAndroid(
- this, media_player_manager_.get());
- }
-
- scoped_ptr<WebMediaPlayerAndroid> web_media_player_android(
- new WebMediaPlayerAndroid(
- frame,
- client,
- AsWeakPtr(),
- media_player_manager_.get(),
- media_player_proxy_,
- stream_texture_factory.release(),
- RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(),
- new RenderMediaLog()));
-#if defined(ENABLE_WEBRTC) && defined(GOOGLE_TV)
- if (media_stream_client_->IsMediaStream(url)) {
- RTCVideoDecoderFactoryTv* factory = RenderThreadImpl::current()
- ->GetMediaStreamDependencyFactory()->decoder_factory_tv();
- // |media_stream_client| and |factory| outlives |web_media_player_android|.
- if (!factory->AcquireDemuxer() ||
- !web_media_player_android->InjectMediaStream(
- media_stream_client_,
- factory,
- base::Bind(
- base::IgnoreResult(&RTCVideoDecoderFactoryTv::ReleaseDemuxer),
- base::Unretained(factory)))) {
- LOG(ERROR) << "Failed to inject media stream.";
- return NULL;
- }
- }
-#endif // defined(ENABLE_WEBRTC) && defined(GOOGLE_TV)
- return web_media_player_android.release();
-#endif // defined(OS_ANDROID)
-
+ return CreateAndroidWebMediaPlayer(frame, url, client);
+#else
scoped_refptr<media::AudioRendererSink> sink;
- if (!cmd_line->HasSwitch(switches::kDisableAudio)) {
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableAudio)) {
sink = RenderThreadImpl::current()->GetAudioRendererMixerManager()->
CreateInput(routing_id_);
DVLOG(1) << "Using AudioRendererMixerManager-provided sink: " << sink.get();
}
- scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories =
- RenderThreadImpl::current()->GetGpuFactories(
- RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy());
-
WebMediaPlayerParams params(
RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(),
base::Bind(&ContentRendererClient::DeferMediaLoad,
base::Unretained(GetContentClient()->renderer()),
- static_cast<RenderView*>(this)),
+ static_cast<RenderFrame*>(render_frame)),
sink,
- gpu_factories,
+ RenderThreadImpl::current()->GetGpuFactories(),
new RenderMediaLog());
- return new WebMediaPlayerImpl(frame, client, AsWeakPtr(), params);
+ return new WebMediaPlayerImpl(this, frame, client, AsWeakPtr(), params);
+#endif // defined(OS_ANDROID)
}
WebCookieJar* RenderViewImpl::cookieJar(WebFrame* frame) {
@@ -3090,7 +3068,7 @@ void RenderViewImpl::didAccessInitialDocument(WebFrame* frame) {
Send(new ViewHostMsg_DidAccessInitialDocument(routing_id_));
}
-void RenderViewImpl::didDisownOpener(WebKit::WebFrame* frame) {
+void RenderViewImpl::didDisownOpener(blink::WebFrame* frame) {
// We only need to notify the browser if the active, top-level frame clears
// its opener. We can ignore cases where a swapped out frame clears its
// opener after hearing about it from the browser, and the browser does not
@@ -3110,6 +3088,15 @@ void RenderViewImpl::willClose(WebFrame* frame) {
FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameWillClose(frame));
}
+void RenderViewImpl::didMatchCSS(
+ WebFrame* frame,
+ const WebVector<WebString>& newly_matching_selectors,
+ const WebVector<WebString>& stopped_matching_selectors) {
+ FOR_EACH_OBSERVER(
+ RenderViewObserver, observers_,
+ DidMatchCSS(frame, newly_matching_selectors, stopped_matching_selectors));
+}
+
void RenderViewImpl::Repaint(const gfx::Size& size) {
OnRepaint(size);
}
@@ -3125,7 +3112,7 @@ void RenderViewImpl::ClearEditCommands() {
edit_commands_.clear();
}
-SSLStatus RenderViewImpl::GetSSLStatusOfFrame(WebKit::WebFrame* frame) const {
+SSLStatus RenderViewImpl::GetSSLStatusOfFrame(blink::WebFrame* frame) const {
std::string security_info;
if (frame && frame->dataSource())
security_info = frame->dataSource()->response().securityInfo();
@@ -3135,20 +3122,35 @@ SSLStatus RenderViewImpl::GetSSLStatusOfFrame(WebKit::WebFrame* frame) const {
&ssl_status.cert_id,
&ssl_status.cert_status,
&ssl_status.security_bits,
- &ssl_status.connection_status);
+ &ssl_status.connection_status,
+ &ssl_status.signed_certificate_timestamp_ids);
return ssl_status;
}
+const std::string& RenderViewImpl::GetAcceptLanguages() const {
+ return renderer_preferences_.accept_languages;
+}
+
WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
WebFrame* frame, WebDataSource::ExtraData* extraData,
const WebURLRequest& request, WebNavigationType type,
WebNavigationPolicy default_policy, bool is_redirect) {
+#ifdef OS_ANDROID
+ // The handlenavigation API is deprecated and will be removed once
+ // crbug.com/325351 is resolved.
if (request.url() != GURL(kSwappedOutURL) &&
- GetContentClient()->renderer()->HandleNavigation(frame, request, type,
- default_policy,
- is_redirect)) {
- return WebKit::WebNavigationPolicyIgnore;
+ GetContentClient()->renderer()->HandleNavigation(
+ this,
+ static_cast<DocumentState*>(extraData),
+ opener_id_,
+ frame,
+ request,
+ type,
+ default_policy,
+ is_redirect)) {
+ return blink::WebNavigationPolicyIgnore;
}
+#endif
Referrer referrer(GetReferrerFromRequest(frame, request));
@@ -3163,12 +3165,12 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
// fixing http://crbug.com/101395.
if (frame->parent() == NULL) {
OpenURL(frame, request.url(), referrer, default_policy);
- return WebKit::WebNavigationPolicyIgnore; // Suppress the load here.
+ return blink::WebNavigationPolicyIgnore; // Suppress the load here.
}
// We should otherwise ignore in-process iframe navigations, if they
// arrive just after we are swapped out.
- return WebKit::WebNavigationPolicyIgnore;
+ return blink::WebNavigationPolicyIgnore;
}
// Allow kSwappedOutURL to complete.
@@ -3207,22 +3209,23 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
if (!same_domain_or_host || frame_url.scheme() != url.scheme()) {
OpenURL(frame, url, referrer, default_policy);
- return WebKit::WebNavigationPolicyIgnore;
+ return blink::WebNavigationPolicyIgnore;
}
}
// If the browser is interested, then give it a chance to look at the request.
if (is_content_initiated) {
- bool is_form_post = ((type == WebKit::WebNavigationTypeFormSubmitted) ||
- (type == WebKit::WebNavigationTypeFormResubmitted)) &&
+ bool is_form_post = ((type == blink::WebNavigationTypeFormSubmitted) ||
+ (type == blink::WebNavigationTypeFormResubmitted)) &&
EqualsASCII(request.httpMethod(), "POST");
bool browser_handles_request =
renderer_preferences_.browser_handles_non_local_top_level_requests &&
IsNonLocalTopLevelNavigation(url, frame, type, is_form_post);
if (!browser_handles_request) {
- browser_handles_request =
- renderer_preferences_.browser_handles_all_top_level_requests &&
- IsTopLevelNavigation(frame);
+ browser_handles_request = IsTopLevelNavigation(frame) &&
+ (renderer_preferences_.browser_handles_all_top_level_requests ||
+ (renderer_preferences_.browser_handles_all_top_level_link_clicks &&
+ type == blink::WebNavigationTypeLinkClicked));
}
if (browser_handles_request) {
@@ -3231,7 +3234,7 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
page_id_ = -1;
last_page_id_sent_to_browser_ = -1;
OpenURL(frame, url, referrer, default_policy);
- return WebKit::WebNavigationPolicyIgnore; // Suppress the load here.
+ return blink::WebNavigationPolicyIgnore; // Suppress the load here.
}
}
@@ -3273,7 +3276,7 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
(cumulative_bindings & BINDINGS_POLICY_WEB_UI) ||
url.SchemeIs(kViewSourceScheme) ||
(frame->isViewSourceModeEnabled() &&
- type != WebKit::WebNavigationTypeReload);
+ type != blink::WebNavigationTypeReload);
if (!should_fork && url.SchemeIs(chrome::kFileScheme)) {
// Fork non-file to file opens. Check the opener URL if this is the
@@ -3295,7 +3298,7 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
if (should_fork) {
OpenURL(
frame, url, send_referrer ? referrer : Referrer(), default_policy);
- return WebKit::WebNavigationPolicyIgnore; // Suppress the load here.
+ return blink::WebNavigationPolicyIgnore; // Suppress the load here.
}
}
@@ -3327,14 +3330,14 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
// Must not have issued the request from this page.
is_content_initiated &&
// Must be targeted at the current tab.
- default_policy == WebKit::WebNavigationPolicyCurrentTab &&
+ default_policy == blink::WebNavigationPolicyCurrentTab &&
// Must be a JavaScript navigation, which appears as "other".
- type == WebKit::WebNavigationTypeOther;
+ type == blink::WebNavigationTypeOther;
if (is_fork) {
// Open the URL via the browser, not via WebKit.
OpenURL(frame, url, Referrer(), default_policy);
- return WebKit::WebNavigationPolicyIgnore;
+ return blink::WebNavigationPolicyIgnore;
}
return default_policy;
@@ -3348,8 +3351,8 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
request, type, default_policy, is_redirect);
}
-void RenderViewImpl::willSendSubmitEvent(WebKit::WebFrame* frame,
- const WebKit::WebFormElement& form) {
+void RenderViewImpl::willSendSubmitEvent(blink::WebFrame* frame,
+ const blink::WebFormElement& form) {
FOR_EACH_OBSERVER(
RenderViewObserver, observers_, WillSendSubmitEvent(frame, form));
}
@@ -3363,6 +3366,15 @@ void RenderViewImpl::willSubmitForm(WebFrame* frame,
void RenderViewImpl::didCreateDataSource(WebFrame* frame, WebDataSource* ds) {
bool content_initiated = !pending_navigation_params_.get();
+ // Make sure any previous redirect URLs end up in our new data source.
+ if (pending_navigation_params_.get()) {
+ for (std::vector<GURL>::const_iterator i =
+ pending_navigation_params_->redirects.begin();
+ i != pending_navigation_params_->redirects.end(); ++i) {
+ ds->appendRedirect(*i);
+ }
+ }
+
DocumentState* document_state = DocumentState::FromDataSource(ds);
if (!document_state) {
document_state = new DocumentState;
@@ -3492,6 +3504,8 @@ NavigationState* RenderViewImpl::CreateNavigationStateFromPending() {
params.pending_history_list_offset,
params.should_clear_history_list,
params.transition);
+ navigation_state->set_should_replace_current_entry(
+ params.should_replace_current_entry);
navigation_state->set_transferred_request_child_id(
params.transferred_request_child_id);
navigation_state->set_transferred_request_request_id(
@@ -3506,11 +3520,8 @@ NavigationState* RenderViewImpl::CreateNavigationStateFromPending() {
void RenderViewImpl::ProcessViewLayoutFlags(const CommandLine& command_line) {
bool enable_viewport =
- command_line.HasSwitch(switches::kEnableViewport);
- bool enable_fixed_layout =
- command_line.HasSwitch(switches::kEnableFixedLayout);
-
- webview()->enableFixedLayoutMode(enable_fixed_layout || enable_viewport);
+ command_line.HasSwitch(switches::kEnableViewport) ||
+ command_line.HasSwitch(switches::kEnableViewportMeta);
// If viewport tag is enabled, then the WebKit side will take care
// of setting the fixed layout size and page scale limits.
@@ -3520,65 +3531,13 @@ void RenderViewImpl::ProcessViewLayoutFlags(const CommandLine& command_line) {
// When navigating to a new page, reset the page scale factor to be 1.0.
webview()->setInitialPageScaleOverride(1.f);
- if (enable_fixed_layout) {
- std::string str =
- command_line.GetSwitchValueASCII(switches::kEnableFixedLayout);
- std::vector<std::string> tokens;
- base::SplitString(str, ',', &tokens);
- if (tokens.size() == 2) {
- int width, height;
- if (base::StringToInt(tokens[0], &width) &&
- base::StringToInt(tokens[1], &height))
- webview()->setFixedLayoutSize(WebSize(width, height));
- }
- }
float maxPageScaleFactor =
command_line.HasSwitch(switches::kEnablePinch) ? 4.f : 1.f ;
webview()->setPageScaleFactorLimits(1, maxPageScaleFactor);
}
+// TODO(nasko): Remove this method once WebTestProxy in Blink is fixed.
void RenderViewImpl::didStartProvisionalLoad(WebFrame* frame) {
- WebDataSource* ds = frame->provisionalDataSource();
-
- // In fast/loader/stop-provisional-loads.html, we abort the load before this
- // callback is invoked.
- if (!ds)
- return;
-
- DocumentState* document_state = DocumentState::FromDataSource(ds);
-
- // We should only navigate to swappedout:// when is_swapped_out_ is true.
- CHECK((ds->request().url() != GURL(kSwappedOutURL)) ||
- is_swapped_out_) << "Heard swappedout:// when not swapped out.";
-
- // Update the request time if WebKit has better knowledge of it.
- if (document_state->request_time().is_null()) {
- double event_time = ds->triggeringEventTime();
- if (event_time != 0.0)
- document_state->set_request_time(Time::FromDoubleT(event_time));
- }
-
- // Start time is only set after request time.
- document_state->set_start_load_time(Time::Now());
-
- bool is_top_most = !frame->parent();
- if (is_top_most) {
- navigation_gesture_ = WebUserGestureIndicator::isProcessingUserGesture() ?
- NavigationGestureUser : NavigationGestureAuto;
- } else if (frame->parent()->isLoading()) {
- // Take note of AUTO_SUBFRAME loads here, so that we can know how to
- // load an error page. See didFailProvisionalLoad.
- document_state->navigation_state()->set_transition_type(
- PAGE_TRANSITION_AUTO_SUBFRAME);
- }
-
- FOR_EACH_OBSERVER(
- RenderViewObserver, observers_, DidStartProvisionalLoad(frame));
-
- Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
- routing_id_, frame->identifier(),
- frame->parent() ? frame->parent()->identifier() : -1,
- is_top_most, ds->request().url()));
}
void RenderViewImpl::didReceiveServerRedirectForProvisionalLoad(
@@ -3622,12 +3581,14 @@ void RenderViewImpl::didFailProvisionalLoad(WebFrame* frame,
ViewHostMsg_DidFailProvisionalLoadWithError_Params params;
params.frame_id = frame->identifier();
+ params.frame_unique_name = frame->uniqueName();
params.is_main_frame = !frame->parent();
params.error_code = error.reason;
GetContentClient()->renderer()->GetNavigationErrorStrings(
frame,
failed_request,
error,
+ renderer_preferences_.accept_languages,
NULL,
&params.error_description);
params.url = error.unreachableURL;
@@ -3671,6 +3632,8 @@ void RenderViewImpl::didFailProvisionalLoad(WebFrame* frame,
// AUTO_SUBFRAME loads should always be treated as loads that do not advance
// the page id.
//
+ // TODO(davidben): This should also take the failed navigation's replacement
+ // state into account, if a location.replace() failed.
bool replace =
navigation_state->pending_page_id() != -1 ||
PageTransitionCoreTypeIs(navigation_state->transition_type(),
@@ -3690,6 +3653,7 @@ void RenderViewImpl::didFailProvisionalLoad(WebFrame* frame,
navigation_state->transition_type();
pending_navigation_params_->request_time =
document_state->request_time();
+ pending_navigation_params_->should_replace_current_entry = replace;
}
// Provide the user with a more helpful error page?
@@ -3808,14 +3772,8 @@ void RenderViewImpl::didClearWindowObject(WebFrame* frame) {
"domAutomationController");
}
- if (enabled_bindings_ & BINDINGS_POLICY_STATS_COLLECTION) {
- if (!stats_collection_controller_.get())
- stats_collection_controller_.reset(new StatsCollectionController());
- stats_collection_controller_->set_message_sender(
- static_cast<RenderView*>(this));
- stats_collection_controller_->BindToJavascript(frame,
- "statsCollectionController");
- }
+ if (enabled_bindings_ & BINDINGS_POLICY_STATS_COLLECTION)
+ StatsCollectionController::Install(frame);
}
void RenderViewImpl::didCreateDocumentElement(WebFrame* frame) {
@@ -3877,11 +3835,12 @@ void RenderViewImpl::didFailLoad(WebFrame* frame, const WebURLError& error) {
FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidFailLoad(frame, error));
const WebURLRequest& failed_request = ds->request();
- string16 error_description;
+ base::string16 error_description;
GetContentClient()->renderer()->GetNavigationErrorStrings(
frame,
failed_request,
error,
+ renderer_preferences_.accept_languages,
NULL,
&error_description);
Send(new ViewHostMsg_DidFailLoadWithError(routing_id_,
@@ -4134,7 +4093,7 @@ void RenderViewImpl::didChangeScrollOffset(WebFrame* frame) {
RenderViewObserver, observers_, DidChangeScrollOffset(frame));
}
-void RenderViewImpl::willInsertBody(WebKit::WebFrame* frame) {
+void RenderViewImpl::willInsertBody(blink::WebFrame* frame) {
NOTREACHED();
}
@@ -4178,11 +4137,11 @@ void RenderViewImpl::SendFindReply(int request_id,
// static
bool RenderViewImpl::ShouldUpdateSelectionTextFromContextMenuParams(
- const string16& selection_text,
+ const base::string16& selection_text,
size_t selection_text_offset,
const gfx::Range& selection_range,
const ContextMenuParams& params) {
- string16 trimmed_selection_text;
+ base::string16 trimmed_selection_text;
if (!selection_text.empty() && !selection_range.is_empty()) {
const int start = selection_range.GetMin() - selection_text_offset;
const size_t length = selection_range.length();
@@ -4191,7 +4150,7 @@ bool RenderViewImpl::ShouldUpdateSelectionTextFromContextMenuParams(
&trimmed_selection_text);
}
}
- string16 trimmed_params_text;
+ base::string16 trimmed_params_text;
TrimWhitespace(params.selection_text, TRIM_ALL, &trimmed_params_text);
return trimmed_params_text != trimmed_selection_text;
}
@@ -4199,17 +4158,13 @@ bool RenderViewImpl::ShouldUpdateSelectionTextFromContextMenuParams(
void RenderViewImpl::reportFindInPageMatchCount(int request_id,
int count,
bool final_update) {
- // TODO(jam): switch PepperPluginInstanceImpl to take a RenderFrame
- main_render_frame_->reportFindInPageMatchCount(
- request_id, count, final_update);
+ NOTREACHED();
}
void RenderViewImpl::reportFindInPageSelection(int request_id,
int active_match_ordinal,
const WebRect& selection_rect) {
- // TODO(jam): switch PepperPluginInstanceImpl to take a RenderFrame
- main_render_frame_->reportFindInPageSelection(
- request_id, active_match_ordinal, selection_rect);
+ NOTREACHED();
}
void RenderViewImpl::requestStorageQuota(
@@ -4221,10 +4176,10 @@ void RenderViewImpl::requestStorageQuota(
}
bool RenderViewImpl::willCheckAndDispatchMessageEvent(
- WebKit::WebFrame* sourceFrame,
- WebKit::WebFrame* targetFrame,
- WebKit::WebSecurityOrigin target_origin,
- WebKit::WebDOMMessageEvent event) {
+ blink::WebFrame* sourceFrame,
+ blink::WebFrame* targetFrame,
+ blink::WebSecurityOrigin target_origin,
+ blink::WebDOMMessageEvent event) {
if (!is_swapped_out_)
return false;
@@ -4234,6 +4189,20 @@ bool RenderViewImpl::willCheckAndDispatchMessageEvent(
if (!target_origin.isNull())
params.target_origin = target_origin.toString();
+ blink::WebMessagePortChannelArray channels = event.releaseChannels();
+ if (!channels.isEmpty()) {
+ std::vector<int> message_port_ids(channels.size());
+ // Extract the port IDs from the channel array.
+ for (size_t i = 0; i < channels.size(); ++i) {
+ WebMessagePortChannelImpl* webchannel =
+ static_cast<WebMessagePortChannelImpl*>(channels[i]);
+ message_port_ids[i] = webchannel->message_port_id();
+ webchannel->QueueMessages();
+ DCHECK_NE(message_port_ids[i], MSG_ROUTING_NONE);
+ }
+ params.message_port_ids = message_port_ids;
+ }
+
// Include the routing ID for the source frame (if one exists), which the
// browser process will translate into the routing ID for the equivalent
// frame in the target process.
@@ -4254,24 +4223,24 @@ void RenderViewImpl::willOpenSocketStream(
}
void RenderViewImpl::willStartUsingPeerConnectionHandler(
- WebKit::WebFrame* frame, WebKit::WebRTCPeerConnectionHandler* handler) {
+ blink::WebFrame* frame, blink::WebRTCPeerConnectionHandler* handler) {
NOTREACHED();
}
-WebKit::WebString RenderViewImpl::acceptLanguages() {
+blink::WebString RenderViewImpl::acceptLanguages() {
return WebString::fromUTF8(renderer_preferences_.accept_languages);
}
-WebKit::WebString RenderViewImpl::userAgentOverride(
- WebKit::WebFrame* frame,
- const WebKit::WebURL& url) {
+blink::WebString RenderViewImpl::userAgentOverride(
+ blink::WebFrame* frame,
+ const blink::WebURL& url) {
NOTREACHED();
- return WebKit::WebString();
+ return blink::WebString();
}
WebString RenderViewImpl::doNotTrackValue(WebFrame* frame) {
NOTREACHED();
- return WebKit::WebString();
+ return blink::WebString();
}
bool RenderViewImpl::allowWebGL(WebFrame* frame, bool default_value) {
@@ -4280,12 +4249,12 @@ bool RenderViewImpl::allowWebGL(WebFrame* frame, bool default_value) {
}
void RenderViewImpl::didLoseWebGLContext(
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
int arb_robustness_status_code) {
NOTREACHED();
}
-// WebKit::WebPageSerializerClient implementation ------------------------------
+// blink::WebPageSerializerClient implementation ------------------------------
void RenderViewImpl::didSerializeDataForFrame(
const WebURL& frame_url,
@@ -4304,6 +4273,10 @@ bool RenderViewImpl::Send(IPC::Message* message) {
return RenderWidget::Send(message);
}
+RenderFrame* RenderViewImpl::GetMainRenderFrame() {
+ return main_render_frame_.get();
+}
+
int RenderViewImpl::GetRoutingID() const {
return routing_id_;
}
@@ -4324,11 +4297,11 @@ void RenderViewImpl::SetWebkitPreferences(const WebPreferences& preferences) {
OnUpdateWebPreferences(preferences);
}
-WebKit::WebView* RenderViewImpl::GetWebView() {
+blink::WebView* RenderViewImpl::GetWebView() {
return webview();
}
-WebKit::WebNode RenderViewImpl::GetFocusedNode() const {
+blink::WebNode RenderViewImpl::GetFocusedNode() const {
if (!webview())
return WebNode();
WebFrame* focused_frame = webview()->focusedFrame();
@@ -4341,7 +4314,7 @@ WebKit::WebNode RenderViewImpl::GetFocusedNode() const {
return WebNode();
}
-WebKit::WebNode RenderViewImpl::GetContextMenuNode() const {
+blink::WebNode RenderViewImpl::GetContextMenuNode() const {
return context_menu_node_;
}
@@ -4370,27 +4343,8 @@ bool RenderViewImpl::IsEditableNode(const WebNode& node) const {
return false;
}
-WebKit::WebPlugin* RenderViewImpl::CreatePlugin(
- WebKit::WebFrame* frame,
- const WebPluginInfo& info,
- const WebKit::WebPluginParams& params) {
-#if defined(ENABLE_PLUGINS)
- bool pepper_plugin_was_registered = false;
- scoped_refptr<PluginModule> pepper_module(PluginModule::Create(
- this, info, &pepper_plugin_was_registered));
- if (pepper_plugin_was_registered) {
- if (pepper_module.get())
- return new PepperWebPluginImpl(pepper_module.get(), params, AsWeakPtr());
- }
-
- return new WebPluginImpl(frame, params, info.path, AsWeakPtr());
-#else
- return NULL;
-#endif
-}
-
-void RenderViewImpl::EvaluateScript(const string16& frame_xpath,
- const string16& jscript,
+void RenderViewImpl::EvaluateScript(const base::string16& frame_xpath,
+ const base::string16& jscript,
int id,
bool notify_result) {
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
@@ -4447,22 +4401,15 @@ void RenderViewImpl::CancelContextMenu(int request_id) {
pending_context_menus_.Remove(request_id);
}
-WebKit::WebPageVisibilityState RenderViewImpl::GetVisibilityState() const {
+blink::WebPageVisibilityState RenderViewImpl::GetVisibilityState() const {
return visibilityState();
}
-void RenderViewImpl::RunModalAlertDialog(WebKit::WebFrame* frame,
- const WebKit::WebString& message) {
+void RenderViewImpl::RunModalAlertDialog(blink::WebFrame* frame,
+ const blink::WebString& message) {
return runModalAlertDialog(frame, message);
}
-void RenderViewImpl::LoadURLExternally(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationPolicy policy) {
- main_render_frame_->loadURLExternally(frame, request, policy);
-}
-
void RenderViewImpl::DidStartLoading() {
didStartLoading();
}
@@ -4471,7 +4418,7 @@ void RenderViewImpl::DidStopLoading() {
didStopLoading();
}
-void RenderViewImpl::DidPlay(WebKit::WebMediaPlayer* player) {
+void RenderViewImpl::DidPlay(blink::WebMediaPlayer* player) {
Send(new ViewHostMsg_MediaNotification(routing_id_,
reinterpret_cast<int64>(player),
player->hasVideo(),
@@ -4479,7 +4426,7 @@ void RenderViewImpl::DidPlay(WebKit::WebMediaPlayer* player) {
true));
}
-void RenderViewImpl::DidPause(WebKit::WebMediaPlayer* player) {
+void RenderViewImpl::DidPause(blink::WebMediaPlayer* player) {
Send(new ViewHostMsg_MediaNotification(routing_id_,
reinterpret_cast<int64>(player),
player->hasVideo(),
@@ -4487,7 +4434,7 @@ void RenderViewImpl::DidPause(WebKit::WebMediaPlayer* player) {
false));
}
-void RenderViewImpl::PlayerGone(WebKit::WebMediaPlayer* player) {
+void RenderViewImpl::PlayerGone(blink::WebMediaPlayer* player) {
DidPause(player);
}
@@ -4504,7 +4451,7 @@ void RenderViewImpl::SyncSelectionIfRequired() {
if (!frame)
return;
- string16 text;
+ base::string16 text;
size_t offset;
gfx::Range range;
#if defined(ENABLE_PLUGINS)
@@ -4521,7 +4468,7 @@ void RenderViewImpl::SyncSelectionIfRequired() {
range = gfx::Range(location, location + length);
- if (webview()->textInputInfo().type != WebKit::WebTextInputTypeNone) {
+ if (webview()->textInputInfo().type != blink::WebTextInputTypeNone) {
// If current focused element is editable, we will send 100 more chars
// before and after selection. It is for input method surrounding text
// feature.
@@ -4580,6 +4527,8 @@ GURL RenderViewImpl::GetAlternateErrorPageURL(const GURL& failed_url,
remove_params.ClearQuery();
remove_params.ClearRef();
const GURL url_to_send = failed_url.ReplaceComponents(remove_params);
+ // TODO(yuusuke): change to net::FormatUrl when link doctor
+ // becomes unicode-capable.
std::string spec_to_send = url_to_send.spec();
// Notify link doctor of the url truncation by sending of "?" at the end.
if (failed_url.has_query())
@@ -4615,7 +4564,7 @@ GURL RenderViewImpl::GetAlternateErrorPageURL(const GURL& failed_url,
return url;
}
-GURL RenderViewImpl::GetLoadingUrl(WebKit::WebFrame* frame) const {
+GURL RenderViewImpl::GetLoadingUrl(blink::WebFrame* frame) const {
WebDataSource* ds = frame->dataSource();
if (ds->hasUnreachableURL())
return ds->unreachableURL();
@@ -4624,12 +4573,12 @@ GURL RenderViewImpl::GetLoadingUrl(WebKit::WebFrame* frame) const {
return request.url();
}
-WebKit::WebPlugin* RenderViewImpl::GetWebPluginFromPluginDocument() {
+blink::WebPlugin* RenderViewImpl::GetWebPluginFromPluginDocument() {
return webview()->mainFrame()->document().to<WebPluginDocument>().plugin();
}
void RenderViewImpl::OnFind(int request_id,
- const string16& search_text,
+ const base::string16& search_text,
const WebFindOptions& options) {
WebFrame* main_frame = webview()->mainFrame();
@@ -4915,7 +4864,7 @@ void RenderViewImpl::OnResetPageEncodingToDefault() {
webview()->setPageEncoding(no_encoding);
}
-WebFrame* RenderViewImpl::GetChildFrame(const string16& xpath) const {
+WebFrame* RenderViewImpl::GetChildFrame(const base::string16& xpath) const {
if (xpath.empty())
return webview()->mainFrame();
@@ -4924,11 +4873,11 @@ WebFrame* RenderViewImpl::GetChildFrame(const string16& xpath) const {
// Example, /html/body/table/tbody/tr/td/iframe\n/frameset/frame[0]
// should break into 2 xpaths
// /html/body/table/tbody/tr/td/iframe & /frameset/frame[0]
- std::vector<string16> xpaths;
+ std::vector<base::string16> xpaths;
base::SplitString(xpath, '\n', &xpaths);
WebFrame* frame = webview()->mainFrame();
- for (std::vector<string16>::const_iterator i = xpaths.begin();
+ for (std::vector<base::string16>::const_iterator i = xpaths.begin();
frame && i != xpaths.end(); ++i) {
frame = frame->findChildByExpression(*i);
}
@@ -4936,8 +4885,8 @@ WebFrame* RenderViewImpl::GetChildFrame(const string16& xpath) const {
return frame;
}
-void RenderViewImpl::OnScriptEvalRequest(const string16& frame_xpath,
- const string16& jscript,
+void RenderViewImpl::OnScriptEvalRequest(const base::string16& frame_xpath,
+ const base::string16& jscript,
int id,
bool notify_result) {
TRACE_EVENT_INSTANT0("test_tracing", "OnScriptEvalRequest",
@@ -4958,6 +4907,18 @@ void RenderViewImpl::OnPostMessageEvent(
source_frame = source_view->webview()->mainFrame();
}
+ // If the message contained MessagePorts, create the corresponding endpoints.
+ DCHECK_EQ(params.message_port_ids.size(), params.new_routing_ids.size());
+ blink::WebMessagePortChannelArray channels(params.message_port_ids.size());
+ for (size_t i = 0;
+ i < params.message_port_ids.size() && i < params.new_routing_ids.size();
+ ++i) {
+ channels[i] =
+ new WebMessagePortChannelImpl(params.new_routing_ids[i],
+ params.message_port_ids[i],
+ base::MessageLoopProxy::current().get());
+ }
+
// Create an event with the message. The final parameter to initMessageEvent
// is the last event ID, which is not used with postMessage.
WebDOMEvent event = frame->document().createEvent("MessageEvent");
@@ -4966,7 +4927,7 @@ void RenderViewImpl::OnPostMessageEvent(
// |canBubble| and |cancellable| are always false
false, false,
WebSerializedScriptValue::fromString(params.data),
- params.source_origin, source_frame, "");
+ params.source_origin, source_frame, "", channels);
// We must pass in the target_origin to do the security check on this side,
// since it may have changed since the original postMessage call was made.
@@ -4978,7 +4939,7 @@ void RenderViewImpl::OnPostMessageEvent(
frame->dispatchMessageEventWithOriginCheck(target_origin, msg_event);
}
-void RenderViewImpl::OnCSSInsertRequest(const string16& frame_xpath,
+void RenderViewImpl::OnCSSInsertRequest(const base::string16& frame_xpath,
const std::string& css) {
WebFrame* frame = GetChildFrame(frame_xpath);
if (!frame)
@@ -5182,9 +5143,9 @@ void RenderViewImpl::OnSetRendererPrefs(
#if defined(USE_DEFAULT_RENDER_THEME) || defined(TOOLKIT_GTK)
if (renderer_prefs.use_custom_colors) {
- WebColorName name = WebKit::WebColorWebkitFocusRingColor;
- WebKit::setNamedColors(&name, &renderer_prefs.focus_ring_color, 1);
- WebKit::setCaretBlinkInterval(renderer_prefs.caret_blink_interval);
+ WebColorName name = blink::WebColorWebkitFocusRingColor;
+ blink::setNamedColors(&name, &renderer_prefs.focus_ring_color, 1);
+ blink::setCaretBlinkInterval(renderer_prefs.caret_blink_interval);
#if defined(TOOLKIT_GTK)
ui::NativeTheme::instance()->SetScrollbarColors(
renderer_prefs.thumb_inactive_color,
@@ -5193,12 +5154,6 @@ void RenderViewImpl::OnSetRendererPrefs(
#endif // defined(TOOLKIT_GTK)
if (webview()) {
-#if defined(TOOLKIT_GTK)
- webview()->setScrollbarColors(
- renderer_prefs.thumb_inactive_color,
- renderer_prefs.thumb_active_color,
- renderer_prefs.track_color);
-#endif // defined(TOOLKIT_GTK)
webview()->setSelectionColors(
renderer_prefs.active_selection_bg_color,
renderer_prefs.active_selection_fg_color,
@@ -5232,6 +5187,7 @@ void RenderViewImpl::OnMediaPlayerActionAt(const gfx::Point& location,
}
void RenderViewImpl::OnOrientationChangeEvent(int orientation) {
+ // Screen has rotated. 0 = default (portrait), 90 = one turn right, and so on.
FOR_EACH_OBSERVER(RenderViewObserver,
observers_,
OrientationChangeEvent(orientation));
@@ -5249,7 +5205,7 @@ void RenderViewImpl::OnGetAllSavableResourceLinksForCurrentPage(
// Prepare list to storage all savable resource links.
std::vector<GURL> resources_list;
std::vector<GURL> referrer_urls_list;
- std::vector<WebKit::WebReferrerPolicy> referrer_policies_list;
+ std::vector<blink::WebReferrerPolicy> referrer_policies_list;
std::vector<GURL> frames_list;
SavableResourcesResult result(&resources_list,
&referrer_urls_list,
@@ -5311,6 +5267,11 @@ void RenderViewImpl::OnShouldClose() {
before_unload_end_time));
}
+void RenderViewImpl::OnSuppressDialogsUntilSwapOut() {
+ // Don't show any more dialogs until we finish OnSwapOut.
+ suppress_dialogs_until_swap_out_ = true;
+}
+
void RenderViewImpl::OnSwapOut() {
// Only run unload if we're not swapped out yet, but send the ack either way.
if (!is_swapped_out_) {
@@ -5341,13 +5302,16 @@ void RenderViewImpl::OnSwapOut() {
// Let WebKit know that this view is hidden so it can drop resources and
// stop compositing.
- webview()->setVisibilityState(WebKit::WebPageVisibilityStateHidden, false);
+ webview()->setVisibilityState(blink::WebPageVisibilityStateHidden, false);
}
+ // It is now safe to show modal dialogs again.
+ suppress_dialogs_until_swap_out_ = false;
+
Send(new ViewHostMsg_SwapOut_ACK(routing_id_));
}
-void RenderViewImpl::NavigateToSwappedOutURL(WebKit::WebFrame* frame) {
+void RenderViewImpl::NavigateToSwappedOutURL(blink::WebFrame* frame) {
// We use loadRequest instead of loadHTMLString because the former commits
// synchronously. Otherwise a new navigation can interrupt the navigation
// to kSwappedOutURL. If that happens to be to the page we had been
@@ -5464,57 +5428,15 @@ void RenderViewImpl::OnResize(const ViewMsg_Resize_Params& params) {
RenderWidget::OnResize(params);
}
-void RenderViewImpl::WillInitiatePaint() {
-#if defined(ENABLE_PLUGINS)
- // Notify all of our instances that we started painting. This is used for
- // internal bookkeeping only, so we know that the set can not change under
- // us.
- for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
- i != active_pepper_instances_.end(); ++i)
- (*i)->ViewWillInitiatePaint();
-#endif
-}
-
void RenderViewImpl::DidInitiatePaint() {
#if defined(ENABLE_PLUGINS)
- // Notify all instances that we painted. The same caveats apply as for
- // ViewFlushedPaint regarding instances closing themselves, so we take
- // similar precautions.
- PepperPluginSet plugins = active_pepper_instances_;
- for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) {
- if (active_pepper_instances_.find(*i) != active_pepper_instances_.end())
- (*i)->ViewInitiatedPaint();
- }
+ main_render_frame_->DidInitiatePaint();
#endif
}
void RenderViewImpl::DidFlushPaint() {
#if defined(ENABLE_PLUGINS)
- // Notify all instances that we flushed. This will call into the plugin, and
- // we it may ask to close itself as a result. This will, in turn, modify our
- // set, possibly invalidating the iterator. So we iterate on a copy that
- // won't change out from under us.
- PepperPluginSet plugins = active_pepper_instances_;
- for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) {
- // The copy above makes sure our iterator is never invalid if some plugins
- // are destroyed. But some plugin may decide to close all of its views in
- // response to a paint in one of them, so we need to make sure each one is
- // still "current" before using it.
- //
- // It's possible that a plugin was destroyed, but another one was created
- // with the same address. In this case, we'll call ViewFlushedPaint on that
- // new plugin. But that's OK for this particular case since we're just
- // notifying all of our instances that the view flushed, and the new one is
- // one of our instances.
- //
- // What about the case where a new one is created in a callback at a new
- // address and we don't issue the callback? We're still OK since this
- // callback is used for flush callbacks and we could not have possibly
- // started a new paint (ViewWillInitiatePaint) for the new plugin while
- // processing a previous paint for an existing one.
- if (active_pepper_instances_.find(*i) != active_pepper_instances_.end())
- (*i)->ViewFlushedPaint();
- }
+ main_render_frame_->DidFlushPaint();
#endif
// If the RenderWidget is closing down then early-exit, otherwise we'll crash.
@@ -5558,16 +5480,8 @@ PepperPluginInstanceImpl* RenderViewImpl::GetBitmapForOptimizedPluginPaint(
gfx::Rect* clip,
float* scale_factor) {
#if defined(ENABLE_PLUGINS)
- for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
- i != active_pepper_instances_.end(); ++i) {
- PepperPluginInstanceImpl* instance = *i;
- // In Flash fullscreen , the plugin contents should be painted onto the
- // fullscreen widget instead of the web page.
- if (!instance->FlashIsFullscreenOrPending() &&
- instance->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, location,
- clip, scale_factor))
- return *i;
- }
+ return main_render_frame_->GetBitmapForOptimizedPluginPaint(
+ paint_bounds, dib, location, clip, scale_factor);
#endif
return NULL;
}
@@ -5644,7 +5558,7 @@ void RenderViewImpl::OnWindowFrameChanged(const gfx::Rect& window_frame,
#endif
}
-void RenderViewImpl::OnPluginImeCompositionCompleted(const string16& text,
+void RenderViewImpl::OnPluginImeCompositionCompleted(const base::string16& text,
int plugin_id) {
// WebPluginDelegateProxy is responsible for figuring out if this event
// applies to it or not, so inform all the delegates.
@@ -5668,7 +5582,7 @@ void RenderViewImpl::DidHandleKeyEvent() {
ClearEditCommands();
}
-bool RenderViewImpl::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) {
+bool RenderViewImpl::WillHandleMouseEvent(const blink::WebMouseEvent& event) {
context_menu_source_type_ = ui::MENU_SOURCE_MOUSE;
possible_drag_event_info_.event_source =
ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE;
@@ -5676,14 +5590,7 @@ bool RenderViewImpl::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) {
gfx::Point(event.globalX, event.globalY);
#if defined(ENABLE_PLUGINS)
- // This method is called for every mouse event that the render view receives.
- // And then the mouse event is forwarded to WebKit, which dispatches it to the
- // event target. Potentially a Pepper plugin will receive the event.
- // In order to tell whether a plugin gets the last mouse event and which it
- // is, we set |pepper_last_mouse_event_target_| to NULL here. If a plugin gets
- // the event, it will notify us via DidReceiveMouseEvent() and set itself as
- // |pepper_last_mouse_event_target_|.
- pepper_last_mouse_event_target_ = NULL;
+ main_render_frame_->WillHandleMouseEvent(event);
#endif
// If the mouse is locked, only the current owner of the mouse lock can
@@ -5691,13 +5598,13 @@ bool RenderViewImpl::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) {
return mouse_lock_dispatcher_->WillHandleMouseEvent(event);
}
-bool RenderViewImpl::WillHandleKeyEvent(const WebKit::WebKeyboardEvent& event) {
+bool RenderViewImpl::WillHandleKeyEvent(const blink::WebKeyboardEvent& event) {
context_menu_source_type_ = ui::MENU_SOURCE_KEYBOARD;
return false;
}
bool RenderViewImpl::WillHandleGestureEvent(
- const WebKit::WebGestureEvent& event) {
+ const blink::WebGestureEvent& event) {
context_menu_source_type_ = ui::MENU_SOURCE_TOUCH;
possible_drag_event_info_.event_source =
ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH;
@@ -5732,10 +5639,7 @@ void RenderViewImpl::OnWasHidden() {
webview()->setVisibilityState(visibilityState(), false);
#if defined(ENABLE_PLUGINS)
- // Inform PPAPI plugins that their page is no longer visible.
- for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
- i != active_pepper_instances_.end(); ++i)
- (*i)->PageVisibilityChanged(false);
+ main_render_frame_->PageVisibilityChanged(false);
#if defined(OS_MACOSX)
// Inform NPAPI plugins that their container is no longer visible.
@@ -5760,10 +5664,7 @@ void RenderViewImpl::OnWasShown(bool needs_repainting) {
webview()->setVisibilityState(visibilityState(), false);
#if defined(ENABLE_PLUGINS)
- // Inform PPAPI plugins that their page is visible.
- for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
- i != active_pepper_instances_.end(); ++i)
- (*i)->PageVisibilityChanged(true);
+ main_render_frame_->PageVisibilityChanged(true);
#if defined(OS_MACOSX)
// Inform NPAPI plugins that their container is now visible.
@@ -5806,10 +5707,7 @@ void RenderViewImpl::OnSetFocus(bool enable) {
(*plugin_it)->SetContentAreaFocus(enable);
}
}
- // Notify all Pepper plugins.
- for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
- i != active_pepper_instances_.end(); ++i)
- (*i)->SetContentAreaFocus(enable);
+ main_render_frame_->OnSetFocus(enable);
#endif
// Notify all BrowserPlugins of the RenderView's focus state.
if (browser_plugin_manager_.get())
@@ -5817,35 +5715,14 @@ void RenderViewImpl::OnSetFocus(bool enable) {
}
void RenderViewImpl::OnImeSetComposition(
- const string16& text,
- const std::vector<WebKit::WebCompositionUnderline>& underlines,
+ const base::string16& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
int selection_end) {
#if defined(ENABLE_PLUGINS)
if (focused_pepper_plugin_) {
- // When a PPAPI plugin has focus, we bypass WebKit.
- if (!IsPepperAcceptingCompositionEvents()) {
- pepper_composition_text_ = text;
- } else {
- // TODO(kinaba) currently all composition events are sent directly to
- // plugins. Use DOM event mechanism after WebKit is made aware about
- // plugins that support composition.
- // The code below mimics the behavior of WebCore::Editor::setComposition.
-
- // Empty -> nonempty: composition started.
- if (pepper_composition_text_.empty() && !text.empty())
- focused_pepper_plugin_->HandleCompositionStart(string16());
- // Nonempty -> empty: composition canceled.
- if (!pepper_composition_text_.empty() && text.empty())
- focused_pepper_plugin_->HandleCompositionEnd(string16());
- pepper_composition_text_ = text;
- // Nonempty: composition is ongoing.
- if (!pepper_composition_text_.empty()) {
- focused_pepper_plugin_->HandleCompositionUpdate(
- pepper_composition_text_, underlines, selection_start,
- selection_end);
- }
- }
+ focused_pepper_plugin_->render_frame()->OnImeSetComposition(
+ text, underlines, selection_start, selection_end);
return;
}
@@ -5882,49 +5759,13 @@ void RenderViewImpl::OnImeSetComposition(
}
void RenderViewImpl::OnImeConfirmComposition(
- const string16& text,
+ const base::string16& text,
const gfx::Range& replacement_range,
bool keep_selection) {
#if defined(ENABLE_PLUGINS)
if (focused_pepper_plugin_) {
- // When a PPAPI plugin has focus, we bypass WebKit.
- // Here, text.empty() has a special meaning. It means to commit the last
- // update of composition text (see
- // RenderWidgetHost::ImeConfirmComposition()).
- const string16& last_text = text.empty() ? pepper_composition_text_ : text;
-
- // last_text is empty only when both text and pepper_composition_text_ is.
- // Ignore it.
- if (last_text.empty())
- return;
-
- if (!IsPepperAcceptingCompositionEvents()) {
- base::i18n::UTF16CharIterator iterator(&last_text);
- int32 i = 0;
- while (iterator.Advance()) {
- WebKit::WebKeyboardEvent char_event;
- char_event.type = WebKit::WebInputEvent::Char;
- char_event.timeStampSeconds = base::Time::Now().ToDoubleT();
- char_event.modifiers = 0;
- char_event.windowsKeyCode = last_text[i];
- char_event.nativeKeyCode = last_text[i];
-
- const int32 char_start = i;
- for (; i < iterator.array_pos(); ++i) {
- char_event.text[i - char_start] = last_text[i];
- char_event.unmodifiedText[i - char_start] = last_text[i];
- }
-
- if (webwidget())
- webwidget()->handleInputEvent(char_event);
- }
- } else {
- // Mimics the order of events sent by WebKit.
- // See WebCore::Editor::setComposition() for the corresponding code.
- focused_pepper_plugin_->HandleCompositionEnd(last_text);
- focused_pepper_plugin_->HandleTextInput(last_text);
- }
- pepper_composition_text_.clear();
+ focused_pepper_plugin_->render_frame()->OnImeConfirmComposition(
+ text, replacement_range, keep_selection);
return;
}
#if defined(OS_WIN)
@@ -5970,6 +5811,11 @@ void RenderViewImpl::SetDeviceScaleFactor(float device_scale_factor) {
webview()->settings()->
setAcceleratedCompositingForFixedRootBackgroundEnabled(
ShouldUseAcceleratedFixedRootBackground(device_scale_factor_));
+ webview()->settings()->setAcceleratedCompositingForScrollableFramesEnabled(
+ ShouldUseAcceleratedCompositingForScrollableFrames(
+ device_scale_factor_));
+ webview()->settings()->setCompositedScrollingForFramesEnabled(
+ ShouldUseCompositedScrollingForFrames(device_scale_factor_));
}
if (auto_resize_mode_)
AutoResizeCompositor();
@@ -6023,12 +5869,12 @@ void RenderViewImpl::GetCompositionCharacterBounds(
if (character_count == 0)
return;
- WebKit::WebFrame* frame = webview()->focusedFrame();
+ blink::WebFrame* frame = webview()->focusedFrame();
if (!frame)
return;
bounds->reserve(character_count);
- WebKit::WebRect webrect;
+ blink::WebRect webrect;
for (size_t i = 0; i < character_count; ++i) {
if (!frame->firstRectForCharacterRange(start_offset + i, 1, webrect)) {
DLOG(ERROR) << "Could not retrieve character rectangle at " << i;
@@ -6052,17 +5898,17 @@ void RenderViewImpl::GetCompositionRange(gfx::Range* range) {
bool RenderViewImpl::CanComposeInline() {
#if defined(ENABLE_PLUGINS)
if (focused_pepper_plugin_)
- return IsPepperAcceptingCompositionEvents();
+ return focused_pepper_plugin_->IsPluginAcceptingCompositionEvents();
#endif
return true;
}
-void RenderViewImpl::InstrumentWillBeginFrame() {
+void RenderViewImpl::InstrumentWillBeginFrame(int frame_id) {
if (!webview())
return;
if (!webview()->devToolsAgent())
return;
- webview()->devToolsAgent()->didBeginFrame();
+ webview()->devToolsAgent()->didBeginFrame(frame_id);
}
void RenderViewImpl::InstrumentDidBeginFrame() {
@@ -6094,6 +5940,18 @@ bool RenderViewImpl::AllowPartialSwap() const {
return allow_partial_swap_;
}
+void RenderViewImpl::SetScreenMetricsEmulationParameters(
+ float device_scale_factor,
+ const gfx::Point& root_layer_offset,
+ float root_layer_scale) {
+ if (webview()) {
+ webview()->setCompositorDeviceScaleFactorOverride(device_scale_factor);
+ webview()->setRootLayerTransform(
+ blink::WebSize(root_layer_offset.x(), root_layer_offset.y()),
+ root_layer_scale);
+ }
+}
+
bool RenderViewImpl::ScheduleFileChooser(
const FileChooserParams& params,
WebFileChooserCompletion* completion) {
@@ -6119,14 +5977,14 @@ bool RenderViewImpl::ScheduleFileChooser(
return true;
}
-WebKit::WebGeolocationClient* RenderViewImpl::geolocationClient() {
+blink::WebGeolocationClient* RenderViewImpl::geolocationClient() {
if (!geolocation_dispatcher_)
geolocation_dispatcher_ = new GeolocationDispatcher(this);
return geolocation_dispatcher_;
}
-WebKit::WebSpeechInputController* RenderViewImpl::speechInputController(
- WebKit::WebSpeechInputListener* listener) {
+blink::WebSpeechInputController* RenderViewImpl::speechInputController(
+ blink::WebSpeechInputListener* listener) {
#if defined(ENABLE_INPUT_SPEECH)
if (!input_tag_speech_dispatcher_)
input_tag_speech_dispatcher_ =
@@ -6135,18 +5993,12 @@ WebKit::WebSpeechInputController* RenderViewImpl::speechInputController(
return input_tag_speech_dispatcher_;
}
-WebKit::WebSpeechRecognizer* RenderViewImpl::speechRecognizer() {
+blink::WebSpeechRecognizer* RenderViewImpl::speechRecognizer() {
if (!speech_recognition_dispatcher_)
speech_recognition_dispatcher_ = new SpeechRecognitionDispatcher(this);
return speech_recognition_dispatcher_;
}
-WebKit::WebDeviceOrientationClient* RenderViewImpl::deviceOrientationClient() {
- if (!device_orientation_dispatcher_)
- device_orientation_dispatcher_ = new DeviceOrientationDispatcher(this);
- return device_orientation_dispatcher_;
-}
-
void RenderViewImpl::zoomLimitsChanged(double minimum_level,
double maximum_level) {
// For now, don't remember plugin zoom values. We don't want to mix them with
@@ -6201,19 +6053,20 @@ void RenderViewImpl::registerProtocolHandler(const WebString& scheme,
user_gesture));
}
-WebKit::WebPageVisibilityState RenderViewImpl::visibilityState() const {
- WebKit::WebPageVisibilityState current_state = is_hidden() ?
- WebKit::WebPageVisibilityStateHidden :
- WebKit::WebPageVisibilityStateVisible;
- WebKit::WebPageVisibilityState override_state = current_state;
+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(this,
+ ShouldOverridePageVisibilityState(main_render_frame_.get(),
&override_state))
return override_state;
return current_state;
}
-WebKit::WebUserMediaClient* RenderViewImpl::userMediaClient() {
+blink::WebUserMediaClient* RenderViewImpl::userMediaClient() {
// This can happen in tests, in which case it's OK to return NULL.
if (!InitializeMediaStreamClient())
return NULL;
@@ -6221,7 +6074,7 @@ WebKit::WebUserMediaClient* RenderViewImpl::userMediaClient() {
return web_user_media_client_;
}
-WebKit::WebMIDIClient* RenderViewImpl::webMIDIClient() {
+blink::WebMIDIClient* RenderViewImpl::webMIDIClient() {
if (!midi_dispatcher_)
midi_dispatcher_ = new MIDIDispatcher(this);
return midi_dispatcher_;
@@ -6234,6 +6087,30 @@ void RenderViewImpl::draggableRegionsChanged() {
DraggableRegionsChanged(webview()->mainFrame()));
}
+WebMediaPlayer* RenderViewImpl::CreateWebMediaPlayerForMediaStream(
+ WebFrame* frame,
+ const blink::WebURL& url,
+ WebMediaPlayerClient* client) {
+#if defined(ENABLE_WEBRTC)
+ if (!InitializeMediaStreamClient()) {
+ LOG(ERROR) << "Failed to initialize MediaStreamClient";
+ return NULL;
+ }
+#if !defined(GOOGLE_TV)
+ if (media_stream_client_->IsMediaStream(url)) {
+#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
+ bool found_neon =
+ (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
+ UMA_HISTOGRAM_BOOLEAN("Platform.WebRtcNEONFound", found_neon);
+#endif // defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
+ return new WebMediaPlayerMS(frame, client, AsWeakPtr(),
+ media_stream_client_, new RenderMediaLog());
+ }
+#endif // !defined(GOOGLE_TV)
+#endif // defined(ENABLE_WEBRTC)
+ return NULL;
+}
+
#if defined(OS_ANDROID)
WebContentDetectionResult RenderViewImpl::detectContentAround(
const WebHitTestResult& touch_hit) {
@@ -6282,13 +6159,82 @@ void RenderViewImpl::LaunchAndroidContentIntent(const GURL& intent,
}
bool RenderViewImpl::openDateTimeChooser(
- const WebKit::WebDateTimeChooserParams& params,
- WebKit::WebDateTimeChooserCompletion* completion) {
+ const blink::WebDateTimeChooserParams& params,
+ blink::WebDateTimeChooserCompletion* completion) {
+ // JavaScript may try to open a date time chooser while one is already open.
+ if (date_time_picker_client_)
+ return false;
date_time_picker_client_.reset(
new RendererDateTimePicker(this, params, completion));
return date_time_picker_client_->Open();
}
+#if defined(OS_ANDROID)
+void RenderViewImpl::DismissDateTimeDialog() {
+ DCHECK(date_time_picker_client_);
+ date_time_picker_client_.reset(NULL);
+}
+#endif
+
+WebMediaPlayer* RenderViewImpl::CreateAndroidWebMediaPlayer(
+ WebFrame* frame,
+ const blink::WebURL& url,
+ WebMediaPlayerClient* client) {
+ GpuChannelHost* gpu_channel_host =
+ RenderThreadImpl::current()->EstablishGpuChannelSync(
+ CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE);
+ if (!gpu_channel_host) {
+ LOG(ERROR) << "Failed to establish GPU channel for media player";
+ return NULL;
+ }
+
+ scoped_ptr<StreamTextureFactory> stream_texture_factory;
+ if (UsingSynchronousRendererCompositor()) {
+ SynchronousCompositorFactory* factory =
+ SynchronousCompositorFactory::GetInstance();
+ stream_texture_factory = factory->CreateStreamTextureFactory(routing_id_);
+ } else {
+ scoped_refptr<cc::ContextProvider> context_provider =
+ RenderThreadImpl::current()->SharedMainThreadContextProvider();
+
+ if (!context_provider.get()) {
+ LOG(ERROR) << "Failed to get context3d for media player";
+ return NULL;
+ }
+
+ stream_texture_factory.reset(new StreamTextureFactoryImpl(
+ context_provider->Context3d(), gpu_channel_host, routing_id_));
+ }
+
+ scoped_ptr<WebMediaPlayerAndroid> web_media_player_android(
+ new WebMediaPlayerAndroid(
+ frame,
+ client,
+ AsWeakPtr(),
+ media_player_manager_,
+ stream_texture_factory.release(),
+ RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(),
+ new RenderMediaLog()));
+#if defined(ENABLE_WEBRTC) && defined(GOOGLE_TV)
+ if (media_stream_client_ && media_stream_client_->IsMediaStream(url)) {
+ RTCVideoDecoderFactoryTv* factory = RenderThreadImpl::current()
+ ->GetMediaStreamDependencyFactory()->decoder_factory_tv();
+ // |media_stream_client| and |factory| outlives |web_media_player_android|.
+ if (!factory->AcquireDemuxer() ||
+ !web_media_player_android->InjectMediaStream(
+ media_stream_client_,
+ factory,
+ base::Bind(
+ base::IgnoreResult(&RTCVideoDecoderFactoryTv::ReleaseDemuxer),
+ base::Unretained(factory)))) {
+ LOG(ERROR) << "Failed to inject media stream.";
+ return NULL;
+ }
+ }
+#endif // defined(ENABLE_WEBRTC) && defined(GOOGLE_TV)
+ return web_media_player_android.release();
+}
+
#endif // defined(OS_ANDROID)
#if defined(OS_MACOSX)
@@ -6354,13 +6300,6 @@ void RenderViewImpl::OnEnableViewSourceMode() {
main_frame->enableViewSourceMode(true);
}
-#if defined(OS_ANDROID)
-void RenderViewImpl::OnJavaBridgeInit() {
- DCHECK(!java_bridge_dispatcher_);
- java_bridge_dispatcher_ = new JavaBridgeDispatcher(this);
-}
-#endif
-
void RenderViewImpl::OnDisownOpener() {
if (!webview())
return;
@@ -6372,7 +6311,7 @@ void RenderViewImpl::OnDisownOpener() {
#if defined(OS_ANDROID)
bool RenderViewImpl::didTapMultipleTargets(
- const WebKit::WebGestureEvent& event,
+ const blink::WebGestureEvent& event,
const WebVector<WebRect>& target_rects) {
// Never show a disambiguation popup when accessibility is enabled,
// as this interferes with "touch exploration".
@@ -6473,6 +6412,18 @@ void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) {
OnResize(params);
}
+void RenderViewImpl::ForceResizeForTesting(const gfx::Size& new_size) {
+ gfx::Rect new_position(rootWindowRect().x,
+ rootWindowRect().y,
+ new_size.width(),
+ new_size.height());
+ ResizeSynchronously(new_position);
+}
+
+void RenderViewImpl::UseSynchronousResizeModeForTesting(bool enable) {
+ resizing_mode_selector_->set_is_synchronous_mode(enable);
+}
+
void RenderViewImpl::EnableAutoResizeForTesting(const gfx::Size& min_size,
const gfx::Size& max_size) {
OnEnableAutoResize(min_size, max_size);
@@ -6489,10 +6440,6 @@ void RenderViewImpl::SetMediaStreamClientForTesting(
media_stream_client_ = media_stream_client;
}
-bool RenderViewImpl::IsPluginFullscreenAllowed() {
- return renderer_preferences_.plugin_fullscreen_allowed;
-}
-
void RenderViewImpl::OnReleaseDisambiguationPopupDIB(
TransportDIB::Handle dib_handle) {
TransportDIB* dib = TransportDIB::CreateWithHandle(dib_handle);
diff --git a/chromium/content/renderer/render_view_impl.h b/chromium/content/renderer/render_view_impl.h
index 2634ce1ebbd..f341ecc08e7 100644
--- a/chromium/content/renderer/render_view_impl.h
+++ b/chromium/content/renderer/render_view_impl.h
@@ -39,6 +39,7 @@
#include "content/renderer/mouse_lock_dispatcher.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_widget.h"
+#include "content/renderer/renderer_date_time_picker.h"
#include "content/renderer/renderer_webcookiejar_impl.h"
#include "content/renderer/stats_collection_observer.h"
#include "ipc/ipc_platform_file.h"
@@ -84,7 +85,7 @@ namespace ui {
struct SelectedFileInfo;
} // namespace ui
-namespace WebKit {
+namespace blink {
class WebApplicationCacheHost;
class WebApplicationCacheHostClient;
class WebDOMMessageEvent;
@@ -111,7 +112,6 @@ class WebTouchEvent;
class WebURLRequest;
class WebUserMediaClient;
struct WebActiveWheelFlingParameters;
-struct WebCursorInfo;
struct WebDateTimeChooserParams;
struct WebFileChooserParams;
struct WebFindOptions;
@@ -153,11 +153,8 @@ class RenderViewObserver;
class RenderViewTest;
class RendererAccessibility;
class RendererDateTimePicker;
-class RendererPpapiHost;
class RendererWebColorChooserImpl;
-class RenderWidgetFullscreenPepper;
class SpeechRecognitionDispatcher;
-class StatsCollectionController;
class WebPluginDelegateProxy;
struct CustomContextMenuContext;
struct DropData;
@@ -176,9 +173,9 @@ class WebMediaPlayerProxyAndroid;
//
class CONTENT_EXPORT RenderViewImpl
: public RenderWidget,
- NON_EXPORTED_BASE(public WebKit::WebViewClient),
- NON_EXPORTED_BASE(public WebKit::WebFrameClient),
- NON_EXPORTED_BASE(public WebKit::WebPageSerializerClient),
+ NON_EXPORTED_BASE(public blink::WebViewClient),
+ NON_EXPORTED_BASE(public blink::WebFrameClient),
+ NON_EXPORTED_BASE(public blink::WebPageSerializerClient),
public RenderView,
NON_EXPORTED_BASE(public WebMediaPlayerDelegate),
public base::SupportsWeakPtr<RenderViewImpl> {
@@ -193,12 +190,12 @@ class CONTENT_EXPORT RenderViewImpl
int32 main_frame_routing_id,
int32 surface_id,
int64 session_storage_namespace_id,
- const string16& frame_name,
+ const base::string16& frame_name,
bool is_renderer_created,
bool swapped_out,
bool hidden,
int32 next_page_id,
- const WebKit::WebScreenInfo& screen_info,
+ const blink::WebScreenInfo& screen_info,
AccessibilityMode accessibility_mode,
bool allow_partial_swap);
@@ -208,13 +205,13 @@ class CONTENT_EXPORT RenderViewImpl
RenderViewImpl* (*create_render_view_impl)(RenderViewImplParams*));
// Returns the RenderViewImpl containing the given WebView.
- static RenderViewImpl* FromWebView(WebKit::WebView* webview);
+ static RenderViewImpl* FromWebView(blink::WebView* webview);
// Returns the RenderViewImpl for the given routing ID.
static RenderViewImpl* FromRoutingID(int routing_id);
// May return NULL when the view is closing.
- WebKit::WebView* webview() const;
+ blink::WebView* webview() const;
int history_list_offset() const { return history_list_offset_; }
@@ -222,26 +219,30 @@ class CONTENT_EXPORT RenderViewImpl
return webkit_preferences_;
}
+ const RendererPreferences& renderer_preferences() const {
+ return renderer_preferences_;
+ }
+
void set_send_content_state_immediately(bool value) {
send_content_state_immediately_ = value;
}
+ RenderFrameImpl* main_render_frame() { return main_render_frame_.get(); }
+
MediaStreamDispatcher* media_stream_dispatcher() {
return media_stream_dispatcher_;
}
+ RendererAccessibility* renderer_accessibility() {
+ return renderer_accessibility_;
+ }
+
MouseLockDispatcher* mouse_lock_dispatcher() {
return mouse_lock_dispatcher_;
}
RendererWebCookieJarImpl* cookie_jar() { return &cookie_jar_; }
-#if defined(OS_ANDROID)
- RendererMediaPlayerManager* media_player_manager() {
- return media_player_manager_.get();
- }
-#endif
-
// Lazily initialize this view's BrowserPluginManager and return it.
BrowserPluginManager* GetBrowserPluginManager();
@@ -262,72 +263,34 @@ class CONTENT_EXPORT RenderViewImpl
// Returns true if the chooser was successfully scheduled. False means we
// didn't schedule anything.
bool ScheduleFileChooser(const FileChooserParams& params,
- WebKit::WebFileChooserCompletion* completion);
+ blink::WebFileChooserCompletion* completion);
void LoadNavigationErrorPage(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& failed_request,
- const WebKit::WebURLError& error,
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& failed_request,
+ const blink::WebURLError& error,
const std::string& html,
bool replace);
+#if defined(OS_ANDROID)
+ void DismissDateTimeDialog();
+#endif
+
// Plugin-related functions --------------------------------------------------
#if defined(ENABLE_PLUGINS)
- // Indicates that the given instance has been created.
- void PepperInstanceCreated(PepperPluginInstanceImpl* instance);
-
- // Indicates that the given instance is being destroyed. This is called from
- // the destructor, so it's important that the instance is not dereferenced
- // from this call.
- void PepperInstanceDeleted(PepperPluginInstanceImpl* instance);
-
- // Notifies that |instance| has changed the cursor.
- // This will update the cursor appearance if it is currently over the plugin
- // instance.
- void PepperDidChangeCursor(PepperPluginInstanceImpl* instance,
- const WebKit::WebCursorInfo& cursor);
-
- // Notifies that |instance| has received a mouse event.
- void PepperDidReceiveMouseEvent(PepperPluginInstanceImpl* instance);
-
- // Notification that the given plugin is focused or unfocused.
- void PepperFocusChanged(PepperPluginInstanceImpl* instance, bool focused);
-
- // Informs the render view that a PPAPI plugin has changed text input status.
- void PepperTextInputTypeChanged(PepperPluginInstanceImpl* instance);
- void PepperCaretPositionChanged(PepperPluginInstanceImpl* instance);
-
- // Cancels current composition.
- void PepperCancelComposition(PepperPluginInstanceImpl* instance);
-
- // Informs the render view that a PPAPI plugin has changed selection.
- void PepperSelectionChanged(PepperPluginInstanceImpl* instance);
-
- // Creates a fullscreen container for a pepper plugin instance.
- RenderWidgetFullscreenPepper* CreatePepperFullscreenContainer(
- PepperPluginInstanceImpl* plugin);
-
- // Notification that a PPAPI plugin has been created.
- void PepperPluginCreated(RendererPpapiHost* host);
-
- // Retrieves the current caret position if a PPAPI plugin has focus.
- bool GetPepperCaretBounds(gfx::Rect* rect);
-
- bool IsPepperAcceptingCompositionEvents() const;
-
- // Notification that the given plugin has crashed.
- void PluginCrashed(const base::FilePath& plugin_path,
- base::ProcessId plugin_pid);
-
- // Simulates IME events for testing purpose.
- void SimulateImeSetComposition(
- const string16& text,
- const std::vector<WebKit::WebCompositionUnderline>& underlines,
- int selection_start,
- int selection_end);
- void SimulateImeConfirmComposition(const string16& text,
- const gfx::Range& replacement_range);
+ PepperPluginInstanceImpl* focused_pepper_plugin() {
+ return focused_pepper_plugin_;
+ }
+ void set_focused_pepper_plugin(PepperPluginInstanceImpl* plugin) {
+ focused_pepper_plugin_ = plugin;
+ }
+ PepperPluginInstanceImpl* pepper_last_mouse_event_target() {
+ return pepper_last_mouse_event_target_;
+ }
+ void set_pepper_last_mouse_event_target(PepperPluginInstanceImpl* plugin) {
+ pepper_last_mouse_event_target_ = plugin;
+ }
#if defined(OS_MACOSX) || defined(OS_WIN)
// Informs the render view that the given plugin has gained or lost focus.
@@ -341,22 +304,10 @@ class CONTENT_EXPORT RenderViewImpl
void RegisterPluginDelegate(WebPluginDelegateProxy* delegate);
void UnregisterPluginDelegate(WebPluginDelegateProxy* delegate);
-
- // Helper function to retrieve information about a plugin for a URL and mime
- // type. Returns false if no plugin was found.
- // |actual_mime_type| is the actual mime type supported by the
- // plugin found that match the URL given (one for each item in
- // |info|).
- bool GetPluginInfo(const GURL& url,
- const GURL& page_url,
- const std::string& mime_type,
- WebPluginInfo* plugin_info,
- std::string* actual_mime_type);
-
#endif // ENABLE_PLUGINS
void TransferActiveWheelFlingAnimation(
- const WebKit::WebActiveWheelFlingParameters& params);
+ const blink::WebActiveWheelFlingParameters& params);
// Returns true if the focused element is editable text from the perspective
// of IME support (also used for on-screen keyboard). Works correctly inside
@@ -374,6 +325,19 @@ class CONTENT_EXPORT RenderViewImpl
// periodic timer so we don't send too many messages.
void SyncNavigationState();
+ // Temporary call until all this media code moves to RenderFrame.
+ // TODO(jam): remove me
+ blink::WebMediaPlayer* CreateMediaPlayer(
+ RenderFrame* render_frame,
+ blink::WebFrame* frame,
+ const blink::WebURL& url,
+ blink::WebMediaPlayerClient* client);
+ // Temporary call until the context menu code moves to RenderFrmae.
+ // TODO(jam): remove me
+ int ShowContextMenu(ContextMenuClient* client,
+ const ContextMenuParams& params);
+ void CancelContextMenu(int request_id);
+
// Returns the length of the session history of this RenderView. Note that
// this only coincides with the actual length of the session history if this
// RenderView is the currently active RenderView of a WebContents.
@@ -387,6 +351,11 @@ class CONTENT_EXPORT RenderViewImpl
// Change the device scale factor and force the compositor to resize.
void SetDeviceScaleFactorForTesting(float factor);
+ // Used to force the size of a window when running layout tests.
+ void ForceResizeForTesting(const gfx::Size& new_size);
+
+ void UseSynchronousResizeModeForTesting(bool enable);
+
// Control autoresize mode.
void EnableAutoResizeForTesting(const gfx::Size& min_size,
const gfx::Size& max_size);
@@ -396,19 +365,16 @@ class CONTENT_EXPORT RenderViewImpl
// Must be called before any players are created.
void SetMediaStreamClientForTesting(MediaStreamClient* media_stream_client);
- // Determines whether plugins are allowed to enter fullscreen mode.
- bool IsPluginFullscreenAllowed();
-
// IPC::Listener implementation ----------------------------------------------
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- // WebKit::WebWidgetClient implementation ------------------------------------
+ // blink::WebWidgetClient implementation ------------------------------------
// Most methods are handled by RenderWidget.
virtual void didFocus();
virtual void didBlur();
- virtual void show(WebKit::WebNavigationPolicy policy);
+ virtual void show(blink::WebNavigationPolicy policy);
virtual void runModal();
virtual bool enterFullScreen();
virtual void exitFullScreen();
@@ -416,287 +382,292 @@ class CONTENT_EXPORT RenderViewImpl
virtual void requestPointerUnlock();
virtual bool isPointerLocked();
virtual void didActivateCompositor(int input_handler_identifier);
- virtual void didHandleGestureEvent(const WebKit::WebGestureEvent& event,
+ virtual void didHandleGestureEvent(const blink::WebGestureEvent& event,
bool event_cancelled) OVERRIDE;
virtual void initializeLayerTreeView() OVERRIDE;
- // WebKit::WebViewClient implementation --------------------------------------
-
- virtual WebKit::WebView* createView(
- WebKit::WebFrame* creator,
- const WebKit::WebURLRequest& request,
- const WebKit::WebWindowFeatures& features,
- const WebKit::WebString& frame_name,
- WebKit::WebNavigationPolicy policy);
- virtual WebKit::WebWidget* createPopupMenu(WebKit::WebPopupType popup_type);
- virtual WebKit::WebExternalPopupMenu* createExternalPopupMenu(
- const WebKit::WebPopupMenuInfo& popup_menu_info,
- WebKit::WebExternalPopupMenuClient* popup_menu_client);
- virtual WebKit::WebStorageNamespace* createSessionStorageNamespace();
+ // blink::WebViewClient implementation --------------------------------------
+
+ virtual blink::WebView* createView(
+ blink::WebFrame* creator,
+ const blink::WebURLRequest& request,
+ const blink::WebWindowFeatures& features,
+ const blink::WebString& frame_name,
+ blink::WebNavigationPolicy policy,
+ bool suppress_opener);
+ virtual blink::WebWidget* createPopupMenu(blink::WebPopupType popup_type);
+ virtual blink::WebExternalPopupMenu* createExternalPopupMenu(
+ const blink::WebPopupMenuInfo& popup_menu_info,
+ blink::WebExternalPopupMenuClient* popup_menu_client);
+ virtual blink::WebStorageNamespace* createSessionStorageNamespace();
virtual bool shouldReportDetailedMessageForSource(
- const WebKit::WebString& source);
+ const blink::WebString& source);
virtual void didAddMessageToConsole(
- const WebKit::WebConsoleMessage& message,
- const WebKit::WebString& source_name,
+ const blink::WebConsoleMessage& message,
+ const blink::WebString& source_name,
unsigned source_line,
- const WebKit::WebString& stack_trace);
- virtual void printPage(WebKit::WebFrame* frame);
- virtual WebKit::WebNotificationPresenter* notificationPresenter();
+ const blink::WebString& stack_trace);
+ virtual void printPage(blink::WebFrame* frame);
+ virtual blink::WebNotificationPresenter* notificationPresenter();
virtual bool enumerateChosenDirectory(
- const WebKit::WebString& path,
- WebKit::WebFileChooserCompletion* chooser_completion);
- virtual void initializeHelperPluginWebFrame(WebKit::WebHelperPlugin*);
+ const blink::WebString& path,
+ blink::WebFileChooserCompletion* chooser_completion);
+ virtual void initializeHelperPluginWebFrame(blink::WebHelperPlugin*);
virtual void didStartLoading();
virtual void didStopLoading();
- virtual void didChangeLoadProgress(WebKit::WebFrame* frame,
+ virtual void didChangeLoadProgress(blink::WebFrame* frame,
double load_progress);
virtual void didCancelCompositionOnSelectionChange();
virtual void didChangeSelection(bool is_selection_empty);
- virtual void didExecuteCommand(const WebKit::WebString& command_name);
+ virtual void didExecuteCommand(const blink::WebString& command_name);
virtual bool handleCurrentKeyboardEvent();
- virtual WebKit::WebColorChooser* createColorChooser(
- WebKit::WebColorChooserClient*, const WebKit::WebColor& initial_color);
+ virtual blink::WebColorChooser* createColorChooser(
+ blink::WebColorChooserClient*,
+ const blink::WebColor& initial_color,
+ const blink::WebVector<blink::WebColorSuggestion>& suggestions);
virtual bool runFileChooser(
- const WebKit::WebFileChooserParams& params,
- WebKit::WebFileChooserCompletion* chooser_completion);
- virtual void runModalAlertDialog(WebKit::WebFrame* frame,
- const WebKit::WebString& message);
- virtual bool runModalConfirmDialog(WebKit::WebFrame* frame,
- const WebKit::WebString& message);
- virtual bool runModalPromptDialog(WebKit::WebFrame* frame,
- const WebKit::WebString& message,
- const WebKit::WebString& default_value,
- WebKit::WebString* actual_value);
- virtual bool runModalBeforeUnloadDialog(WebKit::WebFrame* frame,
+ const blink::WebFileChooserParams& params,
+ blink::WebFileChooserCompletion* chooser_completion);
+ virtual void runModalAlertDialog(blink::WebFrame* frame,
+ const blink::WebString& message);
+ virtual bool runModalConfirmDialog(blink::WebFrame* frame,
+ const blink::WebString& message);
+ virtual bool runModalPromptDialog(blink::WebFrame* frame,
+ const blink::WebString& message,
+ const blink::WebString& default_value,
+ blink::WebString* actual_value);
+ virtual bool runModalBeforeUnloadDialog(blink::WebFrame* frame,
bool is_reload,
- const WebKit::WebString& message);
+ const blink::WebString& message);
+ virtual void showValidationMessage(const blink::WebRect& anchor_in_root_view,
+ const blink::WebString& main_text,
+ const blink::WebString& sub_text,
+ blink::WebTextDirection hint) OVERRIDE;
+ virtual void hideValidationMessage() OVERRIDE;
+ virtual void moveValidationMessage(
+ const blink::WebRect& anchor_in_root_view) OVERRIDE;
+
// DEPRECATED
- virtual bool runModalBeforeUnloadDialog(WebKit::WebFrame* frame,
- const WebKit::WebString& message);
- virtual void showContextMenu(WebKit::WebFrame* frame,
- const WebKit::WebContextMenuData& data);
+ virtual bool runModalBeforeUnloadDialog(blink::WebFrame* frame,
+ const blink::WebString& message);
+ virtual void showContextMenu(blink::WebFrame* frame,
+ const blink::WebContextMenuData& data);
virtual void clearContextMenu();
- virtual void setStatusText(const WebKit::WebString& text);
- virtual void setMouseOverURL(const WebKit::WebURL& url);
- virtual void setKeyboardFocusURL(const WebKit::WebURL& url);
- virtual void startDragging(WebKit::WebFrame* frame,
- const WebKit::WebDragData& data,
- WebKit::WebDragOperationsMask mask,
- const WebKit::WebImage& image,
- const WebKit::WebPoint& imageOffset);
+ virtual void setStatusText(const blink::WebString& text);
+ virtual void setMouseOverURL(const blink::WebURL& url);
+ virtual void setKeyboardFocusURL(const blink::WebURL& url);
+ virtual void startDragging(blink::WebFrame* frame,
+ const blink::WebDragData& data,
+ blink::WebDragOperationsMask mask,
+ const blink::WebImage& image,
+ const blink::WebPoint& imageOffset);
virtual bool acceptsLoadDrops();
virtual void focusNext();
virtual void focusPrevious();
- virtual void focusedNodeChanged(const WebKit::WebNode& node);
+ virtual void focusedNodeChanged(const blink::WebNode& node);
virtual void numberOfWheelEventHandlersChanged(unsigned num_handlers);
virtual void didUpdateLayout();
#if defined(OS_ANDROID)
virtual bool didTapMultipleTargets(
- const WebKit::WebGestureEvent& event,
- const WebKit::WebVector<WebKit::WebRect>& target_rects);
+ const blink::WebGestureEvent& event,
+ const blink::WebVector<blink::WebRect>& target_rects);
#endif
virtual void navigateBackForwardSoon(int offset);
virtual int historyBackListCount();
virtual int historyForwardListCount();
virtual void postAccessibilityEvent(
- const WebKit::WebAXObject& obj, WebKit::WebAXEvent event);
- virtual void didUpdateInspectorSetting(const WebKit::WebString& key,
- const WebKit::WebString& value);
- virtual WebKit::WebGeolocationClient* geolocationClient();
- virtual WebKit::WebSpeechInputController* speechInputController(
- WebKit::WebSpeechInputListener* listener);
- virtual WebKit::WebSpeechRecognizer* speechRecognizer();
- virtual WebKit::WebDeviceOrientationClient* deviceOrientationClient();
+ const blink::WebAXObject& obj, blink::WebAXEvent event);
+ virtual void didUpdateInspectorSetting(const blink::WebString& key,
+ const blink::WebString& value);
+ virtual blink::WebGeolocationClient* geolocationClient();
+ virtual blink::WebSpeechInputController* speechInputController(
+ blink::WebSpeechInputListener* listener);
+ virtual blink::WebSpeechRecognizer* speechRecognizer();
virtual void zoomLimitsChanged(double minimum_level, double maximum_level);
virtual void zoomLevelChanged();
virtual double zoomLevelToZoomFactor(double zoom_level) const;
virtual double zoomFactorToZoomLevel(double factor) const;
- virtual void registerProtocolHandler(const WebKit::WebString& scheme,
- const WebKit::WebString& base_url,
- const WebKit::WebString& url,
- const WebKit::WebString& title);
- virtual WebKit::WebPageVisibilityState visibilityState() const;
- virtual WebKit::WebUserMediaClient* userMediaClient();
- virtual WebKit::WebMIDIClient* webMIDIClient();
+ virtual void registerProtocolHandler(const blink::WebString& scheme,
+ const blink::WebString& base_url,
+ const blink::WebString& url,
+ const blink::WebString& title);
+ virtual blink::WebPageVisibilityState visibilityState() const;
+ virtual blink::WebUserMediaClient* userMediaClient();
+ virtual blink::WebMIDIClient* webMIDIClient();
virtual void draggableRegionsChanged();
#if defined(OS_ANDROID)
- virtual void scheduleContentIntent(const WebKit::WebURL& intent);
+ virtual void scheduleContentIntent(const blink::WebURL& intent);
virtual void cancelScheduledContentIntents();
- virtual WebKit::WebContentDetectionResult detectContentAround(
- const WebKit::WebHitTestResult& touch_hit);
+ virtual blink::WebContentDetectionResult detectContentAround(
+ const blink::WebHitTestResult& touch_hit);
// Only used on Android since all other platforms implement
// date and time input fields using MULTIPLE_FIELDS_UI
- virtual bool openDateTimeChooser(const WebKit::WebDateTimeChooserParams&,
- WebKit::WebDateTimeChooserCompletion*);
- virtual void didScrollWithKeyboard(const WebKit::WebSize& delta);
+ virtual bool openDateTimeChooser(const blink::WebDateTimeChooserParams&,
+ blink::WebDateTimeChooserCompletion*);
+ virtual void didScrollWithKeyboard(const blink::WebSize& delta);
#endif
- // WebKit::WebFrameClient implementation -------------------------------------
-
- virtual WebKit::WebMediaPlayer* createMediaPlayer(
- WebKit::WebFrame* frame,
- const WebKit::WebURL& url,
- WebKit::WebMediaPlayerClient* client);
- virtual WebKit::WebCookieJar* cookieJar(WebKit::WebFrame* frame);
- virtual void didAccessInitialDocument(WebKit::WebFrame* frame);
- virtual void didDisownOpener(WebKit::WebFrame* frame);
- virtual void frameDetached(WebKit::WebFrame* frame);
- virtual void willClose(WebKit::WebFrame* frame);
+ // blink::WebFrameClient implementation -------------------------------------
+
+ virtual blink::WebMediaPlayer* createMediaPlayer(
+ blink::WebFrame* frame,
+ const blink::WebURL& url,
+ blink::WebMediaPlayerClient* client);
+ virtual blink::WebCookieJar* cookieJar(blink::WebFrame* frame);
+ virtual void didAccessInitialDocument(blink::WebFrame* frame);
+ virtual void didDisownOpener(blink::WebFrame* frame);
+ virtual void frameDetached(blink::WebFrame* frame);
+ virtual void willClose(blink::WebFrame* frame);
+ virtual void didMatchCSS(
+ blink::WebFrame* frame,
+ const blink::WebVector<blink::WebString>& newly_matching_selectors,
+ const blink::WebVector<blink::WebString>& stopped_matching_selectors);
// The WebDataSource::ExtraData* is assumed to be a DocumentState* subclass.
- virtual WebKit::WebNavigationPolicy decidePolicyForNavigation(
- WebKit::WebFrame* frame,
- WebKit::WebDataSource::ExtraData* extraData,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationType type,
- WebKit::WebNavigationPolicy default_policy,
+ virtual blink::WebNavigationPolicy decidePolicyForNavigation(
+ blink::WebFrame* frame,
+ blink::WebDataSource::ExtraData* extraData,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationType type,
+ blink::WebNavigationPolicy default_policy,
bool is_redirect);
// DEPRECATED.
- virtual WebKit::WebNavigationPolicy decidePolicyForNavigation(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationType type,
- WebKit::WebNavigationPolicy default_policy,
+ virtual blink::WebNavigationPolicy decidePolicyForNavigation(
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationType type,
+ blink::WebNavigationPolicy default_policy,
bool is_redirect);
- virtual void willSendSubmitEvent(WebKit::WebFrame* frame,
- const WebKit::WebFormElement& form);
- virtual void willSubmitForm(WebKit::WebFrame* frame,
- const WebKit::WebFormElement& form);
- virtual void didCreateDataSource(WebKit::WebFrame* frame,
- WebKit::WebDataSource* datasource);
- virtual void didStartProvisionalLoad(WebKit::WebFrame* frame);
+ virtual void willSendSubmitEvent(blink::WebFrame* frame,
+ const blink::WebFormElement& form);
+ virtual void willSubmitForm(blink::WebFrame* frame,
+ const blink::WebFormElement& form);
+ virtual void didCreateDataSource(blink::WebFrame* frame,
+ blink::WebDataSource* datasource);
+ virtual void didStartProvisionalLoad(blink::WebFrame* frame);
virtual void didReceiveServerRedirectForProvisionalLoad(
- WebKit::WebFrame* frame);
- virtual void didFailProvisionalLoad(WebKit::WebFrame* frame,
- const WebKit::WebURLError& error);
- virtual void didCommitProvisionalLoad(WebKit::WebFrame* frame,
+ blink::WebFrame* frame);
+ virtual void didFailProvisionalLoad(blink::WebFrame* frame,
+ const blink::WebURLError& error);
+ virtual void didCommitProvisionalLoad(blink::WebFrame* frame,
bool is_new_navigation);
- virtual void didClearWindowObject(WebKit::WebFrame* frame);
- virtual void didCreateDocumentElement(WebKit::WebFrame* frame);
- virtual void didReceiveTitle(WebKit::WebFrame* frame,
- const WebKit::WebString& title,
- WebKit::WebTextDirection direction);
- virtual void didChangeIcon(WebKit::WebFrame*,
- WebKit::WebIconURL::Type);
- virtual void didFinishDocumentLoad(WebKit::WebFrame* frame);
- virtual void didHandleOnloadEvents(WebKit::WebFrame* frame);
- virtual void didFailLoad(WebKit::WebFrame* frame,
- const WebKit::WebURLError& error);
- virtual void didFinishLoad(WebKit::WebFrame* frame);
- virtual void didNavigateWithinPage(WebKit::WebFrame* frame,
+ virtual void didClearWindowObject(blink::WebFrame* frame);
+ virtual void didCreateDocumentElement(blink::WebFrame* frame);
+ virtual void didReceiveTitle(blink::WebFrame* frame,
+ const blink::WebString& title,
+ blink::WebTextDirection direction);
+ virtual void didChangeIcon(blink::WebFrame*,
+ blink::WebIconURL::Type);
+ virtual void didFinishDocumentLoad(blink::WebFrame* frame);
+ virtual void didHandleOnloadEvents(blink::WebFrame* frame);
+ virtual void didFailLoad(blink::WebFrame* frame,
+ const blink::WebURLError& error);
+ virtual void didFinishLoad(blink::WebFrame* frame);
+ virtual void didNavigateWithinPage(blink::WebFrame* frame,
bool is_new_navigation);
- virtual void didUpdateCurrentHistoryItem(WebKit::WebFrame* frame);
- virtual void willSendRequest(WebKit::WebFrame* frame,
+ virtual void didUpdateCurrentHistoryItem(blink::WebFrame* frame);
+ virtual void willSendRequest(blink::WebFrame* frame,
unsigned identifier,
- WebKit::WebURLRequest& request,
- const WebKit::WebURLResponse& redirect_response);
- virtual void didReceiveResponse(WebKit::WebFrame* frame,
+ blink::WebURLRequest& request,
+ const blink::WebURLResponse& redirect_response);
+ virtual void didReceiveResponse(blink::WebFrame* frame,
unsigned identifier,
- const WebKit::WebURLResponse& response);
- virtual void didFinishResourceLoad(WebKit::WebFrame* frame,
+ const blink::WebURLResponse& response);
+ virtual void didFinishResourceLoad(blink::WebFrame* frame,
unsigned identifier);
virtual void didLoadResourceFromMemoryCache(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- const WebKit::WebURLResponse&);
- virtual void didDisplayInsecureContent(WebKit::WebFrame* frame);
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request,
+ const blink::WebURLResponse&);
+ virtual void didDisplayInsecureContent(blink::WebFrame* frame);
virtual void didRunInsecureContent(
- WebKit::WebFrame* frame,
- const WebKit::WebSecurityOrigin& origin,
- const WebKit::WebURL& target);
- virtual void didExhaustMemoryAvailableForScript(WebKit::WebFrame* frame);
- virtual void didCreateScriptContext(WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
+ const blink::WebSecurityOrigin& origin,
+ const blink::WebURL& target);
+ virtual void didExhaustMemoryAvailableForScript(blink::WebFrame* frame);
+ virtual void didCreateScriptContext(blink::WebFrame* frame,
v8::Handle<v8::Context>,
int extension_group,
int world_id);
- virtual void willReleaseScriptContext(WebKit::WebFrame* frame,
+ virtual void willReleaseScriptContext(blink::WebFrame* frame,
v8::Handle<v8::Context>,
int world_id);
- virtual void didChangeScrollOffset(WebKit::WebFrame* frame);
- virtual void willInsertBody(WebKit::WebFrame* frame);
- virtual void didFirstVisuallyNonEmptyLayout(WebKit::WebFrame*);
- virtual void didChangeContentsSize(WebKit::WebFrame* frame,
- const WebKit::WebSize& size);
+ virtual void didChangeScrollOffset(blink::WebFrame* frame);
+ virtual void willInsertBody(blink::WebFrame* frame);
+ virtual void didFirstVisuallyNonEmptyLayout(blink::WebFrame*);
+ virtual void didChangeContentsSize(blink::WebFrame* frame,
+ const blink::WebSize& size);
virtual void reportFindInPageMatchCount(int request_id,
int count,
bool final_update);
virtual void reportFindInPageSelection(int request_id,
int active_match_ordinal,
- const WebKit::WebRect& sel);
+ const blink::WebRect& sel);
virtual void requestStorageQuota(
- WebKit::WebFrame* frame,
- WebKit::WebStorageQuotaType type,
+ blink::WebFrame* frame,
+ blink::WebStorageQuotaType type,
unsigned long long requested_size,
- WebKit::WebStorageQuotaCallbacks* callbacks);
+ blink::WebStorageQuotaCallbacks* callbacks);
virtual void willOpenSocketStream(
- WebKit::WebSocketStreamHandle* handle);
- virtual void willStartUsingPeerConnectionHandler(WebKit::WebFrame* frame,
- WebKit::WebRTCPeerConnectionHandler* handler);
+ blink::WebSocketStreamHandle* handle);
+ virtual void willStartUsingPeerConnectionHandler(blink::WebFrame* frame,
+ blink::WebRTCPeerConnectionHandler* handler);
virtual bool willCheckAndDispatchMessageEvent(
- WebKit::WebFrame* sourceFrame,
- WebKit::WebFrame* targetFrame,
- WebKit::WebSecurityOrigin targetOrigin,
- WebKit::WebDOMMessageEvent event);
- virtual WebKit::WebString acceptLanguages();
- virtual WebKit::WebString userAgentOverride(
- WebKit::WebFrame* frame,
- const WebKit::WebURL& url);
- virtual WebKit::WebString doNotTrackValue(WebKit::WebFrame* frame);
- virtual bool allowWebGL(WebKit::WebFrame* frame, bool default_value);
+ blink::WebFrame* sourceFrame,
+ blink::WebFrame* targetFrame,
+ blink::WebSecurityOrigin targetOrigin,
+ blink::WebDOMMessageEvent event);
+ virtual blink::WebString acceptLanguages();
+ virtual blink::WebString userAgentOverride(
+ blink::WebFrame* frame,
+ const blink::WebURL& url);
+ virtual blink::WebString doNotTrackValue(blink::WebFrame* frame);
+ virtual bool allowWebGL(blink::WebFrame* frame, bool default_value);
virtual void didLoseWebGLContext(
- WebKit::WebFrame* frame,
+ blink::WebFrame* frame,
int arb_robustness_status_code);
- // WebKit::WebPageSerializerClient implementation ----------------------------
+ // blink::WebPageSerializerClient implementation ----------------------------
virtual void didSerializeDataForFrame(
- const WebKit::WebURL& frame_url,
- const WebKit::WebCString& data,
+ const blink::WebURL& frame_url,
+ const blink::WebCString& data,
PageSerializationStatus status) OVERRIDE;
// RenderView implementation -------------------------------------------------
virtual bool Send(IPC::Message* message) OVERRIDE;
+ virtual RenderFrame* GetMainRenderFrame() OVERRIDE;
virtual int GetRoutingID() const OVERRIDE;
virtual int GetPageId() const OVERRIDE;
virtual gfx::Size GetSize() const OVERRIDE;
virtual WebPreferences& GetWebkitPreferences() OVERRIDE;
virtual void SetWebkitPreferences(const WebPreferences& preferences) OVERRIDE;
- virtual WebKit::WebView* GetWebView() OVERRIDE;
- virtual WebKit::WebNode GetFocusedNode() const OVERRIDE;
- virtual WebKit::WebNode GetContextMenuNode() const OVERRIDE;
- virtual bool IsEditableNode(const WebKit::WebNode& node) const OVERRIDE;
- virtual WebKit::WebPlugin* CreatePlugin(
- WebKit::WebFrame* frame,
- const WebPluginInfo& info,
- const WebKit::WebPluginParams& params) OVERRIDE;
- virtual void EvaluateScript(const string16& frame_xpath,
- const string16& jscript,
+ virtual blink::WebView* GetWebView() OVERRIDE;
+ virtual blink::WebNode GetFocusedNode() const OVERRIDE;
+ virtual blink::WebNode GetContextMenuNode() const OVERRIDE;
+ virtual bool IsEditableNode(const blink::WebNode& node) const OVERRIDE;
+ virtual void EvaluateScript(const base::string16& frame_xpath,
+ const base::string16& jscript,
int id,
bool notify_result) OVERRIDE;
virtual bool ShouldDisplayScrollbars(int width, int height) const OVERRIDE;
virtual int GetEnabledBindings() const OVERRIDE;
virtual bool GetContentStateImmediately() const OVERRIDE;
virtual float GetFilteredTimePerFrame() const OVERRIDE;
- virtual int ShowContextMenu(ContextMenuClient* client,
- const ContextMenuParams& params) OVERRIDE;
- virtual void CancelContextMenu(int request_id) OVERRIDE;
- virtual WebKit::WebPageVisibilityState GetVisibilityState() const OVERRIDE;
- virtual void RunModalAlertDialog(WebKit::WebFrame* frame,
- const WebKit::WebString& message) OVERRIDE;
- virtual void LoadURLExternally(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request,
- WebKit::WebNavigationPolicy policy) OVERRIDE;
+ virtual blink::WebPageVisibilityState GetVisibilityState() const OVERRIDE;
+ virtual void RunModalAlertDialog(blink::WebFrame* frame,
+ const blink::WebString& message) OVERRIDE;
virtual void DidStartLoading() OVERRIDE;
virtual void DidStopLoading() OVERRIDE;
virtual void Repaint(const gfx::Size& size) OVERRIDE;
virtual void SetEditCommandForNextKeyEvent(const std::string& name,
const std::string& value) OVERRIDE;
virtual void ClearEditCommands() OVERRIDE;
- virtual SSLStatus GetSSLStatusOfFrame(WebKit::WebFrame* frame) const OVERRIDE;
+ virtual SSLStatus GetSSLStatusOfFrame(blink::WebFrame* frame) const OVERRIDE;
+ virtual const std::string& GetAcceptLanguages() const OVERRIDE;
#if defined(OS_ANDROID)
virtual void UpdateTopControlsState(TopControlsState constraints,
TopControlsState current,
@@ -705,9 +676,9 @@ class CONTENT_EXPORT RenderViewImpl
// WebMediaPlayerDelegate implementation -----------------------
- virtual void DidPlay(WebKit::WebMediaPlayer* player) OVERRIDE;
- virtual void DidPause(WebKit::WebMediaPlayer* player) OVERRIDE;
- virtual void PlayerGone(WebKit::WebMediaPlayer* player) OVERRIDE;
+ virtual void DidPlay(blink::WebMediaPlayer* player) OVERRIDE;
+ virtual void DidPause(blink::WebMediaPlayer* player) OVERRIDE;
+ virtual void PlayerGone(blink::WebMediaPlayer* player) OVERRIDE;
// Please do not add your stuff randomly to the end here. If there is an
// appropriate section, add it there. If not, there are some random functions
@@ -722,7 +693,6 @@ class CONTENT_EXPORT RenderViewImpl
// RenderWidget overrides:
virtual void Close() OVERRIDE;
virtual void OnResize(const ViewMsg_Resize_Params& params) OVERRIDE;
- virtual void WillInitiatePaint() OVERRIDE;
virtual void DidInitiatePaint() OVERRIDE;
virtual void DidFlushPaint() OVERRIDE;
virtual PepperPluginInstanceImpl* GetBitmapForOptimizedPluginPaint(
@@ -734,13 +704,13 @@ class CONTENT_EXPORT RenderViewImpl
virtual gfx::Vector2d GetScrollOffset() OVERRIDE;
virtual void DidHandleKeyEvent() OVERRIDE;
virtual bool WillHandleMouseEvent(
- const WebKit::WebMouseEvent& event) OVERRIDE;
+ const blink::WebMouseEvent& event) OVERRIDE;
virtual bool WillHandleKeyEvent(
- const WebKit::WebKeyboardEvent& event) OVERRIDE;
+ const blink::WebKeyboardEvent& event) OVERRIDE;
virtual bool WillHandleGestureEvent(
- const WebKit::WebGestureEvent& event) OVERRIDE;
- virtual void DidHandleMouseEvent(const WebKit::WebMouseEvent& event) OVERRIDE;
- virtual void DidHandleTouchEvent(const WebKit::WebTouchEvent& event) OVERRIDE;
+ const blink::WebGestureEvent& event) OVERRIDE;
+ virtual void DidHandleMouseEvent(const blink::WebMouseEvent& event) OVERRIDE;
+ virtual void DidHandleTouchEvent(const blink::WebTouchEvent& event) OVERRIDE;
virtual bool HasTouchEventHandlersAt(const gfx::Point& point) const OVERRIDE;
virtual void OnSetFocus(bool enable) OVERRIDE;
virtual void OnWasHidden() OVERRIDE;
@@ -748,11 +718,11 @@ class CONTENT_EXPORT RenderViewImpl
virtual GURL GetURLForGraphicsContext3D() OVERRIDE;
virtual bool ForceCompositingModeEnabled() OVERRIDE;
virtual void OnImeSetComposition(
- const string16& text,
- const std::vector<WebKit::WebCompositionUnderline>& underlines,
+ const base::string16& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
int selection_end) OVERRIDE;
- virtual void OnImeConfirmComposition(const string16& text,
+ virtual void OnImeConfirmComposition(const base::string16& text,
const gfx::Range& replacement_range,
bool keep_selection) OVERRIDE;
virtual void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
@@ -765,7 +735,7 @@ class CONTENT_EXPORT RenderViewImpl
#endif
virtual bool CanComposeInline() OVERRIDE;
virtual void DidCommitCompositorFrame() OVERRIDE;
- virtual void InstrumentWillBeginFrame() OVERRIDE;
+ virtual void InstrumentWillBeginFrame(int frame_id) OVERRIDE;
virtual void InstrumentDidBeginFrame() OVERRIDE;
virtual void InstrumentDidCancelFrame() OVERRIDE;
virtual void InstrumentWillComposite() OVERRIDE;
@@ -775,6 +745,10 @@ class CONTENT_EXPORT RenderViewImpl
explicit RenderViewImpl(RenderViewImplParams* params);
void Initialize(RenderViewImplParams* params);
+ virtual void SetScreenMetricsEmulationParameters(
+ float device_scale_factor,
+ const gfx::Point& root_layer_offset,
+ float root_layer_scale) OVERRIDE;
// Do not delete directly. This class is reference counted.
virtual ~RenderViewImpl();
@@ -822,6 +796,8 @@ class CONTENT_EXPORT RenderViewImpl
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
GetCompositionCharacterBoundsTest);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnNavigationHttpPost);
+ FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
+ DecideNavigationPolicyHandlesAllTopLevel);
#if defined(OS_MACOSX)
FRIEND_TEST_ALL_PREFIXES(RenderViewTest, MacTestCmdUp);
#endif
@@ -832,6 +808,9 @@ class CONTENT_EXPORT RenderViewImpl
ShouldUpdateSelectionTextFromContextMenuParams);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, BasicRenderFrame);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, TextInputTypeWithPepper);
+ FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
+ MessageOrderInDidChangeSelection);
+ FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, SendCandidateWindowEvents);
FRIEND_TEST_ALL_PREFIXES(SuppressErrorPageTest, Suppresses);
FRIEND_TEST_ALL_PREFIXES(SuppressErrorPageTest, DoesNotSuppress);
@@ -843,22 +822,22 @@ class CONTENT_EXPORT RenderViewImpl
CONNECTION_ERROR,
};
- static WebKit::WebReferrerPolicy GetReferrerPolicyFromRequest(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request);
+ static blink::WebReferrerPolicy GetReferrerPolicyFromRequest(
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request);
static Referrer GetReferrerFromRequest(
- WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& request);
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& request);
static webkit_glue::WebURLResponseExtraDataImpl* GetExtraDataFromResponse(
- const WebKit::WebURLResponse& response);
+ const blink::WebURLResponse& response);
- void UpdateURL(WebKit::WebFrame* frame);
- void UpdateTitle(WebKit::WebFrame* frame, const string16& title,
- WebKit::WebTextDirection title_direction);
- void UpdateSessionHistory(WebKit::WebFrame* frame);
- void SendUpdateState(const WebKit::WebHistoryItem& item);
+ void UpdateURL(blink::WebFrame* frame);
+ void UpdateTitle(blink::WebFrame* frame, const base::string16& title,
+ blink::WebTextDirection title_direction);
+ void UpdateSessionHistory(blink::WebFrame* frame);
+ void SendUpdateState(const blink::WebHistoryItem& item);
// Update current main frame's encoding and send it to browser window.
// Since we want to let users see the right encoding info from menu
@@ -873,25 +852,25 @@ class CONTENT_EXPORT RenderViewImpl
// c) function:DidFinishDocumentLoadForFrame. When this function is
// called, that means we have got whole html page. In here we should
// finally get right encoding of page.
- void UpdateEncoding(WebKit::WebFrame* frame,
+ void UpdateEncoding(blink::WebFrame* frame,
const std::string& encoding_name);
- void OpenURL(WebKit::WebFrame* frame,
+ void OpenURL(blink::WebFrame* frame,
const GURL& url,
const Referrer& referrer,
- WebKit::WebNavigationPolicy policy);
+ blink::WebNavigationPolicy policy);
bool RunJavaScriptMessage(JavaScriptMessageType type,
- const string16& message,
- const string16& default_value,
+ const base::string16& message,
+ const base::string16& default_value,
const GURL& frame_url,
- string16* result);
+ base::string16* result);
// Sends a message and runs a nested message loop.
bool SendAndRunNestedMessageLoop(IPC::SyncMessage* message);
// Called when the "pinned to left/right edge" state needs to be updated.
- void UpdateScrollState(WebKit::WebFrame* frame);
+ void UpdateScrollState(blink::WebFrame* frame);
// IPC message handlers ------------------------------------------------------
//
@@ -906,15 +885,14 @@ class CONTENT_EXPORT RenderViewImpl
void OnPaste();
void OnPasteAndMatchStyle();
void OnRedo();
- void OnReplace(const string16& text);
- void OnReplaceMisspelling(const string16& text);
+ void OnReplace(const base::string16& text);
+ void OnReplaceMisspelling(const base::string16& text);
void OnScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
void OnSelectAll();
void OnSelectRange(const gfx::Point& start, const gfx::Point& end);
void OnSetEditCommandsForNextKeyEvent(const EditCommands& edit_commands);
void OnUndo();
void OnUnselect();
-
void OnAllowBindings(int enabled_bindings_flags);
void OnAllowScriptToClose(bool script_can_close);
void OnCancelDownload(int32 download_id);
@@ -923,7 +901,7 @@ class CONTENT_EXPORT RenderViewImpl
void OnContextMenuClosed(const CustomContextMenuContext& custom_context);
void OnShowContextMenu(const gfx::Point& location);
void OnCopyImageAt(int x, int y);
- void OnCSSInsertRequest(const string16& frame_xpath,
+ void OnCSSInsertRequest(const base::string16& frame_xpath,
const std::string& css);
void OnCustomContextMenuAction(const CustomContextMenuContext& custom_context,
unsigned action);
@@ -934,7 +912,7 @@ class CONTENT_EXPORT RenderViewImpl
void OnDragSourceEndedOrMoved(const gfx::Point& client_point,
const gfx::Point& screen_point,
bool ended,
- WebKit::WebDragOperation drag_operation);
+ blink::WebDragOperation drag_operation);
void OnDragSourceSystemDragEnded();
void OnDragTargetDrop(const gfx::Point& client_pt,
const gfx::Point& screen_pt,
@@ -942,12 +920,12 @@ class CONTENT_EXPORT RenderViewImpl
void OnDragTargetDragEnter(const DropData& drop_data,
const gfx::Point& client_pt,
const gfx::Point& screen_pt,
- WebKit::WebDragOperationsMask operations_allowed,
+ blink::WebDragOperationsMask operations_allowed,
int key_modifiers);
void OnDragTargetDragLeave();
void OnDragTargetDragOver(const gfx::Point& client_pt,
const gfx::Point& screen_pt,
- WebKit::WebDragOperationsMask operations_allowed,
+ blink::WebDragOperationsMask operations_allowed,
int key_modifiers);
void OnEnablePreferredSizeChangedMode();
void OnEnableAutoResize(const gfx::Size& min_size, const gfx::Size& max_size);
@@ -957,28 +935,27 @@ class CONTENT_EXPORT RenderViewImpl
void OnExtendSelectionAndDelete(int before, int after);
void OnFileChooserResponse(
const std::vector<ui::SelectedFileInfo>& files);
- void OnFind(int request_id, const string16&, const WebKit::WebFindOptions&);
+ void OnFind(int request_id,
+ const base::string16&,
+ const blink::WebFindOptions&);
void OnGetAllSavableResourceLinksForCurrentPage(const GURL& page_url);
void OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
const std::vector<GURL>& links,
const std::vector<base::FilePath>& local_paths,
const base::FilePath& local_directory_name);
void OnMediaPlayerActionAt(const gfx::Point& location,
- const WebKit::WebMediaPlayerAction& action);
-
- // Screen has rotated. 0 = default (portrait), 90 = one turn right, and so on.
+ const blink::WebMediaPlayerAction& action);
void OnOrientationChangeEvent(int orientation);
-
void OnPluginActionAt(const gfx::Point& location,
- const WebKit::WebPluginAction& action);
+ const blink::WebPluginAction& action);
void OnMoveOrResizeStarted();
void OnNavigate(const ViewMsg_Navigate_Params& params);
void OnPostMessageEvent(const ViewMsg_PostMessage_Params& params);
void OnReleaseDisambiguationPopupDIB(TransportDIB::Handle dib_handle);
void OnReloadFrame();
void OnResetPageEncodingToDefault();
- void OnScriptEvalRequest(const string16& frame_xpath,
- const string16& jscript,
+ void OnScriptEvalRequest(const base::string16& frame_xpath,
+ const base::string16& jscript,
int id,
bool notify_result);
void OnSetAccessibilityMode(AccessibilityMode new_mode);
@@ -987,7 +964,7 @@ class CONTENT_EXPORT RenderViewImpl
void OnSetBackground(const SkBitmap& background);
void OnSetCompositionFromExistingText(
int start, int end,
- const std::vector<WebKit::WebCompositionUnderline>& underlines);
+ const std::vector<blink::WebCompositionUnderline>& underlines);
void OnExitFullscreen();
void OnSetEditableSelectionOffsets(int start, int end);
void OnSetHistoryLengthAndPrune(int history_length, int32 minimum_page_id);
@@ -1000,21 +977,18 @@ class CONTENT_EXPORT RenderViewImpl
void OnShouldClose();
void OnStop();
void OnStopFinding(StopFindAction action);
+ void OnSuppressDialogsUntilSwapOut();
void OnSwapOut();
void OnThemeChanged();
void OnUpdateTargetURLAck();
void OnUpdateTimezone();
void OnUpdateWebPreferences(const WebPreferences& prefs);
-
void OnZoom(PageZoom zoom);
void OnZoomFactor(PageZoom zoom, int zoom_center_x, int zoom_center_y);
-
void OnEnableViewSourceMode();
-
- void OnJavaBridgeInit();
-
void OnDisownOpener();
-
+ void OnWindowSnapshotCompleted(const int snapshot_id,
+ const gfx::Size& size, const std::vector<unsigned char>& png);
#if defined(OS_ANDROID)
void OnActivateNearestFindResult(int request_id, float x, float y);
void OnFindMatchRects(int current_version);
@@ -1025,10 +999,11 @@ class CONTENT_EXPORT RenderViewImpl
bool enable_showing,
bool animate);
void OnPauseVideo();
-
+ void OnExtractSmartClipData(const gfx::Rect& rect);
#elif defined(OS_MACOSX)
void OnCopyToFindPboard();
- void OnPluginImeCompositionCompleted(const string16& text, int plugin_id);
+ void OnPluginImeCompositionCompleted(const base::string16& text,
+ int plugin_id);
void OnSelectPopupMenuItem(int selected_index);
void OnSetInLiveResize(bool in_live_resize);
void OnSetWindowVisibility(bool visible);
@@ -1036,10 +1011,6 @@ class CONTENT_EXPORT RenderViewImpl
const gfx::Rect& view_frame);
#endif
- void OnWindowSnapshotCompleted(const int snapshot_id,
- const gfx::Size& size, const std::vector<unsigned char>& png);
-
-
// Adding a new message handler? Please add it in alphabetical order above
// and put it in the same position in the .cc file.
@@ -1047,9 +1018,9 @@ class CONTENT_EXPORT RenderViewImpl
void ZoomFactorHelper(PageZoom zoom, int zoom_center_x, int zoom_center_y,
float scaling_increment);
- void AltErrorPageFinished(WebKit::WebFrame* frame,
- const WebKit::WebURLRequest& original_request,
- const WebKit::WebURLError& original_error,
+ void AltErrorPageFinished(blink::WebFrame* frame,
+ const blink::WebURLRequest& original_request,
+ const blink::WebURLError& original_error,
const std::string& html);
// Check whether the preferred size has changed.
@@ -1078,25 +1049,25 @@ class CONTENT_EXPORT RenderViewImpl
ErrorPageType error_type);
// Locates a sub frame with given xpath
- WebKit::WebFrame* GetChildFrame(const string16& frame_xpath) const;
+ blink::WebFrame* GetChildFrame(const base::string16& frame_xpath) const;
// Returns the URL being loaded by the given frame's request.
- GURL GetLoadingUrl(WebKit::WebFrame* frame) const;
+ GURL GetLoadingUrl(blink::WebFrame* frame) const;
// Should only be called if this object wraps a PluginDocument.
- WebKit::WebPlugin* GetWebPluginFromPluginDocument();
+ blink::WebPlugin* GetWebPluginFromPluginDocument();
// Returns true if the |params| navigation is to an entry that has been
// cropped due to a recent navigation the browser did not know about.
bool IsBackForwardToStaleEntry(const ViewMsg_Navigate_Params& params,
bool is_reload);
- bool MaybeLoadAlternateErrorPage(WebKit::WebFrame* frame,
- const WebKit::WebURLError& error,
+ bool MaybeLoadAlternateErrorPage(blink::WebFrame* frame,
+ const blink::WebURLError& error,
bool replace);
// Make this RenderView show an empty, unscriptable page.
- void NavigateToSwappedOutURL(WebKit::WebFrame* frame);
+ void NavigateToSwappedOutURL(blink::WebFrame* frame);
// If we initiated a navigation, this function will populate |document_state|
// with the navigation information saved in OnNavigate().
@@ -1113,20 +1084,30 @@ class CONTENT_EXPORT RenderViewImpl
#if defined(OS_ANDROID)
// Launch an Android content intent with the given URL.
void LaunchAndroidContentIntent(const GURL& intent_url, size_t request_id);
+
+ blink::WebMediaPlayer* CreateAndroidWebMediaPlayer(
+ blink::WebFrame* frame,
+ const blink::WebURL& url,
+ blink::WebMediaPlayerClient* client);
#endif
+ blink::WebMediaPlayer* CreateWebMediaPlayerForMediaStream(
+ blink::WebFrame* frame,
+ const blink::WebURL& url,
+ blink::WebMediaPlayerClient* client);
+
// Sends a reply to the current find operation handling if it was a
// synchronous find request.
void SendFindReply(int request_id,
int match_count,
int ordinal,
- const WebKit::WebRect& selection_rect,
+ const blink::WebRect& selection_rect,
bool final_status_update);
// Returns whether |params.selection_text| should be synchronized to the
// browser before bringing up the context menu. Static for testing.
static bool ShouldUpdateSelectionTextFromContextMenuParams(
- const string16& selection_text,
+ const base::string16& selection_text,
size_t selection_text_offset,
const gfx::Range& selection_range,
const ContextMenuParams& params);
@@ -1161,6 +1142,31 @@ class CONTENT_EXPORT RenderViewImpl
gfx::RectF ClientRectToPhysicalWindowRect(const gfx::RectF& rect) const;
+ // Helper for LatencyInfo construction.
+ int64 GetLatencyComponentId();
+
+ // RenderFrameImpl accessible state ------------------------------------------
+ // The following section is the set of methods that RenderFrameImpl needs
+ // to access RenderViewImpl state. The set of state variables are page-level
+ // specific, so they don't belong in RenderFrameImpl and should remain in
+ // this object.
+ ObserverList<RenderViewObserver>& observers() {
+ return observers_;
+ }
+
+ // TODO(nasko): Remove this method when we move to frame proxy objects, since
+ // the concept of swapped out will be eliminated.
+ void set_is_swapped_out(bool swapped_out) {
+ is_swapped_out_ = swapped_out;
+ }
+
+ NavigationGesture navigation_gesture() {
+ return navigation_gesture_;
+ }
+ void set_navigation_gesture(NavigationGesture gesture) {
+ navigation_gesture_ = gesture;
+ }
+
// ---------------------------------------------------------------------------
// ADDING NEW FUNCTIONS? Please keep private functions alphabetized and put
// it in the same order in the .cc file as it was in the header.
@@ -1215,6 +1221,11 @@ class CONTENT_EXPORT RenderViewImpl
// decidePolicyForNavigation for details.
bool opener_suppressed_;
+ // Whether we must stop creating nested message loops for modal dialogs until
+ // OnSwapOut is called. This is necessary because modal dialogs have a
+ // PageGroupLoadDeferrer on the stack that interferes with swapping out.
+ bool suppress_dialogs_until_swap_out_;
+
// Holds state pertaining to a navigation that we initiated. This is held by
// the WebDataSource::ExtraData attribute. We use pending_navigation_state_
// as a temporary holder for the state until the WebDataSource corresponding
@@ -1296,7 +1307,7 @@ class CONTENT_EXPORT RenderViewImpl
// portion of this string that is the actual selected text starts at index
// |selection_range_.GetMin() - selection_text_offset_| and has length
// |selection_range_.length()|.
- string16 selection_text_;
+ base::string16 selection_text_;
// The offset corresponding to the start of |selection_text_| in the document.
size_t selection_text_offset_;
// Range over the document corresponding to the actual selected text (which
@@ -1375,7 +1386,7 @@ class CONTENT_EXPORT RenderViewImpl
// MediaStreamClient attached to this view; lazily initialized.
MediaStreamClient* media_stream_client_;
- WebKit::WebUserMediaClient* web_user_media_client_;
+ blink::WebUserMediaClient* web_user_media_client_;
// MIDIClient attached to this view; lazily initialized.
MIDIDispatcher* midi_dispatcher_;
@@ -1389,9 +1400,6 @@ class CONTENT_EXPORT RenderViewImpl
// AccessibilityModeOff.
RendererAccessibility* renderer_accessibility_;
- // Java Bridge dispatcher attached to this view; lazily initialized.
- JavaBridgeDispatcher* java_bridge_dispatcher_;
-
// Mouse Lock dispatcher attached to this view.
MouseLockDispatcher* mouse_lock_dispatcher_;
@@ -1411,12 +1419,9 @@ class CONTENT_EXPORT RenderViewImpl
typedef std::vector< linked_ptr<ContentDetector> > ContentDetectorList;
ContentDetectorList content_detectors_;
- // Proxy class for WebMediaPlayer to communicate with the real media player
- // objects in browser process.
- WebMediaPlayerProxyAndroid* media_player_proxy_;
-
- // The media player manager for managing all the media players on this view.
- scoped_ptr<RendererMediaPlayerManager> media_player_manager_;
+ // The media player manager for managing all the media players on this view
+ // for communicating with the real media player objects in browser process.
+ RendererMediaPlayerManager* media_player_manager_;
// A date/time picker object for date and time related input elements.
scoped_ptr<RendererDateTimePicker> date_time_picker_client_;
@@ -1435,20 +1440,18 @@ class CONTENT_EXPORT RenderViewImpl
#endif
#if defined(ENABLE_PLUGINS)
- typedef std::set<PepperPluginInstanceImpl*> PepperPluginSet;
- PepperPluginSet active_pepper_instances_;
+ // TODO(jam): these belong on RenderFrame, once the browser knows which frame
+ // is focused and sends the IPCs which use these to the correct frame. Until
+ // then, we must store these on RenderView as that's the one place that knows
+ // about all the RenderFrames for a page.
// Whether or not the focus is on a PPAPI plugin
PepperPluginInstanceImpl* focused_pepper_plugin_;
- // Current text input composition text. Empty if no composition is in
- // progress.
- string16 pepper_composition_text_;
-
// The plugin instance that received the last mouse event. It is set to NULL
// if the last mouse event went to elements other than Pepper plugins.
- // |pepper_last_mouse_event_target_| is not owned by this class. We can know
- // about when it is destroyed via InstanceDeleted().
+ // |pepper_last_mouse_event_target_| is not owned by this class. We depend on
+ // the RenderFrameImpl to NULL it out when it destructs.
PepperPluginInstanceImpl* pepper_last_mouse_event_target_;
#endif
@@ -1462,7 +1465,7 @@ class CONTENT_EXPORT RenderViewImpl
std::deque< linked_ptr<PendingFileChooser> > file_chooser_completions_;
// The current directory enumeration callback
- std::map<int, WebKit::WebFileChooserCompletion*> enumeration_completions_;
+ std::map<int, blink::WebFileChooserCompletion*> enumeration_completions_;
int enumeration_completion_id_;
// Reports load progress to the browser.
@@ -1481,7 +1484,7 @@ class CONTENT_EXPORT RenderViewImpl
scoped_ptr<ExternalPopupMenu> external_popup_menu_;
// The node that the context menu was pressed over.
- WebKit::WebNode context_menu_node_;
+ blink::WebNode context_menu_node_;
// All the registered observers. We expect this list to be small, so vector
// is fine.
@@ -1507,10 +1510,6 @@ class CONTENT_EXPORT RenderViewImpl
// DOM automation bindings are enabled.
scoped_ptr<DomAutomationController> dom_automation_controller_;
- // Allows JS to read out a variety of internal various metrics. The JS object
- // is only exposed when the stats collection bindings are enabled.
- scoped_ptr<StatsCollectionController> stats_collection_controller_;
-
// 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_impl_android.cc b/chromium/content/renderer/render_view_impl_android.cc
index 18f41a29ac6..679da548f91 100644
--- a/chromium/content/renderer/render_view_impl_android.cc
+++ b/chromium/content/renderer/render_view_impl_android.cc
@@ -7,7 +7,9 @@
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "cc/trees/layer_tree_host.h"
+#include "content/common/view_messages.h"
#include "content/renderer/gpu/render_widget_compositor.h"
+#include "third_party/WebKit/public/web/WebView.h"
namespace content {
@@ -51,7 +53,7 @@ void RenderViewImpl::UpdateTopControlsState(TopControlsState constraints,
top_controls_constraints_ = constraints_cc;
}
-void RenderViewImpl::didScrollWithKeyboard(const WebKit::WebSize& delta) {
+void RenderViewImpl::didScrollWithKeyboard(const blink::WebSize& delta) {
if (delta.height == 0)
return;
if (compositor_) {
@@ -62,4 +64,9 @@ void RenderViewImpl::didScrollWithKeyboard(const WebKit::WebSize& delta) {
}
}
+void RenderViewImpl::OnExtractSmartClipData(const gfx::Rect& rect) {
+ Send(new ViewHostMsg_SmartClipDataExtracted(
+ routing_id_, webview()->getSmartClipData(rect)));
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_view_impl_params.cc b/chromium/content/renderer/render_view_impl_params.cc
index 44c8353090b..0e77ea41aaa 100644
--- a/chromium/content/renderer/render_view_impl_params.cc
+++ b/chromium/content/renderer/render_view_impl_params.cc
@@ -14,12 +14,12 @@ RenderViewImplParams::RenderViewImplParams(
int32 main_frame_routing_id,
int32 surface_id,
int64 session_storage_namespace_id,
- const string16& frame_name,
+ const base::string16& frame_name,
bool is_renderer_created,
bool swapped_out,
bool hidden,
int32 next_page_id,
- const WebKit::WebScreenInfo& screen_info,
+ const blink::WebScreenInfo& screen_info,
AccessibilityMode accessibility_mode,
bool allow_partial_swap)
: opener_id(opener_id),
diff --git a/chromium/content/renderer/render_view_impl_params.h b/chromium/content/renderer/render_view_impl_params.h
index 07a4f41b494..5993f308999 100644
--- a/chromium/content/renderer/render_view_impl_params.h
+++ b/chromium/content/renderer/render_view_impl_params.h
@@ -13,7 +13,7 @@
struct WebPreferences;
-namespace WebKit {
+namespace blink {
struct WebScreenInfo;
}
@@ -30,12 +30,12 @@ struct CONTENT_EXPORT RenderViewImplParams {
int32 main_frame_routing_id,
int32 surface_id,
int64 session_storage_namespace_id,
- const string16& frame_name,
+ const base::string16& frame_name,
bool is_renderer_created,
bool swapped_out,
bool hidden,
int32 next_page_id,
- const WebKit::WebScreenInfo& screen_info,
+ const blink::WebScreenInfo& screen_info,
AccessibilityMode accessibility_mode,
bool allow_partial_swap);
~RenderViewImplParams();
@@ -47,12 +47,12 @@ struct CONTENT_EXPORT RenderViewImplParams {
int32 main_frame_routing_id;
int32 surface_id;
int64 session_storage_namespace_id;
- const string16& frame_name;
+ const base::string16& frame_name;
bool is_renderer_created;
bool swapped_out;
bool hidden;
int32 next_page_id;
- const WebKit::WebScreenInfo& screen_info;
+ const blink::WebScreenInfo& screen_info;
AccessibilityMode accessibility_mode;
bool allow_partial_swap;
};
diff --git a/chromium/content/renderer/render_view_linux.cc b/chromium/content/renderer/render_view_linux.cc
index 01218adc97f..41f558c2085 100644
--- a/chromium/content/renderer/render_view_linux.cc
+++ b/chromium/content/renderer/render_view_linux.cc
@@ -7,7 +7,7 @@
#include "content/public/common/renderer_preferences.h"
#include "third_party/WebKit/public/web/linux/WebFontRendering.h"
-using WebKit::WebFontRendering;
+using blink::WebFontRendering;
namespace content {
diff --git a/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc b/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc
index 41d21b7bfc5..25b4ccc4ff2 100644
--- a/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc
+++ b/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc
@@ -11,7 +11,7 @@
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/WebKit/public/web/WebWidget.h"
-using WebKit::WebUserGestureIndicator;
+using blink::WebUserGestureIndicator;
namespace content {
diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc
index dc4a9025a13..852e94e1c8b 100644
--- a/chromium/content/renderer/render_widget.cc
+++ b/chromium/content/renderer/render_widget.cc
@@ -16,44 +16,49 @@
#include "base/strings/utf_string_conversions.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/trees/layer_tree_host.h"
#include "content/child/npapi/webplugin.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "content/common/gpu/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"
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/cursor_utils.h"
+#include "content/renderer/external_popup_menu.h"
#include "content/renderer/gpu/compositor_output_surface.h"
#include "content/renderer/gpu/compositor_software_output_device.h"
#include "content/renderer/gpu/delegated_compositor_output_surface.h"
-#include "content/renderer/gpu/input_handler_manager.h"
#include "content/renderer/gpu/mailbox_output_surface.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/ime_event_guard.h"
+#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_webkitplatformsupport_impl.h"
+#include "content/renderer/resizing_mode_selector.h"
#include "ipc/ipc_sync_message.h"
#include "skia/ext/platform_canvas.h"
+#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-#include "third_party/WebKit/public/platform/WebPoint.h"
#include "third_party/WebKit/public/platform/WebRect.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/web/WebCursorInfo.h"
#include "third_party/WebKit/public/web/WebHelperPlugin.h"
#include "third_party/WebKit/public/web/WebPagePopup.h"
#include "third_party/WebKit/public/web/WebPopupMenu.h"
#include "third_party/WebKit/public/web/WebPopupMenuInfo.h"
#include "third_party/WebKit/public/web/WebRange.h"
-#include "third_party/WebKit/public/web/WebScreenInfo.h"
#include "third_party/skia/include/core/SkShader.h"
#include "ui/base/ui_base_switches.h"
-#include "ui/gfx/point.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/skia_util.h"
@@ -74,72 +79,29 @@
#include "third_party/WebKit/public/web/WebWidget.h"
-using WebKit::WebCompositionUnderline;
-using WebKit::WebCursorInfo;
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebKeyboardEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebNavigationPolicy;
-using WebKit::WebPagePopup;
-using WebKit::WebPoint;
-using WebKit::WebPopupMenu;
-using WebKit::WebPopupMenuInfo;
-using WebKit::WebPopupType;
-using WebKit::WebRange;
-using WebKit::WebRect;
-using WebKit::WebScreenInfo;
-using WebKit::WebSize;
-using WebKit::WebTextDirection;
-using WebKit::WebTouchEvent;
-using WebKit::WebVector;
-using WebKit::WebWidget;
+using blink::WebCompositionUnderline;
+using blink::WebCursorInfo;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebNavigationPolicy;
+using blink::WebPagePopup;
+using blink::WebPopupMenu;
+using blink::WebPopupMenuInfo;
+using blink::WebPopupType;
+using blink::WebRange;
+using blink::WebRect;
+using blink::WebScreenInfo;
+using blink::WebSize;
+using blink::WebTextDirection;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+using blink::WebVector;
+using blink::WebWidget;
namespace {
-const char* GetEventName(WebInputEvent::Type type) {
-#define CASE_TYPE(t) case WebInputEvent::t: return #t
- switch(type) {
- CASE_TYPE(Undefined);
- CASE_TYPE(MouseDown);
- CASE_TYPE(MouseUp);
- CASE_TYPE(MouseMove);
- CASE_TYPE(MouseEnter);
- CASE_TYPE(MouseLeave);
- CASE_TYPE(ContextMenu);
- CASE_TYPE(MouseWheel);
- CASE_TYPE(RawKeyDown);
- CASE_TYPE(KeyDown);
- CASE_TYPE(KeyUp);
- CASE_TYPE(Char);
- CASE_TYPE(GestureScrollBegin);
- CASE_TYPE(GestureScrollEnd);
- CASE_TYPE(GestureScrollUpdate);
- CASE_TYPE(GestureFlingStart);
- CASE_TYPE(GestureFlingCancel);
- CASE_TYPE(GestureTap);
- CASE_TYPE(GestureTapUnconfirmed);
- CASE_TYPE(GestureTapDown);
- CASE_TYPE(GestureTapCancel);
- CASE_TYPE(GestureDoubleTap);
- CASE_TYPE(GestureTwoFingerTap);
- CASE_TYPE(GestureLongPress);
- CASE_TYPE(GestureLongTap);
- CASE_TYPE(GesturePinchBegin);
- CASE_TYPE(GesturePinchEnd);
- CASE_TYPE(GesturePinchUpdate);
- CASE_TYPE(TouchStart);
- CASE_TYPE(TouchMove);
- CASE_TYPE(TouchEnd);
- CASE_TYPE(TouchCancel);
- default:
- // Must include default to let WebKit::WebInputEvent add new event types
- // before they're added here.
- DLOG(WARNING) << "Unhandled WebInputEvent type in GetEventName.\n";
- break;
- }
-#undef CASE_TYPE
- return "";
-}
typedef std::map<std::string, ui::TextInputMode> TextInputModeMap;
@@ -148,47 +110,229 @@ class TextInputModeMapSingleton {
static TextInputModeMapSingleton* GetInstance() {
return Singleton<TextInputModeMapSingleton>::get();
}
- TextInputModeMapSingleton()
- : map() {
- map["verbatim"] = ui::TEXT_INPUT_MODE_VERBATIM;
- map["latin"] = ui::TEXT_INPUT_MODE_LATIN;
- map["latin-name"] = ui::TEXT_INPUT_MODE_LATIN_NAME;
- map["latin-prose"] = ui::TEXT_INPUT_MODE_LATIN_PROSE;
- map["full-width-latin"] = ui::TEXT_INPUT_MODE_FULL_WIDTH_LATIN;
- map["kana"] = ui::TEXT_INPUT_MODE_KANA;
- map["katakana"] = ui::TEXT_INPUT_MODE_KATAKANA;
- map["numeric"] = ui::TEXT_INPUT_MODE_NUMERIC;
- map["tel"] = ui::TEXT_INPUT_MODE_TEL;
- map["email"] = ui::TEXT_INPUT_MODE_EMAIL;
- map["url"] = ui::TEXT_INPUT_MODE_URL;
- }
- TextInputModeMap& Map() {
- return map;
- }
+ TextInputModeMapSingleton() {
+ map_["verbatim"] = ui::TEXT_INPUT_MODE_VERBATIM;
+ map_["latin"] = ui::TEXT_INPUT_MODE_LATIN;
+ map_["latin-name"] = ui::TEXT_INPUT_MODE_LATIN_NAME;
+ map_["latin-prose"] = ui::TEXT_INPUT_MODE_LATIN_PROSE;
+ map_["full-width-latin"] = ui::TEXT_INPUT_MODE_FULL_WIDTH_LATIN;
+ map_["kana"] = ui::TEXT_INPUT_MODE_KANA;
+ map_["katakana"] = ui::TEXT_INPUT_MODE_KATAKANA;
+ map_["numeric"] = ui::TEXT_INPUT_MODE_NUMERIC;
+ map_["tel"] = ui::TEXT_INPUT_MODE_TEL;
+ map_["email"] = ui::TEXT_INPUT_MODE_EMAIL;
+ map_["url"] = ui::TEXT_INPUT_MODE_URL;
+ }
+ const TextInputModeMap& map() const { return map_; }
private:
- TextInputModeMap map;
+ TextInputModeMap map_;
friend struct DefaultSingletonTraits<TextInputModeMapSingleton>;
DISALLOW_COPY_AND_ASSIGN(TextInputModeMapSingleton);
};
-ui::TextInputMode ConvertInputMode(
- const WebKit::WebString& input_mode) {
+ui::TextInputMode ConvertInputMode(const blink::WebString& input_mode) {
static TextInputModeMapSingleton* singleton =
TextInputModeMapSingleton::GetInstance();
- TextInputModeMap::iterator it = singleton->Map().find(input_mode.utf8());
- if (it == singleton->Map().end())
+ TextInputModeMap::const_iterator it =
+ singleton->map().find(input_mode.utf8());
+ if (it == singleton->map().end())
return ui::TEXT_INPUT_MODE_DEFAULT;
return it->second;
}
+// TODO(brianderson): Replace the hard-coded threshold with a fraction of
+// the BeginMainFrame interval.
+// 4166us will allow 1/4 of a 60Hz interval or 1/2 of a 120Hz interval to
+// be spent in input hanlders before input starts getting throttled.
+const int kInputHandlingTimeThrottlingThresholdMicroseconds = 4166;
+
} // namespace
namespace content {
-RenderWidget::RenderWidget(WebKit::WebPopupType popup_type,
- const WebKit::WebScreenInfo& screen_info,
+// RenderWidget::ScreenMetricsEmulator ----------------------------------------
+
+class RenderWidget::ScreenMetricsEmulator {
+ public:
+ ScreenMetricsEmulator(
+ RenderWidget* widget,
+ const gfx::Rect& device_rect,
+ const gfx::Rect& widget_rect,
+ float device_scale_factor,
+ bool fit_to_view);
+ virtual ~ScreenMetricsEmulator();
+
+ float scale() { return scale_; }
+ gfx::Point offset() { return offset_; }
+ gfx::Rect widget_rect() const { return widget_rect_; }
+ gfx::Rect original_screen_rect() const { return original_view_screen_rect_; }
+
+ void ChangeEmulationParams(
+ const gfx::Rect& device_rect,
+ const gfx::Rect& widget_rect,
+ float device_scale_factor,
+ bool fit_to_view);
+
+ // The following methods alter handlers' behavior for messages related to
+ // widget size and position.
+ void OnResizeMessage(const ViewMsg_Resize_Params& params);
+ void OnUpdateScreenRectsMessage(const gfx::Rect& view_screen_rect,
+ const gfx::Rect& window_screen_rect);
+ void OnShowContextMenu(ContextMenuParams* params);
+
+ private:
+ void Apply(float overdraw_bottom_height,
+ gfx::Rect resizer_rect, bool is_fullscreen);
+
+ RenderWidget* widget_;
+
+ // Parameters as passed by RenderWidget::EnableScreenMetricsEmulation.
+ gfx::Rect device_rect_;
+ gfx::Rect widget_rect_;
+ float device_scale_factor_;
+ bool fit_to_view_;
+
+ // The computed scale and offset used to fit widget into browser window.
+ float scale_;
+ gfx::Point offset_;
+
+ // Original values to restore back after emulation ends.
+ gfx::Size original_size_;
+ gfx::Size original_physical_backing_size_;
+ blink::WebScreenInfo original_screen_info_;
+ gfx::Rect original_view_screen_rect_;
+ gfx::Rect original_window_screen_rect_;
+};
+
+RenderWidget::ScreenMetricsEmulator::ScreenMetricsEmulator(
+ RenderWidget* widget,
+ const gfx::Rect& device_rect,
+ const gfx::Rect& widget_rect,
+ float device_scale_factor,
+ bool fit_to_view)
+ : widget_(widget),
+ device_rect_(device_rect),
+ widget_rect_(widget_rect),
+ device_scale_factor_(device_scale_factor),
+ fit_to_view_(fit_to_view),
+ scale_(1.f) {
+ original_size_ = widget_->size_;
+ original_physical_backing_size_ = widget_->physical_backing_size_;
+ original_screen_info_ = widget_->screen_info_;
+ original_view_screen_rect_ = widget_->view_screen_rect_;
+ original_window_screen_rect_ = widget_->window_screen_rect_;
+ Apply(widget_->overdraw_bottom_height_,
+ widget_->resizer_rect_, widget_->is_fullscreen_);
+}
+
+RenderWidget::ScreenMetricsEmulator::~ScreenMetricsEmulator() {
+ widget_->screen_info_ = original_screen_info_;
+
+ widget_->SetDeviceScaleFactor(original_screen_info_.deviceScaleFactor);
+ widget_->SetScreenMetricsEmulationParameters(0.f, gfx::Point(), 1.f);
+ widget_->view_screen_rect_ = original_view_screen_rect_;
+ widget_->window_screen_rect_ = original_window_screen_rect_;
+ widget_->Resize(original_size_, original_physical_backing_size_,
+ widget_->overdraw_bottom_height_, widget_->resizer_rect_,
+ widget_->is_fullscreen_, NO_RESIZE_ACK);
+}
+
+void RenderWidget::ScreenMetricsEmulator::ChangeEmulationParams(
+ const gfx::Rect& device_rect,
+ const gfx::Rect& widget_rect,
+ float device_scale_factor,
+ bool fit_to_view) {
+ device_rect_ = device_rect;
+ widget_rect_ = widget_rect;
+ device_scale_factor_ = device_scale_factor;
+ fit_to_view_ = fit_to_view;
+ Apply(widget_->overdraw_bottom_height_,
+ widget_->resizer_rect_, widget_->is_fullscreen_);
+}
+
+void RenderWidget::ScreenMetricsEmulator::Apply(
+ float overdraw_bottom_height, gfx::Rect resizer_rect, bool is_fullscreen) {
+ if (fit_to_view_) {
+ DCHECK(!original_size_.IsEmpty());
+
+ int width_with_gutter =
+ std::max(original_size_.width() - 2 * device_rect_.x(), 1);
+ int height_with_gutter =
+ std::max(original_size_.height() - 2 * device_rect_.y(), 1);
+ float width_ratio =
+ static_cast<float>(widget_rect_.width()) / width_with_gutter;
+ float height_ratio =
+ static_cast<float>(widget_rect_.height()) / height_with_gutter;
+ float ratio = std::max(1.0f, std::max(width_ratio, height_ratio));
+ scale_ = 1.f / ratio;
+ } else {
+ scale_ = 1.f;
+ }
+
+ // Center emulated view inside available view space.
+ offset_.set_x((original_size_.width() - scale_ * widget_rect_.width()) / 2);
+ offset_.set_y((original_size_.height() - scale_ * widget_rect_.height()) / 2);
+
+ widget_->screen_info_.rect = gfx::Rect(device_rect_.size());
+ widget_->screen_info_.availableRect = gfx::Rect(device_rect_.size());
+ widget_->screen_info_.deviceScaleFactor = device_scale_factor_;
+
+ // Pass three emulation parameters to the blink side:
+ // - we keep the real device scale factor in compositor to produce sharp image
+ // even when emulating different scale factor;
+ // - in order to fit into view, WebView applies offset and scale to the
+ // root layer.
+ widget_->SetScreenMetricsEmulationParameters(
+ original_screen_info_.deviceScaleFactor, offset_, scale_);
+
+ widget_->SetDeviceScaleFactor(device_scale_factor_);
+ widget_->view_screen_rect_ = widget_rect_;
+ widget_->window_screen_rect_ = widget_->screen_info_.availableRect;
+
+ gfx::Size physical_backing_size = gfx::ToCeiledSize(gfx::ScaleSize(
+ original_size_, original_screen_info_.deviceScaleFactor));
+ widget_->Resize(widget_rect_.size(), physical_backing_size,
+ overdraw_bottom_height, resizer_rect, is_fullscreen, NO_RESIZE_ACK);
+}
+
+void RenderWidget::ScreenMetricsEmulator::OnResizeMessage(
+ const ViewMsg_Resize_Params& params) {
+ bool need_ack = params.new_size != original_size_ &&
+ !params.new_size.IsEmpty() && !params.physical_backing_size.IsEmpty();
+ original_size_ = params.new_size;
+ original_physical_backing_size_ = params.physical_backing_size;
+ original_screen_info_ = params.screen_info;
+ Apply(params.overdraw_bottom_height, params.resizer_rect,
+ params.is_fullscreen);
+
+ if (need_ack) {
+ widget_->set_next_paint_is_resize_ack();
+ if (widget_->compositor_)
+ widget_->compositor_->SetNeedsRedrawRect(gfx::Rect(widget_->size_));
+ }
+}
+
+void RenderWidget::ScreenMetricsEmulator::OnUpdateScreenRectsMessage(
+ const gfx::Rect& view_screen_rect,
+ const gfx::Rect& window_screen_rect) {
+ original_view_screen_rect_ = view_screen_rect;
+ original_window_screen_rect_ = window_screen_rect;
+}
+
+void RenderWidget::ScreenMetricsEmulator::OnShowContextMenu(
+ ContextMenuParams* params) {
+ params->x *= scale_;
+ params->x += offset_.x();
+ params->y *= scale_;
+ params->y += offset_.y();
+}
+
+// RenderWidget ---------------------------------------------------------------
+
+RenderWidget::RenderWidget(blink::WebPopupType popup_type,
+ const blink::WebScreenInfo& screen_info,
bool swapped_out,
bool hidden)
: routing_id_(MSG_ROUTING_NONE),
@@ -212,6 +356,7 @@ RenderWidget::RenderWidget(WebKit::WebPopupType popup_type,
has_focus_(false),
handling_input_event_(false),
handling_ime_event_(false),
+ handling_touchstart_event_(false),
closing_(false),
is_swapped_out_(swapped_out),
input_method_is_active_(false),
@@ -232,7 +377,8 @@ RenderWidget::RenderWidget(WebKit::WebPopupType popup_type,
#if defined(OS_ANDROID)
outstanding_ime_acks_(0),
#endif
- weak_ptr_factory_(this) {
+ popup_origin_scale_for_emulation_(0.f),
+ resizing_mode_selector_(new ResizingModeSelector()) {
if (!swapped_out)
RenderProcess::current()->AddRefProcess();
DCHECK(RenderThread::Get());
@@ -266,8 +412,8 @@ RenderWidget::~RenderWidget() {
// static
RenderWidget* RenderWidget::Create(int32 opener_id,
- WebKit::WebPopupType popup_type,
- const WebKit::WebScreenInfo& screen_info) {
+ blink::WebPopupType popup_type,
+ const blink::WebScreenInfo& screen_info) {
DCHECK(opener_id != MSG_ROUTING_NONE);
scoped_refptr<RenderWidget> widget(
new RenderWidget(popup_type, screen_info, false, false));
@@ -280,15 +426,15 @@ RenderWidget* RenderWidget::Create(int32 opener_id,
// static
WebWidget* RenderWidget::CreateWebWidget(RenderWidget* render_widget) {
switch (render_widget->popup_type_) {
- case WebKit::WebPopupTypeNone: // Nothing to create.
+ case blink::WebPopupTypeNone: // Nothing to create.
break;
- case WebKit::WebPopupTypeSelect:
- case WebKit::WebPopupTypeSuggestion:
+ case blink::WebPopupTypeSelect:
+ case blink::WebPopupTypeSuggestion:
return WebPopupMenu::create(render_widget);
- case WebKit::WebPopupTypePage:
+ case blink::WebPopupTypePage:
return WebPagePopup::create(render_widget);
- case WebKit::WebPopupTypeHelperPlugin:
- return WebKit::WebHelperPlugin::create(render_widget);
+ case blink::WebPopupTypeHelperPlugin:
+ return blink::WebHelperPlugin::create(render_widget);
default:
NOTREACHED();
}
@@ -370,6 +516,63 @@ bool RenderWidget::UsingSynchronousRendererCompositor() const {
#endif
}
+void RenderWidget::EnableScreenMetricsEmulation(
+ const gfx::Rect& device_rect,
+ const gfx::Rect& widget_rect,
+ float device_scale_factor,
+ bool fit_to_view) {
+ if (!screen_metrics_emulator_) {
+ screen_metrics_emulator_.reset(new ScreenMetricsEmulator(this,
+ device_rect, widget_rect, device_scale_factor, fit_to_view));
+ } else {
+ screen_metrics_emulator_->ChangeEmulationParams(device_rect,
+ widget_rect, device_scale_factor, fit_to_view);
+ }
+}
+
+void RenderWidget::DisableScreenMetricsEmulation() {
+ screen_metrics_emulator_.reset();
+}
+
+void RenderWidget::SetPopupOriginAdjustmentsForEmulation(
+ ScreenMetricsEmulator* emulator) {
+ popup_origin_scale_for_emulation_ = emulator->scale();
+ popup_view_origin_for_emulation_ = emulator->widget_rect().origin();
+ popup_screen_origin_for_emulation_ = gfx::Point(
+ emulator->original_screen_rect().origin().x() + emulator->offset().x(),
+ emulator->original_screen_rect().origin().y() + emulator->offset().y());
+}
+
+void RenderWidget::SetScreenMetricsEmulationParameters(
+ float device_scale_factor,
+ const gfx::Point& root_layer_offset,
+ float root_layer_scale) {
+ // This is only supported in RenderView.
+ NOTREACHED();
+}
+
+void RenderWidget::SetExternalPopupOriginAdjustmentsForEmulation(
+ ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator) {
+ popup->SetOriginScaleAndOffsetForEmulation(
+ emulator->scale(), emulator->offset());
+}
+
+void RenderWidget::OnShowHostContextMenu(ContextMenuParams* params) {
+ if (screen_metrics_emulator_)
+ screen_metrics_emulator_->OnShowContextMenu(params);
+}
+
+void RenderWidget::ScheduleCompositeWithForcedRedraw() {
+ if (compositor_) {
+ // Regardless of whether threaded compositing is enabled, always
+ // use this mechanism to force the compositor to redraw. However,
+ // the invalidation code path below is still needed for the
+ // non-threaded case.
+ compositor_->SetNeedsForcedRedraw();
+ }
+ scheduleComposite();
+}
+
bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderWidget, message)
@@ -378,6 +581,8 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
OnCursorVisibilityChange)
IPC_MESSAGE_HANDLER(InputMsg_MouseCaptureLost, OnMouseCaptureLost)
IPC_MESSAGE_HANDLER(InputMsg_SetFocus, OnSetFocus)
+ IPC_MESSAGE_HANDLER(InputMsg_SyntheticGestureCompleted,
+ OnSyntheticGestureCompleted)
IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose)
IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)
IPC_MESSAGE_HANDLER(ViewMsg_Resize, OnResize)
@@ -386,20 +591,20 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_WasShown, OnWasShown)
IPC_MESSAGE_HANDLER(ViewMsg_WasSwappedOut, OnWasSwappedOut)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateRect_ACK, OnUpdateRectAck)
- IPC_MESSAGE_HANDLER(ViewMsg_SwapBuffers_ACK,
- OnViewContextSwapBuffersComplete)
+ IPC_MESSAGE_HANDLER(ViewMsg_SwapBuffers_ACK, OnSwapBuffersComplete)
IPC_MESSAGE_HANDLER(ViewMsg_SetInputMethodActive, OnSetInputMethodActive)
+ IPC_MESSAGE_HANDLER(ViewMsg_CandidateWindowShown, OnCandidateWindowShown)
+ IPC_MESSAGE_HANDLER(ViewMsg_CandidateWindowUpdated,
+ OnCandidateWindowUpdated)
+ IPC_MESSAGE_HANDLER(ViewMsg_CandidateWindowHidden, OnCandidateWindowHidden)
IPC_MESSAGE_HANDLER(ViewMsg_ImeSetComposition, OnImeSetComposition)
IPC_MESSAGE_HANDLER(ViewMsg_ImeConfirmComposition, OnImeConfirmComposition)
IPC_MESSAGE_HANDLER(ViewMsg_PaintAtSize, OnPaintAtSize)
IPC_MESSAGE_HANDLER(ViewMsg_Repaint, OnRepaint)
- IPC_MESSAGE_HANDLER(ViewMsg_SyntheticGestureCompleted,
- OnSyntheticGestureCompleted)
IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection)
IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateScreenRects, OnUpdateScreenRects)
#if defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(ViewMsg_ImeBatchStateChanged, OnImeBatchStateChanged)
IPC_MESSAGE_HANDLER(ViewMsg_ShowImeIfNeeded, OnShowImeIfNeeded)
IPC_MESSAGE_HANDLER(ViewMsg_ImeEventAck, OnImeEventAck)
#endif
@@ -434,8 +639,7 @@ void RenderWidget::Resize(const gfx::Size& new_size,
const gfx::Rect& resizer_rect,
bool is_fullscreen,
ResizeAck resize_ack) {
- if (!RenderThreadImpl::current() || // Will be NULL during unit tests.
- !RenderThreadImpl::current()->layout_test_mode()) {
+ if (resizing_mode_selector_->NeverUsesSynchronousResize()) {
// A resize ack shouldn't be requested if we have not ACK'd the previous
// one.
DCHECK(resize_ack != SEND_RESIZE_ACK || !next_paint_is_resize_ack());
@@ -474,14 +678,12 @@ void RenderWidget::Resize(const gfx::Size& new_size,
// send an ACK if we are resized to a non-empty rect.
webwidget_->resize(new_size);
- if (!RenderThreadImpl::current() || // Will be NULL during unit tests.
- !RenderThreadImpl::current()->layout_test_mode()) {
+ if (resizing_mode_selector_->NeverUsesSynchronousResize()) {
// Resize should have caused an invalidation of the entire view.
DCHECK(new_size.IsEmpty() || is_accelerated_compositing_active_ ||
paint_aggregator_.HasPendingUpdate());
}
- } else if (!RenderThreadImpl::current() || // Will be NULL during unit tests.
- !RenderThreadImpl::current()->layout_test_mode()) {
+ } else if (!resizing_mode_selector_->is_synchronous_mode()) {
resize_ack = NO_RESIZE_ACK;
}
@@ -503,6 +705,15 @@ void RenderWidget::Resize(const gfx::Size& new_size,
DCHECK(resize_ack != SEND_RESIZE_ACK || next_paint_is_resize_ack());
}
+void RenderWidget::ResizeSynchronously(const gfx::Rect& new_position) {
+ Resize(new_position.size(), new_position.size(), overdraw_bottom_height_,
+ gfx::Rect(), is_fullscreen_, NO_RESIZE_ACK);
+ view_screen_rect_ = new_position;
+ window_screen_rect_ = new_position;
+ if (!did_show_)
+ initial_pos_ = new_position;
+}
+
void RenderWidget::OnClose() {
if (closing_)
return;
@@ -533,6 +744,14 @@ void RenderWidget::OnCreatingNewAck() {
}
void RenderWidget::OnResize(const ViewMsg_Resize_Params& params) {
+ if (resizing_mode_selector_->ShouldAbortOnResize(this, params))
+ return;
+
+ if (screen_metrics_emulator_) {
+ screen_metrics_emulator_->OnResizeMessage(params);
+ return;
+ }
+
screen_info_ = params.screen_info;
SetDeviceScaleFactor(screen_info_.deviceScaleFactor);
Resize(params.new_size, params.physical_backing_size,
@@ -586,6 +805,8 @@ void RenderWidget::OnWasShown(bool needs_repainting) {
if (!is_accelerated_compositing_active_) {
didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
} else {
+ if (compositor_)
+ compositor_->SetNeedsForcedRedraw();
scheduleComposite();
}
}
@@ -667,7 +888,7 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
// be optimized to resolve directly into the IOSurface shared between the
// GPU and browser processes. For these reasons and to avoid platform
// disparities we explicitly disable antialiasing.
- WebKit::WebGraphicsContext3D::Attributes attributes;
+ blink::WebGraphicsContext3D::Attributes attributes;
attributes.antialias = false;
attributes.shareResources = true;
attributes.noAutomaticFlushes = true;
@@ -675,9 +896,6 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
attributes.stencil = false;
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(cc::switches::kForceDirectLayerDrawing))
- attributes.stencil = true;
-
scoped_refptr<ContextProviderCommandBuffer> context_provider;
if (!fallback) {
context_provider = ContextProviderCommandBuffer::Create(
@@ -736,7 +954,7 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
use_swap_compositor_frame_message));
}
-void RenderWidget::OnViewContextSwapBuffersAborted() {
+void RenderWidget::OnSwapBuffersAborted() {
TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersAborted");
while (!updates_pending_swap_.empty()) {
ViewHostMsg_UpdateRect* msg = updates_pending_swap_.front();
@@ -752,7 +970,7 @@ void RenderWidget::OnViewContextSwapBuffersAborted() {
scheduleComposite();
}
-void RenderWidget::OnViewContextSwapBuffersPosted() {
+void RenderWidget::OnSwapBuffersPosted() {
TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersPosted");
if (using_asynchronous_swapbuffers_) {
@@ -769,7 +987,7 @@ void RenderWidget::OnViewContextSwapBuffersPosted() {
}
}
-void RenderWidget::OnViewContextSwapBuffersComplete() {
+void RenderWidget::OnSwapBuffersComplete() {
TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersComplete");
// Notify subclasses that composited rendering was flushed to the screen.
@@ -819,8 +1037,8 @@ void RenderWidget::OnViewContextSwapBuffersComplete() {
DoDeferredUpdateAndSendInputAck();
}
-void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event,
- const ui::LatencyInfo& latency_info,
+void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event,
+ ui::LatencyInfo latency_info,
bool is_keyboard_shortcut) {
handling_input_event_ = true;
if (!input_event) {
@@ -828,14 +1046,23 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event,
return;
}
- const char* const event_name = GetEventName(input_event->type);
+ base::TimeTicks start_time;
+ if (base::TimeTicks::IsHighResNowFastAndReliable())
+ start_time = base::TimeTicks::HighResNow();
+
+ const char* const event_name =
+ WebInputEventTraits::GetName(input_event->type);
TRACE_EVENT1("renderer", "RenderWidget::OnHandleInputEvent",
"event", event_name);
- if (compositor_)
- compositor_->SetLatencyInfo(latency_info);
- else
+ scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor;
+
+ if (compositor_) {
+ latency_info_swap_promise_monitor =
+ compositor_->CreateLatencyInfoSwapPromiseMonitor(&latency_info).Pass();
+ } else {
latency_info_.MergeWith(latency_info);
+ }
base::TimeDelta now = base::TimeDelta::FromInternalValue(
base::TimeTicks::Now().ToInternalValue());
@@ -878,6 +1105,9 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event,
input_event->type == WebInputEvent::GestureLongPress)
resetInputMethod();
+ if (input_event->type == WebInputEvent::TouchStart)
+ handling_touchstart_event_ = true;
+
bool processed = prevent_default;
if (input_event->type != WebInputEvent::Char || !suppress_next_char_events_) {
suppress_next_char_events_ = false;
@@ -885,6 +1115,8 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event,
processed = webwidget_->handleInputEvent(*input_event);
}
+ handling_touchstart_event_ = false;
+
// If this RawKeyDown event corresponds to a browser keyboard shortcut and
// it's not processed by webkit, then we need to suppress the upcoming Char
// events.
@@ -896,41 +1128,66 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event,
if (!processed && input_event->type == WebInputEvent::TouchStart) {
const WebTouchEvent& touch_event =
*static_cast<const WebTouchEvent*>(input_event);
- ack_result = HasTouchEventHandlersAt(touch_event.touches[0].position) ?
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED :
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+ // Hit-test for all the pressed touch points. If there is a touch-handler
+ // for any of the touch points, then the renderer should continue to receive
+ // touch events.
+ ack_result = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+ for (size_t i = 0; i < touch_event.touchesLength; ++i) {
+ if (touch_event.touches[i].state == WebTouchPoint::StatePressed &&
+ HasTouchEventHandlersAt(touch_event.touches[i].position)) {
+ ack_result = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+ break;
+ }
+ }
}
- IPC::Message* response =
- new InputHostMsg_HandleInputEvent_ACK(routing_id_,
- input_event->type,
- ack_result,
- latency_info);
- bool event_type_gets_rate_limited =
+ bool event_type_can_be_rate_limited =
input_event->type == WebInputEvent::MouseMove ||
input_event->type == WebInputEvent::MouseWheel ||
- WebInputEvent::isTouchEventType(input_event->type);
+ input_event->type == WebInputEvent::TouchMove;
bool frame_pending = paint_aggregator_.HasPendingUpdate();
if (is_accelerated_compositing_active_) {
frame_pending = compositor_ &&
- compositor_->commitRequested();
- }
-
- if (event_type_gets_rate_limited && frame_pending && !is_hidden_) {
- // We want to rate limit the input events in this case, so we'll wait for
- // painting to finish before ACKing this message.
- if (pending_input_event_ack_) {
- // As two different kinds of events could cause us to postpone an ack
- // we send it now, if we have one pending. The Browser should never
- // send us the same kind of event we are delaying the ack for.
- Send(pending_input_event_ack_.release());
+ compositor_->BeginMainFrameRequested();
+ }
+
+ // If we don't have a fast and accurate HighResNow, we assume the input
+ // handlers are heavy and rate limit them.
+ bool rate_limiting_wanted = true;
+ if (base::TimeTicks::IsHighResNowFastAndReliable()) {
+ base::TimeTicks end_time = base::TimeTicks::HighResNow();
+ total_input_handling_time_this_frame_ += (end_time - start_time);
+ rate_limiting_wanted =
+ total_input_handling_time_this_frame_.InMicroseconds() >
+ kInputHandlingTimeThrottlingThresholdMicroseconds;
+ }
+
+ if (!WebInputEventTraits::IgnoresAckDisposition(input_event->type)) {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_HandleInputEvent_ACK(routing_id_,
+ input_event->type,
+ ack_result,
+ latency_info));
+ if (rate_limiting_wanted && event_type_can_be_rate_limited &&
+ frame_pending && !is_hidden_) {
+ // We want to rate limit the input events in this case, so we'll wait for
+ // painting to finish before ACKing this message.
+ TRACE_EVENT_INSTANT0("renderer",
+ "RenderWidget::OnHandleInputEvent ack throttled",
+ TRACE_EVENT_SCOPE_THREAD);
+ if (pending_input_event_ack_) {
+ // As two different kinds of events could cause us to postpone an ack
+ // we send it now, if we have one pending. The Browser should never
+ // send us the same kind of event we are delaying the ack for.
+ Send(pending_input_event_ack_.release());
+ }
+ pending_input_event_ack_ = response.Pass();
+ if (compositor_)
+ compositor_->NotifyInputThrottledUntilCommit();
+ } else {
+ Send(response.release());
}
- pending_input_event_ack_.reset(response);
- if (compositor_)
- compositor_->NotifyInputThrottledUntilCommit();
- } else {
- Send(response);
}
#if defined(OS_ANDROID)
@@ -1175,11 +1432,15 @@ void RenderWidget::InvalidationCallback() {
DoDeferredUpdateAndSendInputAck();
}
-void RenderWidget::DoDeferredUpdateAndSendInputAck() {
- DoDeferredUpdate();
-
+void RenderWidget::FlushPendingInputEventAck() {
if (pending_input_event_ack_)
Send(pending_input_event_ack_.release());
+ total_input_handling_time_this_frame_ = base::TimeDelta();
+}
+
+void RenderWidget::DoDeferredUpdateAndSendInputAck() {
+ DoDeferredUpdate();
+ FlushPendingInputEventAck();
}
void RenderWidget::DoDeferredUpdate() {
@@ -1212,8 +1473,8 @@ void RenderWidget::DoDeferredUpdate() {
}
// Tracking of frame rate jitter
- base::TimeTicks frame_begin_ticks = base::TimeTicks::Now();
- InstrumentWillBeginFrame();
+ base::TimeTicks frame_begin_ticks = gfx::FrameTime::Now();
+ InstrumentWillBeginFrame(0);
AnimateIfNeeded();
// Layout may generate more invalidation. It may also enable the
@@ -1271,9 +1532,9 @@ void RenderWidget::DoDeferredUpdate() {
last_do_deferred_update_time_ = frame_begin_ticks;
if (!is_accelerated_compositing_active_) {
- legacy_software_mode_stats_->IncrementAnimationFrameCount();
- legacy_software_mode_stats_->IncrementScreenFrameCount(1, true);
- legacy_software_mode_stats_->IssueTraceEventForMainThreadStats();
+ legacy_software_mode_stats_->IncrementFrameCount(1, true);
+ cc::BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent(
+ legacy_software_mode_stats_->main_thread_rendering_stats());
legacy_software_mode_stats_->AccumulateAndClearMainThreadStats();
}
@@ -1285,9 +1546,6 @@ void RenderWidget::DoDeferredUpdate() {
gfx::Rect scroll_damage = update.GetScrollDamage();
gfx::Rect bounds = gfx::UnionRects(update.GetPaintBounds(), scroll_damage);
- // Notify derived classes that we're about to initiate a paint.
- WillInitiatePaint();
-
// A plugin may be able to do an optimized paint. First check this, in which
// case we can skip all of the bitmap generation and regular paint code.
// This optimization allows PPAPI plugins that declare themselves on top of
@@ -1404,8 +1662,7 @@ void RenderWidget::DoDeferredUpdate() {
// UpdateReply message so we can receive another input event before the
// UpdateRect_ACK on platforms where the UpdateRect_ACK is sent from within
// the UpdateRect IPC message handler.
- if (pending_input_event_ack_)
- Send(pending_input_event_ack_.release());
+ FlushPendingInputEventAck();
// If Composite() called SwapBuffers, pending_update_params_ will be reset (in
// OnSwapBuffersPosted), meaning a message has been added to the
@@ -1518,7 +1775,7 @@ void RenderWidget::didAutoResize(const WebSize& new_size) {
// with invalid damage rects.
paint_aggregator_.ClearPendingUpdate();
- if (RenderThreadImpl::current()->layout_test_mode()) {
+ if (resizing_mode_selector_->is_synchronous_mode()) {
WebRect new_pos(rootWindowRect().x,
rootWindowRect().y,
new_size.width,
@@ -1529,7 +1786,7 @@ void RenderWidget::didAutoResize(const WebSize& new_size) {
AutoResizeCompositor();
- if (!RenderThreadImpl::current()->layout_test_mode())
+ if (!resizing_mode_selector_->is_synchronous_mode())
need_update_rect_for_auto_resize_ = true;
}
}
@@ -1598,7 +1855,7 @@ void RenderWidget::initializeLayerTreeView() {
compositor_->setSurfaceReady();
}
-WebKit::WebLayerTreeView* RenderWidget::layerTreeView() {
+blink::WebLayerTreeView* RenderWidget::layerTreeView() {
return compositor_.get();
}
@@ -1620,14 +1877,11 @@ void RenderWidget::willBeginCompositorFrame() {
UpdateTextInputState(false, true);
#endif
UpdateSelectionBounds();
-
- WillInitiatePaint();
}
void RenderWidget::didBecomeReadyForAdditionalInput() {
TRACE_EVENT0("renderer", "RenderWidget::didBecomeReadyForAdditionalInput");
- if (pending_input_event_ack_)
- Send(pending_input_event_ack_.release());
+ FlushPendingInputEventAck();
}
void RenderWidget::DidCommitCompositorFrame() {
@@ -1674,7 +1928,7 @@ void RenderWidget::didCompleteSwapBuffers() {
void RenderWidget::scheduleComposite() {
if (RenderThreadImpl::current()->compositor_message_loop_proxy().get() &&
compositor_) {
- compositor_->setNeedsRedraw();
+ compositor_->setNeedsAnimate();
} else {
// TODO(nduca): replace with something a little less hacky. The reason this
// hack is still used is because the Invalidate-DoDeferredUpdate loop
@@ -1732,14 +1986,6 @@ void RenderWidget::show(WebNavigationPolicy) {
SetPendingWindowRect(initial_pos_);
}
-void RenderWidget::didProgrammaticallyScroll(
- const WebKit::WebPoint& scroll_point) {
- if (!compositor_)
- return;
- Send(new ViewHostMsg_DidProgrammaticallyScroll(
- routing_id_, gfx::Vector2d(scroll_point.x, scroll_point.y)));
-}
-
void RenderWidget::didFocus() {
}
@@ -1771,6 +2017,19 @@ void RenderWidget::closeWidgetSoon() {
FROM_HERE, base::Bind(&RenderWidget::DoDeferredClose, this));
}
+void RenderWidget::QueueSyntheticGesture(
+ scoped_ptr<SyntheticGestureParams> gesture_params,
+ const SyntheticGestureCompletionCallback& callback) {
+ DCHECK(!callback.is_null());
+
+ pending_synthetic_gesture_callbacks_.push(callback);
+
+ SyntheticGesturePacket gesture_packet;
+ gesture_packet.set_gesture_params(gesture_params.Pass());
+
+ Send(new InputHostMsg_QueueSyntheticGesture(routing_id_, gesture_packet));
+}
+
void RenderWidget::Close() {
if (webwidget_) {
webwidget_->willCloseLayerTreeView();
@@ -1787,25 +2046,30 @@ WebRect RenderWidget::windowRect() {
return view_screen_rect_;
}
-void RenderWidget::setToolTipText(const WebKit::WebString& text,
+void RenderWidget::setToolTipText(const blink::WebString& text,
WebTextDirection hint) {
Send(new ViewHostMsg_SetTooltipText(routing_id_, text, hint));
}
-void RenderWidget::setWindowRect(const WebRect& pos) {
- if (did_show_) {
- if (!RenderThreadImpl::current()->layout_test_mode()) {
+void RenderWidget::setWindowRect(const WebRect& rect) {
+ WebRect pos = rect;
+ if (popup_origin_scale_for_emulation_) {
+ float scale = popup_origin_scale_for_emulation_;
+ pos.x = popup_screen_origin_for_emulation_.x() +
+ (pos.x - popup_view_origin_for_emulation_.x()) * scale;
+ pos.y = popup_screen_origin_for_emulation_.y() +
+ (pos.y - popup_view_origin_for_emulation_.y()) * scale;
+ }
+
+ if (!resizing_mode_selector_->is_synchronous_mode()) {
+ if (did_show_) {
Send(new ViewHostMsg_RequestMove(routing_id_, pos));
SetPendingWindowRect(pos);
} else {
- WebSize new_size(pos.width, pos.height);
- Resize(new_size, new_size, overdraw_bottom_height_,
- WebRect(), is_fullscreen_, NO_RESIZE_ACK);
- view_screen_rect_ = pos;
- window_screen_rect_ = pos;
+ initial_pos_ = pos;
}
} else {
- initial_pos_ = pos;
+ ResizeSynchronously(pos);
}
}
@@ -1838,8 +2102,20 @@ void RenderWidget::OnSetInputMethodActive(bool is_active) {
input_method_is_active_ = is_active;
}
+void RenderWidget::OnCandidateWindowShown() {
+ webwidget_->didShowCandidateWindow();
+}
+
+void RenderWidget::OnCandidateWindowUpdated() {
+ webwidget_->didUpdateCandidateWindow();
+}
+
+void RenderWidget::OnCandidateWindowHidden() {
+ webwidget_->didHideCandidateWindow();
+}
+
void RenderWidget::OnImeSetComposition(
- const string16& text,
+ const base::string16& text,
const std::vector<WebCompositionUnderline>& underlines,
int selection_start, int selection_end) {
if (!ShouldHandleImeEvent())
@@ -1858,7 +2134,7 @@ void RenderWidget::OnImeSetComposition(
#endif
}
-void RenderWidget::OnImeConfirmComposition(const string16& text,
+void RenderWidget::OnImeConfirmComposition(const base::string16& text,
const gfx::Range& replacement_range,
bool keep_selection) {
if (!ShouldHandleImeEvent())
@@ -2022,7 +2298,10 @@ void RenderWidget::OnRepaint(gfx::Size size_to_paint) {
}
void RenderWidget::OnSyntheticGestureCompleted() {
- pending_synthetic_gesture_.Run();
+ DCHECK(!pending_synthetic_gesture_callbacks_.empty());
+
+ pending_synthetic_gesture_callbacks_.front().Run();
+ pending_synthetic_gesture_callbacks_.pop();
}
void RenderWidget::OnSetTextDirection(WebTextDirection direction) {
@@ -2033,16 +2312,17 @@ void RenderWidget::OnSetTextDirection(WebTextDirection direction) {
void RenderWidget::OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect) {
- view_screen_rect_ = view_screen_rect;
- window_screen_rect_ = window_screen_rect;
+ if (screen_metrics_emulator_) {
+ screen_metrics_emulator_->OnUpdateScreenRectsMessage(
+ view_screen_rect, window_screen_rect);
+ } else {
+ view_screen_rect_ = view_screen_rect;
+ window_screen_rect_ = window_screen_rect;
+ }
Send(new ViewHostMsg_UpdateScreenRects_ACK(routing_id()));
}
#if defined(OS_ANDROID)
-void RenderWidget::OnImeBatchStateChanged(bool is_begin) {
- Send(new ViewHostMsg_ImeBatchStateChanged_ACK(routing_id(), is_begin));
-}
-
void RenderWidget::OnShowImeIfNeeded() {
UpdateTextInputState(true, true);
}
@@ -2182,8 +2462,16 @@ void RenderWidget::FinishHandlingImeEvent() {
}
void RenderWidget::UpdateTextInputType() {
+ // On Windows, not only an IME but also an on-screen keyboard relies on the
+ // latest TextInputType to optimize its layout and functionality. Thus
+ // |input_method_is_active_| is no longer an appropriate condition to suppress
+ // TextInputTypeChanged IPC on Windows.
+ // TODO(yukawa, yoichio): Consider to stop checking |input_method_is_active_|
+ // on other platforms as well as Windows if the overhead is acceptable.
+#if !defined(OS_WIN)
if (!input_method_is_active_)
return;
+#endif
ui::TextInputType new_type = GetTextInputType();
if (IsDateTimeInput(new_type))
@@ -2191,7 +2479,7 @@ void RenderWidget::UpdateTextInputType() {
bool new_can_compose_inline = CanComposeInline();
- WebKit::WebTextInputInfo new_info;
+ blink::WebTextInputInfo new_info;
if (webwidget_)
new_info = webwidget_->textInputInfo();
const ui::TextInputMode new_mode = ConvertInputMode(new_info.inputMode);
@@ -2220,7 +2508,7 @@ void RenderWidget::UpdateTextInputState(bool show_ime_if_needed,
if (IsDateTimeInput(new_type))
return; // Not considered as a text input field in WebKit/Chromium.
- WebKit::WebTextInputInfo new_info;
+ blink::WebTextInputInfo new_info;
if (webwidget_)
new_info = webwidget_->textInputInfo();
@@ -2281,47 +2569,47 @@ void RenderWidget::UpdateSelectionBounds() {
#endif
}
-// Check WebKit::WebTextInputType and ui::TextInputType is kept in sync.
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeNone) == \
+// Check blink::WebTextInputType and ui::TextInputType is kept in sync.
+COMPILE_ASSERT(int(blink::WebTextInputTypeNone) == \
int(ui::TEXT_INPUT_TYPE_NONE), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeText) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeText) == \
int(ui::TEXT_INPUT_TYPE_TEXT), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypePassword) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypePassword) == \
int(ui::TEXT_INPUT_TYPE_PASSWORD), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeSearch) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeSearch) == \
int(ui::TEXT_INPUT_TYPE_SEARCH), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeEmail) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeEmail) == \
int(ui::TEXT_INPUT_TYPE_EMAIL), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeNumber) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeNumber) == \
int(ui::TEXT_INPUT_TYPE_NUMBER), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeTelephone) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeTelephone) == \
int(ui::TEXT_INPUT_TYPE_TELEPHONE), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeURL) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeURL) == \
int(ui::TEXT_INPUT_TYPE_URL), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeDate) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeDate) == \
int(ui::TEXT_INPUT_TYPE_DATE), mismatching_enum);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeDateTime) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeDateTime) == \
int(ui::TEXT_INPUT_TYPE_DATE_TIME), mismatching_enum);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeDateTimeLocal) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeDateTimeLocal) == \
int(ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL), mismatching_enum);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeMonth) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeMonth) == \
int(ui::TEXT_INPUT_TYPE_MONTH), mismatching_enum);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeTime) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeTime) == \
int(ui::TEXT_INPUT_TYPE_TIME), mismatching_enum);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeWeek) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeWeek) == \
int(ui::TEXT_INPUT_TYPE_WEEK), mismatching_enum);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeTextArea) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeTextArea) == \
int(ui::TEXT_INPUT_TYPE_TEXT_AREA), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeContentEditable) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeContentEditable) == \
int(ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE), mismatching_enums);
-COMPILE_ASSERT(int(WebKit::WebTextInputTypeDateTimeField) == \
+COMPILE_ASSERT(int(blink::WebTextInputTypeDateTimeField) == \
int(ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD), mismatching_enums);
ui::TextInputType RenderWidget::WebKitToUiTextInputType(
- WebKit::WebTextInputType type) {
+ blink::WebTextInputType type) {
// Check the type is in the range representable by ui::TextInputType.
DCHECK_LE(type, static_cast<int>(ui::TEXT_INPUT_TYPE_MAX)) <<
- "WebKit::WebTextInputType and ui::TextInputType not synchronized";
+ "blink::WebTextInputType and ui::TextInputType not synchronized";
return static_cast<ui::TextInputType>(type);
}
@@ -2456,7 +2744,7 @@ void RenderWidget::CleanupWindowInPluginMoves(gfx::PluginWindowHandle window) {
}
void RenderWidget::GetRenderingStats(
- WebKit::WebRenderingStatsImpl& stats) const {
+ blink::WebRenderingStatsImpl& stats) const {
if (compositor_)
compositor_->GetRenderingStats(&stats.rendering_stats);
@@ -2485,52 +2773,16 @@ void RenderWidget::GetBrowserRenderingStats(BrowserRenderingStats* stats) {
*stats = browser_rendering_stats_;
}
-void RenderWidget::BeginSmoothScroll(
- bool down,
- const SyntheticGestureCompletionCallback& callback,
- int pixels_to_scroll,
- int mouse_event_x,
- int mouse_event_y) {
- DCHECK(!callback.is_null());
-
- ViewHostMsg_BeginSmoothScroll_Params params;
- params.scroll_down = down;
- params.pixels_to_scroll = pixels_to_scroll;
- params.mouse_event_x = mouse_event_x;
- params.mouse_event_y = mouse_event_y;
-
- Send(new ViewHostMsg_BeginSmoothScroll(routing_id_, params));
- pending_synthetic_gesture_ = callback;
-}
-
-void RenderWidget::BeginPinch(
- bool zoom_in,
- int pixels_to_move,
- int anchor_x,
- int anchor_y,
- const SyntheticGestureCompletionCallback& callback) {
- DCHECK(!callback.is_null());
-
- ViewHostMsg_BeginPinch_Params params;
- params.zoom_in = zoom_in;
- params.pixels_to_move = pixels_to_move;
- params.anchor_x = anchor_x;
- params.anchor_y = anchor_y;
-
- Send(new ViewHostMsg_BeginPinch(routing_id_, params));
- pending_synthetic_gesture_ = callback;
-}
-
-bool RenderWidget::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) {
+bool RenderWidget::WillHandleMouseEvent(const blink::WebMouseEvent& event) {
return false;
}
-bool RenderWidget::WillHandleKeyEvent(const WebKit::WebKeyboardEvent& event) {
+bool RenderWidget::WillHandleKeyEvent(const blink::WebKeyboardEvent& event) {
return false;
}
bool RenderWidget::WillHandleGestureEvent(
- const WebKit::WebGestureEvent& event) {
+ const blink::WebGestureEvent& event) {
return false;
}
@@ -2538,25 +2790,50 @@ void RenderWidget::hasTouchEventHandlers(bool has_handlers) {
Send(new ViewHostMsg_HasTouchEventHandlers(routing_id_, has_handlers));
}
+void RenderWidget::setTouchAction(
+ blink::WebTouchAction web_touch_action) {
+
+ // Ignore setTouchAction calls that result from synthetic touch events (eg.
+ // when blink is emulating touch with mouse).
+ if (!handling_touchstart_event_)
+ return;
+
+ content::TouchAction content_touch_action;
+ switch(web_touch_action) {
+ case blink::WebTouchActionNone:
+ content_touch_action = content::TOUCH_ACTION_NONE;
+ break;
+ case blink::WebTouchActionAuto:
+ content_touch_action = content::TOUCH_ACTION_AUTO;
+ break;
+ default:
+ NOTREACHED();
+ }
+ Send(new InputHostMsg_SetTouchAction(routing_id_, content_touch_action));
+}
+
bool RenderWidget::HasTouchEventHandlersAt(const gfx::Point& point) const {
return true;
}
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
RenderWidget::CreateGraphicsContext3D(
- const WebKit::WebGraphicsContext3D::Attributes& attributes) {
+ const blink::WebGraphicsContext3D::Attributes& attributes) {
if (!webwidget_)
return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuCompositing))
return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
- new WebGraphicsContext3DCommandBufferImpl(
- surface_id(),
- GetURLForGraphicsContext3D(),
- RenderThreadImpl::current(),
- weak_ptr_factory_.GetWeakPtr()));
+ if (!RenderThreadImpl::current())
+ return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
+ CauseForGpuLaunch cause =
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
+ scoped_refptr<GpuChannelHost> gpu_channel_host(
+ RenderThreadImpl::current()->EstablishGpuChannelSync(cause));
+ if (!gpu_channel_host)
+ return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
#if defined(OS_ANDROID)
// If we raster too fast we become upload bound, and pending
// uploads consume memory. For maximum upload throughput, we would
@@ -2576,22 +2853,18 @@ RenderWidget::CreateGraphicsContext3D(
static const size_t kBytesPerMegabyte = 1024 * 1024;
// We keep the MappedMemoryReclaimLimit the same as the upload limit
// to avoid unnecessarily stalling the compositor thread.
- const size_t mapped_memory_reclaim_limit =
+ limits.mapped_memory_reclaim_limit =
max_transfer_buffer_usage_mb * kBytesPerMegabyte;
-#else
- const size_t mapped_memory_reclaim_limit =
- WebGraphicsContext3DCommandBufferImpl::kNoLimit;
#endif
- if (!context->Initialize(
+
+ scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
+ new WebGraphicsContext3DCommandBufferImpl(
+ surface_id(),
+ GetURLForGraphicsContext3D(),
+ gpu_channel_host.get(),
attributes,
false /* bind generates resources */,
- CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE,
- kDefaultCommandBufferSize,
- kDefaultStartTransferBufferSize,
- kDefaultMinTransferBufferSize,
- kDefaultMaxTransferBufferSize,
- mapped_memory_reclaim_limit))
- return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
+ limits));
return context.Pass();
}
diff --git a/chromium/content/renderer/render_widget.h b/chromium/content/renderer/render_widget.h
index d43934766c7..043d3aa3f01 100644
--- a/chromium/content/renderer/render_widget.h
+++ b/chromium/content/renderer/render_widget.h
@@ -12,13 +12,13 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "cc/debug/rendering_stats_instrumentation.h"
#include "content/common/browser_rendering_stats.h"
#include "content/common/content_export.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "content/common/input/synthetic_gesture_params.h"
#include "content/renderer/paint_aggregator.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
@@ -27,6 +27,7 @@
#include "third_party/WebKit/public/web/WebPopupType.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
#include "third_party/WebKit/public/web/WebTextInputInfo.h"
+#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"
@@ -48,13 +49,12 @@ namespace IPC {
class SyncMessage;
}
-namespace WebKit {
+namespace blink {
class WebGestureEvent;
class WebInputEvent;
class WebKeyboardEvent;
class WebMouseEvent;
class WebTouchEvent;
-struct WebPoint;
struct WebRenderingStatsImpl;
}
@@ -65,9 +65,12 @@ class Range;
}
namespace content {
+class ExternalPopupMenu;
class PepperPluginInstanceImpl;
class RenderWidgetCompositor;
class RenderWidgetTest;
+class ResizingModeSelector;
+struct ContextMenuParams;
struct GpuRenderingStats;
struct WebPluginGeometry;
@@ -76,18 +79,17 @@ struct WebPluginGeometry;
class CONTENT_EXPORT RenderWidget
: public IPC::Listener,
public IPC::Sender,
- NON_EXPORTED_BASE(virtual public WebKit::WebWidgetClient),
- NON_EXPORTED_BASE(public WebGraphicsContext3DSwapBuffersClient),
+ NON_EXPORTED_BASE(virtual public blink::WebWidgetClient),
public base::RefCounted<RenderWidget> {
public:
// Creates a new RenderWidget. The opener_id is the routing ID of the
// RenderView that this widget lives inside.
static RenderWidget* Create(int32 opener_id,
- WebKit::WebPopupType popup_type,
- const WebKit::WebScreenInfo& screen_info);
+ blink::WebPopupType popup_type,
+ const blink::WebScreenInfo& screen_info);
// Creates a WebWidget based on the popup type.
- static WebKit::WebWidget* CreateWebWidget(RenderWidget* render_widget);
+ static blink::WebWidget* CreateWebWidget(RenderWidget* render_widget);
// The compositing surface assigned by the RenderWidgetHost
// (or RenderViewHost). Will be gfx::kNullPluginWindow if not assigned yet,
@@ -104,7 +106,7 @@ class CONTENT_EXPORT RenderWidget
}
// May return NULL when the window is closing.
- WebKit::WebWidget* webwidget() const { return webwidget_; }
+ blink::WebWidget* webwidget() const { return webwidget_; }
gfx::Size size() const { return size_; }
bool has_focus() const { return has_focus_; }
@@ -117,17 +119,17 @@ class CONTENT_EXPORT RenderWidget
// IPC::Sender
virtual bool Send(IPC::Message* msg) OVERRIDE;
- // WebKit::WebWidgetClient
+ // blink::WebWidgetClient
virtual void suppressCompositorScheduling(bool enable);
virtual void willBeginCompositorFrame();
- virtual void didInvalidateRect(const WebKit::WebRect&);
+ virtual void didInvalidateRect(const blink::WebRect&);
virtual void didScrollRect(int dx, int dy,
- const WebKit::WebRect& clipRect);
- virtual void didAutoResize(const WebKit::WebSize& new_size);
+ const blink::WebRect& clipRect);
+ virtual void didAutoResize(const blink::WebSize& new_size);
virtual void didActivateCompositor(int input_handler_identifier);
virtual void didDeactivateCompositor();
virtual void initializeLayerTreeView();
- virtual WebKit::WebLayerTreeView* layerTreeView();
+ virtual blink::WebLayerTreeView* layerTreeView();
virtual void didBecomeReadyForAdditionalInput();
virtual void didCommitAndDrawCompositorFrame();
virtual void didCompleteSwapBuffers();
@@ -135,21 +137,20 @@ class CONTENT_EXPORT RenderWidget
virtual void scheduleAnimation();
virtual void didFocus();
virtual void didBlur();
- virtual void didChangeCursor(const WebKit::WebCursorInfo&);
+ virtual void didChangeCursor(const blink::WebCursorInfo&);
virtual void closeWidgetSoon();
- virtual void show(WebKit::WebNavigationPolicy);
+ virtual void show(blink::WebNavigationPolicy);
virtual void runModal() {}
- virtual void didProgrammaticallyScroll(const WebKit::WebPoint& scroll_point);
- virtual WebKit::WebRect windowRect();
- virtual void setToolTipText(const WebKit::WebString& text,
- WebKit::WebTextDirection hint);
- virtual void setWindowRect(const WebKit::WebRect&);
- virtual WebKit::WebRect windowResizerRect();
- virtual WebKit::WebRect rootWindowRect();
- virtual WebKit::WebScreenInfo screenInfo();
+ virtual blink::WebRect windowRect();
+ virtual void setToolTipText(const blink::WebString& text,
+ blink::WebTextDirection hint);
+ virtual void setWindowRect(const blink::WebRect&);
+ virtual blink::WebRect windowResizerRect();
+ virtual blink::WebRect rootWindowRect();
+ virtual blink::WebScreenInfo screenInfo();
virtual float deviceScaleFactor();
virtual void resetInputMethod();
- virtual void didHandleGestureEvent(const WebKit::WebGestureEvent& event,
+ virtual void didHandleGestureEvent(const blink::WebGestureEvent& event,
bool event_cancelled);
// Called when a plugin is moved. These events are queued up and sent with
@@ -162,7 +163,7 @@ class CONTENT_EXPORT RenderWidget
// Fills in a WebRenderingStatsImpl struct containing information about
// rendering, e.g. count of frames rendered, time spent painting.
- void GetRenderingStats(WebKit::WebRenderingStatsImpl&) const;
+ void GetRenderingStats(blink::WebRenderingStatsImpl&) const;
// Fills in a GpuRenderingStats struct containing information about
// GPU rendering, e.g. count of texture uploads performed, time spent
@@ -179,25 +180,11 @@ class CONTENT_EXPORT RenderWidget
// Callback for use with synthetic gestures (e.g. BeginSmoothScroll).
typedef base::Callback<void()> SyntheticGestureCompletionCallback;
- // Directs the host to begin a smooth scroll. This scroll should have the same
- // performance characteristics as a user-initiated scroll. Returns an ID of
- // the scroll gesture. |mouse_event_x| and |mouse_event_y| are expected to be
- // in local DIP coordinates.
- void BeginSmoothScroll(bool scroll_down,
- const SyntheticGestureCompletionCallback& callback,
- int pixels_to_scroll,
- int mouse_event_x,
- int mouse_event_y);
-
- // Directs the host to begin a pinch gesture. This gesture should have the
- // same performance characteristics as a user-initiated pinch.
- // |pixels_to_move|, |anchor_x| and |anchor_y| are expected to be in local
- // DIP coordinates.
- void BeginPinch(bool zoom_in,
- int pixels_to_move,
- int anchor_x,
- int anchor_y,
- const SyntheticGestureCompletionCallback& callback);
+ // Send a synthetic gesture to the browser to be queued to the synthetic
+ // gesture controller.
+ void QueueSyntheticGesture(
+ scoped_ptr<SyntheticGestureParams> gesture_params,
+ const SyntheticGestureCompletionCallback& callback);
// Close the underlying WebWidget.
virtual void Close();
@@ -213,7 +200,7 @@ class CONTENT_EXPORT RenderWidget
void StartHandlingImeEvent();
void FinishHandlingImeEvent();
- virtual void InstrumentWillBeginFrame() {}
+ virtual void InstrumentWillBeginFrame(int frame_id) {}
virtual void InstrumentDidBeginFrame() {}
virtual void InstrumentDidCancelFrame() {}
virtual void InstrumentWillComposite() {}
@@ -223,6 +210,46 @@ class CONTENT_EXPORT RenderWidget
bool is_swapped_out() { return is_swapped_out_; }
+ // ScreenMetricsEmulator class manages screen emulation inside a render
+ // widget. This includes resizing, placing view on the screen at desired
+ // position, changing device scale factor, and scaling down the whole
+ // widget if required to fit into the browser window.
+ class ScreenMetricsEmulator;
+
+ // Emulates screen and widget metrics. Supplied values override everything
+ // coming from host.
+ void EnableScreenMetricsEmulation(
+ const gfx::Rect& device_rect,
+ const gfx::Rect& widget_rect,
+ float device_scale_factor,
+ bool fit_to_view);
+ void DisableScreenMetricsEmulation();
+ void SetPopupOriginAdjustmentsForEmulation(ScreenMetricsEmulator* emulator);
+
+ void ScheduleCompositeWithForcedRedraw();
+
+ // Called by the compositor in single-threaded mode when a swap is posted,
+ // completes or is aborted.
+ void OnSwapBuffersPosted();
+ void OnSwapBuffersComplete();
+ void OnSwapBuffersAborted();
+
+ // Checks if the text input state and compose inline mode have been changed.
+ // If they are changed, the new value will be sent to the browser process.
+ void UpdateTextInputType();
+
+ // Checks if the selection bounds have been changed. If they are changed,
+ // the new value will be sent to the browser process.
+ void UpdateSelectionBounds();
+
+
+#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
+ // Checks if the composition range or composition character bounds have been
+ // changed. If they are changed, the new value will be sent to the browser
+ // process.
+ void UpdateCompositionInfo(bool should_update_range);
+#endif
+
protected:
// Friend RefCounted so that the dtor can be non-public. Using this class
// without ref-counting is an error.
@@ -235,8 +262,8 @@ class CONTENT_EXPORT RenderWidget
NO_RESIZE_ACK,
};
- RenderWidget(WebKit::WebPopupType popup_type,
- const WebKit::WebScreenInfo& screen_info,
+ RenderWidget(blink::WebPopupType popup_type,
+ const blink::WebScreenInfo& screen_info,
bool swapped_out,
bool hidden);
@@ -248,7 +275,7 @@ class CONTENT_EXPORT RenderWidget
// Called by Init and subclasses to perform initialization.
bool DoInit(int32 opener_id,
- WebKit::WebWidget* web_widget,
+ blink::WebWidget* web_widget,
IPC::SyncMessage* create_widget_message);
// Finishes creation of a pending view started with Init.
@@ -273,10 +300,11 @@ class CONTENT_EXPORT RenderWidget
void AnimationCallback();
void AnimateIfNeeded();
void InvalidationCallback();
+ void FlushPendingInputEventAck();
void DoDeferredUpdateAndSendInputAck();
void DoDeferredUpdate();
void DoDeferredClose();
- void DoDeferredSetWindowRect(const WebKit::WebRect& pos);
+ void DoDeferredSetWindowRect(const blink::WebRect& pos);
virtual void Composite(base::TimeTicks frame_begin_time);
// Set the background of the render widget to a bitmap. The bitmap will be
@@ -291,10 +319,19 @@ class CONTENT_EXPORT RenderWidget
const gfx::Rect& resizer_rect,
bool is_fullscreen,
ResizeAck resize_ack);
+ // Used to force the size of a window when running layout tests.
+ void ResizeSynchronously(const gfx::Rect& new_position);
+ virtual void SetScreenMetricsEmulationParameters(
+ float device_scale_factor,
+ const gfx::Point& root_layer_offset,
+ float root_layer_scale);
+ void SetExternalPopupOriginAdjustmentsForEmulation(
+ ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator);
+ virtual void OnShowHostContextMenu(ContextMenuParams* params);
// RenderWidget IPC message handlers
- void OnHandleInputEvent(const WebKit::WebInputEvent* event,
- const ui::LatencyInfo& latency_info,
+ void OnHandleInputEvent(const blink::WebInputEvent* event,
+ ui::LatencyInfo latency_info,
bool keyboard_shortcut);
void OnCursorVisibilityChange(bool is_visible);
void OnMouseCaptureLost();
@@ -311,12 +348,15 @@ class CONTENT_EXPORT RenderWidget
void OnUpdateVideoAck(int32 video_id);
void OnRequestMoveAck();
void OnSetInputMethodActive(bool is_active);
+ void OnCandidateWindowShown();
+ void OnCandidateWindowUpdated();
+ void OnCandidateWindowHidden();
virtual void OnImeSetComposition(
- const string16& text,
- const std::vector<WebKit::WebCompositionUnderline>& underlines,
+ const base::string16& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
int selection_end);
- virtual void OnImeConfirmComposition(const string16& text,
+ virtual void OnImeConfirmComposition(const base::string16& text,
const gfx::Range& replacement_range,
bool keep_selection);
void OnPaintAtSize(const TransportDIB::Handle& dib_id,
@@ -325,12 +365,11 @@ class CONTENT_EXPORT RenderWidget
const gfx::Size& desired_size);
void OnRepaint(gfx::Size size_to_paint);
void OnSyntheticGestureCompleted();
- void OnSetTextDirection(WebKit::WebTextDirection direction);
+ void OnSetTextDirection(blink::WebTextDirection direction);
void OnGetFPS();
void OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect);
#if defined(OS_ANDROID)
- void OnImeBatchStateChanged(bool is_begin);
void OnShowImeIfNeeded();
// Whenever an IME event that needs an acknowledgement is sent to the browser,
@@ -356,13 +395,11 @@ class CONTENT_EXPORT RenderWidget
virtual void SetDeviceScaleFactor(float device_scale_factor);
// Override points to notify derived classes that a paint has happened.
- // WillInitiatePaint happens when we're about to generate a new bitmap and
- // send it to the browser. DidInitiatePaint happens when that has completed,
- // and subsequent rendering won't affect the painted content. DidFlushPaint
- // happens once we've received the ACK that the screen has been updated.
- // For a given paint operation, these overrides will always be called in the
- // order WillInitiatePaint, DidInitiatePaint, DidFlushPaint.
- virtual void WillInitiatePaint() {}
+ // DidInitiatePaint happens when that has completed, and subsequent rendering
+ // won't affect the painted content. DidFlushPaint happens once we've received
+ // the ACK that the screen has been updated. For a given paint operation,
+ // these overrides will always be called in the order DidInitiatePaint,
+ // DidFlushPaint.
virtual void DidInitiatePaint() {}
virtual void DidFlushPaint() {}
@@ -376,14 +413,6 @@ class CONTENT_EXPORT RenderWidget
virtual bool ForceCompositingModeEnabled();
- // WebGraphicsContext3DSwapBuffersClient implementation.
-
- // Called by a GraphicsContext associated with this view when swapbuffers
- // is posted, completes or is aborted.
- virtual void OnViewContextSwapBuffersPosted() OVERRIDE;
- virtual void OnViewContextSwapBuffersComplete() OVERRIDE;
- virtual void OnViewContextSwapBuffersAborted() OVERRIDE;
-
// Detects if a suitable opaque plugin covers the given paint bounds with no
// compositing necessary.
//
@@ -419,10 +448,6 @@ class CONTENT_EXPORT RenderWidget
void set_next_paint_is_restore_ack();
void set_next_paint_is_repaint_ack();
- // Checks if the text input state and compose inline mode have been changed.
- // If they are changed, the new value will be sent to the browser process.
- void UpdateTextInputType();
-
#if defined(OS_ANDROID)
// |show_ime_if_needed| should be true iff the update may cause the ime to be
// displayed, e.g. after a tap on an input field on mobile.
@@ -433,23 +458,14 @@ class CONTENT_EXPORT RenderWidget
void UpdateTextInputState(bool show_ime_if_needed, bool send_ime_ack);
#endif
- // Checks if the selection bounds have been changed. If they are changed,
- // the new value will be sent to the browser process.
- virtual void UpdateSelectionBounds();
-
// Override point to obtain that the current input method state and caret
// position.
virtual ui::TextInputType GetTextInputType();
virtual void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end);
virtual ui::TextInputType WebKitToUiTextInputType(
- WebKit::WebTextInputType type);
+ blink::WebTextInputType type);
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
- // Checks if the composition range or composition character bounds have been
- // changed. If they are changed, the new value will be sent to the browser
- // process.
- void UpdateCompositionInfo(bool should_update_range);
-
// Override point to obtain that the current composition character bounds.
// In the case of surrogate pairs, the character is treated as two characters:
// the bounds for first character is actual one, and the bounds for second
@@ -482,7 +498,7 @@ class CONTENT_EXPORT RenderWidget
// been processed by the browser. So we maintain a pending window rect
// size. If JS code sets the WindowRect, and then immediately calls
// GetWindowRect() we'll use this pending window rect as the size.
- void SetPendingWindowRect(const WebKit::WebRect& r);
+ void SetPendingWindowRect(const blink::WebRect& r);
// Called by OnHandleInputEvent() to notify subclasses that a key event was
// just handled.
@@ -492,27 +508,27 @@ class CONTENT_EXPORT RenderWidget
// about to be handled.
// Returns true if no further handling is needed. In that case, the event
// won't be sent to WebKit or trigger DidHandleMouseEvent().
- virtual bool WillHandleMouseEvent(const WebKit::WebMouseEvent& event);
+ virtual bool WillHandleMouseEvent(const blink::WebMouseEvent& event);
// Called by OnHandleInputEvent() to notify subclasses that a key event is
// about to be handled.
// Returns true if no further handling is needed. In that case, the event
// won't be sent to WebKit or trigger DidHandleKeyEvent().
- virtual bool WillHandleKeyEvent(const WebKit::WebKeyboardEvent& event);
+ virtual bool WillHandleKeyEvent(const blink::WebKeyboardEvent& event);
// Called by OnHandleInputEvent() to notify subclasses that a gesture event is
// about to be handled.
// Returns true if no further handling is needed. In that case, the event
// won't be sent to WebKit.
- virtual bool WillHandleGestureEvent(const WebKit::WebGestureEvent& event);
+ virtual bool WillHandleGestureEvent(const blink::WebGestureEvent& event);
// Called by OnHandleInputEvent() to notify subclasses that a mouse event was
// just handled.
- virtual void DidHandleMouseEvent(const WebKit::WebMouseEvent& event) {}
+ virtual void DidHandleMouseEvent(const blink::WebMouseEvent& event) {}
// Called by OnHandleInputEvent() to notify subclasses that a touch event was
// just handled.
- virtual void DidHandleTouchEvent(const WebKit::WebTouchEvent& event) {}
+ virtual void DidHandleTouchEvent(const blink::WebTouchEvent& event) {}
// Check whether the WebWidget has any touch event handlers registered
// at the given point.
@@ -521,9 +537,12 @@ class CONTENT_EXPORT RenderWidget
// Check whether the WebWidget has any touch event handlers registered.
virtual void hasTouchEventHandlers(bool has_handlers);
+ // Tell the browser about the actions permitted for a new touch point.
+ virtual void setTouchAction(blink::WebTouchAction touch_action);
+
// Creates a 3D context associated with this view.
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateGraphicsContext3D(
- const WebKit::WebGraphicsContext3D::Attributes& attributes);
+ const blink::WebGraphicsContext3D::Attributes& attributes);
bool OnSnapshotHelper(const gfx::Rect& src_subrect, SkBitmap* bitmap);
@@ -534,7 +553,7 @@ class CONTENT_EXPORT RenderWidget
int32 surface_id_;
// We are responsible for destroying this object via its Close method.
- WebKit::WebWidget* webwidget_;
+ blink::WebWidget* webwidget_;
// This is lazily constructed and must not outlive webwidget_.
scoped_ptr<RenderWidgetCompositor> compositor_;
@@ -633,6 +652,9 @@ class CONTENT_EXPORT RenderWidget
// Are we currently handling an ime event?
bool handling_ime_event_;
+ // Are we currently handling a touchstart event?
+ bool handling_touchstart_event_;
+
// True if we have requested this widget be closed. No more messages will
// be sent, except for a Close.
bool closing_;
@@ -646,7 +668,7 @@ class CONTENT_EXPORT RenderWidget
bool input_method_is_active_;
// Stores information about the current text input.
- WebKit::WebTextInputInfo text_input_info_;
+ blink::WebTextInputInfo text_input_info_;
// Stores the current text input type of |webwidget_|.
ui::TextInputType text_input_type_;
@@ -668,7 +690,7 @@ class CONTENT_EXPORT RenderWidget
gfx::Range composition_range_;
// The kind of popup this widget represents, NONE if not a popup.
- WebKit::WebPopupType popup_type_;
+ blink::WebPopupType popup_type_;
// Holds all the needed plugin window moves for a scroll.
typedef std::vector<WebPluginGeometry> WebPluginGeometryVector;
@@ -680,7 +702,7 @@ class CONTENT_EXPORT RenderWidget
// While we are waiting for the browser to update window sizes, we track the
// pending size temporarily.
int pending_window_rect_count_;
- WebKit::WebRect pending_window_rect_;
+ blink::WebRect pending_window_rect_;
// The screen rects of the view and the window that contains it.
gfx::Rect view_screen_rect_;
@@ -688,6 +710,9 @@ class CONTENT_EXPORT RenderWidget
scoped_ptr<IPC::Message> pending_input_event_ack_;
+ // The time spent in input handlers this frame. Used to throttle input acks.
+ base::TimeDelta total_input_handling_time_this_frame_;
+
// Indicates if the next sequence of Char events should be suppressed or not.
bool suppress_next_char_events_;
@@ -723,15 +748,17 @@ class CONTENT_EXPORT RenderWidget
std::deque<ViewHostMsg_UpdateRect*> updates_pending_swap_;
// Properties of the screen hosting this RenderWidget instance.
- WebKit::WebScreenInfo screen_info_;
+ blink::WebScreenInfo screen_info_;
// The device scale factor. This value is computed from the DPI entries in
// |screen_info_| on some platforms, and defaults to 1 on other platforms.
float device_scale_factor_;
- // State associated with the synthetic gestures function
- // (e.g. BeginSmoothScroll).
- SyntheticGestureCompletionCallback pending_synthetic_gesture_;
+ // State associated with synthetic gestures. Synthetic gestures are processed
+ // in-order, so a queue is sufficient to identify the correct state for a
+ // completed gesture.
+ std::queue<SyntheticGestureCompletionCallback>
+ pending_synthetic_gesture_callbacks_;
// Specified whether the compositor will run in its own thread.
bool is_threaded_compositing_enabled_;
@@ -753,7 +780,15 @@ class CONTENT_EXPORT RenderWidget
int outstanding_ime_acks_;
#endif
- base::WeakPtrFactory<RenderWidget> weak_ptr_factory_;
+ scoped_ptr<ScreenMetricsEmulator> screen_metrics_emulator_;
+
+ // Popups may be displaced when screen metrics emulation is enabled.
+ // These values are used to properly adjust popup position.
+ gfx::Point popup_view_origin_for_emulation_;
+ gfx::Point popup_screen_origin_for_emulation_;
+ float popup_origin_scale_for_emulation_;
+
+ scoped_ptr<ResizingModeSelector> resizing_mode_selector_;
DISALLOW_COPY_AND_ASSIGN(RenderWidget);
};
diff --git a/chromium/content/renderer/render_widget_fullscreen.cc b/chromium/content/renderer/render_widget_fullscreen.cc
index 5798285de6c..d6650aeb267 100644
--- a/chromium/content/renderer/render_widget_fullscreen.cc
+++ b/chromium/content/renderer/render_widget_fullscreen.cc
@@ -7,11 +7,11 @@
#include "content/common/view_messages.h"
#include "third_party/WebKit/public/web/WebWidget.h"
-using WebKit::WebWidget;
+using blink::WebWidget;
namespace content {
-void RenderWidgetFullscreen::show(WebKit::WebNavigationPolicy) {
+void RenderWidgetFullscreen::show(blink::WebNavigationPolicy) {
DCHECK(!did_show_) << "received extraneous Show call";
DCHECK_NE(MSG_ROUTING_NONE, routing_id_);
DCHECK_NE(MSG_ROUTING_NONE, opener_id_);
@@ -24,8 +24,8 @@ void RenderWidgetFullscreen::show(WebKit::WebNavigationPolicy) {
}
RenderWidgetFullscreen::RenderWidgetFullscreen(
- const WebKit::WebScreenInfo& screen_info)
- : RenderWidget(WebKit::WebPopupTypeNone, screen_info, false, false) {
+ const blink::WebScreenInfo& screen_info)
+ : RenderWidget(blink::WebPopupTypeNone, screen_info, false, false) {
}
RenderWidgetFullscreen::~RenderWidgetFullscreen() {}
diff --git a/chromium/content/renderer/render_widget_fullscreen.h b/chromium/content/renderer/render_widget_fullscreen.h
index 9978fd2bf84..4b65b887809 100644
--- a/chromium/content/renderer/render_widget_fullscreen.h
+++ b/chromium/content/renderer/render_widget_fullscreen.h
@@ -14,13 +14,13 @@ namespace content {
// TODO(boliu): Override non-supported methods with no-op? eg setWindowRect().
class RenderWidgetFullscreen : public RenderWidget {
public:
- virtual void show(WebKit::WebNavigationPolicy);
+ virtual void show(blink::WebNavigationPolicy);
protected:
- RenderWidgetFullscreen(const WebKit::WebScreenInfo& screen_info);
+ RenderWidgetFullscreen(const blink::WebScreenInfo& screen_info);
virtual ~RenderWidgetFullscreen();
- virtual WebKit::WebWidget* CreateWebWidget();
+ virtual blink::WebWidget* CreateWebWidget();
bool Init(int32 opener_id);
};
diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.cc b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
index 751268ea4c4..dc222523bb8 100644
--- a/chromium/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
@@ -19,38 +19,35 @@
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebCanvas.h"
+#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebLayer.h"
#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/WebKit/public/web/WebCursorInfo.h"
#include "third_party/WebKit/public/web/WebWidget.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gl/gpu_preference.h"
-using WebKit::WebCanvas;
-using WebKit::WebCompositionUnderline;
-using WebKit::WebCursorInfo;
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-using WebKit::WebMouseEvent;
-using WebKit::WebMouseWheelEvent;
-using WebKit::WebPoint;
-using WebKit::WebRect;
-using WebKit::WebSize;
-using WebKit::WebString;
-using WebKit::WebTextDirection;
-using WebKit::WebTextInputType;
-using WebKit::WebVector;
-using WebKit::WebWidget;
-using WebKit::WGC3Dintptr;
+using blink::WebCanvas;
+using blink::WebCompositionUnderline;
+using blink::WebCursorInfo;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebPoint;
+using blink::WebRect;
+using blink::WebSize;
+using blink::WebString;
+using blink::WebTextDirection;
+using blink::WebTextInputType;
+using blink::WebVector;
+using blink::WebWidget;
+using blink::WGC3Dintptr;
namespace content {
namespace {
-// See third_party/WebKit/Source/WebCore/dom/WheelEvent.h.
-const float kTickDivisor = 120.0f;
-
class FullscreenMouseLockDispatcher : public MouseLockDispatcher {
public:
explicit FullscreenMouseLockDispatcher(RenderWidgetFullscreenPepper* widget);
@@ -312,7 +309,7 @@ class PepperWidget : public WebWidget {
}
virtual WebTextInputType textInputType() {
- return WebKit::WebTextInputTypeNone;
+ return blink::WebTextInputTypeNone;
}
virtual WebRect caretOrSelectionBounds() {
@@ -348,7 +345,7 @@ RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create(
int32 opener_id,
PepperPluginInstanceImpl* plugin,
const GURL& active_url,
- const WebKit::WebScreenInfo& screen_info) {
+ const blink::WebScreenInfo& screen_info) {
DCHECK_NE(MSG_ROUTING_NONE, opener_id);
scoped_refptr<RenderWidgetFullscreenPepper> widget(
new RenderWidgetFullscreenPepper(plugin, active_url, screen_info));
@@ -360,7 +357,7 @@ RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create(
RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper(
PepperPluginInstanceImpl* plugin,
const GURL& active_url,
- const WebKit::WebScreenInfo& screen_info)
+ const blink::WebScreenInfo& screen_info)
: RenderWidgetFullscreen(screen_info),
active_url_(active_url),
plugin_(plugin),
@@ -376,12 +373,12 @@ void RenderWidgetFullscreenPepper::Invalidate() {
InvalidateRect(gfx::Rect(size_.width(), size_.height()));
}
-void RenderWidgetFullscreenPepper::InvalidateRect(const WebKit::WebRect& rect) {
+void RenderWidgetFullscreenPepper::InvalidateRect(const blink::WebRect& rect) {
didInvalidateRect(rect);
}
void RenderWidgetFullscreenPepper::ScrollRect(
- int dx, int dy, const WebKit::WebRect& rect) {
+ int dx, int dy, const blink::WebRect& rect) {
didScrollRect(dx, dy, rect);
}
@@ -400,19 +397,20 @@ void RenderWidgetFullscreenPepper::Destroy() {
}
void RenderWidgetFullscreenPepper::DidChangeCursor(
- const WebKit::WebCursorInfo& cursor) {
+ const blink::WebCursorInfo& cursor) {
didChangeCursor(cursor);
}
-void RenderWidgetFullscreenPepper::SetLayer(WebKit::WebLayer* layer) {
+void RenderWidgetFullscreenPepper::SetLayer(blink::WebLayer* layer) {
layer_ = layer;
bool compositing = !!layer_;
if (compositing != is_accelerated_compositing_active_) {
if (compositing) {
- initializeLayerTreeView();
+ if (!layerTreeView())
+ initializeLayerTreeView();
if (!layerTreeView())
return;
- layer_->setBounds(WebKit::WebSize(size()));
+ layer_->setBounds(blink::WebSize(size()));
layer_->setDrawsContent(true);
compositor_->setDeviceScaleFactor(device_scale_factor_);
compositor_->setRootLayer(*layer_);
@@ -440,11 +438,6 @@ bool RenderWidgetFullscreenPepper::OnMessageReceived(const IPC::Message& msg) {
return RenderWidgetFullscreen::OnMessageReceived(msg);
}
-void RenderWidgetFullscreenPepper::WillInitiatePaint() {
- if (plugin_)
- plugin_->ViewWillInitiatePaint();
-}
-
void RenderWidgetFullscreenPepper::DidInitiatePaint() {
if (plugin_)
plugin_->ViewInitiatedPaint();
@@ -482,7 +475,7 @@ PepperPluginInstanceImpl*
void RenderWidgetFullscreenPepper::OnResize(
const ViewMsg_Resize_Params& params) {
if (layer_)
- layer_->setBounds(WebKit::WebSize(params.new_size));
+ layer_->setBounds(blink::WebSize(params.new_size));
RenderWidget::OnResize(params);
}
diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.h b/chromium/content/renderer/render_widget_fullscreen_pepper.h
index 29980e8ab74..5e2952cbd3c 100644
--- a/chromium/content/renderer/render_widget_fullscreen_pepper.h
+++ b/chromium/content/renderer/render_widget_fullscreen_pepper.h
@@ -11,7 +11,7 @@
#include "content/renderer/render_widget_fullscreen.h"
#include "third_party/WebKit/public/web/WebWidget.h"
-namespace WebKit {
+namespace blink {
class WebLayer;
}
@@ -28,15 +28,15 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
int32 opener_id,
PepperPluginInstanceImpl* plugin,
const GURL& active_url,
- const WebKit::WebScreenInfo& screen_info);
+ const blink::WebScreenInfo& screen_info);
// pepper::FullscreenContainer API.
virtual void Invalidate() OVERRIDE;
- virtual void InvalidateRect(const WebKit::WebRect& rect) OVERRIDE;
- virtual void ScrollRect(int dx, int dy, const WebKit::WebRect& rect) OVERRIDE;
+ virtual void InvalidateRect(const blink::WebRect& rect) OVERRIDE;
+ virtual void ScrollRect(int dx, int dy, const blink::WebRect& rect) OVERRIDE;
virtual void Destroy() OVERRIDE;
- virtual void DidChangeCursor(const WebKit::WebCursorInfo& cursor) OVERRIDE;
- virtual void SetLayer(WebKit::WebLayer* layer) OVERRIDE;
+ virtual void DidChangeCursor(const blink::WebCursorInfo& cursor) OVERRIDE;
+ virtual void SetLayer(blink::WebLayer* layer) OVERRIDE;
// IPC::Listener implementation. This overrides the implementation
// in RenderWidgetFullscreen.
@@ -54,11 +54,10 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
protected:
RenderWidgetFullscreenPepper(PepperPluginInstanceImpl* plugin,
const GURL& active_url,
- const WebKit::WebScreenInfo& screen_info);
+ const blink::WebScreenInfo& screen_info);
virtual ~RenderWidgetFullscreenPepper();
// RenderWidget API.
- virtual void WillInitiatePaint() OVERRIDE;
virtual void DidInitiatePaint() OVERRIDE;
virtual void DidFlushPaint() OVERRIDE;
virtual void Close() OVERRIDE;
@@ -71,7 +70,7 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
virtual void OnResize(const ViewMsg_Resize_Params& params) OVERRIDE;
// RenderWidgetFullscreen API.
- virtual WebKit::WebWidget* CreateWebWidget() OVERRIDE;
+ virtual blink::WebWidget* CreateWebWidget() OVERRIDE;
// RenderWidget overrides.
virtual GURL GetURLForGraphicsContext3D() OVERRIDE;
@@ -84,7 +83,7 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
// The plugin instance this widget wraps.
PepperPluginInstanceImpl* plugin_;
- WebKit::WebLayer* layer_;
+ blink::WebLayer* layer_;
scoped_ptr<MouseLockDispatcher> mouse_lock_dispatcher_;
diff --git a/chromium/content/renderer/render_widget_unittest.cc b/chromium/content/renderer/render_widget_unittest.cc
new file mode 100644
index 00000000000..1af4fafd7f9
--- /dev/null
+++ b/chromium/content/renderer/render_widget_unittest.cc
@@ -0,0 +1,146 @@
+// 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/render_widget.h"
+
+#include <vector>
+
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/common/input_messages.h"
+#include "content/public/test/mock_render_thread.h"
+#include "content/test/mock_render_process.h"
+#include "ipc/ipc_test_sink.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/gfx/rect.h"
+
+namespace content {
+
+class RenderWidgetUnittest : public testing::Test {
+ public:
+ RenderWidgetUnittest() {}
+ virtual ~RenderWidgetUnittest() {}
+
+ private:
+ MockRenderProcess render_process_;
+ MockRenderThread render_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetUnittest);
+};
+
+class TouchableRenderWidget : public RenderWidget {
+ public:
+ TouchableRenderWidget() : RenderWidget(blink::WebPopupTypeNone,
+ blink::WebScreenInfo(),
+ false,
+ false) {}
+
+ void SetTouchRegion(const std::vector<gfx::Rect>& rects) {
+ rects_ = rects;
+ }
+
+ void SendInputEvent(const blink::WebInputEvent& event) {
+ OnHandleInputEvent(&event, ui::LatencyInfo(), false);
+ }
+
+ IPC::TestSink* sink() { return &sink_; }
+
+ protected:
+ virtual ~TouchableRenderWidget() {}
+
+ // Overridden from RenderWidget:
+ virtual bool HasTouchEventHandlersAt(const gfx::Point& point) const OVERRIDE {
+ for (std::vector<gfx::Rect>::const_iterator iter = rects_.begin();
+ iter != rects_.end(); ++iter) {
+ if ((*iter).Contains(point))
+ return true;
+ }
+ return false;
+ }
+
+ virtual bool Send(IPC::Message* msg) OVERRIDE {
+ sink_.OnMessageReceived(*msg);
+ delete msg;
+ return true;
+ }
+
+ private:
+ std::vector<gfx::Rect> rects_;
+ IPC::TestSink sink_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchableRenderWidget);
+};
+
+TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
+ scoped_refptr<TouchableRenderWidget> widget = new TouchableRenderWidget();
+
+ blink::WebInputEvent::Type type;
+ InputEventAckState ack_state;
+ ui::LatencyInfo latency;
+
+ SyntheticWebTouchEvent touch;
+ touch.PressPoint(10, 10);
+
+ widget->SendInputEvent(touch);
+ ASSERT_EQ(1u, widget->sink()->message_count());
+
+ // Since there's currently no touch-event handling region, the response should
+ // be 'no consumer exists'.
+ const IPC::Message* message = widget->sink()->GetMessageAt(0);
+ EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
+ InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency);
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
+ widget->sink()->ClearMessages();
+
+ std::vector<gfx::Rect> rects;
+ rects.push_back(gfx::Rect(0, 0, 20, 20));
+ rects.push_back(gfx::Rect(25, 0, 10, 10));
+ widget->SetTouchRegion(rects);
+
+ widget->SendInputEvent(touch);
+ ASSERT_EQ(1u, widget->sink()->message_count());
+ message = widget->sink()->GetMessageAt(0);
+ EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
+ InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency);
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
+ widget->sink()->ClearMessages();
+}
+
+TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
+ scoped_refptr<TouchableRenderWidget> widget = new TouchableRenderWidget();
+ std::vector<gfx::Rect> rects;
+ rects.push_back(gfx::Rect(0, 0, 20, 20));
+ rects.push_back(gfx::Rect(25, 0, 10, 10));
+ widget->SetTouchRegion(rects);
+
+ blink::WebInputEvent::Type type;
+ InputEventAckState ack_state;
+ ui::LatencyInfo latency;
+
+ SyntheticWebTouchEvent touch;
+ touch.PressPoint(25, 25);
+
+ widget->SendInputEvent(touch);
+ ASSERT_EQ(1u, widget->sink()->message_count());
+
+ // Since there's currently no touch-event handling region, the response should
+ // be 'no consumer exists'.
+ const IPC::Message* message = widget->sink()->GetMessageAt(0);
+ EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
+ InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency);
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
+ widget->sink()->ClearMessages();
+
+ // Press a second touch point. This time, on a touch-handling region.
+ touch.PressPoint(10, 10);
+ widget->SendInputEvent(touch);
+ ASSERT_EQ(1u, widget->sink()->message_count());
+ message = widget->sink()->GetMessageAt(0);
+ EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
+ InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency);
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
+ widget->sink()->ClearMessages();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/renderer_clipboard_client.cc b/chromium/content/renderer/renderer_clipboard_client.cc
index 9df9508be90..9c47463bddd 100644
--- a/chromium/content/renderer/renderer_clipboard_client.cc
+++ b/chromium/content/renderer/renderer_clipboard_client.cc
@@ -100,69 +100,65 @@ ui::Clipboard* RendererClipboardClient::GetClipboard() {
return NULL;
}
-uint64 RendererClipboardClient::GetSequenceNumber(
- ui::Clipboard::Buffer buffer) {
+uint64 RendererClipboardClient::GetSequenceNumber(ui::ClipboardType type) {
uint64 sequence_number = 0;
RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_GetSequenceNumber(buffer,
- &sequence_number));
+ new ClipboardHostMsg_GetSequenceNumber(type, &sequence_number));
return sequence_number;
}
bool RendererClipboardClient::IsFormatAvailable(
const ui::Clipboard::FormatType& format,
- ui::Clipboard::Buffer buffer) {
+ ui::ClipboardType type) {
bool result;
RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_IsFormatAvailable(format, buffer, &result));
+ new ClipboardHostMsg_IsFormatAvailable(format, type, &result));
return result;
}
-void RendererClipboardClient::Clear(ui::Clipboard::Buffer buffer) {
- RenderThreadImpl::current()->Send(new ClipboardHostMsg_Clear(buffer));
+void RendererClipboardClient::Clear(ui::ClipboardType type) {
+ RenderThreadImpl::current()->Send(new ClipboardHostMsg_Clear(type));
}
void RendererClipboardClient::ReadAvailableTypes(
- ui::Clipboard::Buffer buffer,
- std::vector<string16>* types,
+ ui::ClipboardType type,
+ std::vector<base::string16>* types,
bool* contains_filenames) {
RenderThreadImpl::current()->Send(new ClipboardHostMsg_ReadAvailableTypes(
- buffer, types, contains_filenames));
+ type, types, contains_filenames));
}
-void RendererClipboardClient::ReadText(ui::Clipboard::Buffer buffer,
- string16* result) {
+void RendererClipboardClient::ReadText(ui::ClipboardType type,
+ base::string16* result) {
RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_ReadText(buffer, result));
+ new ClipboardHostMsg_ReadText(type, result));
}
-void RendererClipboardClient::ReadAsciiText(ui::Clipboard::Buffer buffer,
+void RendererClipboardClient::ReadAsciiText(ui::ClipboardType type,
std::string* result) {
RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_ReadAsciiText(buffer, result));
+ new ClipboardHostMsg_ReadAsciiText(type, result));
}
-void RendererClipboardClient::ReadHTML(ui::Clipboard::Buffer buffer,
- string16* markup,
+void RendererClipboardClient::ReadHTML(ui::ClipboardType type,
+ base::string16* markup,
GURL* url, uint32* fragment_start,
uint32* fragment_end) {
- RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_ReadHTML(buffer, markup, url, fragment_start,
- fragment_end));
+ RenderThreadImpl::current()->Send(new ClipboardHostMsg_ReadHTML(
+ type, markup, url, fragment_start, fragment_end));
}
-void RendererClipboardClient::ReadRTF(ui::Clipboard::Buffer buffer,
+void RendererClipboardClient::ReadRTF(ui::ClipboardType type,
std::string* result) {
- RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_ReadRTF(buffer, result));
+ RenderThreadImpl::current()->Send(new ClipboardHostMsg_ReadRTF(type, result));
}
-void RendererClipboardClient::ReadImage(ui::Clipboard::Buffer buffer,
+void RendererClipboardClient::ReadImage(ui::ClipboardType type,
std::string* data) {
base::SharedMemoryHandle image_handle;
uint32 image_size;
RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_ReadImage(buffer, &image_handle, &image_size));
+ new ClipboardHostMsg_ReadImage(type, &image_handle, &image_size));
if (base::SharedMemory::IsHandleValid(image_handle)) {
base::SharedMemory buffer(image_handle, true);
buffer.Map(image_size);
@@ -170,11 +166,11 @@ void RendererClipboardClient::ReadImage(ui::Clipboard::Buffer buffer,
}
}
-void RendererClipboardClient::ReadCustomData(ui::Clipboard::Buffer buffer,
- const string16& type,
- string16* data) {
+void RendererClipboardClient::ReadCustomData(ui::ClipboardType clipboard_type,
+ const base::string16& type,
+ base::string16* data) {
RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_ReadCustomData(buffer, type, data));
+ new ClipboardHostMsg_ReadCustomData(clipboard_type, type, data));
}
void RendererClipboardClient::ReadData(const ui::Clipboard::FormatType& format,
diff --git a/chromium/content/renderer/renderer_clipboard_client.h b/chromium/content/renderer/renderer_clipboard_client.h
index 888f1160c0e..96d05b2621a 100644
--- a/chromium/content/renderer/renderer_clipboard_client.h
+++ b/chromium/content/renderer/renderer_clipboard_client.h
@@ -17,27 +17,27 @@ class RendererClipboardClient : public ClipboardClient {
virtual ~RendererClipboardClient();
virtual ui::Clipboard* GetClipboard() OVERRIDE;
- virtual uint64 GetSequenceNumber(ui::Clipboard::Buffer buffer) OVERRIDE;
+ virtual uint64 GetSequenceNumber(ui::ClipboardType type) OVERRIDE;
virtual bool IsFormatAvailable(const ui::Clipboard::FormatType& format,
- ui::Clipboard::Buffer buffer) OVERRIDE;
- virtual void Clear(ui::Clipboard::Buffer buffer) OVERRIDE;
- virtual void ReadAvailableTypes(ui::Clipboard::Buffer buffer,
- std::vector<string16>* types,
+ ui::ClipboardType type) OVERRIDE;
+ virtual void Clear(ui::ClipboardType type) OVERRIDE;
+ virtual void ReadAvailableTypes(ui::ClipboardType type,
+ std::vector<base::string16>* types,
bool* contains_filenames) OVERRIDE;
- virtual void ReadText(ui::Clipboard::Buffer buffer,
- string16* result) OVERRIDE;
- virtual void ReadAsciiText(ui::Clipboard::Buffer buffer,
+ virtual void ReadText(ui::ClipboardType type,
+ base::string16* result) OVERRIDE;
+ virtual void ReadAsciiText(ui::ClipboardType type,
std::string* result) OVERRIDE;
- virtual void ReadHTML(ui::Clipboard::Buffer buffer, string16* markup,
- GURL* url, uint32* fragment_start,
+ virtual void ReadHTML(ui::ClipboardType type,
+ base::string16* markup,
+ GURL* url,
+ uint32* fragment_start,
uint32* fragment_end) OVERRIDE;
- virtual void ReadRTF(ui::Clipboard::Buffer buffer,
- std::string* result) OVERRIDE;
- virtual void ReadImage(ui::Clipboard::Buffer buffer,
- std::string* data) OVERRIDE;
- virtual void ReadCustomData(ui::Clipboard::Buffer buffer,
- const string16& type,
- string16* data) OVERRIDE;
+ virtual void ReadRTF(ui::ClipboardType type, std::string* result) OVERRIDE;
+ virtual void ReadImage(ui::ClipboardType type, std::string* data) OVERRIDE;
+ virtual void ReadCustomData(ui::ClipboardType clipboard_type,
+ const base::string16& type,
+ base::string16* data) OVERRIDE;
virtual void ReadData(const ui::Clipboard::FormatType& format,
std::string* data) OVERRIDE;
virtual WriteContext* CreateWriteContext() OVERRIDE;
diff --git a/chromium/content/renderer/renderer_date_time_picker.cc b/chromium/content/renderer/renderer_date_time_picker.cc
index 86d268ac913..592e2491451 100644
--- a/chromium/content/renderer/renderer_date_time_picker.cc
+++ b/chromium/content/renderer/renderer_date_time_picker.cc
@@ -6,48 +6,66 @@
#include "base/strings/string_util.h"
#include "content/common/view_messages.h"
-#include "content/renderer/date_time_formatter.h"
+#include "content/renderer/date_time_suggestion_builder.h"
#include "content/renderer/render_view_impl.h"
-
#include "third_party/WebKit/public/web/WebDateTimeChooserCompletion.h"
#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h"
#include "third_party/WebKit/public/web/WebDateTimeInputType.h"
+#include "ui/base/ime/text_input_type.h"
-using WebKit::WebString;
+using blink::WebString;
namespace content {
+static ui::TextInputType ToTextInputType(int type) {
+ switch (type) {
+ case blink::WebDateTimeInputTypeDate:
+ return ui::TEXT_INPUT_TYPE_DATE;
+ break;
+ case blink::WebDateTimeInputTypeDateTime:
+ return ui::TEXT_INPUT_TYPE_DATE_TIME;
+ break;
+ case blink::WebDateTimeInputTypeDateTimeLocal:
+ return ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL;
+ break;
+ case blink::WebDateTimeInputTypeMonth:
+ return ui::TEXT_INPUT_TYPE_MONTH;
+ break;
+ case blink::WebDateTimeInputTypeTime:
+ return ui::TEXT_INPUT_TYPE_TIME;
+ break;
+ case blink::WebDateTimeInputTypeWeek:
+ return ui::TEXT_INPUT_TYPE_WEEK;
+ break;
+ case blink::WebDateTimeInputTypeNone:
+ default:
+ return ui::TEXT_INPUT_TYPE_NONE;
+ }
+}
+
RendererDateTimePicker::RendererDateTimePicker(
RenderViewImpl* sender,
- const WebKit::WebDateTimeChooserParams& params,
- WebKit::WebDateTimeChooserCompletion* completion)
+ const blink::WebDateTimeChooserParams& params,
+ blink::WebDateTimeChooserCompletion* completion)
: RenderViewObserver(sender),
chooser_params_(params),
- chooser_completion_(completion){
+ chooser_completion_(completion) {
}
RendererDateTimePicker::~RendererDateTimePicker() {
}
bool RendererDateTimePicker::Open() {
- DateTimeFormatter parser(chooser_params_);
ViewHostMsg_DateTimeDialogValue_Params message;
- message.dialog_type = parser.GetType();
- if (message.dialog_type == ui::TEXT_INPUT_TYPE_WEEK) {
- message.year = parser.GetWeekYear();
- message.week = parser.GetWeek();
- } else {
- message.year = parser.GetYear();
- message.month = parser.GetMonth();
- message.day = parser.GetDay();
- message.hour = parser.GetHour();
- message.minute = parser.GetMinute();
- message.second = parser.GetSecond();
- message.milli = parser.GetMilli();
- }
+ message.dialog_type = ToTextInputType(chooser_params_.type);
+ message.dialog_value = chooser_params_.doubleValue;
message.minimum = chooser_params_.minimum;
message.maximum = chooser_params_.maximum;
message.step = chooser_params_.step;
+ for (size_t i = 0; i < chooser_params_.suggestions.size(); i++) {
+ message.suggestions.push_back(
+ DateTimeSuggestionBuilder::Build(chooser_params_.suggestions[i]));
+ }
Send(new ViewHostMsg_OpenDateTimeDialog(routing_id(), message));
return true;
}
@@ -63,28 +81,20 @@ bool RendererDateTimePicker::OnMessageReceived(
return handled;
}
-void RendererDateTimePicker::OnReplaceDateTime(
- const ViewHostMsg_DateTimeDialogValue_Params& value) {
-
- DateTimeFormatter formatter(static_cast<ui::TextInputType>(value.dialog_type),
- value.year,
- value.month,
- value.day,
- value.hour,
- value.minute,
- value.second,
- value.milli,
- value.year,
- value.week);
-
+void RendererDateTimePicker::OnReplaceDateTime(double value) {
if (chooser_completion_)
- chooser_completion_->didChooseValue(WebString::fromUTF8(
- formatter.GetFormattedValue().c_str()));
+ chooser_completion_->didChooseValue(value);
+#if defined(OS_ANDROID)
+ static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog();
+#endif
}
void RendererDateTimePicker::OnCancel() {
if (chooser_completion_)
chooser_completion_->didCancelChooser();
+#if defined(OS_ANDROID)
+ static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog();
+#endif
}
} // namespace content
diff --git a/chromium/content/renderer/renderer_date_time_picker.h b/chromium/content/renderer/renderer_date_time_picker.h
index d7292b7e37c..7a780c7826d 100644
--- a/chromium/content/renderer/renderer_date_time_picker.h
+++ b/chromium/content/renderer/renderer_date_time_picker.h
@@ -11,9 +11,9 @@
struct ViewHostMsg_DateTimeDialogValue_Params;
-namespace WebKit {
+namespace blink {
class WebDateTimeChooserCompletion;
-} // namespace WebKit
+} // namespace blink
namespace content {
class RenderViewImpl;
@@ -22,21 +22,21 @@ class RendererDateTimePicker : public RenderViewObserver {
public:
RendererDateTimePicker(
RenderViewImpl* sender,
- const WebKit::WebDateTimeChooserParams& params,
- WebKit::WebDateTimeChooserCompletion* completion);
+ const blink::WebDateTimeChooserParams& params,
+ blink::WebDateTimeChooserCompletion* completion);
virtual ~RendererDateTimePicker();
bool Open();
private:
- void OnReplaceDateTime(const ViewHostMsg_DateTimeDialogValue_Params& value);
+ void OnReplaceDateTime(double value);
void OnCancel();
// RenderViewObserver
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- WebKit::WebDateTimeChooserParams chooser_params_;
- WebKit::WebDateTimeChooserCompletion* chooser_completion_; // Not owned by us
+ blink::WebDateTimeChooserParams chooser_params_;
+ blink::WebDateTimeChooserCompletion* chooser_completion_; // Not owned by us
DISALLOW_COPY_AND_ASSIGN(RendererDateTimePicker);
};
diff --git a/chromium/content/renderer/renderer_main.cc b/chromium/content/renderer/renderer_main.cc
index 1c33cf340a0..f0c16d27815 100644
--- a/chromium/content/renderer/renderer_main.cc
+++ b/chromium/content/renderer/renderer_main.cc
@@ -32,7 +32,6 @@
#include "content/renderer/renderer_main_platform_delegate.h"
#include "ui/base/ui_base_switches.h"
#include "webkit/child/webkit_child_helpers.h"
-#include "webkit/glue/webkit_glue.h"
#if defined(OS_ANDROID)
#include "base/android/sys_utils.h"
@@ -160,7 +159,7 @@ int RendererMain(const MainFunctionParams& parameters) {
RendererMessageLoopObserver task_observer;
#if defined(OS_MACOSX)
// As long as we use Cocoa in the renderer (for the forseeable future as of
- // now; see http://crbug.com/13890 for info) we need to have a UI loop.
+ // now; see http://crbug.com/306348 for info) we need to have a UI loop.
base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI);
#else
// The main message loop of the renderer services doesn't have IO or UI tasks,
diff --git a/chromium/content/renderer/renderer_main_platform_delegate_linux.cc b/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
index e473ad895f3..bc9deec23a8 100644
--- a/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
+++ b/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
@@ -10,7 +10,7 @@
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
-#include "content/common/sandbox_linux.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/sandbox_init.h"
@@ -69,7 +69,7 @@ void RendererMainPlatformDelegate::RunSandboxTests(bool no_sandbox) {
// Here, we test that the status of SeccompBpf in the renderer is consistent
// with what LinuxSandbox::GetStatus() said we would do.
class LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
- if (linux_sandbox->GetStatus() & kSandboxLinuxSeccompBpf) {
+ if (linux_sandbox->GetStatus() & kSandboxLinuxSeccompBPF) {
CHECK(linux_sandbox->seccomp_bpf_started());
}
diff --git a/chromium/content/renderer/renderer_main_platform_delegate_mac.mm b/chromium/content/renderer/renderer_main_platform_delegate_mac.mm
index e7cf9ffa4cd..9f6172e71e1 100644
--- a/chromium/content/renderer/renderer_main_platform_delegate_mac.mm
+++ b/chromium/content/renderer/renderer_main_platform_delegate_mac.mm
@@ -101,7 +101,7 @@ static void LogTestMessage(std::string message, bool is_error) {
if (is_error)
LOG(ERROR) << message;
else
- LOG(INFO) << message;
+ VLOG(0) << message;
}
bool RendererMainPlatformDelegate::InitSandboxTests(bool no_sandbox) {
@@ -127,7 +127,7 @@ bool RendererMainPlatformDelegate::InitSandboxTests(bool no_sandbox) {
}
bool RendererMainPlatformDelegate::EnableSandbox() {
- // http://openradar.appspot.com/radar?id=1156410 is fixed on OS X 10.9+.
+ // rdar://9251340 http://openradar.me/9251340
// See http://crbug.com/31225 and http://crbug.com/152566
// To check if this is broken:
// 1. Enable Multi language input (simplified chinese)
@@ -140,8 +140,8 @@ bool RendererMainPlatformDelegate::EnableSandbox() {
// and then kill that pid to make it go away.)
//
// Chinese Handwriting was introduced in 10.6 and is confirmed broken on
- // 10.6, 10.7, and 10.8. It's reportedly fixed on 10.9.
- bool needs_ime_hack = !base::mac::IsOSLaterThanMountainLion_DontCallThis();
+ // 10.6, 10.7, and 10.8. It's fixed on 10.9.
+ bool needs_ime_hack = base::mac::IsOSMountainLionOrEarlier();
if (needs_ime_hack) {
mach_error_t err = mach_override_ptr(
diff --git a/chromium/content/renderer/renderer_main_platform_delegate_win.cc b/chromium/content/renderer/renderer_main_platform_delegate_win.cc
index c4b46163cbc..e425c5ab77f 100644
--- a/chromium/content/renderer/renderer_main_platform_delegate_win.cc
+++ b/chromium/content/renderer/renderer_main_platform_delegate_win.cc
@@ -38,8 +38,9 @@ void SkiaPreCacheFontCharacters(const LOGFONT& logfont,
unsigned int text_length) {
RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
if (render_thread_impl) {
- render_thread_impl->PreCacheFontCharacters(logfont,
- string16(text, text_length));
+ render_thread_impl->PreCacheFontCharacters(
+ logfont,
+ base::string16(text, text_length));
}
}
diff --git a/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc b/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc
index 42b281c10db..8aeee8a960e 100644
--- a/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc
+++ b/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc
@@ -11,8 +11,8 @@
#include "third_party/WebKit/public/web/WebView.h"
using appcache::AppCacheBackend;
-using WebKit::WebApplicationCacheHostClient;
-using WebKit::WebConsoleMessage;
+using blink::WebApplicationCacheHostClient;
+using blink::WebConsoleMessage;
namespace content {
@@ -34,10 +34,10 @@ void RendererWebApplicationCacheHostImpl::OnLogMessage(
!render_view->webview()->mainFrame())
return;
- WebKit::WebFrame* frame = render_view->webview()->mainFrame();
+ blink::WebFrame* frame = render_view->webview()->mainFrame();
frame->addMessageToConsole(WebConsoleMessage(
static_cast<WebConsoleMessage::Level>(log_level),
- WebKit::WebString::fromUTF8(message.c_str())));
+ blink::WebString::fromUTF8(message.c_str())));
}
void RendererWebApplicationCacheHostImpl::OnContentBlocked(
diff --git a/chromium/content/renderer/renderer_webapplicationcachehost_impl.h b/chromium/content/renderer/renderer_webapplicationcachehost_impl.h
index 06120398cfc..16fd17c2115 100644
--- a/chromium/content/renderer/renderer_webapplicationcachehost_impl.h
+++ b/chromium/content/renderer/renderer_webapplicationcachehost_impl.h
@@ -14,7 +14,7 @@ class RendererWebApplicationCacheHostImpl : public WebApplicationCacheHostImpl {
public:
RendererWebApplicationCacheHostImpl(
RenderViewImpl* render_view,
- WebKit::WebApplicationCacheHostClient* client,
+ blink::WebApplicationCacheHostClient* client,
appcache::AppCacheBackend* backend);
// WebApplicationCacheHostImpl:
diff --git a/chromium/content/renderer/renderer_webcolorchooser_impl.cc b/chromium/content/renderer/renderer_webcolorchooser_impl.cc
index 337ec7e6212..5cfbd7397d2 100644
--- a/chromium/content/renderer/renderer_webcolorchooser_impl.cc
+++ b/chromium/content/renderer/renderer_webcolorchooser_impl.cc
@@ -16,7 +16,7 @@ static int GenerateColorChooserIdentifier() {
RendererWebColorChooserImpl::RendererWebColorChooserImpl(
RenderViewImpl* render_view,
- WebKit::WebColorChooserClient* client)
+ blink::WebColorChooserClient* client)
: RenderViewObserver(render_view),
identifier_(GenerateColorChooserIdentifier()),
client_(client) {
@@ -38,7 +38,7 @@ bool RendererWebColorChooserImpl::OnMessageReceived(
return handled;
}
-void RendererWebColorChooserImpl::setSelectedColor(WebKit::WebColor color) {
+void RendererWebColorChooserImpl::setSelectedColor(blink::WebColor color) {
Send(new ViewHostMsg_SetSelectedColorInColorChooser(routing_id(), identifier_,
static_cast<SkColor>(color)));
}
@@ -47,16 +47,20 @@ void RendererWebColorChooserImpl::endChooser() {
Send(new ViewHostMsg_EndColorChooser(routing_id(), identifier_));
}
-void RendererWebColorChooserImpl::Open(SkColor initial_color) {
- Send(new ViewHostMsg_OpenColorChooser(routing_id(), identifier_,
- initial_color));
+void RendererWebColorChooserImpl::Open(
+ SkColor initial_color,
+ const std::vector<content::ColorSuggestion>& suggestions) {
+ Send(new ViewHostMsg_OpenColorChooser(routing_id(),
+ identifier_,
+ initial_color,
+ suggestions));
}
void RendererWebColorChooserImpl::OnDidChooseColorResponse(int color_chooser_id,
SkColor color) {
DCHECK(identifier_ == color_chooser_id);
- client_->didChooseColor(static_cast<WebKit::WebColor>(color));
+ client_->didChooseColor(static_cast<blink::WebColor>(color));
}
void RendererWebColorChooserImpl::OnDidEndColorChooser(int color_chooser_id) {
diff --git a/chromium/content/renderer/renderer_webcolorchooser_impl.h b/chromium/content/renderer/renderer_webcolorchooser_impl.h
index bd8f235528a..d7534788738 100644
--- a/chromium/content/renderer/renderer_webcolorchooser_impl.h
+++ b/chromium/content/renderer/renderer_webcolorchooser_impl.h
@@ -5,32 +5,36 @@
#ifndef CONTENT_RENDERER_RENDERER_WEBCOLORCHOOSER_IMPL_H_
#define CONTENT_RENDERER_RENDERER_WEBCOLORCHOOSER_IMPL_H_
+#include <vector>
+
#include "base/compiler_specific.h"
+#include "content/public/common/color_suggestion.h"
#include "content/public/renderer/render_view_observer.h"
#include "third_party/WebKit/public/web/WebColorChooser.h"
#include "third_party/WebKit/public/web/WebColorChooserClient.h"
#include "third_party/skia/include/core/SkColor.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
}
namespace content {
class RenderViewImpl;
-class RendererWebColorChooserImpl : public WebKit::WebColorChooser,
+class RendererWebColorChooserImpl : public blink::WebColorChooser,
public RenderViewObserver {
public:
explicit RendererWebColorChooserImpl(RenderViewImpl* sender,
- WebKit::WebColorChooserClient*);
+ blink::WebColorChooserClient*);
virtual ~RendererWebColorChooserImpl();
- virtual void setSelectedColor(const WebKit::WebColor);
+ virtual void setSelectedColor(const blink::WebColor);
virtual void endChooser();
- void Open(SkColor initial_color);
+ void Open(SkColor initial_color,
+ const std::vector<content::ColorSuggestion>& suggestions);
- WebKit::WebColorChooserClient* client() { return client_; }
+ blink::WebColorChooserClient* client() { return client_; }
private:
// RenderViewObserver implementation.
@@ -40,7 +44,7 @@ class RendererWebColorChooserImpl : public WebKit::WebColorChooser,
void OnDidEndColorChooser(int color_chooser_id);
int identifier_;
- WebKit::WebColorChooserClient* client_;
+ blink::WebColorChooserClient* client_;
DISALLOW_COPY_AND_ASSIGN(RendererWebColorChooserImpl);
};
diff --git a/chromium/content/renderer/renderer_webcookiejar_impl.cc b/chromium/content/renderer/renderer_webcookiejar_impl.cc
index c9e6934e714..c74f16ac701 100644
--- a/chromium/content/renderer/renderer_webcookiejar_impl.cc
+++ b/chromium/content/renderer/renderer_webcookiejar_impl.cc
@@ -11,10 +11,10 @@
#include "content/renderer/render_view_impl.h"
#include "third_party/WebKit/public/platform/WebCookie.h"
-using WebKit::WebCookie;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebVector;
+using blink::WebCookie;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebVector;
namespace content {
@@ -22,23 +22,15 @@ void RendererWebCookieJarImpl::setCookie(
const WebURL& url, const WebURL& first_party_for_cookies,
const WebString& value) {
std::string value_utf8 = UTF16ToUTF8(value);
- if (!GetContentClient()->renderer()->HandleSetCookieRequest(
- sender_, url, first_party_for_cookies, value_utf8)) {
- sender_->Send(new ViewHostMsg_SetCookie(
- MSG_ROUTING_NONE, url, first_party_for_cookies, value_utf8));
- }
+ sender_->Send(new ViewHostMsg_SetCookie(
+ MSG_ROUTING_NONE, url, first_party_for_cookies, value_utf8));
}
WebString RendererWebCookieJarImpl::cookies(
const WebURL& url, const WebURL& first_party_for_cookies) {
std::string value_utf8;
-
- if (!GetContentClient()->renderer()->HandleGetCookieRequest(
- sender_, url, first_party_for_cookies, &value_utf8)) {
- // NOTE: This may pump events (see RenderThread::Send).
- sender_->Send(new ViewHostMsg_GetCookies(
- MSG_ROUTING_NONE, url, first_party_for_cookies, &value_utf8));
- }
+ sender_->Send(new ViewHostMsg_GetCookies(
+ MSG_ROUTING_NONE, url, first_party_for_cookies, &value_utf8));
return WebString::fromUTF8(value_utf8);
}
diff --git a/chromium/content/renderer/renderer_webcookiejar_impl.h b/chromium/content/renderer/renderer_webcookiejar_impl.h
index 4820bc487f0..a6451af3509 100644
--- a/chromium/content/renderer/renderer_webcookiejar_impl.h
+++ b/chromium/content/renderer/renderer_webcookiejar_impl.h
@@ -12,7 +12,7 @@
namespace content {
class RenderViewImpl;
-class RendererWebCookieJarImpl : public WebKit::WebCookieJar {
+class RendererWebCookieJarImpl : public blink::WebCookieJar {
public:
explicit RendererWebCookieJarImpl(RenderViewImpl* sender)
: sender_(sender) {
@@ -20,21 +20,21 @@ class RendererWebCookieJarImpl : public WebKit::WebCookieJar {
virtual ~RendererWebCookieJarImpl() {}
private:
- // WebKit::WebCookieJar methods:
+ // blink::WebCookieJar methods:
virtual void setCookie(
- const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies,
- const WebKit::WebString& value);
- virtual WebKit::WebString cookies(
- const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies);
- virtual WebKit::WebString cookieRequestHeaderFieldValue(
- const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies);
+ const blink::WebURL& url, const blink::WebURL& first_party_for_cookies,
+ const blink::WebString& value);
+ virtual blink::WebString cookies(
+ const blink::WebURL& url, const blink::WebURL& first_party_for_cookies);
+ virtual blink::WebString cookieRequestHeaderFieldValue(
+ const blink::WebURL& url, const blink::WebURL& first_party_for_cookies);
virtual void rawCookies(
- const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies,
- WebKit::WebVector<WebKit::WebCookie>& cookies);
+ const blink::WebURL& url, const blink::WebURL& first_party_for_cookies,
+ blink::WebVector<blink::WebCookie>& cookies);
virtual void deleteCookie(
- const WebKit::WebURL& url, const WebKit::WebString& cookie_name);
+ const blink::WebURL& url, const blink::WebString& cookie_name);
virtual bool cookiesEnabled(
- const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies);
+ const blink::WebURL& url, const blink::WebURL& first_party_for_cookies);
RenderViewImpl* sender_;
};
diff --git a/chromium/content/renderer/renderer_webkitplatformsupport_impl.cc b/chromium/content/renderer/renderer_webkitplatformsupport_impl.cc
index 25ca5d13968..6013a05d052 100644
--- a/chromium/content/renderer/renderer_webkitplatformsupport_impl.cc
+++ b/chromium/content/renderer/renderer_webkitplatformsupport_impl.cc
@@ -16,16 +16,19 @@
#include "base/strings/utf_string_conversions.h"
#include "content/child/database_util.h"
#include "content/child/fileapi/webfilesystem_impl.h"
-#include "content/child/indexed_db/proxy_webidbfactory_impl.h"
+#include "content/child/indexed_db/webidbfactory_impl.h"
#include "content/child/npapi/npobject_util.h"
#include "content/child/quota_dispatcher.h"
#include "content/child/quota_message_filter.h"
#include "content/child/thread_safe_sender.h"
+#include "content/child/web_database_observer_impl.h"
#include "content/child/webblobregistry_impl.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/file_utilities_messages.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
+#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "content/common/gpu/gpu_process_launch_causes.h"
#include "content/common/mime_registry_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_switches.h"
@@ -44,8 +47,8 @@
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_clipboard_client.h"
#include "content/renderer/webclipboard_impl.h"
-#include "content/renderer/webcrypto_impl.h"
-#include "content/renderer/websharedworkerrepository_impl.h"
+#include "content/renderer/webcrypto/webcrypto_impl.h"
+#include "content/renderer/webpublicsuffixlist_impl.h"
#include "gpu/config/gpu_info.h"
#include "ipc/ipc_sync_message_filter.h"
#include "media/audio/audio_output_device.h"
@@ -65,6 +68,7 @@
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
+#include "ui/gfx/color_profile.h"
#include "url/gurl.h"
#include "webkit/common/gpu/webgraphicscontext3d_provider_impl.h"
#include "webkit/common/quota/quota_types.h"
@@ -102,33 +106,34 @@
#include "content/renderer/media/android/audio_decoder_android.h"
#endif
-using WebKit::WebAudioDevice;
-using WebKit::WebBlobRegistry;
-using WebKit::WebFileInfo;
-using WebKit::WebFileSystem;
-using WebKit::WebFrame;
-using WebKit::WebGamepads;
-using WebKit::WebIDBFactory;
-using WebKit::WebMIDIAccessor;
-using WebKit::Platform;
-using WebKit::WebMediaStreamCenter;
-using WebKit::WebMediaStreamCenterClient;
-using WebKit::WebMimeRegistry;
-using WebKit::WebRTCPeerConnectionHandler;
-using WebKit::WebRTCPeerConnectionHandlerClient;
-using WebKit::WebStorageNamespace;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebVector;
+using blink::Platform;
+using blink::WebAudioDevice;
+using blink::WebBlobRegistry;
+using blink::WebDatabaseObserver;
+using blink::WebFileInfo;
+using blink::WebFileSystem;
+using blink::WebFrame;
+using blink::WebGamepads;
+using blink::WebIDBFactory;
+using blink::WebMIDIAccessor;
+using blink::WebMediaStreamCenter;
+using blink::WebMediaStreamCenterClient;
+using blink::WebMimeRegistry;
+using blink::WebRTCPeerConnectionHandler;
+using blink::WebRTCPeerConnectionHandlerClient;
+using blink::WebStorageNamespace;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebVector;
namespace content {
static bool g_sandbox_enabled = true;
base::LazyInstance<WebGamepads>::Leaky g_test_gamepads =
LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<WebKit::WebDeviceMotionData>::Leaky
+base::LazyInstance<blink::WebDeviceMotionData>::Leaky
g_test_device_motion_data = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<WebKit::WebDeviceOrientationData>::Leaky
+base::LazyInstance<blink::WebDeviceOrientationData>::Leaky
g_test_device_orientation_data = LAZY_INSTANCE_INITIALIZER;
//------------------------------------------------------------------------------
@@ -136,20 +141,16 @@ base::LazyInstance<WebKit::WebDeviceOrientationData>::Leaky
class RendererWebKitPlatformSupportImpl::MimeRegistry
: public webkit_glue::SimpleWebMimeRegistryImpl {
public:
- // TODO(ddorwin): Remove after http://webk.it/82983 lands.
- virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType(
- const WebKit::WebString& mime_type,
- const WebKit::WebString& codecs);
- virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType(
- const WebKit::WebString& mime_type,
- const WebKit::WebString& codecs,
- const WebKit::WebString& key_system);
- virtual bool supportsMediaSourceMIMEType(const WebKit::WebString& mime_type,
- const WebKit::WebString& codecs);
- virtual WebKit::WebString mimeTypeForExtension(
- const WebKit::WebString& file_extension);
- virtual WebKit::WebString mimeTypeFromFile(
- const WebKit::WebString& file_path);
+ virtual blink::WebMimeRegistry::SupportsType supportsMediaMIMEType(
+ const blink::WebString& mime_type,
+ const blink::WebString& codecs,
+ const blink::WebString& key_system);
+ virtual bool supportsMediaSourceMIMEType(const blink::WebString& mime_type,
+ const blink::WebString& codecs);
+ virtual blink::WebString mimeTypeForExtension(
+ const blink::WebString& file_extension);
+ virtual blink::WebString mimeTypeFromFile(
+ const blink::WebString& file_path);
};
class RendererWebKitPlatformSupportImpl::FileUtilities
@@ -170,7 +171,7 @@ class RendererWebKitPlatformSupportImpl::SandboxSupport {
};
#else
class RendererWebKitPlatformSupportImpl::SandboxSupport
- : public WebKit::WebSandboxSupport {
+ : public blink::WebSandboxSupport {
public:
virtual ~SandboxSupport() {}
@@ -183,18 +184,18 @@ class RendererWebKitPlatformSupportImpl::SandboxSupport
uint32* font_id);
#elif defined(OS_POSIX)
virtual void getFontFamilyForCharacter(
- WebKit::WebUChar32 character,
+ blink::WebUChar32 character,
const char* preferred_locale,
- WebKit::WebFontFamily* family);
+ blink::WebFontFamily* family);
virtual void getRenderStyleForStrike(
- const char* family, int sizeAndStyle, WebKit::WebFontRenderStyle* out);
+ const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out);
private:
// WebKit likes to ask us for the correct font family to use for a set of
// unicode code points. It needs this information frequently so we cache it
// here.
base::Lock unicode_font_families_mutex_;
- std::map<int32_t, WebKit::WebFontFamily> unicode_font_families_;
+ std::map<int32_t, blink::WebFontFamily> unicode_font_families_;
#endif
};
#endif // defined(OS_ANDROID)
@@ -207,7 +208,6 @@ RendererWebKitPlatformSupportImpl::RendererWebKitPlatformSupportImpl()
mime_registry_(new RendererWebKitPlatformSupportImpl::MimeRegistry),
sudden_termination_disables_(0),
plugin_refresh_allowed_(true),
- shared_worker_repository_(new WebSharedWorkerRepositoryImpl),
child_thread_loop_(base::MessageLoopProxy::current()) {
if (g_sandbox_enabled && sandboxEnabled()) {
sandbox_support_.reset(
@@ -221,6 +221,10 @@ RendererWebKitPlatformSupportImpl::RendererWebKitPlatformSupportImpl()
sync_message_filter_ = ChildThread::current()->sync_message_filter();
thread_safe_sender_ = ChildThread::current()->thread_safe_sender();
quota_message_filter_ = ChildThread::current()->quota_message_filter();
+ blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_));
+ web_idb_factory_.reset(new WebIDBFactoryImpl(thread_safe_sender_));
+ web_database_observer_impl_.reset(
+ new WebDatabaseObserverImpl(sync_message_filter_));
}
}
@@ -230,19 +234,19 @@ RendererWebKitPlatformSupportImpl::~RendererWebKitPlatformSupportImpl() {
//------------------------------------------------------------------------------
-WebKit::WebClipboard* RendererWebKitPlatformSupportImpl::clipboard() {
- WebKit::WebClipboard* clipboard =
+blink::WebClipboard* RendererWebKitPlatformSupportImpl::clipboard() {
+ blink::WebClipboard* clipboard =
GetContentClient()->renderer()->OverrideWebClipboard();
if (clipboard)
return clipboard;
return clipboard_.get();
}
-WebKit::WebMimeRegistry* RendererWebKitPlatformSupportImpl::mimeRegistry() {
+blink::WebMimeRegistry* RendererWebKitPlatformSupportImpl::mimeRegistry() {
return mime_registry_.get();
}
-WebKit::WebFileUtilities*
+blink::WebFileUtilities*
RendererWebKitPlatformSupportImpl::fileUtilities() {
if (!file_utilities_) {
file_utilities_.reset(new FileUtilities(thread_safe_sender_.get()));
@@ -251,7 +255,7 @@ RendererWebKitPlatformSupportImpl::fileUtilities() {
return file_utilities_.get();
}
-WebKit::WebSandboxSupport* RendererWebKitPlatformSupportImpl::sandboxSupport() {
+blink::WebSandboxSupport* RendererWebKitPlatformSupportImpl::sandboxSupport() {
#if defined(OS_ANDROID)
// WebKit doesn't use WebSandboxSupport on android.
return NULL;
@@ -260,13 +264,13 @@ WebKit::WebSandboxSupport* RendererWebKitPlatformSupportImpl::sandboxSupport() {
#endif
}
-WebKit::WebCookieJar* RendererWebKitPlatformSupportImpl::cookieJar() {
+blink::WebCookieJar* RendererWebKitPlatformSupportImpl::cookieJar() {
NOTREACHED() << "Use WebFrameClient::cookieJar() instead!";
return NULL;
}
-WebKit::WebThemeEngine* RendererWebKitPlatformSupportImpl::themeEngine() {
- WebKit::WebThemeEngine* theme_engine =
+blink::WebThemeEngine* RendererWebKitPlatformSupportImpl::themeEngine() {
+ blink::WebThemeEngine* theme_engine =
GetContentClient()->renderer()->OverrideThemeEngine();
if (theme_engine)
return theme_engine;
@@ -295,12 +299,12 @@ bool RendererWebKitPlatformSupportImpl::isLinkVisited(
return GetContentClient()->renderer()->IsLinkVisited(link_hash);
}
-WebKit::WebMessagePortChannel*
+blink::WebMessagePortChannel*
RendererWebKitPlatformSupportImpl::createMessagePortChannel() {
return new WebMessagePortChannelImpl(child_thread_loop_.get());
}
-WebKit::WebPrescientNetworking*
+blink::WebPrescientNetworking*
RendererWebKitPlatformSupportImpl::prescientNetworking() {
return GetContentClient()->renderer()->GetPrescientNetworking();
}
@@ -318,7 +322,7 @@ RendererWebKitPlatformSupportImpl::CheckPreparsedJsCachingEnabled() const {
}
void RendererWebKitPlatformSupportImpl::cacheMetadata(
- const WebKit::WebURL& url,
+ const blink::WebURL& url,
double response_time,
const char* data,
size_t size) {
@@ -366,9 +370,6 @@ RendererWebKitPlatformSupportImpl::createLocalStorageNamespace() {
//------------------------------------------------------------------------------
WebIDBFactory* RendererWebKitPlatformSupportImpl::idbFactory() {
- if (!web_idb_factory_)
- web_idb_factory_.reset(
- new RendererWebIDBFactoryImpl(thread_safe_sender_.get()));
return web_idb_factory_.get();
}
@@ -383,13 +384,6 @@ WebFileSystem* RendererWebKitPlatformSupportImpl::fileSystem() {
WebMimeRegistry::SupportsType
RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaMIMEType(
const WebString& mime_type,
- const WebString& codecs) {
- return supportsMediaMIMEType(mime_type, codecs, WebString());
-}
-
-WebMimeRegistry::SupportsType
-RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaMIMEType(
- const WebString& mime_type,
const WebString& codecs,
const WebString& key_system) {
const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
@@ -439,7 +433,7 @@ RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaMIMEType(
bool
RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaSourceMIMEType(
- const WebKit::WebString& mime_type,
+ const blink::WebString& mime_type,
const WebString& codecs) {
const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
std::vector<std::string> parsed_codec_ids;
@@ -557,11 +551,11 @@ bool RendererWebKitPlatformSupportImpl::SandboxSupport::loadFont(
void
RendererWebKitPlatformSupportImpl::SandboxSupport::getFontFamilyForCharacter(
- WebKit::WebUChar32 character,
+ blink::WebUChar32 character,
const char* preferred_locale,
- WebKit::WebFontFamily* family) {
+ blink::WebFontFamily* family) {
base::AutoLock lock(unicode_font_families_mutex_);
- const std::map<int32_t, WebKit::WebFontFamily>::const_iterator iter =
+ const std::map<int32_t, blink::WebFontFamily>::const_iterator iter =
unicode_font_families_.find(character);
if (iter != unicode_font_families_.end()) {
family->name = iter->second.name;
@@ -576,7 +570,7 @@ RendererWebKitPlatformSupportImpl::SandboxSupport::getFontFamilyForCharacter(
void
RendererWebKitPlatformSupportImpl::SandboxSupport::getRenderStyleForStrike(
- const char* family, int sizeAndStyle, WebKit::WebFontRenderStyle* out) {
+ const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out) {
GetRenderStyleForStrike(family, sizeAndStyle, out);
}
@@ -615,22 +609,6 @@ long long RendererWebKitPlatformSupportImpl::databaseGetSpaceAvailableForOrigin(
sync_message_filter_.get());
}
-WebKit::WebSharedWorkerRepository*
-RendererWebKitPlatformSupportImpl::sharedWorkerRepository() {
-#if !defined(OS_ANDROID)
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableSharedWorkers)) {
- return shared_worker_repository_.get();
- } else {
- return NULL;
- }
-#else
- // Shared workers are unsupported on Android. Returning NULL will prevent the
- // window.SharedWorker constructor from being exposed. http://crbug.com/154571
- return NULL;
-#endif
-}
-
bool RendererWebKitPlatformSupportImpl::canAccelerate2dCanvas() {
RenderThreadImpl* thread = RenderThreadImpl::current();
GpuChannelHost* host = thread->EstablishGpuChannelSync(
@@ -638,11 +616,7 @@ bool RendererWebKitPlatformSupportImpl::canAccelerate2dCanvas() {
if (!host)
return false;
- const gpu::GPUInfo& gpu_info = host->gpu_info();
- if (gpu_info.can_lose_context || gpu_info.software_rendering)
- return false;
-
- return true;
+ return host->gpu_info().SupportsAccelerated2dCanvas();
}
bool RendererWebKitPlatformSupportImpl::isThreadedCompositingEnabled() {
@@ -664,6 +638,10 @@ unsigned RendererWebKitPlatformSupportImpl::audioHardwareOutputChannels() {
return thread->GetAudioHardwareConfig()->GetOutputChannels();
}
+WebDatabaseObserver* RendererWebKitPlatformSupportImpl::databaseObserver() {
+ return web_database_observer_impl_.get();
+}
+
// TODO(crogers): remove deprecated API as soon as WebKit calls new API.
WebAudioDevice*
RendererWebKitPlatformSupportImpl::createAudioDevice(
@@ -694,9 +672,9 @@ RendererWebKitPlatformSupportImpl::createAudioDevice(
unsigned channels,
double sample_rate,
WebAudioDevice::RenderCallback* callback,
- const WebKit::WebString& input_device_id) {
+ const blink::WebString& input_device_id) {
// Use a mock for testing.
- WebKit::WebAudioDevice* mock_device =
+ blink::WebAudioDevice* mock_device =
GetContentClient()->renderer()->OverrideCreateAudioDevice(sample_rate);
if (mock_device)
return mock_device;
@@ -748,14 +726,15 @@ RendererWebKitPlatformSupportImpl::createAudioDevice(
media::AudioParameters params(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
layout, input_channels,
- static_cast<int>(sample_rate), 16, buffer_size);
+ static_cast<int>(sample_rate), 16, buffer_size,
+ media::AudioParameters::NO_EFFECTS);
return new RendererWebAudioDeviceImpl(params, callback, session_id);
}
#if defined(OS_ANDROID)
bool RendererWebKitPlatformSupportImpl::loadAudioResource(
- WebKit::WebAudioBus* destination_bus, const char* audio_file_data,
+ blink::WebAudioBus* destination_bus, const char* audio_file_data,
size_t data_size, double sample_rate) {
return DecodeAudioFileData(destination_bus,
audio_file_data,
@@ -765,7 +744,7 @@ bool RendererWebKitPlatformSupportImpl::loadAudioResource(
}
#else
bool RendererWebKitPlatformSupportImpl::loadAudioResource(
- WebKit::WebAudioBus* destination_bus, const char* audio_file_data,
+ blink::WebAudioBus* destination_bus, const char* audio_file_data,
size_t data_size, double sample_rate) {
return DecodeAudioFileData(
destination_bus, audio_file_data, data_size, sample_rate);
@@ -774,18 +753,18 @@ bool RendererWebKitPlatformSupportImpl::loadAudioResource(
//------------------------------------------------------------------------------
-WebKit::WebContentDecryptionModule*
+blink::WebContentDecryptionModule*
RendererWebKitPlatformSupportImpl::createContentDecryptionModule(
- const WebKit::WebString& key_system) {
+ const blink::WebString& key_system) {
return WebContentDecryptionModuleImpl::Create(key_system);
}
//------------------------------------------------------------------------------
-WebKit::WebMIDIAccessor*
+blink::WebMIDIAccessor*
RendererWebKitPlatformSupportImpl::createMIDIAccessor(
- WebKit::WebMIDIAccessorClient* client) {
- WebKit::WebMIDIAccessor* accessor =
+ blink::WebMIDIAccessorClient* client) {
+ blink::WebMIDIAccessor* accessor =
GetContentClient()->renderer()->OverrideCreateMIDIAccessor(client);
if (accessor)
return accessor;
@@ -795,7 +774,7 @@ RendererWebKitPlatformSupportImpl::createMIDIAccessor(
void RendererWebKitPlatformSupportImpl::getPluginList(
bool refresh,
- WebKit::WebPluginListBuilder* builder) {
+ blink::WebPluginListBuilder* builder) {
#if defined(ENABLE_PLUGINS)
std::vector<WebPluginInfo> plugins;
if (!plugin_refresh_allowed_)
@@ -826,11 +805,18 @@ void RendererWebKitPlatformSupportImpl::getPluginList(
//------------------------------------------------------------------------------
-WebKit::WebString
+blink::WebPublicSuffixList*
+RendererWebKitPlatformSupportImpl::publicSuffixList() {
+ return &public_suffix_list_;
+}
+
+//------------------------------------------------------------------------------
+
+blink::WebString
RendererWebKitPlatformSupportImpl::signedPublicKeyAndChallengeString(
unsigned key_size_index,
- const WebKit::WebString& challenge,
- const WebKit::WebURL& url) {
+ const blink::WebString& challenge,
+ const blink::WebURL& url) {
std::string signed_public_key;
RenderThread::Get()->Send(new ViewHostMsg_Keygen(
static_cast<uint32>(key_size_index),
@@ -844,18 +830,23 @@ RendererWebKitPlatformSupportImpl::signedPublicKeyAndChallengeString(
void RendererWebKitPlatformSupportImpl::screenColorProfile(
WebVector<char>* to_profile) {
+#if defined(OS_WIN)
+ // On Windows screen color profile is only available in the browser.
std::vector<char> profile;
RenderThread::Get()->Send(
new ViewHostMsg_GetMonitorColorProfile(&profile));
*to_profile = profile;
+#else
+ // On other platforms color profile can be obtained directly.
+ gfx::ColorProfile profile;
+ *to_profile = profile.profile();
+#endif
}
//------------------------------------------------------------------------------
WebBlobRegistry* RendererWebKitPlatformSupportImpl::blobRegistry() {
- // thread_safe_sender_ can be NULL when running some tests.
- if (!blob_registry_.get() && thread_safe_sender_.get())
- blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_.get()));
+ // blob_registry_ can be NULL when running some tests.
return blob_registry_.get();
}
@@ -869,8 +860,8 @@ void RendererWebKitPlatformSupportImpl::sampleGamepads(WebGamepads& gamepads) {
}
}
-WebKit::WebString RendererWebKitPlatformSupportImpl::userAgent(
- const WebKit::WebURL& url) {
+blink::WebString RendererWebKitPlatformSupportImpl::userAgent(
+ const blink::WebURL& url) {
return WebKitPlatformSupportImpl::userAgent(url);
}
@@ -927,9 +918,9 @@ void RendererWebKitPlatformSupportImpl::SetMockGamepadsForTesting(
//------------------------------------------------------------------------------
-WebKit::WebSpeechSynthesizer*
+blink::WebSpeechSynthesizer*
RendererWebKitPlatformSupportImpl::createSpeechSynthesizer(
- WebKit::WebSpeechSynthesizerClient* client) {
+ blink::WebSpeechSynthesizerClient* client) {
return GetContentClient()->renderer()->OverrideSpeechSynthesizer(client);
}
@@ -944,49 +935,65 @@ bool RendererWebKitPlatformSupportImpl::processMemorySizesInBytes(
//------------------------------------------------------------------------------
-WebKit::WebGraphicsContext3D*
+blink::WebGraphicsContext3D*
RendererWebKitPlatformSupportImpl::createOffscreenGraphicsContext3D(
- const WebKit::WebGraphicsContext3D::Attributes& attributes) {
+ const blink::WebGraphicsContext3D::Attributes& attributes) {
+ if (!RenderThreadImpl::current())
+ return NULL;
+
+ scoped_refptr<GpuChannelHost> gpu_channel_host(
+ RenderThreadImpl::current()->EstablishGpuChannelSync(
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
+
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
+
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kWebGLCommandBufferSizeKb)) {
+ std::string size_string = command_line->GetSwitchValueASCII(
+ switches::kWebGLCommandBufferSizeKb);
+ size_t buffer_size_kb;
+ if (base::StringToSizeT(size_string, &buffer_size_kb)) {
+ limits.command_buffer_size = buffer_size_kb * 1024;
+ }
+ }
+
return WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- RenderThreadImpl::current(),
+ gpu_channel_host.get(),
attributes,
- GURL(attributes.topDocumentURL));
+ GURL(attributes.topDocumentURL),
+ limits);
}
//------------------------------------------------------------------------------
-WebKit::WebGraphicsContext3DProvider* RendererWebKitPlatformSupportImpl::
+blink::WebGraphicsContext3DProvider* RendererWebKitPlatformSupportImpl::
createSharedOffscreenGraphicsContext3DProvider() {
- if (!shared_offscreen_context_.get() ||
- shared_offscreen_context_->DestroyedOnMainThread()) {
- shared_offscreen_context_ =
- RenderThreadImpl::current()->OffscreenContextProviderForMainThread();
- }
- if (!shared_offscreen_context_.get())
+ scoped_refptr<cc::ContextProvider> provider =
+ RenderThreadImpl::current()->SharedMainThreadContextProvider();
+ if (!provider)
return NULL;
- return new webkit::gpu::WebGraphicsContext3DProviderImpl(
- shared_offscreen_context_);
+ return new webkit::gpu::WebGraphicsContext3DProviderImpl(provider);
}
//------------------------------------------------------------------------------
-WebKit::WebCompositorSupport*
+blink::WebCompositorSupport*
RendererWebKitPlatformSupportImpl::compositorSupport() {
return &compositor_support_;
}
//------------------------------------------------------------------------------
-WebKit::WebString RendererWebKitPlatformSupportImpl::convertIDNToUnicode(
- const WebKit::WebString& host,
- const WebKit::WebString& languages) {
+blink::WebString RendererWebKitPlatformSupportImpl::convertIDNToUnicode(
+ const blink::WebString& host,
+ const blink::WebString& languages) {
return net::IDNToUnicode(host.utf8(), languages.utf8());
}
//------------------------------------------------------------------------------
void RendererWebKitPlatformSupportImpl::setDeviceMotionListener(
- WebKit::WebDeviceMotionListener* listener) {
+ blink::WebDeviceMotionListener* listener) {
if (g_test_device_motion_data == 0) {
if (!device_motion_event_pump_) {
device_motion_event_pump_.reset(new DeviceMotionEventPump);
@@ -997,7 +1004,7 @@ void RendererWebKitPlatformSupportImpl::setDeviceMotionListener(
// Testing mode: just echo the test data to the listener.
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
- base::Bind(&WebKit::WebDeviceMotionListener::didChangeDeviceMotion,
+ base::Bind(&blink::WebDeviceMotionListener::didChangeDeviceMotion,
base::Unretained(listener),
g_test_device_motion_data.Get()));
}
@@ -1005,14 +1012,14 @@ void RendererWebKitPlatformSupportImpl::setDeviceMotionListener(
// static
void RendererWebKitPlatformSupportImpl::SetMockDeviceMotionDataForTesting(
- const WebKit::WebDeviceMotionData& data) {
+ const blink::WebDeviceMotionData& data) {
g_test_device_motion_data.Get() = data;
}
//------------------------------------------------------------------------------
void RendererWebKitPlatformSupportImpl::setDeviceOrientationListener(
- WebKit::WebDeviceOrientationListener* listener) {
+ blink::WebDeviceOrientationListener* listener) {
if (g_test_device_orientation_data == 0) {
if (!device_orientation_event_pump_) {
device_orientation_event_pump_.reset(new DeviceOrientationEventPump);
@@ -1024,7 +1031,7 @@ void RendererWebKitPlatformSupportImpl::setDeviceOrientationListener(
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(
- &WebKit::WebDeviceOrientationListener::didChangeDeviceOrientation,
+ &blink::WebDeviceOrientationListener::didChangeDeviceOrientation,
base::Unretained(listener),
g_test_device_orientation_data.Get()));
}
@@ -1032,19 +1039,13 @@ void RendererWebKitPlatformSupportImpl::setDeviceOrientationListener(
// static
void RendererWebKitPlatformSupportImpl::SetMockDeviceOrientationDataForTesting(
- const WebKit::WebDeviceOrientationData& data) {
+ const blink::WebDeviceOrientationData& data) {
g_test_device_orientation_data.Get() = data;
}
//------------------------------------------------------------------------------
-WebKit::WebCrypto* RendererWebKitPlatformSupportImpl::crypto() {
- // Use a mock implementation for testing in-progress work.
- WebKit::WebCrypto* crypto =
- GetContentClient()->renderer()->OverrideWebCrypto();
- if (crypto)
- return crypto;
-
+blink::WebCrypto* RendererWebKitPlatformSupportImpl::crypto() {
if (!web_crypto_)
web_crypto_.reset(new WebCryptoImpl());
return web_crypto_.get();
@@ -1053,7 +1054,6 @@ WebKit::WebCrypto* RendererWebKitPlatformSupportImpl::crypto() {
//------------------------------------------------------------------------------
-#if defined(OS_ANDROID)
void RendererWebKitPlatformSupportImpl::vibrate(unsigned int milliseconds) {
RenderThread::Get()->Send(
new ViewHostMsg_Vibrate(base::checked_numeric_cast<int64>(milliseconds)));
@@ -1062,14 +1062,13 @@ void RendererWebKitPlatformSupportImpl::vibrate(unsigned int milliseconds) {
void RendererWebKitPlatformSupportImpl::cancelVibration() {
RenderThread::Get()->Send(new ViewHostMsg_CancelVibration());
}
-#endif // defined(OS_ANDROID)
//------------------------------------------------------------------------------
void RendererWebKitPlatformSupportImpl::queryStorageUsageAndQuota(
- const WebKit::WebURL& storage_partition,
- WebKit::WebStorageQuotaType type,
- WebKit::WebStorageQuotaCallbacks* callbacks) {
+ const blink::WebURL& storage_partition,
+ blink::WebStorageQuotaType type,
+ blink::WebStorageQuotaCallbacks* callbacks) {
if (!thread_safe_sender_.get() || !quota_message_filter_.get())
return;
QuotaDispatcher::ThreadSpecificInstance(
diff --git a/chromium/content/renderer/renderer_webkitplatformsupport_impl.h b/chromium/content/renderer/renderer_webkitplatformsupport_impl.h
index 1ec2a6c89a1..ca772948a8d 100644
--- a/chromium/content/renderer/renderer_webkitplatformsupport_impl.h
+++ b/chromium/content/renderer/renderer_webkitplatformsupport_impl.h
@@ -10,7 +10,7 @@
#include "base/platform_file.h"
#include "content/child/webkitplatformsupport_impl.h"
#include "content/common/content_export.h"
-#include "third_party/WebKit/public/web/WebSharedWorkerRepository.h"
+#include "content/renderer/webpublicsuffixlist_impl.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebIDBFactory.h"
#include "webkit/renderer/compositor_bindings/web_compositor_support_impl.h"
@@ -27,7 +27,7 @@ namespace IPC {
class SyncMessageFilter;
}
-namespace WebKit {
+namespace blink {
class WebDeviceMotionData;
class WebDeviceOrientationData;
class WebGraphicsContext3DProvider;
@@ -41,8 +41,8 @@ class RendererClipboardClient;
class ThreadSafeSender;
class WebClipboardImpl;
class WebCryptoImpl;
+class WebDatabaseObserverImpl;
class WebFileSystemImpl;
-class WebSharedWorkerRepositoryImpl;
class CONTENT_EXPORT RendererWebKitPlatformSupportImpl
: public WebKitPlatformSupportImpl {
@@ -54,104 +54,102 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl
plugin_refresh_allowed_ = plugin_refresh_allowed;
}
// Platform methods:
- virtual WebKit::WebClipboard* clipboard();
- virtual WebKit::WebMimeRegistry* mimeRegistry();
- virtual WebKit::WebFileUtilities* fileUtilities();
- virtual WebKit::WebSandboxSupport* sandboxSupport();
- virtual WebKit::WebCookieJar* cookieJar();
- virtual WebKit::WebThemeEngine* themeEngine();
- virtual WebKit::WebSpeechSynthesizer* createSpeechSynthesizer(
- WebKit::WebSpeechSynthesizerClient* client);
+ virtual blink::WebClipboard* clipboard();
+ virtual blink::WebMimeRegistry* mimeRegistry();
+ virtual blink::WebFileUtilities* fileUtilities();
+ virtual blink::WebSandboxSupport* sandboxSupport();
+ virtual blink::WebCookieJar* cookieJar();
+ virtual blink::WebThemeEngine* themeEngine();
+ virtual blink::WebSpeechSynthesizer* createSpeechSynthesizer(
+ blink::WebSpeechSynthesizerClient* client);
virtual bool sandboxEnabled();
virtual unsigned long long visitedLinkHash(
const char* canonicalURL, size_t length);
virtual bool isLinkVisited(unsigned long long linkHash);
- virtual WebKit::WebMessagePortChannel* createMessagePortChannel();
- virtual WebKit::WebPrescientNetworking* prescientNetworking();
+ virtual blink::WebMessagePortChannel* createMessagePortChannel();
+ virtual blink::WebPrescientNetworking* prescientNetworking();
virtual void cacheMetadata(
- const WebKit::WebURL&, double, const char*, size_t);
- virtual WebKit::WebString defaultLocale();
+ const blink::WebURL&, double, const char*, size_t);
+ virtual blink::WebString defaultLocale();
virtual void suddenTerminationChanged(bool enabled);
- virtual WebKit::WebStorageNamespace* createLocalStorageNamespace();
- virtual WebKit::Platform::FileHandle databaseOpenFile(
- const WebKit::WebString& vfs_file_name, int desired_flags);
- virtual int databaseDeleteFile(const WebKit::WebString& vfs_file_name,
+ virtual blink::WebStorageNamespace* createLocalStorageNamespace();
+ virtual blink::Platform::FileHandle databaseOpenFile(
+ const blink::WebString& vfs_file_name, int desired_flags);
+ virtual int databaseDeleteFile(const blink::WebString& vfs_file_name,
bool sync_dir);
virtual long databaseGetFileAttributes(
- const WebKit::WebString& vfs_file_name);
+ const blink::WebString& vfs_file_name);
virtual long long databaseGetFileSize(
- const WebKit::WebString& vfs_file_name);
+ const blink::WebString& vfs_file_name);
virtual long long databaseGetSpaceAvailableForOrigin(
- const WebKit::WebString& origin_identifier);
- virtual WebKit::WebString signedPublicKeyAndChallengeString(
+ const blink::WebString& origin_identifier);
+ virtual blink::WebString signedPublicKeyAndChallengeString(
unsigned key_size_index,
- const WebKit::WebString& challenge,
- const WebKit::WebURL& url);
+ const blink::WebString& challenge,
+ const blink::WebURL& url);
virtual void getPluginList(bool refresh,
- WebKit::WebPluginListBuilder* builder);
- virtual void screenColorProfile(WebKit::WebVector<char>* to_profile);
- virtual WebKit::WebIDBFactory* idbFactory();
- virtual WebKit::WebFileSystem* fileSystem();
- virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository();
+ blink::WebPluginListBuilder* builder);
+ virtual blink::WebPublicSuffixList* publicSuffixList();
+ virtual void screenColorProfile(blink::WebVector<char>* to_profile);
+ virtual blink::WebIDBFactory* idbFactory();
+ virtual blink::WebFileSystem* fileSystem();
virtual bool canAccelerate2dCanvas();
virtual bool isThreadedCompositingEnabled();
virtual double audioHardwareSampleRate();
virtual size_t audioHardwareBufferSize();
virtual unsigned audioHardwareOutputChannels();
+ virtual blink::WebDatabaseObserver* databaseObserver();
// TODO(crogers): remove deprecated API as soon as WebKit calls new API.
- virtual WebKit::WebAudioDevice* createAudioDevice(
+ virtual blink::WebAudioDevice* createAudioDevice(
size_t buffer_size, unsigned channels, double sample_rate,
- WebKit::WebAudioDevice::RenderCallback* callback);
+ blink::WebAudioDevice::RenderCallback* callback);
// TODO(crogers): remove deprecated API as soon as WebKit calls new API.
- virtual WebKit::WebAudioDevice* createAudioDevice(
+ virtual blink::WebAudioDevice* createAudioDevice(
size_t buffer_size, unsigned input_channels, unsigned channels,
- double sample_rate, WebKit::WebAudioDevice::RenderCallback* callback);
+ double sample_rate, blink::WebAudioDevice::RenderCallback* callback);
- virtual WebKit::WebAudioDevice* createAudioDevice(
+ virtual blink::WebAudioDevice* createAudioDevice(
size_t buffer_size, unsigned input_channels, unsigned channels,
- double sample_rate, WebKit::WebAudioDevice::RenderCallback* callback,
- const WebKit::WebString& input_device_id);
+ double sample_rate, blink::WebAudioDevice::RenderCallback* callback,
+ const blink::WebString& input_device_id);
virtual bool loadAudioResource(
- WebKit::WebAudioBus* destination_bus, const char* audio_file_data,
+ blink::WebAudioBus* destination_bus, const char* audio_file_data,
size_t data_size, double sample_rate);
- virtual WebKit::WebContentDecryptionModule* createContentDecryptionModule(
- const WebKit::WebString& key_system);
- virtual WebKit::WebMIDIAccessor*
- createMIDIAccessor(WebKit::WebMIDIAccessorClient* client);
-
- virtual WebKit::WebBlobRegistry* blobRegistry();
- virtual void sampleGamepads(WebKit::WebGamepads&);
- virtual WebKit::WebString userAgent(const WebKit::WebURL& url);
- virtual WebKit::WebRTCPeerConnectionHandler* createRTCPeerConnectionHandler(
- WebKit::WebRTCPeerConnectionHandlerClient* client);
- virtual WebKit::WebMediaStreamCenter* createMediaStreamCenter(
- WebKit::WebMediaStreamCenterClient* client);
+ virtual blink::WebContentDecryptionModule* createContentDecryptionModule(
+ const blink::WebString& key_system);
+ virtual blink::WebMIDIAccessor*
+ createMIDIAccessor(blink::WebMIDIAccessorClient* client);
+
+ virtual blink::WebBlobRegistry* blobRegistry();
+ virtual void sampleGamepads(blink::WebGamepads&);
+ virtual blink::WebString userAgent(const blink::WebURL& url);
+ virtual blink::WebRTCPeerConnectionHandler* createRTCPeerConnectionHandler(
+ blink::WebRTCPeerConnectionHandlerClient* client);
+ virtual blink::WebMediaStreamCenter* createMediaStreamCenter(
+ blink::WebMediaStreamCenterClient* client);
virtual bool processMemorySizesInBytes(
size_t* private_bytes, size_t* shared_bytes);
- virtual WebKit::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
- const WebKit::WebGraphicsContext3D::Attributes& attributes);
- virtual WebKit::WebGraphicsContext3DProvider*
+ virtual blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
+ const blink::WebGraphicsContext3D::Attributes& attributes);
+ virtual blink::WebGraphicsContext3DProvider*
createSharedOffscreenGraphicsContext3DProvider();
- virtual WebKit::WebCompositorSupport* compositorSupport();
- virtual WebKit::WebString convertIDNToUnicode(
- const WebKit::WebString& host, const WebKit::WebString& languages);
+ virtual blink::WebCompositorSupport* compositorSupport();
+ virtual blink::WebString convertIDNToUnicode(
+ const blink::WebString& host, const blink::WebString& languages);
virtual void setDeviceMotionListener(
- WebKit::WebDeviceMotionListener* listener) OVERRIDE;
+ blink::WebDeviceMotionListener* listener) OVERRIDE;
virtual void setDeviceOrientationListener(
- WebKit::WebDeviceOrientationListener* listener) OVERRIDE;
- virtual WebKit::WebCrypto* crypto() OVERRIDE;
+ blink::WebDeviceOrientationListener* listener) OVERRIDE;
+ virtual blink::WebCrypto* crypto() OVERRIDE;
virtual void queryStorageUsageAndQuota(
- const WebKit::WebURL& storage_partition,
- WebKit::WebStorageQuotaType,
- WebKit::WebStorageQuotaCallbacks*) OVERRIDE;
-
-#if defined(OS_ANDROID)
+ const blink::WebURL& storage_partition,
+ blink::WebStorageQuotaType,
+ blink::WebStorageQuotaCallbacks*) OVERRIDE;
virtual void vibrate(unsigned int milliseconds);
virtual void cancelVibration();
-#endif // defined(OS_ANDROID)
// Disables the WebSandboxSupport implementation for testing.
// Tests that do not set up a full sandbox environment should call
@@ -163,14 +161,18 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl
static bool SetSandboxEnabledForTesting(bool enable);
// Set WebGamepads to return when sampleGamepads() is invoked.
- static void SetMockGamepadsForTesting(const WebKit::WebGamepads& pads);
+ static void SetMockGamepadsForTesting(const blink::WebGamepads& pads);
// Set WebDeviceMotionData to return when setDeviceMotionListener is invoked.
static void SetMockDeviceMotionDataForTesting(
- const WebKit::WebDeviceMotionData& data);
+ const blink::WebDeviceMotionData& data);
// Set WebDeviceOrientationData to return when setDeviceOrientationListener
// is invoked.
static void SetMockDeviceOrientationDataForTesting(
- const WebKit::WebDeviceOrientationData& data);
+ const blink::WebDeviceOrientationData& data);
+
+ WebDatabaseObserverImpl* web_database_observer_impl() {
+ return web_database_observer_impl_.get();
+ }
private:
bool CheckPreparsedJsCachingEnabled() const;
@@ -196,15 +198,11 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl
// If true, then a GetPlugins call is allowed to rescan the disk.
bool plugin_refresh_allowed_;
- // Implementation of the WebSharedWorkerRepository APIs (provides an interface
- // to WorkerService on the browser thread.
- scoped_ptr<WebSharedWorkerRepositoryImpl> shared_worker_repository_;
-
- scoped_ptr<WebKit::WebIDBFactory> web_idb_factory_;
+ scoped_ptr<blink::WebIDBFactory> web_idb_factory_;
- scoped_ptr<WebFileSystemImpl> web_file_system_;
+ scoped_ptr<blink::WebBlobRegistry> blob_registry_;
- scoped_ptr<WebKit::WebBlobRegistry> blob_registry_;
+ WebPublicSuffixListImpl public_suffix_list_;
scoped_ptr<DeviceMotionEventPump> device_motion_event_pump_;
scoped_ptr<DeviceOrientationEventPump> device_orientation_event_pump_;
@@ -214,7 +212,7 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
scoped_refptr<QuotaMessageFilter> quota_message_filter_;
- scoped_refptr<cc::ContextProvider> shared_offscreen_context_;
+ scoped_ptr<WebDatabaseObserverImpl> web_database_observer_impl_;
webkit::WebCompositorSupportImpl compositor_support_;
diff --git a/chromium/content/renderer/resizing_mode_selector.cc b/chromium/content/renderer/resizing_mode_selector.cc
new file mode 100644
index 00000000000..d51b4570627
--- /dev/null
+++ b/chromium/content/renderer/resizing_mode_selector.cc
@@ -0,0 +1,38 @@
+// 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/resizing_mode_selector.h"
+
+#include "content/common/view_messages.h"
+#include "content/renderer/render_thread_impl.h"
+#include "content/renderer/render_widget.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
+
+namespace content {
+
+ResizingModeSelector::ResizingModeSelector() : is_synchronous_mode_(false) {}
+
+bool ResizingModeSelector::NeverUsesSynchronousResize() const {
+ return !RenderThreadImpl::current() || // can be NULL when in unit tests
+ !RenderThreadImpl::current()->layout_test_mode();
+}
+
+bool ResizingModeSelector::ShouldAbortOnResize(
+ RenderWidget* widget,
+ const ViewMsg_Resize_Params& params) {
+ return is_synchronous_mode_ &&
+ params.is_fullscreen == widget->is_fullscreen() &&
+ params.screen_info.deviceScaleFactor ==
+ widget->screenInfo().deviceScaleFactor;
+}
+
+void ResizingModeSelector::set_is_synchronous_mode(bool mode) {
+ is_synchronous_mode_ = mode;
+}
+
+bool ResizingModeSelector::is_synchronous_mode() const {
+ return is_synchronous_mode_;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/resizing_mode_selector.h b/chromium/content/renderer/resizing_mode_selector.h
new file mode 100644
index 00000000000..ac657e294cd
--- /dev/null
+++ b/chromium/content/renderer/resizing_mode_selector.h
@@ -0,0 +1,43 @@
+// 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_RESIZING_MODE_SELECTOR_H_
+#define CONTENT_RENDERER_RESIZING_MODE_SELECTOR_H_
+
+#include "base/basictypes.h"
+
+struct ViewMsg_Resize_Params;
+
+namespace content {
+
+class RenderWidget;
+
+// Enables switching between two modes of resizing:
+// 1) The "normal" (asynchronous) resizing, which involves sending messages to
+// and receiving them from host; and
+// 2) The synchronous mode, which short-circuits the resizing logic to operate
+// strictly inside renderer.
+// The latter is necessary to support a handful of layout tests that were
+// written with the expectation of a synchronous resize, and we're going to
+// eventually rewrite or remove all of them. See http://crbug.com/309760 for
+// details.
+class ResizingModeSelector {
+ public:
+ ResizingModeSelector();
+ bool NeverUsesSynchronousResize() const;
+ bool ShouldAbortOnResize(RenderWidget* widget,
+ const ViewMsg_Resize_Params& params);
+
+ void set_is_synchronous_mode(bool mode);
+ bool is_synchronous_mode() const;
+
+ private:
+ bool is_synchronous_mode_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResizingModeSelector);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_RESIZING_MODE_SELECTOR_H_
diff --git a/chromium/content/renderer/resource_fetcher_browsertest.cc b/chromium/content/renderer/resource_fetcher_browsertest.cc
index 573fe4d2b79..a9498cb0823 100644
--- a/chromium/content/renderer/resource_fetcher_browsertest.cc
+++ b/chromium/content/renderer/resource_fetcher_browsertest.cc
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/renderer/fetchers/resource_fetcher.h"
+#include "content/public/renderer/resource_fetcher.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
+#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
@@ -20,9 +21,9 @@
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
-using WebKit::WebFrame;
-using WebKit::WebURLRequest;
-using WebKit::WebURLResponse;
+using blink::WebFrame;
+using blink::WebURLRequest;
+using blink::WebURLResponse;
namespace content {
@@ -108,10 +109,13 @@ class EvilFetcherDelegate : public FetcherDelegate {
virtual void OnURLFetchComplete(const WebURLResponse& response,
const std::string& data) OVERRIDE {
+ FetcherDelegate::OnURLFetchComplete(response, data);
+
// Destroy the ResourceFetcher here. We are testing that upon returning
- // to the ResourceFetcher that it does not crash.
+ // to the ResourceFetcher that it does not crash. This must be done after
+ // calling FetcherDelegate::OnURLFetchComplete, since deleting the fetcher
+ // invalidates |response| and |data|.
fetcher_.reset();
- FetcherDelegate::OnURLFetchComplete(response, data);
}
private:
@@ -138,7 +142,7 @@ class ResourceFetcherTests : public ContentBrowserTest {
WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
- scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
+ scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(
url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback()));
delegate->WaitForResponse();
@@ -153,7 +157,7 @@ class ResourceFetcherTests : public ContentBrowserTest {
WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
- scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
+ scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(
url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback()));
delegate->WaitForResponse();
@@ -169,7 +173,7 @@ class ResourceFetcherTests : public ContentBrowserTest {
// Try to fetch a page on a site that doesn't exist.
GURL url("http://localhost:1339/doesnotexist");
scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
- scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
+ scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(
url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback()));
delegate->WaitForResponse();
@@ -186,9 +190,10 @@ class ResourceFetcherTests : public ContentBrowserTest {
WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
- scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout(
+ scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(
url, frame, WebURLRequest::TargetIsMainFrame,
- 0, delegate->NewCallback()));
+ delegate->NewCallback()));
+ fetcher->SetTimeout(base::TimeDelta());
delegate->WaitForResponse();
@@ -204,9 +209,10 @@ class ResourceFetcherTests : public ContentBrowserTest {
WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
scoped_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate);
- scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout(
+ scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(
url, frame, WebURLRequest::TargetIsMainFrame,
- 0, delegate->NewCallback()));
+ delegate->NewCallback()));
+ fetcher->SetTimeout(base::TimeDelta());
delegate->SetFetcher(fetcher.release());
delegate->WaitForResponse();
diff --git a/chromium/content/renderer/resources/media/mediaplayer_remote_playback.png b/chromium/content/renderer/resources/media/mediaplayer_remote_playback.png
new file mode 100644
index 00000000000..6916ce6dd67
--- /dev/null
+++ b/chromium/content/renderer/resources/media/mediaplayer_remote_playback.png
Binary files differ
diff --git a/chromium/content/renderer/sad_plugin.cc b/chromium/content/renderer/sad_plugin.cc
index a30788cf105..52d613d5d4f 100644
--- a/chromium/content/renderer/sad_plugin.cc
+++ b/chromium/content/renderer/sad_plugin.cc
@@ -13,7 +13,7 @@
namespace content {
-void PaintSadPlugin(WebKit::WebCanvas* webcanvas,
+void PaintSadPlugin(blink::WebCanvas* webcanvas,
const gfx::Rect& plugin_rect,
const SkBitmap& sad_plugin_bitmap) {
const int width = plugin_rect.width();
diff --git a/chromium/content/renderer/sad_plugin.h b/chromium/content/renderer/sad_plugin.h
index 827d705568b..4148c0ae086 100644
--- a/chromium/content/renderer/sad_plugin.h
+++ b/chromium/content/renderer/sad_plugin.h
@@ -17,7 +17,7 @@ namespace content {
// Paints the sad plugin to the given canvas for the given plugin bounds. This
// is used by both the NPAPI and the PPAPI out-of-process plugin impls.
-void PaintSadPlugin(WebKit::WebCanvas* canvas,
+void PaintSadPlugin(blink::WebCanvas* canvas,
const gfx::Rect& plugin_rect,
const SkBitmap& sad_plugin_bitmap);
diff --git a/chromium/content/renderer/savable_resources.cc b/chromium/content/renderer/savable_resources.cc
index f1b2fde4474..5e5e0478008 100644
--- a/chromium/content/renderer/savable_resources.cc
+++ b/chromium/content/renderer/savable_resources.cc
@@ -20,16 +20,16 @@
#include "third_party/WebKit/public/web/WebNodeList.h"
#include "third_party/WebKit/public/web/WebView.h"
-using WebKit::WebDocument;
-using WebKit::WebElement;
-using WebKit::WebFrame;
-using WebKit::WebInputElement;
-using WebKit::WebNode;
-using WebKit::WebNodeCollection;
-using WebKit::WebNodeList;
-using WebKit::WebString;
-using WebKit::WebVector;
-using WebKit::WebView;
+using blink::WebDocument;
+using blink::WebElement;
+using blink::WebFrame;
+using blink::WebInputElement;
+using blink::WebNode;
+using blink::WebNodeCollection;
+using blink::WebNodeList;
+using blink::WebString;
+using blink::WebVector;
+using blink::WebView;
namespace content {
namespace {
@@ -97,7 +97,7 @@ void GetSavableResourceLinkForElement(
result->resources_list->push_back(u);
// Insert referrer for above new resource link.
result->referrer_urls_list->push_back(GURL());
- result->referrer_policies_list->push_back(WebKit::WebReferrerPolicyDefault);
+ result->referrer_policies_list->push_back(blink::WebReferrerPolicyDefault);
}
// Get all savable resource links from current WebFrameImpl object pointer.
diff --git a/chromium/content/renderer/savable_resources.h b/chromium/content/renderer/savable_resources.h
index 52b51144cd7..94326927b4a 100644
--- a/chromium/content/renderer/savable_resources.h
+++ b/chromium/content/renderer/savable_resources.h
@@ -12,7 +12,7 @@
#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
#include "url/gurl.h"
-namespace WebKit {
+namespace blink {
class WebElement;
class WebString;
class WebView;
@@ -32,7 +32,7 @@ struct SavableResourcesResult {
// it matched with links one by one.
std::vector<GURL>* referrer_urls_list;
// and the corresponding referrer policies.
- std::vector<WebKit::WebReferrerPolicy>* referrer_policies_list;
+ std::vector<blink::WebReferrerPolicy>* referrer_policies_list;
// vector which contains all savable links of main frame and sub frames.
std::vector<GURL>* frames_list;
@@ -40,7 +40,7 @@ struct SavableResourcesResult {
SavableResourcesResult(
std::vector<GURL>* resources_list,
std::vector<GURL>* referrer_urls_list,
- std::vector<WebKit::WebReferrerPolicy>* referrer_policies_list,
+ std::vector<blink::WebReferrerPolicy>* referrer_policies_list,
std::vector<GURL>* frames_list)
: resources_list(resources_list),
referrer_urls_list(referrer_urls_list),
@@ -56,7 +56,7 @@ struct SavableResourcesResult {
// will send those links to embedder. Return value indicates whether we get
// all saved resource links successfully.
CONTENT_EXPORT bool GetAllSavableResourceLinksForCurrentPage(
- WebKit::WebView* view,
+ blink::WebView* view,
const GURL& page_url,
SavableResourcesResult* savable_resources_result,
const char** savable_schemes);
@@ -66,8 +66,8 @@ CONTENT_EXPORT bool GetAllSavableResourceLinksForCurrentPage(
// the value in "href". For BODY, TABLE, TR, TD, returns the value in
// "background". For BLOCKQUOTE, Q, DEL, INS, returns the value in "cite"
// attribute. Otherwise returns a null WebString.
-CONTENT_EXPORT WebKit::WebString GetSubResourceLinkFromElement(
- const WebKit::WebElement& element);
+CONTENT_EXPORT blink::WebString GetSubResourceLinkFromElement(
+ const blink::WebElement& element);
} // namespace content
diff --git a/chromium/content/renderer/savable_resources_browsertest.cc b/chromium/content/renderer/savable_resources_browsertest.cc
index a7ad83ac266..5f7a0ca4805 100644
--- a/chromium/content/renderer/savable_resources_browsertest.cc
+++ b/chromium/content/renderer/savable_resources_browsertest.cc
@@ -53,7 +53,7 @@ class SavableResourcesTest : public ContentBrowserTest {
// Get all savable resource links for the page.
std::vector<GURL> resources_list;
std::vector<GURL> referrer_urls_list;
- std::vector<WebKit::WebReferrerPolicy> referrer_policies_list;
+ std::vector<blink::WebReferrerPolicy> referrer_policies_list;
std::vector<GURL> frames_list;
SavableResourcesResult result(&resources_list,
&referrer_urls_list,
diff --git a/chromium/content/renderer/scoped_clipboard_writer_glue.cc b/chromium/content/renderer/scoped_clipboard_writer_glue.cc
index 4403952b3a4..37790375303 100644
--- a/chromium/content/renderer/scoped_clipboard_writer_glue.cc
+++ b/chromium/content/renderer/scoped_clipboard_writer_glue.cc
@@ -9,7 +9,7 @@ namespace content {
ScopedClipboardWriterGlue::ScopedClipboardWriterGlue(ClipboardClient* client)
: ui::ScopedClipboardWriter(client->GetClipboard(),
- ui::Clipboard::BUFFER_STANDARD),
+ ui::CLIPBOARD_TYPE_COPY_PASTE),
context_(client->CreateWriteContext()) {
// We should never have an instance where both are set.
DCHECK((clipboard_ && !context_.get()) ||
@@ -27,7 +27,7 @@ void ScopedClipboardWriterGlue::WriteBitmapFromPixels(const void* pixels,
if (context_) {
context_->WriteBitmapFromPixels(&objects_, pixels, size);
} else {
- ScopedClipboardWriter::WriteBitmapFromPixels(pixels, size);
+ NOTREACHED();
}
}
diff --git a/chromium/content/renderer/service_worker/OWNERS b/chromium/content/renderer/service_worker/OWNERS
new file mode 100644
index 00000000000..633b8a4fd96
--- /dev/null
+++ b/chromium/content/renderer/service_worker/OWNERS
@@ -0,0 +1,3 @@
+alecflett@chromium.org
+kinuko@chromium.org
+michaeln@chromium.org
diff --git a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc
new file mode 100644
index 00000000000..0aa4ab2d820
--- /dev/null
+++ b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc
@@ -0,0 +1,94 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/service_worker/embedded_worker_dispatcher.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/child/child_process.h"
+#include "content/child/scoped_child_process_reference.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/common/service_worker_messages.h"
+#include "content/renderer/render_thread_impl.h"
+#include "content/renderer/service_worker/service_worker_context_client.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/web/WebEmbeddedWorker.h"
+#include "third_party/WebKit/public/web/WebEmbeddedWorkerStartData.h"
+#include "webkit/child/worker_task_runner.h"
+#include "webkit/common/user_agent/user_agent.h"
+
+namespace content {
+
+// A thin wrapper of WebEmbeddedWorker which also adds and releases process
+// references automatically.
+class EmbeddedWorkerDispatcher::WorkerWrapper {
+ public:
+ explicit WorkerWrapper(blink::WebEmbeddedWorker* worker) : worker_(worker) {}
+ ~WorkerWrapper() {}
+
+ blink::WebEmbeddedWorker* worker() { return worker_.get(); }
+
+ private:
+ ScopedChildProcessReference process_ref_;
+ scoped_ptr<blink::WebEmbeddedWorker> worker_;
+};
+
+EmbeddedWorkerDispatcher::EmbeddedWorkerDispatcher() : weak_factory_(this) {}
+
+EmbeddedWorkerDispatcher::~EmbeddedWorkerDispatcher() {}
+
+bool EmbeddedWorkerDispatcher::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerDispatcher, message)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_StartWorker, OnStartWorker)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_TerminateWorker, OnTerminateWorker)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void EmbeddedWorkerDispatcher::WorkerContextDestroyed(
+ int embedded_worker_id) {
+ workers_.Remove(embedded_worker_id);
+}
+
+void EmbeddedWorkerDispatcher::OnStartWorker(
+ int embedded_worker_id,
+ int64 service_worker_version_id,
+ const GURL& script_url) {
+ DCHECK(!workers_.Lookup(embedded_worker_id));
+ scoped_ptr<WorkerWrapper> wrapper(new WorkerWrapper(
+ blink::WebEmbeddedWorker::create(
+ new ServiceWorkerContextClient(
+ embedded_worker_id,
+ service_worker_version_id,
+ script_url),
+ NULL)));
+
+ blink::WebEmbeddedWorkerStartData start_data;
+ start_data.scriptURL = script_url;
+ start_data.userAgent =
+ base::UTF8ToUTF16(webkit_glue::GetUserAgent(script_url));
+
+ wrapper->worker()->startWorkerContext(start_data);
+ workers_.AddWithID(wrapper.release(), embedded_worker_id);
+}
+
+void EmbeddedWorkerDispatcher::OnTerminateWorker(int embedded_worker_id) {
+ WorkerWrapper* wrapper = workers_.Lookup(embedded_worker_id);
+ if (!wrapper) {
+ LOG(WARNING) << "Got OnTerminateWorker for nonexistent worker";
+ return;
+ }
+
+ // This should eventually call WorkerContextDestroyed. (We may need to post
+ // a delayed task to forcibly abort the worker context if we find it
+ // necessary)
+ wrapper->worker()->terminateWorkerContext();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h
new file mode 100644
index 00000000000..d4dd6626c5a
--- /dev/null
+++ b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h
@@ -0,0 +1,49 @@
+// 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_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_
+#define CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_
+
+#include "base/basictypes.h"
+#include "base/id_map.h"
+#include "base/memory/weak_ptr.h"
+#include "ipc/ipc_listener.h"
+
+struct ServiceWorkerMsg_StartWorker_Params;
+class GURL;
+
+namespace WebKit {
+class WebEmbeddedWorker;
+}
+
+namespace content {
+
+// A tiny dispatcher which handles embedded worker start/stop messages.
+class EmbeddedWorkerDispatcher : public IPC::Listener {
+ public:
+ EmbeddedWorkerDispatcher();
+ virtual ~EmbeddedWorkerDispatcher();
+
+ // IPC::Listener overrides.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ void WorkerContextDestroyed(int embedded_worker_id);
+
+ private:
+ class WorkerWrapper;
+
+ void OnStartWorker(int embedded_worker_id,
+ int64 service_worker_version_id,
+ const GURL& script_url);
+ void OnTerminateWorker(int embedded_worker_id);
+
+ IDMap<WorkerWrapper, IDMapOwnPointer> workers_;
+ base::WeakPtrFactory<EmbeddedWorkerDispatcher> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.cc b/chromium/content/renderer/service_worker/service_worker_context_client.cc
new file mode 100644
index 00000000000..412ed674800
--- /dev/null
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.cc
@@ -0,0 +1,98 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/service_worker/service_worker_context_client.h"
+
+#include "base/lazy_instance.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/pickle.h"
+#include "base/threading/thread_local.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/renderer/render_thread_impl.h"
+#include "content/renderer/service_worker/embedded_worker_dispatcher.h"
+#include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "webkit/child/worker_task_runner.h"
+
+using webkit_glue::WorkerTaskRunner;
+
+namespace content {
+
+namespace {
+
+// For now client must be a per-thread instance.
+// TODO(kinuko): This needs to be refactored when we start using thread pool
+// or having multiple clients per one thread.
+base::LazyInstance<base::ThreadLocalPointer<ServiceWorkerContextClient> >::
+ Leaky g_worker_client_tls = LAZY_INSTANCE_INITIALIZER;
+
+void CallWorkerContextDestroyedOnMainThread(int embedded_worker_id) {
+ if (!RenderThreadImpl::current() ||
+ !RenderThreadImpl::current()->embedded_worker_dispatcher())
+ return;
+ RenderThreadImpl::current()->embedded_worker_dispatcher()->
+ WorkerContextDestroyed(embedded_worker_id);
+}
+
+} // namespace
+
+ServiceWorkerContextClient*
+ServiceWorkerContextClient::ThreadSpecificInstance() {
+ return g_worker_client_tls.Pointer()->Get();
+}
+
+ServiceWorkerContextClient::ServiceWorkerContextClient(
+ int embedded_worker_id,
+ int64 service_worker_version_id,
+ const GURL& script_url)
+ : embedded_worker_id_(embedded_worker_id),
+ service_worker_version_id_(service_worker_version_id),
+ script_url_(script_url),
+ sender_(ChildThread::current()->thread_safe_sender()),
+ main_thread_proxy_(base::MessageLoopProxy::current()),
+ proxy_(NULL) {
+}
+
+ServiceWorkerContextClient::~ServiceWorkerContextClient() {
+ DCHECK(g_worker_client_tls.Pointer()->Get() != NULL);
+ g_worker_client_tls.Pointer()->Set(NULL);
+}
+
+bool ServiceWorkerContextClient::OnMessageReceived(
+ const IPC::Message& msg) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void ServiceWorkerContextClient::workerContextFailedToStart()
+{
+ DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
+ DCHECK(!proxy_);
+
+ RenderThreadImpl::current()->embedded_worker_dispatcher()->
+ WorkerContextDestroyed(embedded_worker_id_);
+}
+
+void ServiceWorkerContextClient::workerContextStarted(
+ blink::WebServiceWorkerContextProxy* proxy) {
+ DCHECK_NE(0, WorkerTaskRunner::Instance()->CurrentWorkerId());
+ DCHECK(g_worker_client_tls.Pointer()->Get() == NULL);
+ g_worker_client_tls.Pointer()->Set(this);
+ proxy_ = proxy;
+
+ // TODO(kinuko): Send WorkerStarted message to the browser with the
+ // current thread ID so that the browser can start sending embedded worker
+ // messages directly to this client.
+}
+
+void ServiceWorkerContextClient::workerContextDestroyed() {
+ DCHECK_NE(0, WorkerTaskRunner::Instance()->CurrentWorkerId());
+ proxy_ = NULL;
+ main_thread_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&CallWorkerContextDestroyedOnMainThread,
+ embedded_worker_id_));
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.h b/chromium/content/renderer/service_worker/service_worker_context_client.h
new file mode 100644
index 00000000000..e59cc62a84a
--- /dev/null
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.h
@@ -0,0 +1,63 @@
+// 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_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_
+#define CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/strings/string16.h"
+#include "ipc/ipc_listener.h"
+#include "third_party/WebKit/public/web/WebServiceWorkerContextClient.h"
+#include "url/gurl.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace content {
+
+class ThreadSafeSender;
+
+// This class provides access to/from an embedded worker's WorkerGlobalScope.
+// All methods other than the constructor (it's created on the main thread)
+// are called on the worker thread.
+class ServiceWorkerContextClient
+ : public blink::WebServiceWorkerContextClient {
+ public:
+ // Returns a thread-specific client instance. This does NOT create a
+ // new instance.
+ static ServiceWorkerContextClient* ThreadSpecificInstance();
+
+ ServiceWorkerContextClient(int embedded_worker_id,
+ int64 service_worker_version_id,
+ const GURL& script_url);
+
+ virtual ~ServiceWorkerContextClient();
+
+ bool OnMessageReceived(const IPC::Message& msg);
+
+ // WebServiceWorkerContextClient overrides.
+ virtual void workerContextFailedToStart();
+ virtual void workerContextStarted(blink::WebServiceWorkerContextProxy* proxy);
+ virtual void workerContextDestroyed();
+
+ // TODO: Implement DevTools related method overrides.
+
+ int embedded_worker_id() const { return embedded_worker_id_; }
+
+ private:
+ const int embedded_worker_id_;
+ const int64 service_worker_version_id_;
+ const GURL script_url_;
+ scoped_refptr<ThreadSafeSender> sender_;
+ scoped_refptr<base::MessageLoopProxy> main_thread_proxy_;
+
+ blink::WebServiceWorkerContextProxy* proxy_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_
diff --git a/chromium/content/renderer/shared_worker_repository.cc b/chromium/content/renderer/shared_worker_repository.cc
new file mode 100644
index 00000000000..1ccc9e82002
--- /dev/null
+++ b/chromium/content/renderer/shared_worker_repository.cc
@@ -0,0 +1,58 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/shared_worker_repository.h"
+
+#include "content/child/child_thread.h"
+#include "content/common/view_messages.h"
+#include "content/renderer/render_view_impl.h"
+#include "content/renderer/websharedworker_proxy.h"
+#include "third_party/WebKit/public/web/WebView.h"
+
+namespace content {
+
+SharedWorkerRepository::SharedWorkerRepository(RenderViewImpl* render_view)
+ : RenderViewObserver(render_view) {
+ render_view->GetWebView()->setSharedWorkerRepositoryClient(this);
+}
+
+SharedWorkerRepository::~SharedWorkerRepository() {}
+
+blink::WebSharedWorkerConnector*
+SharedWorkerRepository::createSharedWorkerConnector(
+ const blink::WebURL& url,
+ const blink::WebString& name,
+ DocumentID document_id) {
+ int route_id = MSG_ROUTING_NONE;
+ bool exists = false;
+ bool url_mismatch = false;
+ ViewHostMsg_CreateWorker_Params params;
+ params.url = url;
+ params.name = name;
+ params.document_id = document_id;
+ params.render_view_route_id = render_view()->GetRoutingID();
+ params.route_id = MSG_ROUTING_NONE;
+ params.script_resource_appcache_id = 0;
+ Send(new ViewHostMsg_LookupSharedWorker(
+ params, &exists, &route_id, &url_mismatch));
+ if (url_mismatch)
+ return NULL;
+ documents_with_workers_.insert(document_id);
+ return new WebSharedWorkerProxy(ChildThread::current(),
+ document_id,
+ exists,
+ route_id,
+ render_view()->GetRoutingID());
+}
+
+void SharedWorkerRepository::documentDetached(DocumentID document) {
+ std::set<DocumentID>::iterator iter = documents_with_workers_.find(document);
+ if (iter != documents_with_workers_.end()) {
+ // Notify the browser process that the document has shut down.
+ Send(new ViewHostMsg_DocumentDetached(document));
+ documents_with_workers_.erase(iter);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/shared_worker_repository.h b/chromium/content/renderer/shared_worker_repository.h
new file mode 100644
index 00000000000..ce3b53c4978
--- /dev/null
+++ b/chromium/content/renderer/shared_worker_repository.h
@@ -0,0 +1,39 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_SHARED_WORKER_REPOSITORY_H_
+#define CONTENT_RENDERER_SHARED_WORKER_REPOSITORY_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "content/public/renderer/render_view_observer.h"
+#include "third_party/WebKit/public/web/WebSharedWorkerRepositoryClient.h"
+
+namespace content {
+
+class RenderViewImpl;
+
+class SharedWorkerRepository : public RenderViewObserver,
+ public blink::WebSharedWorkerRepositoryClient {
+ public:
+ explicit SharedWorkerRepository(RenderViewImpl* render_view);
+ virtual ~SharedWorkerRepository();
+
+ // WebSharedWorkerRepositoryClient overrides.
+ virtual blink::WebSharedWorkerConnector* createSharedWorkerConnector(
+ const blink::WebURL& url,
+ const blink::WebString& name,
+ DocumentID document_id) OVERRIDE;
+ virtual void documentDetached(DocumentID document_id) OVERRIDE;
+
+ private:
+ std::set<DocumentID> documents_with_workers_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharedWorkerRepository);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SHARED_WORKER_REPOSITORY_H_
diff --git a/chromium/content/renderer/skia_benchmarking_extension.cc b/chromium/content/renderer/skia_benchmarking_extension.cc
index 3890e985c9d..d19dd62c854 100644
--- a/chromium/content/renderer/skia_benchmarking_extension.cc
+++ b/chromium/content/renderer/skia_benchmarking_extension.cc
@@ -24,28 +24,31 @@
#include "ui/gfx/skia_util.h"
#include "v8/include/v8.h"
-using WebKit::WebFrame;
+using blink::WebFrame;
namespace {
const char kSkiaBenchmarkingExtensionName[] = "v8/SkiaBenchmarking";
-static scoped_ptr<base::Value> ParsePictureArg(v8::Handle<v8::Value> arg) {
+static scoped_ptr<base::Value> ParsePictureArg(v8::Isolate* isolate,
+ v8::Handle<v8::Value> arg) {
scoped_ptr<content::V8ValueConverter> converter(
content::V8ValueConverter::create());
return scoped_ptr<base::Value>(
- converter->FromV8Value(arg, v8::Context::GetCurrent()));
+ converter->FromV8Value(arg, isolate->GetCurrentContext()));
}
-static scoped_refptr<cc::Picture> ParsePictureStr(v8::Handle<v8::Value> arg) {
- scoped_ptr<base::Value> picture_value = ParsePictureArg(arg);
+static scoped_refptr<cc::Picture> ParsePictureStr(v8::Isolate* isolate,
+ v8::Handle<v8::Value> arg) {
+ scoped_ptr<base::Value> picture_value = ParsePictureArg(isolate, arg);
if (!picture_value)
return NULL;
return cc::Picture::CreateFromSkpValue(picture_value.get());
}
-static scoped_refptr<cc::Picture> ParsePictureHash(v8::Handle<v8::Value> arg) {
- scoped_ptr<base::Value> picture_value = ParsePictureArg(arg);
+static scoped_refptr<cc::Picture> ParsePictureHash(v8::Isolate* isolate,
+ v8::Handle<v8::Value> arg) {
+ scoped_ptr<base::Value> picture_value = ParsePictureArg(isolate, arg);
if (!picture_value)
return NULL;
return cc::Picture::CreateFromValue(picture_value.get());
@@ -118,16 +121,17 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
content::SkiaBenchmarkingExtension::InitSkGraphics();
}
- virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
+ v8::Isolate* isolate,
v8::Handle<v8::String> name) OVERRIDE {
- if (name->Equals(v8::String::New("Rasterize")))
- return v8::FunctionTemplate::New(Rasterize);
- if (name->Equals(v8::String::New("GetOps")))
- return v8::FunctionTemplate::New(GetOps);
- if (name->Equals(v8::String::New("GetOpTimings")))
- return v8::FunctionTemplate::New(GetOpTimings);
- if (name->Equals(v8::String::New("GetInfo")))
- return v8::FunctionTemplate::New(GetInfo);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "Rasterize")))
+ return v8::FunctionTemplate::New(isolate, Rasterize);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "GetOps")))
+ return v8::FunctionTemplate::New(isolate, GetOps);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "GetOpTimings")))
+ return v8::FunctionTemplate::New(isolate, GetOpTimings);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "GetInfo")))
+ return v8::FunctionTemplate::New(isolate, GetInfo);
return v8::Handle<v8::FunctionTemplate>();
}
@@ -136,7 +140,8 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
if (args.Length() < 1)
return;
- scoped_refptr<cc::Picture> picture = ParsePictureHash(args[0]);
+ v8::Isolate* isolate = args.GetIsolate();
+ scoped_refptr<cc::Picture> picture = ParsePictureHash(isolate, args[0]);
if (!picture.get())
return;
@@ -149,7 +154,7 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
scoped_ptr<content::V8ValueConverter> converter(
content::V8ValueConverter::create());
scoped_ptr<base::Value> params_value(
- converter->FromV8Value(args[1], v8::Context::GetCurrent()));
+ converter->FromV8Value(args[1], isolate->GetCurrentContext()));
const base::DictionaryValue* params_dict = NULL;
if (params_value.get() && params_value->GetAsDictionary(&params_dict)) {
@@ -195,13 +200,15 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
// Raster the requested command subset into the bitmap-backed canvas.
int last_index = debug_canvas.getSize() - 1;
- debug_canvas.setOverdrawViz(overdraw);
- debug_canvas.drawTo(&canvas, stop_index < 0
- ? last_index
- : std::min(last_index, stop_index));
+ if (last_index >= 0) {
+ debug_canvas.setOverdrawViz(overdraw);
+ debug_canvas.drawTo(&canvas, stop_index < 0
+ ? last_index
+ : std::min(last_index, stop_index));
+ }
- WebKit::WebArrayBuffer buffer =
- WebKit::WebArrayBuffer::create(bitmap.getSize(), 1);
+ blink::WebArrayBuffer buffer =
+ blink::WebArrayBuffer::create(bitmap.getSize(), 1);
uint32* packed_pixels = reinterpret_cast<uint32*>(bitmap.getPixels());
uint8* buffer_pixels = reinterpret_cast<uint8*>(buffer.data());
// Swizzle from native Skia format to RGBA as we copy out.
@@ -214,11 +221,11 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
}
v8::Handle<v8::Object> result = v8::Object::New();
- result->Set(v8::String::New("width"),
+ result->Set(v8::String::NewFromUtf8(isolate, "width"),
v8::Number::New(snapped_clip.width()));
- result->Set(v8::String::New("height"),
+ result->Set(v8::String::NewFromUtf8(isolate, "height"),
v8::Number::New(snapped_clip.height()));
- result->Set(v8::String::New("data"), buffer.toV8Value());
+ result->Set(v8::String::NewFromUtf8(isolate, "data"), buffer.toV8Value());
args.GetReturnValue().Set(result);
}
@@ -227,7 +234,8 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
if (args.Length() != 1)
return;
- scoped_refptr<cc::Picture> picture = ParsePictureHash(args[0]);
+ v8::Isolate* isolate = args.GetIsolate();
+ scoped_refptr<cc::Picture> picture = ParsePictureHash(isolate, args[0]);
if (!picture.get())
return;
@@ -235,25 +243,27 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
SkDebugCanvas canvas(bounds.width(), bounds.height());
picture->Replay(&canvas);
- v8::Local<v8::Array> result = v8::Array::New(canvas.getSize());
+ v8::Local<v8::Array> result = v8::Array::New(isolate, canvas.getSize());
for (int i = 0; i < canvas.getSize(); ++i) {
DrawType cmd_type = canvas.getDrawCommandAt(i)->getType();
v8::Handle<v8::Object> cmd = v8::Object::New();
- cmd->Set(v8::String::New("cmd_type"), v8::Integer::New(cmd_type));
- cmd->Set(v8::String::New("cmd_string"), v8::String::New(
- SkDrawCommand::GetCommandString(cmd_type)));
+ cmd->Set(v8::String::NewFromUtf8(isolate, "cmd_type"),
+ v8::Integer::New(isolate, cmd_type));
+ cmd->Set(v8::String::NewFromUtf8(isolate, "cmd_string"),
+ v8::String::NewFromUtf8(
+ isolate, SkDrawCommand::GetCommandString(cmd_type)));
SkTDArray<SkString*>* info = canvas.getCommandInfo(i);
DCHECK(info);
- v8::Local<v8::Array> v8_info = v8::Array::New(info->count());
+ v8::Local<v8::Array> v8_info = v8::Array::New(isolate, info->count());
for (int j = 0; j < info->count(); ++j) {
const SkString* info_str = (*info)[j];
DCHECK(info_str);
- v8_info->Set(j, v8::String::New(info_str->c_str()));
+ v8_info->Set(j, v8::String::NewFromUtf8(isolate, info_str->c_str()));
}
- cmd->Set(v8::String::New("info"), v8_info);
+ cmd->Set(v8::String::NewFromUtf8(isolate, "info"), v8_info);
result->Set(i, cmd);
}
@@ -265,7 +275,8 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
if (args.Length() != 1)
return;
- scoped_refptr<cc::Picture> picture = ParsePictureHash(args[0]);
+ v8::Isolate* isolate = args.GetIsolate();
+ scoped_refptr<cc::Picture> picture = ParsePictureHash(isolate, args[0]);
if (!picture.get())
return;
@@ -287,14 +298,14 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
picture->Replay(&benchmarking_canvas);
v8::Local<v8::Array> op_times =
- v8::Array::New(benchmarking_canvas.CommandCount());
+ v8::Array::New(isolate, benchmarking_canvas.CommandCount());
for (size_t i = 0; i < benchmarking_canvas.CommandCount(); ++i)
op_times->Set(i, v8::Number::New(benchmarking_canvas.GetTime(i)));
- v8::Handle<v8::Object> result = v8::Object::New();
- result->Set(v8::String::New("total_time"),
+ v8::Handle<v8::Object> result = v8::Object::New(isolate);
+ result->Set(v8::String::NewFromUtf8(isolate, "total_time"),
v8::Number::New(total_time.InMillisecondsF()));
- result->Set(v8::String::New("cmd_times"), op_times);
+ result->Set(v8::String::NewFromUtf8(isolate, "cmd_times"), op_times);
args.GetReturnValue().Set(result);
}
@@ -303,14 +314,15 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
if (args.Length() != 1)
return;
- scoped_refptr<cc::Picture> picture = ParsePictureStr(args[0]);
+ v8::Isolate* isolate = args.GetIsolate();
+ scoped_refptr<cc::Picture> picture = ParsePictureStr(isolate, args[0]);
if (!picture.get())
return;
- v8::Handle<v8::Object> result = v8::Object::New();
- result->Set(v8::String::New("width"),
+ v8::Handle<v8::Object> result = v8::Object::New(isolate);
+ result->Set(v8::String::NewFromUtf8(isolate, "width"),
v8::Number::New(picture->LayerRect().width()));
- result->Set(v8::String::New("height"),
+ result->Set(v8::String::NewFromUtf8(isolate, "height"),
v8::Number::New(picture->LayerRect().height()));
args.GetReturnValue().Set(result);
diff --git a/chromium/content/renderer/speech_recognition_dispatcher.cc b/chromium/content/renderer/speech_recognition_dispatcher.cc
index cf7c2fec286..1ac22371017 100644
--- a/chromium/content/renderer/speech_recognition_dispatcher.cc
+++ b/chromium/content/renderer/speech_recognition_dispatcher.cc
@@ -15,13 +15,13 @@
#include "third_party/WebKit/public/web/WebSpeechRecognitionResult.h"
#include "third_party/WebKit/public/web/WebSpeechRecognizerClient.h"
-using WebKit::WebVector;
-using WebKit::WebString;
-using WebKit::WebSpeechGrammar;
-using WebKit::WebSpeechRecognitionHandle;
-using WebKit::WebSpeechRecognitionResult;
-using WebKit::WebSpeechRecognitionParams;
-using WebKit::WebSpeechRecognizerClient;
+using blink::WebVector;
+using blink::WebString;
+using blink::WebSpeechGrammar;
+using blink::WebSpeechRecognitionHandle;
+using blink::WebSpeechRecognitionResult;
+using blink::WebSpeechRecognitionParams;
+using blink::WebSpeechRecognizerClient;
namespace content {
diff --git a/chromium/content/renderer/speech_recognition_dispatcher.h b/chromium/content/renderer/speech_recognition_dispatcher.h
index bffb0c8a1a9..297f174da12 100644
--- a/chromium/content/renderer/speech_recognition_dispatcher.h
+++ b/chromium/content/renderer/speech_recognition_dispatcher.h
@@ -23,7 +23,7 @@ struct SpeechRecognitionResult;
// scripted JS speech APIs. It's the complement of
// SpeechRecognitionDispatcherHost (owned by RenderViewHost).
class SpeechRecognitionDispatcher : public RenderViewObserver,
- public WebKit::WebSpeechRecognizer {
+ public blink::WebSpeechRecognizer {
public:
explicit SpeechRecognitionDispatcher(RenderViewImpl* render_view);
virtual ~SpeechRecognitionDispatcher();
@@ -32,14 +32,14 @@ class SpeechRecognitionDispatcher : public RenderViewObserver,
// RenderViewObserver implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- // WebKit::WebSpeechRecognizer implementation.
- virtual void start(const WebKit::WebSpeechRecognitionHandle&,
- const WebKit::WebSpeechRecognitionParams&,
- WebKit::WebSpeechRecognizerClient*) OVERRIDE;
- virtual void stop(const WebKit::WebSpeechRecognitionHandle&,
- WebKit::WebSpeechRecognizerClient*) OVERRIDE;
- virtual void abort(const WebKit::WebSpeechRecognitionHandle&,
- WebKit::WebSpeechRecognizerClient*) OVERRIDE;
+ // blink::WebSpeechRecognizer implementation.
+ virtual void start(const blink::WebSpeechRecognitionHandle&,
+ const blink::WebSpeechRecognitionParams&,
+ blink::WebSpeechRecognizerClient*) OVERRIDE;
+ virtual void stop(const blink::WebSpeechRecognitionHandle&,
+ blink::WebSpeechRecognizerClient*) OVERRIDE;
+ virtual void abort(const blink::WebSpeechRecognitionHandle&,
+ blink::WebSpeechRecognizerClient*) OVERRIDE;
void OnRecognitionStarted(int request_id);
void OnAudioStarted(int request_id);
@@ -51,14 +51,14 @@ class SpeechRecognitionDispatcher : public RenderViewObserver,
void OnResultsRetrieved(int request_id,
const SpeechRecognitionResults& result);
- int GetOrCreateIDForHandle(const WebKit::WebSpeechRecognitionHandle& handle);
- bool HandleExists(const WebKit::WebSpeechRecognitionHandle& handle);
- const WebKit::WebSpeechRecognitionHandle& GetHandleFromID(int handle_id);
+ int GetOrCreateIDForHandle(const blink::WebSpeechRecognitionHandle& handle);
+ bool HandleExists(const blink::WebSpeechRecognitionHandle& handle);
+ const blink::WebSpeechRecognitionHandle& GetHandleFromID(int handle_id);
// The WebKit client class that we use to send events back to the JS world.
- WebKit::WebSpeechRecognizerClient* recognizer_client_;
+ blink::WebSpeechRecognizerClient* recognizer_client_;
- typedef std::map<int, WebKit::WebSpeechRecognitionHandle> HandleMap;
+ typedef std::map<int, blink::WebSpeechRecognitionHandle> HandleMap;
HandleMap handle_map_;
int next_id_;
diff --git a/chromium/content/renderer/stats_collection_controller.cc b/chromium/content/renderer/stats_collection_controller.cc
index f82a8c4fd56..af86c9ea0ef 100644
--- a/chromium/content/renderer/stats_collection_controller.cc
+++ b/chromium/content/renderer/stats_collection_controller.cc
@@ -4,30 +4,29 @@
#include "content/renderer/stats_collection_controller.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
#include "base/json/json_writer.h"
#include "base/metrics/histogram.h"
#include "base/metrics/statistics_recorder.h"
#include "base/strings/string_util.h"
#include "content/common/child_process_messages.h"
#include "content/renderer/render_view_impl.h"
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
+#include "gin/per_isolate_data.h"
#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebView.h"
-using webkit_glue::CppArgumentList;
-using webkit_glue::CppVariant;
-
namespace content {
namespace {
bool CurrentRenderViewImpl(RenderViewImpl** out) {
- WebKit::WebFrame* web_frame = WebKit::WebFrame::frameForCurrentContext();
+ blink::WebFrame* web_frame = blink::WebFrame::frameForCurrentContext();
if (!web_frame)
return false;
- WebKit::WebView* web_view = web_frame->view();
+ blink::WebView* web_view = web_frame->view();
if (!web_view)
return false;
@@ -50,110 +49,114 @@ bool CurrentRenderViewImpl(RenderViewImpl** out) {
// either value may be null if a web contents hasn't fully loaded.
// load_start_ms is represented as milliseconds since system boot.
void ConvertLoadTimeToJSON(
- const base::TimeTicks& load_start_time,
- const base::TimeTicks& load_stop_time,
+ const base::Time& load_start_time,
+ const base::Time& load_stop_time,
std::string *result) {
base::DictionaryValue item;
if (load_start_time.is_null()) {
- item.Set("load_start_ms", base::Value::CreateNullValue());
+ item.Set("load_start_ms", base::Value::CreateNullValue());
} else {
- // This code relies on an implementation detail of TimeTicks::Now() - that
- // its return value happens to coincide with the system uptime value in
- // microseconds, on Win/Mac/iOS/Linux/ChromeOS and Android. See comments
- // in base::SysInfo::Uptime().
item.SetDouble("load_start_ms", load_start_time.ToInternalValue() / 1000);
}
if (load_start_time.is_null() || load_stop_time.is_null()) {
item.Set("load_duration_ms", base::Value::CreateNullValue());
} else {
item.SetDouble("load_duration_ms",
- (load_stop_time - load_start_time).InMilliseconds());
+ (load_stop_time - load_start_time).InMillisecondsF());
}
base::JSONWriter::Write(&item, result);
}
} // namespace
-StatsCollectionController::StatsCollectionController()
- : sender_(NULL) {
- BindCallback("getHistogram",
- base::Bind(&StatsCollectionController::GetHistogram,
- base::Unretained(this)));
- BindCallback("getBrowserHistogram",
- base::Bind(&StatsCollectionController::GetBrowserHistogram,
- base::Unretained(this)));
- BindCallback("tabLoadTiming",
- base::Bind(
- &StatsCollectionController::GetTabLoadTiming,
- base::Unretained(this)));
-}
-
-void StatsCollectionController::GetHistogram(const CppArgumentList& args,
- CppVariant* result) {
- if (args.size() != 1) {
- result->SetNull();
+// static
+gin::WrapperInfo StatsCollectionController::kWrapperInfo = {
+ gin::kEmbedderNativeGin
+};
+
+// static
+void StatsCollectionController::Install(blink::WebFrame* frame) {
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
+ if (context.IsEmpty())
return;
+
+ v8::Context::Scope context_scope(context);
+
+ gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
+ if (data->GetObjectTemplate(&StatsCollectionController::kWrapperInfo)
+ .IsEmpty()) {
+ v8::Handle<v8::ObjectTemplate> templ =
+ gin::ObjectTemplateBuilder(isolate)
+ .SetMethod("getHistogram", &StatsCollectionController::GetHistogram)
+ .SetMethod("getBrowserHistogram",
+ &StatsCollectionController::GetBrowserHistogram)
+ .SetMethod("tabLoadTiming",
+ &StatsCollectionController::GetTabLoadTiming)
+ .Build();
+ templ->SetInternalFieldCount(gin::kNumberOfInternalFields);
+ data->SetObjectTemplate(&StatsCollectionController::kWrapperInfo, templ);
}
+
+ gin::Handle<StatsCollectionController> controller =
+ gin::CreateHandle(isolate, new StatsCollectionController());
+ v8::Handle<v8::Object> global = context->Global();
+ global->Set(gin::StringToV8(isolate, "statsCollectionController"),
+ controller.ToV8());
+}
+
+StatsCollectionController::StatsCollectionController() {}
+
+StatsCollectionController::~StatsCollectionController() {}
+
+std::string StatsCollectionController::GetHistogram(
+ const std::string& histogram_name) {
base::HistogramBase* histogram =
- base::StatisticsRecorder::FindHistogram(args[0].ToString());
+ base::StatisticsRecorder::FindHistogram(histogram_name);
std::string output;
if (!histogram) {
output = "{}";
} else {
histogram->WriteJSON(&output);
}
- result->Set(output);
+ return output;
}
-void StatsCollectionController::GetBrowserHistogram(const CppArgumentList& args,
- CppVariant* result) {
- if (args.size() != 1) {
- result->SetNull();
- return;
- }
-
- if (!sender_) {
+std::string StatsCollectionController::GetBrowserHistogram(
+ const std::string& histogram_name) {
+ RenderViewImpl *render_view_impl = NULL;
+ if (!CurrentRenderViewImpl(&render_view_impl)) {
NOTREACHED();
- result->SetNull();
- return;
+ return std::string();
}
std::string histogram_json;
- sender_->Send(new ChildProcessHostMsg_GetBrowserHistogram(
- args[0].ToString(), &histogram_json));
- result->Set(histogram_json);
+ render_view_impl->Send(new ChildProcessHostMsg_GetBrowserHistogram(
+ histogram_name, &histogram_json));
+ return histogram_json;
}
-void StatsCollectionController::GetTabLoadTiming(
- const CppArgumentList& args,
- CppVariant* result) {
- if (!sender_) {
- NOTREACHED();
- result->SetNull();
- return;
- }
-
+std::string StatsCollectionController::GetTabLoadTiming() {
RenderViewImpl *render_view_impl = NULL;
if (!CurrentRenderViewImpl(&render_view_impl)) {
NOTREACHED();
- result->SetNull();
- return;
+ return std::string();
}
StatsCollectionObserver* observer =
render_view_impl->GetStatsCollectionObserver();
if (!observer) {
NOTREACHED();
- result->SetNull();
- return;
+ return std::string();
}
std::string tab_timing_json;
ConvertLoadTimeToJSON(
observer->load_start_time(), observer->load_stop_time(),
&tab_timing_json);
- result->Set(tab_timing_json);
+ return tab_timing_json;
}
} // namespace content
diff --git a/chromium/content/renderer/stats_collection_controller.h b/chromium/content/renderer/stats_collection_controller.h
index 63175d830a9..c122972e41f 100644
--- a/chromium/content/renderer/stats_collection_controller.h
+++ b/chromium/content/renderer/stats_collection_controller.h
@@ -5,8 +5,12 @@
#ifndef CONTENT_RENDERER_STATS_COLLECTION_CONTROLLER_H_
#define CONTENT_RENDERER_STATS_COLLECTION_CONTROLLER_H_
-#include "ipc/ipc_sender.h"
-#include "webkit/renderer/cpp_bound_class.h"
+#include "base/basictypes.h"
+#include "gin/wrappable.h"
+
+namespace blink {
+class WebFrame;
+}
namespace content {
@@ -14,28 +18,28 @@ namespace content {
// functionality to read out statistics from the browser.
// Its use must be enabled specifically via the
// --enable-stats-collection-bindings command line flag.
-class StatsCollectionController : public webkit_glue::CppBoundClass {
+class StatsCollectionController
+ : public gin::Wrappable<StatsCollectionController> {
public:
- StatsCollectionController();
+ static gin::WrapperInfo kWrapperInfo;
- void set_message_sender(IPC::Sender* sender) {
- sender_ = sender;
- }
+ static void Install(blink::WebFrame* frame);
+
+ private:
+ StatsCollectionController();
+ virtual ~StatsCollectionController();
// Retrieves a histogram and returns a JSON representation of it.
- void GetHistogram(const webkit_glue::CppArgumentList& args,
- webkit_glue::CppVariant* result);
+ std::string GetHistogram(const std::string& histogram_name);
// Retrieves a histogram from the browser process and returns a JSON
// representation of it.
- void GetBrowserHistogram(const webkit_glue::CppArgumentList& args,
- webkit_glue::CppVariant* result);
+ std::string GetBrowserHistogram(const std::string& histogram_name);
// Returns JSON representation of tab timing information for the current tab.
- void GetTabLoadTiming(const webkit_glue::CppArgumentList& args,
- webkit_glue::CppVariant* result);
- private:
- IPC::Sender* sender_;
+ std::string GetTabLoadTiming();
+
+ DISALLOW_COPY_AND_ASSIGN(StatsCollectionController);
};
} // namespace content
diff --git a/chromium/content/renderer/stats_collection_observer.cc b/chromium/content/renderer/stats_collection_observer.cc
index 00211ff781d..4c4b911ec8c 100644
--- a/chromium/content/renderer/stats_collection_observer.cc
+++ b/chromium/content/renderer/stats_collection_observer.cc
@@ -18,12 +18,12 @@ StatsCollectionObserver::~StatsCollectionObserver() {
void StatsCollectionObserver::DidStartLoading() {
DCHECK(start_time_.is_null());
- start_time_ = base::TimeTicks::Now();
+ start_time_ = base::Time::Now();
}
void StatsCollectionObserver::DidStopLoading() {
DCHECK(stop_time_.is_null());
- stop_time_ = base::TimeTicks::Now();
+ stop_time_ = base::Time::Now();
// Stop observing so we don't get called again.
RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view());
diff --git a/chromium/content/renderer/stats_collection_observer.h b/chromium/content/renderer/stats_collection_observer.h
index 298226f07b8..2717fd943c5 100644
--- a/chromium/content/renderer/stats_collection_observer.h
+++ b/chromium/content/renderer/stats_collection_observer.h
@@ -25,12 +25,12 @@ class StatsCollectionObserver : public RenderViewObserver {
// Timing for the page load start and stop. These functions may return
// a null time value under various circumstances.
- const base::TimeTicks& load_start_time() { return start_time_; }
- const base::TimeTicks& load_stop_time() { return stop_time_; }
+ const base::Time& load_start_time() { return start_time_; }
+ const base::Time& load_stop_time() { return stop_time_; }
private:
- base::TimeTicks start_time_;
- base::TimeTicks stop_time_;
+ base::Time start_time_;
+ base::Time stop_time_;
DISALLOW_COPY_AND_ASSIGN(StatsCollectionObserver);
};
diff --git a/chromium/content/renderer/text_input_client_observer.cc b/chromium/content/renderer/text_input_client_observer.cc
index cec5e1ab76f..5ce95ff6093 100644
--- a/chromium/content/renderer/text_input_client_observer.cc
+++ b/chromium/content/renderer/text_input_client_observer.cc
@@ -6,6 +6,7 @@
#include "base/memory/scoped_ptr.h"
#include "content/common/text_input_client_messages.h"
+#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/render_view_impl.h"
#include "third_party/WebKit/public/platform/WebPoint.h"
#include "third_party/WebKit/public/platform/WebRect.h"
@@ -38,12 +39,12 @@ bool TextInputClientObserver::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-WebKit::WebView* TextInputClientObserver::webview() {
+blink::WebView* TextInputClientObserver::webview() {
return render_view()->GetWebView();
}
void TextInputClientObserver::OnCharacterIndexForPoint(gfx::Point point) {
- WebKit::WebPoint web_point(point);
+ blink::WebPoint web_point(point);
size_t index = webview()->focusedFrame()->characterIndexForPoint(web_point);
Send(new TextInputClientReplyMsg_GotCharacterIndexForPoint(routing_id(),
index));
@@ -52,12 +53,14 @@ void TextInputClientObserver::OnCharacterIndexForPoint(gfx::Point point) {
void TextInputClientObserver::OnFirstRectForCharacterRange(gfx::Range range) {
gfx::Rect rect;
#if defined(ENABLE_PLUGINS)
- if (!render_view_impl_->GetPepperCaretBounds(&rect))
+ if (render_view_impl_->focused_pepper_plugin()) {
+ rect = render_view_impl_->focused_pepper_plugin()->GetCaretBounds();
+ } else
#endif
{
- WebKit::WebFrame* frame = webview()->focusedFrame();
+ blink::WebFrame* frame = webview()->focusedFrame();
if (frame) {
- WebKit::WebRect web_rect;
+ blink::WebRect web_rect;
frame->firstRectForCharacterRange(range.start(), range.length(),
web_rect);
rect = web_rect;
@@ -69,9 +72,9 @@ void TextInputClientObserver::OnFirstRectForCharacterRange(gfx::Range range) {
void TextInputClientObserver::OnStringForRange(gfx::Range range) {
#if defined(OS_MACOSX)
NSAttributedString* string = nil;
- WebKit::WebFrame* frame = webview()->focusedFrame();
+ blink::WebFrame* frame = webview()->focusedFrame();
if (frame) {
- string = WebKit::WebSubstringUtil::attributedSubstringInRange(
+ string = blink::WebSubstringUtil::attributedSubstringInRange(
frame, range.start(), range.length());
}
scoped_ptr<const mac::AttributedStringCoder::EncodedString> encoded(
diff --git a/chromium/content/renderer/text_input_client_observer.h b/chromium/content/renderer/text_input_client_observer.h
index 4c8b9a6ba63..cd674188917 100644
--- a/chromium/content/renderer/text_input_client_observer.h
+++ b/chromium/content/renderer/text_input_client_observer.h
@@ -11,7 +11,7 @@
#include "ui/gfx/point.h"
#include "ui/gfx/range/range.h"
-namespace WebKit {
+namespace blink {
class WebView;
}
@@ -32,7 +32,7 @@ class TextInputClientObserver : public RenderViewObserver {
private:
// Returns the WebView of the RenderView.
- WebKit::WebView* webview();
+ blink::WebView* webview();
// IPC Message handlers:
void OnCharacterIndexForPoint(gfx::Point point);
diff --git a/chromium/content/renderer/v8_value_converter_impl.cc b/chromium/content/renderer/v8_value_converter_impl.cc
index ab2a6330442..0244c338e6b 100644
--- a/chromium/content/renderer/v8_value_converter_impl.cc
+++ b/chromium/content/renderer/v8_value_converter_impl.cc
@@ -115,8 +115,8 @@ void V8ValueConverterImpl::SetStrategy(Strategy* strategy) {
v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Value(
const base::Value* value, v8::Handle<v8::Context> context) const {
v8::Context::Scope context_scope(context);
- v8::HandleScope handle_scope(context->GetIsolate());
- return handle_scope.Close(ToV8ValueImpl(value));
+ v8::EscapableHandleScope handle_scope(context->GetIsolate());
+ return handle_scope.Escape(ToV8ValueImpl(context->GetIsolate(), value));
}
Value* V8ValueConverterImpl::FromV8Value(
@@ -125,64 +125,68 @@ Value* V8ValueConverterImpl::FromV8Value(
v8::Context::Scope context_scope(context);
v8::HandleScope handle_scope(context->GetIsolate());
FromV8ValueState state(avoid_identity_hash_for_testing_);
- return FromV8ValueImpl(val, &state);
+ return FromV8ValueImpl(val, &state, context->GetIsolate());
}
-v8::Handle<v8::Value> V8ValueConverterImpl::ToV8ValueImpl(
- const base::Value* value) const {
+v8::Local<v8::Value> V8ValueConverterImpl::ToV8ValueImpl(
+ v8::Isolate* isolate,
+ const base::Value* value) const {
CHECK(value);
switch (value->GetType()) {
case base::Value::TYPE_NULL:
- return v8::Null();
+ return v8::Null(isolate);
case base::Value::TYPE_BOOLEAN: {
bool val = false;
CHECK(value->GetAsBoolean(&val));
- return v8::Boolean::New(val);
+ return v8::Boolean::New(isolate, val);
}
case base::Value::TYPE_INTEGER: {
int val = 0;
CHECK(value->GetAsInteger(&val));
- return v8::Integer::New(val);
+ return v8::Integer::New(isolate, val);
}
case base::Value::TYPE_DOUBLE: {
double val = 0.0;
CHECK(value->GetAsDouble(&val));
- return v8::Number::New(val);
+ return v8::Number::New(isolate, val);
}
case base::Value::TYPE_STRING: {
std::string val;
CHECK(value->GetAsString(&val));
- return v8::String::New(val.c_str(), val.length());
+ return v8::String::NewFromUtf8(
+ isolate, val.c_str(), v8::String::kNormalString, val.length());
}
case base::Value::TYPE_LIST:
- return ToV8Array(static_cast<const base::ListValue*>(value));
+ return ToV8Array(isolate, static_cast<const base::ListValue*>(value));
case base::Value::TYPE_DICTIONARY:
- return ToV8Object(static_cast<const base::DictionaryValue*>(value));
+ return ToV8Object(isolate,
+ static_cast<const base::DictionaryValue*>(value));
case base::Value::TYPE_BINARY:
return ToArrayBuffer(static_cast<const base::BinaryValue*>(value));
default:
LOG(ERROR) << "Unexpected value type: " << value->GetType();
- return v8::Null();
+ return v8::Null(isolate);
}
}
v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Array(
+ v8::Isolate* isolate,
const base::ListValue* val) const {
- v8::Handle<v8::Array> result(v8::Array::New(val->GetSize()));
+ v8::Handle<v8::Array> result(v8::Array::New(isolate, val->GetSize()));
for (size_t i = 0; i < val->GetSize(); ++i) {
const base::Value* child = NULL;
CHECK(val->Get(i, &child));
- v8::Handle<v8::Value> child_v8 = ToV8ValueImpl(child);
+ v8::Handle<v8::Value> child_v8 = ToV8ValueImpl(isolate, child);
CHECK(!child_v8.IsEmpty());
v8::TryCatch try_catch;
@@ -195,17 +199,21 @@ v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Array(
}
v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Object(
+ v8::Isolate* isolate,
const base::DictionaryValue* val) const {
v8::Handle<v8::Object> result(v8::Object::New());
for (base::DictionaryValue::Iterator iter(*val);
!iter.IsAtEnd(); iter.Advance()) {
const std::string& key = iter.key();
- v8::Handle<v8::Value> child_v8 = ToV8ValueImpl(&iter.value());
+ v8::Handle<v8::Value> child_v8 = ToV8ValueImpl(isolate, &iter.value());
CHECK(!child_v8.IsEmpty());
v8::TryCatch try_catch;
- result->Set(v8::String::New(key.c_str(), key.length()), child_v8);
+ result->Set(
+ v8::String::NewFromUtf8(
+ isolate, key.c_str(), v8::String::kNormalString, key.length()),
+ child_v8);
if (try_catch.HasCaught()) {
LOG(ERROR) << "Setter for property " << key.c_str() << " threw an "
<< "exception.";
@@ -217,15 +225,16 @@ v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Object(
v8::Handle<v8::Value> V8ValueConverterImpl::ToArrayBuffer(
const base::BinaryValue* value) const {
- WebKit::WebArrayBuffer buffer =
- WebKit::WebArrayBuffer::create(value->GetSize(), 1);
+ blink::WebArrayBuffer buffer =
+ blink::WebArrayBuffer::create(value->GetSize(), 1);
memcpy(buffer.data(), value->GetBuffer(), value->GetSize());
return buffer.toV8Value();
}
Value* V8ValueConverterImpl::FromV8ValueImpl(
v8::Handle<v8::Value> val,
- FromV8ValueState* state) const {
+ FromV8ValueState* state,
+ v8::Isolate* isolate) const {
CHECK(!val.IsEmpty());
FromV8ValueState::Level state_level(state);
@@ -261,27 +270,27 @@ Value* V8ValueConverterImpl::FromV8ValueImpl(
if (!date_allowed_)
// JSON.stringify would convert this to a string, but an object is more
// consistent within this class.
- return FromV8Object(val->ToObject(), state);
+ return FromV8Object(val->ToObject(), state, isolate);
v8::Date* date = v8::Date::Cast(*val);
- return new base::FundamentalValue(date->NumberValue() / 1000.0);
+ return new base::FundamentalValue(date->ValueOf() / 1000.0);
}
if (val->IsRegExp()) {
if (!reg_exp_allowed_)
// JSON.stringify converts to an object.
- return FromV8Object(val->ToObject(), state);
+ return FromV8Object(val->ToObject(), state, isolate);
return new base::StringValue(*v8::String::Utf8Value(val->ToString()));
}
// v8::Value doesn't have a ToArray() method for some reason.
if (val->IsArray())
- return FromV8Array(val.As<v8::Array>(), state);
+ return FromV8Array(val.As<v8::Array>(), state, isolate);
if (val->IsFunction()) {
if (!function_allowed_)
// JSON.stringify refuses to convert function(){}.
return NULL;
- return FromV8Object(val->ToObject(), state);
+ return FromV8Object(val->ToObject(), state, isolate);
}
if (val->IsObject()) {
@@ -289,7 +298,7 @@ Value* V8ValueConverterImpl::FromV8ValueImpl(
if (binary_value) {
return binary_value;
} else {
- return FromV8Object(val->ToObject(), state);
+ return FromV8Object(val->ToObject(), state, isolate);
}
}
@@ -299,7 +308,8 @@ Value* V8ValueConverterImpl::FromV8ValueImpl(
base::Value* V8ValueConverterImpl::FromV8Array(
v8::Handle<v8::Array> val,
- FromV8ValueState* state) const {
+ FromV8ValueState* state,
+ v8::Isolate* isolate) const {
if (!state->UpdateAndCheckUniqueness(val))
return base::Value::CreateNullValue();
@@ -307,12 +317,12 @@ base::Value* V8ValueConverterImpl::FromV8Array(
// If val was created in a different context than our current one, change to
// that context, but change back after val is converted.
if (!val->CreationContext().IsEmpty() &&
- val->CreationContext() != v8::Context::GetCurrent())
+ val->CreationContext() != isolate->GetCurrentContext())
scope.reset(new v8::Context::Scope(val->CreationContext()));
if (strategy_) {
Value* out = NULL;
- if (strategy_->FromV8Array(val, &out))
+ if (strategy_->FromV8Array(val, &out, isolate))
return out;
}
@@ -324,13 +334,13 @@ base::Value* V8ValueConverterImpl::FromV8Array(
v8::Handle<v8::Value> child_v8 = val->Get(i);
if (try_catch.HasCaught()) {
LOG(ERROR) << "Getter for index " << i << " threw an exception.";
- child_v8 = v8::Null();
+ child_v8 = v8::Null(isolate);
}
if (!val->HasRealIndexedProperty(i))
continue;
- base::Value* child = FromV8ValueImpl(child_v8, state);
+ base::Value* child = FromV8ValueImpl(child_v8, state, isolate);
if (child)
result->Append(child);
else
@@ -346,14 +356,14 @@ base::BinaryValue* V8ValueConverterImpl::FromV8Buffer(
char* data = NULL;
size_t length = 0;
- scoped_ptr<WebKit::WebArrayBuffer> array_buffer(
- WebKit::WebArrayBuffer::createFromV8Value(val));
- scoped_ptr<WebKit::WebArrayBufferView> view;
+ scoped_ptr<blink::WebArrayBuffer> array_buffer(
+ blink::WebArrayBuffer::createFromV8Value(val));
+ scoped_ptr<blink::WebArrayBufferView> view;
if (array_buffer) {
data = reinterpret_cast<char*>(array_buffer->data());
length = array_buffer->byteLength();
} else {
- view.reset(WebKit::WebArrayBufferView::createFromV8Value(val));
+ view.reset(blink::WebArrayBufferView::createFromV8Value(val));
if (view) {
data = reinterpret_cast<char*>(view->baseAddress()) + view->byteOffset();
length = view->byteLength();
@@ -368,7 +378,8 @@ base::BinaryValue* V8ValueConverterImpl::FromV8Buffer(
base::Value* V8ValueConverterImpl::FromV8Object(
v8::Handle<v8::Object> val,
- FromV8ValueState* state) const {
+ FromV8ValueState* state,
+ v8::Isolate* isolate) const {
if (!state->UpdateAndCheckUniqueness(val))
return base::Value::CreateNullValue();
@@ -376,12 +387,12 @@ base::Value* V8ValueConverterImpl::FromV8Object(
// If val was created in a different context than our current one, change to
// that context, but change back after val is converted.
if (!val->CreationContext().IsEmpty() &&
- val->CreationContext() != v8::Context::GetCurrent())
+ val->CreationContext() != isolate->GetCurrentContext())
scope.reset(new v8::Context::Scope(val->CreationContext()));
if (strategy_) {
Value* out = NULL;
- if (strategy_->FromV8Object(val, &out))
+ if (strategy_->FromV8Object(val, &out, isolate))
return out;
}
@@ -407,7 +418,7 @@ base::Value* V8ValueConverterImpl::FromV8Object(
// Extend this test to cover more types as necessary and if sensible.
if (!key->IsString() &&
!key->IsNumber()) {
- NOTREACHED() << "Key \"" << *v8::String::AsciiValue(key) << "\" "
+ NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) << "\" "
"is neither a string nor a number";
continue;
}
@@ -420,10 +431,10 @@ base::Value* V8ValueConverterImpl::FromV8Object(
if (try_catch.HasCaught()) {
LOG(WARNING) << "Getter for property " << *name_utf8
<< " threw an exception.";
- child_v8 = v8::Null();
+ child_v8 = v8::Null(isolate);
}
- scoped_ptr<base::Value> child(FromV8ValueImpl(child_v8, state));
+ scoped_ptr<base::Value> child(FromV8ValueImpl(child_v8, state, isolate));
if (!child)
// JSON.stringify skips properties whose values don't serialize, for
// example undefined and functions. Emulate that behavior.
diff --git a/chromium/content/renderer/v8_value_converter_impl.h b/chromium/content/renderer/v8_value_converter_impl.h
index 20331648fab..b64b8d8f5e6 100644
--- a/chromium/content/renderer/v8_value_converter_impl.h
+++ b/chromium/content/renderer/v8_value_converter_impl.h
@@ -43,16 +43,21 @@ class CONTENT_EXPORT V8ValueConverterImpl : public V8ValueConverter {
class FromV8ValueState;
- v8::Handle<v8::Value> ToV8ValueImpl(const base::Value* value) const;
- v8::Handle<v8::Value> ToV8Array(const base::ListValue* list) const;
+ v8::Local<v8::Value> ToV8ValueImpl(v8::Isolate* isolate,
+ const base::Value* value) const;
+ v8::Handle<v8::Value> ToV8Array(v8::Isolate* isolate,
+ const base::ListValue* list) const;
v8::Handle<v8::Value> ToV8Object(
+ v8::Isolate* isolate,
const base::DictionaryValue* dictionary) const;
v8::Handle<v8::Value> ToArrayBuffer(const base::BinaryValue* value) const;
base::Value* FromV8ValueImpl(v8::Handle<v8::Value> value,
- FromV8ValueState* state) const;
+ FromV8ValueState* state,
+ v8::Isolate* isolate) const;
base::Value* FromV8Array(v8::Handle<v8::Array> array,
- FromV8ValueState* state) const;
+ FromV8ValueState* state,
+ v8::Isolate* isolate) const;
// This will convert objects of type ArrayBuffer or any of the
// ArrayBufferView subclasses. The return value will be NULL if |value| is
@@ -60,7 +65,8 @@ class CONTENT_EXPORT V8ValueConverterImpl : public V8ValueConverter {
base::BinaryValue* FromV8Buffer(v8::Handle<v8::Value> value) const;
base::Value* FromV8Object(v8::Handle<v8::Object> object,
- FromV8ValueState* state) const;
+ FromV8ValueState* state,
+ v8::Isolate* isolate) const;
// If true, we will convert Date JavaScript objects to doubles.
bool date_allowed_;
diff --git a/chromium/content/renderer/v8_value_converter_impl_unittest.cc b/chromium/content/renderer/v8_value_converter_impl_unittest.cc
index f762f934545..392dd0b0f13 100644
--- a/chromium/content/renderer/v8_value_converter_impl_unittest.cc
+++ b/chromium/content/renderer/v8_value_converter_impl_unittest.cc
@@ -58,7 +58,7 @@ class V8ValueConverterImplTest : public testing::Test {
}
virtual void TearDown() {
- context_.Dispose();
+ context_.Reset();
}
std::string GetString(base::DictionaryValue* value, const std::string& key) {
@@ -72,7 +72,8 @@ class V8ValueConverterImplTest : public testing::Test {
std::string GetString(v8::Handle<v8::Object> value, const std::string& key) {
v8::Handle<v8::String> temp =
- value->Get(v8::String::New(key.c_str())).As<v8::String>();
+ value->Get(v8::String::NewFromUtf8(isolate_, key.c_str()))
+ .As<v8::String>();
if (temp.IsEmpty()) {
ADD_FAILURE();
return std::string();
@@ -110,7 +111,8 @@ class V8ValueConverterImplTest : public testing::Test {
}
bool IsNull(v8::Handle<v8::Object> value, const std::string& key) {
- v8::Handle<v8::Value> child = value->Get(v8::String::New(key.c_str()));
+ v8::Handle<v8::Value> child =
+ value->Get(v8::String::NewFromUtf8(isolate_, key.c_str()));
if (child.IsEmpty()) {
ADD_FAILURE();
return false;
@@ -153,7 +155,7 @@ class V8ValueConverterImplTest : public testing::Test {
}
v8::Handle<v8::Object> object(v8::Object::New());
- object->Set(v8::String::New("test"), val);
+ object->Set(v8::String::NewFromUtf8(isolate_, "test"), val);
scoped_ptr<base::DictionaryValue> dictionary(
static_cast<base::DictionaryValue*>(
converter.FromV8Value(object, context)));
@@ -168,7 +170,7 @@ class V8ValueConverterImplTest : public testing::Test {
EXPECT_FALSE(dictionary->HasKey("test"));
}
- v8::Handle<v8::Array> array(v8::Array::New());
+ v8::Handle<v8::Array> array(v8::Array::New(isolate_));
array->Set(0, val);
scoped_ptr<base::ListValue> list(
static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
@@ -216,9 +218,9 @@ TEST_F(V8ValueConverterImplTest, BasicRoundTrip) {
"}");
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
V8ValueConverterImpl converter;
v8::Handle<v8::Object> v8_object =
@@ -227,21 +229,34 @@ TEST_F(V8ValueConverterImplTest, BasicRoundTrip) {
EXPECT_EQ(static_cast<const base::DictionaryValue&>(*original_root).size(),
v8_object->GetPropertyNames()->Length());
- EXPECT_TRUE(v8_object->Get(v8::String::New("null"))->IsNull());
- EXPECT_TRUE(v8_object->Get(v8::String::New("true"))->IsTrue());
- EXPECT_TRUE(v8_object->Get(v8::String::New("false"))->IsFalse());
- EXPECT_TRUE(v8_object->Get(v8::String::New("positive-int"))->IsInt32());
- EXPECT_TRUE(v8_object->Get(v8::String::New("negative-int"))->IsInt32());
- EXPECT_TRUE(v8_object->Get(v8::String::New("zero"))->IsInt32());
- EXPECT_TRUE(v8_object->Get(v8::String::New("double"))->IsNumber());
EXPECT_TRUE(
- v8_object->Get(v8::String::New("big-integral-double"))->IsNumber());
- EXPECT_TRUE(v8_object->Get(v8::String::New("string"))->IsString());
- EXPECT_TRUE(v8_object->Get(v8::String::New("empty-string"))->IsString());
- EXPECT_TRUE(v8_object->Get(v8::String::New("dictionary"))->IsObject());
- EXPECT_TRUE(v8_object->Get(v8::String::New("empty-dictionary"))->IsObject());
- EXPECT_TRUE(v8_object->Get(v8::String::New("list"))->IsArray());
- EXPECT_TRUE(v8_object->Get(v8::String::New("empty-list"))->IsArray());
+ v8_object->Get(v8::String::NewFromUtf8(isolate_, "null"))->IsNull());
+ EXPECT_TRUE(
+ v8_object->Get(v8::String::NewFromUtf8(isolate_, "true"))->IsTrue());
+ EXPECT_TRUE(
+ v8_object->Get(v8::String::NewFromUtf8(isolate_, "false"))->IsFalse());
+ EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "positive-int"))
+ ->IsInt32());
+ EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "negative-int"))
+ ->IsInt32());
+ EXPECT_TRUE(
+ v8_object->Get(v8::String::NewFromUtf8(isolate_, "zero"))->IsInt32());
+ EXPECT_TRUE(
+ v8_object->Get(v8::String::NewFromUtf8(isolate_, "double"))->IsNumber());
+ EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(
+ isolate_, "big-integral-double"))->IsNumber());
+ EXPECT_TRUE(
+ v8_object->Get(v8::String::NewFromUtf8(isolate_, "string"))->IsString());
+ EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "empty-string"))
+ ->IsString());
+ EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "dictionary"))
+ ->IsObject());
+ EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(
+ isolate_, "empty-dictionary"))->IsObject());
+ EXPECT_TRUE(
+ v8_object->Get(v8::String::NewFromUtf8(isolate_, "list"))->IsArray());
+ EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "empty-list"))
+ ->IsArray());
scoped_ptr<base::Value> new_root(converter.FromV8Value(v8_object, context));
EXPECT_NE(original_root.get(), new_root.get());
@@ -253,9 +268,9 @@ TEST_F(V8ValueConverterImplTest, KeysWithDots) {
base::test::ParseJson("{ \"foo.bar\": \"baz\" }");
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
V8ValueConverterImpl converter;
scoped_ptr<base::Value> copy(
@@ -267,9 +282,9 @@ TEST_F(V8ValueConverterImplTest, KeysWithDots) {
TEST_F(V8ValueConverterImplTest, ObjectExceptions) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
// Set up objects to throw when reading or writing 'foo'.
const char* source =
@@ -278,11 +293,13 @@ TEST_F(V8ValueConverterImplTest, ObjectExceptions) {
"Object.prototype.__defineGetter__('foo', "
" function() { throw new Error('muah!'); });";
- v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
+ v8::Handle<v8::Script> script(
+ v8::Script::New(v8::String::NewFromUtf8(isolate_, source)));
script->Run();
- v8::Handle<v8::Object> object(v8::Object::New());
- object->Set(v8::String::New("bar"), v8::String::New("bar"));
+ v8::Handle<v8::Object> object(v8::Object::New(isolate_));
+ object->Set(v8::String::NewFromUtf8(isolate_, "bar"),
+ v8::String::NewFromUtf8(isolate_, "bar"));
// Converting from v8 value should replace the foo property with null.
V8ValueConverterImpl converter;
@@ -307,9 +324,9 @@ TEST_F(V8ValueConverterImplTest, ObjectExceptions) {
TEST_F(V8ValueConverterImplTest, ArrayExceptions) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
const char* source = "(function() {"
"var arr = [];"
@@ -321,7 +338,8 @@ TEST_F(V8ValueConverterImplTest, ArrayExceptions) {
"return arr;"
"})();";
- v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
+ v8::Handle<v8::Script> script(
+ v8::Script::New(v8::String::NewFromUtf8(isolate_, source)));
v8::Handle<v8::Array> array = script->Run().As<v8::Array>();
ASSERT_FALSE(array.IsEmpty());
@@ -346,18 +364,20 @@ TEST_F(V8ValueConverterImplTest, ArrayExceptions) {
TEST_F(V8ValueConverterImplTest, WeirdTypes) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
+ v8::Local<v8::Context> context =
+ v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
- v8::Handle<v8::RegExp> regex(
- v8::RegExp::New(v8::String::New("."), v8::RegExp::kNone));
+ v8::Handle<v8::RegExp> regex(v8::RegExp::New(
+ v8::String::NewFromUtf8(isolate_, "."), v8::RegExp::kNone));
V8ValueConverterImpl converter;
TestWeirdType(converter,
- v8::Undefined(),
+ v8::Undefined(isolate_),
base::Value::TYPE_NULL, // Arbitrary type, result is NULL.
scoped_ptr<base::Value>());
TestWeirdType(converter,
- v8::Date::New(1000),
+ v8::Date::New(isolate_, 1000),
base::Value::TYPE_DICTIONARY,
scoped_ptr<base::Value>(new base::DictionaryValue()));
TestWeirdType(converter,
@@ -367,7 +387,7 @@ TEST_F(V8ValueConverterImplTest, WeirdTypes) {
converter.SetDateAllowed(true);
TestWeirdType(converter,
- v8::Date::New(1000),
+ v8::Date::New(isolate_, 1000),
base::Value::TYPE_DOUBLE,
scoped_ptr<base::Value>(new base::FundamentalValue(1.0)));
@@ -380,16 +400,17 @@ TEST_F(V8ValueConverterImplTest, WeirdTypes) {
TEST_F(V8ValueConverterImplTest, Prototype) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
const char* source = "(function() {"
"Object.prototype.foo = 'foo';"
"return {};"
"})();";
- v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
+ v8::Handle<v8::Script> script(
+ v8::Script::New(v8::String::NewFromUtf8(isolate_, source)));
v8::Handle<v8::Object> object = script->Run().As<v8::Object>();
ASSERT_FALSE(object.IsEmpty());
@@ -403,15 +424,16 @@ TEST_F(V8ValueConverterImplTest, Prototype) {
TEST_F(V8ValueConverterImplTest, StripNullFromObjects) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
const char* source = "(function() {"
"return { foo: undefined, bar: null };"
"})();";
- v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
+ v8::Handle<v8::Script> script(
+ v8::Script::New(v8::String::NewFromUtf8(isolate_, source)));
v8::Handle<v8::Object> object = script->Run().As<v8::Object>();
ASSERT_FALSE(object.IsEmpty());
@@ -427,16 +449,17 @@ TEST_F(V8ValueConverterImplTest, StripNullFromObjects) {
TEST_F(V8ValueConverterImplTest, RecursiveObjects) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
V8ValueConverterImpl converter;
v8::Handle<v8::Object> object = v8::Object::New().As<v8::Object>();
ASSERT_FALSE(object.IsEmpty());
- object->Set(v8::String::New("foo"), v8::String::New("bar"));
- object->Set(v8::String::New("obj"), object);
+ object->Set(v8::String::NewFromUtf8(isolate_, "foo"),
+ v8::String::NewFromUtf8(isolate_, "bar"));
+ object->Set(v8::String::NewFromUtf8(isolate_, "obj"), object);
scoped_ptr<base::DictionaryValue> object_result(
static_cast<base::DictionaryValue*>(
@@ -445,9 +468,9 @@ TEST_F(V8ValueConverterImplTest, RecursiveObjects) {
EXPECT_EQ(2u, object_result->size());
EXPECT_TRUE(IsNull(object_result.get(), "obj"));
- v8::Handle<v8::Array> array = v8::Array::New().As<v8::Array>();
+ v8::Handle<v8::Array> array = v8::Array::New(isolate_).As<v8::Array>();
ASSERT_FALSE(array.IsEmpty());
- array->Set(0, v8::String::New("1"));
+ array->Set(0, v8::String::NewFromUtf8(isolate_, "1"));
array->Set(1, array);
scoped_ptr<base::ListValue> list_result(
@@ -459,9 +482,9 @@ TEST_F(V8ValueConverterImplTest, RecursiveObjects) {
TEST_F(V8ValueConverterImplTest, WeirdProperties) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
const char* source = "(function() {"
"return {"
@@ -474,7 +497,8 @@ TEST_F(V8ValueConverterImplTest, WeirdProperties) {
"};"
"})();";
- v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
+ v8::Handle<v8::Script> script(
+ v8::Script::New(v8::String::NewFromUtf8(isolate_, source)));
v8::Handle<v8::Object> object = script->Run().As<v8::Object>();
ASSERT_FALSE(object.IsEmpty());
@@ -496,9 +520,9 @@ TEST_F(V8ValueConverterImplTest, WeirdProperties) {
TEST_F(V8ValueConverterImplTest, ArrayGetters) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
const char* source = "(function() {"
"var a = [0];"
@@ -506,7 +530,8 @@ TEST_F(V8ValueConverterImplTest, ArrayGetters) {
"return a;"
"})();";
- v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
+ v8::Handle<v8::Script> script(
+ v8::Script::New(v8::String::NewFromUtf8(isolate_, source)));
v8::Handle<v8::Array> array = script->Run().As<v8::Array>();
ASSERT_FALSE(array.IsEmpty());
@@ -519,16 +544,17 @@ TEST_F(V8ValueConverterImplTest, ArrayGetters) {
TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
v8::Handle<v8::Object> object;
{
const char* source = "(function() {"
"return { foo: undefined, bar: null, baz: function(){} };"
"})();";
- v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
+ v8::Handle<v8::Script> script(
+ v8::Script::New(v8::String::NewFromUtf8(isolate_, source)));
object = script->Run().As<v8::Object>();
ASSERT_FALSE(object.IsEmpty());
}
@@ -538,7 +564,8 @@ TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) {
const char* source = "(function() {"
"return [ undefined, null, function(){} ];"
"})();";
- v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source)));
+ v8::Handle<v8::Script> script(
+ v8::Script::New(v8::String::NewFromUtf8(isolate_, source)));
array = script->Run().As<v8::Array>();
ASSERT_FALSE(array.IsEmpty());
}
@@ -558,9 +585,9 @@ TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) {
TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
V8ValueConverterImpl converter;
// We check that the converter checks identity correctly by disabling the
@@ -568,11 +595,11 @@ TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) {
ScopedAvoidIdentityHashForTesting scoped_hash_avoider(&converter);
// Create the v8::Object to be converted.
- v8::Handle<v8::Array> root(v8::Array::New(4));
- root->Set(0, v8::Handle<v8::Object>(v8::Object::New()));
- root->Set(1, v8::Handle<v8::Object>(v8::Object::New()));
- root->Set(2, v8::Handle<v8::Object>(v8::Array::New(0)));
- root->Set(3, v8::Handle<v8::Object>(v8::Array::New(0)));
+ v8::Handle<v8::Array> root(v8::Array::New(isolate_, 4));
+ root->Set(0, v8::Handle<v8::Object>(v8::Object::New(isolate_)));
+ root->Set(1, v8::Handle<v8::Object>(v8::Object::New(isolate_)));
+ root->Set(2, v8::Handle<v8::Object>(v8::Array::New(isolate_, 0)));
+ root->Set(3, v8::Handle<v8::Object>(v8::Array::New(isolate_, 0)));
// The expected base::Value result.
scoped_ptr<base::Value> expected = base::test::ParseJson("[{},{},[],[]]");
@@ -587,13 +614,13 @@ TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) {
TEST_F(V8ValueConverterImplTest, DetectCycles) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
V8ValueConverterImpl converter;
// Create a recursive array.
- v8::Handle<v8::Array> recursive_array(v8::Array::New(1));
+ v8::Handle<v8::Array> recursive_array(v8::Array::New(isolate_, 1));
recursive_array->Set(0, recursive_array);
// The first repetition should be trimmed and replaced by a null value.
@@ -611,8 +638,10 @@ TEST_F(V8ValueConverterImplTest, DetectCycles) {
const std::string key("key");
v8::Handle<v8::Object> recursive_object(v8::Object::New());
v8::TryCatch try_catch;
- recursive_object->Set(v8::String::New(key.c_str(), key.length()),
- recursive_object);
+ recursive_object->Set(
+ v8::String::NewFromUtf8(
+ isolate_, key.c_str(), v8::String::kNormalString, key.length()),
+ recursive_object);
ASSERT_FALSE(try_catch.HasCaught());
// The first repetition should be trimmed and replaced by a null value.
@@ -629,9 +658,9 @@ TEST_F(V8ValueConverterImplTest, DetectCycles) {
TEST_F(V8ValueConverterImplTest, MaxRecursionDepth) {
v8::HandleScope handle_scope(isolate_);
- v8::Context::Scope context_scope(isolate_, context_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
// Must larger than kMaxRecursionDepth in v8_value_converter_impl.cc.
int kDepth = 1000;
@@ -642,7 +671,7 @@ TEST_F(V8ValueConverterImplTest, MaxRecursionDepth) {
v8::Local<v8::Object> leaf = deep_object;
for (int i = 0; i < kDepth; ++i) {
v8::Local<v8::Object> new_object = v8::Object::New();
- leaf->Set(v8::String::New(kKey), new_object);
+ leaf->Set(v8::String::NewFromUtf8(isolate_, kKey), new_object);
leaf = new_object;
}
diff --git a/chromium/content/renderer/web_preferences.cc b/chromium/content/renderer/web_preferences.cc
index ce14ce13e01..5a94512667e 100644
--- a/chromium/content/renderer/web_preferences.cc
+++ b/chromium/content/renderer/web_preferences.cc
@@ -16,18 +16,18 @@
#include "third_party/icu/source/common/unicode/uscript.h"
#include "webkit/common/webpreferences.h"
-using WebKit::WebNetworkStateNotifier;
-using WebKit::WebRuntimeFeatures;
-using WebKit::WebSettings;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebView;
+using blink::WebNetworkStateNotifier;
+using blink::WebRuntimeFeatures;
+using blink::WebSettings;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebView;
namespace content {
namespace {
-typedef void (*SetFontFamilyWrapper)(WebKit::WebSettings*,
+typedef void (*SetFontFamilyWrapper)(blink::WebSettings*,
const base::string16&,
UScriptCode);
@@ -146,14 +146,10 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) {
settings->setUsesEncodingDetector(prefs.uses_universal_detector);
settings->setTextAreasAreResizable(prefs.text_areas_are_resizable);
settings->setAllowScriptsToCloseWindows(prefs.allow_scripts_to_close_windows);
- if (prefs.user_style_sheet_enabled)
- settings->setUserStyleSheetLocation(prefs.user_style_sheet_location);
- else
- settings->setUserStyleSheetLocation(WebURL());
- settings->setAuthorAndUserStylesEnabled(prefs.author_and_user_styles_enabled);
settings->setDownloadableBinaryFontsEnabled(prefs.remote_fonts_enabled);
settings->setJavaScriptCanAccessClipboard(
prefs.javascript_can_access_clipboard);
+ WebRuntimeFeatures::enableXSLT(prefs.xslt_enabled);
settings->setXSSAuditorEnabled(prefs.xss_auditor_enabled);
settings->setDNSPrefetchingEnabled(prefs.dns_prefetching_enabled);
settings->setLocalStorageEnabled(prefs.local_storage_enabled);
@@ -216,6 +212,8 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) {
// Uses the mock theme engine for scrollbars.
settings->setMockScrollbarsEnabled(prefs.mock_scrollbars_enabled);
+ settings->setLayerSquashingEnabled(prefs.layer_squashing_enabled);
+
settings->setThreadedHTMLParser(prefs.threaded_html_parser);
// Display visualization of what has changed on the screen using an
@@ -236,6 +234,11 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) {
settings->setAntialiased2dCanvasEnabled(
!prefs.antialiased_2d_canvas_disabled);
+ // Set MSAA sample count for 2d canvas if requested on the command line (or
+ // default value if not).
+ settings->setAccelerated2dCanvasMSAASampleCount(
+ prefs.accelerated_2d_canvas_msaa_sample_count);
+
// Enable gpu-accelerated filters if requested on the command line.
settings->setAcceleratedFiltersEnabled(prefs.accelerated_filters_enabled);
@@ -285,15 +288,16 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) {
prefs.allow_running_insecure_content);
settings->setPasswordEchoEnabled(prefs.password_echo_enabled);
settings->setShouldPrintBackgrounds(prefs.should_print_backgrounds);
+ settings->setShouldClearDocumentBackground(
+ prefs.should_clear_document_background);
settings->setEnableScrollAnimator(prefs.enable_scroll_animator);
settings->setVisualWordMovementEnabled(prefs.visual_word_movement_enabled);
- settings->setCSSStickyPositionEnabled(prefs.css_sticky_position_enabled);
- settings->setExperimentalCSSCustomFilterEnabled(prefs.css_shaders_enabled);
settings->setRegionBasedColumnsEnabled(prefs.region_based_columns_enabled);
WebRuntimeFeatures::enableLazyLayout(prefs.lazy_layout_enabled);
WebRuntimeFeatures::enableTouch(prefs.touch_enabled);
+ settings->setMaxTouchPoints(prefs.pointer_events_max_touch_points);
settings->setDeviceSupportsTouch(prefs.device_supports_touch);
settings->setDeviceSupportsMouse(prefs.device_supports_mouse);
settings->setEnableTouchAdjustment(prefs.touch_adjustment_enabled);
@@ -313,8 +317,10 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) {
settings->setSupportsMultipleWindows(prefs.supports_multiple_windows);
settings->setViewportEnabled(prefs.viewport_enabled);
- settings->setInitializeAtMinimumPageScale(
- prefs.initialize_at_minimum_page_scale);
+ settings->setLoadWithOverviewMode(prefs.initialize_at_minimum_page_scale);
+ settings->setViewportMetaEnabled(prefs.viewport_meta_enabled);
+ settings->setMainFrameResizesAreOrientationChanges(
+ prefs.main_frame_resizes_are_orientation_changes);
settings->setSmartInsertDeleteEnabled(prefs.smart_insert_delete_enabled);
@@ -325,7 +331,8 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) {
#if defined(OS_ANDROID)
settings->setAllowCustomScrollbarInMainFrame(false);
settings->setTextAutosizingEnabled(prefs.text_autosizing_enabled);
- settings->setTextAutosizingFontScaleFactor(prefs.font_scale_factor);
+ settings->setAccessibilityFontScaleFactor(prefs.font_scale_factor);
+ settings->setDeviceScaleAdjustment(prefs.device_scale_adjustment);
web_view->setIgnoreViewportTagScaleLimits(prefs.force_enable_zoom);
settings->setAutoZoomFocusedNodeToLegibleScale(true);
settings->setDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled);
@@ -343,8 +350,20 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) {
settings->setUseWideViewport(prefs.use_wide_viewport);
settings->setViewportMetaLayoutSizeQuirk(
prefs.viewport_meta_layout_size_quirk);
+ settings->setViewportMetaMergeContentQuirk(
+ prefs.viewport_meta_merge_content_quirk);
+ settings->setViewportMetaNonUserScalableQuirk(
+ prefs.viewport_meta_non_user_scalable_quirk);
settings->setViewportMetaZeroValuesQuirk(
prefs.viewport_meta_zero_values_quirk);
+ settings->setClobberUserAgentInitialScaleQuirk(
+ prefs.clobber_user_agent_initial_scale_quirk);
+ settings->setIgnoreMainFrameOverflowHiddenQuirk(
+ prefs.ignore_main_frame_overflow_hidden_quirk);
+ settings->setReportScreenSizeInPhysicalPixelsQuirk(
+ prefs.report_screen_size_in_physical_pixels_quirk);
+ settings->setMainFrameClipsContent(false);
+ settings->setShrinksStandaloneImagesToFit(false);
#endif
WebNetworkStateNotifier::setOnLine(prefs.is_online);
@@ -356,6 +375,7 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) {
settings->setPinchOverlayScrollbarThickness(
prefs.pinch_overlay_scrollbar_thickness);
settings->setUseSolidColorScrollbars(prefs.use_solid_color_scrollbars);
+ settings->setCompositorTouchHitTesting(prefs.compositor_touch_hit_testing);
}
} // namespace content
diff --git a/chromium/content/renderer/web_ui_extension.cc b/chromium/content/renderer/web_ui_extension.cc
index 9616dbb76a2..f887e9d765e 100644
--- a/chromium/content/renderer/web_ui_extension.cc
+++ b/chromium/content/renderer/web_ui_extension.cc
@@ -48,13 +48,14 @@ class WebUIExtensionWrapper : public v8::Extension {
WebUIExtensionWrapper();
virtual ~WebUIExtensionWrapper();
- virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
+ v8::Isolate* isolate,
v8::Handle<v8::String> name) OVERRIDE;
static void Send(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetVariableValue(const v8::FunctionCallbackInfo<v8::Value>& args);
private:
- static bool ShouldRespondToRequest(WebKit::WebFrame** frame_ptr,
+ static bool ShouldRespondToRequest(blink::WebFrame** frame_ptr,
RenderView** render_view_ptr);
DISALLOW_COPY_AND_ASSIGN(WebUIExtensionWrapper);
@@ -65,20 +66,21 @@ WebUIExtensionWrapper::WebUIExtensionWrapper()
WebUIExtensionWrapper::~WebUIExtensionWrapper() {}
-v8::Handle<v8::FunctionTemplate> WebUIExtensionWrapper::GetNativeFunction(
- v8::Handle<v8::String> name) {
- if (name->Equals(v8::String::New("Send")))
- return v8::FunctionTemplate::New(Send);
- if (name->Equals(v8::String::New("GetVariableValue")))
- return v8::FunctionTemplate::New(GetVariableValue);
+v8::Handle<v8::FunctionTemplate>
+WebUIExtensionWrapper::GetNativeFunctionTemplate(v8::Isolate* isolate,
+ v8::Handle<v8::String> name) {
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "Send")))
+ return v8::FunctionTemplate::New(isolate, Send);
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "GetVariableValue")))
+ return v8::FunctionTemplate::New(isolate, GetVariableValue);
return v8::Handle<v8::FunctionTemplate>();
}
// static
bool WebUIExtensionWrapper::ShouldRespondToRequest(
- WebKit::WebFrame** frame_ptr,
+ blink::WebFrame** frame_ptr,
RenderView** render_view_ptr) {
- WebKit::WebFrame* frame = WebKit::WebFrame::frameForCurrentContext();
+ blink::WebFrame* frame = blink::WebFrame::frameForCurrentContext();
if (!frame || !frame->view())
return false;
@@ -104,7 +106,7 @@ bool WebUIExtensionWrapper::ShouldRespondToRequest(
// static
void WebUIExtensionWrapper::Send(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- WebKit::WebFrame* frame;
+ blink::WebFrame* frame;
RenderView* render_view;
if (!ShouldRespondToRequest(&frame, &render_view))
return;
@@ -145,7 +147,7 @@ void WebUIExtensionWrapper::Send(
// static
void WebUIExtensionWrapper::GetVariableValue(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- WebKit::WebFrame* frame;
+ blink::WebFrame* frame;
RenderView* render_view;
if (!ShouldRespondToRequest(&frame, &render_view))
return;
@@ -155,7 +157,10 @@ void WebUIExtensionWrapper::GetVariableValue(
std::string key = *v8::String::Utf8Value(args[0]->ToString());
std::string value = WebUIExtensionData::Get(render_view)->GetValue(key);
- args.GetReturnValue().Set(v8::String::New(value.c_str(), value.length()));
+ args.GetReturnValue().Set(v8::String::NewFromUtf8(args.GetIsolate(),
+ value.c_str(),
+ v8::String::kNormalString,
+ value.length()));
}
// static
diff --git a/chromium/content/renderer/webclipboard_impl.cc b/chromium/content/renderer/webclipboard_impl.cc
index 9ab29d1d892..c1ee0a71230 100644
--- a/chromium/content/renderer/webclipboard_impl.cc
+++ b/chromium/content/renderer/webclipboard_impl.cc
@@ -9,6 +9,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/common/drop_data.h"
+#include "content/renderer/clipboard_utils.h"
#include "content/renderer/drop_data_builder.h"
#include "content/renderer/scoped_clipboard_writer_glue.h"
#include "third_party/WebKit/public/platform/WebData.h"
@@ -22,16 +23,14 @@
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "url/gurl.h"
-#include "webkit/glue/webkit_glue.h"
-#include "webkit/renderer/clipboard_utils.h"
-using WebKit::WebClipboard;
-using WebKit::WebData;
-using WebKit::WebDragData;
-using WebKit::WebImage;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebVector;
+using blink::WebClipboard;
+using blink::WebData;
+using blink::WebDragData;
+using blink::WebImage;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebVector;
namespace content {
@@ -42,40 +41,36 @@ WebClipboardImpl::WebClipboardImpl(ClipboardClient* client)
WebClipboardImpl::~WebClipboardImpl() {
}
-uint64 WebClipboardImpl::getSequenceNumber() {
- return sequenceNumber(BufferStandard);
-}
-
uint64 WebClipboardImpl::sequenceNumber(Buffer buffer) {
- ui::Clipboard::Buffer buffer_type;
- if (!ConvertBufferType(buffer, &buffer_type))
+ ui::ClipboardType clipboard_type;
+ if (!ConvertBufferType(buffer, &clipboard_type))
return 0;
- return client_->GetSequenceNumber(buffer_type);
+ return client_->GetSequenceNumber(clipboard_type);
}
bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
- ui::Clipboard::Buffer buffer_type = ui::Clipboard::BUFFER_STANDARD;
+ ui::ClipboardType clipboard_type = ui::CLIPBOARD_TYPE_COPY_PASTE;
- if (!ConvertBufferType(buffer, &buffer_type))
+ if (!ConvertBufferType(buffer, &clipboard_type))
return false;
switch (format) {
case FormatPlainText:
return client_->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
- buffer_type) ||
+ clipboard_type) ||
client_->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
- buffer_type);
+ clipboard_type);
case FormatHTML:
return client_->IsFormatAvailable(ui::Clipboard::GetHtmlFormatType(),
- buffer_type);
+ clipboard_type);
case FormatSmartPaste:
return client_->IsFormatAvailable(
- ui::Clipboard::GetWebKitSmartPasteFormatType(), buffer_type);
+ ui::Clipboard::GetWebKitSmartPasteFormatType(), clipboard_type);
case FormatBookmark:
#if defined(OS_WIN) || defined(OS_MACOSX)
return client_->IsFormatAvailable(ui::Clipboard::GetUrlWFormatType(),
- buffer_type);
+ clipboard_type);
#endif
default:
NOTREACHED();
@@ -86,31 +81,31 @@ bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
WebVector<WebString> WebClipboardImpl::readAvailableTypes(
Buffer buffer, bool* contains_filenames) {
- ui::Clipboard::Buffer buffer_type;
+ ui::ClipboardType clipboard_type;
std::vector<base::string16> types;
- if (ConvertBufferType(buffer, &buffer_type)) {
- client_->ReadAvailableTypes(buffer_type, &types, contains_filenames);
+ if (ConvertBufferType(buffer, &clipboard_type)) {
+ client_->ReadAvailableTypes(clipboard_type, &types, contains_filenames);
}
return types;
}
WebString WebClipboardImpl::readPlainText(Buffer buffer) {
- ui::Clipboard::Buffer buffer_type;
- if (!ConvertBufferType(buffer, &buffer_type))
+ ui::ClipboardType clipboard_type;
+ if (!ConvertBufferType(buffer, &clipboard_type))
return WebString();
if (client_->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(),
- buffer_type)) {
+ clipboard_type)) {
base::string16 text;
- client_->ReadText(buffer_type, &text);
+ client_->ReadText(clipboard_type, &text);
if (!text.empty())
return text;
}
if (client_->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
- buffer_type)) {
+ clipboard_type)) {
std::string text;
- client_->ReadAsciiText(buffer_type, &text);
+ client_->ReadAsciiText(clipboard_type, &text);
if (!text.empty())
return ASCIIToUTF16(text);
}
@@ -121,13 +116,13 @@ WebString WebClipboardImpl::readPlainText(Buffer buffer) {
WebString WebClipboardImpl::readHTML(Buffer buffer, WebURL* source_url,
unsigned* fragment_start,
unsigned* fragment_end) {
- ui::Clipboard::Buffer buffer_type;
- if (!ConvertBufferType(buffer, &buffer_type))
+ ui::ClipboardType clipboard_type;
+ if (!ConvertBufferType(buffer, &clipboard_type))
return WebString();
base::string16 html_stdstr;
GURL gurl;
- client_->ReadHTML(buffer_type, &html_stdstr, &gurl,
+ client_->ReadHTML(clipboard_type, &html_stdstr, &gurl,
static_cast<uint32*>(fragment_start),
static_cast<uint32*>(fragment_end));
*source_url = gurl;
@@ -135,26 +130,31 @@ WebString WebClipboardImpl::readHTML(Buffer buffer, WebURL* source_url,
}
WebData WebClipboardImpl::readImage(Buffer buffer) {
- ui::Clipboard::Buffer buffer_type;
- if (!ConvertBufferType(buffer, &buffer_type))
+ ui::ClipboardType clipboard_type;
+ if (!ConvertBufferType(buffer, &clipboard_type))
return WebData();
std::string png_data;
- client_->ReadImage(buffer_type, &png_data);
+ client_->ReadImage(clipboard_type, &png_data);
return WebData(png_data);
}
WebString WebClipboardImpl::readCustomData(Buffer buffer,
const WebString& type) {
- ui::Clipboard::Buffer buffer_type;
- if (!ConvertBufferType(buffer, &buffer_type))
+ ui::ClipboardType clipboard_type;
+ if (!ConvertBufferType(buffer, &clipboard_type))
return WebString();
base::string16 data;
- client_->ReadCustomData(buffer_type, type, &data);
+ client_->ReadCustomData(clipboard_type, type, &data);
return data;
}
+void WebClipboardImpl::writePlainText(const WebString& plain_text) {
+ ScopedClipboardWriterGlue scw(client_);
+ scw.WriteText(plain_text);
+}
+
void WebClipboardImpl::writeHTML(
const WebString& html_text, const WebURL& source_url,
const WebString& plain_text, bool write_smart_paste) {
@@ -166,22 +166,9 @@ void WebClipboardImpl::writeHTML(
scw.WriteWebSmartPaste();
}
-void WebClipboardImpl::writePlainText(const WebString& plain_text) {
- ScopedClipboardWriterGlue scw(client_);
- scw.WriteText(plain_text);
-}
-
-void WebClipboardImpl::writeURL(const WebURL& url, const WebString& title) {
- ScopedClipboardWriterGlue scw(client_);
-
- scw.WriteBookmark(title, url.spec());
- scw.WriteHTML(UTF8ToUTF16(webkit_clipboard::URLToMarkup(url, title)),
- std::string());
- scw.WriteText(UTF8ToUTF16(std::string(url.spec())));
-}
-
-void WebClipboardImpl::writeImage(
- const WebImage& image, const WebURL& url, const WebString& title) {
+void WebClipboardImpl::writeImage(const WebImage& image,
+ const WebURL& url,
+ const WebString& title) {
ScopedClipboardWriterGlue scw(client_);
if (!image.isNull()) {
@@ -200,8 +187,7 @@ void WebClipboardImpl::writeImage(
// We also don't want to write HTML on a Mac, since Mail.app prefers to use
// the image markup over attaching the actual image. See
// http://crbug.com/33016 for details.
- scw.WriteHTML(UTF8ToUTF16(webkit_clipboard::URLToImageMarkup(url, title)),
- std::string());
+ scw.WriteHTML(UTF8ToUTF16(URLToImageMarkup(url, title)), std::string());
#endif
}
}
@@ -228,8 +214,8 @@ void WebClipboardImpl::writeDataObject(const WebDragData& data) {
}
bool WebClipboardImpl::ConvertBufferType(Buffer buffer,
- ui::Clipboard::Buffer* result) {
- *result = ui::Clipboard::BUFFER_STANDARD;
+ ui::ClipboardType* result) {
+ *result = ui::CLIPBOARD_TYPE_COPY_PASTE;
switch (buffer) {
case BufferStandard:
break;
@@ -240,7 +226,7 @@ bool WebClipboardImpl::ConvertBufferType(Buffer buffer,
// but not the X selection clipboad.
return false;
#else
- *result = ui::Clipboard::BUFFER_SELECTION;
+ *result = ui::CLIPBOARD_TYPE_SELECTION;
break;
#endif
#endif
@@ -252,4 +238,3 @@ bool WebClipboardImpl::ConvertBufferType(Buffer buffer,
}
} // namespace content
-
diff --git a/chromium/content/renderer/webclipboard_impl.h b/chromium/content/renderer/webclipboard_impl.h
index e5a12aa47bd..477f53b08fb 100644
--- a/chromium/content/renderer/webclipboard_impl.h
+++ b/chromium/content/renderer/webclipboard_impl.h
@@ -15,48 +15,43 @@
namespace content {
class ClipboardClient;
-class WebClipboardImpl : public WebKit::WebClipboard {
+class WebClipboardImpl : public blink::WebClipboard {
public:
explicit WebClipboardImpl(ClipboardClient* client);
virtual ~WebClipboardImpl();
// WebClipboard methods:
- virtual uint64 getSequenceNumber();
virtual uint64 sequenceNumber(Buffer buffer);
virtual bool isFormatAvailable(Format format, Buffer buffer);
- virtual WebKit::WebVector<WebKit::WebString> readAvailableTypes(
+ virtual blink::WebVector<blink::WebString> readAvailableTypes(
Buffer buffer, bool* contains_filenames);
- virtual WebKit::WebString readPlainText(Buffer buffer);
- virtual WebKit::WebString readHTML(
+ virtual blink::WebString readPlainText(Buffer buffer);
+ virtual blink::WebString readHTML(
Buffer buffer,
- WebKit::WebURL* source_url,
+ blink::WebURL* source_url,
unsigned* fragment_start,
unsigned* fragment_end);
- virtual WebKit::WebData readImage(Buffer buffer);
- virtual WebKit::WebString readCustomData(
- Buffer buffer, const WebKit::WebString& type);
+ virtual blink::WebData readImage(Buffer buffer);
+ virtual blink::WebString readCustomData(
+ Buffer buffer, const blink::WebString& type);
+ virtual void writePlainText(const blink::WebString& plain_text);
virtual void writeHTML(
- const WebKit::WebString& html_text,
- const WebKit::WebURL& source_url,
- const WebKit::WebString& plain_text,
+ const blink::WebString& html_text,
+ const blink::WebURL& source_url,
+ const blink::WebString& plain_text,
bool write_smart_paste);
- virtual void writePlainText(const WebKit::WebString& plain_text);
- virtual void writeURL(
- const WebKit::WebURL& url,
- const WebKit::WebString& title);
virtual void writeImage(
- const WebKit::WebImage& image,
- const WebKit::WebURL& source_url,
- const WebKit::WebString& title);
- virtual void writeDataObject(const WebKit::WebDragData& data);
+ const blink::WebImage& image,
+ const blink::WebURL& source_url,
+ const blink::WebString& title);
+ virtual void writeDataObject(const blink::WebDragData& data);
private:
- bool ConvertBufferType(Buffer, ui::Clipboard::Buffer*);
+ bool ConvertBufferType(Buffer, ui::ClipboardType*);
ClipboardClient* client_;
};
} // namespace content
#endif // CONTENT_RENDERER_WEBCLIPBOARD_IMPL_H_
-
diff --git a/chromium/content/renderer/webcrypto/OWNERS b/chromium/content/renderer/webcrypto/OWNERS
new file mode 100644
index 00000000000..6b60858e6e8
--- /dev/null
+++ b/chromium/content/renderer/webcrypto/OWNERS
@@ -0,0 +1,2 @@
+eroman@chromium.org
+rsleevi@chromium.org
diff --git a/chromium/content/renderer/webcrypto/webcrypto_impl.cc b/chromium/content/renderer/webcrypto/webcrypto_impl.cc
new file mode 100644
index 00000000000..4e343ba873a
--- /dev/null
+++ b/chromium/content/renderer/webcrypto/webcrypto_impl.cc
@@ -0,0 +1,631 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/webcrypto/webcrypto_impl.h"
+
+#include <algorithm>
+#include <functional>
+#include <map>
+#include "base/json/json_reader.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "base/values.h"
+#include "content/renderer/webcrypto/webcrypto_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+#include "third_party/WebKit/public/platform/WebCryptoKey.h"
+
+namespace content {
+
+namespace {
+
+bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) {
+ // TODO(padolph): include all other asymmetric algorithms once they are
+ // defined, e.g. EC and DH.
+ return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
+ algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
+ algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep);
+}
+
+// Binds a specific key length value to a compatible factory function.
+typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncWithOneShortArg)(
+ unsigned short);
+template <AlgFactoryFuncWithOneShortArg func, unsigned short key_length>
+blink::WebCryptoAlgorithm BindAlgFactoryWithKeyLen() {
+ return func(key_length);
+}
+
+// Binds a WebCryptoAlgorithmId value to a compatible factory function.
+typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncWithWebCryptoAlgIdArg)(
+ blink::WebCryptoAlgorithmId);
+template <AlgFactoryFuncWithWebCryptoAlgIdArg func,
+ blink::WebCryptoAlgorithmId algorithm_id>
+blink::WebCryptoAlgorithm BindAlgFactoryAlgorithmId() {
+ return func(algorithm_id);
+}
+
+// Defines a map between a JWK 'alg' string ID and a corresponding Web Crypto
+// factory function.
+typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncNoArgs)();
+typedef std::map<std::string, AlgFactoryFuncNoArgs> JwkAlgFactoryMap;
+
+class JwkAlgorithmFactoryMap {
+ public:
+ JwkAlgorithmFactoryMap() {
+ map_["HS256"] =
+ &BindAlgFactoryWithKeyLen<webcrypto::CreateHmacAlgorithmByHashOutputLen,
+ 256>;
+ map_["HS384"] =
+ &BindAlgFactoryWithKeyLen<webcrypto::CreateHmacAlgorithmByHashOutputLen,
+ 384>;
+ map_["HS512"] =
+ &BindAlgFactoryWithKeyLen<webcrypto::CreateHmacAlgorithmByHashOutputLen,
+ 512>;
+ map_["RS256"] =
+ &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm,
+ blink::WebCryptoAlgorithmIdSha256>;
+ map_["RS384"] =
+ &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm,
+ blink::WebCryptoAlgorithmIdSha384>;
+ map_["RS512"] =
+ &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm,
+ blink::WebCryptoAlgorithmIdSha512>;
+ map_["RSA1_5"] =
+ &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
+ blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>;
+ map_["RSA-OAEP"] =
+ &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaOaepAlgorithm,
+ blink::WebCryptoAlgorithmIdSha1>;
+ // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet
+ map_["A128KW"] = &blink::WebCryptoAlgorithm::createNull;
+ // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet
+ map_["A256KW"] = &blink::WebCryptoAlgorithm::createNull;
+ map_["A128GCM"] =
+ &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
+ blink::WebCryptoAlgorithmIdAesGcm>;
+ map_["A256GCM"] =
+ &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
+ blink::WebCryptoAlgorithmIdAesGcm>;
+ map_["A128CBC"] =
+ &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
+ blink::WebCryptoAlgorithmIdAesCbc>;
+ map_["A192CBC"] =
+ &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
+ blink::WebCryptoAlgorithmIdAesCbc>;
+ map_["A256CBC"] =
+ &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
+ blink::WebCryptoAlgorithmIdAesCbc>;
+ }
+
+ blink::WebCryptoAlgorithm CreateAlgorithmFromName(const std::string& alg_id)
+ const {
+ const JwkAlgFactoryMap::const_iterator pos = map_.find(alg_id);
+ if (pos == map_.end())
+ return blink::WebCryptoAlgorithm::createNull();
+ return pos->second();
+ }
+
+ private:
+ JwkAlgFactoryMap map_;
+};
+
+base::LazyInstance<JwkAlgorithmFactoryMap> jwk_alg_factory =
+ LAZY_INSTANCE_INITIALIZER;
+
+bool WebCryptoAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1,
+ const blink::WebCryptoAlgorithm& alg2) {
+ DCHECK(!alg1.isNull());
+ DCHECK(!alg2.isNull());
+ if (alg1.id() != alg2.id())
+ return false;
+ switch (alg1.id()) {
+ case blink::WebCryptoAlgorithmIdHmac:
+ case blink::WebCryptoAlgorithmIdRsaOaep:
+ case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
+ if (WebCryptoAlgorithmsConsistent(
+ webcrypto::GetInnerHashAlgorithm(alg1),
+ webcrypto::GetInnerHashAlgorithm(alg2))) {
+ return true;
+ }
+ break;
+ case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
+ case blink::WebCryptoAlgorithmIdSha1:
+ case blink::WebCryptoAlgorithmIdSha224:
+ case blink::WebCryptoAlgorithmIdSha256:
+ case blink::WebCryptoAlgorithmIdSha384:
+ case blink::WebCryptoAlgorithmIdSha512:
+ case blink::WebCryptoAlgorithmIdAesCbc:
+ case blink::WebCryptoAlgorithmIdAesGcm:
+ case blink::WebCryptoAlgorithmIdAesCtr:
+ return true;
+ default:
+ NOTREACHED(); // Not a supported algorithm.
+ break;
+ }
+ return false;
+}
+
+bool GetDecodedUrl64ValueByKey(
+ const base::DictionaryValue& dict,
+ const std::string& key,
+ std::string* decoded) {
+ std::string value_url64;
+ if (!dict.GetString(key, &value_url64) ||
+ !webcrypto::Base64DecodeUrlSafe(value_url64, decoded) ||
+ !decoded->size()) {
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+WebCryptoImpl::WebCryptoImpl() {
+ Init();
+}
+
+void WebCryptoImpl::encrypt(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebCryptoResult result) {
+ DCHECK(!algorithm.isNull());
+ blink::WebArrayBuffer buffer;
+ if (!EncryptInternal(algorithm, key, data, data_size, &buffer)) {
+ result.completeWithError();
+ } else {
+ result.completeWithBuffer(buffer);
+ }
+}
+
+void WebCryptoImpl::decrypt(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebCryptoResult result) {
+ DCHECK(!algorithm.isNull());
+ blink::WebArrayBuffer buffer;
+ if (!DecryptInternal(algorithm, key, data, data_size, &buffer)) {
+ result.completeWithError();
+ } else {
+ result.completeWithBuffer(buffer);
+ }
+}
+
+void WebCryptoImpl::digest(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebCryptoResult result) {
+ DCHECK(!algorithm.isNull());
+ blink::WebArrayBuffer buffer;
+ if (!DigestInternal(algorithm, data, data_size, &buffer)) {
+ result.completeWithError();
+ } else {
+ result.completeWithBuffer(buffer);
+ }
+}
+
+void WebCryptoImpl::generateKey(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoResult result) {
+ DCHECK(!algorithm.isNull());
+ if (IsAlgorithmAsymmetric(algorithm)) {
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
+ if (!GenerateKeyPairInternal(
+ algorithm, extractable, usage_mask, &public_key, &private_key)) {
+ result.completeWithError();
+ } else {
+ DCHECK(public_key.handle());
+ DCHECK(private_key.handle());
+ DCHECK_EQ(algorithm.id(), public_key.algorithm().id());
+ DCHECK_EQ(algorithm.id(), private_key.algorithm().id());
+ DCHECK_EQ(true, public_key.extractable());
+ DCHECK_EQ(extractable, private_key.extractable());
+ DCHECK_EQ(usage_mask, public_key.usages());
+ DCHECK_EQ(usage_mask, private_key.usages());
+ result.completeWithKeyPair(public_key, private_key);
+ }
+ } else {
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ if (!GenerateKeyInternal(algorithm, extractable, usage_mask, &key)) {
+ result.completeWithError();
+ } else {
+ DCHECK(key.handle());
+ DCHECK_EQ(algorithm.id(), key.algorithm().id());
+ DCHECK_EQ(extractable, key.extractable());
+ DCHECK_EQ(usage_mask, key.usages());
+ result.completeWithKey(key);
+ }
+ }
+}
+
+void WebCryptoImpl::importKey(
+ blink::WebCryptoKeyFormat format,
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ const blink::WebCryptoAlgorithm& algorithm_or_null,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoResult result) {
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ if (format == blink::WebCryptoKeyFormatJwk) {
+ if (!ImportKeyJwk(key_data,
+ key_data_size,
+ algorithm_or_null,
+ extractable,
+ usage_mask,
+ &key)) {
+ result.completeWithError();
+ return;
+ }
+ } else {
+ if (!ImportKeyInternal(format,
+ key_data,
+ key_data_size,
+ algorithm_or_null,
+ extractable,
+ usage_mask,
+ &key)) {
+ result.completeWithError();
+ return;
+ }
+ }
+ DCHECK(key.handle());
+ DCHECK(!key.algorithm().isNull());
+ DCHECK_EQ(extractable, key.extractable());
+ result.completeWithKey(key);
+}
+
+void WebCryptoImpl::exportKey(
+ blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ blink::WebCryptoResult result) {
+ blink::WebArrayBuffer buffer;
+ if (!ExportKeyInternal(format, key, &buffer)) {
+ result.completeWithError();
+ return;
+ }
+ result.completeWithBuffer(buffer);
+}
+
+void WebCryptoImpl::sign(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebCryptoResult result) {
+ DCHECK(!algorithm.isNull());
+ blink::WebArrayBuffer buffer;
+ if (!SignInternal(algorithm, key, data, data_size, &buffer)) {
+ result.completeWithError();
+ } else {
+ result.completeWithBuffer(buffer);
+ }
+}
+
+void WebCryptoImpl::verifySignature(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* signature,
+ unsigned signature_size,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebCryptoResult result) {
+ DCHECK(!algorithm.isNull());
+ bool signature_match = false;
+ if (!VerifySignatureInternal(algorithm,
+ key,
+ signature,
+ signature_size,
+ data,
+ data_size,
+ &signature_match)) {
+ result.completeWithError();
+ } else {
+ result.completeWithBoolean(signature_match);
+ }
+}
+
+bool WebCryptoImpl::ImportKeyJwk(
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ const blink::WebCryptoAlgorithm& algorithm_or_null,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+
+ // The goal of this method is to extract key material and meta data from the
+ // incoming JWK, combine them with the input parameters, and ultimately import
+ // a Web Crypto Key.
+ //
+ // JSON Web Key Format (JWK)
+ // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16
+ // TODO(padolph): Not all possible values are handled by this code right now
+ //
+ // A JWK is a simple JSON dictionary with the following entries
+ // - "kty" (Key Type) Parameter, REQUIRED
+ // - <kty-specific parameters, see below>, REQUIRED
+ // - "use" (Key Use) Parameter, OPTIONAL
+ // - "alg" (Algorithm) Parameter, OPTIONAL
+ // - "extractable" (Key Exportability), OPTIONAL [NOTE: not yet part of JOSE,
+ // see https://www.w3.org/Bugs/Public/show_bug.cgi?id=23796]
+ // (all other entries are ignored)
+ //
+ // OPTIONAL here means that this code does not require the entry to be present
+ // in the incoming JWK, because the method input parameters contain similar
+ // information. If the optional JWK entry is present, it will be validated
+ // against the corresponding input parameter for consistency and combined with
+ // it according to rules defined below. A special case is that the method
+ // input parameter 'algorithm' is also optional. If it is null, the JWK 'alg'
+ // value (if present) is used as a fallback.
+ //
+ // Input 'key_data' contains the JWK. To build a Web Crypto Key, the JWK
+ // values are parsed out and combined with the method input parameters to
+ // build a Web Crypto Key:
+ // Web Crypto Key type <-- (deduced)
+ // Web Crypto Key extractable <-- JWK extractable + input extractable
+ // Web Crypto Key algorithm <-- JWK alg + input algorithm
+ // Web Crypto Key keyUsage <-- JWK use + input usage_mask
+ // Web Crypto Key keying material <-- kty-specific parameters
+ //
+ // Values for each JWK entry are case-sensitive and defined in
+ // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16.
+ // Note that not all values specified by JOSE are handled by this code. Only
+ // handled values are listed.
+ // - kty (Key Type)
+ // +-------+--------------------------------------------------------------+
+ // | "RSA" | RSA [RFC3447] |
+ // | "oct" | Octet sequence (used to represent symmetric keys) |
+ // +-------+--------------------------------------------------------------+
+ // - use (Key Use)
+ // +-------+--------------------------------------------------------------+
+ // | "enc" | encrypt and decrypt operations |
+ // | "sig" | sign and verify (MAC) operations |
+ // | "wrap"| key wrap and unwrap [not yet part of JOSE] |
+ // +-------+--------------------------------------------------------------+
+ // - extractable (Key Exportability)
+ // +-------+--------------------------------------------------------------+
+ // | true | Key may be exported from the trusted environment |
+ // | false | Key cannot exit the trusted environment |
+ // +-------+--------------------------------------------------------------+
+ // - alg (Algorithm)
+ // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16
+ // +--------------+-------------------------------------------------------+
+ // | Digital Signature or MAC Algorithm |
+ // +--------------+-------------------------------------------------------+
+ // | "HS256" | HMAC using SHA-256 hash algorithm |
+ // | "HS384" | HMAC using SHA-384 hash algorithm |
+ // | "HS512" | HMAC using SHA-512 hash algorithm |
+ // | "RS256" | RSASSA using SHA-256 hash algorithm |
+ // | "RS384" | RSASSA using SHA-384 hash algorithm |
+ // | "RS512" | RSASSA using SHA-512 hash algorithm |
+ // +--------------+-------------------------------------------------------|
+ // | Key Management Algorithm |
+ // +--------------+-------------------------------------------------------+
+ // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] |
+ // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding |
+ // | | (OAEP) [RFC3447], with the default parameters |
+ // | | specified by RFC3447 in Section A.2.1 |
+ // | "A128KW" | Advanced Encryption Standard (AES) Key Wrap Algorithm |
+ // | | [RFC3394] using 128 bit keys |
+ // | "A256KW" | AES Key Wrap Algorithm using 256 bit keys |
+ // | "A128GCM" | AES in Galois/Counter Mode (GCM) [NIST.800-38D] using |
+ // | | 128 bit keys |
+ // | "A256GCM" | AES GCM using 256 bit keys |
+ // | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 |
+ // | | padding [NIST.800-38A] [not yet part of JOSE, see |
+ // | | https://www.w3.org/Bugs/Public/show_bug.cgi?id=23796 |
+ // | "A192CBC" | AES CBC using 192 bit keys [not yet part of JOSE] |
+ // | "A256CBC" | AES CBC using 256 bit keys [not yet part of JOSE] |
+ // +--------------+-------------------------------------------------------+
+ //
+ // kty-specific parameters
+ // The value of kty determines the type and content of the keying material
+ // carried in the JWK to be imported. Currently only two possibilities are
+ // supported: a raw key or an RSA public key. RSA private keys are not
+ // supported because typical applications seldom need to import a private key,
+ // and the large number of JWK parameters required to describe one.
+ // - kty == "oct" (symmetric or other raw key)
+ // +-------+--------------------------------------------------------------+
+ // | "k" | Contains the value of the symmetric (or other single-valued) |
+ // | | key. It is represented as the base64url encoding of the |
+ // | | octet sequence containing the key value. |
+ // +-------+--------------------------------------------------------------+
+ // - kty == "RSA" (RSA public key)
+ // +-------+--------------------------------------------------------------+
+ // | "n" | Contains the modulus value for the RSA public key. It is |
+ // | | represented as the base64url encoding of the value's |
+ // | | unsigned big endian representation as an octet sequence. |
+ // +-------+--------------------------------------------------------------+
+ // | "e" | Contains the exponent value for the RSA public key. It is |
+ // | | represented as the base64url encoding of the value's |
+ // | | unsigned big endian representation as an octet sequence. |
+ // +-------+--------------------------------------------------------------+
+ //
+ // Consistency and conflict resolution
+ // The 'algorithm_or_null', 'extractable', and 'usage_mask' input parameters
+ // may be different than the corresponding values inside the JWK. The Web
+ // Crypto spec says that if a JWK value is present but is inconsistent with
+ // the input value, it is an error and the operation must fail. If no
+ // inconsistency is found, the input and JWK values are combined as follows:
+ //
+ // algorithm
+ // If an algorithm is provided by both the input parameter and the JWK,
+ // consistency between the two is based only on algorithm ID's (including an
+ // inner hash algorithm if present). In this case if the consistency
+ // check is passed, the input algorithm is used. If only one of either the
+ // input algorithm and JWK alg is provided, it is used as the final
+ // algorithm.
+ //
+ // extractable
+ // If the JWK extractable is true but the input parameter is false, make the
+ // Web Crypto Key non-extractable. Conversely, if the JWK extractable is
+ // false but the input parameter is true, it is an inconsistency. If both
+ // are true or both are false, use that value.
+ //
+ // usage_mask
+ // The input usage_mask must be a strict subset of the interpreted JWK use
+ // value, else it is judged inconsistent. In all cases the input usage_mask
+ // is used as the final usage_mask.
+ //
+
+ if (!key_data_size)
+ return false;
+ DCHECK(key);
+
+ // Parse the incoming JWK JSON.
+ base::StringPiece json_string(reinterpret_cast<const char*>(key_data),
+ key_data_size);
+ scoped_ptr<base::Value> value(base::JSONReader::Read(json_string));
+ // Note, bare pointer dict_value is ok since it points into scoped value.
+ base::DictionaryValue* dict_value = NULL;
+ if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value)
+ return false;
+
+ // JWK "kty". Exit early if this required JWK parameter is missing.
+ std::string jwk_kty_value;
+ if (!dict_value->GetString("kty", &jwk_kty_value))
+ return false;
+
+ // JWK "extractable" (optional) --> extractable parameter
+ {
+ bool jwk_extractable_value;
+ if (dict_value->GetBoolean("extractable", &jwk_extractable_value)) {
+ if (!jwk_extractable_value && extractable)
+ return false;
+ extractable = extractable && jwk_extractable_value;
+ }
+ }
+
+ // JWK "alg" (optional) --> algorithm parameter
+ // Note: input algorithm is also optional, so we have six cases to handle.
+ // 1. JWK alg present but unrecognized: error
+ // 2. JWK alg valid AND input algorithm isNull: use JWK value
+ // 3. JWK alg valid AND input algorithm specified, but JWK value
+ // inconsistent with input: error
+ // 4. JWK alg valid AND input algorithm specified, both consistent: use
+ // input value (because it has potentially more details)
+ // 5. JWK alg missing AND input algorithm isNull: error
+ // 6. JWK alg missing AND input algorithm specified: use input value
+ blink::WebCryptoAlgorithm algorithm = blink::WebCryptoAlgorithm::createNull();
+ std::string jwk_alg_value;
+ if (dict_value->GetString("alg", &jwk_alg_value)) {
+ // JWK alg present
+
+ // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can
+ // only be from the RSA family.
+
+ const blink::WebCryptoAlgorithm jwk_algorithm =
+ jwk_alg_factory.Get().CreateAlgorithmFromName(jwk_alg_value);
+ if (jwk_algorithm.isNull()) {
+ // JWK alg unrecognized
+ return false; // case 1
+ }
+ // JWK alg valid
+ if (algorithm_or_null.isNull()) {
+ // input algorithm not specified
+ algorithm = jwk_algorithm; // case 2
+ } else {
+ // input algorithm specified
+ if (!WebCryptoAlgorithmsConsistent(jwk_algorithm, algorithm_or_null))
+ return false; // case 3
+ algorithm = algorithm_or_null; // case 4
+ }
+ } else {
+ // JWK alg missing
+ if (algorithm_or_null.isNull())
+ return false; // case 5
+ algorithm = algorithm_or_null; // case 6
+ }
+ DCHECK(!algorithm.isNull());
+
+ // JWK "use" (optional) --> usage_mask parameter
+ std::string jwk_use_value;
+ if (dict_value->GetString("use", &jwk_use_value)) {
+ blink::WebCryptoKeyUsageMask jwk_usage_mask = 0;
+ if (jwk_use_value == "enc") {
+ jwk_usage_mask =
+ blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt;
+ } else if (jwk_use_value == "sig") {
+ jwk_usage_mask =
+ blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
+ } else if (jwk_use_value == "wrap") {
+ jwk_usage_mask =
+ blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey;
+ } else {
+ return false;
+ }
+ if ((jwk_usage_mask & usage_mask) != usage_mask) {
+ // A usage_mask must be a subset of jwk_usage_mask.
+ return false;
+ }
+ }
+
+ // JWK keying material --> ImportKeyInternal()
+ if (jwk_kty_value == "oct") {
+
+ std::string jwk_k_value;
+ if (!GetDecodedUrl64ValueByKey(*dict_value, "k", &jwk_k_value))
+ return false;
+
+ // TODO(padolph): Some JWK alg ID's embed information about the key length
+ // in the alg ID string. For example "A128" implies the JWK carries 128 bits
+ // of key material, and "HS512" implies the JWK carries _at least_ 512 bits
+ // of key material. For such keys validate the actual key length against the
+ // value in the ID.
+
+ return ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
+ reinterpret_cast<const uint8*>(jwk_k_value.data()),
+ jwk_k_value.size(),
+ algorithm,
+ extractable,
+ usage_mask,
+ key);
+ } else if (jwk_kty_value == "RSA") {
+
+ // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry
+ // in the JWK, while an RSA private key must have those, plus at least a "d"
+ // (private exponent) entry.
+ // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
+ // section 6.3.
+
+ // RSA private key import is not currently supported, so fail here if a "d"
+ // entry is found.
+ // TODO(padolph): Support RSA private key import.
+ if (dict_value->HasKey("d"))
+ return false;
+
+ std::string jwk_n_value;
+ if (!GetDecodedUrl64ValueByKey(*dict_value, "n", &jwk_n_value))
+ return false;
+ std::string jwk_e_value;
+ if (!GetDecodedUrl64ValueByKey(*dict_value, "e", &jwk_e_value))
+ return false;
+
+ return ImportRsaPublicKeyInternal(
+ reinterpret_cast<const uint8*>(jwk_n_value.data()),
+ jwk_n_value.size(),
+ reinterpret_cast<const uint8*>(jwk_e_value.data()),
+ jwk_e_value.size(),
+ algorithm,
+ extractable,
+ usage_mask,
+ key);
+
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/webcrypto/webcrypto_impl.h b/chromium/content/renderer/webcrypto/webcrypto_impl.h
new file mode 100644
index 00000000000..6537d429b6f
--- /dev/null
+++ b/chromium/content/renderer/webcrypto/webcrypto_impl.h
@@ -0,0 +1,153 @@
+// 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_RENDERER_WEBCRYPTO_WEBCRYPTO_IMPL_H_
+#define CONTENT_RENDERER_WEBCRYPTO_WEBCRYPTO_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebCrypto.h"
+
+namespace content {
+
+class CONTENT_EXPORT WebCryptoImpl
+ : NON_EXPORTED_BASE(public blink::WebCrypto) {
+ public:
+ WebCryptoImpl();
+
+ virtual void encrypt(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebCryptoResult result);
+ virtual void decrypt(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebCryptoResult result);
+ virtual void digest(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebCryptoResult result);
+ virtual void generateKey(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoResult result);
+ virtual void importKey(
+ blink::WebCryptoKeyFormat format,
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ const blink::WebCryptoAlgorithm& algorithm_or_null,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoResult result);
+ virtual void exportKey(
+ blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ blink::WebCryptoResult result);
+ virtual void sign(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebCryptoResult result);
+ virtual void verifySignature(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* signature,
+ unsigned signature_size,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebCryptoResult result);
+
+
+ protected:
+ friend class WebCryptoImplTest;
+
+ void Init();
+
+ bool EncryptInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer);
+ bool DecryptInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer);
+ bool DigestInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer);
+ bool GenerateKeyInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key);
+ bool GenerateKeyPairInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* public_key,
+ blink::WebCryptoKey* private_key);
+ bool ImportKeyInternal(
+ blink::WebCryptoKeyFormat format,
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ const blink::WebCryptoAlgorithm& algorithm_or_null,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key);
+ bool ExportKeyInternal(
+ blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ blink::WebArrayBuffer* buffer);
+ bool SignInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer);
+ bool VerifySignatureInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* signature,
+ unsigned signature_size,
+ const unsigned char* data,
+ unsigned data_size,
+ bool* signature_match);
+
+ bool ImportKeyJwk(
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ const blink::WebCryptoAlgorithm& algorithm_or_null,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key);
+ bool ImportRsaPublicKeyInternal(
+ const unsigned char* modulus_data,
+ unsigned modulus_size,
+ const unsigned char* exponent_data,
+ unsigned exponent_size,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebCryptoImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_WEBCRYPTO_WEBCRYPTO_IMPL_H_
diff --git a/chromium/content/renderer/webcrypto/webcrypto_impl_nss.cc b/chromium/content/renderer/webcrypto/webcrypto_impl_nss.cc
new file mode 100644
index 00000000000..105bfbe9f89
--- /dev/null
+++ b/chromium/content/renderer/webcrypto/webcrypto_impl_nss.cc
@@ -0,0 +1,1013 @@
+// 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/webcrypto/webcrypto_impl.h"
+
+#include <cryptohi.h>
+#include <pk11pub.h>
+#include <sechash.h>
+
+#include <vector>
+
+#include "base/logging.h"
+#include "content/renderer/webcrypto/webcrypto_util.h"
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+#include "crypto/secure_util.h"
+#include "third_party/WebKit/public/platform/WebArrayBuffer.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+namespace content {
+
+namespace {
+
+class SymKeyHandle : public blink::WebCryptoKeyHandle {
+ public:
+ explicit SymKeyHandle(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {}
+
+ PK11SymKey* key() { return key_.get(); }
+
+ private:
+ crypto::ScopedPK11SymKey key_;
+
+ DISALLOW_COPY_AND_ASSIGN(SymKeyHandle);
+};
+
+class PublicKeyHandle : public blink::WebCryptoKeyHandle {
+ public:
+ explicit PublicKeyHandle(crypto::ScopedSECKEYPublicKey key)
+ : key_(key.Pass()) {}
+
+ SECKEYPublicKey* key() { return key_.get(); }
+
+ private:
+ crypto::ScopedSECKEYPublicKey key_;
+
+ DISALLOW_COPY_AND_ASSIGN(PublicKeyHandle);
+};
+
+class PrivateKeyHandle : public blink::WebCryptoKeyHandle {
+ public:
+ explicit PrivateKeyHandle(crypto::ScopedSECKEYPrivateKey key)
+ : key_(key.Pass()) {}
+
+ SECKEYPrivateKey* key() { return key_.get(); }
+
+ private:
+ crypto::ScopedSECKEYPrivateKey key_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrivateKeyHandle);
+};
+
+HASH_HashType WebCryptoAlgorithmToNSSHashType(
+ const blink::WebCryptoAlgorithm& algorithm) {
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return HASH_AlgSHA1;
+ case blink::WebCryptoAlgorithmIdSha224:
+ return HASH_AlgSHA224;
+ case blink::WebCryptoAlgorithmIdSha256:
+ return HASH_AlgSHA256;
+ case blink::WebCryptoAlgorithmIdSha384:
+ return HASH_AlgSHA384;
+ case blink::WebCryptoAlgorithmIdSha512:
+ return HASH_AlgSHA512;
+ default:
+ // Not a digest algorithm.
+ return HASH_AlgNULL;
+ }
+}
+
+CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism(
+ const blink::WebCryptoAlgorithm& algorithm) {
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return CKM_SHA_1_HMAC;
+ case blink::WebCryptoAlgorithmIdSha256:
+ return CKM_SHA256_HMAC;
+ default:
+ // Not a supported algorithm.
+ return CKM_INVALID_MECHANISM;
+ }
+}
+
+bool AesCbcEncryptDecrypt(
+ CK_ATTRIBUTE_TYPE operation,
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+ DCHECK_EQ(blink::WebCryptoAlgorithmIdAesCbc, algorithm.id());
+ DCHECK_EQ(algorithm.id(), key.algorithm().id());
+ DCHECK_EQ(blink::WebCryptoKeyTypeSecret, key.type());
+ DCHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT);
+
+ SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
+
+ const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams();
+ if (params->iv().size() != AES_BLOCK_SIZE)
+ return false;
+
+ SECItem iv_item;
+ iv_item.type = siBuffer;
+ iv_item.data = const_cast<unsigned char*>(params->iv().data());
+ iv_item.len = params->iv().size();
+
+ crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item));
+ if (!param)
+ return false;
+
+ crypto::ScopedPK11Context context(PK11_CreateContextBySymKey(
+ CKM_AES_CBC_PAD, operation, sym_key->key(), param.get()));
+
+ if (!context.get())
+ return false;
+
+ // Oddly PK11_CipherOp takes input and output lengths as "int" rather than
+ // "unsigned". Do some checks now to avoid integer overflowing.
+ if (data_size >= INT_MAX - AES_BLOCK_SIZE) {
+ // TODO(eroman): Handle this by chunking the input fed into NSS. Right now
+ // it doesn't make much difference since the one-shot API would end up
+ // blowing out the memory and crashing anyway. However a newer version of
+ // the spec allows for a sequence<CryptoData> so this will be relevant.
+ return false;
+ }
+
+ // PK11_CipherOp does an invalid memory access when given empty decryption
+ // input, or input which is not a multiple of the block size. See also
+ // https://bugzilla.mozilla.com/show_bug.cgi?id=921687.
+ if (operation == CKA_DECRYPT &&
+ (data_size == 0 || (data_size % AES_BLOCK_SIZE != 0))) {
+ return false;
+ }
+
+ // TODO(eroman): Refine the output buffer size. It can be computed exactly for
+ // encryption, and can be smaller for decryption.
+ unsigned output_max_len = data_size + AES_BLOCK_SIZE;
+ CHECK_GT(output_max_len, data_size);
+
+ *buffer = blink::WebArrayBuffer::create(output_max_len, 1);
+
+ unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data());
+
+ int output_len;
+ if (SECSuccess != PK11_CipherOp(context.get(),
+ buffer_data,
+ &output_len,
+ buffer->byteLength(),
+ data,
+ data_size)) {
+ return false;
+ }
+
+ unsigned int final_output_chunk_len;
+ if (SECSuccess != PK11_DigestFinal(context.get(),
+ buffer_data + output_len,
+ &final_output_chunk_len,
+ output_max_len - output_len)) {
+ return false;
+ }
+
+ webcrypto::ShrinkBuffer(buffer, final_output_chunk_len + output_len);
+ return true;
+}
+
+CK_MECHANISM_TYPE HmacAlgorithmToGenMechanism(
+ const blink::WebCryptoAlgorithm& algorithm) {
+ DCHECK_EQ(algorithm.id(), blink::WebCryptoAlgorithmIdHmac);
+ const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams();
+ DCHECK(params);
+ switch (params->hash().id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return CKM_SHA_1_HMAC;
+ case blink::WebCryptoAlgorithmIdSha256:
+ return CKM_SHA256_HMAC;
+ default:
+ return CKM_INVALID_MECHANISM;
+ }
+}
+
+CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism(
+ const blink::WebCryptoAlgorithm& algorithm) {
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdAesCbc:
+ return CKM_AES_KEY_GEN;
+ case blink::WebCryptoAlgorithmIdHmac:
+ return HmacAlgorithmToGenMechanism(algorithm);
+ default:
+ return CKM_INVALID_MECHANISM;
+ }
+}
+
+unsigned int WebCryptoHmacAlgorithmToBlockSize(
+ const blink::WebCryptoAlgorithm& algorithm) {
+ DCHECK_EQ(algorithm.id(), blink::WebCryptoAlgorithmIdHmac);
+ const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams();
+ DCHECK(params);
+ switch (params->hash().id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return 512;
+ case blink::WebCryptoAlgorithmIdSha256:
+ return 512;
+ default:
+ return 0;
+ }
+}
+
+// Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros,
+// to unsigned long.
+bool BigIntegerToLong(const uint8* data,
+ unsigned data_size,
+ unsigned long* result) {
+ // TODO(padolph): Is it correct to say that empty data is an error, or does it
+ // mean value 0? See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23655
+ if (data_size == 0)
+ return false;
+
+ *result = 0;
+ for (size_t i = 0; i < data_size; ++i) {
+ size_t reverse_i = data_size - i - 1;
+
+ if (reverse_i >= sizeof(unsigned long) && data[i])
+ return false; // Too large for a long.
+
+ *result |= data[i] << 8 * reverse_i;
+ }
+ return true;
+}
+
+bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) {
+ return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
+ algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep ||
+ algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
+}
+
+bool ImportKeyInternalRaw(
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+
+ DCHECK(!algorithm.isNull());
+
+ blink::WebCryptoKeyType type;
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdHmac:
+ case blink::WebCryptoAlgorithmIdAesCbc:
+ type = blink::WebCryptoKeyTypeSecret;
+ break;
+ // TODO(bryaneyler): Support more key types.
+ default:
+ return false;
+ }
+
+ // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys.
+ // Currently only supporting symmetric.
+ CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
+ // Flags are verified at the Blink layer; here the flags are set to all
+ // possible operations for this key type.
+ CK_FLAGS flags = 0;
+
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdHmac: {
+ const blink::WebCryptoHmacParams* params = algorithm.hmacParams();
+ if (!params) {
+ return false;
+ }
+
+ mechanism = WebCryptoAlgorithmToHMACMechanism(params->hash());
+ if (mechanism == CKM_INVALID_MECHANISM) {
+ return false;
+ }
+
+ flags |= CKF_SIGN | CKF_VERIFY;
+
+ break;
+ }
+ case blink::WebCryptoAlgorithmIdAesCbc: {
+ mechanism = CKM_AES_CBC;
+ flags |= CKF_ENCRYPT | CKF_DECRYPT;
+ break;
+ }
+ default:
+ return false;
+ }
+
+ DCHECK_NE(CKM_INVALID_MECHANISM, mechanism);
+ DCHECK_NE(0ul, flags);
+
+ SECItem key_item = {
+ siBuffer,
+ const_cast<unsigned char*>(key_data),
+ key_data_size
+ };
+
+ crypto::ScopedPK11SymKey pk11_sym_key(
+ PK11_ImportSymKeyWithFlags(PK11_GetInternalSlot(),
+ mechanism,
+ PK11_OriginUnwrap,
+ CKA_FLAGS_ONLY,
+ &key_item,
+ flags,
+ false,
+ NULL));
+ if (!pk11_sym_key.get()) {
+ return false;
+ }
+
+ *key = blink::WebCryptoKey::create(new SymKeyHandle(pk11_sym_key.Pass()),
+ type, extractable, algorithm, usage_mask);
+ return true;
+}
+
+bool ExportKeyInternalRaw(
+ const blink::WebCryptoKey& key,
+ blink::WebArrayBuffer* buffer) {
+
+ DCHECK(key.handle());
+ DCHECK(buffer);
+
+ if (key.type() != blink::WebCryptoKeyTypeSecret || !key.extractable())
+ return false;
+
+ SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
+
+ if (PK11_ExtractKeyValue(sym_key->key()) != SECSuccess)
+ return false;
+
+ const SECItem* key_data = PK11_GetKeyData(sym_key->key());
+ if (!key_data)
+ return false;
+
+ *buffer = webcrypto::CreateArrayBuffer(key_data->data, key_data->len);
+
+ return true;
+}
+
+typedef scoped_ptr<CERTSubjectPublicKeyInfo,
+ crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
+ SECKEY_DestroySubjectPublicKeyInfo> >
+ ScopedCERTSubjectPublicKeyInfo;
+
+// Validates an NSS KeyType against a WebCrypto algorithm. Some NSS KeyTypes
+// contain enough information to fabricate a Web Crypto algorithm, which is
+// returned if the input algorithm isNull(). This function indicates failure by
+// returning a Null algorithm.
+blink::WebCryptoAlgorithm ResolveNssKeyTypeWithInputAlgorithm(
+ KeyType key_type,
+ const blink::WebCryptoAlgorithm& algorithm_or_null) {
+ switch (key_type) {
+ case rsaKey:
+ // NSS's rsaKey KeyType maps to keys with SEC_OID_PKCS1_RSA_ENCRYPTION and
+ // according to RFCs 4055/5756 this can be used for both encryption and
+ // signatures. However, this is not specific enough to build a compatible
+ // Web Crypto algorithm, since in Web Crypto, RSA encryption and signature
+ // algorithms are distinct. So if the input algorithm isNull() here, we
+ // have to fail.
+ if (!algorithm_or_null.isNull() && IsAlgorithmRsa(algorithm_or_null))
+ return algorithm_or_null;
+ break;
+ case dsaKey:
+ case ecKey:
+ case rsaPssKey:
+ case rsaOaepKey:
+ // TODO(padolph): Handle other key types.
+ break;
+ default:
+ break;
+ }
+ return blink::WebCryptoAlgorithm::createNull();
+}
+
+bool ImportKeyInternalSpki(
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ const blink::WebCryptoAlgorithm& algorithm_or_null,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+
+ DCHECK(key);
+
+ if (!key_data_size)
+ return false;
+ DCHECK(key_data);
+
+ // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject
+ // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo.
+ SECItem spki_item = {siBuffer, const_cast<uint8*>(key_data), key_data_size};
+ const ScopedCERTSubjectPublicKeyInfo spki(
+ SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
+ if (!spki)
+ return false;
+
+ crypto::ScopedSECKEYPublicKey sec_public_key(
+ SECKEY_ExtractPublicKey(spki.get()));
+ if (!sec_public_key)
+ return false;
+
+ const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get());
+ blink::WebCryptoAlgorithm algorithm =
+ ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null);
+ if (algorithm.isNull())
+ return false;
+
+ *key = blink::WebCryptoKey::create(
+ new PublicKeyHandle(sec_public_key.Pass()),
+ blink::WebCryptoKeyTypePublic,
+ extractable,
+ algorithm,
+ usage_mask);
+
+ return true;
+}
+
+bool ExportKeyInternalSpki(
+ const blink::WebCryptoKey& key,
+ blink::WebArrayBuffer* buffer) {
+
+ DCHECK(key.handle());
+ DCHECK(buffer);
+
+ if (key.type() != blink::WebCryptoKeyTypePublic || !key.extractable())
+ return false;
+
+ PublicKeyHandle* const pub_key =
+ reinterpret_cast<PublicKeyHandle*>(key.handle());
+
+ const crypto::ScopedSECItem spki_der(
+ SECKEY_EncodeDERSubjectPublicKeyInfo(pub_key->key()));
+ if (!spki_der)
+ return false;
+
+ DCHECK(spki_der->data);
+ DCHECK(spki_der->len);
+
+ *buffer = webcrypto::CreateArrayBuffer(spki_der->data, spki_der->len);
+
+ return true;
+}
+
+bool ImportKeyInternalPkcs8(
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ const blink::WebCryptoAlgorithm& algorithm_or_null,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+
+ DCHECK(key);
+
+ if (!key_data_size)
+ return false;
+ DCHECK(key_data);
+
+ // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8
+ // private key info object.
+ SECItem pki_der = {siBuffer, const_cast<uint8*>(key_data), key_data_size};
+
+ SECKEYPrivateKey* seckey_private_key = NULL;
+ if (PK11_ImportDERPrivateKeyInfoAndReturnKey(
+ PK11_GetInternalSlot(),
+ &pki_der,
+ NULL, // nickname
+ NULL, // publicValue
+ false, // isPerm
+ false, // isPrivate
+ KU_ALL, // usage
+ &seckey_private_key,
+ NULL) != SECSuccess) {
+ return false;
+ }
+ DCHECK(seckey_private_key);
+ crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key);
+
+ const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get());
+ blink::WebCryptoAlgorithm algorithm =
+ ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null);
+ if (algorithm.isNull())
+ return false;
+
+ *key = blink::WebCryptoKey::create(
+ new PrivateKeyHandle(private_key.Pass()),
+ blink::WebCryptoKeyTypePrivate,
+ extractable,
+ algorithm,
+ usage_mask);
+
+ return true;
+}
+
+} // namespace
+
+void WebCryptoImpl::Init() {
+ crypto::EnsureNSSInit();
+}
+
+bool WebCryptoImpl::EncryptInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+
+ DCHECK_EQ(algorithm.id(), key.algorithm().id());
+ DCHECK(key.handle());
+ DCHECK(buffer);
+
+ if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) {
+ return AesCbcEncryptDecrypt(
+ CKA_ENCRYPT, algorithm, key, data, data_size, buffer);
+ } else if (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5) {
+
+ // RSAES encryption does not support empty input
+ if (!data_size)
+ return false;
+ DCHECK(data);
+
+ if (key.type() != blink::WebCryptoKeyTypePublic)
+ return false;
+
+ PublicKeyHandle* const public_key =
+ reinterpret_cast<PublicKeyHandle*>(key.handle());
+
+ const unsigned encrypted_length_bytes =
+ SECKEY_PublicKeyStrength(public_key->key());
+
+ // RSAES can operate on messages up to a length of k - 11, where k is the
+ // octet length of the RSA modulus.
+ if (encrypted_length_bytes < 11 || encrypted_length_bytes - 11 < data_size)
+ return false;
+
+ *buffer = blink::WebArrayBuffer::create(encrypted_length_bytes, 1);
+ unsigned char* const buffer_data =
+ reinterpret_cast<unsigned char*>(buffer->data());
+
+ if (PK11_PubEncryptPKCS1(public_key->key(),
+ buffer_data,
+ const_cast<unsigned char*>(data),
+ data_size,
+ NULL) != SECSuccess) {
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool WebCryptoImpl::DecryptInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+
+ DCHECK_EQ(algorithm.id(), key.algorithm().id());
+ DCHECK(key.handle());
+ DCHECK(buffer);
+
+ if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) {
+ return AesCbcEncryptDecrypt(
+ CKA_DECRYPT, algorithm, key, data, data_size, buffer);
+ } else if (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5) {
+
+ // RSAES decryption does not support empty input
+ if (!data_size)
+ return false;
+ DCHECK(data);
+
+ if (key.type() != blink::WebCryptoKeyTypePrivate)
+ return false;
+
+ PrivateKeyHandle* const private_key =
+ reinterpret_cast<PrivateKeyHandle*>(key.handle());
+
+ const int modulus_length_bytes =
+ PK11_GetPrivateModulusLen(private_key->key());
+ if (modulus_length_bytes <= 0)
+ return false;
+ const unsigned max_output_length_bytes = modulus_length_bytes;
+
+ *buffer = blink::WebArrayBuffer::create(max_output_length_bytes, 1);
+ unsigned char* const buffer_data =
+ reinterpret_cast<unsigned char*>(buffer->data());
+
+ unsigned output_length_bytes = 0;
+ if (PK11_PrivDecryptPKCS1(private_key->key(),
+ buffer_data,
+ &output_length_bytes,
+ max_output_length_bytes,
+ const_cast<unsigned char*>(data),
+ data_size) != SECSuccess) {
+ return false;
+ }
+ DCHECK_LE(output_length_bytes, max_output_length_bytes);
+ webcrypto::ShrinkBuffer(buffer, output_length_bytes);
+ return true;
+ }
+
+ return false;
+}
+
+bool WebCryptoImpl::DigestInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+ HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm);
+ if (hash_type == HASH_AlgNULL) {
+ return false;
+ }
+
+ HASHContext* context = HASH_Create(hash_type);
+ if (!context) {
+ return false;
+ }
+
+ HASH_Begin(context);
+
+ HASH_Update(context, data, data_size);
+
+ unsigned hash_result_length = HASH_ResultLenContext(context);
+ DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX));
+
+ *buffer = blink::WebArrayBuffer::create(hash_result_length, 1);
+
+ unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data());
+
+ unsigned result_length = 0;
+ HASH_End(context, digest, &result_length, hash_result_length);
+
+ HASH_Destroy(context);
+
+ return result_length == hash_result_length;
+}
+
+bool WebCryptoImpl::GenerateKeyInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+
+ CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm);
+ unsigned int keylen_bytes = 0;
+ blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret;
+
+ if (mech == CKM_INVALID_MECHANISM) {
+ return false;
+ }
+
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdAesCbc: {
+ const blink::WebCryptoAesKeyGenParams* params =
+ algorithm.aesKeyGenParams();
+ DCHECK(params);
+ keylen_bytes = params->length() / 8;
+ if (params->length() % 8)
+ return false;
+ key_type = blink::WebCryptoKeyTypeSecret;
+ break;
+ }
+ case blink::WebCryptoAlgorithmIdHmac: {
+ const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams();
+ DCHECK(params);
+ if (!params->getLength(keylen_bytes)) {
+ keylen_bytes = WebCryptoHmacAlgorithmToBlockSize(algorithm) / 8;
+ }
+
+ key_type = blink::WebCryptoKeyTypeSecret;
+ break;
+ }
+
+ default: {
+ return false;
+ }
+ }
+
+ if (keylen_bytes == 0) {
+ return false;
+ }
+
+ crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
+ if (!slot) {
+ return false;
+ }
+
+ crypto::ScopedPK11SymKey pk11_key(
+ PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL));
+
+ if (!pk11_key) {
+ return false;
+ }
+
+ *key = blink::WebCryptoKey::create(
+ new SymKeyHandle(pk11_key.Pass()),
+ key_type, extractable, algorithm, usage_mask);
+ return true;
+}
+
+bool WebCryptoImpl::GenerateKeyPairInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* public_key,
+ blink::WebCryptoKey* private_key) {
+
+ // TODO(padolph): Handle other asymmetric algorithm key generation.
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
+ case blink::WebCryptoAlgorithmIdRsaOaep:
+ case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: {
+ const blink::WebCryptoRsaKeyGenParams* const params =
+ algorithm.rsaKeyGenParams();
+ DCHECK(params);
+
+ crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
+ unsigned long public_exponent;
+ if (!slot || !params->modulusLength() ||
+ !BigIntegerToLong(params->publicExponent().data(),
+ params->publicExponent().size(),
+ &public_exponent) ||
+ !public_exponent) {
+ return false;
+ }
+
+ PK11RSAGenParams rsa_gen_params;
+ rsa_gen_params.keySizeInBits = params->modulusLength();
+ rsa_gen_params.pe = public_exponent;
+
+ // Flags are verified at the Blink layer; here the flags are set to all
+ // possible operations for the given key type.
+ CK_FLAGS operation_flags;
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
+ case blink::WebCryptoAlgorithmIdRsaOaep:
+ operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
+ break;
+ case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
+ operation_flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ default:
+ NOTREACHED();
+ return false;
+ }
+ const CK_FLAGS operation_flags_mask = CKF_ENCRYPT | CKF_DECRYPT |
+ CKF_SIGN | CKF_VERIFY | CKF_WRAP |
+ CKF_UNWRAP;
+ const PK11AttrFlags attribute_flags = 0; // Default all PK11_ATTR_ flags.
+
+ // Note: NSS does not generate an sec_public_key if the call below fails,
+ // so there is no danger of a leaked sec_public_key.
+ SECKEYPublicKey* sec_public_key;
+ crypto::ScopedSECKEYPrivateKey scoped_sec_private_key(
+ PK11_GenerateKeyPairWithOpFlags(slot.get(),
+ CKM_RSA_PKCS_KEY_PAIR_GEN,
+ &rsa_gen_params,
+ &sec_public_key,
+ attribute_flags,
+ operation_flags,
+ operation_flags_mask,
+ NULL));
+ if (!private_key) {
+ return false;
+ }
+
+ *public_key = blink::WebCryptoKey::create(
+ new PublicKeyHandle(crypto::ScopedSECKEYPublicKey(sec_public_key)),
+ blink::WebCryptoKeyTypePublic,
+ true,
+ algorithm,
+ usage_mask);
+ *private_key = blink::WebCryptoKey::create(
+ new PrivateKeyHandle(scoped_sec_private_key.Pass()),
+ blink::WebCryptoKeyTypePrivate,
+ extractable,
+ algorithm,
+ usage_mask);
+
+ return true;
+ }
+ default:
+ return false;
+ }
+}
+
+bool WebCryptoImpl::ImportKeyInternal(
+ blink::WebCryptoKeyFormat format,
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ const blink::WebCryptoAlgorithm& algorithm_or_null,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ // A 'raw'-formatted key import requires an input algorithm.
+ if (algorithm_or_null.isNull())
+ return false;
+ return ImportKeyInternalRaw(key_data,
+ key_data_size,
+ algorithm_or_null,
+ extractable,
+ usage_mask,
+ key);
+ case blink::WebCryptoKeyFormatSpki:
+ return ImportKeyInternalSpki(key_data,
+ key_data_size,
+ algorithm_or_null,
+ extractable,
+ usage_mask,
+ key);
+ case blink::WebCryptoKeyFormatPkcs8:
+ return ImportKeyInternalPkcs8(key_data,
+ key_data_size,
+ algorithm_or_null,
+ extractable,
+ usage_mask,
+ key);
+ default:
+ // NOTE: blink::WebCryptoKeyFormatJwk is handled one level above.
+ return false;
+ }
+}
+
+bool WebCryptoImpl::ExportKeyInternal(
+ blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ blink::WebArrayBuffer* buffer) {
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ return ExportKeyInternalRaw(key, buffer);
+ case blink::WebCryptoKeyFormatSpki:
+ return ExportKeyInternalSpki(key, buffer);
+ case blink::WebCryptoKeyFormatPkcs8:
+ // TODO(padolph): Implement pkcs8 export
+ return false;
+ default:
+ return false;
+ }
+}
+
+bool WebCryptoImpl::SignInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+ blink::WebArrayBuffer result;
+
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdHmac: {
+ const blink::WebCryptoHmacParams* params = algorithm.hmacParams();
+ if (!params) {
+ return false;
+ }
+
+ SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
+
+ DCHECK_EQ(PK11_GetMechanism(sym_key->key()),
+ WebCryptoAlgorithmToHMACMechanism(params->hash()));
+ DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign);
+
+ SECItem param_item = { siBuffer, NULL, 0 };
+ SECItem data_item = {
+ siBuffer,
+ const_cast<unsigned char*>(data),
+ data_size
+ };
+ // First call is to figure out the length.
+ SECItem signature_item = { siBuffer, NULL, 0 };
+
+ if (PK11_SignWithSymKey(sym_key->key(),
+ PK11_GetMechanism(sym_key->key()),
+ &param_item,
+ &signature_item,
+ &data_item) != SECSuccess) {
+ NOTREACHED();
+ return false;
+ }
+
+ DCHECK_NE(0u, signature_item.len);
+
+ result = blink::WebArrayBuffer::create(signature_item.len, 1);
+ signature_item.data = reinterpret_cast<unsigned char*>(result.data());
+
+ if (PK11_SignWithSymKey(sym_key->key(),
+ PK11_GetMechanism(sym_key->key()),
+ &param_item,
+ &signature_item,
+ &data_item) != SECSuccess) {
+ NOTREACHED();
+ return false;
+ }
+
+ DCHECK_EQ(result.byteLength(), signature_item.len);
+
+ break;
+ }
+ default:
+ return false;
+ }
+
+ *buffer = result;
+ return true;
+}
+
+bool WebCryptoImpl::VerifySignatureInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* signature,
+ unsigned signature_size,
+ const unsigned char* data,
+ unsigned data_size,
+ bool* signature_match) {
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdHmac: {
+ blink::WebArrayBuffer result;
+ if (!SignInternal(algorithm, key, data, data_size, &result)) {
+ return false;
+ }
+
+ // Handling of truncated signatures is underspecified in the WebCrypto
+ // spec, so here we fail verification if a truncated signature is being
+ // verified.
+ // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097
+ *signature_match =
+ result.byteLength() == signature_size &&
+ crypto::SecureMemEqual(result.data(), signature, signature_size);
+
+ break;
+ }
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool WebCryptoImpl::ImportRsaPublicKeyInternal(
+ const unsigned char* modulus_data,
+ unsigned modulus_size,
+ const unsigned char* exponent_data,
+ unsigned exponent_size,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+
+ if (!modulus_size || !exponent_size)
+ return false;
+ DCHECK(modulus_data);
+ DCHECK(exponent_data);
+
+ // NSS does not provide a way to create an RSA public key directly from the
+ // modulus and exponent values, but it can import an DER-encoded ASN.1 blob
+ // with these values and create the public key from that. The code below
+ // follows the recommendation described in
+ // https://developer.mozilla.org/en-US/docs/NSS/NSS_Tech_Notes/nss_tech_note7
+
+ // Pack the input values into a struct compatible with NSS ASN.1 encoding, and
+ // set up an ASN.1 encoder template for it.
+ struct RsaPublicKeyData {
+ SECItem modulus;
+ SECItem exponent;
+ };
+ const RsaPublicKeyData pubkey_in = {
+ {siUnsignedInteger, const_cast<unsigned char*>(modulus_data),
+ modulus_size},
+ {siUnsignedInteger, const_cast<unsigned char*>(exponent_data),
+ exponent_size}};
+ const SEC_ASN1Template rsa_public_key_template[] = {
+ {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RsaPublicKeyData)},
+ {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, modulus), },
+ {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, exponent), },
+ {0, }};
+
+ // DER-encode the public key.
+ crypto::ScopedSECItem pubkey_der(SEC_ASN1EncodeItem(
+ NULL, NULL, &pubkey_in, rsa_public_key_template));
+ if (!pubkey_der)
+ return false;
+
+ // Import the DER-encoded public key to create an RSA SECKEYPublicKey.
+ crypto::ScopedSECKEYPublicKey pubkey(
+ SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA));
+ if (!pubkey)
+ return false;
+
+ *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()),
+ blink::WebCryptoKeyTypePublic,
+ extractable,
+ algorithm,
+ usage_mask);
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/webcrypto/webcrypto_impl_openssl.cc b/chromium/content/renderer/webcrypto/webcrypto_impl_openssl.cc
new file mode 100644
index 00000000000..9faf51da7be
--- /dev/null
+++ b/chromium/content/renderer/webcrypto/webcrypto_impl_openssl.cc
@@ -0,0 +1,539 @@
+// 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/webcrypto/webcrypto_impl.h"
+
+#include <vector>
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+#include "base/logging.h"
+#include "content/renderer/webcrypto/webcrypto_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/secure_util.h"
+#include "third_party/WebKit/public/platform/WebArrayBuffer.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+namespace content {
+
+namespace {
+
+class SymKeyHandle : public blink::WebCryptoKeyHandle {
+ public:
+ SymKeyHandle(const unsigned char* key_data, unsigned key_data_size)
+ : key_(key_data, key_data + key_data_size) {}
+
+ const std::vector<unsigned char>& key() const { return key_; }
+
+ private:
+ const std::vector<unsigned char> key_;
+
+ DISALLOW_COPY_AND_ASSIGN(SymKeyHandle);
+};
+
+const EVP_CIPHER* GetAESCipherByKeyLength(unsigned key_length_bytes) {
+ // OpenSSL supports AES CBC ciphers for only 3 key lengths: 128, 192, 256 bits
+ switch (key_length_bytes) {
+ case 16:
+ return EVP_aes_128_cbc();
+ case 24:
+ return EVP_aes_192_cbc();
+ case 32:
+ return EVP_aes_256_cbc();
+ default:
+ return NULL;
+ }
+}
+
+unsigned WebCryptoHmacParamsToBlockSize(
+ const blink::WebCryptoHmacKeyParams* params) {
+ DCHECK(params);
+ switch (params->hash().id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return SHA_DIGEST_LENGTH / 8;
+ case blink::WebCryptoAlgorithmIdSha224:
+ return SHA224_DIGEST_LENGTH / 8;
+ case blink::WebCryptoAlgorithmIdSha256:
+ return SHA256_DIGEST_LENGTH / 8;
+ case blink::WebCryptoAlgorithmIdSha384:
+ return SHA384_DIGEST_LENGTH / 8;
+ case blink::WebCryptoAlgorithmIdSha512:
+ return SHA512_DIGEST_LENGTH / 8;
+ default:
+ return 0;
+ }
+}
+
+// OpenSSL constants for EVP_CipherInit_ex(), do not change
+enum CipherOperation {
+ kDoDecrypt = 0,
+ kDoEncrypt = 1
+};
+
+bool AesCbcEncryptDecrypt(CipherOperation cipher_operation,
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+
+ // TODO(padolph): Handle other encrypt operations and then remove this gate
+ if (algorithm.id() != blink::WebCryptoAlgorithmIdAesCbc)
+ return false;
+
+ DCHECK_EQ(algorithm.id(), key.algorithm().id());
+ DCHECK_EQ(blink::WebCryptoKeyTypeSecret, key.type());
+
+ if (data_size >= INT_MAX - AES_BLOCK_SIZE) {
+ // TODO(padolph): Handle this by chunking the input fed into OpenSSL. Right
+ // now it doesn't make much difference since the one-shot API would end up
+ // blowing out the memory and crashing anyway. However a newer version of
+ // the spec allows for a sequence<CryptoData> so this will be relevant.
+ return false;
+ }
+
+ // Note: PKCS padding is enabled by default
+ crypto::ScopedOpenSSL<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free> context(
+ EVP_CIPHER_CTX_new());
+
+ if (!context.get())
+ return false;
+
+ SymKeyHandle* const sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
+
+ const EVP_CIPHER* const cipher =
+ GetAESCipherByKeyLength(sym_key->key().size());
+ DCHECK(cipher);
+
+ const blink::WebCryptoAesCbcParams* const params = algorithm.aesCbcParams();
+ if (params->iv().size() != AES_BLOCK_SIZE)
+ return false;
+
+ if (!EVP_CipherInit_ex(context.get(),
+ cipher,
+ NULL,
+ &sym_key->key()[0],
+ params->iv().data(),
+ cipher_operation)) {
+ return false;
+ }
+
+ // According to the openssl docs, the amount of data written may be as large
+ // as (data_size + cipher_block_size - 1), constrained to a multiple of
+ // cipher_block_size.
+ unsigned output_max_len = data_size + AES_BLOCK_SIZE - 1;
+ const unsigned remainder = output_max_len % AES_BLOCK_SIZE;
+ if (remainder != 0)
+ output_max_len += AES_BLOCK_SIZE - remainder;
+ DCHECK_GT(output_max_len, data_size);
+
+ *buffer = blink::WebArrayBuffer::create(output_max_len, 1);
+
+ unsigned char* const buffer_data =
+ reinterpret_cast<unsigned char*>(buffer->data());
+
+ int output_len = 0;
+ if (!EVP_CipherUpdate(
+ context.get(), buffer_data, &output_len, data, data_size))
+ return false;
+ int final_output_chunk_len = 0;
+ if (!EVP_CipherFinal_ex(
+ context.get(), buffer_data + output_len, &final_output_chunk_len))
+ return false;
+
+ const unsigned final_output_len =
+ static_cast<unsigned>(output_len) +
+ static_cast<unsigned>(final_output_chunk_len);
+ DCHECK_LE(final_output_len, output_max_len);
+
+ webcrypto::ShrinkBuffer(buffer, final_output_len);
+
+ return true;
+}
+
+bool ExportKeyInternalRaw(
+ const blink::WebCryptoKey& key,
+ blink::WebArrayBuffer* buffer) {
+
+ DCHECK(key.handle());
+ DCHECK(buffer);
+
+ if (key.type() != blink::WebCryptoKeyTypeSecret || !key.extractable())
+ return false;
+
+ const SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
+
+ *buffer = webcrypto::CreateArrayBuffer(
+ webcrypto::Uint8VectorStart(sym_key->key()), sym_key->key().size());
+
+ return true;
+}
+
+} // namespace
+
+void WebCryptoImpl::Init() { crypto::EnsureOpenSSLInit(); }
+
+bool WebCryptoImpl::EncryptInternal(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+ if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) {
+ return AesCbcEncryptDecrypt(
+ kDoEncrypt, algorithm, key, data, data_size, buffer);
+ }
+
+ return false;
+}
+
+bool WebCryptoImpl::DecryptInternal(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+ if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) {
+ return AesCbcEncryptDecrypt(
+ kDoDecrypt, algorithm, key, data, data_size, buffer);
+ }
+
+ return false;
+}
+
+bool WebCryptoImpl::DigestInternal(const blink::WebCryptoAlgorithm& algorithm,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+
+ crypto::OpenSSLErrStackTracer(FROM_HERE);
+
+ const EVP_MD* digest_algorithm;
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ digest_algorithm = EVP_sha1();
+ break;
+ case blink::WebCryptoAlgorithmIdSha224:
+ digest_algorithm = EVP_sha224();
+ break;
+ case blink::WebCryptoAlgorithmIdSha256:
+ digest_algorithm = EVP_sha256();
+ break;
+ case blink::WebCryptoAlgorithmIdSha384:
+ digest_algorithm = EVP_sha384();
+ break;
+ case blink::WebCryptoAlgorithmIdSha512:
+ digest_algorithm = EVP_sha512();
+ break;
+ default:
+ // Not a digest algorithm.
+ return false;
+ }
+
+ crypto::ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> digest_context(
+ EVP_MD_CTX_create());
+ if (!digest_context.get()) {
+ return false;
+ }
+
+ if (!EVP_DigestInit_ex(digest_context.get(), digest_algorithm, NULL) ||
+ !EVP_DigestUpdate(digest_context.get(), data, data_size)) {
+ return false;
+ }
+
+ const int hash_expected_size = EVP_MD_CTX_size(digest_context.get());
+ if (hash_expected_size <= 0) {
+ return false;
+ }
+ DCHECK_LE(hash_expected_size, EVP_MAX_MD_SIZE);
+
+ *buffer = blink::WebArrayBuffer::create(hash_expected_size, 1);
+ unsigned char* const hash_buffer =
+ reinterpret_cast<unsigned char* const>(buffer->data());
+
+ unsigned hash_size = 0;
+ if (!EVP_DigestFinal_ex(digest_context.get(), hash_buffer, &hash_size) ||
+ static_cast<int>(hash_size) != hash_expected_size) {
+ buffer->reset();
+ return false;
+ }
+
+ return true;
+}
+
+bool WebCryptoImpl::GenerateKeyInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+
+ unsigned keylen_bytes = 0;
+ blink::WebCryptoKeyType key_type;
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdAesCbc: {
+ const blink::WebCryptoAesKeyGenParams* params =
+ algorithm.aesKeyGenParams();
+ DCHECK(params);
+ if (params->length() % 8)
+ return false;
+ keylen_bytes = params->length() / 8;
+ if (!GetAESCipherByKeyLength(keylen_bytes)) {
+ return false;
+ }
+ key_type = blink::WebCryptoKeyTypeSecret;
+ break;
+ }
+ case blink::WebCryptoAlgorithmIdHmac: {
+ const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams();
+ DCHECK(params);
+ if (!params->getLength(keylen_bytes)) {
+ keylen_bytes = WebCryptoHmacParamsToBlockSize(params);
+ }
+ key_type = blink::WebCryptoKeyTypeSecret;
+ break;
+ }
+
+ default: { return false; }
+ }
+
+ if (keylen_bytes == 0) {
+ return false;
+ }
+
+ crypto::OpenSSLErrStackTracer(FROM_HERE);
+
+ std::vector<unsigned char> random_bytes(keylen_bytes, 0);
+ if (!(RAND_bytes(&random_bytes[0], keylen_bytes))) {
+ return false;
+ }
+
+ *key = blink::WebCryptoKey::create(
+ new SymKeyHandle(&random_bytes[0], random_bytes.size()),
+ key_type, extractable, algorithm, usage_mask);
+
+ return true;
+}
+
+bool WebCryptoImpl::GenerateKeyPairInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* public_key,
+ blink::WebCryptoKey* private_key) {
+ // TODO(padolph): Placeholder for OpenSSL implementation.
+ // Issue http://crbug.com/267888.
+ return false;
+}
+
+bool WebCryptoImpl::ImportKeyInternal(
+ blink::WebCryptoKeyFormat format,
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ const blink::WebCryptoAlgorithm& algorithm_or_null,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+ // TODO(eroman): Currently expects algorithm to always be specified, as it is
+ // required for raw format.
+ if (algorithm_or_null.isNull())
+ return false;
+ const blink::WebCryptoAlgorithm& algorithm = algorithm_or_null;
+
+ // TODO(padolph): Support all relevant alg types and then remove this gate.
+ if (algorithm.id() != blink::WebCryptoAlgorithmIdHmac &&
+ algorithm.id() != blink::WebCryptoAlgorithmIdAesCbc) {
+ return false;
+ }
+
+ // TODO(padolph): Need to split handling for symmetric (raw format) and
+ // asymmetric (spki or pkcs8 format) keys.
+ // Currently only supporting symmetric.
+
+ // Symmetric keys are always type secret
+ blink::WebCryptoKeyType type = blink::WebCryptoKeyTypeSecret;
+
+ const unsigned char* raw_key_data;
+ unsigned raw_key_data_size;
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ raw_key_data = key_data;
+ raw_key_data_size = key_data_size;
+ // The NSS implementation fails when importing a raw AES key with a length
+ // incompatible with AES. The line below is to match this behavior.
+ if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc &&
+ !GetAESCipherByKeyLength(raw_key_data_size)) {
+ return false;
+ }
+ break;
+ case blink::WebCryptoKeyFormatJwk:
+ // TODO(padolph): Handle jwk format; need simple JSON parser.
+ // break;
+ return false;
+ default:
+ return false;
+ }
+
+ *key = blink::WebCryptoKey::create(
+ new SymKeyHandle(raw_key_data, raw_key_data_size),
+ type, extractable, algorithm, usage_mask);
+
+ return true;
+}
+
+bool WebCryptoImpl::ExportKeyInternal(
+ blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ blink::WebArrayBuffer* buffer) {
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ return ExportKeyInternalRaw(key, buffer);
+ case blink::WebCryptoKeyFormatSpki:
+ // TODO(padolph): Implement spki export
+ return false;
+ case blink::WebCryptoKeyFormatPkcs8:
+ // TODO(padolph): Implement pkcs8 export
+ return false;
+ default:
+ return false;
+ }
+ return false;
+}
+
+bool WebCryptoImpl::SignInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+
+ blink::WebArrayBuffer result;
+
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdHmac: {
+
+ DCHECK_EQ(key.algorithm().id(), blink::WebCryptoAlgorithmIdHmac);
+ DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign);
+
+ const blink::WebCryptoHmacParams* const params = algorithm.hmacParams();
+ if (!params)
+ return false;
+
+ const EVP_MD* evp_sha = 0;
+ unsigned int hmac_expected_length = 0;
+ // Note that HMAC length is determined by the hash used.
+ switch (params->hash().id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ evp_sha = EVP_sha1();
+ hmac_expected_length = SHA_DIGEST_LENGTH;
+ break;
+ case blink::WebCryptoAlgorithmIdSha224:
+ evp_sha = EVP_sha224();
+ hmac_expected_length = SHA224_DIGEST_LENGTH;
+ break;
+ case blink::WebCryptoAlgorithmIdSha256:
+ evp_sha = EVP_sha256();
+ hmac_expected_length = SHA256_DIGEST_LENGTH;
+ break;
+ case blink::WebCryptoAlgorithmIdSha384:
+ evp_sha = EVP_sha384();
+ hmac_expected_length = SHA384_DIGEST_LENGTH;
+ break;
+ case blink::WebCryptoAlgorithmIdSha512:
+ evp_sha = EVP_sha512();
+ hmac_expected_length = SHA512_DIGEST_LENGTH;
+ break;
+ default:
+ // Not a digest algorithm.
+ return false;
+ }
+
+ SymKeyHandle* const sym_key =
+ reinterpret_cast<SymKeyHandle*>(key.handle());
+ const std::vector<unsigned char>& raw_key = sym_key->key();
+
+ // OpenSSL wierdness here.
+ // First, HMAC() needs a void* for the key data, so make one up front as a
+ // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key,
+ // which will result if the raw_key vector is empty; an entirely valid
+ // case. Handle this specific case by pointing to an empty array.
+ const unsigned char null_key[] = {};
+ const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key;
+
+ result = blink::WebArrayBuffer::create(hmac_expected_length, 1);
+ crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result(
+ reinterpret_cast<unsigned char*>(result.data()),
+ hmac_expected_length);
+
+ crypto::OpenSSLErrStackTracer(FROM_HERE);
+
+ unsigned int hmac_actual_length;
+ unsigned char* const success = HMAC(evp_sha,
+ raw_key_voidp,
+ raw_key.size(),
+ data,
+ data_size,
+ hmac_result.safe_buffer(),
+ &hmac_actual_length);
+ if (!success || hmac_actual_length != hmac_expected_length)
+ return false;
+
+ break;
+ }
+ default:
+ return false;
+ }
+
+ *buffer = result;
+ return true;
+}
+
+bool WebCryptoImpl::VerifySignatureInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* signature,
+ unsigned signature_size,
+ const unsigned char* data,
+ unsigned data_size,
+ bool* signature_match) {
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdHmac: {
+ blink::WebArrayBuffer result;
+ if (!SignInternal(algorithm, key, data, data_size, &result)) {
+ return false;
+ }
+
+ // Handling of truncated signatures is underspecified in the WebCrypto
+ // spec, so here we fail verification if a truncated signature is being
+ // verified.
+ // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097
+ *signature_match =
+ result.byteLength() == signature_size &&
+ crypto::SecureMemEqual(result.data(), signature, signature_size);
+
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool WebCryptoImpl::ImportRsaPublicKeyInternal(
+ const unsigned char* modulus_data,
+ unsigned modulus_size,
+ const unsigned char* exponent_data,
+ unsigned exponent_size,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+ // TODO(padolph): Placeholder for OpenSSL implementation.
+ // Issue http://crbug.com/267888.
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/webcrypto/webcrypto_impl_unittest.cc b/chromium/content/renderer/webcrypto/webcrypto_impl_unittest.cc
new file mode 100644
index 00000000000..8abe36fe443
--- /dev/null
+++ b/chromium/content/renderer/webcrypto/webcrypto_impl_unittest.cc
@@ -0,0 +1,1641 @@
+// 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/webcrypto/webcrypto_impl.h"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/json/json_writer.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/public/renderer/content_renderer_client.h"
+#include "content/renderer/renderer_webkitplatformsupport_impl.h"
+#include "content/renderer/webcrypto/webcrypto_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebArrayBuffer.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+#include "third_party/WebKit/public/platform/WebCryptoKey.h"
+
+namespace content {
+
+namespace {
+
+std::vector<uint8> HexStringToBytes(const std::string& hex) {
+ std::vector<uint8> bytes;
+ base::HexStringToBytes(hex, &bytes);
+ return bytes;
+}
+
+void ExpectArrayBufferMatchesHex(const std::string& expected_hex,
+ const blink::WebArrayBuffer& array_buffer) {
+ EXPECT_STRCASEEQ(
+ expected_hex.c_str(),
+ base::HexEncode(array_buffer.data(), array_buffer.byteLength()).c_str());
+}
+
+std::vector<uint8> MakeJsonVector(const std::string& json_string) {
+ return std::vector<uint8>(json_string.begin(), json_string.end());
+}
+
+std::vector<uint8> MakeJsonVector(const base::DictionaryValue& dict) {
+ std::string json;
+ base::JSONWriter::Write(&dict, &json);
+ return MakeJsonVector(json);
+}
+
+// Helper for ImportJwkFailures and ImportJwkOctFailures. Restores the JWK JSON
+// dictionary to a good state
+void RestoreJwkOctDictionary(base::DictionaryValue* dict) {
+ dict->Clear();
+ dict->SetString("kty", "oct");
+ dict->SetString("alg", "A128CBC");
+ dict->SetString("use", "enc");
+ dict->SetBoolean("extractable", false);
+ dict->SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
+}
+
+#if !defined(USE_OPENSSL)
+
+// Helper for ImportJwkRsaFailures. Restores the JWK JSON
+// dictionary to a good state
+void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
+ dict->Clear();
+ dict->SetString("kty", "RSA");
+ dict->SetString("alg", "RSA1_5");
+ dict->SetString("use", "enc");
+ dict->SetBoolean("extractable", false);
+ dict->SetString("n",
+ "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
+ "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
+ "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
+ dict->SetString("e", "AQAB");
+}
+
+blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmId algorithm_id,
+ unsigned modulus_length,
+ const std::vector<uint8>& public_exponent) {
+ DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
+ algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
+ algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep);
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
+ algorithm_id,
+ new blink::WebCryptoRsaKeyGenParams(
+ modulus_length,
+ webcrypto::Uint8VectorStart(public_exponent),
+ public_exponent.size()));
+}
+
+// Determines if two ArrayBuffers have identical content.
+bool ArrayBuffersEqual(
+ const blink::WebArrayBuffer& a,
+ const blink::WebArrayBuffer& b) {
+ return a.byteLength() == b.byteLength() &&
+ memcmp(a.data(), b.data(), a.byteLength()) == 0;
+}
+
+// Given a vector of WebArrayBuffers, determines if there are any copies.
+bool CopiesExist(std::vector<blink::WebArrayBuffer> bufs) {
+ for (size_t i = 0; i < bufs.size(); ++i) {
+ for (size_t j = i + 1; j < bufs.size(); ++j) {
+ if (ArrayBuffersEqual(bufs[i], bufs[j]))
+ return true;
+ }
+ }
+ return false;
+}
+
+#endif // #if !defined(USE_OPENSSL)
+
+} // namespace
+
+class WebCryptoImplTest : public testing::Test {
+ protected:
+ blink::WebCryptoKey ImportSecretKeyFromRawHexString(
+ const std::string& key_hex,
+ const blink::WebCryptoAlgorithm& algorithm,
+ blink::WebCryptoKeyUsageMask usage) {
+ std::vector<uint8> key_raw = HexStringToBytes(key_hex);
+
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ bool extractable = true;
+ EXPECT_TRUE(crypto_.ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
+ webcrypto::Uint8VectorStart(key_raw),
+ key_raw.size(),
+ algorithm,
+ extractable,
+ usage,
+ &key));
+
+ EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
+ EXPECT_FALSE(key.isNull());
+ EXPECT_TRUE(key.handle());
+ return key;
+ }
+
+ // Forwarding methods to gain access to protected methods of
+ // WebCryptoImpl.
+
+ bool DigestInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const std::vector<uint8>& data,
+ blink::WebArrayBuffer* buffer) {
+ return crypto_.DigestInternal(
+ algorithm, webcrypto::Uint8VectorStart(data), data.size(), buffer);
+ }
+
+ bool GenerateKeyInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ blink::WebCryptoKey* key) {
+ bool extractable = true;
+ blink::WebCryptoKeyUsageMask usage_mask = 0;
+ return crypto_.GenerateKeyInternal(algorithm, extractable, usage_mask, key);
+ }
+
+ bool GenerateKeyPairInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* public_key,
+ blink::WebCryptoKey* private_key) {
+ return crypto_.GenerateKeyPairInternal(
+ algorithm, extractable, usage_mask, public_key, private_key);
+ }
+
+ bool ImportKeyInternal(
+ blink::WebCryptoKeyFormat format,
+ const std::vector<uint8>& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+ return crypto_.ImportKeyInternal(format,
+ webcrypto::Uint8VectorStart(key_data),
+ key_data.size(),
+ algorithm,
+ extractable,
+ usage_mask,
+ key);
+ }
+
+ bool ExportKeyInternal(
+ blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ blink::WebArrayBuffer* buffer) {
+ return crypto_.ExportKeyInternal(format, key, buffer);
+ }
+
+ bool SignInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const std::vector<uint8>& data,
+ blink::WebArrayBuffer* buffer) {
+ return crypto_.SignInternal(
+ algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer);
+ }
+
+ bool VerifySignatureInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* signature,
+ unsigned signature_size,
+ const std::vector<uint8>& data,
+ bool* signature_match) {
+ return crypto_.VerifySignatureInternal(algorithm,
+ key,
+ signature,
+ signature_size,
+ webcrypto::Uint8VectorStart(data),
+ data.size(),
+ signature_match);
+ }
+
+ bool EncryptInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+ return crypto_.EncryptInternal(algorithm, key, data, data_size, buffer);
+ }
+
+ bool EncryptInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const std::vector<uint8>& data,
+ blink::WebArrayBuffer* buffer) {
+ return crypto_.EncryptInternal(
+ algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer);
+ }
+
+ bool DecryptInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const unsigned char* data,
+ unsigned data_size,
+ blink::WebArrayBuffer* buffer) {
+ return crypto_.DecryptInternal(algorithm, key, data, data_size, buffer);
+ }
+
+ bool DecryptInternal(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const std::vector<uint8>& data,
+ blink::WebArrayBuffer* buffer) {
+ return crypto_.DecryptInternal(
+ algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer);
+ }
+
+ bool ImportKeyJwk(
+ const std::vector<uint8>& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKey* key) {
+ return crypto_.ImportKeyJwk(webcrypto::Uint8VectorStart(key_data),
+ key_data.size(),
+ algorithm,
+ extractable,
+ usage_mask,
+ key);
+ }
+
+ private:
+ WebCryptoImpl crypto_;
+};
+
+TEST_F(WebCryptoImplTest, DigestSampleSets) {
+ // The results are stored here in hex format for readability.
+ //
+ // TODO(bryaneyler): Eventually, all these sample test sets should be replaced
+ // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03
+ //
+ // Results were generated using the command sha{1,224,256,384,512}sum.
+ struct TestCase {
+ blink::WebCryptoAlgorithmId algorithm;
+ const std::string hex_input;
+ const char* hex_result;
+ };
+
+ const TestCase kTests[] = {
+ { blink::WebCryptoAlgorithmIdSha1, "",
+ "da39a3ee5e6b4b0d3255bfef95601890afd80709"
+ },
+ { blink::WebCryptoAlgorithmIdSha224, "",
+ "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
+ },
+ { blink::WebCryptoAlgorithmIdSha256, "",
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ },
+ { blink::WebCryptoAlgorithmIdSha384, "",
+ "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274e"
+ "debfe76f65fbd51ad2f14898b95b"
+ },
+ { blink::WebCryptoAlgorithmIdSha512, "",
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0"
+ "d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
+ },
+ { blink::WebCryptoAlgorithmIdSha1, "00",
+ "5ba93c9db0cff93f52b521d7420e43f6eda2784f",
+ },
+ { blink::WebCryptoAlgorithmIdSha224, "00",
+ "fff9292b4201617bdc4d3053fce02734166a683d7d858a7f5f59b073",
+ },
+ { blink::WebCryptoAlgorithmIdSha256, "00",
+ "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d",
+ },
+ { blink::WebCryptoAlgorithmIdSha384, "00",
+ "bec021b4f368e3069134e012c2b4307083d3a9bdd206e24e5f0d86e13d6636655933"
+ "ec2b413465966817a9c208a11717",
+ },
+ { blink::WebCryptoAlgorithmIdSha512, "00",
+ "b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a"
+ "802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee",
+ },
+ { blink::WebCryptoAlgorithmIdSha1, "000102030405",
+ "868460d98d09d8bbb93d7b6cdd15cc7fbec676b9",
+ },
+ { blink::WebCryptoAlgorithmIdSha224, "000102030405",
+ "7d92e7f1cad1818ed1d13ab41f04ebabfe1fef6bb4cbeebac34c29bc",
+ },
+ { blink::WebCryptoAlgorithmIdSha256, "000102030405",
+ "17e88db187afd62c16e5debf3e6527cd006bc012bc90b51a810cd80c2d511f43",
+ },
+ { blink::WebCryptoAlgorithmIdSha384, "000102030405",
+ "79f4738706fce9650ac60266675c3cd07298b09923850d525604d040e6e448adc7dc"
+ "22780d7e1b95bfeaa86a678e4552",
+ },
+ { blink::WebCryptoAlgorithmIdSha512, "000102030405",
+ "2f3831bccc94cf061bcfa5f8c23c1429d26e3bc6b76edad93d9025cb91c903af6cf9"
+ "c935dc37193c04c2c66e7d9de17c358284418218afea2160147aaa912f4c",
+ },
+ };
+
+ for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
+ ++test_index) {
+ SCOPED_TRACE(test_index);
+ const TestCase& test = kTests[test_index];
+
+ blink::WebCryptoAlgorithm algorithm =
+ webcrypto::CreateAlgorithm(test.algorithm);
+ std::vector<uint8> input = HexStringToBytes(test.hex_input);
+
+ blink::WebArrayBuffer output;
+ ASSERT_TRUE(DigestInternal(algorithm, input, &output));
+ ExpectArrayBufferMatchesHex(test.hex_result, output);
+ }
+}
+
+TEST_F(WebCryptoImplTest, HMACSampleSets) {
+ struct TestCase {
+ blink::WebCryptoAlgorithmId algorithm;
+ const char* key;
+ const char* message;
+ const char* mac;
+ };
+
+ const TestCase kTests[] = {
+ // Empty sets. Result generated via OpenSSL commandline tool. These
+ // particular results are also posted on the Wikipedia page examples:
+ // http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
+ {
+ blink::WebCryptoAlgorithmIdSha1,
+ "",
+ "",
+ // openssl dgst -sha1 -hmac "" < /dev/null
+ "fbdb1d1b18aa6c08324b7d64b71fb76370690e1d",
+ },
+ {
+ blink::WebCryptoAlgorithmIdSha256,
+ "",
+ "",
+ // openssl dgst -sha256 -hmac "" < /dev/null
+ "b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad",
+ },
+ // For this data, see http://csrc.nist.gov/groups/STM/cavp/index.html#07
+ // Download:
+ // http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
+ // L=20 set 45
+ {
+ blink::WebCryptoAlgorithmIdSha1,
+ // key
+ "59785928d72516e31272",
+ // message
+ "a3ce8899df1022e8d2d539b47bf0e309c66f84095e21438ec355bf119ce5fdcb4e73a6"
+ "19cdf36f25b369d8c38ff419997f0c59830108223606e31223483fd39edeaa4d3f0d21"
+ "198862d239c9fd26074130ff6c86493f5227ab895c8f244bd42c7afce5d147a20a5907"
+ "98c68e708e964902d124dadecdbda9dbd0051ed710e9bf",
+ // mac
+ "3c8162589aafaee024fc9a5ca50dd2336fe3eb28",
+ },
+ // L=20 set 299
+ {
+ blink::WebCryptoAlgorithmIdSha1,
+ // key
+ "ceb9aedf8d6efcf0ae52bea0fa99a9e26ae81bacea0cff4d5eecf201e3bca3c3577480"
+ "621b818fd717ba99d6ff958ea3d59b2527b019c343bb199e648090225867d994607962"
+ "f5866aa62930d75b58f6",
+ // message
+ "99958aa459604657c7bf6e4cdfcc8785f0abf06ffe636b5b64ecd931bd8a4563055924"
+ "21fc28dbcccb8a82acea2be8e54161d7a78e0399a6067ebaca3f2510274dc9f92f2c8a"
+ "e4265eec13d7d42e9f8612d7bc258f913ecb5a3a5c610339b49fb90e9037b02d684fc6"
+ "0da835657cb24eab352750c8b463b1a8494660d36c3ab2",
+ // mac
+ "4ac41ab89f625c60125ed65ffa958c6b490ea670",
+ },
+ // L=32, set 30
+ {
+ blink::WebCryptoAlgorithmIdSha256,
+ // key
+ "9779d9120642797f1747025d5b22b7ac607cab08e1758f2f3a46c8be1e25c53b8c6a8f"
+ "58ffefa176",
+ // message
+ "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
+ "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
+ "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
+ "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e",
+ // mac
+ "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b",
+ },
+ // L=32, set 224
+ {
+ blink::WebCryptoAlgorithmIdSha256,
+ // key
+ "4b7ab133efe99e02fc89a28409ee187d579e774f4cba6fc223e13504e3511bef8d4f63"
+ "8b9aca55d4a43b8fbd64cf9d74dcc8c9e8d52034898c70264ea911a3fd70813fa73b08"
+ "3371289b",
+ // message
+ "138efc832c64513d11b9873c6fd4d8a65dbf367092a826ddd587d141b401580b798c69"
+ "025ad510cff05fcfbceb6cf0bb03201aaa32e423d5200925bddfadd418d8e30e18050e"
+ "b4f0618eb9959d9f78c1157d4b3e02cd5961f138afd57459939917d9144c95d8e6a94c"
+ "8f6d4eef3418c17b1ef0b46c2a7188305d9811dccb3d99",
+ // mac
+ "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b",
+ },
+ };
+
+ for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
+ ++test_index) {
+ SCOPED_TRACE(test_index);
+ const TestCase& test = kTests[test_index];
+
+ blink::WebCryptoAlgorithm algorithm =
+ webcrypto::CreateHmacAlgorithmByHashId(test.algorithm);
+
+ blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
+ test.key, algorithm, blink::WebCryptoKeyUsageSign);
+
+ // Verify exported raw key is identical to the imported data
+ blink::WebArrayBuffer raw_key;
+ EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
+ ExpectArrayBufferMatchesHex(test.key, raw_key);
+
+ std::vector<uint8> message_raw = HexStringToBytes(test.message);
+
+ blink::WebArrayBuffer output;
+
+ ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output));
+
+ ExpectArrayBufferMatchesHex(test.mac, output);
+
+ bool signature_match = false;
+ EXPECT_TRUE(VerifySignatureInternal(
+ algorithm,
+ key,
+ static_cast<const unsigned char*>(output.data()),
+ output.byteLength(),
+ message_raw,
+ &signature_match));
+ EXPECT_TRUE(signature_match);
+
+ // Ensure truncated signature does not verify by passing one less byte.
+ EXPECT_TRUE(VerifySignatureInternal(
+ algorithm,
+ key,
+ static_cast<const unsigned char*>(output.data()),
+ output.byteLength() - 1,
+ message_raw,
+ &signature_match));
+ EXPECT_FALSE(signature_match);
+
+ // Ensure extra long signature does not cause issues and fails.
+ const unsigned char kLongSignature[1024] = { 0 };
+ EXPECT_TRUE(VerifySignatureInternal(
+ algorithm,
+ key,
+ kLongSignature,
+ sizeof(kLongSignature),
+ message_raw,
+ &signature_match));
+ EXPECT_FALSE(signature_match);
+ }
+}
+
+#if !defined(USE_OPENSSL)
+
+TEST_F(WebCryptoImplTest, AesCbcFailures) {
+ const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c";
+ blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
+ key_hex,
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
+ blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
+
+ // Verify exported raw key is identical to the imported data
+ blink::WebArrayBuffer raw_key;
+ EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
+ ExpectArrayBufferMatchesHex(key_hex, raw_key);
+
+ blink::WebArrayBuffer output;
+
+ // Use an invalid |iv| (fewer than 16 bytes)
+ {
+ std::vector<uint8> input(32);
+ std::vector<uint8> iv;
+ EXPECT_FALSE(EncryptInternal(
+ webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
+ EXPECT_FALSE(DecryptInternal(
+ webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
+ }
+
+ // Use an invalid |iv| (more than 16 bytes)
+ {
+ std::vector<uint8> input(32);
+ std::vector<uint8> iv(17);
+ EXPECT_FALSE(EncryptInternal(
+ webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
+ EXPECT_FALSE(DecryptInternal(
+ webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
+ }
+
+ // Give an input that is too large (would cause integer overflow when
+ // narrowing to an int).
+ {
+ std::vector<uint8> iv(16);
+
+ // Pretend the input is large. Don't pass data pointer as NULL in case that
+ // is special cased; the implementation shouldn't actually dereference the
+ // data.
+ const unsigned char* input = &iv[0];
+ unsigned input_len = INT_MAX - 3;
+
+ EXPECT_FALSE(EncryptInternal(
+ webcrypto::CreateAesCbcAlgorithm(iv), key, input, input_len, &output));
+ EXPECT_FALSE(DecryptInternal(
+ webcrypto::CreateAesCbcAlgorithm(iv), key, input, input_len, &output));
+ }
+
+ // Fail importing the key (too few bytes specified)
+ {
+ std::vector<uint8> key_raw(1);
+ std::vector<uint8> iv(16);
+
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
+ key_raw,
+ webcrypto::CreateAesCbcAlgorithm(iv),
+ true,
+ blink::WebCryptoKeyUsageEncrypt,
+ &key));
+ }
+
+ // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
+ // keys).
+ EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
+ EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatPkcs8, key, &output));
+}
+
+TEST_F(WebCryptoImplTest, AesCbcSampleSets) {
+ struct TestCase {
+ const char* key;
+ const char* iv;
+ const char* plain_text;
+ const char* cipher_text;
+ };
+
+ TestCase kTests[] = {
+ // F.2.1 (CBC-AES128.Encrypt)
+ // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ {
+ // key
+ "2b7e151628aed2a6abf7158809cf4f3c",
+
+ // iv
+ "000102030405060708090a0b0c0d0e0f",
+
+ // plain_text
+ "6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710",
+
+ // cipher_text
+ "7649abac8119b246cee98e9b12e9197d"
+ "5086cb9b507219ee95db113a917678b2"
+ "73bed6b8e3c1743b7116e69e22229516"
+ "3ff1caa1681fac09120eca307586e1a7"
+ // Padding block: encryption of {0x10, 0x10, ... 0x10}) (not given by the
+ // NIST test vector)
+ "8cb82807230e1321d3fae00d18cc2012"
+ },
+
+ // F.2.6 CBC-AES256.Decrypt [*]
+ // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ //
+ // [*] Truncated 3 bytes off the plain text, so block 4 differs from the
+ // NIST vector.
+ {
+ // key
+ "603deb1015ca71be2b73aef0857d7781"
+ "1f352c073b6108d72d9810a30914dff4",
+
+ // iv
+ "000102030405060708090a0b0c0d0e0f",
+
+ // plain_text
+ "6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ // Truncated this last block to make it more interesting.
+ "f69f2445df4f9b17ad2b417be6",
+
+ // cipher_text
+ "f58c4c04d6e5f1ba779eabfb5f7bfbd6"
+ "9cfc4e967edb808d679f777bc6702c7d"
+ "39f23369a9d9bacfa530e26304231461"
+ // This block differs from source vector (due to truncation)
+ "c9aaf02a6a54e9e242ccbf48c59daca6"
+ },
+
+ // Taken from encryptor_unittest.cc (EncryptorTest.EmptyEncrypt())
+ {
+ // key
+ "3132383d5369787465656e4279746573",
+
+ // iv
+ "5377656574205369787465656e204956",
+
+ // plain_text
+ "",
+
+ // cipher_text
+ "8518b8878d34e7185e300d0fcc426396"
+ },
+ };
+
+ for (size_t index = 0; index < ARRAYSIZE_UNSAFE(kTests); index++) {
+ SCOPED_TRACE(index);
+ const TestCase& test = kTests[index];
+
+ blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
+ test.key,
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
+ blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
+
+ // Verify exported raw key is identical to the imported data
+ blink::WebArrayBuffer raw_key;
+ EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
+ ExpectArrayBufferMatchesHex(test.key, raw_key);
+
+ std::vector<uint8> plain_text = HexStringToBytes(test.plain_text);
+ std::vector<uint8> iv = HexStringToBytes(test.iv);
+
+ blink::WebArrayBuffer output;
+
+ // Test encryption.
+ EXPECT_TRUE(EncryptInternal(webcrypto::CreateAesCbcAlgorithm(iv),
+ key,
+ plain_text,
+ &output));
+ ExpectArrayBufferMatchesHex(test.cipher_text, output);
+
+ // Test decryption.
+ std::vector<uint8> cipher_text = HexStringToBytes(test.cipher_text);
+ EXPECT_TRUE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv),
+ key,
+ cipher_text,
+ &output));
+ ExpectArrayBufferMatchesHex(test.plain_text, output);
+
+ const unsigned kAesCbcBlockSize = 16;
+
+ // Decrypt with a padding error by stripping the last block. This also ends
+ // up testing decryption over empty cipher text.
+ if (cipher_text.size() >= kAesCbcBlockSize) {
+ EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv),
+ key,
+ &cipher_text[0],
+ cipher_text.size() - kAesCbcBlockSize,
+ &output));
+ }
+
+ // Decrypt cipher text which is not a multiple of block size by stripping
+ // a few bytes off the cipher text.
+ if (cipher_text.size() > 3) {
+ EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv),
+ key,
+ &cipher_text[0],
+ cipher_text.size() - 3,
+ &output));
+ }
+ }
+}
+
+TEST_F(WebCryptoImplTest, GenerateKeyAes) {
+ // Generate a small sample of AES keys.
+ std::vector<blink::WebArrayBuffer> keys;
+ blink::WebArrayBuffer key_bytes;
+ for (int i = 0; i < 16; ++i) {
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ ASSERT_TRUE(
+ GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(128), &key));
+ EXPECT_TRUE(key.handle());
+ EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
+ ASSERT_TRUE(
+ ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &key_bytes));
+ keys.push_back(key_bytes);
+ }
+ // Ensure all entries in the key sample set are unique. This is a simplistic
+ // estimate of whether the generated keys appear random.
+ EXPECT_FALSE(CopiesExist(keys));
+}
+
+TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) {
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ EXPECT_FALSE(
+ GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key));
+ EXPECT_FALSE(
+ GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key));
+ EXPECT_FALSE(
+ GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(129), &key));
+}
+
+TEST_F(WebCryptoImplTest, GenerateKeyHmac) {
+ // Generate a small sample of HMAC keys.
+ std::vector<blink::WebArrayBuffer> keys;
+ for (int i = 0; i < 16; ++i) {
+ blink::WebArrayBuffer key_bytes;
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoAlgorithm algorithm = webcrypto::CreateHmacKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmIdSha1, 128);
+ ASSERT_TRUE(GenerateKeyInternal(algorithm, &key));
+ EXPECT_FALSE(key.isNull());
+ EXPECT_TRUE(key.handle());
+ EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
+ }
+ // Ensure all entries in the key sample set are unique. This is a simplistic
+ // estimate of whether the generated keys appear random.
+ EXPECT_FALSE(CopiesExist(keys));
+}
+
+TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) {
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoAlgorithm algorithm =
+ webcrypto::CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0);
+ ASSERT_TRUE(GenerateKeyInternal(algorithm, &key));
+ EXPECT_TRUE(key.handle());
+ EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
+}
+
+TEST_F(WebCryptoImplTest, ImportSecretKeyNoAlgorithm) {
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+
+ // This fails because the algorithm is null.
+ EXPECT_FALSE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatRaw,
+ HexStringToBytes("00000000000000000000"),
+ blink::WebCryptoAlgorithm::createNull(),
+ true,
+ blink::WebCryptoKeyUsageEncrypt,
+ &key));
+}
+
+#endif //#if !defined(USE_OPENSSL)
+
+TEST_F(WebCryptoImplTest, ImportJwkFailures) {
+
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoAlgorithm algorithm =
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
+ blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
+
+ // Baseline pass: each test below breaks a single item, so we start with a
+ // passing case to make sure each failure is caused by the isolated break.
+ // Each breaking subtest below resets the dictionary to this passing case when
+ // complete.
+ base::DictionaryValue dict;
+ RestoreJwkOctDictionary(&dict);
+ EXPECT_TRUE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+
+ // Fail on empty JSON.
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(""), algorithm, false, usage_mask, &key));
+
+ // Fail on invalid JSON.
+ const std::vector<uint8> bad_json_vec = MakeJsonVector(
+ "{"
+ "\"kty\" : \"oct\","
+ "\"alg\" : \"HS256\","
+ "\"use\" : "
+ );
+ EXPECT_FALSE(ImportKeyJwk(bad_json_vec, algorithm, false, usage_mask, &key));
+
+ // Fail on JWK alg present but unrecognized.
+ dict.SetString("alg", "A127CBC");
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkOctDictionary(&dict);
+
+ // Fail on both JWK and input algorithm missing.
+ dict.Remove("alg", NULL);
+ EXPECT_FALSE(ImportKeyJwk(MakeJsonVector(dict),
+ blink::WebCryptoAlgorithm::createNull(),
+ false,
+ usage_mask,
+ &key));
+ RestoreJwkOctDictionary(&dict);
+
+ // Fail on invalid kty.
+ dict.SetString("kty", "foo");
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkOctDictionary(&dict);
+
+ // Fail on missing kty.
+ dict.Remove("kty", NULL);
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkOctDictionary(&dict);
+
+ // Fail on invalid use.
+ dict.SetString("use", "foo");
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkOctDictionary(&dict);
+}
+
+TEST_F(WebCryptoImplTest, ImportJwkOctFailures) {
+
+ base::DictionaryValue dict;
+ RestoreJwkOctDictionary(&dict);
+ blink::WebCryptoAlgorithm algorithm =
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
+ blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+
+ // Baseline pass.
+ EXPECT_TRUE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ EXPECT_EQ(algorithm.id(), key.algorithm().id());
+ EXPECT_FALSE(key.extractable());
+ EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
+ EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
+
+ // The following are specific failure cases for when kty = "oct".
+
+ // Fail on missing k.
+ dict.Remove("k", NULL);
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkOctDictionary(&dict);
+
+ // Fail on bad b64 encoding for k.
+ dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkOctDictionary(&dict);
+
+ // Fail on empty k.
+ dict.SetString("k", "");
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkOctDictionary(&dict);
+
+ // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg
+ // value (128) for an AES key.
+ dict.SetString("k", "AVj42h0Y5aqGtE3yluKL");
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkOctDictionary(&dict);
+}
+
+#if !defined(USE_OPENSSL)
+
+TEST_F(WebCryptoImplTest, ImportJwkRsaFailures) {
+
+ base::DictionaryValue dict;
+ RestoreJwkRsaDictionary(&dict);
+ blink::WebCryptoAlgorithm algorithm =
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
+ blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+
+ // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
+ // entry, while an RSA private key must have those plus at least a "d"
+ // (private exponent) entry.
+ // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
+ // section 6.3.
+
+ // Baseline pass.
+ EXPECT_TRUE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ EXPECT_EQ(algorithm.id(), key.algorithm().id());
+ EXPECT_FALSE(key.extractable());
+ EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
+ EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
+
+ // The following are specific failure cases for when kty = "RSA".
+
+ // Fail if either "n" or "e" is not present or malformed.
+ const std::string kKtyParmName[] = {"n", "e"};
+ for (size_t idx = 0; idx < ARRAYSIZE_UNSAFE(kKtyParmName); ++idx) {
+
+ // Fail on missing parameter.
+ dict.Remove(kKtyParmName[idx], NULL);
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkRsaDictionary(&dict);
+
+ // Fail on bad b64 parameter encoding.
+ dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkRsaDictionary(&dict);
+
+ // Fail on empty parameter.
+ dict.SetString(kKtyParmName[idx], "");
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkRsaDictionary(&dict);
+ }
+
+ // Fail if "d" parameter is present, implying the JWK is a private key, which
+ // is not supported.
+ dict.SetString("d", "Qk3f0Dsyt");
+ EXPECT_FALSE(ImportKeyJwk(
+ MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ RestoreJwkRsaDictionary(&dict);
+}
+
+#endif // #if !defined(USE_OPENSSL)
+
+TEST_F(WebCryptoImplTest, ImportJwkInputConsistency) {
+ // The Web Crypto spec says that if a JWK value is present, but is
+ // inconsistent with the input value, the operation must fail.
+
+ // Consistency rules when JWK value is not present: Inputs should be used.
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ bool extractable = false;
+ blink::WebCryptoAlgorithm algorithm =
+ webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256);
+ blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify;
+ base::DictionaryValue dict;
+ dict.SetString("kty", "oct");
+ dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
+ std::vector<uint8> json_vec = MakeJsonVector(dict);
+ EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key));
+ EXPECT_TRUE(key.handle());
+ EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
+ EXPECT_EQ(extractable, key.extractable());
+ EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
+ EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
+ key.algorithm().hmacParams()->hash().id());
+ EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
+ key = blink::WebCryptoKey::createNull();
+
+ // Consistency rules when JWK value exists: Fail if inconsistency is found.
+
+ // Pass: All input values are consistent with the JWK values.
+ dict.Clear();
+ dict.SetString("kty", "oct");
+ dict.SetString("alg", "HS256");
+ dict.SetString("use", "sig");
+ dict.SetBoolean("extractable", false);
+ dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
+ json_vec = MakeJsonVector(dict);
+ EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key));
+
+ // Extractable cases:
+ // 1. input=T, JWK=F ==> fail (inconsistent)
+ // 4. input=F, JWK=F ==> pass, result extractable is F
+ // 2. input=T, JWK=T ==> pass, result extractable is T
+ // 3. input=F, JWK=T ==> pass, result extractable is F
+ EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, true, usage_mask, &key));
+ EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
+ EXPECT_FALSE(key.extractable());
+ dict.SetBoolean("extractable", true);
+ EXPECT_TRUE(
+ ImportKeyJwk(MakeJsonVector(dict), algorithm, true, usage_mask, &key));
+ EXPECT_TRUE(key.extractable());
+ EXPECT_TRUE(
+ ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key));
+ EXPECT_FALSE(key.extractable());
+ dict.SetBoolean("extractable", true); // restore previous value
+
+ // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value
+ // (HMAC SHA256).
+ EXPECT_FALSE(ImportKeyJwk(
+ json_vec,
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
+ extractable,
+ usage_mask,
+ &key));
+
+ // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value
+ // (HMAC SHA256).
+ EXPECT_FALSE(ImportKeyJwk(
+ json_vec,
+ webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha1),
+ extractable,
+ usage_mask,
+ &key));
+
+ // Pass: JWK alg valid but input algorithm isNull: use JWK algorithm value.
+ EXPECT_TRUE(ImportKeyJwk(json_vec,
+ blink::WebCryptoAlgorithm::createNull(),
+ extractable,
+ usage_mask,
+ &key));
+ EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
+
+ // Pass: JWK alg missing but input algorithm specified: use input value
+ dict.Remove("alg", NULL);
+ EXPECT_TRUE(ImportKeyJwk(
+ MakeJsonVector(dict),
+ webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256),
+ extractable,
+ usage_mask,
+ &key));
+ EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
+ dict.SetString("alg", "HS256");
+
+ // Fail: Input usage_mask (encrypt) is not a subset of the JWK value
+ // (sign|verify)
+ EXPECT_FALSE(ImportKeyJwk(
+ json_vec, algorithm, extractable, blink::WebCryptoKeyUsageEncrypt, &key));
+
+ // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK
+ // value (sign|verify)
+ usage_mask = blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageSign |
+ blink::WebCryptoKeyUsageVerify;
+ EXPECT_FALSE(
+ ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key));
+ usage_mask = blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
+
+ // TODO(padolph): kty vs alg consistency tests: Depending on the kty value,
+ // only certain alg values are permitted. For example, when kty = "RSA" alg
+ // must be of the RSA family, or when kty = "oct" alg must be symmetric
+ // algorithm.
+}
+
+TEST_F(WebCryptoImplTest, ImportJwkHappy) {
+
+ // This test verifies the happy path of JWK import, including the application
+ // of the imported key material.
+
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ bool extractable = false;
+ blink::WebCryptoAlgorithm algorithm =
+ webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256);
+ blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageSign;
+
+ // Import a symmetric key JWK and HMAC-SHA256 sign()
+ // Uses the first SHA256 test vector from the HMAC sample set above.
+
+ base::DictionaryValue dict;
+ dict.SetString("kty", "oct");
+ dict.SetString("alg", "HS256");
+ dict.SetString("use", "sig");
+ dict.SetBoolean("extractable", false);
+ dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
+ std::vector<uint8> json_vec = MakeJsonVector(dict);
+
+ ASSERT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key));
+
+ const std::vector<uint8> message_raw = HexStringToBytes(
+ "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
+ "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
+ "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
+ "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e");
+
+ blink::WebArrayBuffer output;
+
+ ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output));
+
+ const std::string mac_raw =
+ "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b";
+
+ ExpectArrayBufferMatchesHex(mac_raw, output);
+
+ // TODO(padolph): Import an RSA public key JWK and use it
+}
+
+#if !defined(USE_OPENSSL)
+
+TEST_F(WebCryptoImplTest, ImportExportSpki) {
+ // openssl genrsa -out pair.pem 2048
+ // openssl rsa -in pair.pem -out pubkey.der -outform DER -pubout
+ // xxd -p pubkey.der
+ const std::string hex_rsa_spki_der =
+ "30820122300d06092a864886f70d01010105000382010f003082010a0282"
+ "010100f19e40f94e3780858701577a571cca000cb9795db89ddf8e98ab0e"
+ "5eecfa47516cb08dc591cae5ab7fa43d6db402e95991d4a2de52e7cd3a66"
+ "4f58284be2eb4675d5a849a2582c585d2b3c6c225a8f2c53a0414d5dbd06"
+ "172371cefdf953e9ec3000fc9ad000743023f74e82d12aa93917a2c9b832"
+ "696085ee0711154cf98a6d098f44cee00ea3b7584236503a5483ba8b6792"
+ "fee588d1a8f4a0618333c4cb3447d760b43d5a0d9ed6ef79763df670cd8b"
+ "5eb869a20833f1e3e6d8b88240a5d4335c73fd20487f2a7d112af8692357"
+ "6425e44a273e5ad2e93d6b50a28e65f9e133958e4f0c7d12e0adc90fedd4"
+ "f6b6848e7b6900666642a08b520a6534a35d4f0203010001";
+
+ // Passing case: Import a valid RSA key in SPKI format.
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ ASSERT_TRUE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatSpki,
+ HexStringToBytes(hex_rsa_spki_der),
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
+ true,
+ blink::WebCryptoKeyUsageEncrypt,
+ &key));
+ EXPECT_TRUE(key.handle());
+ EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
+ EXPECT_TRUE(key.extractable());
+ EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
+
+ // Failing case: Empty SPKI data
+ EXPECT_FALSE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatSpki,
+ std::vector<uint8>(),
+ blink::WebCryptoAlgorithm::createNull(),
+ true,
+ blink::WebCryptoKeyUsageEncrypt,
+ &key));
+
+ // Failing case: Import RSA key with NULL input algorithm. This is not
+ // allowed because the SPKI ASN.1 format for RSA keys is not specific enough
+ // to map to a Web Crypto algorithm.
+ EXPECT_FALSE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatSpki,
+ HexStringToBytes(hex_rsa_spki_der),
+ blink::WebCryptoAlgorithm::createNull(),
+ true,
+ blink::WebCryptoKeyUsageEncrypt,
+ &key));
+
+ // Failing case: Bad DER encoding.
+ EXPECT_FALSE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatSpki,
+ HexStringToBytes("618333c4cb"),
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
+ true,
+ blink::WebCryptoKeyUsageEncrypt,
+ &key));
+
+ // Failing case: Import RSA key but provide an inconsistent input algorithm.
+ EXPECT_FALSE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatSpki,
+ HexStringToBytes(hex_rsa_spki_der),
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
+ true,
+ blink::WebCryptoKeyUsageEncrypt,
+ &key));
+
+ // Passing case: Export a previously imported RSA public key in SPKI format
+ // and compare to original data.
+ blink::WebArrayBuffer output;
+ ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
+ ExpectArrayBufferMatchesHex(hex_rsa_spki_der, output);
+
+ // Failing case: Try to export a previously imported RSA public key in raw
+ // format (not allowed for a public key).
+ EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &output));
+
+ // Failing case: Try to export a non-extractable key
+ ASSERT_TRUE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatSpki,
+ HexStringToBytes(hex_rsa_spki_der),
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
+ false,
+ blink::WebCryptoKeyUsageEncrypt,
+ &key));
+ EXPECT_TRUE(key.handle());
+ EXPECT_FALSE(key.extractable());
+ EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
+}
+
+TEST_F(WebCryptoImplTest, ImportPkcs8) {
+
+ // The following is a DER-encoded PKCS#8 representation of the RSA key from
+ // Example 1 of NIST's "Test vectors for RSA PKCS#1 v1.5 Signature".
+ // ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt
+ const std::string hex_rsa_pkcs8_der =
+ "30820275020100300D06092A864886F70D01010105000482025F3082025B020100028181"
+ "00A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C510"
+ "56FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B"
+ "2B8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E1"
+ "386B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137020301000102818033A5042A90B27D"
+ "4F5451CA9BBBD0B44771A101AF884340AEF9885F2A4BBE92E894A724AC3C568C8F97853A"
+ "D07C0266C8C6A3CA0929F1E8F11231884429FC4D9AE55FEE896A10CE707C3ED7E734E447"
+ "27A39574501A532683109C2ABACABA283C31B4BD2F53C3EE37E352CEE34F9E503BD80C06"
+ "22AD79C6DCEE883547C6A3B325024100E7E8942720A877517273A356053EA2A1BC0C94AA"
+ "72D55C6E86296B2DFC967948C0A72CBCCCA7EACB35706E09A1DF55A1535BD9B3CC34160B"
+ "3B6DCD3EDA8E6443024100B69DCA1CF7D4D7EC81E75B90FCCA874ABCDE123FD2700180AA"
+ "90479B6E48DE8D67ED24F9F19D85BA275874F542CD20DC723E6963364A1F9425452B269A"
+ "6799FD024028FA13938655BE1F8A159CBACA5A72EA190C30089E19CD274A556F36C4F6E1"
+ "9F554B34C077790427BBDD8DD3EDE2448328F385D81B30E8E43B2FFFA02786197902401A"
+ "8B38F398FA712049898D7FB79EE0A77668791299CDFA09EFC0E507ACB21ED74301EF5BFD"
+ "48BE455EAEB6E1678255827580A8E4E8E14151D1510A82A3F2E729024027156ABA4126D2"
+ "4A81F3A528CBFB27F56886F840A9F6E86E17A44B94FE9319584B8E22FDDE1E5A2E3BD8AA"
+ "5BA8D8584194EB2190ACF832B847F13A3D24A79F4D";
+
+ // Passing case: Import a valid RSA key in PKCS#8 format.
+ blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+ ASSERT_TRUE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatPkcs8,
+ HexStringToBytes(hex_rsa_pkcs8_der),
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
+ true,
+ blink::WebCryptoKeyUsageSign,
+ &key));
+ EXPECT_TRUE(key.handle());
+ EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type());
+ EXPECT_TRUE(key.extractable());
+ EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
+
+ // Failing case: Empty PKCS#8 data
+ EXPECT_FALSE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatPkcs8,
+ std::vector<uint8>(),
+ blink::WebCryptoAlgorithm::createNull(),
+ true,
+ blink::WebCryptoKeyUsageSign,
+ &key));
+
+ // Failing case: Import RSA key with NULL input algorithm. This is not
+ // allowed because the PKCS#8 ASN.1 format for RSA keys is not specific enough
+ // to map to a Web Crypto algorithm.
+ EXPECT_FALSE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatPkcs8,
+ HexStringToBytes(hex_rsa_pkcs8_der),
+ blink::WebCryptoAlgorithm::createNull(),
+ true,
+ blink::WebCryptoKeyUsageSign,
+ &key));
+
+ // Failing case: Bad DER encoding.
+ EXPECT_FALSE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatPkcs8,
+ HexStringToBytes("618333c4cb"),
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
+ true,
+ blink::WebCryptoKeyUsageSign,
+ &key));
+
+ // Failing case: Import RSA key but provide an inconsistent input algorithm.
+ EXPECT_FALSE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatPkcs8,
+ HexStringToBytes(hex_rsa_pkcs8_der),
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
+ true,
+ blink::WebCryptoKeyUsageSign,
+ &key));
+}
+
+TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) {
+ // Note: using unrealistic short key lengths here to avoid bogging down tests.
+
+ // Successful WebCryptoAlgorithmIdRsaEsPkcs1v1_5 key generation.
+ const unsigned modulus_length = 256;
+ const std::vector<uint8> public_exponent = HexStringToBytes("010001");
+ blink::WebCryptoAlgorithm algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ modulus_length,
+ public_exponent);
+ bool extractable = false;
+ const blink::WebCryptoKeyUsageMask usage_mask = 0;
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
+ EXPECT_TRUE(GenerateKeyPairInternal(
+ algorithm, extractable, usage_mask, &public_key, &private_key));
+ EXPECT_FALSE(public_key.isNull());
+ EXPECT_FALSE(private_key.isNull());
+ EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
+ EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
+ EXPECT_EQ(true, public_key.extractable());
+ EXPECT_EQ(extractable, private_key.extractable());
+ EXPECT_EQ(usage_mask, public_key.usages());
+ EXPECT_EQ(usage_mask, private_key.usages());
+
+ // Fail with bad modulus.
+ algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 0, public_exponent);
+ EXPECT_FALSE(GenerateKeyPairInternal(
+ algorithm, extractable, usage_mask, &public_key, &private_key));
+
+ // Fail with bad exponent: larger than unsigned long.
+ unsigned exponent_length = sizeof(unsigned long) + 1; // NOLINT
+ const std::vector<uint8> long_exponent(exponent_length, 0x01);
+ algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, modulus_length, long_exponent);
+ EXPECT_FALSE(GenerateKeyPairInternal(
+ algorithm, extractable, usage_mask, &public_key, &private_key));
+
+ // Fail with bad exponent: empty.
+ const std::vector<uint8> empty_exponent;
+ algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ modulus_length,
+ empty_exponent);
+ EXPECT_FALSE(GenerateKeyPairInternal(
+ algorithm, extractable, usage_mask, &public_key, &private_key));
+
+ // Fail with bad exponent: all zeros.
+ std::vector<uint8> exponent_with_leading_zeros(15, 0x00);
+ algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ modulus_length,
+ exponent_with_leading_zeros);
+ EXPECT_FALSE(GenerateKeyPairInternal(
+ algorithm, extractable, usage_mask, &public_key, &private_key));
+
+ // Key generation success using exponent with leading zeros.
+ exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
+ public_exponent.begin(),
+ public_exponent.end());
+ algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ modulus_length,
+ exponent_with_leading_zeros);
+ EXPECT_TRUE(GenerateKeyPairInternal(
+ algorithm, extractable, usage_mask, &public_key, &private_key));
+ EXPECT_FALSE(public_key.isNull());
+ EXPECT_FALSE(private_key.isNull());
+ EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
+ EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
+ EXPECT_EQ(true, public_key.extractable());
+ EXPECT_EQ(extractable, private_key.extractable());
+ EXPECT_EQ(usage_mask, public_key.usages());
+ EXPECT_EQ(usage_mask, private_key.usages());
+
+ // Successful WebCryptoAlgorithmIdRsaOaep key generation.
+ algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaOaep, modulus_length, public_exponent);
+ EXPECT_TRUE(GenerateKeyPairInternal(
+ algorithm, extractable, usage_mask, &public_key, &private_key));
+ EXPECT_FALSE(public_key.isNull());
+ EXPECT_FALSE(private_key.isNull());
+ EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
+ EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
+ EXPECT_EQ(true, public_key.extractable());
+ EXPECT_EQ(extractable, private_key.extractable());
+ EXPECT_EQ(usage_mask, public_key.usages());
+ EXPECT_EQ(usage_mask, private_key.usages());
+
+ // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation.
+ algorithm = webcrypto::CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
+ modulus_length,
+ public_exponent);
+ EXPECT_TRUE(GenerateKeyPairInternal(
+ algorithm, extractable, usage_mask, &public_key, &private_key));
+ EXPECT_FALSE(public_key.isNull());
+ EXPECT_FALSE(private_key.isNull());
+ EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
+ EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
+ EXPECT_EQ(true, public_key.extractable());
+ EXPECT_EQ(extractable, private_key.extractable());
+ EXPECT_EQ(usage_mask, public_key.usages());
+ EXPECT_EQ(usage_mask, private_key.usages());
+
+ // Fail SPKI export of private key. This is an ExportKey test, but do it here
+ // since it is expensive to generate an RSA key pair and we already have a
+ // private key here.
+ blink::WebArrayBuffer output;
+ EXPECT_FALSE(
+ ExportKeyInternal(blink::WebCryptoKeyFormatSpki, private_key, &output));
+}
+
+TEST_F(WebCryptoImplTest, RsaEsRoundTrip) {
+ // Note: using unrealistic short key length here to avoid bogging down tests.
+
+ // Create a key pair.
+ const unsigned kModulusLength = 256;
+ blink::WebCryptoAlgorithm algorithm =
+ CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ kModulusLength,
+ HexStringToBytes("010001"));
+ const blink::WebCryptoKeyUsageMask usage_mask =
+ blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt;
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
+ EXPECT_TRUE(GenerateKeyPairInternal(
+ algorithm, false, usage_mask, &public_key, &private_key));
+ EXPECT_FALSE(public_key.isNull());
+ EXPECT_FALSE(private_key.isNull());
+
+ // Make a maximum-length data message. RSAES can operate on messages up to
+ // length of k - 11 bytes, where k is the octet length of the RSA modulus.
+ const unsigned kMaxMsgSizeBytes = kModulusLength / 8 - 11;
+ // There are two hex chars for each byte.
+ const unsigned kMsgHexSize = kMaxMsgSizeBytes * 2;
+ char max_data_hex[kMsgHexSize+1];
+ std::fill(&max_data_hex[0], &max_data_hex[0] + kMsgHexSize, 'a');
+ max_data_hex[kMsgHexSize] = '\0';
+
+ // Verify encrypt / decrypt round trip on a few messages. Note that RSA
+ // encryption does not support empty input.
+ algorithm =
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
+ const char* const kTestDataHex[] = {
+ "ff",
+ "0102030405060708090a0b0c0d0e0f",
+ max_data_hex
+ };
+ blink::WebArrayBuffer encrypted_data;
+ blink::WebArrayBuffer decrypted_data;
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestDataHex); ++i) {
+ SCOPED_TRACE(i);
+ ASSERT_TRUE(EncryptInternal(
+ algorithm,
+ public_key,
+ HexStringToBytes(kTestDataHex[i]),
+ &encrypted_data));
+ EXPECT_EQ(kModulusLength/8, encrypted_data.byteLength());
+ ASSERT_TRUE(DecryptInternal(
+ algorithm,
+ private_key,
+ reinterpret_cast<const unsigned char*>(encrypted_data.data()),
+ encrypted_data.byteLength(),
+ &decrypted_data));
+ ExpectArrayBufferMatchesHex(kTestDataHex[i], decrypted_data);
+ }
+}
+
+TEST_F(WebCryptoImplTest, RsaEsKnownAnswer) {
+ // Because the random data in PKCS1.5 padding makes the encryption output non-
+ // deterministic, we cannot easily do a typical known-answer test for RSA
+ // encryption / decryption. Instead we will take a known-good encrypted
+ // message, decrypt it, re-encrypt it, then decrypt again, verifying that the
+ // original known cleartext is the result.
+
+ // The RSA public and private keys used for this test are produced by the
+ // openssl command line:
+ // % openssl genrsa -out pair.pem 1024
+ // % openssl rsa -in pair.pem -out spki.der -outform DER -pubout
+ // % openssl pkcs8 -topk8 -inform PEM -outform DER -in pair.pem -out
+ // pkcs8.der -nocrypt
+ // % xxd -p spki.der
+ // % xxd -p pkcs8.der
+ const std::string rsa_spki_der_hex =
+ "30819f300d06092a864886f70d010101050003818d0030818902818100a8"
+ "d30894b93f376f7822229bfd2483e50da944c4ab803ca31979e0f47e70bf"
+ "683c687c6b3e80f280a237cea3643fd1f7f10f7cc664dbc2ecd45be53e1c"
+ "9b15a53c37dbdad846c0f8340c472abc7821e4aa7df185867bf38228ac3e"
+ "cc1d97d3c8b57e21ea6ba57b2bc3814a436e910ee8ab64a0b7743a927e94"
+ "4d3420401f7dd50203010001";
+ const std::string rsa_pkcs8_der_hex =
+ "30820276020100300d06092a864886f70d0101010500048202603082025c"
+ "02010002818100a8d30894b93f376f7822229bfd2483e50da944c4ab803c"
+ "a31979e0f47e70bf683c687c6b3e80f280a237cea3643fd1f7f10f7cc664"
+ "dbc2ecd45be53e1c9b15a53c37dbdad846c0f8340c472abc7821e4aa7df1"
+ "85867bf38228ac3ecc1d97d3c8b57e21ea6ba57b2bc3814a436e910ee8ab"
+ "64a0b7743a927e944d3420401f7dd5020301000102818100896cdffb50a0"
+ "691bd00ad9696933243a7c5861a64684e8d74b91aed0d76c28234da9303e"
+ "8c6ea2f89b141a9d5ea9a4ddd3d8eb9503dcf05ba0b1fd76060b281e3ae4"
+ "b9d497fb5519bdf1127db8ad412d6a722686c78df3e3002acca960c6b2a2"
+ "42a83ace5410693c03ce3d74cb9c9a7bacc8e271812920d1f53fee9312ef"
+ "4eb1024100d09c14418ce92af7cc62f7cdc79836d8c6e3d0d33e7229cc11"
+ "d732cbac75aa4c56c92e409a3ccbe75d4ce63ac5adca33080690782c6371"
+ "e3628134c3534ca603024100cf2d3206f6deea2f39b70351c51f85436200"
+ "5aa8f643e49e22486736d536e040dc30a2b4f9be3ab212a88d1891280874"
+ "b9a170cdeb22eaf61c27c4b082c7d1470240638411a5b3b307ec6e744802"
+ "c2d4ba556f8bfe72c7b76e790b89bd91ac13f5c9b51d04138d80b3450c1d"
+ "4337865601bf96748b36c8f627be719f71ac3c70b441024065ce92cfe34e"
+ "a58bf173a2b8f3024b4d5282540ac581957db3e11a7f528535ec098808dc"
+ "a0013ffcb3b88a25716757c86c540e07d2ad8502cdd129118822c30f0240"
+ "420a4983040e9db46eb29f1315a0d7b41cf60428f7460fce748e9a1a7d22"
+ "d7390fa328948e7e9d1724401374e99d45eb41474781201378a4330e8e80"
+ "8ce63551";
+
+ // Similarly, the cleartext and public key encrypted ciphertext for this test
+ // are also produced by openssl. Note that since we are using a 1024-bit key,
+ // the cleartext size must be less than or equal to 117 bytes (modulusLength /
+ // 8 - 11).
+ // % openssl rand -out cleartext.bin 64
+ // % openssl rsautl -encrypt -inkey spki.der -keyform DER -pubin -in
+ // cleartext.bin -out ciphertext.bin
+ // % xxd -p cleartext.bin
+ // % xxd -p ciphertext.bin
+ const std::string cleartext_hex =
+ "ec358ed141c45d7e03d4c6338aebad718e8bcbbf8f8ee6f8d9f4b9ef06d8"
+ "84739a398c6bcbc688418b2ff64761dc0ccd40e7d52bed03e06946d0957a"
+ "eef9e822";
+ const std::string ciphertext_hex =
+ "6106441c2b7a4b1a16260ed1ae4fe6135247345dc8e674754bbda6588c6c"
+ "0d95a3d4d26bb34cdbcbe327723e80343bd7a15cd4c91c3a44e6cb9c6cd6"
+ "7ad2e8bf41523188d9b36dc364a838642dcbc2c25e85dfb2106ba47578ca"
+ "3bbf8915055aea4fa7c3cbfdfbcc163f04c234fb6d847f39bab9612ecbee"
+ "04626e945c3ccf42";
+
+ // Import the public key.
+ const blink::WebCryptoAlgorithm algorithm =
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ ASSERT_TRUE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatSpki,
+ HexStringToBytes(rsa_spki_der_hex),
+ algorithm,
+ true,
+ blink::WebCryptoKeyUsageEncrypt,
+ &public_key));
+ EXPECT_FALSE(public_key.isNull());
+ EXPECT_TRUE(public_key.handle());
+
+ // Import the private key.
+ blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
+ ASSERT_TRUE(ImportKeyInternal(
+ blink::WebCryptoKeyFormatPkcs8,
+ HexStringToBytes(rsa_pkcs8_der_hex),
+ algorithm,
+ true,
+ blink::WebCryptoKeyUsageDecrypt,
+ &private_key));
+ EXPECT_FALSE(private_key.isNull());
+ EXPECT_TRUE(private_key.handle());
+
+ // Decrypt the known-good ciphertext with the private key. As a check we must
+ // get the known original cleartext.
+ blink::WebArrayBuffer decrypted_data;
+ ASSERT_TRUE(DecryptInternal(
+ algorithm,
+ private_key,
+ HexStringToBytes(ciphertext_hex),
+ &decrypted_data));
+ EXPECT_FALSE(decrypted_data.isNull());
+ ExpectArrayBufferMatchesHex(cleartext_hex, decrypted_data);
+
+ // Encrypt this decrypted data with the public key.
+ blink::WebArrayBuffer encrypted_data;
+ ASSERT_TRUE(EncryptInternal(
+ algorithm,
+ public_key,
+ reinterpret_cast<const unsigned char*>(decrypted_data.data()),
+ decrypted_data.byteLength(),
+ &encrypted_data));
+ EXPECT_EQ(128u, encrypted_data.byteLength());
+
+ // Finally, decrypt the newly encrypted result with the private key, and
+ // compare to the known original cleartext.
+ decrypted_data.reset();
+ ASSERT_TRUE(DecryptInternal(
+ algorithm,
+ private_key,
+ reinterpret_cast<const unsigned char*>(encrypted_data.data()),
+ encrypted_data.byteLength(),
+ &decrypted_data));
+ EXPECT_FALSE(decrypted_data.isNull());
+ ExpectArrayBufferMatchesHex(cleartext_hex, decrypted_data);
+}
+
+TEST_F(WebCryptoImplTest, RsaEsFailures) {
+ // Note: using unrealistic short key length here to avoid bogging down tests.
+
+ // Create a key pair.
+ const unsigned kModulusLength = 256;
+ blink::WebCryptoAlgorithm algorithm =
+ CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ kModulusLength,
+ HexStringToBytes("010001"));
+ const blink::WebCryptoKeyUsageMask usage_mask =
+ blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt;
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
+ EXPECT_TRUE(GenerateKeyPairInternal(
+ algorithm, false, usage_mask, &public_key, &private_key));
+ EXPECT_FALSE(public_key.isNull());
+ EXPECT_FALSE(private_key.isNull());
+
+ // Fail encrypt with a private key.
+ algorithm =
+ webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
+ blink::WebArrayBuffer encrypted_data;
+ const std::string message_hex_str("0102030405060708090a0b0c0d0e0f");
+ const std::vector<uint8> message_hex(HexStringToBytes(message_hex_str));
+ EXPECT_FALSE(
+ EncryptInternal(algorithm, private_key, message_hex, &encrypted_data));
+
+ // Fail encrypt with empty message.
+ EXPECT_FALSE(EncryptInternal(
+ algorithm, public_key, std::vector<uint8>(), &encrypted_data));
+
+ // Fail encrypt with message too large. RSAES can operate on messages up to
+ // length of k - 11 bytes, where k is the octet length of the RSA modulus.
+ const unsigned kMaxMsgSizeBytes = kModulusLength / 8 - 11;
+ EXPECT_FALSE(EncryptInternal(algorithm,
+ public_key,
+ std::vector<uint8>(kMaxMsgSizeBytes + 1, '0'),
+ &encrypted_data));
+
+ // Generate encrypted data.
+ EXPECT_TRUE(
+ EncryptInternal(algorithm, public_key, message_hex, &encrypted_data));
+
+ // Fail decrypt with a public key.
+ blink::WebArrayBuffer decrypted_data;
+ EXPECT_FALSE(DecryptInternal(
+ algorithm,
+ public_key,
+ reinterpret_cast<const unsigned char*>(encrypted_data.data()),
+ encrypted_data.byteLength(),
+ &decrypted_data));
+
+ // Corrupt encrypted data; ensure decrypt fails because padding was disrupted.
+ std::vector<uint8> corrupted_data(
+ static_cast<uint8*>(encrypted_data.data()),
+ static_cast<uint8*>(encrypted_data.data()) + encrypted_data.byteLength());
+ corrupted_data[corrupted_data.size() / 2] ^= 0x01;
+ EXPECT_FALSE(
+ DecryptInternal(algorithm, private_key, corrupted_data, &decrypted_data));
+
+ // TODO(padolph): Are there other specific data corruption scenarios to
+ // consider?
+
+ // Do a successful decrypt with good data just for confirmation.
+ EXPECT_TRUE(DecryptInternal(
+ algorithm,
+ private_key,
+ reinterpret_cast<const unsigned char*>(encrypted_data.data()),
+ encrypted_data.byteLength(),
+ &decrypted_data));
+ ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data);
+}
+
+#endif // #if !defined(USE_OPENSSL)
+
+} // namespace content
diff --git a/chromium/content/renderer/webcrypto/webcrypto_util.cc b/chromium/content/renderer/webcrypto/webcrypto_util.cc
new file mode 100644
index 00000000000..b5a318a1be2
--- /dev/null
+++ b/chromium/content/renderer/webcrypto/webcrypto_util.cc
@@ -0,0 +1,205 @@
+// 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/webcrypto/webcrypto_util.h"
+
+#include "base/base64.h"
+#include "base/logging.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+blink::WebCryptoAlgorithm CreateAesKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmId aes_alg_id,
+ unsigned short length) {
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
+ aes_alg_id, new blink::WebCryptoAesKeyGenParams(length));
+}
+
+bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) {
+ return alg_id == blink::WebCryptoAlgorithmIdSha1 ||
+ alg_id == blink::WebCryptoAlgorithmIdSha224 ||
+ alg_id == blink::WebCryptoAlgorithmIdSha256 ||
+ alg_id == blink::WebCryptoAlgorithmIdSha384 ||
+ alg_id == blink::WebCryptoAlgorithmIdSha512;
+}
+
+} // namespace
+
+const uint8* Uint8VectorStart(const std::vector<uint8>& data) {
+ if (data.empty())
+ return NULL;
+ return &data[0];
+}
+
+void ShrinkBuffer(blink::WebArrayBuffer* buffer, unsigned new_size) {
+ DCHECK_LE(new_size, buffer->byteLength());
+
+ if (new_size == buffer->byteLength())
+ return;
+
+ blink::WebArrayBuffer new_buffer = blink::WebArrayBuffer::create(new_size, 1);
+ DCHECK(!new_buffer.isNull());
+ memcpy(new_buffer.data(), buffer->data(), new_size);
+ *buffer = new_buffer;
+}
+
+blink::WebArrayBuffer CreateArrayBuffer(const uint8* data, unsigned data_size) {
+ blink::WebArrayBuffer buffer = blink::WebArrayBuffer::create(data_size, 1);
+ DCHECK(!buffer.isNull());
+ if (data_size) // data_size == 0 might mean the data pointer is invalid
+ memcpy(buffer.data(), data, data_size);
+ return buffer;
+}
+
+// This function decodes unpadded 'base64url' encoded data, as described in
+// RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5. To do this, first
+// change the incoming data to 'base64' encoding by applying the appropriate
+// transformation including adding padding if required, and then call a base64
+// decoder.
+bool Base64DecodeUrlSafe(const std::string& input, std::string* output) {
+ std::string base64EncodedText(input);
+ std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+');
+ std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/');
+ base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '=');
+ return base::Base64Decode(base64EncodedText, output);
+}
+
+blink::WebCryptoAlgorithm GetInnerHashAlgorithm(
+ const blink::WebCryptoAlgorithm& algorithm) {
+ if (algorithm.hmacParams())
+ return algorithm.hmacParams()->hash();
+ if (algorithm.hmacKeyParams())
+ return algorithm.hmacKeyParams()->hash();
+ if (algorithm.rsaSsaParams())
+ return algorithm.rsaSsaParams()->hash();
+ if (algorithm.rsaOaepParams())
+ return algorithm.rsaOaepParams()->hash();
+ return blink::WebCryptoAlgorithm::createNull();
+}
+
+blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) {
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL);
+}
+
+blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashOutputLen(
+ unsigned short hash_output_length_bits) {
+ blink::WebCryptoAlgorithmId hash_id;
+ switch (hash_output_length_bits) {
+ case 160:
+ hash_id = blink::WebCryptoAlgorithmIdSha1;
+ break;
+ case 224:
+ hash_id = blink::WebCryptoAlgorithmIdSha224;
+ break;
+ case 256:
+ hash_id = blink::WebCryptoAlgorithmIdSha256;
+ break;
+ case 384:
+ hash_id = blink::WebCryptoAlgorithmIdSha384;
+ break;
+ case 512:
+ hash_id = blink::WebCryptoAlgorithmIdSha512;
+ break;
+ default:
+ NOTREACHED();
+ return blink::WebCryptoAlgorithm::createNull();
+ }
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
+ blink::WebCryptoAlgorithmIdHmac,
+ new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id)));
+}
+
+blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashId(
+ blink::WebCryptoAlgorithmId hash_id) {
+ DCHECK(IsHashAlgorithm(hash_id));
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
+ blink::WebCryptoAlgorithmIdHmac,
+ new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id)));
+}
+
+blink::WebCryptoAlgorithm CreateHmacKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmId hash_id,
+ unsigned key_length_bytes) {
+ DCHECK(IsHashAlgorithm(hash_id));
+ // key_length_bytes == 0 means unspecified
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
+ blink::WebCryptoAlgorithmIdHmac,
+ new blink::WebCryptoHmacKeyParams(
+ CreateAlgorithm(hash_id), (key_length_bytes != 0), key_length_bytes));
+}
+
+blink::WebCryptoAlgorithm CreateRsaSsaAlgorithm(
+ blink::WebCryptoAlgorithmId hash_id) {
+ DCHECK(IsHashAlgorithm(hash_id));
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
+ blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
+ new blink::WebCryptoRsaSsaParams(CreateAlgorithm(hash_id)));
+}
+
+blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm(
+ blink::WebCryptoAlgorithmId hash_id) {
+ DCHECK(IsHashAlgorithm(hash_id));
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
+ blink::WebCryptoAlgorithmIdRsaOaep,
+ new blink::WebCryptoRsaOaepParams(
+ CreateAlgorithm(hash_id), false, NULL, 0));
+}
+
+blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmId algorithm_id,
+ unsigned modulus_length,
+ const std::vector<uint8>& public_exponent) {
+ DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
+ algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
+ algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep);
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
+ algorithm_id,
+ new blink::WebCryptoRsaKeyGenParams(
+ modulus_length,
+ webcrypto::Uint8VectorStart(public_exponent),
+ public_exponent.size()));
+}
+
+blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(const std::vector<uint8>& iv) {
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
+ blink::WebCryptoAlgorithmIdAesCbc,
+ new blink::WebCryptoAesCbcParams(Uint8VectorStart(iv), iv.size()));
+}
+
+blink::WebCryptoAlgorithm CreateAesGcmAlgorithm(
+ const std::vector<uint8>& iv,
+ const std::vector<uint8>& additional_data,
+ uint8 tag_length_bytes) {
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
+ blink::WebCryptoAlgorithmIdAesCbc,
+ new blink::WebCryptoAesGcmParams(Uint8VectorStart(iv),
+ iv.size(),
+ additional_data.size() != 0,
+ Uint8VectorStart(additional_data),
+ additional_data.size(),
+ tag_length_bytes != 0,
+ tag_length_bytes));
+}
+
+blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm(
+ unsigned short key_length_bits) {
+ return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc,
+ key_length_bits);
+}
+
+blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm(
+ unsigned short key_length_bits) {
+ return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm,
+ key_length_bits);
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/renderer/webcrypto/webcrypto_util.h b/chromium/content/renderer/webcrypto/webcrypto_util.h
new file mode 100644
index 00000000000..022b3c29fb7
--- /dev/null
+++ b/chromium/content/renderer/webcrypto/webcrypto_util.h
@@ -0,0 +1,107 @@
+// 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_RENDERER_WEBCRYPTO_WEBCRYPTO_UTIL_H_
+#define CONTENT_RENDERER_WEBCRYPTO_WEBCRYPTO_UTIL_H_
+
+#include <map>
+#include <string>
+#include <vector>
+#include "base/basictypes.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebArrayBuffer.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+// Returns a pointer to the start of |data|, or NULL if it is empty. This is a
+// convenience function for getting the pointer, and should not be used beyond
+// the expected lifetime of |data|.
+CONTENT_EXPORT const uint8* Uint8VectorStart(const std::vector<uint8>& data);
+
+// Shrinks a WebArrayBuffer to a new size.
+// TODO(eroman): This works by re-allocating a new buffer. It would be better if
+// the WebArrayBuffer could just be truncated instead.
+void ShrinkBuffer(blink::WebArrayBuffer* buffer, unsigned new_size);
+
+// Creates a WebArrayBuffer from a uint8 byte array
+blink::WebArrayBuffer CreateArrayBuffer(const uint8* data, unsigned data_size);
+
+// This function decodes unpadded 'base64url' encoded data, as described in
+// RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5.
+// In Web Crypto, this type of encoding is only used inside JWK.
+bool Base64DecodeUrlSafe(const std::string& input, std::string* output);
+
+// Returns the "hash" param for an algorithm if it exists, otherwise returns
+// a null algorithm.
+blink::WebCryptoAlgorithm GetInnerHashAlgorithm(
+ const blink::WebCryptoAlgorithm& algorithm);
+
+// Creates a WebCryptoAlgorithm without any parameters.
+CONTENT_EXPORT blink::WebCryptoAlgorithm CreateAlgorithm(
+ blink::WebCryptoAlgorithmId id);
+
+// Creates an HMAC algorithm whose inner hash algorithm is determined by the
+// specified hash output length. It is an error to call this method with an
+// unsupported hash output length.
+blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashOutputLen(
+ unsigned short hash_output_length_bits);
+
+// Creates an HMAC algorithm whose inner hash algorithm is determined by the
+// specified algorithm ID. It is an error to call this method with a hash
+// algorithm that is not SHA*.
+CONTENT_EXPORT blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashId(
+ blink::WebCryptoAlgorithmId hash_id);
+
+// Creates an HMAC algorithm whose parameters struct is compatible with key
+// generation. It is an error to call this with a hash_id that is not a SHA*.
+// The key_length_bytes parameter is optional, with zero meaning unspecified.
+CONTENT_EXPORT blink::WebCryptoAlgorithm CreateHmacKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmId hash_id,
+ unsigned key_length_bytes);
+
+// Creates an RSASSA-PKCS1-v1_5 algorithm. It is an error to call this with a
+// hash_id that is not a SHA*.
+blink::WebCryptoAlgorithm CreateRsaSsaAlgorithm(
+ blink::WebCryptoAlgorithmId hash_id);
+
+// Creates an RSA-OAEP algorithm. It is an error to call this with a hash_id
+// that is not a SHA*.
+blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm(
+ blink::WebCryptoAlgorithmId hash_id);
+
+// Creates an RSA algorithm with ID algorithm_id, whose parameters struct is
+// compatible with key generation.
+CONTENT_EXPORT blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmId algorithm_id,
+ unsigned modulus_length,
+ const std::vector<uint8>& public_exponent);
+
+// Creates an AES-CBC algorithm.
+CONTENT_EXPORT blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(
+ const std::vector<uint8>& iv);
+
+// Creates and AES-GCM algorithm.
+blink::WebCryptoAlgorithm CreateAesGcmAlgorithm(
+ const std::vector<uint8>& iv,
+ const std::vector<uint8>& additional_data,
+ uint8 tag_length_bytes);
+
+// Creates an AES-CBC algorithm whose parameters struct is compatible with key
+// generation.
+CONTENT_EXPORT blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm(
+ unsigned short key_length_bits);
+
+// Creates an AES-GCM algorithm whose parameters struct is compatible with key
+// generation.
+blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm(
+ unsigned short key_length_bits);
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_WEBCRYPTO_WEBCRYPTO_UTIL_H_
diff --git a/chromium/content/renderer/webcrypto_impl.cc b/chromium/content/renderer/webcrypto_impl.cc
deleted file mode 100644
index b0fc14f5f87..00000000000
--- a/chromium/content/renderer/webcrypto_impl.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/webcrypto_impl.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "third_party/WebKit/public/platform/WebArrayBuffer.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
-#include "third_party/WebKit/public/platform/WebCryptoKey.h"
-
-namespace content {
-
-WebCryptoImpl::WebCryptoImpl() {
- Init();
-}
-
-void WebCryptoImpl::digest(
- const WebKit::WebCryptoAlgorithm& algorithm,
- const unsigned char* data,
- unsigned data_size,
- WebKit::WebCryptoResult result) {
- WebKit::WebArrayBuffer buffer;
- if (!DigestInternal(algorithm, data, data_size, &buffer)) {
- result.completeWithError();
- } else {
- result.completeWithBuffer(buffer);
- }
-}
-
-void WebCryptoImpl::importKey(
- WebKit::WebCryptoKeyFormat format,
- const unsigned char* key_data,
- unsigned key_data_size,
- const WebKit::WebCryptoAlgorithm& algorithm,
- bool extractable,
- WebKit::WebCryptoKeyUsageMask usage_mask,
- WebKit::WebCryptoResult result) {
- WebKit::WebCryptoKeyType type;
- scoped_ptr<WebKit::WebCryptoKeyHandle> handle;
-
- if (!ImportKeyInternal(format,
- key_data,
- key_data_size,
- algorithm,
- usage_mask,
- &handle,
- &type)) {
- result.completeWithError();
- return;
- }
-
- WebKit::WebCryptoKey key(
- WebKit::WebCryptoKey::create(
- handle.release(), type, extractable, algorithm, usage_mask));
-
- result.completeWithKey(key);
-}
-
-void WebCryptoImpl::sign(
- const WebKit::WebCryptoAlgorithm& algorithm,
- const WebKit::WebCryptoKey& key,
- const unsigned char* data,
- unsigned data_size,
- WebKit::WebCryptoResult result) {
- WebKit::WebArrayBuffer buffer;
- if (!SignInternal(algorithm, key, data, data_size, &buffer)) {
- result.completeWithError();
- } else {
- result.completeWithBuffer(buffer);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/webcrypto_impl.h b/chromium/content/renderer/webcrypto_impl.h
deleted file mode 100644
index 362be613074..00000000000
--- a/chromium/content/renderer/webcrypto_impl.h
+++ /dev/null
@@ -1,74 +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_RENDERER_WEBCRYPTO_IMPL_H_
-#define CONTENT_RENDERER_WEBCRYPTO_IMPL_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebCrypto.h"
-
-namespace content {
-
-class CONTENT_EXPORT WebCryptoImpl
- : NON_EXPORTED_BASE(public WebKit::WebCrypto) {
- public:
- WebCryptoImpl();
-
- virtual void digest(
- const WebKit::WebCryptoAlgorithm& algorithm,
- const unsigned char* data,
- unsigned data_size,
- WebKit::WebCryptoResult result);
- virtual void importKey(
- WebKit::WebCryptoKeyFormat format,
- const unsigned char* key_data,
- unsigned key_data_size,
- const WebKit::WebCryptoAlgorithm& algorithm,
- bool extractable,
- WebKit::WebCryptoKeyUsageMask usage_mask,
- WebKit::WebCryptoResult result);
- virtual void sign(
- const WebKit::WebCryptoAlgorithm& algorithm,
- const WebKit::WebCryptoKey& key,
- const unsigned char* data,
- unsigned data_size,
- WebKit::WebCryptoResult result);
-
- protected:
- FRIEND_TEST_ALL_PREFIXES(WebCryptoImplTest, DigestSampleSets);
- FRIEND_TEST_ALL_PREFIXES(WebCryptoImplTest, HMACSampleSets);
-
- void Init();
-
- bool DigestInternal(
- const WebKit::WebCryptoAlgorithm& algorithm,
- const unsigned char* data,
- unsigned data_size,
- WebKit::WebArrayBuffer* buffer);
- bool ImportKeyInternal(
- WebKit::WebCryptoKeyFormat format,
- const unsigned char* key_data,
- unsigned key_data_size,
- const WebKit::WebCryptoAlgorithm& algorithm,
- WebKit::WebCryptoKeyUsageMask usage_mask,
- scoped_ptr<WebKit::WebCryptoKeyHandle>* handle,
- WebKit::WebCryptoKeyType* type);
- bool SignInternal(
- const WebKit::WebCryptoAlgorithm& algorithm,
- const WebKit::WebCryptoKey& key,
- const unsigned char* data,
- unsigned data_size,
- WebKit::WebArrayBuffer* buffer);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WebCryptoImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_WEBCRYPTO_IMPL_H_
diff --git a/chromium/content/renderer/webcrypto_impl_nss.cc b/chromium/content/renderer/webcrypto_impl_nss.cc
deleted file mode 100644
index caf986fce44..00000000000
--- a/chromium/content/renderer/webcrypto_impl_nss.cc
+++ /dev/null
@@ -1,252 +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/webcrypto_impl.h"
-
-#include <pk11pub.h>
-#include <sechash.h>
-
-#include "base/logging.h"
-#include "crypto/nss_util.h"
-#include "crypto/scoped_nss_types.h"
-#include "third_party/WebKit/public/platform/WebArrayBuffer.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
-
-namespace content {
-
-namespace {
-
-class SymKeyHandle : public WebKit::WebCryptoKeyHandle {
- public:
- explicit SymKeyHandle(crypto::ScopedPK11SymKey key) {
- DCHECK(!key_.get());
- key_ = key.Pass();
- }
-
- PK11SymKey* key() { return key_.get(); }
-
- private:
- crypto::ScopedPK11SymKey key_;
-
- DISALLOW_COPY_AND_ASSIGN(SymKeyHandle);
-};
-
-HASH_HashType WebCryptoAlgorithmToNSSHashType(
- const WebKit::WebCryptoAlgorithm& algorithm) {
- switch (algorithm.id()) {
- case WebKit::WebCryptoAlgorithmIdSha1:
- return HASH_AlgSHA1;
- case WebKit::WebCryptoAlgorithmIdSha224:
- return HASH_AlgSHA224;
- case WebKit::WebCryptoAlgorithmIdSha256:
- return HASH_AlgSHA256;
- case WebKit::WebCryptoAlgorithmIdSha384:
- return HASH_AlgSHA384;
- case WebKit::WebCryptoAlgorithmIdSha512:
- return HASH_AlgSHA512;
- default:
- // Not a digest algorithm.
- return HASH_AlgNULL;
- }
-}
-
-CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism(
- const WebKit::WebCryptoAlgorithm& algorithm) {
- switch (algorithm.id()) {
- case WebKit::WebCryptoAlgorithmIdSha1:
- return CKM_SHA_1_HMAC;
- case WebKit::WebCryptoAlgorithmIdSha256:
- return CKM_SHA256_HMAC;
- default:
- // Not a supported algorithm.
- return CKM_INVALID_MECHANISM;
- }
-}
-
-} // namespace
-
-void WebCryptoImpl::Init() {
- crypto::EnsureNSSInit();
-}
-
-bool WebCryptoImpl::DigestInternal(
- const WebKit::WebCryptoAlgorithm& algorithm,
- const unsigned char* data,
- unsigned data_size,
- WebKit::WebArrayBuffer* buffer) {
- HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm);
- if (hash_type == HASH_AlgNULL) {
- return false;
- }
-
- HASHContext* context = HASH_Create(hash_type);
- if (!context) {
- return false;
- }
-
- HASH_Begin(context);
-
- HASH_Update(context, data, data_size);
-
- unsigned hash_result_length = HASH_ResultLenContext(context);
- DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX));
-
- *buffer = WebKit::WebArrayBuffer::create(hash_result_length, 1);
-
- unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data());
-
- unsigned result_length = 0;
- HASH_End(context, digest, &result_length, hash_result_length);
-
- HASH_Destroy(context);
-
- return result_length == hash_result_length;
-}
-
-bool WebCryptoImpl::ImportKeyInternal(
- WebKit::WebCryptoKeyFormat format,
- const unsigned char* key_data,
- unsigned key_data_size,
- const WebKit::WebCryptoAlgorithm& algorithm,
- WebKit::WebCryptoKeyUsageMask usage_mask,
- scoped_ptr<WebKit::WebCryptoKeyHandle>* handle,
- WebKit::WebCryptoKeyType* type) {
- switch (algorithm.id()) {
- case WebKit::WebCryptoAlgorithmIdHmac:
- *type = WebKit::WebCryptoKeyTypeSecret;
- break;
- // TODO(bryaneyler): Support more key types.
- default:
- return false;
- }
-
- // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys.
- // Currently only supporting symmetric.
- CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
- // Flags are verified at the Blink layer; here the flags are set to all
- // possible operations for this key type.
- CK_FLAGS flags = 0;
-
- switch(algorithm.id()) {
- case WebKit::WebCryptoAlgorithmIdHmac: {
- const WebKit::WebCryptoHmacParams* params = algorithm.hmacParams();
- if (!params) {
- return false;
- }
-
- mechanism = WebCryptoAlgorithmToHMACMechanism(params->hash());
- if (mechanism == CKM_INVALID_MECHANISM) {
- return false;
- }
-
- flags |= CKF_SIGN | CKF_VERIFY;
-
- break;
- }
- default:
- return false;
- }
-
- DCHECK_NE(CKM_INVALID_MECHANISM, mechanism);
- DCHECK_NE(0ul, flags);
-
- SECItem key_item = { siBuffer, NULL, 0 };
-
- switch (format) {
- case WebKit::WebCryptoKeyFormatRaw:
- key_item.data = const_cast<unsigned char*>(key_data);
- key_item.len = key_data_size;
- break;
- // TODO(bryaneyler): Handle additional formats.
- default:
- return false;
- }
-
- crypto::ScopedPK11SymKey pk11_sym_key(
- PK11_ImportSymKeyWithFlags(PK11_GetInternalSlot(),
- mechanism,
- PK11_OriginUnwrap,
- CKA_FLAGS_ONLY,
- &key_item,
- flags,
- false,
- NULL));
- if (!pk11_sym_key.get()) {
- NOTREACHED();
- return false;
- }
-
- scoped_ptr<SymKeyHandle> sym_key(new SymKeyHandle(pk11_sym_key.Pass()));
- *handle = sym_key.Pass();
-
- return true;
-}
-
-bool WebCryptoImpl::SignInternal(
- const WebKit::WebCryptoAlgorithm& algorithm,
- const WebKit::WebCryptoKey& key,
- const unsigned char* data,
- unsigned data_size,
- WebKit::WebArrayBuffer* buffer) {
- WebKit::WebArrayBuffer result;
-
- switch (algorithm.id()) {
- case WebKit::WebCryptoAlgorithmIdHmac: {
- const WebKit::WebCryptoHmacParams* params = algorithm.hmacParams();
- if (!params) {
- return false;
- }
-
- SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
-
- DCHECK_EQ(PK11_GetMechanism(sym_key->key()),
- WebCryptoAlgorithmToHMACMechanism(params->hash()));
- DCHECK_NE(0, key.usages() & WebKit::WebCryptoKeyUsageSign);
-
- SECItem param_item = { siBuffer, NULL, 0 };
- SECItem data_item = {
- siBuffer,
- const_cast<unsigned char*>(data),
- data_size
- };
- // First call is to figure out the length.
- SECItem signature_item = { siBuffer, NULL, 0 };
-
- if (PK11_SignWithSymKey(sym_key->key(),
- PK11_GetMechanism(sym_key->key()),
- &param_item,
- &signature_item,
- &data_item) != SECSuccess) {
- NOTREACHED();
- return false;
- }
-
- DCHECK_NE(0u, signature_item.len);
-
- result = WebKit::WebArrayBuffer::create(signature_item.len, 1);
- signature_item.data = reinterpret_cast<unsigned char*>(result.data());
-
- if (PK11_SignWithSymKey(sym_key->key(),
- PK11_GetMechanism(sym_key->key()),
- &param_item,
- &signature_item,
- &data_item) != SECSuccess) {
- NOTREACHED();
- return false;
- }
-
- DCHECK_EQ(result.byteLength(), signature_item.len);
-
- break;
- }
- default:
- return false;
- }
-
- *buffer = result;
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/webcrypto_impl_openssl.cc b/chromium/content/renderer/webcrypto_impl_openssl.cc
deleted file mode 100644
index 9aa1a425301..00000000000
--- a/chromium/content/renderer/webcrypto_impl_openssl.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/webcrypto_impl.h"
-
-namespace content {
-
-void WebCryptoImpl::Init() {
-}
-
-bool WebCryptoImpl::DigestInternal(
- const WebKit::WebCryptoAlgorithm& algorithm,
- const unsigned char* data,
- unsigned data_size,
- WebKit::WebArrayBuffer* buffer) {
- // TODO(bryaneyler): Placeholder for OpenSSL implementation.
- // Issue http://crbug.com/267888.
- return false;
-}
-
-bool WebCryptoImpl::ImportKeyInternal(
- WebKit::WebCryptoKeyFormat format,
- const unsigned char* key_data,
- unsigned key_data_size,
- const WebKit::WebCryptoAlgorithm& algorithm,
- WebKit::WebCryptoKeyUsageMask usage_mask,
- scoped_ptr<WebKit::WebCryptoKeyHandle>* handle,
- WebKit::WebCryptoKeyType* type) {
- // TODO(bryaneyler): Placeholder for OpenSSL implementation.
- // Issue http://crbug.com/267888.
- return false;
-}
-
-bool WebCryptoImpl::SignInternal(
- const WebKit::WebCryptoAlgorithm& algorithm,
- const WebKit::WebCryptoKey& key,
- const unsigned char* data,
- unsigned data_size,
- WebKit::WebArrayBuffer* buffer) {
- // TODO(bryaneyler): Placeholder for OpenSSL implementation.
- // Issue http://crbug.com/267888.
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/webcrypto_impl_unittest.cc b/chromium/content/renderer/webcrypto_impl_unittest.cc
deleted file mode 100644
index 8a9a1004b86..00000000000
--- a/chromium/content/renderer/webcrypto_impl_unittest.cc
+++ /dev/null
@@ -1,277 +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 "webcrypto_impl.h"
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string_number_conversions.h"
-#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/renderer_webkitplatformsupport_impl.h"
-#include "content/renderer/webcrypto_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebArrayBuffer.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
-
-namespace content {
-
-const WebKit::WebCryptoAlgorithmId kAlgorithmIds[] = {
- WebKit::WebCryptoAlgorithmIdSha1,
- WebKit::WebCryptoAlgorithmIdSha224,
- WebKit::WebCryptoAlgorithmIdSha256,
- WebKit::WebCryptoAlgorithmIdSha384,
- WebKit::WebCryptoAlgorithmIdSha512
-};
-
-class WebCryptoImplTest : public testing::Test, public WebCryptoImpl {
-};
-
-TEST_F(WebCryptoImplTest, DigestSampleSets) {
- // The results are stored here in hex format for readability.
- //
- // TODO(bryaneyler): Eventually, all these sample test sets should be replaced
- // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03
- struct {
- const char* input;
- unsigned input_length;
- const char* hex_result[arraysize(kAlgorithmIds)];
- } input_set[] = {
- {
- "", 0,
- {
- // echo -n "" | sha1sum
- "da39a3ee5e6b4b0d3255bfef95601890afd80709",
- // echo -n "" | sha224sum
- "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f",
- // echo -n "" | sha256sum
- "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
- // echo -n "" | sha384sum
- "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274e"
- "debfe76f65fbd51ad2f14898b95b",
- // echo -n "" | sha512sum
- "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0"
- "d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
- },
- },
- {
- "\000", 1,
- {
- // echo -n -e "\000" | sha1sum
- "5ba93c9db0cff93f52b521d7420e43f6eda2784f",
- // echo -n -e "\000" | sha224sum
- "fff9292b4201617bdc4d3053fce02734166a683d7d858a7f5f59b073",
- // echo -n -e "\000" | sha256sum
- "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d",
- // echo -n -e "\000" | sha384sum
- "bec021b4f368e3069134e012c2b4307083d3a9bdd206e24e5f0d86e13d6636655933"
- "ec2b413465966817a9c208a11717",
- // echo -n -e "\000" | sha512sum
- "b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a"
- "802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee",
- },
- },
- {
- "\000\001\002\003\004\005", 6,
- {
- // echo -n -e "\000\001\002\003\004\005" | sha1sum
- "868460d98d09d8bbb93d7b6cdd15cc7fbec676b9",
- // echo -n -e "\000\001\002\003\004\005" | sha224sum
- "7d92e7f1cad1818ed1d13ab41f04ebabfe1fef6bb4cbeebac34c29bc",
- // echo -n -e "\000\001\002\003\004\005" | sha256sum
- "17e88db187afd62c16e5debf3e6527cd006bc012bc90b51a810cd80c2d511f43",
- // echo -n -e "\000\001\002\003\004\005" | sha384sum
- "79f4738706fce9650ac60266675c3cd07298b09923850d525604d040e6e448adc7dc"
- "22780d7e1b95bfeaa86a678e4552",
- // echo -n -e "\000\001\002\003\004\005" | sha512sum
- "2f3831bccc94cf061bcfa5f8c23c1429d26e3bc6b76edad93d9025cb91c903af6cf9"
- "c935dc37193c04c2c66e7d9de17c358284418218afea2160147aaa912f4c",
- },
- },
- };
-
- for (size_t id_index = 0; id_index < arraysize(kAlgorithmIds); id_index++) {
- SCOPED_TRACE(id_index);
-
- WebKit::WebCryptoAlgorithm algorithm(
- WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(
- kAlgorithmIds[id_index], NULL));
-
- for (size_t set_index = 0;
- set_index < ARRAYSIZE_UNSAFE(input_set);
- set_index++) {
- SCOPED_TRACE(set_index);
-
- WebKit::WebArrayBuffer array_buffer;
-
- WebCryptoImpl crypto;
- EXPECT_TRUE(
- crypto.DigestInternal(
- algorithm,
- reinterpret_cast<const unsigned char*>(
- input_set[set_index].input),
- input_set[set_index].input_length,
- &array_buffer));
-
- // Ignore case, it's checking the hex value.
- EXPECT_STRCASEEQ(
- input_set[set_index].hex_result[id_index],
- base::HexEncode(
- array_buffer.data(), array_buffer.byteLength()).c_str());
- }
- }
-}
-
-TEST_F(WebCryptoImplTest, HMACSampleSets) {
- struct {
- WebKit::WebCryptoAlgorithmId algorithm;
- const char* key;
- const char* message;
- const char* mac;
- } input_set[] = {
- // Empty sets. Result generated via OpenSSL commandline tool. These
- // particular results are also posted on the Wikipedia page examples:
- // http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
- {
- WebKit::WebCryptoAlgorithmIdSha1,
- "",
- "",
- // openssl dgst -sha1 -hmac "" < /dev/null
- "fbdb1d1b18aa6c08324b7d64b71fb76370690e1d",
- },
- {
- WebKit::WebCryptoAlgorithmIdSha256,
- "",
- "",
- // openssl dgst -sha256 -hmac "" < /dev/null
- "b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad",
- },
- // For this data, see http://csrc.nist.gov/groups/STM/cavp/index.html#07
- // Download:
- // http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
- // L=20 set 45
- {
- WebKit::WebCryptoAlgorithmIdSha1,
- // key
- "59785928d72516e31272",
- // message
- "a3ce8899df1022e8d2d539b47bf0e309c66f84095e21438ec355bf119ce5fdcb4e73a6"
- "19cdf36f25b369d8c38ff419997f0c59830108223606e31223483fd39edeaa4d3f0d21"
- "198862d239c9fd26074130ff6c86493f5227ab895c8f244bd42c7afce5d147a20a5907"
- "98c68e708e964902d124dadecdbda9dbd0051ed710e9bf",
- // mac
- "3c8162589aafaee024fc9a5ca50dd2336fe3eb28",
- },
- // L=20 set 299
- {
- WebKit::WebCryptoAlgorithmIdSha1,
- // key
- "ceb9aedf8d6efcf0ae52bea0fa99a9e26ae81bacea0cff4d5eecf201e3bca3c3577480"
- "621b818fd717ba99d6ff958ea3d59b2527b019c343bb199e648090225867d994607962"
- "f5866aa62930d75b58f6",
- // message
- "99958aa459604657c7bf6e4cdfcc8785f0abf06ffe636b5b64ecd931bd8a4563055924"
- "21fc28dbcccb8a82acea2be8e54161d7a78e0399a6067ebaca3f2510274dc9f92f2c8a"
- "e4265eec13d7d42e9f8612d7bc258f913ecb5a3a5c610339b49fb90e9037b02d684fc6"
- "0da835657cb24eab352750c8b463b1a8494660d36c3ab2",
- // mac
- "4ac41ab89f625c60125ed65ffa958c6b490ea670",
- },
- // L=32, set 30
- {
- WebKit::WebCryptoAlgorithmIdSha256,
- // key
- "9779d9120642797f1747025d5b22b7ac607cab08e1758f2f3a46c8be1e25c53b8c6a8f"
- "58ffefa176",
- // message
- "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
- "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
- "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
- "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e",
- // mac
- "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b",
- },
- // L=32, set 224
- {
- WebKit::WebCryptoAlgorithmIdSha256,
- // key
- "4b7ab133efe99e02fc89a28409ee187d579e774f4cba6fc223e13504e3511bef8d4f63"
- "8b9aca55d4a43b8fbd64cf9d74dcc8c9e8d52034898c70264ea911a3fd70813fa73b08"
- "3371289b",
- // message
- "138efc832c64513d11b9873c6fd4d8a65dbf367092a826ddd587d141b401580b798c69"
- "025ad510cff05fcfbceb6cf0bb03201aaa32e423d5200925bddfadd418d8e30e18050e"
- "b4f0618eb9959d9f78c1157d4b3e02cd5961f138afd57459939917d9144c95d8e6a94c"
- "8f6d4eef3418c17b1ef0b46c2a7188305d9811dccb3d99",
- // mac
- "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b",
- },
- };
-
- for (size_t index = 0; index < ARRAYSIZE_UNSAFE(input_set); index++) {
- SCOPED_TRACE(index);
-
- WebKit::WebCryptoAlgorithm hash_algorithm(
- WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(
- input_set[index].algorithm, NULL));
-
- scoped_ptr<WebKit::WebCryptoHmacParams> hmac_params(
- new WebKit::WebCryptoHmacParams(hash_algorithm));
-
- WebKit::WebCryptoAlgorithm hmac_algorithm(
- WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(
- WebKit::WebCryptoAlgorithmIdHmac, hmac_params.release()));
-
- WebKit::WebCryptoKeyType type;
- scoped_ptr<WebKit::WebCryptoKeyHandle> handle;
-
- std::vector<uint8> key_raw;
- base::HexStringToBytes(input_set[index].key, &key_raw);
-
- WebCryptoImpl crypto;
-
- EXPECT_TRUE(
- crypto.ImportKeyInternal(
- WebKit::WebCryptoKeyFormatRaw,
- key_raw.data(),
- key_raw.size(),
- hmac_algorithm,
- WebKit::WebCryptoKeyUsageSign,
- &handle,
- &type));
-
- EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, type);
- ASSERT_TRUE(handle.get());
-
- WebKit::WebCryptoKey crypto_key =
- WebKit::WebCryptoKey::create(
- handle.release(),
- type,
- false,
- hmac_algorithm,
- WebKit::WebCryptoKeyUsageSign);
-
- std::vector<uint8> message_raw;
- base::HexStringToBytes(input_set[index].message, &message_raw);
-
- WebKit::WebArrayBuffer array_buffer;
-
- EXPECT_TRUE(
- crypto.SignInternal(
- hmac_algorithm,
- crypto_key,
- message_raw.data(),
- message_raw.size(),
- &array_buffer));
-
- // Ignore case, it's checking the hex value.
- EXPECT_STRCASEEQ(
- input_set[index].mac,
- base::HexEncode(
- array_buffer.data(), array_buffer.byteLength()).c_str());
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/webpublicsuffixlist_impl.cc b/chromium/content/renderer/webpublicsuffixlist_impl.cc
new file mode 100644
index 00000000000..e1e00c22be2
--- /dev/null
+++ b/chromium/content/renderer/webpublicsuffixlist_impl.cc
@@ -0,0 +1,23 @@
+// 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/webpublicsuffixlist_impl.h"
+
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+
+namespace content {
+
+WebPublicSuffixListImpl::~WebPublicSuffixListImpl() {
+}
+
+size_t WebPublicSuffixListImpl::getPublicSuffixLength(
+ const blink::WebString& host) {
+ size_t result = net::registry_controlled_domains::GetRegistryLength(
+ host.utf8(),
+ net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+ return result ? result : host.length();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/webpublicsuffixlist_impl.h b/chromium/content/renderer/webpublicsuffixlist_impl.h
new file mode 100644
index 00000000000..65fcc65e39b
--- /dev/null
+++ b/chromium/content/renderer/webpublicsuffixlist_impl.h
@@ -0,0 +1,22 @@
+// 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_WEBPUBLICSUFFIXLIST_IMPL_H_
+#define CONTENT_RENDERER_WEBPUBLICSUFFIXLIST_IMPL_H_
+
+#include "base/compiler_specific.h"
+#include "third_party/WebKit/public/platform/WebPublicSuffixList.h"
+
+namespace content {
+
+class WebPublicSuffixListImpl : public blink::WebPublicSuffixList {
+ public:
+ // WebPublicSuffixList methods:
+ virtual size_t getPublicSuffixLength(const blink::WebString& host);
+ virtual ~WebPublicSuffixListImpl();
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_WEBPUBLICSUFFIXLIST_IMPL_H_
diff --git a/chromium/content/renderer/websharedworker_proxy.cc b/chromium/content/renderer/websharedworker_proxy.cc
index 190a35c59cf..815568ea793 100644
--- a/chromium/content/renderer/websharedworker_proxy.cc
+++ b/chromium/content/renderer/websharedworker_proxy.cc
@@ -51,11 +51,11 @@ void WebSharedWorkerProxy::Disconnect() {
void WebSharedWorkerProxy::CreateWorkerContext(
const GURL& script_url,
bool is_shared,
- const string16& name,
- const string16& user_agent,
- const string16& source_code,
- const string16& content_security_policy,
- WebKit::WebContentSecurityPolicyType policy_type,
+ const base::string16& name,
+ const base::string16& user_agent,
+ const base::string16& source_code,
+ const base::string16& content_security_policy,
+ blink::WebContentSecurityPolicyType policy_type,
int pending_route_id,
int64 script_resource_appcache_id) {
DCHECK(route_id_ == MSG_ROUTING_NONE);
@@ -121,12 +121,12 @@ bool WebSharedWorkerProxy::isStarted() {
}
void WebSharedWorkerProxy::startWorkerContext(
- const WebKit::WebURL& script_url,
- const WebKit::WebString& name,
- const WebKit::WebString& user_agent,
- const WebKit::WebString& source_code,
- const WebKit::WebString& content_security_policy,
- WebKit::WebContentSecurityPolicyType policy_type,
+ const blink::WebURL& script_url,
+ const blink::WebString& name,
+ const blink::WebString& user_agent,
+ const blink::WebString& source_code,
+ const blink::WebString& content_security_policy,
+ blink::WebContentSecurityPolicyType policy_type,
long long script_resource_appcache_id) {
DCHECK(!isStarted());
CreateWorkerContext(
@@ -134,17 +134,7 @@ void WebSharedWorkerProxy::startWorkerContext(
policy_type, pending_route_id_, script_resource_appcache_id);
}
-void WebSharedWorkerProxy::terminateWorkerContext() {
- // This API should only be invoked from worker context.
- NOTREACHED();
-}
-
-void WebSharedWorkerProxy::clientDestroyed() {
- // This API should only be invoked from worker context.
- NOTREACHED();
-}
-
-void WebSharedWorkerProxy::connect(WebKit::WebMessagePortChannel* channel,
+void WebSharedWorkerProxy::connect(blink::WebMessagePortChannel* channel,
ConnectListener* listener) {
WebMessagePortChannelImpl* webchannel =
static_cast<WebMessagePortChannelImpl*>(channel);
diff --git a/chromium/content/renderer/websharedworker_proxy.h b/chromium/content/renderer/websharedworker_proxy.h
index 75c7b5505ed..a7335b3d01d 100644
--- a/chromium/content/renderer/websharedworker_proxy.h
+++ b/chromium/content/renderer/websharedworker_proxy.h
@@ -11,7 +11,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "ipc/ipc_listener.h"
-#include "third_party/WebKit/public/web/WebSharedWorker.h"
+#include "third_party/WebKit/public/web/WebSharedWorkerConnector.h"
#include "url/gurl.h"
namespace content {
@@ -23,7 +23,7 @@ class ChildThread;
// thread. Once the connect event has been sent, all future communication will
// happen via the WebMessagePortChannel, and the WebSharedWorker instance will
// be freed.
-class WebSharedWorkerProxy : public WebKit::WebSharedWorker,
+class WebSharedWorkerProxy : public blink::WebSharedWorkerConnector,
private IPC::Listener {
public:
// If the worker not loaded yet, route_id == MSG_ROUTING_NONE
@@ -36,21 +36,18 @@ class WebSharedWorkerProxy : public WebKit::WebSharedWorker,
// Implementations of WebSharedWorker APIs
virtual bool isStarted();
- virtual void connect(WebKit::WebMessagePortChannel* channel,
+ virtual void connect(blink::WebMessagePortChannel* channel,
ConnectListener* listener);
virtual void startWorkerContext(
- const WebKit::WebURL& script_url,
- const WebKit::WebString& name,
- const WebKit::WebString& user_agent,
- const WebKit::WebString& source_code,
- const WebKit::WebString& content_security_policy,
- WebKit::WebContentSecurityPolicyType policy_type,
+ const blink::WebURL& script_url,
+ const blink::WebString& name,
+ const blink::WebString& user_agent,
+ const blink::WebString& source_code,
+ const blink::WebString& content_security_policy,
+ blink::WebContentSecurityPolicyType policy_type,
long long script_resource_appcache_id);
- virtual void terminateWorkerContext();
- virtual void clientDestroyed();
-
private:
// IPC::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -73,11 +70,11 @@ class WebSharedWorkerProxy : public WebKit::WebSharedWorker,
void CreateWorkerContext(const GURL& script_url,
bool is_shared,
- const string16& name,
- const string16& user_agent,
- const string16& source_code,
- const string16& content_security_policy,
- WebKit::WebContentSecurityPolicyType policy_type,
+ const base::string16& name,
+ const base::string16& user_agent,
+ const base::string16& source_code,
+ const base::string16& content_security_policy,
+ blink::WebContentSecurityPolicyType policy_type,
int pending_route_id,
int64 script_resource_appcache_id);
void OnWorkerCreated();
diff --git a/chromium/content/renderer/websharedworkerrepository_impl.cc b/chromium/content/renderer/websharedworkerrepository_impl.cc
deleted file mode 100644
index d914cf7b3f0..00000000000
--- a/chromium/content/renderer/websharedworkerrepository_impl.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2009 The Chromium Authors. All 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/websharedworkerrepository_impl.h"
-
-#include "content/child/child_thread.h"
-#include "content/common/view_messages.h"
-#include "content/renderer/websharedworker_proxy.h"
-
-namespace content {
-
-WebSharedWorkerRepositoryImpl::WebSharedWorkerRepositoryImpl() {}
-
-WebSharedWorkerRepositoryImpl::~WebSharedWorkerRepositoryImpl() {}
-
-void WebSharedWorkerRepositoryImpl::addSharedWorker(
- WebKit::WebSharedWorker* worker, DocumentID document) {
- shared_worker_parents_.insert(document);
-}
-
-void WebSharedWorkerRepositoryImpl::documentDetached(DocumentID document) {
- DocumentSet::iterator iter = shared_worker_parents_.find(document);
- if (iter != shared_worker_parents_.end()) {
- // Notify the browser process that the document has shut down.
- ChildThread::current()->Send(new ViewHostMsg_DocumentDetached(document));
- shared_worker_parents_.erase(iter);
- }
-}
-
-bool WebSharedWorkerRepositoryImpl::hasSharedWorkers(DocumentID document) {
- return shared_worker_parents_.find(document) != shared_worker_parents_.end();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/websharedworkerrepository_impl.h b/chromium/content/renderer/websharedworkerrepository_impl.h
deleted file mode 100644
index ebe2a22dcdb..00000000000
--- a/chromium/content/renderer/websharedworkerrepository_impl.h
+++ /dev/null
@@ -1,37 +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_WEBSHAREDWORKERREPOSITORY_IMPL_H_
-#define CONTENT_RENDERER_WEBSHAREDWORKERREPOSITORY_IMPL_H_
-
-#include "base/containers/hash_tables.h"
-#include "third_party/WebKit/public/web/WebSharedWorkerRepository.h"
-
-namespace WebKit {
-class WebSharedWorker;
-}
-
-namespace content {
-
-class WebSharedWorkerRepositoryImpl : public WebKit::WebSharedWorkerRepository {
- public:
- WebSharedWorkerRepositoryImpl();
- virtual ~WebSharedWorkerRepositoryImpl();
-
- virtual void addSharedWorker(WebKit::WebSharedWorker*, DocumentID document);
- virtual void documentDetached(DocumentID document);
-
- // Returns true if the document has created a SharedWorker (used by the
- // WebKit code to determine if the document can be suspended).
- virtual bool hasSharedWorkers(DocumentID document);
-
- private:
- // The set of documents that have created a SharedWorker.
- typedef base::hash_set<DocumentID> DocumentSet;
- DocumentSet shared_worker_parents_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_WEBSHAREDWORKERREPOSITORY_IMPL_H_
diff --git a/chromium/content/shell/DEPS b/chromium/content/shell/DEPS
index 5385a5d07ec..3cc264e515e 100644
--- a/chromium/content/shell/DEPS
+++ b/chromium/content/shell/DEPS
@@ -22,4 +22,12 @@ include_rules = [
# For WebTestRunner library
"+third_party/WebKit/public/testing",
+
+ "+components/breakpad",
]
+
+specific_include_rules = {
+ "shell_views\.cc": [
+ "+ui/wm/test"
+ ],
+}
diff --git a/chromium/content/shell/OWNERS b/chromium/content/shell/OWNERS
index 92bc6c59ab6..2abc7be24fc 100644
--- a/chromium/content/shell/OWNERS
+++ b/chromium/content/shell/OWNERS
@@ -1,2 +1 @@
-jochen@chromium.org
pfeldman@chromium.org
diff --git a/chromium/content/shell/android/browsertests_apk/AndroidManifest.xml b/chromium/content/shell/android/browsertests_apk/AndroidManifest.xml
index 9f9f8a1d97f..6c27e5f0dcc 100644
--- a/chromium/content/shell/android/browsertests_apk/AndroidManifest.xml
+++ b/chromium/content/shell/android/browsertests_apk/AndroidManifest.xml
@@ -96,7 +96,7 @@
android:exported="false" />
</application>
- <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" />
+ <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CAMERA" />
diff --git a/chromium/content/shell/android/browsertests_apk/content_browser_tests_android.cc b/chromium/content/shell/android/browsertests_apk/content_browser_tests_android.cc
index b9792dc8693..0acff508aea 100644
--- a/chromium/content/shell/android/browsertests_apk/content_browser_tests_android.cc
+++ b/chromium/content/shell/android/browsertests_apk/content_browser_tests_android.cc
@@ -61,7 +61,7 @@ static void RunTests(JNIEnv* env,
// Set the application context in base.
base::android::ScopedJavaLocalRef<jobject> scoped_context(
env, env->NewLocalRef(app_context));
- base::android::InitApplicationContext(scoped_context);
+ base::android::InitApplicationContext(env, scoped_context);
base::android::RegisterJni(env);
std::vector<std::string> args;
diff --git a/chromium/content/shell/android/linker_test_apk/AndroidManifest.xml b/chromium/content/shell/android/linker_test_apk/AndroidManifest.xml
new file mode 100644
index 00000000000..815bab5d752
--- /dev/null
+++ b/chromium/content/shell/android/linker_test_apk/AndroidManifest.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.chromium.content_linker_test_apk">
+
+ <permission android:name="org.chromium.content_shell.permission.SANDBOX"
+ android:protectionLevel="signature" />
+
+ <application android:name="ContentLinkerTestApplication"
+ android:label="ContentLinkerTest">
+ <activity android:name="ContentLinkerTestActivity"
+ android:launchMode="singleTask"
+ android:theme="@android:style/Theme.Holo.Light.NoActionBar"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize"
+ android:hardwareAccelerated="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <!-- The following service entries exist in order to allow us to
+ start more than one sandboxed process. -->
+
+ <!-- NOTE: If you change the values of "android:process" for any of the below services,
+ you also need to update kHelperProcessExecutableName in chrome_constants.cc. -->
+ <service android:name="org.chromium.content.app.SandboxedProcessService0"
+ android:process=":sandboxed_process0"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService1"
+ android:process=":sandboxed_process1"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService2"
+ android:process=":sandboxed_process2"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService3"
+ android:process=":sandboxed_process3"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService4"
+ android:process=":sandboxed_process4"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService5"
+ android:process=":sandboxed_process5"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService6"
+ android:process=":sandboxed_process6"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService7"
+ android:process=":sandboxed_process7"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService8"
+ android:process=":sandboxed_process8"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService9"
+ android:process=":sandboxed_process9"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService10"
+ android:process=":sandboxed_process10"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService11"
+ android:process=":sandboxed_process11"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ <service android:name="org.chromium.content.app.SandboxedProcessService12"
+ android:process=":sandboxed_process12"
+ android:permission="org.chromium.content_shell.permission.SANDBOX"
+ android:isolatedProcess="true"
+ android:exported="false" />
+ </application>
+
+ <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+ <uses-permission android:name="android.permission.VIBRATE"/>
+ <uses-permission android:name="android.permission.WAKE_LOCK"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+</manifest>
diff --git a/chromium/content/shell/android/linker_test_apk/content_linker_test_android.cc b/chromium/content/shell/android/linker_test_apk/content_linker_test_android.cc
new file mode 100644
index 00000000000..42c01d0e940
--- /dev/null
+++ b/chromium/content/shell/android/linker_test_apk/content_linker_test_android.cc
@@ -0,0 +1,36 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_registrar.h"
+#include "base/basictypes.h"
+#include "base/debug/debugger.h"
+#include "base/logging.h"
+#include "content/public/app/android_library_loader_hooks.h"
+#include "content/public/app/content_main.h"
+#include "content/public/browser/android/compositor.h"
+#include "content/shell/android/linker_test_apk/content_linker_test_linker_tests.h"
+#include "content/shell/android/shell_jni_registrar.h"
+#include "content/shell/app/shell_main_delegate.h"
+
+// This is called by the VM when the shared library is first loaded.
+JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+ base::android::InitVM(vm);
+ JNIEnv* env = base::android::AttachCurrentThread();
+
+ if (!content::RegisterLibraryLoaderEntryHook(env))
+ return -1;
+
+ // To be called only from the UI thread. If loading the library is done on
+ // a separate thread, this should be moved elsewhere.
+ if (!content::android::RegisterShellJni(env))
+ return -1;
+
+ if (!content::RegisterLinkerTestsJni(env))
+ return -1;
+
+ content::Compositor::Initialize();
+ content::SetContentMainDelegate(new content::ShellMainDelegate());
+ return JNI_VERSION_1_4;
+}
diff --git a/chromium/content/shell/android/linker_test_apk/content_linker_test_linker_tests.cc b/chromium/content/shell/android/linker_test_apk/content_linker_test_linker_tests.cc
new file mode 100644
index 00000000000..c970ff6be0a
--- /dev/null
+++ b/chromium/content/shell/android/linker_test_apk/content_linker_test_linker_tests.cc
@@ -0,0 +1,185 @@
+// 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.
+
+// This file implements the native methods of
+// org.content.chromium.app.LinkerTests
+// Unlike the content of linker_jni.cc, it is part of the content library and
+// can
+// thus use base/ and the C++ STL.
+
+#include "content/shell/android/linker_test_apk/content_linker_test_linker_tests.h"
+
+#include <errno.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/debug/proc_maps_linux.h"
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+
+#include "jni/LinkerTests_jni.h"
+
+namespace content {
+
+namespace {
+
+using base::debug::MappedMemoryRegion;
+
+jboolean RunChecks(bool in_browser_process, bool need_relros) {
+
+ // IMPORTANT NOTE: The Python test control script reads the logcat for
+ // lines like:
+ // BROWSER_LINKER_TEST: <status>
+ // RENDERER_LINKER_TEST: <status>
+ //
+ // Where <status> can be either SUCCESS or FAIL. Other lines starting
+ // with the same prefixes, but not using SUCCESS or FAIL are ignored.
+ const char* prefix =
+ in_browser_process ? "BROWSER_LINKER_TEST: " : "RENDERER_LINKER_TEST: ";
+
+ // The RELRO section(s), after being copied into an ashmem region, will
+ // appear in /proc/self/maps as a mapped memory region for a file name
+ // that begins with the following prefix.
+ //
+ // Note that the full name will be something like:
+ // "/dev/ashmem/RELRO:<libname> (deleted)"
+ //
+ // Where <libname> is the library name and '(deleted)' is actually
+ // added by the kernel to indicate there is no corresponding file
+ // on the filesystem.
+ //
+ // For regular builds, there is only one library, and thus one RELRO
+ // section, but for the component build, there are several libraries,
+ // each one with its own RELRO.
+ static const char kRelroSectionPrefix[] = "/dev/ashmem/RELRO:";
+
+ // Parse /proc/self/maps and builds a list of region mappings in this
+ // process.
+ std::string maps;
+ base::debug::ReadProcMaps(&maps);
+ if (maps.empty()) {
+ LOG(ERROR) << prefix << "FAIL Cannot parse /proc/self/maps";
+ return false;
+ }
+
+ std::vector<MappedMemoryRegion> regions;
+ base::debug::ParseProcMaps(maps, &regions);
+ if (regions.empty()) {
+ LOG(ERROR) << prefix << "FAIL Cannot read memory mappings in this process";
+ return false;
+ }
+
+ size_t num_shared_relros = 0;
+ size_t num_bad_shared_relros = 0;
+
+ for (size_t n = 0; n < regions.size(); ++n) {
+ MappedMemoryRegion& region = regions[n];
+
+ if (region.path.find(kRelroSectionPrefix) != 0) {
+ // Ignore any mapping that isn't a shared RELRO.
+ continue;
+ }
+
+ num_shared_relros++;
+
+ void* region_start = reinterpret_cast<void*>(region.start);
+ void* region_end = reinterpret_cast<void*>(region.end);
+
+ // Check that it is mapped read-only.
+ const uint8 expected_flags = MappedMemoryRegion::READ;
+ const uint8 expected_mask = MappedMemoryRegion::READ |
+ MappedMemoryRegion::WRITE |
+ MappedMemoryRegion::EXECUTE;
+
+ uint8 region_flags = region.permissions & expected_mask;
+ if (region_flags != expected_flags) {
+ LOG(ERROR)
+ << prefix
+ << base::StringPrintf(
+ "Shared RELRO section at %p-%p is not mapped read-only. "
+ "Protection flags are %d (%d expected)!",
+ region_start,
+ region_end,
+ region_flags,
+ expected_flags);
+ num_bad_shared_relros++;
+ continue;
+ }
+
+ // Check that trying to remap it read-write fails with EACCES
+ size_t region_size = region.end - region.start;
+ int ret = ::mprotect(region_start, region_size, PROT_READ | PROT_WRITE);
+ if (ret != -1) {
+ LOG(ERROR)
+ << prefix
+ << base::StringPrintf(
+ "Shared RELRO section at %p-%p could be remapped read-write!?",
+ region_start,
+ region_end);
+ num_bad_shared_relros++;
+ // Just in case.
+ ::mprotect(region_start, region_size, PROT_READ);
+ } else if (errno != EACCES) {
+ LOG(ERROR) << prefix << base::StringPrintf(
+ "Shared RELRO section at %p-%p failed "
+ "read-write mprotect with "
+ "unexpected error %d (EACCES:%d wanted): %s",
+ region_start,
+ region_end,
+ errno,
+ EACCES,
+ strerror(errno));
+ num_bad_shared_relros++;
+ }
+ }
+
+ VLOG(0)
+ << prefix
+ << base::StringPrintf(
+ "There are %d shared RELRO sections in this process, %d are bad",
+ num_shared_relros,
+ num_bad_shared_relros);
+
+ if (num_bad_shared_relros > 0) {
+ LOG(ERROR) << prefix << "FAIL Bad Relros sections in this process";
+ return false;
+ }
+
+ if (need_relros) {
+ if (num_shared_relros == 0) {
+ LOG(ERROR) << prefix
+ << "FAIL Missing shared RELRO sections in this process!";
+ return false;
+ }
+ } else {
+ if (num_shared_relros > 0) {
+ LOG(ERROR) << prefix << "FAIL Unexpected " << num_shared_relros
+ << " shared RELRO sections in this process!";
+ return false;
+ }
+ }
+
+ VLOG(0) << prefix << "SUCCESS";
+ return true;
+}
+
+} // namespace
+
+jboolean CheckForSharedRelros(JNIEnv* env,
+ jclass clazz,
+ jboolean in_browser_process) {
+ return RunChecks(in_browser_process, true);
+}
+
+jboolean CheckForNoSharedRelros(JNIEnv* env,
+ jclass clazz,
+ jboolean in_browser_process) {
+ return RunChecks(in_browser_process, false);
+}
+
+bool RegisterLinkerTestsJni(JNIEnv* env) { return RegisterNativesImpl(env); }
+
+} // namespace content
diff --git a/chromium/content/shell/android/linker_test_apk/content_linker_test_linker_tests.h b/chromium/content/shell/android/linker_test_apk/content_linker_test_linker_tests.h
new file mode 100644
index 00000000000..3fcfa2d4225
--- /dev/null
+++ b/chromium/content/shell/android/linker_test_apk/content_linker_test_linker_tests.h
@@ -0,0 +1,16 @@
+// 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_SHELL_ANDROID_LINKER_TEST_APK_CONTENT_LINKER_TEST_LINKER_TESTS_H
+#define CONTENT_SHELL_ANDROID_LINKER_TEST_APK_CONTENT_LINKER_TEST_LINKER_TESTS_H
+
+#include <jni.h>
+
+namespace content {
+
+bool RegisterLinkerTestsJni(JNIEnv* env);
+
+} // namespace content
+
+#endif // CONTENT_SHELL_ANDROID_LINKER_TEST_APK_CONTENT_LINKER_TEST_LINKER_TESTS_H
diff --git a/chromium/content/shell/android/linker_test_apk/res/layout/test_activity.xml b/chromium/content/shell/android/linker_test_apk/res/layout/test_activity.xml
new file mode 100644
index 00000000000..f018927708b
--- /dev/null
+++ b/chromium/content/shell/android/linker_test_apk/res/layout/test_activity.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent" android:layout_height="match_parent"
+ android:orientation="vertical">
+ <org.chromium.content_shell.ShellManager
+ android:id="@+id/shell_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+</LinearLayout>
diff --git a/chromium/content/shell/android/shell_apk/AndroidManifest.xml b/chromium/content/shell/android/shell_apk/AndroidManifest.xml
index 383c7d027e9..d61d289eb20 100644
--- a/chromium/content/shell/android/shell_apk/AndroidManifest.xml
+++ b/chromium/content/shell/android/shell_apk/AndroidManifest.xml
@@ -97,7 +97,7 @@
android:exported="false" />
</application>
- <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" />
+ <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CAMERA"/>
diff --git a/chromium/content/shell/android/shell_descriptors.h b/chromium/content/shell/android/shell_descriptors.h
index 8bcd3765b70..94418132f21 100644
--- a/chromium/content/shell/android/shell_descriptors.h
+++ b/chromium/content/shell/android/shell_descriptors.h
@@ -5,10 +5,13 @@
#ifndef CONTENT_SHELL_ANDROID_SHELL_DESCRIPTORS_H_
#define CONTENT_SHELL_ANDROID_SHELL_DESCRIPTORS_H_
+#include "content/public/common/content_descriptors.h"
+
// This is a list of global descriptor keys to be used with the
// base::GlobalDescriptors object (see base/posix/global_descriptors.h)
enum {
- kShellPakDescriptor = 1,
+ kShellPakDescriptor = kContentIPCDescriptorMax + 1,
+ kAndroidMinidumpDescriptor,
};
#endif // CONTENT_SHELL_ANDROID_SHELL_DESCRIPTORS_H_
diff --git a/chromium/content/shell/android/shell_manager.h b/chromium/content/shell/android/shell_manager.h
index f5505435f5a..67162514549 100644
--- a/chromium/content/shell/android/shell_manager.h
+++ b/chromium/content/shell/android/shell_manager.h
@@ -12,7 +12,7 @@
class Shell;
-namespace WebKit {
+namespace blink {
class WebLayer;
}
@@ -30,8 +30,8 @@ void CloseShellView(jobject shell_view);
// Registers the ShellManager native methods.
bool RegisterShellManager(JNIEnv* env);
-void ShellAttachLayer(WebKit::WebLayer* layer);
-void ShellRemoveLayer(WebKit::WebLayer* layer);
+void ShellAttachLayer(blink::WebLayer* layer);
+void ShellRemoveLayer(blink::WebLayer* layer);
} // namespace content
#endif // CONTENT_SHELL_ANDROID_SHELL_MANAGER_H_
diff --git a/chromium/content/shell/app/framework-Info.plist b/chromium/content/shell/app/framework-Info.plist
new file mode 100644
index 00000000000..ee19476052d
--- /dev/null
+++ b/chromium/content/shell/app/framework-Info.plist
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.chromium.ContentShell.framework</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+</dict>
+</plist>
diff --git a/chromium/content/shell/app/shell.rc b/chromium/content/shell/app/shell.rc
index 80341119637..2987c067570 100644
--- a/chromium/content/shell/app/shell.rc
+++ b/chromium/content/shell/app/shell.rc
@@ -1,6 +1,6 @@
//Microsoft Visual C++ generated resource script.
//
-#include "shell/app/resource.h"
+#include "content/shell/app/resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/content/shell/app/shell_breakpad_client.cc b/chromium/content/shell/app/shell_breakpad_client.cc
new file mode 100644
index 00000000000..0e7cb95750f
--- /dev/null
+++ b/chromium/content/shell/app/shell_breakpad_client.cc
@@ -0,0 +1,72 @@
+// 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/shell/app/shell_breakpad_client.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/content_switches.h"
+#include "content/shell/common/shell_switches.h"
+
+#if defined(OS_ANDROID)
+#include "content/shell/android/shell_descriptors.h"
+#endif
+
+namespace content {
+
+ShellBreakpadClient::ShellBreakpadClient() {}
+ShellBreakpadClient::~ShellBreakpadClient() {}
+
+#if defined(OS_WIN)
+void ShellBreakpadClient::GetProductNameAndVersion(
+ const base::FilePath& exe_path,
+ base::string16* product_name,
+ base::string16* version,
+ base::string16* special_build,
+ base::string16* channel_name) {
+ *product_name = ASCIIToUTF16("content_shell");
+ *version = ASCIIToUTF16(CONTENT_SHELL_VERSION);
+ *special_build = base::string16();
+ *channel_name = base::string16();
+}
+#endif
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
+void ShellBreakpadClient::GetProductNameAndVersion(std::string* product_name,
+ std::string* version) {
+ *product_name = "content_shell";
+ *version = CONTENT_SHELL_VERSION;
+}
+
+base::FilePath ShellBreakpadClient::GetReporterLogFilename() {
+ return base::FilePath(FILE_PATH_LITERAL("uploads.log"));
+}
+#endif
+
+bool ShellBreakpadClient::GetCrashDumpLocation(base::FilePath* crash_dir) {
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kCrashDumpsDir))
+ return false;
+ *crash_dir = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+ switches::kCrashDumpsDir);
+ return true;
+}
+
+#if defined(OS_ANDROID)
+int ShellBreakpadClient::GetAndroidMinidumpDescriptor() {
+ return kAndroidMinidumpDescriptor;
+}
+#endif
+
+bool ShellBreakpadClient::EnableBreakpadForProcess(
+ const std::string& process_type) {
+ return process_type == switches::kRendererProcess ||
+ process_type == switches::kPluginProcess ||
+ process_type == switches::kPpapiPluginProcess ||
+ process_type == switches::kZygoteProcess ||
+ process_type == switches::kGpuProcess;
+}
+
+} // namespace content
diff --git a/chromium/content/shell/app/shell_breakpad_client.h b/chromium/content/shell/app/shell_breakpad_client.h
new file mode 100644
index 00000000000..5f06cce1fc1
--- /dev/null
+++ b/chromium/content/shell/app/shell_breakpad_client.h
@@ -0,0 +1,55 @@
+// 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_SHELL_APP_SHELL_BREAKPAD_CLIENT_H_
+#define CONTENT_SHELL_APP_SHELL_BREAKPAD_CLIENT_H_
+
+#include "base/compiler_specific.h"
+#include "components/breakpad/app/breakpad_client.h"
+
+namespace content {
+
+class ShellBreakpadClient : public breakpad::BreakpadClient {
+ public:
+ ShellBreakpadClient();
+ virtual ~ShellBreakpadClient();
+
+#if defined(OS_WIN)
+ // Returns a textual description of the product type and version to include
+ // in the crash report.
+ virtual void GetProductNameAndVersion(const base::FilePath& exe_path,
+ base::string16* product_name,
+ base::string16* version,
+ base::string16* special_build,
+ base::string16* channel_name) OVERRIDE;
+#endif
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
+ // Returns a textual description of the product type and version to include
+ // in the crash report.
+ virtual void GetProductNameAndVersion(std::string* product_name,
+ std::string* version) OVERRIDE;
+
+ virtual base::FilePath GetReporterLogFilename() OVERRIDE;
+#endif
+
+ // The location where minidump files should be written. Returns true if
+ // |crash_dir| was set.
+ virtual bool GetCrashDumpLocation(base::FilePath* crash_dir) OVERRIDE;
+
+#if defined(OS_ANDROID)
+ // Returns the descriptor key of the android minidump global descriptor.
+ virtual int GetAndroidMinidumpDescriptor() OVERRIDE;
+#endif
+
+ virtual bool EnableBreakpadForProcess(
+ const std::string& process_type) OVERRIDE;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(ShellBreakpadClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_SHELL_APP_SHELL_BREAKPAD_CLIENT_H_
diff --git a/chromium/content/shell/app/shell_main_delegate.cc b/chromium/content/shell/app/shell_main_delegate.cc
index b5fbb8eccb8..9966c4a8867 100644
--- a/chromium/content/shell/app/shell_main_delegate.cc
+++ b/chromium/content/shell/app/shell_main_delegate.cc
@@ -4,8 +4,10 @@
#include "content/shell/app/shell_main_delegate.h"
+#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "cc/base/switches.h"
@@ -13,6 +15,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/layouttest_support.h"
+#include "content/shell/app/shell_breakpad_client.h"
#include "content/shell/app/webkit_test_platform_support.h"
#include "content/shell/browser/shell_browser_main.h"
#include "content/shell/browser/shell_content_browser_client.h"
@@ -22,6 +25,7 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"
+#include "ui/events/event_switches.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
@@ -41,17 +45,28 @@
#endif
#if defined(OS_MACOSX)
+#include "base/mac/os_crash_dumps.h"
+#include "components/breakpad/app/breakpad_mac.h"
#include "content/shell/app/paths_mac.h"
#include "content/shell/app/shell_main_delegate_mac.h"
#endif // OS_MACOSX
#if defined(OS_WIN)
#include <initguid.h>
+#include <windows.h>
#include "base/logging_win.h"
+#include "components/breakpad/app/breakpad_win.h"
+#endif
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
+#include "components/breakpad/app/breakpad_linux.h"
#endif
namespace {
+base::LazyInstance<content::ShellBreakpadClient>::Leaky
+ g_shell_breakpad_client = LAZY_INSTANCE_INITIALIZER;
+
#if defined(OS_WIN)
// If "Content Shell" doesn't show up in your list of trace providers in
// Sawbuck, add these registry entries to your machine (NOTE the optional
@@ -113,6 +128,7 @@ bool ShellMainDelegate::BasicStartupComplete(int* exit_code) {
return true;
}
}
+
if (command_line.HasSwitch(switches::kDumpRenderTree)) {
EnableBrowserLayoutTestMode();
@@ -140,15 +156,21 @@ bool ShellMainDelegate::BasicStartupComplete(int* exit_code) {
if (!command_line.HasSwitch(switches::kStableReleaseMode)) {
command_line.AppendSwitch(
switches::kEnableExperimentalWebPlatformFeatures);
- command_line.AppendSwitch(switches::kEnableCssShaders);
}
- if (!command_line.HasSwitch(switches::kEnableThreadedCompositing))
+ if (!command_line.HasSwitch(switches::kEnableThreadedCompositing)) {
+ command_line.AppendSwitch(switches::kDisableThreadedCompositing);
command_line.AppendSwitch(cc::switches::kDisableThreadedAnimation);
+ }
command_line.AppendSwitch(switches::kEnableInbandTextTracks);
command_line.AppendSwitch(switches::kMuteAudio);
+#if defined(USE_AURA)
+ // TODO: crbug.com/311404 Make layout tests work w/ delegated renderer.
+ command_line.AppendSwitch(switches::kDisableDelegatedRenderer);
+#endif
+
net::CookieMonster::EnableFileScheme();
// Unless/until WebM files are added to the media layout tests, we need to
@@ -168,6 +190,36 @@ bool ShellMainDelegate::BasicStartupComplete(int* exit_code) {
}
void ShellMainDelegate::PreSandboxStartup() {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableCrashReporter)) {
+ std::string process_type =
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kProcessType);
+ breakpad::SetBreakpadClient(g_shell_breakpad_client.Pointer());
+#if defined(OS_MACOSX)
+ base::mac::DisableOSCrashDumps();
+ breakpad::InitCrashReporter(process_type);
+ breakpad::InitCrashProcessInfo(process_type);
+#elif defined(OS_POSIX) && !defined(OS_MACOSX)
+ if (process_type != switches::kZygoteProcess) {
+#if defined(OS_ANDROID)
+ if (process_type.empty())
+ breakpad::InitCrashReporter(process_type);
+ else
+ breakpad::InitNonBrowserCrashReporterForAndroid(process_type);
+#else
+ breakpad::InitCrashReporter(process_type);
+#endif
+ }
+#elif defined(OS_WIN)
+ UINT new_flags =
+ SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
+ UINT existing_flags = SetErrorMode(new_flags);
+ SetErrorMode(existing_flags | new_flags);
+ breakpad::InitCrashReporter(process_type);
+#endif
+ }
+
InitializeResourceBundle();
}
@@ -187,6 +239,18 @@ int ShellMainDelegate::RunProcess(
return ShellBrowserMain(main_function_params, browser_runner_);
}
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+void ShellMainDelegate::ZygoteForked() {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableCrashReporter)) {
+ std::string process_type =
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kProcessType);
+ breakpad::InitCrashReporter(process_type);
+ }
+}
+#endif
+
void ShellMainDelegate::InitializeResourceBundle() {
#if defined(OS_ANDROID)
// In the Android case, the renderer runs with a different UID and can never
diff --git a/chromium/content/shell/app/shell_main_delegate.h b/chromium/content/shell/app/shell_main_delegate.h
index 73c6d04a9c9..2d69d08f45b 100644
--- a/chromium/content/shell/app/shell_main_delegate.h
+++ b/chromium/content/shell/app/shell_main_delegate.h
@@ -29,6 +29,9 @@ class ShellMainDelegate : public ContentMainDelegate {
virtual int RunProcess(
const std::string& process_type,
const MainFunctionParams& main_function_params) OVERRIDE;
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+ virtual void ZygoteForked() OVERRIDE;
+#endif
virtual ContentBrowserClient* CreateContentBrowserClient() OVERRIDE;
virtual ContentRendererClient* CreateContentRendererClient() OVERRIDE;
diff --git a/chromium/content/shell/browser/minimal_shell.cc b/chromium/content/shell/browser/minimal_shell.cc
deleted file mode 100644
index e7e88f8ab94..00000000000
--- a/chromium/content/shell/browser/minimal_shell.cc
+++ /dev/null
@@ -1,54 +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/shell/browser/minimal_shell.h"
-
-#include "ui/aura/client/default_capture_client.h"
-#include "ui/aura/focus_manager.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/test/test_activation_client.h"
-#include "ui/views/corewm/compound_event_filter.h"
-#include "ui/views/corewm/input_method_event_filter.h"
-
-namespace content {
-
-MinimalShell::MinimalShell(const gfx::Size& default_window_size) {
- root_window_.reset(new aura::RootWindow(
- aura::RootWindow::CreateParams(
- gfx::Rect(default_window_size))));
- root_window_->Init();
- aura::client::SetStackingClient(root_window_.get(), this);
-
- focus_client_.reset(new aura::FocusManager);
- aura::client::SetFocusClient(root_window_.get(), focus_client_.get());
-
- root_window_event_filter_ = new views::corewm::CompoundEventFilter;
- // Pass ownership of the filter to the root_window.
- root_window_->SetEventFilter(root_window_event_filter_);
-
- input_method_filter_.reset(new views::corewm::InputMethodEventFilter(
- root_window_->GetAcceleratedWidget()));
- input_method_filter_->SetInputMethodPropertyInRootWindow(
- root_window_.get());
- root_window_event_filter_->AddHandler(input_method_filter_.get());
-
- test_activation_client_.reset(
- new aura::test::TestActivationClient(root_window_.get()));
-
- capture_client_.reset(
- new aura::client::DefaultCaptureClient(root_window_.get()));
-}
-
-MinimalShell::~MinimalShell() {
- root_window_event_filter_->RemoveHandler(input_method_filter_.get());
-}
-
-aura::Window* MinimalShell::GetDefaultParent(
- aura::Window* context,
- aura::Window* window,
- const gfx::Rect& bounds) {
- return root_window_.get();
-}
-
-} // namespace content
diff --git a/chromium/content/shell/browser/minimal_shell.h b/chromium/content/shell/browser/minimal_shell.h
deleted file mode 100644
index 1388da964b3..00000000000
--- a/chromium/content/shell/browser/minimal_shell.h
+++ /dev/null
@@ -1,67 +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_SHELL_BROWSER_MINIMAL_SHELL_H_
-#define CONTENT_SHELL_BROWSER_MINIMAL_SHELL_H_
-
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/stacking_client.h"
-
-namespace aura {
-class RootWindow;
-class Window;
-namespace client {
-class DefaultCaptureClient;
-class FocusClient;
-}
-namespace test {
-class TestActivationClient;
-}
-}
-
-namespace gfx {
-class Rect;
-class Size;
-}
-
-namespace views {
-namespace corewm {
-class CompoundEventFilter;
-class InputMethodEventFilter;
-}
-}
-
-namespace content {
-
-// Creates a minimal environment for running the shell. We can't pull in all of
-// ash here, but we can create attach several of the same things we'd find in
-// the ash parts of the code.
-class MinimalShell : public aura::client::StackingClient {
- public:
- explicit MinimalShell(const gfx::Size& default_window_size);
- virtual ~MinimalShell();
-
- // Overridden from client::StackingClient:
- virtual aura::Window* GetDefaultParent(aura::Window* context,
- aura::Window* window,
- const gfx::Rect& bounds) OVERRIDE;
-
- private:
- scoped_ptr<aura::RootWindow> root_window_;
-
- // Owned by RootWindow
- views::corewm::CompoundEventFilter* root_window_event_filter_;
-
- scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
- scoped_ptr<views::corewm::InputMethodEventFilter> input_method_filter_;
- scoped_ptr<aura::test::TestActivationClient> test_activation_client_;
- scoped_ptr<aura::client::FocusClient> focus_client_;
-
- DISALLOW_COPY_AND_ASSIGN(MinimalShell);
-};
-
-} // namespace content;
-
-#endif // CONTENT_SHELL_BROWSER_MINIMAL_SHELL_H_
diff --git a/chromium/content/shell/browser/shell.cc b/chromium/content/shell/browser/shell.cc
index df096555b42..41b592f39a2 100644
--- a/chromium/content/shell/browser/shell.cc
+++ b/chromium/content/shell/browser/shell.cc
@@ -15,9 +15,6 @@
#include "content/public/browser/devtools_manager.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
@@ -32,6 +29,10 @@
#include "content/shell/common/shell_messages.h"
#include "content/shell/common/shell_switches.h"
+#if defined(USE_AURA) && !defined(TOOLKIT_VIEWS)
+#include "content/shell/browser/shell_aura.h"
+#endif
+
namespace content {
const int Shell::kDefaultTestWindowWidthDip = 800;
@@ -61,7 +62,8 @@ class Shell::DevToolsWebContentsObserver : public WebContentsObserver {
};
Shell::Shell(WebContents* web_contents)
- : devtools_frontend_(NULL),
+ : WebContentsObserver(web_contents),
+ devtools_frontend_(NULL),
is_fullscreen_(false),
window_(NULL),
url_edit_view_(NULL),
@@ -72,8 +74,6 @@ Shell::Shell(WebContents* web_contents)
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kDumpRenderTree))
headless_ = true;
- registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
- Source<WebContents>(web_contents));
windows_.push_back(this);
if (!shell_created_callback_.is_null()) {
@@ -123,6 +123,7 @@ void Shell::CloseAllWindows() {
std::vector<Shell*> open_windows(windows_);
for (size_t i = 0; i < open_windows.size(); ++i)
open_windows[i]->Close();
+ PlatformExit();
base::MessageLoop::current()->RunUntilIdle();
}
@@ -148,6 +149,12 @@ void Shell::Initialize() {
gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip));
}
+gfx::Size Shell::AdjustWindowSize(const gfx::Size& initial_size) {
+ if (!initial_size.IsEmpty())
+ return initial_size;
+ return gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip);
+}
+
Shell* Shell::CreateNewWindow(BrowserContext* browser_context,
const GURL& url,
SiteInstance* site_instance,
@@ -155,11 +162,7 @@ Shell* Shell::CreateNewWindow(BrowserContext* browser_context,
const gfx::Size& initial_size) {
WebContents::CreateParams create_params(browser_context, site_instance);
create_params.routing_id = routing_id;
- if (!initial_size.IsEmpty())
- create_params.initial_size = initial_size;
- else
- create_params.initial_size =
- gfx::Size(kDefaultTestWindowWidthDip, kDefaultTestWindowHeightDip);
+ create_params.initial_size = AdjustWindowSize(initial_size);
WebContents* web_contents = WebContents::Create(create_params);
Shell* shell = CreateShell(web_contents, create_params.initial_size);
if (!url.is_empty())
@@ -180,6 +183,17 @@ void Shell::LoadURLForFrame(const GURL& url, const std::string& frame_name) {
web_contents_->GetView()->Focus();
}
+void Shell::AddNewContents(WebContents* source,
+ WebContents* new_contents,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture,
+ bool* was_blocked) {
+ CreateShell(new_contents, AdjustWindowSize(initial_pos.size()));
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
+ NotifyDoneForwarder::CreateForWebContents(new_contents);
+}
+
void Shell::GoBackOrForward(int offset) {
web_contents_->GetController().GoToOffset(offset);
web_contents_->GetView()->Focus();
@@ -235,6 +249,7 @@ WebContents* Shell::OpenURLFromTab(WebContents* source,
return NULL;
NavigationController::LoadURLParams load_url_params(params.url);
load_url_params.referrer = params.referrer;
+ load_url_params.frame_tree_node_id = params.frame_tree_node_id;
load_url_params.transition_type = params.transition;
load_url_params.extra_headers = params.extra_headers;
load_url_params.should_replace_current_entry =
@@ -296,16 +311,6 @@ bool Shell::CanOverscrollContent() const {
#endif
}
-void Shell::WebContentsCreated(WebContents* source_contents,
- int64 source_frame_id,
- const string16& frame_name,
- const GURL& target_url,
- WebContents* new_contents) {
- CreateShell(new_contents, source_contents->GetView()->GetContainerSize());
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
- NotifyDoneForwarder::CreateForWebContents(new_contents);
-}
-
void Shell::DidNavigateMainFramePostCommit(WebContents* web_contents) {
PlatformSetAddressBarURL(web_contents->GetLastCommittedURL());
}
@@ -318,9 +323,9 @@ JavaScriptDialogManager* Shell::GetJavaScriptDialogManager() {
bool Shell::AddMessageToConsole(WebContents* source,
int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id) {
+ const base::string16& source_id) {
return CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree);
}
@@ -344,20 +349,9 @@ void Shell::WorkerCrashed(WebContents* source) {
WebKitTestController::Get()->WorkerCrashed();
}
-void Shell::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- if (type == NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED) {
- std::pair<NavigationEntry*, bool>* title =
- Details<std::pair<NavigationEntry*, bool> >(details).ptr();
-
- if (title->first) {
- string16 text = title->first->GetTitle();
- PlatformSetTitle(text);
- }
- } else {
- NOTREACHED();
- }
+void Shell::TitleWasSet(NavigationEntry* entry, bool explicit_set) {
+ if (entry)
+ PlatformSetTitle(entry->GetTitle());
}
void Shell::OnDevToolsWebContentsDestroyed() {
diff --git a/chromium/content/shell/browser/shell.h b/chromium/content/shell/browser/shell.h
index 24c58c81a17..1434b76c119 100644
--- a/chromium/content/shell/browser/shell.h
+++ b/chromium/content/shell/browser/shell.h
@@ -11,9 +11,9 @@
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "build/build_config.h"
#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/browser/web_contents_observer.h"
#include "ipc/ipc_channel.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
@@ -27,19 +27,23 @@ typedef struct _GtkToolItem GtkToolItem;
#include "base/android/scoped_java_ref.h"
#elif defined(USE_AURA)
#if defined(OS_CHROMEOS)
-namespace content {
-class MinimalShell;
+namespace wm {
+class WMTestHelper;
}
-#endif
+#endif // defined(OS_CHROMEOS)
namespace views {
class Widget;
class ViewsDelegate;
}
-#endif
+#endif // defined(USE_AURA)
class GURL;
namespace content {
+#if defined(USE_AURA)
+class ShellAuraPlatformData;
+#endif
+
class BrowserContext;
class ShellDevToolsFrontend;
class ShellJavaScriptDialogManager;
@@ -49,7 +53,7 @@ class WebContents;
// This represents one window of the Content Shell, i.e. all the UI including
// buttons and url bar, as well as the web content area.
class Shell : public WebContentsDelegate,
- public NotificationObserver {
+ public WebContentsObserver {
public:
static const int kDefaultTestWindowWidthDip;
static const int kDefaultTestWindowHeightDip;
@@ -68,7 +72,7 @@ class Shell : public WebContentsDelegate,
#if (defined(OS_WIN) && !defined(USE_AURA)) || \
defined(TOOLKIT_GTK) || defined(OS_MACOSX)
// Resizes the main window to the given dimensions.
- void SizeTo(int width, int height);
+ void SizeTo(const gfx::Size& content_size);
#endif
// Do one time initialization at application startup.
@@ -89,9 +93,6 @@ class Shell : public WebContentsDelegate,
// Closes all windows and returns. This runs a message loop.
static void CloseAllWindows();
- // Closes all windows and exits.
- static void PlatformExit();
-
// Used for content_browsertests. Called once.
static void SetShellCreatedCallback(
base::Callback<void(Shell*)> shell_created_callback);
@@ -111,6 +112,12 @@ class Shell : public WebContentsDelegate,
// WebContentsDelegate
virtual WebContents* OpenURLFromTab(WebContents* source,
const OpenURLParams& params) OVERRIDE;
+ virtual void AddNewContents(WebContents* source,
+ WebContents* new_contents,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture,
+ bool* was_blocked) OVERRIDE;
virtual void LoadingStateChanged(WebContents* source) OVERRIDE;
#if defined(OS_ANDROID)
virtual void LoadProgressChanged(WebContents* source,
@@ -125,11 +132,6 @@ class Shell : public WebContentsDelegate,
bool last_unlocked_by_target) OVERRIDE;
virtual void CloseContents(WebContents* source) OVERRIDE;
virtual bool CanOverscrollContent() const OVERRIDE;
- virtual void WebContentsCreated(WebContents* source_contents,
- int64 source_frame_id,
- const string16& frame_name,
- const GURL& target_url,
- WebContents* new_contents) OVERRIDE;
virtual void DidNavigateMainFramePostCommit(
WebContents* web_contents) OVERRIDE;
virtual JavaScriptDialogManager* GetJavaScriptDialogManager() OVERRIDE;
@@ -140,9 +142,9 @@ class Shell : public WebContentsDelegate,
#endif
virtual bool AddMessageToConsole(WebContents* source,
int32 level,
- const string16& message,
+ const base::string16& message,
int32 line_no,
- const string16& source_id) OVERRIDE;
+ const base::string16& source_id) OVERRIDE;
virtual void RendererUnresponsive(WebContents* source) OVERRIDE;
virtual void ActivateContents(WebContents* contents) OVERRIDE;
virtual void DeactivateContents(WebContents* contents) OVERRIDE;
@@ -165,6 +167,12 @@ class Shell : public WebContentsDelegate,
// Helper for one time initialization of application
static void PlatformInitialize(const gfx::Size& default_window_size);
+ // Helper for one time deinitialization of platform specific state.
+ static void PlatformExit();
+
+ // Adjust the size when Blink sends 0 for width and/or height.
+ // This happens when Blink requests a default-sized window.
+ static gfx::Size AdjustWindowSize(const gfx::Size& initial_size);
// All the methods that begin with Platform need to be implemented by the
// platform specific Shell implementation.
@@ -183,7 +191,7 @@ class Shell : public WebContentsDelegate,
// Sets whether the spinner is spinning.
void PlatformSetIsLoading(bool loading);
// Set the title of shell window
- void PlatformSetTitle(const string16& title);
+ void PlatformSetTitle(const base::string16& title);
#if defined(OS_ANDROID)
void PlatformToggleFullscreenModeForTab(WebContents* web_contents,
bool enter_fullscreen);
@@ -193,10 +201,8 @@ class Shell : public WebContentsDelegate,
gfx::NativeView GetContentView();
- // NotificationObserver
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ // WebContentsObserver
+ virtual void TitleWasSet(NavigationEntry* entry, bool explicit_set) OVERRIDE;
void OnDevToolsWebContentsDestroyed();
@@ -234,8 +240,7 @@ class Shell : public WebContentsDelegate,
gfx::NativeWindow window_;
gfx::NativeEditView url_edit_view_;
- // Notification manager
- NotificationRegistrar registrar_;
+ gfx::Size content_size_;
#if defined(OS_WIN) && !defined(USE_AURA)
WNDPROC default_edit_wnd_proc_;
@@ -251,21 +256,20 @@ class Shell : public WebContentsDelegate,
GtkWidget* spinner_;
GtkToolItem* spinner_item_;
- int content_width_;
- int content_height_;
int ui_elements_height_; // height of menubar, toolbar, etc.
#elif defined(OS_ANDROID)
base::android::ScopedJavaGlobalRef<jobject> java_object_;
#elif defined(USE_AURA)
#if defined(OS_CHROMEOS)
- static content::MinimalShell* minimal_shell_;
+ static wm::WMTestHelper* wm_test_helper_;
#endif
+#if defined(TOOLKIT_VIEWS)
static views::ViewsDelegate* views_delegate_;
views::Widget* window_widget_;
-#elif defined(OS_MACOSX)
- int content_width_;
- int content_height_;
+#else // defined(TOOLKIT_VIEWS)
+ static ShellAuraPlatformData* platform_;
+#endif // defined(TOOLKIT_VIEWS)
#endif
bool headless_;
diff --git a/chromium/content/shell/browser/shell_android.cc b/chromium/content/shell/browser/shell_android.cc
index d827e96b07e..b11ba37abaa 100644
--- a/chromium/content/shell/browser/shell_android.cc
+++ b/chromium/content/shell/browser/shell_android.cc
@@ -26,6 +26,9 @@ void Shell::PlatformInitialize(const gfx::Size& default_window_size) {
DCHECK(command_line->HasSwitch(switches::kEnableThreadedCompositing));
}
+void Shell::PlatformExit() {
+}
+
void Shell::PlatformCleanUp() {
}
@@ -50,14 +53,14 @@ void Shell::PlatformCreateWindow(int width, int height) {
void Shell::PlatformSetContents() {
JNIEnv* env = AttachCurrentThread();
Java_Shell_initFromNativeTabContents(
- env, java_object_.obj(), reinterpret_cast<jint>(web_contents()));
+ env, java_object_.obj(), reinterpret_cast<intptr_t>(web_contents()));
}
void Shell::PlatformResizeSubViews() {
// Not needed; subviews are bound.
}
-void Shell::PlatformSetTitle(const string16& title) {
+void Shell::PlatformSetTitle(const base::string16& title) {
NOTIMPLEMENTED();
}
diff --git a/chromium/content/shell/browser/shell_aura.cc b/chromium/content/shell/browser/shell_aura.cc
index da8460edd05..ccaffb7344f 100644
--- a/chromium/content/shell/browser/shell_aura.cc
+++ b/chromium/content/shell/browser/shell_aura.cc
@@ -4,317 +4,163 @@
#include "content/shell/browser/shell.h"
-#include "base/command_line.h"
-#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
+#include "content/shell/browser/shell_aura.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/client/default_activation_client.h"
+#include "ui/aura/client/default_capture_client.h"
#include "ui/aura/env.h"
+#include "ui/aura/layout_manager.h"
#include "ui/aura/root_window.h"
+#include "ui/aura/test/test_focus_client.h"
+#include "ui/aura/test/test_screen.h"
+#include "ui/aura/test/test_window_tree_client.h"
#include "ui/aura/window.h"
-#include "ui/base/accessibility/accessibility_types.h"
-#include "ui/base/clipboard/clipboard.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/events/event.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/base/ime/input_method_delegate.h"
+#include "ui/base/ime/input_method_factory.h"
#include "ui/gfx/screen.h"
-#include "ui/views/controls/button/label_button.h"
-#include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/controls/textfield/textfield_controller.h"
-#include "ui/views/controls/webview/webview.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/layout/grid_layout.h"
-#include "ui/views/test/desktop_test_views_delegate.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/desktop_aura/desktop_screen.h"
-#include "ui/views/widget/widget.h"
-#include "ui/views/widget/widget_delegate.h"
-
-#if defined(OS_CHROMEOS)
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "content/shell/browser/minimal_shell.h"
-#include "ui/aura/test/test_screen.h"
-#endif
-
-#if defined(OS_WIN)
-#include <fcntl.h>
-#include <io.h>
-#endif
namespace content {
namespace {
-// ViewDelegate implementation for aura content shell
-class ShellViewsDelegateAura : public views::DesktopTestViewsDelegate {
+
+class FillLayout : public aura::LayoutManager {
public:
- ShellViewsDelegateAura() : use_transparent_windows_(false) {
+ explicit FillLayout(aura::RootWindow* root)
+ : root_(root) {
}
- virtual ~ShellViewsDelegateAura() {
- }
+ virtual ~FillLayout() {}
- void SetUseTransparentWindows(bool transparent) {
- use_transparent_windows_ = transparent;
+ private:
+ // aura::LayoutManager:
+ virtual void OnWindowResized() OVERRIDE {
}
- // Overridden from views::TestViewsDelegate:
- virtual bool UseTransparentWindows() const OVERRIDE {
- return use_transparent_windows_;
+ virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
+ child->SetBounds(gfx::Rect(root_->host()->GetBounds().size()));
}
- private:
- bool use_transparent_windows_;
-
- DISALLOW_COPY_AND_ASSIGN(ShellViewsDelegateAura);
-};
-
-// Maintain the UI controls and web view for content shell
-class ShellWindowDelegateView : public views::WidgetDelegateView,
- public views::TextfieldController,
- public views::ButtonListener {
- public:
- enum UIControl {
- BACK_BUTTON,
- FORWARD_BUTTON,
- STOP_BUTTON
- };
-
- ShellWindowDelegateView(Shell* shell)
- : shell_(shell),
- toolbar_view_(new View),
- contents_view_(new View) {
+ virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {
}
- virtual ~ShellWindowDelegateView() {}
- // Update the state of UI controls
- void SetAddressBarURL(const GURL& url) {
- url_entry_->SetText(ASCIIToUTF16(url.spec()));
- }
- void SetWebContents(WebContents* web_contents) {
- contents_view_->SetLayoutManager(new views::FillLayout());
- web_view_ = new views::WebView(web_contents->GetBrowserContext());
- web_view_->SetWebContents(web_contents);
- web_contents->GetView()->Focus();
- contents_view_->AddChildView(web_view_);
- Layout();
+ virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {
}
- void SetWindowTitle(const string16& title) { title_ = title; }
- void EnableUIControl(UIControl control, bool is_enabled) {
- if (control == BACK_BUTTON) {
- back_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
- : views::CustomButton::STATE_DISABLED);
- } else if (control == FORWARD_BUTTON) {
- forward_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
- : views::CustomButton::STATE_DISABLED);
- } else if (control == STOP_BUTTON) {
- stop_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
- : views::CustomButton::STATE_DISABLED);
- }
+
+ virtual void OnChildWindowVisibilityChanged(aura::Window* child,
+ bool visible) OVERRIDE {
}
- private:
- // Initialize the UI control contained in shell window
- void InitShellWindow() {
- set_background(views::Background::CreateStandardPanelBackground());
-
- views::GridLayout* layout = new views::GridLayout(this);
- SetLayoutManager(layout);
-
- views::ColumnSet* column_set = layout->AddColumnSet(0);
- column_set->AddPaddingColumn(0, 2);
- column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
- views::GridLayout::USE_PREF, 0, 0);
- column_set->AddPaddingColumn(0, 2);
-
- layout->AddPaddingRow(0, 2);
-
- // Add toolbar buttons and URL text field
- {
- layout->StartRow(0, 0);
- views::GridLayout* toolbar_layout = new views::GridLayout(toolbar_view_);
- toolbar_view_->SetLayoutManager(toolbar_layout);
-
- views::ColumnSet* toolbar_column_set =
- toolbar_layout->AddColumnSet(0);
- // Back button
- back_button_ = new views::LabelButton(this, ASCIIToUTF16("Back"));
- back_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
- gfx::Size back_button_size = back_button_->GetPreferredSize();
- toolbar_column_set->AddColumn(views::GridLayout::CENTER,
- views::GridLayout::CENTER, 0,
- views::GridLayout::FIXED,
- back_button_size.width(),
- back_button_size.width() / 2);
- // Forward button
- forward_button_ = new views::LabelButton(this, ASCIIToUTF16("Forward"));
- forward_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
- gfx::Size forward_button_size = forward_button_->GetPreferredSize();
- toolbar_column_set->AddColumn(views::GridLayout::CENTER,
- views::GridLayout::CENTER, 0,
- views::GridLayout::FIXED,
- forward_button_size.width(),
- forward_button_size.width() / 2);
- // Refresh button
- refresh_button_ = new views::LabelButton(this, ASCIIToUTF16("Refresh"));
- refresh_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
- gfx::Size refresh_button_size = refresh_button_->GetPreferredSize();
- toolbar_column_set->AddColumn(views::GridLayout::CENTER,
- views::GridLayout::CENTER, 0,
- views::GridLayout::FIXED,
- refresh_button_size.width(),
- refresh_button_size.width() / 2);
- // Stop button
- stop_button_ = new views::LabelButton(this, ASCIIToUTF16("Stop"));
- stop_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
- gfx::Size stop_button_size = stop_button_->GetPreferredSize();
- toolbar_column_set->AddColumn(views::GridLayout::CENTER,
- views::GridLayout::CENTER, 0,
- views::GridLayout::FIXED,
- stop_button_size.width(),
- stop_button_size.width() / 2);
- toolbar_column_set->AddPaddingColumn(0, 2);
- // URL entry
- url_entry_ = new views::Textfield();
- url_entry_->SetController(this);
- toolbar_column_set->AddColumn(views::GridLayout::FILL,
- views::GridLayout::FILL, 1,
- views::GridLayout::USE_PREF, 0, 0);
-
- // Fill up the first row
- toolbar_layout->StartRow(0, 0);
- toolbar_layout->AddView(back_button_);
- toolbar_layout->AddView(forward_button_);
- toolbar_layout->AddView(refresh_button_);
- toolbar_layout->AddView(stop_button_);
- toolbar_layout->AddView(url_entry_);
-
- layout->AddView(toolbar_view_);
- }
+ virtual void SetChildBounds(aura::Window* child,
+ const gfx::Rect& requested_bounds) OVERRIDE {
+ SetChildBoundsDirect(child, requested_bounds);
+ }
- layout->AddPaddingRow(0, 5);
+ aura::RootWindow* root_;
- // Add web contents view as the second row
- {
- layout->StartRow(1, 0);
- layout->AddView(contents_view_);
- }
+ DISALLOW_COPY_AND_ASSIGN(FillLayout);
+};
- layout->AddPaddingRow(0, 5);
- }
- // Overridden from TextfieldController
- virtual void ContentsChanged(views::Textfield* sender,
- const string16& new_contents) OVERRIDE {
- }
- virtual bool HandleKeyEvent(views::Textfield* sender,
- const ui::KeyEvent& key_event) OVERRIDE {
- if (sender == url_entry_ && key_event.key_code() == ui::VKEY_RETURN) {
- std::string text = UTF16ToUTF8(url_entry_->text());
- GURL url(text);
- if (!url.has_scheme()) {
- url = GURL(std::string("http://") + std::string(text));
- url_entry_->SetText(ASCIIToUTF16(url.spec()));
- }
- shell_->LoadURL(url);
- return true;
- }
- return false;
+class MinimalInputEventFilter : public ui::internal::InputMethodDelegate,
+ public ui::EventHandler {
+ public:
+ explicit MinimalInputEventFilter(aura::RootWindow* root)
+ : root_(root),
+ input_method_(ui::CreateInputMethod(this,
+ gfx::kNullAcceleratedWidget)) {
+ input_method_->Init(true);
+ root_->window()->AddPreTargetHandler(this);
+ root_->window()->SetProperty(aura::client::kRootWindowInputMethodKey,
+ input_method_.get());
}
- // Overridden from ButtonListener
- virtual void ButtonPressed(views::Button* sender,
- const ui::Event& event) OVERRIDE {
- if (sender == back_button_)
- shell_->GoBackOrForward(-1);
- else if (sender == forward_button_)
- shell_->GoBackOrForward(1);
- else if (sender == refresh_button_)
- shell_->Reload();
- else if (sender == stop_button_)
- shell_->Stop();
+ virtual ~MinimalInputEventFilter() {
+ root_->window()->RemovePreTargetHandler(this);
+ root_->window()->SetProperty(aura::client::kRootWindowInputMethodKey,
+ static_cast<ui::InputMethod*>(NULL));
}
- // Overridden from WidgetDelegateView
- virtual bool CanResize() const OVERRIDE { return true; }
- virtual bool CanMaximize() const OVERRIDE { return true; }
- virtual string16 GetWindowTitle() const OVERRIDE {
- return title_;
- }
- virtual void WindowClosing() OVERRIDE {
- if (shell_) {
- delete shell_;
- shell_ = NULL;
+ private:
+ // ui::EventHandler:
+ virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
+ const ui::EventType type = event->type();
+ if (type == ui::ET_TRANSLATED_KEY_PRESS ||
+ type == ui::ET_TRANSLATED_KEY_RELEASE) {
+ // The |event| is already handled by this object, change the type of the
+ // event to ui::ET_KEY_* and pass it to the next filter.
+ static_cast<ui::TranslatedKeyEvent*>(event)->ConvertToKeyEvent();
+ } else {
+ if (input_method_->DispatchKeyEvent(*event))
+ event->StopPropagation();
}
}
- virtual View* GetContentsView() OVERRIDE { return this; }
- // Overridden from View
- virtual void ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) OVERRIDE {
- if (details.is_add && details.child == this) {
- InitShellWindow();
- }
+ // ui::InputMethodDelegate:
+ virtual bool DispatchKeyEventPostIME(
+ const base::NativeEvent& event) OVERRIDE {
+ ui::TranslatedKeyEvent aura_event(event, false /* is_char */);
+ return root_->AsRootWindowHostDelegate()->OnHostKeyEvent(
+ &aura_event);
}
- private:
- // Hold a reference of Shell for deleting it when the window is closing
- Shell* shell_;
+ virtual bool DispatchFabricatedKeyEventPostIME(ui::EventType type,
+ ui::KeyboardCode key_code,
+ int flags) OVERRIDE {
+ ui::TranslatedKeyEvent aura_event(type == ui::ET_KEY_PRESSED, key_code,
+ flags);
+ return root_->AsRootWindowHostDelegate()->OnHostKeyEvent(
+ &aura_event);
+ }
- // Window title
- string16 title_;
+ aura::RootWindow* root_;
+ scoped_ptr<ui::InputMethod> input_method_;
- // Toolbar view contains forward/backward/reload button and URL entry
- View* toolbar_view_;
- views::LabelButton* back_button_;
- views::LabelButton* forward_button_;
- views::LabelButton* refresh_button_;
- views::LabelButton* stop_button_;
- views::Textfield* url_entry_;
+ DISALLOW_COPY_AND_ASSIGN(MinimalInputEventFilter);
+};
- // Contents view contains the web contents view
- View* contents_view_;
- views::WebView* web_view_;
+}
- DISALLOW_COPY_AND_ASSIGN(ShellWindowDelegateView);
-};
+ShellAuraPlatformData* Shell::platform_ = NULL;
+
+ShellAuraPlatformData::ShellAuraPlatformData() {
+ aura::TestScreen* screen = aura::TestScreen::Create();
+ gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen);
+ root_window_.reset(screen->CreateRootWindowForPrimaryDisplay());
+ root_window_->host()->Show();
+ root_window_->window()->SetLayoutManager(new FillLayout(root_window_.get()));
+
+ focus_client_.reset(new aura::test::TestFocusClient());
+ aura::client::SetFocusClient(root_window_->window(), focus_client_.get());
+
+ activation_client_.reset(
+ new aura::client::DefaultActivationClient(root_window_->window()));
+ capture_client_.reset(
+ new aura::client::DefaultCaptureClient(root_window_->window()));
+ window_tree_client_.reset(
+ new aura::test::TestWindowTreeClient(root_window_->window()));
+ ime_filter_.reset(new MinimalInputEventFilter(root_window_.get()));
+}
-} // namespace
+ShellAuraPlatformData::~ShellAuraPlatformData() {
+}
-#if defined(OS_CHROMEOS)
-MinimalShell* Shell::minimal_shell_ = NULL;
-#endif
-views::ViewsDelegate* Shell::views_delegate_ = NULL;
+void ShellAuraPlatformData::ResizeWindow(int width, int height) {
+ root_window_->SetHostSize(gfx::Size(width, height));
+}
// static
void Shell::PlatformInitialize(const gfx::Size& default_window_size) {
-#if defined(OS_WIN)
- _setmode(_fileno(stdout), _O_BINARY);
- _setmode(_fileno(stderr), _O_BINARY);
-#endif
-#if defined(OS_CHROMEOS)
- chromeos::DBusThreadManager::Initialize();
- gfx::Screen::SetScreenInstance(
- gfx::SCREEN_TYPE_NATIVE, aura::TestScreen::Create());
- minimal_shell_ = new content::MinimalShell(default_window_size);
-#else
- gfx::Screen::SetScreenInstance(
- gfx::SCREEN_TYPE_NATIVE, views::CreateDesktopScreen());
-#endif
- views_delegate_ = new ShellViewsDelegateAura();
+ CHECK(!platform_);
+ aura::Env::CreateInstance();
+ platform_ = new ShellAuraPlatformData();
}
void Shell::PlatformExit() {
- std::vector<Shell*> windows = windows_;
- for (std::vector<Shell*>::iterator it = windows.begin();
- it != windows.end(); ++it) {
- (*it)->window_widget_->Close();
- }
-#if defined(OS_CHROMEOS)
- if (minimal_shell_)
- delete minimal_shell_;
-#endif
- if (views_delegate_)
- delete views_delegate_;
-#if defined(OS_CHROMEOS)
- chromeos::DBusThreadManager::Shutdown();
-#endif
+ CHECK(platform_);
+ delete platform_;
+ platform_ = NULL;
aura::Env::DeleteInstance();
}
@@ -322,67 +168,37 @@ void Shell::PlatformCleanUp() {
}
void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) {
- ShellWindowDelegateView* delegate_view =
- static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
- if (control == BACK_BUTTON) {
- delegate_view->EnableUIControl(ShellWindowDelegateView::BACK_BUTTON,
- is_enabled);
- } else if (control == FORWARD_BUTTON) {
- delegate_view->EnableUIControl(ShellWindowDelegateView::FORWARD_BUTTON,
- is_enabled);
- } else if (control == STOP_BUTTON) {
- delegate_view->EnableUIControl(ShellWindowDelegateView::STOP_BUTTON,
- is_enabled);
- }
}
void Shell::PlatformSetAddressBarURL(const GURL& url) {
- ShellWindowDelegateView* delegate_view =
- static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
- delegate_view->SetAddressBarURL(url);
}
void Shell::PlatformSetIsLoading(bool loading) {
}
void Shell::PlatformCreateWindow(int width, int height) {
-#if defined(OS_CHROMEOS)
- window_widget_ =
- views::Widget::CreateWindowWithContextAndBounds(
- new ShellWindowDelegateView(this),
- minimal_shell_->GetDefaultParent(NULL, NULL, gfx::Rect()),
- gfx::Rect(0, 0, width, height));
-#else
- window_widget_ =
- views::Widget::CreateWindowWithBounds(new ShellWindowDelegateView(this),
- gfx::Rect(0, 0, width, height));
-#endif
-
- window_ = window_widget_->GetNativeWindow();
- // Call ShowRootWindow on RootWindow created by MinimalShell without
- // which XWindow owned by RootWindow doesn't get mapped.
- window_->GetRootWindow()->ShowRootWindow();
- window_widget_->Show();
+ CHECK(platform_);
+ platform_->ResizeWindow(width, height);
}
void Shell::PlatformSetContents() {
- ShellWindowDelegateView* delegate_view =
- static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
- delegate_view->SetWebContents(web_contents_.get());
+ CHECK(platform_);
+ aura::Window* content = web_contents_->GetView()->GetNativeView();
+ aura::Window* parent = platform_->window()->window();
+ if (parent->Contains(content))
+ return;
+ parent->AddChild(content);
+ content->Show();
}
void Shell::PlatformResizeSubViews() {
}
void Shell::Close() {
- window_widget_->CloseNow();
+ web_contents_.reset();
}
-void Shell::PlatformSetTitle(const string16& title) {
- ShellWindowDelegateView* delegate_view =
- static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
- delegate_view->SetWindowTitle(title);
- window_widget_->UpdateWindowTitle();
+void Shell::PlatformSetTitle(const base::string16& title) {
}
} // namespace content
diff --git a/chromium/content/shell/browser/shell_aura.h b/chromium/content/shell/browser/shell_aura.h
new file mode 100644
index 00000000000..f3f6692244b
--- /dev/null
+++ b/chromium/content/shell/browser/shell_aura.h
@@ -0,0 +1,48 @@
+// 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_SHELL_BROWSER_SHELL_AURA_H_
+#define CONTENT_SHELL_BROWSER_SHELL_AURA_H_
+
+#include "base/memory/scoped_ptr.h"
+
+namespace aura {
+namespace client {
+class DefaultActivationClient;
+class DefaultCaptureClient;
+class FocusClient;
+class WindowTreeClient;
+}
+class RootWindow;
+}
+
+namespace ui {
+class EventHandler;
+}
+
+namespace content {
+
+class ShellAuraPlatformData {
+ public:
+ ShellAuraPlatformData();
+ ~ShellAuraPlatformData();
+
+ void ResizeWindow(int width, int height);
+
+ aura::RootWindow* window() { return root_window_.get(); }
+
+ private:
+ scoped_ptr<aura::RootWindow> root_window_;
+ scoped_ptr<aura::client::FocusClient> focus_client_;
+ scoped_ptr<aura::client::DefaultActivationClient> activation_client_;
+ scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
+ scoped_ptr<aura::client::WindowTreeClient> window_tree_client_;
+ scoped_ptr<ui::EventHandler> ime_filter_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellAuraPlatformData);
+};
+
+} // namespace content
+
+#endif // CONTENT_SHELL_BROWSER_SHELL_AURA_H_
diff --git a/chromium/content/shell/browser/shell_browser_context.cc b/chromium/content/shell/browser/shell_browser_context.cc
index c6dbb9940cb..2283fd9585b 100644
--- a/chromium/content/shell/browser/shell_browser_context.cc
+++ b/chromium/content/shell/browser/shell_browser_context.cc
@@ -107,7 +107,7 @@ void ShellBrowserContext::InitWhileIOAllowed() {
#endif
if (!base::PathExists(path_))
- file_util::CreateDirectory(path_);
+ base::CreateDirectory(path_);
}
base::FilePath ShellBrowserContext::GetPath() const {
@@ -179,6 +179,7 @@ net::URLRequestContextGetter*
void ShellBrowserContext::RequestMIDISysExPermission(
int render_process_id,
int render_view_id,
+ int bridge_id,
const GURL& requesting_frame,
const MIDISysExPermissionCallback& callback) {
// Always reject requests for LayoutTests for now.
@@ -191,6 +192,13 @@ void ShellBrowserContext::RequestMIDISysExPermission(
callback.Run(false);
}
+void ShellBrowserContext::CancelMIDISysExPermissionRequest(
+ int render_process_id,
+ int render_view_id,
+ int bridge_id,
+ const GURL& requesting_frame) {
+}
+
net::URLRequestContextGetter*
ShellBrowserContext::CreateRequestContextForStoragePartition(
const base::FilePath& partition_path,
diff --git a/chromium/content/shell/browser/shell_browser_context.h b/chromium/content/shell/browser/shell_browser_context.h
index ec7159166df..f49fa281a40 100644
--- a/chromium/content/shell/browser/shell_browser_context.h
+++ b/chromium/content/shell/browser/shell_browser_context.h
@@ -46,8 +46,14 @@ class ShellBrowserContext : public BrowserContext {
virtual void RequestMIDISysExPermission(
int render_process_id,
int render_view_id,
+ int bridge_id,
const GURL& requesting_frame,
const MIDISysExPermissionCallback& callback) OVERRIDE;
+ virtual void CancelMIDISysExPermissionRequest(
+ int render_process_id,
+ int render_view_id,
+ int bridge_id,
+ const GURL& requesting_frame) OVERRIDE;
virtual ResourceContext* GetResourceContext() OVERRIDE;
virtual GeolocationPermissionContext*
GetGeolocationPermissionContext() OVERRIDE;
diff --git a/chromium/content/shell/browser/shell_browser_main.cc b/chromium/content/shell/browser/shell_browser_main.cc
index 8e61f6a6b7c..ad2cbdaef9b 100644
--- a/chromium/content/shell/browser/shell_browser_main.cc
+++ b/chromium/content/shell/browser/shell_browser_main.cc
@@ -151,7 +151,7 @@ int ShellBrowserMain(
// We're outside of the message loop here, and this is a test.
base::ThreadRestrictions::ScopedAllowIO allow_io;
base::FilePath temp_path;
- file_util::GetTempDir(&temp_path);
+ base::GetTempDir(&temp_path);
test_controller.SetTempPath(temp_path);
}
std::string test_string;
@@ -160,10 +160,8 @@ int ShellBrowserMain(
size_t command_line_position = 0;
bool ran_at_least_once = false;
-#if defined(OS_ANDROID)
std::cout << "#READY\n";
std::cout.flush();
-#endif
while (GetNextTest(args, &command_line_position, &test_string)) {
if (test_string.empty())
diff --git a/chromium/content/shell/browser/shell_browser_main_parts.cc b/chromium/content/shell/browser/shell_browser_main_parts.cc
index 6f7da003583..a413393ab5a 100644
--- a/chromium/content/shell/browser/shell_browser_main_parts.cc
+++ b/chromium/content/shell/browser/shell_browser_main_parts.cc
@@ -4,6 +4,7 @@
#include "content/shell/browser/shell_browser_main_parts.h"
+#include "base/base_switches.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
@@ -34,12 +35,16 @@
#endif
#if defined(OS_ANDROID)
+#include "components/breakpad/browser/crash_dump_manager_android.h"
#include "net/android/network_change_notifier_factory_android.h"
#include "net/base/network_change_notifier.h"
#endif
#if defined(USE_AURA) && defined(USE_X11)
-#include "ui/base/touch/touch_factory_x11.h"
+#include "ui/events/x/touch_factory_x11.h"
+#if !defined(OS_CHROMEOS)
+#include "ui/base/ime/input_method_initializer.h"
+#endif
#endif
namespace content {
@@ -104,6 +109,9 @@ void ShellBrowserMainParts::PostMainMessageLoopStart() {
}
void ShellBrowserMainParts::PreEarlyInitialization() {
+#if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(USE_X11)
+ ui::InitializeInputMethodForTesting();
+#endif
#if defined(OS_ANDROID)
net::NetworkChangeNotifier::SetFactory(
new net::NetworkChangeNotifierFactoryAndroid());
@@ -114,6 +122,15 @@ void ShellBrowserMainParts::PreEarlyInitialization() {
}
void ShellBrowserMainParts::PreMainMessageLoopRun() {
+#if defined(OS_ANDROID)
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableCrashReporter)) {
+ base::FilePath crash_dumps_dir =
+ CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+ switches::kCrashDumpsDir);
+ crash_dump_manager_.reset(new breakpad::CrashDumpManager(crash_dumps_dir));
+ }
+#endif
net_log_.reset(new ShellNetLog());
browser_context_.reset(new ShellBrowserContext(false, net_log_.get()));
off_the_record_browser_context_.reset(
@@ -163,9 +180,6 @@ bool ShellBrowserMainParts::MainMessageLoopRun(int* result_code) {
}
void ShellBrowserMainParts::PostMainMessageLoopRun() {
-#if defined(USE_AURA)
- Shell::PlatformExit();
-#endif
if (devtools_delegate_)
devtools_delegate_->Stop();
browser_context_.reset();
diff --git a/chromium/content/shell/browser/shell_browser_main_parts.h b/chromium/content/shell/browser/shell_browser_main_parts.h
index 990e1c59a9d..aa11dda0497 100644
--- a/chromium/content/shell/browser/shell_browser_main_parts.h
+++ b/chromium/content/shell/browser/shell_browser_main_parts.h
@@ -10,6 +10,12 @@
#include "content/public/browser/browser_main_parts.h"
#include "content/public/common/main_function_params.h"
+#if defined(OS_ANDROID)
+namespace breakpad {
+class CrashDumpManager;
+}
+#endif
+
namespace base {
class Thread;
}
@@ -49,6 +55,9 @@ class ShellBrowserMainParts : public BrowserMainParts {
net::NetLog* net_log() { return net_log_.get(); }
private:
+#if defined(OS_ANDROID)
+ scoped_ptr<breakpad::CrashDumpManager> crash_dump_manager_;
+#endif
scoped_ptr<net::NetLog> net_log_;
scoped_ptr<ShellBrowserContext> browser_context_;
scoped_ptr<ShellBrowserContext> off_the_record_browser_context_;
diff --git a/chromium/content/shell/browser/shell_content_browser_client.cc b/chromium/content/shell/browser/shell_content_browser_client.cc
index 040fce8a367..2e6ff6b26ec 100644
--- a/chromium/content/shell/browser/shell_content_browser_client.cc
+++ b/chromium/content/shell/browser/shell_content_browser_client.cc
@@ -4,11 +4,10 @@
#include "content/shell/browser/shell_content_browser_client.h"
+#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/path_service.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/storage_partition.h"
@@ -35,10 +34,18 @@
#if defined(OS_ANDROID)
#include "base/android/path_utils.h"
#include "base/path_service.h"
-#include "base/platform_file.h"
+#include "components/breakpad/browser/crash_dump_manager_android.h"
#include "content/shell/android/shell_descriptors.h"
#endif
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
+#include "base/debug/leak_annotations.h"
+#include "base/platform_file.h"
+#include "components/breakpad/app/breakpad_linux.h"
+#include "components/breakpad/browser/crash_handler_host_linux.h"
+#include "content/public/common/content_descriptors.h"
+#endif
+
namespace content {
namespace {
@@ -46,6 +53,61 @@ namespace {
ShellContentBrowserClient* g_browser_client;
bool g_swap_processes_for_redirect = false;
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
+ const std::string& process_type) {
+ base::FilePath dumps_path =
+ CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+ switches::kCrashDumpsDir);
+ {
+ ANNOTATE_SCOPED_MEMORY_LEAK;
+ breakpad::CrashHandlerHostLinux* crash_handler =
+ new breakpad::CrashHandlerHostLinux(
+ process_type, dumps_path, false);
+ crash_handler->StartUploaderThread();
+ return crash_handler;
+ }
+}
+
+int GetCrashSignalFD(const CommandLine& command_line) {
+ if (!breakpad::IsCrashReporterEnabled())
+ return -1;
+
+ std::string process_type =
+ command_line.GetSwitchValueASCII(switches::kProcessType);
+
+ if (process_type == switches::kRendererProcess) {
+ static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
+ if (!crash_handler)
+ crash_handler = CreateCrashHandlerHost(process_type);
+ return crash_handler->GetDeathSignalSocket();
+ }
+
+ if (process_type == switches::kPluginProcess) {
+ static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
+ if (!crash_handler)
+ crash_handler = CreateCrashHandlerHost(process_type);
+ return crash_handler->GetDeathSignalSocket();
+ }
+
+ if (process_type == switches::kPpapiPluginProcess) {
+ static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
+ if (!crash_handler)
+ crash_handler = CreateCrashHandlerHost(process_type);
+ return crash_handler->GetDeathSignalSocket();
+ }
+
+ if (process_type == switches::kGpuProcess) {
+ static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
+ if (!crash_handler)
+ crash_handler = CreateCrashHandlerHost(process_type);
+ return crash_handler->GetDeathSignalSocket();
+ }
+
+ return -1;
+}
+#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+
} // namespace
ShellContentBrowserClient* ShellContentBrowserClient::Get() {
@@ -79,7 +141,7 @@ void ShellContentBrowserClient::RenderProcessHostCreated(
RenderProcessHost* host) {
if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
return;
- host->GetChannel()->AddFilter(new ShellMessageFilter(
+ host->AddFilter(new ShellMessageFilter(
host->GetID(),
BrowserContext::GetDefaultStoragePartition(browser_context())
->GetDatabaseTracker(),
@@ -88,12 +150,6 @@ void ShellContentBrowserClient::RenderProcessHostCreated(
BrowserContext::GetDefaultStoragePartition(browser_context())
->GetURLRequestContext()));
host->Send(new ShellViewMsg_SetWebKitSourceDir(webkit_source_dir_));
- registrar_.Add(this,
- NOTIFICATION_RENDERER_PROCESS_CREATED,
- Source<RenderProcessHost>(host));
- registrar_.Add(this,
- NOTIFICATION_RENDERER_PROCESS_TERMINATED,
- Source<RenderProcessHost>(host));
}
net::URLRequestContextGetter* ShellContentBrowserClient::CreateRequestContext(
@@ -146,6 +202,16 @@ void ShellContentBrowserClient::AppendExtraCommandLineSwitches(
command_line->AppendSwitch(switches::kExposeInternalsForTesting);
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kStableReleaseMode))
command_line->AppendSwitch(switches::kStableReleaseMode);
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableCrashReporter)) {
+ command_line->AppendSwitch(switches::kEnableCrashReporter);
+ }
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kCrashDumpsDir)) {
+ command_line->AppendSwitchPath(
+ switches::kCrashDumpsDir,
+ CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+ switches::kCrashDumpsDir));
+ }
}
void ShellContentBrowserClient::OverrideWebkitPrefs(
@@ -204,11 +270,12 @@ bool ShellContentBrowserClient::ShouldSwapProcessesForRedirect(
return g_swap_processes_for_redirect;
}
-#if defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
void ShellContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
const CommandLine& command_line,
int child_process_id,
std::vector<content::FileDescriptorInfo>* mappings) {
+#if defined(OS_ANDROID)
int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
base::FilePath pak_file;
bool r = PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_file);
@@ -225,37 +292,27 @@ void ShellContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
mappings->push_back(
content::FileDescriptorInfo(kShellPakDescriptor,
base::FileDescriptor(f, true)));
-}
-#endif
-void ShellContentBrowserClient::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- switch (type) {
- case NOTIFICATION_RENDERER_PROCESS_CREATED: {
- registrar_.Remove(this,
- NOTIFICATION_RENDERER_PROCESS_CREATED,
- source);
- registrar_.Remove(this,
- NOTIFICATION_RENDERER_PROCESS_TERMINATED,
- source);
- break;
+ if (breakpad::IsCrashReporterEnabled()) {
+ f = breakpad::CrashDumpManager::GetInstance()->CreateMinidumpFile(
+ child_process_id);
+ if (f == base::kInvalidPlatformFileValue) {
+ LOG(ERROR) << "Failed to create file for minidump, crash reporting will "
+ << "be disabled for this process.";
+ } else {
+ mappings->push_back(FileDescriptorInfo(kAndroidMinidumpDescriptor,
+ base::FileDescriptor(f, true)));
}
-
- case NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
- registrar_.Remove(this,
- NOTIFICATION_RENDERER_PROCESS_CREATED,
- source);
- registrar_.Remove(this,
- NOTIFICATION_RENDERER_PROCESS_TERMINATED,
- source);
- break;
- }
-
- default:
- NOTREACHED();
}
+#else // !defined(OS_ANDROID)
+ int crash_signal_fd = GetCrashSignalFD(command_line);
+ if (crash_signal_fd >= 0) {
+ mappings->push_back(FileDescriptorInfo(
+ kCrashDumpSignal, base::FileDescriptor(crash_signal_fd, false)));
+ }
+#endif // defined(OS_ANDROID)
}
+#endif // defined(OS_POSIX) && !defined(OS_MACOSX)
ShellBrowserContext* ShellContentBrowserClient::browser_context() {
return shell_browser_main_parts_->browser_context();
diff --git a/chromium/content/shell/browser/shell_content_browser_client.h b/chromium/content/shell/browser/shell_content_browser_client.h
index b96b4819f60..008f4cdb5b9 100644
--- a/chromium/content/shell/browser/shell_content_browser_client.h
+++ b/chromium/content/shell/browser/shell_content_browser_client.h
@@ -12,8 +12,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/platform_file.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
#include "content/shell/browser/shell_speech_recognition_manager_delegate.h"
namespace content {
@@ -22,8 +20,7 @@ class ShellBrowserContext;
class ShellBrowserMainParts;
class ShellResourceDispatcherHostDelegate;
-class ShellContentBrowserClient : public ContentBrowserClient,
- public NotificationObserver {
+class ShellContentBrowserClient : public ContentBrowserClient {
public:
// Gets the current instance.
static ShellContentBrowserClient* Get();
@@ -66,18 +63,13 @@ class ShellContentBrowserClient : public ContentBrowserClient,
const GURL& current_url,
const GURL& new_url) OVERRIDE;
-#if defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
virtual void GetAdditionalMappedFilesForChildProcess(
const CommandLine& command_line,
int child_process_id,
std::vector<content::FileDescriptorInfo>* mappings) OVERRIDE;
#endif
- // NotificationObserver implementation.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
-
ShellBrowserContext* browser_context();
ShellBrowserContext* off_the_record_browser_context();
ShellResourceDispatcherHostDelegate* resource_dispatcher_host_delegate() {
@@ -97,8 +89,6 @@ class ShellContentBrowserClient : public ContentBrowserClient,
base::FilePath webkit_source_dir_;
ShellBrowserMainParts* shell_browser_main_parts_;
-
- NotificationRegistrar registrar_;
};
} // namespace content
diff --git a/chromium/content/shell/browser/shell_devtools_delegate.cc b/chromium/content/shell/browser/shell_devtools_delegate.cc
index c8d256f6125..c7aecb2f450 100644
--- a/chromium/content/shell/browser/shell_devtools_delegate.cc
+++ b/chromium/content/shell/browser/shell_devtools_delegate.cc
@@ -9,7 +9,14 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_http_handler.h"
+#include "content/public/browser/devtools_target.h"
+#include "content/public/browser/favicon_status.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
@@ -17,14 +24,25 @@
#include "grit/shell_resources.h"
#include "net/socket/tcp_listen_socket.h"
#include "ui/base/resource/resource_bundle.h"
+#include "webkit/common/user_agent/user_agent_util.h"
#if defined(OS_ANDROID)
#include "content/public/browser/android/devtools_auth.h"
#include "net/socket/unix_domain_socket_posix.h"
#endif
+using content::DevToolsAgentHost;
+using content::RenderViewHost;
+using content::WebContents;
+
namespace {
+#if defined(OS_ANDROID)
+const char kFrontEndURL[] =
+ "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/devtools.html";
+#endif
+const char kTargetTypePage[] = "page";
+
net::StreamListenSocketFactory* CreateSocketFactory() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
#if defined(OS_ANDROID)
@@ -53,16 +71,83 @@ net::StreamListenSocketFactory* CreateSocketFactory() {
return new net::TCPListenSocketFactory("127.0.0.1", port);
#endif
}
+
+class Target : public content::DevToolsTarget {
+ public:
+ explicit Target(WebContents* web_contents);
+
+ virtual std::string GetId() const OVERRIDE { return id_; }
+ virtual std::string GetType() const OVERRIDE { return kTargetTypePage; }
+ virtual std::string GetTitle() const OVERRIDE { return title_; }
+ virtual std::string GetDescription() const OVERRIDE { return std::string(); }
+ virtual GURL GetUrl() const OVERRIDE { return url_; }
+ virtual GURL GetFaviconUrl() const OVERRIDE { return favicon_url_; }
+ virtual base::TimeTicks GetLastActivityTime() const OVERRIDE {
+ return last_activity_time_;
+ }
+ virtual bool IsAttached() const OVERRIDE {
+ return agent_host_->IsAttached();
+ }
+ virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE {
+ return agent_host_;
+ }
+ virtual bool Activate() const OVERRIDE;
+ virtual bool Close() const OVERRIDE;
+
+ private:
+ scoped_refptr<DevToolsAgentHost> agent_host_;
+ std::string id_;
+ std::string title_;
+ GURL url_;
+ GURL favicon_url_;
+ base::TimeTicks last_activity_time_;
+};
+
+Target::Target(WebContents* web_contents) {
+ agent_host_ =
+ DevToolsAgentHost::GetOrCreateFor(web_contents->GetRenderViewHost());
+ id_ = agent_host_->GetId();
+ title_ = UTF16ToUTF8(web_contents->GetTitle());
+ url_ = web_contents->GetURL();
+ content::NavigationController& controller = web_contents->GetController();
+ content::NavigationEntry* entry = controller.GetActiveEntry();
+ if (entry != NULL && entry->GetURL().is_valid())
+ favicon_url_ = entry->GetFavicon().url;
+ last_activity_time_ = web_contents->GetLastSelectedTime();
+}
+
+bool Target::Activate() const {
+ RenderViewHost* rvh = agent_host_->GetRenderViewHost();
+ if (!rvh)
+ return false;
+ WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
+ if (!web_contents)
+ return false;
+ web_contents->GetDelegate()->ActivateContents(web_contents);
+ return true;
+}
+
+bool Target::Close() const {
+ RenderViewHost* rvh = agent_host_->GetRenderViewHost();
+ if (!rvh)
+ return false;
+ rvh->ClosePage();
+ return true;
+}
+
} // namespace
namespace content {
ShellDevToolsDelegate::ShellDevToolsDelegate(BrowserContext* browser_context)
: browser_context_(browser_context) {
- // Note that Content Shell always used bundled DevTools frontend,
- // even on Android, because the shell is used for running layout tests.
+ std::string frontend_url;
+#if defined(OS_ANDROID)
+ frontend_url = base::StringPrintf(kFrontEndURL,
+ webkit_glue::GetWebKitRevision().c_str());
+#endif
devtools_http_handler_ =
- DevToolsHttpHandler::Start(CreateSocketFactory(), std::string(), this);
+ DevToolsHttpHandler::Start(CreateSocketFactory(), frontend_url, this);
}
ShellDevToolsDelegate::~ShellDevToolsDelegate() {
@@ -74,12 +159,20 @@ void ShellDevToolsDelegate::Stop() {
}
std::string ShellDevToolsDelegate::GetDiscoveryPageHTML() {
+#if defined(OS_ANDROID)
+ return std::string();
+#else
return ResourceBundle::GetSharedInstance().GetRawDataResource(
IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE).as_string();
+#endif
}
bool ShellDevToolsDelegate::BundlesFrontendResources() {
+#if defined(OS_ANDROID)
+ return false;
+#else
return true;
+#endif
}
base::FilePath ShellDevToolsDelegate::GetDebugFrontendDir() {
@@ -90,23 +183,27 @@ std::string ShellDevToolsDelegate::GetPageThumbnailData(const GURL& url) {
return std::string();
}
-RenderViewHost* ShellDevToolsDelegate::CreateNewTarget() {
+scoped_ptr<DevToolsTarget>
+ShellDevToolsDelegate::CreateNewTarget(const GURL& url) {
Shell* shell = Shell::CreateNewWindow(browser_context_,
- GURL(kAboutBlankURL),
+ url,
NULL,
MSG_ROUTING_NONE,
gfx::Size());
- return shell->web_contents()->GetRenderViewHost();
+ return scoped_ptr<DevToolsTarget>(new Target(shell->web_contents()));
}
-DevToolsHttpHandlerDelegate::TargetType
-ShellDevToolsDelegate::GetTargetType(RenderViewHost*) {
- return kTargetTypeTab;
-}
-
-std::string ShellDevToolsDelegate::GetViewDescription(
- content::RenderViewHost*) {
- return std::string();
+void ShellDevToolsDelegate::EnumerateTargets(TargetCallback callback) {
+ TargetList targets;
+ std::vector<RenderViewHost*> rvh_list =
+ content::DevToolsAgentHost::GetValidRenderViewHosts();
+ for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin();
+ it != rvh_list.end(); ++it) {
+ WebContents* web_contents = WebContents::FromRenderViewHost(*it);
+ if (web_contents)
+ targets.push_back(new Target(web_contents));
+ }
+ callback.Run(targets);
}
scoped_ptr<net::StreamListenSocket>
diff --git a/chromium/content/shell/browser/shell_devtools_delegate.h b/chromium/content/shell/browser/shell_devtools_delegate.h
index ad694c515e0..f200ed1f40b 100644
--- a/chromium/content/shell/browser/shell_devtools_delegate.h
+++ b/chromium/content/shell/browser/shell_devtools_delegate.h
@@ -27,9 +27,8 @@ class ShellDevToolsDelegate : public DevToolsHttpHandlerDelegate {
virtual bool BundlesFrontendResources() OVERRIDE;
virtual base::FilePath GetDebugFrontendDir() OVERRIDE;
virtual std::string GetPageThumbnailData(const GURL& url) OVERRIDE;
- virtual RenderViewHost* CreateNewTarget() OVERRIDE;
- virtual TargetType GetTargetType(RenderViewHost*) OVERRIDE;
- virtual std::string GetViewDescription(content::RenderViewHost*) OVERRIDE;
+ virtual scoped_ptr<DevToolsTarget> CreateNewTarget(const GURL& url) OVERRIDE;
+ virtual void EnumerateTargets(TargetCallback callback) OVERRIDE;
virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(
net::StreamListenSocket::Delegate* delegate,
std::string* name) OVERRIDE;
diff --git a/chromium/content/shell/browser/shell_devtools_frontend.cc b/chromium/content/shell/browser/shell_devtools_frontend.cc
index 8c3f74b8bb1..bfa93d4644f 100644
--- a/chromium/content/shell/browser/shell_devtools_frontend.cc
+++ b/chromium/content/shell/browser/shell_devtools_frontend.cc
@@ -6,8 +6,10 @@
#include "base/command_line.h"
#include "base/path_service.h"
+#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_manager.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/content_client.h"
@@ -21,8 +23,6 @@
namespace content {
-namespace {
-
// DevTools frontend path for inspector LayoutTests.
GURL GetDevToolsPathAsURL() {
base::FilePath dir_exe;
@@ -41,8 +41,6 @@ GURL GetDevToolsPathAsURL() {
return net::FilePathToFileURL(dev_tools_path);
}
-} // namespace
-
// static
ShellDevToolsFrontend* ShellDevToolsFrontend::Show(
WebContents* inspected_contents) {
@@ -61,11 +59,18 @@ ShellDevToolsFrontend* ShellDevToolsFrontend::Show(
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
shell->LoadURL(GetDevToolsPathAsURL());
else
- shell->LoadURL(delegate->devtools_http_handler()->GetFrontendURL(NULL));
+ shell->LoadURL(delegate->devtools_http_handler()->GetFrontendURL());
+
+ devtools_frontend->Activate();
+ devtools_frontend->Focus();
return devtools_frontend;
}
+void ShellDevToolsFrontend::Activate() {
+ frontend_shell_->ActivateContents(web_contents());
+}
+
void ShellDevToolsFrontend::Focus() {
web_contents()->GetView()->Focus();
}
@@ -95,6 +100,12 @@ void ShellDevToolsFrontend::RenderViewCreated(
frontend_host_.get());
}
+void ShellDevToolsFrontend::DocumentOnLoadCompletedInMainFrame(int32 page_id) {
+ web_contents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
+ base::string16(),
+ ASCIIToUTF16("InspectorFrontendAPI.setUseSoftMenu(true);"));
+}
+
void ShellDevToolsFrontend::WebContentsDestroyed(WebContents* web_contents) {
DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_.get());
delete this;
diff --git a/chromium/content/shell/browser/shell_devtools_frontend.h b/chromium/content/shell/browser/shell_devtools_frontend.h
index 4d3066634f2..5522cd75d5d 100644
--- a/chromium/content/shell/browser/shell_devtools_frontend.h
+++ b/chromium/content/shell/browser/shell_devtools_frontend.h
@@ -16,6 +16,8 @@
namespace content {
+GURL GetDevToolsPathAsURL();
+
class RenderViewHost;
class Shell;
class WebContents;
@@ -24,6 +26,7 @@ class ShellDevToolsFrontend : public WebContentsObserver,
public DevToolsFrontendHostDelegate {
public:
static ShellDevToolsFrontend* Show(WebContents* inspected_contents);
+ void Activate();
void Focus();
void Close();
@@ -35,6 +38,7 @@ class ShellDevToolsFrontend : public WebContentsObserver,
// WebContentsObserver overrides
virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE;
+ virtual void DocumentOnLoadCompletedInMainFrame(int32 page_id) OVERRIDE;
virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
// DevToolsFrontendHostDelegate implementation
diff --git a/chromium/content/shell/browser/shell_download_manager_delegate.cc b/chromium/content/shell/browser/shell_download_manager_delegate.cc
index 1dbbea7626b..e930b93f940 100644
--- a/chromium/content/shell/browser/shell_download_manager_delegate.cc
+++ b/chromium/content/shell/browser/shell_download_manager_delegate.cc
@@ -72,7 +72,7 @@ bool ShellDownloadManagerDelegate::DetermineDownloadTarget(
base::FilePath generated_name = net::GenerateFileName(
download->GetURL(),
download->GetContentDisposition(),
- EmptyString(),
+ std::string(),
download->GetSuggestedFilename(),
download->GetMimeType(),
"download");
@@ -112,7 +112,7 @@ void ShellDownloadManagerDelegate::GenerateFilename(
const base::FilePath& suggested_directory) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (!base::PathExists(suggested_directory))
- file_util::CreateDirectory(suggested_directory);
+ base::CreateDirectory(suggested_directory);
base::FilePath suggested_path(suggested_directory.Append(generated_name));
BrowserThread::PostTask(
diff --git a/chromium/content/shell/browser/shell_gtk.cc b/chromium/content/shell/browser/shell_gtk.cc
index a06a6a036f8..3d2580a1a5e 100644
--- a/chromium/content/shell/browser/shell_gtk.cc
+++ b/chromium/content/shell/browser/shell_gtk.cc
@@ -12,6 +12,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/native_web_keyboard_event.h"
+#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/renderer_preferences.h"
@@ -57,6 +58,9 @@ GtkWidget* CreateMenuBar(Shell* shell) {
void Shell::PlatformInitialize(const gfx::Size& default_window_size) {
}
+void Shell::PlatformExit() {
+}
+
void Shell::PlatformCleanUp() {
// Nothing to clean up; GTK will clean up the widgets shortly after.
}
@@ -103,7 +107,7 @@ void Shell::PlatformSetIsLoading(bool loading) {
void Shell::PlatformCreateWindow(int width, int height) {
ui_elements_height_ = 0;
if (headless_) {
- SizeTo(width, height);
+ content_size_ = gfx::Size(width, height);
return;
}
@@ -218,37 +222,39 @@ void Shell::PlatformCreateWindow(int width, int height) {
ui_elements_height_ += elm_size.height;
// We're ready to set an initial window size.
- SizeTo(width, height);
+ SizeTo(gfx::Size(width, height));
// Finally, show the window.
gtk_widget_show_all(GTK_WIDGET(window_));
}
void Shell::PlatformSetContents() {
- if (headless_)
+ if (headless_) {
+ SizeTo(content_size_);
return;
+ }
WebContentsView* content_view = web_contents_->GetView();
gtk_container_add(GTK_CONTAINER(vbox_), content_view->GetNativeView());
}
-void Shell::SizeTo(int width, int height) {
- content_width_ = width;
- content_height_ = height;
+void Shell::SizeTo(const gfx::Size& content_size) {
+ content_size_ = content_size;
- // Prefer setting the top level window's size (if we have one), rather than
- // setting the inner widget's minimum size (so that the user can shrink the
- // window if she wants).
if (window_) {
- gtk_window_resize(window_, width, height + ui_elements_height_);
+ gtk_window_resize(window_,
+ content_size.width(),
+ content_size.height() + ui_elements_height_);
} else if (web_contents_) {
- gtk_widget_set_size_request(web_contents_->GetView()->GetNativeView(),
- width, height);
+ RenderWidgetHostView* render_widget_host_view =
+ web_contents_->GetRenderWidgetHostView();
+ if (render_widget_host_view)
+ render_widget_host_view->SetSize(content_size);
}
}
void Shell::PlatformResizeSubViews() {
- SizeTo(content_width_, content_height_);
+ // Not needed; the subviews are bound.
}
void Shell::Close() {
@@ -281,7 +287,8 @@ void Shell::OnURLEntryActivate(GtkWidget* entry) {
GURL url(str);
if (!url.has_scheme())
url = GURL(std::string("http://") + std::string(str));
- LoadURL(GURL(url));
+ if (url.is_valid())
+ LoadURL(url);
}
// Callback for when the main window is destroyed.
@@ -328,7 +335,7 @@ gboolean Shell::OnReloadKeyPressed(GtkAccelGroup* accel_group,
return TRUE;
}
-void Shell::PlatformSetTitle(const string16& title) {
+void Shell::PlatformSetTitle(const base::string16& title) {
if (headless_)
return;
diff --git a/chromium/content/shell/browser/shell_javascript_dialog.h b/chromium/content/shell/browser/shell_javascript_dialog.h
index 4001334c788..233296bdad2 100644
--- a/chromium/content/shell/browser/shell_javascript_dialog.h
+++ b/chromium/content/shell/browser/shell_javascript_dialog.h
@@ -29,8 +29,8 @@ class ShellJavaScriptDialog {
ShellJavaScriptDialogManager* manager,
gfx::NativeWindow parent_window,
JavaScriptMessageType message_type,
- const string16& message_text,
- const string16& default_prompt_text,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
const JavaScriptDialogManager::DialogClosedCallback& callback);
~ShellJavaScriptDialog();
@@ -46,8 +46,8 @@ class ShellJavaScriptDialog {
#elif defined(OS_WIN)
JavaScriptMessageType message_type_;
HWND dialog_win_;
- string16 message_text_;
- string16 default_prompt_text_;
+ base::string16 message_text_;
+ base::string16 default_prompt_text_;
static INT_PTR CALLBACK DialogProc(HWND dialog, UINT message, WPARAM wparam,
LPARAM lparam);
#elif defined(TOOLKIT_GTK)
diff --git a/chromium/content/shell/browser/shell_javascript_dialog_gtk.cc b/chromium/content/shell/browser/shell_javascript_dialog_gtk.cc
index 87bd6f3124b..65bf7397c1e 100644
--- a/chromium/content/shell/browser/shell_javascript_dialog_gtk.cc
+++ b/chromium/content/shell/browser/shell_javascript_dialog_gtk.cc
@@ -19,12 +19,12 @@ const char kPromptTextId[] = "content_shell_prompt_text";
// If there's a text entry in the dialog, get the text from the first one and
// return it.
-string16 GetPromptText(GtkDialog* dialog) {
+base::string16 GetPromptText(GtkDialog* dialog) {
GtkWidget* widget = static_cast<GtkWidget*>(
g_object_get_data(G_OBJECT(dialog), kPromptTextId));
if (widget)
return UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(widget)));
- return string16();
+ return base::string16();
}
} // namespace
@@ -36,8 +36,8 @@ ShellJavaScriptDialog::ShellJavaScriptDialog(
ShellJavaScriptDialogManager* manager,
gfx::NativeWindow parent_window,
JavaScriptMessageType message_type,
- const string16& message_text,
- const string16& default_prompt_text,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
const JavaScriptDialogManager::DialogClosedCallback& callback)
: manager_(manager),
callback_(callback),
@@ -113,7 +113,7 @@ void ShellJavaScriptDialog::OnResponse(GtkWidget* dialog, int response_id) {
break;
case GTK_RESPONSE_CANCEL:
case GTK_RESPONSE_DELETE_EVENT:
- callback_.Run(false, string16());
+ callback_.Run(false, base::string16());
break;
default:
NOTREACHED();
diff --git a/chromium/content/shell/browser/shell_javascript_dialog_mac.mm b/chromium/content/shell/browser/shell_javascript_dialog_mac.mm
index fe9de98d355..e7480003836 100644
--- a/chromium/content/shell/browser/shell_javascript_dialog_mac.mm
+++ b/chromium/content/shell/browser/shell_javascript_dialog_mac.mm
@@ -66,7 +66,7 @@
return;
bool success = returnCode == NSAlertFirstButtonReturn;
- string16 input;
+ base::string16 input;
if (textField_)
input = base::SysNSStringToUTF16([textField_ stringValue]);
@@ -89,8 +89,8 @@ ShellJavaScriptDialog::ShellJavaScriptDialog(
ShellJavaScriptDialogManager* manager,
gfx::NativeWindow parent_window,
JavaScriptMessageType message_type,
- const string16& message_text,
- const string16& default_prompt_text,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
const JavaScriptDialogManager::DialogClosedCallback& callback)
: manager_(manager),
callback_(callback) {
diff --git a/chromium/content/shell/browser/shell_javascript_dialog_manager.cc b/chromium/content/shell/browser/shell_javascript_dialog_manager.cc
index 1476f7c2475..6ac7243bfb5 100644
--- a/chromium/content/shell/browser/shell_javascript_dialog_manager.cc
+++ b/chromium/content/shell/browser/shell_javascript_dialog_manager.cc
@@ -27,18 +27,18 @@ void ShellJavaScriptDialogManager::RunJavaScriptDialog(
const GURL& origin_url,
const std::string& accept_lang,
JavaScriptMessageType javascript_message_type,
- const string16& message_text,
- const string16& default_prompt_text,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
const DialogClosedCallback& callback,
bool* did_suppress_message) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) {
- callback.Run(true, string16());
+ callback.Run(true, base::string16());
return;
}
if (!dialog_request_callback_.is_null()) {
dialog_request_callback_.Run();
- callback.Run(true, string16());
+ callback.Run(true, base::string16());
dialog_request_callback_.Reset();
return;
}
@@ -52,7 +52,7 @@ void ShellJavaScriptDialogManager::RunJavaScriptDialog(
return;
}
- string16 new_message_text = net::FormatUrl(origin_url, accept_lang) +
+ base::string16 new_message_text = net::FormatUrl(origin_url, accept_lang) +
ASCIIToUTF16("\n\n") +
message_text;
gfx::NativeWindow parent_window =
@@ -73,17 +73,17 @@ void ShellJavaScriptDialogManager::RunJavaScriptDialog(
void ShellJavaScriptDialogManager::RunBeforeUnloadDialog(
WebContents* web_contents,
- const string16& message_text,
+ const base::string16& message_text,
bool is_reload,
const DialogClosedCallback& callback) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) {
- callback.Run(true, string16());
+ callback.Run(true, base::string16());
return;
}
if (!dialog_request_callback_.is_null()) {
dialog_request_callback_.Run();
- callback.Run(true, string16());
+ callback.Run(true, base::string16());
dialog_request_callback_.Reset();
return;
}
@@ -91,11 +91,11 @@ void ShellJavaScriptDialogManager::RunBeforeUnloadDialog(
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
if (dialog_) {
// Seriously!?
- callback.Run(true, string16());
+ callback.Run(true, base::string16());
return;
}
- string16 new_message_text =
+ base::string16 new_message_text =
message_text +
ASCIIToUTF16("\n\nIs it OK to leave/reload this page?");
@@ -106,11 +106,11 @@ void ShellJavaScriptDialogManager::RunBeforeUnloadDialog(
parent_window,
JAVASCRIPT_MESSAGE_TYPE_CONFIRM,
new_message_text,
- string16(), // default_prompt_text
+ base::string16(), // default
callback));
#else
// TODO: implement ShellJavaScriptDialog for other platforms, drop this #if
- callback.Run(true, string16());
+ callback.Run(true, base::string16());
return;
#endif
}
diff --git a/chromium/content/shell/browser/shell_javascript_dialog_manager.h b/chromium/content/shell/browser/shell_javascript_dialog_manager.h
index 763736f58a7..5bcfb658499 100644
--- a/chromium/content/shell/browser/shell_javascript_dialog_manager.h
+++ b/chromium/content/shell/browser/shell_javascript_dialog_manager.h
@@ -25,14 +25,14 @@ class ShellJavaScriptDialogManager : public JavaScriptDialogManager {
const GURL& origin_url,
const std::string& accept_lang,
JavaScriptMessageType javascript_message_type,
- const string16& message_text,
- const string16& default_prompt_text,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
const DialogClosedCallback& callback,
bool* did_suppress_message) OVERRIDE;
virtual void RunBeforeUnloadDialog(
WebContents* web_contents,
- const string16& message_text,
+ const base::string16& message_text,
bool is_reload,
const DialogClosedCallback& callback) OVERRIDE;
diff --git a/chromium/content/shell/browser/shell_javascript_dialog_win.cc b/chromium/content/shell/browser/shell_javascript_dialog_win.cc
index a59639e9d4e..35371223016 100644
--- a/chromium/content/shell/browser/shell_javascript_dialog_win.cc
+++ b/chromium/content/shell/browser/shell_javascript_dialog_win.cc
@@ -34,7 +34,7 @@ INT_PTR CALLBACK ShellJavaScriptDialog::DialogProc(HWND dialog,
GetWindowLongPtr(dialog, DWLP_USER));
if (owner->dialog_win_) {
owner->dialog_win_ = 0;
- owner->callback_.Run(false, string16());
+ owner->callback_.Run(false, base::string16());
owner->manager_->DialogClosed(owner);
}
break;
@@ -42,7 +42,7 @@ INT_PTR CALLBACK ShellJavaScriptDialog::DialogProc(HWND dialog,
case WM_COMMAND: {
ShellJavaScriptDialog* owner = reinterpret_cast<ShellJavaScriptDialog*>(
GetWindowLongPtr(dialog, DWLP_USER));
- string16 user_input;
+ base::string16 user_input;
bool finish = false;
bool result;
switch (LOWORD(wparam)) {
@@ -79,8 +79,8 @@ ShellJavaScriptDialog::ShellJavaScriptDialog(
ShellJavaScriptDialogManager* manager,
gfx::NativeWindow parent_window,
JavaScriptMessageType message_type,
- const string16& message_text,
- const string16& default_prompt_text,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
const JavaScriptDialogManager::DialogClosedCallback& callback)
: manager_(manager),
callback_(callback),
diff --git a/chromium/content/shell/browser/shell_login_dialog.cc b/chromium/content/shell/browser/shell_login_dialog.cc
index 607fd66ac5a..b01fe987dd6 100644
--- a/chromium/content/shell/browser/shell_login_dialog.cc
+++ b/chromium/content/shell/browser/shell_login_dialog.cc
@@ -34,8 +34,8 @@ void ShellLoginDialog::OnRequestCancelled() {
base::Bind(&ShellLoginDialog::PlatformRequestCancelled, this));
}
-void ShellLoginDialog::UserAcceptedAuth(const string16& username,
- const string16& password) {
+void ShellLoginDialog::UserAcceptedAuth(const base::string16& username,
+ const base::string16& password) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
@@ -48,7 +48,7 @@ void ShellLoginDialog::UserCancelledAuth() {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&ShellLoginDialog::SendAuthToRequester, this,
- false, string16(), string16()));
+ false, base::string16(), base::string16()));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&ShellLoginDialog::PlatformCleanUp, this));
@@ -63,20 +63,20 @@ ShellLoginDialog::~ShellLoginDialog() {
// Bogus implementations for linking. They are never called because
// ResourceDispatcherHostDelegate::CreateLoginDelegate returns NULL.
// TODO: implement ShellLoginDialog for other platforms, drop this #if
-void ShellLoginDialog::PlatformCreateDialog(const string16& message) {}
+void ShellLoginDialog::PlatformCreateDialog(const base::string16& message) {}
void ShellLoginDialog::PlatformCleanUp() {}
void ShellLoginDialog::PlatformRequestCancelled() {}
#endif
-void ShellLoginDialog::PrepDialog(const string16& host,
- const string16& realm) {
+void ShellLoginDialog::PrepDialog(const base::string16& host,
+ const base::string16& realm) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// The realm is controlled by the remote server, so there is no reason to
// believe it is of a reasonable length.
- string16 elided_realm;
+ base::string16 elided_realm;
gfx::ElideString(realm, 120, &elided_realm);
- string16 explanation =
+ base::string16 explanation =
ASCIIToUTF16("The server ") + host +
ASCIIToUTF16(" requires a username and password.");
@@ -90,8 +90,8 @@ void ShellLoginDialog::PrepDialog(const string16& host,
}
void ShellLoginDialog::SendAuthToRequester(bool success,
- const string16& username,
- const string16& password) {
+ const base::string16& username,
+ const base::string16& password) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (success)
request_->SetAuth(net::AuthCredentials(username, password));
diff --git a/chromium/content/shell/browser/shell_login_dialog.h b/chromium/content/shell/browser/shell_login_dialog.h
index d9b0504072d..db70cb6e3d1 100644
--- a/chromium/content/shell/browser/shell_login_dialog.h
+++ b/chromium/content/shell/browser/shell_login_dialog.h
@@ -43,7 +43,8 @@ class ShellLoginDialog : public ResourceDispatcherHostLoginDelegate {
// the aforementioned platform specific code may not have access to private
// members. Not to be called from client code.
// Threading: UI thread.
- void UserAcceptedAuth(const string16& username, const string16& password);
+ void UserAcceptedAuth(const base::string16& username,
+ const base::string16& password);
void UserCancelledAuth();
protected:
@@ -55,7 +56,7 @@ class ShellLoginDialog : public ResourceDispatcherHostLoginDelegate {
// platform specific LoginDialog implementation.
// Creates the dialog.
// Threading: UI thread.
- void PlatformCreateDialog(const string16& message);
+ void PlatformCreateDialog(const base::string16& message);
// Called from the destructor to let each platform do any necessary cleanup.
// Threading: UI thread.
void PlatformCleanUp();
@@ -65,13 +66,13 @@ class ShellLoginDialog : public ResourceDispatcherHostLoginDelegate {
// Sets up dialog creation.
// Threading: UI thread.
- void PrepDialog(const string16& host, const string16& realm);
+ void PrepDialog(const base::string16& host, const base::string16& realm);
// Sends the authentication to the requester.
// Threading: IO thread.
void SendAuthToRequester(bool success,
- const string16& username,
- const string16& password);
+ const base::string16& username,
+ const base::string16& password);
// Who/where/what asked for the authentication.
// Threading: IO thread.
diff --git a/chromium/content/shell/browser/shell_login_dialog_gtk.cc b/chromium/content/shell/browser/shell_login_dialog_gtk.cc
index b08b449ad91..97fafece78d 100644
--- a/chromium/content/shell/browser/shell_login_dialog_gtk.cc
+++ b/chromium/content/shell/browser/shell_login_dialog_gtk.cc
@@ -19,7 +19,7 @@
namespace content {
-void ShellLoginDialog::PlatformCreateDialog(const string16& message) {
+void ShellLoginDialog::PlatformCreateDialog(const base::string16& message) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
int render_process_id;
diff --git a/chromium/content/shell/browser/shell_login_dialog_mac.mm b/chromium/content/shell/browser/shell_login_dialog_mac.mm
index 447aa586e11..3e014e8791c 100644
--- a/chromium/content/shell/browser/shell_login_dialog_mac.mm
+++ b/chromium/content/shell/browser/shell_login_dialog_mac.mm
@@ -87,7 +87,7 @@ const int kPasswordFieldTag = 2;
namespace content {
-void ShellLoginDialog::PlatformCreateDialog(const string16& message) {
+void ShellLoginDialog::PlatformCreateDialog(const base::string16& message) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
helper_ = [[ShellLoginDialogHelper alloc] init];
diff --git a/chromium/content/shell/browser/shell_mac.mm b/chromium/content/shell/browser/shell_mac.mm
index ca6a0ff7f33..e31ba098753 100644
--- a/chromium/content/shell/browser/shell_mac.mm
+++ b/chromium/content/shell/browser/shell_mac.mm
@@ -127,6 +127,9 @@ namespace content {
void Shell::PlatformInitialize(const gfx::Size& default_window_size) {
}
+void Shell::PlatformExit() {
+}
+
void Shell::PlatformCleanUp() {
}
@@ -165,8 +168,7 @@ void Shell::PlatformSetIsLoading(bool loading) {
void Shell::PlatformCreateWindow(int width, int height) {
if (headless_) {
- content_width_ = width;
- content_height_ = height;
+ content_size_ = gfx::Size(width, height);
return;
}
@@ -245,7 +247,7 @@ void Shell::PlatformSetContents() {
[web_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
if (headless_) {
- SizeTo(content_width_, content_height_);
+ SizeTo(content_size_);
return;
}
@@ -258,13 +260,13 @@ void Shell::PlatformSetContents() {
[web_view setNeedsDisplay:YES];
}
-void Shell::SizeTo(int width, int height) {
+void Shell::SizeTo(const gfx::Size& content_size) {
if (!headless_) {
NOTREACHED();
return;
}
NSView* web_view = web_contents_->GetView()->GetNativeView();
- NSRect frame = NSMakeRect(0, 0, width, height);
+ NSRect frame = NSMakeRect(0, 0, content_size.width(), content_size.height());
[web_view setFrame:frame];
}
@@ -272,7 +274,7 @@ void Shell::PlatformResizeSubViews() {
// Not needed; subviews are bound.
}
-void Shell::PlatformSetTitle(const string16& title) {
+void Shell::PlatformSetTitle(const base::string16& title) {
if (headless_)
return;
diff --git a/chromium/content/shell/browser/shell_network_delegate.cc b/chromium/content/shell/browser/shell_network_delegate.cc
index 560426f8979..1e4dddcda47 100644
--- a/chromium/content/shell/browser/shell_network_delegate.cc
+++ b/chromium/content/shell/browser/shell_network_delegate.cc
@@ -69,7 +69,7 @@ void ShellNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {
}
void ShellNetworkDelegate::OnPACScriptError(int line_number,
- const string16& error) {
+ const base::string16& error) {
}
ShellNetworkDelegate::AuthRequiredResponse ShellNetworkDelegate::OnAuthRequired(
diff --git a/chromium/content/shell/browser/shell_network_delegate.h b/chromium/content/shell/browser/shell_network_delegate.h
index a3ce0a249fd..286cc0ae683 100644
--- a/chromium/content/shell/browser/shell_network_delegate.h
+++ b/chromium/content/shell/browser/shell_network_delegate.h
@@ -42,7 +42,7 @@ class ShellNetworkDelegate : public net::NetworkDelegate {
virtual void OnCompleted(net::URLRequest* request, bool started) OVERRIDE;
virtual void OnURLRequestDestroyed(net::URLRequest* request) OVERRIDE;
virtual void OnPACScriptError(int line_number,
- const string16& error) OVERRIDE;
+ const base::string16& error) OVERRIDE;
virtual AuthRequiredResponse OnAuthRequired(
net::URLRequest* request,
const net::AuthChallengeInfo& auth_info,
diff --git a/chromium/content/shell/browser/shell_plugin_service_filter.cc b/chromium/content/shell/browser/shell_plugin_service_filter.cc
index d41b9bd7de0..7cabea402c7 100644
--- a/chromium/content/shell/browser/shell_plugin_service_filter.cc
+++ b/chromium/content/shell/browser/shell_plugin_service_filter.cc
@@ -15,7 +15,7 @@ ShellPluginServiceFilter::~ShellPluginServiceFilter() {}
bool ShellPluginServiceFilter::IsPluginAvailable(
int render_process_id,
- int render_view_id,
+ int render_frame_id,
const void* context,
const GURL& url,
const GURL& policy_url,
diff --git a/chromium/content/shell/browser/shell_plugin_service_filter.h b/chromium/content/shell/browser/shell_plugin_service_filter.h
index 3e9cb5d9875..f48b99c319e 100644
--- a/chromium/content/shell/browser/shell_plugin_service_filter.h
+++ b/chromium/content/shell/browser/shell_plugin_service_filter.h
@@ -18,7 +18,7 @@ class ShellPluginServiceFilter : public PluginServiceFilter {
// PluginServiceFilter implementation.
virtual bool IsPluginAvailable(int render_process_id,
- int render_view_id,
+ int render_frame_id,
const void* context,
const GURL& url,
const GURL& policy_url,
diff --git a/chromium/content/shell/browser/shell_url_request_context_getter.cc b/chromium/content/shell/browser/shell_url_request_context_getter.cc
index dfdb85275d7..27f0c4e5279 100644
--- a/chromium/content/shell/browser/shell_url_request_context_getter.cc
+++ b/chromium/content/shell/browser/shell_url_request_context_getter.cc
@@ -106,7 +106,7 @@ net::URLRequestContext* ShellURLRequestContextGetter::GetURLRequestContext() {
new net::DefaultServerBoundCertStore(NULL),
base::WorkerPool::GetTaskRunner(true)));
storage_->set_http_user_agent_settings(
- new net::StaticHttpUserAgentSettings("en-us,en", EmptyString()));
+ new net::StaticHttpUserAgentSettings("en-us,en", std::string()));
scoped_ptr<net::HostResolver> host_resolver(
net::HostResolver::CreateDefaultResolver(
diff --git a/chromium/content/shell/browser/shell_views.cc b/chromium/content/shell/browser/shell_views.cc
new file mode 100644
index 00000000000..c27e7833d35
--- /dev/null
+++ b/chromium/content/shell/browser/shell_views.cc
@@ -0,0 +1,398 @@
+// 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/shell/browser/shell.h"
+
+#include "base/command_line.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
+#include "ui/aura/env.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/window.h"
+#include "ui/base/accessibility/accessibility_types.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/events/event.h"
+#include "ui/gfx/screen.h"
+#include "ui/views/background.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/controls/textfield/textfield_controller.h"
+#include "ui/views/controls/webview/webview.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/layout/grid_layout.h"
+#include "ui/views/test/desktop_test_views_delegate.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/desktop_aura/desktop_screen.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "ui/aura/test/test_screen.h"
+#include "ui/wm/test/wm_test_helper.h"
+#endif
+
+#if defined(OS_WIN)
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+namespace content {
+
+namespace {
+// ViewDelegate implementation for aura content shell
+class ShellViewsDelegateAura : public views::DesktopTestViewsDelegate {
+ public:
+ ShellViewsDelegateAura() : use_transparent_windows_(false) {
+ }
+
+ virtual ~ShellViewsDelegateAura() {
+ }
+
+ void SetUseTransparentWindows(bool transparent) {
+ use_transparent_windows_ = transparent;
+ }
+
+ // Overridden from views::TestViewsDelegate:
+ virtual bool UseTransparentWindows() const OVERRIDE {
+ return use_transparent_windows_;
+ }
+
+ private:
+ bool use_transparent_windows_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellViewsDelegateAura);
+};
+
+// Maintain the UI controls and web view for content shell
+class ShellWindowDelegateView : public views::WidgetDelegateView,
+ public views::TextfieldController,
+ public views::ButtonListener {
+ public:
+ enum UIControl {
+ BACK_BUTTON,
+ FORWARD_BUTTON,
+ STOP_BUTTON
+ };
+
+ ShellWindowDelegateView(Shell* shell)
+ : shell_(shell),
+ toolbar_view_(new View),
+ contents_view_(new View) {
+ }
+ virtual ~ShellWindowDelegateView() {}
+
+ // Update the state of UI controls
+ void SetAddressBarURL(const GURL& url) {
+ url_entry_->SetText(ASCIIToUTF16(url.spec()));
+ }
+ void SetWebContents(WebContents* web_contents, const gfx::Size& size) {
+ contents_view_->SetLayoutManager(new views::FillLayout());
+ web_view_ = new views::WebView(web_contents->GetBrowserContext());
+ web_view_->SetWebContents(web_contents);
+ web_view_->SetPreferredSize(size);
+ web_contents->GetView()->Focus();
+ contents_view_->AddChildView(web_view_);
+ Layout();
+
+ // Resize the widget, keeping the same origin.
+ gfx::Rect bounds = GetWidget()->GetWindowBoundsInScreen();
+ bounds.set_size(GetWidget()->GetRootView()->GetPreferredSize());
+ GetWidget()->SetBounds(bounds);
+
+ // Resizing a widget on chromeos doesn't automatically resize the root, need
+ // to explicitly do that.
+#if defined(OS_CHROMEOS)
+ GetWidget()->GetNativeWindow()->GetDispatcher()->SetHostSize(
+ bounds.size());
+#endif
+ }
+
+ void SetWindowTitle(const base::string16& title) { title_ = title; }
+ void EnableUIControl(UIControl control, bool is_enabled) {
+ if (control == BACK_BUTTON) {
+ back_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
+ : views::CustomButton::STATE_DISABLED);
+ } else if (control == FORWARD_BUTTON) {
+ forward_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
+ : views::CustomButton::STATE_DISABLED);
+ } else if (control == STOP_BUTTON) {
+ stop_button_->SetState(is_enabled ? views::CustomButton::STATE_NORMAL
+ : views::CustomButton::STATE_DISABLED);
+ }
+ }
+
+ private:
+ // Initialize the UI control contained in shell window
+ void InitShellWindow() {
+ set_background(views::Background::CreateStandardPanelBackground());
+
+ views::GridLayout* layout = new views::GridLayout(this);
+ SetLayoutManager(layout);
+
+ views::ColumnSet* column_set = layout->AddColumnSet(0);
+ column_set->AddPaddingColumn(0, 2);
+ column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
+ views::GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, 2);
+
+ layout->AddPaddingRow(0, 2);
+
+ // Add toolbar buttons and URL text field
+ {
+ layout->StartRow(0, 0);
+ views::GridLayout* toolbar_layout = new views::GridLayout(toolbar_view_);
+ toolbar_view_->SetLayoutManager(toolbar_layout);
+
+ views::ColumnSet* toolbar_column_set =
+ toolbar_layout->AddColumnSet(0);
+ // Back button
+ back_button_ = new views::LabelButton(this, ASCIIToUTF16("Back"));
+ back_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
+ gfx::Size back_button_size = back_button_->GetPreferredSize();
+ toolbar_column_set->AddColumn(views::GridLayout::CENTER,
+ views::GridLayout::CENTER, 0,
+ views::GridLayout::FIXED,
+ back_button_size.width(),
+ back_button_size.width() / 2);
+ // Forward button
+ forward_button_ = new views::LabelButton(this, ASCIIToUTF16("Forward"));
+ forward_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
+ gfx::Size forward_button_size = forward_button_->GetPreferredSize();
+ toolbar_column_set->AddColumn(views::GridLayout::CENTER,
+ views::GridLayout::CENTER, 0,
+ views::GridLayout::FIXED,
+ forward_button_size.width(),
+ forward_button_size.width() / 2);
+ // Refresh button
+ refresh_button_ = new views::LabelButton(this, ASCIIToUTF16("Refresh"));
+ refresh_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
+ gfx::Size refresh_button_size = refresh_button_->GetPreferredSize();
+ toolbar_column_set->AddColumn(views::GridLayout::CENTER,
+ views::GridLayout::CENTER, 0,
+ views::GridLayout::FIXED,
+ refresh_button_size.width(),
+ refresh_button_size.width() / 2);
+ // Stop button
+ stop_button_ = new views::LabelButton(this, ASCIIToUTF16("Stop"));
+ stop_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
+ gfx::Size stop_button_size = stop_button_->GetPreferredSize();
+ toolbar_column_set->AddColumn(views::GridLayout::CENTER,
+ views::GridLayout::CENTER, 0,
+ views::GridLayout::FIXED,
+ stop_button_size.width(),
+ stop_button_size.width() / 2);
+ toolbar_column_set->AddPaddingColumn(0, 2);
+ // URL entry
+ url_entry_ = new views::Textfield();
+ url_entry_->SetController(this);
+ toolbar_column_set->AddColumn(views::GridLayout::FILL,
+ views::GridLayout::FILL, 1,
+ views::GridLayout::USE_PREF, 0, 0);
+
+ // Fill up the first row
+ toolbar_layout->StartRow(0, 0);
+ toolbar_layout->AddView(back_button_);
+ toolbar_layout->AddView(forward_button_);
+ toolbar_layout->AddView(refresh_button_);
+ toolbar_layout->AddView(stop_button_);
+ toolbar_layout->AddView(url_entry_);
+
+ layout->AddView(toolbar_view_);
+ }
+
+ layout->AddPaddingRow(0, 5);
+
+ // Add web contents view as the second row
+ {
+ layout->StartRow(1, 0);
+ layout->AddView(contents_view_);
+ }
+
+ layout->AddPaddingRow(0, 5);
+ }
+ // Overridden from TextfieldController
+ virtual void ContentsChanged(views::Textfield* sender,
+ const base::string16& new_contents) OVERRIDE {
+ }
+ virtual bool HandleKeyEvent(views::Textfield* sender,
+ const ui::KeyEvent& key_event) OVERRIDE {
+ if (sender == url_entry_ && key_event.key_code() == ui::VKEY_RETURN) {
+ std::string text = UTF16ToUTF8(url_entry_->text());
+ GURL url(text);
+ if (!url.has_scheme()) {
+ url = GURL(std::string("http://") + std::string(text));
+ url_entry_->SetText(ASCIIToUTF16(url.spec()));
+ }
+ shell_->LoadURL(url);
+ return true;
+ }
+ return false;
+ }
+
+ // Overridden from ButtonListener
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE {
+ if (sender == back_button_)
+ shell_->GoBackOrForward(-1);
+ else if (sender == forward_button_)
+ shell_->GoBackOrForward(1);
+ else if (sender == refresh_button_)
+ shell_->Reload();
+ else if (sender == stop_button_)
+ shell_->Stop();
+ }
+
+ // Overridden from WidgetDelegateView
+ virtual bool CanResize() const OVERRIDE { return true; }
+ virtual bool CanMaximize() const OVERRIDE { return true; }
+ virtual base::string16 GetWindowTitle() const OVERRIDE {
+ return title_;
+ }
+ virtual void WindowClosing() OVERRIDE {
+ if (shell_) {
+ delete shell_;
+ shell_ = NULL;
+ }
+ }
+ virtual View* GetContentsView() OVERRIDE { return this; }
+
+ // Overridden from View
+ virtual void ViewHierarchyChanged(
+ const ViewHierarchyChangedDetails& details) OVERRIDE {
+ if (details.is_add && details.child == this) {
+ InitShellWindow();
+ }
+ }
+
+ private:
+ // Hold a reference of Shell for deleting it when the window is closing
+ Shell* shell_;
+
+ // Window title
+ base::string16 title_;
+
+ // Toolbar view contains forward/backward/reload button and URL entry
+ View* toolbar_view_;
+ views::LabelButton* back_button_;
+ views::LabelButton* forward_button_;
+ views::LabelButton* refresh_button_;
+ views::LabelButton* stop_button_;
+ views::Textfield* url_entry_;
+
+ // Contents view contains the web contents view
+ View* contents_view_;
+ views::WebView* web_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellWindowDelegateView);
+};
+
+} // namespace
+
+#if defined(OS_CHROMEOS)
+wm::WMTestHelper* Shell::wm_test_helper_ = NULL;
+#endif
+views::ViewsDelegate* Shell::views_delegate_ = NULL;
+
+// static
+void Shell::PlatformInitialize(const gfx::Size& default_window_size) {
+#if defined(OS_WIN)
+ _setmode(_fileno(stdout), _O_BINARY);
+ _setmode(_fileno(stderr), _O_BINARY);
+#endif
+#if defined(OS_CHROMEOS)
+ chromeos::DBusThreadManager::Initialize();
+ gfx::Screen::SetScreenInstance(
+ gfx::SCREEN_TYPE_NATIVE, aura::TestScreen::Create());
+ wm_test_helper_ = new wm::WMTestHelper(default_window_size);
+#else
+ gfx::Screen::SetScreenInstance(
+ gfx::SCREEN_TYPE_NATIVE, views::CreateDesktopScreen());
+#endif
+ views_delegate_ = new ShellViewsDelegateAura();
+}
+
+void Shell::PlatformExit() {
+#if defined(OS_CHROMEOS)
+ if (wm_test_helper_)
+ delete wm_test_helper_;
+#endif
+ if (views_delegate_)
+ delete views_delegate_;
+#if defined(OS_CHROMEOS)
+ chromeos::DBusThreadManager::Shutdown();
+#endif
+ aura::Env::DeleteInstance();
+}
+
+void Shell::PlatformCleanUp() {
+}
+
+void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) {
+ ShellWindowDelegateView* delegate_view =
+ static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
+ if (control == BACK_BUTTON) {
+ delegate_view->EnableUIControl(ShellWindowDelegateView::BACK_BUTTON,
+ is_enabled);
+ } else if (control == FORWARD_BUTTON) {
+ delegate_view->EnableUIControl(ShellWindowDelegateView::FORWARD_BUTTON,
+ is_enabled);
+ } else if (control == STOP_BUTTON) {
+ delegate_view->EnableUIControl(ShellWindowDelegateView::STOP_BUTTON,
+ is_enabled);
+ }
+}
+
+void Shell::PlatformSetAddressBarURL(const GURL& url) {
+ ShellWindowDelegateView* delegate_view =
+ static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
+ delegate_view->SetAddressBarURL(url);
+}
+
+void Shell::PlatformSetIsLoading(bool loading) {
+}
+
+void Shell::PlatformCreateWindow(int width, int height) {
+#if defined(OS_CHROMEOS)
+ window_widget_ = views::Widget::CreateWindowWithContextAndBounds(
+ new ShellWindowDelegateView(this),
+ wm_test_helper_->GetDefaultParent(NULL, NULL, gfx::Rect()),
+ gfx::Rect(0, 0, width, height));
+#else
+ window_widget_ = views::Widget::CreateWindowWithBounds(
+ new ShellWindowDelegateView(this), gfx::Rect(0, 0, width, height));
+#endif
+
+ content_size_ = gfx::Size(width, height);
+
+ window_ = window_widget_->GetNativeWindow();
+ // Call ShowRootWindow on RootWindow created by WMTestHelper without
+ // which XWindow owned by RootWindow doesn't get mapped.
+ window_->GetDispatcher()->host()->Show();
+ window_widget_->Show();
+}
+
+void Shell::PlatformSetContents() {
+ ShellWindowDelegateView* delegate_view =
+ static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
+ delegate_view->SetWebContents(web_contents_.get(), content_size_);
+}
+
+void Shell::PlatformResizeSubViews() {
+}
+
+void Shell::Close() {
+ window_widget_->CloseNow();
+}
+
+void Shell::PlatformSetTitle(const base::string16& title) {
+ ShellWindowDelegateView* delegate_view =
+ static_cast<ShellWindowDelegateView*>(window_widget_->widget_delegate());
+ delegate_view->SetWindowTitle(title);
+ window_widget_->UpdateWindowTitle();
+}
+
+} // namespace content
diff --git a/chromium/content/shell/browser/shell_web_contents_view_delegate_gtk.cc b/chromium/content/shell/browser/shell_web_contents_view_delegate_gtk.cc
index 4c982573298..5020720b726 100644
--- a/chromium/content/shell/browser/shell_web_contents_view_delegate_gtk.cc
+++ b/chromium/content/shell/browser/shell_web_contents_view_delegate_gtk.cc
@@ -22,7 +22,7 @@
#include "ui/base/gtk/focus_store_gtk.h"
#include "ui/base/gtk/gtk_floating_container.h"
-using WebKit::WebContextMenuData;
+using blink::WebContextMenuData;
namespace content {
diff --git a/chromium/content/shell/browser/shell_web_contents_view_delegate_mac.mm b/chromium/content/shell/browser/shell_web_contents_view_delegate_mac.mm
index 00196af0348..1d01f907180 100644
--- a/chromium/content/shell/browser/shell_web_contents_view_delegate_mac.mm
+++ b/chromium/content/shell/browser/shell_web_contents_view_delegate_mac.mm
@@ -22,7 +22,7 @@
#include "content/shell/common/shell_switches.h"
#include "third_party/WebKit/public/web/WebContextMenuData.h"
-using WebKit::WebContextMenuData;
+using blink::WebContextMenuData;
enum {
ShellContextMenuItemCutTag = 0,
diff --git a/chromium/content/shell/browser/shell_web_contents_view_delegate_win.cc b/chromium/content/shell/browser/shell_web_contents_view_delegate_win.cc
index cd387f054ac..63223f4923a 100644
--- a/chromium/content/shell/browser/shell_web_contents_view_delegate_win.cc
+++ b/chromium/content/shell/browser/shell_web_contents_view_delegate_win.cc
@@ -20,7 +20,7 @@
#include "content/shell/common/shell_switches.h"
#include "third_party/WebKit/public/web/WebContextMenuData.h"
-using WebKit::WebContextMenuData;
+using blink::WebContextMenuData;
namespace {
diff --git a/chromium/content/shell/browser/shell_win.cc b/chromium/content/shell/browser/shell_win.cc
index 2854e5c5c7d..b9e57a96d48 100644
--- a/chromium/content/shell/browser/shell_win.cc
+++ b/chromium/content/shell/browser/shell_win.cc
@@ -130,25 +130,25 @@ void Shell::PlatformCreateWindow(int width, int height) {
ShowWindow(window_, SW_SHOW);
- SizeTo(width, height);
+ SizeTo(gfx::Size(width, height));
}
void Shell::PlatformSetContents() {
SetParent(web_contents_->GetView()->GetNativeView(), window_);
}
-void Shell::SizeTo(int width, int height) {
+void Shell::SizeTo(const gfx::Size& size) {
RECT rc, rw;
GetClientRect(window_, &rc);
GetWindowRect(window_, &rw);
int client_width = rc.right - rc.left;
int window_width = rw.right - rw.left;
- window_width = (window_width - client_width) + width;
+ window_width = (window_width - client_width) + size.width();
int client_height = rc.bottom - rc.top;
int window_height = rw.bottom - rw.top;
- window_height = (window_height - client_height) + height;
+ window_height = (window_height - client_height) + size.height();
// Add space for the url bar.
window_height += kURLBarHeight;
@@ -278,7 +278,7 @@ LRESULT CALLBACK Shell::EditWndProc(HWND hwnd, UINT message,
lParam);
}
-void Shell::PlatformSetTitle(const string16& text) {
+void Shell::PlatformSetTitle(const base::string16& text) {
::SetWindowText(window_, text.c_str());
}
diff --git a/chromium/content/shell/browser/webkit_test_controller.cc b/chromium/content/shell/browser/webkit_test_controller.cc
index 6c2a6034f2b..3939669b419 100644
--- a/chromium/content/shell/browser/webkit_test_controller.cc
+++ b/chromium/content/shell/browser/webkit_test_controller.cc
@@ -13,6 +13,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "content/public/browser/devtools_manager.h"
+#include "content/public/browser/dom_storage_context.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
@@ -21,12 +22,14 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/content_switches.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_content_browser_client.h"
+#include "content/shell/browser/shell_devtools_frontend.h"
#include "content/shell/common/shell_messages.h"
#include "content/shell/common/shell_switches.h"
#include "content/shell/common/webkit_test_helpers.h"
@@ -105,9 +108,7 @@ void WebKitTestResultPrinter::PrintImageFooter() {
return;
if (!capture_text_only_) {
*output_ << "#EOF\n";
- *error_ << "#EOF\n";
output_->flush();
- error_->flush();
}
state_ = AFTER_TEST;
}
@@ -138,9 +139,7 @@ void WebKitTestResultPrinter::PrintAudioFooter() {
return;
if (!capture_text_only_) {
*output_ << "#EOF\n";
- *error_ << "#EOF\n";
output_->flush();
- error_->flush();
}
state_ = IN_IMAGE_BLOCK;
}
@@ -171,15 +170,23 @@ void WebKitTestResultPrinter::PrintEncodedBinaryData(
*output_ << "Content-Transfer-Encoding: base64\n";
std::string data_base64;
- const bool success = base::Base64Encode(
+ base::Base64Encode(
base::StringPiece(reinterpret_cast<const char*>(&data[0]), data.size()),
&data_base64);
- DCHECK(success);
*output_ << "Content-Length: " << data_base64.length() << "\n";
output_->write(data_base64.c_str(), data_base64.length());
}
+void WebKitTestResultPrinter::CloseStderr() {
+ if (state_ != AFTER_TEST)
+ return;
+ if (!capture_text_only_) {
+ *error_ << "#EOF\n";
+ error_->flush();
+ }
+}
+
// WebKitTestController -------------------------------------------------------
@@ -251,7 +258,7 @@ bool WebKitTestController::PrepareForLayoutTest(
#if (defined(OS_WIN) && !defined(USE_AURA)) || \
defined(TOOLKIT_GTK) || defined(OS_MACOSX)
// Shell::SizeTo is not implemented on all platforms.
- main_window_->SizeTo(initial_size_.width(), initial_size_.height());
+ main_window_->SizeTo(initial_size_);
#endif
main_window_->web_contents()->GetRenderViewHost()->GetView()
->SetSize(initial_size_);
@@ -279,6 +286,7 @@ bool WebKitTestController::ResetAfterLayoutTest() {
DCHECK(CalledOnValidThread());
printer_->PrintTextFooter();
printer_->PrintImageFooter();
+ printer_->CloseStderr();
send_configuration_to_next_host_ = false;
test_phase_ = BETWEEN_TESTS;
is_compositing_test_ = false;
@@ -559,6 +567,12 @@ void WebKitTestController::OnOverridePreferences(const WebPreferences& prefs) {
}
void WebKitTestController::OnShowDevTools() {
+ ShellBrowserContext* browser_context =
+ ShellContentBrowserClient::Get()->browser_context();
+ StoragePartition* storage_partition =
+ BrowserContext::GetStoragePartition(browser_context, NULL);
+ storage_partition->GetDOMStorageContext()->DeleteLocalStorage(
+ content::GetDevToolsPathAsURL().GetOrigin());
main_window_->ShowDevTools();
}
diff --git a/chromium/content/shell/browser/webkit_test_controller.h b/chromium/content/shell/browser/webkit_test_controller.h
index 58d1fa9b0c4..06bd7df1bba 100644
--- a/chromium/content/shell/browser/webkit_test_controller.h
+++ b/chromium/content/shell/browser/webkit_test_controller.h
@@ -15,7 +15,6 @@
#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/render_view_host_observer.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/gfx/size.h"
#include "webkit/common/webpreferences.h"
@@ -75,6 +74,8 @@ class WebKitTestResultPrinter {
void AddMessageRaw(const std::string& message);
void AddErrorMessage(const std::string& message);
+ void CloseStderr();
+
private:
void PrintEncodedBinaryData(const std::vector<unsigned char>& data);
diff --git a/chromium/content/shell/common/shell_content_client.cc b/chromium/content/shell/common/shell_content_client.cc
index 495ad85b277..8cb0f88c918 100644
--- a/chromium/content/shell/common/shell_content_client.cc
+++ b/chromium/content/shell/common/shell_content_client.cc
@@ -29,7 +29,7 @@ std::string ShellContentClient::GetUserAgent() const {
return webkit_glue::BuildUserAgentFromProduct(product);
}
-string16 ShellContentClient::GetLocalizedString(int message_id) const {
+base::string16 ShellContentClient::GetLocalizedString(int message_id) const {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) {
switch (message_id) {
case IDS_FORM_OTHER_DATE_LABEL:
diff --git a/chromium/content/shell/common/shell_content_client.h b/chromium/content/shell/common/shell_content_client.h
index 84a14839453..478c06595b3 100644
--- a/chromium/content/shell/common/shell_content_client.h
+++ b/chromium/content/shell/common/shell_content_client.h
@@ -18,7 +18,7 @@ class ShellContentClient : public ContentClient {
virtual ~ShellContentClient();
virtual std::string GetUserAgent() const OVERRIDE;
- virtual string16 GetLocalizedString(int message_id) const OVERRIDE;
+ virtual base::string16 GetLocalizedString(int message_id) const OVERRIDE;
virtual base::StringPiece GetDataResource(
int resource_id,
ui::ScaleFactor scale_factor) const OVERRIDE;
diff --git a/chromium/content/shell/common/shell_switches.cc b/chromium/content/shell/common/shell_switches.cc
index a00af456972..dcd66a5b1ae 100644
--- a/chromium/content/shell/common/shell_switches.cc
+++ b/chromium/content/shell/common/shell_switches.cc
@@ -18,6 +18,9 @@ const char kContentBrowserTest[] = "browser-test";
// Makes Content Shell use the given path for its data directory.
const char kContentShellDataPath[] = "data-path";
+// The directory breakpad should store minidumps in.
+const char kCrashDumpsDir[] = "crash-dumps-dir";
+
// Request pages to be dumped as text once they finished loading.
const char kDumpRenderTree[] = "dump-render-tree";
@@ -31,9 +34,6 @@ const char kEncodeBinary[] = "encode-binary";
// and debugging of layout tests that rely on it.
const char kExposeInternalsForTesting[] = "expose-internals-for-testing";
-// Save results when layout-as-browser tests fail.
-const char kOutputLayoutTestDifferences[] = "output-layout-test-differences";
-
// This makes us disable some web-platform runtime features so that we test
// content_shell as if it was a stable release. It is only followed when
// kDumpRenderTree is set. For the features' level, see
diff --git a/chromium/content/shell/common/shell_switches.h b/chromium/content/shell/common/shell_switches.h
index d6b936a5a57..72797f8f9e3 100644
--- a/chromium/content/shell/common/shell_switches.h
+++ b/chromium/content/shell/common/shell_switches.h
@@ -13,11 +13,11 @@ extern const char kAllowExternalPages[];
extern const char kCheckLayoutTestSysDeps[];
extern const char kContentBrowserTest[];
extern const char kContentShellDataPath[];
+extern const char kCrashDumpsDir[];
extern const char kDumpRenderTree[];
extern const char kEnableAccelerated2DCanvas[];
extern const char kEncodeBinary[];
extern const char kExposeInternalsForTesting[];
-extern const char kOutputLayoutTestDifferences[];
extern const char kStableReleaseMode[];
} // namespace switches
diff --git a/chromium/content/shell/common/webkit_test_helpers.cc b/chromium/content/shell/common/webkit_test_helpers.cc
index b0d4fc026c4..3d3212e881d 100644
--- a/chromium/content/shell/common/webkit_test_helpers.cc
+++ b/chromium/content/shell/common/webkit_test_helpers.cc
@@ -41,15 +41,12 @@ void ExportLayoutTestSpecificPreferences(
to->caret_browsing_enabled = from.caretBrowsingEnabled;
to->allow_displaying_insecure_content = from.allowDisplayOfInsecureContent;
to->allow_running_insecure_content = from.allowRunningOfInsecureContent;
- to->css_shaders_enabled = from.cssCustomFilterEnabled;
to->should_respect_image_orientation = from.shouldRespectImageOrientation;
to->asynchronous_spell_checking_enabled =
from.asynchronousSpellCheckingEnabled;
to->allow_file_access_from_file_urls = from.allowFileAccessFromFileURLs;
- to->author_and_user_styles_enabled = from.authorAndUserStylesEnabled;
to->javascript_can_open_windows_automatically =
from.javaScriptCanOpenWindowsAutomatically;
- to->user_style_sheet_location = from.userStyleSheetLocation;
}
// Applies settings that differ between layout tests and regular mode. Some
@@ -60,6 +57,7 @@ void ApplyLayoutTestDefaultPreferences(WebPreferences* prefs) {
prefs->allow_universal_access_from_file_urls = true;
prefs->dom_paste_enabled = true;
prefs->javascript_can_access_clipboard = true;
+ prefs->xslt_enabled = true;
prefs->xss_auditor_enabled = false;
#if defined(OS_MACOSX)
prefs->editing_behavior = webkit_glue::EDITING_BEHAVIOR_MAC;
@@ -73,7 +71,7 @@ void ApplyLayoutTestDefaultPreferences(WebPreferences* prefs) {
prefs->allow_displaying_insecure_content = true;
prefs->allow_running_insecure_content = true;
prefs->webgl_errors_to_console_enabled = false;
- string16 serif;
+ base::string16 serif;
#if defined(OS_MACOSX)
prefs->cursive_font_family_map[webkit_glue::kCommonScript] =
ASCIIToUTF16("Apple Chancery");
@@ -97,7 +95,6 @@ void ApplyLayoutTestDefaultPreferences(WebPreferences* prefs) {
webkit_glue::kCommonScript] = ASCIIToUTF16("Helvetica");
prefs->minimum_logical_font_size = 9;
prefs->asynchronous_spell_checking_enabled = false;
- prefs->user_style_sheet_enabled = true;
prefs->threaded_html_parser = true;
prefs->accelerated_2d_canvas_enabled =
command_line.HasSwitch(switches::kEnableAccelerated2DCanvas);
@@ -111,6 +108,7 @@ void ApplyLayoutTestDefaultPreferences(WebPreferences* prefs) {
#if defined(OS_ANDROID)
prefs->text_autosizing_enabled = false;
#endif
+ prefs->viewport_enabled = false;
}
base::FilePath GetWebKitRootDirFilePath() {
diff --git a/chromium/content/shell/geolocation/shell_access_token_store.cc b/chromium/content/shell/geolocation/shell_access_token_store.cc
index ceae3d60f6e..4b8b0074e92 100644
--- a/chromium/content/shell/geolocation/shell_access_token_store.cc
+++ b/chromium/content/shell/geolocation/shell_access_token_store.cc
@@ -49,7 +49,7 @@ void ShellAccessTokenStore::RespondOnOriginatingThread(
}
void ShellAccessTokenStore::SaveAccessToken(
- const GURL& server_url, const string16& access_token) {
+ const GURL& server_url, const base::string16& access_token) {
}
} // namespace content
diff --git a/chromium/content/shell/geolocation/shell_access_token_store.h b/chromium/content/shell/geolocation/shell_access_token_store.h
index 82ee0f888e9..0345b8c41fd 100644
--- a/chromium/content/shell/geolocation/shell_access_token_store.h
+++ b/chromium/content/shell/geolocation/shell_access_token_store.h
@@ -28,7 +28,7 @@ class ShellAccessTokenStore : public content::AccessTokenStore {
const LoadAccessTokensCallbackType& callback) OVERRIDE;
virtual void SaveAccessToken(
- const GURL& server_url, const string16& access_token) OVERRIDE;
+ const GURL& server_url, const base::string16& access_token) OVERRIDE;
content::ShellBrowserContext* shell_browser_context_;
net::URLRequestContextGetter* system_request_context_;
diff --git a/chromium/content/shell/renderer/shell_content_renderer_client.cc b/chromium/content/shell/renderer/shell_content_renderer_client.cc
index 8569a09a712..d04cbfc2f24 100644
--- a/chromium/content/shell/renderer/shell_content_renderer_client.cc
+++ b/chromium/content/shell/renderer/shell_content_renderer_client.cc
@@ -24,18 +24,18 @@
#include "third_party/WebKit/public/web/WebView.h"
#include "v8/include/v8.h"
-using WebKit::WebAudioDevice;
-using WebKit::WebClipboard;
-using WebKit::WebFrame;
-using WebKit::WebMIDIAccessor;
-using WebKit::WebMIDIAccessorClient;
-using WebKit::WebMediaStreamCenter;
-using WebKit::WebMediaStreamCenterClient;
-using WebKit::WebPlugin;
-using WebKit::WebPluginParams;
-using WebKit::WebRTCPeerConnectionHandler;
-using WebKit::WebRTCPeerConnectionHandlerClient;
-using WebKit::WebThemeEngine;
+using blink::WebAudioDevice;
+using blink::WebClipboard;
+using blink::WebFrame;
+using blink::WebMIDIAccessor;
+using blink::WebMIDIAccessorClient;
+using blink::WebMediaStreamCenter;
+using blink::WebMediaStreamCenterClient;
+using blink::WebPlugin;
+using blink::WebPluginParams;
+using blink::WebRTCPeerConnectionHandler;
+using blink::WebRTCPeerConnectionHandlerClient;
+using blink::WebThemeEngine;
using WebTestRunner::WebTestDelegate;
using WebTestRunner::WebTestInterfaces;
using WebTestRunner::WebTestProxyBase;
@@ -94,7 +94,7 @@ void ShellContentRendererClient::RenderViewCreated(RenderView* render_view) {
}
bool ShellContentRendererClient::OverrideCreatePlugin(
- RenderView* render_view,
+ RenderFrame* render_frame,
WebFrame* frame,
const WebPluginParams& params,
WebPlugin** plugin) {
@@ -160,14 +160,6 @@ WebClipboard* ShellContentRendererClient::OverrideWebClipboard() {
return clipboard_.get();
}
-WebKit::WebCrypto* ShellContentRendererClient::OverrideWebCrypto() {
- if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
- return NULL;
- WebTestInterfaces* interfaces =
- ShellRenderProcessObserver::GetInstance()->test_interfaces();
- return interfaces->crypto();
-}
-
WebThemeEngine* ShellContentRendererClient::OverrideThemeEngine() {
if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
return NULL;
@@ -188,7 +180,7 @@ void ShellContentRendererClient::WebTestProxyCreated(RenderView* render_view,
}
bool ShellContentRendererClient::AllowBrowserPlugin(
- WebKit::WebPluginContainer* container) {
+ blink::WebPluginContainer* container) {
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableBrowserPluginForAllViewTypes)) {
// Allow BrowserPlugin if forced by command line flag. This is generally
diff --git a/chromium/content/shell/renderer/shell_content_renderer_client.h b/chromium/content/shell/renderer/shell_content_renderer_client.h
index fc35f035bd5..16d945baece 100644
--- a/chromium/content/shell/renderer/shell_content_renderer_client.h
+++ b/chromium/content/shell/renderer/shell_content_renderer_client.h
@@ -10,7 +10,7 @@
#include "base/platform_file.h"
#include "content/public/renderer/content_renderer_client.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
class WebPlugin;
struct WebPluginParams;
@@ -20,10 +20,9 @@ namespace WebTestRunner {
class WebTestProxyBase;
}
-class MockWebClipboardImpl;
-
namespace content {
+class MockWebClipboardImpl;
class ShellRenderProcessObserver;
class ShellContentRendererClient : public ContentRendererClient {
@@ -37,24 +36,23 @@ class ShellContentRendererClient : public ContentRendererClient {
virtual void RenderThreadStarted() OVERRIDE;
virtual void RenderViewCreated(RenderView* render_view) OVERRIDE;
virtual bool OverrideCreatePlugin(
- RenderView* render_view,
- WebKit::WebFrame* frame,
- const WebKit::WebPluginParams& params,
- WebKit::WebPlugin** plugin) OVERRIDE;
- virtual WebKit::WebMediaStreamCenter* OverrideCreateWebMediaStreamCenter(
- WebKit::WebMediaStreamCenterClient* client) OVERRIDE;
- virtual WebKit::WebRTCPeerConnectionHandler*
+ RenderFrame* render_frame,
+ blink::WebFrame* frame,
+ const blink::WebPluginParams& params,
+ blink::WebPlugin** plugin) OVERRIDE;
+ virtual blink::WebMediaStreamCenter* OverrideCreateWebMediaStreamCenter(
+ blink::WebMediaStreamCenterClient* client) OVERRIDE;
+ virtual blink::WebRTCPeerConnectionHandler*
OverrideCreateWebRTCPeerConnectionHandler(
- WebKit::WebRTCPeerConnectionHandlerClient* client) OVERRIDE;
- virtual WebKit::WebMIDIAccessor* OverrideCreateMIDIAccessor(
- WebKit::WebMIDIAccessorClient* client) OVERRIDE;
- virtual WebKit::WebAudioDevice* OverrideCreateAudioDevice(
+ blink::WebRTCPeerConnectionHandlerClient* client) OVERRIDE;
+ virtual blink::WebMIDIAccessor* OverrideCreateMIDIAccessor(
+ blink::WebMIDIAccessorClient* client) OVERRIDE;
+ virtual blink::WebAudioDevice* OverrideCreateAudioDevice(
double sample_rate) OVERRIDE;
- virtual WebKit::WebClipboard* OverrideWebClipboard() OVERRIDE;
- virtual WebKit::WebCrypto* OverrideWebCrypto() OVERRIDE;
- virtual WebKit::WebThemeEngine* OverrideThemeEngine() OVERRIDE;
+ virtual blink::WebClipboard* OverrideWebClipboard() OVERRIDE;
+ virtual blink::WebThemeEngine* OverrideThemeEngine() OVERRIDE;
virtual bool AllowBrowserPlugin(
- WebKit::WebPluginContainer* container) OVERRIDE;
+ blink::WebPluginContainer* container) OVERRIDE;
private:
void WebTestProxyCreated(RenderView* render_view,
diff --git a/chromium/content/shell/renderer/shell_render_process_observer.cc b/chromium/content/shell/renderer/shell_render_process_observer.cc
index 2694993e8c7..c4fc6401c2b 100644
--- a/chromium/content/shell/renderer/shell_render_process_observer.cc
+++ b/chromium/content/shell/renderer/shell_render_process_observer.cc
@@ -19,8 +19,8 @@
#include "third_party/WebKit/public/web/WebView.h"
#include "webkit/glue/webkit_glue.h"
-using WebKit::WebFrame;
-using WebKit::WebRuntimeFeatures;
+using blink::WebFrame;
+using blink::WebRuntimeFeatures;
using WebTestRunner::WebTestDelegate;
using WebTestRunner::WebTestInterfaces;
@@ -79,6 +79,10 @@ void ShellRenderProcessObserver::WebKitInitialized() {
test_interfaces_->resetAll();
}
+void ShellRenderProcessObserver::OnRenderProcessShutdown() {
+ test_interfaces_.reset();
+}
+
bool ShellRenderProcessObserver::OnControlMessageReceived(
const IPC::Message& message) {
bool handled = true;
diff --git a/chromium/content/shell/renderer/shell_render_process_observer.h b/chromium/content/shell/renderer/shell_render_process_observer.h
index 5762523ba7b..ffe59e2ba4c 100644
--- a/chromium/content/shell/renderer/shell_render_process_observer.h
+++ b/chromium/content/shell/renderer/shell_render_process_observer.h
@@ -12,7 +12,7 @@
#include "content/public/renderer/render_process_observer.h"
#include "ipc/ipc_platform_file.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
}
@@ -38,6 +38,7 @@ class ShellRenderProcessObserver : public RenderProcessObserver {
// RenderProcessObserver implementation.
virtual void WebKitInitialized() OVERRIDE;
+ virtual void OnRenderProcessShutdown() OVERRIDE;
virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
WebTestRunner::WebTestDelegate* test_delegate() const {
diff --git a/chromium/content/shell/renderer/shell_render_view_observer.cc b/chromium/content/shell/renderer/shell_render_view_observer.cc
index 9758f6497b4..b5b82cd604b 100644
--- a/chromium/content/shell/renderer/shell_render_view_observer.cc
+++ b/chromium/content/shell/renderer/shell_render_view_observer.cc
@@ -17,10 +17,10 @@ ShellRenderViewObserver::ShellRenderViewObserver(RenderView* render_view)
: RenderViewObserver(render_view) {
}
-void ShellRenderViewObserver::DidClearWindowObject(WebKit::WebFrame* frame) {
+void ShellRenderViewObserver::DidClearWindowObject(blink::WebFrame* frame) {
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kExposeInternalsForTesting)) {
- WebKit::WebTestingSupport::injectInternalsObject(frame);
+ blink::WebTestingSupport::injectInternalsObject(frame);
}
}
diff --git a/chromium/content/shell/renderer/shell_render_view_observer.h b/chromium/content/shell/renderer/shell_render_view_observer.h
index c295c344582..c4127792366 100644
--- a/chromium/content/shell/renderer/shell_render_view_observer.h
+++ b/chromium/content/shell/renderer/shell_render_view_observer.h
@@ -7,7 +7,7 @@
#include "content/public/renderer/render_view_observer.h"
-namespace WebKit {
+namespace blink {
class WebFrame;
}
@@ -23,7 +23,7 @@ class ShellRenderViewObserver : public RenderViewObserver {
private:
// RenderViewObserver implementation.
- virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE;
+ virtual void DidClearWindowObject(blink::WebFrame* frame) OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(ShellRenderViewObserver);
};
diff --git a/chromium/content/shell/renderer/webkit_test_runner.cc b/chromium/content/shell/renderer/webkit_test_runner.cc
index 69f32cc0a57..e9b96aecddb 100644
--- a/chromium/content/shell/renderer/webkit_test_runner.cc
+++ b/chromium/content/shell/renderer/webkit_test_runner.cc
@@ -50,7 +50,6 @@
#include "third_party/WebKit/public/web/WebContextMenuData.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebDevToolsAgent.h"
-#include "third_party/WebKit/public/web/WebDeviceOrientation.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebFrame.h"
@@ -61,30 +60,28 @@
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/gfx/rect.h"
#include "webkit/common/webpreferences.h"
-#include "webkit/glue/webkit_glue.h"
-
-using WebKit::Platform;
-using WebKit::WebArrayBufferView;
-using WebKit::WebContextMenuData;
-using WebKit::WebDevToolsAgent;
-using WebKit::WebDeviceMotionData;
-using WebKit::WebDeviceOrientationData;
-using WebKit::WebDeviceOrientation;
-using WebKit::WebElement;
-using WebKit::WebFrame;
-using WebKit::WebGamepads;
-using WebKit::WebHistoryItem;
-using WebKit::WebPoint;
-using WebKit::WebRect;
-using WebKit::WebScriptSource;
-using WebKit::WebSize;
-using WebKit::WebString;
-using WebKit::WebURL;
-using WebKit::WebURLError;
-using WebKit::WebURLRequest;
-using WebKit::WebTestingSupport;
-using WebKit::WebVector;
-using WebKit::WebView;
+
+using blink::Platform;
+using blink::WebArrayBufferView;
+using blink::WebContextMenuData;
+using blink::WebDevToolsAgent;
+using blink::WebDeviceMotionData;
+using blink::WebDeviceOrientationData;
+using blink::WebElement;
+using blink::WebFrame;
+using blink::WebGamepads;
+using blink::WebHistoryItem;
+using blink::WebPoint;
+using blink::WebRect;
+using blink::WebScriptSource;
+using blink::WebSize;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebURLError;
+using blink::WebURLRequest;
+using blink::WebTestingSupport;
+using blink::WebVector;
+using blink::WebView;
using WebTestRunner::WebTask;
using WebTestRunner::WebTestInterfaces;
using WebTestRunner::WebTestProxyBase;
@@ -188,6 +185,20 @@ class NavigateAwayVisitor : public RenderViewVisitor {
DISALLOW_COPY_AND_ASSIGN(NavigateAwayVisitor);
};
+class UseSynchronousResizeModeVisitor : public RenderViewVisitor {
+ public:
+ explicit UseSynchronousResizeModeVisitor(bool enable) : enable_(enable) {}
+ virtual ~UseSynchronousResizeModeVisitor() {}
+
+ virtual bool Visit(RenderView* render_view) OVERRIDE {
+ UseSynchronousResizeMode(render_view, enable_);
+ return true;
+ }
+
+ private:
+ bool enable_;
+};
+
} // namespace
WebKitTestRunner::WebKitTestRunner(RenderView* render_view)
@@ -243,7 +254,7 @@ void WebKitTestRunner::postDelayedTask(WebTask* task, long long ms) {
}
WebString WebKitTestRunner::registerIsolatedFileSystem(
- const WebKit::WebVector<WebKit::WebString>& absolute_filenames) {
+ const blink::WebVector<blink::WebString>& absolute_filenames) {
std::vector<base::FilePath> files;
for (size_t i = 0; i < absolute_filenames.size(); ++i)
files.push_back(base::FilePath::FromUTF16Unsafe(absolute_filenames[i]));
@@ -281,8 +292,7 @@ WebURL WebKitTestRunner::localFileToDataURL(const WebURL& file_url) {
routing_id(), local_path, &contents));
std::string contents_base64;
- if (!base::Base64Encode(contents, &contents_base64))
- return WebURL();
+ base::Base64Encode(contents, &contents_base64);
const char data_url_prefix[] = "data:text/css:charset=utf-8;base64,";
return WebURL(GURL(data_url_prefix + contents_base64));
@@ -351,8 +361,9 @@ std::string WebKitTestRunner::makeURLErrorDescription(
domain.c_str(), code, error.unreachableURL.spec().data());
}
-void WebKitTestRunner::setClientWindowRect(const WebRect& rect) {
- ForceResizeRenderView(render_view(), WebSize(rect.width, rect.height));
+void WebKitTestRunner::useUnfortunateSynchronousResizeMode(bool enable) {
+ UseSynchronousResizeModeVisitor visitor(enable);
+ RenderView::ForEach(&visitor);
}
void WebKitTestRunner::enableAutoResizeMode(const WebSize& min_size,
@@ -501,7 +512,7 @@ bool WebKitTestRunner::allowExternalPages() {
void WebKitTestRunner::captureHistoryForWindow(
WebTestProxyBase* proxy,
- WebVector<WebKit::WebHistoryItem>* history,
+ WebVector<blink::WebHistoryItem>* history,
size_t* currentEntryIndex) {
size_t pos = 0;
std::vector<int>::iterator id;
@@ -591,8 +602,6 @@ void WebKitTestRunner::Reset() {
render_view()->GetWebView()->mainFrame()->clearOpener();
render_view()->GetWebView()->setPageScaleFactorLimits(-1, -1);
render_view()->GetWebView()->setPageScaleFactor(1, WebPoint(0, 0));
- render_view()->GetWebView()->enableFixedLayoutMode(false);
- render_view()->GetWebView()->setFixedLayoutSize(WebSize(0, 0));
// Resetting the internals object also overrides the WebPreferences, so we
// have to sync them to WebKit again.
diff --git a/chromium/content/shell/renderer/webkit_test_runner.h b/chromium/content/shell/renderer/webkit_test_runner.h
index de8d48f3caa..4b126438bd5 100644
--- a/chromium/content/shell/renderer/webkit_test_runner.h
+++ b/chromium/content/shell/renderer/webkit_test_runner.h
@@ -19,7 +19,7 @@
class SkCanvas;
-namespace WebKit {
+namespace blink {
class WebDeviceMotionData;
class WebDeviceOrientationData;
struct WebRect;
@@ -41,39 +41,39 @@ class WebKitTestRunner : public RenderViewObserver,
// RenderViewObserver implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE;
+ virtual void DidClearWindowObject(blink::WebFrame* frame) OVERRIDE;
virtual void Navigate(const GURL& url) OVERRIDE;
- virtual void DidCommitProvisionalLoad(WebKit::WebFrame* frame,
+ virtual void DidCommitProvisionalLoad(blink::WebFrame* frame,
bool is_new_navigation) OVERRIDE;
virtual void DidFailProvisionalLoad(
- WebKit::WebFrame* frame, const WebKit::WebURLError& error) OVERRIDE;
+ blink::WebFrame* frame, const blink::WebURLError& error) OVERRIDE;
// WebTestDelegate implementation.
virtual void clearEditCommand();
virtual void setEditCommand(const std::string& name,
const std::string& value);
- virtual void setGamepadData(const WebKit::WebGamepads& gamepads);
- virtual void setDeviceMotionData(const WebKit::WebDeviceMotionData& data);
+ virtual void setGamepadData(const blink::WebGamepads& gamepads);
+ virtual void setDeviceMotionData(const blink::WebDeviceMotionData& data);
virtual void setDeviceOrientationData(
- const WebKit::WebDeviceOrientationData& data);
+ const blink::WebDeviceOrientationData& data);
virtual void printMessage(const std::string& message);
virtual void postTask(::WebTestRunner::WebTask* task);
virtual void postDelayedTask(::WebTestRunner::WebTask* task,
long long ms);
- virtual WebKit::WebString registerIsolatedFileSystem(
- const WebKit::WebVector<WebKit::WebString>& absolute_filenames);
+ virtual blink::WebString registerIsolatedFileSystem(
+ const blink::WebVector<blink::WebString>& absolute_filenames);
virtual long long getCurrentTimeInMillisecond();
- virtual WebKit::WebString getAbsoluteWebStringFromUTF8Path(
+ virtual blink::WebString getAbsoluteWebStringFromUTF8Path(
const std::string& utf8_path);
- virtual WebKit::WebURL localFileToDataURL(const WebKit::WebURL& file_url);
- virtual WebKit::WebURL rewriteLayoutTestsURL(const std::string& utf8_url);
+ virtual blink::WebURL localFileToDataURL(const blink::WebURL& file_url);
+ virtual blink::WebURL rewriteLayoutTestsURL(const std::string& utf8_url);
virtual ::WebTestRunner::WebPreferences* preferences();
virtual void applyPreferences();
- virtual std::string makeURLErrorDescription(const WebKit::WebURLError& error);
- virtual void setClientWindowRect(const WebKit::WebRect& rect);
- virtual void enableAutoResizeMode(const WebKit::WebSize& min_size,
- const WebKit::WebSize& max_size);
- virtual void disableAutoResizeMode(const WebKit::WebSize& new_size);
+ virtual std::string makeURLErrorDescription(const blink::WebURLError& error);
+ virtual void useUnfortunateSynchronousResizeMode(bool enable);
+ virtual void enableAutoResizeMode(const blink::WebSize& min_size,
+ const blink::WebSize& max_size);
+ virtual void disableAutoResizeMode(const blink::WebSize& new_size);
virtual void showDevTools();
virtual void closeDevTools();
virtual void evaluateInWebInspector(long call_id, const std::string& script);
@@ -90,12 +90,12 @@ class WebKitTestRunner : public RenderViewObserver,
virtual int navigationEntryCount();
virtual void goToOffset(int offset);
virtual void reload();
- virtual void loadURLForFrame(const WebKit::WebURL& url,
+ virtual void loadURLForFrame(const blink::WebURL& url,
const std::string& frame_name);
virtual bool allowExternalPages();
virtual void captureHistoryForWindow(
WebTestRunner::WebTestProxyBase* proxy,
- WebKit::WebVector<WebKit::WebHistoryItem>* history,
+ blink::WebVector<blink::WebHistoryItem>* history,
size_t* currentEntryIndex);
void Reset();
diff --git a/chromium/content/shell/resources/missingImage.png b/chromium/content/shell/resources/missingImage.png
index 5c24d20c2c4..51dde55d5c3 100644
--- a/chromium/content/shell/resources/missingImage.png
+++ b/chromium/content/shell/resources/missingImage.png
Binary files differ
diff --git a/chromium/content/shell/resources/textAreaResizeCorner.png b/chromium/content/shell/resources/textAreaResizeCorner.png
index 023615e5597..a379bdd3053 100644
--- a/chromium/content/shell/resources/textAreaResizeCorner.png
+++ b/chromium/content/shell/resources/textAreaResizeCorner.png
Binary files differ
diff --git a/chromium/content/shell/tools/DEPS b/chromium/content/shell/tools/DEPS
new file mode 100644
index 00000000000..7083ae76862
--- /dev/null
+++ b/chromium/content/shell/tools/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+content/public",
+ "+components/breakpad",
+]
diff --git a/chromium/content/shell/tools/content_shell_crash_service.cc b/chromium/content/shell/tools/content_shell_crash_service.cc
new file mode 100644
index 00000000000..3b82d1b1ec6
--- /dev/null
+++ b/chromium/content/shell/tools/content_shell_crash_service.cc
@@ -0,0 +1,42 @@
+// 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 <windows.h>
+#include <stdlib.h>
+#include <tchar.h>
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "components/breakpad/tools/crash_service.h"
+
+int __stdcall wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd_line,
+ int show_mode) {
+ // Manages the destruction of singletons.
+ base::AtExitManager exit_manager;
+
+ CommandLine::Init(0, NULL);
+
+ // Logging to stderr.
+ logging::LoggingSettings settings;
+ settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
+ logging::InitLogging(settings);
+ // Logging with pid, tid and timestamp.
+ logging::SetLogItems(true, true, true, false);
+
+ VLOG(1) << "session start. cmdline is [" << cmd_line << "]";
+
+ breakpad::CrashService crash_service;
+ if (!crash_service.Initialize(base::FilePath(), base::FilePath()))
+ return 1;
+
+ VLOG(1) << "ready to process crash requests";
+
+ // Enter the message loop.
+ int retv = crash_service.ProcessingLoop();
+ // Time to exit.
+ VLOG(1) << "session end. return code is " << retv;
+ return retv;
+}
diff --git a/chromium/content/utility/utility_main.cc b/chromium/content/utility/utility_main.cc
index c93c1eca536..a522427b6e7 100644
--- a/chromium/content/utility/utility_main.cc
+++ b/chromium/content/utility/utility_main.cc
@@ -3,11 +3,12 @@
// found in the LICENSE file.
#include "base/command_line.h"
+#include "base/debug/leak_annotations.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/platform_thread.h"
#include "base/timer/hi_res_timer_manager.h"
#include "content/child/child_process.h"
-#include "content/common/sandbox_linux.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
#include "content/public/common/sandbox_init.h"
@@ -17,6 +18,12 @@
#include "sandbox/win/src/sandbox.h"
#endif
+#if defined(TOOLKIT_GTK)
+#include <gtk/gtk.h>
+
+#include "ui/gfx/gtk_util.h"
+#endif
+
namespace content {
// Mainline routine for running as the utility process.
@@ -26,10 +33,40 @@ int UtilityMain(const MainFunctionParams& parameters) {
base::PlatformThread::SetName("CrUtilityMain");
#if defined(OS_LINUX)
- // Initialize the sandbox before any thread is created.
+ // Initializes the sandbox before any threads are created.
+ // TODO(jorgelo): move this after GTK initialization when we enable a strict
+ // Seccomp-BPF policy.
LinuxSandbox::InitializeSandbox();
#endif
+#if defined(OS_POSIX)
+ // The utility process is used to load plugins (see OnLoadPlugins() in
+ // utility_thread_impl.cc). Some plugins expect the browser to have loaded
+ // GLib/GTK.
+ // Due to bugs in GLib we need to initialize GLib/GTK before we start threads,
+ // see crbug.com/309093.
+
+#if defined(TOOLKIT_GTK)
+ bool is_sandboxed = false;
+
+#if defined(OS_LINUX)
+ // On Linux, we only initialize GLib/GTK if we're not sandboxed.
+ is_sandboxed = !parameters.command_line.HasSwitch(switches::kNoSandbox);
+#endif
+
+ if (!is_sandboxed) {
+ // g_thread_init() is deprecated since glib 2.31.0, please see release note:
+ // http://mail.gnome.org/archives/gnome-announce-list/2011-October/msg00041.html
+#if !(GLIB_CHECK_VERSION(2, 31, 0))
+ if (!g_thread_get_initialized()) {
+ g_thread_init(NULL);
+ }
+#endif
+ gfx::GtkInitFromCommandLine(*CommandLine::ForCurrentProcess());
+ }
+#endif
+#endif
+
ChildProcess utility_process;
utility_process.set_main_thread(new UtilityThreadImpl());
@@ -48,6 +85,12 @@ int UtilityMain(const MainFunctionParams& parameters) {
base::MessageLoop::current()->Run();
+#if defined(LEAK_SANITIZER)
+ // Invoke LeakSanitizer before shutting down the utility thread, to avoid
+ // reporting shutdown-only leaks.
+ __lsan_do_leak_check();
+#endif
+
return 0;
}
diff --git a/chromium/content/utility/utility_thread_impl.cc b/chromium/content/utility/utility_thread_impl.cc
index ca03da40981..6151de67e7c 100644
--- a/chromium/content/utility/utility_thread_impl.cc
+++ b/chromium/content/utility/utility_thread_impl.cc
@@ -19,12 +19,6 @@
#include "ipc/ipc_sync_channel.h"
#include "third_party/WebKit/public/web/WebKit.h"
-#if defined(TOOLKIT_GTK)
-#include <gtk/gtk.h>
-
-#include "ui/gfx/gtk_util.h"
-#endif
-
namespace content {
namespace {
@@ -55,7 +49,7 @@ void UtilityThreadImpl::Shutdown() {
ChildThread::Shutdown();
if (!single_process_)
- WebKit::shutdown();
+ blink::shutdown();
}
bool UtilityThreadImpl::Send(IPC::Message* msg) {
@@ -98,7 +92,7 @@ void UtilityThreadImpl::Init() {
// needs WebKit initialized in the utility process, they need to have
// another path to support single process mode.
webkit_platform_support_.reset(new WebKitPlatformSupportImpl);
- WebKit::initialize(webkit_platform_support_.get());
+ blink::initialize(webkit_platform_support_.get());
}
GetContentClient()->utility()->UtilityThreadStarted();
}
@@ -132,19 +126,6 @@ void UtilityThreadImpl::OnLoadPlugins(
const std::vector<base::FilePath>& plugin_paths) {
PluginList* plugin_list = PluginList::Singleton();
- // On Linux, some plugins expect the browser to have loaded glib/gtk. Do that
- // before attempting to call into the plugin.
- // g_thread_init API is deprecated since glib 2.31.0, please see release note:
- // http://mail.gnome.org/archives/gnome-announce-list/2011-October/msg00041.html
-#if defined(TOOLKIT_GTK)
-#if !(GLIB_CHECK_VERSION(2, 31, 0))
- if (!g_thread_get_initialized()) {
- g_thread_init(NULL);
- }
-#endif
- gfx::GtkInitFromCommandLine(*CommandLine::ForCurrentProcess());
-#endif
-
std::vector<WebPluginInfo> plugins;
// TODO(bauerb): If we restart loading plug-ins, we might mess up the logic in
// PluginList::ShouldLoadPlugin due to missing the previously loaded plug-ins
diff --git a/chromium/content/worker/shared_worker_devtools_agent.cc b/chromium/content/worker/shared_worker_devtools_agent.cc
index 9de96438077..733dae1ef7a 100644
--- a/chromium/content/worker/shared_worker_devtools_agent.cc
+++ b/chromium/content/worker/shared_worker_devtools_agent.cc
@@ -10,8 +10,8 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebSharedWorker.h"
-using WebKit::WebSharedWorker;
-using WebKit::WebString;
+using blink::WebSharedWorker;
+using blink::WebString;
namespace content {
@@ -44,14 +44,14 @@ bool SharedWorkerDevToolsAgent::OnMessageReceived(const IPC::Message& message) {
}
void SharedWorkerDevToolsAgent::SendDevToolsMessage(
- const WebKit::WebString& message) {
+ const blink::WebString& message) {
Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(
route_id_,
message.utf8()));
}
void SharedWorkerDevToolsAgent::SaveDevToolsAgentState(
- const WebKit::WebString& state) {
+ const blink::WebString& state) {
Send(new DevToolsHostMsg_SaveAgentRuntimeState(route_id_,
state.utf8()));
}
diff --git a/chromium/content/worker/shared_worker_devtools_agent.h b/chromium/content/worker/shared_worker_devtools_agent.h
index ad6bc7d8489..bfe0fefd192 100644
--- a/chromium/content/worker/shared_worker_devtools_agent.h
+++ b/chromium/content/worker/shared_worker_devtools_agent.h
@@ -13,7 +13,7 @@ namespace IPC {
class Message;
}
-namespace WebKit {
+namespace blink {
class WebSharedWorker;
class WebString;
}
@@ -22,13 +22,13 @@ namespace content {
class SharedWorkerDevToolsAgent {
public:
- SharedWorkerDevToolsAgent(int route_id, WebKit::WebSharedWorker*);
+ SharedWorkerDevToolsAgent(int route_id, blink::WebSharedWorker*);
~SharedWorkerDevToolsAgent();
// Called on the Worker thread.
bool OnMessageReceived(const IPC::Message& message);
- void SendDevToolsMessage(const WebKit::WebString&);
- void SaveDevToolsAgentState(const WebKit::WebString& state);
+ void SendDevToolsMessage(const blink::WebString&);
+ void SaveDevToolsAgentState(const blink::WebString& state);
private:
void OnAttach();
@@ -40,7 +40,7 @@ class SharedWorkerDevToolsAgent {
bool Send(IPC::Message* message);
const int route_id_;
- WebKit::WebSharedWorker* webworker_;
+ blink::WebSharedWorker* webworker_;
DISALLOW_COPY_AND_ASSIGN(SharedWorkerDevToolsAgent);
};
diff --git a/chromium/content/worker/shared_worker_permission_client_proxy.cc b/chromium/content/worker/shared_worker_permission_client_proxy.cc
new file mode 100644
index 00000000000..eb187c252de
--- /dev/null
+++ b/chromium/content/worker/shared_worker_permission_client_proxy.cc
@@ -0,0 +1,60 @@
+// 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/worker/shared_worker_permission_client_proxy.h"
+
+#include "content/child/thread_safe_sender.h"
+#include "content/common/worker_messages.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "url/gurl.h"
+
+namespace content {
+
+SharedWorkerPermissionClientProxy::SharedWorkerPermissionClientProxy(
+ const GURL& origin_url,
+ bool is_unique_origin,
+ int routing_id,
+ ThreadSafeSender* thread_safe_sender)
+ : origin_url_(origin_url),
+ is_unique_origin_(is_unique_origin),
+ routing_id_(routing_id),
+ thread_safe_sender_(thread_safe_sender) {
+}
+
+SharedWorkerPermissionClientProxy::~SharedWorkerPermissionClientProxy() {
+}
+
+bool SharedWorkerPermissionClientProxy::allowDatabase(
+ const blink::WebString& name,
+ const blink::WebString& display_name,
+ unsigned long estimated_size) {
+ if (is_unique_origin_)
+ return false;
+ bool result = false;
+ thread_safe_sender_->Send(new WorkerProcessHostMsg_AllowDatabase(
+ routing_id_, origin_url_, name, display_name,
+ estimated_size, &result));
+ return result;
+}
+
+bool SharedWorkerPermissionClientProxy::allowFileSystem() {
+ if (is_unique_origin_)
+ return false;
+ bool result = false;
+ thread_safe_sender_->Send(new WorkerProcessHostMsg_AllowFileSystem(
+ routing_id_, origin_url_, &result));
+ return result;
+}
+
+bool SharedWorkerPermissionClientProxy::allowIndexedDB(
+ const blink::WebString& name) {
+ if (is_unique_origin_)
+ return false;
+ bool result = false;
+ thread_safe_sender_->Send(new WorkerProcessHostMsg_AllowIndexedDB(
+ routing_id_, origin_url_, name, &result));
+ return result;
+}
+
+} // namespace content
diff --git a/chromium/content/worker/shared_worker_permission_client_proxy.h b/chromium/content/worker/shared_worker_permission_client_proxy.h
new file mode 100644
index 00000000000..61f58c95185
--- /dev/null
+++ b/chromium/content/worker/shared_worker_permission_client_proxy.h
@@ -0,0 +1,47 @@
+// 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_WORKER_SHARED_WORKER_PERMISSION_CLIENT_PROXY_H_
+#define CONTENT_WORKER_SHARED_WORKER_PERMISSION_CLIENT_PROXY_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "third_party/WebKit/public/web/WebWorkerPermissionClientProxy.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class ThreadSafeSender;
+
+// This proxy is created on the main renderer thread then passed onto
+// the blink's worker thread.
+class SharedWorkerPermissionClientProxy
+ : public blink::WebWorkerPermissionClientProxy {
+ public:
+ SharedWorkerPermissionClientProxy(
+ const GURL& origin_url,
+ bool is_unique_origin,
+ int routing_id,
+ ThreadSafeSender* thread_safe_sender);
+ virtual ~SharedWorkerPermissionClientProxy();
+
+ // WebWorkerPermissionClientProxy overrides.
+ virtual bool allowDatabase(const blink::WebString& name,
+ const blink::WebString& display_name,
+ unsigned long estimated_size);
+ virtual bool allowFileSystem();
+ virtual bool allowIndexedDB(const blink::WebString& name);
+
+ private:
+ const GURL origin_url_;
+ const bool is_unique_origin_;
+ const int routing_id_;
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharedWorkerPermissionClientProxy);
+};
+
+} // namespace content
+
+#endif // CONTENT_WORKER_SHARED_WORKER_PERMISSION_CLIENT_PROXY_H_
diff --git a/chromium/content/worker/websharedworker_stub.cc b/chromium/content/worker/websharedworker_stub.cc
index 745b63c1956..4f6dd933c6f 100644
--- a/chromium/content/worker/websharedworker_stub.cc
+++ b/chromium/content/worker/websharedworker_stub.cc
@@ -19,7 +19,7 @@
namespace content {
WebSharedWorkerStub::WebSharedWorkerStub(
- const string16& name,
+ const base::string16& name,
int route_id,
const WorkerAppCacheInitInfo& appcache_init_info)
: route_id_(route_id),
@@ -33,10 +33,9 @@ WebSharedWorkerStub::WebSharedWorkerStub(
worker_thread->AddWorkerStub(this);
// Start processing incoming IPCs for this worker.
worker_thread->AddRoute(route_id_, this);
- ChildProcess::current()->AddRefProcess();
// TODO(atwilson): Add support for NaCl when they support MessagePorts.
- impl_ = WebKit::WebSharedWorker::create(client());
+ impl_ = blink::WebSharedWorker::create(client());
worker_devtools_agent_.reset(new SharedWorkerDevToolsAgent(route_id, impl_));
client()->set_devtools_agent(worker_devtools_agent_.get());
}
@@ -47,7 +46,6 @@ WebSharedWorkerStub::~WebSharedWorkerStub() {
DCHECK(worker_thread);
worker_thread->RemoveWorkerStub(this);
worker_thread->RemoveRoute(route_id_);
- ChildProcess::current()->ReleaseProcess();
}
void WebSharedWorkerStub::Shutdown() {
@@ -83,9 +81,10 @@ const GURL& WebSharedWorkerStub::url() {
}
void WebSharedWorkerStub::OnStartWorkerContext(
- const GURL& url, const string16& user_agent, const string16& source_code,
- const string16& content_security_policy,
- WebKit::WebContentSecurityPolicyType policy_type) {
+ const GURL& url, const base::string16& user_agent,
+ const base::string16& source_code,
+ const base::string16& content_security_policy,
+ blink::WebContentSecurityPolicyType policy_type) {
// Ignore multiple attempts to start this worker (can happen if two pages
// try to start it simultaneously).
if (started_)
@@ -107,11 +106,11 @@ void WebSharedWorkerStub::OnStartWorkerContext(
void WebSharedWorkerStub::OnConnect(int sent_message_port_id, int routing_id) {
if (started_) {
- WebKit::WebMessagePortChannel* channel =
+ blink::WebMessagePortChannel* channel =
new WebMessagePortChannelImpl(routing_id,
sent_message_port_id,
base::MessageLoopProxy::current().get());
- impl_->connect(channel, NULL);
+ impl_->connect(channel);
} else {
// If two documents try to load a SharedWorker at the same time, the
// WorkerMsg_Connect for one of the documents can come in before the
diff --git a/chromium/content/worker/websharedworker_stub.h b/chromium/content/worker/websharedworker_stub.h
index 8dd312d5d99..66d11ea7b18 100644
--- a/chromium/content/worker/websharedworker_stub.h
+++ b/chromium/content/worker/websharedworker_stub.h
@@ -6,13 +6,14 @@
#define CONTENT_WORKER_WEBSHAREDWORKER_STUB_H_
#include "base/memory/scoped_ptr.h"
+#include "content/child/scoped_child_process_reference.h"
#include "content/worker/websharedworkerclient_proxy.h"
#include "content/worker/worker_webapplicationcachehost_impl.h"
#include "ipc/ipc_listener.h"
#include "third_party/WebKit/public/web/WebSharedWorker.h"
#include "url/gurl.h"
-namespace WebKit {
+namespace blink {
class WebSharedWorker;
}
@@ -24,7 +25,7 @@ class SharedWorkerDevToolsAgent;
// appropriate WebSharedWorker APIs.
class WebSharedWorkerStub : public IPC::Listener {
public:
- WebSharedWorkerStub(const string16& name, int route_id,
+ WebSharedWorkerStub(const base::string16& name, int route_id,
const WorkerAppCacheInitInfo& appcache_init_info);
// IPC::Listener implementation.
@@ -53,12 +54,15 @@ class WebSharedWorkerStub : public IPC::Listener {
void OnConnect(int sent_message_port_id, int routing_id);
void OnStartWorkerContext(
- const GURL& url, const string16& user_agent, const string16& source_code,
- const string16& content_security_policy,
- WebKit::WebContentSecurityPolicyType policy_type);
+ const GURL& url, const base::string16& user_agent,
+ const base::string16& source_code,
+ const base::string16& content_security_policy,
+ blink::WebContentSecurityPolicyType policy_type);
void OnTerminateWorkerContext();
+ ScopedChildProcessReference process_ref_;
+
int route_id_;
WorkerAppCacheInitInfo appcache_init_info_;
@@ -66,8 +70,8 @@ class WebSharedWorkerStub : public IPC::Listener {
// from the worker object.
WebSharedWorkerClientProxy client_;
- WebKit::WebSharedWorker* impl_;
- string16 name_;
+ blink::WebSharedWorker* impl_;
+ base::string16 name_;
bool started_;
GURL url_;
scoped_ptr<SharedWorkerDevToolsAgent> worker_devtools_agent_;
diff --git a/chromium/content/worker/websharedworkerclient_proxy.cc b/chromium/content/worker/websharedworkerclient_proxy.cc
index ec2e264c481..1e8c92fad29 100644
--- a/chromium/content/worker/websharedworkerclient_proxy.cc
+++ b/chromium/content/worker/websharedworkerclient_proxy.cc
@@ -11,6 +11,7 @@
#include "content/common/worker_messages.h"
#include "content/public/common/content_switches.h"
#include "content/worker/shared_worker_devtools_agent.h"
+#include "content/worker/shared_worker_permission_client_proxy.h"
#include "content/worker/websharedworker_stub.h"
#include "content/worker/worker_thread.h"
#include "content/worker/worker_webapplicationcachehost_impl.h"
@@ -21,14 +22,14 @@
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
-using WebKit::WebApplicationCacheHost;
-using WebKit::WebFrame;
-using WebKit::WebMessagePortChannel;
-using WebKit::WebMessagePortChannelArray;
-using WebKit::WebSecurityOrigin;
-using WebKit::WebString;
-using WebKit::WebWorker;
-using WebKit::WebSharedWorkerClient;
+using blink::WebApplicationCacheHost;
+using blink::WebFrame;
+using blink::WebMessagePortChannel;
+using blink::WebMessagePortChannelArray;
+using blink::WebSecurityOrigin;
+using blink::WebString;
+using blink::WebWorker;
+using blink::WebSharedWorkerClient;
namespace content {
@@ -47,61 +48,6 @@ WebSharedWorkerClientProxy::WebSharedWorkerClientProxy(
WebSharedWorkerClientProxy::~WebSharedWorkerClientProxy() {
}
-void WebSharedWorkerClientProxy::postMessageToWorkerObject(
- const WebString& message,
- const WebMessagePortChannelArray& channels) {
- std::vector<int> message_port_ids(channels.size());
- std::vector<int> routing_ids(channels.size());
- for (size_t i = 0; i < channels.size(); ++i) {
- WebMessagePortChannelImpl* webchannel =
- static_cast<WebMessagePortChannelImpl*>(channels[i]);
- message_port_ids[i] = webchannel->message_port_id();
- webchannel->QueueMessages();
- DCHECK(message_port_ids[i] != MSG_ROUTING_NONE);
- routing_ids[i] = MSG_ROUTING_NONE;
- }
-
- Send(new WorkerMsg_PostMessage(
- route_id_, message, message_port_ids, routing_ids));
-}
-
-void WebSharedWorkerClientProxy::postExceptionToWorkerObject(
- const WebString& error_message,
- int line_number,
- const WebString& source_url) {
- Send(new WorkerHostMsg_PostExceptionToWorkerObject(
- route_id_, error_message, line_number, source_url));
-}
-
-void WebSharedWorkerClientProxy::postConsoleMessageToWorkerObject(
- int source,
- int type,
- int level,
- const WebString& message,
- int line_number,
- const WebString& source_url) {
- WorkerHostMsg_PostConsoleMessageToWorkerObject_Params params;
- params.source_identifier = source;
- params.message_type = type;
- params.message_level = level;
- params.message = message;
- params.line_number = line_number;
- params.source_url = source_url;
- Send(new WorkerHostMsg_PostConsoleMessageToWorkerObject(route_id_, params));
-}
-
-void WebSharedWorkerClientProxy::confirmMessageFromWorkerObject(
- bool has_pending_activity) {
- Send(new WorkerHostMsg_ConfirmMessageFromWorkerObject(
- route_id_, has_pending_activity));
-}
-
-void WebSharedWorkerClientProxy::reportPendingActivity(
- bool has_pending_activity) {
- Send(new WorkerHostMsg_ReportPendingActivity(
- route_id_, has_pending_activity));
-}
-
void WebSharedWorkerClientProxy::workerContextClosed() {
Send(new WorkerHostMsg_WorkerContextClosed(route_id_));
}
@@ -113,7 +59,7 @@ void WebSharedWorkerClientProxy::workerContextDestroyed() {
stub_->Shutdown();
}
-WebKit::WebNotificationPresenter*
+blink::WebNotificationPresenter*
WebSharedWorkerClientProxy::notificationPresenter() {
// TODO(johnnyg): Notifications are not yet hooked up to workers.
// Coming soon.
@@ -122,7 +68,7 @@ WebSharedWorkerClientProxy::notificationPresenter() {
}
WebApplicationCacheHost* WebSharedWorkerClientProxy::createApplicationCacheHost(
- WebKit::WebApplicationCacheHostClient* client) {
+ blink::WebApplicationCacheHostClient* client) {
WorkerWebApplicationCacheHostImpl* host =
new WorkerWebApplicationCacheHostImpl(stub_->appcache_init_info(),
client);
@@ -132,36 +78,28 @@ WebApplicationCacheHost* WebSharedWorkerClientProxy::createApplicationCacheHost(
return host;
}
-// TODO(abarth): Security checks should use WebDocument or WebSecurityOrigin,
-// not WebFrame as the context object because WebFrames can contain different
-// WebDocuments at different times.
+blink::WebWorkerPermissionClientProxy*
+WebSharedWorkerClientProxy::createWorkerPermissionClientProxy(
+ const blink::WebSecurityOrigin& origin) {
+ return new SharedWorkerPermissionClientProxy(
+ GURL(origin.toString()), origin.isUnique(), route_id_,
+ ChildThread::current()->thread_safe_sender());
+}
+
+// TODO(kinuko): Deprecate these methods.
bool WebSharedWorkerClientProxy::allowDatabase(WebFrame* frame,
const WebString& name,
const WebString& display_name,
unsigned long estimated_size) {
- WebSecurityOrigin origin = frame->document().securityOrigin();
- if (origin.isUnique())
- return false;
-
- bool result = false;
- Send(new WorkerProcessHostMsg_AllowDatabase(
- route_id_, GURL(origin.toString().utf8()), name, display_name,
- estimated_size, &result));
- return result;
+ return false;
}
bool WebSharedWorkerClientProxy::allowFileSystem() {
- bool result = false;
- Send(new WorkerProcessHostMsg_AllowFileSystem(
- route_id_, stub_->url().GetOrigin(), &result));
- return result;
+ return false;
}
-bool WebSharedWorkerClientProxy::allowIndexedDB(const WebKit::WebString& name) {
- bool result = false;
- Send(new WorkerProcessHostMsg_AllowIndexedDB(
- route_id_, stub_->url().GetOrigin(), name, &result));
- return result;
+bool WebSharedWorkerClientProxy::allowIndexedDB(const blink::WebString& name) {
+ return false;
}
void WebSharedWorkerClientProxy::dispatchDevToolsMessage(
@@ -171,7 +109,7 @@ void WebSharedWorkerClientProxy::dispatchDevToolsMessage(
}
void WebSharedWorkerClientProxy::saveDevToolsAgentState(
- const WebKit::WebString& state) {
+ const blink::WebString& state) {
if (devtools_agent_)
devtools_agent_->SaveDevToolsAgentState(state);
}
diff --git a/chromium/content/worker/websharedworkerclient_proxy.h b/chromium/content/worker/websharedworkerclient_proxy.h
index 39d12034fd8..636e73f6da3 100644
--- a/chromium/content/worker/websharedworkerclient_proxy.h
+++ b/chromium/content/worker/websharedworkerclient_proxy.h
@@ -10,10 +10,11 @@
#include "ipc/ipc_channel.h"
#include "third_party/WebKit/public/web/WebSharedWorkerClient.h"
-namespace WebKit {
+namespace blink {
class WebApplicationCacheHost;
class WebApplicationCacheHostClient;
class WebFrame;
+class WebSecurityOrigin;
}
namespace content {
@@ -26,56 +27,33 @@ class WebSharedWorkerStub;
// is also called by the worker code and converts these function calls into
// IPCs that are sent to the renderer, where they're converted back to function
// calls by WebWorkerProxy.
-class WebSharedWorkerClientProxy : public WebKit::WebSharedWorkerClient {
+class WebSharedWorkerClientProxy : public blink::WebSharedWorkerClient {
public:
WebSharedWorkerClientProxy(int route_id, WebSharedWorkerStub* stub);
virtual ~WebSharedWorkerClientProxy();
// WebSharedWorkerClient implementation.
- virtual void postMessageToWorkerObject(
- const WebKit::WebString& message,
- const WebKit::WebMessagePortChannelArray& channel);
- virtual void postExceptionToWorkerObject(
- const WebKit::WebString& error_message,
- int line_number,
- const WebKit::WebString& source_url);
- // TODO(caseq): The overload before is obsolete and is preserved for
- // WebKit/chromium compatibility only (pure virtual is base class).
- // Should be removed once WebKit part is updated.
- virtual void postConsoleMessageToWorkerObject(
- int destination,
- int source,
- int type,
- int level,
- const WebKit::WebString& message,
- int line_number,
- const WebKit::WebString& source_url) {
- }
- virtual void postConsoleMessageToWorkerObject(
- int source,
- int type,
- int level,
- const WebKit::WebString& message,
- int line_number,
- const WebKit::WebString& source_url);
- virtual void confirmMessageFromWorkerObject(bool has_pending_activity);
- virtual void reportPendingActivity(bool has_pending_activity);
virtual void workerContextClosed();
virtual void workerContextDestroyed();
- virtual WebKit::WebNotificationPresenter* notificationPresenter();
+ virtual blink::WebNotificationPresenter* notificationPresenter();
- virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost(
- WebKit::WebApplicationCacheHostClient* client);
+ virtual blink::WebApplicationCacheHost* createApplicationCacheHost(
+ blink::WebApplicationCacheHostClient* client);
+ virtual blink::WebWorkerPermissionClientProxy*
+ createWorkerPermissionClientProxy(
+ const blink::WebSecurityOrigin& origin);
- virtual bool allowDatabase(WebKit::WebFrame* frame,
- const WebKit::WebString& name,
- const WebKit::WebString& display_name,
+ // TODO(kinuko): Deprecate these methods.
+ virtual bool allowDatabase(blink::WebFrame* frame,
+ const blink::WebString& name,
+ const blink::WebString& display_name,
unsigned long estimated_size);
virtual bool allowFileSystem();
- virtual bool allowIndexedDB(const WebKit::WebString&);
- virtual void dispatchDevToolsMessage(const WebKit::WebString&);
- virtual void saveDevToolsAgentState(const WebKit::WebString&);
+ virtual bool allowIndexedDB(const blink::WebString&);
+
+ virtual void dispatchDevToolsMessage(const blink::WebString&);
+ virtual void saveDevToolsAgentState(const blink::WebString&);
void EnsureWorkerContextTerminates();
diff --git a/chromium/content/worker/worker_main.cc b/chromium/content/worker/worker_main.cc
index b6a8fd1a34a..8cc8ed0f220 100644
--- a/chromium/content/worker/worker_main.cc
+++ b/chromium/content/worker/worker_main.cc
@@ -9,7 +9,7 @@
#include "base/threading/platform_thread.h"
#include "base/timer/hi_res_timer_manager.h"
#include "content/child/child_process.h"
-#include "content/common/sandbox_linux.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/public/common/main_function_params.h"
#include "content/public/common/sandbox_init.h"
#include "content/worker/worker_thread.h"
@@ -29,6 +29,7 @@ int WorkerMain(const MainFunctionParams& parameters) {
// The main message loop of the worker process.
base::MessageLoop main_message_loop;
base::PlatformThread::SetName("CrWorkerMain");
+ base::debug::TraceLog::GetInstance()->SetProcessName("Shared Web Worker");
#if defined(OS_WIN)
sandbox::TargetServices* target_services =
diff --git a/chromium/content/worker/worker_thread.cc b/chromium/content/worker/worker_thread.cc
index 4cabcb4b34c..54764d0229c 100644
--- a/chromium/content/worker/worker_thread.cc
+++ b/chromium/content/worker/worker_thread.cc
@@ -13,6 +13,7 @@
#include "content/child/indexed_db/indexed_db_message_filter.h"
#include "content/child/runtime_features.h"
#include "content/child/web_database_observer_impl.h"
+#include "content/common/child_process_messages.h"
#include "content/common/worker_messages.h"
#include "content/public/common/content_switches.h"
#include "content/worker/websharedworker_stub.h"
@@ -24,7 +25,7 @@
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "webkit/glue/webkit_glue.h"
-using WebKit::WebRuntimeFeatures;
+using blink::WebRuntimeFeatures;
namespace content {
@@ -37,23 +38,33 @@ WorkerThread::WorkerThread() {
thread_safe_sender(),
sync_message_filter(),
quota_message_filter()));
- WebKit::initialize(webkit_platform_support_.get());
+
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
+ webkit_glue::SetJavaScriptFlags(
+ command_line.GetSwitchValueASCII(switches::kJavaScriptFlags));
+ }
+ SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line);
+
+ blink::initialize(webkit_platform_support_.get());
appcache_dispatcher_.reset(
new AppCacheDispatcher(this, new AppCacheFrontendImpl()));
- web_database_observer_impl_.reset(
- new WebDatabaseObserverImpl(sync_message_filter()));
- WebKit::WebDatabase::setObserver(web_database_observer_impl_.get());
db_message_filter_ = new DBMessageFilter();
channel()->AddFilter(db_message_filter_.get());
indexed_db_message_filter_ = new IndexedDBMessageFilter(
thread_safe_sender());
- channel()->AddFilter(indexed_db_message_filter_.get());
+ channel()->AddFilter(indexed_db_message_filter_->GetFilter());
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line);
+}
+
+void WorkerThread::OnShutdown() {
+ // The worker process is to be shut down gracefully. Ask the browser
+ // process to shut it down forcefully instead and wait on the message, so that
+ // there are no races between threads when the process is shutting down.
+ Send(new WorkerProcessHostMsg_ForceKillWorker());
}
WorkerThread::~WorkerThread() {
@@ -62,14 +73,18 @@ WorkerThread::~WorkerThread() {
void WorkerThread::Shutdown() {
ChildThread::Shutdown();
+ if (webkit_platform_support_) {
+ webkit_platform_support_->web_database_observer_impl()->
+ WaitForAllDatabasesToClose();
+ }
+
// Shutdown in reverse of the initialization order.
- channel()->RemoveFilter(indexed_db_message_filter_.get());
indexed_db_message_filter_ = NULL;
channel()->RemoveFilter(db_message_filter_.get());
db_message_filter_ = NULL;
- WebKit::shutdown();
+ blink::shutdown();
lazy_tls.Pointer()->Set(NULL);
}
@@ -90,6 +105,15 @@ bool WorkerThread::OnControlMessageReceived(const IPC::Message& msg) {
return handled;
}
+bool WorkerThread::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(WorkerThread, msg)
+ IPC_MESSAGE_HANDLER(ChildProcessMsg_Shutdown, OnShutdown)
+ IPC_MESSAGE_UNHANDLED(handled = ChildThread::OnMessageReceived(msg))
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
void WorkerThread::OnCreateWorker(
const WorkerProcessMsg_CreateWorker_Params& params) {
WorkerAppCacheInitInfo appcache_init_info(
diff --git a/chromium/content/worker/worker_thread.h b/chromium/content/worker/worker_thread.h
index fe1379b8fb8..927cd9a2a61 100644
--- a/chromium/content/worker/worker_thread.h
+++ b/chromium/content/worker/worker_thread.h
@@ -15,7 +15,6 @@ namespace content {
class AppCacheDispatcher;
class DBMessageFilter;
class IndexedDBMessageFilter;
-class WebDatabaseObserverImpl;
class WebSharedWorkerStub;
class WorkerWebKitPlatformSupportImpl;
@@ -39,12 +38,13 @@ class WorkerThread : public ChildThread {
private:
virtual bool OnControlMessageReceived(const IPC::Message& msg) OVERRIDE;
virtual void OnChannelError() OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
void OnCreateWorker(const WorkerProcessMsg_CreateWorker_Params& params);
+ void OnShutdown();
scoped_ptr<WorkerWebKitPlatformSupportImpl> webkit_platform_support_;
scoped_ptr<AppCacheDispatcher> appcache_dispatcher_;
- scoped_ptr<WebDatabaseObserverImpl> web_database_observer_impl_;
scoped_refptr<DBMessageFilter> db_message_filter_;
scoped_refptr<IndexedDBMessageFilter> indexed_db_message_filter_;
diff --git a/chromium/content/worker/worker_webapplicationcachehost_impl.cc b/chromium/content/worker/worker_webapplicationcachehost_impl.cc
index 9283906f01d..23201c87bee 100644
--- a/chromium/content/worker/worker_webapplicationcachehost_impl.cc
+++ b/chromium/content/worker/worker_webapplicationcachehost_impl.cc
@@ -11,7 +11,7 @@ namespace content {
WorkerWebApplicationCacheHostImpl::WorkerWebApplicationCacheHostImpl(
const WorkerAppCacheInitInfo& init_info,
- WebKit::WebApplicationCacheHostClient* client)
+ blink::WebApplicationCacheHostClient* client)
: WebApplicationCacheHostImpl(client,
WorkerThread::current()->appcache_dispatcher()->backend_proxy()) {
backend()->SelectCacheForSharedWorker(host_id(),
@@ -19,11 +19,11 @@ WorkerWebApplicationCacheHostImpl::WorkerWebApplicationCacheHostImpl(
}
void WorkerWebApplicationCacheHostImpl::willStartMainResourceRequest(
- WebKit::WebURLRequest&, const WebKit::WebFrame*) {
+ blink::WebURLRequest&, const blink::WebFrame*) {
}
void WorkerWebApplicationCacheHostImpl::didReceiveResponseForMainResource(
- const WebKit::WebURLResponse&) {
+ const blink::WebURLResponse&) {
}
void WorkerWebApplicationCacheHostImpl::didReceiveDataForMainResource(
@@ -38,7 +38,7 @@ void WorkerWebApplicationCacheHostImpl::selectCacheWithoutManifest() {
}
bool WorkerWebApplicationCacheHostImpl::selectCacheWithManifest(
- const WebKit::WebURL&) {
+ const blink::WebURL&) {
return true;
}
diff --git a/chromium/content/worker/worker_webapplicationcachehost_impl.h b/chromium/content/worker/worker_webapplicationcachehost_impl.h
index 2360cb3c767..6f8385cb035 100644
--- a/chromium/content/worker/worker_webapplicationcachehost_impl.h
+++ b/chromium/content/worker/worker_webapplicationcachehost_impl.h
@@ -30,15 +30,15 @@ class WorkerWebApplicationCacheHostImpl : public WebApplicationCacheHostImpl {
public:
WorkerWebApplicationCacheHostImpl(
const WorkerAppCacheInitInfo& init_info,
- WebKit::WebApplicationCacheHostClient* client);
+ blink::WebApplicationCacheHostClient* client);
// Main resource loading is different for workers. The resource is
// loaded by the creator of the worker rather than the worker itself.
// These overrides are stubbed out.
virtual void willStartMainResourceRequest(
- WebKit::WebURLRequest&, const WebKit::WebFrame*);
+ blink::WebURLRequest&, const blink::WebFrame*);
virtual void didReceiveResponseForMainResource(
- const WebKit::WebURLResponse&);
+ const blink::WebURLResponse&);
virtual void didReceiveDataForMainResource(const char* data, int len);
virtual void didFinishLoadingMainResource(bool success);
@@ -46,7 +46,7 @@ class WorkerWebApplicationCacheHostImpl : public WebApplicationCacheHostImpl {
// time what cache to select and do so then.
// These overrides are stubbed out.
virtual void selectCacheWithoutManifest();
- virtual bool selectCacheWithManifest(const WebKit::WebURL& manifestURL);
+ virtual bool selectCacheWithManifest(const blink::WebURL& manifestURL);
};
} // namespace content
diff --git a/chromium/content/worker/worker_webkitplatformsupport_impl.cc b/chromium/content/worker/worker_webkitplatformsupport_impl.cc
index 3cc4c81d5bf..1d7b3265872 100644
--- a/chromium/content/worker/worker_webkitplatformsupport_impl.cc
+++ b/chromium/content/worker/worker_webkitplatformsupport_impl.cc
@@ -11,10 +11,11 @@
#include "base/strings/utf_string_conversions.h"
#include "content/child/database_util.h"
#include "content/child/fileapi/webfilesystem_impl.h"
-#include "content/child/indexed_db/proxy_webidbfactory_impl.h"
+#include "content/child/indexed_db/webidbfactory_impl.h"
#include "content/child/quota_dispatcher.h"
#include "content/child/quota_message_filter.h"
#include "content/child/thread_safe_sender.h"
+#include "content/child/web_database_observer_impl.h"
#include "content/child/webblobregistry_impl.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/file_utilities_messages.h"
@@ -30,18 +31,18 @@
#include "webkit/glue/webfileutilities_impl.h"
#include "webkit/glue/webkit_glue.h"
-using WebKit::Platform;
-using WebKit::WebBlobRegistry;
-using WebKit::WebClipboard;
-using WebKit::WebFileInfo;
-using WebKit::WebFileSystem;
-using WebKit::WebFileUtilities;
-using WebKit::WebMessagePortChannel;
-using WebKit::WebMimeRegistry;
-using WebKit::WebSandboxSupport;
-using WebKit::WebStorageNamespace;
-using WebKit::WebString;
-using WebKit::WebURL;
+using blink::Platform;
+using blink::WebBlobRegistry;
+using blink::WebClipboard;
+using blink::WebFileInfo;
+using blink::WebFileSystem;
+using blink::WebFileUtilities;
+using blink::WebMessagePortChannel;
+using blink::WebMimeRegistry;
+using blink::WebSandboxSupport;
+using blink::WebStorageNamespace;
+using blink::WebString;
+using blink::WebURL;
namespace content {
@@ -83,6 +84,12 @@ WorkerWebKitPlatformSupportImpl::WorkerWebKitPlatformSupportImpl(
child_thread_loop_(base::MessageLoopProxy::current()),
sync_message_filter_(sync_message_filter),
quota_message_filter_(quota_message_filter) {
+ if (sender) {
+ blob_registry_.reset(new WebBlobRegistryImpl(sender));
+ web_idb_factory_.reset(new WebIDBFactoryImpl(sender));
+ web_database_observer_impl_.reset(
+ new WebDatabaseObserverImpl(sync_message_filter));
+ }
}
WorkerWebKitPlatformSupportImpl::~WorkerWebKitPlatformSupportImpl() {
@@ -167,7 +174,7 @@ WorkerWebKitPlatformSupportImpl::createLocalStorageNamespace() {
void WorkerWebKitPlatformSupportImpl::dispatchStorageEvent(
const WebString& key, const WebString& old_value,
const WebString& new_value, const WebString& origin,
- const WebKit::WebURL& url, bool is_local_storage) {
+ const blink::WebURL& url, bool is_local_storage) {
NOTREACHED();
}
@@ -202,13 +209,17 @@ long long WorkerWebKitPlatformSupportImpl::databaseGetSpaceAvailableForOrigin(
sync_message_filter_.get());
}
-WebKit::WebIDBFactory* WorkerWebKitPlatformSupportImpl::idbFactory() {
+blink::WebIDBFactory* WorkerWebKitPlatformSupportImpl::idbFactory() {
if (!web_idb_factory_)
- web_idb_factory_.reset(
- new RendererWebIDBFactoryImpl(thread_safe_sender_.get()));
+ web_idb_factory_.reset(new WebIDBFactoryImpl(thread_safe_sender_.get()));
return web_idb_factory_.get();
}
+blink::WebDatabaseObserver*
+WorkerWebKitPlatformSupportImpl::databaseObserver() {
+ return web_database_observer_impl_.get();
+}
+
WebMimeRegistry::SupportsType
WorkerWebKitPlatformSupportImpl::supportsMIMEType(
const WebString&) {
@@ -230,20 +241,13 @@ WorkerWebKitPlatformSupportImpl::supportsJavaScriptMIMEType(const WebString&) {
WebMimeRegistry::SupportsType
WorkerWebKitPlatformSupportImpl::supportsMediaMIMEType(
- const WebString&, const WebString&) {
- NOTREACHED();
- return WebMimeRegistry::IsSupported;
-}
-
-WebMimeRegistry::SupportsType
-WorkerWebKitPlatformSupportImpl::supportsMediaMIMEType(
const WebString&, const WebString&, const WebString&) {
NOTREACHED();
return WebMimeRegistry::IsSupported;
}
bool WorkerWebKitPlatformSupportImpl::supportsMediaSourceMIMEType(
- const WebKit::WebString& mimeType, const WebKit::WebString& codecs) {
+ const blink::WebString& mimeType, const blink::WebString& codecs) {
NOTREACHED();
return false;
}
@@ -282,15 +286,13 @@ WebString WorkerWebKitPlatformSupportImpl::mimeTypeFromFile(
}
WebBlobRegistry* WorkerWebKitPlatformSupportImpl::blobRegistry() {
- if (!blob_registry_.get() && thread_safe_sender_.get())
- blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_.get()));
return blob_registry_.get();
}
void WorkerWebKitPlatformSupportImpl::queryStorageUsageAndQuota(
- const WebKit::WebURL& storage_partition,
- WebKit::WebStorageQuotaType type,
- WebKit::WebStorageQuotaCallbacks* callbacks) {
+ const blink::WebURL& storage_partition,
+ blink::WebStorageQuotaType type,
+ blink::WebStorageQuotaCallbacks* callbacks) {
if (!thread_safe_sender_.get() || !quota_message_filter_.get())
return;
QuotaDispatcher::ThreadSpecificInstance(
diff --git a/chromium/content/worker/worker_webkitplatformsupport_impl.h b/chromium/content/worker/worker_webkitplatformsupport_impl.h
index d429822a57f..784dcca8e5a 100644
--- a/chromium/content/worker/worker_webkitplatformsupport_impl.h
+++ b/chromium/content/worker/worker_webkitplatformsupport_impl.h
@@ -18,17 +18,18 @@ namespace IPC {
class SyncMessageFilter;
}
-namespace WebKit {
+namespace blink {
class WebFileUtilities;
}
namespace content {
class QuotaMessageFilter;
class ThreadSafeSender;
+class WebDatabaseObserverImpl;
class WebFileSystemImpl;
class WorkerWebKitPlatformSupportImpl : public WebKitPlatformSupportImpl,
- public WebKit::WebMimeRegistry {
+ public blink::WebMimeRegistry {
public:
WorkerWebKitPlatformSupportImpl(
ThreadSafeSender* sender,
@@ -37,83 +38,83 @@ class WorkerWebKitPlatformSupportImpl : public WebKitPlatformSupportImpl,
virtual ~WorkerWebKitPlatformSupportImpl();
// WebKitPlatformSupport methods:
- virtual WebKit::WebClipboard* clipboard();
- virtual WebKit::WebMimeRegistry* mimeRegistry();
- virtual WebKit::WebFileSystem* fileSystem();
- virtual WebKit::WebFileUtilities* fileUtilities();
- virtual WebKit::WebSandboxSupport* sandboxSupport();
+ virtual blink::WebClipboard* clipboard();
+ virtual blink::WebMimeRegistry* mimeRegistry();
+ virtual blink::WebFileSystem* fileSystem();
+ virtual blink::WebFileUtilities* fileUtilities();
+ virtual blink::WebSandboxSupport* sandboxSupport();
virtual bool sandboxEnabled();
virtual unsigned long long visitedLinkHash(const char* canonicalURL,
size_t length);
virtual bool isLinkVisited(unsigned long long linkHash);
- virtual WebKit::WebMessagePortChannel* createMessagePortChannel();
- virtual void setCookies(const WebKit::WebURL& url,
- const WebKit::WebURL& first_party_for_cookies,
- const WebKit::WebString& value);
- virtual WebKit::WebString cookies(
- const WebKit::WebURL& url,
- const WebKit::WebURL& first_party_for_cookies);
- virtual WebKit::WebString defaultLocale();
- virtual WebKit::WebStorageNamespace* createLocalStorageNamespace();
+ virtual blink::WebMessagePortChannel* createMessagePortChannel();
+ virtual void setCookies(const blink::WebURL& url,
+ const blink::WebURL& first_party_for_cookies,
+ const blink::WebString& value);
+ virtual blink::WebString cookies(
+ const blink::WebURL& url,
+ const blink::WebURL& first_party_for_cookies);
+ virtual blink::WebString defaultLocale();
+ virtual blink::WebStorageNamespace* createLocalStorageNamespace();
virtual void dispatchStorageEvent(
- const WebKit::WebString& key, const WebKit::WebString& old_value,
- const WebKit::WebString& new_value, const WebKit::WebString& origin,
- const WebKit::WebURL& url, bool is_local_storage);
+ const blink::WebString& key, const blink::WebString& old_value,
+ const blink::WebString& new_value, const blink::WebString& origin,
+ const blink::WebURL& url, bool is_local_storage);
- virtual WebKit::Platform::FileHandle databaseOpenFile(
- const WebKit::WebString& vfs_file_name, int desired_flags);
- virtual int databaseDeleteFile(const WebKit::WebString& vfs_file_name,
+ virtual blink::Platform::FileHandle databaseOpenFile(
+ const blink::WebString& vfs_file_name, int desired_flags);
+ virtual int databaseDeleteFile(const blink::WebString& vfs_file_name,
bool sync_dir);
virtual long databaseGetFileAttributes(
- const WebKit::WebString& vfs_file_name);
+ const blink::WebString& vfs_file_name);
virtual long long databaseGetFileSize(
- const WebKit::WebString& vfs_file_name);
+ const blink::WebString& vfs_file_name);
virtual long long databaseGetSpaceAvailableForOrigin(
- const WebKit::WebString& origin_identifier);
-
- virtual WebKit::WebBlobRegistry* blobRegistry();
-
- virtual WebKit::WebIDBFactory* idbFactory();
+ const blink::WebString& origin_identifier);
+ virtual blink::WebBlobRegistry* blobRegistry();
+ virtual blink::WebIDBFactory* idbFactory();
+ virtual blink::WebDatabaseObserver* databaseObserver();
// WebMimeRegistry methods:
- virtual WebKit::WebMimeRegistry::SupportsType supportsMIMEType(
- const WebKit::WebString&);
- virtual WebKit::WebMimeRegistry::SupportsType supportsImageMIMEType(
- const WebKit::WebString&);
- virtual WebKit::WebMimeRegistry::SupportsType supportsJavaScriptMIMEType(
- const WebKit::WebString&);
- // TODO(ddorwin): Remove after http://webk.it/82983 lands.
- virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType(
- const WebKit::WebString&, const WebKit::WebString&);
- virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType(
- const WebKit::WebString&,
- const WebKit::WebString&,
- const WebKit::WebString&);
+ virtual blink::WebMimeRegistry::SupportsType supportsMIMEType(
+ const blink::WebString&);
+ virtual blink::WebMimeRegistry::SupportsType supportsImageMIMEType(
+ const blink::WebString&);
+ virtual blink::WebMimeRegistry::SupportsType supportsJavaScriptMIMEType(
+ const blink::WebString&);
+ virtual blink::WebMimeRegistry::SupportsType supportsMediaMIMEType(
+ const blink::WebString&,
+ const blink::WebString&,
+ const blink::WebString&);
virtual bool supportsMediaSourceMIMEType(
- const WebKit::WebString&,
- const WebKit::WebString&);
- virtual WebKit::WebMimeRegistry::SupportsType supportsNonImageMIMEType(
- const WebKit::WebString&);
- virtual WebKit::WebString mimeTypeForExtension(const WebKit::WebString&);
- virtual WebKit::WebString wellKnownMimeTypeForExtension(
- const WebKit::WebString&);
- virtual WebKit::WebString mimeTypeFromFile(const WebKit::WebString&);
+ const blink::WebString&,
+ const blink::WebString&);
+ virtual blink::WebMimeRegistry::SupportsType supportsNonImageMIMEType(
+ const blink::WebString&);
+ virtual blink::WebString mimeTypeForExtension(const blink::WebString&);
+ virtual blink::WebString wellKnownMimeTypeForExtension(
+ const blink::WebString&);
+ virtual blink::WebString mimeTypeFromFile(const blink::WebString&);
virtual void queryStorageUsageAndQuota(
- const WebKit::WebURL& storage_partition,
- WebKit::WebStorageQuotaType,
- WebKit::WebStorageQuotaCallbacks*) OVERRIDE;
+ const blink::WebURL& storage_partition,
+ blink::WebStorageQuotaType,
+ blink::WebStorageQuotaCallbacks*) OVERRIDE;
+
+ WebDatabaseObserverImpl* web_database_observer_impl() {
+ return web_database_observer_impl_.get();
+ }
private:
class FileUtilities;
scoped_ptr<FileUtilities> file_utilities_;
- scoped_ptr<WebKit::WebBlobRegistry> blob_registry_;
- scoped_ptr<WebFileSystemImpl> web_file_system_;
- scoped_ptr<WebKit::WebIDBFactory> web_idb_factory_;
+ scoped_ptr<blink::WebBlobRegistry> blob_registry_;
+ scoped_ptr<blink::WebIDBFactory> web_idb_factory_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
scoped_refptr<base::MessageLoopProxy> child_thread_loop_;
scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
scoped_refptr<QuotaMessageFilter> quota_message_filter_;
+ scoped_ptr<WebDatabaseObserverImpl> web_database_observer_impl_;
};
} // namespace content
diff --git a/chromium/content/zygote/zygote_linux.cc b/chromium/content/zygote/zygote_linux.cc
index 08f1ecbb5d2..2f0bd2033e1 100644
--- a/chromium/content/zygote/zygote_linux.cc
+++ b/chromium/content/zygote/zygote_linux.cc
@@ -21,7 +21,7 @@
#include "base/posix/unix_domain_socket_linux.h"
#include "base/process/kill.h"
#include "content/common/child_process_sandbox_support_impl_linux.h"
-#include "content/common/sandbox_linux.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/common/set_process_title.h"
#include "content/common/zygote_commands_linux.h"
#include "content/public/common/content_descriptors.h"
@@ -41,6 +41,14 @@ namespace {
void SIGCHLDHandler(int signal) {
}
+int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) {
+ for (size_t index = 0; index < fd_mapping.size(); ++index) {
+ if (fd_mapping[index].first == key)
+ return fd_mapping[index].second;
+ }
+ return -1;
+}
+
} // namespace
Zygote::Zygote(int sandbox_flags,
@@ -274,7 +282,7 @@ void Zygote::HandleGetTerminationStatus(int fd,
}
int Zygote::ForkWithRealPid(const std::string& process_type,
- std::vector<int>& fds,
+ const base::GlobalDescriptors::Mapping& fd_mapping,
const std::string& channel_switch,
std::string* uma_name,
int* uma_sample,
@@ -303,8 +311,15 @@ int Zygote::ForkWithRealPid(const std::string& process_type,
}
if (use_helper) {
- fds.push_back(dummy_fd);
- fds.push_back(pipe_fds[0]);
+ std::vector<int> fds;
+ int ipc_channel_fd = LookUpFd(fd_mapping, kPrimaryIPCChannel);
+ if (ipc_channel_fd < 0) {
+ DLOG(ERROR) << "Failed to find kPrimaryIPCChannel in FD mapping";
+ goto error;
+ }
+ fds.push_back(ipc_channel_fd); // kBrowserFDIndex
+ fds.push_back(dummy_fd); // kDummyFDIndex
+ fds.push_back(pipe_fds[0]); // kParentFDIndex
pid = helper_->Fork(fds);
} else {
pid = fork();
@@ -319,9 +334,8 @@ int Zygote::ForkWithRealPid(const std::string& process_type,
// should not fork any child processes (which the seccomp
// sandbox does) until then, because that can interfere with the
// parent's discovery of our PID.
- if (!file_util::ReadFromFD(pipe_fds[0],
- reinterpret_cast<char*>(&real_pid),
- sizeof(real_pid))) {
+ if (!base::ReadFromFD(pipe_fds[0], reinterpret_cast<char*>(&real_pid),
+ sizeof(real_pid))) {
LOG(FATAL) << "Failed to synchronise with parent zygote process";
}
if (real_pid <= 0) {
@@ -459,7 +473,7 @@ base::ProcessId Zygote::ReadArgsAndFork(const Pickle& pickle,
static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD()));
// Returns twice, once per process.
- base::ProcessId child_pid = ForkWithRealPid(process_type, fds, channel_id,
+ base::ProcessId child_pid = ForkWithRealPid(process_type, mapping, channel_id,
uma_name, uma_sample,
uma_boundary_value);
if (!child_pid) {
diff --git a/chromium/content/zygote/zygote_linux.h b/chromium/content/zygote/zygote_linux.h
index ffea49a0da1..37e89b5f718 100644
--- a/chromium/content/zygote/zygote_linux.h
+++ b/chromium/content/zygote/zygote_linux.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/containers/small_map.h"
+#include "base/posix/global_descriptors.h"
#include "base/process/kill.h"
#include "base/process/process.h"
@@ -77,7 +78,7 @@ class Zygote {
// fills in uma_name et al with a report the helper wants to make via
// UMA_HISTOGRAM_ENUMERATION.
int ForkWithRealPid(const std::string& process_type,
- std::vector<int>& fds,
+ const base::GlobalDescriptors::Mapping& fd_mapping,
const std::string& channel_switch,
std::string* uma_name,
int* uma_sample,
diff --git a/chromium/content/zygote/zygote_main_linux.cc b/chromium/content/zygote/zygote_main_linux.cc
index 567b3055ccc..8e91c2f17e5 100644
--- a/chromium/content/zygote/zygote_main_linux.cc
+++ b/chromium/content/zygote/zygote_main_linux.cc
@@ -5,6 +5,7 @@
#include "content/zygote/zygote_main.h"
#include <dlfcn.h>
+#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
@@ -15,11 +16,12 @@
#include <unistd.h>
#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback.h"
#include "base/command_line.h"
#include "base/linux_util.h"
#include "base/native_library.h"
#include "base/pickle.h"
-#include "base/posix/eintr_wrapper.h"
#include "base/posix/unix_domain_socket_linux.h"
#include "base/rand_util.h"
#include "base/sys_info.h"
@@ -27,7 +29,7 @@
#include "content/common/child_process_sandbox_support_impl_linux.h"
#include "content/common/font_config_ipc_linux.h"
#include "content/common/pepper_plugin_list.h"
-#include "content/common/sandbox_linux.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/common/zygote_commands_linux.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
@@ -260,9 +262,10 @@ void PreloadPepperPlugins() {
std::string error;
base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path,
&error);
- DLOG_IF(WARNING, !library) << "Unable to load plugin "
- << plugins[i].path.value() << " "
- << error;
+ VLOG_IF(1, !library) << "Unable to load plugin "
+ << plugins[i].path.value() << " "
+ << error;
+
(void)library; // Prevent release-mode warning.
}
}
@@ -274,7 +277,9 @@ void PreloadPepperPlugins() {
static void PreSandboxInit() {
base::RandUint64();
+ base::SysInfo::AmountOfPhysicalMemory();
base::SysInfo::MaxSharedMemorySize();
+ base::SysInfo::NumberOfProcessors();
// ICU DateFormat class (used in base/time_format.cc) needs to get the
// Olson timezone ID by accessing the zoneinfo files on disk. After
@@ -306,80 +311,8 @@ static void PreSandboxInit() {
new FontConfigIPC(GetSandboxFD()))->unref();
}
-// Do nothing here
-static void SIGCHLDHandler(int signal) {
-}
-
-// The current process will become a process reaper like init.
-// We fork a child that will continue normally, when it dies, we can safely
-// exit.
-// We need to be careful we close the magic kZygoteIdFd properly in the parent
-// before this function returns.
-static bool CreateInitProcessReaper() {
- int sync_fds[2];
- // We want to use send, so we can't use a pipe
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, sync_fds)) {
- LOG(ERROR) << "Failed to create socketpair";
- return false;
- }
-
- // We use normal fork, not the ForkDelegate in this case since we are not a
- // true Zygote yet.
- pid_t child_pid = fork();
- if (child_pid == -1) {
- (void) HANDLE_EINTR(close(sync_fds[0]));
- (void) HANDLE_EINTR(close(sync_fds[1]));
- return false;
- }
- if (child_pid) {
- // We are the parent, assuming the role of an init process.
- // The disposition for SIGCHLD cannot be SIG_IGN or wait() will only return
- // once all of our childs are dead. Since we're init we need to reap childs
- // as they come.
- struct sigaction action;
- memset(&action, 0, sizeof(action));
- action.sa_handler = &SIGCHLDHandler;
- CHECK(sigaction(SIGCHLD, &action, NULL) == 0);
-
- (void) HANDLE_EINTR(close(sync_fds[0]));
- shutdown(sync_fds[1], SHUT_RD);
- // This "magic" socket must only appear in one process.
- (void) HANDLE_EINTR(close(kZygoteIdFd));
- // Tell the child to continue
- CHECK(HANDLE_EINTR(send(sync_fds[1], "C", 1, MSG_NOSIGNAL)) == 1);
- (void) HANDLE_EINTR(close(sync_fds[1]));
-
- for (;;) {
- // Loop until we have reaped our one natural child
- siginfo_t reaped_child_info;
- int wait_ret =
- HANDLE_EINTR(waitid(P_ALL, 0, &reaped_child_info, WEXITED));
- if (wait_ret)
- _exit(1);
- if (reaped_child_info.si_pid == child_pid) {
- int exit_code = 0;
- // We're done waiting
- if (reaped_child_info.si_code == CLD_EXITED) {
- exit_code = reaped_child_info.si_status;
- }
- // Exit with the same exit code as our parent. This is most likely
- // useless. _exit with 0 if we got signaled.
- _exit(exit_code);
- }
- }
- } else {
- // The child needs to wait for the parent to close kZygoteIdFd to avoid a
- // race condition
- (void) HANDLE_EINTR(close(sync_fds[1]));
- shutdown(sync_fds[0], SHUT_WR);
- char should_continue;
- int read_ret = HANDLE_EINTR(read(sync_fds[0], &should_continue, 1));
- (void) HANDLE_EINTR(close(sync_fds[0]));
- if (read_ret == 1)
- return true;
- else
- return false;
- }
+static void CloseFdAndHandleEintr(int fd) {
+ close(fd);
}
// This will set the *using_suid_sandbox variable to true if the SUID sandbox
@@ -419,7 +352,13 @@ static bool EnterSuidSandbox(LinuxSandbox* linux_sandbox,
if (getpid() == 1) {
// The setuid sandbox has created a new PID namespace and we need
// to assume the role of init.
- if (!CreateInitProcessReaper()) {
+ // This "magic" socket must only appear in one process, so make sure
+ // it gets closed in the parent after fork().
+ base::Closure zygoteid_fd_closer =
+ base::Bind(CloseFdAndHandleEintr, kZygoteIdFd);
+ const bool init_created =
+ setuid_sandbox->CreateInitProcessReaper(&zygoteid_fd_closer);
+ if (!init_created) {
LOG(ERROR) << "Error creating an init process to reap zombies";
return false;
}